简体   繁体   English

Bash变量失去了价值-奇怪

[英]Bash Variable losing its value - strange

notice the FTP_PUT_RETVAL . 注意FTP_PUT_RETVAL There are two echo commands, the first one shows a value of '0'. 有两个echo命令,第一个显示值'0'。 The second one shows no value at all. 第二个没有显示任何价值。 I am running this inside a nightly cron . 我在一个夜间的cron里面跑这个。 BASH is GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) BASHGNU 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! 我的脚本告诉我ftp上传不成功,因为FTP_PUT_RETVAL没有包含值!

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

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. 由于管道的原因, main中完成的工作在子外壳中完成,并且子外壳无法在父外壳中设置变量。 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. 因此,当checkSuccess (也在子外壳程序中运行)查看结果时,它会看到父外壳程序中的内容(什么都没有),而不是子外壳程序中main函数中设置的内容。

If you dropped the piping, it would start to work. 如果您掉下管道,它将开始工作。

More reliably, put the call to checkSuccess into the main function. 更可靠地, checkSuccess的调用放入main函数中。 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). 但是, { ... }机制中涉及的进程少了一个,而不是它会对整体性能产生任何可测量的差异(FTP时间将占主导地位)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM