একটি কাজ করা কমান্ড লাইন ExecStart-এ কপি করুন, রিলোড করুন, আর ইউনিটটি ব্যর্থ হয় বা নিঃশব্দে বেরিয়ে যায়, আর্গুমেন্টগুলোকে ফাইলের নাম হিসেবে ধরে নিয়ে। systemd-এ কিছুই ভাঙা নেই। ExecStart একটি আর্গুমেন্ট তালিকা, shell নয়, তাই পাইপ, রিডাইরেকশন ও শর্ত আপনার টার্মিনাল ছাড়ার মুহূর্তেই অর্থ হারায়। shell কোথায় থাকবে তা ঠিক করুন, তারপর এমন ইউনিট লিখুন যা ঠিক কী চালাবে তা বলে।

কেন ExecStart-এ পাইপলাইন কিছুই করে না

টার্মিনালে কমান্ড টাইপ করা হলে shell প্রথমে তা পার্স করে। এটি পাইপলাইন গড়ে, রিডাইরেকশনের জন্য ফাইল খোলে এবং কোনো প্রোগ্রাম শুরুর আগেই ভেরিয়েবল সম্প্রসারিত করে। systemd এর কিছুই করে না: এটি নিজের নিয়মে ExecStart ভাগ করে এবং ফলস্বরূপ প্রোগ্রামটি সেই আর্গুমেন্টসহ চালায়। তাই > আক্ষরিক আর্গুমেন্ট হিসেবে আসে, আর | দুই প্রক্রিয়াকে যুক্ত করার বদলে প্রোগ্রামের কাছে দেওয়া হয়। ইউনিট ভুল আচরণ করছে না; সিনট্যাক্সটি অন্য কিছু বোঝাচ্ছিল।

এটি অসতর্কতা নয়, ইচ্ছাকৃত, কারণ আর্গুমেন্টের পূর্বানুমেয় ব্যবহারই ইউনিটগুলোকে নিরীক্ষণযোগ্য করে। এটি কেবল তাদের অবাক করে যারা ধরে নেয় shell উপস্থিত আছে।

এমন ইউনিট লিখুন যা ঠিক কী চলে তা বলে

ছোট একটি ইউনিট দিয়ে শুরু করুন যার উদ্দেশ্য জার্নালে দেখা যায়, যাতে পার্সিং সমস্যা টানেল সমস্যা থেকে আলাদা থাকে। এটি কেবল একটি বাইনারির সংস্করণ জানায়।

[Unit]
Description=Report the installed OpenVPN version

[Service]
Type=oneshot
ExecStart=/usr/sbin/openvpn --version
StandardOutput=journal
StandardError=journal

পথটি একটি প্লেসহোল্ডার, তাই প্রকৃতপক্ষে ইনস্টল করা বাইনারি বসান। Type=oneshot এমন কমান্ডের জন্য উপযুক্ত যা শেষ পর্যন্ত চলে, আর জার্নাল সেটিংস এর আউটপুট সেখানে রাখে যেখানে টার্মিনাল ছাড়াই পড়া যায়। ইচ্ছাকৃতভাবে কোনো ইনস্টল বিভাগ নেই, তাই ইউনিট বুটে চালু হওয়ার বদলে হাতে ডাকা হয়। চালু করার আগে ফাইলটি যাচাই করুন, কারণ ডিরেক্টিভের নামে টাইপো পথের টাইপোর চেয়ে ভিন্নভাবে ব্যর্থ হয়।

systemd-analyze verify /etc/systemd/system/openvpn-version.service
systemctl start openvpn-version.service

shell লজিক স্ক্রিপ্টে রাখুন

হেল্পারের সত্যিই শর্তসাপেক্ষ লজিক দরকার হলে সেই লজিক একটি স্ক্রিপ্টে রাখুন এবং স্পষ্টভাবে ডাকুন। স্ক্রিপ্টের দরকার একটি ইন্টারপ্রেটার লাইন, চালানোর অনুমতি এবং এমন এক্সিট কোড যা সার্ভিস জানাতে পারে। /bin/sh -c কোটেড কমান্ডসহ চালানো সত্যিই কাজ করে, কিন্তু এটি ইউনিটের ভিতরে কোটিং নিয়ম লুকায় এবং পর্যালোচনা কঠিন করে। নামযুক্ত স্ক্রিপ্ট হাতে পরীক্ষা করা যায় এবং পরে ইউনিট সম্পাদনা ছাড়াই বদলানো যায়। ইন্টারঅ্যাকটিভ ব্যবহারকারীর shell প্রোফাইলের উপর নির্ভর করবেন না, কারণ সার্ভিস নিজের পরিবেশ নিয়ে শুরু হয়।

আপেক্ষিক পথ গুরুত্বপূর্ণ হলে WorkingDirectory সেট করুন, এবং পরিবেশ টার্মিনালে এক্সপোর্ট করার বদলে ইউনিটের সমর্থিত ডিরেক্টিভের মাধ্যমে পাঠান। গোপনীয়তা সুরক্ষিত ফাইল বা ক্রেডেনশিয়ালে থাকে, এমন আর্গুমেন্ট তালিকায় নয় যা জার্নাল রেকর্ড করতে পারে।

প্রকৃতপক্ষে যে ইউনিট আছে তা যাচাই করুন

drop-in ফাইল আপনি সম্পাদনা করার কথা মনে করা ফাইলটি না ছুঁয়েই আচরণ বদলে দেয়। ম্যানেজার কী লোড করেছে এবং শেষ রান কী জানিয়েছে তা পড়ুন।

systemctl cat vpn-helper.service
journalctl -u vpn-helper.service -n 20 --no-pager

ইউনিট ডাম্প লোড ক্রমে drop-in অন্তর্ভুক্ত করে, এবং অপ্রত্যাশিত ExecStart সাধারণত সেখান থেকেই আসে। যেকোনো পরিবর্তনের পরে ম্যানেজার রিলোড করুন এবং নিশ্চিত করুন নতুন সংজ্ঞাটিই তা যা systemctl cat প্রিন্ট করে। জার্নাল সঠিক কমান্ড লাইন ও এক্সিট স্ট্যাটাস দেখায়, যা আর্গুমেন্ট সমস্যাকে অনুপস্থিত বাইনারি বা অনুমতি ত্রুটি থেকে আলাদা করে। তারপর ঠিক করুন হেল্পারটি বিদ্যমান VPN লাইফসাইকেলের অংশ কি না, নাকি হাতে করা ডায়াগনস্টিক থাকা উচিত, কারণ দ্বিতীয় ব্যাকগ্রাউন্ড টানেল প্রক্রিয়া একটি প্রতিদ্বন্দ্বী মালিক তৈরি করে।

চাহিদামতো সঠিক আউটপুট দেওয়া ইউনিট ভালো প্রথম মাইলফলক। এটি এখনো টানেল নয়, এবং টানেল বলে দাবি করা উচিত নয়।

সম্পর্কিত নিবন্ধ