stdout의 COPY를 bash 스크립트 자체에서 로그 파일로 리다이렉트
stdout을 파일로 리디렉션하는 방법을 알고 있습니다.
exec > foo.log
echo test
이렇게 하면 foo.log 파일에 '테스트'가 저장됩니다.
이제 출력을 로그 파일로 리다이렉트하여 stdout에 저장합니다.
즉, 스크립트 외부에서 3회 실행할 수 있습니다.
script | tee foo.log
스크립트 자체에서 선언하고 싶다.
나는 노력했다.
exec | tee foo.log
하지만 그것은 작동하지 않았다.
#!/usr/bin/env bash
# Redirect stdout ( > ) into a named pipe ( >() ) running "tee"
exec > >(tee -i logfile.txt)
# Without this, only stdout would be captured - i.e. your
# log file would not contain any error messages.
# SEE (and upvote) the answer by Adam Spiers, which keeps STDERR
# as a separate stream - I did not want to steal from him by simply
# adding his answer to mine.
exec 2>&1
echo "foo"
echo "bar" >&2
은 「」인 것에 주의해 주세요.bash
아니라, 이에요.sh
. 를 " "로 로 기동합니다.sh myscript.sh
syntax error near unexpected token '>'
.
하고 있는 는, 「」를 하는 합니다.tee -i
시 위한 ( to James)Thomas Moon1979년).
에 쓰느냐에 (「Tool」ls
예를 들어 색상 및 열화된 출력을 사용하여 위 구성을 파이프에 출력한다는 의미로 탐지합니다.
"/"/"컬럼화ls -C --color=always
이렇게 하면 색상 코드도 로그 파일에 기록되므로 읽기 어려워집니다.
승인된 답변은 STDERR을 개별 파일 기술자로 유지하지 않습니다.즉,
./script.sh >/dev/null
하지 .bar
그리고 까지.
./script.sh 2>/dev/null
다 됩니다.foo
★★★★★★★★★★★★★★★★★」bar
터미널에 접속합니다.그것은 일반 사용자가 예상할 수 있는 행동이 아닌 것이 분명하다.은, 같은 파일에 되는, 할 수 .이러한 프로세스는, 「」 「TE」 「TE」 「TE」 「TE」 「TE」 「TE」 「TE」 「TE」입니다.
#!/bin/bash
# See (and upvote) the comment by JamesThomasMoon1979
# explaining the use of the -i option to tee.
exec > >(tee -ia foo.log)
exec 2> >(tee -ia foo.log >&2)
echo "foo"
echo "bar" >&2
(상기에서는 로그파일이 처음에 잘리는 것은 아닙니다.이 동작을 하고 싶은 경우는, 로그 파일을 추가할 필요가 있습니다.
>foo.log
스크립트 맨 위로 이동합니다.)
의 POSIX.1-2008 사양에서는 출력이 버퍼링되지 않은 것, 즉 회선 버퍼링되지 않은 것이 요구되기 때문에 이 경우 STDOUT과 STDERR이 같은 회선에 도달하는 경우가 있습니다.foo.log
단, 단말에서도 발생할 수 있기 때문에 로그파일은 단말기에서 볼 수 있는 것을 정확하게 반영하고 있습니다.STDOUT 행을 STDERR 행에서 완전히 분리할 경우 로그파일을 2개 사용하는 것을 검토해 주십시오.각 행에 날짜 스탬프 프레픽스를 붙이면 나중에 시간순으로 재구성할 수 있습니다.
busybox, macOS bash 및 non-bash 쉘용 솔루션
받아들여진 답변은 확실히 bash에게 최선의 선택이다.bash에 할 수 bash를 .비지박스 배쉬exec > >(tee log.txt)
구문을 사용합니다., 「」는 .exec >$PIPE
지정된 파이프와 같은 이름의 일반 파일을 생성하려고 하는데, 이 파일이 실패하여 중단됩니다.
이것이 배쉬가 없는 다른 사람에게 유용하기를 바란다.
명명된 파이프를 합니다.rm $PIPE
VFS에서 파이프의 링크가 해제되지만 VFS를 사용하는 프로세스는 완료될 때까지 파이프의 참조 카운트를 유지합니다.
$*의 사용이 반드시 안전한 것은 아닙니다.
#!/bin/sh
if [ "$SELF_LOGGING" != "1" ]
then
# The parent process will enter this branch and set up logging
# Create a named piped for logging the child's output
PIPE=tmp.fifo
mkfifo $PIPE
# Launch the child process with stdout redirected to the named pipe
SELF_LOGGING=1 sh $0 $* >$PIPE &
# Save PID of child process
PID=$!
# Launch tee in a separate process
tee logfile <$PIPE &
# Unlink $PIPE because the parent process no longer needs it
rm $PIPE
# Wait for child process, which is running the rest of this script
wait $PID
# Return the error code from the child process
exit $?
fi
# The rest of the script goes here
스크립트 파일 내에서 다음과 같이 모든 명령을 괄호 안에 넣습니다.
(
echo start
ls -l
echo end
) | tee foo.log
bash 를 syslog.bash로 할 수 .은, 「 쪽인가」, 「어느 쪽인가」를 통해서도 할 수 있습니다./var/log/syslog
를 통해 stderr. syslog를 포함한 메타데이터가 됩니다.
맨 위에 다음 행을 추가합니다.
exec &> >(logger -t myscript -s)
또는 로그를 다른 파일로 전송합니다.
exec &> >(ts |tee -a /tmp/myscript.output >&2 )
에는 「」가 필요합니다.moreutils
)ts
타임스탬프가 추가됩니다).
수락된 답변을 사용하여 스크립트는 예외적으로 일찍('exec > > (tee...)' 직후) 반환되고 나머지 스크립트는 백그라운드에서 실행됩니다.그 솔루션을 내 방식대로 사용할 수 없었기 때문에 문제에 대한 다른 해결책/해결책을 찾았습니다.
# Logging setup
logfile=mylogfile
mkfifo ${logfile}.pipe
tee < ${logfile}.pipe $logfile &
exec &> ${logfile}.pipe
rm ${logfile}.pipe
# Rest of my script
이를 통해 스크립트 출력은 프로세스에서 파이프를 통해 모든 것을 디스크 및 스크립트의 원래 stdout에 기록하는 'tee'의 하위 백그라운드 프로세스로 전송됩니다.
'exec & >'는 stdout과 stderr를 모두 리다이렉트하므로 필요에 따라 개별적으로 리다이렉트하거나 stdout을 원할 경우 'exec >'로 변경할 수 있습니다.
스크립트의 선두에서 파이프가 파일시스템에서 삭제되어도 프로세스가 완료될 때까지 계속 기능합니다.rm-line 뒤에 있는 파일 이름을 사용하여 참조할 수 없습니다.
Bash 4에는 명령어에 대한 명명된 파이프를 확립하고 이를 통해 통신할 수 있는 명령어가 있습니다.
이그제큐티브를 기반으로 한 솔루션이 마음에 들지 않는다고는 말할 수 없습니다.저는 Tee를 직접 사용하는 것을 선호하기 때문에 요청 시 스크립트 자체를 Tee로 호출합니다.
# my script:
check_tee_output()
{
# copy (append) stdout and stderr to log file if TEE is unset or true
if [[ -z $TEE || "$TEE" == true ]]; then
echo '-------------------------------------------' >> log.txt
echo '***' $(date) $0 $@ >> log.txt
TEE=false $0 $@ 2>&1 | tee --append log.txt
exit $?
fi
}
check_tee_output $@
rest of my script
이를 통해 다음과 같은 작업을 수행할 수 있습니다.
your_script.sh args # tee
TEE=true your_script.sh args # tee
TEE=false your_script.sh args # don't tee
export TEE=false
your_script.sh args # tee
이를 사용자 정의할 수 있습니다. 예를 들어, tee=false를 기본값으로 만들거나, TEE가 로그 파일을 대신 유지하도록 하는 등입니다.이 솔루션은 jbarlow의 솔루션과 비슷하다고 생각합니다만, 간단하게 말하면, 아직 경험하지 못한 한계가 있을지도 모릅니다.
둘 다 완벽한 솔루션은 아니지만, 다음은 시도해 볼 수 있는 몇 가지 방법입니다.
exec >foo.log
tail -f foo.log &
# rest of your script
또는
PIPE=tmp.fifo
mkfifo $PIPE
exec >$PIPE
tee foo.log <$PIPE &
# rest of your script
rm $PIPE
스크립트에 때 파일이 있는 로 유지되며,가 될 수도 수도 가 되지 않을 수도 있습니다).이것은 문제가 될 수도 있고 아닐 수도 있습니다(즉, 문제가 될 수도 있습니다).rm
중중부부부부부셸셸셸셸셸나 。
언급URL : https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself
'programing' 카테고리의 다른 글
UIStackView에서 프로그래밍 방식으로 보기 추가 (0) | 2023.04.16 |
---|---|
각 시트를 워크북에 저장하여 CSV 파일을 구분합니다. (0) | 2023.04.16 |
"TypeError: method()는 1개의 positional 인수를 사용하지만 2개의 positional 인수가 지정되었습니다." 그러나 1개만 통과했습니다. (0) | 2023.04.16 |
리모트에 존재하지 않는 로컬 추적 브랜치를 삭제하려면 어떻게 해야 합니까? (0) | 2023.04.16 |
모달 View Controller 프레젠테이션 스타일이 UIModal Presentation FormSheet인 경우 iPad 키보드가 꺼지지 않습니다. (0) | 2023.04.16 |