Команда screen

Расскажу, пожалуй, еще об одной очень нужной и полезной, с моей точки зрения, команде, которая сильно облегчает жизнь при удаленной работе с устройствами под управлением Linux. Речь пойдет о screen.

Немного о том, как состоялось мое знакомство с этой командой. В то время я только начинал осваивать удаленное управление моими домашними железками, работающими под управлением Linux - сервером на базе нетбука Toshiba и двумя домашними сетевыми накопителями семейства MyBookLive. Громкое определение "управление" сводилось, как правило, к подкладыванию torrent файлов демону transmission и копированием уже скачанных этим демоном файлов на домашние NAS-ы. Казалось бы, что может быть проще: вошел по SSH на сервер и, при помощи midnight commander или scp, копируешь нужные файлы. На самом деле, в этих несложных, в общем-то, манипуляциях, меня поджидало две неприятности.

Первая была чисто техническая: на моем сервере, работающем под Debian Wheezy, а потом Jessie, что-то было не так с сетевыми драйверами. Точнее, я подозреваю, что драйвера были лишь частью проблемы; свою лепту, скорее всего, вносили еще BarracudaDrive (теперь это FuguHub) и VPN сервер, работающие на сервере. А может, и само железо было не без изьяна, хотя...

Суть неприятности, собственно, заключалась в том, что сетевое соединение, неважно, проводное или WiFi (именно поэтому в вину hardware верилось с трудом - обычно "глючит" что-то одно), в какой-то момент просто отваливалось. Причем, предсказать и объяснить "отваливание" было довольно сложно, но одно можно было утверждать смело: под нагрузкой оно происходило чаще, и WiFi, как ни странно, обладал большей надежностью, нежели витая пара. Надо признаться, что причин этой проблемы я так и не выявил, чему немало способствовали факты непредсказуемости и редкости ее возникновения (с WiFi это случалось от нескольких раз в месяц до пары раз в полгода), а потому, воспроизвести ее по требованию было просто невозможно. Как результат, если такое случалось, я просто переподключал WiFi на нетбуке, или, если был в это время, например, на работе, просил это сделать своих домочадцев.

Вторая проблема заключалась, скажем так, в моих особенностях, как пользователя. Эти особенности находят свое отражение, в частности, в том, что я не очень-то жалую командную строку и, где только возможно, пытаюсь использовать различные оболочки. В случае с копированием больших файлов это приводит к драматическим потерям времени: кто пробовал копировать файлы между устройствами при помощи midnight commander, тот понимает, что я имею в виду. И, хотя, как говорят, есть три вещи, на которые можно смотреть бесконечно: как бежит вода, как танцует пламя и как движется ползунок, отображающий процесс скачивания торрента (с чем я, в принципе, согласен), но смотреть на процесс копирования файлов в midnight commander , особенно ту его часть, которая связана не с ползунком, а с отсчетом скопированных и проверенных байт... Раздражение - это самая безобидная эмоция, посещавшая меня в такие моменты, и, кроме того, всегда возникало жгучее желание именно в это время занятся чем-то другим, более полезным, чем просто ожидание.

К сожалению, проблемы имеют такое нехорошее свойство - сходиться вместе. Когда это (отваливание сети) происходит в конце копирования большого файла при помощи midnight commander, то просто хочется рвать и метать - разрыв связи означает прерывание SSH соединения, и, как следствие, необходимости копировать файл по новой. Чтобы обезопасить себя от таких нежелательных последствий, я решил поискать какой-нибудь способ, который бы позволил завершиться производимому действию, вне зависимости от того, активно ли SSH соединение, или нет.

Для меня было ясно, что надо копать в сторону использования другого потока, сессии и так далее. И первым опробованным решением было фоновое копирование в самом midnight commander. Не буду сейчас подробно рассказывать все перепетии этого процесса, отмечу лишь, что довольно быстро я осознал необходимость продолжения поиска более приемлемого решения. И оно было найдено - команда screen.

Что же это за зверь такой? Всезнающая wiki дает на этот вопрос немного непонятный ответ: консольный мультиплексор. Но если почитать дальше, то становится понятным употребление термина "мультиплексор" - речь идет о возможности использовать в одном терминальном окне нескольких виртуальных консолей, с такой дополнительной функциональностью, как "отсоединение" и “воссоединение" сессий. Если отвлечься от высокой теории, и опуститься на землю, то, на практике, это все означает, что можно одновременно использовать несколько консольных приложений, а также, что можно разорвать связь между запущенным консольным приложением и сессией, это приложение запустившей. Как результат, можно закрыть удаленное соединение, а запущенные приложения продолжат свою работу. А это именно то, что мне требовалось! Ну а теперь по порядку - что, да как.

