stdout 및 stderr을 파일로 리디렉션하고 stderr을 콘솔에 표시하는 방법은 무엇입니까?


18

파일로 리디렉션하고 tee를 사용하는 방법을 알고 있습니다. 기본 수준에서. 그래서

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

문제는 다음과 같은 결과를 얻기 위해 물음표 대신 무엇을 작성해야 하는가입니다.

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

포함 :

  • bash를 가정합니다.
  • 순서는 파일에 보관해야합니다.
  • stderr 내용은 실시간으로 표시됩니다 (즉, 버퍼링 없음).
  • 별도의 스크립트 파일을 사용할 수 있습니다.
  • 마술이 필요할 수 있습니다.

outanderr프로그램의 제어권은 어느 정도 입니까?
Kevin

1
@ 케빈 나는 그 질문이 그보다 더 일반적인 것이라고 생각합니다. 여기, outanderr행을 stdout에 인쇄하고 다른 것을 stderr에 인쇄하는 별명입니다. 가능한 경우 아이디어는 수정하지 않고도 모든 프로그램에서 작동 할 수있는 일반적인 솔루션을 구축하는 것입니다.
lgeorget 2016 년

@lgeorget 나는 그것을 이해하지만 일반적인 솔루션의 모든 제약 조건을 엄격하게 충족 할 수는 없다고 생각하므로 특정 조건을 얻을 수 있는지 보았습니다.
케빈

@Igeorget가 맞습니다.
TWiStErRob 2016 년

답변:


12
2>&1 >>outputfile | tee --append outputfile

쉬운 테스트를 위해 :

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

편집 1 :

이것은 stdout을 파일에 쓰고 sterr stdout이 파이프를 통과하도록 만들고 tee가 출력을 동일한 파일에 쓰도록하여 ​​작동합니다.

두 쓰기는 모두 >>대신 추가 모드에서 수행되어야합니다. >그렇지 않으면 둘 다 서로의 출력을 덮어 씁니다.

파이프가 버퍼이므로 출력이 파일에 올바른 순서로 표시된다는 보장은 없습니다. 응용 프로그램이 두 파일 디스크립터 (파이프 2 개) 모두에 연결된 경우에도 변경되지 않습니다. 순서를 보장하기 위해 두 출력 모두 동일한 채널을 거쳐 각각 표시되어야합니다. 아니면 정말 멋진 것들이 필요할 것입니다.

  1. stdout과 stderr이 모두 동일한 파일이 아닌 파일로 리디렉션되고 두 파일이 모두 FUSE 볼륨에있는 경우 FUSE 모듈은 각 단일 쓰기에 타임 스탬프를 표시하여 두 번째 응용 프로그램이 데이터를 올바르게 정렬하고 결합 할 수 있습니다 실제 출력 파일. 또는 데이터를 표시하지 않지만 모듈이 결합 된 출력 파일을 작성하도록합니다. 아마도이 작업을 수행하는 FUSE 모듈이 아직 없을 것입니다 ...
  2. stdout과 stderr 모두에 지시 될 수 있습니다 /dev/null. 를 통해 실행하면 응용 프로그램의 출력이 분리됩니다 strace -f -s 32000 -e trace=write. 이 경우 이스케이프 처리를 취소해야합니다. 말할 필요없이 응용 프로그램이 더 빨리 실행되지는 않습니다.
  3. 기존의 간단한 FUSE 모듈을 사용하고 애플리케이션 대신 모듈을 추적하여 동일한 결과를 얻을 수 있습니다. 모듈은 아마도 응용 프로그램보다 훨씬 적은 syscall을 가지기 때문에 응용 프로그램을 추적하는 것보다 빠릅니다.
  4. 응용 프로그램 자체를 수정할 수있는 경우 : 각 출력 후에 응용 프로그램을 중지 할 수 있지만 (내부에서만 가능하다고 생각) s 신호 (SIGUSR1 또는 SIGCONT)를 수신 한 후에 만 ​​계속할 수 있습니다. 파이프에서 읽는 응용 프로그램은 파이프와 파일 모두에서 새 데이터가 있는지 확인하고 새 데이터마다 신호를 보내야합니다. 응용 프로그램의 종류에 따라 strace 방법보다 빠르거나 느릴 수 있습니다. FUSE가 최대 속도 솔루션입니다.

1
바. 왜 안 똑같은 대답을 정확하게 작성하는 동안 나를 잡아라.
케빈

2
NB 이것은 라인을 바꿀 수있는 경쟁 조건을 가지고 있지만 피할 수는 없다고 생각합니다.
케빈

1
@Kevin 그것은 우리에게 최선의 일이었고, 나는 전에 그것을 겪었고 거의 "누군가가 글을 쓰고 있다는 것을 보여줘"기능을 요구했다. 경쟁 조건은 파이프 라인에 쓴 후 파일에 쓰기 (stdout)가 발생하는 경우에만 발생하는 것으로 보입니다.
Hauke ​​Laging 2016 년

send가 아닌 둘 것을겠습니까 stdoutstderrtee, 또는 내가 뭔가를 놓친 게 뭐죠? 나는 OP의 요구 사항이 tee stderr유일한 것이라고 생각합니다 .
Joseph R.

@JosephR. 시도해 보지 않으셨습니까?
Hauke ​​Laging
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.