每一個shell進程有一個本身的運行環境,不一樣的Shell進程有不一樣的Shell環境。Shell解析命令行、調用命令行的過程都在這個環境中完成。shell
調用shell程序時,會讀取配置文件來初始化Shell環境。bash
讀取配置文件狀況分爲兩種:ssh
所謂子shell,即從當前shell環境中新開了一個shell環境,這個新開的shell環境就是子shell,而開啓子shell的環境稱爲該子shell的父shell。函數
子Shell的本質能夠理解爲Shell的子進程,子進程的概念是由父進程的概念引伸而來的,在Linux系統中,系統運行的應用程序幾乎都是從init
(pid爲1的進程)進程派生而來的,全部這些應用程序均可以視爲init進程的子進程,而init
則爲它們的父進程。經過執行pstree -a
命令就能夠看到init
及系統中其餘進程的進程樹信息:命令行
[root@test ~]# pstree -a systemd --switched-root --system --deserialize 22 ├─NetworkManager --no-daemon │ └─2*[{NetworkManager}] ├─VGAuthService -s ├─agetty --noclear tty1 linux ├─auditd │ └─{auditd} ├─chronyd ├─crond -n ├─dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation ├─irqbalance --foreground ├─lvmetad -f ├─master -w │ ├─pickup -l -t unix -u │ └─qmgr -l -t unix -u ├─polkitd --no-debug │ └─6*[{polkitd}] ├─rsyslogd -n │ └─2*[{rsyslogd}] ├─sshd -D │ └─sshd │ └─bash │ └─pstree -a ├─systemd-journal ├─systemd-logind ├─systemd-udevd ├─tuned -Es /usr/sbin/tuned -l -P │ └─4*[{tuned}] └─vmtoolsd └─2*[{vmtoolsd}]
Tips:若無pstree命令,請執行
yum -y install psmisc
安裝。debug
對於Shell的子進程來講,它是一個從父級Shell進程派生而來的新的Shell進程,咱們將這種新的Shell進程稱爲這個父級Shell的子Shell。unix
Shell腳本是從上至下、從左至右依次執行每一行的命令及語句的,即執行完一個命令以後再執行下一個。若是在Shell腳本中遇到子腳本(即腳本嵌套),就會先執行子腳本的內容,完成後再返回父腳本繼續執行父腳本內後續的命令及語句。code
子shell會從父shell中繼承不少環境,如變量、命令全路徑、文件描述符、當前工做目錄、陷阱等等,但子shell有不少種類型,不一樣類型的子shell繼承的環境不相同。能夠使用$BASH_SUBSHELL
變量來查看從當前進程開始的子shell層數,$BASHPID
查看當前所處BASH的PID,這不一樣於特殊變量$$
值,由於$$
在大多數狀況下都會從父shell中繼承。blog
注意:子 Shell 雖然能使用父 Shell 的的一切,可是若是子 Shell 對數據作了修改,好比修改了全局變量,那麼這種修改只能停留在子 Shell,沒法傳遞給父 Shell。無論是子進程仍是子 Shell,都是「傳子不傳父」。
大體分爲兩類:
<(cmd),>(cmd)
、命令替換$(cmd)
、(cmd)
、|
或者$
隱式生成的子shell。由於父shell是經過fork
建立sub shell,所以子shell會從父shell中繼承不少環境,如變量、命令全路徑、文件描述符、當前工做目錄、陷阱等等;fork-exec
的方式建立子shell,致使父shell和子shell除了維持「父子關係」外,沒有其餘關聯。註釋:使用 fork() 函數能夠建立一個子進程;除了 PID(進程ID)等極少的參數不一樣外,子進程的一切都來自父進程,包括代碼、數據、堆棧、打開的文件等,就連代碼的執行位置(狀態)都是同樣的。