19

当然,屏幕很棒,但我不想考虑它。我经常 ssh 到一台机器,开始做一堆事情,然后想“天哪,我希望我在做所有这些之前就考虑过启动一个屏幕会话,这样我以后可以从家里重新连接到这个”。

我希望在登录机器时自动启动屏幕。当我断开连接时,我希望能够立即简单地重新连接,而不用担心“screen -ls”和“screen -dr”。

我有一个脚本,它实现了这个问题的一个解决方案,我将作为答案发布。我有兴趣看到其他方法。

4

9 回答 9

15

使用以下ssc, 代替ssh. 如果您只是执行“ ssc remote.com”,那么它将列出现有的屏幕会话。给它第三个参数,它将连接到该屏幕会话,或者创建它并连接到它。无论哪种方式,如果您断开连接,您只需在 shell 中执行“向上箭头,输入”即可重新连接。屏幕知识为零!编辑:感谢@klochner 将其扩展为处理任意 ssh 选项。您现在可以像使用 ssh 一样使用它!

#!/usr/bin/env perl
# Use 'ssc' (this script) instead of 'ssh' to log into a remote machine.
# Without an argument after the hostname it will list available screens.
# Add an argument after the hostname 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.

# ssh option parsing by @klochner
my $optstring = ""; 
while ($val = shift) {
  if    ($val =~ /^-\w$/)  { $optstring .= " ".$val.(shift); }
  elsif ($val =~ /^-\w+$/) { $optstring .= " ".$val;         }
  elsif ($machine)         { $tag        =     $val;         }
  else                     { $machine    =     $val;         }
}

if (!$machine) {
  print "USAGE: ssc [ssh options] remote.com [screen name]\n";
} elsif (!$tag) {
  @screens = split("\n", `ssh $optstring $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"; }
      # remember anything weird about the screen, like shared screens
      if($status =~ /^(attached|detached)$/i) { 
        $special{"$num.$tag"} = "";
      } else {
        $special{"$num.$tag"} = "[$status]";
      }
    }
  }
  print "ATTACHED:\n";
  for(sort { ($a=~/\.(\w+)/)[0] cmp ($b=~/\.(\w+)/)[0] } keys(%att)) {
    ($tag) = /\.(\w+)/;
    print "  $tag\t($_)\t$special{$_}\n" if $att{$_};
  }
  print "DETACHED:\n";
  for(sort { ($a=~/\.(\w+)/)[0] cmp ($b=~/\.(\w+)/)[0] } keys(%att)) {
    ($tag) = /\.(\w+)/;
    print "  $tag\t($_)\t$special{$_}\n" unless $att{$_};
  }
} else {
 system("ssh $optstring -t $machine \"screen -S $tag -dr || screen -S $tag\"");
}

顺便说一句,当您失去网络连接时,有一个技巧可以强制退出 ssh 会话并返回本地终端提示:
https ://superuser.com/questions/147873/ssh-sessions-in-xterms-freeze-for-很多分钟,每当他们断开连接

于 2009-07-02T18:29:18.990 回答
10

autossh它会自动重新连接断开的 ssh 会话。

它带有一个名为的示例脚本rscreen,它正是这样做的。简单来说就是:

#!/bin/sh
autossh -M 0 -t $1 "screen -e^Aa -D -R"

然后你必须重新训练你的手指来打字rscreen hostname而不是ssh hostname

于 2009-12-13T13:43:51.723 回答
7
ssh user@host.com -t 'screen -dRR'

这将在连接时重新加载/创建您的屏幕会话。这正是所要求的,即使它将产生会话的责任转移给了发起客户端。理想情况下,您希望服务器上有一些进程来管理呈现给连接客户端的内容。据我所知不存在。没有人在此线程中提出理想的解决方案。对我来说,这比其他的“不理想”。没有脚本,没有错误,没有 TTY 问题,没有与其他 ssh 命令的不良交互,没有无限循环的可能性,没有文件编辑,不需要额外的包。

于 2011-03-23T18:27:58.147 回答
7

实际上 screen 将 TERM 变量设置为“screen”。所以脚本就更简单了。这是我使用的:

if [ "$TERM" != "screen" ]; then
  screen -xRR
fi

像魅力一样工作,-x确保即使屏幕连接到其他地方,我也将其连接到这里。这样,我每个人只有一个屏幕可以跟踪所有内容。

于 2009-08-11T02:56:08.277 回答
3

我的 .bashrc 中有以下内容

 if [ "$PS1" != "" -a "${_STARTED_SCREEN:-x}" = x -a "${SSH_TTY:-x}" ] 
 then 
     export _STARTED_SCREEN=1;
     sleep 1 
     screen -RR && exit 0 
     # normally, execution of this rc script ends here... 
     echo "Screen failed! continuing with normal bash startup" 
 fi

前段时间在网上找到的,不知道在哪里。

更新修复了评论中指出的错误。谢谢 R. 佩特

于 2009-07-02T18:30:57.490 回答
2

i have used autossh, it is very useful to me

于 2010-05-05T06:54:07.657 回答
1

也许放入exec screen -dr您的.login?

于 2009-07-02T18:29:27.523 回答
1

我使用mosh(移动外壳)。即使您进入睡眠模式、断开网络连接、更改 IP 等,它也会保持您的连接。每当您返回时,您就会恢复连接。

于 2016-03-22T18:22:17.043 回答
0

取决于你的 shell,但是 .bashrc 呢?(如果你使用 bash “screen -rd”)

于 2009-07-02T18:28:59.830 回答