#!/bin/sh # AUTHOR: Matt Simerson (matt@tnpi.net) # # VERSIONS: # 1.02 - Dec 16, 2007 # - adjusted ps invocation for reliable detection when multiple # - users run ssh-agent on a single system # 1.01 - Oct 9, 2007 # - when cleaning up stale agent, remove stale sock file # 1.0 - July, 2007 # - initial release # # INSTRUCTIONS # 1. Install this script in your ~/.ssh directory as agent.sh # # curl -o .ssh/agent.sh http://www.tnpi.net/computing/mac/agent.sh.txt # chmod 755 .ssh/agent.sh # # 2. Configure it to run when a new terminal window opens # # echo 'source .ssh/agent.sh' >> ~/.bash_profile # # 3. Open new terminal/shell sessions # # 4. Enjoy # # GUI APPLICATIONS # # If you use GUI apps that are ssh-agent aware, you will need to run the # script once and then log out and back in. Then your GUI apps will be # ssh-agent aware. unset _sockfile ### begin SSH-AGENT SOCKET NOTES # # Setting _sockfile is an efficiency improvement. Rather than storing the # ssh socket file in /tmp/ssh-XXXXXXXXXX/agent. and having to glob # to find it, we can store it in a fixed location so this script can find # it more efficiently. Since all our shell/terminal windows will share the # first ssh-agent process, there is no need for the random location. # # If you decide to alter the location, keep security in mind. You do not want # others to have access to this socket. Your ~/.ssh directory is a great # choice because its default permissions (600) are readable only by you. # # If you wish to keep the default /tmp behavior, simply comment out this # setting # _sockfile="${HOME}/.ssh/agent.sock" # ### end SSH-AGENT SOCKET NOTES if [ "$0" != "-bash" ]; then echo ' OOPS! Did you mean to source this script? Try this: source ~/.ssh/agent.sh ' fi main() { # There are three states we check for # # 1. ssh-agent not running. # # a) clean up any stale environment variables # b) launch the agent # c) configure our environment to use it # d) add our ssh keys # # 2. ssh-agent is running, but our environment variables are outdated. # (SSH_AGENT_PID is set but different than running ssh-agent pid) # # a) clean up the stale environment variables # b) configure our environment to use the existing ssh-agent # # 3. ssh-agent is running # # a) configure our environment to use the existing ssh-agent set_agent_pid if [ -z "${_agent_pid}" ]; # 1 then cleanup_stale_agent start_ssh_agent elif [ ! -z $SSH_AGENT_PID ] && [ "${_agent_pid}" -ne $SSH_AGENT_PID ]; then # 2 cleanup_stale_agent discover_ssh_agent $_agent_pid else # 3 discover_ssh_agent $_agent_pid fi } set_agent_pid() { # this is expensive but reliable #echo "checking for ssh-agent process" _agent_pid=`ps uwwxU $USER | grep ssh-agent | grep -v grep | awk '{ print $2 }' | tail -n1` } discover_ssh_agent() { if [ -z "$1" ]; then set_agent_pid fi if [ ! -z $_agent_pid ]; then echo "ssh agent for $USER found at pid ${_agent_pid}." export SSH_AGENT_PID=${_agent_pid} # if _sockfile is not defined we must figure it out if [ -z "$_sockfile" ] || [ ! -e "$_sockfile" ]; then _sock_pid=`echo "${_agent_pid} - 1" | bc` _sockfile=`/bin/ls /tmp/ssh-*/agent.${_sock_pid}` fi if [ ! -e "$_sockfile" ]; then echo "ERROR: could not determine ssh-agent socket file for pid: $SSH_AGENT_PID" else export SSH_AUTH_SOCK=$_sockfile # make sure the Mac Login environment is configured if [ "`uname`" == "Darwin" ]; then setup_plist fi fi fi } start_ssh_agent() { if [ -z "$_sockfile" ]; then echo "starting ssh-agent" ssh-agent > /dev/null else echo "starting ssh-agent -a $_sockfile" ssh-agent -a $_sockfile > /dev/null fi discover_ssh_agent if [ ! -z $SSH_AUTH_SOCK ]; then # this will prompt the user to authenticate their ssh key(s) echo "adding ssh key(s) to agent" ssh-add fi } setup_plist() { _envdir="$HOME/.MacOSX" if [ ! -d $_envdir ]; then mkdir $_envdir fi _plist="$_envdir/environment.plist" if [ -e $_plist ]; then if [ ! `grep "$_sockfile" $_plist` ]; then set +o noclobber write_plist # check and update fi else write_plist # create fi } write_plist() { echo "updating Mac OS X environment" ( cat < SSH_AUTH_SOCK ${_sockfile} EOXML ) > $_plist } cleanup_stale_agent() { echo "cleaning up stale ssh agent" # check the environment variable SSH_AGENT_PID as it could be set # despite the ssh-agent process being missing. if [ ! -z $SSH_AGENT_PID ]; then #echo "cleaning up stale ssh agent pid: $SSH_AGENT_PID" unset SSH_AGENT_PID fi if [ ! -z $SSH_AUTH_SOCK ]; then unset SSH_AUTH_SOCK fi if [ -e $_sockfile ]; then echo "cleaning up stale agent socket file: $_sockfile" unlink $_sockfile fi } print_agent_info() { echo "pid : $_agent_pid" echo "sock: $_sockfile" } main #print_agent_info