用cat读取:不接收数据时停止

时间:2011-09-01 12:56:31

标签: linux shell unix sh cat

有没有办法告诉cat命令在没有收到任何数据时停止阅读?可能有一些“超时”,指定没有数据传入的时间。

有什么想法吗?

7 个答案:

答案 0 :(得分:5)

cat本身,没有。它读取输入流,直到告诉它是文件的结尾,必要时阻止输入。

没有什么可以阻止你编写你的自己的 cat等价物,如果没有足够快的时间在标准输入上使用select超时,并在这些条件下退出。

事实上,我曾经写过一个snail程序(因为蜗牛比猫慢),每秒钟需要额外的字符参数才能慢慢输出文件(a)

因此snail 10 myprog.c会以每秒十个字符输出myprog.c。对于我的生活,我不记得为什么我这样做了 - 我怀疑我只是在唠叨,等待一些真正的工作出现。

由于你遇到麻烦,这里有dog.c版本(基于我上面提到的snail程序),可以做你想做的事情:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/select.h>

static int dofile (FILE *fin) {
    int ch = ~EOF, rc;
    fd_set fds;
    struct timeval tv;

    while (ch != EOF) {
        // Set up for fin file, 5 second timeout.

        FD_ZERO (&fds); FD_SET (fileno (fin), &fds);
        tv.tv_sec = 5; tv.tv_usec = 0;
        rc = select (fileno(fin)+1, &fds, NULL, NULL, &tv);
        if (rc < 0) {
            fprintf (stderr, "*** Error on select (%d)\n", errno);
            return 1;
        }
        if (rc == 0) {
            fprintf (stderr, "*** Timeout on select\n");
            break;
        }

        // Data available, so it will not block.

        if ((ch = fgetc (fin)) != EOF) putchar (ch);
    }

    return 0;
}

int main (int argc, char *argv[]) {
    int argp, rc;
    FILE *fin;

    if (argc == 1)
        rc = dofile (stdin);
    else {
        argp = 1;
        while (argp < argc) {
            if ((fin = fopen (argv[argp], "rb")) == NULL) {
                fprintf (stderr, "*** Cannot open input file [%s] (%d)\n",
                    argv[argp], errno);
                return 1;
            }
            rc = dofile (fin);
            fclose (fin);
            if (rc != 0)
                break;
            argp++;
        }
    }

    return rc;
}

然后,您只需运行dog不带参数(因此它将使用标准输入),并且在没有活动的五秒后,它将输出:

*** Timeout on select

(a)实际上,它被称为slowcat,但是snail更好,如果它让故事听起来更好,我就不会超过一些小修正主义: - )

答案 1 :(得分:5)

有一个timeout(1)命令。例如:

timeout 5s cat /dev/random

答案 2 :(得分:1)

以下是timeout-cat的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void timeout(int sig) {
        exit(EXIT_FAILURE);
}

int main(int argc, char* argv[]) {
        int sec = 0; /* seconds to timeout (0 = no timeout) */
        int c;

        if (argc > 1) {
                sec = atoi(argv[1]);
                signal(SIGALRM, timeout);
                alarm(sec);
        }
        while((c = getchar()) != EOF) {
                alarm(0);
                putchar(c);
                alarm(sec);
        }
        return EXIT_SUCCESS;
}

它与paxdiablo的狗基本相同。 它作为一个没有参数的cat - 捕获标准输入。作为第一个参数提供超时秒。

一个限制(也适用于狗) - 行是行缓冲的,所以你有n秒来提供一行(不是任何字符)来重置超时警报。这是因为readline。

<强>使用

而不是无穷无尽的:

cat < some_input > some_output

你可以将上面的代码编译为timeout_cat和:

./timeout_cat 5 < some_input > some_output

答案 3 :(得分:0)

尝试考虑tail -f --pid 我假设你正在读一些文件,当制作人完成时(走了?)你就停止了。

在watcher.sh完成之前处理/ var / log / messages的示例。

./watcher.sh&
tail -f /var/log/messages --pid $! | ... do something with the output

答案 4 :(得分:0)

mbuffer及其-W选项适用于我。

我需要将stdin接收到文件,但是有空闲超时:

  • 我不需要实际连接多个源(但也许有方法可以使用mbuffer。)
  • 我不需要任何cat可能的输出格式选项。
  • 我不介意mbuffer带来的进度条。

我确实需要根据链接的手册页中的建议添加-A /bin/false来抑制警告。我将stdin复制到具有10秒空闲超时的文件的调用最终看起来像

mbuffer -A /bin/false -W 10 -o ./the-output-file

答案 5 :(得分:0)

通过adb shell在tty端口上读取时,我遇到了cat命令阻塞的相同问题,但是没有找到任何解决方案(超时命令也无法正常工作)。以下是我在python脚本(在ubuntu上运行)中使用的最终命令,以使其无阻塞。希望这会帮助某人。

List[Int]

答案 6 :(得分:-1)

只需猫,然后在5秒后杀死猫。

cat xyz & sleep 5; kill $!

5秒后将猫输出作为回复

reply="`cat xyz & sleep 5; kill $!`"
echo "reply=$reply"