INTEGRITY Документация

Подключения терминала

Подключения терминала позволяют браузерным интерфейсам напрямую взаимодействовать с оболочками песочницы. Вместо выполнения отдельных команд с помощью exec(), подключение к терминалу открывает постоянный двунаправленный канал к оболочке bash: та же модель, что используется в SSH или локальном эмуляторе терминала.

Как работают подключения к терминалу

Подключения терминала используют WebSocket для потоковой передачи необработанных байтов между терминалом браузера (например, xterm.js ↗) и процесс псевдотерминала (PTY), выполняющийся внутри контейнера песочницы.

Browser (xterm.js) <-- WebSocket --> Worker <-- proxy --> Container PTY (bash)
  1. Браузер отправляет вашему Worker запрос на обновление соединения до WebSocket
  2. Ваш Worker вызывает sandbox.terminal(request), который проксирует запрос upgrade к контейнеру
  3. Контейнер запускает оболочку bash, подключённую к PTY
  4. Необработанные байты передаются в обе стороны: нажатия клавиш поступают внутрь, а вывод терминала наружу

Это принципиально отличается от exec():

Буферизация вывода

Контейнер буферизует вывод терминала в кольцевом буфере. Когда клиент отключается и подключается заново, сервер воспроизводит буферизованный вывод, поэтому терминал выглядит неизменным. Это означает следующее:

Код на стороне клиента для обработки буферизации не нужен: контейнер делает это прозрачно.

Автоматическое переподключение

Перебои в сети обычны для приложений на основе браузера. Подключения к терминалу справляются с этим за счет буферизации на стороне сервера (описанной выше) и переподключения на стороне клиента с экспоненциальной задержкой.

SandboxAddon для xterm.js реализует это автоматически. При создании собственного клиента вы сами отвечаете за логику переподключения: буферизация на стороне сервера работает независимо от того, какой клиент подключается. См. Справочник по протоколу WebSocket для получения сведений о жизненном цикле соединения.

Терминалы конкретной сессии

Каждый сеанс может иметь собственный терминал с независимым состоянием оболочки:

const devSession = await sandbox.createSession({
	id: "dev",
	cwd: "/workspace/frontend",
	env: { NODE_ENV: "development" },
});

const testSession = await sandbox.createSession({
	id: "test",
	cwd: "/workspace",
	env: { NODE_ENV: "test" },
});

// Each session's terminal has its own working directory,
// environment variables, and command history

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

Протокол WebSocket

Подключения терминала используют двоичные кадры WebSocket для ввода-вывода терминала (для производительности) и текстовые кадры JSON для управляющих сообщений и сообщений о состоянии (для структурированности). Это обеспечивает быструю передачу данных и одновременно позволяет вести структурированный обмен данными для таких операций, как изменение размера терминала.

Полную спецификацию протокола, включая жизненный цикл соединения и форматы сообщений, см. в Справочник Terminal API.

Когда использовать терминалы, а когда команды

Сценарий использования Подход
Выполнение команды и получение результата exec() или execStream()
Интерактивная оболочка для конечных пользователей terminal()
Долго выполняющийся процесс с выводом в реальном времени startProcess() + streamProcessLogs()
Совместный доступ к терминалу terminal() с общей сессией