Reputation: 49
I am getting an nmap result and I am trying to process various (host up or down) results using awk.
I am passing an ip address and I am trying to get the following: status (up or down), host name, OS.
GOAL: I need to have an access to every field to be able to update the database with its value. Also I am trying to accomplish that in as simple as possible way, maybe there is any way to save field in a variable so then I can use it, check if it's empty etc.?
More into details:
Expected output of host that is up:
$ip $status $host_name $os when host up: 134.99.120.2 host_up HostName Linux when host down: 134.99.120.2 host_down unknown unknown
I came up with this one liner here:
sudo nmap -O -R -p 22 -oN -T4 134.99.120.2 | awk '/down/{print$5}/Nmap scan report/{print$5}/Running:/{print$2}/OS guess/{print$4}'
But that does not provide any control over the output.
Raw Outputs from nmap:
When Host up:
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 14:58 EST > Nmap scan report for HostName (134.99.120.2) Host is up (0.00067s > latency). PORT STATE SERVICE 22/tcp open ssh Warning: OSScan > results may be unreliable because we could not find at least 1 open > and 1 closed port Device type: general purpose Running: Linux OS CPE: > xx:/o:xxx:xxxxxos:9.10 OS details: Linux Network Distance: 7 hops OS > detection performed. Please report any incorrect results at > http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned > in 2.58 seconds
When host down:
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 15:00 EST > Note: Host seems down. If it is really up, but blocking our ping > probes, try -Pn Nmap done: 1 IP address (0 hosts up) scanned in 3.64 > seconds
Upvotes: 1
Views: 223
Reputation: 33799
Decided to take a swipe at a (simple) token analyzer that eliminates the need for hard coded field references in awk
, but still assumes the textual output from nmap
is as displayed in the OPs sample outputs.
Sample inputs (in lieu of running nmap
on my host):
$ cat nmap.up.dat
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 14:58 EST
> Nmap scan report for HostName (134.99.120.2) Host is up (0.00067s
> latency). PORT STATE SERVICE 22/tcp open ssh Warning: OSScan
> results may be unreliable because we could not find at least 1 open
> and 1 closed port Device type: general purpose Running: Linux OS CPE:
> xx:/o:xxx:xxxxxos:9.10 OS details: Linux Network Distance: 7 hops OS
> detection performed. Please report any incorrect results at
> http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned
> in 2.58 seconds
$ cat nmap.down.dat
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 15:00 EST
> Note: Host seems down. If it is really up, but blocking our ping
> probes, try -Pn Nmap done: 1 IP address (0 hosts up) scanned in 3.64
> seconds
One awk
idea for a token analyzer:
ipaddr='134.99.120.2'
awk -v ip="${ipaddr}" ' # pass ip addr in as awk variable "ip"
FNR==1 { hstat="host_up" # reset defaults for status ...
hname=hos="unknown" # hostname and host OS
prev="" # clear our "prev"ious token
}
{ for ( i=1 ; i<=NF ; i++ ) # process each field
{ token=$(i) # make note of current token aka field
if ( token == ">" ) continue # ignore the ">" in the first column
# if our "prev"ious token matches any of the case statements then
# update our variables according to the current token
switch (prev) {
case "scan" : if ( token == "report") { prev=prev" "token } ; break
case "scan report" : if ( token == "for" ) { prev=prev" "token } ; break
case "scan report for": hname=token ; prev=token ; break
case "down." : hstat="host_down" ; prev=token ; break
case "Running:" : hos=token ; prev=token ; break
default : prev=token ; break
}
}
}
ENDFILE { fmt="%-18s%-12s%-15s%s\n" # re-usable format
if ( NR==FNR ) # for first file print a header:
{ printf fmt, "$ip", "$status", "$host_name", "$os" }
printf fmt, ip, hstat, hname, hos # otherwise print results
}
' nmap.up.dat nmap.down.dat
NOTE: ENDFILE requires GNU awk
This above generates:
$ip $status $host_name $os
134.99.120.2 host_up HostName Linux
134.99.120.2 host_down unknown unknown
Upvotes: 1
Reputation: 33799
NOTE Looks like Raman was a bit faster on the 'Post Your Answer' button ...
Assumptions:
nmap
output will always be like one of the two examples provided by OPnmap
output will always have the Hostname
and OS
name in the same fields (ie, don't have to worry about nmap
wrapping lines at different words due to variable lengths of data)OS guess
in their sample awk
, the sample nmap
data shows OS details
(answer - below - is based on OS details
; OP can modify per what their nmap
call actually returns)nmap
data does in fact include a >
in the first column of every line of output (as displayed in OPs sample inputs); this means OPs awk
field references may need to shift +/- accordingly (OP can adjust answer - below - based on whether or not a line starts with >
)Sample inputs (in lieu of running nmap
on my host):
$ cat nmap.up.dat
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 14:58 EST
> Nmap scan report for HostName (134.99.120.2) Host is up (0.00067s
> latency). PORT STATE SERVICE 22/tcp open ssh Warning: OSScan
> results may be unreliable because we could not find at least 1 open
> and 1 closed port Device type: general purpose Running: Linux OS CPE:
> xx:/o:xxx:xxxxxos:9.10 OS details: Linux Network Distance: 7 hops OS
> detection performed. Please report any incorrect results at
> http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned
> in 2.58 seconds
$ cat nmap.down.dat
> Starting Nmap 6.40 ( http://nmap.org ) at 2020-11-29 15:00 EST
> Note: Host seems down. If it is really up, but blocking our ping
> probes, try -Pn Nmap done: 1 IP address (0 hosts up) scanned in 3.64
> seconds
One awk
solution, though I'm assuming OP won't actually have 2 sets of nmap
output for a single ip address (???) ...
ipaddr='134.99.120.2'
awk -v ip="${ipaddr}" ' # pass ip addr in as awk variable "ip"
FNR==1 { hstat="host_up" # reset defaults for status ...
hname=hos="unknown" # hostname and host OS
}
/down/ { hstat="host_down" ; next } # reset status
/scan report for/ { hname=$6 ; next } # reset hostname
/OS details/ { hos=$5 ; next } # reset host OS
ENDFILE { fmt="%-18s%-12s%-15s%s\n" # re-usable format
if ( NR==FNR ) # for first file print a header:
{ printf fmt, "$ip", "$status", "$host_name", "$os" }
printf fmt, ip, hstat, hname, hos # otherwise print results
}
' nmap.up.dat nmap.down.dat
NOTE: ENDFILE
requires GNU awk
(per Ed Morton's comment)
The above generates:
$ip $status $host_name $os
134.99.120.2 host_up HostName Linux
134.99.120.2 host_down unknown unknown
Upvotes: 1
Reputation: 12867
You can actually format the data as required by setting the extracted data as variables within awk and then printing them in an END block and so:
sudo nmap -O -R -p 22 -oN -T4 134.99.120.2 | awk -v ip="134.99.120.2" '
/Host is up/ {
status="host_up"
}
/Host seems down/ {
status="host_down"
}
/Nmap scan report/ {
hstname=$5
}
/Running:/ {
os=$2
}
/OS guess/ {
os=$4
}
END {
!os?os="unknown":os=os;
!hstname?hstname="unknown":hstname=hstname;
printf "%s\t%s\t%s\t%s\n",ip,status,hstname,os
}'
One liner:
sudo nmap -O -R -p 22 -oN -T4 134.99.120.2 | awk -v ip="134.99.120.2" '/Host is up/ { status="host_up" } /Host seems down/ { status="host_down" } /Nmap scan report/ { hstname=$5 } /Running:/ { os=$2 } /OS guess/ { os=$4 } END { !os?os="unknown":os=os;!hstname?hstname="unknown":hstname=hstname;printf "%s\t%s\t%s\t%s\n",ip,status,hstname,os }'
Pass the variable ip into awk with -F and then set the os, hstname and status based on the searched text. In the end block, check to see if hstname and os variables exist. If they don't exist, set the variables to unknown, otherwise set them to what they already are. Finally print the variables in the format required.
Upvotes: 3