19

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.

dreeves
  • 25,132
  • 42
  • 147
  • 226

9 Answers9

15

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

Community
  • 1
  • 1
dreeves
  • 25,132
  • 42
  • 147
  • 226
  • 1
    As to screen being too clever with its invisible and silent tab-completion on the screen names, I suggest a convention of making sure every screen name you use start with a distinct letter. Use a descriptive word the first time but from then on you can use just the first letter. – dreeves Jul 17 '09 at 05:06
  • 1
    On my Ubuntu system (10.4) I had to modify the regular expression to account for the date/time info it prints next to each session. if(/^\s*(\d+)\.(\S+)\s+\(([^\)]*)\)\s+\(([^\)]*)\)/) { ($num, $tag, $status) = ($1, $2, $4); – Nathan Bell Nov 22 '12 at 08:11
10

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

levinalex
  • 5,541
  • 2
  • 32
  • 48
7

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.

Feanil
  • 93
  • 4
7
ssh user@host.com -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.

kevinlawler
  • 870
  • 1
  • 8
  • 17
3

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

seth
  • 34,791
  • 7
  • 58
  • 57
  • 1
    Isn't "export _STARTED_SCREEN=1" enough, instead of setting then exporting? –  Jul 02 '09 at 18:49
  • @RogerPate no, it was actually better before with first setting and then exporting - that way it was actually portable, and it worked on other POSIX-compliant shells. Now it is few bytes smaller, but would break if you use for example dash instead of bash, etc. See for example http://mywiki.wooledge.org/Bashism – Matija Nalis Aug 05 '16 at 11:16
2

i have used autossh, it is very useful to me

liupeng
  • 33
  • 4
1

Maybe put exec screen -dr in your .login?

Patrick D'Souza
  • 3,371
  • 2
  • 19
  • 37
Geoff Fritz
  • 392
  • 2
  • 7
1

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.

Rodolfo
  • 146
  • 2
0

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

EFraim
  • 11,975
  • 3
  • 42
  • 62
  • 2
    @highperformance: and what makes you think that you cannot check in .bashrc if you are already running in screen? Do you also need a warning that a coffee might be hot? – EFraim Jan 05 '11 at 19:44
  • 2
    you can check, but it isn't easy to do correctly or succinctly. naive methods will break say `ssh host 'echo hello world'`. see the progress in the other answers. – kevinlawler Jan 05 '11 at 23:07