node.exe 一堆吃光記憶體?不是中毒,是 Codex 留下的殭屍程序吃掉 6.2GB,附清理腳本

目錄

💡 核心結論速覽 (TL;DR)

  • 先別掃毒、也先別買記憶體:工作管理員一整排 node.exe 通常不是病毒。我這台抓到 118 個 node.exe,其中 102 個是 Codex 桌面版留下的閒置 MCP 程序(父程序都是 codex.exe),吃掉約 6.2 GB。
  • 怎麼分辨誰在裝死:看 CPU 累計時間就好。那 102 個裡有 30 個 CPU 時間掛零、72 個累計用不到 1 秒——它們什麼都沒做,只是佔著記憶體。
  • 不是慢慢累積,是暴衝:依建立時間分組後我才看懂,14:27 生 2 個、14:31 一分鐘內冒出 98 個、15:06 再 2 個。這也是為什麼「兩小時清一次」的溫和排程完全擋不住。
  • 行動:先用一行 Get-CimInstance 確認自己中了沒;接著挑一層下手——立即(重開 Codex)/半自動(手動跑清理腳本)/一勞永逸(工作排程器每 30 分鐘自動清)。我清完 node 從 118 降到 24、可用記憶體從 21.5 GB 回到 26.2 GB。

那天下午我只是想拖一個視窗,滑鼠卻黏在螢幕上不動了。我第一個念頭是「顯卡驅動又出事了?」——結果打開工作管理員,看到的是一整片密密麻麻、名字一模一樣的 node.exe,滾輪往下滑,滑了好久還沒到底。連打字都是,按下去要等半拍字才跑出來。

先給你直接的答案:如果你的電腦裝過 AI 編程工具,那一大排 node.exe 十之八九不是中毒,而是這些工具開完沒收回去的背景程序。我這台是 Codex 桌面版留下的——它每開一次 session、每重連一次,就生一對 MCP 程序,然後舊的那對再也不會被收走。

我每天開著 AI 工具跑開發、寫稿、跑自動化,一天用超過 10 小時,所以這種「它很會開、但從來不負責關」的坑,我大概是最早撞上的那批人。這篇我想把整段追兇過程完整攤開:怎麼用三行指令確認你中了沒、怎麼分辨哪些 node.exe 真的在工作哪些只是裝死、以及一份我自己在跑、寫了五道安全設計的自動清理腳本

還有一個你搜到這裡大概最想知道的問題:那把它們全殺掉,會不會弄壞什麼?我先說結論——會,如果你用錯方法的話。後面我會講為什麼我完全不用 taskkill /IM node.exe 這招。


node.exe 是什麼?工作管理員一堆 node.exe 正常嗎?

node.exeNode.js 的執行檔,作用就像 Python 的 python.exe——它本身不是某個特定程式,而是「用來跑 JavaScript 程式的引擎」。所以工作管理員裡看到 node.exe,只代表有東西正在用 Node.js 跑,看不出來是誰在跑。

這就是這件事最惱人的地方,也是我覺得搜尋結果幫倒忙的地方。你去搜「node.exe 一堆」,前幾頁的答案幾乎都在教你「檢查是不是惡意程式偽裝」「跑一次防毒掃描」。這個建議在十年前很合理,但放到現在會害你誤診:你的電腦裡跑 Node 的東西太多了——VS Code 的擴充套件、前端專案的 dev server、Electron 做的桌面 App,還有這幾年新加入的重量級成員:AI 編程工具和它們掛的 MCP 服務。

那到底幾個算正常?我的判斷是這樣,你可以直接對號入座:

你看到的狀況 大概是什麼 要不要處理
3-10 個,且你正開著編輯器或跑著專案 編輯器擴充、dev server、建置工具 正常,別動
十幾二十個,關掉編輯器後就掉下來 開發工具的正常起落 正常,關掉專案就好
幾十上百個,且關掉編輯器也不會少 有東西開了不收——本篇要抓的就是這種 要處理
你根本沒裝過任何開發工具 這才是該懷疑惡意程式的情況 先查來源路徑再說

順帶提一個判斷小訣竅:真正的惡意程式很少會老老實實叫 node.exe 又乖乖待在 C:\Program Files\nodejs\。等一下的診斷指令會把每個程序的完整指令列印出來,那行字會直接告訴你「這支是誰開的、在跑哪個檔案」——比任何猜測都準。所以下一步不是掃毒,是先把兇手的名字問出來。


30 秒自我診斷:怎麼分辨「在工作的 node.exe」和「裝死的殭屍」?

直接給你答案:看兩個欄位就夠了——「指令列」告訴你它是誰開的,「CPU 累計時間」告訴你它到底有沒有在做事。工作管理員預設兩個都不給你看,所以我們換 PowerShell。

打開 PowerShell(開始鍵直接打 powershell 就找得到,這幾行不需要系統管理員權限),複製第一行貼進去:

❶ 先看總數,心裡有個底:

(Get-CimInstance Win32_Process -Filter "Name='node.exe'").Count

❷ 把每一支的來歷印出來(這行是關鍵):

Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
  Select-Object ProcessId, ParentProcessId, CreationDate,
    @{n='MemMB'; e={[math]::Round($_.WorkingSetSize/1MB,1)}},
    @{n='CpuSec';e={[math]::Round((($_.UserModeTime + $_.KernelModeTime)/10000000),2)}},
    @{n='Cmd';   e={$_.CommandLine}} |
  Sort-Object CreationDate | Format-Table -AutoSize -Wrap

跑完你會拿到一張表。Cmd 那欄:如果一大批都長得像 ./mcp/server.mjs./mcp/server.cjs --stdio,那就是 MCP(Model Context Protocol)服務——官方自己的比喻是「AI 應用的 USB-C 埠」,讓 AI 工具能接上你的檔案、資料庫和各種工具。它跑起來就是一支 node.exe。至於 MCP 各家 server 的差別和我自己的分工,我另外整理過一篇;如果你連「我到底掛了幾個 MCP」都不確定,可以先看我實測後留下的 MCP server 分工清單再回來。

再看 CpuSec 那欄,這是我覺得整篇最好用的一招。這個數字是該程序從出生到現在累計燒掉的 CPU 秒數。一支真的在跑編譯、跑 dev server 的 node,累計動輒幾十秒到好幾分鐘;而一支開起來就沒再做事的,會停在 0 到 1 秒之間,怎麼看都不動。

🚧 這裡有個容易讀錯的地方UserModeTimeKernelModeTime官方單位是 100 奈秒,不是毫秒也不是秒。所以要除以 10,000,000 才會變成「秒」。我第一次算的時候少除了三個零,看到「一個閒置程序燒了 300 秒 CPU」還嚇了一跳,回頭翻文件才發現是自己單位搞錯。

❸ 最後這行,是讓你看懂它「什麼時候冒出來」:

Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
  Group-Object { $_.CreationDate.ToString('HH:mm') } |
  Sort-Object Name | Select-Object Name, Count

這行我是後來才想到要加的,結果它直接讓我看懂了整件事——原本我以為程序是慢慢累積的,跑完這行才發現根本不是那樣。這段留到下一節講,那張表我看到的時候是真的愣了幾秒。


我這台抓到什麼?102 個閒置 node.exe 佔掉 6.2 GB

先把數字攤開。我的環境是 Windows 11 Pro(build 26200)、i7-13700、64 GB 記憶體,Codex 桌面版是 MSIX 版本 26.810.6296.0——記憶體 64 GB 這件事等一下很重要,因為它解釋了為什麼我拖了好幾天才發現。

第一次抓到是幾天前,那時只有 26 個殘留程序,我當下的判斷是「還好吧,重開就沒了」,就沒放在心上。等到滑鼠開始延遲那天再測一次,數字變成這樣:

項目 清理前 清理後
node.exe 總數 118 個 24 個
其中 Codex 的 MCP 殘留 102 個
這些程序佔用的記憶體 約 6.2 GB 約 1.2 GB
系統可用記憶體 21.5 GB 26.2 GB

