http://www.launchd.info/ has some great unofficial documentation for launchd
.
Daemons run apart from users, agents run specifically for users.
/System/Library/LaunchDaemons
/System/Library/LaunchAgents
/Library/LaunchDaemons
/Library/LaunchAgents
$USER
’s $HOME
they exist in:
~/Library/LaunchAgents
Read man launchctl
for more.
System Preferences
→ Users & Groups
→ Login Items
There aren’t many configuration options. Right clicking the listed items will bring up a context menu with a single “Show in Finder” option.
Login items can be added programmatically with osascript
, e.g.:
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/TextEdit.app", hidden:false}'
More rarely used:
/Library/StartupItems
/System/Library/StartupItems
Applications can also sneak themselves into your kernel extensions.
These are stored in the filesystem at /System/Library/Extensions
.
List currently loaded extensions with:
sudo kextstat
Stop one like so:
sudo kextunload -b com.paceap.kext.pacesupport.snowleopard
While you can remove the files from /System/Library/Extensions
, it appears that kextunload
also causes the extension not to be loaded in future boots.
Based on my Server Fault answer.
To enable one-off logging, without using the filesystem:
sudo launchctl debug service-target --stdout --stderr
sudo
is required even if the script in question is not a system agent/daemon.service-target
is kind of weird. Supposing the local service is at ~/Library/LaunchAgents/dev.localmon.plist
and has the “label” dev.localmon
, its service-target
is gui/$UID/dev.localmon
.
$UID
is your user ID, which is just a standard environment variable, so the shell will interpolate it when calling this at the CLIFor that dev.localmon
service, the following will pipe the process’s stdout and stderr into the shell the next time (and only the next time) the service starts:
sudo launchctl debug gui/$UID/dev.localmon --stdout --stderr
You must have already called launchctl load ~/Library/LaunchAgents/dev.localmon.plist
before starting the debug session.
That command will hang with the open-and-ready TTYs. In another terminal, run:
launchctl start dev.localmon
start
is a legacy command and doesn’t use the fancy new service-target notationlaunchctl
does not have a reload
command for reading changes to a config.plist
file.
Instead, you must unload
and then load
the plist
file anew, e.g.:
launchctl unload ~/Library/LaunchAgents/local.ssh-add.plist
launchctl load $_
($_
, like !$
refers to the last argument of the previous command)
timestamp hostname com.apple.xpc.launchd\[1] (label[pid]): Service could not initialize: unique-id: xpcproxy + other-pid: 0xd
StandardOutPath
and StandardErrorPath
files should be user-writable if this is a ~/Library/LaunchAgents/*.plist
process.Tilde-expansion (~/Desktop
) is a shell feature, and launchd
does not implicitly run the program specified in ProgramArguments
inside a shell, so you can’t use a tilde there, or in the other configuration values, to refer to the current home directory.
The working directory is always /
unless you set it with WorkingDirectory
,
even for user agents (in ~/Library/LaunchAgents
).
But if you start a bash shell, it will have access to the usual HOME
and USER
environment variables (among others).
The first string
part of ProgramArguments
does not have to be an absolute filename,
though that is recommended, since it’s not clear what directories launchd
will look in to find the executable a relative filename is referring to (like PATH
in a shell).
(Practically speaking, though, it seems that launchd
’s “PATH” defaults to /usr/bin:/bin:/usr/sbin:/sbin
, i.e., /etc/paths
.)
local.ssh-add.plist
, to load an SSH key at system startup:
Create a file at ~/Library/LaunchAgents/local.ssh-add.plist
:
<?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>local.ssh-add</string>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>ssh-add</string>
<string>/Users/chbrown/.ssh/production-remote.pem</string>
</array>
</dict>
</plist>
Then run:
launchctl load ~/Library/LaunchAgents/local.ssh-add.plist