stdout을 파일로 리디렉션하고 stdout + stderr를 다른 파일로 리디렉션하는 방법은 무엇입니까? 어떻게 달성 할 수 있습니까 cmd >>

어떻게 달성 할 수 있습니까

cmd >> file1 2>&1 1>>file2

즉, stdout stderr는 하나의 파일 (file1)로 리디렉션해야하고 stdout (file2) 만 다른 파일로 리디렉션해야합니까 (둘 다 추가 모드에서)?



답변

문제는 출력을 리디렉션 할 때 다음 리디렉션에 더 이상 사용할 수 없다는 것입니다. tee서브 쉘로 파이프 하여 두 번째 경로 재 지정에 대한 출력을 유지할 수 있습니다 .

( cmd | tee -a file2 ) >> file1 2>&1

또는 터미널에서 출력을 보려면 다음을 수행하십시오.

( cmd | tee -a file2 ) 2>&1 | tee -a file1

최초의 표준 오류를 추가 방지하기 tee위해 file1, 당신은 어떤 파일 기술자 (예 : 3)에 명령의 표준 오류 리디렉션, 나중에 다시 표준 출력하려면이 옵션을 추가해야합니다 :

( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1

(@ fra-san 덕분에)


답변

zsh:

cmd >& out+err.log > out.log

추가 모드에서 :

cmd >>& out+err.log >> out.log

에서 zsh1, 제공된 mult_ios파일 기술자 (여기 1) 쓰기를 위해 여러 번 리디렉션 할 때 옵션을 비활성화되지 않았습니다 후 쉘 구현 내장 된 tee모든 대상에 출력을 복제 할 수 있습니다.


답변

다음과 같이 할 수 있습니다. stdout에 태그를 지정하십시오 (UNBUFFERED sed 사용). sed -u ... stderr에 stdout (태깅 sed를 거치지 않았으므로 태그가 지정되지 않음)으로 이동하여 결과 로그 파일에서 2를 구분할 수 있습니다.

다음은 :입니다 느린 (; 할 …; 그것은 심각 대신하면서 …의 exemple 펄 스크립트를 사용하여, 최적화 할 수있는 모든 라인에서 서브 쉘 및 명령을 산란 것, exemple를 들어, 다!), 이상한 에 “: 등, 그러나 그것이 (내가 하나 개의 이름 바꾸기 표준 출력에 다음 다른 하나의 그것에 표준 오류”를 통해 오리엔트 “추가하려면 2 {} 단계를 필요로 보인다) 개념의 증거 “, 즉 유지하려고합니다 출력 순서는 가능한 한 많은 stdout & stderr입니다.

#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch

#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
#  to see if the order of stdout&stderr is kept

#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3

#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs... 
                     # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

{
   { for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
   } | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
    case "$line" in
       ${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
        *)            printf "%s\n" "$line"       >> out_AND_err.file ;;
    esac;
done;

# see the results:
grep "^" out.file out_AND_err.file


답변

출력 순서가 stdout이면 stderr ; 리디렉션 만있는 솔루션은 없습니다.
stderr은 임시 파일에 저장해야합니다

cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err

기술:

하나의 출력 (stdout 또는 stderr와 같은 fd)을 파일 로 리디렉션하는 유일한 방법은 출력 을 재생하는 것입니다. 이 명령 tee은 파일 디스크립터 컨텐츠를 재생하는 올바른 도구입니다. 따라서 두 파일에 하나의 출력을 갖는 초기 아이디어는 다음을 사용하는 것입니다.

... |  tee file1 file2

이것은 티의 stdin을 두 파일 (1 & 2)로 재생하여 티의 출력을 여전히 사용하지 않습니다. 그러나 우리는 (use -a) 를 추가해야하고 사본 하나만 필요합니다. 이렇게하면 두 가지 문제가 모두 해결됩니다.

... | tee -a file1 >>file2

공급하려면 tee우리는 명령에서 직접 표준 에러 소비 할 필요가 표준 출력 (반복에 하나)와 함께. 한 가지 방법은 순서가 중요하지 않은 경우 (출력 순서는 생성 된대로 유지 될 것입니다 (아마도 먼저 출력되는 쪽이 먼저 저장 됨)). 어느 한 쪽:

  1. cmd 2>>file1 | tee -a file2 >>file1
  2. cmd 2>>file1 > >( tee -a file2 >>file1 )
  3. ( cmd | tee -a file2 ) >> file1 2>&1

옵션 2는 일부 쉘에서만 작동합니다. 옵션 3은 추가 서브 쉘 (느리게)을 사용하지만 파일 이름은 한 번만 사용하십시오.

하지만 표준 출력이 해야한다 먼저 우리는 마지막에 파일에 추가 할 저장 stderr에 필요 (중 위해 출력하는 생성) (최초의 솔루션이 게시).


답변

다양성을 위해 :

시스템 지원하는 경우 /dev/stderr, 다음

(cmd | tee -a /dev/stderr) 2>> file1 >> file2

작동합니다. 의 표준 출력은 cmd
파이프 라인의 stdout 및 stderr 모두로 전송됩니다. cmd바이 패스 의 표준 오차 는tee
는 파이프 라인 하고 나옵니다.

그래서

  • 파이프 라인의 표준 출력은 cmd
  • 파이프 라인의 stderr cmd은의 혼합 된 stdout과 stderr입니다 .

그런 다음 해당 스트림을 올바른 파일로 보내는 것은 간단합니다.

(을 포함하여이 같은 거의 모든 방법과 마찬가지로 스테판의 대답 ),
file1순서가 라인을 얻을 수 있습니다.


답변