當Shell執行一個程序時,會要求UNIX內核啓動一個新的進程(process),以便在該進程裏執行所指定的程序。內核知道如何爲編譯型程序作這件事。咱們的nusers Shell腳本並不是編譯型程序;當Shell要求內核執行它時,內核將沒法作這件事,並回應「not executable format file」(不是可執行的格式文件)錯誤信息。Shell收到此錯誤信息時,就會說「啊哈,這不是編譯型程序,那麼必定是Shell腳本」,接着會啓動一個新的 /bin/sh(標準Shell)副原本執行該程序。
html
當系統只有一個Shell時,「退回到/bin/sh」的機制很是方便。但現行的UNIX系統都會擁有好幾個Shell,所以須要經過一種方式,告知UNIX內核應該以哪一個Shell來執行所指定的Shell腳本。事實上,這麼作有助於執行機制的通用化,讓用戶得以直接飲用任何的程序語言解釋器,而非只是一個命令Shell。方法是,經過腳本文件中特殊的第一行來設置:在第一行的開頭處使用#!這兩個字符。
當一個文件中開頭的兩個字符是#!時,內核會掃描該行其他部分,看是否存在可用來執行程序的解釋器的完整路徑。(中間若是出現任何空白符號都會略過。)此外,內核還會掃描是否有一個選項要傳遞給解釋器。內核會以被指定的選項來引用解釋器,再搭配命令行的其餘部分。舉例來講,假設有一個csh腳本(/bin/csh是C Shell的命令解釋器),名爲/usr/ucb/whizprog,它的第一行以下所示:
#! /bin/csh -f
再者,若是Shell的查找路徑(後面會介紹)裏有/usr/ucb,當用戶鍵入 whizprog -q /dev/tty01 這條命令,內核解釋#!這行後,便會以以下的方式來引用csh:
/bin/csh -f /usr/ucb/whizprog -q /dev/tty01
這樣的機制讓咱們得以輕鬆地引用任何的解釋器。例如咱們能夠這樣引用獨立的awk程序:
#! /bin/awk -f
此處是awk程序
Shell腳本一般一開始都是#! /bin/sh。若是你的 /bin/sh 並不符合POSIX標準,請將這個路徑改成符合POSIX標準的Shell。下面是幾個初級的陷阱(gotchas),請特別留意:
- 當今的系統,對#!這一行的長度顯示從63到1024個字符(character)都有。請儘可能不要超過64個字符
- 在某些系統上,命令行部分(也就是要傳遞給解釋器執行的命令)包含了命令的完整路徑名稱。不過有些系統卻不是這樣;命令行的部分會原封不動地傳給程序。所以,腳本是否具備可移植性取決因而否有完整的路徑名稱。
- 別在選項(option)以後放置任何空白,由於空白也會跟着選項一塊兒傳遞給引用的程序。
- 你須要知道解釋器的完整路徑明後才能。這樣能夠用來規避可移植性問題,由於不一樣的廠商可能將一樣的東西放在不一樣的地方(例如 /bin/awk 和 /usr/bin/awk)。
- 一些較舊的系統上,內核不具有解釋#!的能力,有些Shell會自行處理,這些Shell對於#!與緊隨其後的解釋器名稱之間是否能夠有空白,多是有不一樣的解釋。
POSIX標準對#!的行爲模式保留未定義(unspecified)狀態。此狀態是「只要一直保持POSIX兼容性,這是一個擴展功能」的標準說法。
本系列接下來全部腳本開頭都會有#!行,下面是修訂過的nusers程序:
[many@avention my_sh]$ cat nusers
#! /bin/sh -
echo "開始統計用戶數..."
who | wc -l
echo "統計用戶數結束..."
選項 - 表示沒有Shell選項;這是基於安全上的考慮,能夠避免某種程度的欺騙式攻擊(spoofing attack)。
文章引用地址 https://www.cnblogs.com/avention/p/9661402.html