将DOS中的程序的stdout管道化为每日滚动日志文件?

时间:2010-05-21 02:35:37

标签: logging dos

我有一个由cmd脚本启动的DOS程序,该脚本会转储我想在日志文件中跟踪的大量数据。我可以轻松地将它传递给一个文件 - 但我需要一个滚动的日志文件。

是否有一种简单的方法可以将输出传递给将生成每日滚动日志文件的程序? (即每天创建一个新文件)

1 个答案:

答案 0 :(得分:0)

如果您不控制正在运行的程序的源,则有一种可能性是使用另一个脚本作为计划任务运行,该脚本将关闭程序,移动日志文件并重新启动程序。安排在午夜左右的某个地方。

如果不能定期关闭程序,另一种可能性是开发一个过滤程序,它将采用标准输入并根据今天的日期将其发送到日志文件。该程序可以检测日期更改,并在文件跨越午夜边界时关闭/重新打开文件。

然后通过此过滤器管道原始程序的输出。顺便说一句,这是真正的管道。你目前正在做的不是技术上的管道而是重定向(管道进入一个进程,重定向进入一个文件)。

伪代码类似于:

lastDate = ""
currFile = null
while not end of file on standard input:
    get line from standard input
    currDate = getDate()
    if currDate not equal to lastDate:
        if currFile not null:
            close currFile
        currFile = open("prefix_"+currDate+".log")
    write line to currFile
if currFile not null:
    close currFile
exit

作为概念证明,这是一个运行的脚本(qqtest.sh),每十三秒产生一次,十次:

#!/usr/bin/bash
for i in 0 1 2 3 4 5 6 7 8 9 ; do
    echo $i $(date)
    sleep 13
done

这是一个C过滤程序(qq.c),它完成了我在上面的答案中描述的内容:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

static char *getDate (void) {
    static char tbuff[sizeof("yyyymmddhhmm")]; // "yyyymmdd" for date.
    time_t now = time (0);
    struct tm *tm = localtime (&now);
    strftime (tbuff, 100, "%Y%m%d%H%M", tm);   // "%Y%m%d" for date.
    return tbuff;
}

int main (void) {
    int ch, lastCh = '\n';
    FILE *fOut = NULL;
    char *currDate, *lastDate = strdup ("");
    char fspec[1000];

    // Just process characters until finished.

    while ((ch = fgetc (stdin)) != EOF) {
        // Only switch logs if first character of a line.

        if (lastCh == '\n') {
            // Has date changed?

            currDate = getDate();
            if (strcmp (currDate, lastDate) != 0) {
                // Yes, close old file if there was one.

                if (fOut != NULL)
                    fclose (fOut);

                // Then store new date and open new file.

                free (lastDate);
                lastDate = strdup (currDate);
                sprintf (fspec, "qqfile_%s.log", lastDate);
                fOut = fopen (fspec, "w");
            }
        }

        // Output character to current file then save.

        fputc (ch, fOut);
        lastCh = ch;
    }

    // Clean up memory and file handles, then exit.

    free (lastDate);
    if (fOut != NULL)
        fclose (fOut);

    return 0;
}

执行时:

./qqtest.sh | ./qq

它会创建以下文件。

$ cat qqfile_201005211146.log
0 Fri May 21 11:46:40 WAST 2010
1 Fri May 21 11:46:53 WAST 2010

$ cat qqfile_201005211147.log
2 Fri May 21 11:47:06 WAST 2010
3 Fri May 21 11:47:19 WAST 2010
4 Fri May 21 11:47:33 WAST 2010
5 Fri May 21 11:47:46 WAST 2010
6 Fri May 21 11:47:59 WAST 2010

$ cat qqfile_201005211148.log
7 Fri May 21 11:48:12 WAST 2010
8 Fri May 21 11:48:25 WAST 2010
9 Fri May 21 11:48:38 WAST 2010

请注意,这会使用分钟边界来切换日志文件。更改getDate函数以使用日期边界(参见注释)是一件简单的事情。