SSH oturumunda tmux otomatik olarak nasıl başlatılır?


92

SSH ile düzenli olarak bağladığım on kadar sunucum var. Her birinin yerel bilgisayarımın ~/.ssh/configdosyasında bir girişi var .

İnternet bağlantım kaçınılmaz olarak düştüğünde çalışan sürecimin kontrolünü kaybetmemek için her zaman bir tmuxoturum içinde çalışırım . Bir SSH bağlantısı her başlatıldığında tmux'un otomatik olarak bağlanmasını sağlamak için bir yol istiyorum, bu yüzden her zaman tmux attach || tmux newSSH'yi girdikten sonra yazmak zorunda kalmam.

Ne yazık ki, bu aslında umduğum kadar basit olmuyor.

  • ~/.bashrcSunuculara herhangi bir komut eklemek istemiyorum çünkü bunu yerel oturumlar için değil, yalnızca SSH oturumları için istiyorum.
  • Yerel SSH yapılandırma dosyamda bu sunucu için satıra seçenek eklendiğinde bile , sunuculara ekleme tmux attach || tmux newyapmak, bağlantıdan sonra ~/.ssh/rchata not a terminalatılmasına neden olur RequestTTY force.

1
Bu popüler bir soru olmaya devam ettiği ve özellikle de bahsettiği gibi ~/.ssh/config: Buraya gelen çoğunuz muhtemelen ilk beş cevabın hiçbirini değil, altıncıyı ( stackoverflow.com/a/52838493/5354137 ) arıyor . Makul bir şekilde yeni olan herhangi bir tmuxsürümle, bu aynı zamanda işleri yapmanın en mantıklı yolu.
Sixtyfive

Yanıtlar:


90

Sunucu tarafı yapılandırması:

Normalde SSH (ve yalnızca SSH) aracılığıyla oturum açarken uzak sunucunuzda tmux'u otomatik olarak başlatmak için, uzak sunucudaki ~/.bashrckullanıcınızın veya kökünün (veya her ikisinin) uygun şekilde düzenleyin:

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

Bu komut, ssh_tmuxyoksa adı verilen bir tmux oturumu oluşturur veya bu adla zaten var olan bir oturuma yeniden bağlanır. Bağlantınız kesildiğinde veya haftalar önce bir oturumu unuttuğunuzda, her SSH oturumu sizi otomatik olarak geride bıraktığınız tmux-ssh oturumuna geri getirir.

İstemcinizden bağlanın:

Özel bir şey yok, sadece ssh user@hostname.


4
Bunun arıyordu ayrıca bir süre önce sizinkine çok benzer kod parçası kullanılır, ancak oturum kullanıcı adı oldu (değişen ssh_tmuxiçin $USER)
Iacchus

3
Moneytoo en Bkz cevabı hakkında yararlı yorum için $SSH_TTYvs $SSH_CONNECTIONde.
Bay Tao

2
çok daha kısa bir süreyi tmux new-session -A -s ssh_tmuxdeğiştirmek için kullanabilirsiniz tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux, biraz daha kafa karıştırıcıysa, -Atmux'a oturumu zaten varsa eklemesini söyler
Gradient

3
" if [[ -n "$PS1" ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]];
Scp" yi bozmamak için

2
@janfrode güvenmeyin $PS1kullanmak, [[ $- == *i* ]]bu interaktif kabuk değilken bile PS1 tanımlanabilir olarak yerine.
Enrico

53

Pekala, çoğunlukla tatmin edici bir çözüm buldum. Benim yerelde ~/.bashrcbir fonksiyon yazdım:

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

temelde, yerleşik ssh programını verilen bağımsız değişkenlerle çağırmak için ssh terminal işlevinin üzerine yazar, ardından "tmux attach || tmux new".

( $@, Komut satırında sağlanan tüm argümanları gösterir, dolayısıyla ssh -p 123 user@hostnamegenişletilecektir ssh -t -p 123 user@hostname "tmux attach || tmux new")

( -tArgüman, RequestTTY Forcetmux komutuna eşdeğerdir ve bu komut için gereklidir.)


22
Sürümünüz tmuxdestekliyorsa, tmux new -A foohangisinin foomümkünse adlandırılmış mevcut bir oturuma ekleneceğini , gerekirse oluşturmayı düşünün . Bu, işlevinizi basitleştirmenizi sağlar /usr/bin/ssh -t "$@" tmux new -A(ve alıntı yaptığınızdan emin olun $@!).
chepner

1
Not: Düzenli olarak bağlandığınız makinelerin bazılarında tmux kurulu değilse, normal function sshtşekilde kullanmaya devam edebilmeniz için söylemek veya benzeri şeyler yapmak isteyebilirsiniz ssh. Aksi takdirde, /usr/bin/sshtmux olmadan bir makineye bağlanırken komut istemine yazmanız yeterli :)
Alex Ryan

