กระบวนการสังหารเกิดโดย ssh เมื่อ ssh ตาย


23

นี่เป็นคำถามที่ได้รับการแก้ไขหลายครั้งไม่เพียง แต่ที่นี่ แต่ยังอยู่ในไซต์อื่น ๆ ของเครือข่ายแลกเปลี่ยนสแต็ก (เช่นวิธีทำให้ ssh เพื่อฆ่ากระบวนการระยะไกลเมื่อฉันขัดจังหวะ ssh เอง ) อย่างไรก็ตามฉันไม่สามารถแก้ปัญหาใด ๆ ได้สำหรับฉัน

ฉันใช้คำสั่งผ่าน ssh เมื่อใดก็ตามที่ฉันออกจาก ssh ฉันต้องการให้คำสั่งตายเช่นกัน คำสั่งนี้เป็น daemon ชื่อ ktserver ที่รันไปเรื่อย ๆ จนกว่าคุณจะกด Ctrl-C

ฉันรันมันดังนี้: ssh -t compute-0-1 ktserverและแน่นอนเมื่อฉันกด Ctrl-C กระบวนการจะสิ้นสุดลงอย่างสวยงามและสิ้นสุดเซสชัน ssh

อย่างไรก็ตามถ้าแทนที่จะกด Ctrl-C ฉันจะฆ่ากระบวนการ ssh โดยใช้killคำสั่ง (ตัวอย่างเช่นการส่ง SIGINT หรือ SIGHUP) ktserverกระบวนการจะยังคงอยู่

ฉันจะทำให้คนktserverตายมักเป็นอิสระจากการsshถูกฆ่าได้อย่างไร

แก้ไข : หากแทนที่จะให้ktserverฉันทำบางสิ่งที่แตกต่างอย่างสิ้นเชิงเช่นgeditทุกอย่างทำงานเหมือนมีเสน่ห์ (เช่น gedit ตายเมื่อการเชื่อมต่อตาย) ดังนั้นอาจมีบางอย่างผิดปกติกับกระบวนการของตัวเอง ตัวอย่างเช่นฉันคิดว่าอาจละเว้น SIGHUP หรือ SIGINT อย่างไรก็ตามเมื่อฉันเรียกใช้kill -1 ktserverหรือkill -2 ktserverกระบวนการตายตามที่คาดไว้

แก้ไข 2 : ตามที่ Mark Plotnick ชี้ให้เห็นปัญหาเกี่ยวข้องกับความจริงที่ว่าไม่มีการสื่อสารหมุนเวียนในช่อง ssh ฉันได้รับการยืนยันโดยการทำงานssh -t <host> readและการฆ่ากระบวนการ ssh ในภายหลัง readยังมีชีวิตอยู่และเตะ


คุณเคยลองkill -9 ktserverไหม

@HermanTorjussen แน่นอนว่ามันใช้ได้ ปัญหาคือว่าคำสั่งนี้เรียกใช้จากภายในกระบวนการอื่นและฉันอาจไม่สามารถควบคุมความเป็นไปได้ทั้งหมดที่อาจทำให้กระบวนการของฉันตายและดังนั้นเซสชัน ssh กับมัน ดังนั้นฉันจึงต้องการวิธีการที่เชื่อถือได้เพื่อให้แน่ใจว่าเมื่อใดก็ตามที่กระบวนการของฉัน - ดังนั้นจึงตาย ktserver จะตายกับพวกเขา
GermanK

ประสบการณ์ของฉันกับ Linux คือถ้าคำสั่งระยะไกลไม่ได้ทำ i / o ใด ๆ กับการเชื่อมต่อ tcp ที่ตายแล้วมันจะยังคงทำงานต่อไป ฉันเคยssh example.com dd ...ทำงานให้เสร็จแม้เวลาผ่านไปหลายชั่วโมงหลังจากการsshเชื่อมต่อขาดตอนเนื่องจากปัญหาเครือข่าย หากคุณสามารถเปลี่ยนktserverเป็นตัวเลือกในการส่งออกบางสิ่งบางอย่างในชั่วขณะหนึ่งนั่นอาจเป็นการแก้ไข
Mark Plotnick

