สิ่งที่กำหนดว่างานพื้นหลังถูกฆ่าตายเมื่อเปลือกออกหรือฆ่า?


12

คำถามนี้ได้เกิดขึ้นค่อนข้าง มาก ( จริงๆมาก ) แต่ผมหาคำตอบที่จะเป็นโดยทั่วไปที่ไม่สมบูรณ์ คำถามทั่วไปคือ "ทำไม / งานของฉันไม่ถูกฆ่าตายเมื่อฉันออกจาก / kill ssh?" และนี่คือสิ่งที่ฉันได้พบ คำถามแรกคือ: ข้อมูลต่อไปนี้เป็นอย่างไร? ต่อไปนี้น่าจะเป็นจริงสำหรับ Debian linux ที่ทันสมัย ​​แต่ฉันขาดหายไปบ้าง และคนอื่น ๆ จำเป็นต้องรู้อะไร

  1. กระบวนการลูกทั้งหมด, พื้นหลังหรือไม่ของเชลล์ที่เปิดผ่านการเชื่อมต่อ ssh จะถูกฆ่าด้วย SIGHUP เมื่อการเชื่อมต่อ ssh ถูกปิดเฉพาะในกรณีที่huponexitมีการตั้งค่าตัวเลือก: run shopt huponexitเพื่อดูว่าสิ่งนี้เป็นจริงหรือไม่

  2. หากhuponexitเป็นจริงคุณสามารถใช้nohupหรือdisownแยกส่วนกระบวนการออกจากเชลล์ดังนั้นจึงไม่ถูกฆ่าเมื่อคุณออกจาก screenหรือเรียกใช้สิ่งที่มี

  3. หากhuponexitเป็นเท็จซึ่งเป็นค่าเริ่มต้นใน linuxes อย่างน้อยวันนี้งานที่อยู่เบื้องหลังจะไม่ถูกฆ่าเมื่อออกจากระบบปกติ

  4. แต่แม้ว่าhuponexitจะเป็นเท็จแล้วหากการเชื่อมต่อ ssh ถูกฆ่าหรือลดลง (แตกต่างจากการออกจากระบบปกติ) กระบวนการพื้นหลังจะยังคงได้รับการฆ่า สิ่งนี้สามารถหลีกเลี่ยงได้โดยdisownหรือnohupใน (2)

  5. มีความแตกต่างระหว่าง (ก) กระบวนการที่มีพ่อแม่เป็นกระบวนการขั้วและ (ข) กระบวนการที่ได้ stdin, stdout, stderr หรือบางอย่างที่เชื่อมต่อไปยังสถานี ฉันไม่รู้ว่าเกิดอะไรขึ้นกับกระบวนการที่ (ก) และไม่ (ข) หรือในทางกลับกัน

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

แก้ไข:อีกวิธีที่สำคัญที่จะทำให้งานของการถูกฆ่าตายที่ทำงานในกรณีใดกรณีหนึ่งคือการทำงานให้พวกเขาผ่าน (?) หน้าจอ แต่คำถามนั้นเกี่ยวกับการทำความเข้าใจมากขึ้นเมื่อสิ่งต่าง ๆ ถูกฆ่าและเมื่อพวกเขาไม่ทำ: บางครั้งผู้คนต้องการให้งานถูกฆ่าเมื่อออกจากระบบ

หัวข้อเพิ่มเติม: - ชี้แจงเกี่ยวกับสัญญาณ (ถอนหายใจ) งานและสถานีควบคุม - /server/117152/do-background-processes-get-a-sighup-when-logging-off - SSH ต่อไป งาน / งานพื้นหลังเมื่อปิด SSH - งานที่ใส่ไว้ในพื้นหลังจะทำงานต่อไปหลังจากเซสชัน SSH ถูกปิดหรือไม่ - ป้องกันไม่ให้กระบวนการพื้นหลังที่ทำงานอยู่แล้วหยุดทำงานหลังจากปิดไคลเอนต์ SSH - ฉันจะเริ่มต้นกระบวนการผ่าน SSH ได้อย่างไรเพื่อให้กระบวนการทำงานต่อไปหลังจากที่ฉันยกเลิกการเชื่อมต่อ - ไม่สามารถให้งานรีโมตทำงานใน OS X ได้ - ปิดการเชื่อมต่อ SSH

