2011-10-20 110 views
13

甚至在遇到語句刪除自己之後,bash腳本如何執行? 對於例如,當我跑test.sh腳本conains:自我刪除bash腳本

<--some commands--> 
rm test.sh 
<--some more commands--> 

end 

腳本執行到最後刪除本身

+3

執行應用程序時,其代碼被加載到內存中。您只是刪除了磁盤上的文件,這不會影響內存中的代碼。 –

+1

假定整個腳本在執行時被讀入內存,所以'rm test.sh'後面的命令仍然存在於內存中以便執行。 – MrMisterMan

+0

它不會在內存中創建副本。所以,例如,如果腳本在運行時被修改,它將執行修改。最近這讓我很頭疼。可愛的例子:這一行腳本會在短時間內填滿你的磁盤:'cat $ 0 >> $ 0'。 – Ned

回答

24

實際發生的是,慶典保持文件打開和rm不會犯停止。

因此rm調用libc函數「unlink()」,它將從它所在的目錄中刪除inode的「鏈接」。該「鏈接」實際上是一個文件名以及一個inode號碼(可以看到inode數字爲ls -i)。

只要程序打開它,inode就會存在。

您可以輕鬆地測試這一要求如下:

$ echo read a> ni 
$ bash ni 

而在另一個窗口:

$ pgrep -lf bash\ ni 
31662 bash ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 
$ rm ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 

即使你不再能看到它在LS文件仍然打開。 所以這並不是說bash會讀取整個文件 - 只有bash完成後才能真正完成。

+1

這就是爲什麼更新程序不應該更改現有的可執行文件,而是取消它們之間的鏈接,然後重寫新版本。 – curiousguy

+0

好的,但如果文件被另一個進程覆蓋會發生什麼?該文件未鏈接,因此它被視爲「自由空間」,不是嗎? –

+0

@G_G覆蓋僅表示由文件名命名的目錄條目現在鏈接到另一個inode。只要原始inode沒有被bash關閉,它就會存在並將被bash使用。 – w00t

-1

其實之前,這種現象是特定的殼(如bash)的,其閱讀將文件存入內存然後執行它們。

如果執行以下a.bat: 呼應YO1 德爾a.bat 回聲YO2

會得到以下的輸出: C:> a.bat

C:>回聲YO1 Yo1

C:> del a.bat 無法找到批處理文件。

這是按照您的期望:-)

+1

這是錯誤的; w00t的回答是正確的。當bash腳本在運行時,我親眼看到了錯誤結果,表示該文件正在被打開並被讀取。 –