L'article qui suit est ma traduction d'un article du blog de Lennart Poettering, l'auteur de systemd. J'ai réalisé la traduction pour en faire une dépêche sur linuxfr. Je la stocke également ici au cas où et pour me souvenir de ce travail. Je publierai également les autres traductions dans des articles de blog distincts.

Voici un lien vers l'article original.

Tuer des services

Tuer un service, c'est simple non ? Ou pas ?

Bien entendu, tant que votre démon est constitué d'un seul processus, c'est généralement vrai. Vous tapez killall rsyslogd et le démon syslog n'est plus. Néanmoins, c'est un plus sale de faire ainsi étant donné que cela tuera tous les démons qui s'appellent ainsi, incluant ceux qu'un utilisateur malchanceux aurait nommé ainsi par accident. Une version plus correcte aurait été de lire le fichier .pid, c'est-à-dire kill \cat /var/run/syslogd.pid``. Cela nous avance un peu mais néanmoins est-ce vraiment ce que nous souhaitons ?

Dans la majorité des cas en fait, cela ne se passera pas ainsi. Considérons des services tels qu'Apache, crond ou atd qui, dans leur fonctionnement courant, engendrent des processus fils. Généralement, il s'agit de processus fils configurables par l'utilisateur tels que des tâches cron ou at ou encore des scripts CGI, y compris des serveurs d'application complets. Si vous tuez le processus principal Apache/crond/atd cela pourra ou non tuer l'ensemble des processus fils également et c'est à chacun de ces processus de savoir s'ils veulent continuer à tourner ou s'ils doivent s'arrêter. Dans la pratique, cela signifie que mettre fin à Apache pourrait très bien laisser ces scripts CGI fonctionner, réaffectés comme enfants du processus init, ce qui est difficile à tracer.

Systemd vient à la rescousse: avec systemctl kill, vous pouvez facilement envoyer un signal à tous les processus d'un service. Par exemple:

# systemctl kill crond.service

Cela assurera que SIGTERM est envoyé à tous les processus du service crond, pas uniquement au processus principal. Bien entendu, vous pouvez également envoyer un signal différent si vous le souhaitez. Par exemple, si vous êtes mal luné, vous aurez peut-être envie d'envoyer SIGKILL de cette manière:

# systemctl kill -s SIGKILL crond.service

Et voilà, le service sera complètement stoppé brutalement, peu importe combien de fois il a été forké ou qu'il essaye d'échapper à la supervision par un fork double ou par un bombardement de forks.

Parfois, vous avez juste besoin d'envoyer un signal spécifique au processus principal d'un service, par exemple par ce que vous voulez déclencher un rechargement du service par le signal SIGHUP. A la place de retrouver le fichier de PID, voici un moyen plus simple d'y parvenir:

# systemctl kill -s HUP --kill-who=main crond.service

Encore une fois, qu'y-a-t-il de nouveau et de fantaisiste dans la manière de tuer des processus avec systemd ? Eh bien, pour la première fois sous Linux, nous pouvons le faire proprement. Les précédentes solutions dépendaient toutes de la bonne coopération des démons pour qu'ils arrêtent tous les processus qu'ils avaient engendrés lorsqu'ils devaient se terminer. Néanmoins si vous voulez employer SIGTERM ou SIGKILL, vous le faîtes parce qu'ils ne coopèrent pas correctement avec vous.

Qu'est-ce-que ça a à voir avec systemctl stop ? kill envoie directement un signal à chacun des processus situés dans le groupe; stop, pour sa part, utilise le moyen officiellement configuré pour arrêter le service, c'est-à-dire qu'il lance la commande configurée avec ExecStop= dans le fichier de service. En général, stop devrait être suffisant. kill reste la méthode forte à utiliser dans les cas ou vous ne voulez pas utiliser la commande shutdown d'un service ou bien lorsque le service est complètement en carafe.

(C'est à vous bien entendu d'indiquer ou non les noms de signaux avec le préfixe SIG avec ou sans l'option -s. Les deux fonctionnent.)

C'est assez surprenant d'être parvenu jusqu'ici sous Linux sans disposer d'un moyen efficace de tuer des services. Systemd permet pour la première fois de le faire proprement.