タイポで本番事故が起きる理由|似た名前・全角・コピペと防ぎ方
1 文字の違いはエラーになるとは限りません。似た名前、全角、コピペ、履歴。タイポが静かに通ってしまう仕組みと、打ったものを確かめる習慣を説明します。
タイポ(打ち間違い)は、誰にでも起きる小さなミスです。開発環境なら、エラーが出て打ち直すだけで済みます。本番環境で怖いのは、タイポがエラーにならずに「別の正しいコマンド」として通ってしまう場合です。ベテランはタイポをしないのではなく、タイポが起きる前提で、打ったものを確かめる手順を持っています。この記事では、タイポが事故になる仕組みと、その場で真似できる確認の習慣を整理します。
タイポがエラーにならず通ってしまう仕組み
存在しないコマンドやファイル名を打てば、シェルは command not found や No such file or directory を返して止まります。この場合、被害はありません。危ないのは、打ち間違えた結果が「たまたま実在する別のもの」と一致したときです。コンピュータは意図を知らないので、正しい入力として実行します。
| タイポの例 | 実際に起きること |
|---|---|
| db-prd-01 のつもりで db-prod-01 | 古い別名や別のサーバーに接続でき、そこで作業が完了したように見える |
| crontab -e のつもりで crontab -r | e と r はキーボードで隣り合い、-r は crontab を確認なしで全削除する |
| WHERE id = 1024 のつもりで 1042 | 1042 番の行が実在すれば、別の顧客のデータが書き換わる |
| > のつもりで >>、または逆 | > は既存ファイルを空にしてから書き込み、前の内容が消える |
| git push origin HEAD:feature/loign | リモートに無いブランチ名でもエラーにならず、新しいブランチとして作られる |
bash の変数名の打ち間違いも同じ種類の問題です。TARGET_DIR を TARGTE_DIR と打つと、未定義の変数は既定で空文字に展開され、エラーにはなりません。スクリプトの先頭に set -u を書くと、未定義の変数を使った時点でエラーとして止まります。
TARGET_DIR=/var/app/cacheecho "$TARGTE_DIR" # 空行が出るだけでエラーにならないset -uecho "$TARGTE_DIR" # bash: TARGTE_DIR: unbound variableタイポが起きやすい場面
似た名前と、手で打つ ID
本番と検証のホスト名は、prd と stg、01 と 02 のように数文字しか違わないことがよくあります。テーブル名も user と users、order_items と order_item のように、単数形と複数形の両方が存在することがあります。数字の 0 と英字の O、数字の 1 と英字の l は、フォントによっては見分けにくい組み合わせです。ID や伝票番号を画面から目で読んで手で打つと、桁の入れ替わりが起きやすくなります。
全角スペースや全角記号の混入
日本語入力をオンにしたままコマンドを打つと、全角スペースや全角のハイフン、引用符が混ざります。bash は全角スペースを区切りとして扱わないので、ls -l は「ls -l」という名前の 1 つのコマンドとして探され、見つからずにエラーになります。エラーになるうちはまだ安全で、SQL の文字列リテラルの中に全角文字が入った場合は構文としては正しいため、WHERE が 1 件も一致せず「0 件更新」で終わり、作業が済んだと誤解することがあります。
補完と履歴の呼び出し違い
Tab 補完は打ち間違いを減らしますが、候補が複数あるときは共通する部分までしか補完しません。releases と releases-old があるディレクトリで releases まで補完された状態から、残りを確かめずに Enter を押すと、意図と違う対象になることがあります。上矢印キーや Ctrl+R で過去のコマンドを呼び出す場合も、似たコマンドが履歴に複数あると、引数だけが違う古い行を選んでしまいます。
コピペで欠ける、混ざる
チャットや文書作成ソフトから貼り付けたコマンドは、引用符が “ ” のような装飾付きの文字に変わっていたり、-- が長いダッシュ 1 文字に置き換わっていたりすることがあります。範囲選択で先頭や末尾の 1 文字が欠けたり、前後の行まで一緒に選択したりすることもあります。改行を含む複数行を貼り付けると、端末の設定によっては貼り付けた瞬間に行ごと実行されます。
慣れによる読み飛ばしと、自分の文字は正しく見えること
毎日打つコマンドほど、指が先に動き、目は形だけを見て通り過ぎます。さらに、自分で打った文字列は、何を打とうとしたかを知っているため、実際の文字ではなく意図を読んでしまいがちです。文章の誤字を本人が見つけにくいのと同じ理由で、見直しを 1 回しても気づかないことがあります。ダブルチェックで別の人が読むのは、意図を知らない目で文字そのものを読むためです。
本番で特に危ない 5 つの場所
コマンドのすべての文字を同じ注意で読むのは現実的ではありません。ベテランは、1 文字違うと影響が大きい場所に絞って、文字単位で読みます。
| 場所 | 1 文字違うと起きること | 読み方 |
|---|---|---|
| ホスト名・DB 名 | 本番と検証を取り違える | 接続後にプロンプトや hostname で確かめる |
| WHERE の値 | 別の行を更新・削除する | 同じ条件の SELECT で対象の行を見る |
| パス | 別のディレクトリを消す・上書きする | 末尾のスラッシュと空白まで読む |
| リダイレクト先 | > で既存ファイルが空になる | > と >> を区別し、出力先のファイル名を読む |
| ブランチ名 | 新しいブランチができる・別のブランチに push する | git branch や git status で現在地を確かめる |
パスでは、rsync の末尾のスラッシュが 1 文字で意味を変える例があります。rsync -a src/ dst/ は src の中身を dst に、rsync -a src dst/ は src というディレクトリごと dst の下にコピーします。--delete を付けている場合は、この違いで削除される範囲が変わります。
打ったものを確かめる習慣
Tab 補完を使い、補完結果を目で読む
長いパスやファイル名は手で打たず、Tab 補完を使います。補完は実在する名前しか出さないので、存在しない名前のタイポは防げます。ただし補完が止まった位置から先は自分で選ぶ必要があるため、Tab を 2 回押して候補を表示し、どれが選ばれたかを最後まで読んでから Enter を押します。
値は変数に入れて、echo で確かめる
同じホスト名や ID を何度も使う作業では、最初に変数へ入れて表示し、以後は変数を参照します。打つのが 1 回になるので、途中の行で打ち間違える機会が減ります。od -c で 1 バイトずつ表示すると、全角スペース(343 200 200)や制御文字など、画面では見分けにくい文字に気づけます。
HOST=db-prd-01ORDER_ID=1024printf '%s' "$HOST" | LC_ALL=C od -c # 全角スペースなどが混ざっていないかmysql -h "$HOST" app -e "SELECT id, customer_name FROM orders WHERE id = $ORDER_ID;"コピペした後は、貼り付けた内容を読む
ID やホスト名は、手で打つより元の画面からコピーするほうが確実です。ただし貼り付けた後に、先頭と末尾が欠けていないか、引用符やハイフンが変わっていないかを読みます。新しい bash(5.1 以降)や zsh では、貼り付けた文字列を Enter を押すまで実行しない bracketed paste が既定で有効です。手順書のコマンドは、ブラウザの装飾付き表示ではなく、プレーンテキストやコードブロックからコピーします。
プロンプトに環境を出し、読み上げる
ホスト名のタイポや窓の取り違えに気づくには、今いる環境が常に目に入る状態にします。本番サーバーではプロンプトにホスト名を出し、背景色を赤にするなど、検証環境と見た目を変えておきます。実行前には、ホスト名・対象・値を声に出して読み上げると、目で流し読みしていた箇所に気づきやすくなります。
PS1='\[\e[41;97m\][PRD \u@\h \W]\[\e[0m\]\$ '--dry-run と SELECT で影響範囲を先に見る
多くのツールには、実際には変更せずに何が起きるかを表示する機能があります。タイポがあっても、表示された対象を見れば「思っていた件数・ファイルと違う」と気づけます。
rsync -a --delete --dry-run src/ dst/ # -n でも同じgit push --dry-run origin feature/logingit clean -n -dmake -n deploySQL では、UPDATE や DELETE と同じ WHERE で先に SELECT を実行し、返ってきた行の名前や件数が想定と合っているかを見ます。ID を打ち間違えていれば、別の顧客名が表示されるので、そこで止まれます。
bash で set -o noclobber を有効にすると、> で既存のファイルを上書きしようとしたときにエラーになります。意図して上書きするときは >| と書きます。>> と打つつもりで > を打つタイポへの保険になります。
チャットや手順書のタイポは、読んだ人の作業を誤らせる
タイポは自分の端末の中だけで起きるものではありません。手順書のホスト名が 1 文字違っていれば、それを読んだ人が正しく打つほど誤った場所で作業します。チャットで「stg で確認お願いします」と書くつもりが prd になっていれば、相手は本番を操作するかもしれません。書いた本人は意図を知っているので、読み返しても気づきにくいのは端末と同じです。
- 手順書のホスト名・DB 名・ブランチ名は、実際の画面や設定からコピーして書く。
- 環境名(本番・検証)は略語だけにせず、「本番(prd)」のように日本語でも併記する。
- 誤りに気づいたら、「訂正:」として誤った値と正しい値の両方を書き、元の投稿も直す。
- 誤った値ですでに作業した人がいる可能性があれば、その戻し方まで書き添える。
「typo」や「*login」のような短い訂正だけでは、どこがどう違ったのかを読む人が推測しなければなりません。正しい値をそのままコピーできる形で書くことが、訂正のいちばんの目的です。
タイポを事故にしないためのチェックリスト
- ホスト名・DB 名は、接続後のプロンプトや hostname、\conninfo で確かめたか。
- ID・ホスト名は手で打たずにコピーし、貼り付けた内容を読み直したか。
- 日本語入力がオフになっていて、全角スペースや全角記号が混ざっていないか。
- Tab 補完や履歴で呼び出したコマンドの引数を、最後まで読んだか。
- UPDATE・DELETE の前に、同じ WHERE の SELECT で対象の行を見たか。
- --dry-run など、変更せずに影響範囲を表示する方法を先に使ったか。
- 手順書やチャットに書いた値を、送る前に元の画面と突き合わせたか。
タイポは注意力だけでは無くせません。打つ回数を減らし、打ったものを実行前に表示して読む手順にしておけば、1 文字の違いは事故になる前に見つかります。下の問題で、1 文字の違いを見抜けるか確かめてみてください。
問題で確かめる
この記事の内容を、制限時間つきの問題で確かめられます。