The Hoof & Paw
DocsCategoriesTagsView the current conditions from the WolfspyreLabs WeatherstationToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Understanding Launchd

Understanding Launchd


A bit of info on launchd

    In computing, launchd a unified operating system service management framework,
starts, stops and manages daemons, applications, processes, and scripts in macOS.
It was introduced with Mac OS X Tiger and is licensed under the Apache License.

– Wikipedia

If you’ve familiar with any version of Linux, surely you have worked with cron jobs. Basically, launchd is the cron in macOS. Other than executing scripts cron-style, launchd does a lot more. Like systemd on Linux, launchd is a replacement for a lot of old school Unix tools, like init, inetd, cron, etc.

At it’s core, launchd distinguishes daemons and agents. Daemons are system-wide services that always run in the background, while agents describe regular services that are to be executed on user-specific events. Daemons and agents are managed by launchd framework which can be controlled using the launchctl terminal command.

There are two main components in the launchd service creating process that you will need to follow.

Job Definition

Operations

: Control the service using command line utility.


📋 Job Definition

Job Definition
Define the service in special XML file.
The behavior of a daemons or agents are defined in a special XML file called a property list .plist file. Depending on where it is stored it will be treated as a daemon or an agent. Services (Daemons and Agents) are saved as .plist files and can reside in one of the following folders according to your requirement as given below.

launchd supports more than 36 different configuration keys in property list file and only main keys that required for a basic service are described in the below. ( from launchd.plist(5) manual)

Label string
This required key uniquely identifies the job to launchd.
Program string
This key defines what to start. If this key is missing, then the first element of the array of strings provided to the ProgramArguments will be used instead. This key is required in the absence of the ProgramArguments key.
ProgramArguments Array of strings
Use this one if your executable requires command line options. This key is required in the absence of the Program key.
RunAtLoad boolean
This optional key is used to control whether your job is launched once at the time the job is loaded. The default is false.
StartInterval integer
This optional key causes the job to be started every N seconds. If the system is asleep, the job will be started the next time the computer wakes up. If multiple intervals transpire before the computer is woken, those events will be coalesced into one event upon wake from sleep.
StartCalendarInterval dictionary of integers or array of dictionary of integers
This optional key causes the job to be started every calendar interval as specified. Missing arguments are considered to be wildcard. The semantics are much like crontab(5).
Minute integer
The minute on which this job will be run.
Hour integer
The hour on which this job will be run.
Day integer
The day on which this job will be run.
Weekday integer
The weekday on which this job will be run (0 and 7 are Sunday).
Month integer
The month on which this job will be run.

Please refer launchd.plist(5) manual or launchd.info for detailed definitions of other keys in property list files.


⚠️ Please note: property list files are expected to have their name end in .plist.

Also note that it is the expected convention for launchd property list files to be named <Label>.plist. Thus, as an example if your job label is org.wso2.am, your plist file should be named org.wso2.am.plist.


⚙ Operations

This section will define how to obtain information about launchd services and how to load, unload, start and stop those jobs. All of this can be accomplished using the command line utility launchctl.

launchctl interfaces with launchd to load, unload daemons/agents and generally control launchd. launchctl supports taking subcommands on the command line, interactively or even redirected from standard input. — launchctl(1) manual

Some of the popular commands in launchctl are defined in the below.

Getting information about available (loaded) jobs:

launchctl list

Getting information about a given job :

launchctl list | grep <LABEL>

Loading a job (a global daemon) :

launchctl load /Library/LaunchDaemons/<LABEL>.plist

Unloading a job (a global daemon) :

launchctl unload /Library/LaunchDaemons/<LABEL>.plist

Starting a job (a loaded job) :

launchctl start <LABEL>

Stoping a job (a loaded job) :

launchctl stop <LABEL>

Restarting a job (a loaded job) :

launchctl restart <LABEL>

⚠️ Please note: If you are working with Daemon job please use sudo permission with above commands.


🎗Simple Example (using WSO2 API Manager)

In this article, I am hoping to run a WSO2 API Manager server as a service on macOS system as an example to understand above explained methods.

WSO2 API Manager addresses full API lifecycle management, monetization, and policy enforcement and it has been named as a Leader in The Forrester Wave™: API Management Solutions, Q4 2018 Report.

  • Download the Latest WSO2 API Manager distribution from WSO2 Official Website.
  • Extract the API Manager zip and go the WSO2 API Manager directory. ( we will call the path to this directory as PRODUCT_HOME )
  • Download and install OpenJDK 8 or Oracle JDK 1.8.* and set the JAVA_HOME environment variable.
  • Create a property file named org.wso2.am.plist at /Library/LaunchDaemons/.
  • Open the org.wso2.am.plist file in a text editor
  • Copy the following content to the property list (.plist) file.
  • Please replace PRODUCT_HOME with path to the product directory.

org.wso2.am.plist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>org.wso2.am</string>
    <key>ServiceDescription</key>
    <string>WSO2 API Manager Server</string>
    <key>ProgramArguments</key>
    <array>
        <string><PRODUCT_HOME>/bin/wso2server.sh</string>
    </array>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
  • Run the following commands to load and start the WSO2 API Manager as service using launchctl utility. sudo launchctl load /Library/LaunchDaemons/org.wso2.am.plist sudo launchctl start org.wso2.am

  • To check the status of the job run the following command and you will able to observe need information about the jobs as given in the image. sudo launchctl list | grep org.wso2.am

WSO2 API Manager running as a service with PID: 27787

  • Run following commands to stop the running process and unload the daemon service from launchd framework. sudo launchctl stop org.wso2.am sudo launchctl unload /Library/LaunchDaemons/org.wso2.am.plist

Therefore, with the understanding of the simple example of the launchd framework now you can use launchd to create scripts that do things like clean up files, control application servers on a schedule or run an application when a certain file appears. Cheers!! 🍺🍺


More details on launchd framework and launchctl utility: