可靠的PHP脚本可重入锁

可靠的PHP脚本可重入锁,php,locking,webserver,Php,Locking,Webserver,我必须确保某个PHP脚本(由web请求启动)不会同时运行多次 对于二进制文件,很容易检查某个二进制文件的进程是否已经存在 然而,一个PHP脚本可以通过几种途径运行,例如CGI、FCGI、webserver模块内部等。因此,我无法使用系统命令来查找它 那么,如何可靠地检查某个脚本的另一个实例当前是否正在运行?使用与本地应用程序完全相同的策略: 该进程管理一个“锁定文件” 您可以在文件系统中定义一个静态位置。在脚本启动时,检查该位置是否存在锁文件,如果存在,则退出。如果没有,请先创建锁文件,然后继续

我必须确保某个PHP脚本(由web请求启动)不会同时运行多次

对于二进制文件,很容易检查某个二进制文件的进程是否已经存在

然而,一个PHP脚本可以通过几种途径运行,例如CGI、FCGI、webserver模块内部等。因此,我无法使用系统命令来查找它


那么,如何可靠地检查某个脚本的另一个实例当前是否正在运行?

使用与本地应用程序完全相同的策略:

该进程管理一个“锁定文件”

您可以在文件系统中定义一个静态位置。在脚本启动时,检查该位置是否存在锁文件,如果存在,则退出。如果没有,请先创建锁文件,然后继续。在拆除脚本的过程中,您将再次删除该锁定文件。这样的锁文件是一个简单的被动文件,只有它的存在是有意义的,通常不是它的内容。这是一个标准程序

如果您不仅将锁文件用作被动信号量,而且将生成进程的进程id存储在其中,则可以赢得额外的糖果点数。这允许后续尝试验证该进程是否仍然存在或同时崩溃。这是有道理的,因为这样的崩溃会留下一个过时的锁文件,从而创建一个死锁


为了解决评论中讨论的问题,该问题正确地指出,在某些情况下,php脚本在wen环境中使用,流程ID本身可能不足以可靠地测试给定任务是否已成功完成,可以使用稍微修改的设置:


传入的请求不会直接触发执行php脚本本身的任务,而只是一个包装器脚本。该包装器管理锁文件,同时将要执行的实际任务委托给http服务器的子请求。这允许控制包装器脚本使用请求状态的附加信息。如果执行php脚本的实际任务在没有事先通知的情况下真的崩溃了,那么请求包装器就会知道:每个请求都会被一个特定的http状态代码终止,该代码允许决定执行请求的任务是否正常终止。在大多数情况下,该设置应该足够可靠。琐碎的包装器脚本崩溃或终止的可能性属于系统故障,这是任何锁定策略都无法可靠处理的

使用与本地应用程序完全相同的策略:

该进程管理一个“锁定文件”

您可以在文件系统中定义一个静态位置。在脚本启动时,检查该位置是否存在锁文件,如果存在,则退出。如果没有,请先创建锁文件,然后继续。在拆除脚本的过程中,您将再次删除该锁定文件。这样的锁文件是一个简单的被动文件,只有它的存在是有意义的,通常不是它的内容。这是一个标准程序

如果您不仅将锁文件用作被动信号量,而且将生成进程的进程id存储在其中,则可以赢得额外的糖果点数。这允许后续尝试验证该进程是否仍然存在或同时崩溃。这是有道理的,因为这样的崩溃会留下一个过时的锁文件,从而创建一个死锁


为了解决评论中讨论的问题,该问题正确地指出,在某些情况下,php脚本在wen环境中使用,流程ID本身可能不足以可靠地测试给定任务是否已成功完成,可以使用稍微修改的设置:


传入的请求不会直接触发执行php脚本本身的任务,而只是一个包装器脚本。该包装器管理锁文件,同时将要执行的实际任务委托给http服务器的子请求。这允许控制包装器脚本使用请求状态的附加信息。如果执行php脚本的实际任务在没有事先通知的情况下真的崩溃了,那么请求包装器就会知道:每个请求都会被一个特定的http状态代码终止,该代码允许决定执行请求的任务是否正常终止。在大多数情况下,该设置应该足够可靠。琐碎的包装器脚本崩溃或终止的可能性属于系统故障,这是任何锁定策略都无法可靠处理的

由于PHP并不总是提供可靠的文件锁定方式(这取决于脚本的运行方式,例如CGI、FCGI、服务器模块和配置),因此应该使用其他一些锁定环境

例如,PHP脚本可以在其CLI变量中调用另一个PHP解释器。这将提供一个可以检查锁定的唯一PID。PID应该存储到某个锁文件中,然后可以通过查询使用PID的进程是否仍然存在来检查该文件是否存在过时的锁

也许还可以在shell脚本中执行所有需要锁的任务。Shell脚本还提供了一个独特的PID,并在退出后将其释放。shell脚本还可以使用唯一的文件名来检查它是否仍在运行

还可以使用信号量(),它由PHP解释器明确管理,以反映脚本的生命周期。它们似乎工作得很好,但在脚本过早死亡的情况下,它们的可靠性并没有多少模糊性

还要记住,由PHP脚本启动的外部进程可能会继续执行,即使脚本结束。例如,FCGI上的用户中止会释放
passthru
进程,尽管客户端连接关闭,这些进程仍会继续工作。如果积累了足够的产量或根本没有产量,它们可能会被杀死。 所以这样的外部过程