跳至主要內容

【2026年7月】生成式 AI 模型比較(Claude、GPT、Gemini、Grok、DeepSeek、Kimi、GLM、Mistral)

透過 OpenRouter,無論是 Claude、GPT、Gemini 這類封閉模型,還是源自中國的開源權重模型, 都能自由切換使用。不過「到底該選哪一個」還是常常讓人猶豫,這次就大致比較了一下主要模型的 價格與實力。

「開源」與「封閉」到底是什麼意思

  • 封閉(Closed):像 Claude、GPT、Gemini、Grok 這類模型,其內部(權重)並未公開, 只能透過該公司的伺服器使用。
  • 開源權重(Open-weight):像 DeepSeek、Kimi、GLM、Mistral 這類模型,內部是公開的, 任何人都能在自己的電腦或雲端上運行。

依等級劃分的價格

先從最重量級的價格開始看。

Pro 等級 價格比較

可以看到,Claude Fable 5 貴得驚人(輸出每 1M token $50),而 DeepSeek V4 Pro 的輸出 僅需 $0.87。即使同樣掛著「Pro」的名號,價差竟然超過 50 倍。開源陣營(綠色標籤)全面 偏低價,一目瞭然。

再來看看中量級和輕量級。

Mid 等級 價格比較 Nano 等級 價格比較

到了輕量級,GPT-5 nano 的輸出價格僅 $0.40,幾乎達到「隨便用」的等級。若只是做簡單的 分類作業或草稿生成,這個等級往往就綽綽有餘。

看看性價比

單看價格,容易讓人覺得「便宜的模型性能應該也差」,但實際上並非如此。這裡先不分等級, 把價格與 Intelligence Index 分數都齊全的 20 個模型彙整成一張圖。盡量涵蓋了 GPT、Gemini、 Qwen、Llama、Gemma、Mistral 等眾多模型,不分開源或封閉。

成本 vs 性能散點圖(全部模型)

縱軸是「Intelligence Index」這項綜合能力分數(詳見後述)。虛線連接的「性價比前緣」由 跨越 Nano、Mid、Pro 三個等級的 7 個模型構成:Gemma 3 27B → DeepSeek V4 Flash → DeepSeek V4 Pro → Kimi K2.6 → Gemini 3.1 Pro → Claude Opus 4.8 → Claude Fable 5DeepSeek V4 Pro 輸出價格僅 $0.87,分數卻逼近 Gemini 3.1 Pro($12.00),實質上已成為 性價比的起點,一枝獨秀。另一方面,位於前緣內側的 Qwen3.7 Max、MiniMax M3、GLM 5.2、 Claude Sonnet 5、Gemini 3 Flash、Grok 4.20、Claude Haiku 4.5、Gemini 3.1 Flash-Lite、 Qwen3-Coder、Mistral Large 3、Llama 4 Maverick、Llama 4 Scout 等模型,相較同價位的其他 模型,實力則略顯遜色。

若重視性價比,不妨先從最便宜的位置開始嘗試。

到底哪個模型最聰明

再來看看綜合能力與程式撰寫能力的排名。

綜合基準測試:Artificial Analysis Intelligence Index 程式實務能力:SWE-bench Verified

第一張圖的「綜合能力」,是第三方基準測試機構 Artificial Analysis Intelligence Index 的分數;第二張圖的「程式撰寫能力」,是 SWE-bench Verified 的分數,這項測試衡量的是 模型能解決多少實際存在的軟體錯誤修復課題。兩者都不是模型廠商的自我申報,而是由外部評測 網站實際測量並公布的數值。

在綜合能力上,Claude Fable 5 以領先 GPT-5.5 約 5 分的成績奪冠,Claude Opus 4.8、 GPT-5.5、Gemini 3.1 Pro 則以些微差距緊隨其後。僅看程式撰寫能力的話,Claude Fable 5 更是以 95% 的分數一枝獨秀。有趣的是,緊追在後的開源模型 DeepSeek V4 Pro,居然能與 封閉陣營並駕齊驅。

附贈:開源模型「內部規模」有多大

開源權重模型由於內部公開,因此也能得知其參數量(模型規模)。長條圖中深綠色部分是實際 推理時使用的「活性化參數」,淺綠色則是 MoE(Mixture of Experts)架構下,當下未被使用的 其餘專家部分。

開源權重模型的參數量

DeepSeek V4 Pro 以總計 1.6 兆參數居冠,但實際運行時只使用其中的 490 億(得益於 MoE 機制)。規模雖大卻能輕快運行,正是重點所在。圖中唯獨 Gemma 3 27B 的長條全為深綠色, 這是因為它並非 MoE,而是每次都會用到全部參數的「dense(密集)」架構。密集模型的總參數量 等於活性化參數量,因此與 MoE 陣營相比,其規模比較的意義略有不同,需特別留意。

