如何使用Journalctl檢視並操作Systemd日誌

安全劍客發表於2019-04-08
作為最具吸引力的優勢, systemd 擁有強大的處理與系統日誌記錄功能。在使用其它工具時,日誌往往被分散在整套系統當中,由不同的守護程式及程式負責處理,這意味著我們很難跨越多種應用程式對其內容進行解讀。

如何使用Journalctl檢視並操作Systemd日誌如何使用Journalctl檢視並操作Systemd日誌
相比之下,systemd嘗試提供一套集中化管理方案,從而統一打理全部核心及使用者級程式的日誌資訊。這套系統能夠收集並管理日誌內容,而這也就是我們所熟知的journal。

Journal的實現歸功於journald守護程式,其負責處理由核心、initrd以及服務等產生的資訊。在今天的教程中,我們將探討如何使用journalctl工具,並在其幫助下訪問並操作journal內部的資料。

總體思路

Systemd journal的深層驅動力在於以集中方式管理對來自任意來源的日誌資訊。由於大部分引導程式都是由systemd程式處理的,因此我們有理由以標準化方式實現日誌的收集與訪問。其中jornald守護程式會收集全部來源的資料並將其以二進位制格式加以儲存,從而輕鬆實現動態操作。

這種作法能夠實現多種收益。通過單一工具與資料互動,管理員能夠以動態方式顯示日誌資料。另外,我們也可以輕鬆檢視歷史引導資料,或者將日誌條目同其它相關服務加以結合,從而 完成通訊問題除錯。

將日誌資料以二進位制形式儲存還意味著這些資料可根據需求隨時以二進位制輸出格式顯示。例如,大家可以通過標準syslog格式檢視日誌以實現日常管理,並在需要使用圖形服務時將各條目作為JSON物件交由圖形化服務處理。由於資料不會以純文字形式被寫入磁碟,因此我們無需進行任何格式轉換。

大家可以將systemd journal與現有syslog方案配合使用,也可利用其替代現有syslog功能,具體取決於實際需求。儘管systemd journal足以涵蓋大部分管理工作需求,但其同時也能夠補充現有日誌記錄機制。例如,大家可以建立一套集中式syslog伺服器,從而對來自多臺伺服器的資料進行編譯;或者,我們也能夠利用systemd journal將來自多項服務的日誌彙總在單一系統當中。

設定系統時間

使用二進位制journal的一大好處在於,它能夠以UTC或者本地時間顯示日誌記錄。在預設情況下,systemd會以本地時間顯示結果。

有鑑於此,在我們開始使用journal之前,首先要確保時區得到正確設定。Systemd套件中還提供一款timedatectl工具,專門用於解決此類問題。
首先,利用list-timezones選項檢視可用時區:

timedatectl list-timezones

結果將列出系統上可用的全部時區。而後選擇與伺服器所在地相匹配的專案,並使用set-timezone選項加以設定:

sudo timedatectl set-timezone zone

為了確保我們的裝置使用正確的時間,可單獨使用timedatectl 命令 或者新增 status 選項。顯示結果如下:

timedatectl status
Local time: Thu 2015-02-05 14:08:06 EST
Universal time: Thu 2015-02-05 19:08:06 UTC
    RTC time: Thu 2015-02-05 19:08:06
   Time zone: America/New_York (EST, -0500)
 NTP enabled: no
NTP synchronized: no
RTC in local TZ: no
  DST active: n/a

第一行所示應為正確時間。

基礎日誌檢視

要檢視journald守護程式收集到的日誌,可使用journalctl 命令

在單獨使用時,系統中的每個journal條目都會被顯示在單一pager中供我們瀏覽。條目時間越早,排列越靠前:

journalctl
-- Logs begin at Tue 2015-02-03 21:48:52 UTC, end at Tue 2015-02-03 22:29:38 UTC. --
Feb 03 21:48:52 localhost.localdomain systemd-journal[243]: Runtime journal is using 6.2M (max allowed 49.
Feb 03 21:48:52 localhost.localdomain systemd-journal[243]: Runtime journal is using 6.2M (max allowed 49.
Feb 03 21:48:52 localhost.localdomain systemd-journald[139]: Received SIGTERM from PID 1 (systemd).
Feb 03 21:48:52 localhost.localdomain kernel: audit: type=1404 audit(1423000132.274:2): enforcing=1 old_en
Feb 03 21:48:52 localhost.localdomain kernel: SELinux: 2048 avtab hash slots, 104131 rules.
Feb 03 21:48:52 localhost.localdomain kernel: SELinux: 2048 avtab hash slots, 104131 rules.
Feb 03 21:48:52 localhost.localdomain kernel: input: ImExPS/2 Generic Explorer Mouse as /devices/platform/
Feb 03 21:48:52 localhost.localdomain kernel: SELinux:  8 users, 102 roles, 4976 types, 294 bools, 1 sens,
Feb 03 21:48:52 localhost.localdomain kernel: SELinux:  83 classes, 104131 rules
. . .

大家可以一頁頁進行翻看,不過如果系統執行時間較長,那麼systemd中的日誌也將成千上萬,這也證明了journal資料庫中可觀的資料量。

其格式與標準的syslog日誌非常相似。然而,其收集資料的來源較syslog要豐富得多。其中包含有來自先前引導程式、核心、initrd以及應用程式標準錯誤與輸出的日誌。這一切都可在journal中檢視到。

大家可能還注意到,全部時間戳都以本地時間為準。由於已經為系統正確設定了本地時間,所以顯示的時間戳也都準確無誤。

如果大家希望以UTC顯示時間戳,則可使用–utc標記:

journalctl --utc
按時間進行journal過濾

瀏覽大量資料當然有其作用,但資訊量過於龐大則會讓我們很難甚至根本不可能找到真正重要的內容。因此,journalctl提供了極為關鍵的過濾選項。

顯示當前引導程式下的日誌

其中最常用的就是-b標記了,其將顯示全部最近一次重新引導後收集到的journal條目。

journalctl -b

通過這種方式,我們能夠識別並管理源自當前環境下的資訊。
如果不使用這項功能,而且顯示的引導數量超過一天,那麼journalctl會在在系統關閉處插入說明:

. . .
-- Reboot --
. . .

這種方式能夠幫助我們有效區分來自不同引導會話的資訊。

過往引導記錄

大家通常只需要檢視當前引導環境下的資訊,但有時候檢視過往引導記錄也非常必要。Journal能夠儲存大量過往引導資訊,從而允許journalctl輕鬆顯示相關內容。

有些版本會在預設情況下儲存過往引導資訊,而有些則預設禁用這項功能。要啟用此功能,可以使用以下功能以建立用於儲存journal資訊的目錄:

sudo mkdir -p /var/log/journal

或者直接編輯journal配置檔案:

sudo nano /etc/systemd/journald.conf

在[Journal]區段下將Storage=選項設定為“persistent”以啟用持久記錄:

/etc/systemd/journald.conf
. . .
[Journal]
Storage=persistent

當啟用儲存過往引導資訊功能後,journalctl會提供額外命令以幫助大家將各引導記錄作為獨立單元操作。要檢視Journald中已經記錄的引導資訊,可使用–list-boots選項:

journalctl --list-boots
-2 caf0524a1d394ce0bdbcff75b94444fe Tue 2015-02-03 21:48:52 UTC—Tue 2015-02-03 22:17:00 UTC
-1 13883d180dc0420db0abcb5fa26d6198 Tue 2015-02-03 22:17:03 UTC—Tue 2015-02-03 22:19:08 UTC
 0 bed718b17a73415fade0e4e7f4bea609 Tue 2015-02-03 22:19:12 UTC—Tue 2015-02-03 23:01:01 UTC

這裡每次引導都將顯示為一行。第一列可用於在journalctl中引用該次引導。如果大家需要更為準確的引用方式,則可在第二列中找到引導ID。末尾記錄的兩次時間為當次引導的開始與結束時間。

要顯示這些引導中的具體資訊,則可使用第一或者第二列提供的資訊。

例如,要檢視上次引導的journal記錄,則可使用-1相對指標配合-b標記:

journalctl -b -1

另外,也可以使用引導ID:

journalctl -b caf0524a1d394ce0bdbcff75b94444fe
時間窗

按照引導環境檢視日誌條目當然非常重要,但我們往往還需要使用與系統引導無關的時間窗作為瀏覽基準。這種情況在長期執行的伺服器當中較為常見。

大家可以利用–since與–until選項設定時間段,二者分別負責說明給定時間之前與之後的記錄。

時間值可以多種格式輸出。對於絕對時間值,大家可以使用以下格式:

YYYY-MM-DD HH:MM:SS

例如,我們可以通過以下命令檢視全部2015年1月10日下午5:15之後的條目:

journalctl --since "2015-01-10 17:15:00"

如果以上格式中的某些組成部分未進行填寫,系統會直接進行預設填充。例如,如果日期部分未填寫,則會直接顯示當前日期。如果時間部分未填寫,則預設使用“00:00:00”(午夜)。第二欄位亦可留空,預設值為“00”:

journalctl --since "2015-01-10" --until "2015-01-11 03:00"

另外,journal還能夠理解部分相對值及命名簡寫。例如,大家可以使用“yesterday”、“today”、“tomorrow”或者“now”等表達。另外,我們也可以使用“-”或者“+”設定相對值,或者使用“ago”之前的表達。

獲取昨天資料的命令如下:

journalctl –since yesterday

要獲得早9:00到一小時前這段時間內的報告,可使用以下命令:

journalctl --since 09:00 --until "1 hour ago"

如大家所見,時間窗的過濾機制非常靈活且易用。

按資訊型別過濾

現在我們要探討如何利用感興趣的服務或者元件型別實現過濾。Systemd journal同樣提供多種方式供大家選擇。

按單元

最常用的此類過濾方式當數按單元過濾了。我們可以使用-u選項實現這一效果。

例如,要檢視系統上全部來自 Nginx 單元的日誌,可使用以下命令:

journalctl -u nginx.service

一般來講,我們可能需要同時按單元與時間進行資訊過濾。例如,檢查今天某項服務的執行狀態:

journalctl -u nginx.service --since today

我們還可以充分發揮journal檢視多種單元資訊的優勢。例如,如果我們的Nginx程式接入某個 PHP-FPM 單元以處理動態內容,則可將這兩個單元合併並獲取按時間排序的查詢結果:

journalctl -u nginx.service -u php-fpm.service --since today

這種能力對於不同程式間互動及系統除錯顯然非常重要。

按程式、使用者或者群組ID

由於某些服務當中包含多個子程式,因此如果我們希望通過程式ID實現查詢,也可以使用相關過濾機制。

這裡需要指定_PID欄位。例如,如果PID為8088,則可輸入:

journalctl _PID=8088

有時候我們可能希望顯示全部來自特定使用者或者群組的日誌條目,這就需要使用_UID或者_GID。例如,如果大家的Web伺服器執行在www-data使用者下,則可這樣找到該使用者ID:

id -u www-data
33

接下來,我們可以使用該ID返回過濾後的journal結果:

journalctl _UID=33 --since today

Systemd journal擁有多種可實現過濾功能的欄位。其中一些來自被記錄的程式,有些則由journald用於自系統中收集特定時間段內的日誌。

之前提到的_PID屬於後一種。Journal會自動記錄並檢索程式PID,以備日後過濾之用。大家可以檢視當前全部可用journal欄位:

man systemd.journal-fields

下面來看針對這些欄位的過濾機制。-F選項可用於顯示特定journal欄位內的全部可用值。

例如,要檢視systemd journal擁有條目的群組ID,可使用以下命令:

journalctl -F _GID
32
99
102
133
81
84
100
124
87

其將顯示全部journal已經儲存至群組ID欄位內的值,並可用於未來的過濾需求。

按元件路徑

我們也可以提供路徑位置以實現過濾。

如果該路徑指向某個可執行檔案,則journalctl會顯示與該可執行檔案相關的全部條目。例如,要找到與bash可執行檔案相關的條目:

journalctl /usr/bin/bash

一般來講,如果某個單元可用於該可執行檔案,那麼此方法會更為明確且能夠提供更好的相關資訊(與子程式相關的條目等)。但有時候,這種作法則無法奏效。

顯示核心資訊

核心資訊通常存在於dmesg輸出結果中,journal同樣可對其進行檢索。要只顯示此類資訊,可新增-k或者–dmesg標記:

journalctl -k

預設情況下,其會顯示當前引導環境下的全部核心資訊。大家也可以使用常規的引導選擇標記對此前的引導記錄進行查詢。例如,要查詢五次之前引導環境的資訊:

journalctl -k -b -5
按優先順序

管理員們可能感興趣的另一種過濾機制為資訊優先順序。儘管以更為詳盡的方式檢視日誌也很有必要,不過在理解現有資訊時,低優先順序日誌往往會分散我們的注意力並導致理解混亂。

大家可以使用journalctl配合-p選項顯示特定優先順序的資訊,從而過濾掉優先順序較低的資訊。

例如,只顯示錯誤級別或者更高的日誌條目:

journalctl -p err -b

這將只顯示被標記為錯誤、嚴重、警告或者緊急級別的資訊。Journal的這種實現方式與標準syslog資訊在級別上是一致的。大家可以使用優先順序名稱或者其相關量化值。以下各數字為由最高到最低優先順序:

0: emerg
1: alert
2: crit
3: err
4: warning
5: notice
6: info
7: debug以上為可在-p選項中使用的數字或者名稱。選定某一優先順序會顯示等級與之等同以及更高的資訊。
修改journal顯示內容

到這裡,過濾部分已經介紹完畢。我們也可以使用多種方式對輸出結果進行修改,從而調整journalctl的顯示內容。

截斷或者擴大輸出結果

 

我們可以縮小或者擴大輸出結果,從而調整journalctl的顯示方式。 在預設情況下,journalctl會在pager內顯示各條目,並通過右箭頭鍵訪問其資訊。 如果大家希望截斷輸出內容,向其中插入省略號以代表被移除的資訊,則可使用–no-full選項:

journalctl --no-full
. . .
Feb 04 20:54:13 journalme sshd[937]: Failed password for root from 83.234.207.60...h2
Feb 04 20:54:13 journalme sshd[937]: Connection closed by 83.234.207.60 [preauth]
Feb 04 20:54:13 journalme sshd[937]: PAM 2 more authentication failures; logname...ot

大家也可以要求其顯示全部資訊,無論其是否包含不可輸出的字元。具體方式為新增-a標記:

journalctl -a
標準輸出結果

預設情況下,journalctl會在pager內顯示輸出結果以便於查閱。如果大家希望利用文字操作工具對資料進行處理,則可能需要使用標準格式。在這種情況下,我們需要使用–no-pager選項:

journalclt --no-pager

這樣相關結果即可根據需要被重新定向至磁碟上的檔案或者處理工具當中。

輸出格式

如果大家需要對journal條目進行處理,則可能需要使用更易使用的格式以簡化資料解析工作。幸運的是,journal能夠以多種格式進行顯示,只須新增-o選項加格式說明即可。

例如,我們可以將journal條目輸出為JSON格式:

journalctl -b -u nginx -o json
{ "__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635", "__REALTIME_TIMESTAMP" : "1422990364739502", "__MONOTONIC_TIMESTAMP" : "27200938", "_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d", "PRIORITY" : "6", "_UID" : "0", "_GID" : "0", "_CAP_EFFECTIVE" : "3fffffffff", "_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee", "_HOSTNAME" : "desktop", "SYSLOG_FACILITY" : "3", "CODE_FILE" : "src/core/unit.c", "CODE_LINE" : "1402", "CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading", "SYSLOG_IDENTIFIER" : "systemd", "MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5", "_TRANSPORT" : "journal", "_PID" : "1", "_COMM" : "systemd", "_EXE" : "/usr/lib/systemd/systemd", "_CMDLINE" : "/usr/lib/systemd/systemd", "_SYSTEMD_CGROUP" : "/", "UNIT" : "nginx.service", "MESSAGE" : "Starting A high performance web server and a reverse proxy server...", "_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973" }
. . .

這種方式對於工具解析非常重要。大家也可以使用json-pretty格式以更好地處理資料結構:

journalctl -b -u nginx -o json-pretty
{
"__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635",
"__REALTIME_TIMESTAMP" : "1422990364739502",
"__MONOTONIC_TIMESTAMP" : "27200938",
"_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d",
"PRIORITY" : "6",
"_UID" : "0",
"_GID" : "0",
"_CAP_EFFECTIVE" : "3fffffffff",
"_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee",
"_HOSTNAME" : "desktop",
"SYSLOG_FACILITY" : "3",
"CODE_FILE" : "src/core/unit.c",
"CODE_LINE" : "1402",
"CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading",
"SYSLOG_IDENTIFIER" : "systemd",
"MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5",
"_TRANSPORT" : "journal",
"_PID" : "1",
"_COMM" : "systemd",
"_EXE" : "/usr/lib/systemd/systemd",
"_CMDLINE" : "/usr/lib/systemd/systemd",
"_SYSTEMD_CGROUP" : "/",
"UNIT" : "nginx.service",
"MESSAGE" : "Starting A high performance web server and a reverse proxy server...",
"_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973"
}
. . .

以下為可用於顯示的各類格式:

cat : 只顯示資訊欄位本身。
export : 適合傳輸或備份的二進位制格式。
json : 標準JSON,每行一個條目。
json-pretty : JSON格式,適合人類閱讀習慣。
json-sse : JSON格式,經過打包以相容server-sent事件。
short : 預設syslog類輸出格式。
short-iso : 預設格式,強調顯示ISO 8601掛鐘時間戳。
short-monotonic : 預設格式,提供普通時間戳。
short-precise : 預設格式,提供微秒級精度。
verbose : 顯示該條目的全部可用journal欄位,包括通常被內部隱藏的欄位。

這些選項允許大家以最適合需求的格式顯示journal條目。

活動程式監控

Journalctl命令還能夠幫助管理員以類似於tail的方式監控活動或近期程式。這項功能內建於journalctl當中,允許大家在無需藉助其它工具的前提下實現訪問。

顯示近期日誌

要顯示特定數量的記錄,大家可以使用-n選項,具體方式為tail -n。

預設情況下,其會顯示最近十條記錄:

journalctl -n

大家可以在-n之後指定要檢視的條目數量:

journalctl -n 20
追蹤日誌

要主動追蹤當前正在編寫的日誌,大家可以使用-f標記。方式同樣為tail -f:

journalctl -f
Journal維護

儲存這麼多資料當然會帶來巨大壓力,因此我們還需要了解如何清理部分陳舊日誌以釋放儲存空間。

瞭解現有磁碟使用量

大家可以利用–disk-usage標記檢視journal的當前磁碟使用量:

journalctl --disk-usage
Journals take up 8.0M on disk.
刪除舊有日誌

如果大家打算對journal記錄進行清理,則可使用兩種不同方式(適用於systemd 218及更高版本)。

如果使用–vacuum-size選項,則可硬性指定日誌的總體體積,意味著其會不斷刪除舊有記錄直到所佔容量符合要求:

sudo journalctl --vacuum-size=1G

另一種方式則是使用–vacuum-time選項。任何早於這一時間點的條目都將被刪除。

例如,去年之後的條目才能保留:

sudo journalctl --vacuum-time=1years
限定Journal擴充套件

大家可以配置自己的伺服器以限定journal所能佔用的最高容量。要實現這一點,我們需要編輯/etc/systemd/journald.conf檔案。

以下條目可用於限定journal體積的膨脹速度:

SystemMaxUse= : 指定journal所能使用的最高持久儲存容量。
SystemKeepFree= : 指定journal在新增新條目時需要保留的剩餘空間。
SystemMaxFileSize= : 控制單一journal檔案大小,符合要求方可被轉為持久儲存。
RuntimeMaxUse= : 指定易失性儲存中的最大可用磁碟容量(/run檔案系統之內)。
RuntimeKeepFree= : 指定向易失性儲存內寫入資料時為其它應用保留的空間量(/run檔案系統之內)。
RuntimeMaxFileSize= : 指定單一journal檔案可佔用的最大易失性儲存容量(/run檔案系統之內)。

通過設定上述值,大家可以控制journald對伺服器空間的消耗及保留方式。

總結

到這裡,systemd journal對系統及應用資料的收集與管理機制就介紹完畢了。其出色的靈活性源自將廣泛的後設資料自動記錄至集中化日誌之內。另外,journalctl命令則顯著簡化了journal的使用方式,從而讓更多管理員得以利用它完成面向不同應用元件的分析與相關除錯工作。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2640590/,如需轉載,請註明出處,否則將追究法律責任。

相關文章