ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用CMD命令行备份与还原IIS配置:appcmd实战指南

用CMD命令行备份与还原IIS配置:appcmd实战指南 1. 为什么放着IIS管理器不用偏要敲CMD干Windows运维这行总会碰上几个让人手心冒汗的时刻服务器要迁移了、IIS站点要复制到测试环境、或者某个兄弟手一抖把站点绑定的域名改错了老板站在背后等着你三分钟内恢复。这时候如果还开着IIS管理器挨个站点截图、记参数再跑去另一台机器手动重建那叫自找苦吃。我第一次意识到必须用命令行备份IIS配置是在一次凌晨两点的线上事故里。当时一个客户的多站点环境被人误改了应用程序池的高级设置页面全部503。等我把IIS管理器里二十几个池子挨个检查完、恢复完天都亮了。事后我翻日志配了个计划任务每天凌晨自动导出全站配置——从那以后再遇到类似问题恢复时间从两小时压缩到了两分钟。这篇文章要聊的就是Windows Server环境下如何用CMD命令行工具完成IIS站点配置的导出与导入。整篇文章不依赖任何第三方工具用的都是系统自带的appcmd.exe和%systemroot%\system32\inetsrv\目录下的原生命令。适合的人群很明确IIS运维新手、需要做服务器迁移的开发或运维工程师、以及那些喜欢把所有配置都“代码化”“脚本化”的同行。读完你能获得的最核心能力是用一条命令把整个IIS的站点、应用程序池、绑定、虚拟目录全部备份下来再在任意一台相同版本的系统上完整还原。2. 先把环境摆平IIS命令行工具与常见前置障碍2.1 appcmd.exe是什么东西很多新手第一次接触IIS备份第一反应是去IIS管理器里找“导出”按钮。实际上IIS 7.0之后的版本把整套配置管理能力都封装进了名为Microsoft.Web.Administration的托管接口而appcmd.exe就是挂在它上面的命令行壳子。这个工具的位置固定正常情况下在C:\Windows\System32\inetsrv\appcmd.exe。它的厉害之处在于你几乎能在CMD里完成IIS管理器上的所有操作——创建站点、增删绑定、改应用池、查运行状态、导配置、导备份而且支持XML格式输出。这意味着什么意味着你可以把配置工作变成一行一行可追踪、可版本管理的命令而不是鼠标一顿点完还不知道改了什么。2.2 最容易卡住新手的三个坑动手之前有几个前置条件不满足后面所有命令都会原样吐回一个错误。这三个坑我见过太多人踩第一IIS管理脚本和工具没装。Windows Server默认装IIS的时候不一定勾选“管理服务”里的IIS 管理脚本和工具功能。没装这个功能appcmd.exe根本不存在。装法很简单dism /online /enable-feature /featurename:IIS-WebServerRole /all dism /online /enable-feature /featurename:IIS-ManagementScriptingTools或者走服务器管理器勾选“IIS管理脚本和工具”。第二管理员权限缺失。导出配置可能还好但导入和还原操作一定会写C:\Windows\System32\inetsrv\config目录这个目录的写权限只对System和Administrators组开放。所以CMD窗口一定要“以管理员身份运行”。很多报错0x80070005拒绝访问不是命令写错了就是权限没提起来。第三CPU架构和系统版本需要心里有数。64位和32位系统下appcmd.exe的路径一样但配置文件的结构在不同IIS版本比如IIS 8.5和IIS 10之间需要注意低版本配置还原到高版本一般没问题反过来大概率会出怪毛病。做迁移的时候先确认目标系统的IIS版本不低于源系统。提示检查IIS版本最快的方式是打开CMD输入reg query HKLM\SOFTWARE\Microsoft\InetStp /v VersionString一眼就能看到类似10.0.17763.1的输出。3. 导出配置一条appcmd命令搞定全站备份3.1 先学会用add backup做无损备份IIS从7.0开始提供了一套“配置历史”机制底层是把整个applicationHost.config文件连同加密的配置节一起打包放到指定目录。命令行对应的就是appcmd add backup。基本用法极其简单%windir%\system32\inetsrv\appcmd.exe add backup 20250117_mysite_backup执行完系统会在C:\Windows\System32\inetsrv\backup\20250117_mysite_backup目录下生成一套完整的配置快照里面最关键的是applicationHost.config、administration.config以及加密密钥相关的元数据。这里有个细节值得注意add backup做的是“配置级备份”不是“内容级备份”。它备份的是站点结构、绑定信息、应用池参数、认证配置、URL重写规则等但它不会备份你的网站文件、证书私钥和数据库内容。也就是说它能保证“站点配置”原样恢复但网站物理文件还是得靠Robocopy这类工具单独拖。3.2 查看和管理已有的备份备份多了之后你需要确认某个备份是否存在或者想删掉过于陈旧的备份腾空间。对应命令:: 列出所有备份 %windir%\system32\inetsrv\appcmd.exe list backup :: 查看特定备份的详细内容 %windir%\system32\inetsrv\appcmd.exe list backup 20250117_mysite_backup /xml :: 删除指定备份 %windir%\system32\inetsrv\appcmd.exe delete backup 20250117_mysite_backuplist backup的输出会显示备份名和创建时间。每次重大变更前做一个命名清晰的备份比事后满世界找恢复点要靠谱得多。我的习惯是命名里带上日期和用途标记比如backup_before_sslchange_20250117一望即知。3.3 全量导出为XML给配置“拍一张可移植的照片”除了用add backup做内部备份还有一种场景更常见我们要把配置导出来放到另一台服务器上导入。这种情况下直接把关键配置以XML格式导出更灵活。三个最常用的导出命令:: 导出所有站点配置 %windir%\system32\inetsrv\appcmd.exe list site /config /xml D:\iis_config\sites_export.xml :: 导出所有应用程序池配置 %windir%\system32\inetsrv\appcmd.exe list apppool /config /xml D:\iis_config\apppools_export.xml :: 导出所有应用含虚拟目录归属 %windir%\system32\inetsrv\appcmd.exe list app /config /xml D:\iis_config\apps_export.xml把这三个XML文件用文本编辑器打开看你会发现里面记录了你能在IIS管理器里看到的所有参数bindings、physicalPath、applicationPool、enabledProtocols、managedRuntimeVersion、autoStart等等。这等于给整套IIS配置拍了张可移植的“照片”。我还喜欢顺手把根配置里的location路径也导出一下因为这能覆盖到站点级别的override设置%windir%\system32\inetsrv\appcmd.exe list config /xml D:\iis_config\full_config_export.xml4. 导入还原从备份恢复到指定站点的完整链路4.1 还原整个IIS配置restore backup的威力与代价当服务器配置被搞乱或者你要把一台机器完全复原到某个时间点时用restore backup是最快的%windir%\system32\inetsrv\appcmd.exe restore backup 20250117_mysite_backup执行后IIS会拿备份目录里的applicationHost.config覆盖当前生效的配置文件并自动重启WASWindows Process Activation Service和W3SVCWorld Wide Web Publishing Service来让所有改动生效。这里必须泼盆冷水restore backup是“整体覆盖”不是“增量合并”。意思是如果备份之后你新建了三个站点一还原这三个站点就没了——因为当前配置被整个替换成了备份时的状态。所以在做restore操作之前一定要先想清楚这是不是真的想要的结果。我见过一个同行凌晨还原配置把白天新加的临时测试站点弄丢了客户早上过来脸都是绿的。4.2 用导入XML的方式安全迁移站点如果不想整个覆盖更稳的做法是基于XML逐步导入。这个流程在服务器迁移中尤其好用。先把前面导出的站点XML文件传到目标服务器然后逐项导入。顺序上有个讲究先导入或重建应用程序池再导入站点。因为站点配置里引用了应用池的名字如果池子不存在导入会直接报错。:: 导入应用池 %windir%\system32\inetsrv\appcmd.exe add apppool /in apppools_export.xml :: 导入站点 %windir%\system32\inetsrv\appcmd.exe add site /in sites_export.xml分两步执行完以后再启动站点:: 查看导入后的站点状态 %windir%\system32\inetsrv\appcmd.exe list site :: 如果状态是Stopped启动它 %windir%\system32\inetsrv\appcmd.exe start site 你的站点名这种方式的好处在于它只“新增”不“覆盖”目标服务器上原有的站点不受影响。缺点是你得确认导入的站点跟前端绑定端口、主机名不会冲突否则同样会报错。4.3 小范围导入单站点、单应用池的补丁式还原有时候我们根本不需要整站全量导入只是想在现有环境里补一个站点。appcmd add site配合参数就能实现%windir%\system32\inetsrv\appcmd.exe add site /name:NewSite /physicalPath:D:\wwwroot\NewSite /bindings:http/*:8080:newexample.com这种“补丁式”导入跟从XML导入的区别在于你可以在命令里按需组装站点的各个属性而不必受原有导出的约束。实际工作中迁移单个站点到同服务器另一个端口或者另一块磁盘我最常用的就是这类命令。5. 单站点迁移实战不碰全量备份的精细操作5.1 为什么全量备份不适合跨服务器单站迁移假设你管理着十来个站点但这次只需要把其中一个迁移到新服务器。用add backuprestore backup显然太粗暴它会把新服务器上已有的其他配置全部替换掉。这时候正确的姿势是“按需导出 按需导入”也就是只从源服务器导出目标站点的定义再在目标服务器上单独建。这一步的操作思路是第一步在源服务器上把指定站点的配置导出为XML。%windir%\system32\inetsrv\appcmd.exe list site OldSite /config /xml D:\iis_config\OldSite.xml %windir%\system32\inetsrv\appcmd.exe list apppool OldSiteAppPool /config /xml D:\iis_config\OldSiteAppPool.xml第二步把XML文件传到目标服务器注意调整物理路径。源服务器和目标服务器的网站目录很可能不一样比如源是D:\wwwroot\OldSite目标是E:\websites\OldSite。直接用原XML导入物理路径会指向错误位置。解决方案是导入前先改XML里的physicalPath属性或者在导入后用set site命令修正。我的习惯是后者因为改动更直观:: 导入应用池 %windir%\system32\inetsrv\appcmd.exe add apppool /in OldSiteAppPool.xml :: 导入站点 %windir%\system32\inetsrv\appcmd.exe add site /in OldSite.xml :: 修正站点物理路径 %windir%\system32\inetsrv\appcmd.exe set site OldSite /physicalPath:E:\websites\OldSite :: 启动站点验证 %windir%\system32\inetsrv\appcmd.exe start site OldSite第三步同步调整绑定和协议。新环境很可能端口、域名都不一样。用set site改绑定格式如下%windir%\system32\inetsrv\appcmd.exe set site OldSite /bindings:http/*:8090:newsite.example.com执行完建议list site OldSite看一眼完整配置确认bindings、physicalPath、applicationPool三项都符合预期再放流量进来。5.2 别忘了证书、依赖组件和环境变量单站点迁移最容易漏掉三样东西SSL证书。如果站点启用了HTTPS导入配置后目标服务器上没有对应的证书绑定会显示证书加载失败。证书本身.pfx文件需要手动导入证书库再在set site时指定certificateHash和certificateStoreName比如certificateHash你的证书指纹 /certificateStoreName:MY。URL Rewrite规则。如果源服务器装了URL Rewrite模块这部分规则存在applicationHost.config的rewrite节里不会跟着单站点XML导出。你需要单独导出appcmd list config OldSite /section:rewrite /config /xml。应用程序池的CLR版本和管道模式。很多花费大量时间排查的503、500错误最后都发现是目标服务器的.NET运行时版本没装或者应用池的managedRuntimeVersion与站点要求的版本不匹配。5.3 实测中的意外情况那些不按套路出牌的配置项迁移过程中我踩过几个比较刁钻的坑说给大家避雷。第一个坑是应用程序池的Identity类型。源环境用的是ApplicationPoolIdentity到了新机器如果站点文件所在目录的ACL没有给这个虚拟账号授权直接给你抛个403.5。处理方式是导入后用icacls给目录加权限或者干脆把Identity改回LocalSystem测试环境图省事可以用生产环境不建议。第二个坑是站点级配置里的自定义环境变量。有些站点会在appcmd set config里塞自定义的appSettings或环境变量这些内容不一定在最初的list site /config /xml里全量体现。最容易排查的方式是直接在源机器上对比appcmd list config OldSite的完整输出和导入后新机器的输出一眼就能看出缺了什么。6. 还原路上的经典翻车点与排查思路6.1 报错0x80005000管理员权限的“影子错误”这个错误在热词里出现频率很高很多人的第一反应是配置文件权限问题、目录不存在、或者IIS组件损坏。我的排查经验是它最常出现在权限不足尤其是当你的CMD窗口不是管理员权限、却试图通过appcmd set site修改applicationHost.config的时候。遇到0x80005000先别急着改配置文件。按顺序检查当前CMD窗口标题栏是否显示“管理员: 命令提示符”没有就重启CMD再试。确认C:\Windows\System32\inetsrv\config\applicationHost.config文件的ACL里包含NT SERVICE\WAS和SYSTEM的读写权限。如果权限都没问题再看C:\Windows\System32\inetsrv\config目录下是否有异常生成的临时文件.tmp有就手动清理后再执行。6.2 导出的XML导入时报“已存在”或“冲突”另一种高频翻车点是在目标服务器上导入站点XML时目标服务器上已经有一个同名站点或者同名应用池。appcmd add site /in可不会自动帮你跳过重名项它会直接报ERROR ( message:Cannot add duplicate collection entry of type site... )。正确做法是先查后导:: 查目标机器上是否已存在同名试用池或站点 %windir%\system32\inetsrv\appcmd.exe list apppool | findstr /i OldSiteAppPool %windir%\system32\inetsrv\appcmd.exe list site | findstr /i OldSite如果存在就用delete清理掉或者改用不同的名称导入后再set改名。记住一个原则导入动作只做add不做merge所以事前检查是必须养成的操作习惯。6.3 端口、主机名与证书的三角关系绑定的问题最隐蔽。很多时候配置导入成功站点也处在Started状态但从外部浏览器访问却打不开。用netstat -ano | findstr :8080查端口监听发现IIS根本没监听这个端口——原因多半是绑定里写的主机名和访问地址不匹配或者这个端口已被其他进程占用。排查这类问题我的思路是:: 查看站点当前绑定的完整信息 %windir%\system32\inetsrv\appcmd.exe list site OldSite /text:* :: 查看端口占用情况 netstat -ano | findstr :8080 :: 如果确定端口被占用修改绑定换端口 %windir%\system32\inetsrv\appcmd.exe set site OldSite /bindings:http/*:8091:改完绑定的同时记得同步防火墙规则。Windows防火墙里如果有针对旧端口的入站规则新端口上不添加netsh advfirewall firewall add rule放行规则外部同样访问不了。6.4 高版本IIS配置往低版本导各种兼容性怪病的根源IIS 10的配置里会出现一些IIS 8.5没有的节比如webSocket、更细粒度的安全配置项等。低版本IIS解析到未知节点时一般会直接忽略但某些情况下它会拒绝加载整个applicationHost.config导致站点全体500.19。处理这类问题没有银弹最稳妥的做法是导入前先看一眼目标服务器的IIS版本再针对差异配置做筛查。比如目标服务器不支持的rewrite规则就要么确认装了对应模块要么先在XML里剔除对应节点。我在跨版本迁移时一定会先在测试机上跑一遍完整导入流程确认无误后才上生产。7. 从一顿操作到固化流程把备份做进日常命令学会了接下来要思考的问题就是怎么保证下次出问题时手上一定有最新的备份可用。我现在的做法很简单在源服务器上建一个D:\scripts\backup_iis.cmd脚本内容包含三行核心命令echo off set BKNAMEauto_backup_%date:~0,4%%date:~5,2%%date:~8,2% %windir%\system32\inetsrv\appcmd.exe add backup %BKNAME% for /f tokens1 %%i in (%windir%\system32\inetsrv\appcmd.exe list backup /text:name ^| findstr auto_backup_) do ( %windir%\system32\inetsrv\appcmd.exe delete backup %%i /force )大概逻辑是每天生成一个带日期的备份名然后删除掉所有auto_backup_开头的旧备份。这样既保证每天都有一个快照又不会被无限膨胀的备份目录拖垮磁盘。配合任务计划程序每台IIS服务器上放一个每天凌晨2点触发的计划任务指向这个脚本运行账户设为SYSTEM就不需要额外的运维干预了。实际跑下来这条备份链路最让我省心的地方在于任何一次配置变更前我都会手动再执行一次add backup形成一个“变更前时间点”。万一新配置把站点搞挂了一句restore backup回到变更前状态比打开IIS管理器一条条改回来不知道快多少倍。最后分享一个小技巧给关键服务器做迁移演练时别等到业务低峰期才动手。先在测试机上完整跑一遍导出、导入、改路径、调绑定、验证书的流程把日志留下来。真到生产环境操作的时候你手里握着的是一份经过验证的步骤而不是一堆靠临场发挥的命令。这套玩法我用了几年最大的感受就是——面对IIS配置问题手里有备份和没有备份心态完全是两回事。
返回列表