System Center

System Center Operations Manager 中的 Windows PowerShell

Marco Shaw

 

概览:

  • OpsMgr 命令外壳
  • OpsMgr Monitoring 提供程序
  • 自动化常见的管理任务
  • 一些实际的 Windows PowerShell 示例

内容

Operations Manager 命令外壳
OpsMgr Monitoring 提供程序
自动化常见任务
实际示例
结束语

Windows PowerShell 是一种用于自动执行任务的功能强大的新型脚本编写语言,System Center Operations Manager 2007 (OpsMgr) 赋予了管理员对这种语言的访问权限。自从 2006 年 11 月向公众发布以来,其下载次数已超过两百万。

在本文中,我将介绍 Windows PowerShell® 并讨论如何将其应用到 Operations Manager 中。我将展示一些可通过 Windows PowerShell 以更简单、更自动化的方式来完成的常见任务,还会向您推荐一些网站,其中提供了许多有用的脚本和解释。另外我还收集了许多 Windows PowerShell 专家的独到见解和博客帖子。

虽然 Microsoft 已开始发布 Windows PowerShell 2.0 的社区技术预览版 (CTP),但这些版本还无法马上应用到生产中,它们尚未在 OpsMgr 中进行测试,因此不能安装到生产系统中。

Operations Manager 命令外壳

在 OpsMgr 中通过命令外壳来访问 Windows PowerShell,命令外壳类似于默认的 Windows PowerShell 环境,不同之处在于它加载了一个控制台文件和一个脚本,可通过 OpsMgr cmdlet、函数以及默认连接来初始化环境。

命令外壳可以通过 OpsMgr 的 Start(开始)菜单上的图标来启动,也可以通过右键单击 OpsMgr UI 控制台中的计算机名称(请参阅图 1)来启动。这会将您直接带入 OpsMgr Monitoring 驱动器路径中(稍后会对其进行介绍)。

fig01.gif

图 1 通过 OpsMgr UI 打开命令外壳(单击图像可查看大图)

Windows PowerShell 通过 OpsMgr SDK 与 Ops­Mgr 相连接。让管理员感到幸运的是,对于希望通过命令行来自动执行或完成的许多任务,系统都已为其提供了 cmdlet。如果没有用于某个特定任务的 cmdlet,可使用 Windows Power­Shell 与 SDK 进行交互。

Operations Manager 命令外壳提供的命令都包括在一个管理单元中,管理单元是一个 DLL,它由 Windows PowerShell 所加载,其中包含用于 OpsMgr 管理的 cmdlet。管理单元还包括 OperationsManager­Monitoring Windows PowerShell 提供程序。此工具也称为监控提供程序,利用它可以在连接、组和监控对象之间导航,这非常类似于文件系统的导航。

可使用 Get-OperationsManager­Command cmdlet 获取特定于 OpsMgr 的所有 cmdlet 的列表,如图 2 所示。(在第一个版本中,它是一个并不支持 tab 键完成功能的函数;在 SP1 中则变成了 cmdlet。)初始版本的 Operations Manager 中包括 74 个 cmdlet,而 OpsMgr SP1 包括 87 个。

fig02.gif

图 2 获取 OpsMgr cmdlet 的列表(单击图像可查看大图)

OpsMgr Monitoring 提供程序

通过使用 cmdlet Set-Location(或别名 cd),您可以浏览组和计算机的布局。默认 Monitoring 驱动器的基本布局类似于下面所示:

Monitoring:\->RMS->Groups (as defined in OpsMgr)
  ->Computers(as defined in OpsMgr)

在此处您还可以获取更多的专用对象。请注意,在本例中我仅处理一个简单的环境,其中只有一台管理服务器。管理组中安装的第一台管理服务器称为根管理服务器 (RMS)。

命令外壳启动后,将创建一个名为 Monitoring 的驱动器,将此驱动器映射到 OperationsManager­Monitoring 提供程序的根目录,并将当前位置或路径设为 Monitoring 驱动器的根目录。命令外壳随后将在注册表中搜索要连接的默认 RMS 的名称。如果 RMS 连接成功,则当前位置或路径将被设置为该连接(或 RMS)的名称,如图 3 所示。

