Linux bg 命令详解与示例

bg(background)命令用于将挂起的作业放到后台继续运行。它是作业控制(job control)的重要命令之一。

基本概念

作业状态

# 前台作业 (Foreground job)
command           # 在前台运行,占用终端

# 后台作业 (Background job)
command &         # 直接在后台运行

# 挂起作业 (Suspended job)
Ctrl + Z          # 暂停当前前台作业,变为挂起状态

基本语法

bg [作业号]      # 将指定作业放到后台运行
bg              # 将当前作业(最近挂起的)放到后台

基础示例

示例1:基本使用流程

# 1. 启动一个长时间运行的前台作业
$ sleep 100
# 现在终端被占用

# 2. 按 Ctrl+Z 暂停这个作业
^Z
[1]+  Stopped                 sleep 100

# 3. 查看作业状态
$ jobs
[1]+  Stopped                 sleep 100

# 4. 放到后台继续运行
$ bg %1
[1]+ sleep 100 &

# 或简写
$ bg
[1]+ sleep 100 &

# 5. 验证作业在后台运行
$ jobs
[1]+  Running                 sleep 100 &

示例2:多个作业管理

# 启动多个作业
$ sleep 200
^Z
[1]+  Stopped                 sleep 200

$ sleep 300
^Z
[2]+  Stopped                 sleep 300

$ sleep 400
^Z
[3]+  Stopped                 sleep 400

# 查看所有作业
$ jobs
[1]   Stopped                 sleep 200
[2]-  Stopped                 sleep 300
[3]+  Stopped                 sleep 400
# + 表示最近访问的作业,- 表示次近的作业

# 将作业2放到后台
$ bg %2
[2]- sleep 300 &

# 将最近挂起的作业(作业3)放到后台
$ bg
[3]+ sleep 400 &

# 查看状态
$ jobs
[1]   Stopped                 sleep 200
[2]-  Running                 sleep 300 &
[3]+  Running                 sleep 400 &

作业标识符

引用作业的方式

# 1. 使用作业号
bg %1        # 作业号1
bg %2        # 作业号2

# 2. 使用特殊符号
bg %%        # 当前作业(最近挂起的)
bg %+        # 同上,当前作业
bg %-        # 上一个作业

# 3. 使用命令前缀
bg %sleep    # 以'sleep'开头的作业
bg %?sleep   # 包含'sleep'的作业

# 4. 使用进程ID
$ jobs -l
[1]+ 12345 Stopped                 sleep 100

bg %1       # 使用作业号
# 不能直接用进程ID:bg 12345 ❌

实际应用场景

场景1:编译大型项目

# 1. 开始编译(可能耗时很长)
$ make all
# 编译进行中...

# 2. 突然需要执行其他命令
Ctrl+Z
[1]+  Stopped                 make all

# 3. 放到后台继续编译
$ bg
[1]+ make all &

# 4. 现在可以继续使用终端
$ ls
$ git status
# ... 其他操作

# 5. 查看编译进度
$ jobs
[1]+  Running                 make all &

# 6. 需要时带回前台
$ fg %1

场景2:下载文件时操作终端

# 1. 开始下载大文件
$ wget http://example.com/large-file.iso
# 正在下载...

# 2. 需要临时检查系统状态
Ctrl+Z
[1]+  Stopped                 wget http://example.com/large-file.iso

# 3. 将下载放到后台
$ bg
[1]+ wget http://example.com/large-file.iso &

# 4. 检查系统
$ df -h        # 检查磁盘空间
$ free -h      # 检查内存

# 5. 恢复下载到前台查看进度
$ fg
wget http://example.com/large-file.iso
# 可以看到下载进度,再次按 Ctrl+Z 可暂停

场景3:数据库备份

# 1. 开始数据库备份
$ mysqldump -u root -p database > backup.sql
Enter password: ****
# 备份进行中...

# 2. 需要紧急处理其他事情
Ctrl+Z
[1]+  Stopped                 mysqldump -u root -p database > backup.sql

# 3. 备份放到后台继续
$ bg
[1]+ mysqldump -u root -p database > backup.sql &

# 4. 处理紧急任务
$ systemctl status important-service
$ tail -f /var/log/important.log

# 5. 监控备份进度
$ ls -lh backup.sql  # 查看文件大小增长
$ jobs               # 查看作业状态

高级用法

结合 nohup 使用

# 启动一个后台作业,即使关闭终端也继续运行
$ nohup some_long_command &
# 或
$ some_long_command
Ctrl+Z
$ bg
$ disown  # 将作业从作业表中移除,使其在终端关闭后仍运行

管道命令的作业控制

# 1. 启动一个管道命令
$ find / -name "*.conf" 2>/dev/null | grep "network" | tee output.txt
# 命令执行中...

# 2. 暂停整个管道
Ctrl+Z
[1]+  Stopped                 find / -name "*.conf" 2>/dev/null | grep "network" | tee output.txt

# 3. 后台继续
$ bg
[1]+ find / -name "*.conf" 2>/dev/null | grep "network" | tee output.txt &

# 4. 监控输出
$ tail -f output.txt

脚本中的作业控制

#!/bin/bash
# script_with_jobs.sh

echo "Starting task 1..."
sleep 30 &
JOB1=$!  # 获取后台进程ID

echo "Starting task 2..."
sleep 40 &
JOB2=$!

echo "Starting interactive task..."
# 模拟前台任务
sleep 20
# 按 Ctrl+Z 可以暂停这个脚本本身

echo "Task 1 PID: $JOB1"
echo "Task 2 PID: $JOB2"

# 等待所有后台作业完成
wait $JOB1 $JOB2
echo "All tasks completed"

常见问题与解决方案

问题1:作业停止输出

# 后台作业默认输出到终端,可能干扰
$ find / -name "*.log" > logs.txt &
[1] 45678

# 但仍有错误输出到终端
# 解决方案:重定向所有输出
$ find / -name "*.log" > logs.txt 2>&1 &

问题2:需要输入的后台作业

# 后台作业请求输入时会暂停
$ mysql -u root -p
Enter password: 
^Z
[1]+  Stopped                 mysql -u root -p

$ bg
[1]+ mysql -u root -p &
# 作业会暂停等待输入,而不是继续运行

# 解决方案1:使用 expect 或脚本提供输入
# 解决方案2:使用无密码认证或配置文件

问题3:终端关闭后作业终止

# 后台作业默认随终端关闭而终止
$ sleep 1000 &
[1] 12345

# 关闭终端,作业会被终止
# 解决方案:
$ sleep 1000 &
$ disown  # 将作业与当前shell分离
# 或
$ nohup sleep 1000 &

相关命令

jobs - 查看作业状态

jobs          # 列出作业
jobs -l       # 列出作业及进程ID
jobs -p       # 只列出进程ID
jobs -r       # 只列出运行中的作业
jobs -s       # 只列出暂停的作业

fg - 将作业带到前台

fg %1        # 将作业1带到前台
fg           # 将当前作业带到前台

kill - 终止作业

kill %1      # 终止作业1(发送SIGTERM)
kill -9 %1   # 强制终止作业1(发送SIGKILL)

wait - 等待作业完成

sleep 10 &
JOB1=$!
sleep 20 &
JOB2=$!

wait $JOB1   # 等待作业1完成
echo "Job 1 completed"

wait         # 等待所有后台作业完成
echo "All jobs completed"

实战示例

示例1:监控日志文件

# 1. 启动日志监控
$ tail -f /var/log/syslog
# 监控日志...

# 2. 暂停监控,执行清理
Ctrl+Z
[1]+  Stopped                 tail -f /var/log/syslog

$ sudo logrotate /etc/logrotate.conf
$ sudo systemctl restart syslog

# 3. 恢复监控
$ bg
[1]+ tail -f /var/log/syslog &

示例2:并行处理任务

# 并行处理多个文件
for file in *.log; do
    process_file "$file" &
done

# 查看后台作业
jobs

# 暂停所有作业(需要逐个暂停)
# 或者使用进程组

示例3:开发中的调试

# 1. 启动开发服务器
$ python manage.py runserver
# 服务器运行...

# 2. 需要修改代码
Ctrl+Z
[1]+  Stopped                 python manage.py runserver

# 3. 服务器放到后台
$ bg
[1]+ python manage.py runserver &

# 4. 编辑代码
$ vim views.py

# 5. 带回前台查看日志
$ fg
python manage.py runserver
# 查看输出,测试功能

交互式工作流程示例

# 典型的工作会话
$ find /usr -name "*.so" > libraries.txt
^Z
[1]+  Stopped                 find /usr -name "*.so" > libraries.txt

$ bg %1
[1]+ find /usr -name "*.so" > libraries.txt &

$ grep something important.txt
^Z
[2]+  Stopped                 grep something important.txt

$ ls -la
total 100
...

$ fg %2
grep something important.txt
# 查看结果

$ jobs
[1]+  Running                 find /usr -name "*.so" > libraries.txt &

$ kill %1  # 终止find命令
[1]+  Terminated              find /usr -name "*.so" > libraries.txt

最佳实践

  1. 及时清理:完成后台作业后及时清理
  2. 使用作业号:明确指定作业号,避免混淆
  3. 监控状态:定期使用 jobs 检查后台作业
  4. 处理输出:重定向后台作业的输出,避免干扰
  5. 分离关键作业:使用 nohup 或 disown 处理需要持久运行的作业

限制与注意事项

  1. 仅限当前终端:作业控制只在当前shell会话中有效
  2. 某些命令不可暂停:如 vimtop 等全屏程序
  3. 信号传递bg 发送 SIGCONT 信号继续作业
  4. 资源竞争:多个后台作业可能竞争CPU和I/O资源

总结

bg 命令是 Linux 作业控制的核心工具之一,允许用户:

  • 将暂停的作业转为后台运行
  • 管理多个并发任务
  • 灵活切换工作焦点
  • 实现基本的并行处理

掌握 bgfgjobsCtrl+Z 这一套作业控制工具,可以显著提高命令行工作效率,特别是在处理长时间运行的任务时。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