Начнем с того, что эта утилита может быть изначально установлена в вашей системе, но, в моем случае (Debian Wheezy), пришлось ставить ее самостоятельно

apt-get install screen

Не стоит забывать, что при установке надо иметь права "суперпользователя". Так, если вспомнить команду su, то команду на установку можно записать примерно так:

su -c "apt-get install screen" -

С результатом можно ознакомиться на скриншоте:

После установки можно сразу начать использовать эту утилиту. Причем, для этого совершенно не надо обладать правами администратора системы. Простейший способ запустить команду - просто набрать в командной строке screen. В результате выполнения этой команды будет создана сессия screen и в этой сессии - новая виртуальная консоль . При этом, она займет окно терминала полностью и в ней отобразится лицензионная информация о самой screen.

Все, что вы будете делать, все программы и команды, которые вы будете запускать - все будет работать в этой виртуальной консоли (и, соответственно, в сессии screen). Наверное, единственным исключением является сама команда screen - будучи запущенной в виртуальной консоли без параметров, она создаст новую виртуальную консоль в той же сессии screen.

Что делать, если вы захотите завершить работу виртуальной консоли? Как это часто бывает, для этого можно использовать команду exit. При этом, если вы закрываете последнюю используемую виртуальную консоль сессии (в нашем примере так и есть), то закрыта будет и сама сессия

Надо сказать, что в таком режиме использовать screen вроде как нет никакого смысла - ну что такого особенного в том, чтобы открыть, немного поработать и закрыть виртуальную консоль. Может оно и так, но если вы, скажем, работаете удаленно, и произошло что-то нехорошее, например, обрыв связи, то сессия screen все равно останется "жива"! И в нее можно будет вернуться после восстановления соединения! Но об этом - чуть позже. Сейчас продолжим играться с самой командой screen.

Попробуем запустить в такой консоли какой-нибудь долгоиграющий процесс, а самим вернуться в терминальное окно, и продолжить заниматься обычными каждодневными делами. Как это сделать? Да проще некуда. Давайте снова запустим screen и выполним в нем, например, такую команду:

ping 8.8.8.8

Нет, я, конечно, мог предложить действительно скачать какой-нибудь большой файл, например:

wget https://cdimage.debian.org/cdimage/archive/8.11.0/amd64/iso-cd/debian-8.11.0-amd64-CD-1.iso

Но оно вам надо? Нужно место на диске, потом удалять файл... ping значительно "безобиднее".

ping, запущенный без параметров, выполняется до тех пор, пока вы его не прервете при помощи, скажем, комбинации клавиш Ctrl+C. А до тех пор, вы обречены наблюдать время отклика "пингуемого" сайта. Но, не в этот раз. Хотя, конечно, возникает вопрос: а что, собственно, и, главное, как - можно сделать? Куда вводить команды? На самом деле, все довольно просто - командой screen можно управлять при помощи специальных комбинаций клавиш.

Для перехода в режим управления screen используется комбинация клавиш Ctrl+A. Набирается она следующим образом: нажимается и удерживается клавиша Ctrl, нажимается клавиша А (не в смысле "заглавная буква А" а просто клавиша, обозначенная как английская буква A), клавиши отпускаются. После этого оказывается включен режим управления командой screen и следующая нажатая (и отпущенная) клавиша приведет к выполнению какого-нибудь действия. Например, если после ввода комбинации Ctrl+A нажать клавишу ? (в дальнейшем, такие комбинации будем записывать так: Ctrl+A ?), то будет выведен экран помощи по команде screen.

Давайте внимательно посмотрим на этот экран и запомним несколько комбинаций, скажем, Ctrl+A c (эта комбинация помечена, как screen), Ctrl+A n (помечена, как next), Ctrl+A p (помечена, как prev) и Ctrl+A w (помечена, как windows). Запомнили? Теперь, давайте немного поэксперементируем. И начнем, пожалуй, с комбинацииCtrl+A c - просто задействуем ее, пока на экране нашей виртуальной консоли все бежит и бежит результат отклика сервера DNS от Google (8.8.8.8 - это один из серверов Google). Если все сделано правильно, вы должны увидеть перед собой пустую консоль, в которой можно ввести какую-нибудь команду. Это вторая созданная нами виртуальная консоль screen, причем работает она в той же сессии, что и первая. Такого же эффекта мы бы добились, если бы в командной строке виртуальной консоли выполнили команду screen (конечно, если бы могли воспользоваться командной строкой).

Что бы нам такое сделать с этой второй виртуальной консолью? Не будем оригинальничать и "запингуем" другой DNS сервер от Google - 8.8.4.4:

Теперь мы знаем время отклика и от этого сервера Google. Но, стоп! А это время лучше или хуже? Для ответа на этот вопрос внимательно смотрим на время отклика от 8.8.4.4, запоминаем его, после чего применяем комбинацию Ctrl+A p.

Если вам кажется, что ничего не изменилось, то либо вы чуточку невнимательны, либо вы не совсем правильно воспользовались управляющей комбинацией клавиш. Если же эти предположения к вам не относятся, то, присмотревшись, вы увидите, что теперь перед вами время отклика от сервера 8.8.8.8! То есть, комбинация клавиш Ctrl+A p вернула нас в предыдущую виртуальную консоль screen. Ну что, сравнили время отклика? Нет? Забыли? Не беда, воспользуемся управляющей комбинацией Ctrl+A n и освежим свою память - перед нами виртуальная консоль в результатами ping до сервера 8.8.4.4, то есть, мы переключились на следующую виртуальную консоль screen.

Теперь посмотрим, что делает управляющая комбинация Ctrl+A w

Мы видим, что в левом нижнем углу появилось перечисление работающих виртуальных консолей: одна консоль - под логическим номером 0, другая - под номером 1. То есть, комбинация Ctrl+A w выводит список виртуальных консолей, которые вы успели запустить к этому моменту в сессии screen. Ну а сами логические номера консолей можно использовать для того, чтобы переключаться между ними. Для этого надо будет воспользоваться комбинацией вида Ctrl+A номер_консоли, где номер_консоли - цифры от 0 до 9, обозначающие логический номер виртуальной консоли.

Итак, мы находимся в одной из запущенных нами виртуальных консолей. Возникает вопрос: а можем мы оказаться в обычном терминальном окне, оставив при этом работать и саму сессию и ее виртуальные консоли? И ответ довольно предсказуем: да! Для этого надо отключиться от сессии, или, другими словами, отсоединиться от нее, для чего можно использовать комбинацию Ctrl+A d в любой виртуальной консоли, принадлежащей сессии. Задействовав ее, мы окажемся в обычном терминальном окне.

Надо заметить, в обычном терминальном окне управляющие комбинации команды screen не действуют. Сюрприз, не правда ли? Тем временем, у нас, где-то, работают две виртуальных консоли (в рамках запущенной сессии screen). И что нам делать, чтобы снова, каким-то волшебным способом, к ним подключиться? К счастью, у команды screen имеется некоторый набор опций (или ключей) командной строки, часть из которых позволят нам решить нашу задачу - вернуться обратно в виртуальные консоли.

Во-первых, нам нужно посмотреть какую-нибудь информацию о запущенных сессиях команды screen. Сделать это можно при помощи команды screen -ls (допустимо использовать и более развернутый синтаксис команды - screen -list). В ответ, нам будет выдан список запущенных сессий (или сеансов, кому как больше нравится):

По каждой сессии screen выдается следующая информация: идентификационная строка, дата/время создания сессии и ее статус. Строка-идентификатор сессии выдается в формате pid.tty.host. Она состоит из следующих элементов: pid - идентификатор запущенного процесса, tty - название терминала, host - имя хоста. Иногда, когда, например, при помощи команды screen -S имя_сессии, создаются так называемые именованные сессии (или уже существующей сессии задают/изменяют имя при помощи управляющей комбинации клавиш Ctrl+A :sessionname name), вместо tty.host выводится имя соответствующего сеанса.

С датой и временем создания сессии вопросов возникнуть не должно. Немного по статусу (или состоянию) сессии:

  • Если указаноDetached, то сессия работает в "отсоединенном" режиме, то есть, отвязана от какого бы то ни было терминального окна (например, была использована управляющая комбинация клавиш Ctrl+A d). Такие сеансы можно возобновить с помощью команды screen -r.
  • Если указано Attached, то сессия работает и "привязана" к какому-то терминальному окну (такие окна иногда называют " управляющими").
  • Если сеанс работает в многопользовательском режиме, он помечается как Multi.
  • Сеансы, отмеченные как Unreachable, либо "живут" на другом хосте, либо "мертвы". Недоступный сеанс считается "мертвым", когда его имя совпадает либо с именем локального хоста, либо со специальным, ранее указанным, параметром. "Мертвые" виртуальные консоли могут быть удалены при помощи команды screen -wipe, но, конечно, вы должны быть уверенными в том, что вы делаете.

