Co oznacza $$ w powłoce?

143

Czytałem kiedyś, że jednym ze sposobów uzyskania unikalnej nazwy pliku w powłoce dla plików tymczasowych jest użycie podwójnego znaku dolara ( $$). To faktycznie daje liczbę, która zmienia się od czasu do czasu ... ale jeśli wywołujesz ją wielokrotnie, zwraca tę samą liczbę. (Rozwiązaniem jest po prostu wykorzystanie czasu).

Jestem ciekawy, co $$tak naprawdę jest i dlaczego miałoby to być sugerowane jako sposób na generowanie unikalnych nazw plików.

Koteczek
źródło

Odpowiedzi:

102

W Bash $$jest identyfikatorem procesu, jak zauważono w komentarzach, używanie go jako nazwy pliku tymczasowego nie jest bezpieczne z różnych powodów.

W przypadku tymczasowych nazw plików użyj mktemppolecenia.

Joe Skora
źródło
35
Dla ludzi, którzy tylko patrzą na pierwszą odpowiedź, $$ nie jest w porządku nawet dla pojedynczego pliku, jeśli zapisuje się do publicznie zapisywalnego katalogu (np. / Tmp). Łatwo jest zaśmiecać / tmp dowiązaniami symbolicznymi, które spowodują, że twój skrypt napisze gdzieś niepożądany. mktemp jest znacznie lepszy.
Chris Jester-Young,
4
Tak, użycie $$ spowoduje paskudną lukę w zabezpieczeniach. Nie rób tego.
emk
7
Albo osoba, która zadała pytanie powinna ustawić wyżej ocenioną odpowiedź poniżej jako zaakceptowaną odpowiedź ...
jtimberman
6
Dodaję „dolara” na SEO.
Antoine,
1
Jeśli $$ po prostu wypisze pid, jak może być „niebezpieczne”? Dziura w zabezpieczeniach jest spowodowana złym projektem i brakiem użycia PID w nazwie pliku tmp ... Jeśli tak bardzo zależy Ci na integralności wyjścia, które trafia do tmp, może nie powinieneś nawet go tam umieszczać? $$ nie spowoduje dziury w zabezpieczeniach, brak przewidywania
niken
113

$$to identyfikator procesu (PID) w bash. Używanie $$jest złym pomysłem, ponieważ zazwyczaj tworzy sytuację wyścigu i umożliwia atakującemu obalenie skryptu powłoki. Zobacz na przykład wszystkie osoby, które utworzyły niezabezpieczone pliki tymczasowe i musiały publikować porady dotyczące bezpieczeństwa.

Zamiast tego użyj mktemp. Strona człowiek Linux dla mktemp jest doskonała. Oto przykładowy kod z tego:

tempfoo=`basename $0`
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
echo "program output" >> $TMPFILE
emk
źródło
3
Dzięki. Ta mktempopcja -tjest teraz przestarzała (myślę, że z powodu problemów z char -). Użyj mktemp ${tempfoo}.XXXXXXtych dni . Pozwolę sobie zaktualizować Twój post.
Sebastian,
1
Należy również pamiętać, że lewy znacznik jest przestarzały , więc użyj TMPFILE=$(mktemp)zamiast niego.
Michael Kopp,
20

$$ jest identyfikatorem bieżącego procesu.

Krzemień
źródło
7

Każdy proces w systemie operacyjnym podobnym do UNIX ma (tymczasowo) unikalny identyfikator, PID. Żadne dwa procesy działające w tym samym czasie nie mogą mieć tego samego PID, a $$ odnosi się do PID instancji bash, w której działa skrypt.

Nie jest to w zasadzie unikalny identyfikator w tym sensie, że nigdy nie zostanie ponownie użyty (w rzeczywistości PID są ponownie wykorzystywane). To, co daje, to taka liczba, że ​​jeśli inna osoba uruchomi twój skrypt, otrzyma inny identyfikator, podczas gdy twój nadal działa. Gdy twój umrze, PID może zostać przetworzony, a ktoś inny może uruchomić twój skrypt, uzyskać ten sam PID i uzyskać taką samą nazwę pliku.

W związku z tym naprawdę rozsądne jest stwierdzenie, że „$$ podaje taką nazwę pliku, że jeśli ktoś inny uruchomi ten sam skrypt, mimo że moja instancja nadal działa, otrzyma inną nazwę”.

Adam Wright
źródło
5

$$ to Twój PID. Tak naprawdę nie generuje unikalnej nazwy pliku, chyba że jesteś ostrożny i nikt inny nie robi tego dokładnie w ten sam sposób.

Zwykle tworzysz coś takiego jak / tmp / myprogramname $$

Jest tak wiele sposobów, aby to przerwać, a jeśli piszesz w lokalizacjach, w których inni ludzie mogą pisać, w wielu systemach operacyjnych nie jest zbyt trudno przewidzieć, jaki PID będziesz mieć i spieprzyć - wyobraź sobie, że biegniesz jako root i tworzę / tmp / yourprogname13395 jako dowiązanie symboliczne wskazujące na / etc / passwd - i piszesz do niego.

To zła rzecz, którą należy robić w skrypcie powłoki. Jeśli zamierzasz użyć do czegoś pliku tymczasowego, powinieneś użyć lepszego języka, który przynajmniej pozwoli ci dodać flagę „wyłączność” do otwierania (tworzenia) pliku. Wtedy możesz być pewien, że nie walczysz o coś innego.

JBB
źródło
3

$$ to pid bieżącego procesu powłoki. Nie jest to dobry sposób na generowanie unikalnych nazw plików.

leif
źródło
3

$$ to pid (identyfikator procesu) interpretera powłoki, na którym działa twój skrypt. W tej chwili jest inny dla każdego procesu uruchomionego w systemie, ale z czasem pid zawija się, a po wyjściu ostatecznie będzie inny proces z tym samym pid. Tak długo, jak działasz, pid jest unikalny dla ciebie.

Z powyższej definicji powinno być oczywiste, że bez względu na to, ile razy użyjesz znaku $$ w skrypcie, zwróci on tę samą liczbę.

Możesz użyć np. /Tmp/myscript.scratch.$$ jako pliku tymczasowego do rzeczy, które nie muszą być wyjątkowo niezawodne lub bezpieczne. Dobrą praktyką jest usuwanie takich plików tymczasowych na końcu skryptu, używając na przykład polecenia trap:

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

źródło
2

Jest to identyfikator procesu bash. Żadne współbieżne procesy nigdy nie będą miały tego samego PID.


źródło
2

$$ jest identyfikatorem procesu powłoki, w której działa skrypt. Aby uzyskać więcej informacji, zobacz stronę podręcznika systemowego dla sh lub bash. Strony podręcznika można znaleźć albo używając wiersza poleceń "man sh", albo wyszukując w Internecie "shell manpage"

Shannon Nelson
źródło
2

Pozwólcie, że druga odpowiedź emk - nie używaj samego $$ $$ jako „wyjątkowego” czegokolwiek. W przypadku plików użyj mktemp. W przypadku innych identyfikatorów w tym samym skrypcie bash użyj opcji „$$$ (data +% s% N)”, aby uzyskać dość dużą szansę na unikalność.

 -k
Kevin Little
źródło
0

Możesz również pobrać nazwę użytkownika logowania za pomocą tego polecenia. Na przykład.

echo $(</proc/$$/login id). After that, you need to use getent command.
Obivan
źródło