跳转到帖子
在手机APP中查看

一个更好的浏览方法。了解更多

PHP论坛人

主屏幕上的全屏APP,带有推送通知、徽章等。

在iOS和iPadOS上安装此APP
  1. 在Safari中轻敲分享图标
  2. 滚动菜单并轻敲添加到主屏幕
  3. 轻敲右上角的添加按钮。
在安卓上安装此APP
  1. 轻敲浏览器右上角的三个点菜单 (⋮) 。
  2. 轻敲添加到主屏幕安装APP
  3. 轻敲安装进行确认。

Debian 13 系統資源限制調校 Part 2 全域核心優化

精选回复

Debian 13 系統資源限制調校 Part 2 全域核心優化



之前Debian 13配置時,已做了Part 1

Debian 13 系統資源限制調校 Part 1 (VPS 2C/2GB RAM)
https://phpforumer.com/topic/1290/



現在 LNMP 配置完後,接續修改Part 2





----------------------------------------
全域核心 sysctl 優化
----------------------------------------

強烈建議:不要直接修改 /etc/sysctl.conf,以避免系統更新時覆蓋設定

Debian支援在 /etc/sysctl.d/ 目錄下放置獨立的設定檔,便於版本管理與追蹤



建立專用設定檔
vi /etc/sysctl.d/99-lnmp-optimization.conf



寫入以下內容




# ===== 系統級別檔案處理 =====
# 整個系統可以開啟的最大檔案描述符總數
# 必須大於所有服務的 LimitNOFILE 設定值之總和
fs.file-max = 2097152


# 單一行程可分配的最大檔案描述符數量上限
# 此值必須 >= 任何服務的 LimitNOFILE 設定值
fs.nr_open = 2097152


# ===== 網路效能調校 =====
# BBR + 網路優化 已寫在 /etc/sysctl.d/99-network-optimization.conf



# ===== 虛擬記憶體調校 =====
# 降低 Swap 使用傾向(0=盡量不用 Swap,100=積極使用)
# 2GB VPS 建議設為 10,優先保留記憶體給應用程式
# vm.swappiness = 10


# 降低 dirty page 寫回比例,避免 I/O 突刺
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5







儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter






立即套用核心參數 (無需重開機)

sysctl -p /etc/sysctl.d/99-lnmp-optimization.conf



-------------------------
驗證是否已套用
-------------------------

sysctl fs.file-max



# 降低Swap使用傾向,沒修改,則顯示預設 = 60
sysctl vm.swappiness







------------------------------------------
服務級別限制調校 systemd Override
------------------------------------------

這是整個調校的核心。使用 systemd override 的方式,可避免服務套件更新時覆蓋自訂設定

重要:/etc/security/limits.conf 對 systemd 管理的服務無效

MariaDB、Nginx、PHP-FPM 均須透過各自的 override.conf 設定資源限制


以下設定以 2 vCPU / 2GB RAM VPS 為基準,請依實際監控數據微調







----------------------
MariaDB 資料庫
----------------------

mkdir -p /etc/systemd/system/mariadb.service.d/


編輯
vi /etc/systemd/system/mariadb.service.d/override.conf



寫入以下內容



[Service]
# ===== 檔案描述符限制 =====
# 資料庫需要處理大量連線與資料檔案,此值應設定足夠高
LimitNOFILE=65535
LimitNPROC=65535

# ===== 記憶體限制 =====
# MemoryMax:絕對硬上限,超過即被 OOM Killer 終止
# MemoryHigh:軟性高水位,超過時系統會積極嘗試回收記憶體
MemoryMax=1536M
MemoryHigh=1280M


# ===== CPU 限制 =====
# 限制 CPU 使用率,避免資料庫查詢佔用所有 CPU 資源
# 2 vCPU 環境:CPUQuota=80% 表示最多使用 0.8 顆核心
# 若要充分利用兩顆核心,可調整為 160%
CPUQuota=160%


# ===== I/O 優先級 =====
# 提高資料庫的磁碟 I/O 優先級
# IOSchedulingClass=2 為 Best Effort(cfq/bfq 排程器)
# IOSchedulingPriority 範圍 0(最高)~ 7(最低),4 為中等偏高
IOSchedulingClass=2
IOSchedulingPriority=4

# ===== 穩定性策略 =====
# 服務崩潰後自動重啟,RestartSec 為等待秒數
Restart=always
RestartSec=10s

