bin/murder @ eb9f31c299b8

Merge
author Steve Losh <steve@stevelosh.com>
date Tue, 02 Jul 2024 10:03:59 -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 $@