¿Cómo crear un script bash para verificar la conexión SSH?

86

Estoy en el proceso de crear un script bash que iniciaría sesión en las máquinas remotas y crearía claves públicas y privadas.

Mi problema es que las máquinas remotas no son muy confiables y no siempre funcionan. Necesito un script bash que verifique si la conexión SSH está activa. Antes de crear las claves para uso futuro.

chutsu
fuente
2
Normalmente, se ejecuta ssh-keygenpara generar un par de claves en la máquina local y luego ssh-copy-idpara copiar la clave pública en las máquinas remotas. Parece que estás haciendo las cosas de manera diferente. ¿Por qué, cuál es tu objetivo?
Ephemient
1
Dado que obviamente está cambiando la forma en que las máquinas remotas establecen conexiones, considere implementar mosh . mosh.mit.edu Está destinado a complementar SSH en conexiones inestables. Tengo muy buenas experiencias con eso.
Aeyoun
@ephemient Sé que es un poco tarde, pero parece bastante sencillo que la clave no fue para la máquina local o no para el usuario local.
Carrito abandonado

Respuestas:

170

Puede verificar esto con el valor de retorno que ssh le brinda:

$ ssh -q user@downhost exit
$ echo $?
255

$ ssh -q user@uphost exit
$ echo $?
0

EDITAR: Otro enfoque sería usar nmap (no necesitará tener claves o cosas de inicio de sesión):

$ a=`nmap uphost -PN -p ssh | grep open`
$ b=`nmap downhost -PN -p ssh | grep open`

$ echo $a
22/tcp open ssh
$ echo $b
(empty string)

Pero tendrá que grep del mensaje (nmap no usa el valor de retorno para mostrar si un puerto fue filtrado, cerrado o abierto).

EDIT2:

Si está interesado en el estado real del puerto ssh, puede sustituirlo grep openpor egrep 'open|closed|filtered':

$ nmap host -PN -p ssh | egrep 'open|closed|filtered'

Solo para estar completo.

Tim Cooper
fuente
1
Para estar completo, ¿puede indicar qué código de retorno significa éxito y cuál falla en SSH?
Henley Chiu
¿Se pregunta qué pasa si el intento de SSH se bloquea allí?
Sibbs Gambling
2
¡Gran respuesta! Sin embargo, no menciona que intentar sshingresar a un host inactivo falla solo después de un tiempo de espera de, por ejemplo, 60 segundos, lo que puede ser prohibitivo para algunos usos. Además, si se define un nombre de host ~/.ssh/config, el primer sshenfoque funciona mientras que el segundo nmapfalla Failed to resolve "<hostname>".
ssc
2
ninguna explicación sobre los comandos ... o lo que estás haciendo realmente ... ¿qué es $?? etc
Toskan
Una forma aún más concisa de # 1: ssh -q user@downhost exit | echo $? tubería de conexión en el resultado de eco
philn5d
22
ssh -q -o "BatchMode=yes" -i /home/sicmapp/.ssh/id_rsa <ID>@<Servername>.<domain> "echo 2>&1" && echo $host SSH_OK || echo $host SSH_NOK
Brian Ott
fuente
2
Salida de una línea: (ssh -q -o "BatchMode = yes" -o "ConnectTimeout = 3" [email protected] "echo 2> & 1" && echo SSH_OK || echo SSH_NOK) | tail -n1
Xdg
21

Puedes usar algo como esto

$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

Esto dará como resultado "ok" si la conexión ssh está bien

Adrià Cidre
fuente
14

Complementando la respuesta de @Adrià Cidrepuedes hacer:

status=$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

if [[ $status == ok ]] ; then
  echo auth ok, do something
elif [[ $status == "Permission denied"* ]] ; then
  echo no_auth
else
  echo other_error
fi
iarroyo
fuente
7

Tratar:

echo quit | telnet IP 22 2>/dev/null | grep Connected
GUESSWHOz
fuente
1
Un problema de este enfoque es que no reconoce los hosts definidos en ssh_config (es decir, / etc / ssh / config o ~ / .ssh / config)
Ding-Yi Chen
1

