For anyone who ends up on this page, I realized I should post the answer:
Using launchd instead of cron does indeed fix the authorization problem. Your user launchd jobs (which run only when you are logged in) correctly use the SSH agent information that was unlocked via your keychain as part of login (as part of standard OS X key management, no other software required).
To minimize my interactions with launchd, I created a single launchd job that calls a bash script. In this way I can simply edit the script without dealing with launchd.
Here's the launchd file:
<?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>com.mycron.hourly</string>
<key>ProgramArguments</key>
<array>
<string>/Users/john/bin/cron.hourly</string>
</array>
<key>Nice</key>
<integer>1</integer>
<key>StartInterval</key>
<integer>3600</integer> <!-- start every X seconds -->
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
I saved the file to ~/Library/LaunchAgents/com.mycron.hourly.plist
, and then loaded it with:
launchctl load ~/Library/LaunchAgents/com.mycron.hourly.plist
Once loaded, it will run right away and then again every 60 minutes.
If you follow the same procedure, you'll want to change the `ProgramArguments' string with the right path to your script.
Bash has special provisions in its source code to source ~/.bashrc
when it's invoked by rshd
or sshd
. It's a compilation option, which given your experience seems not to be turned on under OSX.
If you're logging in with a key, you can (ab)use the command=
option in the ~/.ssh/authorized_keys
file.
A key with a command
option is good only for running the specified command; but the command in the authorized_keys
file runs with the environment variable SSH_ORIGINAL_COMMAND
set to the command the user specified (empty for interactive sessions). So you can use something like this in ~/.ssh/authorized_keys
(of course, it won't apply if you don't use this key to authenticate):
command=". ~/.profile;
if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
eval \"$SSH_ORIGINAL_COMMAND\";
else exec \"$SHELL\"; fi" ssh-rsa …
Note that I put line breaks above for legibility, but this actually needs to be all on one line.
How can I set environment variables for a remote rsync process? may have other helpful suggestions.
Best Answer
What you're describing is how things are supposed to work. The reason that commands leaves no output is not that some bug or error happened that prevents it from displaying the value of SSH_AUTH_SOCK - it is simply because that variable is not supposed to be set by launchd in your environment.
When you're using key based authentication with SSH, and you want an agent to make it easier to handle the private keys - you'll want to run that agent locally. I.e. when you're ssh'ing into a remote computer, the agent is supposed to run on your local computer that you're ssh'ing from.
Imagine that you're ssh'ing in to a remote computer, and then want to use ssh from there and you need to enter a passphrase - the prompt pops up in the GUI shown on the monitor connected to that remote computer. You can't see it, you can't act with it. This is not how it's supposed to work.
Instead run ssh agent on your local computer, load in the keys, and then ssh into your remote computers using the
-A
parameter for ssh to enable agent forwarding (or set it permanently for that remote computer in the configuration).If you really want to run ssh-agent on the remote computer, you can ofcourse do so. When you have ssh'ed to the remote computer, simply run ssh-agent and add your keys. If you want to automatize running ssh-agent, you can do that.