이전 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 ###
내 질문:
- 무엇을 해야 합니까
exec 2>&1
? - 왜 나에게 실패했는가?
답변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
변경하는 데 사용할 수 있음).