dreeves
dreeves

Reputation: 26932

Using GNU Screen completely transparently and automatically

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.

Upvotes: 20

Views: 6506

Answers (11)

lazee486
lazee486

Reputation: 1

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

Upvotes: 0

Mah35h
Mah35h

Reputation: 1361

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.

Upvotes: 1

Rodolfo
Rodolfo

Reputation: 156

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.

Upvotes: 1

Geoff Fritz
Geoff Fritz

Reputation: 402

Maybe put exec screen -dr in your .login?

Upvotes: 1

kevinlawler
kevinlawler

Reputation: 960

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.

Upvotes: 9

dreeves
dreeves

Reputation: 26932

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

Upvotes: 15

6peng
6peng

Reputation: 33

i have used autossh, it is very useful to me

Upvotes: 2

levinalex
levinalex

Reputation: 5949

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

Upvotes: 10

Feanil
Feanil

Reputation: 93

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.

Upvotes: 7

seth
seth

Reputation: 37277

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

Upvotes: 3

EFraim
EFraim

Reputation: 13028

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

Upvotes: 0

Related Questions