読者です 読者をやめる 読者になる 読者になる

end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転します

perlのNet::OpenSSHで、proxyサーバのように代理でscp getする

全く動作確認していませんが、多分、↓こんな感じです。

#!/usr/local/bin/perl
use strict;
use File::Path;
use File::Temp qw/tempfile tempdir/;
use Log::Log4perl;
use Net::OpenSSH;
use Data::Dumper;

#┌─────┐    ┌──────┐    ┌─────┐
#│caller    ├──┤proxy       ├──┤remote    │
#└─────┘    └──────┘    └─────┘
#ex. [caller]$ ssh hoge@proxy /path/to/get_remote_file.pl remote_file_path local_dir

my $CONF =
    {ssh=>{remote_host=>     'localhost',
           remote_user=>     'endo',
           remote_passwd=>   'XXXXXXXX',
           caller_host=>     'localhost',
           caller_user=>     'endo',
           caller_passwd=>   'XXXXXXXX'
          },
    log=>{
          'log4perl.rootLogger'=> 'DEBUG, LOGFILE',
#          'log4perl.rootLogger'=> 'INFO, LOGFILE',
          'log4perl.appender.LOGFILE'=>'Log::Log4perl::Appender::File',
          'log4perl.appender.LOGFILE.filename'=>'/home/endo/tmp/get_file.log',
          'log4perl.appender.LOGFILE.mode'=>'append',
          'log4perl.appender.LOGFILE.layout'=>'PatternLayout',
          'log4perl.appender.LOGFILE.layout.ConversionPattern'=>'%d [%p] %m %n'
         }
    };


Log::Log4perl::init($CONF->{log});
my $LOGGER = Log::Log4perl::get_logger("rootLogger");

main(@ARGV);
exit(0);


sub main {
    my ($remote_file,$caller_dir) = @_;

    #引数check
    if(not defined($remote_file) or length($remote_file) == 0 or
       not defined($caller_dir)  or length($caller_dir)  == 0){
        my $msg = "usage : $0 REMOTE_FILE CALLER_DIR : $!";
        $LOGGER->error($msg);
        die $msg;
    }

    #remote hostから自身(proxy)のtmp dirへ一旦、scp get
    my $tmp_dir = scp_get_from_remote($remote_file);
    #自身(proxy)からcallerへ、scp put
    scp_put_to_caller($tmp_dir,$caller_dir);

    #後片付け
    unless( File::Path::rmtree([$tmp_dir]) ){
        my $msg = "can't rmdir $tmp_dir";
        $LOGGER->error($msg);
        die $msg;
    }
}

sub scp_put_to_caller {
    my ($tmp_dir,$caller_dir) = @_;

    #caller hostへのssh接続
    my $ssh2caller = Net::OpenSSH->new($CONF->{ssh}->{caller_host},
                                       user  =>$CONF->{ssh}->{caller_user},
                                       passwd=>$CONF->{ssh}->{caller_passwd});
    if($ssh2caller->error){
        my $msg = join(' ',
                       "can't ssh to",
                       "host:$CONF->{ssh}->{caller_host} user:$CONF->{ssh}->{caller_user}",
                       $ssh2caller->error);
        $LOGGER->error($msg);
        die $msg;
    }

    #caller hostへのfile送付(scp put)
    $LOGGER->info("scp_put() $tmp_dir $CONF->{ssh}->{caller_host}:$caller_dir");
    unless( $ssh2caller->scp_put({glob =>1}, "$tmp_dir/*", "$caller_dir")){
        my $msg = join(' ',
                       "can't $CONF->{ssh}->{caller_host}:scp_put()",
                       "$tmp_dir $caller_dir",
                       $ssh2caller->error);
        $LOGGER->error($msg);
        die $msg;
    }

}

sub scp_get_from_remote {
    my ($remote_file) = @_;

    #remote hostへのssh接続
    my $ssh2remote = Net::OpenSSH->new($CONF->{ssh}->{remote_host},
                                       user  =>$CONF->{ssh}->{remote_user},
                                       passwd=>$CONF->{ssh}->{remote_passwd});
    if($ssh2remote->error){
        my $msg = join(' ',
                      "can't ssh to",
                       "host:$CONF->{ssh}->{remote_host} user:$CONF->{ssh}->{remote_user}",
                       $ssh2remote->error);
        $LOGGER->error($msg);
        die $msg;
    }

    #remote hostからのfile取得(scp get)
    my $tmp_dir = tempdir();
    $LOGGER->debug("tempdir is " . $tmp_dir);

    $LOGGER->info("scp_get() $CONF->{ssh}->{remote_host}:$remote_file $tmp_dir");
    unless( $ssh2remote->scp_get({glob=>1},$remote_file,$tmp_dir)){
        my $msg = join(' ',
                       "can't $CONF->{ssh}->{remote_host}:scp_get()",
                       "$remote_file $tmp_dir",
                       $ssh2remote->error);
        $LOGGER->error($msg);
        die $msg;
    }

    return $tmp_dir;
}

1;