O script de shell não pinta a última linha de stdout para a tela sem a entrada do usuário

3

Eu tenho um script de shell que está fazendo todo o meu processo de backup e escrevendo progresso para stderr e stdout, com uma exceção - a última linha não é gravada no meu terminal (se eu chamar o script manualmente) até atingir Enter .

Agora, isso não é grande coisa, mas está realmente me irritando que não esteja fazendo isso, então eu gostaria de entender por que ele está se comportando dessa maneira.

O que é gravado na saída (depois que eu digito Enter ) diz:

[blackero@XXXXXXXXXXXXXXXX ~]$ fullbackup.sh
Tue Feb 28 17:57:41 GMT 2012
Tue Feb 28 17:57:41 GMT 2012
Starting SITE_NAME backup
maintenance_mode was set to 1.                                                    [success]
/home/blackero/bin/fullbackup.sh: line 36: hash: lzma: not found
maintenance_mode was set to 0.                                                    [success]

Backup for SITE_NAME created


[blackero@XXXXXXXXXXXXXXXX ~]$

As partes relevantes do script são lidas da seguinte forma (com indicando que o código foi legível para legibilidade):

#!/bin/bash
date
date 2>&1

# [A bunch of content has been deleted from here]

# Compress with lzma if available, otherwise use gzip
if hash lzma; then
  lzma -c ${backup_dest}/${dbname} >${backup_dest}/${dbname}.lzma
  ↪  && rm ${backup_dest}/${dbname}
else
  gzip -c ${backup_dest}/${dbname} >${backup_dest}/${dbname}.gz
  ↪  && rm ${backup_dest}/${dbname}
fi

# Disable maintenance mode.
drush -r ${drupal_root} vset --always-set maintenance_mode 0

# Remove old backups >30 days
find ${backup_dest} -mtime +30 -exec rm {} \; >> /dev/null 2>&1

echo "Backup for ${sitename} created"
echo
echo 2>&1

Então, você pode ver a linha if hash lzma; then que está causando a linha hash: lzma: not found para stderr (seria legal se eu pudesse suprimir essa mensagem, então ela não escreve esse aviso, mas eu posso viver com isso ). Você pode ver que drush está gravando a linha maintenance_mode was set to 0. para stdout. Mas a linha Backup for SITE_NAME created aparece apenas quando eu teco Enter .

É porque o comando anterior está redirecionando o stdout para /dev/null ? Preciso desfazer esse redirecionamento de alguma forma? (Eu pensei que o redirecionamento de fluxo só afetou o único comando atomicamente).

(Advertências: Fwiw, quando este script é executado a partir do cron, com o stdout e o stderr redirecionados para acrescentar aos arquivos de log, tudo é gravado nos arquivos de log de forma feliz, sem a necessidade de entrada de terminal. O script é originalmente de Guia de Administração daDrupal: fullsitebackup_drush ; editei um valor justo, mas o código lzma ou gzip é de lá.)

    
por Owen Blacker 28.02.2012 / 19:32

1 resposta

7

Se os arquivos de backup forem somente leitura, é possível que o comando rm executado por find esteja solicitando que você confirme se deve ou não excluir um arquivo de backup. Você não pode ver o prompt porque você o redirecionou para / dev / null. O Enter pressionado é lido por rm (e faz com que rm receba a resposta padrão, que não é apagar o arquivo).

Se essa hipótese estiver correta, você poderá corrigir o problema de duas maneiras. Um é portátil, mas inseguro, o outro não é portável, mas é mais seguro. Mesmo que, neste caso, a diferença de segurança seja provavelmente pequena (já que os invasores provavelmente não podem criar links simbólicos em $ {backup_dest}), sugiro as duas opções:

seguro:

find "${backup_dest}" -depth -mtime +30 -delete

portátil:

find "${backup_dest}" -depth -mtime +30 \
  '(' '(' -type d -exec rmdir {} \; -true ')' -o -exec rm -f {} \; ')'

Por fim, não há necessidade de usar "> > / dev / null" em vez de "> / dev / null", já que não há diferença entre anexar a um dispositivo de caractere e escrever nele, pois os dispositivos de caractere são não é procurado.

    
por 29.02.2012 / 00:32