我試圖透過解析腳本的輸出來檢查正在運行和排隊的 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
。