A bash/awk/sed script will always be easy and quick to write for boomers. However there are some benefits to using Python or Ruby – namely appearing trendy. So to faciliate learning Python I will convert some of my scripts.
If a script is written quickly and for personal use then its not going to be pretty. It’s not going to have a “usage” section or might have local only aspects to it. By exposing it to a wider audience I risk ridicule – so okay, even this small bash hack has been tidied up:
#!/bin/bash
function usage {
printf "USAGE:\n"
printf " $0 -n C-CLASS-NETWORK\n"
printf "PURPOSE:\n"
printf " to ping and dns check the network\n"
printf " to see what is available\n"
printf " it will leave the output in NETWORK.txt file\n"
printf " and old output in old/NETWORK.bak file\n"
printf "EXAMPLE:\n"
printf " -n 192.168.0\n"
printf " -h\n"
exit 1
}
if [[ ${#} -eq 0 ]]; then
usage
fi
optstring="hn:"
while getopts ${optstring} arg; do
case ${arg} in
h)
echo "showing usage!"
usage
;;
n)
NETWORK=$2
shift;;
esac
done
file=$NETWORK.txt
test -d old || mkdir old
cp $file old/${file}.bak
>$file
count=0
while [ $count -lt 254 ]
do
count=$((count +1))
printf "%s.%s " $NETWORK $count | tee -a $file
str="none"
str="$(dig -x $NETWORK.$count +short)"
str=${str:-nodns}
printf "%40s " $str | tee -a $file
ping -c 2 -W 5 $NETWORK.$count >/dev/null
if [ $? -eq 0 ];
then printf "%10s\n" "pingable" | tee -a $file
else
printf "%10s\n" "noanswer" | tee -a $file
fi
done
So basically I get output like this:
192.168.1.1 gateway.example.com. pingable 192.168.1.2 nodns noanswer 192.168.1.3 nodns noanswer
I just want to see how populated a LAN is so I can allocate an IP to a new host. (By the way, once I’d picked out a free IP I would probably make additional checks – such as run a port scanner against the IP.)
So in Python, using the Python code seen recently by Daniel Monaghan, this is what I have come up with.
#!/usr/bin/env python3
import ipaddress
import socket
import sys
import subprocess
import shutil
import os
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:n:v", ["help", "network="])
except getopt.GetoptError as err:
print(err)
sys.exit()
def usage():
print("Usage: ")
print(" %s [-h] [[-o <outputfile>] -n <cidr network>]" % sys.argv[0])
print("Example:")
print(" %s -o 192.168.1.txt -n 192.168.1.0/23" % sys.argv[0])
print("Further:")
print(" It will put the output to the screen and will put the result")
print(" in a file called result.txt even if no output file is specified.")
print(" It also lists out the non-answering machines to the screen after")
print(" it completes the range.")
outfile = 'result.txt'
ranges = "x"
for name, value in opts:
if name in ['-h', '--help']:
usage()
sys.exit()
elif name in ['-o', '--output'] :
outfile = str(value)
elif name in ['-n', '--network'] :
ranges = [ str(value) ]
else:
usage()
sys.exit()
if ranges == "x":
print("Must specify a LAN eg. -n 192.168.0.0/24")
sys.exit()
#ranges = ["147.197.131.31/32", "147.197.131.33"]
#ranges = ["147.197.108.0/24", "147.197.131.0/24"]
def check_host(ip):
status = ""
bad_result="100% packet loss"
p = subprocess.Popen(["timeout", "5", "ping", "-c", "1", "-w", "1", ip ],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = str(p.communicate()).strip("\\\n")
ptr, alias, sock = lookup(ip)
if bad_result in result:
status = status + "NOANSWER"
else:
status = status + "OK"
return ptr, status, ip
def lookup(addr):
try:
return socket.gethostbyaddr(addr)
except socket.herror:
return "NoDnsEntry", None,addr
dict = {}
if os.path.exists(outfile):
shutil.move(outfile, outfile + ".bak")
f = open(outfile, "a")
for range in ranges:
for ip in ipaddress.IPv4Network(range):
ptr, status, ip = check_host(str(ip))
dict[ip] = status
print(ip.ljust(15),status.ljust(15),ptr.ljust(40))
f.write("%s%s%s\n" % (ip.ljust(15,' '), status.ljust(15,' '), ptr.ljust(40,' ') ))
for i, s in dict.items():
if s != "OK":
print(i.ljust(15),s.ljust(15),lookup(i)[0])
f.close()
sys.exit()
Hard work (as with anything new) but strangely satisfying – -perhaps by being a bit more precise.