如何修复bash中的函数

如何修复bash中的函数,bash,Bash,我不熟悉bash脚本,请耐心等待。 我有这段代码,它扫描域的端口,并向用户显示它们,它自己可以完美地工作,但当我添加函数时,它会给我错误。我做错了什么 check_parms () { case $# in 1) ports='1-1023' host=$1 ;; 2) ports=$1 host=$2 ;; *) echo 'Usage: portscan [port|range] host' exit 1 ;; esac }

我不熟悉bash脚本,请耐心等待。
我有这段代码,它扫描域的端口,并向用户显示它们,它自己可以完美地工作,但当我添加函数时,它会给我错误。我做错了什么

check_parms () {
case $# in
    1) ports='1-1023'
       host=$1 ;;
    2) ports=$1
       host=$2 ;;
    *) echo 'Usage: portscan [port|range] host'
       exit 1 ;;
esac
}

# check port range
check_ports () {
if [ "$(echo $ports | grep '^[1-9][0-9]*-[1-9][0-9]*$')" != "" ]; then
    firstport=$(echo $ports | cut -d- -f1)
    lastport=$(echo $ports | cut -d- -f2)
elif [ "$(echo $ports | grep '^[1-9][0-9]*$')" != "" ]; then
    firstport=$ports
    lastport=$ports
else
    echo "$ports is an invalid port(s) value"
    exit 2
fi
}

# check firstport > lastport
check_order () {
if [ $firstport -gt $lastport ]; then
    echo $firstport is larger than $lastport
    exit 3
fi
}

# check host value
check_host () {
regex='^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$'
if [ "$(echo $host | grep '[A-Za-z]')" != "" ]; then
    response=$(host $host)
    if [[ "$response" =~ "timed out" || "$response" =~ "not found" ]]; then
        echo host $host not found
        exit 4
    fi
elif [[ ! $host =~ $regex ]]; then
    echo $host is an invalid host address
    exit 5
fi
}

# check if host is reachable using ping
check_ping () {
if [[ "$(ping -c 1 -W 2 -n $host)" =~ "0 received" ]]; then
    echo $host is unreachable
    exit 6
fi
}

# start the scan     
do_scan () {
echo -n "Scanning "
for p in $(seq $firstport $lastport)
do
    echo -n .
    x=$((echo >/dev/tcp/$host/$p) >/dev/null 2>&1 && echo "$p open")
    if [ "$x" != "" ]; then  
        y="${y}
$x"
    fi
done
}

# show results of scan
show_results () {
echo -e "\n$y\n"
exit 0
}

check_parms $#
check_ports $ports
check_order $firstport $lastport
check_host $host
check_ping $host
do_scan $host $firstport $lastport
show_results

传递和使用函数参数的方式没有意义。我认为明显错误的是第一个:

check_parms () {
case $# in
    1) ports='1-1023'
       host=$1 ;;
    2) ports=$1
       host=$2 ;;
    *) echo 'Usage: portscan [port|range] host'
       exit 1 ;;
esac
}

#... then in the main program:
check_parms $#
为了理解这个问题,假设主脚本使用两个参数运行:“5-50”和“10.10.10.10”。行
check_parms$#
运行check_params并将参数数(2)作为参数传递给它。到目前为止还不错。然后在check#params中,它在中运行
case$#,但此时我们在check#params中,因此
$#
指的是传递给check#params的参数数量,而不是传递给主脚本的数量。check_params只传递了一个参数(数字2),因此
$#
为1,它执行
1)
案例,将端口设置为“1-1023”,主机设置为“2”。这根本不是你想要的

如果希望check_params能够看到传递给主脚本的相同参数,则必须使用
check_params“$@”
传递这些相同的参数

传递给其他函数的参数似乎没有被使用;这不一定会引起麻烦,但会造成代码混乱(混乱的代码会滋生bug)。考虑一下,例如CHECKSIORDER函数。您将它作为参数传递
$firstport
$lastport
(这意味着在check_顺序中,
$1
设置为
$firstport
的值,
$2
设置为
$lastport
的值),但是您不在check_顺序中使用这些参数;而是直接使用
$firstport
$lastport
,忽略参数。因为它们是相同的东西,所以这并不重要,但是如果以后有人试图将其用于其他用途(
check\u order$currentport 1023
),它将检查
$firstport
$lastport
),而不是它应该检查的内容

解决方案:更改函数以使用其参数,而不是直接访问全局变量。(或者显式地使用全局变量并停止假装将它们作为参数传递;但是全局变量通常是不好的,所以这是更糟糕的选择。)类似这样:

check_order () {
if [ $1 -gt $2 ]; then
    echo $1 is larger than $2
    exit 3
fi
}

当你提出一个好的问题时,首先要隔离你的问题,这样你就可以只显示你要问的问题所需要的最小的代码片段。使用
set-x
跟踪每个命令的运行并查看第一次出错的地方是一个很好的起点。另请参阅,我还建议您完成代码并修复它发现的问题。除上述建议外,您似乎有一个工作脚本,对它进行了一次“大”重写,发现它不工作。。。一般来说,您希望保持一个紧密的反馈循环,也就是说,更改一个(或只是一些事情),然后立即测试、修复某些事情是否有效,然后继续。。。。这样通常可以更清楚地知道错误所在。为了与其他网络工具保持一致,最好切换参数顺序:
portscan host port
。这也会巧合地简化代码,而且调整它以接受多个离散端口或范围也很简单。