我有一个应用程序(操作系统是 Ubuntu 16.04),它基本上打开相机对视频流执行一些操作。它由 systemd 服务管理:
[Unit]
Description=My Application
After=network.target
StartLimitInterval=0
[Service]
Type=simple
Restart=always
RestartSec=5
User=myuser
WorkingDirectory=/opt/foo/
ExecStart=/opt/foo/myapplication
[Install]
WantedBy=multi-user.target
然后我有一个桌面条目,可以停止服务并使用参数重新运行我的应用程序:
[Desktop Entry]
Name=Myapp
Type=Application
Exec=/opt/foo/launcher.sh
Terminal=true
Path=/opt/foo/
Categories=None;
这是我的启动器:
#!/bin/bash
service myservice stop
/opt/foo/myapplication --debug
这是有效的,无论如何,当我关闭桌面条目启动的应用程序时,我找不到重新启动服务的方法。我尝试在启动器末尾添加服务重新启动,但它不起作用,因为当我关闭运行应用程序的终端时,我认为的所有内容都会被终止。我该怎么做?
答案1
您可以编写一个单元文件,例如/etc/systemd/system/myprocess.service
:
[Unit]
Description=My Process
[Service]
ExecStart=/bin/myprocess
Restart=always
[Install]
WantedBy=multi-user.target
然后在桌面入口创建一个启动器来做
systemctl start myprocess.service
但请记住不要在启动时启用该服务,以便您可以从可执行条目手动启动它。
编辑:
如果您还需要在调试模式下运行,则需要使用该--debug
参数创建另一个服务单元。您可以创建另一个桌面条目来指向看起来像的脚本(只是代表性的想法)
systemctl stop myprocess.service // to stop previous service
systemctl start processwithdebug.servce // to debug
答案2
你可以让 systemd 为你用第二个单元 B 做一些工作,方法是说它Conflicts
用第一个单元 A;那么当你启动B时,它就会停止A。遗憾的是,当B停止时,A默认不会重新启动,但你可以添加一行OnFailure
;如果 B 失败退出,A 将启动。为了确保 B 正常退出时失败,您可以使用ExecStop
将返回代码设置为非零。
A、服务:
[Service]
Type=simple
ExecStart=/opt/foo/myapplication
B、服务:
[Unit]
Conflicts=A.service
OnFailure=A.service
[Service]
Type=simple
ExecStart=/opt/foo/myapplication --debug
ExecStop=/usr/bin/false
答案3
您可以使用锁定文件来确保应用程序只有一个实例运行。不要systemctl stop myservice
在启动器中运行systemctl restart myservice
,并在需要重新启动应用程序的 5 秒内,在获取锁定文件后启动调试版本:
systemctl restart myservice
flock /opt/foo/mylock /opt/foo/myapplication --debug
并更改单元文件以使用相同的锁:
ExecStart=/usr/bin/flock /opt/foo/mylock /opt/foo/myapplication
它将在 5 秒后重新启动,然后等待获取锁,并在运行应用程序时保持它。锁定文件可以位于任何地方。您实际上可以用作/opt/foo/myapplication
锁定文件,但如果您重新编译它或其他内容,当它发生更改时您将失去锁定。