2009/05/22(Fri)2段ssh
2009/05/22 1:28
ここに対してsshセッションを外側張りたい場合、基本的には、インターネットからリーチャブルなゲートウェイの働きをするsshdを通して、その中でさらにssh、つまり2段sshをやるわけだが、sshコマンドを2回も打つのがめんどくさい。どうにか1コマンドで済まないものか。
ssh hostname [command]
ご存じない人もいるかも知れないが、sshコマンドには、ホスト名の後にコマンドを指定すると、ログインした後対話シェルに入らず、コマンドの結果だけを表示して終了する仕様である。manを引くと
NAME ssh - OpenSSH SSH client (remote login program) SYNOPSIS ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-e escape_char] [-F configfile] [-i identity_file] [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-R [bind_address:]port:host:hostport] [-S ctl_path] [-w local_tun[:remote_tun]] [bf:{[user@]hostname [command]}]というように、最後にcommandがoptionalながら指定できる。
例えば、$ ssh username@example.com cat /proc/cpuinfoのようにうつと、リモートのCPUの情報が表示された後、現在のシェルに戻ってくる。
では単純に…??
例として、- gateway.example.com
- インターネットから自由にアクセスできるゲートウェイサーバー
- remote.example.com
- NATの内側にいる目的のリモートサーバー
では単純に$ ssh gateway.example.com ssh remote.example.comとすればよいかというと、これがそううまくはいかない。
何故なら、先ほど説明したように、$ ssh hostname [command]の形式は対話シェルを原則許可していないからである。
このようなコマンドを打った場合、次のように表示されて、プロンプトは現れない。
$ ssh gateway.example.com ssh remote.example.com Pseudo-terminal will not be allocated because stdin is not a terminal.
解決策
sshのオプションにある-tオプションを用いる。manをみると、-t Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.'pseudo'(シュード)というのは、見せかけの/擬似的という意味で、execute screen-based programs on a remote machine、つまり、シェルのようなスクリーンを占有するアプリケーションを起動できるようになるというわけである。
つまり、$ ssh -t gateway.example.com ssh remote.example.comとすればよい。
毎度打つのは面倒なので、シェルスクリプトにしてもよいし、もっと横着したければ私のように.bashrcにaliasを書いてもよい。
$ echo alias remote=\'ssh -t gateway.example.com ssh remote.example.com\' >> ~/.bashrc $ source ~/.bashrc繋ぎに行きたいときは、
[user@local]$ remote [user@remote]$こんな感じ。