Завантажте машину, увійдіть і дізнайтеся, що тунель піднявся і помер через кілька секунд. Профіль був гаразд, сертифікат був гаразд, і єдиний залишок — це журнал цього завантаження. Зазвичай сталася гонка: юніт запустився раніше, ніж у машини з'явилася адреса, а порядок, який він оголосив, не означав того, на що схожий. Усе нижче — про те, як довести цю гонку за свідченнями і правильно її закрити.

Ціль — це місце зустрічі, а не керівник

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-сервер, і цим двом потрібні різні виправлення. Потім доведіть усе холодним завантаженням, а не перезапуском служби, бо перезапуск іде проти вже піднятої мережі й приховає саме той дефект, який ви шукаєте. Повторіть це з навмисно повільним з'єднанням і вважайте юніт, який працює лише за швидкої мережі, досі зламаним.

Схожі статті