getservent#
קריאת הרשומה הבאה ממסד נתוני השירותים של המערכת.
getservent עובר על מסד הנתונים /etc/services רשומה אחת בכל פעם, ומניב את אותה רשימת שדות כמו getservbyname ו־getservbyport אך ללא מפתח חיפוש. כל קריאה מקדמת סמן פנימי; הסמן נפתח בקריאה הראשונה, מוחזר לאחור על־ידי setservent, ומשוחרר על־ידי endservent. הוא משקף את שגרת ספריית C של POSIX getservent(3) ויורש כל מוזרות ניידות שזה מצריך.
תקציר#
my ($name, $aliases, $port, $proto) = getservent;
my $name = getservent; # scalar context
מה מקבלים בחזרה#
בהקשר רשימה, ארבעה שדות התואמים את הסדר המתועד עבור כל וריאנט getserv*:
$name- שם שירות קנוני, לדוגמה"http".$aliases- מחרוזת מופרדת ברווחים של שמות חלופיים, לדוגמה"www www-http". לא מערך; פצלו אותה בעצמכם אם אתם זקוקים לכזה.$port- מספר פורט כמספר שלם מקומי (סדר בתים של מארח), לדוגמה80.$proto- פרוטוקול תעבורה, בדרך כלל"tcp"או"udp".
בהקשר סקלר, רק $name. כאשר הסמן מגיע לסוף הקובץ, getservent מחזיר את הרשימה הריקה בהקשר רשימה ו־undef בהקשר סקלר - לולאת while (my @e = getservent) הניבית נסמכת על כך.
כדי להמיר את הכינויים לרשימה:
my @alt = split / /, $aliases;
מצב גלובלי שהוא נוגע בו#
סמן מסד נתונים פנימי עבור
/etc/services- משותף עםgetservbyname,getservbyport,setserventו־endservent. כל חיפוש לפי־שם או לפי־פורט בפלטפורמות מסוימות מחזיר לאחור או סוגר את הסמן הזה כתופעת לוואי; איטרו בלולאה צמודה או עטפו את האיטרציה ב־setservent/endserventלמען הביטחון.$!- נקבע כאשר קריאת ה־C הבסיסית מדווחת על שגיאה.אינו בטוח־thread.
getserventשומר מצב לכל־תהליך, לא לכל־thread; שני threads המאיטרים בו־זמנית ישלבו רשומות ואף אחד מהם לא יראה את הרשימה המלאה.
דוגמאות#
מעבר על מסד נתוני השירותים המלא והדפסת כל רשומה:
while (my ($name, $aliases, $port, $proto) = getservent) {
print "$name/$proto $port\n";
}
endservent;
איפוס הסמן לפני האיטרציה כך שקריאות מוקדמות במקומות אחרים בתוכנית לא יוכלו להשאיר אותו באמצע־הזרם:
setservent(0);
while (my @e = getservent) {
# @e is ($name, $aliases, $port, $proto)
}
endservent;
איסוף שירותי TCP בלבד לתוך האש שמפתחו הוא הפורט:
my %tcp;
while (my ($name, undef, $port, $proto) = getservent) {
$tcp{$port} = $name if $proto eq 'tcp';
}
endservent;
השתמשו בממשק מונחה־עצמים לפי־שם מ־Net::servent, אשר עוקף את ה־built-in ומחזיר עצם blessed עם מתודות accessor:
use Net::servent;
while (my $s = getservent) {
printf "%-20s %5d/%s\n", $s->name, $s->port, $s->proto;
}
מקרי קצה#
סוף קובץ מחזיר ריק / undef, לא שגיאה. ערך שקר סקלרי יחיד בהקשר רשימה (
my @e = getserventהמניב רשימה ריקה) הוא הסיומת. אל תבדקו את$!כדי לאתר סוף איטרציה./etc/servicesחסר: במערכות ללא הקובץ, הקריאה הראשונה מחזירה את הרשימה הריקה מיד ו־$!נקבע. שום דבר בקריאה אינו מאותת על ההבדל בין מסד נתונים ריק לבין חסר - בדקו את$!לפני שתניחו שמסד הנתונים היה פשוט ריק.שיתוף סמן עם חיפושים לפי־שם / לפי־פורט: קריאה ל־
getservbynameאוgetservbyportבאמצע לולאתgetserventעלולה לאפס את הסמן בפלטפורמות מסוימות. סיימו את המעבר תחילה או פתחו מחדש עםsetservent.$aliasesהוא מחרוזת, לא רשימה.split / /, $aliasesנותן לכם את צורת המערך. התייחסות ל־$aliasesכרשימה ישירות נותנת לכם בשקט את אורך הרשימה בעלת האלמנט היחיד.תוכניות מבוססות־threads: האיטרציה היא לכל־תהליך. תאמו גישה עם מנעול, או העדיפו
getservbyname/getservbyportלשאילתות נקודתיות בקוד מבוסס־threads.הקשר סקלר מחזיר רק את השם. אם אתם זקוקים לפורט, קראו בהקשר רשימה גם כאשר אכפת לכם רק משדה אחד.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
getservbyname- חיפוש שירות יחיד לפי שמו הטקסטואלי במקום איטרציהgetservbyport- חיפוש שירות יחיד לפי הפורט המספרי שלוsetservent- החזרת הסמן המשותף לאחור לפני האיטרציה כך שקריאות קודמות לא יוכלו להשאיר אותו באמצע־הזרםendservent- שחרור הסמן כאשר המעבר הסתיים, ושחרור file descriptor הבסיסיgetprotoent- אותה תבנית איטרטור עבור/etc/protocols, בדרך כלל מזווג בפתרון tuple של(port, proto)Net::servent- עטיפה מונחית־עצמים שה־accessors שלה מסירים את הצורך לזכור את סדר השדות