【发布时间】:2012-08-15 01:58:57
【问题描述】:
我想要一种在 shell 脚本中编写守护程序的方法,它会在循环中运行另一个应用程序,如果它死了就重新启动它。
- 当在 SSH 会话中使用
./myscript.sh运行时,它将启动一个新的守护进程实例,除非该守护进程已经在运行。 - 当 SSH 会话结束时,守护进程将继续存在。
- 应该有一个参数 (
./myscript -stop) 可以杀死任何现有的守护进程。
(关于编辑的注意事项 - 原始问题指定不能使用nohup 和类似工具。这个人为的要求是“XY 问题”,并且接受的答案实际上使用了 OP 声称无法使用的所有工具。)
【问题讨论】:
-
为什么需要 pid?这听起来有点可疑:要拥有一个守护进程,您需要使用双分叉技巧(fork/setsid/fork)。这意味着启动进程虽然可以将孙子进程的 pid 发送给它,但不能等待守护进程。守护进程的 pid 并没有太多用处(当然,守护进程本身可以使用它,例如放入 /var/run 并确保它是自身运行的唯一副本)。
-
@NicholasWilson 如果我们在那个技巧中得到的 PID 没有用,你能给我一个你说的版本的例子吗?因为我前段时间看到过那个技巧,现在记不起很多细节了。我需要 PID 来避免重复。过程。所以主进程将接收诸如启动、停止等参数,并且分叉应该作为那里的另一个进程的看门狗。我对看门狗和 args 没有问题,但坚持正确的分叉
-
您必须再解释一下。你说你想要一个守护进程,也就是说,一个完全脱离启动它的进程。您需要另一个可以控制守护程序的脚本。您是否要避免重复的守护进程?在这种情况下,在您的守护程序脚本开始时您应该执行
if test -f /var/run/appname.pid; then exit; fi; echo $$ > /var/run/appname.pid; trap 'rm /var/run/appname.pid' EXIT。然后使用 nohup 启动守护进程。要与守护进程通信,无论如何您都需要使用其他一些 IPC 机制(bash 支持 FIFO)。 -
@NicholasWilson 所以这个脚本的一般目的是它会被调用让我们说从像 ./my_script.sh 这样的 ssh 会话然后它将自己分叉到守护进程,作为守护进程它将启动另一个appname,然后在无限循环中运行,每秒检查该进程是否处于活动状态,如果没有 - 重新启动它。正如我之前提到的,我非常了解 nohup,但在我的情况下它没有用,就像没有可用的 cron 一样。
-
还有一点,为什么不能使用 nohup 来调用这个脚本本身:这个脚本是从另一个脚本调用的,并检查它是否已经在运行,如果没有,那么它进入守护进程,如果是,它退出让守护程序运行并报告这种情况,如果使用参数调用顶级脚本让我们说停止——它将能够停止这个看门狗。