shell脚本作为保证PHP脚本不挂掉的守护进程实例分享


Posted in PHP onJuly 15, 2013

前几天开始跑一份数据名单,名单需要提供用户名、是否有手机号、是否有邮箱,用户名单我轻易的获取到了,但是,用户名单有2000w之多,并且去检测用户是否有手机号、是否有邮箱必须得通过一个对外开放的安全接口一个一个用户去请求,然后分析返回值才能知道。

下面是我处理的方案:
1、将2000w名单保存到临时数据表
2、用PHP程序每次从该表获取500个用户,检测完后生成SQL update原纪录
3、为了防止PHP程序突然断掉,用shell脚本每隔1分钟检测,PHP挂掉了则重启
我使用shell脚本作为守护进程的原因是,手机与邮箱的检测接口速度慢,不可能在1~2天将2000w用户检测完。

方案详细:
1、临时保存用户名单表users,表结构如下:

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 '标志位', 
  PRIMARY KEY  (`account`), 
  KEY `flag` (`flag`) 
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='名单表';

我先将2000多w用户名导入到这个临时表,has_phone与has_email这二个字段默认都是0(没有),标志位flag说明该用户是否已经检测完。
下面是一部分表数据:
9873aaa,0,0,0
adddwwwd876222,0,0,0
testalexlee,0,0,0
codejia.net,0,0,0
haohdouywaa21,0,0,0
 
2、PHP脚本check_users.php
将 用户名单导入到表之后,再写一个简单的PHP脚本,思路是这样的:每次循环从表取flag=0的500个用户,然后请求接口判断用户是否有手机号、邮箱, 生成一条SQL,保存到一个SQLS数组里,等500个用户全部检测完了之后,循环SQLS数组,更新表里这500个名单,并将flag标志位设置为1, 表示已经检测完,下次就不获取了。
由于PHP脚本代码较长,这里分享下简单的代码说明:
<?php 
class Users{ 
    private $data; 
    private $sqls; 
    private $nums;         //判断是否有500用户 
    private $total_nums;   //当前已经检测完的用户数量     //每次取500个用户 
    private function getUsers(){...} 
    //检测这500个用户并生成SQL 
    private function checkUserInfo(){...} 
    //更新这500个用户 
    private function updateUserInfo(){...} 
    //运行 
    public function run(){ 
        $flag = true; 
        while($flag){ 
             if($this->nums != 500){ $flag = false; } 
             if($this->total_nums == 10000){  
                exit(0); //跑完1w个用户就退出,由守护进程启动 
             } 
             $this->getUsers(); 
             $this->checkUserInfo(); 
             $this->updateUserInfo(); 
             sleep(1); //跑完500用户休息1秒,保护用户检测接口      
         } 
    } 
} 
$user = new Users(); 
$user->run(); 
?>

上面是简洁版的PHP脚本,大概意思到了,刚开始的版本是没有$total_nums这个变量,是因为刚开始跑这个脚本的时候,发现只跑完了4w多条脚本就挂球了,后来一看,是因为连接数据库没连上,脚本一直挂在那里。加上这个变量也无法解决这个问题,只是在每次跑完1w个用户之后,PHP脚本退出,再由下面的shell脚本重新启动。

3、shell脚本作为守护进程
我把这个shell脚本加到了crontab里边,每隔1分钟执行一次,这个shell脚本很简单,检测check_users.php是否存在进程id,如果存在,则说明PHP脚本还在运行,shell脚本不做任何操作;如果不存在,则说明PHP脚本已经exit(0)跑完了1w用户退出了,那么shell脚本启动该脚本,进入下一个1w用户名单的检测。
上面我有讲到,如果PHP脚本在连接数据库的时候,无法连接上的时候,PHP会一直挂球在那里,无法退出了。我在shell脚本里加了一个时间检测,当PHP脚本进程存在的时候,计算已经存在了多长时间,如果超过了我预想的时间,则将PHP脚本kill掉,再重启。

开头的举例数据,结果类似如下:
testalexlee,1,0,1
codejia.net,0,0,1
haohdouywaa21,1,1,1
9873aaa,0,1,1
adddwwwd876222,1,0,1

说在最后:以上用户名单数据只是举个栗子,不要太认真,2000w数据,我估计要跑一段时间了,因为检测接口比较慢,接口在接到请求后还要连表,查表,再返回。其实,最好的方法还是直接从接口请求的表拉一份名单出来,再用shell命令处理下很快就有结果了,可是在公司就是这样,有些东西不开放的,你懂的~~~

PHP 相关文章推荐
利用js调用后台php进行数据处理原码
Oct 09 PHP
PHP简介
Oct 09 PHP
PHP下一个非常全面获取图象信息的函数
Nov 20 PHP
PHP中static关键字原理的学习研究分析
Jul 18 PHP
ThinkPHP3.1新特性之动态设置自动完成及自动验证示例代码
Jun 23 PHP
PHP中使用addslashes函数转义的安全性原理分析
Nov 03 PHP
ThinkPHP中__initialize()和类的构造函数__construct()用法分析
Nov 29 PHP
PHP SPL标准库中的常用函数介绍
May 11 PHP
typecho插件编写教程(一):Hello World
May 28 PHP
php生成固定长度纯数字编码的方法
Jul 09 PHP
php使用file函数、fseek函数读取大文件效率对比分析
Nov 04 PHP
php爬取天猫和淘宝商品数据
Feb 23 PHP
PHP 伪静态技术原理以及突破原理实现介绍
Jul 12 #PHP
php的$_FILES的临时储存文件与回收机制实测过程
Jul 12 #PHP
php图像处理函数大全(推荐收藏)
Jul 11 #PHP
PHP 获取远程文件大小的3种解决方法
Jul 11 #PHP
深入Nginx + PHP 缓存详解
Jul 11 #PHP
基于PHP中的常用函数回顾
Jul 11 #PHP
PHP 获取文件权限函数介绍
Jul 11 #PHP
You might like
初学者入门:细述PHP4的核心Zend
2006/09/05 PHP
浅谈php错误提示及查错方法
2015/07/14 PHP
php使用redis的有序集合zset实现延迟队列应用示例
2020/02/20 PHP
PHP安装扩展mcrypt以及相关依赖项深入讲解
2021/03/04 PHP
HR vs CL BO3 第一场 2.13
2021/03/10 DOTA
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
2013/03/11 Javascript
JavaScript中的方法调用详细介绍
2014/12/30 Javascript
angularjs学习笔记之三大模块(modal,controller,view)
2015/09/26 Javascript
js实现网页收藏功能
2015/12/17 Javascript
Uploadify上传文件方法
2016/03/16 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
纯js三维数组实现三级联动效果
2017/02/07 Javascript
Vue 2.0 服务端渲染入门介绍
2017/03/29 Javascript
JS+HTML实现的圆形可点击区域示例【3种方法】
2018/08/01 Javascript
微信小程序实现两个页面传值的方法分析
2018/12/11 Javascript
JS多个表单数据提交下的serialize()应用实例分析
2019/08/27 Javascript
UEditor 自定义图片视频尺寸校验功能的实现代码
2020/10/20 Javascript
python中如何使用正则表达式的非贪婪模式示例
2017/10/09 Python
python中for用来遍历range函数的方法
2018/06/08 Python
python: 判断tuple、list、dict是否为空的方法
2018/10/22 Python
Python实现二叉搜索树BST的方法示例
2019/07/30 Python
为什么python比较流行
2020/06/19 Python
美国专注于健康商品的网站:eVitamins
2017/01/23 全球购物
网上常见的一份Linux面试题(多项选择部分)
2014/09/09 面试题
优纳科技软件测试面试题
2012/05/15 面试题
保洁主管岗位职责
2013/11/20 职场文书
车贷收入证明范本
2014/01/09 职场文书
业绩倒数第一的检讨书
2014/09/24 职场文书
个人借款协议书范本
2014/11/17 职场文书
第28个世界无烟日活动总结
2015/02/10 职场文书
留学推荐信中文范文
2015/03/26 职场文书
升学宴来宾致辞
2015/07/27 职场文书
咖啡厅里的创业计划书
2019/08/21 职场文书
Go语言 go程释放操作(退出/销毁)
2021/04/30 Golang
Python中可变和不可变对象的深入讲解
2021/08/02 Python
Arthas排查Kubernetes中应用频繁挂掉重启异常
2022/02/28 MySQL