LAMP开发环境搭建日志

前些天差不多把 Ubuntu 美化完了,基本上达到作为工作环境的基础条件。这几天集中精力鼓捣 PHP 的研发环境。要说 PHP 研发环境搭建绝对是最恶心的一个过程,没有之一,为此 Apache 还纠结了几个伙伴,成立了 Apache Friends,搞了个 XAMPP,来尽可能简化开发环境的搭建。不过自己动手的感觉是很棒的,虽然以后我应该不会再全程手工搭建犯这个贱了。
记录一下这个“恶心”的过程,留个念想。
这篇日志主要记录在 Ubuntu 18.04 LTS 版本上通过源码方式安装 PHP 研发环境的方法。
1. ANSI-C 编译和构建系统
无论是 Apache 还是 PHP,通过源码方式安装,首先必须具备的是一套编译和构建环境,以 GCC 安装为例:

sudo apt-get install build-essential

安装结束后,可以执行如下命令进行确认:
gcc --versiongcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2. 编译/安装/运行 Apache HTTP Server
PHP 大多数情况下都是配合 HTTP Server 使用,以 Apache HTTP Server 安装为例:
Apache HTTP Server 官网已经给出清晰的指导(http://httpd.apache.org/docs/2.4/install.html)
  1. Download : Download the latest release from http://httpd.apache.org/download.cgi
  2. Extract : gzip -d httpd-NN.tar.gz -> tar xvf httpd-NN.tar -> cd httpd-NN
  3. Configure : ./configure --prefix=PREFIX
  4. Compile : make
  5. Install : make install
  6. Customize : vi PREFIX/conf/httpd.conf
  7. Test : PREFIX/bin/apachectl -k start
但在上面第三步时,先不要着急执行 “configure”,Apache HTTP Server 的安装还有一些依赖,这些在官网上也有清晰的说明,主要是这两点:
  • APR 和 APR-Util
Download the latest versions of both APR and APR-Util from Apache APR, unpack them into /httpd_source_tree_root/srclib/apr and /httpd_source_tree_root/srclib/apr-util (be sure the directory names do not have version numbers; for example, the APR distribution must be under /httpd_source_tree_root/srclib/apr/) and use ./configure's --with-included-apr option
下载地址:http://apr.apache.org/download.cgi
安装方法:
  • APR:./configure --prefix=/usr/local/apr; make ; make install(这里注意用 sudo)
  • APR-Util:./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr; make; make install(这里注意用 sudo)
在我的系统上,编译 APR-Util的时候上报缺少expat的开发库:xml/apr_xml.c:35:19: error: expat.h: No such file or directory,这样解决:sudo apt-get install libexpat1-dev
  • PCRE
Download the source code from http://www.pcre.org. If your build system can't find the pcre-config script installed by the PCRE build, point to it using the --with-pcre parameter.
这里注意下载 PCRE1,不要使用 PCRE2,否则后面编译 Apache HTTP Server 会出错
安装方法:./configure --prefix=/usr/local/pcre; make; make install(这里注意用 sudo)
在我的系统上,就是因为开始编译使用的是 PCRE2,所以报了这个错误:util_pcre.c:58:10: fatal error: pcre.h: No such file or directory
编译 PCRE 的时候,还可能遇到另外一个编译问题:You need a C++ compiler for C++ support.
这是因为 PCRE 的编译需要 C++ 的环境,但我们往往认为安装了 gcc 就万事大吉,其实还需要安装 g++
通过这个命令来查看是否安装了 g++:g++ -v
sudo apt-get install g++
把 APR/APR-Util/PCRE 编译及安装好后,就可以开始配置 Apache HTTP Server 的编译选项以及最终的编译安装了。
Apache 的编译选项有很多,但最基本的如下所示:
./configure --prefix=/usr/local/apache2 --with-apr=/usr/local/apr/bin/apr-1-config --with-apr-util=/usr/local/apr-util/bin/apu-1-config --with-pcre=/usr/local/pcre/bin/pcre-config* --prefix==XXXX:这个代表将 Apache HTTP Server 安装到哪里 * --with-apr=XXXX:这个要设置为前面编译安装 APR 的目录中的 apr-config 文件 * --with-apr-util=XXXX:这个要设置为前面编译安装 APR-Util 的目录中的 apr-config 文件 * --with-pcre=XXXX:这个要设置为前面编译安装 PCRE 的目录中的 pcre-config 文件

完成编译和安装后,在运行前设置一下 Apache HTTP Server 的配置文件 httpd.conf,增加 “ServerName 127.0.0.1:80” 的配置
#Listen 12.34.56.78:80 Listen 80#这里是新增的配置 ServerName 127.0.0.1:80

然后可以执行如下的命令(后台执行)开启和关闭 Apache HTTP Server。
sudo ./apachectl -k start sudo ./apachectl -k stop

至此,基于源码安装 Apache HTTP Server 的过程暂时告一段落。
3. 安装 MariaDB
MySQL 被 Oracle 收购后,社区便单独拉出了 MariaDB 分支,继续开源,它们在本质上是相同的。
在 Ubuntu 上安装 MariaDB ,MariaDB 官方推荐使用 apt 等软件包管理工具,官方也给出了详细的安装指导,参见(https://downloads.mariadb.org/mariadb/repositories/#mirror=tuna&distro=Ubuntu&distro_release=bionic--ubuntu_bionic&version=10.3)。
简单整理一下步骤:
sudo apt-get install software-properties-common sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 sudo add-apt-repository 'deb [arch=amd64] http://mirrors.neusoft.edu.cn/mariadb/repo/10.3/ubuntu bionic main' sudo apt update sudo apt install mariadb-server

安装过程结束后,检查是否能够连接成功
andy@andy-ubuntu:/usr/local$ sudo mysql -u root -pEnter password: Welcome to the MariaDB monitor.Commands end with ; or \g. Your MariaDB connection id is 47 Server version: 10.3.7-MariaDB-1:10.3.7+maria~bionic mariadb.org binary distributionCopyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type 'help; ' or '\h' for help. Type '\c' to clear the current input statement.MariaDB [(none)]> exit Bye

启动/关闭 MariaDB 服务的方法
sudo service mysql start// 开启 MariaDB 服务 sudo service mysql stop// 关闭 MariaDB 服务

3. 编译/安装/运行 PHP
编译安装 PHP 的过程,可以参考 PHP 官网手册( http://php.net/manual/zh/install.unix.apache2.php )。
1) 编译 PHP
PHP 的编译选项也比较多,主要是打开各种功能,我的编译选项比较简单:
./configure --prefix=/usr/local/PHP \ --with-config-file-path=/usr/local/PHP/lib \ --with-apxs2=/usr/local/apache2/bin/apxs \ --with-mysqli \ --enable-mbstring

--with-apxs2:让 Apache HTTP Server 支持 PHP,体现在 httpd.conf 中增加了一条配置(LoadModule php7_module modules/libphp7.so)
--with-mysqli:mysqli 扩展技术不仅可以调用 MySQL 的存储过程、处理 MySQL 事务,而且还可以使访问数据库工作变得更加稳定
--enable-mbstring:使能 mbstring 扩展插件,我的项目调用了一点相关接口
编译检查时,报了一个错:
configure: error: libxml2 not found. Please check your libxml2 installation.// 执行如下命令解决 sudo apt-get install libxml2-dev

2) 设置 php.ini
将源码目录中的 php.ini-development 拷贝到 /usr/local/PHP/lib 目录中。
cp php.ini-development /usr/local/PHP/lib/php.ini

3) 检查 Apache HTTP Server 配置文件中是否开启了对 PHP 的支持
  • 打开 httpd.conf 文件,如果找到 “LoadModule php7_module modules/libphp7.so”,说明 Apache HTTP Server 已经开启对 PHP 的支持。
  • 设置 Apache 将特定的扩展名解析成 PHP,例如,让 Apache 将扩展名 .php 解析成 PHP。为了避免潜在的危险,例如上传或者创建类似 exploit.php.jpg 的文件并被当做 PHP 执行,PHP已经不再使用 Apache 的 AddType 指令来设置。可以参考官网给出的说明
SetHandler application/x-httpd-php

修改后重启 Apache HTTP Server。
4) 检查 PHP 和 Apache HTTP Server 的配合
写一个简单的测试文件 phpinfo.php 放到 Apache HTTP Server 的 htdoc 目录中

在浏览器中输入 http://127.0.0.1/phpinfo,如果能够成功显示 PHP 的配置信息,说明 PHP 和 Apache 的关联已经成功,Apache HTTP Server 已经能够成功解析 PHP。
**5) 检查 PHP 和 MariaDB(MySQL)的配合
首先,我在 MariabDB上创建了用户、数据库和数据表。通过 source 命令导入如下脚本:
CREATE USER andy IDENTIFIED BY '123456'; CREATE DATABASE IF NOT EXISTS phpstudy; USE phpstudy; CREATE TABLE IF NOT EXISTS admin ( username VARCHAR(32) NOT NULL, password VARCHAR(32) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO admin VALUES ('admin', '12345678'); CREATE TABLE IF NOT EXISTS article ( id INT(11) NOT NULL AUTO_INCREMENT, class VARCHAR(32) NOT NULL, title VARCHAR(256) NOT NULL, modifydate DATE NOT NULL, author VARCHAR(32) NOT NULL, content TEXT NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; GRANT ALL PRIVILEGES ON phpstudy.* TO andy;

然后,写一个简单的数据库连接和访问的代码,db_func.php 中封装了数据库的连接函数, db_test.php 中则访问了一张数据表:
/* db_func.php */ connect_errno) { echo "Fatal Error : connect MySQL failed : " . $mysqli->connect_errno . "
"; $mysqli = null; }return $mysqli; } ?>/* db_test.php */ query($query); if ($db_conn->errno) { echo "Fatal Error : " . $mysqli->errno . "
"; exit; } else { $record = $result->fetch_assoc(); $username = $record['username']; $password = $record['password']; echo 'username = ' . $username . '
'; echo 'password = ' . $password . '
'; } ?>

随后在 Apache HTTP Server 中创建了一个虚拟目录,用于以后的代码调试:
# 设置虚拟目录 Alias /phpstudy"/home/andy/Research/PHP/src" AllowOverride None Options None Require all granted # 设置打开虚拟目录后可以自动识别index.php DirectoryIndex index.html index.php

访问 “http://127.0.0.1/phpstudy/db/db_test.php” 成功显示如下结果:
username = admin password = 12345678

这里遇到一个数据库连接的问题,即代码中通过 “127.0.0.1” 能够连接 MariaDB,但通过 “localhost” 就提示连接失败。
Unix 系统下连接 MariaDB 的方式有两种,一种是 TCP,一种是 Socket。TCP 是所有系统都支持的,通过 TCP/IP 协议可以访问本地和远程 Server;而 Socket 只有 Unix 系统支持,通过 Unix Socket File 只能访问本地server。
通过 --host 参数可以指定主机,默认情况下输入 IP 地址即通过 TCP 方式连接,输入 localhost 或者不指定默认即通过 Socket 方式连接。
1. mysql --host=127.0.0.1 -u root -p# 通过 TCP 连接 2. mysql --host=localhost -u root -p# 通过 Socket 连接 3. mysql -u root -p# 通过 Socket 连接

而我在 Terminal 中通过 mysql -u rott -p 也就是 Socket 方式,是能够正常连接的:
andy@andy-ubuntu:/home$ mysql -u root -p Enter password: Welcome to the MariaDB monitor.Commands end with ; or \g. Your MariaDB connection id is 50 Server version: 10.3.7-MariaDB-1:10.3.7+maria~bionic mariadb.org binary distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help; ' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>

然而,在 PHP 脚本中却无法连接 localhost:
// 告警,连接失败 Warning: mysqli::mysqli(): (HY000/2002): No such file or directory

显然不是 MariaDB 而是 PHP 引擎出现了问题。
我引用这个页面的解答(https://segmentfault.com/q/1010000000328531)
PHP报的错误是No such file or directory,也就是说PHP找不到这个socket文件,那么PHP去哪找了?看手册:
mysqli::__construct ([ string username = ini_get("mysqli.default_user") [, string dbname = "" [, int socket = ini_get("mysqli.default_socket") ]]]]]]
所有参数都是可选参数,如果不指定,默认会从ini配置文件去读。那这个默认值是什么呢? 在php.ini里找到mysqli.default_socket这一行,我的这里是空值。
解决方案有两个:
一个是调用的时候,参数全部指定,如:
$db = new mysqli('localhost','uname','passwd','dbname','3306','/var/run/mysqld/mysqld.sock');
另一个是修改php.ini文件,找到mysqli.default_socket= ,修改为
mysqli.default_socket=/var/run/mysqld/mysqld.sock
我直接修改了 php.ini 文件。有一个小问题,就是 php.ini 文件在哪里。因为有的环境可能采用源码编译 PHP,有的可能是直接下载二进制包,因此大家的 php.ini 存放位置都可能不同,最靠谱的方式是通过 phpinfo() 系统函数来查询,如下是我的系统查询结果:
Item Value
Configure Command './configure' '--prefix=/usr/local/PHP' '--with-apxs2=/usr/local/apache2/bin/apxs' '--with-mysqli'
Configuration File (php.ini) Path /usr/local/PHP/lib
Loaded Configuration File /usr/local/PHP/lib/php.ini
【LAMP开发环境搭建日志】修改 php.ini 后重启 Apache HTTP Server,重新访问,通过 localhost 成功连接 MariaDB。
至此,在 Ubuntu 上搭建 PHP 运行环境的工作已经完成。后面也尝试用一用 XMAPP 或 XMNP 这种自动化套件。
LAMP开发环境搭建日志
文章图片

    推荐阅读