那 102 個的父程序全部都是 codex.exe,指令列全部都是 ./mcp/server.mjs./mcp/server.cjs --stdio 這一對。平均每支吃 50-60 MB——單看一支很不起眼,湊到一百支就是 6 GB。

但真正讓我改變處理方式的,是 CPU 那一欄:102 個裡面,30 個 CPU 累計時間是 0,另外 72 個加起來用不到 1 秒。換句話說,它們從出生到現在,什麼事都沒做過。不是在背景默默幫我跑什麼,就是純粹佔著記憶體發呆。

然後是那張按分鐘分組的表,我到現在還是覺得很誇張:

時間 那一分鐘新生的程序數
14:27 2 個
14:31 98 個
15:06 2 個

一分鐘 98 個。不是一小時漏一點、一天漏一點那種慢性病,是某個瞬間直接噴出來。這個發現很關鍵,因為它推翻了我原本的整套處理邏輯——我後來設清理排程時第一版就是被這件事打臉的,那段我留到後面誠實交代。

另外補一個我觀察到、但不打算下結論的細節:那次暴衝的時間點,正好落在我這台的 Claude 桌面版崩潰重啟後大約兩分鐘。兩件事時間上靠得很近,我看到了就寫出來;但我沒有任何證據說是它造成的,也可能只是我當下同時開了一堆東西。

我能確定的只有「什麼時候冒出來」和「冒出來幾個」,不能確定「為什麼」。這條界線我會守住,因為猜錯的成本是讓你去修一個根本不存在的問題。

順帶一提,如果你覺得「這味道有點熟」——沒錯,這已經是我第二次抓 Codex 在背景偷偷留下的東西了。上一次是它把診斷日誌狂寫進硬碟、連 SSD 壽命都被磨掉一截,那次吃的是硬碟,這次吃的是記憶體。同一種慣性,換一個資源。


只有我這台的 node.exe 這樣嗎?先去官方 repo 看一眼

這是我自己最在意的一題,也是我建議你在動手清之前先確認的一題:如果只有我這台,那該修的是我的環境;如果別人也一樣,那才值得花時間做自動化。

我去 Codex 的官方 GitHub repo 翻了一輪,結論是——不只我這台,而且不只 Windows。以下四則是我逐一打開看過、確認過標題、狀態和數字的回報:

回報編號 平台與現象 目前狀態
#29079 Windows 11 Pro/約 64 GB RAM。指令列同樣是 ./mcp/server.mjs --stdio./mcp/server.cjs --stdio,單支 node 吃到 1,448 MB、1,197 MB,記憶體壓力 67-69% Open
#26327 Windows 長時間多執行緒 session:22 個 node_repl.exe、21 個 node.exe ./mcp/server.cjs --stdio、22 個 codex.exe app-server,31 GB 記憶體用掉 83.3% Closed as not planned
#12491 macOS/M4 Max/64 GB:1,319 個殭屍程序、1,537 個 node,約 37 GB RSS,swap 從 39.4 GB 清到 8.0 GB Open
#20980 回報者實測:重開後基準 98 個程序/5.14 GB,只是開啟一個舊對話就變成 142 個/7.46 GB Closed as duplicate

我想很小心地講清楚這張表代表什麼、不代表什麼。它代表的是:同型現象在 Windows、macOS 上都有人回報,指令列特徵跟我這台一模一樣,所以這不是我電腦壞掉。它不代表 OpenAI 已經正式承認這是 bug,也不代表官方給過什麼修復承諾——這些都只是社群使用者在官方 repo 上留下的回報,其中還有兩則被關掉了。我不會替官方講它沒講過的話。

不過 #20980 那一則值得你多看一眼,因為它給了一個你可以自己驗證的假說:回報者觀察到,光是開啟一個舊對話,程序數就從 98 跳到 142。如果這個觀察在你機器上也成立,那「一分鐘 98 個」就有了合理的解釋——某個動作一次把一堆舊 session 拉回來,每一個都長出自己的一組 MCP 程序。

怎麼驗?很簡單:跑一次上面的計數指令記下數字,去點開幾個舊對話,再跑一次。我強調這是假說不是結論,因為我沒辦法看到 Codex 內部怎麼管理這些程序,只能看到外面的程序數字。但你如果驗出來一樣,至少你知道日常使用時該少開幾個舊 thread——這是一個馬上能改的習慣,比等官方修快得多。


node.exe 怎麼清?三層解法:先止血、再半自動、最後一勞永逸

直接說我的建議:大部分人做到第二層就夠了;只有像我這種一天開關 Codex 十幾次的重度使用者,才真的需要第三層。先看這張表對號入座,細節我一層一層拆。

層級 適合誰 代價
第一層:完全關掉 Codex 再開 偶爾用、發現卡了才處理的人 要記得做,手上的 session 會斷
第二層:手動跑一次清理腳本 每天用,但不想動排程設定 要自己記得跑,但不用關 Codex
第三層:工作排程器每 30 分鐘自動清 整天掛著、開關很多次的重度使用者 設定一次,之後不用管

第一層:完全關閉 Codex 再重開。這招最安全也最無腦,而且我實測有效——殘留的 node.exe 會歸零。但請注意「完全關閉」的意思:按右上角的叉叉通常不算,很多桌面版 App 關掉視窗只是縮到系統匣。到工作列右下角的隱藏圖示區找到它、右鍵選離開,或直接在工作管理員裡結束 codex.exe 這棵樹。關完再跑一次計數指令確認歸零,你會很有感。

第二層:手動跑清理腳本。第一層的問題是它太粗暴——你可能正在跑一個長任務,不想關掉整個 Codex,只想把那些發呆的程序請走。這時候就需要一支「只認得殭屍、認不出來就不動」的腳本。這也是本篇的重點,下一節整份給你。

第三層:掛成排程自動跑。當你發現自己一週要手動跑五次,那就該交給機器了。Windows 內建的工作排程器就能做,指令我也附上。

先講清楚風險,你再決定要不要做第二、三層。清理腳本本質上是在殺程序,萬一它殺到一個你正在使用中的 MCP 連線,Codex 那個 session 的工具會暫時失效,你需要重連或重開那個對話

要強調的是:不會損失資料——你的專案檔案、對話記錄都在別的地方,殺掉的只是一支負責傳話的服務程序。但如果你正跑到一半,那個中斷還是很煩。所以下一節那五道安全設計,每一道都是為了讓這件事盡量不要發生。


為什麼我不用 taskkill /IM node.exe?清理腳本的五道安全設計

先回答那個大家最想問的問題:直接一行 taskkill /F /IM node.exe /T 全殺光,不是最快嗎?

快是快,但這行指令分不出誰是誰。它會連你正在跑的 dev server、正在建置的專案、編輯器的語言伺服器、資料庫工具一起帶走——你會「解決」記憶體問題,然後花二十分鐘搞懂為什麼專案跑不起來了。

我第一次處理這類問題時就是這樣被教訓的,那次的完整教訓我寫在用登記式清理幫背景程序設下班時間的那篇裡;本篇這支腳本則是那套思路的專用版——不靠登記,改靠 Codex MCP 程序自己的特徵字串來辨識。

所以這支腳本的核心不是「怎麼殺」,是「憑什麼確定這支該殺」。五道設計如下,每一道我都說明它擋掉什麼:

❶ 只認特徵字串。只處理指令列符合 ./mcp/server.mjs./mcp/server.cjs 的程序。你的 dev server、建置工具、編輯器擴充完全不符合這個特徵,一開始就被濾掉,連被誤判的機會都沒有。

❷ 只認歸屬。符合特徵還不夠,父程序必須是 codex.exe,或者父程序已經不存在了(孤兒)。這道擋掉「別的工具剛好也用類似路徑」的極端情況。

❸ 比對建立時間,防 PID 重用。這道是我翻文件才補上的。Windows 的程序編號會被回收再利用,微軟官方文件寫得很直白:ParentProcessId 指到的程序可能已經結束,也可能不小心指到一個「剛好撿到同一個編號」的新程序——文件還直接建議用 CreationDate 來確認父子關係。所以腳本會檢查「父程序的出生時間必須早於子程序」,不合理就跳過不動。

