Applet as root via do shell script, but not usefully via launchd

I have an AppleScript applet comprising only one little handler that needs to run as root because it’s the only way I can think of to make my other, main AppleScript applet—which will call that handler—work, for a friend who (foolishly) insists on having his Mac admin account with a blank password. sudo doesn’t work with a blank password, and if I store his blank password in his Keychain, then AppleScript ultimately will:

do shell script "[command]" password "" with administrator privileges

…which still puts up the system password entry dialog, which I’m trying to avoid after it gets stored in the Keychain.

I can get this in AppleScript to launch the little companion AppleScript applet:

do shell script "bin/sh -c \"" & quoted form of "/Users/schmye/Desktop/Companion Applet.app/Contents/MacOS/applet" & "\" &> /dev/null &" with administrator privileges

…which nicely “detaches” from Script Editor or from another AppleScript applet that invokes it. And the launched applet will successfully execute its handler’s root-required command when my other, main AppleScript applet calls it:

tell application "Companion Applet" to theHandler()

I need the little companion applet to be running as root at all times, but I can’t seem to get it to work when launched from a launchd job. I’m using Launch Control to help write my launchd job as a root Global Daemon. A launchd job is not itself a shell, so that’s why for comparison & proof-of-concept purposes, I (unnecessarily) wrote the above do shell script with a sub-shell, but which indeed is necessary in my launchd command:

That launchd job does launch my little companion applet, but calling its handler from my other, main applet this time only returns an Apple Events timeout error after the usual delay. Appending the “run-in-background” ampersand command:

…doesn’t cause it to “detach” like it did when I ran it above in the do shell script, the absence of which I thought at first was causing the Apple Events timeout error because possibly launchd was hanging-on to it and not sharing it with my other applet calling the handler — but in fact, the companion applet wouldn’t even launch at all with the addition of the backgrounder ampersand suffix.

This is my plist that got created in /Library/LaunchDaemons. Any launchd jockeys in the house who can tell me what I’m getting wrong?

AppleScript: 2.1.2
Operating System: Mac OS X (10.6.8)

I would say create temporarily a password for sudo, open console.app and load the plist manually and see what error shows up. I expect that an error will popup because it want’s to connect to the window server but the user is not defined as an console user. Or forbidden because the daemons are not allowed to connect to the window server. Easiest workaround is using sudo, launching it as an agent and adding the applet to the sudoers file so it won’t be prompted for a password.

^ Many thanks! Following your troubleshooting suggestions, I did this:


do shell script "echo [my password] | sudo -S launchctl load -w '/Library/LaunchDaemons/CompanionApplet.plist' "

delay 1

try
	with timeout of 1 second
		tell application "Companion Applet" to theHandler()
	end timeout
on error errorMessage number errorNumber
log " Error #" & errorNumber & ": " & errorMessage & space
end try

do shell script "echo [my password] | sudo -S launchctl unload -w '/Library/LaunchDaemons/CompanionApplet.plist' "

…and got these results:

tell current application
	do shell script "echo [my password] | sudo -S launchctl load -w '/Library/LaunchDaemons/CompanionApplet.plist' "
		--> ""
end tell
tell application "Companion Applet"
	theHandler()
end tell
	(* Error #-1712: Companion Applet got an error: AppleEvent timed out. *)

tell current application
	do shell script "echo [my password] | sudo -S launchctl unload -w '/Library/LaunchDaemons/CompanionApplet.plist' "
		--> ""
end tell

…and Console’s All Messages had nothing whatsoever in-between the two sudo commands:

I wouldn’t intuitively have thought that an AppleScript applet with commands containing no user interaction would involve the window server you mentioned, but there are more things in heaven and earth than are dreamt of in my philosophy, so I moved my plist to /Library/LaunchAgents (matching ownership & permissions), making it a root Global Agent instead of my present root Global Daemon, but, alas, I got the same Error #-1712: Companion Applet got an error: AppleEvent timed out. Now, what?

I was getting ready to say that I thought that editing the sudoers file only could add users, but I knew that you know what you’re talking about, so I googled around and, by gum, I eventually found that there indeed is a syntax to restrict only adding an app filename to the sudoers file, e.g.,:

[originally posted July 26, 2017 9:00:21 PM EDT]

Edit: Jul 27, 2017 5:00 PM EDT

Hold the presses: Some hours later I ran the above test script with the plist as a root Global Agent, and it got through!—it performed the handler. Then I turned right around and ran it again, and it’s back to the AppleEvent timeout error, and subsequently. What the heck?

Edit: Jul 27, 2017 6:48 PM EDT
A pattern is developing here: An hour or so later, I again ran the script (and again, with my launchd job as a Launch Agent) and it once again—one time only—didn’t exhibit the AppleEvent timeout error and the handler in the companion applet executed properly. But adding to the pattern I’ve tentatively identified of the launchd-launched companion applet accepting a tell statement one time after the elapse of some period of time, I can also reproduce every time the companion applet not quitting upon unloading the launchd job. Whatever is letting the tell statement get through launchd’s “barrier” is also stopping it from quitting as it does when the AppleEvent timeout error does occur before unloading the job. Curiouser and curiouser.