一、LNMP架构概述
1. 什么是LNMP
LNMP 是一种Web服务架构组合,由以下组件构成:
text
L - Linux 操作系统
N - Nginx Web服务器/反向代理
M - MySQL 数据库系统
P - PHP 动态内容处理语言
2. LNMP架构工作原理
text
客户端请求
↓
┌─────────────────────────────────────┐
│ Nginx (端口80/443) │
│ └── 静态请求(html, css, js, 图片) │
│ └── 动态请求转发 │
└─────────────────────────────────────┘
↓
┌───────────────────┐
│ PHP-FPM │
│ (端口9000) │
└───────────────────┘
↓
┌───────────────────┐
│ MySQL │
│ (端口3306) │
└───────────────────┘
请求处理流程:
text
1. 客户端发起HTTP请求
2. Nginx接收请求,判断请求类型
├── 静态文件 → 直接返回
└── 动态请求 → 转发给PHP-FPM
3. PHP-FPM执行PHP脚本
├── 如需数据库操作 → 连接MySQL
└── 返回处理结果给Nginx
4. Nginx将结果返回给客户端
3. LNMP与LAMP对比
| 特性 | LNMP | LAMP |
|---|---|---|
| Web服务器 | Nginx | Apache |
| 处理方式 | 异步非阻塞 | 同步阻塞 |
| 静态文件性能 | 高 | 中等 |
| 动态内容处理 | 通过PHP-FPM | 模块化处理 |
| 并发连接 | 高并发 | 相对较低 |
| 内存占用 | 低 | 高 |
| 配置复杂度 | 中等 | 简单 |
| 适用场景 | 高并发、静态资源多 | 兼容性要求高 |
二、环境准备
1. 系统要求
bash
# 操作系统
CentOS 7/8/9
Ubuntu 18.04/20.04/22.04
Debian 10/11
# 硬件要求
CPU: 1核以上
内存: 1GB以上
磁盘: 10GB以上
# 检查系统版本
cat /etc/os-release
uname -a
# 检查系统架构
arch
# x86_64 或 aarch64
2. 关闭防火墙和SELinux(CentOS)
bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 或者开放必要端口
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=9000/tcp # PHP-FPM
firewall-cmd --permanent --add-port=3306/tcp # MySQL
firewall-cmd --reload
# 关闭SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
getenforce
3. 更新系统
bash
# CentOS/RHEL
yum update -y
# Ubuntu/Debian
apt update && apt upgrade -y
# 安装常用工具
# CentOS
yum install -y wget curl vim net-tools telnet lsof
# Ubuntu/Debian
apt install -y wget curl vim net-tools telnet lsof
三、Nginx安装与配置
1. 安装Nginx
bash
# CentOS/RHEL 7/8/9
# 添加EPEL和Nginx仓库
yum install -y epel-release
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
# 安装Nginx
yum install -y nginx
# Ubuntu/Debian
apt install -y nginx
# 或者编译安装(自定义需求)
# 安装编译依赖
yum groupinstall -y "Development Tools"
yum install -y pcre-devel zlib-devel openssl-devel
# 下载源码
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
# 编译配置
./configure \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-stream \
--with-stream_ssl_module
# 编译安装
make -j$(nproc)
make install
# 创建软链接
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
2. 启动Nginx
bash
# 启动Nginx
systemctl start nginx
# 设置开机自启
systemctl enable nginx
# 查看状态
systemctl status nginx
# 如果是编译安装,创建systemd服务
cat > /etc/systemd/system/nginx.service << 'EOF'
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start nginx
3. 验证Nginx安装
bash
# 检查版本
nginx -v
# 检查配置文件语法
nginx -t
# 查看端口监听
netstat -tlnp | grep 80
ss -tlnp | grep 80
# 测试访问
curl -I http://localhost
# 或通过浏览器访问 http://服务器IP
4. Nginx基础配置
nginx
# /etc/nginx/nginx.conf 主要配置
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 10240;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 20m;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# 虚拟主机配置
include /etc/nginx/conf.d/*.conf;
}
5. 创建网站配置文件
nginx
# /etc/nginx/conf.d/example.com.conf
server {
listen 80;
server_name example.com www.example.com;
# 网站根目录
root /var/www/example.com;
index index.php index.html index.htm;
# 访问日志
access_log /var/log/nginx/example.com_access.log main;
error_log /var/log/nginx/example.com_error.log warn;
# 静态文件处理
location / {
try_files $uri $uri/ /index.php?$args;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# PHP处理
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# PHP-FPM超时
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问备份文件
location ~* \.(bak|backup|swp|old|orig)$ {
deny all;
}
}
6. 创建网站目录
bash
# 创建网站根目录
mkdir -p /var/www/example.com
# 设置权限
chown -R nginx:nginx /var/www/example.com
# Ubuntu使用www-data用户
# chown -R www-data:www-data /var/www/example.com
# 创建测试页面
cat > /var/www/example.com/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Welcome to LNMP</title>
</head>
<body>
<h1>LNMP installation successful!</h1>
<p>Nginx is working correctly.</p>
<p>PHP and MySQL will be configured next.</p>
</body>
</html>
EOF
四、MySQL安装与配置
1. 安装MySQL
bash
# CentOS/RHEL 7/8/9
# 添加MySQL官方仓库
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm
# CentOS 8
# yum install -y https://dev.mysql.com/get/mysql80-community-release-el8-4.noarch.rpm
# 安装MySQL 8.0
yum install -y mysql-community-server
# Ubuntu/Debian
# 下载MySQL APT仓库
wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb
dpkg -i mysql-apt-config_0.8.24-1_all.deb
apt update
apt install -y mysql-server
# 安装MariaDB(MySQL替代品)
# CentOS
yum install -y mariadb-server
# Ubuntu
apt install -y mariadb-server
2. 启动MySQL
bash
# 启动MySQL
systemctl start mysqld
# 或 systemctl start mariadb
# 设置开机自启
systemctl enable mysqld
# 查看状态
systemctl status mysqld
# 查看默认密码(MySQL 8.0)
grep 'temporary password' /var/log/mysqld.log
# 安全配置向导
mysql_secure_installation
# 对于MariaDB
mysql_secure_installation
3. MySQL安全配置
sql
-- 手动执行安全配置
-- 1. 修改root密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'StrongPassword123!';
-- 2. 删除匿名用户
DELETE FROM mysql.user WHERE User='';
-- 3. 禁止root远程登录
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
-- 4. 删除测试数据库
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
-- 5. 刷新权限
FLUSH PRIVILEGES;
4. 创建数据库和用户
sql
-- 登录MySQL
mysql -u root -p
-- 创建数据库
CREATE DATABASE example_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建用户
CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'Password123!';
CREATE USER 'example_user'@'%' IDENTIFIED BY 'Password123!';
-- 授权
GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost';
GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 查看用户
SELECT User, Host FROM mysql.user;
-- 测试连接
mysql -u example_user -p -h localhost example_db
5. MySQL优化配置
ini
# /etc/my.cnf 或 /etc/mysql/my.cnf
[mysqld]
# 基本设置
port = 3306
bind-address = 0.0.0.0
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init-connect = 'SET NAMES utf8mb4'
# 存储引擎
default-storage-engine = InnoDB
# 连接设置
max_connections = 1000
max_connect_errors = 100
connect_timeout = 10
wait_timeout = 600
interactive_timeout = 28800
# 缓冲区
key_buffer_size = 256M
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
join_buffer_size = 2M
# 临时表
tmp_table_size = 64M
max_heap_table_size = 64M
# 查询缓存(MySQL 5.7及以下)
# query_cache_type = 1
# query_cache_size = 64M
# query_cache_limit = 2M
# 日志
log_error = /var/log/mysql/error.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
# InnoDB设置
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
# 安全设置
local_infile = 0
skip_symbolic_links = yes
secure_file_priv = /var/lib/mysql-files
[client]
default-character-set = utf8mb4
port = 3306
socket = /var/lib/mysql/mysql.sock
[mysql]
default-character-set = utf8mb4
prompt = '\u@\h [\d]> '
6. MySQL常用命令
bash
# 备份数据库
mysqldump -u root -p example_db > example_db_backup.sql
mysqldump --all-databases > all_databases_backup.sql
# 恢复数据库
mysql -u root -p example_db < example_db_backup.sql
# 导入SQL文件
mysql -u root -p < data.sql
# 查看数据库大小
mysql -e "SELECT table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables
GROUP BY table_schema;"
# 查看进程
mysql -e "SHOW PROCESSLIST;"
# 查看状态
mysql -e "SHOW STATUS LIKE '%connect%';"
五、PHP安装与配置
1. 安装PHP
bash
# CentOS/RHEL 7/8/9
# 添加EPEL和REMI仓库
yum install -y epel-release
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
# CentOS 8
# yum install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
# 启用PHP 8.2仓库
yum module enable php:remi-8.2 -y
# 安装PHP和常用扩展
yum install -y php php-fpm php-cli php-common php-devel \
php-mysqlnd php-pdo php-gd php-mbstring php-xml \
php-zip php-curl php-json php-opcache php-bcmath \
php-redis php-memcached php-intl php-soap php-pear
# Ubuntu/Debian
# 添加PPA(Ubuntu)
apt install -y software-properties-common
add-apt-repository ppa:ondrej/php
apt update
# 安装PHP 8.2
apt install -y php8.2 php8.2-fpm php8.2-cli php8.2-common \
php8.2-mysql php8.2-pdo php8.2-gd php8.2-mbstring \
php8.2-xml php8.2-zip php8.2-curl php8.2-bcmath \
php8.2-redis php8.2-memcached php8.2-intl
# 编译安装PHP(自定义需求)
# 安装依赖
yum groupinstall -y "Development Tools"
yum install -y gcc gcc-c++ make automake autoconf libtool \
libxml2-devel openssl-devel curl-devel libjpeg-devel \
libpng-devel freetype-devel libmcrypt-devel mhash-devel \
libxslt-devel libc-client-devel libicu-devel
# 下载源码
wget https://www.php.net/distributions/php-8.2.10.tar.gz
tar -xzf php-8.2.10.tar.gz
cd php-8.2.10
# 编译配置
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-config-file-scan-dir=/usr/local/php/etc/php.d \
--enable-fpm \
--with-fpm-user=nginx \
--with-fpm-group=nginx \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-gd \
--with-zlib \
--with-curl \
--with-openssl \
--with-xsl \
--with-gettext \
--with-mhash \
--enable-mbstring \
--enable-xml \
--enable-bcmath \
--enable-sockets \
--enable-zip \
--enable-opcache
# 编译安装
make -j$(nproc)
make install
# 复制配置文件
cp php.ini-production /usr/local/php/etc/php.ini
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf
2. 配置PHP-FPM
ini
# /etc/php-fpm.d/www.conf 或 /etc/php/8.2/fpm/pool.d/www.conf
[www]
; 用户和组
user = nginx
group = nginx
; 监听方式(使用Unix Socket或TCP)
; listen = 127.0.0.1:9000
listen = /var/run/php-fpm/php-fpm.sock
; Socket权限
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; 进程管理
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
; 请求超时
request_terminate_timeout = 180s
request_slowlog_timeout = 10s
; 环境变量
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
; 慢日志
slowlog = /var/log/php-fpm/www-slow.log
; 状态页
pm.status_path = /status
ping.path = /ping
ping.response = pong
3. 配置php.ini
ini
# /etc/php.ini 或 /etc/php/8.2/cli/php.ini
[PHP]
; 基本设置
engine = On
short_open_tag = Off
asp_tags = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
; 安全设置
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
disable_classes =
expose_php = Off
max_execution_time = 30
max_input_time = 60
memory_limit = 256M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
html_errors = Off
; 文件上传
file_uploads = On
upload_max_filesize = 20M
max_file_uploads = 20
post_max_size = 20M
max_input_vars = 3000
; 日期时间
date.timezone = Asia/Shanghai
; 会话设置
session.save_handler = files
session.use_strict_mode = 1
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 32
session.sid_bits_per_character = 5
; OPcache
[opcache]
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
opcache.fast_shutdown = 1
opcache.validate_timestamps = 1
4. 启动PHP-FPM
bash
# 启动PHP-FPM
systemctl start php-fpm
# Ubuntu
# systemctl start php8.2-fpm
# 设置开机自启
systemctl enable php-fpm
# 查看状态
systemctl status php-fpm
# 检查PHP-FPM监听
netstat -tlnp | grep 9000
# 或检查Socket
ls -la /var/run/php-fpm/
# 测试PHP处理
php -v
php -m
5. 创建PHP测试页面
php
<?php
// /var/www/example.com/index.php
phpinfo();
?>
<?php
// /var/www/example.com/info.php
$output = '';
$output .= '<h1>LNMP Environment Test</h1>';
// PHP版本
$output .= '<h2>PHP Information</h2>';
$output .= '<p>PHP Version: ' . phpversion() . '</p>';
// 加载的扩展
$output .= '<h2>Loaded Extensions</h2><ul>';
$extensions = get_loaded_extensions();
sort($extensions);
foreach ($extensions as $ext) {
$output .= '<li>' . $ext . '</li>';
}
$output .= '</ul>';
// MySQL连接测试
$output .= '<h2>MySQL Connection Test</h2>';
try {
$db = new PDO('mysql:host=localhost;dbname=example_db;charset=utf8mb4', 'example_user', 'Password123!');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$output .= '<p style="color:green">✓ MySQL connection successful</p>';
} catch (PDOException $e) {
$output .= '<p style="color:red">✗ MySQL connection failed: ' . $e->getMessage() . '</p>';
}
// 系统信息
$output .= '<h2>System Information</h2>';
$output .= '<p>Server IP: ' . $_SERVER['SERVER_ADDR'] . '</p>';
$output .= '<p>Client IP: ' . $_SERVER['REMOTE_ADDR'] . '</p>';
$output .= '<p>Document Root: ' . $_SERVER['DOCUMENT_ROOT'] . '</p>';
$output .= '<p>Current Time: ' . date('Y-m-d H:i:s') . '</p>';
// 内存使用
$output .= '<h2>Memory Usage</h2>';
$output .= '<p>Memory Limit: ' . ini_get('memory_limit') . '</p>';
$output .= '<p>Memory Usage: ' . round(memory_get_usage() / 1024 / 1024, 2) . ' MB</p>';
echo $output;
?>
6. 配置Nginx处理PHP
nginx
# /etc/nginx/conf.d/example.com.conf
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# PHP处理
location ~ \.php$ {
# 使用TCP
# fastcgi_pass 127.0.0.1:9000;
# 使用Socket
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;
# PHP-FPM超时
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
7. 测试PHP处理
bash
# 重启Nginx和PHP-FPM
systemctl restart nginx
systemctl restart php-fpm
# 创建测试文件
cat > /var/www/example.com/test.php << 'EOF'
<?php
echo "PHP is working correctly!";
phpinfo();
?>
EOF
# 测试访问
curl http://localhost/test.php
# 或通过浏览器访问 http://服务器IP/test.php
六、部署Web应用
1. 部署phpMyAdmin
bash
# 下载phpMyAdmin
cd /tmp
wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.zip
unzip phpMyAdmin-5.2.1-all-languages.zip
mv phpMyAdmin-5.2.1-all-languages /var/www/example.com/phpmyadmin
# 创建配置
cd /var/www/example.com/phpmyadmin
cp config.sample.inc.php config.inc.php
# 生成blowfish_secret
cat > /tmp/secret.php << 'EOF'
<?php
echo bin2hex(random_bytes(32));
?>
EOF
php /tmp/secret.php
# 编辑配置文件
vim config.inc.php
# 添加/修改
$cfg['blowfish_secret'] = '生成的32位密钥';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['port'] = '3306';
$cfg['Servers'][$i]['auth_type'] = 'cookie';
# 设置权限
chown -R nginx:nginx /var/www/example.com/phpmyadmin
2. 部署WordPress
bash
# 下载WordPress
cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
mv wordpress /var/www/example.com/
# 设置权限
chown -R nginx:nginx /var/www/example.com/wordpress
chmod -R 755 /var/www/example.com/wordpress
# 创建WordPress数据库
mysql -u root -p -e "CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u root -p -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'WpPassword123!';"
mysql -u root -p -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';"
mysql -u root -p -e "FLUSH PRIVILEGES;"
# 复制配置文件
cd /var/www/example.com/wordpress
cp wp-config-sample.php wp-config.php
# 编辑配置
sed -i "s/database_name_here/wordpress/" wp-config.php
sed -i "s/username_here/wpuser/" wp-config.php
sed -i "s/password_here/WpPassword123!/" wp-config.php
# 生成安全密钥
curl -s https://api.wordpress.org/secret-key/1.1/salt/ >> wp-config.php
# 创建Nginx配置
cat > /etc/nginx/conf.d/wordpress.conf << 'EOF'
server {
listen 80;
server_name blog.example.com;
root /var/www/example.com/wordpress;
index index.php index.html index.htm;
access_log /var/log/nginx/wordpress_access.log main;
error_log /var/log/nginx/wordpress_error.log warn;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
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;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
location = /wp-admin {
rewrite ^ /wp-admin/index.php? permanent;
}
location = /wp-login.php {
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;
# 限制登录尝试
limit_req zone=login burst=5 nodelay;
}
location ~* /(wp-content|wp-includes)/.*\.php$ {
deny all;
}
}
EOF
# 重启Nginx
systemctl restart nginx
3. 部署Laravel应用
bash
# 安装Composer
cd /tmp
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
chmod +x /usr/local/bin/composer
# 创建Laravel项目
cd /var/www/example.com
composer create-project --prefer-dist laravel/laravel laravel
# 设置权限
chown -R nginx:nginx laravel
chmod -R 755 laravel/storage
chmod -R 755 laravel/bootstrap/cache
# 配置.env文件
cd laravel
cp .env.example .env
php artisan key:generate
# 编辑.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel_user
DB_PASSWORD=LaravelPassword123!
# 创建数据库
mysql -u root -p -e "CREATE DATABASE laravel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u root -p -e "CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'LaravelPassword123!';"
mysql -u root -p -e "GRANT ALL PRIVILEGES ON laravel.* TO 'laravel_user'@'localhost';"
mysql -u root -p -e "FLUSH PRIVILEGES;"
# 运行迁移
php artisan migrate
# 创建Nginx配置
cat > /etc/nginx/conf.d/laravel.conf << 'EOF'
server {
listen 80;
server_name app.example.com;
root /var/www/example.com/laravel/public;
index index.php index.html index.htm;
access_log /var/log/nginx/laravel_access.log main;
error_log /var/log/nginx/laravel_error.log warn;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "upload_max_filesize = 20M \n post_max_size = 20M";
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
EOF
systemctl restart nginx
七、性能优化
1. Nginx优化
nginx
# /etc/nginx/nginx.conf
# 工作进程
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 10240;
multi_accept on;
accept_mutex off;
}
http {
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 连接超时
keepalive_timeout 65;
keepalive_requests 100;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 10;
# 客户端缓冲区
client_body_buffer_size 128k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 20m;
# 输出缓冲区
output_buffers 32 32k;
postpone_output 1460;
# 文件缓存
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors off;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_disable "msie6";
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
}
2. PHP-FPM优化
ini
# /etc/php-fpm.d/www.conf
[www]
; 进程管理
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 1000
; 请求限制
request_terminate_timeout = 300
request_slowlog_timeout = 10
; 资源限制
rlimit_files = 65535
rlimit_core = 0
; 进程优先级
process.priority = -19
ini
# /etc/php.ini
[PHP]
; 资源限制
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
; 上传限制
post_max_size = 20M
upload_max_filesize = 20M
max_file_uploads = 20
; 会话
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
[opcache]
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1
opcache.enable_cli = 0
3. MySQL优化
ini
# /etc/my.cnf
[mysqld]
# 连接设置
max_connections = 500
max_user_connections = 100
wait_timeout = 600
interactive_timeout = 28800
# 缓冲区
key_buffer_size = 256M
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
join_buffer_size = 2M
# InnoDB
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_open_files = 2048
innodb_io_capacity = 2000
# 表缓存
table_open_cache = 2048
table_definition_cache = 2048
# 临时表
tmp_table_size = 64M
max_heap_table_size = 64M
# 查询缓存(MySQL 5.7)
# query_cache_type = 1
# query_cache_size = 64M
# 线程缓存
thread_cache_size = 256
# 日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
4. 系统优化
bash
# 调整系统限制
cat >> /etc/security/limits.conf << 'EOF'
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF
# 调整内核参数
cat >> /etc/sysctl.conf << 'EOF'
# 网络优化
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
# 文件系统
fs.file-max = 65535
fs.inotify.max_user_watches = 524288
# 内存
vm.swappiness = 10
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
EOF
# 应用参数
sysctl -p
八、监控和维护
1. 日志管理
bash
# 日志切割配置
cat > /etc/logrotate.d/nginx << 'EOF'
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 nginx nginx
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
EOF
cat > /etc/logrotate.d/php-fpm << 'EOF'
/var/log/php-fpm/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 nginx nginx
sharedscripts
postrotate
[ -f /var/run/php-fpm/php-fpm.pid ] && kill -USR2 `cat /var/run/php-fpm/php-fpm.pid`
endscript
}
EOF
cat > /etc/logrotate.d/mysql << 'EOF'
/var/log/mysql/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 mysql mysql
sharedscripts
postrotate
test -x /usr/bin/mysqladmin || exit 0
mysqladmin flush-logs
endscript
}
EOF
# 手动执行日志切割
logrotate -vf /etc/logrotate.d/nginx
2. 监控脚本
bash
#!/bin/bash
# lnmp_monitor.sh - LNMP监控脚本
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 检查服务状态
check_service() {
local service=$1
if systemctl is-active --quiet $service; then
echo -e "${GREEN}✓ $service 运行中${NC}"
return 0
else
echo -e "${RED}✗ $service 未运行${NC}"
return 1
fi
}
# 检查端口
check_port() {
local port=$1
local service=$2
if netstat -tlnp | grep -q ":$port "; then
echo -e "${GREEN}✓ $service 端口 $port 正常${NC}"
return 0
else
echo -e "${RED}✗ $service 端口 $port 未监听${NC}"
return 1
fi
}
# 检查Nginx
check_nginx() {
echo -e "\n${YELLOW}=== Nginx 状态 ===${NC}"
check_service nginx
check_port 80 "Nginx"
check_port 443 "Nginx"
# 测试访问
if curl -s -o /dev/null -w "%{http_code}" http://localhost | grep -q "200"; then
echo -e "${GREEN}✓ Nginx 响应正常${NC}"
else
echo -e "${RED}✗ Nginx 响应异常${NC}"
fi
# Nginx连接数
CONNECTIONS=$(netstat -anp | grep :80 | grep ESTABLISHED | wc -l)
echo "Nginx连接数: $CONNECTIONS"
}
# 检查PHP-FPM
check_php() {
echo -e "\n${YELLOW}=== PHP-FPM 状态 ===${NC}"
check_service php-fpm
check_port 9000 "PHP-FPM"
# 检查PHP-FPM进程
PHP_PROCESSES=$(ps aux | grep php-fpm | grep -v grep | wc -l)
echo "PHP-FPM进程数: $PHP_PROCESSES"
# 测试PHP处理
if curl -s http://localhost/test.php | grep -q "PHP is working"; then
echo -e "${GREEN}✓ PHP 处理正常${NC}"
else
echo -e "${RED}✗ PHP 处理异常${NC}"
fi
}
# 检查MySQL
check_mysql() {
echo -e "\n${YELLOW}=== MySQL 状态 ===${NC}"
check_service mysqld
check_port 3306 "MySQL"
# 测试连接
if mysqladmin -u root -p"$MYSQL_PASS" ping 2>/dev/null | grep -q "alive"; then
echo -e "${GREEN}✓ MySQL 连接正常${NC}"
else
echo -e "${RED}✗ MySQL 连接失败${NC}"
fi
# 查看MySQL状态
mysql -e "SHOW STATUS LIKE 'Threads_connected';" 2>/dev/null
}
# 检查系统资源
check_system() {
echo -e "\n${YELLOW}=== 系统资源 ===${NC}"
# CPU负载
LOAD=$(uptime | awk -F'load average:' '{print $2}')
echo "CPU负载: $LOAD"
# 内存使用
MEM=$(free -h | grep Mem | awk '{print "已用: " $3 " / 总计: " $2}')
echo "内存使用: $MEM"
# 磁盘使用
DISK=$(df -h / | awk 'NR==2 {print "已用: " $3 " / 总计: " $2 " (" $5 ")"}')
echo "磁盘使用: $DISK"
# inode使用
INODE=$(df -i / | awk 'NR==2 {print "已用: " $3 " / 总计: " $2 " (" $5 ")"}')
echo "inode使用: $INODE"
# 系统连接数
CONNS=$(netstat -an | grep ESTABLISHED | wc -l)
echo "系统连接数: $CONNS"
}
# 主函数
main() {
echo "LNMP 状态监控 - $(date)"
echo "========================"
MYSQL_PASS="your_mysql_password"
check_system
check_nginx
check_php
check_mysql
}
main
3. 备份脚本
bash
#!/bin/bash
# lnmp_backup.sh - LNMP备份脚本
# 配置
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_USER="root"
MYSQL_PASS="your_mysql_password"
WEB_ROOT="/var/www/example.com"
NGINX_CONF="/etc/nginx"
PHP_CONF="/etc/php-fpm.d /etc/php.ini"
MYSQL_CONF="/etc/my.cnf"
RETENTION_DAYS=7
# 创建备份目录
mkdir -p $BACKUP_DIR/{mysql,web,conf,logs}
# 备份MySQL
echo "备份MySQL数据库..."
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW DATABASES;" | grep -Ev "Database|information_schema|performance_schema|mysql|sys" | while read db; do
mysqldump -u$MYSQL_USER -p$MYSQL_PASS --opt --routines --triggers --events $db | gzip > $BACKUP_DIR/mysql/${db}_$DATE.sql.gz
echo " ✓ 备份数据库: $db"
done
# 备份网站文件
echo "备份网站文件..."
tar -czf $BACKUP_DIR/web/web_files_$DATE.tar.gz $WEB_ROOT
echo " ✓ 网站文件备份完成"
# 备份配置文件
echo "备份配置文件..."
tar -czf $BACKUP_DIR/conf/nginx_conf_$DATE.tar.gz $NGINX_CONF
tar -czf $BACKUP_DIR/conf/php_conf_$DATE.tar.gz $PHP_CONF
tar -czf $BACKUP_DIR/conf/mysql_conf_$DATE.tar.gz $MYSQL_CONF
echo " ✓ 配置文件备份完成"
# 备份日志(可选)
echo "备份日志文件..."
tar -czf $BACKUP_DIR/logs/nginx_logs_$DATE.tar.gz /var/log/nginx
tar -czf $BACKUP_DIR/logs/php_logs_$DATE.tar.gz /var/log/php-fpm
tar -czf $BACKUP_DIR/logs/mysql_logs_$DATE.tar.gz /var/log/mysql
echo " ✓ 日志备份完成"
# 删除旧备份
echo "清理旧备份..."
find $BACKUP_DIR/mysql -type f -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR/web -type f -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR/conf -type f -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR/logs -type f -mtime +$RETENTION_DAYS -delete
# 创建备份报告
cat > $BACKUP_DIR/backup_report_$DATE.txt << EOF
备份时间: $(date)
备份内容:
- MySQL数据库
- 网站文件
- 配置文件
- 日志文件
备份位置: $BACKUP_DIR
保留期限: $RETENTION_DAYS 天
EOF
# 计算备份大小
echo "备份大小统计:" >> $BACKUP_DIR/backup_report_$DATE.txt
du -sh $BACKUP_DIR/mysql/*$DATE* >> $BACKUP_DIR/backup_report_$DATE.txt
du -sh $BACKUP_DIR/web/*$DATE* >> $BACKUP_DIR/backup_report_$DATE.txt
du -sh $BACKUP_DIR/conf/*$DATE* >> $BACKUP_DIR/backup_report_$DATE.txt
du -sh $BACKUP_DIR/logs/*$DATE* >> $BACKUP_DIR/backup_report_$DATE.txt
echo "备份完成!"
echo "备份报告: $BACKUP_DIR/backup_report_$DATE.txt"
# 可选:发送邮件通知
# mail -s "LNMP Backup Report $DATE" admin@example.com < $BACKUP_DIR/backup_report_$DATE.txt
# 可选:远程同步
# rsync -avz $BACKUP_DIR/ user@backup-server:/backup/
九、常见问题排查
1. Nginx常见问题
bash
# 检查Nginx配置
nginx -t
# 查看Nginx错误日志
tail -f /var/log/nginx/error.log
# 权限问题
# 502 Bad Gateway
# 检查PHP-FPM是否运行
systemctl status php-fpm
# 检查Socket权限
ls -la /var/run/php-fpm/
chown nginx:nginx /var/run/php-fpm/php-fpm.sock
# 检查文件权限
chown -R nginx:nginx /var/www/example.com
chmod -R 755 /var/www/example.com
# 端口冲突
netstat -tlnp | grep 80
netstat -tlnp | grep 443
# 重载配置
nginx -s reload
systemctl reload nginx
2. PHP-FPM常见问题
bash
# 检查PHP-FPM状态
systemctl status php-fpm
# 查看PHP-FPM日志
tail -f /var/log/php-fpm/error.log
tail -f /var/log/php-fpm/www-slow.log
# 检查PHP-FPM监听
ss -lnp | grep 9000
ls -la /var/run/php-fpm/
# 测试PHP配置
php -v
php -m
php -i | grep memory_limit
# 重新加载PHP-FPM
systemctl reload php-fpm
# 查看PHP-FPM进程
ps aux | grep php-fpm
# 检查PHP扩展
php -m | grep mysql
php -m | grep gd
3. MySQL常见问题
bash
# 检查MySQL状态
systemctl status mysqld
# 查看MySQL日志
tail -f /var/log/mysql/error.log
tail -f /var/log/mysql/slow.log
# 测试连接
mysql -u root -p -e "SELECT 1"
# 查看进程
mysql -e "SHOW PROCESSLIST;"
# 查看性能状态
mysql -e "SHOW STATUS;"
# 修复表
mysqlcheck -u root -p --auto-repair --all-databases
# 优化表
mysqlcheck -u root -p --optimize --all-databases
# 查看数据库大小
mysql -e "SELECT table_schema,
ROUND(SUM(data_length+index_length)/1024/1024,2) AS 'Size(MB)'
FROM information_schema.tables
GROUP BY table_schema;"
# 重置root密码(如果忘记)
systemctl stop mysqld
mysqld_safe --skip-grant-tables &
mysql -u root
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword123!';
FLUSH PRIVILEGES;
quit
systemctl restart mysqld
4. 性能问题排查
bash
# 检查系统负载
top
htop
# 检查内存使用
free -h
vmstat 1 5
# 检查磁盘IO
iostat -x 1 5
iotop
# 检查网络连接
netstat -an | grep ESTABLISHED | wc -l
ss -s
# 分析Nginx访问日志
tail -f /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr
# 分析慢查询
mysqldumpslow /var/log/mysql/slow.log
# 查看PHP-FPM状态
curl http://localhost/status
5. 快速诊断脚本
bash
#!/bin/bash
# lnmp_diagnose.sh - LNMP快速诊断脚本
echo "LNMP 诊断工具"
echo "==============="
echo "1. 系统信息"
echo " OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
echo " Kernel: $(uname -r)"
echo " CPU: $(nproc) cores"
echo " Memory: $(free -h | grep Mem | awk '{print $2}')"
echo " Disk: $(df -h / | awk 'NR==2 {print $2}')"
echo -e "\n2. 服务状态"
for service in nginx php-fpm mysqld; do
if systemctl is-active --quiet $service; then
echo " $service: 运行中"
else
echo " $service: 未运行"
fi
done
echo -e "\n3. 端口监听"
for port in 80 443 9000 3306; do
if ss -tlnp | grep -q ":$port "; then
echo " 端口 $port: 监听中"
else
echo " 端口 $port: 未监听"
fi
done
echo -e "\n4. PHP信息"
echo " PHP版本: $(php -v | head -1 | awk '{print $2}')"
echo " PHP-FPM进程: $(ps aux | grep php-fpm | grep -v grep | wc -l)"
echo -e "\n5. MySQL信息"
echo " MySQL版本: $(mysql -V 2>/dev/null | awk '{print $5}')"
echo " 连接数: $(mysql -e "SHOW STATUS LIKE 'Threads_connected'" 2>/dev/null | grep Threads_connected | awk '{print $2}')"
echo -e "\n6. Nginx信息"
echo " Nginx版本: $(nginx -v 2>&1 | awk -F/ '{print $2}')"
echo " 活动连接: $(curl -s http://localhost/nginx_status 2>/dev/null | grep "Active connections" || echo "N/A")"
echo -e "\n7. 日志错误"
echo " Nginx错误: $(tail -5 /var/log/nginx/error.log 2>/dev/null | wc -l) 条"
echo " PHP错误: $(tail -5 /var/log/php-fpm/error.log 2>/dev/null | wc -l) 条"
echo " MySQL错误: $(tail -5 /var/log/mysql/error.log 2>/dev/null | wc -l) 条"
echo -e "\n诊断完成!"
十、总结
LNMP架构优势
text
✅ 高性能 - Nginx高并发,异步非阻塞
✅ 低资源 - 内存占用少,CPU消耗低
✅ 高稳定性 - 各组件成熟稳定
✅ 可扩展 - 易于水平扩展
✅ 灵活性 - 可按需配置各组件
部署最佳实践
-
安全加固
-
定期更新组件
-
配置防火墙
-
使用强密码
-
最小权限原则
-
-
性能优化
-
调整工作进程数
-
配置缓存
-
启用压缩
-
优化数据库
-
-
监控维护
-
日志轮转
-
定期备份
-
性能监控
-
故障预警
-
-
高可用架构
-
负载均衡
-
主从复制
-
读写分离
-
集群部署
-