运维

记录一些简单的运维知识

国内注册域名后要先实名认证后,使用国内的服务器时,网站还需要在工信部,网安备案

在国内域名商购买了域名,解析的主机或服务器也在国内时,则必须备案通过后才能访问

海外域名,就只能用国外或香港主机/服务器,不能解析到国内的服务器

运维知识库大全

运维相关好用工具

一个 平台工程(Platform Engineering) 相关的优秀工具与最佳实践的开源资源合集。从源码管理、CI/CD、部署、监控、安全、内部开发门户等多个方面,按类别列出对应工具、规范、参考架构以及学习材料,帮助工程团队系统化构建、管理与演进内部平台

iperf3

iPerf是一个支持跨平台部署使用的网络性能测量工具。它可以创建数据流测量两端之间单向或双向的网络吞吐量。

安装

官网下载链接

威联通安装方式

如何在局域网测网速?手把手教会NAS、电脑、路由器、手机如何安装 iperf3

如何在局域网测网速?手把手教会NAS、电脑、路由器、手机如何安装 iperf3

网络环境新增一个 TCP 端口,主机和容器都选择 5201,一般 iperf3 默认的端口也是 5201

如何在局域网测网速?手把手教会NAS、电脑、路由器、手机如何安装 iperf3

在命令行里输入-s,这个是开启5201 监听端口的命令,这样其他设备才能通过命令访问 NAS 的 iperf3 端口

总览:

如何在局域网测网速?手把手教会NAS、电脑、路由器、手机如何安装 iperf3

使用

启动服务端: iperf3 -s

启动客户端: -perf3 -c 服务端ip地址

-P 8表示启用8线程

-R 反转数据流方向(数据从服务端发向客户端)

-t 1800 表示测试时长1800秒

--logfile 保存文件名.txt 设置导出为文件(设置后,测试结果就不会在命令行中展示了)

socat简易代理

1
2
3
4
5
# 安装 socat
brew install socat

# 创建代理,将 0.0.0.0:3003 转发到 127.0.0.1:3002
socat TCP-LISTEN:3003,fork TCP:127.0.0.1:3002

比方说有些服务端程序,只监听了127.0.0.1,而没有监听本机ip,则无法通过本机ip访问到他,就可以通过这个创建个代理解决这个问题

关于ECC

ECC(Error-Correcting Code)内存是一种能够自动检测和修正内存错误的技术。它通过添加额外的位来存储数据,从而能够识别和纠正单比特错误。这在服务器和关键任务系统中尤其重要,因为这些系统对数据的准确性和可靠性有很高的要求。 ECC内存的主要优点包括:

  1. 数据完整性:能够自动检测并修正内存中的错误,从而减少数据损坏的风险。
  2. 系统稳定性:提高系统的稳定性,减少由于内存错误导致的崩溃或数据丢失的可能性。
  3. 适用于关键应用:在需要高可靠性的环境中(如金融、医疗和科学计算等领域),ECC内存是一个理想的选择。

全世界的商用级服务器都在使用ECC内存纠错

内存条的区别主要在于ECC内存条其中一面的一个额外的内存颗粒上,这个颗粒会对内存进行校验,在内存和处理器间传递数据之前,进行奇偶校验

ECC内存通常使用汉明码(Hamming Code)或其他更高级的错误更正码来实现错误检测和纠正功能。

必要性在于bit有时候会自己反转,造成软错误.如果位反转现象没有被发现和解决的话,会导致数据损坏或崩溃

会影响内存出现软错误频率的因素主要有下面几项:

  1. 大小
  2. 速度
  3. 密度

一个来自谷歌的相关研究表明:

大概32%的服务器以及8%的内存会在每年至少遇到一次内存错误

如果使用的是ECC内存,就可以一定程度上把这些内存错误找到并更正

缺点就是: 同一个内存频率下,支持ECC的内存条比普通内存条跑分更低,性能差在0%到20%之间

ECC内存条要比普通内存条贵,原料成本最多增加12%

Windows上的运维工具盘点

powershell中查硬盘信息指令Get-PhysicalDisk | Format-Table FriendlyName, MediaType, Size, HealthStatus

获取剪贴板内容: Get-Clipboard

Sysinternals

Sysinternals 工具包是由微软官方提供的一套免费、专业级的 Windows 系统诊断与管理工具集,由知名系统专家 Mark Russinovich 和 Bryce Cogswell 创建,后于 2006 年被微软收购并持续更新至今。它被广泛誉为“Windows 管理员的瑞士军刀”,适用于系统故障排查、性能优化、安全分析及开发调试等场景。

Sysinternals 工具包是 Windows 系统管理的终极工具箱,尤其适合 IT 运维、安全工程师及开发者。其通过底层监控能力模块化工具设计,解决了从日常维护(如清理启动项)到深度故障(如内核级 Rootkit)的复杂问题。对于普通用户,建议优先掌握 Process ExplorerAutorunsProcess Monitor三大核心工具;专业用户则可结合脚本(如 PowerShell 调用 PsTools)实现自动化管理

下载与配置

下载地址

官方文档

相关书籍: 《Windows Sysinternals 实战指南》(中文版已出版)

将工具路径添加到系统环境变量(永久生效)

  1. Win + S 搜索 “编辑系统环境变量” → 打开。
  2. 点击 “环境变量” → 在 “系统变量” 中找到 Path→ 点击 编辑
  3. 点击 新建 → 输入工具解压目录路径(如 C:\Sysinternals)→ 连续点击 确定 保存。

优势

