As Apple continues to change the ways we interact with launchd on macOS with the launchctl(1) command, I have been attempting to update my processes and code snippets, as well as those I find in some of the open source tools I use. The goal is to iterate and update alongside of Apple, rather than ignoring these deprecations, and hope that the tech debt burden can be lessened when legacy functionality is fully removed.

Which brings me to my most recent iteration. For a few years now I’ve used a shell alias, nads, to help filter and sort the output from the launchctl list command.

# non-apple daemon services (nads)
alias nads='launchctl list | grep -v | sort -k3'

The idea is to have a quick and easy list to look at for what non-Apple services are running on my Mac. This has been useful when troubleshooting software by allowing me to quickly see if there is an errant exit code and/or missing PID.

At some point, the `launchclt list` subcommand made its way into the dreaded LEGACY SUBCOMMANDS section of the launchctl(1) manual. In a slight surprise to myself, however, Apple added a note to the subcommand in this section – Recommended alternative subcommand: print

After a running a quick launchctl print system to see this new alternative, I was quickly overwhelmed with a ton of information, nothing like the quick, short list I was used to with launchclt list.

After spelunking through the output, I found the services section that appears to be very similar output to the previous launchctl list command.

	services = {
		       0      -
		       0      -
		     426      -
		       0      -
		       0      0
		     333      -
		       0      -
		       0      -
		       0   (pe)
		       0      -
		       0      -
		     334      -

After playing with awk for a bit, I was able to come up with 2 new aliases to effectively give me the same output as before.

alias nads='launchctl print system | awk -F\t '\''/^[[:blank:]]services = {/,/}/ {if(/{|}/) next; if(/ next; printf "%s %s\n", $3,$4}'\'' | sort -k3'

alias user-nads='launchctl print gui/$(id -u) | awk -F\t '\''/^[[:blank:]]services = {/,/}/ {if(/{|}/) next; if(/ next; printf "%s %s\n", $3,$4}'\'' | sort -k3'

They aren’t pretty, but the beauty of aliases is that you don’t ever really need to see them. With them, I was able to take 1150 lines of output from launchctl print system to only the 46 lines I care to see.

I should note that Apple did explicitly warn to not rely on the output formatting of the launchctl print subcommand, so it could break at any time.

IMPORTANT: This output is NOT API in any sense at all. Do NOT rely on the structure or information emitted for ANY reason. It may change from release to release without warning.

Got a suggestion for doing this better, I’d love to hear it! Feel free to ping me on Twitter or in the MacAdmins Slack.