kill#
לשלוח אות לרשימת תהליכים.
kill הוא הקצה הקדמי של Perl לקריאת המערכת kill(2). הוא מספק את SIGNAL לכל תהליך שמזוהה על־ידי LIST ומחזיר את מספר הארגומנטים שהאות נשלח אליהם בהצלחה. זוהי גם הדרך הסטנדרטית לשאול את הקרנל ״האם ה־PID הזה עדיין קיים והאם מותר לי לשלוח לו אות?״ מבלי להפריע ליעד בפועל, דרך הצורה signal-zero.
תקציר#
kill SIGNAL, LIST
kill SIGNAL # tainting side-effect only; returns 0
מה מקבלים בחזרה#
מספר הארגומנטים ב־LIST שהועברו בהצלחה ל־kill(2). זה אינו בהכרח מספר התהליכים שאכן קיבלו את האות - כאשר SIGNAL שלילי, או כאשר PID מזהה קבוצת תהליכים, ארגומנט אחד יכול לכוון לתהליכים רבים. בשגיאות הרשאה או ״אין תהליך כזה״ עבור ארגומנט, אותו ארגומנט אינו נספר ו־$! מוגדר ל־errno המתאים (EPERM, ESRCH, EINVAL).
my $cnt = kill 'HUP', $child1, $child2;
kill 'KILL', @goners;
עם LIST ריקה, לא נשלח אות וערך ההחזרה הוא 0. צורת kill SIGNAL חשופה נכתבת לעיתים אך ורק כדי להפעיל בדיקות taint על SIGNAL; ראו perlsec.
SIGNAL: שם או מספר#
SIGNAL יכול להיות או שם אות (מחרוזת) או מספר אות. צורת המחרוזת מומלצת לניידות מכיוון שלאותו אות יכולים להיות מספרים שונים במערכות הפעלה שונות.
שם אות יכול לשאת את התחילית SIG או לא - 'TERM' ו־'SIGTERM' קוראים בשם לאותו אות.
kill 'TERM', $pid; # portable
kill 'SIGTERM', $pid; # also fine
kill 15, $pid; # SIGTERM on Linux; may differ elsewhere
kill 9, $pid; # SIGKILL on Linux
רשימת שמות האותות הזמינים בפלטפורמה הנוכחית חיה ב־$Config{sig_name}, שמסופקת על־ידי המודול Config.
SIGNAL 0: בדיקת חיוּת#
אם SIGNAL הוא המספר 0 או המחרוזת 'ZERO' (או 'SIGZERO'), שום אות אינו מסופק בפועל. kill(2) עדיין מבצע את בדיקת ההרשאה שלו, כך שהקריאה אומרת לך האם יהיה אפשרי לשלוח אות לתהליך - כלומר, התהליך קיים ובבעלות אותו משתמש, או שהקורא הוא super-user.
if (kill 0, $pid) {
# process exists and we may signal it
}
elsif ($!{ESRCH}) {
# no such process - it has exited and been reaped
}
elsif ($!{EPERM}) {
# it exists but we are not allowed to signal it
}
זהו המבנה הקנוני לבדיקה שתהליך בן עדיין חי, אפילו כ־zombie, ולא שינה את ה־UID שלו. הוא אינו קוצר את הבן - יש להשתמש ב־waitpid לשם כך.
SIGNAL שלילי: לשלוח אות לקבוצת תהליכים#
שם או מספר אות שלילי שולח אות לקבוצת תהליכים שלמה במקום לתהליך יחיד. kill '-KILL', $pgrp ו־kill -9, $pgrp שניהם שולחים SIGKILL לכל תהליך בקבוצה שמזוהה על־ידי $pgrp.
kill '-TERM', $pgrp; # polite shutdown of the whole group
kill -9, $pgrp; # forced
אותות חיוביים הם כמעט תמיד מה שרוצים. יש לפנות לאות שלילי רק כאשר היעד הוא בכוונה מנהיג של קבוצת תהליכים (לדוגמה תהליך בן שמיקמת בקבוצה משלו עם setpgrp כך שניתן לסיים את תת־העץ בבת אחת).
PID 0, PIDs שליליים#
ההתנהגות של kill כאשר PID הוא אפס או שלילי תלויה במערכת ההפעלה. במערכות תואמות POSIX (כולל Linux):
PID
0- לשלוח אות לקבוצת התהליכים של השולח עצמו.PID
-1- לשלוח אות לכל תהליך שלקורא יש הרשאה לשלוח לו אות (super-user: כל המערכת, פחות כמה PIDs מיוחדים).כל PID שלילי אחר - מתנהג כמו
SIGNALשלילי מול הערך המוחלט: לשלוח אות לקבוצת התהליכים שה־PGID שלה שווה ל־abs(PID).
אם גם SIGNAL וגם ה־PID שליליים, התוצאה לא־מוגדרת; Perl עתידי עשוי להתריע. אין לשלב את השניים.
דוגמאות#
לבקש בנימוס מתהליך בן להיכבות, ואז להסלים:
kill 'TERM', $child;
sleep 2;
kill 'KILL', $child if kill 0, $child;
waitpid $child, 0;
לא לקצור כלום, רק לבדוק האם קובץ PID עדיין נוקב בשם תהליך חי:
open my $fh, "<", "/run/daemon.pid" or die $!;
chomp(my $pid = <$fh>);
close $fh;
if (kill 0, $pid) {
print "daemon alive (pid $pid)\n";
} else {
print "stale pid file: $!\n";
unlink "/run/daemon.pid";
}
לשלוח אות לקבוצת תהליכים שלמה שנוצרה על־ידי תהליך בן של pipeline של shell:
my $pgrp = getpgrp($child);
kill '-TERM', $pgrp;
להתקין מטפל ולשלוח לעצמך אות:
local $SIG{USR1} = sub { warn "got USR1\n" };
kill 'USR1', $$; # $$ is our own PID
לשדר למספר workers ולגלות לכמה מהם היה אפשר להגיע:
my @workers = (1234, 1235, 9999); # 9999 has exited
my $hit = kill 'HUP', @workers; # probably 2
warn "lost a worker: $!\n" if $hit < @workers;
מקרי קצה#
LIST ריקה:
kill 'TERM'לא שולח כלום ומחזיר0. הקריאה עדיין מעריכה אתSIGNAL, וזוהי הסיבה היחידה לכתוב אותה (הפצת taint).שם אות לא־מוכר: מעלה חריגה (
Unrecognized signal name "FOO"). יש לאמת מול$Config{sig_name}אם השם מגיע מקלט משתמש.$!אחרי הצלחה חלקית:killעובר עלLISTמשמאל לימין.$!משקף את הארגומנט הכושל האחרון, לא את כולם. אם נדרשות שגיאות פר־PID, יש לקרוא ל־killפעם אחת לכל PID.Zombies עדיין נחשבים כחיים:
kill 0, $zombie_pidמחזיר אמת עד שהתהליך הבן נקצר עםwaitאוwaitpid. לרוב זה מה שרוצים לבדיקת חיוּת; לעיתים זה מפתיע.מסירת אותות אסינכרונית:
killמוצלח אומר רק שהאות נכנס לתור. המטפל ב־%SIGבתהליך הקולט עשוי לרוץ מאוחר יותר, ומנגנון safe-signal של Perl דוחה מסירה לגבול ה־opcode הבא.שליחה לעצמך:
kill SIGNAL, $$עובד ומהווה את הדרך הרגילה לבדוק את המטפלים שלך ב־%SIG.אין LIST, עם taint: תחת
-T, כתיבתkill 'TERM'מפיצה את ה־taintedness של'TERM'עבור תופעת הלוואי של הפעלת הבדיקה - לצורה אין שימוש אחר.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
fork- ליצור את התהליך הבן שתשלח אליו אות מאוחר יותרwait- לקצור תהליך בן שהסתיים, לנקות zombies ש־kill 0עדיין ידווח עליהם כחייםwaitpid- לקצור תהליך בן ספציפי, אופציונלית non-blocking (WNOHANG) כך שהוא משתלב בצורה נקייה עםkill 0getpgrp/setpgrp- לבחון ולשנות חברות בקבוצת תהליכים, על מה ש־killעם SIGNAL שלילי פועל%SIG- להתקין מטפלים לאותות שאתה שולח עםkillperlipc- טיפול מלא באותות, מטפלים, וסמנטיקת safe-signal