Search code examples
bashtelnet

Bash Script to Automate Telnet


I'm trying to automate telnet, using this command which works great

echo -e "\x1dclose\x0d" |
  telnet abc.gc.ca 100 |
  grep Connected>/dev/null && printf "PASSED\n" || printf "FAILED\n"

But if I put it in a script, it just hangs and I have no idea why.

#!/bin/bash

SERVERS=(
   "abc.gc.ca 100"
   "defg.gc.ca 101"
   "123.gc.ca 102"
   "xyz.gc.ca 103"
)

for host in ${SERVERS[@]}; do
  echo -e "\x1dclose\x0d" |
    telnet $host |
    grep Connected > /dev/null && printf "PASSED\n" || printf "FAILED\n"
done

Solution

  • The big problem was with the array dereference: Using ${SERVERS[@]} without quotes around it was treating the port as a separate hostname.

    #!/bin/bash
    servers=(
       abc.gc.ca:100
       defg.gc.ca:101
       123.gc.ca:102
       xyz.gc.ca:103
    )
    
    for host_port in "${servers[@]}"; do
      host=${host_port%:*}   # put everything before the last : into host
      port=${host_port##*:}  # put everything after the last : into port
      if printf '\x1dclose\x0d' | telnet "$host" "$port" | grep -q Connected; then
        printf "PASSED\n"
      else
        printf "FAILED\n"
      fi
    done
    

    Other notes:

    • All-caps variable names are used for names meaningful to the shell or operating system; other names are reserved for use by applications (like your script!), so you should use lowercase names where possible.
    • foo && bar || baz is not identical to if foo; then bar; else baz; fi. For reliable code, use if -- not a short-circuiting ternary -- when you want the behavior of if.
    • Using grep -q causes grep not to emit any output, so you don't need to redirect that output.
    • echo -e is not reliable: even if the shell is 100% certain to be bash, if the shell is compiled or configured at runtime to provide an XPG-compatible echo (configuration that can be done through environment variables), echo -e may print -e on output instead of treating it as an argument.

    All that said, consider using a dedicated port-scanning tool if this is intended for any kind of real-world use case. Such tools (nmap &c) can scan a large number of hosts in parallel without needing to run a subprocess for each, much less several subprocesses as used here.