Repository navigation
Sessions ru
M-Commander может пережить закрытие терминала или обрыв ssh, как программа под screen или tmux. Запущенный снова, он возвращает ту же сессию: панели, командную строку, открытые редакторы, копирование в фоне.
Это делает плагин session. Он выключен по умолчанию: кому сессии не нужны,
у того ничего не меняется.
Обычно, если закрыть вкладку терминала или если оборвётся ssh, mc получает SIGHUP и завершается вместе со всем, что было открыто. С включённым плагином mc никогда не работает прямо в терминале пользователя. Процессов три:
- client сидит в терминале пользователя и передаёт ввод и вывод;
- holder держит псевдотерминал mc и unix-сокет сессии, переживает закрытие терминала;
- mc работает на псевдотерминале holder'а и не замечает, что терминал пользователя сменился.
Когда mc запускается в терминале, плагин ещё до инициализации экрана заменяет
процесс на client (/usr/libexec/mcommander/session_helper). Client находит
сессии по сокетам в $XDG_RUNTIME_DIR/mc6/sessions/, а если такого каталога
нет, в $TMPDIR/mc6-sessions-UID/. Дальше он подключается к сессии или
запускает новую. Поскольку у mc собственный псевдотерминал, после
переподключения у программ, запущенных из mc, есть /dev/tty.
Вложенных сессий нет: mc, запущенный внутри сессии, свою сессию не заводит.
Ядро mc о сессиях не знает. Плагин пользуется общими сервисами, которые годятся и другим runtime-плагинам:
- ранняя фаза до инициализации терминала;
- слежение за дескриптором в главном цикле;
- временная отдача терминала;
- выход, как по F10, если ничего не открыто;
- пункты меню;
- флаг "выключен, пока не включат".
При подключении нового терминала mc заново спрашивает у него возможности (цвета, клавиатура, графика) и полностью перерисовывает экран.
Новый терминал приносит с собой переменные SSH_AUTH_SOCK, SSH_AGENT_PID,
DISPLAY, WAYLAND_DISPLAY, DBUS_SESSION_BUS_ADDRESS, XAUTHORITY,
SSH_CONNECTION, SSH_CLIENT. Программы, которые mc запускает после этого,
получают новые значения.
Оболочка командной строки запущена раньше и держит старое окружение, кроме
агента. В сессии SSH_AUTH_SOCK указывает на ссылку <id>.agent рядом с
сокетом, и holder при каждом подключении перенаправляет её на агента нового
терминала. Поэтому git push из командной строки работает и после
переподключения.
- Options, Manage plugins.
- Включить строку Sessions, сохранить.
- Выйти и запустить mc снова: плагин начинает работать со следующего запуска.
При сборке из исходников плагин собирается по умолчанию;
./configure --disable-session-plugin его выключает.
Свободная сессия - это detached (в ней никого нет) или looks lost (её терминал
10 секунд не забирает вывод, как бывает за мёртвым ssh). Считаются только
сессии с тем же TERM.
| Сессии | Что делает mc |
|---|---|
| свободных нет | сразу запускает новую сессию |
| одна, detached | сразу подключается к ней |
| две и больше, или есть looks lost | показывает список, в нём видны и занятые |
M-Commander sessions
1 detached /home/user/src
2 attached, looks lost /home/user
Enter new session
k N end session N
r refresh
q shell
Number to take, Enter, k N, r or q:
-
N: взять сессию. Занятую другим терминалом mc берёт после вопроса y/N, looks lost забирает без вопроса. -
Enterилиn: новая сессия. -
k N: закрыть mc в сессии N, как по F10. Если там открыт редактор, просмотрщик или диалог, mc отказывается. Если после этого свободных сессий не осталось, сразу запускается новая. -
r: перечитать список. -
q: вернуться в shell, сессии остаются.
Сессия не заводится:
- на Linux console;
- в
mcedit6,mviewиmdiff, запущенных отдельно; - в mc, запущенном внутри сессии;
- когда stdin или stdout не терминал.
Внутри сессии в меню Command (F9, Command) есть пункт Sessions.... Он открывает диалог со всеми сессиями; текущая показана как "this one", курсор стоит на первой другой.
- Switch: перейти в выбранную сессию в этом терминале, текущая остаётся detached.
- New: новая сессия в этом терминале, текущая остаётся detached.
-
End: закрыть выбранную сессию, как
k. Текущую закрывают по F10. - Detach: вернуться в shell, сессия остаётся.
Терминал, у которого забрали сессию, возвращается в shell с сообщением
[the session was taken by another terminal], режимы mc в нём (мышь,
win32-input, kitty-клавиатура, альтернативный экран) выключены.
В каталоге сборки (нужен python3):
make -C tests/misc check SUBDIRS= TESTS=session.py
cat tests/misc/session.py.log17 шагов в псевдотерминалах:
- плагин выключен по умолчанию;
- сессия переживает закрытие терминала;
- подключение без списка;
- размер окна;
-
/dev/tty; - агент и
DISPLAY; - Detach;
- терминал, который не читает вывод;
- looks lost;
- сброс режимов у вытесненного терминала;
- диалог: New, Switch, End, Detach;
-
kс открытым диалогом и без; -
q.
Выключен по умолчанию. Без включения в Manage plugins запустить mc, закрыть вкладку. Ожидается: mc завершается вместе с терминалом, в меню Command нет Sessions...
Закрытие вкладки. В mc открыть файл в редакторе (F4), закрыть вкладку терминала крестиком. Открыть новую вкладку, запустить mc. Ожидается: mc сразу возвращается с открытым редактором, без списка и без чёрного экрана.
Обрыв ssh. Зайти по ssh, запустить mc, оборвать соединение (убить ssh на своей стороне или отключить сеть). Зайти снова, запустить mc. Ожидается: если сервер уже заметил обрыв, сразу та же сессия. Если старая сессия ещё числится attached, запускается новая, а старую можно забрать через Sessions..., Switch (с вопросом). Если mc в старой сессии что-то выводил, она видна как looks lost, и в списке её забирают без вопроса.
Агент ssh. Зайти с ssh -A, запустить mc, отключиться, зайти снова с
ssh -A, вернуться в сессию. В командной строке mc выполнить ssh-add -l или
git fetch по ssh.
Ожидается: агент нового подключения виден.
Две сессии и список. Сделать две detached-сессии (Sessions..., New, потом
Sessions..., Detach). Запустить mc.
Ожидается: список из двух сессий; номер берёт сессию; k 1 закрывает первую,
и список остаётся со второй; второй k 1 закрывает последнюю, и сразу
запускается новая.
Нельзя закрыть несохранённое. В сессии открыть редактор или диалог (F7),
отсоединиться. Из другого терминала k N или End в диалоге.
Ожидается: отказ с сообщением, сессия цела.
Забрать занятую сессию. mc в терминале A. В терминале B: Sessions..., Switch на сессию A, ответить Yes. Ожидается: сессия переходит в B; в A печатается сообщение, shell в A работает нормально, без мусора от клавиш. В Windows Terminal это заодно проверка, что режим win32-input выключен.
Разные размеры окна. Вернуться в сессию из окна другого размера. Ожидается: экран сразу перерисован под новый размер.
Фоновое копирование. Запустить большое копирование в фоне (F5, Background), закрыть терминал, через минуту вернуться. Ожидается: копирование шло всё это время.
Где сессии нет. Linux console, mcedit6 и mview, mc внутри сессии (из
её командной строки), mc со stdin не из терминала.
Ожидается: mc работает как без плагина.
- В окне в 24 строки меню Command не помещается на экран, а меню mc не прокручиваются, так что Sessions... (последний пункт) не достать. Нужно окно от 25 строк.
- Сессию looks lost mc при старте сам не забирает: её терминал может быть просто медленным.
- Сессию с другим
TERMвзять нельзя. - Свежезапущенный mc около 1-2 секунд опрашивает терминал; клавиши, нажатые в это время, теряются.
- Раздел о сессиях в man есть пока только на английском.
Желание, чтобы mc переживал потерю терминала, пришло из PR #377 (unxed), который повторял "immortal" режим far2l. Устроено здесь иначе, по образцу screen и dtach; разница описана в PR ветки.