ひゃまだのblog

ひゃまだ(id:hymd3a)の趣味のブログ

unisonでファイル、ディレクトリの同期

(2007-12-30 初稿 - 2021-05-10 転記・追記)

(2021-05-10 追記)

このページももうかなり古い情報なので、転記はやめようと思ったが、Dropboxの台数制限のおかげで、Linux PCとRaspberry Pi等の同期に用いる機会が多くなったので、転記することにした。

unisonとは

複数のパソコンを利用していると、ディレクトリやファイルの同期が面倒である。
これまで筆者は rsync を利用して同期をはかってきたが、双方向に同期する時には、やや面倒であった。そこで、unisonというコマンドを用いることにした。

unisonは異なるディレクトリやファイルを、どちらのファイルを残すのか選択しながら同期することができるコマンド。後述するが、unison自身に判断させ、バッチ化することも可能である。

unisonのインストール

debianubuntu 環境では、以下のように行う。

sudo aptitude install unison

他のディストリビューションでも、標準のコマンドとして準備されていることが多いだろう。

基本的な使い方

異なる2つのディレクトリを同期するためには、以下のように入力する。

unison dir_a dir_b

上記の場合、基本的な動作は以下のようになります。

  • dir_aのみにあるファイルは、dir_bにコピーされる。
  • dir_bのみにあるファイルは、dir_aにコピーされる。
  • 両方のディレクトリにfile_cがある場合は、どちらをコピーするかユーザに聞いてくる。

この他、unisonの動作をわかりやすく説明するオプションを以下の方法で見ることができる。

unison -doc tutorial

 異なるパソコンでファイルを同期する

実際には、サーバとクライアントでファイルを同期させる目的で利用することが多い。
unisonはLinuxWindows間の同期もできるようだが、筆者は主にLinuxLinuxマシンでsshを利用して、サーバとクライアントのファイルの同期に用いているので、ここでの説明は、Linux同士のファイル同期に限って行う。
また、本ページの説明では手元のパソコンをローカル、サーバ等リモート側のパソコンをリモートと呼ぶことにする。

まず、前提条件として以下のことが可能になっていなければならない。

  • ローカル、リモートのパソコンともに、同じバージョンのunisonがインストールされていること
  • ローカルとリモート間では、sshによる通信が可能であること

ローカルにあるdataディレクトリとリモートのdataディレクトリの同期の例を以下に示す。
なお、ここでは、リモートのパソコンのIPアドレスを、192.168.0.100と仮定する。
もちろん、パソコンの名前からIPアドレスが引ける場合は、名前でも可能。

unison data ssh://192.168.0.100/data
unison data ssh://remote-hostname/data

注意点としては、上記の場合は、ディレクトリの相対的な表記だが絶対的な表記の場合は、以下のようになる。
マシン名との区切りが「//」になっている点に注意

unison /home/hoge/data ssh://remote-hostname//home/hoge/data

実際に行ってみると、emacsvimのバックアップファイルまでも、コピーされてしまう。
このような場合は、「-ignore」オプションを使います。

unison data ssh://remote-hostname/data -ignore Name *~ -ignore Name *.bak

しかし、複数のディレクトリを同期したい場合は、ディレクトリごとにunisonを起動しなくてはならず、大変不便だ。

この様な場合にも対処できるように、unisonはprfファイルを作成することができる。
prfファイルは、~/.unison内に作成する。

筆者の場合は、同期したいリモートパソコンの名前のファイルを作成している。
以下に例を示すので、参考に。

cat ~/.unison/remote-host.prf

# Unison preferences file
# option
# times ファイルの時刻をコピー元のままに保存する
times = true
# prefer newer 新しい方を優先する
prefer = newer

# ローカルとリモートの指定
# 実際に同期したいディレクトリはpathで指定するため、全体を指定
root = /home/hoge/
root = ssh://remote-host/
# 実際に同期したいディレクトリを指定(複数可)
path = dir_a
path = dir_b
path = dir_c
#無視して欲しいファイルを指定
ignore = Name *~
ignore = Name .*~
ignore = Name .bak

上記prfファイルを準備した場合の使い方は以下のようになる。

unison remote-host

とても簡単に複数ディレクトリの同期が可能となった。
また、毎回の確認が面倒な時は、以下のように -batch オプションをつけると良い。

unison remote-host -batch

 Tips(2013-03-03追記)

上記のとおり、prfファイルを準備すると大変便利だが、以下に便利な機能を紹介する。

fastcheck

prfファイルに以下を追記すると更新のチェックが高速になる。
特に、Windowsとの同期で威力を発揮するようである。

fastcheck = true

 ただし、時々は、falseにして、実行した方が良いようだ。

follow

unisonにはシンボリック・リンクを同期するコマンドがある。

prfファイルに、同期したいシンボリック・リンクを以下のように記述する。

follow = Path ディレクトリ名 または ファイル名

シンボリック・リンクを活用すると、同期するファイルを減らし、同期の高速化につながる。(^^)

複数のPCで簡単に同期する(2008-12-13 追記)

上記のprfファイルを作成することで、複数のディレクトリを同期することは、簡単にできるようになった。
しかし、複数のPCでそれぞれ別のprfファイルを用いて同期する場合には、各PC毎にコマンドを実行する必要があるためにやや面倒である。

そこで、以下のようなシェル・スクリプトを作成すると、各PCで同じコマンドでそれぞれのディレクトリの同期が可能となる(CUI万歳!!(笑))。

ちなみに、筆者は、以下のコマンドを douki というファイル名にしている。

#!/bin/bash
# dirs and files syncronize
# ver 0.01 2008-12-10

hname=`hostname`

if [ $hname = "hostA" ]; then
    echo "hostA syncronining..."
    /usr/bin/unison remote-host1 -batch
elif [ $hname = "hostB" ]; then
    echo "hostB syncronizeing..."
    /usr/bin/unison remote-host1 -batch
    /usr/bin/unison remote-host2 -batch
else
    echo "other machine"
fi
echo done

上記コマンドでは、hostAとhostBのマシンの同期を行う。
環境に合わせて、同期するPCの増減やPCの名前の変更すること。
PCの名前の変更後に以下のコマンドで実行権を付与する。

chmod +x douki

また、筆者の試したところ、NASとのファイル同期において、NASのファイルのmodeの設定がうまくいかず、unison または rsync で同期させない方が良いようだ。
このため、筆者はNASの同期は、以下のようなshellスクリプトを書いて cp コマンドで行っている。
unisonやrsyncに比べると低速だが、更新するファイルはそれほど多くないので我慢している。^^;

#!/bin/bash
# NAS backup
# ver 0.01 2008-12-10

# backupするディレクトリを一覧に
dirs=(bin mydoc gazo howm)

echo "NAS backup..."
for i in "${dirs[@]}"; do
    echo "$i backup..."
    /bin/cp -ruv --preserve=timestamp $i ~/mnt/hoge
done
echo "done"

上記設定は、NASを~/mnt/hoge にマウントしている場合。
NASのマウントに関しては、debianのページを参考に。

versionの固定

unisonは、同期するマシン間で同じバージョンである必要がある。
筆者の場合、debianubuntuで同期しているが、ubuntuのunisonのversionが上がると同期できなくなってしまう。

そのような場合には、unisonのversionをdebianに合わせて固定する必要がある。
aptまたはaptitudeでversionを固定する方法は、いくつかあるようだが、スレッドテンプレにあるpinを利用する方法を紹介する。

/etc/apt/preferences.d/unison を新たに作成し、以下の記述をする。

Package: unison
Pin: version 2.32.52-1
Pin-Priority: 1001

 これで、いつも通り、aptやaptitudeでupgradeしても、versionが固定されて、同期できなくなることはない。

ただし、debianのversionが上がった時には、再度、preferences.d/unisonを編集する必要があるので注意。

ホストのシステムを変更した時には(2008-08-16 追記)

unisonで同期しているホストのOSを変更後に、初めてunisonで同期をしようとすると、以下のようなメッセージが表示され、同期ができなくなります。

Fatal error: Warning: inconsistent state.
The archive file is missing on some hosts.
For safety, the remaining copies should be deleted.
Archive arXXXXXXXXXXXXX on host hoge should be DELETED
Archive arXXXXXXXXXXXXX on host fuga is MISSING
Please delete archive files as appropriate and try again.

 上記の場合は、ホスト fugaのシステムを入れ替えたため、同期できなくなってしまった例。

対処方法は、記載がある通り、ホスト hogeで以下を実行する。

 

rm .unison/arXXXXXXXXXXXXX

 なお、XXXXXXXXXXXXXの部分は、ホスト毎に固有の値になる。どのファイルがどのホストのものかは、ファイルの先頭部分に記載されているので、以下で確認できる。

head -3 .unison/arXXXXXXXXXXXXX

削除後は、いつも通りに unison で同期できるようになる。

今後の課題

sshで通信するパソコン同士はうまく同期できるが、samba mountをしているNASとの同期には失敗する。なにか良い方法がないかと検討中。

以上、筆者もまだ勉強中なので、何かわかったら追記する予定。

関連ページ