บริการล้มเหลว บันทึกเอ่ยถึง spawn และไดเรกทอรี และปฏิกิริยาแรกคือตรวจการตั้งค่า VPN ทั้งที่ยังไม่มีอะไรถูกอ่านจากไฟล์นั้นเลย systemd ล้มเหลวขณะเตรียมโปรเซส ก่อนที่ไฟล์ปฏิบัติการจะเริ่มทำงาน จึงไม่มี parser ไม่มีใบรับรอง และไม่มีโฮสต์ระยะไกลถูกสอบถาม การอ่านรหัสสถานะเป็นข้อความเกี่ยวกับ systemd ไม่ใช่เกี่ยวกับ OpenVPN คือสิ่งที่ทำให้เรื่องนี้กลายเป็นการสอบสวนสั้น ๆ

อ่านรหัสสถานะก่อนแอปพลิเคชัน

รหัสตัวเลขหลังชื่อบริการระบุขั้นตอนที่ล้มเหลว ความล้มเหลวของไดเรกทอรีถูกรายงานเป็นสถานะ CHDIR ขณะที่ไฟล์ปฏิบัติการที่รันไม่ได้เป็นรหัสอีกชุดหนึ่งโดยสิ้นเชิง ทั้งสองดูคล้ายกันในบรรทัดสรุปและไม่มีอะไรเหมือนกันในสาเหตุ

ความแตกต่างนี้สำคัญเพราะจุดแก้อยู่คนละไฟล์ ความล้มเหลว CHDIR เกี่ยวกับเส้นทางและมุมมองของบริการต่อเส้นทางนั้น ความล้มเหลว exec เกี่ยวกับไบนารี ตัวแปลภาษา หรือเมานต์ที่ไม่เกี่ยวข้อง การเปลี่ยนรีโมต VPN รายการรหัสลับ หรือเส้นทางใบรับรองไม่สามารถแก้ทั้งสองอย่างได้

ยืนยันว่าความล้มเหลวเกิดตอนเริ่ม ไม่ใช่หลังการทำงานที่สำเร็จ หากบริการทำงานได้เมื่อวานและตอนนี้ล้มเหลวในขั้นเดียวกัน แสดงว่ามีบางอย่างเปลี่ยนในไดเรกทอรี สิทธิ์ของมัน หรือ unit เอง และการเปลี่ยนแปลงนั้นคือหลักฐานที่ต้องค้นหา

ถาม unit ว่าอยากอยู่ที่ไหน

อ่าน unit ที่มีผลจริง ไม่ใช่ไฟล์ที่คุณคิดว่าติดตั้งอยู่ เพราะ drop-in สามารถเขียนทับไดเรกทอรีทำงานได้โดยที่คุณไม่เคยแก้ unit หลัก เอาต์พุตของ 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 จึงคาดหวังไฟล์ของตัวเองในไดเรกทอรีเดียวกัน และโปรไฟล์ที่วางไว้ที่อื่นไม่ตรงตามข้อกำหนดไดเรกทอรีทำงานเลย

เทียบสิ่งที่ unit ต้องการกับสิ่งที่มีอยู่ เส้นทางที่เคยมีอยู่ ลิงก์สัญลักษณ์ที่ชี้ไปที่อื่นแล้ว หรือชื่ออินสแตนซ์ที่ไม่ตรงกับไดเรกทอรีอีกต่อไป ล้วนเป็นการเปลี่ยนแปลงธรรมดาที่ก่อให้เกิดความล้มเหลวนี้

ตรวจเส้นทางตามที่บริการมองเห็น

เชลล์ของคุณกับบริการไม่ได้ใช้มุมมองระบบไฟล์เดียวกัน ไดเรกทอรีรากหรือ root image ที่ตั้งค่าไว้เปลี่ยนความหมายของเส้นทางสัมบูรณ์ภายใน unit และเส้นทางที่เห็นชัดบนโฮสต์อาจไม่มีอยู่ในเนมสเปซนั้น อ่านการตั้งค่าของ unit ก่อนเชื่อการทดสอบด้วยมือ

สิทธิ์ทำให้ปัญหารุนแรงขึ้น บริการรันในฐานะผู้ใช้ที่ระบุ และผู้ใช้นั้นต้องผ่านไดเรกทอรีแม่ทุกชั้นเพื่อไปถึงเป้าหมาย ไม่ใช่แค่อ่านเป้าหมายเอง ไดเรกทอรีที่ root อ่านได้แต่ผู้ใช้ของบริการผ่านไม่ได้ทำให้เกิดความล้มเหลวที่ดูเหมือนเส้นทางหายไป

namei -l /etc/openvpn/server
systemctl show [email protected] -p ProtectSystem -p ReadOnlyPaths

การตั้งค่าการเสริมความแข็งแรงก็เป็นส่วนหนึ่งของภาพนี้ unit ที่ ซ่อนไดเรกทอรีโฮมหรือทำให้ส่วนหนึ่งของระบบไฟล์อ่านได้อย่างเดียว ทำตามที่ถูกตั้งค่าไว้ และไดเรกทอรีทำงานต้องอยู่ในที่ที่ sandbox ยังเปิดเผยอยู่

แก้เจ้าของ แล้วคาดหวังข้อผิดพลาดอื่น

แก้เลย์เอาต์หรือ unit ผ่านผู้ที่เป็นเจ้าของการตั้งค่านั้น การย้ายโปรไฟล์ไปยังไดเรกทอรีที่คาดหวังเป็นการแก้ที่ชอบธรรมเมื่อเลย์เอาต์ผิด แต่ไม่ได้อธิบายไดเรกทอรีที่เข้าไม่ได้ จึงไม่ควรถือเป็นคำตอบทั่วไป

อย่าหลงทางลัดด้วยการขยายสิทธิ์บนต้นไม้การตั้งค่าหรือถอด sandbox ทั้งสองทำให้อาการหายไปพร้อมกับถอดการป้องกันที่ตั้งใจวางไว้ และความล้มเหลวครั้งหน้าจะตีความได้ยากขึ้น

รีสตาร์ทอินสแตนซ์และอ่านเหตุการณ์ถัดไปแทนการถือว่าสำเร็จ ข้อผิดพลาดถัดไปที่น่าจะเกิดคือ OpenVPN เปิดไฟล์การตั้งค่าของตัวเองไม่ได้ ซึ่งเป็นความคืบหน้า เพราะเข้าไดเรกทอรีทำงานได้แล้วและ parser กำลังทำงาน จากตรงนั้นให้ตามการแมปไฟล์จริงของ unit อย่ากลับไปแก้ปัญหาเครือข่าย

เอกสารอ้างอิงการทำงานของ systemd กำหนดว่าไดเรกทอรีทำงานถูกตีความร่วมกับไดเรกทอรีรากและ sandbox อย่างไร รูปแบบที่ควรจำนั้นง่าย แต่ละรหัสสถานะระบุขั้นตอนที่ต่างกัน และมีเพียงข้อผิดพลาดของแอปพลิเคชันเองที่อธิบายแอปพลิเคชัน

บทความที่เกี่ยวข้อง