programing

파이프와 함께 "tee"를 사용하는 동안 파일에 표준 오류를 쓰는 방법은 무엇입니까?

muds 2023. 4. 16. 15:57
반응형

파이프와 함께 "tee"를 사용하는 동안 파일에 표준 오류를 쓰는 방법은 무엇입니까?

있습니다.tee출력(표준 출력)을 쓰다aaa.sh로로 합니다.bbb.out단말기에 표시하면서 다음을 수행합니다.

./aaa.sh | tee bbb.out

다음 파일에 표준 오류도 어떻게 쓸 수 있을까요?ccc.out시해해 둔???

터미널에서 표준 오류와 표준 출력을 보고 싶으시겠죠.조쉬 켈리의 대답을 들을 수도 있지만, 난 그 대답에 대해tail백그라운드에서 로그 파일을 매우 해킹하고 투박하게 출력합니다.추가 파일 기술자를 보관하고 나중에 파일을 삭제함으로써 정리하는 방법을 알아두십시오.기술적으로는 파일 기술자를 삭제해야 합니다.trap '...' EXIT.

더 은 이미 발견하셨을 거예요.tee.

표준 출력에만 사용하는 것이 아니라 표준 출력과 표준 오류에 대한 티만 사용하십시오.어떻게 해내실 건가요?프로세스 대체 및 파일 리디렉션:

command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)

분할하여 설명하겠습니다.

> >(..)

>(...) 치환되어 FIFO가 생성됩니다.tee 나서, '이렇게'를 사용합니다.> 리다이렉트.command 번째 FIFO에 tee고고있있있있다다

두 번째도 마찬가지입니다.

2> >(tee -a stderr.log >&2)

해서 ''를 요.tee 「」에 하는 .stderr.logtee, 그 에러이므로, 「 에러」를 리다이렉트 .tee을 사용하다 다음 파일 하여 리다이렉트합니다.commandFIFO)tee의준표입입입입 。

"입력출력" 참조

를 셸로 수 중입니다.는 Bash가 Bash를 입니다.sh(POSIX 본).


»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"

심플:

./aaa.sh 2>&1 | tee -a log

이것은 표준 에러를 표준 출력으로 리다이렉트 할 뿐이기 때문에, TEE는 로그와 화면 양쪽에 에코를 울립니다.제가 뭔가 놓치고 있는 건지도 몰라요. 다른 해결책들은 너무 복잡해 보이거든요.

주의: Bash 버전4부터는|&의 줄임말로서2>&1 |:

./aaa.sh |& tee -a log

이것은 구글을 통해 이것을 찾는 사람들에게 유용할 수 있다.시험해 보고 싶은 예를 간단히 설명하세요.물론 출력 파일의 이름을 변경할 수 있습니다.

#!/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}

표준 에러를 파일로 리다이렉트 하려면 , 화면에 표준 출력을 표시하고,

./aaa.sh 2> ccc.out | tee ./bb.out

화면에 표준 오류와 표준 출력을 모두 표시하고 둘 다 파일에 저장하려면 Bash의 I/O 리디렉션을 사용할 수 있습니다.

#!/bin/bash

# Create a new file descriptor 4, pointed at the file
# which will receive standard error.
exec 4<>ccc.out

# Also print the contents of this file to screen.
tail -f ccc.out &

# Run the command; tee standard output as normal, and send standard error
# 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)grep 방법」도 참조해 주세요.파일 기술자를 추가할 때는 언제입니까?

bash(및 ksh 및 zsh)에서는 사용할 수 있지만 대시 등의 다른 POSIX 쉘에서는 사용할 수 없습니다.

./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out)

이 는 bash가 반환되는 ../aaa.sh.tee명령은 계속 실행됩니다(ksh 및 zsh는 하위 프로세스를 기다립니다).가 될 수 있어요../aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.outksh/zsh로 하다

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

크레딧(내 머리에서부터 대답하지 않음)은 여기에 있습니다: Re: bash: stderr & more(stderr의 파이프)

Z 쉘을 사용하는 경우(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여러 리다이렉션을 시행하는 경우(리다이렉트 참조).

lhunath가 잘 설명해준 답처럼, 당신은 그것을 사용할 수 있다.

command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)

bash를 사용하면 문제가 생길있으니 주의하세요.

매튜 윌콕슨의 예를 들어보겠습니다.

그리고 "보는 것이 믿는 것"을 위한 간단한 테스트:

(echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)

개인적으로 시도해보니 다음과 같은 결과가 나옵니다.

user@computer:~$ (echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)
user@computer:~$ Test Out
Test Err

두 메시지가 동일한 수준으로 표시되지 않습니다.?는 왜?Test Out치치 내전 령령 령?? ?? ???

프롬프트가 공백 행에 표시되어 프로세스가 완료되지 않았다고 생각되며, 이 버튼을 누르면 수정됩니다.파일 내용을 확인하면 정상이며 리다이렉트도 가능합니다.

다른 시험을 치르자.

function outerr() {
  echo "out"     # stdout
  echo >&2 "err" # stderr
}
user@computer:~$ outerr
out
err

user@computer:~$ outerr >/dev/null
err

user@computer:~$ outerr 2>/dev/null
out

리다이렉션을 다시 시도하고 있지만 다음 기능을 사용합니다.

function test_redirect() {
  fout="stdout.log"
  ferr="stderr.log"
  echo "$ outerr"
  (outerr) > >(tee "$fout") 2> >(tee "$ferr" >&2)
  echo "# $fout content: "
  cat "$fout"
  echo "# $ferr content: "
  cat "$ferr"
}

개인적으로 다음과 같은 결과가 있습니다.

user@computer:~$ test_redirect
$ outerr
# stdout.log content:
out
out
err
# stderr.log content:
err
user@computer:~$

