本番環境でやらかしたことまとめ(昔)

# あっ! やっちゃった。どうしよう。。
ちゃんとお客さんに報告してから作業に入ればよかった。
急いで対応して欲しいって言ってたから気を利かせて修正しただけなのに。
コマンド一つで終わるはずだったのに。。
まさかバックアップがきちんと取れていないなんて。

サーバーの再起動に失敗してから早15分
手元の携帯にはエラ〜メール次々と飛んでくる。
データは破損し、上司は不在。
明日は休日、時刻は終電。
向かうは事務所かDC(データセンター)か。

# これは何?
みなさんこんにちは。ETOの江藤です。

これは[株式会社やどかり & 株式会社ネッコス Advent Calender 2021の5日目](https://qiita.com/advent-calendar/2021/yadokari_qiita)の記事です。
昨日は竹内さんです。
明日は川上さん(@mame3 )がもっと楽しい話をしてくれるでしょう。

Y氏から「テーマとか決めないんですか? 本番環境でやらかした話とかでいいんじゃないですか/」
とか言われたので書いてみました。

# 焦った時に頭の中に流れる曲ってありますか?

いきなりどうでもいい話ですが、
僕は大体[Paul Oakenfold - zoo york](https://www.youtube.com/watch?v=PDrlOlTPKDs)のサビの部分が頭の中でグルグルしてます。

# 本番じゃないけどよくやるやーつ

まずは手始めに、本番じゃなくてもうっかりミスしちゃうやつです。

### githubでやっちゃった

#### git で add したやつをアンステージしようとして変更箇所まで吹っ飛ばしてしまう。

```shell
$ git add .
$ git status

... 大量の差分 ...

あ、いけない。node_modulesは除外しなきゃ!

$ git reset --hard
# アンステージどころか修正分まで元に戻る

# ぎゃああ! 一時間の作業がぁ😭
```

いまだにアンステージする時はドキドキします。
`git status`に表示されるアンステージの仕方に従うのが確実ですね。
最近、`git restore`になって分かりやすくなりました。

#### 色々修正したけど一旦全部戻したい -> 必要だった修正までもとに戻してしまう

```shell
$ 最初にいくつか設定を変える。(これは必要な変更)
$ 色々いじったり戻したりする

$ git status
... たくさんの変更ファイル ...

# 一旦きれいにしよう!
$ git checkout .

# ぎゃああ! 最初の変更まで消しちゃった!
```

### ファイル移動でやっちゃった

これもよくあるんじゃないでしょうか。

#### バックアップしたつもりがしてなかった

```shell
# ちょっとログをいろいろ整形したい
$ mv ./data/01.txt /tmp # 加工したら戻そう

# いろいろ grep したり加工したり。。

# やっぱ元のままでいいや。
$ rm -f /tmp/01.txt

$ ls -l ./data/01.txt
> no such a file or directory.

# あ、あれ? コピーしてなかった??
```

#### コピー先とコピー元のパスを間違える

最近はもうめっきり `rsync`を使わなくなりましたが、まだ`scp`は使うので気を使います。

```shell
# 本番サーバーにアップしよっと! (10年くらい前)
$ rsync -(もうオプション忘れたけど削除とかするやつ) 本番のパス ローカルのパス

# ぎゃああ! 手元の修正ファイルが消えちゃった! (まだgit普及前)
```

反対にログを落とそうとして消しちゃうなんてことも。。

#### ディレクトリとファイルがごっちゃになる

転送系コマンドでは `directory` なのか `directory/` なのか `directory/*` なのかで意味が代わってくるため、適当にやってしまうと大量のファイルが一つのディレクトリに混ざったりします。

### これらの対策

- rsyncは必ずdry-run (-n)するべし!
- 転送系コマンドは src -> dst と覚えるべし!
- ディレクトリを移動する時は 対象directory を このdirectory/ の中におく、と覚えるべし!
- ログなどを転送するにはtmpに固めてからscpするべし! (srcとdst間違えても消えることはない)

# 本番でやっちゃった系

さて、ここからが本題です。

## データセンター編

今はもう物理サーバーを触ることはありませんが、昔は1UのラックサーバーにCentOS5をインストールして
電車で二駅のところにあるデータセンターに運んで配線してルータの設定とかしていました。

### データセンターを出た瞬間にエラーが飛んでくる

不器用な素人が配線すると、まあ扉を閉めたりルータをちょっと動かしただけでどこかしら別の配線が抜けてたりしました。
なので、サーバーを設置して5分くらいサーバールームの雰囲気の無機質さを楽しんでから事務所に戻るようにしてました。

### 爆睡してて電話に気づかない
まあ、これは人間だから仕方ないですね。
朝4時にアラートメールがやってきて、朝5時にリーダーからの電話に気づいて、「すみませんーと言いながらデータセンターに行きましたとさ。

### 事務所から誤ってシャットダウンしちゃった

データセンターにおいてあるサーバーにはsshで接続して作業しますが、
初期設定などをしていると手元のサーバーと勘違いして、シャットダウンしちゃうこともありました。
(まあ、サービス稼働中のサーバーと一緒に作業することはまずないので帰り際にDCによって電源ボタン押すだけではありますが)

それにしてもなんで `sudo shutdown -h now`ってあんなに達成感があるんでしょう、

### 再起動コマンドとシャットダウンコマンドを間違える

再起動は `sudo shudwon -r now` なので間違えやすいかもしれません。
間違えやすい故に `reboot` コマンドがあるのでそちらを使います。

再起動コマンドを叩く時は「どうか無事に起動しますように」とお祈りしながら叩くので、この失敗は本番環境ではないですかね。

## リモート編

データセンターとは特に関係ないやーつです。

### 接続先を勘違いする

これはよくやりました。というか今でもよくやります。
なので、よく使うサーバーならプロファイルの色やプロンプトのフォーマットを変更したり、
一時的に複数繋ぐ場合はターミナルやタブの位置を固定して、
今どのサーバーで作業しているのかごっちゃにならないようにしています。

### バックアップが取れていなかった

慣れた時ほど危ない、の典型的なパターンです。
同じようなプロジェクトを複数こなして、DBやプログラムや設定ファイルのバックアップがいつも通り大丈夫だよね。
となった時ほど問題は起こります。

バックアップファイルがあっても、いざ復元しようとしたら文字コードが正しく設定されていなくて文字化けしていたり、
ファイルはあるのに中身がほぼ空だったりしたことがありました。

日頃から避難訓練はしておかないと、いざという時、「あれ?あのファイルは??」となってしまいます。

### cronを消しちゃった!

これはちらほらやらかす人はいました。

```shell
# cronの設定を確認しよう

$ crontab -l
# あ、cronの設定ちょっと変えなきゃ

$ crontab -r
# あ!
```

cronを編集するオプションが `-e`なのですが、
キーボードをよく見ると `e`の一つ右には `r`があり、`r`は削除なのです。。

#### 対策

エイリアスを張りましょう!


## 炎上編

今まさに負荷が上がりサーバーが落ちようとする時。
そんな時こそ冷静さが必要とされるのです。

### 不用意に重たいコマンドを叩いて落としてしまう

「サイトが凄く重たいです」
そう言われてsshでログインする訳ですが、大体接続するのに30秒くらいかかったりします。
そんな時に、不用意に`top` とか叩くとインフラ出身の怖い人に怒られます。

メモリを食いつぶしてスワップ使っているのか、それともDBが詰まっているのかにもよりますが、
依存関係に応じて、バッチを止める -> アパッチとめる -> DB止める　などする費用があります。

下手にいじるとデータの整合性がずれて復旧が面倒になるので、やはり事前の防災訓練は欠かせません。

### 前のバッチが終わる前に次のバッチが走っちゃった!

データ量が多くなってくるとそうなりますね。
今はクラウドに逃せば良いですが、最適化や設計やら意外と大事な部分だと思います。

### レプリケーションずれちゃった

とあるプロジェクト。
Webサーバーは100台近くあるのに、マスターDBは2台という構成。

「ここに80GBのデータがある。データ移行して欲しい。許された時間は15分」
というリプレイス作業に向けての準備を進めていました。

そもそもデータのエクスポートやインポートに30分くらいかかり、それに対してレイアウトの変換も必要でした。
通しでやると一回8時間くらいかかりました。
そのため、古いデータを事前に変換しておき、PL/SQLでリアルタイムに変換しておいたら良いのでは? ということでいろいろ試していました。

移行先用に新しいおはげスペックのサーバーが与えられ、
本番との同期は取れていますが独立はしているので、万一移行先DBがダウンしても影響は全くありません。

安心して数百行のクエリを投げつけていました。
ところがだんだんとテーブルロックの時間が長くなっていき、
process listの処理待ちの数も増えていき、
まあ、でもマスターDBには負荷はかかってないし、移行先のサーバーはお化けスペックだから大丈夫かなー
とか思っていたら突然process listから全てのプロセスが消えました🥶

やってしまったか?
と思いましたが、インフラ部隊の方でアラートが出たようでレプリケーションを外されてしまいました。
(マスターから移行先DBへのレプリケーションがずれたとのこと)

まあ、大事にならなくてよかったですが、ひやっとした瞬間でした。

##　いたずら編

これはもう15年くらい前の話です。
当時、ウェブサイトの会員登録は「ここに空メールを送信」というところから始まりました。
携帯からメールを送ってくるのだから fromを見ればそのメアドは実在するよね。という認証方法です。
そして、「空メール」を送信すると、そこに登録先URLの記載されたメールが自動的に返信されるのが一般的でした。

さて、ここに「空メールを送信」のサイトが二つあるとします。
(`info@example1.com` と `info@example2.com`)

さて、サイト1に対して、fromを`info@example2.com`にしたメールを送ったらどうなるのでしょう?
気になりませんか?
気になりますよね?

というわけで、当時phpで簡単に暗号化されていないメールが送信できましたので試してみました。
すると、、、(まあ、案の定な結果に)

# まとめ
いかがでしたか?
いずれも6年以上前の話で、昨今はクラウドの普及もありだいぶ楽になったように思います。

というわけで、他の方もよかったらぜひやらかしちゃった話を書いてみてくださいね。
僕も書いたんですから。