1

I have a bash script where I continuously read from a text file the hosts and port and create a connection to check for the status.

My code is:

while IFS=";" read -r host ports
do
    eval "arr=($ports)"
    for port in "${arr[@]}";
    do
        echo "connecting to $host on port $port" >> output.txt
        timeout 5s telnet $host $port
        exit_status=$?
        if [[ $exit_status -eq 124 ]]; then
            echo "$host on $port has timed out" >> output.txt
        else
            telnet $host $port >> output.txt
        fi
    echo "---------------------------------------------" >> output.txt
    done
done < "$1"

The first if is to check if the connection timeouts. That works as expected.

In the else - telnet $host $port, I am checking that if the connection does not timeout, then telnet into the remote host to see if the connection was successful or refused.

But, when the connection is successful, the script exits abruptly by spitting out:

Escape character is '^]'.
Connection closed by foreign host.

I want it to write to the output file, "connection is successful" and continue reading the remainder of $1.

When connection is refused, the script does not exit; it works as expected -- it continues to read from $1 and continues running the instructions.

I also, am in a situation where I cannot use netcat.

  • What do you mean, "file status"? You've determined that the port didn't time out, but what's the point of the telnet connection? Are you hoping to establish a connection and execute a command? – Jeff Schaller Dec 28 '18 at 18:51
  • telnet $host $port >> output.txt </dev/null? – Cyrus Dec 29 '18 at 9:38
  • 1
    @JeffSchaller I am trying to check if the connection to the host has been established or refused and write that result to the output file. – RPT Dec 29 '18 at 13:56
1
+50

As roaima pointed out, the telnet commands will soak up stdin input, which you've redirected into the while loop. As a result, as soon as one of the telnet connections is successful, your while loop will end because telnet gobbled up the rest of the input that you were expecting to be fed to while.

The immediate solution to that problem is to redirect telnet's input, most simply from /dev/null, as commented by Cyrus: telnet host port >> output.txt < /dev/null.

To differentiate between a successful connection and a (presumably >5s delayed) refused connection, I've captured the output from the telnet command and checked for the "Connected to" message. If that message is present, we assume success; otherwise: failure.

The main changes to your script were:

  1. redirecting both telnet's stdin from /dev/null
  2. quoting all the variables
  3. capturing & checking the else - telnet output for comparison

The updated script:

#!/bin/bash
while IFS=";" read -r host ports
do
    eval "arr=($ports)"
    for port in "${arr[@]}";
    do
        echo "connecting to $host on port $port" >> output.txt
        timeout 5s telnet "$host" "$port" < /dev/null
        exit_status=$?
        if [[ "$exit_status" -eq 124 ]]; then
            echo "$host on $port has timed out" >> output.txt
        else
            output="$(telnet "$host" "$port" 2>&1 < /dev/null)"
            case $output in
              (*Connected\ to\ *)
                echo "connection is successful to $host $port" >> output.txt
                ;;
              (*)
                echo "connection was refused to $host $port" >> output.txt
                ;;
             esac
        fi
        echo "---------------------------------------------" >> output.txt
    done
done < "$1"
1

Both telnet commands will attempt to read from the remains of your $1 file, whatever that may be. So your loop may get executed an unexpectedly fewer number of times.

I'm not sure what input you were expecting to provide to telnet though.

Incidentally, if you have it installed you'd be better off using netcat (sometimes known as nc). It won't solve it change the input issue but it is usually a better tool for this kind of scripted interaction.

  • I am trying to write to that output file if the telnet connection was successful (that is connected) or has been refused by remote host – RPT Dec 29 '18 at 13:57
  • this is the whole script that I have provided. On <timeout 5s telnet $host $port> i am checking if the connection times outs. Then if it does not I use <telnet $host $port >> output.txt> in the <else> to check if the connection has been refused by remote host, or connected. And I write the telnet output to the output file. But the problem is when the connection is successful, the script exits. – RPT Dec 30 '18 at 12:52
  • Also, I am not in a scenario where i can use nc – RPT Dec 30 '18 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.