Linux

給定單元的 *.journal 文件在哪裡?

  • September 30, 2020

我有一個用於 sshd 的 systemd 服務單元:

$ systemctl status sshd
* ssh.service - OpenBSD Secure Shell server
  Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
  Active: active (running) since Wed 2020-09-30 18:54:10 UTC; 6s ago
 Process: 13923 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Process: 13918 ExecReload=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
 Process: 6287 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Main PID: 6296 (sshd)
   Tasks: 1 (limit: 4915)
  CGroup: /system.slice/ssh.service
          `-6296 /usr/sbin/sshd -D

Sep 30 18:54:10 machine systemd[1]: Starting OpenBSD Secure Shell server...
Sep 30 18:54:10 machine sshd[6296]: Server listening on 0.0.0.0 port 22.
Sep 30 18:54:10 machine sshd[6296]: Server listening on :: port 22.
Sep 30 18:54:10 machine systemd[1]: Started OpenBSD Secure Shell server.

我有一些*.journal它寫的文件:

$ find /var/log/journal -type f -name 'system@*.journal' -exec grep -l 'OpenBSD' {} +
/var/log/journal/0123456789abcdef0123456789abcdef/system@0123456789abcdef0123456789abcdef-000000000100bfdd-0005ac0c092a655f.journal
/var/log/journal/0123456789abcdef0123456789abcdef/system@0123456789abcdef0123456789abcdef-000000000102d6c3-0005ac2251abe7d9.journal
/var/log/journal/0123456789abcdef0123456789abcdef/system@0123456789abcdef0123456789abcdef-00000000010fc6d5-0005ac9be551a106.journal
/var/log/journal/0123456789abcdef0123456789abcdef/system@0123456789abcdef0123456789abcdef-0000000000e043b9-0005aad981c2d167.journal
/var/log/journal/0123456789abcdef0123456789abcdef/system@0123456789abcdef0123456789abcdef-00000000010d9bf1-0005ac875e1241e7.journal

鑑於前者,我如何找到後者?

日誌文件不按單位排序。發布日誌條目的單元只是與條目相關聯的元數據。日誌文件也不總是在/var. /run如果配置為非持久,它們也可以在中找到。

為特定單位提取日記帳分錄的正確方法是使用journalctl -u <unit_name>或使用sd-journalAPI。此外,日誌是一個二進製文件,因此它的格式並不完全適合解析。我什至不確定期刊的內部格式是否遵循穩定的規範。 journalctl或者 API 絕對是讀取這些文件的方式。

如果您詢問此問題是為了備份(或發送故障排除)特定文件,則需要將所有這些文件視為一個單元。


由於您專門詢問了這些日誌文件的文件命名約定,因此我花了一些時間對此進行了調查。重新啟動後,唯一的文件/run/log/journal/run/log/journal/c13e4a2f54334a95891a6a471db3b7e0/system@edd0c14e44a240038601194807d5c28e-0000000000000001-0005b08ccb2c37b3.journal.

我將其分解為以下內容以嘗試理解命名約定:

/run/                                  <-- run/var
 log/journal/                         <-- standard location 
   c13e4a2f54334a95891a6a471db3b7e0/  <-- _MACHINE_ID
   system@                            <-- system/user
   edd0c14e44a240038601194807d5c28e-  <-- Some bus/boot/session ID?
   0000000000000001-                  <-- Sequence number (also looks like offsets as 4-KB blocks in hex)
   0005b08ccb2c37b3                   <-- Timestamp (time since epoch in hex)
   .journal                           <-- Extension

當我看一台已經執行了一段時間的機器時,所有system@*.journal文件都是80M,而所有user@*.journal文件都是8.​​0M。有瞭如此一致的大小,它確實表明文件拆分只是日誌輪換。我還可以通過查看修改日期來確認這一點(隨著我們按順序進行,我看到日期在增加)。


為了弄清楚其中的一些事情(例如_MACHINE_ID),我必須查看與日記條目相關的原始元數據。元數據比你能得到的要多journalctl。我用 sd-journal API 編寫了一個快速程序並"Hello"從服務中列印出來。我在日記中找到了它,並附有以下數據。令人驚訝的是,每個printf.

_UID=0
_GID=0
_CAP_EFFECTIVE=3fffffffff
_TRANSPORT=stdout
_STREAM_ID=2ee82c395817429b975770acb1306d11
SYSLOG_IDENTIFIER=counter
_PID=6523
_COMM=counter
_EXE=/usr/local/bin/counter
_CMDLINE=/usr/local/bin/counter
_SYSTEMD_CGROUP=/system.slice/counter.service
_SYSTEMD_UNIT=counter.service
_SYSTEMD_INVOCATION_ID=711962f5d7bf487b9a262b824c297a42
MESSAGE=Hello
PRIORITY=6
SYSLOG_FACILITY=3
_BOOT_ID=bf0d96cbab2144e3a8544b0e8a0eacc6
_MACHINE_ID=c13e4a2f54334a95891a6a471db3b7e0
_HOSTNAME=simswe24
_TRANSPORT=journal
_SELINUX_CONTEXT=unconfined

如果您對我編寫的用於調查此問題的 sd-journal 程序感興趣,它就在這裡:

// Compile with `gcc journalctl.c -lsystemd`
#include <systemd/sd-journal.h>
#include <stdio.h>
int main()
{
   // Open the log
   sd_journal* journal;

   if ( sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY) < 0 )
   {
       return 1; // Couldn't open journal
   }

   // Subscribe to specific logs:
   // Messages from the service itself
   int r = sd_journal_add_match(journal, "_SYSTEMD_UNIT=counter.service", 0);
   r = r ? r : sd_journal_add_disjunction(journal);
   
   // Messages from PID 1 (systemd) about this service
   r = r ? r : sd_journal_add_match(journal, "_PID=1", 0);
   r = r ? r : sd_journal_add_match(journal, "UNIT=counter.service", 0);
   r = r ? r : sd_journal_add_disjunction(journal);

   if ( r < 0 )
   {
       return 1; // Could not subscribe to all journal entries
   }

   r = sd_journal_seek_head(journal);
   if ( r < 0 )
   {
       return 1; // Problem finding the head of the log
   }


   // Read the log
   int skip_seek=1;
   while( skip_seek || (sd_journal_next(journal) > 0 ) ) 
   {
       const void* data = 0;
       size_t length;
       skip_seek = 0;

       sd_journal_restart_data(journal);

       SD_JOURNAL_FOREACH_DATA(journal, data, length)
       {
           printf("%s\n", data);
       };
   }

   sd_journal_close(journal);

   return 0;
}

引用自:https://unix.stackexchange.com/questions/612250