Bash - 在脚本中突变的命令行参数

时间:2016-04-03 18:53:38

标签: bash

我在理解我的脚本奇怪的行为时遇到了一些困难。首先,这是有问题的脚本:

processor_usage_script.sh

#!/bin/bash
#  This script will be used to obtain and store processor usage information for given ip

function join { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }

retrieve_processor_usage()
{
        # retrieve current id in host table for current IP address
        current_id=($(mysql -u root -phassan01 -D honours_project -e "SELECT id FROM hosts WHERE host_ip='$1'" -s -N))

        # get host os, as windows has different MIB OID for processor usage
        host_os=$(mysql -u root -phassan01 -D honours_project -e "SELECT host_os FROM host_descriptions WHERE host_id='$current_id'" -s -N)

        # take host os value and break it down to see if the os is windows based
        curr_host_os_temp=$(echo "$host_os" | sed 's/^.*\(Windows.*\)/\1/')
        curr_host_os=$(echo $curr_host_os_temp | tr -s ' ' | cut -d\  -f1)

        if [ "$curr_host_os" == "Windows" ]; then
                echo $( date '+%Y-%m-%d_%H-%M-%S' ) " - Host $1 is a $curr_host_os machine" >> logs/$( date '+%Y-%m-%d' )

                IFS=$'\n'
                var=($(snmpwalk -v1 -c public -Ovq -r 1 $1 HOST-RESOURCES-MIB::hrDeviceType))

                # Set up a counter value that I will use to get the values for the porcessor usage
                local count=1

                # create array to keep counts that will be used to get processor usage
                local count_array=()
                for i in "${var[@]}"; do
                        p=$(echo "$i" | sed 's/^.*\(hrDeviceProcessor\)/\1/')

                        if [[ "$p" == "hrDeviceProcessor" ]]; then
                                count_array=("${count_array[@]}" "$count")
                                count=$((count+1))
                        else
                                count=$((count+1))
                        fi
                done

                # declare processor usage array
                processor_usage=()

                # loop through count array and get processor usage
                for i in "${count_array[@]}"; do
                        p_usage=$(snmpget -v1 -c public -r 1 -Ovq $1 .1.3.6.1.2.1.25.3.3.1.2.$i)
                        #processor_usage=("${processor_usage[@]}" "$p_usage");
                        processor_usage+=("$p_usage");
                done

                # make processor usage comma separated
                processor_usage_comma_separated=$(join , "${processor_usage[@]}")
                #proces

sor_usage_comma_separated=$(printf "%s," "${processor_usage[@]}")

                    # pass values to log that values for processor usage has been inserted
                    echo $( date '+%Y-%m-%d_%H-%M-%S' ) " - Inserted into database processor usage details for $1 -- Processor Usage - $processor_usage_comma_separated" >> logs/$( date '+%Y-%m-%d' )
    echo "$processor_usage_comma_separated"
                    # insert value into database under host_processor_usage_windows
                    mysql -u root -phassan01 -D honours_project -e "INSERT INTO host_processor_usage_windows (id,host_id,system_time,processor_usage) VALUES ('','$current_id',NOW(),'$processor_usage_comma_separated')"
    echo $1
else
                # declare base ssCpuRaw variable
                ssCpuRaw=".1.3.6.1.4.1.2021.11"

                # use IP address to retrieve raw kernel usage (ssCpuRawKernel -- .1.3.6.1.4.1.2021.11.55.0)
                kernel_space_time=$(sudo snmpget -v1 -c public -Oqv -r 1 $1 $ssCpuRaw.55.0)

                # use IP address to retrieve raw user space usage (ssCpuRawUser -- .1.3.6.1.4.2021.11.50.0)
                user_space_time=$(sudo snmpget -v1 -c public -Oqv -r 1 $1 $ssCpuRaw.50.0)

                # use IP address to retrieve raw IO space usage, i.e. time spent waiting for IO (ssCpuRawUser -- .1.3.6.1.4.2021.11.54.0)
                io_space_time=$(sudo snmpget -v1 -c public -Oqv -r 1 $1 $ssCpuRaw.54.0)
ssor_usage=("${processor_usage[@]}" "$p_usage");
                        processor_usage+=("$p_usage");
                done

                # make processor usage comma separated
                processor_usage_comma_separated=$(join , "${processor_usage[@]}")
                #processor_usage_comma_separated=$(printf "%s," "${processor_usage[@]}")

                # pass values to log that values for processor usage has been inserted
                echo $( date '+%Y-%m-%d_%H-%M-%S' ) " - Inserted into database processor usage details for $1 -- Processor Usage - $processor_usage_comma_separated" >> logs/$( date '+%Y-%m-%d' )
echo "$processor_usage_comma_separated"
                # insert value into database under host_processor_usage_windows
                mysql -u root -phassan01 -D honours_project -e "INSERT INTO host_processor_usage_windows (id,host_id,system_time,processor_usage) VALUES ('','$current_id',NOW(),'$processor_usage_comma_separated')"
echo $1 retrieve current id in host table for current IP address
                current_id=($(mysql -u root -phassan01 -D honours_project -e "SELECT id FROM hosts WHERE host_ip='$1'" -s -N))

                if [ -n "$kernel_space_time" ] && [ -n "$user_space_time" ] && [ -n "$io_space_time" ]; then
                        echo $( date '+%Y-%m-%d_%H-%M-%S' ) " - Inserted into database processor usage details for $1 -- Kernel space: $kernel_space_time, User space: $user_space_time, IO space: $io_space_time" >> logs/$( date '+%Y-%m-%d' )

                        # insert values into database
                        mysql -u root -phassan01 -D honours_project -e "INSERT INTO host_processor_usage (id,host_id,system_time,kernel_space_time,user_space_time,io_space_time) VALUES ('','$current_id',NOW(),'$kernel_space_time','$user_space_time','$io_space_time')"
                fi

        fi

}

