If you are developing daemons to run on OS X, it is highly recommended that you design your daemons to be
launchd compliant. Using
launchd provides better performance and flexibility for daemons. It also improves the ability of administrators to manage the daemons running on a given system.
If you are running per-user background processes for OS X,
launchd is also the preferred way to start these processes. These per-user processes are referred to as user agents. A user agent is essentially identical to a daemon, but is specific to a given logged-in user and executes only while that user is logged in.
DAEMON Tools Ultra 5 Mac is a powerful and amazing tool in the world. Get the immense list of possibilities to work with virtual drives, create bootable USB-sticks for operating system recovery, It provides to easily RAM disks to speed up your PC and evaluate the unique iSCSI Initiator that allows connecting to USB devices very fast. DAEMON Tools is an unobtrusive macOS application designed to help you mount CD, DVD, or HDD disc images on your Apple computer. For your convenience, the DAEMON Tools app resides in the Dock or in the status bar, but you can also define global hotkeys for mounting and unmounting discs.
Unless otherwise noted, for the purposes of this chapter, the terms “daemon” and “agent” can be used interchangeably. Thus, the term “daemon” is used generically in this section to encompass both system-level daemons and user agents except where otherwise noted.
There are four ways to launch daemons using
launchd. The preferred method is on-demand launching, but
launchd can launch daemons that run continuously, and can replace
inetd-style daemons. In addition,
launchd can start jobs at timed intervals.
launchd supports non-launch-on-demand daemons, this use is not recommended. The
launchd daemon was designed to remove the need for dependency ordering among daemons. If you do not make your daemon be launched on demand, you will have to handle these dependencies in another way, such as by using the legacy startup item mechanism.
Launching Custom Daemons Using launchd
With the introduction of
launchd in OS X v10.4, an effort was made to improve the steps needed to launch and maintain daemons. What
launchd provides is a harness for launching your daemon as needed. To client programs, the port representing your daemon’s service is always available and ready to handle requests. In reality, the daemon may or may not be running. When a client sends a request to the port,
launchd may have to launch the daemon so that it can handle the request. Once launched, the daemon can continue running or shut itself down to free up the memory and resources it holds. If a daemon shuts itself down,
launchd once again relaunches it as needed to process requests.
In addition to the launch-on-demand feature,
launchd provides the following benefits to daemon developers:
Simplifies the process of making a daemon by handling many of the standard housekeeping chores normally associated with launching a daemon.
Provides system administrators with a central place to manage daemons on the system.
Eliminates the primary reason for running daemons as root. Because
launchdruns as root, it can create low-numbered TCP/IP listen sockets and hand them off to the daemon.
Simplifies error handling and dependency management for inter-daemon communication. Because daemons launch on demand, communication requests do not fail if the daemon is not launched. They are simply delayed until the daemon can launch and process them.
Daemon Tools For Mac 7
The launchd Startup Process
After the system is booted and the kernel is running,
launchd is run to finish the system initialization. As part of that initialization, it goes through the following steps:
It loads the parameters for each launch-on-demand system-level daemon from the property list files found in
It registers the sockets and file descriptors requested by those daemons.
It launches any daemons that requested to be running all the time.
As requests for a particular service arrive, it launches the corresponding daemon and passes the request to it.
When the system shuts down, it sends a
SIGTERMsignal to all of the daemons that it started.
The process for per-user agents is similar. When a user logs in, a per-user
launchd is started. It does the following:
It loads the parameters for each launch-on-demand user agent from the property list files found in
/Library/LaunchAgents, and the user’s individual
It registers the sockets and file descriptors requested by those user agents.
It launches any user agents that requested to be running all the time.
As requests for a particular service arrive, it launches the corresponding user agent and passes the request to it.
When the user logs out, it sends a
SIGTERMsignal to all of the user agents that it started.
launchd registers the sockets and file descriptors used by all daemons before it launches any of them, daemons can be launched in any order. If a request comes in for a daemon that is not yet running, the requesting process is suspended until the target daemon finishes launching and responds.
If a daemon does not receive any requests over a specific period of time, it can choose to shut itself down and release the resources it holds. When this happens,
launchd monitors the shutdown and makes a note to launch the daemon again when future requests arrive.
Important: If your daemon shuts down too quickly after being launched,
launchd may think it has crashed. Daemons that continue this behavior may be suspended and not launched again when future requests arrive. To avoid this behavior, do not shut down for at least 10 seconds after launch.
Creating a launchd Property List File
To run under
launchd, you must provide a configuration property list file for your daemon. This file contains information about your daemon, including the list of sockets or file descriptors it uses to process requests. Specifying this information in a property list file lets
launchd register the corresponding file descriptors and launch your daemon only after a request arrives for your daemon’s services. Table 5-1 lists the required and recommended keys for all daemons.
The property list file is structured the same for both daemons and agents. You indicate whether it describes a daemon or agent by the directory you place it in. Property list files describing daemons are installed in
/Library/LaunchDaemons, and those describing agents are installed in
/Library/LaunchAgents or in the
LaunchAgents subdirectory of an individual user’s
Library directory. (The appropriate location for executables that you launch from your job is
Contains a unique string that identifies your daemon to
Contains the arguments used to launch your daemon. (required)
Indicates that your daemon requires a separate instance per incoming connection. This causes
This key specifies whether your daemon launches on-demand or must always be running. It is recommended that you design your daemon to be launched on-demand.
For more information: For a complete listing of the keys, see the
launchd.plist manual page.
For sample configuration property lists, look at the files in
/System/Library/LaunchDaemons/. These files are used to configure many daemons that run on OS X.
Writing a “Hello World!” launchd Job
The following simple example launches a daemon named
world as a single argument, and instructs launchd to keep the job running:
In this example, there are three keys in the top level dictionary. The first is
Label, which uniquely identifies the job. when. The second is
ProgramArguments which has a value of an array of strings which represent the tokenized arguments and the program to run. The third and final key is
KeepAlive which indicates that this job needs to be running at all times, rather than the default launch-on-demand behavior, so launchd should always try to keep this job running.
Listening on Sockets
You can also include other keys in your configuration property list file. For example, if your daemon monitors a well-known port (one of the ports listed in
/etc/services), add a
Sockets entry as follows:
The string for
SockServiceName typically comes from the leftmost column in
SockType is one of
dgram (UDP) or
stream (TCP/IP). If you need to pass a port number that is not listed in the well-known ports list, the format is the same, except the string contains a number instead of a name. For example:
Debugging launchd Jobs
There are some options that are useful for debugging your launchd job.
The following example enables core dumps, sets standard out and error to go to a log file, and instructs launchd to temporarily increase the debug level of its logging while acting on behalf of your job (remember to adjust your syslog.conf accordingly):
Running a Job Periodically
The following example creates a job that is run every five minutes (300 seconds):
Alternately, you can specify a calendar-based interval. The following example starts the job on the 7th day of every month at 13:45 (1:45 pm). Like the Unix cron subsystem, any missing key of the
StartCalendarInterval dictionary is treated as a wildcard—in this case, the month is omitted, so the job is run every month.
Monitoring a Directory
The following example starts the job whenever any of the paths being watched have changed:
An additional file system trigger is the notion of a queue directory. The launchd daemon starts your job whenever the given directories are non-empty, and it keeps your job running as long as those directories are not empty:
The launchd daemon emulates the older
inetd-style daemon semantics if you provide the
Behavior for Processes Managed by launchd
Processes that are managed by
launchd must follow certain requirements so that they interact properly with
launchd. This includes launch daemons and launch agents.
launchd, you must obey the following guidelines when writing your daemon code:
You must provide a property list with some basic launch-on-demand criteria for your daemon. See Creating a launchd Property List File.
You must not daemonize your process. This includes calling the
exec, or calling
exit. If you do,
launchdthinks your process has died. Depending on your property list key settings,
launchdwill either keep trying to relaunch your process until it gives up (with a “respawning too fast” error message) or will be unable to restart it if it really does die.
Daemons and agents that are installed globally must be owned by the root user. Agents installed for the current user must be owned by that user. All daemons and agents must not be group writable or world writable. (That is, they must have file mode set to
launchd, it is recommended that you obey the following guidelines when writing your daemon code:
Wait until your daemon is fully initialized before attempting to process requests. Your daemon should always provide a reasonable response (rather than an error) when processing requests.
Register the sockets and file descriptors used by your daemon in your
launchdconfiguration property list file.
If your daemon advertises a socket, check in with
launchdas part of your daemon initialization. For an example implementation of the check-in process, see SampleD.
During check-in, get the launch dictionary from
launchd, extract and store its contents, and then discard the dictionary. Accessing the data structure used for the dictionary is very slow, so storing the whole dictionary locally and accessing it frequently could hurt performance.
Provide a handler to catch the
In addition to the preceding list, the following is a list of things it is recommended you avoid in your code:
Do not set the user or group ID for your daemon. Include the
GIDkeys in your daemon’s configuration property list instead.
Do not set the working directory. Include the
WorkingDirectorykey in your daemon’s configuration property list instead.
Do not call
chrootto change the root directory. Include the
RootDirectorykey in your daemon’s configuration property list instead.
Do not call
setsidto create a new session.
Do not close any stray file descriptors.
Do not change
stdioto point to
/dev/null. Include the
StandardErrorPathkeys in your daemon’s configuration property list file instead.
Do not set up resource limits with
Do not set the daemon priority with
Although many of the preceding behaviors may be standard tasks for daemons to perform, they are not recommended when running under
launchd. The reason is that
launchd configures the operating environment for the daemons that it manages. Changing this environment could interfere with the normal operation of your daemon.
Deciding When to Shut Down
If you do not expect your daemon to handle many requests, you might want to shut it down after a predetermined amount of idle time, rather than continue running. Although a well-written daemon does not consume any CPU resources when idle, it still consumes memory and could be paged out during periods of intense memory use.
The timing of when to shut down is different for each daemon and depends on several factors, including:
The number and frequency of requests it receives
The time it takes to launch the daemon
The time it takes to shut down the daemon
The need to retain state information
If your daemon does not receive frequent requests and can be launched and shut down quickly, you might prefer to shut it down rather than wait for it to be paged out to disk. Paging memory to disk, and subsequently reading it back, incurs two disk operations. If you do not need the data stored in memory, your daemon can shut down and avoid the step of writing memory to disk.
launchd takes care of dependencies between daemons, in some cases, your daemon may depend on other system functionality that cannot be addressed in this manner. This section describes many of these special cases and how to handle them.
If your daemon depends on the network being available, this cannot be handled with dependencies because network interfaces can come and go at any time in OS X. To solve this problem, you should use the network reachability functionality or the dynamic store functionality in the System Configuration framework. This is documented in System Configuration Programming Guidelines and System Configuration Framework Reference. For more information about network reachability, see Determining Reachability and Getting Connected in System Configuration Programming Guidelines.
Disk or Server Availability
If your daemon depends on the availability of a mounted volume (whether local or remote), you can determine the status of that volume using the Disk Arbitration framework. This is documented in Disk Arbitration Framework Reference.
If your daemon has a dependency on a non-
launchd daemon, you must take additional care to ensure that your daemon works correctly if that non-
launchd daemon has not started when your daemon is started. The best way to do this is to include a loop at start time that checks to see if the non-
launchd daemon is running, and if not, sleeps for several seconds before checking again.
Be sure to set up handlers for
SIGTERM prior to this loop to ensure that you are able to properly shut down if the daemon you rely on never becomes available.
In general, a daemon should not care whether a user is logged in, and user agents should be used to provide per-user functionality. However, in some cases, this may be useful.
To determine what user is logged in at the console, you can use the System Configuration framework, as described in Technical Q&A QA1133.
If your daemon requires that a certain kernel extension be loaded prior to executing, you have two options: load it yourself, or wait for it to be loaded.
The daemon may manually request that an extension be loaded. To do this, run
kextload with the appropriate arguments using
exec or variants thereof. I/O Kit kernel extensions should not be loaded with
kextload; the I/O Kit will load them automatically when they are needed.
kextload executable must be run as root in order to load extensions into the kernel. For security reasons, it is not a setuid executable. This means that your daemon must either be running as the root user or must include a helper binary that is setuid root in order to use
kextload to load a kernel extension.
Alternatively, our daemon may wait for a kernel service to be available. To do this, you should first register for service change notification. This is further documented in I/O Kit Framework Reference.
After registering for these notifications, you should check to see if the service is already available. By doing this after registering for notifications, you avoid waiting forever if the service becomes available between checking for availability and registering for the notification.
Note: In order for your kernel extension to be detected in a useful way, it must publish a node in the I/O registry to advertise the availability of its service. For I/O Kit drivers, this is usually handled by the I/O Kit family.
For other kernel extensions, you must explicitly register the service by publishing a nub, which must be an instance of
For more information about I/O Kit services and matching, see IOKit Fundamentals, I/O Kit Framework Reference (user space reference), and Kernel Framework Reference (kernel space reference).
For More Information
The manual pages for
launchd.plist are the two best sources for information about
In addition, you can find a source daemon accompanying the
launchd source code (available from http://www.macosforge.org/). This daemon is also provided from the Mac Developer Library as the SampleD sample code project.
The Daemons and Agents technical note provides additional information about how
launchd daemons and agents work under the hood.
Finally, many Apple-provided daemons support
launchd. Their property list files can be found in
/System/Library/LaunchDaemons. Some of these daemons are also available as open source from http://www.opensource.apple.com/ or http://www.macosforge.org/.
Estimated reading time: 11 minutes
After successfully installing and starting Docker, the
dockerd daemonruns with its default configuration. This topic shows how to customizethe configuration, start the daemon manually, and troubleshoot and debug thedaemon if you run into issues.
Start the daemon using operating system utilities
On a typical installation the Docker daemon is started by a system utility,not manually by a user. This makes it easier to automatically start Docker whenthe machine reboots.
The command to start Docker depends on your operating system. Check the correctpage under Install Docker. To configure Dockerto start automatically at system boot, seeConfigure Docker to start on boot.
Start the daemon manually
If you don’t want to use a system utility to manage the Docker daemon, orjust want to test things out, you can manually run it using the
dockerdcommand. You may need to use
sudo, depending on your operating systemconfiguration.
When you start Docker this way, it runs in the foreground and sends its logsdirectly to your terminal.
To stop Docker when you have started it manually, issue a
Ctrl+C in yourterminal.
Configure the Docker daemon
There are two ways to configure the Docker daemon:
- Use a JSON configuration file. This is the preferred option, since it keepsall configurations in a single place.
- Use flags when starting
You can use both of these options together as long as you don’t specify thesame option both as a flag and in the JSON file. If that happens, the Dockerdaemon won’t start and prints an error message.
To configure the Docker daemon using a JSON file, create a file at
/etc/docker/daemon.json on Linux systems, or
C:ProgramDatadockerconfigdaemon.jsonon Windows. On MacOS go to the whale in the taskbar > Preferences > Daemon > Advanced.
Here’s what the configuration file looks like:
With this configuration the Docker daemon runs in debug mode, uses TLS, andlistens for traffic routed to
192.168.59.3 on port
2376.You can learn what configuration options are available in thedockerd reference docs
You can also start the Docker daemon manually and configure it using flags.This can be useful for troubleshooting problems.
Here’s an example of how to manually start the Docker daemon, using the sameconfigurations as above:
You can learn what configuration options are available in thedockerd reference docs, or by running:
Many specific configuration options are discussed throughout the Dockerdocumentation. Some places to go next include:
Docker daemon directory
The Docker daemon persists all data in a single directory. This tracks everythingrelated to Docker, including containers, images, volumes, service definition,and secrets.
By default this directory is:
Microsoft Daemon For Mac
You can configure the Docker daemon to use a different directory, using the
data-root configuration option.
Since the state of a Docker daemon is kept on this directory, make sureyou use a dedicated directory for each daemon. If two daemons share the samedirectory, for example, an NFS share, you are going to experience errors thatare difficult to troubleshoot.
Troubleshoot the daemon
You can enable debugging on the daemon to learn about the runtime activity ofthe daemon and to aid in troubleshooting. If the daemon is completelynon-responsive, you can alsoforce a full stack trace of allthreads to be added to the daemon log by sending the
SIGUSR signal to theDocker daemon.
Troubleshoot conflicts between the
daemon.json and startup scripts
If you use a
daemon.json file and also pass options to the
dockerdcommand manually or using start-up scripts, and these options conflict,Docker fails to start with an error such as:
If you see an error similar to this one and you are starting the daemon manually with flags,you may need to adjust your flags or the
daemon.json to remove the conflict.
Note: If you see this specific error, continue to thenext section for a workaround.
If you are starting Docker using your operating system’s init scripts, you mayneed to override the defaults in these scripts in ways that are specific to theoperating system.
Use the hosts key in daemon.json with systemd
One notable example of a configuration conflict that is difficult to troubleshootis when you want to specify a different daemon address fromthe default. Docker listens on a socket by default. On Debian and Ubuntu systems using
systemd,this means that a host flag
-H is always used when starting
dockerd. If you specify a
hosts entry in the
daemon.json, this causes a configuration conflict (as in the above message)and Docker fails to start.
To work around this problem, create a new file
/etc/systemd/system/docker.service.d/docker.conf withthe following contents, to remove the
-H argument that is used when starting the daemon by default.
There are other times when you might need to configure
systemd with Docker, such asconfiguring a HTTP or HTTPS proxy.
Note: If you override this option and then do not specify a
hosts entry in the
-H flag when starting Docker manually, Docker fails to start.
sudo systemctl daemon-reload before attempting to start Docker. If Docker startssuccessfully, it is now listening on the IP address specified in the
hosts key of the
daemon.json instead of a socket.
hosts in the
daemon.json is not supported on Docker Desktop for Windowsor Docker Desktop for Mac.
Out Of Memory Exceptions (OOME)
If your containers attempt to use more memory than the system has available,you may experience an Out Of Memory Exception (OOME) and a container, or theDocker daemon, might be killed by the kernel OOM killer. To prevent this fromhappening, ensure that your application runs on hosts with adequate memory andseeUnderstand the risks of running out of memory.
Read the logs
The daemon logs may help you diagnose problems. The logs may be saved in one ofa few locations, depending on the operating system configuration and the loggingsubsystem used:
|RHEL, Oracle Linux|
|Ubuntu 16.04+, CentOS||Use the command |
|macOS (Docker 18.01+)|
|macOS (Docker <18.01)|
There are two ways to enable debugging. The recommended approach is to set the
debug key to
true in the
daemon.json file. This method works for everyDocker platform.
daemon.jsonfile, which is usually located in
/etc/docker/.You may need to create this file, if it does not yet exist. On macOS orWindows, do not edit the file directly. Instead, go toPreferences / Daemon / Advanced.
If the file is empty, add the following:
If the file already contains JSON, just add the key
'debug': true, beingcareful to add a comma to the end of the line if it is not the last linebefore the closing bracket. Also verify that if the
log-levelkey is set,it is set to either
infois the default, and possiblevalues are
HUPsignal to the daemon to cause it to reload its configuration.On Linux hosts, use the following command.
On Windows hosts, restart Docker.
Instead of following this procedure, you can also stop the Docker daemon andrestart it manually with the debug flag
-D. However, this may result in Dockerrestarting with a different environment than the one the hosts’ startup scriptscreate, and this may make debugging more difficult.
Force a stack trace to be logged
If the daemon is unresponsive, you can force a full stack trace to be loggedby sending a
SIGUSR1 signal to the daemon.
Get the process ID of dockerd
Run the executable with the flag
--pid=<PID of daemon>.
This forces a stack trace to be logged but does not stop the daemon.Daemon logs show the stack trace or the path to a file containing thestack trace if it was logged to a file.
The daemon continues operating after handling the
SIGUSR1 signal anddumping the stack traces to the log. The stack traces can be used to determinethe state of all goroutines and threads within the daemon.
View stack traces
The Docker daemon log can be viewed by using one of the following methods:
- By running
journalctl -u docker.serviceon Linux systems using
/var/log/docker.logon olderLinux systems
Note: It is not possible to manually generate a stack trace on Docker Desktop forMac or Docker Desktop for Windows. However, you can click the Docker taskbar icon andchoose Diagnose and feedback to send information to Docker if you run intoissues.
Look in the Docker logs for a message like the following:
The locations where Docker saves these stack traces and dumps depends on youroperating system and configuration. You can sometimes get useful diagnosticinformation straight from the stack traces and dumps. Otherwise, you can providethis information to Docker for help diagnosing the problem.
Check whether Docker is running
The operating-system independent way to check whether Docker is running is toask Docker, using the
docker info command.
You can also use operating system utilities, such as
sudo systemctl is-active docker or
sudo status docker or
sudo service docker status, or checking the service status using Windowsutilities.
Finally, you can check in the process list for the
dockerd process, usingcommands like