2014-11-21 82 views
0

我對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 
} 

# 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 
+4

這個地方一起把一個很好的問題何時開始正在隔離你的問題,所以你可以只顯示一小段代碼來展示你所問​​的問題。使用'set -x'來跟蹤每個命令的運行,看看事情首先出錯的地方是一個很好的開始。另請參閱http://sscce.org/和http://stackoverflow.com/help/mcve – 2014-11-21 22:28:24

+4

我還建議通過http://shellcheck.net/將代碼加入並修復它發現的問題。 – 2014-11-21 22:30:00

+3

除了上面的建議,看起來你有一個工作腳本,做了一個「大」重寫,並發現它沒有工作......一般來說,你想要保持一個緊密的反饋循環,這意味着,改變一個(或者只是一些東西),然後立即測試,修復一些有效的工作,然後繼續......這樣一來,錯誤發生的地方通常會更清晰。 – Carpetsmoker 2014-11-21 22:34:57

回答

2

你傳遞和使用函數參數的方式沒有任何意義。一個我看這是公然錯的是第一:

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 $# in,但此時我們在check_params之內,因此$#引用傳遞給check_params的參數個數,而不是傳遞給主腳本的數量。 check_params只傳遞一個參數(數字2),因此$#爲1,它執行1)的情況,它將端口設置爲「1-1023」,主機設置爲「2」。這不是你想要的。

如果您希望check_params能夠看到傳遞給主腳本的相同參數,則必須將它們的相同參數傳遞給check_params "[email protected]"

傳遞給其他函數的參數根本不會被使用;這不一定會造成麻煩,但會造成混淆代碼(以及令人困惑的代碼會產生錯誤)。考慮一下,例如check_order函數。您將它作爲參數傳遞給$firstport$lastport(意思是在check_order中,$1設置爲$firstport的值,而$2設置爲$lastport的值),但是您不會在check_order中使用這些參數;而是直接使用$firstport$lastport,忽略參數。既然它們是同一件事,它並不重要,但如果有人以後嘗試將它用於其他事物(check_order $currentport 1023),它將檢查$firstport$lastport,而不是它應該檢查的內容。

解決方案:更改函數以使用它們的參數,而不是直接訪問全局變量。 (或者明確地使用全局變量,並停止假裝它們作爲參數傳遞,但全局是普遍不好,所以這是更壞的選擇。)事情是這樣的:

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