@ MarkPlotnick แน่นอนฉันได้ลองใช้readในคอมพิวเตอร์ระยะไกลและหลังจากฆ่าการเชื่อมต่อ ssh readไม่ได้ตาย น่าเสียดายที่ฉันไม่สามารถเปลี่ยน ktserver เพื่อแสดงผลอะไรได้ ไม่มีวิธีแก้ปัญหาแล้ว?
GermanK

2
ฉันคิดว่าเมื่อ ssh ตายเปลือกของคุณก็ตายเช่นกัน คุณสามารถกำหนดค่าเปลือกของคุณเพื่อส่งสัญญาณ -1 (SIGHUP) เมื่อมันยุติ ( shopt -s huponexit) คุณสามารถทดสอบว่าสิ่งนี้เหมาะกับคุณหรือไม่?
Hennes

คำตอบ:


13

โดยปกติเมื่อการเชื่อมต่อ ssh ตายเชลล์ก็จะตายเช่นกัน คุณสามารถกำหนดค่าเปลือกของคุณเพื่อส่งสัญญาณ -1 (SIGHUP) เมื่อมันสิ้นสุดลงที่ลูก ๆ

สำหรับทุบตีคุณสามารถกำหนดค่าตัวเลือกนี้ผ่านคำสั่ง builtin shopt ( shopt -s huponexit)

สำหรับ zsh คุณต้องการsetoptHUP


ฉันคิดว่านี่เป็นคำตอบสำหรับปัญหาปัจจุบันของฉัน แต่ดูเหมือนจะไม่ทำงาน ฉันกำลังใช้งาน: ssh $ host "scp LargeFile.dat $ OtherHost: / tmp" & pid = $! จากนั้นพยายามหยุดการถ่ายโอนด้วย: shopt -s huponexit; kill $ pid แต่ scp ไม่หยุดเมื่อฉันฆ่า ssh ที่ฉันเริ่ม ความคิดใด ๆ
เดวิดโดเรีย

คุณสามารถทดสอบด้วยการตั้งค่าตัวเลือกเปลือกก่อนที่จะเริ่มคำสั่ง scp? หรือโดยการเริ่มเชลล์ตั้งค่า shopt และเริ่ม scp?
Hennes

2
สิ่งนี้ใช้ได้กับฉัน แต่ฉันต้องทำให้แน่ใจก่อนว่าฉันใช้อยู่ssh -t -t(สังเกตเห็น-tสองครั้ง!) ซึ่งบังคับให้มีการจัดสรร tty แทนที่จะเป็นเพียง pty
นิโคลัสวู

13

ฉันพบว่าเพียงแค่ใช้-t -tเป็นอาร์กิวเมนต์เพื่อให้sshทำงานได้ ฉันไม่จำเป็นต้องตั้งค่าhuponexitให้เป็นจุดเริ่มต้นหรือเปลือกระยะไกล

ฉันทดสอบสิ่งนี้ดังนี้:

ใช้งานไม่ได้:

ssh user@remote sleep 100
^C

นี่เป็นการฆ่าเซสชันของ ssh แต่ฉันเห็นว่ากระบวนการสลีปยังคงทำงานอยู่บนรีโมตโฮสต์ ( ps -ef | grep sleepแสดงให้เห็น)

ทำงานได้:

ssh -t -t user@remote sleep 100
^C

สิ่งนี้จะฆ่าเซสชัน ssh และกระบวนการสลีประยะไกลก็ถูกฆ่าเช่นกัน ฉันได้รับการตรวจสอบว่าสัญญาณที่ถูกส่งไปยังกระบวนการระยะไกลSIGINTถ้าคุณใช้-Control Cฉันยังตรวจสอบว่า SIGKILL (-9) ที่ใช้กับsshกระบวนการจะฆ่ากระบวนการระยะไกลด้วย

แก้ไข 1:

