Run Script on Logout Without Use of Logout Hook

Solution 1:

It seems that Apple isn't interested in a logout hook replacement, as they closed my issue inquiring about one.

However, one of the improvements in Yosemite is that launchd now properly sends signals down to shell scripts. What this means is that you can now do a log-out task like so:

Here's an example logout.sh:

#!/bin/sh
onLogout() {
    echo 'Logging out' >> ~/Logs/logout.sh.log
    exit
}

trap 'onLogout' SIGINT SIGHUP SIGTERM
while true; do
    sleep 86400 &
    wait $!
done

This will simply sleep (asynchronously, doing it synchronously without the ampersand doesn't seem to work) until it receives one of the trapped signals, at which point it will execute the onLogout function.

All you need to do is launch that script using a RunAtLoad launch agent or launch daemon and it will run at log-out or shutdown, though it's important to bear in mind that tasks only have a limited amount of time to complete before they are killed instead, so this shouldn't be used to run anything that takes a long time, or requires a network connection that could be delayed etc.

Of course this is of no use to anyone on Mavericks or earlier, but under Yosemite this now seems to work as expected; so I was actually doing it right in the first place, launchd just wasn't sending the signals properly :)

NOTE: For this to work the shell scripts seems to need to be executed directly by launched, i.e - it shouldn't invoked via sh. So if it were placed in ~/Library/Scripts/foo.sh your program arguments might look like:

<key>ProgramArguments</key>
<array>
    <string>~/Library/Scripts/foo.sh</string>
    <string>bar</string>
</array>
<key>EnableGlobbing</key>
<true/>

Solution 2:

You can use iHook to run login/logout hooks, which I've found to still work for non-interactive login and logout hooks written in Bash and Python on Yosemite.

http://rsug.itd.umich.edu/software/ihook/