守护进程在 shell 关闭时退出

守护进程在 shell 关闭时退出

我有一个脚本,它启动一个守护进程,然后休眠 20 秒。如果我在 SLES11 SP1 或 RHEL6 上运行该脚本,则脚本退出后,进程仍在运行。

如果我在 SLES11 SP3 或 RHEL6.3 上运行该脚本,则脚本退出后,该进程将不再运行。该进程将继续运行整个 20 秒的休眠期,并在退出时被终止。

该脚本是通过 expect 运行的,因此脚本的整个 shell 会随进程一起退出。显然,如果这不是正在启动的守护进程,我就不会感到惊讶。此外,我怀疑问题不在于操作系统版本,而在于我们设置较新服务器的方式不同(但不知道这些差异是什么,旧服务器是几年前设置的)。

在此过程运行的 20 秒内,如果我执行 ps,我会得到以下结果:

root      4699     1  0 15:14 pts/2    00:00:00 sudo -u openmq /opt/PacketPortal/openmq/default/bin/imqbrokerd -bgnd -autorestart -silent -port 7676 -Dimq.service.activelist=admin,ssljms -D
openmq    4701  4699  0 15:14 pts/2    00:00:00 /bin/sh /opt/PacketPortal/openmq/default/bin/imqbrokerd -bgnd -autorestart -silent -port 7676 -Dimq.service.activelist=admin,ssljms -Dimq.ssl
openmq    9095  9063 54 16:21 pts/2    00:00:02 /usr/java/latest/bin/java -cp /opt/PacketPortal/openmq/default/bin/../lib/imqbroker.jar:/opt/PacketPortal/openmq/default/bin/../lib/imqutil.jar:/opt/PacketPortal/ope

4699 的父进程为 1,这似乎表明该进程已正确守护。但是,在 expect 脚本退出后,4699 和 4701 都被终止。这可能是什么原因造成的?

更新

我在正常运行的服务器上打印了相同的输出。在 20 秒的休眠期间,我得到了:

openmq   18652     1  0 15:44 pts/1    00:00:00 /bin/sh /opt/PacketPortal/openmq/default/bin/imqbrokerd -bgnd -autorestart -silent -port 7676 -Dimq.service.activelist=admin,ssljms -Dimq.ssljms.tls.port=7680
openmq   18686 18652  8 15:44 pts/1    00:00:02 /usr/java/latest/bin/java -cp /opt/PacketPortal/openmq/default/bin/../lib/imqbroker.jar:/opt/PacketPortal/openmq/default/bin/../lib/imqutil.jar:/opt/PacketPortal/ope

经过 20 秒的睡眠后,我得到:

openmq   18652     1  0 15:44 ?        00:00:00 /bin/sh /opt/PacketPortal/openmq/default/bin/imqbrokerd -bgnd -autorestart -silent -port 7676 -Dimq.service.activelist=admin,ssljms -Dimq.ssljms.tls.port=7680
openmq   18686 18652  5 15:44 ?        00:00:02 /usr/java/latest/bin/java -cp /opt/PacketPortal/openmq/default/bin/../lib/imqbroker.jar:/opt/PacketPortal/openmq/default/bin/../lib/imqutil.jar:/opt/PacketPortal/ope

脚本退出后会断开控制终端。我不知道为什么在较新的服务器上不这样做。

更新

以下是实际启动 OpenMQ 的脚本部分。-bgnd 标志用于将其作为守护进程。

sudo -u openmq $IMQ_HOME/bin/$EXECUTABLE -bgnd $BROKER_OPTIONS $ARGS > /dev/null 2>&1 &

更新

我偶然发现了一些非常奇怪的行为。如果我将命令更改为:

sudo -u openmq sldkhglksj; $IMQ_HOME/bin/$EXECUTABLE -bgnd $BROKER_OPTIONS $ARGS > /dev/null 2>&1 &

然后我明白了sldkhglksj: command not found,当然,但是...openmq 进程没有被终止。如果我删除那个更改,它就会被终止。

更新

回想起来,似乎神奇的命令改变了 sudo,使其不在实际的 openmq 启动时运行,这让我相信 sudo 以某种方式参与其中。

答案1

您可能会遇到此处记录的问题:https://access.redhat.com/knowledge/solutions/180243

它指出,与你描述的操作类似的 sudo 行为在 RHEL/CentOS 6.3 (sudo-1.7.4p5-11.el6.x86_64) 附带的版本中发生了变化。你看到 RHEL 6 和 6.3 之间的行为不同,而且这涉及到 sudo,这就是我指出这一点的原因。

一些可以尝试的选项(我没有 100% 的答案,只是提出一些想法):

  • 如果您具有 root 级别访问权限(看起来您有),请尝试在不使用的情况下运行该脚本sudo,例如su -c '/opt/PacketPortal/openmq/default/bin/imqbrokerd -bgnd -autorestart -silent -port 7676 -Dimq.service.activelist=admin,ssljms -D' - openmq- 参见http://www.linfo.org/su.html了解更多信息
  • 安装旧版本来sudo解决这个问题(我知道这有点儿不方便,但你可以在临时位置构建/安装它来测试它)
  • 看看huponexit shoptMassimo 引用的答案,如果这不是我上面提到的 sudo 问题,那听起来很有希望

答案2

您可以在脚本中为想要守护进程的命令添加前缀:

  nohup command-that-you-want-to-demonize &

然后当外部脚本完成时程序将继续运行。

答案3

尝试disown在将进程置于后台后在其自己的一行上添加。这应该可以防止您的 shell 在退出时向任何子进程发送信号。

答案4

尝试添加</dev/null到启动命令中。

不确定该-bgnd标志究竟是如何让您的进程退居后台的,但如果进程的标准输入丢失,进程可能会死亡,这正是您丢失 ssh 连接时发生的情况。您已经将所有输出丢弃到 bitbucket,您可能希望确保也没有输入。

我无法解释这种行为的改变,但我的建议是接受它。

相关内容