Linux・その他 6 min read

tarの終了コード ― file changed as we read itで1になるときのエラー判定

GNU tar は、アーカイブ中に対象のファイルが書き換わると file changed as we read it を出して終了コード 1 で終わります。アーカイブ自体はできていますが、$? != 0 で異常と判定すると、ログの圧縮などのジョブが止まります。この記事の出力は GNU tar 1.35(Ubuntu 26.04)で採りました。

まず見る(結論)

終了コード 意味 実際に出た場面
0 正常 —
1 一部のファイルが読み込み中に変わった・消えた file changed as we read it
2 致命的なエラー 対象が無い、読めない、書き込み先が無い、アーカイブが壊れている
tar -czf "$ARCHIVE" "$DIR"
rc=$?
if [ $rc -eq 0 ]; then
    echo "OK"
elif [ $rc -eq 1 ]; then
    echo "WARN: ファイルが途中で変わった"
else
    echo "ERROR (rc=$rc)"; exit $rc
fi

1 を正常扱いにするかどうかは、変わったファイルの中身が必要かで決めます。書き込み中のログを含めて固めるなら、1 は毎回起こりうる結果です。

読み込み中にファイルが変わる・消える

20MB のファイル3つを固めている途中で、別のプロセスから1つに追記しました。

$ tar -czf chg.tar.gz dir
tar: dir/f3: file changed as we read it
$ echo $?
1
$ tar -tzf chg.tar.gz
dir/
dir/f3
dir/f2
dir/f1

アーカイブは作られ、3つとも入っていました。

読み込み中にファイルを消した場合も 1 でした。消したファイルとディレクトリの両方について、file changed as we read it が出ました。

–warning=no-file-changed はメッセージだけを消す

$ tar --warning=no-file-changed -czf nw.tar.gz dir
$ echo $?
1

終了コードで判定しているスクリプトの対策にはなりません。判定は上のように 1 を分けて書きます。

終了コード 2 になる場面

場面 メッセージ
指定したファイルが無い Cannot stat: No such file or directory と Exiting with failure status due to previous errors
読めないファイルがある Cannot open: Permission denied
書き込み先のディレクトリが無い tar (child): ...: Cannot open: No such file or directory
展開するアーカイブが無い tar (child): nosuch.tar.gz: Cannot open: No such file or directory
途中で切れたアーカイブを読む gzip: stdin: unexpected end of file / Unexpected EOF in archive

指定したファイルが無いときも、ほかのファイルは固められていました(tar -czf missing.tar.gz dir nosuchfile は 2 で終わり、dir の中身は入っている)。終了コード 2 のときにできたファイルを正しいアーカイブとして扱わないよう、判定の後で消すか別名にします。

パイプでつなぐと失敗が見えない

$ tar -cf - dir nosuchfile | gzip > pipe.tar.gz
tar: nosuchfile: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
$ echo $? ${PIPESTATUS[*]}
0 2 0

bash でパイプの終了コードとして返るのは最後のコマンド(gzip)の 0 です。set -o pipefail を付けると、パイプ全体の終了コードが 2 になりました。set -e を付けていても、pipefail が無ければスクリプトは止まりません。

set -o pipefail
tar -cf - "$DIR" | gzip > "$ARCHIVE"
rc=$?

関連: psqlでSQLファイルを実行する ― エラーで止めるON_ERROR_STOPと終了コード

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA