Scripting 完全透明、自动地使用GNU屏幕

Scripting 完全透明、自动地使用GNU屏幕,scripting,automation,ssh,gnu-screen,Scripting,Automation,Ssh,Gnu Screen,屏幕是惊人的,当然,但我不想去想它。我经常ssh到一台机器上,开始做一些事情,然后想“天哪,我真希望我在做这些事情之前先想到启动一个屏幕会话,这样我以后就可以从家里重新连接到这个” 我想让屏幕自动启动,每当我登录到一台机器。 当我断开连接时,我希望能够立即简单地重新连接,而不必担心“screen-ls”和“screen-dr” 我有一个脚本,它实现了这个问题的一个解决方案,我将作为答案发布。我想看看其他方法。取决于您的shell,但是.bashrc呢?(如果您使用bash“screen-rd”)

屏幕是惊人的,当然,但我不想去想它。我经常ssh到一台机器上,开始做一些事情,然后想“天哪,我真希望我在做这些事情之前先想到启动一个屏幕会话,这样我以后就可以从家里重新连接到这个”

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


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

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

请使用以下
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会话并返回本地终端提示:

是否可以将
exec screen-dr
放在您的.login中?

我的.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.Pate

实际上screen将术语变量设置为“screen”。所以脚本更容易。以下是我使用的:

if [ "$TERM" != "screen" ]; then
  screen -xRR
fi
工作起来就像一个符咒,
-x
确保即使屏幕连接到其他地方,我也会将其连接到这里。这样,我只有一个屏幕可以跟踪所有内容。

有一个屏幕可以自动重新连接断开的ssh会话

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

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

然后你必须重新训练你的手指来键入
rscreen hostname
,而不是
ssh hostname
我用过autosh,它对我很有用

ssh user@host.com -t 'screen -dRR'

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

我使用。即使您进入睡眠模式、断开网络连接、更改IP等,它也会保持连接。无论何时你回来,你都可以恢复连接

“export\u STARTED\u SCREEN=1”而不是先设置然后导出,这难道还不够吗?@RogerPate不,之前先设置然后导出实际上更好——这样它实际上是可移植的,并且可以在其他兼容POSIX的shell上工作。现在它小了几个字节,但如果使用dash而不是bash等,它会断开。例如,请参阅screen在屏幕名称上的不可见和无声的制表符补全太聪明了,我建议使用一种惯例,确保您使用的每个屏幕名称都以一个不同的字母开头。在我的Ubuntu系统(10.4)上,我不得不修改正则表达式,以说明它在每个会话旁边打印的日期/时间信息。如果(/^\s*(\d+)\(\s+)\s+([^)]*)/(([^)]*){($num,$tag,$status)=($1,$2,$4);如果用户运行“ssh hostname'ls-R~/.local”该怎么办例如?@highperformance:是什么让你认为你无法签入。如果你已经在屏幕上运行bashrc?你是否还需要一个警告,告诉你一杯咖啡可能热了?你可以检查,但要正确或简洁地进行检查并不容易。天真的方法会破坏say
ssh主机“echo hello world”
。请参阅另一个示例回答。