Saya telah mengalami masalah aneh di mana suatu ps -o args -p <pid>
perintah kadang-kadang gagal menemukan proses yang dimaksud, meskipun itu pasti berjalan pada server yang dimaksud. Proses yang dimaksud adalah skrip pembungkus yang sudah berjalan lama yang digunakan untuk meluncurkan beberapa aplikasi Java.
The "di alam liar" kejadian dari masalah ini tampaknya selalu terjadi pagi, sehingga ada beberapa bukti bahwa hal itu terkait dengan beban disk pada server yang bersangkutan, karena mereka cukup berat dimuat kemudian, tetapi dengan menjalankan ps
di pertanyaan dalam lingkaran yang ketat, saya akhirnya bisa meniru masalah - sekali setiap beberapa ratus berjalan saya mendapatkan kesalahan.
Dengan menjalankan skrip bash berikut, saya berhasil menghasilkan output strace untuk menjalankan yang gagal dan berhasil:
while [ $? == 0 ] ; do strace -o fail.out ps -o args -p <pid> >/dev/null ; done ; strace -o good.out ps -o args -p <pid>
Membandingkan output dari fail.out
dan good.out
, saya dapat melihat bahwa getdents
system call pada proses yang gagal, entah bagaimana, mengembalikan jumlah yang jauh lebih kecil daripada jumlah aktual proses pada sistem (pada urutan ~ 500 dibandingkan dengan ~ 1100)
grep getdents good.out
getdents(5, /* 1174 entries */, 32768) = 32760
getdents(5, /* 31 entries */, 32768) = 992
getdents(5, /* 0 entries */, 32768) = 0
grep getdents fail.out
getdents(5, /* 673 entries */, 32768) = 16728
getdents(5, /* 0 entries */, 32768) = 0
... dan daftar yang lebih pendek itu tidak termasuk pid yang sebenarnya dalam pertanyaan, jadi tidak ditemukan.
Anda dapat mengabaikan bagian ini, kesalahan ENOTTY dijelaskan oleh komentar dave_thompson di bawah ini, dan tidak terkait
Selain itu, proses yang gagal mendapatkan beberapa
ENOTTY
kesalahan yang tidak muncul dalam proses yang berhasil. Dekat awal output yang saya lihatioctl (1, TIOCGWINSZ, 0x7fffe19db310) = -1 ENOTTY (ioctl yang tidak sesuai untuk perangkat) ioctl (1, TCGETS, 0x7fffe19db280) = -1 ENOTTY (ioctl tidak sesuai untuk perangkat)
Dan pada akhirnya saya melihat satu pun
ioctl (1, TCGETS, 0x7fffe19db0d0) = -1 ENOTTY (ioctl yang tidak sesuai untuk perangkat)
Gagal
ioctl
pada akhirnya terjadi tepat sebelumps
pengembalian, tetapi terjadi setelahps
telah mencetak hasil kosong yang ditetapkan, jadi saya tidak yakin apakah itu terkait. Saya tahu bahwa mereka konsisten dalam semua output strace gagal yang saya miliki, tetapi tidak muncul di yang sukses.
Saya sama sekali tidak tahu mengapa getdents
kadang-kadang tidak menemukan daftar lengkap proses, dan saya sekarang telah mencapai titik di mana saya hanya akan menampar seluruh bantuan band dengan mengubah skrip kontrol yang memeriksa skrip pembungkus dalam pertanyaan untuk memanggil ps
kedua kalinya jika yang pertama gagal, tetapi saya akan tertarik untuk mengetahui apakah ada yang tahu apa yang terjadi di sini.
Sistem yang dimaksud menjalankan Kernel 4.16.13-1.el7.elrepo.x86_64 pada CentOS 7 dan procps-ng versi 3.3.10-17.el7_5.2.x86_64
>/dev/null
doa 'gagal' (dalam loop) tetapi bukan doa 'baik', maka ENOTTY pada fd 1.Jawaban:
Pertimbangkan untuk membaca informasi yang Anda butuhkan langsung dari sistem
/proc
file daripada melalui alat sepertips
. Anda akan menemukan informasi yang Anda cari ("args") di dalam file/proc/$pid/cmdline
, hanya dipisahkan oleh NUL byte alih-alih spasi.Anda dapat menggunakan
sed
one-liner ini untuk mendapatkan argumen proses$pid
:Perintah ini setara dengan:
(Menggunakan
args=
dips
akan menghilangkan tajuk.)The
sed
Perintah pertama akan mencari trailing terakhir NUL byte dan menggantinya dengan baris baru, dan setelah itu mengganti semua byte NUL lainnya (memisahkan argumen individu) dengan spasi, akhirnya menghasilkan format yang sama yang Anda lihat darips
.Mengenai proses daftar dalam sistem,
ps
lakukan dengan mendaftar direktori/proc
, tetapi ada kondisi ras yang melekat pada prosedur itu, karena proses mulai dan keluar saatps
sedang berjalan, jadi apa yang Anda dapatkan bukanlah snapshot tetapi perkiraan. Secara khusus, ada kemungkinan bahwaps
akan menunjukkan proses yang telah dihentikan pada saat itu menunjukkan hasilnya, atau menghilangkan proses yang telah dimulai saat sedang berjalan (tetapi tidak dikembalikan oleh kernel saat daftar isi/proc
.)Saya selalu berasumsi bahwa jika suatu proses ada sebelum
ps
dimulai dan masih ada setelah selesai, maka itu tidak akan terlewatkan olehnya, saya berasumsi kernel akan menjamin mereka akan selalu disertakan, bahkan jika ada banyak churn dari proses lain diciptakan dan dihancurkan. Apa yang Anda gambarkan menunjukkan bahwa bukan itu masalahnya. Saya masih skeptis tentang itu, tetapi mengingat ada kondisi ras yang dikenal dalam caraps
kerjanya, saya kira setidaknya masuk akal bahwa mendaftarkan PID dari/proc
mungkin kehilangan yang sudah ada karena kondisi ras tersebut.Mungkin untuk memverifikasi bahwa dengan memeriksa sumber kernel Linux, tapi saya belum melakukannya (belum) jadi tidak bisa memastikan apakah kondisi ras seperti itu ada yang akan melewatkan proses yang berjalan lama, seperti Anda jelaskan.
Bagian lainnya adalah cara
ps
kerjanya. Bahkan jika Anda memberikan PID tunggal dengan-p
argumen, itu masih mendaftar semua PID yang ada, meskipun Anda hanya tertarik pada satu PID itu. Pasti bisa mengambil jalan pintas dalam kasus itu dan melewati daftar entri/proc
dan masuk langsung ke/proc/$pid
.Saya tidak bisa mengatakan mengapa ini diterapkan seperti ini. Mungkin karena sebagian besar
ps
opsi adalah "filter" pada proses, jadi menerapkan-p
cara yang sama lebih mudah, mengambil jalan pintas untuk langsung/proc/$pid
melibatkan jalur kode yang terpisah atau duplikasi kode ... Hipotesis lain adalah bahwa beberapa kasus termasuk-p
beberapa opsi tambahan akan akhirnya membutuhkan daftar, jadi mungkin rumit untuk menentukan kasus mana yang memungkinkan mengambil jalan pintas dan mana yang tidak.Yang membawa kita ke solusi, langsung ke
/proc/$pid
, tanpa daftar set lengkap PID sistem, menghindari semua ras yang diketahui dan hanya mendapatkan informasi yang Anda butuhkan langsung dari sumbernya.Agak jelek, tetapi masalah yang Anda jelaskan memang ada, itu harus menjadi cara yang andal untuk mengambil informasi itu.
sumber