我试图通过从bash脚本解析qstat -tn1的输出来检查正在运行和排队的PBS作业的数量.
到目前为止,这有效:
count ()
{
qstat -tn1 | awk '
BEGIN { R = 0; Q = 0; }
$10 == "R" { R++ }
$10 == "Q" { Q++ }
END { print R, Q }'
}
if read -r R Q <
...
但是,我发现qstat偶尔因未知原因而失败.在这种情况下,它不会向stdout打印任何内容,而是向stderr发送一些错误消息,并以非零状态退出(相当标准).但是,awk不知道qstat失败了,并且很高兴为它收到的空输入打印0 0.然后读取为R和Q分配0而不知道qstat实际上失败了.
>我需要在awk脚本的BEGIN块中用0初始化R和Q,因为可能没有正在运行的进程或没有排队进程,并且我需要打印0,而不仅仅是一个空字符串,用于此类进程的数量.
>我可以设置-o pipefail,这将允许count以非零状态退出,但是read无法看到退出状态,并且awk被执行并且无论如何都为空输入打印0 0.
>我可以尝试一个命名管道和子流程,但是必须管理它们感觉就像过度杀伤太复杂了.
有没有什么好方法可以让计数调用者检测到它的失败?
解决方法:
我认为流程替换中的读取计数会阻止您获得其返回状态.所以不要这样做.而是将结果存储在变量中,或使用管道.
count=$(count)
if [ $? -eq 0 ]; then
read -r R Q <<
…
要么
set -o pipefail
if count | { read -r R Q; … }
另一种可能性是使用PIPESTATUS变量来检查第一个命令的返回状态.
count=$(qstat -tn1 | awk …)
if ((${PIPESTATUS[0]} == 0)); then
read P Q
…
或者,安排awk在其输入为空时打印一些与众不同的东西(例如,什么都没有).
awk '
BEGIN { R = 0; Q = 0; }
$10 == "R" { R++ }
$10 == "Q" { Q++ }
END { if (NR) print R, Q }'
您可以使用moreutils或other methods中的ifne来测试命令的输入是否为空.但是由于您正在使用awk,所以您可以在已经拥有的awk脚本中执行此操作.
如果需要从qstat命令获取返回状态,可以将其作为额外输入行提供给awk.为了便于解析,请安排最后一行具有唯一格式.
{
qstat -tn1
echo exit_code = $?
} | awk '
…
/^exit_code = / { status = $3 }
END { if (status == 0) print Q, R }
'
标签:bash,linux,scripting
来源: https://codeday.me/bug/20190810/1641131.html