使用Shell脚本作为PHP定时任务的守护进程
在进行大批量数据处理(如数千万用户信息的异步检测)时,PHP脚本常因执行时间过长、内存耗尽或第三方接口波动而意外终止。为了保障此类定时任务的连续性和可靠性,可以利用轻量级的Shell脚本配合系统Crontab,构建一个简易的守护进程(Daemon),自动监控并重启挂掉的PHP进程。
结果与目标
建立一个可靠的后台批处理机制。该机制能够以10000条数据为一个批次进行循环处理,当PHP脚本达到批次上限或意外异常退出的时候,由Shell脚本接管并重新启动,避免人工干预,直至所有数据全部处理完毕。
准备条件与环境配置
- 数据库表结构:建立一张临时用户名单表,包含账号、手机号状态、邮箱状态及标志位字段。 ``` CREATE TABLE `users` ( `account` varchar(50) COMMENT '用户名', `has_phone` tinyint(3) unsigned NOT NULL default '0' COMMENT '是否有手机号', `has_email` tinyint(3) unsigned NOT NULL default '0' COMMENT '是否有邮箱', `flag` tinyint(3) unsigned NOT NULL default '0' COMMENT '标志位: 0未处理 1已处理', PRIMARY KEY (`account`), KEY `flag` (`flag`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='名单表'; ```
- 系统环境:Linux服务器,支持运行 PHP CLI 模式和 Bash Shell 脚本。
真实操作顺序
第一步:编写分批次处理的 PHP 脚本
首先创建一个 `check_users.php` 文件。由于外部安全接口响应较慢,且需要防止长连接导致的数据库超时,脚本设计为每次提取500个未处理的用户进行批量校验,每完成一批次写入一次数据库。更重要的是,为了防止单线程脚本长时间运行导致崩溃,设定每处理完1万个用户后,脚本主动执行 `exit(0)` 退出程序。
核心逻辑示意如下:
<?php
class Users{
// 定义变量用于控制流程
private $data;
private $sqls;
private $nums;
private $total_nums;
public function run(){
$flag = true;
while($flag){
// 如果本次取不到500个用户,说明数据已处理完
if($this->nums != 500){ $flag = false; }
// 如果累计处理达到1万条,强制退出交由父进程重启
if($this->total_nums == 10000){
exit(0);
}
$this->getUsers(); // 获取未标记用户
$this->checkUserInfo(); // 调用外部API检测手机号/邮箱
$this->updateUserInfo(); // 将检测结果写回数据库
sleep(1); // 适度休眠,保护外部接口压力
}
}
}
$user = new Users();
$user->run();
?>
第二步:编写监控状态的 Shell 守护脚本
创建一个名为 `php_guard.sh` 的 Shell 脚本,主要用于判断当前是否有正在运行的 `check_users.php` 进程。如果发现没有进程在运行,说明前一批次已结束,则重新拉起 PHP 进程;如果发现进程存在但超过预期时间未退出,则将其 Kill 掉以防死锁。
#!/bin/bash
# 设置日志目录和文件名
LOG_DIR="/var/log/php-guard"
LOG_FILE="$LOG_DIR/guard.log"
mkdir -p $LOG_DIR
PROCESS_NAME="check_users.php"
PID_FILE="/tmp/php_guard.pid"
MAX_RUNTIME=3600 # 假设单次运行最长时间限制
while true; do
# 1. 检查 PHP 进程是否存活
PID=$(pgrep -f "$PROCESS_NAME")
if [ -z "PID" ]; then
# 进程不存在,记录日志并启动新进程
echo "[$(date)] Process not found, starting..." >> $LOG_FILE
php /path/to/check_users.php &
else
# 2. 进程存活,计算其运行时长(防卡死逻辑可在此扩展)
ELAPSED=$(ps -o etime= -p $PID | awk '{print $NF}')
# 若发现脚本异常挂起无响应,可根据实际运行时间与设定的阈值对比来执行 kill -9
# 此处省略复杂的时长计算公式,仅作示例
echo "[$(date)] Process running (PID: PID). Elapsed time: ELAPSED." >> $LOG_FILE
fi
# 每隔一分钟检查一次
sleep 60
done
第三步:通过 Crontab 调度守护脚本
利用 Linux 的 cron 服务,让上述 Shell 脚本每1分钟执行一次。打开终端输入:
- 进入命令模式:输入 `sudo crontab -e`。
- 添加计划任务,指向 shell 脚本所在路径: ```bash */1 * * * * /usr/bin/bash /path/to/php_guard.sh & >/dev/null 2>&1 ```
完成判断
执行完成后,查看数据库中 `flag` 字段的值。当用户的 `flag` 全部变为 `1`,即表示所有名单都已经过 API 校验并更新了 `has_phone` 和 `has_email` 的状态。整个过程无需人工干预,即使某时刻脚本中断,守护进程也会在下一次 cron 触发时重新启动。
简要总结
利用 Shell + Cron 做 PHP 的守护进程是运维中解决长任务丢失数据的经典低成本方案。通过将庞大的任务拆分小(分批处理+定期退出),配合外部监控脚本的“看门狗”作用,可以极大提升系统的容错能力。
以上就是Shell脚本作为保证PHP脚本不挂掉的守护进程的详细内容,更多关于Shell编程与PHP后端维护的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













