分类 php 下的文章

nginx和php-fpm环境记录php错误日志

转载自 http://www.jb51.net/article/49645.htm
nginx与apache不一样,在apache中可以直接指定php的错误日志,那样在php执行中的错误信息就直接输入到php的错误日志中,可以方便查询。
在nginx中事情就变成了这样:nginx只对页面的访问做access记录日志。不会有php的error log 信息。或者记录如下的很模糊的错误信息

2016/10/18 15:12:53 [error] 3232#0: *4688 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 121.121.121.121, server: dz.snsnb.com, request: "GET /admin.php?m=content&c=create_html&a=public_index&pc_hash=46yC97 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "xxx.xxx.xxx", referrer: "http://xxx.xxx.xxx/admin.php?m=admin"

nginx把对php的请求发给php-fpm fastcgi进程来处理,默认的php-fpm只会输出php-fpm的错误信息,在php-fpm的errors log里也看不到php的errorlog。
原因是php-fpm的配置文件php-fpm.conf中默认是关闭worker进程的错误输出,直接把他们重定向到/dev/null,所以我们在nginx的error log 和php-fpm的errorlog都看不到php的错误日志。
所以我们要进行如下的设置就能查看到nginx下php-fpm不记录php错误日志的方法:

1,修改php-fpm.conf中的配置,如果没有请增加:(这一步做完,php的错误记录就会记录在php-fpm的日志中)

[global]
; Note: the default prefix is /usr/local/php/var
error_log = log/php_error_log
[www]
catch_workers_output = yes

2.修改php.ini中配置,没有则增加:(这一步无效,可能是与我的环境有关,不纠结了,第二步就已经可以看错误日志了)

log_errors = On
error_log = "/usr/local/php/var/log/error_log"
error_reporting=E_ALL&~E_NOTICE

3.重启php-fpm

当PHP执行错误时就能看到错误日志在”/usr/local/lnmp/php/var/log/php_error_log”中了
如果出现:

[root@localhost etc]# service php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm [17-Apr-2014 18:40:52] ERROR: [/usr/local/php/etc/php-fpm.conf:5] unknown entry 'catch_workers_
[17-Apr-2014 18:40:52] ERROR: failed to load configuration file '/usr/local/php/etc/php-fpm.conf'
[17-Apr-2014 18:40:52] ERROR: FPM initialization failed
 failed

那请在第一步的时候,认真将配置写入相对应的组中,不然就出现上面的:

ERROR: [/usr/local/php/etc/php-fpm.conf:5] unknown entry ‘catch_workers_output'

nginx,php-fpm报错

网站报502错误
nginx记录信息如下

2016/10/18 15:12:53 [error] 3232#0: *4688 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 111.111.111.111, server: dz.snsnb.com, request: "GET /admin.php?m=content&c=create_html&a=public_index&pc_hash=46yC97 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "xxx.xxx.xxx", referrer: "http://xxx.xxx.xxx/admin.php?m=admin"

信息很模糊,打开php-fpm的日志,发现如下

[18-Oct-2016 11:43:25] WARNING: [pool www] child 24554 exited on signal 9 (SIGKILL) after 82.916762 seconds from start
[18-Oct-2016 11:43:25] NOTICE: [pool www] child 24614 started

child在还没有执行完毕就被杀掉了,想起来程序里面加了段提高内存的代码,如下

ini_set('memory_limit','1024M');

在重启完php-fpm之后段时间内是可以正常运行的,可能是child处理多个请求会使用过多内存,于是被杀掉了,于是把max_requests设置成1,使child每次处理完一次请求之后就重启

pm.max_requests = 1

ok

设置nginx连接php-fpm方式为socket

修改下面几项,用户和用户组的设置需要对应nginx的用户,不然会没有权限,我的nginx执行用户是 www

listen = /var/run/php-7.0.11-fpm.sock
listen.owner = www
listen.group = www

nginx 修改配置文件,这里的路径就是上面listen选项的路径

#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/php-7.0.11-fpm.sock;

重启nginx和php-fpm,ok

编译安装nginx,php

安装nginx

安装pcre

为了支持rewrite功能,我们需要安装pcre

yum install -y pcre* //如过你已经装了,请跳过这一步

需要ssl的支持,如果不需要ssl支持,请跳过这一步

yum install -y openssl*

编译安装

./configure --prefix=/usr/local/nginx-1.8.1 \
--with-http_spdy_module \
--with-http_stub_status_module \
--with-pcre

--with-http_stub_status_module:支持nginx状态查询
--with-http_spdy_module:支持google的spdy,想了解请百度spdy,这个必须有ssl的支持
--with-pcre:为了支持rewrite重写功能,必须制定pcre

报错

checking for OS
 + Linux 2.6.32-642.4.2.el6.x86_64 x86_64
checking for C compiler ... not found

./configure: error: C compiler cc is not found

安装所需的软件

yum -y install gcc gcc-c++

再 configure

报错

./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.

安装所需软件

yum install -y zlib-devel

再 configure

Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + using builtin md5 code
  + sha1 library is not found
  + using system zlib library

  nginx path prefix: "/usr/local/nginx-1.8.1"
  nginx binary file: "/usr/local/nginx-1.8.1/sbin/nginx"
  nginx configuration prefix: "/usr/local/nginx-1.8.1/conf"
  nginx configuration file: "/usr/local/nginx-1.8.1/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx-1.8.1/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx-1.8.1/logs/error.log"
  nginx http access log file: "/usr/local/nginx-1.8.1/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

安装

make //确定你的服务器有安装make,如果没有安装请执行yum install make
make install

添加启动脚本

这个网页可以 https://www.nginx.com/resources/wiki/start/topics/examples/redhatnginxinit/ 下载启动脚本

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  NGINX is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/etc/nginx/nginx.conf"

[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

make_dirs() {
   # make required directories
   user=`$nginx -V 2>&1 | grep "configure arguments:.*--user=" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   if [ -n "$user" ]; then
      if [ -z "`grep $user /etc/passwd`" ]; then
         useradd -M -s /bin/nologin $user
      fi
      options=`$nginx -V 2>&1 | grep 'configure arguments:'`
      for opt in $options; do
          if [ `echo $opt | grep '.*-temp-path'` ]; then
              value=`echo $opt | cut -d "=" -f 2`
              if [ ! -d "$value" ]; then
                  # echo "creating" $value
                  mkdir -p $value && chown -R $user $value
              fi
          fi
       done
    fi
}

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    sleep 1
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

修改下面脚本中两项为实际的路径

#nginx="/usr/sbin/nginx"
nginx="/usr/local/nginx-1.8.1/sbin/nginx"
#NGINX_CONF_FILE="/etc/nginx/nginx.conf"
NGINX_CONF_FILE="/usr/local/nginx-1.8.1/conf/nginx.conf"

把文件写入到 /etc/init.d/nginx

给权限,开启服务器

chmod +x /etc/init.d/nginx
service nginx start

php 编译安装,版本 php-7.0.11

取官方下载程序包

安装依赖包

yum install gcc make gd-devel libjpeg-devel libpng-devel libxml2-devel bzip2-devel libcurl-devel -y

configure: error: Please reinstall the libzip distribution

7.3需要安装高版本的libzip

# 先安装高版本的cmake,不然无法安装libzip
wget https://gitlab.kitware.com/cmake/cmake/-/archive/v3.0.2/cmake-v3.0.2.tar.gz
tar -zxvf cmake-v3.0.2.tar.gz 
cd cmake-v3.0.2
./bootstrap 
gmake && gmake install

# 安装libzip
先删除老的版本
yum remove libzip

wget https://nih.at/libzip/libzip-1.5.1.tar.gz
tar -zxvf libzip-1.5.1.tar.gz
cd libzip-1.5.1
mkdir build
cd build
cmake ..
make
make test
make install

编译安装(64位系统需要加上最后一个 --with-libdir=lib64)

./configure --prefix=/usr/local/php-7.0.11 \
--with-config-file-path=/usr/local/php-7.0.11/etc \
--with-bz2 \
--with-curl \
--enable-ftp \
--enable-sockets \
--disable-ipv6 \
--with-gd \
--with-jpeg-dir=/usr/local \
--with-png-dir=/usr/local \
--with-freetype-dir=/usr/local \
--enable-gd-native-ttf \
--with-iconv-dir=/usr/local \
--enable-mbstring \
--enable-calendar \
--with-gettext \
--with-libxml-dir=/usr/local \
--with-zlib \
--with-pdo-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-mysql=mysqlnd \
--enable-dom \
--enable-xml \
--enable-fpm \
--with-libdir=lib64

安装

make 
make test 
make install

复制 php 配置文件

cp php.ini-production /usr/local/php-7.0.11/etc/php.ini

复制 php-fpm 配置文件

cp /usr/local/php-7.0.11/etc/php-fpm.d/www.conf.default /usr/local/php-7.0.11/etc/php-fpm.d/www.conf

加入 service 管理脚本,修改到实际的路径即可

vim /etc/init.d/php7.0.11-fpm
#!/bin/bash
#
# Startup script for the PHP-FPM server.
#
# chkconfig: 345 85 15
# description: PHP is an HTML-embedded scripting language
# processname: php-7.0.11-fpm
# config: /usr/local/php/etc/php.ini
# config: /usr/local/php-7.0.11/etc/php.ini

# Source function library.
. /etc/rc.d/init.d/functions
# php 编译安装的目录
PHP_DIRECTORY=php-7.0.11
PHP_PATH=/usr/local/
DESC="php7.0.11-fpm daemon"
NAME=php-fpm
# php-fpm路径
DAEMON=$PHP_PATH/$PHP_DIRECTORY/sbin/$NAME
# 配置文件路径
CONFIGFILE=$PHP_PATH$PHP_DIRECTORY/etc/php-fpm.d/www.conf
# PID文件路径(在php-fpm.conf设置)
PIDFILE=$PHP_PATH/$PHP_DIRECTORY/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$PHP_DIRECORY

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

rh_start() {
  $DAEMON -y $CONFIGFILE || echo -n " already running"
}
rh_stop() {
  kill -QUIT `cat $PIDFILE` || echo -n " not running"
}

rh_reload() {
  kill -HUP `cat $PIDFILE` || echo -n " can't reload"
}

case "$1" in
  start)
        echo -n "Starting $DESC: $NAME"
        rh_start
        echo "."
        ;;
  stop)
        echo -n "Stopping $DESC: $NAME"
        rh_stop
        echo "."
        ;;
  reload)
        echo -n "Reloading $DESC configuration..."
        rh_reload
        echo "reloaded."
  ;;
  restart)
        echo -n "Restarting $DESC: $NAME"
        rh_stop
        sleep 1
        rh_start
        echo "."
        ;;
  *)
         echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
         exit 3
        ;;
esac
exit 0

给执行权限
chmod +x php-7.0.11-fpm

设置 php-fpm pid 文件
在 php-fpm 配置文件的 [global] 部分加入 pid 设置项

vim /usr/local/php-7.0.11/etc/php-fpm.d/www.conf
#添加
[global]
pid = run/php-fpm.pid

nginx 配置

server {
        server_name www.jintest1.com;
        root /www/www.jintest1.com;
        index index.html index.php;
        location ~ .*\.(php)?$
        {
                expires -1s;
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass 127.0.0.1:9000;

        }
}

ok

php发送apple远程推送

参考网址:http://wenku.baidu.com/link?url=92uLZLWTQcTJ-ZY9GgwNz8LlLEVP67pdnkP8VJnQrbJhnP7LAGhCbEydVxUkYLmGQdVCFLExG-yuHLjIdkA-S_DPcI-HFUvARK4dX3up36O
还有几个网址,浏览器关了,找不到了,就不贴了
配置证书就不记录了,纪录下证书转换成php能处理的格式的步骤。注意以下步骤有几个需要输入密码的地方,分别有不同的用途,为了避免之后混淆,我都设置成一样了

#推送证书转换,这个是从apple下载的推送证书
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
#导出的p12证书转换,注意这个p12证书是从推送证书导出的p12文件
openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12
#合并
cat PushChatCert.pem PushChatKey.pem > ck.pem
#测试是否能连接苹果的服务器
telnet gateway.sandbox.push.apple.com 2195

测试是否能连接苹果的服务器

telnet gateway.sandbox.push.apple.com 2195

出现以下即ok,可以继续进行下面的步骤

admindeMac-mini:远程推送 admin$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.18...
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is '^]'.

查看证书是否有效,注意在执行下面命令的时候会输入密码,就是之前设置的密码

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

出现以下结果即ok,可以进行后续的

#省略一部分。。。
SSL handshake has read 3160 bytes and written 2153 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: B10518ED571EFFF74E16A6C4BF0D61CC4ECA21AED726C01D110B8B879A190F9300578F1D764513AB29C2D11174F8395A
    Key-Arg   : None
    Start Time: 1462440274
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
#省略一部分。。。

php代码

<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 16/5/5
 * Time: 下午2:37
 */

error_reporting(E_ALL);
ini_set('display_errors', '1');

//将出错信息输出到一个文本文件
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');

//手机注册应用返回唯一的deviceToken
$deviceToken = '20596a98 b837fbe3 3df0f3f6 017bfb7e f96fc863 0dc11d0b 926f05dc c3c0b95f';//隐藏了自己的token
// 在google上搜索的时候,有的人因为写的不是绝对路径,或者文件不在本机而导致推送失败的,所以这里最好写本机的绝对路径
$pem = dirname(__FILE__) .'/'.'ck.pem';
//ck.pem通关密码
$pass = '123456';
//消息内容
$message = 'A test message!';
//badge我也不知是什么
$badge = 88;
//推送消息到手机时的提示音类型
$sound = 'default';
//建设的通知有效载荷(即通知包含的一些信息)
$body = array();
$body['aps'] = array('alert' => $message);// 弹窗显示的消息
$body['aps']['sound'] = $sound;// 声音
$body['aps']['badge'] = $badge;// 图标数字
//把数组数据转换为json数据
$payload = json_encode($body);
echo strlen($payload),"\r\n";

//下边的写法就是死写法了,一般不需要修改,
//唯一要修改的就是:ssl://gateway.sandbox.push.apple.com:2195这个是沙盒测试地址,ssl://gateway.push.apple.com:2195正式发布地址
$ctx = stream_context_create();

stream_context_set_option($ctx, 'ssl', 'local_cert', $pem);
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
/** 
 * 有人不能推送是 要加上这个
 * stream_context_set_option($ctx, 'ssl', 'cafile', 'entrust_2048_ca.cer'); 
 * 这个cer需要下载,但是有这个选项的话在生成 pem 文件的时候就和上面不一样了,因为没有遭遇到这样的错误,就不尝试了
 */
// ssl 和 tls 都可以
$fp = stream_socket_client('tls://gateway.sandbox.push.apple.com:2195',$err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp) {
    print "Failed to connect $err $errstr\n";
    return;
}
else {
    print "Connection OK\n<br/>";
}
// send message
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
print "Sending message :" . $payload . "\n";
fwrite($fp, $msg);
fclose($fp);
/*
35 Connection OK
Sending message :{"aps":{"alert":"A test message!"}} 
*/