AWS EC2 で VS Code の Remote-SSH が頻繁に切断される/接続できなくなる 現象に悩まされていませんか? 私もブログ運営中に 「JavaScriptを少し修正しただけでSSHが落ちる」 というトラブルに絶賛遭遇中です。 本記事では、その原因と具体的な解決策を、実際のログと設定例を交えて詳しく解説します。
【現象まとめ】EC2でRemote-SSHが切断される状況
症状としては、JSを修正するとSSH接続が切れるというものです。
再度接続を試みても繋がらず、完全に沈黙します。
しかしAWSコンソールを見ると、インスタンスは running で、ステータスチェックも 2/2 合格。
つまり「サーバーは生きてるけどSSHだけ死んでいる」状態。
ping
も ssh
も通りませんが、CloudWatch上ではCPUもメモリも正常です。
再起動(reboot)では復旧せず、「停止 → 起動」 でやっと直る。
ただしその間、30分ほどブログが停止するのでかなり厄介です。
数ヶ月前から起きていたのですが、JSを頻繁にいじらないので放置していました。
ただ、毎回これではJSを開発するきが起こらないので、今回ちゃんと調べてみました。
補足すると、VS Code の Remote-SSH でファイルを修正したときだけ発生し、
vimで直接編集した場合は問題なしです。
つまり、Remote-SSHまわりが怪しい。
【原因調査】EC2・SSH側に異常はなかった
症状的にサーバ自体に問題がなさそうだったのですが、念の為、サーバ上の調査も行いました。
まずは、サーバー自体に異常がないかを確認しました。
具体的には、メモリ不足(OOM)・システムログ(journalctl)・CloudWatchのメトリクスを順にチェックしました。
dmesg(カーネルメッセージの確認)
dmesg
は、Linuxカーネルが出力するシステムレベルのメッセージを確認するコマンドです。
サーバーがメモリ不足になると、Linuxは自動で「どのプロセスを強制終了するか」を決める OOM(Out Of Memory)キラー を実行するようです。
dmesg | grep -i kill
このコマンドで該当ログを探しましたが、OOM Killerの記録は見つかりませんでした。 つまり、メモリ不足でプロセスが落ちたわけではないということです。
journalctl(システムログの確認)
次に journalctl で、サービスやネットワーク周りの異常を調べました。
journalctl は Linux の「時系列ログビューワー」で、 「どのサービスがいつ起動/停止したか」や「どんなエラーが出たか」をまとめて確認できます。
sudo journalctl -xe
出力を確認したところ、sshd(SSHデーモン)に関するエラーはなしで、 ログ上も特に異常は見当たりませんでした。
CloudWatch(リソースの監視)
最後に、AWS CloudWatch で CPU利用率 や ステータスチェック を確認しました。 グラフ上もリソースは安定しており、異常なスパイクや再起動の痕跡もありません。
調査の結果、やはり、インスタンス自体の問題ではない ということが判明しました。
【結論】Remote-SSHの負荷でSSHがハングする
ここまでの調査で、サーバー側の異常は見つかりませんでした。
また、vimで編集した場合は問題が起きないことから、
原因はサーバーではなく、VS Code の Remote-SSH 側にあると考えられます。
Remote-SSHの負荷によるハング
調べてみると、Remote-SSHは思った以上に重い処理を行っていることが分かりました。
ファイルを保存するたびに、rsync
などを用いてローカルとEC2サーバー間で同期を行います。
その際、ESLint や Prettier などの拡張機能(コードを自動で整形・検証するツール)も同時に動作します。
これらは便利ですが、バックグラウンドでコード全体を解析するため、
t3.micro(1GB RAM)クラスのインスタンスではメモリ負荷が非常に高くなります。
私自身、ESLintやPrettierという拡張機能を意識的に使っていたわけではありません。
調べてみると、VS Codeでは .js
や .ts
ファイルを開いた際に
「このプロジェクトではESLintを使うのがおすすめです」
というポップアップが表示され、自動的にインストールを促されることがあるようです。
その結果、SSHデーモン(sshd
)やネットワーク処理が応答しなくなり、
VS Code 側で 「OfflineError」 が発生する、という現象に繋がります。
「ハング」とは何か
ここでいう「ハング」とは、サーバーやプロセスが完全に停止したわけではなく、動作が止まって応答を返せない状態を指します。
電源は入っておりCPUも動作していますが、何らかの要因でプロセスが処理待ち(デッドロックや過負荷)に陥り、
外部からの通信(SSHリクエストなど)に反応できなくなっている状態です。
今回のケースでは、sshd
プロセスそのものが停止しているわけではなく、
Remote-SSHによる負荷が一時的に通信処理を塞いでしまった(ハングした) 可能性が高いです。
そのため、AWS上では「インスタンスが正常に稼働中(ステータスチェック2/2合格)」と表示されても、
実際には接続できない──という矛盾した状況が起きました。
なぜ通常のSSH接続まで落ちるのか?
これは現時点で明確な原因は特定できていません。
ただし、VS Code Remote-SSH は EC2 内部で .vscode-server
という常駐プロセスを起動しており、
そのプロセスが過負荷やデッドロック状態になると、sshd
全体に影響を及ぼす可能性があります。
要するに、「Remote-SSHがハングすると、SSHデーモンごと巻き込まれる」構造になっているのかもしれません
【設定変更で解決】Remote-SSHの軽量化手順
対処法はいくつかありますが、私は①〜③すべて実施しました。
おそらく①だけでも改善されるとは思いますが、
そもそも t3.micro はリソース的に限界が近い構成だったので、
将来的な安定運用を考えてインスタンスサイズを上げるのが一番現実的だと思います。
t3.small
であれば月額2,000円前後なので、妥協できる範囲だと感じます。
1. settings.json で Remote-SSH を軽量化
以下は、Remote-SSHの接続を軽量化し、保存時の負荷を減らすための設定例です。
{
"remote.SSH.useLocalServer": false, // 中継をやめてEC2に直接接続
"remote.SSH.showLoginTerminal": true, // 接続ログを表示
"editor.formatOnSave": false, // 保存時の自動整形をオフ
"eslint.run": "manual", // ESLintは手動実行に変更
"files.autoSave": "off" // 自動保存を無効化
}
上記の設定を変えるだけで、保存時の負荷を大幅に軽減できます。
2. 不要な拡張機能を無効化
ESLint や Prettier、TypeScript IntelliSense などの拡張機能は、
ローカル環境では便利ですが、リモート環境(EC2上)で動かすとかなり重くなります。
VS Code の拡張機能タブから、対象の拡張機能を右クリックし、
「このリモートで無効化(Disable on Remote)」を選択しましょう。
これにより、リモート接続時のみ拡張機能の実行を停止でき、
CPU・メモリの無駄な消費を防ぐことができます。
3. その他の対策
- スワップ領域を追加 → メモリ不足時の保険として有効
- インスタンスタイプを t3.small (2GB) に変更 t3.microだと1,200円前後であり、t4.smallだと2,300円前後です。
ただでそれなりにする運営費をこれ以上上げたくないので、この修正は見送ります。2025/09/28 に t3.small に変更しました。やっぱり快適です。
t3.micro(1GB)では、Remote-SSH や ESLint/Prettier を同時に動かすにはやや厳しい印象です。
コスト面を考えても、t3.small へのアップグレードが最も効果的な対処法だと思います。
まとめ
Remote-SSH便利なので使っていましたが、こんな罠があったんですね。
一方で、vim で編集すると何の問題も起きません。
大学2年のときに講義で学んで以来、ちょくちょく使っていましたが、
改めて「軽さの正義」を思い出しました。
久しぶりに、vim の良さを再発見した出来事でした。