Anda dapat menggunakan sh -c
dan exec
untuk mendapatkan PID perintah bahkan sebelum dijalankan.
Untuk memulai myCommand
, sehingga PID-nya dicetak sebelum mulai dijalankan, Anda dapat menggunakan:
sh -c 'echo $$; exec myCommand'
Bagaimana itu bekerja:
Ini memulai shell baru, mencetak PID dari shell itu, dan kemudian menggunakan exec
builtin untuk mengganti shell dengan perintah Anda, memastikan ia memiliki PID yang sama. Ketika shell Anda menjalankan perintah dengan exec
builtin, shell Anda sebenarnya menjadi perintah itu , daripada perilaku yang lebih umum dari forking salinan baru itu sendiri, yang memiliki PID sendiri yang terpisah dan yang kemudian menjadi perintah.
Saya menemukan ini jauh lebih sederhana daripada alternatif yang melibatkan eksekusi asinkron (dengan &
), kontrol pekerjaan, atau pencarian dengan ps
. Pendekatan-pendekatan itu baik-baik saja, tetapi kecuali jika Anda memiliki alasan khusus untuk menggunakannya - misalnya, mungkin perintah sudah berjalan, dalam hal mencari PID atau menggunakan kontrol pekerjaan akan masuk akal - saya sarankan mempertimbangkan cara ini terlebih dahulu. (Dan saya pasti tidak akan mempertimbangkan untuk menulis naskah yang rumit atau program lain untuk mencapai ini).
Jawaban ini termasuk contoh dari teknik ini.
Sebagian dari perintah itu kadang-kadang bisa dihilangkan, tetapi tidak biasanya.
Bahkan jika shell yang Anda gunakan adalah gaya Bourne dan karenanya mendukung exec
builtin dengan semantik ini, Anda biasanya tidak boleh mencoba untuk menghindari menggunakan sh -c
(atau setara) untuk membuat proses shell baru yang terpisah untuk tujuan ini, karena:
- Setelah shell menjadi
myCommand
, tidak ada shell yang menunggu untuk menjalankan perintah berikutnya. sh -c 'echo $$; exec myCommand; foo
tidak akan dapat mencoba menjalankan foo
setelah mengganti sendiri dengan myCommand
. Kecuali Anda menulis skrip yang menjalankan ini sebagai perintah terakhir, Anda tidak bisa hanya menggunakan echo $$; exec myCommand
di shell di mana Anda menjalankan perintah lain.
- Anda tidak dapat menggunakan subkulit untuk ini.
(echo $$; exec myCommand)
mungkin secara sintaksis lebih bagus daripada sh -c 'echo $$; exec myCommand'
, tetapi ketika Anda menjalankan $$
di dalam (
)
, itu memberikan PID dari shell induk, bukan dari subkulit itu sendiri. Tapi itu PID subkulit yang akan menjadi PID dari perintah baru. Beberapa shell menyediakan mekanisme non-portabel mereka sendiri untuk menemukan PID subkulit, yang dapat Anda gunakan untuk ini. Secara khusus, dalam Bash 4 , (echo $BASHPID; exec myCommand)
berhasil.
Akhirnya, perhatikan bahwa beberapa shell akan melakukan optimasi di mana mereka menjalankan perintah seolah-olah oleh exec
(yaitu, mereka melupakan forking terlebih dahulu) ketika diketahui bahwa shell tidak perlu melakukan apa-apa sesudahnya. Beberapa shell mencoba melakukan ini kapan saja itu adalah perintah terakhir untuk dijalankan, sementara yang lain hanya akan melakukannya ketika tidak ada perintah lain sebelum atau setelah perintah, dan yang lain tidak akan melakukannya sama sekali. Efeknya adalah bahwa jika Anda lupa untuk menulis exec
dan hanya menggunakan sh -c 'echo $$; myCommand'
maka itu kadang - kadang akan memberi Anda PID yang tepat pada beberapa sistem dengan beberapa shell. Saya sarankan agar tidak mengandalkan perilaku seperti itu , dan alih-alih selalu termasuk exec
saat itulah yang Anda butuhkan.