Jump to content


Photo

Bash Scripting


  • Please log in to reply
7 replies to this topic

#1 lew~

lew~

    Banoffee Pie

  • Atomican
  • 7,913 posts

Posted 25 October 2011 - 02:39 PM

Not sure if this should be in Programming or here.

I have a file with a list of IP addresses, one per line. E.g.:
$ cat ip-list.txt
10.1.1.1
10.1.1.2
10.1.1.3
10.1.1.4


I want to perform a snmpget against each IP in the file, and write the IP with the output into a new file, e.g.:

for $IP in ip-list.txt
do
snmpget -v 2c -c string $IP sysName.0

and have the output appear as follows (tab delimited, for example):
10.1.1.1,host1
10.1.1.2,host2
10.1.1.3,host3
10.1.1.4,host4

For bonus points, return 'null' or similar where no response is received.

In case it's relevant, the output of snmpget looks like this:
$ snmpget -v 2c -c string n.n.n.n sysName.0
SNMPv2-MIB::sysName.0 = STRING: hostname



I have access to redhat, linux and OS X command lines so i'm sure I have the tools I need, just not sure how to put it together. Managed to grep, sed & cat my way to the clean list of IPs, but haven't worked out this last bit.

Ideas?

#2 sponger

sponger

    Apple Strudel

  • Atomican
  • 12,142 posts

Posted 25 October 2011 - 07:47 PM

A bit ugly but should do it:

for IP in `cat ip-list.txt`; do
  output=$(snmpget -v 2c -c string $IP sysName.0)
  if [ $? -eq 0 ]; then
	echo $IP,`echo $output | awk '{print $NF}'`
  else
	echo $IP,null
  fi
done


#3 lew~

lew~

    Banoffee Pie

  • Atomican
  • 7,913 posts

Posted 25 October 2011 - 10:03 PM

A bit ugly but should do it:

for IP in `cat ip-list.txt`; do
  output=$(snmpget -v 2c -c string $IP sysName.0)
  if [ $? -eq 0 ]; then
	echo $IP,`echo $output | awk '{print $NF}'`
  else
	echo $IP,null
  fi
done

Thanks sponger, I'll give it a go tomorrow. You're the boss with this stuff, but do you need to 'declare' the IP variable in the first line or anything? I just typed out pseudo-code in the OP, that doesn't necessarily do anything :p


Edit:

Works awesome sponger, thanks!

Where there's no response it prints two lines; the snmpget output and the script output, but that's not a big deal - easy to clean out:
Timeout: No Response from 10.1.1.1.
10.1.1.1,null

Edited by lew~, 26 October 2011 - 09:22 AM.


#4 sponger

sponger

    Apple Strudel

  • Atomican
  • 12,142 posts

Posted 26 October 2011 - 01:13 PM

No prob

That extra output is probably to stderr, so try changing this line:

output=$(snmpget -v 2c -c string $IP sysName.0 2> /dev/null)

Edited by sponger, 26 October 2011 - 01:14 PM.


#5 lew~

lew~

    Banoffee Pie

  • Atomican
  • 7,913 posts

Posted 26 October 2011 - 05:05 PM

stderr as opposed to stdout, so that wouldn't impact on the output from the command right? cool.
Edit: It doesn't actually write stderr to the file, so it's all good.


Tried to expand on it, but it only half works. It will do the snmpget and the dig if that fails. But it won't do the nmap or "echo $IP,null". Any ideas?
Does it matter that the nmap output is multiple lines?

#! /bin/bash

for IP in `cat resolve.txt`; do
		output=$(snmpget -v 2c -c string $IP sysName.0)
		if [ $? -eq 0 ]; then
				echo $IP,`echo $output | awk '{print $NF}'`
		else
		output=$(dig -x $IP +short)
		if [ $? -eq 0 ]; then
				echo $IP,`echo $output | awk '{print $NF}'`
		else
		output=$(nmap -Pn -F -sS -sU -O -T4 -R --max-retries 3 $IP)
		if [ $? -eq 0 ]; then
				echo $IP,`echo $output | awk '{print $NF}'`
		else
				echo $IP,null
		fi
		fi
		fi
done

Edited by lew~, 26 October 2011 - 06:01 PM.


#6 sponger

sponger

    Apple Strudel

  • Atomican
  • 12,142 posts

Posted 26 October 2011 - 06:40 PM

Try this:

for IP in `cat testresolve.txt`; do
  output=$(snmpget -v 2c -c string $IP sysName.0 2> /dev/null)
  if [ $? -eq 0 ]; then
	host=`echo $output | awk '{print $NF}'`
  else
	output=$(dig -x $IP +short 2> /dev/null)
	if [[ $? -eq 0 && $output =~ ([^[:space:]]*)\. ]]; then
	  host=${BASH_REMATCH[1]}
	else
	  output=$(nmap -Ss -Su -F -O -T4 -R --max-retries 3 $IP 2> /dev/null)
	  if [[ $? -eq 0 && $output =~ report\ for\ ([^[:space:]]*)[[:space:]] ]]; then
		host=${BASH_REMATCH[1]}
	  else
		host=null
	  fi
	fi
  fi
  echo $IP,$host
done

For each command you add you'll have to work out how to get the host from its output. The original code depended on snmpget only.

If the above doesn't work, show me some output for dig and nmap. I just did some quick tests on a different platform to you (OpenBSD).

#7 lew~

lew~

    Banoffee Pie

  • Atomican
  • 7,913 posts

Posted 02 November 2011 - 10:00 AM

Hey sponger, I've had a bit more time to play with this. What you provided works really well, both snmpet and dig outputs are perfect.

I think because of how the NMAP output matching is done, it currently returns the IP address as $host. e.g.:
10.1.1.1,10.1.1.1

The NMAP output looks like this, with the OS detection section varying depending on what it finds:

# nmap -Pn -F -sS -sU -O -T4 -R --max-retries 3 10.1.1.1

Starting Nmap 5.35DC1 ( http://nmap.org ) at 2011-11-02 10:02 CST
Nmap scan report for 10.1.1.1
Host is up (0.00090s latency).
Not shown: 100 open|filtered ports, 99 filtered ports
PORT	STATE  SERVICE
x/x closed x
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: switch|firewall|broadband router
Running: producta, productb, productc
OS details: producta, productb, productc

OS detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.78 seconds


OS detection examples:

# nmap -Pn -F -sS -sU -O -T4 -R --max-retries 3 10.1.1.1 | egrep "OS:|OS details:"
OS:SCAN(V=5.35DC1%D=11/2%OT=21%CT=7%CU=7%PV=Y%DS=4%DC=I%G=Y%TM=4EB08387%P=i
OS:686-redhat-linux-gnu)SEQ(SP=100%GCD=1%ISR=100%TI=BI%TS=7)SEQ(TS=9)SEQ(TI
OS:=RI%TS=8)OPS(O1=M5B4ST11NW0%O2=M5B4ST11NW0%O3=M5B4NNT11NW0%O4=M5B4ST11NW
OS:0%O5=M5B4ST11NW0%O6=M5B4ST11)WIN(W1=16A0%W2=16A0%W3=16A0%W4=16A0%W5=16A0
OS:%W6=16A0)ECN(R=N)T1(R=Y%DF=Y%T=41%S=O%A=S+%F=AS%RD=0%Q=)T1(R=Y%DF=Y%T=41
OS:%S=O%A=O%F=AS%RD=0%Q=)T1(R=N)T2(R=N)T3(R=N)T4(R=N)T5(R=Y%DF=Y%T=7F%W=0%S
OS:=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=N)T7(R=N)U1(R=Y%DF=N%T=7F%IPL=164%UN=0%RIPL
OS:=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=N)
# nmap -Pn -F -sS -sU -O -T4 -R --max-retries 3 10.1.1.2 | egrep "OS:|OS details:"
OS details: producta, productb, productc




Would it be possible to output the "OS details" line if it exists else null?, e.g.:
10.1.1.1,host1
10.1.1.2,host2
10.1.1.3,OS details: producta, productb, productc
10.1.1.4,host4






Also, the other thing I was wondering is if it would be possible to print the method in between $IP & $host? e.g.
10.1.1.1,DNS,host1
10.1.1.2,SNMP,host2

I tried adding it in to the host= line but it didn't like my attempted syntax :(

#8 sponger

sponger

    Apple Strudel

  • Atomican
  • 12,142 posts

Posted 07 December 2011 - 05:42 PM

Finally got some time, try this...have cleaned up, haven't tested at all though. You can now pass the filename as an argument, /path/to/script filename

#!/path/to/bash

[ -e $1 ] && cat $1 | while read IP; do
  output=$(snmpget -v 2c -c string $IP sysName.0 2> /dev/null)
  if [[ $? -eq 0 && $output =~ ([^[:space:]]*)$ ]]; then
	host=${BASH_REMATCH[1]}
  else
	output=$(dig -x $IP +short 2> /dev/null)
	if [[ $? -eq 0 && $output =~ ([^[:space:]]*)\. ]]; then
	  host=${BASH_REMATCH[1]}
	else
	  output=$(nmap -Ss -Su -F -O -T4 -R --max-retries 3 $IP 2> /dev/null)
	  if [ $? -eq 0 ]; then
		host=$(echo "$output" | grep "OS details")		  
	  else
		host=null
	  fi
	fi
  fi
  echo $IP,$host
done

If you don't want "OS details: ", just "producta, productb, productc", replace

host=$(echo "$output" | grep "OS details")
with

echo "$output" | while read line; do
  [[ $line =~ ^OS\ details:\ (.*)$ ]] && host=${BASH_REMATCH[1]} 
done





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users