1

I have a script which runs flawlessly under a normal interactive shell, but which frequently has errors when run as a user LaunchAgent.

Is there a way to manually, and ideally interactively, run a command exactly as it is run by launchd, to make it easier to debug?


To be clear, the script in question does work (intermittently) under launchd. It is not as simple as missing paths. I know that launchd uses a more spartan environment, but the situation is now:

  • There are frequent intermittent failures under launchd
  • I have never reproduced these failures in my user shell

As is common, there are numerous differences in environment between my fully configured user shell and the minimal launchd context, so it is very difficult to guess what difference might be at fault (or whether it even is an environment variable that causes the difference), which is why I was hoping to find a way simply to run commands manually and interactively, exactly as they would run under launchd. I am surprised that there is not a launchd run subcommand or similar.

  • Are you writing a .plist file from "scratch", or are you using the LaunchControl app? – Seamus Jul 7 at 15:25
  • 1
    What kind of errors? Can you edit your post and show us the error messages that you are receiving? The typical issue that users run across is launchd's PATH . – fd0 Jul 7 at 15:40
  • AFAIK there isn't such a thing, but if you add the errors you get (and the plist you use) people might be able to figure out what is wrong. – nohillside Jul 8 at 7:42
  • Thanks for the responses so far. I was hoping for a simple, generic answer about how to manually run (and inspect / interact with) a launchd execution. Given that that seems not to be possible, I will work to revise with a reproducer. Unfortunately the failure is in a complex Pyppeteer-based script which logs into (and therefore requires) a Roam Research account, so it is not trivial simply to share for others to reproduce. – jrk Jul 8 at 21:46
2

Launchd jobs run with a default shell that does not import any of the typical environment variables you'll see in an interactive shell; in particular the PATH variable lacks any directories that your interactive shell might have added, which can cause headaches. You can work around that two ways:

  • By making your script as thoroughly generic as possible: using full path specifications to every command and utility, and explicitly setting variables as you need them rather than relying on the environment.
  • By adding an EnvironmentVariables dictionary to your launchd plist file and specifying the environment there.

The second looks like this:

<?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>VARIABLE_NAME_1</key>
           <string>variable_contents</string>
           <key>VARIABLE_NAME_2</key>
           <string>variable_contents</string>
    </dict>
    < ... >
</dict>
</plist>
| improve this answer | |

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .