当前位置: 首页 > 知识库问答 >
问题:

Perl sftp与net::sftp::foreign一起下载

柳豪
2023-03-14

我是个初学者。我编写了一个perl脚本,该脚本执行以下操作

-在当前日期之前在“/X01/ABCD/ABC_LOGS/ABCD_LOGS”下创建目录,如果尚未创建,则以“YYYYMMDD”的格式创建。即:如果脚本在“2013年1月1日”运行,则在该路径下创建目录“20130101”。因此,每当需要检查日志时,总是查找当前日期之前的目录。

我有一个困难的时间,想出一个解决方案,打印一个消息时,没有文件在共享。当然,这是当用户指定了2个或更多的文件,而这些文件并不存在于共享中时。我知道发生这种情况是因为在“sub get_logs”中有一个“die”语句。我似乎无法理解当我指定的所有文件都不在共享中时如何返回消息。

此脚本的用法如下

./ABC_LOGS....<文件(n)>

my $LOGS_LOCAL_PATH = "/x02/abc/abcba2/";
chomp $LOGS_LOCAL_PATH;
my $LOGS_REM_PATH = "/x01/INT/abc/vabc2/";
chomp $LOGS_REM_PATH;
my $TODAY = `date +%Y%m%d`;
chomp $TODAY;
my @GETLOOP = @ARGV;
    unless ($#ARGV >= 0) {
        print "\nUsage: gtp_logs.pl <file1> <file2> <file3>.....<file(n)>\n\n";
        exit;
    }
        system("clear");
    unless ( -d "$LOGS_LOCAL_PATH"."$TODAY") {
        print "Directory \"$TODAY\" doesn't exist. So creating the directory..!\n";
        print "OK..Done.....!\n\n";
        system("mkdir $LOGS_LOCAL_PATH/$TODAY");
        }
    else {
        print "Directory already exists. Logs will be downloaded to ==>     \"$LOGS_LOCAL_PATH$TODAY\".....!\n\n";
    }
    
               # if_DOWNLOADED($LOGS_LOCAL_PATH,$TODAY,@GETLOOP);
    
    chdir("$LOGS_LOCAL_PATH"."$TODAY") || die "cannot cd to  ($!)";
    foreach my $GETL (@GETLOOP) {
    my $is_downloaded = if_DOWNLOADED($LOGS_LOCAL_PATH,$TODAY,$GETL);
    if(!$is_downloaded)
    {
        get_LOGS("172.25.70.221","abc","abc2","/x01/INT/abc",$GETL);
        print "File \"$GETL\" downloaded to ==>          \"$LOGS_LOCAL_PATH$TODAY\"\n\n";
    }
    else
    {
        print "File \"$GETL\" has already been Downloaded to ==>          \"$LOGS_LOCAL_PATH$TODAY\"\n\n";
    }
    
    
    }
    

 sub get_LOGS {
    my $LOG_HOST  = shift;
    my $REM_USER  = shift;
    my $REM_PASSW = shift;
    my $REM_PATH  = shift;
    my $REM_FILE  = shift;
    
        print "Connecting to the sftp share! Please wait....!\n";
        my $sftp = Net::SFTP::Foreign->new($LOG_HOST, user => $REM_USER, password => $REM_PASSW);
        $sftp->setcwd($REM_PATH) or die "unable to change cwd: " . $sftp->error;
        print "OK. On the share! Downloading the file \"$REM_FILE\"...................!\n\n\n\n";
        $sftp->error and die "Problem connecting to the share...!!!! " . $sftp->error;
        $sftp->get($REM_FILE) or die "File does not seem to be present on the remote share. Please re-request..!!!" . $sftp->error;
        return $REM_FILE;
}
   
