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

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

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

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

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

#ifdef __cplusplus
extern "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 <stdio.h>
#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 <stdio.h>
#include <time.h>
#include <stdarg.h>
#include <sys/statfs.h>
#define MAX_LOGFILE_SIZE 50000
#define LOGFLAG 1
enum 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

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

由于各种原因,后续文章内容将更新到公众号,本平台将不再做更新。

CSDN上相关文章的测试工程代码,也统一放到了公众号上,可以免费免积分下载

可以通过主页上的二维码,也可以通过搜索微信公众号 liwen01 进入公众号

liwen01   2022.08.21

Linux 日志输出控制相关推荐

  1. linux日志大小控制

    linux日志大小控制 1,使用linux自带logrotate 程序控制日志文件大小 #在linux环境下 /etc/目录 分别有: logrotate.conf文件 = 用于全局配置日志 logr ...

  2. FFMPEG 日志输出控制

    原文:https://blog.csdn.net/tea1896/article/details/48310579 1. FFMPEG 编码速度很慢,发现其中打印很多.因为打印是一个执行比较慢的动作, ...

  3. tomcat日志输出控制

    当禁用tomcat管理页面时,但是在服务器从启动时,在tomcat默认的/aliyun/tomcat7/logs/ 存放日志的目录下依然还会生成关于host-manager,manager的日志文件, ...

  4. jpress日志输出控制

    由于公司的服务访问量巨大,导致日志文件特别大,但是这些日志也没什么价值,考虑针对部分访问取消日志打印 复盘 项目使用的是jpress,中间转手好多人,没有文档,都不清楚项目结构 先在项目中搜索日志的几 ...

  5. C语言日志级别和作用,自己写的C语言通用日志框架,可以控制日志输出等级

    /************************************c语言通用日志框架************************************ * * @author 南栀(ke ...

  6. 细粒度控制Grails程序的日志输出

    标准的Grails是配置了日志输出的,但是,无法满足我们的需求.理想状态是想输出谁的日志,想输出哪个级别,就输出谁,就输出哪个级别.而且,不同的程序的日志应该有区分度,不能都叫一个名字. 首先,log ...

  7. Android系统10 RK3399 init进程启动(十八) isLoggable日志级别输出控制

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 在编写 ...

  8. linux机器上crontab定时任务将日志输出到以日期命名的log文件

    linux机器上crontab定时任务将日志输出到以日期命名的log文件 需求:将ansible-playbook脚本加到crontab定时执行linux服务器清理.把清理时打印的日志输出到以日期命名 ...

  9. linux查看gc日志,将GC日志输出到文件

    将GC日志输出到文件:不同JDK设置的参数不同,参考JDK官方文档 SUN:-Xloggc:filename (例如:-Xloggc:D:/gc.log)  linux windows IBM:-Xv ...

最新文章

  1. ps怎么制作流体_ps相框制作教程:ps怎么制作相框效果
  2. 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍
  3. linux 做双机热备
  4. Object.defineProperty与双向绑定、数据监听
  5. Filter的详解与配置应用
  6. 适配器模式原理及实例介绍
  7. java 找出list中相同数据_Java获取List中相同的数据
  8. 流体式布局与响应式布局_将固定像素设计转换为流体比例布局
  9. 如何使用eclemma插件_如何集成和使用EclEmma插件来获得良好的Junit覆盖率
  10. VC嵌入python时debug版lib下载
  11. 切面是异步还是同步操作‘_细说JS异步发展历程
  12. Spring定时任务高级使用篇
  13. mybatis执行opensession时空指针异常_关于 Mybatis 缓存的那点事儿,你知道吗?
  14. xcode 左边导航栏中,类文件后面的标记“A”,M,?……等符号的含义???(转)...
  15. 高速公路坐标高程计算软件3.5发布
  16. Windows 回声消除 怎么外放音乐不让对方听到
  17. 测试人收入情况大曝光,你的收入在什么水平
  18. Burp Suite抓包讲解
  19. gdb调试查看内存数据
  20. sql根据出生日期计算当前年龄 函数TIMESTAMPDIFF()

热门文章

  1. java tea加密_TEA 加密解法,统一了C语言、Java与PHP的运算结果
  2. SmartFlow测试LAN-LAN/WAN throughput
  3. 图像特征点及特征描述子总结
  4. Android4开发入门经典 之 第十二部分:最佳实践
  5. python selenium chrome 控制devtools 一些线索
  6. “渐冻症”运动神经元一般情况下会有哪些症状表现呢?
  7. 固化剂过量会加快涂层固化速度吗?
  8. msp430低功耗芯片概述
  9. 503 service temporarily unavailable的解决
  10. 配置多区域的OSPF协议