Script-server. WebUI для віддаленого запуску ваших скриптів

Всім привіт. У даній статті я б хотів розповісти про свій домашній проект. Якщо коротко: Script server є веб-сервером для надання користувачам доступу до ваших скриптів через web-інтерфейс. Сервер і скрипти виконуються локально, а параметризуются і показуються віддалено.



Передісторія
На новому місці роботи, перші мої завдання були досить рутинну і одноманітні. Схематично вони виглядали так:

  1. Створити файл my_file.txt
  2. Прописати туди нову конфігурацію
  3. Задеплоить
  4. Закомиттить
Кроків було більше і вони були складніші, але вже через пару таких ітерацій лінь перемогла і для всіх повторюваних завдань були написані shell-скрипти, які запускалися з кількома параметрами і іноді запитували додаткові вхідні дані у процесі роботи. У той же час, робочий процес став виглядати приблизно так:

  1. запитати у керівника проекту потрібні параметри
  2. запустити скрипт
  3. доповісти про готовність
Всі ці пункти явно напрошувалися на схлопування в один, щоб керівник проекту вказував параметри і сам запускав скрипт. Але давати йому скрипти було дуже проблематично з ряду причин — скрипти були адаптовані під моє оточення, вони могли давати збої, вони були досить доброзичливі для мене, але не для нетехнічних людей, і т. п.

Треба сказати, що до певного моменту подібні завдання вже перестали на мене призначати і у створених скриптів без необхідної адаптації було дуже примарне майбутнє.

Тому я вирішив створити інструмент, який дозволить віддалено запускати мої скрипти іншим людям, без необхідності створювати необхідне оточення і в більш зручній формі налаштовувати їх запуск.

На шляху створення

Схема роботи


Адміністратор сервера (тобто я) створює файли конфігурації для кожного скрипта, в яких описує призначення скрипта, шлях запуску і необхідні параметри. Ці файли конфігурації використовуються сервером для надання даних про скриптах користувачеві, а також для їх запуску. Інформація на сторінку користувача передається Ajax запитами.

Користувач заповнює параметри і запускає скрипт на сервері, де його виконання передається спеціальному обробникові. Оброблювач в асинхронному режимі приймає input і надає output, а також стежить за процесом виконання скрипта.

Веб сервер служить прошарком між цим обробником та сторінкою, і через веб-сокети здійснює обмін даними.

Вибір інструментів

У той час я вчив Python і для розробки вирішив використовувати саме його, як непогану практику. Для проекту було обрано Python 3, без підтримки 2ї версії, оскільки необхідності в цьому немає, а витрачати зайвий час не хотілося.

На початку розробки для сервера я використовував Flask, але не зміг зробити (читай розібратися) з асинхронностью і відстеженням підключення/відключення клієнтів, тому досить швидко перевів усе на Tornado.

Стосовно web розробки: Web-розробник з мене ніякий, тому тут я теж вирішив трохи попрактикуватися в синтаксисі і основи. У зв'язку з цим не було використано майже ніяких фреймворків і бібліотек, за винятком materializecss для більш-менш пристойного оформлення.

Web сторінка являє собою «одностраничное додаток» з мінімумом HTML і створенням контенту у JS по Ajax запитам.

Перша експлуатація та поліпшення

Приблизно через місяць у мене вийшов сервер, який сяк-так можна було використовувати і я поділився ним з колегами-розробниками, яким теж доводилося виконувати ці рутинні завдання (які як на зло в цей період майже закінчилися).

В процесі експлуатації були виявлені як баги, так і явно відсутні елементи, над якими я потихеньку працював і поліпшував. В той же час були додані дрібні поліпшення, такі як типи параметрів, логгирование усіх запусків тощо

