stdout을 "특정 코드 블록"으로 직접 파이프한 다음 수정된 데이터를 파일에 쓰면 tee
항상 파일에서 예상되는 출력 줄의 전체 보완을 얻습니다.
그러나 tee
동일한 데이터를 프로세스에 보내면 >("same block of code")
출력에서 최대 4줄이 제거될 수 있습니다. 이 숫자는 다양하며 때로는 모든 줄을 작성합니다.
이 문제를 어떻게 해결할 수 있으며,왜에서만 발생합니까 >( process )
?
추가 정보: 이 회선 손실이 발생했을 때 저는 일반 stdout 파이프뿐만 아니라 2개의 프로세스 대체를 "티잉"하고 있었습니다.
Ubuntu 10.04.2 LTS, 버전 4.1.5(1) 릴리스(i486-pc-linux-gnu)에서 GNU bash를 사용합니다.
이것이 실제 스크립트입니다. 두 번째 프로세스 대체는 문제의 프로세스입니다.>(tr $'\x60' $X01
#
# Run 'locate' and direct the output to a temp file
errflag=""
locitmct=0 # Count of located items
columns=4 # The number of columns in the main dialog
colmnb=0 # Column number (NB: columns 1 and 2 are processed together)
X01=$'\x01'
eval locate $zenargs |tee \
>(zenity --progress --pulsate --auto-close) \
>(tr $'\x60' $X01 \
|sed -n "s/^\(.*\/\)\(.*\)/\1\2\n\2\n\1/p" \
|while IFS= read -r line ; do \
#
#
# process the data
#
#
done > "$listf" )\
>/dev/null
#
cat "$listf"
#
답변1
이 질문을 한 지 10시간이 지났고 해결책을 찾았습니다... 참고: 이전에 질문 아래의 설명에서 언급했듯이 wait
이러한 프로세스에서는 작동하지 않습니다. 이는 이러한 "프로세스 재정의"가 기다리고 있는 "하위" 프로세스가 아니기 때문이라고 생각합니다 wait
. (매개변수 없이 시도했습니다 wait
)....
기능과 단점에 대한 의견을 주시면 감사하겠습니다. stdin이 어떻게 선택 zenity
되고 첫 번째 명령이 tr
언제 echo
인지 잘 이해가 안 되지만 그냥 시도해 보고 싶었습니다... 작동하는 것 같지만(이 경우) 이 접근 방식이 안전한가요?
이 문제를 해결하기 위해 잘 시도되고 테스트된 방법이 있을 수 있으므로 다른 답변은 그만한 가치가 있습니다.
#!/bin/bash
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Set up flag-files for processes to send PIDs to main process
# The first thing each process does is: echo -n "$BASHPID " > flag-file
for i in {1..2};do cp /dev/null "$listf".pid$i;done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
eval locate $zenargs |tee \
>(echo -n "$BASHPID " > "$listf".pid1 ; \
zenity --progress --pulsate --auto-close) \
>(echo -n "$BASHPID " > "$listf".pid2 ; \
tr $'\x60' $X01 \
|sed -n "s/^\(.*\/\)\(.*\)/\1\2\n\2\n\1/p" \
|while IFS= read -r line ; do \
#
#
# process the data
#
#
done > "$listf" ) \
>/dev/null
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#### WAIT for processes to terminate
pids=$(cat "$listf".pid{1,2})
while [[ "$pids" == *[0-9]* ]] ; do
sleep .1 # GNU
for pid in $pids ; do
if ! kill -0 "$pid" 2>/dev/null; then
pids="${pids/$pid/}"
fi
done
done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
cat "$listf"
#
답변2
coreutils 버전 8.24부터 다른 방법이 있습니다.
tee -p </dev/zero >(head -c10M | wc -c ) > >(head -c1 | wc -c ) | numfmt --to=iec
출력은 다음과 같습니다
1
10M
여기서 핵심 포인트는
이를 사용하면 파이프에 오류가 아닌 모든 출력에 경고가 기록
-p
됩니다 .tee
즉, EPIPE 오류는 종료를fwrite
유발하지 않으며 쓰기 위해 열려 있는 출력 파일이 하나 이상 있는 한 실행됩니다. stderr 로 인쇄하는 것에 대한 EPIPE 경고를 받으려면 .tee
tee
--output-error=warn
-p
> >(head -c1 | wc -c )
tee의 표준 출력을 다른 출력으로 리디렉션하는 데 사용됩니다>(process substitution)
. 이는 두 가지 이유로 중요합니다. 예를 들어 , stdin을 사용하는 경우 stdin에 데이터가 있는 한 실행됩니다(이 경우 영원히 실행됨)tee
. 동시에 추가 처리를 위해 출력을 표준 출력으로 보낼 수 있습니다. 덜 우아하지만 또 다른 가능성 은 다른 방법으로 stdout 출력을 끄는 것입니다 . 두 가지 가능성은 및 입니다 . 그러나 이는 경고를 발행합니다(tee: stdout: 장치에 남은 공간 없음 및 tee: stdout: 각각 잘못된 파일 설명자).>/dev/null
tee
>(process substitution)
tee
>/dev/full
>&-