目录
一、原理与理论
LNMP架构核心
Linux:操作系统基础环境
Nginx:高性能Web服务器(处理静态请求)
MySQL:关系型数据库(存储动态数据)
PHP:服务端脚本语言(动态内容生成)
工作流程:
用户请求 → Nginx接收 → PHP处理动态请求 → MySQL读写数据 → 返回结果
脚本设计原理
模块化函数:将各组件安装拆分为独立函数(
nginx_install()
,mysql_install()
等)依赖顺序控制:严格遵循
Nginx → MySQL → PHP
的编译安装顺序安全隔离:为服务创建专用系统用户(www/mysql)
资源分离:数据库存储独立挂载到
/data/mysql
二、背景及目的
痛点背景:
手动部署LNMP环境步骤繁琐,平均耗时2小时+
组件版本兼容性问题频发(如PHP扩展依赖)
配置参数易遗漏(如MySQL socket路径)
脚本价值:
✅ 30分钟→5分钟:全自动化编译安装
✅ 解决版本兼容:预设验证版本(Nginx 1.9.5+MySQL 5.7.26+PHP 5.6.40)
✅ 开箱即用:集成WordPress CMS部署
✅ 安全加固:自动关闭SELinux/firewalld(生产环境需调整)
三、关键步骤说明
关键步骤解析:
前置处理
systemctl stop firewalld # 关闭防火墙
sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config # 禁用SELinux
- MySQL安全初始化
chown -R mysql:mysql /data/mysql/ # 数据目录权限控制
/usr/local/mysql/bin/mysqld --initialize-insecure # 免密初始化
- PHP-FPM优化 PHP-FPM 优化
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # PHP处理器监听
include fastcgi.conf; # 关键配置文件
}
四、常见问题及解决方案
问题现象 | 原因分析 | 解决方案 |
---|---|---|
make: *** No targets specified |
源码包未成功解压 | 检查/usr/src/ 下文件完整性 |
MySQL启动失败 | mysql.sock 权限不足 |
执行chown -R mysql:mysql /usr/local/mysql/ 香贤 chown -R mysql:mysql /usr/local/mysql/ |
PHP无法连接MySQL | 未配置socket路径 | 修改php.ini :mysqli.default_socket = /usr/local/mysql/mysql.sock |
Nginx 403错误 | WordPress目录权限不足 | 运行chmod -R 777 /usr/local/nginx/html |
无法外网访问 | 防火墙未关闭 | 确认执行了systemctl disable firewalld 确认执行了 systemctl disable firewalld |
五、总结与心得
脚本优势
版本控制精准:规避了依赖冲突问题
资源隔离完善:数据库独立存储+服务专用用户
自动化程度高:从环境配置到CMS部署一键完成
生产环境建议
🔐 安全强化:
恢复SELinux并配置策略(
setenforce 1
)改用非root用户运行Nginx(脚本已支持)
⚙️ 配置优化:
Nginx启用
gzip
压缩(取消配置文件中#gzip on;
注释)PHP升级到7.4+(修改脚本中PHP版本路径)
🔄 运维改进:
增加服务监控重启机制(如用
supervisord
)
开发心得
“通过此脚本深入理解了LNMP组件的交互依赖关系,特别是PHP-FPM与Nginx的协议通信机制。在MySQL编译中处理
boost
依赖的过程,加深了对C/C++项目构建的理解。建议后续增加Let's Encrypt证书自动部署功能以实现HTTPS化。”
脚本获取:
#!/bin/bash
#function:lnmp
##########################################
if
[ "$USER" != "root" ]
then
echo "错误:非root用户,权限不足!"
exit 0
fi
###############防火墙及SElinux############
systemctl stop firewalld && systemctl disable firewalld && echo "防火墙已经关闭"
sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config && echo "关闭selinux"
sleep 5
cflj=/usr/src
zip_file="lnmp.zip"
##############检查文件是否存在##############
if [ -f "$cflj/$zip_file" ]; then
cd $cflj
unzip lnmp.zip
rm -rf $cflj/lnmp.zip
else
echo "请上传文件 $zip_file 到 $cflj"
exit 1
fi
######### install nginx #########
function nginx_install(){
nginx_path="$cflj/nginx-1.9.5.tar.gz"
if [ -e "$nginx_path" ]; then
cd $cflj;
tar -zxf nginx-1.9.5.tar.gz
cd nginx-1.9.5/
groupadd www
useradd -g www www -s /sbin/nologin
mkdir -p /var/log/nginx
yum install -y gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre pcre-devel make automake
./configure \
--prefix=/usr/local/nginx \
--with-http_dav_module \
--with-http_stub_status_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-pcre \
--with-http_ssl_module \
--with-http_gzip_static_module \
--user=www \
--group=www
if [ $? -eq 0 ]; then
make && make install
if [ $? -eq 0 ]; then
echo "nginx编译安装完成"
else
echo "nginx编译安装失败"
exit 1
fi
else
echo"nginx编译安装失败"
exit 1
fi
else
echo "请上传nginx到/usr/src"
exit 0
fi
}
sleep 3
######### install mysql #########
function mysql_install(){
###########清理旧版本###########
rpm -qa | grep mariadb &>> /dev/null
rpm -qa | grep mysql &>> /dev/null
rpm -e mariadb-libs --nodeps mariadb-libs &>> /dev/null
yum -y remove mysql* mariadb* &>> /dev/null
##########判断boost文件#############
boost_path="$cflj/boost_1_59_0.tar.bz2"
# 检查文件是否存在
if [ -e "$boost_path" ]; then
cd $cflj;
groupadd mysql
useradd mysql -g mysql -M -s /sbin/nologin
mkdir -p /data/mysql/{data,log}
chown -R mysql:mysql /data/mysql/
tar jxf boost_1_59_0.tar.bz2 -C /root/
else
echo "请上传boost到/usr/src"
exit 0
fi
##########判断mysql文件#############
mysql_path="$cflj/mysql-5.7.26.tar.gz"
if [ -e "$mysql_path" ]; then
cd $cflj;
tar xzf mysql-5.7.26.tar.gz
cd mysql-5.7.26/
yum install -y cmake make gcc gcc-c++ bison ncurses ncurses-devel bzip2
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/data/mysql/data \
-DSYSCONFDIR=/etc \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/root/boost_1_59_0
if [ $? -eq 0 ]; then
make && make install
if [ $? -eq 0 ]; then
echo "mysql编译安装完成"
else
echo "mysql编译安装失败"
exit 1
fi
else
echo"mysql编译安装失败"
exit 1
fi
sleep 3
#####设置权限#########
chown -R mysql:mysql /usr/local/mysql/
#####定义配置文件#####
cat >> /etc/my.cnf << EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql/data
port=3306
socket=/usr/local/mysql/mysql.sock
symbolic-links=0
character-set-server=utf8
log-error=/data/mysql/log/mysqld.log
pid-file=/usr/local/mysql/mysqld.pid
EOF
cp /usr/src/mysql-5.7.26/support-files/mysql.server /etc/init.d/mysql.server
chmod +x /etc/init.d/mysql.server
/usr/local/mysql/bin/mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/data/mysql/data
/etc/init.d/mysql.server start
sleep 2
if [ $? -eq 0 ]; then
ln -s /usr/local/mysql/bin/* /usr/local/bin/
echo "mysq启动成功"
else
echo"mysq启动失败"
exit 1
fi
else
echo "请上传mysql到/usr/src"
exit 0
fi
}
sleep 3
######### install phpex #########
function phpex_install(){
libmcrypt_path="$cflj/libmcrypt-2.5.8.tar.gz"
if [ -e "$libmcrypt_path" ]; then
cd $cflj;
yum -y install zlib* libxml2*
tar zxf $cflj/libmcrypt-2.5.8.tar.gz
cd libmcrypt-2.5.8/
./configure
if [ $? -eq 0 ]; then
make && make install
if [ $? -eq 0 ]; then
echo "libmcrypt编译安装完成"
else
echo "libmcrypt编译安装失败"
exit 1
fi
else
echo"libmcrypt编译安装失败"
exit 1
fi
else
echo "请上传libmcrypt到/usr/src"
exit 0
fi
}
######### install php #########
function php_install(){
php_path="$cflj/php-5.6.40.tar.gz"
if [ -e "$php_path" ]; then
cd $cflj;
tar zxf $cflj/php-5.6.40.tar.gz
yum -y install gcc autoconf freetype gd libpng libpng-devel libjpeg libxml2 libxml2-devel zlib curl curl-devel freetype-devel libjpeg-devel bzip2 bzip2-devel openssl openssl-devel
cd php-5.6.40/
./configure --prefix=/usr/local/php5.6 \
--with-mysql=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--enable-mbstring \
--with-curl \
--with-gd \
--enable-fpm \
--with-config-file-path \
--with-openssl \
--enable-fpm \
--enable-sockets \
--enable-sysvshm \
--enable-mbstring \
--with-freetype-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib \
--with-libxml-dir=/usr \
--enable-xml \
--with-mhash \
--with-mcrypt=/usr/local/libmcrypt \
--with-config-file-path=/usr/local/php5.6/etc \
--with-config-file-scan-dir=/etc/php.d \
--with-bz2
if [ $? -eq 0 ]; then
make && make install
if [ $? -eq 0 ]; then
echo "php编译安装完成"
else
echo "php编译安装失败"
exit 1
fi
else
echo"php编译安装失败"
exit 1
fi
else
echo "请上传php到/usr/src"
exit 0
fi
}
sleep 3
######### lnmp config #########
function lnmp_config(){
cp /usr/src/php-5.6.40/php.ini-production /usr/local/php5.6/php.ini
cp /usr/local/php5.6/etc/php-fpm.conf.default /usr/local/php5.6/etc/php-fpm.conf
cp /usr/src/php-5.6.40/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm
/etc/init.d/php-fpm start
sleep 3
sed -i '1221s#^mysqli.default_socket =.*#mysqli.default_socket = /usr/local/mysql/mysql.sock#' /usr/local/php5.6/php.ini
sed -i '202s/short_open_tag = Off/short_open_tag = On/' /usr/local/php5.6/php.ini
sed -i '164s/^listen = .*/listen = 0.0.0.0:9000/' /usr/local/php5.6/etc/php-fpm.conf
sed -i '149s/^user = .*/user = www/' /usr/local/php5.6/etc/php-fpm.conf
sed -i '150s/^group = .*/group = www/' /usr/local/php5.6/etc/php-fpm.conf
sed -i '25s/.*/pid = run\/php-fpm.pid/' /usr/local/php5.6/etc/php-fpm.conf
sleep 3
/usr/local/mysql/bin/mysql -u root -e "grant all on *.* to 'wordpress'@'%' identified by 'wordpress@163.com';"
/usr/local/mysql/bin/mysql -u root -e "flush privileges;"
/usr/local/mysql/bin/mysql -u root -e "flush privileges;"
sleep 3
cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak
mkdir -p /var/log/nginx
cat > /usr/local/nginx/conf/nginx.conf <<EOF
user www;
worker_processes 2;
error_log logs/error.log;
pid logs/nginx.pid;
events {
use epoll;
worker_connections 1024;
}
http {
include 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 logs/access.log main;
sendfile on;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
root html;
index index.php index.html index.htm;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
EOF
#/usr/local/nginx/sbin/nginx -s reload
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
/etc/init.d/mysql.server restart
/etc/init.d/php-fpm restart
#lsof -i :80
#echo $(grep processor /proc/cpuinfo | wc -l)
}
######### cms #########
function cms_install(){
cms_path="$cflj/wordpress-6.2.2-zh_CN.zip"
if [ -e "$cms_path" ]; then
IP=$(ip a | grep "inet "|grep "ens33" | awk '{print $2}' | awk -F / '{print $1}')
rm -rf /usr/local/nginx/html/*
cp /usr/src/wordpress-6.2.2-zh_CN.zip /usr/local/nginx/html && cd /usr/local/nginx/html && unzip wordpress-6.2.2-zh_CN.zip
chmod -R 777 /usr/local/nginx/html && mv /usr/local/nginx/html/wordpress/* /usr/local/nginx/html/
echo "通过如下地址访问CMS:http://$IP/ 数据库默认用户:wordpress,密码:wordpress@163.com "
else
echo "请上传cms到/usr/src"
exit 0
fi
}
PS3="请你选择需要安装的服务:"
select i in nginx mysql phpex php config cms all exit
do
case $i in
nginx)
nginx_install 1
;;
mysql)
mysql_install 2
;;
phpex)
phpex_install 3
;;
php)
php_install 4
;;
config)
lnmp_config 5
;;
cms)
cms_install 6
;;
all)
nginx_install 1
mysql_install 2
phpex_install 3
php_install 4
lnmp_config 5
cms_install 6
;;
exit)
echo "退出..."
exit
esac
done