grep,sed,sort,awk運(yùn)用

概述

        我們?nèi)粘?yīng)用中都離不開日志⊥宜恚可以說日志是我們在排查問題的一個(gè)重要依據(jù)。但是日志并不是寫了就好了,當(dāng)你想查看日志的時(shí)候,你會(huì)發(fā)現(xiàn)線上日志堆積的長度已經(jīng)超越了你一行行瀏覽的耐性的極限了笤成。于是总处,很有必要通過一些手段來高效地輔助你來快速的從日志中找到你要找的問題缝呕。本文通過一個(gè)從項(xiàng)目中衍生出來的例子從查找日志,篩選日志和統(tǒng)計(jì)日志3個(gè)方面層層遞進(jìn)來簡述日志文件查看中一些有用的手段鹦马。(注:在Linux環(huán)境下)


目錄

0.查找關(guān)鍵日志grep

1.查找關(guān)鍵日志grep

2.精簡日志內(nèi)容 sed

3.對記錄進(jìn)行排序sort

4.統(tǒng)計(jì)日志相關(guān)記錄數(shù) awk

5.日志規(guī)范化

6.一些容易遇到的問題

 

例子背景:

        后臺跑一個(gè)定時(shí)任務(wù),對指定時(shí)間段的訂單數(shù)據(jù)表中的每一條記錄進(jìn)行以此任務(wù)處理物赶。在日志中輸出:

        1.訂單id

        2.訂單處理狀態(tài)

        3.日志類別

準(zhǔn)備工具:sort, tail, less, uniqu,grep,sed,awk

示例日志:demo.log

[plain] view plaincopy

    2011-08-23 19:57:00,610 [] INFO  bo.CommodityCerOrderBO - =====>屬性訂正任務(wù)執(zhí)行開始|每頁讀取100條數(shù)據(jù)  
    2011-08-23 19:57:05,012 [] INFO  bo.CommodityCerOrderBO - 當(dāng)前正在處理頁數(shù):1  
    2011-08-23 19:57:30,688 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳過  
    2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104  
    2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id尚骄,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105  
    2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id块差,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107  
    2011-08-23 19:57:32,782 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids成功保存為0|100104|0|100105|100107  
    2011-08-23 19:57:32,782 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids不含0跳過  
    2011-08-23 19:57:32,805 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104  
    2011-08-23 19:57:33,828 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id倔丈,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107  
    2011-08-23 19:57:33,838 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id憨闰,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:46  
    2011-08-23 19:57:34,850 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100106  
    2011-08-23 19:57:35,860 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id需五,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105  
    2011-08-23 19:57:36,871 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id鹉动,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3  
    2011-08-23 19:57:36,884 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3  
    2011-08-23 19:57:36,891 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids成功保存為6|100104|0|0|100107|46|100106|100105|3|3  
    2011-08-23 19:57:36,891 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:attr_ids不含0跳過  
    2011-08-23 19:57:36,928 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id宏邮,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3  
    2011-08-23 19:57:36,942 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id泽示,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104  
    2011-08-23 19:57:36,955 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id缸血,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105  
    2011-08-23 19:57:36,969 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107  
    2011-08-23 19:57:36,980 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id械筛,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:46  
    2011-08-23 19:57:36,992 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id捎泻,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100106  
    2011-08-23 19:57:37,011 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3  


0.一些最基礎(chǔ)的日志查看命令

最簡單的日志查看命令就是瀏覽日志文件了埋哟,一般會(huì)從有限瀏覽文件末尾的

[plain] view plaincopy

    tail -400f demo.log #監(jiān)控最后400行日志文件的變化 等價(jià)與 tail -n 400 -f (-f參數(shù)是實(shí)時(shí))  
    less demo.log #查看日志文件笆豁,支持上下滾屏,查找功能  
    uniq -c demo.log  #標(biāo)記該行重復(fù)的數(shù)量赤赊,不重復(fù)值為1  

以上命令具體使用詳見本機(jī)man手冊


1.查找關(guān)鍵日志記錄 grep

瀏覽了日志文件后你會(huì)發(fā)現(xiàn)闯狱,日志文件成千上萬行,怎么能找到我要找的內(nèi)容呢抛计。這時(shí)候哄孤,就可已用grep來進(jìn)行日志的關(guān)鍵行提取了。

grep 簡單使用

規(guī)則:grep [選項(xiàng)]...模式 [文件]...    (模式是正則表達(dá)式)


例子1:

[plain] view plaincopy

    grep 'INFO' demo.log     #在文件demo.log中查找所有包行INFO的行  

輸出:
2011-08-23 19:57:00,610 [] INFO  bo.CommodityCerOrderBO - =====>屬性訂正任務(wù)執(zhí)行開始|每頁讀取100條數(shù)據(jù)
2011-08-23 19:57:05,012 [] INFO  bo.CommodityCerOrderBO - 當(dāng)前正在處理頁數(shù):1
2011-08-23 19:57:30,688 [] INFO  bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳過
...(略)


例子2:

[plain] view plaincopy

    grep -o 'order-fix.curr_id:[0?9]\+' demo.log    #-o選項(xiàng)只提取order-fix.curr_id:xxx的內(nèi)容(而不是一整行)吹截,并輸出到屏幕上  

輸出:
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10226
...(略)

例子3:
[plain] view plaincopy

    grep -c 'ERROR' demo.log   #輸出文件demo.log中查找所有包行ERROR的行的數(shù)量  

輸出:17

例子4:
[plain] view plaincopy

    grep -v 'ERROR' demo.log   #查找不含"ERROR"的行  

輸出:(功能和grep 'INFO' demo.log 命令一樣瘦陈,輸出略)


grep 用法小結(jié)(轉(zhuǎn)自網(wǎng)絡(luò)圖片):請點(diǎn)擊直接查看大圖

詳細(xì)用法請man之

2.精簡日志內(nèi)容 sed

        從n多行的日志文件中提取到一定數(shù)量的行后,可能你還會(huì)覺得有些功能不夠饭弓,比如你每行并不需要有哪個(gè)類拋出的描述双饥,比如你不需要日志時(shí)間媒抠,或者要把時(shí)間格式換個(gè)形式展示等等弟断,這時(shí)候你就可以通過sed的替換命令來進(jìn)行對日志文件提取具體內(nèi)容了。
        如果把grep比作過濾器趴生,那sed就是個(gè)修改器了阀趴。 

sed簡單用法:

[plain] view plaincopy

    sed [-n][-e] '命令' 文件        #-n選項(xiàng)是默認(rèn)不輸出信息,除非使用了p命令或者是s命令的p標(biāo)志符苍匆;-e是表明空格后面接的是一個(gè)命令  
    sed [-n] -f 腳本 文件           #這個(gè)用法是把命令寫在腳本里  

?'命令'的格式: [地址1[,地址2]][!] 指令 [參數(shù)]
                       ? 地址的格式:用行號標(biāo)識(1 表明匹配第一行)刘急,或者用正則表達(dá)式匹配('^INFO'表明該地址匹配以INFO打頭的行)   
                       ? 指令的例子:p打印指令,s替換指令浸踩,d刪除指令等等(以下表格摘自abs的sed小冊子):

操作符 名字  效果
[地址范圍]/p    打印  打印[指定的地址范圍]
[地址范圍]/d    刪除  刪除[指定的地址范圍]
s/pattern1/pattern2/    替換  將指定行中, 將第一個(gè)匹配到的pattern1, 替換為pattern2.
[地址范圍]/s/pattern1/pattern2/ 替換  在地址范圍指定的每一行中, 將第一個(gè)匹配到的pattern1, 替換為pattern2.
[地址范圍]/y/pattern1/pattern2/ transform   在地址范圍指定的每一行中, 將pattern1中的每個(gè)匹配到pattern2的字符都使用pattern2的相應(yīng)字符作替換. (等價(jià)于tr命令)
g   全局  在每個(gè)匹配的輸入行中, 將每個(gè)模式匹配都作相應(yīng)的操作. (譯者注: 不只局限于第一個(gè)匹配)
小結(jié):sed就是遍歷對于輸入文件的每一行叔汁,如果該行匹配地址1,地址2的范圍之內(nèi)检碗,那么就對這一行執(zhí)行命令据块。

例1:(摘自abs的sed小冊子)

