More
author |
Steve Losh <steve@stevelosh.com> |
date |
Sun, 18 Jun 2023 12:01:14 -0400 |
parents |
758d680aa791 |
children |
(none) |
#!/bin/bash
# https://gist.github.com/anonymous/32b1e619bc9e7fbe0eaa
# Signal numbers to use. Configurable, as long as the number of elements in this
# array matches the number of elements in $delays.
signals=(15 2 1 9)
# How much time processes should be given to finish their work before we try the
# next signal. Configurable, as long as the number of elements in this array
# matches the number of elements in $signals.
delays=(10 10 15 1)
# Takes a list of PIDs and ends the processes through increasingly rude means.
function mykill {
local ps='ps'
ps="$ps o pid="
# Figure out the names of the signals we will try.
local names=($(kill -l ${signals[@]}))
local retval=0
if [[ $# -eq 0 ]]; then
printf 'murder: Too few arguments: %d\nmurder: Usage: murder <PIDs...>\n' $#
retval=1
else
for pid in $@; do
local index=0
# Try the next signal if the process is alive AND there are more
# signals to attempt AND the previous kill reported no errors.
while $ps $pid > /dev/null && [[ $index -lt ${#signals} ]] && [[ $retval -eq 0 ]]; do
echo trying: kill -s ${signals[$index]} $pid
output=$(kill -s ${signals[$index]} $pid 2>&1)
retval=$?
local killed=1
# Give the process some time to finish.
sleep ${delays[$index]}
index=$(($index + 1))
done
if [[ -z $killed ]]; then
printf 'murder: Process with PID %d does not exist.\n' $pid
elif ! ${ps} ${pid} > /dev/null; then
index=$(($index - 1))
printf 'murder: Killed process with PID %d with signal %s (%d).\n' $pid ${names[$index]} ${signals[$index]}
elif [[ ${retval} -ne 0 ]]; then
printf 'murder: kill failed: %s\n' $(echo ${output} | cut -d ' ' -f 5-)
elif [[ ${index} -eq ${#signals} ]]; then
printf 'murder: Failed to kill process with PID %d with signals %s\n' $pid "$(echo ${names[@]})"
retval=-1
fi
done
fi
return ${retval}
}
mykill $@