PlantUML CLI 高级用法:批量渲染、stdin/stdout、CI 集成、增量构建

puml.online

多数人只会 plantuml file.puml——但 plantuml 命令行能做到的事比想象的多得多。这一篇整理「脚本小子」级别用法:批量、CI、监控、管道、自定义预处理。

命令行最小知识

1
plantuml [options] file-or-files

常用选项:

选项 含义
-tsvg / -tpng / -tpdf / -tlatex 输出格式
-o dir 输出目录
-I path !include 搜索路径
-c 共用 SVG 不带 CSS
-DPLANTUML_CONFIG=... 加载全局皮肤文件
-thread N / -no-thread 线程数(默认 JVM 核心数)
-checkonly 只校验,不渲染
-pipe 从 stdin 读 / 输出到 stdout
-stdlib 输出标准库路径
-language 列出支持的语言

1. 单文件管道:从 stdin 读

1
2
3
echo "@startuml
Alice -> Bob: hi
@enduml" | plantuml -pipe -tsvg > out.svg

实战:渲染一段内存里的 puml 字符串,不用写临时文件——配合 curl 拉远程 source 或 jq 解析 JSON 里的 puml block。

2. 渲染整个目录

1
plantuml -tsvg -o rendered/ docs/diagrams/

渲染 docs/diagrams 目录下所有 .puml 文件到 rendered/

缺点:会递归处理所有子目录,包括你不想要的。

控制递归

