انتخاب تصادفی OpenVPN در systemd: چرا ExecStart شکست میخورد
systemd پوسته نیست، بنابراین یک نسخه درهمشده درون ExecStart میمیرد. انتخاب را به ExecStartPre منتقل کنید یا بگذارید OpenVPN خودش سرور را برگزیند.
چهل فایل .ovpn برای یک کشور از یک ارائهدهنده میرسد و برنامه بدیهی به نظر میرسد: یک فایل تصادفی را سر جایش کپی کنید و بعد تونل را راه بیندازید. اگر به شکل خط لوله درون ExecStart نوشته شود، آن برنامه هنگام بوت با کدی وضعیت میمیرد که هیچ چیز را توضیح نمیدهد. فایل یونیت اسکریپت نیست و راهحل یا آوردن صریح یک پوسته است یا دست کشیدن کامل از انتخاب فایل.
نشانه: یونیتی که شروع میشود و بیدرنگ میمیرد
وضعیت نشان میدهد که سرویس در کسری از ثانیه شکست خورده است و خط ژورنال فرمانی را نام میبرد که هیچ پوستهای هرگز دریافت نمیکرد. هیچ چیز درباره تونل ظاهر نمیشود، چون تونل هرگز آغاز نشد.
خواندن خط فرمان دقیق از ژورنال سریعترین راه برای تأیید این است. systemd آنچه را اجرا کرده بازتاب میدهد و رشته، نویسههای خط لوله را بهعنوان آرگومانهای تحتاللفظی نشان میدهد نه عملگرها.
چرا ExecStart نمیتواند خط لوله را اجرا کند
systemd خودش خط فرمان را تقسیم میکند، نقلقول و جایگذاری متغیرهای خودش را اعمال میکند و سپس نتیجه را مستقیم اجرا میکند. خطوط لوله، تغییر مسیر، گسترش الگوی پوسته و جایگذاری فرمان بهسادگی بخشی از این دستور زبان نیستند. این یک انتخاب طراحی است نه یک از قلم افتادگی: یونیت بهصورت اعلانی میگوید چه چیزی اجرا شود و منطق پوسته به اسکریپتی تعلق دارد که یونیت آن را فراخوانی میکند. هر دو راهحل از همینجا میآیند و هیچکدام نیازمند دادن امتیاز بیشتر به یونیت نیست.
این کد خروج گمراهکننده را هم توضیح میدهد. نخستین آرگومان بهعنوان فایل دودویی در نظر گرفته میشود، پس یک خط بدشکل پیش از اجرای هر بخشی از منطق شما شکست میخورد.
انتخاب را در ExecStartPre انجام دهید
راهحل مستقیم یک گام آمادهسازی است که صریحاً یک پوسته را فراخوانی میکند و انتخاب و شروع را در همان یونیت نگه میدارد تا شکست در یکی، دیگری را تنها رها نکند.
[Service]
Type=notify
ExecStartPre=/bin/bash -c "ls /etc/openvpn/profiles/au* | shuf -n 1 | xargs -r -I{} cp -f {} /etc/openvpn/%i.conf"
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf
سه جزئیات تعیین میکند که این در برخورد با یک ماشین واقعی دوام میآورد یا نه. نامگذاری نخستین تله است: systemd در هنگام تجزیه یونیت، مدتها پیش از اجرای bash، %i را جایگذاری میکند، پس مشخصکننده باید بیرون از نقلقول تکی بماند. xargs -r مانع از آن میشود که cp بدون آرگومان اجرا شود وقتی الگو با هیچ چیز مطابقت ندارد. و یک گام آمادهسازی ناموفق یونیت را متوقف میکند و این نتیجه درست است: شروع با پیکربندی دیروز بدتر از شروع نکردن است. انتخاب تصادفیای که همیشه همان فایل را میگیرد معمولاً بدشانسی نیست. بررسی کنید که آیا فایل کپیشده با بهروزرسانی بسته بازنویسی میشود یا آیا الگو تنها با یک ورودی کهنه مطابقت دارد.
یا بگذارید OpenVPN نقطه پایانی را انتخاب کند
OpenVPN از قبل میتواند چند نقطه پایانی را در یک پروفایل نگه دارد و تصادفی از میان آنها انتخاب کند، که پوسته، کپی و دسترسی نوشتن را کاملاً از مسیر بوت حذف میکند.
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
این شکل انتخاب سرور را درون فایلی نگه میدارد که ارائهدهنده نوشته است، پس چرخشی که فایلها را تغییر نام میدهد یونیت را نمیشکند. همچنین فهرست نامزدها را قابل بازبینی میکند، چیزی که الگو روی یک پوشه هرگز نیست. درهمآمیختن هنوز جای خود را دارد وقتی پروفایلها بیش از یک نقطه پایانی تفاوت دارند: گواهیهای متفاوت، دستورهای مسیریابی متفاوت، سیاست رمزنگاری متفاوت. در آن حالت انتخاب میان پیکربندیهای کامل است و یک گام پوسته شیوه صادقانه بیان آن است.
نمونه و فایلی را که به کار برد دوباره بخوانید
پیش از اشکالزدایی محتوای یونیت، تأیید کنید که کدام یونیت واقعاً اجرا میشود. سرویس متای بستهبندیشده و قالب، زیرساختاند؛ یونیتهایی که با فایلهای شما متناظرند همان نمونههایی هستند که به نام آنها نامگذاری شدهاند.
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
نمونهای که هیچکس به یاد ندارد فعالش کرده باشد معمولاً به یک فایل پیکربندی سرگردان در پوشه بسته بازمیگردد. همان نمونه نامدار را خاموش کنید نه قالب را، وگرنه بهروزرسانی بعدی بسته آن را برمیگرداند. پس از تغییر، یونیت را شروع کنید و خط فرمانی را که ژورنال گزارش میدهد بخوانید، سپس مسیر پیکربندیای را که واقعاً باز کرده تأیید کنید. همان یک بررسی، یک انتخاب تصادفی کارآمد را از سرویسی جدا میکند که بیصدا فایلی از ماه گذشته را دوباره به کار میبرد.