❹ 保留最新的 8 個。這道是保護你「現在正在用」的連線。程序按建立時間排序,最新的 8 個一律不碰——因為活躍中的連線必然是最近才建立的。這個數字你可以自己調,我用 8 是因為我常常同時開好幾個 Codex 視窗。

❺ 只動存在超過 45 分鐘的。雙保險。就算某支程序不在「最新 8 個」的保護名單裡,只要它出生還不到 45 分鐘,也一樣不動。

另外還有一件不算「安全設計」但同樣重要的事:寫 log。每次清了幾支、清掉哪些 PID、釋放多少記憶體,全部記下來。這樣萬一哪天 Codex 出現怪狀況,你可以回頭對時間,確認是不是腳本幹的——而不是在那邊猜。會自動化的東西就要留下可追溯的紀錄,這是我從帶團隊做上線流程養成的習慣,用在自己電腦上一樣受用。

整份腳本如下,存成 codex-mcp-reap.ps1

$KeepNewest    = 8          # 最新的幾個一律不碰(保護使用中的連線)
$MinAgeMinutes = 45         # 只動存在超過幾分鐘的
$LogPath       = "$env:USERPROFILE\codex-mcp-reap.log"
$Pattern       = '\./mcp/server\.(mjs|cjs)'

$all = Get-CimInstance Win32_Process -Filter "Name='node.exe'"
$mcp = $all | Where-Object { $_.CommandLine -match $Pattern }

# 建一張「現在還活著的 PID」對照表,用來查父程序
$live = @{}
foreach ($p in (Get-CimInstance Win32_Process | Select-Object ProcessId, Name, CreationDate)) {
    $live[[int]$p.ProcessId] = $p
}

$owned = @()
foreach ($p in $mcp) {
    $ppid   = [int]$p.ParentProcessId
    $parent = $null
    if ($live.ContainsKey($ppid)) { $parent = $live[$ppid] }

    if ($null -eq $parent) {
        $owned += $p                          # 父程序已消失=孤兒
    } elseif ($parent.Name -eq 'codex.exe' -and $parent.CreationDate -le $p.CreationDate) {
        $owned += $p                          # 父程序確實是 codex.exe(且時間順序合理)
    }
}

$eligible = $owned | Where-Object { ((Get-Date) - $_.CreationDate).TotalMinutes -ge $MinAgeMinutes }
$toKill   = @($eligible | Sort-Object CreationDate -Descending | Select-Object -Skip $KeepNewest)

$freed = 0
foreach ($p in $toKill) {
    try {
        Stop-Process -Id $p.ProcessId -Force -ErrorAction Stop
        $freed += [double]$p.WorkingSetSize
        Add-Content -Path $LogPath -Encoding UTF8 -Value ("{0}  killed pid={1} age={2}min mem={3}MB" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $p.ProcessId, [math]::Round(((Get-Date) - $p.CreationDate).TotalMinutes), [math]::Round($p.WorkingSetSize/1MB,1))
    } catch {
        Add-Content -Path $LogPath -Encoding UTF8 -Value ("{0}  skip pid={1} ({2})" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $p.ProcessId, $_.Exception.Message)
    }
}
Add-Content -Path $LogPath -Encoding UTF8 -Value ("{0}  total node={1} mcp={2} killed={3} freed={4}MB" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), @($all).Count, @($mcp).Count, $toKill.Count, [math]::Round($freed/1MB,1))

🚧 存檔編碼這關會卡你,我先講:如果你用的是 Windows 內建的 PowerShell 5.1,這份腳本必須存成「UTF-8 with BOM」。我第一次存成一般 UTF-8,一執行就噴 The string is missing the terminator——因為註解裡的中文被讀成亂碼,把引號吃掉了。換成含 BOM 的編碼後同一份檔立刻正常。VS Code 右下角點編碼選「Save with Encoding → UTF-8 with BOM」就好;懶得處理的話,把中文註解整行刪掉也能跑。

