轉自https://www.cnblogs.com/ting152/p/12554480.html
1.組指令
組指令,就是将多個指令劃分為一組,或者看成一個整體。
用法 | 差別 |
---|---|
Shell 組指令的寫法有兩種: { command1; command2;. . .; } (command1; command2;. . . ) |
包圍的組指令在目前 Shell 程序中執行,由 包圍的組指令會建立一個子Shell,所有指令都會在這個子 Shell 中執行。 在子 Shell 中執行意味着,運作環境被複制給了一個新的 shell 程序,當這個子 Shell 退出時,新的程序也會被銷毀,環境副本也會消失,是以在子 Shell 環境中的任何更改都會消失(包括給變量指派)。是以,在大多數情況下,除非腳本要求一個子 Shell,否則使用 比使用 更受歡迎,并且 的進行速度更快,占用的記憶體更少。 |
舉栗 | |
将多條指令的輸出重定向到out.txt檔案 | 1.普通模式
2.使用組指令 { ls -l ;echo "test432";cat test.txt; }>out.txt (ls -l ;echo "test432";cat test.txt)>out.txt |
組指令與管道結合 | (ls -l ;echo "test432";cat ../test.txt)|wc -l |
2.子程序
2.1 什麼是子程序
子程序的概念是由父程序的概念引申而來的。在 Linux 系統中,系統運作的應用程式幾乎都是從 init(pid為 1 的程序)程序派生而來的,所有這些應用程式都可以視為 init 程序的子程序,而 init 則為它們的父程序。
Shell 腳本是從上至下、從左至右依次執行的,即執行完一個指令之後再執行下一個。如果在 Shell 腳本中遇到子腳本(即腳本嵌套,但是必須以新程序的方式運作)或者外部指令,就會向系統核心申請建立一個新的程序,以便在該程序中執行子腳本或者外部指令,這個新的程序就是子程序。子程序執行完畢後才能回到父程序,才能繼續執行父腳本中後續的指令及語句。
使用
pstree -p
指令就可以看到 init 及系統中其他程序的程序樹資訊(包括 pid):
systemd(1)─┬─ModemManager(796)─┬─{ModemManager}(821)
│ └─{ModemManager}(882)
├─NetworkManager(975)─┬─{NetworkManager}(1061)
│ └─{NetworkManager}(1077)
├─abrt-watch-log(774)
├─abrt-watch-log(776)
├─abrtd(773)
├─accounts-daemon(806)─┬─{accounts-daemon}(839)
│ └─{accounts-daemon}(883)
├─alsactl(768)
├─at-spi-bus-laun(1954)─┬─dbus-daemon(1958)───{dbus-daemon}(1960)
│ ├─{at-spi-bus-laun}(1955)
│ ├─{at-spi-bus-laun}(1957)
│ └─{at-spi-bus-laun}(1959)
├─at-spi2-registr(1962)───{at-spi2-registr}(1965)
├─atd(842)
├─auditd(739)─┬─audispd(753)─┬─sedispatch(757)
│ │ └─{audispd}(759)
│ └─{auditd}(752)
2.2 建立子程序
建立子程序的方式 | 說明 | |
---|---|---|
|
| 組指令、指令替換、管道 |
| 舉栗: 在 ~/bin 目錄下有兩個可執行檔案分别叫 a.out 和 b.out。現在運作 a.out,就會産生一個程序,比如叫做 A。在程序 A 中我又調用 fork() 函數建立了一個程序 B,那麼 B 就是 A 的子程序,此時它們是一模一樣的。但是,我調用 fork() 後立即又調用 exec() 去加載 b.out,這可就壞事了,B 程序中的一切(包括代碼、資料、堆棧等)都會被銷毀,然後再根據 b.out 重建建立一切。這樣一折騰,B 程序除了 ID 沒有變,其它的都變了,再也沒有屬于 A 的東西了。 |
|
2.3 子程序總結
子 Shell 雖然能使用父 Shell 的的一切,但是如果子 Shell 對資料做了修改,比如修改了全局變量,這種修改也隻能停留在子 Shell,無法傳遞給父 Shell。不管是子程序還是子 Shell,都是“傳子不傳父”。
子 Shell 才是真正繼承了父程序的一切,這才像“一個模子刻出來的”;普通子程序和父程序是完全不同的兩個程式,隻是維持着父子關系而已。
3.如何檢測子shell與子程序
echo $$輸出目前程序ID,echo $PPID輸出父shell ID
指令 | 結果 | 結論 | |
---|---|---|---|
輸出目前程序與父程序ID | echo $$;echo $PPID | 34451 34450 | |
子程序形式輸出程序ID 子程序 | bash exit | 52886 | 在普通的子程序中,$ 被展開為子程序的 ID |
組指令形式輸出程序ID 子shell | (echo $$;echo $PPID) | 子shell和父shell中的ID是一樣的 這是因為$ 變量在子 Shell 中無效!Base 官方文檔說,在普通的子程序中,$ 确實被展開為子程序的 ID;但是在子 Shell 中,$ 卻被展開成父程序的 ID | |
管道形式輸出程序ID | echo "test" | { echo $$;echo $PPID; } | ||
程序替換形式輸出程序ID | read < <(echo $$ $PPID) $ echo $REPLY | 34451 34450 |