~~ linux return code with pipeline~~

~~ linux 管道命令中的返回码~~

BASH SHELL中,通常使用 $? 来获取上一条命令的返回码。

Shell Scripting Tutorial - Checking the exit status of ANY command in a pipeline

对于管道中的命令,使用$?只能获取管道中最后一条命令的返回码,例如:

${RUN_COMMAND} 2> "${CUR_DIR}"/weiflow-from-weiclient.log | ${WEIBOX_UTIL_HOME}/rotatelogs.py -n 3 "${CUR_DIR}"/weiflow-from-weiclient.log 500M

使用 $PIPESTATUS来获取管道中每个命令的返回码。

注意:

  1. PIPESTATUS 是一个数组,第一条命令的返回码存储在${PIPESTATUS[0]},以此类推。

  2. 如果前一条命令不是一个管道,而是一个单独的命令,命令的返回码存储为\({PIPESTATUS[0]},此时\){PIPESTATUS[0]}同\(?值相同(事实上,PIPESTATUS最后一个元素的值总是与\)?的值相同)

  3. 每执行一条命令,切记PIPESTATUS都会更新其值为上一条命令的返回码,

cat /not/a/valid/filename|cat

      if [ \({PIPESTATUS[0]} -ne 0 ]; then echo \){PIPESTATUS[@]}; fi

上例中执行完管道后,\({PIPESTATUS[0]}值为1,\){PIPESTATUS[1]}值为0

但是上面的脚本执行完成后,输出为0,这是因为if 分支的测试命令值为真,然后 PIPESTATUS[0]的值此时被置为0。应当在命令执行完成后立即在同一个测试命令中对所有值进行测试,例如

if [ \({PIPESTATUS[0]} -eq 1 -a \){PIPESTATUS[1]} -eq 0 ] ; then echo something; fi

或者先将$PIPESTATUS数组保存下来,以后再处理,例如

ret=${PIPESTATUS[@]};

RESULT

${RUN_COMMAND} 2> "${CUR_DIR}"/weiflow-from-weiclient.log | ${WEIBOX_UTIL_HOME}/rotatelogs.py -n 3 "${CUR_DIR}"/weiflow-from-weiclient.log 500M
exit \${PIPESTATUS[0]}

Checking the exit status of ANY command in a pipeline

  • It's a pretty common thing in a shell script to want to check the exit status of the previous command. You can do this with the $? variable, as is widely known:
#!/bin/bash
grep some.machine.example.com /etc/hosts
if [ "$?" -ne "0" ]; then
# The grep command failed to find "some.machine.example.com" in /etc/hosts file
echo "I don't know the IP address of some.machine.example.com"
exit 2
fi
  • What gets difficult is when you execute a pipeline: (see pipelines for more information on the Unix Pipeline)
#!/bin/bash
grep some.machine.example.com /etc/hosts 2>&1 | tee /tmp/hosts-results.txt
if [ "$?" -ne "0" ]; then
# Ah - what we get here is the status of the "tee" command,
# not the status of the "grep" command :-(
  • What you get is the result of the tee command, which writes the results to the display as well as to the /tmp/hosts-results.txt file.

  • To find out what grep returned, $? is of no use.

  • Instead, use the ${PIPESTATUS[]} array variable. ${PIPESTATUS[0]} tells us what grep returned, while ${PIPESTATUS[1]} tells us what tee returned.

  • So, to see what grep found, we can write our script like this:

#!/bin/bash
grep some.machine.example.com /etc/hosts 2>&1 | tee /tmp/hosts-results.txt
if [ "${PIPESTATUS[0]}" -ne "0" ]; then
# The grep command failed to find "some.machine.example.com" in /etc/hosts file
echo "I don't know the IP address of some.machine.example.com"
exit 2
fi

Here's The Rub

  • The downside is, that any command you use to access ${PIPESTATUS[]}, will automatically replace the current state of the array with the return code of the command you have just run:
Pipeline (command) PIPESTATUS shows status of:
grep ... tee ...
echo "Grep returned ${PIPESTATUS[0]}" echo "Grep ...
echo "Maybe PIPESTATUS isn't so useful after all" echo "Maybe ...
  • So as soon as we use echo to tell us about the return code of grep, the ${PIPESTATUS[]} array now tells us about the return code of the echo statement itself, which is pretty likely to be zero, as not much can cause echo to fail!

The Fix

  • Because ${PIPESTATUS[]} is a special variable, it changes all the time. However, we can copy this array into another array, which is just a regular array, which will not be changed at all just by running some more commands. Copying an array requires a slightly different syntax to simply copying contents of a variable into another:

  • RC=( "${PIPESTATUS[@]}" )

  • Where RC stands for Return Code. We can then investigate the status of RC at our leisure. For testing purposes, the program true always returns zero, and false always returns 1:

#!/bin/bash
echo "tftf"
true | false | true | false
RC=( "${PIPESTATUS[@]}" )
echo "RC[0] = ${RC[0]}" # true = 0
echo "RC[1] = ${RC[1]}" # false = 1
echo "RC[2] = ${RC[2]}" # true = 0
echo "RC[3] = ${RC[3]}" # false = 1 echo "ftft"
false | true | false | true
RC=( "${PIPESTATUS[@]}" )
echo "RC[0] = ${RC[0]}" # false = 1
echo "RC[1] = ${RC[1]}" # true = 0
echo "RC[2] = ${RC[2]}" # false = 1
echo "RC[3] = ${RC[3]}" # true = 0 echo "fftt"
false | false | true | true
RC=( "${PIPESTATUS[@]}" )
echo "RC[0] = ${RC[0]}" # false = 1
echo "RC[1] = ${RC[1]}" # false = 1
echo "RC[2] = ${RC[2]}" # true = 0
echo "RC[3] = ${RC[3]}" # true = 0

Linux中对管道命令中的任意子命令进行返回码校验的更多相关文章

  1. linux命令中"|"管道流的意思

    在linux中.可以利用符号:"|"来实现管道功能. 那么什么是管道功能呢: 管道是Shell的一大特征.他将多个命令前后连接起来形成一个管道流. 管道流中的每一个命令都作为一个单 ...

  2. Linux命令中特殊符号

    转自:http://blog.chinaunix.net/uid-16946891-id-5088144.html   在shell中常用的特殊符号罗列如下:# ; ;; . , / \ 'strin ...

  3. [转帖]Linux命令中特殊符号

    Linux命令中特殊符号 转自:http://blog.chinaunix.net/uid-16946891-id-5088144.html   在shell中常用的特殊符号罗列如下:# ; ;; . ...

  4. linux 中更改用户权限和用户组的命令chmod,chgrp实例

    linux 中更改用户权限和用户组的命令实例; 增加权限给当前用户 chmod +wx filename chmod -R 777 /upload 用户组 chgrp -R foldname zdz ...

  5. linux top命令中各cpu占用率含义

    linux top命令中各cpu占用率含义 [尊重原创文章摘自:http://www.iteye.com/topic/1137848]0.3% us 用户空间占用CPU百分比 1.0% sy 内核空间 ...

  6. linux free命令中buffer与cache的区别

    linux free命令中buffer与cache的区别 2012-05-15      个评论       收藏    我要投稿 linux free命令中buffer与cache的区别   ~$ ...

  7. Linux 下 expect 脚本语言中交互处理常用命令

    Linux 下 expect 脚本语言中交互处理常用命令 1. #!/usr/bin/expect 告诉操作系统脚本里的代码使用那一个 shell 来执行.这里的 expect 其实和 Linux 下 ...

  8. 【转】linux中的cut/tr/join/split/xargs命令

    1. cut命令 cut命令用于从文件或者标准输入中读取内容并截取每一行的特定部分并送到标准输出. 截取的方式有三种:一是按照字符位置,二是按照字节位置,三是使用一个分隔符将一行分割成多个field, ...

  9. Linux grep 命令中的正则表达式详解

    在 Linux .类 Unix 系统中我该如何使用 Grep 命令的正则表达式呢? Linux 附带有 GNU grep 命令工具,它支持扩展正则表达式(extended regular expres ...

  10. Linux 中最常用的目录及文件管理命令

    一.查看文件的命令 对于一个文本文件,在linux中有多种查看方式来获知文件内容,如直接显示整个文本内容.分页查看内容.或者只查看文件开头或末尾的部分内容.在linux可以用不同的命令来实现. 1. ...

随机推荐

  1. AGC061 F Perfect String

    毒瘤出题人,史诗加强 AGC 的 F-- 然而我连原题都不会,所以只学了原题做法. 翻译一下题意就是给定一张循环网格图,求经过 \((0,0)\) 的闭合回路条数. 由于网格图中每一个位置都等价,所以 ...

  2. SpringBoot定义优雅全局统一Restful API 响应框架四

    如果没有看前面几篇文章请先看前面几篇 SpringBoot定义优雅全局统一Restful API 响应框架 SpringBoot定义优雅全局统一Restful API 响应框架二 SpringBoot ...

  3. #Python 利用pivot_table,数据透视表进行数据分析

    前面我们分享了,利用python进行数据合并和连接,但是工作中,我们往往需要对数据进一步的聚合或者运算,以求最后的数据结果. 今天我们就来学习一下利用pandas模块,对数据集进行数据透视分析. pi ...

  4. 2022-08-19:以下go语言代码输出什么?A:equal;B:not equal;C:不确定。 package main import ( “fmt“ “reflect“ )

    2022-08-19:以下go语言代码输出什么?A:equal:B:not equal:C:不确定. package main import ( "fmt" "refle ...

  5. 2022-07-31:给出一个有n个点,m条有向边的图, 你可以施展魔法,把有向边,变成无向边, 比如A到B的有向边,权重为7。施展魔法之后,A和B通过该边到达彼此的代价都是7。 求,允许施展一次魔法

    2022-07-31:给出一个有n个点,m条有向边的图, 你可以施展魔法,把有向边,变成无向边, 比如A到B的有向边,权重为7.施展魔法之后,A和B通过该边到达彼此的代价都是7. 求,允许施展一次魔法 ...

  6. uni-app 选择原因

    开发者.案例数量更多跨平台能力及扩展灵活性更强性能体验优秀周边生态丰富学习成本低开发成本低

  7. Charles抓包补充解释

    配置 大佬的博客真的很详细很详细,我就不重复造轮子了,第一次直接看大佬的博客就好,这里Python爬取微信小程序(Charles) 补充解释 在这一步疑问很多,大佬说的不是很详细,就由我来补充下吧~ ...

  8. L2-3 智能护理中心统计

    题目描述: 智能护理中心系统将辖下的护理点分属若干个大区,例如华东区.华北区等:每个大区又分若干个省来进行管理:省又分市,等等.我们将所有这些有管理或护理功能的单位称为"管理结点" ...

  9. HNU2019 Summer Training 3 E. Blurred Pictures

    E. Blurred Pictures time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  10. ENVI5.6 安装教程,新手入门(超详细)附安装包和常见问题

    ENVI是一个完整的遥感图像处理平台,广泛应用于科研.环境保护.气象.农业.林业.地球科学.遥感工程.水利.海洋等领域.目前ENVI已成为遥感影像处理的必备软件,包含辐射定标.大气校正.镶嵌裁剪.分类 ...