Go to the sub-shell Situation Analysis, shell Situation Analysis
The sub-shell concept runs through the entire shell, and it is not unknown when writing shell scripts. The so-called sub-shell is to create a new shell environment from the current shell environment. This new shell environment is called subshell ), the environment for enabling a sub-shell is called the parent shell of the sub-shell. The relationship between the sub-shell and the parent shell is actually the relationship between the sub-process and the parent process, except that the sub-shell and the parent shell are associated with the bash process.
The sub-shell inherits many environments from the parent shell, such as variables, command full path, file descriptor, current working directory, and traps. However, the sub-shell has many types, different types of sub-shells inherit different environments. Available$ BASH_SUBSHELLVariable to view the number of sub-shell layers starting from the current process,$ BASHPIDView the bash pid, which is different from the special variable "$", because "$" inherits from the parent process.
When to generate a subshell
To understand the sub-shell and what type of sub-shell is generated, you need to understand how to generate sub-processes in Linux. There are three ways to create sub-processes on Linux: one is fork, the other is exec, and the other is clone. You do not need to worry about clone because it is used to implement threads in Linux.
(1). fork is a replication process, which will copy copies of the current process (regardless of the mode of replication at write time) and hand over these resources to the child process in an appropriate way. Therefore, the sub-process has the same resources as the parent process, including the content in the memory, so it also includes environment variables and variables. But the Parent and Child processes are completely independent. They are two instances of a program.
(22.16.exe c is to load another application to replace the currently running process, that is, to load a new program without creating a new process. Exec has another action: After the process is executed, exit the shell environment where exec is located.
To ensure process security,To form a new and independent sub-process, the current process is fork first, and then exec is called on the Sub-process generated by fork to load the new program to replace the sub-process.. For example, if you execute the cp command in bash, A bash will be generated by fork first, and then the exec loads the cp program to overwrite the sub-bash process into the cp process.
Next we will explain the sub-shell problem. Generally, the content of the fork child process is the same as that of the parent process (including variables). For example, the variables of the parent process can also be obtained when the cp command is executed. But where can I execute the cp command? Run the cp command and press Enter. The current bash process fork generates a subbash, and then the subbash loads the cp program through exec to replace the subbash. Is this a sub-shell? The more general question is: under what circumstances will the sub-shell environment be accessed, and when will the sub-shel environment be accessed?
It is very easy to determine whether the Sub-shell is entered. Execute "echo $ BASHPID". If the value is different from the pid value of the parent bash process, it indicates that the sub-shell is entered. Whether a sub-shell is entered in a shell can be divided into several types:
①.When executing bash built-in commands.
Bash built-in commands are very special. The parent process does not create sub-processes to execute these commands, but directly runs them in the current bash environment. However, if you place the built-in commands in the pipeline, the built-in command will belong to the same process group as the process on the left of the pipeline, so the sub-shell will still be created.
[Root @ xuexi ~] # Echo $ BASHPID # current BASHPID65230 [root @ xuexi ~] # Let a = $ BASHPID # bash built-in command, do not enter the sub-shell [root @ xuexi ~] # Echo $ a65230
[Root @ xuexi ~] # Echo $ BASHPID65230 [root @ xuexi ~] # Cd | expr $ BASHPID # The pipeline enables any command to enter the process group and the sub-shell 65603
②.When executing the bash command itself.
This is a coincidence. Bash commands are built-in bash commands. Executing the built-in commands in the Current shell environment will not create subshells, that is, there will be no independent bash processes, the actual result is displayed as a new bash sub-process. One of the reasons is that executing the bash command loads various environment configuration items, so that the parent bash environment is protected without being overwritten, so it should exist as a sub-shell. Although the content of the bash sub-process from fork completely inherits the parent shell,However, because the environment configuration item is re-loaded, the sub-shell does not inherit normal variables. More accurately, it overwrites the variables inherited from the parent shell.Try to define a variable in the/etc/bashrc file, and then execute the environment variable with the same export name but different values in the parent shell to check the value of the variable in the sub-shell?
[root@xuexi ~]# echo "var=55" >>/etc/bashrc[root@xuexi ~]# export var=66[root@xuexi ~]# bash[root@xuexi ~]# echo $var55
Result 55 shows that the variables in/etc/bashrc loaded when bash is executed overwrite the exported environment variable value 66 in the parent bash.
In fact, executing the bash command can be considered as either a sub-shell or not. From the perspective that bash is a built-in command, it will not enter the sub-shell, which can be verified from the value of $ BASH_SUBSHELL after the bash command is executed. However, from the execution of the bash command into the new shell environment, it has its parent bash process, and the value of $ BASHPID is different from that of the parent shell, so it enters the subshell.
[root@xuexi ~]# echo $BASHPID65230[root@xuexi ~]# bash[root@xuexi ~]# echo $BASHPID65534
③.When the shell script is executed.
The first line in the script is always "#! /Bin/bash "or directly" bash xyz. sh ", which is the same as executing bash to enter the sub-shell. Both use the bash command to enter the sub-shell. However, the bash command at this time is different from the options implied by directly executing the bash command in scenario 2, so the inherited and loaded shell environments are different. This is also true,It only inherits some environment variables of the parent shell, and all other environments are initialized.
In addition, the execution of shell scripts has an additional action than the direct execution of bash commands: After the script is executed, it automatically exits the sub-shell.
[root@xuexi ~]# cat b.sh #!/bin/bashecho $BASHPID[root@xuexi ~]# echo $BASHPID65534[root@xuexi ~]# ./b.sh 65570
④.When the shell function is executed.
In fact, shell functions are commands, which are the same as bash built-in commands. The sub-shell is not entered during direct execution, but the sub-shell is entered after the sub-shell is placed in the pipeline.
[Root @ xuexi ~] # Fun_test () {echo $ BASHPID;} # define a function and output the value of the BASHPID variable [root @ xuexi ~] # Echo $ BASHPID 65230 [root @ xuexi ~] # Fun_test # indicates that the execution function will not enter the sub-shell65230 [root @ xuexi ~] # Cd | fun_test # after being placed in the MPs queue, the sub-shell65605 is displayed.
⑤.When executing non-bash built-in commands.
For example, execute the cp command and grep command. They directly fork a bash process and then use the exec loader to replace the subbash. This type of child process inherits all the parent bash environments. But strictly speaking, this is no longer a sub-shell, because the exec-loaded program has replaced the sub-bash process, which means that many bash environments are lost. In the bash document, the environment is called "a separate environment", which is similar to the sub-shell concept.
[Root @ xuexi ~] # Let a = $ BASHPID # let is a built-in command [root @ xuexi ~] # Echo $ a65230 [root @ xuexi ~] # Echo $ BASHPID # echo is a non-built-in command and the result is that the sub-shell65230
6.Command replacement.
When the command line contains the command replacement part, a sub-shell is enabled to execute this part first, and then the execution result is returned to the current command. Because this subshell is not a subshell that is entered through the bash command, it inherits all the variable content of the parent shell. This explains that the result of "$" in "echo $ (echo $)" is the pid of the current bash, rather than the pid of the sub-shell, however, "echo $ (echo $ BASHPID)" is different from the pid of the parent bash process because it is not a sub-shell that uses bash commands.
[Root @ xuexi ~] # Echo $ BASHPID65230 [root @ xuexi ~] # Echo $ (echo $ BASHPID) # Replace $ () with the command to enter the sub-shell65612
7.Use parentheses () to combine a series of commands.
For example (ls; date; echo haha), an independent sub-shell is opened to execute the commands in the brackets. This is equivalent to scenario 5.
[Root @ xuexi ~] # Echo $ BASHPID65230 [root @ xuexi ~] # (Echo $ BASHPID) # Use the command combination of parentheses () to enter the sub-shell65613
Invalid.Tasks run in the background.
It is not only an independent sub-process, but also run in the sub-shell environment. For example, "echo hahha &".
[Root @ xuexi ~] # Echo $ BASHPID65230 [root @ xuexi ~] # Echo $ BASHPID & # enter the sub-shell for running tasks in the background [1] 65614 [root @ xuexi ~] #65614 [1] + Done echo $ BASHPID
Invalid.Process replacement.
Now that the process is a new process, go to the sub-shell for execution. For example, "cat <(echo haha )".
[Root @ xuexi ~] # Echo $ BASHPID65230 [root @ xuexi ~] # Cat <(echo $ BASHPID) # process replacement "< ()"
It must be noted that,The environment settings of the sub-shell are not stuck to the parent shell environment, that is, the variables of the sub-shell will not affect the parent shell.
Finally, we recommend that you read another article at the same time:Environment configuration process during bash startupWhich configuration files are loaded when bash is started.
Back to series article outline: http://www.cnblogs.com/f-ck-need-u/p/7048359.html
Reprinted please indicate the source: Success!