管道相连的命令如何精确获取返回值

920阅读 0评论2015-11-17 sync_1521
分类:LINUX

(1)$PIPESTATUS
这个数组变量将保存最后一个运行的前台管道的退出状态码.
相当有趣的是, 这个退出状态码和最后一个命令运行的退出状态码并不一定相同.
  1. bash$ echo $PIPESTATUS
  2. 0
  3. bash$ ls -al | bogus_command
  4. bash: bogus_command: command not found
  5. bash$ echo $PIPESTATUS
  6. 141
  7. bash$ ls -al | bogus_command
  8. bash: bogus_command: command not found
  9. bash$ echo $?
  10. 127
$PIPESTATUS数组的每个成员都保存了运行在管道中的相应命令的退出状态码.
$PIPESTATUS[0]保存管道中第一个命令的退出状态码.
$PIPESTATUS[1]保存第二个命令的退出状态码, 依此类推.
$PIPESTATUS变量在一个登陆的shell中可能会包含一个不正确0值(在3.0以下版本).
  1. tcsh% bash
  2. bash$ who | grep nobody | sort
  3. bash$ echo ${PIPESTATUS[*]}
  4. 0
如果一个脚本包含了上边的这行, 那么将会产生我们所期望的0 1 0的输出.
感谢, Wayne Pollock指出这一点并提供了上边的例子.
在某些上下文中, 变量$PIPESTATUS可能不会给出期望的结果.
  1. bash$ echo $BASH_VERSION
  2. 3.00.14(1)-release
  3. bash$ $ ls | bogus_command | wc
  4. bash: bogus_command: command not found
  5. 0 0 0
  6. bash$ echo ${PIPESTATUS[@]}
  7. 141 127 0
Chet Ramey把上边输出不正确的原因归咎于ls的行为.
因为如果把ls的结果放到管道上, 并且这个输出并没有被读取, 那么SIGPIPE将会杀掉它, 同时退出状态码变为141. 而不是我们所期望的0.
这种情况也会发生在tr命令中.
$PIPESTATUS是一个"不稳定"变量. 这个变量需要在任何命令干涉之前, 并在管道询问之后立刻被查询.
  1. bash$ $ ls | bogus_command | wc
  2. bash: bogus_command: command not found
  3. 0 0 0
  4. bash$ echo ${PIPESTATUS[@]}
  5. 0 127 0
  6. bash$ echo ${PIPESTATUS[@]}
  7. 0
(2)pipefail
man bash
The return status of a pipeline is the exit status of the last command, unless the  pipefail  option  is  enabled.   
If pipefail  is enabled, the pipelinea??s return status is the value of the last (rightmost) command to exit with a non-zero status, 
or zero if all commands exit successfully.

设置一下pipefail就可以获取最后一个执行错误的错误码了
  1. [root@rac0 ~]# set -o pipefail
  2. [root@rac0 ~]# afeef| echo

  3. -bash: afeef: command not found
  4. [root@rac0 ~]# echo $?
  5. 127
如果未设置pipefail
  1. [root@test ~]# aaaa|echo bbbb
  2. bbbb
  3. -bash: aaaa: command not found
  4. [root@test ~]# echo $?
  5. 0
上一篇:linux自定义开机启动服务和chkconfig使用方法
下一篇:rsync+inotify实现实时同步案例