ทำไม Ctrl-C ถึงไม่ฆ่า Terminal เอง?


38

เทอร์มินัลกำลังทำงานเมื่อเราเปิด

luvpreet@DHARI-Inspiron-3542:/$

ฉันเพิ่งเปิดมัน ดังนั้นเมื่อฉันกดCtrl+ Cทำไมมันไม่ฆ่าตัวเองและปิดเทอร์มินัล


21
เทอร์มินัลไม่ทำงานใน terminal ;-)
Pilot6

3
เกี่ยวกับสาเหตุที่การทำงานของ control-d: unix.stackexchange.com/a/110248/14305
Janus Troelsen

คำตอบ:


47

Ctrl+ Cเป็นสัญญาณขัดจังหวะ เมื่อคุณพิมพ์สิ่งนี้ในเทอร์มินัล bash ส่ง SIGINT ไปยังงานในเบื้องหน้า หากไม่มีงาน (ซึ่งเป็นกรณีเมื่อคุณเพิ่งเปิดเครื่อง) ไม่มีอะไรเกิดขึ้น โปรแกรมเทอร์มินัลอีมูเลเตอร์ไม่ใช่งานที่ทำงานอยู่ในเชลล์ดังนั้นจึงไม่ได้รับสัญญาณและไม่ปิด

หากคุณต้องการปิดเทอร์มินัลด้วยปุ่มควบคุมใช้Ctrl+ D(EOF) ซึ่งทำให้ bash ออก (และปิดเทอร์มินัลด้วย)

ดูเพิ่มเติม: คำแนะนำของ Bash Beginner เกี่ยวกับสัญญาณและในเชิงลึกยิ่งขึ้นวิธีการใช้งานการจัดการสัญญาณ
หมายเหตุ: คำตอบนี้ได้รับการแก้ไขตั้งแต่ความคิดเห็นถูกโพสต์


4
คำที่เหมาะสมคือเชลล์จะ "ดัก" สัญญาณ เรื่องราวที่แตกต่างคือเมื่อคุณเปิดหน้าต่างเทอร์มินัลจากภายในหน้าต่างอื่น การส่ง ctrl + c ไปที่หน้าต่างหลักจะเป็นการฆ่ากระบวนการลูก
Sergiy Kolodyazhnyy

1
นอกจากนี้หน้าต่าง GUI ยังสามารถสั่งให้ดักจับสัญญาณเฉพาะที่มาจากเซิร์ฟเวอร์ X11 นั่นคือวิธีที่คุณสามารถมีป๊อปอัปแจ้งให้คุณทราบถึงงานที่ไม่ได้บันทึกหรือแท็บเปิดเช่นเดียวกับในเบราว์เซอร์
Sergiy Kolodyazhnyy

8
@chrylis โปรแกรมเทอร์มินัลเพิ่งส่งอักขระ ctrl-c จริงๆแล้วมันคือเลเยอร์เคอร์เนล tty ที่เปลี่ยนให้เป็นสัญญาณ
Random832

3
@ chrylis: และเทอร์มินัลหรือโปรแกรมที่ทำงานอยู่ภายใน - ตัวอย่างเช่นโปรแกรมแก้ไขข้อความ - อาจแปล Ctl-C เป็นการกระทำอื่น ๆ ได้
jamesqf

3
ฉันไม่คิดว่าbashจะยุติโปรแกรมใด ๆ เมื่อกด ctrl-c มันจะบอกเคอร์เนลว่ากลุ่มกระบวนการใดที่ทำงานอยู่และเคอร์เนลจะสร้างสัญญาณไปยังกลุ่มกระบวนการนั้นเมื่อมันได้รับ ctrl-c จากโปรแกรมเทอร์มินัล
kasperd

32

การ^Cกดแป้นเช่นเดียวกับการกดแป้นอื่น * ไม่ใช่เรื่องมหัศจรรย์มันส่งรหัสไปยังโปรแกรมใดก็ตามที่มีโฟกัส (ใน X รหัสคือ 54 สำหรับที่Cมีตัวแก้ไข 0x4 สำหรับCtrl) โปรแกรมที่รับกระแสของคีย์มีหน้าที่ทำสิ่งที่เหมาะสมกับพวกเขา - โปรดจำไว้ว่าในแอปพลิเคชัน GUI หลายตัวการกดแป้นพิมพ์ไปยังคลิปบอร์ด

เมื่อตัวเลียนแบบเทอร์มินัล GUI (เช่น Konsole) หรือเทอร์มินัลเสมือนได้รับการกดแป้นที่มันตีความว่า^Cมันสามารถทำหนึ่งในสามสิ่งนี้ หากเทอร์มินัลอยู่ในโหมด rawโปรแกรมที่รันอยู่จะขอให้เครื่องไม่ทำการจัดการกับคีย์พิเศษใด ๆและส่งผ่านไปยังโปรแกรมโดยตรง บางโปรแกรมที่รองรับคุณสมบัติขั้นสูงเช่นการแก้ไขบรรทัดจะได้รับอินพุตแป้นพิมพ์ในการกำหนดค่าบางอย่างระหว่างการกดแป้นพิมพ์แบบสมบูรณ์กับการประมวลผลข้อความ bashตัวอย่างเช่นรับการกดแป้นครั้งละครั้ง ^Cถูกตีความโดยเทอร์มินัล แต่คีย์ backspace ถูกส่งไปยังเชลล์ตามที่เป็น

