Dapatkah seseorang menjelaskan secara detail apa yang dilakukan oleh "set -m"?

16

Di halaman manual , hanya tertulis:

Kontrol pekerjaan -m diaktifkan.

Tapi apa sebenarnya ini artinya?

Saya menemukan perintah ini dalam pertanyaan SO , saya memiliki masalah yang sama dengan OP, yaitu "fabric tidak dapat memulai tomcat". Dan set -mmemecahkan ini. OP sedikit menjelaskan, tapi saya tidak begitu mengerti:

Masalahnya adalah tugas latar belakang karena mereka akan terbunuh ketika perintah berakhir.

Solusinya sederhana: cukup tambahkan "set -m;" awalan sebelum perintah.

laike9m
sumber

Jawaban:

10

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, cukup sederhana mengatakan, memiliki set -m(default untuk shell interaktif) memungkinkan seseorang untuk menggunakan built-in seperti fgdan bg, yang akan dinonaktifkan di bawah set +m(default untuk shell tidak 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 bahwa pekerjaan latar belakang yang dimulai di bawah set +mbukanlah "proses latar belakang" yang sebenarnya ("Proses latar belakang adalah pekerjaan yang ID grup prosesnya berbeda dari terminal"): mereka berbagi ID grup proses yang sama dengan shell yang memulai, alih-alih memiliki sendiri kelompok proses 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 kelompok proses yang sama dengan shell (sehingga membunuh pekerjaan latar belakang dimulai di bawah set +m), tetapi tidak untuk orang-orang dari kelompok proses lain (sehingga meninggalkan proses latar belakang sejati dimulai di bawah set -m).

Jadi, dalam kasus Anda, startup.shskrip mungkin memulai pekerjaan latar belakang. Ketika skrip ini dijalankan secara non-interaktif, seperti di atas SSH seperti dalam pertanyaan yang Anda tautkan, kontrol pekerjaan dinonaktifkan, pekerjaan "latar belakang" membagikan grup proses dari shell jauh, dan dengan demikian terbunuh segera setelah shell keluar. Sebaliknya, dengan mengaktifkan kontrol pekerjaan di shell itu, pekerjaan latar belakang memperoleh grup prosesnya sendiri, dan tidak terbunuh ketika shell induknya keluar.

Dhag
sumber
Terima kasih atas jawaban Anda, tetapi bagaimana tomcat/bin/startup.shhubungannya dengan fg/ bg?
laike9m
1
Ini tidak terkait langsung; Saya mencoba menjawab "Kontrol pekerjaan diaktifkan / apa artinya ini sebenarnya?" secara umum. Mungkin saya belum memperjelasnya, tetapi skrip Anda tampaknya memulai pekerjaan latar belakang, dan itulah yang berlaku untuk sisa jawaban saya.
Dhag
2

Saya menemukan ini di daftar masalah github, dan saya pikir ini benar-benar menjawab pertanyaan Anda.

Ini bukan benar-benar masalah SSH, itu lebih pada perilaku halus di sekitar BASH mode non-interaktif / interaktif dan perambatan sinyal ke grup proses.

Berikut ini didasarkan pada /programming/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 yang tidak sepenuhnya divalidasi, tetapi tes tentang cara kerjanya tampaknya mengonfirmasi.

pty / tty = false

Bash shell diluncurkan menghubungkan ke stdout / stderr / stdin dari proses yang dimulai dan terus berjalan sampai tidak ada yang melekat pada soket dan anak-anak itu sudah keluar. Proses deamon yang baik akan memastikan tidak menunggu anak-anak untuk keluar, bercabang, dan kemudian keluar. Ketika dalam mode ini tidak ada SIGHUP 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 di-background. Jika skrip init menggunakan '&' untuk melatarbelakangi suatu proses maka kemungkinan masalah utamanya adalah apakah proses berlatar belakang itu pernah mencoba membaca dari stdin karena hal itu akan memicu SIGHUP jika sesi telah dihentikan.

pty / tty = true *

Jika skrip init latar belakang proses dimulai, induk BASH shell akan mengembalikan kode keluar ke koneksi SSH, yang pada gilirannya akan terlihat untuk keluar segera karena tidak menunggu proses anak untuk mengakhiri dan tidak diblokir pada stdout / stderr / stdin. Ini akan menyebabkan SIGHUP dikirim ke grup proses bash shell induk, yang karena kontrol pekerjaan dinonaktifkan dalam mode non-interaktif dalam bash, akan mencakup proses anak yang baru saja diluncurkan. Di mana proses daemon secara eksplisit memulai sesi proses baru ketika bercabang atau dalam proses bercabang maka itu atau anak-anak itu tidak akan menerima SIGHUP dari proses induk BASH yang ada. Perhatikan ini berbeda dari pekerjaan yang ditangguhkan yang akan melihat SIGTERM. Saya menduga masalah di sekitar ini hanya bekerja kadang-kadang ada hubungannya dengan kondisi balapan sedikit. 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 orang tua keluar, sehingga menghasilkan acak perilaku sukses / gagal yang disebutkan di atas. Pernyataan tidur akan memberikan cukup waktu bagi proses bercabang untuk membuat sesi baru, itulah sebabnya mengapa hal itu berfungsi untuk beberapa kasus.

pty / tty = true dan kontrol pekerjaan diaktifkan secara eksplisit di bash

SSH tidak akan terhubung ke stdout / stderr / stdin dari bash shell atau proses turunan apa pun yang diluncurkan, yang berarti itu akan keluar segera setelah induk bash shell mulai selesai menjalankan perintah yang diminta. Dalam hal ini, dengan kontrol pekerjaan diaktifkan secara eksplisit, setiap proses yang diluncurkan oleh bash shell dengan '&' untuk melatarbelakanginya akan ditempatkan ke dalam sesi terpisah segera dan tidak akan menerima sinyal SIGHUP ketika induk proses ke sesi BASH keluar ( Koneksi SSH dalam hal ini).

Apa yang perlu diperbaiki

Saya pikir solusi hanya perlu secara eksplisit disebutkan dalam dokumentasi operasi run / sudo sebagai kasus khusus ketika bekerja dengan proses latar belakang / layanan. Pada dasarnya baik menggunakan 'pty = false', atau di mana itu tidak mungkin, secara eksplisit mengaktifkan kontrol pekerjaan sebagai perintah pertama, dan perilaku akan benar.

Dari https://github.com/fabric/fabric/issues/395

pootow
sumber