Preventing script collisions: allow only one instance per %1

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Michael_Stora
Posts: 5
Joined: 16 Apr 2015 13:20

Preventing script collisions: allow only one instance per %1

#1 Post by Michael_Stora » 16 Apr 2015 13:32

Edit: I found a neat implementation, see below.

Does anyone know how to have a .bat scipt check if another version of itself (%0) is running with the same %1 I have several database deamons running and I've had mysterious data corruption issues which I was able to trace to an extra instance running. Each database has it's own workspace and remote share drive locations set in a bat file (which the main script CALLs based on the value of %1).

The database itself is written in *nix (mostly BASH and AWK, some PERL where the faster AWK lacks a capability like MD5Sums) running under Cygwin and the Batch daemons are just the glue to implement things in a Windows environment.

I'd like the script to be able to check if another version of itself is running (the answer will usually be yes) and then terminate itself if another version is running with the same %1.

I am an experianced BASH and AWK scripter and know enough PERL to be dangerous but this experiance makes my Batch scripting more unpredictable than if I did not have it, I'm afraid.

Thanks, Mike
Last edited by Michael_Stora on 17 Apr 2015 23:55, edited 1 time in total.

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Preventing script collisions: allow only one instance pe

#2 Post by jeb » 17 Apr 2015 00:54

Hi Michael_Stora,

you can use lock files.
Each of your instances creates a lock file, but this is only possible when the lock file isn't created and locked by a different process.

Code: Select all

@echo off

set "lockFileName=%~1_lock.tmp"
2>nul (
    4> "%lockFileName%" (
        echo starting instance
      ping -n 2 localhost > nul
    ) || echo Failed %1
)
echo End %1



If the lock file is already there, but no process uses it anymore, then a new process can still be started.

Michael_Stora
Posts: 5
Joined: 16 Apr 2015 13:20

Re: Preventing script collisions: allow only one instance pe

#3 Post by Michael_Stora » 17 Apr 2015 14:30

Thanks for the reply. It looks like the process list does not show %1 and shows my scripts not my their bat name but by cmd.exe :( (even though I see the bat name in the GUI version).

I was trying to avoid lock files because my IT department will do a patch requiring a reboot a couple times a month and lock files won't restart cleanly. I'd like a solution where the lock files vanish on restart.

Can I do a lock environmental variable? Is it possible to export a variable upward? Set seems to only work at the same of deeper process level.

Can you set up a tiny ramdrive in a bat file and use that for lock files?

Mike

Michael_Stora
Posts: 5
Joined: 16 Apr 2015 13:20

A cool implementation of a volatile lock

#4 Post by Michael_Stora » 18 Apr 2015 00:06

Setx does not allow setting in the volatile environment under HKCU, so I am doing it manually:

Code: Select all

@echo off
C:
chdir C:\where\I\am\going

IF "%1"=="" ( Set "myvar=default" ) ELSE ( Set "myvar=%1" )
REM Create a key in the volatile area of the current user registry as a lock.
REG query "HKCU\Volatile Environment" /v %myvar%"_Lock" >NUL 2>NUL & if errorlevel 1 (
    REG add "HKCU\Volatile Environment" /v %myvar%"_Lock" >NUL 2>NUL
    REM Create the key as a lock.
    goto :START )
REM if the key does not exist (error) we are good.

echo ####### WARNING ####### WARNING ####### WARNING ####### WARNING ####### WARNING #######
echo It appears the %myvar% daemon is already running.
echo If you are sure it is not would you like to force it to run?
choice /t 300 /D:N /M "Default No (5 min timeout)"
echo #######################################################################################
echo.
If errorlevel 2 goto :END

:START


I have a gentle quit that deletes the key:

Code: Select all

REG delete "HKCU\Volatile Environment" /v %myvar%"_Lock" /f >NUL 2>NUL & goto :END


That was fun. If I log out or the machine restarts, the locks disappear.

Mike

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Preventing script collisions: allow only one instance pe

#5 Post by Ed Dyreen » 18 Apr 2015 05:32

With jeb's singleTon all you have to do is end the process that locks the file and optionally delete it. A registry key is also stored inside a file so you didn't succeed in avoiding a file. Your solution is much slower. Your lock fails if the lock is not deleted, that's not good! U may want to use autoIT to implement a mutex that doesn't creates a file on disk:

Code: Select all

$handle = DllCall( 'kernel32.dll', 'handle', 'CreateMutexW', 'struct*', $tSecurityAttributes, 'bool', 1, 'wstr', $sOccurenceName )

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: Preventing script collisions: allow only one instance pe

#6 Post by Squashman » 18 Apr 2015 19:46

Does this thread help at all?
viewtopic.php?f=3&t=6133

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Preventing script collisions: allow only one instance pe

#7 Post by dbenham » 19 Apr 2015 11:29

@Squashman - I don't see how that post helps directly, since it is OK if multiple instances are running as long as argument %1 is different for each one.

@Michael_Stora - To further the point Ed was making, the lock files don't have to vanish upon restart - they just cannot be locked. The exclusive lock will indeed be dropped once the batch process that holds it is terminated, regardless how the process is killed - normal exit, Ctrl-C, fatal error, reboot - it doesn't matter. Your script can delete the lock file upon normal termination, but failure to delete will not prevent a subsequent server script from running. I thought jeb did a pretty good job of explaining this important fact when he stated "If the lock file is already there, but no process uses it anymore, then a new process can still be started."


Dave Benham

Michael_Stora
Posts: 5
Joined: 16 Apr 2015 13:20

Re: Preventing script collisions: allow only one instance pe

#8 Post by Michael_Stora » 19 Apr 2015 14:49

Thanks for your patience with me. I was thinking about testing the existence of the lock file and not fact that it is locked. I did not initially understand how Jed's script and how the lock disappears when the process locking it ends.

Thanks guys.

Mike

Michael_Stora
Posts: 5
Joined: 16 Apr 2015 13:20

Re: Preventing script collisions: allow only one instance pe

#9 Post by Michael_Stora » 20 Apr 2015 14:26

My final implementation is just to add the lockfile to the shortcuts that launch the daemons from the desktop (of startup folder). I implemented a log and lockfile external to the program:

Shortcut target: C:\my_path\Databases\Code\database_daemon.bat name 2>&1 | wtee "..\logs\name_%date:/=-%%time::=;%.txt" 4>../lockfiles/name_lock.tmp

Mike

mirrormirror
Posts: 129
Joined: 08 Feb 2016 20:25

Re: Preventing script collisions: allow only one instance per %1

#10 Post by mirrormirror » 11 Mar 2016 18:20

I have a quick question on jeb's code:

Code: Select all

@echo off

set "lockFileName=%~1_lock.tmp"
2>nul (
    4> "%lockFileName%" (
        echo starting instance
      ping -n 2 localhost > nul
    ) || echo Failed %1
)
echo End %1

What does the "4> "%lockFileName%" (" line do? Or more specifically, what does the "4>" do? I know the "2>" redirects stderr, but "4>"??
Shortcut target: C:\my_path\Databases\Code\database_daemon.bat name 2>&1 | wtee "..\logs\name_%date:/=-%%time::=;%.txt" 4>../lockfiles/name_lock.tmp

I could also use a bit of explanation on this solution (above). I know it is "teeing" the output (with wtee.exe) but not sure exactly what is going on. This is what it looks like to me:
"..\logs\name_%date:/=-%%time::=;%.txt" - the filename where output is redirected to (via wtee.exe)

4>../lockfiles/name_lock.tmp - what is going on here?
We have the "4>" again... What is being reditected into "name_lock.tmp"?
Is it the output from "C:\my_path\Databases\Code\database_daemon.bat " or "..\logs\name_%date:/=-%%time::=;%.txt"?

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Preventing script collisions: allow only one instance per %1

#11 Post by sambul35 » 12 Mar 2016 06:46

As you noted, it appears to signify standard output redirection. Some programs mentioned here may help to further check that output.

And I agree, default color for LINKS on this forum better be changed to a more distinctive one from plain text color. Several times already folks didn't notice links I posted, and then asked expected question "what the heck its about?". :P I don't believe the golden rule is to post all links in plain text, unless someone explains why such redundancy should be a rule?

mirrormirror
Posts: 129
Joined: 08 Feb 2016 20:25

Re: Preventing script collisions: allow only one instance per %1

#12 Post by mirrormirror » 12 Mar 2016 19:29

As you noted, it appears to signify standard output redirection. Some programs mentioned here may help to further check that output.

Thanks for the link- interesting reading. So I guess numbers "4-9" could be used?
And are the contents of this file: "..\logs\name_%date:/=-%%time::=;%.txt" being sent to this file: "name_lock.tmp"?

Post Reply