1
Tembelseniz , uzak tmux oturumlarına bağlanmak için ssht kullanabilirsiniz . OS X kullanıcıları için demlemek aracılığı dokunun ve Linux kullanıcıları aracılığıyla bir paket oluşturabilirsiniz fpm bununla Makefile'dan veya basitçe kopya sshtetmek ~/bin.
brejoc

1
Haha güzel! Bu tek satırlık bash'ı Makefiles ve brew ile bütün bir Github deposuna sarmak bana biraz fazla geliyor gibi görünüyor ama hey, ne kadar kolaysa o kadar iyi!
Alex Ryan

1
Çözüldü:ssh -t user@hostname "LANG=$LANG tmux attach || tmux new"
alecdwm

23

Bağlan:

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

Oturum sırasında:

Kullanım Ctrl+diçin bitiş oturumu (tmux pencere kapanır) ya da Ctrl+b dkarşı geçici kopmakta oturumundan daha sonra tekrar bağlanabilirsiniz.

Hatırlamak! Sunucunuz yeniden başlatıldıysa oturum kaybedilir!

Tmux'un içindeyken istediğiniz zaman oturum listesiniCtrl+b s görmek ve mevcut olanı başka birine geçirmek için kullanabilirsiniz.

.Bashrc dosyanızı düzeltin:

Evrensel işlevi şu şekilde tanımlamanızı tavsiye ederim .bashrc:

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

22Varsayılan olarak bağlantı noktasını kullanır . Hızlı bağlantı takma adlarınızı da tanımlayın:

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

Şifre olmadan giriş yapın:

Otomatik.ssh olarak oturum açmak için anahtarlar oluşturmak yerine her seferinde şifre yazmak istemiyorsanız :

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

Genel anahtarınızı uzak ana bilgisayara koyun:

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

Ek ipuçları:

Yerel bir bash oturumuna karşılık gelen geçici oturum kimliğini kullanmak istiyorsanız , tmux kimliği olarak kullanın :

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

1
Temiz bir hile önlemek için ||bazı kullanım senaryoları dahil etmek olduğunu new-sessioniçinde .tmux.confve her zamanki kullanın tmux a -t 0.
Florian Wendelborn

4
Tmux'un daha yeni sürümlerinde, tmux new-session -Avarsa hangisini ekleyeceğinizi de kullanabilirsiniz , aksi takdirde yeni bir tane oluşturur.
dragon788

15

@Kingmeffisto'dan satırlar kullandım (bu yanıtı yorumlamama izin verilmiyor) ve bir çıkış ekledim, böylece tmux'u sonlandırmak ssh bağlantısını da sonlandırıyor. Ancak bu, SFTP oturumlarını bozdu, bu yüzden $SSH_TTYyerine kontrol etmek zorunda kaldım $SSH_CONNECTION.

EDIT 4/2018: [[ $- =~ i ]]Ansible gibi araçların çalışmasına izin vermek için etkileşimli terminal için test eklendi .

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

14

Bu blog gönderisinde açıklandığı gibi , ssh yapabilir ve ardından tek bir komutla mevcut bir tmux oturumuna ekleyebilirsiniz:

ssh hostname -t tmux attach -t 0

Cevabımın yaptığı budur ( tmux attach || tmux newher bağlantı için yeni bir tmux oturumu oluşturulmayacak şekilde kullansam da ). İşin zor yanı, doğru komutun olması ssh -t user@host tmux attach || tmux newve komut dizesi içinde bir argüman gerektiren bir şeyi değiştirmenin tek yolunun, yukarıda yaptığım gibi yeni bir işlev oluşturmaktır.
Alex Ryan 15

Biliyorum, ama (benim gibi) bazı insanlar bir işlev tanımlama içermeyen bir tek astar tercih edebilirsiniz
Fabian Pedregosa

3
Bu, '0' adlı bir oturuma bağlanır. Yani, genel formssh [hostname] -t tmux attach -t [sessionName]
David Doria

1
Bu benim için gerçekten iyi çalıştı .. Bu birleştiğinde unix.stackexchange.com/a/116674 olacak .. yani şimdi macun GUI'm şöyle görünüyor .. imgur.com/uFhxN30 . Cntrl + b + d ile oturumların bağlantısını kesebilirim. Çok basit ve kullanışlı ..
alpha_989

14

uzak makinede tmux 3.1 veya daha yenisi¹

Yerel ~/.ssh/configadresinize koyun²:

Host myhost
  Hostname host
  User user
  RequestTTY yes
  RemoteCommand tmux new -A -s foobar

