注:2019年11月にCentOS 8に移行したため、以降のCentOS 7における状況は追跡していない
Dropboxは2018年10月にLinux版のシステム要件を情け容赦なく更新し、これまで動いていた環境を切り捨てた。主には
- Ubuntu 14.04 以上、Fedora 21 以上 のオペレーティング システム
- Glibc 2.19 以上
- Dropbox フォルダは ext4 形式のハード ドライブかパーティションに配置すること
などの要件が新たに科され、対応するディストリビューションについては(本質的問題ではないので)ともかく、xfsやbtrfsなどext4以外のファイルシステム上で使えなくなった。これはもともとext4以外を標準とするディストリビューションや、宗教上の理由でext4以外を使いたいユーザーへの打撃となった。しかしこれに対してはいくつかのworkaroundが考案された(e.g. btrfsでDropboxを使う とか btrfs? Dropboxさん, あなたが見ているのはext4ですよ とか)。ただ私自身は諦めてext4でフォーマットし直したので、これらの有効性は確認していない。
何より致命的な問題はglibcのバージョンで、CentOS 7はglibc 2.17を採用しているから、ファイルシステム問題をクリアしてもCentOS 7では動作させられなくなった。なおこのシステム要件の更新直後は上記ファイルシステムの問題と同様にglibcのバージョンを騙してやるworkaround(e.g. 2018年版、CentOS 7 で Dropbox を使う)があったようだが、その後にDropboxがアップデートされ、少なくともglibc 2.18を呼ぶようになったみたいでこの方法もまた使えなくなった。
当然システムのglibcをアップデートしてしまうのは影響範囲が甚大で危険だから、Dropboxだけが使う新しいglibcを別に入れるのが比較的安全だとは思っていたが、新しいglibc自体のビルドに必要な要件をCentOS 7が満たしていないので、ちょっとてこずった。
同じようなことを試した人も既にいたが、何が違ってうまく行かないのか不明なので、取り敢えず手元でうまく行った(2019年2~3月頃の)メモ。
Developer Toolset 7を入れる
新しいglibcをビルドするにはGCCなどのバージョンが古いため、Developer Toolsetを入れる。現在の最新版は7であるが、どんどん更新されているようなので新しいバージョンが出ているのかも知れない(現在はたまたま7だが、CentOSのバージョンと一致している、とかいう性格のものではない)。
$ sudo yum install centos-release-scl
$ sudo yum install centos-release-scl patchelf
$ sudo yum-config-manager –enable rhel-server-rhscl-7-rpms
$ sudo yum install devtoolset-7
$ scl enable devtoolset-7 bash
新しいglibcを入れる
現在の最新版はglibc 2.29だが、試行錯誤の過程でglibc 2.27を入れた(別にゆかりんの誕生日だからと思ったわけじゃない)。 Developer Toolset 7であれば問題はないはずなので、本当は最新版を入れた方がよい気がする。(参考にしたサイト:Dropbox – glibc and file systems support)
$ tar xzvf glibc-2.27.tar.gz
$ cd glibc-2.27
$ mkdir build
$ cd build
$ ../configure –prefix=/opt/glibc-2.27
$ make
$ sudo make install
patchelf する
処理内容の想像はついているが、理解していない。Dropboxはしょっちゅうバージョンアップするので、最新のパスにする。バージョンアップの際の作業は下の補足を参照。
$ patchelf --set-interpreter /opt/glibc-2.27/lib/ld-2.27.so ~/.dropbox-dist/dropbox-lnx.x86_64-66.4.84/dropbox
$ patchelf --set-rpath /opt/glibc-2.27/lib ~/.dropbox-dist/dropbox-lnx.x86_64-66.4.84/dropbox
シンボリックリンクとかはる
(参考にしたサイト: CentOS7でDropBox glibc2.9以上でないと使えなくなった対応)
同サイトのglibcバージョン表記は誤記(2.7→2.17、2.9→2.19)だと思うが、取り敢えず気にしないことにする。
$ cd ~/.dropbox-dist/dropbox-lnx.x86_64-66.4.84/
$ ln -s /lib64/libgcc_s.so.1
$ ln -s /usr/lib64/libstdc++.so.6
$ ln -s /lib64/libz.so.1
$ ln -s /lib64/libgthread-2.0.so.0
$ ln -s /lib64/libglib-2.0.so.0
Dropboxを起動する
$ export LD_LIBRARY_PATH=~/.dropbox-dist/dropbox-lnx.x86_64-66.4.84:$LD_LIBRARY_PATH
$ ~/.dropbox-dist/dropboxd
うまく行くのを確認したら、LD_LIBRARY_PATHを加えて起動するスクリプトでも用意するとよいかも。例えばこんな感じ?
#!/bin/sh
export LD_LIBRARY_PATH=~/.dropbox-dist/dropbox-lnx.x86_64-`/usr/bin/cat ~/.dropbox-dist/VERSION`:$LD_LIBRARY_PATH
exec ~/bin/dropbox.py "$@"
Dropboxアップデート時の補足
Dropboxのdaemonは新しいバージョンを自動的に探して自動的にアップデートするが、上記手順からしてこのアップデート機構はうまく動作せず、何らかの工夫が必要となる。放置しておくと、自動アップデートを試みた後、予想通り古いglibcを見に行ってしまう。
ImportError: /lib64/libc.so.6: version `GLIBC_2.18’ not found (required by /tmp/.dropbox-dist-new-45n94tcl/.dropbox-dist/dropbox-lnx.x86_64-67.4.83/dbxlog._dbxlog.cpython-36m-x86_64-linux-gnu.so)
取り敢えず手動で回避しておいて、後から自動化する方法を考えることにする(以下の手順はscl enable devtoolset-7していない通常の環境下で差し支えない)。
$ dropbox stop
$ dropbox update
アップデートそのものは途中まで成功するが、ここでも(当然)エラーが出るので、手動で処理する。
$ dropbox stop
$ cd ~/.dropbox-dist/dropbox-lnx.x86_64-`/usr/bin/cat ~/.dropbox-dist/VERSION`
$ patchelf --set-interpreter /opt/glibc-2.27/lib/ld-2.27.so dropbox
$ patchelf --set-rpath /opt/glibc-2.27/lib dropbox
$ ln -s /lib64/libgcc_s.so.1
$ ln -s /usr/lib64/libstdc++.so.6
$ ln -s /lib64/libz.so.1
$ ln -s /lib64/libgthread-2.0.so.0
$ ln -s /lib64/libglib-2.0.so.0
$ dropbox start
Dropboxアップデート時の自動化の検討
アップデートの自動化につまづいていたのは以下の[y/n]に自動で応答し先に進めることがうまくできていなかったからだった。
Dropbox is the easiest way to share and store your files online. Want to learn more? Head to https://www.dropbox.com/
In order to use Dropbox, you must download the proprietary daemon.
Note: python-gpg (python-gpgme for Ubuntu 16.10 and lower) is not installed, we will not be able to verify binary signatures. [y/n]
めんどくさいのでdropbox.py自体から以下の部分をコメントアウトした(行数はアバウト)。
564 # if not yes_no_question("%s%s" % (WARNING, GPG_WARNING_MSG)):
565 # return
よって自動化するスクリプトは概ねこんな感じで、適当に1日1回くらいcronで呼ぶことにする。古いバージョンのゴミが残るけど、そんな細かいことは…。
#!/bin/sh
STATUS=`~/bin/dropbox status`
if [[ $STATUS = "Dropbox をアップグレード中..." ]]; then
~/bin/dropbox stop
~/bin/dropbox update
cd ~/.dropbox-dist/dropbox-lnx.x86_64-`/usr/bin/cat ~/.dropbox-dist/VERSION`
/usr/bin/patchelf --set-interpreter /opt/glibc-2.27/lib/ld-2.27.so dropbox
/usr/bin/patchelf --set-rpath /opt/glibc-2.27/lib dropbox
/usr/bin/ln -s /lib64/libgcc_s.so.1
/usr/bin/ln -s /usr/lib64/libstdc++.so.6
/usr/bin/ln -s /lib64/libz.so.1
/usr/bin/ln -s /lib64/libgthread-2.0.so.0
/usr/bin/ln -s /lib64/libglib-2.0.so.0
~/bin/dropbox start
fi
(2019.03.21 – 2019.11.12)