답변:
터미널에 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의 입력 ( tee
STDIN) 으로 리디렉션 합니다.
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.log
bash에서 작동합니다.
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
은 우리의 경우에서 stderr
to stdout
로 리디렉션하고 stdout
to descriptor로 리디렉션하는 순서입니다 3
. 이 시점에서 stderr
와 stdout
아직 결합되지 않았습니다.
실제로 stderr
(as stdin
)는 설명자 3에 tee
로그인 stderr.log
하고 설명자 3으로 리디렉션됩니다.
그리고 기술자 3
는 combined.log
항상 그것을 기록 하고 있습니다. 따라서 와를 combined.log
모두 포함합니다 .stdout
stderr
당신이 사용하는 경우 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
( 리디렉션 참조 ).