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?

SSH先のUbuntuから、ローカルWindowsのVS Codeで現在のディレクトリを開く

0
Posted at

WSLでは、開いたターミナルからwindows側のVSCodeをcode .で開くことができる。
これをSSH接続先のubuntuからでもできるようにしたかったので、やった。

今回は、ubuntuマシンFMVAにSSH接続し、vscode .でwindowsのVSCodeを起動できるようにしたのでそのケースを書く。

code --remoteでwindowsからリモートに接続してVSCodeを開けるので、
Windows側でHTTPリスナーを起動しておき、UbuntuからはSSHのポートフォワード経由でhostとpathを送る。リスナーは受け取った情報を使って、Windows上で次のようなコマンドを実行する。

code --remote ssh-remote+FMVA /home/user/projects/test

処理の流れは次のとおり。

  1. Ubuntuでvscode .を実行する。
  2. シェル関数が現在の絶対パスとSSHホスト名をHTTPで送る。
  3. RemoteForwardが、そのHTTPリクエストをWindowsのローカルポートへ転送する。
  4. WindowsのPowerShellスクリプトがcode --remoteを実行する。
  5. VSCodeがRemote SSH経由でUbuntu上のフォルダを開く。

下準備

  • WindowsにVSCodeと拡張機能Remote-SSHを入れる
  • Windowsからssh FMVAでUbuntuへ接続できるようにする
  • WindowsのPowerShellでcode --versionが実行できることを確認する
  • Ubuntuにcurlをインストールする

(この記事の設定は、最初に書いた通りWindowsからUbuntuへSSH接続する場合のもの。FMVAはWindowsのSSH設定で使っているホスト別名なので、各自の名前に置き換える。ubuntuやwindowsのユーザー名も同様。)

1.WindowsのSSH設定にRemoteForwardを追加する

Windowsの~/.ssh/configを開き、対象ホストの設定へRemoteForwardを追加する。

Host FMVA
  HostName 192.168.x.x
  User user
  RemoteForward 54321 localhost:54321

この設定で、Ubuntu側のlocalhost:54321へ接続すると、SSHトンネルを通ってWindows側の localhost:54321へ届く。

設定を反映するには、いったんSSH接続を切断して接続し直す。

2. Windows側でVS Codeを起動するリスナーを作る

Windows側に、HTTPリクエストを受け取ってVS Codeを起動するPowerShellスクリプトを作成する。ここではvscode-listener.ps1という名前にする。

param(
    [int]$Port = 54321
)

$listener = [System.Net.HttpListener]::new()
$listener.Prefixes.Add("http://localhost:$Port/")
$listener.Start()

Write-Host "VS Code listener started: http://localhost:$Port/"
Write-Host "Stop with Ctrl+C"

try {
    while ($listener.IsListening) {
        $context = $listener.GetContext()
        $request = $context.Request
        $response = $context.Response

        try {
            $hostName = $request.QueryString["host"]
            $path = $request.QueryString["path"]

            if ([string]::IsNullOrWhiteSpace($hostName) -or
                [string]::IsNullOrWhiteSpace($path)) {
                throw "host または path が指定されていません。"
            }

            # 意図しない起動を防ぐため、許可するSSHホストを限定する。
            if ($hostName -ne "FMVA") {
                throw "許可されていない host です: $hostName"
            }

            # Ubuntuのホーム配下だけを開けるようにする。
            if (-not $path.StartsWith("/home/user/")) {
                throw "許可されていない path です: $path"
            }

            $code = (Get-Command code -ErrorAction Stop).Source
            Start-Process -FilePath $code -ArgumentList @(
                "--remote",
                "ssh-remote+$hostName",
                $path
            )

            Write-Host "Opened: $hostName $path"
            $response.StatusCode = 204
        }
        catch {
            Write-Warning $_
            $response.StatusCode = 400
        }
        finally {
            $response.Close()
        }
    }
}
finally {
    $listener.Stop()
    $listener.Close()
}

