เริ่มกระบวนการพื้นหลังจากสคริปต์และจัดการเมื่อสคริปต์สิ้นสุด


15

ฉันต้องการเรียกใช้และกำหนดค่ากระบวนการคล้ายกับ daemon จากสคริปต์
shell ของฉันคือ zsh emulated ภายใต้ Cygwin และ daemon คือSFKซึ่งเป็นเซิร์ฟเวอร์ FTP พื้นฐาน

สำหรับสิ่งที่สำคัญที่นี่สคริปต์startserv.shสามารถถูกร่างได้ดังนี้:

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

หลังจากเรียกใช้สคริปต์สคริปต์startserv.shจะหยุด (จบลง?) โดยไม่แสดงพรอมต์ใด ๆ จากนั้น:

  • CTRL+ Cจบทั้งสคริปต์และกระบวนการทำงานเบื้องหลัง

  • การกดปุ่มEnterสคริปต์จะสิ้นสุดกระบวนการจะยังคงอยู่ในพื้นหลัง

อย่างไรก็ตามผมสามารถดูได้ผ่านทางpsและไม่ได้jobsดังนั้นเมื่อฉันต้องการที่จะปิดการที่ผมต้องส่งโหดร้ายkill -9สัญญาณซึ่งเป็นสิ่งที่ผมอยากจะหลีกเลี่ยงในความโปรดปรานของ +CTRLC

ทางเลือกอื่น จะเรียกใช้สคริปต์ทั้งหมดในพื้นหลัง 'จะ' แต่คำสั่งไม่สามารถได้รับข้อมูลผู้ใช้ถ้าสคริปต์ทำงานเป็นreadstartserv.sh &

โปรดทราบว่าฉันต้องการเซิร์ฟเวอร์ชั่วคราวไม่ใช่ภูตจริง: นั่นคือฉันต้องการให้กระบวนการเซิร์ฟเวอร์ทำงานในพื้นหลังหลังจากสคริปต์จบลงเพื่อทำงานเชลล์เชิงโต้ตอบอย่างง่าย (พร้อมแขกเครื่องเสมือน) แต่ฉันไม่ต้อง ' ไม่จำเป็นต้องใช้กระบวนการเพื่อเอาตัวรอดจากเปลือก ดังนั้นจึงnohupดูเหมือนไม่เหมาะสม


รับ id กระบวนการของกระบวนการที่ทำงานในพื้นหลังโดยใช้bgproc="$!"จากนั้นcommand "$bgproc" ดำเนินการตามความเหมาะสม ดูstackoverflow.com/questions/1908610/…
Valentin Bajrami

คุณสามารถสร้างไฟล์ PID ได้เช่นกัน จากนั้นอ่านไฟล์นั้นเพื่อดูว่ากระบวนการนั้นเป็นหมายเลขอะไรและไปจากที่นั่น
jgr208

คำตอบ:


18

การกดปุ่มEnterสคริปต์จะสิ้นสุดกระบวนการจะยังคงอยู่ในพื้นหลัง

เกือบ! Enterที่จริงสคริปต์ที่ได้ออกไปแล้วตามเวลาที่คุณกด อย่างไรก็ตามนั่นเป็นวิธีที่คุณจะได้รับพรอมต์กลับมา (เพราะเชลล์ของคุณพิมพ์$PS1กลับมาอีกครั้ง)

สาเหตุที่การกดCtrl+ Cยุติทั้งคู่นั้นเป็นเพราะทั้งสองเชื่อมโยงกัน เมื่อคุณเรียกใช้งานสคริปต์เชลล์ของคุณจะเริ่ม subshell เพื่อใช้งาน เมื่อคุณยุติ subshell นี้กระบวนการพื้นหลังของคุณจะตายอาจเกิดจากSIGHUPสัญญาณ

แยกสคริปต์กระบวนการพื้นหลังและเชลล์ย่อย

เมื่อใช้nohupคุณอาจสามารถกำจัดความไม่สะดวกเล็ก ๆ น้อย ๆ นี้ได้

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

disownทางเลือก

หากคุณสามารถเปลี่ยนจาก/bin/shเป็น/bin/bashคุณสามารถลองได้disownเช่นกัน ต้องการทราบข้อมูลเพิ่มเติมเพียงพิมพ์help disownในbashอินสแตนซ์

disown -h $cmd &

ฆ่ากระบวนการพื้นหลัง "อย่าง"

ตอนนี้เมื่อมันมาถึงการฆ่ากระบวนการของคุณคุณสามารถที่ดีที่สุดที่ทำ " Ctrl+ C" killโดยใช้ SIGKILLเพียงแค่ไม่ได้ส่งโหดร้าย คุณสามารถใช้:

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

ซึ่งจะส่ง nice SIGINT(2) หรือSIGTERM(15) ไปยังกระบวนการของคุณ คุณอาจต้องการพิมพ์ค่า PID หลังจากเริ่มกระบวนการ:

...
nohup $cmd &
echo $!

... หรือดีกว่าทำให้สคริปต์รอSIGINTและส่งกลับไปยังกระบวนการเบื้องหลัง(นี่จะทำให้สคริปต์ของคุณอยู่เบื้องหน้า) :

#!/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

หาก a SIGINTไม่เพียงพอให้ใช้SIGTERMแทน (15):

trap "kill -15 $bg_pid" 2 15

วิธีนี้เมื่อสคริปต์ของคุณได้รับSIGINT( Ctrl+ C, kill -2) หรือสักSIGTERMครู่หนึ่งwaitสำหรับกระบวนการพื้นหลังสคริปต์จะส่งสัญญาณไปที่มัน หากสัญญาณเหล่านี้ฆ่าsfkอินสแตนซ์ดังนั้นการwaitโทรจะส่งคืนดังนั้นจึงยุติสคริปต์ของคุณเช่นกัน :)


1
+1 มีข้อมูลมาก เนื่องจากสคริปต์ทำงานใน subshell มีความเป็นไปได้ในการเข้าถึงจากสคริปต์ไปยังตารางงานของ parent parent ของสคริปต์หรือไม่ นั่นคือรายการงานที่ออกjobsในเทอร์มินัลหลังจากสคริปต์สิ้นสุด (แทนps)
อันโตนิโอ

1
งานเชื่อมโยงกับเชลล์ปัจจุบันของคุณพวกมันจะไม่ถูกส่งจากเชลล์หนึ่งไปยังอีกเชลล์หนึ่ง เมื่อ subshell ของคุณตายงานจะไม่ถูกกู้คืน ด้วยการพิมพ์กระบวนการพื้นหลัง 'PID ของคุณคุณต้องแน่ใจว่าคุณสามารถรับข้อมูลได้อย่างง่ายดายแม้หลังจากที่ subshell สิ้นสุดลง ( pid -p)
John WH Smith

คำอธิบายที่ดี แต่ถ้าสคริปต์ของคุณมีคำสั่งมากกว่านี้พวกเขาจะไม่ถูกดำเนินการ (เพราะwait) หากคุณลบการรอการจัดการสัญญาณจะใช้งานไม่ได้: /
chefarov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.