如何一次性向远程数千台Windows域计算机发出CLI命令?

我需要向我的上数以千计的计算机发出CLI命令(cmd.exe或PowerShell)。 出于显而易见的原因,这不涉及手动执行任务,或者实际访问每台机器。

这应该怎么做?

一般情况:

如何一次性向远程数千台Windows域计算机发出CLI命令?

与我们职业中的大多数事情一样,最简单的方法通常是将工作分解成简单的离散任务,然后按顺序执行这些任务,或者将它们串起来(例如将它们全部放在一个脚本中) 。

在这里,你有三个离散的任务,我可以build立。

  1. 收集客户端列表以发出命令。

  2. 连接到所有的客户端。

  3. 向所有客户发出命令。

在此之后,您可能想要validation结果,就像之前一样,您需要testing您的过程,但为了解决此问题,我们忽略它。 只是不要忽视现实世界中的实施前和实施后testing,否则你会后悔的。

你也有一个“架构”的决定(不pipe是并行还是串行地执行第2步和第3步),但是我们也不要这样做。 我会连续做他们,因为它更容易,我很懒。

请注意,到目前为止,我没有提到任何特定的工具,实现或给定示例。 这是故意的。 到目前为止,上述都是devise和/或build筑工作。 是的,如果你想做“正确的”,那么你实施之前就要devise和规划。 (从一般到具体。)

为了实现这一点,下面是我通过同时向数千台Windows域计算机发出命令解决的具体问题。


具体案例:

我该如何纠正我所有的Windows域计算机上的时间?

由于不需要的原因,我最近遇到了一种情况,最好的解决scheme是向我的雇主拥有的每台计算机发出一个命令,以便解决全域时间偏差问题。 (我的时间也受到了很大的限制 – 只有不到两个小时的时间,所有的计算机都能恢复到与“真实”时间同步的状态)。

  1. 收集客户端列表以发出命令。
    • 由于我的环境的具体情况,加上我的具体工具和技能,我使用PowerShell来做到这一点。
      • 我已将PowerShell部署到环境中的每个客户端,每个客户端都已join域, 我部署了一个GPO以启用WinRM,为了一年前PowerShell远程处理客户端的目的 ,我喜欢PowerShell,并且非常适合使用它。
      • 此处使用的cmdlet是Get-ADComputer ,用于从Active Directory中检索计算机对象。 这是要走的路,因为所有的计算机都是域join的,因此在AD中列出。
    • 因为我想要所有的计算机,并且因为接下来要做的事情,所以我只想将这个列表存储在一个variables中,所以我将使用的具体命令是:
    • $boxlist = Get-ADComputer -filter * (将在Active Directory中find的所有计算机对象的列表存储到名为boxlist的variables中)
  2. 连接到所有的客户端。
    • 由于我匆忙,我会坚持我所知道的。 我经常使用PowerShell远程处理单个计算机或一小组计算机,并且非常适合使用它。 我还没有把它用于这么大的一个团队,但没有理由不应该这样做,我现在没有时间去学习新的东西或者安装新的工具,所以它不得不这样做。
      • New-PSSession是我的这个去的cmdlet。
    • 在这一点上,我意识到我需要提供凭据来实际完成请求,selectGet-Credential cmdlet来执行此操作,并最终以下面的两个命令结束。
    • $creds = Get-Credential domain\user (创build一个提示符,input我的凭证并将authentication令牌存储在名为creds的variables中)
    • $session = New-PSSession -ComputerName $boxlist.name -Credential $creds (使用刚刚提供的凭据为boxlistvariables中的每台计算机创build新的PowerShell会话,并将这些PowerShell会话存储在名为sessions的variables中)
  3. 向所有客户发出命令。
    • 由于在我们的域上configuration时间的方式,以及时间偏移的根本原因,我已经知道我想发出什么命令。 我们有一个GPO,以我们喜欢的方式设置所有Windows时间服务设置,我们的权威时间源同步到真实时间,我们的从属时间源与域的权威时间源同步,而我需要做的仅仅是强迫客户立即重新同步他们的本地时间源。 – 这将调用w32tm /resync /nowait /rediscover ,并使用Powershell,将与Invoke-Command cmdlet一起调用 。
    • Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover} (将调用ScriptScript开关的命令调用到Session开关,其中包含名为sessions的variables,其中包含我的域中所有计算机的列表它)

脚本或其所有组件都已经写好,可以在PowerShell shell中一次执行一行,或者保存为PowerShell脚本文件并运行。 我很着急,这是一个非常短的脚本,我不认为我需要再次使用(或重新创build有困难,所以在shell窗口中逐行打出它是我最终这样做。

 $boxlist = Get-ADComputer -filter * $creds = Get-Credential domain\user $session = New-PSSession -ComputerName $boxlist.name -Credential $creds Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover}