ทำไมกระบวนการของฉันยังคงทำงานหลังจากที่ฉันออกจากระบบ?


10

หลังจากเข้าสู่ระบบsshฉันพิมพ์คำสั่งนี้ในbash:

sleep 50000000000000 &

จากนั้นฉันก็kill -9คือsleepกระบวนการหลักของกระบวนการ (เช่นbash) จากนั้นหน้าต่างเทอร์มินัลจะยกเลิกการเชื่อมต่อพร้อมกัน

เมื่อฉันเข้าสู่ระบบอีกครั้งฉันพบว่าsleepกระบวนการยังมีชีวิตอยู่

คำถาม : ทำไมsleepกระบวนการสามารถอยู่รอดได้เมื่อฉันออกจากระบบและปิดเครื่อง? ในใจของฉันทุกอย่างยกเว้น daemons และnohupโปรแกรมจะถูกฆ่าระหว่างออกจากระบบ หากsleepสามารถอยู่รอดด้วยวิธีนี้แสดงว่าฉันสามารถใช้วิธีนี้แทนnohupคำสั่งได้หรือไม่


3
&จะแยกกระบวนการเป็นพื้นหลัง (เช่น daemon) และทำงานต่อไปแม้ว่าคุณจะออกจากระบบแล้ว
Aizuddin Zali

คำตอบ:


6

tl; DR:

ทำไมsleepกระบวนการสามารถอยู่รอดได้เมื่อฉันออกจากระบบและปิดเครื่อง? ในใจของฉันทุกอย่างยกเว้น daemons และnohupโปรแกรมจะถูกฆ่าระหว่างออกจากระบบ หากsleepสามารถอยู่รอดด้วยวิธีนี้แสดงว่าฉันสามารถใช้วิธีนี้แทนnohupคำสั่งได้หรือไม่

ยกเว้นว่าการbashวางไข่โดยsshมีhuponexitชุดตัวเลือกจะไม่มีกระบวนการใดถูกยกเลิกโดยค่าเฉลี่ยเมื่อออก / ออกจากระบบและเมื่อhuponexitมีการตั้งค่าตัวเลือกการใช้kill -9บนเชลล์ไม่ใช่ทางเลือกที่ดีในการใช้nohupกับกระบวนการลูกของเชลล์ nohupบนกระบวนการลูกของเชลล์จะยังคงปกป้องพวกเขาจาก SIGHUPs ที่ไม่ได้มาจากเชลล์และแม้ว่าจะไม่ได้รับความสำคัญnohupก็ตามก็ยังคงเป็นที่ต้องการเพราะมันช่วยให้เชลล์ถูกยกเลิกอย่างสง่างาม


ในbashมีตัวเลือกที่เรียกว่าhuponexitซึ่งหากตั้งค่าจะทำให้bashSIGHUP ลูก ๆ ของมันเมื่อออก / ออกจากระบบ;

ในอินสแตนซ์ที่ไม่ใช่การล็อกอินแบบ bashอินเทอร์แอคทีฟเช่นในbashอินสแตนซ์ที่เกิดจากgnome-terminalตัวเลือกนี้จะถูกละเว้น ไม่ว่าจะhuponexitมีการตั้งค่าหรือไม่ได้ตั้งค่าbashลูก ๆ ของจะไม่ถูก SIGHUPPed โดยbashเมื่อออกจาก;

ในอินสแตนซ์การเข้าสู่ระบบ แบบอินเทอร์แอคทีฟbashเช่นในbashอินสแตนซ์ที่เกิดจากsshตัวเลือกนี้จะไม่ถูกละเว้น หากhuponexitมีการตั้งค่าbashลูกของจะถูกยกเลิกโดยbashเมื่อออก / ออกจากระบบ; หากhuponexitไม่ได้ตั้งค่าbashลูกของจะไม่ได้รับการชมซ้ำbashเมื่อออก / ออกจากระบบ

ดังนั้นโดยทั่วไปการออก / ออกจากbashอินสแตนซ์การเข้าสู่ระบบแบบอินเทอร์แอคทีฟยกเว้นว่าhuponexitมีการตั้งค่าตัวเลือกจะไม่ทำให้เชลล์ SIGHUP เป็นลูกของมันและออกจาก / ออกจากbashอินสแตนซ์ที่ไม่ใช่การเข้าสู่ระบบแบบโต้ตอบโดยไม่คำนึงถึง;

อย่างไรก็ตามนี่คือสิ่งที่ไม่เกี่ยวข้องในกรณีนี้: การใช้kill -9 sleepจะอยู่รอดได้โดยไม่คำนึงถึงเพราะการฆ่ากระบวนการหลัก ( bash) จะไม่ปล่อยให้โอกาสสำหรับผู้ใช้ทำสิ่งใด ๆกับอดีต (เช่นเช่นถ้าbashอินสแตนซ์ปัจจุบันเป็นbashอินสแตนซ์ล็อกอินและhuponexitตัวเลือกถูกตั้งค่าเป็น SIGHUP มัน)

การเพิ่มสิ่งนี้ไม่เหมือนกับสัญญาณอื่น ๆ (เช่นสัญญาณ SIGHUP ที่ส่งไปbash) สัญญาณ SIGKILL จะไม่แพร่กระจายไปยังกระบวนการลูกของกระบวนการดังนั้นจึงsleepไม่ได้ถูกฆ่า

nohupเริ่มกระบวนการภูมิคุ้มกันต่อสัญญาณ SIGHUP ซึ่งเป็นสิ่งที่แตกต่าง มันจะป้องกันไม่ให้กระบวนการค้างอยู่ที่การรับสัญญาณ SIGHUP ซึ่งในกรณีนี้สามารถรับได้โดยbashอินสแตนซ์การเข้าสู่ระบบแบบโต้ตอบในกรณีที่huponexitมีการตั้งค่าตัวเลือกและเชลล์ออก; ดังนั้นการใช้เทคนิคnohupในการเริ่มต้นกระบวนการในbashอินสแตนซ์การเข้าสู่ระบบแบบอินเทอร์แอคทีฟด้วยhuponexitตัวเลือกที่ไม่มีการตั้งค่าจะป้องกันไม่ให้กระบวนการวางสายเมื่อรับสัญญาณ SIGHUP แต่การออกจากระบบ

อย่างไรก็ตามโดยทั่วไปเมื่อnohupจำเป็นต้องป้องกันสัญญาณ SIGHUP ที่มาจากเชลล์พาเรนต์ก็ไม่มีเหตุผลใดที่จะkill -9เลือกใช้เมธอด parent nohupบนเมธอด child มันควรจะตรงกันข้าม

การฆ่าผู้ปกครองโดยใช้kill -9วิธีการนั้นไม่ทำให้ผู้ปกครองสามารถออกจากระบบได้อย่างสง่างามในขณะที่การเริ่มต้นเด็กโดยใช้nohupวิธีการอนุญาตให้ผู้ปกครองถูกยกเลิกโดยสัญญาณอื่น ๆ เช่น SIGHUP (เพื่อเป็นตัวอย่างที่เหมาะสมในบริบท ของเด็กเริ่มใช้nohup) ซึ่งอนุญาตให้เด็กออกไปอย่างงดงาม


กล่าวอีกนัยหนึ่งถ้าฉันมีสคริปต์ที่วางไว้ในพื้นหลังมันจะยังคงทำงานแม้ว่าฉันจะฆ่ากระบวนการผู้ปกครองเช่นเชลล์ของฉันใช่มั้ย สิ่งที่จะเป็นวิธีที่จะฆ่าสคริปต์ที่?
Sergiy Kolodyazhnyy

@Serg หากคุณมี PID เพียงแค่ฆ่า PID; หากคุณไม่ได้จัดเก็บ PID แต่คุณสามารถระบุกระบวนการด้วยชื่อของเขาได้ps -e | grep processควรระบุรายการกระบวนการพร้อมกับ PID (หรือดีกว่าpgrep -x processถ้าคุณแน่ใจว่าตรงกับกระบวนการเดียวนั้นและไม่ใช่สิ่งที่ไม่ได้เปิดเผย); ปัญหาคือเมื่อคุณฆ่ากระบวนการที่kill -9เด็ก ๆ เป็นเจ้าของupstartดังนั้น PPID ดั้งเดิมของพวกเขาจะหายไปและ PPID ของพวกเขาเปลี่ยนไปเป็น PID ที่พุ่งพรวดทำให้พวกเขาจำไม่ได้ (AFAIK) แต่สำหรับชื่อหรือ PID
kos

