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é
killpor sí solo no es suficiente para detener un servicio - Utilizar
systemctl stopydisablepara 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
-
¿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é
killpor sí solo no es suficiente?
-
¿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?
-
¿Qué comando podría usarse para buscar todos los servicios que contienen la palabra
wikien su nombre o descripción?- Proponga varios enfoques
-
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
- Guarde el script en un archivo:
nano recherche_service_port.sh
- Hágalo ejecutable:
chmod +x recherche_service_port.sh
- 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
systemctlygrep - Cómo automatizar un diagnóstico de red en Bash
- Cómo utilizar los cgroups para identificar servicios
Resumen de Comandos Importantes
| Comando | Descripción |
|---|---|
lsof -i :3000 | Ver el proceso que escucha en el puerto 3000 |
kill -15 PID | Parada limpia del proceso (SIGTERM) |
kill -9 PID | Parada forzada del proceso (SIGKILL) |
systemctl list-units --type=service --state=running | Listar los servicios activos |
systemctl stop wikijs.service | Detener un servicio |
systemctl disable wikijs.service | Desactivar un servicio al inicio |
systemctl status wikijs.service | Ver el estado de un servicio |
journalctl -u wikijs.service | Ver los logs de un servicio |
sudo ss -lptn 'sport = :3000' | Ver el proceso en un puerto con ss |
sudo fuser -k 3000/tcp | Matar el proceso en un puerto |
Verificación Final
Verifique que ha logrado:
- Identificar el proceso que utiliza el puerto 3000
- Comprender por qué
killpor 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