Start ngrok automatically on OSX - macos

I am trying to start ngrok automatically when my mac mini starts up. I thought maybe OSX had something like the init-folder on ubuntu where you place scripts you want to start automatically, but i haven't found anything like it.
Are there no way to just run commands on startup on OSX?

You can create a LaunchDaemon to run ngrok on startup (or a LaunchAgent if you want to start ngrok after a user logs in). See the apple docs.
A LaunchDaemon is a plist that resides in /Library/LaunchDaemons/. For example, my LaunchDaemon (/Library/LaunchDaemons/com.ngrok.onstartup.plist) looks something 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.ngrok.onstartup</string>
<key>Program</key>
<string>/path/to/ngrokd</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
The choice of the Label is up to you as long as it uniquely identifies your daemon. In this example my LaunchDaemon is called com.ngrok.onstartup.
ngrokd is a bash script looking like this:
#!/bin/sh
/usr/local/bin/ngrok -log=/path/to/ngrok.log -config=/path/to/ngrok.yml start ssh
You can check that launchd started your daemon by typing:
sudo launchctl list com.ngrok.onstartup

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.

How do I write a script that restarts an application that runs in the Terminal on Mac server after the machine reboots?

I have an application that normally runs in Terminal. This requires changing directory to the application directory [cd /mydirectory] and launching the application ./PurplesoftServer
I am struggling with writing a launch script to restart the application if the server restarts for any reason. I saved the script in /Library/LaunchAgents
This is my script:
```<?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>PSM.Restart</string>
<key>ProgramArguments</key>
<array>
<string>/Users/stephenjay/Documents/HW/HW Customers/ACME server 200814</string>
<string>./PurpleSoftServer</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>```
I also ran the following commands in Terminal in an effort to load the script:
sudo launchctl load /Library/LaunchAgents/PSM.Restart.plist
sudo launchctl start PurplesoftServer
Everything appears to run - after I gave ownership of the plist to root:wheel
However, the application doesn't end up running, neither after running the Sudo commands nor after actually restarting the Mac server.
What have I missed?
The first item in the ProgramArguments array should be the path to the executable, not a directory to cd to. You need to use the WorkingDirectory key instead. Something like this:
...
<key>ProgramArguments</key>
<array>
<string>./PurpleSoftServer</string>
</array>
<key> WorkingDirectory</key>
<string>/Users/stephenjay/Documents/HW/HW Customers/ACME server 200814</string>
...
BTW, you'll need to use sudo launchctl unload to unload the bad version, then sudo launchctl load again to load the fixed version.
BTW2, sudo launchctl list PSM.Restart will give you more info about the run status of the item.

Playing audio from OS X launchd daemon

I am trying to execute an Apple Script from my launchd daemon. My script has just one line and it is given below.
say "Message From Daemon!"
This always fails and throws this error message "File some object wasn't found".
Any idea why this is happening? The same script works properly if I run from xcode (not launching it via launchd) and from any other app that runs in user context.
Playing sound using NSSound rely on the window server and daemon is not allowed to connect to the window server.
I am assuming same issue with say command. ( This tool uses the Speech Synthesis manager to convert input text to audible speech and either play it through the sound output device chosen in System
Preferences or save it to an AIFF file.)
I'm guessing you're running into the same problem I had originally when I tried the same kind of thing. The path in your .plist file needs to point deeper into the applescript application. Below is an example of the .plist file.
<?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.namespace.script_name</string>
<key>Program</key>
<string>/Applications/script_name.app/Contents/MacOS/applet</string>
<key>LowPriorityIO</key>
<true/>
<key>Nice</key>
<integer>1</integer>
<key>StartInterval</key>
<integer>7200</integer>
</dict>
</plist>

Making Mac OSX launchctl launch a process as root on startup

My question is how to make a MacOSX daemon process using launchd start with root privileges automatically after a reboot?
I'm writing an application for in house use that blocks access to web sites. It is written in python and modifies the /ect/hosts file to disable or enable listed urls. The main application is in django and I created a python twisted daemon that does the actual modification of the /etc/hosts file as root access privileges are required.
I have created a plist file which works with one minor issue. After rebooting the daemon process has my normal logon privileges instead of root privileges.
A workaround is to stop the process with my normal privileges then startup the process with sudo.
launchctl unload /Library/LaunchAgents/com.balanceinfosystems.socialshields.twisted.plist
sudo launchctl load /Library/LaunchAgents/com.balanceinfosystems.socialshields.twisted.plist
The plist file
<?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>com.balanceinfosystems.socialshields.twisted</string>
<key>Program</key>
<string>/source/social_shields/social_shields_twisted.py</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
You've put this in the wrong directory. LaunchAgents are processes run per-user. System processes go in /Library/LaunchDaemons. They are run as root. If you want this to run at startup, I recommend making that explicit with:
<key>RunAtLoad</key>
<true/>

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/

Resources