t7e
t7e

Reputation: 509

Invoking the function in bash does not give the proper result

I took the code from this nice article: https://catonmat.net/tcp-port-scanner-in-bash

It uses the function scan. When I copy the code, it doesn't work for me.

I had similar issues with bash functions before and could not find the solution either.

I try to invoke the function this way directly in the script:

#!/bin/bash

scan() {
  if [[ -z $1 || -z $2 ]]; then
    echo "Usage: $0 <host> <port, ports, or port-range>"
    return
  fi

  local host=$1
  local ports=()
  case $2 in
    *-*)
      IFS=- read start end <<< "$2"
      for ((port=start; port <= end; port++)); do
        ports+=($port)
      done
      ;;
    *,*)
      IFS=, read -ra ports <<< "$2"
      ;;
    *)
      ports+=($2)
      ;;
  esac

  for port in "${ports[@]}"; do
    alarm 1 "echo >/dev/tcp/$host/$port" &&
      echo "port $port is open" ||
      echo "port $port is closed"
  done
}

scan

I also tried $(scan) - did not work as well.

The result - it does not want to scan anything ( I think there is something I should run in order to invoke the function - the code seems fine):

$ ./scan.sh google.com 22-99
Usage: ./scan.sh <host> <port, ports, or port-range>
$ ./scan.sh scan google.com 22-99
Usage: ./scan.sh <host> <port, ports, or port-range>

What am I missing? It is not the first time I've had a similar problem.


P.S. As was already suggested, scan "$1" "$2" did the job alright. However, now I encountered a similar issue when invoking this function from a different function:

function dosmth {
while test $# -gt 0; do
           case "$1" in
                -t)
                    shift
                    scan "$1" "$2"
                    shift
                    ;;
                *)

exit 1
                   ;;
          esac
  done
}

dosmth $1

I also tried dosmth "$1" "$2" - the issue persists.

Right now dosmth function works alright but scan has the similar result as before it does not scan anything.

$ ./dosmt.sh -t google.com 80
Usage: -t ./dosmt.sh <host> <port, ports, or port-range>


My solution may help somebody - I changed to: dosmth "$1" "$2" "$3"

Upvotes: 0

Views: 98

Answers (1)

Ivan
Ivan

Reputation: 7267

If function run from a script, you need to pass args from script to the function

...
scan "$1" "$2"

Same goes when function run from another function, you have to pass args from "parent" function to "child" function.

fun1() {
    echo "fun1 $1 $2"
}

fun2() {
    fun1 "$1" "$2"
}

fun2 "$1" "$2"

Also it's a good practice to create vars with appropriate names from this args($1, $2, $3 ...) to use in functions.

#!/bin/bash
script=$0
host=$1
port_range=$2
ports=()

scan() {
  if [[ -z $host || -z $port_range ]]; then
    echo "Usage: $script <host> <port, ports, or port-range>"
    return
  fi

  case $port_range in
    *-*)
      IFS=- read start end <<< "$port_range"
      for ((port=start; port <= end; port++)); do
        ports+=($port)
      done
      ;;
    *,*)
      IFS=, read -ra ports <<< "$port_range"
      ;;
    *)
      ports+=($port_range)
      ;;
  esac

  for port in "${ports[@]}"; do
    alarm 1 "echo >/dev/tcp/$host/$port" &&
      echo "port $port is open" ||
      echo "port $port is closed"
  done
}

scan

Upvotes: 2

Related Questions