1

I have written a small applescript that I would like to run automatically every 2 hours. I have thus written the following launchd daemon (probably it is an agent):

<?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>Disabled</key>
        <false/>
        <key>Label</key>
        <string>com.zerowidth.launched.aspect</string>
        <key>Program</key>
        <string>/usr/bin/osascript</string>
        <key>ProgramArguments</key>
        <array>
                <string>osascript</string 
                <string>/Users/***/my_script.scpt</string>
        </array>
        <key>StandardOutPath</key>
        <string>/Users/***/file_log.log</string>
        <key>RunAtLoad</key>
        <true/>
        <key>ThrottleInterval</key>
        <integer>7200</integer>
        <key>KeepAlive</key>
        <true/>
</dict>
</plist>

Then I have opened terminal and done

launchctl load ~/Library/LaunchAgents/com.zerowidth.launched.aspect.plist 

It worked fine, but only once and not every two hours. Checking on Console I got the following messages (and many more actually):

com.apple.xpc.launchd[1] (com.zerowidth.launched.aspect): This service is defined to be constantly running and is inherently inefficient.

Dec 16 17:02:25 Air-of-myself-2 com.apple.xpc.launchd[1] (com.zerowidth.launched.aspect): Service only ran for 7 seconds. Pushing respawn out by 7193 seconds.

Can you help me in understanding what is going on please? How can I run the apple script every two hours?

Thanks.


EDIT. I add, following Robert's advice, the Python script and the Applescript.

Here is Python script. It asks the console to run the LocateMe command and from this it obtains the latitude and longitude of the place where I am. Then calls an API to obtain sunset and sunrise time of this place. Finally a small function decides whether it is day (sunrise < now

output = os.popen('/Users/***/Desktop/LocateMe').read()
###I extract my coordinates 
coord = output[1:25]
lat = float(coord[1:12]) ###latitude
long = float(coord[13:25]) ### longitude

my_sunrise, my_sunset = get_ris_and_set(lat, long) ##this function calls an API that gives sunset and sunrise time in the position given by (lat,long)
my_sunset1 = my_sunset.time()
my_sunrise1 = my_sunrise.time()

result = str(is_day(now.time(), my_sunrise1, my_sunset1))
### compare the time now and returns true if it is day false otherwise    
with open('/Users/***/Desktop/log_file.txt', 'a') as f:
        print(result, file=f)
sys.exit()

Here is the Applescript: it runs the Python script above and reads the boolean value (if it is day or not). Then it checks if the dark mode on Mojave is on and it switches if needed.

tell application id "com.apple.systemevents"
tell application "Terminal"
    do shell script "/usr/local/bin/python3 /Users/***/Desktop/python.py $@"
end tell

tell appearance preferences
    set value to do shell script "tail -n 1 /Users/***/Desktop/log_file.txt"
    if dark mode is true and value = "True" then
        set dark mode to false
    else if dark mode is false and value = "False" then
        set dark mode to true
    else
        return
    end if
end tell
end tell
  • where is your end service command for it to be able to run again. – Ruskes Dec 16 '18 at 16:38
  • @Buscar웃 I am sorry but I am a newbie with launchd... I am not sure I have understood your comment. Could you please be a bit more explicit, please? Thank you very much for your kind help! – Romeo Dec 16 '18 at 16:53
  • launchd is properly running your script every two hours. However, it appears that your script continually runs and it's inefficient to run a continually running script at a set interval. What is your script supposed to do? – Allan Dec 16 '18 at 18:27
  • Mmm, I see. Thanks for your answer! My applescript runs a python script (!) which basically checks the current time and decides whether it is day or night (depending on the my position). Then it turns on/off Mojave Dark-Mode. How can I handle this in a better way? Maybe I should set an instruction inside the Applescript so that it does not run continuously... Thanks! – Romeo Dec 16 '18 at 18:30
  • Assuming your Python script runs, checks the date, does what it needs to then exits, then it doesn't run continually (unless you have an error where it's waiting for something.) Also, why to you have KeepAlive set to true? – Allan Dec 17 '18 at 0:35
2
+50

Isn't StartInterval the key for running periodically? In your case, set to 7200 (seconds)?

https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#//apple_ref/doc/uid/10000172i-SW7-SW7

  • Fantastic! It works exactly as I wanted, thank you very much! Btw, do you know what is the difference between StartInterval and ThrottleInterval? If you have read the code above, do yo think there is a lighter way to implement it? Thanks a lot, I plan to accept your answer and give to you the bounty (if no other answer appears in the meanwhile). Thanks! :-D – Romeo Dec 22 '18 at 16:45
  • I believe ThrottleInterval is how frequently your process is allowed to spawn; i.e., how soon it would be allowed to run again. However, its actually undocumented, so I wouldn't mess with it at all if you don't have to. – Geoff Nixon Dec 22 '18 at 21:31
1

We need to see all your scripts. [ if they are short, or simply before posting. ] You could invoke the python script from your plist. Perhaps you have redundant loop mechanisms in your scripts. You should put debug information in your scripts. Write out to a file in your applescript and phython script. Put something like "date >> mylogfile#1" in your applescript's do shell script. Checking out the syntax in the terminal:

mac $ date >> mylogfile#1
mac $ date >> mylogfile#1
mac $ date >> mylogfile#1
mac $ cat mylogfile#1 
Sun Dec 16 19:32:17 EST 2018
Sun Dec 16 19:32:21 EST 2018
Sun Dec 16 19:32:23 EST 2018

a little more heft might be helpful. This way you can tell if your script is being invoked.

You can do this entirely in applescript. Scroll down to "Now we need to keep running this command periodically in the background. "

http://scriptingosx.com/tag/stay-open/

notice how the idle routine is returning the time after which the idle handler will be invoked again.

Robert

  • Thank you very much for your interest and sorry for late reply. Good point, with idle it works. But I honestly do not like too much the idle solution. At the end is an app that I have to run and remains always open in background on Desktop... in any case, I would like to set it with launchd so that I can learn something new. I will follow your advice and put the whole script in the OP. I hope that you can help me. Thank you very much. – Romeo Dec 21 '18 at 20:20

You must log in to answer this question.

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