作者:E4b9a6, 创建:2023-12-03, 字数:5321, 已阅:488, 最后更新:2023-12-04
Linux后台运行程序的方法有以下常见的几种
以下实践基于Ubuntu2204
系统,理论上其他Linux发行版也适用
如果命令执行时间稍长且不需要查看输出结果,使用&
作为后台运行标志或在运行之后使用ctrl+z
挂起进程到后台,结合jobs
以及fg
来切换当前会话的后台任务
如果希望命令在会话结束之后保持运行,则需要考虑使用screen
与nohup
,screen
适合运行一些短时任务(如脚本),nohup
则适合运行一些长时任务(如代理程序)
如果对日志记录/权限控制方面有需求,screen
与nohup
就显得不太够用了,这个时候适合使用supervisor
与systemd
等daemon程序创建后台守护进程(Web后台)
以ping
为例,向114.114.114.114发送4个icmp包并记录结果
ping -c 4 114.114.114.114 > 114-ping.txt &
&
符号的效果与运行之后ctrl-z
是类似的,如果不希望记录结果,要随时方便切换回来查看结果,则可以考虑使用ctrl+z
挂起进程到后台
ping 114.114.114.114 # 按ctrl+z挂起
挂起后,使用jobs -l
查看被挂起的后台进程
➜ jobs -l
[1] - 241975 suspended ping 114.114.114.114
使用指令fg %num
可以将后台任务进程重新唤起,可以看到进程重新执行了
➜ fg %1
64 bytes from 114.114.114.114: icmp_seq=3 ttl=117 time=6.19 ms
64 bytes from 114.114.114.114: icmp_seq=4 ttl=117 time=6.37 ms
以上的方法只在当前会话有效,如果会话结束,则程序会结束运行
如果希望程序在会话结束之后继续运行,则可以考虑使用screen
,部分Linux发行版需自行安装该程序
sudo apt install screen
使用screen创建一个ping的会话
screen -R ping
退出会话之后,重新创建会话并再次使用创建ping会话的指令
screen -R ping
可以看到命令依旧在运行
screen
相较于nohup
而言,更适合执行一些脚本,nohup则适合运行长时任务,nohup全称是no hang up
,即不挂起地运行程序,无视系统的Hang Up
信号
在网络上搜索nohup
的使用方法,比较常见的运行方法如下
nohup command > command.log 2>&1 &
这里面比较费解的是2>&1
的含义
在Linux中定义了三种输入输出,分别是
标准输出1
在运行时可以不写,所以执行command > command.log
等价于command 1 > command.log
,在理解到这点后,2>&1
的含义就比较清晰了,表示将错误输出2
重定向到标准输出变量&1
中,再结合>
一起输出到日志中的意思
把命令写全了等价于
nohup command 1> command.log 2>&1 &
注意:nohup command 2>&1 > command.log & 是不正确的写法(感谢leafee98指正),错误输出(2)被重定向到标准输出(1),随后标准输出(1)被重定向到文件,所以错误输出失效了
以nc
程序扫描端口为例,用nuhup执行如下
nohup nc -ztv -w 2 114.114.114.114 1-100 > /tmp/nc.log 2>&1 &
检查/tmp/nc.log
文件,可以看到正在执行
➜ ~ tail -f /tmp/nc.log
nc: connect to 114.114.114.114 port 1 (tcp) timed out: Operation now in progress
nc: connect to 114.114.114.114 port 2 (tcp) timed out: Operation now in progress
...
nohup
用于执行一些简易后台任务效果还是非常不错的,但如果对输出日志切割、运行用户、开机自启等有要求,则需要考虑daemon类程序,如supervisor
与systemd
supervisor
是与systemd
类似的轻量级进程控制系统,用于长时间运行程序,常用于web后台程序、代理程序等,在大部分Linux发行版上需要自行安装,如在ubuntu2204
中安装并启动服务
sudo apt install supervisor
sudo systemctl enable supervisor
sudo systemctl start supervisor
supervisor
相较于nohup
,支持非常丰富的参数设定,环境设定以及守护进程,安装supervisor后,以同步软件syncthing
为例
创建/etc/supervisor/conf.d/syncthing.conf
文件,具体如下
[program:syncthing]
directory=/home/apps/syncthing/syncthing-linux-amd64-v1.19.0
command=/home/apps/syncthing/syncthing-linux-amd64-v1.19.0/syncthing
autostart=true
autorestart=true
startsecs=10
stdout_logfile=/var/log/supervisor/%(program_name)s-stdout.log
stdout_logfile_maxbytes=5MB
stdout_capture_maxbytes=5MB
stdout_logfile_backups=5
stderr_logfile=/var/log/supervisor/%(program_name)s-stderr.log
stderr_logfile_maxbytes=5MB
stderr_capture_maxbytes=5MB
stderr_logfile_backups=5
user = apps
environment = HOME="/home/apps/syncthing/syncthing-linux-amd64-v1.19.0"
大部分参数非常简洁易懂,其中
使新创建的服务生效
sudo supervisorctl update
supervisorctl支持多个操作,如
在2015年后,systemd
是大部分发行版自带用于取代SysV init
的系统套件,在引导过程中提供可靠并行性以及对进程、守护进程、服务和挂载点进行集中管理的程序
如果对现代Linux操作系统熟悉,对systemd
大概率是不会感到陌生的,systemd
是比较重量级的系统套件,除非有明确使用需求,否则一般不考虑作为小应用的后台运行方式,supervisor足够应付绝大部分应用场景了
systemd
常见用户单元配置目录如下(区别于系统单元配置)
还是以同步软件syncthing
为例,添加一个配置文件$HOME/.config/systemd/user/syncthing.service
,内容如下
[Unit]description=Sync Files
Documentation=https://syncthing.net
After=network.target
[Service]
Type=simple
Environment=HOME="/home/apps/syncthing/syncthing-linux-amd64-v1.19.0"
ExecStart=/home/apps/syncthing/syncthing-linux-amd64-v1.19.0/syncthing
# 日志记录需systemd版本 > 240
StandardOutput=append:/home/apps/syncthing/syncthing-linux-amd64-v1.19.0/logs/standard-output.log
StandardError=append:/home/apps/syncthing/syncthing-linux-amd64-v1.19.0/logs/standard-error.log
[Install]
WantedBy=multi-user.target
启动服务
systemctl start syncthing --user
如修改配置单,需要运行刷新systemd
systemctl daemon-reload --user
配置单具体怎么写?可以参考 Systemd入门教程:实战篇 - 阮一峰,以下是对配置文件的重点部分进行说明
[Unit]description= # 程序描述
Documentation= # 参考文档
After= # 服务启动顺序,如network.target表示在network服务启动之后再启动该服务
Before= # 同上,表示在某服务启动之前
Wants= # 服务弱依赖,在启动服务前确保wants所指服务已正常启动
Requires= # 强依赖关系,如果Requires所指服务已停止运行,则本服务也会结束
[Service]
Type= # 服务类型,值类型可为simple/fork/oneshot/dbus/notify/idle
Environment= # 环境变量在此添加
EnvironmentFile= # 环境变量文件(如.bashrc)
ExecStart= # 启动进程时执行的命令
ExecReload= # 重启服务时执行的命令
ExecStop= # 停止服务时执行的命令
ExeStartPre= # 启动进程之前执行的命令
ExeStartPost= # 启动进程之后执行的命令
ExeStopPost= # 停止进程之后执行的命令
Restart= # 定义退出后是否要重启服务,值可为no/on-success/on-failure/on-abnormal/on-abort/onwatchdog/always
RestartSec= # 进程退出之后重启的时间间隔
[Install]
WantedBy= # 表示归属的target,这部分比较复杂,常用的是multi-user.target与graphical.target