rsync の終了コード一覧と意味

cron で回している rsync が 0 以外の終了コードを返してきたとき、その番号が何を意味するのかを調べるためのリファレンスです。まず一覧を載せて、そのあとで実際によく遭遇するコードの読み方とスクリプトでの扱い方を説明します。

終了コードは直後に echo $? で確認できます。

$ rsync -a /path/to/src/ /path/to/dst/
$ echo $?
0

終了コード一覧(rsync 3.4.4 の man ページより)

コード意味(man の記述)ざっくり言うと
0Success成功
1Syntax or usage errorオプションの書き間違い
2Protocol incompatibility両端の rsync が噛み合わない
3Errors selecting input/output files, dirs入出力のファイル・ディレクトリを開けない
4Requested action not supported相手側がその機能に未対応(32/64bit 差や古い rsync など)
5Error starting client-server protocolクライアント・サーバ間の開始に失敗
6Daemon unable to append to log-fileデーモンがログに書けない
10Error in socket I/Oソケット入出力エラー(接続断など)
11Error in file I/Oファイル入出力エラー(ディスクフルなど)
12Error in rsync protocol data streamプロトコルストリームのエラー
13Errors with program diagnostics診断出力まわりのエラー
14Error in IPC codeプロセス間通信のエラー
20Received SIGUSR1 or SIGINTシグナルで中断された(Ctrl+C など)
21Some error returned by waitpid()子プロセスの待ち合わせでエラー
22Error allocating core memory buffersメモリ確保に失敗
23Partial transfer due to errorエラーで一部だけ転送された
24Partial transfer due to vanished source files転送中にソースのファイルが消えた
25The –max-delete limit stopped deletions–max-delete の上限で削除が止まった
30Timeout in data send/receiveデータ送受信のタイムアウト(–timeout)
35Timeout waiting for daemon connectionデーモン接続待ちのタイムアウト(–contimeout)

このほか、リモート転送で ssh 自体が失敗すると、rsync は「unexplained error (code 255)」として ssh の終了コード 255 をそのまま返します。255 が出たら rsync ではなく ssh 接続(ホスト名、鍵、ポート)を疑ってください。

いちばんよく見る 23 と 24 の違い

実運用で目にする終了コードの大半は 23 か 24 です。どちらも「一部のファイルが転送できなかった」ですが、原因がはっきり区別されています。

24 は「転送中にソースのファイルが消えた」専用のコードです。一時ファイルやキャッシュを含むディレクトリを、システムを動かしたまま同期すればごく普通に出ます。詳しい原因と対処は rsync の「file has vanished」警告(code 24)の意味と対処 にまとめています。

23 は「消えた以外の何らかのエラーで転送しきれなかった」です。stderr に出ている個別のエラーメッセージ(rsync error: の前の行)を見て原因を特定します。よくあるのは次のパターンです。

  • Permission denied: 読み取り権限がない(root 以外で他ユーザーのファイルを含むディレクトリを同期した、など)
  • No space left on device: 転送先のディスクフル
  • cannot convert filename: --iconv 使用時にファイル名の文字コード変換に失敗

最後の変換失敗は手元(rsync 3.4.4)で再現するとこうなります。

$ rsync -a --iconv=utf-8,ascii src/ dst/
[Receiver] cannot convert filename: 日本語ファイル.txt (Illegal byte sequence)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1356) [sender=3.4.4]
$ echo $?
23

ファイル名の文字コードがらみの対処は rsync でファイル名が文字化けするときの対処 を参照してください。

スクリプトで特定のコードだけ許容する

バックアップスクリプトでは「24 は正常扱いにしたいが、23 などの本当のエラーは検知したい」という要件が定番です。素直に書くとこうなります。

#!/bin/sh
rsync -a /path/to/src/ /path/to/dst/
rc=$?
case "$rc" in
    0|24) exit 0 ;;   # 成功、または転送中にファイルが消えただけ
    *)    exit "$rc" ;;
esac

set -e を使っているスクリプトでは、rsync が 0 以外を返した瞬間にスクリプトごと落ちてしまうので、いったん || で受け止めます。

#!/bin/bash
set -e
rc=0
rsync -a /path/to/src/ /path/to/dst/ || rc=$?
if [ "$rc" -ne 0 ] && [ "$rc" -ne 24 ]; then
    exit "$rc"
fi

メッセージ出力ごと抑えたい(cron のエラーメールを止めたい)場合は、rsync ソース同梱の公式ラッパー support/rsync-no-vanished が使えます。詳しくは rsync の「file has vanished」警告(code 24)の意味と対処 で説明しています。

おまけ:パイプ越しの終了コードに注意

rsync の出力を tee などにパイプすると、$? はパイプの最後のコマンドの終了コードになってしまい、rsync の失敗を見逃します。bash なら PIPESTATUS を使うか、set -o pipefail を付けてください。

rsync -a src/ dst/ | tee rsync.log
rc=${PIPESTATUS[0]}   # tee ではなく rsync の終了コード

さいごに

終了コードの意味は man rsync の EXIT VALUES 節が一次情報です(この記事の一覧は rsync 3.4.4 のものです)。0 と 24 だけを成功扱いにして、23 やそれ以外はメッセージを見て個別に対処する、というのが運用の基本形になります。

あわせて読みたい: