【问题标题】:FTP script issueFTP脚本问题
【发布时间】:2023-01-11 23:13:24
【问题描述】:

我们使用 FTP 脚本将文件发送到服务器,之前我们曾经在 AIX 上运行脚本,但现在由于云迁移,我们的脚本失败了,因为它在 SLES 12 中使用了 LFTP。

我需要修改脚本的帮助。

就像它无法将文件发送到目标服务器并且 ksh 已经安装在我们的服务器上。

代码 :

#!/bin/bash


#alias ftp=/usr/bin/lftp
alias ftp=/usr/bin/lftp

#Current Execution specific variables
PID=$$
TIMESTAMP=`date '+%Y%d%m%H%M%S'`

#Validate TIMESTAMP and PID
if [[ -z ${TIMESTAMP} || -z ${PID} ]]
then
        echo "ERROR: Failed to get process id and/or system timestamp"
        exit 1
fi

#Sub-routine to display command line usage
usage()
{
        echo "$1"
        echo "Please find below the valid argument options "
        echo "-h Host Name"
        echo "-s Source Dir"
        echo "-d Destination Dir"
        echo "-f Feed Name"
        echo "-o Output Feed Name"
        echo "-l Log File"
        echo "-u User Id"
        echo "-p Password"
        exit 1
}

#Sub-routine to check FTP errors
sub_check_error(){
        ftp_code=$1
        log_code=`egrep -i "fail|error" ${LOG_FILE}.ftp |wc -l| awk '{print $1}'`
        status=0
        ((status=ftp_code+log_code))

        if [ $status == 0 ]
        then
                echo "INFO: FTP $2 script succeeded..."
        else
                echo "ERROR: FTP $2 script failed"
                exit 1
        fi
}

# Get the command line options
while getopts h:s:d:f:o:l:u:p: opt
do
        case $opt in
                h) HOST_NAME=$OPTARG ;;
                s) SOURCE_DIR=$OPTARG ;;
                d) DEST_DIR=$OPTARG ;;
                f) FEED_NAME=$OPTARG ;;
                o) OUT_FEED_NAME=$OPTARG ;;
                l) LOG_FILE=$OPTARG ;;
                u) CONNECT_USER=$OPTARG ;;
                p) PASSWD=$OPTARG ;;
        esac
done

#Validating the arguments

#Log file
if [[ -z ${LOG_FILE} ]]
then
        usage "ERROR: Argument(l) LOG_FILE is blank"
fi

if [ -f ${LOG_FILE}.ping ]
then
        mv ${LOG_FILE}.ping ${LOG_FILE}.ping.${TIMESTAMP}
fi

if [ -f ${LOG_FILE}.ftp ]
then
        mv ${LOG_FILE}.ftp ${LOG_FILE}.ftp.${TIMESTAMP}
fi

#Host name
if [[ -z $HOST_NAME ]]
then
        usage "ERROR: Argument(h) HOST_NAME is blank"
fi

/usr/bin/ping  -c 5 $HOST_NAME > ${LOG_FILE}.ping

pingResult=`grep "0% packet loss" ${LOG_FILE}.ping | wc -l | awk '{print $1}'`
if [ $pingResult == 0 ]
then
        echo "ERROR: HOST_NAME \"$HOST_NAME\" is not valid or reachable"
#       exit 1
fi

#Feed name
if [[ -z $FEED_NAME ]]
then
        usage "ERROR: Argument(f) FEED_NAME is blank"
fi

#Output feed name
if [[ -z $OUT_FEED_NAME ]]
then
        usage "ERROR: Argument(o) OUT_FEED_NAME is blank"
fi

#Source Directory
if [[ -z $SOURCE_DIR ]]
then
        usage "ERROR: Argument(s) SOURCE_DIR is blank"
fi

if [[ ! -d $SOURCE_DIR ]]
then
        echo "ERROR: Source directory \"$SOURCE_DIR\" does not exist"
        exit 1
fi

#Checking the existense of source file
if [ ! -f $SOURCE_DIR/$FEED_NAME ]
then
        echo "ERROR: Source file \"$SOURCE_DIR/$FEED_NAME\" does not exists"
        exit 1
fi

#Destination Directory
if [[ -z $DEST_DIR ]]
then
        usage "ERROR: Argument(d) DEST_DIR is blank"
fi

#User id and password
if [[ -z $CONNECT_USER || -z $PASSWD ]]
then
        usage "ERROR: Argument(u) and/or Argument(p) i.e. CONNECT_USER and PASSWD are blank"
fi

