如何避免cron定时运行的PHP脚本因未执行完而重复启动?
防止Cron重复运行PHP脚本的几种实用方法
方法一:使用文件锁(最可靠)
利用PHP的flock()函数创建排他锁,脚本启动时尝试获取锁,获取失败则直接退出,避免重复执行。这种方法能自动处理脚本意外崩溃的情况(锁会随进程结束自动释放)。
在script.php开头添加以下代码:
// 定义锁文件路径,建议放在tmp目录或者脚本所在目录 $lockFile = '/tmp/script_run.lock'; // 打开锁文件,模式为读写+创建 $lockHandle = fopen($lockFile, 'w'); if (!$lockHandle) { exit("无法创建锁文件\n"); } // 尝试获取排他锁,LOCK_NB表示非阻塞获取,避免等待 if (!flock($lockHandle, LOCK_EX | LOCK_NB)) { exit("脚本已在运行中\n"); } // 脚本核心逻辑写在这里... // 脚本结束时可手动释放锁(可选,进程结束后系统会自动释放) flock($lockHandle, LOCK_UN); fclose($lockHandle);
方法二:检查系统进程
通过系统命令检查是否已有script.php的进程在运行,判断后决定是否继续执行。注意要过滤掉当前执行的检查命令本身,避免误判。
示例代码:
// 构造检查命令,用[ s ]cript.php的正则技巧过滤grep自身进程 $command = "ps aux | grep '[s]cript.php' | wc -l"; $runningCount = (int)shell_exec($command); // 如果运行中的进程数大于1,说明已有实例在运行 if ($runningCount > 1) { exit("脚本已在运行中\n"); } // 脚本核心逻辑...
方法三:改用Systemd Timers(Linux系统)
如果你的服务器使用systemd,可以抛弃cron,改用systemd定时器管控脚本执行,天生支持"前一个实例结束才启动下一个"的逻辑。
- 创建服务文件
script.service:
[Unit] Description=Run script.php periodically [Service] Type=oneshot ExecStart=/usr/bin/php /path/to/script.php RemainAfterExit=no
- 创建定时器文件
script.timer:
[Unit] Description=Timer for script.php [Timer] # 每5分钟执行一次,以上一次执行结束时间为起点计算 OnUnitActiveSec=5min # 开机后立即执行一次(可选) OnBootSec=0min [Install] WantedBy=timers.target
- 启用并启动定时器:
sudo systemctl daemon-reload sudo systemctl enable --now script.timer
这种方式无需修改脚本本身,由systemd负责实例唯一性管控。
内容的提问来源于stack exchange,提问作者Geckon01
相关产品推荐
相关产品推荐