第一次跑,請先讓它空轉一次。Stop-Process 那行結尾加上 -WhatIf,它就只會告訴你「本來要殺誰」而不會真的動手。確認名單合理,再把 -WhatIf 拿掉。我自己在寫這篇時就是這樣驗的:空轉結果是符合 MCP 特徵 8 支、通過歸屬檢查 8 支、超過 45 分鐘的 4 支,但最後實際要殺的是 0 支——因為那 4 支都落在「保留最新 8 個」的保護範圍內。護欄真的有在擋,這比我嘴上保證安全有說服力多了。


掛成每 30 分鐘自動跑,還有我一開始設錯的門檻

腳本能手動跑之後,剩下的就是別再靠自己記得。Windows 內建的工作排程器一行指令就能建好,開一個系統管理員身分的 PowerShell 貼進去:

schtasks /create /tn "Codex MCP Reap" /sc minute /mo 30 /f `
  /tr "powershell -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$env:USERPROFILE\codex-mcp-reap.ps1`""

拆開來看就四件事:/sc minute /mo 30官方文件裡「每 n 分鐘跑一次」的寫法(/mo 在分鐘排程可填 1 到 1439);-WindowStyle Hidden 讓它別每半小時彈一個黑視窗嚇你;-ExecutionPolicy Bypass 讓沒簽章的腳本跑得起來;/f 是同名工作直接覆蓋,方便你之後改參數重建。想確認它有沒有乖乖跑,就去看 log 檔,或用 schtasks /query /tn "Codex MCP Reap" /v 查上次執行結果。不想要了就 schtasks /delete /tn "Codex MCP Reap" /f

接下來是這篇我最想跟你分享的一段,因為它是我實實在在做錯的地方。

我的第一版參數是:只留最新 1 對、清掉存在超過 2 小時的、每 2 小時跑一次。邏輯聽起來很穩健對吧?溫和、保守、不容易誤殺。結果它幾乎沒發揮作用——我隔天再看,記憶體還是被吃光。

回頭比對時間我才想通:問題出在我用「慢慢累積」的假設去對付一個「瞬間暴衝」的現象。當一分鐘就能生 98 個的時候,「兩小時清一次」意味著這 98 個至少要在你記憶體裡待兩小時;更慘的是它們都是同一分鐘出生的,「清掉超過 2 小時的」這個條件對它們同時成立又同時不成立——它們會整整齊齊地一起等到滿兩小時,中間那段時間你一點救都沒有。

調整後的參數就是你現在看到的這組,每一個數字都有理由:

參數 第一版(失敗) 現在這版
執行頻率 每 2 小時 每 30 分鐘(縮短暴衝後的曝險時間)
年齡門檻 2 小時 45 分鐘(比暴衝週期短,才追得上)
保留數量 最新 1 對 最新 8 個(我常同時開多個視窗,1 對不夠用)

這裡也順便說一下「保留 8 個」為什麼是往調而不是往緊調。第一版留 1 對,看起來清得更乾淨,但它讓誤殺活躍連線的機率變高了——而清理排程最不該做的事,就是在你工作到一半時把你的工具打掉。

清得乾不乾淨是效率問題,誤殺是信任問題。我寧願多留幾個閒置程序在那邊發呆,也不要一個會偶爾捅你一刀的自動化。你可以照自己習慣調:只開一個 Codex 視窗的人,留 4 個大概就夠。

如果你同時還跑著 Claude Code 或別的 agent,那還會多一層「兩個工具搶同一台機器資源」的問題,我把本機和雲端怎麼分工寫在兩個 AI agent 在我電腦搶 port 的那篇解法裡;如果你是把 Codex 掛進 Claude Code 一起用的,計費和開關的雷則在我算完額度表後建議先別開的那個設定那篇。


這樣就修好了嗎?要不要先別用 Codex、要不要加記憶體

老實說,沒有修好。這套做的是「定期收屍」,不是「不再產生屍體」。只要 Codex 還是照現在的方式運作,程序就會繼續長出來,我的腳本只是讓它們待得比較短。這句話我一定要講清楚,因為我很討厭那種讀完覺得問題解決了、結果一週後又卡住的文章。

所以真正該問的是三個決定,我一個一個給你我的判斷。

❶ 要不要先別用 Codex?我的答案是不用,而且我自己還在用。理由是這個問題的三個特性都很友善:它可觀測(一行指令就看得到)、可控(一支腳本就收得住)、不傷資料(清掉程序不動你的檔案和對話)。比起我上次遇到的硬碟狂寫,這個溫和多了。

但機器的記憶體多大,會直接改變這題的答案——同樣 100 個程序、同樣 6 GB,在 64 GB 的機器上是「有點卡」,在 16 GB 的機器上是「整台停擺」。記憶體越小,越該把清理排程當成必做而不是選配。你可以直接照自己的配置對號入座:

  • 8 GB:這批程序一堆起來就會直接卡住你,排程請當必做;同時盡量只開一個 Codex 視窗,$KeepNewest 調到 4 就夠。
  • 16 GB:日常還撐得住,但只要你一天開關 Codex 超過幾次,就別靠自己記得,直接掛排程。
  • 32 GB 以上:可以先只做第一、二層;等你發現一週要手動清好幾次,再上第三層也不遲。

❷ 要不要加記憶體?如果你是因為這件事才想升級,先別急著下單。我知道看到「可用記憶體剩 21 GB」的心情是什麼——會很直覺地想「是不是該加到 128 GB」。但你花錢加的容量,會被同一個洩漏用同樣的速度吃掉,只是撐得比較久而已。正確順序是:先清、再觀察一週、清完還是不夠用再考慮升級。我清完之後回到 26.2 GB 可用,這台機器完全沒有升級的必要——那筆錢我寧願拿去續 AI 訂閱方案。

❸ 那要不要換工具?我的看法是:換工具不會讓這類問題消失,只會換一種形式出現。這幾年我用下來的心得是,AI 編程工具普遍都很會「開」——開服務、寫日誌、拉子程序——但對「關」都不太上心。

與其追著找一個完美的工具,不如養成一組固定的檢查習慣。我把各種資源坑的全景整理成一篇總入口,如果你想一次看完硬碟、成本、安全、限流各類的地雷分布,可以從五大類常見問題的全景地圖進去。

最後給你一組可以直接照抄的判斷清單,這也是我自己在跑的:

  • 每天:覺得電腦變鈍的時候,先跑那行計數指令再說。數字比感覺可靠。
  • 每週:翻一次 log,看清理量有沒有異常暴增——那通常代表你的使用習慣變了。
  • 每次 Codex 大版本更新後:手動測一輪,確認特徵字串沒變。萬一官方改了程序啟動方式,腳本的 $Pattern 會失效而且是安靜地失效——你不會收到任何錯誤,只會發現記憶體又開始被吃。
  • 想從源頭少開一點:關掉沒在用的 MCP server,並且盡量少開舊對話(呼應前面那個假說)。設定怎麼調、哪些參數會影響它的行為,可以看9 個 config.toml 參數讓它更快更省更聽話那篇——這篇治的是「收拾殘局」,那篇治的是「一開始就少留一點」,兩篇搭起來用效果最好。

還有一件事我想順口提醒:這支腳本會自動殺程序,是會實際動到你系統的自動化。我一直覺得,讓 AI 工具或腳本代替你動手之前,最該先想清楚的是「它最壞會做出什麼」。同樣的思路我寫過一篇AI 代理喊了 11 次「不要動」還是把檔案刪掉的真實災難與五道防線,如果你打算讓更多自動化跑在自己機器上,那篇的心法比本篇的腳本更值得先讀。


FAQ 常見問題

直接把所有 node.exe 殺光比較快,為什麼你不建議?

因為 node.exe 只是執行引擎,不代表任何特定程式。全殺會一起帶走你的 dev server、建置流程、編輯器語言伺服器和資料庫工具,你會用五秒解決記憶體問題,然後花二十分鐘搞懂專案為什麼跑不起來。本篇腳本先靠指令列特徵字串篩、再驗父程序是不是 codex.exe、還要比對建立時間防 PID 被重用,就是為了避開這種無差別誤殺。真的想快,用第一層解法(完全關掉 Codex 再開)更安全。

