VPN ב-Mac בזמן האתחול: launchd מפקח על המשימה, לא על המנהרה
plist נקי אינו מוכיח דבר לגבי אישורים או מוכנות. התאימו את המשימה לסשן שלה, השאירו את הלקוח בחזית ובדקו בהקשר הזה.
המשימה פועלת בעת ההתחברות, היומן מראה שהלקוח מתחיל, והמנהרה לא עולה. או שהיא עולה ונעלמת כמה שניות לאחר מכן. בשני המקרים רשימת המאפיינים כנראה הייתה תקינה. launchd נתן שתי הבטחות כשקיבל את המשימה: הוא יפקח על תהליך, והתהליך הזה ימשיך לרוץ. ה-VPN זקוק לשניהם, וקובץ XML תקין לא מספק אף אחד מהם.
רשימת מאפיינים תקינה אינה שירות עובד
plutil -lint בודק את המבנה. הוא לא יכול לומר אם קובץ ההרצה קיים, אם הארגומנטים נתמכים בגרסת לקוח זו, או אם המשימה מתחילה בהקשר שבו האישורים זמינים. אלו שאלות סמנטיות, והן מסבירות את רוב הכשלים שנראים כמו בעיות של launchd.
plutil -lint /Library/LaunchDaemons/com.example.vpn.plist
launchctl print system/com.example.vpn
קראו את הפלט של הפקודה השנייה במקום להניח שהמשימה נטענה. הוא מדווח את סטטוס היציאה האחרון ואם השירות פועל, מה שמבדיל בין “מעולם לא התחיל” לבין “התחיל ומת” לפני שאתם נוגעים בפרופיל.
סוכנים יורשים סשן משתמש, דמונים לא
התיעוד של Apple ל-launchd מפריד בין סוכנים לפי משתמש לבין דמוני מערכת. סוכן פועל בהקשר של המשתמש המחובר, עם מחזיק המפתחות והסביבה שלו. דמון פועל בלי הסשן הזה, והעברת משימה לספריית מערכת אינה יוצרת מחדש את האישורים האינטראקטיביים של המשתמש.
ההבחנה הזו קובעת את התכנון. אם החיבור דורש שאדם יתחבר או יאשר בקשת MFA, הסידור הנתמך הוא משימה בסשן המשתמש שרצה לאחר ההתחברות. אם היא חייבת לעבוד בלי שאף אחד מחובר, הלקוח זקוק לזהות מאושרת ללא השגחה עם תהליך חידוש וביטול משלה. בחירת השורה הלא נכונה מייצרת משימה שמתחילה נקי ונכשלת בשלב האימות הראשון.
אל תטשטשו את ההבדל עם סיסמה במערך הארגומנטים או על ידי השבתת בדיקות תעודה. שניהם הופכים דרישת אימות לסוד קבוע בקובץ קריא, והשני פירושו שהמנהרה מאמתת כל דבר שעונה.
פיקוח עובד רק אם התהליך נשאר בחזית
לקוח שהופך את עצמו לדמון מחזיר את השליטה ל-launchd מיד, והמפקח צופה אז בתהליך שכבר יצא. המנהרה עשויה להיות למעלה, אבל launchd חושב שהמשימה נכשלה, ומדיניות ההפעלה מחדש שלו תעשה משהו שלא התכוונתם לו.
השתמשו במצב החזית או במצב השירות המתועד של הלקוח. אם למוצר יש תכונת אתחול נתמכת משלו, היא כבר יודעת איך להישאר בחזית ואיך למסור למערך הרשת; משימה מותאמת היא תכנון נפרד, לא שיפור שלה.
תנו למשימה תווית ייחודית, את קובץ ההרצה המיועד ומערך ארגומנטים מחושב. מערך אינו שורת פקודה של shell, ולכן צינורות והפניות לא עובדים שם, והמירכאות מתנהגות אחרת. פקודה שמצליחה במסוף של מנהל מערכת היא לכל היותר בדיקה מקדימה.
האישורים חייבים לעבוד בלי בקשה
הפעלה ללא השגחה מזיזה את בעיית האישורים במקום להסיר אותה. מישהו צריך להחזיק בזהות, להחליט כמה זמן היא חיה ולתעד איך מחליפים אותה. תעודה בלי ניטור תפוגה הופכת לתקלה עם תאריך בלוח השנה.
הרחיקו סודות מהארגומנטים ומהפלט הסטנדרטי של המשימה. אם הלקוח תומך בקריאת אישור ממאגר מוגן, השתמשו בנתיב הזה, ובדקו שהקשר ההרצה של המשימה מגיע למאגר. דמון שרץ כ-root בדרך כלל לא יכול לקרוא פריט במחזיק המפתחות של ההתחברות, וזה בדיוק סוג הפרט שמתגלה רק בהקשר המערכת.
הגדירו מה פירוש מוכנות, ואז בדקו אותה שם
הפעלה מוצלחת מוכיחה שהתהליך התחיל. היא לא מוכיחה שהרשת פועלת, שהשער קיבל את הזהות, או שהיישום הפרטי נגיש. אם משהו אחר תלוי במנהרה, הוא זקוק לאות מוכנות שמשקף את החיבור, לא את שעת ההתחלה של המשימה.
הניסיונות החוזרים צריכים להיות מוגבלים ולהבחין בין רשת חסרה לבין אישור שנדחה. הפעלה מחדש בכל כשל אינה מתקנת תעודה שפגה ומייצרת יומן מלא בניסיונות זהים שמסתיר את האמיתי.
קבלו את המשימה בהקשר שבו היא באמת תרוץ: בלי רשת באתחול, התחברות רגילה, התעוררות משינה ועצירה מבוקרת. אחר כך רשמו יחד את תווית המשימה, גרסת הלקוח ואת מהדורת הפרופיל, כדי שהאדם הבא יירש שירות שניתן לייחס אותו במקום קובץ שפעל פעם.