Четиридесет файла .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

Инстанция, която никой не помни да е включвал, обикновено води до заблуден конфигурационен файл в директорията на пакета. Изключете именно тази именувана инстанция, а не шаблона, иначе следващата актуализация на пакета ще я върне. След промяната стартирайте юнита и прочетете командния ред, който журналът съобщава, после потвърдете пътя до конфигурацията, който той наистина е отворил. Тази една проверка отделя работещ случаен избор от услуга, която тихо преизползва файл от миналия месец.

Подобни статии