การตัดการเชื่อมต่อจากเซสชัน SSH จะทำให้โปรแกรมของคุณเสียหายหรือไม่?


88

ดังนั้นสมมติว่าฉันถูกตัดการเชื่อมต่อจากเซสชัน SSH หลังจากที่ฉันเริ่มrsyncหรือcpคำสั่งอื่น ๆ ที่สามารถใช้งานได้นาน คำสั่งนั้นยังคงทำงานต่อไปจนกว่าจะเสร็จสิ้นหลังจากที่ฉันถูกตัดการเชื่อมต่อหรือเพิ่งถูกฆ่า?

สงสัยในสิ่งนี้เสมอ


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

มันจะฆ่าโปรแกรมของคุณ น่ารำคาญมากถ้าคุณกำลังอัปเดตเวอร์ชัน OS จากพูดว่า Ubuntu 16.04 ถึง 17.10 ผ่าน SSH
kurdtpage

คำตอบ:


118

แก้ไขสำหรับปี 2016:

Q & A นี้ถือกำเนิดน้ำท่วม V230 systemd ในฐานะของ systemd v230 ค่าดีฟอลต์ใหม่คือการฆ่าชายด์ทั้งหมดของเซสชันการล็อกอินที่ถูกยกเลิกโดยไม่คำนึงถึงข้อควรระวังที่ถูกต้องในอดีตที่ถูกใช้เพื่อป้องกันสิ่งนี้ พฤติกรรมที่สามารถเปลี่ยนแปลงได้โดยการตั้งค่าKillUserProcesses=noใน/etc/systemd/logind.confหรือโกงโดยใช้กลไก systemd เฉพาะสำหรับการเริ่มต้นภูตใน userspace กลไกเหล่านั้นอยู่นอกขอบเขตของคำถามนี้

ข้อความด้านล่างอธิบายถึงวิธีการทำงานแบบดั้งเดิมใน UNIX designspace เป็นเวลานานกว่า Linux


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

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

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

กระบวนการที่อยู่รอดจาก Hangup ของเทอร์มินัลการควบคุมนั้นเป็นกระบวนการที่ยกเลิกการเชื่อมโยงตัวเองจากการมีเทอร์มินัล (กระบวนการ daemon ที่คุณเริ่มภายใน) หรือกระบวนการที่ถูกเรียกใช้ด้วยnohupคำสั่งที่นำหน้า (เช่น "อย่าวางสายบนนี้") Daemons ตีความสัญญาณ HUP แตกต่างกัน เนื่องจากไม่มีเทอร์มินัลการควบคุมและไม่ได้รับสัญญาณ HUP โดยอัตโนมัติจึงมีการใช้งาน repurposed แทนเป็นการร้องขอด้วยตนเองจากผู้ดูแลระบบเพื่อโหลดการกำหนดค่าใหม่ สิ่งนี้หมายความว่าผู้ดูแลระบบส่วนใหญ่ไม่ได้เรียนรู้การใช้งาน "hangup" ของสัญญาณนี้สำหรับผู้ที่ไม่ได้เป็น daemons จนกระทั่งมาถึงมากในภายหลัง นั่นเป็นเหตุผลที่คุณกำลังอ่านข้อความนี้!

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


มีการร้องขอให้ฉันทำอย่างละเอียดว่า SSH daemon ใช้เวลานานแค่ไหนในการตัดสินใจว่าการเชื่อมต่อของคุณจะตาย นี่เป็นลักษณะการทำงานที่เฉพาะเจาะจงกับทุกการใช้งานของ SSH daemon แต่คุณสามารถวางใจได้ว่าพวกเขาทั้งหมดจะยุติเมื่อทั้งสองฝ่ายรีเซ็ตการเชื่อมต่อ TCP สิ่งนี้จะเกิดขึ้นอย่างรวดเร็วหากเซิร์ฟเวอร์พยายามเขียนลงในซ็อกเก็ตและแพ็กเก็ต TCP จะไม่ได้รับการยอมรับหรือช้าลงหากไม่มีสิ่งใดที่พยายามจะเขียนไปยัง PTY

ในบริบทนี้ปัจจัยที่มีแนวโน้มที่จะทริกเกอร์การเขียนคือ:

  • กระบวนการ (โดยปกติจะเป็นกระบวนการที่อยู่ด้านหน้า) พยายามที่จะเขียนไปยัง PTY ทางฝั่งเซิร์ฟเวอร์ (เซิร์ฟเวอร์> ลูกค้า)
  • ผู้ใช้พยายามเขียนไปยัง PTY บนฝั่งไคลเอ็นต์ (แบบ client> เซิร์ฟเวอร์)
  • รักษาทุกประเภท โดยปกติแล้วสิ่งเหล่านี้จะไม่เปิดใช้งานโดยค่าเริ่มต้นไม่ว่าจะโดยไคลเอนต์หรือเซิร์ฟเวอร์และโดยทั่วไปจะมีสองรสชาติ: ระดับแอปพลิเคชันและ TCP (เช่นSO_KEEPALIVE) จำนวน Keepalives กับเซิร์ฟเวอร์หรือไคลเอนต์ส่งแพ็กเก็ตไปอีกด้านนาน ๆ ครั้งแม้ว่าจะไม่มีเหตุผลใดที่จะมีเหตุผลในการเขียนไปยังซ็อกเก็ต แม้ว่าโดยทั่วไปแล้วสิ่งนี้จะทำให้ไฟร์วอลล์ไฟร์วอลล์นั้นหมดเวลาเชื่อมต่อเร็วเกินไป แต่ก็มีผลข้างเคียงที่ทำให้ผู้ส่งสังเกตเห็นเมื่ออีกด้านหนึ่งไม่ตอบสนองเร็วขึ้น

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

หากฝ่ายใดฝ่ายหนึ่งตัดสินใจว่าซ็อกเก็ตนั้นตายโดยปกติแล้วเอฟเฟกต์จะเกิดขึ้นทันที: กระบวนการ sshd จะส่งHUPและสิ้นสุดด้วยตนเอง (ดังที่อธิบายไว้ก่อนหน้านี้) หรือไคลเอ็นต์จะแจ้งให้ผู้ใช้ทราบถึงปัญหาที่ตรวจพบ มันเป็นเรื่องน่าสังเกตว่าเพียงเพราะฝ่ายหนึ่งคิดว่าอีกฝ่ายเป็นคนตายไม่ได้หมายความว่าอีกฝ่ายได้รับแจ้งเรื่องนี้แล้ว โดยปกติแล้วด้านที่ไม่ได้ใช้งานของการเชื่อมต่อจะยังคงเปิดอยู่จนกว่าจะพยายามเขียนและหมดเวลาหรือรับการรีเซ็ต TCP จากอีกด้านหนึ่ง (หากการเชื่อมต่อพร้อมใช้งานในเวลานั้น) การล้างข้อมูลที่อธิบายในคำตอบนี้จะเกิดขึ้นเมื่อเซิร์ฟเวอร์สังเกตเห็นเท่านั้น


3
ฉันยังเพิ่มคำสั่ง 'dtach' ลงในรายการนั้น - มันตรงกันข้ามกับหน้าจอ / tmux ซึ่งช่วยให้คุณสามารถเชื่อมต่อเทอร์มินัลหลายตัวเข้ากับเซสชันเดียวและยังยอดเยี่ยมสำหรับการยืดเซสชันแม้ว่ามันจะไม่ ให้วิธีการใด ๆ ในการเล่นประวัติล่าสุด
ปุย

dtachurl อยู่ที่นี่: dtach.sourceforge.net
slm

2
คำอธิบายที่ดีเยี่ยม ฉันรู้สึก linuxey มากขึ้นแล้ว!
fregas

3
แม้ว่าจะไม่ได้เป็นส่วนหนึ่งของคำตอบของคุณ แต่นี่เป็นเรื่องเล็กน้อยที่น่าสนใจ: คุณสามารถใช้kill -HUPเป็นรากเพื่อบังคับให้เทอร์มินัลของใครบางคนวางสาย คุณไม่ควรทำสิ่งนี้โดยไม่มีเหตุผลที่ดี ฉันได้รับไมล์สะสมส่วนใหญ่จากการใช้งานเมื่อผู้ใช้ปล่อยให้เชลล์ทำงานในระหว่างการบำรุงรักษาและฉันจำเป็นต้องยกเลิกการต่อเชื่อมระบบไฟล์ที่เชลล์เปิดอยู่ หากผู้ใช้เชื่อมต่อ แต่ไม่ได้ใช้งานเป็นระยะให้ส่งสัญญาณไปยังกระบวนการ sshd มิฉะนั้นถ้ามันทำงานอยู่ภายใน terminal multiplexer ให้ส่งมันไปยัง shell ที่คุณต้องการหยุด วางสายเท่านั้นที่จะทำให้คุณไม่ทำงาน!
Andrew B

@AndrewB คุณช่วยอธิบายรายละเอียดเกี่ยวกับวิธี "กระบวนการภูต SSH ... ตัดสินใจว่าการเชื่อมต่อของคุณตาย" และฉันจะรู้ได้อย่างไรว่า SSH daemon คิด / รู้ว่าการเชื่อมต่อ (ซึ่ง) นั้นตายหรือไม่?
Xiao Peng - ZenUML.com

22

ดังที่คนอื่น ๆ ได้กล่าวไว้เมื่อคุณตัดการเชื่อมต่อจากสิ่งที่ทำงานอยู่ภายในมันจะหายไป

ดังที่@Michael Hamptonและคนอื่น ๆ พูดถึงคุณสามารถใช้เครื่องมือเช่นtmuxหรือscreenยกเลิกการเชื่อมต่อ / เชื่อมต่อกับเทอร์มินัลโดยไม่สูญเสียเนื้อหาของพวกเขา (เช่นกระบวนการลูก)

นอกจากนี้คุณสามารถใส่กระบวนการลงในพื้นหลังโดยใช้เครื่องหมาย&และจากนั้นใช้คำสั่งdisownเพื่อยกเลิกการเชื่อมโยงกระบวนการเหล่านั้นกับเชลล์ปัจจุบัน

# start a command
% sleep 5000 &
[1] 3820

# check it
% jobs
[1]+  Running                 sleep 5000 &

# disown everything
% disown -a

# check it again (gone from shell)
% jobs
%

# but it's still running on the system
% ps -eaf|grep "[s]leep"
saml      3820 23791  0 00:16 pts/1    00:00:00 sleep 5000
%

เป็นไปได้ไหมที่จะทำการเชื่อมต่อเทอร์มินัลเซสชันกับdisownกระบวนการ ed อีกครั้ง?
ชื่อปลอม

4
ใช่. ดูคำถาม U&L นี้สำหรับรายละเอียด: unix.stackexchange.com/questions/4034/…
slm

13

ไม่โปรแกรมใด ๆ ที่ยังคงติดอยู่กับเครื่องและไม่ได้ถูกวางไว้ในพื้นหลังด้วยสิ่งที่คล้ายnohupกันจะถูกฆ่า

นี่คือเหตุผลที่มีโซลูชันเทอร์มินัลเสมือนเช่นเดียวtmuxกับที่เก่ากว่าscreenซึ่งสร้างเซสชันที่ทำงานต่อไปแม้ว่าคุณจะถูกตัดการเชื่อมต่อและคุณสามารถติดตั้งใหม่ได้ในภายหลัง

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