macOS: Run script on startup
MacOS uses launchd
as the daemon for running services and other daemons.
To run a script or a few on startup, you can interface with launchd
by writing a corresponding plist file. In my case, I want to run networksetup
to connect to a specific VPN on startup, but to only run it once so that I can switch to other ones later.
Essentially, whenever my computer starts up, I want to run
$ networksetup -connectpppoeservice VPN_Name
First, let’s figure out where the actual executable we want to use is:
$ which networksetup
/usr/sbin/networksetup
Next, we’ll create a small plist to that describes what we want to run, and how. A plist is a specific kind of XML file.
<?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>com.karltarvas.startup</string>
<key>OnDemand</key>
<false/>
<key>LaunchOnlyOnce</key>
<true/>
<key>UserName</key>
<string>karltarvas</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/networksetup</string>
<string>-connectpppoeservice</string>
<string>VPN_Name</string>
</array>
</dict>
</plist>
Most of the keys have self-explanatory names, the crucial bit here is to set LaunchOnlyOnce
to only run the service once.
ProgramArguments
is an array of strings corresponding to the command you want to run with its arguments.
Once the above is set up, save the file as a .plist
and move it into /Library/LaunchAgents/
, for example /Library/LaunchAgents/com.karltarvas.startup.plist
.
The file needs to be owned by root for launchd
to play nicely with it:
sudo chown root:wheel /Library/LaunchAgents/com.karltarvas.startup.plist
The final step is to load up the file:
sudo launchctl load /Library/LaunchAgents/com.karltarvas.startup.plist
When your system starts up, the above command will be run along with any other services you’ve set up.