ExecStart ไม่ใช่ shell: แก้ไขยูนิตตัวช่วย VPN
ExecStart รันโปรแกรมพร้อมอาร์กิวเมนต์ ไม่ใช่ไปป์ไลน์ของ shell ใช้อินเทอร์พรีเตอร์ที่ชัดเจนหรือสคริปต์จริง จากนั้นตรวจสอบยูนิตและอ่านเจอร์นัล
คัดลอกบรรทัดคำสั่งที่ใช้งานได้ลงใน ExecStart โหลดใหม่ แล้วยูนิตล้มเหลวหรือจบแบบเงียบ ๆ เพราะอาร์กิวเมนต์ถูกมองเป็นชื่อไฟล์ ไม่มีอะไรเสียใน systemd ExecStart เป็นรายการอาร์กิวเมนต์ ไม่ใช่ shell ดังนั้นไปป์ การเปลี่ยนเส้นทาง และเงื่อนไขจะหมดความหมายทันทีที่ออกจากเทอร์มินัลของคุณ ตัดสินใจว่า shell ควรอยู่ตรงไหน แล้วเขียนยูนิตที่ระบุชัดเจนว่าจะเรียกใช้อะไร
ทำไมไปป์ใน ExecStart ไม่ทำอะไรเลย
เมื่อพิมพ์คำสั่งในเทอร์มินัล shell จะแยกวิเคราะห์ก่อน มันสร้างไปป์ เปิดไฟล์สำหรับการเปลี่ยนเส้นทาง และขยายตัวแปรก่อนที่โปรแกรมใดจะเริ่ม systemd ไม่ทำสิ่งเหล่านั้นเลย: มันแบ่ง ExecStart ตามกฎของตัวเองและรันโปรแกรมที่ได้ด้วยอาร์กิวเมนต์เหล่านั้น ดังนั้น > จึงมาถึงในฐานะอาร์กิวเมนต์ตามตัวอักษร และ | ถูกส่งให้โปรแกรมแทนที่จะเชื่อมสองโปรเซส ยูนิตไม่ได้ทำงานผิด ไวยากรณ์หมายถึงสิ่งอื่น
นี่เป็นเจตนาไม่ใช่ความประมาท เพราะการจัดการอาร์กิวเมนต์ที่คาดเดาได้คือสิ่งที่ทำให้ยูนิตตรวจสอบได้ มันทำให้แปลกใจเฉพาะคนที่คิดว่ามี shell อยู่
เขียนยูนิตที่ระบุชัดเจนว่าอะไรรันอยู่
เริ่มจากยูนิตเล็ก ๆ ที่เห็นจุดประสงค์ได้ในเจอร์นัล เพื่อให้ปัญหาการแยกวิเคราะห์แยกจากปัญหาอุโมงค์ ตัวนี้รายงานเฉพาะเวอร์ชันของไบนารี
[Unit]
Description=Report the installed OpenVPN version
[Service]
Type=oneshot
ExecStart=/usr/sbin/openvpn --version
StandardOutput=journal
StandardError=journalพาธเป็นตัวยึดตำแหน่ง ดังนั้นแทนที่ด้วยไบนารีที่ติดตั้งจริง Type=oneshot เหมาะกับคำสั่งที่รันจนจบ และการตั้งค่าเจอร์นัลวางเอาต์พุตไว้ในที่ที่อ่านได้โดยไม่ต้องมีเทอร์มินัล ตั้งใจไม่มีส่วนติดตั้ง ดังนั้นยูนิตจึงถูกเรียกด้วยมือแทนที่จะเปิดใช้ตอนบูต ตรวจสอบไฟล์ก่อนเริ่ม เพราะการพิมพ์ผิดในชื่อไดเรกทีฟล้มเหลวต่างจากการพิมพ์ผิดในพาธ
systemd-analyze verify /etc/systemd/system/openvpn-version.service
systemctl start openvpn-version.serviceเก็บตรรกะของ shell ไว้ในสคริปต์
เมื่อตัวช่วยต้องการตรรกะแบบมีเงื่อนไขจริง ๆ ให้ใส่ตรรกะนั้นในสคริปต์และเรียกอย่างชัดเจน สคริปต์ต้องมีบรรทัดอินเทอร์พรีเตอร์ สิทธิ์ในการรัน และรหัสออกที่บริการรายงานได้ /bin/sh -c ด้วยคำสั่งที่ใส่เครื่องหมายคำพูดนั้นได้ผล แต่มันซ่อนกฎการใส่เครื่องหมายคำพูดไว้ในยูนิตและทำให้ตรวจทานยากขึ้น สคริปต์ที่ตั้งชื่อไว้สามารถทดสอบด้วยมือและแทนที่ได้ในภายหลังโดยไม่ต้องแก้ยูนิต อย่าพึ่งโปรไฟล์ shell ของผู้ใช้แบบอินเทอร์แอกทีฟ เพราะบริการเริ่มด้วยสภาพแวดล้อมของตัวเอง
เมื่อพาธสัมพัทธ์สำคัญ WorkingDirectory ตั้งค่า และส่งสภาพแวดล้อมผ่านไดเรกทีฟที่ยูนิตสนับสนุนแทนการ export ในเทอร์มินัล ความลับอยู่ในไฟล์ที่ป้องกันหรือข้อมูลรับรอง ไม่ใช่ในรายการอาร์กิวเมนต์ที่เจอร์นัลอาจบันทึก
ตรวจสอบยูนิตที่มีอยู่จริง
ไฟล์ drop-in เปลี่ยนพฤติกรรมโดยไม่แตะไฟล์ที่คุณจำได้ว่าแก้ไข อ่านสิ่งที่ผู้จัดการโหลดและสิ่งที่การรันครั้งล่าสุดรายงาน
systemctl cat vpn-helper.service
journalctl -u vpn-helper.service -n 20 --no-pagerการดัมป์ยูนิตมีไฟล์ drop-in ตามลำดับการโหลด และนั่นคือที่มาของ ExecStart ที่ไม่คาดคิดบ่อยครั้ง หลังจากเปลี่ยนแปลงใด ๆ ให้โหลดผู้จัดการใหม่และยืนยันว่าคำนิยามใหม่คือสิ่งที่ systemctl cat พิมพ์ออกมา เจอร์นัลแสดงบรรทัดคำสั่งและสถานะออกที่แน่นอน ซึ่งแยกปัญหาอาร์กิวเมนต์ออกจากไบนารีที่หายไปหรือข้อผิดพลาดด้านสิทธิ์ จากนั้นตัดสินใจว่าตัวช่วยเป็นส่วนหนึ่งของวงจรชีวิต VPN ที่มีอยู่หรือควรเป็นการวินิจฉัยด้วยมือ เพราะโปรเซสอุโมงค์เบื้องหลังตัวที่สองสร้างเจ้าของที่แข่งขันกัน
ยูนิตที่พิมพ์เอาต์พุตถูกต้องเมื่อร้องขอเป็นหมุดหมายแรกที่ดี มันยังไม่ใช่อุโมงค์ และไม่ควรแสร้งว่าเป็น