launchctl on macOS is the direct equivalent of systemctl on Linux systems using systemd

launchctl on macOS manages launchd, which fulfills the role of systemctl and cron on Linux systems.

Here you can read about it

launchctl is used to control and manage services, daemons, and agents running in the background.

Launchctl is also responsible for running tasks at specific intervals or times, a function traditionally handled by cron in Linux.

While cron uses a table format (crontab), launchd does so through special keys in the same .plist file used for services.

systemctl (Linux): This is the command-line tool for interacting with the system and service manager (systemd). It is used to control and manage system services and units, such as starting, stopping, restarting, and enabling or disabling services to start automatically. Services are defined via .service files.

launchctl (macOS): This is the command-line tool for interacting with the launchd startup daemon. Like systemctl, it is used to load and unload daemons and agents, start and stop launchd-controlled jobs, and generally control the macOS startup system. Jobs are defined in property list (.plist) files.

Both pairs of tools (systemd/systemctl and launchd/launchctl) perform a similar function in their respective operating systems, which is to manage how services and processes are started, run, and stopped.

Services in macOS are managed through .plist (property list) files

.plist Directories


The .plist (property list) file format on macOS is a standard way to store serialized data. They are essentially XML or binary files containing key-value pairs, organized into dictionaries and arrays.

<key>ProgramArguments</key>
<array>
    <string>/usr/local/bin/myscript.sh</string>
    <string>--mode</string>
    <string>prod</string>
</array>

The main difference is that a daemon is a single system-level process, while an agent is an instance of a process that runs for each user who needs it.

Daemon and agent are different, I had a hard time understanding

system first, then user, daemon first then agent

Launchd handles processes at system startup:

The operating system boots.

Launchd starts the system daemons (which are independent of any user).

A user logs in.

That user’s launchd process is activated and launches its corresponding agents.

User Agents: (At the user level, the operating system is already started)

for the agents of an individual user

~/Library/LaunchAgents

for agents that will run for each user who logs in, but still as a separate process per user

/Library/LaunchAgents

System Daemons (at the operating system level):

for third-party daemons

/Library/LaunchDaemons

for Apple daemons

/System/Library/LaunchDaemons

Note: To manage daemons in /Library/LaunchDaemons/ or /System/Library/LaunchDaemons/, you’ll need to use sudo.

Daemons need superuser permissions, i.e. sudo.

It doesn’t make sense for a user to have their own daemon, since a daemon is a single process for the entire system.

Upload and Download Services

Load a service:

launchctl load [path_to_the_plist_file]

Example: launchctl load ~/Library/LaunchAgents/com.mycompany.myagent.plist

Download a service:

launchctl unload [path_to_the_plist_file]

Example: launchctl unload ~/Library/LaunchAgents/com.mycompany.myagent.plist

for a system daemon: sudo launchctl unload /Library/LaunchDaemons/com.mycompany.midaemon.plist

Start a loaded service:

launchctl start [service_name]

The service_name is the value of the Label key inside the .plist file.

Example: launchctl start com.mycompany.myagent

Stop a loaded service

launchctl stop [service_name]

Example: launchctl stop com.mycompany.myagent

List Services (list) shows you all the services that launchd is currently managing.

List all services of the current user:

 launchctl list

List all system services (requires sudo):

sudo launchctl list

Filter the list by name:

launchctl list | grep [service_name]

Example: launchctl list | grep com.apple.smbd (to see the Samba service)

Restart Services (kickstart)

This command is useful for restarting a service without having to use stop and start separately. It’s the equivalent of systemctl restart.

launchctl kickstart [service_name]

Example: launchctl kickstart com.apple.smbd

  • .plist Files: For launchd to recognize a service, the .plist file must be in the correct directory and the user must have the appropriate permissions.
  • Legacy vs. Modern: Over time, Apple has introduced new commands like bootstrap and bootout to replace load and unload, but the latter still work and are the most common for most use cases.
  • Troubleshooting: If a service fails to start, check the system log files using the Console app or the log show command in Terminal, and ensure that the path to the executable within the .plist is absolute and correct.