我有一个名为lightid的专有程序,我想将它作为一个守护进程运行。 lightid的开发人员在命令行选项中添加了一个“-d”开关,以便能够将其作为守护进程运行。 使用sample-service-script,我创建了一个正确的启动/停止bash脚本并将其安装为服务,以便能够使用它来控制它 服务lightid开始 服务lightid停止 服务状态 等等... 最重要的是,我可以使用monit检查其状态。 bash脚本的启动功能(将放在/etc/init.d/lightid中)看起来像这样
SCRIPT="/home/foo/lightid -d"
RUNAS=giulio
NAME=lightid
PIDFILE=/var/run/$NAME.pid
LOGFILE="/dev/null"
CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
正如您所看到的,su命令应该返回守护进程的pid,以便可以将其写入$ PIDFILE, 并且可以使用检查其状态 PID = $(cat $ PIDFILE) ps axf | grep $ {PID} | grep -v grep 并且守护进程可以使用 kill -15 $(cat“$ PIDFILE”)
问题是,su -c "$CMD" $RUNAS > "$PIDFILE"
上方的行向$PIDFILE
写入了一个pid,该pid与后台运行的进程不同。例如,它将返回9933,而在后台运行的进程将返回pid = 9935。实际的pid始终是返回值+2。
我问开发人员lightid它的“-d”开关实际上做了什么,如果这可能是某种原因,实际的pid与su返回的pid不同。实际上,我怀疑返回的pid是父进程之一,它在fork之后“daemonizes”自身就会终止。他回复我了
“我按照我的方式创建守护进程的原因是因为这是Michael Kerrisk的书”Linux编程接口“中记录的内容。他给出的理由是:
1。)通过分叉和终止父级,子级成为init进程的子级。
2。)孩子需要调用setsid来启动新会话并从控制终端中解放出来。
3。)第二个分支确保进程不是会话负责人,因此无法重新获取控制终端(系统V要求)。
我从来没有遇到过创建守护进程的方法,因此无法按照你想要的方式获取进程PID的问题,我担心,这不是我以前处理过的事情。“
有什么方法可以得到正确的pid吗? 我应该通过适当地将stdin,stdout和stderr重定向到/ dev / null来在非守护进程模式下运行lightid吗?
答案 0 :(得分:2)
就像你正确地推断出来一样,问题是你的脚本守护着点亮lightid服务的lightid启动器。
由于您正在守护守护进程而不是实际服务,因此最终会出现错误的pid。
您应确保只涉及一个守护程序。如果lightid
支持本机编写pid文件,只需使用其功能。
如果没有,您应该使用一个用于守护事物的工具,例如daemon
,并让它运行非守护进程 lightid。这些工具重定向fds,创建会话,重置信号处理程序以及休闲守护程序脚本将忘记的所有其他内容。