Windows10に公開鍵認証でssh接続，Tensorboard表示の備忘録

コロナ禍のため，中々研究室にも行きづらくなった昨今，自宅のMacからリモートデスクトップで研究室のPC（Windows）を動かしていた．しかし，キーボードマッピングの問題や，解像度を考え，ssh接続でモデルの学習やTensorboardの表示ができないかを検討した．そのときに躓いたことや，自分なりに工夫したことを備忘録として残しておく．

#表記について
コマンドの実行が，クライアント（macOS）とサーバ（Windows）とで行き来するため，以下のような書き分けを行う．

```:mac
#クライアント側で実行するコマンド
```

```:windows
#windowsマシンまたはssh接続した状態で実行するコマンド．場合によっては，PowerShell等細かく注釈をつける
```

#やったこと

- Windows10にsshサーバを立てて，macOSから接続
- ポートフォワーディングを利用して，macのブラウザでTensorboardの表示
- 公開鍵認証で接続できるよう修正
- `.ssh/config`の作成
- ログインシェルをgit bashに変更，起動時に深層学習用の仮想環境のactivateと実行フォルダへの移動

##注意
WindowsのOpenSSHをインストールするところから始める方は，[公開鍵認証での接続](#公開鍵認証での接続)のコメントアウトの箇所から始めると，後々の作業が非常にスムーズになるので強くオススメする．

#Windows10へのssh接続
[Windows 10 に OpenSSH サーバをインストールする](https://qiita.com/iShinkai/items/a12c9d26f8f4264897f9)，を参考に，まずOpenSSHサーバのインストールを行った．
windows側の設定を終えたら，macのターミナルで以下のコマンドを実行する．

```:mac
ssh <サーバのUsername>@<サーバのホスト名（グローバルIP）>
```
`Username`は，エクスプローラーを開いて，`C:¥Users¥????`の`????`を，グローバルIPは[cman.jp](https://www.cman.jp/network/support/go_access.cgi)というサイトを利用してサーバのIPアドレスを確認した．
まず，これでmacOSから接続を確認，パスワードを聞かれるので，Windowsのログイン時のパスワードを入力すればおｋ．

#Tensorboardの表示

そもそも出来るのか，と思ったら[やってる人がいた．](http://miscellanea.hateblo.jp/entry/2017/07/17/231728)
しかし，こちらのサイトのように

```terminal:mac
ssh -L 8888:localhost:9999 user@server.host.name
```
では，なぜかポートフォワーディングが上手く行かなかった．なので，`localhost`の箇所を`127.0.0.1`に変更して実行したところ，成功した．もし上手く行かなかった方は書き換えてみると良いかも．
そして，以下のような形でポートフォワーディングを行う．

- ssh接続時，`6006:127.0.0.1:6006`にポートフォワーディングをしておく（tensorboardのポートのデフォルトが6006なので）
- ssh接続したクライアント側で，Tensorboardの実行を行う

といった形で実現した．コードは以下のようになる．

```:mac
ssh -L 6006:127.0.0.1:6006 <サーバのUsername>@<サーバのホスト名（グローバルIP）> 
#ssh接続後
tensorboard --logdir=<logのディレクトリ>
```
ただし，この方法の場合，ターミナルを強制終了したとき等に，サーバ側でtensorboardが実行されたままになることがあるので，その場合はサーバ側でtensorboardのプロセスを直接終了させる必要がある．

 ```powershell:windows
netstat -nao
#ローカルアドレスが127.0.0.1:6006のPIDを確認
taskkill /pid <tensorboardのPID>
```
以下の２つを参考にした．

- [あるポート番号が何のアプリケーションで使用されているか調べる方法](https://www.projectgroup.info/tips/Windows/comm_0133.html)
- [Windowsでプロセスを強制終了するコマンド](http://俺の技術メモ.net/windows-process-force-kill-command/)

#公開鍵認証での接続
ここまで行い，いちいちパスワードを入れるのが面倒になったのと，セキュリティの観点から公開鍵認証でssh接続出来るように変更．__これが非常に手間取った．__
まず，[SSH公開鍵認証で接続するまで](https://qiita.com/kazokmr/items/754169cfa996b24fcbf5)，を参考にKeyの作成や転送等を行ったが，なぜか公開鍵認証でログインできない．
色々調べ，以下２つのサイトの情報を参考にしたところ解決した．

- [Windows10+SSHサーバーにWindows10のSSHクライアントにて公開鍵認証でパスワード入力なしで接続できるようにしたときの覚え書き](https://lil.la/archives/4192)
- [Windows の OpenSSH](http://blog.livedoor.jp/aspplus/archives/51913440.html)


まず，`C:\ProgramData\ssh\sshd_config`の最後２行をコメントアウトする．

```ssh:sshd_config
Match Group administrators

       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
```
しかし，これだけでは出来るようにならなかったので，

- sshdを終了
- `C:\ProgramData\ssh\`配下にある`ssh_host_***_key`と，`ssh_host_***_key.pub`を全て消す
- sshdを開始


こうすると，再びホストキーが自動生成される．その後，同じ手順で鍵の登録を行ったところ，鍵認証での接続に成功した．もし，windowsのOpenSSHで，公開鍵認証ができない人は，この手順を行うと出来るようになるかもしれないので，参考までにどうぞ

#`.ssh/config`の作成
ここまで来ると，`ssh`コマンドが長くなってきたので，`.ssh/config`を作成して，サクッと接続出来るようにした．
[.ssh/configファイルでSSH接続を管理する](https://qiita.com/0084ken/items/2e4e9ae44ec5e01328f1)，を参考にして，以下のようにした．

```config
Host lab
    HostName <サーバのIPアドレス>
    User <サーバのUsername>
    IdentityFile ~/.ssh/id_rsa
    TCPKeepAlive yes
    IdentitiesOnly yes
    LocalForward 6006 127.0.0.1:6006
    ServerAliveInterval 15
    ServerAliveCountMax 10
```
こうすれば，以下のコマンドでssh接続が出来る．

```:mac
ssh lab
```

#ログインシェルをgit bashに変更
macのターミナルと，windowsでコマンドがけっこう異なること，実行ファイルをgitでも管理しやすいように，ログインシェルをgit bashに変更した．
[Windows10でSSHサーバーを立ててデフォルトシェルをBashにする](https://qiita.com/kenji0x02/items/3f4e7262e6de0d8c8702)を参考にして，

```powershell:windows,PowerShell
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Program Files\Git\bin\bash.exe"
 -PropertyType String -Force 
```
を実行したら変更できた．
しかし，git bashにAnacondaのpathが通っていなかったので，[PIFuHDをWindows + Anaconda + Git Bash環境で実行する](https://qiita.com/edo_m18/items/06ed95e427e7921b60c9)，を参考にして，pathを通した．自分の環境の場合，`C:\Program Files\Git\etc\bash.bashrc`に以下のコードを追加した．

```bash:bash.bashrc
export PATH=$PATH:/c/Users/<サーバのUsername>/anaconda3
export PATH=$PATH:/c/Users/<サーバのUsername>/anaconda3/Scripts

# >>> conda init >>>
__conda_setup="$(CONDA_REPORT_ERRORS=false '$HOME/anaconda3/bin/conda' shell.bash hook 2> /dev/null)"
if [ $? -eq 0 ]; then
    \eval "$__conda_setup"
else
    if [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then
        . "$HOME/anaconda3/etc/profile.d/conda.sh"
        CONDA_CHANGEPS1=false conda activate base
    else
        \export PATH="$PATH:$HOME/anaconda3/bin"
    fi
fi

unset __conda_setup
# <<< conda init <<<
```
更に，いちいち実行ファイルのディレクトリに移動して，`conda activate`するのも面倒だったので，上のコードの下に，以下の２行を追加した．

```bash:bash.bashrc
conda activate <仮想環境名>
cd <実行ファイルのディレクトリ>
```
これで，git bashが立ち上がると，仮想環境のactivateとディレクトリ移動をセットでやってくれるので，非常に便利になった．

#まとめ
自宅からwindowsへのssh接続とその他諸々のセットアップについてまとめた．正直リモートデスクトップでも問題はないが，やはりmac側のブラウザでTensorboardが見られるのはかなり良いし，今後AWSやGCPで深層学習を行う際にも活かせることが多いと思うので，その時にも色々工夫をして行きたい．