by 太田俊哉さん
太田俊哉さんにいただいたNet::SSHの翻訳なのです。
太田さんどうもありがとうございます(川合孝典 2002/2/28)
debug($msg)packet_start($packet_type)Net::SSH::Perl - Perl client Interface to SSH
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new($host);
$ssh->login($user, $pass);
my($stdout, $stderr, $exit) = $ssh->cmd($cmd);
Net::SSH::Perlは、SSH(Secure Shell)クライアントを実装しているPerlのみのモジュールである。これは、SSH-1とSSH-2プロトコルと互換性を持つ。
Net::SSH::Perlは、簡単に、そして、安全にリモート・マシンの命令を実行して、STDOUT、STDERRとそのリモート命令のexitステータスを受けるのを可能にする。 これは、サーバーが認証する(パスワード認証、RSAチャレンジ-レスポンス認証、その他)、いろいろなメソッドのビルトイン・サポートを含む。 これは、I/Oバッファリング、パケット・トランスポートとSSHプロトコルのユーザー認証層を完全にインプリメントして、外部のperlライブラリの使用法を用意する(Crypt:: ファミリモジュールで)安全でないネットワークを経由して送られる全てのデータの暗号化を取り扱う。 また、既存のSSH構成ファイル(/etc/ssh_configなど)、RSA identityファイル、DSA identityファイル、既知のhostファイル、その他を読むことができる。
sshクライアントのラッバー形式インプリメンテーション上で、Net::SSH::Perlを使うことの1つの利点は、それがプロセス・オーバーヘッドを軽減するということである。もはや1つのsshdに接続するために、別々のプロセスをフォークして実行する必要がない。プロセスをフォークするのに、大量の時間とメモリが必要になることに依存するので、この勝利は、全く相当でありえる。特に、新しいプロセスをフォークすることがプロセスとメモリ・リソースの消耗である、永続しているperl環境において動作しているならば(たとえば、mod_perl )。
これはまた、sshを囲んでラッバーを書くとき、多分sshクライアントを制御して、それにパスワードを与えるためにExpectを使う必要がある、パスワードに基づく認証を使うプロセスを単純化する。 Net::SSH::Perlは、認証プロトコルのビルトイン・サポートが用意されているので、もはや任意の外部のプロセスと通信する苦労は少しもない。
SSH2プロトコル・サポート(バージョン1.00として現在のNet::SSH::Perlで提供)は、OpenSSHでのSSH2インプリメンテーションと互換性を持って、また、充分に公式のSSHインプリメンテーションと互換性を持つべきである。
もしも、Net::SSH::Perlと互換性を持たないSSH2インプリメンテーションを発見したならば、(AUTHOR & COPYRIGHTSセクションでの電子メール・アドレス)知らせてください。いくつかのSSH2インプリメンテーションが他との微妙な違いを持っていることがわかる。
3DES (3des-cbc), Blowfish (blowfish-cbc)とRC4 (arcfour)暗号は現在SSH2による暗号化と完全性チェックに対してサポートされていて、hmac-sha1 かhmac-md5 アルゴリズムのとちらかによる完全性チェックが実行される。
圧縮が要求されても、方式はZlibに限られる。
サポートされたサーバー・ホスト・キー・アルゴリズムは、ssh-dss(既定値)とssh-rsa(Crypt::RSAを必要とする)であリ、また、サポートされたSSH2公開鍵認証アルゴリズムは、同じものである。
あなたがSFTPサポートを捜しているならば、SFTPのフル機能のperlインプリメンテーションを提供している、Net::SSH::Perlのトップに位置するNet::SFTPを見なさい。 SFTPは、SSH2プロトコルを使うことを必要とする。
Net::SSH::Perlの使用法は、非常にシンプルである。
新しいコネクションを確立するためには、$hostに繋ぎ、Net::SSH::Perlオブジェクトを返す、newメソッドを呼ぶ。
newは、%params中の、以下で名をつけられたパラメータを受け付ける。
2, 1, '1,2' か'2,1' のどちらかである。
最初の二つは全く単に、「プロトコルのこのバージョンを使うだけにすること(SSH-2またはSSH-1のそれぞれどちらか)を意味している。
後の二つはどちらのプロトコルも使うとができることを示すが、そのうちの1つのプロトコル(コンマで区切られたリストの最初の方)がもうに優先する。
この理由のため、どちらの手段でも接続を保証するので、後者2つのプロトコル仕様を使うことは「より確実に」接続ができる。 もし、サーバーが指示された最初の方のプロトコルをサポートしないならば、第二番目のプロトコルが使われる(多分、サーバーは、2つのプロトコルのうちの少なくとも1つをサポートする)。
既定値は、OpenSSHとの互換性のために、'1,2'である。これは、サーバーがSSH-1をサポートするならば、クライアントがSSH-1を使うことを意味する。
もちろん、常にこのユーザー/グローバルな構成ファイルを使うか、このコンストラクタ引数を使うことを通して、この既定値に優先して指定を行なうことができる。
SSH-1で、サポートされている暗号化方式は、IDEA、DES、DES3とBlowfishである。 SSH-2で、サポートされている暗号化方式は、arcfour、blowfish-cbcと3des-cbcである。
既定値のSSH-1暗号化方法は、IDEAである。既定値のSSH-2暗号化方式は、3des-cbcである。
既定値は、 3des-cbc,blowfish cbc,arcfour である。
既定値は 偽 である。
既定値は 偽 である。
このパラメータを提供しなく、Net::SSH::Perlがルートとして動作してないならば、これは自動的に 真 にセットされる。さもなければ、既定値は 偽 である。
これを提供しないならば、RSA認証は$ENV{HOME}/.ssh/identityファイルを既定値として使い、DSA認証は、$ENV{HOME}/.ssh/id_dsaファイルを既定値として使う。
圧縮は、既定値では行なわれない。
圧縮は、利用するシステム上にCompress::Zlibモジュールがインストールされている事を必要とする点に注意。 モジュールのロードが失敗すると、圧縮は無効になる。もし、デバッグを有効にしている(debugを1にセットしている)ならば、起動時に警告を受け取り、圧縮をオンにしようとする。
この設定はSSH-1にだけ適用できる。SSH-2 Zlib圧縮の圧縮レベルは、常に6にセットされる。
既定値は、6である。
シェルを起動しているならば 1 が既定値であり、その他の場合は 0 である。
このオプションが使用されると、configファイル中で使われる形式中のオプション・ディレクティブのリストへの参照であるべきである。以下が例である。
my $ssh = Net::SSH::Perl->new("host", options => [
"BatchMode yes", "RhostsAuthentication no" ]);
sshdデーモンで認証時に使われる、ユーザー名とパスワードをセットする。 ユーザー名$userは全ての認証プロトコル(リモート・サーバーに自分自身を識別するために)のために必要とされるが、もしも指定しないならば、プログラムを実行しているユーザーのユーザー名が使われる。 パスワード$passwordは、パスワード認証(暗号化されたRSA/DSA識別ファイル上のパスフレーズとしては使用されないが、たぶん)だけのために必要とされる。 そして、インタラクティブ・セッションで動作していて、かつ、パスワードを提供しないならば、パスワードのためのプロンプトが表示される。
リモート・サーバー上で命令$cmdを動作させ、stdout、stderrとその命令のexitステータスを返す。
$stdinが指定されると、リモートコマンド$cmdの標準入力に供給される。
注意: リモート・シェルがコマンドを評価することができるために、コマンドが一連になっている限り、SSH-1プロトコルは、コネクションあたり複数のコマンドの実行をサポートしない。 このため、cmdを呼び出すたび毎に新しいソケット・コネクションが作成され、終了後になくなる。言い換えれば、以下のコード
my $ssh = Net::SSH::Perl->new("host1");
$ssh->login("user1", "pass1");
$ssh->cmd("foo");
$ssh->cmd("bar");
は、cmdの最初の起動時に、実際にsshdに接続し、切断する。そして、第二番目のcmdの起動に一度接続し、切断する。
これはがSSH-2プロトコルにはあてはまらないことに注意。SSH-2は、同じコネクション上で複数のコマンド実行を十分にサポートする。
リモート・マシン上のインタラクティブ・シェルをオープンし、それをSTDINに接続する。 疑似TTYで使われるとき、これは最も効果的である。それ以外では、コマンド・ライン・プロンプトを得られず、シェルのようには見えない。この理由 -- それを特に避けている間は -- により、もしも、引数new(上記説明)に、use_ptyをセットしない場合でも、pty はリモート・マシンから要求される。
これは、対話型プログラムでのみ役に立つ。
それに加え、多分このメソッドを呼ぶ前に、手元のターミナルをraw入力にセットすることを希望するだろう。これは、タイプした文字を、Net::SSH::Perlに、各文字毎に処理させ、リモート・マシンに送る。
そうしたいならば、プログラム中でTerm::ReadKey を使うのがよい。
use Term::ReadKey;
ReadMode('raw');
$ssh->shell;
ReadMode('restore');
実際、プログラムがその行を処理する前に exitする場合に備えて、1つの ENDブロック中にrestore行を置くことをしてもよい。
もしも例を必要とするならば、sshシェルを実装するためのほとんど正確なコードを使っているeg/psshを参照しなさい。
クライアント・ループの間、タイプ$packet_typeのパケットを取り扱うために匿名のサブルーチン・ハンドラー$subrefを登録する。 タイプ$packet_typeのパケットを受け取った時、サブルーチンは呼ばれ、標準の引数(下記参照)に加えて、指定されるならば、@argsで任意の追加の引数を受けとる。
リモート・サーバーに送る命令をコマンドを送った後で、任意のSTDINデータが送られたあと、クライアント・ループに入る。 サーバーがリモートで実行されたコマンドのexitステータスを送るまで、サーバー(STDOUTパケット、STDERRパケット、その他)から、パケットを読み込む。この時点で、クライアントはクライアント・ループを抜け出し、サーバーから切り離される。
cmdメソッドを呼び出す時、クライアント・ループは既定値では単にSTDOUTパケットをスカラー変数に入れ、呼び出し側にその値を返す。STDERRパケットとプロセスのexitステータスにも同じことを行なう(cmdのドキュメントを参照)。
しかし、それらの既定の動作を変更でき、かつクライアントに送られるデータそれ自身を代わりに処理することができる。 これを行なうには、register_handlerメソッドを呼び出し、かつ、特定の時間に呼ばれるハンドラーをセットアップする。
register_handlerメソッドの動作は、Net::SSH::Perl SSH-1とSSH-2インプリメンテーション間では違う。これはプロトコルの違いに由来する(すべてのSSH-2クライアント-サーバー通信は、入力パケットが違って処理されることを意味するチャネル・メカニズムを経由する)。
use Net::SSH::Perl::Constants qw( :msg );
上記の文で、すべてのMSG定数を名前空間にロードするので、ハンドラーを登録する時に、それらを使うことができる。 この事を行なうためには、このメソッドを使いなさい。例は以下の通りである。
$ssh->register_handler(SSH_SMSG_STDOUT_DATA, sub {
my($ssh, $packet) = @_;
print "I received this: ", $packet->get_str;
});
パケット・オブジェクト上で呼ぶことができるメソッドについて学ぶために、Net::SSH::Perl::Bufferドキュメントと同じように、Net::SSH::Perl::Packetドキュメント(get_*とput_*メソッド)を参照しなさい。
明らかに、これらのハンドラーを書くことは、各パケットの内容についての若干の知識を必要とする。それのために、詳細に各パケット・タイプを説明するSSH RFCを通読しなさい。パケットから読んでもよい各々のデータタイプのためのget_*メソッドがある。
register_handlerを利用てリモートコマンドと相互に作用する例は、eg/remoteinteract.plを見よ。
stdoutかstderrでなければならない。他のどのような文字列も、黙って無視される。
stdoutは、サーバーから送られてくるSTDOUTデータを扱い、stderrは、STDERRデータを扱うことを望むことを意味する。
サブルーチンへの参照では、2つの引数が渡される。それは、データが送られたオープン・チャネルを表すNet::SSH::Perl::Channelオブジェクトと、サーバから読んだデータを含むNet::SSH::Perl::Bufferオブジェクトである。 これらの2つの引数に加えて、コールバック時にはregister_handlerに渡した任意の追加の引数@argsも受けとる。これは、希望する場合、その他のプライベートな変数の一部に、コールバック関数がアクセスすることを与えるために使わうことができる。
これは、SSH-1とSSH-2インプリメンテーションの2つの主な違いを図示する。最初の違いは上記で説明した通りであリ、クライアントとサーバー間の主なコネクションのトップに構築されたチャネルを通して、サーバーとクライアント間の全てのコミュニケーションが終了する。 複数のチャネルは、同じコネクションの上に多重送信される。 第二の違いは、SSH-1では、入ってきた実際のパケットを処理しているということであリ、SSH-2では、パケットがどこかで処理済みで、その内容がバッファにおいて保存されていて、そのバッファを処理するということである。
上記の、SSH-1でregister_handlerを使う(I received thisの例)は、SSH-2では以下のようになる。
$ssh->register_handler("stdout", sub {
my($channel, $buffer) = @_;
print "I received this: ", $buffer->bytes;
});
上記のように、重要な2、3の違い以外、SSH-1で使われる形式に似ているが、それは、SSH-1とSSH-2間の違いで言及されるものである。
基本的なSSHの必要性は、上記でリストされるメソッドによって有効に達成できる。 しかし、もしもそうでなけれらば、ここでリストされる追加のメソッドの一部を使ってもよい。 それらの一部は、他が書いた、エンドユーザ向けの、実際により便利であろう認証モジュールまたは暗号、その他である。
SSHオブジェクトのために構成データを管理しているNet::SSH::Perl::Configオブジェクトを返す。 これはコンストラクタnew(上記参照)から渡されるデータから構成され、ユーザーとシステムの構成ファイル読み出されたデータがマージされる。 このオブジェクト(多分getとsetメソッドにより興味を持つだろう)を呼ぶことができるメソッドに関する詳細は、Net::SSH::Perl::Configドキュメントを参照のこと。
sshdへのソケット・コネクションを返す。もしもクライアントが接続されていないと die が実行される。
debug($msg)debuggingが現セッションでオンにされていると(上記のnewメソッドへのdebugパラメータを参照)、STDERRへ$msgを出力する。その他の場合は何もしない。
タイプNet::SSH::Perl::Bufferのオブジェクトである入力データ・バッファである。 バッファ・オブジェクトを返す。
このアイデアの背景は、ソケットが非ブロッキングであり、そのため、完全なパケットを読んだか、入力をバッファし、それを観察するために定期的にチェックする事である。 もしも、完全なパケットがあれば、入力データ・バッファからそれを取り出し、処理し、それを問い合わせた呼び出し側に返す。
このデータは、Net::SSH::Perl::Packet中の根底にあるパケット層に「属している」。 あなたが本当に、何をしようとしているか真に分かっていない限り、そのデータを捨ててはならない。
キーと共に送られるチェックビットと、サーバーのホストとサーバー・キーから生成されるセッションIDを返す。 サーバーは、(例えばRSAチャレンジに応答する時)他のパケットの中で渡されるセッションIDを必要としてもよい。
packet_start($packet_type)タイプ$packet_typeの新しいパケットの構築を始める。 これは、怠惰な人々のためのちょうど手ごろなメソッドである。 内部では、Net::SSH::Perl::Packet::newを呼び出すので、詳細はそれらのドキュメントに目を通しなさい。
サンプル/チュートリアルは、配布ディレクトリeg/中のスクリプトにある。
なにか質問、コード・サンプル、バグ・レポートまたはフィードバックをがあるならば、、以下の宛先に電子メールを送ってください
ben@rhumba.pair.com
Benjamin Trott, ben@rhumba.pair.com
特に記述がある場合を除いて、Net::SSH::PerlはCopyright 2001 Benjamin Trott である。 著作権所有。 Net::SSH::Perlは、フリー・ソフトウェアであリ、再配布および修正は、はperlと同じ条件の下で大なってもよい。
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。