php

[toc]

在公司的网站上推荐使用 docker 容器来安装环境,一个项目一个 docker 容器。

、、

百度百科:https://baike.baidu.com/item/Docker/13344470?fr=aladdin

```nginx

server {

    listen 80;

    server_name  example.com;

    index index.php index.html index.htm;

    client_max_body_size 50M;

    error_log /home/deploy/apps/logs/example.error.log;

    access_log /home/deploy/apps/logs/example.access.log;

    root  /home/deploy/apps/example.com/current/public;

    # Load configuration files for the default server block.

    include /etc/nginx/default.d/*.conf;

    location / {

        try_files $uri $uri/ /index.php$is_args$args;

    }

    location ~ \.php {

        try_files $uri /index.php =404;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        fastcgi_param SCRIPT_NAME $fastcgi_script_name;

        fastcgi_index index.php;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_pass 127.0.0.1:9000;

        include fastcgi_params;

    }

}

````

#### 首先要安装 epel、remi 源

地址:...

#### 安装 PHP

现在,我们要从 EPEL 和 remi 仓库中安装最新版 PHP 。在安装之前,我们要知道有哪些可用的 PHP 包,以及各自的作用,PHP 以两种形式分发;一种是 CLI 包,目的是让我们在命令行中使用 PHP(我们会以这种形式),另外还有几个 PHP 包,把 PHP 与 Apache或Nginx Web 服务器集成在一起。

##### 安装 PHP CLI 包和 PHP-FPM:

Nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端。

Nginx一般是把请求发fastcgi管理进程处理,fascgi管理进程选择cgi子进程处理结果并返回给 nginx

一、编译安装php-fpm

什么是PHP-FPM

PHP-FPM是一个PHP FastCGI管理器,是只用于PHP的,可以在 http://php-fpm.org/download下载得到.

PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。

新版PHP已经集成php-fpm了,不再是第三方的包了,推荐使用。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,比spawn-fcgi具有更多优点,所以被PHP官方收录了。在./configure的时候带 –enable-fpm参数即可开启PHP-FPM,其它参数都是配置php的,具体选项含义可以查看这里。

```

sudo yum -y --enablerepo=epel,remi,remi-php70 install php-fpm php-cli php-gb php-mbstring php-mcrypt php-mysqlnd php-opcache php-pdo php-devel php-xml;

// 或者是只使用 remi-php70 仓库

sudo yum -y --enablerepo=remi-php70 install php-fpm php-cli php-gb php-mbstring php-mcrypt php-mysqlnd php-opcache php-pdo php-devel  php-xml;

```

`--enablerepo` 这个选项的作用是,告诉 `yum` 从 EPEL、remi和remi-php70 仓库中安装指定的软件包。没有这个选项的话,`yum` 只是使用默认的软件源。`--enablerepo=remi` 意思是使用 `remi` 源。或者修改 `/etc/yum.repos.d` 文件夹下面的 `epel.repo` 或 `remi.repo` 两个文件中的 `enabled=0` 属性,改为 `enabled=1`.

`-y` 是指全自动安装。

##### 搜索 PHP 扩展

```

yum search php

```

找到 PHP 扩展列表之后,按照下面演示的方法安装,你安装的包或许有所不同

确认 PHP 是否安装成功

```

php -v

```

##### 报错

如果报以下错误:

```

PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/sqlite3.so' - /usr/lib64/php/modules/sqlite3.so: undefined symbol: sqlite3_errstr in Unknown on line 0

```

##### 解决方法

You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.(您还可以在终端中运行`php --ini`,以查看PHP在CLI模式下使用的文件。)

```

php --'ini'

```

找到:`/etc/php.d/20-sqlite3.ini` 配置文件:把 `extension=sqlite3.so`注释掉。

##### EPEL 和 remi 下载 PHP 扩展

```

sudo yum -y --enablerepo=remi-php70 install 扩展名

// 例如:

sudo yum -y --enablerepo=remi-php70 install php-xdebug

```

##### 配置文件地址

- 扩展配置地址:`/etc/php.d`

    - 查看命令:`php --ini`

- 扩展存放目录:`/usr/lib64/php/modules`

    - 查看命令:`php-config --extension-dir` 或 `php -i | grep extension_dir`


> 不启用扩展在扩展配置文件里面注释掉即可。

##### 全局配置

在 Ubuntu 中 PHP-FPM 住配置文件所在:`etc/php7/fpm/php-fpm.conf`;

在 CentOS 中 PHP-FPM 住配置文件所在:`etc/php-fpm.conf`;

> PHP-FPM 的配置文件使用 INI 文件格式。

下面是 PHP-FPM 最重要的全局设置,我建议把默认值改为下面列出的值,默认情况下这两个设置可能被注释掉了,如果需要,去掉注释。这两个作用是:如果在指定的一段时间内优指定个子进程失效了,让 PHP-FPM 主进程重启。这是 PHP-FPM 进程的进本安全保障,能解决简单的问题,但是不能解决拙劣的 PHP 代码引起的重大问题。

- 在指定的一段时间内,如果实效的 PHP-FPM 子进程数超过这个值,PHP-FPM 主进程就优雅重启。


    ```

    emergency_restart_threshold = 10

    ```

- 设定 `emergency_restart_threshold` 设置采用的时间跨度


    ```

    emergency_restart_interval = 1m

    ```

> PHP-FPM 全局设置的详细信息参见:https://php.net/manual/zh/install.fpm.configuration.php

##### 配置进程池

PHP-FPM 配置文件其余的内容是一个名为 Pool Definitions 的区域。这个区域里的配置文件用于设置每个 PHP-FPM 进程池。PHP-FPM 进程池中是一系列相关的 PHP 子进程。通常一个 PHP 应用有自己的一个 PHP-FPM 进程池。

##### Ubuntu

在 Ubuntu 中 Pool Definitions 区域只有下面一行内容:

```

