我有一个脚本,它启动一个守护进程,然后休眠 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
shopt
Massimo 引用的答案,如果这不是我上面提到的 sudo 问题,那听起来很有希望
答案2
您可以在脚本中为想要守护进程的命令添加前缀:
nohup command-that-you-want-to-demonize &
然后当外部脚本完成时程序将继续运行。
答案3
尝试disown
在将进程置于后台后在其自己的一行上添加。这应该可以防止您的 shell 在退出时向任何子进程发送信号。
答案4
尝试添加</dev/null
到启动命令中。
不确定该-bgnd
标志究竟是如何让您的进程退居后台的,但如果进程的标准输入丢失,进程可能会死亡,这正是您丢失 ssh 连接时发生的情况。您已经将所有输出丢弃到 bitbucket,您可能希望确保也没有输入。
我无法解释这种行为的改变,但我的建议是接受它。