目录
log.h
#ifndef LOG_H
#define LOG_H
/* ************************************************************************************ */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/types.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
//C++中建议将define 改为 const
#define LOG_PROCNAME 0x00000001 /* msglog 输出日志时打印程序名 */
#define LOG_PID 0x00000010 /* msglog 输出日志时打印进程 PID */
#define LOG_PERROR 0x00000100 /* msglog 是否把告警内容输出到stderr */
#define NLO_PROCNAME 0x11111110 /* msglog 不输出程序名 */
#define NLO_PID 0x11111101 /* msglog 不输出进程 PID */
#define NLO_PERROR 0x11111011 /* msglog 不输出告警到stderr */
//日志级别 日志级别越高打印的日志越多
#define MSG_INFO 0x00000001 /* msglog 输出到告警日志文件中 */
#define MSG_WARN 0x00000010 /* msglog 输出到普通日志文件中 */
#define MSG_BOTH MSG_INFO|MSG_WARN /* msglog 输出到普通和告警日志文件中 */
#define LOG_MESSAGE_FILE "/home/holo/epoll_fwq/log/tcpsvr" /* 系统程序运行日志信息文件 */
#define LOG_MESSAGE_DFMT "%m-%d %H:%M:%S" /* 日志信息时间格式字串 */
#define LOG_POSTFIX_MESS "%y%m" /* 程序运行日志信息文件后缀 */
#define LOG_WARNING_FILE "/home/holo/epoll_fwq/log/log.sys_warn" /* 系统程序运行告警日志文件 */
#define LOG_WARNING_DFMT "%m-%d %H:%M:%S" /* 告警信息时间格式字串 */
#define LOG_POSTFIX_WARN "" /* 程序运行告警日志文件后缀(拓展名),默认没有 */
/* ************************************************************************************ */
int msglog(int mtype, char *outfmt, ...);//写日志文件函数
int msgLogFormat(int mopt, char *mdfmt, int wopt, char *wdfmt);//按照格式写日志文件,对日志格式化 参数中没有看到路径,说明用到了全局变量
int msgLogOpen(char *ident, char *mpre, char *mdate, char *wpre, char *wdate);//打开日志文件
int msgLogClose(void);//关闭日志文件
long begusec_process(void); /* 设置开始时间 0=ok */
long getusec_process(void); /* 获得时间 返回usecond 从 begusec_process历时 */
int msgInit(char *pName); //获得文件名
#endif
/* ************************************************************************************ */
/* ************************************************************************************ */
/* ************************************************************************************ */
/* ************************************************************************************ */
log.c
#include "log.h"
static int msgopt, wanopt;
static char msgdatefmt[100], wandatefmt[100], ident_name[100];
static struct timeval be_stime;
static FILE *msgfile = NULL, *wanfile = NULL; //静态变量生命周期和进程相同
/* ************************************************************************************ */
/* ************************************************************************************ */
/* ************************************************************************************ */
//日志文件初始化,也可以通过msgLogOpen进行初始化
int msgInit(char *pName)
{
if (msgLogOpen(pName, LOG_MESSAGE_FILE, LOG_POSTFIX_MESS,LOG_WARNING_FILE, LOG_POSTFIX_WARN) == 0)
{
//对日志文件格式化, 按照指定格式显示
msgLogFormat(LOG_PROCNAME|LOG_PID, LOG_MESSAGE_DFMT, LOG_PROCNAME|LOG_PID, LOG_WARNING_DFMT);
}
else
{
printf("can not create log!\n");
return -1;
}
return 0;
}
/* ************************************************************************************ */
/* 文件作用: 打开日志文件 */
int msgLogOpen(char *ident, char *mpre, char *mdate, char *wpre, char *wdate)
{
time_t now_time;
char openfilename[200], timestring[100];
now_time = time(NULL);
if ((!msgfile) && (*mpre))
{
strcpy(openfilename, mpre);
if (*mdate)
{
strftime(timestring, sizeof(timestring), mdate, localtime(&now_time));
strcat(openfilename, ".");
strcat(openfilename, timestring);
}
//返回文件指针, 保存到静态文件变量msgfile里
if ((msgfile = fopen(openfilename, "a+b")) == NULL) //a+b:追加+二进制 linux下没有b
{ /* 如果没有应该把目录建上 */
printf("openfilename=%s\n", openfilename);
return -1;
}
setlinebuf(msgfile);
}
if ((!wanfile) && (*wpre))
{
strcpy(openfilename, wpre);
if (*wdate)
{
strftime(timestring, sizeof(timestring), wdate, localtime(&now_time));
strcat(openfilename, ".");
strcat(openfilename, timestring);
}
if ((wanfile = fopen(openfilename, "a+b")) == NULL)
{
return -1;
}
setlinebuf(wanfile);
}
if ((msgfile) && (wanfile))
{
if (*ident)
{
strcpy(ident_name, ident);
} else {
ident_name[0] = '\0';
}
msgopt = LOG_PROCNAME|LOG_PID; /* 设置默认信息输出信息选项 */
wanopt = LOG_PROCNAME|LOG_PID; /* 设置默认告警输出信息选项 */
strcpy(msgdatefmt, "%m-%d %H:%M:%S"); /* 默认信息输出时间格式 MM-DD HH24:MI:SS */
strcpy(wandatefmt, "%m-%d %H:%M:%S"); /* 默认告警输出时间格式 MM-DD HH24:MI:SS */
msglog(MSG_INFO,"File is msgfile=[%d],wanfile=[%d].",fileno(msgfile),fileno(wanfile));
return 0;
} else {
return -1;
}
}
/* ************************************************************************************ */
/* 自定义日志输出函数系列,可以按普通信息及告警信息分类输出程序日志 */
/*
* 函数作用: 写日志文件
*/
int msglog(int mtype, char *outfmt, ...)
{
time_t now_time;
va_list ap;//变参的列表
char logprefix[1024], tmpstring[1024];
time(&now_time);
if (mtype & MSG_INFO)
{ /*strftime会将localtime(&now_time)按照msgdatefmt格式,输出到logprefix.*/
strftime(logprefix, sizeof(logprefix), msgdatefmt, localtime(&now_time));
strcat(logprefix, " ");
/*static int msgopt,wanopt;*/
if (msgopt&LOG_PROCNAME)
{
strcat(logprefix, ident_name);
strcat(logprefix, " ");
}
if (msgopt&LOG_PID)
{
sprintf(tmpstring, "[%6d]", getpid());
strcat(logprefix, tmpstring);
}
fprintf(msgfile, "%s: ", logprefix); //调用底层的写日志函数
va_start(ap, outfmt); //处理可变参数的函数 ap:变参列表即 fpaintf里的"%s %s" 第二个参数
vfprintf(msgfile, outfmt, ap);
va_end(ap);
fprintf(msgfile, "\n");
}
if (mtype & MSG_WARN)
{
strftime(logprefix, sizeof(logprefix), wandatefmt, localtime(&now_time));
strcat(logprefix, " ");
/*#define LOG_PROCNAME 0x00000001*/ /* msglog 输出日志时打印程序名 */
if (wanopt & LOG_PROCNAME)
{
strcat(logprefix, ident_name);
strcat(logprefix, " ");
}
if (wanopt & LOG_PID)
{
sprintf(tmpstring, "[%6d]", getpid());
strcat(logprefix, tmpstring);
}
fprintf(wanfile, "%s: ", logprefix);
va_start(ap, outfmt);
vfprintf(wanfile, outfmt, ap);
va_end(ap);
fprintf(wanfile, "\n"); //用fprintf写日志的好处:可以格式化, 用sprintf和write组合起来可以代替fprintf
if (wanopt & LOG_PERROR)
{
fprintf(stderr, "%s: ", logprefix);
va_start(ap, outfmt);
vfprintf(stderr, outfmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
}
return 0;
}
/* ************************************************************************************ */
/*
* 函数作用: 设置日志格式,和选项 */
int msgLogFormat(int mopt, char *mdfmt, int wopt, char *wdfmt)
{
if (mopt >= 0)
{
msgopt = mopt;
} else {
msgopt = msgopt & mopt;
}
if (wopt >= 0)
{
wanopt = wopt;
} else {
wanopt = wanopt & wopt;
}
if (*mdfmt) strcpy(msgdatefmt, mdfmt);
if (*wdfmt) strcpy(wandatefmt, wdfmt);
return 0;
}
/* ************************************************************************************ */
int msgLogClose(void) /* 关闭日志文件 */
{
if (msgfile) fclose(msgfile);
if (wanfile) fclose(wanfile);
return 0;
}
/* ************************************************************************************ */
long begusec_process(void) /* 设置开始时间 0=ok */
{
gettimeofday(&be_stime,NULL);
return 0;
}
/* ************************************************************************************ */
// 函数作用: 返回进程执行了多少时间
long getusec_process(void) /* 返回usecond 从 begusec_process历时 */
{
struct timeval ed_stime;
gettimeofday(&ed_stime,NULL);
return ((ed_stime.tv_sec-be_stime.tv_sec)*1000000+ed_stime.tv_usec-be_stime.tv_usec);
}
/* ************************************************************************************ */
/* ************************************************************************************ */
/* ************************************************************************************ */
/* ************************************************************************************ */
log.demo.c
#include "log.h"
int main(int argc,char *argv[])
{
char *pName = argv[0];
pName +=2; //跳过./
printf("pName is %s\n",pName);
msgInit("log_demo");
msglog(MSG_INFO,"begin run program....");
sleep(2);
msglog(MSG_BOTH,"begin to game over...%ld",time(NULL));
msgLogClose();
return 0;
}
运行演示
log_demo.c:14:5: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘__pid_t’ [-Wformat=]
printf("%ld\n",getpid());
^
holo@holo:~/epoll_fwq$ ./log_demo
pName is log_demo
97125
holo@holo:~/epoll_fwq$ cat log/tcpsvr.2311
11-09 14:18:31 log_demo [ 93388]: File is msgfile=[3],wanfile=[4].
11-09 14:18:31 log_demo [ 93388]: begin run program....
11-09 14:18:33 log_demo [ 93388]: begin to game over...1699510713
11-09 14:23:55 log_demo [ 97125]: File is msgfile=[3],wanfile=[4].
11-09 14:23:55 log_demo [ 97125]: begin run program....
11-09 14:23:57 log_demo [ 97125]: begin to game over...1699511037
holo@holo:~/epoll_fwq$ cd log
holo@holo:~/epoll_fwq/log$ ls
log.sys_warn tcpsvr.2311
holo@holo:~/epoll_fwq/log$ cat log.sys_warn
11-09 14:18:33 log_demo [ 93388]: begin to game over...1699510713
11-09 14:23:57 log_demo [ 97125]: begin to game over...1699511037