/
functions
267 lines (235 loc) · 6.06 KB
/
functions
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#!/bin/sh
#TODO: old code - validate
__sm.process.status()
{
typeset _name _pid _ps
_name="$1"
_pid="$2"
log "${name:-"process"}:"
if (( ${_pid} > 0 ))
then
_ps=$(ps -p ${_pid} -ostate,sgi_rss,vsize | tail -1)
log " status: running"
log " version: ${service_version}"
log " process: "
log " pid: ${_pid}"
if __sm.os.type.is linux
then
log " parent_pid: $(awk '/^PPid:/{print $2}' /proc/${_pid}/status)"
log " state: $(printf "$_ps" | awk '{print $1}')"
log " rss: $(printf "$_ps" | awk '{print $2}')"
log " vsz: $(printf "$_ps" | awk '{print $3}')"
fi
# TODO: Use /proc for linux and lsof otherwise
if __sm.command.exists lsof
then
typeset cwd binary
typeset -a libraries tcp_ports udp_ports sockets logs string
while read -r line
do
case "$line" in
(*[[:space:]]cwd[[:space:]]*)
cwd="${line##* }"
;;
(*[[:space:]]txt[[:space:]]*)
binary="${line##* }"
;;
(*/lib/*)
string="${line%% \(*}"
libraries+=("${string##* }")
;;
(*.log*)
logs+=("${line##* }")
;;
(*.sock*)
sockets+=("${line##* }")
;;
(*TCP*)
string="${line%% \(*}"
tcp_ports+=("${string##* }")
;;
(*)
true # ignore other lines
;;
esac
done < <(lsof -U -p ${_pid})
log " cwd: ${cwd}"
log " binary: ${binary}"
if __sm.array.is.nonempty logs
then
log " logs:"
__sm.array.sort asc logs
__sm.array.unique logs
__sm.array.each logs 'printf " - %s\n" "${element}"'
fi
if __sm.array.is.nonempty libraries
then
log " libraries:"
__sm.array.sort asc libraries
__sm.array.unique libraries
__sm.array.each libraries 'printf " - %s\n" "${element}"'
fi
if __sm.array.is.nonempty tcp_ports
then
log " tcp_ports:"
__sm.array.sort asc tcp_ports
__sm.array.unique tcp_ports
__sm.array.each tcp_ports 'printf " - %s\n" "${element}"'
fi
if __sm.array.is.nonempty sockets
then
log " sockets:"
__sm.array.sort asc sockets
__sm.array.unique sockets
__sm.array.each sockets 'printf " - %s\n" "${element}"'
fi
fi
else
log " status: not running."
fi
}
#TODO: old code - validate
__sm.process.signal()
{
typeset _signal _pid
_signal="$1"
_pid="$2"
if [[ -n "${_pid}" ]] && (( _pid > 0 ))
then
kill -${_signal} ${_pid}
else
log "Not sending signal ${_signal} to process, as pid is 0 (process not found/running)."
fi
}
#TODO: old code - validate
#TODO: add lockfile.init, lockfile.unlock, lockfile.finish
__sm.process.lockfile.lock()
{
typeset _lockfile
_lockfile="${1:-}"
printf "$$" >> "${_lockfile}" # *Append* current process's pid to the lockfile
# Now read in the first pidfile from the lockfile. This means that the first
# instance that successfully writes its pid to the lockfile obtains the lock.
read -r _pid < "${_lockfile}"
# If the pidfile read in matches the pid of the current process, then
if [[ "${_pid}" != "$$" ]]
then
__sm.log.debug "Another process already owns the lockfile;"
return 1
fi
# The currently running process has the lock; immediately add an on-exit
# hook that removes the lockfile when the process exits, thus relinquishing
# the filesystem-level lock. This also preserves existing EXIT code.
__sm.traps.on.exit "cd '$PWD';rm -f ${_lockfile}"
return 0 # The lock has been obtained! Proceed with nefarious things!
}
# start process
# ex. __sm.process.start NAME TIMEOUT COMMAND ...
__sm.process.start()
{
typeset _name _pid _counter _counter_value
_name="$1"
_counter_value="$2"
shift 2
if __sm.process.is.running "${_name}"
then
return 0
fi
nohup "$@" </dev/null >"${_name}_out.log" 2>"${_name}_err.log" &
_pid=$!
_counter=${_counter_value}
while (( _counter-- )) && __sm.process.pid.running ${_pid}
do
sleep 1s
done
if __sm.process.pid.running ${_pid}
then __sm.process.pid.write "${_name}" ${_pid}
else return $?
fi
}
# stop process
# ex. __sm.process.stop NAME TIMEOUT
__sm.process.stop()
{
typeset _pid _counter
if _pid=$(__sm.process.pid.read "${1}")
then
_counter=$2
while (( _counter-- )) && __sm.process.pid.running ${_pid}
do
kill ${_pid}
sleep 1s
done
if __sm.process.pid.running ${_pid}
then
kill -9 ${_pid}
fi
if ! __sm.process.pid.running ${_pid}
then
__sm.process.pid.write "${1}"
fi
else return 0
fi
}
# stop if running ; start
# ex. __sm.process.restart NAME TIMEOUT_START TIMEOUT_STOP COMMAND ...
__sm.process.restart()
{
typeset _name _counter_start _counter_stop
_name="$1"
_counter_start="$2"
_counter_stop="$3"
shift 3
if __sm.process.stop "${_name}" ${_counter_stop}
then true #continue
else return $?
fi
if __sm.process.start "${_name}" ${_counter_start} "$@"
then return 0
else return $?
fi
}
# Check if a process with a given NAME is working
# ex. __sm.process.is.running NAME
__sm.process.is.running()
{
typeset _pid
if _pid=$(__sm.process.pid.read "$1")
then
if __sm.process.pid.running ${_pid}
then return 0
else return $?
fi
else return $?
fi
}
## Private?
# read a pid from pid file NAME
# ex. __sm.process.pid.read NAME
__sm.process.pid.read()
{
if cat ".${1}.pid" 2>/dev/null
then return 0
else return $?
fi
}
# write a PID to pid file NAME
# ex: __sm.process.pid.write NAME PID
# delete pid file NAME if no PID
# ex: __sm.process.pid.write NAME
__sm.process.pid.write()
{
if [[ -n "${2:-}" ]]
then echo "$2" > ".${1}.pid" 2>/dev/null
else rm -f ".${1}.pid" 2>/dev/null
fi
}
# Check if a process with a given PID is working
# ex. __sm.process.pid.running PID
__sm.process.pid.running()
{
if kill -0 $1 2>/dev/null
then return 0
else return $?
fi
}