데이터 스트림을 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 '
답변2
데이터의 16진수만 인쇄하는 간단한 것을 원한다면 다음 Perl 스크립트를 사용할 수 있습니다.
perl -e '$| = 1; $i = 1;
while(1){
sysread(STDIN,$ch,1) or exit;
printf "%02x%s",ord($ch),$i++%16==0?"\n":" ";
}'
실제로 블록까지 읽고 hexdump를 실행하려면 다음을 수행하십시오.
perl -e '$| = 1; $i = 1; $rin = ""; vec($rin, fileno(STDIN), 1) = 1;
open(F,"|hexdump -C") or die;
while(1){
$nfound = select($rout=$rin, undef, undef, 0);
if($nfound==1){
sysread(STDIN,$data,999) or exit;
syswrite(F,$data) or die;
}else{
close(F);
open(F,"|hexdump -C") or die;
select($rout=$rin, undef, undef, undef);
}
}'