我在检查多管道命令链中的某个命令是否发生错误时遇到问题。通常这不难检查,但set -o pipefail
和检查${PIPESTATUS[@]}
都不适用于我的情况。设置是这样的:Bash:检查多管道命令链的退出状态
cmd="$snmpcmd $snmpargs $agent $oid | grep <grepoptions> for_stuff | cut -d',' f$fields | sed 's/ubstitute/some_other_stuff/g'"
注意1:该命令进行了彻底测试,并完美地工作。
现在,我想将该命令的输出存储在名为procdata
的数组中。因此,我所做的:
declare -a procdata
procdata=($(eval $cmd))
注2:eval
是必要的,因为否则$snmpcmd
与invalid option -- <grepoption>
错误,是没有意义的,因为<grepoption>
不是$snmpcmd
选项明显抛出了。在这个阶段,我认为这是一个错误$snmpcmd
,但这是另一个节目...
如果发生错误,procdata
将为空。但是,由于两种不同的原因,它可能为空:要么是因为在执行$snmpcmd
时发生错误(例如超时),要么是因为grep
找不到要查找的内容。问题是,我需要能够区分这两种情况并分别处理它们。
因此,set -o pipefail
不是一个选项,因为它会传播任何错误,我无法区分哪部分管道失败。另一方面echo ${PIPESTATUS[@]}
总是0
后procdata=($(eval $cmd))
即使我有很多管道!然而,如果我在提示符处直接执行整个命令,并立即调用echo ${PIPESTATUS[@]}
,它将正确返回所有管道的退出状态。
我知道我可以将err流绑定到标准输出,但我必须使用启发式方法来检查procdata
中的元素是否有效或错误消息,并且我冒着获得误报的风险。我也可以将stdout管道输入到/dev/null
并只捕获错误流并检查是否${#procdata[@]} -eq 0
。但我不得不重复这个呼叫来获取实际数据,整个命令的时间成本很高(大约3-5s)。我不想打两次电话。或者我可以使用一个临时文件来写错误,但我宁愿这样做,而没有创建/删除文件的开销。
任何想法,我可以使这项工作在bash?
感谢
PS:
$ echo $BASH_VERSION
4.2.37(1)-release
我有同样的想法。不幸的是它不起作用,但我不知道为什么。我发布了确切的命令,因为我可能看不到明显的: – user3040975
'local cmdargs =“ - CHf,-m $ mibs -v $ snmpver -c $ community $ agent”; local procdatacmd =“$ tblcmd $ cmdargs $ proc_table”; procdatacmd + =“| cut -d','-f $ fields | grep -we -e | sort | uniq -c | sed's/^ * \ | \”// g; s //,/ g' ; echo $ {PIPESTATUS [@]}“'然后执行:'declare -a procdata =($(head -n-1 <<< $ $ procdatacmd))'输出是空的......只是没有。 –
user3040975
@ user3040975你似乎没有_running_上面的行中有任何命令 – devnull