递归调用 sh 脚本的安全方法



所以我发现在Linux中这样做的困难方法真的很糟糕:

# a.sh
while true
do
  some stuff
  sh a.sh
done

我希望能够更新脚本并自行修复。这样的事情被认为是安全的吗/

# a.sh
while true
do
  wget http://127.0.0.1/b.sh
  sh b.sh
done
# b.sh
some stuff

这样我就可以更新脚本b.sh并且它的下一次执行将强制更新,因为a.sh调用它?

如果您希望进程更改其源代码并重新启动自身,并且不希望进程的多个(略有不同的)副本同时运行,那么您需要以某种方式杀死父进程。你怎么做并不重要;例如,如果代码的"重写自我"部分仅在实际需要重写时才触发,那么您可以在调用重写脚本的行之后放置"exit"。(我怀疑像mv -f b.sh a.sh && sh a.sh && exit这样的东西也可能有效,因为我认为整行会在脚本被销毁之前发送给 Bash 解释器。

如果您确实希望运行进程的多个副本,则需要找到某种方法来限制此数量。例如,您可以让脚本在分叉之前检查自身已经运行了多少次迭代。

请注意,在这两种情况下,这都假设您的脚本已准确地修改了自身,这...至少可以说,这是一个棘手的问题。你踩在危险的地面上。

最后,如果你真正想要的只是一个守护进程,当它死去时会自动重新启动(这听起来像你在评论中描述的),还有其他方法可以实现这一点。我不太熟悉这种事情通常是如何完成的,但我想在 shell 脚本中你可以简单地使用 trap .(trap a.sh EXIT可能就足够了,尽管如果您后来决定犯了错误,这将使您的脚本很难永久终止。

您可能

想要exec脚本。 exec将执行中的脚本替换为新的执行环境,因此它永远不会返回(除非启动指示的程序时出现问题)。

除非您知道自己在做什么,否则覆盖正在运行的脚本是个坏主意。 bash 在启动脚本时不会将整个文件读入内存,因此它将在被覆盖的文件中以相同的字节偏移量继续。

最后,当你的意思是bash时,不要使用shsh可能是一个不同的外壳,即使它是bash,它也会有不同的行为。

最新更新