Linux sed 命令

其实对于爱情,越单纯越幸福。

sed是一种流编辑器,它能够完美配合正则表达式使用,功能非同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等。

文件截取

从2012-02-09到2012-09-10的所有数据行, 日志文件以yyyy-MM-dd的日期格式开头

1
sed -n '/^2012-02-09/,/^2012-09-10/p' whole.log > part.log

从文件中导出包含指定内容的行

1
sed -n '/.*010000061905.*/p' catalina.out.2016-12-19 > 010000061905.log

从日志中截取指定时间的内容,如提取12:00-13:00的内容

1
sed -n '/^16-12-19 12:00*/,/^16-12-19 13:00*/p' catalina.out.2016-12-19 > part.log

提取svn日志

找出svn提交历史中的message信息

1
svn log -l2 --xml | grep msg | sed -E "s:</?msg>::g"

日志分析

以下API网管的部分日志数据,URL请求需要经过身份验证才可以被API网管转发,每个请求都需要经过流速控制,下面我们分析9:00-11:00的用户的请求类别、数量以及请求频率是否存在异常:

1
2
3
4
5
6
7
8
9
10
2017-07-17 10:29:59.947 [http-apr-8080-exec-968] INFO PlatformUriHandler - Http request ok : /securityFinanceService.queryFinanceAccountWithProfit(execution times):1130
2017-07-17 10:29:59.967 [http-apr-8080-exec-953] INFO h.a.a.f.AppPlatformRateLimiterFilter - http request=http://api.*.com/securityFinanceService.queryHoldPositionOverview
2017-07-17 10:29:59.967 [http-apr-8080-exec-953] INFO h.a.a.f.AppPlatformRateLimiterFilter - parameter=_appCrypt_=RHtNFWqD74F0TF4WH8YeLA==&ticket=2.daVmH6WojkSmBfJ-ige_cj8mcUolrWsVceIPKnEAcUIy2UvPIGrt8Q-5tIDd8Kt-vD51aSfKhcwMBa4qd4mZc31bDVluaYQvAjPvzSCv-v7QZaH5dOM2QsJN8jrn0ppWJyKpWVQWt8mFWpJ0XoNUYhLd9kB95X2g-bMNI4xGDi0&_t_=HBStockWarningAndroid_3.6.6&
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] INFO hbec.app.api.filter.RateLimiter - userId:2988470, 在 5s 内第1次 执行操作 http://api.*.com/securityFinanceService.queryHoldPositionOverview, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] DEBUG h.a.a.f.AppPlatformRateLimiterFilter - pass rate limiter~
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] DEBUG h.p.commons.web.HbecApiHandleAdapter - param-sha1 : null, appCrypt<1> : RHtNFWqD74F0TF4WH8YeLA==, dataKey=9mycm#kjd=g4r24r
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] DEBUG h.p.commons.web.HbecApiHandleAdapter - plainText<2> reqParam : ,
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] DEBUG h.p.commons.web.HbecApiHandleAdapter - rpc paramter = 2988470
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] DEBUG h.p.commons.web.HbecApiHandleAdapter - rpc parameter = [2988470]
2017-07-17 10:30:00.021 [http-apr-8080-exec-906] INFO h.a.a.f.AppPlatformRateLimiterFilter - http request=http://api.*.com/conditionTradeService.countEntrustedResult

1.按时间段裁剪日志

分析以上日志不难发现,每行都以固定的时间格式开头:2017-07-17 10:29:59.969

1
sed -n '/^2017-07-17 09:00*/,/^2017-07-17 11:00*/p' api2.txt > api2.0900_1000.txt

2.筛选出包含用户Id和请求url的行记录

经过流速控制的请求,都会输出指定的日志,因此我们可以从中筛选出用户信息和请求信息。

