【问题标题】:Self deleting bash script自删除 bash 脚本
【发布时间】:2011-10-20 10:35:48
【问题描述】:

bash 脚本在遇到删除自身的语句后如何执行? 例如,当我运行包含以下内容的 test.sh 脚本时:

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

end

脚本会一直执行到最后才删除自己

【问题讨论】:

  • 当一个应用程序被执行时,它的代码被加载到内存中。你只是删除磁盘上的文件,不会影响内存中的代码。
  • 大概是整个脚本在执行时被读入内存,所以rm test.sh之后的命令还在内存中待执行。
  • 它不会在内存中复制。因此,例如,如果脚本在运行时被修改,它将执行修改。这让我最近很头疼。可爱的例子:这一行脚本将在短时间内填满你的磁盘:'cat $0 >>$0'。

标签: bash self-destruction


【解决方案1】:

实际发生的是 bash 保持文件打开,rm 不会停止。

所以rm 调用 libc 函数“unlink()”,它会从它所在的目录中删除指向 inode 的“链接”。这个“链接”实际上是一个文件名和一个 inode 编号(你可以看到ls -i 的 inode 编号)。

只要程序打开,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 完成之前并没有真正消失。

【讨论】:

  • 这就是为什么更新程序不应该更改现有的可执行文件,而是取消它们的链接,然后重写新版本。
  • 好的,但是如果文件被另一个进程覆盖了怎么办?该文件未链接,因此算作“可用空间”,不是吗?
  • @G_G 覆盖只是意味着由文件名命名的目录条目现在链接到另一个 inode。只要原来的inode没有被bash关闭,它就会存在并且会被bash使用。
【解决方案2】:

其实这种现象是shell特有的(比如bash),它把文件读入内存然后执行。

如果执行以下a.bat: 回声 Yo1 德尔阿巴特 回声Yo2

您会得到以下输出: C:>a.bat

C:>回声 Yo1 哟1

C:>del a.bat 找不到批处理文件。

这是您的期望:-)

【讨论】:

  • 这是错误的; w00t 的答案是正确的。我个人看到,当 bash 脚本在运行时被编辑时会出现错误,这表明文件正在保持打开和读取状态。
猜你喜欢
  • 2019-07-21
  • 2021-01-17
  • 1970-01-01
  • 2022-10-23
  • 2014-10-28
  • 1970-01-01
  • 2011-01-28
  • 2016-07-07
  • 2011-04-06
相关资源
最近更新 更多