คำตอบ:


1

กระบวนการไม่ "ถูกฆ่าด้วย SIGHUP" - อย่างน้อยไม่ใช่ในความหมายที่เข้มงวดของคำ แต่เมื่อการเชื่อมต่อหลุดกระบวนการควบคุมของเทอร์มินัล (ในกรณีนี้คือ Bash) จะถูกส่งสัญญาณการวางสาย * ซึ่งโดยปกติจะเรียกว่า "สัญญาณ HUP" หรือเพียงแค่ SIGHUP

ตอนนี้เมื่อกระบวนการรับสัญญาณมันสามารถจัดการได้ทุกอย่างที่มันต้องการ ** ค่าเริ่มต้นสำหรับสัญญาณส่วนใหญ่ (รวมถึง HUP) คือการออกทันที อย่างไรก็ตามโปรแกรมมีอิสระที่จะเพิกเฉยต่อสัญญาณแทนหรือแม้แต่เรียกใช้ฟังก์ชันตัวจัดการสัญญาณบางชนิด

Bash เลือกตัวเลือกสุดท้าย ตัวจัดการสัญญาณ HUP จะตรวจสอบเพื่อดูว่าตัวเลือก "huponexit" เป็นจริงหรือไม่และหากเป็นเช่นนั้นส่ง SIGHUP ไปยังกระบวนการลูกแต่ละกระบวนการ เพียงครั้งเดียวมันจบด้วย Bash ที่ออก

กระบวนการของเด็กแต่ละคนมีอิสระที่จะทำสิ่งที่ต้องการเมื่อได้รับสัญญาณ: ปล่อยให้มันตั้งค่าเริ่มต้น (เช่นตายทันที) ไม่สนใจมันหรือเรียกใช้ตัวจัดการสัญญาณ

Nohup เพียงเปลี่ยนการกระทำเริ่มต้นสำหรับกระบวนการลูกเพื่อ "ละเว้น" เมื่อกระบวนการลูกทำงาน แต่ไม่มีการเปลี่ยนแปลงการตอบสนองของสัญญาณเอง

ฉันคิดว่านี่เป็นเหตุผลว่าทำไมบางโปรแกรมถึงตายถึงแม้ว่าคุณจะรันโปรแกรมเหล่านั้นด้วย nohup:

  1. Nohup ตั้งค่าการกระทำเริ่มต้นเป็น "ละเว้น"
  2. โปรแกรมจำเป็นต้องทำการล้างข้อมูลบางอย่างเมื่อออกดังนั้นจึงติดตั้งตัวจัดการ SIGHUP โดยบังเอิญเขียนทับแฟล็ก "ละเว้น"
  3. เมื่อ SIGHUP มาถึงตัวจัดการจะเรียกใช้ทำความสะอาดไฟล์ข้อมูลของโปรแกรม (หรือสิ่งที่จำเป็นต้องทำ) และออกจากโปรแกรม
  4. ผู้ใช้ไม่ทราบหรือไม่สนใจเกี่ยวกับตัวจัดการหรือการล้างข้อมูลและเพิ่งเห็นว่าโปรแกรมออกจากแม้จะไม่มีข้อความใด ๆ

นี่คือที่มาของ "การปฏิเสธ" กระบวนการที่ถูกปฏิเสธโดย Bash จะไม่ส่งสัญญาณ HUP โดยไม่คำนึงถึงตัวเลือก huponexit ดังนั้นแม้ว่าโปรแกรมจะตั้งค่าตัวจัดการสัญญาณของตัวเองสัญญาณจะไม่ถูกส่งจริงดังนั้นตัวจัดการจะไม่ทำงาน อย่างไรก็ตามโปรดทราบว่าหากโปรแกรมพยายามที่จะแสดงข้อความให้กับผู้ใช้ที่ออกจากระบบก็จะทำให้เกิดข้อผิดพลาด I / O ซึ่งอาจทำให้โปรแกรมออกจากต่อไป

