Скрипт Bash - способ игнорировать зависший сервер

Скрипт Bash - способ игнорировать зависший сервер

Я написал скрипт, который запускает команды на 1000+ серверах в фоновом режиме. Иногда скрипт зависает на одном из серверов. Если/когда сервер зависает (из-за высокой средней нагрузки) при запуске скрипта, команда также может зависнуть на этом сервере. Есть ли способ пропустить этот хост, чтобы скрипт мог перейти на следующий хост и продолжить работу?.

Я выделяю две основные функции моего скрипта, но не могу указать ключевые слова «ConnectTimeout» и wait.

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 &
}

решение1

Ваш сценарий как он написанбыпродолжать выполнять все ваши удаленные команды одновременно, но для вашего использования waitwhich явно будет ждать завершения фоновой задачи. В случае, если вы описываете сервер с высокой нагрузкой, это означает, что ваша sshкоманда не истекает по времени, а просто занимает много времени для выполнения, поэтому скрипт делает именно то, что вы ему просите. ConnectTimeoutне имеет смысла, когда вы можете успешно установить sshсоединение.

Если вы хотите использовать этот тип скрипта, а не инструмент, предназначенный для распределенного удаленного выполнения, такой какАнсибль, я могу изменить ваш сценарий следующим образом:

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" &
}

Также, возможно, стоит рассмотреть возможность разделения теста «могу ли я подключиться к хосту по SSH» и теста «могу ли я выполнить задание»:

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

решение2

По мере того, как ваши локальные и удаленные команды становятся все более сложными, вы быстро перегружаетесь попытками втиснуть все это в один связный сценарий, а при наличии сотен или тысяч фоновых процессов вы, скорее всего, столкнетесь с проблемами конкуренции за ресурсы даже на мощной локальной машине.

Вы можете взять это под контроль с помощью xargs -P. Обычно я разбиваю такие задачи на два скрипта.

локальный.ш

Обычно этот скрипт имеет один аргумент — имя хоста — и выполняет все необходимые проверки, предполетные задачи, ведение журнала и т. д. Например:

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

удаленный.sh

Скрипт, который вы хотите запустить удаленно, но теперь вам не нужно втискивать его в однострочный текст и иметь дело с адом экранирования кавычек.

Фактическая команда

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

Где:

  • -P 16будет разветвляться до 16 подпроцессов
  • -n 1будет передавать только один аргумент на команду
  • -I {}подставит аргумент вместо {}[здесь это не обязательно, но может быть полезно для построения более сложных вызовов xargs.

Таким образом, даже если один из ваших локальных или удаленных скриптов зависнет, остальные 15 продолжат беспрепятственно работать.

Связанный контент