完全透明地自动使用GNU Screen

时间:2009-07-02 18:26:04

标签: scripting automation ssh gnu-screen

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

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

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

9 个答案:

答案 0 :(得分:14)

使用以下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-many-minutes-whenever-they-disconnect

答案 1 :(得分:10)

autossh会自动重新连接断开连接的ssh-sessions。

它带有一个名为rscreen的示例脚本,它正是这样做的。它只是:

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

然后你必须重新训练手指才能输入rscreen hostname而不是ssh hostname

答案 2 :(得分:7)

实际上,屏幕将TERM变量设置为“屏幕”。因此脚本更容易。这是我使用的:

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

像魅力一样工作,-x确保即使屏幕附着在其他地方,我也会附在此处。这样我只有一个屏幕可以跟踪所有内容。

答案 3 :(得分:7)

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

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

答案 4 :(得分: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. Pate

答案 5 :(得分:2)

我使用过autossh,对我来说非常有用

答案 6 :(得分:1)

也许将exec screen -dr放入.login?

答案 7 :(得分:1)

我使用mosh (mobile shell)。即使您进入睡眠模式,断开网络连接,更改IP等,它也会保持连接。无论什么时候返回,都可以恢复连接。

答案 8 :(得分:0)

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