2016-11-17 4 views
4

Ich habe ein bash Skript erstellt, das gestartete Instanzen von sich selbst zählt.Bash Skript zählt Instanzen von sich falsch

Hier ist es (in diesem Beispiel zeige ich die Instanzen, anstatt sie mit wc -l mitgezählt):

#!/bin/bash 
nb=`ps -aux | grep count_itself.sh` 
echo "$nb" 
sleep 20 

(Natürlich, mein Skript gestattet count_itself.sh)

Nach dessen Ausführung erwarte ich, dass es zwei Zeilen zurück, aber es gibt drei:

[email protected]:/# ./count_itself.sh 
root 16225 0.0 0.0 12400 1176 pts/0 S+ 11:46 0:00 /bin/bash ./count_itself.sh 
root 16226 0.0 0.0 12408 564 pts/0 S+ 11:46 0:00 /bin/bash ./count_itself.sh 
root 16228 0.0 0.0 11740 932 pts/0 S+ 11:46 0:00 grep count_itself.sh 

auf sie mit der & Flagge Ausführung (dh im Hintergrund, und die ps -aux Bit manuell ausgeführt wird, gibt es zwei, das ist, was ich will:

[email protected]:/# ./count_itself.sh & 
[1] 16233 
[email protected]:/# ps -aux | grep count_itself.sh 
root  16233 0.0 0.0 12408 1380 pts/0 S 11:48 0:00 /bin/bash ./count_itself.sh 
root  16240 0.0 0.0 11740 944 pts/0 S+ 11:48 0:00 grep --color=auto count_itself.sh 

Meine Frage ist: Warum wird die ps -aux Ausführung im Skript zurückgeben eine Zeile mehr als erwartet?

Oder mit anderen Worten, warum ist der Prozess mit der ID 16226 in meinem ersten Beispiel erstellt?

EDIT (wie die meisten Leute scheinen meine Frage falsch zu verstehen):

Ich frage mich, warum die bash Ausführung zwei Instanzen von /bin/bash ./count_itself.sh zurückzugibt, nicht, warum es grep count_itself.sh zurückzugibt.

EDIT 2:

Und natürlich, ich bin auf der Suche nach einem Weg, um dieses Verhalten zu vermeiden und das Skript haben /bin/bash ./count_itself.sh Rückkehr nur einmal.

+2

'\' ps -aux | grep count_itself.sh wird in einer Sub-Shell, d. h. in einem Sub-Prozess, ausgeführt. Auf diese Weise wird die Shell, die das Skript ausführt, gegabelt, und das Kind führt dann die Datei "ps -aux |" aus grep count_itself.sh' Befehl. – Leon

+0

Ich schlage vor: nb = 'ps -aux | grep [c] ount_itself.sh – Cyrus

+2

wenn Sie 'ps -aux | ausführen grep count_itself.sh' dein grep zählt es wie eine Instanz von count_itself. Sie müssen Ihre Regex – Stargateur

Antwort

1

schließlich einen Weg gefunden, wenn auch eine hässliche, teilweise von der Frage inspiriert @TomFenech verknüpft in seiner answer:

#!/bin/bash 
nb=$(ps f | grep '[c]ount_itself.sh' | grep -v ' \\_') 
echo "$nb" 
sleep 20 

Ausführung:

[email protected]:/# ./count_itself.sh 
17725 pts/1 S+  0:00 \_ /bin/bash ./count_itself.sh 

Ausführung mit einem bereits in bg ausgeführt wird:

[email protected]:/# ./count_itself.sh & 
[1] 17733 
[email protected]:/# ./count_itself.sh 
17733 pts/1 S  0:00 \_ /bin/bash ./count_itself.sh 
17739 pts/1 S+  0:00 \_ /bin/bash ./count_itself.sh 

Erklärung (von dem, was ich verstanden habe):

  • ps f kehrt die Baum der aktiven Prozesse
  • grep '[c]ount_itself.sh' schränkt den vorherigen Befehl nur zeigt Beispiele von count_itself.sh

Returns

17808 pts/1 S+  0:00 \_ /bin/bash ./count_itself.sh 
17809 pts/1 S+  0:00  \_ /bin/bash ./count_itself.sh 
  • grep -v ' \\_' schließt Zeilen 4 Räume (Äquivalent eines TAB) enthält, wird dann \_, die
  • Unterprozesse entsprechen
4

Dies ist ein Standardproblem mit grep in der Ausgabe ps.

Eine Lösung ist es, einige eckigen Klammern um ein Zeichen

nb=$(ps -aux | grep '[c]ount_itself.sh') 

Dies bedeutet, dass Ihre grep Instanz nicht selbst übereinstimmt, da der Name des Prozesses mit seinen Argumenten enthält eckige Klammern, aber das Muster hinzuzufügen, dass es stimmt nicht überein.

Wie in den Kommentaren erwähnt, sollten Sie doppelte Anführungszeichen um Ihre Variablen verwenden, um Leerzeichen zu erhalten.

Der Grund, warum Sie scheinen, zwei Instanzen der gleichen Shell in Ihren Ergebnissen zu haben, ist, dass die Befehlsersetzung innerhalb einer Untershell ausgeführt wird. Weitere Informationen zum Anzeigen des übergeordneten Prozesses finden Sie unter this question.

+0

Ich habe meine Frage bearbeitet, gibt es eine Möglichkeit, dass die 'ps -aux' die Subshell-Ausführung nicht zurückgibt? – roberto06

+0

Bearbeitet, um einen Link hinzuzufügen. –

2

Prozesssubstitution erfordert, dass die übergeordnete Shell eine Subshell startet, d. H. Die angegebenen Befehle in einer untergeordneten Shell ausgibt und ausführt. Dies ist erforderlich, damit die übergeordnete Shell nicht von Änderungen an der Umgebung (Variablen, aktuelles Arbeitsverzeichnis, Traps) betroffen ist, die das Skript in $(...) einfügt.

Beispiel:

$ cat test.sh 
#!/bin/bash 

a=1 
b="$(a=2; echo abc)" 
echo "a=$a" 
echo "b=$b" 
$ ./test.sh 
a=1   # Note that the variable 'a' preserved its value 
b=abc 

Es ist als Ergebnis gabeln, dass Sie eine zusätzliche Instanz des Skripts sehen.

Ich glaube nicht, dass es möglich ist, diese unerwünschten Prozesse zuverlässig aus Ihrer Ausgabe zu eliminieren, da ein Skript im Prinzip eine andere Instanz von sich selbst starten kann (die als Subprozess läuft), und Sie können nicht unterscheiden zwischen diesen beiden Fällen.

Eine Hacky-Lösung besteht darin, das Skript an einem bestimmten Ort (z. B. in /tmp/your_script_name) eine PID-Datei beim Aufruf erstellen zu lassen und sie bei Beendigung zu entfernen.

2

schlage ich nächsten Weg:

alle Verfahren ausschließen, dass Eltern sind selbst:

ps --pid $$ -N -a | grep count_itself.sh 

Das bedeutet, zeigt alle Befehle, die Eltern nicht selbst (so ausschließt dies Ihren grep Prozess und Gabel Prozess ausführen Gegen Satz)

+0

Es gibt immer noch zwei Zeilen mit nur dem '--pid $$' -Flag, und es gibt keine Echos, wenn ich das '-N'-Flag hinzufüge. Ich bin auf der Suche nach einem Ergebnis irgendwo in der Mitte: P – roberto06

+0

Ich denke, wenn mit "-N" Flag ist nichts zurück, es ist, weil Sie die einzige Instanz ausgeführt werden, möglicherweise, wenn Sie selbst zählen möchten, können Sie 1 hinzufügen zu dem Ergebnis. –