LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   to check instance of a script running (http://www.linuxquestions.org/questions/programming-9/to-check-instance-of-a-script-running-416666/)

kushalkoolwal 02-17-2006 06:13 PM

to check instance of a script running
 
Hi,

I have a script called check.sh which does a bunch of things and generally takes 5-10 mins to process.I run it from the /root/check.sh location. Now I would like to know how can I prevent it to run when it is already running. In short how can I make sure that the user does not run the second instance(by mistake) of that script while it is already running.

How can I check this in the check.sh script itself? What lines will I have to write at the beginning of the script to achieve this.

Thanks

satinet 02-17-2006 06:18 PM

you could create a lock file. crude but works? or where u thinking of somehting more technical?

kushalkoolwal 02-17-2006 08:02 PM

Quote:

Originally Posted by satinet
you could create a lock file. crude but works? or where u thinking of somehting more technical?

yeah some example which I can follow and implement in my own script.

thanks for the effort though...

baldwonder 02-17-2006 11:55 PM

I'm not entirely sure, but putting this code at the beginning of check.sh should do the trick:

Code:

#! /bin/bash

test=$(ps aux|grep check.sh|wc -l)

if [ $test -ne 0 ]; then
  exit
fi

.... rest of code for check.sh

it should check and see if check.sh is running. If it is, it will just exit without executing anything, otherwise it will execute the rest of the script.

kushalkoolwal 02-18-2006 07:43 AM

Quote:

Originally Posted by baldwonder
I'm not entirely sure, but putting this code at the beginning of check.sh should do the trick:

Code:

#! /bin/bash

test=$(ps aux|grep check.sh|wc -l)

if [ $test -ne 0 ]; then
  exit
fi

.... rest of code for check.sh

it should check and see if check.sh is running. If it is, it will just exit without executing anything, otherwise it will execute the rest of the script.

.


Thanks baldwonder. I will try that and see how it goes. Thank you very much.

satinet 02-18-2006 12:56 PM

good idea, but even if there are no processes running "wc" reports one line.

try "ps -ef|grep -i sopnfgsdpajgsn |wc -l" and you will see what i mean.

so you might need to use:

if test $test -gt 1
then
exit 2
fi


this is because grep finds itself.

you could also do:

ps -ef|grep check.sh|grep -v grep|wc -l

or similar...

alienDog 02-18-2006 01:06 PM

One possible simple locking method for scripts:

Code:

kill -0 `cat /var/lock/yourscript 2> /dev/null` 2> /dev/null && exit 1
echo $$ > /var/lock/yourscript

It tries to send 0 signal to the pid stored in the file /var/lock/yourscript. If the signal get's send, the script is running and another instance will exit. If not, the pid is stored to /var/lock/yourscript. kill -0 only sends the signal and does nothing else, so it can well be used for something like this.

ta0kira 02-18-2006 04:18 PM

Quote:

Originally Posted by baldwonder
I'm not entirely sure, but putting this code at the beginning of check.sh should do the trick

I've tried something like this (`ps -A | grep -c " check.sh$"` -gt 1), but it doesn't work reliably from within the script itself. It works fine from another script, however. For some reason ps thinks there are 2 instances running when polled from within the script.

I use the lock file method. This is handy if you are running the script as a daemon; to terminate the daemon, design the script to stop if the lock file disappears, then design a kill script to remove the lock file. This is a much easier and safer way to terminate as opposed to finding the process number and killing it.

Here is an example: scroll down and look for the secure message interface example (mostly the 'receive' and 'kill' scripts.)
ta0kira

satinet 02-18-2006 04:29 PM

i like the kill -0 option.

there will be 2 from within the script. 1 - the script itself 2 grep finding itself greppingg. so you would have to put gt 2. sorry i didnt think of that.

the kill way is more elegant.

ta0kira 02-19-2006 12:50 PM

Quote:

Originally Posted by satinet
there will be 2 from within the script. 1 - the script itself 2 grep finding itself greppingg.

I would think it would show up as a grep and not a check.sh.

'kill 0' works fine if you are calling it from the same shell it was started in; what if it starts without a tty like in an rc, or if the process extends beyond the shell it was called in? I kind of think kill is a little sloppy anyway; it doesn't give the script a chance to exit its own way, kind of like turning off your power strip instead of shutting down your computer properly. I think it's meant to clean up messes left by processes that encounter something they can't work around and they end up hanging (and for real binaries which are designed to process a TERM signal.) Also, if you are writing or reading a fifo, you could hang another entirely separate process that's trying to use the other end of it.
ta0kira

baldwonder 02-19-2006 01:18 PM

So I realized I used the wrong ps option in my code above. If you use ps -e instead of ps aux, it will show up as code.sh and not as grep (grep will be there, but only as grep and not grep check.sh). Satinet is right, you would have to change the code to say

[code]
if [ $test -gt 1 ]; then
exit 0
fi
[\code]

since there will be one instance of the code running when you are checking for extras.

alienDog 02-19-2006 03:16 PM

Quote:

Originally Posted by ta0kira
'kill 0' works fine if you are calling it from the same shell it was started in; what if it starts without a tty like in an rc, or if the process extends beyond the shell it was called in? I kind of think kill is a little sloppy anyway; it doesn't give the script a chance to exit its own way, kind of like turning off your power strip instead of shutting down your computer properly.

You didn't pay attention to how the locking actually works. It stores the pid of the script to a file. Then when another instance of the script is started, the new script tries to send signal 0 (=do nothing) to the pid stored in the file (i.e. previous instance of the script) using the kill command. If the signal gets send it means that the script is running and the new script will exit _cleanly_. ABSOLUTELY NOTHING HAPPENS TO THE ALREADY RUNNING SCRIPT. It's not "sloppy" in any way and there is nothing in this that can be compared to turning off power without a proper shutdown. Also starting the new script from another shell, without tty etc. is no problem, the locking still works fine.

I think you must be confusing kill -0 with kill 0? The latter sends SIGTERM (signal 15) to the process group. That won't work in this case. It needs a dash.

Quote:

Originally Posted by ta0kira
I think it's meant to clean up messes left by processes that encounter something they can't work around and they end up hanging (and for real binaries which are designed to process a TERM signal.)

You think wrong ;) The kill command is quite different from SIGKILL signal that kills programs. It's just a way to send signals to processes, including things like telling the process to continue execution if it's stopped (SIGCONT, 18). Granted, the name of the command is not very well picked. You signal some stopped pid with command kill -18 [PID] and it resumes execution... How is that kill? ;)

Furthermore, the only signal that doesn't allow programs to exit their own way is the forementioned SIGKILL (signal 9). All the other signals (including SIGTERM, 15 and SIGINT, 2, which is same as CTRL+C) can be handled using the trap command, from scripts as well as binaries. Signal 0 of course doesn't need to be handled as it does nothing...

Quote:

Originally Posted by ta0kira
Also, if you are writing or reading a fifo, you could hang another entirely separate process that's trying to use the other end of it.

I honestly don't see how this could happen???

bigearsbilly 02-20-2006 11:17 AM

ps | grep isn't really resilient.
for instance it will find 'vi check.sh'
It also seems faintly inelegant to me.

pgrep -x check.sh may work better.


I generally use a lock file myself.
t seems a common idiom so maybe it works?

satinet 02-21-2006 05:03 AM

i wrote a script like this on hp ux:

MYSTATUS="$(UNIX95= ps -C $PROC -o pid= -o comm=)"
if [ -z "$MYSTATUS" ]
then
<do something>
fi

Although i doubt this would work on linux quite the same. anyway, this code avoids the whole grep issue. which is something to be mindful of on production/important servers/computers.

grep can give results that you dont expect. e,g someone could run another check related programme at the same time, which could throw a spanner in the works.

ta0kira 02-23-2006 06:51 PM

Quote:

Originally Posted by alienDog
You didn't pay attention to how the locking actually works.

I do suppose you are right. For some reason I was thinking the call was intended to kill the script that was already running.
Quote:

Originally Posted by alienDog
I think you must be confusing kill -0 with kill 0?

Yes, also correct.
Quote:

Originally Posted by alienDog
You think wrong ;) The kill command is quite different from SIGKILL signal that kills programs.

I think I was unclear. I noted that it sends the TERM signal to the process, which is normally handled by a POSIX binary, however a script does not have the functionality to process these signals, therefore if it was in a loop or the sort it would be killed before it could exit the loop and clean up after itself.
Quote:

Originally Posted by alienDog
I honestly don't see how this could happen???

Yes, you caught me again; I was trying to reply fairly fast and was thinking in the context of the script I cited earlier. What happens with that is one script gives another script the OK to write to a fifo, but if that script is killed mid-wait then the other script hangs because it thought it was OK to write to the fifo, but that changed after the OK went through.
ta0kira


All times are GMT -5. The time now is 04:04 PM.