8d  刪除輸入的第8行.
/^$/d   刪除所有空行.
1,/^$/d 從輸入的開頭一直刪除到第1個(gè)空行(第一個(gè)空行也刪除掉).
/Jones/p    只打印那些包含"Jones"的行(使用-n選項(xiàng)).
s/Windows/Linux/    在每個(gè)輸入行中, 將第一個(gè)出現(xiàn)的"Windows"實(shí)例替換為"Linux".
s/BSOD/stability/g  在每個(gè)輸入行中, 將所有"BSOD"都替換為"stability".
s/ *$// 刪除掉每行結(jié)尾的所有空格.
s/00*/0/g   將所有連續(xù)出現(xiàn)的0都壓縮成單個(gè)的0.
/GUI/d  刪除掉所有包含"GUI"的行.
s/GUI//g    將所有"GUI"都刪除掉, 并保持剩余部分的完整性.

看完基本用法,讓我們結(jié)合demo.log來具體應(yīng)用下:

例2:輸出demo.log中的某個(gè)日期中的ERROR的行

來具體應(yīng)用下:

[plain] view plaincopy

    sed -n '/^2011-08-23.*ERROR/p' demolog.log  

輸出:

2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id折剃,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id另假,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105
2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107

例3:提取demo.log中的日期怕犁,日志級別边篮,訂單id和狀態(tài)己莺。

[plain] view plaincopy

    sed -f demo.sed2 demo.log  

[plain] view plaincopy

    #n                                #這一行用法和命令中的-n一樣意思,就是默認(rèn)不輸出  
    #demo.sed2  
      
    #下面的一行是替換指令戈轿,就是把19位長的日期和INFO/ERROR,id,和后面的一截提取出來凌受,然后用@分割符把這4個(gè)字段重新按順序組合  
    s/^[?0?9]{19}.*INFO∥ERROR .*order-fix.curr_id:[0?9]\+,.?$/\1@\3@\2@\4/p   

輸出:
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:30@10117@ERROR@status:添加屬性id,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加屬性id思杯,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加屬性id胁艰,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存為0|100104|0|100105|100107
...略


sed詳細(xì)用法可以參考《sed 與 awk》(第二版), 或者man之

或者點(diǎn)擊下面這個(gè)參考鏈接http://www.reddragonfly.org/abscn/x17814.html


3.對記錄進(jìn)行排序 sort

        經(jīng)過了日志文件的精煉后,我們可能不想對日志進(jìn)行時(shí)間排序智蝠,這時(shí)候我們就可以用sort進(jìn)行排序腾么。

基本使用

 sort [options] [file...]

對于demo.log,經(jīng)過了上面的sed提取后杈湾,我希望先用id進(jìn)行排序解虱,然后再用日志級別倒序進(jìn)行排序,最后才是日期排序

[plain] view plaincopy

    #排序功能 -t表示用@作為分割符漆撞,-k表示用分割出來的第幾個(gè)域排序(不要漏掉后面的,2/,3/,1殴泰,詳細(xì)意思看下面的參考鏈接,這里不做詳述)  
    sed -f test.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1                  #n為按數(shù)字排序浮驳,r為倒序  

輸出:

2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存為0|100104|0|100105|100107
2011-08-23 19:57:30@10117@ERROR@status:添加屬性id悍汛,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加屬性id,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加屬性id至会,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107
2011-08-23 19:57:36@10222@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id离咐,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id奉件,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100106
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id宵蛀,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id县貌,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:46
2011-08-23 19:57:37@10222@ERROR@status:添加屬性id术陶,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3
2011-08-23 19:57:32@10226@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:36@10226@INFO@status:attr_ids成功保存為6|100104|0|0|100107|46|100106|100105|3|3
2011-08-23 19:57:32@10226@ERROR@status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
2011-08-23 19:57:33@10226@ERROR@status:添加屬性id煤痕,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107
2011-08-23 19:57:33@10226@ERROR@status:添加屬性id梧宫,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:46
2011-08-23 19:57:34@10226@ERROR@status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100106
2011-08-23 19:57:35@10226@ERROR@status:添加屬性id摆碉,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105
2011-08-23 19:57:36@10226@ERROR@status:添加屬性id塘匣,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3
2011-08-23 19:57:36@10226@ERROR@status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:3

詳盡手冊http://ss64.com/bash/sort.html


4.統(tǒng)計(jì)日志相關(guān)記錄數(shù) awk

現(xiàn)在日志已經(jīng)比較清晰了兆解,但是如果我想對不同日志進(jìn)行統(tǒng)計(jì)怎么辦馆铁,比如我要統(tǒng)計(jì)所有ERROR的日志記錄書,或者要統(tǒng)計(jì)每個(gè)訂單有多少個(gè)ERROR锅睛?這就需要我們的awk幫忙了埠巨。

awk簡單使用:

[plain] view plaincopy

    awk [-v 變量名=變量值] [-Fre] [--] '模式 { 語句 }' 變量名=變量值 文件名  
    awk [-v 變量名=變量值] [-Fre] -f 腳本文件 [--] 變量名=變量值 文件名  

和sed一樣历谍,awk也支持2中方式調(diào)用,一種是把a(bǔ)wk腳本直接在命令行寫入辣垒,第二種是把a(bǔ)wk寫在文件中在命令行中調(diào)用望侈。

awk處理方式也與sed類似,對文件中的每一個(gè)輸入行進(jìn)行處理勋桶,每個(gè)處理首先判斷是否是模式中匹配的行脱衙,是的話就具體執(zhí)行相應(yīng)的語句。
不同的是例驹,awk側(cè)重與對每一行的列進(jìn)行處理捐韩,并且,awk腳本和c語言類似也擁有變量鹃锈,條件判斷荤胁,循環(huán)等復(fù)雜語句,所以這里只能簡單介紹一下基本應(yīng)用屎债,詳細(xì)的請查看后面給出的相關(guān)鏈接仅政。

而且,awk在處理所有行前和處理完行后各有BEGIN和END語句做預(yù)處理和后置處理盆驹。

例子1:打印日志中的第2圆丹,3列

[plain] view plaincopy

    awk 'BEGIN{FS="@"} {print $2,$3}' demo.log_after_sort   #BEGIN中預(yù)處理的是,把@號作為行的列分割符,把分割后的行的第2躯喇,3列輸出  

輸出:(對于從sort得出的結(jié)果作為輸入)
10117 INFO
10117 INFO
10117 ERROR
10117 ERROR
10117 ERROR
10222 INFO
...略

例子2. 統(tǒng)計(jì)日志中INFO辫封,ERROR出現(xiàn)的總數(shù),以及總記錄數(shù)

[plain] view plaincopy

    #下面的例子是作為命令行輸入的,利用單引號作為換行標(biāo)記玖瘸,這樣就不用另外把腳本寫進(jìn)文件調(diào)用了  
    awk '  
    BEGIN {  
      FS="@"  
    }  
      
    {  
      if ($3 == "INFO") {info_count++}  
      if ($3 == "ERROR") {error_count++}  
      
    }  
      
    END {  
      print "order total count:"NR           #NR是awk內(nèi)置變量秸讹,是遍歷的當(dāng)前行號檀咙,到了END區(qū)域自然行號就等于總數(shù)了  
      printf("INFO count:%d ERROR count:%d\n",info_count,error_count)  
    } ' demo.log_after_sort  

輸出:

order total count:22
INFO count:5 ERROR count:17

例子3. 對指定時(shí)間范圍內(nèi)的日志進(jìn)行統(tǒng)計(jì)雅倒,包括輸出INFO,ERROR總數(shù)弧可,記錄總數(shù)蔑匣,每個(gè)訂單記錄分類統(tǒng)計(jì)

下面的例子綜合了前面sed和sort

[plain] view plaincopy

    sed -f demo.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1 | awk -f demo.awk  

[plain] view plaincopy

    #demo.awk  
    BEGIN {  
      FS="@"  
      stime="2011-08-23 19:57:31"  
      etime="2011-08-23 19:57:37"  
    }  
      
    $1 > stime && $1 < etime {  
      if ($3 == "INFO") {info_count++}  
      if ($3 == "ERROR") {error_count++}  
      
      ++total  
      
      status[$2]=status[$2]"\t"$1"\t"$3"\t"$4"\n"  
      
    }  
      
    END {  
      for(i in status){  
          printf("id:%s:\n%s\n",i,status[i])  
      }  
      
      print "order total count:"total  
      printf("INFO count:%d ERROR count:%d\n",info_count,error_count)  
    } <span style="font-size:18px;"><strong>  
    </strong></span>  

