-
Notifications
You must be signed in to change notification settings - Fork 1
/
zap-proc
151 lines (130 loc) · 2.87 KB
/
zap-proc
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
#!/usr/bin/env bash
#
# Synopsis:
# Safe, chatty zap of process using variations of pkill.
# Description:
# Zap a process whose id is stored in a file. Should the file not
# exist or not disappear after pkill -F, then force killing process
# with an explicit list of process names. Explicit process names
# are used to prevent killing invoking scripts with names similar
# to victim processes.
# Usage:
# zap-proc <pid-file>
# zap-proc <pid-file> <exact-proc1-name> <exact-proc2-name> ...
# Exit Status:
# 0 probably no processes running
# 1 unexpected error
# Note:
# Shouldn't zap-proc ALWAYS specify "-F pidfile", for both GRACEFUL
# and EXACT kills?
#
PROG=$(basename $0)
PROC_OWNER=$(id -nu)
PROC_PAUSE=3
log()
{
if [ -z "$PROC_NAME" ]; then
PROC_WHO="$PROG#$$: $PROC_SUFFIX"
else
PROC_WHO="$PROG#$$"
fi
echo "$(date +'%Y/%m/%d %H:%M:%S'): $PROC_WHO: $@"
}
ERROR()
{
log "ERROR: $@" >&2
}
die()
{
ERROR "$@"
exit 1
}
_zap()
{
WHAT=$1
shift
log "pkill: $WHAT: $@"
pkill -u $PROC_OWNER $@
STATUS=$?
case $STATUS in
0)
;;
1)
log "WARN: $WHAT: no process running (ok)"
;;
*)
die "pkill $WHAT failed: exit status=$STATUS"
;;
esac
rm -f $PID_PATH || die "rm -f pid file failed: exit status=$?"
}
# zap list of processes with particular names
_name_zap()
{
if [ $CLI_ARGC = 0 ]; then
_zap EXACT $PROC_NAME
exit
fi
log "EXACT: forcing the kill of $CLI_ARGC processes"
for EXACT_PROC in $CLI_ARGV; do
_zap EXACT -x $EXACT_PROC || exit 1
done
exit 0
}
# zap process when contents of pid file may be corrupt.
_corrupt_zap()
{
ERROR "corrupted pid file: $PID_PATH"
if [ -s $PID_PATH ]; then
ERROR "hex dump of pid file: $PID_PATH"
echo
hexdump -C $PID_PATH
echo
else
ERROR 'pid file is empty'
fi
_name_zap || exit 1
}
test $# = 0 && die 'no arguments: pid file must be first argument'
PID_PATH=$1
shift
PROC_NAME=$(basename $(basename $PID_PATH) .pid)
log "process owner: $PROC_OWNER"
CLI_ARGC=$#
CLI_ARGV=$*
if [ ! -e $PID_PATH ]; then
log "no pid file (ok): $PID_PATH"
log "process $PROC_NAME may not be running"
_name_zap
exit
fi
log "pid file exists: $PID_PATH"
if [ ! -s $PID_PATH ]; then
log "WARN: empty pid file: $PID_PATH"
_name_zap
exit
fi
# first line of pid contains the process id
PID=$(cat $PID_PATH | head -1)
case "$PID" in
[0-9]*)
log "process to kill: $PROC_NAME#$PID owned by $PROC_OWNER"
;;
*)
ERROR "first line of pid file is not number: $PID"
_corrupt_zap
exit
esac
_zap GRACEFUL -F $PID_PATH
test $? -lt 2 || exit 1
log "zapped $PROC_NAME process with pid #$PID"
log "sleeping $PROC_PAUSE sec while process #$PID exits ..."
sleep $PROC_PAUSE
test -e $PID_PATH || exit 0
log "pid file still exists, so force exact kill"
_name_zap
test -e $PID_PATH || exit 0
log "hmm, pid still exists, so nuke $PID with -9 and remove pid file"
kill -9 $PID
rm -f $PID_PATH || die "rm -f $PID_PATH failed: exit status=$?"
exit 0