Por que o 'exec 2 & 1' falha neste script de shell bourne?

7

Estou portando um script ksh antigo para o shell Bourne. O antigo script ksh contém o seguinte código:

#!/bin/sh

tmpLog=/var/tmp/logfile.$$

exec 1> $tmpLog
exec 2>&1

eval $*
another_command_1
another_command_2

Pelo que eu li, parece que estas duas instruções exec destinam-se a executar $ *, another_command_1, another_command_2 e todos os comandos seguintes; e, em seguida, redirecione todos os STDERR e STDOUT desses comandos para /var/tmp/logfile.$$ . No entanto, quando executo isso em um script, o script falha após 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:~ $

E quando eu executo isso na linha de comando, meu shell congela depois que eu executo exec 2>&1 :

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

Minhas perguntas:

  1. O que o exec 2>&1 deve fazer?
  2. Por que isso está falhando para mim?
por Stefan Lasiewski 31.07.2012 / 20:07

2 respostas

15

Seu script não está falhando - está funcionando muito bem. Seu entendimento está correto em que exec >logfile; exec 2>&1 redireciona a saída padrão e o erro padrão para logfile . Então, você deve estar procurando no arquivo de log e não no seu terminal por saída e erro. Se você executar esses redirecionamentos diretamente no seu shell atual, parece que o seu shell congelou porque você enviou toda a saída do seu terminal.

Observe que a saída da opção xtrace ( set -x ) também vai para o erro padrão, que é sempre o descritor de arquivo 2 ... que você enviou para o arquivo de log. Você deve encontrar o resto depois do exec 2>&1 .

    
por 31.07.2012 / 20:16
4

Esta forma de execução (isto é, sem um comando) é usada para redirecionar todas as saídas subsequentes do interpretador de shell atual.

da ajuda integrada do bash:

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.
    [...]

Eu uso exec &> logfile para redirecionar stdout e stderr ao mesmo tempo. por exemplo. a maioria dos meus scripts de backup e wrapper rsync (ou qualquer script que produza muitos resultados que eu possa querer examinar em detalhes mais tarde) comece com algo assim:

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

Eu, então, executo o script do cron, ou em segundo plano, e uso tail -F para observar o arquivo de log enquanto o script está sendo executado. O savelog me permite manter a saída das últimas 7 execuções (7 por padrão, savelog -c pode ser usado para alterar isso).

    
por 01.08.2012 / 01:11