我在检查多管道命令链中的某个命令是否引发错误时遇到问题。通常这并不难检查,但在我的情况下也set -o pipefail
没有检查工作。${PIPESTATUS[@]}
设置是这样的:
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-5 秒)。我不想叫它两次。或者我可以使用一个临时文件来写入错误,但我宁愿这样做,而不需要创建/删除文件的开销。
有什么想法可以让我在 bash 中完成这项工作吗?
谢谢
PS:
$ echo $BASH_VERSION
4.2.37(1)-release