Bash 스크립트 - 중단된 서버를 무시하는 방법

Bash 스크립트 - 중단된 서버를 무시하는 방법

저는 1000개 이상의 서버에서 백그라운드로 명령을 실행하는 스크립트를 작성했습니다. 때때로 스크립트가 서버 중 하나에서 중단되는 경우가 있습니다. 스크립트를 실행할 때 서버가 중단되는 경우(평균 로드가 높기 때문에) 명령이 해당 서버에서 중단될 수도 있습니다. 스크립트가 다음 호스트로 이동하여 계속 실행될 수 있도록 해당 호스트를 건너뛸 수 있는 방법이 있습니까?

내 스크립트의 두 가지 주요 기능을 강조하고 있지만 "ConnectTimeout" 및 대기 키워드를 제공하는 데 운이 없습니다.

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

작성된 스크립트~일 것이다모든 원격 명령을 동시에 계속 실행하세요. 단, wait이 명령을 사용하려면 백그라운드 작업이 완료될 때까지 명시적으로 기다립니다. 부하가 높은 서버에 대해 설명하는 경우 이는 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. 나는 일반적으로 이와 같은 작업을 두 개의 스크립트로 나눕니다.

local.sh

일반적으로 이 스크립트에는 호스트 이름이라는 단일 인수가 있으며 필요한 유효성 검사, 비행 전 작업, 로깅 등을 수행합니다. 예:

#!/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개는 방해받지 않고 계속 작동할 수 있습니다.

관련 정보