running launchd scripts on interval basis

I am trying to get a launchdaemon to run every 5 minutes. According to the documentation, StartInterval seems like it should do this:

StartInterval <integer>
This optional key causes the job to be started every N seconds. If the system is asleep, the job will
be started the next time the computer wakes up. If multiple intervals transpire before the computer is
woken, those events will be coalesced into one event upon wake from sleep.

But for me, when I type in "launchctl load <plist file name>" it just runs once and never again. By the way, I also have the problem of getting this to run at startup on it's own (that's why I'm doing it manually for now) but since I can't even get the script to run properly, that is an issue I'll have to address later.

The script I am trying to run checks the timestamp of an image file and is supposed to reboot the program if it's not updating. Here is the plist file which is supposed to run the script every 5 min. What am I doing wrong with it?


<?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.sns.sentinel.monitor</string>
<key>KeepAlive</key>
<false/>
<key>StartInterval</key>
<integer>300</integer>
<key>WorkingDirectory</key>
<string>/Applications/oc4j/</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>./keepRunning.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>root</string>
</dict>
</plist>

Posted on Mar 29, 2010 11:10 AM

Reply
10 replies

Mar 30, 2010 8:46 AM in response to netdeep

You didn't specify where you installed the daemon. Presuming that it's in /Library/LaunchDaemons, you don't need to specify the user... You will be running as root.

Your Program arguments should just look like:
<key>ProgramArguments</key>
<array>
<string>keepRunning.sh</string>
</array>

I'm not sure without testing it, but the KeepAlive FALSE might be causing you problems. I'm a little unclear on the exact interaction between LaunchInterval and KeepAlive, but in general, I think you'd want KeepAlive to be TRUE.

Mar 30, 2010 12:48 PM in response to Brian Nesse

Thanks for the response. I'll tried changing those arguments but it's still not working properly. I'm wondering if perhaps the script which gets run by the daemon isn't exiting and so it doesn't run the check every five minutes like I want. The script launches a program that should keep running. Here is the script being launched by the daemon:


#!/bin/bash

FILES="/Library/WebServer/Documents/sentinel/beta/Energy and_Power_onTarget-img.png"

for f in "$FILES";

do

if test `find $f -mmin +2`; then
echo "Old file needs to be shut down $f";
kill -6 `ps -ef | grep 'oc4j.jar' | egrep -v grep | awk '{print $2}'`;
kill -6 `ps -ef | grep 'Sentinel.app' | egrep -v grep | awk '{print $2}'`;
else
echo "File up to date $f";
fi

done

sleep 10

PROCESS=oc4j.jar

if ps aux | grep "$PROCESS" | grep -v grep >/dev/null ; then
echo Process $PROCESS is running
else
echo "$PWD"

Mar 31, 2010 8:37 AM in response to netdeep

You state that
The script launches a program that should keep running.


I see no evidence that anything is being launched in that script... only killed.

If the script was launching something though, that could keep the script from exiting unless you use the control operator & to execute it in the background.

Check the system log for any output from launchd pertaining to your identifier. You might try adding the Debug key to your .plist and see if you get any useful output (also in syslog).

Apr 1, 2010 12:54 PM in response to Brian Nesse

Oops, I am using a terminal to remote into the server and sometimes it drops stuff from copy and paste. Here's the end of the script:

if ps aux | grep "$PROCESS" | grep -v grep >/dev/null ; then
echo Process $PROCESS is running
else
echo "$PWD"
echo keepRunning Process $PROCESS has successfully been stopped Restarting it ...
java -jar /Applications/oc4j/j2ee/home/oc4j.jar &
fi


I added the '&' just now to see if that would work but it doesn't ever launch the jar file that way.

I also tried adding the '&' to the plist file but it doesn't even run that way.

<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>./keepRunning.sh</string>
<string>&</string>
</array>

instead it gives me the error:

for command "launchctl load com.sns.sentinel.monitor":

launchctl: propertyList is NULL
launchctl: no plist was returned for: com.sns.sentinel.monitor
launchctl: no plist was returned for: com.sns.sentinel.monitor
nothing found to unload

Apr 2, 2010 8:38 AM in response to netdeep

This should be the correct approach
java -jar /Applications/oc4j/j2ee/home/oc4j.jar &

and I don't know why that wouldn't work unless, the following is interfering.

As I noted above, your Program arguments should just look like:
<key>ProgramArguments</key>
<array>
<string>keepRunning.sh</string>
</array>

launchd, given a path to a script, will just execute it. You are actually sub-launching sh, and then executing a script within it.

Jun 8, 2010 12:33 PM in response to Brian Nesse

Okay, I know this issue has not been active for a while, but I never did get it resolved. Some other things came up and I was able to get it working by logging in and launching the app from my own user area but obviously that is not a viable long term solution.

So, to bring the situation up to date, the '&' does not work in plist files just by itself. I tried \& instead thinking that it might be an escape character, but that didn't work either. I'm not sure that the & really needs to be there anyway. I can get the plist scripts to work fine using launchctl, but the main issue now is that when launchd runs these daemons at startup, they never work right. They either get into some sort of race condition (lots of "throttling respawn" messages) or one time when they did work, the programs eventually crashed with lots of LSOpenFromURLSpec errors.

I've tried launching them with scripts and without scripts and nothing seems to work. Essentially I have to three things:

A) Launch a java server
B) Launch an AIR application that communicates with the server
C) Check an image file to make sure it's timestamp is not more than 10 minutes old. If so, then I kill A and B and launchd should restart them.

Is there something wrong with my approach? Shouldn't launchd be able to accomplish this?

Jun 9, 2010 5:55 AM in response to foilpan

Well I finally realized something that was going on with the script which was causing it problems. The particular plist file which is not working is this one:

<plist version="1.0">
<dict>
<key>Label</key>
<string>com.sns.sentinel.air</string>
<key>KeepAlive</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>/Applications/oc4j/restartSentinel.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

And restartSentinel.sh is very simple:

echo Process Sentinel.app is being restarted...
open /Applications/oc4j/j2ee/home/applications/Sentinel/Sentinel.app;

What I noticed is that when this script runs, unlike the other process (launched via the 'java -jar oc4j.jar' command), the script releases back to the prompt. So I'll bet that as far as launchd is concerned, the process has exited or finished. It therefore most likely wants to immediately restart it. This would explain all the 'throttling respawn' messages in the log.

So in short, the paths are correct, but I need to avoid the respawn problem now. Any ideas on how to do this?

Jun 9, 2010 7:56 AM in response to netdeep

Well, I added the -W option to the script and that seems to take care of the respawn problem. Now, I've run into 2 more problems however. For some reason, Sentinel.app still gets restarted every so often (between 10-30 min). I have no idea why. The app is not crashing on its own. It seems to crash every time someone uses screen sharing to log into the machine (it's running on a server and that is the only way to access it) but it also crashes at other times as well according to the log.

Jun 9, 2010 9:57 AM in response to netdeep

So all the crashes/restarts seem to occur around using screen sharing. Even worse, if any other user besides me tries to log out, launchd prevents log off or restart. The plist files have to be unloaded first. This is extremely inconvenient to say the least. All plist files are 644 for permissions with an owner of root and a group of wheel. Again it seems to be only the Sentinel.app that's failing. The jar runs forever like a champ, though it does prevent log out.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

running launchd scripts on interval basis

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.