syslogd 详解二

相关博文:

syslogd 详解一

syslogd 详解三

 

1. 前言

上一篇博文中详细了分析了syslogd的架构,解析了syslogd的调用过程,以及syslog.conf 的详细使用方法,这一篇通过对syslogd 的源码的解析,进一步分析syslogd 的使用方法以及注意事项。

 

2. priority

#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 */

syslogd 支持的priority 定义在syslog.h 中,占用3个bit 位。

syslogd 命令行中 -l 选项控制 logLevel 变量,而这个logLevel 体现的就是这里的priority,代码中:

    if (LOG_PRI(pri) < G.logLevel) {
#if ENABLE_FEATURE_IPC_SYSLOG
        if ((option_mask32 & OPT_circularlog) && G.shbuf) {
            log_to_shmem(G.printbuf);
            return;
        }
#endif

        log_locally(now, G.printbuf, &G.logFile);
    }

如果定义的priority 比设置的logLevel 大,那么log 会被忽略掉。

 

3. facility

/* facility codes */
#define	LOG_KERN	(0<<3)	/* kernel messages */
#define	LOG_USER	(1<<3)	/* random user-level messages */
#define	LOG_MAIL	(2<<3)	/* mail system */
#define	LOG_DAEMON	(3<<3)	/* system daemons */
#define	LOG_AUTH	(4<<3)	/* security/authorization messages */
#define	LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
#define	LOG_LPR		(6<<3)	/* line printer subsystem */
#define	LOG_NEWS	(7<<3)	/* network news subsystem */
#define	LOG_UUCP	(8<<3)	/* UUCP subsystem */
#define	LOG_CRON	(9<<3)	/* clock daemon */
#define	LOG_AUTHPRIV	(10<<3)	/* security/authorization messages (private) */
#define	LOG_FTP		(11<<3)	/* ftp daemon */

    /* other codes through 15 reserved for system use */
#define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
#define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
#define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
#define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
#define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
#define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
#define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
#define	LOG_LOCAL7	(23<<3)	/* reserved for local use */

#define	LOG_NFACILITIES	24	/* current number of facilities */
#define	LOG_FACMASK	0x03f8	/* mask to extract facility part */

syslogd 中facility 应该定义了24个,前 16个是系统使用,后8个是用户使用。

但是从LOG_FACMASK 看,实际上syslogd 给facility 7个bit 位的空间,也就是说实际上可以支持 128个facility。除去系统的16个,用户可以定义112 个facility。

 

4. syslogd 命令行选项

通过代码:

opts = getopt32(argv, "^"OPTION_STR"\0""=0", OPTION_PARAM);

可以得知syslogd 支持的命令行选项有:

#define OPTION_STR "m:nO:l:S" \
	IF_FEATURE_ROTATE_LOGFILE("s:" ) \
	IF_FEATURE_ROTATE_LOGFILE("b:" ) \
	IF_FEATURE_REMOTE_LOG(    "R:*") \
	IF_FEATURE_REMOTE_LOG(    "L"  ) \
	IF_FEATURE_IPC_SYSLOG(    "C::") \
	IF_FEATURE_SYSLOGD_DUP(   "D"  ) \
	IF_FEATURE_SYSLOGD_CFG(   "f:" ) \
	IF_FEATURE_KMSG_SYSLOG(   "K"  )

即-m -n -O -l -S -s -b -R -L -C -D -f -K。

  • 其中n 、S、L、D 和K 是不带参数的;
  • 其中m、O、l、s、b、R、f是带参数的;
  • 其中C 带可选参数;
-n               运行在前台进程
-O file          log 文件的路径,默认在/var/log/messages
-l N             log 可以扩充到N个
-S               较小的输出
-R host[:port]   远程存放log 的主机地址和端口,port为可选,默认为514
-L               log 保存到本地,还是通过网络。默认值只有在-R 指定时候才是网络,其它则是本地。
-C [size_kb]     log 存放到share memory,通过logread 读取,单位为kb。
-K               log保存到kernel buffer中,通过dmesg读取
-s size          log 文件最大空间为size(kb),默认为200kb,设0是关闭限制
-b N             N 个log 文件滚动保存,默认值为1,最大为99,设0 表示只用一个log 文件
                 文件的接口会以数字区分,0为最新的log文件,数字越小,文件越新
-D               去除重复log
-f               指定syslogd 的config 路径,默认为/etc/syslog.conf
-m MIN           每隔MIN 分钟在log 中做一次标记

通过代码理解选项:

例如,-K

    if (option_mask32 & OPT_kmsg) {
        log_to_kmsg(pri, msg);
        return;
    }

 

例如,-S

    if (option_mask32 & OPT_small)
        sprintf(G.printbuf, "%s %s\n", timestamp, msg);
    else {
        char res[20];
        parse_fac_prio_20(pri, res);
        sprintf(G.printbuf, "%s %.64s %s %s\n", timestamp, G.hostname, res, msg);
    }

如果-S,log格式只是时间戳 + 消息

没有-S,log 格式会多host name  和priority

 

5. facility 名字不能太长

上面第 3 节中说到facility 可以有128 个,用户可以使用其中的112个,但是在定义facility 名字的时候需要注意长度。

static void parse_fac_prio_20(int pri, char *res20)
{
    const CODE *c_pri, *c_fac;

    c_fac = find_by_val(LOG_FAC(pri) << 3, bb_facilitynames);
    if (c_fac) {
        c_pri = find_by_val(LOG_PRI(pri), bb_prioritynames);
        if (c_pri) {
            snprintf(res20, 20, "%s.%s", c_fac->c_name, c_pri->c_name);
            return;
        }
    }
    snprintf(res20, 20, "<%d>", pri);
}

facility.priority 的长度不能多于20个字节,按照prioriy 最长6个字节,那么要求facility 最多为12个字符

 

6. 本地和shmem 不能同时

#if ENABLE_FEATURE_SYSLOGD_CFG
    {
        bool match = 0;
        logRule_t *rule;
        uint8_t facility = LOG_FAC(pri);
        uint8_t prio_bit = 1 << LOG_PRI(pri);

        for (rule = G.log_rules; rule; rule = rule->next) {
            if (rule->enabled_facility_priomap[facility] & prio_bit) {
                log_locally(now, G.printbuf, rule->file);
                match = 1;
            }
        }
        if (match)
            return;
    }
#endif

    if (LOG_PRI(pri) < G.logLevel) {
#if ENABLE_FEATURE_IPC_SYSLOG
        if ((option_mask32 & OPT_circularlog) && G.shbuf) {
            log_to_shmem(G.printbuf);
            return;
        }
#endif
        log_locally(now, G.printbuf, &G.logFile);
    }

源码中如果syslog.conf有配置,并且匹配上,就会调用log_locally (第一次log_locally)进行保存,最后直接return;

如果想要保存到本地的同时,也能使用logread 进行读取,那么源码需要适当的改动;

如果syslog.conf 中的配置没有匹配,会优先确认是否输出到shmem,如果shmem 打开,那么本地(第二次log_locally)不会再做保存。如果需要同时保存到shmem 和本地,逻辑需要适当的改动;

 

 

 

相关博文:

syslogd 详解一

syslogd 详解三

 

你可能感兴趣的:(unix/linux)