Difficulties with launchd executing python script - macos

I am trying to use launchd to run a python script every 10 minutes. This is easy with cron, but I have been trying for several hours to understand how to operate launchd and I have been unsuccessful. I am using a version of python located in /Users/turtle/bin/. Here is what my launchd file (com.foobar) looks like:
<?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.foobar</string>
<key>ProgramArguments</key>
<array>
<string>/Users/turtle/bin/python</string>
<string>/Users/turtle/code/baz.py</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>10</integer>
</dict>
</dict>
</plist>
When I run:
launchctl load /Library/LaunchAgents/com.foobar
I get:
launchctl: Couldn't stat("/Library/LaunchAgents/com.foobar"): No such file or directory nothing found to load
Can anyone help me? Thanks for your time.

StartCalendarInterval with the key Minute : the script run at the 10th minutes of every hour.
You must use StartInterval : job to be started every N seconds
<key>StartInterval</key>
<integer>600</integer>

launchctl load -w /Library/LaunchAgents/com.foobar
Does that work?

Related

OSX asdf Launch Daemon Does Not Have Access to Languages

I have a launch daemon plist that runs a python script. The problem is that it is unable to run the script because it does not have access to python.
I am trying to make a launch daemon to change mac address (https://github.com/feross/SpoofMAC)
Here is the plist file in /Library/LaunchDaemons:
<?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>MacSpoof</string>
<key>ProgramArguments</key>
<array>
<string>/Users/username/.asdf/shims/spoof-mac.py</string>
<string>randomize</string>
<string>en0</string>
</array>
<key>StandardOutPath</key>
<string>/Users/username/Projects/MAC/out.log</string>
<key>StandardErrorPath</key>
<string>/Users/username/Projects/MAC/err.log</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
The Error Log reads:
No version is set for command spoof-mac.py
Consider adding one of the following versions in your config file at
python 3.11.1
My tool_version does include Python, how can I make this work?
Okay, I kinda got it working. I moved the plist file from /Library/LaunchDaemons to /Library/LaunchAgents and it works because LaunchAgents run after the user is logged in. It's not exactly what I wanted, but it works.

How do I schedule a launchd task?

I want to run a python script every day at 7pm on a mac-based computer. I put together a script, but I'm not sure where to save it or where I can monitor progress. What can I do to turn this into a task-
<?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.example.nightlyscript</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python</string>
<string>/path/to/script.py</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>19</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>
According to this excellent article at townrdsdatascience.com, you need to put your property list in the ~/Library/LaunchAgents directory (which you can create in ~/Library if it doesn't already exist. The launchd man page further explains that you can put it in /Library/LaunchAgents if you want it to run for each user on your machine, or in /Library/LaunchDaemons to make it run across the whole system. Be sure to check your plist against the instructions in either of those sources -- I haven't looked to see if you've included everything that's needed. You'll also want to make your python script executable.

Need help getting launch daemon working on macOS

I have a launch daemon that I just can't get to work. It's supposed to run a script every day at 3 AM. The script works and I can run it manually without sudo. See below for the launch daemon (com.rsync.plist) and the output of the commands I ran to start it. If anyone has any ideas why it won't run, I would really appreciate 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.rsync</string>
<key>Program</key>
<string>/Users/xserve10/Documents/rsync.sh</string>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>
Xserve-10s-Mac-mini:Documents xserve10$ ls /Library/LaunchDaemons/com.rsync.plist
/Library/LaunchDaemons/com.rsync.plist
Xserve-10s-Mac-mini:Documents xserve10$ sudo launchctl load -w /Library/LaunchDaemons/com.rsync.plist
Password:
/Library/LaunchDaemons/com.rsync.plist: service already loaded
Load failed: 37: Operation already in progress
'''

rsync with launchd on OS X always gives me error code 255

I want to rsync my /var/repo backup to a remote machine when it changes.
I made a ssh key pairs to make my machine can ssh login to remote without password(ignore details).
I added a file com.ph.rsync2.plist in ~/Library/LaunchAgents.
The content is
<?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.ph.rsync2.plist</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/rsync</string>
<string>-avz</string>
<string>--rsh=ssh</string>
<string>/var/repo</string>
<string>flora#192.168.19.28:/var/ph_backups/</string>
</array>
<key>WatchPaths</key>
<array>
<string>/var/repo</string>
</array>
</dict>
Then I launchctl load com.ph.rysnc2.plist.
When /var/repo has any change, it will trigger rsync to work
but I always get the error log in Console.app
It reads like
11/3/15 2:15:26.399 PM com.apple.xpc.launchd[1]:
(com.ph.rsync2.plist) Service only ran for 1 seconds. Pushing respawn out by 9 seconds.
And I tried to move the rsync commands to a script, then let launchd exec my script. but it's still the same
I can't figure out which part of settings make all these fail.
Anyone can give me a clue?
Comments will mess up the formatting, so I'll post how to setup the StandardErrorPath key as an answer.
Modify your job definition 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.ph.rsync2.plist</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/rsync</string>
<string>-avz</string>
<string>--rsh=ssh</string>
<string>/var/repo</string>
<string>flora#192.168.19.28:/var/ph_backups/</string>
</array>
<key>StandardErrorPath</key>
<string>/tmp/com.ph.rsync2.plist.stderr</string>
<key>WatchPaths</key>
<array>
<string>/var/repo</string>
</array>
</dict>
</plist>
Check the file /tmp/com.ph.rsync2.plist.stderr after reloading and starting the job.

Launchd plist service is not shutting down

I have application i want to run as LaunchDaemon on OSX. My plist 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>KeepAlive</key>
<false/>
<key>Label</key>
<string>my.service</string>
<key>ProgramArguments</key>
<array>
<string>/servertest/MyService</string>
<string>-jvm</string>
<string>server</string>
<string>-nodetach</string>
<string>-outfile</string>
<string>out.txt</string>
<string>-errfile</string>
<string>err.txt</string>
<string>-verbose</string>
<string>-debug</string>
<string>-home</string>
<string>/System/Library/Frameworks/JavaVM.framework/Home</string>
<string>-cp</string>
<string>./lib/hsqldb.jar:./lib/myservice-wrapper.jar:./lib/commons-daemon-1.0.8.jar</string>
<string>my.service.DaemonMac</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/servertest/stderr.log</string>
<key>StandardOutPath</key>
<string>/servertest/stdout.log</string>
<key>WorkingDirectory</key>
<string>/servertest</string>
</dict>
</plist>
Service starts on load or when i call 'launchctl start my.service'. But it's not going down when i use 'launchctl stop my.service' or even unload plist. It remains in memory and runs as if nothing happened. Have no idea what could be the reason. Please, help!
Does your application daemonize itself (i.e. drop into the background)? If so, it's essentially detaching itself from launchd and hence preventing launchd from managing it.
EDIT: if the application isn't daemonizing itself, the next thing to look at is to see what launchd thinks is going on with launchctl list my.service. This should dump a list of properties of the daemon, including its PID (if launchd thinks it's running) and LastExitStatus (whether it exited successfully last time it ran). Does the PID correspond to the actual running process? Does the result change when you try to stop the service (esp. does the PID change to 0)? Does a process listing (e.g. with ps -axj) show any child processes living on after the parent exits?
Oh, and just to make sure: when managing LaunchDaemons, you need to use sudo launchctl (without the sudo, launchctl will try to manage LaunchAgents within your user session).
The file that worked for me is below. I've learned that my deamon must not detach itself from controling process and it has to be "OnDemand" so i could stop it when i want. I've made some shaman dances while working on it and though it's not clear to me at which point it began to work. Now it does.
<?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>KeepAlive</key>
<false/>
<key>Label</key>
<string>myserver</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/opt/MYServer/MYServer</string>
<string>-server</string>
<string>-outfile</string>
<string>/opt/MYServer/out.txt</string>
<string>-errfile</string>
<string>/opt/MYServer/err.txt</string>
<string>-verbose</string>
<string>-debug</string>
<string>-nodetach</string>
<string>-home</string>
<string>/System/Library/Frameworks/JavaVM.framework/Home</string>
<string>-cp</string>
<string>/opt/MYServer/lib/hsqldb.jar:/opt/MYServer/lib/my-wrapper.jar:/opt/MYServer/lib/commons-daemon-1.0.8.jar</string>
<string>my.service.DaemonMac</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/opt/MYServer/stderr.log</string>
<key>StandardOutPath</key>
<string>/opt/MYServer/stdout.log</string>
<key>WorkingDirectory</key>
<string>/opt/MYServer</string>
</dict>
</plist>

Resources