結論:該選哪一個

  • 不管怎樣就是要最聰明的 → Claude Fable 5 或 Claude Opus 4.8(要有花大錢的心理準備)
  • 重視性價比,也想拿來寫程式 → DeepSeek V4 Pro(便宜到不行卻相當優秀)
  • 日常使用的均衡型 → Claude Sonnet 5 或 Gemini 3 Flash
  • 不管怎樣就是要便宜大量處理 → GPT-5 nano 或 DeepSeek V4 Flash

由於價格與排名的變動速度都很快,實際使用前別忘了到 openrouter.ai/models 確認最新資訊。

分數的資料來源

本文所使用的基準測試分數,來源如下。兩者皆為獨立於模型廠商之外的第三方評測網站所測量並 公布的數值。

另外,Kimi K2.6 / Qwen3.7 Max 的 SWE-bench Verified 分數在不同資料來源間存在近似值混雜的 情形,故僅作為參考值處理。

在 Claude Code 中使用 GLM-5.2 / GLM-4.7-Flash 模型

Claude Code CLI(claude)不只能用 Anthropic 原生模型,透過 OpenRouter 提供的 Anthropic Messages API 相容端點(「Anthropic Skin」),也能讓任意模型作為後端運作。這次我 嘗試了將對話主模型設為 z-ai/glm-5.2、標題產生等輕量背景任務用的模型設為 z-ai/glm-4.7-flash 的設定,這裡整理一下作法。

參考: https://openrouter.ai/docs/cookbook/coding-agents/claude-code-integration

前提條件

  • 已將 OpenRouter 的 API 金鑰設定於 $env:OPENROUTER_API_KEY
  • 即使已用 claude.ai 帳號登入 Claude Code,只要有透過環境變數的驗證,就會優先採用該方式。 此時會出現 ⚠ claude.ai connectors are disabled ... 的警告,但不影響實際運作。

所需的環境變數

變數備註
ANTHROPIC_BASE_URLhttps://openrouter.ai/apiOpenRouter 的 Anthropic 相容端點
ANTHROPIC_AUTH_TOKENOpenRouter 的 API 金鑰Authorization: Bearer 傳送
ANTHROPIC_API_KEY""(明確設為空字串)若未設定或非空,驗證方式會衝突而導致錯誤
ANTHROPIC_MODELz-ai/glm-5.2主要對話模型。直接指定 OpenRouter 上的模型 ID
ANTHROPIC_SMALL_FAST_MODELz-ai/glm-4.7-flash用於標題產生等輕量背景任務的子模型

主模型與子模型的區分使用

ANTHROPIC_MODEL 只控制主要對話模型。Claude Code 內部用於標題產生、 auto-mode 判斷等輕量、高速任務的子模型,則由 ANTHROPIC_SMALL_FAST_MODEL 指定。 只要設定這個變數,就能確實切換輕量任務所使用的模型。

設定方法

方法A:以專案為單位啟用(推薦)

在儲存庫的 .claude/settings.local.json 中設定如下內容。

{
"env": {
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
"ANTHROPIC_API_KEY": "",
"ANTHROPIC_MODEL": "z-ai/glm-5.2",
"ANTHROPIC_SMALL_FAST_MODEL": "z-ai/glm-4.7-flash"
}
}

ANTHROPIC_AUTH_TOKEN(機密資訊)不要寫入檔案,而是在 shell 端由 OPENROUTER_API_KEY 提供。只要在 PowerShell 設定檔($PROFILE)中加入以下內容一次, 之後每次開啟 shell 都會自動設定完成。

$env:ANTHROPIC_AUTH_TOKEN = $env:OPENROUTER_API_KEY

bash/zsh 的情況,則在 ~/.bashrc~/.zshrc 中加入:

export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"

在此狀態下於此目錄中執行 claude -p "...",就會自動讀取 .claude/settings.local.json 的設定,讓主模型與子模型都透過 OpenRouter 運作。 不會影響其他專案中 Claude Code 的執行。

方法B:僅針對特定指令暫時切換

若不想修改 shell 設定檔,可以在執行時當場指定環境變數。

PowerShell:

$env:ANTHROPIC_BASE_URL = "https://openrouter.ai/api"
$env:ANTHROPIC_AUTH_TOKEN = $env:OPENROUTER_API_KEY
$env:ANTHROPIC_API_KEY = ""
$env:ANTHROPIC_MODEL = "z-ai/glm-5.2"
$env:ANTHROPIC_SMALL_FAST_MODEL = "z-ai/glm-4.7-flash"
claude -p "1+1は?"

bash:

ANTHROPIC_BASE_URL="https://openrouter.ai/api" \
ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY" \
ANTHROPIC_API_KEY="" \
ANTHROPIC_MODEL="z-ai/glm-5.2" \
ANTHROPIC_SMALL_FAST_MODEL="z-ai/glm-4.7-flash" \
claude -p "1+1は?"

方法C:設為整台機器的預設值(不推薦)

若將上述變數持久化為 Windows 的使用者環境變數,任何終端機、任何專案都會預設透過 OpenRouter/GLM 運作。但這也會影響其他專案中原本打算使用一般 Claude(Anthropic) 的操作,因此除非確實想改變整體預設值,否則建議使用方法A/B。

動作確認

以下指令確認回應內容及計費紀錄(modelUsage)中都記錄了 z-ai/glm-5.2

claude -p "Reply with exactly: OK-GLM-TEST" --output-format json
{
"result": "OK-GLM-TEST",
"modelUsage": {
"z-ai/glm-5.2": { "inputTokens": 3272, "outputTokens": 8, "costUSD": 0.028336 }
}
}

此外,搭配 --debug all 執行稍長的提示詞後,也確認主模型與子模型的 派送實際上都有發生。

[API:timing] dispatching to firstParty model=z-ai/glm-4.7-flash
[API:timing] dispatching to firstParty model=z-ai/glm-5.2

針對單一提示詞,輕量任務正確地交由 z-ai/glm-4.7-flash 處理,正式回應則交由 z-ai/glm-5.2,模型的區分使用是正確的。

已知注意事項:互動式工作階段中的請求增生

在互動式 claude 工作階段(無論是從 VS Code 開啟或直接在 TTY 上啟動)中,即使只是輕微 輸入,OpenRouter 的 Activity 紀錄中同一分鐘內就記錄了多達 13 次 API 呼叫。其中 12 次是 發送給子模型(GLM 4.7 Flash)的小型呼叫,只有最後 1 次是主模型(GLM 5.2)的正式回應。 總成本約在 $0.0094 以內。

另一方面,也確認了透過 claude -p(非互動、print 模式)的單次執行,幾乎不會發生這種 增生現象。若想壓低成本,使用 -p 較為安全。若經常使用互動式工作階段,建議設定 ANTHROPIC_SMALL_FAST_MODEL 讓請求流向便宜的模型,同時透過 OpenRouter 的 Activity 儀表板監控用量。

疑難排解

  • ⚠ claude.ai connectors are disabled because ANTHROPIC_API_KEY or another auth source is set... 這個警告可以忽略(只是 claude.ai 的連接器功能被停用,API 呼叫本身仍會成功)。
  • ANTHROPIC_API_KEY 未設定而非設為空字串,驗證方式可能會變得曖昧而導致錯誤。 務必明確設定為 ""
  • 若想切換至其他模型,只需將 ANTHROPIC_MODEL 改為 OpenRouter 上的模型 ID (例如:anthropic/claude-opus-4-8openai/gpt-5 等)即可。
  • 工具搜尋最佳化(ENABLE_TOOL_SEARCH)在非 Anthropic 主機上預設為停用。 如有需要,請加入 ENABLE_TOOL_SEARCH=true

開發了連接 Claude Code、Codex、Gemini 的 LLM API 轉換代理伺服器「llmglot」

在 AI 開發現場,比起模型本身,越來越常被 API 規格差異所困擾。

Claude Code 使用 Anthropic Messages API。OpenAI 系工具使用 Chat Completions API 或 Responses API。Gemini 則有自己的獨立 API,而在本機 LLM 環境中,Ollama 與 LM Studio 會提供 OpenAI 相容 API。

明明想用的模型已經存在,卻因為 API 規格不同而無法連接。必須改寫 SDK、實作轉換層,並針對不同環境分別設定。

解決這類問題的就是 llmglot

GitHub: https://github.com/Himeyama/llmglot

llmglot 是什麼

llmglot 是一個可在多種 LLM API 之間相互轉換的代理伺服器。

它會接收 Anthropic Messages API、OpenAI Responses API、OpenAI Chat Completions API、Gemini API 等請求,並適當轉換後轉送到上游 API。

也就是說,即使客戶端要求的 API 規格與實際想使用的模型 API 規格不一致,也仍然可以使用。

支援範圍

以客戶端來說,支援:

  • Claude Code
  • Anthropic SDK
  • OpenAI SDK
  • Responses API 用戶端
  • Gemini SDK

等。

作為連接端則可使用:

  • Ollama
  • LM Studio
  • OpenAI
  • Gemini
  • OpenRouter
  • Azure OpenAI
  • vLLM

等。

例如:

  • Claude Code → Ollama
  • OpenAI SDK → Gemini
  • Responses API → Chat Completions API

這類連接都能實現。

連接 Claude Code 與本機 LLM

llmglot 的用途之一,就是連接 Claude Code 與本機 LLM。

