Linux的Shell脚本中,& 符号有两个主要作用:
- 使命令在后台运行
- 将命令运行在子进程中
举个例子:
sleep 10
普通执行上述命令,会把 shell 挂起 10 秒,此时 shell 对用户不可用。
sleep 10 &
如果在命令后添加 &,则会在后台运行这个命令。shell 就会立刻返回,用户可以继续操作。
这就实现了使命令在后台运行。
另一个例子:
(sleep 10)
这里使用 () 将 sleep 命令括起来,表示运行在一个子进程中。
父进程 shell 会立刻返回,不等待子进程结束。
(sleep 10) &
如果再添加 &,则不仅运行在子进程中,而且还在后台运行。
父进程 shell 会立即返回,不等待子进程结束。
仔细观察会发现,(sleep 10) 和 (sleep 10) & 好像没有区别。
这是因为在这个简单的例子中,(sleep 10) 这个子shell自始至终只有一个命令需要执行,所以等同于一个后台线程。
区别在于,当子shell中有多条需要序列执行的命令时:
(
command1
command2
)
(
command1
command2
) &
这两种写法会有明显区别:
- 不加 & 时,父进程(父shell)会等待子shell执行结束后再执行后面的命令
- 加上 & 后,父进程会立即执行后面的命令,不等待子shell结束
例如:
(
sleep 10
echo "done"
)
echo "continue..."
# 会等待10秒后打印"continue..."
(
sleep 10
echo "done"
) &
echo "continue..."
# 会立即打印"continue...",不等待子shell结束
所以在含有多个命令需要顺序执行的子shell中:
- 不加&,父shell会等待子shell全部命令执行结束后再执行后面的命令
- 加上&后,父shell会立即执行后面的命令,不等待子shell结束
在例子 (sleep 10) 中,子shell只有一个sleep命令,相当于一个后台线程,添加&与否效果一样。
& 能区别子shell有多条需要顺序执行的命令时的表现。而对于只有一个命令需要执行的子shell, &并不会产生明显效果。
注意:
父子的层级关系并不一定是上下的嵌套。
只要根据()来判断:
外层 Shell 是父 Shell
() 定义的内层 Shell 是子 Shell
综上,&符号的作用主要有两个:
- 使命令在后台运行,shell 不等待命令结束才返回
- 将命令运行在子进程中,父进程不需要等待子进程结束才返回