2

I have this function in bash that uses netcat to check that a port is open on an address. As an example, I am testing with localhost 3000.

ERROR

I am having trouble getting the error code from running nc. I keep seeing the messge:

nc_output: integer expression expected

from the if-condition. (See CODE below)

CODE

#!/bin/bash
set -o nounset

scan() {
  local host=$1
  local port=$2
  local nc_output

  nc_output=$(nc ${host} ${port} -w 5)
  eval ${nc_output}
  if [ nc_output -ne 0 ]; then
     "PORT ${port} CLOSED on ${host}"
  else
    echo "PORT ${port} OPEN on ${host}"
  fi
}

scan 127.0.0.1 3000
Inian
  • 80,270
  • 14
  • 142
  • 161
vamsiampolu
  • 6,328
  • 19
  • 82
  • 183
  • `if [ "$nc_output" -ne 0 ]; then` (note the dollar sign before the variable), what you have compares a literal string `nc_output` with `0` – Inian Aug 16 '19 at 06:35
  • What is `eval ${nc_output}` supposed to do? – melpomene Aug 16 '19 at 06:45
  • "*nc output is not an exit code*" is correct (output and exit codes are different things), but what does that have to do with your question? – melpomene Aug 16 '19 at 06:45
  • @melpomene I am trying to run the nc command by using `eval ${nc_output}` which should run the command. – vamsiampolu Aug 16 '19 at 06:47
  • That makes no sense. `$(nc ${host} ${port} -w 5)` already runs `nc`. – melpomene Aug 16 '19 at 06:56
  • @melpomene I got it working with `nc -z ${host} ${port}` followed by `nc_output=$?` on the next line. – vamsiampolu Aug 16 '19 at 06:58
  • @melpomene: I think OP most likely wrongly used a command substitution syntax instead of just plain variable assignment. Maybe the intention was to assign the `nc` command in a variable and `eval` it (which is a bad approach also) – Inian Aug 16 '19 at 06:59
  • 1
    That means `nc_output` is misnamed. `$?` is the exit code, not the output. – melpomene Aug 16 '19 at 06:59
  • @melpomene Good call. I renamed it to `nc_exit_code`. – vamsiampolu Aug 16 '19 at 07:07
  • If all you're doing is testing the exit status, you could just write `if nc ${host} ${port} -w 5; then echo "open"; fi`. – melpomene Aug 16 '19 at 07:09
  • Closely a duplicate of [How to display nc return value in Linux shell script?](https://stackoverflow.com/q/42377276/5291015), but this needed an explanation to what was wrong with OP's attempt – Inian Aug 16 '19 at 07:27

1 Answers1

11

I think the problem comes down to usage of how you are storing the nc command in a variable to eval it later. When you did

nc_output=$(nc ${host} ${port} -w 5)
#          ^^                      ^

The marked syntax $(..) is for command substitution in bash, which runs the command inside and stores the output of the command in the variable used. So the above line runs the nc command and stores the output returned in the variable nc_output. Remember this only stores the standard output of the command and not the return code of the nc command which should been fetched from the variable $?

I'm guessing your intention was to store the command in a variable and then eval it once and get the exit code, but you are doing it wrong by eval-ing the output returned from the nc command which is roundabout and unnecessary.

The ideal way should have been just

nc "${host}" "${port}" -w 5
nc_exit_code=$?

and use this variable in the condition

if [ "$nc_exit_code" -ne 0 ]; then

Note that the $ prefix before the variable name. You need to use the $var syntax to access the value of the identifier var in shell syntax. You weren't using the symbol in your original post. Not doing so will compare a literal string nc_output with 0 which does not make sense as the native types of two are different from one another.

Also storing this exit code explicitly in a variable is redundant, the if conditionals work directly on the exit code of the command returned, so just

if ! nc "${host}" "${port}" -w 5; then
    echo "PORT ${port} CLOSED on ${host}"
else
    echo "PORT ${port} OPEN on ${host}"
fi

should be sufficient for your logic.

Inian
  • 80,270
  • 14
  • 142
  • 161