0924 介紹一個既常見又強大的linux指令給大家——grep指令
引言
工作中,經常要檢視程式的日誌,最簡單粗暴的方式就是使用工具xftp5。把日誌檔案拉到本地,然後用文字編輯器如nodepad++進行檢視。在剛進公司的時候,每次要檢視日誌,都是使用這種方式。
但是,在與其他專案經理接觸的過程中,我發現使用linux指令在命令列中直接檢視日誌是一個更好的選擇。首先,逼格更高,其次,效率更高。
如果能很好的使用grep命令,效率真的會很高。
效率更高,怎麼說?
舉個例子
舉個例子,假如我要檢視最近幾次的BusinessException,那麼我可以通過xftp5下載最新的那份日誌檔案,拉到本地,然後通過文字編輯器,拉到最後一行,在搜尋框中輸入關鍵字“BusinessException”然後向前搜尋。如此檢視最近幾次的BusinessException。這還可以忍受。
再舉一個例子,假如我要檢視昨天發生過的所有的BusinessException(ps:日誌檔案按照日期劃分,並且每30m又劃分為1個小的檔案,而通常一天下來,假設日誌檔案一共300MB),那麼就有10段日誌檔案。如果這時要檢視這一天發生過的BusinessException,那麼就得把這10份日誌檔案下載下來,然後一個一個檔案的去遍歷,再個每個具體的檔案中去搜索。這樣依然可行,只是效率會很低很低。其實一開始我也是使用這種方式,偶爾一兩次還能接受,但是一天四五次,七八次我就無法忍受了,時間都花在了查日誌上,不是在浪費時間嗎???
而其實使用grep指令,一行語句解決上面的問題。
真例項子
上面說的例子可能你會覺得只是為了說明問題無中生有的一個操作。然而在工作中,還真的是有類似的操作。譬如,使用者向客服反饋說自己上星期5在操作app的時候綁卡一直失敗,提示說“綁卡失敗,請稍後重試”。這時你就得檢視日誌排查問題了。就像前面說的,一天下來,日誌檔案共幾百M甚至更多,以30M來分割,那麼一天的日誌檔案就有十幾份。如果這時還使用文字編輯器notepad++去定位就會顯得很被動了。比方說,你得去問清楚,使用者是在什麼時候操作發生這個問題的。客戶如果說:“使用者反饋是在上星期5上午,具體時間他記不太清了”。那麼這個時候,你就不得不去檢視時間截至至上午的每一份日誌檔案,然後再一份一份的通過正則表示式加關鍵字如“userId=13246800000.*?綁卡失敗,請稍後重試”(假設使用者的賬號是13246800000)去搜索。如果你查完時間在上午的每一份日誌檔案,依然沒有定位有問題。你可能會生氣會抱怨:“使用者是在耍我們嗎??”但是如果你要確認使用者是否在耍你,你還得把上午除外的其他日誌都檢查過並且確認確實沒找到,你才能確定是使用者記錯了時間。你還可能會抱怨:“為什麼當時出問題的時候不來反饋,而要等隔了幾天才來反饋問題?要是一出現這個問題就馬上反饋,那我只要檢視最新的日誌檔案,一下就能定位問題了”。然而這種抱怨並沒什麼用,也不切實際。
好吧,以上說的就是我,一個真實的例子之一!!!之一!!!
如果使用grep指令,會有多簡單呢?grep指令支援多檔案搜尋!grep指令可以把上面我手動的許多操作交給機器,讓機器來完成。比如我只要使用這麼一個指令,就能找到使用者說的“綁卡失敗,請稍後重試”的日誌:
這裡上星期5指的是2018-09-21號。 這一天的日誌檔名有如:
theLog.2018-09-21.0.log、
theLog.2018-09-21.1.log、
theLog.2018-09-21.2.log
...
theLog.2018-09-21.15.log
grep指令為:
grep -a -r -E 'userId=13246800000.*?綁卡失敗,請稍後重試' ./theLog.2018-09-21*
這樣就能匹配出以theLog.2018-09-21開頭的檔名且滿足正則表示式"userId=13246800000.*?綁卡失敗,請稍後重試"的關鍵字所在的那一行的資訊。
如果查詢出來的結果為空,說明這一天這個使用者都沒出現過這個綁卡失敗的問題。這時我們就可以懷疑是使用者記錯的日期,然而我們並不需要被動的找客服,讓客服詢問使用者操作的日期到底是哪一天,畢竟使用者可能真的記不起了,他只記得是上星期,也可能是上上星期。這時我們只要簡單的改變一下grep指令中的日期:
grep -a -r -E 'userId=13246800000.*?綁卡失敗,請稍後重試' ./theLog.2018-09-22*
或者
grep -a -r -E 'userId=13246800000.*?綁卡失敗,請稍後重試' ./theLog.2018-09-20*
就能一下子查詢使用者在20號和22號有沒有出現過這個問題。如果依然查不到,可以更粗暴的查詢9月份的所有日誌檔案:
grep -a -r -E 'userId=13246800000.*?綁卡失敗,請稍後重試' ./theLog.2018-09*
而grep指令的效率非常非常的高,在使用notepad++對單獨的一個檔案進行搜尋時,經常會出現卡頓,而使用grep指令,則完全沒感覺,一下子就查詢完畢了。
最後
grep指令我常用到的引數有 -a,-r,-E,-F,-B,-A,-C,-v。
-a 表示不要忽略2進位制資料,每次使用grep指令,都會帶上這個引數:
例子:
grep -a '綁卡失敗,請稍後重試' ./theLog.log
-r 表示對目錄也進行遍歷,如果沒加-r,當查詢範圍是目錄時,會返回xx Is a directory:
例子(查詢範圍是當前目錄):
grep -a -r '綁卡失敗,請稍後重試' ./
-E 表示關鍵字中使用正則表示式
例子(關鍵字中使用正則表示式,關鍵字資訊為:userId=1324680開頭,且包含綁卡失敗,請稍後重試):
grep -a -E 'userId=132480.*?綁卡失敗,請稍後重試'
-F 與-E相反,表示關鍵字中不使用正則表示式
例子(列印含有8個星號的記錄,這裡的星號不是正則表示式中的星號,它僅僅表示星號):
grep -a -F '********' ./theLog.log
-B 的B表示before,用法如 -B 1,表示列印關鍵字所在行以及該行的前一行
例子:
grep -a -r -B 1 '綁卡失敗' ./theLog.log
-A 的A表示after,用法如 - A 3,表示列印關鍵字所在行以及該行的後面三行
例子:
grep -a -r -A 3 '綁卡失敗' ./theLog.log
例子(-B和-A一起用):
grep -a- r -B 3 -A 1 '綁卡失敗' ./theLog.log
-C 的單詞含義不知道是什麼,但是其作用類似上面兩個,用法如 -C 1,表示列印關鍵字所在行以及前後各一行。
例子:
grep -a -r -C 10 '綁卡失敗' ./theLog.log
-v 的v表示invert-match,表示反轉查詢,即列印不含指定關鍵字的所在行。
例子(匹配不含關鍵字“====”的記錄):
grep -a -r -v '====' ./theLog.log
grep指令真的很強大,這裡不深入的去介紹,只是通過例子介紹一下,讓大家知道這個命令,也建議大家嘗試著去用指令查詢替代文字編輯器查詢。當然,要想讓grep指令更好的發揮作用,程式的日誌記錄很重要,如果程式日誌都做得太爛,那即使使用grep指令,也不會有過大的作用。
最後的最後,我建議學習linux指令,第一步先是去明白該指令名字的全稱,這樣才能更好的記住該指令。
如grep,是global search regular expression and print out the line,這樣就能很直觀的明白grep指令的作用:全面搜尋正則表示式並打印出所在行。
又如lsof指令,一開始我總是記成losf,但是知道該指令的全稱後,就不會再混淆了。lsof:list open file。即ls是list的縮寫,o是open的縮寫,f是file的縮寫。這樣一來,一旦想不起該指令,想想其含義,其單詞,自然也就知道是lsof而不是losf了。
哈哈,這是一個過來人的學習建議。希望能幫到有需要的人。