Launchd task unloads when computer restarts - macos

I have a simple launchd plist file that I am using to run a shell script that is designed to restart the computer:
<?xml vesion="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.sag95.restartscript</string>
<key>KeepAlive</key>
<false/>
<key>RunAtLoad</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/Users/sag95/Desktop/Scripts/restartscript.sh</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</plist>
The script file is a single line force restart command(password in real file, not placed here):
echo <password> | sudo -S shutdown -r now
Once I load the plist file using
launchctl load com.sag95.restartscript.plist
it appears in the list (launchctl list). Currently I have the plist file to run the script every 5 minutes. After the 5 minutes of loading, the script is called the first time and subsequently restarts the computer. Once I login, the launchd plist file is no longer in the list (launchctl list). I waited 30 minutes and it hasn't run again to restart my computer.
My question is why is the com.sag95.restartscript plist file unloading after the restart/force reboot?

launchctl load only loads it for the current session. Next time you log in, it loads your list of launch agents from /System/Library/LaunchAgents/*.plist, /Library/LaunchAgents/*.plist, and /Users/sag95/Library/LaunchAgents/*.plist. If the file isn't in one of these folders, it will not get loaded.
Assuming you want it to run only when you are logged in, place the file in /Users/sag95/Library/LaunchAgents. If you wanted it to run for any logged in user, put it in /Library/LaunchAgents instead (but with this specific script, the password will only work for your account, so this wouldn't be useful).

Related

My personal launchagents have stopped working in MacOS Ventura. Any ideas?

I have a number of launch agents I've written over the years to automate some simple tasks, like rsyncing my music and photos from my laptop to my NAS. Recently I've noticed that they have stopped running daily like they used to. Instead, they're only running when I log in. Here's a sample launchagent:
<?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.mwheinz.backup_photos</string>
<key>Program</key>
<string>/Users/michaelheinz/bin/backup_photos</string>
<key>StartInterval</key>
<integer>86400</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
When I run them with "debug" it says they are configured to run "at launch":
~ ยป sudo launchctl debug gui/501/com.mwheinz.backup_books
Password:
Service configured for next launch.
Any suggestions? One thing I've noticed is that launchd now insists I refer to my agents as "gui/501/<label>" instead of just "<label>".
Okay - I figured it out. The problem for me was that the syntax for the plists changed at some point. This syntax:
Program
/Users/michaelheinz/bin/backup_books
StartInterval
became this syntax:
ProgramArguments
/Users/michaelheinz/bin/backup_books
StartInterval
I changed all my plists and they started working again.

Why won't LaunchAgents run my Automator app?

I'd like to run an app I created via Automator every 5 minutes, so I placed the following com.user.wilson.plist file in this folder:
/Library/LaunchAgents
<?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.wilson</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/open</string>
<string>-a</string>
<string>/Users/paul/Documents/Wilson/Script/mt-wilson-background_app</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</plist>
Then, I loaded it using the following command in the terminal:
launchctl load Library/LaunchAgents/com.user.wilson.plist
but for some reason, the app never runs.
I can, however, successfully run the app using this command:
/usr/bin/open -a /Users/paul/Documents/Wilson/Script/mt-wilson-background_app
Any ideas why the .plist file won't do what I'm expecting it to?
In order to see what's going wrong, you can add a log file in your plist 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>Label</key>
<string>com.user.wilson</string>
<key>StandardErrorPath</key>
<string>/Users/paul/Documents/Wilson/Script/err.log</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/open</string>
<string>-a</string>
<string>/Users/paul/Documents/Wilson/Script/mt-wilson-background_app</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</plist>
Note: For the modifications to take effect, unload and load again:
launchctl unload Library/LaunchAgents/com.user.wilson.plist
launchctl load Library/LaunchAgents/com.user.wilson.plist
Typically, if the err.log says it can't find your app, it means it's a permission issue.
I would suggest you try to move your app from /Users/paul/Documents/Wilson/Script/mt-wilson-background_app to /Users/paul/Documents/mt-wilson-background_app
Then update your plist accordingly, unload an reload your plist, is it working better now?
I ran into nearly the exact same problem. I finally (FINALLY!!!) found a cure that worked for me.
Originally, the broken version of the .plist launch agent that wouldn't run no matter what I tried was in /Library/LaunchAgents. Moving the agent to /Users/[me]/LaunchAgents eliminated the "Application Not Running" error.
It seems counterintuitive since the root agent should be able to run everything from any location, but I can only guess that AppleScript's check to see if an app is running or not is user account-dependent somehow. I'm betting there's something you can add to the AppleScript to actually fix this the "right" way, but this works well enough for me, so I'm taking the win.

Launchd runs with manual "launchctl start", but not on StartCalendarInterval

I have a very simple Launch Daemon, com.daily.vocab.plist, which simply runs a basic script. It is supposed to run every day at a certain time (using StartCalendarInterval), but I can't get that to happen. Many posts online are saying it runs a minute or two off, but for me it just never runs.
I have been setting the run time to be 5 minutes in the future while I am testing, and now have it set to run at the 0th second of every minute, just so I can get it to work. Once it's working, I will set it to my desired daily run time.
As advised in this tutorial, it is saved in /Library/LaunchDaemons. I loaded it manually with launchctl load /Library/LaunchDaemons/com.daily.vocab.plist. I do in fact see it has loaded when I run launchctl list. When I manually tell it to run with launchctl start com.daily.vocab, it works immediately as expected. The only issue is that the StartCalendarInterval seems to be ignored. I am on Mavericks on my Macbook.
Here is the file: com.daily.vocab.plist
<?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.daily.vocab</string>
<key>Program</key>
<string>/Users/MGS/developer/projects/vocab-sms/scripts/DEvocab.sh</string>
<key>StartCalendarInterval</key>
<dict>
<key>Second</key>
<integer>0</integer>
</dict>
</dict>
</plist>
Ideally, I believe I want it to run at 7:15am every day making the StartCalendarInterval section be instead:
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>15</integer>
</dict>
If you could even share an example of a LaunchDaemon you got to work using StartCalendarInterval and every step you made to make it work (e.g. running launchctl load x.x.x.plist), that would be really helpful!
Solution: This local daemon should actually be a user agent, so it needed to be saved in and loaded from the ~/Library/LaunchAgents directory. From there, I also needed to unload the agent and reload the agent.
NOTE: Daemons/Agents do not automatically update in launchd until you unload/load. You can't just save the updated .plist and expect it to work!
launchd plists saved in /Library/... are daemons / agents in the local domain and have to be loaded with sudo. Without sudo you're loading the daemon in the user domain which doesn't match the actual path.
Since you are calling a script in the user domain anyway, save the script in ~/Library/LaunchAgents (it's not a daemon). The plist syntax is supposed to be correct.
will have to change the permission for the bash file
chmod u+v /Users/MGS/developer/projects/vocab-sms/scripts/DEvocab.sh

cannot get real hostname when launching shell script at boot with launchd

I'm trying to run a shell script at boot with launchd, via a plist file in /Library/LaunchDaemons (on 10.8.x, if that matters):
<?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>testD</string>
<key>ProgramArguments</key>
<array>
<string>/Users/lfriedman/cuda-stuff/sw/gpgpu/build/scripts/testing/testD.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>UserName</key>
<string>lfriedman</string>
<key>AbandonProcessGroup</key>
<false/>
<key>StandardOutPath</key>
<string>/tmp/testD.out</string>
<key>StandardErrorPath</key>
<string>/tmp/testD.err</string>
</dict>
</plist>
Inside the shell script is a call to 'hostname -s'. If I run the script manually, everything works fine. If I run the script via cron, everything works fine. However, when it runs at boot via launchd the value returned from 'hostname -s' is always (erroneously) returned as 'localhost', rather than the actual hostname of the system. If I tweak the plist to run the script at a time other than at bootup, it also does the right thing and returns the actual short hostname of the system. This leads me to think that there's some sort of race condition going on where launchd is firing off its jobs before the network subsystem of the OS is fully running.
Is there some special way to ensure that the OS is "fully" booted before launchd runs a job? Or a way to force a delay inside the plist file before the program is invoked?
Unfortunately, launchd doesn't have a way of setting dependencies, so you'll need to have the delay in your script. In a shell script, an easy way to check for networking is:
#!/bin/bash
# Example Daemon Starter
. /etc/rc.common
CheckForNetwork
while [ "${NETWORKUP}" != "-YES-" ]
do
sleep 5
NETWORKUP=
CheckForNetwork
done
# Now do what you need to do.
You can see more info at the following link:
http://blog.slaunchaman.com/2010/07/01/how-to-run-a-launchdaemon-that-requires-networking/

Creating a timed launchd plist

I'm trying to create a plist for the LaunchAgents folder that will run perpetually and call a shell script every 30 seconds. It started with a template that I got here and that I tried to tailor to fit my needs, but it's still not working. Any help?
<?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.Intel_Watchdog</string>
<key>ProgramArguments</key>
<array>
<string>/Library/A_Intel_WATCHDOG/A_WatchDog.sh</string>
</array>
<key>StandardErrorPath</key>
<string>/dev/null</string>
<key>StandardOutPath</key>
<string>/dev/null</string>
<key>StartInterval</key>
<integer>30</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Thanks so much!
I dropped this in my LaunchDaemons directory, and it worked fine. So, here're some things to check:
Is the .plist getting loaded? Note that the contents of the LaunchAgents folders are loaded at login, so you either need to log out and back in, or manually load it with launchctl load ~/Library/LaunchAgents/com.Intel_Watchdog.plist (or whatever/wherever the file is). You can check its status with launchctl list.
Is /Library/A_Intel_WATCHDOG/A_WatchDog.sh executable? Check the system log (/var/log/system.log) to see if launchd is having trouble launching it.
Is the script running into trouble before it does its job? Try adding date >>/tmp/watchdog.log to it, right after the shebang, and see if anything appears in /tmp/watchdog.log. If it does, try changing the StandardErrorPath and StandardOutPath to an actual file so you can see what's going on as the script runs. Note that you'll have to unload and reload the .plist to get the change to take effect (logging out and back in would do it).
Finally, although it shouldn't cause trouble, your label doesn't follow the standard convention (unless you actually own the domain Intel_Watchdog.com). If this is for local-only use, name it something like local.Intel_Watchdog instead. If you're going to publish this item, you should base the label on a domain you own (in reverse order, with ".Intel_Watchdog" added to the end) -- see Wikipedia's entry on the reverse domain name system.

Resources