追記:これを書いた当時は開発者ごとにEC2インスタンスが配られてる環境でした。Amazon LinuxやRDSとかも使っていたので、ローカルでやるのは面倒という状況だったので、いかにEC2上でローカルと同じように開発するかを追求したという背景です。
EC2とかでもAtom使いたい・・!
VimとかEmacsとかのCUIエディタでの開発からの脱却を狙っていて、
ローカルエディタで開発したいが・・
- ssh先のサーバでしか開発できない
- 手元のMacに依存関係のセットアップするのがとても面倒
実際やってみたが・・
- 変更都度rsyncとかscpとか許せない
- sshfsは遅すぎて使いものにならない
- エディタの機能でssh上のファイルを開くとGit連携とかのいろんな機能が使えずつらい
- (以前上がっていたAtomプラグインを使用する方法だと一部機能が使えないはずです)
- エディタだけじゃなくシェルなどもなるべくローカルのものを使いたい
シンプルなソリューション:unison
エディタの自由のためにはファイルを自動で双方向同期するのが一番手っ取り早かったです。
unisonを使うとssh先のサーバとDropboxのように同期することができます。
rsyncと違って、前回の同期状態を保存していたり、ファイルの変更をリアルタイムに監視したり、競合を手動で解決したりできます。
最近も更新されていますが、製品自体とても枯れてて安心です。
また、副作用的に、ローカルシェルで全てのファイルを編集できるようになるので、EC2上に最低限の環境しか構築しなくて済むようになります。
1行でまとめるともっと評価されるべき。
セットアップ
サーバ・クライアント双方でセットアップが必要です。
Mac
homebrewに最新版が上がっていました。
追記: 以前はunison-fsmonitorがPython 3でしか動かなかったのですが、今は逆にPython 2でしか動かなくなってしまいました・・。
brew install unison
# ファイルシステム変更監視用のscriptが同梱されていないので別途持ってくる
mkdir -p ~/bin
curl -L https://github.com/jumpstarter-io/unox/raw/master/unox.py > ~/bin/unison-fsmonitor
chmod +x ~/bin/unison-fsmonitor
# ~/binをPATHに通してください
# pyenv install 2.x.xなど何らかの方法でpython3を用意する
# まだ特にセットアップしてない人はanyenvがオススメです http://qiita.com/luckypool/items/f1e756e9d3e9786ad9ea
# pyenvな人はインストールしたpythonを使うように設定します
cd /path/to/your/repo
pyenv local 2.x.x
# 依存ライブラリを導入
pip install MacFSEvents
Amazon Linux (EC2)
少なくとも2015年前半においては、ものすごく古いバージョンしかyum installできなかったので、ソースからビルドしました。
お使いのディストリで2.48.3が配信されていれば単にインストールするだけで良いと思います。
ここだけちょっと面倒です。
他力本願ですがrpmをどなたか作っていただきたく・・w
追記: 面倒すぎたので確認したところ外部yum repoを使う方法もありました。
ocamlのインストール:外部yum repoを入れる方法
下記の手順に従って導入します。
http://rnowling.github.io/software/engineering/2015/04/02/installing-ocaml.html
Amazon Linuxに対応するCent OSのバージョンに合わせて追加するrepoのURLを変更してください。
ocamlのインストール:ocamlbrewを使う方法
# 最新版を入れるためにソースからビルドするため、言語環境のOCamlをセットアップする
curl -kL https://raw.github.com/hcarty/ocamlbrew/master/ocamlbrew-install | bash
# エラーになリますが無視で
# https://github.com/hcarty/ocamlbrew/issues/25#issuecomment-97130288
# gitで管理していないような.**shrcファイルに環境変数を追加しておく
vim ~/.zshrc_local # 自分はこのファイルを.zshrcからsourceしている
下記を貼り付け
__ocaml_path__="$HOME/ocamlbrew/ocaml-4.XX.X" # ~/ocamlbrewをlsしてみて適切なバージョン番号に置き換えてください
PATH="$__ocaml_path__/bin:$PATH"
export OPAMROOT="$__ocaml_path__/.opam"
source "$OPAMROOT/opam-init/init.zsh" > /dev/null 2> /dev/null || true
編集したファイルをsourceし、下記のコマンドでセットアップを完了します。
opam switch 4.XX.X # (上記の「適切なバージョン番号」を使います
(共通)unisonをインストールする
ocamlがインストールできたのでunisonをインストールします。
# unisonのocaml依存関係を入れておく
opam install oasis utop Batteries ocamlscript
# http://www.cis.upenn.edu/~bcpierce/unison/download.html からCurrent Stable Versionのものをwgetなどで落としてきて、tar -xfなどで展開する。
# unison-2.48.3に展開したとする
cd ~/unison-2.48.3
make
# デフォルトで~/binにインストールされる
mkdir -p ~/bin
make install
# 監視用のスクリプトはinstallされないので別途コピーする
cp unison-fsmonitor ~/bin/
# パスが通ってない場合は通す(ただしsshで実行コマンドを直指定しても読み込まれる箇所(.zshenvや.bashrc)に書かなくてはならない)
echo 'export PATH="$HOME/bin:$PATH" >> ~/.zshenv
使い方
コマンド
使用例
unison ssh://host/dir /path/to/local/dir -ignore 'Path vendor' -ignore 'Name {tmp,log}' -repeat watch -auto
基本はunison A B
です。
-repeat watch
はファイルシステム監視を有効にして、-auto
はコンフリクトがなければ勝手に同期するためのフラグです(いわゆる--yes)。
-ignoreは開発する環境に合わせて付け替えます。
例に載ってるvendorは、railsのgem群が多すぎて辛かったのとmacとlinuxでバイナリが非互換だったのがあり(「罠」を参照のこと)、ignoreしています(手元でbundle installしている)。
設定ファイル
~/.unison/foobar.prf に 設定ファイルを置くと、unison foobar -repeat watch [OPTIONS]
で同期できます。
注:ignore設定に罠(バグ)があります。「罠」を参照のこと。
root = ssh://host/dir
root = /path/to/local/dir
ignore = Path vender
ignore = Name {tmp,log}
auto = true
コンフリクト
調子にのって両方のホストでファイルを編集してからunison -repeat watch
コマンド叩くと、下記のようにCONFLICT表示になります。
Looking for changes
Waiting for changes from server
Reconciling changes
changed <-?-> changed conflict.txt
Propagating updates
UNISON 2.48.3 started propagating changes at 10:33:42.14 on 04 Aug 2015
[CONFLICT] Skipping conflict.txt
contents changed on both sides
罠っぽいのが-repeat watch
の場合conflictが発生しても(そのファイルをスキップして)何食わぬ顔で同期し続けるので、unison -repeat watch
コマンドを叩いた直後は一応確認しておいたほうが良いです。
解消するには、-repeat watch
なしでunisonコマンドを叩きます。
ssh-host local
changed <-?-> changed conflict.txt []
上記の表示が出て、現在のファイルに対するアクションを1文字(y/nに似てる)で聞いてきます。
とりあえず利用可能なアクションを表示するには?
を押します。
よく使いそうなのは下記です。
d show differences
> or . propagate from from ssh-host to local
< or , propagate from from local to ssh-host
罠
- ignoreをprfファイルに書いても反映されない(同期はされないけどファイルの監視が実行される?)模様(コマンドラインならいけた)
- Rails限定:macでtherubyracerというgemをビルドするためには特定バージョンにしなくてはならない http://3.1415.jp/d3wpyqjr/
- Rails限定:vendor/bundle以下は同期から外さないと、ライブラリのバイナリが無いと言われたり、ファイル監視の上限を超えたというエラーが出たりする
- ignoreしたパス(gemの中身)を編集してしまいローカルにしか反映されていない、みたいな罠を踏んだorz...
- 1回だけ、両方のホストでgitの操作をしてしまったところ、gitのobjectファイルが片方に存在して片方に存在しないみたいな状況が発生しました(git logするとエラー) → gitで複数のワーキングディレクトリを作ってたのに、コピーの方しか同期してなかったからでした。この場合は元となった.gitディレクトリがちゃんと同期されている必要があります。
近況
とりあえず1年近くうまく使えているのでVim→Atomにほぼ完全に乗り換えることができました。