İlgisiz, ancak ASCII olmayan karakterlerle uğraşıyorsanız tmux -u …, uygun ortam değişkenleri setine sahip olmayan makinelerde bile Unicode desteğini açıkça etkinleştirmek için bunu olarak değiştirmenizi tavsiye ederim .

uzak makinede tmux 3.0a veya daha eski

Neredeyse yukarıdakiyle aynı, ancak son satırı ³ olarak değiştirin:

  RemoteCommand tmux at -t foobar || tmux new -s foobar

¹ 2020-10-29 itibariyle, tmux 3.1 veya daha yenisi ile gönderilen dağıtımların listesi zaten oldukça uzundur.

² newkısaltmasıdır new-session.

³ atkısaltmasıdır attach-session.


Uzaktan kumandanın authorized_keysdosyasını kullanan alternatif yöntem :

Herhangi bir ~/.ssh/confignedenle bir dosyaya sahip olmak istemiyorsanız veya uzak makinenin bağlanan makineyi oturuma bağlanmaya / açmaya zorlamasını istiyorsanız, bunu uzaktan kumandanıza ekleyin ~/.ssh/authorized_keys:

command="tmux at -t foobar || tmux new -s foobar" pubkey user@client

Bu, elbette, istediğiniz özel anahtara bağlı olarak olumlu veya olumsuz bir etkisi olabilecek ilgili özel anahtarın yüklü olduğu tüm istemcilerde işe yarar. Bir şeyler ters giderse, artık bağlanmanın mümkün olmaması riski vardır.


neden tmux atyerine tmux a? Ayrıca bunun için adlandırılmış bir oturum kullanmak akıllıca olacaktır veya tmux, ana bilgisayarda oturum açtıktan sonra "rastgele" mevcut oturumlara bağlanacaktır.
Eric

Tmux oturumunu nasıl askıya alırsınız? ssh vurulduktan sonra limbo durumuna geçer Ctrl+A Ctrl+Z.
Eric

Sadece bağlantısı kesiliyor. Bana kalırsa, beklediğim ve mutlu olduğum davranış bu.
Sixtyfive

1
Ctrl-B Dile karşılaştırıldığında işler tedavi eder Ctrl-B Ctrl-Z. Teşekkürler!
Eric

1
Bu, imho, en çok oylanan cevap olmalı. Tam olarak (2) 'yi arıyordum.
cduguet

1

byobu , tmux / screen için güzel ve kullanışlı bir sarmalayıcıdır. Varsa mevcut bir oturuma bağlanır veya yeni bir tane oluşturur.

Bunu , ssh oturumunu incelikle yeniden bağlayan autossh ile kullanıyorum . Kesintili bağlantı sorunları olması durumunda şiddetle tavsiye edilir.

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

Bunu yararlı bulabilirsiniz - bir döngüde ssh kullanır ve mevcut bir tmux oturumuna yeniden bağlanır veya bağlanır, böylece bir ağ kesintisinden sonra yeniden bağlanmanın güzel ve kolay ve güvenilir bir yoluna sahip olursunuz

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

Bu, aslında harika bir kullanıcı deneyimi yaratan şeydir. Terminali her açtığınızda (hem fiziksel hem de ssh) otomatik olarak tmux'u başlatır. Çalışmanıza bir cihazda başlayabilir, terminalden çıkabilir ve diğer cihazda devam edebilirsiniz. Oturuma zaten bağlanmış birini algılarsa, yeni oturum oluşturacaktır. Koy sunucuda kabuğundan bağlı ~/.zshrcveya ~/.bashrc.

 if [[ -z "$TMUX" ]] ;then
     ID="$( tmux ls | grep -vm1 attached | cut -d: -f1 )" # get the id of a deattached session
     if [[ -z "$ID" ]] ;then # if not available attach to a new one
         tmux new-session
     else
         tmux attach-session -t "$ID" # if available attach to it
     fi
fi

0

Eski bir konuyu yeniden canlandırdığımı biliyorum ama bashrc çözümü üzerinde biraz çalıştım ve bunun bir faydası olduğunu düşünüyorum:

#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

Şimdilik 10 (11) oturumda bir sınır var - sunucumu bashrc'de sonsuz bir döngü ile öldürmek istemedim. Oturum yoksa, tmux'un liste istemcilerinde başarısız olması dışında oldukça güvenilir bir şekilde çalışıyor gibi görünüyor.


0

Thie yolu, ssh oturumunuz düştüğünde eski bir tmux örneğine yeniden bağlanmanıza izin verir. execElbette bir çatal kaydeder.

if [ -z "$TMUX"  ]; then
  pid=$(tmux ls | grep -vm1 "(attached)" | cut -d: -f1)
  if [ -z "$pid" ]; then
    tmux new -d -s $pid
  fi

  exec tmux attach -t $pid
fi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.