

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WordPress筆記 &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/category/wp/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Tue, 31 Mar 2026 05:02:59 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/max-stackoverflow-256.png</url>
	<title>WordPress筆記 &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>用 AI 修改原作者 theme改版</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 05:02:58 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8211</guid>

					<description><![CDATA[希望可以把改動的部份寫成一個 python sc...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="558" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1024x558.jpg" alt="" class="wp-image-8212" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1024x558.jpg?v=1774933354 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-600x327.jpg?v=1774933354 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-768x419.jpg?v=1774933354 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1536x837.jpg?v=1774933354 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g.jpg?v=1774933354 1970w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>希望可以把改動的部份寫成一個 python script 給我進行 patch.</p>



<p>目前的設定是 max-width: 75rem; (1200px)，若扣除內距或特定的瀏覽器渲染，體感寬度確實接近 1150px。要提升到1280px，我們需要將其改為 80rem (1280 / 16 = 780)。</p>



<p>這是一個進階版的 Python 腳本，它會自動掃描伺服器路徑（如 /var/www/），尋找所有名為 gutenshop 的主題目錄，並統一對其<br>foundation.css 進行寬度補丁。<br><br>✦ 我現在就在當前目錄為您產生 patch_gutenshop.py 實體檔案</p>



<pre class="wp-block-code"><code>import os
import re
import sys

def patch_gutenshop_width(base_path='.'):
    """
    自動尋找並修改所有 gutenshop 主題的寬度限制。
    目標寬度: 1280px (80rem)
    """
    # 目標檔案在主題內的相對路徑
    target_rel_path = os.path.join('css', 'foundation.css')
    found_count = 0
    patched_count = 0

    print(f"開始掃描目錄: {os.path.abspath(base_path)}")
    print("-" * 50)

    # 遍歷目錄尋找所有名為 gutenshop 的主題目錄
    for root, dirs, files in os.walk(base_path):
        if os.path.basename(root) == 'gutenshop':
            full_file_path = os.path.join(root, target_rel_path)
            
            if os.path.exists(full_file_path):
                found_count += 1
                print(f"找到目標: {full_file_path}")
                
                try:
                    with open(full_file_path, 'r', encoding='utf-8') as f:
                        content = f.read()

                    # 將 75rem (1200px) 替換為 80rem (1280px)
                    # 使用正則表達式鎖定 max-width: 75rem
                    new_content = re.sub(r'max-width:\s*75rem', 'max-width: 80rem', content)

                    if content == new_content:
                        # 檢查是否已經是 80rem，避免誤報
                        if 'max-width: 80rem' in content:
                            print("  &#91;跳過] 寬度已經是 1280px (80rem)")
                        else:
                            print("  &#91;跳過] 檔案中未找到 max-width: 75rem 設定")
                    else:
                        with open(full_file_path, 'w', encoding='utf-8') as f:
                            f.write(new_content)
                        patched_count += 1
                        print("  &#91;成功] 已將寬度修正為 1280px (80rem)")
                
                except Exception as e:
                    print(f"  &#91;錯誤] 無法讀寫檔案: {e}")
            
    print("-" * 50)
    print(f"掃描結束。共找到 {found_count} 個主題，成功補丁 {patched_count} 個檔案。")

if __name__ == "__main__":
    # 如果執行時有帶參數，則以參數為搜尋路徑，否則預設為當前路徑 '.'
    search_dir = sys.argv&#91;1] if len(sys.argv) > 1 else '.'
    
    # Linux 權限提示
    if os.name != 'nt' and hasattr(os, 'getuid') and os.getuid() != 0:
        print("提示：在 Linux 伺服器上建議使用 sudo 權限執行以確保檔案可寫入。")
        
    patch_gutenshop_width(search_dir)
</code></pre>



<p>使用方式：</p>



<p>本機測試：直接執行 python patch_gutenshop.py，它會掃描當前目錄。</p>



<p>伺服器大量修改：將此檔案上傳至伺服器，並指定掃描路徑：</p>



<pre class="wp-block-code"><code>sudo python3 patch_gutenshop.py /var/www </code></pre>



<p>此腳本會尋找所有路徑下包含 gutenshop 的目錄，並修改其 css/foundation.css 中的 max-width: 75rem 為 max-width: 80rem (1280px)。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cloudflare Security rules 「保護敏感目錄，但又不誤殺正常圖片」且「排除多個網段與 IP」</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/cloudflare-security-rules-block-ip/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/cloudflare-security-rules-block-ip/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 17 Mar 2026 07:19:05 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[cloudflare]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7991</guid>

					<description><![CDATA[如果你希望達到「保護敏感目錄，但又不誤殺正常圖片...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="693" height="1024" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j-693x1024.jpg?v=1773731872" alt="" class="wp-image-7993" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j-693x1024.jpg?v=1773731872 693w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j-406x600.jpg?v=1773731872 406w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j-768x1134.jpg?v=1773731872 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j-1040x1536.jpg?v=1773731872 1040w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/chrome_2026-03-17-15-00-1j.jpg?v=1773731872 1093w" sizes="(max-width: 693px) 100vw, 693px" /></figure>



<p>如果你希望達到「保護敏感目錄，但又不誤殺正常圖片」且「排除多個網段與 IP」的效果，你需要修改原本的運算式。</p>



<p>目前的規則因為使用了 wildcard 且沒有限制檔案類型，會導致該資料夾下所有東西（含圖片、CSS、JS）都被封鎖。</p>



<h3 class="wp-block-heading">推薦的 Expression 寫法</h3>



<p>請在 Cloudflare WAF 規則編輯頁面點擊 <strong>Edit expression</strong>，並將以下內容貼入：</p>



<p>Plaintext</p>



<pre class="wp-block-code"><code>(
  (http.request.uri.path contains "/wp-includes/" and not http.request.uri.path contains ".js" and not http.request.uri.path contains ".css" and not http.request.uri.path contains ".gif") 
  or 
  (http.request.uri.path contains "/wp-content/uploads/" and http.request.uri.path contains ".php")
) 
and not (ip.src in {140.0.0.0/8 1.1.1.1})
</code></pre>



<p><em>請將 1.1.1.1 替換為你實際的其他管理 IP。</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">邏輯重點說明</h3>



<ul class="wp-block-list">
<li><strong>精準防禦 wp-includes</strong>：這個目錄通常不應該被直接存取 PHP 檔案。但我排除了 <code>.js</code> 與 <code>.css</code>，因為有些佈景主題或外掛會需要載入這裡的靜態資源，這樣寫可以避免網站版面壞掉。</li>



<li><strong>uploads 目錄只擋 PHP</strong>：針對 <code>/wp-content/uploads/</code>，我們只封鎖 <code>.php</code> 檔案。這能精準擋掉上傳漏洞（Webshell），同時讓你所有的 <code>.jpg</code>、<code>.png</code> 圖片都能正常顯示。</li>



<li><strong>白名單機制</strong>：後方的 <code>and not (ip.src in { ... })</code> 會把你的 140 網段和其他指定 IP 排除在規則之外，讓你擁有最高權限。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">設定後的檢查清單</h3>



<ol start="1" class="wp-block-list">
<li><strong>檢查圖片</strong>：點擊你之前貼的那張圖片連結，確認是否能正常開啟。</li>



<li><strong>檢查 VPS 負載</strong>：回到終端機輸入 <code>top</code>。
<ul class="wp-block-list">
<li>如果 <strong>load average</strong> 降到 <strong>1.0 ~ 2.0</strong> 之間。</li>



<li>如果 <strong>%Cpu(s)</strong> 的 <strong>id (idle)</strong> 數值增加。</li>



<li>如果 <strong>php-fpm</strong> 的進程數量明顯減少。</li>
</ul>
</li>
</ol>



<p>這代表你的 WAF 已經在第一線發揮作用，把攻擊擋在 Cloudflare，你的伺服器終於可以「休息」處理正常的請求了。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/cloudflare-security-rules-block-ip/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cloudflare 的 Rocket Loader 與你的 React 代碼發生了衝突</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/cloudflare-rocket-loader-react/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/cloudflare-rocket-loader-react/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 12 Feb 2026 13:33:10 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[cloudflare]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7784</guid>

					<description><![CDATA[你的網頁變白，是因為 Cloudflare 的 ...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="207" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma-1024x207.jpg?v=1770902864" alt="" class="wp-image-7785" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma-1024x207.jpg?v=1770902864 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma-600x121.jpg?v=1770902864 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma-768x155.jpg?v=1770902864 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma-1536x311.jpg?v=1770902864 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-12_21-27_ma.jpg?v=1770902864 1775w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>你的網頁變白，是因為 Cloudflare 的 <strong>Rocket Loader</strong> 與你的 React 代碼發生了衝突。Rocket Loader 的原理是延遲所有 JavaScript 的執行，來讓網頁載入看起來變快。</p>



<p>但你的程式碼使用了 <code>@babel/standalone</code> 在瀏覽器現場解析 React。當 Rocket Loader介入時，它會打亂腳本執行的順序。原本應該先由 Babel 解析的代碼，可能因為順序錯亂而沒被處理，導致瀏覽器看不懂 <code>&lt;App /&gt;</code> 這種 JSX 語法，最後就卡死在空白畫面。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">解決方法：關閉 Rocket Loader</h2>



<p>最直接的解決方式是在 Cloudflare 控制台關閉這個功能。這是一個常見的坑，特別是對於直接在 HTML 寫 React 的專案。</p>



<ol start="1" class="wp-block-list">
<li>登入 Cloudflare 後台，選擇你的網域。</li>



<li>點擊左側選單的 <strong>Speed（速度）</strong> -> <strong>Optimization（最佳化）</strong>。</li>



<li>在標籤分頁中找到 <strong>Content Optimization</strong>。</li>



<li>將 <strong>Rocket Loader</strong> 選項切換為 <strong>Off（關閉）</strong>。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">另一種解法：略過特定腳本</h2>



<p>如果你想保留 Rocket Loader 的其他功能，只想讓 React 正常運作，你可以告訴 Cloudflare 不要動你的腳本。</p>



<p>在你 HTML 裡所有的 <code>&lt;script&gt;</code> 標籤中，加入 <code>data-cfasync="false"</code>。例如：</p>



<pre class="wp-block-code"><code><code>&lt;script data-cfasync="false" src="..."&gt;&lt;/script&gt;</code></code></pre>



<p>這樣 Cloudflare 就會跳過這些腳本，按照原本的順序執行，React 就能正常渲染畫面。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">對網站速度的直覺影響</h2>



<p>關閉 Rocket Loader 後，最明顯的變化是 WordPress 的 JavaScript 檔案會回到「原始載入順序」。如果你的佈景主題或外掛（例如投影片、彈出視窗）使用了大量的腳本，網頁在載入初期可能會感覺稍微慢一點點，因為瀏覽器必須先下載並執行這些 JS 檔案。</p>



<p>不過，這對於 WordPress 來說通常是更安全的做法。Rocket Loader 雖然能提高跑分數據，但它經常會導致某些功能失靈，比如選單點不開、聯絡表單送不出，或是像你剛才遇到的 React 畫面變白。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">穩定性會大幅提升</h2>



<p>WordPress 是一個由多種外掛組合起來的系統。很多外掛在寫代碼時，會假設某些資源（如 jQuery）是第一個載入的。Rocket Loader 為了求快，會強行改變這個規則。</p>



<p>關閉它之後，你的 WordPress 網站會變得更穩定。你不再需要擔心更新了某個外掛後，網站突然版面亂掉或功能失效。對於企業用的打卡管理系統來說，穩定性絕對比那零點幾秒的跑分差距更重要。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">其他補償方案</h2>



<p>如果你擔心關閉後速度變慢，WordPress 還有很多更好的優化方式。你可以使用快取外掛（如 WP Rocket 或 W3 Total Cache）來進行檔案壓縮（Minify）和延遲載入。</p>



<p>這些外掛比 Cloudflare 的 Rocket Loader 更了解 WordPress 的結構，處理起來會更細緻。你也可以保留 Cloudflare 的其他功能，例如 CDN 加速和內容快取，這些對速度的幫助依然很大，且不會像 Rocket Loader 那樣容易造成腳本衝突。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">建議的操作步驟</h2>



<p>既然你目前的打卡系統出現了白畫面，我強烈建議先關掉它。關閉後，請先清除瀏覽器快取再重新開啟網頁。</p>



<p>如果你發現 WordPress 真的慢了很多，我們可以再透過調整 <code>functions.php</code> 或是使用專業的優化外掛來補救。對於開發者來說，能掌握程式碼的執行順序，遠比交給 Cloudflare 自動處理來得安心。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/cloudflare-rocket-loader-react/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>1CPU+1GB RAM 的 WordPress 主機效能瓶頸與優化</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/1cpu-1gb-ram-wordpress-vps/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/1cpu-1gb-ram-wordpress-vps/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 11 Feb 2026 07:21:11 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7769</guid>

					<description><![CDATA[請求處理的瓶頸邏輯 當 Apache 面對大量連...]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">請求處理的瓶頸邏輯</h3>



<p>當 Apache 面對大量連線時，即便 CPU 沒滿，使用者確實可能需要排隊。這通常是因為 Apache 的 mpm 設定限制了同時處理請求的數量（MaxRequestWorkers）。當請求超過這個值，後續的連線會被放在作業系統的 backlog 隊列中等待。如果這個隊列也滿了，使用者就會看到連線逾時或拒絕連線。</p>



<p>在高併發場景下，Apache 每個連線通常會佔用一個進程或線程，這非常消耗記憶體與 CPU 資源。即便你調整了核心網路參數，如果 Apache 本身的工人數量設得太低，連線進不來；設得太高，記憶體會耗盡導致系統瘋狂交換資料（Swap），進而讓 CPU 飆升到 100%。</p>



<h3 class="wp-block-heading">記憶體與 Swap 的警訊</h3>



<p>從你提供的資訊來看，這台 WordPress 主機只有約 1GB 的記憶體（961Mi），且目前已經使用了 196Mi 的 Swap。當系統開始頻繁讀寫 Swap 時，磁碟 I/O 會拖慢所有處理程序，CPU 會花費大量時間在等待 I/O 完成（iowait），這也是造成系統停擺與 CPU 滿載的常見原因。1GB 記憶體對於執行現代 WordPress 加上 Apache 來說非常吃力，建議至少提升至 2GB 以上，或嚴格限制 Apache 的進程數量。</p>



<h3 class="wp-block-heading">動態請求的資源消耗</h3>



<p>WordPress 是基於 PHP 的動態網站，每一個連線都要啟動 PHP 解釋器去抓資料庫、執行外掛程式碼，這比處理靜態網頁耗費更多資源。如果你沒有使用快取機制（如 Redis 或是 WP Super Cache），每個訪客都會對 CPU 造成直接壓力。即便你把網路隊列加長（如 somaxconn），那也只是讓訪客在「門外排隊」排得久一點，並沒有真正解決「門內的消化速度」。</p>



<h3 class="wp-block-heading">改善建議</h3>



<p>要解決排隊與 CPU 滿載問題，調整核心參數只是輔助，你需要針對軟體層優化：</p>



<ul class="wp-block-list">
<li>檢查 Apache 的 mpm_event 設定，確保 MaxRequestWorkers 與你的記憶體大小匹配，避免觸發 Swap。</li>



<li>安裝 PHP 的 OPcache，這能顯著降低 CPU 處理 PHP 代碼的負擔。</li>



<li>強烈建議在 WordPress 加入物件快取（Object Cache）並搭配 Redis，減少對 MySQL 的重複查詢。</li>



<li>如果硬體資源無法提升，考慮將前端換成 Nginx 或是在 Apache 前面擋一層 Cloudflare，過濾掉不必要的壓力。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>修改 prefork MPM 設定值:</p>



<pre class="wp-block-code"><code>nano /etc/apache2/mods-available/mpm_prefork.conf</code></pre>



<p>prefork MPM 設定值:</p>



<pre class="wp-block-code"><code>StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 200
MaxConnectionsPerChild 2000</code></pre>



<h3 class="wp-block-heading">記憶體過載的風險</h3>



<p>你目前的 MaxRequestWorkers 設定為 200，這對於一台只有 1GB 記憶體的主機來說非常危險。在 prefork 模式下，每個 Apache 進程都會消耗獨立的記憶體。以 WordPress 來說，一個 PHP 進程大約佔用 40MB 到 80MB 不等。</p>



<p>如果同時有 200 個請求進來，記憶體需求會來到 200 x 40MB = 8000MB（約 8GB）。你的主機只有 1GB，這會導致系統強制使用硬碟當記憶體（Swap），讓 CPU 飆升到 100% 且網頁完全打不開。這就是為什麼你感覺到系統停擺的主因。</p>



<h3 class="wp-block-heading">針對 1GB 記憶體的設定建議</h3>



<p>假設扣除作業系統與其他程序佔用的 300MB，剩下約 600MB 給 Apache 使用。以每個進程 40MB 計算，MaxRequestWorkers 設定在 15 到 20 之間比較安全。</p>



<p>以下是建議的設定值：</p>



<pre class="wp-block-code"><code>StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 20
MaxConnectionsPerChild 1000</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">設定值的邏輯說明</h3>



<ul class="wp-block-list">
<li><strong>MaxRequestWorkers (20)</strong>：<br>這是最重要的防線。設定為 20 代表最多只允許 20 個連線同時進入 PHP 處理階段。雖然這會讓第 21 個人排隊，但至少能保證這 20 個人能快速拿到網頁，且不會搞垮整台主機。</li>



<li><strong>MaxConnectionsPerChild (1000)</strong>：<br>原先的 2000 稍微偏高。調低到 1000 可以更頻繁地釋放可能洩漏的記憶體，對於小記憶體主機比較友善。</li>



<li><strong>預留空間</strong>：<br>當你發現 CPU 依然很高，但記憶體還有剩時，再以每次加 5 的幅度調升 MaxRequestWorkers。</li>
</ul>



<h3 class="wp-block-heading">如何減少排隊感</h3>



<p>雖然限制了進程數可以防止當機，但使用者可能會因為排隊感到緩慢。你可以嘗試以下方法緩解：</p>



<ol start="1" class="wp-block-list">
<li><strong>啟用 Page Cache</strong>：<br>使用外掛如 WP Rocket 或 WP Super Cache 將頁面轉為靜態 HTML。這樣 Apache 處理請求的速度會快上百倍，同樣 20 個進程能服務的總人數會大幅提升。</li>



<li><strong>更換 MPM 模式</strong>：<br>如果可能，建議將 Apache 從 prefork 換成 event 模式並搭配 PHP-FPM。event 模式處理連線的效率更高，且更省記憶體。</li>



<li><strong>檢查資料庫連線</strong>：<br>確保你的 WordPress 設定指向 MySQL 主機時使用的是私有 IP（例如 10.x.x.x），避免走公網造成額外的連線延遲。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Q: 2GB swap 是否太多?</p>



<h3 class="wp-block-heading">Swap 的定位與影響</h3>



<p>在 1GB 記憶體的主機上，設定 2GB 的 Swap 並不算是「太多」，但它是一把雙刃劍。當你的實體記憶體用完時，Swap 可以作為緩衝，防止系統因為記憶體不足（OOM Killer）直接強制關閉資料庫或 Apache 進程。然而，Swap 的存取速度遠慢於記憶體，一旦系統頻繁使用 Swap，整台主機的效能會劇烈下降。</p>



<p>從你提供的數據看，目前已經使用了 196Mi 的 Swap，這代表 1GB 的記憶體已經不夠用了。系統正在把不常用的資料搬到硬碟，如果這個數值持續跳動或增加，就是 CPU 飆高的前兆，因為 CPU 會浪費大量時間在處理記憶體與硬碟之間的資料交換。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">為什麼不建議依賴大量 Swap</h3>



<ul class="wp-block-list">
<li><strong>效能瓶頸</strong>：<br>硬碟（即使是 SSD）的速度比記憶體慢上千倍。當 Apache 請求排隊且又需要讀取 Swap 時，反應時間會從毫秒變成秒，使用者會感覺網站掛掉了。</li>



<li><strong>CPU 負擔</strong>：<br>管理 Swap 需要 CPU 參與，當記憶體極度短缺導致系統瘋狂交換資料（Thrashing）時，CPU 使用率會直接衝上 100%，但實際上沒有處理任何網頁請求。</li>



<li><strong>硬碟壽命</strong>：<br>如果是雲端主機，頻繁的 Swap 讀寫會消耗大量的 IOPS，有些服務商會因此限制你的磁碟效能。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">調整建議與優化</h3>



<p>與其擔心 Swap 太大，不如減少系統對它的依賴。</p>



<p><strong>1. 調整 Swappiness</strong></p>



<p>你目前的 <code>vm.swappiness = 10</code> 已經是很合理的設定。這代表系統會盡可能使用實體記憶體，直到剩下約 10% 左右才會開始考慮使用 Swap。請保持這個設定。</p>



<p><strong>2. 核心問題在記憶體配置</strong></p>



<p>2GB 的 Swap 空間本身沒問題，問題出在你的 Apache 配置（MaxRequestWorkers 200）會輕易吃光 1GB 記憶體，強制系統去填滿那 2GB 的 Swap。這就像是雖然路邊有很大的路肩可以停車，但如果你把高速公路主線都塞滿了，車流還是會動彈不得。</p>



<p><strong>3. 監控建議</strong></p>



<p>你可以觀察 <code>vmstat 1</code> 指令中的 <code>si</code> (swap in) 與 <code>so</code> (swap out) 欄位。如果這兩個數字持續不是 0，代表系統正在發生頻繁交換，這才是真正的效能殺手。</p>



<p>目前的狀況下，2GB Swap 是安全的備援，但你應該透過調整 Apache 的進程數，讓 Swap 使用量維持在幾百 MB 以內甚至不使用。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p id="mpm_event">apache 的 mods mpm_event 沒被 enable, 只有 enable mpm_prefork</p>



<h3 class="wp-block-heading">為什麼你的主機只開啟了 mpm_prefork</h3>



<p>在較舊的系統或預設安裝中，Apache 為了確保與 PHP 的相容性（特別是當 PHP 以 mod_php 模組運行時），會預設使用 mpm_prefork。這個模式的特色是每個請求由一個獨立的進程處理，雖然穩定，但非常耗費記憶體，這正是導致你 1GB 記憶體主機容易 CPU 100% 的根本原因。</p>



<p>如果你想大幅提升連線處理能力，並讓 CPU 不再輕易滿載，切換到 mpm_event 是最有效的做法。mpm_event 使用線程（threads）處理連線，能用極少的記憶體處理數倍於 prefork 的併發量。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">切換到 mpm_event 的必要前提</h3>



<p>在切換之前，你必須確認 PHP 的運行方式。mpm_event 不支援傳統的 mod_php。</p>



<p><strong>安裝 PHP-FPM</strong>：你必須先安裝並啟動 php-fpm 服務。</p>



<p><strong>停用 mod_php</strong>：切換 MPM 前需要先停用 PHP 模組。</p>



<p><strong>更換模組</strong>：</p>



<p>停用 mpm_prefork：</p>



<pre class="wp-block-code"><code><code>sudo a2dismod mpm_prefork</code></code></pre>



<p>啟用 mpm_event：</p>



<pre class="wp-block-code"><code><code>sudo a2enmod mpm_event</code></code></pre>



<p>重啟 Apache：</p>



<pre class="wp-block-code"><code><code>sudo systemctl restart apache2</code></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">如果決定留在 mpm_prefork 的優化</h3>



<p>如果你因為某些舊外掛必須維持 mpm_prefork，那麼你必須嚴格執行我之前建議的 <strong>MaxRequestWorkers 20</strong>。</p>



<p>在 prefork 模式下，當連線數超過 MaxRequestWorkers 時，多出來的連線會進入作業系統的等待隊列（backlog）。這就是你問的「排隊等待」：</p>



<ul class="wp-block-list">
<li><strong>CPU 沒滿載但要排隊</strong>：這是因為 MaxRequestWorkers 限制了同時作業的人數，門外的人在排隊，但門內的人處理很快。</li>



<li><strong>CPU 滿載且要排隊</strong>：這是因為 MaxRequestWorkers 設太大（如你原本的 200），門內擠滿了人，大家都在互搶記憶體跟磁碟 IO，導致系統接近崩潰。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">總結建議</h3>



<p>以你目前的硬體資源（1GB RAM），維持 mpm_prefork 並設定 MaxRequestWorkers 200 絕對會當機。</p>



<ul class="wp-block-list">
<li><strong>短期方案</strong>：立即將 MaxRequestWorkers 調降至 20 左右，保證系統不崩潰。</li>



<li><strong>長期方案</strong>：改用 mpm_event 搭配 PHP-FPM。這樣同樣 1GB 的記憶體，你可能可以將 MaxRequestWorkers 開到 100 以上而不會觸發 Swap。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>如何知道目前是使用 mod_php or php-fpm?</p>



<h3 class="wp-block-heading">確認目前 PHP 運行方式</h3>



<p>你可以透過以下兩種方式快速判斷：</p>



<p><strong>查看 Apache 模組清單</strong>：執行指令 </p>



<pre class="wp-block-code"><code><code>apache2ctl -M | grep php</code></code></pre>



<p>如果你看到 <code>php_module</code> 或 <code>php7.x_module</code> / <code>php8.x_module</code>，代表你正在使用 <strong>mod_php</strong>。</p>



<p><strong>建立 info.php 網頁</strong>：在網頁根目錄建立一個檔案，內容寫 </p>



<pre class="wp-block-code"><code><code>&lt;?php phpinfo(); ?&gt;</code></code></pre>



<p>用瀏覽器開啟後，搜尋 <strong>Server API</strong> 這一項：</p>



<p>如果顯示 <code>Apache 2.0 Handler</code>，就是 <strong>mod_php</strong>。</p>



<p>如果顯示 <code>FPM/FastCGI</code>，就是 <strong>php-fpm</strong>。</p>



<p>修改前: Server API: Apache 2.0 Handler</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="744" height="300" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-47_m8.jpg?v=1770793963" alt="" class="wp-image-7770" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-47_m8.jpg?v=1770793963 744w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-47_m8-600x242.jpg?v=1770793963 600w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">切換至 mpm_event 與 PHP-FPM 詳細步驟</h3>



<p>假設你使用的是 PHP 8.3（請根據你的版本自行調整數字，例如 7.4 或 8.1）：</p>



<p><strong>1. 安裝 PHP-FPM 與相關模組</strong></p>



<pre class="wp-block-code"><code>sudo apt update
sudo apt install php8.3-fpm libapache2-mod-fcgid
</code></pre>



<p>安裝完成後，確認 FPM 已經啟動：</p>



<pre class="wp-block-code"><code>sudo systemctl status php8.3-fpm
</code></pre>



<p><strong>2. 啟用必要模組並停用 mod_php</strong></p>



<p>這是一連串的模組切換動作，請依序執行：</p>



<pre class="wp-block-code"><code># 啟用 proxy 相關模組，讓 Apache 能溝通 PHP-FPM
sudo a2enmod proxy_fcgi setenvif

# 啟用 FPM 的設定檔
sudo a2enconf php8.3-fpm

# 停用 PHP 模組 (注意版本號要對應)
sudo a2dismod php8.3

# 核心切換：停用 prefork 並啟用 event
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event</code></pre>



<p><strong>3. 檢查設定並重啟</strong></p>



<p>在重啟前先測試設定檔是否正確：</p>



<pre class="wp-block-code"><code>sudo apache2ctl configtest</code></pre>



<p>如果顯示 <code>Syntax OK</code>，就重啟服務：</p>



<pre class="wp-block-code"><code>sudo systemctl restart apache2</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">為什麼這能解決你的問題</h3>



<p>切換到 mpm_event 後，Apache 不再為每個連線維持一個笨重的進程。這對你的 1GB 記憶體主機有以下好處：</p>



<ul class="wp-block-list">
<li><strong>記憶體佔用極低</strong>：Apache 進程只負責把連線傳遞給 PHP-FPM，閒置連線幾乎不佔記憶體。</li>



<li><strong>併發能力提升</strong>：你可以安全地將同時連線數設得更高。</li>



<li><strong>獨立管理</strong>：PHP-FPM 有自己的進程管理設定檔，你可以獨立限制 PHP 能用多少記憶體，而不會跟 Apache 搶資源。</li>
</ul>



<p>切換完成後，原本在 <code>/etc/apache2/mods-enabled/mpm_prefork.conf</code> 的設定就失效了，你需要去修改 <code>/etc/apache2/mods-enabled/mpm_event.conf</code>。</p>



<p>修改用指令:</p>



<pre class="wp-block-code"><code>nano /etc/apache2/mods-available/mpm_event.conf</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">針對 1GB 記憶體的 event 模式優化</h3>



<p>切換到 mpm_event 後，你的主機體質已經大幅改善。在 event 模式下，Apache 的進程變得很輕量，主要的記憶體壓力轉移到了 PHP-FPM 手上。你提供的預設值對於 1GB 記憶體來說稍嫌激進，特別是 MaxRequestWorkers 150。如果這 150 個連線同時觸發 PHP 運算，主機依然會因為記憶體耗盡而崩潰。</p>



<p>以下是針對 1GB 記憶體環境的建議設定值：</p>



<pre class="wp-block-code"><code>StartServers 2
MinSpareThreads 25
MaxSpareThreads 50
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 50
MaxConnectionsPerChild 1000</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">設定值調整邏輯</h3>



<ul class="wp-block-list">
<li><strong>MaxRequestWorkers (50)</strong>：雖然 event 模式很省資源，但後端的 PHP-FPM 依然很吃記憶體。將此值設為 50 是一個安全的基準，代表 Apache 最多同時送 50 個請求給 PHP 處理。這能確保在高負載時，系統仍有足夠的緩衝記憶體，不至於觸發大量的 Swap 讀寫。</li>



<li><strong>MaxSpareThreads (50)</strong>：將最大閒置線程調低，可以讓 Apache 在離峰時段釋放不必要的資源。</li>



<li><strong>MaxConnectionsPerChild (1000)</strong>：建議不要設定為 0（無限）。設定一個數值（如 1000）可以讓進程在處理一定量請求後重啟，有效防止長期運行可能產生的記憶體洩漏問題。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">同步檢查 PHP-FPM 的設定</h3>



<p>切換到 event 模式後，你還需要檢查 PHP-FPM 的設定檔：</p>



<pre class="wp-block-code"><code>nano /etc/php/8.3/fpm/pool.d/www.conf</code></pre>



<p>這才是決定 CPU 是否衝到 100% 的關鍵：</p>



<pre class="wp-block-code"><code>pm = dynamic
pm.max_children = 15
pm.process_idle_timeout = 10s
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
</code></pre>



<ul class="wp-block-list">
<li><strong>pm.max_children (20)</strong>：這限制了同時運行的 PHP 進程數。因為每個 PHP 進程大約 40-60MB，20 個大約佔用 1GB 左右的空間。這個數值應與 Apache 的 MaxRequestWorkers 搭配。如果你發現記憶體還有剩餘，可以慢慢往上加。 反之，如果設了 20 還是占用掉大量 swap 就要降低。</li>
</ul>



<h3 class="wp-block-heading">觀察成效</h3>



<p>完成設定後，請重啟服務：</p>



<pre class="wp-block-code"><code><code>sudo systemctl restart php8.3-fpm apache2</code></code></pre>



<p>你可以觀察 <code>top</code> 或 <code>htop</code>。如果 CPU 負載下降且 Swap 使用量不再增加，代表目前的平衡點是正確的。如果使用者仍反映要排隊，但 CPU 很閒，再逐步調高 <code>pm.max_children</code> 與 <code>MaxRequestWorkers</code>。</p>



<p>修改之後: Server API: FPM/FastCGI</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="678" height="355" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-58_m9.jpg?v=1770794049" alt="" class="wp-image-7771" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-58_m9.jpg?v=1770794049 678w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-11_14-58_m9-600x314.jpg?v=1770794049 600w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">計算單個 PHP 進程的記憶體平均值</h3>



<p>要精確設定 <code>pm.max_children</code>，你需要知道每個 PHP 進程實際上吃了多少記憶體。請在終端機執行以下指令：</p>



<pre class="wp-block-code"><code>ps -ylC php-fpm8.3 --sort:rss | awk '{sum+=$8; ++n} END {if (n &gt; 0) print sum/n/1024 " MB"}'
</code></pre>



<p>（請根據你的版本修改 <code>php-fpm8.3</code>）</p>



<p>這條指令會抓取所有正在執行的 PHP-FPM 進程，並計算出平均每個進程佔用的實體記憶體（RSS）。</p>



<h3 class="wp-block-heading">如何根據結果調整 pm.max_children</h3>



<p>得到平均值後，你可以使用以下公式來估算：</p>



<pre class="wp-block-preformatted">(可用記憶體 - 系統預留) / 單個 PHP 進程平均大小 = pm.max_children</pre>



<p>舉例來說：</p>



<ul class="wp-block-list">
<li>可用記憶體：1024MB</li>



<li>系統預留（作業系統 + Apache + MySQL）：400MB</li>



<li>剩餘空間：624MB</li>



<li>如果你的 PHP 進程平均是 40MB，則 $624 / 40 = 15.6$。</li>



<li>建議設定：<strong>pm.max_children = 15</strong>。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">優化 PHP-FPM 與 Apache 的連動</h3>



<p>當你設定好 <code>pm.max_children</code> 後，Apache 的 <code>MaxRequestWorkers</code> 應該設為與其相同或略大一點。如果 <code>pm.max_children</code> 設得太小，Apache 送過去的請求會因為沒有多餘的 PHP 工人處理而在後台排隊，這就是為什麼 CPU 沒滿但使用者要等待的原因之一。</p>



<h3 class="wp-block-heading">其他關鍵優化</h3>



<p>為了讓這 1GB 記憶體發揮最大效益，請檢查以下設定：</p>



<ul class="wp-block-list">
<li><strong>pm.max_requests</strong>：在 <code>www.conf</code> 中將此值設為 <strong>500</strong> 或 <strong>1000</strong>。這會讓 PHP 進程在處理完固定次數請求後重啟，能有效清理記憶體殘留，對小主機非常重要。</li>



<li><strong>opcache</strong>：確保 <code>/etc/php/8.3/fpm/php.ini</code> 中的 <code>opcache.enable=1</code> 與 <code>opcache.memory_consumption=128</code> 是開啟的。這能大幅降低 CPU 負擔。</li>



<li><strong>MySQL 檢查</strong>：你的 WordPress 與 MySQL 分開兩台，這很好。但請確保 WordPress 那台主機的 <code>wp-config.php</code> 是使用私有 IP 連線，避免 DNS 解析或公網延遲拖慢 PHP 進程的存活時間。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>為什麼預設 /etc/php/8.3/fpm/php.ini&nbsp;中的&nbsp;opcache.enable 沒被啟用?</p>



<h3 class="wp-block-heading">PHP FPM 與 OPcache 的預設行為</h3>



<p>在多數 Linux 發行版（如 Ubuntu 或 Debian）中，當你透過套件管理員安裝 PHP 8.3 時，你會發現 php.ini 檔案裡的 opcache.enable 前面標註了分號，這代表該行是被註釋掉的。雖然在 php.ini 檔案中看起來像是沒啟用，但實際上 OPcache 在 FPM 環境下通常是運行的。</p>



<p>這是因為 PHP 的設定採用了模組化管理。在 /etc/php/8.3/fpm/conf.d/ 目錄下，會有一個類似 10-opcache.ini 的符號連結，它指向 /etc/php/8.3/mods-available/opcache.ini。在這個獨立的設定檔中，通常已經包含了 zend_extension=opcache.so 以及 opcache.enable=1。</p>



<p>PHP 在啟動時會先讀取主 php.ini，接著讀取 conf.d 目錄下的所有額外設定。由於 conf.d 中的設定載入順序較晚，它會覆蓋掉 php.ini 裡的預設值。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">為什麼不直接在主設定檔啟用</h3>



<p>這種設計主要是為了維護的便利性。透過將不同擴充功能的設定拆分到獨立檔案，系統管理員可以簡單地使用 phpenmod 或 phpdismod 指令來開啟或關閉特定功能，而不需要去更動核心的 php.ini 檔案。</p>



<p>如果 opcache.enable 在 php.ini 中被硬編碼啟用，當你想暫時停用它來進行除錯時，操作會變得比較麻煩。模組化的做法讓升級 PHP 版本時，設定檔的遷移與管理變得更加直覺，也能避免主設定檔變得過於臃腫。</p>



<p>如果你想確認目前 OPcache 是否真的有在運作，可以撰寫一個包含 phpinfo(); 內容的檔案並透過瀏覽器執行，或者在終端機輸入 php-fpm8.3 -i | grep opcache.enable 來查看最終生效的數值。</p>



<p>指令實際執行畫面:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="682" height="184" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-02_16-13_mm.jpg?v=1772439227" alt="" class="wp-image-7811" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-02_16-13_mm.jpg?v=1772439227 682w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-02_16-13_mm-600x162.jpg?v=1772439227 600w" sizes="auto, (max-width: 682px) 100vw, 682px" /></figure>



<p>opcache.enable 在 php.ini 裡, 是被註解沒啟用, 實際上是有被 enable</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>如何在負載測試期間（例如使用 ab 工具）監控記憶體與 Swap 的即時變化？</p>



<h3 class="wp-block-heading">即時監控與測試方法</h3>



<p>要找出系統的極限，最有效的方法是在模擬負載時觀察資源變化。你可以使用 Apache 內建的 $ab$ (Apache Benchmark) 工具，從外部或另一台主機進行測試。</p>



<p><strong>1. 準備監控視窗</strong></p>



<p>建議同時開啟兩個終端機視窗：</p>



<p><strong>視窗 A（觀察記憶體與 Swap）：</strong> 執行 </p>



<pre class="wp-block-code"><code><code>watch -n 1 free -m</code></code></pre>



<p>這讓你每秒看到記憶體減少與 Swap 增加的速度。</p>



<p><strong>視窗 B（觀察 PHP 進程）：</strong> 執行 </p>



<pre class="wp-block-code"><code><code>watch -n 1 "ps aux | grep php-fpm | grep -v grep | wc -l"</code></code></pre>



<p>這能讓你確認 <code>pm.max_children</code> 是否已經達到上限。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">使用 ab 進行壓力測試</h3>



<p>在另一台電腦執行以下指令（不要在 WordPress 主機自己跑，會影響測試準確性）：</p>



<p><code>ab -n 500 -c 20 http://你的網站IP/</code></p>



<ul class="wp-block-list">
<li><code>-n 500</code>：總共發出 500 個請求。</li>



<li><code>-c 20</code>：同時有 20 個連線（併發）。</li>
</ul>



<p><strong>測試時的觀察重點：</strong></p>



<ul class="wp-block-list">
<li><strong>情境 1：</strong> 如果 Swap 數字開始快速跳動，代表 <code>pm.max_children</code> 設得太高，記憶體爆了。</li>



<li><strong>情境 2：</strong> 如果 <code>free</code> 顯示記憶體還有剩，但 <code>ab</code> 測試結果很慢，且 PHP 進程數卡在 20 不動，代表你的 <code>pm.max_children</code> 設太低，CPU 沒事做但大家在排隊。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>count children = 10, each thread 127MB  已大於該  VPS  的 1GB RAM.</p>



<h3 class="wp-block-heading">找出完美的平衡點</h3>



<p>理想的狀態是：當併發連線進來時，CPU 使用率上升（代表有在做事），實體記憶體用到約 80%~90%，但 Swap 幾乎不動。</p>



<p>如果你的測試結果顯示 CPU 還是很容易衝到 100%，即使記憶體夠用，那通常是因為 WordPress 處理每個請求的時間太長。這時你需要檢查：</p>



<ul class="wp-block-list">
<li><strong>MySQL 慢查詢：</strong> 檢查 MySQL 主機是否因為沒有索引導致查詢變慢，拖住 PHP 進程。</li>



<li><strong>Object Cache：</strong> 在 WordPress 安裝 Redis Object Cache 插件。這能讓原本需要 0.5 秒處理的頁面縮短到 0.1 秒，同樣的進程數就能服務 5 倍的使用者。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">記憶體共享機制與計算誤差</h3>



<p>這是一個非常經典的誤區。雖然指令算出的平均值是 127MB，但這 10 個進程並不是真的佔用了 </p>



<pre class="wp-block-preformatted">10 x  127 = 1270MB</pre>



<p><strong>1. 共享記憶體 (Shared Memory)</strong></p>



<p>PHP-FPM 的主進程啟動時，會載入 PHP 核心、擴充功能和常用代碼（特別是開啟 OPcache 後）。當它產生子進程（Workers）時，這些子進程會共享主進程已經載入的唯讀記憶體區塊。</p>



<p><code>ps</code> 指令算出的 RSS（Resident Set Size）包含了進程自己獨有的資料以及它跟別人共享的資料。如果你把每個進程的 RSS 全部加總，會重複計算那些「共享的部分」，導致總數看起來超過了實體記憶體。</p>



<p><strong>2. 為什麼系統沒崩潰</strong></p>



<p>從你的 <code>free -m</code> 來看，<code>used</code> 是 678Mi，這才是系統目前真正消耗的實體記憶體。扣除掉快取後，你的 <code>available</code> 還有 282Mi。這代表這 10 個 PHP 進程實際上扣除掉彼此重複的部分，總共只佔用了大約 400 到 500MB 左右。</p>



<p><strong>3. 127MB 的警訊</strong></p>



<p>雖然有共享機制，但平均每個進程 127MB 在 WordPress 裡算是偏肥大的。這通常代表：</p>



<ul class="wp-block-list">
<li>你安裝了較多或較大型的外掛。</li>



<li>你的主題（Theme）載入了大量函式庫。</li>



<li>這些進程在處理完請求後，還沒釋放某些動態生成的資料。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">如何更精準地觀察與調整</h3>



<p><strong>1. 使用 PSS 計算（更準確）</strong></p>



<p>如果你想看扣除共享後「真正」佔用的記憶體，可以試試安裝 <code>smem</code> 工具，它計算的 PSS (Proportional Set Size) 會把共享記憶體平攤給每個進程，算出來的總和才等於系統實際消耗量。</p>



<p><strong>2. 調整 pm.max_requests</strong></p>



<p>你的進程長到 127MB，有可能是因為處理過太多請求而累積了碎片。在 <code>www.conf</code> 裡設定：</p>



<pre class="wp-block-code"><code><code>pm.max_requests = 500</code></code></pre>



<p>這能強迫進程在處理 500 次請求後重啟，把記憶體歸零，防止它無限制長大到真的塞爆 RAM。</p>



<p><strong>3. 修正 pm.max_children</strong></p>



<p>根據你現在 127MB 的觀察值，即便有共享，我也建議你的 <code>pm.max_children</code> 最多設 <strong>10 到 12</strong> 就好。因為在高負載下，每個進程處理複雜查詢時，獨有的記憶體會迅速增加，那時共享部分的比例會下降，如果不限制數量，136Mi 的 Swap 很快就會變成 500Mi，到時 CPU 就會衝上 100%。</p>



<p>你想確認目前 <code>www.conf</code> 裡的 <code>pm</code> 模式是 <code>static</code> 還是 <code>dynamic</code> 嗎？這會影響這 10 個進程是否會自動增減。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>雖然把數值調低, 在 CPU / RAM / Disk IO 都明顯下降，但實際上造成的平均反應時間是大大的上升，所以讓 CPU / RAM 微微滿載，可能可以再降低一點回應時間。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="809" height="665" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-01_23-27_ml.jpg?v=1772378866" alt="" class="wp-image-7808" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-01_23-27_ml.jpg?v=1772378866 809w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-01_23-27_ml-600x493.jpg?v=1772378866 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-03-01_23-27_ml-768x631.jpg?v=1772378866 768w" sizes="auto, (max-width: 809px) 100vw, 809px" /></figure>



<p>page views 下降，且page load time 還上升，也許不去調整，performance 才是更好的, 呵呵。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/1cpu-1gb-ram-wordpress-vps/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress 安裝 Redis 與 PHP 擴展</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/wordpress-redis-php/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/wordpress-redis-php/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sat, 07 Feb 2026 03:07:34 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7757</guid>

					<description><![CDATA[在 WordPress 那台 VPS 上安裝 R...]]></description>
										<content:encoded><![CDATA[
<p>在 WordPress 那台 VPS 上安裝 Redis 伺服器以及讓 PHP 能與 Redis 溝通的擴展模組。</p>



<pre class="wp-block-code"><code># 更新套件清單
sudo apt update

# 安裝 Redis 伺服器與 PHP Redis 擴展
sudo apt install redis-server php-redis -y</code></pre>



<p>安裝完成後，確認 Redis 是否正常啟動：</p>



<pre class="wp-block-code"><code>sudo systemctl status redis-server</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">配置 Redis 記憶體限制</h3>



<p>為了防止 Redis 佔用過多系統記憶體導致主機當機，建議設定上限。編輯設定檔：</p>



<pre class="wp-block-code"><code><code>sudo nano /etc/redis/redis.conf</code></code></pre>



<p>在檔案中找到或加入以下兩行（假設分配 256MB 給快取，可根據你的 VPS 記憶體大小調整）：</p>



<p>程式碼片段</p>



<pre class="wp-block-code"><code>maxmemory 256mb
maxmemory-policy allkeys-lru
</code></pre>



<p>這代表記憶體滿了時，Redis 會自動刪除最近最少使用的舊資料。修改後重啟 Redis：</p>



<pre class="wp-block-code"><code><code>sudo systemctl restart redis-server</code></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">WordPress 設定檔調整</h3>



<p>雖然外掛會幫你處理大部分工作，但有時候需要手動在 <code>wp-config.php</code> 定義 Redis 的連線資訊，特別是如果你有特殊需求時。編輯 WordPress 根目錄下的 <code>wp-config.php</code>，在 <code>/* That's all, stop editing! */</code> 之前加入：</p>



<pre class="wp-block-code"><code>define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
// 如果這台主機上有連往不同網站，可以用這個區分快取
define('WP_CACHE_KEY_SALT', 'my_site_name_');</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">安裝與啟用外掛</h3>



<ol start="1" class="wp-block-list">
<li>登入 WordPress 後台。</li>



<li>前往 <strong>外掛</strong> -&gt; <strong>安裝外掛</strong>。</li>



<li>搜尋 <strong>Redis Object Cache</strong>（作者通常是 Till Krüss）。</li>



<li>點擊安裝並啟用。</li>



<li>前往 <strong>設定</strong> -&gt; <strong>Redis</strong>，點擊 <strong>Enable Object Cache</strong> 按鈕。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">驗證快取是否運作</h3>



<p>啟用後，你可以在後台看到 Status 顯示為 Connected。你也可以在主機終端機輸入以下指令來即時監控：</p>



<pre class="wp-block-code"><code><code>redis-cli monitor</code></code></pre>



<p>當你重新整理網頁時，終端機會瘋狂跳出 <code>GET</code> 或 <code>SET</code> 的指令，這代表 WordPress 已經成功將原本要丟給 MySQL 的負擔，轉移到 Redis 記憶體快取中了。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Redis 記憶體分配評估</h3>



<p>從你的系統負載來看，總實體記憶體只有 <strong>961Mi</strong>（約 1GB），目前已使用了 <strong>537Mi</strong>，可用空間（available）僅剩 <strong>423Mi</strong>。在這種記憶體受限的環境下，將 Redis 設定為 <strong>256MB</strong> 會有點冒險，因為這還沒計算 PHP-FPM 或是其他系統服務在流量高峰時可能增加的消耗。</p>



<p>為了確保系統穩定，不至於因為記憶體耗盡（OOM）而導致資料庫連線或 PHP 崩潰，我建議將 Redis 的 <code>maxmemory</code> 調低。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">修正後的設定建議</h3>



<p>建議先從 <strong>128MB</strong> 開始，這對於一般的 WordPress 網站來說，存放 Object Cache（如選單、文章 metadata、選項等）通常已經足夠。</p>



<p>編輯 <code>/etc/redis/redis.conf</code>：</p>



<p>程式碼片段</p>



<pre class="wp-block-code"><code># 針對 1GB RAM 的小主機建議值
maxmemory 128mb
maxmemory-policy allkeys-lru
</code></pre>



<p>這樣的設定能確保 Redis 在記憶體用滿時，會優先刪除最久沒被使用的資料，而不會導致系統當機。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">觀察可用記憶體</h3>



<p>你可以定期觀察 <code>available</code> 這一欄。如果設定 128MB 後，<code>available</code> 穩定維持在 200Mi 以上，且 Redis 的命中率很高，則可以維持現狀。如果 <code>available</code> 掉到 100Mi 以下，你就必須考慮縮減 Redis 或是 PHP-FPM 的行程數量。</p>



<p>設定完成並重啟 Redis 後，可以到 WordPress 後台的 Redis 設定頁面看目前的 <strong>Memory Usage</strong>，如果它一直沒用到 100MB，那就代表 128MB 的上限非常安全。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">查看 Redis 記憶體即時狀態</h3>



<p>你可以直接在終端機輸入以下指令，這會顯示 Redis 目前實際使用的記憶體、峰值以及目前的碎片率：</p>



<p>Bash</p>



<pre class="wp-block-code"><code>redis-cli info memory | grep -E "used_memory_human|used_memory_peak_human|maxmemory_human"
</code></pre>



<p>這條指令會讓你看到：</p>



<ul class="wp-block-list">
<li><strong>used_memory_human</strong>：目前 Redis 裡面存的資料佔了多少空間。</li>



<li><strong>used_memory_peak_human</strong>：從啟動到現在，最高曾經用到多少。</li>



<li><strong>maxmemory_human</strong>：你剛剛在設定檔限制的 128MB。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">判斷是否需要加碼記憶體</h3>



<p>在觀察一段時間後，你可以根據顯示的數據做調整：</p>



<ul class="wp-block-list">
<li><strong>如果 used_memory 經常達到 128MB</strong>：代表你的網站資料量大，Redis 正在頻繁刪除舊快取來放新資料（這稱為 Eviction）。這時連線效率會稍微下降，如果 <code>available</code> 還有剩，可以考慮調到 192MB。</li>



<li><strong>如果 used_memory 遠低於 128MB</strong>：代表 128MB 非常充足，不需要再動它。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">另一個實用的監控指令</h3>



<p>如果你想看更細節的統計資訊（例如快取命中率），可以執行：</p>



<p>Bash</p>



<pre class="wp-block-code"><code>redis-cli info stats | grep keyspace
</code></pre>



<ul class="wp-block-list">
<li><strong>keyspace_hits</strong>：從快取拿到資料的次數（越高越好）。</li>



<li><strong>keyspace_misses</strong>：快取找不到，必須跑去問 MySQL 的次數（越低越好）。</li>
</ul>



<p>如果你的命中率（Hits）遠高於遺失率（Misses），恭喜你，你的兩台 VPS 溝通效率已經因為 Redis 的加入而大幅提升，因為很多請求在 WordPress 這台就處理完了，根本不需要跨網段去吵 MySQL。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">建立 Redis 與系統監控指令腳本</h3>



<p>這個腳本會整合 Linux 剩餘記憶體、Redis 記憶體使用狀況以及快取命中率，方便你隨時檢查主機健康狀態。</p>



<p>請在 WordPress 主機執行以下步驟：</p>



<p>建立腳本檔案：</p>



<pre class="wp-block-code"><code><code>nano check_redis.sh</code></code></pre>



<p>貼入以下內容：</p>



<pre class="wp-block-code"><code>#!/bin/bash
echo "=== 系統記憶體狀態 ==="
free -h | grep -E "Mem|可用"
echo ""
echo "=== Redis 記憶體使用現況 ==="
redis-cli info memory | grep -E "used_memory_human|used_memory_peak_human|maxmemory_human"
echo ""
echo "=== Redis 快取命中統計 ==="
redis-cli info stats | grep -E "keyspace_hits|keyspace_misses"
</code></pre>



<ol start="3" class="wp-block-list">
<li>儲存離開，並賦予執行權限：<code>chmod +x check_redis.sh</code></li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">如何閱讀監控結果</h3>



<p>之後你只需要輸入 <code>./check_redis.sh</code> 就能看到結果。</p>



<ul class="wp-block-list">
<li><strong>used_memory_human</strong> 如果接近你設定的 <strong>maxmemory</strong>，代表快取空間快滿了。</li>



<li><strong>keyspace_hits</strong> 與 <strong>keyspace_misses</strong> 的比例很重要。例如命中 1000 次、遺失 10 次，代表 99% 的請求都直接在本地端處理，兩台 VPS 之間的網路負擔降低了 99%。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">進階調整建議</h3>



<p>如果你發現 <strong>keyspace_misses</strong> 很高，通常是因為 WordPress 還有許多資料沒被快取進去，或是快取時間太短。這時可以檢查 WordPress 的 Redis 外掛設定，確保 <strong>Object Cache</strong> 確實有發揮作用。</p>



<p>另外，如果這兩台主機在同機房，別忘了檢查 WordPress 連接 MySQL 的 <code>DB_HOST</code> 是不是已經改成 <strong>內網 IP</strong>，這是最直接影響延遲的物理因素。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Redis 多網站衝突問題與解決方案</h3>



<p>在同一台 VPS 上讓多個網站共用同一個 Redis 伺服器，<strong>確實會發生衝突</strong>。如果沒有特別設定，網站 A 的快取資料可能會被網站 B 讀取或覆蓋，導致登入狀態錯亂、顯示錯誤的文章內容或是後台設定被跳槽。</p>



<p>要解決這個問題，有兩種最常見且有效的方法：</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">方法一：使用不同的資料庫編號（最簡單）</h3>



<p>Redis 預設提供 16 個資料庫（編號為 0 到 15）。你可以指定網站 A 使用資料庫 0，網站 B 使用資料庫 1。</p>



<p>編輯每個網站根目錄下的 <code>wp-config.php</code>，加入對應的資料庫編號：</p>



<p>PHP</p>



<pre class="wp-block-code"><code>// 網站 A 的設定
define('WP_REDIS_DATABASE', 0);

// 網站 B 的設定
define('WP_REDIS_DATABASE', 1);
</code></pre>



<p>這樣兩個網站的資料就會在 Redis 內部被隔離開來。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">方法二：使用 Cache Key Salt（最推薦）</h3>



<p>如果你的網站超過 16 個，或是想更保險一點，可以使用「加鹽」機制。這會讓 Redis 在儲存每一筆資料時，都在 key 的前面加上一段特定的前綴字串。</p>



<p>在每個網站的 <code>wp-config.php</code> 加入唯一的識別碼：</p>



<p>PHP</p>



<pre class="wp-block-code"><code>// 網站 A
define('WP_CACHE_KEY_SALT', 'site_a_name_');

// 網站 B
define('WP_CACHE_KEY_SALT', 'site_b_name_');
</code></pre>



<p>這樣即使它們都在同一個 Redis 資料庫裡，Key 的名稱也會變成 <code>site_a_name_options</code> 與 <code>site_b_name_options</code>，彼此互不干涉。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">注意事項與記憶體壓力</h3>



<p>雖然解決了衝突，但你必須注意<strong>記憶體用量</strong>。</p>



<ul class="wp-block-list">
<li><strong>加總計算</strong>：你之前設定的 <code>maxmemory 128mb</code> 是所有網站共用的總額。如果 site A 佔了 80MB，site B 佔了 60MB，總合就會超過 128MB。</li>



<li><strong>LRU 機制</strong>：當總量超過 128MB 時，Redis 會根據我們設定的 <code>allkeys-lru</code> 策略，隨機刪除所有網站中最舊的快取。這不會讓網站掛掉，但會導致兩邊的快取命中率都下降。</li>
</ul>



<p>如果你發現 <code>check_redis.sh</code> 顯示的 <code>used_memory</code> 經常卡在 128MB，建議稍微上修這個數值，或是增加 VPS 的實體記憶體。</p>



<p>需要我幫你檢查目前這台 VPS 上所有網站加起來大約佔用了多少 Redis Key 嗎？</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">查看 Redis 中各網站的 Key 數量</h3>



<p>你可以利用 Redis 的 <code>INFO keyspace</code> 指令來查看目前各個資料庫（Database）分別存了多少筆資料。如果你是使用「方法一」（不同資料庫編號）來區隔網站，這個指令最精準。</p>



<p>請執行：</p>



<pre class="wp-block-code"><code><code>redis-cli info keyspace</code></code></pre>



<p>輸出的結果會像這樣：</p>



<p><code>db0:keys=1250,expires=1200,avg_ttl=4500</code></p>



<p><code>db1:keys=850,expires=800,avg_ttl=3800</code></p>



<p>這代表 <strong>db0</strong>（網站 A）存了 1250 個 Key，而 <strong>db1</strong>（網站 B）存了 850 個。如果某個 db 的 keys 數量遠高於其他網站，代表該網站對 Redis 的依賴度最高，或是該網站的外掛/佈景產生了大量的快取資料。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">查看具體的前綴分佈</h3>



<p>如果你是使用「方法二」（Cache Key Salt），所有的 Key 都會擠在同一個 db0 裡面。這時我們可以用 <code>SCAN</code> 指令搭配 <code>grep</code> 來估算各網站的比例：</p>



<pre class="wp-block-code"><code># 查看 site_a 開頭的 key 有多少個
redis-cli --scan --pattern 'site_a_name_*' | wc -l

# 查看 site_b 開頭的 key 有多少個
redis-cli --scan --pattern 'site_b_name_*' | wc -l
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">綜合效能評估建議</h3>



<p>當多個網站併行時，請持續關注你的 <code>check_redis.sh</code> 指令。如果發現以下情況，請採取對應行動：</p>



<ul class="wp-block-list">
<li><strong>Evicted Keys 增加</strong>：執行 <code>redis-cli info stats | grep evicted_keys</code>。如果這個數字一直跳動，代表 128MB 真的不夠用了，Redis 正在被迫踢掉舊資料來塞新網站的資料。</li>



<li><strong>CPU 使用率飆升</strong>：如果 Redis 所在的 WordPress 主機 CPU 負載變高，可能是因為某些網站的快取過期時間（TTL）設太短，導致 Redis 頻繁處理寫入動作。</li>
</ul>



<p>目前你總共架設了幾個 WordPress 網站？如果超過 3 個，且平均流量不低，建議將 <code>maxmemory</code> 稍微放寬到 <strong>200mb</strong> 到 <strong>256mb</strong>，只要確保系統整體的 <code>available</code> 記憶體還有 100Mi 以上即可。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">建立多網站 Redis 統計腳本</h3>



<p>這個腳本會自動掃描 Redis 裡所有的資料庫（Database），並針對你設定的網站前綴（Salt）進行統計。這能讓你一眼看出哪個網站最佔空間。</p>



<p>建立腳本：</p>



<pre class="wp-block-code"><code><code>nano redis_sites_check.sh</code></code></pre>



<p>貼入以下內容（請根據你實際在 <code>wp-config.php</code> 設定的 <code>SALT</code> 修改 <code>SITES</code> 列表）：</p>



<pre class="wp-block-code"><code>#!/bin/bash
# 在下方的括號內填入你各個網站設定的 WP_CACHE_KEY_SALT
SITES=("site_a_name_" "site_b_name_" "site_c_name_")

echo "=== 各資料庫 Key 總數 (按 DB 編號) ==="
redis-cli info keyspace | grep "^db"

echo ""
echo "=== 各網站前綴 Key 統計 (按 SALT 區分) ==="
for prefix in "${SITES&#91;@]}"
do
    count=$(redis-cli --scan --pattern "${prefix}*" | wc -l)
    echo "網站前綴 &#91;${prefix}]: ${count} 個 Key"
done

echo ""
echo "=== Redis 強制刪除統計 (Evicted) ==="
redis-cli info stats | grep evicted_keys
</code></pre>



<p>賦予權限並執行：</p>



<pre class="wp-block-code"><code><code>chmod +x redis_sites_check.sh &amp;&amp; ./redis_sites_check.sh</code></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">如何解讀統計數據</h3>



<ul class="wp-block-list">
<li><strong>Key 數量落差大</strong>：如果某個網站有數千個 Key，而其他只有幾百個，通常是因為該網站安裝了較多外掛（如 WooCommerce、多語系外掛），或是佈景主題寫得比較肥大。</li>



<li><strong>evicted_keys &gt; 0</strong>：如果這個數字不是 0，代表你的 <code>maxmemory</code> 已經封頂，Redis 正在「丟車保帥」。只要這數字增加得很快，就建議加碼 50-100MB 的記憶體。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">最終優化小提醒</h3>



<p>由於你的主機記憶體只有 1GB 左右，跑多個網站加上 Redis 會讓記憶體非常吃緊。除了 Redis 優化，建議也要檢查兩台 VPS 之間的 <strong>Ping 值</strong>。</p>



<p>在 WordPress 主機輸入：</p>



<pre class="wp-block-code"><code><code>ping &lt;MySQL 主機內網 IP&gt;</code></code></pre>



<ul class="wp-block-list">
<li><strong>&lt; 1ms</strong>：完美，同機房內網。</li>



<li><strong>1ms ~ 10ms</strong>：普通，可能是同地區但不同機房。</li>



<li><strong>&gt; 50ms</strong>：不理想，建議考慮將兩台主機遷移到同一個機房，這比任何軟體優化都有效。</li>
</ul>



<p>如果你發現 Ping 值過高，或是想要了解如何優化 PHP-FPM 的行程數量來騰出記憶體，隨時告訴我。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">選擇建議：維持現狀使用 DB0 加前綴即可</h3>



<p>針對只有 3 個網站的情況，我建議<strong>繼續使用 DB0 並搭配 Salt 前綴</strong>，不需要刻意切換到不同的 Keyspace（DB 1, DB 2 等）。</p>



<p>主要原因有三點：</p>



<ol start="1" class="wp-block-list">
<li><strong>管理方便</strong>：從你跑出來的腳本可以看到，目前 3 個網站的 Key 總數才 3300 多個，佔用記憶體僅 <strong>7.41MB</strong>，遠低於 128MB 的上限。放在一起管理非常輕鬆。</li>



<li><strong>性能差異極小</strong>：在 Redis 中，切換 DB 並不會帶來明顯的性能提升，反而會讓你的監控腳本變複雜（需要切換資料庫才能掃描）。</li>



<li><strong>擴充性</strong>：使用前綴（Salt）是目前 WordPress 社群最主流的做法，許多自動化備份或快取清理外掛對前綴的支援度也比切換 DB 來得好。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">數據診斷與優化建議</h3>



<p>從你的 <code>redis_status.sh</code> 結果來看，有幾個有趣的發現：</p>



<ul class="wp-block-list">
<li><strong>命中率 (Hits) 表現良好</strong>：你的 <code>keyspace_hits</code> (25104) 遠大於 <code>keyspace_misses</code> (7042)，這代表大約 <strong>78%</strong> 的請求已經不需要去吵 MySQL 了，這對提升兩台 VPS 間的溝通效率非常有感。</li>



<li><strong>記憶體非常充裕</strong>：目前只用了 7.41MB，你可以放心地把這 3 個網站都跑在 Redis 上，完全不需要擔心 128MB 不夠用。</li>



<li><strong>第三個網站活性低</strong>：<code>stickerline_</code> 只有 47 個 Key，這通常代表該網站流量極低，或者 Redis Object Cache 外掛雖然啟用了，但還沒累積足夠的存取資料。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">下一個優化重點：減少 Misses</h3>



<p>雖然 78% 的命中率不錯，但如果你想進一步壓榨效能，可以觀察 <code>keyspace_misses</code>。這通常是因為：</p>



<ol start="1" class="wp-block-list">
<li><strong>快取過期</strong>：某些資料的 TTL（存活時間）設太短。</li>



<li><strong>不支援快取的查詢</strong>：某些複雜的 SQL 查詢或特定外掛（如購物車、會員中心）為了即時性會避開快取。</li>
</ol>



<p>你可以試著在離峰時段執行 <code>redis-cli monitor</code>，看看哪些 Key 經常出現 <code>MISS</code>，如果是某些特定的頁面，可以檢查該頁面的外掛設定。</p>



<p>目前你的兩台 VPS 溝通效率已經比「裸奔」狀態好很多了。需要我幫你看看 MySQL 那台主機的 <code>slow query log</code> (慢查詢日誌)，找出那些 Redis 擋不掉、且執行太慢的 SQL 指令嗎？</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/wordpress-redis-php/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress 與 mysql 溝通效率優化</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/wordpress-mysql-fine-tune/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/wordpress-mysql-fine-tune/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sat, 07 Feb 2026 03:02:10 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7755</guid>

					<description><![CDATA[網路延遲與連線優化 要提升兩台主機間的溝通效率，...]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">網路延遲與連線優化</h3>



<p>要提升兩台主機間的溝通效率，首要任務是減少網路延遲。如果這兩台 VPS 位在同一個機房，請務必使用內網 IP（Private IP）進行連線，不要走公網 IP。內網傳輸不只速度快、頻寬不受限，還能省下流量費用。如果機房支援虛擬私有網路（VPC），也建議將兩者放在同一個 VPC 網段。</p>



<p>在 Linux 系統層面，可以調整 TCP 堆疊參數來優化連線回收速度。當 WordPress 頻繁讀取資料庫時，會產生大量短暫連線，透過修改 <code>/etc/sysctl.conf</code> 並開啟 <code>net.ipv4.tcp_tw_reuse</code>，可以讓系統更有效率地重複使用連線，避免因等待連線關閉導致的延遲。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">資料庫連線技術優化</h3>



<p>傳統的資料庫連線方式是每次請求都要重新握手，這會消耗大量時間。建議在 WordPress 主機端安裝並配置持久連線（Persistent Connections）。在 PHP 設定中啟用 <code>mysqli.allow_persistent</code>，或是在 WordPress 的資料庫設定中調整，讓 PHP 與 MySQL 之間維持長連線，避免反覆登入登出的開銷。</p>



<p>另外，如果資料庫查詢量極大，可以在兩台主機之間架設資料庫代理（Database Proxy），例如 ProxySQL。它可以處理連線池（Connection Pooling），將大量前端請求整合進少數幾個後端長連線，對提升高併發環境下的效率非常有幫助。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">軟體層與快取機制</h3>



<p>WordPress 預設每次載入頁面都會去資料庫撈資料，這對遠端資料庫來說負擔很大。建議安裝 Redis 或 Memcached 作為 Object Cache。當 WordPress 讀取過一次資料後，就直接存在主記憶體中，下次再有人訪問同一篇文章時，WordPress 會直接從記憶體拿資料，根本不需要跨過網路去問 MySQL 主機。</p>



<p>最後要檢查 MySQL 主機的 <code>my.cnf</code> 設定。確保 <code>bind-address</code> 綁定在內網 IP，並且檢查 <code>max_connections</code> 是否夠大。另外，如果在內網環境，可以關閉 MySQL 的 DNS 反向解析功能（在設定檔加入 <code>skip-name-resolve</code>），這能防止 MySQL 在每次連線時都去查主機名，直接提升連線反應速度。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">MySQL 主機連線優化</h3>



<p>在 MySQL 主機的設定檔（通常是 /etc/mysql/mysql.conf.d/mysqld.cnf）中，有幾個關鍵點可以調整。最重要的是關閉 DNS 反解，因為這常是導致連線延遲數秒的元兇。</p>



<p>Ini, TOML</p>



<pre class="wp-block-code"><code>&#91;mysqld]
# 禁用 DNS 反向解析，直接用 IP 驗證，速度最快
skip-name-resolve

# 增加最大連線數，避免 WordPress 併發高時被拒絕
max_connections = 500

# 調整等待逾時，避免無效的長連線佔用資源
wait_timeout = 600
interactive_timeout = 600
</code></pre>



<p>修改完畢後，記得重啟 MySQL 服務。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">WordPress 端的 Object Cache</h3>



<p>與其優化連線，不如減少連線。在 WordPress 這台 VPS 安裝 Redis，並搭配 Redis Object Cache 外掛。這樣重複的資料庫查詢結果會直接存在記憶體，減少跨主機存取 MySQL 的次數。</p>



<p>如果你使用的是 Ubuntu，可以快速安裝：</p>



<p><code>sudo apt install redis-server php-redis</code></p>



<p>安裝後在 WordPress 後台啟用外掛，並將資料庫主機地址改為內網 IP。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">WordPress 主機的重點</h3>



<p>這台主機扮演的是發起請求的角色。它會產生大量的短暫連線去詢問資料庫，因此最重要的參數是 <code>net.ipv4.tcp_tw_reuse = 1</code>。</p>



<p>由於 PHP 處理完請求後會關閉連線，這些連線在 Linux 系統中會進入 TIME_WAIT 狀態，佔用連接埠（Port）。開啟這個參數可以讓 WordPress 主機更快速地回收這些舊連線，避免在流量高峰時因為連接埠用盡而導致連線失敗或變慢。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">MySQL 主機的重點</h3>



<p>這台主機扮演的是接收請求的角色。它的壓力來自於同時要處理非常多個來自 WordPress 的連線請求，因此最重要的參數是 <code>net.core.somaxconn</code>。</p>



<p>當瞬間湧入大量查詢時，如果 MySQL 來不及處理，這些請求會先被放在系統的監聽佇列（Listen Queue）中。將這個數值調大（例如 4096），可以防止在高負載時請求被直接丟棄（Packet Drop），確保連線穩定不中斷。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">具體操作建議</h3>



<p>請在兩台主機分別執行以下步驟：</p>



<ol start="1" class="wp-block-list">
<li>編輯設定檔：<code>sudo nano /etc/sysctl.conf</code></li>



<li>將剛才提到的參數貼在檔案最末端。</li>



<li>存檔離開後執行：<code>sudo sysctl -p</code></li>
</ol>



<p>如果你之後發現資料庫主機的 CPU 負載過高，那可能就不是網路連線的問題，而是需要調整 MySQL 的 <code>innodb_buffer_pool_size</code> 等記憶體參數。</p>



<p>你想先檢查目前的網路連線狀態，看看是否有大量 TIME_WAIT 堆積嗎？</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">WordPress 主機的優化建議</h3>



<p>這台主機主要是作為 Client 端頻繁發起請求。重點在於加速連線回收與擴大發送端緩衝，避免因為連接埠（Port）回收不及導致的連線延遲。</p>



<pre class="wp-block-code"><code># 允許將 TIME_WAIT 狀態的連線重新用於新的 TCP 連線
net.ipv4.tcp_tw_reuse = 1
# 增加系統同時保持 TIME_WAIT 的最大數量
net.ipv4.tcp_max_tw_buckets = 50000
# 擴大本機暫時連接埠的範圍，增加可同時建立的連線數
net.ipv4.ip_local_port_range = 1024 65535
# 增加 TCP 傳輸與接收的緩衝區最大值（16MB）
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# 增加接收封包的排隊佇列
net.core.netdev_max_backlog = 5000
# 調整虛擬記憶體交換傾向
vm.swappiness = 10
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">MySQL 主機的優化建議</h3>



<p>這台主機作為 Server 端負責接收大量併發連線。重點在於擴大監聽佇列（Listen Queue）以及優化記憶體對大型資料傳輸的處理能力，防止請求在系統層級就被丟棄。</p>



<pre class="wp-block-code"><code># 增加系統同時處理的監聽佇列上限，防止高併發連線溢出
net.core.somaxconn = 8192
# 增加接收封包的排隊佇列
net.core.netdev_max_backlog = 5000
# 擴大 TCP 緩衝區最大值，有利於大型查詢結果的傳輸
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# 開啟連線重用（Server 端同樣建議開啟）
net.ipv4.tcp_tw_reuse = 1
# 增加 TCP SYN 隊列長度，容納更多等待握手的連線
net.ipv4.tcp_max_syn_backlog = 4096
# 減少快取壓力，優先使用記憶體
vm.swappiness = 10
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">套用與驗證步驟</h3>



<p>將上述內容分別複製到對應主機的 <code>/etc/sysctl.conf</code> 檔案末尾。請確保不要重複設定相同的變數，如果有重複的請以我給的新數值為主。</p>



<p>套用設定請執行：</p>



<p><code>sudo sysctl -p</code></p>



<p>驗證連線狀況：</p>



<p>你可以執行 <code>netstat -n | awk '/^tcp/ {print $6}' | sort | uniq -c</code> 來檢查目前連線狀態。如果看到大量的 TIME_WAIT 且你的連線效率還是沒提升，那我們就得從 PHP-FPM 的連線池（Pool）設定下手。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/wordpress-mysql-fine-tune/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ubuntu 24 安裝 WordPress 教學</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-wordpress/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 14:46:30 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7722</guid>

					<description><![CDATA[在 Ubuntu 24.04 上安裝 WordP...]]></description>
										<content:encoded><![CDATA[
<p>在 Ubuntu 24.04 上安裝 WordPress 需要建立 LAMP 架構，也就是 Linux、Apache、MySQL 和 PHP 的組合。以下是完成安裝的具體步驟。</p>



<h3 class="wp-block-heading">安裝 Apache 與 PHP</h3>



<p>首先更新系統軟體套件清單，然後安裝 Apache 伺服器以及 WordPress 運行所需的 PHP 組件。</p>



<pre class="wp-block-code"><code>sudo apt update
sudo apt install apache2 php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip -y</code></pre>



<p>安裝完成後，Apache 會自動啟動，你可以透過瀏覽器輸入伺服器的 IP 地址來確認是否看到預設網頁。</p>



<h3 class="wp-block-heading">安裝並設定 MariaDB 資料庫</h3>



<p>WordPress 需要資料庫來儲存內容，這裡使用 MariaDB。<sup></sup></p>



<pre class="wp-block-code"><code>sudo apt install mariadb-server -y<sup></sup></code></pre>



<p>安裝後進入資料庫終端機，建立專屬的資料庫與使用者。請將下面的 password 換成你的密碼。</p>



<pre class="wp-block-code"><code>sudo mysql -u root
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;</code></pre>



<p></p>



<h3 class="wp-block-heading">下載並配置 WordPress</h3>



<p>接下來下載最新版的 WordPress 檔案並解壓縮到網頁根目錄。</p>



<pre class="wp-block-code"><code>wget <a href="https://www.google.com/search?q=https://wordpress.org/latest.tar.gz" target="_blank" rel="noreferrer noopener">https://wordpress.org/latest.tar.gz</a>
tar -xzvf latest.tar.gz
sudo cp -R wordpress/* /var/www/html/</code></pre>



<p>為了確保伺服器有權限讀寫檔案，需要更改目錄的所有權，並刪除原本的預設首頁。</p>



<pre class="wp-block-code"><code>sudo chown -R www-data:www-data /var/www/html/
sudo rm /var/www/html/index.html</code></pre>



<p></p>



<h3 class="wp-block-heading">完成安裝網頁導向</h3>



<p>現在打開瀏覽器並輸入伺服器的 IP 地址。你會看到 WordPress 的設定畫面。依照畫面提示輸入剛才建立的資料庫名稱 wordpress、使用者 wpuser 以及你設定的密碼。</p>



<p>最後設定你的網站標題和管理員帳號密碼，點擊安裝後即可進入後台。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>在 Ubuntu 24.04 上將資料庫更換為 MySQL 的步驟與 MariaDB 非常相似，主要是套件名稱的差異。</p>



<h3 class="wp-block-heading">安裝 MySQL 伺服器</h3>



<p>首先卸載可能存在的 MariaDB 並安裝 MySQL 官方套件。</p>



<pre class="wp-block-code"><code>sudo apt update
sudo apt install mysql-server -y</code></pre>



<p>安裝後，MySQL 服務會自動執行。你可以執行 sudo mysql_secure_installation 來進行基本的安全性設定，例如設置密碼強度與移除匿名用戶。</p>



<h3 class="wp-block-heading">建立 WordPress 資料庫與用戶</h3>



<p>進入 MySQL 終端機進行權限設定。請注意，MySQL 8.0 以上版本對密碼安全性要求較高。</p>



<pre class="wp-block-code"><code>sudo mysql -u root</code></pre>



<p>在 MySQL 提示字元下執行以下指令，請將 password 替換成你的強密碼：</p>



<pre class="wp-block-code"><code>CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;</code></pre>



<p>這裡使用 mysql_native_password 是為了確保 PHP 的插件能順利連線，避免部分版本出現驗證錯誤。</p>



<h3 class="wp-block-heading">調整 PHP 設定與權限</h3>



<p>如果你之前已經移動過 WordPress 檔案，請確認 PHP 的 MySQL 擴充元件已安裝，這能讓 PHP 程式碼與 MySQL 通訊。</p>



<pre class="wp-block-code"><code>sudo apt install php-mysql -y
sudo systemctl restart apache2</code></pre>



<p>接著確認 /var/www/html/ 目錄下的權限是否正確，這關係到你是否能在 WordPress 後台直接安裝外掛或更新。</p>



<pre class="wp-block-code"><code>sudo chown -R www-data:www-data /var/www/html/
sudo chmod -R 755 /var/www/html/</code></pre>



<p></p>



<h3 class="wp-block-heading">完成安裝</h3>



<p>現在你可以直接訪問伺服器 IP，在資料庫主機欄位填入 localhost，並使用剛才建立的 wpuser 與密碼進行連線。如果連線失敗，通常是密碼輸入錯誤或是 mysql_native_password 設定未生效。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>在 Ubuntu 24.04 中，MySQL 預設使用 auth_socket 插件，這表示 root 使用者不需要密碼，而是透過 Linux 系統權限直接登入。如果你需要設定或修改 root 密碼，請依照以下步驟操作。</p>



<h3 class="wp-block-heading">進入 MySQL 修改密碼</h3>



<p>首先使用 sudo 權限進入 MySQL 終端機：</p>



<p>sudo mysql -u root</p>



<p>進入後，執行以下指令來修改密碼。請將 new_password 替換成你想設定的強密碼：</p>



<p>ALTER USER &#8216;root&#8217;@&#8217;localhost&#8217; IDENTIFIED WITH mysql_native_password BY &#8216;new_password&#8217;;</p>



<p>FLUSH PRIVILEGES;</p>



<p>EXIT;</p>



<p>這裡使用 mysql_native_password 是為了確保相容性，讓傳統的 PHP 程式或管理工具能順利連線。</p>



<h3 class="wp-block-heading">驗證密碼修改</h3>



<p>修改完成後，原本的 sudo mysql 指令可能無法直接登入。你需要加上 -p 參數來手動輸入密碼：</p>



<p>mysql -u root -p</p>



<p>系統會提示你輸入剛才設定的密碼，輸入正確後即可進入。</p>



<h3 class="wp-block-heading">恢復成無密碼登入</h3>



<p>如果你發現設定密碼後不方便，想換回原本透過系統權限登入（auth_socket）的方式，可以進入 MySQL 後執行：</p>



<p>ALTER USER &#8216;root&#8217;@&#8217;localhost&#8217; IDENTIFIED WITH auth_socket;</p>



<p>FLUSH PRIVILEGES;</p>



<p>這樣以後只要在終端機輸入 sudo mysql 就能直接管理資料庫。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>你可以透過以下指令來檢查目前 MySQL 所有使用者的身份驗證方式：</p>



<h3 class="wp-block-heading">檢查驗證方式</h3>



<p>請先進入 MySQL 終端機：</p>



<p>sudo mysql -u root -p</p>



<p>登入後執行這段查詢指令：</p>



<p>SELECT user, host, plugin FROM mysql.user;</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="824" height="362" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-02_23-04_m7.jpg?v=1770044666" alt="" class="wp-image-7729" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-02_23-04_m7.jpg?v=1770044666 824w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-02_23-04_m7-600x264.jpg?v=1770044666 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/02/2026-02-02_23-04_m7-768x337.jpg?v=1770044666 768w" sizes="auto, (max-width: 824px) 100vw, 824px" /></figure>



<p>你會看到一個表格，顯示每個使用者對應的 plugin 欄位：</p>



<ol start="1" class="wp-block-list">
<li>如果 plugin 顯示為 auth_socket，代表該帳號是透過 Linux 系統權限登入，不需要在 MySQL 輸入密碼。</li>



<li>如果 plugin 顯示為 mysql_native_password 或 caching_sha2_password，則代表需要使用密碼登入。</li>
</ol>



<h3 class="wp-block-heading">為什麼這很重要</h3>



<p>在 Ubuntu 24.04 上，如果你打算使用圖形化管理工具（如 phpMyAdmin）或某些舊版的外掛程式，通常需要將 root 或專用帳號的 plugin 改為 mysql_native_password，否則連線會被拒絕。</p>



<p></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>wordpress 網頁伺服器掃描攻擊與應對</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/wordpress-scan-attack/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/wordpress-scan-attack/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 05:32:10 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[cloudflare]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7697</guid>

					<description><![CDATA[網站又被太多連線連到連不上網站, 雖然網站掛在 ...]]></description>
										<content:encoded><![CDATA[
<p>網站又被太多連線連到連不上網站, 雖然網站掛在 cloudflare 後面, 還是被太多連線造成網站掛掉.</p>



<h2 class="wp-block-heading">伺服器現況分析</h2>



<p>從你提供的日誌來看，你的伺服器正在遭受大規模的自動化掃描攻擊。這些攻擊者利用工具不斷嘗試存取你多個 WordPress 網站的敏感目錄，例如 wp-includes 或 wp-admin。雖然 Apache 正確地攔截了這些請求並顯示 client denied，但短時間內湧入的龐大連線數已經讓你的系統吃不消。在重啟之前，load average 高達 56，這表示你的 CPU 負載已經爆表，且 1GB 的記憶體完全耗盡，迫使系統頻繁使用硬碟的 Swap 空間，這正是伺服器變得極度緩慢的主因。</p>



<h2 class="wp-block-heading">重啟後的觀察</h2>



<p>重啟 Apache 後，記憶體雖然釋放出了一些空間，load average 也降到了 22，但這個數值對 1GB 的小主機來說依然非常危險。日誌中出現的大量 TIME_WAIT 代表剛才有非常多連線被切斷。目前掃描行為明顯還在持續，如果不做進一步的防護，系統很快會再次因為記憶體不足而陷入卡頓。此外，你在這台小主機上跑了至少五個不同的 WordPress 網站，這會讓資源分配變得非常吃緊。</p>



<h2 class="wp-block-heading">具體應對建議</h2>



<p>既然你的伺服器在 Cloudflare 後面，最有效的辦法是到 Cloudflare 的後台開啟 Under Attack 模式，或者建立 WAF 防護規則。你可以設定一條規則：只要請求的路徑包含 wp-includes 或以 .php 結尾且位於敏感目錄，就直接在 Cloudflare 端阻擋或要求驗證。這樣惡意流量就不會直接撞擊你的 Apache。另外，建議你檢查各個網站的 .htaccess 檔案，確保已經關閉目錄瀏覽功能。如果預算允許，這台主機的記憶體建議增加到 2GB 以上，才能比較穩定地運行這麼多網站。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Cloudflare WAF 防護規則建議</h2>



<p>既然你的日誌顯示攻擊者都在掃描 wp-includes 與 wp-admin 底下的特定 PHP 檔案，你可以直接在 Cloudflare 的 Security -&gt; WAF 建立一條規則。這能讓惡意請求在到達你的 Ubuntu 伺服器前就被攔截，大幅降低 CPU 負載與記憶體消耗。</p>



<h3 class="wp-block-heading">建議的 WAF 規則邏輯</h3>



<p>你可以選擇 Block (直接阻擋) 或 Managed Challenge (要求過圖形驗證)。規則條件建議如下：</p>



<ul class="wp-block-list">
<li><strong>Field</strong>: URI Path</li>



<li><strong>Operator</strong>: contains</li>



<li><strong>Value</strong>: /wp-includes/</li>



<li><strong>AND</strong></li>



<li><strong>Field</strong>: URI Path</li>



<li><strong>Operator</strong>: ends with</li>



<li><strong>Value</strong>: .php</li>
</ul>



<p>這條規則會抓出所有嘗試直接執行 wp-includes 資料夾內程式碼的行為，這在正常的 WordPress 運作中幾乎是不需要的。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">伺服器端優化建議</h2>



<p>除了外層防護，你的主機目前資源非常緊繃，建議調整 Apache 的設定來避免記憶體被耗盡：</p>



<ul class="wp-block-list">
<li><strong>降低 MaxRequestWorkers</strong>: 你的記憶體僅 1GB，如果這個數值設得太高，當攻擊來襲時，Apache 會開啟過多處理程序導致進入 Swap。</li>



<li><strong>調整 KeepAliveTimeout</strong>: 將這個數值改為 2 或 3 秒，讓閒置連線快點斷開，釋放資源給下一個請求。</li>



<li><strong>安裝 Fail2Ban</strong>: 雖然在 Cloudflare 後面，但如果你有安裝 mod_remoteip，Fail2Ban 依然可以根據日誌自動將頻繁掃描的 IP 加入系統防火牆阻擋。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Apache 記憶體優化設定</h3>



<p>針對 1GB 記憶體的伺服器，我們必須嚴格限制 Apache 的行程數量，避免它把記憶體吃光導致系統進入 Swap 甚至當機。請根據你使用的 MPM 模式（通常是 event 或 worker）修改設定。</p>



<p>請編輯 <code>/etc/apache2/mods-available/mpm_event.conf</code> 或 <code>/etc/apache2/mods-available/mpm_worker.conf</code>：</p>



<p>Apache</p>



<pre class="wp-block-code"><code>&lt;IfModule mpm_event_module&gt;
    StartServers             2
    MinSpareThreads          10
    MaxSpareThreads          25
    ThreadsPerChild          25
    # 這是關鍵，限制最大同時連線數，1GB 建議設在 100-150 之間
    MaxRequestWorkers        100
    MaxConnectionsPerChild   1000
&lt;/IfModule&gt;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">連線控制優化</h3>



<p>接著請編輯 <code>/etc/apache2/apache2.conf</code>，調整連線回收的速度：</p>



<ul class="wp-block-list">
<li><strong>KeepAlive On</strong>: 保持開啟，但要縮短時間。</li>



<li><strong>MaxKeepAliveRequests 100</strong>: 限制每個連線的請求數。</li>



<li><strong>KeepAliveTimeout 2</strong>: 原本預設通常是 5 秒，縮短到 2 秒可以讓無用的連線趕快斷開。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">針對 wp-includes 的本地端防護</h3>



<p>雖然 Cloudflare 擋了第一層，但在伺服器本機端也可以加上這段設定，直接在 Apache 層級拒絕非法存取。請將此段加入你的 VirtualHost 設定中：</p>



<p>Apache</p>



<pre class="wp-block-code"><code>&lt;Directory "/var/www/*/wp-includes"&gt;
    &lt;Files "*.php"&gt;
        Require all denied
    &lt;/Files&gt;
&lt;/Directory&gt;
</code></pre>



<p>這樣即便攻擊者繞過 Cloudflare 直接連到你伺服器的 IP，Apache 也會直接回絕請求，不會去執行 PHP 程式，能省下大量 CPU 運算。</p>



<p>設定完成後，請記得執行 <code>sudo apachectl configtest</code> 確認沒語法錯誤，再重啟服務：</p>



<p><code>sudo systemctl restart apache2</code></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>在 Ubuntu 系統中，這類設定通常有兩個地方可以放，取決於你想針對單一網站還是全伺服器生效。</p>



<h3 class="wp-block-heading">1. 針對特定網站（建議做法）</h3>



<p>如果你想針對特定的 WordPress 網站進行防護，請到 <code>/etc/apache2/sites-available/</code> 目錄下找對應的設定檔。例如你的網站名稱可能是 <code>vpn.conf</code> 或 <code>000-default.conf</code>。</p>



<p>你可以使用這個指令列出所有啟用的設定檔路徑：</p>



<p><code>ls /etc/apache2/sites-enabled/</code></p>



<p>然後使用編輯器開啟該檔案：</p>



<p><code>sudo nano /etc/apache2/sites-available/你的檔案名稱.conf</code></p>



<p>將防護程式碼放在 <code>&lt;VirtualHost *:80&gt;</code> 或 <code>&lt;VirtualHost *:443&gt;</code> 的區塊內即可。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. 針對伺服器所有網站</h3>



<p>因為你這台主機跑了 vpn, jasonfonts, stackoverflow, krita 等多個網站，如果你想一次全部保護，可以修改全域安全性設定檔：</p>



<p><code>sudo nano /etc/apache2/conf-available/security.conf</code></p>



<p>將這段程式碼貼在檔案的最末端：</p>



<p>Apache</p>



<pre class="wp-block-code"><code>&lt;Directory "/var/www/*/wp-includes"&gt;
    &lt;Files "*.php"&gt;
        Require all denied
    &lt;/Files&gt;
&lt;/Directory&gt;

&lt;Directory "/var/www/*/wp-content/uploads"&gt;
    &lt;Files "*.php"&gt;
        Require all denied
    &lt;/Files&gt;
&lt;/Directory&gt;
</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>補充：我也順便幫你加上了 uploads 資料夾的 PHP 阻擋，因為那是駭客最常上傳惡意後門程式的地方。</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. 套用並重啟</h3>



<p>如果你是修改 <code>security.conf</code>，請確保該設定檔已啟用：</p>



<p><code>sudo a2enconf security</code></p>



<p>最後檢查語法並重啟 Apache：</p>



<p><code>sudo apachectl configtest</code></p>



<p><code>sudo systemctl restart apache2</code></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>你可以將新的規則邏輯直接加入現有的表達式中。為了讓規則更嚴謹，我們使用括號將 <code>wp-includes</code> 的路徑與 <code>.php</code> 副檔名組合起來。</p>



<p>修改後的 Cloudflare WAF 規則表達式如下：</p>



<p>SQL</p>



<pre class="wp-block-code"><code>(http.request.uri.path contains "/cgi-bin/") 
or (http.referer contains "binance.com") 
or (http.request.uri.path eq "/xmlrpc.php")
or (http.request.uri.path contains "/wp-includes/" and http.request.uri.path targets_lib_path_suffix ".php")
</code></pre>



<p>或是更直覺的寫法：</p>



<p>SQL</p>



<pre class="wp-block-code"><code>(http.request.uri.path contains "/cgi-bin/") 
or (http.referer contains "binance.com") 
or (http.request.uri.path eq "/xmlrpc.php")
or (http.request.uri.path contains "/wp-includes/" and http.request.uri.path matches ".*\.php$")
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">設定說明</h3>



<ul class="wp-block-list">
<li><strong>為什麼要加 AND</strong>: 如果只阻擋 <code>/wp-includes/</code>，會連帶擋掉正常的 CSS 或 JS 檔案，導致網站排版壞掉。加上 <code>.php</code> 的條件後，就只會針對該目錄下的程式執行檔進行阻擋，這是最安全的作法。</li>



<li><strong>建議動作 (Action)</strong>: 既然你目前的 Log 顯示這全是惡意掃描，建議將此規則的 Action 設為 <strong>Block</strong>（阻擋）或 <strong>Managed Challenge</strong>（驗證碼）。</li>
</ul>



<h3 class="wp-block-heading">後續檢查</h3>



<p>設定完成後，你可以觀察 Cloudflare 的 <strong>Security -&gt; Events</strong>，看是否有攔截到來自 <code>/wp-includes/</code> 的請求。如果攔截成功，你 Ubuntu 伺服器上的 Apache <code>error.log</code> 應該就不會再出現這些 IP 的掃描紀錄，系統負載也會隨之下降。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>既然無法使用 Matches 運算子，我們可以改用比較基礎的 <strong>contains</strong> 或 <strong>ends with</strong> 來組合。這在 Cloudflare 免費版或一般方案都能運作。</p>



<h3 class="wp-block-heading">修改後的 WAF 規則建議</h3>



<p>你可以將表達式改成以下內容，這樣就不需要 Matches：</p>



<p>SQL</p>



<pre class="wp-block-code"><code>(http.request.uri.path contains "/cgi-bin/") 
or (http.referer contains "binance.com") 
or (http.request.uri.path eq "/xmlrpc.php")
or (http.request.uri.path contains "/wp-includes/" and http.request.uri.path contains ".php")
</code></pre>



<h3 class="wp-block-heading">為什麼這樣寫有效</h3>



<ul class="wp-block-list">
<li><strong>contains &#8220;.php&#8221;</strong>: 雖然沒有正則表達式那麼精準，但絕大多數針對 <code>wp-includes</code> 的攻擊都是直接存取 <code>.php</code> 檔案。在正常情況下，WordPress 核心不會讓使用者從瀏覽器直接讀取該目錄下的 PHP 檔案，所以這條規則非常安全。</li>



<li><strong>組合條件</strong>: 透過 <code>and</code> 將目錄與副檔名綁在一起，可以確保不會誤擋到 <code>wp-includes</code> 裡的圖片或樣式表（CSS/JS）。</li>
</ul>



<h3 class="wp-block-heading">操作步驟</h3>



<ol start="1" class="wp-block-list">
<li>登入 Cloudflare，進入 <strong>Security > WAF</strong>。</li>



<li>點擊現有規則旁邊的 <strong>Edit</strong>。</li>



<li>點擊右下角的 <strong>Edit expression</strong> 切換到純文字模式。</li>



<li>將上面的代碼貼上並點擊 <strong>Deploy</strong>。</li>
</ol>



<p>設定完成後，建議你先觀察半小時，看伺服器的 load average 是否有從 22 慢慢降下來。如果還有其他特定路徑在報錯，我們可以再繼續擴充這條規則。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>好的，我們把 <code>wp-content/uploads</code> 的防護也併入。在 WordPress 中，uploads 資料夾是用來存放圖片和媒體檔的，絕對不應該出現任何可執行的 <code>.php</code> 檔案。如果有人嘗試在裡面執行 PHP，那幾乎可以確定是駭客上傳了後門程式。</p>



<h3 class="wp-block-heading">更新後的 Cloudflare WAF 表達式</h3>



<p>請將規則更新為以下內容：</p>



<p>SQL</p>



<pre class="wp-block-code"><code>(http.request.uri.path contains "/cgi-bin/") 
or (http.referer contains "binance.com") 
or (http.request.uri.path eq "/xmlrpc.php")
or (http.request.uri.path contains "/wp-includes/" and http.request.uri.path contains ".php")
or (http.request.uri.path contains "/wp-content/uploads/" and http.request.uri.path contains ".php")
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">規則說明與後續建議</h3>



<ul class="wp-block-list">
<li><strong>阻擋 uploads 內的 PHP</strong>: 這是非常強效的防護。駭客最常見的手法是利用外掛漏洞上傳一個名為 <code>shell.php</code> 或 <code>info.php</code> 的檔案到圖片區。現在這條規則會在對方執行這些後門時，直接在 Cloudflare 端切斷連線。</li>



<li><strong>確認負載</strong>: 更新規則後，你可以再次觀察伺服器的 <code>top</code> 指令或 <code>load average</code>。如果規則奏效，連線數（Connection Counts）裡的 <code>ESTABLISHED</code> 數量應該會顯著減少，因為惡意請求在進入你的 Apache 之前就被擋掉了。</li>



<li><strong>檢查其他目錄</strong>: 你的日誌中還提到了 <code>wp-admin/css/colors/ectoplasm/</code> 這種奇怪的掃描，這通常是針對特定外掛漏洞。目前的規則已經涵蓋了最危險的兩個區域（includes 和 uploads）。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>要查看 Cloudflare 攔截了哪些 IP，請按照以下步驟操作，這能幫你確認防護規則是否發揮作用：</p>



<h3 class="wp-block-heading">1. 進入 Cloudflare 事件日誌</h3>



<p>登入 Cloudflare 後，在左側選單點擊 <strong>Security</strong>（安全性） &gt; <strong>Events</strong>（事件）。</p>



<h3 class="wp-block-heading">2. 查看活動摘要</h3>



<p>在該頁面你會看到一個圖表和下方的清單。你可以從清單中看到：</p>



<ul class="wp-block-list">
<li><strong>Action taken</strong>: 如果顯示 <strong>Block</strong>，表示該請求已被成功攔截。</li>



<li><strong>Rule ID</strong>: 確認是否為剛才設定的那條 WAF 規則。</li>



<li><strong>IP address</strong>: 攻擊者的來源 IP。</li>



<li><strong>Path</strong>: 對方嘗試存取的路徑（例如 <code>/wp-includes/xxx.php</code>）。</li>
</ul>



<h3 class="wp-block-heading">3. 使用篩選功能（選用）</h3>



<p>如果事件太多，你可以點擊 <strong>Add filter</strong>，選擇 <strong>Service</strong> 等於 <strong>WAF</strong>，或是直接搜尋特定路徑，這樣就能精確看到針對 WordPress 敏感目錄的攻擊頻率。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">觀察伺服器壓力是否釋放</h3>



<p>在 Cloudflare 設定好之後，建議你在 Ubuntu 終端機執行 <code>uptime</code> 或 <code>top</code>。</p>



<ul class="wp-block-list">
<li>如果 <strong>load average</strong> 從原本的 20-50 降到 2 以下，說明 Cloudflare 已經幫你的 CPU 擋掉了大半的工作。</li>



<li>如果負載依然很高，請再執行一次 <code>netstat -n | awk '/^tcp/ {print $6}' | sort | uniq -c | sort -n</code>，看看 <code>ESTABLISHED</code> 的數量有沒有減少。</li>
</ul>



<p>如果負載還是降不下來，可能還有其他非 PHP 的資源存取（例如大量的圖片請求）在消耗頻寬，到時候我們再針對那些行為調整規則。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/wordpress-scan-attack/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>只有透過 Cloudflare 代理的流量才能順利讀取網頁</title>
		<link>https://stackoverflow.max-everyday.com/2026/01/only-cloudflare-pass/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/01/only-cloudflare-pass/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 01:11:36 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[cloudflare]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7676</guid>

					<description><![CDATA[獲取 Cloudflare IP 列表 在設定防...]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">獲取 Cloudflare IP 列表</h3>



<p>在設定防火牆之前，必須先取得 Cloudflare 官方提供的 IP 位段。這包含 IPv4 與 IPv6 兩個部分。你可以直接從 Cloudflare 官網查看，或是使用 curl 指令在終端機抓取。</p>



<h3 class="wp-block-heading">使用 UFW 設定步驟</h3>



<p>UFW 是 Ubuntu 內建較簡單的防火牆工具。設定的邏輯是先拒絕所有連入 80 與 443 埠的流量，再逐一放行 Cloudflare 的 IP。</p>



<p>首先，確保你的 SSH 連線（通常是 22 埠）已經放行，否則你會把自己鎖在伺服器外：</p>



<pre class="wp-block-code"><code>sudo ufw allow 22/tcp</code></pre>



<p>接著，利用迴圈將 Cloudflare 的 IP 加入允許清單：</p>



<pre class="wp-block-code"><code># 允許 IPv4
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do sudo ufw allow from $ip to any port 80,443 proto tcp; done

# 允許 IPv6
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do sudo ufw allow from $ip to any port 80,443 proto tcp; done</code></pre>



<p>最後啟用防火牆並檢查狀態：</p>



<pre class="wp-block-code"><code>sudo ufw enable
sudo ufw status
</code></pre>



<h3 class="wp-block-heading">使用 iptables 設定方式</h3>



<p>如果你偏好使用 iptables，原理相同，即針對特定的來源 IP 開放目的連接埠。</p>



<pre class="wp-block-code"><code># 允許 IPv4
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do sudo iptables -I INPUT -p tcp -s $ip --dport 80 -j ACCEPT; sudo iptables -I INPUT -p tcp -s $ip --dport 443 -j ACCEPT; done
</code></pre>



<p>請注意，iptables 的設定在重啟後會失效，建議安裝 iptables-persistent 來儲存規則。</p>



<h3 class="wp-block-heading">自動化更新腳本</h3>



<p>Cloudflare 的 IP 偶爾會變動。為了避免失效，建議將上述指令寫成一個 shell 腳本，並利用 crontab 設定每週執行一次。這樣當 Cloudflare 增加新機房時，你的防火牆規則也會自動同步，確保網站服務不會中斷。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>如何設定 crontab 來定期自動執行這些指令？</p>



<h3 class="wp-block-heading">建立自動化更新腳本</h3>



<p>為了確保防火牆規則永遠跟隨 Cloudflare 的最新 IP 清單，我們可以寫一個簡單的腳本。請在你的家目錄建立一個檔案，例如叫 update_cf_ips.sh。</p>



<pre class="wp-block-code"><code>#!/bin/bash

# 先刪除現有的 Cloudflare UFW 規則（可選，或直接覆蓋）
# 這裡建議直接執行允許指令，UFW 會自動處理重複的規則

# 下載最新的 IPv4 並加入 UFW
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
    sudo ufw allow from $ip to any port 80,443 proto tcp
done

# 下載最新的 IPv6 並加入 UFW
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do
    sudo ufw allow from $ip to any port 80,443 proto tcp
done

# 重新載入防火牆
sudo ufw reload
</code></pre>



<p>儲存後，記得給予執行權限：</p>



<pre class="wp-block-code"><code>chmod +x update_cf_ips.sh
</code></pre>



<h3 class="wp-block-heading">設定 Crontab 定期執行</h3>



<p>接著我們使用 crontab 讓系統每週一凌晨三點自動執行這個腳本。</p>



<p>輸入以下指令進入編輯介面：</p>



<pre class="wp-block-code"><code>sudo crontab -e
</code></pre>



<p>在檔案最後面加入這行（請將路徑替換成你實際存放腳本的位置）：</p>



<pre class="wp-block-code"><code>0 3 * * 1 /home/youruser/update_cf_ips.sh &gt; /dev/null 2&gt;&amp;1
</code></pre>



<h3 class="wp-block-heading">驗證規則是否生效</h3>



<p>設定完成後，你可以從外部直接輸入你的伺服器 IP（而非網域名稱）來測試。如果防火牆運作正常，瀏覽器應該會顯示連線逾時，因為你的個人電腦 IP 不在 Cloudflare 的允許清單內。只有透過 Cloudflare 代理的流量才能順利讀取網頁。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">使用對象與權限的區別</h2>



<p>sudo crontab -e 是用來編輯個別使用者的排程。即便你加上 sudo，它通常也是針對 root 這個帳號的個人排程。每個使用者都有自己的 crontab 檔案，這些檔案存放在特定的系統目錄下，不建議直接手動改動。</p>



<p>vi /etc/crontab 則是編輯系統層級的排程。這是一個純文字檔，通常只有系統管理員會去動它。這裡定義的是整個系統要跑的任務，而不是針對某個特定的人。</p>



<h2 class="wp-block-heading">格式上的關鍵不同</h2>



<p>這兩者在語法上最大的差別在於有沒有使用者欄位。</p>



<p>在 sudo crontab -e 裡面，每一行只有五個時間參數加上指令。因為系統已經知道這是 root 的排程，所以不需要再特別註明由誰執行。</p>



<p>在 /etc/crontab 裡面，時間參數後面必須多加一個欄位，指定要用哪個帳號執行指令。例如你想用 root 權限跑程式，就得在指令前寫上 root。如果漏掉這個欄位，排程就不會動。</p>



<h2 class="wp-block-heading">安全性與自動檢查</h2>



<p>使用 crontab -e 有一個很大的好處，就是它會幫你檢查語法。如果你寫錯了，儲存離開時它會提醒你，甚至不讓你存檔。這可以避免因為一個小空格打錯，導致所有排程失效。</p>



<p>直接用 vi 修改 /etc/crontab 就沒有這種防護機制。如果你打錯字或格式不對，系統不會報錯，但任務就是不會執行。對於新手來說，用指令編輯會安全很多。</p>



<h2 class="wp-block-heading">環境變數的設定</h2>



<p>/etc/crontab 是一個設定檔，裡面通常會預設好 PATH 等環境變數。這讓管理系統任務變得比較直觀。</p>



<p>個別使用者的 crontab 往往比較乾淨，環境變數可能跟你的 shell 環境不太一樣。所以寫個人排程時，建議指令都要寫絕對路徑，才不會發生找不到程式的情況。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/01/only-cloudflare-pass/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>封鎖特定 Referer 攻擊 既然這些惡意探測都偽裝成從 binance.com 過來的請求，你可以直接在 .htaccess 阻擋這種來源</title>
		<link>https://stackoverflow.max-everyday.com/2026/01/ban-referer-htaccess/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/01/ban-referer-htaccess/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sun, 25 Jan 2026 21:12:32 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7664</guid>

					<description><![CDATA[這份存取日誌揭露了更多細節，除了搜尋引擎爬蟲（如...]]></description>
										<content:encoded><![CDATA[
<p>這份存取日誌揭露了更多細節，除了搜尋引擎爬蟲（如 Bingbot, ClaudeBot, AhrefsBot）的正常行為外，有幾點異常需要處理：</p>



<h3 class="wp-block-heading">異常請求與機器人掃描</h3>



<p>日誌中出現大量來自 binance.com 的 Referer（來源網址），正在存取你的 wp-includes 目錄下的 PHP 檔案，例如 class-wp-block-parser-frame.php。這明顯是針對 WordPress 核心檔案的惡意探測，雖然回傳 200，但如果你的檔案權限設定正確，通常不會有立即危險，不過這會增加伺服器負荷。</p>



<p>另外，還有一些看起來像是在搜尋特定關鍵字的請求（例如波斯文或阿拉伯文的搜尋字串），這可能是嘗試進行 SQL 注入或利用搜尋功能消耗你的 CPU 資源。</p>



<h3 class="wp-block-heading">內部虛擬連線 (Internal Dummy Connection)</h3>



<p>日誌中頻繁出現 OPTIONS * HTTP/1.0 來自 ::1（本機端）的請求。這是 Apache 用來喚醒閒置子行程的機制。如果你覺得這很佔日誌空間，可以在設定中過濾掉，但它本身不是安全威脅。</p>



<h3 class="wp-block-heading">針對性的優化建議</h3>



<p><strong>一、 封鎖特定 Referer 攻擊</strong></p>



<p>既然這些惡意探測都偽裝成從 binance.com 過來的請求，你可以直接在 .htaccess 阻擋這種來源：</p>



<pre class="wp-block-code"><code>RewriteEngine on
RewriteCond %{HTTP_REFERER} binance\.com &#91;NC]
RewriteRule .* - &#91;F]</code></pre>



<p>如果你的網站掛在 cloudflare 後面, 也可以設定 rule 來擋, 會更有效率:<br></p>



<p><strong>二、 保護 wp-includes 目錄</strong></p>



<p>除了 xmlrpc.php，wp-includes 目錄也不應該被外部直接執行 PHP 檔案。你可以將以下程式碼放入 wp-includes/ 目錄下的 .htaccess 檔案中（如果沒有就建立一個）：</p>



<pre class="wp-block-code"><code>&lt;Files *.php&gt;
    deny from all
&lt;/Files&gt;
&lt;Files wp-tinymce.php&gt;
    allow from all
&lt;/Files&gt;
&lt;Files ms-files.php&gt;
    allow from all
&lt;/Files&gt;
</code></pre>



<p>這會封鎖該目錄下所有 PHP 的直接存取，但保留幾個 WordPress 運作必要的例外。</p>



<p><strong>三、 處理搜尋功能濫用</strong></p>



<p>如果你的網站不需要搜尋功能，或者被大量垃圾關鍵字搜尋，可以考慮安裝外掛限制搜尋頻率，或是透過 Cloudflare 的 WAF 規則，阻擋包含特殊字元或非預期語系的搜尋請求。</p>



<p><strong>四、 設定連線超時 (Timeout)</strong></p>



<p>在 Apache 設定中縮短連線等待時間，可以讓那些佔著連線不放的機器人趕快斷線，釋放 Workers：</p>



<p>將 Timeout 改為 30 甚至 15（秒），並確保 KeepAliveTimeout 設在 2 到 5 之間。</p>



<p>你目前的伺服器負載感覺已經緊繃，調整完這些設定後，建議觀察 top 或 htop 查看記憶體與 CPU 的即時變化。</p>



<p>這個參考解法，由原本預設的的 mpm_prefork 切換為改用 mpm_event<br><a href="https://stackoverflow.max-everyday.com/2026/02/1cpu-1gb-ram-wordpress-vps/#mpm_event">https://stackoverflow.max-everyday.com/2026/02/1cpu-1gb-ram-wordpress-vps/#mpm_event</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/01/ban-referer-htaccess/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
