【发布时间】:2015-03-02 15:07:17
【问题描述】:
我想打开一个文件并继续在其中写入一些日志。但是限制它
- 按文件大小,如 50kb 或
- 文件被允许写入的持续时间。
这是允许写入文件的唯一两个条件,然后它将创建自己的备份并再次为新文件重新启动相同的过程。它会一直持续下去。稍后将使用备份文件来填充数据库。
知道怎么做。我可能会使用哪些功能?
【问题讨论】:
-
所以是你的程序在写文件,那么谁在阻止你跟踪写作?
我想打开一个文件并继续在其中写入一些日志。但是限制它
这是允许写入文件的唯一两个条件,然后它将创建自己的备份并再次为新文件重新启动相同的过程。它会一直持续下去。稍后将使用备份文件来填充数据库。
知道怎么做。我可能会使用哪些功能?
【问题讨论】:
您可以通过以下方式实现文件大小限制:
~/shell.sh | head -c 50K > test.log
您可以通过以下方式实现文件时间限制:
1 秒: 超时 1s ~/shell.sh > test.log
1 分钟
timeout 1M ~/shell.sh > test.log
【讨论】:
要检查文件状态,您可以使用fstat。
它将返回一个结构,告诉您上次访问时间和总文件大小。如果您想知道文件的创建时间,您需要自己跟踪它。
fstat 作用于文件描述符,所以如果你使用FILE,你必须得到它的描述符。
【讨论】:
计时器:
如果你想在 c 中使用计时器,最好的方法是使用alarm 函数。
示例:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
unsigned int timedout = 0;
void onAlarmTimeout(int signal) {
timedout = 1;
}
int main() {
signal(SIGALRM, onAlarmTimeout);
printf("Setting Timer\n");
alarm(10);
while(timeout == 1);
printf("Timeout..\n");
return 0;
}
文件大小:
要获取文件大小,请使用:
stat - 如果你知道文件名。fstat - 如果你有文件描述符。lstat - 如果你想stat 一个符号链接指向的文件。并使用st_size 成员获取文件的总大小(以字节为单位)。
示例:
#include <sys/stat.h>
off_t getFileSize(const char *fileName) {
struct stat st;
if (stat(fileName, &st) == 0)
return st.st_size;
return -1;
}
或使用:
fseek 到文件末尾并调用ftell 来获取文件大小,但是要使用fseek 和ftell 方法,您需要通过添加b 将文件作为二进制文件打开fopen 调用中的文件模式。
示例:
// Error checking is ignored for clarity
FILE *fptr = fppen("file","rb");
// seek to end of the file
fseek(fptr, 0L, SEEK_END);
size = ftell(fptr);
// seek back to beginning of file
fseek(f, 0, SEEK_SET);
这里是一个示例代码,它实现了日志写入,这里的文件大小是根据写入文件的字节数来计算的。
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <linux/limits.h>
unsigned int currentLogFileSize = 0; // to store Log size
const unsigned int maxLogFileSize = 4096; // Max Log Size
const char* logFilePath = "./logFile"; // Log File Path
const unsigned int WRITETIME = 3; // Write log time
unsigned int timedout = 0; // timeout flag
FILE* logFilePtr = NULL;
FILE* openLogFile(const char* logFileName) {
FILE* logFilePtr = NULL;
// Open Log File
if ((logFilePtr = fopen(logFilePath,"w")) == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n",
logFilePath, strerror(errno));
return NULL;
}
timedout = 0;
alarm(WRITETIME); // Set alarm with WriteTime
currentLogFileSize = 0; // Reset current log File size
return logFilePtr;
}
// Backup the log File
int backupLog(void) {
static count = 1; // for creating backup file name
char newLogFilePath[PATH_MAX];
snprintf(newLogFilePath,PATH_MAX,"%s_%d",logFilePath,count++);
// Close previous log File
if (fclose(logFilePtr) == -1) {
fprintf(stderr, "Cannot close file %s: %s\n",
logFilePath, strerror(errno));
return -1;
}
// Rename the current file to new log File
if (rename(logFilePath,newLogFilePath) == -1) {
fprintf(stderr, "Cannot rename file %s to %s: %s\n",
logFilePath, newLogFilePath, strerror(errno));
return -1;
}
fprintf(stdout,"Backed Up log File %s to %s\n",logFilePath,newLogFilePath);
// Open a the log File again for writing.
if ((logFilePtr = openLogFile(logFilePath)) == NULL)
return -1;
return 0;
}
// On timer timeout call backup log function
void timeout_trigger(int sig) {
timedout = 1;
}
// Write log File.
int fwriteLog(const char* strlog) {
// if log File is not opened open a new log file
if (logFilePtr == NULL)
if ((logFilePtr = openLogFile(logFilePath)) == NULL)
goto cleanUp;
if (currentLogFileSize + strlen(strlog) >= maxLogFileSize) {
fprintf(stdout,"Max Log File Size %d reached!...\n",currentLogFileSize);
if (backupLog() == -1)
goto cleanUp;
}
// on timeout
if (timedout) {
timedout = 0;
fprintf(stdout,"Log Write timeout %d..\n",WRITETIME);
if (backupLog() == -1)
goto cleanUp;
}
if (fwrite(strlog,sizeof(char),strlen(strlog),logFilePtr) != strlen(strlog)) {
fprintf(stderr, "Cannot write to file %s: %s\n",
logFilePath, strerror(errno));
goto cleanUp;
}
// Keep track of log file size
currentLogFileSize += strlen(strlog);
return 0;
// any error happens perform cleanup
cleanUp:
fclose(logFilePtr);
logFilePtr = NULL;
currentLogFileSize = 0;
return -1;
}
int main(void) {
// on alarm timeout calls timeout_trigger function
signal(SIGALRM, timeout_trigger);
int i = 0;
for(i = 0; i < 20; ++i) {
sleep(1);
fwriteLog("logit\n");
}
return 0;
}
【讨论】: