21. 子shell
运行一个shell脚本会启动一个新的进程,即子shell。
定义: 一个子shell是由一个shell(或shell脚本)触发的子进程。
一个子shell是命令处理器(-- 在终端或者xtrem窗口给出提示符的shell)的一个独立的例子。正如你的命令在命令行提示符处被理解执行一样,一个脚本批处理一组命令。每一个shell脚本运行实际上是父shell的一个支线进程(子进程)。
一个shell脚本可以自己启动多个子进程。这些子进程使得脚本进行并行处理,实际上是多个支线任务同事进行。
#!/bin/bash
# subshell-test.sh
(
# 在圆括号内,因此是一个子shell . . .
while [ 1 ] # 无限循环.
do
echo "Subshell running . . ."
done
)
# 脚本会永远运行,或者至少直到由Ctl-C终止。
exit $? # 脚本结束 (但是永远无法到达这里)。
现在,运行这个脚本:
sh subshell-test.sh
另外,在脚本运行的同时, 从另一个xterm运行:
ps -ef | grep subshell-test.sh
UID PID PPID C STIME TTY TIME CMD
500 2698 2502 0 14:26 pts/4 00:00:00 sh subshell-test.sh
500 2699 2698 21 14:26 pts/4 00:00:24 sh subshell-test.sh
^^^^
分析:
PID 2698, 脚本, 启动 PID 2699, 子shell.
注释: “UID ...”这一列可以通过“grep”命令筛去,但是由于说明的目的而显示在这里。一般来说,脚本的一个外部命令会使得子进程产生分叉,[^1] 但是一个Bash内建命令不会如此。
在圆括号内的命令列
(命令1; 命令1; 命令3; ...)
子shell的变量不能被这个子shell内代码区块之外的部分看见。这些变量不能被父进程中调用,也不能被启动次子shell的shell调用。这些变量实际上是子进程的局部变量。
例21-1.子shell的变量范围
定义: 变量的范围是指其有意义的上下文内容,在此变量值可以被引用。比如说,局部变量的范围只在函数、代码区块或子shell内的相应定义范围内,而全局变量的范围则是其出现的整个脚本区域。
内部变量 $BASH_SUBSHELL 指出一个子shell的嵌套层级时,而变量 $SHLVL 指示在子shell内不变的层级。
子shell内的路径改变不会带入到父shell中。
例21-2. 列出用户信息
一个子shell可以用来为一个命令组设定一个“特定环境”。
从这里可以看出,命令 exit 只终止正在运行的子shell,并不终止父shell或脚本。
这样的“特定环境”的一个应用是检查一个变量是否被定义。
另一个应用是检查一个锁定文件。
多个进程可以在不同子shell内并行执行。这样就可以将一个复杂的任务分解成多个子部分同时处理。
例21-3. 在子shell中运行并行进程
向子shell的I/O重定向使用管道算符"|",正如 ls -al | (命令)
在花括号间的代码块不会启动一个子shell。
{ 命令1; 命令2; 命令3; ...命令N; }
Notes
[^1] 和 exec 命令一起触发的外部命令(通常)不会分叉一个子进程 / 子shell
最后更新于
这有帮助吗?