使用PowerShell排错----PowerShell入门

PowerShell是一个Microsoft创建的面向对象、命令行、脚本处理的引擎,它建立在.NET Framework之上。PowerShell能够完全访问COM、WMI、Windows Registry及.NET Framework。PowerShell可以让开发者通过新的cmdlets、providers及modules来扩展和增强环境。这种深度的Windows集成及框架的扩展性意味着你可以创建脚本来执行几乎任何你能够想象得到的任务。

使用PowerShell的优势是明显的,自动化重复性的任务、减少错误及协助调查并解决问题。比如通过下面的命令,你就可以快速识别前10项最耗CPU资源的进程:

Get-Process | Sort-Object cpu -Descending | Select-Object -First 10

另一个你想查明的疑难问题是计算机最后一次启动的时间点及正常运行时间,你也可以通过简单的脚本(代码文件:PS_LastBootTime01.PS1)来完成:

$wmiBootTime = (get-wmiobject Win32_OperatingSystem).lastbootuptime;
[DateTime]$lastBootUpTime =
[Management.ManagementDateTimeConverter]::ToDateTime($wmiBootTime);
$uptime = (Get-Date) - $lastBootUpTime;
Write-Host $lastBootUpTime;
Write-Host $uptime;

PowerShell环境

PowerShell 2预装在Win7及Windows Server 2008 R2 OS上。你可以在http://support.microsoft.com/kb/968929找到并下载PowerShell。一旦安装,你就可以以交互式命令行模式使用PowerShell,或者使用脚本编辑器创建包含多语句的脚本文件来执行。要启动交互式命令行,运行PowerShell.exe或在开始菜单里找到“Windows PowerShell ”快捷方式。下面的PowerShell变量允许你查看PowerShell模块位于你电脑的什么地方。

$env:PSModulePath

环境变量包含很多系统配置设置。你可以通过罗列变量的内容来查看它们,命令如下:

PS > get-childitem env:

当你安装PowerShell包作为Windows功能的一部分时,PowerShell模块将会安装在这里,这提供了一个快速的方式来确保当你装载命令行时每个PowerShell支持的Windows功能都有其全部的可用功能。

你所熟悉的cmd.exe的所有命令都可用,如DIR。你也能访问很多PowerShell自带的新命令,这些命令通常称为cmdlets。

PowerShell自带主机应用程式,PowerShell Integrated Scripting Environment (ISE)。这默认安装在Win7,在Windows Server 2008 R2中可以通过安装功能“Windows PowerShell Integrated Scripting Environment (ISE)”来激活。PowerShell ISE能够让你创建脚本文件,按照惯例,该文件会有一个.PS1的扩展名。你还可以在这个环境中调试和运行脚本,尽管这在Notepad的PowerShell 1命令窗口中是个重大改进,但仍然还有改进空间。我更喜欢PowerGUI,一个免费的PowerShell Scripting Environment,可以从www.powergui.org下载。PowerGUI还提供了大量额外的cmdlets,这些在PowerShell里是没有的。如果你使用Visual Studio,那么你是幸运的,因为Adam Driscoll创建了一个Visual Studio,用于PowerShell扩展名(VSX),它使用PowerGUI。你可以从http:/visualstudiogallery.msdn.microsoft.com/01516103-d487-4a7e-bb40-c15ec709afa3下载VSX,这项扩展让你能够在VS IDE里创建、调试和管理脚本。

用户社区贡献了额外的cmdlets和模块。最知名的社区是http://pscx.codeplex.com。实用工具PowerShell Community Extensions (PSCX)值得你下载到本地,因为它包含大量的cmdlets、函数及模块,从而给你的工作带来便利。SQL Server的专区,也称为SQL PowerShell Extensions,可以从http://sqlpsx.codeplex.com下载。
当产品团队开发PowerShell时,安全是重要的考量。 Execution Policy是系统级别的配置,用于指定可以执行的脚本的类型,以防止非法脚本执行。表14-1概括了4种可能的Execution Policy的值。

使用PowerShell排错----PowerShell入门_第1张图片

你可以用cmdlet Get-ExecutionPolicy来检查Execution Policy的当前状态。

基础--Cmdlets, Variables, Advanced Functions和Modules

Cmdlets

