Saya ingin mendapatkan daftar semua proses yang turun (misalnya anak-anak, cucu-cucu, dll) dari $pid
. Ini adalah cara paling sederhana yang saya buat:
pstree -p $pid | tr "\n" " " |sed "s/[^0-9]/ /g" |sed "s/\s\s*/ /g"
Apakah ada perintah, atau cara sederhana untuk mendapatkan daftar lengkap dari semua proses turunan?
'\n'
dibatasi vs' '
dibatasi). Kasus penggunaan praktis adalah: a) skrip daemonizer yang saya tulis dari masokisme murni (khususnya, fungsi "stop" harus berurusan dengan pohon proses apa pun yang proses daemonisasi telah hasilkan); dan b) skrip batas waktu yang akan membunuh apa pun yang berhasil dibuat oleh proses batas waktu.kill
. Lihat unix.stackexchange.com/questions/9480/… , unix.stackexchange.com/questions/50555/…ps ax -opid,ppid,pgrp,cmd
Saya melihat ada banyak proses yang berbagi samapgrp
dengan subtree persis yang ingin saya bunuh. (Selain itu, saya tidak dapat melihatsetpgrp
program terdaftar di mana saja dalam paket debian stable: packages.debian.org/... )Jawaban:
Berikut ini agak sederhana, dan memiliki keuntungan tambahan mengabaikan angka dalam nama perintah:
Atau dengan Perl:
Kami sedang mencari angka di dalam tanda kurung sehingga kami tidak, misalnya, memberi 2 sebagai proses anak-anak ketika kami bertemu
gif2png(3012)
. Tetapi jika nama perintah berisi nomor yang diurung, semua taruhan dimatikan. Hanya sejauh ini pemrosesan teks dapat membawa Anda.Jadi saya juga berpikir bahwa kelompok proses adalah cara untuk pergi. Jika Anda ingin menjalankan proses dalam grup prosesnya sendiri, Anda dapat menggunakan alat 'pgrphack' dari paket Debian 'daemontools':
Atau Anda bisa kembali ke Perl:
Satu-satunya peringatan di sini adalah bahwa grup proses tidak bersarang, jadi jika beberapa proses membuat grup proses sendiri, subproses tidak akan lagi berada di grup yang Anda buat.
sumber
pstree -lp | grep -Po "(?<=\()\d+(?=\))"
sumber
bash
,zsh
,fish
, dan bahkanksh 99
), tapi mungkin tidak bekerja pada kerang yang lebih tua, misalnyaksh 88
Versi terpendek yang saya temukan yang juga berurusan dengan perintah seperti
pop3d
:Ini berkaitan salah jika Anda memiliki perintah yang memiliki nama aneh seperti:
my(23)prog
.sumber
ffmpeg
menggunakan utas. Padahal, dari pengamatan cepat, tampaknya bahwa utas diberikan dengan nama mereka di dalam kurung kurawal{ }
,.Ada juga masalah kebenaran. Mengurai output
pstree
secara naif bermasalah karena beberapa alasan:Jika Anda memiliki Python dan
psutil
paket yang diinstal, Anda dapat menggunakan cuplikan ini untuk mendaftar semua proses turunan:(Paket psutil misalnya diinstal sebagai dependensi dari
tracer
perintah yang tersedia di Fedora / CentOS.)Atau, Anda bisa melakukan traversal pertama-lebar dari pohon proses di shell bourne:
Untuk menghitung transitif-penutupan pid, bagian ekor dapat dihilangkan.
Perhatikan bahwa di atas tidak menggunakan rekursi dan juga berjalan di ksh-88.
Di Linux, seseorang dapat menghilangkan
pgrep
panggilan dan bukannya membaca informasi dari/proc
:Ini lebih efisien karena kami menyimpan satu fork / exec untuk setiap PID dan
pgrep
melakukan beberapa pekerjaan tambahan di setiap panggilan.sumber
Versi Linux ini hanya membutuhkan / proc dan ps. Itu diadaptasi dari bagian terakhir dari jawaban sempurna @ maxschlepzig . Versi ini membaca / proc langsung dari shell alih-alih melahirkan sub-proses dalam satu lingkaran. Ini sedikit lebih cepat dan bisa dibilang sedikit lebih elegan, seperti permintaan judul utas ini.
sumber
Dalam masing-masing dari dua kasus penggunaan Anda (yang tampaknya sangat artifisial), mengapa Anda ingin membunuh sub-proses beberapa proses yang tidak menguntungkan? Bagaimana Anda tahu lebih baik daripada sebuah proses ketika anak-anaknya harus hidup atau mati? Ini sepertinya desain yang buruk bagi saya; suatu proses harus membersihkan setelah itu sendiri.
Jika Anda benar-benar tahu lebih baik, maka Anda harus mencari-cari sub-proses ini, dan 'proses yang terampas' tampaknya terlalu bodoh untuk dipercaya
fork(2)
.Anda harus menghindari menyimpan daftar proses anak atau merendahkan melalui pohon proses, misalnya dengan menempatkan proses anak dalam kelompok proses terpisah seperti yang disarankan oleh @Gilles.
Dalam kasus apa pun, saya menduga bahwa proses daemonisasi Anda akan lebih baik menciptakan kumpulan thread pekerja (yang tentu mati bersama dengan proses yang mengandung) daripada pohon sub-sub-sub-proses yang mendalam, yang harus dibersihkan sesuatu di suatu tempat kemudian .
sumber
Berikut ini skrip pembungkus pgrep yang memungkinkan Anda menggunakan pgrep dan mendapatkan semua keturunan secara bersamaan.
~/bin/pgrep_wrapper
:Aktifkan dengan cara yang sama Anda akan memanggil pgrep normal, seperti
pgrep_recursive -U $USER java
untuk menemukan semua proses dan sub-proses Java dari pengguna saat ini.sumber
IFS
dan menggunakan array ("${array[*]}
").