2011-10-20 123 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脚本在运行时,我亲眼看到了错误结果,表示该文件正在被打开并被读取。 –