如何远程检测窗口已重新启动后完成修补程序configuration

我们计划自动为我们的构build基础设施创build虚拟机,以便我们能够:

  1. 根据需求扩展构build资源,例如在需要时添加更多构build代理,并在不需要时删除它们
  2. 当机器死亡时,重新创build全部或部分构build环境
  3. 当我们需要testing设置时复制构build环境

此过程中的一个步骤是自动创buildVM基本映像(在我们的情况下使用Hyper-V)。 为此,我们有一个脚本:

  1. 使用Convert-WindowsImage脚本从ISO创build新的VHDX。 目前我们正在使用Windows 2012R2,但一旦可用,我们将尽快开始使用。
  2. 使用我们所需的全部基本configuration将无人参与脚本添加到新的VHDX
  3. 使用Apply-WindowsUpdate脚本使用最新的Windows修补程序更新VHDX
  4. 基于VHDX创build一个新的Hyper-V VM并启动它
  5. 等待VM启动并等待WinRM服务准备好接受远程连接
  6. 等待Windows完成初始configuration和新修补程序的configuration
  7. 应用所有更多的修补程序
  8. 重新启动完成最新补丁的configuration
  9. 等待Windows完成configuration补丁
  10. 将sysprep脚本推送到机器并调用该脚本。 这将运行sysprep,然后closures机器
  11. 删除VM但保留VHDX
  12. 从VHDX中删除sysprep和unattend文件,然后压缩VHDX
  13. 将VHDX移动到模板位置并标记为只读

我们遇到的问题是在第6步和第9步。理想情况下,我们等待所有的configuration完成之前,我们重新启动/closures机器,但似乎没有一种方法来检测窗口已完成configuration阶段。

当通过用户界面时,任何一个步骤完成时都非常清楚,因为login用户界面在进程准备就绪之前不会显示出来。 但是,当使用WinRM远程连接到计算机时,这是不太清楚的,因为WinRM在完成configuration工作之前提供对计算机的访问。

所以问题是什么是最有远见的方式来检测远程连接的Windows已经完成configuration更新等,以便我们可以重新启动/closures机器,而不会导致问题以后。

——编辑—–

最后,我们正在使用Katherine的答案的修改版本,因为我们的脚本还等待windeploywindeploy完成。 鉴于ngen在操作系统完成初始化之后才能完成,作为奖励,最终的VHDX将拥有所有的.NET框架,这意味着当我们创build时,我们不需要处理这个框架新模板磁盘的虚拟机。 我们用来创buildVHDX模板的脚本和创build本地testing环境的脚本都在github上,以防有人感兴趣。

这可能听起来像一个奇怪的答案,但…

有一个PowerShell脚本来检查Nagios是否有可用的更新 。 你可以使用这个脚本或者一个变体来实现你的目的,没有Nagios。

至于是否正在进行,请检查Wuauclt和TrustedInstaller是否正在运行。 微软关于服务器核心更新的build议可能对此有所帮助 :

根据所安装的更新,您可能需要重新启动计算机,但系统不会通知您这一点。 要确定安装过程是否已完成,请使用“任务pipe理器”来validationWuauclt或“受信任的安装程序”进程是否正在运行。 您还可以使用“查看安装的更新”部分中的方法来检查已安装更新的列表。

你可以用类似于Get-Process -Computername YourImage TrustedInstaller.exe这些信息。 在Wuauclt和TrustedInstaller进程完成之后,重启应该是安全的。

每个Windows更新修补程序将在安装程序事件日志中写入几个事件。

  • 事件ID 1 – 启动对程序包KB ####的更改
  • 事件ID 4 – 必须重新启动才能将包KB ####更改为已安装状态
  • 事件ID 2 – 包KB ####已成功更改为已安装状态

确定所有补丁的一种方法是应用循环检查事件ID 4.比较该事件的时间与当前时间。 如果没有事件ID 4已经写了5或10分钟,那么所有的事件都可能已经完成,并准备重新启动。

我不清楚在补丁安装完成(event4)时是否要进行第一次重新引导,或者在完成configuration(事件2)后进行第二次重新引导。 这个代码做前者。 在步骤10之前,只需将filterHashTable更改为事件ID 2,以便重启另一次。

 $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 } } 

使用以下方法取得了巨大的成功:等待Windows将Windows模块安装程序服务(又名TrustedInstaller)的启动types更改为手动(Demand Start) – 重新启动后。 在这一点上,更新已经完成安装。

受信任的安装程序进程有时会在补丁安装后继续运行? 但服务启动types仍然重置为手动。

您可以通过查看以前的事件日志消息并关联系统日志和安装日志之间的事件来validation上述观察是否一致/正确。

Windows模块安装程序的启动更改logging为7040系统事件,并且与重新启动后的安装程序日志中的最后一个事件2相关联。

我认为,当第一次安装更新时,如果需要重新启动,此服务设置为“自动启动”。 当安装最后一个补丁(不pipe是否需要重新启动)时,它将被重新设置为“手动”。

在某些服务器上,我注意到受信任的安装程序启动很快就会从手动切换到自动并返回,这可能会在每个小时左右发生。 我怀疑这是一些定期检查更新的应用程序。 但是,我的经验是,假设启动是手动的,那么一般来说似乎是安全的,那么就不会发生修补。