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会抛出一个无效选项 – < grepoption>因为< grepoption>而没有任何意义的错误显然不是$snmpcmd选项.在这个阶段我认为这是一个$snmpcmd的错误,但这是另一个节目……
如果发生错误,procdata将为空.但是,由于两个不同的原因,它可能是空的:要么因为执行$snmpcmd时发生错误(例如超时),要么因为grep找不到它要查找的内容.问题是,我需要能够区分这两种情况并单独处理它们.
因此,设置-o pipefail不是一个选项,因为它会传播任何错误,我无法区分管道的哪个部分失败.另一方面,在procdata =($(eval $cmd))之后echo ${PIPESTATUS [@]}总是0,即使我有很多管道!?然而,如果我在提示符下直接执行整个命令并立即调用echo ${PIPESTATUS [@]},它会正确返回所有管道的退出状态.
我知道我可以将错误的流绑定到stdout但是我必须使用启发式方法来检查procdata中的元素是有效还是错误消息,并且我冒着获得误报的风险.我还可以将stdout传递给/ dev / null并仅捕获错误流并检查是否${#procdata [@]} -eq 0.但是我必须重复调用以获取实际数据并且整个命令是时间成本高(约3-5s).我不想两次打电话.或者我可以使用临时文件来写错误,但我宁愿这样做也没有创建/删除文件的开销.
有什么想法我怎么能用bash做这个工作?
谢谢
P.S:
$echo $BASH_VERSION 4.2.37(1)-release
(1)当您说eval $cmd并尝试获取命令$cmd中包含的管道中进程的退出值时,echo“${PIPESTATUS [@]}”将仅包含eval的退出状态.而不是eval,您需要提供完整的命令行.
(2)在将管道输出分配给变量时,需要获取PIPESTATUS.试图在以后这样做是行不通的.
举个例子,你可以说:
foo=$(command | grep something | command2; echo "${PIPESTATUS[@]})"
这会将管道输出和PIPESTATUS数组捕获到变量foo中.
您可以通过以下方式将命令输出到数组中:
result=($(head -n -1 <<< "$foo"))
和PIPESTATUS阵列说
tail -1 <<< "$foo"