Método 1: ssh-keyscan
Um método seria usar o comando ssh-keyscan
para ver se um daemon ssh está ativo e funcionando.
Basta percorrer os endereços IP e ssh-keyscan <ip> | grep -v ...
de cada servidor. Se o servidor estiver lá, o status retornado pela execução do comando ssh-keyscan ... | grep -v ...
será 0, qualquer outra coisa (1 ou superior) significa que não há um servidor lá.
Exemplo
$ for IP_ADDRESS in 'cat $IP_FILE' ; do
ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
[ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
done
Apenas para detalhar isso um pouco mais, é claro o que está acontecendo, o ssh-keyscan $IP_ADDRESS 2>&1
será executado, qualquer saída retornada (ambos stderr
& stdout
serão mesclados). Toda essa saída é canalizada para o grep -v "^$"
, que retornará um 0 para as linhas que retornam a saída (servidores ssh em execução) e um 1 para os servidores que não retornam (o "^$"
é uma linha em branco).
O mecanismo de looping acima (para loop) funciona porque o arquivo contém apenas uma cadeia de caracteres dos quais nenhum é um espaço e que cada "string" é terminada por um novo caractere de linha. Por padrão, um espaço é o caractere de separação especial usado para designar ao loop for como analisar os argumentos que estão sendo passados para ele. Esse caractere é definido pela variável $IFS
e pode ser substituído de forma que seja o novo caractere de linha ( IFS='^M'
), por exemplo.
Você pode tornar isso um pouco mais eficiente ao substituir o cat $IP_FILE
por $( < $IP_FILE )
. Por exemplo:
$ for IP_ADDRESS in $( < $IP_FILE ) ; do
ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
[ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
done
Se as linhas no arquivo $IP_FILE
incluírem espaços, você poderia substituir o $IFS
, conforme discutido há pouco, para que ele fosse definido como ^M
ou um loop while poderia ser usado, ou seja, ( while read -ra line ; do ... ; done < $IP_FILE
).
$ while read -ra IP_ADDRESS ; do
ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
[ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
done < $IP_FILE
Seu exemplo
touch logfile_$(date "+%Y%m%d%T")
IP_FILE="ip.txt"
LOGFILE="logfile_$(date "+%Y%m%d%T")"
if [[ ! -f ${IP_FILE} ]]; then
echo "Cannot find IP address!"
exit 1
fi
for IP_ADDRESS in 'cat $IP_FILE' ; do
#ssh $IP_ADDRESS >> $LOGFILE 2>&1
ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
[ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
done
Método # 2: nmap
Você também pode fazer algo com a ferramenta nmap
.
$ nmap -A -iL ip.txt -p T:22
Isso passará pelo arquivo ip.txt
, que pode conter nomes de host e endereços IP, e varrerá a porta TCP # 22 de cada um, retornando resultados semelhantes aos seguintes:
Nmap scan report for somehost.somedom.local (192.168.1.200)
Host is up (0.012s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.3 (protocol 2.0)
| ssh-hostkey: 1024 2e:32:85:a2:56:23:01:f1:c2:8f:df:aa:83:7a:1e:ad (DSA)
|_2048 f6:a1:23:1d:aa:44:4a:ce:b4:d3:f4:fe:e1:00:47:b7 (RSA)