我目前正在尝试使用两个 Fifo 套接字创建一个 systemd 服务。这些套接字映射到应用程序的标准输出和标准输入。我当前正在使用以下配置文件。
foo.service
[Unit]
Description=foo Fifo test
After=network.target foo-in.socket foo-out.socket
Requires=foo-in.socket foo-out.socket
[Service]
Sockets=foo-out.socket
Sockets=foo-in.socket
StandardOutput=fd:foo-out.socket
StandardInput=fd:foo-in.socket
StandardError=journal
ExecStart=/path/to/foo/exec
foo-out.socket
[Unit]
Description=foo Task Writes to this
[Socket]
Service=foo.service
ListenFIFO=%t/foo/out
foo-in.socket
[Unit]
Description=foo Task reads commands from this
[Socket]
Service=foo.service
ListenFIFO=/run/user/1000/foo/in
systemctl --user daemon-reload
我可以使用命令和启动服务systemctl --user start foo
。当我尝试停止 foo.service 时,问题就出现了。我收到这条消息:
Warning: Stopping foo.service, but it can still be activated by:
foo-in.socket
foo-out.socket
有没有办法在服务停止时自动停止套接字?
答案1
这是一个可以手动关闭的好例子。这里的示例是尝试关闭“docker”服务。
root@localhost:~# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
root@llocalhost:~# systemctl stop docker.socket
root@logicaldoc:~# ps aux | grep docker
root 1519 0.0 0.0 14220 924 pts/0 S+ 17:41 0:00 grep --color=auto docker
答案2
ExecStopPost 方法
当服务在成功完成后或由于失败而停止时,您可以使用该[Service]
块的选项来运行任意命令。ExecStopPost=
例子
仅更新了最后一行。
[Unit]
Description=foo Fifo test
After=network.target foo-in.socket foo-out.socket
Requires=foo-in.socket foo-out.socket
[Service]
Sockets=foo-out.socket
Sockets=foo-in.socket
StandardOutput=fd:foo-out.socket
StandardInput=fd:foo-in.socket
StandardError=journal
ExecStart=/path/to/foo/exec
ExecStopPost=systemctl --user stop foo-out.socket ; systemctl --user stop foo-in.socket
来源:系统服务(强调我的)
服务停止后执行的附加命令。这包括使用 ExecStop= 中配置的命令、服务未定义任何 ExecStop= 或服务意外退出的情况。此参数采用多个命令行,遵循与 ExecStart= 描述的相同方案。这些设置的使用是可选的。支持说明符和环境变量替换。请注意,与 ExecStop= 不同的是,当服务无法正确启动并再次关闭时,将调用使用此设置指定的命令。
建议使用此设置进行清理操作,即使服务无法正确启动也应执行这些操作。即使服务中途启动失败并留下未完全初始化的数据,使用此设置配置的命令也需要能够运行。由于在执行使用此设置指定的命令时服务的进程已经终止,因此它们不应尝试与它们通信。
请注意,使用此设置配置的所有命令都将使用服务的结果代码以及主进程的退出代码和状态进行调用,这些代码和状态在 $SERVICE_RESULT、$EXIT_CODE 和 $EXIT_STATUS 环境变量中设置,请参阅 systemd.exec (5) 详细信息。
请注意,出于 Before=/After= 排序约束的目的,考虑了 ExecStopPost= 的执行。
答案3
添加ExecStopPost=/rm (socket pathname)
到定义中,该定义是由via/etc/systemctl/system/(???).socket
启动的。(???).service
"Requires=???.socket"
要删除套接字,请停止服务,然后也停止套接字。如果您不停止套接字,则任何写入套接字的客户端都将重新激活服务,根据您停止服务时的消息:
警告:正在停止 (???).service,但仍可以通过以下方式激活它:(???).socket
答案4
我不会添加,而是ExecStopPost=systemctl ...
依赖 systemd 的预定义关系PartOf=
。
来自手册页:
PartOf=
Configures dependencies similar to Requires=, but limited to stopping and
restarting of units. When systemd stops or restarts the units listed
here, the action is propagated to this unit. Note that this is a one-way
dependency — changes to this unit do not affect the listed units.
When PartOf=b.service is used on a.service, this dependency will show as
ConsistsOf=a.service in property listing of b.service. ConsistsOf=
dependency cannot be specified directly.
在foo-out.socket
和中foo-in.socket
,您可以添加PartOf=foo.service
您的[Unit]
部分。然后,当foo.service
停止时,套接字也会停止。
foo.service(未触及)
[Unit]
Description=foo Fifo test
After=network.target foo-in.socket foo-out.socket
Requires=foo-in.socket foo-out.socket
[Service]
Sockets=foo-out.socket
Sockets=foo-in.socket
StandardOutput=fd:foo-out.socket
StandardInput=fd:foo-in.socket
StandardError=journal
ExecStart=/path/to/foo/exec
foo-out.socket
[Unit]
Description=foo Task Writes to this
PartOf=foo.service
[Socket]
Service=foo.service
ListenFIFO=%t/foo/out
foo-in.socket
[Unit]
Description=foo Task reads commands from this
PartOf=foo.service
[Socket]
Service=foo.service
ListenFIFO=/run/user/1000/foo/in