hostとpathを検証しているのは、受け取った値をそのままVS Codeの起動に使わないため。自分だけが使う構成でも、ホスト名と開けるパスを絞っておくと安心。

PowerShellでスクリプトを起動する。

Set-Location "C:\Users\<ユーザー名>\Scripts"
.\vscode-listener.ps1

次の表示が出れば、リスナーの起動は完了。

VS Code listener started: http://localhost:54321/

このPowerShellのウィンドウは、Ubuntuからvscodeを使っている間は開いたままにしておく。

3. Ubuntuに vscode 関数を追加する

Ubuntuの~/.bashrcまたは~/.bash_aliasesに次の関数を追加する。

vscode() {
  local path
  path="$(realpath "${1:-.}")" || return

  echo "Opening: $path"
  curl --fail --silent --show-error -G \
    --data-urlencode "host=FMVA" \
    --data-urlencode "path=$path" \
    http://localhost:54321/
}

source ~/.bashrcまたはsource ~/.bash_aliasesで反映する。

この関数では、引数がなければ現在のディレクトリを使う。realpathで絶対パスにしてから、curl --data-urlencodeで安全に送信しているため、パスに空白や日本語が含まれていても扱える。

これで、SSH先のUbuntuで次のように使える。

vscode .
vscode ~/projects/my-app

動作確認

まず、Windows側のリスナーを直接叩いて、VSCodeが起動するか確認する。

Invoke-WebRequest `
  -Uri "http://localhost:54321/?host=FMVA&path=%2Fhome%2Fuser" `
  -Method Get

HTTPステータスが204で、VSCodeが開けばリスナーは正常。

次にWindowsからssh FMVAで接続し直し、Ubuntuで確認する。

curl -v -G \
  --data-urlencode "host=FMVA" \
  --data-urlencode "path=$HOME" \
  http://localhost:54321/

このリクエストでVSCodeが開けば、RemoteForwardも正常に動いている。最後にvscode .を実行して確認する。

うまく動かないとき

Ubuntuで接続エラーになる

curl: (7) Failed to connectのようなエラーが出る場合は、次を確認する。

  • Windows側でvscode-listener.ps1を起動しているか
  • SSH接続を、RemoteForwardを追加したあとに張り直したか
  • Windowsの~/.ssh/configの対象が、実際に接続しているHost FMVA

Ubuntu側でcurl -v http://localhost:54321/を実行すると、どこで止まっているか確認しやすい。

HTTPは204だがVSCodeが開かない

WindowsのPowerShellで、次を単体で実行してみる。

code --remote ssh-remote+FMVA /home/user

これで開かない場合は、リスナーではなくVSCode CLIまたはRemote SSH側の問題。code --version が実行できるか、VSCodeのRemote SSH設定にFMVAが見えているかを確認する。

以前は動いたのに急に動かなくなった

この構成ではWindows側のリスナーが常駐している必要がある。まずPowerShellのリスナー画面が閉じていないかを確認する。

VSCodeは開けるがSSH接続はエラーになる

まずこれが躓くところだと思う。すごく苦労した。
RemoteForwardをターミナルとVSCode内で奪い合ってしまうのが原因。
ターミナルで接続するSSHをこのように迂回する。

Host FMVA
  HostName FMVA
  User user
  IdentityFile ~/.ssh/id_ed25519

Host FMVA-shell
    HostName FMVA
    User user
    IdentityFile ~/.ssh/id_ed25519
    RemoteForward 54321 localhost:54321
    ExitOnForwardFailure yes

ターミナルでSSH接続するときはFMVA-shellを使い、VSCodeではFMVAを使う。

PowerShellに打ち込む文字列をもっと短くしたい

Set-Location "C:\Users\<ユーザー名>\Scripts"
.\vscode-listener.ps1

長い。なのでバッチファイルを作る。

@powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%USERPROFILE%\bin\vscode-listener.ps1"

%USERPROFILE%\binvscode-listener.ps1があれば、これで起動する。
%USERPROFILE%\binにパスを通しておくといいだろう。

これで使用感をWSLと同じようにできる。

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?