Dengarkan untuk keluar dari proses yang diberikan pid $$

16

Katakanlah saya memiliki pid di tangan, mypid=$$

adakah perintah bash / system yang bisa saya gunakan untuk mendengarkan keluarnya proses dengan pid yang diberikan?

Jika tidak ada proses dengan mypid, saya kira perintah seharusnya gagal.

Alexander Mills
sumber
Saya tidak menggunakan C #, tetapi tampaknya harus ada caranya: msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx
Alexander Mills
Di Unix, itu umum untuk menunggu proses anak menggunakan waitdi shell atau fungsi wait()C library. Tidak ada cara standar AFAIK untuk menunggu proses non-anak. Lebih lanjut tidak jelas apakah fungsi C # dapat melakukan itu (itu tergantung pada apa "proses terkait" itu).
Kusalananda
Saya bisa melakukan ini dengan polling tapi itu akan mengerikan
Alexander Mills
Ini juga berpotensi memberi Anda hasil yang salah. Penggunaan kembali PID secara teoritis berarti bahwa suatu proses dapat menjadi hidup dengan PID yang sama dengan proses yang Anda tunggu. Di Linux (dengan PID berurutan) ini tidak mungkin , tetapi pada sistem seperti OpenBSD (alokasi PID acak), ini akan menjadi masalah.
Kusalananda

Jawaban:

21

Saya mendapatkan apa yang saya butuhkan dari jawaban ini: https://stackoverflow.com/a/41613532/1223975

..turns out menggunakan wait <pid> hanya akan berfungsi jika pid itu adalah proses anak dari proses saat ini .

Namun berikut ini akan bekerja untuk proses apa pun:

Untuk menunggu proses apa pun selesai

Linux:

tail --pid=$pid -f /dev/null

Darwin (mengharuskan yang $pidmemiliki file terbuka):

lsof -p $pid +r 1 &>/dev/null

Dengan batas waktu (detik)

Linux:

timeout $timeout tail --pid=$pid -f /dev/null

Darwin (mengharuskan yang $pidmemiliki file terbuka):

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
Alexander Mills
sumber
Ini tidak terkait dengan Linux, ini adalah fitur dari GNU tail. Jadi itu akan bekerja pada sistem apa pun dengan ekor GNU seperti yang GNU / Linux, dan itu tidak akan bekerja pada sistem berbasis Linux non-GNU.
Stéphane Chazelas
Saya khawatir bahwa tail / lsof akan menggunakan polling dalam kasus ini, setidaknya mengingat bukti empiris yang terlihat seperti itu pada MacOS.
Alexander Mills
lsof + r menempatkannya dalam mode ulang, sehingga perintah itu diulang setiap detik sehingga menggunakan polling, sialan
Alexander Mills
3

Anda dapat menggunakan bash builtin wait:

$ sleep 10 &
[2] 28751
$ wait 28751
[2]-  Done                    sleep 10
$ help wait
wait: wait [-n] [id ...]
    Wait for job completion and return exit status.

    Waits for each process identified by an ID, which may be a process ID or a
    job specification, and reports its termination status.  If ID is not
    given, waits for all currently active child processes, and the return
    status is zero.  If ID is a a job specification, waits for all processes
    in that job's pipeline.

    If the -n option is supplied, waits for the next job to terminate and
    returns its exit status.

    Exit Status:
    Returns the status of the last ID; fails if ID is invalid or an invalid
    option is given.

Ini menggunakan panggilan sistem waitpid()..

$ whatis waitpid
waitpid (2)          - wait for process to change state
Derek Callaway
sumber
bagus yang bekerja untuk saya, semoga tidak menggunakan polling di bawah tenda, terima kasih!
Alexander Mills
1
ya tidak akan berfungsi untuk kasus penggunaan saya, saya mendapatkan kesalahan ini: bash: wait: pid 47760 is not a child of this shell... kembali ke papan gambar lol
Alexander Mills
Saya punya jawaban, saya baru mempostingnya thx
Alexander Mills
2
Ini hanya akan menunggu proses anak, bukan untuk proses yang tidak terkait dengan proses saat ini.
Kusalananda
1

Mengenai solusi https://stackoverflow.com/a/41613532/1223975 yang diulangi oleh Alexander Mills Timeout in Seconds Darwin,, adalah solusi untuk OS mirip UNIX yang tidak memiliki GNU tail. Ini tidak spesifik untuk Darwin, tetapi, tergantung pada usia sistem operasi seperti UNIX, baris perintah yang ditawarkan lebih kompleks daripada yang diperlukan, dan dapat gagal:

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

Pada setidaknya satu UNIX lama, lsofargumen +r 1m%sgagal (bahkan untuk pengguna super):

lsof: can't read kernel name list.

Ini m%sadalah spesifikasi format keluaran. Post-prosesor yang lebih sederhana tidak memerlukannya. Misalnya, perintah berikut menunggu pada PID 5959 hingga lima detik:

lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'

Dalam contoh ini, jika PID 5959 keluar dengan sendirinya sebelum lima detik berlalu, ${?}adalah 0. Jika tidak ${?}kembali 1setelah lima detik.

Ini juga mungkin layak tegas mencatat bahwa +r 1, yang 1adalah interval polling (dalam detik), sehingga dapat diubah sesuai situasi.

kbulgrien
sumber