sub if_DOWNLOADED {
    my $DWD_FILE_PATH = shift;
    my $DWD_DIR       = shift;
    my $DWD_FILE      = shift;
    if (-e "$DWD_FILE_PATH/$DWD_DIR/$DWD_FILE")
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

请有人能帮我找到解决这件事的办法吗?请尝试使用相同的脚本并修改。

/V

共有1个答案

缑嘉玉
2023-03-14

代码的一些注释:

>

  • 使用严格和警告,以便及早发现大量错误。

    阅读一些关于风格的书(例如,Damian Conway的Perl最佳实践)。但在任何情况下,在命名变量、子程序和所有内容时,都要与它们的大小写保持一致。

    不要为琐碎的事情使用子程序。

    您不需要对已定义且结尾没有“\n”字符的变量调用chomp

    为每次文件传输打开一个新的SFTP连接是非常低效的。您可以在开始时只打开一个,并将其用于所有传输。

    现在是脚本的简化版本:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $host = "172.25.70.221";
    my $user = "abc";
    my $password = "abc1234321";
    
    my $LOGS_LOCAL_PATH = "/x02/ABC/abc2";
    my $LOGS_REM_PATH = "/x01/INT/abc/vim";
    my $TODAY = `date +%Y%m%d`;
    chomp $TODAY;
    my $TODAY_LOCAL_PATH = "$LOGS_LOCAL_PATH/$TODAY";
    
    my @files = @ARGV;
    @files or die "\nUsage: gtp_logs.pl <file1> <file2> <file3>.....<file(n)>\n\n";
    
    system("clear");
    
    if ( -d $TODAY_LOCAL_PATH) {
        print "Directory already exists. Logs will be downloaded to ==>     \"$TODAY_LOCAL_PATH\".....!\n\n";
    }
    else {
        print "Directory \"$TODAY\" doesn't exist. So creating the directory..!\n";
        mkdir "$TODAY_LOCAL_PATH" or die "unable to create directory: $!\n";
        print "OK..Done.....!\n\n";
    }
    
    chdir $TODAY_LOCAL_PATH or die "cannot cd to  ($!)\n";
    
    my $sftp =  Net::SFTP::Foreign->new($host, user => $user, password => $password);
    $sftp->error
        and die "Problem connecting to the share...!!!! " . $sftp->error;
    
    my $ok = 0;
    my $failed = 0;
    foreach my $file (@files) {
        if (-e "$TODAY_LOCAL_PATH/$file") {
            print "File \"$file\" has already been Downloaded to ==>          \"$TODAY_LOCAL_PATH\"\n";
        }
        else {
            if ($sftp->get("$LOGS_REM_PATH/$file")) {
                print "File \"$file\" downloaded to ==>          \"$TODAY_LOCAL_PATH\"\n";
                $ok++;
            }
            else {
                print "Unable to download file \"$file\" : " . $sftp->error . "\n";
                $failed++;
            }
        }
    }
    
    print "$ok files have been downloaded, $failed files failed!\n\n";    
    

  •  类似资料:
    • 我使用的是net::ftp::foreign,但我一直收到一个关于文件找不到的错误,我不确定是我的语法错了还是我误解了如何使用它。 我得到的错误是远程端不存在这样的文件,但我已经确认当我执行LS cmd时它们确实存在。 我的脚本有什么明显的错误导致它不能工作吗? 另外,我使用的是net::sftp::foreign因为net::sftp不会构建在运行10.7的MBP上

    • 我的本地计算机上有一个文件。我有一个Perl脚本可以通过SFTP连接将此文件复制到远程位置()。

    • 在调用时,连接不会关闭,Perl脚本处于挂起状态,直到我手动终止进程。 下面是我在nohup.out文件中得到的错误。

    • 我是不是漏掉了什么?我很确定编码sshPrivateKey字节[]是一种方法(如果我不这样做,JSCH会抱怨错误的密钥),但我不确定我还缺少什么?

    • 我需要做一个服务器应用程序,监听几个TCP连接。这个应用程序必须是轻量级的和TCP连接将来自GPS设备(不是从浏览器,所以我不能使用WebSockets例如)。 为了确保这可以适当地扩展到数千台设备,我需要充分利用所有机器的CPU。根据我的研究,我发现了两种做这件事的方法: 创建服务器并使用本地API node.js提供的 创建一个应用程序,并使用PM2将其“分叉”到所有CPU上 根据我的理解,这

    • 我正在尝试从SFTP服务器位置下载文件,但日志看起来不错,最后没有任何东西从服务器下载到本地。没有错误也来了。请提前感谢您的意见。 可用的 SFTP 文件: 路由器: 日志: 砰.xml