linux c使用syslog记录消息

2018-06-14 18:22:04

syslog 工具提供了一个集中式日志工具,系统中的所有应用程序都可以使用这个记录日志消息。如下图

syslogd 从两个不同的源接收日志消息:一个是unix domain docket /dev/log,它保存本地产生的消息。另一个是tcp/udp 514端口,保存通过 tcp/ip 网络发送过来的消息。

#include <syslog.h>

void openlog(const char *ident, int log_options, int facility);

ident 为字符串指针,syslog() 输出的每条消息都会包含这个字符串,这个参数的取值通常为程序名,设为NULL 默认就是程序名。

log_options 部分选项如下:

1.LOG_CONS 同时写入到控制台 /dev/console。
2.LOG_NDELAY 立即打开日志系统的连接,默认情况下在首次调用syslog() 时才会连接到/dev/log,为了防止后面访问不到/dev/log,比如在openlog()之后调用chroot()。
3.LOG_PERROR 将消息写入到标准错误和系统日志。
4.LOG_PID 在每条消息中加上调用者的进程ID。

facility 值和 syslog() 的 priority参数

值 描述 
 LOG_AUTH 安全和验证消息
 LOG_AUTHPRIV 私有的安全和验证消息
 LOG_CRON 来自crond和atd消息
 LOG_DAEMON 其他系统daemon消息
 LOG_FTP ftpd消息
 LOG_KERN 内核消息(用户进程无法生成此类消息)
 LOG_LOCALO 保留给本地使用,包括1-7
 LOG_LPR 来及行打印机消息(lpr,lpd,lpc)
 LOG_MAIL 邮件系统消息
 LOG_NEWS 与usenet网络新闻相关消息
 LOG_SYSLOG 来自syslogd 消息
 LOG_USER 用户进程生成的消息(默认值)
 LOG_UUCP 来自uucp系统的消息


#include <syslog.h>

void syslog(int priority, const char *format, ...);

记录日志消息,如果priority省略,则会用openlog()调用指定的 facility 值,如果也省略,默认为LOG_USER。

syslog中的priority参数的level值如下(严重性从最高到最低)

值 描述 
 LOG_EMERG 紧急或令人恐慌的情况
 LOG_ALERT 需要立即处理的情况(如破坏了系统数据库)
 LOG_CRIT 关键情况
 LOG_ERR 常规错误
 LOG_WARNING 警告
 LOG_NOTICE 可能需要处理的普通情况
 LOG_INFO 情报性消息
 LOG_DEBUG 调试消息


#include <syslog.h>

void closelog(void);

当完成日志记录之后可以调用closelog() 来释放分配给/dev/log socket的文件描述符。


#include <syslog.h>

int setlogmask(int mask_priority);

//Returns previous log priority mask

过滤syslog,所有level不在当前掩码设置中的消息都会被丢弃。

下面只记录LOG_ERR及以上的消息。

setlogmask(LOG_MASK(LOG_EMERG) | LOG_MASK(LOG_ALERT) |
LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ERR));

setlogmask(LOG_UPTO(LOG_ERR));


配置文件 /etc/rsyslog.conf 解释

kern			内核
user			使用者层级产生的信息
mail			邮件相关
daemon			系统服务相关
auth			认证相关
syslog			rsyslogd产生
cron			crontab信息
authpriv		类似auth,但是记录更多信息
ftp				ftp相关
local0-local7	保留给本机用户

debug,info,notice,warn,err,crit,alert,emerg

mail.					记录全部
mail.info				比mail.info严重的都记录下来
mail.=info				只记录info
mail.!info				记录info以外的

#记录所有但是除去news,cron,mail
.;news,cron,mail.none
.;news.none;cron.none;mail.none	

#代表先存buffer,等数据量够大时再一次性写入文件
#加快写入速度,但是系统崩溃的话可能会丢失数据
mail.*					-/var/log/maillog

#开启udp514端口接收其他服务器的syslog日志
$ModLoad imudp
$UDPServerRun 514

#开启tcp514端口接收其他服务器的syslog日志(如果网络不稳定最好用tcp)
$ModLoad imtcp
$InputTCPServerRun 514

#客户端配置tcp
*.* @@192.168.1.3:514

#客户端配置udp
*.* @192.168.1.3:514

例子

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <syslog.h>

