Ситуация, в которой терминала не хватает

Вы запускаете в терминале долгую команду. Например, она опрашивает что-то раз в пару секунд и печатает результат на экран, а вы в это время хотите открыть второй терминал и посмотреть файл проекта. Никакой проблемы: в Ubuntu можно открыть новое окно терминала или новую вкладку, и работать дальше. Но теперь представьте, что соединение с машиной идёт по SSH. Вы запустили долгую операцию на сервере, и тут сеть моргнула. После обрыва сеанса запущенный процесс может завершиться вместе с ним. Ещё обиднее, когда вы сами случайно закрыли окно, не подумав.

Хочется, чтобы работа в терминале не была привязана к конкретному окну. Чтобы можно было запустить команду, отключиться от неё, заняться другим делом, а потом вернуться и увидеть тот же экран с выводом. Именно эту задачу решает tmux — терминальный мультиплексор. Он запускается как обычная программа внутри терминала, но берёт на себя роль посредника между окном терминала и запускаемыми командами. Окно можно закрыть, а команды продолжат работать внутри tmux. Когда мы снова откроем терминал и подключимся к tmux, мы увидим тот же самый сеанс: тот же вывод, те же процессы, то же состояние.

Слово tmux — сокращение от terminal multiplexer. Программа есть в репозиториях Ubuntu, и для урока она понадобится установленной.

Проверяем установку

Сначала проверим, установлен ли tmux:

tmux -V

Опция -V — это сокращение от version, и заглавная буква здесь важна: строчная -v у tmux имеет другое назначение. Если tmux есть, мы увидим что-то похожее:

tmux 3.4

Номер версии может отличаться. Если же команда не найдена, установим пакет:

sudo apt update
sudo apt install tmux

После установки снова проверим версию. Никакой начальной настройки для этого урока не требуется. Мы работаем с tmux как с чистой программой, без конфигурационного файла.

Три слоя tmux: клиент, сервер, сессия

У tmux есть важная особенность, которую полезно понять с самого начала. Программа не просто открывает новое окно. Она запускает собственный фоновый процесс — сервер tmux. Именно сервер хранит всё, что происходит внутри: открытые сессии, окна, запущенные команды и их вывод. Клиент — это то, что мы видим в терминале. Когда мы вводим команду tmux, запускается клиент, который подключается к серверу и показывает нам его состояние. Если сервера ещё нет, первая команда tmux его создаст.

Внутри сервера живёт одна или несколько сессий. Сессия — это наш рабочий сеанс, у которого есть имя. В нём могут быть окна и панели, но на этом уроке мы ограничимся одной сессией и одним окном, чтобы не перегружать знакомство. Важно различать эти три слова: внутри терминала работает клиент tmux; фоновый процесс, который держит всё состояние, — сервер; именованный рабочий сеанс внутри сервера — сессия.

Когда мы закроем окно терминала, клиент исчезнет, но сервер и сессия останутся. Позже мы откроем новый терминал, запустим клиент заново и подключимся к той же сессии.

Создаём сессию, не задев чужую

Прежде чем создавать сессию, проверим, какие сессии tmux уже запущены:

tmux ls

Команда ls здесь — сокращение от list-sessions. Если сервер только что установлен и мы его ни разу не запускали, вывод будет такой:

no server running on /tmp/tmux-1000/default

Путь может отличаться, но смысл один: сервера нет, значит, и сессий нет. Если же в выводе будут перечислены сессии, не нужно создавать новую с тем же именем и тем более не нужно удалять чужие. Обычно tmux использует отдельный сервер для каждого пользователя. Но в той же учётной записи могут идти другие работы, поэтому существующие сессии не трогаем. В учебной среде скорее всего вывод окажется пустым или сообщит об отсутствии сервера, и мы сможем спокойно двигаться дальше.

Создадим нашу сессию с именем course-work:

tmux new -s course-work

Разберём опции. new — это сокращение от new-session, то есть создать новую сессию. Опция -s задаёт имя сессии, от слова session. Аргумент после неё — само имя. Имя нужно выбирать осмысленно, чтобы потом легко было понять, где что лежит. У нас будет рабочая сессия курса, поэтому course-work.

Сразу после этой команды вид терминала изменится: появится зелёная полоса внизу, а командная строка останется прежней. Полоса — это признак того, что мы теперь видим не просто терминал, а клиент tmux, подключённый к нашей новой сессии. Внутри мы работаем с обычной оболочкой Bash: те же команды, те же пути, то же окружение.

