เทอร์มินัลกำลังทำงานเมื่อเราเปิด
luvpreet@DHARI-Inspiron-3542:/$
ฉันเพิ่งเปิดมัน ดังนั้นเมื่อฉันกดCtrl+ Cทำไมมันไม่ฆ่าตัวเองและปิดเทอร์มินัล
เทอร์มินัลกำลังทำงานเมื่อเราเปิด
luvpreet@DHARI-Inspiron-3542:/$
ฉันเพิ่งเปิดมัน ดังนั้นเมื่อฉันกดCtrl+ Cทำไมมันไม่ฆ่าตัวเองและปิดเทอร์มินัล
คำตอบ:
Ctrl+ Cเป็นสัญญาณขัดจังหวะ เมื่อคุณพิมพ์สิ่งนี้ในเทอร์มินัล bash ส่ง SIGINT ไปยังงานในเบื้องหน้า หากไม่มีงาน (ซึ่งเป็นกรณีเมื่อคุณเพิ่งเปิดเครื่อง) ไม่มีอะไรเกิดขึ้น โปรแกรมเทอร์มินัลอีมูเลเตอร์ไม่ใช่งานที่ทำงานอยู่ในเชลล์ดังนั้นจึงไม่ได้รับสัญญาณและไม่ปิด
หากคุณต้องการปิดเทอร์มินัลด้วยปุ่มควบคุมใช้Ctrl+ D(EOF) ซึ่งทำให้ bash ออก (และปิดเทอร์มินัลด้วย)
ดูเพิ่มเติม: คำแนะนำของ Bash Beginner เกี่ยวกับสัญญาณและในเชิงลึกยิ่งขึ้นวิธีการใช้งานการจัดการสัญญาณ
หมายเหตุ: คำตอบนี้ได้รับการแก้ไขตั้งแต่ความคิดเห็นถูกโพสต์
bash
จะยุติโปรแกรมใด ๆ เมื่อกด ctrl-c มันจะบอกเคอร์เนลว่ากลุ่มกระบวนการใดที่ทำงานอยู่และเคอร์เนลจะสร้างสัญญาณไปยังกลุ่มกระบวนการนั้นเมื่อมันได้รับ ctrl-c จากโปรแกรมเทอร์มินัล
การ^Cกดแป้นเช่นเดียวกับการกดแป้นอื่น * ไม่ใช่เรื่องมหัศจรรย์มันส่งรหัสไปยังโปรแกรมใดก็ตามที่มีโฟกัส (ใน X รหัสคือ 54 สำหรับที่Cมีตัวแก้ไข 0x4 สำหรับCtrl) โปรแกรมที่รับกระแสของคีย์มีหน้าที่ทำสิ่งที่เหมาะสมกับพวกเขา - โปรดจำไว้ว่าในแอปพลิเคชัน GUI หลายตัวการกดแป้นพิมพ์ไปยังคลิปบอร์ด
เมื่อตัวเลียนแบบเทอร์มินัล GUI (เช่น Konsole) หรือเทอร์มินัลเสมือนได้รับการกดแป้นที่มันตีความว่า^Cมันสามารถทำหนึ่งในสามสิ่งนี้ หากเทอร์มินัลอยู่ในโหมด rawโปรแกรมที่รันอยู่จะขอให้เครื่องไม่ทำการจัดการกับคีย์พิเศษใด ๆและส่งผ่านไปยังโปรแกรมโดยตรง บางโปรแกรมที่รองรับคุณสมบัติขั้นสูงเช่นการแก้ไขบรรทัดจะได้รับอินพุตแป้นพิมพ์ในการกำหนดค่าบางอย่างระหว่างการกดแป้นพิมพ์แบบสมบูรณ์กับการประมวลผลข้อความ bash
ตัวอย่างเช่นรับการกดแป้นครั้งละครั้ง ^Cถูกตีความโดยเทอร์มินัล แต่คีย์ backspace ถูกส่งไปยังเชลล์ตามที่เป็น
อย่างไรก็ตามโปรแกรมส่วนใหญ่ใช้โหมดสุก (เพราะมันไม่ได้ดิบ) ซึ่งเทอร์มินัลตีความการกดแป้นพื้นฐานบางอย่างก่อนที่จะส่งพวกเขาไปยังโปรแกรม (นี่คือเหตุผลที่คุณสามารถใช้ Backspace ในcat
) ในโหมดนี้เทอร์มินัลจะแปลการ^Cกดแป้นเป็นSIGINT
สัญญาณและส่งไปยังกระบวนการลูก เนื่องจากเทอร์มินัลสร้างสัญญาณมันจะไม่สับสนและยุติลง
Ctrl
+ Alt
+ Delete
ในโลก Windows ซึ่งการผสมผสานคีย์ใกล้เคียงกับเวทมนต์ (สามารถใช้เพื่อให้ Windows ทำงานได้นั่นเป็นเวทย์มนตร์ที่ยอดเยี่ยมและในตัวของมันเอง!) เนื่องจากมันยากที่จะเข้ารหัสเข้าสู่ระบบเพื่อขัดขวาง และแทนที่ทุกอย่างมาก - ค่อนข้างคล้ายกับSysRq
ในแง่นั้น
cbreak
/ -icanon
แต่จะออกจากisig
โหมดการตั้งค่าและรับสัญญาณจริงเมื่อคุณกดปุ่มที่แมปไว้ จะจัดการSIGINT
โดยพฤติกรรมตามที่คุณอธิบาย (มันไม่เพียง แต่ยกเลิกการแก้ไขบรรทัดก็ยังยกเลิกคำสั่งภายในใด ๆ ที่อาจจะมีการทำงานในวง) และสมบูรณ์ละเว้นและSIGTSTP
SIGQUIT
โปรแกรมอื่น ๆ เช่น vi อาจไม่
Ctrl
+ Alt
+ Delete
ที่ใช้จะเป็นความมหัศจรรย์มากยิ่งขึ้นกว่าที่เป็นอยู่วันนี้ - blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 แม้ว่าฉันจะเป็นคนใจดี แต่ฉันก็มักจะตกใจกับการที่ Windows ทำสิ่งต่าง ๆ ที่เป็นมิตรกับผู้ใช้และใช้ทรัพยากรอย่าง จำกัด ในช่วงแรก ๆ
^c
จะไม่ฆ่าตัวจัดการหน้าต่าง :) ไม่สามารถแสดงความคิดเห็นเกี่ยวกับตัวละครแบบ raw / สุกในเวลา แต่คำตอบคือจุดที่เกี่ยวกับวิธีการสร้างการกดแป้นพิมพ์ที่SIGINT
^Cมักจะถูกแมป (ดูstty -a
) กับSIGINT
สัญญาณ (ดูman 7 signal
)
ไม่ถูกจับได้SIGINT
ขัดจังหวะกระบวนการทำงาน แต่ ...
SIGINT
เป็นหนึ่งในสัญญาณที่กระบวนการสามารถระบุพฤติกรรมสำหรับ ("การจับสัญญาณ")
สิ่งที่คุณเรียกว่า "เทอร์มินัล" จับSIGINT
และกลับไปทำงาน
ตอนที่ฉันเป็นผู้เริ่มต้นฉันขาดส่วนที่เมื่อฉันใช้บรรทัดคำสั่งจริง ๆ แล้วฉันใช้โปรแกรมแยกกันสองโปรแกรมเทอร์มินัลและเชลล์ (เช่นทุบตี)
เชลล์คือสิ่งที่คุณรู้อยู่แล้วโปรแกรมที่ใช้เป็นคำสั่งอินพุตหรือสคริปต์เรียกใช้งานมันและพิมพ์ผลลัพธ์
เทอร์มินัลที่อยู่อีกด้านหนึ่งนั้นเหมือนคนที่อยู่ตรงกลางระหว่างผู้ใช้และโปรแกรม (ซึ่งโปรแกรมมักจะเป็นเชลล์เช่นทุบตีหรือปลา) สิ่งที่เครื่องเทอร์มินัลทำคืออ่านอินพุตจากคีย์บอร์ดอาจจะประมวลผลอินพุตนั้นในบางวิธีและเปลี่ยนเส้นทางไปยังโปรแกรมอื่น (ทุบตี)
นอกจากนี้ยังทำงานในลักษณะอื่นเช่นกันเมื่อโปรแกรมอื่นแสดงผลบางสิ่งบางอย่างถูกเปลี่ยนเส้นทางไปยังเทอร์มินัลดังนั้นจึงเป็นหน้าที่ของเทอร์มินัลในการส่งสัญญาณบางสิ่งไปยังหน้าจอ ในระหว่างการรับอินพุตและการพิมพ์ไปยังหน้าจอเครื่องสามารถตีความอินพุตที่ได้รับในรูปแบบต่างๆ
ตัวอย่างเช่นหากโปรแกรมแสดงลำดับต่อไปนี้:
\e[0;31m some extra foobar text
เทอร์มินัลจะส่งออกไปยังหน้าจอ "ข้อความ foobar พิเศษบางอย่าง" ด้วยตัวอักษรสีแดง นี่เป็นเพราะเทอร์มินัลเลือกที่จะปฏิบัติต่อรหัสแปลก ๆ ในลักษณะพิเศษซึ่งรหัสบอกเป็นนัยให้พิมพ์ผลลัพธ์ต่อไปนี้ด้วยสีแดง
ในทำนองเดียวกันเมื่อผู้ใช้กดCtrl - C
สิ่งพิเศษเฉพาะเกี่ยวกับเรื่องนี้คือว่าขั้วเลือกที่จะรักษามันในลักษณะพิเศษไม่มีอะไรพิเศษอื่น ๆ เกี่ยวกับลำดับของคีย์นี้ โดยเฉพาะสิ่งนี้บอกเป็นนัยถึงการส่งสัญญาณขัดจังหวะ (SIGINT) ไปยังกระบวนการที่ทำงานอยู่ภายในเทอร์มินัลนั่นคือเชลล์ หากในขณะนั้นมีโปรแกรมใด ๆ ที่วางไข่โดยเชลล์และกำลังทำงานในเบื้องหน้าก็จะได้รับสัญญาณ ตอนนี้เชลล์มีตัวจัดการพิเศษสำหรับสัญญาณนี้และไม่มีอะไรเกิดขึ้น แต่โปรแกรมส่วนใหญ่มีตัวจัดการเริ่มต้นซึ่งในกรณีของ SIGINT เพิ่งจะออก
สัญญาณทุกตัวมีการกระทำเริ่มต้นที่เกี่ยวข้อง การกระทำเริ่มต้นสำหรับสัญญาณคือการกระทำที่สคริปต์หรือโปรแกรมดำเนินการเมื่อได้รับสัญญาณ
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