20.16/20.17 shell中的函数
函数,是一个子shell,代码段,定义完函数后可以引用它。
函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这个小单元的名字即可。
function f_name(){ command }
函数必须要放在最前面
示例1
1 编写脚本
#!/bin/bash function inp() { echo $1 $2 $3 $0 $# } inp 1 a 2
解释:
#!/bin/bash
function inp() {inp 是参数的名字
echo $1 $2 $3 $0 $# $1第一个参数,$2第二个参数,$3第三个参数,$0文件的名字,$#统计参数
}
inp 1 a 2 输入函数名称inp直接调用函数,输出结果是 $1=a $2=a $3=2
2 执行输出
[root@AliKvn shell]# sh fun1.sh 1 a 2 fun1.sh 3 [root@AliKvn shell]# sh -x fun1.sh + inp 1 a 2 + echo 1 a 2 fun1.sh 3 1 a 2 fun1.sh 3
编写第二种脚本
[root@AliKvn shell]# vim fun1.sh #!/bin/bash function inp() { echo "the first par is $1" echo "the second par is $2" echo "the triple par is $3" echo "the script is $0" echo "total par is $#" } inp 1 a 2 3 adf
参数解释:
inp 1 a 2 3 adf 调用inp的时候,由于没有调用$4 $5,所以这里第四个参数3 第五个参数adf是不会显示的,因为函数没有执行他们。
以上脚本,正确的输出结果应该是与echo里面除了$参数之外的参数对应,就是说 正常的话 应该输出是对应的.
执行过程
[root@AliKvn shell-re]# sh fun1.sh the first par is 1 the second par is a the triple par is 2 the script is fun1.sh total par is 5 [root@AliKvn shell-re]# sh -x fun1.sh + inp 1 a 2 3 adf + echo 'the first par is 1' the first par is 1 + echo 'the second par is a' the second par is a + echo 'the triple par is 2' the triple par is 2 + echo 'the script is fun1.sh' the script is fun1.sh + echo 'total par is 5' total par is 5
另一种编写方法,输出$1
[root@AliKvn shell]# vim fun2.sh #!/bin/bash function inp() { echo "the first par is $1" echo "the second par is $2" echo "the triple par is $3" echo "the script is $0" echo "total par is $#" } inp $1 $2 $3
解释:
inp $1 $2 $3 $1表示fun2.sh的第一个参数,$2表示fun2.sh的第二个参数,$3表示fun2.sh的第三个参数...
sh fun2.sh执行过程
[root@AliKvn shell-re]# sh fun2.sh 1 the first par is 1 the second par is the tri par is the script name is fun2.sh total number is 1 [root@AliKvn shell-re]# sh fun2.sh 1 2 the first par is 1 the second par is 2 the tri par is the script name is fun2.sh total number is 2 [root@AliKvn shell-re]# sh fun2.sh 1 2 3 the first par is 1 the second par is 2 the tri par is 3 the script name is fun2.sh total number is 3
示例2
用意环境:这个函数用来定义加法
编写脚本
#!/bin/bash sum() { s=$[$1+$2] echo $s } sum 1 10
脚本解释:
s=$[$1+$2] 函数的第一个参数跟第二个参数相加
sum 1 10 调用sum函数,$1+$2=1+10,因为第一个函数1 第二个是10
脚本整个意思就是, s=$[$1+$2]两个函数相加$1+$2(相当于1+10),最后把$s打印出来,其实$s就是他们相加的和
示例3
用意环境:用来显示IP地址的脚本.
编写脚本
#!/bin/bash/ ip() { ifconfig |grep -A1 "$1: " |awk '/inet/ {print $2}' } read -p "plz input the eth name: " eth ip $eth
解释:
ifconfig |grep -A1 "$1: " |awk '/inet/ {print $2}'
用$1参数是针对用于多网卡之下使用,如果只有一个网卡的话,这里写网卡名字就可以.
脚本动作分解,
执行#ifconfig的内容
[root@centos7-01 ~]# ifconfig ens33: flags=4163mtu 1500 inet 192.168.189.128 netmask 255.255.255.0 broadcast 192.168.189.255 inet6 fe80::20c:29ff:fe15:5353 prefixlen 64 scopeid 0x20 ether 00:0c:29:15:53:53 txqueuelen 1000 (Ethernet) RX packets 84 bytes 10800 (10.5 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 142 bytes 15337 (14.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33:0: flags=4163 mtu 1500 inet 192.168.189.150 netmask 255.255.255.0 broadcast 192.168.189.255 ether 00:0c:29:15:53:53 txqueuelen 1000 (Ethernet) ens37: flags=4163 mtu 1500 inet 192.168.149.147 netmask 255.255.255.0 broadcast 192.168.149.255 inet6 fe80::df58:834c:af48:5f38 prefixlen 64 scopeid 0x20 ether 00:0c:29:15:53:5d txqueuelen 1000 (Ethernet) RX packets 1 bytes 243 (243.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 15 bytes 1134 (1.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1 (Local Loopback) RX packets 2252 bytes 691000 (674.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2252 bytes 691000 (674.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
下面以ens33为例 #执行# ifconfig |grep -A1 "ens33: ",因为ens33有2个网卡,所以也会把ens33:0给过滤出来 #表示过滤"ens33"这一行,包括和它下一行 [root@centos7-01 ~]# ifconfig |grep -A1 "ens33: " ens33: flags=4163mtu 1500 inet 192.168.189.128 netmask 255.255.255.0 broadcast 192.168.189.255 -- ens33:0: flags=4163 mtu 1500 inet 192.168.189.150 netmask 255.255.255.0 broadcast 192.168.189.255 #不过滤ens33:0,执行# ifconfig |grep -A1 "ens33: " [root@centos7-01 ~]# ifconfig |grep -A1 "ens33: " ens33: flags=4163 mtu 1500 inet 192.168.189.128 netmask 255.255.255.0 broadcast 192.168.189.255 #ip地址是inet这行,所以,只需过滤这行信息出来 [root@centos7-01 ~]# ifconfig |grep -A1 "ens33: " |grep 'inet' inet 192.168.189.128 netmask 255.255.255.0 broadcast 192.168.189.255 #截取过滤了inet这行出来了,下面需要把想要的ip地址给过滤出来 192.168.189.128是我需要的信息,那么它属于第二个字段,所以可以利用awk把它分割过滤出来 [root@centos7-01 ~]# ifconfig |grep -A1 "ens33: " |grep 'inet' |awk '{print $2}' 192.168.189.128 #或者将后面直接grep的用法换成awk [root@centos7-01 ~]# ifconfig |grep -A1 "ens33: " |awk '/inet/ {print $2}' 192.168.189.128
执行过程:
[root@centos7-01 shell]# sh -x fun3.sh + read -p 'plz input the eth name: ' eth plz input the eth name: ens33 + ip ens33 + ifconfig + grep -A1 'ens33: ' + awk '/inet/ {print $2}' 192.168.189.128 [root@centos7-01 shell]# sh -x fun3.sh + read -p 'plz input the eth name: ' eth plz input the eth name: ens33:0 + ip ens33:0 + ifconfig + grep -A1 'ens33:0: ' + awk '/inet/ {print $2}' 192.168.189.150 [root@centos7-01 shell]# sh -x fun3.sh + read -p 'plz input the eth name: ' eth plz input the eth name: ens37 + ip ens37 + ifconfig + grep -A1 'ens37: ' + awk '/inet/ {print $2}' 192.168.149.147
课后练习:
给此脚本添加2个判断条件:
输入的网卡名称是否存在本机
输入的网卡有没有ip地址
20.18 shell中的数组
shell中的数组1
定义数组 a=(1 2 3);
打印方法 echo ${a[@]}
[root@centos7-01 shell]# a=(1 2 3) [root@centos7-01 shell]# echo ${a[@]} 1 2 3
用*可以代替@,不影响输出,效果一样
[root@centos7-01 shell]# echo ${a[*]} 1 2 3
查看某个参数值,0表示第一个
[root@centos7-01 shell]# echo ${a[1]} 2 [root@centos7-01 shell]# echo ${a[2]} 3 [root@centos7-01 shell]# echo ${a[0]} 1
echo ${#a[@]} 获取数组的元素个数
[root@centos7-01 shell]# echo ${#a[*]} 4
数组赋值
[root@centos7-01 shell]# a[3]=b
打印
[root@centos7-01 shell]# echo ${a[*]} 1 2 3 b
同样,赋值也支持覆盖,更改
[root@centos7-01 shell]# a[3]=bbbb [root@centos7-01 shell]# echo ${a[*]} 1 2 3 bbbb
a[5]=2; echo ${a[@]} 如果下标不存在则会自动添加一个元素
数组的删除
删除a的第四个参数
[root@centos7-01 shell]# unset a[3] [root@centos7-01 shell]# echo ${a[*]} 1 2 3
删除整个数组a
[root@centos7-01 shell]# unset a [root@centos7-01 shell]# echo ${a[*]}
shell中的数组2
数组分片
a=(`seq 1 10`) 可以 1 循环到 10
[root@centos7-01 shell]# a=(`seq 1 10`) [root@centos7-01 shell]# echo ${a[*]} 1 2 3 4 5 6 7 8 9 10
上面的输出,截取4-7的数字
[root@centos7-01 shell]# echo ${a[@]:3:4} 4 5 6 7
解释:
# echo ${a[@]:3:4}
因为从4开始截取,4的前面是3,且3是第三个,然后截取3后面的4个参数。
倒数截取
倒数3个数,截取2个(倒数是负数,所以是0- 表示,截取是从左到右)
[root@centos7-01 shell]# echo ${a[@]:0-3:2} 8 9
数组替换
例子:echo ${a[@]/7/6} 7是需要替换的值,6是被替换的值
[root@centos7-01 shell]# echo ${a[*]} 1 2 3 4 5 6 7 8 9 10 [root@centos7-01 shell]# echo ${a[*]/7/6} 1 2 3 4 5 6 6 8 9 10
同样,可以给a赋值为输出后的参数
[root@centos7-01 shell]# echo ${a[*]/7/6} 1 2 3 4 5 6 6 8 9 10 [root@centos7-01 shell]# a=(${a[*]/7/6}) [root@centos7-01 shell]# echo ${a[*]} 1 2 3 4 5 6 6 8 9 10
输出结果一样
20.19 告警系统需求分析
shell项目-告警系统
需求:使用shell定制各种个性化告警工具,但需要统一化管理、规范化管理。
思路:指定一个脚本包,包含主程序、子程序、配置文件、邮件引擎、输出日志等。
主程序:作为整个脚本的入口,是整个系统的命脉。
配置文件:是一个控制中心,用它来开关各个子程序,指定各个相关联的日志文件。
子程序:这个才是真正的监控脚本,用来监控各个指标。
邮件引擎:是由一个python程序来实现,它可以定义发邮件的服务器、发邮件人以及发件人密码。
输出日志:整个监控系统要有日志输出。
要求:我们的机器角色多种多样,但是所有机器上都要部署同样的监控系统,也就说所有机器不管什么角色,整个程序框架都是一致的,不同的地方在于根据不同的角色,定制不同的配置文件。
程序架构:
bin下是主程序
conf下是配置文件
shares下是各个监控脚本
mail下是邮件引擎
log下是日志