我经常想做的一件事是以我自己的非特权用户身份启动一些长时间运行的进程或服务器,然后有办法判断它是否仍在运行,如果没有则重新启动它。
例如,我可能会设置一个 cron 作业,该作业经常运行,检查我的进程是否正在运行,如果崩溃则重新启动它。这是 djb 的 daemontools、supervisord、launchd 等进程管理工具的本质,除了这些工具默认配置为以 root 身份运行并带有配置文件,/etc
但我想要一个实用程序,可以让我做与我的程序相同的事情来自我的主目录的非特权用户。
答案1
使用系统:
1.创建服务单元配置文件
~/.config/systemd/user/<service_name>.service
[Unit]
Description=<Write some description here>
[Service]
ExecStart=<Write some command here>
Restart=always
[Install]
WantedBy=graphical.target
看man systemd.service
和man systemd.unit
以获得更多选择。
2. 在用户空间启用服务
$ systemctl --user enable <service_name>
3.立即启动并检查其状态
$ systemctl --user start <service_name>
$ systemctl --user status <service_name>
4.确保它自动启动
现在您可以重新加载PC并登录图形环境,然后再次检查服务状态。
5.享受吧!
答案2
deamontools
你提到作为用户工作得很好。看https://cr.yp.to/daemontools/supervise.html
更新-解决方案
根据上述建议,OPsvscan
在尝试了两种不同的方法后使用该程序实现了此工作daemontools
:
- 像这样将其放入现代 crontab 中:
@reboot /usr/bin/svscan $HOME/.local/service 2>&1 > $HOME/.local/service/log
将
~/.config/autostart/svscan.desktop
行设置为使用包装器脚本Exec=...
启动。svscan
我的包装脚本如下所示:#!/usr/bin/env sh ( echo "Starting svscan." date /usr/bin/svscan $HOME/.local/service 2>&1 ) >> $HOME/.local/service/log
两种方法都有效,但每种方法适用于不同的情况。如果您在无头计算机上执行此操作,并且希望允许非特权用户安装自己的长时间运行的服务和进程,则第一种方法很好。如果您希望所有服务继承当前登录的 X 用户的环境、ssh-agent 等,则第二种方法很好,这意味着进程有效地成为当前登录用户本身的代理。
答案3
如果您的服务器运行 systemd,您可以使用systemd --user start myservice
.服务文件必须放置在~/.config/systemd/user/
.
如果您配置Restart
该服务的选项,systemd 将在该服务退出时自动重新启动该服务(使用不同的配置选项)。
另一个独立于 systemd 的选项可能会启动screen
。您可以通过调用 来检查屏幕会话是否存在screen -list
,并在必要时启动(分离)。您可以使用 .“远程”在屏幕中执行命令screen -S "$screen_session" -X stuff 'command\n'
。然后,您只需在该屏幕会话的后台启动该程序,并记住变量中的 PID。
cron 作业使用 screen 的stuff
命令来检查进程是否仍在运行,否则重新启动。
答案4
在 Debian 系统上你可以使用start-stop-daemon
与 init 脚本使用的方式类似。对于守护进程(双分叉)和保存 PID,不需要额外的权限(但是,如果您尝试使用任何需要它们的选项,以非特权用户身份运行程序将会失败)。
要开始长时间运行的流程:
/sbin/start-stop-daemon --start --pidfile /path/to/pidfile --make-pidfile \
--background --exec /path/to/executable -- options
检查状态:
/sbin/start-stop-daemon --status --pidfile /path/to/pidfile
停止进程:
/sbin/start-stop-daemon --stop --pidfile /path/to/pidfile