0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VS Code Remote-SSH がタイムアウトする原因は、リモート側の fish シェルだった

0
Posted at

はじめに

Mac mini をリモートサーバーとして運用し、MacBook Air の VS Code から、標準機能の Remote-SSH を使って接続しようとしたところ、ターミナルからは問題なく SSH 接続できるのに、VS Code Remote-SSH から接続した場合に限ってエラーが発生した。

解決してから分かったのだが、原因は Mac mini(リモートサーバー)側で fish シェルを使っていたことだった。

この問題は Codex(GPT-5.5)の助けを借りて解決した。

TL;DR

  • 症状: ターミナルからの ssh 接続は即座に成功する一方、VS Code Remote-SSH だけが認証成功から約17秒後に Connecting with SSH timed out となる。
  • 本当の原因: リモートサーバーのアカウントで、ログインシェルに fish を使用していたこと。VS Code が接続直後にリモートサーバーをインストールするためのブートストラップスクリプトは POSIX(sh/bash)構文で書かれており、fish では実行できない。そのため、サーバーのインストール処理全体が失敗していた。
  • 解決策(ログインシェルは変更しない): VS Code 専用の SSH エイリアスを作成し、接続時のブートストラップ処理だけを bash で実行する。使用するのは RemoteCommandremote.SSH.enableRemoteCommand

症状

Authenticated to <host> using "publickey"   ← 認証は成功
(node) DeprecationWarning ...
(約17秒間、応答なし)
Terminating local server → Connecting with SSH timed out

ssh <host> では問題なく接続できるのに、VS Code の Remote-SSH だけが何度試してもタイムアウトした。

試したこと(疑ったものの、原因ではなかった)

確認したところ、以下はすべて正常だった。

  • SSH、ネットワーク、公開鍵認証
  • VS Code Server の tarball ダウンロード(手動でダウンロードし、node の起動まで成功)
  • ディスク容量
  • Gatekeeper による隔離属性(quarantine)が付いていないこと
  • シェル初期化時の出力による汚染(ssh -T <host> < /dev/nullstdout は 0 バイトで、余計な出力なし)

よく原因として挙げられる ~/.vscode-server のキャッシュ破損や、シェルの rc ファイルによる出力汚染も疑い、削除や修正を試したが、いずれも関係なかった。

fish で失敗する理由

最近の Remote-SSH は接続後、リモート側のログインシェルをそのまま exec チャネルとして使用し、サーバーインストール用のスクリプト(POSIX 構文)を流し込む。

ログインシェルが bash や zsh なら問題ないが、fish は構文が異なるため、このスクリプトを実行できない。

その結果、次の状態になる。

  • リモート側の ~/.vscode-server にサーバーがインストールされない
  • VS Code は応答(handshake)を受け取れず、約17秒後にタイムアウトする

~/.vscode-server がいつまでも空のままなら、「サーバーのダウンロードに失敗した」のではなく、ブートストラップ処理自体が実行されていない可能性を疑うべきだ。これはシェルの問題を示す重要な手掛かりになる。

VS Code Remote-SSH は、fish のような 非 POSIX ログインシェルを公式にはサポートしていない

参考: microsoft/vscode-remote-release #10967

解決策 — fish を維持したまま接続する

ログインシェルを bash または zsh に変更するのが最も簡単だが、fish を使い続けたい場合は、VS Code 接続時のブートストラップ処理だけを bash で実行すればよい。

1. ~/.ssh/config に VS Code 専用エイリアスを追加する

既存のホスト設定はそのまま残し、VS Code 用の設定を別名で追加する。

# 通常の接続用 — fish のまま
Host myserver
    HostName myserver.example.com
    User me

# VS Code Remote-SSH 専用 — 接続時のブートストラップだけ bash を使用
Host myserver-vscode
    HostName myserver.example.com
    User me
    RequestTTY force
    RemoteCommand /bin/bash -l

2. VS Code の settings.json を設定する

"remote.SSH.enableRemoteCommand": true

3. Remote-SSH から myserver-vscode に接続する

これで接続できるようになった。

通常どおり ssh myserver で接続した場合は、引き続き fish が起動する。また、VS Code のリモート統合ターミナルもログインシェルの設定に従うため、fish のまま利用できる。

RemoteCommand が影響するのは、接続時のブートストラップ処理だけである。

代替案

  • 最も手軽: settings.json"remote.SSH.useLocalServer": false を設定する。exec-server モデルを無効化することで回避できる場合がある。
  • 最も確実: chsh -s /bin/bash(または zsh)でログインシェルを変更する。インタラクティブシェルだけ fish にしたい場合は、~/.bash_profile[[ $- == *i* ]] && exec fish を記述すればよい。
  • 非推奨: config.fishTERM_PROGRAM=vscode の場合に exec bash する。ブートストラップ実行時点ではこの環境変数が設定されていないため、信頼できない

学んだこと

  1. 通常の SSH 接続は成功するのに Remote-SSH だけが失敗する場合、ネットワークではなく、リモートシェルやブートストラップ処理を疑う。
  2. 調査時に何でも bash -lc で囲んでしまうと、ログインシェル自体の問題を見落とす。少なくとも一度はシェルを明示せずにリモートコマンドを実行するとよい。fish の構文エラーがそのまま表示される。
  3. ~/.vscode-server が空だからといって、必ずしもダウンロードに失敗したとは限らない。ブートストラップ処理が実行されていないサインである可能性がある。

おわりに

まさか fish が原因だとは考えていなかったため、解決までにかなり遠回りしてしまった。

やはり Bash か Zsh が最強なのかもしれない……。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?