我试图通过解析脚本的输出来检查正在运行和排队的 PBS 作业的qstat -tn1
数量bash
。到目前为止,这已经奏效了:
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
收到的空输入。然后read
将 0 分配给两者R
,并且Q
不知道qstat
实际上失败了。
- 我需要在脚本块中使用 0
R
进行初始化,因为可能没有正在运行的进程或没有排队的进程,并且我需要打印,而不仅仅是一个空字符串来获取此类进程的数量。Q
BEGIN
awk
0
- 我可以这样做
set -o pipefail
,这将允许count
以非零状态退出,但read
看不到退出状态,并且无论如何awk
都会执行并打印0 0
空输入。 - 我可以尝试命名管道和子进程,但必须管理它们感觉太复杂了。
有什么好的方法可以让调用者count
检测到它的失败吗?
答案1
我认为读取count
进程替换会阻止您获取其返回状态。所以不要这样做。相反,请将结果存储在变量中,或使用管道。
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 }'
ifne
您可以使用from测试命令的输入是否为空更多实用程序或者其他方法。但既然您要通过管道连接到 awk,那么您不妨在已有的 awk 脚本中执行此操作。
如果需要从qstat
命令获取返回状态,可以将其作为额外的输入行提供给 awk。为了更容易解析,请安排最后一行具有唯一的格式。
{
qstat -tn1
echo exit_code = $?
} | awk '
…
/^exit_code = / { status = $3 }
END { if (status == 0) print Q, R }
'
答案2
这:
count ()
{
{ qstat -tn1 || echo "EPIC FAIL" } | awk '
BEGIN { R = 0; Q = 0; }
$10 == "R" { R++ }
$10 == "Q" { Q++ }
END { print R, Q }'
}
if read -r R Q < <(count)
...
如果qstat
成功,其输出将发送到awk
。如果qstat
返回非零状态,则文本“EPIC FAIL”将发送至awk
。
这只是一个例子。将 echo 替换为您可以在内部awk
或使用处理的适当内容if read
。