如何在 bash 脚本中使这些多个 Nmap 命令更优雅?

How do I make these multiple Nmap commands more elegant in bash script?

我有一个我一直在处理的小项目脚本,它扫描我的网络以寻找新的 MAC 地址,并在我的网络上有不熟悉的设备时通知我。

我已经引入了对未知 MAC 地址自动执行 OS 扫描的功能(如果有的话)。但是,我只能通过将 ping 扫描的 grepped 部分保存到一个临时文件 (tmpmac.txt),然后将该文件中的 IP 地址 grep 到另一个临时文件 (tmpip.txt), 因为 -O Nmap 选项需要 IP 才能扫描:

        nmap -sn 192.168.0.0/24 | grep -B 2 "$address" > /home/pi/tmpmac.txt
        cat /home/pi/tmpmac.txt | grep "Nmap" | awk {'print '} > /home/pi/tmpip.txt
        unknown_mac=$( cat /home/pi/tmpip.txt )
        nmap -O $unknown_mac | tee -a /home/pi/mac_scan.log | mutt -s "OS Scan for $address" XXXXXXXX@gmail.com

整个脚本:

echo "<<---AUTOMATIC SCAN--->>" >>/home/pi/mac_scan.log
date >>/home/pi/mac_scan.log
nmap -sn 192.168.0.0/24 | grep "MAC" | awk '{print }'| sort > /home/pi/arp.txt

readarray -t mac </home/pi/arp.txt

foundall=true

for address in "${mac[@]}"; do
    if ! grep -Fxq "$address" /home/pi/arp_table.txt;
    then
        echo "WARNING: $address is an unknown device on the network" >> /home/pi/mac_scan.log
        nmap -sn 192.168.0.0/24 | grep -B 2 "$address" | tee -a /home/pi/mac_scan.log | mutt -s "Unknown Devices on Network" XXXXXXX@yahoo.com
        echo ""
        echo "MAC SEARCH RESULTS: $address" >> /home/pi/mac_scan.log
        nmap -sn 192.168.0.0/24 | grep -B 2 "$address" > /home/pi/tmpmac.txt
        cat /home/pi/tmpmac.txt | grep "Nmap" | awk {'print '} > /home/pi/tmpip.txt
        unknown_mac=$( cat /home/pi/tmpip.txt )
        nmap -O $unknown_mac | tee -a /home/pi/mac_scan.log | mutt -s "OS Scan for $address" XXXXXXXX@yahoo.com
        foundall=false
    fi
done

[[ "${foundall}" == 'true' ]] && echo "All Devices are familiar on your network" | tee -a /home/pi/mac_scan.log

当前形式的脚本执行应有的方式,但我很好奇是否有更优雅的方法来完成此操作。

我的 nmap 显然与你的输出不同,所以我无法对此进行测试,但我看不出有任何理由不跳过所有文件,并将整个管道放在 var=$(command)结构:

unknown_mac=$( nmap -sn 192.168.0.0/24 |
               grep -B 2 "$address" |
               grep "Nmap" |
               awk {'print '} )

但是,整个脚本运行s nmap -sn 192.168.0.0/24多次(开始一次,然后每个新主机两次);为什么不在开始时将其存储在变量(或文件)中,然后在需要时使用它?

hostscan=$(nmap -sn 192.168.0.0/24)
...
echo "$hostscan" | othercommand
# or:
othercommand <<<"$hostscan"
# or if you prefer:
<<<"$hostscan" othercommand

请注意,使用变量时双引号很重要。实际上,您应该几乎总是用双引号引用变量;有时您可以跳过双引号,但 understanding when it's safe is more trouble than it's worth. There are a bunch of other places in the script where you should do this. shellcheck.net 善于指出它们以及其他常见错误;我建议 运行 通过它修改你的脚本并修复它指出的内容。

您也可以将 grep "somestring" | awk '{print }' 折叠为 awk '/somestring/ {print }。通过所有这些更改,捕获未知 MAC 只是:

unknown_mac=$(<<<"$hostscan" grep -B 2 "$address" | awk '{/Nmap/ print }')

您还可以使用带 readarray 的此处字符串 (<<<)(注意:将 readarray 放在管道的末尾是行不通的,因为管道中的东西运行 在子外壳中):

readarray -t mac <<<"$(<<<"$hostscan" awk '/MAC/ {print }' | sort)"