15

I am trying to create a script to test whether it is possible to login via telnet. I do not want to really log in; therefore, expect is not needed. I just want to see if I am able to get a login prompt. This is being done from a Linux system so I have been trying to use nc:

nc 192.168.10.5 23 -w 1 | grep -q login 
if [ $? -eq 1 ]
then
    echo "console is down"
fi

The problem is that this is causing my console to lock up. It seems like the -w is not really dropping the connection.

I also tried using telnet but I am not able to break the connection from within the script. Trying

\echo "\035" | telnet 192.168.10.5

breaks before I get a login prompt.

rleon
  • 151
  • 1
  • 1
  • 3
  • Possible duplicate of http://superuser.com/questions/621870/test-if-a-port-on-a-remote-system-is-reachable-without-telnet – vschum Sep 05 '14 at 01:35

4 Answers4

19

Bash provides pseudo devices that you're likely familiar with such as /dev/null. However there are other devices such as /dev/tcp and /dev/udp for testing network connections, which you may use from within Bash scripts too.

excerpt from Bash's man page

Bash handles several filenames specially when they are used in redirections, as described in the following table:

          /dev/fd/fd
                 If fd is a valid integer, file descriptor fd is duplicated.
          /dev/stdin
                 File descriptor 0 is duplicated.
          /dev/stdout
                 File descriptor 1 is duplicated.
          /dev/stderr
                 File descriptor 2 is duplicated.
          /dev/tcp/host/port
                If  host  is a valid hostname or Internet address, and port 
                is an integer port number or service name, bash attempts to 
                open a TCP connection to the corresponding socket.
          /dev/udp/host/port
                If host is a valid hostname or Internet address, and port 
                is an integer port number or service name, bash attempts to 
                open a  UDP  connection to the corresponding socket.

Example

Here's I'm testing the connection to a host in my domain named skinner and seeing if I can connect to its port 22.

NOTE: Port 22 is for SSH, for telnet use port 23.

$ echo > /dev/tcp/skinner/22 && echo "it's up" || echo "it's down"
it's up

Great so let's try a non-port:

$ echo > /dev/tcp/skinner/223 && echo "it's up" || echo "it's down"
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused
it's down

Well that works, but it's awfully ugly output. Not to worry. You can run the echo > /dev/tcp/... in a subshell and redirect all the output to /dev/null to clean it up a bit. Here's the pattern you can use within your shell scripts:

$ (echo > /dev/tcp/skinner/22) > /dev/null 2>&1 \
    && echo "it's up" || echo "it's down"
it's up

$ (echo > /dev/tcp/skinner/223) > /dev/null 2>&1 \
    && echo "it's up" || echo "it's down"
it's down
slm
  • 363,520
  • 117
  • 767
  • 871
  • If you are specifically wanting to test `telnet`, then that by default runs on port 23, so where slm has used 22 and 223, use 23. – Warwick Sep 05 '14 at 05:03
  • @Warwick - thanks, I've added that as a note in the examples section. – slm Sep 05 '14 at 10:40
  • @sim thanks for the comment. I saw this before but I was not able to get it to work with this. My issue is that I need to be able to grep or test for a login prompt. In this case the console is locked up and there is no login prompt. `# telnet 192.168.10.5 Trying 192.168.10.5... Connected to 192.168.10.5 (192.168.10.5). Escape character is '^]'. Connection closed by foreign host.` – rleon Sep 05 '14 at 14:25
  • `# cat < /dev/tcp/192.168.10.12/23 ` gives me a login prompt but i am not able to break out of it. – rleon Sep 05 '14 at 14:28
  • @rleon - You'll likely need to do something like this: `exec 3 afile; exec 3<&-`. The `^]` is a Ctrl+V Ctrl+]. – slm Sep 05 '14 at 14:51
  • 1
    wow .. allot of redirection there. `# cat afile ^]` after running that it is just echoing the break to `afile`. Still playing with it but i feel i am almost there. – rleon Sep 05 '14 at 17:52
9

You're on the right track using nc, but if you really want to just test whether you can establish the connection, use nc's -z switch:

#!/bin/bash
REMOTEHOST=10.11.12.13
REMOTEPORT=1234
TIMEOUT=1

if nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT; then
    echo "I was able to connect to ${REMOTEHOST}:${REMOTEPORT}"
else
    echo "Connection to ${REMOTEHOST}:${REMOTEPORT} failed. Exit code from Netcat was ($?)."
fi
StackzOfZtuff
  • 297
  • 2
  • 9
DopeGhoti
  • 73,792
  • 8
  • 97
  • 133
5

I know the answer is a bit late, but I was looking how to do this and using nc was not an option for security reasons, so here it is if it can help someone.

What was missing in your initial echo was the -e switch:

   -e     enable interpretation of backslash escapes
   -E     disable interpretation of backslash escapes (default)

And a newline + the quit command to quit telnet after disconnecting. As such:

echo -e '\035\nquit' | telnet 10.0.0.1 23 && echo "success" || echo "failed"

Obviously the same will work if you use a block style if statement and evaluate $? as you did initially:

echo -e '\035\nquit' | telnet 10.0.0.1 23
if [ $? -eq 1 ]
then
  echo "Console is down."
fi

While we're at it, as far as nc goes, it depends on what flavor of nc you have (gnu ncat vs nmap-ncat). Gnu will have the -z switch:

  -z                         Zero-I/O mode, report connection status only
nc -z 10.0.0.1 23
# (evaluate $? here)

while the other won't and you'll have to pipe an empty line to your nc to not be stuck:

echo | nc 10.0.0.1 23
# (evaluate $? here)
Alex B
  • 51
  • 1
  • 1
1

run nc -z 192.168.10.5 23 in the command prompt or create a bash script to run this command.

It returns the statement below if the connection is successful.

Connection to 192.168.10.5 23 port [tcp/*] succeeded!

Ruban Savvy
  • 8,409
  • 8
  • 29
  • 43