有人可以解释一下为什么“s”和“localhot”保留在最终的主机列表中吗?
“s”仍然存在,尽管它已被删除......
$ 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
$
答案1
删除时,您删除字符串中的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[@]}"
答案2
您还可以通过迭代来完成此操作指数数组 ( ${!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 来代替(对于每个主机来说,应该比 fork 快一点):/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[@]}"