2009-07-02 6 views
19

Bildschirm ist erstaunlich, natürlich, aber ich möchte nicht darüber nachdenken müssen. Ich ssh oft zu einer Maschine, fange an, eine Menge Sachen zu machen, und denke dann "Gott, ich wünschte, ich hätte gedacht, dass ich eine Bildschirmsitzung beginnen würde, bevor ich das alles mache, damit ich später von zu Hause aus wieder Verbindung aufnehmen kann."Verwendung von GNU-Bildschirm vollständig transparent und automatisch

Ich möchte, dass der Bildschirm automatisch gestartet wird, wenn ich mich an einem Computer anmelde. Und wenn ich getrennt werde, möchte ich in der Lage sein, sofort und einfach wieder zu verbinden, ohne mit "screen-ls" und "screen -dr" zu beschäftigen.

Ich habe ein Skript, das eine Lösung für dieses Problem implementiert, die ich als Antwort posten werde. Ich bin daran interessiert, andere Ansätze zu sehen.

Antwort

14

Verwenden Sie Folgendes, ssc, anstelle von ssh. Wenn Sie nur "ssc remote.com" tun, wird es vorhandene Bildschirmsitzungen auflisten. Geben Sie ein drittes Argument und es wird eine Verbindung zu dieser Bildschirmsitzung hergestellt, oder es wird erstellt und eine Verbindung hergestellt. So oder so, wenn Sie die Verbindung trennen, können Sie einfach "Pfeil nach oben, Enter" in der Shell, um die Verbindung wiederherzustellen. Null Kenntnisse des Bildschirms erforderlich! Edit: Danke an @klochner für die Erweiterung um beliebige ssh Optionen zu bearbeiten. Du kannst es jetzt genauso benutzen wie 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, gibt es einen Trick, eine SSH-Sitzung zu zwingen Sie Ihren lokalen Terminal Aufforderung zu beenden und geben Sie zurück, wenn Sie die Netzwerkverbindung verlieren:
https://superuser.com/questions/147873/ssh-sessions-in-xterms-freeze-for-many-minutes-whenever-they-disconnect

+1

Da der Bildschirm mit seinen unsichtbaren und stillen Tab-Vervollständigungen auf den Bildschirmnamen zu schlau ist, schlage ich eine Konvention vor, die sicherstellt, dass jeder verwendete Bildschirmname mit einem bestimmten Buchstaben beginnt. Verwenden Sie ein beschreibendes Wort beim ersten Mal, aber ab dann können Sie nur den ersten Buchstaben verwenden. – dreeves

+0

Auf meinem Ubuntu-System (10.4) musste ich den regulären Ausdruck ändern, um die Datums-/Zeitinformationen zu berücksichtigen, die er neben jeder Sitzung druckt. if (/^\ s * (\ d +) \. (\ S +) \ s + \ (([^ \)] *) \) \ s + \ (([^ \)] *) \) /) { ($ num, $ tag, $ status) = ($ 1, $ 2, $ 4); –

0

Hängt von Ihrer Shell ab, aber was ist mit .bashrc? (Wenn Sie bash "screen -rd" verwenden)

+0

Der Grund für downvote ist: Manche mögen Bash? – EFraim

+2

der Grund ist eine Gabel Bombe – kevinlawler

+2

@highperformance: und was macht Sie denken, dass Sie nicht einchecken können. Bashrc, wenn Sie bereits im Bildschirm laufen? Brauchen Sie auch eine Warnung, dass ein Kaffee heiß sein könnte? – EFraim

1

setzen exec screen -dr in Ihre .login Vielleicht?

3

Ich habe folgend in meinem .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 

ich es irgendwo online vor einer Weile gefunden, nicht sicher, wo.

Update Fehler behoben, der in Kommentaren angegeben wurde. Danke R. Pate

+1

Ist "export _STARTED_SCREEN = 1" nicht ausreichend, anstatt zu setzen und dann zu exportieren? –

+0

@RogerPate nein, es war eigentlich besser vorher mit der ersten Einstellung und dann exportieren - so war es tatsächlich tragbar, und es funktionierte auf anderen POSIX-konformen Shells. Jetzt ist es ein paar Bytes kleiner, würde aber brechen, wenn Sie zum Beispiel statt Bindestrich Dash verwenden usw. Siehe zum Beispiel http://mywiki.wooledge.org/Bashism –

7

Eigentlich Bildschirm setzt die TERM-Variable auf "Bildschirm". So ist das Skript noch einfacher. Hier ist, was ich benutze:

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

wirkt wie ein Zauber, die -x sorgt dafür, dass auch wenn der Bildschirm irgendwo anders angebracht ist, ich es hier befestigen. So habe ich nur jeden Bildschirm, auf dem ich alles im Auge behalten kann.

+0

Was passiert, wenn der Benutzer "ssh hostname 'ls -R ~" ausführt /.local '"zum Beispiel? –

9

gibt es autossh, die automatisch getrennte ssh-Sitzungen wieder verbindet.

Es kommt mit einem Beispiel-Skript namens rscreen, die genau das tut.Es ist einfach:

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

Dann müssen Sie Ihre Finger umschulen rscreen hostname geben statt ssh hostname

2

i verwendet autossh haben, ist es sehr nützlich für mich

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

Dies wird neu geladen/Erstellen Sie Ihre Bildschirmsitzung beim Verbinden. Dies tut genau das, was angefordert wurde, selbst wenn es die Verantwortung für das Starten der Sitzung auf den initiierenden Client verlagert. Idealerweise möchten Sie, dass auf dem Server ein Prozess verwaltet wird, der verwaltet, was den verbundenen Clients präsentiert wird. Soweit ich weiß, existiert das nicht. Niemand hat in diesem Thread die ideale Lösung vorgeschlagen. Für mich ist das weniger "nicht ideal" als der Rest. Keine Skripte, keine Bugs, keine TTY-Probleme, keine schlechten Interaktionen mit anderen SSH-Befehlen, kein Potenzial für Endlosschleifen, keine Dateibearbeitung, keine zusätzlichen Pakete erforderlich.

1

Ich verwende mosh (mobile shell). Es hält Ihre Verbindung auch dann aufrecht, wenn Sie in den Energiesparmodus wechseln, die Verbindung zum Netzwerk trennen, die IP-Adresse ändern und so weiter. Immer wenn du zurückkommst, bekommst du deine Verbindung zurück.