My Script For Process Checking is NOT Working

Hello there ULF,

Good day! Just want to share my code and as well as my problem on why I'm not getting the output that I want. My original code was:

#!/usr/bin/sh

echo
echo -n "Please input an IP-Pool: "
read ip
echo
echo "Please wait....."
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker1.sh $ip > temp_output
sleep 15
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker2.sh $ip | grep -v NOTE >> temp_output
sleep 1
cp temp_output final_output
pd1=`cat temp_output | awk 'NR==10 {print $3}'`
bd1=`cat temp_output | awk 'NR==11 {print $3}'`
pu1=`cat temp_output | awk 'NR==12 {print $3}'`
bu1=`cat temp_output | awk 'NR==13 {print $3}'`
pd2=`cat temp_output | awk 'NR==18 {print $3}'`
bd2=`cat temp_output | awk 'NR==19 {print $3}'`
pu2=`cat temp_output | awk 'NR==20 {print $3}'`
bu2=`cat temp_output | awk 'NR==21 {print $3}'`
pd=$(expr $pd2 - $pd1)
bd=$(expr $bd2 - $bd1)
pu=$(expr $pu2 - $pu1)
bu=$(expr $bu2 - $bu1)
echo >> final_output
echo "Delta Summary:" >> final_output
echo "==============" >> final_output
echo "Delta Pkts-Dwn: $pd" >> final_output
echo "Delta Bytes-Dwn: $bd" >> final_output
echo "Delta Pkts-Up: $pu" >> final_output
echo "Delta Bytes-Up: $bu" >> final_output
cat final_output
rm temp_output
rm final_output
echo

Now since this script can be used by other users, there will be a possibility of having simultaneous running-process for this script which will lead to a wrongly data to be parsed, so in order for this one not to happen, I want to check if the process is running it will prompt the user that it's not yet safe to run the script otherwise begin using it. So I've decided to put something like this into my code:

#!/usr/bin/sh

psef=`ps -ef | grep IP-PoolSession-Summary.sh | grep -v grep | wc -l`
if [ $psef -eq 1 ]; 
then
echo
echo -e "\033[41;37mSorry! Another user is currently running the script. Please try again later.\033[0m"
echo
exit
else
echo -n "Please input an IP-Pool: "
read ip
echo
echo "Please wait....."
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker1.sh $ip > temp_output
sleep 15
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker2.sh $ip | grep -v NOTE >> temp_output
sleep 1
cp temp_output final_output
pd1=`cat temp_output | awk 'NR==10 {print $3}'`
bd1=`cat temp_output | awk 'NR==11 {print $3}'`
pu1=`cat temp_output | awk 'NR==12 {print $3}'`
bu1=`cat temp_output | awk 'NR==13 {print $3}'`
pd2=`cat temp_output | awk 'NR==18 {print $3}'`
bd2=`cat temp_output | awk 'NR==19 {print $3}'`
pu2=`cat temp_output | awk 'NR==20 {print $3}'`
bu2=`cat temp_output | awk 'NR==21 {print $3}'`
pd=$(expr $pd2 - $pd1)
bd=$(expr $bd2 - $bd1)
pu=$(expr $pu2 - $pu1)
bu=$(expr $bu2 - $bu1)
echo >> final_output
echo "Delta Summary:" >> final_output
echo "==============" >> final_output
echo "Delta Pkts-Dwn: $pd" >> final_output
echo "Delta Bytes-Dwn: $bd" >> final_output
echo "Delta Pkts-Up: $pu" >> final_output
echo "Delta Bytes-Up: $bu" >> final_output
cat final_output
rm temp_output
rm final_output
echo
fi

The problem with this code is that it's not prompting the user and still continues and proceed with the original code (which is after the else function) even if I already ran one before running it again.

Then I've modified the if/else by doing something like this:

#!/usr/bin/sh

psef=`ps -ef | grep IP-PoolSession-Summary.sh | grep -v grep | wc -l`
if [ $psef -eq 1 ]; then
echo
echo -e "\033[41;37mSorry! Another user is currently running the script. Please try again later.\033[0m"
echo
exit
elif [ $psef -eq 0 ]; then
echo
echo -n "Please input an IP-Pool: "
read ip
echo
echo "Please wait....."
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker1.sh $ip > temp_output
sleep 15
/home/nsadm/scripts/IP-PoolSession-Checker/ip_checker2.sh $ip | grep -v NOTE >> temp_output
sleep 1
cp temp_output final_output
pd1=`cat temp_output | awk 'NR==10 {print $3}'`
bd1=`cat temp_output | awk 'NR==11 {print $3}'`
pu1=`cat temp_output | awk 'NR==12 {print $3}'`
bu1=`cat temp_output | awk 'NR==13 {print $3}'`
pd2=`cat temp_output | awk 'NR==18 {print $3}'`
bd2=`cat temp_output | awk 'NR==19 {print $3}'`
pu2=`cat temp_output | awk 'NR==20 {print $3}'`
bu2=`cat temp_output | awk 'NR==21 {print $3}'`
pd=$(expr $pd2 - $pd1)
bd=$(expr $bd2 - $bd1)
pu=$(expr $pu2 - $pu1)
bu=$(expr $bu2 - $bu1)
echo >> final_output
echo "Delta Summary:" >> final_output
echo "==============" >> final_output
echo "Delta Pkts-Dwn: $pd" >> final_output
echo "Delta Bytes-Dwn: $bd" >> final_output
echo "Delta Pkts-Up: $pu" >> final_output
echo "Delta Bytes-Up: $bu" >> final_output
cat final_output
rm temp_output
rm final_output
echo
fi

