2016-12-15 2 views
0

/home/deploy/backup-scripts/utils.sh: line 41: $2: unbound variableБаш несвязанных переменная при использовании источника

Я не могу понять это из Bitbucket резервных копий скриптов ... может кто-нибудь помочь?

Когда я использую это, другой сценарий вызывает его, используя source. Я не могу понять, почему переменная unbound, когда я вызываю ее с source из другого созданного мной скрипта, который я создал, и он отлично работает при вызове из собственных скриптов Bitbuckets ?. Есть ли проблема с bash, когда вы не можете использовать 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

Какова ваша точная строка 'source'? Ваша ошибка свидетельствует о том, что вы не дали сценарию [второй аргумент] (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, или аргумент, если вы будете, сценария. Вы должны указать этот параметр, когда «sourcing» файл, как и любой другой вызов сценария, который ожидает второй параметр.

В вашем случае, сценарий, кажется, ожидает три параметра, так называют его:

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

Смежные вопросы