Нам нужно убедиться, что сессия действительно создана и мы можем в ней работать, но сделать это нужно, не выходя из неё. Запомним простое правило: мы пока внутри tmux, и обычные команды выполняет оболочка. Специальные команды tmux мы будем вызывать через префикс, но об этом чуть ниже.

Первая команда внутри tmux

Внутри сессии посмотрим служебную переменную tmux:

echo "$TMUX"

Это не команда tmux, а обычное обращение к переменной окружения. tmux выставляет её для каждой сессии. Вывод содержит путь к сокету, PID сервера tmux и числовой идентификатор сессии, например:

/tmp/tmux-1000/default,12345,0

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

Теперь запустим долгую команду. Она не делает ничего вредного: просто печатает текущее время каждые две секунды, пока мы её не остановим. Выглядит она так:

while true; do date -Is; sleep 2; done

Здесь while true; do начинает бесконечный цикл. Команда date -Is выводит текущую дату и время в формате ISO 8601, той же командой мы пользовались в уроках о расписаниях. sleep 2 приостанавливает цикл на две секунды. done закрывает цикл. В итоге на экран каждые две секунды добавляется новая строка с временем, и цикл сам не закончится — его нужно будет остановить вручную.

Строки начнут появляться одна за другой. Так и должно быть. Команда выполняется прямо сейчас, и экран занят ею. Мы больше не можем вводить другие команды в этом окне: оболочка занята циклом. Но нам и не нужно ничего вводить — сейчас главное увидеть, что сессия работает.

Отключаемся от сессии

Пока цикл продолжает печатать время, отключимся от сессии. Для этого используется особое сочетание клавиш, которое называется префикс. В tmux по умолчанию префикс — это Ctrl+b. Работает он не так, как обычные сочетания вроде Ctrl+C. Сначала нужно нажать Ctrl+b и отпустить, а затем нажать следующую клавишу — саму команду. Клавиши не нужно держать одновременно.

Для отключения от сессии после префикса нажимается латинская буква d, от слова detach — отсоединить. Итак, полная последовательность: нажать и отпустить Ctrl+b, затем нажать d. Никакого подтверждения не будет. Экран вернётся к обычному терминалу, а цикл останется работать внутри tmux. Внешне это выглядит так, будто мы вышли из программы, но это не так: мы оставили сессию работать в фоне и просто закрыли клиент.

Важно не путать detach с остановкой. Цикл продолжит печатать время, но мы этого не видим. tmux хранит текущий экран и ограниченную историю строк. После возвращения мы увидим новый вывод, но tmux не заменяет сохранение полного журнала в файл.

Смотрим на сессию со стороны

Теперь, когда мы снова в обычном терминале, проверим список сессий:

tmux ls

Вывод станет другим. Теперь мы увидим нашу сессию:

course-work: 1 windows (created ...)

Точная дата и время будут вашими. Смысл вывода: у нас есть одна сессия с именем course-work, и в ней одно окно. Сервер tmux при этом продолжает работать в фоне. Мы можем закрыть окно терминала, открыть новое, и сессия останется. Мы даже можем просто продолжить в том же окне — это не имеет значения. Главное, что мы отсоединились, а не уничтожили сессию.

Возвращаемся и останавливаем цикл

Вернёмся внутрь:

tmux attach -t course-work

Опция -t сокращает слово target, цель. Она указывает, к какой сессии подключаться. Можно было написать полную форму attach-session, но attach быстрее. После этой команды снова появится зелёная полоса, а на экране мы увидим уже накопившиеся строки с временем. Их может быть много — цикл не останавливался всё то время, пока нас не было. Это и есть главное свойство tmux: процесс не зависел от открытого терминала.

Остановим цикл так же, как остановили бы любую команду в обычной оболочке: нажмём Ctrl+C. Цикл прервётся, оболочка снова станет доступна, и можно вводить следующие команды. Останавливать нужно именно сам цикл, а не tmux. Убивать сервер tmux для этого не требуется и нежелательно: наша цель — оставить сессию живой для следующего урока.

После Ctrl+C командная строка вернётся. Проверим, что мы всё ещё внутри tmux:

echo "$TMUX"

Переменная должна быть на месте. Это ожидаемо: мы не выходили из сессии, а только остановили одну команду внутри неё.

Оставляем сессию для следующего урока

Теперь нам нужно завершить урок, но сохранить сессию для продолжения. Отключимся тем же способом, что и раньше: Ctrl+b, затем d. Мы снова окажемся в обычном терминале. Проверим список сессий:

tmux ls

Сессия course-work всё ещё на месте. Внутри неё теперь работает обычная оболочка Bash, готовая принимать команды. В следующем уроке мы подключимся к этой же сессии и разберём, как создавать окна и панели.

На этом первый урок с tmux закончен. Мы не удаляем сервер и не убиваем сессию. Не останавливайте весь сервер tmux ради одной учебной команды: это затронуло бы остальные сессии этой учётной записи. Учебная среда должна остаться в том состоянии, к которому мы придём в конце каждого урока, чтобы следующее занятие начиналось с осмысленного продолжения.

tmux решает задачу отвязки работы в терминале от конкретного окна. Он состоит из трёх частей: клиента, который показывает нам экран, сервера, который хранит всё состояние, и сессии — именованного рабочего сеанса внутри сервера. Когда мы закрываем окно терминала, клиент исчезает, но сервер и сессия продолжают работать. Мы создали сессию course-work командой tmux new -s course-work, предварительно проверив через tmux ls, что имя свободно.

Внутри сессии мы запустили бесконечный цикл while true; do date -Is; sleep 2; done, который печатал время каждые две секунды. Пока он работал, мы отключились от сессии сочетанием Ctrl+b и затем d. Цикл продолжил выполняться. Вернувшись через tmux attach -t course-work, мы увидели накопившийся вывод и остановили команду обычным Ctrl+C. После этого сессия осталась работать с обычной оболочкой. В следующем уроке мы подключимся к ней снова и научимся делить экран на окна и панели.

Практика: знакомство с tmux

Мы разобрали, из чего состоит tmux и как устроены сессии: клиент показывает экран, сервер держит состояние, а сессия хранит рабочий сеанс. Теперь проверим это на двух задачах. Сначала разберём ситуацию с отсоединением и остановкой среды, а потом вы сами пройдёте полный круг: создадите свою сессию, отключитесь, вернётесь и оставите её живой.

Detach, завершение и остановка WSL

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

11

В учебной среде WSL в терминале открыта сессия tmux с именем course-work. Внутри неё запущен бесконечный цикл, который печатает время каждые две секунды. Ученик нажал и отпустил Ctrl+b, а затем нажал d. Экран вернулся к обычному терминалу. Команда tmux ls показывает: course-work: 1 windows (created ...). После этого ученик закрыл окно терминала. Какие утверждения верны? Выберите все верные.

Своя сессия: от создания до возврата

Теперь пройдём весь путь самостоятельно, но не в сессии course-work, а в своей. Это позволит потренироваться и не задеть состояние, которое понадобится на следующем занятии.

В учебной среде WSL уже работает сервер tmux, и в нём есть сессия course-work, которую мы создавали на уроке. Трогать её нельзя: она останется для следующего занятия. Также допустим, что в этой же учётной записи могли бы быть и другие сессии, поэтому ни одну чужую сессию мы не удаляем и не переименовываем.

Придумайте своё новое имя для учебной сессии, которого ещё нет (не course-work и не занятое другими). Опишите последовательность команд и нажатий, которая выполняет следующее:

  1. сначала проверяет, какие сессии tmux уже запущены;
  2. создаёт вашу новую сессию с вашим именем;
  3. внутри неё запускает команду, которая печатает строку раз в пару секунд и сама не заканчивается;
  4. отключается от сессии, оставив её и процесс работать;
  5. из обычного терминала убеждается, что ваша сессия есть в списке;
  6. возвращается в неё;
  7. останавливает бесконечный процесс, не завершая саму сессию;
  8. оставляет сессию живой, чтобы к ней можно было вернуться позже.

Сервер tmux убивать нельзя, а также нельзя завершать или трогать сессию course-work и любые другие чужие сессии. Укажите команды так, как вводили бы их в терминале, и коротко поясните, что ожидаете увидеть на каждом шаге. Начинайте из обычной оболочки вне tmux; если $TMUX непустая, сначала отсоединитесь от текущего клиента, не завершая его сессию.

Обсуждение урока

0
Комментарии видны всем. Чтобы участвовать в обсуждении, войдите или зарегистрируйтесь.
Модерация сообщества

Пожаловаться на комментарий

Расскажите модераторам, что именно требует внимания.