linux日志:syslogd和klogd及syslog

时间:2022-06-12 16:07:03

一. 日志守护进程

syslogd和klogd是很有意思的守护进程,syslogd是一个分发器,它将接收到的所有日志按照/etc/syslog.conf的配置策略发送到这些日志应该去的地方,当然也包括从klogd接收到的日志。klogd首先接收内核的日志,然后将之发送给syslogd。

syslogd日志记录器由两个守护进程(klogd,syslogd)和一个配置文件(syslog.conf)组成。klogd不使用配置文件,它负责截获内核消息,它既可以独立使用也可以作为syslogd的客户端运行。syslogd默认使用/etc/syslog.conf作为配置文件,负责截获应用程序消息,还可以截获klogd向其转发的内核消息。支持internet/unix domain sockets的特性使得这两个工具可以用于记录本地和远程的日志。

二. 日志应用编程

 syslog是lib函数,用于向系统发送日志(send messages to the system logger)。

       #include <syslog.h>

       void openlog(const char *ident, int option, int facility);
       void syslog(int priority, const char *format, ...);
       void closelog(void);

       void vsyslog(int priority, const char *format, va_list ap);

默认的日志操作步骤为openlog() -> syslog()/ vsyslog() -> closelog()。

openlog()的参数ident指向一个字符串,追加到每条日志前,用于标记日志属主,一般为程序名,为NULL时默认是程序名(不统一);

option控制log行为,下列值可OR:

LOG_CONS       Write directly to system console if there is an error while sending to system logger.
LOG_NDELAY     Open the connection immediately (normally, the connection is opened when the first message is logged).
LOG_NOWAIT     Don't  wait  for child processes that may have been created while logging the message.  
         (The GNU C library does not create a child process, so this option has no
effect on Linux.) LOG_ODELAY The converse of LOG_NDELAY; opening of the connection is delayed until syslog() is called.
          (This is the default, and need not be specified.) LOG_PERROR (Not in POSIX.1-2001 or POSIX.1-2008.) Print to stderr as well. LOG_PID Include PID with each message.

facility指定哪种类型程序在发送日志,配置文件可指定不同facility日志可进行不同处理:

LOG_AUTH       security/authorization messages
LOG_AUTHPRIV   security/authorization messages (private)
LOG_CRON       clock daemon (cron and at)
LOG_DAEMON     system daemons without separate facility value
LOG_FTP        ftp daemon
LOG_KERN       kernel messages (these can't be generated from user processes)
LOG_LOCAL0 through LOG_LOCAL7   reserved for local use
LOG_LPR        line printer subsystem
LOG_MAIL       mail subsystem
LOG_NEWS       USENET news subsystem
LOG_SYSLOG     messages generated internally by syslogd(8)
LOG_USER (default)   generic user-level messages
LOG_UUCP       UUCP subsystem

syslog()负责写日志,priority指定日志级别:

       LOG_EMERG      system is unusable
       LOG_ALERT      action must be taken immediately
       LOG_CRIT       critical conditions
       LOG_ERR        error conditions
       LOG_WARNING    warning conditions
       LOG_NOTICE     normal, but significant, condition
       LOG_INFO       informational message
       LOG_DEBUG      debug-level message

man手册明确指出不要向format传入用户数据(Never pass a string with user-supplied data as a format, use the following instead)

syslog(priority, "%s", string);

 一般应用程序中都要都其进行封装,以便于直接打印相关级别日志(封装LOG_EMERG级别日志):

#define BUF_SIZE 1024

char *ident = "hello";

void hello_syslog_emerg(char *format,...)
{
    va_list ptr;
    char buf[BUF_SIZE] = {0};

    // ident null or format message null
    if(!ident || !format) {
        return;
    }   

    openlog(ident, 0, LOG_DAEMON);

    // put log
    va_start(ptr, format);
    vsprintf(buf, format, ptr);
    va_end(ptr);
    syslog(LOG_EMERG, "%s", buf);

    return; 
}

示例:

#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>

#define BUF_SIZE 1024

char *ident = "hello";

void hello_syslog_emerg(char *format,...)
{
    va_list ptr;
    char buf[BUF_SIZE] = {0};

    // ident null or format message null
    if(!ident || !format) {
        return;
    }   

    openlog(ident, 0, LOG_DAEMON);

    // put log
    va_start(ptr, format);
    vsprintf(buf, format, ptr);
    va_end(ptr);
    syslog(LOG_EMERG, "%s", buf);

    return; 
}

int main(void)
{
    char cbuf[BUF_SIZE] = {0};
    
    printf("send one emergency message to system:\n");
    scanf("%s", cbuf);
    hello_syslog_emerg("%s", cbuf); 

    return 0;
}
@ubuntu:~/vmlinux$ gcc hello.c -o hello -Wall
@ubuntu:~/vmlinux$ ./hello 
send one emergency message to system:
thesystemisoff
@ubuntu:~/vmlinux$ 
Broadcast message from systemd-journald@ubuntu (Sat 2018-05-12 17:12:50 CST):

hello[3786]: thesystemisoff

或宏定义封装:

#define ERROR(fmt, ...) do { \
    syslog(LOG_ERR, "jail: "fmt, ## __VA_ARGS__); \
    } while (0)

 

参考:

1. http://blog.csdn.net/dog250/article/details/5707979

2. http://www.360doc.com/content/13/0102/10/7775902_257612487.shtml