如何让一个进程在linux中重新加载自身?
题
我有一个服务,比如 foo,用 C++ 编写,以 root 身份运行。有常用的脚本 /etc/init.d/foo start|stop|restart。
在某些时候,foo 需要重新加载自身。通常在升级完成后。但做这样的事情:
system("/etc/init.d/foo restart")
不起作用,因为一旦重新启动杀死了 foo,system() 调用显然也会被杀死,并且重新启动脚本永远不会执行完成。
我是否可以使用另一个调用来代替 system() 作为调用进程的同级进程异步运行,而不是创建同步子进程?
谢谢!
解决方案
您是否考虑过 exec[*]
家人了吗?这是一个—— execve
.
其他提示
您可以将其放在 inittab 中,让 init 负责在进程因任何原因退出时重新启动该进程。如果您的进程发生崩溃或断言()或意外退出,这也将处理自动重新启动。
然后,为了处理您的用例,该进程将自行终止。
fork() 后面跟着 exec() 怎么样?
考虑实施
/etc/init.d/foo reload
对于你的守护进程(通过我的 Debian 盒子的 grep 判断,这是相当标准的)。
这通常是通过向进程发送 SIGHUP 信号来完成的;守护程序应具有信号处理程序,该信号处理程序捕获此并重新加载任何配置。
如果进程知道需要重新加载,它可以向自己发出信号。
如果您确实需要重新启动以获取新库,那么请使用 exec*()
结合到目前为止的两个答案,使用 分叉执行.
补充一下 Ori 已经说过的,一些 Linux 发行版仍然使用 initab,但 Ubuntu 和其他可能的发行版已经切换到 /etc/event.d。您将一个文件放入其中(复制并编辑现有文件之一),然后使用“sudo start ssh_tunnel”或任何您的文件名称启动守护进程。
然后当你需要它重新启动时,你只需用一个信号杀死它,系统就会重新启动它。或者它可以自己决定是该重新启动的时候,称“退出(0);”管他呢。
exec*()
在原始命令行上单独使用应该可以解决问题。您可能可以省略 fork,因为您有两个不需要的副本正在运行,然后原始副本需要退出。
但还要根据您的发行版查看 inittab 和 event.d,看看它是否能以更好的方式满足您的需要。
Ori 和 Paul 建议的第三种可能性是使用 daemontools。它更便携,但不太可能可用。您创建一个名为 /service/foo/run 的脚本,并且 daemontools 会在服务退出时重新生成您的服务。
查看 inittab 的手册页。
它描述了如果进程死亡(重生),系统将如何自动重新启动进程。
正确设置后,您的服务所要做的就是退出,系统将自动为您重新启动(重生)。