Dropbox が Raspberry Pi で動かないので、その代替えに作ったネットワーク双方向ファイル同期ツール。
特徴は以下の通り。
同期元と相手の両方に 実行ファイルのインストール と 同期ディレクトリの設定 の作業が必要。
下記で実行ファイルが ~/bin/ へインストールされる。
$ curl -O http://kobayasy.com/psync/psync-2.34.tar.gz $ tar xzf psync-2.34.tar.gz $ cd psync-2.34 $ ./configure --prefix=$HOME $ make install
下記は ~/pSync/Private/ と ~/pSync/Work/ を同期ディレクトリに設定して、それぞれに識別名 private と work を付ける設定例。
$ install -m700 -d ~/pSync/Private $ install -m700 -d ~/pSync/Work $ cat <<EOF > ~/.psync.conf #ID Directory private pSync/Private work pSync/Work EOF $ chmod 600 ~/.psync.conf
下記を実行。 下記は同期相手が guest@example.com の場合の例なので実際の相手に合わせて置き換える事。
$ psync --help pSync 2.34 (protocol pSp1) Usage: psync [--sync] [-v|-q] [USER@]HOST[#PORT] psync --put [-v|-q] [USER@]HOST[#PORT] psync --get [-v|-q] [USER@]HOST[#PORT] psync --help USER@HOST#PORT HOST hostname USER username (default: current login user) PORT SSH port (default: 23) runmode -s, --sync synchronous mode (default) -p, --put oneway put mode -g, --get oneway get mode options -v, --verbose verbose mode (default) -q, --quiet quiet mode subcommand --help show this help $ ssh guest@example.com psync --help pSync 2.34 (protocol pSp1) (中略) $
下記を実行するだけ。 下記は同期相手が guest@example.com の場合の例なので実際の相手に合わせて置き換える事。 これで同期ディレクトリ内のファイルが同期相手と同期する。
$ psync guest@example.com private work $
$ ps ax | grep psync裏で pSync が動作していないのにこのメッセージが出る場合は前回の同期処理が Ctrl-| 入力や kill -9 pid コマンドで強制終了された等の原因で、同期ディレクトリがロックされた状態のまま残ってしまっている可能性が考えられる。 その場合、下記コマンドで強制的にロックを解除する事が出来る。
$ rm -r 同期ディレクトリ/.psync/lock
$ find 同期ディレクトリ ! -type f ! -type d ! -type l
$ find 同期ディレクトリ -type f ! -readable -o -type d ! ( -readable -writable -executable )
本ツールの正式名称は頭1文字目が小文字で2文字目が大文字、それ以降が小文字表記の pSync で、オリジナル配布元は http://kobayasy.com/psync/
この文章を含め pSync の配布ファイルは下記ライセンスの元、使用と再配布を許可する。
Copyright (C) 2018-2023 by Yuichi Kobayashi <kobayasy@kobayasy.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
その他、作者のメモとか、どうでも良い事とか、実は大事な事とか... いろいろ思い付いたらここに追記。
これ以降はいい加減にしかメンテナンスされていおらず、旧バージョンの情報も残っており最新バージョンとは合わない部分もあるので注意。
$ find 同期ディレクトリ ! -type f ! -type d ! -type l
$ find 同期ディレクトリ -type f ! -readable -o -type d ! ( -readable -writable -executable )
$ sshpass -p password psync guest@example.com
warning: comparison of constant -1 with expression of type '符号無し整数型' is always false warning: shift count >= width of type warning: adding 'unsigned int' to a string does not append to the string
双方向ファイル同期アルゴリズムは、psync.c と psync_utils.h で実装されており、psync.h がそのヘッダファイル。
#include "psync.h" PSYNC *psync_new(const char *dirname, time_t expire, volatile sig_atomic_t *stop)
#include "psync.h" void psync_free(PSYNC *psync)
#include "psync.h" int run(bool master, PSYNC *psync)
下記はカレントディレクトリからの相対パスディレクトリ Test1/ と Test2/ を同期するコーディング例。
/* dirsync.c * Example code: Synchronize local directory "./Test1/" and "./Test2/" */ #include <limits.h> #include <stdio.h> #include <time.h> #include <pthread.h> #include <unistd.h> #include "psync.h" #define EXPIRE_DEFAULT 400 /* [days] */ typedef struct { int status; PSYNC *psync; bool master; pthread_t tid; } RUN_PARAM; static void *run_thread(void *data) { RUN_PARAM *param = data; param->status = run(param->master, param->psync); return NULL; } static void dirsync(const char *dirname1, const char *dirname2, time_t expire) { int fd[2][2] = { {-1, -1}, {-1, -1} }; RUN_PARAM param[2] = { {.status = INT_MIN, .psync = NULL}, {.status = INT_MIN, .psync = NULL} }; unsigned int n1, n2; for (n1 = 0; n1 < 2; ++n1) { pipe(fd[n1]); for (n2 = 0; n2 < 2; ++n2) if (fd[n1][n2] == -1) goto error; } param[0].psync = psync_new(dirname1, expire * (60*60*24), NULL); if (param[0].psync == NULL) goto error; param[1].psync = psync_new(dirname2, expire * (60*60*24), NULL); if (param[1].psync == NULL) goto error; param[0].psync->fdin = fd[0][0], param[0].psync->fdout = fd[1][1]; param[1].psync->fdin = fd[1][0], param[1].psync->fdout = fd[0][1]; param[0].master = true; param[1].master = false; if (pthread_create(¶m[0].tid, NULL, run_thread, ¶m[0]) != 0) goto error; if (pthread_create(¶m[1].tid, NULL, run_thread, ¶m[1]) != 0) goto error; if (pthread_join(param[0].tid, NULL) != 0) goto error; if (pthread_join(param[1].tid, NULL) != 0) goto error; error: for (n1 = 0; n1 < 2; ++n1) if (param[n1].psync != NULL) psync_free(param[n1].psync); for (n1 = 0; n1 < 2; ++n1) for (n2 = 0; n2 < 2; ++n2) if (fd[n1][n2] != -1) close(fd[n1][n2]); printf("status = %d, %d\n", param[0].status, param[1].status); } int main(int argc, char *argv[]) { dirsync("Test1", "Test2", EXPIRE_DEFAULT); return 0; }
これをビルドするための Makefile はこんな感じ。
# Makefile CFLAGS = -O2 dirsync : dirsync.o psync.o $(CC) -lpthread -o $@ $^ psync.o : psync.c psync_utils.h dirsync.o : dirsync.c psync.h %.o : %.c $(CC) $(CFLAGS) -c $< clean : $(RM) dirsync $(RM) dirsync.o psync.o
C言語用の手軽に使えるシリアライザが探しても見つからくてなくて自作した。 psync_utils.h で定義しているマクロの WRITE() と READ() がそれ。 扱えるのは整数の数値だけだけど 248bit の値まで対応しているので、全ての整数値型変数に対応できるはず。
READ() の data 型は WRITE() のそれと一致している必要は無いが、値が収まる型である事。 例えば WRITE() 側の型が intmax_t であっても、その値が 255 ならば READ() 側は uin8_t で受ける事が出来る。
WRITE(data, fd, status)
READ(data, fd, status)