Ich versuche, die Anzahl der laufenden und in der Warteschlange befindlichen PBS-Jobs zu überprüfen, indem ich die Ausgabe qstat -tn1
eines bash
Skripts analysiere. Bisher hat das funktioniert:
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)
...
Ich sehe jedoch, dass dies qstat
gelegentlich aus unbekannten Gründen fehlschlägt. In diesem Fall wird nichts stdout
und eine Fehlermeldung an ausgegeben stderr
und das System wird mit einem Status ungleich Null beendet (ziemlich normal). Allerdings awk
weiß es nicht, dass der qstat
Fehler aufgetreten ist, und druckt fröhlich 0 0
für die leere Eingabe, die es erhalten hat. Dann read
weist es beiden 0 zu R
und Q
ohne zu wissen, dass dies qstat
tatsächlich fehlgeschlagen ist.
R
Ich muss undQ
imBEGIN
Block des Skripts mit 0 initialisierenawk
, da möglicherweise keine laufenden Prozesse oder keine in die Warteschlange gestellten Prozesse vorhanden sind und ich0
für die Anzahl dieser Prozesse und nicht nur eine leere Zeichenfolge drucken muss.- Ich könnte dies tun , wodurch das Beenden mit einem Status ungleich Null
set -o pipefail
möglich wäre , der Beendigungsstatus jedoch nicht angezeigt wird und das Programm trotzdem ausgeführt wird und für die leere Eingabe druckt .count
read
awk
0 0
- Ich könnte es mit einer benannten Pipe und Unterprozessen versuchen, aber deren Verwaltung erscheint mir zu kompliziert und übertrieben.
Gibt es eine gute Möglichkeit, dem Anrufer count
das Erkennen des Fehlers zu ermöglichen?
Antwort1
Ich denke, das Einlesen count
einer Prozesssubstitution verhindert, dass Sie deren Rückgabestatus erhalten. Tun Sie es also nicht. Speichern Sie das Ergebnis stattdessen in einer Variablen oder verwenden Sie eine Pipe.
count=$(count)
if [ $? -eq 0 ]; then
read -r R Q <<<"$count"
…
oder
set -o pipefail
if count | { read -r R Q; … }
Eine andere Möglichkeit besteht darin, die Variable zu verwenden, PIPESTATUS
um den Rückgabestatus des ersten Befehls zu überprüfen.
count=$(qstat -tn1 | awk …)
if ((${PIPESTATUS[0]} == 0)); then
read P Q
…
Alternativ können Sie dafür sorgen, dass awk etwas Bestimmtes ausgibt (z. B. nichts), wenn seine Eingabe leer ist.
awk '
BEGIN { R = 0; Q = 0; }
$10 == "R" { R++ }
$10 == "Q" { Q++ }
END { if (NR) print R, Q }'
Ob die Eingabe eines Befehls leer ist, können Sie testen mit ifne
frommehrutilsoderandere Methoden. Aber da Sie eine Weiterleitung in awk durchführen, können Sie dies auch gleich in dem awk-Skript tun, das Sie bereits haben.
Wenn Sie den Rückgabestatus des Befehls benötigen qstat
, können Sie ihn als zusätzliche Eingabezeile an awk übermitteln. Sorgen Sie zur einfacheren Analyse dafür, dass die letzte Zeile ein eindeutiges Format hat.
{
qstat -tn1
echo exit_code = $?
} | awk '
…
/^exit_code = / { status = $3 }
END { if (status == 0) print Q, R }
'
Antwort2
Das:
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)
...
Bei qstat
Erfolg wird die Ausgabe an gesendet awk
. Wenn qstat
ein Status ungleich Null zurückgegeben wird, wird der Text „EPIC FAIL“ an gesendet awk
.
Dies ist nur ein Beispiel. Ersetzen Sie das Echo durch etwas Passendes, das Sie innerhalb awk
oder mit verarbeiten können if read
.