Since startup items and rc
commands are both deprecated (and in many cases not working at all) on OS X in favour of launchd
, I'd like to find out what the correct way would be to setup a shell script that runs on logout/shutdown.
For a startup item it was possible to create a shell script that looked something like:
#!/bin/sh
StartService() {
echo "Started."
}
StopService() {
echo "Stopped."
}
RunService "$1"
But the RunService
command isn't supported when running a script from launchd
, and I'm not sure it's meant to be used anymore anyway.
If possible, I'd like to create a shell script that will be provided to launchd
as an on-demand service that will be started near to shutdown and somehow informed that the system is shutting down.
Alternatively, I may need a shell script that is opened on login/system start and remains running (or rather, asleep) until a SIGTERM
or other kill signal is received, so that it can run some commands before closing.
@gaige thanks for the reply! In the end I went for the following:
#!/bin/sh
StartService() {
echo "Started"
}
StopService() {
echo "Stopped"
exit 0
}
StartService
trap StopService SIGTERM
while true; do
sleep 86400 &
wait $!
done
Sleeping for a full day should prevent it from wasting any processing power, though it's not exactly my favourite solution to have something running like that. However, launchd
doesn't really have any criteria that seemed like it would allow my script to only run at shutdown. The above instead is run on load (login) and then captures a SIGTERM
on termination, logout or shutdown. Note the asynchronous use of sleep
, as some environments will wait for the sleep to finish before executing the trap, which is no good as launchd
only allows a couple of seconds to respond to SIGTERM
before SIGKILL
is sent.
As far as I can tell launchd
only supports on demand services if they're triggered by a socket or watched path or whatever, which didn't really present a solution for me since it would still require some kind of outside influence.
One beneficial side effect however is that any results I obtained in StartService, such as file pointers etc., can be easily accessed by StopService since it's just in memory, no need for file saving. Just doesn't feel like the most elegant solution, but hey, if it works it's fine!