Black title card reading "Example of creating an Automator job", subtitled "launchd task scheduler"
Back to Blog
DevOps & Infrastructure
November 20, 2019
Fahim Hossain

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

How to run a script automatically at startup on macOS using a launch daemon, written for anyone arriving from Linux and finding it unfamiliar.

Black title card reading "Example of creating an Automator job", subtitled "launchd task scheduler"

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.

Running infrastructure like this in production? ARITS does Kubernetes and DevOps platform engineering so your team can ship without babysitting servers.

Need extra engineers, or a team to run the build?

Tell us the shape of the work and your deadline. You will get a straight read on what it takes and what it will cost, from a team that has shipped 400+ projects out of Dhaka and London.

Cookies

We use cookies to see how people find this site and to measure our ads. You can turn those off — everything here still works. Privacy policy

Necessary

Keeps the site working and remembers this choice.

Always on

Analytics

Anonymous stats on which pages get read, so we know what to write next.

Marketing

Lets us measure which ads brought someone here.