我在办公室里有一台 Linux 机器,我想通过家里的 Macbook 来 ssh 连接它。我无法直接通过端口 22 连接该机器,但我在 localhost:23001 和远程 Linux 机器上的端口 22 之间建立了一个端口隧道。这适用于常规 ssh 会话:
$ ssh -t -2 -A -p 23001 [email protected]
下一步是,我想在屏幕会话中自动运行我的终端会话。它几乎可以做到:
$ ssh -t -2 -A -p 23001 [email protected] screen -R
如果我没有当前屏幕会话,它会创建一个。如果已经有一个分离的屏幕,它会连接到它。到目前为止,一切顺利。但问题是,我从来没有得到一个登录 shell,所以我的 .profile 从来没有运行过,我的环境也没有设置好。所以,我更进一步,尝试了:
$ ssh -t -2 -A -p 23001 [email protected] bash -l -c screen -R
现在,我得到了一个运行 .profile 的真正的登录 shell,但屏幕无法重新连接到分离的会话。我在 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.
知道这是怎么回事吗?为什么插入登录 shell 会导致屏幕无法找到现有会话?
答案1
如果没有现有的会话可以连接,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'"
是的,令人兴奋的是,您需要两层引号才能实现该功能:外层引号告诉您的本地 shell 保留内层引号,而内层引号是必需的,因为 ssh 将结果命令 发送为包含bash -l -c 'screen -R'
四个空格的字符串,而不是四个单词的列表。使用一层引号,远程 shell 仍将看到bash -l -c screen -R
。
这也可以做到这一点,远程 shell 被赋予命令字符串bash -l -c screen\ -R
:
$ ssh [...]@127.0.0.1 bash -l -c 'screen\ -R'
或者这样给出远程 shell bash -l -c "screen -R"
:
$ ssh [...]@127.0.0.1 bash -l -c \"screen -R\"
答案2
我发现我如何让屏幕表现得像一个标准的 bash shell?,这为我指明了正确的方向。在我的 .screenrc 中输入“defshell -bash”可以实现我想要的行为。但是,我可以弄清楚 screen 到底在做什么。我讨厌在不理解原因的情况下找到有效的东西。