Cmdlets遵照[Name]-[Verb]的命名规范,如Get-Process、Get-Help和Remove-Item,以辅助识别。Cmdlets是提供单一功能的.NET类,由PowerShell环境提供,或由.NET开发者提供并安装到PowerShell环境中。通过操作符(|),可以将多个Cmdlets组成单行,前一个cmdlet的输出就是下一个cmdlet的输入。下面的例子使用Get-Process罗列所有正在运行的进程,然后把Get-Process的输出连接到Export-Csv,后者将进程列表导出到一个CSV文件。

Get-Process | Export-Csv .\processes.csv -NoTypeInformation

在命令行中,查看功能是重要的。首先要注意的cmdlet是Get-Help。Get-Help带一个参数CmdletName或TopicName。你也可以提供一些属性:-examples用于显示实例;-detailed用于获取详细信息;-full用于获取所有技术信息。下面的例子使用Get-Help检索Get-Process的所有信息。

Get-Help Get-Process -full

为了“Get-Help”,你需要知道可用的cmdlets,而PowerShell提供的Get-Command就是为了此目的。如果你想找出一个模块中所有可用的cmdlet,你可以使用模块名称来过滤出你想要的结果。用于SQL Server 2012的模块名称是SQLPS,所以你可以使用如下命令来获取SQL Server 2012提供的cmdlet:

Get-Command -Module sqlps

如果没有模块sqlps,那么命令会返回空。你可以导入该模块:

Import-Module sqlps

别名使cmdlets可以有不同的名字,比如PowerShell cmdlet Get-ChildItem为了向后兼容,有别名DIR,在UNIX平台还有别名LS。

Variables

PowerShell提供变量来存放数据。变量总以$开头,后面紧接你选择的名字。例如,要存放前十个CPU使用最多的进程,你可以使用如下命令:

$TopTenProcessesByCPU = Get-Process | Sort-Object cpu -Descending | Select-Object -First 10

你可以使用Get-Variable来获取所有可用的变量。表14-2显示了一些比较重要的变量:

使用PowerShell排错----PowerShell入门_第2张图片

最重要的变量是$_,它是pipeline中的当前对象。当你想要遍历所有item时,这个变量就非常好使。下面的例子使用Where-Object来过滤出当前进程中WorkingSet大于100MB的进程:

Get-Process | Where-Object {$_.WorkingSet –gt 100MB}

注意,这个实例中使用了-gt比较运算符。PowerShell提供了一套比较运算符,表14-3罗列了常用的比较运算符:

使用PowerShell排错----PowerShell入门_第3张图片

知道一个变量的组成通常是有用的。你可以使用Get-Member来查看一个对象的结构。下面的代码显示了创建一个新的字符串对象,然后传递给Get-Member:

PS > [String]$NewString | Get-Member

知道一个对象的可用成员非常有用,因为你可以使用它们。例如下面的例子,返回Statement字符串的最后一个单词,用到属性Length和方法IndexOf及Substring:

$Statement = "PowerShell Rocks"
$Statement.SubString($Statement.IndexOf(" ") + 1, $Statement.Length -
$Statement.IndexOf(" ") - 1)

高级函数

把代码放在函数里就很容易复用。例如下面的例子获取以SQL打头的进程:

function Get-SQLProcess
{
<#
.SYNOPSIS
Retrieves processes starting with the term SQL
.DESCRIPTION
The Get-SQLProcess function uses the Get-Process Cmdlet to retrieve all the
processes
that start with SQL from the local computer.
#>
[CmdletBinding()]
Param()
Process
{
Get-Process SQL*
}
}

代码在PowerShell环境中执行后,你就可以调用这个函数。由于它使用CmdletBinding属性,这区分高级函数和标准函数,PowerShell会把它看成是一个已编译的cmdlet----意味着它将自动完成并列入可用的cmdlets。该例子里还写入了简单的说明文档。可以使用Get-Help来显示:

PS > Get-Help Get-SQLProcess
NAME
Get-SQLProcess
SYNOPSIS
Retrieves processes starting with the term SQL
SYNTAX
Get-SQLProcess []
DESCRIPTION
The Get-SQLProcess function uses the Get-Process Cmdlet to retrieve all the
processes that start with SQL from the local computer.
RELATED LINKS
REMARKS
To see the examples, type: "get-help Get-SQLProcess -examples".
For more information, type: "get-help Get-SQLProcess -detailed".
For technical information, type: "get-help Get-SQLProcess -full".
模块

