我想知道在做logrotate时我的选择是什么 对于从不关闭其文件描述符的进程。我知道了 "重启服务"和 copytruncate 选项。但是,假设重启过程是不合需要的,应用程序不响应SIGHUP,并且由于潜在的数据丢失, copytruncate 是不可接受的,我不知道我有哪些选项剩下。
我想到的一个解决方案是将已命名的管道放在哪里 该过程即将登录。从该管道读取另一个实用程序(复制到另一个日志文件)并让它对SIGHUP信号作出反应(来自logrotate)。
现在我的问题是,我已经可以使用这个了吗? 如果没有,为什么?这种方法有什么本质上的错误吗?
为了测试这个,我做了2次测试,一次用拷贝截断确认数据丢失, 还有一个来测试我的名字管+健身'的方法:
证明copytruncate丢失:
app.c
int main(int argc, char *argv[]) {
FILE* f = fopen("log.txt", "a");
int cnt = 0;
for (int i = 0; i < 1000000; i++) {
for (int j = 0; j < 100; j++) {
fprintf(f, "Logging line %d\n", cnt);
cnt++;
}
fflush(f);
}
fflush(f);
fclose(f);
printf("Wrote %d lines\n", cnt);
return 0;
}
随附的logrotate配置:
$cat /etc/logrotate.d/logexp
/home/synepis/git/logexp/log.txt {
size 20M
create 700 synepis users
rotate 4
copytruncate
}
最后,我运行了应用程序,在它运行期间,我通过以下方式手动启动了logrotate几次:
logrotate --force /etc/logrotate.d/logexp
应用结果:
./app
Wrote 100000000 lines
记录行数:
$ cat log.txt* | wc -l
69091700
日志实用程序方法:
我实施了一个简单的实用工具&#39; loghup&#39;这会创建一个命名管道&#39; log.txt&#39;然后简单地将其读取到&#39; safe_log.txt&#39;。 最后,它通过重新打开文件来响应SIGHUP(从而开始新的日志轮换)。
loghup.c
int sighup = 0;
void sig_handler(int signo) {
if (signo == SIGHUP)
sighup = 1;
}
void do_piping(char *input, char *output) {
int fi = open(input, O_RDONLY);
int fo = open(output, O_WRONLY | O_CREAT, 0644);
size_t ret;
char buff[4096];
while((ret = read(fi, buff, 4096)) != 0) {
if(ret == -1 && errno == EINTR) { // Retry later
continue;
} else if (ret == -1) {
break; // Error occured
}
write(fo, buff, ret);
if (sighup) { // Reopen output log file on SIGHUP
close(fo);
fo = open(output, O_WRONLY | O_CREAT, 0644);
sighup = 0;
}
}
close(fo);
close(fi);
}
int main(int argc, char *argv[]) {
char *input_file = argv[1];
char *output_file = argv[2];
signal(SIGHUP, sig_handler); // Setup signal handler
mkfifo(input_file, S_IRUSR | S_IWUSR); // Create named pipe
do_piping(input_file, output_file);
}
使用SIGHUP的新logrotate配置:
$cat /etc/logrotate.d/logexp
/home/synepis/git/logexp/safe_log.txt {
size 20M
create 700 synepis users
rotate 4
postrotate
/bin/kill -SIGHUP $(ps aux | grep "[l]oghup" | awk '{print $2}')
endscript
}
然后我跑了:
./app
./loghup log.txt safe_log.txt
最后强迫logrotate几次:
$ cat safe_log.txt* | wc -l
100000000