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