# ===== 其他系統限制 =====
# 允許記憶體鎖定(mlock),避免關鍵資料被 Swap 出去
# 對 InnoDB Buffer Pool 等效能敏感操作有幫助
LimitMEMLOCK=infinity

# 堆疊大小(單位:位元組,此處為 10MB)
LimitSTACK=10485760






儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter



-----------------------
Nginx 網頁伺服器
-----------------------


mkdir -p /etc/systemd/system/nginx.service.d/


編輯
vi /etc/systemd/system/nginx.service.d/override.conf




寫入以下內容



[Service]
# ===== 檔案描述符限制 =====
# 每個 HTTP 連線、靜態檔案、upstream 連線、Log 檔案都需要計入
LimitNOFILE=65535
LimitNPROC=65535

# ===== 記憶體限制 =====
# Nginx 以事件驅動架構著稱,記憶體用量很低
# 但仍需設定上限防止記憶體洩漏時無限成長
MemoryMax=512M
MemoryHigh=384M

# ===== CPU 限制 =====
# 靜態檔案服務 CPU 消耗較低,動態代理時消耗稍高
CPUQuota=50%

# ===== 穩定性策略 =====
Restart=always
RestartSec=5s






儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter




------------------------
PHP-FPM
------------------------


mkdir -p /etc/systemd/system/php8.4-fpm.service.d


編輯
vi /etc/systemd/system/php8.4-fpm.service.d/override.conf



寫入以下內容




[Service]
# ===== 檔案描述符限制 =====
# PHP-FPM 可能同時連接資料庫、Redis、Session 儲存等多個外部資源
LimitNOFILE=65535
LimitNPROC=65535

# ===== 記憶體限制 =====
# PHP 動態內容處理是記憶體消耗主要來源之一
# 此限制為 PHP-FPM master + 所有 worker 行程的記憶體總和
MemoryMax=768M
MemoryHigh=512M

# ===== CPU 限制 =====
# PHP 腳本執行 (模板渲染、資料庫查詢組裝) 對CPU消耗較高
CPUQuota=70%

# ===== 穩定性策略 =====
Restart=always
RestartSec=10s






儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter



------------------------
套用、驗證與監控
------------------------

設定完成後,必須依序執行以下步驟使設定生效


套用設定並重啟服務

重新載入 systemd 配置 (讓 systemd 讀取新增的 override 檔案)

systemctl daemon-reload





依序重啟所有服務

systemctl restart mariadb


systemctl restart nginx


systemctl restart php8.4-fpm





確認服務狀態

systemctl status mariadb


systemctl status nginx


systemctl status php8.4-fpm


每個服務都應顯示 active (running)






----------------------
驗證限制是否生效
----------------------

重要:查看 /proc/<PID>/limits 才是確認設定是否真正生效的唯一標準,而非查看設定檔本身

驗證各服務的檔案描述符限制 Max open files 應為 65535



MariaDB
cat /proc/$(pgrep -o mariadbd)/limits | grep "Max open files"


驗證檔案描述符限制 Max open files 應為 65535




Nginx (取 master process PID)
cat /proc/$(pgrep -o nginx)/limits | grep "Max open files"

驗證檔案描述符限制 Max open files 應為 65535




PHP-FPM (取 master process PID)
cat /proc/$(pgrep -o php-fpm)/limits | grep "Max open files"

驗證檔案描述符限制 Max open files 應為 65535






使用 systemd 指令查看詳細屬性

systemctl show mariadb | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"



systemctl show nginx | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"



systemctl show php8.4-fpm | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"





查看核心檔案描述符使用狀況

查看
cat /proc/sys/fs/file-nr


輸出:已使用      未使用      最大值




------------------
安裝監控工具
------------------


安裝監控工具

apt update && apt install -y htop iotop iftop nethogs lsof



即時查看 CPU / 記憶體 / 行程使用量
htop


監控磁碟 I/O 使用狀況
iotop


即時網路流量監控
iftop


依行程分類顯示網路流量
nethogs


計算特定行程目前開啟的檔案數
lsof -p <PID> \| wc -l








----------------------
設定日誌輪替
----------------------

避免日誌檔案無限增長而佔滿磁碟空間,這是生產環境容易忽略的維運重點



建立
vi /etc/logrotate.d/lnmp


貼上內容


