У меня в офисе стоит 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 дает мне желаемое поведение. Однако с помощью я мог понять, что на самом деле делает экран. Я ненавижу находить то, что работает, не понимая почему.