Linux中对管道命令中的任意子命令进行返回码校验
~~ 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来获取管道中每个命令的返回码。
注意:
PIPESTATUS 是一个数组,第一条命令的返回码存储在${PIPESTATUS[0]},以此类推。
如果前一条命令不是一个管道,而是一个单独的命令,命令的返回码存储为\({PIPESTATUS[0]},此时\){PIPESTATUS[0]}同\(?值相同(事实上,PIPESTATUS最后一个元素的值总是与\)?的值相同)
每执行一条命令,切记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中对管道命令中的任意子命令进行返回码校验的更多相关文章
- linux命令中"|"管道流的意思
在linux中.可以利用符号:"|"来实现管道功能. 那么什么是管道功能呢: 管道是Shell的一大特征.他将多个命令前后连接起来形成一个管道流. 管道流中的每一个命令都作为一个单 ...
- Linux命令中特殊符号
转自:http://blog.chinaunix.net/uid-16946891-id-5088144.html 在shell中常用的特殊符号罗列如下:# ; ;; . , / \ 'strin ...
- [转帖]Linux命令中特殊符号
Linux命令中特殊符号 转自:http://blog.chinaunix.net/uid-16946891-id-5088144.html 在shell中常用的特殊符号罗列如下:# ; ;; . ...
- linux 中更改用户权限和用户组的命令chmod,chgrp实例
linux 中更改用户权限和用户组的命令实例; 增加权限给当前用户 chmod +wx filename chmod -R 777 /upload 用户组 chgrp -R foldname zdz ...
- linux top命令中各cpu占用率含义
linux top命令中各cpu占用率含义 [尊重原创文章摘自:http://www.iteye.com/topic/1137848]0.3% us 用户空间占用CPU百分比 1.0% sy 内核空间 ...
- linux free命令中buffer与cache的区别
linux free命令中buffer与cache的区别 2012-05-15 个评论 收藏 我要投稿 linux free命令中buffer与cache的区别 ~$ ...
- Linux 下 expect 脚本语言中交互处理常用命令
Linux 下 expect 脚本语言中交互处理常用命令 1. #!/usr/bin/expect 告诉操作系统脚本里的代码使用那一个 shell 来执行.这里的 expect 其实和 Linux 下 ...
- 【转】linux中的cut/tr/join/split/xargs命令
1. cut命令 cut命令用于从文件或者标准输入中读取内容并截取每一行的特定部分并送到标准输出. 截取的方式有三种:一是按照字符位置,二是按照字节位置,三是使用一个分隔符将一行分割成多个field, ...
- Linux grep 命令中的正则表达式详解
在 Linux .类 Unix 系统中我该如何使用 Grep 命令的正则表达式呢? Linux 附带有 GNU grep 命令工具,它支持扩展正则表达式(extended regular expres ...
- Linux 中最常用的目录及文件管理命令
一.查看文件的命令 对于一个文本文件,在linux中有多种查看方式来获知文件内容,如直接显示整个文本内容.分页查看内容.或者只查看文件开头或末尾的部分内容.在linux可以用不同的命令来实现. 1. ...
随机推荐
- 模块 ""element-plus"" 没有导出的成员 "ElMessage"。你是想改用 "import ElMessage from "element-plus"" 吗?
背景:在使用Element Plus写demo时,导入ElMessage组件出现 [模块 ""element-plus"" 没有导出的成员 "ElMe ...
- 聊一聊 dotnet-trace 调查 lock锁竞争
一:背景 1. 讲故事 最近在分析一个 linux 上的 dump,最后的诱因是大量的lock锁诱发的高频上下文切换,虽然问题告一段落,但我还想知道一点信息,所谓的高频到底有多高频?锁竞争到底是一个怎 ...
- 2022-08-13:以下go语言代码输出什么?A:[5 6 7 1 2 3 4] B:[1 2 3 4 5 6 7] C:[4 5 6 7 1 2 3]。 package main import
2022-08-13:以下go语言代码输出什么?A:[5 6 7 1 2 3 4] B:[1 2 3 4 5 6 7] C:[4 5 6 7 1 2 3]. package main import ( ...
- 2022-01-01:给定int[][] meetings,比如 { {66, 70} 0号会议截止时间66,获得收益70 {25, 90} 1号会议截止时间25,获得收益90
2022-01-01:给定int[][] meetings,比如 { {66, 70} 0号会议截止时间66,获得收益70 {25, 90} 1号会议截止时间25,获得收益90 {50, 30} 2号 ...
- odoo开发教程五:高级视图
树视图 tree视图表现出来是列表视图,列表中一行一纪录.可以根据每行纪录的某字段值不同而把每行以不同样式显示. decoration-{样式}="条件" 样式主要有: bf(fo ...
- ODOO13 之十 :Odoo 13开发之后台视图 – 设计用户界面
Odoo 13开发之后台视图 – 设计用户界面 本文将学习如何为用户创建图形化界面来与图书应用交互.我们将了解不同视图类型和小组件(widgets)之间的差别,以及如何使用它们来提供更优的用户体验. ...
- Java动态数组及数组排序的三种常用方法
一.动态数组 1.数组的定义: 用于存储相同数据类型的一组连续的存储空间 2.数组的特点: 数组的长度一旦定义,则不可改变 访问数组的元素需要通过下标(索引)访问,下标从0开始 数组是 ...
- P1585 魔法阵 题解
题意: 题目传送门 可以看做一个人手中有一些宝石,并将宝石分成两组,一组的编号为 1 至 n×m/2,二组为 n×m/2+1 至 n×m+1.当两组两个宝石编号相差为 n×m/2 为一对.现在要遍历一 ...
- ChatGPT的原理与前端领域实践
一.ChatGPT 简介 ChatGPT的火爆 ChatGPT作为一个web应用,自22年12月发布,仅仅不到3个月的时间,月活用户就累积到1亿.在此之前,最快记录的保持者也需要9个月才达到月活1亿. ...
- 2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j。
2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j. ...