Score:-1

How to check if pkill was successful

in flag

We use pkill to check if a program is running to kill it before restarting it when new code is being deployed.

pkill --signal 15 --pidfile programname.pid

This normally works, but when there is a problem and the application program hangs, signal 15 doesn't kill the process. The exit codes for pkill are:

EXIT STATUS
       0      One or more processes matched the criteria.
       1      No processes matched.
       2      Syntax error in the command line.
       3      Fatal error: out of memory etc.

For obvious reasons to me after thinking about it, it cannot return a code to indicate that the process kill was successful, since pkill only sends a signal to it and nothing more. So I will have to check if the process was ended and if not try again with signal 9 and if not killed yet, try with signal 6 (or some others even).

So I guess doing some kind of if/elif/else/fi to test for this should suffice:

#!/bin/bash
pkill --signal 15 --pidfile programname.pid
result1=$?
echo 'result1 is ' $result1
if [ "$result1" -eq 0 ]  
then
    echo "programname found running"
    pgrep --pidfile programname.pid
    result2=$?
    if [ "$result2" -eq 1 ]
    then
        # happens if pid# is not found
        echo "programname killed successfully with signal 15"
        # restart the program that was killed
    else
        pkill --signal 9 --pidfile programname.pid
        result3=$?
        if [ "result3" -eq 0 ]
        then
            pgrep --pidfile programname.pid
            result4=$?
            if [ "result4" -eq 1 ]
            then
                echo "programname killed successfully with signal 9"
                # restart the pgram that was killed
            fi
        fi
    fi
elif [ $result1 -eq 1 ]
then
    echo "programname pid# not found. Is the system running?"
else
    echo "pkill exited with error" $result1
fi

echo 'Continue...'

This all seems a bit convoluted, or am I just being pedantic? Is there a better way to achieve this result in a script?

cn flag
we don't accept questions about 14.04.
guiverc avatar
cn flag
Only supported releases of Ubuntu (*standard support*) are on-topic for this site. Ubuntu 14.04 LTS is in extended support and now Ubuntu 14.04 ESM thus only supported by Canonical via Ubuntu Advantage and off-topic here. Refer https://askubuntu.com/help/on-topic https://help.ubuntu.com/community/EOLUpgrades http://fridge.ubuntu.com/2019/05/02/ubuntu-14-04-trusty-tahr-reached-end-of-life-on-april-25-2019-esm-available/
Marco avatar
br flag
Kill with signal 0 should show if a process is still running.
in flag
Since this is a question about bash scripting in general, I have removed the offensive version ref from the post... I think, try to focus in the issue, not on the irrelevant "problem"
in flag
@Marco, would this differ significantly from using pgrep to determine if the process is still running?
Marco avatar
br flag
@LifeBoy if you have the id anyway, you can use the `kill` command which reduces dependencies, because `kill` is part of bash. Otherwise there is no difference.
in flag
@muru, why did you remove the bash and pkill tags? Surely they are relevant? If I were looking for a solution in such a scenario, having these tags would be really helpful? Maybe you can explain the reasons, so I can understand this better please.
muru avatar
us flag
@LifeBoy you're using bash, yes, but I don't see anything bash-specific here. The script is pretty much standard shell, you could have run it using dash or ksh without making any difference. People over use the bash tag here when all they want is a command-line solution without caring for bashisms. As for pkill, I didn't see any reason for this command to have its own tag - it's not hard to search for and it's _exactly_ the same command as pgrep (check it, they're the same binary).
Score:0
in flag

I decided that creating a function to do this is the better option. Also, using a for loop seems to be a neater solution:

#!/bin/bash
trykill () {

    timeout=${2:-5} 
    # echo "wait =" $timeout

    # Run the loop for signal 15, 9 and 6
    for n in 15 9 6;
    do
        if [[ -f "$1.pid" ]]; then
            pkill --signal $n --pidfile $1.pid  
            result1=$?
        else
            result1=1
        fi
        #echo 'result1 is ' $result1
        if [ "$result1" -eq 0 ]  
        then
            echo $1 "found running, waiting" $timeout "seconds for process to die."
            sleep $timeout  # Wait # seconds set by second parameter
            pgrep --pidfile $1.pid
            result2=$?
            if [ "$result2" -eq 1 ]
            then
                 # happens if pid# is not found
                echo $1 "killed successfully with signal" $n"."
                return 0
            fi
        elif [ $result1 -eq 1 ]
        then
            echo $1".pid # not found." $1 "doesn't seem to be running. Starting it anyway."
            return 0
        else
            echo "pkill exited with error" $result1
            return 1
        fi
    done
}

And I call the function for each service I want to restart. Here's a example script to do that.

#!/bin/bash
source trykill.sh

trykill $1
result1=$?
#echo 'result1 is ' $result1
if [ "$result1" -eq 0 ]  
then
    echo 'Start' $1 'again'
fi

echo 'Done.'
Marco avatar
br flag
According to the manual, the exit code of `pkill` can not be used to tell if `pkill` killed the process successful. e.g exit 1 if no process can be found.
in flag
@Marco, that's why I check with pgrep to see if the process still exists after the pkill. That way I know whether pkill was successful or not.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.