Linux日志終極指南
Linux 日志分析
雖然提取的時候,不總是和你想的一樣簡單,但是日志中有大量信息在等著你。在這部分,我們會講一些基本分析示例,你可以馬上拿來處理你的日志(只是搜索里面有什么)。我們還會講一些高級分析方法,開始的時候可能要花時間來做配置,但會為以后省很多時間。你可以把高級分析的示例用在待解析的數據上,比如生成摘要計數,過濾字段值等。
首先我們會演示,你應該如何使用不同的工具在命令行進行日志分析;然后,演示一個日志管理工具,它能夠讓大多數乏味的工作變得自動化和高效。
使用 Grep 搜索
搜索文本是找到你想要的信息的最基本方法。搜索文本最常用的工具是 grep 。這個命令行工具,大多數 Linux 發行版上都有,它支持你用正則表達式來搜索日志。正則表達式是一種用專門語言寫成的語句,可用來識別匹配文本。最簡單的正則表達式是把你搜索的字符串加上引號。
正則表達式
這里有個例子,它在 Ubuntu 的認證日志里搜索 “user hoover”:
- $ GREP "USER HOOVER" /VAR/LOG/AUTH.LOG
- ACCEPTED PASSWORD FOR HOOVER FROM 10.0.2.2 PORT 4792 SSH2
- PAM_UNIX(SSHD:SESSION): SESSION OPENED FOR USER HOOVER BY (UID=0)
- PAM_UNIX(SSHD:SESSION): SESSION CLOSED FOR USER HOOVER
構造精確的正則表達式很難。例如,假設我們搜索一個數字,比如端口號“4792” ,它也可以匹配時間戳,URLs和其他不需要的數據。在下面針對 Ubuntu 的例子里,它匹配了 Apache 日志,但這并不是我們想要的。
- $ grep "4792" /var/log/auth.log
- Accepted password for hoover from 10.0.2.2 port 4792 ssh2
- 74.91.21.46 - - [31/Mar/2015:19:44:32 +0000] "GET /scripts/samples/search?q=4972HTTP/1.0" 404 545 "-" "-”
延伸搜索
另一個有用的技巧是你可以用grep 做延伸搜索。它會輸出匹配項的前幾行和后幾行內容。它可以幫你調試是什么導致了錯誤或問題。B 選項指定顯示匹配項前面的行數,A 選項指定顯示匹配項后面的行數。如下所示,我們看到,當有人以 admin 身份登陸失敗后, 反向映射也會失敗,這說明他們可能沒有有效的域名。這很可疑!
- $ grep -B 3 -A 2 'Invalid user' /var/log/auth.log
- Apr 28 17:06:20 ip-172-31-11-241 sshd[12545]: reverse mapping checking getaddrinfo for 216-19-2-8.commspeed.net[216.19.2.8] failed - POSSIBLE BREAK-IN ATTEMPT!
- Apr 28 17:06:20 ip-172-31-11-241 sshd[12545]: Received disconnect from 216.19.2.8: 11: Bye Bye [preauth]
- Apr 28 17:06:20 ip-172-31-11-241 sshd[12547]: <b>Invalid user</b>; admin from 216.19.2.8
- Apr 28 17:06:20 ip-172-31-11-241 sshd[12547]: input_userauth_request: invalid user admin [preauth]
- Apr 28 17:06:20 ip-172-31-11-241 sshd[12547]: Received disconnect from 216.19.2.8: 11: Bye Bye [preauth]
Tail命令
你也可以將 tail 和 grep 搭配起來使用,以獲取文件***幾行,或者跟蹤日志并實時打印。當你在進行交互式更改比如架設服務器或測試代碼更改的時候,非常有用。
- $ tail -f /var/log/auth.log | grep 'Invalid user'
- Apr 30 19:49:48 ip-172-31-11-241 sshd[6512]: Invalid user ubnt from 219.140.64.136
- Apr 30 19:49:49 ip-172-31-11-241 sshd[6514]: Invalid user; admin from 219.140.64.136
全面介紹 grep 和正則表達式超出了本文的范圍,Ryan 的教程里有更深入的介紹。
日志管理系統中有更高效更強大的搜索工具。它們通常對數據建立索引和并行查詢,因此你可以在數秒之內快速查詢高達 G 字節或 T 字節的日志。相比之下,用 grep ,可能要花幾分鐘,極端情況下會花費數小時。日志管理系統也像 Lucene (譯注:一個開源的全文檢索引擎工具包)一樣使用查詢語言 ,它為數字,字段等的搜索提供了簡單的語法。
用Cut,AWK 和 Grok 解析日志
命令行工具
Linux 提供了幾種文本解析和分析的命令行工具。如果你想快速解析少量的數據,它們很強大,但是處理大量數據要花很長時間。
Cut 命令
cut 命令可以從帶分隔符的日志中解析字段。分隔符是類似等號或逗號的字符,用來劃分字段或鍵值對。
比如說,我們想從這個日志中提取用戶名:
- pam_unix(su:auth): authentication failure; logname=hoover uid=1000 euid=0 tty=/dev/pts/0 ruser=hoover rhost= user=root
我們可以和下面一樣使用 cut 命令,獲取第八個等號后邊的文本。這是 Ubuntu 上的例子:
- $ grep "authentication failure" /var/log/auth.log | cut -d '=' -f 8
- root
- hoover
- root
- nagios
- nagios
AWK 命令
此外,你還可以用 awk,它擁有更強的解析字段的功能。它提供了一個腳本語言,讓你幾乎可以過濾出任何毫不相關的信息。
舉個例子,假設我們在 Ubuntu 上有如下的日志,我們想提取登陸失敗的用戶名:
- Mar 24 08:28:18 ip-172-31-11-241 sshd[32701]: input_userauth_request: invalid user guest [preauth]
下面是使用 awk 的例子。首先,用一個正則表達式 /sshd.*invalid user/ 匹配 sshd 無效用戶的那一行。然后使用 { print $9 } 打印第九個字段(默認的分隔符是空格)。這樣就輸出了用戶名。
- $ awk '/sshd.*invalid user/ { print $9 }' /var/log/auth.log
- guest
- admin
- info
- test
- ubnt
你可以從 Awk 用戶指南中獲取更多關于如何使用正則表達式和打印字段的信息。
日志管理系統
日志管理系統讓解析更容易并且讓用戶可以快速分析大量日志文件。它們可以自動解析標準日志格式,比如公共 Linux 日志或 web 服務日志。這會節省很多時間,因為你在定位系統問題的時候不用去想如何寫你的解析邏輯。
這里你可以看一個來自 sshd 的日志信息,解析出了遠程主機和用戶字段。這個截圖來自 Loggly,一個基于云計算的日志管理服務。
對非標準格式的日志,你也可以自定義解析規則。最常用的工具是 Grok,它用通用正則表達式庫把純文本解析成 JSON 格式。這是 Grok 的配置示例,用來解析 Logstash 的內核日志 :
- filter{
- grok {
- match => {"message" => "%{CISCOTIMESTAMP:timestamp} %{HOST:host} %{WORD:program}%{NOTSPACE} %{NOTSPACE}%{NUMBER:duration}%{NOTSPACE} %{GREEDYDATA:kernel_logs}"
- }
- }
這是用 Grok 解析后輸出的結果:
使用 Rsyslog 和 AWK 過濾
過濾是搜索特定的字段,而不是全部文本。這讓你的日志分析更精確,因為它會忽略其他不需要的日志信息。為了搜索一個字段值,你需要先解析你的日志或者至少有一種基于事件結構的搜索方法。
如何篩選出同一個應用的日志
通常,你只想看來自同一個應用的日志。如果你的應用總是把日志記錄在單個文件中,這樣很容易分析。如果你要從聚合或集中起來的日志里篩選出和某個程序相關的日志,會很復雜。這里有幾種解決的辦法。
用 Rsyslog 服務解析和過濾日志。這個例子是將 sshd 應用程序的日志寫入名為 sshd-messages 的文件中,然后丟棄事件,所以它不會在其他日志里重復出現。你可以把它加到你的 Rsyslog.conf 文件里試一下。
- :programname, isequal, “sshd” /var/log/sshd-messages
- &~
使用命令行工具比如 awk ,提取特定字段的值,比如取 sshd 用戶名。這是 Ubuntu 上的例子。
- $ awk '/sshd.*invalid user/ { print $9 }' /var/log/auth.log
- guestadmin
- info
- test
- ubnt
使用日志管理系統自動解析你的日志,然后點擊目標應用的名字進行過濾。這個截圖顯示了 syslog 的各個字段,在一個叫做 Loggly 的日志管理服務中。如圖中文氏圖所示,當前正在過濾 sshd 這個應用。
如何篩選出錯誤信息
最常見的事情是,人們想看到日志中的錯誤。不巧的是,默認的 syslog 配置不會直接輸出錯誤的級別,這使得錯誤信息很難被篩選。
這里有兩種方案來解決這個問題。首先,你可以修改 rsyslog 配置,讓它輸出級別到日志文件中,使得錯誤信息容易被讀取和搜索。在你的 Rsyslog 配置中你可以加一個pri-text 模版,如下所示:
- "<%pri-text%> : %timegenerated%,%HOSTNAME%,%syslogtag%,%msg%n"
這個例子的輸出如下,可以看到級別是 err。
- <authpriv.err> : Mar 11 18:18:00,hoover-VirtualBox,su[5026]:, pam_authenticate: Authentication failure
你可以用 awk 或grep 篩選出錯誤信息。這是 Ubuntu 下的例子,我們加了開始結束標志 . 和 > ,這樣它就只匹配這個字段。
- $ grep '.err>' /var/log/auth.log
- <authpriv.err> : Mar 11 18:18:00,hoover-VirtualBox,su[5026]:, pam_authenticate: Authentication failure
第二種選擇是使用日志管理系統。好的日志管理系統會自動解析 syslog 消息并提取出級別字段。只需點一下,就會按指定的級別篩選日志。
這是 Loggly 的截圖。顯示了 syslog 各個字段, Error 級別高亮顯示了,說明正在按級別 Error 過濾





