1
plantuml -tsvg -recursive=false -o rendered/ docs/diagrams/*.puml

不用递归时显式列出文件列表。

3. 批量并发

1
2
3
4
5
# plantuml 自身支持线程
plantuml -tsvg -thread 8 -o rendered/ docs/diagrams/*.puml

# 或者外部并行调度
ls docs/diagrams/*.puml | xargs -P 4 -I{} plantuml -tsvg {} -o rendered/

注意xargs -P N 调 N 个 plantuml 进程,每个都是 JVM——4 进程 = 4 × JVM 启动开销。用 plantuml 自带的多线程模式更划算

性能调优

1
2
# 4 核 → 用 3 个线程,1 个给系统
plantuml -tsvg -thread 3 -o rendered/ docs/diagrams/*.puml

4. stdin → 多个输出格式

1
cat diagram.puml | plantuml -pipe -tsvg -o /tmp/pipe/

-pipe + 输出目录:植物uml 自动产生 diagram.svg/tmp/pipe/

多个输出格式用 -pipe 不行——只能一次一种。

一次渲染多格式

1
2
3
for fmt in svg png pdf; do
plantuml -t${fmt} -o "rendered-${fmt}" diagram.puml
done

5. 只校验不渲染(CI 友好)

1
plantuml -checkonly diagram.puml

exit code 0 成功;非 0 失败——CI 友好。

实际 CI 校验流程

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
set -e
fail=0
for f in $(find docs -name '*.puml'); do
if ! plantuml -checkonly "$f"; then
echo "❌ $f 语法错"
fail=1
fi
done
exit $fail

-tsvg:只解析不渲染,CI pipeline 里 1 分钟跑完 100 张图。

6. 增量构建:复用旧图

1
2
plantuml -tsvg -o rendered/ docs/diagrams/*.puml
# PlantUML 不检测改动 —— 会重渲染所有图

自建增量

1
2
3
4
5
6
7
8
#!/bin/bash
# 增量渲染:只重渲 mtime 比 SVG 新的 puml
for puml in docs/diagrams/*.puml; do
svg="rendered/$(basename "$puml" .puml).svg"
if [ ! -f "$svg" ] || [ "$puml" -nt "$svg" ]; then
plantuml -tsvg "$puml" -o rendered/
fi
done

更聪明:记住上次 hash

1
2
3
4
5
6
7
8
9
10
11
12
13
store=".cache/puml-hashes.json"
mkdir -p .cache
[ -f "$store" ] || echo '{}' > "$store"

for puml in docs/diagrams/*.puml; do
name=$(basename "$puml" .puml)
cur_hash=$(md5sum "$puml" | cut -d' ' -f1)
prev_hash=$(jq -r ".\"$name\" // \"\"" "$store")
if [ "$cur_hash" != "$prev_hash" ]; then
plantuml -tsvg "$puml" -o rendered/
jq --arg n "$name" --arg h "$cur_hash" '.[$n]=$h' "$store" > "$store.tmp" && mv "$store.tmp" "$store"
fi
done

依赖图变化也会触发(让 !include 子文件被追踪):

1
2
3
4
5
6
7
8
# 监听:puml + include 的依赖文件
hash_inputs() {
local puml="$1"
cat "$puml"
grep -h '!include' "$puml" | awk '{print $2}' | while read -r inc; do
[ -f "inc/$inc" ] && cat "inc/$inc"
done | md5sum
}

7. 监控文件:自动重新渲染

fswatch(macOS)

1
fswatch -o docs/diagrams/ | xargs -I{} plantuml -tsvg -o rendered/ docs/diagrams/*.puml

每次文件变动都重新渲染。

inotifywait(Linux)

1
2
3
while inotifywait -e close_write docs/diagrams/; do
plantuml -tsvg -o rendered/ docs/diagrams/
done

实用 dev workflow

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# scripts/dev-watch.sh
# 监听 docs/diagrams 变化,自动渲染
trap "kill 0" EXIT
while true; do
if inotifywait -qq -e close_write docs/diagrams/; then
echo "→ re-render"
plantuml -tsvg -o public/img/diagrams/ docs/diagrams/*.puml
fi
done

启这个脚本 + 浏览器 localStorage: refreshInterval: 5 ——「边写边看图」全流程。

8. 预处理:自动注入皮肤

CI 渲染时想统一加皮肤,但不想改每个 .puml 文件:

1
2
3
4
5
6
7
8
9
10
11
# 注入 skinparam 到 @startuml 之后
for puml in docs/diagrams/*.puml; do
awk '/^@startuml/ {
print
print "skinparam defaultFontName \"Noto Sans CJK SC\""
next
}
{ print }
' "$puml" > /tmp/processed.puml
plantuml -tsvg /tmp/processed.puml -o rendered/
done

用 sed 简易版

1
2
sed '/^@startuml/a skinparam defaultFontName "Noto Sans CJK SC"' file.puml > /tmp/processed.puml
plantuml -tsvg /tmp/processed.puml

9. 错误处理 / 日志

默认输出

1
2
plantuml -tsvg diagram.puml
# 默认输出大量 INFO 日志

静默

1
plantuml -tsvg -quiet diagram.puml

或者 -SINGLE_LINE_LOG=quiet。CI 用 2>/dev/null

详细日志

1
plantuml -tsvg -DEBUG diagram.puml 2> debug.log

调试 .h 文件 / 字体加载问题时用。

10. 标准库路径

1
2
3
plantuml -stdlib
# 输出标准库路径
# /opt/plantuml/stdlib/

你的 puml 可以用 !include <C4/Container> 之类引用标准库图(C4 模型、BPMN、Archimate 等)。

自定义 stdlib

1
plantuml -stdlib %your-custom-stdlib-path%

11. 用 plantuml 跑 stdin + 拿 stdout

1
2
echo 'Alice -> Bob' | plantuml -pipe -tsvg
# 输出 SVG 到 stdout

但 PlantUML 输出含 XML 头——直接 cat:

1
2
3
svg="$(echo 'Alice -> Bob' | plantuml -pipe -tsvg)"
# 嵌入 HTML
echo "<div>$svg</div>" > /tmp/page.html

多文件打包

1
2
3
for puml in files/*.puml; do
echo "<div>$(plantuml -pipe -tsvg < "$puml")</div>"
done > all.html

12. 注入 Python / JS 预处理

如果你想让 plantuml 在 render 前自动 lint、加指纹、做兼容处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
# preprocess():预处理 puml 源码
preprocess() {
python3 -c "
import sys
src = sys.stdin.read()
# 加全局皮肤
src = src.replace('@startuml', '@startuml\n!theme cyborg', 1)
# 移除注释
src = '\n'.join(l for l in src.split('\n') if not l.strip().startswith(\"' ''\"))
sys.stdout.write(src)
"
}

cat docs/diagrams/system.puml | preprocess | plantuml -pipe -tsvg > out.svg

13. SVG 后处理(CSS / transform / 压缩)

1
2
3
plantuml -tsvg diagram.puml
# 用 SVGO 压缩
npx svgo -i rendered/diagram.svg -o rendered/diagram.min.svg

或者注入企业颜色:

1
2
3
plantuml -tsvg diagram.puml
sed -i 's|fill="#FFFFFF"|fill="#FAF9F6"|g' rendered/diagram.svg
sed -i 's|font-family="sans-serif"|font-family="Inter"|g' rendered/diagram.svg

14. 完整 CI pipeline 例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# .github/workflows/diagrams.yml
name: Render PlantUML diagrams
on:
push:
paths: ['docs/diagrams/**']

jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install PlantUML
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk
wget -O plantuml.jar https://github.com/plantuml/plantuml/releases/download/v1.2026.x/plantuml-1.2026.x.jar

- name: Lint
run: |
for f in docs/diagrams/*.puml; do
java -jar plantuml.jar -checkonly "$f" || exit 1
done

- name: Render
run: |
java -jar plantuml.jar -tsvg -o public/img/diagrams/ docs/diagrams/*.puml

- name: Diff
run: |
git diff --exit-code public/img/diagrams/ || {
echo "图有改动但 puml 没动,PR 必检"
exit 1
}

- name: Commit
run: |
git add public/img/diagrams/
git commit -m "docs: re-render diagrams"
git push

关键git diff --exit-code 让图过时变成 build failure。

15. 一段「综合」脚本(覆盖 80% 用例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
# scripts/render-puml.sh
# 渲染 docs/diagrams 里所有图到 public/img/diagrams
# 改 puml 才重渲,改 alone include 也连带
set -e

INPUT_DIR="${1:-docs/diagrams}"
OUTPUT_DIR="${2:-public/img/diagrams}"
mkdir -p "$OUTPUT_DIR"

# 检查 plantuml 已安装
if ! command -v plantuml > /dev/null; then
echo "❌ plantuml not found"
exit 1
fi

# 校验
echo "→ 校验 puml"
fail=0
while read -r puml; do
if ! plantuml -checkonly "$puml" 2>&1 | grep -qE "ERROR"; then
:
else
echo "❌ $puml"
fail=1
fi
done < <(find "$INPUT_DIR" -name '*.puml' -type f)
[ "$fail" -eq 0 ] || exit 1

# 渲染
echo "→ 渲染"
plantuml -tsvg -thread 4 -o "$OUTPUT_DIR" "$(find "$INPUT_DIR" -name '*.puml')"

# 压缩 SVG
for svg in "$OUTPUT_DIR"/*.svg; do
[ -f "$svg" ] || continue
npx svgo -i "$svg" -o "$svg" 2>/dev/null || true
done

echo "✓ done"

16. 调试 PlantUML CLI 自身

1
2
3
4
5
6
7
8
9
# Java 启动信息
plantuml -version
java -version # Java 必须在 PATH

# 字体调试
plantuml -checkonly -DEBUG diagram.puml 2>&1 | grep -i font

# 堆栈 / 调试
plantuml -tsvg -DEBUG -J-Djdk.trace=true diagram.puml 2>&1 | head -50

排除具体错误

错误 怎么排查
Could not find Graphviz graphviz,或换 ELK
Java not found apt install default-jdk
font not found fc-list 看字体;用 -fontpath 指定
diagram not supported 改用 client render / 换 cheat
OutOfMemoryError: Java heap space -Xmx2048m JAVA_OPTS

小结

  • plantuml CLI 不是 单文件 1 命令——管道、监控、并发、增量都有方案
  • 增量是提升 CI 效率的关键—— 8 张图 vs 200 张图差 50×
  • 调试时 plantuml -checkonly -DEBUG 是入口
  • 配合 inotifywait + fswatch 边写边看

下一步

  • 标题: PlantUML CLI 高级用法:批量渲染、stdin/stdout、CI 集成、增量构建
  • 作者: puml.online
  • 创建于 : 2026-07-30 12:30:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-cli-advanced/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。