답변:
터미널에 STDERR 및 STDOUT이 계속 표시되기를 원한다고 가정합니다. 조쉬 켈리 (Josh Kelley)의 답변을 얻을 수는 있지만 tail로그 파일을 매우 해킹하고 어리석게 출력하는 백그라운드를 유지합니다 . exra FD를 어떻게 유지하고 나중에 죽여서 정리해야하는지 기술적으로 기술적으로해야합니다 trap '...' EXIT.
이를 수행하는 더 좋은 방법이 있으며 이미 발견했습니다 tee..
stdout에 사용하는 대신 stdout에 대한 티와 stderr에 대한 티를 사용하십시오. 당신은 이것을 어떻게 성취 할 것입니까? 프로세스 대체 및 파일 리디렉션 :
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
그것을 나누고 설명합시다.
> >(..)
>(...)(프로세스 대체) FIFO를 작성하고 tee청취하십시오. 그런 다음 >(파일 리디렉션)을 사용 하여 STDOUT을 command처음 tee듣고 있는 FIFO 로 리디렉션합니다 .
두 번째도 마찬가지입니다.
2> >(tee -a stderr.log >&2)
프로세스 대체를 다시 사용 tee하여 STDIN에서 읽고 프로세스를 덤프 하는 프로세스 를 만듭니다 stderr.log. tee입력을 STDOUT에 다시 출력하지만 입력이 STDERR이므로 tee의 STDOUT을 STDERR로 다시 리디렉션하려고 합니다. 그런 다음 파일 리디렉션을 사용하여 command의 STDERR을 FIFO의 입력 ( teeSTDIN) 으로 리디렉션 합니다.
http://mywiki.wooledge.org/BashGuide/InputAndOutput을 참조하십시오 .
프로세스 대체는 (POSIX 또는 Bourne) bash과 달리 쉘로 선택하는 보너스로 얻는 정말 멋진 것들 중 하나입니다 sh.
에서 sh수동으로 작업을 수행해야합니다.
out="${TMPDIR:-/tmp}/out.$$" err="${TMPDIR:-/tmp}/err.$$"
mkfifo "$out" "$err"
trap 'rm "$out" "$err"' EXIT
tee -a stdout.log < "$out" &
tee -a stderr.log < "$err" >&2 &
command >"$out" 2>"$err"
$ echo "HANG" > >(tee stdout.log) 2> >(tee stderr.log >&2)그것은 효과가 있지만 입력을 기다린다. 이런 일이 발생하는 간단한 이유가 있습니까?
/bin/bash 2> err와/bin/bash -i 2> err
(echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)
왜 간단하지 않습니까?
./aaa.sh 2>&1 | tee -a log
이것은 단순히 리디렉션 stderr하기 stdout, 티 에코 그래서 모두가 로그인 화면에 할 수 있습니다. 다른 솔루션 중 일부가 실제로 복잡해 보이므로 뭔가 빠졌을 수 있습니다.
참고 : bash 버전 4부터 다음에|& 대한 약어로 사용할 수 있습니다 2>&1 |.
./aaa.sh |& tee -a log
./aaa.sh |& tee aaa.logbash에서 작동합니다.
set -o pipefail다음 ;또는 &&경우에 나는 잘못이 아니에요.
이것은 사람들이 구글을 통해 이것을 찾는 데 유용 할 수 있습니다. 시도하려는 예제의 주석을 해제하십시오. 물론 출력 파일 이름을 자유롭게 바꾸십시오.
#!/bin/bash
STATUSFILE=x.out
LOGFILE=x.log
### All output to screen
### Do nothing, this is the default
### All Output to one file, nothing to the screen
#exec > ${LOGFILE} 2>&1
### All output to one file and all output to the screen
#exec > >(tee ${LOGFILE}) 2>&1
### All output to one file, STDOUT to the screen
#exec > >(tee -a ${LOGFILE}) 2> >(tee -a ${LOGFILE} >/dev/null)
### All output to one file, STDERR to the screen
### Note you need both of these lines for this to work
#exec 3>&1
#exec > >(tee -a ${LOGFILE} >/dev/null) 2> >(tee -a ${LOGFILE} >&3)
### STDOUT to STATUSFILE, stderr to LOGFILE, nothing to the screen
#exec > ${STATUSFILE} 2>${LOGFILE}
### STDOUT to STATUSFILE, stderr to LOGFILE and all output to the screen
#exec > >(tee ${STATUSFILE}) 2> >(tee ${LOGFILE} >&2)
### STDOUT to STATUSFILE and screen, STDERR to LOGFILE
#exec > >(tee ${STATUSFILE}) 2>${LOGFILE}
### STDOUT to STATUSFILE, STDERR to LOGFILE and screen
#exec > ${STATUSFILE} 2> >(tee ${LOGFILE} >&2)
echo "This is a test"
ls -l sdgshgswogswghthb_this_file_will_not_exist_so_we_get_output_to_stderr_aronkjegralhfaff
ls -l ${0}
exec >즉, 파일 디스크립터의 대상을 특정 대상으로 이동합니다. 기본값은 1 exec > /dev/null이므로이 세션에서 stdout의 출력을 지금부터 / dev / null로 이동합니다. 이 세션의 현재 파일 디스크립터는를 수행하여 볼 수 있습니다 ls -l /dev/fd/. 시도 해봐! 그런 다음 발행시 발생하는 상황을 참조하십시오. exec 2>/tmp/stderr.log.또한 exec 3>&1번호 3으로 새 파일 디스크립터를 작성하여 파일 디스크립터 1의 대상으로 경로 재 지정하십시오. 예에서 대상은 명령이 발행되었을 때의 화면이었습니다.
stderr을 파일로 리디렉션하려면 stdout을 화면에 표시하고 stdout을 파일에 저장하십시오.
./aaa.sh 2> ccc.out | 티 ./bbb.out
편집 : stderr 및 stdout을 화면에 표시하고 파일에 모두 저장하려면 bash의 I / O 리디렉션을 사용할 수 있습니다 .
#!/bin/bash
# Create a new file descriptor 4, pointed at the file
# which will receive stderr.
exec 4<>ccc.out
# Also print the contents of this file to screen.
tail -f ccc.out &
# Run the command; tee stdout as normal, and send stderr
# to our file descriptor 4.
./aaa.sh 2>&4 | tee bbb.out
# Clean up: Close file descriptor 4 and kill tail -f.
exec 4>&-
kill %1
즉, stdout을 한 필터 ( tee bbb.out) 에 파이프 하고 stderr를 다른 필터 ( tee ccc.out) 에 파이프하려고합니다 . stdout 이외의 다른 것을 다른 명령으로 파이프하는 표준 방법은 없지만 파일 설명자를 저글링하여 해결할 수 있습니다.
{ { ./aaa.sh | tee bbb.out; } 2>&1 1>&3 | tee ccc.out; } 3>&1 1>&2
표준 오류 스트림을 잡는 방법 (stderr) 도 참조하십시오 . 그리고 언제 추가 파일 디스크립터를 사용한다?
bash (및 ksh 및 zsh)에서는 대시와 같은 다른 POSIX 셸에서는 프로세스 대체를 사용할 수 있습니다 .
./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out)
bash에서는이 명령 이 여전히 실행 되더라도 (ksh 및 zsh가 하위 프로세스를 기다리 ./aaa.sh더라도) 완료 되 자마자이 명령이 리턴된다는 점에 유의하십시오 tee. 다음과 같은 작업을 수행하면 문제가 될 수 있습니다 ./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.out. 이 경우 대신 파일 디스크립터 저글링 또는 ksh / zsh를 사용하십시오.
sh프로세스 대체를 사용할 수없는 cron 작업에 유용한 가장 간단한 방법입니다 .
bash를 사용하는 경우 :
# Redirect standard out and standard error separately
% cmd >stdout-redirect 2>stderr-redirect
# Redirect standard error and out together
% cmd >stdout-redirect 2>&1
# Merge standard error with standard out and pipe
% cmd 2>&1 |cmd2
신용 (내 머리 위에서 대답하지 않음)은 여기에 있습니다 : http://www.cygwin.com/ml/cygwin/2003-06/msg00772.html
필자의 경우 stdout 및 stderr을 파일로 리디렉션하는 동안 스크립트가 명령을 실행 중이었습니다.
cmd > log 2>&1
오류가 발생했을 때 오류 메시지를 기반으로 몇 가지 조치를 취하도록 업데이트해야했습니다. 물론 dup을 제거하고 2>&1스크립트에서 stderr을 캡처 할 수는 있지만 오류 메시지는 참조를 위해 로그 파일로 이동하지 않습니다. @lhunath에서 허용 대답은 동일한 기능을 수행하도록되어 있지만, 리디렉션 stdout및 stderr내가 원하는하지 않은, 다른 파일에 있지만, 그것은 나를 정확한 해결책을 마련하는 데 도움이된다는 사실을 내가 필요 :
(cmd 2> >(tee /dev/stderr)) > log
위로, 로그는 모두의 사본을해야합니다 stdout그리고 stderr내가 캡처 할 수 있습니다 stderr에 대해 걱정할 필요없이 내 스크립트 stdout.
다음은 프로세스 대체가 불가능한 KornShell (ksh)에서 작동합니다.
# create a combined(stdin and stdout) collector
exec 3 <> combined.log
# stream stderr instead of stdout to tee, while draining all stdout to the collector
./aaa.sh 2>&1 1>&3 | tee -a stderr.log 1>&3
# cleanup collector
exec 3>&-
여기서 실제 트릭 2>&1 1>&3은 우리의 경우에서 stderrto stdout로 리디렉션하고 stdoutto descriptor로 리디렉션하는 순서입니다 3. 이 시점에서 stderr와 stdout아직 결합되지 않았습니다.
실제로 stderr(as stdin)는 설명자 3에 tee로그인 stderr.log하고 설명자 3으로 리디렉션됩니다.
그리고 기술자 3는 combined.log항상 그것을 기록 하고 있습니다. 따라서 와를 combined.log모두 포함합니다 .stdoutstderr
당신이 사용하는 경우 zsh을을 당신도 필요가 없습니다, 당신은 여러 리디렉션을 사용할 수 있습니다 tee:
./cmd 1>&1 2>&2 1>out_file 2>err_file
여기서는 각 스트림을 자신 과 대상 파일 로 리디렉션 합니다.
전체 예
% (echo "out"; echo "err">/dev/stderr) 1>&1 2>&2 1>/tmp/out_file 2>/tmp/err_file
out
err
% cat /tmp/out_file
out
% cat /tmp/err_file
err
이를 위해서는 MULTIOS옵션을 설정 해야합니다 (기본값).
MULTIOS여러 리디렉션을 시도 할 때 암시 적
tee또는을 수행하십시오cat( 리디렉션 참조 ).