网络中断后自动(或更轻松地)重新连接到屏幕会话

时间:2009-01-23 22:56:33

标签: ssh scripting automation gnu-screen

补充:我相信现在这个问题归于这一问题:   Using GNU Screen completely transparently and automatically

另见相关问题:
https://superuser.com/questions/147873/ssh-sessions-in-xterms-freeze-for-many-minutes-whenever-they-disconnect

原始问题:

如果有一种方法可以ssh到一台机器并立即重新连接到特定的屏幕会话,那将是很好的。你可以这样做:

laptop> ssh server.com screen -ls

它将显示server.com上可用的屏幕列表,如[1]:

123.pts-1
456.pts-2

然后你可能会尝试这样做:

laptop> ssh server.com screen -dr pts-2

但失败了,说“必须连接到终端”。 你必须首先ssh然后在server.com上执行“screen -dr pts-2”,如果你有一个片状连接并断开很多连接,这是不好的。您希望能够通过笔记本电脑上的简单“向上箭头输入”继续。 (或者让它更自动化。)

我对这个问题有一个可怕的解决方案,我会将其作为答案发布,并希望它能够被遗忘以支持正确的方法来解决这个问题。

<小时/> 脚注:

[1]或者,更好的是,如果您创建了名为“screen -S foo”和“screen -S bar”的屏幕会话,那么您将获得更友好的列表,如:

123.foo
456.bar

并可以重新连接,例如“screen -dr foo”。


迷你屏幕教程,结合了这个问题的答案:

登录server.com并执行

screen -S foo 

然后再也不会退出该会话。 要从其他地方重新连接,请执行

ssh -t server.com screen -dr foo

列出要重新协商的可用屏幕:

screen -ls

或者,当然,

ssh server.com screen -ls

远程检查server.com的可用屏幕。

我现在根据Jason的答案使用以下别名(tcsh)连接到命名屏幕(如果存在)或创建并以其他方式连接:

alias ssc 'ssh -t \!:1 "screen -S \!:2 -dr || screen -S \!:2"'

6 个答案:

答案 0 :(得分:58)

-t选项是否符合您的要求?

     -t      Force pseudo-tty allocation.  This can be used to execute arbi-
             trary screen-based programs on a remote machine, which can be
             very useful, e.g. when implementing menu services.  Multiple -t
             options force tty allocation, even if ssh has no local tty.

所以:

laptop> ssh -t server.com screen -dr pts-2

这似乎适用于我的安装。

答案 1 :(得分:3)

现在这包含在:Using GNU Screen completely transparently and automatically

<小时/> 这是一个脚本ssc,它的工作方式与ssh类似,但需要第三个参数来指定要重新连接的屏幕或新屏幕的名称。 我相信这个剧本包含原始问题中的所有内容。

#!/usr/bin/env perl
# Use 'ssc' (this script) instead of 'ssh' to log into a remote machine.
# Without a 3rd argument it will list available screens.
# Give it a 3rd argument to attach to an existing screen or specify a new
#   screen.  Eg, ssc remote.com foo
# The numbers in front of the screen tag can usually be ignored.
# Screen is a little too clever though in that if there's an existing screen "bar"
#   and you say "ssc remote.com b" it will reconnect you to "bar" instead of making
#   a new screen "b".  It's like invisible and silent tab-completion.

if(scalar(@ARGV)==0 || scalar(@ARGV) > 2) {
  print "USAGE: ssc remote.com [screen name]\n";
} elsif (scalar(@ARGV) == 1) {
  $machine = shift;
  @screens = split("\n", `ssh $machine screen -ls`);
  for(@screens) {
    if(/^\s*(\d+)\.(\S+)\s+\(([^\)]*)\)/) {
      ($num, $tag, $status) = ($1, $2, $3);
      if($status =~ /attached/i) { $att{"$num.$tag"} = 1; }
      elsif($status =~ /detached/i) { $att{"$num.$tag"} = 0; }
      else { print "Couldn't parse this: $_\n"; }
    }
  }
  print "ATTACHED screens:\n";
  for(keys(%att)) { print "  $_\n" if $att{$_}; }
  print "DETACHED screens:\n";
  for(keys(%att)) { print "  $_\n" unless $att{$_}; }
} else {
  $machine = shift;
  $tag = shift;
  system("ssh -t $machine \"screen -S $tag -dr || screen -S $tag\"");
}

答案 2 :(得分:2)

使用-t选项ssh在直接运行命令时分配终端。

laptop> ssh -t server.com screen -dr pts-2

答案 3 :(得分:2)

我一直在做类似的事情,但并没有完全达到目的,你的解决方案已经解决了我的问题,所以这是我的建议:

ssh -t server.com "screen -S foo -rd || screen -S foo"

这只是尝试打开名为foo的现有屏幕,如果它不存在,则创建它。 我将它放在笔记本电脑上的发射器中,所以当无线网络运行时,我可以打开我离开的地方。

只是注意到默认的屏幕外壳有点弱,所以改善你的家庭环境会更好:

ssh -t server.com "screen -S foo -rd || screen -S foo bash -l"

答案 4 :(得分:1)

我将此转换为在OS X .bash_profile上添加一个:如果没有给出第二个参数,它将启动会话“default”。

function ssc() {
    if [[ -z $2 ]]; then
        screen="default"
    else
        screen=$2
    fi
    ssh -t $1 "screen -S $screen -dr || screen -S $screen"
}

答案 5 :(得分:1)

如果您想连接到同一个会话,即使它已处于活动状态,已分离或尚未存在:

  

ssh -t user @ server screen -xR screenName

同样但如果它已在其他某个pty上处于活动状态,则创建一个新会话:

  

ssh -t user @ server screen -rR screenName