-
Notifications
You must be signed in to change notification settings - Fork 0
/
sshagent.plugins.bash
144 lines (121 loc) · 2.92 KB
/
sshagent.plugins.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# shellcheck shell=bash
cite about-plugin
about-plugin 'SSH Agent helper functions'
_get_sshagent_pid_from_env_file () {
local env_file="${1}"
[[ -r "${env_file}" ]] || {
echo "";
return
}
tail -1 "${env_file}" \
| cut -d' ' -f4 \
| cut -d';' -f1
}
_get_process_status_field () {
# uses /proc filesystem
local \
pid \
status_file \
field
pid="${1}"
field="${2}"
status_file="/proc/${pid}/status"
if ! ([[ -d "${status_file%/*}" ]] \
&& [[ -r "${status_file}" ]]); then
echo ""; return;
fi
grep "${field}:" "${status_file}" \
| cut -d':' -f2 \
| sed -e 's/[[:space:]]\+//g' \
| cut -d'(' -f1
}
_is_item_in_list () {
local item
for item in "${@:1}"; do
if [[ "${item}" == "${1}" ]]; then
return 1
fi
done
return 0
}
_is_proc_alive_at_pid () {
local \
pid \
expected_name \
actual_name \
actual_state
pid="${1?}"
expected_name="ssh-agent"
# we want to exclude: X (killed), T (traced), Z (zombie)
actual_name=$(_get_process_status_field "${pid}" "Name")
[[ "${expected_name}" == "${actual_name}" ]] || return 1
actual_state=$(_get_process_status_field "${pid}" "State")
if _is_item_in_list "${actual_state}" "X" "T" "Z"; then
return 1
fi
return 0
}
_ensure_valid_sshagent_env () {
local \
agent_pid \
tmp_res
mkdir -p "${HOME}/.ssh"
type restorecon &> /dev/null
tmp_res="$?"
if [[ "${tmp_res}" -eq 0 ]]; then
restorecon -rv "${HOME}/.ssh"
fi
# no env file -> shoot a new agent
if ! [[ -r "${SSH_AGENT_ENV}" ]]; then
ssh-agent > "${SSH_AGENT_ENV}"
return
fi
## do not trust pre-existing SSH_AGENT_ENV
agent_pid=$(_get_sshagent_pid_from_env_file "${SSH_AGENT_ENV}")
if [[ -z "${agent_pid}" ]]; then
# no pid detected -> shoot a new agent
ssh-agent > "${SSH_AGENT_ENV}"
return
fi
## do not trust SSH_AGENT_PID
if _is_proc_alive_at_pid "${agent_pid}"; then
return
fi
ssh-agent > "${SSH_AGENT_ENV}"
return
}
_ensure_sshagent_dead () {
[[ -r "${SSH_AGENT_ENV}" ]] \
|| return ## no agent file - no problems
## ensure the file indeed points to a really running agent:
agent_pid=$(
_get_sshagent_pid_from_env_file \
"${SSH_AGENT_ENV}"
)
[[ -n "${agent_pid}" ]] \
|| return # no pid - no problem
_is_proc_alive_at_pid "${agent_pid}" \
|| return # process is not alive - no problem
echo -e -n "Killing ssh-agent (pid:${agent_pid}) ... "
kill -9 "${agent_pid}" && echo "DONE" || echo "FAILED"
rm -f "${SSH_AGENT_ENV}"
}
sshagent () {
about 'ensures ssh-agent is up and running'
param '1: on|off '
example '$ sshagent on'
group 'ssh'
[[ -z "${SSH_AGENT_ENV}" ]] \
&& export SSH_AGENT_ENV="${HOME}/.ssh/agent_env.${HOSTNAME}"
case "${1}" in
on) _ensure_valid_sshagent_env;
# shellcheck disable=SC1090
source "${SSH_AGENT_ENV}" > /dev/null;
;;
off) _ensure_sshagent_dead
;;
*)
;;
esac
}
sshagent on