1. 背景介绍:
2022年1月12日微软如期发布了安全补丁和月度汇总补丁,其中需要我们操作的有两部分,一部分是windows server的安全补丁,一部分是exchange 安全补丁。
IT同学像以往一样,立即开始准备修复。windows 补丁我们会通过saltstalk去安装,效率比较高。 Exchange补丁只能逐台操作,通常需要2-3天的时间(10台以上)。
1月14日,微软发布公告,本次补丁会引发其他的故障,比如hyper-v虚拟机不能启动,域控制器频繁重启故障,原因还在进一步定位中,因此建议用户先卸载掉本次补丁。
2. 遇到的问题
虽然我们尚未遇到补丁引发的问题,但是考虑到稳定性,还是计划先卸载掉。
SaltStack版本:
[root@BJ-SaltStack-Node1 ~]# salt-master --version
salt-master 2018.3.5
SaltStack提供了 wusa模块, 该模块提供了wusa.install、wusa.is_installed、wusa.uninstall 三个方法,分别用于安装、检查、卸载。
因为不同的操作系统补丁KB号不同,所以我们可以根据操作系统类型来分批次卸载对应的KB补丁。
一直以来主要用saltstack批量安装补丁,批量卸载还是第一次。
所以先看一下uninstall用法:
[root@BJ-SaltStack-Node1 ~]# salt SC-CD-AVS-01.123.com sys.doc wusa.uninstall
wusa.uninstall:
Uninstall a specific KB.
Args:
path (str):
The full path to the msu file to uninstall. This can also be just
the name of the KB to uninstall
restart (bool):
``True`` to force a restart if required by the installation. Adds
the ``/forcerestart`` switch to the ``wusa.exe`` command. ``False``
will add the ``/norestart`` switch instead. Default is ``False``
Returns:
bool: ``True`` if successful, otherwise ``False``
Raises:
CommandExecutionError: If an error is encountered
CLI Example:
salt '*' wusa.uninstall KB123456
# or
salt '*' wusa.uninstall C:/temp/KB123456.msu
通过相关语法来看,卸载还是比较容易的,wusa.uninstall 后面可以直接跟KB号 也可以跟补丁绝对路径。
- 卸载2012ServerR2:
salt -G 'osrelease:2012ServerR2' wusa.uninstall KB WJ-NPS02.immomo.com: ERROR: Unknown error: 3010
3010: 指的安装或卸载成功,但是等待重启。 详见: https://docs.microsoft.com/en-us/windows/win32/msi/error-codes
- 但是当我们执行卸载2016Server和2019Server时,却遇到错误。如图示:

而指定补丁绝对路径的话,需要将补丁拷贝至目标机器。
我们尝试下是否可行:
[root@BJ-SaltStack-Node1 ~]# salt BJ-WJ-AVS-01.123.com cp.get_file salt://fix_win/WS2019.msu c:\
BJ-WJ-AVS-01.123.com:
c:\WS2019.msu
[root@BJ-SaltStack-Node1 ~]# salt BJ-WJ-AVS-01.123.com wusa.uninstall c:/WS2019.msu
BJ-WJ-AVS-01.123.com:
ERROR: Unknown error: -2147418113
从结果来看,能够支持2016Server和2019Server的补丁安装,却不支持这两个版本操作系统的补丁卸载。 大概是版升级的原因。
公司内部2019和2016的服务器近百台,逐一登录卸载效率太低了,至少一个礼拜。 况且以后说不定也会有类似问题。 总得靠技术解决。
### 3. 改变思路:尝试使用dism
微软官方是明确的不支持使用wusa命令远程安装补丁(所以通过saltstack运行wusa.exe相关的命令或脚本是不可行的),解决方案是dism或Add-WindowsPackage。 如图示:

dism 卸载补丁 可以参考链接 https://www.windowslatest.com/2021/04/23/how-to-uninstall-windows-10-updates-manually/
- 大致2步实现:
- 通过 dism /online /get-packages 获取对应补丁包的id.
- 通过 dism /Online /NoRestart /Remove-Package /PackageName:id 卸载补丁包。
经过测试,在计算机本地确实可行。
如图示:
- dism /online /get-packages 获取补丁id

- dism /Online /NoRestart /Remove-Package /PackageName:id 卸载

既然dism可行,那我们就可以通过saltstack cmd.run 或cmd.script 进行批量卸载了。
### 4. 完美实现
- 通过SaltStack执行批量卸载:
salt -G 'osrelease:2019Server' cmd.run 'dism /online /norestart /remove-package /packagename:Package_for_RollupFix~31bf3856ad364e35~amd64~~17763.2452.1.5 shell='powershell'
卸载过程:

- 结果查验

全部显示该补丁已卸载,最终顺利完成批量卸载功能的实现。