我为 manqge HLTV 服务器制作了一个小型 systemctl 服务(它记录游戏中的演示并将其存储在磁盘上):
[Unit]
Description=HLTV server
Requires=cs16.service
After=cs16.service
[Service]
Type=simple
User=cs16
Group=cs16
UMask=007
ExecStart=/home/cs16/server/hltv_start.sh
Restart=on-failure
# Configures the time to wait before service is stopped forcefully.
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
它工作得很好,但是如果我关闭/重新启动系统服务,它会杀死该进程,从而损坏当前正在编写的演示。
为了正确保存演示,我需要在 htlv 命令工具中输入“quit”或“stop”。有没有办法让 systemctl 在关闭程序之前将其中一个命令发送到程序?
答案1
默认情况下,如果您是systemctl stop
一个进程,systemd 会向该进程发送 SIGTERM。该进程负责处理信号并正常关闭。如果进程在 90 秒内没有关闭,SIGKILL 将强制停止该进程。
有多种方法可以更改此默认行为:
ExecStop=
:如果您的进程通常会通过来自套接字、共享内存、触摸文件的外部信号关闭,您可以执行一个脚本,使用 将该信号发送到您的进程ExecStop=
。KillSignal=
:如果您的进程对 SIGTERM 响应不佳,您可以使用 更改发送到进程的信号KillSignal=
。也许您的进程对 SIGINT、SIGABRT 或 SIGQUIT 的响应更好。请注意,此信号应启动程序将执行的保存。TimeoutStopSec=
,默认为 90 秒,给出第一个KillSignal
和之间的时间FinalKillSignal
。我看到您已经将其增加到 300 秒。如果您的保存通常需要比这更长的时间,请增加它。如果这超出了您对保存的预期,那么您的进程可能不会响应您当前的KillSignal=
.SendSIGKILL=
:如果您的进程确实启动了保存,但您想无限期地等待,则可以将其设置no
为让服务永远挂起。 (先玩TimeoutStopSet
)。FinalKillSignal=
:如果您的 Killsignal 效果不佳,并且您想TimeoutStopSet
使用其他内容进行后续操作SIGKILL
,则可以在此处设置该代码。
考虑一下如果您不将其作为服务运行,通常会如何停止该进程。然后效仿一下。你CTRL+D
在终端中使用吗?你kill
有流程吗?
既然你的流程是从 开始的ExecStart=/home/cs16/server/hltv_start.sh
,也许你想要ExecStop=/home/cs16/server/hltv_stop.sh
。
为了正确保存演示,我需要在 htlv 命令工具中输入“quit”或“stop”。
这个命令工具是命令行应用程序吗?如果是这样,也许您只需要:
ExecStop=/home/cs16/server/hltv_command_tool.sh -c stop
如果此工具是 HLTV GUI 的一部分,您可以通过窗口管理器发送文本来发送quit
或文本。stop
以下命令运行bash
shell,然后用于xdotool
搜索hltv
标题中带有 in 的窗口。然后它将quit
在该窗口中输入内容,然后按Enter
:
ExecStop=/bin/bash -c 'xdotool type --window "$(xdotool search hltv | head -1)" quit && xdotool key --window "$(xdotool search hltv | head -1)" Enter'
答案2
它不应该是一项服务
无法在不对其操作造成灾难性损坏的情况下终止的内容不应作为“服务”运行,而应作为每个作业脚本或进程运行。
您所尝试的操作相当于等待互联网停止向您的网站发出请求,然后再允许systemctl stop apache2
其自行完成。
对于本地机器,如果需要关闭机器,无论如何都无法继续写入文件。如果你决定这样做,那么你想 systemctl
无需等待即可结束服务。
也许,您的服务应该运行另一个等待终止的脚本。
该解决方案将在您的产品路线图中,即让开发人员告诉产品经理哪些用户体验是不可能的以及用户应该体验哪些。
我用以下建议回答这个问题,但不知道你的脚本的内容,hltv_start.sh
因为你没有分享它。所以,它一定不是你问题的核心。因此,除了这些头脑风暴之外,我无法具体说明......
考虑:
- 采用脚本化方法来实现 Kdenlive 在 GUI 中的功能,类似于完成渲染后关闭机器的选项。您可以调整脚本来开始写入文件,然后通过以下方式自动关闭您的服务
systemctl stop
后你写完你的文件。 - 创建一个脚本来根据每个作业写入文件,
wait
以便在退出之前完成写入过程。 - 编写一个单独的脚本来
systemctl
结束该进程,作为一种动力移动应该停止进程中间文件。 - 如果您需要涉及服务,请使用它来“监听”或其他内容,而不是实际编写 - 一个调用用于
wait
结束的脚本的服务,如果有必要的话。 - 如果服务仅“侦听”,然后运行另一个使用 写入文件的脚本
wait
,那么理论上您可以systemctl stop
在允许写入操作完成的同时提供服务,我认为这是您的目标。