LoginSignup
15
15

More than 5 years have passed since last update.

アプリのコンテキストでコマンド実行するappdoコマンドを作ったよ

Posted at

ホストにログインしてから Ruby on Rails のアプリケーションで rake を実行するまでの前準備が長すぎるので、 appdo という一つのコマンドにまとめてしまおう、という話をします。

解決したい問題

Ruby を rbenv や rvm で入れていると、 sudocron 等でのコマンド実行時に ruby が見つからなくて困ります。まあ ~/.bashrc などを都度読めばいいんですが、そうするとコマンドが複雑になってしまいます。そういう処理をしてる箇所が増えると、修正漏れも起きやすくなります。こまる。

Ruby on Rails のアプリケーションを運用しているときにはさらに cd $RAILS_ROOT しないと bundle exec rakebin/rails runner も実行できません。結果、運用コマンドはどんどん長くなり、 crontabconfig/deploy.rb はメンテナンスしづらくなってしまいます。こまる。

どうせ同じホストではいっつもおんなじ準備をするんだから、そんな設定はホストに持つべきでしょーってことで、そういうコマンドを作りました。

appdo で解決だ

アプリのコンテキストでコマンド実行するための appdo コマンドというものを作りました。pip install できます。

pip install appdo

appdo を使うと、これまで以下のように実行していた rails c が…、

$ su - web                       # まずログインして…
$ cd my-awesome-app              # あった、このディレクトリだ
$ cd current                     # あ、capistrano 管理下だった
$ export RAILS_ENV=production    # 環境変数設定してーの
$ export RACK_ENV=production     # (なんかいろいろ)設定してーの
$ bundle exec rails c            # ほい

これだけで済むようになります。

$ sudo -iu web appdo rails c     # webユーザのアプリ内で rails c

設定ファイルは以下のように、 $HOME/.appdo.conf に書いておきます。書式は TOML

# /home/web/.appdo.conf
#
##    sudo した場合、 sudo 先のユーザの .appdo.conf が適用されます

[default]
cd = "~/my-awesome-app/current"
source = ["/etc/profile", "~/.bashrc"]
prefix = "bundle exec"

[default.env]
RAILS_ENV = production
RACK_ENV = production

見たまんま、 cd して source して環境変数設定したうえでコマンドを bundle exec してくれるわけです。

必ず毎回やることなら、人間がやるべき仕事じゃないですよね。設定ファイルに入れ、そのファイルをプロビジョニング管理する方が人間が幸せになります。

その他の変化

crontab の変化

appdo がないとき

RAILS_ROOT=/home/web/my-awesome-app/current
BASHRC=/home/web/.bashrc
RAILS_ENV=production

30 3 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron.run()"
30 4 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron2.run()"
30 5 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron3.run()"

appdo があるとき

30 3 * * * appdo rails runner MyAwesomeApp::MyCron.run()
30 4 * * * appdo rails runner MyAwesomeApp::MyCron2.run()
30 5 * * * appdo rails runner MyAwesomeApp::MyCron3.run()

環境変数を設定する必要がない(appdoが吸収してくれる)ので、crontab が超シンプルになります。
何のコマンドを打ってるのか、appdo なら見えるよ。わたしにもみえるよ

ssh でのコマンド変化

appdo がないとき

ssh my.server.example.com sudo -u web bash -c "cd /home/web/my-awesome-app/current; source ~/.bashrc; RAILS_ENV=production bundle exec rake assets:precompile"

appdo があるとき

ssh my.server.example.com sudo -iu web appdo rake assets:precompile

こちらも crontab と同様、単純になります。
ssh を単純にするのは、 config/deploy.rb が簡易化できるっていう利点が大きいです。アプリのコードにホスト固有の情報(パスとか環境変数とか)を入れる必要がなくなるので、分離がよくなる。

手順書の簡易化

想像してごらん、すべての cd/source がドキュメント外に移動する
うっうー

ホスト移行が簡単になる

例えばアプリのパスが異なっていたり、ruby が rvm/rbenv 混在環境であっても、それぞれのホストにある設定ファイルでこの違いを吸収できます。結果、デプロイスクリプトに変更の必要がないので、順次移行がかなり楽になるかもしれません。

その他の活用例

サーバの設定ファイル管理

# /root/.appdo.conf

[apache]
cd = "/etc/apache2"

[bind]
cd = "/var/bind/etc/bind"

cd 先だけ指定しておいて、設定ファイルの管理コマンドだけ共有しておくのも便利かも。

# appdo --app=apache -- ls sites-available
# appdo --app=apache -- ln -s sites-available/99-default sites-enabled
# appdo --app=bind -- co -l master/my.example.com
# appdo --app=bind -- vim master/my.example.com
# appdo --app=bind -- ci -u master/my.example.com

まとめ

  • appdo を使って「アプリの文脈」でコマンド実行しよう
  • appdo を使って「アプリの文脈」を設定ファイルに落とし込んでしまおう
  • appdo を使ってアプリとインフラの切れ目を整理しよう

おわりに呟き

まだ個人で作ったばかりで bullet proof でないスクリプトですが、まずはリリースして仕様叩きをしてみることにしました。バグ報告や要望など、お待ちしています。

もともとは、「rvm/rbenv を使った際に sudo から ruby を使えない」ことがストレスで、この appdo コマンドを考えました。
昨今インフラに求められているものはまた変化しつつありますが、 docker にせよ serf/consul にせよ autoscaling にせよ、ホストが自律的に動作するように設計したほうがうまく回るように思います。そんなところでも appdo を使うことにより「ホスト層」のようなものを作っていろいろ吸収できるのであれば、なんか頭使うところが減って幸せになれるんじゃないかなあとかぼんやりと思います。

実装が Python なのはいわゆるファーストプロトタイピング的なやつです。Python でパッケージ作ったことなかったので、実装に際しては @mkouhei さんの bootstrap-py を使用させていただきました。オプション等の要件が固まってきたら Go に移行するのがいいのかなーと考えています。

え?Rustのほうがいいって?…

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15