다음 명령을 고려하십시오:
bash -c "echo x; cat 1" | tee 1
.
내 이해는 새 쉘로 포크하고, x
stdout에 쓰고, file 1 not found
stderr에 쓰고, 종료하고 상위 프로세스에 제어권을 반환한 다음 x
stdout 및 1
. 따라서 최종 출력은 x
이고 파일에는 1
정확히 문자열이 포함되어 있을 것으로 예상됩니다 x
.
그러나 이는 사실이 아니다. 실제로 파일에는 1
일반적으로 최소 두 개의 s 인스턴스가 포함되며 x
때로는 수천 줄의 x
s가 포함됩니다. 이 명령을 1만번 실행한 일괄 테스트에서 x
파일에 기록된 s의 평균 개수는 52.3개, 중앙값은 1개였습니다. 어떤 메커니즘으로 인해 이런 일이 발생하나요? 이 행동의 확률 분포는 무엇입니까? 나는 그것이 조건적으로 기하학적이고 다른 점에서는 균일하다고 생각합니다.
답변1
이것은 매우 이상한 문제이므로 strace의 도움을 받아 조사해 보았습니다. 명령을 1000번 반복합니다.
mkdir {000..999}
for i in {000..999}; do
echo $i
(cd $i; strace -f -o trace.log bash -c 'bash -c "echo x; cat 1" | tee 1 >/dev/null'; )
done
wc -l */1 | sort -nr | head -n2
가장 많은 줄( ) 이 있는 파일을 찾아 그에 따라 확인하면 trace.log
다음과 같은 내용이 많이 표시됩니다.
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
7568 read(3, "x\n", 131072) = 2
7568 write(1, "x\n", 2) = 2
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
7568 read(3, "x\n", 131072) = 2
7568 write(1, "x\n", 2) = 2
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
여기서 7567은 이고 tee 1
7568은 입니다 cat 1
. 두 가지는 확실히 번갈아 가므로 의심되는 것처럼 두 명령의 실행 시간에 관한 것입니다(컨텍스트 전환이라고 생각합니다).