Saltar al contenido principal

Lab 8.6 - Detener un Servicio

Objetivos​

Al final de este laboratorio, usted será capaz de:

  • Identificar un proceso que utiliza un puerto específico
  • Encontrar el servicio systemd asociado a un proceso
  • Comprender por qué kill por sí solo no es suficiente para detener un servicio
  • Utilizar systemctl stop y disable para detener definitivamente un servicio
  • Automatizar la identificación de un servicio mediante un script bash
  • Utilizar métodos avanzados para diagnosticar servicios

Prerrequisitos​

  • Tener un sitio Wiki.js en funcionamiento
  • Tener nginx instalado
  • Ubuntu 24.04 instalado
  • Acceso sudo/root
  • Terminal abierto

Instalación de Nginx (si es necesario)​

sudo apt update
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx

Contexto​

El señor Éric, administrador de sistemas, intenta instalar y lanzar una aplicación llamada Wiki.js en un servidor Ubuntu. La aplicación debería escuchar en el puerto 3000, pero no funciona. Tras varios intentos fallidos, Éric inicia una serie de investigaciones para identificar y resolver el problema.


Paso 1 – Verificación del Puerto Utilizado​

Éric comienza verificando si el puerto 3000 ya está siendo utilizado por otro servicio. Utiliza el siguiente comando:

lsof -i :3000

Resultado obtenido:

COMMAND   PID   USER     FD   TYPE DEVICE SIZE/OFF NODE NAME
node 9744 wikijs 22u IPv4 59242 0t0 TCP *:3000 (LISTEN)

Un proceso node está escuchando en el puerto 3000. Él toma nota del PID: 9744.

Análisis​

  • COMMAND: node - El proceso es una aplicación Node.js
  • PID: 9744 - Identificador del proceso
  • USER: wikijs - El usuario que ejecuta el proceso
  • PORT: 3000 - El puerto en escucha

Paso 2 – Intento de Liberar el Puerto con kill​

Éric intenta detener el proceso manualmente:

# Intento de parada limpia (SIGTERM)
kill -15 9744

# Si esto no funciona, parada forzada (SIGKILL)
kill -9 9744

Verificación​

Después de ejecutar estos comandos, Éric verifica nuevamente:

lsof -i :3000

Resultado:

COMMAND   PID   USER     FD   TYPE DEVICE SIZE/OFF NODE NAME
node 9842 wikijs 22u IPv4 59243 0t0 TCP *:3000 (LISTEN)

Conclusión: El proceso se reinicia automáticamente. Aparece un nuevo PID (9842). Otra entidad (probablemente un servicio systemd) lo relanza.

¿Por qué el proceso se reinicia?​

El proceso se reinicia automáticamente porque está gestionado por un servicio systemd con la opción Restart=always en su configuración. Incluso si usted mata el proceso, systemd lo relanza inmediatamente.


Paso 3 – Búsqueda del Servicio systemd​

Éric sospecha de un servicio systemd. Por lo tanto, busca identificar su nombre exacto.

Comandos Utilizados​

# Listar todos los servicios
systemctl list-units --type=service

# Listar los servicios detenidos
systemctl list-units --type=service --state=exited

# Listar los servicios en ejecución
systemctl list-units --type=service --state=running

# Filtrar para encontrar los servicios Wiki
systemctl list-units --type=service --state=running | grep -i wiki

Búsqueda en los Archivos de Servicio​

# Listar los archivos de servicio por fecha de modificación
ls -l --sort=time /etc/systemd/system/

# Filtrar para encontrar los servicios Wiki
ls -l /etc/systemd/system/ | grep wiki

Búsquedas Cruzadas​

# Buscar en las conexiones de red
sudo ss | grep -i wiki
sudo ss | grep -i 3000

# Buscar los procesos Node.js
ps aux | grep node

# Buscar los servicios que contienen "node"
systemctl | grep node

Los Comandos Ganadores​

Los comandos más eficaces para identificar el servicio son:

# Encontrar los servicios Wiki en ejecución
systemctl list-units --type=service --state=running | grep -i wiki

# Buscar los archivos de servicio Wiki
ls -l /etc/systemd/system/ | grep wiki

# Ver los procesos Node.js
ps aux | grep node

# Buscar los servicios que contienen "node"
systemctl | grep node

Hipótesis confirmada: Un servicio llamado wikijs.service parece ser responsable del proceso.


Paso 4 – Verificación de la Correlación Entre Proceso, Puerto y Servicio​

Éric establece manualmente el vínculo entre el proceso node, el puerto 3000 y el servicio en cuestión:

Identificar el Proceso en el Puerto​

# Ver el proceso que escucha en el puerto 3000
lsof -i :3000

# Ver todos los procesos Node.js y sus puertos
sudo lsof -i -P -n | grep node