echo "INFO: Host Name - $HOST_NAME"
echo "INFO: Source Dir - $SOURCE_DIR"
echo "INFO: Destination Dir - $DEST_DIR"
echo "INFO: Feed Name - $FEED_NAME"
echo "INFO: Output Feed Name - $OUT_FEED_NAME"
echo "INFO: Log File - ${LOG_FILE}.ftp and ${LOG_FILE}.ping"
echo "INFO: User Id - $CONNECT_USER"
echo "INFO: Password - $PASSWD"

# The commands to issue to FTP are listed below
#ftp -n -i -v $HOST_NAME << End-Of-Session  > ${LOG_FILE}.ftp
#user $CONNECT_USER $PASSWD
ftp -d -e "set ftp:ssl-allow no" -u $CONNECT_USER,$PASSWD DCSQ.CLDC.CHRYSLER.COM << End-Of-Session > ${LOG_FILE}.ftp
cd $DEST_DIR
lcd $SOURCE_DIR
quote site lrecl=600
quote site recfm=fb
quote site CY
quote site PRI=200
quote site SEC=200
put $SOURCE_DIR/$FEED_NAME -o "$OUT_FEED_NAME"
quit
End-Of-Session

ftpstat=$?
#Validate FTP error
sub_check_error $ftpstat "PUT"

#Validate FTP file transfer
ftpval=`egrep "226 Transfer complete|226 File receive OK|250 Transfer completed successfully" ${LOG_FILE}.ftp | wc -l | awk '{print $1}'`
if [ $ftpval == 0 ]
then
        echo "ERROR: Failed to FTP the file"
        exit 1
else
        echo "INFO: Successfully FTP'ed the file"
fi
exit 0

输出错误日志:

当我运行脚本时,这是我得到的输出。

---- Resolving host address...
---- 1 address found: 151.171.109.220
---(151.171.109.220) port 21
<--- 220-FTPSERVE IBM FTP CS V2R3 at DCSQ, 07:28:29 on 2023-01-11.
<--- 220 Connection will close if idle for more than 10 minutes.
---> FEAT
<--- 211- Extensions supported
<---  AUTH TLS
<---  PBSZ
<---  PROT
<--- 211 End
---> USER tftpsap
<--- 331 Send password please.
<--- 230 TFTPSAP is logged on.  Working directory is "TFTPSAP.".
---> PWD
<--- 257 "'TFTPSAP.'" is working directory.
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---> TYPE I
<--- 200 Representation type is Image
---> site lrecl=600
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---> site recfm=fb
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---> site CY
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---> site PRI=200
---- CWD path to be sent is `~/'TFTPSAP.'/FTP'
---> CWD
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD 'TFTPSAP.'
<--- 250 "TFTPSAP." is the working directory name prefix.
---> CWD FTP
<--- 250 "TFTPSAP.FTP." is the working directory name prefix.
---> site SEC=200
put: /PentaSap/interfaces/AR/data/out/T.M.FIN.AR.050*: No such file or directory
---> QUIT
<--- 221 Quit command received. Goodbye.
---- Closing control socket
ERROR: FTP PUT script failed
ERROR: ftpPutScriptAP.ksh failed. Exiting ..

【问题讨论】:

  • 你做 lcd $SOURCE_DIR,那么为什么 $SOURCE_DIR 在 put 中?
  • 我们有一个配置文件,它在其中获取 $SOURCE_DIR 和所有内容。
  • 你有一个名为T.M.FIN.AR.050*的文件吗?请注意,这不是 bash,因此不会执行 bash 扩展。
  • ftp 是交互式的,如果它成功地告诉你所有失败的事情,它将返回一个成功的退出代码......
  • 是的,我们的本地服务器中有文件 T.M.FIN.AR.050*

标签: linux ftp suse lftp


【解决方案1】:

这是一个 reference 的帖子,我在其中引用了几篇我已经解决了这个问题的帖子。

有更好、更简单、更可靠的替代品。如果您有任何选择(您通常会这样做),请避免将ftp 用于脚本。它不是为此而设计的。

当你在这里的时候,搜索lftpsftp,但是真的考虑使用 scp 或什至 ssh to run some list of commands remotely 来做您需要的事情。

只需检查您的返回代码。

【讨论】:

  • sftp 和 lftp 功能是否相同?
  • 不,但他们都是相似的,并且两者都有很好的建议 - 但你最好的选择真的是使用一些东西建成对于精细的结果,例如 scp如果您可以设置 SSH 公钥信任,然后整个 ftp 操作及其所有测试都简化为 if scp $SOURCE_DIR/$FEED_NAME $CONNECT_USER@DCSQ.CLDC.CHRYSLER.COM:$DEST_DIR/$FEED_NAME; then echo done; else echo transfer failed; fi,并且不需要在脚本中输入密码。如果要以交互方式使用脚本,您可以让用户在出现提示时输入密码。另外,顺便说一句-不要 ALL_CAP 你的 VARS.