ohh*_*hho 10 php linux cron centos
目前,我试图阻止onlytask.php脚本多次运行:
$fp = fopen("/tmp/"."onlyme.lock", "a+");
if (flock($fp, LOCK_EX | LOCK_NB)) {
echo "task started\n";
//
while (true) {
// do something lengthy
sleep(10);
}
//
flock($fp, LOCK_UN);
} else {
echo "task already running\n";
}
fclose($fp);
Run Code Online (Sandbox Code Playgroud)
每分钟都有一个cron作业来执行上面的脚本:
* * * * * php /usr/local/src/onlytask.php
Run Code Online (Sandbox Code Playgroud)
它有效一段时间了.几天后,当我这样做时:
ps auxwww | grep onlytask
Run Code Online (Sandbox Code Playgroud)
我发现有两个实例正在运行!不是三个或更多,而不是一个.我杀死了其中一个实例.几天后,又有两个例子.
代码有什么问题?还有其他选择只限制onlytask.php运行的一个实例吗?
ps我的/tmp/文件夹没有清理干净.ls -al /tmp/*.lock显示锁定文件是在第一天创建的:
-rw-r--r-- 1 root root 0 Dec 4 04:03 onlyme.lock
Run Code Online (Sandbox Code Playgroud)
gal*_*han 11
x打开锁定文件时应该使用标志:
<?php
$lock = '/tmp/myscript.lock';
$f = fopen($lock, 'x');
if ($f === false) {
die("\nCan't acquire lock\n");
} else {
// Do processing
while (true) {
echo "Working\n";
sleep(2);
}
fclose($f);
unlink($lock);
}
Run Code Online (Sandbox Code Playgroud)
请注意PHP手册
' x ' - 创建并仅供写作; 将文件指针放在文件的开头.如果文件已存在,则fopen()调用将失败,返回FALSE并生成级别为E_WARNING的错误.如果该文件不存在,请尝试创建它.这相当于为底层的open(2)系统调用指定O_EXCL | O_CREAT标志.
以下是手册页的O_EXCL解释:
O_EXCL - 如果设置了O_CREAT和O_EXCL,则如果文件存在,open()将失败.检查文件是否存在以及文件的创建(如果不存在)对于执行open()的其他线程来说应该是原子的,在设置了O_EXCL和O_CREAT的同一目录中命名相同的文件名.如果设置了O_EXCL和O_CREAT,并且路径名称为符号链接,则open()将失败并将errno设置为[EEXIST],而不管符号链接的内容如何.如果设置了O_EXCL且未设置O_CREAT,则结果未定义.
更新:
更可靠的方法 - 运行主脚本,获取锁,运行工作脚本并释放锁.
<?php
// File: main.php
$lock = '/tmp/myscript.lock';
$f = fopen($lock, 'x');
if ($f === false) {
die("\nCan't acquire lock\n");
} else {
// Spawn worker which does processing (redirect stderr to stdout)
$worker = './worker 2>&1';
$output = array();
$retval = 0;
exec($worker, $output, $retval);
echo "Worker exited with code: $retval\n";
echo "Output:\n";
echo implode("\n", $output) . "\n";
// Cleanup the lock
fclose($f);
unlink($lock);
}
Run Code Online (Sandbox Code Playgroud)
这是工人.让我们在其中引发一个假的致命错误:
#!/usr/bin/env php
<?php
// File: worker (must be executable +x)
for ($i = 0; $i < 3; $i++) {
echo "Processing $i\n";
if ($i == 2) {
// Fake fatal error
trigger_error("Oh, fatal error!", E_USER_ERROR);
}
sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
galymzhan@atom:~$ php main.php
Worker exited with code: 255
Output:
Processing 0
Processing 1
Processing 2
PHP Fatal error: Oh, fatal error! in /home/galymzhan/worker on line 8
PHP Stack trace:
PHP 1. {main}() /home/galymzhan/worker:0
PHP 2. trigger_error() /home/galymzhan/worker:8
Run Code Online (Sandbox Code Playgroud)
重点是锁定文件已正确清理,因此您可以main.php再次运行而不会出现问题.
现在我检查进程是否正在运行ps并通过bash脚本扭曲php 脚本:
#!/bin/bash
PIDS=`ps aux | grep onlytask.php | grep -v grep`
if [ -z "$PIDS" ]; then
echo "Starting onlytask.php ..."
php /usr/local/src/onlytask.php >> /var/log/onlytask.log &
else
echo "onlytask.php already running."
fi
Run Code Online (Sandbox Code Playgroud)
并按分钟运行bash脚本cron.