프로세스 교체 및 리디렉션을 위해 tee 사용

프로세스 교체 및 리디렉션을 위해 tee 사용

bash 명령의 표준 출력을 cmd이름이 지정된 파일로 리디렉션하고 f.out표준 오류를 로 리디렉션 f.err한다고 가정하면 tee콘솔 인쇄를 유지합니다.

cmd 1> >(tee f.out) 2> >(tee f.err)

그런 다음 f.out출력과 오류를 포함합니다(적어도 내 시스템에서는).

이제 리디렉션 순서를 변경하면 다음과 같습니다.

cmd 2> >(tee f.err) 1> >(tee f.out)

f.out출력만 포함됩니다( f.err두 경우 모두 오류만 포함).

그래서 내 질문은 두 가지입니다. stderr을 로 어떻게 리디렉션합니까 f.out? 그리고 리디렉션 순서가 결과에 영향을 미치는 이유는 무엇입니까?

을 사용하지 않는 경우 tee예를 들면 cat다음과 같습니다.

cmd 1> >(cat>f.out) 2> >(cat>f.err)

이 문제는 없으며 예상대로 프로세스 교체 없이 리디렉션 순서는 중요하지 않습니다( cmd 1>f.out 2>f.err).

답변1

Bash는 해석하는 명령에서 찾은 순서대로 리디렉션을 적용하기 때문에 리디렉션 순서가 중요합니다.

이는 예상대로 관용구가 작동하도록 하기 위한 것입니다 > file 2>&1. 즉, stderr이 stdout과 동일하도록 합니다. 이 관용구는 file"stdout에 할당한 다음 stderr을 stdout과 동일하게 만듭니다"와 동일하게 작동합니다. 이는 stdout의 값이 stderr이 stdout과 동일한 값을 얻을 때이기 때문에 예상된 결과를 생성합니다 file. 다른 방법(예: 2>&1 1> file)은 stderr 값을 복사한 후 stdout 값이 변경되기 때문에 동일한 결과를 생성하지 않습니다. 파일 설명자는 자체 값을 가지며 에서와 같이 다른 변수 값의 복사본을 얻는 데 사용할 수 있다는 점에서 일반 변수와 유사하다고 생각할 수 있습니다. var1="${var2}"이와 유사하게 후속 값 변경이 var1따르지 않습니다 . var2파일 설명자도 그렇지 않습니다.

또한 편리합니다. 예를 들어 에서처럼 같은 줄에서 파일 설명자를 바꿀 수 있습니다 3>&1 1>&2 2>&3-. 이는 fd 3을 fd 1과 2를 바꾸는 임시 "도우미" fd로 사용합니다.

따라서 리디렉션은 명령이나 스크립트의 별도 두 줄에 있는 것처럼 순차적으로 실행되는 명령으로 생각할 수 있습니다.

특정 사례에 따라 프로세스 대체도 포함되며 지정된 순서로 실행됩니다.지금까지 표현된 리디렉션 상속

즉, 요약하면 다음과 같습니다.

  1. 먼저 stdout을 실행 중인 프로세스로 리디렉션합니다 tee f.out. 이때 stdout은 cmd필요에 따라 tee f.outstdin 에 연결됩니다.
  2. 그런 다음 stderr는 실행 중인 프로세스로 리디렉션되지만 tee f.err이는 앞서 표현한 리디렉션에 따라 표준 출력, 즉 연결된 tee f.out표준 입력을 상속합니다.

따라서 stdout과 f.err 파일로 무해하게 출력하여 오류 메시지를 stdin으로 tee f.err파이프하여 모든 메시지를 수신하고 f.out 파일과 터미널 창으로 출력합니다.cmdtee f.out

답변2

나는 이 문제에 직면했고 이것이 내가 실행 중인 테스트에 대한 답변의 일부입니다. 이 명령의 일반적인 경우는 cmd를 실행하여 터미널에 표시하고 stderr(들여쓰기 및 빨간색으로 표시)를 수정한 다음 화면에 표시된 내용을 로그 파일에 저장하는 것입니다. 로그에서 색상 코딩을 제거하십시오.

따라서 2개의 stdout 및 2개의 stderr 행을 생성하는 예제 cmd는 다음과 같습니다.

{ ls -l /usr/bin/col{1,2,a,b} 2>&1 >&3 | sed 's/.*/\t\o33[31mSTDERR: &\o33[0m/'; } 3>&1  

이제 로그 파일에 복사본을 넣으세요.

{ ls -l /usr/bin/col{1,2,a,b} 2>&1 >&3 | sed 's/.*/\t\o33[31mSTDERR: &\o33[0m/'; } 3>&1 | tee >( sed 's/\o33//g;s/\[31m//g;s/\[0m//' > /tmp/file )

그러나 이것은 잘 작동합니다. 이를 달성하는 더 좋은 방법이 있습니까?

관련 정보