通过脚本案例学习shell(五) 通过创建DNS脚本一步一步教你将一个普通脚本规范到一个生产环境脚本

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

为了能够很好的学习shell脚本的规范书写,这里将搭建过程分为四个步骤,其中每个步骤都是上个步骤的延续,直至创建出生产环境下可以使用的脚本,也就是任何一个人在未知此脚本内容的情况下都可以很好的运行此脚本.

步骤1、先通过手动搭建DNS服务,然后将执行的命令复制到脚本文件中,创建一个简单脚本。

1、安装bind、bind-chroot包

 
  1. yum install bind bind-chroot -y 

2、修改/etc/named.conf文件

 
  1. sed -i  ‘s/127\.0\.0\.1/any/’ /etc/named.conf  //替换127.0.0.1为any 
  2. sed -i  's/::1/any/' /etc/named.conf  //替换::1为any 
  3. sed -i  's/localhost/any/' /etc/named.conf //替换localhost为any 
  4. #sed -i -e '/listen-on/d' -e '/allow-query/d' -e '/dnssec/d' /etc/named.conf  //将以上sed的三行删掉,dns默认为any,也可以实现。 
  5. sed -i  's/^dnssec/\/\/&/' /etc/named.conf  //将以dnssec开头的所有行前面加\\,其中&是引用前面的替换值,\/是转义 
  6. 注意:使用sed命令的时候,先不要-i参数,可以通过-n和p函数先在屏幕上显示是否正常,例:sed -n ‘s/127\.0\.0\.1/any/p’ /etc/named.conf 

3、在/etc/named.rfc1912.zone中创建区域

 
  1. cat >> /etc/named.rfc1912.zones << ENDF \\使用cat追加多行信息到文件中 
  2. zone "rsyslog1.com" IN { 
  3.         type master; 
  4.         file "rsyslog1.com.zone"; 
  5.         allow-update { none; }; 
  6. }; 
  7. ENDF 

4、在/var/named/创建zone文件并设置相应权限cp -p 可以继承原有权限

 
  1. cp -p /var/named/named.localhost /var/named/rsyslog1.com.zone 
  2. sed -i '/127.0.0.1\|AAAA/d' /var/named/rsyslog1.com.zone  //删除不需要的包含127.0.0.1或AAAA的行,其中\|是或的意思 
  3.  
  4. cat >> /var/named/rsyslog1.com.zone << ENDF  //追加A记录 
  5.         A       192.168.100.109 
  6. www     A       192.168.100.109 
  7. ENDF 

5、设置DNS,重启named服务并通过nslookup进行本地解析

 
  1. sed -i '1inameserver 192.168.100.109' /etc/resolv.conf //在resolv.conf首行添加nameserver语句,其中1i i是变量当前行上插入一行的意思,1i是在第一行前加入一行
  2. /etc/rc.d/init.d/named restart 
  3. nslookup www.rsyslog1.com 

将以上命令统一放到文件当中就形成了一个简单脚本如下解释如上

 
  1. #!/bin/bash 
  2.  
  3. yum install bind bind-chroot -y 
  4.  
  5. sed -i 's/127\.0\.0\.1/any/' /etc/named.conf 
  6. sed -i 's/::1/any/' /etc/named.conf 
  7. sed -i 's/localhost/any/' /etc/named.conf 
  8. sed -i 's/dnssec/\/\/&/g' /etc/named.conf 
  9. #sed -i -e '/listen-on/d' -e '/allow-query/d' -e '/dnssec/d' /etc/named.conf 
  10.  
  11. cat >> /etc/named.rfc1912.zones << ENDF 
  12. zone "rsyslog1.com" IN { 
  13.         type master; 
  14.         file "rsyslog1.com.zone"; 
  15.         allow-update { none; }; 
  16. }; 
  17. ENDF 
  18.  
  19. cp -p /var/named/named.localhost /var/named/rsyslog1.com.zone 
  20.  
  21. sed -i '/127.0.0.1\|AAAA/d' /var/named/rsyslog1.com.zone 
  22.  
  23. cat >> /var/named/rsyslog1.com.zone << ENDF 
  24.         A       192.168.100.109 
  25. www     A       192.168.100.109 
  26. ENDF 
  27.  
  28. sed -i '1inameserver 192.168.100.109' /etc/resolv.conf 
  29. /etc/rc.d/init.d/named restart 
  30. nslookup www.rsyslog1.com 

脚本运行结果如下

 
  1. [root@RHEL6U3-9 named.sh]# ./named1.sh  
  2. ......//省略 
  3. Server:     192.168.100.109 
  4. Address:    192.168.100.109#53 
  5.  
  6. Name:   www.rsyslog1.com    
  7. Address: 192.168.100.109 

以上正确解析,说明脚本运行OK

 

步骤2、将一些常用到的路径以及会变的内容通过变量引用

脚本使用过程中很多部分内容都会在不同的环境下有所变动,为了修改方便,引入变量,每次只需要修改变量的值,脚本中所有引用变量的地方都会自动取定义的变量。(可在vim下使用 :.,$%A%B%g 将光标以下内容中的A全部替换成B)

修改部分:

1、定义安装包变量、配置文件路径变量、域名变量、IP地址变量

脚本修改后如下:

 
  1. #!/bin/bash 
  2. PKG="bind bind-chroot"  //定义安装的包,不同版本包可能不一样 
  3. M_CONF="/etc/named.conf" //定义主配置文件named.conf路径 
  4. R_CONF="/etc/named.rfc1912.zones" //定义named.rfc1912.zones文件路径 
  5. DOMAIN_N="rsyslog2.com" //定义域名 
  6.  
  7. MYIP="$(ifconfig eth0 | grep "inet addr:" | awk -F[:" "]+ '{print $4}')"  //取eth0的IP地址 –F[:” ”]+表示以:或者空格分隔,’{print $4}’表示打印第四列 
  8. #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地址,解析如下: 
  9. sed –n ‘s///p’  sed标准写法 
  10. \(\) 保存被匹配的字符          \1 引用第一个保存匹配的字符 
  11. .* 表示所有 
  12. [0-9]\{1,3\} 表示至少1个最多3个数字组合 
  13. \. 表示转义 
  14. #MYIP="$(ifconfig eth0 | grep "inet addr:" | cut -d":" -f2 | cut -d " " -f1)"  //取eth0的IP地址,-d: 以:分隔,-d” “ 以空格分隔,-f1 打印:分隔的第一部分 
  15. #MYIP="$(ifconfig eth0 | grep "inet addr" |sed -e 's/.*addr://' -e 's/Bcast.*//') //将IP地址两边的多余部分替换成空即可。
  16. #MYIP="$("ifconfig eth0 | grep "inet addr" |awk -F: '{print $2}' |awk '{print $1}') //先以:分割过滤,然后以空格分割过滤
  17. yum install $PKG -y 
  18.  
  19. sed -i 's/127\.0\.0\.1/any/' $M_CONF   
  20. sed -i 's/::1/any/' $M_CONF 
  21. sed -i 's/localhost/any/' $M_CONF 
  22. sed -i 's/dnssec/\/\/&/' $M_CONF 
  23.  
  24. cat >> $R_CONF << ENDF 
  25. zone "$DOMAIN_N" IN { 
  26.         type master; 
  27.         file "$DOMAIN_N.zone"; 
  28.         allow-update { none; }; 
  29. }; 
  30. ENDF 
  31.  
  32. cp -p /var/named/named.localhost /var/named/$DOMAIN_N.zone 
  33.  
  34. sed -i '/127.0.0.1\|AAAA/d' /var/named/$DOMAIN_N.zone 
  35.  
  36. cat >> /var/named/$DOMAIN_N.zone << ENDF 
  37.         A       $MYIP 
  38. www     A       $MYIP 
  39. ENDF 
  40.  
  41. sed -i "1inameserver $MYIP" /etc/resolv.conf 
  42. service named restart 
  43. nslookup www.$DOMAIN_N 

脚本运行结果

 
  1. [root@RHEL6U3-9 named.sh]# ./named2.sh 
  2. ...... 
  3. Server:     192.168.100.109 
  4. Address:    192.168.100.109#53 
  5.  
  6. Name:   www.rsyslog2.com 
  7. Address: 192.168.100.109 
  8. 脚本运行正常 

步骤3、将各个部分模块化函数化

修改部分:

1、  各模块函数化,后面调用函数即可

2、  安装包函数定义for循环判断是否安装过

3、  创建的域名通过在脚本后面跟上域名进行传递到脚本里面$1里

4、  多行sed命令写入文件中,然后通过-f参数进行引用

5、  函数部分如果比较大可以单独写一个文件,然后在脚本中通过source或者.进行调用。例:source /etc/install.sh或 . /etc/install.sh  (以下脚本未举例可自行测试)

脚本修改后如下

 
  1. #!/bin/bash 
  2.  
  3. PKG="bind bind-chroot" 
  4. M_CONF="/etc/named.conf" 
  5. R_CONF="/etc/named.rfc1912.zones" 
  6. DOMAIN_N="$1" 
  7. MYIP="$(ifconfig eth0 | grep "inet addr:" | awk -F[:" "]+ '{print $4}')" 
  8.  
  9. INSTALL_PKG() //安装包定义一个函数 
  10. #       yum install $PKG -y 
  11.         for i in $PKG 
  12.         do 
  13.                 rpm -q $i &> /dev/null 
  14.                 [ $? -ne 0 ] && UNPKG="$UNPKG $i" //将所有检测出来未安装的包保存到变量UPPKG中,也可以保存到文件中,不过变量是临时存储在内存中的,速度要比文件快的多,其次可以减少磁盘I/O性能。 
  15.         done 
  16.         [ -n "$UNPKG" ] && yum install $UNPKG –y //判断变量UNPKG是否为空,如果不为空就安装里面包含的包 
  17.  
  18. MAIN_CONF() 
  19. sed -i -f /root/shell/sed.txt $M_CONF  //将之前那四行sed内容写到一个文件中,然后通过-f参数进行调用即可,其实四行命令也可以通过-e命令连接,不建议这么操作。 
  20.  
  21.         cat >> $R_CONF << ENDF 
  22. zone "$DOMAIN_N" IN { 
  23.         type master; 
  24.         file "$DOMAIN_N.zone"; 
  25.         allow-update { none; }; 
  26. }; 
  27. ENDF 
  28.  
  29.         cp -p /var/named/named.localhost /var/named/$DOMAIN_N.zone 
  30.  
  31.         sed -i '/127.0.0.1\|AAAA/d' /var/named/$DOMAIN_N.zone 
  32.  
  33.         cat >> /var/named/$DOMAIN_N.zone << ENDF 
  34.         A       $MYIP 
  35. www     A       $MYIP 
  36. ENDF 
  37.  
  38. MYTEST() 
  39.         sed -i "1inameserver $MYIP" /etc/resolv.conf 
  40.         service named restart 
  41.         nslookup www.$DOMAIN_N 
  42.  
  43. INSTALL_PKG 
  44. MAIN_CONF 
  45. MYTEST 
  46.  
  47. [root@RHEL6U3-9 shell]# cat /root/shell/sed.txt  //引用的四条sed写入的文件格式如下。注意没有’’符号。 
  48. s/127\.0\.0\.1/any 
  49. s/::1/any/ 
  50. s/localhost/any/ 
  51. s/dnssec/\/\/&/ 

脚本运行结果如下

 
  1. [root@RHEL6U3-9 named.sh]# ./named3.sh rsyslog3.org 
  2. Stopping named: .                                          [  OK  ] 
  3. Starting named:                                            [  OK  ] 
  4. Server:     192.168.100.109 
  5. Address:    192.168.100.109#53 
  6.  
  7. Name:   www.rsyslog3.org 
  8. Address: 192.168.100.109 

步骤4、完善脚本中存在的各种情况,初步达到生产环境基本要求

修改部分:

1、定义错误函数,方便他人传递参数错误报错。

2、传递参数加上-d 增强书写规范

4、定义测试函数,测试传递参数是否有效

5、定义case语句,内含测试函数,将传递参数一一验证,如果正确报错所有域名参数为后面所用,如果不正确,调用错误函数输出结束。

脚本修改后如下

 
  1. #!/bin/bash 
  2.  
  3. PKG="bind bind-chroot" 
  4. M_CONF="/etc/named.conf" 
  5. R_CONF="/etc/named.rfc1912.zones" 
  6. MYIP="$(ifconfig eth0 | grep "inet addr:" | awk -F[:" "]+ '{print $4}')" 
  7.  
  8. MYHELP() //定义输出错误方便他人尤其是开发人员正确运行脚本,这也能体现出来一个大牛写脚本是否规范地方,同时也能体现出来团队协作精神,方便他人使用。 
  9. cat << ENDF 
  10. usage: $0 [option] // $0 表示第一个参数 也就是脚本名称 
  11. option: 
  12. -d dn1 dn2 ...  :input your domain names 
  13. ENDF 
  14. exit 1 
  15.  
  16. TEST_D() //定义测试函数,测试输入域名格式是否有效,以下只列出了两种域名格式有效,分别为***.***或者***.***.*** 
  17.         echo $1 | grep '.\..\|.*\..*\..*' &>/dev/null  // \|或的意思 
  18.         [ $? -ne 0 ] && MYHELP \\如果执行没有结果或者报错,则显示错误帮助 
  19.  
  20. INSTALL_PKG() 
  21. #       yum install $PKG -y 
  22.         for i in $PKG 
  23.         do 
  24.                 rpm -q $i &> /dev/null 
  25.                 [ $? -ne 0 ] && UNPKG="$UNPKG $i" 
  26.         done 
  27.         [ -n "$UNPKG" ] && yum install $UNPKG -y 
  28.  
  29. MAIN_CONF() 
  30.         sed -i -f /root/shell/sed.txt $M_CONF 
  31.         cat >> $R_CONF << ENDF 
  32.         zone "$DOMAIN_N" IN { 
  33.                 type master; 
  34.                 file "$DOMAIN_N.zone"; 
  35.                 allow-update { none; }; 
  36.         }; 
  37. ENDF 
  38.  
  39.         cp -p /var/named/named.localhost /var/named/$DOMAIN_N.zone 
  40.  
  41.         sed -i '/127.0.0.1\|AAAA/d' /var/named/$DOMAIN_N.zone 
  42.  
  43.         cat >> /var/named/$DOMAIN_N.zone << ENDF 
  44.         A       $MYIP 
  45. www     A       $MYIP 
  46. ENDF 
  47.  
  48. MYTEST() //由于是可以传递多个域名参数,使用for循环将多个域名进行解析 
  49.         sed -i "1inameserver $MYIP" /etc/resolv.conf 
  50.         service named restart 
  51.         for i in $DOMAIN_N_ALL 
  52.         do 
  53.                 nslookup $i 
  54.         done 
  55.  
  56. [ -z "$1" ] && MYHELP  //如果脚本不跟任何传递参数,则退出显示帮助信息 
  57.  
  58. case $1 in  //定义case语句,判断脚本后所有域名是否有效,如果有效全部写入变量DOMAIN_N_ALL中,后面再通过for循环读取变量获取的值,如果无效则退出显示帮助错误, 
  59.         -d)  //加入 –d 参数后,域名部分从$2开始 
  60.                 shift  向左移动一位,将$2的值传递给$1,后面依次类推 
  61.                 TEST_D $1 //判断第一个域名是否有效 
  62.                 DOMAIN_N_ALL="$1" 将域名保存到变量DOMAIN_N_ALL变量中 
  63.                 shift 继续左移动,将第二个域名传递给$1 
  64.                 while [ $# -gt 0 ] //判断位置参数个数是否为0,也就是是否还有域名存在 
  65.                 do 
  66.                         TEST_D $1 //如果有继续判断是否有效 
  67.                         DOMAIN_N_ALL="$DOMAIN_N_ALL $1" //如果有效,将域名追加到DOMAIN_N_ALL变量中,注意中间是有空格的 
  68.                         shift \\传递之后,位置参数继续左移 
  69.                 done 
  70.         ;; 
  71.         *) 
  72.                 MYHELP 
  73.         ;; 
  74. esac 
  75.  
  76.  
  77.  
  78.  
  79. INSTALL_PKG 
  80. for DOMAIN_N in $DOMAIN_N_ALL  //使用for循环添加传递的所有域名 
  81. do 
  82.         MAIN_CONF 
  83. done 
  84. MYTEST 

脚本执行结果如下

 
  1. [root@RHEL6U3-9 named.sh]# ./named4.sh  //不传递任何参数报错 
  2. usage: ./named4.sh [option] 
  3. option: 
  4. -d dn1 dn2 ...  :input your domain names 
  5. [root@RHEL6U3-9 named.sh]# ./named4.sh –d  //传递参数有问题报错 
  6. usage: ./named4.sh [option] 
  7. option: 
  8. -d dn1 dn2 ...  :input your domain names 
  9. [root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1 //传递的参数不符合域名格式报错 
  10. usage: ./named4.sh [option] 
  11. option: 
  12. -d dn1 dn2 ...  :input your domain names 
  13. [root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1.net rsyslog2  //传递的第二个域名不符合格式报错 
  14. usage: ./named4.sh [option] 
  15. option: 
  16. -d dn1 dn2 ...  :input your domain names 
  17. [root@RHEL6U3-9 named.sh]# ./named4.sh -d rsyslog1.net rsyslog2.net  //正确传递两个域名,后面还可以跟域名 
  18. Stopping named: .                                          [  OK  ] 
  19. Starting named:                                            [  OK  ] 
  20. Server:     192.168.100.109 
  21. Address:    192.168.100.109#53 
  22.  
  23. Name:   rsyslog1.net 
  24. Address: 192.168.100.109 
  25.  
  26. Server:     192.168.100.109 
  27. Address:    192.168.100.109#53 
  28.  
  29. Name:   rsyslog2.net 
  30. Address: 192.168.100.109 

 

步骤5、继续完善脚本中存在的各种情况,最终达到生产环境要求

1、   加复杂文件锁,防止脚本被重复执行或者系统宕机再次被执行

2、   ……………..

待续.......................

 


本文转自凌激冰51CTO博客,原文链接:http://blog.51cto.com/dreamfire/1156189,如需转载请自行联系原作者

相关文章
|
1月前
|
监控 Unix Shell
shell脚本编程学习
【10月更文挑战第1天】shell脚本编程
58 12
|
2月前
|
人工智能 监控 Shell
常用的 55 个 Linux Shell 脚本(包括基础案例、文件操作、实用工具、图形化、sed、gawk)
这篇文章提供了55个常用的Linux Shell脚本实例,涵盖基础案例、文件操作、实用工具、图形化界面及sed、gawk的使用。
162 2
|
23天前
|
物联网 5G UED
|
2月前
|
网络协议 关系型数据库 MySQL
Shell 脚本案例
Shell 脚本案例
43 8
|
2月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
150 3
|
3月前
|
XML Web App开发 数据挖掘
Postman接口测试工具全解析:功能、脚本编写及优缺点探讨
文章详细分析了Postman接口测试工具的功能、脚本编写、使用场景以及优缺点,强调了其在接口自动化测试中的强大能力,同时指出了其在性能分析方面的不足,并建议根据项目需求和个人偏好选择合适的接口测试工具。
99 1
|
3月前
|
Java Shell Linux
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
关于如何使用Shell脚本来解析Linux系统中的应用服务日志,提供了脚本实现的详细步骤和技巧,以及一些Shell编程的技能扩展。
48 0
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
|
3月前
|
存储 数据采集 JSON
数据存储的正确规范:csv/xlsx和JSON全方位解析
数据存储的正确规范:csv/xlsx和JSON全方位解析
53 1
|
4月前
|
Shell Linux
Shell 脚本编程学习
Shell 脚本编程学习
36 0

相关产品

  • 云解析DNS
  • 推荐镜像

    更多