LAMP
一、什么是 LAMP
LAMP 是一种常用的开源软件组合,用于构建和部署动态网站和 Web 应用程序。LAMP 代表的是 Linux、Apache、MySQL 和 PHP
-
Linux Linux 是一种开源的操作系统,提供了稳定、安全和高效的环境。它是 LAMP 架构的基础,负责管理硬件资源和提供必要的系统服务
-
Apache Apache 是一个开源的 HTTP 服务器,广泛用于提供网页服务。它能够处理大量的并发连接,支持多种编程语言和模块扩展,具有高性能和稳定性。Apache 负责接收用户请求并将其传递给相应的应用程序处理
-
MySQL MySQL 是一个关系型数据库管理系统,用于存储和管理网站的数据。它支持 SQL 语言,能够高效地处理大量数据查询和操作。MySQL 在 LAMP 架构中负责存储用户信息、产品信息等各种数据,并提供数据的增删改查功能
-
PHP PHP 是一种服务器端脚本语言,常用于生成动态网页内容。它可以嵌入到 HTML 中,能够与 MySQL 数据库进行交互,生成用户请求的动态内容。PHP 在 LAMP 架构中负责处理业务逻辑,并将结果返回给 Apache 服务器
- LAMP 架构的工作流程:
- 用户通过浏览器发送请求到 Apache 服务器
- Apache 服务器接收到请求后,将其传递给 PHP 脚本进行处理
- PHP 脚本根据业务逻辑,可能需要从 MySQL 数据库中读取或写入数据
- PHP 脚本处理完成后,将生成的动态内容返回给 Apache 服务器
- Apache 服务器将生成的网页内容发送回用户的浏览器进行显示
二、LAMP 的作用
LAMP 架构在 Web 开发和部署中有着广泛的应用和重要作用
-
动态网站和 Web 应用程序的开发:LAMP 提供了一个完整的开发环境,支持动态网站和 Web 应用程序的开发。通过 PHP 脚本语言,可以生成动态网页内容,并与 MySQL 数据库进行交互,存储和管理用户数据。
-
高效的服务器环境:LAMP 组合中的 Linux 操作系统和 Apache 服务器提供了一个高效、稳定的服务器环境。Apache 服务器能够处理大量并发连接,支持多种编程语言和模块扩展,适合各种规模的网站和应用。
-
数据存储和管理:MySQL 数据库管理系统在 LAMP 架构中负责存储和管理数据。它支持 SQL 语言,能够高效地处理大量数据查询和操作,适用于各种类型的数据存储需求。
-
开源和成本效益:LAMP 组件都是开源软件,意味着它们可以免费使用和修改。这使得 LAMP 成为一个成本效益高的解决方案,特别适合中小型企业和个人开发者。
-
跨平台和扩展性LAMP 具有良好的跨平台兼容性,可以在不同的操作系统上运行。此外,LAMP 组件的模块化设计使得系统具有良好的扩展性,可以根据需求添加或替换组件。
-
社区支持和资源丰富:由于 LAMP 组件都是开源软件,拥有庞大的用户社区和丰富的资源。开发者可以方便地找到文档、教程和支持,快速解决问题和提升开发效率。
总的来说,LAMP 架构为 Web 开发提供了一个高效、稳定、灵活的解决方案,广泛应用于各种类型的网站和 Web 应用程序。
三、部署 LAMP
1. 部署 MySQL
1.1 安装 MySQL
我们可以从 MySQL官网 里找到并下载源码包/可以使用包管理器安装的软件包,我们这里使用二进制免编译包
1
$ wget http://mirrors.163.com/mysql/Downloads/MySQL-5.6/mysql-5.6.47-linux-glibc2.12-x86_64.tar.gz -P /usr/local/src
发现阿铭提供的 MySQL 的二进制免编译包不可用,又从网上找了一个
将二进制免编译包上传到 /usr/local/src
目录下,然后进行如下操作
|
|
此处出错
1 2 3 4 5 6 7 8
$ sudo ./scripts/mysql_install_db --user=mysql --datadir=/data/mysql FATAL ERROR: please install the following Perl modules before executing ./scripts/mysql_install_db: Data::Dumper 或者是 $ sudo ./scripts/mysql_install_db --user=mysql --datadir=/data/mysql -bash: ./scripts/mysql_install_db: /usr/bin/perl: 坏的解释器: 没有那个文件或目录
提示缺少
perl-Module-Install
软件,通过yum install -y perl-Module-Install
来安装
安装后再次执行 ./scripts/mysql_install_db --user=mysql --datadir=/data/mysql
|
|
-
检查是否安装成功:
如果向上面一样看到了两个
OK
且在/data/mysql
下看到了生成的文件和目录,说明执行正确 或者是在执行完最后一条命令江批,马上执行
echo $?
看输出的结果为0
,说明执行正确
1.2 配置 MySQL
首先复制配置文件,然后打开配置文件并把配置文件改成如下内容
|
|
- 备注: 嵌套字地址:在 Linux 系统下,很多服务不仅可以监听一个端口(通过 TCP/IP 的方式通信),也可以监听 socket,两个进程就可以通过这个 socket 文件通信
然后复制启动脚本并修改其属性
|
|
然后修改启动脚本,并把启动脚本加入系统服务项,然后设置开机启动并启动 MySQL
|
|
-
备注:
-
上面加入到系统服务项的步骤是《跟阿铭学Linux 第三版》所给出的步骤,实际上
chkconfig
命令现在已经被systemctl
命令所替代,所以也可以这么做1 2 3 4 5 6 7 8 9 10 11
# 将服务文件复制到 /etc/systemd/system/ 目录 $ sudo cp /usr/local/mysql/support-files/mysql.server /etc/systemd/system/mysqld.service # 重新加载 systemd 配置 $ sudo systemctl daemon-reload # 设置 MySQL 为开机启动 $ sudo systemcrl enable mysqld # 启动 MySQL 服务 $ sudo systemctl start mysqld
-
如果启动不了,就到
data/mysql
目录下查看错误日志,这个日志名通常是[主机名].err
检查 MySQL 是否启动的命令为:1 2 3 4 5 6 7 8
# 检查 mysqld 服务的状态 $ sudo systemctl status mysqld # 查看 mysqld 相关进程(结果应该大于2行) $ sudo ps aux | grep mysqld # 看看有没有监听3306端口 $ sudo netstat -lnp | grep 3306
- 最后一个要是提示
-bash: netstat: 未找到命令
的,就是用命令sudo yum install -y net-tools
,安装之后就可以用了
- 最后一个要是提示
-
1.3 问题与解决
在最后使用 service mysqld start
启动服务的时候,我遇到了如下图所示的问题
尝试的解决方法:
- 在
/etc/init.d/mysqld
里,把之前没填上的【第46行basedir= /usr/local/mysql
】给填上,发现还是出现这个情况 - 发现上面有一条命令错误
误:
sudo mv mysql-5.6.49-linux-glibc2.12-x86_64 mysql
正:sudo mv mysql-5.6.49-linux-glibc2.12-x86_64 /usr/local/mysql
修改后成功运行
2. 部署 Apache
2.1 安装 Apache
同样,我们也可以从 Apache官网 里找到并下载源码包
由于这里使用的是 Apache(httpd) 2.4 版本的,所以需要额外下配套的 apr 和 apr-util 源码包并进行编译,apr 和 apr-util(统称 apr)可以理解为一个通用的函数库,主要为上层应用提供服务,在这里,httpd 是依赖 apr 的,如果不安装 apr,httpd 就无法工作
将下载好的源码包上传到 /usr/local/src
目录下,然后进行如下操作
|
|
在运行
./configure --prefix=/usr/local/apr
的时候出现以下错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ ./configure --prefix=/usr/local/apr checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking target system type... x86_64-pc-linux-gnu Configuring APR library Platform: x86_64-pc-linux-gnu checking for working mkdir -p... yes APR Version: 1.6.5 checking for chosen layout... apr checking for gcc... no checking for cc... no checking for cl.exe... no configure: error: in `/usr/local/src/apr-1.6.5': configure: error: no acceptable C compiler found in $PATH See `config.log' for more details
上网查到需要安装必要的工具和依赖库
1
$ sudo yum install -y gcc autoconf libtool openssl openssl-devel
都安装了之后,正常解决
然后编译 apr-util
|
|
在运行
make && make install
的时候遇到了如下问题
1 2 3 4 5 6 7 8 9
$ sudo make && make install ...... xml/apr_xml.c:35:19: 致命错误:expat.h:没有那个文件或目录 #include <expat.h> ^ 编译中断。 make[1]: *** [xml/apr_xml.lo] 错误 1 make[1]: 离开目录“/usr/local/src/apr-util-1.6.3” make: *** [all-recursive] 错误 1
缺少
expat
库,需要安装expat-devel
来解决
1
$ sudo yum install -y expat-devel expat
安装之后重新运行
make && make install
成功解决
安装完 apr 和 apr-util 之后,继续安装 httpd,配置编译参数,如下所示
|
|
为了避免出错,提前安装好一些库文件 pcre
和 pcre-devel
- 注意:有些时候可能不安装
pcre
和pcre-devel
反而会编译成功
|
|
然后开始编译
|
|
- 检查是否安装成功:使用命令
echo $?
如果输出0
那就是成功
在最后
make && make install
的时候出现了以下错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$ sudo make && make install ... /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_GetErrorCode' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_SetEntityDeclHandler' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_ParserCreate' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_SetCharacterDataHandler' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_ParserFree' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_SetUserData' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_StopParser' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_Parse' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_ErrorString' /usr/local/apr-util/lib/libaprutil-1.so: undefined reference to `XML_SetElementHandler' collect2: error: ld returned 1 exit status make[2]: *** [htpasswd] 错误 1 make[2]: 离开目录“/usr/local/src/httpd-2.4.57/support” make[1]: *** [all-recursive] 错误 1 make[1]: 离开目录“/usr/local/src/httpd-2.4.57/support” make: *** [all-recursive] 错误 1
网上搜到说主要问题是
libaprutil-1.so
中缺少expat
库相关的符号引用。这个问题通常是由于apr-util
在编译时没有正确链接到expat
库目前发现问题:
在 apr 的
make && make install
的时候出现了如下情况
1 2 3 4 5
$ sudo make && make install #在apr的安装 ... config.status: executing libtool commands rm: cannot remove 'libtoolT': No such file or directory config.status: executing default commands
- 缺少
libtoolT
尝试安装后重新编译
1
$ sudo yum install -y libtool
但是系统已安装最新版的
libtoolT
1 2 3 4 5 6
$ sudo yum install -y libtool 已加载插件:fastestmirror Loading mirror speeds from cached hostfile * epel: d2lzkl7pfhq30w.cloudfront.net 软件包 libtool-2.4.2-22.el7_3.x86_64 已安装并且是最新版本 无须任何处理
重复"从头到尾"的操作的时候发现成功 检查步骤的时候发现,并没有提前安装
pcre
和pcre-devel
-
安装完后,可以执行如下命令,查看 httpd 目录结构以及 modules 目录下面的木块文件:
1 2 3 4 5 6 7
$ ls /usr/local/apache2.4/ bin build cgi-bin conf error htdocs icons include logs man manual modules $ ls /usr/local/apache2.4/modules/ httpd.exp mod_cache_disk.so mod_log_debug.so mod_sed.so mod_access_compat.so mod_cache.so mod_logio.so ... # 省略了许多绿色的.so文件,这就是上面提到的木块,之所以有这么多,就是因为上面定义了一个most参数
这些模块不会全部加载,如果想要使用哪个模块,在配置文件里配置即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
$ sudo /usr/local/apache2.4/bin/apachectl -M AH00558: httpd: Could not reliably determine the servers fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message Loaded Modules: core_module (static) so_module (static) http_module (static) mpm_event_module (static) authn_file_module (shared) authn_core_module (shared) authz_host_module (shared) authz_groupfile_module (shared) authz_user_module (shared) authz_core_module (shared) access_compat_module (shared) auth_basic_module (shared) reqtimeout_module (shared) filter_module (shared) mime_module (shared) log_config_module (shared) env_module (shared) headers_module (shared) setenvif_module (shared) version_module (shared) unixd_module (shared) status_module (shared) autoindex_module (shared) dir_module (shared) alias_module (shared)
前面以
AH00558
开头的行,并不是错误,而是警告,可以在配置文件中定义”ServerName"使其消失,稍后将会说到配置文件 这些带shared
字样的,表示该模块为动态共享模块 还有带static
字样的,表示以静态的形式存在 动态和静态的区别在于: 静态模块直接和主程序 ( /usr/local/apache2.4/bin/httpd ) 绑定在一起,我们看不到 而动态 模块都是一个个独立存在的文件 ( modules 目录下的 .so 文件即是)
2.2 问题与解决
1. 在运行 ./configure --prefix=/usr/local/apr
的时候出现以下错误
|
|
上网查到需要安装必要的工具和依赖库
|
|
都安装了之后,正常解决
- 在运行
make && make install
的时候遇到了如下问题
|
|
缺少 expat
库,需要安装 expat-devel
来解决
|
|
安装之后重新运行 make && make install
成功解决
3. 在最后 make && make install
的时候出现了以下错误
|
|
通过不安装 pcre
和 pcre-devel
就可以解决该问题
3. 部署 PHP
3.1 安装 PHP
同样,我们也可以从 PHP官网 里找到并下载源码包
(这里以阿铭所使用的 PHP 5.6 举例)
|
|
在这里遇到了错误
1 2 3
$ sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... configure: error: xml2-config not found. Please check your libxml2 installation.
缺少对应组件,通过安装
libxml2-devel
解决
1
$ sudo yum install -y libxml2-devel
1 2 3 4
$sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... checking for BZip2 in default path... not found configure: error: Please reinstall the BZip2 distribution
缺少对应组件,通过安装
bzip2
和bzip2-devel
解决
1
$ sudo yum install -y bzip2 bzip2-devel
1 2 3
$ sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... configure: error: jpeglib.h not found.
系统中缺少
jpeglib.h
头文件,这是 JPEG 图像处理库的一部分需要安装
libjpeg-devel
包来解决这个问题
1
$ sudo yum install -y libjpeg-devel
1 2 3 4 5 6
$ sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... checking whether to enable JIS-mapped Japanese font support in GD... no If configure fails try --with-vpx-dir=<DIR> checking for jpeg_read_header in -ljpeg... yes configure: error: png.h not found.
缺少对应组件,通过安装
libpng
和libpng-devel
解决
1
$ sudo yum install -y libpng libpng-devel
1 2 3
$ sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... configure: error: freetype-config not found.
缺少对应组件,通过安装
freetype
和freetype-devel
来解决
1
$ sudo yum install -y freetype freetype-devel
1 2 3
$ sudo ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2.4/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif ... configure: error: mcrypt.h not found. Please reinstall libmcrypt.
缺少对应组件,通过安装
libmcrypt-devel
来解决
1
$ sudo yum install -y libmcrypt-devel
(安装
libmcrypt-devel
的前提是,系统里得有epel-release
才可以,根据具体情况,可能首先需要安装epel-release
才可以)
1
$ sudo yum install -y epel-release
以上全都做完之后,就可以编译好
然后开始编译
|
|
- 检查是否安装成功:使用命令
echo $?
如果输出0
那就是成功
最后复制配置文件
|
|
3.2 问题与解决
在编译时,遇到了这些错误
|
|
一句话,就是缺少组件,在编译前,通过这么一条命令来安装所有在这次编译中所需要的组件
|
|
然后如果自己的系统没有 epel-release
的话,就先
|
|
如果要是有,就直接再上面那条的命令后面再加上一个 libmcrypt-devel
否则就是
|
|
4. 配置 httpd 支持 PHP
httpd 的主配置文件为
/usr/local/apache2.4/conf/httpd.conf
编辑 httpd 主配置文件,如下所示
|
|
|
|
|
|
|
|
5. 测试 LAMP 是否成功
5.1 测试配置文件是否正确
启动 httpd 之前需要先检验配置文件是否正确
|
|
如像上面一样显示 Syntax OK
即为配置成功,否则请继续修改配置文件 httpd.conf
然后启动 httpd
|
|
查看是否启动的命令
|
|
如果像上面一样显示了那么一行,则说明已经启动了 httpd
另外,我们也可以使用 curl
命令进行简单的测试
|
|
如果显示了这么一行,则说明测试成功
5.2 测试是否正确解析 PHP
首先编写一个测试脚本,如下所示
|
|
并写入如下内容
|
|
保存脚本后继续测试,如下所示
|
|
如果能显示以上信息,则说明 PHP 解析正确
四、 配置 LAMP(主要是配置 httpd)
1. 配置文件
1.1 主服务器配置文件
httpd.conf:
- 位置:通常在
/etc/httpd/conf/httpd.conf
或/usr/local/apache2/conf/httpd.conf
- 作用:这是 Apache 的主配置文件,包含了服务器的全局设置和主服务器配置。例如:
- ServerRoot:指定 Apache 安装目录的路径
- Listen:指定服务器监听的 IP 地址和端口号
- DocumentRoot:指定网站文件的根目录
1.2 虚拟主机配置文件
httpd.conf 或 conf.d/*.conf:
- 位置:虚拟主机配置可以直接在
httpd.conf
文件中进行,也可以在conf.d
目录下的单独配置文件中进行 - 作用:配置多个虚拟主机,使得同一台服务器可以托管多个网站。例如:
<VirtualHost>
:定义虚拟主机的配置块,指定虚拟主机的 IP 地址、端口号、文档根目录等
1.3 日志配置文件
httpd.conf:
- 位置:通常在
/etc/httpd/conf/httpd.conf
或/usr/local/apache2/conf/httpd.conf
- 作用:配置 Apache 的日志文件。例如:
- ErrorLog:指定错误日志文件的路径
- CustomLog:指定访问日志文件的路径和格式
1.4 进程相关配置文件
envvars:
- 位置:通常在
/etc/httpd/envvars
或/usr/local/apache2/bin/envvars
- 作用:用于设置 Apache 服务器的环境变量,例如 PATH、LD_LIBRARY_PATH 等
2. Apache 配置内容、功能
2.1 默认虚拟主机
Q. 什么是 虚拟主机 和 默认虚拟主机?
A. 虚拟主机 就像是在一台物理服务器上创建多个独立的小房间,每个房间都可以托管一个独立的网站。这样,多个网站可以共享同一台服务器的资源(如 CPU、内存、存储等),但彼此之间是独立的。每个虚拟主机都有自己的域名、配置和文件目录。 默认虚拟主机 是当服务器接收到一个请求,但无法确定该请求属于哪个虚拟主机时,服务器会将请求发送到默认虚拟主机。就像是一个接待处,当有人进来但没有明确说明要去哪个房间时,接待处会先接待他们。
最后总结成一句话,任何一个域名指向这台服务器,只要是没有对应的虚拟主机,就会由这个默认服务器来处理。
那这个虚拟主机长啥样?我们怎么去配置它?就得来看看 httpd 的配置文件 httpd.conf
|
|
保存之后编辑虚拟主机配置文件 httpd-vhosts.conf
|
|
- 配置:
- ServerAdmin:指定管理员邮箱(平常没啥用)
- DocumentRoot:虚拟主机站点的根目录,网站的程序就放在这个目录下面
- ServerName:网站的域名
- ServerAlias:网站的第二域名,这里的域名可以写多个,用 空格 分割
- ErrorLog:网站的错误日志
- CustomLog:网站的访问日志
这里我们定义了两个站点 anitsuri.com
和 123.com
,那么当把第三个域名 abc.com
指向本机的时候,会去访问 anitsuri.com
,也就是默认虚拟主机
测试
让我们测试一下
|
|
由此,可以看出默认主机为anitsuri.com
,不管把什么域名指向该服务器,只要配置文件中没有标记,就会访问这个默认主机
2.2 用户认证
用户认证这个功能就是在用户访问网站的时候,需要认证(输入用户名和密码)才能顺利访问。一些比较重要的站点或者网站后台通常会加上用户认证,目的是保证安全
先来对 123.com
站点做一个全站的用户认证
|
|
这样 httpd 的配置文件配置完成,但是还需要创建密码文件
|
|
- 配置:
htpasswd
命令为创建用户的工具,-c
为 create(创建),-m
为指定密码加密方式为 MD5/data/.htpasswd
为密码文件,moka 为要创建的用户,第一次执行该命令的时候需要加上-c
,第二次再创建新的用户的时候就不用加-c
了,否则/data/.htpasswd
文件会被重置,之前的用户被清空
|
|
测试
配置完成后,需要到宿主机(真实的电脑)上去修改一下 hosts
文件,类似于 Linux 上的 /etc/hosts
Windows 上的 hosts 文件所在路径为 C:\Windows\System32\drivers\etc\hosts
,用记事本/写字板(或者其他支持文本编辑的工具,如:Notepad2)打开
保存 hosts
文件后,就可以用 Windows 的浏览器去访问 www.123.com
了。这时会弹出一个用于认证的提示框
这里在访问的时候出现了一个问题 ”我在我的 Windows 主机上能 ping 通
www.123.com(192.168.75.150 --- 主机地址)
但是浏览器却无法连接这个网址解决方法:记得关闭防火墙
1
$ systemctl stop firewalld
输入完用户名和密码后,将会进入 www.123.com
网站
上面的操作是针对整个站点做的认证,其实也可以针对某个目录或者某个文件进行认证
比如说要对 www.123.com/admin/
目录进行认证,只需要修改一个地方:把 <Directory /data/wwwroot/www.123.com>
改为 <Directory /data/wwwroot/www.123.com/admin>
如果是一个文件,比如 www.123.com/admin.php
则需要这样做
|
|
但是这样会有一个问题,网址中带有 admin.php
的链接都会弹出认证窗口
2.3 域名跳转
Q. 什么是域名跳转 A. 一个网站可能会有多个域名,比如 我的博客 可以用
blog.anitsuri.top
访问,也可以用moka.anitsuri.top
访问 而用blog.anitsuri.top
访问到时候,浏览器里面的网址直接变成了moka.anitsuri.top
,这就是域名的跳转过程Q. 域名跳转有什么作用 A.
- 用户体验:将用户从旧域名或错误的URL重定向到正确的页面,确保他们能够找到所需的信息
- SEO优化:通过重定向旧的或无效的链接到新的URL,保持搜索引擎排名,避免因死链而导致的SEO问题
- 网站迁移:在更换域名或网站结构时,通过重定向确保旧链接仍然有效,避免流量损失
- 负载均衡:将流量重定向到不同的服务器,以分散负载,提高网站性能和可靠性
那接下来我们将会实现一个需求:把 123.com
域名跳转到 www.123.com
,配置如下
|
|
-
备注:
-
在 RewriteRule 里是有【正则表达式】存在的。RewriteRule 后面由空格划分成三个部分
- 第一个部分是当前的 URL (也就是网址),不过这个 URL 是不把 主机头(也就是域名) 算在内的
- 第二个部分是 要跳转的目标地址,这个地址可以写全(包含了主机头),当然也可以不加主机头,默认就是前面定义的 ServerName
- 第三个部分是一些选项,需要用方括号括起来
- 301 是 状态码,它被称作 “永久重定向” (还有一种跳转用的状态码为 302,叫做 “临时重定向”)
- L 表示 “last”,意思是跳转一次就结束了
-
要实现域名跳转,需要有 rewrite 模块支持,所以先查看 httpd 是否已经加载该模块,如果没有还需要配置:
1 2 3 4 5 6 7 8 9 10
$ sudo /usr/local/apache2.4/bin/apachectl -M | grep -i rewrite # 如果此处没有任何输出,则需要编辑配置文件 $ sudo vi /usr/local/apache2.4/conf/httpd.conf # 搜索 rewrite 找到那行(第153行)把前面的井号删除 # 重新加载配置文件 $ sudo /usr/local/apache2.4/bin/apachectl graceful $ sudo /usr/local/apache2.4/bin/apachectl -M | grep -i rewrite rewrite_module (shared) #有这一行输出,说明正常加载 rewrite 模块
-
测试
配置完成后,进行测试,这里我们用 curl
测试就可以看到效果,如下所示
|
|
可以看到状态码为 301,跳转后的网址 (Location 那行) 为 http://www.123.com/
,则为配置成功
2.4 访问日志
访问日志的作用很大,不仅可以记录网站的访问情况,还可以在网站由异常发生时帮组我们定位问题,比如有攻击的时候,可以通过查看日志看到一些规律的
要配置 httpd 访问日志,首先要在主配置文件中定义访问日志的格式
|
|
- 可以看到两个格式的日志,建议用第一个,记录的信息会更安全
%h
为访问网站的IP%l
为远程登录名, 这个字段基本上为-
%u
为用户名,当使用用户认证时,这个字段为认证的用户名%t
为时间%r
为请求的动作(比如用curl -I
时就为HEADE
%s
为请求的状态码,写成%>s
为最后的状态码%b
为传输数据大小%{Referer}i
为 referer 信息 请求本次地址上一次的地址就是 referer 比如在百度中搜索 Rotaeno,然后通过百度的搜索结果页面点击到了 Rotaeno官网,那访问 Rotaeno 官网的 referer 就是 baidu,当然那个地址肯定是很长的%{User-Agent}
为浏览器标识 比如你用 FireFox 或者 Chrome 浏览器,则该字段显示内容不一样,是带有浏览器标识的
- 对于这个日志格式,你可以自定义调整各个字段的位置,也可以额外增加其他字段
比如增加
%D
(请求消耗时间) 不过对我来说没啥用,就没整
然后继续编辑虚拟主机配置文件
|
|
保存配置文件后,测试语法并重新加载配置
|
|
发现生成了日志,并且有相关的日志记录 另外,用 FireFox 浏览器访问一下,再次查看日志,发现多了一行
|
|
一个网站会有很多元素,尤其是图片、js、css等静态的文件非常多,用户每请求一个页面就会访问诸多的图片、js等静态元素,这些元素的请求都会被记录在日志中 如果一个站点访问量很大,那么访问日志文件增长会非常快,一天就可以达到几GB。这不仅对于服务器的磁盘空间造成影响,更重要的时会影响磁盘的读写速度 但是访问日志又非常重要,又不能不去记录,还好这些巨量的静态元素请求记录到日志里意义不大
所以可以限制这些静态元素去记录日志,并且需要把日志按天归档,一天一个日志,这样也可以防止单个日志文件过大
|
|
- 先定义了一个
image-request
环境变量,把 gif、jpg、png、bmp、swf、js、css 等格式的文件全部归类到image-request
里,后面的env=!image-request
有用到一个!
,这相当于取反了,意思是吧image-request
以外类型的文件记录到日志里 - 正常应该
CustomLog
后面为日志文件名,但是这里我们用了一个管道,它会把日志内容交给后面的rotatelogs
命令处理 这个rotatelogs
为 httpd 自带切割日志的工具,它会把访问日志按我们定义的文件名格式进行切割 - 其中
86400
单位是 “秒” 也就是 “一天”
测试
保存配置文件后,测试配置文件是否存在错误,没有错误的话就重新加载服务
|
|
这里的 123.com-access_20240808.log
就是新生成的日志,而且以后会每天生成一个按日期命名的日志
下面再来测试一下 “在日志不记录静态元素” 的配置
|
|
可以看到,123.com-access_20240808.log
日志中只有 moka.txt
的请求日志,但没有 moka.jpg
的请求日志
去除了静态元素的日志,日志文件会瘦身很多
2.5 静态元素过期时间
在上面的日志里,如果你观察的很仔细,会发现有一个状态码为 304,这个状态码标识该文件已经缓存到用户的电脑里了,再次请求它的时候不用从服务器上下载,而是直接访问用户电脑里面的缓存 这样做的目的是降低服务器的资源小号,还可以提升用户访问网站的速度 平时我们访问一个网站时,会有很多元素为静态的小图片,那这些小图片完全可以缓存到咱们的电脑里,这样再次访问该站点时,速度就会更快
那到底能缓存多久呢?如果服务器上某个图片更改了,那么应该访问新的图片才对 这就涉及了一个静态文件缓存市场的问题。也叫做 ”缓存过期时间“
在 httpd 的配置文件中,我们是可以控制这个时间的
|
|
- 这部分配置用到了 mod_expires 模块,相关配置内容并不难理解,通过字面也可以大概猜到其含义
- 这里 gif、jpeg、png 格式的文件过期时长为 1天,css、js、flah 格式的文件过期时长为 2 消失,其他文件过期时长为 0,也就是不缓存
保存配置文件,检查配置是否有问日,没问题重新加载服务
|
|
测试
下面,使用 curl 来测试它的效果
|
|
- 可以看到
max-age-86400
,这说明 jpg 的图片将缓存 86400 秒,也就是一天 - 上面我们也提到了状态码是 304,按理说既然有缓存,那我们请求该图片的时候也应该是 304 才对,但是这里却是 200 这是因为我们是使用 curl 工具来请求的,它并不像浏览器那样可以缓存这些文件
另外也可以测试一下 txt 的文件
|
|
- 其中
max-age-0
,说明没有缓存该类型的文件
2.6 防盗链
讲个故事:(故事来源于《跟阿铭学Linux 第三版》 2009年的时候,阿铭负责运维一个业务5d6d(早已经死翘翘了)为免费论坛,谁都可以申请,其中一个站长申请了一个站点专门来存放图片。由于经验匮乏,阿铭并没有给该业务做防盗链,所以导致这个网站的图片随便被别的网站借用,该站点的图片有点偏色情,所以访问量巨大,最终导致该业务带宽在一个月内飙升了 300 M.当发现带宽异常时,通过抓包找到了对应的站点,随后给服务器做了防盗链,并且删除了有问题的图片,这样我们才把带宽恢复到正常值。但那个月的带宽费用确实让公司出血了。
通过这个真实案例,我们可以体会到做防盗链是多么有价值。 防盗链,通俗讲,就是不让别人到用你网站上的资源。这个资源,通常指的是图片、视频、歌曲、文档等 讲解防盗链配置之前,再说一下 referer 的概念,上面讲解日志格式的时候提到过它 我们通过 A 网站的一个页面
http://a.com/a.html
里面的链接去访问 B 网站的一个页面http://b.com/b.html
,那么这个 B 网站页面的 referer 就是http://a.com/a.html
。也就是说,一个 referer 其实就是一个网站
下面来学习配置防盗链
|
|
- 首先定义允许访问链接的 referer,其中
^$
为空 referer,当直接在浏览器里输入图片地址去访问它时,它的 referer 就为空。然后又使用filesmatch
来定义需要保护的文件类型,访问 txt、doc、mp3、zip、rar、jpg、gif 格式的文件,当访问这样类型的文件时就会被限制。
测试
|
|
2.7 访问控制
对于一些比较重要的网站内容,出来可以使用用户认证限制访问之外,还可以通过其他一些方法做到限制,比如可以限制 IP,也可以限制
user_agent
- 限制 IP 只的是限制访问网站的来源 IP
- 限制
user_agent
通常用来限制恶意或者不正常的请求
2.7.1 限制 IP 访问
先来看如何限制 IP 访问
|
|
- 使用
<Directory>
来指定要限制访问的目录,order
定义控制顺序,哪个在前面就先匹配哪个规则 在本例中deny
在前面,所以先匹配Deny from all
,这样所有的来源 IP 都会被限制,然后匹配Allow from 127.0.0.1
,这样又允许了127.0.0.1
这个 IP 最终的结果是,只允许来源为127.0.0.1
的访问
2.7.1 限制 IP 访问 测试
下面为认证过程
|
|
-
本机有两个IP
(其实是三个,但是另一个没用上),一个是192.168.92.128
,一个是127.0.0.1
,通过这两个 IP 都可以访问到站点 可来源IP分别为192.168.92.128
和127.0.0.1
,其实和本机IP是一样的,也可以使用 Windows 的浏览器访问 浏览器访问提示Forbidden
其实就是 403 再来看看日志,可以查看到对应来源IP为192.168.75.10
,不要把来源IP和本机IP搞混了 前面的实验中之所以本机IP和来源IP一样,就是因为相当于自己访问自己,而后面用浏览器访问,相当于拿 Windows 机器访问 Linux 服务器1 2
$ sudo tail -1 /usr/local/apache2.4/logs/123.com-access_20240809.log 192.168.75.10 - - [09/Aug/2024:19:19:13 +0800] "GET /admin HTTP/1.1" 403 199 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
-
也可以单独针对某个文件来限制
1 2 3 4 5 6 7 8 9
$ sudo vi /usr/local/apache2.4/conf/extra/httpd-vhosts.conf <Directory /data/wwwroot/www.123.com> <Filesmatch "admin.php(.*)"> Order deny,allow Deny from all Allow from 127.0.0.1 </Filesmatch> </Directory>
2.7.2 限制恶意或者不正常的请求 1(禁止指定目录进行解析)
对于使用PHP语言编写的网站,有一些目录是由需求上传文件的,比如之前列举的防盗链故事,因为服务器可以上传图片,并且没有做防盗链,所以被人家当成了一个图片存储服务器,并且盗用带宽流量 如果网站代码有漏洞,让黑客上传了一个用PHP代码写的木马,由于网站可以执行 PHP 程序,最终会让黑客拿到服务器权限
为了避免上诉情况发生,我们需要把能上传文件的目录直接禁止解析 PHP 代码(不用担心会影响网站访问,若这种目录也需要解析 PHP,那说明程序员不合格)
|
|
2.7.2 限制恶意或者不正常的请求 1(禁止指定目录进行解析) 测试
认证过程如下
|
|
这说明 1.php
是不能正常解析的
2.7.3 限制恶意或者不正常的请求 2(对特定 user_agent 进行限制)
下面再来研究一下
user_agent
,前面讲过user_agent
为浏览器秃瓢,当用curl
访问时,user_agent
为 “curl/7.29.0”,用 FireFox 浏览器访问时,user_agent
为 “Mozilla/5.0(Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 FireFox/52.0” 我们在日常生活中经常针对user_agent
来限制一些访问,比如可以限制一些不太友好的搜索引擎 “爬虫”,你之所以能在百度看到自己的网站,就是因为百度会派一些 “蜘蛛爬虫” 抓取数据。类似于用户用浏览器访问网站,当 ”蜘蛛爬虫“ 太多或者访问太频繁,就会浪费服务器资源 另外,也可以限制恶意请求,这种恶意请求我们通常称作 cc 攻击。它的攻击原理很简单,就是用很多用户的电脑同时访问同一个站点,当访问量或者频率达到一定层次,会耗尽服务器资源,从而使之不能提供正常服务 这种 cc 攻击其实有很明显的规律,其中这些恶意请求的user_agent
相同或者相似,那我们就可以通过限制user_agent
发挥防攻击的作用
下面是针对 user_agent
来做访问控制
|
|
- 这个需求也用到了
rewrite
模块,%{HTTP_USER_AGENT}
为user_agent
的内置变量 在本例中,当user_agent
匹配curl
或者baidu.com
的时候,都会触发下面的规则 - 方括号中的
OR
标识 ”或者“,NC
表示 ”不区分大小写“,F
相当于 Forbidden
2.7.3 限制恶意或者不正常的请求 2(对特定 user_agent 进行限制)测试
下面进行认证
|
|
curl
的-A
选项指定user_agent
- 第一个请求:
user_agent
为 “curl/7.29.0” 匹配了第一个条件,所以会 403 - 第二个请求:
user_agent
为自定义的 “123123” 没有匹配任何条件,所以状态码为 200
- 第一个请求:
3. PHP 配置内容,功能
3.1 PHP 配置
虽然 PHP 是以 httpd 一个模块的形式存在的,但是 PHP 本身也有自己的配置文件 查看 PHP 配置文件所在位置的命令为
|
|
此处遇到了问题
1 2
$ sudo /usr/local/php/bin/php -i | grep -i "loaded configuration file" Loaded Configuration File => (none)
此时使用命令查看 php.ini 的位置,发现在
/usr/local/php/php.ini
里面
1 2
$ sudo find / -name php.ini /usr/local/php/php.ini
但是,我们在部署 PHP 的时候有这么一个设置
--with-config-file-path=/usr/local/php/etc
所以 PHP 默认在/usr/local/php/etc
这个位置查找配置文件
解决方法:
将
/usr/local/php/php.ini
复制到/usr/local/php/etc
里面
1
$ sudo cp /usr/local/php/php.ini /usr/local/php/etc
这时候我们再使用命令就出来了
1 2 3
$ sudo /usr/local/php/bin/php -i | grep -i "loaded configuration file" Loaded Configuration File => /usr/local/php/etc/php.ini PHP Warning: Unknown: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in Unknown on line 0
php.ini
为 PHP 的配置文件,可以看出其在 /usr/local/php/etc/php.ini
,第一行的 Warning
为警告信息,可以忽略,取消这个警告需要编辑 php.ini
,找到 date.timezone
设置如下
|
|
再次执行不再提示警告信息
|
|
3.1.1 PHP 的 disable_functions
PHP 有诸多内置的函数,有一些函数(比如 exec
)会直接调取 Linux 系统命令,如果开放,将会非常危险
因此,基于安全考虑,应该把一些存在安全风险的函数禁掉
|
|
-
对于这里列出来的这些函数,暂时可以不用细究,将来遇到问题要记得你曾经禁用了一些函数,这些被禁掉的函数是不能在 PHP 代码中调用的
-
更改完
php.ini
后,由于需要在 httpd 中调用 PHP,所以还需要重启 httpd 服务使其生效1
$ sudo /usr/local/apache2.4/bin/httpd -k restart
3.1.2 配置 error_log
PHP 的日志对于程序员来讲非常重要,他是排查问题的重要手段 设置 PHP 错误日志,有诸多步骤
|
|
log_errors
可以设置为on
或者off
,如果想让 PHP 记录错误日志,需要设置为on
error_log
设置错误日志路径error_reporting
设定错误日志的级别E_ALL
为所有类型的日志,不管是提醒还是警告都会记录 在开发环境下面设置为E_ALL
,可以方便程序员们排查问题,但也会造成日志记录很多无意义的内容&
表示并且,~
表示排除,所以两个组合在一起就是在E_ALL
的基础上,排除掉notice
相关的日志
display_error
设置为on
,则会把错误日志直接显示在浏览器里,这样对于用户访问来说体验不好,而且还会暴露网站的一些文件路径等重要信息,所以要设置为off
设置完 php.ini
,还需要做一些额外的操作
|
|
测试
|
|
-
其中出现了状态码 500,这说明我们访问的页面是存在错误的,此时需要查看 PHP 的错误日志来判断错误原因
1 2
$ cat /var/log/php/php_errors.log [12-Aug-2024 18:59:40 Asia/Shanghai] PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';' in /data/wwwroot/www.123.com/test.php on line 3
通过日志判断,
test.php
文件第三行少了分号
3.1.3 配置 open_basedir
一个服务器上跑很多网站,这是几乎所有小公司为节省成本采用的做法,但这样做也会有一些弊端:多个网站泡在同一个服务器上,如果其中一个网站被黑,很有可能连累到其他站点 我觉得这里用一句俗语形容比较合适 “一颗老鼠屎坏一锅汤” 为了避免这种尴尬的事情发生,我们应当做一些预防手段
还好 PHP 里有一个概念叫做
open_basedir
,它的作用是将网站限定在指定目录里,就算该站点被黑了,黑客只能在该目录下面所有作为,而不能左右其他目录 如果你的服务器上只有一个站点,那可以直接在php.ini
中设置open_basedir
参数 但如果服务器上跑的站点比较多,那在php.ini
中设置就不合适了,因为在php.ini
中只能定义一次,也就是说所有站点都一起定义限定的目录,那这样似乎起不到隔离多个站点的目的
先来看如何在 php.ini
中设置 open_basedir
|
|
open_basedir
可以是多个目录,用 :
分割,先来验证 open_basedir
的作用吧
因为已经限制 PHP 只能在 /tmp
和 /data/wwwroot/www.123.com
两个目录下活动,所以这次拿 anitsuri.com
来掩饰:
|
|
-
发现
anitsuri.com/1.php
不能访问,状态码为 500,所以查看一下错误日志,得到信息如下1 2 3 4 5
$ cat /var/log/php/php_errors.log [12-Aug-2024 18:59:40 Asia/Shanghai] PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';' in /data/wwwroot/www.123.com/test.php on line 3 [12-Aug-2024 19:35:29 Asia/Shanghai] PHP Warning: Unknown: open_basedir restriction in effect. File(/data/wwwroot/anitsuri.com/1.php) is not within the allowed path(s): (/tmp:/data/wwwroot/www.123.com) in Unknown on line 0 [12-Aug-2024 19:35:29 Asia/Shanghai] PHP Warning: Unknown: failed to open stream: Operation not permitted in Unknown on line 0 [12-Aug-2024 19:35:29 Asia/Shanghai] PHP Fatal error: Unknown: Failed opening required '/data/wwwroot/anitsuri.com/1.php' (include_path='.:/usr/local/php/lib/php') in Unknown on line 0
下面说如何给单个虚拟主机设置 open_basedir
对于 php.ini
里面的配置,在 httpd.conf
中也是可以设置的
|
|
起作用的就是这句 php_admin_value
,它可以定义 php.ini
里面的参数
除此之外,像 error_log
之类的也可以定义
这样就可以实现一个虚拟主机定义一个 open_basedir
4. PHP 动态拓展模块安装
编译 httpd 是,有涉及动态和静态模块,其实 PHP 也一样有这样的说法 在这篇文章中讲述的 PHP 安装时,所有的木块全部都为静态,并没有任何的模块 所谓动态,就是一个独立存在的
.so
文件,在 httpd 中 PHP 就是以动态模块的形式被加载的 PHP 一旦编译完成后,要想再增加一个功能模块的话,要么重新编译 PHP,要么直接编译一个拓展模块(生成一个.so
文件),然后在php.ini
中配置一下,就可以加载使用了
首先,应该会查看 PHP 都加载了哪些功能模块
|
|
下面说一个安装 PHP 的 redis
拓展模块的方法
|
|
这里遇到问题:
1 2 3
$ sudo unzip !$ unzip phpredis-develop.zip -bash: unzip: 未找到命令
解决方法:
sudo yum install -y unzip
,安装完后再运行一遍命令即可
1 2 3 4 5 6 7 8 9
$ sudo make ... In file included from /usr/local/src/phpredis-develop/php_redis.h:20:0, from /usr/local/src/phpredis-develop/redis.c:25: /usr/local/src/phpredis-develop/common.h:13:28: 致命错误:zend_smart_str.h:没有那个文件或目录 #include <zend_smart_str.h> ^ 编译中断。 make: *** [redis.lo] 错误 1
这里是因为一开始在
https://codeload.github.com/phpredis/phpredis/zip/develop
下载的为最新版,已不支持 PHP,现已将网址改成https://github.com/phpredis/phpredis/archive/refs/tags/2.2.8.zip
|
|
步骤虽然多,但并不复杂
以后遇到增加模块的需求,都可以按照此方案安装
另外,要想在 PHP 网站使用 redis
模块,还需要重启一下 httpd 服务
|
|