2012-03-01 35 views
1

我想确保一次只能运行一个perl脚本的一个实例。该脚本根据传入的参数执行某种类型的db_operation。该脚本不一定位于一个地方或一台机器上,也可能位于多个OS中。虽然文件系统在各种机器上自动安装。Muetexes in perl&MySQL

我的第一个形式给出是只创建一个.lock文件,并执行以下操作:

use warnings; 
use strict; 
use Fcntl qw(:DEFAULT :flock); 
... 
open(FILE,">>",$lockFilePath); 
flock(FILE,LOCK_EX) or die("Could not lock "); 
do_something(); 
flock(FILE,LOCK_UN) or die("Could not unlock "); 
close(FILE); 

,但我不断收到以下错误:

Bareword "LOCK_EX" not allowed while "strict subs" in use 
Bareword "LOCK_UN" not allowed while "strict subs" in use 

所以我要寻找另一种方式来解决这个问题。锁定数据库本身也是不现实的,因为数据库可以被其他脚本使用(这是可以接受的),我只是试图阻止这个脚本运行。并且锁定一个表格是不实际的,因为我的脚本不知道该操作发生在哪个表上,它只是启动另一个作为参数提供的perl脚本。

我正在考虑向db中添加一个表,只有一个值,并将其用作muetex,但我不知道这是多么的实用/可靠(我的很多红旗都在头)。我有一个到这个脚本使用的db的DBI连接。

谢谢

+0

听起来像你的子脚本需要做自己的锁定,因为你的跑步者脚本不知道是否安全地运行多个副本。 – 2012-03-01 15:13:47

+0

很奇怪,你会得到那个错误。确保'使用Fcntl qw(:flock);'对你使用它的块有效。尝试直接在'flock'调用之上添加它。你也可以尝试使用这些常量的值,参见[flock](http://perldoc.perl.org/functions/flock.html)。 – Qtax 2012-03-01 15:31:11

回答

5

您听到的Bareword错误听起来像是您在“...”中做了一些事情来混淆Perl关于导入的Fcntl常量。使用那些常量是没有问题的。你可以尝试像LOCK_UN()这样的东西来看看你会得到什么样的错误。

如果您使用MySQL,您可以使用GET_LOCK()RELEASE_LOCK()机制。它的工作原理相当不错了这样的情况:

SELECT GET_LOCK("script_lock"); 

,然后当你完成:

SELECT RELEASE_LOCK("script_lock"); 

详见http://dev.mysql.com/doc/refman/4.1/en/miscellaneous-functions.html

+0

谢谢,这似乎是工作 – Smartelf 2012-03-01 16:03:17

+0

或'&LOCK_EX','&LOCK_UN'等。 – mob 2012-03-01 16:05:23

1

您可能想要避免文件锁定;从我记得在非本地文件系统中出现的臭名昭着的不可靠。最好的办法是仅仅使用文件本身的存在来指示脚本已经在运行(类似于UNIX的PID文件)。当然,这不是100%可靠的,但是应该在非常低的开销下合理可靠地工作,前提是脚本不会被不断调用。

如果您需要更好的可靠性,使用互斥数据库是一个很好的解决方案。