დააკოპირეთ მომუშავე ბრძანების სტრიქონი 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-ის სიცოცხლის ციკლს თუ უნდა დარჩეს ხელითი დიაგნოსტიკა, რადგან მეორე ფონური გვირაბის პროცესი ქმნის კონკურენტ მფლობელს.

ერთეული, რომელიც მოთხოვნისთანავე ბეჭდავს სწორ გამომავალს, კარგი პირველი ეტაპია. ის ჯერ არ არის გვირაბი და არ უნდა მოიქცეს ისე, თითქოს არის.

დაკავშირებული სტატიები