Warum gibt $$ dieselbe ID wie der übergeordnete Prozess zurück?

159

Ich habe ein Problem mit Bash und weiß nicht warum.
Unter Shell gebe ich ein:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

"getpid" ist ein C-Programm zum Abrufen der aktuellen PID, wie:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

Was mich verwirrt ist:

  1. Ich denke, "(Befehl)" ist ein Unterprozess (habe ich Recht?), Und ich denke, seine PID sollte sich von seiner übergeordneten PID unterscheiden, aber sie sind gleich, warum ...
  2. Wenn ich mein Programm verwende, um pid zwischen Klammern anzuzeigen, ist die angezeigte pid anders, stimmt das?
  3. ist '$$' so etwas wie ein Makro?

Können Sie mir helfen?

Ruanhao
quelle
8
Beachten Sie, dass getpideine andere Prozess-ID angezeigt wird, selbst wenn sie nicht in einer Subshell ausgeführt wird.
Chepper
1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )zeigt, dass dies der Fall ist. Runde Klammern bilden eine Unterschale. Die Anweisungen können Variablenwerte ändern, und die übergeordnete Shell darf diese Änderungen nicht sehen. Dies wird als fork()Operation implementiert .
Ben

Antworten:

222

$$ist definiert, um die Prozess-ID des übergeordneten Elements in einer Subshell zurückzugeben. von der Manpage unter "Spezielle Parameter":

$ Wird zur Prozess-ID der Shell erweitert. In einer () Subshell wird die Prozess-ID der aktuellen Shell und nicht die Subshell erweitert.

In bash4 können Sie die Prozess-ID des Kindes mit abrufen BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
chepner
quelle
16
"parent" ist ein bisschen irreführend (zumindest für mich), es ist eigentlich die "Top Level" -Shell. Zum Beispiel: gibt echo $$; (echo $$; (echo $$))die gleiche PID dreimal wieder
Martin Bouladour
1
Richtig; Ich hätte sagen sollen, dass der Wert von einer übergeordneten Shell geerbt wird (die seinen Wert von ihrer übergeordneten Shell usw. geerbt hat ). Die Shell der obersten Ebene legt sie zunächst fest, anstatt von ihrem übergeordneten Prozess (ohne Shell) zu erben.
Chepner
$ Expands to the process ID of the shelltut es das? echo $gibt nur das wörtliche $ wieder.
Alexander Mills
@ AlexanderMills Nun ja; $allein ist keine Parametererweiterung. Die Manpage bezieht sich auf den Namen des speziellen Parameters $; es wird nicht behauptet, dass sich $allein ausdehnt.
Chepner
Ok, ich habe ehrlich gesagt keine Ahnung, was das bedeutet, aber es echo $BASHPIDfunktioniert in Bash 4 und 5 (aber nicht in Version 3.2.57 unter MacOS)
Alexander Mills
81

Sie können eine der folgenden Optionen verwenden.

  • $! ist die PID des letzten Hintergrundprozesses.
  • kill -0 $PID prüft, ob es noch läuft.
  • $$ ist die PID der aktuellen Shell.
Craken
quelle
2
Sollte die zweite Kugel nicht sein, kill -0 $!wenn wir über Hintergrundprozesse sprechen? PIDist standardmäßig auf nichts eingestellt.
Isaac Freeman
26
  1. Klammern rufen eine Unterschale in Bash auf . Da es sich nur um eine Unterschale handelt, hat sie möglicherweise dieselbe PID - abhängig von der Implementierung.
  2. Das von Ihnen aufgerufene C-Programm ist ein separater Prozess, der über eine eigene eindeutige PID verfügt - unabhängig davon, ob es sich in einer Subshell befindet oder nicht.
  3. $$ist ein Alias ​​in Bash zur aktuellen Skript-PID . Sehen Sie die Unterschiede zwischen $$und $BASHPIDhier und direkt darüber die zusätzliche Variable, $BASH_SUBSHELLdie die Verschachtelungsebene enthält.
Niels Keurentjes
quelle
4

Versuchen Sie, getppid()ob Ihr C-Programm die PID Ihrer Shell drucken soll.

Alex
quelle
2

Wenn Sie fragen würden, wie Sie die PID eines bekannten Befehls erhalten, würde dies ungefähr so ​​aussehen:

Wenn Sie den folgenden Befehl ausgegeben haben #Der ausgegebene Befehl war ***

dd if = / dev / diskx von = / dev / disky


Dann würden Sie verwenden:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

Was hier passiert, ist, dass alle benötigten eindeutigen Zeichen an ein Feld weitergeleitet werden und dieses Feld mit wiederholt werden kann

Echo $ PIDs

Don-Pierre Halfaway
quelle
1

Dies ist ein einzigartiger Weg, um die richtige PID zu erhalten

pid=$(cut -d' ' -f4 < /proc/self/stat)

gleich schön gearbeitet für sub

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

Ausgabe prüfen

pid = 8099
8099 != 8100
ARTEM LAPKIN
quelle
Gute Idee, aber bringt Ihnen das nicht die PID der Gabel, die die Schale ausgeführt hat, um die Ausgabe des Schnitts zu erfassen? Wenn ich es zweimal ausführe, einmal mit echo $ (...) und einmal ohne, bekomme ich unterschiedliche Antworten.
Martin Dorey