Проверьте, открыт ли удаленный порт TCP из сценария оболочки - PullRequest
279 голосов
/ 07 февраля 2011

Я ищу быстрый и простой способ для правильного тестирования, если данный порт TCP открыт на удаленном сервере, внутри скрипта Shell.

Мне удалось сделать это с помощью команды telnet, и она прекрасно работает при открытии порта, но, похоже, не истекает время ожидания, когда его нет, и просто зависает там ...

Вот пример:

l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
if [ "$?" -ne 0 ]; then
  echo "Connection to $SERVER on port $PORT failed"
  exit 1
else
  echo "Connection to $SERVER on port $PORT succeeded"
  exit 0
fi

Мне нужен либо лучший способ, либо способ принудительно установить время ожидания telnet, если он не подключается менее чем за 8 секунд, например, и вернуть что-то, что я могу поймать в Shell (код возврата или строку в stdout).

Мне известен метод Perl, который использует модуль IO :: Socket :: INET и написал успешный скрипт, который тестирует порт, но хотел бы по возможности избегать использования Perl.

Примечание: это то, что мой сервер работает (откуда я должен запустить это)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc

Ответы [ 16 ]

4 голосов
/ 07 апреля 2017

Если вы хотите использовать nc, но у вас нет версии, которая поддерживает -z, попробуйте использовать --send-only:

nc --send-only <IP> <PORT> </dev/null

и с таймаутом:

nc -w 1 --send-only <IP> <PORT> </dev/null

и без поиска DNS, если это IP:

nc -n -w 1 --send-only <IP> <PORT> </dev/null

Возвращает коды как -z в зависимости от того, может ли он подключиться или нет.

1 голос
/ 30 октября 2015

Мне нужен был короткий скрипт, который запускался в cron и не выводил. Я решаю свои проблемы, используя nmap

open=`nmap -p $PORT $SERVER | grep "$PORT" | grep open`
if [ -z "$open" ]; then
  echo "Connection to $SERVER on port $PORT failed"
  exit 1
else
  echo "Connection to $SERVER on port $PORT succeeded"
  exit 0
fi

Для его запуска Вам следует установить nmap, поскольку он не является установленным по умолчанию пакетом.

1 голос
/ 23 марта 2011

Полагаю, что уже слишком поздно для ответа, и он может быть не очень хорошим, но вот, пожалуйста ...

Как насчет того, чтобы поместить его в цикл while с таймером? Я скорее Perl, чем Solaris, но в зависимости от используемой вами оболочки, вы сможете сделать что-то вроде:

TIME = 'date +%s' + 15
while TIME != `date +%s'
do whatever

А затем просто добавьте флаг в цикл while, чтобы, если время ожидания истекло до завершения, вы могли указать в качестве причины сбоя время ожидания.

Я подозреваю, что у telnet также есть переключатель тайм-аута, но я думаю, что вышеприведенное сработает.

0 голосов
/ 07 марта 2018

Опираясь на ответ с наибольшим количеством голосов, здесь есть функция ожидания открытия двух портов, а также время ожидания.Обратите внимание на два порта, которые должны быть открыты, 8890 и 1111, а также max_attempts (1 в секунду).

function wait_for_server_to_boot()
{
    echo "Waiting for server to boot up..."
    attempts=0
    max_attempts=30
    while ( nc 127.0.0.1 8890 < /dev/null || nc 127.0.0.1 1111 < /dev/null )  && [[ $attempts < $max_attempts ]] ; do
        attempts=$((attempts+1))
        sleep 1;
        echo "waiting... (${attempts}/${max_attempts})"
    done
}
0 голосов
/ 19 апреля 2016

nmap-ncat для проверки локального порта, который еще не используется


availabletobindon() {
  port="$1"
  nc -w 2 -i 1 localhost "$port" 2>&1 | grep -v -q 'Idle timeout expired'
  return "$?"
}
0 голосов
/ 19 февраля 2016

Это использует telnet за кулисами, и, кажется, отлично работает на Mac / Linux. Он не использует netcat из-за различий между версиями в linux / mac, и это работает при установке Mac по умолчанию.

Пример:

$ is_port_open.sh 80 google.com
OPEN

$ is_port_open.sh 8080 google.com
CLOSED

is_port_open.sh

PORT=$1
HOST=$2
TIMEOUT_IN_SEC=${3:-1}
VALUE_IF_OPEN=${4:-"OPEN"}
VALUE_IF_CLOSED=${5:-"CLOSED"}

function eztern()
{
  if [ "$1" == "$2" ]
  then
    echo $3
  else
    echo $4
  fi
}

# cross platform timeout util to support mac mostly
# https://gist.github.com/jaytaylor/6527607
function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }

function testPort()
{
  OPTS=""

  # find out if port is open using telnet
  # by saving telnet output to temporary file
  # and looking for "Escape character" response
  # from telnet
  FILENAME="/tmp/__port_check_$(uuidgen)"
  RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1)
  rm -f $FILENAME;
  SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED")

  echo "$SUCCESS"
}

testPort 
...