随着 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 ;
}

用下面的命令编译程序:

$ 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 syslog
syslog.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 ;
}

用下面的命令编译程序:

$ 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 ;
}

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

在 Python 中的用法如下:

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

在 bash 中的用法如下:

#!/bin/bash
echo "<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 ;
}

相比上文使用 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 ;
}

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

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

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

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

展开成 json 格式看下:

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

总结

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

参考:
Systemd 日志管理相关
systemd for Developers III

通过 Systemd Journal 收集日志的更多相关文章

  1. Linux 系统 /var/log/journal/ 垃圾日志清理

    CentOS系统中有两个日志服务,分别是传统的 rsyslog 和 systemd-journal systemd-journald是一个改进型日志管理服务,可以收集来自内核.系统早期启动阶段的日志. ...

  2. ELK收集日志到mysql

    场景需求 在使用ELK对日志进行收集的时候,如果需要对数据进行存档,可以考虑使用数据库的方式.为了便于查询,可以同时写一份数据到Elasticsearch 中. 环境准备 CentOS7系统: 192 ...

  3. ELK快速入门(二)通过logstash收集日志

    ELK快速入门二-通过logstash收集日志 说明 这里的环境接着上面的ELK快速入门-基本部署文章继续下面的操作. 收集多个日志文件 1)logstash配置文件编写 [root@linux-el ...

  4. ELK快速入门(四)filebeat替代logstash收集日志

    ELK快速入门四-filebeat替代logstash收集日志 filebeat简介 Filebeat是轻量级单用途的日志收集工具,用于在没有安装java的服务器上专门收集日志,可以将日志转发到log ...

  5. ELK收集日志到mysql数据库

    场景需求 在使用ELK对日志进行收集的时候,如果需要对数据进行存档,可以考虑使用数据库的方式.为了便于查询,可以同时写一份数据到Elasticsearch 中. 环境准备 CentOS7系统: 192 ...

  6. nginx日志切割并使用flume-ng收集日志

    nginx的日志文件没有rotate功能.如果你不处理,日志文件将变得越来越大,还好我们可以写一个nginx日志切割脚本来自动切割日志文件.第一步就是重命名日志文件,不用担心重命名后nginx找不到日 ...

  7. 使用开源软件sentry来收集日志

    原文地址:http://luxuryzh.iteye.com/blog/1980364 对于一个已经上线的系统,存在未知的bug或者运行时发生异常是很常见的事情,随之而来的几点需求产生了: 1.系统发 ...

  8. nswl 收集日志

    nswl 收集日志 参考链接:https://docs.citrix.com/en-us/citrix-adc/12-1/system/web-server-logging.html PS C:\Us ...

  9. rancher使用fluentd-pilot收集日志分享

    fluentd-pilot简介 fluentd-pilot是阿里开源的docker日志收集工具,Github项目地址:https://github.com/AliyunContainerService ...

随机推荐

  1. Spring Data Redis 让 NoSQL 快如闪电(2)

    [编者按]本文作者为 Xinyu Liu,文章的第一部分重点概述了 Redis 方方面面的特性.在第二部分,将介绍详细的用例.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 把 Redis ...

  2. 原型模式ProtoType

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/3/4 21:49 # @Author : ChenAdong # @emai ...

  3. python--私有属性--私有方法

    Class 定义类 def 初始化方法(形参) 属性1 属性2   私有属性(属性之前加--) def  方法1() print() 属性和方法定义好以后,在创建对象 对象=类名(“”) print( ...

  4. stored information about method csdn

    Eclipse编译时保留方法的形参 Window -> Preferences -> Java -> Compiler. 选中Store information about meth ...

  5. numpy中stack、hstack,vstack,dstack函数功能解释

    https://blog.csdn.net/Riverhope/article/details/78922006 https://blog.csdn.net/ygys1234/article/deta ...

  6. C++实现第三方资源释放与载入过程(以DLL为例)

    简介 我们经常看见有一些程序开始执行时会释放一些文件,以便于后续操作.例如一些病毒为了便于传播和隐藏,经常把一些需要用的动态库或是驱动文件打包进一个可执行文件中,再由需要使用的时候,再临时释放和加载. ...

  7. PHP使用Apache中的ab(ApacheBench)测试网站的并发量

    AB(ApacheBench) 是 Apache 自带的超文本传输协议 (HTTP) 性能测试工具. 其设计意图是描绘当前所安装的 Apache 的执行性能, 主要是显示 Apache 每秒可以处理多 ...

  8. IntelliJ IDEA 创建Spring+SpringMVC+mybatis+maven项目

    参考自:https://www.cnblogs.com/hackyo/p/6646051.html 第一步: 创建maven项目 输入项目名和工程id 选择maven 默认就可以了 刚开始时间比较长, ...

  9. Linux for Python教程01

    目录 1. Linux和操作系统 1.1. 什么是操作系统 1.2. 现有操作系统 1.3. Linux用户目录 1.4. Linux文件权限 2. Linux命令 2.1 文件管理相关 (1).ls ...

  10. 【Teradata】数值类型

     1.Decimal(n,m) 十进位小数 n为最大数值位数(取值1-38),m为小数位数(取值0-n). decimal(3,2)    -9.99 to 9.99 decimal(4,4)   - ...