นั่นเป็นความจริงสำหรับsleep... สำหรับกระบวนการรีโมตที่ดื้อมากขึ้นฉันพบว่าsshจัดการกับ ^ C ที่แตกต่างจาก SIGINT Ctrl- ใช้Cงานได้ แต่ไม่kill -INT $pidทำงาน

นี่คือสิ่งที่ในที่สุดฉันก็พบว่าทำงานได้กับแอปพลิเคชันจริงของฉัน (ขโมยจากคำตอบอื่น ๆ )

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

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


สิ่งนี้ทำงานได้ดีที่สุดสำหรับฉัน แต่ FYI ก็ทำให้ตัวควบคุมเทอร์มินัลตกเลือดซึ่งอาจทำให้เกิดเอาต์พุตตลก catดังนั้นวิธีแก้ปัญหาที่ง่ายในกรณีของฉันก็จะห่อเรียกว่าคำสั่งและท่อส่งออกของพวกเขาผ่าน ตัวอย่างเช่นssh -ttq user@host '{ cmd; cmd; } | cat'
Droj

Ctrl-Cไม่เท่ากับเสมอkill -INT $pidดูคำตอบของฉันในunix.stackexchange.com/questions/377191/และอีกอันในstackoverflow.com/questions/8398845/…สำหรับรายละเอียดเลือด ;-)
thecarpy

@thecarpy - คำตอบแรกของคุณบอกว่าCtrl-C จะคล้ายกับการ SIGINTและคำตอบอื่น ๆ กล่าวว่า^Cจะส่ง SIGINT แล้วอะไรคือความแตกต่างที่แน่นอนถ้าพวกมันไม่เท่ากัน?
Mark Lakata

1

หาก ssh ไม่แพร่กระจายสัญญาณจะได้รับสิ่งที่คุณคาดหวังจากมัน

UPD (พิเศษสำหรับ JosephR): เห็นได้ชัดว่ามันเป็นข้อผิดพลาดในคำถามตัวเองซึ่งตามมาจากความเข้าใจผิด - "กระบวนการฆ่าเกิดจาก ssh เมื่อ ssh ตาย" SSH มักจะไม่วางไข่กระบวนการ (บางครั้งก็เป็นเช่นนั้น แต่นี่เป็นอีกเรื่องหนึ่ง) SSHD จะทำแทนเมื่อเรามองที่การเชื่อมต่ออีกด้านหนึ่ง SSH พึ่งอาศัยรีโมตเซิร์ฟเวอร์ pstudo-terminal abstraction เท่านั้น นั่นเป็นเหตุผลที่สิ่งเดียวที่สามารถช่วยได้คือความสามารถของเทอร์มินัลในการส่งสัญญาณไปยังกระบวนการที่แนบมา นี่ค่อนข้างพื้นฐานสำหรับระบบ UNIX ทุกระบบ


1
สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม หากต้องการวิจารณ์หรือขอคำชี้แจงจากผู้แต่งโปรดแสดงความคิดเห็นใต้โพสต์ของพวกเขา
Anthon

@ ทันใดนั้นมันเป็นคำอธิบาย แต่ไม่มีใครระบุว่านี่เป็นคำตอบที่ถูกต้องเท่านั้น ขอบคุณสำหรับความคิดเห็นของคุณด้านล่าง
poige

1
@poige บางทีคำอธิบายอาจทำให้เข้าใจได้ว่ามันสามารถใช้กับ OP และอื่น ๆ ได้
โจเซฟอาร์.

@JosephR. ตกลงสำหรับคุณโดยเฉพาะ
poige

1
ถ้าฉันพูดว่า "ขั้นตอนการฆ่าวางไข่โดย sshd เมื่อการเชื่อมต่อ ssh หายไป" คุณจะฟังดูดีขึ้นไหม ฉันไม่คิดว่าการใช้ถ้อยคำใหม่แก้ปัญหาของฉันในทางใดทางหนึ่ง
GermanK

0

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

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

คำสั่งที่ใช้เวลานานของฉันไม่ได้ทำงานอีกต่อไปเมื่อการเชื่อมต่อถูกยกเลิกเช่นนี้

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