2

mysqldumpコマンドが成功したかどうかをテストする bash 関数を作成したいと考えています。これまでに試したことは、次のように、ダンプ ファイルのサイズがゼロかどうかをテストすることです。

l_mysqldump= # set your custom mysqldump path here, like /Applications/MAMP/Library/bin/mysqldump

${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name > latest-dump.mssql

if [[ -s latest-dump.mssql ]]
then
    echo "Success: not zero size."
else
    echo "Error: zero size."
    exit 1
fi

mysqldumpデフォルトのmysqlサーバーがダウンしているときにmysqldumpコマンドを実行すると次のエラーが発生するため、コマンドの終了ステータスをテストするのではなく、この方法でテストすることにしました。

mysqldump: エラーが発生しました: 2002: 接続しようとすると、ソケット '/tmp/mysql.sock' (2) を介してローカル MySQL サーバーに接続できません

このエラーが発生しても、0 バイトの .mssql ファイルが生成されます。また、終了ステータスは何があっても0です。mysqldumpダンプが失敗した場合、スクリプトは終了する必要があり、別のバイナリを指定するか、サーバーをアクティブにする必要があることをユーザーに伝える必要があります。

上記のコードは正常に動作します。mysqldumpただし、圧縮されていないダンプ ファイルを生成したくありません。次のように、bzipしたい:

${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name | bzip2 -c > latest-dump.mssql.bz2

問題は、[-s]生成される .bz2 ファイルが 14 バイトであるため、これが私の bash テストを中断することです。したがって、圧縮されていない .mssql ファイルのサイズがゼロであっても、同等のアーカイブのサイズはゼロではありません。

それで、これを解決する最善の方法は何ですか?圧縮されていないダンプ ファイルを生成し、テストしてから bzip するだけで済みます。ただし、これを行うにはもっとスマートな方法があると思います。

4

2 に答える 2

3

本当の問題は、パイプを使用すると、デフォルトの戻りステータスが最後のコマンドの終了コード( bzip2) になることです。引用するにはman bash

   The return status of a pipeline is the exit status of the last command,
   unless  the  pipefail  option  is enabled.  If pipefail is enabled, the
   pipeline's return status is the value of the last  (rightmost)  command
   to  exit  with a non-zero status, or zero if all commands exit success‐
   fully.

パイプのコマンドが失敗した場合に失敗を報告したい場合は、オプションを設定する必要がありますpipefail。と仮定するとbash、ここに例があります(ローカルホストで実行されているmysqlサーバーがありません):

sylvain@daal:~$ set -o pipefail
sylvain@daal:~$ if mysqldump -u root -p db | bzip2 -c > latest-dump.mssql.bz2; then echo ok; else echo non ok; fi
Enter password: 
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) when trying to connect
non ok

特定のケースでは、次のように記述します。

set -o pipefail

if ${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name | bzip2 -c > latest-dump.mssql.bz2
    then
      ...
    fi


ところで:「mysqldumpコマンドでこのエラーが発生します [..]このエラーが発生して、0 バイトの .mssql ファイルが生成されます。」

より正確には、 shell redirectionを使用するため、ファイルを作成するのはホスト シェルです。コマンドを実行 しようとする前に。

于 2013-08-12T10:40:47.647 に答える
1

mysql コマンドで一般的なエラー文字列をチェックするのはどうですか? stdout と stderr をリダイレクトする際に、コマンドをプロセス置換内に配置できます。

IFS= read -rd '' OUTPUT < <(${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name 2>&1 > >(bzip2 -c > latest-dump.mssql.bz2))

次に、grep、case、[[ == ]]、または [[ =~ ]] などを使用して通常どおり出力を確認します。

if echo "$OUTPUT" | grep "error" >/dev/null; then
    (failure)
else
    (success)
fi

case "$OUTPUT" in
*"error"*|*another_error_pattern*|...)
  (failure)
  ;;
*)
  (success)
  ;;
esac

おそらく別の方法は、出力ファイルのサイズがデフォルトのサイズ 14 より大きいかどうかを確認することですが、それでは確実性が低いと思います。

${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name > latest-dump.mssql

if IFS= read SIZE < <(stat -c "%s" latest-dump.mssql) && [[ SIZE -gt 14 ]]; then
   (success)
else
   (fail)
fi

また、予期しない拡張から保護するために、変数を適切に引用することもお勧めします。

"${l_mysqldump:-mysqldump}" "-u$l_db_user" "-p$l_db_pass" -h "$l_db_host" "$l_db_name" > latest-dump.mssql

更新: あなたの更新を見て、エラー出力パターンの理想的な文字列は "mysqldump: Got error:" または単に "Got error:" になると思います。例えば

IFS= read -rd '' OUTPUT < <("${l_mysqldump:-mysqldump}" -u"$l_db_user" -p"$l_db_pass" -h "$l_db_host" "$l_db_name" 2>&1 > >(bzip2 -c > latest-dump.mssql.bz2))

if echo "$OUTPUT" | grep "Got error:" >/dev/null; then
...

if grep "Got error:" >/dev/null <<< "$OUTPUT"; then
...

case "$OUTPUT" in
*"Got error:"*)
...

if [[ $OUTPUT == *"Got error:"* ]]; then
...
于 2013-08-12T10:54:14.560 に答える