Saya memulai proses latar belakang dari skrip shell saya, dan saya ingin menghentikan proses ini ketika skrip saya selesai.
Bagaimana cara mendapatkan PID dari proses ini dari skrip shell saya? Sejauh yang saya bisa lihat variabel $!
berisi PID dari skrip saat ini, bukan proses latar belakang.
linux
shell
background-process
pid
Volodymyr Bezuglyy
sumber
sumber
Jawaban:
Anda harus menyimpan PID dari proses latar belakang saat Anda memulainya:
Anda tidak dapat menggunakan kontrol pekerjaan, karena itu adalah fitur interaktif dan terikat ke terminal pengendali. Sebuah skrip tidak harus memiliki terminal yang terpasang sama sekali sehingga kontrol pekerjaan tidak harus tersedia.
sumber
foo
dan$!
, dan kita mendapatkan pid sesuatu itu bukannya darifoo
itu?foo
kebetulan ada beberapa perintah pipa (mis.tail -f somefile.txt | grep sometext
). Dalam kasus seperti itu, Anda akan mendapatkan PID dari perintah grep$!
daripada dari perintah tail jika itu yang Anda cari. Anda harus menggunakanjobs
ataups
suka dalam hal ini.grep
, tetapi jika Anda membunuh itu, ekor akan mendapatkan SIGPIPE ketika mencoba untuk menulis ke pipa. Tetapi begitu Anda mencoba masuk ke proses manajemen / kontrol yang rumit, bash / shell menjadi sangat menyakitkan./bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &
- sysfault 24 Nov '10 jam 14:28Anda dapat menggunakan
jobs -l
perintah untuk sampai ke pekerjaan tertentuLDalam hal ini, 46841 adalah PID.
Dari
help jobs
:jobs -p
adalah pilihan lain yang hanya menunjukkan PID.sumber
$!
setelah Anda mulai , PID lebih mudah dibawa-bawa dan lebih mudah dalam sebagian besar situasi. Itulah yang dilakukan oleh jawaban yang saat ini diterima.jobs -p
kembali sama sepertijobs -l
di Lubuntu 16.4$$
adalah pid skrip saat ini$!
adalah pid dari proses latar belakang terakhirBerikut ini adalah transkrip sampel dari sesi bash (
%1
merujuk ke nomor urut proses latar belakang seperti yang terlihat darijobs
):sumber
%1
tidak kembali proses latar belakang pada Ubuntu saya sedangkanecho $!
tidakCara yang lebih sederhana untuk membunuh semua proses anak dari skrip bash:
The
-P
bendera bekerja dengan cara yang sama denganpkill
danpgrep
- itu akan proses anak, hanya denganpkill
proses anak terbunuh dan denganpgrep
PID anak dicetak ke stdout.sumber
bash -c 'bash -c "sleep 300 &"' &
berlaripgrep -P $$
tidak menunjukkan apa-apa, karena tidur tidak akan menjadi anak langsung dari cangkang Anda.$$
mengacu pada shell saat ini.bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$
, saya mulai stdout[1] <pid>. So at least it shows something, but this is probably not the output of
pgrep`bash -c 'bash -c "sleep 10 & wait $!"' & sleep 0.1; pstree -p $$
inilah yang telah saya lakukan. Lihatlah, semoga bisa membantu.
Maka jalankan saja sebagai:
./bgkill.sh
dengan izin yang tepat tentu sajasumber
Anda mungkin juga dapat menggunakan pstree:
Ini biasanya memberikan representasi teks dari semua proses untuk "pengguna" dan opsi -p memberikan id proses. Sejauh yang saya mengerti, tidak tergantung pada proses yang dimiliki oleh shell saat ini. Itu juga menunjukkan garpu.
sumber
pgrep
bisa membuat Anda semua PID anak dari proses induk. Seperti disebutkan sebelumnya$$
adalah PID skrip saat ini. Jadi, jika Anda ingin skrip yang membersihkan setelah itu sendiri, ini harus melakukan trik:sumber
trap 'pkill -P $$' SIGING SIGTERM EXIT
terlihat lebih sederhana, tetapi saya tidak mengujinya.SIG
awalan. Itu diizinkan oleh POSIX tetapi hanya sebagai ekstensi yang implementasi dapat mendukung: pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html Dash shell misalnya tidak.