Linux 日志输出控制
发布日期:2021-06-29 12:42:07 浏览次数:2 分类:技术文章

本文共 5839 字,大约阅读时间需要 19 分钟。

    在嵌入式Linux设备中,系统资源比较有限,在产品开发时我们会打印很多的日志信息方便工程调试和问题定位。但是在产品发布的时候,为了节省系统资源,那些调试信息或是一些不总要的信息就不需要再记入到日志当中,所以我们需要设置相应的日志等级。

    Linux内核调试信息printk函数,它的输出等级在Linux内核中已经帮我们定义好。可以通过命令查看和设置系统日志等级:

/ # cat /proc/sys/kernel/printk4       4       1       7/ # / # / # echo 7 4 1 7 > /proc/sys/kernel/printk/ # / # / # cat /proc/sys/kernel/printk7       4       1       7

    这四个值分别表示:控制台日志级别;默认的消息日志级别;最低的控制台日志级别,默认的控制台日志级别。这四个值是在kernel的printk.c文件中被定义,数值越小,优先级越高。如果要修改默然的开机启动日志级别,可以直接修改printk.c中的定义。

    对于应用层的日志输出控制,一般的应用会有自己的日志系统。如果没有日志系统,或是使用的日志系统比较混乱,也可以自己定义一套属于自己的日志系统。

#ifdef __cplusplusextern "C" {#endif /* __cplusplus *//** Name: debug.h* Purpose: general debug system* Created By: licaibiao* Created Date: 2016.11.10* ChangeList: *//*must use _B_  ,have a DEBUG_ in Jason*/#ifndef _DEBUG_B_H_#define _DEBUG_B_H_/** debug control, you can switch on (delete 'x' suffix)* to enable log output and assert mechanism*/#define CONFIG_ENABLE_DEBUG/** debug level,* if is DEBUG_LEVEL_DISABLE, no log is allowed output,* if is DEBUG_LEVEL_ERR, only ERR is allowed output,* if is DEBUG_LEVEL_INFO, ERR and INFO are allowed output,* if is DEBUG_LEVEL_DEBUG, all log are allowed output,*/enum debug_level {	DEBUG_LEVEL_DISABLE = 0,	DEBUG_LEVEL_ERR,	DEBUG_LEVEL_INFO,	DEBUG_LEVEL_DEBUG};#ifdef CONFIG_ENABLE_DEBUG/* it can be change to others, such as file operations */#include 
#define PRINT printf#define debug DEBUG_LEVEL_DISABLE#define ASSERT() \do { \ PRINT("ASSERT: %s %s %d", \ __FILE__, __FUNCTION__, __LINE__); \ while (1); \} while (0)#define ERR(...) \do { \ if (debug >= DEBUG_LEVEL_ERR) { \ PRINT(__VA_ARGS__); \ } \} while (0)#define INFO(...) \do { \ if (debug >= DEBUG_LEVEL_INFO) { \ PRINT(__VA_ARGS__); \ } \} while (0)#define DEBUG(...) \do { \ if (debug >= DEBUG_LEVEL_DEBUG) { \ PRINT(__VA_ARGS__); \ } \} while (0)#else /* CONFIG_ENABLE_DEBUG */#define ASSERT()#define ERR(...)#define INFO(...)#define DEBUG(...)#endif /* CONFIG_ENABLE_DEBUG */#endif /* _DEBUG_H_ */#ifdef __cplusplus}#endif /* __cplusplus */

    在应用程序中可以直接包含头文件调用接口:

ERR("This is a test interface \n");

    对于linux应用层的日志信息,如果要将日志写入到文件中,且能够打印时间戳等信息,可以使用下面的接口:

#ifndef __GPS_DEBUG_H__#define __GPS_DEBUG_H__#include 
#include
#include
#include
#define MAX_LOGFILE_SIZE 50000#define LOGFLAG 1enum UserDefineLogNum{ GENERAL_LOG_NUM=1, DAEMON_LOG_NUM, ROUTER_LOG_NUM, MODEM_LOG_NUM, PERIPHER_LOG_NUM, GPSSERVICE_LOG_NUM, CAPTURE_LOG_NUM, OTHER_LOG_NUM,};#if LOGFLAG > 0#define TRACE_TRACE_GENERAL Trace(GENERAL_LOG_NUM, __LINE__) #define TRACE_DAEMON Trace(DAEMON_LOG_NUM, __LINE__) #define TRACE_ROUTER Trace(ROUTER_LOG_NUM, __LINE__) #define TRACE_MODEM Trace(MODEM_LOG_NUM, __LINE__) #define TRACE_PERIPHER Trace(PERIPHER_LOG_NUM, __LINE__) #define TRACE_GPSSERVICE Trace(GPSSERVICE_LOG_NUM, __LINE__) #define TRACE_CAPTURE Trace(CAPTURE_LOG_NUM, __LINE__) #define TRACE_OTHER Trace(OTHER_LOG_NUM, __LINE__) #else#define TRACE printf#define TRACE_GENERAL printf#define TRACE_DAEMON printf#define TRACE_GPS printf#define TRACE_CAPTURE printf#define TRACE_PPP printf#define TRACE_COMM printf#define TRACE_UPDATE printf#endif#define SYSLOGDIR "/mnt/log/"#define SYSLOGDISK "/mnt/"#define MIX_AVAILABLE_DISK (1024+512)#define TRACE_HST (printf("%s(%d)-<%s>: ",__FILE__, __LINE__, __FUNCTION__), printf)class Trace{public: Trace(UserDefineLogNum LogNum, int nLineNo ):defineLogNum(LogNum),m_nLineNo(nLineNo) { } inline void operator()(const char *pszFmt, ...) const { va_list ptr; va_start(ptr, pszFmt); TraceV(m_nLineNo,pszFmt,ptr); va_end(ptr); }private: unsigned int availableDisk(const char * pcDir) const { if(NULL == pcDir) return -1; struct statfs diskInfo; unsigned int blocksize = 0; //每个block里包含的字节数 unsigned int availableDisk = 0; //可用空间大小 int iRet = -1; iRet = statfs(pcDir, &diskInfo); if(0 == iRet) { blocksize = diskInfo.f_bsize; availableDisk = diskInfo.f_bavail * blocksize/1024;//(K) } return availableDisk; } void TraceV(int nLine,const char *pszFmt, va_list args) const { time_t tNow; time(&tNow); struct tm *time; time=localtime(&tNow); char log_path[64] ={0}; char log_dir[64] ={0}; if(time->tm_year-100 < 16 && time->tm_year-100 > 30) { time->tm_year =116; time->tm_mon =0; } if(MIX_AVAILABLE_DISK>=availableDisk(SYSLOGDISK)) { system("rm -rf /mnt/log/*"); //统一删除不做覆盖 return; } sprintf(log_dir,"%sl-%02d%02d%02d",SYSLOGDIR,(time->tm_year-100),(1+time->tm_mon),(time->tm_mday)); if ( 0 != access(log_dir, F_OK) ) { if( mkdir(log_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0 ) { printf("[%s:%d] create dir %s ok!\n", __func__, __LINE__,log_dir); } else { printf("[%s:%d] create dir %s error!\n", __func__, __LINE__,log_dir); perror("mkdir"); return; } } sprintf(log_path,"%s/1000000%d.log",log_dir,defineLogNum); FILE* pFile=fopen(log_path,"a+"); if (pFile==NULL) { vprintf(pszFmt,args); return; } fprintf(pFile,"%02d-%02d %02d:%02d:%02d : ",time->tm_mon+1,time->tm_mday,time->tm_hour,time->tm_min,time->tm_sec); vfprintf(pFile,pszFmt,args); fclose(pFile); return; }private: UserDefineLogNum defineLogNum; const int m_nLineNo;};#endif

        上面代码可以实现不同进程调用同一套接口,根据时间和预定义的名字将日志文件打印到相应的文件中去。

 

 

转载地址:https://caibiao-lee.blog.csdn.net/article/details/53121308 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:TCP与UDP的区别以及UDP程序设计中的几个问题
下一篇:shell脚本编程:sed命令编辑文本

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月14日 04时18分01秒