Aller au contenu principal

Lab 8.6 - Arrêter un Service

Objectifs​

À la fin de ce lab, vous serez capable de:

  • Identifier un processus qui utilise un port spécifique
  • Trouver le service systemd associé à un processus
  • Comprendre pourquoi kill seul ne suffit pas pour arrêter un service
  • Utiliser systemctl stop et disable pour arrêter définitivement un service
  • Automatiser l'identification d'un service via un script bash
  • Utiliser des méthodes avancées pour diagnostiquer les services

Prérequis​

  • Avoir un site Wiki.js en cours d'exécution
  • Avoir nginx installé
  • Ubuntu 24.04 installé
  • Accès sudo/root
  • Terminal ouvert

Installation de Nginx (si nécessaire)​

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

Contexte​

Monsieur Éric, administrateur système, tente d'installer et de lancer une application nommée Wiki.js sur un serveur Ubuntu. L'application est censée écouter sur le port 3000, mais elle ne fonctionne pas. Après plusieurs essais infructueux, Éric entreprend une série d'investigations pour identifier et résoudre le problème.


Étape 1 – Vérification du Port Utilisé​

Éric commence par vérifier si le port 3000 est déjà utilisé par un autre service. Il utilise la commande suivante :

lsof -i :3000

Résultat obtenu :

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

Un processus node est en écoute sur le port 3000. Il relève le PID : 9744.

Analyse​

  • COMMAND : node - Le processus est une application Node.js
  • PID : 9744 - Identifiant du processus
  • USER : wikijs - L'utilisateur qui exécute le processus
  • PORT : 3000 - Le port en écoute

Étape 2 – Tentative de Libération du Port avec kill​

Éric tente d'arrêter le processus manuellement :

# Tentative d'arrêt propre (SIGTERM)
kill -15 9744

# Si cela ne fonctionne pas, arrêt forcé (SIGKILL)
kill -9 9744

Vérification​

Après avoir exécuté ces commandes, Éric vérifie à nouveau :

lsof -i :3000

Résultat :

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

Conclusion : Le processus est automatiquement redémarré. Un nouveau PID (9842) apparaît. Une autre entité (probablement un service systemd) le relance.

Pourquoi le processus redémarre-t-il ?​

Le processus redémarre automatiquement car il est géré par un service systemd avec l'option Restart=always dans sa configuration. Même si vous tuez le processus, systemd le relance immédiatement.


Étape 3 – Recherche du Service systemd​

Éric suspecte un service systemd. Il cherche donc à identifier son nom exact.

Commandes Utilisées​

# Lister tous les services
systemctl list-units --type=service

# Lister les services arrêtés
systemctl list-units --type=service --state=exited

# Lister les services en cours d'exécution
systemctl list-units --type=service --state=running

# Filtrer pour trouver les services Wiki
systemctl list-units --type=service --state=running | grep -i wiki

Recherche dans les Fichiers de Service​

# Lister les fichiers de service par date de modification
ls -l --sort=time /etc/systemd/system/

# Filtrer pour trouver les services Wiki
ls -l /etc/systemd/system/ | grep wiki

Recherches Croisées​

# Chercher dans les connexions réseau
sudo ss | grep -i wiki
sudo ss | grep -i 3000

# Chercher les processus Node.js
ps aux | grep node

# Chercher les services contenant "node"
systemctl | grep node

Les Commandes Gagnantes​

Les commandes les plus efficaces pour identifier le service sont :

# Trouver les services Wiki en cours d'exécution
systemctl list-units --type=service --state=running | grep -i wiki

# Chercher les fichiers de service Wiki
ls -l /etc/systemd/system/ | grep wiki

# Voir les processus Node.js
ps aux | grep node

# Chercher les services contenant "node"
systemctl | grep node

Hypothèse confirmée : Un service appelé wikijs.service semble être responsable du processus.


Étape 4 – Vérification de la Corrélation Entre Processus, Port et Service​

Éric établit manuellement le lien entre le processus node, le port 3000 et le service en question :

Identifier le Processus sur le Port​

# Voir le processus qui écoute sur le port 3000
lsof -i :3000

# Voir tous les processus Node.js et leurs ports
sudo lsof -i -P -n | grep node

# Voir tous les processus Wiki.js
sudo lsof -i -P -n | grep wiki

Identifier le Fichier de Service​

# Chercher le fichier de service
ls -l /etc/systemd/system/ | grep wiki

Fichier identifié : wikijs.service

Vérifier le Service​

# Voir le statut du service
sudo systemctl status wikijs.service

# Voir les logs du service
sudo journalctl -u wikijs.service --no-pager --lines=50

Étape 5 – Arrêt Définitif du Service et Libération du Port​

Éric stoppe proprement le service et désactive son redémarrage automatique :

Arrêter le Service​

# Arrêter le service
sudo systemctl stop wikijs.service

Désactiver le Redémarrage Automatique​

# Désactiver le service au démarrage
sudo systemctl disable wikijs.service

Vérification Finale​

# Vérifier que le port est libéré
lsof -i :3000

# Vérifier le statut du service
sudo systemctl status wikijs.service

Résultat : Le port 3000 est maintenant libéré. Le service ne redémarrera plus automatiquement.


Étape Bonus – Scan Complet des Ports Ouverts (Facultatif)​

Pour s'assurer de l'état global du serveur, Éric utilise l'outil nmap :

# Installer nmap
sudo apt install nmap -y

# Scanner les ports ouverts sur localhost
sudo nmap -sT -O localhost

# Scanner un port spécifique
sudo nmap -p 3000 localhost

Questions de Réflexion​

  1. Pourquoi le port 3000 restait-il bloqué malgré l'usage de kill ?

    • Expliquez le rôle de systemd dans la gestion des services
    • Pourquoi kill seul ne suffit pas ?
  2. Quelle méthode permet d'identifier le nom du service qui utilise un port spécifique ?

    • Décrivez la méthode étape par étape
    • Quelles commandes sont les plus efficaces ?
  3. Quelle commande pourrait-on utiliser pour rechercher tous les services contenant le mot wiki dans leur nom ou leur description ?

    • Proposez plusieurs approches
  4. Proposez un script bash permettant d'automatiser cette investigation.

    • Le script doit identifier automatiquement le service associé à un port

Annexe 1: Méthodes Plus Avancées​

La méthode décrite (recherche manuelle à partir du port avec lsof, ps, systemctl, etc.) est fiable mais artisanale. Il existe des méthodes plus avancées et automatisées, utiles pour les environnements complexes, comme les serveurs de production ou les clusters.

1. systemd-cgls ou systemd-cgtop​

Ces outils permettent de visualiser l'arborescence des services et processus contrôlés par systemd.

# Voir l'arborescence complète
systemd-cgls

# Filtrer pour Wiki.js
systemd-cgls | grep -i wiki

# Filtrer pour PostgreSQL
systemd-cgls | grep -i postgres

# Filtrer pour Nginx
systemd-cgls | grep -i nginx

# Voir l'arborescence d'un service spécifique
systemd-cgls /system.slice/wikijs.service

# Lister les cgroups
ls /sys/fs/cgroup/system.slice/ | grep wiki

# Voir les processus Wiki
ps -ef | grep wiki

2. systemctl status Combiné à --property​

Vous pouvez interroger tous les services et demander à voir leur MainPID, puis croiser avec le port :

# Voir tous les MainPID des services
systemctl show --all --property=MainPID --no-pager

# Pour un service spécifique
systemctl show wikijs.service --property=MainPID

Puis :

# Voir le PID qui utilise le port 3000
sudo lsof -i :3000

Et vous comparez les MainPID au PID qui utilise le port.

3. Utiliser fuser pour Directement Tuer le Processus par Port​

# Tuer le processus associé au port 3000
sudo fuser -k 3000/tcp

Attention : Cette méthode ne désactive pas le service, donc il peut redémarrer. Elle est utile dans un script temporaire.

4. Avec ss --processes​

# Voir le processus qui écoute sur le port 3000
sudo ss -lptn 'sport = :3000'

Cela montre directement :

  • le port,
  • le protocole,
  • le processus,
  • et parfois le nom du service si bien configuré.

5. Utiliser netstat avec --program (si disponible)​

# Installer net-tools si nécessaire
sudo apt update
sudo apt install net-tools

# Voir le processus sur le port 3000
sudo netstat -tulnp | grep 3000

Permet d'identifier directement le programme utilisant un port. Vous pouvez croiser avec systemctl :

# Voir les détails du processus
ps -p <PID> -o pid,cmd

6. Via Journaux systemd​

Si le service a bien démarré par systemd, vous pouvez faire :

# Voir les logs du service
journalctl -u wikijs.service

# Voir les logs en temps réel
journalctl -u wikijs.service -f

# Voir les dernières lignes
journalctl -u wikijs.service --no-pager --lines=50

Cela vous montre l'historique d'exécution, y compris le port écouté.


Annexe 2: Automatiser l'Identification du Service​

Script Bash : Identifier le Service systemd Derrière un Port​

Créez un fichier recherche_service_port.sh :

#!/bin/bash

# Demande à l'utilisateur d'entrer le numéro de port
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

Utilisation​

  1. Enregistrez le script dans un fichier :
nano recherche_service_port.sh
  1. Rendez-le exécutable :
chmod +x recherche_service_port.sh
  1. Exécutez-le :
./recherche_service_port.sh

Ce que Vous Avez Appris​

  • Comment lier un port à un processus (lsof)
  • Comment remonter au service via systemctl et grep
  • Comment automatiser un diagnostic réseau en Bash
  • Comment utiliser les cgroups pour identifier les services

Résumé des Commandes Importantes​

CommandeDescription
lsof -i :3000Voir le processus qui écoute sur le port 3000
kill -15 PIDArrêt propre du processus (SIGTERM)
kill -9 PIDArrêt forcé du processus (SIGKILL)
systemctl list-units --type=service --state=runningLister les services actifs
systemctl stop wikijs.serviceArrêter un service
systemctl disable wikijs.serviceDésactiver un service au démarrage
systemctl status wikijs.serviceVoir le statut d'un service
journalctl -u wikijs.serviceVoir les logs d'un service
sudo ss -lptn 'sport = :3000'Voir le processus sur un port avec ss
sudo fuser -k 3000/tcpTuer le processus sur un port

Vérification Finale​

Vérifiez que vous avez réussi à :

  • Identifier le processus qui utilise le port 3000
  • Comprendre pourquoi kill seul ne suffit pas
  • Trouver le service systemd responsable
  • Arrêter et désactiver le service correctement
  • Vérifier que le port est libéré
  • Utiliser les méthodes avancées de diagnostic
  • Créer et utiliser le script d'automatisation
  • Répondre aux questions de réflexion

Prochaines Étapes​

  • Lab 8.1: Gestion des Services systemd (révision)
  • Lab 8.5: Instances Wiki.js Multiples (création de plusieurs instances)
  • TP 3: Examen systemd et Processus (évaluation)

Lab créé le: Décembre 2024