Perl scp 从 windows 到 Linux 的文件

Perl scp a file from windows to Linux

Windows 上的这个 Perl 脚本 运行,我正在尝试将文件从本地机器 scp 到 Linux 机器,它没有打印任何错误,但复制文件。

use Net::SCP qw(scp);
$source = 'c:\temp\a.txt';
$destination = '/tmp';
$scp = Net::SCP->new( "$ip", "$user" ) or die "cannot scp $!";
print "scp $source $destination";
$scp->scp($source, $destination);
$scp = Net::SCP->new( "$ip", "$user" ) or die "cannot scp $!";
$scp = new Net::SCP;

调用 Net::SCP 构造函数两次。第二次,它在没有主机名或用户 ID 的情况下调用它,不检查 return 值,并覆盖您之前看起来正确的调用。删除第二行。

您正在测试调用 scp 对象的构造函数是否成功,但您并未测试实际执行 scp 操作是否成功。

这条线可以改进:

$scp->scp($source, $destination);

该模块的文档指出 scp returns 失败时为 false,并设置了 errstr 属性。因此,您可以按如下方式更改该行:

$scp->scp($source, $destination) or die 'scp failed: ', $scp->{errstr};

通过这样做,您应该获得有用的诊断信息,这是真正了解解决问题所必须采取的措施的唯一途径。

此外,与您的问题无关但值得一提:use Net::SCP qw(scp); 是错误的,因为它将 scp 函数导入到您的调用命名空间中。这是错误的原因是您正在使用 scp 的面向对象 "method call" 调用(换句话说,$scp->scp(...)。调用 scp 的方法调用方式不不需要将任何内容导入您的调用命名空间。

Net::SCP documentation有两个例子说明如何调用scp():

use Net::SCP qw(scp iscp);
scp($source, $destination);

$scp = new Net::SCP;
$scp->scp($source, $destination);

您会注意到,这两个版本都没有说明如何指定主机名、用户名或密码,或者复制操作是本地到远程还是远程到本地。

事实是 Net::SCP 文档没有很好地描述如何使用 scp()。查看 source code for the module 表明:

  1. scp() 子例程不使用传递给 Net::SCP 构造函数的任何值。
  2. scp() 调用 scp 命令行实用程序,将源和目标参数传递给该程序 verbatim.

因此,指定主机名、用户名、密码和复制方向的正确方法与 the scp command line utility 相同。您的 $source$destination 值必须遵循 scp 程序接受的一般形式。假设你正在尝试进行本地到远程的传输,你应该尝试这样的事情:

$source = 'c:\temp\a.txt';
$destination = "${user}\@${ip}:/tmp";
$scp = new Net::SCP;
$scp->scp($source, $destination);

这会生成一个格式为 "user@1.2.3.4:/tmp" 的目标,这是 scp 程序接受的格式。

如果您尝试进行远程到本地的复制,则应将“${user}\@${ip}:”字符串添加到 $source 而不是 $destination 之前。请注意,此处“@”前面有一个反斜杠,因为它在双引号字符串中很特殊。

顺便说一句,如果您使用两个本地路径名调用 scp 程序,它会调用系统的文件复制实用程序来执行本地复制操作。因此,您可能已将源文件名复制到 C:\tmp 或本地系统上的类似位置。