MacOS – How to run multiple commands on reboot using launchctl/plist

launchdmacos

In OS X, you can write a plist file in ~/Library/LaunchAgents/ (or something similar, depending on what permissions/users you like it to be operated on), and load it using launchctl to make it function on reboot. However, is it possible to define multiple commands in the plist file, and if that's the case, how can I define it?

For example, suppose that I want to run a series of Python programs, such as:

python first_script.py

And then I want to run the script after the first script is done (so I cannot just define those two scripts in two different plist files, since it doesn't guarantee which one to be executed first), I want to run this script:

python second_script.py

I use OS X Mavericks 10.9.2.

bonus

This is not what I want to do right now and comes from nothing but curiosity, but is it also possible to execute the second program depending upon the result of the first program? So for example:

python first_script.py

And if this script succeeds:

python second_script.py --result true

And if it fails:

python second_script.py --result false --reason XXX

Best Answer

Run a shell command that starts the other commands:

<?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>some.label</string>
  <key>ProgramArguments</key>
  <array>
    <string>bash</string>
    <string>-c</string>
    <string>python first_script.py;python second_script.py</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Or change the ProgramArguments key to

<key>Program</key>
<string>/path/to/script</string>

and use a script like this:

#!/bin/bash

output=$(python first_script.py 2>&1)
if [[ $? = 0 ]]; then
  python second_script.py --result true
else
  python second_script.py --result --false --reason "$output"
fi