手動編譯 Apache/Nginx、MySQL、PHP 不僅耗時易錯,難以複現。本文提供一個 **253 行、模組化、支援 CentOS 7/8、Rocky/AlmaLinux** 的生產級部署腳本,涵蓋 YUM 源優化、依賴解決、原始碼編譯參數調優、systemd 服務化、防火牆放行、驗證測試全流程。
deploy_lnmp_lamp.sh
├─ yum_update() # 阿里雲源 + EPEL,建立快取
├─ yum_depend() # 編譯/運行依賴全裝
├─ install_mysql() # CMake 參數調優,data 目錄分離
├─ install_apache() # APR/APR-util 靜態連結,MPM event
├─ install_nginx() # pcre/ssl/gzip/stub_status 模組
├─ install_php() # PHP-FPM 模式,生產 php.ini
├─ set_lamp() # Apache 整合 PHP、測試頁
├─ set_lnmp() # Nginx fastcgi_pass、測試頁
├─ install_lamp() # 編排 LAMP 全流程
├─ install_lnmp() # 編排 LNMP 全流程
└─ 主選單 # 互動式選擇 1.LAMP 2.LNMP 3.Exit
| 模組 | 優化細節 |
|---|---|
| MySQL 5.6/5.7/8.0 | -DWITH_INNOBASE_STORAGE_ENGINE=1、innodb_buffer_pool_size 佔實體記憶體 70%、datadir=/data/mysql 分離 |
| Apache 2.4 | MPM Event、--enable-mods-shared=most、靜態連結 APR、ServerName localhost 消除警告 |
| Nginx 1.18+ | --with-http_v2_module、--with-http_ssl_module、--with-threads、--with-file-aio |
| PHP 7.4/8.1/8.2 | PHP-FPM 專用、opcache.enable=1、date.timezone=Asia/Shanghai、cgi.fix_pathinfo=0 |
| 防火牆 | 自動 firewall-cmd --add-service={http,https,mysql} 或 iptables 相容 |
| 驗證 | 各模組結尾 check_ok 檢查返回碼、curl localhost/test.php 實測 |
#!/bin/bash
set -euo pipefail
. /etc/init.d/functions # CentOS 紅綠燈輸出
check_ok() {
if [ $? -ne 0 ]; then
action "FAILED: $1" /bin/false
exit 1
fi
action "$1" /bin/true
}
yum_update() {
echo "=== 更新 YUM 源 ==="
mv /etc/yum.repos.d/CentOS-Base.repo{,.bak}
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum clean all && yum makecache fast
check_ok "YUM source updated"
}
yum_depend() {
yum install -y gcc gcc-c++ make cmake autoconf automake libtool \
libxml2-devel libxslt-devel openssl-devel bzip2-devel libcurl-devel \
libjpeg-devel libpng-devel freetype-devel libmcrypt-devel \
libicu-devel openldap-devel postgresql-devel sqlite-devel \
oniguruma-devel libzip-devel zlib-devel readline-devel \
ncurses-devel pcre-devel
check_ok "Dependencies installed"
}
install_mysql() {
cd /usr/local/src
tar xzf mysql-8.0.35-linux-glibc2.28-x86_64.tar.xz # 或原始碼編譯
mv mysql-8.0.35 /usr/local/mysql
useradd -r -s /sbin/nologin mysql
mkdir -p /data/mysql /var/log/mysql
chown -R mysql:mysql /usr/local/mysql /data/mysql /var/log/mysql
/usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
sed -i 's#^basedir=#basedir=/usr/local/mysql#; s#^datadir=#datadir=/data/mysql#' /etc/init.d/mysqld
systemctl daemon-reload && systemctl enable --now mysqld
check_ok "MySQL installed"
}
install_nginx() {
cd /usr/local/src
tar xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module --with-http_v2_module --with-http_realip_module \
--with-http_stub_status_module --with-http_gzip_static_module \
--with-pcre --with-threads --with-file-aio \
--user=nginx --group=nginx
make -j$(nproc) && make install
useradd -r -s /sbin/nologin nginx
cat > /etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=Nginx
After=network.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 quit
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now nginx
check_ok "Nginx installed"
}
set_lnmp() {
sed -i '/location \/ {/a\ location ~ \.php$ {\n fastcgi_pass 127.0.0.1:9000;\n fastcgi_index index.php;\n fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n include fastcgi_params;\n }' /usr/local/nginx/conf/nginx.conf
systemctl reload nginx
echo '' > /usr/local/nginx/html/index.php
curl -sf localhost/index.php | grep -q "PHP Version" && check_ok "LNMP verified"
}
# 主選單
cat <<'EOF'
1) Install LAMP
2) Install LNMP
3) Exit
EOF
read -t 30 -p "Choice [1-3]: " choice
case $choice in
1) install_lamp ;;
2) install_lnmp ;;
3) exit 0 ;;
*) echo "Invalid"; exit 1 ;;
esac
/usr/local/src(腳本可自動 wget)# 1. 服務狀態
systemctl status mysqld nginx php-fpm
# 2. 連線測試
mysql -uroot -p -e "SELECT VERSION();"
curl -I localhost | head -1
curl -sf localhost/index.php | grep -c "PHP Version"
# 3. 埠口
ss -lntp | grep -E ':80|:3306|:9000'
# 4. 日誌無 ERROR
journalctl -u mysqld -u nginx -u php-fpm -p err --since "1 hour ago"
| 現象 | 原因 | 修正 |
|---|---|---|
| MySQL 啟動失敗 | datadir 權限、SELinux、殘留 pid | chown -R mysql:mysql /data/mysql; setenforce 0; rm -f /data/mysql/*.pid |
| Nginx 502 Bad Gateway | PHP-FPM 未啟動、sock 路徑錯誤、fastcgi_pass 不通 | systemctl status php-fpm; ss -lntp | grep 9000 |
| PHP 模組缺失 | 編譯時缺少 -devel 套件 | 補裝 libxxx-devel 重新 make clean && make install |
| 防火牆擋住 | firewalld/iptables 未放行 | 腳本自動處理,手動 firewall-cmd --add-service=http --permanent |
結語: 一鍵腳本不是「跑完不管」,而是「標準化、可複現、可審計」的基礎設施即代碼雛形。把版本號、編譯參數、目錄佈局固化在腳本裡,新機器 30 分鐘交付生產可用的 LAMP/LNMP,才是運維效率的真正躍升。