加 & 只是临时后台,不脱离终端;nohup 是轻量可靠的真后台;screen/tmux 适合需交互的长期任务;systemd 用户服务适合开机自启与自动恢复。

直接加 & 只是“后台”,不是“持久后台”
加 & 是最快速的后台启动方式,但它只把进程放到当前 shell 的后台作业队列里,不脱离终端控制。一旦你退出 SSH 或关闭终端,shell 会向所有子进程发送 SIGHUP,该进程大概率被终止。
常见错误现象:明明写了 python app.py &,一关终端就没了;jobs 能看到任务,但 ps 查不到对应进程了。
- 适合场景:临时、短时、你人还在终端里继续操作的命令(比如
tail -f /var/log/syslog &) - 输出默认仍打到终端,可能刷屏或报错看不见 —— 建议始终搭配重定向:
python script.py > log.txt 2>&1 & - 别依赖
disown补救:虽然disown %1能剥离作业,但它不保证进程免受 SIGHUP,尤其在某些 shell 或 systemd 环境下行为不一致
nohup 是最轻量可靠的“真后台”方案
nohup 的核心作用就是忽略 SIGHUP,配合 & 启动后,进程能真正活过终端断开。它默认把 stdout/stderr 追加写入 nohup.out,这点很关键。
容易踩的坑:
- 没写重定向时,
nohup会尝试写当前目录下的nohup.out;如果目录不可写(比如权限不足、磁盘满、挂载为只读),命令直接失败,且不报错提示 —— 用strace nohup ...才能看到 open() 失败 -
2>&1必须写在重定向文件之后,顺序不能错:nohup cmd > out.log 2>&1 &✅,nohup cmd 2>&1 > out.log &❌(stderr 仍打屏) - Python 脚本建议加
-u参数:nohup python -u script.py > log.txt 2>&1 &,避免输出缓冲导致日志延迟或丢失
screen/tmux 适合需要交互或中途查看输出的长期任务
当你不只是“扔进去跑完”,而是可能要中途 attach 进去看日志、按 Ctrl+C 中断、或调试输出,screen 和 tmux 比 nohup 更合适。它们创建的是独立会话,完全脱离原始终端生命周期。
关键区别:
-
screen -S name启动后,必须按Ctrl+A再按D才算“分离”(detach);直接关终端只是断连,会话仍在后台运行 -
tmux new-session -d -s mytask的-d参数可直接后台启动,无需交互 —— 适合脚本调用 - 恢复时:
screen -r name或tmux attach-session -t name;如果提示 “There is a screen on …”,说明已有会话存在,用screen -D -r name强制接管 - 注意:
screen在某些最小化系统(如 Alpine)默认不装,tmux依赖 ncurses,两者都不是“开箱即用”
systemd 用户服务适合开机自启和自动恢复
如果你的程序要长期稳定跑,比如 Web 服务、数据采集脚本、定时轮询器,systemd --user 是唯一能自动重启、记录 journal 日志、设置资源限制的方案。它不依赖你是否登录,只要用户 session 启动就生效。
实操要点:
- 服务文件必须放在
~/.config/systemd/user/下,且文件名以.service结尾(如myapp.service) -
Type=推荐用simple(启动即认为成功)或forking(适用于 daemon 自己 fork 并退出父进程);别乱设Type=notify,除非程序真的实现了 sd_notify() - 启用前必须执行:
systemctl --user daemon-reload,否则新 service 不会被识别 - 启动后查状态:
systemctl --user status myapp.service;看日志:journalctl --user -u myapp.service -f
复杂点在于环境变量继承 —— systemd 用户服务默认没有 $PATH 或 shell profile 里的变量,务必在 service 文件中显式写 Environment=PATH=/usr/bin:/bin 或用 ExecStart=/bin/bash -c '...' 包一层。











