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

发布于 2024-07-26 04:59:19 字数 248 浏览 2 评论 0原文

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

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

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

Screen is amazing, of course, but I don't want to have to think about it. I often ssh to a machine, start doing a bunch of stuff, and then think "gosh, I wish I had thought to start a screen session before doing all that so I could reconnect to this from home later".

I'd like to have screen automatically started whenever I log in to a machine.
And when I get disconnected, I want to be able to immediately and simply reconnect without fussing with "screen -ls" and "screen -dr".

I have a script that implements one solution to this problem which I'll post as an answer. I'm interested to see other approaches.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

谁的新欢旧爱 2024-08-02 04:59:19

使用以下命令 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-每当断开连接时冻结许多分钟

Use the following, ssc, instead of ssh. If you just do "ssc remote.com" then it will list existing screen sessions. Give it a 3rd argument and it will connect to that screen session, or create it and connect to it. Either way, if you get disconnected you can just do "up-arrow, enter" in the shell to reconnect. Zero knowledge of screen required!
Edit: Thanks to @klochner for extending this to handle arbitrary ssh options. You can now use this just like 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\"");
}

Btw, there's a trick to forcing an ssh session to exit and give you back your local terminal prompt when you lose network connectivity:
https://superuser.com/questions/147873/ssh-sessions-in-xterms-freeze-for-many-minutes-whenever-they-disconnect

朱染 2024-08-02 04:59:19

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

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

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

然后您必须重新训练手指来输入 rscreen hostname 而不是 ssh hostname

there is autossh which automatically reconnects disconnected ssh-sessions.

It comes with an example script called rscreen which does exactly that. It is, simply:

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

Then you have to retrain your fingers to type rscreen hostname instead of ssh hostname

风吹短裙飘 2024-08-02 04:59:19
ssh [email protected] -t 'screen -dRR'

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

ssh [email protected] -t 'screen -dRR'

This will reload/create your screen session on connect. This does exactly what was requested, even if it moves the responsibility for spawning the session to the initiating client. Ideally you would want some process on the server managing what gets presented to connecting clients. As far as I know that doesn't exist. No one has suggested the ideal solution in this thread. For me this is less "not ideal" than the rest. No scripts, no bugs, no TTY issues, no bad interactions with other ssh commands, no potential for infinite loops, no file editing, no additional packages required.

美男兮 2024-08-02 04:59:19

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

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

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

Actually screen sets the TERM variable to 'screen'. So the script is even easier. Here is what I use:

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

Works like a charm, the -x ensures that even if the screen is attached somewhere else I attach to it here. This way I only every have one screen where I can keep track of everything.

如果没有 2024-08-02 04:59:19

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

I have the following in my .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

I found it online somewhere awhile ago, not sure where.

Update Fixed error that was pointed out in comments. Thanks R. Pate

木森分化 2024-08-02 04:59:19

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

i have used autossh, it is very useful to me

青衫负雪 2024-08-02 04:59:19

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

Maybe put exec screen -dr in your .login?

银河中√捞星星 2024-08-02 04:59:19

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

I use mosh (mobile shell). It keeps your connection on even if you go to sleep mode, disconnect from the network, change IP, and so on. Whenever you return, you get your connection back.

扛刀软妹 2024-08-02 04:59:19

我经常从多个终端选项卡连接到远程计算机。 我的 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

欢迎提出改进建议。

I often connect to a remote machine from multiple terminal tabs. This in my zshrc checks if there's any detached session, and if there's one, connects to it. Else, it'll create a new screen. This allows me to resume work easily after an facing a network interruption easily even if I had 3 ssh sessions open. I just have to reopen 3 ssh tabs or reconnect on the previous 3 tabs and they'll resume as if nothing happened.
First if checks if already inside another screen or tmux window and to make sure that the shell is in interactive mode.

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

suggestions for improving are welcome.

马蹄踏│碎落叶 2024-08-02 04:59:19

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

Depends on your shell, but what about .bashrc? (If you use bash "screen -rd")

浊酒尽余欢 2024-08-02 04:59:19

在 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并且该会话移动到我当前的电脑...

running this line on ubuntu adds this code to the end of my .bashrc

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

what this does is make a "follow me" ssh... I can be working on one pc at work, power outage, just go home an connect and it asks if i want to resume the session there...also if i forget a ssh session logged in anywhere it will close that one... so if i leave my pc doing updates on a server with screen locked and never go back, just ssh in and that session moves to my current pc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文