티셔츠의 예측할 수 없는 행동에 대한 설명

티셔츠의 예측할 수 없는 행동에 대한 설명

반복적으로 실행되는 프로그램의 출력을 합산하는 스크립트를 테스트하는 동안 이해할 수 없는 동작을 발견했습니다. 이를 재현하려면 out내 프로그램의 출력을 나타내는 텍스트 파일을 생성하고 sum, 이 파일은 이전 실행에서 반환된 값의 합계를 보유하고 의 복사본으로 시작합니다 out.

cat > out << EOF
2 20
5 50
EOF
cp out sum

달리는 중에 이상한 일이 일어납니다

paste out sum | awk '{$1 += $3; $2 += $4; NF = 2; print}' | tee sum

여러 번(15~20회 소요될 수 있음) 실행할 때마다 명령은 sum해당 값에 값을 추가 out하고 결과를 다시 작성해야 합니다 sum. 내가 얻는 것은 예측할 수 없는 횟수만큼 작동한 sum다음

2 20
5 50

나중에 배웠어요작업 중인 동일한 파일로 출력을 리디렉션하거나 티잉할 수 없습니다.임시 파일을 사용하면 문제가 해결되었지만 이 동작은 여전히 ​​혼란스럽습니다.

  • … | tee sum제한된 횟수의 반복으로도 작동하지만 … > sum덮어쓰지 않는 이유는 무엇입니까 sum?

  • 왜 예상대로 작동하지 않습니까?

답변1

이것,

paste out sum | awk ... | tee sum

경쟁 조건이 있습니다. 읽기 위해 paste열고 , 쓰기 위해 열고, 자릅니다. 쉘은 거의 동시에 시작되므로 파일을 먼저 여는 쉘에 따라 다릅니다.sumtee

물론 실제로는 쉘이 특정 순서에 따라 한 번에 하나씩 유틸리티를 시작해야 합니다. 왼쪽에서 오른쪽으로 실행될 수도 있으므로 paste먼저 실행될 가능성이 더 높을 수도 있지만 이는 구현 세부 사항이며 어쨌든 실행할 시기는 OS 스케줄러가 결정합니다.

먼저 진행 하면 paste데이터가 그대로 유지되고 데이터를 읽을 충분한 시간이 있는 파일이 열립니다. 파일을 읽기 전에 열면 tee빈 파일이 보입니다.pastepaste

여기,

paste out sum | awk ... > sum

쉘은 sum쓰기를 위해 열리고 잘립니다. 이는 start 와 병렬로 실행될 수 있지만 paste잘림에는 sum다른 유틸리티 시작이 포함되지 않으므로 먼저 발생할 수 있습니다. (리디렉션을 처리하는 규칙과 이와 같은 파이프라인에서 명령이 시작되는 순서가 있는지 확실하지 않지만 이에 의존하지는 않습니다.)

sponge이 문제를 해결하는 도구가 있습니다 .그것에 관한 질문). 얻은 입력을 수집하고 입력이 닫힌 후에만 씁니다. 이는 sum항상 올바르게 업데이트되어야 합니다.

paste out sum | awk ... | sponge sum

관련 정보