Skip to content

Instantly share code, notes, and snippets.

@baseonmars
Created April 16, 2009 09:32
Show Gist options
  • Save baseonmars/96333 to your computer and use it in GitHub Desktop.
Save baseonmars/96333 to your computer and use it in GitHub Desktop.
#!/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.<ppid> 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 <<EOXML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SSH_AUTH_SOCK</key>
<string>${_sockfile}</string>
</dict>
</plist>
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment