ฉันจะตรวจสอบว่า PID ที่ระบุกำลังทำงานอยู่ได้อย่างไร


16

ฉันกำลังเขียนสคริปต์ Perl ที่แยกวิเคราะห์ logfiles เพื่อรวบรวม PID แล้วตรวจสอบว่า PID นั้นทำงานอยู่หรือไม่ ฉันพยายามคิดวิธีที่ดีที่สุดในการตรวจสอบ เห็นได้ชัดว่าฉันสามารถทำสิ่งที่ชอบ:

system("ps $pid > /dev/null") && print "Not running\n";

อย่างไรก็ตามฉันต้องการหลีกเลี่ยงการเรียกระบบถ้าเป็นไปได้ ฉันจึงคิดว่าฉันสามารถใช้/procระบบไฟล์ได้ (ความสะดวกในการพกพาไม่ใช่เรื่องที่น่ากังวลนี่จะทำงานบนระบบ Linux เสมอ) ตัวอย่างเช่น:

if(! -d "/proc/$pid"){
    print "Not running\n";
}

ปลอดภัยไหม ฉันสามารถเดาได้หรือไม่ว่าหากไม่มี/proc/$pid/ไดเรกทอรี PID ที่เกี่ยวข้องไม่ทำงานอยู่ ฉันคาดหวังเช่นนั้นเนื่องจาก AFAIK psเองได้รับข้อมูลจากตัวเอง/procแต่เนื่องจากเป็นรหัสการผลิตฉันจึงต้องการให้แน่ใจ

ดังนั้นจะมีกรณีที่กระบวนการทำงานไม่มี/proc/PIDไดเรกทอรีหรือมี/proc/PIDไดเรกทอรีอยู่และกระบวนการไม่ทำงานหรือไม่ มีเหตุผลใดที่ต้องการแยกวิเคราะห์psมากกว่าการตรวจสอบการมีอยู่ของไดเรกทอรีหรือไม่?


2
นอกจากนี้ยังมีkillฟังก์ชั่นPerl โดยใช้สัญญาณ 0 ซึ่งไม่ฆ่า แต่บอกว่าคุณสามารถทำได้ (เช่นคุณต้องได้รับอนุญาตในการส่งสัญญาณกระบวนการนั้น)
meuh

1
'/ proc / $ PID' น่าจะดีถ้าคุณทำสิ่งนี้ใน Linux
likewhoa

7
@terdon โปรดทราบว่าวิธีการใดก็ตามที่คุณใช้ (และkill -0เป็นวิธีที่ดีที่สุด) นี่จะบอกคุณว่ามีกระบวนการกำลังทำงานที่มี PID ที่กำหนดหรือไม่ ไม่ได้บอกคุณว่ากระบวนการจะยังคงทำงานต่อไปหนึ่งมิลลิวินาทีหรือไม่และไม่ได้บอกคุณว่ากระบวนการนั้นเป็นกระบวนการที่คุณสนใจหรือกระบวนการที่ไม่เกี่ยวข้องซึ่งกำหนด PID เดียวกันหลังจากกระบวนการที่น่าสนใจตาย . มันเกือบจะผิดพลาดในการทดสอบว่า PID ที่กำหนดกำลังทำงานอยู่หรือไม่ : มีบางสถานการณ์ที่ไม่ได้เกิดจากสภาพการแข่งขัน
Gilles 'หยุดชั่วร้าย'

1
@Gilles แน่นอนฉันควรตรวจสอบชื่อกระบวนการด้วย อย่างไรก็ตามในกรณีนี้ฉันไม่สนใจว่าจะมีสถานะเปลี่ยนเป็นมิลลิวินาทีในภายหลัง ฉันมีกระบวนการที่ระบุว่าใช้งานอยู่ในเดซิเบลและไฟล์ที่เกี่ยวข้องกับ pids ฉันแค่ต้องตรวจสอบว่าสิ่งใดที่ DB คิดว่าทำงานอยู่ไม่ได้ทำงานจริง ๆ และมีการควบคุมการตั้งค่าเพียงพอที่จะรู้ว่ามันไม่สามารถเริ่มต้นใหม่ได้แบบสุ่ม
terdon

3
@MickLH ว้าวฉันบอกแล้ว ที่จริงแล้วจะเป็นความคิดเห็นที่มีประโยชน์แทนการเฉลิมฉลองความสามารถของคุณเองถ้าคุณใส่ใจที่จะอธิบายสิ่งที่เลวร้ายและอันตราย ฉันไม่สงสัยเลยว่าคุณพูดถูกฉันไม่เคยอ้างว่าเป็นโปรแกรมเมอร์ซึ่งเป็นสาเหตุที่ฉันถามคำถามนี้ แต่คุณจัดการเพื่อดูถูกเหยียดหยามและช่วยเหลือไม่ได้
terdon

คำตอบ:


20

kill(0,$pid)สามารถใช้ฟังก์ชัน perl

หากรหัสส่งคืนเป็น 1 แสดงว่ามี PID อยู่และคุณได้รับอนุญาตให้ส่งสัญญาณ

หากรหัสส่งคืนเป็น 0 คุณต้องตรวจสอบ $! อาจเป็น EPERM (สิทธิ์ถูกปฏิเสธ) ซึ่งหมายถึงกระบวนการนั้นมีอยู่หรือ ESRCH ซึ่งในกรณีนี้ไม่มีกระบวนการ

หากรหัสการตรวจสอบของคุณกำลังทำงานอยู่rootคุณสามารถทำให้มันง่ายขึ้นเพียงแค่ตรวจสอบรหัสส่งคืนของการฆ่า 0 => ข้อผิดพลาด 1 => ตกลง

ตัวอย่างเช่น:

% perl -d -e 0

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> print kill(0,500)
0
  DB<2> print $!
No such process
  DB<3> print kill(0,1)
0
  DB<4> print $!
Operation not permitted
  DB<5> print kill(0,$$)
1

สิ่งนี้สามารถทำให้เป็นฟังก์ชั่นที่เรียบง่าย

use Errno;

sub test_pid($)
{
  my ($pid)=@_;

  my $not_present=(!kill(0,$pid) && $! == Errno::ESRCH);

  return($not_present);
}

print "PID 500 not present\n" if test_pid(500);
print "PID 1 not present\n" if test_pid(1);
print "PID $$ not present\n" if test_pid($$);

FWIW ฉันได้เพิ่มฟังก์ชั่นพื้นฐานที่แสดงให้เห็นว่าคุณทำได้อย่างไร
Stephen Harris

ใช่ฉันคิดว่าฉันจะไปกับสิ่งนี้ ฉันลบความคิดเห็นของฉันเนื่องจากฉันตระหนักว่าสิ่งที่ฉันต้องการทั้งหมดนั้นif (!kill(0,$pid) && $! =~ /No such process/){ exit; }หรือคล้ายกัน ฉันชอบErrnoทางออกของคุณดีกว่าขอบคุณ ในขณะที่ฉันอาจจะไปกับสิ่งนี้ฉันจะรอสักครู่ในกรณีที่ทุกคนสามารถตอบคำถาม Linux พื้นฐาน
terdon

2
ถ้า/procเมานต์แล้ว PID ทุกอันที่ปรากฏในเนมสเปซจะมีอยู่ดังนั้น-d /proc/$pidการทดสอบของคุณจะทำงาน ...
Stephen Harris

ซึ่งเป็นสิ่งที่ฉันต้องการหลีกเลี่ยงอย่างแน่นอน
terdon

