status=200/CHDIR: systemd מעולם לא הפעיל את OpenVPN
כשל CHDIR פירושו ש-systemd לא הצליח להיכנס לספרייה, לא ש-OpenVPN לא הצליח לקרוא פרופיל. קרא את היחידה לפני שאתה נוגע בתצורת ה-VPN.
השירות נכשל, הלוגים מזכירים spawn וספרייה, והדחף הראשון הוא לבדוק את תצורת ה-VPN. בקובץ ההוא עדיין לא נקרא דבר. systemd נכשל בעת הכנת התהליך, לפני שהקובץ ההרצה עלה, ולכן לא נבדק שום מנתח, שום תעודה ושום מארח מרוחק. קריאת קוד המצב כהצהרה על systemd ולא על OpenVPN היא מה שהופך את זה לחקירה קצרה.
קרא את קוד המצב לפני היישום
הקוד המספרי שאחרי שם השירות מציין את השלב שנכשל. כשל ספרייה מדווח כמצב CHDIR, ואילו קובץ הרצה שלא ניתן להריץ הוא קוד אחר לגמרי. השניים נראים דומים בשורת סיכום ואין להם דבר במשותף בסיבותיהם.
ההבחנה הזו חשובה כי התיקונים נמצאים בקבצים שונים. כשל CHDIR עוסק בנתיב ובאופן שבו השירות רואה אותו. כשל exec עוסק בקובץ הבינארי, במפרש שלו או ב-mount לא קשור. שינוי נקודת הקצה המרוחקת של ה-VPN, רשימת הצפנים או נתיב התעודה לא יכול לפתור אף אחד מהם.
ודא שהכשל מתרחש בהתחלה ולא אחרי ריצה מוצלחת. אם השירות עבד אתמול וכעת נכשל באותו שלב, משהו השתנה בספרייה, בהרשאות שלה או ביחידה עצמה, והשינוי הזה הוא הראיה שיש לחפש.
שאל את היחידה איפה היא רוצה להיות
קרא את היחידה האפקטיבית ולא את הקובץ שאתה חושב שמותקן, מפני שקבצי drop-in יכולים לעקוף את ספריית העבודה בלי שאי פעם תערוך את היחידה הראשית. פלט show עונה על השאלה ישירות:
systemctl cat [email protected]
systemctl show [email protected] -p WorkingDirectory -p RootDirectory -p User -p ProtectHome
journalctl -u [email protected] -b --no-pager | tail -30
בתבנית שרת ה-upstream, ספריית העבודה היא ספריית התצורה של השרת, שבה שם המופע בוחר את הפרופיל שבתוכה. מופע בשם branch מצפה אפוא לקובץ שלו באותה ספרייה, ופרופיל שהוצב במקום אחר אינו עומד כלל בדרישת ספריית העבודה.
השווה את מה שהיחידה דורשת למה שקיים. נתיב שהתקיים בעבר, קישור סמלי שמצביע כעת למקום אחר, או שם מופע שאינו תואם עוד לספרייה — כולם שינויים רגילים שמייצרים בדיוק את הכשל הזה.
בדוק את הנתיב כפי שהשירות רואה אותו
הקליפה שלך והשירות אינם חולקים את אותה תצוגה של מערכת הקבצים. ספריית שורש או תמונת שורש מוגדרות משנות את משמעותו של נתיב מוחלט בתוך היחידה, ונתיב שקיים בבירור במארח עשוי להיות חסר במרחב השמות הזה. קרא את הגדרות היחידה לפני שאתה סומך על בדיקה ידנית.
ההרשאות מחמירות את הבעיה. השירות רץ כמשתמש מסוים, ומשתמש זה חייב להיות מסוגל לעבור דרך כל ספריית אב כדי להגיע ליעד, ולא רק לקרוא את היעד עצמו. ספרייה שקריאה ל-root ואינה עבירה למשתמש השירות מייצרת כשל שנראה כמו נתיב חסר.
namei -l /etc/openvpn/server
systemctl show [email protected] -p ProtectSystem -p ReadOnlyPaths
גם הגדרות ההקשחה הן חלק מהתמונה. יחידה אשר מסתירה ספריות בית או הופכת חלק ממערכת הקבצים לקריאה בלבד עושה בדיוק את מה שהוגדר לה, וספריית העבודה חייבת לשבת במקום שארגז החול עדיין חושף אותו.
תקן את הבעלים, ואז צפה לשגיאה אחרת
תקן את הפריסה או את היחידה דרך מי שמחזיק בתצורה הזו. העברת פרופיל לספרייה המצופה היא תיקון לגיטימי כשהפריסה שגויה, אבל היא אינה מסבירה ספרייה שלא ניתן להיכנס אליה, לכן אל תתייחס אליה כתשובה הכללית.
התנגד לקיצור הדרך של הרחבת הרשאות על עץ התצורה או הסרת ארגז החול. שניהם מעלימים את הסימפטום ובמקביל מסירים את ההגנות שהוצבו שם במכוון, והכשל הבא יהיה קשה יותר לפרשנות.
הפעל מחדש את המופע וקרא את האירוע הבא במקום להניח הצלחה. השגיאה הבאה הסבירה היא ש-OpenVPN אינו יכול לפתוח את קובץ התצורה שלו, וזהו התקדמות: נכנסו לספריית העבודה והמנתח פועל כעת. משם עקוב אחר מיפוי הקבצים בפועל של היחידה במקום לחזור לפתרון בעיות רשת.
הפניה להרצה של systemd מגדירה כיצד ספריית העבודה מתפרשת יחד עם ספריות שורש וארגז חול. התבנית שכדאי לזכור פשוטה: כל קוד מצב מציין שלב אחר, ורק השגיאות של היישום עצמו מתארות את היישום.