Windows 上で SSH 越しに `atom .` とか `code .` した話

こんにちは @3846masa です．

この記事は [NCC Advent Calendar] 2日目の記事です．

[3846masa Advent Calendar] 2日目の記事でもありますが，
こちらはそもそも **1日目がない** 上に **続ける気力もない** ので気にしなくていいです．

[NCC Advent Calendar]: http://www.adventar.org/calendars/1835
[3846masa Advent Calendar]: http://www.adventar.org/calendars/1908

- - - - -

# tl;dr | 概略

- VirtualBox 上の Ubuntu から ホストOS 側の Windows に `atom .` したい
  - 普段は VirtualBox の Ubuntu からコマンドを叩くため
  - エディタは samba 経由で Windows 上の Atom や VSCode を使っている
- OpenSSH on MSYS2 を使うとできるようになる
  - 他の SSHD も試したけど，これでないと動かなかった
- 問題点は結構あるので，汎用的に使えるように解決していきたい
- **こんな環境は稀有なので，役に立たない記事**

以下は `cmd <windows command>` できるようにした図．（`cmd atom .` などもできる）

![cmd echo](https://gyazo.com/90dfb3f3a067f5447f67200fcdea34d5.png)

![cmd code](https://gyazo.com/1a67a960e05671f41a05a4a013a28d2a.gif)

# はじめに

## 問題の環境

- ホストOS は Windows 10 （Anniversary Update 済み）
- 普段の作業は VirtualBox で Ubuntu 16.04 を動かしている
  - 画面は非表示（ヘッドレスモード）
  - [MSYS2] で OpenSSH を使って接続
  - ターミナルは [Cmder]
- Ubuntu では samba が建っていて Windows からアクセス可能
  - U ドライブにマウントしている
  - 普段は U ドライブからファイルを Atom や VSCode で開く

[MSYS2]: https://msys2.github.io/
[Cmder]: http://cmder.net/

## 問題点

- カレントディレクトから GUI アプリケーションを起動できない
  - `atom .` や `code .` や `explorer .` ができない

# 手法

問題点を解決するために色々試した．

## 試行 1 | SSHBroker

Bash on Ubuntu on Windows をインストールすると， SSHBroker なるものが勝手にインストールされる．
（参考：[Windows10 Anniversary updateで知らぬ間にSSHdが起動している : やすひでぶろぐ](http://yasuhide.blog.jp/archives/48155574.html)）

これは SSH 越しに cmd を使うことができる代物らしいが， **パスワード認証である** ため開放するのが怖い．

公開鍵認証にする方法を探してみるも， **無効にする方法しかでてこない**．
早々に断念する．

## 試行 2 | Win32-OpenSSH

Windows 版 OpenSSH である [Win32-OpenSSH] があることを思い出す．
[インストール方法][win32-openssh-install] があるので，そつなく SSH 接続までたどり着く．便利である．

ただし， `atom .` をしても **バックグラウンドプロセスになり，ウィンドウが表示されない**．
ググっても似たようなことをしている人がおらず，早々に断念する．

[Win32-OpenSSH]: https://github.com/PowerShell/Win32-OpenSSH
[win32-openssh-install]: https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH

## 試行 3 | OpenSSH on MSYS2

MSYS2 の `ssh` を使って VirtualBox にアクセスしていたことを思い出す．

MSYS2 の `sshd` を使う記事を探すといくつか見つかる．
[Windows10タブレットにMSYS2を入れてsshデーモンを立ち上げてみた - もぐてっく](http://moguno.hatenablog.jp/entry/2015/09/06/134835) を参考に進めていく．

準備が整い， `explorer .` と 試してみたところ，しっかりウィンドウが表示された．

# OpenSSH on MSYS2 での弊害と解決法

結論を言うと，OpenSSH on MSYS2 で目的は達成できた．
しかし，実際の運用には問題がいくつか生じたのでここに記す．

## 問題点 1 | ネットワークドライブ

前述の記事通りに `cygeunsrv` を使えば SSHD のデーモン化ができる．
しかし， **管理者権限で実行される** という弊害がある．

これによって， **なぜかネットワークドライブに割り当てたドライブレターに SSH でアクセスできない** 問題が生じる．

理由の解明はしていないが，管理者権限でなければアクセスできた．
そのため， `cygeunsrv` を避ける方針に変更する．

### 解決策

適当なバッチファイルを作って， `sshd` を起動させる．

このとき， **`/usr/bin/sshd` として起動させる必要があるため**，一旦 `bash` を経由する必要がある．

以下のバッチファイルを `C:\msys64` に生成して，スタートアップに登録する．

```bat
@echo off
REM 参考： http://scripting.cocolog-nifty.com/blog/2009/10/powershell-20-4.html
PowerShell -WindowStyle Hidden -Command Exit
%~dp0\usr\bin\bash.exe -c "/usr/bin/sshd -D"
```

## 問題点 2 | 環境変数が読み込まれない

SSH 経由でアクセスすると， **Windows 側の環境変数が読み込まれない**．

その影響により， **VSCode や Atom は起動をしてくれない**．

（その他，環境変数に依存するプログラムは起動しない．）

![VSCode Error](https://gyazo.com/56f3612e226694c6f9950ee3d6d7b512.png)

### 解決策

[ssh-env - ssh実行時に環境変数を設定/変更したい - spikelet days](http://d.hatena.ne.jp/taiyo/20080613/p1) を参考に， SSH 接続時に環境変数を設定してくれるようにする．

（現在は手動で追加しているが，自動で反映されるようにしたほうが良い．）

```
# ~/.ssh/environment
# For VSCode
APPDATA=C:\Users\3846masa\AppData\Roaming
# For Atom
USERNAME=3846masa
USERPROFILE=C:\Users\3846masa
```

## 問題点 3 | `PTY allocation request failed on channel 0`

SSH 接続時に `PTY allocation request failed on channel 0` というエラーが発生する場合がある．

いまのところ原因がよくわかっていないが， **前回 SSH 越しに起動失敗したプロセスが残っていると起きる** ようである．

### 解決策

いまのところ見つかっていない．
原因と思われるプロセスをタスクマネージャーから停止させる他ない．

## 問題点 4 | パスが違う

Ubuntu 内のパスと MSYS2 内のパスが一致しない．

### 解決策

次のようなシェルスクリプトを書くことによって，雑に対処する．

```bash
function cmd() {
  CUR_DIR=`pwd | sed -e "s#^$HOME#/u#"`
  ssh 3846masa@192.168.206.1 -q -i ~/.ssh/virtualbox -t "cd $CUR_DIR; cmd //c $@"
}
```

これによって

![cmd echo](https://gyazo.com/90dfb3f3a067f5447f67200fcdea34d5.png)

こんな感じで雑に書ける．

# 結論

`cmd code .` とか `cmd atom .` とか `cmd explorer .` とかできるようになった :tada:

![cmd explorer](https://gyazo.com/29aaa8adf28d8e1e36240015c92ceeec.gif)

# おわりに

VirtualBox 上の Ubuntu から `atom .` や `code .` を起動させる手法について検討した．

- OpenSSH on MSYS2 の `sshd` を利用する
- 管理者権限は与えずに `sshd` を実行する
- 環境変数は `~/.ssh/environment` に記載する

上記の手法で目的を達成する事ができた．
しかし，まだ問題点はいくつか残っているため，汎用的につかえる方法を模索していきたい．