我用的是 Claude Code、Cursor 或其他 agent,也會有同樣問題嗎?

可能會,但特徵字串會不一樣,所以本篇腳本不能直接套用。判斷方法是通用的:跑那行印出指令列的診斷指令,看那批可疑的 node.exe 是誰開的、CPU 累計時間是不是趨近於零。如果是別的工具留下的,把腳本裡的 $Pattern 和父程序名稱換成對應的特徵即可。但請務必先用 -WhatIf 空轉驗名單再實跑,別直接改完就上。

每 30 分鐘跑一次,會不會殺到我正在用的 MCP 連線?

設計上機率很低,但不是零。腳本有兩道保護:最新的 8 個一律不碰,且只動存在超過 45 分鐘的——活躍連線幾乎必然落在這兩道保護裡。真的不巧被殺到,後果是那個 Codex session 的工具暫時失效、需要重連或重開對話,不會損失專案檔案或對話記錄。會擔心的話,把 $KeepNewest 調高到 12、$MinAgeMinutes 調到 90,清理效率略降但更保守。

清掉之後電腦真的會變快嗎?值得花時間設定嗎?

看你積了多少、以及你的記憶體多大。我這台清掉 102 個程序、釋放約 5 GB 之後,滑鼠鍵盤延遲當下就消失了。但如果你的工作管理員裡只有三五支 node.exe,那清了也沒感覺,這套對你就是預防性質。判斷方式很簡單:跑一次計數指令,數字如果只有十幾個就先別急著設排程;破五十、又關不掉編輯器也不會少,那就值得花十分鐘設定。

腳本存好了卻一執行就報錯,是哪裡出問題?

最常見的是編碼。Windows 內建的 PowerShell 5.1 讀不含 BOM 的 UTF-8 檔會把中文註解讀成亂碼,症狀是報 The string is missing the terminator 或抱怨少了大括號——看起來像程式碼寫壞,其實是存檔編碼問題。存成「UTF-8 with BOM」就好,或者把中文註解刪掉。第二常見的是執行原則擋住未簽章腳本,排程指令裡的 -ExecutionPolicy Bypass 就是在處理這件事;手動跑的話,在該次 PowerShell 視窗先下 Set-ExecutionPolicy -Scope Process Bypass 即可。


結論:會開的東西,也要有人負責關

回頭看,這件事真正花我時間的不是解法,是「看懂它」。從滑鼠變鈍到抓出 102 個閒置程序,中間卡最久的是一個錯誤假設——我一直以為程序是慢慢累積的,直到那行按分鐘分組的指令跑出「14:31 生了 98 個」,我才知道自己一直在用錯的模型對付它,連清理排程都設錯了門檻。診斷指令真正的價值不是給你數字,是打掉你腦中那個想當然爾的假設。

所以如果這篇只能帶走一件事,我希望是這個習慣:當電腦莫名變慢,先問「是誰開的」,再問「它在做事嗎」,最後才問「該不該殺」。順序反過來,就會像網路上多數答案那樣——直接叫你去掃毒,或者叫你把 node.exe 全殺光。兩個都會讓你離真相更遠。

AI 工具這幾年給我的最大體感,就是那句我常說的:它沒有讓人更清閒,反而更忙了。它很會替你開東西——開服務、開程序、寫日誌——但「關」這件事,目前還是得由我們自己補上。這篇的腳本、上一篇的硬碟清理、再上一篇的背景程序登記,本質上都是同一件事:替一個很會做事、但不太會收尾的夥伴,把下班流程補起來。

如果你也每天讓 AI 在自己的機器上跑東西,我把整個 AI 工具的挑選、設定與踩坑心得都放在依需求分類的 AI 工具總整理;帳單方面容易失控的部分,則可以先看一個任務燒掉好幾美元的真相與砍半省法,那是另一個很多人被咬過、但同樣有解的坑。


參考資料

 

延伸閱讀