/var/log/mysql/*.log
/var/log/nginx/*.log
/var/log/php8.4-fpm.log
{
    daily           # 每天輪替
    rotate 30       # 保留 30 天份日誌
    missingok       # 日誌檔遺失時不報錯
    compress        # 壓縮舊日誌(使用 gzip)
    delaycompress   # 延遲一次壓縮,確保服務釋放舊檔案後再壓縮
    notifempty      # 日誌為空則不執行輪替
    create 0640 www-data adm  # 建立新日誌檔的權限與擁有者
    sharedscripts   # 所有日誌輪替完成後,只執行一次 postrotate

    postrotate
        # 通知服務重新開啟日誌檔(發送 USR1 訊號)
        [ -f /var/run/mysqld/mysqld.pid ] && kill -USR1 $(cat /var/run/mysqld/mysqld.pid) 2>/dev/null || true
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid) 2>/dev/null || true
    endscript
}




儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter




--------------------------------
測試 logrotate 設定是否正確
--------------------------------

測試 logrotate 設定是否正確 (加上 --debug 不實際執行)

logrotate --debug /etc/logrotate.d/lnmp



----------------------------------------------
2GB RAM VPS 記憶體配置建議
----------------------------------------------

MariaDB
768MB ~ 1024MB
記憶體消耗大戶,InnoDB Buffer Pool 需足夠大


PHP-FPM
512MB
依 worker 數量與每個 worker 的 memory_limit 決定


Nginx
256MB
極低,事件驅動架構


Redis (選用)
128MB
用於 Session 或頁面快取


系統及其他
384MB
OS 核心、SSH、Cron 等


合計 約 2GB



重要提醒:systemd 的 MemoryMax 設定值總和可以略高於實體記憶體,但若所有服務同時達到尖峰,仍可能觸發 OOM Killer 強制終止行程

請務必根據實際監控數據進行微調,切勿照單全收



-------------------------
論壇部署最終檢查清單
-------------------------

完成所有設定後,請逐項確認:

系統基礎

/etc/security/limits.conf 已針對所有使用者設定完成
Swap 空間已建立並設定開機自動掛載
/etc/sysctl.d/99-lnmp-optimization.conf 已建立,核心參數已套用 sysctl -p
防火牆 已啟用,僅開放 22、80、443 連接埠


服務設定

MariaDB、Nginx、PHP-FPM 的 systemd override.conf 均已正確建立
執行 systemctl daemon-reload 並已重啟所有服務
三個服務的 systemctl status 均顯示 active (running)
使用 cat /proc/<PID>/limits 驗證每個服務的 Max open files 均為 65535


安全性

已變更 MariaDB 的 root 密碼,並移除匿名帳號與測試資料庫 mysql_secure_installation
Nginx 已關閉版本號顯示 server_tokens off
PHP 已設定 expose_php = Off、display_errors = Off
已確認 AppArmor 或 SELinux 狀態不會阻擋服務運作
HTTPS TLS/SSL 已設定


維運

日誌輪替 logrotate 設定已完成並通過 --debug 測試
資料庫、網站檔案、設定檔的自動化備份策略已建立  (如 cron + rsync 或 borgbackup)
基礎監控告警已設定 (如 netdata、prometheus + node_exporter、或被動式監控服務)
快速狀態檢查腳本 /root/check-lnmp-limits.sh 已建立並可正常執行







---------------
常見問題
---------------


Q1: 修改了 /etc/security/limits.conf,為什麼重啟 MariaDB 後,查看 /proc/pid/limits 還是沒變?

因為 MariaDB 是由 systemd 管理的服務,它不會讀取 limits.conf

你必須在對應的 systemd override.conf 中設定 LimitNOFILE





Q2: 如何快速確認目前整個系統或特定服務開啟了多少檔案?


系統整體
cat /proc/sys/fs/file-nr


輸出: 已分配數  未使用數  總上限




查看特定服務 (以 nginx master process 為例) 開啟了多少檔案
lsof -p $(pgrep -o nginx) 2>/dev/null | wc -l







Q3: 修改了 systemd override 並 daemon-reload 重啟後,服務卻無法啟動了,怎麼辦?

查看錯誤日誌
journalctl -u mariadb -xe --no-pager


檢查服務狀態
systemctl status mariadb


驗證 systemd 讀取到的限制值
systemctl show mariadb | grep -i "limitnofile\|memory"


常見原因:

override.conf 語法錯誤 如多餘空格、缺少區段標頭 [Service]

設定了不支援的參數名稱

MemoryMax 值設得太小,服務一啟動就因超限而被終止

服務名稱與實際安裝的版本不符 (如 PHP 版本號)




Q4:CPUQuota 設定的百分比是相對於什麼?

CPUQuota=80% 表示允許使用最多 80% 的單顆CPU核心時間

若VPS有2顆 vCPU,則 CPUQuota=160% 才等於充分利用兩顆核心

請依VPS實際核心數調整



Q5:MemoryMax 和 MemoryHigh 有什麼差別?

MemoryHigh 軟性高水位。超過後,系統會積極嘗試回收該服務的記憶體,但不會強制終止服務

MemoryMax 絕對硬上限。超過後,服務內的行程會被 OOM Killer 立即終止

建議將 MemoryHigh 設為 MemoryMax 的 80~85%,讓系統有空間提前介入,避免觸及硬上限



Q6:MariaDB 無法啟動

可能原因與解決方法:

查看錯誤日誌
journalctl -u mariadb -n 50

驗證設定檔語法
mariadbd --validate-config

若調整 innodb_log_file_size 後發生錯誤,刪除舊的 redo log 讓 MariaDB 重建
systemctl stop mariadb
rm /var/lib/mysql/ib_logfile*
systemctl start mariadb


檢查資料目錄權限
ls -la /var/lib/mysql
chown -R mariadb:mariadb /var/lib/mysql




Q7:Too many connections 錯誤

暫時調高連線數(立即生效)
sudo mariadb -e "SET GLOBAL max_connections = 150;"

查看閒置連線
sudo mariadb -e "SHOW PROCESSLIST;"

終止閒置過久的連線
sudo mariadb -e "SHOW PROCESSLIST;" | grep Sleep | awk '{print "KILL "$1";"}' | mysql


永久調整請修改 50-server.cnf 中的 max_connections 後重啟服務

提示:應用端建議實作連線池 (如 PHP PDO persistent connection),可大幅降低連線開銷




Q8:磁碟空間持續增加

檢查磁碟使用
df -h
du -sh /var/lib/mysql/


檢查 Binary Log 使用狀況
sudo mariadb -e "SHOW BINARY LOGS;"


手動清除 7 天前的 Binary Log
sudo mariadb -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"

檢查日誌大小
ls -lh /var/log/mysql/


若完全不需要主從複製,可將 50-server.cnf 中 log-bin 相關行全部註解掉





Q9:innodb_buffer_pool_size 設定後發生 OOM

檢查記憶體使用
free -h
top -o %MEM

2 GB 總記憶體建議 innodb_buffer_pool_size = 768M,並為系統 + 其他服務保留至少 512 MB

若系統頻繁使用 Swap,應考慮升級記憶體或降低 buffer pool






Q10:設定檔改了但未生效

確認目前生效的設定
mariadbd --print-defaults


找出所有載入的設定檔路徑
mariadbd --help --verbose | grep -A 1 "Default options"


確認修改的檔案是否在載入列表中,再重新啟動
systemctl daemon-reload
systemctl restart mariadb


確認特定參數
sudo mariadb -e "SHOW VARIABLES LIKE '參數名稱';"

-----------------------

快速健康檢查腳本

-----------------------

建立

vi /root/mysql_healthcheck.sh

貼上以下內容

mysql_healthcheck.sh

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter


------------------
賦予執行權限
------------------

賦予執行權限
chmod 700 /root/mysql_healthcheck.sh


chown root:root /root/mysql_healthcheck.sh




執行腳本
/root/mysql_healthcheck.sh



--------------------------
crontab 定時任務
--------------------------


設定每小時定期執行

crontab -e

加入以下行

0 * * * * /root/mysql_healthcheck.sh >> /var/log/mysql_health.log 2>&1





儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter

-----------------

快速檢查腳本

-----------------

將以下腳本儲存為 /root/check-lnmp-limits.sh,方便日後快速檢查系統狀態

編輯

vi /root/check-lnmp-limits.sh

貼上以下內容

check-lnmp-limits.sh

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter

賦予執行權限
chmod 700 /root/check-lnmp-limits.sh


chown root:root /root/check-lnmp-limits.sh



執行腳本
/root/check-lnmp-limits.sh

本帖最后于,由Jack编辑

创建帐户或登录后发表意见

帐户

导航

搜索

配置浏览器推送通知

Chrome (安卓)
  1. 轻敲地址栏旁的锁形图标。
  2. 轻敲权限 → 通知。
  3. 调整你的偏好。
Chrome (台式电脑)
  1. 点击地址栏中的挂锁图标。
  2. 选择网站设置。
  3. 找到通知选项并调整你的偏好。