Mengutip dokumentasi bash (dari man bash
):
JOB CONTROL
Job control refers to the ability to selectively stop
(suspend) the execution of processes and continue (resume)
their execution at a later point. A user typically employs
this facility via an interactive interface supplied jointly
by the operating system kernel's terminal driver and bash.
Jadi, sederhananya, memiliki set -m
(default untuk shell interaktif) memungkinkan seseorang untuk menggunakan built-in seperti fg
dan bg
, yang akan dinonaktifkan di bawah set +m
(default untuk shell non-interaktif).
Tidak jelas bagi saya apa hubungan antara kontrol pekerjaan dan mematikan proses latar belakang saat keluar, tetapi saya dapat mengonfirmasi bahwa ada satu:menjalankan set -m; (sleep 10 ; touch control-on) &
akan membuat file jika seseorang keluar dari shell tepat setelah mengetik perintah itu, tetapi set +m; (sleep 10 ; touch control-off) &
tidak akan.
Saya pikir jawabannya terletak pada sisa dokumentasi untuk set -m
:
-m Monitor mode. [...] Background pro‐
cesses run in a separate process group and a line con‐
taining their exit status is printed upon their comple‐
tion.
Ini berarti pekerjaan latar belakang dimulai di bawah set +m
bukan "proses latar belakang" yang sebenarnya ("Proses latar belakang adalah mereka yang ID grup prosesnya berbeda dari terminal"):mereka berbagi ID grup proses yang sama dengan shell yang memulainya, daripada memiliki grup proses mereka sendiri seperti proses latar belakang yang tepat. Ini menjelaskan perilaku yang diamati ketika shell berhenti sebelum beberapa pekerjaan latar belakangnya:jika saya mengerti dengan benar, ketika berhenti, sinyal dikirim ke proses dalam grup proses yang sama dengan shell (sehingga mematikan pekerjaan latar belakang dimulai di bawah set +m
), tetapi tidak untuk grup proses lain (sehingga membiarkan sendiri proses latar belakang yang sebenarnya dimulai di bawah set -m
).
Jadi, dalam kasus Anda, startup.sh
skrip mungkin memulai pekerjaan latar belakang. Ketika skrip ini dijalankan secara non-interaktif, seperti melalui SSH seperti pada pertanyaan yang Anda tautkan, kontrol pekerjaan dinonaktifkan, pekerjaan "latar belakang" berbagi grup proses dari shell jarak jauh, dan dengan demikian dimatikan segera setelah shell keluar. Sebaliknya, dengan mengaktifkan jobcontrol di shell tersebut, tugas latar belakang memperoleh grup prosesnya sendiri, dan tidak dimatikan saat shell induknya keluar.
Saya menemukan ini di daftar masalah github, dan menurut saya ini benar-benar menjawab pertanyaan Anda.
Ini sebenarnya bukan masalah SSH, ini lebih merupakan perilaku halus seputar mode non-interaktif/interaktif BASH dan propagasi sinyal untuk memproses grup.
Berikut ini berdasarkan https://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 dan http:// www.itp.uzh.ch/~dpotter/howto/daemonize, dengan beberapa asumsi tidak sepenuhnya divalidasi, tetapi tes tentang cara kerjanya sepertinya mengonfirmasi.
pty/tty =salah
Shell bash diluncurkan terhubung ke stdout/stderr/stdin dari proses yang dimulai dan terus berjalan sampai tidak ada yang terpasang ke soket dan anak-anaknya telah keluar. Proses deamon yang baik akan memastikannya tidak menunggu anak-anaknya keluar, memotong proses anak, lalu keluar. Saat dalam mode ini tidak ada SIGHUP yang akan dikirim ke proses anak oleh SSH. Saya percaya ini akan bekerja dengan benar untuk sebagian besar skrip yang menjalankan proses yang menangani deamonisasi itu sendiri dan tidak perlu dilatar belakang. Jika skrip init menggunakan '&' untuk melatarbelakangi suatu prosesmaka kemungkinan besar masalah utamanya adalah apakah proses yang dilatarbelakangi pernah mencoba membaca dari stdin karena hal itu akan memicu SIGHUP jika sesi telah dihentikan.
pty/tty =true*
Jika skrip init melatar belakangi proses yang dimulai, induk BASHshell akan mengembalikan kode keluar ke koneksi SSH, yang akan mengubah tampilan untuk segera keluar karena tidak menunggu proses anak berhenti dan tidak diblokir di stdout/stderr/ stdin. Ini akan menyebabkan SIGHUP dikirim ke grup proses bash shell induk, yang karena kontrol pekerjaan dinonaktifkan dalam mode non-interaktif di bash, akan menyertakan proses anak yang baru saja diluncurkan. Di mana proses daemon secara eksplisit memulai sesi proses baru saat bercabang atau dalam proses bercabang, maka anak-anaknya tidak akan menerima SIGHUP dari proses induk BASH yang keluar. Catatan ini berbeda dari pekerjaan yang ditangguhkan yang akan melihat SIGTERM. Saya menduga masalah seputar ini hanya bekerja kadang-kadang ada hubungannya dengan sedikit kondisi balapan. Jika Anda melihat pendekatan standar untuk deamonisasi -http://www.itp.uzh.ch/~dpotter/howto/daemonize, Anda akan melihat bahwa dalam kode sesi baru dibuat oleh proses bercabang yang mungkin tidak dijalankan sebelum induk keluar, sehingga menghasilkan perilaku sukses/gagal acak yang disebutkan di atas. Pernyataan tidur akan memberikan cukup waktu bagi proses bercabang untuk membuat sesi baru, itulah sebabnya ini berfungsi untuk beberapa kasus.
pty/tty =true dan kontrol tugas diaktifkan secara eksplisit di bash
SSH tidak akan terhubung ke stdout/stderr/stdin dari bash shell atau proses anak yang diluncurkan, yang berarti akan keluar segera setelah shell bash induk mulai selesai menjalankan perintah yang diminta. Dalam hal ini, dengan kontrol pekerjaan diaktifkan secara eksplisit, proses apa pun yang diluncurkan oleh bash shell dengan '&' sebagai latar belakangnya akan segera ditempatkan ke dalam sesi terpisah dan tidak akan menerima sinyal SIGHUP ketika proses induk ke sesi BASH keluar (koneksi SSH dalam kasus ini).
Yang perlu diperbaiki
Saya pikir solusinya hanya perlu disebutkan secara eksplisit dalam dokumentasi operasi therun/sudo sebagai kasus khusus saat bekerja dengan proses/layanan latar belakang. Pada dasarnya gunakan 'pty=false', atau jika tidak memungkinkan, aktifkan kontrol tugas secara eksplisit sebagai perintah pertama, dan perilaku akan benar.
Dari https://github.com/fabric/fabric/issues/395