Linux 进程守护与后台运行实战经验:nohup、screen、systemd 与 Supervisor

在 Linux 服务器上跑程序,最烦的就是终端一关程序就停了。这篇记录一下常用的几种后台运行方案,从最简单的 nohup 到生产环境用的 Supervisor

问题场景分析

为什么终端关闭会终止程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌─────────────────────────────────────────────────────────────┐
│ 终端关闭导致进程终止的原理 │
├─────────────────────────────────────────────────────────────┤

│ 登录终端
│ │
│ ▼
│ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ │ bash │────►│ 子进程 │────►│ 程序 │
│ │ (shell)│ │ (sh/php)│ │(node) │
│ └────┬────┘ └─────────┘ └────┬────┘
│ │ │
│ │ SIGHUP 信号 │
│ │ 终端挂起时发送 │
│ ▼ ▼
│ 用户关闭终端 ──────────────────────► 子进程收到 SIGHUP
│ │ │
│ │ │ 默认行为:终止进程
│ │ ▼
│ └────────────────────────────► 程序退出

│ 解决方案:让程序忽略 SIGHUP 信号

当终端(TTY)关闭时,操作系统会向该终端下运行的所有进程发送 SIGHUP(挂起信号,Signal Hang Up)。默认情况下,进程收到此信号后会终止执行。

方案一:nohup 命令

基本用法

nohup(no hang up)是最简单、最常用的后台运行方案,它会让程序忽略 SIGHUP 信号。

1
2
3
4
5
6
7
8
9
10
11
# 基本用法:在后台运行程序
nohup ./your_program &

# 示例:运行 Node.js 服务
nohup node server.js &

# 示例:运行 Python 脚本
nohup python3 script.py &

# 输出重定向到指定文件
nohup ./your_program > output.log 2>&1 &

输出重定向详解

命令 作用
nohup command & 标准输出重定向到 nohup.out
nohup command > app.log & 输出到 app.log,错误丢弃
nohup command > app.log 2>&1 & 标准输出和错误都写入 app.log
nohup command > /dev/null 2>&1 & 完全丢弃所有输出

常用操作

1
2
3
4
5
6
7
8
# 查看 nohup 运行的进程
ps aux | grep node

# 终止后台进程
kill -9 PID

# 查看 nohup.out 实时输出
tail -f nohup.out

优缺点

优点 缺点
使用简单,无需额外安装 程序崩溃后不会自动重启
几乎所有 Linux 系统自带 无进程监控功能
适合临时运行任务 重启服务器后需手动重新启动

方案二:disown 与作业控制

disown 命令

如果已经在终端启动了程序但忘记使用 nohup,可以使用 disown 将作业从 shell 的作业表中移除,使其不受 SIGHUP 影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动程序(在前台或后台)
./long_running_task &

# 查看作业列表
jobs -l

# 将最近一个作业从 shell 作业表中移除
disown

# 移除指定作业号
disown %1

# 移除所有作业
disown -a

setsid 命令

setsid 会创建一个新的会话(session),使进程成为新会话的领头进程,从而完全脱离当前终端。

1
2
3
4
5
# 使用 setsid 启动程序
setsid ./your_program

# 程序会立即在后台运行,无需 & 符号
# 输出不会被重定向,需要注意日志处理

三种方案对比

方案 脱离终端 自动重启 使用场景
nohup 简单后台任务
disown 已启动程序的补救
setsid 是(完全) 需要完全脱离终端

方案三:screen / tmux 终端复用

screen 工具

screen 是一个终端复用器,可以在一个物理终端上创建多个虚拟终端,即使网络断开,会话中的程序也会继续运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 安装 screen
sudo apt-get install screen # Debian/Ubuntu
sudo yum install screen # CentOS/RHEL

# 创建新会话
creen -S mysession

# 在会话中运行程序
node server.js

# detached 模式(按 Ctrl+A,然后按 D)
# 程序继续在后台运行

# 列出所有会话
screen -ls

# 重新连接到会话
screen -r mysession

# 如果会话被其他终端占用,强制连接
screen -rD mysession

# 终止会话
# 在会话中按 Ctrl+D 或输入 exit

tmux 工具(推荐)

tmuxscreen 的现代化替代品,功能更强大,界面更友好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 安装 tmux
sudo apt-get install tmux

# 创建新会话
tmux new -s myapp

# 常用快捷键
# Ctrl+B D - detached(分离会话)
# Ctrl+B C - 创建新窗口
# Ctrl+B N - 切换到下一个窗口
# Ctrl+B P - 切换到上一个窗口
# Ctrl+B % - 垂直分割窗格
# Ctrl+B " - 水平分割窗格

# 列出会话
tmux ls

# 连接会话
tmux attach -t myapp

# 终止会话
tmux kill-session -t myapp

screen vs tmux

特性 screen tmux
默认快捷键 Ctrl+A Ctrl+B
窗口分割 较弱 强大
配置灵活性 一般 高(支持主题、插件)
脚本化 支持 更完善
社区活跃度 稳定 活跃

方案四:Supervisor 进程管理

什么是 Supervisor

Supervisor 是一个用 Python 编写的客户端/服务器系统,用于控制和监控类 Unix 操作系统上的进程。它是生产环境中最常用的进程管理工具之一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌─────────────────────────────────────────────────────────────┐
│ Supervisor 架构 │
├─────────────────────────────────────────────────────────────┤

│ ┌──────────────┐ ┌──────────────┐
│ │ supervisord │◄────────│ supervisorctl│
│ │ (服务端) │ Unix │ (客户端) │
│ │ │ Socket │ │
│ └──────┬───────┘ └──────────────┘
│ │
│ │ 监控和管理
│ ▼
│ ┌──────────────────────────────────────────────────────┐
│ │ 被管理的进程组 │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ │ Node.js│ │ Python │ │ Redis │ │ Nginx │ │
│ │ │ Server │ │ Worker │ │ Server │ │ Proxy │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │
│ └──────────────────────────────────────────────────────┘

│ 核心功能:
│ • 自动启动进程
│ • 进程崩溃自动重启
│ • 日志轮转
│ • 进程组管理
│ • Web 界面监控(可选)

安装 Supervisor

1
2
3
4
5
6
7
8
9
# Debian/Ubuntu
sudo apt-get install supervisor

# CentOS/RHEL
sudo yum install supervisor

# 启动服务
sudo systemctl start supervisor
sudo systemctl enable supervisor

配置文件

Supervisor 的主配置文件位于 /etc/supervisor/supervisord.conf(Debian/Ubuntu)或 /etc/supervisord.conf(CentOS)。

/etc/supervisor/conf.d/ 目录下创建应用配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
; /etc/supervisor/conf.d/node-app.conf
[program:node-app]
; 程序启动命令
command=/usr/bin/node /var/www/app/server.js

; 进程运行目录
directory=/var/www/app

; 自动启动
autostart=true

; 程序崩溃后自动重启
autorestart=true

; 启动失败后重试次数
startretries=3

; 启动等待时间(秒)
startsecs=5

; 运行用户
user=www-data

; 环境变量
environment=NODE_ENV="production",PORT="3000"

; 日志配置
stdout_logfile=/var/log/supervisor/node-app.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
stderr_logfile=/var/log/supervisor/node-app-error.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=5

; 进程数量(如需多个实例)
numprocs=1

; 进程名称
process_name=%(program_name)s

常用管理命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 重新加载配置
sudo supervisorctl reread
sudo supervisorctl update

# 启动、停止、重启进程
sudo supervisorctl start node-app
sudo supervisorctl stop node-app
sudo supervisorctl restart node-app

# 查看所有进程状态
sudo supervisorctl status

# 查看进程日志
sudo supervisorctl tail -f node-app

