web-dev-qa-db-fra.com

Comment démarrer automatiquement tmux sur une session SSH?

J'ai une dizaine de serveurs auxquels je me connecte régulièrement avec SSH. Chacun a une entrée dans le fichier ~/.ssh/config de mon ordinateur local.

Pour ne pas perdre le contrôle de mon processus en cours lorsque ma connexion Internet est interrompue, je travaille toujours dans une session tmux. Je voudrais un moyen de connecter automatiquement tmux à chaque fois qu'une connexion SSH est démarrée. Je n'ai donc pas besoin de toujours taper tmux attach || tmux new après I SSH.

Malheureusement, cela n’est pas aussi simple que je l’espérais au départ.

  • Je ne souhaite ajouter aucune commande au ~/.bashrc sur les serveurs car je ne le souhaite que pour les sessions SSH, pas pour les sessions locales.
  • L'ajout de tmux attach || tmux new au ~/.ssh/rc sur les serveurs entraîne simplement le déclenchement de l'erreur not a terminal après la connexion, même lorsque l'option RequestTTY force est ajoutée à la ligne de ce serveur dans mon fichier de configuration SSH local.
50
Alex Ryan

D'accord, j'ai trouvé une solution généralement satisfaisante. Dans mon ~/.bashrc local, j'ai écrit une fonction:

function ssh () {/usr/bin/ssh -t $@ "tmux attach || tmux new";}

qui écrase la fonction de terminal ssh pour appeler le programme ssh intégré avec les arguments donnés, suivis de "tmux attach || tmux new".

(Le $@ dénote tous les arguments fournis sur la ligne de commande, donc ssh -p 123 user@hostname sera étendu à ssh -t -p 123 user@hostname "tmux attach || tmux new")

