VPN सेवा EXEC वर अपयशी: unit, बाइनरी आणि sudoers यांची तुलना करा
EXEC टप्प्यावर अपयश म्हणजे systemd बाइनरी सुरू करू शकले नाही। काहीही बदलण्यापूर्वी unit चा मार्ग, इन्स्टॉल केलेला मार्ग आणि sudoers परवानगी यांची तुलना करा।
काल टनेल काम करत होते, आणि आज सकाळी unit मृत आहे, जर्नलमध्ये Failed at step EXEC spawning /usr/local/bin/vpnclient आहे। क्रेडेन्शियल्स, रूट आणि खाते कधीही त्या वाक्यात येत नाहीत। systemd ने ExecStart ला मार्ग म्हणून सोडवले, कर्नेलला तो चालवण्याची विनंती केली, आणि कर्नेलने नकार दिला, बहुतेक वेळा त्या मार्गावर काहीही नसल्यामुळे किंवा फाइल चालवण्यायोग्य नसल्यामुळे। विश्लेषित कमांड उलट सिद्ध करेपर्यंत या बिघाडाला फाइल आणि argv ची समस्या माना।
प्रमाणीकरण सुरू होण्यापूर्वीच EXEC का अपयशी होते
systemd ExecStart शेलमधून चालवत नाही। ते fork करते, ओळीतून आर्ग्युमेंट वेक्टर तयार करते आणि पहिल्या घटकावर execve कॉल करते। जर तो कॉल अपयशी झाला, तर सेवा कधीही VPN क्लायंटच्या स्वतःच्या कोडपर्यंत पोहोचत नाही, त्यामुळे प्रोफाइल संपादन किंवा क्रेडेन्शियल तपासणी उपयोगी पडत नाही।
स्थिती कोड हे कुटुंब सामान्य क्रॅशपासून वेगळे करतो। status=203/EXEC सह बाहेर पडणाऱ्या unit ने कधीही प्रक्रिया सुरू केली नाही; सुरू होऊन नंतर status=1 सह बाहेर पडणाऱ्या unit मध्ये प्रमाणीकरण, DNS किंवा राउटिंगमध्ये अपयश आले असेल। क्लायंट लॉग वाचण्यापूर्वी कोड वाचा, कारण पहिल्या प्रकरणात क्लायंट लॉग रिकामा असेल।
जर्नलमधील मार्ग हा systemd ने वापरलेला मार्ग आहे, तुम्ही संपादित केलेला मार्ग असावा असे नाही। Drop-in फाइल्स आणि जनरेटरचे आउटपुट व्हेंडरची फाइल बदलू शकतात, आणि जुना daemon-reload जुनी ओळ मेमरीत ठेवतो। म्हणून पहिले निदान म्हणजे तुम्हाला आठवणारी फाइल उघडण्याऐवजी systemd ला कमांड काय मानते हे विचारणे।
बाइनरीचा मार्ग लिहिला जाणारी तीन ठिकाणे
डिस्ट्रिब्युशन पॅकेज, व्हेंडर स्क्रिप्ट आणि रिलीज tarball मधून इन्स्टॉल केलेला VPN क्लायंट तीन वेगवेगळ्या प्रीफिक्समध्ये जाऊ शकतो। unit, विशेषाधिकार नियम आणि इन्स्टॉलर यांनी त्यातील प्रत्येकी एक प्रीफिक्स नोंदवला, आणि तीनपैकी दोन जुळले नाहीत तेव्हा बिघाड दिसतो।
| Record | Common value | How to read it |
|---|---|---|
| Unit or drop-in | /usr/local/bin/vpnclient | systemctl cat vpnclient.service |
| Installed binary | /usr/bin/vpnclient | command -v vpnclient, then ls -l the result |
| Sudoers grant | /opt/vpnclient/bin/vpnclient | sudo grep -r vpnclient /etc/sudoers.d/ |
ठोस फरक असा दिसतो: व्हेंडर स्क्रिप्ट /usr/local/bin मध्ये इन्स्टॉल करते, tarball /opt खाली उघडले गेले, आणि unit अजूनही मागील पॅकेजचा जुना /usr/bin मार्ग सांगते। त्या फाइल्सपैकी फक्त एक अस्तित्वात आहे, आणि ती क्वचितच ExecStart मधील फाइल असते।
कोणतीही फाइल बदलण्यापूर्वी कोणता मार्ग प्रमाणित आहे हे ठरवा। बाइनरी डिस्ट्रिब्युशन पॅकेजची असेल, तर पॅकेजचा मार्ग प्रमाणित आहे आणि unit ने त्याचे अनुसरण केले पाहिजे। व्हेंडर स्क्रिप्टची असेल, तर तोच नियम व्हेंडर प्रीफिक्सला लागू होतो। प्रीफिक्सदरम्यान बाइनरी कॉपी केल्यास दोन प्रती तयार होतात ज्या पुढील अपग्रेडमध्ये वेगळ्या होतात।
जेव्हा अवतरण चिन्हांतील कमांड फाइलचे नाव बनते
दुसरी बिघाड पद्धत त्याच जर्नल ओळीमागे लपलेली आहे। कोणी हे unit मध्ये लिहिते आणि बूट दरम्यान क्लायंट जोडला जाईल अशी अपेक्षा करते:
ExecStart=/usr/bin/"vpnclient connect office"systemd मूल्याचे शब्दांत विभाजन करते, त्यामुळे पहिला शब्द /usr/bin/vpnclient connect office होतो, आणि अवतरण चिन्हे गट करण्याची वाक्यरचना म्हणून काढली जातात। नंतर कर्नेल अशी फाइल शोधते जिच्या नावात मोकळ्या जागा आहेत, आणि अशी फाइल नाही। बाइनरी इन्स्टॉल असूनही त्रुटी गहाळ बाइनरीसारखीच आहे।
समर्थित स्वरूप म्हणजे खरी चालवण्यायोग्य फाइल, त्यानंतर स्वतंत्र आर्ग्युमेंट्स, उदाहरणार्थ ExecStart=/usr/bin/vpnclient connect office। कार्यप्रवाहाला खरोखर पाइपलाइन किंवा साखळी हवी असेल, तर ती स्क्रिप्टमध्ये ठेवा आणि स्क्रिप्टला कॉल करा, कारण ExecStart मध्ये && नाही, पाइप नाहीत आणि glob विस्तार नाही।
फाइलसिस्टम नाही, unit दुरुस्त करा
मोहक उपाय म्हणजे अपेक्षित मार्गापासून खऱ्या बाइनरीपर्यंतची सिम्बॉलिक लिंक। पॅकेज अपडेट होऊन लिंक काढलेल्या फाइलकडे निर्देश करेपर्यंत, किंवा SELinux लेबल लक्ष्याशी जुळत नाही तोपर्यंत ती चालते। unit drop-in द्वारे संपादित करणे बरे, म्हणजे व्हेंडरची फाइल अस्पर्श राहील आणि अपग्रेड अंदाजनीय राहतील।
विशेषाधिकार नियम त्याच मार्गाशी आणि त्याच उपकमांडशी जुळला पाहिजे। /usr/local/bin/vpnclient साठीची sudoers नोंद /usr/bin/vpnclient ला अधिकृत करत नाही, आणि प्रत्येक आर्ग्युमेंटला परवानगी देणारी नोंद कोणत्याही स्थानिक प्रक्रियेला टनेल पुन्हा संरचीत करण्याची किंवा थांबवण्याची परवानगी देते। unit ला आवश्यक असलेल्या दोन क्रिया द्या आणि सेवा थांबवल्याने इंटरफेस आधीच बंद होत असेल तर विसर्जन त्याबाहेर ठेवा।
इथेच तुलना फळ देते: unit, पॅकेज डेटाबेस आणि sudoers यांनी एकच मार्ग सांगितला पाहिजे। असे झाल्यास रीबूट न करता आणि तिसऱ्या ठिकाणी बाइनरीची प्रत न ठेवता EXEC त्रुटी नाहीशी होते।
रीबूटपूर्वी विश्लेषित कमांड सिद्ध करा
sudo systemctl daemon-reload
sudo systemctl cat vpnclient.service
systemctl show -p ExecStart vpnclient.service
systemd-analyze verify /etc/systemd/system/vpnclient.service
sudo systemctl restart vpnclient.service
systemctl status vpnclient.service --no-pagersystemctl show निर्णायक आउटपुट आहे, कारण ते systemd ने प्रत्यक्षात विश्लेषित केलेले argv, कोणत्याही drop-in सह छापते। systemd-analyze verify रीस्टार्टपूर्वी गहाळ किंवा न चालवता येणारा मार्ग पकडते, आणि रीस्टार्टनंतरचा status कमांड प्रक्रिया आता आहे का ते सांगतो।
unit सुरू होऊन नंतर अपयशी झाले, तर तुम्ही EXEC कुटुंब सोडून क्लायंटच्या स्वतःच्या त्रुटी हाताळणीत प्रवेश केला आहे। जर्नलमध्ये क्लायंटचा संदेश शोधा, आणखी एक execve अपयश नाही। unit चा diff आणि sudoers चा diff बदल नोंदीत एकत्र ठेवा, जेणेकरून पुढील अपग्रेड विभाजित मार्ग शांतपणे परत आणणार नाही।