设计思路:

  1 用一个INI配置文件管理日志目录,日志文件限制的大小,特殊的日志名,特殊日志的大小限制。

  2 读取INI文件中的所有信息:每一个日志目录对应的大小限制,每一个特殊日志对应的大小限制。如特殊日志在既定的日志目录中需去除。

  3 按设置的大小循环检测并清理每一个日志文件。

  4 监听有名管道的信号,如读取到了修改了INI文件的信号,则重新开始读取,循环。

代码:

LogSizeLimit.h

#ifndef LOGSIZELIMIT_H_
#define LOGSIZELIMIT_H_ #include <map>
#include <vector>
#include <string.h>
#include "GlobDefine.h"
#include "Mutex.h" static const INT8 *IniFileName = "/LogService/LogSizeManage.ini";
//static const UINT32 LogFileSizeDefault = 2 * 1024 * 1024;
static const INT8 * LogFileSizeDefault = "2M";
static const INT8 *LogPipeName = "/LogService/LOGSIZE.fifo";
static const INT8 *ChangedStr = "changed";
static const UINT32 CleanInterval = ;
static const UINT32 LogFilePathMaxLen = ;
static const UINT32 LogFileAttrMaxLen = ; class LogSizeLimit {
// static Mutex mutex;
public:
LogSizeLimit(const string iniFile);
~LogSizeLimit();
bool start();
bool getChangeFlag() {
return changeFlag;
}
void setChangeFlag(bool status) {
changeFlag = status;
}
private:
string _iniFile;
map<string, string> _catelogAttr;
map<string, string> _specialFileAttr; map<string, vector<string> > _logFiles;
bool changeFlag; static void *run(void *args);
static void *listenChanged(void*args);
bool readConfig();
bool limitLogFile(); bool readFileList(const INT8 *mapStrPath, const INT8 *basePath);
bool checkAndCleanLog(string logName, INT32 size);
INT32 transSizeToBytes(const INT8 * size);
bool readPipeMsg();
}; #endif /* LOGSIZELIMIT_H_ */

LogSizeLimit.cpp

