Apa maksud $$ di dalam shell?

143

Saya pernah membaca bahwa salah satu cara untuk mendapatkan nama file unik di shell untuk file temp adalah dengan menggunakan tanda dolar ganda ( $$). Ini memang menghasilkan angka yang bervariasi dari waktu ke waktu ... tetapi jika Anda memanggilnya berulang kali, ia mengembalikan nomor yang sama. (Solusinya adalah dengan menggunakan waktu saja.)

Saya ingin tahu apa $$sebenarnya itu, dan mengapa itu akan disarankan sebagai cara untuk menghasilkan nama file yang unik.

kucing
sumber

Jawaban:

102

Dalam Bash $$adalah ID proses, seperti yang tercantum dalam komentar itu tidak aman untuk digunakan sebagai nama file temp karena berbagai alasan.

Untuk nama file sementara, gunakan mktempperintah.

Joe Skora
sumber
35
Bagi orang yang hanya melihat jawaban teratas, $$ tidak baik untuk satu file jika menulis ke direktori yang dapat ditulis untuk umum (misalnya, / tmp). Sangat mudah untuk membuang sampah / tmp dengan symlink yang akan menyebabkan skrip Anda menulis di suatu tempat yang tidak diinginkan. mktemp jauh lebih baik.
Chris Jester-Young
4
Ya, menggunakan $$ akan menyebabkan lubang keamanan yang buruk. Jangan lakukan itu.
emk
7
Atau orang yang mengajukan pertanyaan harus menetapkan jawaban berperingkat tinggi di bawah ini sebagai jawaban yang diterima ...
jtimberman
6
Saya menambahkan "dolar dolar" untuk SEO.
Antoine
1
Jika $$ hanya menampilkan pid, bagaimana bisa "tidak aman"? Lubang keamanan dibuat berdasarkan desain yang buruk tidak menggunakan PID dalam nama file tmp ... Jika Anda peduli tentang integritas output yang terlalu banyak ke tmp, mungkin Anda bahkan tidak seharusnya meletakkannya di sana? $$ tidak akan menyebabkan lubang keamanan, kurangnya pandangan ke depan
niken
113

$$adalah ID proses (PID) dalam bash. Menggunakan $$adalah ide yang buruk, karena biasanya akan menciptakan kondisi balapan, dan memungkinkan skrip shell Anda untuk ditumbangkan oleh penyerang. Lihat, misalnya, semua orang ini yang membuat file sementara tidak aman dan harus mengeluarkan nasihat keamanan.

Sebaliknya, gunakan mktemp. The halaman manual Linux untuk mktemp sangat baik. Berikut beberapa contoh kode dari itu:

tempfoo=`basename $0`
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
echo "program output" >> $TMPFILE
emk
sumber
3
Terima kasih. The mktemppilihan -tsekarang tidak berlaku (saya pikir karena masalah dengan char -). Gunakan mktemp ${tempfoo}.XXXXXXhari ini . Saya mengambil kebebasan untuk memperbarui posting Anda.
Sebastian
1
Harap perhatikan juga, bahwa backtick sudah usang , jadi gunakan TMPFILE=$(mktemp)saja.
Michael Kopp
20

$$ adalah id dari proses saat ini.

Batu api
sumber
7

Setiap proses dalam sistem operasi mirip UNIX memiliki (sementara) pengidentifikasi unik, PID. Tidak ada dua proses yang berjalan pada saat yang sama dapat memiliki PID yang sama, dan $$ merujuk ke PID dari instance bash yang menjalankan skrip.

Ini sangat tidak pengenal unik dalam arti bahwa itu tidak akan pernah digunakan kembali (memang, PID digunakan kembali terus-menerus). Apa yang diberikannya adalah angka sehingga, jika orang lain menjalankan skrip Anda, mereka akan mendapatkan pengenal yang berbeda saat milik Anda masih berjalan. Setelah milik Anda mati, PID dapat didaur ulang dan orang lain dapat menjalankan skrip Anda, dapatkan PID yang sama, dan dapatkan nama file yang sama.

Dengan demikian, itu hanya benar-benar waras untuk mengatakan "$$ memberikan nama file sehingga jika orang lain menjalankan skrip yang sama ketika contoh saya masih berjalan, mereka akan mendapatkan nama yang berbeda".

Adam Wright
sumber
5

$$ adalah PID Anda. Itu tidak benar-benar menghasilkan nama file yang unik, kecuali Anda berhati-hati dan tidak ada orang lain yang melakukannya dengan cara yang persis sama.

Biasanya Anda akan membuat sesuatu seperti / tmp / myprogramname $$

Ada begitu banyak cara untuk memecahkan ini, dan jika Anda menulis ke lokasi orang lain dapat menulis untuk itu tidak terlalu sulit pada banyak OS untuk memprediksi PID apa yang akan Anda miliki dan mainkan - bayangkan Anda menjalankan sebagai root dan saya membuat / tmp / yourprogname13395 sebagai symlink yang menunjuk ke / etc / passwd - dan Anda menulis di dalamnya.

Ini adalah hal yang buruk untuk dilakukan dalam skrip shell. Jika Anda akan menggunakan file sementara untuk sesuatu, Anda harus menggunakan bahasa yang lebih baik yang setidaknya akan membiarkan Anda menambahkan bendera "eksklusif" untuk membuka (membuat) file. Maka Anda dapat yakin bahwa Anda tidak mengalahkan sesuatu yang lain.

JBB
sumber
3

$$ adalah pid dari proses shell saat ini. Itu bukan cara yang baik untuk menghasilkan nama file yang unik.

Leif
sumber
3

$$ adalah pid (id proses) dari shell interpreter yang menjalankan skrip Anda. Ini berbeda untuk setiap proses yang berjalan pada suatu sistem saat ini, tetapi seiring waktu pid tersebut membungkus, dan setelah Anda keluar akan ada proses lain dengan pid yang sama pada akhirnya. Selama Anda menjalankan, pid itu unik untuk Anda.

Dari definisi di atas harus jelas bahwa tidak peduli berapa kali Anda menggunakan $$ dalam sebuah skrip, itu akan mengembalikan angka yang sama.

Anda dapat menggunakan, misalnya /tmp/myscript.scratch.$$ sebagai file temp Anda untuk hal-hal yang tidak perlu terlalu dapat diandalkan atau aman. Merupakan praktik yang baik untuk menghapus file temp semacam itu di akhir skrip Anda, menggunakan, misalnya, perintah trap:

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

sumber
2

Ini adalah ID proses dari proses bash. Tidak ada proses bersamaan yang akan memiliki PID yang sama.


sumber
2

$$ adalah id proses dari shell di mana skrip Anda berjalan. Untuk detail lebih lanjut, lihat halaman manual untuk sh atau bash. Halaman manual dapat ditemukan menggunakan baris perintah "man sh", atau dengan mencari di web untuk "shell manpage"

Shannon Nelson
sumber
2

Biarkan saya menjawab kedua emk - jangan gunakan $$ dengan sendirinya sebagai sesuatu yang "unik". Untuk file, gunakan mktemp. Untuk ID lain dalam skrip bash yang sama, gunakan "$$$ (tanggal +% s% N)" untuk peluang keunikan yang cukup baik.

 -k
Kevin Little
sumber
0

Anda juga dapat mengambil nama pengguna login melalui perintah ini. Misalnya.

echo $(</proc/$$/login id). After that, you need to use getent command.
Obivan
sumber