โปรแกรมรันจากเซสชัน ssh ขึ้นอยู่กับการเชื่อมต่อหรือไม่?


29

โปรแกรมที่รันจากเซสชัน ssh นั้นขึ้นอยู่กับการเชื่อมต่อกับลูกค้าหรือไม่? ตัวอย่างเช่นเมื่อการเชื่อมต่อช้าจริงๆ ดังนั้นมันจะรอจนกว่าสิ่งที่พิมพ์บนหน้าจอหรือไม่

และถ้ามันขึ้นอยู่กับการเชื่อมต่อมันจะเกิดขึ้นกับหน้าจอหรือbyobuเช่นกัน? เนื่องจากโปรแกรมเหล่านี้ยังคงทำงานอยู่แม้จะถูกตัดการเชื่อมต่อจากโฮสต์


หมายเหตุ: ฉันพบคำถามที่เกี่ยวข้องเหล่านี้เท่านั้น:


1
โปรดทราบว่าหากการเชื่อมต่อของคุณขาดหายไปโปรแกรมจะยังคงทำงานต่อไปจนกว่าจะหมดเวลาเซสชัน (เว้นแต่จะติดอยู่ในการดำเนินการพิมพ์) แต่ถ้าเซสชันของคุณสิ้นสุดลงโปรแกรมจะสิ้นสุดลงอย่างสง่างาม
Sebb

คำตอบ:


26

เอาต์พุตของโปรแกรมถูกบัฟเฟอร์ดังนั้นหากการเชื่อมต่อช้าโปรแกรมจะหยุดทำงานหากบัฟเฟอร์เต็ม

ถ้าคุณใช้screenมันมีบัฟเฟอร์เช่นเดียวกับที่ใช้ในการลองและแสดงไปยังเซสชันที่เชื่อมต่อ แต่โปรแกรมที่เชื่อมต่อในเซสชันหน้าจอจะไม่หยุดหากscreenไม่สามารถอัปเดตเทอร์มินัลระยะไกลได้เร็วพอ เช่นเดียวกับเมื่อการเชื่อมต่อขาดหายไปโปรแกรมจะเติมscreensบัฟเฟอร์ต่อไปจนกว่าจะล้น (ผลักข้อมูลที่เก่าที่สุดออก) สิ่งที่คุณเห็นมาใน (และสามารถเลื่อนกลับไปที่) ขึ้นอยู่กับสิ่งที่ (นิ่ง) ในบัฟเฟอร์นั้น screenยกเลิกโปรแกรมของคุณอย่างมีประสิทธิภาพจากเทอร์มินัลของคุณ (และการเชื่อมต่อ SSH ที่ช้า)


9

การเชื่อมต่อ SSH สามารถตายก่อนกำหนดได้หากการเชื่อมต่อ TCP พื้นฐานได้รับแพ็คเก็ตที่มีการตั้งค่าสถานะRST ซึ่งอาจเกิดขึ้นได้หากด้านใดด้านหนึ่งส่งแพ็กเก็ต (ซึ่งอาจเป็นโพรบ Keepalive SSH เป็นระยะ) แต่ไม่ได้รับการตอบรับ TCP ในระยะเวลาที่เหมาะสมหรือหากเราเตอร์ตัดสินใจว่าการเชื่อมต่อนั้นไม่ได้ใช้งานนานเกินไปหรือหาก ISP เป็นเพียงแค่ความชั่วร้าย

ในโมเดลเทอร์มินัล Unix เมื่อการเชื่อมต่อเทอร์มินัลหลุดไดรเวอร์เทอร์มินัลส่งสัญญาณ HUPไปยังเชลล์ซึ่งการเลิกจ้างยังทำให้ SIGHUP ส่งไปยังกระบวนการที่ทำงานในเชลล์

จากคำถามที่พบบ่อยเกี่ยวกับโปรแกรมเมอร์ Unixรายการ 1.15:

SIGHUPเป็นสัญญาณที่มีความหมายว่า "สายขั้วถูกวางสาย" มันไม่มีส่วนเกี่ยวข้องกับกระบวนการพาเรนต์และมักจะสร้างโดยไดรเวอร์ tty (และส่งไปยังกลุ่มกระบวนการพื้นหน้า)

อย่างไรก็ตามเป็นส่วนหนึ่งของระบบการจัดการเซสชันมีสองกรณีที่SIGHUPถูกส่งไปที่กระบวนการของการตาย:

  • เมื่อกระบวนการที่ตายไปแล้วเป็นผู้นำเซสชันของเซสชันที่เชื่อมต่อกับอุปกรณ์เทอร์มินัลSIGHUPจะถูกส่งไปยังกระบวนการทั้งหมดในกลุ่มกระบวนการทำงานเบื้องหน้าของอุปกรณ์เทอร์มินัลนั้น

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

จัดการสัญญาณเริ่มต้นสำหรับ SIGHUPคือการยุติกระบวนการ:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process

