一、基础知识
LAMP 架构是一种常用的Web应用程序开发和部署架构,它由四个核心组件组成,分别是:
Linux操作系统(L):作为 LAMP 架构的基础,Linux 提供了稳定、安全且可靠的操作系统环境。它与其他三个组件(Apache、MySQL、PHP)拥有高兼容度,共同构成了一个强大的 Web 应用程序平台。
Apache Web服务(A):是一个流行的开源 Web 服务器软件,用于处理 HTTP 请求并向客户端提供网页内容。它能够处理静态 HTML、图像等文件,同时也支持调用动态脚本(如 PHP)来生成动态内容。Apache 还提供了灵活的配置选项,如设置虚拟主机、URL 重定向、访问控制等,方便对网站进行管理和扩展。
MySQL数据库(M):是一个广泛使用的关系型数据库管理系统(RDBMS),用于创建、存储和管理结构化数据。它支持 SQL 语言,可以进行高效的数据查询、插入、更新和删除操作。MySQL 还提供了客户端工具和 API,使应用程序可以通过与数据库建立连接并执行 SQL 语句来实现与数据库的交互。此外,MySQL 还支持数据的备份和恢复、用户权限管理以及事务处理,确保数据的安全性和一致性。
PHP编程语言(P) :是一种常用的服务器端脚本语言,用于编写动态网页和 Web 应用程序。它能够与 HTML 混合使用,并且可以嵌入到Web服务器中进行解析和执行。PHP 提供了丰富的函数和库,可用于处理表单数据、文件操作、数据库查询等多种任务。PHP 还具备良好的数据库支持,可以与 MySQL 等数据库系统进行连接,并执行数据库查询、插入、更新和删除操作,实现动态网页的数据交互。
LAMP 是中小型动态网站的常见组合,虽然这些开放源代码程序本身并不是专门设计成同另几个程序一起工作的,但由于它们各自的特点和普遍性,使得这个组合在搭建动态网站这一领域开始流行起来。
二、工作流程
1、客户端发起请求
客户端发送 HTTP 请求到 web 服务器(运行 LAMP 架构)的 80 端口;
2、Linux 操作系统接受请求
服务器的 Linux 操作系统作为底层平台,负责网络协议(如 TCP/IP)的处理,将用户的 HTTP 请求转发给运行在系统上的 Apache Web 服务器(默认监听 80 端口,HTTPS 为 443 端口)。
3、Apache Web 服务器处理请求
Apache 作为 web 服务器,接收和处理 HTTP 请求,首先分析请求的资源类型:
静态资源(如HTML、CSS、JavaScript文件等):Apache 会查找该资源并直接返回给客户端;
动态资源(如PHP文件):Apache 加载并调用与 PHP 解析相关的模块(如 libphpX.so)来解析 PHP 代码;
4、PHP 解释器处理动态逻辑
Apache 将 .php 脚本文件的路径和请求参数传递给 PHP 解释器,PHP 开始执行脚本中的逻辑:
处理用户输入数据;
若需要操作数据(如查询、插入、更新),PHP 通过数据库扩展(如MySQLi、PDO)与 MySQL 数据库建立连接,发送 SQL 命令;
MySQL 执行 SQL 命令,处理数据(如查询表中记录),并将结果返回给 PHP;
5、PHP 生成动态响应内容
PHP 接收 MySQL 返回的数据后,结合脚本逻辑(如条件判断、循环处理)生成动态 HTML 内容(也可能是 JSON、XML 等格式),并将结果返回给 Apache;
6、Apache 返回响应给用户
Apache 接收 PHP 生成的动态内容,将其封装为标准 HTTP 响应(包含响应头、响应体),通过 Linux 操作系统的网络协议栈返回给客户端。
三、部署实践
1、Ubuntu24 部署 Apache
安装 apache2 软件包
apt install apache2 -y
查看服务状态
systemctl status apache2
查看监听端口(ubuntu 系统中 apache 的用户是 apache2)
查看相关进程(每个进程有26个线程:1个监听线程,25个工作线程)
查看管理工具
2、Rocky9 部署 Apache
安装 httpd 软件包
yum install httpd -y
启动服务
systemctl start httpd && systemctl enable httpd
查看服务状态
查看监听端口(Rocky9 系统中 apache 的用户是 httpd)
查看相关进程(每个进程有 57 个线程)
查看管理工具
3、配置解读
Apache2 的配置主要分为三部份,分别是全局配置,虚拟主机配置,模块配置,这些配置项分散在不同的目录和文件中,在主配置文件中以文件包含的形式引用它们。配置文件中每一行包含一个配置指令,并指定值,配置指令不区分大小写,但值区分大小写。以 # 开头的行是注释行,注释不能出现在指令的后边,空白行和指令前的空白字符将被忽略,因此可以采用缩进以保持配置层次的清晰。
Ubuntu24 系统相关的配置
目录结构
apache2.conf #主配置文件
conf-available/ #子配置文件目录
conf-enabled/ #生效的子配置文件,链接到 confavailable中
envvars #全局环境变量配置文件
magic #配合 mod_mime_magic 模块判断 MIME 类型的配置文件
mods-available/ #可用的模块配置文件
mods-enabled/ #生效的模块配置文件,链接到 modsavailable 中
ports.conf #默认端口配置文件
sites-available/ #可用的虚拟主机配置文件
sites-enabled/ #生效的虚似主机配置文件,链接到 sitesavailable 中
全局配置
charset.conf #默认编码,全都注释
localized-error-pages.conf #自定义错误页面,全注释
other-vhosts-access-log.conf #未定义的虚拟主机访问日志
security.conf #安全设置配置文件
serve-cgi-bin.conf #CGI 配置
Rocky9 系统相关的配置
目录结构
autoindex.conf #配置Apache服务器的自动索引功能。通常包含Options +Indexes指令来启用此功能
README #包含关于目录内容或如何使用目录中文件的说明。
userdir.conf #用于配置Apache的UserDir功能,该功能允许每个用户在自己的家目录下拥有一个可以通过Web访问的公共HTML目录。
welcome.conf #用于配置Apache的欢迎页面。当用户访问一个未配置默认索引文件的目录时,如果启用了欢迎页面功能,Apache将显示一个默认的欢迎页面,而不是目录索引。
00-base.conf #包含Apache HTTP服务器的基本模块配置
00-brotli.conf #配置Brotli压缩模块,用于压缩发送给客户端的内容
00-dav.conf #配置WebDAV(基于Web的分布式创作和版本控制)模块
00-lua.conf #配置Lua脚本处理模块,允许在Apache中嵌入Lua脚本
00-mpm.conf #配置多处理模块(MPM),决定Apache如何处理并发连接
00-optional.conf #包含可选的、非核心的模块配置
00-proxy.conf #配置代理模块,允许Apache作为反向代理或负载均衡器
00-systemd.conf #配置与systemd相关的设置,以便更好地与systemd集成
01-cgi.conf #配置CGI(Common Gateway Interface)模块,允许执行外部脚本
10-h2.conf #配置HTTP/2协议支持模块
10-proxy_h2.conf #配置HTTP/2代理模块,用于处理通过HTTP/2协议代理的请求
README #包含关于此目录中配置文件的说明和如何使用它们的指导
这些文件通常包含了 LoadModule 指令,用于加载 Apache 的各种模块。每个文件都按照特定的顺序命名(如00-、01-、10-等),这决定了它们在 Apache 配置过程中的加载顺序。README 文件则提供了有关这些配置文件的额外信息和指导。
4、配置检测
Ubuntu24 系统配置检测
默认情况下,/etc/apache2/apache2.conf 文件中没有改属性配置,如果不在主配置文件中增加该属性,则会一直发生信息提示。
修改配置
sed -i '/#ServerRoot/a ServerName www.example.com' /etc/apache2/apache2.conf
再测检测
Rocky9 系统配置检测
原因同上
修改配置
sed -i "s@#ServerName@ServerName@" /etc/httpd/conf/httpd.conf
再次检测
查看 web 页面
5、安装 php 软件(模块形式)
apache2 默认是 event 模型
没有 php 模块
安装 php 环境
检查效果(安装完 php 后工作模型变为 prefork模型了)
对应的 php 模块已经存在(php 必须在 apache2 的 prefork 模型下工作,否则 apache2 将无法启动)
6、安装 php 软件(fpm 形式)
安装 php-fpm 软件包
查看配置目录(增加了 fpm 目录)
查看配置文件(监听方式可以是 socket 或 IP:PORT,每个进程池都需要设置)
查看服务状态
拥有独立的 php-fpm 进程
7、Apache 应用 php(模块形式)
定制配置文件
定制首页
重启 apache 服务
查看 http://10.0.0.112/index.php 页面
8、Apache 应用 php(fpm 形式)
先删除 php 模块化配置
设置 php-fpm 代理(需要额外的 fcgi 的加载)
cd /etc/apache2/mods-enabled/
ln -sv ../mods-available/proxy_fcgi.load ./proxy_fcgi.load
ln -sv ../mods-available/proxy.conf ./proxy.conf
ln -sv ../mods-available/proxy.load ./proxy.load
定制 php 功能访问
配置代理
cat > proxy.conf
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
eof
重启服务
查看 apache 加载的模块
查看 http://10.0.0.112/index.php 页面
9、mysql 数据库安装部署
安装 mysql-server 软件包
查看进程及监听端口(默认监听本机 3306 端口)
默认情况下,mysql可以使用root用户登录,密码为空
修改 root 用户密码(为了方便实践密码设置为 root,生产上请使用强密码)
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';
退出后使用密码验证登录
10、模块环境安装
安装 php 和 mysql 的相关模块
apt install php-fpm php-cli php-mysqlnd php-json php-gd php-xml php-mbstring php-zip
检测环境
11、php 对接 mysql
准备数据库环境,生成 mysql_test.sql 并编辑内容
-- 创建数据库
DROP DATABASE IF EXISTS test_db;
CREATE DATABASE IF NOT EXISTS test_db;
-- 使用数据库
USE test_db;
-- 创建表:指定存储引擎(InnoDB 支持事务、外键,适合业务表)
-- 字段注释按需补充,增强可读性
CREATE TABLE IF NOT EXISTS users (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '用户唯一ID,自增',
username VARCHAR(50) NOT NULL COMMENT '用户名,最长50字符',
email VARCHAR(100) NOT NULL UNIQUE COMMENT '用户邮箱,唯一约束',
password VARCHAR(255) NOT NULL COMMENT '密码,建议哈希存储',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间'
);
-- 插入数据:显式指定字段(单行格式 + 字符串转义)
INSERT INTO users (username, email, password) VALUES ('user1','user1@example.com', 'pass1');
INSERT INTO users (username, email, password) VALUES ('user2','user2@example.com', 'pass2');
INSERT INTO users (username, email, password) VALUES ('user3','user3@example.com', 'pass3');
运行该文件
查看结果
12、定制测试文件1
生成文件 /var/www/html/test_mysql1.php 并编辑内容
connect_error) {
die("连接失败: " . $mysqli->connect_error);
}
echo "恭喜!数据库连接成功!";
// 关闭连接
$mysqli->close();
?>
测试效果
13、定制测试文件2
生成文件 /var/www/html/test_mysql2.php 并编辑内容
";
// 执行查询
$result = mysqli_query($conn, "SELECT * FROM users");
// 创建表格
echo "";
echo "";
echo "ID";
echo "用户名";
echo "邮箱";
echo "";
// 输出数据行
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
echo "";
echo "" . $row['id'] . "";
echo "" . $row['username'] . "";
echo "" . $row['email'] . "";
echo "";
}
} else {
echo "暂无数据";
}
echo "";
mysqli_close($conn);
?>
测试效果
14、定制测试文件3
生成文件 /var/www/html/test_mysql3.php 并编辑内容
'localhost:3306',
'db' => 'test_db',
'db_user' => 'root',
'db_pwd' => 'root',
);
$mysqli = @new mysqli($mysql_conf['host'], $mysql_conf['db_user'],
$mysql_conf['db_pwd']);
if ($mysqli->connect_errno) {
die("could not connect to the database:\n" . $mysqli->connect_error);//诊断连接错误
}
$mysqli->query("set names 'utf8';");//编码转化
$select_db = $mysqli->select_db($mysql_conf['db']);
if (!$select_db) {
die("could not connect to the db:\n" . $mysqli->error);
}$sql = "select username from users where username = 'user1';";
$res = $mysqli->query($sql);
if (!$res) {
die("sql error:\n" . $mysqli->error);
}
while ($row = $res->fetch_assoc()) {
var_dump($row);
}
$res->free();
$mysqli->close();
?>
测试效果
15、定制测试文件4
生成文件 /var/www/html/test_mysql4.php 并编辑内容
connect_error) {
die("数据库连接失败: " . $mysqli->connect_error);
}
echo "数据库连接成功!";
// 设置字符集
$mysqli->set_charset("utf8mb4");
// 示例 1:查询用户表数据
$result = $mysqli->query("SELECT id, username, email FROM users LIMIT 5");
echo "用户列表(前5条)";
echo "";
echo "ID用户名邮箱";
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "";
echo "{$row['id']}";
echo "{$row['username']}";
echo "{$row['email']}";
echo "";
}
} else {
echo "暂无数据";
}
echo "";
// 示例 2:执行插入操作(预处理语句)
$username = 'test_user' . rand(1000, 9999);
$email = 'test' . rand(1000, 9999) . '@example.com';
$password = password_hash('test123', PASSWORD_DEFAULT);
$stmt = $mysqli->prepare("INSERT INTO users (username, email, password) VALUES
(?, ?, ?)");
$stmt->bind_param("sss", $username, $email, $password);
if ($stmt->execute()) {
echo "新用户插入成功!ID: " . $stmt->insert_id . "";
} else {
echo "插入失败: " . $stmt->error . "";
}
// 释放资源
$stmt->close();
$result->close();
$mysqli->close();
?>
测试效果
16、定制测试文件5
生成文件 /var/www/html/test_mysql5.php 并编辑内容
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 输出连接成功信息
echo "数据库连接成功!";
// 执行简单查询
$stmt = $pdo->query("SELECT VERSION()");
$version = $stmt->fetchColumn();
echo "MySQL 版本: " . $version . "";
// 创建测试表(如果不存在)
$pdo->exec("CREATE TABLE IF NOT EXISTS test_table (
id INT PRIMARY KEY AUTO_INCREMENT,
message VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
echo "测试表创建成功!";
// 插入测试数据
$pdo->exec("INSERT INTO test_table (message) VALUES ('测试数据')");
echo "数据插入成功!";
// 查询数据
$stmt = $pdo->query("SELECT * FROM test_table");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "查询结果:";
foreach ($rows as $row) {
echo "ID: " . $row['id'] . ", 消息: " . $row['message'] . ", 时间: " .
$row['created_at'] . "";
}
} catch(PDOException $e) {
// 输出错误信息
die("数据库连接失败: " . $e->getMessage());
}
// 关闭连接(可选,脚本结束时会自动关闭)
$pdo = null;
?>
测试效果