awk [options] 'commands' filenames
-F:对于每次处理的内容,可以指定一个自定义的分隔符,默认的分隔符是空白字符(空格或 tab 键 )
awk -F":" '{print $1,$3}' /etc/passwd
1.awk使用一行作为输入,并将这一行赋给变量$0
,每一行可称作为一个记录,以换行符结束
2.然后,行被空格分解成字段,每个字段存储在已编号的变量中,从$1
开始
3.awk如何知道空格来分隔字段的呢?因为有一个内部变量FS来确定字段分隔符,初始时,FS赋为空格或者是tab
4.awk打印字段时,将以设置的方法,使用print函数打印,awk在打印的字段间加上空格,因为$1,$2间有一个,逗号。逗号比较特殊,映射为另一个变量,成为输出字段分隔符OFS,OFS默认为空格
5.awk打印字段时,将从文件中获取另一行,并将其存储在$0
中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程持续到处理文件结束。
command:BEGIN{} {} END{} filename
? 行处理前的动作 行内容处理的动作 行处理之后的动作 文件名
?
BEGIN{}和END{} 是可选项
BEGIN{}:读入文本之前要操作的命令。(也可以设置变量,取值可以不加$)
{}:主输入循环(用的最多),读入文件之后擦操作的命令;如果不读入文件都可以不用写。
END{}:文本全部读入完成之后执行的命令。
[root@localhost ~]# awk 'BEGIN{ print 1/2} {print "ok"} END{print "----"}' /etc/hosts
?//或者 cat /etc/hosts | awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}'
0.5
ok
ok
----
awk 按记录处理:一行是一条记录,因为awk默认以换行符分开的字符串是一条记录。(默认\n换行符:记录分隔符)
字段:以字段分割符分割的字符串 默认是单个或多个“ ” tab键。
?awk中的变量
$0表示整行NF统计字段的个数/统计列的列数$NFnumber finally,表示最后一列的信息 (用的最多)RS输入记录分隔符ORS输出记录分隔符NR打印记录行号(用的最多)FNR可以分开,按不同的文件打印行号FS输入字段分隔符,默认为一个空格OFS输出的字段分隔符,默认为一个空格FILENAMEFILENAME 文件名 被处理的文件名称$1$1第一个字段,$2第二个字段,以此类推…
?注:如果-F不加默认为空格区分!
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN{FS=":"} {print $1,$2}'
//或者 awk -F':' '{print $1,$2}' /etc/passwd
root x
bin x
daemon x
....
[root@localhost ~]# cat /etc/passwd | awk -F":" '{print $1,$2}'
root x
bin x
daemon x
....
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN{FS=":";OFS=".."} {print $1,$2}' #OFS 输出的字段分隔符,默认为一个空格。
root..x
bin..x
daemon..x
...
//创建两个文件
[root@localhost ~]# vim a.txt
love
love.
loove
looooove
[root@localhost ~]# vim file1.txt
isuo
IPADDR=192.168.246.211
hjahj123
GATEWAY=192.168.246.1
NETMASK=255.255.255.0
DNS=114.114.114.114
[root@localhost ~]# awk '{print NR,$0}' a.txt file1.txt
1 love
2 love.
3 loove
4 looooove
5
6 isuo
7 IPADDR=192.168.246.211
8 hjahj123
9 GATEWAY=192.168.246.1
10 NETMASK=255.255.255.0
11 DNS=114.114.114.114
[root@localhost ~]# awk '{print FNR,$0}' a.txt file1.txt
1 love
2 love.
3 loove
4 looooove
5
1 isuo
2 IPADDR=192.168.246.211
3 hjahj123
4 GATEWAY=192.168.246.1
5 NETMASK=255.255.255.0
6 DNS=114.114.114.114
FR和FNR的区别:
NR:代表总的记录(行)数,在所有文件中是连续不断的。
FNR:仅代表当前文件中的记录(行)数,不同文件从1开始计数。
//创建一个文件
[root@localhost ~]# cat a.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/bash
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:1001:1001::/home/nginx:/bin/bash
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin
?
[root@localhost ~]# awk 'BEGIN{RS="bash"} {print $0}' a.txt
root:x:0:0:root:/root:/bin/
?
bin:x:1:1:bin:/bin:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/
?
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:1001:1001::/home/nginx:/bin/
?
root:x:0:0:root:/root:/bin/
bin:x:1:1:bin:/bin:/sbin/nologin
//对刚才的文件进行修改
[root@localhost ~]# vim passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
//输入记录符为bash,输出记录符为换行
[root@localhost ~]# awk 'BEGIN{RS="bash";ORS="----"} {print $0}' a.txt
root:x:0:0:root:/root:/bin/----
bin:x:1:1:bin:/bin:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/----
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:1001:1001::/home/nginx:/bin/----
root:x:0:0:root:/root:/bin/----bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost ~]# cat /etc/passwd | awk -F":" '{print NF}'
7
7
7
7
[root@localhost ~]# cat /etc/passwd | awk -F":" '{print $NF}'
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
练习1:将文件合并为一行
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN{ORS="" } {print $0}'
练习2:把一行内容分成多行
//首先创建一个文件
[root@localhost ~]# vim d.txt
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# cat d.txt | awk 'BEGIN{RS=":"} {print $0}'
root
x
0
0
root
/root
/bin/bash
字符串需要使用双引号
!= 表示不等于,取反
[root@localhost ~]# awk -F":" '$NF=="/bin/bash"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
tang:x:1000:1000:tang:/home/tang:/bin/bash
nginx:x:1001:1001::/home/nginx:/bin/bash
// == 后面的字符串不加引号就无法打印出来
?
[root@localhost ~]# awk -F":" '$1 != "root"' /etc/passwd
[root@localhost ~]# awk -F":" '$NF!="/sbin/nologin"' /etc/passwd
示例
[root@localhost ~]# awk -F":" '$3 == 0 ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
?
[root@localhost ~]# awk -F":" '$3 < 2 ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
?
[root@localhost ~]# awk -F":" '$3<2' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
?
[root@localhost ~]# awk -F":" '$3<=2' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
?
[root@localhost ~]# awk -F":" '$3>100' passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/bash
?
[root@localhost ~]# awk -F":" '$3>=1000' passwd
tang:x:1000:1000:tang:/home/tang:/bin/bash
可以在模式中执行计算,awk都将按浮点数方式执行算术运算
[root@localhost ~]# awk -F: '$3 * 10 > 1000' /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/bash
nginx:x:1001:1001::/home/nginx:/bin/bash
?
[root@localhost ~]# awk -F":" '$3 * 10 >=10000' passwd
tang:x:1000:1000:tang:/home/tang:/bin/bash
[root@localhost ~]# awk -F":" '$NF=="/bin/bash" && $3 >=15' /etc/passwd
tang:x:1000:1000:tang:/home/tang:/bin/bash
nginx:x:1001:1001::/home/nginx:/bin/bash
?
?
[root@localhost ~]# awk -F":" '$NF=="/bin/bash" || $3 >=15' /etc/passwd
root:x:0:0:root:/root:/bin/bash
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
tang:x:1000:1000:tang:/home/tang:/bin/bash
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:1001:1001::/home/nginx:/bin/bash
1.打印一个文件中的第一行的第2列和第3列
[root@localhost ~]# cat /etc/passwd | awk -F: 'NR==1 {print $2,$3}'
x 0
2.打印指定行指定列的某个字符
//获取内存可使用空间
[root@localhost ~]# free -h|awk 'NR==2 {print $4}'
2.5G
?
[root@localhost ~]# cat /etc/passwd | awk -F: 'NR==2 {print $1}'
bin
?
//获取根分区的使用量
[root@localhost ~]# df -Th|awk 'NR==6 {print $5}'
48G
3.统计一个文件的行数、列数
//打印行数
[root@localhost ~]# cat /etc/passwd | awk '{print NR}'
?
//打印列数
[root@localhost ~]# cat /etc/passwd | awk -F: '{print NF}'
4.awk和if条件判断结合使用(使用最广)
监控告警脚本使用if判断
[root@localhost ~]# df -Th|awk 'NR==6 {print $6}'|awk -F% '{print $1}'
5
//判断根分区当前使用率
[root@localhost ~]# vim disk.sh
#!/bin/bash
root_used=`df -Th|awk 'NR==6 {print $6}'|awk -F% '{print $1}'`
if [[ $root_used -gt 90 ]]; then
echo "警报!服务器根分区使用率超过90%,当前使用率为${root_used}%"
else
echo "当前根分区使用率${root_used}%,一切正常!"
fi
//往/root中写入测试文件
[root@localhost ~]# dd if=/dev/zero of=/root/text.txt count=44 bs=1G //大小根据磁盘空间
[root@localhost ~]# wacth -n1 bash disk.sh //另一个终端查看
//判断当前cpu使用率,当空闲率小于20%时告警
//查看当前cpu的空闲率
[root@localhost ~]# top -b -n1|grep -i cpu|awk -F,'NR==1 {print $4}' |awk '{print $1}'
100.0
参数解释:
n 设置退出前屏幕刷新的次数
b 将top输出编排成适合输出到文件的格式,可以使用这个选项创建进程日志
//当cpu空闲率小于20%就告警(说明使用率超过了80%)
#!/bin/bash
cpu_free=$(top -b -n1|grep -i cpu|awk -F',' 'NR==1 {print $4}' |awk '{print $1}')
alarm_value=20.0
if [[ $(echo "$cpu_free > $alarm_value" | bc) -eq 1 ]];then
echo "当前服务器CPU空闲率为:${cpu_free}%,一切正常!"
else
echo "警报!服务器CPU使用率超过80%,当前CPU空闲率为${cpu_free}%!"
fi
?
//或将bc去掉也可以,不过只能比较整数
#!/bin/bash
cpu_free=$(top -b -n1|grep -i cpu|awk -F',' 'NR==1 {print $4}' |awk -F"." '{print $1}')
alarm_value=20
if [[ "$cpu_free > $alarm_value" ]];then
echo "当前服务器CPU空闲率为:${cpu_free}%,一切正常!"
else
echo "警报!服务器CPU使用率超过80%,当前CPU空闲率为${cpu_free}%!"
fi
?
//bc是一种用于高精度计算的命令行计算器工具,支持数学运算、函数计算、字节单位换算等。
bc -eq 1 解释:
[root@localhost ~]# echo "29.9 <=29.99"|bc
1 #正确为1
[root@localhost ~]# echo "29.9 >= 29.99"|bc
0 #错误为0
[root@localhost ~]# yum -y install bc
?
//正常情况的脚本:
[root@localhost ~]# bash cpu.sh
当前服务器CPU空闲率为:97.1%,一切正常!
?
//使用压测工具,将cpu的使用率拉满
//安装压测工具
yum install stress sysstat -y
?
//模拟cpu运行
stress --cpu 2 --timeout 600
?
//执行完之后再去执行脚本,查看是否会报错
[root@localhost ~]# bash cpu.sh
警报!服务器CPU使用率超过80%,当前CPU空闲率为0.0%!
?
?//查询CPU占用情况
[root@localhost ~]# mpstat -P ALL 5
Linux 3.10.0-1160.66.1.el7.x86_64 (localhost.localdomain) 2023年07月16日 _x86_64_ (2 CPU)
?
08时53分35秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
08时53分40秒 all 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08时53分40秒 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08时53分40秒 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#-P ALL:显示所有的逻辑处理器(CPU)的CPU使用和负载信息
#5:显示信息的间隔为 5 秒。
?
//或者使用top/htop查看
[root@localhost ~]# top -b -n1|grep -i cpu
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
#使用top查看cpu的可用率为0.0
?
?
//判断当前内存可用空间,低于0.5G时告警
[root@localhost ~]# free -h|awk 'NR==2 {print $4}'|awk -FG '{print $1}'
2.4
?
//当内存可用空间少于0.5G时告警
#!/bin/bash
free=$(free -h|awk 'NR==2 {print $7}'|awk -FG '{print $1}')
alarm_value=0.5
if [[ $(echo "$free > $alarm_value" | bc) -eq 1 ]];then
echo "当前服务器内存可用空间为:${free}G,一切正常!"
else
echo "警报!服务器内存可用空间少于0.5G,当前内存的可用空间为:${free}"
fi
?
//正常情况下执行的脚本
[root@localhost ~]# bash free.sh
当前服务器内存可用空间为:3.5G,一切正常!
?
//使用压测工具将内存值拉高,并执行告警脚本
[root@localhost ~]# stress --vm 10 --vm-bytes 1024M --timeout 30s
stress: info: [94472] dispatching hogs: 0 cpu,0 io,10 vm,0 hdd
参数解释:
–vm 指定测试类型,此处为 memory 测试。
10 指定创建 10 个虚拟用户。每个虚拟用户都会占用指定大小的内存空间。
–vm-bytes 1024M 指定每个虚拟用户分配的内存大小,此处为 1024MB。
–timeout 30s 指定测试运行时间,此处为 30 秒。
?
[root@localhost ~]# bash free.sh
(standard_in) 1: illegal character: M
警报!服务器内存可用空间少于0.5G,当前内存的可用空间为:84M
5.在awk中使用for循环
//每行打印两遍
[root@localhost ~]# awk '{for(i=1;i<=2;i++) {print $0}}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
UV与PV统计
PV:即访问量,也就是访问您商铺的次数;
例如:今天显示有300 PV,则证明今天你的商铺被访问了300次。
UV:即访问人数,也就是有多少人来过您的商铺; #需要去重
例如:今天显示有50 UV,则证明今天有50个人来过你的商铺。
切割nginx的日志,统计PV/UV,出现次数最多的url等各种切割统计
1.根据访问IP统计UV
[root@localhost ~]# cat access.log | awk '{print $1}' |sort |uniq -c | wc -l
//uniq:去重
//-c:统计每行连续出现的次数
2.更具访问ip统计PV
[root@localhost ~]# cat access.log | awk '{print $1}' |wc -l
或者是url
[root@localhost ~]# cat access.log | awk '{print $7}' |wc -l
3.查询访问最频繁的URL
[root@localhost ~]# cat access.log | awk '{print $7}'|sort | uniq -c |sort -rn -k1
4.查询访问最频繁的IP
[root@localhost ~]# cat access.log | awk '{print $1}'|sort | uniq -c |sort -n -k 1 -r | more