nixhacks.net/content/terminal_muxers.rst
2022-10-21 22:29:23 +03:00

254 lines
12 KiB
ReStructuredText
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:title: Терминальные мультиплексоры
:date: 19 Oct 22
===========================
Терминальные мультиплексоры
===========================
Терминальный мультиплексор — это утилита, которая позволяет запускать
несколько сессий оболочки в рамках одной сессии и также отсоединять
собственную сессию от оболочки.
Для пояснения зачем это нужно я процитирую русскую Википедию:
Это полезно для работы с несколькими программами из командной строки, а
также для запуска программ на удаленном сервере.
Возможно звучит сложно, но всё проще чем кажется. В этой заметке я попробую
наглядно объяснить концепцию и приёмы работы с мультиплексорами терминала.
Сейчас распространено два мультиплексора терминала:
* `GNU screen <https://www.gnu.org/software/screen/>`_
* `tmux <https://github.com/tmux/tmux/wiki>`_
Рано или поздно вы с одним из них столкнётесь.
Матчасть
========
Вот основные концепции, которые использются в упомянутых утилитах.
Сессия
Непосредственно сессия мультиплексора терминала. Сессий может быть
множество, их можно создавать, закрывать, отсоединяться от них или
присоединяться, задать имя.
Окно
В любой сессии мультиплек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 <http://gnuscreen.org/>`_
* `GNU screen - ArchWiki <https://wiki.archlinux.org/title/GNU_Screen>`_
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"