Bash script automation in macOS
Scheduling bash scripts to be run at login using `launchd`

Machine Learning Engineer at datachef.co
Search for a command to run...
Scheduling bash scripts to be run at login using `launchd`

Machine Learning Engineer at datachef.co
Over the past few weeks, my team and I at DataChet worked tirelessly to craft and deliver an exciting new product: WordMentor.ai. As a language enthusiast and a proud member of the DataChef team, I am delighted to introduce you to Wordmentor—a powerf...

VSCode build's tasks for CDK deploy, destroy, and synth

Free but powerful solutions to uninstall any application

How to load/save datasets in Amazon SageMaker

Using NetworkX, PageRank, and Graph visualization

There are many scenarios in which bash scripts can be used to automate processes. Sometimes, I like to test things in Python. For instance, sometimes one of my colleagues asks me if something is possible in Python or how it is done. In those cases, I don't want to create a new project, but rather to create a new folder, throw a bunch of python files in, and figure out things. After some time, these test projects make a big mess in my directories, which I don't like.
To fix this, I made a bash script to remove all the files and folders that I have created under "temp" every time I boot my Mac. This blog post will describe how I managed to use macOS launchd to schedule a bash script to delete all the test files and folders.
launchd?As a Linux user or at least someone who has worked with Linux, you may be familiar with systemd. launchd is exactly the same, but it can do more like a job scheduler (corn replacement) and it is much more reliable than systemd.
launchd?Anyhow, to interact with Launchd, use launchctl in your bash shell. Same as the systemd and the systemctl commands, isn't it? You can see more information about launchctl by typing man launchctl in your terminal window.
launchd configuration files look like?Having learned about the concept of launchd and its interface launchctl, it is now time to understand how we can define a new configuration for this. In contrast to systemd, which uses TOML config files, launchd makes use of plist files to define a configuration. Below is an example:
<?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>Label</key>
<string>com.example.hello</string>
<key>ProgramArguments</key>
<array>
<string>hello</string>
<string>world</string>
</array>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
launchd configuration files?There are three locations in which you can store a launchd configuration file. If your application is supposed to run as a daemon service, you can store it under /System/Library/LaunchDaemons/. If your application is supposed to run whenever a user logs in, you should store it under /Library/LaunchAgents. Finally, If your application is supposed to run whenever a specific user logged in it must be stored under ~/Library/LaunchAgents.
It's time to set up the automation now that we know how launchd works. Let's create the bash script file first:
rm -rf $HOME/projects/temp && mkdir $HOME/projects/temp
You need to save this script to ~/.scripts/loginscript.sh. The script will delete the files and folders in the temp folder every time you run it. We will now need to create the config file for Launchd so the script runs every time we log in.
<?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>Label</key>
<string>com.user.loginscript</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>PATH-TO-HOME-DIRECTORY/.scripts/loginscript.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Let's save this to ~/Library/LaunchAgents/com.user.loginscript.plist. Before registering it to launchd we first need to get the user id as it needs by launchd:
id -u
Copy the output and run the command below to register the configuration to launchd:
sudo launchctl bootstrap gui/<USER-ID> ~/Library/LaunchAgents/com.user.loginscript.plist