อย่างไรก็ตามโปรแกรมส่วนใหญ่ใช้โหมดสุก (เพราะมันไม่ได้ดิบ) ซึ่งเทอร์มินัลตีความการกดแป้นพื้นฐานบางอย่างก่อนที่จะส่งพวกเขาไปยังโปรแกรม (นี่คือเหตุผลที่คุณสามารถใช้ Backspace ในcat) ในโหมดนี้เทอร์มินัลจะแปลการ^Cกดแป้นเป็นSIGINTสัญญาณและส่งไปยังกระบวนการลูก เนื่องจากเทอร์มินัลสร้างสัญญาณมันจะไม่สับสนและยุติลง

  • SysRq วิเศษจริงๆ

เห็นได้ชัดว่าไม่ได้เกี่ยวข้องกับซุปเปอร์ที่นี่ แต่สำหรับการคำนวณทั่วไปมีการกดแป้นเวทเพิ่มเติมที่นั่น ส่วนใหญ่ที่มีชื่อเสียงCtrl+ Alt+ Deleteในโลก Windows ซึ่งการผสมผสานคีย์ใกล้เคียงกับเวทมนต์ (สามารถใช้เพื่อให้ Windows ทำงานได้นั่นเป็นเวทย์มนตร์ที่ยอดเยี่ยมและในตัวของมันเอง!) เนื่องจากมันยากที่จะเข้ารหัสเข้าสู่ระบบเพื่อขัดขวาง และแทนที่ทุกอย่างมาก - ค่อนข้างคล้ายกับSysRqในแง่นั้น
KRyan

7
Bash ไม่ใช้โหมด raw - ใช้โหมด character-at-a-time เช่นcbreak/ -icanonแต่จะออกจากisigโหมดการตั้งค่าและรับสัญญาณจริงเมื่อคุณกดปุ่มที่แมปไว้ จะจัดการSIGINTโดยพฤติกรรมตามที่คุณอธิบาย (มันไม่เพียง แต่ยกเลิกการแก้ไขบรรทัดก็ยังยกเลิกคำสั่งภายในใด ๆ ที่อาจจะมีการทำงานในวง) และสมบูรณ์ละเว้นและSIGTSTP SIGQUITโปรแกรมอื่น ๆ เช่น vi อาจไม่
Random832

1
@KRyan Ctrl+ Alt+ Deleteที่ใช้จะเป็นความมหัศจรรย์มากยิ่งขึ้นกว่าที่เป็นอยู่วันนี้ - blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 แม้ว่าฉันจะเป็นคนใจดี แต่ฉันก็มักจะตกใจกับการที่ Windows ทำสิ่งต่าง ๆ ที่เป็นมิตรกับผู้ใช้และใช้ทรัพยากรอย่าง จำกัด ในช่วงแรก ๆ
Muzer

ในบางระบบปฏิบัติการแม้ว่าโปรแกรมอื่นจะมุ่งเน้นไปที่ระบบ (ตัวจัดการหน้าต่างที่ฉันเดา?) จะได้รับการกดปุ่มก่อนที่เทอร์มินัลอีมูเลเตอร์เคยทำ หากคุณสามารถกำหนดค่าแป้นพิมพ์ลัดเพื่อจัดเรียงหน้าต่างให้เปิดแอปพลิเคชันเรียกสคริปต์จากนั้นก่อนที่จะกดปุ่มกดจะถูกส่งไปยังเครื่องจำลองเทอร์มินัลเพื่อตรวจสอบว่ามีทางลัดใด ๆ และอีกตัวอย่างหนึ่งถ้าคุณไม่มีแอปพลิเคชั่นเปิดอยู่^cจะไม่ฆ่าตัวจัดการหน้าต่าง :) ไม่สามารถแสดงความคิดเห็นเกี่ยวกับตัวละครแบบ raw / สุกในเวลา แต่คำตอบคือจุดที่เกี่ยวกับวิธีการสร้างการกดแป้นพิมพ์ที่SIGINT
Ajay

2
" โหมดปรุงสุก (เพราะไม่ได้ดิบ)": ฉัน ... พูดไม่ออก หลังจากหลายปีที่ผ่านมาฉันไม่เคยเชื่อมต่อ
isanae

8

^Cมักจะถูกแมป (ดูstty -a) กับSIGINTสัญญาณ (ดูman 7 signal)

ไม่ถูกจับได้SIGINTขัดจังหวะกระบวนการทำงาน แต่ ...

SIGINT เป็นหนึ่งในสัญญาณที่กระบวนการสามารถระบุพฤติกรรมสำหรับ ("การจับสัญญาณ")

