Предупреждение OpenVPN о нескольких --up-скриптах: выполняется только один
Перестановка двух строк up не заставит работать оба. OpenVPN хранит одну команду на этап, поэтому найдите оба определения и дайте работе единую точку входа.
Предупреждение о нескольких скриптах звучит как жалоба на планировщик, поэтому очевидное решение — переставлять строки, пока оно не исчезнет. Но это не жалоба на планировщик. Более позднее определение --up заменяет команду, уже сохранённую для этого этапа, и анализатор так и сообщает, а значит, из двух ваших скриптов когда-либо выполнялся ровно один. Второй не стоит в очереди за ним; он исчез.
Поэтому предупреждение заслуживает внимания, даже если оно не фатально: оно предсказывает обновление DNS или изменение маршрута, которые тихо перестали происходить.
Предупреждение не о порядке
OpenVPN хранит одну команду пользовательского скрипта для этапа up. Когда анализатор встречает другое определение — из профиля, включённого файла или командной строки, — он заменяет уже сохранённое и выдаёт предупреждение. Ничего не объединяется, ничего не выполняется дважды, и вопроса о порядке не существует. Выживает та команда, которую анализатор увидел последней, поэтому перенос строки может сменить победителя, а другой скрипт останется мёртвым.
Тот же принцип действует и для остальных этапов скриптов: по одной команде на каждый. Если две работы должны произойти обе, им нужна единая точка входа, а не две директивы, похожие на список.
Найдите оба определения в реальном запуске
Начните с того, что демон действительно получил, а не с профиля, который вы правили. ps -ef и ExecStart юнита показывают командную строку, в которую могут добавить --up из точки входа контейнера или обёртки; init-файл дистрибутива может сделать то же. systemctl cat openvpn-server@server показывает, что добавляет сама служба, а рекурсивный grep по каталогу конфигурации находит определения на уровне файлов. Дубликаты обычно приходят из разных слоёв, и именно поэтому правка одного файла ничего не меняет.
Копирование скрипта в другой каталог или переименование тоже не удаляет директиву. Анализатор считает определения, а не файлы.
Пусть один hook владеет работой
Долговечное решение — один диспетчер, который выполняет оба действия в продуманном порядке. Короткий shell-скрипт с set -eu, который вызывает нужную интеграцию, затем локальное действие и передаёт "$@", чтобы границы аргументов сохранились, держит поведение в одном проверяемом месте. Передача аргументов лишь сохраняет их; она не доказывает, что два помощника ожидают один и тот же интерфейс, поэтому прочитайте контракт каждого. Решите, что должна делать ошибка и нужно ли откатывать частичные изменения.
Если загрузчик предлагает поддерживаемый hook расширения, предпочтите его самодельной цепочке. Образ контейнера или пакет поставщика часто имеет документированное место для дополнительной работы, и его использование не даёт обновлению перезаписать ваш диспетчер.
Очистка относится к соответствующему этапу down. Действие up, которое переписывает DNS или добавляет маршруты, требует документированного отката, а диспетчер, который занимается только запуском, — это половина проекта.
Подтвердите интеграцию, а не только тишину
Убрать предупреждение о дубликате — простая часть; интеграция всё равно должна работать. Проверьте состояние резолвера после подключения с помощью resolvectl status или прочитав /etc/resolv.conf, и подтвердите маршруты с помощью ip route. Затем отключитесь и подключитесь снова, потому что наспех связанный hook обычно оставляет что-то от предыдущей сессии. journalctl -u openvpn-server@server -b показывает, запускался ли ваш диспетчер и что он вывел.
Держите привилегии hook там, где им место. Повышение script-security или запуск демона с большими правами — не решение для заменённого hook; это расширяет то, что может делать каждый будущий скрипт, включая тот, который назовёт злоумышленник.
Признак настоящего исправления — не тишина в журнале. Это ответ DNS, запись маршрута и очистка, которые работают после двух переподключений.