如何防止脚本的多个实例? [英] How to prevent multiples instances of a script?

查看:144
本文介绍了如何防止脚本的多个实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有必须在linux以及Windows服务器上运行的php脚本. 我想在不对这2种环境进行任何修改的情况下使用相同的脚本.

I have php scripts that I have to run on linux as well as on Windows servers. I want to use the same scripts without doing any modifications for those 2 environments.

这些脚本将在Windows环境中使用cron(在Linux上)和Windows Scheduler(或其他,我现在不在意)中进行调度.

Theses scripts will be scheduled with cron (on linux) and with the windows scheduler (or other, I don't care for now) for my Windows environment.

但是,其中一些脚本可能需要几分钟才能完成.我只是想防止调度程序在上次启动之前完成调度程序(cron或Windows的脚本)启动该脚本.

However, some of theses scripts might take several minutes to complete. I just want to prevent the same script from being launched by the scheduler (cron or the windows's one) before it has finished the last time it was launched.

我不确定该怎么做. 我要确保在执行过程中出现问题时释放锁",以便下次在没有人为干预的情况下再次启动它.

I'm not sure how to do that.. I want to be sure that the "lock" is released if something goes wrong during the execution, so it is launched again the next time without human intervention.

也许在虚拟文件上有一群羊就能解决这个问题,但是我不确定如何做到这一点.

Maybe with a flock on a dummy file would do the trick, but i'm not sure how to do that.

我在这些服务器上也有一个MySQL数据库.我以为可能在数据库端使用了锁.

I also have a MySQL database on theses servers. I thought maybe using a lock on the database side.

1- Start a transaction
2- Insert script name in a table.
3- execution of the script.
4- If successful then delete the row and commit the transaction or simply rollback;

如果脚本名称在表中,则可以阻止其运行. 如果脚本执行失败,则Mysql将自动回滚事务,以使该行在下次调用脚本时不会出现.

If the script name is in the table, I then could prevent it from running. If the script execution fails, then Mysql will automatically rollback the transaction so the row does not appear the next time the script is called.

但是,在事务中,其他连接是否可以查看未提交的数据?如果是,怎么办?

But, in a transaction, is there a way for other connections see the uncommited data? if yes, how?

我还认为,如果不可能使用回滚功能,则在行上使用锁.

I also thought using a lock on the row if it is impossible to use the rollback thing..

1- Insert script name in a table if it doesn't already exists.
2- Start a transaction.
2- Select * from Table where script_name FOR UPDATE.
3- execution of the script.
4- If successful then release the lock (rollback or commit).

但是我这里的主要问题是Mysql.选择FOR UPDATE挂起,直到释放上一个锁或如果50秒超时(innodb_lock_wait_timeout变量)过去.我希望Mysql当场告诉我我的行被锁定而不会影响整个数据库.这是因为innodb_lock_wait_timeout变量是全局变量(而不是会话变量1). 是否有另一个变量可以模仿Oracle中可用的NO_WAIT子句?

But my major problem here is with Mysql. Select FOR UPDATE hang until the previous lock is released or if the 50 seconds timeout(innodb_lock_wait_timeout variable) is elapsed. I would like Mysql to tell me right on the spot that my row is locked without affecting the whole Database. That is because the innodb_lock_wait_timeout variable is a global one (not a session one). Is there another variable that mimic the NO_WAIT clause that is available in Oracle?

还是应该让脚本挂起50秒而没有任何问题?

Or should I let the script hang 50 seconds without any problem?

在这方面最好的方法是什么,因为我是php新手,并且我不想在服务器上引起任何问题.

What is the best approach on that as I am a php newbie and I don't want to cause any problems on the server.

也许我还有另一个我没有看到的选择.

Maybe I have another option that I didn't see..

推荐答案

我使用...套接字解决了此问题.您可以启用php_sockets扩展,然后尝试.这是代码示例:

I solved this problem using... sockets. It you can enable php_sockets extention then try it. Here is code sample:

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (false === $socket) {
    throw new Exception("can't create socket: ".socket_last_error($socket));
}
## set $port to something like 10000
## hide warning, because error will be checked manually
if (false === @socket_bind($socket, '127.0.0.1', $port)) {
    ## some instanse of the script is running
    return false;
} else {
    ## let's do your job
    return $socket;
}

在特定$port上的绑定套接字是安全的操作,可以并行执行.操作系统将确保没有其他进程将套接字绑定到同一端口.您只需要检查返回值即可.

Bind socket on specific $port is safe operation for concurent execution. Operation system will make sure that there is no other process which bound socket to same port. You just need to check return value.

如果脚本崩溃,则操作系统将自动解除端口绑定.

If script crashes then operation system will unbind the port automatically.

这也可以使用任何语言.我已经在基于perl和php的项目上对其进行了广泛的测试.即使我们在crontab中错误地添加了两次脚本,它也停止了并行执行.

This also can be used in any language. I've tested it wide on perl and php based projects. It stoped parallel execution even when we've added script twice in crontab by mistake.

这篇关于如何防止脚本的多个实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