Getting exit status code from 'ftp' command in linux shell

为君一笑 提交于 2019-11-30 04:11:56

You should be looking for success message from ftp command rather than looking for a status. It's "226 Transfer complete". You can confirm it with ftp manual on your system.

200 PORT command successful.
150 Opening ASCII mode data connection for filename.
226 Transfer complete.
189 bytes sent in 0.145 seconds (0.8078 Kbytes/s)

Here's a sample script.

FTPLOG=/temp/ftplogfile
ftp -inv <<! > $FTPLOG
open server
user ftp pwd
put filename
close
quit
!

FTP_SUCCESS_MSG="226 Transfer complete"
if fgrep "$FTP_SUCCESS_MSG" $FTPLOG ;then
   echo "ftp OK"
else
   echo "ftp Error: "$OUT
fi
exit 0

If you need to download something and see if the download succeeded, why don't you use wget? It supports the FTP protocol.

It will report the status of the download with several return codes (quote from man page):

EXIT STATUS
   Wget may return one of several error codes if it encounters problems.
   0   No problems occurred.
   1   Generic error code.
   2   Parse error---for instance, when parsing command-line options, the .wgetrc or .netrc...
   3   File I/O error.
   4   Network failure.
   5   SSL verification failure.
   6   Username/password authentication failure.
   7   Protocol errors.
   8   Server issued an error response.

Try the following scripts.

To copy:

#!/bin/bash
# cftp.sh
# set -x

FTPSERVER="$1"
FTPPORT="$2"
REMOTEDIR="$3"

[[ "$REMOTEDIR" ]] || { echo -e "Usage: $0 <ftpserver> <ftpport> <remotedir> [file1] [file2] ..." > /dev/stderr ; exit 1 ; }

L=$((BASH_ARGC-3))

LOCALFILES=("${BASH_ARGV[@]:0:$L}")

RETCODE=0

for LOCALFILE in "${LOCALFILES[@]}"
do
  THISRETCODE=0
  [[ -f "$LOCALFILE" ]] || THISRETCODE=1

  LOCALDIR="$(dirname "$LOCALFILE")"
  LOCALFILENAME="$(basename "$LOCALFILE")"

  [[ $THISRETCODE = 0 ]] &&
  /usr/bin/ftp -iv "$FTPSERVER" << EOF | grep -q '226 Transfer complete' || THISRETCODE=1
    lcd $LOCALDIR
    cd $REMOTEDIR
    put $LOCALFILENAME
EOF

  RETCODE=$((RETCODE+THISRETCODE))
done

exit $RETCODE

To move:

#!/bin/bash
# mftp.sh
# set -x

FTPSERVER="$1"
FTPPORT="$2"
REMOTEDIR="$3"

[[ "$REMOTEDIR" ]] || { echo -e "Usage: $0 <ftpserver> <ftpport> <remotedir> [file1] [file2] ..." > /dev/stderr ; exit 1 ; }

L=$((BASH_ARGC-3))

LOCALFILES=("${BASH_ARGV[@]:0:$L}")

RETCODE=0

for LOCALFILE in "${LOCALFILES[@]}"
do
  THISRETCODE=0
  [[ -f "$LOCALFILE" ]] || THISRETCODE=1

  LOCALDIR="$(dirname "$LOCALFILE")"
  LOCALFILENAME="$(basename "$LOCALFILE")"

  [[ $THISRETCODE = 0 ]] &&
  /usr/bin/ftp -iv "$FTPSERVER" << EOF | grep -q '226 Transfer complete' || THISRETCODE=1
    lcd $LOCALDIR
    cd $REMOTEDIR
    put $LOCALFILENAME
EOF

  [[ $THISRETCODE = 0 ]] &&
  /bin/rm -f "$LOCALFILE" || THISRETCODE=1

  RETCODE=$((RETCODE+THISRETCODE))
done

exit $RETCODE

Here are some test cases:

For copying.

$ ./cftp.sh ; echo return code: $?
Usage: ./cftp.sh <ftpserver> <ftpport> <remotedir> [file1] [file2] ...
return code: 1
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.sh mftp.sh ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test *ftp.sh ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.s ; echo return code: $?
return code: 1
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.s mftp.s ; echo return code: $?
return code: 2
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/tes cftp.sh ; echo return code: $?
return code: 1

For moving.

$ ./mftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.sh ; echo return code: $?
/bin/rm: cannot remove `cftp.sh': Permission denied
return code: 1
$ echo foo > /tmp/bar
$ ./mftp.sh ftpserver 21 /mnt/disk4/d0/test /tmp/bar ; echo return code: $?
return code: 0
$ ls -lha /tmp/bar
ls: cannot access /tmp/bar: No such file or directory

Update: Remember to read man 5 netrc

some scripts do -

ftp -n $HOST > /tmp/ftp.worked 2> /tmp/ftp.failed <<END_SCRIPT
blah blah
END_SCRIPT

EXITSTATUS=$?

if [ $EXITSTATUS != "0" ]
then
    # handle the error...
fi 

Except that the above doesn't always work - most FTP clients always exit with a status of 0. This leads to ugly "false negatives": the file transfer fails, but the script doesn't detect the problem.

One way to verify that a file transfer took place - transfer it back:

#!/bin/sh

ftp -n << END_SCRIPT
open $1
user $2 $3
put $4
get $4 retrieval.$$
bye
END_SCRIPT

if [ -f retrieval.$$ ]
then
    echo "FTP of $4 to $1 worked"
    rm -f retrieval.$$
else
    echo "FTP of $4 did not work"
fi

The last time I needed to use ftp in a script, I got so frustrated with it that I finally found a BSD-licensed ftp client source and simply modified it to give it the behavior I needed, and used that instead of the version provided with the OS.

Ugly, but the depth of head-level dents in the cube wall was starting to get ridiculous

Another way around this is to check if you have the file on your server post transfer!

Something like...

if ![ -s "$INPUT_DIR/HOP_PSA_Transactions_$BATCH_ID.csv" ]
then
    ## No Transactions file
    FAIL_TIME=`date +"%d-%m-%Y %H:%M"`
	echo "ERROR: File HOP_PSA_Transactions_$BATCH_ID.csv not found @ $FAIL_TIME" >>$LOGFILE_DIR$LOGFILE_NAME
	exit $ERR_NO_TRANS_FILE    
fi

If it's not there then it didn't transfer successfully!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!