live.com の OneDrive と Linux を同期した時のメモです。私が普段使っているLinux環境はホームディレクトリを暗号化していないので、そこと同期するのもなーということで暗号化されたディスクイメージを作ってそこと同期しています。今回は Lubuntu16.04(64bit) で動作確認を行いました。残念ながらOffice365 のOneDrive には対応していませんのでご注意を。
どうやって?
OneDrive との同期は python で書かれた onedrived-dev というLinuxクライアントが https://github.com/xybu/onedrived-dev で公開されているのでそれを使います。暗号化されたディスクイメージは cryptsetup を使って作成します。
onedrived-devのインストール
では早速インストールです。
まず python3 がインストールされていることを確認します。私の環境の場合はすでに3.5.2がインストールされていることが確認できました。もしpython3コマンドがなかったりバージョンが3.3より小さい場合はインストールの必要があるようですが、その必要はなさそうです。
$ python3 --version
Python 3.5.2
PIP をインストールします。PIPとsetuptoolsはパッケージからもインストールできるみたいですけど、そっちだとエラーになってしまったのでダウンロードしてインストールしています。他のところで影響がでないか心配ではありますが…。
$ wget -O- https://bootstrap.pypa.io/get-pip.py | sudo python3
$ sudo pip3 install -U pip setuptools
続けて必要となりそうなパッケージをインストールします。
$ sudo apt install build-essential python3-dev libssl-dev inotify-tools python3-dbus git
onedrived-dev のソースコードをゲットしてインストールします。
$ git clone https://github.com/xybu/onedrived-dev.git
$ cd onedrived-dev
$ python3 ./setup.py test
$ sudo pip3 install -e .
ngrok をインストールします。ngrok のことはよく知らないのですがonedrived-devの実行に必要なようです。ngrok は https://ngrok.com/ にアクセスしてダウンロード後unzip
コマンドで解凍します。解凍すると ngrok コマンドが作成されます。
$ unzip ngrok-stable-linux-amd64.zip
Archive: ngrok-stable-linux-amd64.zip
inflating: ngrok
先ほどonedrived-devディレクトリで作業していましたので、onedrived-devディレクトリにngrokが解凍されてしまいましたので、忘れないように場所はメモっときましょう。
これでインストールは完了です。
暗号化されたディスクイメージの作成
今回はOneDriveの容量と同じ5ギガの暗号化されたディスクイメージを作成し/media/onedriveにマウントしてみます。
まず暗号化に必要となる cryptsetup をインストールします。
$ sudo apt install cryptsetup
5ギガの空ファイルを作成します。
$ fallocate -l 5G onedrive.img
cryptsetupを使って暗号化されたパーティションを初期化します。途中で本当に良いか?と聞いてくるので大文字で「YES」と入力し、続けてパスワードを入力します。
$ cryptsetup -y luksFormat onedrive.img
WARNING!
========
This will overwrite data on onedrive.img irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:
先ほど作成したパーティションを開きます。開くときにパスワードを求められるので先ほど設定したパスワードを入力します。これで /dev/mapper/cryptroot_onedrive というパスで暗号化されたパーティションにアクセスできるようになります。
$ sudo cryptsetup luksOpen onedrive.img cryptroot_onedrive
Enter passphrase for onedrive.img:
フォーマットします。
$ sudo mkfs.ext4 -j /dev/mapper/cryptroot_onedrive
mke2fs 1.42.13 (17-May-2015)
Creating filesystem with 1310208 4k blocks and 327680 inodes
Filesystem UUID: d90fe66c-844e-4ea9-9dce-9d7458466d29
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
/media/onedrive ディレクトリを作成しそこにマウントします。念のためパーミッションを設定しておきます。
$ sudo mkdir /media/onedrive
$ sudo mount /dev/mapper/cryptroot_onedrive /media/onedrive
$ sudo chown -R $USER /media/onedrive
これでディスクイメージの作成とマウントは完了です。なみにアンマウントする場合は以下のようにします。
$ sudo umount /media/onedrive
$ sudo cryptsetup luksClose cryptroot_onedrive
onedrived-devの設定
onedrived-dev にアカウントを追加します。 アカウントを追加の追加はonedrived-pref account add
コマンドを実行します。実行すると https://login.live.com で始まるURLが表示されて Paste URL here: で待機状態になりますので、 https://login.live.com で始まるURLをコピーしてブラウザのURL欄にペーストしてページを開きます。
$ onedrived-pref account add
NOTE: To better manage your OneDrive accounts, onedrived needs permission to access your account info (e.g., email address to distinguish different accounts) and read/write your OneDrive files.
Paste this URL into your browser to sign in and authorize onedrived:
https://login.live.com/oauth20_authorize.srf?response_type=code&scope=wl.signin+wl.emails+wl.offline_access+onedrive.readwrite&client_id=00000000********&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf
The authentication web page will finish with a blank page whose URL starts with "https://login.live.com/oauth20_desktop.srf". Paste this URL after the prompt.
Paste URL here:
URL欄にペーストしてページを開くと live.com のログイン画面が表示されますので、自分のIDとパスワードでログインします。するとアクセス許可の画面になりますので「Yes」ボタンをクリックします。
「Yes」ボタンをクリックすると真っ白の画面になるため失敗したのではないかと途方に暮れそうになりますが大丈夫です。重要なのはURL欄に表示されているURLなので、URL欄の https://login.live.com で始まるURLをコピーします。
そして先ほどのコンソール画面に戻り貼り付けます。Successfully authorized onedrived. と表示されれば追加は完了です。
Paste URL here: https://login.live.com/oauth20_desktop.srf?code=Md*******-****-****-****-************&lc=1033
Successfully authorized onedrived.
Successfully added account for ******** (********@outlook.com)!
All OneDrive accounts associated with user "****":
# Account ID Owner Name Email Address
--- ---------------- ------------ ------------------------
0 **************** ******** ********@outlook.com
続けて使用するドライブを選択します。ドライブを選択するにはonedrived-pref drive set
コマンドを使います。コマンドを入力するとドライブの一覧が表示され番号を入力する状態になります。ドライブは1つしかないと思いますので最初の0を入力します。続けて同期するディレクトリを聞かれますので先ほど作成したディレクトリ /media/onedrive を指定します。
$ onedrived-pref drive set
Reading drives information from OneDrive server...
All available Drives of authorized accounts:
# Account Email Drive ID Type Quota Status
--- ------------------------ ---------------- -------- -------------------------- --------
0 ********@outlook.com **************** personal 3.0 GB Used / 5.0 GB Total active
Please enter row number of the Drive to add or modify (CTRL+C to abort): 0
Going to add/edit Drive "****************" of account "********@outlook.com"...
Enter the directory path to sync with this Drive [/home/****/OneDrive]: /media/onedrive
Syncing with directory "/media/onedrive"? [y/N]: y
Enter the path to ignore file for this Drive [/home/****/.config/onedrived/ignore_v2.txt]:
Successfully configured Drive **************** of account ********@@outlook.com (****************):
Local directory: /media/onedrive
Ignore file path: /home/****/.config/onedrived/ignore_v2.txt
完了です
同期実行!
テストするためにフォアグランドで onedrived-dev を起動し同期が実行されることを確認します。
$ NGROK=~/onedrived-dev/ngrok onedrived start --debug
--debug
を外せばバックグラウンドで動かせるようですのですが私の場合は今だに--debug
で動かしているので、動作検証はできていないです。
同期するためのスクリプト
暗号化されたイメージファイルをマウントして同期するまでを簡単に実行できるようにスクリプトにしておきます。
# !/bin/sh
# マウントされていなかったらマウント
if [ -z "$(df -h | grep /media/onedrive)" ]; then
sudo cryptsetup luksOpen onedrive.img cryptroot_onedrive
sudo mount /dev/mapper/cryptroot_onedrive /media/onedrive
fi
# 同期(マウントに失敗している場合は実行しない)
if [ -n "$(df -h | grep /media/onedrive)" ]; then
NGROK=~/onedrived-dev/ngrok onedrived start --debug
fi
終わりです。
おまけ
cryptsetupで作成したイメージファイルは本当に暗号化されているの?
というわけで試してみました。cryptsetupで作成したイメージファイルとそうでないイメージファイルを作成し比較してみます。
まずはテスト用のファイルです。単純にabc..zが10行並んでいるだけのテキストファイルです。
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
4Mの小さなイメージファイルを作成し、先ほど作成したtest.txtをコピーします。
# 暗号化されていないイメージファイル
$ fallocate -l 4M a.img
$ mkfs.ext4 -j a.img
$ sudo mount a.img /mnt
$ sudo cp test.txt /mnt
$ sudo umount /mnt
# 暗号化されたイメージファイル
$ fallocate -l 4M b.img
$ cryptsetup -y luksFormat b.img
$ sudo cryptsetup luksOpen b.img cryptroot_b
$ sudo mkfs.ext4 -j /dev/mapper/cryptroot_b
$ sudo mount /dev/mapper/cryptroot_b /mnt
$ sudo cp test.txt /mnt
$ sudo umount /mnt
$ sudo cryptsetup luksClose cryptroot_b
先頭から少しダンプして目で比較してみます。見るからに差があることがわかります。ちょっと安心です。
$ hexdump -Cv a.img | head -16
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
# hexdump -Cv b.img | head -16
00000000 4c 55 4b 53 ba be 00 01 61 65 73 00 00 00 00 00 |LUKS....aes.....|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 78 74 73 2d 70 6c 61 69 |........xts-plai|
00000030 6e 36 34 00 00 00 00 00 00 00 00 00 00 00 00 00 |n64.............|
00000040 00 00 00 00 00 00 00 00 73 68 61 31 00 00 00 00 |........sha1....|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 20 |............... |
00000070 97 51 16 74 15 bc b6 c8 4e a8 d3 32 37 75 f2 a9 |.Q.t....N..27u..|
00000080 f5 11 13 00 84 4e 41 30 2e 94 50 c0 b4 55 20 ef |.....NA0..P..U .|
00000090 36 80 27 a6 a1 45 24 b8 0f 43 33 97 3c 36 1c ba |6.'..E$..C3.<6..|
000000a0 17 df 3e cd 00 01 47 a3 65 34 63 30 36 32 65 62 |..>...G.e4c062eb|
000000b0 2d 63 64 35 38 2d 34 39 65 34 2d 39 32 62 36 2d |-cd58-49e4-92b6-|
000000c0 33 61 31 39 32 30 39 38 61 38 66 38 00 00 00 00 |3a192098a8f8....|
000000d0 00 ac 71 f3 00 05 2c 80 d9 c9 7f b8 92 54 7d ad |..q...,......T}.|
000000e0 f7 e2 a9 be ab 41 2c 39 0b 77 b1 bf cd 7b 73 c6 |.....A,9.w...{s.|
000000f0 65 e2 4c 0f 1b 94 cf 21 00 00 00 08 00 00 0f a0 |e.L....!........|
先ほどコピーしたファイルから文字列abcdを検索してみます。暗号化されていないイメージファイルからは10件検出できましたが、暗号化されたファイルからは検出できませんでした。
$ strings a.img | grep -c abcd
10
$ strings b.img | grep -c abcd
0
空きがあるのにNo space left on deviceが出た時は?
ある日、同期してみたところ以下のようなエラーが出て同期できなくなりました。
[2018-07-01 21:27:08,282] DEBUG: Worker-0: Adding watcher for "/media/onedrive"
Exception in thread Worker-0:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/home/****/onedrived-dev/onedrived/od_threads.py", line 29, in run
task.handle()
File "/home/****/onedrived-dev/onedrived/od_tasks/merge_dir.py", line 168, in handle
self.repo.context.watcher.add_watch(self.repo, self.local_abspath)
File "/home/****/onedrived-dev/onedrived/od_watcher.py", line 55, in add_watch
wd = self.notifier.add_watch(local_abspath, self.FLAGS)
File "/usr/local/lib/python3.5/dist-packages/inotify_simple/inotify_simple.py", line 87, in add_watch
return _libc_call(_libc.inotify_add_watch, self.fd, path, mask)
File "/usr/local/lib/python3.5/dist-packages/inotify_simple/inotify_simple.py", line 52, in _libc_call
raise OSError(errno, os.strerror(errno))
OSError: [Errno 28] No space left on device
dfコマンドで調べてみてもディスクに空きはあります。
$ df -h /media/onedrive/
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cryptroot_onedrive 4.8G 3.1G 1.5G 68% /media/onedrive
よく見るとエラーメッセージ中にinotify_add_watchという文字列があるので、試しにinotifyで監視できるファイル数の上限を変更してみます。
# 現在の上限を確認
$ sysctl fs.inotify.max_user_watches
fs.inotify.max_user_watches = 8192
# 条件を倍の16384に変更
$ sudo sysctl fs.inotify.max_user_watches=16384
fs.inotify.max_user_watches = 16384
再度実行してみます。…無事同期されました。案外とあっけなく解決してしまいました。とりあえずめでたしめでたし…かな。