Скринкаст терминала с помощью asciinema

от автора

Вы наверняка знакомы с asciinema (github), это удобный опенсорсный инструмент для записи действий в терминале. Записи сохраняются в простом для чтения текстовом формате, поэтому весят совсем немного, а веб-плеер по сути воспроизводит текст из терминала вместо видео, так что любой кусок можно скопировать и использовать. Готовый материал можно загрузить в одно нажатие на asciinema.org или сначала отредактировать локально. Плеер можно встроить на сайт буквально в три строки, бонусом прилагаются всякие плюшки с оформлением и совместимостью, и вообще по совокупности всех фич (и отсутствия головной боли) asciinema давно перерос все аналоги. Вот только есть несостыковка: записи в проекте называют asciicasts, по аналогии со скринкастами — но возможности стримить сессию в реальном времени не было несколько лет, пока не вышел релиз 2.0, в котором с помощью нового формата файлов удалось реализовать на удивление стабильную и удобную раздачу на любой терминал в реал-тайме. О том, как это работает, о подводных камнях и перспективах — под катом.

Один формат — много возможностей

В старых версиях данные записывались в JSON, что добавляло немало оверхеда, да и парсинг у него нетривиальный, а главное, объект неудобно дробить на чанки для частичной передачи и чтения данных. На смену пришёл кастомный формат:

  {"version": 2, "width": 236, "height": 54, "timestamp": 1613998795, "idle_time_limit": 1.0, "env": {"SHELL": "/bin/bash", "TERM": "screen"}}   [0.023635, "o", "client@some-desktop:~$ "]   [0.812065, "o", "h"]   [1.087183, "o", "e"]   [1.246706, "o", "l"]   [1.473065, "o", "l"]   [1.657363, "o", "o"]   [4.114169, "o", "exit\r\n"] 

В первую строку записываются метаданные и параметры воспроизведения, в каждую последующую — очередная строка терминала. На вид очень похоже на JSON, но теперь можно отображать любую строку по отдельности, добавив к ней метаданные. Теперь можно не только передавать данные по частям, но и дописывать новый каст в конец старого файла.

Если раньше единственным способом синхронного вывода было перенаправление записи в stdin второго терминала, что подразумевало хранение всего каста в памяти и воспроизведение после полного получения и парсинга, то теперь воспроизведение начинается сразу после анализа первой строки. Поток можно, например, завернуть в юниксовый именованный канал:

  mkfifo /tmp/demo.pipe    # viewing terminal   asciinema play /tmp/demo.pipe      # recording terminal   asciinema rec /tmp/demo.pipe 

Или можно передавать данные по сети с помощью netcat:

  # viewing terminal (hostname: node123)   asciinema play <(nc -l localhost 9999)      # recording terminal   asciinema rec >(nc node123 9999) 

Причём на принимающей стороне необязательно даже иметь установленный asciinema, с режимом —raw данные отправляются «как есть», без конвертации. Но там не будет метаданных, не будут сохранены тайминги и задержки, поэтому такой вариант не слишком привлекателен. Гораздо лучше шагнуть ещё дальше и стримить сессию по ssh! Но здесь лучше не торопиться и сначала разобраться в реализации.

Рисуем картинку локально

Установка asciinema:

  sudo apt install python3-pip   sudo pip3 install asciinema 

Запишем тестовый файл командой asciinema rec -i 1 file.cast. -i 1 — это параметр, обрезающий задержку при вводе до одной секунды.

Пример файла каста выше соответствует выводу cat file.cast, он статичен. Но если начать запись и в соседней вкладке запустить tail -f file.cast, строки будут появляться по мере дописывания в файл после изменений в терминале. Этот динамически обновляющийся вывод можно перенаправить в asciinema play:

  # принимающая вкладка   tail -fn +1 file.cast | asciinema play - 

Таким нехитрым образом мы запускаем зеркальное отображение наших действий в записываемой вкладке. Но картинка будет соответствовать источнику только если плеер изначально принял первую строку с параметрами (в частности, -i) и успел «догнать» стрим. Чтобы избежать проблем с задержкой просто будем передавать вместе с последней строкой первую:

  # принимающая вкладка   (head -1 file.cast && tail -fn 0 file.cast) | asciinema play - 

К сожалению, при этом ломается первая строка в «зеркале» — она начинается сразу с введённых символов, опуская префикс, но это не критично, да и достаточно одного переноса, чтобы всё вернулось:

В целом, для простых юзкейсов можно не запариваться head’ом, но если строить полноценную систему с подключением посередине стрима и восстановлением после обрыва соединения, конечно, передавать первую строку нужно обязательно.

Переносим отображение на удалённый сервер

Нам понадобится беспарольный доступ, поэтому в принимающей вкладке генерируем ключи RSA, добавляем публичный ключ на сервер и идём его настраивать:

  ssh-keygen -t rsa   ssh-copy-id -i ~/.ssh/id_rsa.pub user@hostname   ssh user@hostname    # на сервере поставим также утилиту pv для буферизации   sudo apt install python3-pip pv   sudo pip3 install asciinema 

После установки осталось перенаправить поток текста в файл на сервере:

  # клиент   asciinema rec -i 1 >(ssh user@hostname tee /path/to/file.cast >/dev/null) 
  # сервер   tail -fn +1 /path/to/file.cast | asciinema play - 

Готово! По сути, всё уже работает. Но стоит добавить ещё пару штрихов: во-первых, asciinema play — высокоуровневая команда, для которой можно определить скорость выполнения операций. Чем выше значение (опционального) параметра -s, тем меньше задержка и выше нагрузка. Для наших целей куда лучше подойдёт asciinema cat, который работает на запись как аналог режима --raw, но воспроизводится с сохранением метаданных и параметров. Кроме того, воспользуемся pv для создания буфера на случай скачков производительности или сетевых лагов:

  # сервер   tail -fn +1 /home/benaryorg/.local/tmp/tmp.6nkIacxYqF/foo | pv -q -b 8m | asciinema cat - 

Результат


Плеер не встраивается в Хабр, извините

Светлое будущее

Вообще вся эта чудесная функциональность появилась довольно давно: 2.0 вышел около трёх лет назад. Однако, хорошая новость в том, что весь предыдущий год команда asciinema-player переписывала плеер целиком чтобы добавить в него вебсокеты, event sourcing и полностью сделать его совместимым с настоящими скринкастами. И хотя в профильном issue нет активности с весны, по коммитам видно, что работа кипит. Будет очень интересно посмотреть на стриминговый сервис для воинов консоли, не находите?


На правах рекламы

Подыскиваете VDS для отладки проектов, сервер для разработки и размещения? Вы точно наш клиент 🙂 Посуточная тарификация, создавайте собственный конфиг в несколько кликов.

ссылка на оригинал статьи https://habr.com/ru/company/vdsina/blog/543756/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *