相关博文:
syslogd 详解一
syslogd 详解三
1. 前言
上一篇博文中详细了分析了syslogd的架构,解析了syslogd的调用过程,以及syslog.conf 的详细使用方法,这一篇通过对syslogd 的源码的解析,进一步分析syslogd 的使用方法以及注意事项。
2. priority
#defineLOG_EMERG0/* system is unusable */
#defineLOG_ALERT1/* action must be taken immediately */
#defineLOG_CRIT2/* critical conditions */
#defineLOG_ERR3/* error conditions */
#defineLOG_WARNING4/* warning conditions */
#defineLOG_NOTICE5/* normal but significant condition */
#defineLOG_INFO6/* informational */
#defineLOG_DEBUG7/* 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 */
#defineLOG_KERN(0<<3)/* kernel messages */
#defineLOG_USER(1<<3)/* random user-level messages */
#defineLOG_MAIL(2<<3)/* mail system */
#defineLOG_DAEMON(3<<3)/* system daemons */
#defineLOG_AUTH(4<<3)/* security/authorization messages */
#defineLOG_SYSLOG(5<<3)/* messages generated internally by syslogd */
#defineLOG_LPR(6<<3)/* line printer subsystem */
#defineLOG_NEWS(7<<3)/* network news subsystem */
#defineLOG_UUCP(8<<3)/* UUCP subsystem */
#defineLOG_CRON(9<<3)/* clock daemon */
#defineLOG_AUTHPRIV(10<<3)/* security/authorization messages (private) */
#defineLOG_FTP(11<<3)/* ftp daemon */
/* other codes through 15 reserved for system use */
#defineLOG_LOCAL0(16<<3)/* reserved for local use */
#defineLOG_LOCAL1(17<<3)/* reserved for local use */
#defineLOG_LOCAL2(18<<3)/* reserved for local use */
#defineLOG_LOCAL3(19<<3)/* reserved for local use */
#defineLOG_LOCAL4(20<<3)/* reserved for local use */
#defineLOG_LOCAL5(21<<3)/* reserved for local use */
#defineLOG_LOCAL6(22<<3)/* reserved for local use */
#defineLOG_LOCAL7(23<<3)/* reserved for local use */
#defineLOG_NFACILITIES24/* current number of facilities */
#defineLOG_FACMASK0x03f8/* 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, "", 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 详解三