ทำไม bash จึงไม่สนใจ SIGTERM


10

kill -15 -1บางครั้งเมื่อฉันต้องการที่จะออกจากระบบได้อย่างรวดเร็วที่ฉันทำ ฉันสังเกตเห็นว่า bash ไม่สนใจ SIGTERM

ฉันสงสัยว่าอะไรคือเหตุผลสำหรับพฤติกรรมทุบตีดังกล่าว ?

UNIX ไม่ได้สนใจ SIGTERM มากนักโดยไม่มีเหตุผลใช่ไหม

UPDATE:

ผลเหมือนกัน (ไม่) สำหรับทุกคน:

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

UPDATE2:

จากคนทุบตี :

เมื่อทุบตีเป็นแบบโต้ตอบในกรณีที่ไม่มีกับดักใด ๆ ก็จะละเว้น SIGTERM

ดังนั้นมันจึงเสร็จสิ้นตามวัตถุประสงค์ แต่ทำไม


คุณกำลังฆ่าคนไหน /bin/killหรือเปลือก builtin? ถ้าอย่างหลังฉันเดาว่ากระสุนจะไม่ฆ่าตัวเองด้วยตัวมันเอง
terdon

@terdon: ฉันใช้ builtin แต่ฉันไม่คิดว่านั่นเป็นเหตุผลที่จะไม่ฆ่ามันเอง
MichałŠrajer

1
หากคุณต้องการออกจากระบบอย่างรวดเร็วให้ใช้ Ctrl + d
YoMismo

1
@YoMismo: "ออกจากระบบจากเซสชัน X"
MichałŠrajer

2
@ MichałŠrajer: Ctrl-Alt-Backspace ทำสิ่งนี้ให้ฉันใน Xorg ... คุณอาจต้องเปิดใช้งานใน xorg.conf
Laszlo Valko

คำตอบ:


10

ครั้งแรกนี้ไม่เฉพาะทุบตี ATT ksh, dash และ zsh ทำงานในลักษณะเดียวกัน: จะไม่สนใจ SIGTERM และ SIGQUIT ในระหว่างบรรทัดคำสั่ง สำหรับ mksh มันก็ไม่ได้เลิก แต่ถือว่าพวกมันเหมือน SIGINT

ทั้งคู่มือ ksh และคู่มือทุบตีปรับเหตุผลโดยไม่สนใจ SIGTERM ในเงื่อนไขเหล่านี้:

เพื่อที่kill 0จะไม่ฆ่าเชลล์แบบโต้ตอบ

kill 0ฆ่ากระบวนการทั้งหมดในกลุ่มกระบวนการที่เชลล์เป็นin¹ โดยสรุปกลุ่มกระบวนการประกอบด้วยกระบวนการทั้งหมดที่ทำงานในเบื้องหน้าของเทอร์มินัลหรือกระบวนการทั้งหมดในพื้นหลังหรืองานที่ถูกระงับ

แม่นยำมากขึ้นนี่คือสิ่งที่เกิดขึ้นในเปลือกหอยที่ทันสมัยด้วยการควบคุมงาน ในเชลล์ดังกล่าวkill 0จะไม่มีประโยชน์เนื่องจากเชลล์จะอยู่ในกลุ่มกระบวนการของมันเอง เชลล์ที่เก่ากว่า (หรือเชลล์ที่ทันสมัยหลังจากset +m) ไม่ได้สร้างกลุ่มกระบวนการสำหรับคำสั่งพื้นหลัง ดังนั้นคุณสามารถใช้คำสั่งkill 0เพื่อฆ่าคำสั่งพื้นหลังทั้งหมดโดยไม่ต้องออกจากระบบ²ดังนั้นkill 0เหตุผลดูเหมือนเป็นคำสั่งเก่าที่ไม่ได้รับการพิสูจน์อีกต่อไปในปัจจุบัน แต่ยังคงไว้ซึ่งความเข้ากันได้ย้อนหลัง

อย่างไรก็ตามมีสถานการณ์อื่น ๆ ที่คล้ายกันซึ่งการทำให้ภูมิคุ้มกันของเชลล์มีประโยชน์ พิจารณากรณีที่คุณมีโปรเซสที่กำลังเทอร์มินัลและคุณต้องการฆ่าพวกเขาโดยไม่ต้องออกจากระบบ ระบบจำนวนมากมีเครื่องมือpkillที่ช่วยให้คุณสามารถฆ่ากระบวนการที่รันบนเทอร์มินัล คุณสามารถเรียกใช้pkill -t $TTYหรือpkill -QUIT -t $TTYฆ่ากระบวนการทั้งหมดที่กำลังทำงานบนเทอร์มินัลปัจจุบันยกเว้นเชลล์ที่ละเว้นสัญญาณ

โดยปกติเชลล์จะหายไปเมื่อผู้ใช้ออกจากมัน (ด้วยคำสั่งเหมือนexitหรือlogout) หรือเมื่อเทอร์มินัลส่งสัญญาณจุดสิ้นสุดของอินพุต (ผู้ใช้สามารถทำให้เกิดสิ่งนี้ได้โดยการกดCtrl+ D) หรือหายไปโดยสิ้นเชิง ในกรณีสุดท้ายนี้เชลล์ได้รับสัญญาณ SIGHUP และจะไม่เพิกเฉยต่อสัญญาณนั้น

