Mengapa $$ mengembalikan id yang sama dengan proses induk?

160

Saya punya masalah dengan Bash, dan saya tidak tahu mengapa.
Di bawah shell, saya masukkan:

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

"getpid" adalah program C untuk mendapatkan pid saat ini, seperti:

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

Yang membingungkan saya adalah:

  1. Saya pikir "(perintah)" adalah sub-proses (apakah saya benar?), Dan saya pikir pidnya harus berbeda dengan pid induknya, tetapi mereka sama, mengapa ...
  2. ketika saya menggunakan program saya untuk menunjukkan pid antara kurung, pid itu menunjukkan berbeda, apakah itu benar?
  3. Apakah '$$' itu seperti makro?

Bisakah kamu membantuku?

ruanhao
sumber
8
Catatan yang getpidakan menunjukkan ID proses yang berbeda bahkan jika itu tidak dijalankan dalam subkulit.
chepner
1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )menunjukkan hal itu. Kurung bundar membuat subkulit. Pernyataan dapat mengubah nilai variabel, dan shell induk tidak harus melihat perubahan itu. Ini diimplementasikan sebagai fork()operasi.
Ben

Jawaban:

223

$$didefinisikan untuk mengembalikan ID proses induk dalam subkulit; dari halaman manual di bawah "Parameter Khusus":

$ Perluas ke ID proses shell. Dalam subkulit (), itu mengembang ke ID proses shell saat ini, bukan subkulit.

Di bash4, Anda bisa mendapatkan ID proses anak BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
chepner
sumber
17
"parent" agak menyesatkan (setidaknya bagi saya), sebenarnya shell "level atas". Misalnya: echo $$; (echo $$; (echo $$))gema pid yang sama tiga kali
Martin Bouladour
1
Baik; Saya harus mengatakan bahwa nilai diwarisi dari shell orang tua (yang diwarisi nilainya dari yang tua, dll). Shell tingkat atas mengaturnya semula, daripada mewarisi dari proses induknya (non-shell).
chepner
$ Expands to the process ID of the shellapakah begitu echo $hanya menggemakan $ literal.
Alexander Mills
@AlexanderMills Yah, ya; $sendiri bukanlah ekspansi parameter. Halaman manual mengacu pada nama parameter khusus, yaitu $; itu tidak mengklaim bahwa itu $sendiri mengembang.
chepner
Ok saya jujur ​​tidak tahu apa artinya itu, tetapi echo $BASHPIDbekerja di bash 4 dan 5 (tetapi tidak versi 3.2.57 pada MacOS)
Alexander Mills
81

Anda dapat menggunakan salah satu dari yang berikut ini.

  • $! adalah PID dari proses latar belakang terakhir.
  • kill -0 $PID memeriksa apakah masih berjalan.
  • $$ adalah PID dari shell saat ini.
kasar
sumber
2
Bukankah peluru kedua seharusnya kill -0 $!jika kita berbicara tentang proses latar belakang? PIDtidak disetel ke apa pun secara default.
Isaac Freeman
26
  1. Tanda kurung memanggil subshell di Bash . Karena ini hanya subkulit, ia mungkin memiliki PID yang sama - tergantung pada implementasinya.
  2. Program C yang Anda panggil adalah proses terpisah, yang memiliki PID uniknya sendiri - tidak masalah apakah itu dalam subkulit atau tidak.
  3. $$adalah alias dalam Bash ke skrip PID saat ini . Lihat perbedaan antara $$dan di $BASHPIDsini , dan tepat di atas bahwa variabel tambahan $BASH_SUBSHELLyang berisi tingkat bersarang.
Niels Keurentjes
sumber
4

Coba getppid()jika Anda ingin program C Anda mencetak PID shell Anda.

Alex
sumber
2

Jika Anda bertanya bagaimana cara mendapatkan PID dari perintah yang dikenal itu akan menyerupai sesuatu seperti ini:

Jika Anda telah mengeluarkan perintah di bawah ini # Perintah yang dikeluarkan adalah ***

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


Maka Anda akan menggunakan:

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

Apa yang terjadi di sini adalah mem-pipe semua karakter unik yang diperlukan ke suatu bidang dan bidang itu dapat digaungkan menggunakan

echo $ PIDs

Don-Pierre Halfaway
sumber
2

ini cara univesal untuk mendapatkan pid yang benar

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

sama bagusnya bekerja untuk sub

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

echo "pid = $$"

(SUB)

periksa output

pid = 8099
8099 != 8100
ARTEM LAPKIN
sumber
Ide yang bagus, tetapi bukankah itu akan membuat Anda mendapatkan fork dari shell yang telah dijalankan untuk menangkap output dari cut? Jika saya menjalankannya dua kali, sekali dengan echo $ (...) dan sekali tanpa, maka saya mendapatkan jawaban yang berbeda.
Martin Dorey