2016-12-15 63 views
0

/home/deploy/backup-scripts/utils.sh: line 41: $2: unbound variablebash無約束變量當使用源

我無法從Bitbucket備份腳本中找出這個......任何人都可以幫忙嗎?

當我使用它時,另一個腳本使用source來調用它。我無法弄清楚爲什麼變量沒有被綁定,當我從另一個我創建的定製腳本中調用source時,它在從Bitbuckets自己的腳本中調用時工作正常嗎?有沒有一個bash的問題,你不能從父腳本使用source,然後再從子腳本中使用source

# ------------------------------------------------------------------------------------- 
# Common utilities for logging, terminating script execution and Hipchat integration. 
# ------------------------------------------------------------------------------------- 

# Terminate script execution with error message 
function bail { 
    error "$*" 
    print_stack_trace 
    exit 99 
} 

# Test for the presence of the specified command and terminate script execution if not found 
function check_command { 
    type -P "$1" &> /dev/null || bail "Unable to find $1, please install it and run this script again" 
} 

# Log an debug message to the console if BITBUCKET_VERBOSE_BACKUP=true 
function debug { 
    if [ "${BITBUCKET_VERBOSE_BACKUP}" = "true" ]; then 
     print "$(script_ctx)[$(hostname)] DEBUG: $*" 
    fi 
} 

# Log an error message to the console and publish it to Hipchat 
function error { 
    # Set the following to have log statements print contextual information 
    echo "$(script_ctx)[$(hostname)] ERROR: $*" > /dev/stderr 
    hc_announce "[$(hostname)] ERROR: $*" "red" 1 
} 

# Log an info message to the console and publish it to Hipchat 
function info { 
    # Set the following to have log statements print contextual information 
    print "$(script_ctx)[$(hostname)] INFO: $*" 
    hc_announce "[$(hostname)] INFO: $*" "gray" 
} 

# Checks if a variable is zero length, if so it prints the supplied error message and bails 
function check_config_var { 
    local conf_var_name="$1" 
    local conf_error_message="$2" 
    local conf_bail_message="$3" 

    if [ -z "${conf_error_message}" ]; then 
     conf_error_message="The configuration var '${conf_var_name}' is required, please update '${BACKUP_VARS_FILE}'." 
    fi 
    if [ -z "${conf_bail_message}" ]; then 
     conf_bail_message="See bitbucket.diy-backup.vars.sh.example for the defaults and instructions." 
    fi 

    check_var "${conf_var_name}" "${conf_error_message}" "${conf_bail_message}" 
} 

# Similar to check_config_var but does does not print the extra message about consulting the vars file 
function check_var { 
    local set_var_name="$1" 
    local set_error_message="$2" 
    local set_bail_message="$3" 

    if [ -z "${!set_var_name}" ]; then 
     if [ -z "${set_error_message}" ]; then 
      set_error_message="Fatal error '${set_var_name}' has not been set" 
     fi 
     if [ -z "${set_bail_message}" ]; then 
      bail "${set_error_message}" 
     else 
      error "${set_error_message}" 
      bail "${set_bail_message}" 
     fi 
    fi 
} 

# A function with no side effects. Normally called when a callback does not need to do any work 
function no_op { 
    echo > /dev/null 
} 

# Log a message to the console without adding standard logging markup 
function print { 
    echo "[email protected]" 
} 

function script_ctx { 
    if [ -n "${BASH_VERSION}" ]; then 
     local depth=0 
     for func in ${FUNCNAME[@]}; do 
      case "${func}" in 
       debug|info|error|bail|check_config_var|check_var|run|script_ctx|print_stack_trace) 
        depth=$((${depth}+1)) 
       ;; 
      esac 
     done 
     echo "[$(basename ${BASH_SOURCE[${depth}]}):${BASH_LINENO[${depth}]} -> ${FUNCNAME[${depth}]}]" 
    fi 
} 

function print_stack_trace { 
    if [ -n "${BASH_VERSION}" ]; then 
     local idx=0 
     local depth=" " 
     echo "Stack trace:" > /dev/stderr 
     for func in ${FUNCNAME[@]}; do 
      case "${func}" in 
       debug|info|error|bail|check_config_var|check_var|run|script_ctx|print_stack_trace) 
       ;; 
      *) 
       echo "${depth}[${BASH_SOURCE[${idx}]}:${BASH_LINENO[${idx}]} -> ${FUNCNAME[${idx}]}]" > /dev/stderr 
       ;; 
      esac 
      depth="${depth} " 
      idx=$((${idx}+1)) 
     done 
    fi 
} 

