Скрипт up в OpenVPN запустився занадто рано чи він так і не був готовий?
Хук up спрацьовує, коли з'являється тунельний пристрій, раніше за маршрути та готовність застосунку. Прив'яжіть скрипт до потрібної події замість додавання паузи.
Скрипт up виконується, завершується з нулем, а завдання всередині нього не досягає приватного сервісу, який із термінала чудово працює за дві секунди. Інстинкт підказує, що річ у таймінгу, і звичайне виправлення — пауза, яка приховує гонку, не розуміючи її. Корисніше прочитання: «up» називає хук, а не гарантує готовність. Він спрацьовує, коли тунельний пристрій налаштовано, а це раніше за маршрути, DNS і точно раніше за будь-який застосунок за тунелем.
Тест у оболонці пройшов, бо виконувався після того, як усе вляглося. Хук виконувався в один конкретний момент.
Де up стоїть у порядку запуску
OpenVPN налаштовує тунельний пристрій, а потім запускає хук up. Встановлення маршрутів — пізніший етап, і в нього є власний хук, тому завдання, що залежить від маршрутів і розміщене в up, може побачити пристрій без корисного шляху. Розмістіть роботу з маршрутами в route-up, і проблема таймінгу зазвичай зникає.
Посібник документує цей порядок і середовище, яке отримує кожен хук. Цей порядок — усе пояснення класичного звіту «працює з моєї оболонки», і він же причина, чому той самий скрипт може пройти на одній машині й не пройти на іншій із повільнішим етапом маршрутів. Жоден із результатів нічого не каже про якість скрипта.
DNS і готовність застосунку настають ще пізніше. Навіть встановлені маршрути не є доказом, що віддалена кінцева точка слухає, що ім'я розв'язується або що існує сесія робочого столу для завдання в межах користувача.
Що хук насправді успадковує
Хук виконується під обліковим записом і в середовищі процесу OpenVPN, що не те саме, що ваша інтерактивна оболонка. Йому може бракувати шини сеансу користувача, середовища робочого столу або облікових даних, які розблоковуються лише під час входу. Запишіть, що з цього насправді потрібно завданню.
Це важливо для завдань, які виглядають мережевими, але залежать від контексту користувача: монтування спільного ресурсу з обліковими даними користувача, налаштування проксі для користувача або налаштування принтера. Привілейований тунельний хук — неправильне місце для них, і жодне очікування не виправить відсутній сеанс.
Коли завдання падає в хуку, запишіть обліковий запис, середовище та першу операцію, що не вдалася. Це відокремлює передчасний таймінг від проблеми з дозволами чи контекстом, і ці два мають зовсім різні виправлення. Вгадування між ними — це шлях, яким п'ятихвилинне виправлення перетворюється на цілий день.
Чому додавання паузи не є перевіркою готовності
Пауза затримує скрипт і зсуває вікно гонки. У швидкий день завдання вдається; у повільний день воно знову падає, і збій стає важче відтворити, бо затримка ніби працює. Затримка, яка працює лише під легким навантаженням, — збіг, а не виправлення.
Якщо залежність — маршрут, використовуйте хук, що відповідає встановленню маршрутів. Якщо залежність — сервіс за тунелем, використовуйте обмежену перевірку, яка чекає саме на цю умову й чітко падає, коли вона так і не настає.
Тримайте збій явним. Хук, що завершується з нулем, коли його реальна робота провалилася, гірший за хук, що падає, бо менеджер сервісів записує успіх і більше ніхто не дивиться. Один рядок журналу із самого скрипта — найдешевший спосіб зберегти це чесним.
Очищення та перепідключення заслуговують такої ж турботи
Скрипт, який змінює спільний стан, потребує відповідного шляху скасування. Маршрути, записи резолвера й позначки брандмауера, додані хуком, мають бути ідемпотентними та оборотними, інакше перепідключення накладе другу копію поверх першої.
Перепідключення також можуть запускати хуки частіше, ніж повний запуск сервісу. Постійний інтерфейс, який знову встановлює сеанс, може знову викликати цикл up і route-up, тож скрипт, що припускає одне виконання на завантаження, зрештою почне працювати неправильно. Порахуйте виконання в журналі за день миготіння, щоб побачити, як часто він насправді запускається. Потім зробіть скрипт безпечним для такої кількості запусків.
Перевіряйте той життєвий цикл, який падав, а не пізнішу команду. Відтворіть завантаження або перепідключення, спостерігайте за виконанням хука й підтвердьте, що завдання вдалося в той момент, коли він справді запускається. Успіх з інтерактивної оболонки потім — це доказ про залежність, а не доказ того, що шлях запуску працює.
Назвіть подію, від якої залежить кожне завдання, і прив'яжіть завдання до цієї події. Усе інше — затримка, що вдає перевірку.