이 문제를 설명하기 위해 간단한 C 프로그램을 만들었습니다.
root@u2004:~# cat test.c
#include <stdio.h>
int main(){
printf("output 1\n");
fprintf(stderr, "error 1\n");
printf("output 2\n");
fprintf(stderr, "error 2\n");
return 0;
}
root@u2004:~# gcc test.c
root@u2004:~#
실행하면 다음과 같은 결과가 나타납니다.
root@u2004:~# ./a.out
output 1
error 1
output 2
error 2
root@u2004:~#
보시다시피 콘솔의 출력 순서는 프로그램에 정의된 명령문과 동일합니다. 이제 stderr과 stdout을 단일 파일로 리디렉션하고 출력 순서를 유지하고 싶습니다. 내가 시도한 것은 다음과 같습니다.
root@u2004:~# ./a.out > out 2>&1
root@u2004:~# cat out
error 1
error 2
output 1
output 2
root@u2004:~#
root@u2004:~# cat <(./a.out)
error 1
error 2
output 1
output 2
root@u2004:~#
보시다시피 두 경우 모두 오류 메시지가 먼저 나타난 다음 일반 출력이 나타납니다. 이는 프로그램에서 정의한 순서와 다릅니다. stdout과 stderr을 동일한 파일로 리디렉션할 때 출력 순서를 유지하는 방법은 무엇입니까?
답변1
이는 프로그램(C 라이브러리)의 버퍼링 때문입니다. 기본 동작은 stdout에 대한 출력이 터미널로 이동하는 경우 라인 버퍼링되지만 파일로 이동하는 경우 완전히 버퍼링된다는 것입니다. 기본적으로 stderr은 항상 버퍼링되지 않습니다.
따라서 전체 라인을 인쇄하므로 라인 버퍼링이 명확하지 않지만 파일로 리디렉션되면 stdout으로 전송된 출력은 실제로 작성되기 전에 전체 청크(몇 kB)가 수집될 때까지 버퍼링됩니다. (라인의 일부를 인쇄하면 어떤 일이 발생하는지 확인할 수도 있습니다.)
setbuf()
C 프로그램 내에서 버퍼링 동작을 사용/변경할 수 setvbuf()
있으며 이 도구를 사용하여 외부에서 버퍼링 동작을 변경할 수 있습니다 stdbuf
(다른 도구도 많이 있으므로 사이트에서 파이프 버퍼링을 찾아보세요).
setbuf(stdout, NULL)
예를 들어, 프로그램 시작 부분에 추가하면 표준 출력이 버퍼링되지 않으며 실행해도 stdbuf -o0 ./a.out
마찬가지입니다. 그러나 이렇게 하면 프로그램 속도가 느려집니다.
마지막 예에서는 cat <(./a.out)
프로그램의 표준 출력만 통과하고 cat
표준 오류는 터미널로 직접 전달됩니다. 두 사람이 서로 다른 곳으로 가서 또 다른 과정을 거치게 되면 재정렬이 발생하게 된다. 당신 은 그것 을 모두 통과 cat <(./a.out 2>&1)
시켜야 합니다 ../a.out 2>&1 | cat
cat