輸出:

id:10117:

    2011-08-23 19:57:32 INFO  status:attr_ids成功保存為0|100104|0|100105|100107
    2011-08-23 19:57:32 ERROR  status:添加屬性id,但由于認(rèn)證分類參數(shù)有誤默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107

id:10226:

    2011-08-23 19:57:32 INFO  status:attr_ids不含0跳過
    2011-08-23 19:57:32 ERROR  status:添加屬性id棕诵,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100104
    2011-08-23 19:57:33 ERROR  status:添加屬性id裁良,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100107
    2011-08-23 19:57:33 ERROR  status:添加屬性id,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:46
    2011-08-23 19:57:34 ERROR  status:添加屬性id校套,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100106
    2011-08-23 19:57:35 ERROR  status:添加屬性id价脾,但由于沒有屬性在該分類下默認(rèn)取匹配屬性名稱的第一個(gè)屬性id:100105


#這個(gè)例子只是舉例說明awk的統(tǒng)計(jì)用法,實(shí)際運(yùn)用中可能會(huì)統(tǒng)計(jì)超時(shí)的次數(shù)笛匙,頁面訪問次數(shù)等侨把。


awk相關(guān)資料:

《sed 與 awk》(第二版)

  awk腦圖


補(bǔ)充:

其他實(shí)踐時(shí)例子:

1. 在本地分支把代碼修改從一個(gè)分支復(fù)制到另一個(gè)分支(例子的b1022st.txt是一個(gè)記錄了文件新增或修改的變化的文件路徑名)

[plain] view plaincopy

    awk 'BEGIN{FS="b1022-scm/"} {system("cp -rf b1022-scm/"$2" b1022-lpscm/"$2);}' /home/nizen/b1022st.txt  

通過awk和其system命令結(jié)合犀变,這樣就把文件從b1022-scm復(fù)制到b1022-lpscm下


2.內(nèi)置函數(shù) http://www.cnblogs.com/chengmo/archive/2010/10/08/1845913.html
3.內(nèi)建變量 http://www.linuxsong.org/2010/09/awk-built-in-variable/
4.shell變量傳遞 http://www.51testing.com/?uid-225738-action-viewspace-itemid-246383
5.awk統(tǒng)計(jì)某個(gè)開始-結(jié)束范圍內(nèi)的關(guān)鍵字累加總數(shù):
[java] view plaincopy

    BEGIN {  
      running=0  
      count=0  
      startRow="begin =====>" id            #id,nextId是通過-v 參數(shù)從外部傳入  
      endRow="begin =====>" nextId  
    }  
      
    $0 ~ startRow{    # ~是匹配運(yùn)算符,判斷$0是否滿足startRow正則表達(dá)式  
      running = 1  
    #  printf("start\n")  
    }  
      
    $0 ~ endRow {  
      running = 0  
    #  printf("end\n")  
    }  
      
    {  
      if(running==1) {      # 僅在startRow 和 endRow 范圍內(nèi)統(tǒng)計(jì)  
        if($0 ~ "it show") {  
    #        printf($0 "\n")  
            str=$0  
            sub(/^.*show times:/, "", str)  
            sub(/ .*$/, "", str)  
            printf(str "\n")  
            count = count + str  
        }  
      }  
    }  
      
    END {  
      printf("showTimeCount:"+count)  
    }  

6. printf "10ms occur:%.2lf%%\n",t10/total*100 #輸出百分比數(shù)據(jù)秋柄,精確到百分位后2位


5.日志規(guī)范化

從前面可以看出获枝,日志文件為了要讓后續(xù)工具能夠?qū)锩娴膬?nèi)容進(jìn)行提取和處理,就必須要讓日志文件規(guī)范的輸出骇笔。

個(gè)人想到有幾個(gè)點(diǎn)可以規(guī)范:

1.記錄日志時(shí)候可以寫入一些特殊的文本語句省店,一遍與工具的檢索和處理。

2.記錄日志最好不要用中文笨触,因?yàn)樵诓煌Z言環(huán)境下對日志的處理可能因?yàn)榫幋a不同導(dǎo)致沒法處理日志懦傍。