@kos ภายใต้เงื่อนไขใดที่nohupจะไม่สามารถป้องกันไม่ให้กระบวนการวางสายเมื่อรับสัญญาณ SIGHUP จากกระบวนการหลัก ฉันกำลังพยายามที่จะใช้กระบวนการในพื้นหลัง (ในสถานีฉาบ SSH เชลล์) nohup <command> <arg> &โดย เมื่อฉันออกจากระบบโดยคลิกXปุ่มPuTTY กระบวนการพื้นหลังจะสิ้นสุดลงทันที เมื่อฉันออกจากระบบโดยพิมพ์exitในเทอร์มินัลเปลือก PuTTY SSH กระบวนการจะยังคงทำงานในพื้นหลังต่อไป
userpal

3

bashโดยค่าเริ่มต้นจะไม่ส่งลงสัญญาณหุบกับกระบวนการเด็กเมื่อออกจาก เพิ่มเติมในรายละเอียด (@kos ขอบคุณ) ก็ไม่เคยไม่ได้สำหรับเปลือกหอยที่ไม่ได้เข้าสู่ระบบ

คุณสามารถกำหนดค่าทุบตีที่จะทำเพื่อเปลือกหอยเข้าสู่ระบบhuponexitถ้าตั้งค่าตัวเลือก ในเทอร์มินัลให้ทำ:

[romano:~] % bash -l

(นี่เป็นการเริ่มเชลล์ "ล็อกอิน" ใหม่)

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

ตอนนี้ตรวจสอบsleepกระบวนการ:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... ไม่ทำงาน: ได้รับสัญญาณ HUP และออกตามที่ขอ


@kos --- ใช่คุณมีสิทธิ แต่ ... ดังนั้นทำไมถ้าผมรอด? แจ้งให้ทราบว่าถ้าผมกระบวนการมันจะออกจาก และแม้ว่าชุดที่รอด สับสน ... (ฉันจะพยายามเข้าใจให้ดีขึ้นและแก้ไข asnwer มิฉะนั้นฉันจะลบมัน) sleep 1000 & ; exitsleepkill -HUPsleephuponexitsleep
Rmano

2

หากsleepสามารถอยู่รอดได้ด้วยวิธีนี้ถ้าหมายความว่าฉันสามารถใช้วิธีนี้แทนnohupคำสั่งได้

kill -9ไม่ใช่วิธีที่ควรไป มันเหมือนกับการยิงด้วยปืนที่ทีวีเพื่อปิด นอกจากองค์ประกอบตลกไม่มีประโยชน์ กระบวนการไม่สามารถตรวจจับหรือเพิกเฉยSIGKILLได้ หากคุณไม่ให้โอกาสในการทำสิ่งที่มันกำลังทำอยู่ให้เสร็จสิ้นและทำความสะอาดมันอาจทำให้ไฟล์ที่เสียหาย (หรือสถานะอื่น ๆ ) หายไปและจะไม่สามารถเริ่มต้นใหม่ได้ kill -9เป็นความหวังสุดท้ายเมื่อไม่มีอะไรได้ผล


เหตุใดกระบวนการสลีปจึงสามารถอยู่รอดได้เมื่อฉันออกจากระบบและเทอร์มินัลปิด ในใจของฉันทุกอย่างยกเว้น daemon และโปรแกรม nohup จะถูกฆ่าเมื่อออกจากระบบ

เกิดอะไรขึ้นในกรณีของคุณ:

กระบวนการหลักของsleepคือbashเปลือกที่กำลังทำงานอยู่ เมื่อคุณkill -9ทุบตีกระบวนการทุบตีไม่มีโอกาสที่จะส่งSIGHUPไปยังกระบวนการลูกใด ๆ เพราะSIGKILL(ซึ่งถูกส่งโดยkill -9) ไม่สามารถจับได้โดยกระบวนการ กระบวนการสลีปทำงานต่อไป การนอนหลับตอนนี้กลายเป็นกระบวนการเด็กกำพร้า

กระบวนการ init (PID 1) ทำกลไกที่เรียกว่าการซ่อมแซมซ้ำ นั่นหมายความว่ากระบวนการเริ่มต้นในขณะนี้กลายเป็นแม่ของกระบวนการเด็กกำพร้านั้น init เป็นข้อยกเว้นโปรเซสอาจกลายเป็นลูกได้เนื่องจากมันรวบรวมกระบวนการที่สูญเสียโปรเซสหลักของพวกเขา Btw: ภูต (เหมือนsshd) ทำเช่นนั้นเมื่อ "เข้าสู่พื้นหลัง"

หากสิ่งนั้นไม่เกิดขึ้นกระบวนการกำพร้าในภายหลัง (เมื่อเสร็จสิ้น) จะกลายเป็นกระบวนการซอมบี้ นี่คือสิ่งที่เกิดขึ้นเมื่อwaitpid()ไม่ถูกเรียก (ความรับผิดชอบของกระบวนการหลักที่ไม่สามารถเติมได้เต็มเมื่อกระบวนการนั้นถูกฆ่า) เริ่มต้นการเรียกwaitpid()ใน intervall ที่เฉพาะเจาะจงเพื่อหลีกเลี่ยงการซอมบี้เด็ก


กระบวนการนี้ยังคงอยู่แม้ว่าจะมีสัญญาณที่สุภาพเช่นTERMหรือHUP
heemayl

@heemayl HUP huponextขึ้นอยู่กับการตั้งค่าเปลือกหอย: และจะรอจนกว่าการนอนหลับจะเสร็จสิ้น ในกรณีที่มีคำสั่งตรวจการณ์นอนหลับมันจะเป็นพัน ๆ ปี =)
ความวุ่นวาย

1

&เริ่มต้นกระบวนการในพื้นหลัง หากคุณพิมพ์ps -efคุณจะเห็นรหัสผู้ปกครองกระบวนการ (PPID) ของการนอนหลับของคุณคือทุบตี จากนั้นออกจากระบบและลงชื่อเข้าใช้อีกครั้ง กระบวนการจะยังคงทำงานหลังจากที่คุณออกจากระบบ หลังจากคุณเข้าสู่ระบบเป็นครั้งที่สองคุณจะทำงานps -efอีกครั้ง คุณจะเห็นว่าตอนนี้ผู้ปกครองของกระบวนการนอนหลับของคุณจะเป็นกระบวนการที่มี ID "1" นั่นคือ init ซึ่งเป็นพาเรนต์ของกระบวนการทั้งหมด


0

การใช้&จะทำให้โปรแกรมทำงานเป็นพื้นหลัง หากต้องการดูโปรแกรมในการใช้พื้นหลังคำสั่งและเพื่อให้มันทำงานเป็นเบื้องหน้าอีกครั้งวิ่งbgfg

ใช่มีหลายวิธีในการทำให้โปรแกรมทำงานต่อไปแม้จะออกจากเทอร์มินัลหลัก


ขอบคุณ หน้าคนทุบตีสับสนเล็กน้อย มันบอกว่า: "ก่อนที่จะออกจากเปลือกโต้ตอบโต้ตอบส่ง SIGHUP ไปยังงานทั้งหมดทำงานหรือหยุด" แต่อันที่จริงแล้วเชลล์ส่ง SIGHUP ไปยังงานforgroundเท่านั้น กระบวนการพื้นหลังไม่มีโอกาสที่จะได้รับสัญญาณ SIGHUP (เว้นแต่เปลี่ยนตัวเลือกเชลล์ 'huponexit')
tom_cat

@ kos บางทีคุณพูดถูก ฉันวาดข้อสรุปข้างต้นจากโพสต์นี้: stackoverflow.com/questions/4298741/… ตอนนี้ฉันสับสนตัวเองมากขึ้น
tom_cat

@tom_cat กลับไปที่นี้อีกครั้งคิดเกี่ยวกับมันครั้งที่สอง: มีเพียงกรณีที่เปลือกไม่สามารถออกจากกระบวนการทำงานเบื้องหน้าก็สามารถ SIGHUPped หรืออะไร แต่ที่ไม่ได้ออก มันถูกต้องมันใช้กับกระบวนการพื้นหลังเท่านั้นเพราะสิ่งที่ตรงกันข้ามจะไม่สมเหตุสมผล อย่างไรก็ตามจากการวิจัยเพิ่มเติมจิตใจยังใช้huponexitงานได้กับเชลล์การเข้าสู่ระบบเช่นเชลล์ที่ได้รับผ่านssh(และไม่ต้องพูดว่าในเชลล์ที่ได้รับผ่านgnome-terminal)
kos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.