2014-01-13 31 views

回答

1

殼加載腳本到存儲器,併產生一個單獨的過程,所以舊腳本將繼續運行未修改

顯然,如果您嘗試重新運行它,您將獲得新版本。

如果你想在運行時引入一些新功能,我會建議寫入臨時文件,然後使用$()或`(反引號)語法執行該文件以產生一個新進程。

或者,您可以使用exec來完全替換當前正在運行的程序。

+1

一般的好建議,但似乎並不能保證bash會預先讀取*整個*原始文件;相反,它似乎以固定大小的塊讀取腳本 - 請參閱http://stackoverflow.com/a/20722200/45375。因此,被覆蓋的內容*可能會被執行。 – mklement0

6

bash一般會這麼做不是提前加載整個腳本,因此覆蓋腳本會產生不可預知的後果。例如,我剛剛創建了一個包含以下內容的腳本:

#!/bin/bash 
echo start old file 
sleep 20 
echo end old file 

...並運行它。

#!/bin/bash 
echo started new file 
sleep 20 
echo end new file 

在此輸出所得:

$ ./test.sh 
start old file 
./test.sh: line 4: 0: command not found 
end new file 

事情是這樣的bash已通過「休眠20 \ n」行中讀取(儘管它正在睡覺,我這個稍微不同的腳本可以覆蓋它包括終止換行的行)。在此之後繼續,它從文件中的下一個字節位置讀取下一個命令,並且由於第二行已經增加了兩個字節(「開始」 - >「開始」),所以它讀完了最後兩個新睡眠行的字節(「sleep 20 \ n」 - >「0 \ n」),嘗試執行「0」作爲命令,並且出現錯誤。然後它運行新內容的最後一行。很凌亂,對吧?

幸運的是,有一種方法來強制bash整個腳本加載到內存中,這樣就不會感到困惑,如果它得到改變運行時:

#!/bin/bash 
{ 
    echo start old file 
    sleep 20 
    echo end old file 
    exit 
} 

{迫使外殼至少通過閱讀匹配}爲了正確解析命令,然後exit確保它永遠不會嘗試執行任何在}之後添加的內容。我正在測試這與bash版本3.2.48(1) - 釋放(在OS X 10.8.5);其他版本可能會有不同的行爲...

更新:其他版本的行爲確實有所不同。我使用4.3.0(1)版本(在NetBSD 6.1.4下)嘗試了相同的測試,並在文件內容被替換後繼續運行舊代碼。顯然它現在將文件緩存在8KB塊中(請參閱this unix.se answer)。

+0

我更喜歡這個答案。 – Donovan