Jak uzyskać ekran, aby automatycznie łączyć się z bieżącym agentem ssh podczas ponownego podłączania do istniejącego ekranu?

48

Jeśli rozpoczniesz sesję ekranową, gdy ssh-agent jest uruchomiony (z przekazywania ssh -A agent), dostęp do ssh-agent działa poprawnie. Jeśli jednak odłączysz się od tej sesji, wylogujesz się, zalogujesz ponownie (z przekazaniem ssh-agent) i ponownie przyłączysz się do sesji ekranowej, dostęp ssh-agent nie będzie działać.

Jak to może zostać naprawione?

Der Hochstapler
źródło

Odpowiedzi:

41

1) W skrypcie rc SSH (~ / .ssh / rc) skonfigurujesz dowiązanie symboliczne z lokalizacji kanonicznej do „bieżącego” SSH_AUTH_SOCK. Oto jak to robię w bash (zawartość ~ / .ssh / rc):

#!/bin/bash
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

(i upewnij się, że chmod 755 ~ / .ssh / rc). „Test” ma jedynie na celu zapobieganie wyświetlaniu błędu, jeśli nie korzystasz z ssh-agent (tzn. Masz ssh bez -A). Druga połowa tego polecenia ustawia dowiązanie symboliczne w kanonicznej lokalizacji, która aktualizuje się do „prawdziwego” SSH_AUTH_SOCK podczas logowania. Jest to niezależne od używania powłoki w ssh lub bezpośredniego wywoływania polecenia, działa również z „ssh -t screen -RRD”.

Uwaga: istnienie ~ / .ssh / rc zmienia zachowanie sshd. W szczególności nie będzie wywoływać xauth. Zobacz man sshd, aby uzyskać więcej informacji i jak to naprawić.

Nie powinieneś także używać „-v” z ln, gdy tylko zepsuje rsync-over-ssh z następującą diagnostyką:

$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]

2) W swoim .screenrc wystarczy zastąpić SSH_AUTH_SOCK do lokalizacji kanonicznej:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Zauważ, że używasz setenv bez względu na to, jakiej powłoki używasz; Myślę, że setenv to składnia ekranu, a nie powłoka.

Rozwiązanie pierwotnie zaadaptowane z tego postu , które nie działa, ale ma właściwy pomysł.

apinstein
źródło
Zakłada się, że najpierw się zalogujesz, a następnie ekran startowy. Dobrze?
innaM
1
Jak może być inaczej? Jak uruchomisz ekran bez zalogowania?
1
Masz rację. Pytanie zostało sformułowane w głupi sposób. Ale musisz się zalogować, uruchomić powłokę, a stamtąd ekran startowy? Często robię coś w stylu „ssh -t some.machine screen -R”.
innaM
1
Ach ok. Właśnie próbowałem tego i to nie działa (tzn. Ssh-agent nie jest podłączony). Wydaje mi się, że ssh nie konfiguruje odpowiednich gniazd, kiedy są używane w ten sposób. Może jakiś argument-foo mógłby to wyjaśnić?
SSH ustawia gniazda, po prostu nigdy nie uruchamia powłoki. Ale ta wskazówka jest tak przydatna, że ​​myślę, że mogę po prostu zmienić swoje nawyki.
innaM
23

Myślę, że działa to jako uproszczenie odpowiedzi @ sandip-bhattacharya. Umieść to w swoim ~/.bashrcpliku i uruchom polecenie eksportu we wszystkich aktualnie uruchomionych sesjach ekranu.

if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

To brzmi „if $SSH_AUTH_SOCKjest gniazdem ( -S), a nie dowiązaniem symbolicznym ( ! -h), utwórz nowe dowiązanie symboliczne na znanej ścieżce. We wszystkich przypadkach ponownie zdefiniuj, SSH_AUTH_SOCKaby wskazywać znaną ścieżkę.

W ! -hunika tworzenia odwołanie cykliczne jeśli uruchomić ten wielokrotnie.

Ponadto, jeśli używasz byobu, robi to automatycznie, bez potrzeby edytowania plików konfiguracyjnych.

Jedyny błąd, który w tym znalazłem ( byobuteż go ma), to to, że jeśli otworzysz drugie połączenie ssh -Alub ForwardAgentpołączenie, zastąpi ono pierwsze gniazdo, a jeśli zamkniesz drugie połączenie przed pierwszym, stracisz swoje jedyne dobre gniazdo.

Collin Anderson
źródło
1
To też działa tmux.
Dag Høidahl
Działa świetnie, ale psuje się podczas korzystania ze zdalnie montowanych folderów domowych. W takim przypadku użyj ~/.ssh/ssh_auth_sock_"$(hostname)"dla swojego dowiązania symbolicznego. Będzie przechowywać osobne gniazda uwierzytelniania dla każdego hosta.
Kibber
4

„ssh -t some.machine screen -R” nie uruchomi bash i dlatego nie uruchomi skryptu .bash_profile, w którym tworzony jest dowiązanie symboliczne.

Możesz spróbować: ssh -t some.machine bash -c "screen -R"

(zakładając, że używasz bash jako swojej powłoki)

Edycja: Ta „odpowiedź” jest właściwie komentarzem do pierwszej odpowiedzi podanej powyżej :)

Społeczność
źródło
„Pierwsza odpowiedź podana powyżej” nic nie znaczy, ponieważ kolejność odpowiedzi zmienia się w trakcie głosowania itp. Podaj link udostępniania odpowiedzi, na którą się powołujesz, ponieważ to się nie zmieni.
rjmunro
3

Myślę, że potrzebujesz autossh. Używam go od lat i w połączeniu z ekranem sprawia, że ​​wszystkie moje sesje terminalowe są całkowicie przenośne i przejrzyste. Po prostu zamykam lappy, przeprowadzam się do nowej lokalizacji, otwieram lappy, a wszystkie moje ekrany i ekrany zagnieżdżone łączą się automatycznie. Już nawet o tym nie myślę.

http://www.linux.com/archive/feature/134133

to podstawy ... Rubinowałem skrypt lil, aby zautomatyzować proces w moim .screenrc dla danego hosta. (także moje przekazywanie ssh, więc we wszystkich tych miejscach mogę tunelować moje połączenie przez moje serwery)

w dystrybucji autossh powinien być program o nazwie rscreen (i .. jest!)

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$HOST.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

To powinno pomóc w problemach z ssh / screen

Wreszcie, aby utrzymać działanie ssh-agenta, używam pęku kluczy, ponieważ jestem rodzajem powłoki ... Myślę, że OSX ma coś, co pozwala utrzymać twojego agenta w pobliżu ...

chiggsy
źródło
2

Oto metoda, której używam:

SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP

Zazwyczaj konfiguruję alias lub funkcję powłoki za pomocą następujących poleceń:

function ssh-screen-auth() {
  SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
  eval $SOCK
  export SSH_AUTH_SOCK
  DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
  eval $DISP
  export DISPLAY
}

Może być konieczne dostosowanie wyrażenia regularnego „ screen - (r | DR) ” do dokładnych poleceń używanych do ponownego podłączenia ekranu.

  • Pierwszy wiersz odczytuje zmienną środowiskową SSH_AUTH_SOCK w obszarze procesu właśnie wprowadzonej komendy „ screen -r ” i aktualizuje wartość w bieżącej powłoce.
  • Drugi wiersz jest konieczny, jeśli używasz „ ssh -X ” do przekazywania połączeń X11: aktualizuje zmienną DISPLAY w ten sam sposób.

Zastrzeżenie dotyczące mojej metody: może się nie udać, jeśli na komputerze uruchomione zostanie inne polecenie „ screen ”.

Farzy
źródło
-1 za niepotrzebne użycie sudo.
0xC0000022L
1

Często utrzymuję długoterminowe (ponad 6 miesięcy) sesje w moim miejscu pracy na różnych serwerach. Wielokrotne ponowne podłączanie i posiadanie realnego agenta przekazującego ssh było problematyczne. Oto, co skonfigurowałem w moich systemach:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

Jeśli po prostu zaloguję się na serwerze zdalnym bez ekranu uruchamiania / ponownego podłączania, pojawią się dwa „gniazda”, jedno używane przez screendrugie, a drugie przez nową powłokę. Nie powinny istnieć dwie sesje „startowe”, ale nadal można rozpocząć drugą sesję reattach -S new; w tej sytuacji agent byłby współdzielony z tą ~/.ssh/agent-screenwartością. Aby odzyskać działającego agenta przesyłania dalej, odłączę się, zaloguj ponownie. X${USER} = XmyusernameZapewnia to, że kod nie zostanie wywołany sudona tym samym serwerze.

Arcege
źródło
1

Używam odmiany tego, co @apinstein używa dla mojego .bashrc .

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

Działa to dla wszystkich aplikacji uruchomionych w mojej sesji ekranowej. To działałoby dla wszystkich nowych powłok w sesji ekranowej. W przypadku istniejących powłok należy uruchomić export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockpowłokę hosta, aby działała.

PS Przepraszam, że dodałem to jako niezależną odpowiedź, podczas gdy po prostu oparło się na odpowiedzi @ apinstein. Musiał to zrobić, ponieważ komentarze w przepełnieniu stosu nie obsługują bloków kodu.

Sandip Bhattacharya
źródło
Dlaczego nie zawsze link symboliczny i zawsze eksportować?
Collin Anderson
@CollinAnderson Dwa różne zachowania. jeden w powłoce ekranowej, a drugi w zwykłej powłoce logowania. zmienna środowiskowa w powłoce logowania jest ustawiana przez ssh, a zatem tam znajduje się dowiązanie symboliczne. jeśli zrobimy to w sesji ekranowej, wywołamy pętlę dowiązania symbolicznego.
Sandip Bhattacharya
Ach, racja. Będziesz musiał tylko linkować, jeśli $ SSH_AUTH_SOCK nie jest już linkiem. Zobacz mój post superuser.com/a/424588/134212
Collin Anderson
0

Wypróbowałem tę prostą linijkę zgodnie z sugestią zawartą w artykule Zróbmy znajomych z ekranu i agenta ssh i to działa dla mnie.

Pierwsze logowanie do Target.Należy zrobić tylko raz.

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

Uruchom ekran po raz pierwszy. Potrzeba zrobienia tylko raz.

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

W przypadku odłączenia lub rozłączenia użyj tego polecenia, aby zalogować się później, aby połączyć się z ekranem wyjścia.

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
Sharjeel
źródło
0

To są naprawdę dobre odpowiedzi. Robię to nieco inaczej. Po uruchomieniu nowej sesji ssh i ponownym podłączeniu ekranu resetuję SSH_AUTH_SOCKzmienną środowiskową na podstawie zawartości środowiska root bash. Wymagam dostępu ssh-agent tylko sporadycznie, gdy używam svn, więc po prostu zresetuję SSH_AUTH_SOCKwymagane w tych powłokach.

Wykorzystuje system plików proc, więc jest specyficzny dla systemu Linux. Testowałem to tylko na bezgłowym urządzeniu z linuksem, do którego dostęp mam tylko, może to wymagać drobnych poprawek, aby działało w innych środowiskach.

Aby zresetować SSH_AUTH_SOCK (może to być alias).

$ . ~/bin/screen_auth.sh

screen_auth.sh wygląda następująco

# Find the pid of putty's bash shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
Iain
źródło
0

Wszystkie powyższe rozwiązania podlegają warunkom wyścigowym (podczas wielu sesji EKRANU lub wielu połączeń SSH). Jedynym uniwersalnym rozwiązaniem, o którym mogę pomyśleć, jest wpchnięcie SSH_AUTH_SOCK do procesu serwera SCREEN, screen -ra następnie wciągnięcie go do sesji BASH przed każdą interaktywną niewbudowaną komendą. Niestety, SCREEN i BASH zostały zaprojektowane bez świadomości tego rodzaju problemów, więc raczej trudno jest je poprawnie wdrożyć (choć nigdy nie jest za późno, aby zamieścić prośby o dodanie funkcji do obu projektów). Podjęto moją próbę rozwiązania tego problemu dla sesji BASH, które można znaleźć tutaj:

Żeby zainstalować:

  1. włóż oba skrypty $HOME/bin, dodaj bit wykonywalny;
  2. upewnij się, że $HOME/bindzieje się to wcześniej /usr/binw PATH:

    ŚCIEŻKA = $ DOM / bin: $ ŚCIEŻKA

  3. dodaj to do .bashrc:

    źródło $ HOME / bin / screen-helper setup

Teraz możesz spróbować utworzyć sesję EKRAN w ramach sesji SSH, odłączyć, rozłączyć, połączyć i ponownie podłączyć, i mam nadzieję, że ssh-add -lpoprawnie pokażą twoje klucze.

midenok
źródło
Pamiętaj, że stały ssh-agentdemon (jak sugerowano tutaj superuser.com/a/412052/376867 ) nie cierpi z powodu warunków wyścigowych, ale cierpi na przestarzały brelok. Co ważniejsze, pozostawienie wszystkich kluczy na zdalnym hoście wraz z sesją screena (lub nawet dłużej do ponownego uruchomienia w przypadku wspomnianego postu) nie jest zbyt bezpieczne.
midenok
0

Przejrzałem inne odpowiedzi i nie mogłem znaleźć mojej. Oto czego używam. Utwórz plik ~/.screenrc-wrappero następującej treści:

escape ^xx
bindkey ^Ad detach

I dodaj to do ~/.bashrc(lub ~/.zshrcjeśli tego używasz):

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

W ten sposób użyjesz dwóch sesji ekranowych - jedna to „wrapper”, a druga wewnętrzna. To pozwoli utrzymać to drugie przy życiu, nawet gdy się wylogujesz i nadal będzie mieć włączony ssh-agent. Kolejną miłą funkcją jest to, że zapamięta konfigurację twojego okna - jeśli używasz podzielonych okien, może być bardzo przydatne.

Możesz znaleźć tę funkcję w kontekście w moich plikach dot .

d33tah
źródło