Perl で、ssh でリモートのサーバにアクセスしてファイルをアップロード(SCP)する方法 (Net::SSH2)

バックアップのためにリモートのサーバにファイルをコピー(アップロード)したい。 そんな欲求が私の中に生まれた。Linux ではファイルを ssh でコピーするのに scp というコマンドがあるので、早速試してみたのは Net::SCP という Perl のモジュールなのだが、なぜかこのモジュールのメソッドにはパスワードを指定するものがない。ホスト名とユーザー名しか指定しないのだ。ではパスワードはどこにいった? Net::SCPに書いてあるように、どうやら ssh の手動コマンドのようにユーザー名とパスワードを指定するのではなく、パスワードは ssh-keygen -t rsa または dsa として、できた公開鍵をリモートサーバの ~/.ssh/authorized_key というところに置くことによって、セキュリティを高めるとともにパスワードが要らない、ということらしいのだ。うーんめんどい。しかし仕方がない、やってみようということで実際に私は試してみたのだが、いろいろ試してみてうまくいかなかった。ソースはこんな感じ。
<strong>use Net::SCP;</strong>

our $HOSTNAME = 'yourdomain.com';
our $USERNAME = 'yourname';
our $REMOTE_DIR = 'path_to_remote_dir';
our $FILENAME = 'filename_to_put';

$scp = Net::SCP->new($HOSTNAME, $USERNAME) or die $scp->{errstr};
$scp->login($USERNAME) or die $scp->{errstr};
$scp->cwd($REMOTE_DIR) or die $scp->{errstr};
$scp->put($FILENAME) or die $scp->{errstr};
$scp->quit;
仕方がないので Net::SSH::Expect モジュールを試してみるとことにした。
<strong>use Net::SSH::Expect;</strong>

our $HOSTNAME = 'yourdomain.com';
our $USERNAME = 'yourname';
our $PASSWORD = 'yourpassword';
our $LOCAL_FILE  = 'filename_to_put';
our $REMOTE_FILE = 'path_to_remote_file';

my $scp = Net::SCP::Expect->new();
$scp->host($HOSTNAME);
$scp->login($USERNAME, $PASSWORD);
$scp->scp($LOCAL_FILE, $REMOTE_FILE);
しかしこれでも成功しない。ほんじゃあ Net::SFTP はどうだ?
<strong>use Net::SFTP;</strong>

our $HOSTNAME = 'yourdomain.com';
our $USERNAME = 'yourname';
our $PASSWORD = 'yourpassword';
our $LOCAL_FILE  = 'filename_to_put';
our $REMOTE_FILE = 'path_to_remote_file';

my %arg = ('user'=>$USERNAME, 'password'=>$PASSWORD, 'debug'=>true, 'Passive'=>true);
my $sftp = Net::SFTP->new($HOSTNAME, %arg);
$sftp->put($LOCAL_FILE, $REMOTE_FILE);
うわ、ダメだ orz。そもそも FTP はできるのだろうか?
<strong>use Net::FTP;</strong>

our $HOSTNAME = 'yourdomain.com';
our $USERNAME = 'yourname';
our $PASSWORD = 'yourpassword';
our $LOCAL_FILE = 'filename_to_put';
our $REMOTE_DIR = 'path_to_remote_dir';

$ftp = Net::FTP->new($HOSTNAME, Debug => 1);
$ftp->login($USERNAME, $PASSWORD);
$ftp->cwd($REMOTE_DIR);
$ftp->put($LOCAL_FILE);
$ftp->quit;
今度はうまくいった。しかし!!! 2度実行させると 553 Could not create file. となりエラー。もちろんディレクトリやファイルのパーミッション、所有権もチェックした。いろいろ権限を変えてみたものの、同じエラーでつまずく。うーんじゃあ、Net::SSH2 モジュールはどうだ?
<strong>use Net::SSH2;</strong>

our $HOSTNAME = 'yourdomain.com';
our $USERNAME = 'yourname';
our $PASSWORD = 'yourpassword';
our $LOCAL_FILE  = 'filename_to_put';
our $REMOTE_FILE = 'path_to_remote_file';

my $ssh2 = Net::SSH2->new();

$ssh2->connect($HOSTNAME) or die;
if ($ssh2->auth_keyboard($USERNAME, $PASSWORD)) {
  $ssh2->scp_put($LOCAL_FILE, $REMOTE_FILE);
}
成功!何度でもコピーできる。しかも FTP と違ってセキュアだ。めでたしめでたし。
トラックバック URL: https://perltips.twinkle.cc/trackback/266
Posted on 2007-11-07 by yas |