我有一个用PHP编写的守护进程(不是最好的语言,但与我一起工作),它用于从队列接收作业,并在需要完成作业时处理它们。对于每个新作业,我使用pcntl_fork()将作业分叉到子进程中。在这个子进程中,我然后使用proc_open()执行用于音频转码的长时间运行的系统命令,完成后直接返回到子进程。作业完成后,子进程退出并由父进程清理。
为了保持这个守护进程始终运行,我使用upstart。这是我的暴发户配置文件:
description "Audio Transcoding Daemon"
start on startup
stop on shutdown
# kill signal SIGCHLD
kill timeout 1200 # Don't force kill the process until it runs over 20 minutes
respawn
exec audio-daemon.php
因为我想在分布式环境中使用这个守护进程,所以我希望能够在不中断任何正在运行的作业的情况下随时关闭服务器。为此,我已经在父进程上使用pcntl_signal()为SIGTERM、SIGHUP和SIGINT实现了信号处理程序,它在退出自身之前等待所有子进程正常退出。子进程也有信号处理程序,但它们被要求忽略所有终止信号。
问题是,根据文件...
由 kill 信号节指定的信号将发送到主进程的进程组。(这样,属于作业主进程的所有进程都被终止)。默认情况下,此信号为 SIGTERM。
这很令人担忧,因为在我的子进程中,我通过proc_open()运行系统命令,这也会产生新的子进程。因此,每当我运行sudo Stop Audio-daemon
时,这个子进程(碰巧是sox)会立即被杀死,并且作业返回时会出现错误。显然,sox遵守SIGTERM并按照它的指示行事...
最初,我想,“好吧。我只会改变终止信号
来发送一些本质上被忽略的东西,我只会在主进程中拾取它。但根据手册,默认情况下只有两个信号被忽略:SIGCHLD和SIGURG(可能还有SIGWINCH)。但我害怕得到错误的标志,因为这些也可以通过其他方式触发。
有一些方法可以使用手册中所称的“实时信号”创建自定义信号,但它也指出。。。
未处理实时信号的默认操作是终止接收过程。
所以这没有帮助...
你能想出任何方法让我成为暴发户,让我所有的子流程保持开放,直到它们完成吗?我真的不想去挖掘sox的源代码来修改它的信号处理程序,虽然我可以设置SIGCHLD,SIGURG或SIGWINCH作为我的暴发户杀戮信号,并祈祷没有其他任何东西可以按照我的方式发送它们,但我忍不住认为有更好的方法来做到这一点......有什么想法吗?
谢谢你的帮助!:)
免责声明:我不知道任何PHP
我通过为已启动的子进程设置新的组id,解决了ruby进程的类似问题。看起来php也有类似的功能。
您可以通过设置它的组id到它的进程id来启动一个新组(从您的audio-daemon.php
分离)
类似的东西
$chldPid=pcntl_fork()
... << error checks etc
if ($chldPid){
...
posix_setpgid($chldPid, $chldPid)
由于我没有收到任何其他关于如何以更好的方式做这件事的答案,这就是我最后做的,我希望它能帮助那里的人...
为了在守护进程完成之前停止系统的关闭/重启,我在upstart配置中更改了我的< code>start on和< code>stop on。为了防止upstart杀死我的孩子,我使用SIGURG作为我的< code>kill signal,然后我只在我的主守护进程中捕获它作为kill signal。
这是我的最终upstart配置:
description "Audio Transcoding Daemon"
start on runlevel [2345]
stop on starting rc RUNLEVEL=[016] # Block shutdown/reboot until the daemon ends
kill signal SIGURG # Kill the process group with SIGURG instead of SIGTERM so only the main process will pick it up (since SIGURG will be ignored by all children by default)
kill timeout 1200 # Don't force kill the process until it runs over 20 minutes
respawn
exec audio-daemon.php
请注意,使用< code > stop on starting RC run level =[016]是停止关机/重启所必需的。< code >在运行级别[016]停止将不起作用。
另外请注意,如果您在应用程序中出于任何其他原因使用SIGURG,将其用作终止信号可能会导致问题。就我而言,我不是,所以就我所知,这一切都很好。
理想情况下,如果POSIX标准提供了一个默认忽略的用户定义信号,如SIGUSR1和SIGUSR2,那就太好了。但是现在,它看起来不存在。
如果你有更好的答案,请随意插话,但现在,我希望这能帮助其他有这个问题的人。
我正在使用Javaexec运行bash脚本,但当我进入CTRL C时,Java进程将退出,子进程也将退出,如何在JVM关闭后保持子进程运行? 父母亲上海: 我已经在这里和这里阅读了类似问题的答案,例如,使用nohup在脚本运行命令中启动父bash脚本,或者使用trap命令来阻止信号,在我的研究中,它可以工作,例如“tail-f somefile”,但不适用于我的用例“ffmpeg-params”,
null 正在停止现有后台进程
我使用Spring Boot Gradle插件启动Tomcat服务器&我的应用程序。我通过启动Tomcat服务器。我还启用了Gradle守护进程,希望能让Gradle构建更快。
[注意:这与如何从Java程序启动完全独立的进程有关?但不同] 我希望能够从一个“管理器”Java进程中派生出外部进程(shell脚本),当JVM被杀死时,该进程应该继续运行——但当我杀死父Java程序时,子Java程序似乎也被杀死(注意,如果JVM自然退出,行为会有所不同)。我拥有的最简单的测试程序是: 和外部脚本: 作为 java-带有依赖项的类路径jar。罐子温度。执行官。快跑快跑。嘘 如果
问题内容: 例如从bash: 仅杀死父进程。 问题答案: 当您将 负 PID传递给时,它实际上会通过该(绝对)数字将信号发送到过程 组 。您可以在Python中完成与之等效的操作。
问题内容: 使用shelljs创建一个子进程 杀死父进程后,子进程仍在运行.. 问题答案: 如果您可以使用node的内置,则可以向子进程发送信号: 这样做的好处是,主进程应该一直徘徊,直到所有子进程都终止。