Linux 日志文件管理——限制大小
设计思路:
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 日志文件管理——限制大小的更多相关文章
- Linux命令-文件管理(二)
Linux命令-文件管理(二) Linux gitview命令 Linux gitview命令用于观看文件的内容,它会同时显示十六进制和ASCII格式的字码. 语法:gitview [-bchilv] ...
- Linux日志管理系统rsyslog
一.日志的概念 什么是日志?日志就是历史事件.历史事件包括时间.地点.人物.时间.这个是生活中所说的日志很好理解.在Linux中也有类似的服务,它主要作用就是记录Linux系统的历史事件,包括什么时间 ...
- linux日志文件
linux日志文件 在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时从容找出问题并加以解决. /var/log/messages — 包括整体系统信息,其中也包含系统启动期间的 ...
- 调整Linux磁盘分区的大小的方法
昨天数据入库时,一直报错,说磁盘满了,,df -h 一看,发现/目录下只有50G空间,已使用49G:我的程序和dbss都安装在/目录下,ftp到的数据放在/data下的一个子目录下,分解完的 ...
- Linux日志轮循实现(shell)
在Linux系统中,日志的使用非常频繁,那么对日志就需要一定策略的管理,包括存放目录的设计,log文件命名规则,历史log文件的存放,log目录的容量限制,另外还有日志轮循. 日志轮循就是,将过期的l ...
- Rsync,Linux日志及Screen工具介绍
第十六次课 Rsync,Linux日志及Screen工具介绍 目录 一.rsync工具介绍 二.rsync常用选项 三.rsync通过ssh同步 四. rsync通过服务同步 五.linux系统日志 ...
- Linux日志分析的实战专题
来自 日志也是用户应该注意的地方之一.不要低估日志文件对网络安全的重要作用,因为日志文件能够详细记录系统每天发生的各种各样的事件.用户可以通过日志文件 检查错误产生的原因,或者在受到攻击和黑客入侵 ...
- 【第六章】MySQL日志文件管理
1.日志文件管理概述: 配置文件:/etc/my.cnf 作用:MySQL日志文件是用来记录MySQL数据库客户端连接情况.SQL语句的执行情况以及错误信息告示. 分类:MySQL日志文件分为4种:错 ...
- 转 Linux命令-文件管理命令
http://jingyan.baidu.com/article/9113f81bc1c7a72b3214c7d3.html Linux命令-文件管理命令 浏览:4118 | 更新:2012-11-1 ...
随机推荐
- Vue.js05:vue内联样式
对象就是无序键值对的集合 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- python3通过os模块统计指定目录下文件个数
代码: import os path = r"C:\Users\Administrator\Desktop\***" print('filenum:',len([lists for ...
- 元数据Metadata
元数据是什么? 元数据(Metadata),又称中介数据.中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置.历史数据. ...
- HTML基础-------HTML标签(1)
HTML标签(1) h系列(容器级双标签) h系列标签分为六个等级(h1,h2,h3,h4,h5,h6) 语义:给文本添加一个标题 标题重要程度逐级递减,一个页面只能有一个h1级的标签,并且大多数时候 ...
- Django-CRM项目学习(八)-客户关系系统整体实现(待完成!)
注意点:利用stark组件与rbac组件实现客户关系系统 1.需求整理与确认 1.1 客户关系系统整体需求 a
- windows 和linux 路径解析的区别
windows下使用的是“\”作为分隔符,而linux则反其道而行之使用"/"作为分隔符.所以在windows 环境中获取路径常见 C:\windows\system 的形式,而l ...
- Redis详解(五)------ redis的五大数据类型实现原理
前面两篇博客,第一篇介绍了五大数据类型的基本用法,第二篇介绍了Redis底层的六种数据结构.在Redis中,并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这些对 ...
- openstack第五章:cinder
第五篇cinder— 存储服务 一.cinder 介绍: 理解 Block Storage 操作系统获得存储空间的方式一般有两种: 通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接 ...
- React 精要面试题讲解(五) 高阶组件真解
说明与目录 在学习本章内容之前,最好是具备react中'插槽(children)'及'组合与继承' 这两点的知识积累. 详情请参照React 精要面试题讲解(四) 组合与继承不得不说的秘密. 哦不好意 ...
- Photoshop给草坪上的人物加上唯美的紫色霞光
最终效果 1.打开原图素材大图,创建可选颜色调整图层,对黄色,绿色进行调整,参数设置如图1,2,效果如图3.这一步给地面部分增加橙黄色. <图1> <图2> <图3> ...