如何通过PowerShell完全停止IIS站点 解决备份文件占用报错
问题场景
通过PowerShell编写网站备份脚本,逻辑为压缩网站根目录归档后传输至SFTP服务器。测试中执行以下任一命令停止目标站点:
Stop-WebSite "website" Stop-IISSite -Name "website"
后续执行压缩操作时仍抛出文件占用错误:
ZipArchiveHelper : The process cannot access the file 'C:\inetpub...\www\AutoMapper.dll' because it is being used by another process.
At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:697 char:30
通过IIS管理器手动停止站点时,备份代码可正常运行。
根本原因
Stop-WebSite和Stop-IISSite命令仅会停止站点的网络监听、断开新的访问请求,不会自动终止站点绑定的应用程序池对应的w3wp工作进程,站点目录下的DLL、静态资源等文件句柄仍被该进程持有,因此压缩时会触发占用报错。手动在IIS管理器停止站点时,默认会联动停止对应应用程序池,释放所有被占用的文件句柄,因此备份可以正常执行。
解决方法
停止站点时同步停止对应的应用程序池,等待文件句柄完全释放后再执行压缩操作,备份完成后重启应用池和站点即可,完整参考代码:
# 配置目标站点名称 $targetSite = "website" # 停止站点 Stop-WebSite -Name $targetSite # 获取站点绑定的应用程序池名称 $relatedAppPool = (Get-WebSite -Name $targetSite).ApplicationPool # 停止关联的应用程序池,释放w3wp进程的文件占用 Stop-WebAppPool -Name $relatedAppPool # 等待3秒确保所有文件句柄释放完成 Start-Sleep -Seconds 3 # 此处放置目录压缩、SFTP传输的备份逻辑 # Compress-Archive ... # 备份完成后恢复应用池和站点运行 Start-WebAppPool -Name $relatedAppPool Start-WebSite -Name $targetSite
残留占用排查
如果执行上述操作后仍提示文件占用,可运行以下命令定位具体占用进程:
# 替换为实际的站点根目录路径 $siteRoot = "C:\inetpub\wwwroot\your_site_path" Get-Process | ForEach-Object { $currentProcess = $_ try { $currentProcess.Modules.FileName | Where-Object { $_ -like "$siteRoot*" } | ForEach-Object { Write-Host "文件被占用 -> 进程ID: $($currentProcess.Id), 进程名: $($currentProcess.ProcessName)" } } catch {} }
如果排查到非IIS工作进程(如日志采集、守护进程等)占用文件,根据实际业务场景处理对应进程即可。
内容的提问来源于stack exchange,提问作者Salar

