Was bedeutet $$ in der Shell?


143

Ich habe einmal gelesen, dass eine Möglichkeit, einen eindeutigen Dateinamen in einer Shell für temporäre Dateien zu erhalten, darin besteht, ein doppeltes Dollarzeichen ( $$) zu verwenden. Dies führt zu einer Nummer, die von Zeit zu Zeit variiert. Wenn Sie sie jedoch wiederholt anrufen, wird dieselbe Nummer zurückgegeben. (Die Lösung besteht darin, nur die Zeit zu nutzen.)

Ich bin gespannt, was $$eigentlich ist und warum dies vorgeschlagen wird, um eindeutige Dateinamen zu generieren.

Antworten:


102

In Bash $$ist die Prozess-ID, wie in den Kommentaren angegeben, aus verschiedenen Gründen nicht sicher als temporärer Dateiname zu verwenden.

Verwenden Sie für temporäre Dateinamen den mktempBefehl.


35
Für Leute, die sich nur die Top-Antwort ansehen, ist $$ nicht einmal für eine einzelne Datei in Ordnung, wenn sie in ein öffentlich beschreibbares Verzeichnis (z. B. / tmp) schreiben. Es ist einfach, / tmp mit Symlinks zu verunreinigen, die dazu führen, dass Ihr Skript an eine unerwünschte Stelle schreibt. mktemp ist viel besser.
Chris Jester-Young

4
Ja, die Verwendung von $$ führt zu einer bösen Sicherheitslücke. Tu es nicht.
emk

7
Oder die Person, die die Frage gestellt hat, sollte die höher bewertete Antwort unten als akzeptierte Antwort
festlegen

6
Ich füge "Dollar Dollar" für SEO hinzu.
Antoine

1
Wenn $$ nur die PID ausgibt, wie kann es dann "nicht sicher" sein? Eine Sicherheitslücke entsteht aufgrund eines schlechten Designs, bei dem keine PID im tmp-Dateinamen verwendet wird. Wenn Sie sich für die Integrität der Ausgabe von tmp interessieren, sollten Sie sie vielleicht gar nicht erst dort ablegen? $$ wird keine Sicherheitslücke verursachen, mangelnde Voraussicht wird
niken

113

$$ist die Prozess-ID (PID) in bash. Die Verwendung $$ist eine schlechte Idee, da dadurch normalerweise eine Race-Bedingung erstellt wird und Ihr Shell-Skript von einem Angreifer untergraben werden kann. Sehen Sie sich zum Beispiel all diese Personen an , die unsichere temporäre Dateien erstellt haben und Sicherheitshinweise ausgeben mussten.

Verwenden Sie stattdessen mktemp. Die Linux-Manpage für mktemp ist ausgezeichnet. Hier ist ein Beispielcode daraus:

tempfoo=`basename $0`
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
echo "program output" >> $TMPFILE

3
Vielen Dank. Die mktempOption -tist jetzt veraltet (ich denke wegen Problemen mit dem Zeichen -). Verwenden Sie mktemp ${tempfoo}.XXXXXXdiese Tage . Ich erlaube mir, Ihren Beitrag zu aktualisieren.
Sebastian

1
Bitte beachten Sie auch, dass der Backtick veraltet war. Verwenden Sie ihn TMPFILE=$(mktemp)stattdessen.
Michael Kopp


7

Jeder Prozess in einem UNIX-ähnlichen Betriebssystem hat eine (vorübergehend) eindeutige Kennung, die PID. Keine zwei Prozesse, die gleichzeitig ausgeführt werden, können dieselbe PID haben, und $$ bezieht sich auf die PID der Bash-Instanz, auf der das Skript ausgeführt wird.

Dies ist kein eindeutiger Identifikator in dem Sinne, dass er niemals wiederverwendet wird (tatsächlich werden PIDs ständig wiederverwendet). Sie erhalten eine Nummer, mit der eine andere Person, die Ihr Skript ausführt, eine andere Kennung erhält, während Ihre noch ausgeführt wird. Sobald Ihre stirbt, wird die PID möglicherweise recycelt, und jemand anderes führt möglicherweise Ihr Skript aus, erhält dieselbe PID und erhält denselben Dateinamen.

Daher ist es nur wirklich vernünftig zu sagen, dass "$$ einen Dateinamen angibt, sodass jemand anderes, der dasselbe Skript ausführt, während meine Instanz noch ausgeführt wird, einen anderen Namen erhält".


5

$$ ist Ihre PID. Es wird nicht wirklich ein eindeutiger Dateiname generiert, es sei denn, Sie sind vorsichtig und niemand anderes tut dies genauso.

Normalerweise erstellen Sie so etwas wie / tmp / myprogramname $$

Es gibt so viele Möglichkeiten, dies zu umgehen, und wenn Sie an Orte schreiben, an die andere Leute schreiben können, ist es für viele Betriebssysteme nicht allzu schwierig, vorherzusagen, welche PID Sie haben und herumdrehen werden - stellen Sie sich vor, Sie laufen als root und ich erstelle / tmp / yourprogname13395 als symlink auf / etc / passwd - und du schreibst hinein.

Dies ist eine schlechte Sache in einem Shell-Skript. Wenn Sie eine temporäre Datei für etwas verwenden möchten, sollten Sie eine bessere Sprache verwenden, mit der Sie zumindest das "exklusive" Flag zum Öffnen (Erstellen) der Datei hinzufügen können. Dann können Sie sicher sein, dass Sie nichts anderes überfallen.


3

$$ ist die PID des aktuellen Shell-Prozesses. Es ist keine gute Möglichkeit, eindeutige Dateinamen zu generieren.


3

$$ ist die PID (Prozess-ID) des Shell-Interpreters, der Ihr Skript ausführt. Es ist für jeden Prozess, der im Moment auf einem System ausgeführt wird, anders, aber im Laufe der Zeit wird die PID umgangen, und nach dem Beenden wird es irgendwann einen anderen Prozess mit derselben PID geben. Solange Sie ausgeführt werden, ist die PID für Sie eindeutig.

Aus der obigen Definition sollte ersichtlich sein, dass unabhängig davon, wie oft Sie $$ in einem Skript verwenden, dieselbe Zahl zurückgegeben wird.

Sie können z. B. /tmp/myscript.scratch.$$ als temporäre Datei für Dinge verwenden, die nicht besonders zuverlässig oder sicher sein müssen. Es wird empfohlen, solche temporären Dateien am Ende Ihres Skripts zu löschen, indem Sie beispielsweise den Befehl trap verwenden:

trap "echo 'Cleanup in progress'; rm -r $TMP_DIR" EXIT

2

Es ist die Prozess-ID des Bash-Prozesses. Kein gleichzeitiger Prozess wird jemals dieselbe PID haben.


2

Das $$ ist die Prozess-ID der Shell, in der Ihr Skript ausgeführt wird. Weitere Informationen finden Sie in der Manpage für sh oder bash. Die Manpages können entweder über eine Befehlszeile "man sh" oder durch Durchsuchen des Webs nach "Shell Manpage" gefunden werden.


2

Lassen Sie mich die Antwort von emk als Zweites verwenden - verwenden Sie $$ nicht als "einzigartiges" Objekt. Verwenden Sie für Dateien mktemp. Verwenden Sie für andere IDs innerhalb desselben Bash-Skripts "$$$ (Datum +% s% N)", um eine einigermaßen gute Chance auf Eindeutigkeit zu erhalten.

 -k

0

Über diesen Befehl können Sie auch den Benutzernamen für die Anmeldung abrufen. Z.B.

echo $(</proc/$$/login id). After that, you need to use getent command.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.