#include <pthread.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include "LogSizeLimit.h"
#include "IniConfigFile.h"
#include "Logger.h"
#include "FileOperation.h"
using namespace FrameWork; LogSizeLimit::LogSizeLimit(const string iniFile) :
_iniFile(iniFile), changeFlag(true) {
} LogSizeLimit::~LogSizeLimit() { } bool LogSizeLimit::start() {
pthread_t tid, changetid;
pthread_create(&tid, NULL, run, (void*) this);
pthread_create(&changetid, NULL, listenChanged, (void*) this);
return true;
} bool LogSizeLimit::readConfig() {
//Clean map vars
map<string, string>::iterator iter_tmp = _catelogAttr.begin();
while (iter_tmp != _catelogAttr.end()) {
_catelogAttr.erase(iter_tmp);
iter_tmp++;
}
//Clean map vars
iter_tmp = _specialFileAttr.begin();
while (iter_tmp != _specialFileAttr.end()) {
_specialFileAttr.erase(iter_tmp);
iter_tmp++;
}
//Clean map vars
map<string, vector<string> >::iterator mvIter_tmp = _logFiles.begin();
while (mvIter_tmp != _logFiles.end()) {
_logFiles.erase(mvIter_tmp);
mvIter_tmp++;
} if (!FileOperation::isExistFile(_iniFile)) {
Logger::GetInstance().Fatal("Can not find ini file : %s !",
_iniFile.c_str());
return false;
}
//Create ini file handling var.
IniConfigFile iniSet(_iniFile.c_str()); INT8 logPath[LogFilePathMaxLen] = { };
INT8 logFileAttr[LogFileAttrMaxLen] = { }; INT8 specialFile_1[LogFilePathMaxLen] = { };
INT8 specialFileAttr_1[LogFileAttrMaxLen] = { }; const INT8 *catelogBase = "catelog_";
const INT8 *limitBase = "logSizeLimit_";
const INT8 *specialFileBase = "specialFile_";
const INT8 *specialLimitBase = "specialFileSizeLimit_"; INT8 catelogCnt = '';
bool isExist = true; INT8 catelogIndex[] = { };
INT8 logSizeIndex[] = { }; while (isExist) { memset(catelogIndex, , );
memset(logSizeIndex, , );
memset(logPath, , LogFilePathMaxLen);
memset(logFileAttr, , LogFileAttrMaxLen); memcpy(catelogIndex, catelogBase, strlen(catelogBase));
memcpy(catelogIndex + strlen(catelogBase), &catelogCnt, );
memcpy(logSizeIndex, limitBase, strlen(limitBase));
memcpy(logSizeIndex + strlen(limitBase), &catelogCnt, ); //section key value
do {
if (iniSet.readIniConfFile("LogSizeManage", catelogIndex, logPath,
LogFilePathMaxLen) != true) {
Logger::GetInstance().Error("Can not locate %s !",
catelogIndex);
isExist = false;
break;
} else
Logger::GetInstance().Info("Get a catelog %s=%s !",
catelogIndex, logPath); if (iniSet.readIniConfFile("LogSizeManage", logSizeIndex,
logFileAttr, LogFilePathMaxLen) != true) {
Logger::GetInstance().Error(
"Can not get size %s, using default size %s !",
logSizeIndex, LogFileSizeDefault);
memcpy(logFileAttr, LogFileSizeDefault,
strlen(LogFileSizeDefault));
} else
Logger::GetInstance().Info("Get a log size attr %s !",
logFileAttr); _catelogAttr[logPath] = logFileAttr;
isExist = true;
map<string, string>::iterator iter;
iter = _catelogAttr.begin();
for (UINT32 i = ; i < _catelogAttr.size(); i++)
iter++;
cout << "_catelogAttr_size : " << _catelogAttr.size() << " begin : "
<< iter->first << " end : " << iter->second << endl; } while (); // read the normal catelogs memset(catelogIndex, , );
memset(logSizeIndex, , );
memset(logPath, , LogFilePathMaxLen);
memset(logFileAttr, , LogFileAttrMaxLen); memcpy(catelogIndex, specialFileBase, strlen(specialFileBase));
memcpy(catelogIndex + strlen(specialFileBase), &catelogCnt, );
memcpy(logSizeIndex, specialLimitBase, strlen(specialLimitBase));
memcpy(logSizeIndex + strlen(specialLimitBase), &catelogCnt, ); do {
if (iniSet.readIniConfFile("LogSizeManage", catelogIndex, logPath,
LogFilePathMaxLen) != true) {
Logger::GetInstance().Error("Can not locate a special log %s !",
catelogIndex);
break;
} else
Logger::GetInstance().Info("Get a special log %s=%s !",
catelogIndex, logPath); if (iniSet.readIniConfFile("LogSizeManage", logSizeIndex,
logFileAttr, LogFilePathMaxLen) != true) {
Logger::GetInstance().Error(
"Can not get log size %s, using default size %s !",
logFileAttr, LogFileSizeDefault);
memcpy(logFileAttr, LogFileSizeDefault,
strlen(LogFileSizeDefault));
// break;
} else
Logger::GetInstance().Info("Get a special log size %s !",
logFileAttr);
if (!isExist)
isExist = true; _specialFileAttr[logPath] = logFileAttr;
map<string, string>::iterator iter;
iter = _specialFileAttr.begin();
cout << "_specialFileAttr_size : " << _specialFileAttr.size()
<< " begin : " << iter->first << " end : " << iter->second
<< endl;
} while (); // read the special log files catelogCnt++;
} //while return true;
} //struct dirent
//{
// long d_ino; /* inode number 索引节点号 */
// off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
// unsigned short d_reclen; /* length of this d_name 文件名长 */
// unsigned char d_type; /* the type of d_name 文件类型 */其中d_type表明该文件的类型:文件(8)、目录(4)、链接文件(10)等。
// char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
//} bool LogSizeLimit::readFileList(const INT8 *mapStrPath, const INT8 *basePath) {
DIR *dir;
struct dirent *direntPtr;
char base[LogFilePathMaxLen] = { }; if ((dir = opendir(basePath)) == NULL) {
Logger::GetInstance().Error("Can not open directory %s ! ", basePath);
return false;
} while ((direntPtr = readdir(dir)) != NULL) {
if (strcmp(direntPtr->d_name, ".") ==
|| strcmp(direntPtr->d_name, "..") == ) ///current dir OR parrent dir
continue;
else if (direntPtr->d_type == ) { ///file
string fileName;
fileName += basePath;
if (basePath[strlen(basePath) - ] != '/')
fileName += '/';
fileName += direntPtr->d_name;
_logFiles[mapStrPath].push_back(fileName);
} else if (direntPtr->d_type == ) ///link file
Logger::GetInstance().Info("A link file : %s !", direntPtr->d_name);
else if (direntPtr->d_type == ) ///dir
{
memset(base, '\0', sizeof(base));
strcpy(base, basePath);
if (base[strlen(base) - ] != '/')
strcat(base, "/");
strcat(base, direntPtr->d_name);
readFileList(mapStrPath, base);
}
}
closedir(dir);
return true;
} bool LogSizeLimit::limitLogFile() {
changeFlag = true;
map<string, string>::iterator mIter;
for (mIter = _catelogAttr.begin(); mIter != _catelogAttr.end(); mIter++) {
if (!FileOperation::isExisteDirectory(mIter->first)) {
Logger::GetInstance().Fatal("Catelog %s is not existed !",
mIter->first.c_str());
} else {
Logger::GetInstance().Info("catelog %s is existed !",
mIter->first.c_str());
readFileList(mIter->first.c_str(), mIter->first.c_str());
}
} //
map<string, vector<string> >::iterator mvIter = _logFiles.begin();
vector<string>::iterator vIter;
bool deleteFlag = false;
while (mvIter != _logFiles.end()) {
vIter = mvIter->second.begin();
while (vIter != mvIter->second.end()) {
Logger::GetInstance().Info("Log file : %s : %s ",
mvIter->first.c_str(), vIter->c_str());
mIter = _specialFileAttr.begin();
for (; mIter != _specialFileAttr.end(); mIter++) {
deleteFlag = false;
//Remove the special log file from the normal catelog
if (strncmp(vIter->c_str(), mIter->first.c_str(),
strlen(vIter->c_str())) == ) {
Logger::GetInstance().Info(
"Remove log file for special log : %s !",
vIter->c_str());
vIter = _logFiles[mvIter->first].erase(vIter);
deleteFlag = true;
break;
}
}
if (!deleteFlag)
vIter++;
}
mvIter++;
} // Check change signal
while (changeFlag) {
mIter = _catelogAttr.begin();
for (; mIter != _catelogAttr.end(); mIter++) {
vIter = _logFiles[mIter->first].begin();
for (; vIter != _logFiles[mIter->first].end(); vIter++) {
// cout << "log clean : " << *vIter << " size ; "
// << transSizeToBytes(mIter->second.c_str()) << endl;
checkAndCleanLog(*vIter,
transSizeToBytes(mIter->second.c_str()));
}
} mIter = _specialFileAttr.begin();
for (; mIter != _specialFileAttr.end(); mIter++) {
// cout << "special log clean : "<<mIter->first<<endl;
checkAndCleanLog(mIter->first,
transSizeToBytes(mIter->second.c_str()));
}
sleep(CleanInterval);
} return true;
} bool LogSizeLimit::checkAndCleanLog(string logName, INT32 size) {
struct stat statbuff;
if (- == stat(logName.c_str(), &statbuff)) {
// Logger::GetInstance().Error("Can not Stat() log file %s !",
// logName.c_str());
return false;
} //Clean file
if (statbuff.st_size >= size) {
fstream fout(logName.c_str(), ios::out | ios::trunc);
fout.close();
}
return true;
} // Get bytes
INT32 LogSizeLimit::transSizeToBytes(const INT8 * size) {
if (size[strlen(size) - ] == 'M' || size[strlen(size) - ] == 'm') {
INT8 msize[] = { };
memcpy(msize, size, strlen(size) - );
return atoi(msize) * * ;
} else if (size[strlen(size) - ] == 'K' || size[strlen(size) - ] == 'k') {
INT8 ksize[] = { };
memcpy(ksize, size, strlen(size) - );
return atoi(ksize) * ;
} else {
Logger::GetInstance().Error("Unknow size %s !", size);
return ;
}
} void *LogSizeLimit::run(void *args) {
LogSizeLimit *logLimit = (LogSizeLimit*) args;
do {
logLimit->readConfig();
logLimit->limitLogFile();
} while (logLimit->getChangeFlag() == false); return NULL;
} void *LogSizeLimit::listenChanged(void*args) {
LogSizeLimit *logLimit = (LogSizeLimit*) args;
logLimit->readPipeMsg();
return NULL;
} // Listen fifo signal
bool LogSizeLimit::readPipeMsg() {
INT8 buf_r[];
INT32 fd;
INT32 nread; if ((mkfifo(LogPipeName, O_CREAT | O_EXCL) < ) && (errno != EEXIST))
Logger::GetInstance().Error("Can not create fifo server !"); memset(buf_r, , sizeof(buf_r));
fd = open(LogPipeName, O_RDONLY | O_NONBLOCK, );
if (fd == -) {
Logger::GetInstance().Error("Can not open fifo %s for %s !",
LogPipeName, strerror(errno));
return false;
}
while () {
memset(buf_r, , sizeof(buf_r));
if ((nread = read(fd, buf_r, )) == -) {
// if (errno == EAGAIN)
// printf("no data yet\n");
}
if ((strncmp(buf_r, ChangedStr, strlen(ChangedStr))) == ) {
Logger::GetInstance().Info("Get changed cmd !");
setChangeFlag(false);
}
sleep();
}
unlink(LogPipeName);
return true;
}

使用

echo changed > /LogService/LOGSIZE.fifo

可以使更新的INI配置立即生效。

INI配置文件:

[LogSizeManage]
catelog_1=/nand/log/
logSizeLimit_1=2M
catelog_2=/var/log
specialFile_1=/nand/log/App.log
specialFileSizeLimit_1=4M

Linux 日志文件管理——限制大小的更多相关文章

  1. Linux命令-文件管理(二)

    Linux命令-文件管理(二) Linux gitview命令 Linux gitview命令用于观看文件的内容,它会同时显示十六进制和ASCII格式的字码. 语法:gitview [-bchilv] ...

  2. Linux日志管理系统rsyslog

    一.日志的概念 什么是日志?日志就是历史事件.历史事件包括时间.地点.人物.时间.这个是生活中所说的日志很好理解.在Linux中也有类似的服务,它主要作用就是记录Linux系统的历史事件,包括什么时间 ...

  3. linux日志文件

    linux日志文件 在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时从容找出问题并加以解决. /var/log/messages — 包括整体系统信息,其中也包含系统启动期间的 ...

  4. 调整Linux磁盘分区的大小的方法

      昨天数据入库时,一直报错,说磁盘满了,,df -h    一看,发现/目录下只有50G空间,已使用49G:我的程序和dbss都安装在/目录下,ftp到的数据放在/data下的一个子目录下,分解完的 ...

  5. Linux日志轮循实现(shell)

    在Linux系统中,日志的使用非常频繁,那么对日志就需要一定策略的管理,包括存放目录的设计,log文件命名规则,历史log文件的存放,log目录的容量限制,另外还有日志轮循. 日志轮循就是,将过期的l ...

  6. Rsync,Linux日志及Screen工具介绍

    第十六次课 Rsync,Linux日志及Screen工具介绍 目录 一.rsync工具介绍 二.rsync常用选项 三.rsync通过ssh同步 四. rsync通过服务同步 五.linux系统日志 ...

  7. Linux日志分析的实战专题

      来自 日志也是用户应该注意的地方之一.不要低估日志文件对网络安全的重要作用,因为日志文件能够详细记录系统每天发生的各种各样的事件.用户可以通过日志文件 检查错误产生的原因,或者在受到攻击和黑客入侵 ...

  8. 【第六章】MySQL日志文件管理

    1.日志文件管理概述: 配置文件:/etc/my.cnf 作用:MySQL日志文件是用来记录MySQL数据库客户端连接情况.SQL语句的执行情况以及错误信息告示. 分类:MySQL日志文件分为4种:错 ...

  9. 转 Linux命令-文件管理命令

    http://jingyan.baidu.com/article/9113f81bc1c7a72b3214c7d3.html Linux命令-文件管理命令 浏览:4118 | 更新:2012-11-1 ...