模块是PowerShell 2.0引入的另一项新功能。模块是包含cmdlets、providers、函数、变量、别名等成员的包。有4种类型的模块:

脚本模块

带有.PSM1扩展名的PowerShell脚本称为脚本模块。PowerShell脚本可以在组织内共享,如果需要的话,还可以在更大范围内共享。添加高级函数能够让脚本作者创建类似cmdlet的函数并共享它。脚本模块是最容易访问的模块,因为任何有效的PowerShell脚本都可以简单地保存到一个.PSM1的文件中,然后像其他模块类型一样被使用。

二进制模块

二进制模块包括已编译的.NET代码,被编译到程序集(.dll)里。使用二进制模块的优势是帮助有经验的C#开发者创建模块。

Manifest模块

Manifest模块用于描述模块的内容,包括前提条件(PowerShell版本,.NET Framework版本等)、处理指示、格式及类型属性。可以使用限制条件,例如模块成员导出,这在创建干净的API用于共享时很有用。按照惯例,Manifest文件有一个.psd1扩展名,格式化及类型文件有一个.psxml扩展名。

动态模块

动态模块是使用New-Module创建的。这些模块仅在会话活动时驻留内存,因此它们不能通过Get-Module看到。

使用模块

要查看系统里可用的模块,你可以使用Get-Module,参数为-ListAvailable,来获取导入到会话的所有模块。下面的例子显示了可用的SQL模块:

PS > get-module -listavailable sql*
ModuleType Name ExportedCommands
---------- ---- ----------------
Manifest SQLASCMDLETS {}
Manifest SQLPS {}

一旦你看到你想用的模块,就可以使用Import-Module把它导入。SQL Server 2012自带两个模块SQLPS和SQLASCMDLETS。下面的例子把这两个模块导入活动会话:

Import-Module SQLPS,SQLASCMDLETS -DisableNameChecking

你可以使用Get-Command -Module来过滤出可用的cmdlet。例如:

PS SQLSERVER:\> Get-Command -Module SQLASCMDLETS
CommandType Name
----------- ----
Cmdlet Add-RoleMember
Cmdlet Backup-ASDatabase
Cmdlet Invoke-ASCmd
Cmdlet Invoke-ProcessCube
Cmdlet Invoke-ProcessDimension
Cmdlet Invoke-ProcessPartition
Cmdlet Merge-Partition
Cmdlet New-RestoreFolder
Cmdlet New-RestoreLocation
Cmdlet Remove-RoleMember
Cmdlet Restore-ASDatabase

如果你不再想引用导入的模块,你可以使用Remove-Module来移除它, 提供你希望移除的模块的名称。

PowerShell脚本签名

模块是为了共享而设计,因此要进行数字签名,以便那些用Set-ExecutionPolicy锁定计算机的用户依然能够执行脚本,除非计算机被锁定为Restricted,在这种情况下任何脚本都不能执行。脚本签名需要代码签名证书,这超出本书范围,但是你可以从下面的链接中获取更多信息:

http://technet.microsoft.com/en-us/magazine/2008.04.powershell.aspx.

远程工作

在PowerShell的第一个版本中,用户只能在本地使用。如果你只有一台电脑需要管理,这当然没问题;但是很多管理员要在复杂的计算环境下操作多台计算机,使用PowerShell远程连接到每台计算机就是个重要的限制。当WinRM启用后,2.0版本就引入了远程。WinRM是一个Windows服务,它运行在目标计算机上,并允许远程计算机运行PowerShell 2.0,并能从本地计算机执行PowerShell 2.0脚本。从管理员的角度而言,这开启了很多可能----能够用PowerShell构建一个完整的监控框架,在一台单独的管理计算机上进行操作。

要设置PowerShell远程功能,你必须在所有参与的计算机上安装PowerShell 2.0。必须完成两步,才能运行起来:

1、 在目标计算机上,以管理员权限运行PowerShell,运行Enable-PSRemoting -force来设置WinRM(Windows Remote Management)服务,防火墙要允许远程命令通过:

PS WSMan:\localhost\Client> Enable-PSRemoting -force
WinRM already is set up to receive requests on this machine.
WinRM has been updated for remote management.
Created a WinRM listener on HTTP://* to accept WS-Man requests to any IP on
this machine.
WinRM firewall exception enabled.

