shell脚本可以删除或覆盖自身吗?

时间:2013-12-21 18:15:07

标签: bash

#beginning of bashscript1.sh
source bashscript2.sh
echo $variable

这是源文件:

#beginning of bashscript2.sh
rm -f bashscript2.sh
variable = "integer of some kind"

如何处理bash脚本?是首先加载源文件然后删除它,还是变量在bash脚本1中有值?

2 个答案:

答案 0 :(得分:17)

在类Unix操作系统上,如果文件仍处于打开状态,则可以删除该文件。文件名将不再存在,但数据本身仍然存在,并且任何具有打开句柄的程序(包括bash)都可以继续使用该句柄读取(甚至写入)。只有当最后一个程序关闭其句柄时,该文件才真正被删除。

因此,从某种意义上说,是的,shell脚本可以自行删除,但在执行该脚本完成之前,

请注意,如果覆盖文件而不是删除文件,则会得到不同的结果。 shell可以(并且确实)使用缓冲来避免一次读取一个字节,但缓冲区的大小有限。如果文件内容超出了shell已经读入内存的范围,它将看到新内容。如果检查系统的缓冲区大小,可以创建一个简单的示例。在我的系统上,恰好是8 KiB。所以包含

的shell脚本
echo line 1
>test.sh
# (8167 random characters)
echo line 4

所以第二个数据块是“cho line 4”,在我的系统上输出

$ bash test.sh
line 1
test.sh: line 4: e: command not found

因为已经读取了e,并且在尝试读取该行的其余部分时shell遇到了EOF。

更新:rici显示,如果使用覆盖文件的不同示例,则会使用新写入的内容。重做:

script="`tr 12 21 <test.sh`"
env echo "$script" >test.sh
echo toggle: 1

第二行故意不使用bash的内置echo命令,因为根据注释,有时不会导致bash重新读取脚本,但恰恰是在它执行和不执行时我不清楚。当bash到达第三行时,bash输出新写​​入的切换值。这与我之前的例子之间的相关区别似乎是,在这里,bash可以在到达第三行时寻找当前位置,而在我之前的例子中,这是不可能的,因为该位置不再存在,因为文件是空。

答案 1 :(得分:2)

这是您的好奇心还是您真正想要获得的东西?

无论如何,我已经尝试过这个简单的脚本(test_script.sh):

rm -f test_script.sh
echo "Still here!"

并打印Still here!,因此文件在执行前加载。 第二次无法执行。

回答你的问题,是的,不是。脚本中的命令被加载并执行,并且可以删除脚本的源文件。当然,这将无法再次执行相同的文件,但不会影响第一次执行。