使用Shell脚本作为PHP定时任务的守护进程

温以宁
温以宁
发布时间:2026-10-14 | 8人浏览过
原创

在进行大批量数据处理(如数千万用户信息的异步检测)时,PHP脚本常因执行时间过长、内存耗尽或第三方接口波动而意外终止。为了保障此类定时任务的连续性和可靠性,可以利用轻量级的Shell脚本配合系统Crontab,构建一个简易的守护进程(Daemon),自动监控并重启挂掉的PHP进程。

结果与目标

建立一个可靠的后台批处理机制。该机制能够以10000条数据为一个批次进行循环处理,当PHP脚本达到批次上限或意外异常退出的时候,由Shell脚本接管并重新启动,避免人工干预,直至所有数据全部处理完毕。

准备条件与环境配置

  1. 数据库表结构:建立一张临时用户名单表,包含账号、手机号状态、邮箱状态及标志位字段。
  2. ``` 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='名单表'; ```
  3. 系统环境: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分钟执行一次。打开终端输入:

  1. 进入命令模式:输入 `sudo crontab -e`。
  2. 添加计划任务,指向 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后端维护的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表