如何获取 Net::OpenSSH->scp_get() 方法复制的文件列表

Posted

技术标签:

【中文标题】如何获取 Net::OpenSSH->scp_get() 方法复制的文件列表【英文标题】:How to get a list of file copied by Net::OpenSSH->scp_get() method 【发布时间】:2012-11-28 22:34:48 【问题描述】:

我想将一个目录从远程机器复制到本地。为此,我正在使用 Net::OpenSSH perl 模块。它工作正常,文件也被复制到我的本地机器上。但我想获取复制的文件列表。如何获取文件列表。

我不想使用 Net::SCP。

use Net::OpenSSH;
use Data::Dumper;

my $host='1.1.1.1';
my $credentials=username => 'root', password =>'abc123';

my $ssh_obj = Net::OpenSSH->new(
                $host,
                user     => $credentials->username,
                password => $credentials->password,

            );
ooen $fh, ">/tmp/abc_scp" or die "$!";
my $opts=recursive => 1, glob => 1, timeout => 100, quiet => 1,stderr_to_stdout => 1,stdout_fh => $fh;
my $op=$ssh_obj->scp_get($opts, "/home/ABC", "/tmp/");

【问题讨论】:

您的ooen 声明中有错字;) 如果您启用 'verbose=>1',它将打印发送的文件。不幸的是,您还必须筛选所有调试语句。 【参考方案1】:

Net::OpenSSH scp 方法不允许这样做,但还有其他方法:

使用tar

$ssh->system(stdout_file => '| (cd /tmp/ && tar xvzf - ) 2>tar.log',
             '(cd /tmp/ABC && tar czf - .)');

那么您将不得不阅读tar.log 以获取复制的文件列表。

通过 Net::OpenSSH + Net::SFTP::Foreign(或只是 Net::SFTP::Foreign)使用 SFTP:

# untested!
my $ssh = Net::OpenSSH->new(...);
my $sftp = $ssh->sftp;

my @log;
$sftp->rget("/home/ABC", "/tmp",
            wanted => sub  push @log, $_[1]->filenane ,
            on_error => sub  push @log if $_[1]->filename eq $log[-1] );

使用可以在 Net::OpenSSH 之上运行的 Net::SSH::Any 的 development version:

my $ssh = Net::SSH::Any->new($host, ..., backend => 'Net::OpenSSH');
my @log;
$ssh->scp_get(recursive => 1, action_log => \@log, "/home/ABC", "/tmp");

Net::OpenSSH 本身并没有实现 SCP 协议,而是使用 OpenSSH scp 二进制文件,遗憾的是它不会返回复制的文件列表。 Net::SSH::Any 有自己的用 Perl 编写的 SCP 实现,因此可以做更多的事情。最终,一旦 Net::SSH::Any 上的 SCP 实现成熟,我可能会将其反向移植到 Net::OpenSSH。

【讨论】:

【参考方案2】:

您真的应该考虑只使用rsync 和无密码的基于密钥的 ssh,而只需从 Perl 调用它。它将为您带来以下好处:

第二次和进一步尝试的同步时间非常快。它甚至会重新开始大文件的部分下载。 不太依赖 Perl,或者有时是奇怪的模块行为(不要误会 - 我喜欢 Perl,但一切都有它的位置)。

您可以进行递归同步并删除旧的本地文件:

rsync -av --delete --progress --partial --stats \
      user@host:/src/dir/ dst/dir/
您将获得同步文件列表(使用选项-v - 详细)。 您可以使用 rsync 选项 --stats 获取一些同步统计信息。 您可以使用--bwlimit 选项限制同步进程使用的网络带宽。 您不应该将密码(尤其是 root!)嵌入到您的脚本中。配置无密码 ssh 并更好地睡眠。 rsync 将使用它。

【讨论】:

我不能使用你的建议,因为我不想使用系统调用。我的某些机器没有 rsync 命令。

以上是关于如何获取 Net::OpenSSH->scp_get() 方法复制的文件列表的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 perl 和 Net::OpenSSH 在远程机器上启动后台进程?

如何使用 Perl 的 OpenSSH 读取输出的每一行

如何在 perl 的 openssh 中指定 -v 选项

Net::OpenSSH::Gateway->find_gateway 在设置 ControlPersist 选项时失败

如何使用 perl 和 Net::OpenSSH 检测远程端是不是只处理协议 1?

Windows 上的 openSSH 错误