# 停止所有进程
sudo supervisorctl stop all

进程组配置

当有多个相关联的进程需要一起管理时,可以使用进程组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
; /etc/supervisor/conf.d/my-project.conf
[program:myproject-worker]
command=/usr/bin/python3 /var/www/project/worker.py
autostart=true
autorestart=true
user=www-data
stdout_logfile=/var/log/supervisor/worker.log

[program:myproject-scheduler]
command=/usr/bin/python3 /var/www/project/scheduler.py
autostart=true
autorestart=true
user=www-data
stdout_logfile=/var/log/supervisor/scheduler.log

[group:myproject]
programs=myproject-worker,myproject-scheduler
priority=999

管理进程组:

1
2
# 重启整个组
sudo supervisorctl restart myproject:*

方案五:systemd 服务管理

创建 systemd 服务

对于现代 Linux 发行版(CentOS 7+、Ubuntu 16.04+、Debian 8+),systemd 是系统和服务管理器,也是配置后台服务的标准方式。

创建服务文件 /etc/systemd/system/myapp.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Unit]
Description=My Node.js Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/app
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=10
Environment=NODE_ENV=production PORT=3000

# 日志输出
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp

[Install]
WantedBy=multi-user.target

管理服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start myapp

# 停止服务
sudo systemctl stop myapp

# 重启服务
sudo systemctl restart myapp

# 查看状态
sudo systemctl status myapp

# 设置开机自启
sudo systemctl enable myapp

# 禁用开机自启
sudo systemctl disable myapp

# 查看日志
sudo journalctl -u myapp -f

systemd vs Supervisor

特性 systemd Supervisor
系统集成度 高(系统级) 中(应用级)
配置复杂度 较复杂 简单
日志管理 journalctl 内置轮转
Web 界面 有(需配置)
适用场景 系统服务 应用进程
跨发行版一致性 现代系统通用 完全一致

方案选择决策树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────────────────────────┐
│ Linux 后台运行方案选择指南 │
├─────────────────────────────────────────────────────────────┤

│ 是临时运行还是长期服务?

│ 临时 ────────► nohup / screen / tmux
│ │
│ 长期
│ │
│ ▼
│ 需要自动重启吗?

│ 不需要 ──────► nohup + cron 检查
│ │
│ 需要
│ │
│ ▼
│ 单应用还是多进程管理?

│ 单应用 ──────► systemd(现代系统)
│ │ Supervisor(跨平台兼容)
│ │
│ 多进程 ──────► Supervisor(推荐)
│ PM2(Node.js 专用)

最佳实践建议

1. 日志管理

无论使用哪种方案,都应确保日志不会无限增长:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 使用 logrotate 轮转日志
cat > /etc/logrotate.d/myapp << 'EOF'
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0644 www-data www-data
sharedscripts
postrotate
/usr/bin/supervisorctl restart myapp > /dev/null 2>&1
endscript
}
EOF

2. 健康检查

在程序中实现健康检查端点,配合外部监控:

1
2
# cron 定时检查(每分钟)
* * * * * /usr/bin/curl -f http://localhost:3000/health || /usr/bin/systemctl restart myapp

3. 环境变量管理

避免在配置文件中硬编码敏感信息:

1
2
3
[Service]
# 从环境文件加载
EnvironmentFile=/etc/myapp/environment
1
2
3
# /etc/myapp/environment
DATABASE_URL=postgres://user:pass@localhost/db
SECRET_KEY=your-secret-key

写在最后

Linux 进程守护方案对比:

方案 复杂度 可靠性 监控能力 推荐场景
nohup 临时任务、开发测试
screen/tmux 交互式会话、手动操作
Supervisor 生产环境应用进程
systemd 系统服务、现代 Linux

对于生产环境,推荐使用 Supervisorsystemd 进行进程管理,它们提供了自动重启、日志轮转、进程组管理等核心功能,确保服务的高可用性。