Gor*_*son 10
庆典一般不会不提前加载整个脚本,因此可以写剧本能有不可预知的后果.例如,我刚刚创建了一个包含以下内容的脚本:
#!/bin/bash
echo start old file
sleep 20
echo end old file
Run Code Online (Sandbox Code Playgroud)
......跑了 在它睡觉的时候,我用这个略有不同的脚本覆盖了它:
#!/bin/bash
echo started new file
sleep 20
echo end new file
Run Code Online (Sandbox Code Playgroud)
导致此输出:
$ ./test.sh
start old file
./test.sh: line 4: 0: command not found
end new file
Run Code Online (Sandbox Code Playgroud)
发生了什么事情是bash在睡觉之前读过"睡20"线(包括终止换行的行).当它继续之后,它从文件中的下一个字节位置读取下一个命令,并且由于第二行已经长了两个字节("开始" - >"开始"),它最后读取了最后两个字节新的睡眠行("睡眠20 \n" - >"0 \n"),尝试执行"0"作为命令,并收到错误.然后它运行新内容的最后一行.很乱,对吧?
幸运的是,有一种方法可以强制bash将整个脚本加载到内存中,这样如果在运行时它被改变就不会混淆:
#!/bin/bash
{
echo start old file
sleep 20
echo end old file
exit
}
Run Code Online (Sandbox Code Playgroud)
该{外壳通过匹配至少阅读的力量},以便正确解析命令,并且exit然后确保它永远不会尝试执行被之后添加任何东西}.
顺便说一下,我用bash版本3.2.48(1)-release(OS X 10.8.5)测试了这个; 其他版本可能表现不同......
更新:其他版本确实表现不同.我尝试使用版本4.3.0(1)-release(在NetBSD 6.1.4下)进行相同的测试,并在文件内容被替换后继续运行旧代码.显然它现在以8KB块缓冲文件(请参阅此unix.se答案).
Don*_*van -1
shell 将脚本加载到内存中并生成一个单独的进程,因此旧脚本将继续运行而不进行修改。
显然,如果您尝试重新运行它,您将获得新版本。
如果您尝试在运行时引入一些新功能,我建议写入临时文件,然后使用 或$()``(反引号)语法执行该文件以生成新进程。
或者,您可以使用它exec来完全替换当前正在运行的程序。