¿Cómo verificar si un puerto en particular está abierto en una máquina desde un script de shell y realizar una acción basada en eso?

24

Estoy ejecutando mi script de shell a continuación en una máquina en la que se ejecuta el servidor de aplicaciones c ++ en el puerto 8080 y en el script de shell estoy ejecutando una URL y almacena la respuesta proveniente de esa URL en la variable DATA.

Pero suponga que si el mismo servidor de aplicaciones está inactivo, no podrá ejecutar la URL y luego se imprimirá Retrying Againy dormirá durante 30 segundos y luego ejecutará la misma URL nuevamente.

#!/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"

Y aquí HOSTNAMEestá el nombre de host local del servidor en el que estoy ejecutando mi script de shell anterior.

Planteamiento del problema:-

Ahora lo que estoy tratando de hacer es, si el servidor está inactivo, se imprimirá, Retrying Againasí que después de eso quiero verificar si el puerto 8080está abierto $HOSTNAMEo no. Si no, significa que el servidor está inactivo, por lo que quiero reiniciar el servidor ejecutando este comando y luego dormir durante 30 segundos como se muestra arriba en el script de shell.

/opt/app/test/start_stop.sh start

¿Es esto posible hacer aquí en mi script de shell anterior?

Estoy ejecutando este script de shell en Ubuntu 12.04.

david
fuente

Respuestas:

23

El programa le lsofpermite verificar qué procesos están utilizando qué recursos, como archivos o puertos.

Para mostrar qué procesos están escuchando en el puerto 8080:

lsof -Pi :8080 -sTCP:LISTEN

En su caso, desea probar si un proceso está escuchando en 8080: el valor de retorno de este comando le dice exactamente eso. También imprime el pid del proceso.

lsof -Pi :8080 -sTCP:LISTEN -t

Si solo necesita la prueba, sin salida, rediríjala a /dev/null:

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


Si usa varios nombres de host con múltiples direcciones IP localmente, especifique el nombre de host también como
lsof -Pi @someLocalName:8080 -sTCP:LISTEN

Volker Siegel
fuente
Gracias volker. Intenté esto lsof -i :8080 -sTCP:LISTENy no obtengo nada en la consola, pero si lo intento netstat -tulpn | grep :8080, obtengo mi proceso que se ejecuta en el puerto 8080 ¿por qué es así?
David
¿Cuál es la salida de netstat -tulpn | grep :8080?
Volker Siegel
Esto es lo que obtengo con 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
david
Extraño, si intento cosas similares funciona. Podría estar relacionado con IPv6 ... hmmm.
Volker Siegel
¿Está listado con lsof -iTCP -sTCP:LISTEN | grep 8080?
Volker Siegel
16

La manera más simple en bash. Prueba si tu puerto está abierto.

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

Reemplace el eco con lo que quiere.

O puedes usar nc.

nc -vz 127.0.0.1 8080

Devoluciones:

Conexión al puerto 127.0.0.1 8080 [tcp / *] exitosa

RJ
fuente
1
nces una gran solución para mi caso de uso; gracias por sugerir
Jon
1

Elaborar sobre la respuesta de RJ, que notas nctambién es útil ... No solo es ncútil para consultas rápidas en la línea de comandos

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

pero se puede usar sin -v si lo de legibilidad humana no es lo que está buscando, por ejemplo, para usar en un script (el código de salida indicará si el puerto está abierto o cerrado).

 nc -z 127.0.0.1 8080

 echo $?             
1
thomp45793
fuente