Linux与Shell实战之Nginx日志分析

课程价值

  • 掌握linux的基本命令
  • 掌握shell的管道机制
  • 掌握三剑客的常见用法

大纲

  • linux数据统计基本命令 sort head tail uniq less vim
  • linux系统命令 ps top netstat
  • 实战环境

时长

180分钟

学习资料

  • 高级Bash脚本编程指南
  • LINUX与UNIX SHELL编程指南
  • 鸟哥的Linux私房菜
  • IBM DeveloperWorks
  • 阮一峰的《bash脚本教程》
  • Google

awk官方文档, mac下的awk与gawk并不一致,用法上有一定的差异。

代码格式化

  • vs code
  • shell format插件

演练环境

#copy到你的个人主目录
ssh 你的个人账号@shell.ceshiren.com
cp /tmp/nginx.log  nginx.log
#copy你的本地
scp 你的个人账号@shell.ceshiren.com:/tmp/nginx.log nginx.log

nginx.log的日志文件,每个关键字段空格隔开,如果字段内容本身有空格,会有其他符号,比如中括号,冒号等进行约束。

223.104.7.59 - - [05/Dec/2018:00:00:01 +0000] "GET /topics/17112 HTTP/2.0" 200 9874 "https://www.googleapis.co
m/auth/chrome-content-suggestions" "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.1
5 (KHTML, like Gecko) CriOS/70.0.3538.75 Mobile/15E148 Safari/605.1" 0.040 0.040 .
123.125.71.60 - - [05/Dec/2018:00:00:02 +0000] "GET /yuanyibo/topics?locale=en HTTP/1.1" 200 12164 "-" "Mozill
a/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" 0.032 0.032 .
141.8.142.131 - - [05/Dec/2018:00:00:02 +0000] "GET /topics?page=63 HTTP/1.1" 200 16739 "-" "Mozilla/5.0 (comp
atible; YandexBot/3.0; +http://yandex.com/bots)" 0.120 0.120 .

定义函数

[root@shell.ceshiren.com ~]$ list_user(){ w | sed '1,2d' | awk '{print $1}' | sort | uniq -c  | wc -l; }^C
[root@shell.ceshiren.com ~]$ type list_user
list_user 是函数
list_user ()
{
    w | sed '1,2d' | awk '{print $1}' | sort | uniq -c | wc -l
}

awk字段枚举

awk 'NR==1{for(i=1;i<=NF;i++) {print i"="$i} }' nginx.log
1=223.104.7.59
2=-
3=-
4=[05/Dec/2018:00:00:01
5=+0000]
6="GET
7=/topics/17112
8=HTTP/2.0"
9=200
10=9874
11="https://www.googleapis.com/auth/chrome-content-suggestions"
12="Mozilla/5.0
13=(iPhone;
14=CPU
15=iPhone
16=OS
17=12_1
18=like
19=Mac
20=OS
21=X)
22=AppleWebKit/605.1.15
23=(KHTML,
24=like
25=Gecko)
26=CriOS/70.0.3538.75
27=Mobile/15E148
28=Safari/605.1"
29=0.040
30=0.040
31=.

善用less

[root@shell.ceshiren.com ~]$ awk '{print $1}' nginx |less
[root@shell.ceshiren.com ~]$ awk '{print $1}' nginx.log |less
[root@shell.ceshiren.com ~]$ awk '{print $1}' nginx.log | sort | less
[root@shell.ceshiren.com ~]$ awk '{print $1}' nginx.log | sort | uniq | less
[root@shell.ceshiren.com ~]$ awk '{print $1}' nginx.log | sort | uniq -c | less

课间作业

演练数据

把/tmp/nginx.log文件复制到自己的主目录下,用来演练

find_error_log

编写一个函数 find_error_log()
找出log中的404 500的报错 考察严谨性,某次训练没有一人做对
回复的时候按照这个格式,直接回帖,回帖的时候记得代码格式化

find_error_log() {
awk '$9~/404|500/{print $0}' nginx.log
}

find_before_and_after

找出500错误时候的上下文,找出500错误记录的前一行与后一行 考察grep高级用法,并把这个参数的描述信息贴上

find_before_and_after(){
}

find_top_3

找出访问量最高的ip, 统计分析,取出top3


find_top_3(){

}

url_avg_time

找出 /topics 的平均响应时间,响应时间在倒数第二个字段

url_avg_time(){
awk '$7=="/topics"{print $(NF-1)}' nginx.log | awk '{sum+=$1}END{print sum/NR}'
}

课后作业 url聚类 url_summary

找出访问量最高的页面地址 借助于sed的统计分析

  • /topics/16689/replies/124751/edit 把数字替换为 /topics/int/replies/int/edit
  • /_img/uploads/photo/2018/c54755ee-6bfd-489a-8a39-81a1d7551cbd.png!large 变成 /_img/uploads/photo/2018/id.png!large
  • /topics/9497 改成 /topics/int
  • 其他规则参考如上

输出

  • url pattern对应的请求数量
  • 取出top 10请求量的url pattern

类似
nnn urlxxx
mmm urlxxx

url_summary(){

}

课程反馈

PPT

find_error_log() { awk '{print $0}' nginx.log |grep -E "\b(404|500)\b"; }
find_error_log() {less nginx.log | grep '404';less nginx.log | grep '500';} 
find_error_log(){
	sed -n -e '/404/p' -e '/500/p' nginx.log;
}
{ 
    grep --color=auto '404\|500' nginx.log
}
find_error_log() {grep -E "\b500|404\b" ~/nginx.log;}
find_error_log() {
less nginx.log | grep ' 404 ';less nginx.log | grep ' 500 ';
}
find_error_log() {
grep -E '\s500\s|\s404\s' nginx.log } 

-C NUM, -NUM, --context=NUM
Print NUM lines of output context. Places a line containing a group separator
(described under --group-separator) between contiguous groups of matches. With the -o
or --only-matching option, this has no effect and a warning is given.

find_before_and_after(){
    grep -E -C2 "\b500\b" ~/nginx.log;
}
1 Like

find_before_and_after(){grep -1 -i ‘\b500\b’ nginx.log
}

find_before_and_after(){
grep -C 1 ’ 500 ’ nginx.log
}

}
 grep -B 1 -A 1 -E '\s500\s' nginx.log 
}
find_top_3(){less nginx.log | awk '{print $1}' | sort | uniq -c | head -3 }

find_top_3(){
awk ‘{print $1}’ nginx.log|sort|uniq -c|sort -nr|head -3
}

find_top_3(){
cat /tmp/nginx.log|awk -F" " ‘{print $1}’|sort|uniq -c|sort -nrk 1 -t’ '|awk -F" " ‘{print $2}’|head -3 ;
}

find_top_3(){cat nginx.log|awk -F " " '{print $1}'|sort|uniq -c|sort -nrk 1|awk -F " " '{print $2}'|head -3}
find_top_3()
{
   awk '{print $1}' nginx.log|sort|uniq -c|sort -nr|head -3; 
}
@shell.ceshiren.com ~]$ find_top_3 
    282 216.244.66.241
    130 136.243.151.90
    110 127.0.0.1
1 Like
cat nginx.log |cut -d ' ' -f 1 | sort |uniq -c | sort -nr | awk '{print $0 }' | head -n 3 | less

find_top_3(){ awk ‘{print $1}’ nginx.log|sort |uniq -c|sort -r -n -k 1|head -n 3;}

cat nginx.log | awk '{sum+=$(NF-1)} END {print "", sum/NR}'