Итак, мы видим, что есть "отсоединенная" сессия. Для того, чтобы вернуться в виртуальную консоль этой сессии можно использовать команду screen -r идентификатор_сессии. В качестве параметра идентификатор_сессии можно указать либо всю идентификационную строку целиком, либо ее часть. У меня получалось подключаться и по целой строке, и по значению pid, и по значению tty.host, и только по значению tty. Примеры:

screen -r 23236
screen -r 23236.pts-0.debian
screen -r pts-0.debian
screen -r pts-0

Если необходимо подключиться к именованной сессии, то, в качестве еще одной альтернативы, можно указать имя нужной сессии:

screen -r test

При этом я заметил, что если в сессии есть несколько открытых виртуальных консолей, то возвращаешься в ту же виртуальную консоль, которая была активна на момент отсоединения от сессии при помощи, например, комбинации клавиш Ctrl+A d.

На самом деле, у screen есть масса возможностей: можно, например, разделить окно терминала между несколькими виртуальными консолями, можно не просто создать сессию, но и сразу запустить в ней нужную команду, можно даже указать, чтобы созданная сессия с запущенным приложением сразу "отсоединилась". Можно даже попытаться изменить стандартное поведение screen - для этого есть специальные файлы: ~/.screenrc и /etc/screenrc. Я не буду подробно рассказывать про все эти возможности, в конце концов, можно и документацию почитать, да и в сети полно разнообразных материалов по этой теме. Но несколько примеров запуска screen я, все-таки, приведу: просто потому, что документация - документацией, это, так сказать, теория, а практика - это наглядная иллюстрация того, как можно пользоваться знаниями, полученными в результате изучения теории, и эта наглядность позволяет быстрее и проще понимать теорию, облегчая ее применение на практике... фуф...

Чуть выше я упоминал "именованные" сессии. Работать с ними довольно удобно - можно давать вполне осмысленные имена, которые и проще запомнить и, следовательно, проще использовать. Задать имя сессии можно при ее создании:

screen -S test

Эта команда создаст новую сессию с незамысловатым именем test.

А вот так можно сразу еще и команду какую-нибудь запустить:

screen -S ping ping 8.8.8.8

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

screen -dmS ping ping 8.8.8.8

то будет создана новая сессия с именем ping, в виртуальной консоли которой будет запущена команда ping 8.8.8.8 и кроме всего этого - будет произведено отключение от этой сессии. Но все можно повернуть и чуть-чуть иначе:

screen -dR ping ping 8.8.8.8

Эта команда попробует заново подсоединиться к сессии с именем ping, а если таковой нет, то она будет создана, после чего в ней будет запущена команда ping и произведено отключение. А еще можно подключиться к сессии, которая выполняется в другом терминальном окне, для чего следует использовать ключ x:

screen -x ping

Такое может потребоваться, например, при неожиданном обрыве связи в процессе удаленного управления. Кстати, другой пользователь, работающий под такой же учетной записью, как и вы[1], может выполнить эту же команду и вы оба окажетесь в одной виртуальной консоли сессии screen. Получится "многопользовательская" консоль. На самом деле, можно все устроить таким образом, чтобы к виртуальной консоли мог подключиться пользователь, работающий и под другой учетной записью, но для этого надо делать специальные манипуляции.

Теперь представим, что мы очень часто выполняем команду screen и нам порядком надоело лицезреть стартовый экран. Для того, чтобы избавиться от него, надо в конфигурационный файл команды screen добавить строку:

startup_message off

Сделать это можно при помощи любого текстового редактора. Причем, если произвести это изменение в файле ~/.screenrc (в домашнем каталоге текущего пользователя), то стартовый экран перестанет появляться при запуске screen под этим пользователем. Если же модифицировать файл /etc/screenrc, то произведенное редактирование получит статус "system wide", то есть, затронет всех пользователей системы.

Такие примеры можно продолжать приводить довольно долго. Но пора и честь знать, и так получилось довольно длинное повествование. Напоследок хочу отметить, что удаленное управление (по ssh, например) - не единственная область деятельности администратора (да и простого пользователя), когда команда screen приходит, что называется, на выручку. Можно еще вспомнить, что с ее помощью легко эмулируется режим демона, то есть, можно запускать в фоне задачи, которые не могут быть запущены в качестве демона, по причине, скажем, наличия пользовательского интерфейса. Очень часто так запускают rtorrent, например. Да и это не последняя возможность применения команды screen. Так что, дерзайте...


  1. обратите внимание, я не пишу "под вашей учетной записью", а "под такой же учетной записью" - передавать данные своей учетной записи какому-то другому пользователю я бы не советовал, а вот пользоваться специально созданной "общей" учеткой - вполне нормально, особенно если не оставлять свои конфиденциальные данные ↩︎