例如使用 Ollama 時,可以用:

CHAT_BASE_URL=http://localhost:11434/v1 llmglot

來啟動。

接著只要把 Claude Code 的連接目的地改成 llmglot,就能從 Claude Code 使用本機 LLM。

不用昂貴的 API 就能試用程式碼代理,這點非常有吸引力。

(補充:Ollama 支援 Messages API,所以其實不需要代理)

也支援 Responses API

近年來,使用 Responses API 的工具越來越多。

llmglot 實作了 /v1/responses 端點,除了 HTTP 之外也支援 WebSocket。

因此,像 Codex CLI 這類以 Responses API 為基礎的客戶端也更容易連接。

日誌功能很方便

llmglot 配有日誌顯示功能。

可確認的資訊包括:

  • 模型名稱
  • 供應商
  • 輸入 token 數
  • 輸出 token 數
  • 快取使用量
  • 預估成本
  • 生成速度

等。

在使用多個 LLM 的環境中,能集中管理使用情況的優點非常大。

與 LiteLLM 的差異

這裡令人好奇的是與 LiteLLM 的差異。

兩者都是位於 LLM 中間層的軟體,但目標方向大不相同。

LiteLLM 的思路

LiteLLM 會將多數 LLM 供應商統一成 OpenAI 格式。

也就是:

應用程式

LiteLLM

各 LLM 供應商

這樣的架構。

可以說,它是為了讓應用程式開發者使用統一 API 的機制。

llmglot 的思路

另一方面,llmglot 則是:

Claude Code
Codex CLI
Gemini SDK

llmglot

各 LLM 供應商

這樣的架構。

其目的在於轉換客戶端的 API 規格。

以 Claude Code 來比較

Claude Code 使用 Anthropic Messages API。

LiteLLM 基本上是以 OpenAI 相容 API 為中心,因此要直接連接 Claude Code 並不容易。

相對地,llmglot 可以直接接收 Anthropic Messages API。

因此可以實現:

Claude Code

llmglot

Ollama

這樣的架構。

這是 llmglot 非常大的特色。

該選哪一個

適合 LiteLLM 的是:

  • 開發 AI 應用程式的人
  • 想把 OpenAI SDK 當作統一介面的人
  • 想做負載平衡或 fallback 的人

另一方面,適合 llmglot 的是:

  • 想讓 Claude Code 使用其他模型的人
  • 想讓既有客戶端使用本機 LLM 的人
  • 想把 Responses API 轉成其他 API 的人
  • 不想改寫 SDK 的人

總結

在 LLM 的世界裡,越來越多情況下,問題不在模型本身,而在 API 的差異。

想使用 Claude Code,卻想搭配 Ollama。想使用 OpenAI SDK,卻想搭配 Gemini。這類需求未來只會越來越多。

llmglot 就是在中間吸收這些 API 規格差異。

  • Claude Code → Ollama
  • OpenAI SDK → Gemini
  • Responses API → Chat Completions API
  • Gemini API → OpenAI 相容 API

如果說 LiteLLM 是「給開發者的統一 API」,那麼 llmglot 就可以說是「客戶端相容代理」。

什麼是適用於 Windows 的 Coreutils

WinGet 可安裝的 Microsoft 官方 Linux 指令群最新動向(2026 年 6 月更新)

2026 年 6 月,Microsoft 正式公開了 Coreutils for Windows

winget install Microsoft.Coreutils

透過這個指令可安裝的 Microsoft.Coreutils,是 Microsoft 官方專案,可讓 Linux 與 macOS 日常使用的 lscprmcat 等 UNIX 系指令,能在 Windows 上以原生方式執行。

本文將整理專案概要、支援指令、限制事項,以及與 WSL 和 PowerShell 的差異。

概要

Microsoft.Coreutils 是由 Microsoft 維護、面向 Windows 的命令列工具集。

其內部是以以下專案為基礎構建:

  • uutils/coreutils
  • findutils
  • grep

並以 Rust 實作。

Microsoft 將此專案的目的說明為:

降低在 Linux、macOS、WSL、容器、Windows 之間來回切換的開發者摩擦

安裝方法

可透過 WinGet 輕鬆導入。

winget install Microsoft.Coreutils

WinGet 是 Windows 內建的套件管理員,可自動下載並安裝指定套件。

安裝後即可作為一般指令使用。

ls
cat file.txt
grep keyword log.txt
cp source.txt backup.txt

可使用的主要指令

代表性的指令如下。

分類指令範例
檔案列表ls
檔案複製cp
檔案移動mv
檔案刪除rm
內容顯示cat
目前工作目錄pwd
建立目錄mkdir
休眠sleep
管線處理tee
搜尋grep, find

對 Linux 使用者來說,熟悉的指令可直接使用。

與 PowerShell 的衝突問題

這裡是最大的注意點!

PowerShell 內已經存在同名的別名或內建指令。

例如:

指令問題
ls與 PowerShell 別名衝突
cp與 Copy-Item 衝突
cat與 Get-Content 衝突
rm與 Remove-Item 衝突
pwd與 Get-Location 衝突

因此,

ls

即使執行了,也不一定會呼叫 Coreutils 版本。

Microsoft 建議使用 PowerShell 7.4 以上版本。

Windows 特有的限制

雖然目標是相容 Linux,但仍存在因 Windows 機制造成的限制。

1. 沒有 POSIX 訊號

Linux 的

kill
SIGTERM
SIGKILL

機制在 Windows 中不存在。

因此,

kill
timeout

目前尚未提供。

2. 沒有 /dev/null

Linux:

grep error log.txt > /dev/null

Windows:

grep error log.txt > NUL

會是這樣。

3. ACL 與 POSIX 權限的差異

Windows 是以 ACL 為基礎的權限管理。

因此,

chmod
chown
chgrp

等指令不會提供。


4. 建立符號連結

雖然可以讀取,但若要新建立,則需要:

  • Developer Mode
  • 管理員權限

不提供的主要指令

Microsoft 有意排除了一部分指令。

與 Windows 衝突的項目

  • dir
  • more
  • paste
  • whoami
  • expand

與 POSIX 強烈依賴的項目

  • chmod
  • chown
  • chgrp
  • chroot
  • nohup
  • stty
  • tty
  • who

目前尚未實作的項目

  • kill
  • timeout
  • dd

與 WSL 的差異

最常被比較的是 WSL(Windows Subsystem for Linux)。

項目Microsoft.CoreutilsWSL
導入成本非常低需要建置 Linux 環境
啟動速度原生有虛擬環境層
Linux 相容性部分非常高
Bash 環境
apt 可用性不可
Shell 腳本相容性有限制

WSL 是「Linux 環境本身」,而 Coreutils 則是「在 Windows 上使用類 Linux 指令的工具集」。

Makefile 的推薦

背景與問題意識

在日常工作中,使用 Python 腳本進行資料轉換自動化時,常常會遇到以下問題:

  • 明明只更新了原始資料的一部分,卻得整體重新執行,白白浪費時間。
  • 哪個步驟依賴哪個檔案不夠清楚,難以管理執行順序與遺漏情況。
  • 不容易掌握腳本修改會影響哪些產出物。

Makefile 具備「相依關係」與「只重跑差異部分(增量建置)」這些標準功能,能用很少的描述解決上述問題。

