我有一个服务器进程(从 systemd 启动)可以启动更新进程。更新过程 self 守护,然后(理论上)用 SIGTERM 杀死服务器。我的问题是 SIGTERM 传播到更新进程及其子进程。
出于调试目的,更新进程只是休眠,我手动发送 kill。
杀死前的 PS 输出示例:
1 1869 1869 1869 ? -1 Ss 0 0:00 /usr/local/bin/state_controller --start
1869 1873 1869 1869 ? -1 Sl 0 0:00 \_ ProcessWebController --start
1869 1886 1869 1869 ? -1 Z 0 0:00 \_ [UpdateSystem] <defunct>
1 1900 1900 1900 ? -1 Ss 0 0:00 /bin/bash /usr/local/bin/UpdateSystem refork /var/ttm/update.bin
1900 1905 1900 1900 ? -1 S 0 0:00 \_ sleep 10000
请注意,UpdateSystem 位于单独的 PGID 和 TPGID 中。 (<defunct>
进程是守护进程的结果,不是(我认为)问题。)
UpdateSystem 是一个 bash 脚本(尽管如果有帮助,我可以轻松地将它变成一个 C 程序)。在取自 https://stackoverflow.com/a/29107686/771073 的守护程序代码之后,有趣的一点是:
#############################################
trap "echo Ignoring SIGTERM" SIGTERM
sleep 10000
echo Awoken from sleep - presumably by the SIGTERM
exit 0
当我 kill 1869
(它将 SIGTERM 发送到 state_controller
服务器进程,我的日志文件包含:
Terminating
Ignoring SIGTERM
Awoken from sleep - presumably by the SIGTERM
我真的很想阻止 SIGTERM 被发送到 sleep
过程。
(实际上,我真的想阻止它被发送到 apt-get upgrade
,它通过 systemctl stop ttm.service
的道德等价物停止系统并且 ExecStop
被指定为 /bin/kill $MAINPID
- 以防万一这会改变任何人的答案。)
这个问题很相似,但接受的答案(使用 KillMode=process
)对我来说效果不佳 - 我想杀死一些子进程,而不是更新进程:
Can't detach child process when main process is started from systemd
最佳答案
一种完全不同的方法是升级过程通过更新 /sys/fs/cgroup/systemd
文件系统将自己从服务组中删除。特别是在 bash 中:
echo $$ > /sys/fs/cgroup/systemd/tasks
一个进程只属于一个控制组。将其 PID 写入根 tasks
文件会将其添加到 other 控制组,并将其从服务控制组中删除。
关于linux - 如何在 systemd 控制组之外启动进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35200232/