【问题标题】:Transferring & Deleting Files From SFTP Using SFTP Foreign Module使用 SFTP 外部模块从 SFTP 传输和删除文件
【发布时间】:2016-04-21 03:19:22
【问题描述】:

我的要求是将文件和文件夹从 SFTP 远程位置传输到 unix 位置。我是 perl 和 shell 脚本的新手,这非常令人困惑。我尝试使用来自 sftp foreign 的 rget 命令,如下所示。但它不起作用,也没有被转移。从 sftp 服务器复制文件和文件夹后如何删除?

use Net::SFTP::Foreign;

my $host       = "sftp.elsevier.com";
my $remote_dir = "sample/host";
my $localdir = "sample/local";
my $username   = "username";
my $password   = "password";
my $debug      = 0;

$sftp = Net::SFTP::Foreign->new($host, timeout => 240,user => $username, password => $password) or $newerr = 1;
push @ERRORS, "Can't sftp to $host: $!\n" if $newerr;
myerr() if $newerr;
print "Connected to $host\n";

$sftp->rget($remote_dir, $localdir) or $newerr = 1;
push @ERRORS, "Cant tranfer\n" if $newerr;
myerr() if $newerr;
$sftp->disconnect if $newerr;
print "Files are transferred successfully\n";

#Deleting files

$sftp->setcwd($remote_dir) or $newerr = 1;
push @ERRORS, "Can't cd $!\n" if $newerr;
myerr()    if $newerr;
$sftp->disconnect if $newerr;

my $files = $sftp->ls or $newerr = 1;
push @ERRORS, "Can't get file list $!\n" if $newerr;
myerr() if $newerr;

foreach (@$files){
$sftp->remove($_) or $newerr = 1;
push @ERRORS, "Cant delete\n" if $newerr;
myerr() if $newerr;

print "Deleted files successfully\n";

#}
$sftp->disconnect;

sub myerr {
    print "Error: \n";
    print @ERRORS;
    exit 0;
}

在 SFTP 位置 - sample/host 中,我有许多文件夹和文件都需要复制到本地 unix 服务器 - sample/local 并从远程位置删除。

【问题讨论】:

  • 这有点跑题了,但是你是从哪里学到这种将参数传递给 subs 并进行错误处理的方式的?您是从一些教程或其他资源中获取的吗?我会非常对链接感兴趣,因为这是令人难以置信的糟糕风格。

标签: perl unix sftp delete-file


【解决方案1】:

您需要获得一本好的 Perl 书籍,这将帮助您学习如何以更现代的风格编写 Perl。我推荐Learning Perl。这应该教你一些编码技巧。

例如,始终使用use strict;use warnings;。这两个模块将捕获大约 99% 的编码错误。

此外,进行错误检查的标准方法是使用or die 样式语法。这是一种比设置变量,然后检查变量,如果有错误,则进入子程序更自然的方法:

$stfp->ls or die qq(Cannot access remote machine ) . HOST;

如果你也缩进也很好。让您更轻松地跟踪您的代码。

Perl 有一个标准,即变量应该全部小写,而最新的标准是使用下划线来帮助分隔变量名。常量应该全部大写。

您还应该查看模块的完整文档。例如,当您创建 Net::SFTP::Foreign 对象时有一个 autodie 选项,该选项将在任何失败时终止您的 sftp 会话。这简化了编码,因为您不必检查错误。

您还需要知道Net::SFTP::Foreign->ls 返回一个数组的引用。因此,您需要取消引用该数组。您还必须知道,这个 数组引用 中的每个条目实际上都是对哈希的引用,并且文件名位于该哈希引用的 filename 键下。

该文档还提到了一个小事实:该程序使用 Unix/Linux 安装的ssh 客户端。如果您没有安装 ssh 客户端,这将无法正常工作。

您可能想查看References 上的 Perl 教程

我已经重写了您的程序以利用autodie 并使用更现代的语法。通常,我会对此进行测试,但不幸的是,我没有安装 Net::SFTP::Foreign,也没有可用于测试的远程计算机:

#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use autodie;

use Net::SFTP::Foreign;

use constant {
    HOST            => "sftp.elsvier.com",
    REMOTE_DIR      => "sample/host",
    LOCAL_DIR       => "sample/local",
    USER_NAME       => "username",
    PASSWORD        => "password",
    DEBUG           => "0",
};

my $sftp;
$sftp = Net::SFTP::Foreign->new (
    HOST,
    timeout         => 240,
    user            => USER_NAME,
    password        => PASSWORD,
    autodie         => 1,
);

#
# Fetch Files
#
$sftp->rget( REMOTE_DIR, LOCAL_DIR );

#
# Delete Files
#

$sftp->setcwd( REMOTE_DIR );
my @files = @{ $sftp->ls };  #Returns a reference to an array of hashes

for my $file ( @files ) {
    $sftp->remove( $file->{filename} ); #Reference to a hash
}

say "Deleted files successfully";

$sftp->disconnect;

【讨论】:

  • 我想补充一点,$sftp = Net::SFTP::Foreign->new(...) 永远不会失败。它总是返回一个有效的对象,之后您必须检查sftp->error 以查看连接是否失败,或者正如您所指出的,只需使用autodie 功能。
  • @salva - 我打算在new 和每个方法调用之后使用$sftp->error 编写示例,直到我看到autodie 设置。我喜欢autodie。在任何失败的方法或构造函数上,所有方法都应写入autodie。然后,如果开发者想继续,他们必须使用evalTry::Tiny(应该是标准模块)来处理异常。这样,您就不会忘记处理问题。
  • @salva 我现在在我的帖子中看到了这个问题......当我给出or die 语法的示例时,我使用了new 构造函数。我将示例更改为使用$sftp->ls。我检查了代码,你是对的:new 总是返回一个Net::SFTP::Foreign 对象。我还看到开发人员正在使用$sftp->{_option} = delete $opt{_option}。这意味着如果我设置 option => 0 或 `option => `,该选项仍将打开。这也违背了大多数模块的编程方式。有时你真的需要看代码。
  • W: 使用 option => 0option => "" 确实会禁用该选项。
  • @salva 我查看了代码,发现他们通过获取键上的删除状态来处理方法设置部分的设置。例如:$sftp->{_autodie} = delete $opts{autodie};。在我的阅读中,如果我设置了autodie => 0。那么delete ${opts{autodie} 仍将返回true,因为autodie 键仍然存在于$opts 散列中,即使散列中该元素的值为0。我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
相关资源
最近更新 更多