Shell基础——简单命令和pipeline

简单命令

由空格分隔,由control operators(换行符, ‘||’, ‘&&’, ‘&’, ‘;’, ‘;;’, ‘;&’, ‘;;&’, ‘|’, ‘|&’, ‘(’, or ‘)’)终止的单词序列,构成了shell的简单命令(Simple Command)。
通常,第一个单词指定要执行的命令,其余单词是该命令的参数。

control operators将命令进行组合,产生pipeline和list

pipeline

首先,一个独立的简单命令,都是pipeline

command # 这也是pipeline

由 | 或 |& 分隔的命令序列,也是pipeline

command1 [ | or |& command2 ] ... # 这还是是pipeline

pipeline中每个命令的输出通过管道连接到下一个命令的输入。 也就是说,每个命令都会读取前一个命令的输出。

$ ls -al /proc/self/fd|cat
total 0
dr-x------ 2 felix felix 0 May 31 07:01 .
dr-xr-xr-x 7 felix felix 0 May 31 07:01 ..
lrwx------ 1 felix felix 0 May 31 07:01 0 -> /dev/tty1
l-wx------ 1 felix felix 0 May 31 07:01 1 -> pipe:[289] # 标准输出fd 1连接到了管道
lrwx------ 1 felix felix 0 May 31 07:01 2 -> /dev/tty1
lr-x------ 1 felix felix 0 May 31 07:01 3 -> /proc/239/fd
$ : fakecomand|ls -al /proc/self/fd
total 0
dr-x------ 2 felix felix 0 May 31 07:03 .
dr-xr-xr-x 7 felix felix 0 May 31 07:03 ..
lr-x------ 1 felix felix 0 May 31 07:03 0 -> 'pipe:[295]' # 标准输入fd 0连接到了管道
lrwx------ 1 felix felix 0 May 31 07:03 1 -> /dev/tty1
lrwx------ 1 felix felix 0 May 31 07:03 2 -> /dev/tty1
lr-x------ 1 felix felix 0 May 31 07:03 3 -> /proc/242/fd
$ ls -al /proc/self/fd|&cat
total 0
dr-x------ 2 felix felix 0 May 31 07:05 .
dr-xr-xr-x 7 felix felix 0 May 31 07:05 ..
lrwx------ 1 felix felix 0 May 31 07:05 0 -> /dev/tty1
l-wx------ 1 felix felix 0 May 31 07:05 1 -> pipe:[302]
l-wx------ 1 felix felix 0 May 31 07:05 2 -> pipe:[302]
lr-x------ 1 felix felix 0 May 31 07:05 3 -> /proc/243/fd
$ : fakecomand|&ls -al /proc/self/fd
total 0
dr-x------ 2 felix felix 0 May 31 07:05 .
dr-xr-xr-x 7 felix felix 0 May 31 07:05 ..
lr-x------ 1 felix felix 0 May 31 07:05 0 -> 'pipe:[308]'
lrwx------ 1 felix felix 0 May 31 07:05 1 -> /dev/tty1
lrwx------ 1 felix felix 0 May 31 07:05 2 -> /dev/tty1
lr-x------ 1 felix felix 0 May 31 07:05 3 -> /proc/246/fd

如果使用|&,则command1的standard output和standard error,都将通过管道连接到command2的standard input。 它是2>&1 |的简写.

如果pipeline不是异步执行,Shell将等待pipeline中的所有命令完成。
pipeline中的每个命令都在其自己的subshell中执行,该subshell是一个单独的进程。

$ ps -ef|grep 'bash'
felix        6     5  0 21:25 tty1     00:00:00 -bash
felix       77     6  0 21:35 tty1     00:00:00 grep --color=auto bash
$ ps -ef|grep 'ps'
felix       78     6  0 21:35 tty1     00:00:00 ps -ef
felix       79     6  0 21:35 tty1     00:00:00 grep --color=auto ps
$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 21:25 ?        00:00:00 /init
root         5     1  0 21:25 tty1     00:00:00 /init
felix        6     5  0 21:25 tty1     00:00:00 -bash
felix       80     6  0 21:36 tty1     00:00:00 ps -ef

pipeline的exit status是最后一条命令的exit status. shell等待pipeline中的所有命令终止后才返回exist status.

其实,完整的pipeline格式可以是:

[time [-p]] [!] command1 [ | or |& command2 ]

time在这里是保留字(reserved word),在pipeline完成后打印时间统计信息包括消耗的时间、命令执行所消耗的用户和系统时间。-p选项将输出格式更改为POSIX指定的格式。Bash变量TIMEFORMAT可以为时间设置格式字符串。如果没有设置该变量,Bash默认使用如下格式:

$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'
$ time ps -ef | grep 'ef'
felix       90     6  0 21:43 tty1     00:00:00 ps -ef
felix       91     6  0 21:43 tty1     00:00:00 grep --color=auto ef

real    0m0.037s
user    0m0.000s
sys     0m0.047s

保留字!将pipeline的退出状态逻辑取反

pipeline与redirection

pipeline中每个命令的输出通过管道连接到下一个命令的输入,这种连接,要早于redirection. 所以redirection会覆盖管道的连接
例如

$ : fakecomand|&ls -al /proc/self/fd <foo
total 0
dr-x------ 2 felix felix 0 May 31 07:07 .
dr-xr-xr-x 7 felix felix 0 May 31 07:07 ..
lr-x------ 1 felix felix 0 May 31 07:07 0 -> /home/felix/foo # fd0 被redirection覆盖
lrwx------ 1 felix felix 0 May 31 07:07 1 -> /dev/tty1
lrwx------ 1 felix felix 0 May 31 07:07 2 -> /dev/tty1
lr-x------ 1 felix felix 0 May 31 07:07 3 -> /proc/248/fd

在上面的例子里,先建立了pipe,但第二个命令的ls的fd0被redirection修改为文件。此时,建立的pipe其实是broken的。

组成pipeline的命令是并行执行的

command1|command2

command1和command2是同时执行的,虽然command1的PID通常比command2的要小,但是两个命令分别在自己的process里运行。两个平行的process通过pipe来同步,即,command2如果要从pipe里读,那么必须要等command1往pipe里写。如果command2的执行根本就不依赖于从pipe里读,那么command1和command2的执行进度就没有关系,也就无法确定谁先执行结束。这与顺序执行命令里介绍的“串行执行”结构不同:

command1;command2 # Bash一定会等待command1执行完成后,再执行command2

你可能感兴趣的:(每天一点点)