Ich suche nach einer Möglichkeit, die Ausgabe eines Befehls programmgesteuert zu überwachen, bis eine bestimmte Zeichenfolge beobachtet wird, und dann zu beenden. Dies ist dieser Frage sehr ähnlich , aber anstatt eine Datei zu verfolgen, möchte ich einen Befehl verfolgen.
So etwas wie:
watch -n1 my_cmd | grep -m 1 "String auf der Suche nach"
(Aber das funktioniert bei mir nicht.)
UPDATE: Ich muss klarstellen, dass 'my_cmd' keinen fortlaufenden Text ausgibt, sondern wiederholt aufgerufen werden muss, bis die Zeichenfolge gefunden wurde (weshalb ich an den Befehl 'watch' dachte). In dieser Hinsicht ähnelt 'my_cmd' vielen anderen Unix-Befehlen wie: ps, ls, lsof, last usw.
tail -f
ein Programm genauso wie eine Datei auszugeben ... irre ich mich?Antworten:
Benutze eine Schleife:
Stattdessen
:
können Siesleep 1
(oder 0.2) verwenden, um die CPU zu entlasten.Die Schleife wird ausgeführt, bis grep die Zeichenfolge in der Ausgabe des Befehls findet.
-m 1
bedeutet "eine Übereinstimmung ist genug", dh grep stoppt die Suche, nachdem es die erste Übereinstimmung gefunden hat.Sie können auch verwenden,
grep -q
was auch beendet wird, nachdem Sie die erste Übereinstimmung gefunden haben, ohne jedoch die übereinstimmende Zeile auszudrucken.quelle
grep -q
was eine andere Option ist. grep wird beendet, nachdem der String gefunden wurde.!
negiert den Exit-Code der Befehlspipelinegrep -m 1
Wird beendet, wenn eine Zeichenfolge gefunden wirdwatch -e
Gibt zurück, wenn ein Fehler aufgetreten istDies kann jedoch verbessert werden, um tatsächlich die übereinstimmende Linie anzuzeigen, die bisher weggeworfen wurde.
quelle
watch
Befehl (CentOS) hat keine-e
Flagge (was eigentlich keine Rolle spielen sollte). Noch wichtiger ist jedoch, dass die Überwachung nach dem Auffinden der Zeichenfolge weiterläuft und nicht beendet wird. Es scheint, dass wenn es beendet wirdgrep -m
, es nur tötetmy_cmd
, aber nicht beendet wirdwatch
.tee
dafür anstellen, aber dies führt zu einem irreführenden Zeilenumbruch. Ich weiß momentan nicht, wie ich das umgehen soll:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
watch
hört pflichtbewusst auf zu schauen, wenn die Zeichenfolge gefunden wird, wird jedoch erst beendet, wenn Sie eine Taste drücken. So nah.Für diejenigen, die ein Programm haben, das kontinuierlich nach stdout schreibt, ist alles, was Sie tun müssen, es an grep mit der Option 'single match' weiterzuleiten. Sobald grep die passende Zeichenfolge gefunden hat, wird es beendet, wodurch stdout für den Prozess geschlossen wird, der an grep weitergeleitet wird. Dieses Ereignis sollte natürlich dazu führen, dass das Programm ordnungsgemäß beendet wird , solange der Prozess erneut schreibt .
Was passieren wird, ist, dass der Prozess ein SIGPIPE erhält, wenn er versucht, nach dem Beenden von grep auf closed stdout zu schreiben. Hier ist ein Beispiel mit Ping, das andernfalls auf unbestimmte Zeit ausgeführt würde:
Dieser Befehl stimmt mit dem ersten erfolgreichen 'pong' überein und wird dann beendet, wenn das nächste Mal
ping
versucht wird, nach stdout zu schreiben.Jedoch,
Es ist nicht immer garantiert, dass der Prozess wieder auf stdout schreibt und daher möglicherweise kein SIGPIPE ausgelöst wird (dies kann z. B. beim Verfolgen einer Protokolldatei passieren). Die beste Lösung für dieses Szenario ist das Schreiben in eine Datei. Bitte kommentieren Sie, wenn Sie glauben, dass Sie sich verbessern können:
Aufschlüsselung:
tail -f log_file & echo $! > pid
- legt eine Datei an, hängt den Prozess an den Hintergrund an und speichert die PID ($!
) in einer Datei. Ich habe versucht, die PID stattdessen in eine Variable zu exportieren, aber es scheint, als gäbe es eine Wettlaufsituation zwischen hier und dem Zeitpunkt, an dem die PID erneut verwendet wird.{ ... ;}
- Gruppieren Sie diese Befehle, damit wir die Ausgabe an grep leiten können, während der aktuelle Kontext beibehalten wird. (Hilft beim Speichern und Wiederverwenden von Variablen, konnte diesen Teil jedoch nicht zum Laufen bringen.)|
- Leiten Sie den Abstand der linken Seite zum Abstand der rechten Seitegrep -m1 "find_me"
- Finden Sie die Zielzeichenfolge&& kill -9 $(cat pid)
- Erzwinge das Beenden (SIGKILL) destail
Prozesses nach demgrep
Beenden, sobald der passende String gefunden wurde&& rm pid
- Entfernen Sie die von uns erstellte Dateiquelle
Wenn
tail
die+1f
Syntax nicht unterstützt wird , versuchen Sie estail -f -n +1
. (Das-n +1
weist es an, am Anfang zu beginnen.tail -f
Standardmäßig beginnt es mit den letzten 10 Ausgabezeilen.)quelle
Hängen Sie das Ergebnis Ihrer Programmaufrufe an eine Datei an. Dann
tail -f
diese Datei. So sollte es funktionieren ... hoffe ich.Wenn Sie das Programm erneut aufrufen, müssen Sie die Datei löschen oder etwas Kauderwelsch anhängen, damit sie nicht gleich wieder mit dem übereinstimmt, wonach Sie gesucht haben.
quelle