removendo hosts ssh-dead da matriz

0

alguém poderia explicar por que "s" e "localhot" são mantidos no HOSTLIST final?

"s" está lá, embora estivesse sendo removido ...

$ HOSTLIST="localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1"
$ for h in ${HOSTLIST};do { timeout 3 bash -c "</dev/tcp/${h}/22" 2>/dev/null; } || { echo removing $h from HOSTLIST;HOSTLIST=${HOSTLIST[@]/${h}}; };done ; echo final HOSTLIST :: ${HOSTLIST}
removing sdfsd from HOSTLIST
removing sdfs from HOSTLIST
removing s from HOSTLIST
removing fsdf from HOSTLIST
removing sdfs from HOSTLIST
removing fsdf from HOSTLIST
removing sdf from HOSTLIST
final HOSTLIST :: localhot s localhost 127.0.0.1
$
$ telnet s 22
telnet: s: Name or service not known
s: Host name lookup failure
$ telnet localhot 22
telnet: localhot: Name or service not known
localhot: Host name lookup failure
$
    
por DonJ 12.03.2018 / 16:11

2 respostas

3

Ao remover s , você remove o primeiro s na string $HOSTLIST . Isso provavelmente não será o s que você deseja remover (observe localhot na saída).

Melhor usar uma matriz e construir uma matriz de hosts ok, talvez algo como

hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )

for h in "${hostlist[@]}"; do
    if timeout 3 bash -c "</dev/tcp/$h/22" 2>/dev/null; then
       ok+=( "$h" )
    fi
done

printf 'Ok host: %s\n' "${ok[@]}"
    
por 12.03.2018 / 16:18
0

Você também pode fazer isso iterando os índices da matriz ( ${!hostlist[@]} , observe o ! ) em vez dos valores ( ${hostlist[@]} ) e, em seguida, usando unset para excluir índices de matriz indesejados.

por exemplo, com base na resposta de @ Kusalananda:

hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )

for h in "${!hostlist[@]}"; do
  if ! timeout 3 bash -c "</dev/tcp/${hostlist[$h]}/22" 2>/dev/null; then
   unset hostlist[$h]
  fi
done

printf 'Ok hosts: %s\n' "${hostlist[@]}"

ou, se tiver netcat instalado, você pode usar nc em vez do bash /dev/tcp interno (deve ser um pouco mais rápido do que forking timeout e bash para cada host):

hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )

for h in "${!hostlist[@]}"; do
  if ! nc -w 3 "${hostlist[$h]}" 22 >& /dev/null; then
   unset hostlist[$h]
  fi
done

printf 'Ok hosts: %s\n' "${hostlist[@]}"

Se você não precisa fazer mais nada dentro da instrução if / then , você a encurta ainda mais:

hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )

for h in "${!hostlist[@]}"; do
  nc -w 3 "${hostlist[$h]}" 22 >& /dev/null || unset hostlist[$h]
done

printf 'Ok hosts: %s\n' "${hostlist[@]}"
    
por 12.03.2018 / 23:17