In einem Bash-Skript möchte ich die Standardausgabe eines langen Befehls zeilenweise erfassen, damit sie analysiert und gemeldet werden können, während der erste Befehl noch ausgeführt wird. Das ist die komplizierte Art, wie ich es mir vorstellen kann:
# Start long command in a separated process and redirect stdout to temp file
longcommand > /tmp/tmp$$.out &
#loop until process completes
ps cax | grep longcommand > /dev/null
while [ $? -eq 0 ]
do
#capture the last lines in temp file and determine if there is new content to analyse
tail /tmp/tmp$$.out
# ...
sleep 1 s # sleep in order not to clog cpu
ps cax | grep longcommand > /dev/null
done
Ich würde gerne wissen, ob es einen einfacheren Weg gibt.
BEARBEITEN:
Um meine Frage zu klären, werde ich dies hinzufügen. Der longcommand
zeigt seinen Status zeilenweise einmal pro Sekunde an. Ich möchte die Ausgabe vor dem longcommand
Abschluss abfangen .
Auf diese Weise kann ich möglicherweise die töten, longcommand
wenn es nicht die Ergebnisse liefert, die ich erwarte.
Ich habe versucht:
longcommand |
while IFS= read -r line
do
whatever "$line"
done
Aber whatever
(zB echo
) wird erst ausgeführt, nachdem longcommand
abgeschlossen wurde.
Antworten:
Leiten Sie den Befehl einfach in eine
while
Schleife. Es gibt eine Reihe von Nuancen, aber im Grunde (inbash
oder jeder POSIX-Shell):Das andere Hauptproblem
IFS
ist, wenn Sie versuchen, Variablen innerhalb der Schleife zu verwenden, sobald diese beendet ist. Dies liegt daran, dass die Schleife tatsächlich in einer Sub-Shell (nur einem anderen Shell-Prozess) ausgeführt wird, von der aus Sie nicht auf Variablen zugreifen können. du kannst tun:Hauke des Beispiel der Einstellung
lastpipe
inbash
einer anderen Lösung.Aktualisieren
Um sicherzustellen, dass Sie die Ausgabe des Befehls "wie sie ausgeführt wird" verarbeiten, können Sie
stdbuf
den Prozess so einstellenstdout
, dass er zeilengepuffert wird.Dadurch wird der Prozess so konfiguriert, dass jeweils eine Zeile in die Pipe geschrieben wird, anstatt die Ausgabe intern in Blöcke zu puffern. Beachten Sie, dass das Programm diese Einstellung intern selbst ändern kann. Ein ähnlicher Effekt kann mit
unbuffer
(einem Teil vonexpect
) oder erzielt werdenscript
.stdbuf
ist auf GNU- und FreeBSD-Systemen verfügbar, wirkt sich nur auf diestdio
Pufferung aus und funktioniert nur für nicht-setuid- und nicht-setgid-Anwendungen, die dynamisch verknüpft sind (da ein LD_PRELOAD-Trick verwendet wird).quelle
IFS=
wird nicht benötigtbash
, das habe ich nach dem letzten mal überprüft.line
(in diesem Fall wird das Ergebnis$REPLY
ohne die vorangestellten und nachfolgenden Leerzeichen eingefügt). Versuchen Sie:echo ' x ' | bash -c 'read line; echo "[$line]"'
und vergleichen Sie mitecho ' x ' | bash -c 'IFS= read line; echo "[$line]"'
oderecho ' x ' | bash -c 'read; echo "[$REPLY]"'
quelle