เหตุใด“ su -c <command> &” จึงอนุญาตให้คำสั่งทำงานในพื้นหลังโดยไม่ต้องวางสาย


11

ฉันช่วยเพื่อนร่วมงานที่กำลังมีปัญหากับกระบวนการพื้นหลังที่กำลังจะตายเป็นระยะ

ฉันพบว่าพวกเขาเริ่มกระบวนการพื้นหลังด้วยการเข้าสู่เซิร์ฟเวอร์และดำเนินการ:

su - <user> -c '<command>' &

"Aha" ฉันอุทาน "ถ้าคุณเริ่มต้นคำสั่งด้วย" & "คำสั่งจะวางสายเมื่อคุณออกจากเทอร์มินัลการควบคุมคุณต้องใช้บางอย่างเช่น nohup เพื่อให้บรรลุสิ่งนี้จริง ๆ แล้วกระบวนการนี้ต้องรองรับการทำงานเป็น daemon, tut tut"

เราทดสอบคำสั่งข้างต้นเพื่อแสดงให้เห็นถึงจุดของฉันและ ... มันดูเหมือนจะทำงาน: กระบวนการเริ่มต้นโดยคำสั่งไม่ได้ออกเมื่อเราออกจากสถานีที่วิ่งคำสั่งดังกล่าว

commandเป็นสคริปต์ Python ที่กำหนดเองซึ่งเอาต์พุตไปที่ไฟล์ เท่าที่ฉันสามารถบอกได้ไม่มี "daemonize" ที่ชาญฉลาดเหมือนความสามารถในสคริปต์ มันไม่ได้ทำสิ่งใด ๆ ที่จำเป็นในการใช้งานเป็น daemon ที่ระบุไว้ในWikipedia: Daemon (คำนวณ):หน้าสร้าง

การรันคำสั่งเช่นนั้นจะทำงานตามที่คาดไว้:

<command> &
exit

ในกรณีข้างต้นกระบวนการพื้นหลังเริ่มต้นโดยคำสั่งออกเมื่อเราออกจากสถานี

คำถามของฉันคือ:

  1. เกิดอะไรขึ้นเมื่อเราเพิ่ม "su - -c &" ที่ป้องกันไม่ให้กระบวนการออกจากเมื่อเครื่องของเราออก ฉันต้องการที่จะเข้าใจในรายละเอียดเกี่ยวกับสถานีควบคุมอินพุตมาตรฐานและเอาท์พุท ฯลฯ

  2. นี่เป็นวิธีที่สมเหตุสมผลในการบรรลุเป้าหมายของการรันคำสั่งนี้เป็นกระบวนการพื้นหลังหรือไม่ ถ้าไม่ใช่เพราะอะไร

ฉันต้องการเผยแพร่แนวปฏิบัติที่ดีที่สุดภายใน บริษัท ของฉัน แต่ฉันต้องสามารถแสดงและสำรองข้อมูลคำแนะนำใด ๆ ที่ฉันทำ

ฉันยังต้องการที่จะเข้าใจสิ่งที่เกิดขึ้นอย่างแน่นอน

คำตอบ:


12

มีหลายวิธีที่กระบวนการอาจถูกฆ่าเนื่องจากเทอร์มินัลที่กำลังจะตาย

  1. วิธีแรกคือการที่คนขับรถมินัลใน kernel ส่งสัญญาณ SIGHUPกับกระบวนการควบคุมที่สถานีเป็นสถานีควบคุม ในกรณีส่วนใหญ่กระบวนการควบคุมคือเชลล์ที่เริ่มต้นในเทอร์มินัลและเทอร์มินัลการควบคุมนั้นเป็นกระบวนการที่ stdin, stdout และ stderr เชื่อมต่ออยู่ setsidกระบวนการตัดการเชื่อมต่อจากสถานีควบคุมถ้ามันเรียกร้อง

  2. วิธีที่สองคือเชลล์เมื่อได้รับ SIGHUP จะส่งสัญญาณนั้นไปยังกระบวนการย่อยอีกครั้ง - แม่นยำยิ่งขึ้นไปยังงานพื้นหลัง เชลล์บางตัว (ksh, bash, zsh) มีdisownbuiltin เพื่อบอกเชลล์ไม่ให้ส่ง SIGHUP ไปยังงานเฉพาะ

  3. หากเทอร์มินัลหายไปและโปรแกรมพยายามอ่านจากเครื่องจะแจ้งให้ทราบถึงสภาพการสิ้นสุดไฟล์ (หรืออาจเป็น EIO สำหรับงานแบ็คกราวน์) หากเทอร์มินัลหายไปและโปรแกรมพยายามเขียนลงไปการเขียนจะส่งคืนพร้อมข้อผิดพลาด EIO สิ่งเหล่านี้อาจทำให้โปรแกรมออกจาก

ดังนั้นsuการเปลี่ยนแปลงที่นี่คือ (2) โดยปกติจะทำให้เชลล์เริ่มต้นฆ่างานแบ็คกราวน์ แต่เนื่องจากกระบวนการแบ็คกราวน์นั้นทำงานในฐานะผู้ใช้คนอื่นสัญญาณจึงไม่สามารถส่งได้และกระบวนการแบ็คกราวน์จะทำงาน


chroot --userspec root:root / sh -c "exec some_forever_process" &ผมเคยเห็นรากทำผู้ใช้ งานกำลังเรียกใช้ในฐานะผู้ใช้เดียวกันโดยไม่มีความชัดเจนnohupก่อนหรือdisownหลัง ดังนั้นสำหรับกรณีนี้มันไม่สามารถส่งสัญญาณในระยะทางออกได้อย่างไร
Toddius Zho

@ToddiusZho สันนิษฐานว่าsome_forever_processมีวัตถุประสงค์เพื่อให้ทำงานได้ตลอดไป (daemon) และป้องกันตัวเองจากการรับ SIGHUP จากทางออกของเทอร์มินัล (โดยการทำงานในกลุ่มกระบวนการของตัวเอง)
Gilles 'หยุดชั่วร้าย'

bash / tail ไม่ได้ป้องกัน SIGHUP แต่ก็ยังใช้งานได้: `` `local $ ssh root @ REMOTE_HOST # chroot #usropec ระยะไกล #: ราก / sh -c" exec bash -c 'tail -f / dev / null '"& [1] 6376 remote # ps -p $! - ไม่มีส่วนหัว -o pid, uid, คำสั่ง -ww 6376 0 หาง -f / dev / null รีโมต # ออกจากโลคัล $ ssh root @ REMOTE_HOST remote # ps -p 6376 - ไม่มีส่วนหัว -o pid, uid, คำสั่ง -ww 6376 0 tail -f / dev / null `` `
Toddius Zho
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.