Linux 后台任务详解:&、nohup、jobs、systemd 的区别
1. 前言
在 Linux 中,我们经常需要让程序在后台运行。
常见场景:
- 后台执行脚本;
- 退出 SSH 后程序继续运行;
- 让服务开机自启;
- 查看后台任务;
- 把程序做成系统服务。
常见工具有:
bash
&
nohup
jobs
fg
bg
systemd
本文重点讲清楚它们的区别和使用场景。
2. 前台任务和后台任务
默认运行命令时,任务在前台执行。
bash
sleep 100
此时终端会被占用。
命令结束前,不能继续输入其他命令。
如果想后台执行,在命令后加 &:
bash
sleep 100 &
输出类似:
text
[1] 12345
含义:
| 内容 | 含义 |
|---|---|
[1] |
当前 shell 中的任务编号 |
12345 |
进程 PID |
3. jobs:查看当前 shell 的后台任务
查看后台任务:
bash
jobs
示例:
bash
[1]+ Running sleep 100 &
注意:
text
jobs 只能查看当前 shell 管理的任务。
如果重新打开一个终端,原来终端里的 jobs 不会显示在新终端中。
4. fg 和 bg
把后台任务切回前台:
bash
fg %1
暂停前台任务:
text
Ctrl+Z
暂停后查看:
bash
jobs
可能看到:
bash
[1]+ Stopped python app.py
让暂停任务继续在后台运行:
bash
bg %1
这一套适合临时控制任务。
5. & 的局限
使用:
bash
python app.py &
程序会进入后台。
但是如果关闭终端,程序可能退出。
原因是它仍然和当前终端会话有关。
终端关闭时,系统可能向进程发送 SIGHUP 信号。
所以:
text
& 适合临时后台运行,不适合长期服务。
6. nohup:退出终端后继续运行
nohup 的作用是让程序忽略挂起信号。
常见写法:
bash
nohup python app.py > app.log 2>&1 &
拆开理解:
| 部分 | 含义 |
|---|---|
nohup |
忽略 SIGHUP |
python app.py |
要运行的程序 |
> app.log |
标准输出写入日志 |
2>&1 |
标准错误也写入日志 |
& |
后台运行 |
查看日志:
bash
tail -f app.log
如果不指定日志文件,默认可能写入:
bash
nohup.out
7. 2>&1 是什么
Linux 中有三个常见文件描述符:
| 编号 | 含义 |
|---|---|
| 0 | 标准输入 |
| 1 | 标准输出 |
| 2 | 标准错误 |
命令:
bash
> app.log
等价于:
bash
1> app.log
只重定向标准输出。
如果还想把错误输出也写进同一个文件:
bash
> app.log 2>&1
所以完整后台运行常写成:
bash
nohup command > app.log 2>&1 &
8. disown:脱离当前 shell
如果已经用 & 启动任务:
bash
python app.py &
可以用:
bash
jobs
disown %1
让任务脱离当前 shell 作业管理。
但实际项目中,更建议直接用 nohup 或 systemd。
9. systemd:正式服务管理
systemd 是现代 Linux 常用的系统服务管理器。
它适合管理长期运行的服务。
常见命令:
bash
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl status nginx
systemctl enable nginx
systemctl disable nginx
| 命令 | 作用 |
|---|---|
| start | 启动 |
| stop | 停止 |
| restart | 重启 |
| status | 查看状态 |
| enable | 开机自启 |
| disable | 取消开机自启 |
10. 创建 systemd 服务
假设程序路径:
bash
/opt/myapp/app
创建服务文件:
bash
sudo vim /etc/systemd/system/myapp.service
内容:
ini
[Unit]
Description=My App Service
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/app
Restart=always
RestartSec=3
User=www-data
Group=www-data
[Install]
WantedBy=multi-user.target
重新加载配置:
bash
sudo systemctl daemon-reload
启动服务:
bash
sudo systemctl start myapp
查看状态:
bash
sudo systemctl status myapp
设置开机自启:
bash
sudo systemctl enable myapp
查看日志:
bash
journalctl -u myapp -f
11. &、nohup、systemd 对比
| 方式 | 适合场景 | 退出终端是否稳定 | 是否支持开机自启 | 是否方便管理 |
|---|---|---|---|---|
& |
临时后台任务 | 不稳定 | 不支持 | 一般 |
nohup + & |
长时间脚本 | 较稳定 | 不支持 | 一般 |
tmux/screen |
交互式会话 | 稳定 | 不支持 | 适合调试 |
systemd |
正式服务 | 稳定 | 支持 | 很方便 |
选择建议:
text
临时跑一下:&
退出终端继续跑:nohup
需要交互会话:tmux/screen
正式服务部署:systemd
12. 常见问题
12.1 nohup 启动后马上退出
先看日志:
bash
cat app.log
cat nohup.out
常见原因:
- 工作目录不对;
- 配置文件路径错误;
- 端口被占用;
- 环境变量缺失;
- 程序启动时报错。
12.2 systemd 手动运行正常,服务运行失败
常见原因是 systemd 环境变量较少,不会自动加载用户的 .bashrc。
解决思路:
- 使用绝对路径;
- 配置
WorkingDirectory; - 配置
Environment; - 指定正确
User; - 用
journalctl -u 服务名看日志。
示例:
ini
Environment=JAVA_HOME=/usr/lib/jvm/java-17
Environment=PATH=/usr/local/bin:/usr/bin:/bin
13. 小结
Linux 后台任务可以这样记:
text
&:放到当前 shell 后台
jobs:看当前 shell 的任务
fg/bg:前后台切换
nohup:退出终端继续运行
systemd:正式服务管理
常用命令:
bash
command &
jobs
fg %1
bg %1
nohup command > app.log 2>&1 &
systemctl status myapp
journalctl -u myapp -f
如果只是临时执行脚本,用 nohup 就够。
如果是线上服务,建议写成 systemd 服务。