2、在目标计算机上,确保执行脚本的计算机是可信任的主机,通过命令TrustHosts来实现,如下显示:

PS C:\> cd wsman:\localhost\client
PS WSMan:\localhost\Client> Set-Item TrustedHosts SQL2012 -Force
PS WSMan:\localhost\Client> Get-Item TrustedHosts
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client
Name Value
---- -----
TrustedHosts SQL2012

完成这两步后,你就可以运行远程脚本。你可以使用New-PSSession来交互式地进行,然后使用Enter-PSSession输入远程会话。你还可以使用Invoke-Command来调用远程机器上的脚本。例如:

Invoke-Command -Session $sessions –ScriptBlock {Hostname}

SQL Server 2012中PowerShell的新特性

SQL Server 2012之前,SQL Server团队开发了PowerShell mini-shell SQLPS。SQLPS现在成为标准的PowerShell 2.0主机,导入SQLPS模块。如果你在使用标准的PowerShell主机,这要容易很多,因为你也可以在另一个PowerShell主机上使用import-module SQLPS和SQLASCMDLETS来获取所有的SQL Server提供程序功能。SQL Server 2012自带40个cmdlets:

SQLPS CMDLETS                                                             SQLASCMDLETS CMDLETS
Add-SqlAvailabilityDatabase                                            Add-RoleMember
Add-SqlAvailabilityGroupListenerStaticIp                      Backup-ASDatabase
Backup-SqlDatabase                                                        Invoke-ASCmd
Convert-UrnToPath                                                            Invoke-ProcessCube
Decode-SqlName                                                              Invoke-ProcessDimension
Disable-SqlHADRService                                                 Invoke-ProcessPartition
Enable-SqlHADRService                                                  Merge-Partition
Encode-SqlName                                                              New-RestoreFolder
Invoke-PolicyEvaluation                                                    New-RestoreLocation
Invoke-Sqlcmd                                                                    Remove-RoleMember
Join-SqlAvailabilityGroup                                                  Restore-ASDatabase
New-SqlAvailabilityGroup
New-SqlAvailabilityGroupListener
New-SqlAvailabilityReplica
New-SqlHADREndpoint
Remove-SqlAvailabilityDatabase
Remove-SqlAvailabilityGroup
Remove-SqlAvailabilityReplica
Restore-SqlDatabase
Resume-SqlAvailabilityDatabase
Set-SqlAvailabilityGroup
Set-SqlAvailabilityGroupListener
Set-SqlAvailabilityReplica
Set-SqlHADREndpoint
Suspend-SqlAvailabilityDatabase
Switch-SqlAvailabilityGroup
Test-SqlAvailabilityGroup
Test-SqlAvailabilityReplica
Test-SqlDatabaseReplicaState

 这些cmdlets中,有22个用于管理High Availability功能及分析服务。从排错和性能角度而言,其他值得注意的cmdlet是用于备份和还原的。SQL Server备份和还原cmdlet在2012中很受欢迎。过去有两个选项:

>>Invoke-SQL,写T-SQL在PowerShell脚本中执行

>>装载SMO对象,通过SMO库使用其中的备份和还原功能。

Backup-SqlDatabase

下面的脚本显示了如何使用SQL Provider和Backup-SqlDatabase脚本来遍历所有数据库,为每个数据库创建一个文件夹,然后生成一个基于时间戳的备份(代码文件:PS_SQLBackup01.PS1)

foreach($database in (Get-ChildItem))
{
$dbName = $database.Name
$timeStamp = Get-Date -FORMAT yyyyMMddHHmmss
$backupFolder = "c:\backups\$dbName"
if((Test-Path $backupFolder) -eq $False)
{
New-Item -type directory -path $backupFolder
}
Backup-SqlDatabase -Database $dbName -BackupFile "$backupFolder\$dbName-
$timeStamp.bak"
}

Restore-SqlDatabase

这个cmdlet使还原数据库非常简单。下面的脚本显示了如何还原Adventure Works数据库:

Restore-sqldatabase -Database AdventureWorks '
-BackupFile "C:\Backups\AdventureWorks\AdventureWorks-20120220005537.bak"

单引号( ' )是连续字符,当单行语句很长时很有用。

 

你可能感兴趣的:(SQL,Server,2012的内部原理和故障排除,PowerShell)