`kill -0` ทำอะไร


61

ฉันเพิ่งเจอสิ่งนี้ในเชลล์สคริปต์

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

อะไรkill -0 ...ทำอย่างไร


2
ดูที่นี่หากคุณสับสนเกี่ยวกับความแตกต่าง b / w trapคำสั่งBash และ 0 กับสัญญาณ 0 จากkill: สัญญาณ 0 ในคำสั่ง Trap คืออะไร
slm

ดูเพิ่มเติมคำถามเก่า StackOverflow อะไรkill -0 $pidในสคริปต์เปลือกทำอย่างไร เช่นเดียวกับสิ่งที่ไม่ฆ่า 0 ทำจริง? .
Adam Katz

คำตอบ:


76

อันนี้ค่อนข้างยากที่จะรวบรวม แต่ถ้าคุณดูใน 2 man pages ต่อไปนี้คุณจะเห็นหมายเหตุต่อไปนี้:

ฆ่า (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
ฆ่า (2)
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed; 
this can be used to check for the existence of a process ID or process 
group ID.
...

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

สิ่งนี้อาจมีประโยชน์ที่ไหน?

สถานที่หนึ่งที่ชัดเจนคือถ้าคุณพยายามตรวจสอบว่าคุณมีสิทธิ์ในการส่งสัญญาณไปยังกระบวนการที่ทำงานอยู่killหรือไม่ คุณสามารถตรวจสอบก่อนที่จะส่งkillสัญญาณจริงที่คุณต้องการโดยการตรวจสอบเพื่อให้แน่ใจว่าkill -0 <PID>ได้รับอนุญาตก่อน

ตัวอย่าง

บอกว่ากระบวนการกำลังถูกรูทโดยดังนี้:

$ sudo sleep 2500 &
[1] 15693

ตอนนี้ในหน้าต่างอื่นถ้าเราเรียกใช้คำสั่งนี้เราสามารถยืนยันได้ว่า PID กำลังทำงานอยู่

$ pgrep sleep
15693

ทีนี้ลองคำสั่งนี้ดูว่าเราสามารถส่งสัญญาณ PID killนั้นได้หรือไม่

$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!

ดังนั้นจึงใช้งานได้ แต่เอาต์พุตกำลังรั่วข้อความจากkillคำสั่งที่เราไม่มีสิทธิ์ใช้งาน ไม่ได้เป็นเรื่องใหญ่ก็จับ STDERR /dev/nullและส่งไปยัง

$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!

ตัวอย่างที่สมบูรณ์

ดังนั้นเราจึงสามารถทำสิ่งนี้killer.bash:

#!/bin/bash

PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then 
  echo "you don't have permissions to kill PID:$PID"
  exit 1
fi

kill -9 $PID

ตอนนี้เมื่อฉันเรียกใช้ข้างต้นเป็นผู้ใช้ที่ไม่ใช่รูท:

$ ~/killer.bash 
you don't have permissions to kill PID:15693

$ echo $?
1

อย่างไรก็ตามเมื่อมันรันเป็นรูท:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

9
ฉันจะเพิ่มสิ่งนี้สามารถใช้สำหรับสคริปต์แบบหลาย proc เพื่อดูว่ากระบวนการยังคงทำงานอยู่หรือไม่
prateek61

1
@slm พบที่ดี ใช้ตรรกะนี้ตอนนี้ในสคริปต์ฉันเขียนขอบคุณ
111 ---

12
Prateek61 ถูกต้อง คุณไม่สามารถใช้pgrep, psการแยกหรือtest -e /proc/$PIDใน scrips แบบพกพา แต่kill -0ทำงานได้ทุกที่ หากคุณได้รับ PID ที่อาจค้าง - เช่น/var/runรายการ - นี่เป็นวิธีพกพาเพื่อตรวจสอบว่ากระบวนการยังมีชีวิตอยู่หรือไม่
Warren Young

1
นอกเหนือจากการบอกคุณว่า PID ยังมีชีวิตอยู่หรือไม่มันยังบอกคุณได้อย่างมีประสิทธิภาพว่ายังใช้กระบวนการจาก UID ของคุณหรือไม่เนื่องจากคุณไม่ได้รับอนุญาตให้ส่งสัญญาณไปยัง UID อื่น ๆ (ยกเว้นว่าคุณรูท) สิ่งนี้ทำให้ผลบวกผิดพลาดเนื่องจาก PID ใช้ซ้ำมีโอกาสน้อย
Barmar

ความล้มเหลวkill -0 $(pgrep sleep)อาจไม่ได้หมายความว่าคุณกำลังอ่อนแอมันจะกลับมาผิดพลาดหากไม่มีsleepคำสั่งทำงานหรือมีมากกว่าหนึ่งและมีสิ่งหนึ่งที่คุณไม่สามารถฆ่าได้หรือถ้าหนึ่งในสลีปเสียชีวิตระหว่าง pgrep และการฆ่า คำสั่งถูกเรียกใช้
Stéphane Chazelas

22

kill -0(หรือตัวแปร POSIX แบบพกพามากกว่าkill -s 0) ผ่านการเคลื่อนที่ของการส่งสัญญาณ แต่ไม่ได้ส่งสัญญาณ มันเป็นคุณสมบัติของC API พื้นฐานที่คำสั่งเชลล์เปิดเผยในลักษณะที่ตรงไปตรงมา

kill -s 0 -- "$pid"ดังนั้นทดสอบว่ามีกระบวนการทำงานด้วย PID ที่กำหนด (หรือ PGID ถ้า$pidเป็นลบ) หรือไม่และกระบวนการปัจจุบันจะได้รับอนุญาตให้ส่งหรือไม่ (กระบวนการใด ๆ ในกลุ่มกระบวนการในกรณีที่$pidมีสัญญาณลบ) ส่วนใหญ่เป็นวิธีการทดสอบว่ากระบวนการ (หรือกลุ่มกระบวนการ) ยังมีชีวิตอยู่

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


0

กระบวนการkill -0 $pidจะบอกคุณว่ากระบวนการที่มี$pidอยู่หรือไม่

ในตัวอย่าง

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

บล็อก... do something ...จะถูกดำเนินการหากกระบวนการที่มี PID ที่เก็บอยู่/path/to/file.pidนั้นกำลังทำงานอยู่ - และ - ยกเว้นว่าข้อมูลโค้ดนั้นทำงานเป็นรูท - หาก PID นั้นทำงานภายใต้ผู้ใช้รายเดียวกัน

มาตรฐาน POSIX ระบุบทบาทของ0สัญญาณ:

หาก sig เป็น 0 (สัญญาณว่าง) การตรวจสอบข้อผิดพลาดจะดำเนินการ แต่ไม่มีการส่งสัญญาณใด ๆ สัญญาณว่างสามารถใช้เพื่อตรวจสอบความถูกต้องของ pid

(kill (3p), POSIX.1-2008 - ถ้อยคำที่คล้ายกันใน POSIX.1-2001)

โปรดทราบว่า POSIX ระบุทั้งสไตล์kill -0และkill -s 0บรรทัดคำสั่ง (kill (1p))

ตรงกันข้ามกับ kill syscall interface killไม่สามารถใช้คำสั่งเพื่อตรวจสอบการมีอยู่ของ PID ที่ผู้ใช้รายอื่นเป็นผู้ใช้ (ในฐานะผู้ใช้ทั่วไป) ได้อย่างน่าเชื่อถือเช่น:

$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1

เมื่อเทียบกับ

$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1

เมื่อเรียกใช้ kill syscall สามารถแยกแยะกรณีเหล่านี้ได้อย่างน่าเชื่อถือผ่านการดูerrnoค่า (เช่นตัวอย่าง Python )

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