12

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

有任何想法吗?

4

7 回答 7

6

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

timeout 5s cat /dev/random

视你的情况而定。例如,您使用 -e 运行 bash 并通常关心退出代码。

timeout 5s cat /dev/random || true
于 2011-09-01T13:05:55.610 回答
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)实际上,它被称为slowcatsnail更好,如果它使故事听起来更好,我并没有超过一点小修正主义:-)

于 2011-09-01T13:02:09.693 回答
2

mbuffer,有它的-W选项,对我有用。

我需要沉入stdin一个文件,但有一个空闲超时:

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

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

mbuffer -A /bin/false -W 10 -o ./the-output-file
于 2017-11-07T23:14:50.830 回答
1

这是超时猫的代码:

#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没有参数的工作 - 捕获标准输入。作为第一个参数,提供超时秒数。

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

用法

而不是可能无穷无尽:

cat < some_input > some_output

您可以将上面的代码编译为 timeout_cat 并且:

./timeout_cat 5 < some_input > some_output
于 2011-09-01T16:38:57.077 回答
0

尝试考虑 tail -f --pid 我假设您正在阅读一些文件,并且当生产者完成(消失?)时,您会停止。

将处理 /var/log/messages 直到 watcher.sh 完成的示例。

./watcher.sh&
tail -f /var/log/messages --pid $! | ... do something with the output
于 2012-10-17T22:44:49.843 回答
0

我在通过 adb shell 读取 tty 端口时遇到了同样的 cat 命令阻塞问题,但没有找到任何解决方案(超时命令也不起作用)。下面是我在我的 python 脚本(在 ubuntu 上运行)中使用的最后一个命令,以使其成为非阻塞的。希望这会对某人有所帮助。

bash_command = "adb shell \"echo -en 'ATI0\\r\\n' > /dev/ttyUSB0 && cat /dev/ttyUSB0\" & sleep 1; kill $!"
response = subprocess.check_output(['bash', '-c', bash_command])
于 2019-01-16T07:50:59.780 回答
-1

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

cat xyz & sleep 5; kill $!

5秒后获取猫输出作为回复

reply="`cat xyz & sleep 5; kill $!`"
echo "reply=$reply"
于 2016-03-02T13:18:36.100 回答