* และใช่ก่อนที่คุณจะถามคำศัพท์ "hang-up" จะค้างอยู่จากวันที่เฟรมการโทรของ UNIX

** สัญญาณส่วนใหญ่อยู่ดี ตัวอย่างเช่น SIGKILL จะทำให้โปรแกรมหยุดทำงานทันทีในช่วงเวลา


2

จุดที่ 1-4 นั้นถูกต้องฉันไม่รู้อะไรเกี่ยวกับจุดที่ 5 สำหรับจุดสุดท้ายของคุณแอปพลิเคชั่นที่ดีหน้าจอจะช่วยให้คุณสามารถทำให้กระบวนการทั้งหมดทำงานตามปกติโดยไม่คำนึงว่าคุณจะยุติการเชื่อมต่ออย่างไร หน้าจออยู่ใน repos

คำอธิบายผู้ชายของหน้าจอไม่ใช่เรื่องง่ายที่จะอ่าน แต่เหนือสิ่งอื่นใดมันระบุ:

เมื่อหน้าจอถูกเรียกมันจะสร้างหน้าต่างเดียวโดยมีเชลล์อยู่ในนั้น (หรือคำสั่งที่ระบุ) จากนั้นจึงออกนอกเส้นทางของคุณเพื่อให้คุณสามารถใช้โปรแกรมได้ตามปกติ จากนั้นทุกเวลาคุณสามารถสร้างหน้าต่างใหม่ (แบบเต็มหน้าจอ) ด้วยโปรแกรมอื่น ๆ ในหน้าต่างเหล่านั้น (รวมถึง shells เพิ่มเติม), ฆ่า windows ที่มีอยู่, ดูรายการ windows, เปิดและปิดการบันทึกผลลัพธ์, คัดลอกและวางข้อความ ระหว่าง windows, ดูประวัติ scrollback, สลับระหว่าง windows ในลักษณะใด ๆ ที่คุณต้องการ, ฯลฯ windows ทั้งหมดเรียกใช้โปรแกรมของพวกเขาอย่างสมบูรณ์ indepen‐ กันและกัน โปรแกรมยังคงทำงานต่อไปเมื่อหน้าต่างของพวกเขาไม่สามารถมองเห็นได้และแม้ในขณะที่เซสชันหน้าจอทั้งหมดถูกถอดออกจากเทอร์มินัลของผู้ใช้. เมื่อโปรแกรมหยุดทำงานหน้าจอ (ต่อค่าเริ่มต้น) จะฆ่าหน้าต่างที่มีอยู่ หากหน้าต่างนี้อยู่เบื้องหน้าจอแสดงผลจะสลับไปที่หน้าต่างก่อนหน้า หากไม่มีสิ่งใดเหลืออยู่หน้าจอจะออก

ฉันได้เน้นส่วนที่สำคัญที่สุด: คุณสามารถแยกหน้าต่างด้วยคำสั่ง Ctrl + a + d จากนั้นคุณอาจฆ่า / ออกจากระบบเซสชันของคุณและหน้าต่างที่แยกออกตอนนี้จะยังคงทำงานต่อไปโดยโปรแกรมภายในยังคงทำงานอยู่ เมื่อคุณเชื่อมต่อกลับเช่นโดยเริ่มเซสชัน ssh ใหม่หน้าจอคำสั่ง-rจะกลับมาทำงานเซสชันหน้าจอที่ถูกถอดออกก่อนหน้านี้พร้อมกับเอาต์พุตทั้งหมดไปยังข้อผิดพลาด / เอาต์พุตมาตรฐานที่มองเห็นได้ชัดเจน

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