vlambda博客
学习文章列表

选择高起点(上),PHP开发首选LNMP经典架构

代码虽小,影响甚大。

果创科技CEO 黄禅宗


图片来源于网络


现在起,从微观角度,我们将会着手开始搭建一个小网站;从宏观角度,我们将踏入软件开发这个领域。在这条路上,我们会遇到很多之前未接触过的技术、概念、工具和框架等。在迎来自己参与搭建的千万级高并发大型网站系统前,我们需要做好承受各种问题和压力的心理准备,酝酿持续学习的心态,并有意识地不断投入时间和精力。


好的开始,是成功的一半。如果你是一个初学者,或者是刚入门的新手,我建议是在一开始就选择一个高起点。也许有人会问,选择低起点,选择入门成本低、学习曲线平缓的路径不好吗?这样可以快速上手。没错,确实是这样,但这只是短期的收益。我们还要从长期的发展来考虑。


如果仅是作为对技术的简单尝鲜,以及日后的目标也只是停留在普通的网站维护和开发时,那么低起点是可以的。但是,如果你也和我一样,致力成为专业的软件开发工程师,致力于尽我们最大的努力,开发并交付价值最大化的软件的话,那么你应该选择一个高起点。对于类似Windows图形化界面和集成开发环境XAMPP,正因为它的简单性、易用性,使得我们容易产生依赖、错觉和习惯。


如果解决方案都是别人现成提供的,只会安装使用,那么最多只能算是一名使用者。一旦出了问题就会措手不及、不知所措,因为从没亲自深入解决过遇到的问题。而专家都是能亲自解决各种难题的人,并且专家也会经常帮助他人解决问题。错觉则是指这些大众化的软件容易让人忽略背后的原理、底层实现、数据结构和算法等冰山以下的内容,觉得软件开发是那么简单,殊不知背后还蕴藏着如此庞大的知识体系。有时候,不知道自己不知道是危险的。参加马拉松长跑比赛和百米冲刺赛跑的运动员,都会有意识在比赛前不断地锻炼,他们会选择与之类似的运动难度而不只是在公园内散散步就企图希望能获得好成绩。同样,在软件开发中,我们也要时刻注意要锻炼我们的思维能力,有意识地训练我们的左右脑。当然不能只是通过简单使用一键安装式的软件来刺激我们的大脑,而是要深入细节,深入底层,深入过程,有意识地去学习、掌握和接触大量的技术、知识和信息。


由俭入奢易,由奢入俭难。类似地,大脑从高度集中、活跃状态到放松状态容易,而从放松状态进入活跃状态很难。特别当一个已经长期都习惯放松平衡的状态时,更难。还记得吗?软件开发是一项需要高智力的脑力开发活动。你的思维方式决定了你所编写的代码,也决定了今后做事的方式——不管高效与否。


今天的选择,会在潜移默化下无意识地影响我们今后几年内工作的方式,也会间接制约我们后面所能取得的成就和成果。通俗来说,往往今天的丰富收获,并不在于我们今天做了什么,或者是最近几天做了什么,而在于多年前做了什么,以及这么多年以来我们一直做了什么。


假设多年后的你穿越回到当前,如果你也已经意识到了一个高起点对于专业软件开发工程师的重要性,那么就让我们来开始新的选择吧——选择一个高起点!下面,将会介绍怎样选择操作系统、开发环境和框架。即便你是有经验的开发人员,相信也可以从中获益。


2.1 服务器系统首选Linux

一定要抵制住对Windows服务器系统的诱惑,要抵制住对GUI图形化界面的诱惑。


这里,并不是说Windows系统不好,也不是说CLI就一定要比GUI好。像高考填志愿一样,没有最好,只有更合适。后面我们将学习的网站开发所取用的技术大部分都是开源的,PHP开发语言是开源的,MySQL数据库是开源的,Nginx服务器是开源的,鉴于此,我觉得LNMP“黄金组合”再搭配开源的Linux操作系统是非常合理的,而不是Windows商业系统。除此之外,我们在后续搭建企业级网站系统过程中还会用到很多开源的软件、开源的框架和开源的类库,这是一个庞大的开源生态圈。如果硬要在这个开源生态圈内注入一个商业系统,会显得格格不入,也会对文化、技术、架构等产生一定副作用。当然,并不是说Windows系统不好,Windows系统很强大,但在这里适合选择Linux。


另一方面,作为一名专业人士,很有必要熟练掌握命令行终端的操作,也就是对各种shell命令的使用。通过使用命令,我们可以将任务脚本化,即在一个脚本内使用多条命令就可以完成一个任务的操作。这样可以节省每次手动重复操作的时间。更重要的是,脚本化代表的是一种自动化处理的能力,即可以完全脱离人工干预而进行的操作。试想一下,这是对宝贵的人力资源多大的解脱!举个例子,我们需要为每个小区的每位业主发送月度物业费邮件电子账单,假设业主有1000人。如果是人工来操作的话,需要登录邮箱然后分别编写邮件,找到对应的收件人,然后核实发送,这个过程显然时间漫长并且容易出错。如果换种方式,将这些操作全部都使用命令脚本来实现的话,只需要每个月,花一分钟执行这个命令即可。人力成本大为降低的背后就是效率极大的提升。纵使是这样,如果负责发送邮件通知的那个人,因为忘记或者刚好那天是国家节假日而没发邮件的话,就会产生差错。这时,我们可以将此脚本任务通过Linux的crontab定时任务固化下来。这样,完全不需要任何人干预,电脑就会自动并且非常负责任地帮我们完成任务啦!


千万不要因为Linux的高深莫测就打退堂鼓。Linux本身并不复杂,很多人,特别是初学者觉得它很难。这只是因为Linux设计时面向的人群就不是普通的电脑使用者,而是面向特定领域的专业人士,尤其是面向技术类专业人士。这一过程的转换之所以难,是因为对我们多年来使用操作系统习惯和思维的转换,才会觉得很难。Linux没有提供GUI图形界面,在上面我们不能使用鼠标左右移动,没有良好的人机交互体验。要想在我们的大脑和Linux操作系统之间进行通讯,我们只能使用键盘,敲下指令,回车,等待终端的输出反馈。


这里有一个悖论,看似这样的人机操作,限制了我们的操作速度,限制了我们的可视范围,但恰恰是这样的CLI终端,为我们打开了更广阔的知识大门,打开了思维上的新天地。Linux秉持着简单之美的原则,在屏幕上输出的信息全部都是非常有用的。如果能在一屏内显示完整,决不会给你显示两屏。对于那些非关键性、可显示也可不显示的信息,则通常都不会显示。如果说我们是在和高效的命令行打交道,还不如说是我们正在和开发提供这些命令行的专家在对话,与这些来自世界各地大师级的专家在“沟通”,我们收获的不仅是更高效完成当前任务,从长远角度上看,收获的是向专家级权威人士靠拢的思维方式和见解。当哪天,你能看懂顶级专家编写的代码和论著时,你离专家也就不远了。


但是学习Linux这个过程,特别是刚开始的时候,可以说是步履维艰的。这点我深有体会。我也是刚毕业不久才正式学习和使用Linux操作系统的,当时连一个tar解压打包的命令都要保存下来,每次执行时都要找出来贴上去,然后改改参数再执行,因为对shell命令很陌生,完全记不住。而现在,我已经可以熟练地掌握常用命令的操作,并且对于未曾接触过的命令,也可以快速通过man命令来查看帮助。


选择Linux操作系统,还有一个很大的现实原因就是:当毕业后,你会发现,你所就职的公司,基本上绝大部分的网站系统都是运行在Linux操作系统之上。谁更懂Linux,谁就能更容易解决将要发生的问题,并且更能胜任随时到来的挑战。


服务器系统首选Linux,这是我对全部致力于成为专业开发人士的建议之一。


2.2 自已动手搭建LNMP环境

确定了操作系统后,接下来,自然就到了LNMP环境。LNMP是中小型公司,乃至大型公司都会选择的方案。因为这个“黄金组合”成熟稳定,并且熟悉的人多。前面也有简单介绍,这里再稍微罗列下:


  • L表示Linux系列的操作系统,在本书中我们使用的是CentOS。

  • N表示Nginx,它可以实现均衡负载、反向代理、读写分离、URL重写等一系列功能。

  • P表示PHP,即网站开发语言,一种解释性脚本编程语言。

  • M表示MySQL,即开源的关系型数据库,可用于持久化存储数据。


与其他的教程不同,我不建议使用一键式集成开发环境,哪怕你现在是一个小白,我也会建议你一开始就自己动手搭建LNMP环境。


刚开始时,有可能你需要花费几天的时间,才能把整个开发环境搭建起来。但是没关系,不要急,也不要浮躁。要沉下心来,如果现在遇到这点难题就放弃的话,那么我们将会与千万级访问量的大型系统失之交臂。设想一下,如果你日后能在短时间内(例如几分钟内)找出使网站系统崩溃的原因并恢复正常,你需要具备哪些能力?你又需要为之做些什么呢?没错!就是当下,要把这个LNMP环境拿下。


就像医生诊断病人一样,如果他连人体的构造,各器官的位置和作用都不了解的话,他是不可能找得出病理的,更别说开药治病。病人也不会放心把自己的健康甚至生命托付给一无所知的医生。同样的道理,如果我们连LNMP都不了解,公司又怎能放心把网站系统托付给我们来维护和管理呢?这里说的了解,不是指表面上知其然,会使用,还要知其所以然,清楚涉及的安装、配置、优化、错误处理、实现原理等。能在今后和其他人进行技术沟通时,做到一问一答,举一反三。而不是一问三不知。


关于LNMP开发环境的搭建,网上已经有很多教程,大家可以根据自己的情况,结合当前使用的环境进行搭建,这里不再赘述。但我接下来会讲一些非常重要的关键点,讲一些不一样的内容。这些环节通常会容易被人遗忘或忽略,但却又是不可轻视的。至少从很多前来应聘的初级、中级开发工程师的回答上可以看出,他们缺少对这一块的认识。


2.2.1 Nginx的站点配置在哪?

Nginx的配置,在不同的系统上,因为安装方式不同,所存放的位置也不相同。我们先来简单看下Nginx的配置有哪些,再来看下可以通过什么途径找到这些配置的位置。最后看下配置Nginx的原则。


CentOS上的配置

默认情况下,Nginx的默认配置目录是在:/etc/nginx/,并且在这目录下会有一个nginx.conf的默认配置文件,也就是Nginx的配置文件。这里面有比较多重要、关键性的配置。其中,需要注意的是,如果在这份配置里搜索“include”,你会找到类似这样的配置:

http {
# 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 {
# Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; }}


 

这里有两处include配置。在http内但在server外的inclue的这行配置指明了,Nginx会从加载/etc/nginx/conf.d/目录下全部以conf为文件扩展名的配置文件。换言之,在此目录下正确配置的站点,都能通过Nginx来访问。根据这条线索和技巧,你就能快速找到Nginx的站点配置在哪。


Ubuntu上的配置

因为有时候,站点的配置不一定“藏”在这里。例如在Ubuntu上,就倾向放在/etc/nginx/sites-enabled/这个目录下。在Ubuntu系统上,Nginx.conf的配置会这样:

 include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;

它除了加载 /etc/nginx/conf.d/目录下,全部以.conf为后缀的配置文件外,还会加载/etc/nginx/sites-enabled/下全部的配置文件,注意,这时不管文件是什么后缀都会加载。似乎技术开发人员故意要为难技术开发人员,另外还有一个/etc/nginx/sites-available/目录。这个目录又是什么呢?原来这里才是放置Nginx真身配置的地方,在sites-enabled那个目录放置的是配置的“替身”,即指向/etc/nginx/sites-available/这个目录的软链接。举一个例子就很容易明白了。假设有一个配置文件:

/etc/nginx/sites-available/www.test.com

需要再添加软链接:

ln -s /etc/nginx/sites-available/www.test.com /etc/nginx/s
ites-enabled/www.test.com

然后重启Nginx才能访问www.test.com这个站点。


编译安装方式的配置

有时Nginx又比较调皮。它默认的配置文件nginx.conf可能是在/usr/local/nginx/conf/nginx.conf。如果采用的是下载Nginx源代码再手动编译安装的话,Nginx目录位置根据技术人员在安装时指定的位置不同而不同。可以在Nginx执行configure时指定,如:

./configure --prefix=/usr/local/nginx

在此nginx.conf配置文件里面,可能会看到:

include ./vhosts/*.conf;

则表示,此时Nginx的站点配置文件在/usr/local/nginx/conf/vhosts/这个目录下,并且需要以.conf为后缀。


Nginx的配置位置,可能还会有很多情况。但如果大家掌握了技巧,不管它在哪,我们都能快速找出来。这背后,只需要对include配置和文件路径的一点了解就可以了。要注意是绝对路径,还是相对路径;同时要注意是全部文件后缀,还是指定了.conf文件后缀。下面通过示例再稍微小结一下。


# 绝对路径,仅限.conf后缀include /etc/nginx/default.d/*.conf;
# 绝对路径,不限后缀include /etc/nginx/sites-enabled/*;
# 相对路径,仅限.conf后缀include ./vhosts/*.conf;
# 相对路径,不限后缀include ./vhosts/*;

专家技巧:根据nginx.conf文件里面的include配置项,可以快速找到Nginx站点的配置目录。


Nginx配置的原则

在开始配置你的站点前,注意不要把配置追加在/etc/nginx/nginx.conf默认文件里,也不要把多个站点都配置在/etc/nginx/conf.d/下的同一份配置文件里。而是应该一个网站,一份Nginx配置,并且以站点的名称作为文件名前缀。例如参考以下这样的配置:

 /etc/nginx/conf.d/www.examples.com.conf /etc/nginx/conf.d/docs.examples.com.conf /etc/nginx/conf.d/api.examples.com.conf

上面配置了三个站点,分别是:www.examples.com、docs.examples.com和api.examples.com。每个站点一份Nginx配置,以后维护更方便,也更简单。

专家原则:一个网站,一份Nginx配置,并以站点域名命名。


Nginx还有很多强大的配置,我们会在后面学习过程中,不断学习更多高级的技能。这时,我们先再来关注下,Nginx是如何和PHP-FPM通信的,也就是Nginx是怎样执行PHP文件的?


2.2.2 Nginx如何与PHP-FPM通信?

知道Nginx站点配置在哪后,下一步需要了解每份Nginx配置里面都有哪些内容?Nginx的配置有很多,刚开始时,我们只需要关注以下几项目配置。我把这称为最小化可用配置,即使网站运行起来的最基本的配置。

  • listen  侦听的端口,默认是80,可省略。

  • server_name  网站域名,多个域名使用空格分开。

  • index  默认访问的首页索引访问文件,一般对于静态网站是index.html,对于PHP则是index.php,对于C#则是index.asp,依此类推。

  • root   网站访问的根路径,通常我建议在项目内建立一个单独的public目录给外部访问,这样更安全,也更容易管理。

  • location  对PHP请求的转发和处理。Nginx本身不执行PHP文件,而是将对应的PHP请求通过FastCgi交由php-fpm进程来处理。

下面来看下对应的示例配置。以刚才的/etc/nginx/conf.d/www.examples.com.conf配置为例,在里面配置以下内容。

server{ listen 80; server_name www.examples.com;
index index.html index.php; root /path/to/www.examples.com/public;
location ~ .*\.(php|php5)?$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }}

可以看到,这里侦听的是80端口,网站域名为www.examples.com。默认首页为index.html和index.php,网站根目录为指向www.examples.com目录下的public子目录。最后,则是关键的部分,Nginx进程与PHP-FPM进程之间如何通讯的配置。这里传递的方式是通过socket来通讯的:

fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;

但在Linux操作系统上,两个不同的进程之间的通讯,还可以通过端口,这就是为什么有时候会这样配置:

fastcgi_pass 127.0.0.1:9000;

当你看到的是不同的配置时,不要困惑,一旦你了解了进程之间的通讯手段,就很容易明白了。


清楚这一点有什么用处呢?当你清楚整个请求背后的大概处理流程后,当发生问题或者故障时,就可以快速定位排查啦。


一个比喻,了解Nginx的执行流程

我们可以来找个比喻,你就能很容易明白上面Nginx的配置以及其执行流程了。


假设,我们开了一张新餐馆。把新店的位置以及餐馆正门告诉市场后,就会陆续迎来我们尊贵的客人。而对于网站,则是通过域名和端口来告诉互联网,告诉广大冲浪者。例如我们的www.examples.com域名和80端口。

 listen 80; server_name www.examples.com;

客人来了之前,他会拿起菜牌,挑选喜欢的菜式,然后向服务员下单。对于网站,网站访客会浏览页面上的内容和信息,然后点击页面链接进入他们感兴趣的页面。也就是说有人发起了请求,访问了我们网站根目录下的某些文件或页面。

 index index.html index.php; root /path/to/www.examples.com/public;

但是服务员本人不会下厨,服务员只会把客人要点的菜交由厨师来处理,然后等待厨师完成后,再把美食呈现给客人。Nginx和这个处理方式是类似的,Nginx本身不执行PHP文件,而是把PHP的请求通过socket或者IP和端口转发给php-fpm进程来处理。最后,等待php-fpm处理完成返回结果后,再中转返回给客户端。这就是为什么我们会看到:

 location ~ .*\.(php|php5)?$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

一旦明白了解这个过程,后面遇到任何问题,都不必惊慌。利用已经掌握的知识,稍微分析下,你就能很快找到原因了。下面我们会来看下可能会遇到哪些问题。


2.2.3 HOST绑定与网站访问

现在,我们可以开始简单测试网站的访问了。


首先,我们先创建一个简单的首页。继续前面的例子,先在www.examples.com/public目录下,添加index.php文件,并放置以下代码。

// $ vim ./index.php <?phpecho "<h1>Hello Wolrd!</h1>";

在本地开发时,我们通常需要绑定HOST后,才能访问自己的网站。因为这时网站还没发布,还只是在局域网内,并且公网的域名也还没进行公网DNS解析。绑定HOST的配置很简单,假设网站服务器的IP是192.168.1.2,那么对应的host配置是:

# www.examples.com的本地开发环境192.168.1.2 www.examples.com

但问题是,对于Windows、Linux和Mac操作系统,配置这个host的地方又有点不同。对于Winonws,通常位于C:\Windows\System32\drivers\etc\hosts;对于Linux和Mac,通常是保存在/etc/hosts文件。


添加保存后,这里使用浏览器就能这样访问啦!

选择高起点(上),PHP开发首选LNMP经典架构  

图2-1 搭建Nginx和PHP后的示例首页访问效果


是不是很简单?也许,但现实并不总是那么顺利的。在搭建过程中,你有可能会遇到各种问题。


2.2.4 关注错误日志

以下是你有可能遇到的问题,这里的目的并不是为了罗列出全部的问题和解决方案,而是为了分享在面对问题时,如何快速定位问题。从而哪怕是新手,也能做到有章可循,有条不紊地解决问题。

首先,我们先来了解一件法宝。这件法宝就是错误日志。例如Nginx的错误日志和php-fpm的错误日志。如前面的示例中,可以这样追加Nginx的错误日志配置:

server{ server_name www.examples.com; # 略…… error_log /var/log/nginx/www.examples.com.error_log;}

对于php-fpm,可以在php.ini配置文件中修改error_log选项,指定错误日志的文件路径。如下:

error_log = /var/log/php5-fpm.log

记得,在配置完上面内容后,都需要重启nginx或者php-fpm。

专家技巧:遇到问题时,要首先关注查看错误日志。


好了,准备妥当后,让我们看下将可能会遇到哪些问题,又将是如何进行分析、排查和解决。


502 Bad Gateway 错误

不管出现什么错误,首先看下Nginx的错误日志,可以看到当出现“502 Bad Gateway”错误时,有类似如下的错误日志:

2018/03/10 15:18:46 [error] 21426#0: *16 connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: www.examples.com, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "www.examples.com"


图2-2 502 Bad Gateway错误


Nginx的日志都是有一定格式的,从中不难发现提示了这样的错误:

connect() failed (111: Connection refused) while connecting to upstream
 

这里是指连接失败,即Nginx与php-fpm通讯失败。如果nginx配置没错的话,可检查php-fpm是否已启动。这类简单的问题,往往是困扰新手的大问题。就好像很多维修人员上门去解决电脑无法开机时,原来是因为未插电源。


启动php-fpm后,应该就能正常访问了。


404 File not found 错误

注意,前面是说应该能正常访问,而不是一定能。因为还可能会有别的问题。例如常见的404 File not found。导致404的原因有很多种,那种明显文件不存在,或者配置错误的原因就不说了。我这里分享另外一个会导致404,却很隐晦的原因。即便是有经验的人,也可能会忽略。


同样,出错404错误时,先来看下错误日志信息。会看到类似这样的提示:

2018/03/10 15:23:18 [crit] 21426#0: *19 stat() "/path/to/www.examples.com/public/" failed (13: Permission denied), client: 127.0.0.1, server: www.examples.com, request: "GET / HTTP/1.1", host: "www.examples.com"


里看到是权限不足。


对比查看下我们的PHP源代码的文件权限,检测后发现也是有执行权限的。那为什么还是没执行权限呢?

ll ./www.examples.com/public/index.php -rwxrwxr-x 1 dogstar dogstar 36 Mar 10 14:56 ./www.examples.com/public/index.php*


这是因为不仅需要PHP文件本身要有执行权限,还要求它的当前目录,全部父级目录也需要有执行权限。假设index.php文件的存储路径为/home/dogstar/projects/www.examples.com/public/index.php,那就要逐一检测各个目录的执行权限。

通过排查,可以发现dogstar这个用户的目录没有执行权限。而通常在Linux创建新账号时,其账号对应的目录都是没有执行权限的,这点需要注意。

$ ll /homedrwxr--r-- 36 dogstar dogstar 4096 Mar 10 14:56 dogstar/
解决的方法很简单,只需要追加执行权限即可,例如:
$ chmod +x /home/dogstar

再重新页面重新访问,就能正常访问首页了。如果还不行,再逐级排查。


500 Internal Server Error 错误

可以说,500错误是我们日后经常会遇到的错误。如果php-fpm已经启动,并且也具备全部执行权限时,若出现500错误时,通常都是PHP本身的问题,这样可以方便我们进一步收拢排查的范围。先来看下Nginx的错误日志。

2018/03/10 15:41:04 [error] 21429#0: *35 FastCGI sent in stderr: "PHP message: PHP Parse error:  syntax error, unexpected $end, expecting ',' or ';' in /path/to/www.examples.com/public/index.php on line 4" ……
这表明是PHP语法有错误。查看下对应的PHP源代码,原来是刚才我们新加的代码有问题。
<?phpecho "<h1>Hello World!</h1>";echo "by dogstar"

最后一行代码少了分号,补上即可正常访问。


2.2.5 PHP的两份配置

知道编写PHP代码的程序员不少,但知道PHP有几种运行模式的人并不多。

如果在网上搜索一下,可以找到例如这5种运行模式:

  • CGI(Common Gateway Interface),通用网关接口

  • FastCGI(Long-Live CGI),常驻型CGI

  • CLI(Command Line Interface),命令行运行模式

  • Web模块模式,Apache等Web服务器运行的模式

  • ISAPI(Internet Server Application Program Interface)


不同的运行模式,是有所差异的。而对我们技术开发人员来说,主要在以下这两方面。


配置上的差异

以常用的CGI和CLI这种运行模式为例,php-fpm使用的配置文件很有可能和命令行终端使用的配置文件是不同的。这也为什么,我们安装了一个PHP扩展,明明在浏览器访问是可以,但通过命令行来访问却是失败的。又或者反过来,命令行终端正常,在浏览端访问时却失败了。


如何找到php-fpm和命令终端用的是哪份配置?


要想快速找到命令终端用的是哪份配置,非常简单,使用以下命令即可:

$ php --iniConfiguration File (php.ini) Path: /etc/php5/cliLoaded Configuration File: /etc/php5/cli/php.iniScan for additional .ini files in: /etc/php5/cli/conf.dAdditional .ini files parsed:      /etc/php5/cli/conf.d/curl.ini,/etc/php5/cli/conf.d/gd.ini,/etc/php5/cli/conf.d/mcrypt.ini,……
通过这个php --ini这个命令,它会告诉你当前使用的是哪份配置。例如这里的是/etc/php5/cli/php.ini。

对于php-fpm用的是哪份配置,有两种方式,你可以继续使用命令行,如:

$ ps -ef | grep php-fpmroot     22190     1  0 15:46 ?        00:00:00 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)


通过查看进程的信息,可以看到用的是哪份php-fpm.conf,然后在同目录下找到对应的php.ini。


另外一种方式,是更常见也是更可靠的做法。就是通过phpinfo()函数来查看配置。例如添加phpinfo.php文件,并写入:

// www.examples.com$ vim ./public/phpinfo.php <?phpphpinfo();

然后保存,访问,就可以看到类似这样:

图2-3 phpinfo页面信息


从中可以找到php.ini的位置是在/etc/php5/fpm/php.ini。


如果php-fpm和命令行模式使用的不是同一份配置,会容易产生不一致的问题。在这里,你可以创建软链,使一方指向另一方。当然,你也可以继续手动维护两份配置。

专家技巧:为降低维护成本,将php-fpm和命令行模式的php.ini配置文件指向同一份文件。


2.2.6 数据库环境配置的方式

最后我们简单来说一下,如何集成MySQL数据库,也就是LNMP黄金组合的最后一部分。


首先,千万不要把数据库账号和密码写死在代码里。这是初级项目,个人项目,学校项目经常会做的事。但我们应当养成开发商业级项目的习惯,始终坚持高标准,高要求,尽量与日后线上商业系统的做法保持一致。


更好的方式,是采用配置方式来配置数据库的账号、密码、用户名等重要信息。一来避免敏感信息的泄露,二来方便不同环境下开发、测试、部署的便利。


考虑以下最初的MySQL数据库配置:

// www.examples.com$ vim ./config/db.php<?phpreturn array( 'name' => 'examples', // 数据库名字 'host' => 'localhost', // 数据库域名 'user' => 'root', // 数据库用户名 'password' => '123456', // 数据库密码 'port' => 3306, // 数据库端口);

这里采用的是硬编码的方式。这是常用、简单但也是有一定弊端的做法。

更好的方式,是通过环境变更来进行配置。这样会更灵活,也更容易进行管控。例如改为:

// www.examples.com$ vim ./config/db.php<?phpreturn array( 'name' => $_ENV['DB_NAME'], // 数据库名字 'host' => $_ENV['DB_HOST'], // 数据库域名 'user' => $_ENV['DB_USER'], // 数据库用户名 'password' => $_ENV['DB_PASS'], // 数据库密码 'port' => $_ENV['DB_PORT'], // 数据库端口);
不过,好的做法都需要一点成本。这里的成本就是需要我们额外添加对应的数据库环境变量配置。打开/etc/php5/fpm/pool.d/www.conf配置文件,然后同步追加以下配置:
env[DB_NAME]='examples'env[DB_HOST]='localhost'env[DB_USER]='root'env[DB_PASS]='123456'env[DB_PORT]=3306

然后,保存并重启php-fpm。你会发现,以上的配置不一定能正常读取。这是因为php-fpm默认是没有开启ENV环境变量的。每一次,我们都可以从新的问题获得新的知识。这时,可以修改/etc/php5/fpm/php.ini文件,并修改variables_orders配置项在前面追加表示ENV的字母E,从原来的GPCS变成EGPCS。如:

variables_order = "EGPCS"

然后,再次重启php-fpm。这时通过浏览器就能正常获取到上面配置的数据库信息了。


但是(生活里总有很多但是),CLI命令行模式呢?是否也能正常获取ENV环境变量?还记得我们前面说过吗?CLI不一定共用php-fpm的配置,因此这时你很可能还要同步修改/etc/php5/cli/php.ini文件里面的variables_orders配置项。


好了,但是(又一个但是,希望读者可以忍住骂我的声音),CLI模式下读取到ENV配置为空又是什么原因呢?这是因为,命令行方式下读取的环境变量来自/etc/environment文件。这时,需要切换到root用户权限,并追加以下配置,注意格式有所差异。

# vim /etc/environment export DB_NAME='examples'export DB_HOST='localhost'export DB_USER='root'export DB_PASS='123456'export DB_PORT=3306

因为是Linux的环境变量,所以需要export来导入。


通过环境变量而不是hard code的方式,我们就可以在不同的环境进行部署,而不需要来回修改代码中的配置。只需要修改不同环境上的数据库配置,就可以实现不同环境下的数据库连接了。

专家技巧:通过环境变量而不是硬编码的方式,进行数据库连接信息的配置。


这时,总算可以告一段落了。休息一下,我们稍候继续!