systemd ã®ç®¡çãããã°ã¯ /var/log/journal ã¾ã㯠/run/log/journal 以ä¸ã«åºåããã¦ãã¾ããããããã®ãã°ã¯ç¬èªã®ãã¤ããªå½¢å¼ã§ä¿åããã¦ãããããããã°ã©ã ãããã°ãèªã¿ããå ´åã¯ä»¥ä¸ã®ãããªæ段ãçµãå¿ è¦ãããã¾ãã
- journalctl -o export ã§Journal Export Formatã¨ãã¦ãã°ãèªã
- systemd-journal-gatewayd.serviceãçµç±ãã¦Journal JSON Formatã¨ãã¦ãã°ãèªã
- Native C API(sd-journal)ã使ã£ã¦ãã°ãèªã
å ¬å¼ã«Journal File Formatã¨ããããã¥ã¡ã³ãã§ãã¤ããªå½¢å¼ã®ãã©ã¼ãããä»æ§ãèªãã¾ãããããã¥ã¡ã³ãã®æåã«
Or, to put this in other words: this low-level document is probably not what you want to use as base of your project. You want our C API instead! And if you really don't want the C API, then you want the Journal Export Format instead! This document is primarily for your entertainment and education.
ã®ããã«æ¸ããã¦ãã¦ããã¤ããªãã°ãç´æ¥èªããã¨ã¯æ¨å¥¨ããã¦ãã¾ãããããã§ããã®è¨äºã§ã¯ sd-journal ã¨ããCã®ã©ã¤ãã©ãªã使ã£ã¦ã¸ã£ã¼ãã«ãèªãå®è£ ãç´¹ä»ãã¾ããããã§ã¯Cã使ã£ã¦ãã¾ãããGoããcgoã使ã£ã¦ãããã§ãããä»ã®è¨èªããCãå¼ã³åºãã¨ãã«ãåèã«ãªãã§ãããã
ã³ã¼ãã®ã³ã³ãã¤ã«æ¹æ³
Cã³ã³ãã¤ã©ã«ã¯ãªã³ã¯ããã©ã¤ãã©ãªãä¸ãããã©ã°ãããã¨æãã®ã§ããã㧠libsystemd ãæå®ãã¦ãã ããã
$ gcc -lsystemd -o journalread main.c
è¤æ°ã®ã¢ã¼ããã¯ãã£ç¨ã«ã¯ãã¹ã³ã³ãã¤ã«ããå ´åã¯GitHub Actionsã§Cè¨èªã®ã³ã¼ããã¯ãã¹ã³ã³ãã¤ã«ãããèªãã§ãã ããã
ãã°ãèªã
ãã¡ã¤ã«ã¨åæ§ã«ãã¸ã£ã¼ãã«ãã°ãèªãã¨ãã¯ãã°ãéãæç¶ããå¿ è¦ã§ãã
#include <systemd/sd-journal.h> int main(void) { sd_journal *j; if(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM) < 0) fatal("failed to open journal: %m\n"); /* ããã« j ãæä½ãã¦ãã°ãèªãããã®ã³ã¼ããæ¸ã */ sd_journal_close(j); return 0; }
sd_journal_openã«æ¸¡ãã¦ãã SD_JOURNAL_LOCAL_ONLY ãã©ã°ã¯ /var/log/journal 以ä¸ãåç §ãããã©ã°ã§ãã/run/log/journal 以ä¸ãåç §ããããã® SD_JOURNAL_RUNTIME_ONLY ãã©ã°ãããã¾ãã
ããã²ã¨ã¤ãSD_JOURNAL_SYSTEM ãã©ã°ã渡ãã¨ã·ã¹ãã ãµã¼ãã¹ãã«ã¼ãã«ã®ãã°ã対象ã¨ãã¾ããã¦ã¼ã¶ã¼ãµã¼ãã¹ã®ãã°ãæ±ãããã® SD_JOURNAL_CURRENT_USER ãã©ã°ãããã¾ããjournalctl ã³ãã³ãã§ããã°ããããã --system ãªãã·ã§ã³ã¨ --user ãªãã·ã§ã³ã«ç¸å½ãã¾ãã
ãã°ãèªã¿é²ãã
1è¡ãã¤ãã°ãèªãã¨ãã¯sd_journal_nextã¨sd_journal_get_dataã使ãã¾ãã
int rv, e; char *s, *m; size_t n; sd_journal_set_data_threshold(j, 0); while((rv=sd_journal_next(j)) > 0){ e = sd_journal_get_data(j, "MESSAGE", (void*)&s, &n); if(e == -ENOENT) /* ãã£ã¼ã«ããç¡ãå ´åã¯ENOENTãè¿ã */ continue; if(e < 0) fatal("failed to get MESSAGE: code=%d\n", -e); /* s㯠"MESSAGE=xxx" ã®ããã«ãã£ã¼ã«ãåãå«ãã§ããã®ã§8æåé£ã°ã */ printf("message = %*s\n", n-8, s+8); } if(rv < 0) fatal("failed to move next: %m\n");
ããã©ã«ãè¨å®ã®å ´åãsd_journal_get_data ã¯64KBãè¶ããé·ãã®ããã¹ããéä¸ã§åãè©°ãã¾ããåãè©°ãããµã¤ãºãå¤æ´ãããå ´å㯠sd_journal_set_data_threshold ã§ä¸éã¨ãªããµã¤ãºãè¨å®ãã¾ãã0ãè¨å®ããã¨ç¡å¶éã¨ãªãã¾ãã
ãã¨ã¯ sd_journal_next ã§ã«ã¼ã½ã«ãé²ãã¦ãsd_journal_get_data ã§ã«ã¼ã½ã«ä½ç½®ã®ãã°ãèªããã¨ã«ãªãã¾ããããã®ã¨ã1ã¤ã®ãã°ã«ã¯è¤æ°ã®ãã£ã¼ã«ããåå¨ãã¦ãã¾ããä¾ãã°ä»¥ä¸ã®ãããªç¨éã§ãã£ã¼ã«ããããã¾ãã
- MESSAGE: ãã°åºåããã¡ãã»ã¼ã¸ãã®ãã®
- PRIORITY: 1(alert)ã6(info)ã®ãããªã¨ã©ã¼ã¬ãã«ã®æ°å¤ã0ãæé«ã§7ãæä½
- UNIT: ãã°ãçºè¡ããã¦ãããå
- _SYSTEMD_UNIT: ãã°ãçºè¡ããã¦ãããå
ãã®ãããªãã£ã¼ã«ãåãæå®ãã¦ããã°ããå¿ è¦ãªãã¼ã¿ãèªãã§ããã¾ãããã®ã¨ããsd_journal_get_data ãè¿ãããã¼ã¿ã¯ã次㮠sd_journal_next ã§ä¸æ¸ãããã¦ãã¾ãã®ã§ãå¥ã®å ´æã§åç §ãããå ´åã¯èªåã§ã³ãã¼ãä½ããªããã°ããã¾ããããã£ã¼ã«ãåã¯ä¸è¨ã®ä»ã«ããã£ã±ãããã®ã§ã詳細ã¯systemd.journal-fieldsã®ããã¥ã¢ã«ãè¦ã¦ãã ããã
sd_journal_get_data ãè¿ãã¨ã©ã¼ã®ç¨®é¡ã詳細ã¯ããã¥ã¢ã«ã«æ¸ããã¦ãã¾ãã
ååãã¢ã³ãã¼ã¹ã³ã¢(_)ã§å§ã¾ããã£ã¼ã«ã
ã¢ã³ãã¼ã¹ã³ã¢ã1ã¤ã ãã®å ´åããã®ãã£ã¼ã«ã㯠systemd ã«ãã£ã¦ä¿è·ããããã£ã¼ã«ãã§ãããããã®å¤ã¯ã¦ã¼ã¶ã¼ã®ã³ã¼ãããå¤æ´ã§ãã¾ããã
ã¢ã³ãã¼ã¹ã³ã¢ã2ã¤ç¶ãã¦ããå ´åããã°ã®ã¢ãã¬ã¹ãã·ãªã¢ã©ã¤ãºãããã®ãæå³ãã¾ãããããã®ãã£ã¼ã«ãã¯ã以ä¸ã§ç´¹ä»ãããã£ã«ã¿ã®æ¡ä»¶ã«ã¯ä½¿ãã¾ããã
è²ã ãªUNITãã£ã¼ã«ã
ã¨ããã§ãä¸ã§ UNIT 㨠_SYSTEMD_UNIT ãæãã¾ããããå¤ãã®systemãµã¼ãã¹ã§ã¯
_SYSTEMD_UNIT=dbus-broker.service
ã¨ã ãè¨å®ããããã®ãå¤ãã®ã§ãããã©ã[email protected] ã®å ´åã¯
_SYSTEMD_UNIT=init.scope [email protected]
ã®ããã«2ã¤è¨å®ããã¾ããã¾ããpipewire.service ã®å ´åã¯ã
[email protected] _SYSTEMD_USER_UNIT=pipewire.service
ã¨ãªãã¾ããæå¾ã« user ãµã¼ãã¹ã® gvfs-metadata.service ãè¨é²ãããã°ã¨ã³ããªã¯
[email protected] _SYSTEMD_USER_UNIT=init.scope USER_UNIT=gvfs-metadata.service
ã§ãã欲ããã¦ãããåãã©ãã«åºç¾ãããã確èªããããã§ãã£ã¼ã«ããèªããã¨ããããããã¾ãã
ã«ã¼ã½ã«ä½ç½®ãè¨æ¶ãã
ã«ã¼ã½ã«ã¯sd_journal_get_cursorã§åå¾ã§ãã¾ãã
char *cursor; if(sd_journal_get_cursor(j, &cursor) < 0) fatal("failed to get cursor: %m\n");
ããã§åå¾ããã«ã¼ã½ã«ã¯ãã ã®æååãªã®ã§ããã®ã¾ã¾ãã¡ã¤ã«ã«ä¿åããã°ããã§ãããã次ã®å®è¡ã§ã«ã¼ã½ã«ä½ç½®ã¾ã§ç§»åãããå ´åã¯sd_journal_seek_cursorã§ç§»åãã¾ãã
if(sd_journal_test_cursor(j, cursor) < 0) fatal("invalid cursor: %m\n"); if(sd_journal_seek_cursor(j, cursor) < 0) fatal("failed to seek to the cursor: %m\n");
注æç¹ã¨ãã¦ãã«ã¼ã½ã«ã移åããã ãã§ã¯ãã°ã¨ã³ããªã®èªã¿è¾¼ã¿ããã¦ããªãã®ã§ sd_journal_get_data çã使ãã¾ããããªã®ã§ç§»åããå¾ã¯å¿ ã sd_journal_next ã¾ãã¯åçã®å¦çãè¡ãã¾ããããã¾ããããã§èªãããã°ã¯ãsd_journal_get_cursor ãåå¾ããæç¹ã®ãã°ãã¨åããã®ã§ãããªã®ã§ãã«ã¼ã½ã«ã®æ¬¡ã«æ¸ããããã°ããèªã¿ããå ´å㯠sd_journal_next ã2åå¿ è¦ã§ãã
ãã°ããã£ã«ã¿ãã
sd_journal_get_data ã§ãã£ã¼ã«ããåå¾ãã¦ããããã°ã©ã ä¸ã§ãã£ã«ã¿ãã¦ãããã®ã§ãããsd-journal ã«ã¯sd_journal_add_matchã¨ããã©ã¤ãã©ãªå´ã§ãã£ã«ã¿ãã¦ãããä»çµã¿ãç¨æããã¦ãã¾ãã
/* ã¨ã©ã¼ã®å ´åã¯è² æ°ãè¿ãã¾ãããããã§ã¯ã¨ã©ã¼å¦çãçç¥ãã¾ã */ sd_journal_add_match(j, "SYSLOG_FACILITY=9", 0); sd_journal_add_match(j, "PRIORITY=5", 0); sd_journal_add_match(j, "PRIORITY=6", 0);
ã¨ã¦ãã·ã³ãã«ãªé¢æ°ãªãã§ãããåä½ã¯é常ã«é£è§£ã§ãããã®é¢æ°ãè¤æ°åå®è¡ããå ´åã¯æ¬¡ã®ã«ã¼ã«ã«å¾ãã¾ãã
- ç°ãªããã£ã¼ã«ãã®æ¡ä»¶ãä¸ããã¨ããããã AND ã¨ãã¦çµåãã
- åããã£ã¼ã«ãã®æ¡ä»¶ãããã°ããããããæãé«ãåªå é ä½ã® OR ã§çµåãã
- å®å ¨ã«åãæ¡ä»¶ã¯1ã¤ã«ã¾ã¨ãã
ãããä¸ã®ã³ã¼ãã«å½ã¦ã¯ããã¨ã次ã®ããã«è§£éã§ãã¾ãã
SYSLOG_FACILITY=0 AND (PRIORITY=0 OR PRIORITY=1)
ä»»æã®ORæ¡ä»¶ã追å ãã
ãã㧠sd_journal_add_disjunction ãå¼ã³åºãã¨ãããã¾ã§ã«æ§ç¯ããå¼ã OR ã§ç¹ãã¦ãæ°ããå¼ã®æ§ç¯ãéå§ãã¾ãã
sd_journal_add_disjunction(j);
çµæã¯æ¬¡ã®ãããªå¼ã«ãªãã¾ãã
( SYSLOG_FACILITY=9 AND (PRIORITY=5 OR PRIORITY=6) ) OR ( -- ã¾ã ä½ããªããã以ésd_journal_add_matchããã¨ããã«å ¥ã )
SYSLOG_FACILITY=0 ã追å ãã¦ã¿ã¾ãããã
sd_journal_add_match(j, "SYSLOG_FACILITY=0", 0);
çµæã§ãã
( SYSLOG_FACILITY=9 AND (PRIORITY=5 OR PRIORITY=6) ) OR ( SYSLOG_FACILITY=0 -- 次ã«sd_journal_add_matchããã¨ãããã«æ°ããå¼ã追å ããã )
ä»»æã®ANDæ¡ä»¶ã追å ãã
æå¾ãsd_journal_add_conjunction 㧠AND æ¡ä»¶ã追å ãã¾ããOR ãããåªå é ä½ãé«ãã®ã§ããã大ããªç¯å²ã§ AND ãæ§ç¯ãã¾ãã
sd_journal_add_conjunction(j); sd_journal_add_match(j, "_SYSTEMD_UNIT=systemd-timesyncd.service", 0);
æçµçãªãã£ã«ã¿å¼ã§ãã
( ( SYSLOG_FACILITY=9 AND (PRIORITY=5 OR PRIORITY=6) ) OR ( SYSLOG_FACILITY=0 ) ) AND ( ( _SYSTEMD_UNIT=systemd-timesyncd.service -- 次ã«sd_journal_add_matchããã¨ãããã«æ°ããå¼ã追å ããã ) -- 次ã«sd_journal_disjunctionããã¨ãããã«æ°ããORå¼ã追å ããã ) -- 次ã«sd_journal_conjunctionããã¨ãããã«æ°ããANDå¼ã追å ããã