มันเป็นไปได้ที่จะหลีกเลี่ยงการยกเลิกกระบวนการ

  • คุณสามารถแทรกตัวจัดการสัญญาณที่ละเว้น SIGHUP nohupต้องการทำเช่นนั้นเป็นผู้ใช้ห่อคำสั่งใน ตัวอย่างเช่น:

    nohup make all &
    
  • คุณสามารถบอกเชลล์เพื่อแยกการเชื่อมโยงกระบวนการลูกจากนั้น ตัวอย่างเช่น Bash มีdisownคำสั่งในตัว:

    make all
    

    CtrlZ

    bg
    disown %1
    

    จากนั้น SIGHUP จะไม่ถูกเผยแพร่ไปยังเด็ก (ซึ่งไม่ใช่เด็กอีกต่อไป)

  • บางโปรแกรมโดยเฉพาะdaemonsจะใช้กลไกด้านบนโดยอัตโนมัติ: โปรแกรมสามารถติดตั้งตัวจัดการ SIGHUP สำรอง (โดยใช้sigaction(2)) หรืออาจเลือกที่จะเข้าร่วมเซสชันใหม่ ( setsid(2))
  • คุณสามารถรันscreenหรือtmuxจัดสรร pseudo-TTY เพื่อรันเซสชันด้วยเชลล์ที่ไม่ได้รับ SIGHUP เมื่อการเชื่อมต่อ SSH ตาย SIGHUP ไม่ถูกถ่ายทอดจากเซสชัน SSH ไปยังเซสชัน screen / tmux

วิธีอื่นในการจัดการกับการเชื่อมต่อ SSH ที่ไม่น่าเชื่อถือคือการใช้โปรโตคอลMoshแทน Mosh ทำงานมากกว่า UDP ดังนั้นจึงไม่มีการเชื่อมต่อ TCP ที่มีความเสี่ยงในการรีเซ็ต



1

ใช่โปรแกรมที่ทำงานผ่าน SSH จะขึ้นอยู่กับเอาต์พุตของมันที่อื่น หากการเชื่อมต่อช้าออกจะต้องบัฟเฟอร์ที่ใดที่หนึ่งและบัฟเฟอร์ไม่สามารถไม่มีที่สิ้นสุดดังนั้นโปรแกรมจะต้องปิดกั้นหากพวกเขาจะเต็ม

โปรดทราบว่าผลลัพธ์อาจไม่จำเป็นต้องไปที่เทอร์มินัล: ลองใช้งานบางอย่างเช่น

ssh user@somewhere "cat file.txt" > file.txt

ซึ่งจะมีผลในการคัดลอกไฟล์ เพื่อการทำงานอัตราการส่งออกของแมวจะต้องตรงกับการเชื่อมต่อ: มันชัดเจนว่าการสูญเสียบางส่วนของเอาท์พุทจากตรงกลางจะไม่เป็นที่ยอมรับ

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

จากหน้าคน:

nonblock [เปิด | ปิด | numsecs]

บอกหน้าจอวิธีจัดการกับส่วนต่อประสานกับผู้ใช้ (จอแสดงผล) ที่หยุดรับเอาต์พุต สิ่งนี้สามารถเกิดขึ้นได้หากผู้ใช้กด ^ S หรือการเชื่อมต่อ TCP / โมเด็มได้รับการตัด แต่จะไม่ได้รับ Hangup หากไม่มีการปิดกั้นหน้าจอ (นี่คือค่าเริ่มต้น) จะรอจนกระทั่งจอแสดงผลรีสตาร์ทเพื่อยอมรับเอาต์พุต หากไม่มีการปิดกั้นหน้าจอจะรอจนกระทั่งถึงระยะหมดเวลา (จะถือว่าเป็น 1 วินาที) หากหน้าจอยังไม่ได้รับตัวอักษรหน้าจอจะพิจารณาว่า "ถูกบล็อก" และหยุดส่งตัวอักษรไปที่หน้าจอนั้น หากในบางครั้งมันรีสตาร์ทเพื่อยอมรับตัวอักษรหน้าจอจะปลดบล็อคจอแสดงผลและแสดงเนื้อหาหน้าต่างที่ได้รับการอัพเดตใหม่

การตัดการเชื่อมต่อแตกต่างจากการเชื่อมต่อที่ช้า ธรรมดา SSH ไม่สามารถกู้คืนได้โดยอัตโนมัติดังนั้นโปรแกรมของคุณจะได้รับ SIGHUP ในทางกลับกันหน้าจอจะตรวจจับการตัดการเชื่อมต่อถอดและถอยกลับไปที่การบัฟเฟอร์ในพื้นที่จนกว่าหน้าจอจะถูกแนบใหม่ สิ่งนี้จะไม่บล็อกโปรแกรมที่กำลังทำงานอยู่

(การตั้งค่าnonblock 1ของคุณ.screenrcเป็นสิ่งสำคัญหากคุณเรียกใช้บางอย่างเช่น irssi ที่จะสร้างผลลัพธ์อย่างต่อเนื่อง แต่ยังคงต้องพูดคุยกับเครือข่ายในเวลาเดียวกันการปิดกั้นจะนำไปสู่การตัดการเชื่อมต่อจาก IRC ซึ่งน่ารำคาญอย่างยิ่ง ... )

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