在Linux环境下,常常会使用一些脚本,但我们想使其后台长期运行,需要使用Linux的终端命令,使其即使在shell终端关了之后依然执行脚本,并可以将日志重定向到日志文件。本文章将以启动一个本地脚本my_script.sh为例子,介绍三种常用后台启动方法。
1. tmux / screen(推荐用于开发与可视化监控)
tmux / screen 是终端复用器:它创建一个独立于 SSH 会话的会话(session),在该会话中启动的所有进程都与该会话的伪终端(pty)绑定。即使 SSH 断开,tmux 会话仍在后台运行,随后可以重新 attach 回来查看输出或交互。
关键点:进程不依赖于当前 SSH 终端;你可以随时 detach/reattach。
启动命令:
# 新建 session 并进入
tmux new -s new_session
# 在 tmux 里运行(示例)
bash ./my_script.sh > run.log 2>&1
# 按 Ctrl-b d 退出(detach),任务继续运行重连:
tmux ls # 列出 sessions
tmux attach -t new_session # 重新 attach终止会话:
# 在会话里 ctrl-c 或 kill pid;或从外部:
tmux kill-session -t new_session2. setsid 完全脱离会话(推荐用于一次性彻底脱离)
setsid 在 Linux 中用来创建一个新的 session 并使调用进程成为新 session 的 leader。被 setsid 启动的进程 不再属于原来的控制终端,因此终端关闭不会向其发送 SIGHUP(除非另有外力)。配合把 stdin 重定向到 /dev/null 并将 stdout/stderr 重定向到文件,能最大程度保证进程不受终端影响。
关键点:改变 session/pgid,使进程彻底脱离原来终端的进程组和会话。但是无法像 tmux 那样重连查看交互终端(需查看日志文件)。不能防止 SIGTERM/SIGKILL 或外部调度器杀掉进程
启动命令:
# 推荐一行(创建 PID 文件,重定向 stdin)
setsid bash ./my_script.sh > run.log 2>&1 < /dev/null & echo $! > ./my_script.pid终止进程:
kill $(cat ./my_script.pid)
# 若无响应,强杀:
kill -9 $(cat .my_script.pid)注意:
一定要加
< /dev/null避免进程在需要 stdin 时阻塞或在终端关闭时行为异常。若脚本内再 fork 出子进程,确保这些子进程正确 inherit session/pgid(通常正常)。
若程序在内部又自行设置 signal handler 或恢复 SIGHUP,则需要在程序内或 wrapper 脚本中处理。
3. nohup + disown + 重定向 stdin(常用但比 setsid 容易出坑)
nohup 会把进程的 SIGHUP 信号忽略(signal disposition 设为 IGN),并在必要时把 stdout 重定向到 nohup.out。disown(shell 内置)把一个后台作业从 shell 的作业表中移除,防止 shell 退出时再次向作业发送信号。配合 &(后台运行)和重定向 stdin,可实现脱离会话运行。
关键点:
nohup防止 SIGHUP;disown防止 shell 在终止时管理作业;< /dev/null防止 stdin 问题。命令简单、兼容性好(几乎所有 Unix shell 都支持)。适合快速后台化任务。缺点:
对复杂 pipeline 支持差(
nohup cmd | tee只对左侧 cmd 无效,pipe 中其他命令可能被终止)。仍然不能防 SIGTERM/SIGKILL、不能保证子进程行为(比 setsid 更脆弱)。
需要注意把 stdin 重定向并
disown,否则可能失败。
启动命令:
nohup bash ./my_script.sh > run.log 2>&1 < /dev/null & echo $! > ./my_script.pid; disown注意:
使用
&后,用echo $!记录 PID(如上)。如果脚本使用管道(
|),请确认 pipe 中的所有命令都能在无终端下正确运行,或避免管道。nohup会把输出写nohup.out(若没有显式重定向),建议明确重定向到你的日志文件。