:title: Терминальные мультиплексоры :date: 19 Oct 22 =========================== Терминальные мультиплексоры =========================== Терминальный мультиплексор — это утилита, которая позволяет запускать несколько сессий оболочки в рамках одной сессии и также отсоединять собственную сессию от оболочки. Для пояснения зачем это нужно я процитирую русскую Википедию: Это полезно для работы с несколькими программами из командной строки, а также для запуска программ на удаленном сервере. Возможно звучит сложно, но всё проще чем кажется. В этой заметке я попробую наглядно объяснить концепцию и приёмы работы с мультиплексорами терминала. Сейчас распространено два мультиплексора терминала: * `GNU screen `_ * `tmux `_ Рано или поздно вы с одним из них столкнётесь. Матчасть ======== Вот основные концепции, которые использются в упомянутых утилитах. Сессия Непосредственно сессия мультиплексора терминала. Сессий может быть множество, их можно создавать, закрывать, отсоединяться от них или присоединяться, задать имя. Окно В любой сессии мультиплекcора есть как минимум одно окно. Если закрыть последнее окно, то закроется вся сессия. В каждом окне запускается новая сессия командной оболочки (Bash, Zsh и пр.). Окон также может быть множество. К ним применимы те же действия, что и к сессиям, кроме отсоединения. Между окнами можно переключаться с помощью горячих клавиш. Область экрана (или панель) Каждое окно можно разбить на несколько областей. В каждой области будет запущена новая сессия оболочки. Делить окно можно по вертикали и горизонтали. Размеры областей обычно можно отрегулировать. По умолчанию экран делится пополам. Здесь надо отметить, что в **screen** понятия окно и область экрана смешаны. То есть область экрана приравнивается к отдельному окну, хотя они и отображаются на одном экране. Итак, я подключаюсь к серверу по SSH с целью запустить там какую-то команду. После запуска команды я намерен отключиться от сервера. При этом команда должна продолжить выполняться. Я также должен увидеть результат её выполнения, когда вновь подключусь к серверу. **1.** Подключаюсь по SSH: .. code-block:: text localhost server +------------+ +------------------+ | ssh_client |----->| ssh_session | +------------+ +------------------+ (you are here)----->| shell_session(0) | +------------------+ После успешного подключения по SSH я окажусь в сессии оболочки — **(0)**. При этом если оборвётся SSH-сессия, то я потеряю всё что в ней было. **2.** Как только я запущу **screen** картинка примет следующий вид: .. code-block:: text localhost server +------------+ +------------------+ | ssh_client |----->| ssh_session | +------------+ +------------------+ | shell_session(0) | +------------------+ | screen_session | +------------------+ (you are here)----->| shell_session(1) | +------------------+ **3.** Для примера запущу **vim**: .. code-block:: text localhost server +------------+ +------------------+ | ssh_client |----->| ssh_session | +------------+ +------------------+ | shell_session(0) | +------------------+ | screen_session | +------------------+ (you are here)----->| shell_session(1) | +------------------+ | vim | +------------------+ **4.** Теперь я отключусь (detach) от сессии **screen**: .. code-block:: text localhost server +------------+ +------------------+ +------------------+ | ssh_client |----->| ssh_session | | screen_session | +------------+ +------------------+ +------------------+ (you are here)----->| shell_session(0) | | shell_session(1) | +------------------+ +------------------+ | vim | +------------------+ Сессия **screen** отсоединилась от оболочки **(0)**. При этом оболочка **(1)** продолжает работать. Сейчас можно отключиться от SSH. Когда я подключусь к серверу вновь, то окажусть в ситуации как на схеме 4, но после выполнения команды **screen -r** всё вернётся к состоянию как на схеме 3 и я смогу продолжить работу в **vim**. .. admonition:: Как набирать комбинации клавиш Вначале набрается модификатор, например ``Ctrl+a``, затем надо отпустить клавиши и нажать на клавишу команды, например ``?``. screen ====== **screen** просто работает. Он минималистичен и прост в использовании. Запуск новой сессии: .. code-block:: text screen [-S имя_сессии] Подключиться к запущенной сессии: .. code-block:: text screen -r [имя_сессии] =============== ============================================================ Комбинация Действие =============== ============================================================ Ctrl+a ? Показать справку Ctrl+a : Открыть приглашение для ввода команд screen Ctrl+a " Список окон Ctrl+a 0 Открыть окно номер 0 Ctrl+a A Переименовать текущее окно Ctrl+a a Отправить комбинацию Ctrl+a в текущее окно Ctrl+a c Создать новое окно (с оболочкой) Ctrl+a S Разделить текущую область по горизонтали Ctrl+a | Разделить текущую область по вертикали Ctrl+a tab Перевести фокус ввода на следующую область Ctrl+a Ctrl+a Переключиться между текущей и предыдущей областью Ctrl+a Esc Перейти в режим копирования (используйте Enter для выделения текста). Также скроллинг терминала. Ctrl+a ] Вставить текст Ctrl+a Q Закрыть все окна, кроме текущего Ctrl+a X Закрыть текущую область Ctrl+a d Отсоединиться от текущей сессии =============== ============================================================ При разделении экрана на области появится новая пустая область. Нужно переключить на неё фокус и запустить новое окно с оболочкой ``Ctrl+a`` ``c``. Конфигурация **screen** хранится в файле **~/.screenrc**. Я для себя написал совсем простой конфиг, который тем не менее показывает всё что действительно нужно. .. code-block:: unixconfig startup_message off hardstatus alwayslastline hardstatus string '%S: %-w%>(%n %t)%{-}%+w%<' .. image:: https://i.nxhs.cloud/Swl.png :alt: Terminal with screen Материалы по **screen**: * `GNU screen usage `_ * `GNU screen - ArchWiki `_ tmux ==== **tmux** — это более новороченное решение. Он умеет почти всё то же что **screen** + имеет дополнительные фичи вроде управления мышью. Запустить новую сессию: .. code-block:: text tmux [new -s имя_сессии] Подключиться к сессии: .. code-block:: text tmux a [-t имя_сессии] =============== ============================================================ Комбинация Действие =============== ============================================================ Ctrl+b c Создать новое окно Ctrl+b , Переименовать окно Ctrl+b w Список окон Ctrl+b " Разделить текущую область по горизотали ctrl+b % Разделить текущую область по вертикали Ctrl+b x Закрыть текущую панель Ctrl+b [ Перейти в режим копирования текста + скроллинг Ctrl+b d Отсоединиться от сессии =============== ============================================================ Мой **~/.tmux.conf**: .. code-block:: unixconfig set -g mouse on set -g history-limit 5000 # vim style controls bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R bind -r H resize-pane -L 10 bind -r J resize-pane -D 10 bind -r K resize-pane -U 10 bind -r L resize-pane -R 10 # Copy / paste bind b list-buffers bind B show-buffer bind P paste-buffer bind-key -T copy-mode-vi v send-keys -X begin-selection bind-key -T copy-mode-vi y send-keys -X copy-selection bind-key -T copy-mode-vi r send-keys -X rectangle-toggle bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel \ "xclip -i -f -selection primary | xclip -i -selection clipboard"