ruby for better bash
DESCRIPTION
better bashとしてのrubyの利用を薦めるスライドです。 そのまま導入するために手順の解説もしています。TRANSCRIPT
Qonceptでは、ARを中心にiOS/Androidアプリ開発を行っていますが、複雑なアプリケーションのリソース管理や、プラットフォーム型のサービスの運用において、細かい作業が徐々に自動化される事がよくあります。
普段はシェルとしてbashを使っているため、その延長で自動化しやすいbashスクリプトがよく書かれています。
しかし、慣れているbashスクリプトであっても、高度な事をしようとすると厳しい部分があるので、better bashとしての別の方法を検討してきました。
いろいろと試したところ、rubyは結構実用的だという実感が得られてきたので、社内向けに展開するために作ったのが、このスライドです。
このスライドについて
薦め
bashスクリプトとは
・単純な作業の自動化によく使う。
・いろいろな環境で動く。ローカルのMacでも、そのままサーバのLinuxでも。
・使い慣れたコマンドが使える。mkdir, grep, wc, zip, rsync, convert...。・普段のシェル操作の延長でスクリプティングが始められる。
運搬性が高いが保守性、拡張性が低い
・配列や辞書のサポートが貧弱。
・ややこしい独自の構文が多い。
・相対パスを取ろうとすると苦しい。
・jsonとか取り扱おうとすると苦しい。
・bashでがんばるぐらいなら、良い感じのスクリプト言語に切り替えよう。
Rubyの薦め
・見かけがbashに似ているため、代替として使う上でのハードルが低い気がする。
・言語のバージョン間互換性が低いが、rbenvによりrubyのバージョンを切り替えられるので、問題なし。
・シェルと同様に外部コマンドも呼び出せる。
・標準ライブラリや、gemによる外部ライブラリが豊富なため、壁にぶつからない。
・環境構築が簡単なため、運搬性もそこそこある。
見かけがbashに似てる
a=1if [[ a -gt 0 ]] ; then
echo "こんにちは"fi
bash
a = 1if a > 0 then
puts "こんにちは"end
ruby
・ブレース{}ではなく予約語による制御構文。・文末のセミコロンが無い。・丸括弧の無い関数呼び出し。
rbenvによるruby切り替え
$ rbenv versions system 2.0.0-p195 2.0.0-p451 2.1.0 2.1.1* 2.1.2 (set by /usr/local/var/rbenv/version)$ rbenv global 2.0.0-p195$ ruby --versionruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.4.1]$ rbenv global 2.1.2$ ruby --versionruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
・ディレクトリに対してバージョンを設定して、自動で切り替える事もできる。
・下記は、コマンドラインでrubyのバージョンを切り替える様子。
外部コマンドの呼び出し下記コマンドを実行するrubyプログラムの例です。
$ ls -1 | grep -E '\.rb$'
呼び出した後、パイプで繋がれた各コマンド(lsとgrep)のステータスコードをチェックしている。実際に利用ではこれを関数で包むのが良いでしょう。
require "open3"status_list = Open3.pipeline(["ls", "-1"], ["grep", "-E", "\\.rb$"])status_list.each.with_index do |status, index|
if status.exitstatus != 0raise Exception.new("pipeline[#{index}] " +
"exit status is #{status.exitstatus}")end
end
・コマンドの引数を配列の要素として指定するため、半角スペース文字に関するバグが防げます。また、コマンドを組み立てるコードが書きやすいです。
gem
・rubyのライブラリ専用のパッケージマネージャ。rubyは広く利用されているため、gemが充実しています。
少し紹介
・kramdown: markdownをレンダリングする。
・rugged: gitリポジトリを操作する。
・rmagick: imagemagickの機能を使う。
・rails: 有名なウェブアプリケーションフレームワーク。
rbenvとgemの関係
・rbenvで複数のrubyを入れている場合、それぞれのrubyごとに独立なgem環境が用意される。
・例えば、ruby2.0.0にした状態でkramdownをインストールしても、ruby2.1.2に切り替えると使えないので、別途インストールが必要。
参考: 先端事情の紹介
・rbenvでは、rubyごとにgem環境があったが、bundlerというライブラリを使うと、更に細かく、ディレクトリ(≒アプリ)に対してgem環境を構築できる。
・rbenvは、ディレクトリごとにrubyのバージョンを設定できるので、これらを組み合わせて、ruby(言語)もgem(ライブラリ群)もディレクトリで独立、完結した状態にできる。
・railsアプリを起動するサーバ(unicornなど)自体も、gemでインストールする。そのため、1つのホストマシンの中で、アプリサーバをアプリごとに独立して持つ事ができる。
・1つのホストマシンに複数のウェブアプリをデプロイする場合などにおいて、環境の独立性、分離性が高く、相互の干渉を防ぐことができる。
・昔は、1つのサーバの中に1つのバージョンのapache、1つのバージョンのphp、1つのpecl, pear環境があって、アップグレードすると、既存のアプリが壊れる恐れがあり、新規開発で最新バージョンの言語やライブラリが使えない事がよくあった。
導入
※Macが前提になります。
導入
公式サイト(http://brew.sh/index_ja.html)を参照してインストールします。
更新保守
$ brew doctorで状態の診断ができます。もし何かしら問題が指摘されたら、1つずつ解決して、下記のように、何も問題がない状態にしましょう。
これはかなり重要です。
$ brew doctorYour system is ready to brew.
大体の場合、「24時間以内にupdateしていません」という趣旨のエラーが出るので、そ
のときは$ brew updateをしましょう。
homebrewの導入、更新保守
rbenvの導入
下記コマンドにてインストールします。
$ brew install rbenv
無事にインストールできたら、.bash_profileに下記を追記します。
export RBENV_ROOT=/usr/local/var/rbenvif which rbenv > /dev/null; then eval "$(rbenv init -)"; fi
次に、下記のrbenvプラグインを入れます。このプラグインについての説明は省略し
ます。
$ brew install rbenv-gem-rehash最後に、下記のrbenvプラグインを入れます。このプラグインが、rubyのバージョン選
択してビルドする機能を提供します。(素のrbenvは、切り替え機能のみを提供してい
ます)$ brew install ruby-build
rubyのインストール
下記コマンドで、インストール可能なrubyのバージョンリストが表示されます。
$ rbenv install --list
ruby公式サイト(https://www.ruby-lang.org/ja/downloads/)と表示されたリストを見比べて、インストールするバージョンを決めたら、下記のように指定して実行します。
$ rbenv install -v 2.1.2
リストの中に、目的の新しいバージョンが含まれていない時は、下記コマンドにてプラグインをアップデートします。
$ brew upgrade ruby-build※2.0.0では、オプションを指定しないと rubyのビルドに失敗する事がありましたが、 2.1.2はそのままで行けました。うまくいかない場合はググってみると良いです。
rubyのバージョンの選択
rbenvでインストールした、選択可能なバージョンの一覧を下記で確認します。
$ rbenv versions
下記で選択します。
$ rbenv global 2.1.2
下記で実際に切り替わったことを確認します。
$ ruby --version
gemのインストール
先述の通り、rubyのバージョンごとにgem環境が存在します。
そのため、まずrbenvでrubyのバージョンを切り替えた後で、gemコマンドでライブラリをインストールします。
下記に例を示します。
$ rbenv global 2.1.2
$ gem install kramdown
書く
irbで試す
すぐに試したい時や、動作をちょっと確認したい時などは、irbという対話環境が便利です。
(水色の網掛けが入力した行です)$ irbirb(main):001:0> a = 1=> 1irb(main):002:0> b = 2=> 2irb(main):003:0> puts "a=#{a}, b=#{b}, a+b=#{a+b}"a=1, b=2, a+b=3=> nilirb(main):004:0> quit
エディタの導入
sublime text 2を入れると良いでしょう。
http://www.sublimetext.com/
rubyスクリプト テンプレート
冒頭2行は決め打ちしましょう。3行目以降を書き換えましょう。
#!/usr/bin/env ruby#coding: utf-8puts "こんにちは"
シェルでの実行
エディタでスクリプトを書いて保存します。
ここでは、hoge.rbとして保存したとします。
ファイルに実行権限をつけます。
$ chmod +x hoge.rb
実行します。
$ ./hoge.rb
よくある処理の紹介
デバッグ目的で変数の値を確認する
p hoge_var
1行出力と、式の文字列への埋め込み。
puts "こんにちは、#{name}さん。現在時刻は#{Time.now}ですよ。"
スクリプトファイルのあるディレクトリのフルパスを得る
script_dir = File.expand_path(File.dirname(__FILE__))
エラー時に終了する
raise Exception.new("引数が不足しています。")
その他、ググるといっぱい出ます。
構文の注意
関数呼び出しは丸括弧無しでも有りでも呼べますが、
丸括弧無しを入れ子で使うと思わぬ誤動作をするので、入れ子にするなら丸括弧を付けましょう。
# 以下4つはOK
Math.sin(30.0 * Math::PI / 180.0)
Math.sin 30.0 * Math::PI / 180.0
printf("sin(30) = %f", Math.sin(30.0 * Math::PI / 180.0) )
printf "sin(30) = %f", Math.sin(30.0 * Math::PI / 180.0)
# 下記はエラーになる
printf "sin(30) = %f", Math.sin 30.0 * Math::PI / 180.0
終わり