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

发布于 2024-12-03 00:09:29 字数 86 浏览 3 评论 0原文

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

有什么想法吗?

Is there any way to tell the cat command to stop reading when not receiving any data? maybe with some "timeout" that specifies for how long no data is incoming.

Any ideas?

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

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

发布评论

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

评论(7

空心空情空意 2024-12-10 00:09:29

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

timeout 5s cat /dev/random

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

timeout 5s cat /dev/random || true

There is a timeout(1) command. Example:

timeout 5s cat /dev/random

Dependening on your circumstances. E.g. you run bash with -e and care normally for the exit code.

timeout 5s cat /dev/random || true
罪歌 2024-12-10 00:09:29

cat 本身,不。它读取输入流,直到得知文件末尾,并在必要时阻止输入。

没有什么可以阻止您编写自己的 自己 cat 等效项,它将在标准输入上使用 select 来超时,如果没有足够快的信息出现,并退出那些条件。

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

因此,snail 10 myprog.c 将以每秒 10 个字符的速度输出 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 更好,如果它能让故事听起来更好的话,我不会超越一点小修正主义:-)

cat itself, no. It reads the input stream until told it's the end of the file, blocking for input if necessary.

There's nothing to stop you writing your own cat equivalent which will use select on standard input to timeout if nothing is forthcoming fast enough, and exit under those conditions.

In fact, I once wrote a snail program (because a snail is slower than a cat) which took an extra argument of characters per second to slowly output a file (a).

So snail 10 myprog.c would output myprog.c at ten characters per second. For the life of me, I can't remember why I did this - I suspect I was just mucking about, waiting for some real work to show up.

Since you're having troubles with it, here's a version of dog.c (based on my afore-mentioned snail program) that will do what you want:

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

Then, you can simply run dog without arguments (so it will use standard input) and, after five seconds with no activity, it will output:

*** Timeout on select

(a) Actually, it was called slowcat but snail is much nicer and I'm not above a bit of minor revisionism if it makes the story sound better :-)

送君千里 2024-12-10 00:09:29

mbuffer,及其 -W选项,对我有用。

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

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

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

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

mbuffer, with its -W option, works for me.

I needed to sink stdin to a file, but with an idle timeout:

  • I did not need to actually concatenate multiple sources (but perhaps there are ways to use mbuffer for this.)
  • I did not need any of cat's possible output-formatting options.
  • I did not mind the progress bar that mbuffer brings to the table.

I did need to add -A /bin/false to suppress a warning, based on a suggestion in the linked man page. My invocation for copying stdin to a file with 10 second idle timeout ended up looking like

mbuffer -A /bin/false -W 10 -o ./the-output-file
情仇皆在手 2024-12-10 00:09:29

下面是 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

Here is the code for 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;
}

It does basically the same as paxdiablo's dog.
It works as a cat without an argument - catting the stdin. As a first argument provide timeout seconds.

One limitation (applies to dog as well) - lines are line-buffered, so you have n-seconds to provide a line (not any character) to reset the timeout alarm. This is because of readline.

usage:

instead of potentially endless:

cat < some_input > some_output

you can do compile code above to timeout_cat and:

./timeout_cat 5 < some_input > some_output
楠木可依 2024-12-10 00:09:29

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

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

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

Try to consider tail -f --pid
I am assuming that you are reading some file and when the producer is finished (gone?) you stop.

Example that will process /var/log/messages until watcher.sh finishes.

./watcher.sh&
tail -f /var/log/messages --pid $! | ... do something with the output
绝對不後悔。 2024-12-10 00:09:29

我在通过 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])

I faced same issue of cat command blocking while reading on tty port via adb shell but did not find any solution (timeout command was also not working). Below is the final command I used in my python script (running on ubuntu) to make it non-blocking. Hope this will help someone.

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])
咆哮 2024-12-10 00:09:29

只需猫,5秒后杀死猫。

cat xyz & sleep 5; kill $!

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

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

Simply cat then kill the cat after 5 sec.

cat xyz & sleep 5; kill $!

Get the cat output as a reply after 5 seconds

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