이 Bourne 쉘 스크립트에서 `exec 2>&1`이 실패하는 이유는 무엇입니까?

이 Bourne 쉘 스크립트에서 `exec 2>&1`이 실패하는 이유는 무엇입니까?

이전 ksh 스크립트를 Bourne 쉘로 이식하고 있습니다. 이전 ksh 스크립트에는 다음 코드가 포함되어 있습니다.

#!/bin/sh

tmpLog=/var/tmp/logfile.$$

exec 1> $tmpLog
exec 2>&1

eval $*
another_command_1
another_command_2

내가 읽은 바에 따르면 이 두 exec 문은 $*, another_command_1, another_command_2 및 다음 명령을 모두 실행한 다음 해당 명령의 모든 STDERR 및 STDOUT을 /var/tmp/logfile.$$. 스크립트 이 스크립트를 사용하는 경우 스크립트는 에 있습니다 exec 2>&1.

stefanl@host:~ $ sh -xv ./output.sh echo "Hello"
#!/bin/sh

tmpLog=/var/tmp/logfile.$$
+ tmpLog=/var/tmp/logfile.39918

exec 1> $tmpLog
+ exec
exec 2>&1
+ exec
stefanl@host:~ $

명령줄에서 이 명령을 실행하면 실행 후 쉘이 정지됩니다 exec 2>&1.

stefanl@host:~ $ tmpLog=/var/tmp/logfile.$$
stefanl@host:~ $ exec 1> $tmpLog
stefanl@host:~ $ exec 2>&1
### FREEZE ###

내 질문:

  1. 무엇을 해야 합니까 exec 2>&1?
  2. 왜 나에게 실패했는가?

답변1

귀하의 스크립트는 실패하지 않습니다. 정상적으로 작동합니다. exec >logfile; exec 2>&1표준 출력과 표준 오류 logfile를 . 현재 셸에서 이러한 리디렉션을 직접 수행하면 터미널에서 모든 출력을 보냈기 때문에 셸이 정지된 것처럼 보입니다.

xtrace( ) 옵션의 출력은 set -x항상 파일 설명자 2인 표준 오류로 이동한다는 점에 유의하세요. 로그 파일에 보내는 파일 설명자입니다. 거기에서 나머지 내용을 찾아야 합니다 exec 2>&1.

답변2

이 형태의 exec(즉, 명령 없이)는 현재 쉘 인터프리터의 모든 후속 출력을 리디렉션하는 데 사용됩니다.

Bash의 내장 도움말:

$는 실행을 돕습니다
exec: exec [-cl] [-a 이름] [명령 [매개변수...]] [리디렉션...]
    쉘을 주어진 명령으로 대체합니다.

    COMMAND를 실행하여 이 쉘을 지정된 프로그램으로 바꾸십시오.
    ARGUMENTS는 COMMAND의 매개변수가 됩니다. 명령이 지정되지 않은 경우
    모든 리디렉션은 현재 셸에 적용됩니다.
    [...]

나는 exec &> logfile stdout과 stderr을 동시에 리디렉션하는 데 사용합니다. 예를 들어 대부분의 백업 및 rsync 래퍼 스크립트(또는 나중에 자세히 조사할 수 있는 많은 출력을 생성하는 스크립트)는 다음과 같이 시작됩니다.

BNAME=$(basename "$0" .sh)
LOGFILE="/tmp/$BNAME.log"
savelog "$LOGFILE"
exec &> "$LOGFILE"

그런 다음 cron이나 백그라운드에서 스크립트를 실행하고 tail -F스크립트가 실행되는 동안 로그 파일을 관찰합니다. 로그 저장을 사용하면 마지막 7개 실행의 출력을 유지할 수 있습니다(기본값은 7이며 savelog -c변경하는 데 사용할 수 있음).

관련 정보