As you can see, I've just changed the if/else to if/elif, but again the output is that after executing the script, it automatically exits. No prompt appeared even.

Can you please help me with this problem? I'm working on a SUSE Linux.

Thanks and Best Regards,
rymnd_12345

Try :

psef=`ps -ef | grep IP-PoolSession-Summary.sh | grep -v grep | wc -l`
if [ $psef -ge 1 ]; 
then
    echo
    echo -e "\033[41;37mSorry! Another user is currently running the script. Please try again later.\033[0m"
    echo
    exit
else

or

if ps -ef | grep -q P-PoolSession-Summary.sh
then
    echo
    echo -e "\033[41;37mSorry! Another user is currently running the script.  Please try again later.\033[0m"
    echo
    exit
else

jean-Pierre.

I would use a lock file for this (the number of the process may vary between different shells).

Hi aigles,

Thanks for your input, I've tried using those two (2) suggestions but both of them resulted to same output like below:

user# ./IP-PoolSession-Summary.sh

Sorry! Another user is currently running the script.  Please try again later.

This is what I always get even if I didn't yet run the script prior running it again and I've also checked that no one uses it.

Hi radoulov.

How's that?

Thanks!

BR,
Raymond

Try printing the output of the ps command at the beginning of your script:

(ps -ef | grep P-PoolSession-Summary.sh)

You'll see the current instance of your script.
Than try to invoke the script like this and compare the output:

bash <your_script_name>
ksh <your_script_name>

To elaborate further: you cannot only check the presence of your script in the process list for obvious reasons: your script
is running when you're running the ps .. | grep .. pipeline, so this thest will always return true.
If you count with ps .. | grep -c .. the output will depend on the shell implementation
(some shells thread differently the last command in a pipeline).

So, again, for a more robust solution, I'd suggest the implementation of some
locking mechanism.

Assuming that the script containing the duplicate session test is called
IP-PoolSession-Summary.sh then surely one copy running is not a problem ($psef -eq 1). The second and subsequent copies are a problem ($psef -ge 2). Don't forget to count the script you are running the test from!

psef=`ps -ef | grep "IP-PoolSession-Summary.sh" | grep -v "grep" | wc -l`
if [ $psef -ge 2 ]

I too recommend using flag files. The output from ps is not reliable enough for this type of processing.

Hi radoulov,

How is it? about the locking mechanism? How to do it?

Hi methyl,

I've tried simulating it, and still it returned the error prompt even without running the script yet, then I noticed that as if it includes the count of the

grep -v "grep"

still. So what I've did is to have it this way:

psef=`ps -ef | grep "IP-PoolSession-Summary.sh" | grep -v "grep" | wc -l`
if [ $psef -ge 3 ]; then
echo
echo -e "\033[41;37mSorry! Another user is currently running the script. Please try again later.\033[0m"

and it worked... don't know why it behaved that way.

Thanks for all you input.
Still expecting for a better solution like locking mechanism though.

BR,
Raymond

This should work fine if you're sure that your script will always be executed with bash
(and - really less likely to happen - that the name of the script will never appear in the process list for some other reason).

You may implement a lock/flag file like this:

_lock_dir=<some_lock_dir>
_lock_file=${0##*/}.lck

[ -f "$_lock_dir/$_lock_file" ] && [ ! -L "$_lock_dir/$_lock_file" ] && {
  printf >&2 'another instance of %s is already running: $s\n' "${0##*/}" "$(< "$_lock_dir/$_lock_file")"
  exit 1
  }

[ -d "$_lock_dir" ] || 
  mkdir "$_lock_dir" || {
    printf >&2 'failed to create lock dir: %s\n' "$_lock_dir"
    exit 1
    }

printf > "$_lock_dir/$_lock_file" '%d\n' $$

<the rest of your code here ... >

# remove the lock file at the end

[ -f "$_lock_dir/$_lock_file" ] && [ ! -L "$_lock_dir/$_lock_file" ] &&
  rm -- "$_lock_dir/$_lock_file" || {
    printf >&2 'failed to remove lock file: %s\n' "$_lock_dir/$_lock_file"
    exit 1
    }
  1. In the above demo I'm using some constructs that are not available in the old (the traditional) Bourne shell (the parameter expansion).
  2. In one place I'm using a non standard (not POSIX) syntax, but that construct is available in most modern shells.

Let me know if that's a problem for you.

Hi radoulov,

Thanks dude!

ULF, Thank you all! Til next time :slight_smile:

BR,
Raymond