systemd 服务因错误而终止,因为脚本(预期)返回

systemd 服务因错误而终止,因为脚本(预期)返回

广泛搜索,许多相关问题,但我发现没有一个真正有效。

所以我有一个 shell 脚本,我想通过 systemd 服务实现自动化。剧本:

#!/usr/bin/env bash

SESSION="daemon"
DAEMON_WINDOW="daemon"
CLIENT_WINDOW="client"

tmux new-session -d -s $SESSION
tmux rename-window -t 0 $DAEMON_WINDOW
tmux send-keys -t $DAEMON_WINDOW 'cd $HOME/work/gastd' C-m './gastd' C-m

sleep 30

tmux new-window -t $SESSION:1 -n $CLIENT_WINDOW 
tmux send-keys -t $CLIENT_WINDOW 'gast-client' C-m

tmux attach-session -t $SESSION:1

好的,从 shell 运行时可以正常工作。基本上它在一个窗口中启动守护进程。守护进程会初始化一些东西,所以我必须等待,在睡眠后,我与客户端一起启动第二个窗口。

现在,当我作为 systemd 运行时,它实际上似乎启动正常,然后失败退出。

我认为原因很简单:一切都运行完毕,然后脚本终止,因此 systemd 假设它终止并存在该服务 - 杀死 tmux 会话和窗口,这是真正的问题。

目标是保持会话和窗口永远运行,除非我运行 systemctl stop service。

我可以在脚本末尾添加一个无限循环,但这看起来不太好。

有没有更好的办法?我尝试过,Type=forking但这也没有帮助,最后还因为某种原因崩溃了。

这是我当前的 systemd 脚本:

[Unit]
Description=gast daemon

[Service]
ExecStart=/home/gastuser/start-tmux-session.sh
WorkingDirectory=/home/gastuser/work/gastd
User=gastuser
StandardOutput=file:/home/gastuser/.gast/gast.log
StandardError=file:/home/gastuser/.gast/gast.log
Restart=on-failure

[Install]
WantedBy=multi-user.target

我真的进行了广泛的搜索,如果问题/答案已经存在,抱歉。

答案1

读自文档:

systemd 的简单服务类型如下:

oneshot是一个在短时间内运行完成然后完全退出的服务。

simple是一个在前台运行的程序。因此,systemd 无法确定它何时完成启动并假设它立即启动。

forking适用于启动后台任务的经典双分叉守护进程或进程。假设当原始进程退出时服务已完成启动。当服务的子进程运行时,该服务被视为正在运行。如果 systemd 猜错了,它可以被告知一个 PID 文件来查找子进程。

我认为你拥有的是 asimple或 a forking,但是使用tmux它会把它搞砸。我认为tmux会话名义上由守护进程拥有tmux。因此,systemd 不一定能确定该服务仍在运行并声明其已提前退出。 30 秒的睡眠可能没有帮助,因为它可能会保证您超出forking或之类的默认启动超时oneshot

要解决此问题,您可能需要转换为普通的旧后台任务,&或者找到某种方法来明确告诉 systemd 哪些进程是您的以及启动何时完成。对于分叉任务,这可能可以通过设置 PID 文件然后使用选项告诉 systemd 在哪里找到它来完成PIDFile=。另一种选择是创建一个类型为notifydbus的服务,通知 systemd 它们可以直接通过调用启动sd_notify,也可以通过使用预定义的D-Bus接口名称来启动。即使如此,我也不确定 tmux 会对此做什么。

答案2

尝试:

Type=oneshot

来自男人:

oneshot 的行为与 simple 类似;但是,服务管理器将在主进程退出后考虑该单元。

相关内容