微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

linux – 如果前一个命令失败,则退出管道

我试图通过从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 < <(count)
    ...

但是,我发现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 <<<"$count"
  …

要么

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 }'

您可以使用moreutilsother methods中的ifne来测试命令的输入是否为空.但是由于您正在使用awk,所以您可以在已经拥有的awk脚本中执行此操作.

如果需要从qstat命令获取返回状态,可以将其作为额外输入行提供给awk.为了便于解析,请安排最后一行具有唯一格式.

{
  qstat -tn1
  echo exit_code = $?
} | awk '
    …
    /^exit_code = / { status = $3 }
    END { if (status == 0) print Q, R }
'

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