后台运行 jobs

Shell 支持作业控制,可以将任务放到后台运行,在前后台之间切换。这对于长时间运行的任务特别有用,可以让终端继续做其他事情。

前台和后台

前台任务:占用终端,运行时无法执行其他命令。

后台任务:在后台运行,不占用终端,可以继续输入命令。

后台运行

& 符号

在命令后加 &,将命令放到后台运行:

./long_task.sh &
sleep 100 &

输出示例:

[1] 12345

[1] 是作业号,12345 是进程 ID。

查看后台任务

jobs 命令查看当前 Shell 的后台任务:

jobs
jobs -l

输出示例:

[1]-  Running     ./long_task.sh &
[2]+  Stopped     vim file.txt

-l 显示进程 ID。

状态说明:

状态含义
Running正在运行
Stopped已暂停
Done已完成

+ 表示最近的任务,- 表示次近的任务。

前后台切换

暂停前台任务

Ctrl+Z 暂停当前前台任务,放入后台:

vim file.txt
# 按 Ctrl+Z
[1]+  Stopped     vim file.txt

恢复到前台

fg 命令将后台任务恢复到前台:

fg
fg %1

%1 指定作业号。

恢复到后台

bg 命令将暂停的任务在后台继续运行:

bg
bg %1

nohup 命令

普通后台任务在终端关闭时会被终止。nohup 可以让任务忽略挂起信号,终端关闭后继续运行:

nohup ./long_task.sh &
nohup ./script.sh > output.log 2>&1 &

默认输出重定向到 nohup.out 文件。

disown 命令

已经运行的后台任务可以用 disown 使其脱离终端:

./task.sh &
disown
disown %1
disown -h %1

-h 使任务忽略 SIGHUP,但仍属于当前 Shell。

查看已 disown 的任务:

jobs -l

disown 后任务不再显示在 jobs 列表中。

wait 命令

wait 等待后台任务完成:

./task1.sh &
./task2.sh &
wait
echo "所有任务完成"

等待特定任务:

./task.sh &
pid=$!
wait $pid
echo "任务 $pid 完成"

$! 是最后一个后台任务的 PID。

进程替代

有时候需要让脚本在后台运行,但又想看到输出:

nohup ./script.sh > output.log 2>&1 &
tail -f output.log

实用示例

后台运行备份任务

nohup tar -czf backup.tar.gz /data > backup.log 2>&1 &

并行执行多个任务

task1.sh &
task2.sh &
task3.sh &
wait
echo "所有任务完成"

管理长时间任务

# 启动任务
./long_script.sh

# Ctrl+Z 暂停
# 放到后台继续运行
bg

# 查看状态
jobs

# 需要时恢复到前台
fg

脱离终端运行

# 方法一:nohup
nohup ./server.sh &

# 方法二:disown
./server.sh &
disown -h %1

# 方法三:setsid
setsid ./server.sh

# 方法四:screen/tmux
screen -dmS server ./server.sh

监控后台任务

while true; do
    jobs -l
    sleep 5
done

screen 和 tmux

screen 和 tmux 是更强大的终端复用工具,可以创建多个虚拟终端,断开后会话保持:

# 创建新会话
screen -S mysession
tmux new -s mysession

# 分离会话
# Ctrl+A D (screen)
# Ctrl+B D (tmux)

# 重新连接
screen -r mysession
tmux attach -t mysession

# 列出会话
screen -ls
tmux ls

小结

  • & 将命令放到后台运行
  • jobs 查看后台任务
  • Ctrl+Z 暂停,fg 恢复到前台,bg 在后台继续
  • nohup 让任务在终端关闭后继续运行
  • disown 使任务脱离当前 Shell
  • wait 等待后台任务完成
  • screen 和 tmux 提供更强大的会话管理