1

I'm currently creating a lock folder which is created when my script runs, I also move files into sub folders here for processing. When the script ends a TRAP is called which removes the lock folder and contents, all of which is working fine. We had an issue the other day when someone pulled the power from one of the servers so my TRAP was never called so when re-booted the lock folder was still there which meant my scripts couldn't re-start until they were manually removed. What's the best way of checking if the script is already running ? I currently have this approach using process id's:

if ! mkdir $LOCK_DIR 2>/dev/null; then # Try to create the lock dir. This should pass successfully first run. # If the lock dir exists pid=$(cat $LOCK_DIR/pid.txt) if [[ $(ps -ef | awk '{print $2}' | grep $pid | grep -v grep | wc -l) == 1 ]]; then echo "Script is already running" exit 1 else echo "It looks like the previous script was killed. Restarting process." # Do some cleanup here before removing dir and re-starting process. fi fi # Create a file in the lock dir containing the pid. Echo the current process id into the file. touch $LOCK_DIR/pid.txt echo $$ > $LOCK_DIR/pid.txt # Rest of script below 
4
  • Check man 1 lockfile lockfile-check lockfile-create lockfile-remove lockfile-touch Commented Jul 13, 2015 at 10:09
  • 2
    Use the flock command. man flock contains examples Commented Jul 13, 2015 at 10:20
  • From what I understand using mkdir is also an atomic operation and seeing as I need that directory each run it might as well be used as the main lock "file". I'm not sure how I'd tie flock into the current implementation? Commented Jul 13, 2015 at 11:59
  • Using flock You can determine if there is a currently running version of your script, assuming it is the only one locking the file. flock locks also automagically go away when your code closes the lockfile, so no extra cleanup is needed. Commented Jul 13, 2015 at 12:37

2 Answers 2

1

Checking /proc/ and cmdline is a good call - especially as at the moment you are simply checking that there isn't a process with the process id and not if the process is actually your script.

You could still do this with your ps command - which would offer some form of platform agnosticism.

COMMAND=$(ps -o comm= -p $pid) if [[ $COMMAND == my_process ]] then ..... 

Note the command line arguments to ps limit it to command only with no header.

Sign up to request clarification or add additional context in comments.

4 Comments

Looks good! Fits in with my current implementation and seems to solve my issue. Although the process name returned is in the format of "proc_name." why is it missing the file extension of sh but including the dot?
I might have just answered that. It looks as though ps has a limit on the length of process name?
You can specify the width of the column. According to the man page ps -o comm:100= -p $pid should do it. But it doesn't. ps -o command= -p $pid Will give you the full command including arguments.
I think the limit on comm's length is because it's an alias for %c which is AIX's ps format descriptors.
0

Many systems nowadays use tmpfs for directories like /tmp. These directories will therefore always be cleared after a reboot.

If using your pid file, note you can easily see the command running under that pid in /proc/$pid/cmdline and /proc/$pid/exe.

3 Comments

Unfortunately given our server structure I wouldn't want to do the processing in the tmp folder. So in that case I could replace the ps with the below, although I don't think there's much to be gained there? : ls /proc | grep $pid | wc -l
You dont have to put everything in /tmp, just a lock file. You dont need to ls /proc. There is a directory per process. So cat /proc/$pid/cmdline shows you what command pid $pid is running.
Note that locks under Linux are expected to go under /run/lock/... now a day, which is always deleted between reboots.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.