2
@terdon: ผมเพิ่งตระหนักความสับสนของฉันมาจากข้อเท็จจริงที่ว่าด้วย "ระบบเรียกว่า" คุณหมายจริง " systemโทร" - กล่าวคือการเรียกsystemฟังก์ชั่นของตัวเองไม่ได้เป็น"สายระบบ" หลังที่คุณไม่สามารถหลีกเลี่ยงได้ แต่ในอดีตคุณสามารถทำได้อย่างแน่นอน เข้าท่าเลย!
user541686

6
  • ฉันแน่ใจว่า 99.9% การตรวจสอบว่ามีอยู่ (และเป็นไดเรกทอรี) หรือไม่ 98% น่าเชื่อถือเท่ากับเทคนิค เหตุผลที่ 98% ไม่ใช่ 100% เป็นประเด็นที่สตีเฟ่นแฮร์ริสแตะ (และกระเด็น) ในความคิดเห็น - กล่าวคือระบบไฟล์อาจไม่ถูกเมาท์ มันอาจจะเป็นที่ถูกต้องเพื่ออ้างว่าระบบ Linux โดยไม่ต้อง เป็นความเสียหายระบบเสื่อมโทรม - หลังจากที่ทุกสิ่งที่ชอบ, และอาจจะไม่ทำงาน - และอื่น ๆ อาจจะไม่เป็นปัญหาสำหรับระบบการผลิต แต่เป็นไปได้ (ในทางทฤษฎี) ที่เป็นไปได้เพราะไม่เคยมีการติดตั้ง (แม้ว่าจะทำให้ระบบไม่สามารถเข้าสู่สถานะปกติ) ได้แน่นอนว่าเป็นไปได้ที่จะยกเลิกการต่อเชื่อม (ฉันได้ทดสอบแล้ว1/proc/PIDkill 0/proc/procpstoplsof) และฉันเชื่อว่าไม่มีการรับประกันว่าจะมีอยู่ (กล่าวคือไม่จำเป็นต้องใช้โดย POSIX) และถ้าระบบถูกปิดอย่างสมบูรณ์killก็จะทำงานได้
  • ความคิดเห็นของสตีเฟ่นพูดถึง“ การออกไปสู่ระบบไฟล์” และ“ การใช้การเรียกใช้ระบบดั้งเดิม” ฉันเชื่อว่านี่เป็นปลาเฮอริ่งแดงส่วนใหญ่
    • ใช่ความพยายามที่จะเข้าถึงใด ๆ/proc ต้องอ่านไดเรกทอรีรากจะพบ/procระบบแฟ้ม นี้เป็นจริงสำหรับความพยายามใด ๆ ที่จะเข้าถึงใด ๆไฟล์โดยชื่อพา ธ สัมบูรณ์รวมถึงสิ่งที่อยู่ใน/bin, และ/etc /devสิ่งนี้เกิดขึ้นบ่อยครั้งที่ไดเรกทอรีรากถูกแคชไว้ในหน่วยความจำตลอดอายุการใช้งาน (uptime) ของระบบดังนั้นขั้นตอนนี้สามารถทำได้โดยไม่มีดิสก์ I / O ใด ๆ และเมื่อคุณมีไอโหนด/procแล้วสิ่งอื่น ๆ ที่เกิดขึ้นก็อยู่ในความทรงจำ
    • คุณเข้าถึงได้/procอย่างไร ด้วยstat, open, readdirฯลฯ killซึ่งเป็นระบบพื้นเมืองเรียกทุกบิตมากที่สุดเท่าที่
  • คำถามพูดคุยเกี่ยวกับกระบวนการทำงาน นี่เป็นวลีที่ลื่น หากคุณต้องการทดสอบว่ากระบวนการกำลังทำงานอยู่หรือไม่ (เช่นในคิวการทำงานอาจเป็นกระบวนการปัจจุบันของ CPU บางตัวไม่นอนรอหรือหยุดทำงาน) คุณอาจต้องทำและอ่านเอาต์พุตหรือดูที่. แต่ฉันไม่เห็นคำใบ้ในคำถามหรือความคิดเห็นของคุณที่คุณกังวลps PID /proc/PID/stat

    อย่างไรก็ตามช้างในห้องนั้นเป็นกระบวนการที่ซอมบี้2สามารถแยกความแตกต่างจากกระบวนการที่มีชีวิตและดี  kill 0ทำงานกับซอมบี้และมีอยู่จริง คุณสามารถระบุซอมบี้ด้วยเทคนิคที่แสดงรายการในย่อหน้าก่อนหน้า (การทำและอ่านผลลัพธ์หรือดูที่) ฉันมากอย่างรวดเร็วและสบาย ๆ (เช่นไม่ใช่อย่างมาก) การทดสอบแสดงให้เห็นว่าคุณยังสามารถทำเช่นนี้โดยการทำหรือ บน, หรือ- เหล่านี้จะล้มเหลวในซอมบี้ (อย่างไรก็ตามพวกเขาจะล้มเหลวในกระบวนการที่คุณไม่ได้เป็นเจ้าของ)/proc/PIDps PID/proc/PID/statreadlinklstat/proc/PID/cwd/proc/PID/root/proc/PID/exe

____________
1  หากตัวเลือก-f( f orce) ใช้งานไม่ได้ให้ลอง-l( l azy)
2  คือกระบวนการที่ได้ออก / การตาย / ยกเลิก waitแต่มีผู้ปกครองยังไม่ได้ทำ


ขอบคุณสำหรับความคิดเห็นของคุณในคำตอบของฉันซึ่งฉันได้ลบไปแล้วเพราะมันผิด ฉันไม่เชื่อว่าkill(2)manpage บ่งบอกถึงพฤติกรรมที่คุณชี้ให้เห็นโดยตรง แต่perlfuncmanpage นั้น ฉันจะส่งอีเมล Michael Kerrisk เพื่อดูสิ่งที่เขาพูดเกี่ยวกับ manpage ของระบบ
jrw32982 รองรับ Monica

ฉันได้ยื่นรายงานข้อผิดพลาดเพื่อชี้แจง man-page สำหรับkill(2)เกี่ยวกับการอนุญาตให้ "ส่ง" สัญญาณ 0
jrw32982 รองรับโมนิก้า

@ jrw32982: หน้าคนพูดว่า " อาร์กิวเมนต์sig ... อาจเป็น 0 ซึ่งดำเนินการตรวจสอบข้อผิดพลาดกรณี ... " และ " ข้อผิดพลาด - การเรียกระบบkill ()จะล้มเหลวและไม่มีสัญญาณถูกส่งถ้า: ... กระบวนการส่งไม่ใช่ผู้ใช้ขั้นสูงและรหัสผู้ใช้ที่มีประสิทธิภาพไม่ตรงกับรหัสผู้ใช้ที่มีประสิทธิภาพของกระบวนการรับ …” ตอนนี้คุณพูดถึงแล้วฉันคิดว่ามันสามารถตีความได้มากกว่าหนึ่งทาง แต่น่าเสียดายที่หน้าเว็บของ Unix หลายเล่มเขียนด้วยวิธีนี้ทำให้คุณต้องอ่านระหว่างบรรทัด ไมเคิลอาจจะเชื่อว่ามันชัดเจนเพียงพอแล้ว
G-Man พูดว่า 'Reinstate Monica'

Michael ทำการเปลี่ยนแปลงkill(2)manpage (ฉันไม่เห็นมันยังออนไลน์อยู่): "ถ้า sig เป็น 0 จะไม่มีการส่งสัญญาณ แต่การตรวจสอบการมีอยู่และการอนุญาตยังคงดำเนินการนี่สามารถใช้เพื่อตรวจสอบการมีอยู่ของ ID กระบวนการหรือ ID กลุ่มกระบวนการที่ผู้โทรได้รับอนุญาตให้ส่งสัญญาณ "
jrw32982 รองรับ Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.