# Ver todos los procesos Wiki.js
sudo lsof -i -P -n | grep wiki

Identificar el Archivo de Servicio​

# Buscar el archivo de servicio
ls -l /etc/systemd/system/ | grep wiki

Archivo identificado: wikijs.service

Verificar el Servicio​

# Ver el estado del servicio
sudo systemctl status wikijs.service

# Ver los logs del servicio
sudo journalctl -u wikijs.service --no-pager --lines=50

Paso 5 – Detención Definitiva del Servicio y Liberación del Puerto​

Éric detiene correctamente el servicio y desactiva su reinicio automático:

Detener el Servicio​

# Detener el servicio
sudo systemctl stop wikijs.service

Desactivar el Reinicio Automático​

# Desactivar el servicio al inicio
sudo systemctl disable wikijs.service

Verificación Final​

# Verificar que el puerto está liberado
lsof -i :3000

# Verificar el estado del servicio
sudo systemctl status wikijs.service

Resultado: El puerto 3000 ahora está liberado. El servicio ya no se reiniciará automáticamente.


Paso Extra – Escaneo Completo de Puertos Abiertos (Opcional)​

Para asegurarse del estado global del servidor, Éric utiliza la herramienta nmap:

# Instalar nmap
sudo apt install nmap -y

# Escanear los puertos abiertos en localhost
sudo nmap -sT -O localhost

# Escanear un puerto específico
sudo nmap -p 3000 localhost

Preguntas de Reflexión​

  1. ¿Por qué el puerto 3000 seguía bloqueado a pesar del uso de kill?

    • Explique el rol de systemd en la gestión de servicios
    • ¿Por qué kill por sí solo no es suficiente?
  2. ¿Qué método permite identificar el nombre del servicio que utiliza un puerto específico?

    • Describa el método paso a paso
    • ¿Qué comandos son los más eficaces?
  3. ¿Qué comando podría usarse para buscar todos los servicios que contienen la palabra wiki en su nombre o descripción?

    • Proponga varios enfoques
  4. Proponga un script bash que permita automatizar esta investigación.

    • El script debe identificar automáticamente el servicio asociado a un puerto

Anexo 1: Métodos Más Avanzados​

El método descrito (búsqueda manual a partir del puerto con lsof, ps, systemctl, etc.) es fiable pero artesanal. Existen métodos más avanzados y automatizados, útiles para entornos complejos, como servidores de producción o clústeres.

1. systemd-cgls o systemd-cgtop​

Estas herramientas permiten visualizar el árbol de servicios y procesos controlados por systemd.

# Ver el árbol completo
systemd-cgls

# Filtrar para Wiki.js
systemd-cgls | grep -i wiki

# Filtrar para PostgreSQL
systemd-cgls | grep -i postgres

# Filtrar para Nginx
systemd-cgls | grep -i nginx

# Ver el árbol de un servicio específico
systemd-cgls /system.slice/wikijs.service

# Listar los cgroups
ls /sys/fs/cgroup/system.slice/ | grep wiki

# Ver los procesos Wiki
ps -ef | grep wiki

2. systemctl status Combinado con --property​

Puede consultar todos los servicios y pedir ver su MainPID, luego cruzar con el puerto:

# Ver todos los MainPID de los servicios
systemctl show --all --property=MainPID --no-pager

# Para un servicio específico
systemctl show wikijs.service --property=MainPID

Luego:

# Ver el PID que utiliza el puerto 3000
sudo lsof -i :3000

Y compara los MainPID con el PID que utiliza el puerto.

3. Usar fuser para Matar Directamente el Proceso por Puerto​

# Matar el proceso asociado al puerto 3000
sudo fuser -k 3000/tcp

Atención: Este método no desactiva el servicio, por lo que puede reiniciarse. Es útil en un script temporal.

4. Con ss --processes​

# Ver el proceso que escucha en el puerto 3000
sudo ss -lptn 'sport = :3000'

Esto muestra directamente:

  • el puerto,
  • el protocolo,
  • el proceso,
  • y a veces el nombre del servicio si está bien configurado.

5. Usar netstat con --program (si está disponible)​

# Instalar net-tools si es necesario
sudo apt update
sudo apt install net-tools

# Ver el proceso en el puerto 3000
sudo netstat -tulnp | grep 3000

Permite identificar directamente el programa que utiliza un puerto. Puede cruzar con systemctl:

# Ver los detalles del proceso
ps -p <PID> -o pid,cmd

6. Vía Registros systemd​

Si el servicio ha sido iniciado por systemd, puede hacer:

# Ver los logs del servicio
journalctl -u wikijs.service

# Ver los logs en tiempo real
journalctl -u wikijs.service -f

# Ver las últimas líneas
journalctl -u wikijs.service --no-pager --lines=50

Esto le muestra el historial de ejecución, incluido el puerto en escucha.


