Wednesday, December 16, 2009

Scripting FTP, with error checking

FTP is great for sending data back and forth. It's easy to automate, and there are many sites out there that will tell you how to do so. But it's a real pain to get any error checking going.

Allow me to demonstrate. Here's a quick script:

#!/bin/bash
# send_ftp_copies

HOST='www.google.com'
USER='mysername'
PASSWD='mypassword'

if [ "$1" = "" ]
then
    echo "$0: Sorry, must be specify filename. Exiting..."|mail root
    exit 1
else
    FILENAME=$1
fi

if test ! -f "/tmp/$FILENAME"
then
   echo "$0: File $FILENAME does not exist. Exiting..."|mail root
   exit 1
fi

ftp -n $HOST << EOF
    user $USER $PASSWD
    cd /myinbox
    lcd /tmp
    put $FILENAME
    quit
EOF

You'd invoke this like

send_ftp_file FILENAME

it would check if the file existed, execute the commands up to the EOF, and quit.

Ah, but what if you wanted to check for an error? Something simple, like not being able to connect.

The usual way would be to do something like this:

if [ "$?" -ne 0 ]; then
    echo "Command failed: $?. Exiting..."|mail root
    exit 1
fi

Unfortunately, this doesn't work. FTP, as far as I can tell, never returns an error to the shell.

So let's redirect the output. Let's do something like this:

ERROR_FILE="/tmp/ftp_error$$"
ftp -n $HOST 2> "$ERROR_FILE" << EOF
...
EOF

if [ -s "$ERROR_FILE" ] ; then
    echo "ftp transfer failed! Error is in $ERROR_FILE"
    exit 1
fi

and see what happens when I connect to a site (mine) that has no FTP server running. Sure enough:

ftp transfer failed! Error is in /tmp/ftp_error17237

cat /tmp/ftp_error17237
ftp: connect: Connection timed out

Hah! Worked. So, I put it into production and... got an error message each and every time I had a connection, even a valid one.

It seems that most Linux systems try Kerberos authentication first. So if the target site doesn't do Kerberos, you'll get the message

KERBEROS_V4 rejected as an authentication type

and then it'll try password authentication, which will work. But in the meantime, your error file now has that message in it, and your script will fail.

grep to the rescue:

cat $ERROR_FILE|grep -v KERBEROS_V4>"$ERROR_FILE".1

if [ -s "$ERROR_FILE.1" ] ; then
    echo "ftp transfer failed! Error is in $ERROR_FILE.1"
    exit 1
fi

which works just fine.

No comments:

Post a Comment