정신적으로이 문제, 단일 소스에서 분기된 데이터 스트림을 생성하고 싶습니다.
cmd1 ──> tee ──────────────> │
├─────> cmd2 ─────> │ cmd4
└─────> cmd3 ─────> │
이 질문과 달리 한 번에 하나의 명령이 아닌 출력이 인터리브되기를 원합니다. 명명된 파이프를 사용하여 이 작업을 수행할 수 있습니다 paste
.
$ mkfifo fifo1 fifo2
$ seq 1 100 \
| tee \
>(awk '$0+=1' > fifo1) \
>(awk '$0+=2' > fifo2) \
| paste - fifo1 fifo2
이것은 잘 작동하는 것 같습니다. 즉, 인쇄됩니다.
1 2 3
2 3 4
...
100 101 102
다음은 개념을 설명하는 개념적 예입니다. 내 거진짜파이프라인은 다음과 같습니다.
find "$1" -type d -print0 \
| tee \
>(xargs -0 -n1 du -bs | cut -f1 > fifo1) \
>(xargs -0 -n1000 stat --printf="%G\n" > fifo2) \
| xargs -0 -n1 echo \
| paste - fifo1 fifo2
이것은 또한 대부분의 경우 꽤 잘 작동하는 것 같습니다. 하지만 거대한 파일 시스템에서 실행하면 중간에 멈추게 됩니다. 위의 질문을 읽어보니 교착상태에 빠진 것 같습니다. 하지만 그것이 어디에 있는지는 잘 모르겠습니다. paste
모든 데이터 흐름을 유지해야 하는 것 같습니다.
tee
나는 아직도 버퍼링과 스트리밍 , 파이프와 FIFO를 이해하지 못하는 것 같습니다 . 내가 여기서 무엇을 놓치고 있는지 설명할 수 있는 사람이 있나요? 막힌 부분은 어디에 있고 어떻게 고치나요? (아니면 더 조사해볼까요?)
답변1
병렬 쓰기 및 읽기 파이프라인에는 엄격한 규율이 필요합니다.
파이프가 128KBytes를 버퍼링할 수 있다고 가정합니다. 이제 모든 파일 이름의 길이가 1MB라고 가정합니다. 파일 이름이 파이프에 맞지 않으므로 리더는 나머지를 쓰기 전에 파일 이름 중 일부를 읽어야 합니다. 그러나 판독기가 현재 다른 파이프의 입력을 기다리고 있는 경우에는 이런 일이 발생하지 않습니다.
귀하의 예에서는 xargs -n1000
출력되기 전에 1000MBytes를 읽으므로 stdout에 쓰려고 시도하는 동안 입력을 paste
기다립니다 .$fifo2
tee
이 시도:
du_cut() { du -bs "$1" | cut -f1; }
stat_print() { stat --printf="%G\n" "$1"; }
doit() { printf "%s\t%s\n" $(du_cut "$1") $(stat_print "$1"); }
export -f du_cut stat_print doit
find "$1" -type d -print0 | parallel -0 --tag doit