PHP脚本浏览器运行正常但Cron任务中数据库恢复失败求助
问题
搭建供用户测试的演示网站,需要每隔X小时恢复一次数据库。在浏览器中运行PHP脚本时,能正常删除数据表并完成数据库恢复;但把脚本加入Cron任务后,仅能删除数据表,无法完成恢复。
原PHP脚本:
<?php $mysqli = new mysqli("localhost", "", "", ""); $mysqli->query('SET foreign_key_checks = 0'); if ($result = $mysqli->query("SHOW TABLES")) { while($row = $result->fetch_array(MYSQLI_NUM)) { $mysqli->query('DROP TABLE IF EXISTS '.$row[0]); } } $mysqli->query('SET foreign_key_checks = 1'); echo "Deleted databse"; sleep(5); $sqlScript = file('demo.sql'); foreach ($sqlScript as $line) { $startWith = substr(trim($line), 0 ,2); $endWith = substr(trim($line), -1 ,1); if (empty($line) || $startWith == '--' || $startWith == '/*' || $startWith == '//') { continue; } $query = $query . $line; if ($endWith == ';') { mysqli_query($mysqli,$query) or die('<div class="error-response sql-import-response">Problem in executing the SQL query <b>' . $query. '</b></div>'); $query= ''; } } $mysqli->close(); echo '<div class="success-response sql-import-response">SQL file imported successfully</div>'; ?>
Cron任务:
*/10 * * * * /usr/local/bin/php /home/demo/public_html/db.php
排查方向及解决方法
- 文件路径错误:Cron执行时的工作目录不是脚本所在目录,
file('demo.sql')找不到文件。解决:把SQL文件路径改成绝对路径,比如file('/home/demo/public_html/demo.sql')。 - 权限不足:Cron运行的系统用户(比如
www-data或主机用户)没有读取demo.sql的权限。解决:给文件设置可读权限,执行chmod 644 /home/demo/public_html/demo.sql,确保Cron用户能访问。 - 数据库连接参数缺失:浏览器运行时依赖Web服务器环境变量,CLI模式下空用户名/密码可能无法连接。解决:在
mysqli构造函数里填写正确的数据库用户名、密码和库名,比如new mysqli("localhost", "demo_user", "your_pass", "demo_db")。 - 错误信息无法查看:Cron执行的错误不会在浏览器显示,脚本里的
die()输出看不到。解决:修改Cron任务把输出重定向到日志文件,方便排查:
或者在脚本里用*/10 * * * * /usr/local/bin/php /home/demo/public_html/db.php >> /home/demo/public_html/cron_log.txt 2>&1error_log()记录错误,替代echo和die()。 - PHP CLI配置差异:CLI模式下的PHP可能有不同的
php.ini配置(比如内存限制更低),导致大SQL脚本执行失败。解决:检查CLI的php.ini(执行/usr/local/bin/php -i | grep php.ini找路径),调整memory_limit参数,或者拆分大SQL脚本。
修改后的示例脚本
<?php // 填写正确的数据库连接信息 $mysqli = new mysqli("localhost", "demo_user", "your_db_password", "demo_database"); // 检查连接错误 if ($mysqli->connect_error) { error_log("数据库连接失败: " . $mysqli->connect_error); exit; } $mysqli->query('SET foreign_key_checks = 0'); if ($result = $mysqli->query("SHOW TABLES")) { while($row = $result->fetch_array(MYSQLI_NUM)) { $mysqli->query('DROP TABLE IF EXISTS '.$row[0]); } } $mysqli->query('SET foreign_key_checks = 1'); error_log("已删除所有数据表"); sleep(5); // 使用绝对路径读取SQL文件 $sqlFilePath = '/home/demo/public_html/demo.sql'; if (!file_exists($sqlFilePath)) { error_log("SQL文件不存在: " . $sqlFilePath); exit; } $sqlScript = file($sqlFilePath); $query = ''; // 初始化变量避免未定义警告 foreach ($sqlScript as $line) { $trimmedLine = trim($line); $startWith = substr($trimmedLine, 0, 2); $endWith = substr($trimmedLine, -1, 1); // 跳过注释和空行 if (empty($trimmedLine) || $startWith == '--' || $startWith == '/*' || $startWith == '//') { continue; } $query .= $line; // 执行完整的SQL语句 if ($endWith == ';') { if (!$mysqli->query($query)) { error_log("SQL执行失败: " . $query . " | 错误信息: " . $mysqli->error); } $query = ''; } } $mysqli->close(); error_log("数据库恢复完成"); ?>
内容的提问来源于stack exchange,提问作者Mangesh Yadav
相关产品推荐
相关产品推荐

