将 DOS 中程序的标准输出通过管道传输到每日滚动日志文件?

发布于 2024-09-02 04:56:08 字数 134 浏览 6 评论 0原文

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

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

I've got a DOS program kicked off by a cmd script that dumps a lot of data I'd like to track in a log file. I can easily pipe it to a file - but I need a rolling logfile.

Is there an easy way to pipe the output to a program that will generate a daily rolling logfile? (ie a new file is created for each day)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

审判长 2024-09-09 04:56:08

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

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

然后通过这个过滤器输送原始程序的输出。顺便说一句,这是真正的管道。从技术上讲,您当前所做的不是管道而是重定向(管道转到进程,重定向转到文件)。

伪代码类似于:

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),每 13 秒生成一次日期,共十次:

#!/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 函数更改为使用日期边界是一件简单的事情(请参阅评论)。

If you don't control the source for the program you're running, one possibility is to have another script, run as a scheduled task, which shuts down the program, moves the log file, and restarts the program. Schedule this for somewhere around midnight.

If you can't shut down the program periodically, another possibility is to develop a filter program which will take standard input and send it to a log file based on today's date. That program can detect date changes and close/reopen the file when it crosses the midnight boundary.

Then pipe the output of your original program through this filter. This is true piping by the way. What you're currently doing is not technically piping but redirection (piping goes to a process, redirection goes to a file).

Pseudocode would be something like:

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

As a proof of concept, here's a script (qqtest.sh) that runs, generating the date every thirteen seconds, ten times:

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

And here's a C filter program (qq.c) that does what I describe in my answer above:

#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;
}

When you execute:

./qqtest.sh | ./qq

it creates the following files.

$ 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

Note that this uses a minute boundary to switch log files. It's a simple matter to change the getDate function to use the day boundary instead (see the comments).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文