Mulai proses latar belakang dari skrip dan kelola ketika skrip berakhir

15

Saya ingin menjalankan dan mengonfigurasi proses yang mirip dengan daemon dari skrip.
Shell saya ditiru zsh di bawah Cygwin dan daemonnya adalah SFK , server FTP dasar.

Untuk yang penting di sini, skrip startserv.shdapat disusun sebagai berikut:

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
$cmd &

Setelah menjalankan skrip startserv.sh, berhenti (berakhir?) Tanpa menampilkan prompt, lalu:

  • CTRL+ Cmengakhiri skrip dan proses pekerjaan latar belakang;

  • Memukul Enterscript berakhir proses tetap di latar belakang.

Pokoknya saya bisa melihatnya hanya melalui psdan tidak jobs, jadi, ketika saya ingin menutup proses, saya harus mengirim kill -9sinyal brutal , yang merupakan sesuatu yang saya ingin hindari mendukung CTRL+ C.

Alternatif akan menjalankan seluruh skrip di latar belakang. 'Would be', tetapi readperintah tidak dapat mendapatkan input pengguna jika skrip dijalankan sebagai startserv.sh &.

Perhatikan bahwa saya memerlukan server singkat, bukan daemon sejati : yaitu, saya ingin proses server berjalan di latar belakang, setelah skrip berakhir, untuk melakukan tugas shell interaktif sederhana (dengan tamu mesin virtual), tetapi saya tidak t perlu proses untuk bertahan dari cangkang; oleh karena itu nohupsepertinya tidak tepat.

antonio
sumber
dapatkan id proses dari proses yang berjalan di latar belakang menggunakan bgproc="$!"dan kemudian command "$bgproc" untuk mengambil tindakan yang sesuai. Lihat juga stackoverflow.com/questions/1908610/...
Valentin Bajrami
Anda juga dapat membuat file PID. Kemudian baca file itu untuk melihat nomor proses apa itu dan pergi dari sana.
jgr208

Jawaban:

18

Memukul Enterscript berakhir proses tetap di latar belakang.

Hampir! Sebenarnya, skrip sudah keluar pada saat Anda menekan Enter. Namun, begitulah cara Anda mendapatkan balasan kembali (karena shell Anda mencetak $PS1semuanya lagi).

Alasan mengapa memukul Ctrl+ Cmengakhiri keduanya adalah karena keduanya terhubung. Saat Anda menjalankan skrip Anda, shell Anda memulai subkulit untuk menjalankannya. Ketika Anda mengakhiri subkulit ini, proses latar belakang Anda mati, mungkin dari SIGHUPsinyal.

Pisahkan skrip, proses latar belakang dan subkulit

Dengan menggunakan nohup, Anda mungkin bisa menghilangkan sedikit ketidaknyamanan ini.

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

The disownalternatif

Jika Anda dapat beralih dari /bin/shke /bin/bash, Anda dapat mencoba disownjuga. Untuk tahu lebih banyak, cukup ketikkan help disownsebuah bashinstance.

disown -h $cmd &

Membunuh proses latar belakang "dengan baik"

Sekarang, ketika datang untuk membunuh proses Anda, Anda dapat dengan sempurna melakukan " Ctrl+ C" menggunakan kill. Hanya saja, jangan mengirim brutal SIGKILL. Sebagai gantinya, Anda dapat menggunakan:

$ kill -2 [PID]
$ kill -15 [PID]

Yang akan mengirim barang bagus SIGINT(2) atau SIGTERM(15) ke proses Anda. Anda mungkin juga ingin mencetak nilai PID setelah memulai proses:

...
nohup $cmd &
echo $!

... atau bahkan lebih baik, buat skrip menunggu SIGINT, dan kirim kembali ke proses latar belakang (ini akan membuat skrip Anda tetap di latar depan) :

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

# Storing the background process' PID.
bg_pid=$!

# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2

# In the meantime, wait for $bg_pid to end.
wait $bg_pid

Jika a SIGINTtidak cukup, gunakan SIGTERMsaja (15):

trap "kill -15 $bg_pid" 2 15

Dengan cara ini, ketika skrip Anda menerima SIGINT( Ctrl+ C, kill -2) atau SIGTERMsebentar waituntuk proses latar belakang, itu hanya akan menyampaikan sinyal ke sana. Jika sinyal-sinyal ini benar-benar membunuh sfkinstance, maka waitpanggilan akan kembali, karena itu akhiri skrip Anda juga :)

John WH Smith
sumber
1
+1 Sangat informatif. Karena skrip berjalan dalam subkulit, apakah ada kemungkinan mengakses dari skrip ke tabel pekerjaan shell induk skrip? Itu adalah daftar pekerjaan yang dikeluarkan jobsdi terminal setelah skrip berakhir (bukan ps).
antonio
1
Pekerjaan dikaitkan dengan shell Anda saat ini, mereka tidak ditransmisikan dari satu shell ke shell lainnya. Ketika subkulit Anda mati, tugasnya tidak dipulihkan. Dengan mencetak PID proses latar belakang Anda, Anda memastikan Anda dapat memperoleh informasi tentang hal itu dengan mudah bahkan setelah subkulit telah diakhiri ( pid -p).
John WH Smith
penjelasan yang bagus, namun jika skrip Anda mengandung lebih banyak perintah, skrip tersebut tidak pernah dieksekusi (karena wait). Jika Anda menghapus menunggu, maka penanganan sinyal rusak: /
chefarov