实现php毫秒定时器方法详解

编程实验

72人已加入

描述

PHP编程语言是一种快速、简洁的服务端脚本编程语言,可以制作强大的交互性展现。在编程界PHP是完全免费的语言,在程序员身上使用非常的广泛,在编程中是大家高效的选择。

PHP能实现的功能

1.可以快速的生成动态网站页面内容,方便快捷。

2.可以在网站端实现对服务器上的文件管理,例如对文件的:创建、打开、读取、写入、关闭。

3.手机html中的表单数据,实现交互性。

4.方便、简单的可以发送和接收 cookies数据。

5.链接MySQL数据库之后,可以对数据库的数据进行可以对数据库中的数据,进行增、删、查、改等功能

6.方便的对隐私数据进行加密,限制某些用户访问网站上的资源。

实现php毫秒定时器

PHP 小程序,功能为每30秒记录时间,写入到文件

代码如下

# vi for_ever.php

#! /usr/local/php/bin/php

define(‘ROOT’, dirname(__FILE__)。‘/’);

set_time_limit(0);

while (true) {

file_put_contents(ROOT.‘for_ever.txt’, date(‘Y-m-d H:i:s’)。“\n”, FILE_APPEND);

echo date(‘Y-m-d H:i:s’), ‘ OK!’;

sleep(30);

}

?>

保存退出,然后赋予 for_ever.php 文件可执行权限:

# chmod +x for_ever.php

让它在再后台执行:

# nohup /home/andy/for_ever.php.php &

记得最后加上 & 符号,这样才能够跑到后台去运行

执行上述命令后出现如下提示:

[1] 5157

nohup: appending output to ‘nohup.out’

所有命令执行输出信息都会放到 nohup.out 文件中

这时你可以打开 for_ever.php 同目录下的 for_ever.txt 和 nohup.out 看看效果!

好了,它会永远运行下去了,怎么结束它呢?

# ps

PID TTY TIME CMD

4247 pts/1 00:00:00 bash

5157 pts/1 00:00:00 for_ever.php

5265 pts/1 00:00:00 ps

# kill -9 5157

找到进程号 5157 杀之,你将看到

[1]+ Killed nohup /home/andy/for_ever.php

OK!

=========================================================================

在很多项目中,或许有很多类似的后端脚本需要通过crontab定时执行。比如每10秒检查一下用户状态。脚本如下:

@file: /php_scripts/scan_userstatus.php

代码如下:

#!/usr/bin/env php -q

$status = has_goaway();

if ($status) {

//done

}

?>

通过crontab定时执行脚本scan_userstatus.php

#echo “*:*/10 * * * * /php_scripts/scan_userstatus.php”

这样,每隔10秒钟,就会执行该脚本。

我们发现,在短时间内,该脚本的内存资源还没有释放完,又启用了新的脚本。也就是说:新脚本启动了,旧脚本占用的资源还没有如愿释放。如此,日积月累,浪费了很多内存资源。我们对这个脚本进行了一下改进,改进后如下:

@file: /php_scripts/scan_userstatus.php

代码如下:

#/usr/bin/env php -q

while (1) {

$status = has_goaway();

if ($status) {

//done

}

usleep(10000000);

}

?>

这样,不需要crontab了。可以通过以下命令执行脚本,达到相同的功能效果

#chmod +x /php_scripts/scan_userstatus.php

#nohup /php_scripts/scan_userstatus.php &

在这里,我们通过&将脚本放到后台运行,为了防止随着终端会话窗口关闭进程被杀,我们使用了nohup命令。那么有没有办法,不使nohup命令,也能够运行呢,就像Unin/Linux Daemon一样。接下来,就是我们要讲的守护进程函数。

什么是守护进程?一个守护进程通常补认为是一个不对终端进行控制的后台任务。它有三个很显著的特征:在后台运行,与启动他的进程脱离,无须控制终端。常用的实现方式是fork() -> setsid() -> fork() 详细如下:

@file: /php_scripts/scan_userstatus.php

代码如下:

#/usr/bin/env php -q

daemonize();

while (1) {

$status = has_goaway();

if ($status) {

//done

}

usleep(10000000);

}

function daemonize() {

$pid = pcntl_fork();

if ($pid === -1 ) {

return FALSE;

} else if ($pid) {

usleep(500);

exit(); //exit parent

}

chdir(“/”);

umask(0);

$sid = posix_setsid();

if (!$sid) {

return FALSE;

}

$pid = pcntl_fork();

if ($pid === -1) {

return FALSE;

} else if ($pid) {

usleep(500);

exit(0);

}

if (defined(‘STDIN’)) {

fclose(STDIN);

}

if (defined(‘STDOUT’)){

fclose(STDOUT);

}

if (defined(‘STDERR’)) {

fclose(STDERR);

}

}

?>

实现了守护进程函数以后,则可以建立一个常驻进程,所以只需要执行一次:

#/php_scripts/scan_userstatus.php

这里较为关键的二个php函数是pcntl_fork()和posix_setsid()。fork()一个进程,则表示创建了一个运行进程的副本,副本被认为是子进程,而原始进程被认为是父进程。当fork()运行之后,则可以脱离启动他的进程与终端控制等,也意味着父进程可以自由退出。 pcntl_fork()返回值,-1表示执行失败,0表示在子进程中,而返进程ID号,则表示在父进程中。在这里,退出父进程。setsid(),它首先使新进程成为一个新会话的“领导者”,最后使该进程不再控制终端,这也是成为守护进程最关键的一步,这意味着,不会随着终端关闭而强制退出进程。对于一个不会被中断的常驻进程来说,这是很关键的一步。进行最后一次fork(),这一步不是必须的,但通常都这么做,它最大的意义是防止获得控制终端。(在直接打开一个终端设备,而且没有使用O_NOCTTY标志的情况下, 会获得控制终端)。

其它事项说明:

1) chdir() 将守护进程放到总是存在的目录中,另外一个好处是,你的常驻进程不会限制你umount一个文件系统。

2)umask() 设置文件模式,创建掩码到最大的允许限度。如果一个守护进程需要创建具有可读,可写权限的文件,一个被继承的具有更严格权限的掩码会有反作用。

3)fclose(STDIN), fclose(STDOUT), fclose(STDERR) 关闭标准I/O流。注意,如果有输出(echo),则守护进程会失败。所以通常将STDIN, STDOUT, STDERR重定向某个指定文件。

====================================

#!/bin/bash

PHP=/opt/php/bin/php

CMD_DIR=/data/yii2-angularjs

cd $CMD_DIR

while :; do

$PHP yii user/add-user

echo “$PHP yii user/add-user”

sleep 1

done

done

done

====================================

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分