-
Notifications
You must be signed in to change notification settings - Fork 36
/
killprocess.sh
422 lines (368 loc) · 14.8 KB
/
killprocess.sh
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
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#!/bin/bash
#
# Author: Lorenzo Padovani
# @padosoft
# https://github.com/lopadova
# https://github.com/padosoft
# Depending on your 'top' version and OS you might have
# to change head and tail line-numbers
#
#process command name to check
declare -a KILLLIST
KILLLIST=("/usr/sbin/apache2" "/usr/bin/php5-cgi")
#email (if empty no email will sent)
EMAIL="[email protected]"
#max cpu % load
MAX_CPU=90
#max execution time for CPU percentage > MAX_CPU (in seconds 7200s=2h)
MAX_SEC=1800
#max execution time for any %CPU (in seconds 2700s=45min)
MAX_SEC2=2700
#MAX_RAM in Kilobytes ex.: 250MB = 250*1024 = 256000 kb, 350MB=358400)
MAX_RAM=358400
#exclude root process (leave empty for match root process too)
EXCLUDE_ROOT="grep -v root"
#colors
RED=`tput setaf 1`
GREEN=`tput setaf 2`
YELLOW=`tput setaf 3`
NC=`tput sgr0` # No Color
#set screen width
#if you command (specially if executed in cron) truncate columns to 80 less chars
#and your line is too long, set the right columns number here.
#leave empty string "" for default columns environment.
COLSNUM=""
#
# Load config file if exists
#
CONFIG_DIR=$( dirname "$(readlink -f "$0")" )
CONFIG_FILE="$CONFIG_DIR/killprocess.config"
if [[ -f $CONFIG_FILE ]]; then
echo "${YELLOW}Loading settings from $CONFIG_FILE. ${NC}"
source $CONFIG_FILE
else
echo "${RED}Could not load settings from $CONFIG_FILE (file does not exist), kill process use default settings.${NC}"
fi
#
# PARSE ARGUMENTS
#
#print command signature and usage
if [ "$1" = "" ] || [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then
printf '%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n' \
"USAGE: bash $0 [dry|kill|--help] [top|ps] [cpu|time|mem]" \
"Example:" \
"bash $0 dry" \
"bash $0 dry top" \
"bash $0 kill top cpu" \
"For memory use only ps (if you pass top force it to ps):" \
"bash $0 kill ps mem" \
"For help:" \
"bash $0" \
"OR" \
"bash $0 --help" >&2
exit 0
fi
#check if needed to set columns
if [ "$COLSNUM" = "" ]; then
echo "process use default environment columns number."
else
echo "process set '${YELLOW}${COLSNUM}${NC}' columns number."
fi
#kill or not kill?
if [ "$1" = "kill" ]; then
KILL=1
echo "${RED}Process execute in 'kill' mode.${NC}"
else
KILL=0
echo "Process execute in '${YELLOW}dry${NC}' mode (no kill)."
fi
#command to retrive process
if [ "$2" = "ps" ]; then
CMD="ps"
echo "Process fetched by '${YELLOW}ps${NC}' command"
elif [ "$2" = "top" ]; then
CMD="top"
echo "Process fetched by '${YELLOW}top${NC}' command"
else
CMD="top"
echo "Process fetched by '${YELLOW}top${NC}' command"
fi
#process Sort by
SORTBYN=""
if [ "$3" = "cpu" ]; then
if [ "$CMD" = "ps" ]; then
SORTBY=2
else
SORTBY=9
fi
echo "Process sort by ${YELLOW}%CPU${NC} ( $SORTBY )"
elif [ "$3" = "time" ]; then
if [ "$CMD" = "ps" ]; then
SORTBY=3
else
SORTBY=11
SORTBYN="-n"
fi
echo "Process sort by ${YELLOW}TIME${NC} ( $SORTBY $SORTBYN)"
else
if [ "$CMD" = "ps" ]; then
SORTBY=2
else
SORTBY=9
fi
echo "Process sort by default ${YELLOW}CPU${NC} ( $SORTBY )"
fi
#iterate for each process to check in list
for PROCESS_TOCHECK in ${KILLLIST[*]}
do
echo "Check ${YELLOW}$PROCESS_TOCHECK${NC} process..."
if [ "$3" = "mem" ]; then
#check for memory
#pid
if [ "$COLSNUM" = "" ]; then
PID=$(ps -eo pid,rss,command --sort -rss | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $1}')
else
PID=$(ps --cols ${COLSNUM} -eo pid,rss,command --sort -rss | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $1}')
fi
if [ -z "$PID" ]; then
echo "${GREEN}There isn't any matched process for $PROCESS_TOCHECK${NC}"
continue
fi
#MEM
if [ "$COLSNUM" = "" ]; then
MEM=$(ps -eo pid,rss,command --sort -rss | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $2}')
else
MEM=$(ps --cols ${COLSNUM} -eo pid,rss,command --sort -rss | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $2}')
fi
if [ -z "$MEM" ]; then
echo "${GREEN}There isn't any matched process for $PROCESS_TOCHECK${NC}"
continue
fi
MEMMB=$((MEM / 1024))
#Fetch other process stats by pid
#% CPU
if [ "$COLSNUM" = "" ]; then
CPU=$(ps -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $2}')
else
CPU=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $2}')
fi
#format integer cpu
CPU=${CPU%%.*}
#process name
if [ "$COLSNUM" = "" ]; then
PNAME=$(ps -p $PID -o pid,pcpu,time,comm,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
else
PNAME=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,comm,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
fi
#full process command
if [ "$COLSNUM" = "" ]; then
COMMAND=$(ps -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
else
COMMAND=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
fi
#user
if [ "$COLSNUM" = "" ]; then
USER=$(ps -p $PID -o pid,pcpu,time,user,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
else
USER=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,user,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | head -n 1 | awk '{print $4}')
fi
#process summary
echo "${YELLOW}TOP MEMORY consuming $PROCESS_TOCHECK process is:${NC}"
echo "PID:$PID"
echo "PNAME:$PNAME"
echo "CPU:$CPU"
echo "MEM:${MEMMB}MB (${MEM}kb)"
MAX_RAM_MB=$((MAX_RAM / 1024))
echo "MAX_RAM is ${MAX_RAM_MB}MB"
echo "USER:$USER"
echo "COMMAND:$COMMAND"
#if user process is root, skip it
if [ "$USER" = "root" ]; then
echo "this is a root process, skip it!"
echo " "
continue;
fi
if [ $MEM -gt $MAX_RAM ]; then
echo "WEB: The process $PNAME ( PID: $PID ) User: $USER has reaches ${MEMMB}MB more than ${MAX_RAM_MB}MB of max allowed memory"
if [ ! -z $EMAIL ]; then
echo "Send Mail to $EMAIL"
mail -s "WEB: The process $PNAME ( PID: $PID ) User: $USER has reaches ${MEMMB}MB more than ${MAX_RAM_MB}MB of max allowed memory" $EMAIL < .
fi
if [ "$KILL" = "1" ]; then
echo "${RED}kill -15 $PID${NC}"
kill -15 $PID
sleep 3
echo "kill -9 $PID"
kill -9 $PID
echo "kill zombies"
kill -HUP $(ps -A -ostat,ppid | grep -e '[zZ]'| awk '{ print $2 }')
fi
else
echo "${GREEN}$PROCESS_TOCHECK it's OK!${NC}"
fi
else
#pid
if [ "$CMD" = "ps" ]; then
if [ "$COLSNUM" = "" ]; then
PID=$(ps -eo pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $1}')
else
PID=$(ps --cols ${COLSNUM} -eo pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $1}')
fi
else
if [ "$COLSNUM" = "" ]; then
PID=$(top -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort $SORTBYN -k $SORTBY -r | head -n 1 | awk '{print $1}')
else
PID=$(COLUMNS=${COLSNUM} top -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort $SORTBYN -k $SORTBY -r | head -n 1 | awk '{print $1}')
fi
fi
if [ -z "$PID" ]; then
echo "${GREEN}There isn't any matched process for $PROCESS_TOCHECK${NC}"
continue
fi
#Fetch other process stats by pid
#% CPU
if [ "$CMD" = "ps" ]; then
if [ "$COLSNUM" = "" ]; then
CPU=$(ps -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $2}')
else
CPU=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $2}')
fi
else
if [ "$COLSNUM" = "" ]; then
CPU=$(top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $9}')
else
CPU=$(COLUMNS=${COLSNUM} top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $9}')
fi
fi
#format integer cpu
CPU=${CPU%%[.,]*}
#time elapsed d-HH:MM:ss
if [ "$CMD" = "ps" ]; then
if [ "$COLSNUM" = "" ]; then
TIME_STR=$(ps ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $3}')
else
TIME_STR=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $3}')
fi
else
if [ "$COLSNUM" = "" ]; then
TIME_STR=$(top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $11}')
else
TIME_STR=$(COLUMNS=${COLSNUM} top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $11}')
fi
fi
#process name
if [ "$COLSNUM" = "" ]; then
PNAME=$(ps -p $PID -o pid,pcpu,time,comm,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
else
PNAME=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,comm,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
fi
#full process command
if [ "$CMD" = "ps" ]; then
if [ "$COLSNUM" = "" ]; then
COMMAND=$(ps -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
else
COMMAND=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
fi
else
if [ "$COLSNUM" = "" ]; then
COMMAND=$(top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $12,$13,$14}')
else
COMMAND=$(COLUMNS=${COLSNUM} top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $12,$13,$14}')
fi
fi
#user
if [ "$CMD" = "ps" ]; then
if [ "$COLSNUM" = "" ]; then
USER=$(ps -p $PID -o pid,pcpu,time,user,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
else
USER=$(ps --cols ${COLSNUM} -p $PID -o pid,pcpu,time,user,command | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $4}')
fi
else
if [ "$COLSNUM" = "" ]; then
USER=$(top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $2}')
else
USER=$(COLUMNS=${COLSNUM} top -p $PID -bcSH -n 1 | $EXCLUDE_ROOT | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $2}')
fi
fi
# Decode the CPU time format [dd-]hh:mm:ss.
TIME_SEC=0
IFS="-:" read c1 c2 c3 c4 <<< "$TIME_STR"
#with top command time format is hh:mm.ss, so truncare seconds in c2
c2=${c2%%.*}
if [ -n "$c4" ]
then
TIME_SEC=$((10#$c4+60*(10#$c3+60*(10#$c2+24*10#$c1))))
elif [ -n "$c3" ]
then
if [ "$CMD" = "ps" ]; then
TIME_SEC=$((10#$c3+60*(10#$c2+60*10#$c1)))
else
TIME_SEC=$(((10#$c3*24)*60*60)+60*(10#$c2+60*10#$c1))
fi
else
if [ "$CMD" = "ps" ]; then
TIME_SEC=$((10#0+(10#$c2+60*10#$c1)))
else
TIME_SEC=$((10#0+60*(10#$c2+60*10#$c1)))
fi
fi
#process summary
if [ "$3" = "time" ]; then
echo "${YELLOW}TOP Long Time $PROCESS_TOCHECK process is:${NC}"
else
echo "${YELLOW}TOP %CPU consuming $PROCESS_TOCHECK process is:${NC}"
fi
echo "c1:$c1"
echo "c2:$c2"
echo "c3:$c3"
echo "c4:$c4"
echo "PID:$PID"
echo "PNAME:$PNAME"
echo "CPU:$CPU"
echo "TIME_STR:$TIME_STR"
echo "TIME_SEC:$TIME_SEC"
echo "USER:$USER"
echo "COMMAND:$COMMAND"
#if user process is root, skip it
if [ "$USER" = "root" ]; then
echo "this is a root process, skip it!"
echo " "
continue;
fi
#check if need to kill process
if [ $CPU -gt $MAX_CPU ] && [ $TIME_SEC -gt $MAX_SEC ]; then
echo "CPU load from process $PNAME ( PID: $PID ) User: $USER has reached ${CPU}% for $TIME_STR. Process was killed."
if [ ! -z $EMAIL ]; then
echo "Send Mail to $EMAIL"
mail -s "WEB: CPU load from process $PNAME ( PID: $PID ) User: $USER has reached ${CPU}% for $TIME_STR. Process was killed." $EMAIL < .
fi
if [ "$KILL" = "1" ]; then
echo "${RED}kill -15 $PID${NC}"
kill -15 $PID
sleep 3
echo "kill -9 $PID"
kill -9 $PID
echo "kill zombies"
kill -HUP $(ps -A -ostat,ppid | grep -e '[zZ]'| awk '{ print $2 }')
fi
elif [ $TIME_SEC -gt $MAX_SEC2 ]; then
echo "WEB: The process $PNAME ( PID: $PID ) User: $USER has running too long for $TIME_STR"
if [ ! -z $EMAIL ]; then
echo "Send Mail to $EMAIL"
mail -s "WEB: The process $PNAME ( PID: $PID ) User: $USER has running too long for $TIME_STR" $EMAIL < .
fi
if [ "$KILL" = "1" ]; then
echo "${RED}kill -15 $PID${NC}"
kill -15 $PID
sleep 3
echo "kill -9 $PID"
kill -9 $PID
echo "kill zombies"
kill -HUP $(ps -A -ostat,ppid | grep -e '[zZ]'| awk '{ print $2 }')
fi
else
echo "${GREEN}$PROCESS_TOCHECK it's OK!${NC}"
fi
fi
echo " "
done