빈 줄에 프롬프트가 표시되지 않지만 정상적인 출력이 표시되지 않습니다.stdout.log 내용이 잘못된 것 같고 stderr.log만 정상인 것 같습니다.

다시 시작하면 출력이 달라질 수 있습니다.

그럼, 왜?

왜냐하면 여기서 설명한 바와 같이:

bash에서는 tee 명령이 계속 실행되더라도 [first command]가 끝나는 대로 이 명령이 반환된다는 점에 유의하십시오(ksh 및 zsh는 하위 프로세스를 기다립니다).

따라서 Bash를 사용하는 경우 다음 답변에 제시된 보다 나은 예를 사용하는 것이 좋습니다.

{ { outerr | tee "$fout"; } 2>&1 1>&3 | tee "$ferr"; } 3>&1 1>&2

이전 문제가 해결됩니다.

문제는 종료 상태 코드를 어떻게 검색하느냐는 것입니다.

$?동작하지 않습니다.

장애로 인한 파이프 더 .set -o pipefail )set +o pipefail를 끄고 ${PIPESTATUS[0]}음음음같 뭇매하다

function outerr() {
  echo "out"
  echo >&2 "err"
  return 11
}

function test_outerr() {
  local - # To preserve set option
  ! [[ -o pipefail ]] && set -o pipefail; # Or use second part directly
  local fout="stdout.log"
  local ferr="stderr.log"
  echo "$ outerr"
  { { outerr | tee "$fout"; } 2>&1 1>&3 | tee "$ferr"; } 3>&1 1>&2
  # First save the status or it will be lost
  local status="${PIPESTATUS[0]}" # Save first, the second is 0, perhaps tee status code.
  echo "==="
  echo "# $fout content :"
  echo "<==="
  cat "$fout"
  echo "===>"
  echo "# $ferr content :"
  echo "<==="
  cat "$ferr"
  echo "===>"
  if (( status > 0 )); then
    echo "Fail $status > 0"
    return "$status" # or whatever
  fi
}
user@computer:~$ test_outerr
$ outerr
err
out
===
# stdout.log content:
<===
out
===>
# stderr.log content:
<===
err
===>
Fail 11 > 0

이 경우 스크립트가 stdout과 stderr를 모두 파일로 리다이렉트하면서 다음과 같은 명령을 실행하고 있었습니다.

cmd > log 2>&1

에러 메세지에 근거해, 에러 메세지에 근거해 몇개의 조치를 취할 필요가 있었습니다. 듀프는 할 수 .2>&1스크립트에서 stderr을 캡처하면 오류 메시지가 참조용으로 로그 파일에 저장되지 않습니다.lhunath로부터 수신된 응답도 같은 처리를 하도록 되어 있습니다만, 리다이렉트 됩니다.stdout ★★★★★★★★★★★★★★★★★」stderr하다그것은 제가 원하는 것은 아니지만, 제가 필요로 하는 정확한 솔루션을 생각해 낼 수 있었습니다.

(cmd 2> >(tee /dev/stderr)) > log

경우, 에는, 「중요」와「중요」의 모두의 됩니다.stdout ★★★★★★★★★★★★★★★★★」stderr할 수 .stderr하지 되는 내 stdout.

다음은 프로세스 대체를 사용할 수 없는 KornShell(ksh)에 적용됩니다.

# create a combined (standard input and standard output) collector
exec 3 <> combined.log

# stream standard error instead of standard output to tee, while draining all standard output to the collector
./aaa.sh 2>&1 1>&3 | tee -a stderr.log 1>&3

# cleanup collector
exec 3>&-

은 기서 the of의 입니다.2>&1 1>&3이 경우 표준 에러를 표준 출력으로 리다이렉트하고 표준 출력을 파일 기술자 3으로 리다이렉트 합니다.현시점에서는 표준오차와 표준출력은 아직 조합되지 않았습니다.

실제로 표준오차(표준입력)는 다음 주소로 전달됩니다.tee서 「」에 로그 .stderr.log파일 디스크립터 3으로 리다이렉트 합니다.

파일 은 이 하고 있습니다.combined.log 그...combined.log에는 표준 출력과 표준 오류가 모두 포함되어 있습니다.

POSIX에 답변해 주셔서 감사합니다.

POSIX에서 필요한 더 복잡한 상황은 다음과 같습니다.

# Start script main() function
# - We redirect standard output to file_out AND terminal
# - We redirect standard error to file_err, file_out AND terminal
# - Terminal and file_out have both standard output and standard error, while file_err only holds standard error

main() {
    # my main function
}

log_path="/my_temp_dir"
pfout_fifo="${log_path:-/tmp}/pfout_fifo.$$"
pferr_fifo="${log_path:-/tmp}/pferr_fifo.$$"

mkfifo "$pfout_fifo" "$pferr_fifo"
trap 'rm "$pfout_fifo" "$pferr_fifo"' EXIT

tee -a "file_out" < "$pfout_fifo" &
    tee -a "file_err" < "$pferr_fifo" >>"$pfout_fifo" &
    main "$@" >"$pfout_fifo" 2>"$pferr_fifo"; exit

( 「」 「」 「」)STDERR 또는 할 수 : ) 、 음 、 음 、 다 、 다 、 다 、 다 、 ) 、 ):::::: 。

배쉬:

gcc temp.c &> error.log

C 쉘(csh

% gcc temp.c |& tee error.log

참고 항목: 컴파일/빌드 오류를 파일로 리디렉션하려면 어떻게 해야 합니까?

언급URL : https://stackoverflow.com/questions/692000/how-do-i-write-standard-error-to-a-file-while-using-tee-with-a-pipe

반응형