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 ...
随机推荐
- Linq语法常见普通语法
闲言碎语 近期比较忙,但还是想写点什么,就分享一些基础的知识给大家看吧,希望能帮助一些linq新手,如果有其它疑问,可以进右上角群,进行交流探讨,谢谢. 开门见山 读这篇文章之前,我先说下,每一种搜索 ...
- 使用make
5.11 库的使用 代码的复用是计算机程序设计语言中的一个重要的概念.可以把编译好的目标文件模块统一放到一个库中,使得程序员可以在不同的程序中共享这些代码. 在Linux操作系统下,最后连接生成可执行 ...
- MacOS 10.13.6 下装xcode 流程
1.最好先安装brew https://github.com/Homebrew/brew/releases 自动安装脚本 /usr/bin/ruby -e "$(curl -fsSL htt ...
- Luogu4655 [CEOI2017]Building Bridges
Luogu4655 [CEOI2017]Building Bridges 有 \(n\) 根柱子依次排列,每根柱子都有一个高度.第 \(i\) 根柱子的高度为 \(h_i\) . 现在想要建造若干座桥 ...
- 【vue】iView-admin2.0动态菜单路由
vue项目实现动态路由有俩种方式 一.前端在routers中写好--所有--路由表 <前端控制路由>,登录时根据用户的角色权限来动态的显示菜单路由 二.前端通过调用接口请求拿到当前用户-- ...
- scala的多种集合的使用(5)之数组Array(ArrayBuffer)的操作
1.创建和更新数组的不同方式 1)定义一个数组的初始大小和类型,随后填充值. scala> val array = new Array[String](3) array: Array[Strin ...
- myeclipse新建javaweb项目,并部署到tomcat
myeclipse使用的版本: 新建web项目: File-->New-->Web Project,输入项目名称,选择J2EE规范. 完成后: JRE System Library是只要做 ...
- 微信内分享第三方H5链接无法使用内置浏览器打开的解决方案
很多朋友在微信内想分享转发H5链接的时候都会很容易碰到H5链接在微信内无法打开或在微信内无法打开app下载页的情况.通常这种情况微信会给个提示 “已停止访问该网址” ,那么导致这个情况的因素有哪些呢, ...
- Kubernetes & Docker
Docker核心技术原理及其应用 Docker 概览 Docker版本与安装介绍 Docker 核心技术之镜像 Docker 核心技术之容器 Docker 核心技术之容器与镜像 Docker 核心技术 ...
- 滴滴 CTO 架构师 业务 技术 战役 时间 赛跑 超前 设计
滴滴打车CTO张博:生死战役,技术和时间赛跑-CSDN.NEThttps://www.csdn.net/article/2015-06-25/2825058-didi 滴滴出行首席架构师李令辉:业务的 ...