18 votes

lancé : Confusion sur la sémantique de bootstrap et bootout etc. après avoir lu les pages du manuel

J'ai lu les pages de manuel suivantes sur launchd : launchctl , launchd et launchd.plist .

Cependant, rien n'est vraiment dit dans ces pages de manuel concernant ce que le launchctl boostrap y launchctl bootout (sous-)commandements font réellement (voir ci-dessous). Faut-il le déduire de leurs noms ?

En outre, je ne trouve aucune information dans les pages de manuel concernant l'utilisateur ou le groupe sous lequel le service (agent/daemon) fonctionne. Cependant, launchd.plist mentionne UserName / GroupName pour contrôler l'utilisateur/le groupe pour le domaine du système. Alors, à quoi servent les services par utilisateur en /Library/LaunchAgents ou ~/Library/LaunchAgents en tant que ?

Enfin, je pense que je dois bootstrap / load mon daemon mais après avoir placé le fichier .plist dans le dossier de l'utilisateur, il est possible de l'utiliser. /Library/LaunchAgents ou /Library/LaunchDaemons il a été automatiquement chargé (exécuté) au démarrage du système. En effet, RunAtLoad=true mais quel est le but de bootstrap si les services fonctionnent quand même ?

man launchctl :

 bootstrap | bootout domain-target [service-path service-path2 ...] | service-target
          Bootstraps or removes domains and services. When service arguments are present, bootstraps and correspondingly removes their definitions into the domain.  Services may be specified as a series of
          paths or a service identifier.  Paths may point to XPC service bundles, launchd.plist(5) s, or a directories containing a collection of either. If there were one or more errors while bootstrapping or
          removing a collection of services, the problematic paths will be printed with the errors that occurred.

          If no paths or service target are specified, these commands can either bootstrap or remove a domain specified as a domain target. Some domains will implicitly bootstrap pre-defined paths as part of
          their creation.

27voto

Prado Points 1415

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é :

  • uid = 503 -> le processus est en cours d'exécution pour l'utilisateur 503

  • asid = 100008 -> le processus fonctionne sur la session GUI 100008


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

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X