天天看點

通過腳本案例學習shell(五) 通過建立DNS腳本一步一步教你将一個普通腳本規範到一個生産環境腳本

為了能夠很好的學習shell腳本的規範書寫,這裡将搭建過程分為四個步驟,其中每個步驟都是上個步驟的延續,直至建立出生産環境下可以使用的腳本,也就是任何一個人在未知此腳本内容的情況下都可以很好的運作此腳本.

<b>步驟1、先通過手動搭建DNS服務,然後将執行的指令複制到腳本檔案中,建立一個簡單腳本。</b>

<b></b>

<b>1、安裝bind、bind-chroot包</b>

yum install bind bind-chroot -y 

<b>2、修改/etc/named.conf檔案</b>

sed -i  ‘s/127\.0\.0\.1/any/’ /etc/named.conf  //替換127.0.0.1為any 

sed -i  's/::1/any/' /etc/named.conf  //替換::1為any 

sed -i  's/localhost/any/' /etc/named.conf //替換localhost為any 

#sed -i -e '/listen-on/d' -e '/allow-query/d' -e '/dnssec/d' /etc/named.conf  //将以上sed的三行删掉,dns預設為any,也可以實作。 

sed -i  's/^dnssec/\/\/&amp;/' /etc/named.conf  //将以dnssec開頭的所有行前面加\\,其中&amp;是引用前面的替換值,\/是轉義 

注意:使用sed指令的時候,先不要-i參數,可以通過-n和p函數先在螢幕上顯示是否正常,例:sed -n ‘s/127\.0\.0\.1/any/p’ /etc/named.conf 

<b>3</b><b>、在</b><b>/etc/named.rfc1912.zone</b><b>中建立區域</b>

cat &gt;&gt; /etc/named.rfc1912.zones &lt;&lt; ENDF \\使用cat追加多行資訊到檔案中 

zone "rsyslog1.com" IN { 

        type master; 

        file "rsyslog1.com.zone"; 

        allow-update { none; }; 

}; 

ENDF 

<b>4</b><b>、在</b><b>/var/named/</b><b>建立</b><b>zone</b><b>檔案</b><b>,</b><b>并設定相應權限</b><b>(cp -p </b><b>可以繼承原有權限</b><b>)</b>

cp -p /var/named/named.localhost /var/named/rsyslog1.com.zone 

sed -i '/127.0.0.1\|AAAA/d' /var/named/rsyslog1.com.zone  //删除不需要的包含127.0.0.1或AAAA的行,其中\|是或的意思 

cat &gt;&gt; /var/named/rsyslog1.com.zone &lt;&lt; ENDF  //追加A記錄 

        A       192.168.100.109 

www     A       192.168.100.109 

<b>5</b><b>、設定DNS,重新開機</b><b>named</b><b>服務并通過</b><b>nslookup</b><b>進行本地解析</b>

sed -i '1inameserver 192.168.100.109' /etc/resolv.conf //在resolv.conf首行添加nameserver語句,其中1i i是變量目前行上插入一行的意思,1i是在第一行前加入一行

/etc/rc.d/init.d/named restart 

nslookup www.rsyslog1.com 

<b>将以上指令統一放到檔案當中就形成了一個簡單腳本如下</b><b>(</b><b>解釋如上</b><b>)</b>

#!/bin/bash 

sed -i 's/127\.0\.0\.1/any/' /etc/named.conf 

sed -i 's/::1/any/' /etc/named.conf 

sed -i 's/localhost/any/' /etc/named.conf 

sed -i 's/dnssec/\/\/&amp;/g' /etc/named.conf 

#sed -i -e '/listen-on/d' -e '/allow-query/d' -e '/dnssec/d' /etc/named.conf 

cat &gt;&gt; /etc/named.rfc1912.zones &lt;&lt; ENDF 

sed -i '/127.0.0.1\|AAAA/d' /var/named/rsyslog1.com.zone 

cat &gt;&gt; /var/named/rsyslog1.com.zone &lt;&lt; ENDF 

sed -i '1inameserver 192.168.100.109' /etc/resolv.conf 

<b>腳本運作結果如下</b><b>:</b>

[root@RHEL6U3-9 named.sh]# ./named1.sh  

......//省略 

Server:     192.168.100.109 

Address:    192.168.100.109#53 

Name:   www.rsyslog1.com    

Address: 192.168.100.109 

以上正确解析,說明腳本運作OK

<b>步驟2、将一些常用到的路徑以及會變的内容通過變量引用</b>

腳本使用過程中很多部分内容都會在不同的環境下有所變動,為了修改友善,引入變量,每次隻需要修改變量的值,腳本中所有引用變量的地方都會自動取定義的變量。(<b>可在vim下使用 :.,$%A%B%g 将光标以下内容中的A全部替換成B)</b>

<b>修改部分:</b>

<b>1、</b><b>定義安裝包變量、配置檔案路徑變量、域名變量、IP位址變量</b>

腳本修改後如下:

PKG="bind bind-chroot"  //定義安裝的包,不同版本包可能不一樣 

M_CONF="/etc/named.conf" //定義主配置檔案named.conf路徑 

R_CONF="/etc/named.rfc1912.zones" //定義named.rfc1912.zones檔案路徑 

DOMAIN_N="rsyslog2.com" //定義域名 

MYIP="$(ifconfig eth0 | grep "inet addr:" | awk -F[:" "]+ '{print $4}')"  //取eth0的IP位址 –F[:” ”]+表示以:或者空格分隔,’{print $4}’表示列印第四列 

#MYIP="$(ifconfig eth0 | sed –n   's/.*addr:\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p')" //也是取eth0的IP位址,解析如下: 

sed –n ‘s///p’  sed标準寫法 

\(\) 儲存被比對的字元          \1 引用第一個儲存比對的字元 

.* 表示所有 

[0-9]\{1,3\} 表示至少1個最多3個數字組合 

\. 表示轉義 

#MYIP="$(ifconfig eth0 | grep "inet addr:" | cut -d":" -f2 | cut -d " " -f1)"  //取eth0的IP位址,-d: 以:分隔,-d” “ 以空格分隔,-f1 列印:分隔的第一部分 

#MYIP="$(ifconfig eth0 | grep "inet addr" |sed -e 's/.*addr://' -e 's/Bcast.*//') //将IP位址兩邊的多餘部分替換成空即可。

#MYIP="$("ifconfig eth0 | grep "inet addr" |awk -F: '{print $2}' |awk '{print $1}') //先以:分割過濾,然後以空格分割過濾

yum install $PKG -y 

sed -i 's/127\.0\.0\.1/any/' $M_CONF   

sed -i 's/::1/any/' $M_CONF 

sed -i 's/localhost/any/' $M_CONF 

sed -i 's/dnssec/\/\/&amp;/' $M_CONF 

cat &gt;&gt; $R_CONF &lt;&lt; ENDF 

zone "$DOMAIN_N" IN { 

        file "$DOMAIN_N.zone"; 

cp -p /var/named/named.localhost /var/named/$DOMAIN_N.zone 

sed -i '/127.0.0.1\|AAAA/d' /var/named/$DOMAIN_N.zone 

cat &gt;&gt; /var/named/$DOMAIN_N.zone &lt;&lt; ENDF 

        A       $MYIP 

www     A       $MYIP 

sed -i "1inameserver $MYIP" /etc/resolv.conf 

service named restart 

nslookup www.$DOMAIN_N 

<b>腳本運作結果</b><b>:</b>

[root@RHEL6U3-9 named.sh]# ./named2.sh 

...... 

Name:   www.rsyslog2.com 

腳本運作正常 

<b>步驟</b><b>3</b><b>、将各個部分子產品化</b><b>(</b><b>函數化</b><b>)</b>

1、  各子產品函數化,後面調用函數即可

2、  安裝包函數定義for循環判斷是否安裝過

3、  建立的域名通過在腳本後面跟上域名進行傳遞到腳本裡面$1裡

4、  多行sed指令寫入檔案中,然後通過-f參數進行引用

5、  函數部分如果比較大可以單獨寫一個檔案,然後在腳本中通過source或者.進行調用。例:source /etc/install.sh或 . /etc/install.sh  (以下腳本未舉例可自行測試)

<b>腳本修改後如下</b>

PKG="bind bind-chroot" 

M_CONF="/etc/named.conf" 

R_CONF="/etc/named.rfc1912.zones" 

DOMAIN_N="$1" 

MYIP="$(ifconfig eth0 | grep "inet addr:" | awk -F[:" "]+ '{print $4}')" 

INSTALL_PKG() //安裝包定義一個函數 

#       yum install $PKG -y 

        for i in $PKG 

        do 

                rpm -q $i &amp;&gt; /dev/null 

                [ $? -ne 0 ] &amp;&amp; UNPKG="$UNPKG $i" //将所有檢測出來未安裝的包儲存到變量UPPKG中,也可以儲存到檔案中,不過變量是臨時存儲在記憶體中的,速度要比檔案快的多,其次可以減少磁盤I/O性能。 

        done 

        [ -n "$UNPKG" ] &amp;&amp; yum install $UNPKG –y //判斷變量UNPKG是否為空,如果不為空就安裝裡面包含的包 

MAIN_CONF() 

sed -i -f /root/shell/sed.txt $M_CONF  //将之前那四行sed内容寫到一個檔案中,然後通過-f參數進行調用即可,其實四行指令也可以通過-e指令連接配接,不建議這麼操作。 

        cat &gt;&gt; $R_CONF &lt;&lt; ENDF 

        cp -p /var/named/named.localhost /var/named/$DOMAIN_N.zone 

        sed -i '/127.0.0.1\|AAAA/d' /var/named/$DOMAIN_N.zone 

        cat &gt;&gt; /var/named/$DOMAIN_N.zone &lt;&lt; ENDF 

MYTEST() 

        sed -i "1inameserver $MYIP" /etc/resolv.conf 

        service named restart 

        nslookup www.$DOMAIN_N 

INSTALL_PKG 

MAIN_CONF 

MYTEST 

[root@RHEL6U3-9 shell]# cat /root/shell/sed.txt  //引用的四條sed寫入的檔案格式如下。注意沒有’’符号。 

s/127\.0\.0\.1/any 

s/::1/any/ 

s/localhost/any/ 

s/dnssec/\/\/&amp;/ 

[root@RHEL6U3-9 named.sh]# ./named3.sh rsyslog3.org 

Stopping named: .                                          [  OK  ] 

Starting named:                                            [  OK  ] 

Name:   www.rsyslog3.org 

<b>步驟</b><b>4</b><b>、完善腳本中存在的各種情況</b><b>,初步</b><b>達到生産環境基本要求</b>

1、定義錯誤函數,友善他人傳遞參數錯誤報錯。

2、傳遞參數加上-d 增強書寫規範

4、定義測試函數,測試傳遞參數是否有效

5、定義case語句,内含測試函數,将傳遞參數一一驗證,如果正确報錯所有域名參數為後面所用,如果不正确,調用錯誤函數輸出結束。

MYHELP() //定義輸出錯誤友善他人尤其是開發人員正确運作腳本,這也能展現出來一個大牛寫腳本是否規範地方,同時也能展現出來團隊協作精神,友善他人使用。 

cat &lt;&lt; ENDF 

usage: $0 [option] // $0 表示第一個參數 也就是腳本名稱 

option: 

-d dn1 dn2 ...  :input your domain names 

exit 1 

TEST_D() //定義測試函數,測試輸入域名格式是否有效,以下隻列出了兩種域名格式有效,分别為***.***或者***.***.*** 

        echo $1 | grep '.\..\|.*\..*\..*' &amp;&gt;/dev/null  // \|或的意思 

        [ $? -ne 0 ] &amp;&amp; MYHELP \\如果執行沒有結果或者報錯,則顯示錯誤幫助 

INSTALL_PKG() 

                [ $? -ne 0 ] &amp;&amp; UNPKG="$UNPKG $i" 

        [ -n "$UNPKG" ] &amp;&amp; yum install $UNPKG -y 

        sed -i -f /root/shell/sed.txt $M_CONF 

        zone "$DOMAIN_N" IN { 

                type master; 

                file "$DOMAIN_N.zone"; 

                allow-update { none; }; 

        }; 

MYTEST() //由于是可以傳遞多個域名參數,使用for循環将多個域名進行解析 

        for i in $DOMAIN_N_ALL 

                nslookup $i 

[ -z "$1" ] &amp;&amp; MYHELP  //如果腳本不跟任何傳遞參數,則退出顯示幫助資訊 

case $1 in  //定義case語句,判斷腳本後所有域名是否有效,如果有效全部寫入變量DOMAIN_N_ALL中,後面再通過for循環讀取變量擷取的值,如果無效則退出顯示幫助錯誤, 

        -d)  //加入 –d 參數後,域名部分從$2開始 

                shift  向左移動一位,将$2的值傳遞給$1,後面依次類推 

                TEST_D $1 //判斷第一個域名是否有效 

                DOMAIN_N_ALL="$1" 将域名儲存到變量DOMAIN_N_ALL變量中 

                shift 繼續左移動,将第二個域名傳遞給$1 

                while [ $# -gt 0 ] //判斷位置參數個數是否為0,也就是是否還有域名存在 

                do 

                        TEST_D $1 //如果有繼續判斷是否有效 

                        DOMAIN_N_ALL="$DOMAIN_N_ALL $1" //如果有效,将域名追加到DOMAIN_N_ALL變量中,注意中間是有空格的 

                        shift \\傳遞之後,位置參數繼續左移 

                done 

        ;; 

        *) 

                MYHELP 

esac 

for DOMAIN_N in $DOMAIN_N_ALL  //使用for循環添加傳遞的所有域名 

do 

        MAIN_CONF 

done 

<b>腳本執行結果如下</b><b>:</b>

[root@RHEL6U3-9 named.sh]# ./named4.sh  //不傳遞任何參數報錯 

usage: ./named4.sh [option] 

[root@RHEL6U3-9 named.sh]# ./named4.sh –d  //傳遞參數有問題報錯 

[root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1 //傳遞的參數不符合域名格式報錯 

[root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1.net rsyslog2  //傳遞的第二個域名不符合格式報錯 

[root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1.net rsyslog2.net  //正确傳遞兩個域名,後面還可以跟域名 

Name:   rsyslog1.net 

Name:   rsyslog2.net 

<b>步驟</b><b>5</b><b>、繼續完善腳本中存在的各種情況</b><b>,最終</b><b>達到生産環境要求</b><b></b>

1、   加複雜檔案鎖,防止腳本被重複執行或者系統當機再次被執行

2、   ……………..

待續.......................

本文轉自淩激冰51CTO部落格,原文連結:http://blog.51cto.com/dreamfire/1156189,如需轉載請自行聯系原作者