深度系统访问

  • 深度系统访问: 直接调用 Windows 内核 API,提供任务管理器、资源监视器等原生工具无法获取的底层数据(如句柄类型、线程堆栈
  • 轻量化与高效性: 工具均为绿色单文件,体积小巧(多数 <1MB),运行时资源占用低,适合生产环境部署
  • 跨平台与持续更新: 支持 Windows XP 至 Windows 11,含 x86、x64 及 ARM 架构版本,微软每月推送安全及功能更新
  • 开源与社区生态: 部分工具开源(如 ProcDump),拥有活跃社区和官方博客(Mark Russinovich 定期发布案例解析)

工具盘点

Sysinternals 包含 70 余款工具,按功能可分为以下类别

场景 推荐工具
系统监控 Process Explorer, Process Monitor, TCPView
安全分析 Autoruns, Sysmon, AccessChk
故障排除 ProcMon, VMMap, RAMMap, Procdump
远程管理 PsExec, PsService, PsPing, PsKill
性能优化 Contig, CacheSet, Coreinfo, DU
演示培训 ZoomIt, BgInfo

进程和系统监视工具

工具 类型 功能 使用说明
Process Explorer
procexp.exe
GUI 高级进程管理器,Task Manager增强版 双击运行,支持搜索进程句柄/DLL,查看进程树,VirusTotal集成
[Process Monitor](#Process Monitor)
procmon.exe
GUI 实时文件系统/注册表/进程监控 双击运行,捕获实时操作,支持强大过滤,可保存Capture文件供分析
DebugView
dbgview.exe
GUI 捕获和显示调试输出 双击运行,Capture→Capture Kernel启用内核调试输出
Handle CLI 显示进程句柄信息 handle 列出所有句柄;handle procname 查找特定进程
ListDLLs CLI 列出进程加载的DLL listdlls 列出所有进程DLL;listdlls -d dllname 查找加载某DLL的进程
VMMap GUI 进程虚拟/物理内存分析 双击运行,选择进程查看内存布局,分析内存泄漏
RAMMap GUI Windows物理内存使用分析 双击运行,查看内存分类使用,Empty菜单可清空缓存
Pipelist CLI 列出命名管道 pipelist 列出所有管道;pipelist -s 显示详细信息
CPUSTRES GUI/CLI CPU压力测试 双击运行,添加线程设置负载百分比
Procdump CLI 生成进程转储文件 procdump -ma pid 生成完整Dump;procdump -e -w procname 崩溃时自动Dump
D:\dumps\:指定保存路径 procdump -ma -e -w -o myapp.exe D:\dumps\
-ma:生成完整的内存 dump;-o:覆盖已存在的同名 dump 文件
NotMyFault GUI/CLI 模拟系统故障 双击运行,可模拟蓝屏、内存泄漏、CPU负载等
Testlimit CLI 测试系统资源限制 testlimit -m 500 分配500MB内存;testlimit -h 1000 创建1000句柄
WinObj GUI NT对象管理器查看器 双击运行,浏览内核对象命名空间
Process Monitor

ProcMon 是微软 Sysinternals 里Windows 实时行为监控的终极工具

程序闪退、报错、权限不足、找不到文件、被篡改配置、偷偷联网、启动异常等所有疑难问题

ProcMon 只抓真实发生的系统操作,覆盖所有你排查问题需要的行为:

  1. 文件系统

    新建、读取、写入、删除、重命名、遍历文件夹

  2. 注册表

    读取、写入、创建、删除注册表项 / 键值

  3. 网络

    TCP/UDP 连接(目标 IP、端口、协议)

  4. 进程 / 线程

    进程创建 / 退出、线程启动、DLL / 驱动加载

用法

  • 启动要求

    • ProcMon64.exe
    • 必须右键 → 以管理员身份运行,否则看不到系统 / 服务级活动
  • 工具栏 5 个核心按钮

    1. ☑️ Capture(Ctrl+E):开始 / 停止捕获日志(抓完问题立刻停,减少性能占用)
    2. 🧹 Clear(Ctrl+X):清空当前所有日志
    3. 🔍 Filter(Ctrl+L):打开过滤规则(最核心功能)
    4. 📌 Highlight:把关键日志高亮(比如标红报错)
    5. 5 个类别开关:只显示:注册表 / 文件系统 / 网络 / 进程 / 性能统计 → 建议默认关掉「Performance」,日志少 90%
  • 关键列含义

    • Process Name:哪个进程在操作(如 xxx.exe

    • Operation:做了什么(Read/Write/Create/Connect 等)

    • Path:操作的文件 / 注册表 / 网络地址

    • Result

      :结果

      • SUCCESS:成功
      • NOT FOUND:找不到文件 / 注册表
      • ACCESS DENIED:权限被拒绝(排查报错神器)
    • Detail:详细参数

配合 ProcDump 查崩溃

  • ProcMon:看崩溃前最后一步操作(读什么文件、写什么注册表)

  • ProcDump:抓崩溃内存 dump

    两者配合 = 100% 定位崩溃原因

以网络行为的UDP过滤为例可以设置为

  1. Ctrl+L 打开过滤窗口

  2. 只看特定程序的 UDP 流量案例

    按照下面内容配置

    1
    2
    3
    4
    5
    6
    7
    Process Name is 目标程序.exe → Include
    Operation contains UDP → Include
    Category is Network → Include
    #如果还要排查失败情况
    Result contains FAIL → Include
    Result contains ACCESS DENIED → Include
    Result contains TIMEOUT → Include
  3. 这样可同时满足「网络类别 + UDP 协议」双重条件

若需要查看数据包中的具体内容,需要通过抓包软件

NotMyFault

Not My Fault 是模拟 Windows 进程 / 系统崩溃的专用工具,核心用于测试 dump 捕获工具(如 ProcDump)或系统故障恢复机制

注意: 必须管理员权限启动

  • 触发 NotMyFault64.exe 进程崩溃(生成完整 dump)

    1
    2
    # 管理员权限运行
    NotMyFault64.exe /crash /full
  • 触发系统蓝屏(0xE2 错误)

    1
    2
    # 管理员权限运行
    NotMyFault64.exe /bugcheck
  • 让进程挂起 10 秒后恢复(进阶)

    1
    2
    # 挂起进程,10 秒后自动恢复
    NotMyFault64.exe /hang /timeout 10

内存泄露指标 分页与非分页内存

内存池类型 核心特性
分页池(Paged Pool) 1. 内存数据可以被分页到磁盘(写入 pagefile.sys 页面文件);
2. 当物理内存不足时,系统会把这部分内存暂存到硬盘,释放物理内存;
3. 仅内核中 “不要求实时访问” 的代码 / 数据会使用这类内存。
非分页池(Nonpaged Pool) 1. 内存数据永远常驻物理内存,绝不会被分页到磁盘;
2. 内核中 “需要实时访问” 的代码 / 数据(比如硬件驱动、中断处理程序)必须用这类内存;
3. 容量受物理内存大小严格限制(32 位系统更明显)。

泄露表现区别

对比维度 Leak Paged(分页内存泄漏) Leak Nonpaged(非分页内存泄漏)
泄漏的内存类型 分页池(Paged Pool) 非分页池(Nonpaged Pool)
内存是否可换出 是(不足时可写入硬盘页面文件) 否(永久占用物理内存)
系统影响速度 较慢,系统会先消耗页面文件,再逐步影响性能 极快,直接耗尽物理内存中留给内核的关键区域
典型系统表现 1. 系统逐渐卡顿、响应变慢;
2. 页面文件(pagefile.sys)体积持续增大;
3. 应用程序可能因内存不足报错,但系统暂时不会蓝屏。
1. 短时间内触发系统高内存占用;
2. 驱动 / 内核进程无法分配内存,直接导致系统蓝屏(常见错误码:0x0000008E、0x000000A0);
3. 蓝屏前可能出现服务崩溃、硬件无响应。
危险程度 中等(影响性能,极少直接蓝屏) 极高(几乎必然导致系统蓝屏,是服务器故障的常见原因)
测试适用场景 验证系统对低优先级内存泄漏的容忍度、页面文件的扩容机制 测试系统崩溃转储(dump)是否正常、内核内存监控告警是否生效
CPUSTRES

CpuStres 是微软 Sysinternals 套件中的轻量级 CPU 压力测试工具,核心能力是通过可控的多线程循环模拟不同强度的 CPU 负载,用于系统稳定性验证、散热性能测试、资源瓶颈定位与性能基准评估,完全免费、无需安装、即用即走。

场景 核心用途
系统稳定性测试 长时间高负载验证,排查隐性硬件 / 驱动问题
散热效能评估 满负载测试 CPU 温度、风扇转速与散热系统能力
性能基准对比 测试不同配置(超频 / 降频 / 电源计划)下的 CPU 表现
软件兼容性验证 模拟高 CPU 使用率环境,测试软件稳定性
资源瓶颈定位 结合 Process Monitor 等工具,观察系统在压力下的资源争用

核心参数

  • Activity Level(负载强度)详解:这是最关键的参数,决定了每个线程的 CPU 占用率。

    级别 休眠策略 典型 CPU 占用 适用场景
    Low 长休眠 + 短计算 5-15% 模拟轻度负载,测试系统在低压力下的响应
    Medium 中等休眠 + 中等计算 30-50% 模拟日常办公负载,如浏览器 + 办公软件
    Busy 短休眠 + 长计算 70-90% 模拟重度负载,如视频渲染、编译
    Maximum 无休眠 + 持续计算 99-100% 满负载压力测试,验证系统极限能力
    • 原理:每个线程在计算循环中插入 Sleep() 调用,通过调整休眠时间控制 CPU 占用率
  • Thread Priority(线程优先级):控制线程在系统调度中的优先级。

    • 建议使用 Normal(标准)优先级,避免影响系统关键进程
    • 高优先级(Above Normal/High)会抢占更多 CPU 时间,适合模拟关键任务负载
  • Affinity(CPU 亲和性):将线程绑定到特定 CPU 核心,用于:

    • 测试单个核心性能
    • 模拟 NUMA 架构下的负载分布
    • 排查特定核心的硬件问题
    • 示例:绑定线程 1 到 CPU0,线程 2 到 CPU1,模拟多核心独立负载

使用案例

  • 场景 1:模拟 8 核 CPU 50% 负载

    • 点击 Options → Thread Count → 选择 8
    • 为每个线程设置 Activity Level: Medium
    • 启动所有线程,总 CPU 使用率约 50%
  • 场景 2:测试特定核心性能

    • 右键线程 1 → Set Affinity → 选择 CPU0
    • 设置 Activity Level: Maximum
    • 启动线程 1,观察单个核心的负载情况
  • 场景 3:混合负载模拟

    • 线程 1-4: Maximum(核心业务负载)
    • 线程 5-8: Medium(后台任务负载)
    • 线程 9-12: Low(系统服务负载)
    • 启动所有线程,模拟真实复杂系统环境
  • 命令行模式(自动化测试)

    CpuStres 支持命令行参数,适合脚本化 / 自动化测试:

    1
    2
    3
    4
    5
    6
    7
    8
    # 启动4个Maximum负载线程,运行10分钟后自动停止
    CpuStres64.exe /start 4 /activity maximum /duration 600

    # 启动2个Medium负载线程,绑定到CPU0和CPU1
    CpuStres64.exe /start 2 /activity medium /affinity 0x3

    # 命令行参数完整列表
    CpuStres64.exe /? # 查看所有可用参数
    参数 说明 示例
    /start N 启动 N 个线程 /start 8
    /activity [level] 设置活动级别 /activity busy
    /priority [level] 设置线程优先级 /priority high
    /affinity [mask] 设置 CPU 亲和性掩码 /affinity 0xF(绑定到 CPU0-3)
    /duration [seconds] 运行时长(秒) /duration 300(5 分钟)
    /pause 启动后暂停所有线程 /pause
    /stop 停止所有线程 /stop
Testlimit

Testlimit 是微软 Sysinternals 套件中专门用于模拟各类系统资源耗尽的测试工具,核心作用是主动耗尽内存、句柄、进程、线程等系统资源,验证系统在低资源环境下的稳定性、OOM(内存不足)处理机制,以及应用程序的容错能力,是排查内存泄漏、资源争用、系统崩溃等问题的关键工具

Sysinternals Live 在线运行 Testlimit.exe

Testlimit 的核心功能是通过模拟内存、句柄、进程 / 线程、桌面堆 / GDI 等各类系统资源的耗尽状态,来测试目标应用程序在极端情况下的响应行为。这使得开发者能够在可控的环境中复现和诊断程序在资源不足时可能出现的异常问题

用法

Testlimit 的基本语法格式为:

1
Testlimit [[-h [-u]] | [-p [-n]] | [-t [-n [KB]]] | [-u [-i]] | [-g [object size]] | [-a|-d|-l|-m|-r|-s|-v [MB]] | [-w]] [-c [count]] [-e [seconds]]
  • 内存相关参数:
    • -a:泄漏地址窗口化扩展(AWE)内存,单位为 MB,默认值为 1
    • -d:泄漏并接触指定 MB 数的内存,默认值为 1
    • -m:泄漏指定 MB 数的内存,默认值为 1
    • -r:保留指定 MB 数的内存,默认值为 1
    • -s:泄漏指定 MB 数的共享内存,默认值为 1
    • -v:锁定指定 MB 数的虚拟内存,默认值为 1
  • 句柄相关参数:
    • -h:创建句柄,可通过添加 -u 参数同时分配文件对象
    • -g:创建指定大小的 GDI 句柄,默认大小为 1 字节。当指定大小为 0 时,会导致 GDI 对象耗尽
    • -u:创建用户菜单句柄
  • 进程 / 线程相关参数:
    • -p:创建进程,可添加 -n 参数设置最小工作集
    • -t:创建线程,可添加 -n 参数指定最小堆栈保留大小(单位为 KB)
  • 特殊参数:
    • -i:耗尽用户桌面堆
    • -l:分配指定数量的大页面(会自动舍入为大页面大小的倍数)
    • -w:将工作集最小值重置为最高可能值
    • -c:要分配的对象数量,默认为尽可能多。此参数必须是最后一个指定的选项
    • -e:两次分配之间的间隔秒数,默认值为 0

详解如下👇🏻

  • 内存相关参数(最常用)

    参数格式 作用说明 示例 注意事项
    -m <数值> 分配指定 MB 内存(不释放);<数值=-1> 持续分配直到耗尽 TestLimit64.exe -m 8192(分配 8GB)
    TestLimit64.exe -m -1(极限耗尽)
    -1 会导致系统卡顿 / 蓝屏,仅测试环境用
    -r 分配内存后随机读写(模拟真实内存使用场景) TestLimit64.exe -m 4096 -r 更贴近实际程序的内存占用特征
    -c 用 Copy-on-Write(写时复制)方式分配内存 TestLimit64.exe -m 2048 -c 占用物理内存更少,主要消耗虚拟内存
    -d 分配内存后立即释放(模拟内存波动) TestLimit64.exe -m 1024 -d 测试系统内存回收机制
    -l <MB数> 分配并锁定物理内存(不允许换页到磁盘) TestLimit64.exe -l 512 直接占用物理内存,对系统压力更大
    -v 分配虚拟内存(仅占用地址空间,不占物理内存) TestLimit64.exe -v 16384 测试虚拟地址空间耗尽场景
  • 句柄相关参数

    句柄是 Windows 访问文件 / 注册表 / 进程等对象的标识,耗尽后程序无法创建新对象。

    参数格式 作用说明 示例
    -h <数值> 创建指定数量句柄(默认事件句柄);<数值=-1> 持续创建直到耗尽 TestLimit64.exe -h 100000(10 万个句柄)
    TestLimit64.exe -h -1(极限耗尽)
    -t <类型> 指定句柄类型:
    - e = 事件句柄(默认)
    - f = 文件句柄
    - m = 互斥体句柄
    - s = 信号量句柄
    TestLimit64.exe -h 50000 -t f(5 万个文件句柄)
    -n 创建命名句柄(而非匿名句柄) TestLimit64.exe -h 20000 -t e -n
    模拟命名对象句柄泄漏场景
  • 进程 / 线程相关参数

    参数格式 作用说明 示例 注意事项
    -p <数值> 创建指定数量子进程;<数值=-1> 持续创建直到系统上限 TestLimit64.exe -p 500(500 个子进程) 子进程过多会导致任务管理器卡顿
    -t <数值> 创建指定数量线程(与句柄类型参数重名,需结合上下文) TestLimit64.exe -t 1000(1000 个线程) 线程数建议不超过 CPU 逻辑核心数 ×20
    -s <数值> 设置线程栈大小(KB) TestLimit64.exe -t 500 -s 1024(设置线程栈大小为 1024KB) 栈越大,单线程占用内存越多
  • 其他资源耗尽参数(进阶)

    参数格式 作用说明 示例 适用场景
    -u 耗尽桌面堆(Desktop Heap) TestLimit64.exe -u 测试桌面程序(如 Explorer)在堆不足时的表现
    -g <数值> 耗尽 GDI 对象(绘图相关) TestLimit64.exe -g 10000 排查桌面程序 GDI 泄漏导致的卡顿 / 崩溃
    -w <数值> 耗尽 USER 对象(窗口 / 菜单相关) TestLimit64.exe -w 5000 测试 GUI 程序在 USER 对象不足时的容错性
    -a 耗尽 ATOM 表(系统字符串表) TestLimit64.exe -a 模拟老旧程序 ATOM 表溢出问题
  • 通用辅助参数

    参数格式 作用说明 示例
    -k 执行资源耗尽后不退出,保持占用 TestLimit64.exe -m 2048 -k
    -q 静默模式(无控制台输出) TestLimit64.exe -h 80000 -q
    -? 查看所有参数帮助 TestLimit64.exe -?
VMMap

VMMap 是微软 Sysinternals 套件 核心工具之一,由 Mark Russinovich 开发,是 Windows 平台专属的进程虚拟地址空间(VAS)专业分析工具。它能以可视化、精细化的粒度,拆解进程内存的分配类型、状态、权限、占用详情与地址分布,是内存泄漏排查、恶意代码检测、内存异常排障、性能优化的核心利器,粒度和专业性远超任务管理器、资源监视器

  • 支持环境:Windows 7/Server 2008 R2 及以上,兼容 32/64 位进程与系统
  • 权限要求:普通权限仅可查看当前用户进程;管理员权限可查看系统进程、获取完整内核态内存信息,是完整使用功能的前提
  • 核心优势:静态快照 + 差异对比、可视化地址空间布局、内存段级别的全维度详情、内置字符串扫描,兼顾易用性与专业深度

核心术语

Windows 内存体系里,先分清 2 个核心维度,所有列都是围绕这两个维度展开的:

  1. 虚拟地址空间:每个进程独享的「内存地址账本」,64 位进程有超大的地址范围,只是「地址编号」,不代表真的占了内存条。就像你租了一个超大商场,拿到了整个场地的门牌号,不代表你把整个商场都装满了东西
  2. 物理内存 / 提交内存
    • 提交内存:系统给进程「承诺可用」的内存,要么在内存条里,要么在硬盘的虚拟内存页文件里,是真正分配出去的内存
    • 工作集(WS=Working Set)当前实实在在占用你内存条的物理内存,就是你平时看任务管理器里「程序占了多少内存」的核心指标
  3. 私有 / 共享
    • 私有:只有当前这个进程能用,完全独占,其他进程碰不到
    • 共享:可以给多个进程共用(比如系统 DLL,100 个进程加载,内存条里只存 1 份)
术语 核心含义
虚拟地址空间(VAS) 进程可访问的地址范围,32 位进程用户态默认 2GB,64 位进程用户态默认 8TB,不等于物理内存
保留(Reserved) 进程向系统预订的地址范围,不会被其他分配占用,但未分配物理内存 / 页文件,无法直接访问
提交(Committed) 系统为地址分配了实际内存资源(物理内存 / 页文件),进程可直接读写,是系统「提交限制」的统计对象
私有内存(Private) 仅当前进程可访问的独占内存,不会被其他进程共享,如进程堆、线程栈、私有数据段
可共享内存(Shareable) 支持多进程共享的内存段,如文件映射、匿名共享内存,即使当前未被共享也会标记为此类
共享内存(Shared) 当前已被至少 2 个进程映射的可共享内存,如系统 DLL 的代码段
工作集(WS) 当前驻留在物理内存中的内存页面,分为私有工作集、共享工作集,任务管理器的「内存(专用工作集)」对应私有 WS
保护属性(Protection) 内存页的访问权限,如只读、读写、可执行等,是恶意代码检测的核心指标

界面

image-20260305151553443

  • 顶部标题栏与进程信息

    • VMMap - Sysinternals:工具名称与来源(Sysinternals 是微软旗下的 Windows 系统工具集)
    • Process: PowerToys.exe:当前分析的进程名
    • PID: 2712:进程 ID(唯一标识)
  • 顶部内存摘要条形图(核心概览)

    • Committed:已提交的虚拟内存总量(已分配并承诺给进程的内存)
    • Private Bytes:进程私有的、不可与其他进程共享的内存(核心泄漏关注对象)
    • Working Set:当前物理内存中驻留的部分(实际占用的物理内存)
  • 内存类型汇总表(上半部分表格)

    VMMap 内存类型 界面颜色标注 核心说明 排查重点
    Total(汇总行) 蓝色行 进程虚拟地址空间所有内存类型的统计总和,是进程完整地址空间占用的全局概览 整体内存增长趋势,对比不同时间点的总提交内存、私有字节变化,定位全量内存泄漏
    Free 白色行 进程虚拟地址空间中未被保留、未被分配的空闲区域,可被后续内存分配请求直接使用 最大连续空闲块大小,决定进程能否分配大内存;32 位进程需重点关注空闲空间是否被碎片化耗尽
    Image 紫色行 可执行 PE 文件的内存映射,包括进程自身 EXE、加载的系统 / 第三方 DLL,包含代码段、只读数据段,默认支持进程间共享、带执行权限 无数字签名的异常 DLL、临时目录 / 非系统路径的恶意映像、保护属性异常(可写 + 可执行)的风险代码段
    Heap 橙色行 用户态堆内存,包括进程默认堆、自定义私有堆,是 C/C++ malloc/new、原生程序动态内存分配的核心区域 绝大多数用户态原生内存泄漏都发生在此类,是快照对比、内存泄漏追踪的核心关注项,重点监控私有工作集的持续无上限增长
    Managed Heap 绿色行 .NET 运行时管理的托管堆内存,用于 .NET 程序的托管对象分配,由 GC(垃圾回收器)负责自动回收 GC 无法回收的托管内存泄漏(如未释放的事件订阅、静态对象强引用、大对象堆 LOH 碎片化)
    Mapped File 浅蓝行 非可执行文件的内存映射(如文档、资源、配置文件、系统数据文件),与 Image 的核心区别是默认无执行权限 大文件映射后未释放、异常 / 非授权路径的映射文件、映射内存持续增长不释放的泄漏问题
    Page Table 粉色行 内核态页表内存,用于管理该进程虚拟地址与物理内存地址的映射关系,用户态无法直接访问和修改 页表占用过高,通常伴随进程虚拟地址空间过度碎片化、大量小内存块分配后不释放
    Private Data 黄色行 进程独占的私有数据内存,不可与其他进程共享,包含线程栈(Thread Stack)、线程环境块 TEB、进程环境块 PEB、静态数据段等 线程栈溢出、单线程栈提交内存过大(递归过深 / 栈上大对象)、静态数据持续增长、未释放的私有数据段
    Shareable 浅浅蓝行 非文件映射的可共享内存段,通常由 CreateFileMapping 创建的匿名 / 命名共享内存,支持跨进程访问 跨进程异常共享、带执行权限的匿名共享段、共享内存句柄未关闭导致的泄漏
    Unusable 灰色行 不可用内存碎片,虚拟地址空间中因内存对齐、区域间隙产生的小于 64KB 的空闲块(Windows 无法分配使用) 32 位进程地址空间碎片化的核心指标,过高会导致可用地址空间提前耗尽,无法分配新内存

    列标题说明

    列名 理解 专业说明 核心排查用途
    Type 内存块的「用途分类」,标注这块内存是用来干嘛的(比如放代码、放动态数据) VMMap 按 Windows 内存机制,对进程虚拟地址空间按用途做的标准化分类,是所有统计的维度 快速定位内存问题根源,比如 Heap 数值异常大概率是动态内存泄漏
    Size 该类型在进程「虚拟地址账本」里占的总地址范围,不管有没有真的分配实际内存 包含「已提交 + 已保留」的总虚拟地址空间大小,仅占用地址编号,不代表占用物理存储 查看地址空间整体占用,判断 Unusable 碎片化、Free 空闲空间是否充足
    Committed 该类型里,系统已经给进程实实在在分配好、可直接读写的内存总量 Windows 内存管理器已确认分配的内存,会占用物理内存或硬盘页文件空间,是进程真实分配的内存总量 内存泄漏核心排查指标之一,数值持续只涨不回落,必存在内存泄漏
    Private 该类型里,完全属于当前进程、仅它能访问、绝对无法和其他进程共享的私有内存总量 也叫 Private Bytes(专用字节数),包含堆、栈、私有数据段,是进程独占的提交内存 排查用户态内存泄漏最核心、最精准的指标,仅受进程自身内存申请 / 释放影响
    Total WS 该类型里,当前实实在在占用电脑内存条的物理内存总大小 全称 Total Working Set(总工作集),是当前驻留在物理内存中的内存页,不包含被换出到硬盘的内存 查看程序实际物理内存占用,判断是否因内存占用过高导致系统卡顿
    Private WS 总工作集里,仅当前进程能用的、独占的物理内存大小 全称 Private Working Set(专用工作集),是物理内存中进程独占的内存页,不会和其他进程共享 最能反映进程本身真实的物理内存占用,数值持续上涨大概率存在私有内存泄漏
    Shareable WS 总工作集里,系统允许被其他进程共享的物理内存大小 全称 Shareable Working Set(可共享工作集),物理内存中标记为可共享的内存页,最常见为系统 DLL 代码段 区分进程真实占用与共享内存占比,数值过大说明进程加载了大量共享 DLL,自身占用不高
    Shared WS 可共享工作集里,当前真的有其他进程在共用的物理内存大小 全称 Shared Working Set(已共享工作集),可共享内存中,当前实际被至少 2 个进程同时使用的内存页 查看共享内存的实际复用率,数值越接近 Shareable WS,共享内存利用率越高
    Locked WS 工作集里,被进程强制锁死在内存条里、永远不会被系统换到硬盘的内存大小 全称 Locked Working Set(锁定工作集),通过 API 锁定的内存页,必须常驻物理内存,不会被系统换页 排查异常物理内存锁定,数值过大会导致系统可用内存减少、整机卡顿
    Blocks 该类型的内存,一共被分成了多少个独立、不连续的小内存块 每个连续的虚拟地址范围为一个内存块,Blocks 即该类型下不连续的内存段总数 核心排查内存碎片化,Blocks 数量越多,代表内存被切割得越碎,碎片化越严重
    Largest 该类型的内存里,最大的那一个连续、无隔断的内存块的大小 该类型下,最大的连续虚拟地址范围的大小,是判断进程能否申请大内存的核心指标 查看 Free 类型的 Largest,判断地址空间碎片化是否会导致大内存申请失败
  • 详细内存区域表(下半部分表格)

    颜色同上

    列名 含义
    Address 内存区域的起始虚拟地址
    Type 区域类型(同汇总表)
    Size 该区域大小
    Committed 已提交大小
    Private 是否私有(是则显示大小)
    Total WS/Private WS/Shareable WS/Shared WS/Locked WS 同汇总表的工作集细分
    Blocks 该区域内的内存块数
    Protection 内存保护属性(如 Read/Write 可读可写、Execute/Read 可读可执行等)
    Details 额外细节(如模块名、堆 ID、线程 ID 等)
  • 底部功能按钮

    • Timeline…:打开时间线视图,记录内存随时间的变化(用于追踪泄漏趋势)
    • Heap Allocations…:堆分配跟踪,查看具体堆分配调用栈
    • Call Tree…:调用树视图,关联内存分配到具体函数调用
    • Trace…:启动内存跟踪,记录分配 / 释放事件

用法和操作指南

典型使用场景

  • 业务应用内存泄漏排查:定位服务端程序、客户端软件长时间运行内存持续增长的根因。
  • 恶意代码应急响应:排查进程是否被注入 DLL、shellcode,定位恶意内存区域,溯源攻击行为。
  • 程序崩溃排障:解决「内存不足」报错但系统内存充足的问题,定位地址空间碎片化、提交限制不足等根因。
  • 应用内存优化:分析进程内存分布,优化大内存分配、减少不必要的 DLL 加载、降低内存占用。
  • 驱动 / 内核内存排障:排查进程关联的分页池 / 非分页池泄漏,定位驱动异常问题。
  • 安全审计:扫描进程内存中的明文敏感数据,排查数据泄露风险。

内存泄漏排查(最核心场景)

VMMap 是 Windows 平台用户态内存泄漏排查的首选工具,核心是快照对比法,操作步骤:

  1. 以管理员身份启动 VMMap,打开目标进程,待进程稳定后,点击 File -> Save 保存基准快照(.mmp 格式)。
  2. 复现内存泄漏场景(如循环执行业务操作、长时间运行程序),触发内存增长。
  3. 点击 File -> Compare with Saved,选择之前保存的基准快照。
  4. 查看对比结果:VMMap 会按类型汇总内存增量,详情面板高亮新增 / 增长的内存块,精准定位泄漏发生在哪个堆、哪个模块、哪段地址。
  5. 配合 WinDbg、调试器,针对泄漏的堆 ID、地址范围,进一步定位泄漏的代码位置。

恶意代码 / 进程注入检测

VMMap 是应急响应中排查进程注入的利器,核心排查点:

  • 保护属性异常:重点关注 Private/Shareable 类型的内存,带有 PAGE_EXECUTE_READWRITE(RWX)权限,正常程序的可执行代码均为 RX(只读可执行),不会同时开放写权限。
  • 保护属性被篡改Allocation Protection 与当前 Protection 不一致,典型注入流程为:分配 RW 内存→写入 shellcode→修改为 RX 执行。
  • 无文件映射的可执行内存:可执行内存无对应的 PE 文件路径(非 Image 类型),属于无文件注入的特征。
  • 异常映像文件:Image 类型的 DLL,路径位于临时目录、用户目录,无微软数字签名,或文件名随机,大概率是恶意 DLL 注入。
  • 异常堆 / 栈内存:堆 / 栈内存中出现可执行权限,属于异常行为。

地址空间碎片化排查

32 位进程极易出现「系统总内存充足,但进程无法分配大内存」的问题,根源是地址空间碎片化:

  1. 顶部条形图可直观看到空闲内存块的分布,识别是否存在大量小空闲块、大连续空闲块缺失。
  2. 详情面板筛选 Free 类型,按大小排序,查看最大连续空闲块的大小。
  3. 筛选 Unusable 类型,查看不可用间隙的总大小,定位碎片化的核心来源。
  4. 结合 Image 类型的 DLL 加载地址,排查是否因 DLL 基址冲突导致地址空间被切割。

线程栈与托管内存分析

  • 线程栈排查:筛选 Stack 类型,Details 列可看到对应线程 ID(TID),查看每个线程栈的提交大小。若单线程栈提交量远超 1MB,大概率是递归过深、栈上分配大对象,存在栈溢出风险。
  • .NET 托管内存分析:.NET 的 GC 托管堆属于 Heap 类型,通过快照对比可定位托管堆的增长,配合 PerfView、SOS 调试扩展,可进一步定位托管内存泄漏、GC 堆碎片化问题。

命令行用法

VMMap 支持命令行操作,适合自动化脚本、批量采集、无界面场景,核心语法:

1
vmmap.exe [参数] [进程PID/名称] [输出文件]
参数 用途说明
-accepteula 自动接受用户许可协议,无需弹窗,自动化必备
-p [PID] 指定要分析的进程 PID
-o [文件路径] 将分析结果输出为 CSV 文件,便于后续批量分析
-launch [程序路径] [启动参数] 启动指定程序并全程追踪其内存分配
1
2
#指定ip直接抓取内存快照
vmmap64 -accepteula -p 78452 D:\MemSnap\test_snap.mmp

下面一个自动内存快照脚本

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# ====================== 配置区(只改这里)======================
$processName = "IonImplantationSystem" # 目标进程名
$savePath = "D:\MemSnap" # 快照保存路径
$vmmapExeName = "vmmap64.exe" # VMMap程序名(已加系统路径)
$interval = 3600 # 快照间隔(秒),60分钟=3600秒
$waitAfterRun = 5 # 延长等待时间至5秒(适配大进程)
# ===============================================================

# 前置检查1:验证是否以管理员身份运行
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "❌ 错误:请以管理员身份运行此脚本!" -ForegroundColor Red
pause
exit 1
}

# 前置检查2:动态检测vmmap64.exe是否在系统路径中
try {
$vmmapPath = (Get-Command -Name $vmmapExeName -ErrorAction Stop).Source
Write-Host "✅ 找到VMMap程序:$vmmapPath`n" -ForegroundColor Green
} catch {
Write-Host "❌ 错误:未在系统路径中找到 $vmmapExeName!" -ForegroundColor Red
Write-Host "请确认:1. 已下载VMMap并解压 2. 所在文件夹已加入系统环境变量 3. 重启过PowerShell" -ForegroundColor Yellow
pause
exit 1
}

# 前置检查3:测试保存路径写入权限
$testFile = Join-Path $savePath "test_permission.txt"
try {
New-Item -Path $testFile -ItemType File -Force | Out-Null
Remove-Item -Path $testFile -Force | Out-Null
Write-Host "✅ 保存路径可写:$savePath`n" -ForegroundColor Green
} catch {
Write-Host "❌ 保存路径无写入权限:$savePath" -ForegroundColor Red
Write-Host "请检查文件夹权限,或更换保存路径(如 C:\Temp\MemSnap)" -ForegroundColor Yellow
pause
exit 1
}

# 创建保存目录(确保存在)
New-Item -ItemType Directory -Path $savePath -Force | Out-Null

Write-Host "===== 进程内存监控开始 =====`n" -ForegroundColor Green
Write-Host "监控进程: $processName"
Write-Host "保存路径: $savePath"
Write-Host "快照间隔: $interval 秒`n"

# 循环监控并生成快照
while ($true) {
$currentTime = Get-Date -Format 'HH:mm:ss'
$proc = Get-Process -Name $processName -ErrorAction SilentlyContinue

if ($null -eq $proc -or $proc.Count -eq 0) {
Write-Host "[$currentTime] 未找到进程: $processName`n" -ForegroundColor Yellow
} else {
# 用自定义变量名,避免覆盖PowerShell内置只读变量$pid
$targetPID = $proc[0].Id
$timeStamp = Get-Date -Format "yyyyMMdd_HHmmss"
$outFile = Join-Path $savePath "snap_$processName_$timeStamp.pid$targetPID.mmp"

try {
Write-Host "[$currentTime] 抓取目标进程 PID $targetPID 快照..." -ForegroundColor Cyan
Write-Host "[$currentTime] 目标保存路径:$outFile" -ForegroundColor Gray

# 执行验证通过的VMMap指令
& $vmmapExeName -accepteula -p $targetPID $outFile

# 关键1:延长等待时间,确保VMMap完全写入文件
Start-Sleep -Seconds $waitAfterRun

# 关键2:强制刷新保存目录的文件列表(解决缓存问题)
Get-ChildItem -Path $savePath -Force | Out-Null

# 验证文件:分步骤排查,增加容错
$fileExists = $false
$fileSize = 0
# 先检查文件是否存在(忽略大小写/缓存)
if (Test-Path -Path $outFile -PathType Leaf -ErrorAction SilentlyContinue) {
$fileExists = $true
# 关键3:重试获取文件大小(最多3次,解决临时获取失败)
for ($i=1; $i -le 3; $i++) {
try {
$fileInfo = Get-Item -Path $outFile -Force -ErrorAction Stop
$fileSize = $fileInfo.Length
if ($fileSize -gt 0) { break } # 获取到有效大小则退出重试
} catch {
Start-Sleep -Seconds 1 # 重试前等待1秒
}
}
}

# 最终判定:只要文件存在,即使大小检测失败也判定为成功(兜底)
if ($fileExists) {
if ($fileSize -gt 0) {
Write-Host "[$currentTime] ✅ 快照保存成功!文件大小:$([math]::Round($fileSize / 1KB, 2)) KB`n" -ForegroundColor Green
} else {
Write-Host "[$currentTime] ✅ 快照保存成功!(文件存在但大小检测异常,实际已生成)`n" -ForegroundColor Green
}
} else {
Write-Host "[$currentTime] ❌ 快照保存失败!" -ForegroundColor Red
Write-Host "[$currentTime] 调试信息:文件存在=$fileExists,文件大小=$fileSize 字节,退出码=$LASTEXITCODE`n" -ForegroundColor DarkYellow
}
} catch {
Write-Host "[$currentTime] ❌ 执行VMMap出错:$($_.Exception.Message)`n" -ForegroundColor Red
}
}

# 等待下一次快照的明确标识
if ($interval -ge 3600) {
$waitDesc = "$([math]::Round($interval / 3600, 1)) 小时"
} else {
$waitDesc = "$([math]::Round($interval / 60, 1)) 分钟"
}
$waitTime = Get-Date -Format 'HH:mm:ss'
Write-Host "[$waitTime] 开始等待下一次快照采集!" -ForegroundColor Blue
Write-Host "[$waitTime] 间隔时长:$waitDesc(原始秒数:$interval 秒)" -ForegroundColor Gray
Write-Host "[$waitTime] 提示:脚本将在等待结束后自动执行下一次快照,请勿关闭此窗口`n" -ForegroundColor Gray

Start-Sleep -Seconds $interval
}

pause

安全和管理工具

完整名称 类型 功能 使用说明
Autoruns GUI 系统启动项管理
autorunsc为命令行版本
双击运行,查看 Everything 标签,所有启动项;Verify 验证签名
Sysmon CLI 系统监控服务 sysmon -i 安装;sysmon -c config.xml 应用配置;事件查看器查看日志
AccessChk CLI 检查安全权限 accesschk -c -s c:\ 检查系统目录权限;accesschk -d dir 显示有效权限
AccessEnum GUI 文件系统权限枚举 双击运行,扫描目录显示权限过宽的位置
ShareEnum GUI 网络共享枚举 双击运行,扫描网络共享及权限
Sigcheck CLI 文件签名验证 sigcheck -e -vt file.exe 检查签名和 VirusTotal;sigcheck -s -e c:\dir 递归扫描
ShellRunas GUI 以其他用户身份运行 右键菜单集成,指定凭据运行程序
ADExplorer GUI Active Directory 查看器 双击运行,连接 AD 域,浏览编辑 AD 对象
ADInsight GUI LDAP 实时监控 双击运行,实时显示 LDAP API 调用和操作
ADRestore CLI 恢复已删除的 AD 对象 adrestore -r 预览可恢复对象;adrestore 交互式恢复
Autoruns

Autoruns 是 Windows 启动项管理的终极工具,能可视化所有自动启动入口(含任务管理器看不到的内核 / 服务 / 驱动级项),支持禁用 / 删除 / 校验签名 / 对比基线,适合系统优化与问题排查

必须以管理员身份运行(右键→以管理员身份运行),否则无法查看 / 修改系统级启动项

核心标签页功能(按常用度排序)

标签页 核心内容 典型用途
Everything 所有启动项汇总 全局概览,快速定位异常项
Logon 用户登录时启动的程序(含启动文件夹、注册表 Run 键) 最常见的开机自启项管理
Services Windows 服务(含驱动服务) 禁用冗余服务,优化启动速度
Scheduled Tasks 计划任务中的自动触发项 清理隐藏的定时启动任务
Drivers 内核驱动程序启动项 排查驱动相关问题,禁用不明驱动
Explorer 资源管理器扩展(如右键菜单、工具栏) 解决资源管理器卡顿问题
Internet Explorer/Chrome 浏览器插件与扩展 清理恶意浏览器插件
AppInit DLLs 系统级 DLL 注入项 排查 DLL 劫持等安全问题

列表字段说明

  • 勾选框:控制是否启用该启动项
  • 名称:启动项标识
  • 发布者:程序签名信息(无签名 / 黄色高亮可能为可疑项)
  • 路径:启动项对应的文件位置
  • 描述:程序功能说明
  • 状态:文件是否存在(黄色表示文件缺失)

用法说明

禁用启动项: 取消勾选左侧复选框(启用则重新勾选)

删除启动项(谨慎使用,不可逆): 右键目标条目→选择Delete 👈🏻确认无用且需彻底清理的残留项(如已卸载软件的残留启动项)

隐藏微软官方项(快速定位第三方软件)

  • 菜单→Options→Hide Microsoft Entries(快捷键 Ctrl+M)
  • 效果:只显示非微软签名的启动项,减少干扰项

验证数字签名(识别可信程序)

  • 菜单→Options→Verify Code Signatures(快捷键 Ctrl+V)
  • 效果:无有效签名的程序会显示为红色,警惕此类启动项

优化开机速度(针对 Logon 和 Services 标签)

  1. 切换到Logon标签,禁用非必要的用户级自启程序(如视频播放器、聊天软件自动启动)
  2. 切换到Services标签,对非关键服务:右键→Properties→启动类型改为手动禁用
  3. 注意:保留杀毒软件、驱动程序、系统关键服务(如 Windows Installer、WLAN AutoConfig)
Sysmon

Sysmon = System Monitor,是微软 Sysinternals 套件里的系统级行为监控 / 审计神器,免费、轻量、装完就后台常驻,专门用来详细记录 Windows 到底发生了什么 即把系统里所有敏感操作,原原本本记进 Windows 事件日志

系统自带日志:只告诉你 “发生了什么结果”(如:进程启动了、服务运行了)

Sysmon:告诉你 “谁干的、用什么命令干的、父进程是谁、连了哪个 IP、改了哪个文件 / 注册表”

Sysmon 主要监控什么(最实用)

  1. 进程创建 / 退出(完整命令行)
  2. 进程外连网络(哪个程序、连哪个 IP / 端口)
  3. 文件创建、修改、删除
  4. 注册表关键项修改
  5. DLL 注入、驱动加载
  6. 计划任务、登录等系统行为

使用方式

1
2
3
4
5
6
7
8
Sysmon64.exe -i -accepteula

#-i:安装
#-accepteula:自动同意协议
#全程无弹窗、后台静默运行

Sysmon64.exe -u
#不想用了一键卸载

查看记录: 事件查看器 →Applications and Services Logs →Microsoft → Windows → **Sysmon → Operational

磁盘和文件系统工具

工具 类型 功能 使用说明
Disk2vhd GUI 物理磁盘转VHD虚拟磁盘 双击运行,选择磁盘/卷生成VHD,可在线转换
SDelete CLI 安全删除文件 sdelete -p 3 file.txt 三次覆写;sdelete -z C: 清理空闲空间
Contig CLI 磁盘碎片整理 contig -v filename 分析碎片;contig -a filename 整理单个文件
DiskMon GUI 磁盘活动监视 双击运行,Capture切换开始/停止,类似磁盘指示灯
DiskView GUI 图形化磁盘扇区查看 双击运行,可视化显示磁盘使用情况
**Disk Usage **
du.exe
CLI 磁盘使用分析 du -c -s c:\dir 显示目录总大小;du -l 1 -c c:\dir 递归显示
Junction CLI 创建NTFS符号链接 junction dir junction_dir 创建目录联接点
Streams CLI NTFS备用数据流管理 streams -s -d c:\dir 扫描并删除所有数据流
Cacheset GUI 文件系统缓存控制 双击运行,可调整缓存工作集大小
MoveFile CLI 安排启动时文件操作 movefile oldfile newfile 移动;movefile file "" 删除
PendMoves CLI 列出计划的文件操作 pendmoves 显示启动时待执行的文件操作
SDelete

SDelete(Secure Delete)是微软旗下 Sysinternals 团队开发的Windows 平台命令行安全删除工具,核心能力是通过数据覆盖实现文件的不可逆删除,解决 Windows 系统常规删除仅清除文件索引、原始数据可被恢复的安全隐患,其符合美国国防部 DOD 5220.22-M 数据清除标准,是 Windows 环境下敏感数据安全擦除的官方合规工具。

  • 适用系统:Windows 10 及以上客户端、Windows Server 2012 及以上服务器、Nano Server 2016 及以上
  • 核心特性:无图形界面,纯命令行操作;兼容 NTFS、FAT 文件系统;支持对压缩、加密、稀疏文件的安全处理;可对逻辑卷 / 物理磁盘的空闲空间做安全清理。

基础语法

1
2
3
4
5
6
# 文件/目录安全删除
sdelete [-p passes] [-r] [-s] [-q] [-f] <file or directory [...]>
# 逻辑卷空闲空间清理
sdelete [-p passes] [-q] [-z|-c] <drive letter [...]>
# 物理磁盘空闲空间清理
sdelete [-p passes] [-q] [-z|-c] <physical disk number [...]>

全参数说明

参数 核心作用 使用说明
-p N 指定覆盖次数 默认 1 次覆盖,N 为自定义的覆盖遍数,数值越高安全性越强,耗时也越长,涉密场景常用 3 次
-r 移除只读属性 针对带只读保护的文件,自动解除只读属性后执行安全删除
-s 递归子目录 对目标目录及其所有子目录下的文件执行递归安全删除
-q 静默模式 无交互输出,适合批处理脚本、计划任务自动化执行
-f 强制参数识别 强制将仅含字母的参数判定为文件 / 目录,而非磁盘盘符
-c 随机数据清理空闲空间 用随机数覆盖磁盘未分配空间,优先用于数据安全防护场景
-z 零值清理空闲空间 用 0 填充磁盘未分配空间,不提升数据删除安全性,适合虚拟磁盘压缩、镜像优化
-nobanner 隐藏启动横幅 不显示工具版权、版本信息,精简输出内容

示例

1
2
3
4
5
6
7
8
9
10
11
#单文件安全删除,3 次覆盖
sdelete -p 3 C:\Users\Desktop\敏感文件.docx

#目录树递归安全删除,自动处理只读文件
sdelete -r -s C:\Users\Desktop\敏感目录

#清理 C 盘空闲空间,2 次随机数据覆盖
sdelete -c -p 2 C:

#对 D 盘空闲空间零值填充,优化虚拟磁盘体积
sdelete -z D:

网络工具

工具 类型 功能 使用说明
TCPView GUI 实时 TCP/UDP 连接显示 双击运行,绿色=新建连接,红色=关闭,鼠标右键结束连接
PsPing CLI 网络延迟/带宽测试 psping -t hostname:80 持续 Ping;psping -b -n 10 hostname 带宽测试
TCPvCon CLI TCPView 命令行版 tcpvcon -a 显示所有连接;tcpvcon -c CSV 格式输出

PsTools-远程管理套件(核心)

PsTools是Sysinternals最著名的套件,专门用于远程系统管理。所有工具都是CLI

PsTools 也可以本机用,本机就是增强版系统命令集,用来查进程、杀进程、提权、看信息,比系统自带的强得多

工具 功能 使用说明
PsExec 远程执行程序 psexec \computername -u domain\user cmd 远程执行cmd
psexec \computername -d app.exe 运行并返回PID
PsService 服务查看和控制 psservice \computername query 查询服务
psservice \computername stop servicename 停止服务
PsKill 远程进程终止 pskill \computername pid 按PID终止
pskill \computername notepad 按名称终止
PsSuspend 远程进程挂起 pssuspend \computername pid 挂起进程
pssuspend -r \computername pid 恢复进程
PsShutdown 远程关机/重启 psshutdown -s -t 60 60秒后关机
psshutdown -r -t 0 -m "重启" 立即重启
PsFile 显示远程打开的文件 psfile 列出本地远程打开的文件
psfile -c \computername id 关闭远程文件
PsInfo 获取系统信息 psinfo -s -h -d \computername 显示系统信息、补丁、磁盘信息
PsList 列出进程 pslist -t \computername 显示进程树
pslist -m \computername 按内存排序
PsLogList 查看事件日志 psloglist -s \computername application 显示应用日志
psloglist -c -n 10 \computername 清空并显示最近10条
PsPasswd 修改密码 pspasswd \computername admin newpassword 远程修改密码
PsLoggedOn 显示登录用户 psloggedon -l \computername 仅本地登录
psloggedon \computername 所有登录用户
PsGetsid 显示SID psgetsid \computername 显示计算机SID
psgetsid -u username \computername 显示用户SID
PsPing 网络延迟/带宽测试 psping -n 10 -w 2 hostname 10次Ping测试
psping -b -l 1000 -n 100 hostname 带宽测试

目标主机要提前开什么(才能用)

  1. 开启默认管理共享C$ADMIN$(专业版默认有,家庭版不支持)

  2. 防火墙放行:文件和打印机共享(开放 445 端口)

  3. 必须启动服务:

    • Remote Registry(远程注册表)
    • RPC 服务(默认已开)
  4. 账号:必须用管理员账号密码不能为空

  5. 关闭远程 UAC 限制(必改,否则权限不够):

    注册表项:

    1
    2
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
    新建 DWORD:LocalAccountTokenFilterPolicy = 1

演示和生产力工具

工具 类型 功能 使用说明
ZoomIt GUI 屏幕缩放和标注 运行后使用 Ctrl+1 放大,Ctrl+2 绘图,Ctrl+3 倒计时,Ctrl+4 白板
BgInfo GUI/CLI 系统信息桌面背景 双击运行,点击 Configure 选择显示信息,点击 Apply 应用
RDCMan GUI 远程桌面连接管理器 双击运行,File → New 创建连接组,支持凭据继承
Desktops GUI 虚拟桌面工具 双击运行,通过托盘图标切换 4 个虚拟桌面
Autologon GUI 配置自动登录 双击运行,设置登录凭据,让 Windows 开机自动登录、不用输密码的小工具
BgInfo

BgInfo 是微软 Sysinternals 套件中的轻量级桌面信息显示工具,核心价值是将系统关键信息直接叠加到桌面壁纸

核心原理:读取 WMI / 注册表 / 环境变量 → 渲染文本到壁纸 → 设置为桌面背景 → 立即退出(非后台驻留)

可显示的关键信息(可自定义)

类别 典型信息
系统标识 计算机名、域名、登录用户、OS 版本 / 架构 / 更新号
网络配置 IPv4/IPv6 地址、MAC、子网掩码、网关、DNS
硬件状态 CPU 型号 / 核心数、内存容量 / 使用率、磁盘分区 / 空间
运行状态 系统启动时间、服务状态、进程数、屏幕分辨率
自定义内容 支持脚本输出、环境变量、注册表值,甚至添加公司 Logo

加载自定义配置文件刷新命令:

1
2
3
4
# 示例:加载 D:\Configs\MyBgInfo.bgi 配置并立即静默刷新(无任何界面 / 弹窗)
#适合放在开机启动项、计划任务中,全程无感知刷新:
BgInfo64.exe "D:\Configs\MyBgInfo.bgi" /timer:0 /silent
#/rt 覆盖模式,不修改原始壁纸文件,改用绘制文字显示在壁纸上方,性能占用更低,重启设备后不会保留

系统信息工具(CLI)

完整名称 工具名 类型 功能 使用说明
Coreinfo coreinfo.exe CLI CPU和缓存拓扑信息 coreinfo -c 逻辑CPU数;coreinfo -v 虚拟化特性
Whois whois.exe CLI 域名注册信息查询 whois microsoft.com 查询域名注册信息
ClockRes clockres.exe CLI 系统时钟分辨率 clockres 显示时钟分辨率
Hex2dec hex2dec.exe CLI 十六进制/十进制转换 hex2dec 0xFF → 255;hex2dec 256 → 0x100
Strings strings.exe CLI 文件中搜索字符串 strings -n 5 file.exe 搜索5字符以上字符串
LiveKD livekd.exe CLI 本地内核调试 livekd -k 启动内核调试
Ctrl2Cap ctrl2cap.exe CLI 键盘映射 ctrl2cap /install 安装CapsLock转Ctrl
Portmon portmon.exe GUI 串行端口监视器 双击运行,捕获串口通信
LogonSessions logonsessions.exe CLI 列出所有登录会话 logonsessions 显示所有活动会话
NTFSInfo ntfsinfo.exe CLI 显示NTFS卷信息 ntfsinfo c: 显示NTFS结构信息
VolumeID volumeid.exe CLI 修改卷ID volumeid c: XXXX-XXXX 修改NTFS卷序列号
Sync sync.exe CLI 刷新文件系统缓存 sync 确保数据写入磁盘

注册表工具

工具 类型 功能 使用说明
RegJump CLI 跳转到注册表位置 regjump HKLM\Software 直接打开 regedit 定位
RegDelNull CLI 删除包含空字符的注册表键 regdelnull -r HKLM\Software 扫描并删除

应用场景

  1. 故障诊断

    • 系统蓝屏:通过 ProcDump 捕获崩溃转储,结合 Process Monitor 分析异常操作链
    • 文件占用冲突:Handle 定位锁定文件的进程,强制解除占用
  2. 性能优化

    • 内存泄漏:RAMMap 分析缓存分布,VMMap 定位进程内存异常增长
    • 磁盘瓶颈:DiskMon 监控实时 I/O,Contig 整理关键文件碎片
  3. 安全加固

    • 启动项审计:Autoruns 清除恶意自启动项,修复注册表劫持
    • 恶意进程分析:Process Explorer 验证签名和父进程链,识别注入 DLL
  4. 开发与测试

    • API 调用追踪:Process Monitor 记录应用程序的注册表和文件操作,辅助调试
    • 压力测试:NotMyFault 主动触发系统崩溃或内存泄漏,验证容错机制

fsutil

fsutil 是 Windows 系统内置的高级命令行工具,用于对 FAT、NTFS、ReFS 等文件系统进行底层管理与配置,涵盖卷管理、文件操作、元数据管控、系统行为调优等核心能力,是 Windows 系统运维、排障、性能优化的核心工具之一Microsoft Learn

  • 适用环境: 支持 Windows 7/8/8.1/10/11,以及 Windows Server 2008 R2 至 2025 全系列服务器系统,无需额外安装,系统原生自带Microsoft Learn。
  • 核心权限要求: 必须以管理员身份运行命令提示符(CMD)或 PowerShell,否则绝大多数子命令会执行失败并提示权限不足,仅推荐对 Windows 文件系统有深入理解的进阶用户使用,错误操作可能导致文件系统损坏、数据丢失。

典型实用场景

  1. 极速生成大测试文件

    相比手动写入内容,fsutil file createnew可瞬间生成 GB 级大文件,用于磁盘测速、软件测试、填充磁盘空间等场景。

  2. 系统性能优化

    禁用 8.3 短文件名、禁用最近访问时间戳,可显著提升机械硬盘、高文件数量目录的访问性能,是老旧电脑优化的常用手段。

  3. 磁盘故障排障

    通过脏位查询、NTFS 信息查询、空间统计,快速定位磁盘文件系统损坏、空间占用异常、坏簇等问题。

  4. 多用户环境磁盘管控

    通过配额管理,限制不同用户的磁盘使用上限,防止单用户占用全部磁盘空间,适用于机房、共享服务器场景。

  5. 虚拟化 / 大文件存储优化

    通过稀疏文件特性,让虚拟机磁盘、日志文件等大文件仅占用实际有数据的磁盘空间,大幅节省存储资源。

常用案例

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
#极速生成指定大小的空白测试文件  (生成的是全 0 空白文件,瞬间完成,不占用 CPU,仅占用对应磁盘空间)
# 生成512MB空白文件
fsutil file createnew D:\测试文件\512MB测试文件.dat 536870912
# 生成100GB空白文件
fsutil file createnew D:\测试文件\100GB测试文件.dat 107374182400

#一键查询系统所有盘符
fsutil fsinfo drives

#精准查询磁盘剩余空间(字节级,比资源管理器更准)
# 查C盘剩余空间
fsutil volume diskfree C:

#禁用文件最后访问时间戳,提升磁盘性能(机械硬盘必用) (修改后重启电脑生效,仅极老的备份软件依赖该时间戳,普通用户无任何副作用)
# 禁用最后访问时间更新(推荐)
fsutil behavior set disablelastaccess 1
# 恢复启用(如需还原执行这条)
fsutil behavior set disablelastaccess 0

#卸载无法安全弹出的 U 盘 / 移动硬盘
# 卸载U盘
fsutil volume dismount U:
#执行前必须关闭 U 盘内所有打开的文件、文件夹、程序;卸载后盘符仍可见但无法访问,重新插拔即可恢复,比强制拔盘更安全,避免文件损坏

#线卸载数据盘,执行 chkdsk 磁盘修复
# 1. 卸载D盘卷(替换为目标数据盘盘符,不可用于系统盘C:)
fsutil volume dismount D:
# 2. 执行完整磁盘检查与坏道修复
chkdsk D: /f /r

PIX

PIX(Performance Insight X) 是微软开发的图形调试、性能分析与诊断工具,主要用于开发和调试基于 DirectX 的图形应用(如 WPF、DirectX、D3D、Vulkan、DirectComposition 等)。它支持多种图形 API 的性能分析和帧调试,是 Windows 10 和 Windows 11 系统中非常有用的开发工具

下载链接

  • GPU Capture 帧级 GPU 渲染 / 资源全量快照

    给 GPU 的所有 DirectX 资源、渲染状态、API 调用拍一张「高清 X 光片」,能看到每一个资源的创建 / 销毁、每一步渲染细节

    能检测 DirectX 资源泄露、定位泄露资源的模式

  • Timing Capture 时间线级 CPU/GPU 性能耗时采样

    给程序的运行过程录一段「性能监控视频」,统计全程的帧率、CPU/GPU 耗时、利用率、函数执行时间

    用于性能分析,识别 CPU 和 GPU 的瓶颈与耗时部分,帮助优化应用运行效率

系统监视指标说明

✅ 针对WPF程序启动捕获的时候: 必须勾选 Force D3D11on12(WPF 底层用的是 D3D11,PIX 默认只捕获 D3D12,不勾这个完全捕获不到 WPF 的 DirectX 资源)

表格列说明

每一行指标的表格列,都是对该指标的统计与图表控制

列名 全称 / 核心含义 实际用法
View 视图显示开关 勾选后,该指标的曲线会显示在右侧的折线图中;取消勾选则隐藏,用于筛选你重点关注的指标
Color 曲线颜色 该指标在右侧图表中对应的曲线颜色,用于快速区分不同指标
Name 指标名称 核心监控项的名字,下文会逐个拆解每个名称的含义
Value 实时值 当前时刻该指标的最新数值,最直观的「当前状态」
Units 数值单位 指标的计量单位,常见的有:Frames/sec(帧率)、ms(毫秒)、B(字节)、MB(兆字节)、binary(二进制 0/1,代表是否启用)、%(百分比)
Min 最小值 整个录制周期内,该指标出现过的最小值
Max 最大值 整个录制周期内,该指标出现过的峰值,判断内存 / 负载上限的核心参数
Mean 平均值 整个录制周期内的平均数值,反映指标的整体平均水平
StdDev 标准差 数值的波动幅度,数值越大,说明该指标波动越剧烈(比如帧率忽高忽低,StdDev 就会很高)
Agg Aggregation 聚合方式 右侧图表的曲线计算规则,默认Avg是按平均值绘制,也可切换为 Min/Max/Sum,一般保持默认 Avg 即可
Auto Fit 自动适配 Y 轴 勾选后,图表的 Y 轴范围会自动适配该指标的数值范围,无需手动调整
Y-min / Y-max Y 轴最小 / 最大值 手动设置图表 Y 轴的上下限,用于放大查看细节(比如内存只涨了几 MB,自动适配看不到趋势,手动设置后可清晰观察)
具体数据项
  • [Present Data 帧呈现数据](#Present Data 帧呈现数据)
  • [CPU Memory CPU 内存](#CPU Memory CPU 内存)
  • [GPU Utilization GPU 利用率](#GPU Utilization GPU 利用率) 👈🏻DirectX资源泄露重点关注
  • [Present Mode 呈现模式](#Present Mode 呈现模式)
  • [Local GPU Memory 本地 GPU 内存](#Local GPU Memory 本地 GPU 内存) 👈🏻DirectX资源泄露重点关注
  • [Non-Local GPU Memory 非本地 GPU 内存](#Non-Local GPU Memory 非本地 GPU 内存)
  • [Demoted GPU Memory 降级 GPU 内存](#Demoted GPU Memory 降级 GPU 内存)
Present Data 帧呈现数据

核心作用:监控 WPF 界面的渲染帧率、帧耗时、渲染延迟,反映界面的流畅度,间接体现渲染压力(资源泄露会导致渲染耗时持续升高、帧率下降)

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Frames per second 每秒渲染帧数(FPS) Frames/sec WPF 界面的渲染帧率,正常桌面场景稳定 60 帧为最佳;如果资源泄露导致 GPU/CPU 压力过大,帧率会持续下降、波动剧烈
MsBetweenPresents 两次帧提交之间的间隔时间 ms 正常 60 帧对应 16.6ms;数值越大帧率越低,持续升高说明渲染压力越来越大
MsBetweenDisplayChange 两次屏幕内容刷新的间隔时间 ms 屏幕实际刷新内容的间隔,和上一个指标的区别是:WPF 没有新内容渲染时,这个数值会变大;如果闲置时仍频繁刷新,说明有异常渲染循环
MsInPresentAPI 执行 Present API 的耗时 ms 把渲染好的帧提交给显卡的耗时,耗时越高说明显卡提交帧有瓶颈,资源泄露导致 GPU 负载过高时,这个数值会持续升高
MsUntilRenderComplete 单帧渲染完成的总耗时 ms 从帧开始渲染到渲染结束的总耗时,直接反映 WPF 渲染管线的压力,数值越高渲染越卡,泄露导致资源过多时,耗时会持续上涨
MsUntilDisplayed 帧从渲染到显示在屏幕的总耗时 ms 端到端的渲染延迟,包含渲染、提交、屏幕刷新的全流程,数值越高界面越卡顿
Sync Interval 垂直同步间隔 vertical blank(屏幕刷新周期) 0 = 关闭垂直同步,1 = 每 1 个屏幕刷新周期同步一次(对应 60 帧),2 = 每 2 个周期同步(对应 30 帧);WPF 默认开启垂直同步,正常数值为 1
CPU Memory CPU 内存

核心作用:监控 WPF 进程的内存占用,是判断内存泄露(含托管内存泄露、DirectX 非托管资源泄露)的核心维度之一,DirectX 资源泄露一定会伴随 CPU 内存的同步上涨

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Working Set Size 进程工作集大小 字节 B 当前 WPF 进程占用的物理内存总量,包含 WPF 的 C# 托管内存、DirectX 资源对应的系统内存、程序代码段等。
✅ 泄露核心判断项:反复执行同一操作(如打开 / 关闭窗口)后,数值持续上涨,操作停止后也不回落,说明存在内存泄露(含 DirectX 资源泄露)
Page File Usage (Commit) 提交内存大小 字节 B 进程向系统申请的虚拟内存总量,不管有没有实际用到物理内存,比 Working Set 更能反映进程申请的内存总规模。泄露时这个数值会和 Working Set 同步持续上涨。
Page Fault Count 缺页中断次数 无单位 进程访问的内存不在物理内存中,需要从硬盘 / 页文件读取的次数。数值越高说明内存压力越大,泄露导致内存不足时,这个数值会快速飙升。
GPU Utilization GPU 利用率

核心作用:监控 WPF 进程的 GPU 负载,反映显卡的 3D 渲染压力,资源泄露会导致 GPU 闲置时仍居高不下

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Target Process 3D Engine Utilization 目标进程的3D 引擎利用率 % WPF 的 DirectX 渲染占用的 GPU 3D 计算能力占比。
✅ 泄露判断项:WPF 界面无任何操作时,这个数值仍持续高于 5%,说明有异常的持续渲染,大概率是资源泄露导致 GPU 一直在处理无效资源;正常闲置的 WPF 程序该数值应接近 0
All Processes 3D Engine Utilization 系统所有进程的 3D 引擎总利用率 % 整个系统的 GPU 3D 负载,用于对比:如果总占用很高,但 WPF 的占用很低,说明是其他程序(浏览器、游戏)占用了 GPU,不是你的程序的问题
剩余 2 个带–%的 Utilization 项 其他 GPU 计算单元利用率 % Intel 核显的其他非 3D 计算单元,WPF 渲染不会用到,正常数值为 0,无需关注

除了硬件外还会有个CPU模拟的GPU渲染驱动

维度 Intel UHD Graphics 730 engine 0 Microsoft Basic Render Driver engine
性质 物理硬件 GPU(你的 CPU 集成的核显) 纯软件模拟的渲染驱动(用 CPU 模拟 GPU 功能)
渲染方式 硬件加速渲染(GPU 芯片直接计算) 软件渲染(CPU 计算所有渲染逻辑)
性能 高,流畅支持 WPF、视频、轻量 3D 极低,仅能满足基本界面显示,容易卡顿
资源占用 占用 Intel 核显的专用显存(Local GPU Memory) 不占用 GPU 显存,完全占用 CPU 和系统内存
用途 正常场景下的主力渲染器 备用 / 兼容渲染器(仅在硬件 GPU 不可用时启用)
Present Mode 呈现模式

核心作用:显示 WPF 渲染好的帧,用什么方式显示到屏幕上,和渲染性能强相关,和资源泄露无直接关联,仅用于判断渲染效率是否正常

注意:该大项的单位是binary,数值只有 0/1,1 = 当前正在使用该模式,0 = 未使用

子指标名称 含义 WPF 场景说明
ComposedCopyWithCpuGdi CPU 通过 GDI 合成拷贝模式 效率最低的模式,CPU 占用高,WPF 仅在系统兼容性模式下会启用,正常场景不会用到
ComposedCopyWithGpuGdi GPU 通过 GDI 合成拷贝模式 效率略高于 CPU 模式,但仍属于低效兼容模式,正常 WPF 不会使用
ComposedFlip 合成翻转模式 WPF 最常用的高效模式,直接翻转帧缓冲区,无需全量拷贝,性能损耗极低,正常 WPF 程序默认用这个模式
HardwareComposedIndependentFlip 硬件合成独立翻转模式 Win10 + 的最高效模式,支持多窗口独立刷新,性能最好,需要显卡和系统支持
HardwareIndependentFlip 硬件独立翻转模式 同上,也是高效硬件加速模式,适配不同的显卡驱动
剩余 HardwareLegacy 开头的项 硬件传统兼容模式 老系统 / 老显卡的兼容模式,效率低,正常 WPF 不会使用
OtherPresentMode 其他未分类模式 一般为 0,无需关注
Local GPU Memory 本地 GPU 内存

核心作用:监控显卡专用显存的占用,是WPF DirectX 资源泄露检测的最核心维度——WPF 的 BitmapImage、ImageBrush、D3DImage、渲染纹理、顶点缓冲区等所有 DirectX 资源,全部存储在这里

Intel 核显,会共享系统内存作为专用显存,所以预算会很高

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Local Budget 本地 GPU 内存总预算 MB 系统给显卡分配的最大专用显存容量,固定值,不会随程序运行变化,仅用于判断是否接近显存上限
Local Resident 本地显存驻留大小 MB 当前所有 DirectX 资源,实际加载到专用显存里的总大小。
✅ 泄露第一核心判断项:反复执行可疑操作后,这个数值持续上涨,操作停止、窗口关闭后,等待 1-2 分钟仍不回落,100% 是 DirectX 资源泄露(比如纹理、缓冲区创建后未释放)
Local Usage 本地显存实际使用大小 MB 当前 GPU 正在实时使用的显存大小,和 Resident 的区别是:Resident 是已经加载到显存的总资源量,Usage 是当前正在用的量。
✅ 泄露辅助判断项:泄露时会和 Local Resident 同步持续上涨,趋势完全一致
Non-Local GPU Memory 非本地 GPU 内存

核心作用:监控系统主内存(RAM)被 GPU 当作显存使用的部分,当专用显存不足时,DirectX 会把溢出的资源放到这里

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Non-Local Budget 非本地 GPU 内存总预算 MB 系统允许 GPU 使用的最大系统内存容量,若为 0,说明核显全部用 Local Budget 的共享内存,无需额外分配
Non-Local Resident 非本地内存驻留大小 MB 放在系统内存里的 DirectX 资源总大小;如果该数值持续上涨,说明专用显存不足,或存在资源泄露
Non-Local Usage 非本地内存实际使用大小 MB GPU 正在使用的系统内存大小,泄露时会和 Resident 同步上涨
Demoted GPU Memory 降级 GPU 内存

核心作用:监控被 GPU 从高速专用显存,降级到低速系统内存的资源大小,仅在显存压力极大时才会出现数值

若全为 0,说明显存压力正常,无资源降级,无需重点关注

子指标名称 含义 单位 WPF 场景说明 & 泄露关联
Minimum/Low/Normal Priority 低 / 普通优先级降级内存 MB 不重要的资源被降级到系统内存的大小,数值高说明显存压力大
High/Maximum Priority 高 / 最高优先级降级内存 MB 核心渲染资源被降级,数值 > 0 说明显存已经严重不足,大概率是资源泄露把显存占满了

资源追踪器

至少有一帧数据,才能使用

Widows各种资源泄露现象

可以针对Testlimit进行测试

  • 句柄耗尽时的系统行为

    • 系统频繁弹出 “系统资源不足,无法完成请求” 的错误提示

    • 系统响应迟缓,窗口无法打开或程序无响应

    • 无法创建新的窗口、文件或网络连接

    • 严重时可能导致 Explorer.exe 崩溃并自动重启

  • 线程耗尽的影响

    • 无法创建新的线程或进程

    • 应用程序的并发处理能力严重下降

    • 可能触发 “配额不足” 错误

  • 桌面堆和GDI对象耗尽的影响

    • 窗口无法正确显示或渲染

    • 窗口出现黑色或空白区域

    • 窗口崩溃或无响应

    • 任务栏卡死、开始菜单无响应、右键菜单失效

    • 输入法切换异常

内存碎片排查

用「任务管理器 + 资源监视器」看关键指标 —— 初步排查

先看两个核心指标,区分「真的内存不够」还是「碎片导致的分配失败」:

指标 看什么? 碎片的典型表现
提交大小(Commit Size) 任务管理器 → 详细信息 → 你的程序 → 「提交大小」列 提交大小没到上限(32 位没到 2GB,64 位没到物理内存 + 虚拟内存总和),但还是 OOM
虚拟内存布局 资源监视器 → 内存 → 你的程序 → 看「硬错误」和「提交」 硬错误不多(说明不是物理内存不够),但「提交」一直在涨,且 OOM 时没有明显的「内存泄漏式暴涨」

如果是 64 位程序,「提交大小」只有几百 MB,但还是 OOM → 重点查「大对象堆碎片」

VMMap直观看到碎片

Windows事件查看器

**Windows事件查看器(Event Viewer)**是Windows操作系统内置的系统日志管理工具,用于记录系统运行状态、应用程序行为和安全事件。它通过分析事件日志,帮助用户快速定位系统故障、应用程序错误及安全隐患

核心功能与作用

日志分类

  • 应用程序日志:记录软件运行事件(如程序崩溃、安装卸载)
  • 系统日志:记录操作系统组件事件(如驱动加载失败、服务启动错误)
  • 安全日志:记录安全相关操作(如登录尝试、权限变更)
  • Setup日志:系统安装或更新事件
  • 转发事件:其他计算机转发的日志

事件级别

  • 错误(红色):严重故障(如蓝屏、服务崩溃)
  • 警告(黄色):潜在问题(如磁盘空间不足)
  • 信息(蓝色):正常操作记录(如系统启动)

打开方式

  1. 快捷搜索

    Win + S 输入“事件查看器”或“Event Viewer”

  2. 运行命令

    Win + R 输入 eventvwreventvwr.msc

  3. 控制面板

    控制面板 → 管理工具 → 事件查看器

  4. 任务管理器

    Ctrl + Shift + Esc → 文件 → 运行新任务 → 输入 eventvwr

  5. 文件资源管理器

    访问路径 C:\Windows\System32\eventvwr.exe

网站快速部署方案

Linux控制面板

特性维度 Websoft9 宝塔面板 cPanel 1Panel FastPanel Urlos
核心定位 开源应用全生命周期管理 通用服务器运维 专业虚拟主机管理 现代化容器化运维 快速建站与多语言支持 轻量级、低资源占用
应用生态 ★★★★★ (300+模板,深度优化) ★★★★☆ (丰富,但需手动调优) ★★★☆☆ (通用功能为主,缺乏深度适配) ★★★☆☆ (模板较少,依赖容器化) ★★★☆☆ (支持WordPress/Joomla等一键安装) ★★☆☆☆ (支持多语言环境但应用较少)
部署效率 ★★★★★ (3-5分钟,一键自动化) ★★★☆☆ (30-60分钟,需一定基础) ★★★☆☆ (依赖主机商) ★★★★☆ (20分钟,容器化部署)
安全机制 ★★★★★ (全生命周期自动防护+漏洞修复) ★★★☆☆ (基础防火墙+依赖插件) ★★★★☆ (企业级但成本高) ★★★☆☆ (侧重容器和网络隔离) ★★★☆☆ (提供基础防火墙和SSL管理)
资源效率 ★★★★★ (轻量化,1GB内存即可运行) ★★★☆☆ (高负载时性能可能下降) ★★☆☆☆ (需要企业级硬件支持) ★★★★☆ (中等,容器化有优势) ★★★★★ (资源占用极低,占传统面板1/3)
扩展性 ★★★★★ (支持Docker/K8s,自主扩展中间件) ★★★★☆ (插件生态丰富) ★★★☆☆ (功能依赖主机商) ★★★★☆ (兼容K8s,容器编排)
学习成本 ★★☆☆☆ (基础功能简单,高级功能需学习) ★★★☆☆ (中文友好,社区活跃) ★★★★☆ (现代化UI,但需容器知识) ★★★☆☆ (中等) ★★★☆☆ (低)
适用场景 需快速部署、深度管理多种开源应用的企业、开发者、教育机构 国内用户广泛,适合通用服务器运维、单站点管理 传统虚拟主机管理、邮件服务 需要轻量级容器化管理的场景 需要搭建多语言教学平台或快速创建课程网站 资源有限的服务器、老旧设备改造

Websoft9

Websoft9 的核心是提供一个大量预配置好的、生产就绪的开源应用目录(如 WordPress、Jenkins、Nextcloud、Moodle 等)。它解决了手动部署这些应用时遇到的依赖复杂、配置繁琐、优化和安全加固困难的问题。它非常适合那些希望快速获得这些特定开源软件,并希望其稳定、安全运行,而不想深究底层基础设施细节的用户和团队

项目地址

  • Websoft9 的核心定位是一个 “Applications self-hosting and DevOps platform”“lite PaaS”

    用于运行开源、基于 Web 的 Linux Panel 或 Lite PaaS 的应用程序自托管和 DevOps 平台

    • 自托管: 数据存储在本地

    • DevOps 平台: DevOps是“Development(开发)”和“Operations(运维)”的组合词,是一种文化、实践和工具的集合,旨在缩短软件开发生命周期,实现持续集成、持续交付和高效运维,即一套“自动化流水线”工具。传统方式是开发人员写完代码,扔给运维人员去手动部署,效率低易出错。DevOps平台则自动化了这个过程:代码一提交,自动测试、自动打包、自动部署上线

    • 基于 Web 的 Linux Panel: 一个通过浏览器访问的图形化用户界面,用于管理和操作Linux服务器。隐藏了复杂的命令行操作

    • Lite PaaS (轻量级平台即服务): PaaS是云计算服务的一种模式,提供软件部署和运行的环境(如运行时、数据库、Web服务器),开发者只需关心自己的代码。“Lite”(轻量级) 指这是一个简化版,通常为单机或小规模集群设计,易于部署和使用.即给你一个“应用程序的万能运行底座”。你不需要关心服务器环境配置(比如需要哪个版本的PHP、Python,如何配置Nginx),只需要把你的代码或应用程序打包扔给它,它就能自动为你准备好一切并运行起来

    但是要注意Websoft9是针对开源项目优化才能实现到这一点,针对自己的项目并不一定可以

  • 它的主要功能是帮助用户在单台 Linux 服务器上通过 Docker Compose 以微服务的方式 部署和管理预配置好的开源应用模板(例如 WordPress, Nextcloud, MySQL, Redis, GitLab 等)

Websoft9 的核心优势在于自动化集中管理。它通过应用商店和容器技术,简化了从部署、配置到维护的全过程,非常适合管理多个应用或需要快速搭建标准业务系统的场景

部署自己的项目

  1. Dokku:极致简约的个人版 Heroku

    Dokku 的核心是极简模仿 Heroku 的 Git 推送部署体验。它非常适合个人开发者或微型项目,让你在最低成本的 VPS 上就能体验到类似 Heroku 的部署流程。其功能主要通过插件体系扩展,本身非常轻量

  2. CapRover:功能完善的小团队利器

    CapRover 在 Dokku 的理念基础上,增加了友好的 Web 管理界面丰富的开箱即用功能(如一键部署数据库)。它降低了自托管 PaaS 的使用门槛,适合小团队、初创公司或个人开发者,希望在易用性和控制权之间取得平衡

  3. Coolify:面向未来的自托管中心

    Coolify 的目标是成为一体化的自托管解决方案。它不仅支持应用部署,还强调多云/混合云管理强大的自动化(如自动备份、Webhooks)和团队协作。适合注重数据主权、需要灵活部署策略,且有一定运维能力的用户

  4. Heroku:省心省力的全托管标杆

    Heroku 提供了最完整的开箱即用体验无忧的运维管理。你完全不需要关心底层基础设施,只需专注代码。但其昂贵的成本和可能的厂商锁定风险,使得许多开发者和团队开始寻求像 Dokku、CapRover 和 Coolify 这样的替代方案

  • 共同点:它们都通过容器化技术(Docker),将开发者从配置服务器环境、安装依赖、配置 Web 服务器(如 Nginx)、设置 SSL 证书等重复性劳动中解放出来。你通常只需要简单地推送代码(git push),平台就会自动完成构建和部署。
  • 差异点
    • Dokku 最轻量,极致模仿 Heroku 的体验,但功能相对单一,适合个人项目。
    • CapRover 在 Dokku 基础上增加了友好的 Web 界面更丰富的功能(如一键部署数据库),在易用性和灵活性之间取得了很好的平衡,是小团队和独立开发者的热门选择
    • Coolify 目标更宏大,更像一个一体化的自托管解决方案,支持多云管理强大的自动化,适合对控制权和部署灵活性要求更高的用户。
特性维度 Heroku (参照基准) Dokku CapRover Coolify
核心定位 全托管云 PaaS 轻量级、极简的个人版 Heroku 功能丰富的自托管 PaaS,平衡易用性与灵活性 开源自托管平台,追求全面控制与自动化,支持多云/混合云
托管方式 完全托管 自托管 (通常单服务器) 自托管 (支持单机与集群) 自托管 (支持单服务器、多服务器、Docker Swarm集群,计划支持Kubernetes)
开源协议 闭源 开源 开源 开源
部署方式 Git Push、CLI、容器 Git Push (主要方式) Git Push、Web界面、Dockerfile、Docker Compose Git Push (支持多种Git平台)、Dockerfile、Docker Compose
数据库支持 需通过付费插件市场集成 需手动部署或通过插件扩展 支持一键部署多种数据库 (MySQL, PostgreSQL, MongoDB, Redis等) 支持一键部署多种数据库 (MySQL, PostgreSQL, MongoDB, Redis等),并支持自动备份到S3兼容存储
Web界面 功能完善的Web控制台 无官方Web界面 (主要依赖CLI) 提供直观的Web控制台 提供功能强大的Web控制台
多语言/框架支持 广泛支持 支持多种语言 (通过Buildpack) 支持多种语言和框架 支持多种语言和框架
SSL证书 自动管理 可通过Let’s Encrypt插件获取 内置Let’s Encrypt,自动申请和续期 内置Let’s Encrypt,自动申请和续期
扩展性 垂直与水平扩展(需付费) 仅限于单机性能 支持Docker Swarm集群部署,可实现水平扩展 支持多服务器、Docker Swarm集群,未来计划支持Kubernetes
成本 昂贵(免费层已取消) 极低(仅服务器成本) 低(仅服务器成本) 低(仅服务器成本)
适用场景 初创公司(快速原型验证)、企业项目(追求稳定免运维)、开发者(学习) 个人开发者、小型项目、需要极致简单和低成本的情景 小团队、初创公司、需要Web界面和一定灵活性、希望平衡易用性和控制权的场景 注重数据主权和控制权、需要多云/混合云部署、有一定运维能力或愿意学习的团队和个人
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
flowchart TD
A[开始平台选择] --> B{是否需要完全托管的服务<br>且预算充足?};

B -- 是 --> C[选择 Heroku];

B -- 否 --> D{主要用户是?};

D --> E[个人开发者];
D --> F[小型团队];
D --> G[中大型团队或<br>追求全面控制];

E --> H{追求极致简单<br>且只需基础部署?};
H -- 是 --> I[选择 Dokku];
H -- 否 --> J[考虑 CapRover 或 Coolify];

F --> K[选择 CapRover];

G --> L[选择 Coolify];

C --> M[特点:免运维、易用、昂贵];
I --> N[特点:极简、低成本、CLI操作];
K --> O[特点:功能全面、有Web界面、性价比高];
L --> P[特点:高度可控、支持多云、功能强大];

选择哪个工具取决于你的具体需求:

  1. 想快速使用成熟的、优化好的开源软件(如 WordPress, GitLab, Jenkins):Websoft9 是更直接的选择,它帮你处理好了应用本身的所有复杂问题。

  2. 想部署自己写的代码项目(如一个 Node.js 后端或 Python Web 应用):

    追求极致简单和低成本:从 Dokku 开始。

    • 希望有Web界面更好的易用性,适合小团队协作:CapRover 是很棒的选择
    • 需要更强大的功能支持多云/混合云,且不介意稍高的学习成本:关注 Coolify
  3. 预算充足,追求极致省心和开箱即用,不想维护任何服务器Heroku 仍然是体验非常好的选择。

临时公共子域名

完全免费使用: 使用 npx localtunnel --port [你的端口]命令启动服务不需要支付任何费用。它会为你生成一个随机的公共子域名(如 https://your-random-subname.loca.lt)指向你本地运行的服务。

开源项目: localtunnel 的代码在 GitHub 上公开,遵循 MIT 许可证。这意味着你可以自由地使用、修改和分发它。

官方公共服务器: 默认情况下,命令连接的是由 localtunnel 项目维护者提供的公共中继服务器loca.lt域名)。这是他们提供的免费公共服务

临时性: 免费提供的链接是临时的。当:

  • 主动停止了运行 npx localtunnel的命令行进程。

  • 你的电脑断网或者本地服务进程停止

  • 长时间没有流量通过隧道(具体超时时间可能由服务器设定)。

  • 公共服务器维护或重启。

    链接就会失效。下次启动时,你会获得一个新的随机子域名

1
2
3
# 完整部署流程(仅需两行命令):
cd project/dist && npx http-server -p 3000 &
npx localtunnel --port 3000

Coolify

自托管是完全免费的

官网 官方文档

免费云服务器盘点

参考来源

  1. Google Cloud Platform (GCP)

    • 免费资源
      • 1个非抢占式 e2-micro实例(每月750小时,可连续运行)
      • 30GB HDD存储 + 5GB快照存储
      • 5GB Cloud Storage + 1GB网络出口流量
    • 条件:仅限特定区域(如 us-west1, us-central1),超出部分按量付费。
  2. Oracle Cloud

    • 免费资源
      • 2个AMD虚拟机(1/8 OCPU + 1GB内存)
      • 4个Arm核心 + 24GB内存(可拆分或单机使用)
      • 200GB块存储 + 10GB对象存储
    • 条件:实例闲置时可能被回收,10TB免费出口流量/月。
  3. Cloudflare Workers

    • 免费资源
      • 无服务器部署(10万次请求/日)
      • Workers KV(100k读请求/日)
      • R2对象存储(10GB/月)
    • 特点:全球边缘网络,无需管理服务器。
  4. Fly.io

    • 免费资源
      • 3台共享CPU虚拟机(256MB内存/台)
      • 3GB持久存储
      • 160GB出站流量/月
    • 适合:轻量级容器化应用。
  5. Koyeb

    • 免费资源
      • 2个vCPU + 2GB内存实例
      • 无限应用部署
    • 限制:需绑定信用卡,但免费额度不扣费。

开源自托管项目盘点

certbot

比acme更好用

Certbot是一个由Electronic Frontier Foundation (EFF)赞助的开源工具,用于自动化管理和部署SSL/TLS证书。SSL/TLS证书是用于加密网站与用户之间传输的数据的一种安全协议。Certbot的主要目的是使网站管理员能够轻松获取、部署和更新这些证书,以确保网站的安全性

github链接

Let’s Encrypt 采用 ACME 协议来自动化验证你是否真正控制着要申请证书的域名。上述流程中最常见的两种验证方式是:

验证方式 是否需要公网IP 是否需要开放端口 配合内网穿透的可行性 推荐度
HTTP-01 间接需要(穿透服务器有即可) 需要开80端口 可行但麻烦,受穿透服务限制 ⭐⭐
DNS-01 完全不需要 不需要 非常可行且简单,是最佳方案 ⭐⭐⭐⭐⭐
  • HTTP-01 挑战 (HTTP-01 Challenge):这是最常用的方式。Certbot 会在你的服务器上(通常是80端口)临时生成一个特定的验证文件,Let’s Encrypt 的服务器会尝试通过公网访问这个文件(例如 http://你的域名/.well-known/acme-challenge/某个令牌)。如果你的服务器没有公网IP,或者80端口被防火墙阻挡,外界就无法访问到这个文件,验证自然会失败
  • DNS-01 挑战 (DNS-01 Challenge):这种方式下,Certbot 会提供一个特定的文本(TXT)记录,你需要手动或通过API自动将其添加到你的域名DNS配置中。Let’s Encrypt 随后会通过查询DNS来验证。这种方式不要求你的服务器有公网IP或开放端口,但需要你能够操作域名的DNS记录。这对于无法开放端口的服务器或申请通配符证书(*.\你的域名.com)非常有用。
    • 无论服务器在哪里(有无公网IP),运行 certbot certonly --manual --preferred-challenges dns
    • Certbot 会给你提供一个随机生成的TXT记录值。
    • 手动(或通过API脚本自动) 到你的域名DNS管理后台(如阿里云、Cloudflare等),为你的域名添加这条TXT记录(例如 _acme-challenge.example.com. IN TXT "随机值")。
    • 确认记录添加后,回车继续。
    • Let’s Encrypt 会去查询域名的DNS记录,如果找到并匹配成功,就颁发证书。
    • 成功后,别忘了从DNS中删除那条TXT记录(虽然不删也没大问题,但保持整洁为好)

如果服务器位于网络地址转换(NAT) 后面,或者由云服务提供商托管,但提供商集成了 Let’s Encrypt(例如某些云平台的负载均衡器或托管服务),那么你可能不需要直接在你的服务器实例上配置公网IP。证书的申请和验证过程可以由云平台在其基础设施层面代为完成

为确保顺利申请证书,你的服务器和环境需满足以下条件

  • 公网IP与开放端口:服务器需具备公网IP,并确保所需验证端口(HTTP-01验证需开放80端口)未被防火墙或云服务商的安全组阻挡。
  • 域名与DNS解析:你必须拥有一个已注册的域名,并已将该域名(如 example.comwww.example.com)的DNS记录(通常是A记录或CNAME记录)正确解析到你的服务器公网IP。
  • 服务器环境:服务器需安装支持的操作系统(如Linux发行版),并具备命令行sudo权限。对于HTTP-01验证,需提前安装并运行Web服务器软件(如Nginx或Apache);对于DNS-01验证,需具备域名DNS管理权限或API访问密钥。
  • Certbot工具:在服务器上安装Certbot客户端。官方推荐通过Snap包安装,以获得最新版本和完整功能

安装流程

1
2
3
4
5
6
#Debian/Ubuntu安装certbot
apt update -y && apt install -y certbot
#CentOS安装certbot
yum -y update && yum -y install certbot
#Alpine Linux安装certbot
apk update && apk add certbot

首先确保80和443端口未被占用

1
2
3
4
curl -s ipv4.ip.sb
certbot certonly --standalone -d $yuming --email your@email.com --agree-tos --no-eff-ernewal
#证书存放目录
ls /etc/letsencrypt/live/

docker方案部署流程

docker方式参考下面

步骤 操作内容 关键信息/命令
1. 选择验证方式 采用 DNS-01 验证 无需公网IP,需域名服务商API支持。
2. 准备域名API凭证 从您的域名服务商(如Cloudflare)获取API密钥。 例如Cloudflare的 Global API KeyToken
3. 创建存储目录 在群晖上创建目录,用于持久化Certbot配置和证书。 mkdir -p /docker/certbot/{etc,lib,log}
4. 首次申请证书 运行Certbot容器,使用DNS插件和API凭证申请证书。
5. 配置自动续期 创建续期脚本,并添加群晖计划任务。

获取cloudflare api token

cloudflare获取api token链接

这个api token必须要有修改dns记录的权限

image-20250915153328475 image-20250915153455139

配置令牌权限和范围

  • 权限(Permissions):确保权限范围是 Zone - DNS - Edit。这赋予了Token修改DNS记录的权限。
  • 资源范围(Resource scope):选择 “包括” (Include) - “特定区域” (Specific zone),然后在下拉列表中选择你托管的那个域名。这样可以将Token的权限限制在仅管理该域名的DNS记录,遵循最小权限原则,更安全。

完成配置后,点击 “继续到摘要” (Continue to summary)检查设置,确认无误后点击 “创建令牌” (Create Token)

下载运行镜像申请证书

镜像名称 描述
certbot/certbot 基础镜像,只包含核心的 certbot 功能,不包含任何 DNS 插件
certbot/dns-cloudflare 专用镜像,在基础镜像上额外预装了 certbot-dns-cloudflare插件,支持 --dns-cloudflare参数。

由于没有公网ip,所以需要采用 DNS-01 验证方式申请证书,因此需要的镜像是certbot/dns-cloudflare

新建需要映射的文件夹和文件

  • 点击 添加文件夹
    • 文件夹:选择您之前创建的 /docker/certbot/etc
    • 挂载路径:输入 /etc/letsencrypt
  • 再次点击 添加文件夹
    • 文件夹:选择 /docker/certbot/lib
    • 挂载路径:输入 /var/lib/letsencrypt
  • 再次点击 添加文件夹
    • 文件夹:选择 /docker/certbot/logs
    • 挂载路径:输入 /var/log/letsencrypt
  • 点击添加文件(这是一个重要技巧!)
    • 文件:选择您创建的 cloudflare.ini凭证文件。
    • 挂载路径:输入 /etc/letsencrypt/cloudflare.ini:ro。最后的 :ro代表只读,更安全(群晖中不写:ro,而是手动选择只读)

cloudflare.ini中内容如下:

1
2
3
4
5
6
# 如果您使用的是 Global API Key(不推荐,但可用):
dns_cloudflare_email = your_login_email@example.com
dns_cloudflare_api_key = your_global_api_key

# 或者,如果您使用的是 API Token(推荐,更安全):
dns_cloudflare_api_token = your_api_token_here(这套方案采用这种方式,这里填入上一个流程获取到的cloudflare的api token)

👆🏻要么使用 dns_cloudflare_email+ dns_cloudflare_api_key组合,要么单独使用 dns_cloudflare_api_token绝不能同时出现这三行

运行镜像的配置如下:

image-20250917173621893
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#写成指令大概如下:
docker run --rm \
--name certbot-ApplyOnce \
-p 443:443/tcp \
-p 80:80/tcp \
-v /docker/certbot/etc:/etc/letsencrypt \
-v /docker/certbot/lib:/var/lib/letsencrypt \
-v /docker/certbot/logs:/var/log/letsencrypt \
-v /docker/certbot/cloudflare.ini:/etc/letsencrypt/cloudflare.ini:ro \
-e PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin... \
-e LANG=C.UTF-8 \
-e GPG_KEY=7169605F62C751356D054A26A821E680... \
-e PYTHON_VERSION=3.12.10 \
-e PYTHON_SHA256=07ab697474595e06f06647417d3c7fa97d... \
-e EMAIL=xxxxxxxxxx@qq.com \
--memory="4g" \
certbot/dns-cloudflare \
certonly --non-interactive --agree-tos --email xxxxxxxxxx@qq.com \
--dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
--dns-cloudflare-propagation-seconds 30 \
-d nas.jhh1.site -d *.nas.jhh1.site

运行后可以在日志/docker/certbot/logs/...中观察到如下内容表示成功,虽然docker消息会显示意外中断

1
2
3
4
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/nas.xxxx.site/fullchain.pem
Key is saved at: /etc/letsencrypt/live/nas.xxxx.site/privkey.pem
This certificate expires on 2025-12-16.

生成的证书在此处: ls -la /volume1/docker/certbot/etc/archive/nas.xxxx.site/(不需要勾选显示隐藏就能看见)

/volume1/docker/certbot/etc/live/nas.xxxx.site/里,您会找到以下几个符号链接文件(在群晖中默认被隐藏,在ssh中可以被看到),他们始终指向archive中的真实证书文件(真实证书文件名最后会带数字编号,更新后得以标识证书)

  • fullchain.pem- 证书链文件 (这是您需要在Web服务器中配置的证书文件)
  • privkey.pem- 私钥文件 (这是您需要在Web服务器中配置的密钥文件)
  • cert.pem- 证书文件
  • chain.pem- 中间证书文件

自动续期

下面流程需要结合[[git#Gitea|参考此处来一起使用]]

1
2
3
4
5
6
7
8
9
flowchart TD
A[创建自动续期脚本] --> B[赋予脚本执行权限]
B --> C[登录群晖DSM后台]
C --> D[打开控制面板 → 任务计划器]
D --> E[创建新计划任务 → 用户定义的脚本]
E --> F[设置任务执行计划:<br>例如:每月1号和15号 凌晨3点]
F --> G[在任务设置中粘贴脚本路径]
G --> H[保存并运行任务测试]
H --> I[检查证书目录<br>确认续期成功]
  1. 创建自动续期脚本

    建议放在一个固定的、有权限的目录,例如 /docker/certbot/目录下,方便管理

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #!/bin/bash

    # 记录当前证书的过期时间
    CERT_FILE="/volume1/docker/certbot/etc/live/nas.jhh1.site/fullchain.pem"

    # 检查证书文件是否存在
    if [ ! -f "$CERT_FILE" ]; then
    echo "错误:证书文件不存在: $CERT_FILE"
    exit 1
    fi

    # 获取证书的过期时间(天数)
    get_cert_expiry_days() {
    local cert_file="$1"
    local expiry_date
    expiry_date=$(openssl x509 -in "$cert_file" -enddate -noout 2>/dev/null | cut -d= -f2)
    if [ $? -eq 0 ]; then
    local expiry_epoch=$(date -d "$expiry_date" +%s 2>/dev/null || date -j -f "%b %d %T %Y" "$expiry_date" +%s 2>/dev/null)
    local now_epoch=$(date +%s)
    echo $(( ($expiry_epoch - $now_epoch) / 86400 ))
    else
    echo -1
    fi
    }

    # 记录开始前的过期天数
    BEFORE_DAYS=$(get_cert_expiry_days "$CERT_FILE")

    # 记录日志
    echo "=============================="
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 开始执行证书续期检查"
    echo "当前证书将在 $BEFORE_DAYS 天后过期"

    # 运行Certbot续期命令
    docker run --rm --name certbot-renew \
    -v /volume1/docker/certbot/etc:/etc/letsencrypt \
    -v /volume1/docker/certbot/lib:/var/lib/letsencrypt \
    -v /volume1/docker/certbot/logs:/var/log/letsencrypt \
    -v /volume1/docker/certbot/cloudflare.ini:/etc/letsencrypt/cloudflare.ini:ro \
    certbot/dns-cloudflare renew --non-interactive --quiet

    DOCKER_EXIT_CODE=$?

    # 检查状态并判断是否真的续期了
    if [ $DOCKER_EXIT_CODE -eq 0 ]; then
    # 获取续期后的过期天数
    AFTER_DAYS=$(get_cert_expiry_days "$CERT_FILE")

    if [ "$AFTER_DAYS" -eq -1 ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 错误:无法读取证书过期时间"
    exit 1
    elif [ "$AFTER_DAYS" -gt "$BEFORE_DAYS" ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 证书已成功续期,新证书将在 ${AFTER_DAYS} 天后过期"

    # 重启相关服务
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 重启nginx-macvlan容器..."
    if docker restart nginx-macvlan; then
    echo "$(date '+%Y-%m-%d %H:%M:%S'): nginx容器重启成功"
    else
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 警告:nginx容器重启失败"
    fi


    echo "$(date '+%Y-%m-%d %H:%M:%S'): 重启gitea-macvlan容器..."
    if docker restart gitea-macvlan; then
    echo "$(date '+%Y-%m-%d %H:%M:%S'): Gitea容器重启成功"
    else
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 警告:Gitea容器重启失败"
    fi

    # 如果使用群晖Web Station,也重启nginx
    # echo "$(date '+%Y-%m-%d %H:%M:%S'): 重启Nginx..."
    # if synosystemctl restart nginx; then
    # echo "$(date '+%Y-%m-%d %H:%M:%S'): Nginx重启成功"
    # else
    # echo "$(date '+%Y-%m-%d %H:%M:%S'): 警告:Nginx重启失败"
    # fi

    else
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 证书检查完成,无需续期(证书 ${AFTER_DAYS} 天后过期)"
    fi
    else
    echo "$(date '+%Y-%m-%d %H:%M:%S'): 证书续期过程中出现错误,Docker退出码: $DOCKER_EXIT_CODE"
    exit 1
    fi

    赋予脚本执行可读可写权限: chmod +wrx ./renew_cert.sh

    Certbot 的 renew命令有以下特点:

    • 如果证书未到期(距离过期时间超过30天),它会安静退出(状态码0),不做任何操作
    • 如果证书即将到期(30天内),它会执行续期并退出(状态码0)
    • 只有遇到错误时才会返回非零状态码
  2. 配置群晖计划任务

    • 登录 DSM,打开 控制面板 > 任务计划器
    • 点击 新增 > 计划的任务 > 用户定义的脚本
    • 常规 选项卡中:
      • 任务:填写一个描述性名称,例如 Certbot 证书自动续期
      • 用户账号:选择 root。这一点非常重要,因为普通用户可能没有足够的权限执行 Docker 命令。
    • 计划 选项卡中:
      • 设置执行频率。建议每月运行 1-2 次(例如,每月 1 号和 15 号的凌晨 3 点)。Let‘s Encrypt 证书会在到期前 30 天才允许续期,所以不需要每天检查。
    • 任务设置 选项卡中:
      • 用户定义的脚本 框中,输入/bin/bash /volume1/docker/certbot/renew_cert.sh
  3. 验证自动续期是否工作

    1. 手动测试:在“任务计划器”中,找到您创建的任务,选中它并点击 运行。然后检查脚本输出的日志或去证书目录查看时间戳。
    2. 查看日志:脚本的执行日志会输出到您指定的位置。您也可以运行 docker logs certbot-renew(在任务运行时)来查看实时输出。
    3. 检查证书:续期成功后,/etc/letsencrypt/archive/您的域名/目录下会生成新的证书文件(如 cert2.pem, privkey2.pem),而 live目录下的符号链接会更新指向这些新文件。

使用证书

特性 方案A: 群晖DSM管理证书 方案B: Gitea容器管理证书
配置位置 群晖 控制面板 -> 安全性 -> 证书 Gitea 容器内部的 app.ini 配置文件
自动续期 无法自动续期,需手动下载新证书并重新导入 简单。指向Certbot的Live目录,续期后自动生效
管理方式 图形化界面,简单直观 需修改配置文件
影响范围 影响整个DSM系统及所有相关服务 仅影响Gitea一个服务
冲突风险 。两者是完全独立的
群晖中使用证书

控制面板 - 安全性 - 证书 - 新增 - 新增新证书 - 导入证书 - 导入私钥,证书,中间证书 - 确定

控制面板 - 安全性 - 证书 - 设置 - 将域名设置到对应的证书

为Gitea本身配置SSL证书

Gitea是直接安装在群晖Docker中的,您可以跳过群晖DSM的证书设置,直接为Gitea容器配置SSL

p.s. 必须是 Gitea Docker 容器内部 能访问到的路径,这个路径的设置要参考gitea容器本身部署的时候的文件映射

1
2
3
4
[server]
ROOT_URL = https://nas.xxxx.site
CERT_FILE = /ssl/live/nas.xxxx.site/fullchain.pem
KEY_FILE = /ssl/live/nas.xxxx.site/privkey.pem

因为gitea的文件夹映射为:/ssl --> /volume1/docker/certbot/etc/

所以 /ssl/live/nas.xxxx.site/privkey.pem ---> /volume1/docker/certbot/etc/live/nas.xxxx.site/privkey.pem

重启Gitea容器。这样Gitea服务本身就直接提供了HTTPS

Jenkins

🔄 Jenkins:灵活可扩展的自动化引擎

Jenkins 是一个开源的、高度可扩展的持续集成和持续交付 (CI/CD) 工具。它的核心价值在于自动化软件的构建、测试和部署流程。

  • 它能做什么

    • 自动化流水线:通过丰富的插件生态系统(超1800个插件),支持与各种工具(如 Git、Maven、Docker、Kubernetes 等)集成,实现高度定制化的构建、测试、部署自动化。
    • 流水线即代码:使用 Jenkinsfile(基于 Groovy)定义流水线,实现复杂流程的版本化和可重复性。
    • 分布式构建:支持主从(Master-Agent)架构,可在多台机器上分布式执行构建任务,提升效率。
  • 谁适合用

    • 需要高度定制化和控制其 CI/CD 流水线的团队。
    • 技术栈多样,需要与大量第三方工具集成的场景。
    • 需要注意的是,Jenkins 通常需要更多的维护和配置工作。

私有云平台

Nextcloud

☁️ Nextcloud:开源私有云平台

Nextcloud 是一个开源的文件同步与共享平台,允许你搭建属于自己的私有云服务。

  • 它能做什么

    • 文件同步与共享:类似 Dropbox 或 Google Drive,你可以在不同设备间同步文件,并与他人安全共享。
    • 丰富的应用生态:通过安装应用,可以扩展出日历、联系人管理、在线文档编辑(Collabora Online)、视频会议(Talk)、任务管理等众多功能,成为一个完整的协作平台。
    • 数据掌控与隐私:所有数据都存储在你自己的服务器上,无需担心第三方云服务的隐私问题。
  • 谁适合用

    • 对数据隐私和安全非常重视的个人、团队或企业。
    • 希望替代公有云服务(如百度网盘、Google Drive),完全掌控自己数据的用户。

copyparty

开箱即用的文件服务器

copyparty 最大的特色就是简单粗暴。整个服务器就是一个 Python 文件,不需要安装任何依赖,双击运行就能启动。

整个安装过程不到 30 秒,服务器启动后会自动监听 3923 端口,用浏览器打开 localhost:3923 就能看到熟悉的文件管理界面。

虽然在界面美观度和插件生态方面还比不上 NextCloud,但它的轻量简单易上手特性,让更多人能上手体验。

如果你正在寻找一个 “开箱即用” 的文件服务器解决方案,不妨试试这个只有一个文件的小工具。

GitHub 项目地址

域名相关

个人域名购买

费用范围:首年 50元 - 200元人民币

  • .com.net 等国际域名:约 60-120元/年(首年常有优惠)。

  • .cn 等国内域名:约 30-100元/年(需实名认证)。

  • 其他小众后缀(如 .xyz.site):可能低至 10元/年(促销时)。

  • 备注:续费价格通常高于首年价,需留意服务商续费政策。

热门后缀: com,cn,net 利于SEO收录和排名

冷门后缀: top,vip,love,icu 不利于SEO优化,但价格便宜

无限邮域名也可以使用

域名商

域名购买商 fxmjyxgs.net fengxingmuju.cn
Namesilo 15.95美金一年
namecheap 12.98美金一年
daomain 14.99美金一年
godaddy 1.04元首年
阿里云 10年 386
腾讯云
spaceship

spaceship 的.top 很便宜

spaceship 的 10年 6位数+ xyz后缀域名50元

阿里云买这个域名↑,10年一共67

免费可对接cloudflare的二级域名: dnshe

将购买的域名连接到Cloudflare

主要是为了利用cloudflare提供的CDN加速,安全防护(如DDOS防御),免费SSL证书等服务

通常有两种主要方式

  • 仅使用 Cloudflare 的 DNS 托管(更简单、可逆):只将域名的 DNS 解析服务器改为 Cloudflare 的,域名注册商仍是 GoDaddy
  • 将域名完全转移到 Cloudflare(更彻底):将域名的管理权从 GoDaddy 转移到 Cloudflare 注册商

对于大多数用户,推荐第一种方式(DNS 托管),因为它更简单快捷,且可逆

  1. 在 Cloudflare 账户主页 - 域 中添加域名
  • 输入从 GoDaddy 购买的完整域名(例如 yourdomain.com),然后点击”继续”
  • Cloudflare 会自动扫描该域名现有的 DNS 记录。请仔细核对,确保所有必要的记录(如 A 记录、CNAME 记录、MX 记录等)都已正确导入。也可以在此手动添加或修改记录
  • 选择套餐,免费计划通常足够个人使用。点击”继续”
  1. 更改 GoDaddy 的名称服务器(NameServers)
  • 这是最关键的一步。完成上一步后,Cloudflare 会提供两个(或更多)特定的名称服务器地址(通常类似于 lara.ns.cloudflare.com 和 vern.ns.cloudflare.com)。请完整准确地复制这些地址
  • 登录GoDaddy 账户,进入域名管理后台
  • 找到要管理的域名,点击”管理 DNS”或类似选项
  • 找到”名称服务器”(NameServers)设置部分
  • 选择”使用自定义名称服务器”(或类似选项),将 GoDaddy 默认的名称服务器删除,替换为 Cloudflare 提供的那两个地址
  • 保存更改
  1. 在 Cloudflare 完成并检查激活
  • 回到 Cloudflare 界面,点击”完成”或类似按钮
  • Cloudflare 会开始检查名称服务器更改是否生效。此过程最多需要 24-48 小时(DNS 传播时间),但通常几分钟到几小时内就会完成
  • 完成后,会收到 Cloudflare 的确认邮件,在 Cloudflare 仪表板上也能看到域名状态变为”有效”

关闭 DNSSEC:如果您之前在 GoDaddy 启用了 DNSSEC必须先将其关闭,否则在 Cloudflare 可能导致解析问题。您可以在 Cloudflare 添加域名成功后再重新配置 DNSSEC

SSL证书购买

免费证书(推荐个人使用):

  • Let’s Encrypt:完全免费,支持自动续期,适用于企业官网,个人博客和小型网站。

    • 证书有效期短:Let’s Encrypt证书仅90天有效(行业主流商业证书为1年),需定期续订。
    • 自动续订机制:可通过工具(如Certbot)实现自动化续期,几乎无需人工干预。
    特性 自签名证书 Let‘s Encrypt 证书
    颁发机构 自己给自己签发 Let’s Encrypt (一个受全球信任的非营利证书颁发机构CA)
    浏览器信任 不信任,会显示“不安全”警告 完全信任,显示绿色锁头或安全标识
    安全性 加密强度可以很高,但身份无法被第三方验证 加密强度高,且身份由可信的第三方(Let’s Encrypt)验证
    成本 免费 免费
    获取难度 自己一行命令生成,非常简单 需要验证您对域名的所有权(自动化的过程)
    有效期 可以任意设置,例如10年 很短(90天),强制要求自动化续期以提升安全
  • 服务商赠送:部分云平台(如阿里云、腾讯云)购买服务器时赠送免费SSL证书。

  • 付费证书:

    • DV证书(域名验证型):50-500元/年(适合个人)。
    • OV/EV证书(企业验证型):500-2000元/年(企业用途更多)。
  • 备注:个人网站建议优先选择免费证书。

  • DV证书(Domain Validation)
    ✅ ​适合:个人博客、小型网站、测试环境。
    ❌ ​不适用:涉及用户隐私、支付等敏感信息的网站。

  • OV证书(Organization Validation)
    ✅ ​适合:企业官网、电商平台、API服务。
    ❌ ​不适用:需要最高信任度的金融、政务场景。

  • EV证书(Extended Validation)
    ✅ ​适合:银行、支付平台、政府机构、大型企业官网。
    ❌ ​不适用:个人或非敏感业务(成本过高)

    EV证书的“绿色地址栏”在部分新浏览器(如Chrome 92+)中不再显示,但企业名称仍会展示在证书详情页

网站备案(ICP备案)

  • 费用免费(官方流程不收费)。

    代理服务费

    (可选):

    • 如果自行备案:0元(需自行准备材料并提交)。
    • 通过服务商代理备案:约 300-1000元(协助资料审核和流程处理)。
  • 耗时:约 10-20 个工作日(需配合管局审核)。

费用总结

  • 最低成本

    (自行操作):

    • 域名(50元) + 免费SSL(0元) + 备案(0元) ≈ 50元
  • 常规成本

    (含代理服务):

    • 域名(100元) + 免费SSL(0元) + 备案代理(500元) ≈ 600元
  • 高端配置

    (付费证书+代理服务):

    • 域名(200元) + 付费SSL(2000元) + 备案代理(500元) ≈ 2700元

DNS解析配置相关

如果需要将一个域名指向另一个域名

公网ip申请

难度评估

  • 中国移动: ipv4很难申请,拉专线
  • 中国联通: 一般般,打电话给客服
  • 中国电信: 一个月20元,就可以申请到公网ip

话术: 今天打开监控,发现我们家的那个公网ipv4地址怎么没有了?之前装监控的时候有公网呀

结果: 广东电信实测失败…

公网ip解决方案

方案 成本 速度 难度 适用场景
IPv6 + DDNS 免费 快(直连) 中等 外部设备支持 IPv6
FRP 自建穿透 高频访问、需自定义端口
Zerotier 组网 免费 中等 多设备互联、低频率访问
花生壳商业服务 低-高 中等 临时测试、小白用户

解决ipv4访问ipv6服务器的问题解决方案

方案 成本 实现难度 适用场景
双栈部署 企业有公网 IPv4/IPv6 资源
CDN 协议转换 快速兼容,适合大多数企业
NAT64/DNS64 实验性场景,依赖运营商支持
IPv4 回退服务 对兼容性要求极高的关键业务

通过 CDN/反向代理实现协议转换

  • 原理:使用支持 IPv4/IPv6 双栈的 CDN 或反向代理服务,将 IPv4 流量自动转换为 IPv6 请求。

  • 推荐工具:Cloudflare(免费版支持):

    1. 将域名 DNS 解析托管到 Cloudflare。
    2. 在 Cloudflare 中开启 IPv6 兼容性DNS 代理
    3. Cloudflare 边缘节点会同时响应 IPv4/IPv6 请求,并将流量转发到公司的 IPv6 源站。
    • Nginx 反向代理(自建):nginx

      1
      2
      3
      4
      5
      6
      7
      8
      9
      # 在具备双栈的代理服务器上配置
      server {
      listen 80; # IPv4
      listen [::]:80; # IPv6
      server_name example.com;
      location / {
      proxy_pass http://[公司IPv6源站]:80;
      }
      }

    优点:

    • 无需公司源站支持 IPv4。
    • CDN 可缓存内容,提升访问速度。
  • 缺点:依赖第三方服务(如 Cloudflare)或自建代理服务器。

替代方案

  • 若只需临时、低速访问DSM管理Docker:可使用QuickConnect,它适合临时从外网登录DSM后台来管理容器启停和设置
  • 若有公网IP且追求最佳速度:可考虑端口转发。但务必注意网络安全风险,仅映射必要端口,并使用强密码和非标端口号
  • 若要暴露Web服务(如博客、导航页)Cloudflare Tunnel是首选。它无需公网IP,能自动提供HTTPS证书,安全性较好。
  • 若需访问所有协议的服务(如SSH、远程桌面、私有数据库)Tailscale等零信任网络方案是最佳选择。它能在所有设备间建立加密通道,像在局域网内一样安全访问所有服务,配置也不复杂

IPv6

可以用IPv6开+cloudflare cdn代理支持IPv4,待后续了解

不同ipv6地址特征

地址类型 前缀范围(十六进制) 用途 是否可全球路由
全球单播地址 (公网IPv6) 2000::/3(如 2001:, 2408:, 2409:, 240e:) 全球唯一,可直接访问互联网
唯一本地地址 (ULA, 内网IPv6) fc00::/7(通常 fd00::/8) 类似IPv4的私有地址,限本地网络使用
链路本地地址 fe80::/10 仅在同一物理链路有效(如局域网通信)

查看是否支持ipv6

  • Windows系统:打开命令提示符(CMD)或 PowerShell,输入 ipconfig,查看以 “IPv6 地址” 标识的条目。
  • Linux/macOS系统:打开终端,输入 ip -6 addr showifconfig,查看网卡信息。

在输出信息中,寻找那些不以 fe80fd开头的IPv6地址。如果你看到的IPv6地址是以 2001:2408:2409:240e:等开头的(属于 2000::/3范围),这很可能就是一个公网IPv6地址

使用在线工具测试

通过访问一些支持IPv6的测试网站,可以快速验证你的公网IPv6连通性和显示的地址。

  • 访问 test-ipv6.comipv6-test.com
  • 网站会自动检测你的IPv6连接状态。如果页面显示 “IPv6 访问优先”、给出了一个完整的IPv6地址(并且这个地址与你之前查看到的、以2xxx3xxx开头的地址一致),或者测试分数很高(如10/10),就说明你已成功连接到IPv6互联网,并且该地址是公网地址

路由器开启ipv6支持

以tplink企业路由器为例

  1. 首先需要在基本设置 - LAN设置中启用ipv6

    image-20250915114858281
  2. 然后需要在基本设置 - LAN设置 - SLAAC中启用服务

    image-20250915114935926

当开启SLAAC后,DHCPv6服务的开关变为不可操作的状态,这并非故障,而是TP-LINK路由器的一种智能设计。它强制用户采用业界推荐的 “SLAAC + 无状态DHCPv6” 的协同工作模式

功能 负责内容 当前状态
SLAAC 分配IPv6地址(解决“我是谁”) 已开启,工作正常
DHCPv6 分配DNS等信息(解决“如何找到别人”) 被SLAAC联动开启,无需单独操作

然后就可以在基本设置 - LAN设置 - IPV6客户端列表中查看ipv6的地址分配情况

群晖nas开启ipv6

控制面板 - 网络 - 网络界面 - 找到正在使用的局域网,右键 - 编辑 - IPv6 - IPv6设置改为自动 - 确定

解决动态变化的IPv6地址

IPv6地址是动态变化的

  • 虽然运营上粉皮儿的IPv6前缀通常比较固定,但设备通过SLAAC生成的地址后缀可能会变(尤其是隐私拓展地址)
  • 解决方案: 为需要访问的设备(如NAS)配置静态IPv6地址

内网穿透方案

参考内网穿透

内网穿透

服务名称 免费带宽 免费流量 免费隧道数 实名认证 支持协议 特点与注意事项
cpolar 1Mbps 不限流量 4条 TCP、HTTP、HTTPS 流量不限是显著优势,带宽适中,隧道数较多,每 24 小时会变化的公网地址(付费解决)
Sakura Frp 10Mbps 每月5GB 2条 TCP、UDP、HTTP、HTTPS 免费带宽较大,通过每日签到可获取额外免费流量
NATAPP 1Mbps 不限流量 2条 TCP、HTTP、HTTPS 不限流量,但免费版域名或端口可能不定时强制更换
花生壳 1Mbps 每月1GB 2条 TCP、HTTP、HTTPS 老牌服务,需6元认证费,免费版流量较少
飞鸽 0.5Mbps 不限流量 1条 TCP、HTTP、UDP 带宽较低,解压即用无需安装,适合临时轻量级需求

备选方案:自建内网穿透:如果你拥有一台具有公网IP的云服务器(国内或海外均可),可以考虑使用 FRPOpenVPN 等开源工具自建内网穿透服务。这种方式前期投入较高(需要服务器成本),但长期来看更灵活、可控,且无商业服务的额度限制

对于绝大多数个人用户——无论是远程访问家庭NAS、调试开发中的Web项目,还是运行一个小型博客——Cloudflare Tunnel 免费版提供的带宽和无限流量是完全足够且非常划算的

cloudflare方案

cloudflare的域名安全配置:

1️⃣进入 SSL/TLS 设置

  1. 进入域名管理,左侧菜单栏点击 SSL/TLS
  2. 默认进入 概述 页面,找到 SSL/TLS 加密模式
  3. 点击 配置 进入详细设置。

2️⃣ 选择合适的 SSL/TLS 模式

  1. 默认 SSL/TLS 模式为 “灵活”

    ,需要改成:

    • 完全(Full):适用于一般场景(安全性较高)。

      风险: 内网中可能面临中间人攻击风险,如果有这种风险,需要采用下面的完全(严格)模式

    • 完全(严格)(Full (strict)):适用于指向服务器的域名,但服务器需安装有效 SSL 证书。(可以使用Let’s Encrypt 证书,搭配90天自动续期服务)

  2. 如果域名不指向服务器,仅做跳转或解析,可选择“完全”模式

  3. 点击保存,完成 SSL/TLS 加密设置。

3️⃣ 开启边缘证书(Edge Certificates)

  1. 点击 “边缘证书” 选项
  2. Cloudflare 会自动申请并管理 托管证书
  3. 下拉找到 “始终使用 HTTPS” 选项,点击 开启(可选,但推荐)。
  4. 这样可以确保所有 HTTP 请求都自动跳转到 HTTPS,提高安全性

p.s. 可通过 SSL Labs 测试工具 验证加密强度

参考视频教程

参考博客

Zero Trust: cloud flare提供的内网穿透服务

必须现有一个托管在cloudflare的域名

Zero Trust界面中 - 网络 - Tunnels - 添加隧道 - 选择Cloudflared

按照安装要求进行相应安装cloudflare连接器,然后就可以转到隧道管理中配置内网穿透的具体服务了:

image-20250428165816614

就可以实现内网穿透了

但是要注意内网穿透没法将设备直接暴露到公网,只能暴露某个端口

群晖部署Cloudflare Tunnel

Cloudflare Tunnel能把 NAS 低频访问的内网服务,用最低成本稳定暴露到外网。关键数据全程 SSL 加密,比自建 FRP 省了服务器钱还不用操心 DDoS 防护‌

使用outlook邮箱可以无手机注册

然后再试用outlook账号注册cloudflare

要先在cloudflare新建隧道,新建后继续下面的步骤

群晖通过docker部署cloudflare隧道连接器

docker部署gitea参考

  1. 下载镜像: 打开群晖的 Container Manager,进入“镜像仓库”页面;搜索 cloudflare/cloudflared,选择并下载 latest (最新) 标签的镜像

  2. 创建容器: 在“映像”中找到下载好的 cloudflare/cloudflared镜像,点击“启动”

  3. 按照下面进行配置

image-20250912151754618

注意网络一定要设置为host模式,命令要设置为tunnel run

总结一下配置

选项卡 设置项 推荐配置
执行命令 Entrypoint cloudflared --no-autoupdate(保持不变)
命令 tunnel run
环境 变量 (新增) TUNNEL_TOKEN
值 (新增) eyJhIjoi...(您的真实Token)
网络 网络模式 建议选择“使用与 Docker Host 相同的网络”

配置完成后需要告诉cloudflare哪个公网域名对应哪个内网服务

  1. 在 Cloudflare Zero Trust 面板中,进入你刚创建的隧道的配置页面。
  2. 点击 “Public Hostnames” 选项卡,然后点击 “Add a public hostname”
  3. 配置你的服务映射:
    • Subdomain: 输入你喜欢的子域名前缀,如 nasdsm
    • Domain: 从下拉菜单中选择一个你托管在 Cloudflare 上的域名。
    • Service: 选择 HTTPHTTPS
    • URL: 填写你的群晖服务在内网的地址和端口。例如:
      • 访问 DSM 管理界面: http://localhost:5000
      • 访问 Docker 中的某个 Web 服务: http://localhost:3000
  4. 点击“Save”保存。现在,你就可以通过你配置的公网域名(例如 https://nas.yourdomain.com)安全地访问内网服务了

到此就部署成功了

验证连接的命令

1
2
3
4
5
6
# 检查 tunnel 状态
docker exec <cloudflared-container> cloudflared tunnel list
docker exec <cloudflared-container> cloudflared tunnel route ip show

# 测试 tunnel 连接
docker exec <cloudflared-container> cloudflared tunnel test zeroko.site

docker网络配置问题,确保cloudflared容器能访问其他容器

1
2
3
4
5
6
7
8
# 检查容器网络
docker network ls
docker inspect <nginx-container> | grep IPAddress

# 从 cloudflared 容器内部测试 nginx 连接
docker exec <cloudflared-container> curl -v http://nginx:8080
# 或者使用容器 IP
docker exec <cloudflared-container> curl -v http://<nginx-ip>:8080

Cloudflare Tunnel 认证问题: 重新验证tunnel凭据

1
2
3
4
5
# 重新登录 Cloudflare(如果需要)
docker exec <cloudflared-container> cloudflared tunnel login

# 重新创建凭据文件
docker exec <cloudflared-container> cloudflared tunnel create zeroko-site-tunnel

自建服务器内网穿透

使用 frpngrok 将宿主机端口映射到公网

无限邮域名

参考链接

在spaceship购买无限邮域名,site后缀会特别便宜

另外免费方式: 在cloudflare上配置一个域名,然后找到电子邮件配置邮件路由就可以

配置方式,在spaceship上配置非常简单,如果是在cloudflare稍微复杂一些,即使托管到cloudflare,也可以使用spaceship本身的邮箱转发功能,虽然cloudflare本身其实也支持

技巧记录

ssh -o ProxyCommand="none" Qian0407@192.168.8.6绕开代理,连接ssh,不然会显示ssh被127.0.0.1断开连接

路由器配置

静态ip注意

路由器的客户端列表不会显示所有设备的ip地址,如果是静态设置(手动配置ip地址的设备)在客户端列表中不可见

特性 静态地址分配 (DHCP保留) 静态设置 (手动配置)
配置位置 路由器的管理界面 每台终端设备的操作系统内
管理方式 集中式管理,所有IP在一个地方分配和查看 分散式管理,需要登录每台设备修改
可靠性 非常高。IP地址由权威的DHCP服务器分配,绝对不会有冲突。 较低。容易因人为失误导致IP冲突,造成网络中断。
灵活性 。更改IP地址只需在路由器上操作,设备无感知。 。更改IP需要逐台设备操作,非常繁琐。
迁移性 。设备拿到新网络会自动获取新IP,无需重新配置。 。设备换网络后仍需手动设置,否则无法上网。
所需知识 较低。只需知道设备的MAC地址。 较高。需要正确填写IP、子网掩码、网关、DNS。
推荐场景 绝大多数情况,尤其是家庭、中小企业环境。 极特殊情况,如:无DHCP服务的纯静态网络、网络设备(交换机、路由器自身)、临时测试。

路由器防火墙

一般被称为虚拟服务器

将某个内网ip的某个端口对外开放

网络设备盘点

云管理交换机

VLAN

VLAN(Virtual Local Area Network,虚拟局域网)最核心、最根本的作用是可以实现”将一个物理交换机虚拟成多个独立的逻辑交换机”的效果

工作原理

  • 传统交换机(无VLAN): 所有端口都处于同一个广播域中。一台电脑发送的广播数据包(如ARP请求),会被交换机转发给所有其他端口上的设备。整个交换机就像一个大的、开放的房间,大家都能听到彼此的喊话。
  • 启用VLAN的交换机: 您可以将不同的端口划分到不同的VLAN中。例如:
    • 将端口1-8划分到 VLAN 10(比如给财务部使用)
    • 将端口9-16划分到 VLAN 20(比如给市场部使用)
    • 效果: 此时,VLAN 10和VLAN 20就相当于两个完全独立的虚拟交换机。
      • 广播隔离: 一台连接在VLAN 10端口上的电脑发送广播包,这个包只会被转发到其他属于VLAN 10的端口。VLAN 20的端口完全收不到任何VLAN 10的流量,反之亦然。
      • 通信隔离: 即使两台电脑都接在同一台物理交换机上,但如果它们属于不同的VLAN,它们之间默认也无法直接通信,就像接在了两台完全不同的交换机上一样。

TL-SG2024D

说明书 tplink云管理交换机用户手册

TP-LINK全新开发推出的“云交换系列”全千兆云管理交换机,提供更为高效、简单、安全、易用的远程管理方式,支持智能开局、自动配置组网、异常告警等功能,无需专业IT运维人员,小白也能轻松上手;采用新一代高性能硬件和软件平台,提供灵活、高性价比的全千兆端口,支持灵活的802.1Q VLAN、端口监控、端口汇聚、QoS、带宽控制等基础网络管理功能,易于管理维护,适用于校园、酒店及企业园区网络接入应用场景

一键切换工作模式

  • 云管理模式:交换机支持VLAN、端口汇聚、端口监控等网管功能,可以通过商云APP、商用网络云平台、本地界面进行管理和维护。
  • VLAN隔离模式:交换机不支持网管功能,并且部分端口相互隔离,详⻅安装手册相关说明。
  • 标准交换模式:交换机不支持网管功能,并且所有端口均可以自由通信

网络指令

路由表查看

操作系统 核心指令 补充参数/说明
Windows route print -4:仅看IPv4路由
-6:仅看IPv6路由
Linux/macOS route -n -n:不解析域名,加快速度(工业环境推荐)
ip route show:更现代的路由查看方式(Linux专属)
Cisco设备 show ip route 工控网络中交换机/路由器常用,可加网段筛选如show ip route 192.168.8.0

路由追踪

操作系统 核心指令 常用参数/说明
Windows tracert -d:不解析域名(内网优先用)
-h 跳数:指定最大跳数(如-h 10)
-w 毫秒:设置超时时间(如-w 2000)
Linux/macOS traceroute -I:使用ICMP协议(同Windows tracert)
-T:使用TCP协议(排查端口拦截)
-n:不解析域名
简化替代(跨平台) mtr 结合ping和traceroute的实时追踪工具,Linux需安装mtr包,Windows可下载第三方版本

测试连通性

操作系统 核心指令 常用参数/说明
Windows ping 目标IP/域名 -t:持续ping,按Ctrl+C停止
-n 次数:指定ping的次数(如ping -n 5 192.168.8.201)
Linux/macOS ping 目标IP/域名 -c 次数:指定ping的次数(如ping -c 5 192.168.8.201)
-i 间隔:设置ping包发送间隔(秒)
Cisco设备 ping 目标IP repeat 次数:指定ping次数(如ping 192.168.8.201 repeat 5

查看网卡信息

操作系统 核心指令 常用参数/说明
Windows ipconfig /all 显示所有网卡详细信息”
ipconfig /release:释放IP”
ipconfig /renew:重新获取IP
Linux/macOS ifconfig(传统)
ip addr show(现代)
ifconfig 网卡名:查看指定网卡信息(如ifconfig eth0)”
ip addr show eth0:同上(Linux专属)
Cisco设备 show ip interface brief 查看接口IP、状态简要信息”
show interfaces 接口名:查看指定接口详细信息

端口连通性测试

操作系统 工具/命令 用法示例 工具说明
Windows telnet telnet 192.168.8.201 80 需手动开启Windows“Telnet客户端”功能,仅返回连接状态volume
Windows Test-NetConnection Test-NetConnection 192.168.8.201 -Port 80 PowerShell专属工具,无需额外配置,直接返回端口通断结果volume
Linux/macOS telnet telnet 192.168.8.201 80 基础端口测试工具,部分系统需手动安装volume
Linux/macOS nc(netcat) nc -zv 192.168.8.201 80-88 功能强大的网络工具,-z扫描端口,-v输出详细信息,支持端口段扫描volume
Cisco设备 telnet telnet 192.168.8.201 80 部分型号支持,用于测试设备间端口连通性volume
Cisco设备 test tcp-connect test tcp-connect 192.168.8.201 80 专用端口测试命令,返回明确的连接成功/失败提示volume

局域网扫描工具

特性维度 Angry IP Scanner Advanced IP Scanner
macOS 支持 明确支持 (Linux, Windows, Mac OS X) Windows
免费性 完全免费 (开源) 免费
主要功能特点 快速扫描IP地址和端口、支持自定义IP范围、数据导出、插件扩展、命令行界面 快速扫描局域网设备、显示设备信息(IP, MAC地址)、远程开关机(WOL)、访问共享资源
用户友好性 界面简洁,提供图形界面和命令行界面 强调易于使用,提供图形化界面
额外优势 跨平台兼容性佳、无需安装(便携版)、开源 绿色免安装、支持Radmin远程控制
官网 官网 官网

运维终端工具

部署问题盘点

群晖默认nginx与docker nginx端口冲突

常见解决方案:

  • 释放默认端口,通过修改DSM的Nginx配置,将80/443改成其他端口,比如8080/8443. 注意 DSM 系统升级可能会恢复配置,需使用计划任务定时执行脚本 参考做法: 群晖 DSM 停用内置 Nginx

  • 使用独立 IP:给反向代理容器分配一个单独的局域网 IP(如通过 Docker macvlan),使它不与 DSM 共享 IP。这样反向代理可以在该 IP 的 80/443 上运行,而 DSM 自带服务绑定在另一 IP 上。例如 Andy 的案例中,他将 NPM 容器分配到 192.168.0.201,让它独立监听 80/443 。下图示意了这种网络布局:Docker 容器和 DSM 主机各自拥有不同 IP,反向代理可独占端口。参考做法

  • 更换端口:如果不想改系统 Nginx,可以让容器监听其他端口(如 8443、8080),并在 DSM 侧进行端口映射或转发。不过这样访问时需要指定非标准端口,或使用额外的 HTTP 到 HTTPS 转发(如 stream 模块或 DSM 自带转发)

    stream方案注意:

使用独立IP方案

  1. SSH登录到群晖NAS,查看宿主机的物理网卡名ip link,通常是 eth0 或者类似 ovs_eth0(取决于你是否用了群晖的虚拟网络层)

  2. 创建一个 Macvlan 网络

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker network create -d macvlan \
    --subnet=192.168.8.0/24 \
    --gateway=192.168.8.1 \
    -o parent=eth0 \
    macvlan_net
    # --subnet:局域网的子网
    # --gateway:局域网网关
    # parent=eth0:替换为你实际的物理网卡名
    # macvlan_net:这个是网络的名字,可以自己定义
  3. 启动容器并绑定独立 IP

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker run -d \
    --name my-nginx \
    --network macvlan_net \
    --ip 192.168.8.115 \
    -v /path/to/nginx.conf:/etc/nginx/nginx.conf \
    -p 80:80 -p 443:443 \
    nginx:latest
    # --ip 192.168.8.115:这是容器在局域网的固定 IP
    # -p 可以省略,因为容器直接在独立 IP 上监听,不需要映射到宿主机
  4. 配置域名解析

    在路由器或本地 DNS 中,把 nas.jhh1.site 解析到 192.168.8.115

注意事项

  • 宿主机访问容器问题:Macvlan 模式下,宿主机(群晖本身)默认不能直接访问这个容器 IP。如果需要 DSM 本身访问容器(例如 DSM 的备份任务访问 192.168.8.115:443),你需要再建一个 macvlan bridge 或者用 ipvlan 替代。
  • 防火墙:检查群晖和路由器的防火墙设置,确保放行 80/443 到 192.168.8.115。
  • DHCP 冲突:务必在路由器 DHCP 池之外选择 IP,或者在路由器里给容器 IP 做静态绑定。

macvlan

简单定义:macvlan 是 Docker(Linux 内核)的一种网络驱动,把容器虚拟成网络上的独立设备:每个容器拥有自己的 MAC 地址和 IP,像一台真实主机那样直接出现在 L2 网络上(交换机能识别它的 MAC)。

物理网口,即使是两个网口各自有独立的ip地址,也会在nginx层面涉及到互相之间端口占用的影响,而使用macvlan方案是真正意义上可以不互相占用的

解决的问题:当你想让容器直接在局域网中拥有独立 IP(并可以占用标准端口 80/443),而不与宿主机(群晖 DSM 自带服务)端口冲突时,macvlan 非常合适。

应用场景:反向代理(Nginx)直接对外提供 HTTPS;把容器暴露成局域网内独立服务;在多服务/多 IP 下避免端口冲突。

工作原理

  • macvlan 在宿主物理网口上创建虚拟网口(子接口),容器的网口直接挂在这个虚拟网口上,容器发出的帧带自己的 MAC,物理交换机会像对待物理主机一样转发。
  • parent:你需要指定一个物理网卡作为 parent(例如 eth0, bond0, ovs_eth0 等),macvlan 会基于它创建虚拟接口。
  • 主机与容器隔离:宿主机(host)默认不能直接访问 macvlan 上的容器 IP(因为主机和容器处于不同的 L2 接口)。这通常是优点(隔离),但也带来需要额外配置以便 host 访问的尴尬。
  • 支持 VLAN(如果你的网络需要 802.1Q 标签,可以在 parent 上用子接口如 eth0.10)。

优缺点

优点

  • 容器看起来像局域网内真实主机:直接使用标准端口 80/443,不需要宿主端口映射。
  • 几乎原生网速,延迟低(无 DNAT/SNAT)
  • 便于把容器放到已有网络策略 / 路由里(如静态 IP、路由器防火墙规则等)

缺点 / 限制

  • 宿主机默认无法访问容器 IP(需要特殊配置才能从 DSM 访问容器的 IP)。
  • 一些家用路由器 / 交换机或 ISP 提供的设备可能会限制一个物理端口上的多个 MAC,或者对 Wi-Fi 客户端行为不友好(尤其某些 ISP 网关或 Wi-Fi 中继)。
  • 容器在网络上直接可见,安全性依赖你在容器内配置的防护(而不是 Docker NAT 隔离)。
  • 需要知道宿主机物理接口名称,并具有对其操作权限(在群晖上需要 SSH)。

替代方案说明

  • host 网络模式:容器直接和宿主共享网络栈(能访问 host 的接口),但你无法分配独立 IP。
  • ipvlan:与 macvlan 类似,但在某些场景(比如需要更低开销)更合适;此外 ipvlan 在 host <-> container 通信上有不同行为。一般入门用 macvlan 更直观。

使宿主机能和macvlan容器互通(可选)

如前所述,macvlan 默认内核会阻止宿主和其 macvlan “子设备”互通(这是内核设计/安全隔离),若你需要从 NAS 上直接访问/调试容器(或容器访问 NAS,只是局域网内别的机器能访问容器就行),需要在宿主上建立一个 macvlan 虚拟接口(shim)并给它一个 IP(通常是 –aux-address 保留的那个)。这是社区推荐的解决办法

示例命令(继续用上面假设):

1
2
3
4
5
6
# 创建 macvlan 虚拟设备(仅在内存,不会重启后保留)
ip link add macvlan-shim link ovs_eth0 type macvlan mode bridge
ip addr add 192.168.8.199/32 dev macvlan-shim # 这个 IP 同 aux-address 保持一致
ip link set macvlan-shim up
# 告诉宿主到容器网段走 macvlan-shim(ip-range)
ip route add 192.168.8.200/29 dev macvlan-shim

验证:宿主上 ping 192.168.8.200(容器 IP)应该可达(容器已运行的情况下)

持久化:上面这些命令是临时的,重启会丢失。建议用 DSM 的 控制面板 → 任务计划程序 新建一个“开机/登录时运行”的任务,以 root 身份运行一个小脚本来恢复这几个 ip link / ip addr / ip route(脚本示例我会在下面给出)

运维可部署项目盘点

SafeLine开源Web防火墙

100+格式在线预览开源项目,支持Windows、Linux平台一键部署,两行js代码就可以接入预览,kkFileView

现代防火墙 免费额度: 300,000 次查询/月

0成本快速部署网站开源项目PinMe,可用于临时快速部署AI生成的vue和React项目等,还可以集成到GitHub Actions中,实现代码一推送就自动构建和部署

App2Docker一键将应用打包成 Docker 镜像的可视化平台,支持 Java(JAR)、Node.js、Python、Go、静态网站等多种应用类型,提供 Web 界面操作,无需编写 Dockerfile 支持CICD自动构建镜像 参考文档

一个开源的服务监控平台,通过 GitHub Actions 去监控服务是否正常在线

数据库相关

开源数据库备份,支持mysql/PostgreSQL,不支持sql server

1panel

性能调优

Linux性能调优参考

25个Linux系统性能调优技巧

运维软件盘点

高性能日志查看器和处理器,可将 JSON 和 logfmt 格式的日志转换为人类可读的输出。该工具以高效为设计理念,能够以最小的开销快速解析和分析大型日志文件

免费域名盘点

子域名netlib.re 最大的用处其中之一,可以用于国内访问vercel部署的网站

监控相关

专为云原生环境(如微服务,容器化应用)设计的监控系统Prometheus,已成为了监控领域的事实标准

Prometheus 生态中独立的警报处理配套拓展组件 Alertmanager

[[虚拟化网络模型#K8S|Kubernetes]] 和 Prometheus 是云原生领域最著名的“黄金搭档”

  • Kubernetes 负责管理和运行容器化的应用程序。
  • Prometheus 在 Kubernetes 集群上部署和运行 Prometheus,用于监控包括 Kubernetes 集群本身的健康状态(节点、调度器等的指标)以及运行在其中的所有应用程序的性能指标。
  • 需要报警相关功能,需要单独部署 Alertmanager,并配置 Prometheus 与其通信

Doris分布式高性能实时大数据分析数据库

邮箱注册功能

推荐使用Resend 每月3000额度使用,推荐注册功能代培谷歌登录一起使用,均使用Better Auth服务来封装调用

防火墙配置相关

windows

以管理员身份运行 PowerShell (开放3000端口的案例)
New-NetFirewallRule -DisplayName "Docker 3000" -Direction Inbound -Protocol TCP -LocalPort 3000 -Action Allow

Windows公用/专用/域网络详解

Windows 里的「公用网络」「专用网络」「域网络」,官方名称为网络位置配置文件(Network Location Profile),是 Windows Defender 防火墙内置的三套完全独立、互相隔离的安全规则体系

系统会根据你连接的网络环境,自动加载对应的配置文件,一键切换整套防火墙安全策略,核心设计逻辑是:给不同信任度的网络,匹配对应强度的安全防护,兼顾内网协作的便捷性与公网环境的安全性

补充说明:Windows 7 时代的「家庭网络」「工作网络」,在 Windows 10/11 中已全部合并为「专用网络」,逻辑完全一致。

对比维度 专用网络 公用网络 域网络
核心适用场景 家庭、信任的小型办公内网 公共 Wi-Fi、陌生不可控网络 企业 AD 域办公内网
安全防护等级 中等(信任优先) 最高(安全优先) 企业定制化(合规优先)
默认入站规则 阻止陌生流量,放行内网协作规则 全部拦截未经请求的入站流量 由域组策略统一定义
网络发现 默认开启 默认完全关闭 域内默认开启
文件 / 打印机共享 默认开启 默认完全关闭 域内默认受控开启
新网络默认选项 否,需手动切换 是,所有新网络默认标记 否,仅域认证通过后自动激活
规则管控权 本地管理员可修改 本地管理员可修改 域控制器统一下发,本地无权修改
规则隔离性 仅当前专用网络生效 仅当前公用网络生效 仅域环境内生效,离开自动失效

核心底层逻辑:规则 100% 隔离

三个配置文件的防火墙规则是完全独立、互不干扰的,这是整个体系的核心设计:

  • 你在专用网络里创建的入站放行规则(比如远程桌面、文件共享),默认仅对专用网络生效,切换到公用网络后,这条规则会自动禁用,不会把内网的宽松权限带到公网环境;
  • 每个 Wi-Fi / 有线网络的配置文件标记是独立的:比如家里的 Wi-Fi 设为专用,公司的 Wi-Fi 设为公用,咖啡厅的 Wi-Fi 设为公用,切换网络时自动加载对应配置,互不影响

查看 / 切换当前网络的配置文件

Windows 11 操作步骤

  1. 点击右下角任务栏的网络 / Wi-Fi 图标,打开快速设置面板;
  2. 点击当前连接网络右侧的「i」(详情)图标,进入网络属性页;
  3. 在「网络配置文件类型」区域,直接点选「专用」或「公用」即可完成切换。

Windows 10 操作步骤

  1. 点击右下角任务栏的 Wi-Fi 图标,打开网络列表;
  2. 点击当前已连接的网络,选择「属性」;
  3. 在「网络配置文件」区域,选择「专用」或「公用」完成切换。

windows首次应用启动弹框是否允许

当应用首次尝试创建监听套接字listen () 系统调用,也就是要开放本地端口、接受外部设备的入站连接时,才会触发这个弹窗

弹窗触发的完整底层流程

整个机制完全基于 WFP(Windows 筛选平台)的 ALE 层(应用层强制层)实现,和你之前了解的规则层级完全契合,触发时序如下:

  1. 应用发起监听请求:应用启动后,调用 Windows 系统 API 创建 TCP/UDP 监听端口,准备接受外部入站连接;
  2. ALE 层拦截校验:请求进入 WFP 的 ALE 层(入站流量最终校验关口、程序级规则唯一生效层),防火墙会执行 3 项核心检查:
    • Windows 防火墙是否处于开启状态(关闭则直接跳过,不弹窗也不拦截);
    • 系统中是否已存在针对该应用.exe 的入站规则(允许 / 阻止均可);
    • 防火墙的入站通知功能是否开启(默认开启);
  3. 弹窗触发条件达成:当「防火墙开启 + 无对应现成规则 + 通知功能开启」三个条件同时满足时,ALE 层会临时阻止该应用的入站监听请求,同时通过 MpsSvc(防火墙核心服务)向当前登录用户弹出授权通知;
  4. 等待用户授权决策:在用户点击「允许访问」/「取消」前,该应用的入站连接始终被默认阻止,不影响应用的出站联网能力。

用户选择后的规则生成逻辑

用户的每一个选择,都会直接对应防火墙入站规则的变更,完全遵循之前讲的规则优先级体系:

选择「允许访问」(勾选对应网络类型)

  • 系统会自动在入站规则库中生成一条永久生效的允许规则,路径为:wf.msc → 入站规则,可直接查看编辑;
  • 自动生成的规则核心配置:
    • 匹配维度:精准绑定应用的完整.exe 程序路径,无端口 / IP 限制,默认放行该应用的所有 TCP/UDP 入站流量;
    • 生效范围:仅对用户勾选的网络配置文件(专用 / 公用网络)生效,默认勾选「专用网络」(家庭 / 办公内网),「公用网络」默认不勾选;
    • 优先级:和手动创建的允许规则完全一致,低于阻止规则,高于全局默认阻止规则;
  • 后续效果:该应用再次启动时,不会再弹出通知,直接按已生成的规则放行入站连接。

选择「取消」/ 直接关闭弹窗

  • 系统不会生成任何允许规则,也不会生成阻止规则;
  • 后续效果:该应用的入站连接继续按防火墙全局默认规则执行(入站默认全部阻止);应用下次再次发起监听请求时,会重新弹出授权通知。

特殊情况:管理员权限运行的应用

  • 若应用以管理员权限安装 / 启动,安装程序可通过管理员权限,提前自动创建防火墙入站规则;
  • 这种情况下,应用首次启动时不会弹出任何通知,直接按预设规则放行入站连接,这也是很多大型游戏、专业软件不弹该窗口的核心原因。

防火墙规则过滤优先级

系统 底层核心框架 具体规则分级(优先级从高到低)
Windows WFP(Windows 筛选平台) 1. 域组策略(GPO)规则:全局最高优先级,企业 AD 域控制器下发,强制覆盖所有本地规则,本地用户无法修改
2. 本地组策略 / 安全策略规则:优先级高于本地控制台配置的规则,仅本地管理员可编辑
3. 显式阻止规则(Block):同策略集内优先级最高,匹配即一票否决,直接终止流量处理,无视所有冲突的允许规则
4. 显式允许规则(Allow):仅无匹配阻止规则时生效,同动作下按匹配精度排序,维度越精准优先级越高:程序路径+IP+端口+协议 > 端口+IP+协议 > 纯端口/纯IP规则
5. 网络配置文件默认规则:兜底规则,未匹配任何自定义规则时生效,对应公用 / 专用 / 域网络的默认行为(入站默认阻止,出站默认允许)
Linux Netfilter + 可选 LSM(AppArmor/SELinux) 1. LSM 安全模块规则:全局最高优先级,AppArmor/SELinux 在内核进程发起网络系统调用时生效,进程级管控,拦截后数据包不会进入协议栈,完全无视 Netfilter 所有规则
2. Netfilter 表优先级规则:按表的固定优先级执行,从高到低为 raw → mangle → nat → filter,高优先级表的规则先匹配执行
3. 链时序规则:同表内按数据包流转的固定时序匹配,先经过的链先执行规则(如出站流量先匹配 OUTPUT 链,再匹配 POSTROUTING 链)
4. 同链内带终止动作的规则:同链内规则按从上到下的顺序匹配,匹配到 DROP/ACCEPT 等终止动作时,立即终止后续规则遍历,先匹配先执行
5. 链默认策略规则:兜底规则,数据包未匹配同链内任何自定义规则时,执行链的默认策略(ACCEPT/DROP)
Mac 应用沙盒 → 应用防火墙 → PF(Packet Filter) 1. App Sandbox 沙盒权限规则:全局最高优先级,内核级进程权限管控,App Store 应用强制启用,无网络权限的应用直接被禁止创建 socket,数据包不会进入后续过滤环节
2. Application Firewall 应用防火墙规则:系统原生应用级管控规则,基于 Socket Filter 框架实现,匹配即终止,优先级完全碾压底层 PF 端口规则
3. PF 带 quick 关键字的规则:底层包过滤层最高优先级,匹配到后立即执行动作,终止后续所有规则遍历
4. PF 普通规则(无 quick 关键字):全量遍历所有规则后,执行最精准匹配的规则
5. PF 默认策略规则:兜底规则,未匹配任何自定义规则时执行默认动作

通用优先级铁律:三个系统均遵循「应用 / 进程级规则优先级 > 端口 / IP 级规则优先级」,Windows/Mac 为原生内置的层级设计,Linux 原生 Netfilter 需通过规则顺序或 LSM 安全模块实现。

  • Windows 独有特性:全局「阻止规则绝对优先」,不受规则顺序、匹配精度影响,只要命中阻止规则直接拦截;仅同动作下才按匹配精度排序。
  • Linux 独有特性:Netfilter 无全局动作优先级,同链内完全由规则上下顺序决定,先写先匹配;仅 LSM 能实现全局的进程级优先拦截,也是最容易被忽略的层级。
  • Mac 独有特性:三层架构完全隔离,上层应用级规则与底层 PF 规则完全独立,上层拦截的流量根本不会进入 PF 层,PF 端口规则完全无法覆盖上层应用管控。

Windows规则优先级

顶层决策:动作优先级层级

优先级层级 规则类型 核心执行逻辑
1(最高) 显式阻止规则(Block) 只要流量匹配任意一条阻止规则,直接终止整个匹配流程,执行拦截动作,丢弃数据包,完全无视所有与之冲突的允许规则(哪怕是全端口、全 IP 的宽泛允许规则)
2 显式允许规则(Allow) 仅当流量没有匹配到任何阻止规则时,才会进入允许规则的匹配流程;匹配到允许规则则放行流量,终止匹配
3(最低) 全局默认规则 流量没有匹配到任何自定义阻止 / 允许规则时,执行对应网络配置文件的默认行为:入站默认全部阻止,出站默认全部允许

同动作下:匹配精度优先级层级(同允许 / 同阻止时,谁先匹配)

当多条规则是相同动作类型(都是允许、或都是阻止),才会进入这个层级的匹配,核心逻辑是:匹配维度越多、作用域越精准的规则,优先级越高,先被匹配执行

优先级从高到低的完整排序,直接明确程序与端口的层级关系

精度优先级 规则匹配维度组合 核心说明 示例
1(最高) 程序路径 + 协议 + 本地端口 + 远程端口 + 源 IP + 目的 IP + 网络配置文件 全维度精准匹配,覆盖所有关键信息,优先级最高 仅允许 QQ.exe,UDP 协议,本地任意端口,远程 53 端口,仅专用网络,192.168.1.0/24 网段
2 程序路径 + 协议 + 端口 + IP 比上一级少部分限定条件,精度次之 阻止 XX.exe,UDP 协议,所有端口,所有 IP
3 程序路径 + 协议 仅匹配程序 + 协议,不限制端口 / IP 允许微信.exe,TCP+UDP 协议,全端口全 IP
4 程序路径(全协议全端口全 IP) 仅匹配程序,不管协议、端口、IP 阻止 XX.exe,所有协议,所有端口,所有 IP
5 协议 + 本地端口 + 远程端口 + 源 IP + 目的 IP + 网络配置文件 无程序维度,端口 + IP + 协议全匹配,精度永远低于带程序路径的规则 允许 UDP 协议,所有本地端口,所有远程端口,所有 IP(就是你创建的全 UDP 放行规则)
6 协议 + 端口 + IP 无程序维度,端口 + IP + 协议匹配 允许 UDP 协议,本地 500-5000 端口,所有 IP
7 协议 + 端口 仅匹配协议 + 端口,无 IP、程序限制 允许 UDP 协议,所有端口
8(最低) 仅协议 / 仅 IP / 全通配规则 单维度匹配,或无任何限制的全通配规则 允许所有协议,所有端口,所有 IP

原理

入站默认全部阻止,出站默认全部允许

出站方向

本机程序→外网

数据包从程序发出后,过滤层的执行顺序从上到下,上层拦截的数据包不会向下传递:

  1. ALE 层(应用层强制层):出站流量的第一个过滤关口,也是程序级规则的唯一生效层。
    • 这里会直接匹配所有带「程序路径」的规则,校验流量对应的进程、程序路径、用户权限;
    • 如果这里命中阻止规则,数据包直接被丢弃,完全不会进入后续的传输层 / 网络层,你的纯端口规则根本碰不到这个数据包
  2. 传输层(TCP/UDP 层):仅当 ALE 层放行了数据包,才会到这一层,匹配端口、协议类型的规则,执行状态化会话跟踪。
  3. 网络层(IP 层):匹配源 / 目的 IP 地址、IP 网段的规则。
  4. 数据链路层(NDIS 层):数据包出网卡前的最后关口,匹配 MAC 地址、网卡类型的规则。
入站方向

外网→本机程序

数据包从网卡进入后,过滤层的执行顺序从下到上,下层拦截的数据包不会向上传递:

  1. 数据链路层:入站流量第一个关口,过滤非法帧、MAC 黑名单。
  2. 网络层 / 传输层:匹配 IP、端口、协议规则,哪怕这里你的全 UDP 端口规则放行了流量,也只是通过了这一层。
  3. ALE 层(应用层强制层):入站流量的最终校验关口,必须匹配对应监听程序的规则,才能最终放行。
    • 如果这里有针对目标程序的阻止规则,哪怕前面端口规则全放开了,数据包依然会在这里被拦截丢弃。

定位哪条规则拦截了流量

  • 打开wf.msc,右键左侧根节点,选择「属性」;
  • 切换到对应网络配置文件,点击「日志」区域的「自定义」;
  • 开启「记录被丢弃的数据包」,设置日志路径,保存配置;
  • 重现程序连不上的问题,打开日志文件(默认路径%systemroot%\system32\logfiles\firewall\pfirewall.log),即可看到被拦截的数据包信息,以及对应的规则 ID。

权威规则验证命令

1
2
3
4
5
# 查看指定程序的所有生效规则
Get-NetFirewallRule -Program "C:\XX路径\XX.exe" | Select-Object DisplayName, Action, Direction, Enabled

# 查看所有UDP协议的生效规则
Get-NetFirewallRule -Protocol UDP | Select-Object DisplayName, Action, Direction, Enabled

Linux规则优先级

Linux 主流发行版(Ubuntu、Debian、RHEL、Fedora 等)的网络安全体系是分层架构,核心分为「强制访问控制层→内核过滤框架→上层管控工具」三层

Linux 网络过滤的核心是Netfilter(内核态 TCP/IP 协议栈内置的钩子框架),用户态管理工具主流为nftables(新版发行版默认)、iptables(legacy 旧版);同时有 LSM(Linux 安全模块)做进程级权限管控,优先级全局最高

Linux 防火墙严格遵循 「表优先级→链顺序→规则上下顺序」 的铁律:

  1. 第一优先级:表的优先级。Netfilter 4 张核心表,优先级从高到低:raw > mangle > nat > filter,端口 / 程序过滤规则默认都在filter表。
  2. 第二优先级:链的顺序。按数据包流转时序,先经过的链先匹配规则。比如出站流量先经过 OUTPUT 链,再经过 POSTROUTING 链,OUTPUT 链的规则先执行。
  3. 第三优先级:同链内规则从上到下依次匹配,先匹配先执行。一旦数据包匹配到某条规则的所有条件,就会执行对应动作(ACCEPT/DROP/REJECT),匹配即终止,后续规则完全不会被遍历(LOG/RETURN 等特殊动作除外)。

致命避坑:Linux 中,如果你先写「全 UDP 端口 ACCEPT」,再写「XX 程序 UDP DROP」,数据包会先匹配到 ACCEPT 规则直接放行,后面的 DROP 规则完全不生效!和 Windows 的逻辑完全相反。

原理

出站方向

本机程序→外网

从早到晚,先经过先匹配

越靠前的环节,优先级越高,拦截后数据包直接终止流转,不会进入后续环节。

  1. LSM 安全校验(AppArmor/SELinux)

    进程发起网络系统调用(创建 socket、发起连接)的第一关,也是全局最高优先级。如果进程被禁止网络访问,直接在这里拒绝,

    数据包根本不会进入协议栈,Netfilter 的所有端口规则完全不生效

    • Ubuntu/Debian 默认启用 AppArmor,RHEL/CentOS 默认启用 SELinux,绝大多数发行版默认开启,也是最容易被忽略的拦截点。
  2. OUTPUT 链(Netfilter 核心钩子点)

    数据包进入协议栈后的第一个过滤点,唯一能匹配进程 / 程序信息的链

    • 可匹配维度:源 / 目的 IP、协议、端口,通过owner扩展模块匹配程序路径、进程 UID/GID、PID。
    • 你的端口放行规则、程序过滤规则,绝大多数都写在这条链的filter表(默认表)中。
  3. 路由决策:确定数据包的出网卡、下一跳地址

  4. POSTROUTING 链

    数据包出网卡前的最后一个钩子点,主要用于 SNAT / 地址伪装,无法匹配进程信息(路由后已脱离进程上下文)

  5. 数据包通过网卡发出

入站方向

外网→本机程序

  1. PREROUTING 链:数据包从网卡进入后的第一个钩子点,用于 DNAT / 端口转发,无法匹配进程信息。
  2. 路由决策:判断数据包是否为本机流量。
  3. INPUT 链:本机入站流量的核心过滤点,原生无法匹配进程 / 程序信息(数据包还未关联到用户态进程)。
  4. LSM 安全校验:数据包递交给用户态进程时,校验进程是否有权限接收该流量。
  5. 数据包被进程接收

关键差异:Linux 原生 Netfilter仅出站 OUTPUT 链能匹配程序信息,入站无法直接匹配程序,和 Windows 入站 / 出站都能精准匹配程序有本质区别。

实操排查命令

1
2
3
4
5
6
7
8
9
10
# 1. 查看filter表所有规则,确认规则顺序
iptables -L -n -v --line-numbers

# 2. 查看AppArmor状态与对应程序的配置
aa-status
cat /etc/apparmor.d/usr.bin.xx程序 # 查看程序是否被禁止网络

# 3. 查看SELinux状态与拦截日志
getenforce
ausearch -m avc -ts recent | grep xx程序 # 查看SELinux是否拦截了程序网络请求

Mac规则优先级

MacOS 10.10+ 完全淘汰了旧的 ipfw,采用三层分层架构,越上层的管控优先级越高、执行时序越早,逻辑和 Windows 高度相似,天生支持应用级优先管控

MacOS 防火墙体系从高到低(优先级从高到低,执行时序从早到晚)分为三层,上层拦截后,数据包直接终止流转,不会进入下层:

  1. App Sandbox(应用沙盒,最高优先级):MacOS 强制沙盒机制,所有 App Store 上架的应用必须开启,沙盒内严格管控应用的网络权限,在内核进程创建阶段就生效。
  2. Application Firewall(应用防火墙,次高优先级):系统设置→网络→防火墙中的图形化管控工具,基于内核 Socket Filter 框架,专门管控应用的网络访问权限,是 Mac 原生的应用级防火墙。
  3. PF(Packet Filter,底层核心):源自 OpenBSD 的内核态包过滤框架,对应 Linux 的 Netfilter,支持 IP、端口、协议的精细化过滤,用户态管理工具为pfctl

原理

出站方向

本机程序→外网

  1. App Sandbox 权限校验:应用发起网络请求,首先校验沙盒权限。如果沙盒未开启网络权限,直接拒绝创建 socket,数据包根本不会进入内核协议栈,后面的所有防火墙规则完全不生效。
  2. Application Firewall 校验:socket 创建请求进入内核,应用防火墙检查该应用的放行 / 阻止规则。如果应用被禁用网络,直接在这里拒绝连接,不会进入 PF 过滤层
  3. PF 过滤层(OUTPUT 链):只有通过了上面两层校验的数据包,才会进入 PF 的 OUTPUT 链,匹配 IP、端口、协议规则,执行放行 / 阻止动作。
  4. 路由决策与网卡发送
入站方向

外网→本机程序

  1. PF 过滤层(PREROUTING/INPUT 链):数据包从网卡进入,首先经过 PF 的入站过滤,匹配端口、IP 规则。
  2. Application Firewall 校验:通过 PF 放行的数据包,校验目标监听应用的入站权限,被禁用则直接拦截。
  3. App Sandbox 校验:最终校验应用的沙盒入站权限,通过后才会把数据包递交给应用。

核心结论:Mac 上应用级规则(沙盒 / 应用防火墙)永远优先于 PF 的端口级规则,哪怕 PF 全端口全协议放行,只要上层应用被禁用,直接拦截,和 Windows 的逻辑完全一致。

规则优先级与匹配逻辑

  1. 跨层全局优先级(铁律)

    App Sandbox 规则 > Application Firewall 规则 > PF 端口规则

    上层的阻止规则一票否决,完全无视下层的所有允许规则,和 Windows 的阻止规则优先逻辑完全一致。

  2. PF 内部的规则优先级

    PF 内部规则匹配逻辑和 Linux iptables 类似:规则按配置顺序从上到下匹配,先匹配先执行,核心关键字为quick

    • quick关键字的规则:匹配到后立即执行动作,终止后续所有规则匹配,是最常用的写法。
    • 不带quick的规则:会遍历所有规则,最后执行最匹配的规则(不推荐)。
    1
    2
    3
    4
    # 先写带quick的阻止规则,匹配到直接拦截
    block out quick proto udp from any to any port 53
    # 后写放行规则,不会覆盖上面的quick阻止规则
    pass out quick proto udp from any to any

实操排查命令

1
2
3
4
5
6
7
8
9
10
11
# 1. 查看应用防火墙的所有应用规则
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --listapps

# 2. 查看指定应用的防火墙状态(放行/阻止)
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getappblocked /Applications/xx.app

# 3. 查看PF当前加载的所有规则
sudo pfctl -s rules

# 4. 查看PF拦截日志
log show --predicate 'process == "kernel" and eventMessage contains "pf"' --last 1m

性能问题排查

如何调试慢API参考文章

刷机相关

系统U盘

balenaEtcher

主要用于Linux系统和树莓派等

balenaEtcher下载

balenaEtcher 的设计定位是 「整盘写入工具」,核心适配img/iso 格式的嵌入式系统镜像 (如树莓派 OS、Linux 发行版),这类镜像本身包含完整的分区表、引导程序、系统文件,Etcher 只需把镜像原封不动写入 U 盘,电脑就能识别启动。

Windows(含 Windows Server)的官方 ISO 镜像并非 “完整可启动镜像”,而是 「安装介质包」,它的特点是:

  1. 镜像内无现成的可引导分区表,需要工具在烧录时自动创建 EFI 引导分区、系统安装分区(MBR/UEFI 双引导适配);
  2. Windows Server 镜像体积通常超 4G,而传统 FAT32 文件系统有4G 单个文件限制,需要工具自动处理格式兼容(转 NTFS);
  3. 不同电脑的启动模式(Legacy BIOS/UEFI)不同,需要工具适配对应的引导程序,而 Etcher 无此适配逻辑。

简单说:Etcher 只是 “单纯复制镜像内容到 U 盘”,而 Windows 需要工具在烧录时 “额外构建启动引导、划分专用分区、适配文件系统”,这就是所谓的 “特殊处理”

Rufus

官网下载

Rufus 是一款免费开源、轻量便携、高速稳定的 Windows 平台可启动 USB 创建工具,专为制作 Windows/Linux 等系统安装盘设计,尤其擅长处理 Windows Server 这类需要特殊引导的镜像

特性 说明 对比 balenaEtcher 的差异
轻量便携 单文件 (约 1.3MB),免安装,即开即用,可直接从 U 盘运行 Etcher 体积更大 (>100MB),启动慢
Windows 专属优化 自动识别 Windows 镜像,创建 EFI 引导分区,处理 4GB + 大文件 Etcher 无 Windows 专属引导逻辑,易失败
启动模式智能适配 自动匹配 MBR (GPT)/UEFI (Legacy),支持双引导 Etcher 仅整盘写入,无引导适配
高速写入 比微软官方工具快约 2 倍,支持 USB3.0 全速写入 Etcher 速度慢,无 Windows 优化
文件系统灵活 支持 FAT32/NTFS/exFAT/UDF,自动选择最优格式 Etcher 默认 FAT32,无法处理 4GB + 文件
安全可靠 开源 (AGPLv3),微软数字签名,内置 ISO 校验 Etcher 虽安全,但无 Windows 引导优化

操作步骤

  1. 插入 U 盘,双击运行 Rufus,自动识别 U 盘
  2. 点击启动选择选择,导入 Windows Server ISO 镜像
  3. 关键参数(Rufus 自动识别,建议保持默认):
    • 设备:确认是目标 U 盘 (避免误格硬盘)
    • 引导类型:自动识别 (Windows UEFI/BIOS)
    • 分区方案:自动选择 (MBR 对应 BIOS,GPT 对应 UEFI)
    • 文件系统:自动选择 (通常为 NTFS)
    • 卷标:可自定义 (如 “WinServer2022”)
  4. 点击开始,确认格式化提示,等待完成 (约 5-10 分钟,取决于 U 盘速度)
  5. 完成后安全弹出 U 盘,即可用于服务器安装

Windows上程序Dump文件分析

Dump 分析核心是先定位异常类型,再从基础信息到深度根因逐层拆解,核心工具为 WinDbg Preview(微软官方推荐新版),辅助工具为 Sysinternals 套件、DebugDiag

Dump 类型 适用场景 特点
完整用户态 Dump(Full Dump) 内存泄漏、碎片、死锁、复杂崩溃分析 包含进程完整内存、堆、线程、模块信息,体积大,是内存问题分析的唯一选择
小内存转储(Minidump) 常规崩溃快速定位 仅包含异常线程、调用栈、基础模块信息,体积小,无法分析内存 / 堆问题
内核完整转储 系统蓝屏、驱动崩溃、内核池碎片 包含系统内核完整内存,需系统崩溃时自动生成或手动抓取

最新的Windbg安装

从微软商店下载的WinDbg,有漂亮的图形界面、菜单、点击按钮,还有 “调用栈”、“线程”、“内存” 等可视化窗口

访问微软官方 WinDbg 安装页面,找到 “直接安装 WinDbg” 部分,下载windbg.appinstaller文件

或直接下载最新版本的 msixbundle 包(提取自 appinstaller 文件)

windbg.appinstaller 安装的是 UWP 版 WinDbg Preview,它不含 gflags.exe**,且依赖微软商店 / 联网下载依赖 。要拿到离线安装、必带 gflags.exe** 的版本,必须走 Windows SDK 独立安装 Debugging Tools for Windows 路线

访问微软官方 SDK 页 这里面包含windbg和[Global Flags工具](#Global Flags)

这个windows SDK的安装过程也是要联网的,如果想离线下载,直接找一台电脑将Windows Kits\10\Debuggers目录拷贝到目标机器使用!

生成转储文件

任务管理器:右键进程→创建转储文件(自动生成完整 Dump,仅适用于当前运行的进程)

Procdump(Sysinternals,线上环境首选)

1
2
3
4
# 抓取进程完整内存Dump,核心参数-ma必须携带,否则无堆内存数据
procdump -ma <进程PID/进程名> <输出路径\xxx.dmp>
# 进程崩溃时自动抓取Dump
procdump -ma -e <进程PID> <输出路径\xxx.dmp>

WinDbg:附加进程后,执行.dump /ma <路径\xxx.dmp>生成完整 Dump

PDB文件详解

PDB(Program Database,程序数据库)是微软开发的一种文件格式,用于存储程序的调试信息,通常与编译生成的 EXE、DLL 等二进制文件配套出现。

即使源代码完全未修改,重新编译生成的 PDB 也可能不同,可以默认认为每次编译的 PDB 都是不同

PDB 文件包含的核心信息

  • 符号信息:函数名、变量名、类名等,帮助调试器将二进制地址映射到可读的代码标识
  • 行号信息:二进制指令与源代码行号的对应关系,支持源码级调试(如设置断点、单步执行)
  • 类型信息:结构体、类、枚举等数据类型的定义,用于调试时查看变量的具体结构
  • 全局 / 静态变量信息:记录这些变量的地址和类型

PDB 的主要作用

  • 调试程序:在 Visual Studio 等工具中,没有 PDB 就无法进行源码级调试,只能看到汇编代码
  • 崩溃分析:通过 PDB 可以将崩溃时的 “调用堆栈” 转换为具体的函数名和行号,快速定位问题
  • 性能分析:性能分析工具(如 Visual Studio Profiler)需要 PDB 来将性能数据关联到具体函数

PDB与生成EXE/DLL的匹配机制

调试器通过以下方式验证 PDB 是否与二进制文件匹配:

  • 检查 PDB 中的 GUID 是否与 EXE/DLL 头中的 GUID 一致;
  • 检查时间戳是否匹配

若不匹配,调试器会拒绝加载 PDB,或提示 “符号不匹配”

PDB文件生成

默认情况下,会包含,但具体取决于编译配置(Debug/Release)和项目设置:

  • Debug 配置:默认一定会生成 PDB,且包含完整的调试信息(行号、变量名等),因为 Debug 模式的核心目的就是调试
  • Release 配置:默认也会生成 PDB,但调试信息可能相对精简(取决于编译器设置)。很多开发者误以为 Release 不生成 PDB,其实 VS 默认是开启的,仅在手动关闭 “生成调试信息” 选项时才会跳过

常见默认路径

C#/VB.NET项目

解决方案根目录 → binDebugRelease文件夹(如 MyProject\bin\Debug\MyProject.pdb)。

C++ 项目

解决方案根目录 → DebugRelease文件夹(如 MyProject\Debug\MyProject.pdb);若为子项目,可能在子项目目录下的Debug/Release

若找不到,可通过项目属性查看:

  • C# 项目右键项目 → 属性 → 生成 → 输出路径(此处显示的目录即为 PDB 所在位置)。
  • C++ 项目右键项目 → 属性 → 链接器 → 调试 → 生成调试信息(确认开启),同时查看 “常规”→“输出文件” 路径,PDB 通常与输出文件同目录。

分析环境搭建

特性 Default Symbol Path(默认符号路径) Default Source Path(默认源路径)
核心作用 定位PDB 文件(程序数据库) 定位源代码文件(.c/.cpp/.cs 等)
关联文件 .pdb 文件 .c/.cpp/.cs/.h 等源码文件
核心功能 将内存地址 ↔ 函数名 / 行号 / 类型信息映射 基于 PDB 的行号信息,找到实际源码文件
无此路径的后果 只能看到内存地址,无法解析函数名 / 行号 能看到函数名 + 行号,但无法显示源码
典型配置示例 srv*D:\Symbols*https://msdl.microsoft.com/download/symbols D:\TestApp\src;D:\CommonLib\src

可视化配置符号路径

符号文件(.pdb)就是 WinDbg 的「翻译字典」:它能把内存里的十六进制地址,翻译成你能看懂的函数名、代码行号,没有它,所有分析都是无效的。

  1. 点击 WinDbg 左上角的文件(File) 按钮
  2. 左侧菜单找到设置(Settings),点击进入调试设置界面
  3. 在设置页找到Debugging settings(调试设置),往下滑动找到Symbol path(符号路径)输入框
  4. 按以下格式填写,分两部分(微软官方符号 + 你自己的程序 PDB 路径):
1
srv*C:\Symbols*https://msdl.microsoft.com/download/symbols;D:\你的程序PDB所在文件夹路径

前半段srv*C:\Symbols*https://msdl.microsoft.com/download/symbols是固定写法:

  • srv:告诉 WinDbg 从符号服务器下载文件
  • C:\Symbols:本地缓存文件夹(WinDbg 会自动创建,不用手动新建),下载过的系统符号会存在这里,下次不用重复下载
  • 后面的链接是微软官方的符号服务器,提供所有 Windows 系统 dll/exe 的符号文件

分号;后面,替换成你自己的程序 PDB 文件夹路径(比如你的程序编译后,PDB 和 exe 在同一个文件夹D:\TestApp\bin\x64\Release,就填这个路径)

完整例子: (本地缓存文件改到D盘)

1
srv*D:\Symbols*https://msdl.microsoft.com/download/symbols;D:\TestApp\bin\x64\Release

将 PDB 与二进制文件放在同一目录

最简单的方式:将所有 EXE、DLL 和对应的 PDB 复制到同一个文件夹,WinDbg 会自动在该目录下查找匹配的 PDB。

验证符号是否加载成功: windbg中执行lmv命令,会列出所有加载的模块,若符号加载成功,会在模块信息中看到Symbol file: ...\YourProject.pdb

  1. (可选)往下找到Source path(源码路径),填写你程序的源码文件夹路径,配置后调试时能直接跳转到崩溃的代码行
  2. 点击右下角保存(Save),关闭设置窗口,全局配置就完成了。

命令行中配置源码路径与符号路径

下面命令仅对当前 WinDbg 会话生效;

若要永久生效,需在 WinDbg「文件」→「符号文件路径」/「源文件路径」中设置,或修改 WinDbg 配置文件。

符号路径命令.sympath(覆盖)、.sympath+(追加),设置后需.reload生效;

源码路径命令.srcpath(覆盖)、.srcpath+(追加),路径不匹配时用.srcfix映射;

p.s. 路径含空格:需用引号包裹

符号路径相关

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
//覆盖式设置符号路径(替换原有所有路径)
// 示例:设置你的符号路径(微软服务器缓存+本地PDB目录)
.sympath srv*D:\Symbols*https://msdl.microsoft.com/download/symbols;D:\TestApp\bin\x64\Release

//追加式添加符号路径(保留原有,新增路径)
// 示例:在原有路径基础上,添加另一个本地PDB目录
.sympath+ D:\TestApp\Libs\Release

//查看当前符号路径
.sympath // 简洁输出
// 或
.lsympath // 详细输出(显示每个路径的状态)

//重置符号路径为默认
//作用:恢复到 WinDbg 默认符号路径(通常为空或系统默认)
.sympath .

//关键补充(设置后生效)
//设置符号路径后,需执行 .reload 让 WinDbg 重新加载符号
.reload // 重新加载所有模块的符号
// 或指定模块重新加载(更高效)
.reload MyApp.exe

lm v//详细列出所有模块的符号状态
// 或更简洁的筛选版:
lm m *你的DLL名称* // 替换成你的自定义DLL名,比如 lm m MyProject*.dll

lm v指标判断

符号状态 说明
PDB symbols ✅ 自定义 DLL 符号加载成功
Public symbols ❌ 仅加载了公共符号(无调试信息)
No symbols loaded ❌ 完全没加载符号
Deferred ❌ 延迟加载(未实际加载)

源码路径相关

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
//直接设置新的源码路径,清空原有路径。
// 示例:设置单个源码目录
.srcpath D:\TestApp\src
// 示例:设置多个源码目录(分号分隔)
.srcpath D:\TestApp\src;D:\TestApp\Common\src;D:\ThirdParty\Lib\src

//追加式添加源码路径
//作用:保留原有路径,新增源码目录。
// 示例:追加一个新的源码目录
.srcpath+ D:\TestApp\ModuleA\src

// 查看当前源码路径
.srcpath // 简洁输出
// 或
.lsrcpath // 详细输出

//重置源码路径为默认
.srcpath .

//解决 “PDB 中源码路径与本地不一致” 的问题
//PDB 中记录的是编译时的源码路径(比如编译机上的C:\Build\TestApp\src),若本地源码路径不同(如D:\TestApp\src),WinDbg 会找不到源码,需用 .srcfix 映射路径
// 自动将PDB中的源码路径映射到本地指定目录
.srcfix D:\TestApp\src
// 手动映射(精准匹配):将编译时的路径映射到本地路径
.srcpath+ C:\Build\TestApp\src=D:\TestApp\src

加载dump与符号步骤

  1. 加载 Dump 文件

  2. 开启符号加载详细日志 !sym noisy

    执行后输出noisy mode - symbol prompts on,就是开启成功。作用是让 WinDbg 告诉你,它去哪里找符号、有没有找到、哪里出错了。

  3. 加载需要的符号与源码

  4. 强制重载所有符号 .reload /f

    /f是 force 强制的意思,让 WinDbg 重新加载所有模块的符号文件

  5. 最终验证符号状态 lm

    执行后会列出所有加载的模块(exe、dll),看模块前面的标记:

    • M:微软官方符号加载成功
    • P:你的程序私有 PDB 加载成功(完美匹配)
    • 无任何标记:符号加载失败,需要排查路径、PDB 版本、程序位数(32 位 Dump 必须用 32 位 WinDbg,64 位同理)

完整 Dump 分析全流程

程序崩溃闪退异常退出的分析流程

程序崩溃、闪退、异常退出的分析流程

一键自动分析,定位崩溃根因: !analyze -v

这是 WinDbg 最强大的命令,会自动解析 Dump 里的异常,输出完整的崩溃报告,你只需要关注 4 个核心部分

  • 异常代码(ExceptionCode):直接告诉你崩溃的类型

    常见异常代码 含义
    0xC0000005 内存访问违例(最常见,空指针、数组越界、写只读内存)
    0xC0000017 内存不足,分配内存失败
    0xC00000FD 栈溢出(无限递归、超大局部变量)
    0x80000003 断点触发,程序里有调试断点
  • 调用栈(STACK_TEXT):崩溃的核心线索

    这里会从下往上列出函数调用的完整顺序,最顶部的就是崩溃时正在执行的函数

    示例:00 0000000000000000 00007ff612345678 TestApp!MyFunction+0x23

    翻译:崩溃在TestApp.exeMyFunction函数里,偏移 0x23 的位置。

  • 故障指令(FAULTING_IP):崩溃时 CPU 执行的指令地址,对应具体的函数

  • BUGCHECK_STR:如果是系统蓝屏的内核 Dump,这里会显示蓝屏类型;用户态程序崩溃一般显示APPLICATION_FAULT

补充分析,确认完整执行流

  1. 查看当前崩溃线程的详细调用栈(带参数) kp
  2. 查看所有线程的调用栈,排查是否是其他线程触发的崩溃 ~*kp
  3. 查看当前函数的局部变量,定位空指针 / 变量异常 dv
  4. 查看 CPU 寄存器状态,确认异常地址 r

内存碎片、内存泄漏、内存不足的分析流程

必须用procdump -ma抓取的完整 Full Dump,否则没有堆内存数据,无法分析

确认是不是内存碎片问题 !address -summary

  • Total Size:进程总空闲内存大小

  • Largest Region Size:最大的连续空闲内存块大小

    ✅ 碎片判定标准:Total Size很大,但 Largest Region Size远小于你程序要分配的内存大小,就是虚拟地址空间碎片

    示例:总空闲内存有 8GB,但最大的连续块只有 20MB,你要分配 30MB 的连续内存,就会报内存不足,这就是典型的碎片问题

确认堆内存碎片严重程度

!heap -s

这个命令会列出进程里所有的堆(每个进程至少有 1 个默认堆,可能有自定义堆),核心看每个堆的这几个指标:

指标 碎片判断逻辑
Free Blocks 空闲块数量,数量越多,碎片越严重
Total Free Size 堆内总空闲内存大小
Max Free Block 堆内最大的连续空闲块大小
Heap Flags 有没有LFH标记(低碎片堆,开启后碎片会大幅减少)

✅ 堆碎片判定标准:Total Free Size很大,但Max Free Block很小,Free Blocks数量达到几万 / 几十万,就是堆内存碎片严重

定位导致碎片的核心分配源

!heap -s的结果里,复制碎片最严重的堆的句柄(第一列的十六进制数,比如0000000000580000

输入命令,查看这个堆的内存块分配统计:!heap -stat -h 0000000000580000

执行后会按占用大小排序,核心看size(内存块大小)、blocks(块数量)、total(总占用)。

✅ 重点关注:blocks数量最多的size,比如 size=128 字节,blocks 有 100 万个,这个就是导致碎片的高频分配内存块。

找到分配调用栈定位到具体代码

⚠️ 必须提前用 gflags 开启了堆栈回溯,否则看不到调用栈。

输入命令,过滤出所有对应大小的内存块:

1
!heap -flt s 128

把 128 换成上一步找到的高频分配 size,执行后会列出所有对应内存块的地址。

随便选一个内存块地址,输入命令查看分配调用栈:

1
!heap -p -a 000000000a5b23c0

把地址换成你复制的内存块地址,执行后看输出里的Stack Trace部分,就是分配这个内存块的完整函数调用顺序,从下往上看,就能找到你代码里的哪一行、哪个函数,在频繁分配内存导致碎片。

针对.NET程序的补充

.NET 程序 85% 的内存碎片都来自大对象堆(LOH,大于 85000 字节的对象会分配在这里,默认不会被 GC 压缩),专门分析步骤如下:

  • 加载 .NET 调试扩展 SOS:
    • .NET Framework:.loadby sos clr
    • .NET Core/.NET 5+:.loadby sos coreclr
  • 查看 GC 堆整体情况,重点看 LOH 占用:
    • !eeheap -gc
  • 查看堆内所有空闲块,统计碎片程度:
    • !dumpheap -type Free
  • 查看所有 LOH 大对象,定位频繁分配的对象:
    • !dumpheap -min 85000
  • 查看固定对象(会阻止 GC 压缩,加剧碎片):
    • !gchandles -type Pinned
指令!eeheap -gc详解
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
DATAS = 
========================================
#👇🏻 表明是单GC堆,64 位桌面程序默认单堆,服务器程序可能多堆
Number of GC Heaps: 1
----------------------------------------
#👇🏻 代龄起始地址: 标注了 0/1/2 代对象在内存中的起始地址,仅用于调试定位对象
generation 0 starts at 149bded7368
generation 1 starts at 149bda11000
generation 2 starts at 14980001000
ephemeral segment allocation context: none
#👇🏻 小对象堆(SOH)—— 核心使用区域
Small object heap
segment begin allocated committed allocated size committed size
014980000000 014980001000 0149895f7b20 014989627000 0x95f6b20 (157248288) 0x9627000 (157446144)
0149bda10000 0149bda11000 0149be4c9b48 0149be581000 0xab8b48 (11242312) 0xb71000 (11997184)
#👇🏻 大对象堆(LOH)—— 碎片重灾区
Large object heap starts at 14990001000
segment begin allocated committed allocated size committed size
014990000000 014990001000 014993c01048 014993c02000 0x3c00048 (62914632) 0x3c02000 (62922752)
#👇🏻 固定对象堆(POH)
Pinned object heap starts at 14998001000
segment begin allocated committed allocated size committed size
014998000000 014998001000 0149980dd118 0149980de000 0xdc118 (901400) 0xde000 (909312)
------------------------------
#👇🏻 汇总信息
GC Allocated Heap Size: Size: 0xdd8b7c8 (232306632) bytes.
GC Committed Heap Size: Size: 0xde78000 (233275392) bytes.

这是 .NET 程序 GC 托管堆 的内存使用报告,能清晰看到托管堆的分配、提交大小和各区域的碎片情况,程序当前托管堆碎片程度极低,内存使用健康

  • GC 堆:.NET 程序的内存由垃圾回收器(GC)管理,GC 将内存分为多个「堆段」和「代龄」,目的是高效回收无用对象、减少碎片;
  • 代龄(generation):GC 按对象存活时间分代,0 代是最新创建的临时对象,2 代是存活最久的老对象(如全局变量)
  • 分配大小(allocated):实际已分配给对象使用的内存;
  • 提交大小(committed):GC 向操作系统申请并已「锁定」的内存(即使未分配给对象,也无法被系统回收)
  • 提交大小 - 分配大小 = 差值 : 内存碎片重要评估指标
  • 碎片判断committed - allocated 的差值越小,碎片越少(差值大说明有大量未使用但被锁定的内存,即碎片)

堆损坏导致内存资源不足排查场景

!heap -triage 能「发现堆损坏的结果」,无法直接定位代码行

堆损坏的本质:你之前检测到的 LFH 堆元数据损坏(回指指针错误),相当于 “库存台账被篡改 / 撕毁”,管理员(堆管理器)已经无法正确识别哪些内存块可用、哪些已释放;

后续内存操作失败:当程序后续调用malloc/new/HeapAlloc申请内存时,堆管理器查 “台账” 发现无法找到可用的内存块(因为台账坏了),此时它不会说 “台账坏了”,而是返回「内存分配失败」的错误码(比如ERROR_NOT_ENOUGH_MEMORY,对应 0x80070008);

程序层面的误判:绝大多数程序的错误处理逻辑,会把「内存分配失败」直接解读为 “系统内存资源不足”,并将这个错误信息记录到全局异常日志中,而非识别出底层的堆损坏问题。

为什么直接用 !heap -triage 定位不到代码行?

你之前的操作是「堆损坏后才检测」,相当于 “案发现场已被破坏”:

  1. 延迟崩溃特性:堆损坏(比如第 50 行代码破坏 LFH 元数据)不会立即崩溃,程序可能继续运行,直到后续调用 new/malloc 申请内存时(比如第 500 行)才触发错误;
  2. 调用栈丢失:此时 WinDbg 看到的崩溃调用栈是「第 500 行申请内存」,而非真正导致堆损坏的「第 50 行」;
  3. 托管 / 非托管隔离:WPF 是.NET 托管程序,!heap 只能分析原生堆(非托管),无法直接关联到 C# 代码,需要加载 SOS 扩展解析托管调用栈。

确保wpf程序生成了PDB符号文件(Debug模式默认生成,Release模式需手动勾选「生成调试信息」)

  • 启用 PageHeap(让错误 “即时崩溃”)

    以管理员身份打开命令提示符,执行

    1
    2
    # 替换为你的WPF程序名(比如MyWpfApp.exe)
    gflags /i MyWpfApp.exe +hpa

    +hpa:启用全页堆,让每个非托管堆分配占用独立内存页;一旦出现越界写 / 释放后使用,程序会立即崩溃(而非延迟崩溃),且崩溃点就是「导致堆损坏的代码行」

  • 用 WinDbg 启动 / 附加 WPF 程序

    1
    2
    3
    4
    5
    # 方式1:直接启动程序(推荐,能捕获全程)
    windbg -g -G MyWpfApp.exe

    # 方式2:附加已运行的程序
    windbg -pn MyWpfApp.exe

    -g:忽略初始断点,直接运行程序;

    -G:忽略退出断点,方便查看崩溃信息

  • 加载 SOS 扩展(解析 C# 托管调用栈)

    WPF 是.NET 程序,需加载 SOS 扩展才能看到 C# 代码的调用栈:

    1
    2
    3
    4
    5
    # .NET Framework(如4.8)
    .load sos

    # .NET Core/.NET 5+(如.NET 6/7/8)
    .load sos.dll
  • 复现问题,捕获崩溃现场

    触发导致堆损坏的场景(比如点击某个按钮)—— 此时程序会立即崩溃,WinDbg 会暂停并显示崩溃信息

  • 定位具体代码行

    执行以下命令,逐层解析崩溃原因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#查看原生调用栈(非托管):
k // 简洁调用栈
kb // 带参数的调用栈(更详细)
#能看到崩溃的原生函数(比如 ntdll!RtlValidateHeap 或 msvcrt!malloc),确认是堆操作触发的崩溃。

#查看托管调用栈(C# 代码)
!clrstack -p // 显示托管调用栈,-p带函数参数

#此时会直接显示出崩溃的 C# 代码行,比如
OS Thread Id: 0x1234 (0)
Child SP IP Call Site
000000000018E800 00007ffd12345678 MyWpfApp.MainWindow.btnUseAgain_Click(System.Object, System.Windows.RoutedEventArgs) [C:\Projects\MyWpfApp\MainWindow.xaml.cs @ 89]
#其中 @ 89 就是具体的代码行号

#验证堆损坏的具体内存地址(可选):
!heap -x <崩溃地址> // 查看崩溃地址所属的堆块
#能确认该地址是之前!heap -triage检测到的损坏堆块,关联到具体的内存分配 / 释放操作

WFP中导致原因

WPF 中导致 LFH 堆损坏(误报内存不足)的最高发场景

  1. 非托管资源释放后仍访问(Use-After-Free 高发场景)

    WPF 中大量控件 / API 依赖非托管资源(如HwndSourceInteropBitmap、Win32 API 调用),释放后未置空引用,后续代码仍访问,是最常见的堆损坏原因

  2. 跨线程操作 WPF UI 对象(隐性堆损坏)

    WPF UI 元素(如ButtonTextBox)必须在 UI 线程访问,跨线程操作会导致 UI 对象的非托管句柄被异常释放 / 复用,进而破坏堆结构

    原因:

    WPF UI 对象的非托管句柄(如 HWND)由 UI 线程管理,跨线程写入会导致:

    1. UI 线程可能正在释放该句柄对应的堆内存;
    2. 后台线程同时往该内存写数据,造成「释放后使用」或「缓冲区越界」;
    3. 最终触发 LFH 堆的回指指针错误。
  3. P/Invoke 时缓冲区大小不匹配(缓冲区下溢 / 溢出)

    WPF 中调用 Win32 API(如系统对话框、注册表操作)时,若传入的缓冲区大小计算错误,会直接导致堆内存越界,破坏 LFH 元数据

  4. WeakReference 弱引用不当使用(访问已回收对象)

    WPF 中用WeakReference管理大对象(如图片、控件)时,若未检查对象是否已被 GC 回收,强制转换后操作会触发「释放后使用」

一些指令盘点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 查看用户态 Dump 基本信息(包括 Dump 类型、进程名、抓取时间)
!peb

// 或更直接的:查看 内核 类型(只针对内核)
.version

//验证 Dump 完整性
!address -summary

// 1. 查看当前调试的进程基本信息
!process 0 0

// 2. 查看 Dump 类型(是否为完整内存 Dump)
!dumpdebug

// 3. 列出所有实际加载的模块(关键!找正确模块名)
lm // 小写 L + M,列出所有模块的完整列表

lm命令含义解析

状态标识 含义 对内存碎片分析的影响
(pdb symbols) 系统 / 第三方库的完整符号加载 无影响,调试命令可正常执行
(private pdb symbols) 私有 PDB 符号加载(如 apphost、combase) 无影响,可解析更多私有函数(加分项)
(service symbols: CLR Symbols without PDB) CLR 程序的公共符号(无私有 PDB) 不影响碎片分析,仅函数名可能显示不全
(export symbols) 仅导出符号(如 coreclr、winmm) 无影响,仅无法解析非导出函数
(no symbols) 无符号(如 MFC100CHS) 无影响

Global Flags

Global Flags(全称 Global Flags Editor,可执行文件为 gflags.exe 是微软 Windows 调试工具集(Debugging Tools for Windows) 里的核心工具

  • 不带参数运行 gflags.exe → 弹出你现在的「Global Flags」可视化界面;
  • 带参数运行(如 gflags /i MyApp.exe +hpa)→ 直接在命令行执行配置,不弹出界面。

核心作用是:给 Windows 系统或特定进程配置「调试标志」,强化内存错误检测(比如你遇到的堆损坏、内存泄漏)、调试日志记录、异常捕获等能力,是定位底层内存问题的关键工具

安装方式

windows SDK

通过 Windows SDK(Windows 软件开发工具包) 安装 Windows SDK 下载页

运行安装包后,不需要安装完整 SDK,只需要勾选「调试工具 for Windows(Debugging Tools for Windows)」这一个组件(体积约 50MB),其他组件可以全部取消

默认安装路径: C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe

通过 WinDbg Preview(微软商店版)安装

微软新版调试工具 WinDbg Preview 已内置 gflags.exe

使用方式

开启PageHeap操作

PageHeap 的核心作用是让内存违规从 “隐性延迟崩溃” 变成 “即时可控崩溃”

命令行用法为: gflags /i 进程名.exe +hpa 启用全页堆(PageHeap),让内存违规即时崩溃

禁用全页堆: gflags /i 进程名.exe -hpa 启用或禁用后,直接打开程序就能生效了

👇🏻下面是ui界面操作

  1. 界面顶部的 Image File 标签(在 System Registry 右边),是针对单个 exe 程序配置的页面,不会影响系统全局
  2. 在「Image File Name」输入框中,填写你的 WPF 程序的 完整 exe 文件名(必须带 .exe 后缀)
  3. 勾选「Enable page heap」: 右侧的选项列表中,找到 Enable page heap 这个复选框,把它勾选上
  4. 保存配置: 点击右下角的 应用 (A)确定 按钮,保存这个配置

验证配置是否生效

  1. 重启你的 WPF 程序;
  2. 用 WinDbg 附加到进程;
  3. 执行 !heap -s 命令,如果看到堆类型显示为「Page Heap」,说明配置成功。

配置完成后,复现你之前的堆损坏场景,程序会立即崩溃,此时用 WinDbg 捕获崩溃现场,加载 SOS 扩展(.load sos),执行 !clrstack -p 就能直接定位到导致堆损坏的 C# 代码行