Como gzip somente se o mysqldump não errar?

3

Eu quero zip o sql dump se e somente se o mysqldump não produzir nenhum erro. Eu tento colocar a senha errada, mas ainda executa o gzip.

 mysqldump -u username -ppassword dbname |& if [ $? == 0 ]; then gzip > test.gz; else echo "error"; fi

O que há de errado com meu comando ou há alguma solução melhor?

    
por Gilles 06.08.2017 / 04:43

5 respostas

4

Eu acho que você poderia remover |& (o motivo é que você não precisa canalizar o stdout ou stderr para o próximo condicional, se você puder usar apenas ';' como um separador de comando). Algo como isso provavelmente deve funcionar:

#!/bin/bash
mysqldump -u myuser -p mypasswd > mydb.dump
if [[ $? -eq 0 ]]; then
    gzip mydb.dump
else 
    echo >&2 "DB backup failed" 
    exit 1
fi

Edit: para verificar o sucesso do gzip você poderia fazer algo assim:

mysqldump -u myuser -p mypasswd | gzip > mydb.dump.gz && echo "success" || echo "failure" 

No entanto, isso seria um sucesso, mesmo se mysqldump falhasse, ou seja, se o backup falhasse por vários outros motivos além de o gzip ter preenchido o disco.

    
por 06.08.2017 / 10:29
3

Você também pode

mysqldump -someparams dump.sql && gzip dump.sql || echo "Backup failed"  

Ou

mysqldump -someparams dump.sql  
[[ $? == 0 ]] && gzip dump.sql || echo "Backup failed "
    
por 06.08.2017 / 17:07
2

Um pipe executa os dois lados em paralelo. A maneira como você está tentando fazer isso é conceitualmente impossível: você não pode testar o status do comando mysqldump até que ele seja concluído se você fizer esse teste em paralelo com a execução de mysqldump . Você precisa executar mysqldump , esperar que ele termine e então decidir se deseja executar gzip .

Como mysqldump precisa terminar a execução, sua saída precisa ir para algum lugar. Provavelmente você espera que a saída seja grande, já que você está comprimindo. Portanto, a opção sensata é comprimi-lo. Então, comprima a saída incondicionalmente.

mysqldump -u username -ppassword dbname | gzip > test.gz

Observe que usei | , não |& . Usar |& aqui não faz sentido: se houver alguma mensagem de erro, eles acabarão misturados com o dump e seria impossível restaurar o dump.

O problema que ainda precisa ser resolvido é detectar se mysqldump foi bem-sucedido. Supondo que este seja um script bash ou ksh (ou seja, ele começa com #!/bin/bash ou #!/bin/ksh ou algo semelhante, não com #!/bin/sh ), defina o pipefail , para que o pipeline falhe se alguma parte falhar. (Por padrão, o status de um pipeline é o status de seu comando mais à direita e o status dos outros comandos é ignorado.)

#!/bin/bash
set -o pipefail -o errexit
tmp="mydump.tmp.$$.gz"
trap 'rm -f "$tmp"' ERR INT TERM HUP
mysqldump … | gzip >"$tmp"
mv "$tmp" mydump.gz

Definir a opção errexit garante que, se o pipeline falhar, o script saia nesse ponto (com o mesmo status de erro do pipeline). Assim, um arquivo chamado mydump.gz é criado apenas se o dump foi bem-sucedido. O comando trap configura uma interceptação para que, se o script falhar ou for eliminado por um dos sinais listados, o arquivo temporário seja excluído.

    
por 10.08.2017 / 01:50
1

Você também pode usar a tabela de build-in bash $ PIPESTATUS [x] para interceptar erros.

por exemplo:

$ cmd1 | cmd2 | cmd3 | ..
  • o status de cmd1 estará na variável $ PIPESTATUS [0]
  • o status de cmd2 estará em $ PIPESTATUS [1]

e assim por diante.

Então você veria qual comando falhou

    
por 21.06.2018 / 10:14
0

Se você quiser evitar o uso de um arquivo temporário, outra solução é excluir o arquivo resultante do erro:

( mysqldump ... || rm -f test.gz ) | gzip > test.gz

Ou, se você quiser ter um sinalizador explícito, algo assim:

rm -f test.ok
( mysqldump ... && touch test.ok ) | gzip > test.gz
if [[ $? -eq 0 && -r test.ok ]]; then
    echo it worked
else
    echo something went wrong
fi
    
por 21.06.2018 / 10:27