詳解)
如果你已經(jīng)寫了幾年P(guān)HP可能早就習慣了集成環(huán)境一鍵裝好或者干脆把項目丟進容器里跑。但說句實話能把經(jīng)典的LAMP在Ubuntu上從零手動搭一遍的人和只會用管理面板的人遇到線上問題時的處理思路完全不一樣。這篇不是給剛?cè)腴TPHP的小白看的傻瓜式安裝說明而是給有基礎(chǔ)、想徹底搞明白Apache、MariaDB、PHP-FPM之間是怎么配合工作的進階開發(fā)者準備的實操記錄。整個搭建過程我會按真實項目的標準來走包括版本選擇、目錄規(guī)劃、權(quán)限控制、安全初始化、虛擬主機配置、故障排查每一步都會解釋為什么這么做。如果你之前只會在Windows上用某個集成軟件這次試著把心態(tài)切換到Linux運維視角收獲會大很多。1. LAMP依然值得手動搭建選型思路先理清1.1 LAMP四件套的角色分工LAMP是Linux、Apache、MariaDB/MySQL、PHP的組合縮寫。四者各司其職Linux是操作系統(tǒng)底座Apache負責接收HTTP請求并把靜態(tài)資源直接返回PHP模塊或PHP-FPM進程負責運行動態(tài)腳本MariaDB負責數(shù)據(jù)持久化存儲。理解這層分工很重要因為后續(xù)所有配置其實都是在解決四個組件如何正確對話的問題。舉個例子當瀏覽器請求一個PHP頁面時請求先到ApacheApache發(fā)現(xiàn)URI對應(yīng)的是.php文件會把請求轉(zhuǎn)交給PHP處理PHP執(zhí)行過程中可能需要查詢數(shù)據(jù)庫拿到結(jié)果后生成HTML返回給Apache再由Apache返回給瀏覽器。任何一個環(huán)節(jié)配置不對鏈路就斷。手動搭建的意義就在于你能親眼看到每一條配置指令到底作用在哪個環(huán)節(jié)。1.2 為什么不用集成環(huán)境或容器不是否定集成環(huán)境和容器而是它們各有適用場景。集成環(huán)境把Apache、PHP、MySQL打包在一起確實省事但你在生產(chǎn)服務(wù)器上遇到問題時往往需要對每個組件單獨調(diào)參這時候如果連組件之間怎么通信都不清楚排查效率會很低。容器的思路更先進但容器鏡像默認配置通常偏寬松也屏蔽了系統(tǒng)層面的很多細節(jié)。我的建議是本地開發(fā)用集成環(huán)境或容器都沒問題但如果你想成為能處理線上故障的開發(fā)者最好先在虛擬機或一臺閑置Ubuntu機器上手動搭建一次LAMP。這篇文章就是以這種生產(chǎn)思維來寫的下面的每一步都是按可持續(xù)維護的標準來做的。提示我這次的操作基于Ubuntu 22.04 LTS環(huán)境命令在其他LTS版本上基本通用。如果你用的是非LTS版本個別軟件源地址可能有差異不影響整體流程。2. 動手前的準備Ubuntu版本確認與環(huán)境初始化2.1 版本選擇與系統(tǒng)更新如果你手頭還沒有Ubuntu環(huán)境建議直接裝22.04 LTS或24.04 LTSLTS版本有五年以上安全更新適合做服務(wù)器。已經(jīng)裝有舊版本的先確認系統(tǒng)版本再決定要不要升級lsb_release -a可以順便看一下系統(tǒng)架構(gòu)正常都是amd64這點后面選PHP擴展包時用得上。確認版本之后第一件事是更新軟件源緩存和已有軟件包sudo apt update sudo apt upgrade -y這里有一個值得養(yǎng)成的好習慣把系統(tǒng)更新和業(yè)務(wù)軟件安裝分開執(zhí)行。因為生產(chǎn)環(huán)境上系統(tǒng)內(nèi)核或者基礎(chǔ)庫的升級可能會影響正在運行的PHP程序貿(mào)然全部升級有風險。但你剛裝的機器沒有業(yè)務(wù)壓力這時候一次性升到位最省心。2.2 創(chuàng)建專門的運行用戶與目錄規(guī)劃很多教程一上來就直接用root操作這確實簡單但存在安全隱患。PHP項目在root權(quán)限下運行的話一旦代碼出現(xiàn)任意文件寫入漏洞攻擊者可以直接控制整臺機器。正確的做法是創(chuàng)建一個普通用戶用來部署和運行Web服務(wù)。sudo useradd -m -s /bin/bash webapp sudo passwd webapp然后規(guī)劃目錄。我習慣用以下結(jié)構(gòu)sudo mkdir -p /var/www/myproject/{public,logs,storage}publicWeb根目錄存放入口文件如index.phplogs項目專屬日志獨立于系統(tǒng)日志storage業(yè)務(wù)緩存、上傳文件等運行期數(shù)據(jù)這個結(jié)構(gòu)雖然簡單但目錄語義清晰后面配置虛擬主機和設(shè)置權(quán)限時非常直觀。等系統(tǒng)里項目多了你會發(fā)現(xiàn)每個項目獨立目錄的人維護成本遠低于把所有內(nèi)容堆在某個默認目錄下。3. Apache安裝與配置的實操細節(jié)3.1 安裝Apache與默認目錄結(jié)構(gòu)Ubuntu的Apache包名是apache2安裝方式sudo apt install apache2 -y安裝完成后服務(wù)默認就是啟動的。檢查一下狀態(tài)sudo systemctl status apache2如果看到active (running)說明服務(wù)正常。Ubuntu下Apache的配置文件有自己的一套組織方式和源碼編譯安裝的Apache不太一樣新手很容易搞混。關(guān)鍵目錄如下/etc/apache2/apache2.conf主配置文件/etc/apache2/ports.conf監(jiān)聽端口配置/etc/apache2/sites-available/可用站點配置/etc/apache2/sites-enabled/已啟用站點配置通常是指向available目錄的軟鏈接/etc/apache2/mods-available/和/etc/apache2/mods-enabled/模塊配置目錄/var/log/apache2/日志目錄Ubuntu這種可用/啟用雙目錄設(shè)計本質(zhì)上是把Apache的模塊化配置進一步封裝成了站點級別的開關(guān)。啟用一個站點不是直接改配置文件而是執(zhí)行a2ensite命令創(chuàng)建軟鏈接禁用則用a2dissite。這個設(shè)計非常利于多站點管理。3.2 啟用關(guān)鍵模塊與配置虛擬主機Apache本身功能很克制很多能力都要通過模塊啟用。在LAMP場景下至少需要以下幾個模塊sudo a2enmod rewrite sudo a2enmod headers sudo a2enmod expiresrewriteURL重寫絕大多數(shù)PHP框架的偽靜態(tài)路由都依賴它headers設(shè)置HTTP響應(yīng)頭方便后續(xù)做安全加固expires靜態(tài)資源緩存控制模塊啟用的原理就是創(chuàng)建軟鏈接到mods-enabled所以修改后需要重啟Apache生效sudo systemctl restart apache2接下來是最核心的一步配置虛擬主機。我們的目標是讓Apache知道來自某個域名的請求要交給哪個目錄處理。打開默認站點配置看看Apache的默認寫法然后我們新建一個項目專屬的配置文件sudo nano /etc/apache2/sites-available/myproject.conf一個最基礎(chǔ)的PHP虛擬主機配置長這樣VirtualHost *:80 ServerName myproject.local ServerAlias www.myproject.local DocumentRoot /var/www/myproject/public Directory /var/www/myproject/public Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory ErrorLog ${APACHE_LOG_DIR}/myproject-error.log CustomLog ${APACHE_LOG_DIR}/myproject-access.log combined /VirtualHost這里有幾個容易忽略的點AllowOverride All必須開啟否則.htaccess文件不會生效很多PHP框架的路由會直接失效。DocumentRoot必須指向項目的public目錄而不是項目根目錄。這樣可以讓用戶無法直接訪問項目里的源碼文件、配置文件這是PHP項目部署的基本安全習慣。ServerName在本地測試時可以用自定義域名但需要同步修改本機的/etc/hosts文件。3.3 Apache配置容易踩的坑第一個坑是端口被占用。如果你本機之前裝過Nginx或者其他Web服務(wù)Apache啟動時可能報Address already in use。排查方法sudo netstat -tlnp | grep :80找到占用端口的進程要么停掉它要么改Apache監(jiān)聽端口。第二個坑是改了配置但沒生效。Apache的配置語法檢查命令是apachectl configtest這個命令在修改完配置文件之后建議必跑sudo apachectl configtest輸出Syntax OK才說明語法沒問題然后sudo systemctl reload apache2重載配置。注意改動配置用reload增刪模塊或者改動監(jiān)聽端口才需要restart區(qū)分清楚可以減少很多無謂的抖動。第三個坑是對目錄權(quán)限的誤解。Apache默認以www-data用戶運行如果項目的日志目錄屬主不是www-dataPHP寫入日志時就會報權(quán)限錯誤。這一點在后面第6章會詳細講。4. 數(shù)據(jù)庫層MariaDB安裝、初始化與賬號體系4.1 為什么選MariaDBMySQL和MariaDB在Ubuntu的軟件源里都有但默認安裝的往往是MariaDB。MariaDB是MySQL的開源分支API完全兼容PHP連接方式和MySQL一模一樣但我們團隊實際用下來MariaDB在并發(fā)寫入場景下的表現(xiàn)更穩(wěn)而且?guī)讉€關(guān)鍵性能參數(shù)的開源實現(xiàn)更透明。對個人開發(fā)者來說選哪個都行但如果你希望長期維護MariaDB默認配置更省心。不要糾結(jié)所謂的是不是MySQLPHP的PDO擴展通過mysql驅(qū)動連接MariaDB沒有任何問題這是完全兼容的。你在代碼里的new PDO(mysql:hostlocalhost;dbnamemyproject, ...)寫法不變。4.2 安裝與安全初始化安裝sudo apt install mariadb-server -yMariaDB在Ubuntu上的默認認證方式有時會讓人困惑——root用戶通過unix_socket插件認證也就是說只有系統(tǒng)root用戶或帶sudo的用戶能直接登錄數(shù)據(jù)庫root賬號。這樣的設(shè)計其實是更安全的數(shù)據(jù)庫root賬號不依賴密碼而是和操作系統(tǒng)用戶強綁定避免了空密碼或者弱密碼暴露在網(wǎng)絡(luò)上。查看服務(wù)狀態(tài)sudo systemctl status mariadb接下來運行安全初始化腳本sudo mysql_secure_installation腳本會問你幾個問題逐一說明Enter current password for root直接回車因為當前root走socket認證沒有密碼Switch to unix_socket authentication選擇Y保持現(xiàn)有的安全認證方式Change the root password這個看情況。如果root只在本機通過sudo登錄可以不設(shè)密碼但如果你的應(yīng)用確實需要遠程管理數(shù)據(jù)庫那就要單獨創(chuàng)建賬號而不是給root設(shè)密碼Remove anonymous usersYDisallow root login remotelyY這是必須的Remove test databaseYReload privilege tablesY這套交互式初始化其實是在幫你清理數(shù)據(jù)庫默認安裝的隱患刪除匿名用戶、刪除測試庫、禁止root遠程登錄。每一項都是安全基線生產(chǎn)環(huán)境務(wù)必要做。4.3 創(chuàng)建業(yè)務(wù)數(shù)據(jù)庫和最小權(quán)限賬號接下來的操作習慣我強烈建議所有PHP開發(fā)者都遵守不要用root賬號連接業(yè)務(wù)庫而是單獨創(chuàng)建一個權(quán)限受限的賬號。登錄數(shù)據(jù)庫sudo mariadb執(zhí)行以下SQLCREATE DATABASE myproject DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER myproject_userlocalhost IDENTIFIED BY 這里填一個高強度的密碼; GRANT ALL PRIVILEGES ON myproject.* TO myproject_userlocalhost; FLUSH PRIVILEGES;兩點說明myproject_userlocalhost表示該賬號只能從本機連接這個限制能避免數(shù)據(jù)庫賬號從外網(wǎng)被暴力破解。如果你的PHP應(yīng)用和數(shù)據(jù)庫在同一臺機器上這個配置是最優(yōu)解。ON myproject.*表示權(quán)限范圍只限myproject這個庫。不要隨手GRANT ALL ON *.*那等于給了賬號整個數(shù)據(jù)庫實例的權(quán)限一旦代碼注入攻擊者就能把整庫拖走。還有一個細節(jié)字符集用utf8mb4而不是utf8。雖然MySQL的utf8字符集看起來差不多但它最多存3字節(jié)的字符像Emoji這類4字節(jié)字符存不進去會導(dǎo)致線上報錯。utf8mb4是完整版的UTF-8從一開始就選它后面少很多麻煩。5. PHP的安裝與擴展版本選擇是重點5.1 PHP版本倉庫配置Ubuntu默認軟件源里帶的PHP版本往往偏保守。如果只是寫簡單的腳本默認版本夠用但如果你要跑現(xiàn)代PHP框架比如Laravel、Symfony就需要至少PHP 8.1以上的版本這時候建議添加第三方源。安裝軟件源管理工具和相關(guān)依賴sudo apt install software-properties-common -y sudo add-apt-repository ppa:ondrej/php -y sudo apt updateondrej/php源維護得很活躍包含多個PHP版本、所有官方擴展以及PHP-FPM。安裝PHP 8.3及常用擴展sudo apt install php8.3-fpm php8.3-mysql php8.3-cli php8.3-curl php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip php8.3-bcmath php8.3-intl -y這里每個擴展都有明確用途php8.3-mysql連數(shù)據(jù)庫的驅(qū)動必裝php8.3-curl請求外部接口的工具包很多SDK依賴它php8.3-gd圖像處理驗證碼這類功能要用php8.3-mbstring多字節(jié)字符串中文場景必裝php8.3-xmlXML解析很多框架的配置讀取依賴它php8.3-zip壓縮包處理Composer安裝依賴時需要php8.3-bcmath高精度數(shù)學運算涉及金額計算必裝php8.3-intl國際化組件做多語言站點需要安裝完之后可以確認一下版本php -v5.2 PHP核心擴展怎么選很多人不知道PHP擴展是分兩部分的一部分是編譯進PHP核心或者以模塊形式加載的另一部分是獨立的php8.3-xxx軟件包。上面的命令安裝的是Debian系打包好的擴展它們會自動注冊到PHP配置里。啟用或禁用擴展有兩個命令phpenmod mbstring # 啟用 phpdismod gd # 禁用但注意這個命令只是生成或刪除/etc/php/8.3/mods-available里的軟鏈接。真正生效的配置會分三種上下文Apache模塊、CLI命令行、PHP-FPM。它們的配置目錄是分開的/etc/php/8.3/apache2/Apache mod_php的配置/etc/php/8.3/cli/命令行PHP的配置/etc/php/8.3/fpm/PHP-FPM進程的配置這解釋了為什么很多新手改了php.ini卻不起作用——你可能改的是CLI的配置而Web請求走的是FPM的配置兩邊完全是獨立文件。進階開發(fā)者一定要記住改哪個上下文就改哪個目錄下的php.ini。查看當前加載的擴展php -m5.3 PHP-FPM與Apache的對接方式PHP運行模式有兩種常見選擇mod_phpApache模塊方式和PHP-FPM獨立進程管理器。mod_php簡單把PHP直接編譯進Apache性能在老場景下不錯但它與Apache進程生命周期綁定PHP出問題可能拖垮Apache多項目多版本也不好隔離。PHP-FPM的方式是PHP作為獨立進程池運行Apache通過FastCGI協(xié)議把請求轉(zhuǎn)發(fā)給PHP-FPM兩者之間通過Socket通信。這種方式隔離性更好也方便在同一臺機器上為不同項目啟用不同PHP版本。我在生產(chǎn)環(huán)境一律用PHP-FPM。啟用Apache的FastCGI模塊并配置PHP-FPMsudo a2enmod proxy_fcgi setenvif sudo a2enconf php8.3-fpm sudo systemctl restart apache2這里a2enconf是把PHP-FPM的Socket配置關(guān)聯(lián)進Apache。Ubuntu在安裝php8.3-fpm時其實已經(jīng)自動生成了大部分配置你只需要確認模塊和配置已啟用。檢查PHP-FPM狀態(tài)sudo systemctl status php8.3-fpm默認情況下PHP-FPM監(jiān)聽的是/run/php/php8.3-fpm.sock這個Socket文件。在虛擬主機配置里我們需要告訴Apache把.php請求交給這個Socket。這一步留到第6章一起做。6. 讓虛擬主機、PHP-FPM與權(quán)限體系協(xié)同工作6.1 虛擬主機配置詳解在完成Apache、PHP、MariaDB的安裝之后整個搭建的關(guān)鍵在于把它們串聯(lián)。繼續(xù)編輯myproject.confVirtualHost *:80 ServerName myproject.local ServerAlias www.myproject.local DocumentRoot /var/www/myproject/public Directory /var/www/myproject/public Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory # 將.php請求轉(zhuǎn)發(fā)給PHP-FPM FilesMatch \.php$ SetHandler proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost /FilesMatch # 禁止訪問隱藏文件 FilesMatch ^\. Require all denied /FilesMatch ErrorLog ${APACHE_LOG_DIR}/myproject-error.log CustomLog ${APACHE_LOG_DIR}/myproject-access.log combined /VirtualHost重點看FilesMatch里那行SetHandler proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost這段配置的意思是當Apache發(fā)現(xiàn)請求的文件以.php結(jié)尾就把請求通過php8.3-fpm.sock這個Unix Socket轉(zhuǎn)給PHP-FPM處理協(xié)議是FastCGI。如果你之前在別的教程里見過類似SetHandler proxy:fcgi://127.0.0.1:9000那是通過網(wǎng)絡(luò)端口通信的寫法兩種都可以但Socket方式比TCP端口方式更快、更安全因為不需要在網(wǎng)絡(luò)上暴露PHP端口。接下來啟用這個站點并禁用默認站點sudo a2ensite myproject.conf sudo a2dissite 000-default.conf sudo apachectl configtest sudo systemctl reload apache26.2 目錄權(quán)限與文件屬主的處理權(quán)限配置是整個部署里最容易出問題的地方。前面提到Apache以www-data用戶運行PHP-FPM默認也是www-data用戶所以項目目錄里需要讓www-data可寫的地方必須設(shè)置好屬主。我推薦的做法是按目錄職責區(qū)分權(quán)限sudo chown -R webapp:www-data /var/www/myproject/public sudo chmod 750 /var/www/myproject/public sudo chown -R www-data:www-data /var/www/myproject/logs /var/www/myproject/storagepublic的屬主是webapp、屬組是www-data這樣你平時可以用webapp賬號直接編輯代碼而Apache和PHP-FPM也能讀但不能隨意寫代碼目錄。logs和storage直接給www-data屬主因為PHP運行時要寫日志、寫緩存、傳文件。注意外層目錄的權(quán)限比如/var/www/myproject如果完全不可讀Apache也進不去子目錄。目錄逐級都要有執(zhí)行權(quán)限也就是x這是Linux權(quán)限和Windows權(quán)限的一個差異點。6.3 驗證整個LAMP鏈路在public目錄寫一個探針文件sudo -u webapp nano /var/www/myproject/public/index.php內(nèi)容?php phpinfo();然后本機hosts指向正確后瀏覽器訪問http://myproject.local如果能看到PHP探針頁面說明Apache和PHP-FPM已連通。接下來測試數(shù)據(jù)庫連接寫一個臨時腳本?php try { $pdo new PDO(mysql:hostlocalhost;dbnamemyproject;charsetutf8mb4, myproject_user, 你的密碼); echo Database connection OK; } catch (PDOException $e) { echo Connection failed: . $e-getMessage(); }如果輸出Database connection OK說明整個鏈路已經(jīng)通了一半。到此LAMP四層組件就全部串聯(lián)起來了。7. 上線前的安全加固與基礎(chǔ)性能優(yōu)化7.1 安全項逐項檢查搭建完成不等于可以直接上線至少要把下面的安全檢查做一遍1. 移除探針文件并使用生產(chǎn)配置剛才寫的臨時測試文件一定要刪phpinfo()會把當前的PHP配置、模塊、環(huán)境變量全部展示出來這是非常危險的信息泄露sudo rm /var/www/myproject/public/index.php同時把PHP的運行環(huán)境從development切換到productionsudo phpenmod -v 8.3 productionUbuntu的PHP包自帶了不同環(huán)境的配置生產(chǎn)配置會關(guān)閉display_errors避免錯誤信息直接暴露給用戶。2. 關(guān)閉目錄列表看Apache配置里Options IndexesIndexes表示允許顯示目錄文件列表。如果你的站點某個目錄下沒有默認索引文件訪問目錄URL就會列出所有文件這顯然不安全。建議把Indexes去掉Options FollowSymLinks3. 隱藏Apache版本號編輯/etc/apache2/conf-available/security.conf確認以下配置ServerTokens Prod ServerSignature Off這樣響應(yīng)頭里不會暴露完整的Apache版本號也減少了攻擊者探測服務(wù)器指紋的渠道。4. 數(shù)據(jù)庫賬號復(fù)查執(zhí)行SELECT user, host, plugin FROM mysql.user;檢查是否有奇怪的賬號尤其要確認root的host不是%允許任意主機登錄。如果發(fā)現(xiàn)異常及時清理權(quán)限。7.2 性能參數(shù)微調(diào)剛搭建完的LAMP默認配置是按通用場景給的針對PHP業(yè)務(wù)可以做幾項微調(diào)。PHP-FPM的進程管理配置在/etc/php/8.3/fpm/pool.d/www.conf。最關(guān)鍵的是以下三個參數(shù)pm dynamic pm.max_children 20 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 10max_children需要根據(jù)內(nèi)存估算。假設(shè)每個PHP-FPM進程平均占用約30-40MB內(nèi)存一臺2GB內(nèi)存的機器還要給MariaDB和Apache留余量max_children設(shè)在20左右比較安全。設(shè)置太大內(nèi)存不夠會導(dǎo)致OOM設(shè)置太小并發(fā)上來后請求排隊反而更慢。再說MariaDB默認配置適用小流量場景。如果你預(yù)期并發(fā)查詢比較多建議至少調(diào)整/etc/mysql/mariadb.conf.d/50-server.cnf里的緩沖池大小[mysqld] innodb_buffer_pool_size 256Minnodb_buffer_pool_size是InnoDB引擎的緩沖池負責緩存表數(shù)據(jù)和索引。調(diào)大它能讓熱數(shù)據(jù)留在內(nèi)存里減少磁盤IO。但也不是越大越好一般建議設(shè)為物理內(nèi)存的50%-70%左右比如4G內(nèi)存設(shè)2G。改完重啟MariaDBsudo systemctl restart mariadb8. 故障排查與維護命令速查8.1 常見問題定位方法整個LAMP鏈路里故障可能出在任何一層但排查有個固定順序先看進程狀態(tài)再看日志最后驗證配置。場景一網(wǎng)站返回500錯誤第一步看Apache錯誤日志sudo tail -f /var/log/apache2/myproject-error.log如果日志里出現(xiàn)關(guān)于/run/php/php8.3-fpm.sock的權(quán)限或連接錯誤多半是PHP-FPM沒啟動或者Socket路徑不匹配。執(zhí)行sudo systemctl status php8.3-fpm確認Socket文件存在且權(quán)限正確。ls -l /run/php/php8.3-fpm.sock如果屬主不是www-data需要檢查FPM配置里的listen.owner和listen.group。場景二MySQL連接被拒絕日志里出現(xiàn)SQLSTATE[HY000] [2002] Connection refused先確認MariaDB進程還活著sudo systemctl status mariadb再檢查端口監(jiān)聽sudo netstat -tlnp | grep 3306如果服務(wù)正常但連接還是失敗那就是賬號權(quán)限的問題?;氐降?章確認創(chuàng)建賬號的host是localhost而不是其他值。場景三URL重寫不生效訪問非根路由時出現(xiàn)404多半是AllowOverride沒開或者rewrite模塊沒啟用。逐個確認sudo apachectl -M | grep rewrite如果沒有輸出重新執(zhí)行sudo a2enmod rewrite并重啟Apache。場景四PHP擴展加載但代碼還是不認比如你明明裝了php8.3-mbstring但PHP代碼里調(diào)用mb_strlen()還是報未定義。此時要分清CLI和FPM兩套獨立環(huán)境php -m | grep mbstring # CLI環(huán)境 sudo php -i | grep Loaded Configuration # 確認CLI配置路徑 curl -I http://myproject.local # 確認Web環(huán)境是否走了FPM用探針文件確認Web環(huán)境實際加載的擴展列表別只看命令行結(jié)果。8.2 日常維護命令清單把常用的系統(tǒng)操作整理成一張速查表會顯著提高日常維護效率操作場景命令查看Apache狀態(tài)sudo systemctl status apache2重載Apache配置sudo systemctl reload apache2檢查Apache配置語法sudo apachectl configtest查看PHP-FPM狀態(tài)sudo systemctl status php8.3-fpm重啟PHP-FPMsudo systemctl restart php8.3-fpm查看MariaDB狀態(tài)sudo systemctl status mariadb排查端口占用sudo netstat -tlnp | grep :80查看PHP已加載擴展php -m跟蹤錯誤日志sudo tail -f /var/log/apache2/myproject-error.log清理apt緩存sudo apt clean還有一件事情值得做啟用Ubuntu的自動安全更新。這條只對服務(wù)器有實際意義本地開發(fā)無所謂sudo dpkg-reconfigure --prioritylow unattended-upgrades選擇啟用即可。安全補丁日常不會打擾人但它能在漏洞公開后的第一時間自動修復(fù)系統(tǒng)組件這對長期運行的項目是很重要的保障。一點總結(jié)和我的個人習慣LAMP在今天的生態(tài)里看起來有點“老派”但它仍然承載著大量真實業(yè)務(wù)。手動搭建這套環(huán)境你收獲的不只是一個能跑PHP的服務(wù)器而是對組件邊界、通信方式、權(quán)限模型都建立起了整體認知。之后不管是排查性能瓶頸還是把服務(wù)遷移到容器或云主機你都能更快定位問題在哪一層。最后分享一個小經(jīng)驗我在配置文件里寫注釋的習慣是從手動搭建LAMP時養(yǎng)成的。每改一行注釋里寫清楚這行的作用和改動日期。三個月后再回去看你大概率會感謝當時的自己。如果你按這篇教程順利跑通了建議再拿一臺新機器閉卷練一遍過程中卡住的步驟就是你需要補的知識點。