static void usageError(const char *progName){
    fprintf(stderr, "Usage: %s [-p] [-e] [-l level] \"message\"\n", progName);
    fprintf(stderr, "    -p   log PID\n");
    fprintf(stderr, "    -e   log to stderr also\n");
    fprintf(stderr, "    -l   level (g=EMERG; a=ALERT; c=CRIT; e=ERR\n");
    fprintf(stderr, "                w=WARNING; n=NOTICE; i=INFO; d=DEBUG)\n");
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]){
    int level, options, opt;

    options = 0;
    level = LOG_INFO;

    while ((opt = getopt(argc, argv, "l:pe")) != -1) {
        switch (opt) {
        case 'l':
            switch (optarg[0]) {
            case 'a': level = LOG_ALERT;        break;
            case 'c': level = LOG_CRIT;         break;
            case 'e': level = LOG_ERR;          break;
            case 'w': level = LOG_WARNING;      break;
            case 'n': level = LOG_NOTICE;       break;
            case 'i': level = LOG_INFO;         break;
            case 'd': level = LOG_DEBUG;        break;
            default:
                printf("Bad facility: %c\n", optarg[0]);
                return 1;
            }
            break;

        case 'p':
            options |= LOG_PID;
            break;

        case 'e':
            options |= LOG_PERROR;
            break;

        default:
            fprintf(stderr, "Bad option\n");
            usageError(argv[0]);
        }
    }

    if (argc != optind + 1)
        usageError(argv[0]);

    openlog(argv[0], options, LOG_USER);
    syslog(LOG_USER | level, "%s", argv[optind]);
    closelog();

    exit(EXIT_SUCCESS);
}

rsyslog.conf配置如下

*.info;mail.none;authpriv.none;cron.none                /var/log/messages
[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out -p -la "test-alert"
[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out -p -li "test-info"
[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out -p -ld "test-debug"
[root@izj6cfw9yi1iqoik31tqbgz ~]# tail -f /var/log/messages

Jun 14 18:20:22 izj6cfw9yi1iqoik31tqbgz ./a.out[13395]: test-alert
Jun 14 18:20:33 izj6cfw9yi1iqoik31tqbgz ./a.out[13396]: test-info


备注
1.编译器版本gcc4.8,运行环境centos7 64位
2.原文地址http://www.freecls.com/a/2712/58

©著作权归作者所有
收藏
推荐阅读
  • linux c进程调度-CPU亲和力

    进程切换 CPU 时对性能会有一定的影响:如果在原来的 CPU 的高速缓冲器中存在进程的数据,那么为了将进程的一行数据加载进新 CPU 的高速缓冲器中,首先必须使这行数据失效(即在没被修改的情况下丢弃...

  • err
    linux c线程(2)-同步和线程取消

    本篇将介绍线程用来同步彼此行为的两个工具:互斥量和条件变量。我们先来看一个例子。#include &lt;sys/types.h&gt; #include &lt;std...

  • err
    linux c线程(1)-基础

    与进程类似,线程是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。线程间共享同一份全局内存区域,其中包括初始化数据段,未初始化数据段,堆内存。传统uni...

  • err
    linux c程序的执行

    执行新程序:execve系统调用 execve() 可以将新程序加载到某一进程的内存空间。进程的栈、数据段、堆都会被新程序的相应部件所替换。由fork() 生成的子进程对...

  • err
    linux c监控子进程

    接下来描述两种监控子进程的技术:系统调用wait()及其变体,SIGCHLD信号。系统调用wait()#include &lt;sys/wait.h&gt; pid_t...

  • nginx模块 ngx_http_headers_module

    ngx_http_headers_module 模块是用来增加 Expires 和 Cache-control,或者是任意的响应头。Syntax: add_header name value [alw...

  • nginx模块 ngx_http_gunzip_module、ngx_http_gzip_module、ngx_http_gzip_static_module

    ngx_http_gunzip_module 模块将文件解压缩后并在响应头加上 "Content-Encoding: gzip" 返回给客户端。为了解决客户端不支持gzip压缩。编译的时候带上 --w...

  • nginx模块 ngx_http_flv_module、ngx_http_mp4_module

    ngx_http_flv_module模块提供了对 flv 视频的伪流支持。编译的时候带上 --with-http_flv_module。它会根据指定的 start 参数来指定跳过多少字节,并在返回数...

  • nginx模块 ngx_http_fastcgi_module

    ngx_http_fastcgi_module 模块使得nginx可以与 fastcgi 服务器通信。比如目前要使得 nginx 支持 php 就得使用 fastcgi技术,在服务器上装上 nginx...

  • nginx模块 ngx_http_autoindex_module

    ngx_http_autoindex_module 模块可以将uri以 / 结尾时,列出里面的文件和目录。Syntax: autoindex on | off; Default: autoindex ...

简介
天降大任于斯人也,必先苦其心志。