sh 쉘: 출력을 스크립트 내의 터미널 및 파일로 리디렉션

sh 쉘: 출력을 스크립트 내의 터미널 및 파일로 리디렉션

stdout 및 stderr을 스크립트 내부에서 파일 및 터미널로 리디렉션하는 방법.

#!/bin/bash

LOG_FILE="/tmp/abc.log"

exec &> >(tee -a $LOG_FILE)

echo "Start"
echo "Hi" 1>&2 
echo "End"

위의 스크립트를 찾았습니다. 하지만 이 스크립트는 bash에서만 작동합니다. sh 쉘을 사용하면 다음 오류가 발생합니다.

./abc.sh: 5: Syntax error: redirection unexpected (expecting word)

sh 및 bash 쉘과 함께 사용할 수 있는 스크립트를 원합니다.

답변1

예, &>연산자 bash(이제 에서도 지원되며 zsh항상 에서와 동일한 기능을 zsh가짐 )와 연산자 (현재 및 에서도 지원됨 )는 둘 다 연산자가 아닙니다. 따옴표가 없는 $LOG_FILE, 여기서는 분명히 분할+glob을 사용하여 zsh 구문으로 만들고 싶지 않습니다( 이런 방식이기는 하지만 분할+glob이 따옴표가 없는 확장에서 암시적으로 수행하지 않는 유일한 셸입니다 ).>&csh>(...)kshzshbashshzshexec >&1 > $LOG_FILE 2>&1

구문적으로는 sh다음과 같이 할 수 있습니다.

#! /bin/sh -
LOG_FILE="/tmp/abc.log"

{

  # your script here


} 2>&1 | tee -- "$LOG_FILE"

아니면 모든 것을 함수에 넣으세요:

#! /bin/sh -
LOG_FILE="/tmp/abc.log"

main() {

  # your script here


}

main "$@" 2>&1 | tee -- "$LOG_FILE"

그럼에도 불구하고 이 접근 방식과 zsh-style 접근 방식은 모두 표준 출력에서 ​​열린 동일한 리소스에 오류 메시지를 인쇄하게 됩니다. 따라서 누군가가 이렇게 하면 비어 있고 your-script > out 2> err정상적인 출력과 오류가 포함됩니다.errout

출력 및 오류의 원래 대상이 보존되도록 하려면 다음을 수행할 수 있습니다.

{
  {
    main "$@" 3>&- | tee -a -- "$LOG_FILE" >&3 3>&-
  } 2>&1 | tee -a -- "$LOG_FILE" >&2 3>&-
} 3> "$LOG_FILE" 3>&1

(검증되지 않은).

또한 보안 관점에서 볼 때 전역적으로 쓰기 가능한 디렉터리에 고정된 이름을 가진 파일을 사용하는 것은 /tmp나쁜 습관 입니다. 다른 사용자가 동일한 이름의 악의적인 심볼릭 링크를 배치할 수 있으므로 해당 링크가 가리키는 지점을 덮어쓰게 될 수 있습니다. 문서.

관련 정보