Назад | Перейти на главную страницу

screen -R не работает с ssh

У меня в офисе стоит Linux, и я хочу подключиться к нему по ssh с Macbook дома. Я не могу достучаться до коробки непосредственно через порт 22, но у меня есть туннель порта, прибитый между localhost: 23001 и портом 22 на удаленном Linux-сервере. Это работает для обычного сеанса ssh:

$ ssh -t -2 -A -p 23001 roysmith@127.0.0.1

Следующий шаг - я хочу автоматически запускать сеанс терминала внутри сеанса экрана. Это почти работает:

$ ssh -t -2 -A -p 23001 roysmith@127.0.0.1  screen -R

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

$ ssh -t -2 -A -p 23001 roysmith@127.0.0.1  bash -l -c screen -R

Теперь я получаю настоящую оболочку входа в систему, которая запускает .profile, но screen не может повторно подключиться к отключенному сеансу. Я запускаю указанную выше команду на своем Macbook, и на удаленном компьютере у меня есть прикрепленный экран:

$ screen -list
There is a screen on:
    21117.pts-21.roysmith01 (01/19/2015 01:50:59 PM)    (Attached)
1 Socket in /var/run/screen/S-roysmith.

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

$ screen -list
There is a screen on:
    21117.pts-21.roysmith01 (01/19/2015 01:50:59 PM)    (Detached)
1 Socket in /var/run/screen/S-roysmith.

Теперь, если я открою другое окно локального терминала и снова запустил эту команду ssh, screen не сможет найти отключенный сеанс и создаст новый:

$ screen -list
There are screens on:
    21304.pts-21.roysmith01 (01/19/2015 01:52:40 PM)    (Attached)
    21117.pts-21.roysmith01 (01/19/2015 01:50:59 PM)    (Detached)
2 Sockets in /var/run/screen/S-roysmith.

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

Если нет существующего сеанса для подключения, screen будет использовать любую команду, которую вы дадите после в -R флаг. Итак, это должно делать то, что вы хотите (без необходимости касаться .screenrc):

$ ssh [...]@127.0.0.1 screen -R bash -l

(Это, безусловно, самый простой способ сделать то, что вы изначально намеревались сделать.)

Но поскольку вы спросили, я также упомяну, почему ваш bash -l подход не работал. Это было так близко!

bash -c принимает в качестве команды только следующий аргумент. Аргументы после этого переходят в $0, $1, и т.д.

$ bash -c echo bar
[just a blank line]
$ bash -c 'echo foo'
foo
$ bash -c 'echo $1' foo bar baz
bar

Это делает то, что вы хотели bash -l -c screen -R делать:

$ ssh [...]@127.0.0.1 bash -l -c "'screen -R'"

Да, интересно, что вам нужно два уровня цитирования для того, чтобы это работало: внешние кавычки сообщают вашей локальной оболочке, что нужно сохранять внутренние кавычки, а внутренние кавычки необходимы, потому что ssh отправляет результирующую команду, bash -l -c 'screen -R', как строка с четырьмя пробелами в ней, а не как список из четырех слов. С одним уровнем кавычек удаленная оболочка все равно увидит bash -l -c screen -R.

Это тоже будет сделано, если удаленной оболочке будет дана командная строка bash -l -c screen\ -R:

$ ssh [...]@127.0.0.1 bash -l -c 'screen\ -R'

Или это, чтобы дать удаленной оболочке bash -l -c "screen -R":

$ ssh [...]@127.0.0.1 bash -l -c \"screen -R\"

я нашел Как заставить экран вести себя как стандартная оболочка bash?, который указал мне правильное направление. Ввод "defshell -bash" в мой .screenrc дает мне желаемое поведение. Однако с помощью я мог понять, что на самом деле делает экран. Я ненавижу находить то, что работает, не понимая почему.