从Unix脚本检查ftp返回代码

时间:2020-03-06 14:47:21  来源:igfitidea点击:

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

解决方案

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

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

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

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

这三个数字代码称为"系列代码",可以在此处找到列表

我认为运行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;

安装ncftp软件包。它带有ncftpget和ncftpput,它们将分别尝试上载/下载单个文件,如果有问题,则返回描述性错误代码。请参见手册页的"诊断"部分。

这就是我最后去的。感谢所有帮助。所有的答案都有助于我朝正确的方向前进。
检查结果和日志可能有点过大,但它应该涵盖所有基础。

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

我们说过要在那里传输文件,但是并没有说普通BSD FTP客户端是否是在那里传输文件的唯一方法。 BSD FTP不会为我们提供必须进行所有分析的错误情况的返回码,但是如果我们或者管理员将其安装,则还有其他一系列Unix程序可用于通过FTP传输文件。我将为我们提供一些通过FTP传输文件的方式的示例,同时仍然可以使用少量代码捕获所有错误情况。

FTPUSER是ftp用户登录名

FTPPASS是ftp密码

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

如果发生任何错误,所有这些程序都将返回非零退出代码,以及指示失败原因的文本。我们可以对此进行测试,然后根据需要对输出进行任何操作,记录,通过电子邮件发送,等等。

但是请注意以下几点:

  • URL中使用"%2f"表示以下路径是远程计算机上的绝对路径。但是,如果FTP服务器chroot我们,我们将无法绕过它。
  • 对于上面使用到服务器的实际URL(ftp:// etc)且其中嵌入了用户名和密码的命令,如果用户名和密码包含特殊字符,则必须使用URL编码。
  • 在某些情况下,一旦我们熟悉每个程序的语法,就可以灵活地将远程目录设置为绝对目录,将本地文件设置为纯文件名。我们可能只需要添加本地目录环境变量或者仅对所有内容进行硬编码。
  • 如果确实要绝对使用常规的FTP客户端,则可以通过以下方法测试失败的一种方法:在脚本中,包括首先输入文件的命令,然后执行对同一文件进行GET的命令,并在不同的情况下将其返回姓名。 FTP退出后,只需测试Shell脚本中是否存在下载的文件,甚至对原始文件进行校验和以确保其正确传输。是的,这很臭,但我认为拥有易于阅读的代码比对每种可能的错误情况进行大量分析要好。 BSD FTP并不是那么出色。

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

IE

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

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

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

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