Выпадковы выбар 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 падстаўляе %i падчас разбору юніта, задоўга да запуску bash, таму спецыфікатар мусіць стаяць па-за адзінарнымі лапкамі. 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
Асобнік, які ніхто не памятае, што ўключаў, звычайна вядзе да асобнага файла канфігурацыі ў каталогу пакета. Адключыце менавіта гэты названы асобнік, а не шаблон, інакш наступнае абнаўленне пакета верне яго. Пасля змены запусціце юніт і прачытайце радок каманды, які паведамляе журнал, затым пацвердзіце шлях канфігурацыі, які ён сапраўды адкрыў. Гэтая адна праверка аддзяляе працуючы выпадковы выбар ад службы, якая ціха паўторна выкарыстоўвае файл з мінулага месяца.