Почему команды умирают вместе с соединением
Когда вы подключаетесь к серверу по SSH и запускаете команду, она работает внутри терминального сеанса. Если соединение пропало, например из-за нестабильной сети или закрытой крышки ноутбука, сервер закрывает сеанс и посылает его процессам сигнал о разрыве. Большинство программ на этот сигнал завершаются. Долгая загрузка, архивация или обновление прерывается на середине, иногда с неприятными последствиями.
Решение — отделить работу от соединения. Терминальные мультиплексоры tmux и screen запускают на сервере собственный постоянный сеанс. Вы входите в него, как в окно, запускаете команды, а при обрыве связи сеанс продолжает жить и работать. Потом вы подключаетесь снова и «присоединяетесь» к нему, видя всё, что произошло.
Есть и более простые варианты вроде nohup и запуска в фоне, но они не позволяют вернуться в интерактивный сеанс и посмотреть вывод так, как он выглядел. Мультиплексор удобнее, когда команда может задавать вопросы или нужно наблюдать за ходом выполнения.
Программы не всегда установлены на сервере по умолчанию. Установить их можно штатным менеджером пакетов вашей системы, как показано на странице про apt.
tmux: основной сценарий за пять шагов
Работа с tmux строится вокруг трёх понятий: сессия, окно и панель. Для начала достаточно сессий.
- Подключитесь к серверу и создайте именованную сессию: tmux new -s работа. Имя поможет не путаться.
- Запустите в ней нужную долгую команду.
- Отсоединитесь, не прерывая работу: нажмите Ctrl+b, затем отпустите и нажмите d. Вы окажетесь в обычном терминале, а сессия продолжит работать.
- Позже, после нового подключения по SSH, посмотрите список: tmux ls.
- Вернитесь в сессию: tmux attach -t работа.
Если закрыть окно терминала на вашем компьютере или потерять связь, не отсоединившись, сессия всё равно остаётся на сервере: вы просто присоединяетесь к ней заново теми же командами. Чтобы завершить сессию окончательно, выйдите из оболочки внутри неё командой exit; когда закроется последняя оболочка, сессия исчезнет. Принудительно завершить сессию можно командой tmux kill-session -t работа, но внутри неё могут быть работающие задачи, поэтому проверьте, что вы закрываете нужную.
screen: те же действия другими командами
Программа screen старше tmux, и на некоторых серверах присутствует именно она. Принцип тот же, различаются команды и клавиши. Ниже сопоставление.
| Действие | tmux | screen |
|---|---|---|
| создать именованную сессию | tmux new -s имя | screen -S имя |
| отсоединиться | Ctrl+b, затем d | Ctrl+a, затем d |
| список сессий | tmux ls | screen -ls |
| присоединиться | tmux attach -t имя | screen -r имя |
| закрыть сессию | exit внутри | exit внутри |
Если у screen в списке есть сессия со статусом Attached, а вы не можете подключиться из нового окна, используйте screen -d -r имя: она отсоединит прежнее подключение и присоединит вас. В tmux похожее действие выполняет tmux attach -d -t имя.
Какой из двух инструментов выбрать, вопрос привычки. Если на вашем сервере уже есть один из них, пользуйтесь им и не устанавливайте второй без причины. Для начинающих набор действий в обоих случаях почти одинаков: создать, отсоединиться, вернуться.
Окна, панели и копирование текста
Когда базовый сценарий освоен, tmux предлагает полезные добавки. Сочетания клавиш начинаются с префикса Ctrl+b, после которого нажимают нужную клавишу. Самые употребимые:
- c — создать новое окно внутри сессии;
- n и p — следующее и предыдущее окно, цифры переключают на окно по номеру;
- % и двойная кавычка — разделить окно на панели по вертикали и по горизонтали;
- стрелки — перейти в соседнюю панель;
- [ — режим прокрутки и копирования, выход клавишей q.
Прокрутка вывода в tmux работает не колесом мыши по умолчанию, а через режим копирования, и это вызывает недоумение у новичков. Включить поддержку мыши можно в файле настроек ~/.tmux.conf. Подробности параметров и их названия проверяйте в справке man tmux, так как они менялись между версиями.
Полезный приём — держать в одной сессии два окна: в одном выполняется длинная задача, в другом вы следите за журналом и нагрузкой. Так удобно наблюдать за системой, не прерывая работу.
Ограничения и частые вопросы
Мультиплексор спасает от обрыва связи, но не от перезагрузки сервера. Если сервер перезапустился, все сеансы, включая tmux и screen, пропадают вместе с запущенными задачами. Для работы, которая должна пережить перезагрузку, нужны службы системы: они описаны на странице про systemctl.
Ещё несколько замечаний:
- не запускайте в сессии то, что должно работать годами: для этого лучше подходит служба с автоперезапуском;
- сохраняйте вывод длительных задач в файл, добавив перенаправление, чтобы он не потерялся при переполнении буфера прокрутки;
- сессия принадлежит пользователю: другой пользователь системы её не увидит, а вы, подключившись под другим именем, увидите другой список;
- на общем сервере не оставляйте открытыми сессии с паролями и ключами в истории: чужой администратор может присоединиться к вашему сеансу.
Если вы не уверены, существует ли сессия, выполните tmux ls или screen -ls. Сообщение об отсутствии сессий означает, что их нет: возможно, сервер был перезапущен или сессия завершилась сама, когда закончилась программа внутри.
Сопутствующие приёмы: nohup и настройка соединения
Если мультиплексора на сервере нет и поставить его нельзя, для простых случаев подойдёт nohup. Команда nohup запускает программу так, что она игнорирует сигнал о разрыве терминала, а вывод по умолчанию записывается в файл nohup.out. Запись команда nohup имя > файл 2>&1 & направляет вывод в нужный файл и отправляет программу в фон. Вернуться к такой задаче как к интерактивному сеансу нельзя, зато посмотреть журнал и проверить, жив ли процесс, можно командами tail и ps.
Чтобы соединение рвалось реже, помогают настройки ssh: параметры ServerAliveInterval и ServerAliveCountMax в файле ~/.ssh/config на вашем компьютере заставляют программу периодически посылать служебные пакеты и замечать обрыв. Точные значения подбирайте по ситуации и проверяйте в справке man ssh_config. Эти параметры не заменяют мультиплексор, а лишь уменьшают число случайных разрывов, например при простое за маршрутизатором, который закрывает неактивные соединения.