awk高级应用

awk流程控制

分支结构

  • 单分支:   if(条件){编辑指令}
  • 双分支:   if(条件){编辑指令}else{编辑指令2}
  • 多分支:   if(条件){编辑指令}else  if(条件){编辑指令2}...
  •                else{编辑指令N} 

if(条件1){编辑指令1}else if (条件2){编辑指令2}else{编辑指令N}

单分支练习

[root@server0 ~]# cat user                           #准备素材
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
 
[root@server0 ~]# awk  -F: '{if($3==0){print}}' user     #如果第三列是0,则输出该行
root:x:0:0:root:/root:/bin/bash
 
[root@server0 ~]# awk -F:  '{if($3<=2){print  "haha"}else{print  "heihei"}}' user        #如果第三列小于等于2,则输出haha,否则输出heihei 
haha
haha
haha
heihei
heihei

 

双分支练习

统计用户UID,小于10和大于1000的数量

[root@server0 ~]# awk -F: '$3>1000' /etc/passwd  | wc -l      
2
[root@server0 ~]# awk -F: '$3<10' /etc/passwd  | wc -l
9
[root@server0 ~]# awk -F: '$3>=10&&$3<=1000' /etc/passwd  | wc -l
29
 
[root@server0 ~]# awk  -F: 'BEGIN{a=0;b=0;c=0}{if($3<10){a++}else if($3>1000){b++}else{c++}}END{print a,b,c}' /etc/passwd
9 2 29                                #9为UID小于10的数量,2为UID大于1000的数量,29为UID10到1000的数量

分别统计/etc/passwd文件中登录shell是"/bin/bash",登录shell不是"/bin/bash"的用户个数

[root@server0 ~]# awk -F: '{if($7=="/bin/bash"){a++} else{b++}}END{print a,b}' /etc/passwd
3 37

 多分支练习

列出UID小于等于10或者大于1000的数量,并统计总数:

[root@server0~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3<=10){x++}else if($3>1000){y++}else{z++}}END{print x,y,z}' /etc/passwd
9 7 15
加上常量显示:
[root@server0~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3<=10){x++}else if($3>1000){y++}else{z++}}END{print "UID小于10的数量是"x,"UID大于10的数量是"y,"两者总数是"z}' /etc/passwd
UID小于10的数量是9 UID大于10的数量是7 两者总数是15

数组:能够存储多个不同值的特殊变量

定义数组的格式:数组名[下标]=元素值
下标可以是数字或者字母或者变量
调用数组的格式:数组名[下标]
遍历数组的用法:for(变量 in 数组名){print 数组名[变量]}。
定义数组后配合for循环可以方便的查看数组所有内容,次过程成为遍历数组
下标和值可以不用数字

定义数组a自增1,输出结果:
[root@server0~]# awk 'BEGIN{a[0]++;print a[0]}'
1
定义数组a,for循环数组a,由于数组a只有三个下标所以循环3次并输出下标及对应下标的值:
[root@server0~]# awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}'
0 0
1 11
2 22
定义数组a,下标分别是1和2,然后输出该数组对应下标的值:
[root@server0~]# awk 'BEGIN{a[1]=100;a[2]=200;print a[1],a[2]}'
100 200
调用数组的顺序:
[root@server0~]# awk 'BEGIN{a[1]=100;a[2]=200;print a[2],a[1]}'
200 100
对定义好的数组做运算:
[root@server0~]# awk 'BEGIN{a[1]=100;a[1]++;print a[1]}'
101
定义数组a,for循环遍历数组下标:
[root@server0~]# awk 'BEGIN{a[1]=100;a[2]=200;for(i in a){print i}}'
1
2
定义数组a,for循环遍历数组a:
[root@server0~]# awk 'BEGIN{a[1]=100;a[2]=200;for(i in a){print i,a[i]}}'
1 100
2 200
定义数组的下标为字母a,需要用""引起来
[root@server0~]# awk 'BEGIN{a["a"]="abc";print a["a"]}'
abc
[root@server0~]# cat abc   以abc作为素材
abc
abc
xyz
opq
xyz
abc
在逐行任务中定义数组a++,for循环遍历数组a,显示下标:
[root@server0~]# awk '{a[$1]++}END{for(i in a){print i}}' abc
opq
abc
xyz
逐行任务,相当于收集数据,然后在END任务中用for循环查看数组的所有内容:
[root@server0~]# awk '{a[$1]++}END{for(i in a){print i,a[i]}}' abc
opq 1
abc 3
xyz 2
 
以上结果解析:
abc (定义ABC下标)  a[abc]=1  (统计次数为1次) 
abc (已有ABC下标)  a[abc]=2  (统计次数为2次)
xyz (定义xyz下标)  a[xyz]=1  (统计次数为1次)
opt (定义opt下标)  a[opt]=1  (统计次数为1次)
abc (已有ABC下标)  a[abc]=3  (统计次数为3次)
xyz (已有xyz下标)  a
[root@server0~]# cat abc  以abc为素材
abc 192.168.0.1
abc 192.168.0.1
xyz 192.168.0.2
opq 192.168.0.3
xyz 192.168.0.2
abc 192.168.0.1
[root@proxy mnt]# awk '{ip[$2]++}END{for(i in ip){print i}}' abc
192.168.0.1
192.168.0.2
192.168.0.3
[root@proxy mnt]# awk '{ip[$2]++}END{for(i in ip){print i,ip[i]}}' abc
192.168.0.1 3
192.168.0.2 2
192.168.0.3 1
 
结果解析:
abc 192.168.0.1 (定义192.168.0.1为下标)  a[192.168.0.1]=1  (统计次数为1次) 
abc 192.168.0.1 (已有192.168.0.1下标)    a[192.168.0.1]=2  (统计次数为2次)
xyz 192.168.0.2 (定义192.168.0.2为下标)  a[192.168.0.2]=1  (统计次数为1次)
opt 192.168.0.3 (定义192.168.0.3为下标)  a[192.168.0.3]=1  (统计次数为1次)
abc 192.168.0.1 (已有192.168.0.1下标)    a[192.168.0.2]=2  (统计次数为3次)
xyz 192.168.0.2 (已有192.168.0.2下标)    a[192.168.0.1]=3  (统计次数为2次)
192.168.0.1下标的总数为3次
192.168.0.2下标的总数为2次
192.168.0.3下标的总数为1次

利用sort对提取结果排序

sort 命令: 将文本文件内容加以排序,sort可针对文本文件的内容,以行为单位来排序。

 -b   忽略每行前面开始出的空格字符。
 -c   检查文件是否已经按照顺序排序。
 -d   排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
 -f    排序时,将小写字母视为大写字母。
 -i    排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
 -k    针对指定的列进行排序
 -m    将几个排序好的文件进行合并。
 -M   将前面3个字母依照月份的缩写进行排序。
 -n   依照数值的大小排序。是以数字形式排序
 -o  <输出文件>   将排序后的结果存入指定的文件。
 -r   以相反的顺序来排序。是降序
 -t  <分隔字符>   指定排序时所用的栏位分隔字符。

awk扩展应用

使用awk统计Web访问排名:

在分析Web日志文件时,每条访问记录的第一列就是客户机的IP地址,其中会有很多重复的IP地址。因此只用awk提取出这一列是不够的,还需要统计重复记录的数量并且进行排序。

通过awk提取信息时,利用IP地址作为数组下标,每遇到一个重复值就将此数组元素递增1,最终就获得了这个IP地址出现的次数。

