linux shell指令檔執行分析 一.shell指令碼父子進程分析 代碼:[cpp] #!/bin/bash echo $$ ps -ef |grep `echo $$` echo "-------------------------------------" ( pwd;echo $$;ps -ef |grep `echo $$`;) echo "-------------------------------------" { pwd;echo $$;ps -ef |grep `echo $$`; } 運行結果1: www.2cto.com
結果分析1:1. 最後一行顯示當前登入shell進程ID為9561;2. 第三行顯示登入shell派生出一個進程ID為10767的shell執行進程;該進程負責掃描shell指令碼進行執行;3. 10767指令碼執行進程負責逐行執行指令碼:遇到內建命令直接在當10767進程中執行,遇到可執行程式就fork 新的子進進程來執行。4. 進程號為 10768和10769的進程都是執行shell 10767進程派生的子進程ps 和grep .5. 10767指令碼執行進程掃描到( com1;com2;) 語句群時,會再派生一個ID為10771子shell負責執行()內的命令和語句:10771 漸進式掃描()中的語句,按照步驟3的規則進行處理:進程號 10773 grep 還有另一個進程 ps 都是10771又派生出的子進程,ps子進程的父進程是10771 此處沒有顯示出來。6. 10767指令碼執行進程掃描到{ com1;com2;} 語句時,不會新派生子shell,直接使用當前進程10767進行負責逐行執行指令碼。 運行結果2:
結果分析2其運行結果和運行1是一樣的,bash cpro.sh 和直接運行cpro.sh 的工作機制是一樣的,都會派生出一個執行shell,逐行讀指令碼進行執行; www.2cto.com 總結:Ø 在當前shell中執行內部命令不會派生子shell,因此有些內部命令才能夠改變當前的shell執行環境;Ø 在當前shell中執行外部命令或指令碼時會派生子shell,所以這時命令的執行不會影響當前shell環境;Ø 要想在當前shell中執行指令碼,而不派生子shell,可以使用 . 和source 命令 + 指令碼名進行執行Ø ./command.sh = bash ./command.sh 當前shell會派生子shell執行指令檔,指令碼的執行不會影響到當前shell環境Ø . ./command.sh = source ./command.sh 直接在當前shell中執行指令碼,指令碼的執行回影響到當前shell環境 二.管道與shell指令碼執行關係 command | read var 和 comand | while read var代碼:[cpp] pwd | read var echo $var #1 www.2cto.com ls -l |while read var do echo $var #2 done 結果分析:#1 輸出時空置#2輸出有值這就是管道的秘笈,bash 在執行pwd | read var時管道兩邊的都是子shell執行,執行echo $var 是父shell執行,父shell無法讀到子shell變數bash 執行ls -l |while read var 左邊是子shell 右邊是父shell執行,故最後可以讀到內容shell指令碼執行匯總: 1.內建命令(builtin)是shell解釋程式內建的,由shell直接執行,不需要派生新的進程;有一些內部命令可以用來改變當前的shell環境,如:cd /pathvar=valueread varexport var... www.2cto.com 2.外部命令("externalcommand" or "disk command")二進位可執行檔,需要由磁碟裝入記憶體執行。會派生新的進程,shell解釋程式會調用fork自身的一個拷貝,然後用exec系列函數來執行外部命令,然後外部命令就取代了先前fork的子shell。 3.shell指令碼(script)shell解釋程式會fork+exec執行這個指令碼命令,在exec調用中核心會檢查指令碼的第一行(如:#!/bin/sh),找到用來執行指令碼的解釋程式,然後裝入這個解釋程式,由它解釋執行指令碼程式。解釋程式可能有很多種,各種shell(Bourne shell,Korn shell cshell,rc及其變體ash,dash,bash,zshell,pdksh,tcsh,es...),awk,tcl/tk,expect,perl,python,等等。在此解釋程式顯然是當前shell的子進程。如果這個解釋程式與當前使用的shell是同一種shell,比如都是bash,那麼它就是當前shell的子shell,指令碼中的命令都是在子shell環境中執行的,不會影響當前shell的環境。 www.2cto.com 三. 如何查看一個命令時內建命令還是外部命令(程式)使用者輸入命令之後,shell一般fork,在子shell中執行命令。內建命令不是這樣的。 執行內建命令相當於調用Shell進程中的一個函數,並不建立新的進程。如何查看命令是否為內建命令? type命令 type - write a description of command type · 不加參數,會顯示命令是內建命令還是外部命令。[cpp] $type echo echoisa shell builtin · -t 參數,傳回值 file :表示為外部指令,一般是外部可執行程式,ELF格式 alias :表示該指令為命令別名所設定的名稱; builtin :表示該指令為 bash 內建的指令功能; $type-t ls alias $type-t alias builtin $type-t chmod file www.2cto.com · -a 會將命令PATH 路徑顯示出來。 其他相關命令:which命令 只能找到path 下可執行程式,即外部程式,內建命令沒有辦法識別 file 命令查看檔案類型,file 會嘗試讀檔案頭,解析檔案類型 http://blog.csdn.net/hittata/article/details/8017368