हिजो टनेल काम गरिरहेको थियो, र आज बिहान 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, विशेषाधिकार नियम र इन्स्टलरले तीमध्ये एक-एक प्रिफिक्स रेकर्ड गरेका थिए, र तीनमध्ये दुई नमिल्दा त्रुटि देखिन्छ।

RecordCommon valueHow to read it
Unit or drop-in/usr/local/bin/vpnclientsystemctl cat vpnclient.service
Installed binary/usr/bin/vpnclientcommand -v vpnclient, then ls -l the result
Sudoers grant/opt/vpnclient/bin/vpnclientsudo 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-pager

systemctl show निर्णायक आउटपुट हो, किनकि यसले systemd ले वास्तवमै विश्लेषण गरेको argv, कुनै पनि drop-in सहित छाप्छ। systemd-analyze verify रिस्टार्ट अघि हराएको वा नचल्ने बाटो पक्रन्छ, र रिस्टार्टपछिको status आदेशले प्रक्रिया अहिले छ कि छैन भन्छ।

यदि unit सुरु भएर पछि असफल भयो भने, तपाईंले EXEC परिवार छोडेर क्लाइन्टको आफ्नै त्रुटि व्यवस्थापनमा प्रवेश गर्नुभएको छ। जर्नलमा क्लाइन्टको सन्देश खोज्नुहोस्, अर्को execve असफलता होइन। unit को diff र sudoers को diff परिवर्तन रेकर्डमा सँगै राख्नुहोस्, ताकि अर्को अपग्रेडले विभाजित बाटो चुपचाप फर्काउने छैन।

सम्बन्धित लेखहरू