この記事はAIで生成していますが、
その方が面白くわかりやすい文章になると判断したためです。
内容はすべて事実に基づいています。
今回の出来事自体、AIでトラブルシュートして解決しており
最後にその内容を記事にしてもらいました。
前提
対象のサーバーはOracle Cloud上にあるRocky Linux 9です
TL;DR
- すべてのアプリを .NET 10 へ移行完了 🎉
- 大き目のファイルを生成する新規アプリを開発した
- 不要になった .NET 9 を削除して容量を空けようと焦る
- ログインシェルが PowerShell(.NET 9 依存)だった
- SSH接続 → 即切断
- 「\(^o^)/オワタ」
- GRUB → シングルユーザーモード → シェル修正
- 復旧
サーバは壊れる。復旧経路は作っておこう
事象
ある日いつものようにSSHしようとしたら:
- ping → 通る
- ポート → 開いてる
- SSH → 接続直後に切断
「ネットワークは生きてるのに入れない」という一番イヤなやつ。
しかも数日前までは普通にログインできていた。
私について(少し変わった前提)
私は .NET 推しである。
そして PowerShell をログインシェルにするタイプの人間 である。
普通はやらない。
やっている人はたぶん少数派。
でも好きだから仕方ない。
「bash で入って pwsh を起動」ではなく
「最初から PowerShell で生きる」。
そんな運用をしていた。
この時点でフラグは立っていた。
発端(祝・移行完了 → そして焦り)
この日、私は達成感に包まれていた。
すべてのアプリの .NET 10 への移行が完了。
依存関係も整理し、不要になったランタイムを削除。
クリーン。美しい。完璧。
…のはずが。
新規開発したアプリは容量の大きいファイルを生成する。
(不具合ではなく仕様)
そうだ.NET 9を消して少しでも容量を増やそう。
そうと決まれば早い方がいい。
達成感と焦りのコンボで判断が軽くなる瞬間。
そして実行。
.NET 9 をアンインストール。
ここまでは良かった。
原因(セルフ地雷)
私はログインシェルを PowerShell にしていた。
そしてPowerShell が .NET 9 に依存していることを理解していなかった。
つまり:
ログイン時に起動するシェルが存在しない
→ セッション即死
→ SSH即切断
最初の感情の推移
「まあ何とかなるでしょ」
↓
「シリアルコンソールで接続」
↓
「クラウドのデフォルトの仕様で普段使用するユーザーもrootもパスワード設定してない」
※仮に普段使用するユーザーでは入れてもシェルは同じなのでrootで入る必要あり
↓
「コンソールからも入れない」
↓
\(^o^)/オワタ
しかしクラウドは最後の希望をくれた
クラウドのシリアルコンソールから
GRUB が見えることを確認。
これは勝ち筋がある。
シングルユーザーモードにして対象ユーザーのログインシェルをbashに戻そう。
GRUBとの戦い
しかしGRUBはすぐ消える。
そして気づくとgrub>プロンプト。
何もわからない。
※ESC連打し過ぎて起動パーティション選ぶ画面からgrub> プロンプトまで行ってしまいました。
とりあえずパーティションを列挙:
ls
ls (lvm/rocky-root)/
ls (hd0,gpt2)
カーネルとinitramfsを発見。
シングルユーザーモードで起動できるように設定。
linux (hd0,gpt2)/vmlinuz-5.x.x root=/dev/mapper/rocky-root rw init=/bin/bash
initrd (hd0,gpt2)/initramfs-5.x.x.img
boot
起動成功。
ここで初めて希望が見える。
シングルユーザーモード初体験
rootシェルに入れた。
ファイルシステムを書き込み可能に:
mount -o remount,rw
ユーザーのログインシェル修正:
chsh -s /bin/bash rocky
もう一度SSH
再起動後:
SSH接続成功。
生還。
学んだこと
1. ログインシェルは壊れる
特殊シェルは .bashrc から起動するのが安全。
2. SSHとコンソールは同じログインシェルを使う
つまりシェルが壊れると両方死ぬ。
真の復旧経路は:
-
GRUB操作
-
シングルユーザーモード
-
レスキューモード
3. rootパスワードより大事なもの
「ブートパラメータをいじれる手段」
これがある限り詰まない。
4. サーバ運用の真理
サーバは壊れる。
ログインは壊れる。
起動も壊れる。
復旧経路を作っておけば怖くない。
おまけ:PowerShellは悪くない
PowerShellが悪いのではない。
ログインシェルにした私が悪い。
安全な使い方(以下を.bashrcに記載):
# ~/.bash_profile などに書く例
# PowerShellログインシェルを安全に起動
if command -v pwsh >/dev/null 2>&1; then
# pwsh は存在する
# 依存ライブラリが揃っているかテスト
if pwsh -noprofile -command '$PSVersionTable' >/dev/null 2>&1; then
# 起動OKならログインシェルを PowerShell に置き換える
exec pwsh
else
# 起動不可なら bash のまま
echo "PowerShell 起動失敗: 必要なランタイムが揃っていません。bash を使用します。"
fi
fi
これで事故らない。