Script Bash: forma de ignorar el servidor colgado

Script Bash: forma de ignorar el servidor colgado

Escribí un script que ejecuta comandos en más de 1000 servidores en segundo plano. A veces el script se cuelga en uno de los servidores. Si/cuando un servidor se bloquea (debido a una carga promedio alta) al ejecutar un script, es posible que el comando también se bloquee en ese servidor. ¿Hay alguna manera de omitir ese host para que el script pueda pasar al siguiente host y seguir ejecutándose?

Estoy destacando dos funciones principales de mi script, pero no tuve suerte al proporcionar las palabras clave "ConnectTimeout" y esperar.

exec_ssh()
{
for i in `cat $file`
do 
    ssh -q -o "StrictHostKeyChecking no" -o "NumberOfPasswordPrompts 0" -o ConnectTimeout=2 $i $command  2>>/dev/null &
        if wait $!; then
                echo "" >> /dev/null
        else
                echo "$i is not reachable over SSH or passwordless authentication is not setup on the server" >> /tmp/not_reachable
        fi

done >/tmp/output.csv &


run_command()
{
                        export -f exec_ssh
                        export command
                        nohup bash -c exec_ssh &>>$log_file &
}

Respuesta1

Tu guión tal como está escritoharíasiga ejecutando todos sus comandos remotos al mismo tiempo, pero para su uso waitesperará explícitamente a que se complete una tarea en segundo plano. En el caso que usted describe de un servidor de alta carga, esto significa que su sshcomando no está agotando el tiempo de espera, sino que simplemente está tardando mucho en completarse, por lo que el script está haciendo exactamente lo que usted le pide. ConnectTimeoutes discutible cuando puede realizar la sshconexión con éxito.

Si desea utilizar este tipo de script en lugar de una herramienta diseñada para la ejecución remota distribuida comoansible, podría modificar su script de la siguiente manera:

exec_ssh() {
  while read file; do
    if ! ssh -q -o BatchMode=yes -o ConnectTimeout=2 "$i" "$command"  2>>/dev/null & then
      echo "$i is not reachable via non-interactive SSH or remote command threw error - exit code $?" >> /tmp/not_reachable
    fi
  done < "$file" > /tmp/output.csv &
}

run_command() {
    export -f exec_ssh
    export command
    nohup bash -c exec_ssh &>> "$log_file" &
}

También podría valer la pena considerar separar la prueba "puedo enviar SSH al host" y la prueba "puedo completar el trabajo":

if ssh -q -o BatchMode=yes -o ConnectTimeout=2 "$host" true; then
    # connection succeeded
  if ! ssh -q -o BatchMode=yes -o ConnectTimeout=2 "$host" "$command" & then
    echo "Remote command threw $?"
  fi
else
    echo "SSH threw $?"
fi

Respuesta2

A medida que sus comandos locales y remotos se vuelven más complejos, rápidamente se sentirá abrumado al tratar de agrupar todo esto en un script coherente, y con cientos o miles de procesos en segundo plano es probable que se encuentre con problemas de contención de recursos incluso con un sistema robusto. máquina local.

Puedes controlar esto con xargs -P. Normalmente divido tareas como esta en dos guiones.

local.sh

Generalmente, este script tiene un único argumento que es el nombre del host y realiza las validaciones necesarias, tareas previas al vuelo, registro, etc. Por ejemplo:

#!/bin/bash
hostname=$1
# simple
cat remote.sh | ssh user@$hostname
# sudo the whole thing
cat remote.sh | ssh user@$hostname sudo
# log to files
cat remote.sh | ssh user@$hostname &> logs/$hostname.log
# or log to stdout with the hostname prefixed
cat remote.sh | ssh user@$hostname 2>&1 | sed "s/^/$hostname:/"

remoto.sh

El script que desea ejecutar de forma remota, pero ahora no tiene que meterlo en una frase entre comillas y lidiar con el infierno de escapar de las comillas.

El comando real

cat host_list.txt | xargs -P 16 -n 1 -I {} bash local.sh {}

Dónde:

  • -P 16bifurcará hasta 16 subprocesos
  • -n 1alimentará exactamente un argumento por comando
  • -I {}sustituirá el argumento en lugar de {}[no es necesario aquí, pero puede ser útil para construir llamadas xargs más complejas.

De esta manera, incluso si uno de sus scripts locales o remotos se bloquea, los otros 15 seguirán funcionando sin obstáculos.

información relacionada