我有一个基于 C++ 的应用程序,我将其作为 systemd 的守护进程运行(可执行)。
单位档案:
[单元] 描述=控制台服务 之后=网络.目标 [服务] 环境=“用户= ubuntu”“路径= / home / ubuntu / console / bin” 工作目录=/home/ubuntu/console/bin ExecStart=/bin/sh -ec "exec /sbin/start-stop-daemon -S -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --oknodo --exec控制台可执行文件“#2>/dev/null ExecStop=/bin/sh -ec "exec /sbin/start-stop-daemon -K --quiet -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --retry =TERM/30/KILL/5 --oknodo --exec consoleExecutable" #2>/dev/null 重新启动=失败时 退出后剩余=否 超时停止秒=10 成功退出状态=0 1 超时开始秒=360 [安装] WantedBy=多用户.target
当我发出启动命令时,服务正在启动,但随后它立即收到关闭信号,然后退出。任何线索,发生了什么?
sudo systemctl 状态控制台.service ● console.service - 控制台服务 已加载:已加载(/etc/systemd/system/console.service;已启用;供应商预设:已启用) 活跃:自 UTC 时间 2017-09-25 星期一 19:58:58 起停用(stop-sigterm); 1秒前 进程:8706 ExecStop=/bin/sh -ec exec /sbin/start-stop-daemon -K --quiet -c ${USER} -d ${Path} --pidfile=/var/run/console.pid - -retry=TERM/30/KILL/5 --oknodo --exec consoleExecutable #2>/dev/null (代码=已退出,状态=0/成功) 进程:8701 ExecStart=/bin/sh -ec exec /sbin/start-stop-daemon -S -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --oknodo - -exec consoleExecutable #2>/dev/null (代码=已退出,状态=0/成功) 主 PID:8701(代码=已退出,状态=0/成功) 任务:1 内存:1.8M 中央处理器:53毫秒 CGroup:/system.slice/console.service └─8705 控制台可执行文件 9 月 25 日 19:58:58 mgmt1 systemd[1]:启动控制台服务。 sudo systemctl 状态控制台.service ● console.service - 控制台服务 已加载:已加载(/etc/systemd/system/console.service;已启用;供应商预设:已启用) 活跃:自 UTC 时间 2017-09-25 星期一 19:59:01 起不活跃(死亡); 947 毫秒前 进程:8706 ExecStop=/bin/sh -ec exec /sbin/start-stop-daemon -K --quiet -c ${USER} -d ${Path} --pidfile=/var/run/console.pid - -retry=TERM/30/KILL/5 --oknodo --exec consoleExecutable #2>/dev/null (代码=已退出,状态=0/成功) 进程:8701 ExecStart=/bin/sh -ec exec /sbin/start-stop-daemon -S -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --oknodo - -exec consoleExecutable #2>/dev/null (代码=已退出,状态=0/成功) 主 PID:8701(代码=已退出,状态=0/成功) 9 月 25 日 19:58:58 mgmt1 systemd[1]:启动控制台服务。
答案1
环境=“用户= ubuntu”“路径= / home / ubuntu / console / bin” 工作目录=/home/ubuntu/console/bin ExecStart=/bin/sh -ec "exec /sbin/start-stop-daemon -S -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --oknodo --exec控制台可执行文件“#2>/dev/null ExecStop=/bin/sh -ec "exec /sbin/start-stop-daemon -K --quiet -c ${USER} -d ${Path} --pidfile=/var/run/console.pid --retry =TERM/30/KILL/5 --oknodo --exec consoleExecutable" #2>/dev/null
这几乎堪比systemd的恐怖屋了。如果不是已经有一个恐怖故事可以做到这一点的话。
不要start-stop-daemon
在服务单位中使用来做所有的事情服务单位已经这样做了ExecStart
.不仅有不必要的 PID 文件,而且还错误地假设可以接受 shell 语法注释。
并且不要按照其他答案所说的去做并尝试用 来回避它Type=forking
。这会让事情变得更糟,而不是更好。
胡说八道start-stop-daemon
就是为什么事情会出错。因为进程运行时start-stop-daemon
不变得服务,但实际上几乎立即退出,systemd 认为您的服务正在终止。在第一个systemctl status
输出中,您可以看到 systemd 正在发送SIGTERM
清理操作后所有剩余运行进程的消息ExecStop
,这是它在认为服务已终止时所做的操作。
简单地做事:
类型=简单 工作目录=/home/ubuntu/console/bin 用户=ubuntu ExecStart=/home/ubuntu/console/bin/consoleExecutable
不,实际上ExecStop
也不是必需的。Environment
进一步阅读
- 乔纳森·德博因·波拉德 (2015)。您确实不需要守护进程。真的。。 systemd 恐怖屋。
- 乔纳森·德博因·波拉德 (2016)。如果您有两个服务,请定义两个服务。。 systemd 恐怖屋。
- 乔纳森·德博因·波拉德 (2015)。Unix 守护进程的就绪协议问题。经常给出的答案。
- Systemd 启动后立即终止服务
答案2
systemd 认为您的守护进程的 pid 是 8701,这是start-stop-daemon
.你的守护进程的 pid 是 8705。你需要在你的单元文件中设置Type=forking
(在 下)。[Service]
默认情况下Type=simple
假设进程不分叉。
然而,你为什么要使用这个/bin/sh -ec exec /sbin/start-stop-daemon
怪物呢? systemd 可以处理 start-stop-daemon 所做的一切。