0

I can't seem to find the answer that combines the two things I need: on startup and in the background.

So I've made a script that checks the battery percentages of the mouse and keyboard for my mac (Catalina). The script runs indefinitely performing a check every 30 minutes.

Currently, my best option was that I created a .app file using automator that runs the python script. I then put this in 'login items' and it runs on startup, very good.

The only problem with this is that I now get an annoying cog that spins around permanently in the menu bar.

I've read that using launchctl would allow the script to run in the background, but apparently you can't run it from startup this way. Is that true?

Does anyone know how I can achieve both requirements: having the script run on startup, and have it run without me noticing that it's running?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • 1
    @TigerhawkT3 OP's OS is macOS (Catalina), not Windows. [This answer](https://stackoverflow.com/a/36378007/8280773) seems more suitable. – Leônidas Villeneuve Dec 21 '20 at 22:31
  • @LeônidasVilleneuve I wouldn't advise any answer that suggests cron -- launchd is the process supervisor on MacOS, and is built for the purpose (of making sure things run on boot), as opposed to the different purpose `cron` has (of making sure things run at specific times). Better to go launchd->script than launchd->cron->script; fewer moving parts is better than more. However, while that _answer_ isn't ideal, the _question_ is directly on-point. – Charles Duffy Dec 21 '20 at 23:58

1 Answers1

0

I use launch-agents to achieve similar jobs, jobs that i need to run when in my login.

In this case you should change your script so that it does not loop forever, but does the work once and schedule this script to be executed periodically every 30 mins.

Create a small plist file in ~/Library/LaunchAgents/your-service-name.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>your.namespace.goes.here</string>
    <key>ProgramArguments</key>
    <array>
        <string>yourscript-path-goes-here</string>
        <string>some-args</string>
    </array>
    <key>StartInterval</key>
    <integer>1800</integer>
</dict>
</plist>

Load the launch agent launchctl load -w <path_to_the_plist_file>

Remember to set up proper environment variables in the plist file, since it does not inherit the environment variables from your shell, since it is not run within that scope.

Refer this link for more info on launchagents and daemons.

I have noticed that when the launch agent framework invokes my script and the script exits quickly, the fw thinks the script dint work properly, So it restarts the script again and again and finally marks it as not-working. So I had to give a sleep 10 in my scripts that launch agent invokes.

You can alias launchctl print user/$(id -u $(whoami)) | grep <yournamespace> to show the list of active launch agents.

Here is where you can find my petty scripts for launch agents.

Sam Daniel
  • 1,800
  • 12
  • 22