もろず blog

もろちゃんがITに関しての様々なトピックを解説します

【在庫一掃処分セール2015】ログインできなくなったサーバーを救え!

f:id:chanmoro999:20151229163300p:plain

【在庫一掃処分セール2015】
とりあえず記事を書き始めたものの途中で何らかの理由でモチベーションが下がり放置されていた記事を掘り起こして、なんとか続きを書き切ることで 2015年に悔いを残さず新年を迎えようという企画です

この記事の途中でモチベーションが落ちた主な原因
  • 自分の問題が解決したので満足してしまった
  • 記事にするほどのことじゃないかもと思ってしまった
  • こんな状況にまず陥らないのではと気づいてしまった

さあ、そんな理由でボツになりかけていた記事をお楽しみください




この記事では
1. サーバーにログインできなくなった!
2. 解決に至るまでの頭の中
3. どうやって救ったのか
4. まとめ
について説明します


1. サーバーにログインできなくなった!

ある日僕は、VirtualBox 上で CentOS の仮想サーバーをいじっていました

そして、bash 起動時に proxy の環境変数を設定したくなり、/etc/profile.d 配下に bash スクリプトを追加しました

ところが、追加したスクリプトの処理内には無限ループになってしまうバグがありました

僕はあまりにも油断しすぎてスクリプトを単体で動かして動作確認していなかったので、そんな超絶凡ミスを犯していたことに全く気づいていませんでした


そうとは知らずに

source /etc/profile

を実行したところ、見事にシェルが反応しなくなってしまいました

こんな感じになってこれ以上全く反応しなくなります
f:id:chanmoro999:20151229145033j:plain


一瞬、何が起きたか全くわかりませんでした


/etc/profile、/etc/profile.d 以下のスクリプトbash でのログイン時に必ず読み込まれるので、
新たにログインしても同じ状況になってしまい完全詰んだ状態になりました


もはやパニックです


記事の先頭に戻る


2. 解決に至るまでの頭の中

最悪このサーバーは捨てて作り直すしかないか・・・と一度は涙目で腹をくくったんですが、なんとか復旧方法がないかを調べました


/etc/profile、/etc/profile.d が読み込まれなくすればいいはずで、どうにかしてバグがあるスクリプトが実行されないようにできればログインできるかも?と考えました

そしてググった結果、/etc/profile の設定は、sh、kshbashzsh で読み込まれるそうで、cshtcsh を使った場合は読み込まれないということが分かりました

つまり、なんとか cshtcsh からログインすることができればミスッたファイルを書き換えることができるはずです


ただ、サーバーにログインすることはできないので設定は変えられません
普通にログインしても必ず bash が起動してしまいます


そんな時に、遠い昔に LPIC の勉強をしたときの記憶が蘇ってきて、たしかブートローダーでシェルを指定できたような・・・?ということを思い出しました


それを手掛かりにググった結果、シングルユーザーモードでログインする時にシェルが指定できるということが分かりました

なので、cshtcsh を指定してログインして、バグのあるファイルを書き換えるか別の場所に移動すれば問題は解決するはずです


これでどうにかサーバーを救えそうな感じになりました


記事の先頭に戻る


3. どうやって救ったのか

ブートローダーの画面からカーネルの起動パラメータを変更して tcsh でログインできるように設定します


まず、サーバーの起動時の画面で "e" を押すとこんな画面が出てきます
ここから CentOS を選択して "e" を押します

f:id:chanmoro999:20151229142941j:plain

"kernel 〜" を選択して "e" を押します

f:id:chanmoro999:20151229143037j:plain

そうするとこんな画面に切り替わりパラメータを編集できるようになります
"quiet" の後に " single init=/bin/tcsh" と入力して "Enter" を押します

f:id:chanmoro999:20151229143316j:plain

さきほどの画面に戻るので "b" を押して OS を起動します
f:id:chanmoro999:20151229143414j:plain

すると root でログインできるようになります
bash とは使い勝手が違ってかなり違和感がありました
f:id:chanmoro999:20151229143522j:plain

問題のシェルを別の場所に移動しようとしましたが、"Read-only file system" と出て移動できません
f:id:chanmoro999:20151229143639j:plain


これは、シングルユーザーモードで起動すると、/ は Read Only でマウントされるからでした
なので、書き込みができるように以下のコマンドで再マウントします

$ mount -o remount /

たいていの場合ルートはマウントオプションが defaults になっているので、単純に再マウントすれば書き込み可能になります
※マウントの設定は /etc/fstab を参照

ちなみに、以下のコマンドでもやりたいことは同じなので問題ありません

$ mount -o remount,rw /

これで原因となっていたファイルを問題がない場所に移動することができました


その後に、" single init=/bin/tcsh" を追記した起動パラメータは忘れずに元に戻しておきましょう


再起動後には無事に bash でログインできるようになっています


これでなんとか仮想サーバーを救うことができました!


AWSでやらかしちゃった場合
ちなみに、もしこれが、EC2 で同じことをやっちゃったらどーやって直せばいいんだろう?と思って調べてみましたが、
同じようにやろうとしても EC2はシングルユーザーモードでのログインができないらしいです

なので別の方法を利用します

EC2 のデータは全て EBS に入ってるので、別の EC2 インスタンスを作って問題が起きた EBS を追加でアタッチします
そうすれば OS の領域とは別のパスにマウントできるので、中のファイルにアクセスして修正することができるわけですね



記事の先頭に戻る


4. まとめ

さて、今回は普段まずお目にかかることがないようなレイヤーの話でしたね

極論を言うと、コマンド打つときは気をつけようね、という話になってしまうんですが。。


とはいえ、人間がやることなのでオペミスが起きるのは仕方ありません


どういうわけか人間は

$ rm -rf / 

というような破壊の呪文を唱えてしまう生き物なのです

そして、大抵の場合、その時のことは全く覚えていないのです
まるで何かに取り憑かれていたかのように


なので、

  • オペミスが発生する原因を排除する
  • 問題が発生してもリカバリできるようにしておく

というのはインフラに限らず大切なことですね
フールプルーフとも言いますね


仮想サーバーや特にクラウド上のリソースを使う場合は、Immutable Infrastructure 的な考えで構築することが重要だと思ってます

サーバーは使い捨てるものと考えて、ぶっ壊れてもすぐに全く同じものを用意できるようにしておくという感じでしょうか


そんな感じで今回は、緊急時にサーバーを救う方法について書きました

皆さんもこんな事にならないように気をつけましょう・・・


記事の先頭に戻る