C 盘红了。监控平台告警:磁盘剩余 3%。你远程连上去,发现数据库已经停止写入,IIS 返回 500,甚至连远程桌面都登不进去——因为 profile 加载失败。这就是 Windows 服务器磁盘空间不足最典型的现场:它不会提前打招呼,往往是在某个深夜突然爆发,而且因为系统盘满载,连排查工具都跑不起来。
本文给出一套从“快速止血”到“长期优化”的完整方案:先定位空间去哪了,再按风险从低到高逐项清理(更新缓存、日志、临时文件、休眠文件、卷影副本),最后讲容量扩展和预防机制。所有命令均可直接复制执行。
一、先定位:空间到底被谁吃了
不要上来就删 C:\Windows 里的东西。第一步一定是量化:哪个目录最大、哪个文件最大。Windows 没有 du 命令,但 PowerShell 可以很优雅地做到。
# 查看各卷剩余空间(CMD 下用 fsutil volume diskfree C:)
Get-Volume | Select-Object DriveLetter, FileSystemLabel, FileSystem,
@{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}},
@{n='FreeGB';e={[math]::Round($_.SizeRemaining/1GB,1)}},
@{n='FreePct';e={[math]::Round($_.SizeRemaining/$_.Size*100,1)}} |
Format-Table -AutoSize
Get-PSDrive -PSProvider FileSystem | Select-Object Name, Used, Free
# 统计 C 盘一级目录占用(最有用的一段,建议保存为脚本)
Get-ChildItem C:\ -Force -Directory -ErrorAction SilentlyContinue | ForEach-Object {
$size = (Get-ChildItem $_.FullName -Recurse -Force -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
[PSCustomObject]@{ Name=$_.Name; SizeMB=[math]::Round($size/1MB,1) }
} | Sort-Object SizeMB -Descending | Select-Object -First 15
# 找出最大的 30 个文件(常见元凶:日志、dump、VHD、SQL 数据文件)
Get-ChildItem C:\ -Recurse -Force -File -ErrorAction SilentlyContinue |
Sort-Object Length -Descending | Select-Object -First 30 FullName,
@{n='SizeMB';e={[math]::Round($_.Length/1MB,1)}}, LastWriteTime
经验上的“嫌疑犯”排序:C:\inetpub\logs(IIS 日志)、C:\Windows\WinSxS(组件存储)、C:\Windows\SoftwareDistribution\Download(更新缓存)、C:\Windows\System32\winevt\Logs(事件日志)、C:\Users\<用户>\AppData\Local\Temp、C:\Windows\MEMORY.DMP(蓝屏转储)、C:\pagefile.sys、C:\hiberfil.sys。
二、低风险清理:更新缓存、临时文件、回收站
这一类可以放心删,几乎不会影响业务。建议在任何服务器上作为常规操作。
REM 停止更新服务后清空更新缓存(安全,重启服务会自动重建) net stop wuauserv net stop bits rd /s /q C:\Windows\SoftwareDistribution\Download net start wuauserv net start bits
# 清理系统临时目录(跳过正在占用的文件)
$dirs = @("$env:TEMP", "C:\Windows\Temp", "C:\Windows\Prefetch")
foreach ($d in $dirs) {
if (Test-Path $d) {
Get-ChildItem $d -Recurse -Force -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "Cleaned: $d"
}
}
# 清空所有用户的回收站
Clear-RecycleBin -Force -ErrorAction SilentlyContinue
# 清理 Windows 更新下载缓存(PowerShell 5.1+ 可用)
Get-ChildItem "C:\Windows\SoftwareDistribution\Download" -Recurse -Force -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
图形化方式:运行 cleanmgr.exe(磁盘清理),第一次使用需要注册清理集,之后可以无人值守执行:
REM 第一次:勾选要清理的项目(会写入注册表 sageset:1) cleanmgr /sageset:1 REM 之后:按上面配置静默执行 cleanmgr /sagerun:1 REM 服务器核心版(Server Core)默认没有 cleanmgr, REM 需要先安装 Server Core App Compatibility FOD,或手动拷贝 cleanmgr.exe 与 mui 文件
注意:cleanmgr 在 Server Core 上不可用,也没有 Windows 10/11 的“存储感知”功能。Server 环境建议把上面的 PowerShell 脚本做成计划任务,每周执行一次。
三、中风险清理:组件存储 WinSxS 与服务包备份
C:\Windows\WinSxS 经常能长到 10 GB 以上。很多人想直接删——绝对不要。WinSxS 是组件存储,里面大量是硬链接,删除会破坏系统。正确做法是用 DISM 做组件清理。
REM 分析组件存储实际占用,判断是否需要清理 DISM.exe /Online /Cleanup-Image /AnalyzeComponentStore REM 清理被取代的组件(安全,保留已安装更新的卸载能力) DISM.exe /Online /Cleanup-Image /StartComponentCleanup REM 彻底清理:删除所有已安装更新的卸载文件(不可回滚补丁,空间收益最大) DISM.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase REM 清理 Service Pack 备份(老系统) DISM.exe /Online /Cleanup-Image /SPSuperseded
# PowerShell 等价命令 Start-Process -FilePath "DISM.exe" -ArgumentList "/Online /Cleanup-Image /StartComponentCleanup /ResetBase" -Wait -NoNewWindow # 清理后可再核验一次占用 DISM.exe /Online /Cleanup-Image /AnalyzeComponentStore
| 清理项 | 典型收益 | 风险 | 建议 |
|---|---|---|---|
| 更新缓存 SoftwareDistribution\Download | 数百 MB ~ 数 GB | 极低 | 随时可清 |
| 临时文件 / Prefetch / 回收站 | 数百 MB | 极低 | 随时可清 |
| WinSxS 组件清理(StartComponentCleanup) | 1 ~ 5 GB | 低 | 常规执行 |
| WinSxS 彻底清理(ResetBase) | 再省 1 ~ 3 GB | 中(无法卸载已装更新) | 补丁稳定运行两周后执行 |
| 事件日志清空 | 视保留策略,数百 MB ~ 数 GB | 中(丢失审计线索) | 先归档再清,且保留安全日志 |
| IIS / 应用日志 | 数 GB 常见 | 低 | 先归档,可压缩 |
| hiberfil.sys 休眠文件 | 约物理内存 40%~75% | 低(服务器本就不需要休眠) | 直接关闭 |
| 卷影副本(Shadow Copy) | 数 GB ~ 数十 GB | 高(影响还原能力) | 调小上限而非全删 |
四、日志清理:IIS 日志与事件日志
4.1 IIS 日志
IIS 默认在 C:\inetpub\logs\LogFiles 下按站点目录写入 W3C 日志,高流量站点一天几 GB 很常见。长期不清理,这里就是 C 盘杀手。正确做法是先改日志目录到数据盘,再建立定期归档压缩机制。
REM 用 appcmd 把站点日志目录改到 D 盘(IIS 7.0 及以上) %windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites -siteDefaults.logFile.directory:"D:\IISLogs" %windir%\system32\inetsrv\appcmd.exe list site %windir%\system32\inetsrv\appcmd.exe set site "Default Web Site" -logFile.directory:D:\IISLogs REM 图形方式:inetmgr → 站点 → 日志 → 目录
# 统计 IIS 日志占用
Get-ChildItem "C:\inetpub\logs\LogFiles" -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum |
ForEach-Object { "IIS Logs: {0:N1} MB" -f ($_.Sum/1MB) }
# 归档并删除 30 天前的日志
$cut = (Get-Date).AddDays(-30)
Get-ChildItem "D:\IISLogs" -Recurse -File -Filter *.log -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -lt $cut } |
ForEach-Object {
compact /c $_.FullName | Out-Null # 可选:NTFS 压缩后再归档
Move-Item $_.FullName "D:\IISArchive\" -Force -ErrorAction SilentlyContinue
}
4.2 Windows 事件日志
事件日志在 C:\Windows\System32\winevt\Logs,默认每个日志上限约 20 MB(Security 默认 128 MB 或 20 MB 视版本),超过后按“需要时覆盖”策略滚动。如果策略被改成“不覆盖”,写满后会导致应用报错甚至拒绝服务。用 eventvwr.msc 打开事件查看器,右键日志 → 属性,可设置最大大小和保留策略。
REM 列出所有日志及其当前大小
wevtutil el | ForEach-Object { wevtutil gl "$_" }
REM 查看指定日志配置(单位字节)
wevtutil gl System
wevtutil gl Security
REM 清空日志(建议先导出)
wevtutil epl System D:\bak\System_%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.evtx
wevtutil cl System
wevtutil cl Application
REM 调整日志最大大小(例如 256MB)与保留策略(false=按需覆盖,true=不覆盖需手动清)
wevtutil sl System /ms:268435456 /rt:false
# PowerShell 方式查看与设置
Get-WinEvent -ListLog * | Where-Object { $_.RecordCount -gt 0 } |
Select-Object LogName, RecordCount,
@{n='SizeMB';e={[math]::Round($_.FileSize/1MB,1)}},
MaximumSizeInBytes, IsEnabled, LogMode |
Sort-Object SizeMB -Descending | Format-Table -AutoSize
# 归档后清空
wevtutil epl Application D:\bak\App_Archive.evtx
wevtutil cl Application
安全警告:清空 Security 日志会丢失登录审计记录,在等保/合规场景下可能属于违规操作。生产环境建议先 wevtutil epl 导出归档,再清空,或者干脆把日志转发到集中日志服务器(WEF 或第三方 Agent)。
五、大文件清理:休眠、页面文件、内存转储、卷影副本
5.1 休眠文件与页面文件
服务器不需要休眠,hiberfil.sys 是纯浪费(大小约为物理内存的 40%~75%,128 GB 内存的机器能占 90 GB)。
REM 关闭休眠并删除 hiberfil.sys(立即生效) powercfg -h off REM 确认已删除 dir C:\hiberfil.sys /a
页面文件(pagefile.sys)不建议直接删除,但可以迁到数据盘或调整大小。路径:SystemPropertiesAdvanced.exe → 性能 → 设置 → 高级 → 虚拟内存 → 更改。命令行方式:
REM 查看当前页面文件配置 wmic pagefileset list /format:list REM 关闭自动管理后自定义(示例 C 盘 8GB~16GB) wmic computersystem where name="%computername%" set AutomaticManagedPagefile=False wmic pagefileset where name="C:\\pagefile.sys" set InitialSize=8192,MaximumSize=16384
5.2 内存转储文件
蓝屏后会在 C:\Windows\MEMORY.DMP 生成完整内存转储,大小接近物理内存。确认不需要分析后可删除;也可以把转储类型改成“小内存转储”避免反复撑爆 C 盘。
REM 查看当前转储配置 reg query "HKLM\SYSTEM\CurrentControlSet\Control\CrashControl" /v CrashDumpEnabled REM 值:0=无 1=完整 2=核心 3=小内存转储(64KB/默认 minidump 目录) reg add "HKLM\SYSTEM\CurrentControlSet\Control\CrashControl" /v CrashDumpEnabled /t REG_DWORD /d 2 /f dir C:\Windows\MEMORY.DMP
5.3 卷影副本与系统还原
vssadmin list shadowstorage 经常能发现“已用 40 GB”的卷影存储,这是磁盘莫名变满的经典元凶。不要直接删所有影子,而是限制上限。
REM 查看卷影存储占用 vssadmin list shadowstorage vssadmin list shadows REM 限制 C 盘卷影存储上限为 10GB(默认通常是磁盘的 10%,高配机器上绝对值很大) vssadmin resize shadowstorage /for=C: /on=C: /maxsize=10GB REM 删除最旧的影子副本(应急) vssadmin delete shadows /for=C: /oldest REM 调整任务计划中的"系统还原"频率:taskschd.msc → Microsoft → Windows → SystemRestore
六、扩容:清理解决不了时的正解
清理永远是权宜之计。如果业务数据本身在增长(数据库、文件服务器、备份落地),正确做法是扩盘。Windows Server 支持在线扩展卷(Server 2008 起支持同磁盘扩展,跨磁盘需动态磁盘)。
# 查看分区与可扩展空间 Get-Partition -DriveLetter C | Select-Object DriveLetter, Size, Type Get-PartitionSupportedSize -DriveLetter C # 扩展到该磁盘支持的最大值(需磁盘上有未分配空间) $max = (Get-PartitionSupportedSize -DriveLetter C).SizeMax Resize-Partition -DriveLetter C -Size $max
云主机的流程是:控制台扩容云盘 → 磁盘管理(diskmgmt.msc)里“重新扫描磁盘” → 扩展卷。注意扩展前务必先做快照,跨磁盘合并、动态磁盘转换等操作有数据风险。
长期优化还包括:把 pagefile.sys、IIS 日志、SQL 数据/日志文件、备份目录全部规划到独立数据盘;对归档类目录开启 NTFS 压缩:
REM 对归档日志目录启用 NTFS 压缩(文本日志压缩率通常 5~8 倍) compact /c /s /i D:\IISArchive compact /c /s /i D:\AppLogs REM 查看压缩状态 compact /q /s D:\IISArchive
七、标准处理步骤清单
- 用
Get-Volume确认哪个卷告警、剩余百分比。 - 用 PowerShell 统计一级目录占用,锁定 Top 3 大目录。
- 用大文件扫描脚本找出 Top 30 文件,识别异常(dump、VHD、.bak、.log)。
- 清理更新缓存、临时文件、回收站(零风险,可立即执行)。
- 运行
DISM /Online /Cleanup-Image /StartComponentCleanup精简 WinSxS。 - 归档并清理 IIS 日志与应用日志,同时把日志目录迁到数据盘。
- 调整事件日志最大大小与覆盖策略,必要时导出归档后清空。
- 关闭休眠(
powercfg -h off),检查 MEMORY.DMP 并调整转储类型。 - 用
vssadmin resize shadowstorage限制卷影副本上限。 - 若清理后仍不足,走扩容流程(先快照,再扩展卷)。
- 把清理脚本配置为
schtasks计划任务,并设置磁盘余量监控告警阈值(建议 15% 预警、10% 严重)。
小结与避坑建议
Windows 服务器磁盘空间不足,处理原则是“先量化、后清理、再扩容”。WinSxS、卷影副本、IIS 日志、更新缓存是四大隐形大户,用对命令每一块都能省出几个 GB。真正治本的是把日志、页面文件、备份目录从系统盘剥离,并配上监控告警。
避坑清单:
- 绝不手动删除
C:\Windows\WinSxS目录。它包含大量硬链接,删除后系统补丁、角色安装会全面失败,只能重装。必须用 DISM 命令清理。 - 不要随便清空 Security 安全日志。等保 2.0 与多数合规审计要求保留 6 个月以上,先归档。
/ResetBase要慎用。执行后已安装的更新无法卸载,如果某个补丁刚装完就出问题,就没有退路了。建议补丁稳定运行两周后再做。- 页面文件不要直接删到 0。完全禁用页面文件会导致内存转储失败,某些依赖提交内存的组件也会异常;内存小于 32 GB 的服务器尤其别动。
- 卷影副本优先“调上限”而不是“全删”。全删会同时丧失“以前的版本”恢复能力和部分备份软件的还原点。
- 扩容前一定打快照。云盘快照成本很低,但能救回一次误操作。
- 把磁盘监控阈值设在 15% 而不是 5%。留足响应时间,别让告警和故障同时到达。
企业QQ咨询




