OpenVPN شیل میں چلتا ہے مگر cron کے تحت ناکام ہوتا ہے: مسئلہ PATH ہے
شیل سے جڑنے والا کمانڈ ٹنل شروع ہونے سے پہلے ہی cron یا subprocess کے تحت ناکام ہو سکتا ہے۔ راستہ، کام کی ڈائریکٹری اور ٹرمینل درست کریں۔
وہی کمانڈ شیل سے جڑتا ہے اور cron کے تحت مر جاتا ہے، اس لیے فطری نتیجہ یہ ہے کہ ٹنل یا سرٹیفکیٹ قصوروار ہے۔ اس پر یقین کرنے سے پہلے دیکھیں کہ دونوں رن میں کیا مشترک ہے: بائنری، کنفیگریشن اور اسناد یکساں ہیں، اور صرف عمل کا ماحول بدلا ہے۔ جب پروگرام ہی نہ ملے تو TLS ڈیبگنگ کی کوئی مقدار مدد نہیں کرتی۔ درستی عام طور پر راستے، کام کی ڈائریکٹری اور مٹھی بھر ماحولی متغیرات میں ہوتی ہے، VPN میں نہیں۔
جو شیل کام کرتا ہے اس میں command -v openvpn جواب چھاپتا ہے، اور یہ اکثر /usr/sbin/openvpn ہوتا ہے، یعنی ایسی ڈائریکٹری جسے cron اپنے تلاش کے راستے میں نہیں رکھتا۔
ٹنل کبھی شروع ہی نہیں ہوا، اس لیے ٹنل مسئلہ نہیں
cron کی شروع کی ہوئی نوکریاں کم سے کم ماحول ورثے میں لیتی ہیں، روایتی طور پر PATH=/usr/bin:/bin، اور کوئی کنٹرول ٹرمینل نہیں لیتیں۔ /usr/sbin یا /usr/local/sbin میں نصب کوئی بھی چیز اس فہرست سے سیدھی غائب ہوتی ہے، اور لاگ کی سطر TLS خرابی کے بجائے openvpn: not found پڑھتی ہے۔ Python کا subprocess مختلف طریقے سے ناکام ہوتا ہے: یہ مترجم کے عمل کا ماحول ورثے میں لیتا ہے، جو cron سے زیادہ بھرپور ہو سکتا ہے مگر ٹلڈا پھیلانے کے لیے اب بھی کوئی شیل نہیں۔ دونوں ناکامیاں ایک بھی پیکٹ میزبان چھوڑنے سے پہلے ہوتی ہیں۔
انہیں الگ پہچاننے کا تیز طریقہ آخری کے بجائے پہلی خرابی پڑھنا ہے۔ غائب بائنری شیل یا Python استثنا پیدا کرتی ہے، خراب کنفیگریشن OpenVPN کا استعمال پیغام پیدا کرتی ہے، اور حقیقی ہینڈ شیک ناکامی وقت کے مہر اور ساتھی پتے پیدا کرتی ہے۔ صرف تیسرا ہی ٹنل کا مسئلہ ہے۔
مطلق راستے اور دلائل کی فہرستیں شیل کی تاروں کو ہرا دیتی ہیں
حل شدہ راستہ واضح طور پر دیں اور شیل کو مکمل طور پر چھوڑ دیں۔ subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) آپ کو واپسی کوڈ، stdout اور stderr دیتا ہے، شیل سے فائل کا نام سمجھانے کو کہے بغیر۔ کنفیگریشن کا راستہ os.environ["HOME"] یا pathlib.Path.home() سے بنائیں، تاکہ ٹلڈا کبھی پھیلانا نہ پڑے۔ جب واقعی شیل نحو درکار ہو، shlex.split استعمال کریں، کیونکہ .split() سے تار تقسیم کرنا خالی جگہ والے کسی بھی راستے پر ٹوٹ جاتا ہے۔ stderr بھی پڑھیں، کیونکہ OpenVPN اپنی بیشتر ابتدائی ناکامیاں وہیں لکھتا ہے۔
یہی اصول cron پر بھی لاگو ہے: نوکری کی سطر لاگ ان شیل نہیں ہے، اس لیے کوئی چیز آپ کی پروفائل لوڈ نہیں کرتی اور کوئی چیز آپ کے عرفی نام متعین نہیں کرتی۔
crontab اصل میں کیا ورثے میں لیتا ہے
crontab اندراج کو وہ ماحول ملتا ہے جو crontab اعلان کرتا ہے اور کچھ ورثے میں ملے ڈیفالٹ، اس لیے راستہ پورا لکھیں یا کال کو ایسی اسکرپٹ میں لپیٹیں جو یہ کرتی ہو۔ فائل کے اوپر PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin جیسی سطر عام تنصیبی مقامات کو ڈھانپ لیتی ہے، اور >> cron.log 2>&1 کے ساتھ ری ڈائریکٹ کرنا ہی اگلی ناکامی کو پڑھنے کے قابل بناتا ہے۔ پاس فریز سے محفوظ پروفائل کے پاس cron کے تحت اپنا راز مانگنے کا کوئی طریقہ نہیں، کیونکہ پوچھنے کے لیے کوئی ٹرمینل نہیں۔ ایسا کنکشن systemd یونٹ میں ہونا چاہیے جو اسناد کی فائل پڑھ سکے، ایسی نوکری میں نہیں جو خود کو متعامل ظاہر کرے۔
نسبتی راستے دوسرا جال ہیں۔ ٹیسٹ رن اکثر اس فولڈر سے ہوتا ہے جس میں پروفائل ہے، اور cron نوکری بالکل کہیں اور شروع ہوتی ہے، اس لیے --config office.ovpn ایسی فائل میں حل ہوتا ہے جو وہاں نہیں اور پیغام غائب ٹنل کے بجائے غائب فائل کے طور پر پڑھا جاتا ہے۔
ماحول ہٹا کر اسے ثابت کریں
کم سے کم ماحول براہ راست دوبارہ پیدا کریں: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4۔ اس رن سے راستے یا ٹرمینل کی شکایت کا مطلب ہے کہ مسئلہ VPN کے اوپر ہے۔ اگر یہ جڑ جائے تو باقی مشتبہ وہ اکاؤنٹ جس کے تحت یہ چلتا ہے، وہ ڈائریکٹری جہاں سے شروع ہوتا ہے، اور وہ اسناد جو پیش کرتا ہے۔ دونوں نتائج میں سے کوئی بھی سرٹیفکیٹ جانچ کے ایک اور دور سے بہتر ہے۔
پھر ریپر کو خود رپورٹ کرنے والا بنائیں۔ جس مرحلے تک پہنچا اس کے لیے الگ حیثیت کے ساتھ باہر نکلیں، دونوں اسٹریم وقت کے مہر کے ساتھ لاگ کریں، اور اگلی ناکامی بتائے گی کہ یہ راستہ حل کرنے میں، تصدیق میں، یا ٹنل پہلے ہی اوپر ہونے کے بعد مرا۔
یونٹ کو درست ترتیب بھی درکار ہے: Wants=network-online.target کے ساتھ After=network-online.target کلائنٹ کو پتہ یا ڈیفالٹ روٹ بننے سے پہلے شروع ہونے سے روکتے ہیں، جو بصورت دیگر سرٹیفکیٹ یا TLS خرابیوں کے طور پر سامنے آتا ہے اور ہاتھ سے دوبارہ شروع کرنے پر غائب ہو جاتا ہے۔