capistranoでdeployしたらdeployしたものをdeleteした話

あ…ありのまま 今 起こった事を話すぜ!
『おれはcapコマンドでdeployしたと思ったらいつのまにかソースコード一式が消えていた』

な… 何を言ってるのか わからねーと思うが
おれも何をされたのかわからなかった…

頭がどうにかなりそうだった…
催眠術だとか超スピードだとか
そんなチャチなもんじゃあ 断じてねえ

もっと恐ろしいものの片鱗を味わったぜ…

(AA省略)

ということがあったので、こんな人はあんまりいないと思いますが、自戒の意味を込めて投稿しておきます。

事象
capistranoのリリースフォルダのcleanup処理にて、今回リリースしたバージョンを含めて全てrmしてしまう

原因
deployまえに/etc/profileにこんなechoを追加したのが原因でした

echo "*****************************************"
echo "* 本番サーバです注意してください            *"
echo "*****************************************"

そして、capファイルには以下のように設定されていました。

default_run_options[:shell] = '/bin/bash -l'

これをやってしまったがために、ls -xtでリリースフォルダの一覧を取得する処理で、結果が混ざってしまいました。
-lオプションはログインシェルとして起動させるオプションです
これにより非対話的なシェルでもログインしたときと同じような環境を再現できます。

/etc/profile編集前
executing `ls -xt’
20121019053647 20121019053641

/etc/profile編集後
executing `ls -xt’
*****************************************
* 本番サーバです注意してください *
*****************************************
20121019053647 20121019053641

capistranは改行かスペースを区切りにして、ファイルをカウントします。この場合メッセージ部分だけで、5ファイルだと認識してしまうため、今回deployしたフォルダをrmしてしまいます。(デフォルトの保存世代は5世代)

どうすればよかったのか

    • ログインするユーザーへの通知は/etc/motdを使う

/etc/motdに書けば-lオプション付で実行されても問題ないです

    • 安易に-lオプションを付けない

-lオプションは確かに便利です。rvm、rbenv等のユーザ環境で構築したrubyを実行する場合、環境変数等の煩わしい設定から解放されます。
ただし、-lオプションは/etc/profile→~/.bash_profile→本来のコマンドという流れで実行されることを認識すべきでした。

起動ファイルの読み込みについて
ついでに、/etc/profile、/etc/profile.d/、/etc/bash.bashrc、~/.bash_profile、~/.bash_login、~/.profile、~/.bashrc等の読み込みとか役割とかをまとめておきます。
※今回はbashのみ

    • /etc/profile

ログインシェル※1として起動した場合に最初に読まれるファイル。これはbashに限らず大抵のシェルはこれ読みます。bash依存のコードを書いちゃいけません。書く場合はちゃんと判定すること。

    • /etc/profile.d/

/etc/profileから順次呼び出され、実行されるスクリプトを格納するディレクトリです。bash_completion.shとか置かれます。これはbashの仕様に関係なくただ、/etc/profileがそこを見ているだけです。

    • /etc/bash.bashrc

これも/etc/profileから呼び出されるシェルです。環境によっては無いかもしれないです。ログインシェルがbashだと呼び出すので、/etc/profileに書きたいけど、bash依存のコードだしなぁ・・・というときはこっちに書きます。

    • ~/.bash_profile

こちらは/etc/profileを読み込んだ後にbashが探す個人用の設定です。/etc/profile読み込み後は~/.bash_profile, ~/.bash_login, ~/.profileの順番で探します。
よく勘違いするのが、~/.bash_profileと~/.bash_login両方があった場合、~/.bash_loginは読まれません。/etc/profileの次の個人設定を1個でも読んだらそれ以降は読まないみたいです。

    • ~/.bash_login

~/.bash_profileが無かった場合こちらを探します。あれば読みません。bash固有の設定を書くと良いんじゃないでしょうか

    • ~/.profile

こちら大抵のディストリだと/etc/skelの中に入っていてデフォルトである設定ファイルです。中を見ると分かるのですが、こいつが.bashrcファイルを呼びます。←ここ重要
普通ログインした場合は.bashrcは読み込みません。ログインシェルが呼び出す~/.profileに.bashrcを読み込む設定が書いてあるので、bashrcはいつも呼ばれると錯覚しますがそうではないのです。
なので、何も知らずに~/.bash_loginをつくるとbashrcが呼ばれなくなるので注意です。後このファイルはbashに限らず他のシェルも読み込みます。bash依存のコードはかけません

    • ~/.bashrc

大抵の人がbashが起動する時はいつも呼ばれると思っているファイルです。こちらは対話的な非ログインシェル※2で呼ばれた時のみ読まれます。
非ログインシェルはprofile等のシェルを読みません.bashrcだけです。

※1ログインシェルは「sshとかtelnetでログインしたときに起動するシェル」、「非対話式シェル呼び出しだが、-lオプションを付けた場合」、「su – hogehogeみたいにスイッチしたときのシェル」のこと
※2非ログインシェルは「sshとかtelnetでログインした後にbash等のコマンドで呼ばれたシェル」、「su hogehogeみたいにハイフンなしでスイッチしたときのシェル」のこと

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

yamasita

東京電機大学工学部→3年間某SIerにて銀行システムの開発→bpsに入社→TechRacho外部ライター

yamasitaの書いた記事

インフラ
現場で使うansible

2014年12月25日

関連する記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