日常的に使うコマンドも本番環境では気をつけなきゃいけないよねって話

# はじめに

[Ateam cyma Adevent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-cyma) の 13日目です。
本日は、株式会社エイチームEC事業本部cymaのエンジニア@ihsiekが担当します。

「[本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production)」が大好評ですね。
最近はCI/CD環境が充実して本番環境にシェルアクセスする機会が減っているのと、他人(他社)の失敗談は同じ轍を踏まないようにする転ばぬ先の杖になるということで若手のエンジニアほど、こういう失敗談を読んでほしいと思っています。

ということで、私が前職でやらかしたリスクをまったく認識していなかったオペレーションによる本番環境での失敗談を書きたいと思います。

# TL; DR

* Linuxコマンドの`--force`オプションを使う場合は使用するバージョンの挙動を確かめて使ったほうがよい。
* 本番環境での動作検証はダメ、ゼッタイ。
* OSのアップデート運用は必要。
* 他人の失敗談を自身の糧にできる「[本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production)」はオススメなのでぜひともいろんな人に読んでほしい。

# 起こったこと

* NAS(Network Attached Storage)上に格納されていたファイルが突如消失した。

# 経緯

## 前日

* とあるシステムのリリースを実施
    * 当時CI/CD環境などはなく、gitコマンドでmasterをpullしたあとBuildする運用でした。
    * 理由は忘れましたが、このリリースだけ、前断面のディレクトリごとバックアップをとっておいて、バックアップをcpコマンドでロールバックする手順にしていました。
* バックアップが正常に機能することを検証するために、`cp -rf [バックアップ] [リリース先]`を実行
* 再度、リリースして無事動作検証が完了したため帰宅

## 当日

* 現場のメンバーから電話による問い合わせ
    * 「NASに上げたはずのファイルが過去数年分無くなっているんだけどなんで？」とのこと。
* 調査するも原因不明
    * NASにファイルへのアクセスログが残る様になっていたため確認したところ、前日のリリース時刻付近にファイルを削除した履歴が残っていました。
    * そもそもファイルを削除するようなコマンドを実行していないので、心当たりなどあろうはずもなく、しばしファイルのアクセスログを精査することに。
    * よくよく観察して、本番サーバからシンボリックリンクを貼ったファイルだけが消えてそれ以外は残っていること、アクセスログからcpコマンドっぽい挙動であることが確認できたため、実験してみる。
        * /tmpに適当なディレクトリ(/tmp/hoge)を作成
        * シンボリックリンクを貼ったディレクトリとファイルを用意
        * `cp -rf /tmp/hoge /tmp/hoge`を実施
        * シンボリックリンクを張ったディレクトリの中身が丸々消えたことを確認
* 原因特定へ
    * `cp -rf`が悪さをしているっぽいので`man cp`で`-f, --force`オプションの仕様を確認してみて原因がわかりました。

# 解説

以下、発生環境で`man cp`した結果です。

```text
　ファイルをそれ自身にコピーしようとした場合、(エラーメッセージを出す以外は)何もしない。
　既存のファイルにコピーする場合、コピー先のファイルは‘open(path,O_WRONLY|O_TRUNC)’で開かれる。
　新規ファイルにコピーする場合、新規ファイルは‘open(path,O_WRONLY|O_CREAT,mode)’で作成される。
　コピー先のファイルが存在し、かつ-fオプションが与えられている場合にこの形式でのファイルのオープンに失敗すると、
　cpは既存のファイルの削除(もしくはアンリンク)を試みる。
　そして、削除に成功した場合は新規ファイルへのコピーとして命令を続行する。
```

下から2行目にありますが、シンボリックリンクの先はバックアップとリリース先とで同一ファイルを見ているので、

1. ファイルのオープンに失敗
2. 既存のファイルを削除
3. 新規ファイルへのコピーとして命令を続行
4. 2でコピー元ファイルが消えているため、3に失敗

というのが事の顛末だったようです。
ちなみに、cpコマンドの挙動はディストリビューションごとに異なるようですが、ちゃんとバージョンアップをしていれば、当時であってもこのような問題は発生しなかったことを確認しています。

# まとめ

cpコマンドを単なるコピーコマンドだし大丈夫だろうと油断していたことと、本番でしか検証するすべを用意していなかったこと、OSのアップデート運用を徹底できていなかったことが招いたトラブルだと思います。
ここで得た私の教訓は以下のとおりです。

* ディストリビューションごと、バージョンごとにコマンドの挙動が異なる前提を認識しましょう。
* `-f, --force`オプションは極力使用を避け、必要な場合は仕様を確認して使用しましょう。
* 本番環境でしか検証できないはNG, 本番環境のコピーを作るなどして検証できる場を作りましょう。
    * AWS, GCPのようなサービスを使用していれば、コピーしたイメージから本番環境のダミーを簡単に作るのがオススメです。
    * コンテナオーケストレーションやっていると厄介かもしれないと思ったけど、そもそもコンテナ運用していたらこんな問題に遭遇しませんね。
* OSのアップデート運用は必要なので、計画的にやりましょう。

# おわりに
[Ateam cyma Adevent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-cyma) の 13日目、いかがでしたか。
前職の話なので、いまの職場だとありえない内容だなと思いながら振り返りましたが、同じ轍をみなさんが踏まないことをお祈りしています。
あとは当時の関係者の皆様、大変ご迷惑をおかけいたしました:bow_tone1:

また、他人の失敗を自身の糧にしてほしいという意味で「[本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production)」は本当にオススメなので、本番運用を経験したことがない人を含めいろんな方に読んでほしいと思っています。
明日はちょっとおちゃめな帰国子女な新卒エンジニアの @namedpython さんです。
データ分析基盤をしっかりと作り上げる期待の新人の投稿を楽しみにしています。

株式会社エイチームでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。

エンジニアとしての働き方に興味を持たれた方は[cymaのQiita Jobs](http://bit.ly/35E1I08)をご覧ください。

そのほかの職種は、[エイチームグループ採用サイト](http://bit.ly/2XQpd3q)をご覧ください。