El siguiente sshcomando debe tener un código de salida de 0una conexión exitosa y un valor distinto de cero en caso contrario.

ssh -q -o BatchMode=yes [email protected] exit

if [ $? != "0" ]; then
    echo "Connection failed"
fi
mate
fuente
¡Excelente! Recomiendo también agregar -o ConnectTimeout = 5, para una salida más rápida en los casos en que se filtra el puerto de destino.
Daniel
0

En caso de que alguien solo desee verificar si el puerto 22 está abierto en una máquina remota, este simple comando netcat es útil. Lo usé porque nmap y telnet no estaban disponibles para mí. Además, mi configuración de ssh usa autenticación de contraseña de teclado.

Es una variante de la solución propuesta por GUESSWHOz.

nc -q 0 -w 1 "${remote_ip}" 22 < /dev/null &> /dev/null && echo "Port is reachable" || echo "Port is unreachable"
Mathieu C.
fuente
0

Si desea verificar que existe una carpeta remota, o cualquier otro archivo de prueba realmente:

if [ -n "$(ssh "${user}@${server}" [ -d "$folder" ] && echo 1; exit)" ]; then
    # exists
else
    # doesn't exist
fi

No olvide las comillas en "$(ssh ...)".

Jonathan H
fuente
Esto no responde a la pregunta. El OP quiere verificar si se puede establecer una conexión SSH sin verificar un archivo en una ubicación ssh remota.
Rakib Fiha
0

Ejemplo de uso del script BASH 4+:

# -- ip/host and res which is result of nmap (note must have nmap installed)
ip="192.168.0.1"
res=$(nmap ${ip} -PN -p ssh | grep open)

# -- if result contains open, we can reach ssh else assume failure) --
if [[ "${res}" =~ "open" ]] ;then
    echo "It's Open! Let's SSH to it.."
else
    echo "The host ${ip} is not accessible!"
fi
Mike Q
fuente
0

https://onpyth.blogspot.com/2019/08/check-ping-connectivity-to-multiple-host.html

El enlace anterior es para crear un script de Python para verificar la conectividad. Puede utilizar un método similar y utilizar:

ping -w 1 -c 1 "IP Address" 

Comando para crear script bash.

Dheeraj Kumar
fuente
2
Esto solo hará ping a la IP remota. No garantiza si la conexión ssh es posible.
RJ
Gracias por señalar eso, aquí está el código para ssh xlinu.blogspot.com/2019/09/… export user = "username" export pass = "password" export i = "hostname" export SSHPASS = $ pass sshpass -e ssh $ usuario @ $ i -q "echo $ i es accesible"
Dheeraj Kumar
-7

Siento que estás tratando de resolver el problema equivocado aquí. ¿No deberías intentar hacer que los demonios ssh sean más estables? Intente ejecutar algo como monit , que verificará si el demonio se está ejecutando y lo reiniciará si no lo está (dándole tiempo para encontrar la raíz del problema detrás de sshd que se apaga). ¿O el servicio de red es problemático? Intente mirar man ifup. ¿A Whole Damn Thing le gusta cerrarse contigo? Bueno, ese es un problema mayor ... intente mirar sus registros (comience con syslog) para encontrar fallas de hardware o servicios que están apagando su boxen (¿tal vez un monitor de temperatura?).

Hacer que sus scripts sean tolerantes a fallas es excelente, pero es posible que también desee que su boxen sea tolerante a fallas.

Sam Bisbee
fuente
4
Sam: hay casos de uso válidos para que el script lo verifique. Por ejemplo (como yo): tengo un trabajo cron ejecutándose en mi máquina para hacer una copia de seguridad de mis datos a través de rsync en mi nas de casa. Ahora estoy afuera o incluso desconectado con bastante frecuencia y necesito reprogramar si la conexión no estaba disponible. Mi boxen funciona bastante bien, pero como dice el refrán: siempre es el cable (también conocido como red)
stwissel