如果正在执行的bash脚本文件被覆盖会发生什么?它会继续执行旧文件还是覆盖文件?覆盖正在执行的bash脚本文件
例如 /etc/test.sh具有以下内容
CP /test.sh /etc/test.sh
如果正在执行的bash脚本文件被覆盖会发生什么?它会继续执行旧文件还是覆盖文件?覆盖正在执行的bash脚本文件
例如 /etc/test.sh具有以下内容
CP /test.sh /etc/test.sh
壳加载脚本到存储器,并产生一个单独的过程,所以旧脚本将继续运行未修改。
显然,如果您尝试重新运行它,您将获得新版本。
如果你想在运行时引入一些新功能,我会建议写入临时文件,然后使用$()
或`(反引号)语法执行该文件以产生一个新进程。
或者,您可以使用exec
来完全替换当前正在运行的程序。
一般的好建议,但似乎并不能保证bash会预先读取*整个*原始文件;相反,它似乎以固定大小的块读取脚本 - 请参阅http://stackoverflow.com/a/20722200/45375。因此,被覆盖的内容*可能会被执行。 – mklement0
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)。
我更喜欢这个答案。 – Donovan
你自己尝试过吗?发生了什么? – grebneke