Цікавий момент: для деяких дрібних завдань (пов'язаних з роботою в консолі і зі скриптами) я також перестав користуватися консоллю, а перейшов на цей UI. Тобто у мене заведено кілька конфігурацій скриптів, які я використовую частіше, ніж інші люди.

Експлуатація реальним користувачем

Через деякий час локального тестування (мною і іншими розробниками), інструмент був нарешті надано керівнику проекту, який почав потихеньку ним користуватися. І треба відзначити, що він дуже задоволений, оскільки це економить в тому числі і його час. Процес «впровадження» і навчання користувача зайняв приблизно 5 хвилин.

Із-за особливостей процесів і обмежень, Script server використовується в основному для тестового оточення. Але деякі її частини вже стали використовуватися і для Production (в тій частині, де це безпечно).

Основні камені
Нижче наведено список проблем і моїх особистих відкриттів, які мені найбільше запам'яталися.

Передача вихідних даних з процесу виконання скрипта на сторінку в асинхронному режимі. Тут позначилася відсутність досвіду як у Flask, так і в інтернеті: як краще організувати таку передачу. У підсумку реалізував на вебсокетах передачу даних у вигляді подій (тип і дані). Також у подіях можна відправляти і інші команди під час виконання, але поки це не використовується.

Передача введення користувача в виконуваний скрипт. Намагався зробити запит на введення тільки при очікуванні такого в скрипті, але не знайшов способу. Тому користувачі під час виконання скрипта можуть вводити стільки інформації, скільки хочуть (звичайний термінал веде себе так само). Дані передаються через той же вебсокет.

Відстеження відключення користувачів. Саме із-за цієї проблеми відмовився від Flask: в той момент я робив не на вебсокетах, а на SSE (ну майже). Проте пізніше я все ж переклав передачу input/output скрипта на вебсокеты, так що можливо і Flask би підійшов. В Торнадо ж просто можна підписатися на закриття вебсокета.

Зчитування вихідних даних виконання скрипта. Тут була проблема з тим щоб зчитувати тільки поточні доступні дані і відправляти на клієнт. Зчитувати по рядках не можна, т. к. наприклад «read -p input_prompt» не переносить на наступний рядок. Зчитувати по символам можна надсилати так багато запитів на клієнт не варто. Зчитування буфером дає рядок обрізану в незрозумілих місцях (а ще і в разі UTF-8 це породжує неправильні символи). Поточне рішення рясніє набором компромісів та милиць, але в цілому це побуферное зчитування з відключення блокування читання.

Output скриптів (не)термінальному режимі. Чесно кажучи для мене це було відкриттям: output скриптів може відрізнятися якщо запускати їх в терміналі або поза. Наприклад той же…

read -p input_prompt

… показує input_prompt тільки у термінальному режимі. Не дуже добре-чого чекати від користувачів, не показуючи їм чого саме. Довелося розбиратися з pty, щоб обманювати запускаються скрипти. З цієї причини у мене зараз два типи обгорток для запуску скриптів: з підтримкою терміналу і без. Перший включається за замовчуванням, другий можна включити за допомогою конфігурації (залишив його на всякий випадок, якщо термінальний режим буде давати збої).

Автоскролл вихідних даних скрипта. З одного боку це вирішується досить просто, з іншого боку були проблеми з налаштуванням автоматичного відключення цього (якщо користувач скроллит вручну або виділяє текст), а також з тінню, введенням користувача і т. п. Нічого экстраординаорного, але кілька годин довелося витратити.

Настройка панелі з вихідними даними скрипта таким чином, щоб вона займала все доступне місце, але при цьому ніколи не виходила за межі вікна. Таким чином сторінка завжди вміщується у вікно і єдиний скролл додається саме всередині output панелі. Для мене це було особливо важливо, оскільки я категорично не люблю скролли в скроллах.

Продуктивність сторінки при дуже великій кількості вихідних даних скрипта. Тут зі мною злий жарт зіграв наступний код:

htmlElement.innerText += "text";

Справа в тому, що одержання innerText це сама по собі досить дешева операція, яка намагається представити вхідний html як рядок, навіть якщо це просто текст. Якщо викликати цю операцію кілька сотень разів і для тисячі символів, то ефект не помітний, але в моєму випадку даних було набагато більше і браузер просто зависав на кілька хвилин від такого навантаження. Вирішилося зміною коду на наступний:

var textNode = document.createTextNode("text");
htmlElement.appendChild(textNode);

Висять процеси, тобто ніхто нічого не виконує, але в процесах висить виконуваний скрипт. Причини були різні, наприклад: користувач закрив сторінку, а сервер не обробляє це. Чи не закритий дескриптор файлу. Або незакриті дочірні процеси. І це не рахуючи інших очевидних помилок. Але усувалося всі гуглением, вивчення і виправленням.

Безпека
Її немає зовсім. Даний інструмент розрахований на локальний запуск і роботу в локальній мережі з довіреними користувачами. Оскільки часто скрипти теж пишуться для себе, вони також не є особливо захищеними. Відповідно перш ніж запускати такий сервер, потрібно бути на 100% впевненим у фаерволле і користувачів.

З точки зору приховування даних, у Script server на поточний момент також немає нічого. Включати паролі в якості параметрів або в конфігурацію вкрай не рекомендується, оскільки вони будуть логироваться і зберігатися в чистому вигляді.

Приклади і скріншоти
Для налагодження в проекті я завів тестові конфігурації, які можна використовувати для тестування і демонстрації. В даному розділі всі надані скріншоти будуть ґрунтуватися на них.

Налаштування скриптів

Щодо стандартний баш скрипт з параметрами, введенням користувача під час роботи і печаткою: Write file.

Простий пітон-скрипт, який виводить стіну тексту, розбиваючи його на абзаци і запитуючи input користувача: Destroy world. Ця конфігурація використовується для налагодження інтерфейсу користувача при відображенні параметрів. Містить всі можливі типи параметрів: Parameterized

Скріншоти

Повний екран


Зліва область вибору скриптів, праворуч інформація з відкритих скрипту:

  • Назва
  • Опис
  • Список параметрів
  • Кнопки запуску/зупинки
  • Output скрипта
Панель параметрів


В цьому хаосі можна побачити сім'ю різних типів параметрів: обов'язкові, списки, числа, булеаны. Скріншот створений на основі конфігурації Parameterized

Панель input/output


Зверху кнопки запуску і зупинки. Оскільки скрипт запущено, активна лише остання. Нижче панель вихідних даних скрипта, в самому низу поле для вводу вхідних даних. Панель вихідних даних стиснута по висоті для демо-цілі, у звичайному вікні вона набагато вище.

Подальші кроки
На даний момент розробка не ведеться, оскільки в поточному вигляді Script server повністю покриває покладені на нього завдання. Що-небудь оптимізувати в поточному інтерфейсі я також не бачу потреби. Таким чином ми з ним обидва знаходимося в очікуванні нових викликів і проблем.

Зокрема, я був би дуже радий, якби цей інструмент так же нагоді кому-небудь з хабрасообщества і у мене з'явилася необхідність у нових поліпшень.

» Посилання на репозиторій проекту: github.com/bugy/script-server

Список використовуваних бібліотек/фрейворков/подяк:

  • materializecss — materializecss.com
  • tornado — www.tornadoweb.org
  • Окреме спасибі моєму колишньому колезі за підтримку і допомогу у вирішенні деяких web проблем, особливо стосуються верстки.
Спасибі всім тим, хто знайшов час прочитати дану статтю. Буду вдячний за цінні коментарі та критику (з точки зору підходу, програми або особливостей реалізації).
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.