ปุ่มสัญญาณเช่นCtrl+ Cส่งสัญญาณไปยังกระบวนการทั้งหมดในเบื้องหน้ากลุ่มกระบวนการ
ในกรณีทั่วไปกลุ่มกระบวนการคือไพพ์ไลน์ ตัวอย่างเช่นในhead <somefile | sortกระบวนการทำงานheadและกระบวนการทำงานsortอยู่ในกลุ่มกระบวนการเดียวกันเช่นเดียวกับเปลือกดังนั้นพวกเขาทั้งหมดได้รับสัญญาณ เมื่อคุณเรียกใช้งานในพื้นหลัง ( somecommand &) งานนั้นอยู่ในกลุ่มกระบวนการของตัวเองดังนั้นการกดCtrl+ Cจะไม่ส่งผลกระทบต่อมัน
timeoutโปรแกรมที่ตัวเองอยู่ในกลุ่มกระบวนการของตัวเอง จากซอร์สโค้ด:
/* Ensure we're in our own group so all subprocesses can be killed.
Note we don't just put the child in a separate group as
then we would need to worry about foreground and background groups
and propagating signals between them. */
setpgid (0, 0);
เมื่อการหมดเวลาเกิดขึ้นให้ทำtimeoutตามขั้นตอนง่ายๆในการฆ่ากลุ่มกระบวนการที่เป็นสมาชิก เนื่องจากมันได้ทำให้ตัวเองอยู่ในกลุ่มกระบวนการที่แยกต่างหากกระบวนการแม่ของมันจะไม่อยู่ในกลุ่ม การใช้กลุ่มกระบวนการที่นี่ทำให้แน่ใจได้ว่าหากแอปพลิเคชันลูกแยกออกเป็นหลาย ๆ กระบวนการกระบวนการทั้งหมดจะรับสัญญาณ
เมื่อคุณเรียกใช้timeoutโดยตรงบนบรรทัดคำสั่งและกดCtrl+ CSIGINT ที่ได้รับจะได้รับทั้งจากtimeoutและโดยกระบวนการลูก แต่ไม่ใช่โดยเชลล์เชิงโต้ตอบซึ่งเป็นtimeoutกระบวนการหลักของ เมื่อtimeoutถูกเรียกจากสคริปต์เชลล์ที่รันสคริปต์เท่านั้นที่รับสัญญาณ: timeoutไม่รับเนื่องจากเชลล์อยู่ในกลุ่มกระบวนการที่แตกต่างกัน
คุณสามารถตั้งค่าตัวจัดการสัญญาณในเชลล์สคริปต์ด้วยtrapbuiltin น่าเสียดายที่มันไม่ง่ายอย่างนั้น พิจารณาสิ่งนี้:
#!/bin/sh
trap 'echo Interrupted at $(date)' INT
date
timeout 5 sleep 10
date
หากคุณกดCtrl+ Cหลังจาก 2 วินาทีจะยังคงรอ 5 วินาทีเต็มจากนั้นพิมพ์ข้อความ“ ขัดจังหวะ” นั่นเป็นเพราะเชลล์ละเว้นการเรียกใช้โค้ดแทร็บในขณะที่งานพื้นหน้าแอ็คทีฟ
เพื่อแก้ไขปัญหานี้ให้รันงานในพื้นหลัง ในตัวจัดการสัญญาณโทรkillเพื่อถ่ายทอดสัญญาณไปยังtimeoutกลุ่มกระบวนการ
#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid
bgของfgอย่างไรก็ตามมีความแตกต่างระหว่างตัวอย่างที่ 1 และ 3d ของคุณหรือไม่