下面以server0虚拟机作为web服务端:由真机,另一台虚拟机作为测试机
[root@server0~]# rpm -q httpd
httpd-2.4.6-80.el7.centos.x86_64
[root@server0~]# systemctl restart httpd
[root@server0~]# netstat  -nutlp |grep :80
tcp    LISTEN     0      128       *:80                    *:*                   users:(("httpd",pid=1037,fd=3),("httpd",pid=1036,fd=3),("httpd",pid=1035,fd=3),("httpd",pid=1034,fd=3),("httpd",pid=1033,fd=3),("httpd",pid=1032,fd=3))
[root@server0~]# cd /var/log/httpd
[root@server0 httpd]# ls  ##httpd服务的访问日志
access_log  error_log
利用真机,其他虚拟机进行访问
[root@server0~

编写监控脚本

本案例要求编写脚本,实现计算机各个性能数据监控的功能,具体监控项目要求如下:
1.CPU负载
2.网卡流量
3.内存剩余容量
4.磁盘剩余容量
5.计算机账户数量
6.当前登录账户数量
7.计算机当前开启的进程数量
8.本机已安装的软件包数量

1.查看性能数据的命令

1.CPU负载 : [root@server0~]# uptime                                                   (top命令或uptime数量,top命令是交互式的!)
2.网卡流量 : [root@server0~]# ifconfig eth0                                           (ifconfig筛选接收和发送流量)
3.内存剩余容量 :  [root@server0~]# free                                                (free  -h命令或者head -2 /proc/meminfo)
4.磁盘剩余容量 :  [root@server0~]# df                                                    (df -h)
5.计算机账户数量 : [root@server0~]# wc -l /etc/passwd                         (/etc/passwd或者sed命令或者awk命令)
6.当前登录账户数量 : [root@server0~]# who |wc -l                                 (who命令)
7.计算机当前开启的进程数量 : [root@server0~]# ps aux | wc -l              (ps  aux)
8.本机已安装的软件包数量 : [root@server0~]# rpm -qa |wc -l                 (rpm -qa)

2.用awk进行处理1-5

1.[root@proxy mnt]# uptime | awk '{print "CPU的平均负载是"$8 $9 $10}'  ##列数请参照实际情况,此为案例
2.[root@proxy mnt]#  ifconfig eth0 |awk -F[] '/RX p/{print "eth0的接收流量是"$2}'
2.[root@proxy mnt]# ifconfig eth0 |awk -F[] '/TX p/{print "eth0的接收流量是"$2}'
3.[root@proxy mnt]#  free -m | awk '/Mem:/{print "当前主机剩余内存空间"$4"MB"}'
4.[root@proxy mnt]#  df -h |awk '/\/$/{print "主机根分区剩余空间是"$4}'
5.[root@proxy mnt]#  awk 'END{print "本机账户数量是"NR"个"}' /etc/passwd |wc -l

3.编写脚本

[root@server0 ~]# vim jk.sh
#!/bin/bash
while :
do
        uptime  | awk '{print "当前主机CPU平均负载是"$NF}'
        ifconfig eth0 | awk -F[\(\)] '/Rx p/{print "eth0网卡的接收流量是" $2}'
        ifconfig eth0 | awk -F[\(\)] '/Tx p/{print "eth0网卡的发送流量是" $2}'
        free -h | awk '/Mem/{print  "当前主机内存剩余空间是" $4}'
        df -h | awk '/vda1/{print "当前主机根分区剩余空间是" $4}'
        awk  'END{print "当前主机用户数量总共是"NR"个"}' /etc/passwd
        x=`who | wc -l`
        echo "当前主机登录账户的数量是$x 个"
        p=`ps aux | wc -l`
        echo "当前主机开启的进程数量是$p 个"
        n=`rpm -aq  | wc -l`
        echo "当前主机安装的软件包数量是$n 个"
        sleep 2
        clear               #效果与ctrl+l相同
done
 
[root@server0 ~]# bash jk.sh
当前主机CPU平均负载是0.06
当前主机内存剩余空间是126M
当前主机根分区剩余空间是7.0G
当前主机用户数量总共是41个
当前主机登录账户的数量是2 个
当前主机开启的进程数量是128 个
当前主机安装的软件包数量是1214 个
编写安全检测脚本

编写安全检测脚本

防止远程ssh暴力破解密码,具体监控项目要求如下:

检测ssh登录日志,如果远程登陆账号名错误3次,则屏蔽远程主机的IP
检测ssh登录日志,如果远程登陆密码错误3次,则屏蔽远程主机的IP

1.过滤帐户名失败的命令(登陆日志文件为/var/log/secure)

[root@server0~]# awk '/Invalid user/{print $11}' /var/log/secure   ##列出登录失败的账号
[root@server0~]# awk '/Invalid user/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure  ##统计次数

2. 过滤密码失败的命令

[root@server0~]# awk '/Failed/{print $11}' /var/log/secure  ##列出密码登录失败的账号
[root@server0~]# awk '/Failed/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure ##统计次数

3.编写脚本

root@server0 ~]# vim test.sh
#!/bin/bash
#这是一个防止远程登录失败3次的脚本
u=`awk '/Failed/{ip[$11]++}END{for(i in ip){print ip[i],i}}'  /var/log/secure | awk '$1>3{print $2}'`
[ -z  "$u"  ]  || echo "有人尝试登录服务器!相关信息是$u" | mail -s test root
 
此时可以用其他的虚拟机模拟远程登录失败三次
[root@server0 ~]# bash test.sh             #执行脚本
 
[root@server0 ~]# mail                    #查看root邮件
Heirloom Mail version 12.5 7/5/10.  Type ? for help.
"/var/spool/mail/root": 1 message 1 new
>N  1 root                  Thu Jan  9 15:53  18/634   "test"
& 1
Message  1:
From [email protected]  Thu Jan  9 15:53:55 2020
Return-Path: 
X-Original-To: root
Delivered-To: [email protected]
Date: Thu, 09 Jan 2020 15:53:55 +0800
To: [email protected]
Subject: test
User-Agent: Heirloom mailx 12.5 7/5/10
Content-Type: text/plain; charset=utf-8
From: [email protected] (root)
Status: R
 
有人尝试登录服务器!相关信息是172.25.0.10
 
& q   
Held 1 message in /var/spool/mail/root

你可能感兴趣的:(awk高级应用)