

<?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>linux &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Thu, 02 Apr 2026 03:53:12 +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>linux &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>git push 每次都要輸入密碼鎖(passphrase)的解法</title>
		<link>https://stackoverflow.max-everyday.com/2026/04/git-push-passphrase/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/04/git-push-passphrase/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 01 Apr 2026 09:17:05 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8219</guid>

					<description><![CDATA[之前產生的 SSH 金鑰有設定密碼鎖。雖然這比沒...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="559" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/git-push-passphrase_clean-1024x559.jpg?v=1775035163" alt="" class="wp-image-8222" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/git-push-passphrase_clean-1024x559.jpg?v=1775035163 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/git-push-passphrase_clean-600x327.jpg?v=1775035163 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/git-push-passphrase_clean-768x419.jpg?v=1775035163 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/git-push-passphrase_clean.jpg?v=1775035163 1408w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>之前產生的 SSH 金鑰有設定密碼鎖。雖然這比沒設密碼安全，但每次都要輸入確實很麻煩。如果你不想重新產生金鑰，有兩個方法可以解決。</p>



<h2 class="wp-block-heading">使用 ssh-agent 自動管理</h2>



<p>這是最推薦的做法。你可以讓系統在背景跑一個代理程式，幫你記住解鎖後的金鑰。只要在 WSL 終端機執行這兩行指令：</p>



<pre class="wp-block-code"><code>eval $(ssh-agent -s)
ssh-add ~/.ssh/id_rsa_personal</code></pre>



<p>執行第二行時，輸入最後一次密碼。之後只要這個視窗沒關掉，再次 push 就不會再問你密碼。</p>



<p>如果你希望每次開啟 WSL 都自動生效，可以把這兩行指令加到 ~/.bashrc 檔案的最末端。這樣每天第一次開機輸入一次，之後整天都不用再打。</p>



<h2 class="wp-block-heading">移除金鑰本身的密碼</h2>



<p>如果你覺得在私有電腦上不需要這層保護，也可以直接把金鑰的密碼拿掉。執行這行指令：</p>



<pre class="wp-block-code"><code>ssh-keygen -p -f ~/.ssh/id_rsa_personal</code></pre>



<p>系統會先要求你輸入舊密碼。接著會問你新的密碼，這時直接按兩次 Enter 留白。這樣這組金鑰就會變成無密碼狀態，以後執行 git push 就會直接通過。</p>



<h2 class="wp-block-heading">確認設定是否正確</h2>



<p>處理完密碼後，你可以測試一下連線是否正常。輸入：</p>



<pre class="wp-block-code"><code>ssh -T git@github.com -i ~/.ssh/id_rsa_personal</code></pre>



<p>如果看到 Hi 帳號名！You&#8217;ve successfully authenticated，就代表搞定了。以後不管 Windows 那邊登入哪個帳號，WSL 這邊都會走你這組專屬的 SSH 金鑰。</p>



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



<p>如果你使用的是 zsh，要把設定寫在 <strong>~/.zshrc</strong> 這個檔案裡。</p>



<h2 class="wp-block-heading">修改設定檔</h2>



<p>你可以使用 nano 或 vim 來編輯：</p>



<pre class="wp-block-code"><code>nano ~/.zshrc</code></pre>



<p>把下面這段程式碼貼到檔案的最末端：</p>



<p>Bash</p>



<pre class="wp-block-code"><code>if &#91; -z "$SSH_AUTH_SOCK" ]; then
   eval $(ssh-agent -s)
   ssh-add ~/.ssh/id_rsa_personal
fi
</code></pre>



<p>存檔離開後，執行 <strong>source ~/.zshrc</strong> 讓設定立即生效。這樣你下次開啟新的 zsh 視窗時，系統就會自動啟動代理並載入你的金鑰。</p>



<h2 class="wp-block-heading">使用 oh-my-zsh 插件</h2>



<p>如果你有安裝 oh-my-zsh，其實有一個更優雅的插件做法。在 ~/.zshrc 找到 <strong>plugins=(&#8230;)</strong> 這行，把 <strong>ssh-agent</strong> 加進去：</p>



<pre class="wp-block-code"><code>plugins=(git ssh-agent)</code></pre>



<p>接著在下面補上一行設定，指定要自動載入的金鑰名稱：</p>



<pre class="wp-block-code"><code>zstyle :omni:plugins:ssh-agent identities id_rsa_personal</code></pre>



<p>這樣它會在你開啟終端機時自動處理一切，不用自己寫 shell script。</p>



<h2 class="wp-block-heading">解決重複啟動問題</h2>



<p>要注意的是，如果直接在設定檔寫 eval，每次開新視窗都會產生一個新的 ssh-agent 處理程序。如果你發現系統變慢，或是用 ps 指令看到一堆 ssh-agent，建議使用上面提到的 if 判斷式，或是安裝 <strong>keychain</strong> 這個套件來管理。</p>



<p>keychain 會幫你找現有的代理程序，確保整個系統只跑一個 ssh-agent。這對於習慣開多個分頁的人來說，是比較乾淨的做法。</p>



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



<h2 class="wp-block-heading">關於 Keychain</h2>



<p>keychain 是一個用來管理 ssh-agent 的工具。它的好處是能讓所有開啟的終端機視窗共用同一個 ssh-agent。如果不使用它，你每開一個新的 zsh 分頁，系統可能就會跑一個新的 ssh-agent 程式，久了會變得很亂。</p>



<p>keychain 會在背景記住你解鎖過的金鑰。只要你在第一次登入時輸入過一次密碼，之後不管是重開分頁還是執行 git push，它都不會再煩你。</p>



<h2 class="wp-block-heading">安裝方式</h2>



<p>在 Ubuntu 或 WSL (Ubuntu) 環境下，安裝非常簡單。直接輸入這行指令：</p>



<pre class="wp-block-code"><code>sudo apt update &amp;&amp; sudo apt install keychain</code></pre>



<p>安裝完後，它還不會自動運作，需要去修改你的 zsh 設定檔。</p>



<h2 class="wp-block-heading">設定 zsh 自動執行</h2>



<p>你需要把啟動指令加進 <strong>~/.zshrc</strong>。請編輯該檔案：</p>



<p>nano ~/.zshrc</p>



<p>在檔案最後面加上這兩行程式碼：</p>



<p>Bash</p>



<pre class="wp-block-code"><code>/usr/bin/keychain --nogui ~/.ssh/id_rsa_personal
source ~/.keychain/$HOST-sh
</code></pre>



<p>第一行是叫 keychain 去管理你的那把金鑰。第二行則是載入相關的環境變數，讓目前的 zsh 知道要去哪裡找已經解鎖的金鑰。</p>



<h2 class="wp-block-heading">實際使用效果</h2>



<p>設定完成後，執行 <strong>source ~/.zshrc</strong> 或是重開視窗。這時候系統會最後一次詢問你金鑰的密碼。</p>



<p>輸入完畢後，這把金鑰就會一直保持在解鎖狀態。就算你開了十個 zsh 視窗，也都只需要輸入那一次密碼。這對頻繁使用 git push 的開發者來說，是最省心也兼顧安全的方法。</p>



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



<p>在 Windows CMD 環境下，Git 每次 push 都要求輸入密碼鎖，通常是因為 SSH Agent 沒有在背景執行，或是金鑰沒有被正確載入。以下提供兩個主要的解決方案。</p>



<h3 class="wp-block-heading">使用 Windows 內建的 OpenSSH 服務</h3>



<p>這是最推薦的做法，因為它可以讓 SSH Agent 在開機時自動啟動，並持久化儲存你的金鑰密碼。</p>



<p>以管理員身分開啟 PowerShell，執行以下指令將 OpenSSH Authentication Agent 服務設定為自動啟動</p>



<pre class="wp-block-code"><code>Set-Service -Name ssh-agent -StartupType AutomaticStart-Service ssh-agent</code></pre>



<p>回到一般的 CMD 視窗，將你的私鑰加入 Agent。假設你的金鑰路徑是預設值：</p>



<pre class="wp-block-code"><code>ssh-add %USERPROFILE%\.ssh\id_rsa</code></pre>



<p>執行後系統會要求你輸入最後一次密碼鎖。之後只要服務維持執行狀態，重開 CMD 也不需要再輸入密碼。</p>



<p>執行上述指令, 錯誤訊息:</p>



<pre class="wp-block-preformatted">Error connecting to agent: No such file or directory</pre>



<p>這個錯誤通常是因為 CMD 無法識別 %USERPROFILE% 後接續的路徑格式，或是 ssh-agent 服務雖然啟動了，但目前的視窗環境變數還沒有對接上。你可以依照以下步驟排查並修正。</p>



<h3 class="wp-block-heading">修正路徑格式與環境變數</h3>



<p>在 CMD 中，路徑的分隔符號與變數引用非常嚴格。請嘗試手動補上反斜線，並加上雙引號確保路徑正確：</p>



<pre class="wp-block-code"><code>ssh-add "%USERPROFILE%\.ssh\id_rsa"</code></pre>



<p>如果依然顯示無法連線到 Agent，請在同一個 CMD 視窗內執行以下指令，手動啟動 Agent 並設定環境變數：</p>



<pre class="wp-block-code"><code>for /f "tokens=1-2 delims==;" %a in ('ssh-agent -s') do set %a=%b</code></pre>



<p>執行完畢後，再次嘗試執行 ssh-add 指令。</p>



<h3 class="wp-block-heading">確認 SSH 服務執行狀態</h3>



<p>如果手動啟動有效，但每次開新視窗都要重來，代表系統服務沒有正確常駐。請再次確認服務狀態：</p>



<ol start="1" class="wp-block-list">
<li>按下 Win + R 鍵，輸入 services.msc 並執行。</li>



<li>找到 OpenSSH Authentication Agent。</li>



<li>確認狀態為 正在執行，且啟動類型為 自動。</li>
</ol>



<p>結果是服務被停用, 啟用就好了.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="590" height="710" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/2026-04-02_11-51_n3.jpg?v=1775101951" alt="" class="wp-image-8230" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/2026-04-02_11-51_n3.jpg?v=1775101951 590w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/04/2026-04-02_11-51_n3-499x600.jpg?v=1775101951 499w" sizes="(max-width: 590px) 100vw, 590px" /></figure>



<h3 class="wp-block-heading">檢查 GIT_SSH 環境變數</h3>



<p>有時候安裝 Git 時會內建自家的 SSH 套件，這會干擾系統內建的 ssh-add。請檢查你的環境變數中是否有名為 GIT_SSH 的變數。如果有，請將它刪除，讓 Git 預設使用系統路徑 C:\Windows\System32\OpenSSH\ssh.exe。</p>



<p>另外，請確認你的 .ssh 資料夾內確實存在 id_rsa 這個檔案。你可以輸入 dir %USERPROFILE%.ssh 來查看檔案清單。如果你的金鑰檔名不是 id_rsa (例如是 id_ed25519)，請將指令中的檔名更換為正確的名稱。</p>



<h3 class="wp-block-heading">設定 Git 使用內建的 SSH 工具</h3>



<p>有時候 Git 會使用自己打包的 SSH 工具而不是 Windows 系統路徑下的工具，這會導致兩者金鑰紀錄不互通。你可以強制 Git 指向系統的 SSH 路徑：</p>



<pre class="wp-block-code"><code>git config --global core.sshCommand C:/Windows/System32/OpenSSH/ssh.exe</code></pre>



<h3 class="wp-block-heading">修改金鑰設定移除密碼鎖</h3>



<p>如果你覺得維護 Agent 服務太麻煩，且確認電腦環境安全，也可以選擇直接移除私鑰的密碼鎖。</p>



<p>執行以下指令：</p>



<pre class="wp-block-code"><code>ssh-keygen -p -f %USERPROFILE%.ssh\id_rsa</code></pre>



<p>系統會先要求輸入舊密碼，當詢問新密碼時直接按兩次 Enter 留白。這樣該金鑰就會變成無密碼狀態，之後任何 Git 操作都不會再跳出輸入提示。不過請注意，這會降低金鑰外洩時的安全性。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/04/git-push-passphrase/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>UFW 限制特定 IP 訪問 3306</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ufw-ip-3306/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ufw-ip-3306/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 05 Feb 2026 05:18:03 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7739</guid>

					<description><![CDATA[設定 UFW 規則 要精確限制只有 10.130...]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">設定 UFW 規則</h3>



<p>要精確限制只有 10.130.0.6 這個 IP 能夠連線到本機的 3306 埠口，請執行以下指令：</p>



<pre class="wp-block-code"><code>sudo ufw allow from 10.130.0.6 to any port 3306</code></pre>



<p>這條規則會明確指定來源（from）必須是 10.130.0.6，目標（to any）則是本機任何網路介面上的 3306 埠口。如果你有多張網卡，想限制得更嚴格，可以把 any 改成本機在該網路環境下的私人 IP。</p>



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



<h3 class="wp-block-heading">確認規則優先順序</h3>



<p>在 UFW 中，規則的順序非常重要。如果之前已經有過開放給所有人的規則（例如 allow 3306），新加入的特定 IP 規則可能會失效。請使用以下指令檢查：</p>



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



<p>請確認針對 10.130.0.6 的規則排在最前面。如果發現有其他更寬鬆的規則排在上面（例如 3306 ALLOW ANYWHERE），請使用 sudo ufw delete 加上編號將其刪除，確保防火牆只對特定 IP 放行。</p>



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



<h3 class="wp-block-heading">資料庫連線配置</h3>



<p>即使防火牆門開了，MySQL 或 MariaDB 如果沒有監聽正確的介面，連線依然會失敗。請檢查設定檔（通常在 /etc/mysql/mariadb.conf.d/50-server.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf）：</p>



<pre class="wp-block-code"><code>bind-address = 0.0.0.0</code></pre>



<p>如果這裡設定為 127.0.0.1，則外部 IP（包含 10.130.0.6）將無法連入，因為資料庫只接受來自 localhost 內部的連線。修改後記得重啟資料庫服務：sudo systemctl restart mysql。</p>



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



<h3 class="wp-block-heading">查詢 IP 位址與網路設定</h3>



<p>在 Ubuntu 中，最常用且推薦的指令是 ip addr，你可以簡寫為 ip a。這個指令會列出所有網路介面的詳細資訊。</p>



<h3 class="wp-block-heading">常用查詢指令</h3>



<p>如果你只需要快速看一眼 IP，或是需要詳細的設定資訊，可以參考以下幾種指令：</p>



<ul class="wp-block-list">
<li><strong>詳細資訊：</strong> ip addr show 或 ip a。這會顯示每個介面的 MAC 位址、IPv4、IPv6 以及運作狀態。</li>



<li><strong>精簡格式：</strong> ip -br addr。這會以一行一個介面的方式列出 IP，適合快速閱讀。</li>



<li><strong>純 IP 位址：</strong> hostname -I。這會直接印出本機目前所有的私人 IP，不含其他雜訊。</li>



<li><strong>對外公網 IP：</strong> curl ifconfig.me。如果你想知道在網際網路上的 IP，可以使用這個指令向外部伺服器查詢。</li>
</ul>



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



<h3 class="wp-block-heading">解讀 ip addr 輸出內容</h3>



<p>當你執行 ip a 時，你會看到類似以下的內容：</p>



<p>2: enp0s3: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 &#8230;</p>



<p>link/ether 08:00:27:xx:xx:xx brd ff:ff:ff:ff:ff:ff</p>



<p>inet 192.168.1.105/24 brd 192.168.1.255 scope global dynamic enp0s3</p>



<p>valid_lft 86134sec preferred_lft 86134sec</p>



<ul class="wp-block-list">
<li><strong>enp0s3：</strong> 這是網路介面的名稱（以前常叫 eth0）。</li>



<li><strong>inet：</strong> 後面接的就是你的 <strong>IPv4 位址</strong>（例如 192.168.1.105）。</li>



<li><strong>UP：</strong> 代表該介面目前正在運作中。</li>



<li><strong>link/ether：</strong> 這是你的硬體位址（MAC Address）。</li>
</ul>



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



<h3 class="wp-block-heading">靜態 IP 設定位置</h3>



<p>如果你想修改 IP 設定使其永久生效，Ubuntu 現在預設使用 Netplan 工具。設定檔通常存放在以下路徑：</p>



<p>/etc/netplan/</p>



<p>檔案通常是 .yaml 格式，例如 01-netcfg.yaml。編輯該檔案後，需要執行 sudo netplan apply 才能讓設定生效。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ufw-ip-3306/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ubuntu 24 安裝 Oh My Zsh</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-oh-my-zsh/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-oh-my-zsh/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 14:32:40 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7715</guid>

					<description><![CDATA[在 Ubuntu 24.04 安裝 Oh My ...]]></description>
										<content:encoded><![CDATA[
<p>在 Ubuntu 24.04 安裝 Oh My Zsh 的步驟非常直覺，主要分為安裝 Zsh 本體、下載 Oh My Zsh 框架以及後續的套件設定。</p>



<h2 class="wp-block-heading">安裝 Zsh</h2>



<p>Ubuntu 預設使用 Bash，所以要先安裝 Zsh 並將其設為預設 shell。</p>



<p>Bash</p>



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

# 安裝 zsh 與 git（下載框架時需要）
sudo apt install zsh git curl -y

# 確認安裝版本
zsh --version

# 將 Zsh 設為目前使用者的預設 shell
chsh -s $(which zsh)
</code></pre>



<p>執行完成後，需要登出並重新登入，或者直接重啟電腦，變更才會生效。</p>



<h2 class="wp-block-heading">安裝 Oh My Zsh</h2>



<p>Oh My Zsh 提供了一鍵安裝腳本，你可以選擇使用 curl 或 wget 來執行。</p>



<p>Bash</p>



<pre class="wp-block-code"><code># 使用 curl 安裝
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
</code></pre>



<p>安裝過程中，腳本會詢問是否要將 Zsh 設為預設 shell，如果你剛才已經執行過 chsh，這裡選 Y 或 N 都可以。安裝成功後，你會看到經典的 Oh My Zsh 大 Logo。</p>



<h2 class="wp-block-heading">常用插件與主題設定</h2>



<p>預設的主題是 robbyrussell。如果想修改主題或啟用插件，請編輯家目錄下的設定檔。</p>



<p>Bash</p>



<pre class="wp-block-code"><code>nano ~/.zshrc
</code></pre>



<p>在檔案中找到以下內容進行修改：</p>



<ul class="wp-block-list">
<li>主題：修改 ZSH_THEME=&#8221;robbyrussell&#8221; 這一行。</li>



<li>插件：找到 plugins=(git) 這一行，可以在括號內加入其他預設插件，例如 plugins=(git docker sudo)。</li>
</ul>



<h2 class="wp-block-heading">推薦安裝外掛（自動補全與語法高亮）</h2>



<p>這兩個外掛能大幅提升使用體驗，需要額外從 GitHub 下載。</p>



<p>Bash</p>



<pre class="wp-block-code"><code># 語法高亮 (zsh-syntax-highlighting)
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

# 自動補全建議 (zsh-autosuggestions)
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
</code></pre>



<p>下載後，請再次編輯 ~/.zshrc，將它們加入 plugins 清單中：</p>



<p>Bash</p>



<pre class="wp-block-code"><code>plugins=(git zsh-syntax-highlighting zsh-autosuggestions)
</code></pre>



<p>最後執行 source ~/.zshrc 讓設定立即生效。</p>



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



<p>這是一個完整的自動化腳本，你可以將其內容複製並存成 install_zsh.sh，然後執行它。這個腳本會幫你安裝 Zsh、Oh My Zsh 以及兩個最受歡迎的插件。</p>



<h2 class="wp-block-heading">自動化安裝腳本</h2>



<p>這個腳本包含了環境檢查與插件配置，適合在乾淨的 Ubuntu 24.04 環境執行。</p>



<p>Bash</p>



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

# 更新套件並安裝必要工具
sudo apt update &amp;&amp; sudo apt install -y zsh git curl

# 下載並安裝 Oh My Zsh (自動跳過互動模式)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended

# 定義插件路徑
ZSH_CUSTOM_DIR=${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}

# 安裝 zsh-syntax-highlighting
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM_DIR/plugins/zsh-syntax-highlighting

# 安裝 zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM_DIR/plugins/zsh-autosuggestions

# 修改 .zshrc 啟用插件
sed -i 's/plugins=(git)/plugins=(git zsh-syntax-highlighting zsh-autosuggestions)/' ~/.zshrc

# 切換預設 Shell
sudo chsh -s $(which zsh) $USER

echo "安裝完成，請重新啟動終端機或輸入 'zsh' 開始使用。"
</code></pre>



<h2 class="wp-block-heading">如何執行</h2>



<p>請在終端機依照順序輸入以下指令。</p>



<p>Bash</p>



<pre class="wp-block-code"><code># 建立腳本檔案
nano install_zsh.sh

# 將上面的程式碼貼入後，按 Ctrl+O 儲存，Ctrl+X 離開

# 賦予執行權限
chmod +x install_zsh.sh

# 執行腳本
./install_zsh.sh
</code></pre>



<h2 class="wp-block-heading">注意事項</h2>



<p>腳本執行完畢後，目前的畫面可能還是舊的 Bash，請直接輸入 zsh 切換，或者關閉視窗重新開啟。如果你發現指令補全的顏色太暗看不清楚，這是因為終端機配色（如預設的 Ubuntu 紫色背景）與外掛顏色衝突，建議到終端機設定調整配色方案為內建的 Color schemes 即可。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-oh-my-zsh/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ubuntu VPS 增加 Swap 空間</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ubuntu-vps-swap/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ubuntu-vps-swap/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 13:40:46 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7712</guid>

					<description><![CDATA[要在 Ubuntu 24.04 的 VPS 上增...]]></description>
										<content:encoded><![CDATA[
<p>要在 Ubuntu 24.04 的 VPS 上增加 swap 空間，你可以按照下列步驟操作。這通常用於記憶體較小的伺服器，防止因為記憶體不足導致程式崩潰。</p>



<h3 class="wp-block-heading">檢查目前的 swap 狀態</h3>



<p>在開始之前，先確認系統是否已經有 swap 空間。輸入 free -h 或是 swapon &#8211;show。如果輸出結果是空的，代表目前沒有 swap。</p>



<h3 class="wp-block-heading">建立 swap 檔案</h3>



<p>決定你要增加的大小，通常建議是記憶體的 1 倍到 2 倍。這裡以增加 2G 為例。</p>



<p>使用 fallocate 指令快速建立檔案：</p>



<pre class="wp-block-code"><code>sudo fallocate -l 2G /swapfile</code></pre>



<p>如果系統提示找不到 fallocate，也可以使用傳統的 dd 指令：</p>



<pre class="wp-block-code"><code>sudo dd if=/dev/zero of=/swapfile bs=1M count=2048</code></pre>



<h3 class="wp-block-heading">設定檔案權限</h3>



<p>為了安全起見，只有 root 使用者應該有讀寫 swap 檔案的權限。</p>



<pre class="wp-block-code"><code>sudo chmod 600 /swapfile</code></pre>



<h3 class="wp-block-heading">格式化並啟用檔案</h3>



<p>將該檔案轉化為 swap 格式：</p>



<pre class="wp-block-code"><code>sudo mkswap /swapfile</code></pre>



<p>接著啟用它：</p>



<pre class="wp-block-code"><code>sudo swapon /swapfile</code></pre>



<p>此時你可以再次輸入 free -h，應該就能看到 swap 欄位出現了剛才設定的大小。</p>



<h3 class="wp-block-heading">設定開機自動掛載</h3>



<p>目前的設定在重啟伺服器後會消失。為了讓它永久生效，需要修改 /etc/fstab 檔案。</p>



<p>建議先備份檔案：</p>



<pre class="wp-block-code"><code>sudo cp /etc/fstab /etc/fstab.bak</code></pre>



<p>然後將設定寫入：</p>



<pre class="wp-block-code"><code>echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab</code></pre>



<h3 class="wp-block-heading">調整 swappiness 參數</h3>



<p>swappiness 決定系統使用 swap 的頻率，數值在 0 到 100 之間。對於 VPS 來說，通常設定在 10 到 60 之間比較合適。數值愈小，系統愈傾向使用實體記憶體。</p>



<p>查看目前數值：</p>



<pre class="wp-block-code"><code>cat /proc/sys/vm/swappiness</code></pre>



<p>如果你想暫時修改為 10：</p>



<pre class="wp-block-code"><code>sudo sysctl vm.swappiness=10</code></pre>



<p>若要永久修改，請編輯 /etc/sysctl.conf</p>



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



<p>在檔案末尾加入</p>



<pre class="wp-block-code"><code>vm.swappiness=10</code></pre>



<p>或直接使用 script 修改</p>



<pre class="wp-block-code"><code>echo "調整 swappiness 為 10..."
sysctl vm.swappiness=10
if ! grep -q "vm.swappiness" /etc/sysctl.conf; then
    echo "vm.swappiness=10" >> /etc/sysctl.conf
else
    sed -i 's/vm.swappiness=.*/vm.swappiness=10/' /etc/sysctl.conf
fi</code></pre>



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



<p>這是一個自動化腳本，你可以將它儲存在伺服器上執行。這個腳本會自動建立一個 2G 的 swap 檔案，並完成所有權限與永久掛載的設定。</p>



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



<p>你可以使用 nano 建立檔案：</p>



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



<p>將以下內容貼上：</p>



<p>Bash</p>



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

# 設定 swap 大小為 2G
SWAP_SIZE="2G"
SWAP_PATH="/swapfile"

# 檢查是否具備 root 權限
if &#91;&#91; $EUID -ne 0 ]]; then
   echo "請使用 sudo 執行此腳本"
   exit 1
fi

echo "正在建立 ${SWAP_SIZE} 的 swap 檔案..."
fallocate -l $SWAP_SIZE $SWAP_PATH || dd if=/dev/zero of=$SWAP_PATH bs=1M count=2048

echo "設定權限..."
chmod 600 $SWAP_PATH

echo "格式化 swap..."
mkswap $SWAP_PATH

echo "啟用 swap..."
swapon $SWAP_PATH

echo "設定開機自動掛載..."
if ! grep -q "$SWAP_PATH" /etc/fstab; then
    echo "$SWAP_PATH none swap sw 0 0" &gt;&gt; /etc/fstab
fi

echo "調整 swappiness 為 10..."
sysctl vm.swappiness=10
if ! grep -q "vm.swappiness" /etc/sysctl.conf; then
    echo "vm.swappiness=10" &gt;&gt; /etc/sysctl.conf
else
    sed -i 's/vm.swappiness=.*/vm.swappiness=10/' /etc/sysctl.conf
fi

echo "完成！目前的記憶體狀態："
free -h
</code></pre>



<h3 class="wp-block-heading">執行腳本</h3>



<p>存檔離開後（Ctrl+O 然後 Ctrl+X），賦予執行權限並執行：</p>



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



<h3 class="wp-block-heading">確認結果</h3>



<p>執行完畢後，你可以觀察最後顯示的表格。如果 swap 這一列的總量（total）不再是 0，就代表設定成功。這個腳本也幫你處理了 swappiness 的設定，讓伺服器優先使用物理記憶體，只有在必要時才動用硬碟上的 swap，這有助於維持效能。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ubuntu-vps-swap/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ubuntu 24 無法直接安裝 python package</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 12:59:13 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7706</guid>

					<description><![CDATA[在 Ubuntu 24.04 中，系統預設安裝 ...]]></description>
										<content:encoded><![CDATA[
<p>在 Ubuntu 24.04 中，系統預設安裝 Python 3.12。為了維護系統穩定，這類較新的 Linux 版本採用了 PEP 668 規範，限制直接使用 pip 將套件安裝到全域環境。如果你直接執行 pip install，通常會看到外部管理環境的錯誤提示。</p>



<h3 class="wp-block-heading">使用虛擬環境安裝</h3>



<p>這是目前最推薦且標準的作法，可以避免不同專案之間的套件衝突。你必須先安裝 venv 工具，然後建立一個獨立的資料夾來存放套件。</p>



<pre class="wp-block-code"><code>sudo apt update
sudo apt install python3-venv
python3 -m venv myenv
source myenv/bin/activate</code></pre>



<p>進入虛擬環境後，終端機提示字元前會出現環境名稱，這時你就可以放心使用 pip install 安裝任何套件，它們會被存放在 myenv 資料夾內。</p>



<h3 class="wp-block-heading">使用 pipx 安裝工具</h3>



<p>如果你想安裝的是像 black、ansible 或 flake8 這種可以在終端機直接執行的工具，而不是要在程式碼裡 import 的函式庫，pipx 是最好的選擇。它會自動幫每個工具建立隔離環境並設定好執行路徑。</p>



<pre class="wp-block-code"><code>sudo apt install pipx
pipx ensurepath
pipx install 套件名稱</code></pre>



<h3 class="wp-block-heading">使用 APT 系統套件管理</h3>



<p>如果你需要的套件非常常見，例如 NumPy 或 Requests，Ubuntu 的官方軟體倉庫通常會有維護好的版本。這些套件會安裝在全域，且由系統統一管理。</p>



<pre class="wp-block-code"><code>sudo apt install python3-numpy</code></pre>



<h3 class="wp-block-heading">強制全域安裝</h3>



<p>雖然非常不建議，但如果你非得在全域環境安裝套件且不在乎系統穩定性，可以使用 break-system-packages 參數來跳過保護機制。請注意這可能會導致 Ubuntu 系統內建的 Python 工具故障。</p>



<pre class="wp-block-code"><code>pip install 套件名稱 --break-system-packages</code></pre>



<p>要退出已經啟動的 Python 虛擬環境，方法非常簡單，只需要在終端機輸入一個指令即可。</p>



<h3 class="wp-block-heading">使用 deactivate 指令</h3>



<p>當你完成工作，想要回到 Ubuntu 系統預設的 Python 環境時，直接輸入：</p>



<pre class="wp-block-code"><code>deactivate</code></pre>



<p>執行後，你會發現終端機提示字元前方的括號環境名稱（例如 (myenv)）消失了，這表示你已經成功登出虛擬環境。這個指令不需要加上 sudo，也不需要路徑，因為在你啟動環境時，deactivate 函式就已經被載入到目前的 shell 階段中。</p>



<h3 class="wp-block-heading">刪除虛擬環境</h3>



<p>如果你不再需要這個虛擬環境，想要徹底移除它，做法並非透過 pip 卸載，而是直接刪除該環境所在的資料夾。</p>



<pre class="wp-block-code"><code>rm -rf myenv</code></pre>



<p>這會刪除所有在該環境中安裝的套件與相關設定，且不會影響到系統其他的 Python 設定。</p>



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



<p>python3 -m pip install pr pip-req.txt<br>error: externally-managed-environment</p>



<p>× This environment is externally managed<br>╰─&gt; To install Python packages system-wide, try apt install<br>python3-xyz, where xyz is the package you are trying to<br>install.</p>



<pre class="wp-block-code"><code>If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.

If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.

See /usr/share/doc/python3.12/README.venv for more information.</code></pre>



<p>note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing &#8211;break-system-packages.<br>hint: See PEP 668 for the detailed specification.</p>



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



<p>python3 -m venv ./venv<br>The virtual environment was not created successfully because ensurepip is not<br>available. On Debian/Ubuntu systems, you need to install the python3-venv<br>package using the following command.</p>



<pre class="wp-block-code"><code>apt install python3.12-venv</code></pre>



<p>You may need to use sudo with that command. After installing the python3-venv<br>package, recreate your virtual environment.</p>



<p>Failing command: /root/venv/bin/python3</p>



<p>➜ ~ apt install python3-venv</p>



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



<p>在 Ubuntu 24.04 上為 Python 3.12 安裝 MySQL 連接器，最穩定的做法是透過虛擬環境。目前主流有兩種套件選擇：官方的 mysql-connector-python 或社群常用的 mysqlclient。</p>



<h3 class="wp-block-heading">準備系統依賴項目</h3>



<p>在安裝 Python 套件之前，建議先安裝編譯所需的系統開發庫。如果是要安裝 mysqlclient（效能較好），則必須先執行以下指令：</p>



<p>sudo apt update</p>



<p>sudo apt install python3-dev default-libmysqlclient-dev build-essential</p>



<h3 class="wp-block-heading">在虛擬環境中安裝</h3>



<p>首先建立並進入虛擬環境，接著使用 pip 安裝。</p>



<p>python3 -m venv env</p>



<p>source env/bin/activate</p>



<p>如果你想安裝官方提供的連接器：</p>



<p>pip install mysql-connector-python</p>



<p>如果你想安裝效能較佳、符合 Python DB API 規範的套件：</p>



<p>pip install mysqlclient</p>



<h3 class="wp-block-heading">驗證安裝結果</h3>



<p>你可以進入 Python 互動環境測試是否安裝成功：</p>



<p>python</p>



<p>import mysql.connector</p>



<p>print(mysql.connector.<strong>version</strong>)</p>



<p>或是針對 mysqlclient：</p>



<p>python</p>



<p>import MySQLdb</p>



<p>print(MySQLdb.<strong>version</strong>)</p>



<h3 class="wp-block-heading">使用 APT 安裝（全域環境）</h3>



<p>如果你不想使用虛擬環境，而是希望整個系統都能使用，可以使用 Ubuntu 官方維護的套件。這會自動處理所有依賴關係，且不會觸發 PEP 668 的外部環境錯誤。</p>



<p>sudo apt install python3-mysql.connector</p>



<p>這種方式安裝的版本通常比較舊，但保證與系統相容。</p>



<p>需要我提供一段連接 MySQL 資料庫並執行查詢的範例程式碼嗎？</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>伺服器資料移轉</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/server-migrate/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/server-migrate/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 12:14:11 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7701</guid>

					<description><![CDATA[要將舊伺服器的資料搬移到新的 VPS，最簡單且穩...]]></description>
										<content:encoded><![CDATA[
<p>要將舊伺服器的資料搬移到新的 VPS，最簡單且穩定的方式是使用 rsync 指令。這個工具可以透過 SSH 安全地傳輸檔案，並且會保留檔案的權限與屬性。</p>



<h3 class="wp-block-heading">準備工作</h3>



<p>在開始搬運之前，請確保你已經把新伺服器的 SSH 公鑰加入到舊伺服器，或者擁有新伺服器的 root 密碼。此外，新舊伺服器之間必須網路互通，因為你提供的是私有 IP (10.130.0.5)，這代表兩台伺服器必須位在同一個 VPS 的 VPC 網路內。</p>



<h3 class="wp-block-heading">執行資料搬移</h3>



<p>請在舊伺服器上執行以下指令，這會將 /root 目錄下的所有內容同步到新伺服器：</p>



<pre class="wp-block-code"><code>rsync -avzP /root/ root@10.130.0.5:/root/
</code></pre>



<p>指令參數解釋：</p>



<ul class="wp-block-list">
<li>-a：代表歸檔模式，會保留連結檔、權限、時間戳記等資訊。</li>



<li>-v：顯示詳細過程。</li>



<li>-z：傳輸時進行壓縮，加快速度。</li>



<li>-P：顯示進度條，如果中斷了可以續傳。</li>
</ul>



<h3 class="wp-block-heading">搬移系統設定檔</h3>



<p>如果你指的 config 包含 /etc 底下的系統設定（例如 Nginx 或資料庫設定），建議針對特定目錄個別搬移，而不是直接覆蓋整個 /etc，因為新舊伺服器的硬體驅動或部分系統組件可能略有不同。</p>



<p>例如搬移 Nginx 設定：</p>



<pre class="wp-block-code"><code>rsync -avzP /etc/nginx/ root@10.130.0.5:/etc/nginx/
</code></pre>



<h3 class="wp-block-heading">資料庫搬移建議</h3>



<p>如果你的 /root 底下包含資料庫原始檔案（例如 MySQL 的 /var/lib/mysql），直接用 rsync 搬移運行中的資料庫檔案可能會導致資料損壞。建議先在舊伺服器執行資料庫匯出（dump），將產出的 .sql 檔放在 /root 內，再執行上述的 rsync 指令，最後到新伺服器匯入。</p>



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



<p>這是一個簡單的自動化搬移腳本。這個腳本會先在舊伺服器將資料庫打包（假設使用 MySQL/MariaDB），接著把 /root 目錄與指定的設定目錄同步到新伺服器。</p>



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



<p>請在舊伺服器上建立一個名為 migrate.sh 的檔案，並貼入以下內容：</p>



<pre class="wp-block-code"><code>#!/bin/bash
# 設定變數
NEW_SERVER_IP="10.130.0.5"
BACKUP_SQL="/root/all_databases.sql"

echo "正在匯出資料庫..."
mysqldump --all-databases > $BACKUP_SQL

echo "正在傳輸 /root 目錄資料..."
rsync -avzP /root/ root@$NEW_SERVER_IP:/root/

echo "正在傳輸 Nginx 設定 (如果有)..."
if &#91; -d "/etc/nginx" ]; then
    rsync -avzP /etc/nginx/ root@$NEW_SERVER_IP:/etc/nginx/
fi

echo "正在傳輸 SSL 憑證 (LetsEncrypt)..."
if &#91; -d "/etc/letsencrypt" ]; then
    rsync -avzP /etc/letsencrypt/ root@$NEW_SERVER_IP:/etc/letsencrypt/
fi

echo "搬移完成"
</code></pre>



<p>如果要改變 port</p>



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

# 設定變數
NEW_SERVER_IP="10.130.0.5"
PORT="22"

echo "正在傳輸 /root 目錄資料 (Port: $PORT)..."
rsync -avzP -e "ssh -p $PORT" /root/ root@$NEW_SERVER_IP:/root/</code></pre>



<p></p>



<h3 class="wp-block-heading">修改後的指令碼</h3>



<p>如果你想要在使用 rsync 時排除所有以點號開頭的隱藏檔案或目錄，可以使用 &#8211;exclude 參數並配合通配符。</p>



<pre class="wp-block-code"><code>NEW_SERVER_IP="10.130.0.5"
PORT="22"

echo "正在傳輸 /root 目錄資料 (排除隱藏檔, Port: $PORT)..."
rsync -avzP -e "ssh -p $PORT" --exclude=".*" /root/ root@$NEW_SERVER_IP:/root/</code></pre>



<p></p>



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



<h3 class="wp-block-heading">參數說明</h3>



<p>在 rsync 中加入 &#8211;exclude=&#8221;.*&#8221; 會讓程式跳過所有名稱開頭為點的檔案與資料夾。這包括常見的設定檔如 .bashrc 或隱藏目錄如 .ssh。</p>



<p>需要注意的是，這個寫法會排除所有層級下的隱藏內容。如果你原本的 /root/ 目錄下有特定的隱藏資料夾是你需要的，則必須改用更具體的排除規則。另外，rsync 預設就不會處理代表目前目錄的 . 與上層目錄的 ..，所以加上這個排除規則不會影響基本的目錄定位。</p>



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



<h3 class="wp-block-heading">搬移自定義 Service 設定檔</h3>



<p>在 Linux 系統中，使用者自定義的 service 設定檔通常放在 <code>/etc/systemd/system/</code> 目錄下。你可以延用之前的 <code>rsync</code> 指令，將這些 <code>.service</code> 檔案同步到新伺服器。</p>



<pre class="wp-block-code"><code>NEW_SERVER_IP="10.130.0.5"
PORT="22"
echo "正在傳輸自定義 service 設定檔 (Port: $PORT)..."
rsync -avzP -e "ssh -p $PORT" /etc/systemd/system/*.service root@$NEW_SERVER_IP:/etc/systemd/system/</code></pre>



<p></p>



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



<h3 class="wp-block-heading">注意事項與後續步驟</h3>



<p>同步完成後，新伺服器不會自動偵測到這些新檔案，你需要手動執行以下步驟來啟動服務：</p>



<p>重新載入系統設定登入新伺服器，執行以下指令讓系統辨識新加入的 service 檔案：</p>



<pre class="wp-block-code"><code>systemctl daemon-reload</code></pre>



<p>啟用並啟動服務針對你搬移過來的特定服務，執行啟用與啟動指令：</p>



<pre class="wp-block-code"><code>systemctl enable 服務名稱
systemctl start 服務名稱</code></pre>



<h3 class="wp-block-heading">安全建議</h3>



<p>如果你的 service 檔案中包含 <code>ExecStart</code> 指向的路徑（例如 <code>/root/my-app/start.sh</code>），請確保這些執行檔也已經透過之前的指令搬移到新伺服器的相同位置，否則服務將無法順利啟動。</p>



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



<p>這是一個自動化腳本片段，你可以將它加入到之前的搬移腳本中。這段程式碼會找出你搬移過去的 service 檔案名稱，並在新伺服器上執行重新載入與啟動的動作。</p>



<h3 class="wp-block-heading">自動化啟動腳本 (新伺服器執行)</h3>



<p>你可以將以下指令存在新伺服器的 <code>setup_services.sh</code> 並執行：</p>



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

echo "正在重新載入 systemd 設定..."
systemctl daemon-reload

# 取得剛剛搬移過來的自定義 service 列表 (排除系統預設連結)
SERVICES=$(ls /etc/systemd/system/*.service | xargs -n 1 basename)

for SERVICE in $SERVICES; do
    echo "正在啟動並設定服務開機啟動: $SERVICE"
    systemctl enable $SERVICE
    systemctl restart $SERVICE
done

echo "所有自定義服務已嘗試啟動，請執行 systemctl status &#91;服務名] 檢查狀態"
</code></pre>



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



<h3 class="wp-block-heading">遠端一鍵執行 (從舊伺服器觸發)</h3>



<p>如果你希望在舊伺服器同步完檔案後，直接遠端觸發新伺服器載入設定，可以在原本的 <code>rsync</code> 指令後加上這行：</p>



<pre class="wp-block-code"><code>ssh -p $PORT root@$NEW_SERVER_IP "systemctl daemon-reload &amp;&amp; echo '新伺服器已重新載入設定'"</code></pre>



<h3 class="wp-block-heading">貼心提醒</h3>



<p>自定義服務通常會依賴特定的執行環境，請確認以下項目在新伺服器是否已就緒：</p>



<ol start="1" class="wp-block-list">
<li>執行路徑：檢查 .service 檔內的 ExecStart 路徑是否存在。如果路徑是在 /root 底下，請確認你之前的 rsync 已經完整同步該目錄。</li>



<li>軟體環境：如果你的服務是用 Python、Node.js 或 Docker 執行，新伺服器必須先安裝好對應的 runtime。</li>



<li>使用者權限：如果服務設定以特定使用者執行 (User=xxx)，新伺服器必須建立該使用者。</li>
</ol>



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



<h3 class="wp-block-heading">執行腳本</h3>



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



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



<h3 class="wp-block-heading">後續操作</h3>



<p>當資料傳輸完成後，請登入到新伺服器（10.130.0.5）執行以下步驟來恢復資料庫：</p>



<pre class="wp-block-code"><code>mysql &lt; /root/all_databases.sql
</code></pre>



<p>如果你的服務包含 Nginx 或 Docker，記得在新伺服器安裝對應的軟體後，重啟服務以讀取搬過來的設定檔。</p>



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



<p>為了讓新伺服器能承接舊有的服務，你需要安裝與舊伺服器相同的執行環境。以下是一個針對常見網頁環境（Ubuntu/Debian 系統）的自動化安裝腳本，它會安裝 Nginx、MariaDB（MySQL）以及 PHP。</p>



<h3 class="wp-block-heading">環境安裝腳本</h3>



<p>請在新伺服器（10.130.0.5）建立並執行這個腳本：</p>



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

echo "更新系統軟體源..."
apt update &amp;&amp; apt upgrade -y

echo "安裝基礎工具..."
apt install -y curl wget vim rsync unzip

echo "安裝 Nginx..."
apt install -y nginx

echo "安裝 MariaDB 資料庫..."
apt install -y mariadb-server
systemctl enable mariadb
systemctl start mariadb

echo "安裝 PHP 常用組件..."
apt install -y php-fpm php-mysql php-common php-cli

echo "環境安裝完成"
</code></pre>



<h3 class="wp-block-heading">匯入資料與恢復服務</h3>



<p>在環境安裝好，且你已經執行過舊伺服器的搬移腳本後，請在新伺服器執行以下指令來完成最後的對接：</p>



<p>匯入資料庫：</p>



<pre class="wp-block-code"><code><code>mysql &lt; /root/all_databases.sql</code></code></pre>



<p>檢查 Nginx 設定並重啟：</p>



<pre class="wp-block-code"><code><code>nginx -t &amp;&amp; systemctl restart nginx</code></code></pre>



<h3 class="wp-block-heading">注意事項</h3>



<p>由於新舊伺服器的 IP 不同，如果你的設定檔（如 Nginx 的 config 或網站的 wp-config.php）中有寫死舊伺服器的 IP 位址，記得要搜尋並修改為新伺服器的位址。另外，如果原本有設定防火牆（如 ufw），在新伺服器上也需要重新開啟對應的連接埠（80, 443, 22 等）。</p>



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



<p>既然要使用 MySQL，我們需要調整安裝腳本的套件名稱，並在安裝過程中處理可能的權限問題。</p>



<h3 class="wp-block-heading">MySQL 環境安裝腳本</h3>



<p>請在新伺服器（10.130.0.5）執行以下指令：</p>



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

echo "更新系統軟體源..."
apt update

echo "安裝 MySQL Server..."
# 設定非互動模式，避免安裝過程跳出視窗要求輸入密碼
export DEBIAN_FRONTEND=noninteractive
apt install -y mysql-server

echo "啟動並設定 MySQL 開機自啟..."
systemctl start mysql
systemctl enable mysql

echo "安裝 Nginx 與 PHP 組件..."
apt install -y nginx php-fpm php-mysql

echo "MySQL 環境安裝完成"
</code></pre>



<h3 class="wp-block-heading">匯入資料庫的注意事項</h3>



<p>在執行 mysql &lt; /root/all_databases.sql 之前，由於 MySQL 8.0 以上版本的 root 帳號預設使用 auth_socket 認證，你可能需要使用 sudo 權限才能順利匯入：</p>



<pre class="wp-block-code"><code>sudo mysql &lt; /root/all_databases.sql
</code></pre>



<h3 class="wp-block-heading">調整舊 IP 關鍵字</h3>



<p>如果你擔心舊的設定檔（例如 Nginx config）裡還留著舊伺服器的 IP，可以在新伺服器的 /etc 目錄執行這行指令，將所有舊 IP 批次替換成新的（請將 1.2.3.4 替換為你的舊伺服器公網或私網 IP）：</p>



<pre class="wp-block-code"><code>grep -rl "1.2.3.4" /etc/nginx | xargs sed -i 's/1.2.3.4/10.130.0.5/g'</code></pre>



<p>最後記得重啟服務讓設定生效：</p>



<pre class="wp-block-code"><code>systemctl restart nginx
systemctl restart mysql</code></pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/server-migrate/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>Apache 伺服器的路徑穿越攻擊（Path Traversal）</title>
		<link>https://stackoverflow.max-everyday.com/2026/01/apache2-path-traversal/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/01/apache2-path-traversal/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 01:03:34 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[cloudflare]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7674</guid>

					<description><![CDATA[這個錯誤日誌顯示有人正在對你的伺服器進行路徑穿越...]]></description>
										<content:encoded><![CDATA[
<p>這個錯誤日誌顯示有人正在對你的伺服器進行路徑穿越攻擊（Path Traversal）:</p>



<pre class="wp-block-preformatted">[Mon Jan 26 00:26:10.407883 2026] [core:error] [pid 13727:tid 13727] [client 103.142.62.35:34636] AH10244: invalid URI path (/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh)</pre>



<p></p>



<h3 class="wp-block-heading">攻擊行為分析</h3>



<p>對手嘗試利用 <code>/%2e%2e/</code>（即 <code>../</code> 的編碼）來跳出網頁根目錄，目標是存取系統底層的 <code>/bin/sh</code>（Shell 執行檔）。這是一種典型的自動化漏洞掃描，試圖尋找設定不當的 CGI 腳本來執行遠端指令。</p>



<p>好消息是，日誌中的 <code>AH10244: invalid URI path</code> 代表 Apache 的核心模組已經識別出這是一個無效且具威脅的路徑，並在進入任何處理程序前就直接封鎖了它。這說明你的 Apache 版本（2.4.66）具有基本的防護能力。</p>



<h3 class="wp-block-heading">進一步防護建議</h3>



<p>雖然 Apache 已經幫你擋下了，但這種掃描會佔用連線資源。</p>



<p><strong>1. 使用 Fail2Ban 自動封鎖 IP</strong></p>



<p>你可以設定 Fail2Ban 監控 <code>error.log</code>。只要同一個 IP 出現多次 <code>AH10244</code> 或 <code>AH01276</code> 等錯誤，就直接在系統防火牆（iptables/ufw）層級封鎖該 IP。這樣流量連進入 Apache 的機會都沒有，能徹底節省 CPU 資源。</p>



<p><strong>2. 停用不必要的 CGI 模組</strong></p>



<p>如果你沒有使用 CGI 腳本，建議確保相關模組已關閉，減少攻擊面：</p>



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



<p><strong>3. 檢查檔案權限</strong></p>



<p>請確認 <code>/var/www/</code> 以外的系統目錄權限正確，確保 <code>www-data</code> 使用者無法讀取 <code>/etc/shadow</code> 或執行不必要的系統指令。</p>



<p>目前 Apache 已經正確攔截了這個請求，你不需要太過驚慌。</p>



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



<p>要在 Cloudflare 阻擋這種路徑穿越（Path Traversal）攻擊，最快且最有效的方式是建立一條 <strong>WAF Custom Rule</strong>。這類攻擊的特徵非常明顯，通常包含 <code>cgi-bin</code> 或連續的 <code>../</code>（或其編碼後的變體如 <code>%2e%2e</code>）。</p>



<h3 class="wp-block-heading">Cloudflare WAF 規則設定步驟</h3>



<ol start="1" class="wp-block-list">
<li>登入 Cloudflare，進入你的網站網域。</li>



<li>導覽至 <strong>Security (安全性)</strong> -&gt; <strong>WAF</strong> -&gt; <strong>Custom rules (自訂規則)</strong>。</li>



<li>點擊 <strong>Create rule (建立規則)</strong>。</li>
</ol>



<p>請依照以下內容填寫：</p>



<ul class="wp-block-list">
<li><strong>Rule name</strong>: Block Path Traversal and CGI Scans</li>



<li><strong>If incoming requests match</strong>: (使用 <strong>Edit expression</strong> 模式貼入以下代碼，或手動建立欄位)</li>
</ul>



<p><strong>欄位設定建議：</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><td><strong>Field</strong></td><td><strong>Operator</strong></td><td><strong>Value</strong></td></tr></thead><tbody><tr><td>URI Path</td><td><strong>contains</strong></td><td><code>/cgi-bin/</code></td></tr><tr><td><strong>OR</strong></td><td></td><td></td></tr><tr><td>URI Path</td><td><strong>contains</strong></td><td><code>..</code></td></tr><tr><td><strong>OR</strong></td><td></td><td></td></tr><tr><td>URI Path</td><td><strong>contains</strong></td><td><code>%2e%2e</code></td></tr></tbody></table></figure>



<p><strong>進階 Expression (直接貼入 Edit expression 效果更好)：</strong></p>



<p>SQL</p>



<pre class="wp-block-code"><code>(http.request.uri.path contains "/cgi-bin/") or (http.request.uri.path contains "..") or (http.request.uri.path contains "%2e%2e")
</code></pre>



<ul class="wp-block-list">
<li><strong>Choose action</strong>: <strong>Block</strong> (直接封鎖)</li>



<li>最後點擊 <strong>Deploy (部署)</strong>。</li>
</ul>



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



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



<p>這條規則鎖定了攻擊者的核心手段。</p>



<p>首先，<code>cgi-bin</code> 是老式伺服器漏洞的常見入口，現代 WordPress 網站幾乎不會用到這個路徑，直接阻斷可以過濾掉大量老舊漏洞掃描器。</p>



<p>其次，針對 <code>..</code> 和 <code>%2e%2e</code> 的檢查，能攔截所有嘗試跳出網頁根目錄的行為。即便攻擊者像你提供的日誌那樣使用了雙重編碼或變體（例如 <code>.%%32%65</code>），Cloudflare 的 WAF 在解碼處理後通常也能識別出其代表的 <code>..</code> 意圖。</p>



<h3 class="wp-block-heading">額外安全加固建議</h3>



<p>如果你發現攻擊依然頻繁，可以考慮在同一條規則中增加 <strong>Bot Score</strong> 的判斷：</p>



<ul class="wp-block-list">
<li>在規則中加入 <code>And (Cloudflare Bot Score &lt; 30)</code>。</li>



<li>這會確保這條嚴格的規則主要針對自動化腳本，而不影響少數可能路徑中帶有兩個點的正常開發者工具或特殊網頁。</li>
</ul>



<p>部署完這條規則後，你可以觀察 Cloudflare 的 <strong>Events (事件)</strong> 儀表板。你應該會看到這些 <code>cgi-bin</code> 的請求在到達你的伺服器之前，就已經被 Cloudflare 擋下來了。</p>



<p>需要我幫你確認如何合併之前提到的 <code>binance.com</code> Referer 規則到這條新規則中嗎？</p>



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



<p>將這幾項威脅合併成一條 Cloudflare 規則是最高效的做法，這樣可以減少規則數量的消耗，同時一次解決多種掃描問題。</p>



<h3 class="wp-block-heading">合併規則設定步驟</h3>



<p>在 Cloudflare 的 <strong>Custom rules</strong> 中，點擊進入剛才建立的規則，選擇 <strong>Edit expression</strong> 模式，直接將以下內容替換進去：</p>



<p>SQL</p>



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



<h3 class="wp-block-heading">規則內容詳解</h3>



<p>這條合併後的規則包含了以下三道防線：</p>



<ol start="1" class="wp-block-list">
<li><strong>路徑穿越與 CGI 掃描</strong>：<code>cgi-bin</code>、<code>..</code> 與 <code>%2e%2e</code> 會攔截嘗試讀取系統底層檔案（如 <code>/bin/sh</code>）的行為。</li>



<li><strong>特定的惡意來源</strong>：<code>referer contains "binance.com"</code> 會阻斷你日誌中看到的那批偽裝來源。</li>



<li><strong>XML-RPC 保護</strong>：<code>uri.path eq "/xmlrpc.php"</code> 直接在雲端攔截針對 WordPress 的暴力破解與 Pingback 攻擊，流量完全不會進到你的主機。</li>
</ol>



<h3 class="wp-block-heading">驗證效果</h3>



<p>部署完這條合併規則後，建議你觀察以下兩處：</p>



<p><strong>一、 Cloudflare Events (安全性事件)</strong></p>



<p>在 <strong>Security</strong> -&gt; <strong>Events</strong> 頁面，你應該會看到大片的 <strong>Block</strong> 紀錄。點開細節，你會發現這些請求的來源（Source）是 <strong>WAF custom rule</strong>，這代表它們在到達你的 Apache 之前就被解決掉了。</p>



<p><strong>二、 Apache Error Log</strong></p>



<p>再次檢查你的 <code>error.log</code>。原本頻繁出現的 <code>AH10244</code>（URI 無效）或 <code>AH01797</code>（Denied by config）應該會顯著減少。更重要的是，那條關於 <strong>MaxRequestWorkers reached</strong> 的警告應該不再出現，因為連線資源已經釋放出來給正常的使用者了。</p>



<p>設定完成後，你的伺服器負載應該會大幅下降。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/01/apache2-path-traversal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
