从Unix脚本检查ftp返回码

时间:2008-09-26 14:53:58

标签: unix ftp scripting return

我目前正在创建一个调用Unix脚本的夜间作业,该脚本依次使用ftp创建和传输文件。我想查看所有可能的退货代码。 ftp的手册页未列出返回代码。有谁知道在哪里找到一个清单?有经验的人吗?我们有其他脚本可以在日志中查找某些返回字符串,并在出错时发送电子邮件。但是,他们经常会错过意料之外的代码。 然后我将原因放入日志和电子邮件中。

9 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:4)

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

答案 3 :(得分:3)

我认为运行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=$?

答案 4 :(得分:1)

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

答案 5 :(得分:1)

我喜欢Anurag的解决方案,因为字节传输问题我用grep -v“bytes”扩展了命令

grep“^ 530”ftp_out2.txt | grep -v“byte”

- 而不是530,你可以使用Anurag所做的所有错误代码。

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

FTPUSER是您的ftp用户登录名

FTPPASS是您的ftp密码

FILE是您要上传的本地文件,没有任何路径信息(例如file1.txt,而不是/whatever/file1.txt或者/ 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

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

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

请注意以下内容:

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

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

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

  4. 如果你真的,绝对必须使用普通的FTP客户端,你可以在脚本中测试失败的一种方法,首先是一个PUT文件的命令,然后是另一个执行相同的GET的命令文件以不同的名称返回。 FTP退出后,只需在shell脚本中测试下载文件是否存在,甚至在原始文件中对其进行校验,以确保正确传输。是的,这很糟糕,但在我看来,拥有易于阅读的代码比对每种可能的错误条件进行大量解析更好。 BSD FTP并不是那么好。

答案 8 :(得分:-1)

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