首页 > 其他分享 >高效日志管理:通过 Systemd Journal 收集日志的终极指南

高效日志管理:通过 Systemd Journal 收集日志的终极指南

时间:2024-05-30 16:34:39浏览次数:20  
标签:Systemd LOG int journal systemd Hello 日志 Journal

随着 systemd 成了主流的 init 系统,systemd 的功能也在不断的增加,比如对系统日志的管理。Systemd 设计的日志系统好处多多,这里笔者就不再赘述了,本文笔者主要介绍 systemd journal 收集日志的三种方式:

  • 程序使用 libc 库中的 syslog() 函数输出的日志

  • 使用 printf() 函数打印的日志

  • 任何服务进程输出到 STDOUT/STDERR 的所有内容

说明:本文的演示环境为 ubuntu 16.04。

syslog()

该函数的声明如下:

#include <syslog.h>void syslog(int priority, const char *message, ... /* argument */);

创建下面的 C 语言代码,并保存到文件 clog.c 文件中:

#include <syslog.h>
int main(int argc, char *argv[]) { syslog(LOG_NOTICE, "C Hello World"); return 0;}

用下面的命令编译程序:

$ gcc -Wall clog.c -o clog

然后执行编译好的 clog 程序,就可以从 journal -f 的输出中看到对应的日志:

图片

这里笔者执行了三次 clog 程序,所以日志输出了三遍。
代码中的 LOG_NOTICE 代表日志的严重等级,我们可以使用下面定义好的等级:


#define    LOG_EMERG    0    /* system is unusable */#define    LOG_ALERT    1    /* action must be taken immediately */#define    LOG_CRIT    2    /* critical conditions */#define    LOG_ERR        3    /* error conditions */#define    LOG_WARNING    4    /* warning conditions */#define    LOG_NOTICE    5    /* normal but significant condition */#define    LOG_INFO    6    /* informational */#define    LOG_DEBUG    7    /* debug-level messages */

 

下面尝试在 python 代码中做同样的事情,把下面的代码保存到文件 plog.py 中:


#!/usr/bin/evn python
import syslogsyslog.syslog('P Hello World')

然后执行下面的命令:

$ python plog.py

图片

笔者同样执行了三遍,这次输出的是 python 代码中的日志。

我们还可以通过 journalctl -o json-pretty -f 命令查看 json 格式的日志:

图片

printf()

journal 可以捕获服务进程往 STDOUT/STDERR 输出的所有内容,比如 C 语言中 print 函数打印的内容,Python 中 print 打印的内容,以及 Shell 脚本中 echo 打印的内容等等都可以被 journal 捕获到并加入到日志中。注意,只有以 service 的方式运行程序时,journal 才会捕获 STDOUT/STDERR 输出的内容。
创建下面的 C 语言代码,并保存到文件 printlog.c 文件中:

#include <stdio.h>
int main(int argc, char *argv[]) { printf("C Print Hello World.\n"); return 0;}

用下面的命令编译程序:

$ gcc -Wall printlog.c -o printlog

配置一个简单的 service,先创建 一个配置文件  /lib/systemd/system/testlog.service,其内容如下:


[Unit]Description=test log
[Service]ExecStart=/home/nick/projects/journaldemo/printlog
[Install]WantedBy=multi-user.target

 

$ sudo systemctl daemon-reload$ sudo systemctl start testlog.service

Journal 会捕获 STDOUT/STDERR 输出的内容:

图片

默认情况下,这样输出的日志等级为 LOG_INFO(6),我们可以通过 json 格式的日志看到日志等级信息:

图片

我们还可以在打印日志时指定日志的等级,比如在每行打印的内容前加上"<N>",N为需要指定的日志等级。看下面的 C 语言示例:

#include<stdio.h>
#define PREFIX_NOTICE "<5>"
int main(void){ printf(PREFIX_NOTICE "Hello World\n"); fprintf(stderr, "<3>Hello Error\n");
return 0;}

把上面的代码编译为 printlog 程序,再查看下日志,显示的就是我们自己设置的日志等级:

图片

在 Python 中的用法如下:


#!/usr/bin/env pythonprint '<5>Hello World'

在 bash 中的用法如下:

#!/bin/bashecho "<5>Hello World"

Systemd 日志库

Systemd 提供了原生的 C 语言库(systemd/sd-journal.h) 用于向 journal 输出日志(ubuntu 16.04 需要通过 sudo apt install libsystemd-dev 命令安装 libsystemd-dev 包),相关函数的声明为:

#include <systemd/sd-journal.h>int sd_journal_print(int priority, const char *format, ...);int sd_journal_send(const char *format, ...);

把下面的示例代码会把日志发送给 journal:

#include <systemd/sd-journal.h>
int main(int argc, char *argv[]) { sd_journal_print(LOG_NOTICE, "Hello World"); return 0;}

相比上文使用 print() 或者 syslog() 提交的日志,使用 sd_journal_print 可以直观的指定 LOG 等级、日志内容等等,另外输出的日志会包含执行代码的位置信息,例如执行到的函数,代码文件位置,代码具体行数,方便开发人员调试。

除了可以包含代码信息,也可以向提交的日志中加入自定义段包含更多自定义信息,配合 journalctl 工具,可以更方便的过滤日志,如下面的代码:

 

#include <systemd/sd-journal.h>#include <unistd.h>#include <stdlib.h>
int main(int argc, char *argv[]) { sd_journal_send("MESSAGE=Hello World!", "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555", "PRIORITY=5", "HOME=%s", getenv("HOME"), "TERM=%s", getenv("TERM"), "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE), "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), NULL); return 0;}

 

我们在日志中添加了自定义的字段,并且可以通过 journalctl 过滤这些字段。

除了 systemd 提供的一套C语言库,目前其他个别语言也衍生了 systemd 的相关扩展,其中就包含了和 journald 相关的扩展。下面是段 python 的演示代码:


from systemd import journaljournal.send('Hello world')journal.send('Hello, again, world', FIELD2='Greetings!', FIELD3='Guten tag')

在运行上面的代码前你需要先通过 pip 安装 python 的 systemd 模块(pip install systemd ),然后运行这段代码,你就可以从日志中看到它输出的信息了:

图片

展开成 json 格式看下:

图片

我们自定义的字段 FIELD2 和 FIELD3 也都输出到日志中了。

总结

本文介绍了常见的一些往 systemd journal 中写入日志的方式,了解这些日志的写入方式可以帮助我们更好的设计应用的日志输出,并有助于我们通过日志解决问题。

链接:https://www.cnblogs.com/sparkdev/p/10509938.html

标签:Systemd,LOG,int,journal,systemd,Hello,日志,Journal
From: https://www.cnblogs.com/testzcy/p/18222623

相关文章

  • 阿里云日志搜索
    阿里云日志搜索(SLS日志搜索)查找多个关键词,使用and逻辑:content:"关键词1"andcontent:"关键词2"使用or逻辑:content:"关键词1"orcontent:"关键词2"模糊查询:在关键词后面使用星号,可以模糊查询。如果关键词后面带有一些中文符号,也可以用星号代替。"关键词*"......
  • JVM GC日志分析之日志参数
    不同的垃圾收集器(参考JVM垃圾收集器分类),输出的日志格式各不相同,但也有一些相同的特征。熟悉各个常用垃圾收集器的GC日志,是进行JVM调优的必备一步。解析GC日志,首先需要收集日志(参考https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#enable-logging-wi......
  • 一文搞懂 MySQL 日志
    前言MySQL的日志记录了运行的各种信息,是MySQL事务、性能、数据容灾、异常排查等的基础。本文将介绍MySQL一些关键日志的作用和原理。MySQLInnoDB引擎重要的三个日志:日志说明redolog重做日志,保证事务的持久性undolog回滚日志,来保证事务的原子性binlo......
  • python基础 - 异常与日志
    异常----异常1:try:print(1/0)#try里放的是被检测的语句块exceptZeroDivisionErrorase:#处理异常的语句块print('除数不能为0')#自定义的异常print(e)#系统自带的异常----异常2:try:num=int(input('请输入一个数:‘))print(1/num)exceptZeroDivisionError:print(‘除数不能......
  • linux定时删除历史日志
    在Linux系统中,日志文件是记录系统、应用程序或服务的运行信息、错误消息和警告的重要工具。然而,随着时间的推移,这些日志文件会不断积累,占用大量的磁盘空间。如果不及时清理,可能会导致磁盘空间不足,从而影响系统的正常运行。因此,定时删除历史日志成为了Linux系统管理中不可或缺的......
  • 【ubuntu】使用split切割大的日志文件
    1、问题场景  太慢了  2、命令split-b500mtest.DEBUG.BAKtest.DEBUG.BAK_ 3、命令帮助$split--help用法:split[选项]...[文件[前缀]]将<文件>拆分并输出到"前缀aa"、"前缀ab"等文件;默认以1000行为拆分单位,默认<前缀>为"x"。如果没有指定......
  • python提取日志中访问IP信息+去重+汇总
    实现功能:1、提取日志文件中所有源IP2、对提取到的IP进行去重3、统计每个IP的访问次数4、输出到csv文件代码如下:importrefilter=r'"\s"(\d{1,3}(?:\.\d{1,3}){3})"\s'#使用正则表达式来匹配IP地址log_path="D:/你的日志文件位置.txt"withopen(l......
  • Sirupsen/logrus是一个日志库
    Golang:Sirupsen/logrus是一个日志库原创吃个大西瓜CodingBigTree2024-05-2808:00北京听全文图片 Sirupsen/logrus是一个日志库 文档 https://github.com/Sirupsen/logrus安装 gogetgithub.com/sirupsen/logrus代码示例 packagemain import( ......
  • nginx日志按天分割
    原帖是这样的:nginx日志分割是比较常见的运维工作,关于这方面的文章也很多,通常无外乎两种做法:cron定期执行shell脚本对日志文件进行归档。使用专门日志归档logrotate。以上方式与nginx其实没有特别的关系。从nginx0.7.6版本开始,access_log的路径配置可以包含变量,我们以此......
  • SpringBoot如何使用日志Logback,及日志等级详解
    SpringBoot默认已经集成了SLF4J(SimpleLoggingFacadeforJava)作为日志的接口,以及Logback作为日志的实现。这意味着在大多数情况下,你无需做额外的配置即可开始记录日志。下面是一个简要的指南,包括如何在SpringBoot应用中使用SLF4J和Logback,以及一些实际的代码示例。默......