Make 的基本概念

  • 目標(target):產出物(例:output/report.csv)
  • 相依關係(dependency):產出所需的檔案(例:data/clean/*.csv 或腳本)
  • 配方(recipe):用來產出的指令(例:python scripts/aggregate.py ...)

Make 會在「相依關係比目標更新」時才執行配方。如此一來,當原始資料或 Python 腳本更新時,只會自動重跑必要的部分。

最小構成的 Makefile 範例

以下是一個將 raw 資料清理後,再產生彙總報表的差異執行範例。

# Makefile
SHELL := bash
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
.ONESHELL:
.DEFAULT_GOAL := all

RAW_DIR := data/raw
CLEAN_DIR := data/clean
OUT_DIR := output

RAW := $(wildcard $(RAW_DIR)/*.csv)
CLEAN := $(patsubst $(RAW_DIR)/%.csv,$(CLEAN_DIR)/%.csv,$(RAW))
REPORT := $(OUT_DIR)/report.csv

# 目錄為順序相依(不存在時建立,但不作為更新判定依據)
$(CLEAN_DIR) $(OUT_DIR):
mkdir -p $@

# 彙總報表依賴已清理的 CSV 與彙總腳本
$(REPORT): $(CLEAN) scripts/aggregate.py | $(OUT_DIR)
python scripts/aggregate.py -i $(CLEAN_DIR) -o $@

# 由各 raw CSV 產生對應的 clean CSV
$(CLEAN_DIR)/%.csv: $(RAW_DIR)/%.csv scripts/clean.py | $(CLEAN_DIR)
python scripts/clean.py -i $< -o $@

.PHONY: all clean status

all: $(REPORT)

clean:
rm -rf $(CLEAN_DIR) $(OUT_DIR)

# 確認哪些項目會被重建的輔助指令
status:
@echo "RAW : $(RAW)"
@echo "CLEAN : $(CLEAN)"
@echo "REPORT: $(REPORT)"
@echo
@echo "Dry-run (what would run):"
@$(MAKE) -n all

透過這個架構,可以達成以下效果:

  • 更新原始資料 data/raw/foo.csv 時,只會重新產生對應的 data/clean/foo.csv。
  • 更新 scripts/clean.py 時,只會在必要範圍內重新執行清理流程。
  • 更新 scripts/aggregate.py 時,只會重新執行彙總報表。

動作示意

# 第一次執行(全部產生)
make -j

# 部分 raw 更新(只重新執行該檔案的清理與報表)
touch data/raw/a.csv
make -j

# 清理腳本更新(重新執行所有清理與報表)
touch scripts/clean.py
make -j

# 彙總腳本更新(只重新執行報表)
touch scripts/aggregate.py
make

想事先確認「會執行什麼」時,make -n 很有用。

腳本相依性的設計指引

  • 每個規則都應明確將其直接呼叫的 Python 腳本列為相依關係,這很重要。
  • 若拆分成多個模組,應將目標規則所 import 的模組也納入相依關係,才能正確傳遞變更。簡便作法是把目標目錄下所有 Python 檔案變成變數,再加進相依關係中。

例(簡便作法):

PY_SRCS := $(wildcard scripts/**/*.py) $(wildcard scripts/*.py)

$(CLEAN_DIR)/%.csv: $(RAW_DIR)/%.csv $(PY_SRCS) | $(CLEAN_DIR)
python scripts/clean.py -i $< -o $@

平行執行與加速

  • 透過 make -j 可以將彼此獨立的檔案轉換平行化。資料點越多,效果越明顯。
  • 中間產物切得越細,增量執行越有效,也越能避免整體重算。
  • 若 I/O 是瓶頸,可搭配壓縮格式、檔案分割、或本機 SSD 使用。

實務上的訣竅

  • 目錄建立使用順序相依(| dir)處理,可避免不必要的重建。
  • 為了在失敗時不留下不完整產物,建議啟用 .DELETE_ON_ERROR
  • 常用入口可用 .DEFAULT_GOAL := all 標準化,讓 make 一次就能執行。
  • 除錯時可使用 make -n(只顯示不執行)、make --trace(顯示為何會執行)、make -d(詳細日誌)。
  • 清理請使用 .PHONY: clean,並注意只刪除生成物。

虛擬環境與依賴套件(選用)

Python 執行環境也可以交由 Make 管理。

VENV := .venv
PY := $(VENV)/bin/python

$(VENV)/bin/python: requirements.txt
python3 -m venv $(VENV)
$(VENV)/bin/pip install -r requirements.txt
touch $@

# 後續配方中使用 $(PY)
$(CLEAN_DIR)/%.csv: $(RAW_DIR)/%.csv scripts/clean.py | $(CLEAN_DIR) $(VENV)/bin/python
$(PY) scripts/clean.py -i $< -o $@

$(REPORT): $(CLEAN) scripts/aggregate.py | $(OUT_DIR) $(VENV)/bin/python
$(PY) scripts/aggregate.py -i $(CLEAN_DIR) -o $@

更新 requirements.txt 時,只會在必要範圍內重新完成設定。

總結

  • Makefile 是一種能自動化「明確相依關係」與「只重跑差異部分」的工具,能大幅提升資料轉換流程的可靠性與開發速度。
  • 正確連結原始資料、腳本與產出物,並將處理細化後,更新影響的範圍就能被快速重新計算。
  • 以最少的描述即可獲得可重現性、平行化與可觀測性,讓日常自動化工作變得更加順手。

在 Cloudflare Workers 上將自訂域名指向櫻花伺服器的子路徑

背景

櫻花的租用伺服器「輕量方案」以 每月121元 的超低價格提供36個月的預付方案。(12個月預付則為每月165元) 對於靜態文件的託管或 CGI 用途而言,這個價格相當合理,非常適合個人用途的儲存。

然而,所分配的域名會是 用戶名稱.sakura.ne.jp 的子域名, 若想要將自訂域名綁定於特定路徑,就需要一些技巧。

想要達成的目標

當訪問 https://app.example.com 時, 應該能在不更改 URL 的情況下顯示 https://sakurauser.sakura.ne.jp/app/ 的內容。

為什麼簡單的 DNS 設定無法實現

DNS 的 CNAME 記錄只能指定主機名稱,無法指定包含 路徑 的 URL,如 /app/

雖然使用重定向 (301) 也是一種方法,但這樣會使瀏覽器的地址欄中的 URL 變為 sakurauser.sakura.ne.jp/flower/

使用 Cloudflare Workers 的透明代理方式, 可以讓 URL 保持為 app.example.com

前提條件

  • 已在 Cloudflare 註冊自訂域名(例如: example.com
  • 使用 Cloudflare 的免費方案即可(每日 100,000 次請求以內免費)

步驟

1. 創建 Worker

  1. 進入 Cloudflare 儀表板 → Workers & PagesCreate
  2. 選擇 Start with Hello World!
  3. 輸入 Worker 名稱(例如: storage-proxy
  4. 點擊 Deploy

2. 編輯代碼

部署後,點擊 Edit code, 將其全部替換為以下代碼。

export default {
async fetch(request) {
const url = new URL(request.url);
const target = new URL("https://sakurauser.sakura.ne.jp");
target.pathname = "/app" + url.pathname;
target.search = url.search;

const newRequest = new Request(target.toString(), {
method: request.method,
headers: request.headers,
body: request.body,
});

const response = await fetch(newRequest);

const newHeaders = new Headers(response.headers);
newHeaders.delete("content-security-policy");
newHeaders.delete("x-frame-options");

return new Response(response.body, {
status: response.status,
headers: newHeaders,
});
}
};

總結

  • 櫻花租用伺服器的輕量方案價格非常便宜,特別適合用來儲存靜態文件,僅需 每月121元
  • 然而,要將自訂域名指向子路徑的 DNS 設定不是標準功能。
  • 通過使用 Cloudflare Workers 作為透明代理,可以在不改變 URL 的情況下提供內容。
  • Workers 的代碼大約只需要幾十行,並且可以在 Cloudflare 免費方案的範圍內運作。

CSS 為什麼「8 的倍數」成為邊距的標準

現代的 UI 設計中,「邊距設定為 8 的倍數」的規則被廣泛使用。這不僅僅是慣例,而是基於 螢幕密度、排版和比例的數學一致性所支持的經驗法則。

針對多種螢幕密度的應對

現代顯示器具有 1x、1.5x、2x、3x、4x 等像素比率。

1x1.5x2x3x4x
8 px812162432
5 px57.5 ⚠️101520

8 可以在多種倍率下整除,因此不容易發生次像素渲染的模糊效果。如果使用像 5 px 這樣的值,在 1.5x 環境中會導致 7.5 px 的尾數,渲染會變得不準確。

與排版的相容性

瀏覽器的預設字體大小為 16 px (= 8 × 2)。行距通常也為 1.5 倍 = 24 px (= 8 × 3)。

使用 8 的倍數設置邊距,可以讓文本的節奏視覺上更一致。因為標題和正文的高度與邊距網格相一致,從而產生整齊的垂直節奏

便於設計標記的創建

--space-1: 8px;
--space-2: 16px;
--space-3: 24px;
--space-4: 32px;

這樣的比例簡單,使設計師和工程師能更易於使用共同語言。Material Design 和 Tailwind CSS 也採用了這一思路。

設計師只需指定「這裡是 space-3」,工程師便能毫不猶豫地使用 24px。命名規則的統一降低了代碼評審時的溝通成本。

4 px 基礎的選擇

對於需要更細微調整的 UI,4 px 基礎 (4、8、12、16...) 也很常見。Tailwind CSS 預設採用 4 px 基礎 (p-1 = 4px)。

4 px 基礎也是 8 px 基礎的子集,因此兩者並不矛盾。可以在組件內部等細微的邊距使用 4 px 單位,在不同區域間等較大的邊距使用 8 px 單位進行區分,這樣的運用也很有效。

總結

8 px 的倍數作為邊距標準的原因可以歸納為三點。

  1. 應對螢幕密度: 在多種像素比率下能整除,防止次像素模糊。
  2. 與排版的一致性: 與預設字體大小 (16 px) 和行距 (24 px) 一致,產生垂直節奏。
  3. 比例的一致性: 簡單的標記體系成為設計師和工程師的共同語言。

新功能 Amazon S3 Files 讓 S3 桶可以掛載到 EC2

Amazon S3 Files 是一項可以將 S3 桶直接掛載到 EC2 等計算資源的服務,並且以 NFS 檔案系統的形式運行。資料保持在 S3 中,可以使用一般的檔案操作(lscpcat 等)進行讀寫。

S3 Files 是什麼

S3 Files 是基於 Amazon EFS 建立的共享檔案系統,讓使用者能以檔案系統的形式存取 S3 桶中的數據。

主要特點如下:

項目內容
協定NFS 4.1 / 4.2
支援的計算資源EC2、Lambda、ECS、EKS
同時連接數量最多 25,000 個計算資源
讀取吞吐量最大 TB/秒
IOPS超過 1,000 萬/桶
加密TLS(傳輸中)+ AWS KMS(儲存時)
檔案系統功能POSIX 權限、檔案鎖定、讀取後寫入一致性

運作原理

S3 Files 將被訪問的資料自動載入高效能儲存系統,並以低延遲的方式提供服務。

  • 小檔案(預設小於 128 KB):直接從高效能儲存中讀取
  • 大檔案(1 MB 以上):直接從 S3 流式傳輸
  • 寫入:在高效能儲存中寫入後,自動同步到 S3

高效能儲存中的資料,如果在一定時間內(預設 30 天,可設置為 1 - 365 天)未被訪問,將自動刪除。

前提條件

  • AWS 帳戶
  • EC2 實例(Linux)
  • S3 桶(與 EC2 相同區域)
  • 兩個 IAM 角色
    • 建立檔案系統用:對 S3 桶的讀寫權限
    • EC2 實例用:附加 AmazonS3FilesClientFullAccess 管理策略
  • 安全群組:允許 NFS 的 2049 端口通訊

IAM 角色的建立

S3 Files 需要兩個 IAM 角色。

1. 用於建立檔案系統的角色

使用管理控制台時會自動創建,因此不需要手動創建

此角色用於讓 S3 Files 存取桶。

# 創建角色
aws iam create-role \
--role-name S3Files-FileSystem-Role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "s3files.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}'

# 附加 S3 Files 客戶端策略
aws iam attach-role-policy \
--role-name S3Files-FileSystem-Role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess

在創建檔案系統時用 --role-arn 指定此角色。

2. 用於 EC2 實例的角色

未附加 IAM 角色會導致掛載失敗

在 CloudShell 中創建以下角色。

# 創建角色
aws iam create-role \
--role-name EC2-S3Files-Role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}'

# 附加 S3 Files 客戶端策略
aws iam attach-role-policy \
--role-name EC2-S3Files-Role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess

# 創建並附加實例檔案配置
aws iam create-instance-profile \
--instance-profile-name EC2-S3Files-Profile

aws iam add-role-to-instance-profile \
--instance-profile-name EC2-S3Files-Profile \
--role-name EC2-S3Files-Role

將此角色附加到實例上。

設定步驟

1. 準備 S3 桶

在 S3 控制台中創建通用桶,也可以使用現有的桶。

需要特別注意的是,必須啟用桶的版本控制設定

2. 創建檔案系統

從控制台創建

alt text

  1. 在 S3 控制台中選擇桶
  2. 點擊「檔案系統」標籤 → 「創建檔案系統」

從控制台創建後,所有可用區會自動創建掛載目標和存取點。

alt text

  1. 指定前綴和 VPC,然後點擊「創建檔案系統」。

記錄下輸出的檔案系統 ID(例如:fs-0123456789abcdef0)。

3. 在實例中掛載

在終端中執行以下命令。

# 創建掛載點
sudo mkdir /mnt/s3files

# 挂載
sudo mount -t s3files fs-0123456789abcdef0:/ /mnt/s3files
備註

如果無法掛載,請執行以下命令再試一次:

sudo dnf install -y amazon-efs-utils # Amazon Linux, RHEL
# sudo apt install -y amazon-efs-utils (Ubuntu, Debian)
備註

如果在執行 dnf 命令時通訊出現問題,請設置 S3 端點(網關),並指定與實例相同的可用區。

但要注意,S3 端點的路由表應與實例所在的子網相同。

確認掛載情況:

df -h /mnt/s3files

應顯示類似以下內容:

Filesystem Size Used Avail Use% Mounted on
<s3files-dns> 8.0E 129M 8.0E 1% /mnt/s3files

4. 確認運行

cd /mnt/s3files

# 創建檔案
sudo sh -c 'echo "Hello, s3 Files!" > test.txt'

# 讀取檔案
cat test.txt

# 創建目錄
sudo mkdir test-directory

ls -la

# 複製檔案
sudo cp test.txt test-directory/

cd test-directory/

# 確認檔案列表
ls -la

寫入的檔案會在約 1 分鐘內與 S3 桶同步。可以在 S3 控制台確認對象已創建。

aws s3 ls s3://<bucket-name>/

自動掛載設定

為了在重啟後保持掛載,需要將以下內容添加到 /etc/fstab

# 添加到 /etc/fstab
fs-0123456789abcdef0:/ /mnt/s3files s3files _netdev,nofail 0 0

_netdev 是一個選項,確保在網路連接後再進行掛載,這是必需的。加入 nofail 可以防止掛載失敗時導致實例無法啟動。

收費

S3 Files 的收費如下:

  • 高效能儲存使用量:檔案系統中數據的儲存費用
  • 檔案系統存取費用:對高效能儲存進行讀寫操作的費用
  • S3 請求費用:對於直接從 S3 讀取大於 1 MB 的檔案,僅收取 S3 GET 費用

為按量計費的無需配置模式,根據 AWS 的說法,與傳統 S3 和檔案系統間數據複製相比可減少最多 90% 的成本。

總結

  • 使用 S3 Files 可以將 S3 桶掛載為 NFS 檔案系統在 EC2 上
  • 數據保留在 S3 中,可以使用 lscatcp 等正常的檔案操作
  • 透過高效能儲存提供低延遲,未被訪問的數據會自動退避
  • 通過 /etc/fstab 設定自動掛載,即使重啟後也能維持

參考