本文最后更新于 353 天前,其中的信息可能已经有所发展或是发生改变。
/*
时间:2023/09/12
作者:马文杰
代码功能:存储文件之前,检查内存使用百分比,内存使用超过80%会自动删除最老旧的文件,以此来保证系统正常运行
函数名称: getLogUsePercentage / findMatchingFile / compareFileNames / delOldLogFile / main
历史:
日期:2023/09/21
作者:mawenjie
修改:函数delOldLogFile中有一处没有释放资源,是在combinedTime 申请资源失败时没有释放,文中已有记录标记。
*/
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
/*
函数功能: 获取系统指定路径下内存使用的百分比
*/
int getLogUsePercentage()
{
int iUsePcent = -1;
char line[512] = {0};
// 执行df命令并读取输出
FILE* pipe = popen("df /home/delphi/solo", "r");
if (pipe == NULL)
{
perror("Failed to execute df command");
exit(EXIT_FAILURE);
}
// 读取df命令的输出
while(fgets(line, sizeof(line), pipe));
printf("[+][%s:%d] line: %s\n",__FUNCTION__,__LINE__,line); // "56%"
pclose(pipe);
// 解析输出并提取百分比信息
sscanf(line, "%*s %*s %*s %*s %d%%", &iUsePcent);
printf("[+][%s:%d] iUsePcent: %d\n",__FUNCTION__,__LINE__,iUsePcent);
return iUsePcent;
}
/*
函数功能: 字符串匹配,根据字符串的一部分,匹配到一个完整的字符串(文件名称)
*/
char* findMatchingFile(const char* directory, const char* searchString)
{
DIR* dir = opendir(directory);
if (dir == NULL)
{
printf("[+][%s:%d] 无法打开目录: %s\n",__FUNCTION__,__LINE__,directory);
return NULL;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
if (entry->d_type == DT_REG) // 只处理普通文件
{
char* fileName = entry->d_name;
if (strstr(fileName, searchString) != NULL) // 匹配文件名
{
char* filePath = malloc(strlen(directory) + strlen(fileName) + 2); // 分配足够的内存来存储文件路径
if (filePath == NULL)
{
closedir(dir);
retturn NULL;
}
sprintf(filePath, "%s/%s", directory, fileName);
closedir(dir);
printf("[+][%s:%d] 匹配到的文件路径: %s\n",__FUNCTION__,__LINE__,filePath);
return filePath;
}
}
}
closedir(dir);
return NULL; // 没有找到匹配的文件
}
/*
函数功能: qsort排序的规则
*/
int compareFileNames(const void* a, const void* b)
{
return strcmp(*(const char**)a, *(const char**)b);
}
/*
函数功能: 删除旧的文件,保证存储文件之前,空间是足够的
*/
void delOldLogFile(void)
{
// 删除路径下最老的文件
const char* logPath = "/home/delphi/solo";
char* combinedTime = NULL;
int i = 0;
struct dirent* entry;
char** fileNames = NULL;
int numFiles = 0;
DIR* dir = opendir(logPath);
if (dir == NULL)
{
printf("[+][%s:%d] 无法打开目录: %s\n",__FUNCTION__,__LINE__,logPath);
return;
}
while ((entry = readdir(dir)) != NULL)
{
if (entry->d_type == DT_REG) // 只处理普通文件
{
char* fileName = entry->d_name;
if (strstr(fileName, ".log") != NULL) // 只处理以.log结尾的文件
{
char* timePart = strtok(fileName, "_"); // 提取文件名中的时间部分
if (timePart != NULL)
{
// 判断文件名的数字部分的时间
char* secondPart = strtok(NULL, "_"); // 提取文件名中的第二部分
if (secondPart != NULL)
{
combinedTime = malloc(strlen(timePart) + strlen(secondPart) + 2); // 分配足够的内存来存储两个部分的时间
if (combinedTime == NULL)
{
closedir(dir); /* 2023/09/21修改 */
return;
}
strcpy(combinedTime, timePart);
strcat(combinedTime, secondPart);
long long fileTime = atoll(combinedTime);
printf("[+][%s:%d] 文件组装: %s 文件转换成longlong类型:%d\n",__FUNCTION__,__LINE__,combinedTime,fileTime);
if (fileTime != 0)
{
fileNames = realloc(fileNames, (numFiles + 1) * sizeof(char*));
fileNames[numFiles] = strdup(combinedTime);
numFiles++;
}
free(combinedTime);
}
}
}
}
}
closedir(dir);
if (numFiles == 0)
{
printf("[+][%s:%d] 目录: %s 中没有日志文件\n",__FUNCTION__,__LINE__,logPath);
return;
}
// 按文件名进行排序
qsort(fileNames, numFiles, sizeof(char*), compareFileNames);
// 看一下这个排序之后的输出结果对不对
for (i = 0; i < numFiles; i++)
printf("[+] 排序结果fileNames:%s\n",fileNames[i]);
// 获取最老的文件名
char* oldestFileNameNum = fileNames[0];
// 打印最老的文件名 20231201221202 -> 20231201_221202
char oldFileName[16];
strncpy(oldFileName, oldestFileNameNum, 8);
oldFileName[8] = '_';
oldFileName[9] = '\0';
strcat(oldFileName, oldestFileNameNum + 8);
printf("[+][%s:%d] 获取最老的文件名:%s\n",__FUNCTION__,__LINE__,oldFileName);
// 这个文件还需要再文件夹中遍历,找到匹配的文件 20231201_221202 -> 20231201_221202_syslog_user.log
const char* directory = "/home/delphi/solo";
char* oldestFilePath = findMatchingFile(directory, oldFileName);
if (oldestFilePath != NULL)
{
printf("即将删除的文件: %s\n", oldestFilePath);
remove(oldestFilePath);
free(oldestFilePath);
}
else
{
printf("未找到匹配的文件\n");
}
// 释放内存
for (i = 0; i < numFiles; i++)
{
free(fileNames[i]);
}
free(fileNames);
return;
}
/*
函数功能:存储文件之前,检查内存使用概率,内存使用超过80%会自动删除最老旧的文件,以此来保证系统正常运行
*/
int main()
{
int iUsePcent = -1;
iUsePcent = getLogUsePercentage();
// 读取文件名称并删除旧文件,直到剩余空间达到20%
if(iUsePcent > 80)
printf("剩余空间不足,读取文件名称并删除旧文件\n");
while (iUsePcent > 80)
{
// TODO: 在此处添加读取文件名称和删除旧文件的代码
delOldLogFile();
// 更新使用的百分比
iUsePcent = getLogUsePercentage();
}
// 保存文件
printf("剩余空间足够,保存文件\n");
// ...
return 0;
}
修改:函数delOldLogFile中有一处没有释放资源