sftp-server と sshfs のプロセス間通信について

概要

コンテナや仮想マシンとホストマシンで、ファイルシステムを共有するにはどうすればいいのかを知りたくて、いくつかのOSSソースコードを読んでみた。

今回は sftp-server と sshfs の組み合わせを題材に、その方法をまとめていく。
なお sshfs は現在積極的な開発が行われていないようなので、新規プロジェクトの場合は他のツールが適当と思われる。

手順

結論を先に書くと、ローカルで sftp-server を立てて、リモートからの sshfs (ローカルからのsshコマンドとして実行)と接続できるようにする。

そのために両プロセスの入出力を相互に接続してプロセス間通信を行う。
sshfs の man ページの表現を借りると、passive オプションにある communicate over stdin and stdout bypassing network というもの。

例えば Golang だとコマンドの入出力を宣言的に記述できるが、これをシェルで行う場合は名前付きパイプ(FIFO)を使って実現する。

fifo=/tmp/fifo-$$
mkfifo -m600 "$fifo"

これであたかも存在するファイルのようにパイプを扱うことができる。
この名前付きパイプへの write/read は他プロセスからの read/write があるまで、待機してくれるようなイメージ。

このパイプを使って、sftp-server と sshfs の入出力を接続し、プロセス間通信を行うには、このように書く。

< "$fifo" /usr/libexec/sftp-server -e -d /path/to/dir | ssh -p <port> <host> -- sshfs ":/path/to/dir" "/path/to/mountpoint" -o slave -o allow_other > "$fifo"

これで、リモートとローカルのファイルシステムを同期できる。 厳密に測定していないが、同期には1秒ほどかかり、同期されない場合はどちらかのディレクトリで ls などを叩くと反映される。

参考

github.com