کل ٹنل کام کر رہا تھا، اور آج صبح unit مردہ ہے، جرنل میں Failed at step EXEC spawning /usr/local/bin/vpnclient موجود ہے۔ اسناد، راستے اور اکاؤنٹ کبھی اس جملے میں نہیں آتے۔ systemd نے ExecStart کو راستے میں حل کیا، کرنل سے اسے چلانے کی درخواست کی، اور کرنل نے انکار کر دیا، زیادہ تر اس لیے کہ اس راستے پر کچھ نہیں ہے یا فائل چلانے کے قابل نہیں ہے۔ جب تک تجزیہ شدہ کمانڈ اس کے برعکس ثابت نہ کرے، اس خرابی کو فائل اور argv کا مسئلہ سمجھیں۔

تصدیق شروع ہونے سے پہلے EXEC کیوں ناکام ہوتا ہے

systemd ExecStart کو شیل کے ذریعے نہیں چلاتا۔ یہ fork کرتا ہے، لائن سے دلائل کا ویکٹر بناتا ہے اور پہلے عنصر پر execve کال کرتا ہے۔ اگر وہ کال ناکام ہو جائے تو سروس کبھی VPN کلائنٹ کے اپنے کوڈ تک نہیں پہنچتی، اس لیے پروفائل میں ترمیم یا اسناد کی جانچ مدد نہیں کر سکتی۔

اسٹیٹس کوڈ اس خاندان کو عام کریش سے الگ کرتا ہے۔ status=203/EXEC کے ساتھ باہر نکلنے والے unit نے کبھی عمل شروع نہیں کیا؛ جو unit شروع ہو کر پھر status=1 کے ساتھ باہر نکلے، وہ شاید تصدیق، 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 فیصلہ کن آؤٹ پٹ ہے، کیونکہ یہ وہ argv چھاپتا ہے جو systemd نے واقعی تجزیہ کیا، کسی بھی drop-in سمیت۔ systemd-analyze verify ری اسٹارٹ سے پہلے گمشدہ یا نہ چلنے والا راستہ پکڑ لیتا ہے، اور ری اسٹارٹ کے بعد status کمانڈ بتاتی ہے کہ عمل اب موجود ہے یا نہیں۔

اگر unit شروع ہو کر پھر ناکام ہو جائے تو آپ EXEC خاندان چھوڑ کر کلائنٹ کے اپنے خرابی کے انتظام میں داخل ہو گئے ہیں۔ جرنل میں کلائنٹ کا پیغام ڈھونڈیں، کوئی اور execve ناکامی نہیں۔ unit کا diff اور sudoers کا diff تبدیلی کے ریکارڈ میں ساتھ رکھیں، تاکہ اگلی اپ گریڈ تقسیم شدہ راستہ خاموشی سے واپس نہ لے آئے۔

متعلقہ مضامین