后面再貼下淘寶中找到的一些打印日志的建議:

    正常情況下應(yīng)該返回true, 卻返回false的, 反正就是你在對返回值進(jìn)行檢查的時(shí)候, 如果不正常, log一下
    出現(xiàn)異常的地方, 以前認(rèn)為hsf.log會(huì)幫我們記下所有的異常, 但是這個(gè)也不一定可靠, 所以還得我們自己記一下
    日志必須包含上下文信息
    如果出于統(tǒng)計(jì)的需要, 可打可不打
    在完成代碼之后, 查看一下整個(gè)代碼結(jié)構(gòu), 在一些關(guān)鍵的點(diǎn), 加上日志, 正常的info, 少數(shù)情況出現(xiàn)的warning, 異常情況的error或者warning
    打印的日志內(nèi)容要容易查詢, 以前我比較傾向于打中文日志, 雖然易讀, 但是中文在linux下的搜索統(tǒng)計(jì)稍微有些麻煩,所以如果能加上英文標(biāo)識(比如說用于唯一標(biāo)識的前綴), 能識別不同日志, 這個(gè)對定位也是非常有好處的.


6.一些容易遇到的問題

a.處理中文出現(xiàn)亂碼

這個(gè)主要是因?yàn)槟愕膌inux locale的配置,與編輯文件的語言環(huán)境芦劣,還有你登錄ssh客戶端的編碼規(guī)則有關(guān)谎脯,所以最好還是不用中文記錄日志。

b.正則表達(dá)式不同工具的區(qū)別

這個(gè)主要是因?yàn)椴煌ぞ叩恼齽t表達(dá)式定義的元字符不同持寄,網(wǎng)上有總結(jié)的源梭,可點(diǎn)擊正則迷霧參考

OO后記:

目前只是簡單介紹了grep,sed,sort,awk的幾個(gè)簡單應(yīng)用,實(shí)際上的日志監(jiān)控回根據(jù)不同的情景進(jìn)行不同的處理稍味。比如需要對調(diào)用的耗時(shí)進(jìn)行統(tǒng)計(jì)(平均時(shí)間或者超時(shí)記錄)废麻,對訪問量進(jìn)行統(tǒng)計(jì),但是基本原理都和本文例子出發(fā)點(diǎn)一致模庐。本文一方面是為了記錄下學(xué)習(xí)過程中積累的東西烛愧,另一方面為了拋磚引玉引起大家對日志記錄的關(guān)注。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掂碱,一起剝皮案震驚了整個(gè)濱河市怜姿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疼燥,老刑警劉巖沧卢,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異醉者,居然都是意外死亡但狭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門撬即,熙熙樓的掌柜王于貴愁眉苦臉地迎上來立磁,“玉大人,你說我怎么就攤上這事剥槐〕纾” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵粒竖,是天一觀的道長颅崩。 經(jīng)常有香客問我绍刮,道長,這世上最難降的妖魔是什么挨摸? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任孩革,我火速辦了婚禮,結(jié)果婚禮上得运,老公的妹妹穿的比我還像新娘膝蜈。我一直安慰自己,他們只是感情好熔掺,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布饱搏。 她就那樣靜靜地躺著,像睡著了一般置逻。 火紅的嫁衣襯著肌膚如雪推沸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天券坞,我揣著相機(jī)與錄音鬓催,去河邊找鬼。 笑死恨锚,一個(gè)胖子當(dāng)著我的面吹牛宇驾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猴伶,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼课舍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了他挎?” 一聲冷哼從身側(cè)響起筝尾,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎办桨,沒想到半個(gè)月后筹淫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崔挖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年贸街,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狸相。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖捐川,靈堂內(nèi)的尸體忽然破棺而出脓鹃,到底是詐尸還是另有隱情,我是刑警寧澤古沥,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布瘸右,位于F島的核電站娇跟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏太颤。R本人自食惡果不足惜苞俘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龄章。 院中可真熱鬧吃谣,春花似錦、人聲如沸做裙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锚贱。三九已至仔戈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拧廊,已是汗流浹背监徘。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吧碾,地道東北人耐量。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像滤港,于是被迫代替她去往敵國和親廊蜒。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容