변수 범위가 영향을 받지 않도록 서브쉘을 사용하지 않고 티 동작을 복제합니다.

변수 범위가 영향을 받지 않도록 서브쉘을 사용하지 않고 티 동작을 복제합니다.

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

관련 정보