我们计划自动创建用于构建基础架构的虚拟机,以便我们可以:
- 根据需求扩展构建资源,例如在需要时添加更多构建代理,在不需要时删除它们
- 当机器死机时,重新创建全部或部分构建环境
- 当我们需要设置测试时,复制构建环境
此过程的一个步骤是自动创建 VM 基础映像(在我们的示例中使用 Hyper-V)。为此,我们有一个脚本:
- 使用 ISO 创建新的 VHDX转换-WindowsImage脚本。我们目前正在使用 Windows 2012R2,但希望在 2016 可用时尽快开始使用。
- 向新的 VHDX 添加一个无人参与脚本,其中包含我们需要的所有基本配置
- 使用最新的 Windows 补丁更新 VHDX应用-WindowsUpdate脚本
- 根据 VHDX 创建新的 Hyper-V VM 并启动它
- 等待虚拟机启动并等待 WinRM 服务准备好接受远程连接
- 等待windows完成初始配置和新补丁的配置
- 应用任何进一步的补丁
- 重新启动以完成最新补丁的配置
- 等待 Windows 完成补丁配置
- 将 sysprep 脚本推送到机器并调用该脚本。这将运行 sysprep,然后关闭机器
- 删除虚拟机但保留 VHDX
- 从 VHDX 中删除 sysprep 和无人参与文件,然后压缩 VHDX
- 将 VHDX 移动到模板位置并标记为只读
我们遇到的问题出现在步骤 6 和 9。理想情况下,我们应该等待所有配置完成后再重新启动/关闭机器,但似乎没有办法检测 Windows 是否已完成配置阶段。
通过 UI 可以非常清楚地看到每个步骤的完成情况,因为登录 UI 直到流程准备就绪才会显示。但是,当使用 WinRM 远程连接到计算机时,情况就不那么清楚了,因为 WinRM 在完成配置工作之前提供了对计算机的访问权限。
所以问题是,通过远程连接检测 Windows 是否已完成配置更新等的最万无一失的方法是什么,以便我们可以重新启动/关闭机器而不会在以后引起问题。
- - - 编辑 - - -
最后,我们使用了 Katherine 答案的修改版本,因为我们的脚本也等待windeploy
和ngen
完成。考虑ngen
到直到操作系统完成初始化后才能完成,这是可行的,而且作为奖励,最终的 VHDX 将具有所有 .NET 框架 ngen-ed,这意味着我们在创建模板磁盘的新虚拟机时不必处理这个问题。我们用来创建的两个脚本VHDX 模板以及创建本地测试环境在 github 上,如果有人感兴趣的话。
答案1
这个答案听起来可能有点奇怪,但是......
有一个 PowerShell 脚本可用于检查 Nagios 是否有可用的更新。您可能可以使用此脚本或其变体来达到您的目的,而无需使用 Nagios。
至于它们是否正在进行,请检查 Wuauclt 和 TrustedInstaller 是否正在运行。 微软关于服务器核心更新的建议可能会有所帮助:
根据安装的更新,您可能需要重新启动计算机,尽管系统不会通知您这一点。要确定安装过程是否已完成,请使用任务管理器验证 Wuauclt 或 Trusted Installer 进程是否未主动运行。您还可以使用“查看已安装的更新”部分中的方法检查已安装更新的列表。
您可能可以使用类似 的方法来获取该信息Get-Process -Computername YourImage TrustedInstaller.exe
。在 Wuauclt 和 TrustedInstaller 进程完成后,就可以安全地重新启动了。
答案2
每个 Windows 更新补丁都会在安装事件日志中写入几个事件。
- 事件 ID 1 - 启动程序包 KB#### 的更改
- 事件 ID 4 - 需要重新启动才能将程序包 KB#### 更改为已安装状态
- 事件 ID 2 - 程序包 KB#### 已成功更改为已安装状态
确定所有补丁都已应用的一种方法是循环检查事件 ID 4。将该事件的时间与当前时间进行比较。如果 5 分钟或 10 分钟内没有写入事件 ID 4,则所有补丁可能都已完成,并准备重新启动。
我不清楚您是想在补丁安装完成后进行第一次重启(事件 4),还是在补丁配置完成后进行第二次重启(事件 2)。此代码执行前者。只需将 filterHashTable 更改为事件 ID 2,即可在执行步骤 10 之前进行另一次重启。
$target = "bart"
$found = $false
while (-not $found) {
$lastEvent4 = (get-winevent -comp $target -maxEvents 1 -filterHashTable @{ Logname='Setup'; id = '4';}).timeCreated
if (((get-date) - $lastEvent4).totalMinutes -gt 10) {
"do reboot"
restart-computer -comp -$target
$found = $true
} else {
"wait"
start-sleep 60
}
}
答案3
我使用以下方法取得了很好的效果:等待 Windows 将 Windows 模块安装程序服务(又名 TrustedInstaller)的启动类型更改为手动(按需启动) - 重新启动后。此时,更新已完成安装。
补丁安装后,受信任的安装程序进程有时会继续运行?但是服务启动类型仍然重置为手动。
您可以通过查看以前的事件日志消息并关联系统日志和设置日志之间的事件来亲自验证上述观察是否一致/正确。
Windows 模块安装程序的启动更改被记录为 7040 系统事件,并且它与重新启动后安装日志中的最后一个事件 2 相关。
我认为,首次安装更新时,此服务设置为“自动启动”,以防需要重新启动。安装最后一个补丁后,它会重新设置为“手动”(无论是否需要重新启动)。
在某些服务器上,我注意到受信任的安装程序启动会快速从手动切换到自动并切换回来,这种情况可能每小时左右发生一次。我怀疑这是某些应用程序定期检查更新。但是,根据我的经验,通常可以安全地假设,如果启动是手动的,则不会发生修补。