日志處理中一些shell命令技巧
陰差陽錯(cuò)的做的日志分析,前途未卜的這段日子,唯一還有點(diǎn)意思的可能就是手動的處理大量日志??偨Y(jié)一下。
日志文件的輸入是動則幾個(gè)G的文本。從N個(gè)這樣的文件中得到一個(gè)列表,一個(gè)數(shù)字,一個(gè)比例。在什么工具都沒有情況下,用shell命令不僅是驗(yàn)證系統(tǒng)數(shù)據(jù)的準(zhǔn)確性的方法,也是一個(gè)很好的學(xué)習(xí)過程。
使用cut命令切割日志行
下面的一行典型的apache訪問日志:
120.51.133.125 - - [26/Apr/2013:12:20:06 +0800] "GET /skins/skin_homepage.php?display=wvga&lang=ja_JP&pixel=720X1280&density=2.0&version=5.7&key=5146f54950f09f71750005ef&uid=1 HTTP/1.1" 200 4847 "http://t.co/rww3WDuhS5" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; YTB730)" 0
如果需要得到IP地址可以使用cut
命令
-d ' '
表示按照空格將行切開,-f1
取第一個(gè)字段,這樣得到的結(jié)果就是IP列表
有時(shí)候拿到的文件是\t
分隔,也可以使用cut切開,只不過需要多寫一個(gè)$
[l]$ cat log | cut -d '\t' -f1 cut: the delimiter must be a single character #-d '\t'會報(bào)錯(cuò)的 cut -f2 -d$'\t' infile #work
使用tr命令去掉字符,替換字符
如果拿到
分割的文件
將空格替換成,文件變成csv
上面的命令直接刪除空格
日志處理后經(jīng)常會出現(xiàn)空行,tr命令去掉空行的原理就是將連續(xù)兩個(gè)換行替換成一個(gè)換行
cat log | tr -s '\n\n' '\n'
使用uniq命令去重
試想得到IP列表,欲得到獨(dú)立訪問的IP列表。
[l]$ cat log | cut -d ' ' -f1 | uniq -u
如果不僅僅是去重,還想統(tǒng)計(jì)每個(gè)IP訪問次數(shù),可以加一個(gè)參數(shù)c
[l]$ cat log | cut -d ' ' -f1 | uniq -uc
得到的格式形如:
1 126.193.38.128 5 49.98.156.154
前面的數(shù)字就是出現(xiàn)的次數(shù)
使用awk/seed來處理日志
awk/seed是處理日志的最終的萬金油。確實(shí)是什么都可以做。awk/seed是一門很大的學(xué)問。這里取我碰到的一個(gè)日志,日志格式形如:
display=wvga|||lang=ja_JP|||isActive=1|||pixel=720X1280|||density=2.0|||version=5.7|||key=5146f54950f09f71750005ef|||out=abc'3|||uid=1
如果我需要得到isActive=1的日志行,取到out=中'前一段,如上面的abc。
cat l | grep "isActive=1|" | awk 'match($0,/out=[^\x27]+/){print substr($0,RSTART+4,RLENGTH-4)}'
grep的功能是篩選isActive=1
的行。awk 后面跟''的是awk語言。$0
總是代表當(dāng)前匹配的字段值,match substr是awk可以用的函數(shù),當(dāng)match時(shí)后面{}中的代碼才會執(zhí)行。當(dāng)match,$0就是正則匹配的部分。RSTART,RLENGTH是awk可以使用的常量,分別表示開始匹配的開始下標(biāo),RLENGTH是匹配的長度。
在''中需要再使用'光轉(zhuǎn)義是不行的,得用16進(jìn)制的代碼\x27。轉(zhuǎn)16進(jìn)制可以使用python代碼 "'".encode("hex")
得到
//驚訝awk就這么簡單的解釋了,可這連入門都算不上。
集合操作
試想我想得到兩個(gè)列表的交際,并集,差集,統(tǒng)計(jì)中經(jīng)常會碰到,比如我想獲得昨天今天都在訪問的IP,其實(shí)就是今天的IP列表和昨天IP列表的交集。
先定義兩個(gè)簡單的文件:
[ l]$ cat a.txt 1 2 3 4 5 [ l]$ cat b.txt 4 5 6 7 8 9
如果想得到ab的交集4 5 ,可以使用下面的命令:
sort -m a.txt b.txt | uniq -d 4 5
如果要得到并集1-9,可以:
sort -m a.txt b.txt | uniq 1 2 3 4 5 6 7 8 9
如果想得到ab的差集,即a去掉ab的交集1 2 3
comm -23 a.txt b.txt 1 2 3
同理:ba的差集:
comm -13 a.txt b.txt comm -23 b.txt a.txt
上述兩個(gè)命令等價(jià)
comm命令就是compare功能,如果什么參數(shù)都不帶呢得到的什么呢?
comm a.txt b.txt 1 2 3 4 5 6 7 8 9
diff命令以前經(jīng)??创a改了哪些:
diff a.txt b.txt 1,3d0 < 1 < 2 < 3 5a3,6 > 6 > 7 > 8 > 9
總結(jié)&&參考資料
竊以為能玩轉(zhuǎn)上面這些命令,處理個(gè)日志問題不大了。
一篇介紹shell中集合操作的博文:
http://wordaligned.org/articles/shell-script-sets
一直放在收藏夾的shell方面的博客:
Linux Shell常用技巧
Linux Shell高級技巧 awk部分寫的獨(dú)好