Appearance
作业控制
作业控制(Job Control)允许用户在一个终端中管理多个进程,在前台和后台之间切换。
基本概念
- 前台作业:独占终端,用户需等待其完成才能继续输入
- 后台作业:在后台运行,不独占终端,用户可以继续操作
- 作业编号:Shell 为每个后台作业分配的编号(如
[1])
后台运行
bash
# 在命令末尾加 & 使其在后台运行
sleep 60 &
# 输出:[1] 12345 ([作业编号] PID)
# 后台运行并忽略输出
sleep 60 > /dev/null 2>&1 &
# 获取最后一个后台进程的 PID
echo "后台进程 PID: $!"查看作业
bash
# 列出当前 Shell 的所有作业
jobs
# 显示 PID
jobs -l
# 只显示运行中的作业
jobs -r
# 只显示已停止的作业
jobs -s输出示例:
[1] Running sleep 60 &
[2]- Stopped vim file.txt
[3]+ Running ping google.com > /dev/null &+表示最近的作业(fg/bg 默认操作对象)-表示倒数第二个作业
前台与后台切换
bash
# 挂起前台进程(Ctrl+Z)
# 按下 Ctrl+Z 将当前前台进程暂停并放入后台
# 将挂起的作业放到后台继续运行
bg # 操作最近的作业
bg %1 # 操作编号为 1 的作业
# 将后台作业调到前台
fg # 操作最近的作业(带 + 号的)
fg %1 # 操作编号为 1 的作业
fg %2 # 操作编号为 2 的作业作业编号引用
bash
%n # 作业编号 n
%+ # 最近的作业
%- # 倒数第二个作业
%string # 命令以 string 开头的作业
%?string # 命令包含 string 的作业bash
# 示例
sleep 100 & # [1] 12345
sleep 200 & # [2] 12346
vim file.txt # 按 Ctrl+Z 挂起 → [3] 12347
jobs -l
# [1] 12345 Running sleep 100 &
# [2]- 12346 Running sleep 200 &
# [3]+ 12347 Stopped vim file.txt
fg %vim # 恢复 vim
kill %1 # 终止作业 1终止作业
bash
# 通过作业编号发送信号
kill %1 # 发送 SIGTERM
kill -9 %2 # 发送 SIGKILL
# 等待特定作业完成
wait %1
wait # 等待所有后台作业完成nohup — 忽略挂起信号
退出终端时,Shell 会向所有作业发送 SIGHUP,导致后台进程也退出。使用 nohup 可以防止这种情况:
bash
# 使用 nohup 运行,退出终端后进程继续运行
nohup ./long_script.sh &
# 输出默认写入 nohup.out
nohup ./long_script.sh > mylog.txt 2>&1 &
# 查看 nohup 进程
ps aux | grep long_scriptdisown — 从 Shell 作业表中移除
bash
# 先将进程放入后台
sleep 1000 & # [1] 12345
# 从作业表中移除(不再受 SIGHUP 影响)
disown %1
# 移除所有作业
disown -a
# 移除并抑制 SIGHUP
disown -h %1实用场景
并行执行多个任务
bash
#!/bin/bash
# 并行执行,等待全部完成
task1() { sleep 3; echo "任务1完成"; }
task2() { sleep 2; echo "任务2完成"; }
task3() { sleep 4; echo "任务3完成"; }
task1 &
task2 &
task3 &
wait # 等待所有后台任务完成
echo "全部任务完成"带超时的后台任务
bash
#!/bin/bash
run_with_timeout() {
local timeout=$1
local cmd="${@:2}"
$cmd &
local pid=$!
sleep "$timeout" &
local sleep_pid=$!
# 等待任意一个完成
wait -n 2>/dev/null
if kill -0 "$pid" 2>/dev/null; then
echo "超时,终止进程 $pid"
kill "$pid"
fi
kill "$sleep_pid" 2>/dev/null
wait
}
run_with_timeout 5 sleep 100