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.
GNU Screen is a terminal multiplexer, a software application that can be used to multiplex several virtual consoles, allowing a user to access multiple separate login sessions inside a single terminal window, or detach and reattach sessions from a terminal.
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
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With