fig03.gif

图 3 命令外壳位置被设置为 RMS(单击图像可查看大图)

自动化常见任务

让我们来看一看 Windows PowerShell 如何处理一些最常见的管理任务。

控制维护模式 无论处理何种任务,通常都会指定希望它发生的日期和时间。我将简单介绍一下 Get-Date cmdlet,向您展示实现此功能是多么简单。图 4 显示了一些示例。

fig04.gif

图 4 使用 Get-Date cmdlet(单击图像可查看大图)

正如您所看到的,我创建了一个 $date 变量,它包含了一个代表当前时间的对象。然后,我将利用一些记载的此对象支持的方法来演示如何轻松获取五分钟以及五小时以后的日期和时间。要想获取过去的值,只需用 (-5) 代替 (5) 即可。

当需要阻止来自计算机的所有警报时,即可启用维护模式。OpsMgr 2007 允许您将某个 Windows® 服务(或是特定的数据库)而不是整个计算机或组置于维护模式中。以下三个 cmdlet 专门用于处理维护模式任务:Get-MaintenanceWindow、New-MaintenanceWindow 和 Set-MaintenanceWindow。

要在命令外壳内部将计算机置于维护模式中,可使用 Monitoring 提供程序导航到所需的计算机或监控对象,然后调用 New-MaintenanceWindow cmd­let,如图 5 所示。正如您看到的,此操作将把名为 Denver.contoso.com 的计算机置于维护模式中。我还定义了维护窗口立即生效的开始时间以及一小时后生效的结束时间。请注意,使用此方法将计算机置于维护模式并不会停止所有警报,因为此对象的 HealthService 和 HealthService­Watcher 实例仍处于启用状态。

fig05.gif

图 5 使用 New-MaintenanceWindow cmdlet(单击图像可查看大图)

Microsoft Ops­Mgr 团队的项目经理 Boris Yanushpolsky 提供了一些非常方便的 Windows PowerShell 代码,可用来将引用某台计算机的所有对象设为维护模式,并且他还解释了在创建脚本后应如何使用此代码。要了解更多信息,请访问他的博客:blogs.msdn.com/boris_yanushpolsky/archive/2007/07/25/putting-a-computer-into-maintenance-mode.aspx

有时需要确定维护模式中是否包括不应存在的对象。但是,要通过遍历所有对象的方式进行寻找,工作量可能会相当大。幸运的是,Boris Yanushpolsky 再次带着 Windows PowerShell 脚本前来解困,这次的这个脚本使用的是 OpsMgr SDK。您可以直接从他的博客帖子 (blogs.msdn.com/boris_yanushpolsky/archive/2007/08/06/so-what-is-in-maintenance-mode.aspx) 下载脚本代码并粘贴到命令外壳窗口中,以获取处于维护模式的所有对象的列表。

当某个对象处于维护模式时,您可能希望在最初指定的结束时间之前结束维护期。如果熟悉 Windows PowerShell,您可能希望能有一个包含 stop 或 remove 动词的 cmdlet,但实际上必须要使用 Set-MaintenanceWindow,如图 6 所示。

fig06.gif

图 6 使用 Set-MaintenanceWindow 更改结束时间(单击图像可查看大图)

管理代理 管理员经常需要处理代理,共有六个 cmdlet 和一个函数(截至当前版本)用来处理各种与代理相关的任务。可通过以下命令获取它们的列表:

Get-Command *-agent*

从 SP1 版本开始,Install-AgentBy­Name 被打包为一个 cmdlet 而非函数。建议使用 Install-AgentByName cmdlet,因为它所提供的支持和一致性基础更为出色。

在命令外壳随附的内置帮助中提供了一些有关 Install-Agent 和 Uninstall-Agent cmdlet 使用方法的不错示例。Microsoft Ops­Mgr 团队的高级软件设计工程师 Roger Sprague 在他的博客中提供了一种替代方法,图 7 再现了该方法(原帖地址:blogs.msdn.com/scshell/archive/2006/09/28/getting-started.aspx)。

此脚本非常适合 OpsMgr RTM(必须位于监控提供程序的根目录 — 在本文中为 monitoring:\oxford.contoso.com),但它不能用于 OpsMgr SP1。为使其能在 OpsMgr SP1 中正常运行,应将图 7 中的第一条命令改为:

 $managementServer = Get-RootManagementServer

图 7 安装代理

# Get the Root Management Server.
$managementServer = Get-ManagementServer -Root: $true

# Create the discovery configuration for computer2 and computer3.
$discoConfig = New-WindowsDiscoveryConfiguration -ComputerName: computer2, computer3

# Discover the computers.
$discoResult = Start-Discovery -ManagementServer: $managementServer -WindowsDiscoveryConfiguration: $discoConfig

# Install an agent on each computer.
Install-Agent -ManagementServer: $managementServer -AgentManagedComputer: $discoResult.CustomMonitoringObjects

此时,代理被安装在要监控的远程系统中,但还有最后一步,即管理服务器必须实际接受这个新代理,系统才会完全受到监控。如果不采取进一步的行动,监控服务器会自动接受这个新代理以便进行监控。但是,也可以使用 Get-AgentPendingAction cmdlet 来快速跟踪此接受过程。下面的单行命令可以快速跟踪代理接受过程:

Get-AgentPendingAction | Where Object {$_.AgentName –like 
'computer*'} | Approve-AgentPendingAction

通过将其传送到 Reject-AgentPending­Action 而非 Approve-AgentPending­Action,可阻止 OpsMgr 服务器接受此代理(如果操作仍处于未完成状态)。如果它不是未完成的,则改用 Uninstall-Agent cmdlet。

正如我提到的,也可以使用 Install-­AgentByName 在命令行中直接指定将要安装代理的计算机。

使用管理包 有四个 cmdlet 可帮助您处理各种管理包任务。可使用以下命令列出它们:

Get-Command –noun ManagementPack

下面的简单命令可列出目前安装的管理包及其版本号:

Get-ManagementPack | Format-Table –autosize

现在,我将使用命令外壳来安装两个常用管理包(使用以下安装程序):

  • Internet Information Services System Center Operations Manager2007 Management Pack.msi
  • Windows Server® Base OS System Center Operations Manager2007 Management Pack.msi。

由于我的目标是展示命令外壳如何使常规任务更容易,因此我将尽可能使用最少的命令来实现此目的(如图 8 所示)。我本来可以更改此安装过程以将 quiet 标记传递到安装程序(.msi 文件),但我想手动选择要将文件提取到的位置。

fig08.gif

图 8 安装管理包(单击图像可查看大图)

接下来,我需要安装常用库文件,方法如下:

Get-ChildItem –Path C:\MPs –filter *Library.mp |
ForEach-Object
  {Install-ManagementPack –filePath $_.FullName}

然后安装另一个必需的管理包:

Get-ChildItem –Path C:\MPs –filter *200?.mp | 
ForEach-Object
  {Install-ManagementPack –filePath $_.FullName}

图 9 所示,内置的命令外壳帮助提供了一些非常出色的示例,可帮助您了解如何使用 Export-ManagementPack cmdlet 来导出未封装的管理包。如果想要导出所有管理包,请更改以下命令行

 $mps=Get-ManagementPack | 
Where-Object {$_.Sealed –eq $false} 
 $mps=Get-ManagementPack

fig09.gif

图 9 导出管理包(单击图像可查看大图)

操控用户角色 Get-UserRole cmdlet 提供了一些用于管理用户的功能,但奇怪的是,它并未同时提供作为补充的 Set cmdlet,而且您通常不会使用它来执行编辑或更新操作(根据 Windows PowerShell SDK 文档)。如图 10 所示,首先我获取当前用户角色的列表,然后向 Read-Only Operators 组添加一个用户(请参阅图 11)。

fig10.gif

图 10 显示用户角色(单击图像可查看大图)

fig11.gif

图 11 添加用户(单击图像可查看大图)

启用审核收集服务 (ACS) ACS 是 Operations Manager 2007 中的一项新的可选功能,简单地说,它提供了一种集中的方式来处理安全审核信息。默认情况下 ACS 是不启用的,通常会在 OpsMgr 部署的某个后续阶段进行配置。

当需要为 ACS 启用大量代理时,Windows PowerShell 可通过帮您自动执行设置过程来为您解围。在 OpsMgr 测试版阶段,Microsoft 提供了一个脚本以在所有代理中启用 ACS。SystemCenterForum.org 的撰稿人和博客作者 Neale Browne 在这方面更深入了一步,添加了对其他参数的支持。

SystemCenterForum.org 站点(一个提供各种 Microsoft® System Center 解决方案的社区站点)提供了两个不同的 Windows PowerShell 脚本,用来自动化 ACS 的设置。要在某个特定组中设置所有代理,可使用 systemcenterforum.org/wp-content/uploads/ACSBulkEnableGroupDisplayName.zip。要设置所有受监控的代理,请下载 systemcenterforum.org/wp-content/uploads/ACSBulkEnableAllAgents.zip

启用代理代表 OpsMgr 环境可能包括无代理的受监控设备。必须将这些设备分配到提供远程监控的管理服务器或受代理管理的设备。可通过以下网址获取有关使用 Windows PowerShell 脚本配置大量代理的详细说明:systemcenterforum.org/enable-agent-act-as-a-proxy-in-bulk-via-powershell。以下网址提供了更新版本的脚本:systemcenterforum.org/wp-content/uploads/Set­AgentProxyBulk_FQDN.zip

有时,特定管理包需要代理还要充当委托代理这一角色。如需详细信息,请参阅管理包文档。

实际示例

以下实际示例进一步演示了 Windows PowerShell 如何帮助实现自动化。

解决警报 您是否曾经不得不删除某个特定计算机的一些警报?这可能是由于应用程序出现了问题或者警报没有被主动解决。下面的单行命令将解决所有解决状态为 0 的警报:

Get-Alert –criteria 'ResolutionState = ''0''' |
Resolve-Alert | Out-Null

以下示例与第一个示例的功能完全相同,但在包含更多未解决警报的更大规模环境中,它的运行速度要快得多:

Get-Alert | Where-Object {$_.ResolutionState -eq 0} |
Resolve-Alert | Out-Null

造成性能差异的原因是在使用条件参数时,传递的值被直接提供给了 SQL Server® 数据库,并且只返回了相关的数据。这可以减少必须传回 Windows PowerShell 控制台的对象。

现在,您就有了一种可以快速删除某台计算机中所有未解决警报的方法。根据需求的不同,您也可以将它设为自动运行。

最后,可通过以下命令快速查看某一天的所有警报:

Get-Alert -criteria 'TimeRaised >= ''4/25/2008'''

可以非常方便地更改日期值,并可将输出传送到 Resolve-Alert cmdlet。

测试警报 有时,您可能希望能够监控 Windows 事件查看器中的特定事件并测试它们。以下两行命令将创建一个快速事件日志条目:

 $api=New-Object -comObject MOM.ScriptAPI
$api.logscriptevent("API test",100,0,
  "Test using PowerShell")

但在默认情况下,它会写入到 Operations Manager 的事件日志中,而这可能并非是您监控要记录的特定事件的位置。幸运的是,Microsoft 的高级现场解决方案工程师 Stefan Stranger 编写了一个在 Windows 事件查看器中创建事件的脚本,可以在写入特定日志时提供更大的灵活性。您可以在 go.microsoft.com/fwlink/?LinkId=120308 找到该脚本。(Stefan 已将该脚本打包在一个 .cab 文件中。您需要下载此文件,然后右键单击它来提取此脚本。)

对于 Stefan 编写的这个脚本,唯一需要注意的是针对事件来源输入的值将决定条目被写入哪个日志。要确保警报被导向到正确的日志,最简单的方法或许是打开 Windows 事件查看器并查找最后一个条目的事件源。