# Log then execute the provided command 
function run { 
    if [ "${BITBUCKET_VERBOSE_BACKUP}" = "true" ]; then 
     local cmdline= 
     for arg in "[email protected]"; do 
      case "${arg}" in 
       *\ * | *\"*) 
        cmdline="${cmdline} '${arg}'" 
        ;; 
       *) 
        cmdline="${cmdline} ${arg}" 
        ;; 
      esac 
     done 
     case "${cmdline}" in 
      *curl*) 
       cmdline=$(echo "${cmdline}" | sed -e 's/-u .* /-u ******:****** /g') 
       ;; 
      *PGPASSWORD=*) 
       cmdline=$(echo "${cmdline}" | sed -e 's/PGPASSWORD=".*" /PGPASSWORD="**********" /g') 
       ;; 
     esac 
     debug "Running${cmdline}" > /dev/stderr 
    fi 
    "[email protected]" 
} 

# Log a success message to the console and publish it to Hipchat 
function success { 
    print "[$(hostname)] SUCC: $*" 
    hc_announce "[$(hostname)] SUCC: $*" "green" 
} 

# ------------------------------------------------------------------------------------- 
# Internal methods 
# ------------------------------------------------------------------------------------- 

# Publish a message to Hipchat using the REST API 
# 
# $1: string: message 
# $2: string: color (yellow/green/red/purple/gray/random) 
# $3: integer: notify (0/1) 
# 
function hc_announce { 
    if [ -z "${HIPCHAT_ROOM}" ]; then 
     return 0 
    fi 
    if [ -z "${HIPCHAT_TOKEN}" ]; then 
     return 0 
    fi 

    if [ -z "$1" ]; then 
     print "ERROR: HipChat notification message is missing." 
     return 1 
    fi 

    local hc_color="gray" 
    if [ -n "$2" ]; then 
     hc_color=$2 
    fi 
    local hc_notify="false" 
    if [ "1" = "$3" ]; then 
     hc_notify="true" 
    fi 

    local hc_message=$(echo "$1" | sed -e 's|"|\\\"|g') 
    local hipchat_payload="{\"message\":\"${hc_message}\",\"color\":\"${hc_color}\",\"notify\":\"${hc_notify}\"}" 
    local hipchat_url="${HIPCHAT_URL}/v2/room/${HIPCHAT_ROOM}/notification?auth_token=${HIPCHAT_TOKEN}" 
    ! curl ${CURL_OPTIONS} -X POST -H "Content-Type: application/json" -d "${hipchat_payload}" "${hipchat_url}" 
    true 
} 
+1

什麼是你的確切'源'行?你的錯誤表明你沒有給腳本[第二個參數](http://stackoverflow.com/questions/29258603/what-do-0-1-2-mean-in-shell-script)。 –

+0

'SCRIPT_DIR = $(dirname「$ 0」)' 'source「$ {SCRIPT_DIR} /utils.sh」' 'source「$ {SCRIPT_DIR} /common.sh」 – eekfonky

+0

@eekfonky:你只需要避免得到錯誤(或)需要調試爲什麼某些應該有值的變量實際上是空的? – Inian

回答

1

$2是第二positional parameter,或者參數,你會,腳本。您需要在「採購」文件時指定此參數,就像您對其他需要第二個參數的腳本的其他調用一樣。

在你的情況,腳本似乎想到三個參數,所以稱其爲:

source /path/to/the/script my_var_name my_err_msg my_bail_msg 

例如:

$ cat test.sh 
#!/usr/bin/env bash 

source test2.sh singing rain 
$ cat test2.sh 
#!/usr/bin/env bash 

var1="$1" 
var2="$2" 

printf "I'm %s in the %s\n" $var1 $var2 
$ ./test.sh 
I'm singing in the rain 

如果你忘記指定的參數(如果你使用set -u),你會得到一個錯誤:

$ cat test.sh 
#!/usr/bin/env bash 

set -u 

source test2.sh 
$ cat test2.sh 
#!/usr/bin/env bash 

var1="$1" 
var2="$2" 

printf "I'm %s in the %s\n" $var1 $var2 
$ ./test.sh 
test2.sh: line 3: $1: unbound variable 
+0

請記住,刪除'nounset'這只是繞過錯誤OP正在看到。不知道他是否想要或調試腳本爲什麼指向未初始化的變量。 – Inian

+0

@Inian同意。我絕對**不建議刪除'set -o nounset(相當於'set -u')。相反,這應該始終設置。 –

0

看來,如果我使用exec而不是source它的作品?

+0

'exec'不會使用腳本的上下文來執行被調用的腳本,所以如果你使用了'set -u',它將不會被應用到你正在調用的腳本上。因此,如果您執行'exec script.sh',未初始化的$ 2將被設置爲空白或'「」',而不是觸發錯誤。如果它有效,對你有好處,但你正在使用的腳本清楚地意味着與參數一起使用,所以它可能會在稍後咬你。 ;-) –

+0

謝謝,它現在工作,但我確實需要一個永久的解決方案,以便我可以用'source' – eekfonky