FreeBSD で OneDrive

# やりたいこと

FreeBSD でも OneDrive を使いたい。
2022/12/04 現在で ports&packages に入っているその手のソフトウェアとしては、[rclone](https://rclone.org/)、[OneDrive Free Client](https://github.com/abraunegg/onedrive) がある。ただし、OneDrive Free Client はコンパイラ（ldc）の問題で amd64 アーキテクチャでしか使えない。

# rclone

様々なクラウドに対応しているクライアント。洋物のクラウドだったらこれでだいたい使える。クラウドと同期して使う方法としては、ローカルにコピーを持ちオフライン時も使える bisync と、FUSE を使ってファイルシステムのようにアクセスできる mount がある。
bisync は最近のバージョンで追加されたコマンドで、従来だと sync を2方向に使ってなんとかしていたが、そうするとタイミングによってファイルが古い内容で上書きされてしまう場合があってあまりよくなかった。そういうわけで bisync ができて良かったのだが、rclone version 1.60.0 だと bisync はまだ experimental という扱いのようである。

## インストール

root で

```terminal
# pkg install rclone
```

でインストールされる。

## 設定

```terminal
$ rclone config
```

でクラウドに接続する remote の設定が開始される。ダイアログは英語だが、指示に従って入力してゆくのはそう難しくないので詳しいことは割愛する。コマンドだけでわからない場合は[rclone の OneDrive の説明](https://rclone.org/onedrive/)を参考にしてほしい。
ここでは、```ondrive:``` という名で remote を作成していることとし、同期先のディレクトリは ```${HOME}/OneDrive``` とする。このディレクトリはあらかじめ作成しておく必要がある。

## bisync

bisync で動かすには、まず bisync を --resync オプションをつけて動かす必要がある。

```terminal
$ rclone bisync --resync onedrive: ~/OneDrive --exclude '*.swp' --exclude '*~' --exclude '.~lock.*'
```

上記```--exclude```は、vim のスワップファイルとバックアップファイル、LibreOffice のロックファイルは同期しないようにしたものである。各自の環境に応じて調整して欲しい。
2回目以降は ```--resync``` オプションなしで実行すればよく、その都度同期される。

```terminal
$ rclone bisync onedrive: ~/OneDrive --exclude '*.swp' --exclude '*~' --exclude '.~lock.*'
```

これを都度手で実行するのは面倒なので、```crontab -e``` で cron に次のように仕込むと 3分おきに rclone が実行されて同期される。pgrep の部分は、既に ```onedrive:``` にアクセスする rclone プロセスが走っていた場合に実行しないためのものである。

```sh
*/3 * * * * pgrep -f 'rclone .*onedrive:' 2>&1 > /dev/null || rclone bisync onedrive: ~/OneDrive --exclude '*.swp' --exclude '*~' --exclude '.~lock.*' --log-file ${HOME}/.config/rclone/onedrive.log 2>&1 > /dev/null
```

## mount

bisync を使うと全部もしくは一部のディレクトリをまるごとローカルにコピーする必要があるが、アクセスするファイルしかコピーして来たくないという場合もあるだろう。その場合は、オンラインでしか使えないが ```rclone mount``` で FUSE マウントして使う方法がある。
root で使うことはあまり考えられないので、まずは一般ユーザーでも mount が実行できるようにする必要がある。

```terminal
# sysctl vfs.usermount=1
```

継続して使う場合は /etc/sysctl.conf に以下のように書いておくとよい。

```
vfs.usermount=1
```

そうして空の ${HOME}/OneDrive ディレクトリを作成し、次のようにして fusefs を mount する。

```terminal
$ rclone mount onedrive: ~/OneDrive
```

これで ${HOME}/OneDrive 以下にリモートの内容がマウントされ、ファイルにアクセスすることができる。
当方は経験がないが、常時接続環境であればログイン時に ```rclone mount``` して、ログアウト時に ```pkill rclone``` するようにすればよいのではないか。

# OneDrive Free Client

onedrive は ```--synchronize``` モードでは rclone の bisync と同じように実行する都度同期を取るが、```--monitor``` モードで実行すると、実行中に inotify を使ってローカルの変更を検知して同期をかけてくれる。リモートの変更検知は一定時間ごとの polling ではあるけれど、そこはそういうものだろう。

## インストール

root で

```terminal
# pkg install onedrive
```

とすればインストールされる。

## 設定

デフォルトの設定でよければ、onedrive を引数なしで起動する。
初回は下記のように URI が出てくるので、それをブラウザに貼り付けて開く。OneDrive にログインしてアクセス許可を設定したら、リダイレクトされたページの URI をコンソールに貼り付ける。
これで、設定が ~/.config/onedrive 以下に置かれ、同期するディレクトリが ~/OneDrive に設定された。

```terminal
$ onedrive
Configuring Global Azure AD Endpoints
Authorize this app visiting:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=...

Enter the response uri: 
```

まだローカルに何もないので、次に

```terminal
$ onedrive --synchronize --download-only
```

でローカルに持ってくるとよい。その後は、

```terminal
$ onedrive --monitor &
```

でデーモン化して動かすと同期がとられる。

## 自動化

Linux だと systemd がユーザーデーモンとして動かしてくれるが、FreeBSD にはその仕組みがないので、cron で細工する。個人の crontab で

```sh
@every_minute    pgrep onedrive 2>&1 > /dev/null || /usr/local/bin/onedrive --monitor
```
と設定すれば、毎分、自分の権限で動いている onedrive があるかチェックし、なければ monitor モードで起動するようになる。バージョンアップした時などは

```terminal
$ pkill onedrive
```

とやれば一分後には新しいバージョンが起動してくる。
止めたい場合は、まずは crontab のエントリをコメントアウトしてから pkill すればよい。