bash bash中的ftp脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4645503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:14:06  来源:igfitidea点击:

ftp script in bash

bashftp

提问by bernie

I have the following script that pushes files to remote location:

我有以下脚本将文件推送到远程位置:

#!/usr/bin/bash
HOST1='a.b.c.d'
USER1='load'
PASSWD1='load'
DATE=`date +%Y%m%d%H%M`
DATE2=`date +%Y%m%d%H`
DATE3=`date +%Y%m%d`
FTPLOGFILE=/logs/Done.$DATE2.log
D_FOLDER='/dir/load01/input'

PUTFILE='file*un'
ls $PUTFILE | while read file
do
  echo "${file} transfered at $DATE" >> /logs/$DATE3.log
done

ftp -n -v $HOST1 <<SCRIPT >> ${FTPLOGFILE} 2>&1
quote USER $USER1
quote PASS $PASSWD1
cd $D_FOLDER
ascii
prompt off
mput /data/file*un 
quit
SCRIPT

mv *un test/

ls test/*un | awk '{print("mv "" ")}' | sed 's/\.un/\.processed/2' |sh
rm *unl

I am getting this error output:

我收到此错误输出:

200 PORT command successful.
553 /data/file1.un: A file or directory in the path name does not exist.
200 PORT command successful.

回答by Paused until further notice.

Some improvements:

一些改进:

#!/usr/bin/bash
HOST1='a.b.c.d'
USER1='load'
PASSWD1='load'
read Y m d H M <<<$(date "+%Y %m %d %H %M")    # only one call to date
DATE='$Y$m$d$H$M'
DATE2='$Y$m$d$H'
DATE3='$Y$m$d'
FTPLOGFILE=/logs/Done.$DATE2.log
D_FOLDER='/dir/load01/input'

PUTFILE='file*un'
for file in $PUTFILE    # no need for ls
do
  echo "${file} transfered at $DATE"
done >> /logs/$DATE3.log    # output can be done all at once at the end of the loop.

ftp -n -v $HOST1 <<SCRIPT >> ${FTPLOGFILE} 2>&1
quote USER $USER1
quote PASS $PASSWD1
cd $D_FOLDER
ascii
prompt off
mput /data/file*un 
quit
SCRIPT

mv *un test/

for f in test/*un    # no need for ls and awk
do
  mv "$f" "${f/%.un/.processed}"
done

rm *unl

I recommend using lower case or mixed case variables to reduce the chance of name collisions with shell variables.

我建议使用小写或混合大小写变量来减少与 shell 变量发生名称冲突的机会。

Are all those directories really directly off the root directory?

所有这些目录真的直接脱离根目录吗?

回答by gpvos

Ftp to the the remote site and execute the ftp commands by hand. When the error occurs, look around to see what is the cause. (Use "help" if you don't know the ftp command line.)

ftp 到远程站点并手动执行 ftp 命令。当错误发生时,环顾四周看看是什么原因。(如果您不知道 ftp 命令行,请使用“帮助”。)

Probably the /datadirectory does not exist. has anyone reorganized the upload directory recently, or maybe moved the root directory of the ftp server?

可能/data目录不存在。有没有人最近重新组织了上传目录,或者移动了ftp服务器的根目录?

回答by Paul Hodges

The problem with scripting an FTP session is that FTP believes it has executed itself correctly if it reports errors to stdout. Consequently, it's devilishly hard to pick up errors, since it will only return a fail on something catastrophic. If you need anything more than the most simple of command lists, you should really be using something like expect or a java or perl program that can easily test the result of each action.

编写 FTP 会话脚本的问题在于,如果 FTP 向标准输出报告错误,则 FTP 认为它自己已正确执行。因此,发现错误非常困难,因为它只会在发生灾难性事件时返回失败。如果您需要的不仅仅是最简单的命令列表,您真的应该使用像expect 或java 或perl 程序这样可以轻松测试每个操作的结果的程序。

That said, you canrun the ftp as a coprocess, or set it up so that it runs in background with it's stdin and stdout fitted to named pipes, or some structure like that where you can read and parse the output from one command before deciding what to pass in for the next one.

也就是说,您可以将 ftp 作为协进程运行,或将其设置为在后台运行,并将标准输入和标准输出安装到命名管道,或类似的结构,您可以在决定之前读取和解析一个命令的输出为下一个传递什么。

A read loop that cycles on a case statement which tests for known responses and behaves accordingly is a passably acceptable all-bash version. if you always terminate every command block with something like an imagecommand that returns a fixed and known value, you can scan for known errors, and check for the return from that command in the case statement, and when you get the "sentinal" return loop back and read the next input. This makes for a largish and fairly complicated shell script, though.

在 case 语句上循环的读取循环测试已知响应并相应地进行操作,这是一个可以接受的全 bash 版本。如果您总是使用image返回固定和已知值的命令之类的命令终止每个命令块,您可以扫描已知错误,并在 case 语句中检查该命令的返回,以及何时获得“哨兵”返回循环返回并阅读下一个输入。不过,这会产生一个较大且相当复杂的 shell 脚本。

Also, you need to test that when you get (for example) a 5[0-9][0-9] *)return it isn't actually "553 bytes*" because ftp screws you that way too.

此外,您需要测试当您获得(例如)5[0-9][0-9] *)返回时,它实际上不是“553 字节*”,因为 ftp 也会以这种方式给您带来麻烦。

Apologies for the length of the answer without including a code example - I just wanted to mention some ideas and caveats that wouldn't fit readably in a comment.

对于不包含代码示例的答案的长度表示歉意 - 我只是想提及一些不适合在评论中阅读的想法和警告。