ExecStart nie je shell: oprava pomocnej jednotky VPN
ExecStart spúšťa program s argumentmi, nie shellovú rúru. Použite explicitný interpret alebo skutočný skript, potom jednotku overte a prečítajte journal.
Skopírujte fungujúci príkazový riadok do ExecStart, znovu načítajte a jednotka zlyhá alebo ticho skončí, pretože argumenty sa považujú za názvy súborov. V systemd nie je nič pokazené. ExecStart je zoznam argumentov, nie shell, takže rúry, presmerovanie a podmienky strácajú zmysel v okamihu, keď opustia váš terminál. Rozhodnite, kam shell patrí, a potom napíšte jednotku, ktorá presne hovorí, čo sa má spustiť.
Prečo rúra v ExecStart nič nerobí
Keď sa príkaz napíše do terminálu, shell ho najprv spracuje. Zostaví rúru, otvorí súbory na presmerovanie a rozvinie premenné skôr, než sa spustí akýkoľvek program. systemd nič z toho nerobí: rozdelí ExecStart podľa vlastných pravidiel a spustí výsledný program s týmito argumentmi. Preto > dorazí ako doslovný argument a | sa odovzdá programu namiesto toho, aby spojil dva procesy. Jednotka sa nespráva zle; syntax znamenala niečo iné.
Je to zámer, nie nedbalosť, pretože predvídateľné zaobchádzanie s argumentmi robí jednotky auditovateľnými. Prekvapí len tých, ktorí predpokladajú, že shell je prítomný.
Napíšte jednotku, ktorá presne hovorí, čo sa spúšťa
Začnite malou jednotkou, ktorej účel je vidieť v journali, aby problémy s parsovaním zostali oddelené od problémov s tunelom. Táto len hlási verziu binárky.
[Unit]
Description=Report the installed OpenVPN version
[Service]
Type=oneshot
ExecStart=/usr/sbin/openvpn --version
StandardOutput=journal
StandardError=journalCesta je zástupný text, takže ju nahraďte binárkou, ktorá je skutočne nainštalovaná. Type=oneshot sa hodí na príkaz, ktorý beží do konca, a nastavenia journalu umiestnia jeho výstup tam, kde si ho prečítate bez terminálu. Sekcia pre inštaláciu zámerne chýba, takže jednotka sa volá ručne namiesto toho, aby sa povolila pri štarte. Overte súbor pred spustením, pretože preklep v názve direktívy zlyháva inak ako preklep v ceste.
systemd-analyze verify /etc/systemd/system/openvpn-version.service
systemctl start openvpn-version.serviceNechajte shellovú logiku v skripte
Keď pomocník naozaj potrebuje podmienenú logiku, dajte ju do skriptu a volajte ho explicitne. Skript potrebuje riadok s interpretom, právo spúšťania a návratové kódy, ktoré služba dokáže nahlásiť. Spúšťanie /bin/sh -c s príkazom v úvodzovkách funguje, ale skrýva pravidlá úvodzoviek vnútri jednotky a sťažuje kontrolu. Pomenovaný skript sa dá vyskúšať ručne a neskôr nahradiť bez úpravy jednotky. Nespoliehajte sa na profil shellu interaktívneho používateľa, pretože služba štartuje s vlastným prostredím.
Nastavte WorkingDirectory, keď záleží na relatívnych cestách, a odovzdávajte prostredie podporovanými direktívami jednotky namiesto exportu v termináli. Tajomstvá patria do chránených súborov alebo prihlasovacích údajov, nie do zoznamov argumentov, ktoré môže journal zaznamenať.
Skontrolujte jednotku, ktorá skutočne existuje
Drop-in súbory menia správanie bez toho, aby sa dotkli súboru, ktorý si pamätáte, že ste upravovali. Prečítajte si, čo správca načítal a čo nahlásil posledný beh.
systemctl cat vpn-helper.service
journalctl -u vpn-helper.service -n 20 --no-pagerVýpis jednotky zahŕňa drop-in súbory v poradí načítania a práve odtiaľ zvyčajne pochádza neočakávaný ExecStart. Po každej zmene znovu načítajte správcu a potvrďte, že nová definícia je to, čo vypisuje systemctl cat. Journal zobrazuje presný príkazový riadok a stav ukončenia, čo oddeľuje problém s argumentmi od chýbajúcej binárky alebo chyby oprávnení. Potom rozhodnite, či pomocník patrí k existujúcemu životnému cyklu VPN alebo má zostať ručnou diagnostikou, pretože druhý proces tunela na pozadí vytvára konkurenčného vlastníka.
Jednotka, ktorá na požiadanie vypíše správny výstup, je dobrý prvý míľnik. Ešte to nie je tunel a nemala by predstierať, že ním je.