เซสชัน tmux ถูกฆ่าเมื่อตัดการเชื่อมต่อจาก ssh


23

สรุป : ฉันกำลังพยายามหาสาเหตุว่าทำไมเซสชัน tmux ของฉันถึงตายเมื่อฉันตัดการเชื่อมต่อจาก ssh

รายละเอียด :

ฉันติดตั้ง tmux ไว้ในระบบ Arch Linux แล้ว เมื่อฉันเริ่มเซสชัน tmux ฉันสามารถแยกออกจากมันแล้วแนบอีกครั้งในขณะที่เซสชัน ssh ใช้งานอยู่ แต่ถ้าฉันจบเซสชัน ssh ของฉันดังนั้นเซสชัน tmux จะถูกฆ่า

ฉันรู้ว่านี่ไม่ใช่พฤติกรรมปกติเพราะฉันมีระบบอื่นที่เซสชัน tmux ยังคงทำงานแม้ว่าจะสิ้นสุดเซสชัน ssh และฉันสามารถแนบกับเซสชัน tmux หลังจากสร้างการเชื่อมต่อ ssh ใหม่ ระบบที่มีปัญหาและระบบที่ทำงานอย่างถูกต้องมีการกำหนดค่าที่คล้ายกันมากดังนั้นฉันไม่แน่ใจว่าจะตรวจสอบอะไร

ฉันใช้ tmux เวอร์ชั่น 1.9a ระบบที่มีปัญหา (ที่ฉันมีการเข้าถึงรูท) มี Linux kernel เวอร์ชั่น 3.17.4-1 และระบบที่ทำงานถูกต้องมี kernel รุ่น 3.16.4-1-ARCH (ฉันไม่มีรูทอยู่ ระบบ). ฉันสงสัยว่าเวอร์ชันเคอร์เนลเป็นสาเหตุของปัญหา แต่นั่นเป็นเพียงความแตกต่างเดียวที่ฉันสังเกตเห็น

ฉันคิดว่าฉันขอให้ดูว่าใครเห็นปัญหาที่คล้ายกันและรู้วิธีแก้ปัญหาที่เป็นไปได้หรือไม่

ขั้นตอนที่แม่นยำที่นำไปสู่ปัญหาคือ:

  1. ssh กับเครื่อง
  2. รันtmuxเพื่อเริ่ม tmux
  3. ctrl-B D เพื่อแยกออก (ตอนนี้ฉันสามารถติดตั้งใหม่ได้ด้วย tmux attach
  4. ปิดเซสชัน ssh (ณ จุดนี้เซสชัน tmux ถูกฆ่าฉันสามารถสังเกตได้เมื่อฉันเข้าสู่ระบบในฐานะรูทในเทอร์มินัลอื่น)
  5. เชื่อมต่อกับ SSH และเรียกใช้tmux attachและฉันได้รับข้อความno sessionsและทำงานผลตอบแทนtmux ls failed to connect to server: Connection refusedสิ่งนี้สมเหตุสมผลเนื่องจากการให้บริการไม่ได้ทำงาน สิ่งที่ไม่สมเหตุสมผลสำหรับฉันคือเหตุผลที่มันถูกฆ่าในขั้นตอนที่ 4 เมื่อฉันตัดการเชื่อมต่อจากเซสชัน ssh

ข้อมูล strace:

ในการตอบสนองต่อหนึ่งในความคิดเห็นที่ฉันใช้ strace เพื่อดูสิ่งที่ระบบเรียกกระบวนการเซิร์ฟเวอร์ tmux ทำ ดูเหมือนว่าเมื่อฉันออกจากเซสชัน ssh ของฉัน (โดยการพิมพ์exitหรือด้วยctrl-d) ว่ากระบวนการ tmux จะถูกฆ่า นี่เป็นตัวอย่างของส่วนสุดท้ายของเอาต์พุต strace

poll([{fd=4, events=POLLIN}, {fd=11, events=POLLIN}, {fd=6, events=POLLIN}], 3, 424) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=1, si_uid=0} ---
sendto(3, "\17", 1, 0, NULL, 0)         = 1
+++ killed by SIGKILL +++

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


เพื่อให้แน่ใจว่าได้โปรดอธิบายทีละขั้นตอน: ฉันถือว่าคุณ ssh เริ่มเซสชั่น tmux แยกออกจากเซสชั่นและปิด shh: เมื่อคุณ ssh อีกครั้งคุณไม่มีทางที่จะเข้าร่วมเซสชั่น tmix? นั่นคือเซสชั่นจะไม่ทำงานอีกต่อไป?
Olivier Dulac

@OlivierDulac ใช่สมมติฐานของคุณถูกต้อง ฉันได้แก้ไขคำถามเพื่อรวมรายละเอียดเหล่านี้ด้วย
Gabriel Southern

คุณจะปิดเซสชัน ssh ได้อย่างไร และคุณสามารถแนบ strace กับ pid ของ tmux และอีกอันกับ pid ของ sshd เพื่อดูว่ามันได้รับบางอย่างเมื่อคุณปิดการเชื่อมต่อ ssh (verbose มาก, เปลี่ยนเส้นทางไปยังไฟล์)
Olivier Dulac

@OlivierDulac ขอบคุณสำหรับคำแนะนำ ฉันได้อัปเดตคำถามด้วยข้อมูลจาก strace ดูเหมือนว่ากระบวนการเซิร์ฟเวอร์ tmux กำลังถูกทำลายเมื่อฉันสิ้นสุดเซสชัน ssh ฉันไม่คิดว่ามันควรจะเกิดขึ้นดังนั้นฉันต้องหาสาเหตุที่มันเกิดขึ้น
Gabriel Southern

เริ่ม tmux ด้วยการเปิดใช้งานการบันทึก verbose และดูว่ามีอะไรที่พิมพ์ไปยังบันทึกเมื่อคุณตัดการเชื่อมต่อ นอกจากนี้ TERM ในเครื่องระยะไกลเข้าและออกจาก tmux คืออะไร?
jasonwryan

คำตอบ:


16

ทฤษฎี

ระบบ init บางระบบรวมถึง systemd จัดเตรียมคุณลักษณะเพื่อฆ่ากระบวนการทั้งหมดที่เป็นของบริการ บริการมักจะเริ่มกระบวนการเดียวซึ่งสร้างกระบวนการเพิ่มเติมโดยการฟอร์กและกระบวนการเหล่านั้นสามารถทำได้เช่นกัน โดยทั่วไปกระบวนการดังกล่าวถือเป็นส่วนหนึ่งของบริการ ใน systemd นี้จะกระทำโดยใช้cgroups

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

การเปิดใช้งาน Killmode และซ็อกเก็ต

พฤติกรรมเริ่มต้นสามารถเปลี่ยนแปลงได้โดยใช้KillModeคำสั่ง โปรเจ็กต์อัปสตรีมไม่ได้ AFAIK รวม.serviceไฟล์ใด ๆและไฟล์เหล่านั้นแตกต่างกันไปตามการกระจาย โดยทั่วไปมีสองวิธีในการเปิดใช้งาน SSH ในระบบของคุณ หนึ่งคือคลาสสิกssh.serviceที่ดูแล daemon SSH ที่ใช้งานมานานบนเครือข่าย อีกอย่างคือการเปิดใช้งานซ็อกเก็ตที่จัดการโดยssh.socketที่จะเริ่มต้นsshd@.serviceซึ่งจะทำงานเฉพาะสำหรับเซสชั่น SSH เดียว

โซลูชั่น

หากกระบวนการของคุณถูกฆ่าเมื่อสิ้นสุดเซสชันอาจเป็นไปได้ว่าคุณกำลังใช้การเปิดใช้งานซ็อกเก็ตและจะถูกฆ่าโดย systemd เมื่อพบว่ากระบวนการเซสชัน SSH ออก ในกรณีนั้นมีวิธีแก้ไขสองวิธี หนึ่งคือการหลีกเลี่ยงการใช้เปิดใช้งานซ็อกเก็ตโดยใช้แทนssh.service ssh.socketอื่น ๆ คือการตั้งค่าKillMode=processในส่วนของServicessh@.service

การKillMode=processตั้งค่าอาจมีประโยชน์กับแบบคลาสสิกssh.serviceเนื่องจากจะหลีกเลี่ยงการฆ่ากระบวนการเซสชัน SSH หรือกระบวนการหน้าจอหรือกระบวนการtmuxเมื่อเซิร์ฟเวอร์หยุดทำงานหรือรีสตาร์ท

บันทึกในอนาคต

เห็นได้ชัดว่าคำตอบนี้ได้รับความนิยมในระดับหนึ่ง ในขณะที่มันทำงานกับ OP มันอาจเกิดขึ้นว่ามันไม่ทำงานสำหรับใครบางคนในอนาคตเนื่องจากsystemd-logind การพัฒนาหรือการกำหนดค่า โปรดตรวจสอบเอกสารเกี่ยวกับเซสชันการเข้าสู่ระบบหากคุณพบพฤติกรรมที่แตกต่างจากคำอธิบายในคำตอบนี้


มีข้อเสนอแนะใด ๆ จากผู้ลงคะแนนหรือเพียงแค่หมุนเล่น?
Pavel Šimerda

3
ขอบคุณสำหรับการตอบสนองอย่างละเอียด การสลับไปใช้ sshd.service ช่วยแก้ไขปัญหาได้
Gabriel Southern

ฉันพบปัญหานี้ในระบบโดยใช้มากกว่าinit systemdแต่มันก็แตกต่างกันเล็กน้อยแล้วดูคำถามของฉัน
gerrit

5

คุณใช้ systemd ด้วยการเปิดใช้งานซ็อกเก็ตสำหรับ SSH หรือไม่

ถ้าเป็นเช่นนั้นมีปัญหาที่ทราบแล้วว่า ตามผู้เสนอ systemd นี่เป็นคุณลักษณะ - systemd ฆ่ากระบวนการทั้งหมดที่เกิดจากเซสชันเมื่อเซสชันสิ้นสุดลง (ฉันเห็นได้ว่ามีประโยชน์ แต่ใน GNU screenหรือtmuxกรณีคุณไม่ต้องการแน่นอนว่า☺หรือในกรณีอื่น ๆ ส่วนใหญ่ที่ผู้ใช้อาจใช้กระบวนการพื้นหลังแน่นอน)

ถ้าเป็นเช่นนั้นลองเปลี่ยนจากsshd.socketsshd.serviceการ


1
ฉันจะบอกว่าโดยทั่วไปคุณไม่ต้องการใช้คุณลักษณะนั้นสำหรับการเข้าสู่ระบบ SSH หากผู้ใช้ของคุณได้รับอนุญาตให้เรียกใช้กระบวนการที่ทำงานหลังจากออกจากระบบ ที่ไม่เฉพาะกับหน้าจอหรือ tmux แต่แทนที่จะ SSH (มีกระบวนการพื้นหลังใด ๆ ในฝั่งเซิร์ฟเวอร์)
Pavel Šimerda

2
@ PavelŠimerdaใช่ฉันคิดว่าโดยปริยาย แต่แก้ไขโพสต์เพื่อให้ชัดเจนยิ่งขึ้นในขณะนี้
mirabilos

3

ฉันมีปัญหาเดียวกันกับ tmux และหน้าจอบน Ubuntu 16.04 (kde Neon) เมื่อเซสชัน ssh ถูกตัดการเชื่อมต่อหน้าจอ / tmux ถูกยกเลิก

เรื่องสั้นสั้น systemd เปลี่ยนการตั้งค่าเริ่มต้นเป็น killuserprocess = ใช่ดังนั้นหลังจากออกจากเซสชัน ssh ทุกกระบวนการที่สร้างขึ้นจะถูกยกเลิก

แก้ไขปัญหาได้ง่าย (หลังจากพยายามหลายชั่วโมง) เรียกใช้หน้าจอ / tmux โดยใช้คำสั่งนี้

สำหรับหน้าจอ

systemd-run --scope --user screen

สำหรับ Tmux

systemd-run --scope --user tmux

คุณสามารถสร้างชื่อแทนเพื่อให้ง่ายขึ้น

alias tmux= "systemd-run --scope --user tmux"


-bash: systemd-run: command not foundRed Hat Enterprise Linux Server release 6.8 (Santiago)บน
gerrit

ใช้งานได้เมื่อฉันไม่รูทหรือไม่?
gerrit

1
ฉันสังเกตเห็นว่าพฤติกรรมการฆ่า tmux / screen ที่ไม่พึงประสงค์ไม่ได้เกิดขึ้นบน Ubuntu 18.04 LTS เพียง 16.04
เซท

2

อีกวิธีในการแก้ปัญหานี้ซึ่งไม่ต้องการย้ายจากsshd.socketไปยังsshd.serviceคือเริ่มtmuxเซิร์ฟเวอร์เป็นบริการ systemd [0] ด้วยวิธีนี้tmuxเซิร์ฟเวอร์จะทำงานอยู่แล้วเมื่อคุณ SSH เข้าสู่เซิร์ฟเวอร์แทนที่จะเกิดจากtmuxคำสั่งใน SSH ดังนั้นจะไม่ถูกฆ่า

[0] https://wiki.archlinux.org/index.php/tmux#Autostart_with_systemd


ใช้งานได้เมื่อฉันไม่รูทหรือไม่?
gerrit

ใช่นั่นเป็นทางออกที่ถูกต้อง แต่คุณยังต้องการแก้ปัญหาด้วยการเริ่มบริการ SSH ใหม่ผ่านเซสชัน SSH :)
Pavel Šimerda

พวกในกรณีที่คุณใช้ OpenRC ฉันทำtmux initscriptเหมือนกับแฟ้มบริการที่กล่าวถึงใน ArchWiki
Megver83

1

คำตอบที่ดีที่สุดที่ฉันได้พบ IMO ให้ไว้ที่Prevent Logoff จาก Killing tmux Session :

นี้ "คุณสมบัติ" ที่มีอยู่ในsystemdก่อนหน้านี้ แต่พัฒนาตัดสินใจที่จะมีผลกระทบต่อการเปลี่ยนแปลงในการเริ่มต้นการเปิดใช้งานการตั้งค่าสำหรับการสิ้นสุดของกระบวนการที่เด็กเมื่อออกจากระบบของเซสชั่นsystemd

คุณสามารถคืนค่าการตั้งค่านี้ในlogind.conf( /etc/systemd/logind.conf):

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