リモートサーバー上で起動したjupyterですが、ip='0.0.0.0’にしてportを公開する人はほとんどいないでしょう。
sshのPort fowardingで接続する人が大半だと思います。そのほうがセキュアだし。
コマンド1つでリモートサーバーでjupyterを起動し、ローカルのブラウザですぐ使いたい&後始末もしたい
要はローカルと同じ使用感でさくっとjupyterを使いたいというだけです。
ローカルの場合はjupyter lab
コマンドだけで済む話ですが、リモートの場合は完全手動だと
- リモートサーバーにsshしてjupyter起動
- 別のTerminalを開いてssh port fowarding
- Step 1で表示されているtoken付きURLを、ローカルのブラウザのアドレスバーに貼り付ける
という作業が必要になります。
閉じる際も、
- sshで起動したjupyterをCtrl-Cで停止
- ssh port fowardingを解除(当該portを使用しているsshのプロセスをkill)
という後始末も必要です。
めんどくさいので自動化します。
こういうのは、構成管理ツールの範疇な気もするのですが、そういったツールが必要になるのは、複数台のサーバーを同時管理するなどの業務レベルケースの話であり、個人開発レベルの自動化であれば、シェルスクリプトでさくっと書けたほうがいい気がします(手間的にも技術力的にも)。
なのでシェルスクリプト(ごくふつうのbashスクリプト)で対応します。
スクリプト
P=$1
cleanup () {
echo "STOP jupyter server on PORT: ${P}"
ssh yourserver "/path/to/jupyter lab stop ${P}"
kill -9 $(lsof -t -i:${P})
}
# Ctrl-Cでmainを停止した場合の処理
trap 'cleanup' 2
main () {
echo "START jupyter Server on PORT: ${P}"
ssh -fNL ${P}:localhost:${P} yourserver
ssh yourserver "/path/to/jupyter lab --no-browser --port ${P}"
}
# 実行
main
全体の実装は以上になります。
前出の手動操作は理解しているという前提で、要点を解説します。
Portは、色々変えるニーズがあると思うので、シェルスクリプトの第1引数にしています。
main処理
yourserver
は、sshのconfigファイルに記載してあるリモートサーバーのホスト名です。つまり、ssh yourserver
とするとssh接続ができる状態になっている必要があります。
main処理では、sshでport fowardingした後、再度sshコマンドで、リモートでコマンドを実行しています。
ここでjupyter lab
コマンドを実行することで、リモートサーバー上でjupyterが立ち上がります。
めんどくさいのでローカルとリモートのportは同じにしていますが、こだわりがあれば引数を増やすなりして対応してください。
ssh yourserver "command"
とすることで、リモートでコマンドを実行できます。pathが通っていないため、絶対パスでの指定が必要でした。
mainが実行されると、お馴染みのjupyter起動メッセージが出てきて
http://localhost:8888/lab?token=XXXXXXX
という出力で止まります。コントロールはリモート側に取られたままで、ローカルのシェルスクリプトに処理が戻りません。
ただし、この状態で既にjupyterは起動しているので、全く問題ありません。
上記のtoken付きURLをブラウザに貼り付けると、晴れてリモートのjupyter labをローカルブラウザから使えます。
残念ながら、このブラウザへの貼り付けだけは手動でやる必要があります。すみません。
cleanup処理
trapコマンドで第1引数にcleanup処理を仕込んでおくことで、後始末も自動化します。
trapの第2引数の2というのはシグナル番号で、2は割り込みシグナルSIGINT(Ctrl-C)になります。
(ちなみにkill -l
コマンドで一覧を確認できます)
trapコマンドでは、第2引数に指定したシグナルを受け取った際、第1引数にセットしたコマンドを実行するようにしてくれます。
cleanup処理では、リモートのjupyterの停止(portを指定して停止できます)と、
port fowardingしているローカルのsshプロセスをkillしています(当該portを使用しているsshプロセスのpidを調べています)。
jupyterを停止させるには、Ctrl-Cを押す必要があります(jupyter起動時のInfoログに書いてある)。
ただ、ちょっと考えればわかりますが、ローカルのTerminalでCtrl-Cを押すと、SIGINTを受け取るのはローカルのシェルスクリプト本体であって、リモートのjupyterまでSIGINTが届きません。
ふつうはsshが落ちたり途切れたりすると、sshで起動したプロセス(子プロセス)も落ちる仕様なのですが、
上記のシェルスクリプトでは、Ctrl-Cでローカルのシェルスクリプトを終了してもリモートのjupyterは生きたままでした(ここはちょっと何でか分からない)。
なので、cleanup処理にて、jupyerの停止やport fowardingの解除が必要です。
で、最初のtrapコマンドに戻ります。
ローカルのCtrl-Cをtrapで拾ってcleanup処理を実行できるようにしておけば、Ctrl-Cを使って後始末も自動化できることになります。
0 件のコメント:
コメントを投稿