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개 스크립트를 차단 해제된 상태로 유지할 수 있습니다.

관련 정보