1
2017-07-17 10:29:59.969 [http-apr-8080-exec-953] INFO hbec.app.api.filter.RateLimiter - userId:2988470, 在 5s 内第1次 执行操作 http://api.*.com/securityFinanceService.queryHoldPositionOverview, 通过流速控制器, 阀值(5s最高40次)
1
sed -n '/.*hbec.app.api.filter.RateLimiter - userId:.*/p' api2.0900_1000.txt > part.txt

筛选后的日志:

1
2
3
4
5
6
2017-07-17 09:30:00.064 [http-apr-8080-exec-880] INFO hbec.app.api.filter.RateLimiter - userId:3229792, 在 5s 内第3次 执行操作 http://api.touker.com/conditionTradeService.countEntrustedResult, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 09:30:00.091 [http-apr-8080-exec-835] INFO hbec.app.api.filter.RateLimiter - userId:3262223, 在 5s 内第2次 执行操作 http://api.touker.com/securityFinanceService.queryHoldPositionOverview, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 09:30:00.119 [http-apr-8080-exec-868] INFO hbec.app.api.filter.RateLimiter - userId:2328415, 在 5s 内第1次 执行操作 http://api.touker.com/securityExchangeController.queryAvailableNumber, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 09:30:00.138 [http-apr-8080-exec-877] INFO hbec.app.api.filter.RateLimiter - userId:2996025, 在 5s 内第4次 执行操作 http://api.touker.com/followStockService.query, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 09:30:00.182 [http-apr-8080-exec-869] INFO hbec.app.api.filter.RateLimiter - userId:3261451, 在 5s 内第5次 执行操作 http://api.touker.com/abossQuery.queryAbossStatus, 通过流速控制器, 阀值(5s最高40次)
2017-07-17 09:30:00.238 [http-apr-8080-exec-778] INFO hbec.app.api.filter.RateLimiter - userId:2976226, 在 5s 内第3次 执行操作 http://api.touker.com/followStockService.query, 通过流速控制器, 阀值(5s最高40次)

3.替换多余信息

1
2
3
4
sed -i "s/.*.RateLimiter - userId://g" part.txt
sed -i "s/, 通过流速控制器, 阀值(5s最高40次)//g" part.txt
sed -i "s/, 在 5s 内第[0-9]*次 执行操作//g" part.txt
sed -i "s/, 未通过流速控制器, 阀值(5s最高40次)//g" part.txt

替换后

1
2
3
4
5
6
7
8
9
10
3263487 stockService.queryIndustryConceptChange
3263487 followStockService.query
3224197 securityFinanceService.queryHoldPositionOverview
3229792 conditionTradeService.findMonitorPageWithMarket
183981 followStockService.query
3249596 dynamicConfiguration.queryTradeConfiguration
3255313 securityFinanceService.queryHoldPositionOverview
3249596 securityFinanceService.queryFinanceAccountWithProfit
3264204 abossQuery.queryAbossStatus
2868006 stockService.queryIndustryConceptChange

4.统计

统计每个用户的请求信息

1
2
3
排序 : sort part.txt > sort.part
统计 : uniq -c sort.part > count.txt

统计用户数量

1
2
3
4
5
筛选出userId : sed -i "s/ http:\/\/api.touker.com\/.*//g" part.txt
排序 : sort part.txt > userId.sort.part
统计 : uniq -c userId.sort.part > userId.count.txt

统计

统计请求量最大的URL

1
2
3
4
5
6
筛选出URL : sed -i "s/.*http:\/\/api.touker.com\///g" part.txt
排序 : sort part.txt > url.sort.part
统计 : uniq -c url.sort.part > url.count.txt

统计url调用次数

1
2
3
筛选出URL : sed -i "s/.*http:\/\/api.touker.com\///g" part.txt
awk '{sum += $1};END {print sum}' part.txt

合并多个API日志文件的请求次数

1
2
awk '{s[$2] += $1}END{ for(i in s){ print i, s[i] } }' part.txt > final.txt