Как проверить, открыт ли конкретный порт на машине из сценария оболочки, и выполнить действие на его основе?

24

Я запускаю сценарий оболочки ниже на компьютере, на котором сервер приложений c ++ работает через порт 8080, и в сценарии оболочки я выполняю URL-адрес и сохраняю ответ, полученный с этого URL-адреса, в переменной DATA.

Но предположим, что если тот же сервер приложений не работает, он не сможет выполнить URL-адрес, затем он распечатает Retrying Againи спит в течение 30 секунд, а затем снова выполнит тот же URL-адрес.

#!/bin/bash

HOSTNAME=$hostname
DATA=""
RETRY=15

echo $HOSTNAME

while [ $RETRY -gt 0 ]
do
    DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat)
    if [ $? -eq 0 ]
    then
        break
    else
        echo "Retrying Again" >&2

        # restart the server

        let RETRY-=1
        sleep 30
    fi
done

echo "Server is UP"

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

Постановка задачи:-

Теперь, что я пытаюсь сделать, если сервер не работает, он будет распечатан, Retrying Againпоэтому после этого я хочу проверить, 8080открыт порт $HOSTNAMEили нет. Если нет, то это означает, что сервер не работает, поэтому я хочу перезапустить сервер, выполнив эту команду, а затем спать в течение 30 секунд, как показано выше в сценарии оболочки.

/opt/app/test/start_stop.sh start

Можно ли это сделать здесь, в моем сценарии оболочки выше?

Я запускаю этот скрипт на Ubuntu 12.04.

Дэвид
источник

Ответы:

23

Программа lsofпозволяет проверить, какие процессы используют какие ресурсы, например файлы или порты.

Чтобы показать, какие процессы прослушивают порт 8080:

lsof -Pi :8080 -sTCP:LISTEN

В вашем случае вы хотите проверить, прослушивает ли процесс 8080 - возвращаемое значение этой команды говорит вам об этом. Это также печатает pid процесса.

lsof -Pi :8080 -sTCP:LISTEN -t

Если вам нужен только тест без вывода, перенаправьте его на /dev/null:

if lsof -Pi :8080 -sTCP:LISTEN -t >/dev/null ; then
    echo "running"
else
    echo "not running"
fi


Если вы используете несколько имен хостов с несколькими IP-адресами локально, укажите имя хоста тоже как
lsof -Pi @someLocalName:8080 -sTCP:LISTEN

Volker Siegel
источник
Спасибо Фолькер. Я попробовал это, lsof -i :8080 -sTCP:LISTENи я ничего не получаю на консоли, но если я пытаюсь это сделать, netstat -tulpn | grep :8080то я получаю свой процесс, который работает на порту 8080, почему это так?
Дэвид
Какой выход netstat -tulpn | grep :8080?
Фолькер Сигел
Это то, что я получаю с помощью netstat - david@machineA:/home/david$ netstat -tulpn | grep :8080 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 27530/test_server
Дэвид
Странно, если я попробую похожие вещи, это работает. Может быть связано с IPv6 ... хммм.
Фолькер Сигел
Это перечислено с lsof -iTCP -sTCP:LISTEN | grep 8080?
Фолькер Сигел
16

Самый простой способ в Bash. Проверьте, открыт ли ваш порт.

(echo >/dev/tcp/localhost/8080) &>/dev/null && echo "TCP port 8080 open" || echo "TCP port 8080 close"

Замените эхо на то, что вы хотите.

Или вы можете использовать nc.

nc -vz 127.0.0.1 8080

Возвращает:

Соединение с портом 127.0.0.1 8080 [tcp / *] успешно

RJ
источник
1
ncотличное решение для моего случая использования; спасибо за предложение
Джон
1

Разработка ответа RJ, примечания ncтакже полезны ... Не только ncполезны для быстрого запроса командной строки

 nc -z -v -w5 127.0.0.1 8080
localhost [127.0.0.1] 8080 (http-alt) : Connection refused

но его можно использовать без -v, если удобочитаемость не та, к которой вы стремитесь - например, для использования в скрипте (код выхода укажет, открыт порт или закрыт).

 nc -z 127.0.0.1 8080

 echo $?             
1
thomp45793
источник