billhubb84 billhubb84 - 6 months ago 22
Linux Question

bash process monitor script echo empty when no process found

I've created a process monitor to check for the presence of a running process, and if found we need to check its parent to determine if it is acceptable or not, it's a security check basically. It works great when I look for running processes and gives me output that I expect. However, for some reason when no process is found, it's spitting out an empty line instead of "ok" like I would expect. I know that the variable rmanRUNNING is being populated with a 0 if no process is running, I've checked, so I'm not sure why the first if statement isn't just failing over to the else and then performing the echo "ok" line before closing. Any help will be GREATLY appreciated. See below:

#!/bin/bash

rmanRUNNING=`ps -ef|grep rman|egrep -v grep|wc -l`

if [ "$rmanRUNNING" -gt "0" ]
then
PPIDs=($( ps -oppid= $(pgrep rman)))
kshddPID=($(pgrep -f 'ksh.*/rman_dd.ksh'))
for i in "${PPIDs[@]}"
do
:
for j in "${kshddPID[@]}"
do
:
if [ "$i" == "$j" ]
then
result="ok"
else
result="bad"
break
fi
done
if [ "$result" == "bad" ]
then
break
fi
done
echo "$result"
else
echo "ok"
fi


I must be missing something simple, I just can't seem to isolate it, if I simplify this to be just the if with the current conditional and then an echo followed by an else and an echo, it seems to work right, so I feel it's something to do with the loops inside the main if that are causing some error that I don't see. Or, perhaps it has to do with a misunderstanding of how break works so I'm breaking out to a point where I echo an empty "result" variable and then terminating, I'm just not sure.

Thanks in advance!

Answer

The problem is that ps -ef | grep rman | grep -v grep is matching the process name rman_check.sh. So when you run your script, $rmanRunning is not 0, because it's counting itself.

Use pgrep with the -x option so that it matches the command name exactly, rather than looking for a substring.

#!/bin/bash

rmanRunning=$(pgrep -x rman | wc -l)

if [ "$rmanRUNNING" -gt "0" ]
 then
    PPIDs=($( ps -oppid= $(pgrep -x rman)))
    kshddPID=($(pgrep -f 'ksh.*/rman_dd.ksh'))
    for i in "${PPIDs[@]}"
    do
        :
        for j in "${kshddPID[@]}"
        do
            :
            if [ "$i" == "$j" ]
                then
                    result="ok"
            else
                result="bad"
                break
            fi
        done
        if [ "$result" == "bad" ]
            then
                break
        fi
    done
    echo "$result"
else
    echo "ok"
fi

However, there's also a problem with your overall logic. If you have two rman_dd.ksh processes and they each have an rman child, you'll report bad when you compare one parent with the other. A simpler way is to just sort the two PID lists and compare them.

PPIDs=$(pgrep -x rman | sort)
kshddPIDs=$(pgrep -f 'ksh.*rman_dd.ksh' | sort)
if [ "$PPIDs" = "$kshddPIDs" ]
then echo "ok"
else echo "bad"
fi
Comments