Comment obtenez-vous l'écran pour vous connecter automatiquement à l'agent ssh actuel lors de la réattachement à un écran existant?


47

Si vous démarrez une session d'écran alors que ssh-agent est en cours d'exécution (à partir de ssh -A agent forwarding), l'accès à ssh-agent fonctionne correctement. Toutefois, si vous vous déconnectez de cette session, vous déconnectez, vous reconnectez-vous (avec le transfert ssh-agent) et vous reconnectez à votre session écran, l'accès à ssh-agent ne fonctionne pas.

Comment cela peut-il être corrigé?

Réponses:


41

1) Dans votre script SSH rc (~ / .ssh / rc), vous allez configurer un lien symbolique depuis un emplacement canonique vers le "courant" SSH_AUTH_SOCK. Voici comment je le fais dans bash (contenu de ~ / .ssh / rc):

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

(et assurez-vous de chmod 755 ~ / .ssh / rc). Le "test" sert simplement à empêcher une erreur de s'afficher si vous n'exécutez pas ssh-agent (c'est-à-dire que vous utilisez ssh sans -A). La seconde moitié de cette commande établit un lien symbolique dans un emplacement canonique qui se met à jour avec la "vraie" SSH_AUTH_SOCK au moment de la connexion. Ceci est indépendant de l'utilisation d'un shell dans ssh ou de l'appel direct d'une commande, fonctionne également avec "ssh -t screen -RRD".

Remarque: l'existence de ~ / .ssh / rc modifie le comportement de sshd. Notamment, il n'appellera pas xauth. Voir man sshd pour plus d'informations et pour résoudre ce problème.

De plus, vous ne devriez pas utiliser "-v" avec ln dès que cela cassera rsync-over-ssh avec les diagnostics suivants:

$ 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) Dans votre .screenrc, il vous suffit de remplacer le SSH_AUTH_SOCK par l'emplacement canonique:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Notez que vous utilisez setenv quel que soit le shell que vous utilisez; Je pense que setenv est la syntaxe de l'écran, pas le shell.

La solution initialement adaptée de ce post , qui ne fonctionne pas, mais a la bonne idée.


Cela suppose que vous vous connectiez d'abord, puis démarrez l'écran. Droite?
InnaM

1
Comment peut-il en être autrement? Comment voulez-vous démarrer l'écran sans être connecté?

1
Vous avez raison. La question était formulée de manière stupide. Mais vous devez vous connecter, démarrer un shell et à partir de cet écran de démarrage? Je fais souvent quelque chose comme "ssh -t some.machine screen -R".
InnaM

1
Ah ok. Eh bien, je viens d'essayer cela et cela ne fonctionne pas (c'est-à-dire que ssh-agent n'est pas connecté). Je suppose que ssh ne configure pas les sockets appropriés lorsqu'il est utilisé de cette façon. Peut-être qu'un peu plus d'argumentaire pourrait régler cela?

SSH configure les sockets, il ne démarre jamais le shell. Mais cette astuce est tellement utile que je pense que je pourrais changer mes habitudes.
InnaM

22

Je pense que cela fonctionne comme une simplification de la réponse de @ sandip-bhattacharya. Placez ceci dans votre ~/.bashrcfichier et exécutez la commande d'exportation dans toutes les sessions d'écran en cours d'exécution.

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

Cela se lit "si $SSH_AUTH_SOCKest un socket ( -S) et pas un lien symbolique ( ! -h), créez un nouveau lien symbolique sur le chemin connu. Dans tous les cas, redéfinissez SSH_AUTH_SOCKpour pointer sur le chemin connu.

Les ! -hévite la création d' une référence circulaire si vous exécutez cette opération plusieurs fois.

De plus, si vous l'utilisez byobu, cela se fait automatiquement, sans avoir besoin de modifier de fichier de configuration.

Le seul bogue que j’ai trouvé dans ce problème (qui l’ byobua aussi) est que si vous ouvrez une deuxième connexion ssh -Aou une autre ForwardAgentconnexion, le premier socket sera écrasé et si vous fermez la deuxième connexion avant la première, vous perdrez votre seul bon socket.


1
Cela fonctionne tmuxaussi bien.
Dag Høidahl

Fonctionne très bien, mais se casse lors de l’utilisation de dossiers personnels montés à distance. Dans ce cas, utilisez ~/.ssh/ssh_auth_sock_"$(hostname)"pour votre lien symbolique. Il conservera des sockets d’authentification séparés pour chaque hôte.
Kibber

4

"ssh -t some.machine screen -R" n’exécutera pas bash et ne lancera donc pas le script .bash_profile où le lien symbolique est créé.

Vous pouvez essayer: ssh -t some.machine bash -c "screen -R"

(en supposant que vous utilisez bash comme shell, bien sûr)

Edit: Cette "réponse" est en fait un commentaire sur la première réponse donnée ci-dessus :)


"La première réponse donnée ci-dessus" ne signifie rien car les réponses changent d'ordre car elles sont votées, etc. Merci d'inclure le lien de partage de la réponse à laquelle vous faites référence, car cela ne changera pas.
Rjmunro

3

Je pense que vous avez besoin d'autossh. Je l'utilise depuis des années et, combiné à l'écran, toutes mes sessions de terminal sont entièrement portables et transparentes. Je ferme simplement lappy, je me déplace vers un nouvel emplacement, ouvre lappy et tous mes écrans et écrans imbriqués se connectent automatiquement. Je n'y pense même plus.

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

est la base ... Je ruby'd un script lil pour automatiser le processus dans mon .screenrc pour un hôte donné. (fait également mon transfert ssh, donc dans tous ces endroits différents je peux canaliser ma connexion via mes serveurs)

dans la distribution automatique, il devrait y avoir un programme appelé rscreen (et .. il y en a!)

#!/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"

Cela devrait aider avec les problèmes de ssh / screen

Enfin, afin de maintenir mon agent ssh en marche, j'utilise un trousseau, car je suis en quelque sorte une tête de shell ... Je pense que OSX a quelque chose de disponible pour garder votre agent dans les parages ...


2

Voici la méthode que j'utilise:

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

Je configure habituellement un alias ou une fonction shell avec ces commandes:

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
}

Vous devrez peut-être adapter l'expression régulière ' écran - (r | DR) ' aux commandes exactes que vous utilisez pour rattacher votre écran.

  • La première ligne lit la variable d’environnement SSH_AUTH_SOCK dans l’espace de processus de la commande " screen -r " que vous venez de taper et met à jour la valeur dans votre shell actuel.
  • La deuxième ligne est nécessaire si vous utilisez " ssh -X " pour transférer les connexions X11: elle met à jour la variable DISPLAY de la même manière.

Une mise en garde avec ma méthode: des problèmes peuvent survenir si une autre commande " écran " est exécutée sur l'ordinateur.


-1 pour l'utilisation inutile de sudo.
0xC0000022L

1

En règle générale, je maintiens des sessions à long terme (plus de 6 mois) sur mon lieu de travail sur différents serveurs. Il a donc été difficile de recoller de manière répétée et de disposer d'un agent de transmission ssh viable. Voici ce que j'ai mis en place sur mes systèmes:

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

Si je me connecte simplement au serveur distant sans démarrer / recoller l'écran, il y aura deux "sockets", l'un utilisé par l' screenautre et l'autre par le nouveau shell. Il ne devrait pas y avoir deux sessions de "démarrage", mais une deuxième session peut toujours être démarrée avec reattach -S new; dans cette situation, l'agent serait partagé avec la ~/.ssh/agent-screenvaleur. Pour récupérer un agent de transfert en état de fonctionnement, je me détache puis me reconnecte. X${USER} = XmyusernameCela garantit que le code ne sera pas appelé sudosur le même serveur.


1

J'utilise une variante de ce que @apinstein utilise pour mon .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

Cela fonctionne pour toutes les applications en cours d'exécution dans ma session d'écran. Cela fonctionnerait pour tous les nouveaux shells de votre session screen. Pour les shells existants, vous devez exécuter export SSH_AUTH_SOCK=~/.ssh/ssh_auth_socksur le shell hôte pour le faire fonctionner.

PS Désolé de l'ajouter en tant que réponse indépendante, alors qu'il vient de s'appuyer sur la réponse de @ apinstein. Cela devait se faire car les commentaires dans stackoverflow ne supportent pas les blocs de code.


Pourquoi ne pas toujours symlink et toujours exporter?
Collin Anderson

@CollinAnderson Deux comportements différents. un dans un shell d'écran et un dans le shell de connexion habituel. la variable d'environnement dans un shell de connexion est définie par ssh et donc le lien symbolique y. si nous faisons cela dans une session d'écran, nous allons alors créer une boucle de lien symbolique.
Sandip Bhattacharya

Ah, d'accord. Vous n'auriez besoin de lien que si $ SSH_AUTH_SOCK n'est pas déjà un lien. Voir mon post superuser.com/a/424588/134212
Collin Anderson

0

J'ai essayé ce type de doublure simple, comme suggéré dans la page Faisons en sorte que des amis d'écran et de l'agent-ssh-agent fonctionnent et cela fonctionne pour moi.

Première connexion à Target.Nécessité d'une seule fois.

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

Lancer l'écran pour la première fois .. Il ne faut qu'une fois.

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

Si vous êtes déconnecté ou déconnecté, utilisez cette commande pour vous connecter ultérieurement afin de vous connecter à l'écran existant.

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000

0

Ce sont toutes de très bonnes réponses, je le fais légèrement différemment. Après avoir démarré une nouvelle session ssh et un nouvel écran, je réinitialise la SSH_AUTH_SOCKvariable d’environnement en fonction du contenu de l’environnement root bash. Je n'ai besoin que de temps en temps d'un accès à ssh-agent lorsque j'utilise svn, alors je réinitialise simplement le SSH_AUTH_SOCKsi nécessaire dans ces shells.

Ceci utilise le système de fichiers proc, il est donc spécifique à Linux. Je n’ai testé cela que sur une machine Linux sans tête à laquelle je n’accède que par moi; il faudra peut-être un peu de peaufinage pour que cela fonctionne sur d’autres environnements.

Pour réinitialiser SSH_AUTH_SOCK (cela pourrait être un alias).

$ . ~/bin/screen_auth.sh

screen_auth.sh ressemble à ceci

# 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"

0

Toutes les solutions ci-dessus souffrent de conditions de course (soit dans plusieurs sessions SCREEN, soit dans plusieurs connexions SSH). La seule solution universelle à laquelle je puisse penser est d’appliquer d’abord SSH_AUTH_SOCK au processus de serveur SCREEN screen -r, puis de le rentrer dans la session BASH avant chaque commande non intégrée interactive. Malheureusement, SCREEN et BASH ont été conçus sans prendre en compte ce type de problèmes, il est donc assez difficile de les implémenter correctement (même s’il n’est jamais tard de poster des demandes de fonctionnalités pour les deux projets). Ma tentative a été faite de surmonter ce problème pour les sessions BASH qui peut être trouvée ici:

À installer:

  1. mettre les deux scripts dans $HOME/bin, ajouter un bit exécutable;
  2. assurez-vous que cela $HOME/binva avant /usr/bindans PATH:

    PATH = $ HOME / bin: $ PATH

  3. ajoutez ceci à votre .bashrc:

    configuration $ HOME / bin / screen-helper

Vous pouvez maintenant essayer de créer une session SCREEN dans une session SSH, de détacher, de vous déconnecter, de vous connecter, de vous reconnecter et, espérons ssh-add -l-le, d’afficher correctement vos clés.


Notez que les ssh-agentdémons permanents (comme suggéré ici, superuser.com/a/412052/376867 ) ne souffrent pas de la condition de course, mais souffrent du trousseau de clés périmé. Et ce qui est plus important, il n’est pas très sûr de laisser toutes vos clés sur l’hôte distant en même temps que la session écran (ou même plus longtemps jusqu’au redémarrage en cas de message mentionné).
midenok

0

J'ai parcouru d'autres réponses sans pouvoir trouver la mienne. Voici ce que j'utilise. Créez un fichier ~/.screenrc-wrapperavec le contenu suivant:

escape ^xx
bindkey ^Ad detach

Et ajoutez ceci à votre ~/.bashrc(ou ~/.zshrcsi vous utilisez ça):

  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

De cette façon, vous utiliseriez deux sessions d’écran - l’une est "wrapper" et l’autre est la session interne. Cela gardera ce dernier en vie même lorsque vous vous déconnectez et continuera à avoir ssh-agent. Une autre fonctionnalité intéressante est qu'il mémorisera votre configuration de fenêtre - si vous utilisez des fenêtres divisées, cela peut s'avérer très pratique.

Vous pouvez trouver cette fonctionnalité dans son contexte dans mes fichiers de points .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.