完全透明且自动地使用GNU Screen

问题描述 投票:0回答:11

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

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

我有一个脚本可以实现该问题的一种解决方案,我将其作为答案发布。我有兴趣了解其他方法。

scripting automation ssh gnu-screen
11个回答
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-many-months-whenever-they-disconnect


10
投票

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

它附带了一个名为

rscreen
的示例脚本,它正是这样做的。简单来说就是:

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

然后你必须重新训练手指来输入

rscreen hostname
而不是
ssh hostname


8
投票
ssh [email protected] -t 'screen -dRR'

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


7
投票

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

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

就像一个魅力,

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


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.佩特


2
投票

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


1
投票

也许可以将

exec screen -dr
放入您的 .login 中?


1
投票

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


1
投票

我经常从多个终端选项卡连接到远程计算机。我的 zshrc 中的这会检查是否有任何分离的会话,如果有,则连接到它。否则,它将创建一个新屏幕。这使我能够在面临网络中断后轻松恢复工作,即使我打开了 3 个 ssh 会话。我只需重新打开 3 个 ssh 选项卡或重新连接前 3 个选项卡,它们就会恢复,就像什么都没发生一样。 首先 if 检查是否已经在另一个屏幕或 tmux 窗口内,并确保 shell 处于交互模式。

if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ] && [[ ! "$TERM" =~ screen.xterm-256color ]]; then
    SCLS=$(screen -ls | grep Detached)
    if [ ${#SCLS} -gt 0 ]
    then
        echo -n $SCLS | wc -l
        SID=$( echo $SCLS | head -n1 | cut -d. -f1 | awk '{print $1}' )
        screen -r $SID
    else
        screen zsh -c "echo -e Spawned new screen '\n' && screen -ls && echo  && zsh"
    fi
fi

欢迎提出改进建议。


0
投票

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


0
投票

在 ubuntu 上运行此行会将此代码添加到我的 .bashrc 的末尾

sudo echo "read -p \"Press ENTER to resume previous session or CTR-D to start a new session\" && screen -D -RR" >> ~/.bashrc

它的作用是创建一个“跟随我”的 ssh...我可以在工作时在一台电脑上工作,断电,只需回家连接,它会询问我是否要恢复那里的会话...另外,如果我忘记在任何地方登录了 ssh 会话,它将关闭该会话...因此,如果我让我的电脑在屏幕锁定的服务器上进行更新并且永远不会返回,只需 ssh 登录,该会话就会移动到我当前的电脑...

© www.soinside.com 2019 - 2024. All rights reserved.