标签归档:php

不依赖于web服务器的php测试环境

<?php
$scriptInvokedFromCli =
    isset($_SERVER['argv'][0]) && $_SERVER['argv'][0] === 'server.php';

if($scriptInvokedFromCli) {
    echo 'starting server on port 3000' . PHP_EOL;
    exec('php -S localhost:3000 -t public server.php');
} else {
    return routeRequest();
}

function routeRequest()
{
    $comments = file_get_contents('_comments.json');
    switch($_SERVER["REQUEST_URI"]) {
        case '/':
            echo file_get_contents('./public/index.html');
            break;
        case '/comments.json':
            if($_SERVER['REQUEST_METHOD'] === 'POST') {
                $commentsDecoded = json_decode($comments, true);
                $commentsDecoded[] = ['author'  => $_POST['author'],
                                      'text'    => $_POST['text']];

                $comments = json_encode($commentsDecoded, JSON_PRETTY_PRINT);
                file_put_contents('_comments.json', $comments);
            }
            header('Content-Type: application/json');
            echo $comments;
            break;
        default:
            return false;
    }
}

一个贪睡的sleeper

php写的命令行服务,有时候在不需要执行的时候,需要尽可能的降低消耗资源,最简单的降低消耗就是sleep了。
单次循环sleep间隔时间,有时候不满足需求,当前的sleeper采用了类似tcp的重传定时器,
不过,这个东西越sleep越贪睡奥,需要适度控制。

<?php

abstract class sleeper {

	protected $init_sleep_time;
	protected $sleep_time = 0;
	
	public function sleeper($init_sleep_time){
		$this->sleep_time = $init_sleep_time;	
		$this->init_sleep_time = $init_sleep_time;
	}

	public function real_sleep(){
		if($this->need_sleep()){
			echo $this->sleep_time . "\n";
			sleep($this->sleep_time);
			$this->sleep_time += 3;
		} else {
			$this->sleep_time = $this->init_sleep_time;
		}
	}
	
	public abstract function need_sleep();

}

class test_sleeper extends sleeper {
	
	public function sleeper($init_sleep_time = 1){
		$this->sleep_time = $init_sleep_time;	
	}

	public function need_sleep(){
		return true;	
	}

}

$sl = new test_sleeper(1);
for($i = 0; $i< 10; $i++){
	$sl->real_sleep();
}

gdb + nm 调试php扩展

调试php扩展,首先要保证生成的.so文件包含调试信息。
这个需要先修改config.m4
在其中加入:

if test -z "$PHP_DEBUG" ; then
   AC_ARG_ENABLE(debug,
           [--enable-debug compile with debugging system],
           [PHP_DEBUG=$enableval],[PHP_DEBUG=no]
   )
fi

接着phpize这一步没什么区别,重点在./configure的时候加入 –enable-debug

然后正常编译我们的php 扩展,make && make install

这样我们就拿到了,带有调试信息的so文件。

然后,我们需要找断点,我们查找so文件中定义的函数作为断点。

nm正好完成这个功能。
nm example.so 最右边那一列就是函数的名字,可以跟在break的后边作为断点。
最好结合grep来查找我们需要调试的函数,不过函数名并不是我们在扩展中定义的名字,因为,我们使用了一些像ZEND_FUNCTION,ZEND_METHOD等的宏,所以,grep到的名字可能很多,挑选我们需要的。

用php -m 查询一下我们要调试的php扩展是否加载。

如果加载了,我们就可以继续了。

gdb /usr/local/bin/php

break nm找到的调试的函数名

run 需要调试的php脚本,怎么也得包含需要调用的php扩展的函数调用吧,不然干嘛

剩下的工作就跟普通的gdb一样了。