ぽよメモ

レガシーシステム考古学専攻

rsyncでファイルを同期する

botを作るにあたり、だいたいはThinkPadに入れたUbuntuで開発を行っていたのですが、結局動作させるのはRasPiなわけで、動かしてみてうまく行かなかった時細かい修正はRasPiにsshして行っていました。
するとRasPi側と開発環境側で齟齬が発生するようになってしまい、ちょっとややこしいことに。

そこでスクリプトが入っているフォルダごと同期してしまおうということになりました。
Linuxにはこういうとき超便利なrsyncというコマンドが用意されています。最高。
RasPiへのアクセスにはsshを用いてログインしrsyncを使うので、まずはsshの設定をします(省略)
-eを使うなど古い書き方になってしまいますがこれが普通です。

rsync -au -e "ssh -p 22 -i ~/.ssh/id_rsa" pi@192.168.10.50:/home/pi/bot ~/

-aは「元のパーミッションやグループなどを保持したまま同期(-rlptgoDと同義)」、-uは「追加されたファイルだけをコピー」、-eは「リモートシェルの指定(最近はsshがデフォらしいので指定しないで良い?)」です。
しかしシェルスクリプト内での rsync に ssh 鍵を指定するに書いてあるように、シェルスクリプト内では”ssh (以下略)”の部分は読み取ってもらえません。
つまりcronで定期的に回すなどの実装にはこのままでは不適だということです。
なので.bashrcにRSYNC_RSHという環境変数を設定します。

RSYNC_RSH="ssh -p 22 -i $HOME/.ssh/id_rsa"

あとはsource ~/.bashrcして、普通にrsyncします。

rsync -au pi@192.168.10.50:/home/pi/bot ~/

また、ssh公開鍵暗号を使う今回のような場合、cronを使って定期的に回したければ公開鍵と秘密鍵を作る際にパスをかけないようにしておく必要があります。
あとはこれを適当なファイルに書いて「〜〜.sh」といった感じで書き、適当にcronに投げればオッケーです。
今回はリモートフォルダからローカルに保存するように書きましたが逆も可能です。また、リモート↔ローカルだけでなく、ローカル↔ローカルやリモート↔リモートも可能です。
このとき注意するのはソースとなるディレクトリのパスの最後に/を入れるかどうかです。

#ディレクトリごと同期
rsync -au /path/to/remote /path/to/local
#ディレクトリ以下の内容のみ同期
rsync -au /path/to/remote/ /path/to/local

つまり最後に「/」をつけなければリモートにある「A」というディレクトリをローカルにある「B」を指定してrsyncしたとき、Bの中にAというディレクトリが出来ます。「/」をつけると、「A」というディレクトリの中身が「B」に展開されます。
これにさえ注意を払っておけば問題ないと思います。
その他のオプションについてはググればすぐに出てくると思いますので省略。場合によって--excludeや--deleteを上手く使えばかなり高度なファイル同期/バックアップとして使えると思います。