Les agents de lancement sont en gros les mêmes que les démons de lancement, sauf que.. :
-
LaunchAgents s'exécute uniquement après que l'utilisateur se soit connecté, le processus s'exécute sur l'UID (ID utilisateur) connecté avec les privilèges de l'utilisateur connecté. Le processus peut interagir avec l'utilisateur connecté via l'interface graphique.
-
LaunchDaemons s'exécute au moment du démarrage, avant que l'interface graphique soit en place, pendant la barre de progression sur l'écran de démarrage. Il s'exécute en tant que Root, il n'est pas nécessaire d'avoir un utilisateur connecté, il fonctionne en arrière-plan (comme les services système de Windows, ou les démons rc.d de Linux), il ne peut pas interagir avec un utilisateur sur l'interface graphique. (Personnellement, j'ai un launchDaemon qui télécharge et met à jour mon fichier /etc/hosts en bloquant certaines URLs malveillantes, c'est un bash script que j'ai créé comme un service).
/Library/LaunchAgents/
- (Pour tous les utilisateurs) [charger après tout utilisateur se connecter]
~/Library/LaunchAgents/
- (pour un utilisateur SPÉCIFIQUE) [charger après qu'il se soit connecté]
-- Charger signifie "exécuter le service", vous le chargez en mémoire. Mais il se peut qu'il ne s'exécute pas exactement au moment du chargement, si votre paramètre interne plist définit par exemple une minuterie pour s'exécuter, après X heures.
Eg : Je crée mon démon personnalisé /Library/LaunchDaemons/local.updateHosts.plist
Je vais le charger :
sudo launchctl load /Library/LaunchDaemons/local.updateHosts.plist
Load doit pointer vers le chemin/to/file.plist.
**Il se peut que vous deviez le démarrer après le chargement, de cette façon il sera exécuté, se terminera, et attendra le prochain temps d'exécution (si c'est un service temporisé comme le mien)*.
Comme il est sur LaunchDaemon, c'est un service système.
[une brève pause ici à propos de launchctl]
Car pour continuer, nous devons comprendre l'architecture d'exécution des processus de MacOS :
MacOS Bootstraps domaines, sessions et espaces de noms
En plus des contextes de processus BSD [ UID ], MacOS possède les contextes de processus d'amorçage Mach, appelés espaces de noms.
Un espace de noms est comme un "lieu" ou un regroupement, où s'exécutent divers processus.
Les espaces de noms Bootstrap sont organisés de manière hiérarchique. Il existe un Système sous lequel se trouve un espace de nom global par utilisateur (non GUI), et en dessous de celui-ci nous avons un par session Espace de noms GUI [créé par le WindowServer lorsque l'utilisateur se connecte via GUI] .
Hiérarchiquement, chaque niveau inférieur peut accéder à tous les services de l'espace de nommage des niveaux supérieurs (processus de services parents).
----
System_Namespace
Per-User_Namespace
Per-Session_Namespace(GUI WindowServer)
----
Techniquement, l'espace de nom par session de l'interface graphique est appelé Session 'Aqua' dans les documents de l'API d'Apple.
La hiérarchie ci-dessus montre le domaine système, le domaine utilisateur et le domaine session (qui appartient à l'utilisateur, chaque utilisateur a le sien).
Une vue étendue avec 2 utilisateurs connectés est ci-dessous :
``
// System_Namespace [System]
// |
// ------ PerUSER_Namespace [Background] [user 501]
// | |
// | ----- PerSESSION_Namespace [Aqua] (MacOS GUI WindowServer) [user 501]
// |
// |
// ------ PerUSER_Namespace [Background] [user 502]
// |
// ----- PerSESSION_Namespace [Aqua] (MacOS GUI WindowServer) [user 502]
// ----
//
``
C'est exactement l'origine de l'architecture de sécurité de MacOS, appelée couche Mach, qui travaille en conjonction avec la couche BSD (qui s'occupe des permissions des fichiers utilisateurs et des autres permissions linux/bsd/unix).
MacOS dispose de 2 mécanismes de sécurité distincts intégrés et fonctionnant ensemble : le Unix + le Mach les mécanismes de sécurité.
Pour continuer sur launchctl, lorsque vous êtes sur le point de créer un daemon/service, vous devez choisir où il sera exécuté, quel domaine et quel contexte.
Tout d'abord, nous allons imprimer le domaine du système services, cela listera tous les launchdaemons, chargés ou non, activés et désactivés.
sudo launchctl print system/
Maintenant, imprimons les services du domaine de l'utilisateur : (en considérant l'identifiant 501, vous pouvez trouver d'autres numéros d'identification d'utilisateurs avec la commande : id username
sudo launchctl print user/501
Remarque : Catalina accepte également la syntaxe : sudo launchctl print user/admin
<- nom d'utilisateur
Vous pouvez également interroger un PID, et vérifier sous quel domaine et espace de nom il fonctionne :
sudo launchctl print pid/784
(sachant que 784 est le PID de Finder par exemple)
> $ sudo launchctl print pid/758
com.apple.xpc.launchd.domain.pid.Finder.758 = {
type = process
handle = 758
active count = 91
on-demand count = 1
service count = 90
active service count = 2
activity ratio = 0.02
originator = /System/Library/CoreServices/Finder.app
creator = Finder.758
creator euid = 503
uniqueid = 758
external activation count = 0
security context = {
uid = 503
asid = 100008
}
bringup time = 20 ms
death port = 0x52a63
in-progress bootstraps = 0
pended requests = 0
pending requests = {
}
subdomains = {
}
pending attachments = {
}
task-special ports = {
0x3fc73 4 bootstrap com.apple.xpc.launchd.user.domain.503.100008.Aqua
0x15f03 9 access com.apple.taskgated
}
Dans le contexte de la sécurité :
com.apple.xpc.launchd.domain.pid.Finder.758 com.apple.xpc.launchd.user.domain.503.100008.Aqua
Moyens :
- Finder, qui a le PID 758
- a été créé par launchd,
- en vertu de la domaine utilisateur ,
- pour l'utilisateur 503,
- qui exécute une interface graphique avec l'ID de session 100008.
Vous pouvez maintenant choisir et contrôler le domaine, les espaces de noms et l'utilisateur de votre démon.
démarrage signifie arrêter un service en cours d'exécution, par exemple :
sudo launchctl bootout system/com.apple.netbiosd
Ceci arrête le démon netbios.
__ Revenons au service que nous avons créé avec cette commande :
sudo launchctl load /Library/LaunchDaemons/local.updateHosts.plist
charge est le seul paramètre qui vous permet de passer le chemin complet du fichier .plist, toutes les autres commandes launchctl fonctionnent. via la référence de la hiérarchie des domaines !
Ainsi, pour imprimer notre service est : sudo launchctl print system/local.updateHosts
vous n'utilisez pas l'extension .plist, et la référence est system/process.name
Le nom du processus est celui que vous définissez dans le fichier .plist sous la clé Étiquette :
<key>Label</key>
<string>local.updateHosts</string>
<key>ProgramArguments</key>
<array>
Le site bootstrap est de forcer le chargement de votre service tout en choisissant le domaine ou l'espace de nom que vous voulez lui faire exécuter, ex :
sudo launchctl bootstrap user/503 /Library/LaunchDaemons/local.updateHosts.plist`
/Library/LaunchDaemons/local.updateHosts.plist: Service cannot load in requested session
La commande ci-dessus a retourné une erreur parce que mon service .plist ne permet à mon service de s'exécuter en tant que service système, sinon il aurait été lancé pour l'utilisateur 503.
bootstrap vous permet de démarrer n'importe quel service ou bundle de services XPC sous d'autres domaines/espaces de noms. En gros, vous choisissez un service ET un cible pour qu'il fonctionne.
Taxes supplémentaires :
sudo launchctl start system/local.updateHosts
sudo launchctl stop system/local.updateHosts
sudo launchctl unload system/local.updateHosts
sudo launchctl kickstart system/local.updateHosts
Si vous voulez aller très loin sur ce sujet, je vous suggère cette excellente documentation d'Apple, elle est très technique et très détaillée :
https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/contexts/contexts.html#//apple_ref/doc/uid/TP30000905-CH212-BEHJDFCA