所有現今的UNIX系統都支援解譯器檔案(interpreter file)(也可稱為解譯器指令碼)。這種檔案是,是:
驚嘆號和pathname之間的空格是可選的。最常見的解譯器檔案以下列行開始:
#!/bin/sh
pathname通常是絕對路徑名,對它不進行什麼特殊的處理(即不使用PATH進行路徑搜尋)。。核心調用exec函數的進程實際執行的並不是該解譯器檔案,而是該解譯器檔案第一行中pathname所指定的檔案。一定要將解譯器檔案(文字檔,它以#!開頭)和解譯器(由該解譯器檔案第一行中的pathname指定)區分開來。(我們可以認為:解譯器檔案就是在首行指定了其所使用的解譯器的文字檔。)
要知道很多系統對解譯器檔案的第一行有長度限制。這些限制包括#!、pathname、選擇性參數、終止分行符號以及空格數。在Linux中支援該限制為127位元組。
執行個體
讓我們觀察一個執行個體,從中可瞭解當被執行的檔案是解譯器檔案時,核心如何處理exec函數的參數及該解譯器檔案第一行的選擇性參數。程式清單8-10調用exec執行一個解譯器檔案。
程式清單8-10 執行一個解譯器檔案的程式
[root@localhost apue]# cat prog8-<sys/wait.h>((pid = fork()) < (pid == ) (execl(, , , ( *)) < (waitpid(pid, NULL, ) < )
程式清單8-10中被執行的解譯器檔案內容如下(只有一行):
!/home/zhu/apue/echoarg foo
程式echoarg(解譯器)回送每一個命令列參數(它就是程式清單7-3,參見:http://www.cnblogs.com/nufangrensheng/p/3507949.html)。
程式清單8-10運行結果:
[root@localhost apue]# ./prog8-]: /home/zhu/apue/]: /home/zhu/apue/]: MY ARG2
注意,當核心exec該解譯器(/home/zhu/apue/echoarg)時,argv[0]是該解譯器的pathname,argv[1]是解譯器檔案中的選擇性參數,其餘參數是pathname(/home/zhu/apue/testinterp),以及程式清單8-10中調用execl的第二個和第三個參數(myarg1和MY ARG2)。調用execl時的argv[1]和argv[2]已右移了兩個位置(?)。注意,核心取execl調用中的pathname而非第一個參數(testinterp),因為一般而言,pathname包含了比第一個參數更多的資訊(通常第一個參數只是pathname的一部分)。
總的來說,當核心exec解譯器時,其命令列參數依次是該解譯器的pathname、解譯器的選擇性參數、解譯器檔案的pathname、exec函數調用參數列表中argv[0]以後的參數(不包括argv[0],通常argv[0]只是解譯器檔案pathname中的一部分)。(http://www.cnblogs.com/nufangrensheng/p/3510821.html中有提到我們可將argv[0]設定為任何字串。)
執行個體
在解譯器pathname後可跟隨選擇性參數。如果一個解譯器程式支援-f選項,那麼在pathname後經常使用的選擇性參數就是-f。
例如,可以以下列方式執行awk(1)程式:
awk -f myfile
它告訴awk從檔案myfile中讀取awk程式。
如果在解譯器檔案中使用-f選項,則可以寫成:
#!/bin/awk -
例如,程式清單8-11為/usr/local/bin/awkexample這樣一個解譯器檔案。
程式清單8-11 作為解譯器檔案的awk程式
#!/bin/awk -(i=; i<ARGC; i++
如果路徑首碼之一是/usr/local/bin,則可以用下列方式執行程式清單8-11:
] =] =] =] = f3
其實,shell會這樣調用exec:
exec(, , , , NULL);
但是,實際上exec執行的是解譯器/bin/awk而不是解譯器檔案awkexample,並且其命令列參數是:
/bin/awk -f /usr/local/bin/awkexample file1 FILENAME2 f3
是否一定需要解譯器檔案呢?那也不完全如此。但是它們確實使使用者得到效率方面的好處,其代價是核心的額外開銷(因為識別解譯器檔案的是核心)。
由於下述理由,解譯器檔案是有用的:
(1)有些程式是用某種語言編寫的指令碼,解譯器檔案可將這一事實隱藏起來。例如,為了執行程式8-11,只需使用下列命令列:
awkexample opitonal-arguments
而並不需要知道該程式實際上是一個awk指令碼,否則就需要以下列方式執行該程式:
awk -f awkexample optional-arguments
(2)解譯器指令碼在效率方面也提供了好處。通常,用一個shell指令碼代替解譯器指令碼需要更多的開銷。
(3)解譯器指令碼使我們可以使用除/bin/sh以外的其他shell來編寫shell指令碼。(此時,我們只需要在解譯器指令碼首行指明所用的shell即可。
本篇博文內容摘自《UNIX環境進階編程》(第二版),僅作個人學習記錄所用。關於本書可參考:http://www.apuebook.com/。