linux - 作为守护进程运行程序返回错误的 pid

标签 linux shell fork daemon pid

我有一个名为 lightid 的专有程序,我想将它作为守护进程运行。 lightid 的开发人员在命令行选项中添加了一个“-d”开关,以便能够将其作为守护进程运行。 使用sample-service-script ,我创建了一个正确的启动/停止 bash 脚本并将其作为服务安装,以便能够使用 服务 lightid 启动 服务 lightid 停止 服务 lightid 状态 ETC... 最重要的是,这样我可以使用 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 斧头 | grep ${PID} | grep -v grep 并且可以使用杀死守护进程 kill -15 $(cat "$PIDFILE")

问题是 su -c "$CMD"$RUNAS > "$PIDFILE" 上面的行向 $PIDFILE 写入了一个与在后台运行的进程。例如,它将返回 9933 而在后台运行的进程将具有 pid=9935 。实际的 pid 始终是返回值 +2。 我问 lightid 的开发者它的“-d”开关实际上做了什么,以及这是否是实际 pid 与 su 返回的 pid 不同的原因。事实上,我怀疑返回的 pid 是父进程之一,它在 fork 之后“守护进程”后立即终止。他回复了我

"The reason I create the daemon the way I do is because that's what's documented in Michael Kerrisk's book The Linux Programming Interface. The reasons he gives are:

1.) By forking and terminating the parent the child becomes a child of the init process.

2.) The child needs to call setsid to start a new session and free itself from the controlling terminal.

3.) The second fork ensures the process is not a session leader and thus can't re-acquire the controlling terminal (System V requirement).

I've never come across a means of creating a daemon without forking so the problem of getting the processes PID the way you want to is, I'm afraid, not something I've dealt with before."

有什么方法可以获得正确的 pid 吗? 我是否应该通过将 stdin、stdout 和 stderr 适本地重定向到/dev/null 而在非守护进程模式下运行 lightid?

最佳答案

正如您正确推断的那样,问题在于您的脚本守护进程 lightid 启动程序,后者守护进程 lightid 服务。

由于您正在守护守护程序而不是实际服务,因此您最终得到了错误的 pid。

您应该确保只涉及一个守护进程。如果 lightid 支持本地编写 pid 文件,只需使用它的功能即可。

如果没有,您应该使用一个用于守护进程的工具,例如 daemon,并让它运行一个非守护进程 lightid。这些工具重定向 fds、创建 session 、重置信号处理程序以及临时守护程序脚本会忘记的所有其他事情。

关于linux - 作为守护进程运行程序返回错误的 pid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24643340/

相关文章:

linux - 在 Docker 容器中运行的进程的主机中的 PID 是什么?

linux - 使用 wget 处理身份验证重定向

Linux awk 打印某些文本

multithreading - 常见的Lisp : Run function in the background

linux - Apache 测试页面不知从何而来

linux - Grep 多个 bash 参数

Shell 添加 sleep 和循环

c - 使用 fork 和 pipe 在数组中搜索最大值

c - 接收到用户定义的信号时,进程不会取消暂停

子进程在使用父进程将数据写入管道之前读取数据