到目前为止我的配置是:
foo.path
[Path]
PathExists=/tmp/foo.path
[Install]
WantedBy=multi.user.target
foo.service
[Unit]
Description=Matt Test
BindsTo=foo.path
[Service]
ExecStart=/bin/sh /home/mpekar/bin/foo.sh
PIDFile=/run/foo.pid
这在启动时工作正常,但当 /tmp/foo.path 被删除时 foo.service 不会被终止。有没有办法让 systemd 做到这一点,或者它只是不适合这项工作的工具?
答案1
我会尝试这个。使用 PathChanged 创建附加服务:
foo-stop.path
[Path]
PathChanged=/tmp/foo.path
[Install]
WantedBy=multi.user.target
然后创建:foo-stop.service
让其“ExecStart”脚本检查是否/tmp/foo.path
已被删除(因为 PathChanged 也可能会触发其他更改)。如果路径已被删除,请让脚本调用/bin/systemctl stop foo
.
答案2
如果您能够在删除 /tmp/foo.path 时终止绑定到 PIDFile (/run/foo.pid) 的进程(例如,两者都作为服务关闭脚本中的操作),那么可以。
我在运行 <= RHEL-7.7 的 Tomcat 上实现了这一点,并使用分叉服务,其中包括 ExecStartPost 操作,该操作将应用程序 pidfile (catalina.pid) 的内容记录到服务 PIDFile 路径中。相应的 .path 文件中的“PathExists”会跟踪此 catalina.pid 上出现的内容,以便在用户(在我的情况下为无特权)调用启动脚本时挂钩 systemd 服务。当用户启动关闭时,应用程序 pidfile 被删除,PID(也是非特权的)优雅地终止,并且 systemd 停止服务作为 systemd pid 监督的结果。
poc.服务:
[nouser@nohost system]# cat poc.service
# . . .
[Unit]
After=network.target
After=%p.path
Wants=%p.path
# . . .
[Service]
Type=forking
Environment="%p_APPLICATION_PID_FILE=/opt/%p/logs/catalina.pid"
PIDFile=/var/run/%p.pid
ExecStart=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen start'
ExecStartPost=/bin/sh -c 'cat ${%p_APPLICATION_PID_FILE} > $(systemctl show %n -p PIDFile|cut -f2- -d"=")'
ExecStop=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen stop'
# . . .
poc.路径:
[nouser@nohost system]# cat poc.path
# . . .
[Path]
PathExists=/opt/%p/logs/catalina.pid
# . . .
这种方式也适用于 Spring Boot 应用程序。但由于它们天生就挂在 bash 进程上,我必须立即终止该父进程,以强制 PID 1 成为应用程序父进程。如果没有,journalctl 会显示一条消息“*.service:监督进程 XXXXX 这不是我们的子进程。我们很可能不会注意到它何时退出。”,并且最后 systemd 服务不会在用户关闭操作时停止。