linux基于file的logger
我们可能会遇到这样的问题:即写出的代码可能需要编译成动态连接库并在不同运行环境下运行,而这些运行环境下log的输出方式可能不同,一种运行环境的log方式在另一种运行环境下可能无法输出。而为保证多种运行环境下的运行正确,我们不能在程序中使用特定运行环境的log机制,于是我们需要找到一种能够在多种运行环境下均能使用的log方式。
有两种办法可以解决这个问题,一种是写一个抽象层的log库,用插件的方式在不同运行环境中加载为当时运行环境编写的log适配插件。另一种方式是将log输出到一个各种运行环境都能看到的地方,这里选择了file,之后为特殊运行环境单独写一个log读取器,将log内容重新输出到当时运行环境中。
我这里演示后一种方式:创建一个如下名为demo_file_logger.h的文件
/**
* demo_file_logger.h
*/
#ifndef DEMO_FILE_LOGGER_H
#define DEMO_FILE_LOGGER_H #include <sys/file.h>
#include <stdio.h>
#include <assert.h>
class DemoFileLogger
{
public:
static DemoFileLogger& ref()
{
static DemoFileLogger self;
return self;
} ~DemoFileLogger()
{
if (ok())
{
fclose(file);
file = nullptr;
}
} FILE* lock()
{
flock(file->_fileno, LOCK_EX);
return file;
} void unlock()
{
flock(file->_fileno, LOCK_UN);
} bool ok()
{
return file != nullptr;
} private:
DemoFileLogger()
{
file = fopen(logFileName, "a");
assert(file);
} private:
static constexpr const char* logFileName { "/tmp/demo_file_log.log" };
FILE* file { nullptr };
}; #define DEMO_FILE_DEBUG(...) if (DemoFileLogger::ref().ok()) { \
auto f = DemoFileLogger::ref().lock(); \
if (f) { \
fseek(f, , SEEK_END); \
fprintf(f, __VA_ARGS__);\
fprintf(f, "\r\n"); \
} \
DemoFileLogger::ref().unlock(); }
#define DEMO_FILE_INFO DEMO_FILE_DEBUG
#define DEMO_FILE_WARNING DEMO_FILE_DEBUG
#define DEMO_FILE_ERROR DEMO_FILE_DEBUG #endif /* DEMO_FILE_LOGGER_H */
之后在另一个头文件demo_debug.h中使用开关ENABLE_DEMO_FILE_LOG来开启FILE LOG的功能
/**
* demo_debug.h
*/ #ifndef DEMO_DEBUG_H
#define DEMO_DEBUG_H #ifdef ENABLE_DEMO_FILE_LOG
#include "demo_debug_file.h"
#else // ENABLE_DEMO_FILE_LOG
#include "demo_debug_disable.h
#endif // ENABLE_DEMO_FILE_LOG #endif // DEMO_DEBUG_H
我们可以在其他程序代码里使用我们的log宏:
/**
* main.cpp
*/ #include <unistd.h> #define ENABLE_DEMO_FILE_LOG
#include "demo_debug.h" int main(int argc, char* argv[])
{
for (int i = ; i < ; ++i)
{
DEMO_FILE_DEBUG("hello world %d", i);
sleep();
}
return ;
}
这样,log就保存到了/tmp/demo_file_log.log中,我们可以用一个log读取器去实时读取这个log,并且清空这个临时文件,以保证其不会占用过多系统资源,下面是一个python写的示例:
#!/usr/bin/env python def __main():
import fcntl
import time
f = open("/tmp/demo_file_log.log", "a+")
if f:
while True:
f.seek(0, 2)
fl = f.tell()
f.seek(0)
fcntl.flock(f.fileno(), fcntl.LOCK_SH)
if fl > 0:
reading = True
while reading:
s = f.read(1024)
print(s)
if f.tell() >= fl:
reading = False
fcntl.flock(f.fileno(), fcntl.LOCK_UN) fcntl.flock(f.fileno(), fcntl.LOCK_EX)
reading = True
curpos = f.tell()
f.seek(0, 2)
fl = f.tell()
f.seek(curpos, 0)
if fl - curpos > 0:
while reading:
s = f.read(1024)
print(s)
if f.tell() >= fl:
reading = False
f.truncate(0)
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
time.sleep(0.01) if __name__ == "__main__":
__main()
linux基于file的logger的更多相关文章
- Linux -- 基于zookeeper的java api(二)
Linux -- 基于zookeeper的java api(二) 写一个关于基于集群的zookeeper的自定义实现HA 基于客户端和监控器:使用监控的方法查看每个注册过的节点的状态来做出操作. Wa ...
- Linux -- 基于zookeeper的java api(一)
Linux -- 基于zookeeper的java api 首先启动你所有的 zkService.sh 查看状态:检查是否启动正确 [root@hu-hadoop2 ~]# zkServer.sh s ...
- linux -- 基于zookeeper搭建yarn的HA高可用集群
linux -- 基于zookeeper搭建yarn的HA高可用集群 实现方式:配置yarn-site.xml配置文件 <configuration> <property> & ...
- linux C file format analysis
c语言文件格式 source file file.c C source, ASCII text pretreatment 预处理文件 file.i C source, ASCII text assem ...
- linux move file / folder bash command
linux move file / folder bash command mv $ which mv $ man mv # mv [-f] source target/ target folder ...
- Linux基于Docker的Redis主从复制、哨兵模式搭建
本教程基于CentOS7,开始本教程前,请确保您的Linux系统已安装Docker. 1.使用docker下载redis镜像 docker pull redis 安装完成后,使用docker imag ...
- 基于File NIO写的一个文件新增内容监控器
基于File NIO写的一个文件新增内容监控器 需求说明 监控一个文件,如果文件有新增内容,则在控制台打印出新增内容. 代码示例 FileMoniter文件监控器类 package com.black ...
- 嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示
在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们 ...
- Linux Kernel File IO Syscall Kernel-Source-Code Analysis(undone)
目录 . 引言 . open() syscall . close() syscall 0. 引言 在linux的哲学中,所有的磁盘文件.目录.外设设备.驱动设备全部被抽象为了"文件" ...
随机推荐
- Global.asax 文件是什么(转)
原文链接:http://www.cnblogs.com/I-am-Betty/archive/2010/09/06/1819558.html MSDN :https://msdn.microsoft. ...
- NOR型flash与NAND型flash的区别
1) 闪存芯片读写的基本单位不同 应用程序对NOR芯片操作以“字”为基本单位.为了方便对大容量NOR闪存的管理,通常将NOR闪存分成大小为128KB或者64KB的逻辑块,有时候块内还分成扇区.读写时 ...
- 零基础学习hadoop到上手工作线路指导
零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...
- 安装Python
因为Python是跨平台的,它可以运行在Windows.Mac和各种Linux/Unix系统上.在Windows上写Python程序,放到Linux上也是能够运行的. 要开始学习Python编程,首先 ...
- Altium Designer快捷键 【worldsing笔记】
Shift + R 切换三种布线模式 (忽略, 避开或推挤) Shift + E 触发电气格点开/关 Shift + B 建立查询 Shift + PgUp 放大到最小的递增 Shift + PgDn ...
- Struts2 + Spring + Hibernate 通用 Service 和 DAO
我在 Struts2 + Spring + Hibernate 项目开发中总结出了一个Service 和 DAO ,可以用于处理任何的pojo(bean).使用这两个Service 和 DAO 可以 ...
- HDU 1018 Big Number
LINK:HDU 1018 题意:求n!的位数~ 由于n!最后得到的数是十进制,故对于一个十进制数,求其位数可以对该数取其10的对数,最后再加1~ 易知:n!=n*(n-1)*(n-2)*...... ...
- Ajax调用WebService(一)
Ajax调用WebService(一) http://www.cnblogs.com/leslies2/archive/2011/01/26/1934889.html 分类: Ajax 使用技术 We ...
- linux makefile: c++ 编程_基础入门_如何开始?
学习android 终究还是需要研究一下其底层框架,所以,学习c++很有必要. 这篇博客,算是linux(ubuntu) 下学习 c++ 的一个入门. 刚开始学习编程语言的时候,最好还是使用命令行操作 ...
- android自动填充短信验证码
自动拦截短信实际上就是在系统注册一个BroadcastReceiver,然后通过设置拦截短信的: filter.addAction("android.provider.Telephony.S ...