include=/etc/php7/fpm/pool.d/*.conf

```

##### CentOS

CentOS 则在 PHP-FPM 主配置文件的顶部使用下面的这样代码引人进程池定义文件:

```

include=/etc/php-fpm.d/*.conf

```

_____

这行代码的作用是让 PHP-FPM 加载 `/etc/php7/fpm/pool.d/目录`(Ubuntu) 或 `/etc/php-fpm.d/目录`(CentOS) 中的各个进程池定义文件。进入这个目录可以看到有个 `www.conf` 文件,这是默认的 PHP-FPM 进程池的配置文件。

> 每个 PHP-FPM 进程池的配置文件开头都是 "["  符号,后跟进程池的名称,然后是 "]" 符号。例如:在默认的 PHP-FPM 进程池的配置文件中,开头是 "[www]"。

各个 PHP-FPM 进程池都已制定的操作系统用户和用户组的身份运行。Modern 作者喜欢以非根用户身份运行各个 PHP-FPM 进程池,这样在命令行中使用 `top` 或 `ps aux` 命令时便于识别每个 PHP 应用的 PHP-FPM 进程池。这是个好习惯,因为每个 PHP-FPM 进程池中的进程都受相应的操作系统用户和用户组的权限限制在沙盒中。

我们要配置默认的 `www` PHP-FPM 进程池,让他以 `deploy` 用户和用户组的身份运行 (如果是 root 用户请跳过)。

==我建议把一下设置的默认值改为下面设置的:==

- 拥有这个 PHP-FPM 进程池中子进程池的系统用户,默认为 `apache`,可以改为让 `nginx` 去运行,在这里教程是设置为,非根用户的用户名

    ```

    user = deploy 

    ```

- 拥有这个 PHP-FPM 进程池中子进程池的系统用户组,默认为 `apache`,可以改为让 `nginx` 去运行

    ```

    gropu = deploy

    ```

- PHP-FPM 进程池监听的IP地址和端口号,让 PHP-FPM 只接受 nginx 冲这里传入的请求。

    ```

    listen = 127.0.0.1:9000

    ```

- 可以向这个 PHP-FPM 进程池发送请求的 IP 地址(一个或多个)。为了安全为把这个设置为:127.0.0.1,即只有当前设备能把请求转发给这个 PHP-FPM 进程池。

    ```

    listen.allowed_clients = 127.0.0.1

    ```

- 设定任何时间点 PHP-FPM 进程池中最多能有多少个进程,这个设置没有绝对正确点值,你应该测试你的 PHP 应用,确定每个进程需要使用多少内存,然后把这个设置设为设备可用内存能容纳的 PHP 进程的总数。对大多数中小型 PHP 应用来说,每个 PHP 进程要使用 5~15MB 内存。假设我们使用的设备为这个 PHP-FPM 进程池分配了 512MB 可用内存,那么我们可以把这个设置的值设为(512MB总内存)/(每个进程使用10MB) = 51 个进程。

    ```

    pm.max_children = 51

    ```

- PHP-FPM 启动 PHP-FPM 进程池中痢疾可用的进程数。对大多数中小型 PHP 应用来说,我建议设为 2 或 3.这么做是为了先准备好两到三个进程,等待请求进入,不让 PHP 应用的头几个 HTTP 请求等待 PHP-FPM 初始化进程池中的进程。

    ```

    pm.start_servers = 3

    ```

- PHP 应用空闲时 PHP-FPM 进程池中可以存在的进程数量最小值,一般和 `pm.start_servers` 设置的值一样,用于确保新进入的 HTTP 请求无需等待 PHP-FPM 在进程池中重新初始化进程。

    ```

    pm.min_spare_servers = 2

    ```

- PHP 应用空闲时 PHP-FPM 进程池中可以存在的进程数量最大值。

    ```

    pm.max_spare_serves = 35

    ```

- 回收进程之前,PHP-FPM 进程池中各个进程最多能处理的 HTTP 请求的数量。这个设置有助于避免 HTTP 扩展或库因编写拙劣导致不断泄露内存,为建议设为 1000

    ```

    pm.max_requests = 1000

    ```

- 日志文件在文件系统的绝对路径, PHP-FPM 进程池所属的用户和用户组必须有这个文件的写权限。

    ```

    slowlog = /var/log/php-fpm/www-slow.log

    ```

- 如果当前 HTTP 请求的处理时间超过指定的值,就把请求的回溯信息写入 `slowlog` 设置指定的日志文件。

    ```

    request_slowlog_timeout = 5s

    ```

编写保存 PHP-FPM 的配置文件后,要执行下述命令==重启== PHP-FPM 主进程:

##### Ubuntu

```

sudo service php7-fpm restart

```

##### CentOS

```

// CentOS7 的命令

sudo systemctl restart php-fpm.service

// CentOS6 的命令

sudo /sbin/service php-fpm start

sudo /sbin/service php-fpm restart

```

##### 9000 被占用报错

如果在启动 PHP-FPM 或者是在重启到时候报以下错误:(意思 9000 端口被占用)

```

[root@jdu4e00u53f7 ~]# /sbin/service php-fpm restart

Stopping php-fpm:                                          [FAILED]

Starting php-fpm: [04-Aug-2017 10:38:50] ERROR: unable to bind listening socket for address '127.0.0.1:9000': Address already in use (98)

[04-Aug-2017 10:38:50] ERROR: FPM initialization failed

                                                          [FAILED]

```

查看 9000 端口状态

```

netstat -anp | grep 9000

// 例如:

tcp  0  0 0.0.0.0:9000    0.0.0.0:*    LISTEN      5609/daemon.i686.mo

```

假如被 `daemon.i686.mo` 它占用了,杀死它,直接杀死它的 PID 5609:

```

kill 5609

```

#### 安装 MySQL

使用 EPEL6 与 remi 的 yum 源安装 MySQL 5.5.x

```

yum --enablerepo=remi install mysql mysql-server

```

如果是升级MySQL,请用:

```

yum --enablerepo=remi update mysql mysql-server

```

##### 如果 MySQl 报错

如果 MySQL 报以下错误:

```

Can't connect to local MySQL server through socket '/var/mysql/mysql.sock' (38)

```

##### 解决方法

启用MySQL服务:

```

/sbin/chkconfig mysqld on

```

启动MySQL服务器:

```

/sbin/service mysqld start

```

之后设置MySQL root密码:

```

mysqladmin -u root password 'new-password'

```

#### 安装 Nginx

##### Ubuntu

在 Ubuntu 中可以使用 PPA 包安装 Nginx。PPA 是 Ubuntu 专用术语,是指由 nginx 社区维护且预先打包好的档案。

```

sudo add-apt-repository ppa:nginx/stable;

sudo apt-get update;

sudp apt-get install nginx;

```

##### CentOS

在 CentOS 中可以使用前面添加的第三方软件仓库 EPEL 安装 nginx。CentOS 默认使用的软件仓库可能没有最新版本的 nginx。

> **`CentOS7`** 才能使用 `systemctl` 命令

```

sudo yum install nginx;

sudo systemctl enable nginx.service; // 系统自动启动

sudo systemctl start nginx.service; // 立刻启动服务

```

> **`CentOS6`** 使用以下命令

```

/sbin/service nginx start  // 立即启动 nginx

/sbin/service nginx restart //  重启 nginx

```

#### Nginx 虚拟主机

虚拟主机是一系列设置,用于告诉 nginx 应用的域名、PHP 应用在文件系统的什么地方,以及如何把 HTTP 请求转发给 PHP-FPM 进程池。

首先,我们必须决定把应用放在文件系统的什么位置。非根用户 `deploy` 必须拥有 PHP 应用所在文件系统目录的读写权限。这里,我们把应用的文件放在 `/home/deploy/apps/example.com/current` 目录中。我们还需要一个保存应用日志文件的目录。我们把日志文件放在 `/home/deploy/apps/logs` 目录中。

创建所需的目录,并赋予正确的权限:

```

mkdir -p /home/deploy/apps/example.com/current/public;

mkdir -p /home/deploy/apps/logs;

chmod -R +rx /home/deploy;

```

然后把 PHP 应用放到 `/home/deploy/apps/example.com.current/` 目录中。nginx 虚拟主机假设 PHP 应用有个 `public` 目录,这个是虚拟主机的文档根目录。

每个虚拟主机都有各自的配置文件。

- 如果使用 Ubuntu,请创建 `/etc/nginx/sites-available/example.com/` 配置文件;

- 如果使用 CentOS,请创建 `/etc/nginx/conf.d/example.conf` 文件。

虚拟主机的设置在 `server{}` 块中,例如:

```

server {

    listen 80;

    server_name  example.com;

    index index.php index.html index.htm;

    client_max_body_size 50M;

    error_log /home/deploy/apps/logs/example.error.log;

    access_log /home/deploy/apps/logs/example.access.log;

    root  /home/deploy/apps/example.com/current/public;


    # Load configuration files for the default server block.

    include /etc/nginx/default.d/*.conf;

    location / {

        try_files $uri $uri/ /index.php$is_args$args;

    }

    location ~ \.php {

        try_files $uri /index.php =404;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        fastcgi_param SCRIPT_NAME $fastcgi_script_name;

        fastcgi_index index.php;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_pass 127.0.0.1:9000;

        include fastcgi_params;

    }

}

```

复制上述代码,粘贴到 `example.conf` 虚拟主机配置文件中。记得要修改 `server_name` 设置,还要把 `error_log`、`access_log` 和 `root` 改为适当的路径。

##### 虚拟机主机设置

- **`listen`** 设置 nginx 监听哪个端口进入的 HTTP 请求。大多数情况下,HTTP 流量从 80 端口进入,HTTPS 流量从 443 端口进入。

- **`server_name`** 用于识别虚拟主机的域名。这个设置要设为你的应用使用的域名,而且域名要只想服务器的 IP 地址。如果 HTTP 请求中 Host 首部的值和虚拟机中的 `server_name` 的值匹配,nginx 就会把这个 HTTP 请求发给这个虚拟主机。

- **`index`** HTTP 请求 URL 没指定文件时的默认读取的文件。

- **`client_max_body_size`** 对着虚拟主机来说,nginx 接受 HTTP 请求主体长度的最大值。如果请求住的长度超过这个值,nginx 会返回 HTTP 4xx 响应。

- **`error_log`** 这个虚拟主机错误日志在文件系统中的路径。

- **`access_log`** 这个虚拟主机访问日志文件在文件系统中的路径。

- **`root`** 文档根目录的路径。

除了上述的设置之外,`server{}` 块中还有两个 `location` 块。作用:告诉 nginx 如何处理匹配指定 URL 模式的 HTTP 请求。

- **`location / {}`** 使用 `try_files` 指令查找匹配所请求 URI 的文件;如果未找到相应的文件,在查找匹配所请求 URI 的目录;如果也未找到相应的目录,把 HTTP 请求的 URI 重写为 `/index.php`,如果查询字符串的话,还会把查询字符串加到 URI 的末尾。这个重写的 URL ,以及所有以 `.php` 结尾的 URI,都由 `location ~\.php{}` 块管理。

- **`location ~\.php {}`** 把 HTTP 请求转发给 PHP-FPM 进程池处理。还记得吗,前面我们设置 PHP-FPM 进程池监听端口 `9000`。在这个块中,我们把 PHP 请求转发到端口 `9000` ,交给 PHP-FPM 进程池处理。

    > `location ~ \.php {}` 块中其他几行的作用是避免潜在的远程代码执行攻击。


如果操作系统是 Ubuntu 必须执行以下命令,创建虚拟主机配置文件的符号链接:

```

sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/example.cof;

```

最后,执行下述命令:重启 nginx:

Ubuntu

```

sudo service nginx restart

```

CentOS

```

sudo systemctl restart nginx.service

```

```

# For more information on configuration, see:

#  * Official English Documentation: http://nginx.org/en/docs/

#  * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;

worker_processes auto;

error_log /var/log/nginx/error.log;

pid /var/run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.

include /usr/share/nginx/modules/*.conf;

events {

    worker_connections  1024;

}

http {

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

                      '$status $body_bytes_sent "$http_referer" '

                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;

    tcp_nopush          on;

    tcp_nodelay        on;

    keepalive_timeout  65;

    types_hash_max_size 2048;

    include            /etc/nginx/mime.types;

    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.

    # See http://nginx.org/en/docs/ngx_core_module.html#include

    # for more information.

    include /etc/nginx/conf.d/*.conf;


  server {

        listen 80;

        server_name www.mdvtrw.com;

        index index.php index.html index.htm;

        root /var/www/phpub;

        # Load configuration files for the default server block.

        include /etc/nginx/default.d/*.conf;

    location / {

        try_files $uri $uri/ /index.php$is_args$args;

    }

    location ~ \.php {

        try_files $uri /index.php =404;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        fastcgi_param SCRIPT_NAME $fastcgi_script_name;

        fastcgi_index index.php;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_pass 127.0.0.1:9000;

        include fastcgi_params;

    }

  }

}

```

##### 报错

```

Uncaught SyntaxError: Unexpected token <

```

意思是nginx没有配置对,因为没有读取到 js。

> 本章节是最基础的设置,因为这个一个关于 PHP 的章节,而不是 nginx 章节。

## 相关主题

进一步学习 nginx

- http://nginx.org

- https://github.com/h5bp/server-configs-nginx

- https://serversforhackers.com/editions/

推荐阅读更多精彩内容