1

notice the FTP_PUT_RETVAL. There are two echo commands, the first one shows a value of '0'. The second one shows no value at all. I am running this inside a nightly cron. BASH is GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)

My script tells me that the ftp upload was unsuccessful, because FTP_PUT_RETVAL contains no value!

Why is this occuring? How can I change this? What have I done wrong?

    #!/bin/sh
    #
    # Filename: rh5-manager-cron.sh
    #
    # Purpose: Runs backup.cron, and FTP uploads backup to Linux4
    #
    # Usage: the program is run with no arguments. This program is
    # intended to run from manager cron, and redirection is handled inside the cron
    #     e.g. 00 1 * * * /u2/app/lbin/rh5-manager-cron.sh > /tmp/log/rh5-manager-cron.log 2>&1
    trap signalCaught ABRT EXIT HUP INT PIPE TERM QUIT
    signalCaught () {
        for file in $FTP_LOG_FILE $TMPF; do
            $BIN_HOME/rm_file $TMPF
        done
        exit
    }

    if [[ ! -r /u2/conf/ctrl/lettus.sh || ! -r /u2/app/lbin/fsh_sh_lib ]]; then
        printf "Cannot source environment.\n" >&2
        exit 1
    fi
    . /u2/conf/ctrl/lettus.sh
    . /u2/app/lbin/fsh_sh_lib

    #-------------------------------------------------------
    # Variables
    #-------------------------------------------------------
    PRG=${0##*/}
    FTPUSER=dummy
    FTPPASS=dummy
    FTPHOST=192.168.0.3
    BACKUPDIR=/backup
    FTPBACKUPNAME=Redhat5Backup.tgz
    FTPBACKUPFILE=$BACKUPDIR/$FTPBACKUPNAME
    LOGDIR=/tmp/log
    FTP_LOG_FILE=$LOGDIR/Redhat5FTP.log
    SENDLOGS=$C/sendlogs.dat
    ZOOT_XML=$C/zoot.xml
    TMPF=`mktemp` || exit 1

    #-------------------------------------------------------
    # Sanity
    #-------------------------------------------------------
    if ! isValidUser root manager; then
        printf "$PRG: Must be run as user 'root' or user 'manager'.\n" >&2
        exit 1
    fi

    if [[ ! -d $BACKUPDIR ]]; then
        logger "$PRG: $BACKUPDIR: Not a valid directory" >&2
        exit 1
    fi

    if [[ ! -d $LOGDIR ]]; then
        logger "$PRG: $LOGDIR: Not a valid directory" >&2
        exit 1
    fi

    if [[ ! -r $SENDLOGS || ! -r $ZOOT_XML ]]; then
        logger "$PRG: E-mail: Files are not readable: $SENDLOGS, $ZOOT_XML" >&2
        exit 1
    fi

    if ! which lftp >/dev/null 2>&1; then
        logger "$PRG: lftp: command not found" >&2
        exit 1
    fi

    # e-mail
    EMAIL_SUBJECT="Redhat5 FTP PUT"
    EMAIL_TO=$(email_to $SENDLOGS)
    EMAIL_FROM=$(email_from $ZOOT_XML)

    # ftp binary
    LFTP_BIN=$(which lftp 2>/dev/null)

    #-------------------------------------------------------
    # Functions
    #-------------------------------------------------------

    # calls lftp to upload a file to server non-interactively
    ftp_put() {
        $LFTP_BIN $LFTP_DEBUG -u ${FTPUSER},${FTPPASS} $FTPHOST <<-EOF
    put $FTPBACKUPFILE
    pwd
    ls $FTPBACKUPNAME
    quit
    EOF
    #^^^^^^^^^^^ leave the above indentation alone
    }

    main() {
        # Backup, and send manager logs
        logger "Running backup.cron..."
        echo
        backup.cron
        BACKUP_CRON_RETVAL=$?

        logger "Running fsh_sendlogs..."
        echo
        $SH_HOME/fsh_sendlogs 1

        # show ls listing
        logger "Here comes a directory listing..."
        echo
        /bin/ls -l /backup/Redhat5Backup.tgz
        echo

        # ftp upload
        logger "Running ftp upload..."
        echo
        ftp_put
        FTP_PUT_RETVAL=$?
        echo " -- debug: Line ${LINENO:-}: FTP_PUT_RETVAL=${FTP_PUT_RETVAL:-}"
    }

    checkSuccess() {
        if [[ "$BACKUP_CRON_RETVAL" -eq 0 ]]; then
            echo "Backup was successful."
            echo
            echo "*********************************"
            echo "   OK: Backup was successful."
            echo "*********************************"
            echo
        else
            echo "ERROR: Backup FAILED! "
            echo
            echo "*********************************"
            echo "     ERROR: Backup FAILED! "
            echo "*********************************"
            echo
        fi

        echo " -- debug: Line ${LINENO:-}: FTP_PUT_RETVAL=${FTP_PUT_RETVAL:-}"
        if [ "$FTP_PUT_RETVAL" -eq 0 ]; then
            echo "lftp: ftp file upload complete."
            echo
            echo "*********************************"
            echo "  OK: ftp file upload complete."
            echo "*********************************"
            echo
        else
            echo "lftp: error ftp file upload not successful."
            echo
            echo "*********************************"
            echo "      ERROR: file upload"
            echo "       NOT successful."
            echo "*********************************"
            echo
        fi
    }

    email_logs() {
        if [[ -z "$EMAIL_FROM" || -z $EMAIL_TO || -z $EMAIL_SUBJECT || ! -r $FTP_LOG_FILE ]]; then
            logger "$PRG: One of the variables is not correctly configured" >&2
            exit 1
        fi
        fsh_mail -r "${EMAIL_TO}" -F "${EMAIL_FROM}" -s "${EMAIL_SUBJECT}" -t "${FTP_LOG_FILE}"
        return
    }

    #----------------------------------------------------------------------
    # Main Program
    #----------------------------------------------------------------------
    main               | tee $FTP_LOG_FILE
    checkSuccess       | tee -a $FTP_LOG_FILE $TMPF
    cat $FTP_LOG_FILE >> $TMPF

    # E-mail ftp log file
    logger "Emailing ftp logfile"
    echo
    email_logs

    #eof
chown
  • 51,908
  • 16
  • 134
  • 170
Felipe Alvarez
  • 3,720
  • 2
  • 33
  • 42
  • 1
    May be you need to define a variable in the global scope of your script and store the value of `FTP_PUT_RETVAL` to it whilst inside `ftp_put`, and see if it retains when used in `main`? – Drav Sloan Nov 22 '11 at 02:38

1 Answers1

3

The problem is that you are using:

main               | tee $FTP_LOG_FILE
checkSuccess       | tee -a $FTP_LOG_FILE $TMPF

Because of the piping, the work done in main is done in a sub-shell, and a sub-shell cannot set variables in the parent shell. So, when checkSuccess (which is also run in a sub-shell) goes to look at the results, it sees what was in the parent shell (nothing), rather than what was set in the main function in a sub-shell.

If you dropped the piping, it would start to work.

More reliably, put the call to checkSuccess into the main function. Or use one or the other of these two notations:

{ main; checkSuccess; } | tee $FTP_LOG_FILE $TMPF
( main; checkSuccess )  | tee $FTP_LOG_FILE $TMPF

Note that the { ... } notation requires a semi-colon after the second function which the ( ... ) notation does not require. However, there is one less process involved in the { ... } mechanism, not that it is going to make any measurable difference to the overall performance of this (the FTP time will dominate).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Good catch, this is actually the problem, not the single `[ ]` as I had suggested. – chown Nov 22 '11 at 02:51
  • 1
    This could be fixed by switching to bash (i.e. `#!/bin/bash` at the beginning of the script, so it won't try to be plain-sh compatible), and using process substitution instead of pipes: `main > >(tee $FTP_LOG_FILE)` – Gordon Davisson Nov 22 '11 at 03:49
  • Wow. I learned something. I also had a look at http://stackoverflow.com/questions/5760640/left-side-of-pipe-is-the-subshell – Felipe Alvarez Nov 23 '11 at 06:03