สำหรับกรณีการใช้งานของคุณในการออกจากระบบของ X session นั้นkill -15 -1จะทำเพราะมันจะทำการจำลองเทอร์มินัลซึ่งทำให้เชลล์ได้รับ SIGHUP ในความเป็นจริงมันเพียงพอแล้วที่จะฆ่าเซิร์ฟเวอร์ X แต่ต้องค้นหา ID กระบวนการของมัน kill -15 -1; exitหากคุณต้องการคำสั่งเดียวกันกับการทำงานในเซสชั่นข้อความคุณสามารถใช้ นั่นเป็นคำสั่งที่อันตรายที่จะมีอยู่แค่ปลายนิ้วของคุณ

¹ ดูเหมือนจะไม่ได้กล่าวถึงในคู่มือเชลล์ว่าเป็นกฎ มันเป็นคุณสมบัติของการโทรระบบพื้นฐาน มันถูกกล่าวถึงอย่างชัดเจนในข้อกำหนด POSIX
² ทุกวันนี้ในการทำเช่นนั้นเรียกใช้jobs -lเพื่อดูรายการของงานที่มี ID กลุ่มกระบวนการของพวกเขาแล้วkill -123 -456 …เพื่อฆ่ากลุ่มกระบวนการ


5

นี่อาจตอบคำถามของคุณ:

เมื่อ Bash เป็นแบบอินเทอร์แอกทีฟในกรณีที่ไม่มีกับดักใด ๆ มันจะข้าม SIGTERM (ดังนั้น 'kill 0' จะไม่ฆ่าเชลล์แบบโต้ตอบ) และ SIGINT จะถูกจับและจัดการ (เพื่อให้การรอคอยในตัวถูกขัดจังหวะ) เมื่อ Bash ได้รับ SIGINT มันจะแตกออกจากลูปที่ดำเนินการใด ๆ ในทุกกรณี Bash จะไม่สนใจ SIGQUIT หากการควบคุมงานมีผลบังคับใช้ (ดูที่การควบคุมงาน) Bash จะไม่สนใจ SIGTTIN, SIGTTOU และ SIGTSTP

คำสั่งที่ไม่ใช่บิลด์เริ่มต้นโดย Bash มีตัวจัดการสัญญาณตั้งค่าเป็นค่าที่สืบทอดโดยเชลล์จากพาเรนต์ เมื่อการควบคุมงานไม่มีผลบังคับใช้คำสั่งแบบอะซิงโครนัสจะไม่สนใจ SIGINT และ SIGQUIT นอกเหนือจากตัวจัดการที่สืบทอดเหล่านี้ คำสั่งที่เรียกใช้เป็นผลมาจากการทดแทนคำสั่งละเว้นสัญญาณควบคุมงานที่สร้างด้วยคีย์บอร์ด SIGTTIN, SIGTTOU และ SIGTSTP

เชลล์จะออกโดยปริยายเมื่อได้รับ SIGHUP ก่อนออกจากเชลล์แบบโต้ตอบจะส่ง SIGHUP ไปที่งานทั้งหมดทำงานหรือหยุด งานที่หยุดจะถูกส่ง SIGCONT เพื่อให้แน่ใจว่าพวกเขาได้รับ SIGHUP เพื่อป้องกันไม่ให้เชลล์ส่งสัญญาณ SIGHUP ไปยังงานเฉพาะควรลบออกจากตารางงานด้วย built-in ที่สร้างขึ้น (ดูที่ตัวควบคุมงานในตัว) หรือทำเครื่องหมายว่าไม่รับ SIGHUP โดยใช้ disown -h

หากตั้งค่าตัวเลือก huponexit shell ด้วย shopt (ดูที่ Shopt Builtin) Bash จะส่ง SIGHUP ไปยังงานทั้งหมดเมื่อเชลล์ล็อกอินแบบโต้ตอบออกจาก

หาก Bash กำลังรอให้คำสั่งดำเนินการจนเสร็จสิ้นและรับสัญญาณที่มีการตั้งค่ากับดักไว้กับดักจะไม่ถูกดำเนินการจนกว่าคำสั่งจะเสร็จสิ้น เมื่อ Bash กำลังรอคำสั่งแบบอะซิงโครนัสผ่านการรอในตัวการรับสัญญาณที่มีการตั้งค่ากับดักจะทำให้การรอการสร้างกลับมาทันทีโดยมีสถานะการออกมากกว่า 128 ทันทีหลังจากที่มีการดำเนินการกับดัก

แหล่งที่มา : คู่มือ GNU Bash


ฉันอ้างถึงสิ่งนี้ใน update2 ของฉัน ผู้ชายระบุว่าการทุบตีทำเช่นนั้น แต่ไม่ได้อธิบายว่าทำไมการตัดสินใจเช่นนั้น คำถามยังคงอยู่ - ทำไม?
MichałŠrajer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.