![Bash 스크립트 - 중단된 서버를 무시하는 방법](https://linux55.com/image/146783/Bash%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%20-%20%EC%A4%91%EB%8B%A8%EB%90%9C%20%EC%84%9C%EB%B2%84%EB%A5%BC%20%EB%AC%B4%EC%8B%9C%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95.png)
나는 백그라운드에서 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개 스크립트를 차단 해제된 상태로 유지할 수 있습니다.