endgrent#
סוגר את מסד נתוני הקבוצות לאחר איטרציה עליו.
endgrent הוא חצי הניקוי של שלישיית האיטרציה על מסד נתוני הקבוצות setgrent / getgrent / endgrent. הוא מודיע לספריית C שסיימת לעבור על /etc/group (או מקור ה־NSS שמאחוריו), משחרר כל file descriptor או מצב במטמון שהספרייה פתחה בשמך. לאחר endgrent, הקריאה הבאה ל־getgrent מתחילה איטרציה רעננה מהראש.
תקציר#
endgrent;
endgrent();
ללא ארגומנטים, ללא ערך החזרה משמעותי.
מה מקבלים בחזרה#
ערך ההחזרה אינו מוגדר ואין להסתמך עליו. endgrent נקרא בעבור תופעת הלוואי שלו - סגירת מסד נתוני הקבוצות - לא בעבור תוצאה. התייחס אליו כאל קריאה ב־void.
endgrent; # correct
my $ok = endgrent; # wrong: $ok is not a success flag
אם הפלטפורמה שלך אינה ממשת endgrent, הקריאה croaks עם The endgrent function is unimplemented בזמן ריצה. זוהי למעשה בדיקת הידור־חד־פעמית - אם הפונקציה עובדת במערכת שלך בכלל, היא תמשיך לעבוד.
מצב גלובלי שהוא נוגע בו#
endgrent פועל אך ורק על מצב איטרציית־הקבוצות הפנימי של libc ש־setgrent ו־getgrent חולקים. הוא אינו קורא ואינו כותב משתנים מיוחדים של Perl. הוא אינו משנה את $!: מסלול כישלון שמגדיר errno בקריאת ה־C הבסיסית אינו מועלה ל־Perl.
The iteration state is per-process, not per-thread. In a threaded program, one thread’s endgrent closes the iteration for every thread
see Edge cases.
דוגמאות#
תבנית האיטרציה־וסגירה הקנונית. תמיד התאם לולאת setgrent / getgrent עם endgrent כדי שתוכניות ארוכות־טווח לא ידלפו את ה־file descriptor שספריית C משאירה פתוח:
setgrent;
while (my @g = getgrent) {
my ($name, $passwd, $gid, $members) = @g;
print "$name ($gid): $members\n";
}
endgrent;
נפילה אל endgrent באמצע איטרציה היא חוקית - היא פשוט נוטשת את כל מיקום הסמן שהספרייה החזיקה:
setgrent;
while (my @g = getgrent) {
last if $g[0] eq 'wheel'; # found what we wanted
}
endgrent; # release the handle anyway
הפעלה מחדש של איטרציה. endgrent ולאחריו setgrent היא הדרך הניידת להחזיר לאחור:
setgrent;
my @first_pass = collect_groups();
endgrent;
setgrent;
my @second_pass = collect_groups(); # starts over from the top
endgrent;
ניקוי הגנתי בבלוק END עבור תוכניות שעלולות למות באמצע מעבר:
setgrent;
END { endgrent }
while (my @g = getgrent) { ... } # any die still triggers END
מקרי קצה#
קריאה ל־
endgrentללאsetgrentאוgetgrentקודמים היא לא־מזיקה. ספריית C אינה עושה דבר בשקט אם אין איטרציה בעיצומה.קריאה לו פעמיים ברצף היא גם לא־מזיקה - הקריאה השנייה היא no-op.
עמימות פענוח.
endgrentאינו לוקח ארגומנט ויש לו את הקדימות של אופרטור unary בעל שם. ביטוי bareword מיד מימינו יפורש כארגומנט וייפסל:endgrent or die; # WRONG: parses as endgrent(or die) endgrent() or die; # right: empty parens disambiguate
בפועל אין מול מה לבדוק את ערך ההחזרה, כך שמלכודת זו נושכת לעתים נדירות - אך אותו כלל חל על כל ביטוי משורשר.
Threads חולקים את האיטרציה.
endgrentמ־thread אחד מסיים איטרציה לכל ה־threads של אותו תהליך, מאחר שהמצב הבסיסי הוא גלובלי־לתהליך. אל תשלב קריאותgetgrentעל פני threads בציפייה שכל אחד יראה כל רשומה.NSS ושמירה במטמון. במערכות שבהן מסד נתוני הקבוצות מוגש דרך NSS (nss_ldap, nss_sss וכו«),
endgrentמשחרר מטמונים לכל־מודול שה־backend של NSS עשוי להחזיק. דמונים ארוכי־חיים שעוברים על מסד נתוני הקבוצות מעת לעת אמורים לקרוא ל־endgrentלאחר כל מעבר כדי להימנע מצבירת מצב backend.אין השפעה על קריאות חיפוש לפי שם.
getgrnamו־getgrgidבלתי־תלויים בסמן האיטרציה.endgrentאינו פוסל את התוצאות שלהם או נתונים במטמון, ואינך צריך לקרוא ל־endgrentלפניהם או אחריהם.לא ממומש בחלק מהפלטפורמות. Perl עושה croak
The endgrent function is unimplementedאם ל־libc המארח איןendgrent(3). כל מערכות Linux, BSD ו־macOS מודרניות מספקות אותו.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
setgrent- פותח או מחזיר לאחור את מסד נתוני הקבוצות לפני המעבר עליו; תמיד הפרולוג לאיטרציה שמסתיימת ב־endgrentgetgrent- שולף את הרשומה הבאה מהאיטרציה ש־endgrentסוגרgetgrnam- מחפש קבוצה אחת לפי שם, בלתי־תלוי בסמן האיטרציה; אין צורך ב־endgrentendpwent- קריאת הניקוי המקבילה למסד נתוני passwd; שתי האיטרציות בלתי־תלויות ושתיהן זקוקות לסגירה אם פתחת את שתיהן