【问题标题】:Checking ftp return codes from Unix script检查 Unix 脚本的 ftp 返回码
【发布时间】:2010-09-13 11:47:49
【问题描述】:

我目前正在创建一个调用 Unix 脚本的通宵作业,该脚本又使用 ftp 创建和传输文件。我想检查所有可能的返回码。 ftp 的手册页没有列出返回码。有谁知道在哪里可以找到清单?有这方面经验的人吗?我们还有其他脚本在日志中对某些返回字符串进行 grep,并在出错时发送电子邮件。然而,他们经常错过意料之外的代码。 然后我将原因放入日志和电子邮件中。

【问题讨论】:

  • 谢谢大家,您可能已经知道了,我的 unix 脚本还没有走得太远。我基本上是从以前在这里工作的人的其他脚本中工作的。但是,我想让它比我迄今为止发现的更防弹。到目前为止,我感谢所有答案。
  • 到目前为止,基本上我的代码如下: echo " open $ftpip pwd binary lcd /out cd /in mput $datafile quit"|ftp -iv > $ftpreturn -v 选项看起来像我需要。但是 $ftpreturn 变量是空白的。该文件没有得到 ftp'​​d 并且正在静默失败。我错过了什么?

标签: unix ftp scripting return


【解决方案1】:

在我遇到的大多数实现中,ftp 命令不会返回零以外的任何值。

最好处理日志中的三位数代码 - 如果您要发送二进制文件,您可以检查发送的字节是否正确。

三位数字代码称为“系列代码”,可以在here找到一个列表

【讨论】:

  • 很抱歉,我有两个问题。 1)但是日志在哪里?我假设它会在 $ftpreturn 中。 2) 如何检查发送的字节数?
  • 提示:使用 -v(详细)从 FTP 命令获取返回码。
【解决方案2】:

我编写了一个脚本来一次只传输一个文件,并在该脚本中使用grep 来检查226 Transfer complete 消息。如果找到,grep 返回 0。

ftp -niv < "$2"_ftp.tmp | grep "^226 "

【讨论】:

    【解决方案3】:

    安装ncftp 包。它带有ncftpgetncftpput,它们都会尝试上传/下载单个文件,如果出现问题,会返回描述性错误代码。请参阅man page 的“诊断”部分。

    【讨论】:

      【解决方案4】:

      如果出现问题,我认为运行 ftp 并检查 ftp 的退出代码会更容易。

      我按照下面的例子做了这个:

      # ...
      ftp -i -n $HOST 2>&1 1> $FTPLOG << EOF
      quote USER $USER
      quote PASS $PASSWD
      cd $RFOLDER
      binary
      put $FOLDER/$FILE.sql.Z $FILE.sql.Z
      bye
      EOF
      
      # Check the ftp util exit code (0 is ok, every else means an error occurred!)
      EXITFTP=$?
      if test $EXITFTP -ne 0; then echo "$D ERROR FTP" >> $LOG; exit 3; fi
      if (grep "^Not connected." $FTPLOG); then echo "$D ERROR FTP CONNECT" >> $LOG; fi 
      if (grep "No such file" $FTPLOG); then echo "$D ERROR FTP NO SUCH FILE" >> $LOG; fi 
      if (grep "access denied" $FTPLOG ); then echo "$D ERROR FTP ACCESS DENIED" >> $LOG; fi
      if (grep "^Please login" $FTPLOG ); then echo "$D ERROR FTP LOGIN" >> $LOG; fi
      

      编辑: 为了捕捉错误,我 grep ftp 命令的输出。但这确实不是最好的解决方案。

      我不知道您对 Perl、Python 或 Ruby 等脚本语言有多熟悉。它们都有一个可供您使用的 FTP 模块。这使您能够在每个命令之后检查错误。这是 Perl 中的一个示例:

      #!/usr/bin/perl -w
      use Net::FTP;
      $ftp = Net::FTP->new("example.net") or die "Cannot connect to example.net: $@";
      $ftp->login("username", "password") or die "Cannot login ", $ftp->message;
      $ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message;
      $ftp->binary;
      $ftp->put("foo.bar") or die "Failed to upload ", $ftp->message;
      $ftp->quit;
      

      为了使这个逻辑正常工作,用户还需要从 ftp 命令重定向 STDERR,如下所示

      ftp -i -n $HOST >$FTPLOG 2>&1 << EOF
      

      下面的命令将始终分配 0(成功),因为 ftp 命令不会返回成功或失败。所以用户不应该依赖它

      EXITFTP=$?
      

      【讨论】:

      • 据我了解,ftp 返回是不可信的。如下科林所述。
      【解决方案5】:

      我知道蹩脚的答案,但是如何获取 ftp 源并自己查看

      【讨论】:

        【解决方案6】:

        我喜欢 Anurag 的解决方案,对于字节传输问题,我使用 grep -v "bytes" 扩展了命令

        grep "^530" ftp_out2.txt | grep -v "字节"

        -您可以像 Anurag 那样使用所有错误代码,而不是 530。

        【讨论】:

          【解决方案7】:

          你说你想把文件 FTP 到那里,但你没有说普通的 BSD FTP 客户端是否是你想把它送到那里的唯一方法。 BSD FTP 不会为需要所有解析的错误条件提供返回代码,但是如果您或您的管理员将安装它们,则可以使用一系列其他 Unix 程序通过 FTP 传输文件。我将为您提供一些通过 FTP 传输文件的方法示例,同时仍然可以用少量代码捕获所有错误情况。

          FTPUSER 是您的 ftp 用户登录名

          FTPPASS 是您的 ftp 密码

          FILE 是您要上传的本地文件,没有任何路径信息(例如 file1.txt,而不是 /whatever/file1.txt 或whatever/file1.txt

          FTPHOST 是您要通过 FTP 连接到的远程计算机

          REMOTEDIR 是您要上传到的远程计算机上的位置的绝对路径

          以下是示例:

          curl --user $FTPUSER:$FTPPASS -T $FILE ftp://$FTPHOST/%2f$REMOTEDIR

          ftp-upload --host $FTPHOST --user $FTPUSER --password $FTPPASS --as $REMOTEDIR/$FILE $FILE

          tnftp -u ftp://$FTPUSER:$FTPPASS@$FTPHOST/%2f$REMOTEDIR/$FILE $FILE

          输入 $FILE ftp://$FTPUSER:$FTPPASS@$FTPHOST/%2f$REMOTEDIR/$FILE

          如果出现任何问题,所有这些程序都将返回一个非零退出代码,以及指示失败的文本。您可以对此进行测试,然后根据需要对输出进行任何操作、记录、发送电子邮件等。

          但请注意以下几点:

          1. “%2f”在 URL 中用于指示以下路径是远程计算机上的绝对路径。但是,如果您的 FTP 服务器对您进行 chroot,您将无法绕过。

          2. 对于上述使用实际 URL (ftp://etc) 到服务器并嵌入用户和密码的命令,如果用户名和密码包含特殊字符,则必须进行 URL 编码。

          3. 在某些情况下,一旦您熟悉了每个程序的语法,您就可以灵活地将远程目录设为绝对目录,将本地文件设为纯文件名。您可能只需要添加一个本地目录环境变量或对所有内容进行硬编码。

          4. 1234563文件以不同的名称返回它。在 FTP 退出后,只需在您的 shell 脚本中测试下载的文件是否存在,或者甚至将其与原始文件进行校验,以确保它正确传输。是的,这很臭,但在我看来,拥有易于阅读的代码比对每种可能的错误情况进行大量解析要好。 BSD FTP 并不是那么好。

          【讨论】:

            【解决方案8】:

            这是我最终选择的。感谢所有的帮助。所有的答案都帮助我朝着正确的方向前进。 检查结果和日志可能有点矫枉过正,但它应该涵盖所有基础。

            echo "open ftp_ip
            pwd
            binary    
            lcd /out
            cd /in
            mput datafile.csv
            quit"|ftp -iv > ftpreturn.log
            
            ftpresult=$?
            
            bytesindatafile=`wc -c datafile.csv | cut -d " " -f 1`    
            bytestransferred=`grep -e '^[0-9]* bytes sent' ftpreturn.log | cut -d " " -f 1`    
            ftptransfercomplete=`grep -e '226 ' ftpreturn.log | cut -d " " -f 1`
            
            echo "-- FTP result code: $ftpresult" >> ftpreturn.log
            echo "-- bytes in datafile: $bytesindatafile bytes" >> ftpreturn.log
            echo "-- bytes transferred: $bytestransferred bytes sent" >> ftpreturn.log
            
            if [ "$ftpresult" != "0" ] || [ "$bytestransferred" != "$bytesindatafile" ] || ["$ftptransfercomplete" != "226" ]    
            then    
              echo "-- *abend* FTP Error occurred" >> ftpreturn.log    
              mailx -s 'FTP error' `cat email.lst` < ftpreturn.log
            else    
              echo "-- file sent via ftp successfully" >> ftpreturn.log    
            fi
            

            【讨论】:

              【解决方案9】:

              为什么不直接将命令的所有输出存储到日志文件中,然后检查命令的返回码,如果不为 0,则在电子邮件中发送日志文件?

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-11-05
                • 2010-09-05
                • 1970-01-01
                • 1970-01-01
                • 2014-12-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多