Como saber se uma conexão do ssh ControlMaster está em uso

3

Gostaria de usar ssh 's ControlMaster para compartilhar conexões para aumentos de velocidade. Eu estou tentando script para que eu possa iniciar / reiniciar / parar um número de conexões para hosts diferentes.

Como posso determinar se alguma dessas conexões está em uso? Se eu matá-los quando uma sessão ssh estiver aberta, ela será fechada

Meu script de reinicialização seria idealmente parecido com (pseudo-script) - o script de parada seria equivalente sem o comando ssh na parte inferior:

for HOST in $HOST_LIST
  do
    MASTER_PID='find_master_pid $HOST'
    if $MASTER_PID
      then
        if 'find_child_pid'
          echo Connection to $HOST in use: not terminating
        else
          kill -SIGHUP $MASTER_PID
        fi
    ssh -TMNf $HOST
    
por David Fraser 10.12.2010 / 10:31

3 respostas

3

Você poderia simplesmente usar

ssh -o ControlPath=$socket -O check 

para cada $ socket que você abriu (fácil se você mantê-los em um único diretório).

Isso retorna 255 se a verificação falhar (a conexão não está mais ativa), um outro valor se for aprovado. Você pode precisar especificar o nome do host também, mas nada que um awk no $ socket não lhe dará:)

    
por 10.12.2010 / 12:35
0

Minha abordagem atual é usar lsof para encontrar os soquetes Unix. Se eu souber o nome do arquivo de destino especificado por ControlPath , posso procurar o processo mestre assim:

function find_master_pid() {
  lsof -a -U -u $USER -c ssh | grep $CM_DIR/$RUSER@$HOST | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u
}

Isso me dará o PID (infelizmente, dar o nome do arquivo do soquete unix diretamente para lsof não funciona, caso contrário eu poderia pedir para ele me mostrar o pid com -f ; daí o sed e cut )

A pesquisa pelo processo filho é mais complicada. O processo mestre abre um novo soquete para cada processo filho, conectado ao arquivo padrão. O processo filho contém um soquete que simplesmente marcou socket . No entanto, o inode retornado por lsof é um a menos que o soquete do processo mestre correspondente. Portanto, o seguinte encontra processos filho que estão conectados ao processo mestre (isso precisa do $MASTER_PID para verificar)

function find_child_pid() {
  for CHILD_PID in 'lsof -a -U -u $USER -c ssh | grep socket | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u'
    do
      CHECK_PID=0
      for NODE in 'lsof -a -U -u $USER -p $CHILD_PID -F i | grep ^i | sed 's/i//''
        do
          MASTER_NODE=$((NODE+1))
          CHECK_PID='lsof -a -U -u $USER -p $MASTER_PID | grep $MASTER_NODE | wc -l'
          [[ $CHECK_PID == 1 ]] && echo $CHILD_PID
        done
    done
}
    
por 10.12.2010 / 10:37
0

@ A resposta de Renik não funcionou para mim. Veja abaixo o que aconteceu.

Isso funciona para mim usando apenas o arquivo de soquete para o mestre de controle:

$ ssh -o ControlPath=~/.ssh/<controlfile> -O check <bogus arg>

Exemplo

Aqui está um exemplo em que já estabeleci uma conexão com um servidor remoto:

$ ssh -o ControlPath=~/.ssh/master-57db26a0499dfd881986e23a2e4dd5c5c63e26c2 -O check blah
Master running (pid=89228)
$

E com isso desconectado:

$ ssh -o ControlPath=~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O check blah
Control socket connect(/Users/user1/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74): No such file or directory
$

Se ainda estivesse conectado, isso forçaria a saída imediata:

$ ssh -o ControlPath=~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O exit blah
Exit request sent.
$

Não está claro para mim, mas parece ser um bug em ssh que requer um argumento adicional no final, mesmo que blah não tenha sentido no contexto dos switches que estou usando. / p>

Sem isso me dá isso:

$ ssh -o ControlPath=~/.ssh/master-57db26a0499dfd881986e23a2e4dd5c5c63e26c2 -O check
usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-E log_file] [-e escape_char]
           [-F configfile] [-I pkcs11] [-i identity_file]
           [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
           [-O ctl_cmd] [-o option] [-p port]
           [-Q cipher | cipher-auth | mac | kex | key]
           [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] [user@]hostname [command]

Informações da versão

OSX
$ ssh -V
OpenSSH_6.9p1, LibreSSL 2.1.8
CentOS 7.x
$ ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017

Confirmei que em ambas as versões, a necessidade do argumento falso adicional era necessária.

Referências

por 31.07.2018 / 01:23