Apakah `disown -h` dan` nohup` bekerja secara efektif sama?

18

disown

  • menyebabkan shell tidak mengirim SIGHUP ke pekerjaan yang tidak diakui saat shell berakhir, dan

  • menghapus pekerjaan yang tidak diakui dari kontrol pekerjaan shell.

Apakah yang pertama adalah hasil dari yang kedua? Dengan kata lain, jika suatu proses dimulai dari shell dihapus dari kontrol pekerjaan shell dengan cara apa pun, akankah shell tidak mengirim SIGHUP ke proses ketika shell berakhir?

disown -h masih menyimpan proses di bawah kendali pekerjaan shell. Apakah itu berarti bahwa disown -hmembuat suatu proses masih menerima SIGHUP yang dikirim dari shell, tetapi mengatur aksi SIGHUP dengan proses untuk "diabaikan"? Kedengarannya mirip nohup.

$ sleep 123 & disown -h
[1] 26103
$ jobs
[1]+  Running                 sleep 123 &
$ fg 1
sleep 123
$ ^Z
[1]+  Stopped                 sleep 125
$ bg 1
[1]+ sleep 123 &
$ exit

$ ps aux | grep sleep
t        26103  0.0  0.0  14584   824 ?        S    15:19   0:00 sleep 123

Apakah disown -hdan nohupbekerja secara efektif sama, jika kita mengabaikan perbedaan mereka dalam menggunakan terminal?

Terima kasih.

Tim
sumber
Perbedaan lain yang tidak dibahas di sini adalah bahwa jika Anda tidak menggunakan nohup, Anda perlu mengarahkan stdin / stdout / stderr menjauh dari TTY (jika shell asli Anda terhubung ke satu) sendiri. (OTOH, saya benar-benar menganggap bahwa praktik yang lebih baik daripada mengandalkan standar hardcode mengerikan seperti ./nohup.out).
Charles Duffy

Jawaban:

21

nohupdan disown -hbukan hal yang persis sama.

Dengan disown, suatu proses dihapus dari daftar pekerjaan di shell interaktif saat ini. Berjalan jobssetelah memulai proses latar belakang dan menjalankan disowntidak akan menunjukkan proses itu sebagai pekerjaan di shell. Pekerjaan yang tidak diakui tidak akan menerima HUPdari shell saat keluar (tetapi lihat catatan di bagian akhir).

Dengan disown -h, pekerjaan tidak dihapus dari daftar pekerjaan, tetapi shell tidak akan mengirim HUPsinyal kepadanya jika keluar (tapi lihat catatan di akhir).

The nohuputilitas mengabaikan HUPsinyal dan mulai utilitas yang diberikan. Utilitas mewarisi topeng sinyal dari nohupdan karena itu juga akan mengabaikan HUPsinyal. Ketika shell berakhir, proses itu tetap sebagai proses anak dari nohup(dan di nohup-parent init).

Perbedaannya adalah bahwa proses dimulai dengan nohupmengabaikan HUPterlepas dari siapa yang mengirim sinyal. Proses diakui hanya tidak dikirim sebuah HUPsinyal oleh shell , tapi mungkin masih akan dikirim sinyal dari misalnya kill -s HUP <pid>dan tidak akan mengabaikan hal ini.

Perhatikan bahwa HUPhanya dikirim ke pekerjaan shell jika

  • shell adalah shell login dan huponexitopsi shell diatur, atau
  • shell itu sendiri menerima HUPsinyal.

Bit yang relevan dari bashmanual (penekanan saya):

SINYAL

[...]

Shell keluar secara default setelah menerima aSIGHUP . Sebelum keluar, shell interaktif mengirim ulang SIGHUPke semua pekerjaan, berjalan atau berhenti. Pekerjaan yang dihentikan dikirim SIGCONTuntuk memastikan bahwa mereka menerima SIGHUP. Untuk mencegah shell mengirim sinyal ke pekerjaan tertentu, itu harus dihapus dari tabel pekerjaan dengan disownbuiltin (lihat di SHELL BUILTIN COMMANDSbawah) atau ditandai untuk tidak menerima SIGHUP penggunaan disown -h.

Jika huponexitopsi shell telah diatur dengan shopt, bashkirim a SIGHUPke semua pekerjaan saat shell login interaktif keluar.

disown [-ar] [-h] [jobspec ... | pid ... ]

Tanpa opsi, hapus masing-masing jobspecdari tabel pekerjaan aktif. [...] Jika -hopsi ini diberikan, masing jobspec- masing tidak dihapus dari tabel, tetapi ditandai sehingga SIGHUPtidak dikirim ke pekerjaan jika shell menerima aSIGHUP . [...]

Terkait:

Kusalananda
sumber
Saya mendapatkan bash: disown: nohup: no such jobdan sama untuk sleepdan 5dari disown nohup sleep 5 &. Apa yang Anda maksud dengan perintah kedua dari kalimat terakhir?
Ruslan
@Ruslan Ya saya tidak ada &di sana (dan urutan nohupdan disownjuga salah). Terima kasih. Akan diperbarui sekarang.
Kusalananda
@ Tim Maaf untuk mengedit jawaban yang berlebihan. Butuh beberapa saat untuk memahaminya. Saya sudah selesai sekarang.
Kusalananda
Terima kasih. disownmembuat shell tidak mengirim SIGHUP ke anak dengan mengeluarkan anak dari daftar pekerjaan shell. Bagaimana disown -hmencapai hal yang sama?
Tim
4

Mereka berbeda:

  • Disown menghapus pekerjaan dari tabel pekerjaan aktif. Kemudian dilanjutkan dengan pekerjaan saat ini. Dengan -h proses TIDAK dikirim SIGHUP. Alih-alih dibiarkan mati dengan shell yang berisi itu, ketika menerima SIGHUP.

  • nohup mengabaikan HUP. Maka segala sesuatu yang akan diteruskan ke terminal oleh penutupan proses bukannya pergi ke file nohup.out.

    nohup didefinisikan oleh POSIX sementara disown tidak.

Michael Prokopec
sumber
Apa maksudmu, "mati dengan cangkang yang berisi itu"? Membunuh proses orang tua tidak dengan sendirinya membunuh anak. Program yang terminalnya ditutup biasanya mati karena kegagalan terkait dengan upaya untuk berinteraksi dengan pegangan file yang melekat pada PTY terminal, tetapi jika stdin / stdout / stderr dialihkan ke tempat lain, itu tidak akan terjadi.
Charles Duffy