はじめに
初めまして、髙橋と申します。
新卒2年目になり間もない頃、インスタンスのCPU使用率をCSVファイルで取得し、古いデータを削除して新しいデータを格納するためのshellスクリプトを作成するというタスクがありました。
しかし、変数名を変更したことが原因で、予期しない事態が発生してしまいました。
今回はその事故の詳細と教訓を共有します。
事故の背景
やりたかったこと
特定のディレクトリのファイルを削除し、各インスタンスのcpu使用率のデータをCSVファイルで出力するshellの作成
作成したスクリプト
以前似たようなshellスクリプトを書いていたので、そのスクリプトをコピーして作成しました。
完成したコードがこちら
#!/bin/bash
LIST_FILE="/xxx/data/hosts.csv"
EXPORT_DIR="/xxx/data/cpu"
# ファイル削除
rm -rf $EXPORT_DIR/*
cat $LIST_FILE | while read TLINE; do
/yyy/get_ec2_cpu_info_test ${TLINE}
done
このスクリプトの目的
-
EXPORT_DIR
に保存されている古いデータを全削除 -
LIST_FILE
に記載されたホスト情報を一行ずつ読み込む -
/yyy/get_ec2_cpu_info_test
を実行し、新しいデータを取得&格納
これは特に問題もなく動作しました。順調。
事故発生3分前から発生まで
EXPORT_DIR
よりも DEL_DIR
の方が変数名として適切じゃね?と思い、変数名を変更しました。
(スクリプトをコピペしてきたので変数名がそのままになっていた)
…で、完成した特級呪物がこちら
#!/bin/bash
LIST_FILE="/xxx/data/hosts.csv"
DEL_DIR="/xxx/data/cpu"
# ファイル削除
rm -rf $EXPORT_DIR/*
cat $LIST_FILE | while read TLINE; do
/yyy/get_ec2_cpu_info_test ${TLINE}
done
おわかりいただけただろうか
変数名は DEL_DIR
に変更されたものの、rm -rf $EXPORT_DIR/*
の部分の修正が漏れてしまいました。
つまり、EXPORT_DIR
に新しい値がセットされていないため、このコマンドは次のように実行されることに…。
rm -rf /*
※rm -rf /*
は、ファイルシステム内のすべてのデータを警告なしで削除する命令
…という訳で実行した結果、開発環境の全ファイルが吹き飛んでしまいました。
ちなみに、全ファイルが消えるとこうなります。マジで何もできません。
参考記事
発生した被害
前日までのデータ
バックアップとしてAmazon Machine Image(AMI)を取得していたため、前日までのデータは無事復旧することができました。
当日分のデータ
rm
コマンドで全ファイル(OS設定関連のファイル含む)が削除されてしまうと流石に復旧できません。全部消えました。
ちなみに、僕のほかに作業者が2名いました。1人はVSCodeのエディタ上にコードが残っていたので実質無事でしたが、もう1人の作業分は完全に消えてしまいました。
(社会人人生で一番謝りました)
対策・対処方法
この事件以降、対策として実施しているものを5つ紹介します。
1. 変数の置換は必ず抜け漏れが無いようにする
変数名の置換を行う際は、単純な手作業で変更せず、エディタの検索・置換機能(Ctrl+h
など)を使って全ての参照箇所が漏れなく修正されているかを確認しましょう。
修正が漏れると今回のようなことが起こるかもしれません。
2. パスに*
を含めたい場合、理由がない限りパスを分割しない
パスに*
を含める場合、リスクを最小限に抑えるため、パスを極力分割せず完全なパスで指定しましょう。
3. 変数の値がセットされているか確認するスクリプトを挟む
変数に値がセットされているかを確認する簡単なスクリプトを挟むことで、誤った変数が参照されることを防ぐことができます。
サンプルコード
if [ -z "$EXPORT_DIR" ]; then
echo "ERROR: EXPORT_DIR is not set"
exit 1
fi
4. 不可逆なコマンドを実行する前は入念に見直す
rm -rf
のような不可逆なコマンドを実行する前にスクリプトを数回確認し、意図しない結果が起こらないか確認しましょう。
5. 日ごろからバックアップを取得する
この対策は事件以前にも行っていました。前日分までのデータを復旧できたのもバックアップのお陰です。バックアップ、大事。
おわりに
rm -rf
なんて誰が実行するねんと思っていましたが、まさか自分がやるとは思っていませんでした。以降はこのような事が無いように、前述した対策を実行しています。
スクリプトやコードを書いたときは「よし! 完成!」と思いがちですが、少し立ち止まってコードを見直すことが大切です。皆さんは既に意識されているかもしれませんが、僕と同じ轍を踏まぬよう改めて意識してみてください。
ここまで読んでいただきありがとうございました!