2017-08-16 72 views
1

我正在嘗試編寫一個bash腳本,它將爲文件中的鏈接CNAME記錄提供輸出。我設法只做一個步驟鏈(cname1 CNAME cname2 - > cname2 - >一些A記錄)。Bash腳本在區域文件中顯示CNAME鏈

我想要做的是打印出整個鏈,如果它們之間有多個步驟。

chainA一個10.100.250.22
chainB CNAME chainA
chainC CNAME chainB
chainD CNAME chainC

我想有這樣的輸出: chainD - > chainC - > chainB - > chainA是一條記錄。

到目前爲止,我所有的CNAME記錄提取到一個文件和一個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

感謝您指出,這是我的第一篇文章... – stevansv

+0

哦,哎喲,這就是爲什麼你需要包括你的代碼。所以很好的顯示更新你的Q.幾乎可以肯定這可以作爲1 awk腳本來完成。另外,看起來像閱讀'人tsort'可能會幫助你。如果它不能作爲1 awk腳本完成,至少應將'name = $(awk | sed | awk)'這樣的項目減少到'name = $(awk'{sub(s /[.].*$/, 「」,$ 1); $ 1 = $ 1} 1'<<<「$ line」'!回想一下'awk'可以執行多條語句並且具有'sub'和'gsub'(和'gensub')替代函數。這是深夜,我明天再看看能否幫忙。祝你好運。 – shellter

+0

謝謝!我會盡量用tsort解決問題,也可以用tnx來縮短可變縮短的建議,一旦我到達與循環有關的地方,我就會將其納入。 :)。我實際上將盡量減少此類似: '例1 CNAME示例2 例題CNAME example3' ,然後就在那裏檢查與示例3挖,輸出的建議記錄導致 '例1例2 CNAME應該是:例1 CNAME [A_record_output_from_dig_ +答案]' – stevansv

回答

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 

如果你真的需要->輸出,我相信你能弄清楚如何得到它。 另外,您需要參數化傳入文件名。

理解代碼是如何工作的,執行第一「管滿」,然後添加另一部分,和另一等

閉合| { tsort ... ; awk ..; }被稱爲進程組(由匹配的一對錶示如果你想將輸出重定向到一個文件,使用進程組使得它變得很容易,例如...| {tsort ... ; awk ...;} > outFile(我包括一個; char以顯示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

+0

我還是個新手,不知道awk的一些東西,但是這個東西很實用! tnx! P.S.而tnx對於tsort wiki來說,手冊頁對於這樣的命令絕對是毫無價值的...... – stevansv

+0

再一次,我鼓勵你將這些代碼分開,一次一個語句。看看(並且理解)'awk'NR!= 1 {print $ 1「'$ 3} '。/ testDat.raw'確實如此,然後添加'|'和下一個cmd等來查看發生了什麼。另外,獲得「有效的Awk編程」,這是非常值得的!在等待印刷書到達時,請運行[Grymoire Awk教程](https://grymoire.com/Unix/Awk.html)。很高興這有助於。 – shellter

+0

當然,爲了您的教育,然後考慮如何將您的原始代碼轉換爲一個(可能是2個)'awk'程序。 (我猜在'awk'中寫'tsort'不會很麻煩)。你知道計算在腳本中創建的進程嗎?每個外部cmd和'$(...)'結構都需要shell停止,要求操作系統創建一個新進程,複製環境,附加std-in和std-out(可能還有一些其他的東西) 。如果您按照每行處理多個字段,則非常「昂貴」(如上所述)。無論如何,這可能需要等待另一天。祝你好運! – shellter