Go 言語の習作に watchevent ってファイルシステム監視するやつ作った(おまけに Subsonic で音楽ファイルを追加・削除されたタイミングでスキャンさせる方法)
習作って言っても以前 Go 触ってたことはありましたが、 そのツールを作ったこと自体忘れてたぐらい記憶が抜け落ちていたので、改めて Go に再入門しました。
作ったもの
使い方は README.md 読んでください(まだ不十分だと思いますが、分からない点は issue に上げてくれると助かります…)。
各種バイナリは GitHub release のページにあります(watchevent コマンドしか入ってません)。
きっかけ
自分は Subsonic というストリーミングサーバーを自宅に立てて運用してますが、 いくつか不満がありました。
ちなみに上記記事では同じくストリーミングサーバの Libresonic に移行したと書いてるのですが、色々問題点があって結局戻ってきました。 それについては気が向いたら詳しく別記事で書きますが、なんと言っても第一の理由は今回利用する API が Libresonic では対応してなかったからです。 それが音楽フォルダのスキャンを開始する API です。
Subsonic では音楽フォルダに mp3 ファイルをポンと置いてもすぐ Web に現れる訳ではなく、 音楽フォルダのスキャンを行う必要があります。 しかしこのスキャンのタイミングがデフォルトでは夜の3時のみで、不便なことに定期スキャンは1日1回だけという制限があります(時間は変えられます)。
もちろんこれでは不便すぎるので Subsonic にはアップロード機能があって、 アップロードした音楽ファイルであれば即座に認識されます。 しかしアップロードするために ZIP で固めるのが面倒だったり、 何となくディレクトリ構造は手動で決めたいという欲求から自分はアップロード機能は使ってません。
しかしそれでは手元にある音楽ファイルを音楽フォルダに移動してすぐ聴きたいという時に不便です。 幸いスキャンは設定画面から手動でも行うことができるので、音楽フォルダに移動するたびにわざわざスキャンのボタンをポチっていましたが、できれば自動化したい。
そこで Subsonic の REST API のページを眺めていると前述のスキャンを行うエンドポイントがあると書いてありました。 ならファイルの変更を検知して curl で叩くツール作ればいいのでは?ということで作りました。
Systemd で管理する
自分は watchevent は Systemd で管理して使ってますので、 ついでにそのインストール手順を書きます。
まずバイナリを GitHub release のページからダウンロードしてきて、
どこでもいいですが /opt/watchevent
に置きます。
$ # ダウンロード URL は OS, arch によって変えてください $ curl -LO https://github.com/tyru/go-watchevent/releases/download/v0.0.1/watchevent-v0.0.1-linux-amd64.tar.gz $ tar xzf watchevent-v0.0.1-linux-amd64.tar.gz $ sudo mkdir /opt/watchevent/ $ sudo install -o root -g root -m 0755 watchevent-v0.0.1-linux-amd64/watchevent /opt/watchevent/watchevent
次に各設定ファイルを作ります。
/etc/systemd/system/watchevent.service
[Unit] Description=Watchevent [Service] Type=simple EnvironmentFile=-/etc/default/watchevent ExecStart=/opt/watchevent/watchevent -c /etc/watchevent/watchevent.yml $DIRECTORY PrivateTmp=true [Install] WantedBy=multi-user.target
/etc/default/watchevent
DIRECTORY="-d {監視対象のディレクトリ}"
ちなみにこんな風に2個以上監視することもできます。
DIRECTORY="-d dir1 -d dir2"
/etc/watchevent/watchevent.yml
action: - name: post-subsonic-rescan on: [all] # 30s after latest file change, access to Subsonic API interval: 30s interval_action: - on: [all] do: cancel # {user}, {token}, {salt} は変えてください。{token}, {salt} については後述 run: curl 'http://localhost:4040/rest/startScan?u={user}&t={token}&s={salt}&v=1.15.0&c=watchevent-curl' log: level: "info" encoding: "console" #encoding: "json" encoderConfig: messageKey: "msg" levelKey: "level" timeKey: "time" nameKey: "name" callerKey: "caller" stacktraceKey: "stacktrace" levelEncoder: "capital" timeEncoder: "iso8601" durationEncoder: "string" callerEncoder: "short" outputPaths: - "stdout" errorOutputPaths: - "stderr"
ちなみに Subsonic API の解説もしておくと、curl コマンドの引数の URL の {token}
はこんな風に求めます({salt}
は適当に決めてください)。
$ echo -n '{パスワード}{salt}' | md5sum
で出力された MD5 値を token に指定します。 うまくいかなければ u (username), p (password), c (client) パラメータだけでもいけます(がセキュリティ上よろしくない)。
上記設定ファイルを作った後、
$ sudo systemctl daemon-reload $ sudo systemctl enable watchevent $ sudo systemctl start watchevent
として起動します。 ちゃんと動作してるかログが見たい方は
$ journalctl -ef -u watchevent
とかすると watchevent の出力が tail -f されるので眺めるといいかもしれません。