retrieve_processor_usage $1

此脚本要做的是获取给定的IP地址并在检索到正确的MIB ID后执行snmpget。然后使用IP地址使用另一个脚本进行另一次检索。当执行一个单独的脚本工作正常。传入的IP地址在此脚本执行结束时是相同的。但是,当在上下文中运行时,它的设计失败了。以下是它执行的上下文:

main.sh

...
SECONDS=300

while true
do
for i in "${active_ip_open_161[@]}"
do
  . ./processor_usage_script.sh $i
  . ./memory_usage_script.sh $i
  . ./bandwidth_usage_script.sh $i
done

sleep $SECONDS
done
...

在实际执行上下文中,首先将给定IP传递到proceessor_usage_script.sh,然后传递给memory_usage_script.sh,依此类推。在这种情况下,执行processessor_usage_script.sh后,将返回值7并将其传递给后续脚本。我不明白它为什么会这样做,但我相信我已经把它缩小到执行MySQL语句。我想知道我是否可以帮助调试它失败的原因。

1 个答案:

答案 0 :(得分:3)

Siguza's对该问题的提示进行了评论:

sourcing [1]  您调用的脚本(. <script> ...),这些脚本的变量修改/添加到调用 shell的变量。

具体来说,由于$i在调用脚本和processor_usage_script.sh内被修改, next sourcing命令. ./memory_usage_script.sh $i将通过{{1}将processor_usage_script.sh设置为 - 而不是原始的$i循环变量值。

解决方案选项:

  • 使用不同的变量名称来避免冲突。

  • 最好不使用sourcing - 通过参数传递帮助程序脚本需要的任何信息,并使用stdout输出传递信息 out

    • 如果没有采购,只需使用诸如
      的语句调用助手脚本 $i(前面没有./processor_usage_script.sh "$i"

Siguza还建议对你的变量引用进行双引号,我在上面做过(.<space>),这总是一个好主意,以确保这些值不被解释为shell - 即使在手边的情况下(IP地址)它也没有任何区别。

[1]注意链接的POSIX规范。只需调用"$i"内置实用程序 dot ,而Bash使用术语 sourcing (并且还允许使用.代替{{1} })。无论哪种方式,关键方面是指定的脚本被加载到调用 shell的上下文中,因此允许该脚本修改调用脚本的环境(变量,函数,别名) ,shell选项状态,...) - 相比之下,直接调用脚本会导致它在子进程中运行而对调用shell没有影响&#39 ;环境。