(L'argument -t est équivalent à RequestTTY Force et est nécessaire pour la commande tmux.)

38
Alex Ryan

Configuration côté serveur:

Pour démarrer automatiquement tmux sur votre serveur distant lorsque vous vous connectez normalement via SSH (et uniquement SSH), modifiez le ~/.bashrc de votre utilisateur ou de la racine (ou des deux) sur le serveur distant en conséquence: 

if [[ -z "$TMUX" ]] && [ "$SSH_CONNECTION" != "" ]; then
    tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi

Cette commande crée une session tmux appelée ssh_tmux s'il n'en existe aucune, ou se rattache à une session existante portant ce nom. Si votre connexion est interrompue ou si vous avez oublié une session il y a plusieurs semaines, chaque connexion SSH vous ramène automatiquement à la session tmux-ssh que vous avez laissée.

Connectez-vous à partir de votre client:

Rien de spécial, juste ssh user@hostname.

50
kingmeffisto

J'ai utilisé les lignes de @kingmeffisto (je ne suis pas autorisé à commenter cette réponse) et j'ai ajouté une sortie afin que terminer tmux mette également fin à la connexion ssh. Cependant, cela cassait les sessions SFTP, je devais donc vérifier $SSH_TTY au lieu de $SSH_CONNECTION.

EDIT 4/2018: Ajout du test du terminal interactif via [[ $- =~ i ]] pour permettre à des outils tels que Ansible de fonctionner.

if [ -z "$TMUX" ] && [ -n "$SSH_TTY" ] && [[ $- =~ i ]]; then
    tmux attach-session -t ssh || tmux new-session -s ssh
    exit
fi
10
moneytoo

Comme décrit dans cet article de blog vous pouvez ssh, puis vous attacher à une session tmux existante avec une seule commande:

ssh hostname -t tmux attach -t 0
7
Fabian Pedregosa

Connecter:

ssh user@Host -t "tmux new-session -s user || tmux attach-session -t user"

Pendant la session:

Utilisez Ctrl+d pour terminer la session (la fenêtre tmux se ferme) ou Ctrl+b d pour supprimer temporairement de la session et vous y reconnecter ultérieurement.

Souviens-toi! Si votre serveur a redémarré la session perdue!

Lorsque vous êtes dans tmux à tout moment, vous pouvez utiliser Ctrl+b s pour voir la liste de sessions et changer de courant.

Corrige ton .bashrc:

Je vous recommande de définir la fonction universelle dans votre .bashrc:

function tmux-connect {
    TERM=xterm-256color ssh -p ${3:-22} $1@$2 -t "tmux new-session -s $1 || tmux attach-session -t $1"
}

Il utilise le port 22 par défaut. Définissez également vos alias de connexion rapide:

alias office-server='tmux-connect $USER 192.168.1.123'
alias cloud-server='tmux-connect root my.remote.vps.server.com 49281'

Connexion sans mot de passe:

Et si vous ne voulez pas taper le mot de passe à chaque fois, générez des clés .ssh pour vous connecter automatiquement:

ssh-keygen -t rsa
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa

Placez votre clé publique sur l'hôte distant:

ssh-copy-id -p <port> user@hostname

Conseils supplémentaires:

Si vous voulez utiliser id_session temporaire qui correspond à une session locale bash, utilisez tmux id:

SID=$USER-$BASHPID
ssh user@Host -t "tmux new-session -s $SID || tmux attach-session -t $SID"
7
DenisKolodin

byobu est un wrapper très utile pour tmux/screen. Se connecte à une session existante si présente ou en crée une nouvelle.

Je l'utilise avec autossh qui permet de reconnecter gracieusement la session ssh. Fortement recommandé en cas de problèmes de connectivité intermittents.

function ssh-tmux(){
  if ! command -v autossh &> /dev/null; then echo "Install autossh"; fi
  autossh -M 0 $* -t 'byobu || {echo "Install byobu-tmux on server..."} && bash'
}
1
Sandeep

Cela pourrait vous être utile - utilisez ssh dans une boucle et reconnectez-vous ou connectez-vous à une session tmux existante afin de disposer d'un moyen simple, fiable et agréable de faire la reconnexion après une panne de réseau

#!/bin/bash
#
# reconnect to or spawn a new tmux session on the remote Host via ssh.
# If the network connection is lost, ssh will reconnect after a small
# delay.
#

SSH_HOSTNAME=$1
TMUX_NAME=$2
PORT=$3

if [[ "$PORT" != "" ]]
then
    PORT="-p $PORT"
fi

if [ "$TMUX_NAME" = "" ]
then
    SSH_UNIQUE_ID_FILE="/tmp/.ssh-UNIQUE_ID.$LOGNAME"

    if [ -f $SSH_UNIQUE_ID_FILE ]
    then
        TMUX_NAME=`cat $SSH_UNIQUE_ID_FILE`
        TMUX_NAME=`expr $TMUX_NAME + $RANDOM % 100`
    else
        TMUX_NAME=`expr $RANDOM % 1024`
    fi

    echo $TMUX_NAME > $SSH_UNIQUE_ID_FILE

    TMUX_NAME="id$TMUX_NAME"
fi

echo Connecting to tmux $TMUX_NAME on hostname $SSH_HOSTNAME

SLEEP=0
while true; do

    ssh $PORT -o TCPKeepAlive=no -o ServerAliveInterval=15 -Y -X -C -t -o BatchMode=yes $SSH_HOSTNAME "tmux attach-session -t $TMUX_NAME || tmux -2 -u new-session -s $TMUX_NAME"
    SLEEP=10
    if [ $SLEEP -gt 0 ]
    then
        echo Reconnecting to session $TMUX_NAME on hostname $SSH_HOSTNAME in $SLEEP seconds
        sleep $SLEEP
    fi
done
1
Neil McGill

IMHO il y a deux solutions possibles qui manquent dans la liste des réponses:

  1. Utilisation du fichier ~/.ssh/authorized_keys de l'hôte:
command="tmux attach-session -t mysession || tmux new-session -s mysession" ssh-ed25519 AAAAfoo23bar45foo23bar45foo23bar45foo23bar45foo23bar45foo23bar45foo23bar45 user@client

Cela fonctionnera évidemment avec tous les clients disposant de la clé privée correspondante, ce qui peut être un inconvénient, selon le cas. Il y a un risque qu'en cas de problème, il ne soit plus possible d'entrer dans le serveur.

  1. En utilisant le ~/.ssh/config file du client, que @op utilise déjà de toute façon:
Host myhost
  Hostname Host
  User user
  RequestTTY yes # tmux needs a tty and won't work without one!
                 # sometimes requires "force" instead of "yes".
  RemoteCommand tmux attach-session -t mysession || tmux new-session -s mysession

Considérant le risque avec l'option (1), cela pourrait être la meilleure solution. En cas de problème, il suffit de commenter les deux lignes.

0
Rainer Verteidiger

Je sais que je ressuscite un vieux fil, mais j’ai travaillé sur la solution bashrc et je pense qu’elle a une utilité:

#attach to the next available tmux session that's not currently occupied
if [[ -z "$TMUX" ]] && [ "SSH_CONNECTION" != "" ];
then
    for i in `seq 0 10`; do #max of 10 sessions - don't want an infinite loop until we know this works
            SESH=`tmux list-clients -t "$USER-$i-tmux" 2>/dev/null` #send errors to /dev/null - if the session doesn't exist it will throw an error, but we don't care
            if [ -z "$SESH" ] #if there's no clients currently connected to this session
            then
                tmux attach-session -t "$USER-$i-tmux" || tmux new-session -s "$USER-$i-tmux" #attach to it
                break #found one and using it, don't keep looping (this will actually run after tmux exits AFAICT)
            fi #otherwise, increment session counter and keep going
    done

fi

Il y a un plafond à 10 (11) sessions pour le moment - je ne voulais pas tuer mon serveur avec une boucle infinie dans bashrc. Cela semble fonctionner de manière assez fiable, à part l'erreur de tmux qui échoue sur list-clients si la session n'existe pas.

0
Brydon Gibson