Added improved ssh-agent support.

This commit is contained in:
Darren 'Tadgy' Austin 2019-07-01 15:19:05 +01:00
commit ace5e0e8e3
3 changed files with 174 additions and 28 deletions

102
.bashrc
View file

@ -1,3 +1,105 @@
# Functions.
_agent_prompt_command() {
hash ssh-add >/dev/null 2>&1 && {
local SOCK
declare -g _SSH_PROMPT_ERROR_ISSUED
# Check the ssh agent socket is still alive.
ssh-add -l >/dev/null 2>&1
if (($? >= 2)); then
# Auth socket has become unusable, search for a new one.
SOCK="$(_find_agent_sock)"
if ((${PIPESTATUS[0]} == 0)); then
export SSH_AUTH_SOCK="$SOCK"
_SSH_PROMPT_ERROR_ISSUED=0
echo "Connected to alternate ssh-agent - you may need to re-add keys."
else
if [[ -z "$(egrep -v '^$' ~/.ssh/agents)" ]]; then
((${_SSH_PROMPT_ERROR_ISSUED:-0} == 0)) && {
echo "$(tput setaf 1 || tput AF 1)Lost connection to ssh-agent - no alternate available!$(tput op)"
unset SSH_AUTH_SOCK
_SSH_PROMPT_ERROR_ISSUED=1
}
else
((${_SSH_PROMPT_ERROR_ISSUED:-0} == 0)) && {
echo "$(tput setaf 1 || tput AF 1)Lost connection to ssh-agent - failed to connect to new agent!$(tput op)"
unset SSH_AUTH_SOCK
_SSH_PROMPT_ERROR_ISSUED=1
}
fi
fi
else
_SSH_PROMPT_ERROR_ISSUED=0
fi
unset SOCK
}
}
_clean_agent_socks() {
local I SSH_AUTH_SOCK
# Go through the array of sockets and validate each one.
for ((I = 0; I < ${#SOCKS[@]}; I++)); do
SSH_AUTH_SOCK="${SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
(($? >= 2)) && {
unset SOCKS[$I]
}
done
}
_find_agent_sock() {
local I IFS=$'\n' REPLY SOCKS=() SSH_AUTH_SOCK="$SSH_AUTH_SOCK"
# Load the array of sockets, minus the one we know is unusable.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
else
while read -r; do
SOCKS+=("$REPLY")
done < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
fi
# Search backwards through the list to find an active socket.
for ((I = (${#SOCKS[@]} - 1); I >= 0; I--)); do
SSH_AUTH_SOCK="${SOCKS[$I]}" ssh-add -l >/dev/null 2>&1
(($? <= 1)) && [[ ! -z "${SOCKS[$I]}" ]] && {
printf "%s" "${SOCKS[$I]}"
return 0
}
done
return 1
}
_pop_agent_sock() {
local IFS=$'\n' REPLY SOCKS=()
# Read the current list of auth sockets.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
else
while read -r; do
SOCKS+=("$REPLY")
done < <(egrep -v "^$SSH_AUTH_SOCK\$" ~/.ssh/agents 2>/dev/null)
fi
# Clean up any dead sockets - this modifies the SOCKS array.
_clean_agent_socks
# Write the new list back to disk.
printf "%s\n" "${SOCKS[@]}" >~/.ssh/agents
return $?
}
_push_agent_sock() {
local IFS=$'\n' REPLY SOCKS=()
# Read the current list of auth sockets.
if ((${BASH_VERSINFO[0]} >= 4)); then
mapfile -t SOCKS <~/.ssh/agents
else
while read -r; do
SOCKS+=("$REPLY")
done <~/.ssh/agents
fi
# Clean up any dead sockets - this modifies the SOCKS array.
_clean_agent_socks
# Write the new list back to disk.
printf "%s\n" "${SOCKS[@]}" "$SSH_AUTH_SOCK" >~/.ssh/agents
return $?
}
# Make bash a little more pleasent - these are valid for all versions.
shopt -s cdspell checkhash checkwinsize cmdhist histappend no_empty_cmd_completion