OSX launchd and launchctl issues
By Tim on Thursday 17 November 2011, 21:36 - work - Permalink
I recently re-installed Lion on my MBP and ran into the problem that by
default ssh-agent
remembers my private key
indefinitely. I wanted to reduce this to something sane and found the file
/System/Library/LaunchAgents/org.openbsd.ssh-agent.plist which
controls ssh-agent's behaviour. I started tweaking stuff with
launchctl,
first broke my ssh-agent altogether and after a while figured out
how to tweak it to my needs.
After initially breaking my ssh-agent because I copy/pasted
commands that I didn't really understand, I found the following apt quote:
A good rule for rocket experimenters to follow is this: always assume
that it will explode
– Astronautics, issue 38, October 1937
(source)
Fortunately I managed to fix it and get some basic understandign of launcd on OSX. This information seemed to be a bit fragmented, so here are my findings.
Changing ssh-agent private key timeout
- 1. Edit
/System/Library/LaunchAgents/org.openbsd.ssh-agent.plist - 2. Add the two options
<string>-t</string> <string>1800</string>
to
<key>ProgramArguments</key>
N.B. The flag -t and the value 1800 have to be
seperate elements (apparently).
- 3. Quit Terminal, log out & log in, restart Terminal, done
Removing or adding a service from launchd as user
- 1. Find the service, try
launchctl listorlaunchctl <service> - 2. Unload and disable with
$ launchctl unload -w <plist file path>
This unloads (and stops) the specific service. -w tells
launchd to disable the service as well.
- 3. Log out and log in, done
To add the service again
- 4. Load the service with launchctl:
$ launchctl load -w <plist file path>
- 5. Log out and log in
Adding a launch service as user
Here we stop the system default ssh-agent service and add our
own in our own directory.
- 1. Unload the system-wide service:
$ launchctl unload -w /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist
- 2. Copy the file to your own homedir:
$ cp /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist ~/Library/LaunchAgents/
- 3. Edit some settings, such as the ssh-agent timeout
$ vim ~/Library/LaunchAgents/org.openbsd.ssh-agent.plist
- 4. Load the new service as user
$ launchctl load -w ~/Library/LaunchAgents/org.openbsd.ssh-agent.plist
- 5. Verify it is indeed loaded
$ launchctl list | grep ssh - 0 org.openbsd.ssh-agent
This means launchctl knows about this service. Column 1 is the
PID (none), col 2 is the last exit status (not started). Column 3 is the
service name.
More information is gained by querying the service itself:
$ launchctl list org.openbsd.ssh-agent
{
"Label" = "org.openbsd.ssh-agent";
"LimitLoadToSessionType" = "Aqua";
"OnDemand" = true;
"LastExitStatus" = 0;
"PID" = 4978;
"TimeOut" = 30;
"ProgramArguments" = (
"/usr/bin/ssh-agent";
"-l";
"-t";
"1800";
);
"EnableTransactions" = true;
"TransactionCount" = 0;
"Sockets" = {
"Listeners" = (
file-descriptor-object;
);
};
};
;
- 6. Quit terminal, log out & in, start terminal,
sshsomewhere:
$ ssh <server>
This will start the ssh-agent and you will be greeted with a familiar
Keychain login (Leopard and higher). ssh-agent now runs with your
(custom) options:
$ ps ax | grep ssh-agent 3140 ?? S 0:00.03 /usr/bin/ssh-agent -l -t 1800
- 7. Rejoice!
Reload new configuration parameters without loggin out
- 1. Stop the service
$ launchctl unload Library/LaunchAgents/org.openbsd.ssh-agent.plist
- 2. Re-load the service
$ launchctl load Library/LaunchAgents/org.openbsd.ssh-agent.plist
- 3. Check the settings
$ launchctl list org.openbsd.ssh-agent
- 4. Start the service manually
$ launchctl start org.openbsd.ssh-agent
This is approximately how far I got, everything seems to work except the
environment variable SSH_AUTH_SOCK. Here are some things that look
right but don't work properly:
- 5. Unset
SSH_AUTH_SOCKvariable
$ launchctl unsetenv SSH_AUTH_SOCK
- 6. Re-set
SSH_AUTH_SOCKmanually (system wide)
$ launchctl setenv SSH_AUTH_SOCK $(launchctl getenv SSH_AUTH_SOCK) $ export SSH_AUTH_SOCK=$(launchctl getenv SSH_AUTH_SOCK)
- 7. Rejoice!
N.B. Somehow this still does not properly work, you have to run export for
all Terminal sessions. SSH_AUTH_SOCK is set to the previous value
otherwise. I don't know why or where this is configured.
Some other things I found out, background information
- launchctl controls launchd
- launchctl looks in these directories (from launchctl(1)):
FILES
~/Library/LaunchAgents Per-user agents provided by the user.
/Library/LaunchAgents Per-user agents provided by the adminis-
trator.
/Library/LaunchDaemons System wide daemons provided by the admin-
istrator.
/System/Library/LaunchAgents Mac OS X Per-user agents.
/System/Library/LaunchDaemons Mac OS X System wide daemons.
- launchctl is user-specific, i.e.
$ sudo launchctl list
gives a different output than
$ launchctl list
launchctl loadandlaunchctl unloadload a certain service intolaunchd. This does not mean it will be started immediately, some services are on-demand.
- load and unload have a -w flag that
disabled loading, this is stored elsewhere on disk
(overrides.plist (?)), possibly in
/private/var/db/launchd.db/com.apple.launchd/overrides.plist
or
private/var/db/launchd.db/com.apple.launchd.peruser.<number>/overrides.plist
- Some services create sockets (?) in
/tmp/that listen to connections. In the case ofssh-agent, this can for example be/tmp/launch-oEZ3J9/Listeners.launchdsets the environment variableSSH_AUTH_SOCKto this location. Whensshis issued, lauchd detects somebody wants to usessh-agentand starts this.
- Manually setting
SSH_AUTH_SOCKto the right listener also 'works'.
launchctl getenv SSH_AUTH_SOCKgives the right socket
- Restarting Terminal or applications in general might be necessary to reload updated launchd information
- My
launchctl list org.openbsd.ssh-agent output(after tampering and restoring):
[tim@Saturn] LaunchAgents% launchctl list org.openbsd.ssh-agent
{
"Label" = "org.openbsd.ssh-agent";
"LimitLoadToSessionType" = "Aqua";
"OnDemand" = true;
"LastExitStatus" = 512;
"PID" = 917;
"TimeOut" = 30;
"ProgramArguments" = (
"/usr/bin/ssh-agent";
"-l";
);
"EnableTransactions" = true;
"TransactionCount" = 0;
"Sockets" = {
"Listeners" = (
file-descriptor-object;
);
};
};
Some unresolved issues
- After loading/unloading with
launchctlas user and as root,SSH_AUTH_SOCKdid not seem to be generated properly anymore. Why?
- For
ssh-agentdoes it matter if you load the service as root or user?
- Are load and unload operations persistent over reboots? If so, where is this stored?
References
On the -w flag and disabling services permanently