ちょっと前(1,2年前?)に話題になってた気がする sshのラッパープログラムのMosh (the mobile shell) を試してみました。
Mosh
Moshは特にMobile端末からsshでどこかのサーバーへ接続して ネットワークがとぎれとぎれ担ってしまうような場合にも 接続を維持できる様に(自動で再接続)してくれるプログラムです。
接続認証にはsshを使いますが、サーバー側、クライアント側両側で プログラムを動かして別のポートを使って接続を行い、維持するようにします。
これらのプログラムはmosh
コマンド実行時に自動的にスタートするので、
サーバー側でも先に動かしておく必要はありません。
事前準備としては、サーバー側、クライアント側両方にmosh
をインストールし、
mosh
が使えるポートを開けておくことです。
インストール
Mac
Homebrew でインストールできます。
ただし、パッケージ名がmosh
ではなくmobile-shell
です。
$ brew install mobile-shell
Windows (Cygwin)
Windowsで使いたい場合はCygwinにインストールして使います。
$ apt-cyg install mosh
Linux
root権限を持っていて apt-getで管理している様な場合はDebianでは
$ sudo apt-get install mosh
だけでOK。Ubuntuだと
$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:keithw/mosh
$ sudo apt-get update
$ sudo apt-get install mosh
の様にレポジトリを追加してのインストールになります。 公式ページにあるように、その他のシステムでも広くサポートされてます。
以下では 今回やったLinuxで管理者権限を持っていなくてユーザーローカルにインストールした場合について。
今回必要だったものはpkg-config、 protobuf、 OpenSSL、 ncurses です。
いくつかの場所にインストールしましたが、protobufは全てに入ってませんでしたが、
Opensslはもちろんシステムの/usr
に通常のが入っていますがdevelバージョンが必要で
別途ローカルにインストールしました。
ncursesはローカルにインストールしてあるところもありましたが、
下に書くようにfPIC
オプション付きでコンパイルし直す必要がありました。
Linuxでのローカル初期設定
に書いたように、~/usr/local/
下にstow
を使ってインストールします。
pkg-config
moshのconfigureで
checking for pkg-config... no
となって確かに入ってないサーバーだったのでインストール。
$ v=pkg-config-0.28
$ wget http://pkgconfig.freedesktop.org/releases/${v}.tar.gz
$ tar xzf ${v}.tar.gz
$ cd $v
$ ./configure --with-internal-glib --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v
最初、configure
の所で--with-internal-glib
を付けなかったら
...
checking for pkg-config... no
checking for GLIB... no
configure: error: Either a previously installed pkg-config or "glib-2.0 >= 2.16" could not be found. Please set GLIB_CFLAGS and GLIB_LIBS to the correct values or pass --with-internal-glib to configure to use the bundled copy.
と言われてしまって、glibをインストールしようかと思ったら glibのインストールにpkg-configが必要だったりわけがわからなくなりましたが、 上のオプションを試してみたらうまくいきました。
protobuf
protobufが無いと、moshでconfigureするときに
configure: error: cannot find protoc, the Protocol Buffers compiler
と言われます。これを言われたらprotobufをインストール。
$ cd ~/tmp
$ v=protobuf-2.5.0
$ wget https://protobuf.googlecode.com/files/${v}.tar.gz
$ tar xzf ${v}.tar.gz
$ cd ${v}
$ ./configure --prefix=$HOME/usr/local/stow/${v}
$ make
$ make check
$ make install
$ cd ~/usr/local/stow && stow $v
な感じ。一部のシステムで(Debian)、make check
の時に
5つあるテストのうち1つがエラーを吐きましたが、
コンパイルやその後のmoshのコンパイルでも問題なかったのでそのままにしてあります。
OpenSSL
OpenSSLのdevel(libssl.so等)がないと moshのcongigure時に、
checking for OPENSSL... no
configure: error: Package requirements (openssl) were not met:
No package 'openssl' found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables OPENSSL_CFLAGS
and OPENSSL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
こんな感じで怒られます。もし、すでに/usr/lib
等にあるのに怒られる場合は、
上にあるようにPKG_CONFIG_PATH
の指定が必要です(下のmoshのインストールの部分参照)。
$ cd ~/tmp
$ v=openssl-1.0.1h
$ wget ftp://sunsite.cnlab-switch.ch/mirror/openssl/source/${v}.tar.gz
$ targz ${v}.tar.gz
$ cd ${v}
$ ./config --shared -fPIC --prefix=$HOME/usr/local/stow/${v}
$ make
$ make install
$ cd ~/usr/local/stow && stow $v
と--shared
を忘れずに。また、-fPIC
をつけろ、というエラー
1
が出るような場合は
上の様に-fPIC
をつけるのが必須です。
Ncurses
moshのmake時(configureは通った)に、
CXXLD mosh-client
/usr/bin/ld: $HOME/usr/local/lib/libncurses.a(lib_setup.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
$HOME/usr/local/lib/libncurses.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
こんな感じのエラーが。
そもそも、ncursesの共有ライブラリが無いので、作るために
--with-shared
付きでconfigureし直し再インストール。
$ cd ~/tmp
$ v=ncurses-5.9
$ wget http://ftp.gnu.org/pub/gnu/ncurses/${v}.tar.gz
$ tar xzf $v
$ cd $v
$ ./configure --with-shared --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v
mosh
準備が整ったのでmoshを。 ソースはGitHubにあるのでそちらから取ってきます。
$ cd ~/tmp
$ git clone https://github.com/keithw/mosh
または
$ v=mosh-1.2.5
$ wget http://mosh.mit.edu/${v}.tar.gz
と言った感じにアーカイブも用意されています。
とりあえずGitHub版を取ってきたとして
$ cd mosh
$ v=mosh-$(grep released ChangeLog|head -n1|awk '{print $3}')
$ ./autogen.sh
$ CXXFLAGS="-I$HOME/usr/local/include" CFLAGS="-I$HOME/usr/local/include" LDFLAGS="-L$HOME/usr/local/lib" PKG_CONFIG_PATH=$HOME/usr/local/lib/pkgconfig ./configure --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v
でOK。 configureの所で幾つか環境変数を設定して渡す必要があります。
上に書いたようにPKG_CONFIG_PATH
へは*.pc
ファイルがあるディレクトリ
(通常.../lib/
下)を渡します。
上でインストールしたopensslなどの情報が入ったファイルが
$HOME/usr/local/lib
にopenssl.pc
等という名前などで入っているので、
ここへのパスを書きます
2。
CXXFLAGS、CFLAGS、LDFLAGSは渡しておかないとmake時に見てくれないので渡す必要があります。 ここで、CFLAGSの方だけ設定しておくと、configure時には
...
checking for curses.h... no
checking for NcursesW wide-character library... no
checking for Ncurses library... yes
checking for working ncurses/curses.h... yes
checking for working ncurses.h... no
checking whether forkpty is declared... no
checking for forkpty in -lutil... yes
...
こんな感じでOKが出ますが、makeすると
$ make
...
make[3]: Entering directory `$HOME/tmp/mosh/src/terminal'
CXX terminaldisplayinit.o
terminaldisplayinit.cc:48:30: fatal error: ncurses/curses.h: No such file or directory
compilation terminated.
といった感じでCXX
時にncurses/curses.h
が見つかりませんので、
きちんとCXXFLAGSにも渡して上げる必要があります。
Android
AndroidではJuiceSSH がmoshを公式にサポートしてくれる様になり、クライアントとして使えます。
基本無料で、有料でCloudで設定をシェアしたり出来たりするようになりますが、 基本的な機能は無料で十分使えます。
インストールしたら、Typeでmoshを選び、
ポートの変更等がある場合はCommandの部分に必要なMoshに 与えるオプションを書き加えてあげます。
後は普通にsshするのと同じ様にしてあげればmoshでの接続になり、 例えば電車などですごく不安定な所でつなげても つながるたびに復活してくれます (だからといって流石に電車なんかでそれで普通に使えるほどではないですが。。。)
iPhone
iPhoneは公式にも載ってませんが、
iSSH
というアプリが対応しているっぽいです(試してない)。
使い方
まず、moshはデフォルトで60000~61000番のいずれかのポートを使います。
sshでつないでサーバー側でmosh-server
を起動した後、
ポートを1つ指定し、そのポート経由でローカルで起動するmosh-client
からつなげる様な作業を行います。
ですので、もし、これらのポートがファイアウォール等で外から使えない時は
ルート権限があるなら/sbin/iptables
などを使って(自己責任で)開けて置く必要があります。
serverというホストにmoshを使ってログインしたい時は単に
$ mosh server
とすればOK。~/.ssh/config
にある設定に従ってホスト名の解釈やユーザー名の設定も
行ってくれます。
ユーザー名を直接
$ mosh user@server
と通常のsshみたくしてもOK。
または、適当に使えるポートが有るなら、ポート指定も出来ます。
$ mosh -p 5050 server
と-p
で指定すればOK。
ポートを指定しないと60000~61000番の空いてるポートどれか(普通は数が小さい方から)
を使って行って、新たなセッションを作ると別のポートを使いますが、
ポート指定すればそのポートだけが使われるのでより安全にしたい場合もそちらで。
一方、sshのポート番号が22以外の場合には
$ mosh --ssh="ssh -p 1022" user@server
の様に、--ssh
オプションにssh
コマンドに加えて与える
オプションをまとめて指定することができます。
上手くいけば
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
[server ~]$
こんな感じのメッセージとともにログイン出来るはずです。
恐らくmoshを起動する際にターミナルへ\e]0;
~\a
の
エスケープシーケンスを送っているのか
3
iTermではタイトルバーを見ると本来のタイトルの左に[mosh]
という文字が追加されていました。
起動後は通常のsshと同様に作業してexit
等でログアウトするとmoshのプロセスも終了します。
もし、moshのプロセスを中断したいような場合には Ctrl-^ Ctrl-zを押せば中断出来ます。
エラー等
指定したポート(もしくは指定しない場合に向こうで勝手に指定する60000番など) が外から使えないものだと
mosh: Nothing received from server on UDP port 60001. [To quit: Ctrl-^ .]
な感じのメッセージが青いバックグラウンドで表れ
mosh: Last reply 19 seconds ago. [To quit: Ctrl-^ .]
こんな感じでつながらないよ、とカウントをしていきます。 暫くそのままつながらないで放置しておくか、書いてある通り Ctrl-^ .を押せば
mosh did not make a successful connection to 1xx.1xx.2xx.xx:60001.
Please verify that UDP port 60001 is not firewalled and can reach the server.
(By default, mosh uses a UDP port between 60000 and 61000. The -p option
selects a specific UDP port number.)
[mosh is exiting.]
その後、こんな感じで終了します。
もし、ポートが既にたのセッションで使われてると、
mmbp ~]$ dcnode
Failed binding to 1xx.1xx.2xx.xx:5050
Error binding to IP 1xx.1xx.2xx.xx: bind: Address already in use
Failed binding to 0.0.0.0:5050
Error binding to any interface: bind: Address already in use
Network exception: bind: Address already in use
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.
[mmbp ~]$ ssh dcnode
の様なメッセージになります。
もし、そのようなセッションが無いのにこういったメッセージが出る場合は、
サーバー側でmosh-server
が生き残ってしまっている場合があるので、
直接sshするなりしてプロセスをkillして来る必要があります。
また、いくつか試した中で、通常は~/usr/local
においてあるものを正しく
見てくれるのですが、中に
$ mosh server
bash: mosh-server: command not found
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.
といったふうに、mosh-server
コマンドを見つけられない所がありました。
.bashrc
等は等しく同じもので~/usr/
下も同じ構造なんですが、なぜだかよく分かりませんが、
とりあえず、moshには--server
と言うオプションでmosh-server
の位置を
教えられるので
$ mosh --server="~/usr/local/bin/mosh-server" server
$HOME/usr/local/bin/mosh-server: error while loading shared libraries: libprotobuf.so.8: cannot open shared object file: No such file or directory
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.
$
と、今度はLD_LIBRARY_PATHも設定がうまく行ってない模様。 仕方ないので、
$ mosh --server="LD_LIBRARY_PATH=~/usr/local/lib:$LD_LIBRARY_PATH ~/usr/local/bin/mosh-server" server
と、LD_LIBRARY_PATHまで指定してあげると動きました。
使ってみての感想
まず、普通につなげてみて、ネットワークを切ったりすると、
ssh
ではもちろん
[server ~] $ Write failed: Broken pipe
[local ~] $
みたいな感じでセッションが切れます。
これがmosh
だと、一番上に青いバックグラウンドとともに
mosh: sendto: Network is unreachable (15 s without contact.) [To quit: Ctrl-^ .]
と言ったメッセージが出ます。 この状態でもう一度ネットワークが繋がると、きちんと元に戻りました! ちょっと嬉しい。
普段、リモートで作業するときは必ずscreen を立ち上げるので、切れても作業状態へ復帰は出来るのですが、 ワイヤレス等で接続が悪いと、切れるたびに再接続させないといけないので 結構面倒です。 その煩わしさがちょっと減るので嬉しいかも。 ただ、ネットワークが繋がってから再び動き出すまでに少し時間がかかり過ぎな 感じもしました。(といっても数秒から数十秒程度ですが)
また、moshの一つの特徴であるinstant echo(local echo)は、 コマンドを打ち込むときにサーバー側がレスポンスする前にも ローカル側で表示だけしてしまう(サーバー側に送られてない部分は下線が表示される)、 というものですが、 これは確かにターミナルでコマンドを入力するには少し快適に感じるかな、と言った感じ。
実際にVimでの編集などはやはり変更が行われないと変更されないし、 書いた文字を消したりしたい場合には実際に待たないと行けなかったりするので、 あったらいいな、程度。 でもちょっと面白いです。
1つ注意としては、screenなどのセッションを立ち上げた中から moshを使って何処かへつなぐと、そのアウトプットが崩れるので、 スクロールバックした時などに本来の出力が見れなくなります4。
通常の使い方ではサーバー側にmoshでつないで、サーバー側でscreenを立ち上げる、 というのが多いのであまり問題にならないと思いますが、 screenの中から他につなげる事があってスクロールバックを良く使う人は moshを使わず直接sshした方が良さそうです。
その他現状の問題点等
Xが飛ばせない
まず第一に問題なのがXフォワードに対応してないことです。 まあ、とぎれとぎれになるのにきちんと対応させる事は結構難しそうですが、 moshでのセッションは最初からXが飛ばせません。 なので、Xを飛ばす作業には使えません。
ProxyCommandが使えない
Moshの中でPorxyCommandを使っているようなもの?なので、 ~/.ssh/configに書かれている設定のうち ProxyCommandの部分は無視されます。
なので、ちょっと前に多段ssh設定のまとめ で書いたようなログインサーバーを乗り越えて外から見えないサーバーへ moshでログイン、みたいなことは出来ません。
現状、一番簡単な解としては、ローカルからの直截 多段接続は諦めて、 moshでローカルとログインサーバーをつなぎ、 ログインサーバーから目的の隠れたサーバーまでは普通に sshで入る方法(上のポストのPuTTYの件の様な)。
$ mosh login.server ssh work.server
的な感じで、moshで接続した後に目的のサーバー(work.server)まで sshします。
通常、このようなログインサーバーと目的のサーバーは しっかりつながっていて途切れることなんて無いので、 実務上はこれで殆ど問題無いと思います。
鍵認証の場合には目的のサーバー用の秘密鍵を ログインサーバーが持ってないといけないことと、 ログインサーバーにmoshをインストールしないといけない、という点 さえ大丈夫ならこれで。
それから、上の下の方の議論の中で出てくるmosh_pc.sh というスクリプトが、目的はおいておいても、 サーバー側でmosh-server、クライアント側でmosh-client をmoshを使わずに別々に起動しているのですが、 moshがそれらをどのように使っているのかが理解でるので 一度見ておくとなんとなくmoshがやってることをわかった気になれます。
-
-fPIC
をつけないとこんな感じのエラーが出ました。... /usr/bin/ld: libcrypto.a(e_4758cca.o): relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC libcrypto.a(e_4758cca.o): could not read symbols: Bad value collect2: ld returned 1 exit status make[4]: *** [link_a.gnu] Error 1 make[4]: Leaving directory `$HOME/tmp/openssl-1.0.1h' make[3]: *** [do_linux-shared] Error 2 make[3]: Leaving directory `$HOME/tmp/openssl-1.0.1h' make[2]: *** [libcrypto.so.1.0.0] Error 2 make[2]: Leaving directory `$HOME/tmp/openssl-1.0.1h' make[1]: *** [shared] Error 2 make[1]: Leaving directory `$HOME/tmp/openssl-1.0.1h/crypto' make: *** [build_crypto] Error 1 $
-
これを忘れるとconfigure時に
checking for OPENSSL... no configure: error: Package requirements (openssl) were not met: No package 'openssl' found Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables OPENSSL_CFLAGS and OPENSSL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.
こんな感じのエラーが出ます。 ↩
-
Scrollback and alternate screen (was: Use alternate screen on smcup/rmcup ) · Issue #2 · keithw/mosh
殆ど読んでないですが、mosh単体でのscrollbackについては 今後1.3のリリースでは完璧になるとのこと。(HPのFAQにあり)
screen/tmuxのサポートについてはざっと読んだ限りではよくわからないですね。。。