【发布时间】:2011-11-08 09:29:40
【问题描述】:
有什么方法可以告诉cat 命令在没有收到任何数据时停止读取?可能有一些“超时”来指定没有数据传入的时间。
有什么想法吗?
【问题讨论】:
-
你不是在找
read吗? -
猫 $fifo |而数控...
有什么方法可以告诉cat 命令在没有收到任何数据时停止读取?可能有一些“超时”来指定没有数据传入的时间。
有什么想法吗?
【问题讨论】:
read吗?
有一个timeout(1) 命令。示例:
timeout 5s cat /dev/random
取决于你的情况。例如。您使用 -e 运行 bash 并正常关注退出代码。
timeout 5s cat /dev/random || true
【讨论】:
timeout,但请注意它是一个 GNU 实用程序(换句话说:不是 POSIX 实用程序集的一部分,因此并非在所有平台)。
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 更好,如果它使故事听起来更好,我并没有超过一点小修正主义:-)
【讨论】:
snail 的 dog 程序,它可以满足您的需求。
dog 时,如果我每秒输入一个字母(不返回),那么无论如何我都会超时。换句话说 - 选择查看行缓冲数据。
setvbuf 使其无缓冲。
mbuffer 及其 -W 选项对我有用。
我需要将stdin 接收到一个文件,但是有一个空闲超时:
mbuffer。)cat 的任何可能的输出格式选项。mbuffer 带来的进度条。根据链接手册页中的建议,我确实需要添加 -A /bin/false 来禁止警告。我将stdin 复制到具有 10 秒空闲超时的文件的调用最终看起来像
mbuffer -A /bin/false -W 10 -o ./the-output-file
【讨论】:
这是 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 工作,没有参数 - 捕获标准输入。作为第一个参数,提供超时秒数。
一个限制(也适用于 dog) - 行是行缓冲的,因此您有 n 秒的时间提供一行(不是任何字符)来重置超时警报。这是因为 readline。
用法:
而不是可能无穷无尽:
cat < some_input > some_output
您可以将上面的代码编译到 timeout_cat 并且:
./timeout_cat 5 < some_input > some_output
【讨论】:
cat 命令,没有任何参数。唯一的参数是超时。
尝试考虑tail -f --pid 我假设您正在阅读一些文件,并且当制作人完成时(走了?)您停止了。
将处理 /var/log/messages 直到 watcher.sh 完成的示例。
./watcher.sh&
tail -f /var/log/messages --pid $! | ... do something with the output
【讨论】:
tails 上。我希望它是 Gnu-only。
我在通过 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])
【讨论】:
cat?
简单地猫,然后在 5 秒后杀死猫。
cat xyz & sleep 5; kill $!
在 5 秒后获取 cat 输出作为回复
reply="`cat xyz & sleep 5; kill $!`"
echo "reply=$reply"
【讨论】: