BASH의 명령 그룹 출력을 STDOUT 및 로그 파일로 캡처해야 합니다. 명령 및 해당 출력으로 그룹화된 다음 코드를 고려하세요.
#!/usr/bin/bash
main(){
declare -i mycode=1
echo "Declared mycode:${mycode}"
{
#command group
echo "mycode:${mycode}"
mycode=2
echo "mycode:${mycode}"
} 2>&1
echo "mycode:${mycode}"
}
main
출력은 다음과 같습니다
Declared mycode:1
mycode:1
mycode:2
mycode:2
명령 그룹 출력을 로그 파일 및 STDOUT으로 캡처해야 하므로 다음과 같이 tee를 추가합니다.
#!/usr/bin/bash
main(){
declare -i mycode=1
echo "Declared mycode:${mycode}"
{
#command group
echo "mycode:${mycode}"
mycode=2
echo "mycode:${mycode}"
} 2>&1 | tee ~/log.log
echo "mycode:${mycode}"
}
main
그러나 이제 출력은 다음과 같습니다.
Declared mycode:1
mycode:1
mycode:2
mycode:1
그래서 가치는내 코드tee를 사용하는 경우 tee의 왼쪽이 하위 쉘에서 실행되므로 외부 범위에서 변수가 2로 설정되지 않습니다. 여러 가지 이유로 나에게 필요한내 코드전역 범위에서 정의되었으므로 하위 쉘 사용을 피해야 합니다.
서브쉘 없이 tee의 동작을 구현하여 출력을 STDOUT 및 로그 파일로 스트리밍하려면 어떻게 해야 합니까?
답변1
이 문제를 해결하는 한 가지 방법은 파이프 커넥터를 직접 구현하는 것입니다.
#!/bin/bash
# Initialisation
mycode=1
# Tidy up
trap 'ss=$?; [ -n "$tmpd" ] && [ -d "$tmpd" ] && rm -rf "$tmpd"; exit $ss' 1 2 15
# Unique temporary directory
tmpd=$(mktemp --directory "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
# Create pipe
pipe="$tmpd/pipe"
mknod "$pipe" p
# Output
tee <"$pipe" "$HOME/log.log" &
# Subprocess
{
echo "mycode:${mycode}"
mycode=2
echo "mycode:${mycode}"
} >"$pipe" 2>&1
# Destroy temporary, including pipe
wait
rm -rf "$tmpd"
# Done
echo "final mycode:${mycode}"
산출
mycode:1
mycode:2
final mycode:2
반품cat ~/log.log
mycode:1
mycode:2
답변2
로그 파일로 달성하려는 목적에 따라 설명자 #3에 추가할 수 있습니다. (기억하다표준 출력1위이고표준 에러# 3입니다. )
#!/bin/bash
# Initialisation
mycode=1
# Attach fd3 to the logfile and stdout
exec 3> >(tee "$HOME/log.log" >&1)
# Demonstrations
echo this is to stdout
echo this is to stderr >&2
echo this is to logfile and stdout >&3
# Subprocess
{
echo "mycode:${mycode}"
mycode=2
echo "mycode:${mycode}"
} 2>&1 1>&3
# Done
echo "final mycode:${mycode}"
sleep 0.25
이 접근 방식의 한 가지 장점은 파일 설명자 3으로 리디렉션하기만 하면 어디에서나 로그 파일에 쉽게 쓸 수 있다는 것입니다(위의 "데모" 코드 블록 참조).
단점은 tee
비동기식으로 실행되므로 출력이 잘못 인터리브될 수 있다는 것입니다. 궁극적인 목표는 출력 작성을 완료 sleep 0.25
할 시간을 허용하는 것입니다 . tee
기능을 어떻게 사용하느냐에 따라 인터리브가 실제 문제가 될 수도 있고 아닐 수도 있습니다.
출력 예:
this is to stdout
this is to stderr
final mycode:2
this is to logfile and stdout
mycode:1
mycode:2
로그 파일( cat "$HOME/log.log"
):
this is to logfile and stdout
mycode:1
mycode:2