Você precisa redirecionar o comando stdin do SSH em seu loop para lugar nenhum, para evitar a leitura de todas as suas linhas. Isso deve ser feito:
http_status=$(ssh $name "ps -ef | grep -v grep | grep $service | wc -l" < /dev/null)
Eu tenho um conjunto de servidores mencionados em um arquivo de texto chamado network_list.txt
. Como posso executar através dos servidores e executar o comando e exibir o resultado? Eu tentei o seguinte:
filename="network_list.txt"
service=httpd
while read -r line
do
name="$line"
ping -c 3 $name > /dev/null 2>&1;
RETVAL=$?
if [ $RETVAL -ne 0 ]
then
echo "$name is down"
else
echo "$name is up and running"
fi
http_status=$(ssh $name ps -ef | grep -v grep | grep $service | wc -l)
if [ $http_status -ne 0 ]
then
echo "$service is up and running in $name"
else
echo "$service is down in $name"
fi
done < "$filename"
Mas ele pára após o primeiro servidor.
Obrigado :).
Existe uma solução com os parâmetros -n -x
:
http_status=$(ssh -nx name ps -ef | grep -v grep | grep $service | wc -l)
O -x
desativa o encaminhamento do X11 para eliminar possíveis mensagens X11 forwarding request failed
.
O -n
redireciona o stdin de / dev / null (na verdade, impede a leitura do stdin).
Embora a resposta aceita seja totalmente válida, gostaria de oferecer este script que pode ser útil caso alguém se depare com ele.
Uso
Então, obviamente, você precisaria mudar as linhas sob as linhas "Echo $ server $ serverIP" para refletir os comandos reais que você gostaria de usar. $ 1 é a primeira coisa que você digita depois de "./scriptname.sh" - por exemplo ./scriptname.sh $ 1 $ 2 $ 3 ... - e aqui está como isso se divide:
$ 1 deve ser o arquivo com seus nomes de host. $ 2 é o parâmetro posicional que você passa para a FunctionC (que sempre é chamada neste script de exemplo). $ 2 e $ 3 podem ser usados para chamar as outras Funções (A / B) - alternativamente você pode substituir $ 3 e $ 4 no EOF com "FunctionA" e "FunctionB" se você sempre quiser executá-los.
Espero que isso ajude alguém, que foi INVALUABLE para mim ao implantar pacotes ou testar coisas em todo o domínio.
#! /bin/bash
SVRList='ls ./$1'
#========[ FUNCTIONS ]===============
FunctionA () {
for server in 'cat $SVRList | grep -v ^#' # Makes variable "server" from each line in $SVRlist that is not commented
do
serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
echo "============= $server | $serverIP ============="
#command that you'd like to run locally
done
}
FunctionB () {
for server in 'cat $SVRList | grep -v ^#'
do
passedvar="192.16.${1}"
serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
echo "============= $server | $serverIP ============="
ssh -q $serverIP '#command that you'd like to run remotely'
ssh -q $serverIP '#second command, if you so fancy'
ssh -q $serverIP "ping $passedvar"
#^ is done just to show an example of what can be done
done
}
FunctionC () {
for server in 'cat $SVRList | grep -v ^#'
do
passedvar="192.16.${1}"
serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
echo "============= $server | $serverIP ============="
ssh -q $serverIP "ping $passedvar"
#^ is done just to show the power of positional parameters.
done
}
#========[ SCRIPT ]==========
if [ $# -lt 2 ]
then
printf "Usage: %s <file containing list of server hostnames> <passed variable> <functions> \n" "$(basename "$0")" >&2
exit 64
else
echo "Starting Script"
fi
FunctionC $2
$3
$4
exit
Por que definir service = httpd? Pode ser melhor usar [testing e "service = $ 1", em que $ 1 pode ser httpd, splunkd ou qualquer outro serviço. Além disso, a variável http_status deve ser alterada para algo como "service_status" para tornar o script melhor documentado.
Por que não usar pssh
?
É uma ferramenta SSH paralela que tem suporte para obter uma lista de hosts de um arquivo:
pssh -h network_list.txt ps -ef | grep -v grep | grep $service | wc -l
Depois, você pode analisar a saída como quiser
Tags ssh shell-scripting service