我有一个 bash 脚本,它列出了一个端口上连接的 IP 地址数量。我的问题是,如果有大量连接,它会像便便一样慢。我认为这是因为使用了子外壳,但我无法在不破坏脚本其余部分的情况下删除它们。这是完整的脚本,因为它相当短:
#!/bin/bash
portnumber=80
reversedns_enabled=0
[ ! -z "${1}" ] && portnumber=${1}
[ ! -z "${2}" ] && reversedns_enabled=${2}
#this will hold all of our ip addresses extracted from netstat
ipaddresses=""
#get all of our connected ip addresses
while read line; do
ipaddress=$( echo ${line} | cut -d' ' -f5 | sed s/:[^:]*$// )
ipaddresses="${ipaddresses}${ipaddress}\n"
done < <( netstat -ano | grep -v unix | grep ESTABLISHED | grep \:${portnumber} )
#remove trailing newline
ipaddresses=${ipaddresses%%??}
#output of program
finaloutput=""
#get our ip addresses sorted, uniq counted, and reverse sorted based on amount of uniq
while read line; do
if [[ ${reversedns_enabled} -eq 1 ]]; then
reversednsname=""
#we use justipaddress to do our nslookup(remove the count of uniq)
justipaddress=$( echo ${line} | cut -d' ' -f2 )
reversednsstring=$( host ${justipaddress} )
if echo "${reversednsstring}" | grep -q "domain name pointer"; then
reversednsname=$( echo ${reversednsstring} | grep -o "pointer .*" | cut -d' ' -f2 )
else
reversednsname="reverse-dns-not-found"
fi
finaloutput="${finaloutput}${line} ${reversednsname}\n"
else
finaloutput="${finaloutput}${line}\n"
fi
done < <( echo -e ${ipaddresses} | uniq -c | sort -r )
#tabulate that sheet son
echo -e ${finaloutput} | column -t
大部分时间都花在了这个操作上:echo ${line} |剪切-d''-f5 | sed s/:[^:]*$//
内联它以生成更快的脚本的最佳方法是什么。 1000 个并发用户需要超过一秒的时间(这是我的基本目标,尽管应该能够在不耗尽我所有 cpu 的情况下处理更多)。
最佳答案
您可以使用 cut -d' ' <<< "$line" | sed ...
来减少它.你可以写一个更复杂的 sed
脚本并避免使用 cut
.
但真正的好处是避免循环,所以只有一个 sed
(或 awk
或 perl
或……)涉及脚本。我可能希望将其减少到 ipaddresses=$(netstat -ano | awk '...')
所以不是 3 grep
进程,加一 cut
和 sed
每行,只有一个 awk
过程。
ipaddresses=$(netstat -ano |
awk " /unix/ { next } # grep -v unix
!/ESTABLISHED/ { next } # grep ESTABLISHED
!/:${portnumber}/ { next } # grep :${portnum} "'
{ sub(/:[^:]*$/, "", $5); print $5; }'
)
这可能相当笨拙,但它是对现有代码的相当直接的音译。注意报价以获得${portnumber}
进入正则表达式。
由于您将 IP 地址列表输入 uniq -c
和 sort -r
.你可能应该使用 sort -rn
, 你可以使用 awk
做 uniq -c
,也是。
唯一不能轻易改进的是 host
;这似乎一次只接受一个主机或 IP 地址参数,因此您必须为每个名称或地址运行它。
关于linux - 优化 Bash 脚本,移除 subshell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21083851/