Home

Awesome

Offset

Automatically process packages and scripts at logout (for 10.12 and earlier) or login window (for 10.13 and 10.14).

Update 2023

I no longer actively maintain, use, or support this project, but I've just updated it for Python 3 in case that might be helpful to someone. I was hoping to use the MacAdmins Python for this, but I found it was giving errors when importing the plistlib module. So I've just put in the Munki Python instead, which seems to work better. Feel free to use whatever version of Python 3 you want that actually works.

I've done very minimal testing of this on Ventura (macOS 13). Your mileage may vary in Ventura itself or in Sonoma and beyond.

Backstory

Heavily based on Joseph Chilcote's Outset, which processes packages and scripts at boot and login. He believed the running of logout scripts was outside the scope of his project and also had reservations about the implementation, so he suggested I could make it and call it offset, which is actually a great name, when you start looking at all the dictionary definitions of the word (a counterbalance, an offshoot, an actual outset still).

There was a bit of debate about what method to use for this, since there is a workaround that uses a Launch Agent that then runs trapped code when the script gets SIGINT, SIGUP, or SIGTERM. Chilcote had some concerns about that approach: that it does not respawn if killed prematurely, and that it will run the script's commands without warning the user if the Launch Agent is killed prematurely. Anecdotally, I haven't noticed any of these issues adversely affecting day-to-day functionality in my workplace, but if there's a tool that can be used by many people in various contexts, it's good to use a method that's a bit more thoroughly tested.

Apple (since 10.4, I believe) has officially deprecated, in Login and Logout Hooks, the use of login and logout hooks in favor of Launch Agents. The only problem is that they don't present an actual alternative to the logout hook, and the logout hook appears to still work as of 10.12 (Sierra).

Greg Neagle suggested using a launch agent that runs at the login screen (meaning the user is logged out), and that appears to be the best (safest) way to go, so that's what this project is using.

So Offset, which can be used in conjunction with Outset if you want both scripts for login/boot/on-demand and logout scripts, you can install both Outset and Offset. Of course, you can also write custom Launch Agents and Launch Daemons for every single script, but the point here is convenience--placing scripts in a few folders to run instead of creating separate launchd's for each script.

Technical Notes on Implementation

Notes about macOS 10.13 (High Sierra) and 10.14 (Mojave)

In High Sierra, the change from loggedIn to loggedOut in the com.apple.loginwindow.plist doesn't happen immediately. The time it takes to switch seems to vary. It can be a little more than a second or even slightly more than three seconds. I did some trials of having a time delay before checking for the loggedIn/loggedOut status, and there didn't seem to be a consistent time delay that would reliably work. The same appeared to be the case for 10.14. So if Offset sees the OS is 10.13 or greater, it will pretty much just run at the login window. I haven't done extensive testing on this, but I don't believe it will run twice on reboot.

Caveats for macOS 10.12 (Sierra) and earlier

Unexpected Bonuses for macOS 10.12 (Sierra) and earlier

How to Install Offset

.pkg Method

Go to the the releases page, where you'll be able to download a .pkg file and just run it.

Create package yourself

Use munkipkg to build (and maybe sign?) the package yourself.

How to use Offset

Put any scripts or packages in the /usr/local/offset/logout-every folder and make sure they have root:wheel ownership. The scripts should have 755 permissions. Packages should have 644 permissions.

Acknowledgements

Huge shoutout to @chilcote, whose code this project (in a Frankenstein's monster way) is based on a rearrangement of. Also kudos to @gregneagle for suggesting the login window Launch Agent as an alternative to the logout hook or the interrupted user-context Launch Agent.