本番環境でのperl/ruby/nodeのセットアップ
本番環境にperlとかrubyとかnodeを入れるんだけど、もちろん system perl じゃやってられないので指定したバージョンのものを一般ユーザの管理下に突っ込みたい。
で、そういうのをこれまで perlbrew とか rvm とか rbenv とか nvm とか nodebrew とかでやってたんだけど、さすがに色々疑問が湧いてきた。バッチで単発実行するために eval "$(rbenv init -)" とかさすがにおかしくね? みたいな。
ということで tokuhirom method 的にインストール用の簡単コマンドを使って実行、あとはパスを通せばいいじゃん、ということにしようかと思う。
参考: サーバーのセットアップは perlbrew とかじゃなくてよくね? という時のライフハック - blog.64p.org
これ、今朝までは Perl::Build をどうにかしてCPANからとってきてインストールしないといけなかったのがネックでどうしようかと思ってたんだけど、なんかお願いしたら perl-build スクリプト単体で実行可能なようにパッケージングしてくれたので超簡単になった。tokuhirom++
これだけでもよかったんだけど cpanm とか carton は確実に使う + これがあればランタイムグローバルにモジュールを入れなくてもよくなるから最初から入っててほしいよねってことで、このあたりのセットアップもついでにやってくれるようなスクリプトを適当に書いた。
(3/28追記: githubに上げた https://github.com/tagomoris/xbuild )
こんな感じで使う。
xbuild/perl-install 5.16.3 ~/local/perl-5.16 xbuild/ruby-install 2.0.0-p0 ~/local/ruby-2.0.0 xbuild/node-install v0.10.1 ~/local/node-v0.10 export PATH=$HOME/local/perl-5.16/bin:$PATH cd myproject1 cpanm -Lextlib -n --installdeps . # or carton install ... perl -Iextlib/lib/perl5 -Ilib my_script.pl # carton exec ... export PATH=$HOME/local/ruby-2.0.0/bin:$PATH cd myproject2 bundle install --path vendor bundel exec ruby my_script.rb
なお以下のスクリプトはすべてスクリプト自身があるディレクトリに bin/ や var/ を掘って使うので xbuild/ 以下に隔離して置いておくのがよい。コードの最新版については github を参照のこと。
#!/bin/bash TARGET_VERSION=$1 LOCATION=$2 if [ "x"$TARGET_VERSION = "x-h" -o "x"$TARGET_VERSION = "x--help" -o "x"$LOCATION = "x" ]; then echo "[usage] perl-install VERSION LOCATION" echo " ex: perl-install 5.16.3 ~/local/perl-5.16" exit 0 fi cd $(dirname $0) mkdir -p ./bin curl -s https://raw.github.com/tokuhirom/Perl-Build/master/perl-build > ./bin/perl-build curl -s -L http://cpanmin.us/ > ./bin/fatpack_cpanm perl ./bin/perl-build $TARGET_VERSION $LOCATION > /tmp/perl-install.log 2>&1 RETVAL=$? if [ $RETVAL != 0 ]; then echo "perl-build failed. see log: /tmp/perl-install.log" exit 1 fi $LOCATION/bin/perl ./bin/fatpack_cpanm --notest App::cpanminus Carton App::pmuninstall > /tmp/perl-install-cpanm.log 2>&1 RETVAL=$? if [ $RETVAL != 0 ]; then echo "failed to install cpanm/carton. see log: /tmp/perl-install-cpanm.log" exit 2 fi echo "perl $TARGET_VERSION (and cpanm/carton) successfully installed on $LOCATION" echo "To use this perl, do 'export PATH=$LOCATION/bin:\$PATH'."
rubyについてもrbenvとかいらねーよ、ruby-buildでいいんだけどruby-buildのインストールをいちいちやるのがめんどくさいよ、ということで完全に同じインターフェイスでえいやと書いた。
#!/bin/bash TARGET_VERSION=$1 LOCATION=$2 if [ "x"$TARGET_VERSION = "x-h" -o "x"$TARGET_VERSION = "x--help" -o "x"$LOCATION = "x" ]; then echo "[usage] ruby-install VERSION LOCATION" echo " ex: ruby-install 1.9.3-p392 ~/local/ruby-1.9.3" exit 0 fi cd $(dirname $0) XBUILD_PATH=$(pwd) if [ ! -d ./var/ruby-build ]; then ( set -e mkdir -p var cd var git clone -q git://github.com/sstephenson/ruby-build.git ruby-build-repo cd ruby-build-repo PREFIX=$XBUILD_PATH/var/ruby-build ./install.sh >/dev/null 2>&1 ) || (echo "failed to download ruby-build" && exit 1) fi ./var/ruby-build/bin/ruby-build $TARGET_VERSION $LOCATION > /tmp/ruby-install.log 2>&1 RETVAL=$? if [ $RETVAL != 0 ]; then echo "ruby-build failed. see log: /tmp/ruby-install.log" exit 1 fi $LOCATION/bin/gem install --no-rdoc --no-ri bundler pry > /tmp/ruby-install-bundler.log 2>&1 RETVAL=$? if [ $RETVAL != 0 ]; then echo "gem install failed. see log /tmp/ruby-install-bundler.log" exit 2 fi echo "ruby $TARGET_VERSION successfully installed on $LOCATION" echo "To use this ruby, do 'export PATH=$LOCATION/bin:\$PATH'."
node.jsの場合は各OSおよびCPUアーキテクチャごとにバイナリが細かく用意されててそいつを落としてきて展開するだけでいいんだけど、まあついでなのでこれも。なおこういう形にしておけば v0.10.0 -> v0.10.1 へのアップデートを同じ ~/local/node-v0.10/ というパス上で行う、というような用途のときにインストールコマンドを叩き直すだけで実行できる、というメリットもある。(これはperl/rubyも同じ)
#!/bin/bash TARGET_VERSION=$1 LOCATION=$2 ARCH=$3 if [ "x"$TARGET_VERSION = "x-h" -o "x"$TARGET_VERSION = "x--help" -o "x"$LOCATION = "x" ]; then echo "[usage] node-install VERSION LOCATION [arch]" echo " ex: node-install v0.10.1 ~/local/node-v0.10" echo " ex: node-install v0.10.1 ~/local/node-v0.10 darwin-x86" echo " default arch is 'linux-x64'" exit 0 fi if [ "x"$ARCH = "x" ]; then ARCH="linux-x64" fi cd $(dirname $0) ARCHIVE_FILENAME="node-"$TARGET_VERSION"-"$ARCH".tar.gz" ARCHIVE_DIRNAME="node-"$TARGET_VERSION"-"$ARCH set -e mkdir -p var/node-archive cd var/node-archive curl -s -O http://nodejs.org/dist/$TARGET_VERSION/$ARCHIVE_FILENAME cd .. tar xzf node-archive/$ARCHIVE_FILENAME if [ -d $LOCATION ]; then [[ -d $LOCATION.replaced ]] && rm -rf $LOCATION.replaced mv $LOCATION $LOCATION.replaced else mkdir -p $LOCATION && rmdir $LOCATION fi mv $ARCHIVE_DIRNAME $LOCATION echo "node $TARGET_VERSION successfully installed on $LOCATION" echo "To use this node, do 'export PATH=$LOCATION/bin:\$PATH'."
もうこのくらいシンプルでいいじゃんね。使うときはPATHを通す。以上。