データストリームをSTDOUTに出力するコマンド(A)があります。データストリームは小さく、ほとんどの場合何も送信されません。読み取りがブロックを停止してデータをパイプするときに、読み取った各データチャンクに対してコマンド(C)をすぐに実行する別のコマンド(B)にそのデータをパイプしたいと思います。
ブロックのサイズは重要ではなく、意味のあるサイズであれば何でも可能です。本質的にxargsが欲しいが、区切り文字はない。代わりに、読み取りがブロックされ始めたときにコマンドを実行する必要があります。
具体的には、Aコマンドは「tail -f logfile」、Cコマンドは「hexdump -C」です。 「hexdump -C」を直接パイプできない理由は、hexdumpが新しい行を印刷する前に16バイトの読み取り全体を待つためです。だから、読み取ったブロックごとにコマンドを実行したいと思います。
ベストアンサー1
read
Rawはパイプが空でない限りブロックしません。より多くのバイトを要求しても、パイプで使用可能なバイト数に関係なく返されます。これを利用して、hexdump -C
正常に返されるたびに実行できますread
。
#define _BSD_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define N (8*512) //pipe size on my system as shown in `ulimit -a`
static char buf[N];
int main(){
ssize_t nread;
FILE* p;
for(;;){
do { nread = read(0, buf, N); }while (nread < 0 && errno == EINTR);
if(nread == 0) return 0; //EOF
if(nread < 0) goto error;
p = popen("hexdump -C", "w"); if(!p) goto error;
if(fwrite(buf, sizeof(char), nread, p) != nread) goto error;
pclose(p);
}
return 0;
error:
perror(""); return 1;
}
shovel.c
たとえば、then make shovel
(または)として保存gcc shovel.c -o shovel
し、パイプラインで使用できます。
あるいは、興味がなければ、同じことをするRubyコードの断片があります。
tail -f file |
ruby -e 'PSIZE=8*512;
while(bytes = STDIN.readpartial(PSIZE));
IO.popen("hexdump -C","w") {|p| p.syswrite(bytes) }
end '