Home 攻略指南 Ubuntu下LAMP环境搭建与优化指南

Ubuntu下LAMP环境搭建与优化指南

1. 为什么选择LAMP环境?

LAMP(Linux + Apache + MySQL + PHP)这个组合已经统治Web开发领域超过20年。作为一个老PHP开发者,我见证了这个技术栈从最初的简单组合,逐步演变成如今高度成熟的开发环境。即使在云原生和容器化技术盛行的今天,LAMP仍然是大多数PHP项目的首选开发环境。

在Ubuntu上搭建LAMP有几个明显优势:

软件源维护良好,版本更新及时

系统稳定性高,长期运行不易崩溃

社区支持完善,遇到问题容易找到解决方案

与生产环境高度一致,减少部署时的环境差异

注意:虽然现在有Docker等容器化方案,但直接在本机搭建LAMP环境仍然是理解Web开发底层原理的最佳方式。

2. 环境准备与基础配置

2.1 系统要求与初始设置

我推荐使用Ubuntu 22.04 LTS版本,这是一个长期支持版本,会获得5年的安全更新。以下是推荐的硬件配置:

CPU:至少2核

内存:4GB以上

磁盘空间:20GB可用空间

在开始安装前,有几个基础操作需要完成:

bash复制# 更新软件包列表

sudo apt update

# 升级已安装的软件包

sudo apt upgrade -y

# 安装常用工具

sudo apt install -y curl wget git unzip

2.2 防火墙配置

Ubuntu默认使用ufw防火墙,我们需要开放必要的端口:

bash复制sudo ufw allow ssh

sudo ufw allow http

sudo ufw allow https

sudo ufw enable

这个配置会允许SSH(22端口)、HTTP(80端口)和HTTPS(443端口)的访问,同时启用防火墙。

3. Apache安装与优化

3.1 Apache2安装

Apache是LAMP中的"A",也是整个环境的Web服务器部分:

bash复制sudo apt install -y apache2

安装完成后,可以通过以下命令检查状态:

bash复制sudo systemctl status apache2

正常情况下,你应该看到"active (running)"的状态。此时在浏览器访问服务器IP,应该能看到Apache的默认欢迎页面。

3.2 基础配置调整

Apache的主要配置文件位于/etc/apache2目录下。有几个关键配置需要调整:

修改主配置文件:

bash复制sudo nano /etc/apache2/apache2.conf

找到并修改以下参数:

code复制KeepAlive On

MaxKeepAliveRequests 100

KeepAliveTimeout 5

启用rewrite模块(后续开发中常用):

bash复制sudo a2enmod rewrite

调整MPM(多处理模块)配置。对于内存大于2GB的服务器,建议使用event模式:

bash复制sudo a2enmod mpm_event

sudo systemctl restart apache2

3.3 虚拟主机配置

在实际开发中,我们通常需要配置多个网站。这里演示如何配置一个虚拟主机:

bash复制sudo nano /etc/apache2/sites-available/example.com.conf

添加以下内容(根据实际情况修改):

code复制

ServerAdmin webmaster@example.com

ServerName example.com

ServerAlias www.example.com

DocumentRoot /var/www/example.com/public_html

ErrorLog ${APACHE_LOG_DIR}/error.log

CustomLog ${APACHE_LOG_DIR}/access.log combined

然后启用这个站点并重载配置:

bash复制sudo a2ensite example.com.conf

sudo systemctl reload apache2

4. MySQL/MariaDB数据库安装

4.1 安装MariaDB

在Ubuntu中,MariaDB是MySQL的替代品,完全兼容MySQL:

bash复制sudo apt install -y mariadb-server mariadb-client

安装完成后运行安全脚本:

bash复制sudo mysql_secure_installation

这个脚本会引导你完成以下设置:

设置root密码

移除匿名用户

禁止root远程登录

移除测试数据库

重新加载权限表

4.2 基础配置优化

编辑MySQL配置文件:

bash复制sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

根据服务器配置调整以下参数(以下配置适用于4GB内存的服务器):

code复制[mysqld]

innodb_buffer_pool_size = 1G

innodb_log_file_size = 256M

innodb_flush_log_at_trx_commit = 2

innodb_flush_method = O_DIRECT

query_cache_size = 64M

query_cache_limit = 4M

max_connections = 100

修改配置后需要重启服务:

bash复制sudo systemctl restart mariadb

4.3 创建数据库用户

在生产环境中,不建议直接使用root用户。创建一个专用用户:

bash复制sudo mysql -u root -p

在MySQL提示符下执行:

sql复制CREATE DATABASE example_db;

CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'strong_password';

GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost';

FLUSH PRIVILEGES;

EXIT;

5. PHP安装与配置

5.1 安装PHP

Ubuntu 22.04默认仓库提供了PHP 8.1版本:

bash复制sudo apt install -y php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip

这个命令安装了PHP核心和常用的扩展:

php-mysql:MySQL数据库连接

php-curl:HTTP请求处理

php-gd:图像处理

php-mbstring:多字节字符串处理

php-xml:XML处理

php-zip:压缩文件处理

5.2 PHP配置优化

主要的PHP配置文件位于/etc/php/8.1目录下。我们需要修改两个文件:

修改Apache使用的PHP配置:

bash复制sudo nano /etc/php/8.1/apache2/php.ini

调整以下参数:

code复制memory_limit = 256M

upload_max_filesize = 64M

post_max_size = 64M

max_execution_time = 120

date.timezone = Asia/Shanghai

修改CLI使用的PHP配置(用于命令行脚本):

bash复制sudo nano /etc/php/8.1/cli/php.ini

同样调整上述参数,然后重启Apache:

bash复制sudo systemctl restart apache2

5.3 安装Composer

Composer是PHP的依赖管理工具,现代PHP开发几乎必不可少:

bash复制curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

验证安装:

bash复制composer --version

6. 环境验证与测试

6.1 创建测试文件

在网站根目录创建一个PHP测试文件:

bash复制sudo nano /var/www/html/info.php

内容如下:

php复制

phpinfo();

?>

然后在浏览器访问http://your_server_ip/info.php,你应该能看到PHP的信息页面,其中包含了所有已安装的模块和配置信息。

6.2 数据库连接测试

创建另一个测试文件测试数据库连接:

bash复制sudo nano /var/www/html/dbtest.php

内容如下(替换为你的数据库凭据):

php复制

$host = 'localhost';

$dbname = 'example_db';

$user = 'example_user';

$pass = 'strong_password';

try {

$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

echo "数据库连接成功!";

} catch (PDOException $e) {

echo "数据库连接失败: " . $e->getMessage();

}

?>

访问这个文件应该能看到"数据库连接成功!"的消息。

7. 性能优化与安全加固

7.1 Apache性能优化

启用HTTP/2支持:

bash复制sudo a2enmod http2

启用压缩:

bash复制sudo a2enmod deflate

然后在/etc/apache2/mods-enabled/deflate.conf中添加:

code复制AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript

启用缓存:

bash复制sudo a2enmod expires

在虚拟主机配置中添加:

code复制

ExpiresActive On

ExpiresByType image/jpg "access plus 1 year"

ExpiresByType image/jpeg "access plus 1 year"

ExpiresByType image/gif "access plus 1 year"

ExpiresByType image/png "access plus 1 year"

ExpiresByType text/css "access plus 1 month"

ExpiresByType application/pdf "access plus 1 month"

ExpiresByType text/javascript "access plus 1 month"

ExpiresByType application/javascript "access plus 1 month"

ExpiresByType application/x-javascript "access plus 1 month"

ExpiresDefault "access plus 2 days"

7.2 PHP安全配置

禁用危险函数:

bash复制sudo nano /etc/php/8.1/apache2/php.ini

找到disable_functions并添加:

code复制disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

限制文件上传:

code复制file_uploads = On

upload_max_filesize = 10M

max_file_uploads = 5

隐藏PHP版本信息:

code复制expose_php = Off

7.3 MySQL安全加固

定期备份数据库:

bash复制sudo mysqldump -u root -p --all-databases > full_backup.sql

设置定期自动备份:

bash复制sudo crontab -e

添加以下内容(每天凌晨3点备份):

code复制0 3 * * * /usr/bin/mysqldump -u root -p'your_password' --all-databases > /var/backups/mysql/all-databases-$(date +\%Y\%m\%d).sql

8. 常见问题与解决方案

8.1 Apache无法启动

可能原因:

端口冲突(如其他Web服务器占用了80端口)

配置文件语法错误

解决方案:

bash复制# 检查端口占用

sudo netstat -tulnp | grep :80

# 检查Apache配置语法

sudo apache2ctl configtest

8.2 PHP文件被下载而非执行

这通常是因为Apache没有正确配置PHP处理:

解决方案:

确保已安装libapache2-mod-php

检查/etc/apache2/mods-enabled/目录下是否有php8.1.conf和php8.1.load

确保虚拟主机配置中有:

code复制

SetHandler application/x-httpd-php

8.3 MySQL连接问题

常见错误:

"Access denied for user"

"Can't connect to local MySQL server"

解决方案:

检查用户权限:

sql复制SHOW GRANTS FOR 'username'@'localhost';

检查MySQL服务状态:

bash复制sudo systemctl status mariadb

检查MySQL错误日志:

bash复制sudo tail -f /var/log/mysql/error.log

9. 进阶配置与扩展

9.1 安装PHP扩展

根据项目需求,你可能需要安装额外的PHP扩展。例如,安装Redis扩展:

bash复制sudo apt install -y php-redis

sudo systemctl restart apache2

其他常用扩展:

php-bcmath:高精度数学运算

php-intl:国际化支持

php-soap:SOAP服务支持

php-sqlite3:SQLite数据库支持

9.2 使用OPcache加速PHP

OPcache可以显著提高PHP性能:

bash复制sudo apt install -y php-opcache

然后编辑配置文件:

bash复制sudo nano /etc/php/8.1/apache2/conf.d/10-opcache.ini

推荐配置:

code复制opcache.enable=1

opcache.memory_consumption=128

opcache.interned_strings_buffer=8

opcache.max_accelerated_files=4000

opcache.revalidate_freq=60

opcache.fast_shutdown=1

9.3 配置PHP-FPM

对于高流量网站,建议使用PHP-FPM替代mod_php:

bash复制sudo apt install -y php-fpm

sudo a2dismod php8.1

sudo a2enconf php8.1-fpm

sudo a2enmod proxy_fcgi setenvif

然后在虚拟主机配置中添加:

code复制

SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost/"

10. 开发环境与生产环境差异

10.1 开发环境配置

在开发环境中,我们通常需要:

开启错误显示:

ini复制display_errors = On

display_startup_errors = On

error_reporting = E_ALL

禁用OPcache或设置短时间缓存:

ini复制opcache.revalidate_freq=0

安装开发工具:

bash复制sudo apt install -y php-xdebug

10.2 生产环境配置

生产环境需要:

关闭错误显示:

ini复制display_errors = Off

display_startup_errors = Off

log_errors = On

error_log = /var/log/php_errors.log

启用所有缓存和优化

设置严格的权限:

bash复制sudo chown -R www-data:www-data /var/www/html

sudo find /var/www/html -type d -exec chmod 755 {} \;

sudo find /var/www/html -type f -exec chmod 644 {} \;

11. 备份与恢复策略

11.1 完整环境备份

备份网站文件:

bash复制sudo tar -czvf /backup/website_$(date +\%Y\%m\%d).tar.gz /var/www/html

备份数据库:

bash复制sudo mysqldump -u root -p --all-databases > /backup/mysql_$(date +\%Y\%m\%d).sql

备份配置文件:

bash复制sudo tar -czvf /backup/configs_$(date +\%Y\%m\%d).tar.gz /etc/apache2 /etc/php /etc/mysql

11.2 自动化备份脚本

创建一个备份脚本/usr/local/bin/backup_lamp.sh:

bash复制#!/bin/bash

DATE=$(date +\%Y\%m\%d)

BACKUP_DIR="/backup"

# 创建备份目录

mkdir -p $BACKUP_DIR/$DATE

# 备份网站

tar -czvf $BACKUP_DIR/$DATE/website.tar.gz /var/www/html

# 备份数据库

mysqldump -u root -p'your_password' --all-databases > $BACKUP_DIR/$DATE/mysql.sql

# 备份配置

tar -czvf $BACKUP_DIR/$DATE/configs.tar.gz /etc/apache2 /etc/php /etc/mysql

# 删除7天前的备份

find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;

然后添加到cron:

bash复制sudo crontab -e

添加:

code复制0 2 * * * /usr/local/bin/backup_lamp.sh

12. 监控与日志分析

12.1 基础监控设置

安装监控工具:

bash复制sudo apt install -y htop sysstat

配置日志轮转:

编辑/etc/logrotate.d/apache2:

code复制/var/log/apache2/*.log {

daily

missingok

rotate 14

compress

delaycompress

notifempty

create 640 root adm

sharedscripts

postrotate

/usr/lib/apache2/apache2ctl graceful

endscript

}

12.2 分析访问日志

使用goaccess工具分析Apache访问日志:

bash复制sudo apt install -y goaccess

goaccess /var/log/apache2/access.log --log-format=COMBINED

12.3 监控MySQL性能

使用mysqladmin查看状态:

bash复制mysqladmin -u root -p status

或者进入MySQL查看:

sql复制SHOW STATUS;

SHOW PROCESSLIST;

13. 从LAMP到LEMP

如果你考虑使用Nginx替代Apache,可以转换为LEMP环境:

13.1 安装Nginx

bash复制sudo apt install -y nginx

sudo systemctl stop apache2

sudo systemctl start nginx

13.2 配置PHP-FPM

确保已安装php-fpm,然后配置Nginx:

bash复制sudo nano /etc/nginx/sites-available/example.com

添加类似配置:

code复制server {

listen 80;

server_name example.com www.example.com;

root /var/www/example.com/public_html;

index index.php index.html index.htm;

location / {

try_files $uri $uri/ /index.php?$query_string;

}

location ~ \.php$ {

include snippets/fastcgi-php.conf;

fastcgi_pass unix:/run/php/php8.1-fpm.sock;

}

location ~ /\.ht {

deny all;

}

}

14. 容器化方案对比

虽然本文主要介绍传统安装方式,但了解容器化方案也很重要:

14.1 Docker方案优势

环境隔离

快速部署

版本控制

易于迁移

14.2 传统LAMP优势

性能更好

调试更方便

学习成本低

更接近生产环境

在实际开发中,我通常建议新手先从传统LAMP开始,理解底层原理后再学习容器化技术。

15. 个人经验分享

在多年的LAMP环境搭建中,我总结了一些实用技巧:

保持系统更新,但不要盲目升级主要版本(如PHP 8.1 → 8.2)

每个项目使用单独的虚拟主机配置和数据库用户

定期检查日志文件,可以设置日志监控告警

使用配置管理工具(如Ansible)来管理服务器配置

开发环境和生产环境的配置差异要文档化

一个特别有用的技巧是创建配置检查脚本,定期验证关键配置是否被意外修改。例如:

bash复制#!/bin/bash

# 检查关键配置文件MD5

CONFIG_FILES=("/etc/apache2/apache2.conf" "/etc/php/8.1/apache2/php.ini" "/etc/mysql/mariadb.conf.d/50-server.cnf")

KNOWN_MD5=("known_md5_1" "known_md5_2" "known_md5_3")

for i in "${!CONFIG_FILES[@]}"; do

current_md5=$(md5sum "${CONFIG_FILES[$i]}" | awk '{print $1}')

if [ "$current_md5" != "${KNOWN_MD5[$i]}" ]; then

echo "警告: ${CONFIG_FILES[$i]} 已被修改!"

fi

done