设置所有者 有时,自动设置警报的所有者可能会非常有用。下面的这个简单方法可通过命令外壳来实现此目的:

 $alert = Get-Alert 
  -id f3f73d62-37ab-45ce-a7ff-2bdda0dfaeb4
$alert.set_owner("Administrator")
$alert.update("Updated owner")

此代码的第一行会获取特定警报对象的 ID 并将它传递给 $alert 变量。在第二行中,该变量被用于设置所有者,最后将更新应用到 OpsMgr 数据库。如果使用以下命令检查警报的所有者,则它会变为:

Get-Alert -id f3f73d62-37ab-45ce-a7ff-2bdda0dfaeb4 |
Select-Object Owner

要为整组警报设置所有者,可将代码简化为:

Get-Alert | ForEach-Object {$_.Set_
  Owner("Administrator");
  $_.Update("Owner set")}

恢复监控状态 有时您可能会遇到处于“未受监控”状态的代理。此时,您可能需要快速将所有代理恢复到完全受监控的状态,然后再尝试确定究竟发生了什么。通过直接在命令外壳中运行图 12 所示的脚本,可恢复对受影响的所有代理的完全监控。

图 12 重置运行状况服务存储

 $all="Microsoft.SystemCenter.AllComputersGroup"
$agents = Get-ChildItem Microsoft.SystemCenter.AllComputersGroup | `
  Where-Object {$_.HealthState -eq 'Uninitialized'}
foreach ($agent in $agents)
{
$agent.DisplayName
Push-Location $all\$agent\Microsoft.SystemCenter.HealthService
Get-Task | Where-Object {$_.Name -eq "Microsoft.SystemCenter.ResetHealthServiceStore"} | `
    Start-Task -Asynchronous
Pop-Location
}

请看一看图 12 中的代码。声明变量后,我获取了此 RMS 中所有代理的列表并筛选出了可能存在问题的代理。然后我异步调用了一个任务,在筛选后的列表中重置所有代理的“运行状况服务存储”。

将警报与管理包相关联 图 13 显示了如何获取所有新警报的列表以及每个警报所关联的管理包。

此代码需要一些技巧来确保所有管理包名称都能够被解析。使用的 cmdlet 可能会有所不同,具体取决于警报是来自规则还是来自监控器。(请注意,在图 13 中,我需要针对 Get-Monitor cmdlet 实现一个简单的解决方法。从 OpsMgr SP1 开始,cmdlet 已支持一个新的 ID 参数,这可能会使代码略微得到简化。)

图 13 查找管理包

Get-Alert | Where-Object {($_.PrincipalName -ne $null) -and ($_.ResolutionState = '0')}| `
Format-Table –autosize PrincipalName,Severity, `
  @{Label="MP"
      Expression={If(!($_.IsMonitorAlert)){
        ForEach-Object {
          ((Get-Rule $_.MonitoringRuleId).GetManagementPack()).DisplayName}
       }  
       Else{
         ForEach-Object {
          $id=$_.ProblemId
          ((Get-Monitor -criteria "Id='$id'").GetManagementPack()).DisplayName}
         }
   }
}

易于报告 在升级环境时,可能需要审核所有已安装的代理的版本。只需使用一个简单的脚本即可打印出一份不错的报告:

Get-Agent| `
Format-Table DisplayName,@{ `
  Label="Version"
  Expression={ `
    switch ($_.Version){
    "6.0.5000.0" {"RTM"}
    "6.0.6246.0" {"SP1 (RC)"}
    "6.0.6278.0" {"SP1 (RTM)"}
    }
  }
}

图 14 显示了此脚本的输出。此脚本是 systemcenterforum.org/checking-operations-manager-2007-agent-and-server-versions-via-powershell 中所提供示例的扩展版本。

fig14.gif

图 14 显示了某些代理版本的输出(单击图像可查看大图)

计划任务 您可能希望定期运行某个 Windows PowerShell 脚本。假设使用一台客户端计算机来连接和管理 OpsMgr 服务器,并且在本地已经安装了 OpsMgr 管理工具。同时假设您希望定期(例如每天)运行代理版本报告,并将输出保存到一个以当前日期作为名称的文件中。您可以使用 Windows 内置的任务计划程序从本地计算机中运行脚本。

为此,只需建立一个新任务并将程序设为 powershell.exe(通常位于 C:\Windows\System32\WindowsPowerShell\v1.0 下)即可。创建了任务后,编辑此任务并将命令设置为如下所示运行:

C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe 
  –Command "& {& 'c:\agent_report2.ps1'}"

事实证明,我必须要对原始 Windows PowerShell 代码进行相当多的更改,如图 15 所示。我必须添加 OpsMgr PowerShell 管理单元、创建映射到 Operations­ManagerMonitoring 提供程序的 Monitoring 驱动器,还要创建一个到 RMS 的连接。另外我还需要加载 Ops­Mgr 自定义 Windows Power­Shell 脚本 (Microsoft.Enterprise­Management.OperationsManager.ClientShell.Startup.ps1) 以加载 OpsMgr 专用的函数。

图 15 计划代理版本脚本

Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client
New-PSDrive Monitoring Microsoft.EnterpriseManagement.OperationsManager.Client\
  OperationsManagerMonitoring ""
New-ManagementGroupConnection Oxford.contoso.com

Set-Location 'C:\Program Files\System Center Operations Manager 2007'
./Microsoft.EnterpriseManagement.OperationsManager.ClientShell.NonInteractiveStartup.ps1

$file="C:\$(Get-Date -f `"MMddyyyy`").rpt"

Get-Agent -Path Monitoring:\Oxford.contoso.com | `
Format-Table DisplayName,@{ `
  Label="Version"
  Expression={ `
    switch ($_.Version){
    "6.0.5000.0" {"RTM"}
    "6.0.6246.0" {"SP1 (RC)"}
    "6.0.6278.0" {"SP1 (RTM)"}
    }
  }
} | Out-File $file

但事情还没结束。您可能已经注意到,每次运行此任务时,如果有人登录正在运行脚本的系统,屏幕上就会弹出一个黑色的控制台窗口。Sapien 公司的 Don Jones 和 Jeffery Hicks 提供了一个用来解决此问题的小技巧,可在 blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell 中找到它。

一般来说,需要在 VBScript 中将脚本封装起来。为此,应该使用类似于图 16 所示的代码,而不应从计划任务调用以下命令:

C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe
  –Command "& {& 'c:\agent_report2.ps1'}"

图 16 隐藏弹出窗口

Dim objShell
Set objShell=CreateObject("WScript.Shell")

'enter the PowerShell expression you need to use short filenames and paths 
strExpression="'c:\agent_report2.ps1'"

strCMD="powershell -nologo  -command " & Chr(34) & _
"&{&" & strExpression &"}" & Chr(34) 

'Uncomment next line for debugging
'WScript.Echo strCMD

'use 0 to hide window
objShell.Run strCMD,0

现在,该任务将使用 wscript.exe 程序,并且调用过程将类似于下面所示:

C:\WINDOWS\System32\wscript.exe C:\agent_report.vbs 

最后,可以创建自动化报告,以避免登录用户看到此过程。

结束语

本文快速介绍了 OpsMgr 2007 中提供的全新自动化功能,并概要讲述了如何使用 Windows PowerShell 来实现 OpsMgr 的管理。

非常感谢本文提及的所有人员以及身为 MOM MVP 和 SystemCenterForum.org 创始人的 Pete Zerger 所提供的宝贵帮助。

Marco Shaw 是一家加拿大电信公司的 IT 系统分析师。他从事 IT 行业已有 10 多年的时间,最近还荣获了 Windows PowerShell MVP 奖。Marco 还是新的 PowerShell 社区网站(powershellcommunity.org)的社区副主管。他的博客地址是 marcoshaw.blogspot.com

© 2008 Microsoft Corporation 和 CMP Media, LLC。保留所有权利;未经允许不得复制本文的部分或全部内容。