我目前正在创建一个调用Unix脚本的夜间作业,该脚本依次使用ftp
创建和传输文件。我想查看所有可能的退货代码。 ftp
的手册页未列出返回代码。有谁知道在哪里找到一个清单?有经验的人吗?我们有其他脚本可以在日志中查找某些返回字符串,并在出错时发送电子邮件。但是,他们经常会错过意料之外的代码。
然后我将原因放入日志和电子邮件中。
答案 0 :(得分:7)
在我遇到的大多数实现中,ftp
命令不会返回除零之外的任何内容。
在日志中处理三位数代码要好得多 - 如果您要发送二进制文件,则可以检查发送的字节是否正确。
三位数代码称为“系列代码”,可以找到一个列表here
答案 1 :(得分:5)
我编写了一个脚本,一次只传输一个文件,并在该脚本中使用grep
来检查226 Transfer complete
消息。如果找到,grep
将返回0.
ftp -niv < "$2"_ftp.tmp | grep "^226 "
答案 2 :(得分:4)
答案 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
如果出现任何问题,所有这些程序都将返回非零退出代码,以及指示失败的文本。您可以测试这个,然后根据需要随意输出,记录,发送电子邮件等。
请注意以下内容:
URL中使用“%2f”表示以下路径是远程计算机上的绝对路径。但是,如果您的FTP服务器chroot,您将无法绕过此。
对于上面使用实际URL(ftp://etc)并且其中嵌入了用户和密码的服务器的命令,如果用户名和密码包含特殊字符,则必须对其进行URL编码。< / p>
在某些情况下,一旦熟悉每个程序的语法,您就可以灵活地将远程目录作为绝对目录,而本地文件就是纯文件名。您可能只需添加本地目录环境变量或只需对所有内容进行硬编码。
如果你真的,绝对必须使用普通的FTP客户端,你可以在脚本中测试失败的一种方法,首先是一个PUT文件的命令,然后是另一个执行相同的GET的命令文件以不同的名称返回。 FTP退出后,只需在shell脚本中测试下载文件是否存在,甚至在原始文件中对其进行校验,以确保正确传输。是的,这很糟糕,但在我看来,拥有易于阅读的代码比对每种可能的错误条件进行大量解析更好。 BSD FTP并不是那么好。
答案 8 :(得分:-1)
为什么不将命令的所有输出存储到日志文件中,然后检查命令的返回码,如果不是0,则在电子邮件中发送日志文件?