Kann $! Rennbedingungen verursachen, wenn sie in parallel laufenden Skripten verwendet werden?

8

Angenommen, ich habe mehrere Bash-Skripte, die parallel ausgeführt werden, mit Code wie dem folgenden:

#!/bin/bash

tail -f /dev/null &
echo "pid is "$!

Gibt $!mir garantiert die PID der neuesten Hintergrundaufgabe in diesem Skript oder ist es die aktuellste Hintergrundaufgabe weltweit? Ich bin nur neugierig, ob das Verlassen auf diese Funktion zu Rennbedingungen führen kann, wenn die zurückgegebene PID aus einem Prozess stammt, der in einem anderen Skript gestartet wurde.

Philraj
quelle

Antworten:

16

$!wird Ihnen garantiert die PID des Prozesses geben, in dem die Shell diesen tailBefehl ausgeführt hat. Shells haben einen einzelnen Thread. Jede Shell lebt in einem eigenen Prozess mit einem eigenen Satz von Variablen. Es gibt keine Möglichkeit , die $!von einer Schale wird undicht in einer anderen Schale, wie ein Shell - Variable in einer Schale Zuordnung wird nicht die Variable mit dem gleichen Namen in einer anderen Schale beeinflussen (wenn wir beiseite die festgelegten universellen Variablen der fishShell) .

Nun tail -f /dev/nullist ein Befehl, der auf unbestimmte Zeit läuft, aber für kurzlebige Befehle, die Note , da es nur eine begrenzte Anzahl von möglichem Prozess - IDs ist, Prozess - IDs zwangsläufig wiederverwendet am Ende wird.

Im:

true &
pid=$!

Das $pidenthält die ID des Prozesses, in dem die Shell ausgeführt truewurde. $pidWenn Sie dies jedoch verwenden, ist diese PID möglicherweise tot und bezieht sich möglicherweise auf einen anderen Prozess.

Stéphane Chazelas
quelle
3
Ja, ich war mir Ihres zweiten Punktes bewusst, und wenn Sie einen zuverlässigen Hintergrundprozessmanager erstellen möchten, müssen Sie eine Sprache verwenden, die garantiert, dass Sie genau wissen, wann ein untergeordneter Prozess beendet und seine PID in den Pool zurückgegeben wurde , die Shell-Skripte anscheinend nicht können, da sie untergeordnete Prozesse aggressiv ernten. Vielen Dank für die klare Erklärung.
Philraj
5
@philraj, in zsh können Sie Handler auf SIGCHLD installieren, die nach Beendigung asynchroner Jobs verarbeitet und dort $jobstate/$jobtextzur Überprüfung des Prozessstatus verwendet werden. Nicht ohne Rasse, da das Kind zum Zeitpunkt der Ausführung der Falle bereits geerntet ist, aber das bedeutet sehr kurze Rennfenster, in denen es sehr unwahrscheinlich ist, dass Pids bereits wiederverwendet werden.
Stéphane Chazelas