Linux中的日志系统简介

在的Linux系统上使用的日志系统一般为rsyslogdrsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志。用户进程是通过调用syslog函数生成系统日志的。该函数将日志输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中,rsyslogd则监听该文件以获取用户进程的输出。

一、日志的输出

1.1、打开日志

#include <syslog.h>

void openlog(const char* ident, int logopt, int facility);
  • ident参数指定的字符串将被添加到每条日志消息的开头,以便于识别消息的来源,通常是程序名称

  • logopt参数对后续syslog调用的行为进行配置,它可取下列值的按位或:

    •   #define LOG_PID 0x01/*在日志消息中包含程序PID*/
        #define LOG_CONS 0x02/*如果消息不能记录到日志文件,则打印至终端*/
        #define LOG_ODELAY 0x04/*延迟打开日志功能直到第一次调用syslog*/
        #define LOG_NDELAY 0x08/*不延迟打开日志功能*/
      
  • facility 参数可用来修改syslog函数中的默认设施值

    • LOG_USER:用户级别的消息。

    • LOG_MAIL:邮件系统。

    • LOG_DAEMON:系统守护进程。

    • LOG_AUTH:安全/授权消息。

    • LOG_SYSLOG:由syslogd(8)内部生成的消息。

1.2、打印日志

#include <syslog.h>

void syslog(int priority, const char* message, ...);
  • priority参数是设施值与日志级别的按位或

    • 设施值的默认值是LOG_USER,基本也只用到这一种

    • 日志级别有如下几个:

    •   #include <syslog.h>
        
        #define LOG_EMERG 0/*系统不可用*/
        #define LOG_ALERT 1/*报警,需要立即采取动作*/
        #define LOG_CRIT 2/*非常严重的情况*/
        #define LOG_ERR 3/*错误*/
        #define LOG_WARNING 4/*警告*/
        #define LOG_NOTICE 5/*通知*/
        #define LOG_INFO 6/*信息*/
        #define LOG_DEBUG 7/*调试*/
      
  • format:一个格式字符串,类似于 printf 函数中的格式字符串。它指定了如何格式化后续参数

1.3、关闭日志

#include <syslog.h>

void closelog();

1.4、设置日志掩码

程序在开发阶段可能需要输出很多调试信息,而发布之后我们又需要将这些调试信息关闭。解决这个问题的方法并不是在程序发布之后删除调试代码(因为日后可能还需要用到),而是简单地设置日志掩码,使日志级别大于日志掩码的日志信息被系统忽略。下面这个函数用于设置syslog的日志掩码:

#include <syslog.h>

int setlogmask(int maskpri);

maskpri参数指定日志掩码值。该函数始终会成功,它返回调用进程先前的日志掩码值。

二、日志的保存

rsyslogd守护进程在接收到用户进程或内核输入的日志后,会把它们输出至某些特定的日志文件。常见日志文件

/var/log/debug:调试信息
/var/log/btmp:记录登录失败的用户信息、时间及远程 ip
/var/log/cron:记录 crontab 执行情况
/var/log/kern.log:内核消息
/var/log/dmesg :开机自检信息
/var/log/lastlog:记录最后一次登录的时间、IP 等信息
/var/log/maillog:记录邮件收发详细信息
/var/log/wtmp:永久记录所有用户的登陆、注销信息,同时记录系统的后动、重启、关机事件
/var/log/messages:记录内核消息及各种应用程序的日志信
/var/log/secure:系统安全日志,记录用户登录认证情况,如 pop3、ssh、telnet、ftp 等记录
/var/run/utmp:记录当前登录的用户信息

三、日志的配置

内核日志由printk函数打印至内核的环状缓存中。缓存直接映射到/proc/kmsg文件中。rsyslogd则通过读取该文件获得内核日志。

用户日志则是调用 syslog 函数,向文件 /dev/log中写入信息,rsyslogd则通过读取该文件获得用户日志。

NeatReader-1713100850831

日志信息具体如何分发,可以在rsyslogd的配置文件中设置。rsyslogd的主配置文件是/etc/rsyslog.conf

主要可以设置的项包括:内核日志输入路径,是否接收UDP日志及其监听端口(默认是514,见/etc/services文件),是否接收TCP日志及其监听端口,日志文件的权限,包含哪些子配置文件(比如/etc/rsyslog.d/*.conf)。rsyslogd的子配置文件则指定各类日志的目标存储文件。

3.1、修改日志默认输出文件

/etc/rsyslog.conf文件末尾添加:

if $programname == 'httpp' then /var/log/httpp
& stop
  • if $programname == 'httpp' then /var/log/httpp:如果日志消息的程序名($programname)是'httpp',那么将该消息写入/var/log/httpp文件。
  • & stop:执行完上述写入操作后,停止对这条消息的进一步处理。

修改完配置后需要重启服务

sudo systemctl restart rsyslog

四、仿真

通过配置文件将httpp程序的日志输出到 /var/log/httpp 文件中。

现在输出日志信息

#include <unistd.h>  
#include <syslog.h>  
  
int main() {  
    // 打开日志  
    openlog("httpp", LOG_PID | LOG_CONS, LOG_USER);  
      
    // 记录日志消息  
    syslog(LOG_INFO, "LOG_INFO: Program started by user %d", getuid());  
    syslog(LOG_NOTICE, "LOG_NOTICE: Program started by user %d", getuid());  
    syslog(LOG_WARNING, "LOG_WARNING: Program started by user %d", getuid());  
    syslog(LOG_ERR, "LOG_ERR: Program started by user %d", getuid());  
    syslog(LOG_CRIT, "LOG_CRIT: Program started by user %d", getuid());  
    syslog(LOG_ALERT, "LOG_ALERT: Program started by user %d", getuid());  
    syslog(LOG_EMERG, "LOG_EMERG: Program started by user %d", getuid());  
      
    // 关闭日志  
    closelog();  
      
    return 0;  
}

仿真结果如下所示:

image-20240427210153912

  • 18
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LyaJpunov

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值