I need to retrive the exit status code from a command line program. No worries, I used $?.
But for ftp, even if it doesn't connect, it opens the ftp shell, so I'm not able to understand that the connection haven't take place.
Try this code for understand:
#!/bin/sh
ftp 1234567
OUT=$?
if [ $OUT -eq 0 ];then
echo "ftp OK"
else
echo "ftp Error: "$OUT
fi
exit 0
Any help?
Thanks Filippo
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!