Gérer les services avec Systemd

Il est aussi possible de personnaliser le démarrage (runlevel) des services avec le programme ci-dessous :

apt-get install sysv-rc-conf
sysv-rc-conf

Surveiller l'état des services

  • Visualiser l'état général de la machine :
systemctl status
  • Lister l'état des services (démarré/stoppé) :
systemctl list-units [--type=target]
systemctl list-unit-files
systemctl --user list-utils # Quand on est avec un compte utilisateur
  • Lister les dépendances d'un service :
systemctl list-dependencies $SERVICE
  • [Visualiser|Démarrer|Redémarrer|Stopper] l'état d'un service :
systemctl [status|start|restart|stop] ssh.service
  • [Démarrer|Stopper] le service au boot :
systemctl [enable|disable] ssh.service
  • Liste des services à l'état FAIL :
systemctl --failed
  • Désactiver le lancement d'une unité :
udo systemctl mask $SERVICE
  • Activer le lancement d'une unité :
udo systemctl unmask $SERVICE
  • Suivre les sorties des services :
journalctl -f
  • suivre la sortie d'un processus ou programme :
journalctl _PID=100
journalctl /usr/sbin/sshd
  • Afficher le service ayant le plus de processus en cours :
systemd-cgtop -t
  • Retrouver des messages entre deux dates :
journalctl --since "2016-02-10 21:00:00" --until "2016-02-10 22:00:00"

Analyse du boot

  • Récupérer le temps du boot :
 systemd-analyze time

On peut obtenir une réponse tel que :

Startup finished in 3.289s (kernel) + 16.857s (userspace) = 20.146s
  • Récupérer le temps de boot sous forme d'image SVG :
 systemd-analyze plot > output.svg
  • Analyser le chemin critique du boot :
systemd-analyze critical-chain

Créer un service

Voici notre script qui va simuler un service qui tournera en tache de fond. Ici il aura juste pour fonction d'écrire un fichier tout les 10 seconde dans le dossier /tmp/.

nano /usr/local/sbin/mon-service
mon-service
#!/usr/bin/ruby
 
Signal.trap(36) do
  puts "<1>Service tuée via SIGRTMIN+2 (emergency)..."
  sleep 2
  `systemd-notify --status 'Service tuée via SIGRTMIN+2 (emergency)...'`
  exit(1)
end
 
`systemd-notify --status 'Chargement du service...'`
 
# Faire quelque chose...
sleep 2
puts "Service chargé"
 
`systemd-notify --ready --status 'Service lancé!'`
 
while(true)
  File.open('/tmp/mon-service.txt', 'w') do |ligne|
    ligne << "Le service a bien démarré! :)"
  end
  sleep 10
end

On applique les bon droits :

chmod a+rx /usr/local/sbin/mon-service

On configure le comportement du service à l'aide d'un fichier de configuration présent dans le dossier suivant :

nano /lib/systemd/system/mon-service.service
mon-service.service
[Service]
ExecStart=/usr/local/sbin/faked
IgnoreSIGPIPE=false
NotifyAccess=all
Type=notify
Restart=on-failure
 
[Install]
WantedBy=multi-user.target

On prend en compte ce nouveau service avec :

systemctl daemon-reload

Une fois fait, on peut démarrer le service ci-dessous :

systemctl start mon-service.service

Le code ci-dessus permet également de comprendre un seul signal qui peut être émis depuis le terminal. Mais avant, il faut connaître le PID du processus qui a lancé ce service. Cette commande permet de le connaître (ligne Main PID) :

systemctl status mon-service.service
● mon-service.service
   Loaded: loaded (/lib/systemd/system/mon-service.service; disabled; vendor preset: enabled)
   Active: active (running) since mar. 2017-03-14 22:50:03 CET; 11min ago
 Main PID: 25420 (mon-service)
   Status: "Service lancé!"
    Tasks: 2 (limit: 4915)
   CGroup: /system.slice/mon-service.service
           └─25420 /usr/bin/ruby /usr/local/sbin/mon-service

mars 14 22:50:01 lubuntu-xmg systemd[1]: Starting mon-service.service...
mars 14 22:50:03 lubuntu-xmg mon-service[25420]: Service chargé
mars 14 22:50:03 lubuntu-xmg systemd[1]: Started mon-service.service.

Et ainsi faire :

kill -SIGRTMIN+2 25420

Spécificités

https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers

Exemple d'unité côté utilisateur :

Cliquez pour afficher ⇲

Cliquez pour masquer ⇱

* Ensure to enable systemd units for your user by executing in root : loginctl enable-linger <user> * Create $SERVICE.service in ~/.config/systemd/user/ * Adjust GEM_HOME with your ruby version * systemctl –user enable $SERVICE && systemctl –user start $SERVICE

[Unit]
Description=Puma HTTP Server
After=network.target

[Service]
WorkingDirectory=/home/%u/www/current
UMask=0027
Environment="GEM_HOME=/home/%u/www/shared/bundle/ruby/2.3.0/"
Environment="RBENV_ROOT=/home/%u/.rbenv"
Environment="RAILS_ENV=production"
Environment="RACK_ENV=production"
ExecStart=/home/%u/.rbenv/bin/rbenv exec bundle exec pumactl -S /home/%u/www/shared/tmp/pids/puma.state -F /home/%u/www/shared/puma.rb restart
Type=forking
RemainAfterExit=yes

[Install]
WantedBy=default.target
Directives

Cliquez pour afficher ⇲

Cliquez pour masquer ⇱

root@icinga2-web:~# cat /etc/systemd/system/program-rs.service [Unit] Description=Interactive Bot IRC for Icinga Wants=network-online.target After=network-online.target

[Service] User=program-rs Group=program-rs RemoveIPC=yes

ExecStart=/usr/local/bin/program-rs –config /etc/program-rs/conf.toml –irc-config /etc/program-rs/irc.toml –hl-file /var/lib/program-rs/hl.tmp

Restart=on-failure

CapabilityBoundingSet= NoNewPrivileges=yes UMask=0077

ProtectSystem=strict ReadWritePaths=/var/lib/program-rs

PrivateTmp=yes PrivateDevices=yes PrivateUsers=yes ProtectHome=yes ProtectKernelTunables=yes ProtectControlGroups=yes RestrictNamespaces=yes ProtectKernelModules=yes MemoryDenyWriteExecute=yes RestrictRealtime=yes

SystemCallArchitectures=native

RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6

[Install] WantedBy=multi-user.target