syslog替代者Journal詳細(xì)解讀
51CTO編者按:在前幾天的外電頭條中,我們說到紅帽的兩位開發(fā)者表示將用The Journal替換掉原本的Syslog。下面這篇是LinuxToy上翻譯的兩位開發(fā)者的原文內(nèi)容,里面對(duì)The Journal的功能進(jìn)行了詳細(xì)的介紹,還有一些常見問題的解答,以供參考。
Lennart Poettering 發(fā)表長(zhǎng)篇文檔介紹 systemd 即將添加的新功能:Journal。
介紹 Journal
今天將為您介紹在過去的幾周我們?cè)谥铝?shí)現(xiàn)一個(gè) systemd 的新功能。這項(xiàng)新功能同時(shí)將幫助我們顯著的簡(jiǎn)化最小化安裝的 Linux 系統(tǒng),同時(shí)帶來一些新的概念,也會(huì)取代一個(gè)經(jīng)典 Unix 系統(tǒng)中的部件。因此它需要一個(gè)比較長(zhǎng)的介紹。所以請(qǐng)準(zhǔn)備好一杯熱巧克力,慢慢閱讀。
背景:syslog
長(zhǎng)久以來 syslog 是每一個(gè) Unix 系統(tǒng)中的重要部件。在漫長(zhǎng)的歷史中在各種 Linux 發(fā)行版中都有不同的實(shí)現(xiàn)去完成類似的工作,它們采取的是邏輯相近,并使用基本相同的文件格式。
如其名所述,syslog 守護(hù)進(jìn)程的任務(wù)是系統(tǒng)記錄。它從應(yīng)用程序和服務(wù)中獲取格式各異的日志消息并保存到磁盤上。通常,這些消息唯一的元數(shù)據(jù)是組件名、優(yōu)先級(jí)、時(shí)間戳、進(jìn)程標(biāo)簽和 PID。這些屬性由客戶端傳入,不經(jīng)過驗(yàn)證就直接原樣保存。很多這些屬性都是可選的,不同的實(shí)現(xiàn)中具體的格式也是有很大變化的。有個(gè) RFC 嘗試逐漸改進(jìn)和規(guī)范化消息格式,但是最重要的實(shí)現(xiàn)(比如 glibc’s syslog() 調(diào)用)基本無視了這些改進(jìn)。
現(xiàn)實(shí)中,寬松的 syslog 日志消息格式帶來了靈活和強(qiáng)大,但同時(shí)也成為它最大的不足。因?yàn)闆]有定義結(jié)構(gòu)化的格式,系統(tǒng)的分析和日志消息處理變得十分混亂:在將其翻譯為人類語言的過程中大量與消息生成源相關(guān)的上下文都丟失了。而且還有很多日志分析器會(huì)嘗試通過分析人類語言來重構(gòu)上下文。
Syslog 已經(jīng)存在了差不多 30 年了,由于它的簡(jiǎn)單和普遍,成為系統(tǒng)管理員的一個(gè)重要工作。但是它切實(shí)存在的局限開始導(dǎo)致一些嚴(yán)重的問題:
- 消息的內(nèi)容無法驗(yàn)證。每一個(gè)本地進(jìn)程都可以聲稱自己是 Apache PID 4711,而 syslog 也就相信并保存到磁盤上。
- 數(shù)據(jù)格式散漫。自動(dòng)化的日志分析器需要分析人類語言字符串來 a) 識(shí)別消息類型;b)分析其中的參數(shù)。這會(huì)導(dǎo)致災(zāi)難性的運(yùn)用正則表達(dá)式,同時(shí)也意味著需要不斷的跟進(jìn)上游開發(fā)者,以免他在新版本中改變了哪怕一點(diǎn)點(diǎn)人類語言日志字符串。于是在這種方式下,為了不影響用戶自定義的正則表達(dá)式,所有的日志消息將成為軟件的 ABI,而這通常并不是開發(fā)者所期望的。
- 時(shí)間戳并不包含時(shí)區(qū)信息,盡管一些較新的實(shí)現(xiàn)提供對(duì)它的支持。
- Syslog 只是系統(tǒng)上眾多日志系統(tǒng)的之一。其他的日志包括 utmp/wtmp, lastlog, audit, 內(nèi)核日志, 固件日志, 和很多應(yīng)用程序特定格式的日志。這不僅是毫無必要的復(fù)雜,并且掩蓋了各個(gè)子系統(tǒng)之間日志的關(guān)系。
- 閱讀日志文件很簡(jiǎn)單但是很低效,很多日志操作的復(fù)雜性為 O(n),進(jìn)行索引基本不可能。
- syslog 的網(wǎng)絡(luò)協(xié)議很簡(jiǎn)單但有限。由于它一般僅支持文件推送傳輸模式,沒有保存和轉(zhuǎn)發(fā),所以同時(shí)有大量進(jìn)程響應(yīng)(Thundering Herd)或者包丟失將嚴(yán)重影響它的使用。
- 日志文件很容易被駭客篡改,容易將攻擊信息從系統(tǒng)管理員眼皮底下掩蓋起來。
- 沒有訪問控制。除非由系統(tǒng)管理員手動(dòng)腳本控制,一個(gè)用戶要不然擁有日志文件的完整權(quán)限,要不就一點(diǎn)兒都沒有。
- 日志項(xiàng)目保存的元數(shù)據(jù)很有限,缺少一些關(guān)鍵信息,比如服務(wù)名、授權(quán)進(jìn)程或者穩(wěn)定的時(shí)間戳。
- 日志的自動(dòng)化滾動(dòng)是存在的,但是在大多數(shù)實(shí)現(xiàn)中都不甚理想:并不是持續(xù)監(jiān)視磁盤使用上限,而是在固定時(shí)間點(diǎn)上執(zhí)行滾動(dòng)操作,因此遺留了 DoS 攻擊的可能。
- 在一些實(shí)現(xiàn)中有更新速度限制,但是一般來說并不會(huì)考慮所建議的磁盤使用和服務(wù)指派信息。
- 一般都有磁盤上日志結(jié)構(gòu)的壓縮,但僅僅在滾動(dòng)時(shí)生效,并且又增加了已經(jīng)比較糟糕的日志操作復(fù)雜性。
- 經(jīng)典的 Syslog 傳統(tǒng)上并不處理系統(tǒng)啟動(dòng)早期和關(guān)機(jī)晚期的日志,盡管在最近的改進(jìn)中(比如 systemd )增添了此功能。
- 無法記錄二進(jìn)制數(shù)據(jù),在一些情況下恰好是必要的(比如 ATA SMART、SCSI 數(shù)據(jù)、固件轉(zhuǎn)儲(chǔ))。
很多這些問題在最近變得十分明顯,例如覺察修改了日志文件的入侵行為通常僅能靠運(yùn)氣。此外,由于 syslog 的功能所限,目前部分用戶常常要依靠一些閉源的組件來處理收集到的日志信息,使其變得有意義,訪問更便捷。
日志是服務(wù)管理中關(guān)鍵的一部分。在 Unix 系統(tǒng)上,絕大多數(shù)的運(yùn)行服務(wù)都連接到 syslog 來寫入日志消息。在 systemd 中,我們將日志做為服務(wù)管理的核心部分:從 Fedora 16 開始所有啟動(dòng)的服務(wù)都將把標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出自動(dòng)連接到 syslog 上。 不管服務(wù)是在啟動(dòng)早期還是正常操作中,它的輸出結(jié)果都會(huì)保存到系統(tǒng)日志中。因此,由于日志如此重要,于是需要特別配置才能禁用它,將原先的“可選記錄”策略轉(zhuǎn)變?yōu)?ldquo;可選不記錄”策略。信息透明不再是明智的選擇,而是默認(rèn)選擇。
在開發(fā) systemd 的過程中 syslog 的局限變得愈加明顯。例如:我們非常想添加的的一個(gè)簡(jiǎn)化系統(tǒng)管理工作的功能是當(dāng)使用 “systemctl status foo.service”時(shí),在通常服務(wù)信息的下面顯示最近的 10 條日志信息。若是使用經(jīng)典的 syslog 這個(gè)實(shí)現(xiàn)將是難以忍受的低效率、不可靠和不安全:需要對(duì)于所有日志文件的線性搜索(可能涉及實(shí)時(shí)解壓的操作),并且存儲(chǔ)的數(shù)據(jù)也是被修改過的,無法快捷的和 systemd 的服務(wù)名和運(yùn)行環(huán)境匹配。
如果用一句話代替這些內(nèi)容:傳統(tǒng)的 syslog 在 30 年的發(fā)展中演變成為有很多嚴(yán)重局限的強(qiáng)大工具。
現(xiàn)在,我們將如何改變這個(gè)狀況?
Journal
您可能已經(jīng)從如上的描述中猜出了:我們正在開發(fā)一個(gè)解決已有日志問題,彌補(bǔ)以上不足并且增添了一些新功能的工具:Journal。
當(dāng)然,構(gòu)建一個(gè)全新的系統(tǒng)核心組件時(shí),設(shè)計(jì)目標(biāo)必須要明確:
- 簡(jiǎn)單性:代碼少,依賴少,抽象開銷最小。
- 零維護(hù):日志是除錯(cuò)和監(jiān)控系統(tǒng)的核心功能,因此它自己不能再是產(chǎn)生問題,在嚴(yán)酷的環(huán)境下也要能工作。舉例說,這意味著系統(tǒng)要合理的應(yīng)對(duì)如有限磁盤空間或者 /var 不可用等問題,避免自己引發(fā)磁盤空間問題(例如在擴(kuò)展日志文件時(shí)在守護(hù)進(jìn)程正確的實(shí)現(xiàn)日志文件滾動(dòng))。
- 健壯性:由 Journal 生成的數(shù)據(jù)文件應(yīng)該可以由管理員直接訪問,并且在使用 “scp” 或 “rsync” 之類的工具復(fù)制到其他主機(jī)上的時(shí)候依然可用。合理的處理不完整拷貝的情況。Journal 文件瀏覽客戶端應(yīng)該可以在沒有 Journal 守護(hù)進(jìn)程的情況下工作。
- 移植性:Journal 文件應(yīng)該在所有類型的 Linux 系統(tǒng)上可用,無論它使用的何種 CPU 或者字節(jié)序。在嵌入式 ARM 系統(tǒng)上生成的 Journal 文件應(yīng)該可以在 x86 的桌面系統(tǒng)上可以讀取,如同本地生成的一般。
- 性能:以復(fù)雜性為前提,添加和瀏覽 Journal 操作應(yīng)該足夠快。最好實(shí)現(xiàn) O(log n) 或者更快,即便在大型組織內(nèi)的日志監(jiān)控也有良好性能。
- 整合性:因?yàn)槿罩臼欠?wù)的基礎(chǔ)之一,Journal 應(yīng)該和系統(tǒng)的其他部分緊密的整合起來,所以需要特別的聲明才能不使用它。日志是服務(wù)管理器的核心責(zé)任,所以應(yīng)該通過整合來反映這一點(diǎn)。
- 最小資源占用:Journal 數(shù)據(jù)文件需要較小,特別是和經(jīng)典的 syslog 生成的數(shù)據(jù)相比時(shí)。
- 通用的事件存儲(chǔ):Journal 應(yīng)該可以用來進(jìn)行任何 Journal 條目的存儲(chǔ),無論其格式、元數(shù)據(jù)還是大小。
- 統(tǒng)一化:各種不同的日志存儲(chǔ)技術(shù)應(yīng)該統(tǒng)一起來,將所有的可記錄事件保存在同一個(gè)數(shù)據(jù)存儲(chǔ)中。所以 Journal 內(nèi)容的全局上下文都會(huì)被保存并且可供日后查詢。例如一條固件記錄后通常會(huì)跟隨一條內(nèi)核記錄,最終還會(huì)有一條用戶態(tài)記錄。重要的是當(dāng)保存到硬盤上時(shí)這三者之間的關(guān)系不會(huì)丟失。
- 高級(jí)別工具的基礎(chǔ):Journal 應(yīng)該提供一個(gè)通用的 API ,以便狀態(tài)監(jiān)控器、恢復(fù)工具、崩潰報(bào)告生成器和其他高級(jí)別的工作來訪問 Journal 數(shù)據(jù)。
- 擴(kuò)展性:和 Linux 的適用范圍從嵌入式設(shè)備跨越到超級(jí)計(jì)算機(jī)集群一樣,Journal 也應(yīng)該可以有廣泛。日志對(duì)于開發(fā)嵌入式設(shè)備和維護(hù)集群一樣重要。為了保持較小占用,Journal 需要著重于常見的一般使用模式,同時(shí)對(duì)于一些特定的變化做一定考量。
- 通用性:做為操作系統(tǒng)的基礎(chǔ)模塊,Journal 應(yīng)該可以通用,并能擴(kuò)展以滿足于一些應(yīng)用程序特定的需求。格式應(yīng)該是可擴(kuò)展的,并且提供 API。
- 集群和網(wǎng)絡(luò):今日計(jì)算機(jī)很少是獨(dú)立工作的了。所以有必要從 Journal 文件和工具的設(shè)計(jì)初始就考慮對(duì)于多主機(jī)安裝配置的支持。
- 安全性:Journal 文件應(yīng)該是可以驗(yàn)證的,讓無法檢測(cè)的修改不再可能。
說了很多設(shè)計(jì)目標(biāo),下面是一些我們實(shí)現(xiàn)過程的技術(shù)概覽,并介紹新系統(tǒng)是如何工作的:
受 udev 事件啟發(fā),Journal 條目與環(huán)境組塊相似。一個(gè)鍵值域,按照換行符分開,使用大寫的變量名。和 udev 設(shè)備事件和真實(shí)環(huán)境組塊相比,有一個(gè)主要不同:盡管毫無疑問主要值會(huì)是 ASCII 格式的字符串,也支持以二進(jìn)制為值 -- 某些情況下可以用來添加 ATA SMART 健康信息、SCSI 數(shù)據(jù)、內(nèi)核轉(zhuǎn)儲(chǔ)或固件轉(zhuǎn)儲(chǔ)。由代碼生成的 Journal 條目可以包含多個(gè)域,既可以是已知的類型,也可以是服務(wù)/子系統(tǒng)/驅(qū)動(dòng)特定的。
應(yīng)用程序和服務(wù)可以通過將項(xiàng)目域傳遞給 systemd journald 服務(wù)來生成項(xiàng)目。該服務(wù)可以為項(xiàng)目增加一定數(shù)量的元數(shù)據(jù)。這些受信任域的值由 Journal 服務(wù)來決定且無法由客戶端來偽造。一旦牽扯到硬件和內(nèi)核設(shè)備,Journal 服務(wù)將為日志項(xiàng)目添加從 udev 數(shù)據(jù)庫(kù)獲得的當(dāng)前設(shè)備信息,其中包含了所有設(shè)備名和符號(hào)鏈接,以及與 Journal 條目關(guān)聯(lián)的其他設(shè)備數(shù)據(jù)。
由 Journal 守護(hù)進(jìn)程添加的域?qū)⒕哂邢聞澗€前綴(“_”), 用來標(biāo)示該區(qū)域是可信的,而不是由未知客戶端提供的。應(yīng)用程序自身無法傳遞以下劃線開頭的的域名稱。這是一個(gè)樣例展示在客戶端傳輸基礎(chǔ)上添加內(nèi)容的日志條目展示:
_SERVICE=systemd-logind.service MESSAGE=User harald logged in MESSAGE_ID=422bc3d271414bc8bc9570f222f24a9 _EXE=/lib/systemd/systemd-logind _COMM=systemd-logind _CMDLINE=/lib/systemd/systemd-logind _PID=4711 _UID=0 _GID=0 _SYSTEMD_CGROUP=/system/systemd-logind.service _CGROUPS=cpu:/system/systemd-logind.service PRIORITY=6 _BOOT_ID=422bc3d271414bc8bc95870f222f24a9 _MACHINE_ID=c686f3b205dd48e0b43ceb6eda479721 _HOSTNAME=waldi LOGIN_USER=500
該樣例條目是由 systemd logind 守護(hù)進(jìn)程在用戶 “harald” 登錄時(shí)創(chuàng)建的。如您所見它自動(dòng)添加了相當(dāng)復(fù)雜的數(shù)據(jù),包括一些重要的執(zhí)行進(jìn)程參數(shù)。更加詳細(xì)的定義的域說明請(qǐng)參考:
原生的 Journal 文件格式從經(jīng)典的日志文件和 Git 倉(cāng)庫(kù)獲得啟發(fā)。它被設(shè)計(jì)來只將日志數(shù)據(jù)添加到末尾(用來保證基于 mmap() 的訪問的健壯和原子性),以及一些在用來反映新添加內(nèi)容的文件頭元數(shù)據(jù)變更。這些用來組成項(xiàng)目的域以獨(dú)立對(duì)象的方式保存在 Journal 文件中,當(dāng)需要時(shí)被項(xiàng)目所引用。這將節(jié)省大量的磁盤空間,因?yàn)槿罩卷?xiàng)目通常會(huì)有很多的重復(fù)(試想:每個(gè)本地的消息都會(huì)包含相同的HOSTNAME= 和 MACHINE_ID= 域)。數(shù)據(jù)域還會(huì)被壓縮來節(jié)省磁盤空間。直接效果就是盡管 Journal 相比經(jīng)典的 Syslog 明顯記錄了更多的元數(shù)據(jù)信息,但是磁盤占用卻無明顯變化。
磁盤上使用特定的 64位 LE(從小到大)偏移,目的是簡(jiǎn)化操作并保證我們可以存儲(chǔ)大小可觀的二進(jìn)制數(shù)據(jù)。日志瀏覽工具和 journald 之間的無需同步,需要瀏覽 Journal 文件的客戶端可以簡(jiǎn)單的使用 mmap() 訪問文件,并使用文件變化通知來告知更新。
提供用于客戶端訪問 Journal 文件的庫(kù),用來實(shí)現(xiàn)對(duì)項(xiàng)目任意域的索引,以及通過單調(diào)化或者時(shí)序化時(shí)間戳的隨機(jī)訪問。客戶端庫(kù)會(huì)自動(dòng)合并多個(gè) Journal 文件使其看起來好像是一個(gè)統(tǒng)一的 Journal 項(xiàng)目流。這用來隱藏底層細(xì)節(jié)譬如已經(jīng)歸檔的文件,或?qū)儆诙鄠€(gè)用戶的 Journal 文件。在瀏覽接口上透明化的 Journal 文件合并是完全動(dòng)態(tài)的:當(dāng)創(chuàng)建新的 Journal 文件或者刪除舊的文件時(shí)都會(huì)自動(dòng)更新瀏覽視圖。事實(shí)上,Journal 瀏覽期望做到即時(shí)性的,從而實(shí)現(xiàn)對(duì) Journal 來源的實(shí)時(shí)監(jiān)控。
從非特權(quán)登錄用戶發(fā)來的消息將按照每用戶分割為獨(dú)立的 Journal 文件。使用 POSIX ACL 來實(shí)現(xiàn)讀取權(quán)限控制,保證用戶可以訪問他自己的 Journal 文件。系統(tǒng)服務(wù)生成的 Journal 條目默認(rèn)情況下無法被一般用戶訪問,除非他們屬于一個(gè)特殊的 Unix 用戶組。值得注意的是文件的分割是用來協(xié)助合適的訪問控制的,但是全局的上下文并未因此丟失。客戶端會(huì)通過所有消息強(qiáng)制按照統(tǒng)一的排序的方式將 Journal 文件合并起來,從而保證自動(dòng)分配的序列號(hào)碼的全局順序。這意味著可以在不影響用戶條目上下文的情況下實(shí)現(xiàn)訪問控制。
Journal 的核心思路就是統(tǒng)一目前所用的各類日志記錄技術(shù)。因此它將成為 wtmp 的替代品,啟動(dòng)早期記錄器甚至授權(quán)記錄后端。數(shù)據(jù)將從各種不同的來源生成:printk() 生成的內(nèi)核消息,syslog(3) 生成的用戶態(tài)消息,使用原生 API 生成的用戶態(tài)條目,通過 /proc/proc/sys/kernel/core_pattern 生成的核心轉(zhuǎn)儲(chǔ)及更多。以后我們希望能有固件消息(UEFI 日志)的鉤子,并擴(kuò)展基于內(nèi)核的日志來支持內(nèi)核中結(jié)構(gòu)化日志。因?yàn)樵?Journal 數(shù)據(jù)結(jié)構(gòu)中所有的域都是隱式的索引過的,所以跟 wtmp 相比從 Journal 的中提取用戶數(shù)據(jù)是個(gè)很簡(jiǎn)單的操作。啟動(dòng)早期和運(yùn)行時(shí)日志時(shí)統(tǒng)一的。只要 /var 不可用,所有的 Journal 條目便會(huì)自動(dòng)保存在 /run 下,等待 /var 可用時(shí)再立刻寫入。這意味著最終所有系統(tǒng)生成的消息,不管是在 POST 中由固件,還是在內(nèi)核初始化,啟動(dòng)早期還是運(yùn)行時(shí),都將保存到索引的 Journal 文件中。
為了讓條目可以被客戶端工具識(shí)別出來,Journal 條目可選包含一個(gè) 128 位的標(biāo)示符,由生成消息的服務(wù)設(shè)定于 MESSAGE_ID= 中。這個(gè) ID 應(yīng)該由開發(fā)者在開發(fā)過程中隨機(jī)生成的。例如,一個(gè) ID 表示“用戶登出”而另外一個(gè) ID 表示“用戶登入”。所有這些事件的條目都分別包含 128 位的 ID,因此將很容易辨識(shí)出來并索引。這個(gè) ID 完全可以和 RFC4122 UUID 類型四保持兼容,但是這嚴(yán)格的來說并不需要故也不強(qiáng)求。該設(shè)計(jì)會(huì)和其他采用 UUID 標(biāo)示消息類型的日志系統(tǒng)保持兼容,比如 UEFI 固件日志。考慮到128 位 ID 的全局錯(cuò)誤代碼的隨機(jī)本質(zhì),它們并不需要一個(gè)集中式的標(biāo)準(zhǔn)化機(jī)構(gòu)來為某個(gè)特定的消息類型指定 ID。指定消息 ID 是完全可選的,我們認(rèn)為只要少量的 Journal 的條目會(huì)包括它,比如那些需要被用戶態(tài)識(shí)別出來的部分。如果一個(gè)開發(fā)者需要為他新引入的消息類型指定一個(gè)新 128 位 ID 的話,只需要運(yùn)行 “cat /proc/sys/kernel/random/uuid” 即可,它會(huì)在每次運(yùn)行的時(shí)候返回一個(gè)新的 UUID。這 128 位的 ID 亦可用于實(shí)現(xiàn)本地化的消息 UI,按照他在 UI 工具中尋找翻譯過的消息,然后呈現(xiàn)給用戶。
所有的條目都用現(xiàn)實(shí)時(shí)間和單調(diào)時(shí)間打上時(shí)間戳。為了使單調(diào)時(shí)間戳有意義,所有的消息同時(shí)也包含運(yùn)行的 Linux 內(nèi)核的啟動(dòng) ID (比如 /proc/sys/kernel/random/boot_id)。精確度是 1 微妙,現(xiàn)實(shí)時(shí)間采用 UTC 計(jì)時(shí)以避免遭受和 syslog 類似的時(shí)區(qū)問題。
Journal 文件可以回滾、刪除、復(fù)制到其他機(jī)器、合并或者更改。為了保證應(yīng)用程序、同步公布和網(wǎng)絡(luò)服務(wù)可靠的識(shí)別條目,所有 Journal 條目都可以用一個(gè)指針字符串標(biāo)識(shí)。一個(gè)這樣的字符串可以標(biāo)識(shí)一個(gè)特定的消息,甚至在條目丟失或不可用時(shí)也保持不變,于是可以用來定位最近的下一個(gè)條目。
如果超過某個(gè)限額的話,journald 會(huì)自動(dòng)回滾 Journal 文件。這被內(nèi)建在磁盤空間分配的邏輯中,目的是避免單純基于時(shí)間回滾的漏洞。回滾不僅考慮最大磁盤利用限制,并且還將監(jiān)視通常的磁盤使用水平來保證磁盤上至少預(yù)留有一定空間。
由客戶端發(fā)送的條目隱含的受到速率限制,避免未信任的客戶端通過大量發(fā)送自身數(shù)據(jù)的方式?jīng)_掉 Journal 中的相關(guān)數(shù)據(jù)。這個(gè)速率依照可用磁盤空間調(diào)整,于是在磁盤空間富裕的時(shí)候速率會(huì)高些,而磁盤空間低時(shí)將會(huì)強(qiáng)制為較低的速率。
在初始版本的 journald 中對(duì)于網(wǎng)絡(luò)支持會(huì)非常簡(jiǎn)陋:要在網(wǎng)絡(luò)中分享 Journal 文件的話,使用比如 scp、rsync 或者 NFS 復(fù)制到一個(gè)集中化主機(jī)上。Journal 瀏覽器客戶端將會(huì)透明化的合并這些文件,如果需要的話進(jìn)行交叉存儲(chǔ)。在稍候的版本中我們計(jì)劃最低限度的擴(kuò)展 Journal 來支持實(shí)時(shí)遠(yuǎn)程日志,通過用本地 Journal 文件做為緩存的存儲(chǔ)-轉(zhuǎn)發(fā)邏輯來實(shí)現(xiàn) PUSH 和 PULL 兩種模式。不管使用何種模式,Journal 的底層格式設(shè)計(jì)適用于擴(kuò)展到大規(guī)模主機(jī)環(huán)境,所有的條目都會(huì)用機(jī)器 ID 和主機(jī)名來標(biāo)示。目的是實(shí)現(xiàn)一種有效的 Journal 監(jiān)控工具完成透明化、實(shí)時(shí)的多重主機(jī)日志瀏覽任務(wù),并且留給管理員按照自己需要調(diào)整傳輸方式的空間,比如是否實(shí)時(shí)功能比避免大量進(jìn)程響應(yīng)(Thundering Herd)更重要等。
互聯(lián)網(wǎng)是個(gè)險(xiǎn)象叢生的地方。對(duì)于重要網(wǎng)站的入侵已經(jīng)變得愈加常見。在成功的滲透之后,攻擊者通常會(huì)通過編輯日志文件的方式掩藏他的蹤跡。 這類修改在傳統(tǒng)的 syslog 下很難檢測(cè):因?yàn)樗玫氖菦]有加密認(rèn)證的純文本,所以無法獲知變更。從 Git 中獲得啟發(fā),Journal 中的所有條目都是加密哈希過的,且在文件中包含先前條目的哈希值。這樣的結(jié)果是一個(gè)條目鏈,每一個(gè)條目都可以認(rèn)證之前的全部。如果最頂端的哈希通常都保存在一個(gè)只讀的位置,整個(gè)鏈條都可以通過它認(rèn)證。檢測(cè)攻擊者的修改將變得十分容易。
如上所述日志是服務(wù)管理的必要部分。這不僅意味著服務(wù)本身的日志輸出將傳遞到 Journal,并且將為額外的服務(wù)事件生成 Journal 條目,比如當(dāng)服務(wù)開始、錯(cuò)誤推出、停止或崩潰之時(shí)。
Journal 的守護(hù)進(jìn)程 journald 首先將取代目前 systemd 分發(fā)的兩個(gè)日志相關(guān)迷你守護(hù)進(jìn)程(systemd-kmsg-syslogd and systemd-stdout-syslog-bridge)。長(zhǎng)期目標(biāo)是在多種安裝配置中取代傳統(tǒng)的 syslog 守護(hù)進(jìn)程,而不造成沖突。由于運(yùn)行服務(wù)的減少(由 3 降為 1)以及相比全尺寸的 syslog 守護(hù)進(jìn)程少很多代碼的 journald,Linux 系統(tǒng)的資源消耗將會(huì)減低。
當(dāng)前狀態(tài)
目前為止,核心的功能和和全部重要的算法已經(jīng)實(shí)現(xiàn)并放置在 systemd git 的 Journal 分支中。但是代碼目前還不完善,缺少一些上面提到的功能。
這篇博文是用來澄清一些社區(qū)中對(duì)于我們計(jì)劃、選擇和原因的誤解。
我們計(jì)劃在 Fedora 17 中初步實(shí)現(xiàn),不過在首次亮相中只選擇與極少幾個(gè)部件關(guān)聯(lián)。rsyslog 會(huì)和它一起運(yùn)行,用戶可能會(huì)很難注意到它,除了 “systemctl status” 將會(huì)顯示所有服務(wù)的最近日志信息,以及嘗試使用我們的客戶端工具,比如 “journalctl” 來搜索索引的 Journal 時(shí)。
常見問題及回答
我們一直在和不同知識(shí)背景的人討論,收集想法、建議和批評(píng)。有一些問題經(jīng)常被重復(fù)提到,下面就是我們的回答:
Journal 很酷,但是 systemd 很糟糕。我可以不用 systemd 而單獨(dú)使用 journald 么?
不行。日志是服務(wù)管理的核心部分。Journal 和 systemd 緊密結(jié)合從而保證系統(tǒng)的每一個(gè)部分都可以監(jiān)控,查詢和除錯(cuò)。生成的 Journal 項(xiàng)目是從 systemd 的不同部分查詢出來的。實(shí)際上,systemd 和 journald 是如此緊密耦合以至于拆分開的舉動(dòng)毫無意義。不過正如所說,這是自由軟件,您可以隨自己愿望修改代碼。最后,您認(rèn)為 systemd 很糟糕的想法是錯(cuò)誤的。
運(yùn)行 Journal 會(huì)破壞 rsyslog/syslog-ng 么?
不會(huì)。您可以同時(shí)運(yùn)行 rsyslog 或 syslog-ng 及 journald,syslog 消息會(huì)雙雙記錄在 rsyslog/syslog-ng 和 Journal 中。但是,Journal 將記錄一些純文本的 syslog 所不具備的豐富元信息。
我的應(yīng)用程序需要在磁盤保存?zhèn)鹘y(tǒng)的純文本日志。我可以配置 Journald 生成么?
不能。如果您需要這樣做的話,只要和 Journal 同時(shí)運(yùn)行一個(gè)傳統(tǒng)的 syslog 實(shí)現(xiàn)如 rsyslog, 即可幫助您生成想要的文件。
為什么 Journal 不生成傳統(tǒng)的日志文件?
簡(jiǎn)單來說,傳統(tǒng)的日志文件無法索引,并且其速度隨著復(fù)雜度按照函數(shù) O(n) 降低。原生的 Journal 文件格式下關(guān)鍵操作速度隨著復(fù)雜度按照 O(log(n)) 降低,性能更佳。更多原因請(qǐng)參考上面章節(jié)。
我可以連接一個(gè) syslog 協(xié)議兼容的遠(yuǎn)程 RFC 到 Journal 么?
在目前您不可以,并且 Journal 也不太可能會(huì)默認(rèn)支持這個(gè)。但是編寫一個(gè)可行的轉(zhuǎn)換器或者網(wǎng)關(guān)應(yīng)該不困難。
我在嵌入式設(shè)備上使用 systemd 于是對(duì)永久性保存日志不感興趣,我可以移除 Journal 么?
不可以。但是您可以告訴 systemd 您不需要永久性日志。通過移除(或者一開始就不創(chuàng)建)/var/log/journal 目錄,在這種情況下 journald 僅會(huì)將記錄到 /run/log/journal (如同在早期啟動(dòng)的情況下)。/run 是臨時(shí)的并且會(huì)在重啟時(shí)丟失,和 /var 不同。在此之上您可以將 Journal 使用的最大磁盤空間設(shè)置為一個(gè)很小的值。
人人都說 UUID 是有問題的。為何還要用 UUID 來表示消息呢?
UUID 規(guī)格的確是奇形怪狀且不必要的復(fù)雜。因此我們推薦只要和 UUID 類型4保持一致即可,不用理會(huì) RFC 4122。實(shí)際上 UUID 已經(jīng)在 Linux 上成功的應(yīng)用了很長(zhǎng)時(shí)間,所有發(fā)行版默認(rèn)都是依據(jù)文件系統(tǒng) UUID 來執(zhí)行掛載的。
但是 UUID 從來沒正常工作過!比如 MAC 地址是重復(fù)的并且所有我的 USB 設(shè)備都使用的同一個(gè)。為什么要堅(jiān)持使用它呢?
我們實(shí)際上一直在使用它,比如像上面說的在文件系統(tǒng)中,它工作的很好。硬件都包含有序列號(hào),不少?gòu)S商初始化為 1-2-3-4-5,但是它和 UUID 沒什么關(guān)系。設(shè)備序列號(hào)并不是 UUID,不要混淆!
另外,我們并沒有強(qiáng)制使用它們。如上所述它是完全可選的,并且只需要并賦予到需要后來識(shí)別出來的消息上即可。
但我在代碼中引入了一個(gè) UUID 來標(biāo)識(shí)一個(gè)消息類型,其他人使用了該段代碼做為別的工作的模板,那么 Journal 就會(huì)壞掉了。
不,這不對(duì)。為什么?很簡(jiǎn)單,因?yàn)橥瑯拥?128位 ID 將會(huì)用來指定同一個(gè)錯(cuò)誤/條件/項(xiàng)目類型,不管來源是什么。比如同樣的 128位 ID 將會(huì)用來標(biāo)識(shí)“在塊設(shè)備上存在壞扇區(qū)”,而不管是哪個(gè)設(shè)備或驅(qū)動(dòng)器生成了這個(gè)消息。如果用戶態(tài)軟件需要在不同的服務(wù)、驅(qū)動(dòng)或設(shè)備之間區(qū)分開 Journal 項(xiàng)的話,請(qǐng)使用其他額外的匹配服務(wù)/設(shè)備/驅(qū)動(dòng)的 Journal 信息域。
不過從另一個(gè)角度講,您指出的實(shí)際上是個(gè)好事情。我們特別鼓勵(lì)人們?cè)谒麄兊能浖兄赜孟?ID,而不是創(chuàng)造新的。
但是 printf()/printk() 格式化字符串是標(biāo)識(shí)消息類型的更好選擇!
現(xiàn)實(shí)并不是這樣的。格式化字符串到頭來不過只是人類語言的模板。將人類語言用于消息類型識(shí)別是不可靠的:每個(gè)修正的錯(cuò)誤拼寫都會(huì)影響消息類型,并且導(dǎo)致 Journal 客戶端識(shí)別消息錯(cuò)誤。每次對(duì)一個(gè) Journal 消息進(jìn)行擴(kuò)充或者重寫的時(shí)候,將會(huì)導(dǎo)致 ABI 破壞。讓人類語言變?yōu)?ABI 是致命的錯(cuò)誤。事實(shí)上,將所有消息類型變?yōu)?ABI 的方式在經(jīng)典的正則表達(dá)式匹配條件下風(fēng)險(xiǎn)很大。OTOH 消息標(biāo)識(shí)可以在改變?nèi)祟愓Z言字符串時(shí)保持不變,因此很好的將 ABI 和人類語言分割開了。
你們一點(diǎn)兒都不懂!你們應(yīng)該使用源代碼文件名和位置作為消息的標(biāo)識(shí)符!
這并不可行,因?yàn)檫@將使源代碼位置變?yōu)?ABI:?jiǎn)栆淮伍_發(fā)者在頭文件中增加一行將導(dǎo)致全部消息 ID 的改變。這將是個(gè)大問題。
誰會(huì)來組織和管理 UUID 的命名空間并生成 UUID?Who would organize and manage the UUID namespace and generate UUIDs? 認(rèn)真點(diǎn)兒,我們不需要更多官僚機(jī)制的人!
128 位隨機(jī) ID 的好處之一就是它的命名空間并不需要管理。所有人都可以從 /proc/sys/kernel/random/uuid 里取出一個(gè)隨機(jī) UUID 為他所用。只要需要,開發(fā)者可以生成任意多的 UUID 而不需要詢問任意集中管理體制。UUID 允許我們擁有一個(gè)共同點(diǎn)的命名空間而無需官僚機(jī)制。
但是 UUID?你是認(rèn)真的么?你是哪個(gè)星球來的!?人人都知道像 LANANA 這樣的中介是為應(yīng)用程序指定全球唯一消息標(biāo)識(shí) ID 的理想選擇!
Linux 并不是一個(gè)孤島。我們需要在 Journal 中與其他基礎(chǔ)架構(gòu)中所使用消息 ID 無縫整合起來。因此我們選擇了有用途的并且已經(jīng)在他處實(shí)踐過的。同樣,UUID 只不過是為了無需集中管理的唯一標(biāo)識(shí)符。為什么要在沒必要的時(shí)候選擇一個(gè)人手不足的官僚的集中注冊(cè)中心的?
喏,你應(yīng)該使用逆序的域名表示消息類型,像 Java 一樣!
實(shí)質(zhì)上,比較字符串要比比較固定長(zhǎng)度的 ID 更加復(fù)雜。并且,實(shí)事求是的說這不能解決命名空間的問題,因?yàn)楣烙?jì)有 90% 的消息類型將在同個(gè)命名空間內(nèi):org.freedesktop resp. org.kernel.
但是 ASN.1 OID 可以成為很好的消息類型區(qū)分符!
兄弟,沒搞錯(cuò)吧?
現(xiàn)在我有了更好的主意,不如用 URL 做為類型 ID 吧?
實(shí)際上相比逆序域名的方式它并未好多少,不是么?
但是如果你們?cè)诿總€(gè)項(xiàng)目上都要生成一個(gè) UUID 的話,很快便會(huì)窮盡我的熵池的!
再度一遍博文,很顯然您并沒有仔細(xì)閱讀。 128 位的消息 ID 是由開發(fā)者在開發(fā)過程中指定的,并不是在運(yùn)行時(shí)。大多數(shù)項(xiàng)目在整個(gè)開發(fā)過程中幾乎不可能生成超過 30 個(gè),這個(gè)數(shù)量哪怕在 10 年前的機(jī)器的熵池中都是微不足道的。
你們這些用戶態(tài)的小屁孩們,先是強(qiáng)迫我在系統(tǒng)中使用 20 個(gè) CPU 進(jìn)程分組,現(xiàn)在又要強(qiáng)迫我在系統(tǒng)中使用惡心的 UUID?
先不談我們并沒有強(qiáng)迫您使用 20 個(gè)進(jìn)程分組的事實(shí),您幾乎肯定已經(jīng)在使用 UUID 了,因?yàn)槟奈募到y(tǒng)是在啟動(dòng)過程中依據(jù) UUID 加載的。將這些當(dāng)作是實(shí)現(xiàn)的具體細(xì)節(jié),而您并不喜歡它,那么您就沒必要在消息中添加它。影響的只是消息無法被再度識(shí)別,除非使用極度復(fù)雜的正則表達(dá)式。不過或許這就是您想要的?無論怎樣,我們沒有強(qiáng)迫任何人做任何事。
所以你們是依照發(fā)送用戶的 ID 來分割 Journal 項(xiàng)目的了。那么你怎么能保證用戶不會(huì)偽裝身份呢?
幸運(yùn)的是,Linux 內(nèi)核支持 SCM_CREDENTIALS,可以提供我們無法偽造的消息發(fā)送者信息。
Journal 文件格式會(huì)標(biāo)準(zhǔn)化么?哪里可以找到磁盤上數(shù)據(jù)結(jié)構(gòu)的說明?
截至目前我們還沒有打算要將格式其標(biāo)準(zhǔn)化,保留在需要時(shí)進(jìn)行變更的權(quán)力。我們會(huì)逐步完善磁盤上格式的文檔,但是目前我們不希望能有程序直接讀取、寫入和修改 Journal 文件。對(duì)其的訪問可以通過一個(gè)共享庫(kù)和命令行程序?qū)崿F(xiàn)。(不過再一次,這是自由軟件,您隨時(shí)可以閱讀源代碼!)
為什么你們這些人又搞重復(fù)發(fā)明?為什么不只把你們想要的增加到已有的 syslog?如果您只想清理日志格式的話,syslog 足夠了。
有些情況下改進(jìn)現(xiàn)有方案是一種方式,但是當(dāng)需要的變化太大時(shí),有正確的原因并且對(duì)以前解決方案提供了良好的兼容性的重新發(fā)明卻是更好的選擇。我們相信我們有著正確的原因,并且我們?cè)谂μ峁┳畲罂赡艿募嫒菪浴?/p>
不,僅僅修復(fù)日志格式?jīng)]法帶來很多變革。不僅無法實(shí)現(xiàn)最基本的二進(jìn)制文件或敏感的結(jié)構(gòu)化日志,也沒有索引或者訪問控制。
是不是 Journal 將完全拋棄 syslog ?
不,首先,syslog API syslog(3) 作為寫入日志的第一級(jí)別接口被支持,并且將持續(xù)用作主要的簡(jiǎn)單文本日志 API。但是只要元數(shù)據(jù)(特別是二進(jìn)制元數(shù)據(jù))被加入到條目中,便會(huì)轉(zhuǎn)而使用原生的 Journal API。
其次,Journal 是個(gè)全新的產(chǎn)物。從另一個(gè)方面說,Syslog 是一個(gè)工業(yè)標(biāo)準(zhǔn)(盡管是定義的相當(dāng)孱弱,日志格式幾乎都沒有統(tǒng)一),并且被廣泛接受,存在于為數(shù)眾多的操作系統(tǒng)、應(yīng)用程序和設(shè)備中。因此,syslog 依然是很重要的并且將繼續(xù)存在于許多安裝配置中。Journal 守護(hù)進(jìn)程并不使用 RFC syslog 協(xié)議,將來也不太可能會(huì)。當(dāng)需要一個(gè) syslog 兼容協(xié)議的地方,依然需要使用經(jīng)典的 syslog 實(shí)現(xiàn)方案。為了保證此項(xiàng)工作,我們確保 Journal 的實(shí)現(xiàn)可以和本地的 syslog 守護(hù)進(jìn)程協(xié)作,且將需要的消息轉(zhuǎn)發(fā)給 syslog,使其可以像如同沒有 journald 中介一般的工作。
需要您的加入!
在決定這個(gè)設(shè)計(jì)之前,我們了解一些高負(fù)荷的日志用戶,包括那些擁有超過 100 臺(tái)活躍主機(jī)的用戶。我們也和一些可能成為主要 Journal 用戶的工程師聊過。我們對(duì)于使用慣例和擴(kuò)展性問題尤其感興趣。但是,每一個(gè)安裝配置都有自己的需求,因此,如果您在上面的設(shè)計(jì)描述中看到了某個(gè)用于您特定需要的重要功能沒有實(shí)現(xiàn)的話,我們希望您能和我們?nèi)サ穆?lián)系。上面的設(shè)計(jì)著重于日志記錄的底層。目前我們并不負(fù)責(zé)特定的 UI,所以如果有這方面的需求話請(qǐng)稍候再留下意見。另外,現(xiàn)在還沒到圣誕節(jié),因此我們無法實(shí)現(xiàn)所有愿望(請(qǐng)不要失望),但是我們很在意的去了解它們,甚至可以保證至少我們會(huì)去考慮它們!先謝過了!
消息來源:Phoronix
【編輯推薦】