2016-07-09 5 views
0

Ich möchte die PID von Bash und markieren Sie es, wenn es in einer Textdatei ist (angenommen, es ist). Also, wenn ich schreibe dies in meinem Shell:Wie grep die Pidof Bash in einem Shell-Skript?

grep -o $(pidof bash) test.txt 

es nur funktioniert gut und gibt mir die gewünschte Ausgabe, die PID bash. Warum wird dieses Skript nicht funktioniert:

#!/bin/bash 
PID=$(grep -o $(pidof bash) test.txt) 
echo $PID 

erhalte ich nur ein paar Zeilen mit:

grep: xxx: Datei oder das Verzeichnis nicht

gefunden

xxx Zufallszahlen sind, aber normalerweise ist der letzte derjenige, den ich suche.

Wie erreiche ich das und warum funktioniert das obige nicht?

Hat das etwas mit dem Erstellen eines neuen Prozesses durch die Shell zu tun, wenn grep im Skript aufgerufen wird?

Vielen Dank.

+1

'$ BASH_PID' ist das richtige Werkzeug oder' $$ '(abhängig davon, welche Shell-PID Sie haben wollen - die Parent-Shell oder die Subshell, die mit' $() 'gestartet wurde). –

+0

... 'pidof' ist im Allgemeinen ein Werkzeug, das man am besten vermeidet, es sei denn, man kann keinen besseren Weg finden, einen bestimmten Prozess zu identifizieren - irgendein System wird * viele * Bash-Instanzen haben, die zu einer bestimmten Zeit laufen. –

Antwort

1

Wenn Sie in Ihrem Shell-Skript pidof ausführen, werden mindestens zwei Instanzen von bash ausgeführt, sodass mehrere Zahlen zurückgegeben werden. Die Art, wie grep entworfen wird, kann nur nach einem Muster auf einmal suchen, so dass die erste Zahl als Muster interpretiert wird und die anderen Zahlen fälschlicherweise als Datei- oder Verzeichnisnamen interpretiert werden.

Ich bin nicht sicher, welche bash PID Sie kümmern uns um, aber eine Lösung ist so etwas wie grep, head zu verwenden, oder tail die Ausgabe von pidof zu filtern, um nur Sie eine Nummer. Eine andere Lösung besteht darin, die spezielle Variable $$ zu verwenden, bei der es sich um die PID der Bash-Instanz handelt, die sie auswertet.

In Zukunft können Sie dies besser für sich selbst debuggen. Zum Debuggen, würde ich, indem Sie diesen Befehl in Ihrem Skript starten, genau zu sehen, was Argumente zu grep geben werden:

echo grep -o $(pidof bash) test.txt 
+0

'$$' ist nicht * ziemlich * was Sie es als beschreiben - wenn Sie eine Subshell haben, '' '' '' expandiert zu der PID der Eltern-Shell, also würden Sie eigentlich '$ BASH_PID' stattdessen wollen, wenn das Ziel ist um diese Subshell zu identifizieren. –

+0

Echo ist auch kein großartiges Werkzeug. Ich würde vorschlagen 'printf'% q 'grep -o $ (pidof bash) test.txt; echo' - so übermittelst du die Dinge wörtlich, so dass 'printf'% q 'grep -o "$ (pidof bash)" test.txt; echo' würde anders aussehen, während mit dem 'echo' die Fixierung der Anführungszeichen (während sie das tatsächliche Verhalten stark verändert) keinen sichtbaren Effekt auf die Ausgabe hat. –

+0

'set -x' ist eine andere vorzuziehende Alternative, ein bisschen weniger ausführlich als die ganze' printf% q' Mund voll. 'set -x' bringt die Shell in den Debug-Modus, wo sie jeden Befehl vor der Ausführung druckt, bis sie mit' set -x' ausgeschaltet wird, und druckt sie so aus, dass Zitate, Whitespace und anderer Inhalt weggelassen werden 'echo' explizit *. –

1

ich nicht pidof haben, so gehe ich davon aus, dass es ein Äquivalent zu pgrep -v ist, Drucken einer Liste von PIDs, eine auf jeder Zeile, mit einer neuen Zeile zwischen ihnen.

Wenn das so ist, bedenken Sie:

egrep -o "$(pgrep -v bash | tr '\n' '|')" test.txt 

wird angenommen, dass die Ausgabe von pgrep -v bash ist:

123 
456 
789 

Ihre ursprüngliche Code würde dies tun:

egrep -o 123 456 789 test.txt 

... Suche nach 123 in einer Datei mit dem Namen 456, in eine Datei mit dem Namen 789 und in einer Datei mit dem Namen test.txt.Jetzt


, zu vergleichen, zu dem, was passiert, wenn Sie, dass Leerzeichen mit Rohr Symbole ersetzen:

egrep -o "123|456|789" test.txt 

... wie ausgeführt durch die Pipeline weiter oben in dieser Frage vorgeschlagen ist genau das, was Sie suchen. (Übrigens sind die Zitate hier rein syntaktisch - das heißt, sie werden von der Shell konsumiert, wenn sie verstehen, wie Dinge geparst werden und nicht an übergeben werden).


Das heißt, wenn Sie für den aktuellen bash verwenden entweder $$ (für die übergeordnete PID der aktuellen Shell) oder $BASH_PID (für die aktuelle Shell selbst selbst wenn es sich um eine Sub-Shell ist willkommen), anstatt so ungenau ein Werkzeug wie pgrep oder pidof zu verwenden.