Anexo 2: Automatizar la Identificación del Servicio​

Script Bash: Identificar el Servicio systemd Detrás de un Puerto​

Cree un archivo recherche_service_port.sh:

#!/bin/bash

# Demanda al usuario que ingrese el número de puerto
read -p "Entrez le numéro de port (ex: 3000) : " PORT

# Étape 1 : Obtenir le PID du processus qui écoute sur ce port
PID=$(sudo lsof -i :$PORT -sTCP:LISTEN -t)

# Vérification si un PID a été trouvé
if [ -z "$PID" ]; then
echo "Aucun processus ne semble écouter sur le port $PORT."
exit 1
fi

echo "Processus détecté sur le port $PORT : PID = $PID"

# Étape 2 : Afficher les informations sur le processus
echo "Commande liée à ce PID :"
ps -p $PID -o pid,cmd

# Étape 3 : Chercher le service systemd auquel appartient ce PID
echo ""
echo "Recherche du service systemd correspondant..."

# Méthode 1 : Chercher via systemctl
SERVICE=$(systemctl | grep $PID | awk '{print $1}')

# Méthode 2 : Si pas trouvé, chercher dans les fichiers de service
if [ -z "$SERVICE" ]; then
echo "Recherche dans les fichiers de service..."
# Chercher le PID dans les cgroups
for service_file in /etc/systemd/system/*.service; do
if [ -f "$service_file" ]; then
service_name=$(basename "$service_file")
# Vérifier si le service est actif et correspond au PID
main_pid=$(systemctl show "$service_name" --property=MainPID --value 2>/dev/null)
if [ "$main_pid" = "$PID" ]; then
SERVICE="$service_name"
break
fi
fi
done
fi

# Méthode 3 : Chercher via cgroup
if [ -z "$SERVICE" ]; then
cgroup=$(cat /proc/$PID/cgroup 2>/dev/null | grep system.slice | cut -d: -f3)
if [ -n "$cgroup" ]; then
SERVICE=$(basename "$cgroup" .service)
fi
fi

if [ -z "$SERVICE" ]; then
echo "Aucun service systemd trouvé automatiquement pour le PID $PID."
echo "Vérification manuelle possible avec :"
echo " systemctl status <nom_du_service>"
echo "ou recherche dans /etc/systemd/system/"
echo ""
echo "Commandes utiles :"
echo " ps -p $PID -o pid,cmd"
echo " systemctl list-units --type=service | grep -i wiki"
echo " ls -l /etc/systemd/system/ | grep wiki"
else
echo "Service systemd détecté : $SERVICE"
echo ""
echo "Statut du service :"
systemctl status $SERVICE --no-pager -l
echo ""
echo "Pour arrêter le service :"
echo " sudo systemctl stop $SERVICE"
echo " sudo systemctl disable $SERVICE"
fi

Uso​

  1. Guarde el script en un archivo:
nano recherche_service_port.sh
  1. Hágalo ejecutable:
chmod +x recherche_service_port.sh
  1. Ejecute el script:
./recherche_service_port.sh

Lo que Ha Aprendido​

  • Cómo vincular un puerto a un proceso (lsof)
  • Cómo rastrear hasta el servicio mediante systemctl y grep
  • Cómo automatizar un diagnóstico de red en Bash
  • Cómo utilizar los cgroups para identificar servicios

Resumen de Comandos Importantes​

ComandoDescripción
lsof -i :3000Ver el proceso que escucha en el puerto 3000
kill -15 PIDParada limpia del proceso (SIGTERM)
kill -9 PIDParada forzada del proceso (SIGKILL)
systemctl list-units --type=service --state=runningListar los servicios activos
systemctl stop wikijs.serviceDetener un servicio
systemctl disable wikijs.serviceDesactivar un servicio al inicio
systemctl status wikijs.serviceVer el estado de un servicio
journalctl -u wikijs.serviceVer los logs de un servicio
sudo ss -lptn 'sport = :3000'Ver el proceso en un puerto con ss
sudo fuser -k 3000/tcpMatar el proceso en un puerto

Verificación Final​

Verifique que ha logrado:

  • Identificar el proceso que utiliza el puerto 3000
  • Comprender por qué kill por sí solo no es suficiente
  • Encontrar el servicio systemd responsable
  • Detener y desactivar correctamente el servicio
  • Verificar que el puerto está liberado
  • Utilizar los métodos avanzados de diagnóstico
  • Crear y utilizar el script de automatización
  • Responder a las preguntas de reflexión

Próximos Pasos​

  • Lab 8.1: Gestión de Servicios systemd (revisión)
  • Lab 8.5: Instancias Múltiples de Wiki.js (creación de varias instancias)
  • TP 3: Examen de systemd y Procesos (evaluación)

Lab creado el: Diciembre 2024