Bash脚本在区域文件中显示CNAME链

时间:2017-08-16 21:20:12

标签: bash dns

我正在尝试编写一个bash脚本,该脚本将为我提供区域文件中链接CNAME记录的文件输出。我设法只创建了一个步骤链(cname1 CNAME cname2 - > cname2 - >某些A记录)。

如果中间有多个步骤,我要做的就是打印整个链。

  链A A 10.100.250.22
  chainB CNAME chainA
  chainC CNAME chainB
  chainD CNAME chainC

我希望输出如下: chainD - > chainC - > chainB - > chainA是A记录。

到目前为止,我将所有的cnames提取到一个文件中,并将while循环遍历它们,但它只找到一步:

#!/bin/bash
    read -e -p "Enter filename (use tab for completion): " file
    ls -l "$file"
    date=$(date +%m_%d_%y)
    echo $date
    if [ -f chained_cnames_$date ] ; then
        rm chained_cnames_$date
    fi
    grep -w "CNAME" $file | grep "^[^#;]" > cnames_out
    while IFS='' read -r line || [[ -n "$line" ]]
    do
      echo "Scanning record: $line"
      name=$(echo $line | awk '{print $1}' | sed 's/[.].*$//' | awk '{$1=$1};1')
      dst=$(echo $line | awk '{print $3}' | sed 's/[.].*$//' | awk '{$1=$1};1')
      dst_long=$(echo $line | awk '{print $3}')
      dst_long_a=$(dig +noall +answer $dst_long | awk '{print $1}')
      if [ "$name" = "$dst" ]
      then
        ipaddr="$(dig $dst_long +short)"
        if [ -z "$ipaddr" ]
        then
          echo $line "   --->   "  "NO A RECORD"  >> chained_cnames_$date
        else
          echo $line "   --->   "  $ipaddr "  A record exists, but is not in this zone file.\n It should be like:\n $name   CNAME   $dst_long_a" >> chained_cnames_$date
        fi
      else
        while IFS='' read -r line1 || [[ -n "$line1" ]]
        do
          testrec=$(echo $line1 | awk '{print $1}' | awk '{$1=$1};1')
          if [ "$dst" = "$testrec" ]
          then
            echo >> chained_cnames_$date
            echo $line " ---> " $line1 >> chained_cnames_$date
            echo >> chained_cnames_$date
         fi
        done < "cnames_out"
      fi
    done < "cnames_out"
    echo
    echo
    echo "Done! Invalid records are stored in the chained_cnames_$date file."
    rm cnames_out

如何创建这样的循环?

1 个答案:

答案 0 :(得分:1)

这很有趣,

% cat cNamePath.sh

#!/bin/bash
# chainA A 10.100.250.22
# chainB CNAME chainA
# chainC CNAME chainB
# chainD CNAME chainC

awk '
  NR!=1{print $1 " " $3}
' ./testDat.raw | {
  tsort | tr '\n' ' '
  # process inFile a 2nd time, just to grab the first record
  # this could be simplified to just a `print` statment, do you see how? ;-)
  awk 'NR==1{base=$1;skip=$2;ip=$3;print base " is A record"}' ./testDat.raw
}
% chmod +x cNamePath.sh

<强>输出

chainD chainC chainB chainA chainA is A record

如果你确实需要->的输出,我相信你可以弄清楚如何获得它。 此外,您还需要参数化文件名中的传递。

要了解代码是如何工作的,请执行第一个“pipe-full”,然后添加另一个部分,另一个部分等。

结束| { tsort ... ; awk ..; }被称为一个进程组(由匹配的对{ ..}表示。你使用它来使所有输出“折叠在一起”并传递给相同的“目标”。如果你想要的话要将输出重定向到文件,使用进程组使其变得非常简单,即...| {tsort ... ; awk ...;} > outFile(我包含一个;字符,以显示cmd是独立的,并且不会在管道中发送到跟随cmd。它不包含在代码中,因为tsort行和nawk行功能之间的换行方式与;相同,只需一行。(TMI) ?)

如果您不了解tsort,请查看此linux tsort on Wikipedia文章。

tsort的美妙之处在于它会为你找出关系的顺序,你不需要你提供的“排序”文件。它可以轻松地订购数据,如

chainA A 10.100.250.22
chainD CNAME chainC
chainC CNAME chainB
chainB CNAME chainA

IHTH