随机推荐

  1. 海思uboot启动流程详细分析(二)

    1. 第二个start.S 从start_armboot开始,在startup.c中有包含#include <config.h> 在config.h中: /* Automatically ...

  2. .Net Core 在Linux服务器下部署程序--(4). 前端ReactWeb应用部署

    确认第二步中的软件已经安装完成 Nodejs前端Web服务器 Zip与UnZip压缩包软禁 nrm前端包源管理器 PM2前端Web程序守护进程 创建部署文件夹 如果已经执行过( 3. 租户平台后端程序 ...

  3. gradle下载及配置

    windows安装 1.下载地址:http://services.gradle.org/distributions/ 2.下载**-bin.zip,解压即可 配置环境变量:gradle_home:D: ...

  4. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  5. 小程序--scroll-view的横向滑动无效

  6. commons-lang3 事件机制 <EventListenerSupport>

    俗话说,站在巨人肩上,可以使我们走的更远 使用已有的java组件,可以提高我们的开发效率,减少出错几率,apache commons中包含有很多这样的组将,commons-lang3就是其中的一个,当 ...

  7. 设置SSH Key

    初始设置git config --global user.name "qian" git config --global user.email "1067803326@q ...

  8. 2019年3月8日_CCF-A类文章分享

    3月8日下午3点开始,王利朋老师主持实验室会议,实验室全体人员参加.首先王利朋老师就基全本子存在的问题进行了再一次的说明以及如何修改部分内容, 其次,王利朋老师对近段时间做了相关工作总结和下阶段任务分 ...

  9. Frame Interpolation

    对于视频网站.电视厂商以及进行视频压制的用户来说,改变视频的帧率算是一个比较常见的需求.视频网站改变帧率主要是为了向不同级别的网站用户提供差异化服务:电视厂商则是以提供更好的显示效果作为电视的卖点:对 ...

  10. cesium-navigation 使用(非require,es6引用)

    cesium-navigation-es6(非require,es6引用) 为什么你建立cesium-navigation插件? 插件形式不影响之前项目使用,es6 使用 首先,所有的Cesiumjs ...