1

I want to make a script which will check if a port is open on a server. If not open stay in a while. If open continue. The break conditions is use are if "host is up" is present and not "closed". I assume conenction is ok. The problem is that the grep is not working as expected.

I have tried with following:

while true; do
 NMAP=$(nmap -p 1700 router.eu.thethings.network)
 if [[$NMAP | grep "Host is up" -ne ""]] && [[$NMAP | grep "closed" -eq ""]]; then
    echo "connection!!!"
    break
 fi


 echo "waiting for connectiong"
 done

I run it on a raspberry pi jessie system.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 1
    For a start, -eq and -ne are arithmetic operators. If you want to do string comparisons, you need = (==) and != – user4556274 Aug 08 '17 at 12:55

3 Answers3

6
nmap -p 1700 router.eu.thethings.network

Will print "Host is up" if the hosts network is up and there is nothing listening on the port. Use nc instead:

if nc -w1 -z router.eu.thethings.network 1700; then
  echo "Port is listening"
else
  echo "Port is not listening"
fi
m-ric
  • 125
Paranoid
  • 315
  • when i run the nc -z router.eu.thethings.network 1700 it does not return. Will it behave different in a script? – Peter Savnik Aug 08 '17 at 13:11
  • This is due to the way tcp/ip works. If it gets no response then it will resend and eventually timeout after about a minute. You could try a simple ping test before testing the port. – Paranoid Aug 08 '17 at 13:24
  • 1
    Add the -w1 option to nc to try the connection for one second. This will let you get a quick failure if the host is not up. – 111--- Aug 08 '17 at 13:49
2

The problem is that [[$NMAP | grep "Host is up" -ne ""]] is very far from valid bash syntax. The error messages don't tell you exactly how to fix it, but they are a hint that something is seriously wrong.

To test whether a string contains a substring, you can either use the == operator in a conditional expression, or a pipe through grep (which doesn't involve a conditional expression). With grep, you're not running $NMAP as a command, you want to pass this as input to grep, so you need to echo it into the pipe. Pass -q to grep since you only care about its return status, not about its output.

if echo "$NMAP" | grep "Host is up"  && echo "$NMAP" | grep "closed"; then …

With a conditional expression:

if [[ $NMAP == *"Host is up"* || $NMAP == *"closed"* ]]; then …

Do read Confused about operators [[ vs [ vs ( vs (( which explains about conditional expressions and how they aren't the only way to test whether a condition is true. Also, read Why does my shell script choke on whitespace or other special characters?

0

There is an example to display Host is up when grep success and Host is down when grep return nothing:

NMAP=$(nmap -p 1700 router.eu.thethings.network)
(NMAP$ | grep "Host is up") &>/dev/null && echo "Host is up" || echo "Host is down"
GAD3R
  • 66,769