Почему юнит VPN запускается раньше сети и затем умирает
Юнит, который запускается раньше, чем у соединения появится адрес, отказывает так, что это выглядит случайным. Докажите порядок по журналу, затем добавьте ожидание и повтор.
Загрузите машину, войдите и узнайте, что тоннель поднялся и умер через несколько секунд. Профиль был в порядке, сертификат был в порядке, и единственный оставшийся след — журнал этой загрузки. Обычно случилась гонка: юнит запустился раньше, чем у машины появился адрес, а порядок, который он объявлял, не означал того, на что похож. Всё ниже — о том, как доказать эту гонку по свидетельствам и правильно её закрыть.
Цель — точка встречи, а не менеджер
network-online.target понятия не имеет, что такое сеть. Это точка координации, которая собирает ту службу, что должна задержать запуск до тех пор, пока соединение не станет пригодным, и передаёт определение тому менеджеру сети, которому принадлежит машина. На большинстве рабочих станций и серверов это означает службу ожидания, поставляемую NetworkManager или systemd-networkd. Не включите ни одну — и цели нечего ждать, поэтому она завершается в тот момент, когда что-то её втягивает, а это может быть задолго до ответа DHCP. Строка порядка в вашем юните была честной и всё равно бесполезной.
Поэтому первый вопрос — не то, что объявляет ваш юнит. А то, делает ли что-нибудь на этой машине ожидание на самом деле.
Читайте последнюю загрузку, а не файл юнита
Файлы юнитов описывают намерение, а журнал описывает то, что произошло. Запросите только эту загрузку, с монотонными отметками времени, чтобы каждое сообщение стояло на одних часах. Затем найдите две строки: момент, когда юнит тоннеля начал запускаться, и момент, когда появился адрес или завершилась служба ожидания. Упорядочите эти два числа, и гонка либо подтвердится, либо исключится.
Представление зависимостей это подтверждает. Если критическая цепочка для юнита тоннеля не содержит службы ожидания, ничто на этом пути не задержало запуск, и цель не сделала той работы, которую вы предполагали. Два представления, один вывод.
systemctl list-units --type=service --state=running | grep wait-online
journalctl -b -o short-monotonic -u openvpn-client@office
Добавьте ожидание, затем повтор
Используйте drop-in вместо правки упакованного юнита, чтобы обновление пакета молча не отбросило изменение. Важны две директивы: юнит должен быть упорядочен после цели и должен втянуть цель в ту же транзакцию. Один только порядок цель не вызывает; это делает желание.
Упакованный юнит клиента OpenVPN уже несёт и то, и другое. Написанные вручную юниты обычно несут одно или ничего, что стоит проверить, прежде чем что-то добавлять.
[Service]
Restart=on-failure
RestartSec=15
Почему фиксированный сон — ловушка
Сон в ExecStartPre ощущается как исправление порядка и ведёт себя как задержка с лишними шагами. Он замедляет каждую загрузку, включая те, что были здоровыми, и всё равно проигрывает, когда соединение занимает больше времени, чем выбранное число.
Хуже того, он скрывает, работает ли служба ожидания, поэтому следующий отказ выглядит совершенно новой проблемой, а не той же самой с другим временем. Короткая задержка перезапуска — лучший инструмент: при здоровой загрузке она ничего не стоит и превращает проигранную гонку в ещё одну попытку. Держите интервал скромным и дайте юниту добиться успеха. Если он перезапускается вечно, профиль испорчен, и никакое количество повторов этого не изменит, поэтому читайте журнал, а не увеличивайте интервал.
Когда порядок верен, а имена всё равно не разрешаются
Активный юнит с маршрутом тоннеля означает, что порядок сделал своё дело, а оставшаяся неисправность находится на уровень выше. Обычная форма — настройка резолвера, которую up-скрипт тоннеля применяет раньше, чем соединение или резолвер был готов её удержать. Сравните состояние резолвера во время отказа с состоянием после перезапуска юнита тоннеля.
Если перезапуск исправляет поиск, у вас дефект порядка запуска, а не неправильный DNS-сервер, и этим двум нужны разные исправления. Затем докажите всё холодной загрузкой, а не перезапуском службы, потому что перезапуск идёт против уже поднятой сети и скроет именно тот дефект, который вы ищете. Повторите это с намеренно медленным соединением и считайте юнит, который работает только при быстрой сети, всё ещё сломанным.