cat
データを受信していないときに読み取りを停止するようにコマンドに指示する方法はありますか? おそらく、データが受信されない時間を指定する「タイムアウト」があります。
何か案は?
コマンドがありtimeout(1)
ます。例:
timeout 5s cat /dev/random
状況によって異なります。たとえば、-eを指定してbashを実行し、通常は終了コードに注意します。
timeout 5s cat /dev/random || true
cat
それ自体、いいえ。ファイルの終わりであると通知されるまで入力ストリームを読み取り、必要に応じて入力をブロックします。
標準入力で使用する独自の cat
等価物を書くのを止めるものは何もありません。これselect
は、十分に速く何も来ていない場合にタイムアウトし、それらの条件下で終了します。
実際、私はかつて(カタツムリは猫より遅いので) ファイル(a)snail
をゆっくりと出力するために 1 秒あたりの文字数の余分な引数を取るプログラムを書いたことがあります。
したがって、1 秒あたり 10 文字で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
(標準入力が使用されます)、5 秒間アクティビティがないと、次のように出力されます。
*** Timeout on select
(a)実際、それは呼ばれてslowcat
いましたsnail
が、はるかに優れており、ストーリーのサウンドが良くなるのであれば、マイナーな修正主義を超えているわけではありません :-)
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
します-stdinをcatします。最初の引数として、タイムアウト秒を指定します。
1 つの制限 (犬にも適用されます) - 行は行バッファリングされるため、タイムアウト アラームをリセットするために行 (文字ではなく) を提供するのに n 秒かかります。これは readline によるものです。
使用法:
潜在的に無限の代わりに:
cat < some_input > some_output
上記のコードを timeout_cat にコンパイルして、次のことを行うことができます。
./timeout_cat 5 < some_input > some_output
tail -f --pidを検討してみてください。ファイルを読み取っていて、プロデューサーが終了すると(なくなった?)停止すると想定しています。
watcher.shが終了するまで/var/ log/messagesを処理する例。
./watcher.sh&
tail -f /var/log/messages --pid $! | ... do something with the output