在 Shell 脚本中,&
是一个非常重要的符号,具有多种用途。它的核心作用包括 后台运行命令 和 子进程执行。
一、基本语法
1. 后台运行命令
command &
- 作用:将
command
放入 后台运行,释放当前终端(用户可以在前台继续执行其他操作)。 - 退出状态码:命令执行完成后,系统会返回其退出状态码(0 表示成功,非 0 表示失败)。
- 示例:
# 让 sleep 命令在后台运行,不阻塞当前终端 sleep 10 &
2. 子进程执行
(command1; command2) &
- 作用:将一组命令放在 子进程中执行,并将其放入后台运行。
- 子进程:子进程是父进程(当前 Shell)的副本,父进程不会等待子进程结束。
- 示例:
# 在子进程中执行多个命令,并在后台运行 (sleep 5 && echo "Done") &
二、工作原理
1. 后台运行
- 当命令后添加
&
时,Shell 会立即返回控制权给用户,而不是等待命令执行完成。 - 后台运行的命令会持续占用系统资源(如 CPU 或内存),直到任务完成或被手动终止。
2. 子进程执行
- 使用括号
( ... )
包裹的命令会在 子 Shell 中执行,父 Shell 不会等待子 Shell 结束。 - 子 Shell 的环境变量与父 Shell 独立,修改子 Shell 中的变量不会影响父 Shell。
三、典型应用场景
1. 长时间任务
- 用于执行需要较长时间的任务,避免阻塞当前终端。
- 示例:
# 下载大文件并在后台运行 wget https://example.com/large-file.zip &
2. 并行执行
- 同时运行多个独立任务,提高效率。
- 示例:
# 并行执行多个命令 sleep 5 & sleep 10 & wait # 等待所有后台任务完成 echo "All tasks done"
3. 子进程隔离
- 在子进程中执行敏感操作(如修改环境变量),避免影响父进程。
- 示例:
# 在子进程中修改环境变量,不影响父进程 (export VAR="child"; echo $VAR) & echo $VAR # 输出空值
四、与其他符号的区别
符号 | 功能 | 说明 |
---|---|---|
& | 后台运行 | 将命令放入后台执行,不阻塞当前终端 |
&& | 逻辑与 | 前一个命令成功时执行后一个命令 |
` | ` | |
; | 顺序执行 | 无论前一个命令是否成功,均执行后一个命令 |
` | ` | 管道符 |
五、高级用法
1. 并行执行多个任务
# 并行执行三个命令
command1 &
command2 &
command3 &
wait # 等待所有后台任务完成
echo "All commands finished"
2. 结合子进程和后台运行
# 在子进程中执行多个命令,并在后台运行
(
echo "Start task"
sleep 5
echo "Task done"
) &
3. 使用 nohup
保持后台任务运行
# 即使关闭终端,任务仍会运行
nohup long-running-process > output.log 2>&1 &
六、常见问题解答
Q1: 如何让命令在后台运行?
A: 在命令后添加 &
。
sleep 10 &
Q2: 如何查看后台任务?
A: 使用 jobs
命令。
jobs -l # 显示任务编号和 PID
Q3: 如何终止后台任务?
A: 使用 kill
或 kill %n
。
kill %1 # 终止第一个后台任务
Q4: 如何避免关闭终端后任务终止?
A: 使用 nohup
或 disown
。
nohup command > output.log 2>&1 &
七、注意事项
-
后台任务管理
- 使用
jobs
查看当前终端的后台任务。 - 使用
fg %n
将后台任务切换到前台(%n
是任务编号)。 - 使用
kill %n
终止后台任务。
- 使用
-
子进程与父进程的区别
- 子进程的环境变量与父进程独立。
- 父进程退出时,子进程通常会终止(除非使用
nohup
或disown
保持运行)。
-
输出重定向
- 后台运行的命令默认输出到当前终端,需手动重定向输出到文件:
nohup long-running-process > output.log 2>&1 &
- 后台运行的命令默认输出到当前终端,需手动重定向输出到文件:
-
资源竞争
- 多个后台任务可能竞争系统资源(如 CPU、内存),需合理控制并发数。