When using SSH with public keys it is very annoying to enter the pass phrase everytime you connect to a host. In some cases (I won’t talk about security here, but you should really check waht it means to use an SSH agent) you can use a SSH agent to store your private keys. I’ll show a little script here, wich I include in my .zprofile to reuse a running SSH agent or to start a new one in the case that no agent is running. This allows to share one single instance between all shell sessions.
First we define a little helper function in .zprofile (if you’re using bash instead of zsh, you have to edit .bash_profile instead):
exists() { for i in $*; do which $i >/dev/null 2>&1 || return 1 done return 0 }
This helps us to identify, which programms are installed.
First we check if ssh-agent is installed on our system (line 1). If this is the case, we check if SSH_AUTH_SOCKET
isn’t already set (line 2; this is the case if we are connected via SSH and agent forwarding). If we don’t have an agent, we take a look at .agent.env
: if it does not exist (lines 11-12) we can start an agent and save it’s PID in .agent.env
to allow other shells to reuse the agent. If the file is already there we check if the referenced agent is still running (line 6). If it is, we reuse it, otherwise we start a new one (line 7-8):
if exists ssh-agent; then if [[ -z $SSH_AUTH_SOCK ]]; then if [[ -f ~/.agent.env ]]; then . ~/.agent.env -s > /dev/null if ! kill -0 $SSH_AGENT_PID > /dev/null 2>&1; then ssh-agent -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi else ssh-agent -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi fi fi
So far, after parsing the .zprofile file, we have a running ssh-agent in every case. We can now execute ssh-add and add our key(s). On Windows, if using cygwin, the chance is high that you’re using pageant as your ssh-agent. pageant is the SSH agent that comes with PuTTY or WinSCP. However, there are some wrappers that allows openssh to authenticate with PuTTY’s pageant. One of these solutions is ssh-pageant. It is easyly installed:
% git clone git://github.com/cuviper/ssh-pageant.git Cloning into 'ssh-pageant'... remote: Counting objects: 206, done. remote: Compressing objects: 100% (189/189), done. remote: Total 206 (delta 117), reused 23 (delta 9) Receiving objects: 100% (206/206), 69.59 KiB, done. Resolving deltas: 100% (117/117), done. % cd ssh-pageant % make cc -O2 -Werror -Wall -Wextra -MMD -c -o main.o main.c cc -O2 -Werror -Wall -Wextra -MMD -c -o winpgntc.o winpgntc.c cc main.o winpgntc.o -o ssh-pageant.exe % cp ssh-pageant /usr/bin/ %
The startup code looks nearly the same. I’ll show a univeral version here which works on all environments:
if [[ "$OSTYPE" != cygwin ]]; then if exists ssh-agent; then if [[ -z $SSH_AUTH_SOCK ]]; then if [[ -f ~/.agent.env ]]; then . ~/.agent.env -s > /dev/null if ! kill -0 $SSH_AGENT_PID > /dev/null 2>&1; then ssh-agent -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi else ssh-agent -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi fi fi else if exists ssh-pageant; then if [[ -f ~/.agent.env ]]; then . ~/.agent.env -s > /dev/null if ! kill -0 $SSH_PAGEANT_PID > /dev/null 2>&1; then ssh-pageant -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi else ssh-pageant -s > ~/.agent.env . ~/.agent.env > /dev/null 2>&1 fi fi fi
On linux, is also possible to kill the agent if the last user logs out:
on_logout() { if [ $(users |sed 's/ /\n/'| grep -c $USER) -eq 1 ]; then ssh-agent -k >/dev/null 2>&1 fi } trap 'on_logout' EXIT
Have more fun using SSH