-->

Exploring Parent and Child Shell Relationships On Linux

The default interactive shell started when a user logs into a virtual console terminal or starts a terminal emulator in the GUI is a parent shell. As you have read so far in this book, a parent shell process provides a CLI prompt and waits for commands to be entered.

When the /bin/bash command or the equivalent bash command is entered at the CLI prompt, a new shell program is created. This is a child shell. A child shell also has a CLI prompt and waits for commands to be entered.

Because you do not see any relevant messages when you type bash and spawn a child shell, another command can help bring clarity. Using this with the -f option before and after entering a child shell is useful:

$ ps -f
UID  PID   PPID  C  STIME  TTY         TIME   CMD
501  1841  1840  0  11:50  pts/0   00:00:00   -bash
501  2429  1841  4  13:44  pts/0   00:00:00   ps -f
$$
bash
$$
ps -f
UID  PID   PPID  C  STIME   TTY        TIME   CMD
501  1841  1840  0  11:50   pts/0  00:00:00   -bash
501  2430  1841  0  13:44   pts/0  00:00:00   bash
501  2444  2430  1  13:44   pts/0  00:00:00   ps -f
$

The first use of ps -f shows two processes. One process has a process ID of 1841 (second column) and is running the bash shell program (last column). The second process (process ID 2429) is the actual ps -f command running.

Note
A process is a running program. The bash shell is a program, and when it runs, it is a process. A running shell is simply one type of process. Therefore, when reading about running a bash shell, you often see the word “shell” and the word “process” used interchangeably

After the command bash is entered, a child shell is created. The second ps -f is executed from within the child shell. From this display, you can see that two bash shell programs are running. The first bash shell program, the parent shell process, has the original process ID (PID) of 1841. The second bash shell program, the child shell process, has a PID of 2430. Note that the child shell has a parent process ID (PPID) of 1841, denoting that the parent shell process is its parent.

Parent and child bash shell processes
Parent and child bash shell processes


When a child shell process is spawned, only some of the parent’s environment is copied to the child shell environment. This can cause problems with items such as variables.

A child shell is also called a subshell. A subshell can be created from a parent shell, and a subshell can be created from another subshell:

$ ps -f
UID  PID    PPID  C  STIME  TTY        TIME  CMD
501  1841   1840  0  11:50  pts/0  00:00:00  -bash
501  2532   1841  1  14:22  pts/0  00:00:00  ps -f
$$
bash
$$
bash
$$
bash
$$
ps —forest
PID      TTY          TIME    CMD
1841     pts/0     00:00:00    bash
2533     pts/0     00:00:00    \_ bash
2546     pts/0     00:00:00        \_ bash
2562     pts/0     00:00:00            \_ bash
2576     pts/0     00:00:00                \_ ps
$

In the preceding example, the bash shell command was entered three times. Effectively, this created three subshells. The ps —forest command shows the nesting of these subshells. the picture below also shows this subshell nesting.

Subshell nesting
Subshell nesting



The ps -f command can be useful in subshell nesting, because it displays who is whose parent via the PPID column:

$ ps -f
UID   PID   PPID   C   STIME   TTY        TIME   CMD
501   1841  1840   0   11:50   pts/0  00:00:00   -bash
501   2533  1841   0   14:22   pts/0  00:00:00   bash
501   2546  2533   0   14:22   pts/0  00:00:00   bash
501   2562  2546   0   14:24   pts/0  00:00:00   bash
501   2585  2562   1   14:29   pts/0  00:00:00   ps -f
$

The bash shell program can use command line parameters to modify the shell start. Table 5.1 lists the command line parameters available in bash.

The bash Command Line Parameters
The bash Command Line Parameters


You can find more help on the bash command and even more command line parameters by typing man bash. The bash —help command provides additional assistance as well. You can gracefully exit out of each subshell by entering the exit command:

$ exit
exit

$$
ps —forest
PID     TTY           TIME     CMD
1841    pts/0     00:00:00     bash
2533    pts/0     00:00:00      \_ bash
2546    pts/0     00:00:00          \_ bash
2602    pts/0     00:00:00              \_ ps
$
exit
exit
$$
exit
exit
$$
ps —forest
PID   TTY         TIME   CMD
1841  pts/0   00:00:00   bash
2604  pts/0   00:00:00    \_ ps
$


Not only does the exit command allow you to leave child subshells, but you can also log out of your current virtual console terminal or terminal emulation software as well. Just type exit in the parent shell, and you gracefully exit the CLI. Another time a subshell can be created is when you run a shell script.

Also, you can spawn subshells without using the bash shell command or running a shell script. One way is by using a process list.

Looking at process lists

On a single line, you can designate a list of commands to be run one after another. This is done by entering a command list using a semicolon (;) between commands:

$ pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
/etc
/home/Christine
Desktop     Downloads   Music Public   Videos
Documents   junk.dat    Pictures       Templates
$

In the preceding example, the commands all executed one after another with no problems. However, this is not a process list. For a command list to be considered a process list, the commands must be encased in parentheses:

$ (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
/etc
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
$

Though the parentheses addition may not appear to be a big difference, they do cause a very different effect. Adding parentheses and turning the command list into a process list created a subshell to execute the commands.

Note
A process list is a command grouping type. Another command grouping type puts the
commands between curly brackets and ends the command list with a semicolon (;).
The syntax is as follows: { command; }. Using curly brackets for command grouping
does not create a subshell as a process list does.

To indicate if a subshell was spawned, a command using an environment variable is
needed here. The command
needed is echo $BASH_SUBSHELL. If it returns a 0, then there is no subshell. If it returns 1
or more, then there is a subshell.

First, the example using just a command list is executed with the echo $BASH_SUBSHELL
tacked onto the end:

$ pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls ; echo $BASH_SUBSHELL
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
/etc
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
0

At the very end of the commands’ output, you can see the number zero (0) is displayed. This indicates a subshell was not created to execute these commands. The results are different using a process list. The list is executed with echo $BASH_SUBSHELL tacked onto the end:

$ (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls ; echo $BASH_SUBSHELL)
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
/etc
/home/Christine
Desktop     Downloads   Music      Public Videos
Documents   junk.dat    Pictures   Templates
1

In this case, the number one (1) displayed at the output’s end. This indicates a subshell was indeed created and used for executing these commands.

Thus, a process list is a command grouping enclosed with parentheses, which creates a subshell to execute the command(s). You can even create a grandchild subshell by embedding parentheses within a process list:

$ ( pwd ; echo $BASH_SUBSHELL)
/home/Christine
1$
( pwd ; (echo $BASH_SUBSHELL))
/home/Christine

Notice in the first process list, the number one (1) is displayed indicating a child subshell as you would expect. However in the example’s second process list, additional parentheses were added around the echo $BASH_SUBSHELL command. These additional parentheses caused a grandchild subshell to be created for the command’s execution. Thus, a number two (2) was displayed indicating a subshell within a subshell.

Subshells are often used for multi-processing in shell scripts. However, entering into a subshell is an expensive method and can significantly slow down processing. Subshell issues exist also for an interactive CLI shell session. It is not truly multi-processing, because the terminal gets tied up with the subshell’s I/O.

Creatively using subshells

At the interactive shell CLI, you have more productive ways to use subshells. Process lists, co-processes, and pipes (covered in Chapter 11) use subshells. They all can be used effectively within the interactive shell.

One productive subshell method in the interactive shell uses background mode. Before discussing how to use background mode and subshells together, you need to understand background mode itself.

Investigating background mode

Running a command in background mode allows the command to be processed and frees up your CLI for other use. A classic command to demonstrate background mode is the sleep command.

The sleep command accepts as a parameter the number of seconds you want the process to wait (sleep). This command is often used to introduce pauses in shell scripts. The command sleep 10 causes the session to pause for 10 seconds and then return a shell CLI prompt:

$ sleep 10
$

To put a command into background mode, the & character is tacked onto its end. Putting the sleep command into background mode allows a little investigation with the ps command:

$ sleep 3000&
[1] 2396
$ ps -f
UID       PID   PPID  C  STIME  TTY        TIME  CMD
christi+  2338  2337  0  10:13  pts/9  00:00:00  -bash
christi+  2396  2338  0  10:17  pts/9  00:00:00  sleep 3000
christi+  2397  2338  0  10:17  pts/9  00:00:00  ps -f
$

The sleep command was told to sleep for 3000 seconds (50 minutes) in the background (&). When it was put into the background, two informational items were displayed before the shell CLI prompt was returned. The first informational item is the background job’s number (1) displayed in brackets. The second item is the background job’s process ID (2396).

The ps command was used to display the various processes. Notice that the sleep 3000 command is listed. Also note that its process ID (PID) in the second column is the same PID displayed when the command went into the background, 2396.

In addition to the ps command, you can use the jobs command to display background job information. The jobs command displays any user’s processes (jobs) currently running in background mode:

$ jobs
[1]+ Running sleep 3000 &
$

The jobs command shows the job number (1) in brackets. It also displays the job’s current status (running) as well as the command itself, (sleep 3000 &).

You can see even more information by using the -l (lowercase L) parameter on the jobs command. The -l parameter displays the command’s PID in addition to the other information:

$ jobs -l
[1]+ 2396 Running sleep 3000 &
$

When the background job is finished, its completion status is displayed:


[1]+ Done sleep 3000 &

$

Tip
Be aware that a background job’s completion status won’t necessarily wait till a convenient time to display itself. Don’t let it surprise you when a job’s completion status just suddenly appears on your screen.
Background mode is very handy. And it provides a method for creating useful subshells at the CLI.

Putting process lists into the background

As stated earlier, a process list is a command or series of commands executed within a subshell. Using a process list including sleep commands and displaying the BASH_SUBSHELL variable operates as you would expect:

$ (sleep 2 ; echo $BASH_SUBSHELL ; sleep 2)
1$

In the preceding example, a two-second pause occurs, the number one (1) is displayed indicating a single subshell level (child subshell), and then another two-second pause occurs before the prompt returns. Nothing too dramatic here.

Putting the same process list into background mode can cause a slightly different effect with command output:

$ (sleep 2 ; echo $BASH_SUBSHELL ; sleep 2)&
[2] 2401
$ 1
[2]+ Done ( sleep 2; echo $BASH_SUBSHELL; sleep 2 )
$z


Putting the process list into the background causes a job number and process ID to appear, and the prompt returns. However, the odd event is that the displayed number one (1), indicating a single-level subshell, is displayed by the prompt! Don’t let this confuse you. Simply press the Enter key, and you get another prompt back.

Using a process list in background mode is one creative method for using subshells at the CLI. You can do large amounts of processing within a subshell and not have your terminal tied up with the subshell’s I/O.

Of course, the process list of sleep and echo commands are just for example purposes. Creating backup files with tar (see Chapter 4) is a more practical example of using background process lists effectively:

$ (tar -cf Rich.tar /home/rich ; tar -cf My.tar /home/christine)&
[3] 2423
$

Putting a process list in background mode is not the only way to use subshells creatively at the CLI. Co-processing is another method.

Looking at co-processing


Co-processing does two things at the same time. It spawns a subshell in background mode and executes a command within that subshell.

To perform co-processing, the coproc command is used along with the command to be executed in the subshell:

$ coproc sleep 10
[1] 2544
$

Co-processing performs almost identically to putting a command in background mode, except for the fact that it creates a subshell. You’ll notice that when the coproc command and its parameters were entered, a background job was started. The background job number (1) and process ID (2544) were displayed on the screen.

The jobs command allows you to display the co-processing status:

$ jobs
[1]+ Running coproc COPROC sleep 10 &
$

From the preceding example, you can see the background command executing in the subshell is coproc COPROC sleep 10. The COPROC is a name given to the process by the coproc command. You can set the name yourself by using extended syntax for the command:

$ coproc My_Job { sleep 10; }
[1] 2570
$$
jobs
[1]+ Running coproc My_Job { sleep 10; } &
$

By using the extended syntax, the co-processing name was set to My_Job. Be careful here, because the extended syntax is a little tricky. You have to make sure that a space appears after the first curly bracket ({) and before the start of your command. Also, you have to make sure the command ends with a semicolon (;). And you have to ensure that a space appears after the semicolon and before the closing curly bracket (}).

Note
Co-processing allows you to get very fancy and send/receive information to the process running in the subshell. The only time you need to name a co-process is when you have multiple co-processes running, and you need to communicate with them all. Otherwise, just let the coproc command set the name to the default, COPROC.

You can be really clever and combine co-processing with process lists creating nested subshells. Just type your process list and put the command coproc in front of it:

$ coproc ( sleep 10; sleep 2 )
[1] 2574
$$
jobs
[1]+ Running coproc COPROC ( sleep 10; sleep 2 ) &
$$
ps —forest
PID TTY TIME CMD
2483 pts/12 00:00:00 bash
2574 pts/12 00:00:00 \_ bash
2575 pts/12 00:00:00 | \_ sleep
2576 pts/12 00:00:00 \_ ps
$

Just remember that spawning a subshell can be expensive and slow. Creating nested subshells is even more so!

Using subshells can provide flexibility at the command line as well as convenience. Understanding their behavior is important to obtaining this flexibility and convenience. Command behavior is also important to understand. In the next section, the behavior differences between built-in and external commands are explored.



0 Response to "Exploring Parent and Child Shell Relationships On Linux"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel