在需要精確控制版本、模塊、優化參數的生產環境中,從源碼編譯安裝 LAMP (Linux + Apache + MySQL + PHP) 仍是核心技能。本文提供基於 CentOS/RHEL 的完整編譯安裝流程,涵蓋依賴包準備、各組件配置參數解析、Cacti 監控部署、啟動腳本與驗證步驟。
# 1. 安裝編譯工具鏈與庫開發包 (CentOS/RHEL 7/8)
yum -y install gcc gcc-c++ make autoconf libtool \
libjpeg-devel libpng-devel freetype-devel \
libxml2-devel zlib-devel bzip2-devel \
openssl-devel curl-devel \
pcre-devel \
ncurses-devel \
cmake \
perl-Data-Dumper \
wget tar gzip bzip2
# 2. 創建專用用戶 (安全最佳實踐)
useradd -r -s /sbin/nologin -M mysql
useradd -r -s /sbin/nologin -M apache
useradd -r -s /sbin/nologin -M cacti
# 3. 統一安裝前綴 (便於管理/遷移/多版本共存)
export PREFIX=/usr/local
mkdir -p ${PREFIX}/{mysql,httpd,php,cacti}
cd /usr/local/src
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36.tar.gz
tar xzf mysql-8.0.36.tar.gz
cd mysql-8.0.36
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=${PREFIX}/mysql \
-DMYSQL_DATADIR=${PREFIX}/mysql/data \
-DSYSCONFDIR=/etc \
-DWITH_INNODB_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DWITH_FEDERATED_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DWITH_SSL=system \
-DWITH_ZLIB=system \
-DWITH_BOOST=../boost/boost_1_77_0 # MySQL 8.0 需指定 Boost 源碼路徑
make -j$(nproc) && make install
# 初始化數據目錄
${PREFIX}/mysql/bin/mysqld --initialize-insecure --user=mysql \
--basedir=${PREFIX}/mysql --datadir=${PREFIX}/mysql/data
# 配置文件
cp ${PREFIX}/mysql/support-files/my-default.cnf /etc/my.cnf
# 編輯 /etc/my.cnf 調優參數 (見文末模板)
# 啟動腳本與服務註冊
cp ${PREFIX}/mysql/support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
# 設置 root 密碼
${PREFIX}/mysql/bin/mysqladmin -u root password 'StrongPassw0rd!'
cd /usr/local/src
wget https://dlcdn.apache.org/httpd/httpd-2.4.59.tar.gz
wget https://dlcdn.apache.org/apr/apr-1.7.4.tar.gz
wget https://dlcdn.apache.org/apr/apr-util-1.6.3.tar.gz
# APR/APR-Util 解壓至 httpd/srclib/
tar xzf httpd-2.4.59.tar.gz
cd httpd-2.4.59/srclib
tar xzf ../../apr-1.7.4.tar.gz && mv apr-1.7.4 apr
tar xzf ../../apr-util-1.6.3.tar.gz && mv apr-util-1.6.3 apr-util
cd ..
./configure \
--prefix=${PREFIX}/httpd \
--enable-mpms-shared=all \
--with-mpm=event \
--enable-mods-shared=most \
--enable-ssl \
--with-ssl=/usr/bin/openssl \
--enable-rewrite \
--enable-deflate \
--enable-expires \
--enable-headers \
--enable-proxy \
--enable-proxy-http \
--enable-proxy-fcgi \
--with-pcre=/usr/bin/pcre-config \
--with-zlib=/usr \
--enable-so
make -j$(nproc) && make install
# 配置 httpd.conf 關鍵調整
# 1. User/Group apache
# 2. ServerName localhost:80
# 3. EnableModule: mod_rewrite, mod_deflate, mod_expires, mod_headers, mod_proxy_fcgi
# 4. DirectoryIndex index.php index.html
# 5. Include conf/extra/httpd-vhosts.conf (虛擬主機)
# 啟動腳本
cp ${PREFIX}/httpd/bin/apachectl /etc/init.d/httpd
chmod +x /etc/init.d/httpd
chkconfig --add httpd
chkconfig httpd on
cd /usr/local/src
wget https://www.php.net/distributions/php-8.3.6.tar.gz
tar xzf php-8.3.6.tar.gz
cd php-8.3.6
./configure \
--prefix=${PREFIX}/php \
--with-config-file-path=${PREFIX}/php/etc \
--with-config-file-scan-dir=${PREFIX}/php/etc/php.d \
--enable-fpm \
--with-fpm-user=apache \
--with-fpm-group=apache \
--enable-mbstring \
--enable-xml \
--enable-bcmath \
--enable-sockets \
--enable-pcntl \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-openssl \
--with-curl \
--with-zlib \
--with-zip \
--with-gd \
--with-jpeg \
--with-freetype \
--enable-gd \
--with-gettext \
--with-mhash \
--enable-opcache \
--enable-intl \
--with-pear \
--disable-rpath \
--disable-debug
make -j$(nproc) && make install
# 配置文件
cp php.ini-production ${PREFIX}/php/etc/php.ini
# 編輯 php.ini:
# date.timezone = Asia/Shanghai
# expose_php = Off
# memory_limit = 256M
# post_max_size = 50M
# upload_max_filesize = 50M
# max_execution_time = 300
# 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
# PHP-FPM 配置
cp ${PREFIX}/php/etc/php-fpm.conf.default ${PREFIX}/php/etc/php-fpm.conf
cp ${PREFIX}/php/etc/php-fpm.d/www.conf.default ${PREFIX}/php/etc/php-fpm.d/www.conf
# 編輯 www.conf:
# pm = dynamic
# pm.max_children = 200
# pm.start_servers = 20
# pm.min_spare_servers = 10
# pm.max_spare_servers = 50
# pm.max_requests = 1000
# request_terminate_timeout = 300
# slowlog = /var/log/php-fpm-slow.log
# request_slowlog_timeout = 10
# 啟動腳本
cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm
chkconfig --add php-fpm
chkconfig php-fpm on
# 在 httpd-vhosts.conf 或 httpd.conf 中
SetHandler "proxy:fcgi://127.0.0.1:9000"
# 或目錄級
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
SetHandler "proxy:fcgi://127.0.0.1:9000"
# 重啟驗證
service httpd restart
service php-fpm restart
# 創建測試頁
echo '' > ${PREFIX}/httpd/htdocs/info.php
curl https://localhost/info.php | grep -i "php version"
# 1. 安裝依賴
yum -y install net-snmp net-snmp-utils rrdtool rrdtool-devel php-snmp php-xml php-mbstring php-gd php-ldap
# 2. 下載 Cacti
cd /usr/local/src
wget https://www.cacti.net/downloads/cacti-1.2.27.tar.gz
tar xzf cacti-1.2.27.tar.gz
mv cacti-1.2.27 ${PREFIX}/cacti
# 3. 數據庫準備
mysql -uroot -p -e "CREATE DATABASE cacti DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
mysql -uroot -p -e "GRANT ALL PRIVILEGES ON cacti.* TO 'cacti'@'localhost' IDENTIFIED BY 'CactiPassw0rd!'; FLUSH PRIVILEGES;"
mysql -uroot -p cacti < ${PREFIX}/cacti/cacti.sql
# 4. 配置 config.php
cp ${PREFIX}/cacti/include/config.php.sample ${PREFIX}/cacti/include/config.php
# 編輯:
$database_type = 'mysql';
$database_default = 'cacti';
$database_hostname = 'localhost';
$database_username = 'cacti';
$database_password = 'CactiPassw0rd!';
$database_port = '3306';
$database_ssl = false;
# 5. Apache 虛擬主機指向 Cacti
# DocumentRoot "${PREFIX}/cacti"
# ... Require all granted
# 6. 定時任務 (每分鐘輪詢)
echo "*/1 * * * * apache ${PREFIX}/php/bin/php ${PREFIX}/cacti/poller.php > /dev/null 2>&1" > /etc/cron.d/cacti
# 7. 權限調整
chown -R apache:apache ${PREFIX}/cacti/{rra,log,scripts,resource}
chmod -R 755 ${PREFIX}/cacti/{rra,log,scripts,resource}
# 8. 瀏覽器訪問 https://IP/cacti 完成安裝向導
# 默認用戶/密碼: admin / admin (首次登錄強制修改密碼)
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
socket = /usr/local/mysql/data/mysql.sock
pid-file = /usr/local/mysql/data/mysql.pid
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
default-storage-engine = InnoDB
innodb_buffer_pool_size = 4G # 物理內存 60-70%
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_read_io_threads = 8
innodb_write_io_threads = 8
max_connections = 2000
thread_cache_size = 100
table_open_cache = 4000
table_definition_cache = 2000
query_cache_type = 0
query_cache_size = 0
slow_query_log = 1
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
[client]
default-character-set = utf8mb4
socket = /usr/local/mysql/data/mysql.sock
ServerTokens Prod
ServerSignature Off
Timeout 60
KeepAlive On
MaxKeepAliveRequests 10000
KeepAliveTimeout 5
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 10000
# 安全頭
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
| 驗證項 | 命令/方法 | 預期結果 |
|---|---|---|
| MySQL 運行 | mysql -uroot -p -e "SELECT VERSION();" | 顯示版本號,無 ERROR 2002/2003 |
| Apache 語法 | ${PREFIX}/httpd/bin/apachectl -t | Syntax OK |
| PHP 模塊 | ${PREFIX}/php/bin/php -m | grep -E "mysqli|opcache|gd|curl" | 列出所需擴展 |
| PHP-FPM 連接 | netstat -ltnp | grep :9000 | LISTEN 狀態,進程 php-fpm |
| Cacti 輪詢 | 查看 ${PREFIX}/cacti/log/cacti.log | 無 FATAL/ERROR,有 POLLER 完成記錄 |
| 圖形生成 | 瀏覽器訪問 Cacti → Graphs → Local Linux Machine | CPU、內存、磁盤、網絡圖正常顯示 |
boost 缺失:下載對應版本 Boost 源碼,-DWITH_BOOST=path 指定。AH00558: Could not reliably determine the server's fully qualified domain name:設置 ServerName localhost:80。ERROR: unable to bind listening socket for address '127.0.0.1:9000': Address already in use:端口衝突,修改 www.conf listen = 127.0.0.1:9001 並同步 Apache 配置。poller.php 執行用戶權限、SNMP 社區名、防火牆 161/udp、RRDTool 路徑 (Cacti 設置 → Paths)。setsebool -P httpd_can_network_connect 1 (允許 Apache 連接 PHP-FPM/MySQL);chcon -R -t httpd_sys_content_t ${PREFIX}/cacti。源碼編譯安裝 LAMP + Cacti 雖步驟繁多,但賦予了**版本自主、模塊精簡、參數深度調優**的極致控制力。關鍵成功因素:
my.cnf, httpd.conf, php.ini, php-fpm.conf) 針對業務負載深度調優。建議將上述流程封裝為 Ansible Playbook 或 Shell 腳本,實現**基礎設施即代碼 (IaC)**,保證環境可復現、可審計、可版本控制。