удаление ssh-мертвых хостов из массива

Во-первых, вы всегда должны заключать выражение grep в кавычки, так как попытки запомнить, какая оболочка что делает с каким специальным символом - это мучение:

grep -o -E '[x]{3,4}' testfile

Во-вторых, grep найдет минимальное совпадение, это просто, так что с радостью найдет 3 или 4 пробега x в более длинном пробеге xs. Чтобы предотвратить это, необходимо какое-то граничное условие, чтобы не совпадало с подмножеством более длинного пробега. grep с поддержкой PCRE может использовать обходные пути нулевой ширины для достижения этого:

(echo xxx; echo xxxxxx) | grep -P '(?<!x)xxx(?!x)'
0
12.03.2018, 17:11
2 ответа

При удалении sвы удаляете первый sв строке $HOSTLIST. Скорее всего, это будет не тот s, который вы хотите удалить (примечание localhotв выходных данных ).

Лучше использовать массив и создать массив из подходящих хостов, может быть что-то вроде

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[@]}"
3
28.01.2020, 02:24

Вы также можете сделать это, перебирая индексы массива (${!hostlist[@]}, обратите внимание на !), а не значения (${hostlist[@]}), а затем используя unsetдля удаления нежелательные индексы массива.

например, на основе ответа @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[@]}"

или, если у вас установлен netcat, вы можете использовать ncвместо bash /dev/tcp, встроенный -в (должен быть немного быстрее, чем разветвление timeoutи bashдля каждого хозяин):

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[@]}"

Если вам больше не нужно делать что-либо внутри оператора if/ then, вы можете сократить его еще больше:

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[@]}"
0
28.01.2020, 02:24

Теги

Похожие вопросы