将 for 循环转换为 while 循环比较数组

将 for 循环转换为 while 循环比较数组

有时(比如 8 小时轮班中 4 或 5 次)我需要检查共享服务器提供的站点是否正在加载。我目前有一个可以执行此操作的脚本,但是我使用嵌套 for 循环遍历两个数组以确保只检查该服务器实际提供的站点。我阅读后发现这种方法可能会出现问题,但不知道如何将它们转换为 while 循环或其他方法。我设置了两个数组,一个是所有站点和 dig 所说的为其提供服务的 IP,以及来自 curl 的状态代码(203.0.113.231 - foobar.com - Status_code=200)。另一个数组是服务器上的所有 IP。然后,它将第一个数组与第二个数组进行比较,且只打印第一个数组中位于第二个数组中的元素。

#!/bin/bash
_ORGIFS=$IFS
IFS=$'\n'
_sitecrls=($( for _x in $(grep 'ServerName' /etc/httpd/conf.d/vhost_* |grep -v '000_defaults' |uniq |awk '{print $NF}'); do printf "%s %s %s %s %s\n" "$(dig +short $_x |head -n1) - $_x - Status_code=$(curl -so /dev/null -w %{http_code} $_x)" | sed '/^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/!d'; done ))
_ips=($(ip a |sed -e 's/^[ \t]*//g' -e '/inet /!d' -e '/127.0.0.1/d' -e 's/inet //g' |cut -d'/' -f1))
echo
  for _x in "${_sitecrls[@]}"
  do
    for _z in "${_ips[@]}"
    do
      echo "$_x" |sed -n "/$_z/p"
    done
  done
echo
IFS=$_ORGIFS

答案1

设置IFS你这样做的方式是将命令输出拆分为元素的好方法。然后,使用for迭代数组元素是一个完美的选择。

我不太理解你的代码,但我想知道这是否更容易维护:

#!/bin/bash

IFS=$'\n'

ips=( $( ip a | sed -n '/\<inet\>/ { /127\.0\.0\.1/! s,.*inet \([^/]*\)/.*,\1,p }' ) )
hosts=( $( awk ' /ServerName/ && !/000_defaults/ && !seen[$NF]++ {print $NF} ' /etc/httpd/conf.d/vhost_* ) )

for host in "${hosts[@]}"; do 
    domain=$( dig +short $host | head -n1 )
    status=$( curl -so /dev/null -w '%{http_code}' $host )

    found=false
    for ip in "${ips[@]}"; do
        if [[ $domain == $ip ]]; then
            echo "$domain - $host - Status_code=$code"
            found=true
            break
        fi
    done

    if ! $found; then
        echo "no IP found for $domain - $host - Status_code=$code" >&2
    fi
done 

相关内容