邮件打开率统计

PHP 代码如下

$base64 = “R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7”;
$img = base64_decode($base64);

Header( “Content-type: image/gif”);//直接输出显示jpg格式图片
echo $img;

 

Base64 Encode 1x1px透明GIF图片

下面就是Base64 Encode 1x1px透明GIF图片的data URI数据,有一天你会用到它们。

 

透明图片

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

黑色图片

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=">

php session 反序列化

 

session.serialize_handler stringsession.serialize_handler 定义用来序列化/解序列化的处理器名字。 当前支持 PHP 序列化格式 (名为 php_serialize)、 PHP PHP 内部格式 (名为 phpphp_binary) 和 WDDX (名为 wddx)。 如果 PHP 编译时加入了 WDDX 支持,则只能用 WDDX。 自 PHP 5.5.4 起可以使用 php_serializephp_serialize 在内部简单地直接使用 serialize/unserialize 函数,并且不会有 phpphp_binary 所具有的限制。 使用较旧的序列化处理器导致 $_SESSION 的索引既不能是数字也不能包含特殊字符(| and !) 。 使用 php_serialize 避免脚本退出时,数字及特殊字符索引导致出错。 默认使用 php

 

反序列化方法 可使用session_decode()

<?php
// if session is not started
session_start();

// store our current session
$my_sess = $_SESSION;

// decode $data (the encoded session data, either from a file or database). Remember, decoded data is put directly into $_SESSION
session_decode($data);
$data = $_SESSION;

print_r($data);

// restore our own session
$_SESSION = $my_sess;

?>

 

http://blog.spoock.com/2016/10/16/php-serialize-problem/

MySQL wait_timeout

mysql wait_timeout 是指MySQL多久未收到请求,就关闭连接所用时间。

默认php 不需要调用mysql_close() 也会自己断开连接。

最近遇到一长时间运行程序,由于wait_timeout设置时间为10s 而此程序 每循环一次也sleep 10s ,程序未调用关闭MySQL,导致每次 MySQL都断开连接,因而产生大量close_wait连接。

主动关闭后,close_wait 不再产生。

 

http://blog.itpub.net/22664653/viewspace-2143671/

浅谈CLOSE_WAIT

php curl dnscache 问题

通过IP直接访问网站,如果是HTTP请求,使用ip地址直接访问接口,配合header中Host字段带上原来的域名信息即可;如果是https请求,curl 中有一个 -resolve 方法可以实现使用指定ip访问https网站.
但是发现连接的ip会有错乱。如下:

$resolve= array(sprintf(
“%s:%d:%s”,
“xx.xx.com”,
443,
“10.176.137.232”
));

结果1:

[0]=>
string(51) “* Added xx.xx..com:443:10.176.137.232 to DNS cache”
[1]=>
string(45) “* Hostname xx.xx.com was found in DNS cache”
[2]=>
string(27) “* Trying 10.228.10.176…”
[3]=>
string(56) “* Connected to xx.xx.com (10.228.10.176) port 443 (#0)”

结果2:
[0]=>
string(51) “* Added xx.xx.com:443:10.176.137.232 to DNS cache”
[1]=>
string(45) “* Hostname xx.xx.com was found in DNS cache”
[2]=>
string(28) “* Trying 10.176.137.232…”
[3]=>
string(57) “* Connected to xx.xx.com (10.176.137.232) port 443 (#0)”

通过测试发现 加上选项:

curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE,false); 就可解决。

curl_multi*

<?php
        // While we're still active, execute curl
        $active = null;
        do {
            $mrc = curl_multi_exec($multi, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    
        while ($active && $mrc == CURLM_OK) {
            // Wait for activity on any curl-connection
            if (curl_multi_select($multi) == -1) {
                usleep(1);
            }
    
            // Continue to exec until curl is ready to
            // give us more data
            do {
                $mrc = curl_multi_exec($multi, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
function classic_curl($urls, $delay) 
{
    $queue = curl_multi_init();
    $map = array();

    foreach ($urls as $url) 
    {
        // create cURL resources
        $ch = curl_init();

        // 设置 URL 和 其他参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_NOSIGNAL, true);

        // 把当前 curl resources 加入到 curl_multi_init 队列
        curl_multi_add_handle($queue, $ch);
        $map[$url] = $ch;
    }

    $active = null;

    // execute the handles
    do {
        $mrc = curl_multi_exec($queue, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active > 0 && $mrc == CURLM_OK) {
        while (curl_multi_exec($queue, $active) === CURLM_CALL_MULTI_PERFORM);
        // 这里 curl_multi_select 一直返回 -1,所以这里就死循环了,CPU就100%了
        if (curl_multi_select($queue, 0.5) != -1) 
        {
            do {
                $mrc = curl_multi_exec($queue, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }

    $responses = array();
    foreach ($map as $url=>$ch) {
        //$responses[$url] = callback(curl_multi_getcontent($ch), $delay);
        $responses[$url] = callback(curl_multi_getcontent($ch), $delay, $url);
        curl_multi_remove_handle($queue, $ch);
        curl_close($ch);
    }

    curl_multi_close($queue);
    return $responses;
}

php-fpm Nginx 502 Bad Gateway – Permission denied

http://stackoverflow.com/questions/24325695/nginx-and-php-fpm-socket-owner

http://stackoverflow.com/questions/23598271/nginx-502-bad-gateway-permission-denied

php-fpm.conf 中
172 ; Set permissions for unix socket, if one is used. In Linux, read/write
173 ; permissions must be set in order to allow connections from a web server. Many
174 ; BSD-derived systems allow connections regardless of permissions.
175 ; Default Values: user and group are set as the running user
176 ; mode is set to 0660
177 listen.owner = nobody
178 listen.group = nobody
179 listen.mode = 0660

nginx.conf 中
user nobody nobody;

https 证书检测

需要对多台机器https证书进行检测。因此需要通过ip进行请求。
原方法:

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
            curl_exec($ch);

这种请求方式无法做到检测https证书;
采用下面的方法:
http://stackoverflow.com/questions/24351152/how-to-manually-resolve-hosts-in-https-connections-in-php

https://curl.haxx.se/libcurl/c/CURLOPT_RESOLVE.html
需用到php版本比较新,因此升级到php5.6.28,另libcurl版本也较低,升级到7.50.0,同时需要支持https;

重新编译php,升级curl

查找php编译参数
/usr/local/php/bin/php -i |grep configure

修改参数:

–with-curl=/usr/local/curl

make

make install

重启php-fpm即可;

新代码如下:

     
$ip='xx.xx.xx.20';

$url='https://xx.com';
$port=443;

$hostname='';
$resolve= array(sprintf(
    "%s:%d:%s", 
    $hostname,
    $port,
    $ip
));

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RESOLVE, $resolve);
curl_setopt($ch, CURLOPT_VERBOSE,true);
curl_setopt($ch, CURLOPT_STDERR,fopen('01.log','w'));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO,  'E:/ca-bundle.crt'); 
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);


$response = curl_exec($ch);
echo $response;
$error=curl_error($ch);
echo $error;

结果如下:

* Added xx.com:443:xx.xx.xx.20 to DNS cache
* Rebuilt URL to: https://xx.com/
* Hostname xx.com was found in DNS cache
* Trying xx.xx.xx.20…
* Connected to xx.com (xx.xx.xx.20) port 443 (#0)

可以看到请求到指定的ip上。其他信息如证书过期时间,证书是否匹配也会输出的log文件。

可能错误信息:
SSL: no alternative certificate subject name matches target host name ‘xx.xx.com’

可以调整系统时间测试证书过期情况。