对从不关闭日志文件描述符的进程进行Logrotate

时间:2017-02-18 16:25:13

标签: c linux logging named-pipes logrotate

我想知道在做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

0 个答案:

没有答案