two while nested loops

                        for server in $(echo `cat /tmp/ScanHosts_${USERSNAME}.TXT`)
                        do
                                for portnumber in $(echo `cat /tmp/ScanPorts_${USERSNAME}.TXT`)
                                do
                                        #echo ${server} ${portnumber}

                                        #nc -v ${server} ${portnumber} -w 2 | tr -d '\015\032' 2>/dev/null

                                        DATE=$(date | awk '{print $2" "$3" "$4" "$6}')
                                        ANSWER=$(nc -v ${server} ${portnumber} -w 2 | tr -d '\015\032' 2>/dev/null)

                                        if [ ! -z "${ANSWER}" ] ; then
                                               echo "${DATE} ${server}:${portnumber}:${ANSWER}" | tee -a /tmp/ScanResults_${USERSNAME}.txt
                                        elif [ -z "${ANSWER}" ] || [ "${ANSWER}" = "" ] ; then
                                               echo "${DATE} ${server}:${portnumber}:COULD NOT CONNECT" | tee -a /tmp/ScanResults_${USERSNAME}.txt
                                        else
                                               echo "${DATE} ${server}:${portnumber}:COULD NOT CONNECT" | tee -a /tmp/ScanResults.txt
                                        fi
                                done
                        done

is there a better way to run the above?

the first file being looped through contains a list of hosts. the second file contains a list of ports.

for each host found in the list of hosts, i want every port found in the port file scanned against it.

shell: bash
os: linux/sunos

Why not just use nmap? It's the right tool for this sort of task.

Anyway, after having a quick look at your script, I came up with:

Logic: Try and change things around so you have multiple nc commands running at once (in the background). After all, the majority of the runtime for a task like this is spent wating for the reply packets.

Instead of date | awk '{print $2" "$3" "$4" "$6}' , you can use date "+%d %b, %Y %T"

On this command:

ANSWER=$(nc -v ${server} ${portnumber} -w 2 | tr -d '\015\032' 2>/dev/null)

tr is pretty unlikley to produce any output on stderr, you probably want:

ANSWER=$(nc -v ${server} ${portnumber} -w 2 2> /dev/null | tr -d '\015\032')

thank you for the suggestions. i'm curious as to if all that "while looping" that im doing makes sense? is this how a more advanced user like you would do it?

i will incorporate your suggestions, however, i'm interested in making the while loop look more elegant. can awk be used for this?

The nested for loops are fine and are quite efficient as they are implemented within the shell. The trick here is to avoid calling the external command (nc) more times than is necessary.

As an example if you are just looking for open ports, you would gain a heap of performance by using the nc -z option and call nc once for the whole set of ports eg:

# nc -z host.example.com 25,80,5900-5910
Connection to host.example.com 25 port [tcp/smtp] succeeded!
Connection to host.example.com 5900 port [tcp/vnc] succeeded!

But, of course, this is different functionality and comes under requirements optimization, not code tweaking.

1 Like