ארבעים קובצי .ovpn עבור מדינה אחת מגיעים מספק, והתוכנית נראית מובנת מאליה: להעתיק אחד באקראי למקומו, ואז להפעיל את המנהרה. כשהיא נכתבת כצינור בתוך ExecStart, התוכנית הזו מתה בעת האתחול עם קוד סטטוס שלא מסביר דבר. קובץ היחידה אינו סקריפט, והתיקון הוא או להביא מעטפת באופן מפורש או להפסיק לגמרי לבחור קבצים.

התסמין: יחידה שעולה ומתה מיד

הסטטוס מראה שהשירות נכשל בשבריר שנייה, ושורת היומן מציינת פקודה שאף מעטפת לא הייתה מקבלת אותה אי פעם. דבר על המנהרה אינו מופיע, כי המנהרה מעולם לא החלה.

קריאת שורת הפקודה המדויקת מהיומן היא הדרך המהירה ביותר לאשר זאת. systemd משקף את מה שהפעיל, והמחרוזת תציג את תווי הצינור כארגומנטים מילוליים ולא כאופרטורים.

מדוע ExecStart אינו יכול להריץ צינור

systemd מפצל בעצמו את שורת הפקודה, מחיל את כללי הציטוט והחלפת המשתנים שלו, ואז מריץ את התוצאה ישירות. צינורות, הפניה מחדש, הרחבת תבניות על ידי מעטפת והחלפת פקודות פשוט אינם חלק מהדקדוק הזה. זו בחירת תכנון ולא השמטה: יחידה אומרת באופן הצהרתי מה להריץ, והלוגיקה של המעטפת שייכת לסקריפט שהיחידה קוראת לו. שני התיקונים נובעים מכך, ואף אחד מהם אינו דורש לתת ליחידה הרשאות נוספות.

זה גם מסביר את קוד היציאה המטעה. הארגומנט הראשון נתפס כקובץ הבינארי, ולכן שורה פגומה נכשלת לפני שחלק כלשהו מהלוגיקה שלכם רץ.

בצעו את הבחירה ב-ExecStartPre

התיקון הישיר הוא שלב הכנה שקורא למעטפת באופן מפורש, ושומר על הבחירה וההפעלה באותה יחידה כך שכשל באחד לא יותיר את השני פועל לבדו.

[Service]
Type=notify
ExecStartPre=/bin/bash -c "ls /etc/openvpn/profiles/au* | shuf -n 1 | xargs -r -I{} cp -f {} /etc/openvpn/%i.conf"
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf

שלושה פרטים מכריעים אם זה שורד מפגש עם מכונה אמיתית. השמות הם המלכודת הראשונה: systemd מחליף את %i כבר בשלב ניתוח היחידה, הרבה לפני ש-bash רץ, ולכן המזהה חייב לעמוד מחוץ למירכאות בודדות. xargs -r מונע מ-cp לרוץ בלי ארגומנט כשהתבנית אינה תואמת דבר. ושלב הכנה שנכשל עוצר את היחידה, וזו התוצאה הנכונה: התחלה עם התצורה של אתמול גרועה מאי-התחלה. בחירה אקראית שלוקחת תמיד את אותו קובץ היא בדרך כלל לא מזל רע. בדקו אם הקובץ המועתק נדרס על ידי עדכון חבילה, או אם התבנית תואמת רשומה מיושנת אחת בלבד.

או הניחו ל-OpenVPN לבחור את נקודת הקצה

OpenVPN כבר יכולה להחזיק כמה נקודות קצה בפרופיל אחד ולבחור ביניהן באקראי, מה שמסיר לגמרי את המעטפת, את ההעתקה ואת הרשאת הכתיבה מנתיב האתחול.

client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>

הצורה הזו שומרת את בחירת השרת בתוך הקובץ שהספק כתב, ולכן סיבוב שמשנה שמות קבצים אינו שובר את היחידה. היא גם הופכת את רשימת המועמדים לניתנת לביקורת, מה שתבנית על תיקייה אף פעם אינה. הערבוב עדיין ראוי למקומו כשפרופילים נבדלים ביותר מנקודת קצה: תעודות שונות, הנחיות ניתוב שונות, מדיניות הצפנה שונה. במקרה כזה הבחירה היא בין תצורות שלמות ושלב מעטפת הוא הדרך הכנה לבטא זאת.

קראו בחזרה את היחידה ואת הקובץ שבו השתמשה

ודאו איזו יחידה באמת פועלת לפני שאתם מאתרים תקלות בתוכן שלה. שירות המטא הארוז והתבנית הם תשתית; היחידות שמתאימות לקבצים שלכם הן המופעים הנקראים על שמם.

systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager

מופע שאיש אינו זוכר שהפעיל בדרך כלל מוביל לקובץ תצורה תועה בתיקיית החבילה. כבו את המופע הנקרא הזה ולא את התבנית, אחרת עדכון החבילה הבא יחזיר אותו. לאחר השינוי, הפעילו את היחידה וקראו את שורת הפקודה שהיומן מדווח עליה, ואז ודאו את נתיב התצורה שהיא באמת פתחה. הבדיקה האחת הזו מפרידה בין בחירה אקראית שעובדת לבין שירות שממחזר בשקט קובץ מהחודש שעבר.

מאמרים קשורים