*有时*分叉的脚本的 systemd 服务文件

*有时*分叉的脚本的 systemd 服务文件

我有一个 systemd 服务来运行由 systemd 计时器启动的监视 bash 脚本。我用过Type=oneshot看起来最合适的。然而,有时脚本需要调用另一个程序,这恰好会fork。一旦完成,脚本就会完成并退出,但是一旦脚本退出,systemd 将杀死所有剩余的子进程。

我可以用来KillMode=process防止这种情况,但是存在这样的风险:在脚本的其他路径中,其他进程(不分叉)可能在退出后继续运行。

处理这个问题的最佳方法是什么?

顺便说一句,分叉程序是 dhcpcd,但我认为这个问题普遍适用。 dhcpcd 最初由 ifplugd 启动,此脚本是一个故障保护脚本,以防系统最终处于 dhcpcd 不再运行的状态。

答案1

进程被杀死是因为它们属于与服务关联的控制组(cgroup),例如这里(对于系统服务):

/sys/fs/cgroup/systemd/system.slice/your-service.service

要将进程移出 cgroup,将其分配给另一个cgroup。 “父cgroup”似乎是正确的。对于系统服务来说是这样的:

echo <PID> > /sys/fs/cgroup/systemd/system.slice/tasks
# or even to the general systemd cgroup
echo <PID> > /sys/fs/cgroup/systemd/tasks

要从一开始就运行此 cgroup 中的某些命令,请运行一个将自身分配给该 cgroup 的 shell,然后exec运行实际命令:

sh -c 'echo "$$" > /sys/fs/cgroup/systemd/tasks; exec /the/forking/program'

/the/forking/program将替换已经在新 cgroup 中的 shell。当它分叉时,分叉的实例将发现自己位于新的 cgroup 中。当主脚本退出时,systemd 将杀死与该服务关联的 cgroup 中的进程,但有问题的程序不会在其中。

也许有更合适的方法来解决您的问题,使用单元文件或其他东西。但我不知道。

相关内容