Adding Startup Scripts to Launch Daemon on Mac OS X Sierra 10.12.6

Fahim Hossain
Sep 2, 2017 · 3 min read

Being new to working on OS X, it has been somewhat confusing to how things work on Mac compared to that on Linux — to be completely honest it has been a painstaking journey while wrapping my head around the differences between the systems.

I intend to share my experience relating to adding start up shell scripts to the Launch Daemon on OS X Sierra. Any suggestions for a better solution is most welcome.

A good starting point to get to know about Launch Daemon Process — how to configure, troubleshoot and get some examples can be found here.

What is a Daemon

A daemon is a program running in the background without requiring user input.

Task in Hand

  1. Create an shell script file to start mariadb (for simplicity of demo)
  2. Launch the shell script file as soon as the computer boots up (i.e. without requiring the user to login)

Lets Start

Step 1: Create an shell script file using the terminal

vim ~/scripts/startup/startup.sh

Now add in the following code to the file — save and exit. This primarily checks if the mariadb service is enabled or not and then starts the service if it is stopped.

#!bin/bash
#Start Mariadb Server only if it is not running
if [ “$(ps -ef | grep -v grep | grep mariadb | wc -l)” -le 0 ]
then # Note starting mariadb not as a sudoer
mariadb start
echo "Mariadb Server Started"
else
echo "Mariadb Server Already Running"
fi

Give the script file execution permission

chmod +x ~/scripts/startup/startup.sh

Step 2: Launch the shell script file as soon as the computer boots up

We now have to add the script file to the Launch Daemon process — which will run the Job as soon as the Mac is booted.

Job Description

The behavior of a daemon/agent is specified in a special XML file called a property list. Depending on where it is stored it will be treated as a daemon or an agent.

Again, just to be clear between the difference between daemon/agents:

The main difference is that an agent is run on behalf of the logged in user while a daemon runs on behalf of the root user or any user you specify with the UserName key.

In Mac OS X, the Launch Daemons are stored inside

/Library/LaunchDaemons/ 

folder while the Launch Agents are inside

/Library/LaunchAgents/

Now, lets create a property list file(.plist) here as root user. (Please note there are conventions in naming the plist file which is outside the scope of this article)

sudo vim /Library/LaunchDaemons/com.startup.plist

Configuration of the plist file will vary upon your use case. The list of properties that can be configured is again nicely illustrated under the Configuration section on launchd.info

For easier illustration, please check the following plit file and the inline commets:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:</string>
</dict>
<key>Label</key>
<string>com.startup</string>
<key>Program</key>
<string>/Users/admin/Scripts/startup/startup.sh</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
<key>LaunchOnlyOnce</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/startup.stdout</string>
<key>StandardErrorPath</key>
<string>/tmp/startup.stderr</string>
<key>UserName</key>
<string>admin</string>
<key>GroupName</key>
<string>admin</string>
<key>InitGroups</key>
<true/>
</dict>
</plist>

Now that we have all the necessary files ready and in place, we need to add the property list file onto the launchctl as follows:

# -w flag permanently adds the plist to the Launch Daemon
sudo launchctl load -w /Library/LaunchDaemons/com.startup.plist

Other notes,

  • To permanently remove the plist to the Launch Daemon
# -w flag permanently remove the plist to the Launch Daemon
sudo launchctl unload -w /Library/LaunchDaemons/com.startup.plist
  • Once a script is added onto the Launch Daemon it will auto-start even if the user runs the following command
# Will only temporarily stop. It will again auto launch unless the service is explicitly stopped using launchctl unload command 
mariadb stop
#You can stop the launchctl process by
#sudo launchctl stop /Library/LaunchDaemons/com.startup.plist
#You can start the launchctl process by
#sudo launchctl start -w /Library/LaunchDaemons/com.startup.plist
  • A Gist with the source files is provided here.

That is it!

Do let me know if this works for you! Any suggestion for improvement will be most appreciated.

Sources:

  1. A Launchd Tutorial

Fahim Hossain

Written by

Director & CEO at ARITS Limited. More at https://www.aritsltd.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade