ปุ่มสัญญาณเช่น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
ไม่รับเนื่องจากเชลล์อยู่ในกลุ่มกระบวนการที่แตกต่างกัน
คุณสามารถตั้งค่าตัวจัดการสัญญาณในเชลล์สคริปต์ด้วยtrap
builtin น่าเสียดายที่มันไม่ง่ายอย่างนั้น พิจารณาสิ่งนี้:
#!/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 ของคุณหรือไม่