สิ่งที่คุณเรียกว่า "เทอร์มินัล" จับSIGINTและกลับไปทำงาน


7

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

เชลล์คือสิ่งที่คุณรู้อยู่แล้วโปรแกรมที่ใช้เป็นคำสั่งอินพุตหรือสคริปต์เรียกใช้งานมันและพิมพ์ผลลัพธ์

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

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

ตัวอย่างเช่นหากโปรแกรมแสดงลำดับต่อไปนี้:

\e[0;31m some extra foobar text

เทอร์มินัลจะส่งออกไปยังหน้าจอ "ข้อความ foobar พิเศษบางอย่าง" ด้วยตัวอักษรสีแดง นี่เป็นเพราะเทอร์มินัลเลือกที่จะปฏิบัติต่อรหัสแปลก ๆ ในลักษณะพิเศษซึ่งรหัสบอกเป็นนัยให้พิมพ์ผลลัพธ์ต่อไปนี้ด้วยสีแดง

ในทำนองเดียวกันเมื่อผู้ใช้กดCtrl - Cสิ่งพิเศษเฉพาะเกี่ยวกับเรื่องนี้คือว่าขั้วเลือกที่จะรักษามันในลักษณะพิเศษไม่มีอะไรพิเศษอื่น ๆ เกี่ยวกับลำดับของคีย์นี้ โดยเฉพาะสิ่งนี้บอกเป็นนัยถึงการส่งสัญญาณขัดจังหวะ (SIGINT) ไปยังกระบวนการที่ทำงานอยู่ภายในเทอร์มินัลนั่นคือเชลล์ หากในขณะนั้นมีโปรแกรมใด ๆ ที่วางไข่โดยเชลล์และกำลังทำงานในเบื้องหน้าก็จะได้รับสัญญาณ ตอนนี้เชลล์มีตัวจัดการพิเศษสำหรับสัญญาณนี้และไม่มีอะไรเกิดขึ้น แต่โปรแกรมส่วนใหญ่มีตัวจัดการเริ่มต้นซึ่งในกรณีของ SIGINT เพิ่งจะออก


5

สัญญาณทุกตัวมีการกระทำเริ่มต้นที่เกี่ยวข้อง การกระทำเริ่มต้นสำหรับสัญญาณคือการกระทำที่สคริปต์หรือโปรแกรมดำเนินการเมื่อได้รับสัญญาณ

Ctrl+ Cส่งสัญญาณ "ขัดจังหวะ" ( SIGINT ) ซึ่งเป็นค่าเริ่มต้นที่จะยุติกระบวนการไปยังงานที่ทำงานอยู่เบื้องหน้า

Ctrl+ Dบอกสถานีที่ว่ามันควรจะลงทะเบียนEOFกับการป้อนข้อมูลมาตรฐานซึ่งตีความทุบตีเป็นความปรารถนาที่จะออกจาก

กระบวนการสามารถเลือกที่จะไม่สนใจสัญญาณ INT และ Bash ทำเช่นนั้นเมื่อมันทำงานในโหมดโต้ตอบ

จากคู่มือ :

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


ทำความเข้าใจกับดัก :

trapเป็นฟังก์ชั่นที่สร้างขึ้นในเชลล์ที่ตอบสนองต่อสัญญาณฮาร์ดแวร์และเหตุการณ์อื่น ๆ มันกำหนดและเปิดใช้งานตัวจัดการที่จะทำงานเมื่อเปลือกได้รับสัญญาณหรือเงื่อนไขพิเศษอื่น ๆ

trap [-lp] [arg] [sigspec …]

-l พิมพ์รายการชื่อสัญญาณและหมายเลขที่เกี่ยวข้อง
-pแสดงคำสั่ง trap ที่เกี่ยวข้องกับแต่ละ SIGNAL_SPEC

หาเรื่องจะอ่านและดำเนินการเมื่อเปลือกได้รับสัญญาณ sigspec sigspec แต่ละตัวอาจเป็นชื่อสัญญาณหรือหมายเลขสัญญาณ ชื่อสัญญาณไม่คำนึงถึงขนาดตัวพิมพ์และส่วนนำหน้า SIG เป็นทางเลือก

หากsigspecเป็น0หรือEXITหาเรื่องจะถูกดำเนินการเมื่อเชลล์ออก เพื่อความเข้าใจให้ปิดเทอร์มินัล & เปิดหลังจากแก้ไขบรรทัดต่อไปนี้ใน.bashrcไฟล์

trap 'notify-send "Ctrl D pressed"' 0

Ctrl D คล้ายกับexitคำสั่งเพื่อออกจากเทอร์มินัล

หากคุณต้องการให้ Bash ออกเมื่อได้รับสัญญาณ INT แม้ในโหมดโต้ตอบคุณสามารถเพิ่มสิ่งต่อไปนี้ใน~/.bashrc:

trap 'exit' INT

หรือ

trap 'exit' 2

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