介绍

PowerShell通过管道(pipeline)把命令互相连接起来。管道通过传输一个命令,把其输出作为另外一个Cmdlet的输入,使得第二个命令可以通过第一个的结果作为输入并联合起来运行。
如“Dir | More”命令的运行情况,它把“Dir”命令的输出以管道方式传输给“More”命令。“More”命令把目录每次展现到一个页中。

输出结果到CSV或XML文件

管道和另外一个命令可以在导出文件时派上用场。Export-CliXML”和“Export-CSV”都可以通过创建并覆盖文件来修改系统,可以用 –noclobber参数来阻止它们覆盖现有文件。

  • get-service | Export-Csv services.csv –noclobber

    输出到CSV

    把进程信息传输到“Export-CSV”中:
    1. Get-Process | Export-Csv procs.csv
    第二个Cmdlet有一个强制的位置参数,用于指定输出文件名称。因为“Export-CSV”是一个内置的PowerShell Cmdlet,它知道如何把通过“Get-Process”产生的常规表格转换到一个普通的CSV文件中。

查看导出的文件:notepad .\procs.csv
image.png
文件的第一行是以“#”开头的注释,代表着文件中包含的信息类型。如上图,“System.Diagnostics.Process”是Windows用于标识一个正在运行的进程相关的底层名称。
如果要忽略文件头部“#”,可使用–NoTypeInformation参数。

导入csv文件,可以使用Import--Csv procs.csv。Shell会读取CSV文件然后展示,该输出并不是基于实时的信息,而是基于CSV创建时的快照。

分隔符

让“Export-CSV”使用当前系统默认的分隔符而不是逗号:get-service | Export-Csv services.csv -UseCulture

若要使用指定分隔符,可以用-Delimiter参数:

  1. Get-Process | Export-Csv -Path .\Processes.csv -Delimiter ';' -NoTypeInformation

查看帮助信息:

  1. PS D:\(Tmp> help Export-Csv -Parameter delimi*
  2. -Delimiter <System.Char>
  3. Specifies a delimiter to separate the property values. The default is a comma (`,`). Enter a character, such as a colon (`:`). To specify a sem
  4. icolon (`;`), enclose it in quotation marks.
  5. 是否必需? False
  6. 位置? 1
  7. 默认值 comma (,)
  8. 是否接受管道输入? False
  9. 是否接受通配符? False

输出到XML

PowerShell还提供了“Export-CliXML”Cmdlet,用于创建常规的命令行界面可扩展标记语言文件(generic command-line interface (CLI)Extensible Markup Language(XML))。CliXML是PowerShell专用的,但任何能够解析XML文件的程序都能够读取它。

对应的导入xml,可以使用“Import-CliXML”Cmdlet。

除此之外,PowerShell还提供了其他导入导出命令吗?有,可以用“Get-Command”Cmdlet配合“-verb”参数来找到所有“Import”或“Export”的命令。

对比文件

在展示、共享信息给别人及后续重新查看过程中,CSV和CliXML文件都很有用。实际上,Compare-Object可以在此过程中发挥重要作用(别名Diff)。PowerShell的“Diff”命令在对比文本文件时并不表现得很好。

Diff用于把两个结果集组合在一起并进行比对。比如,你在两台不同的机器上运行“Get-Process”。可以把正确配置的计算机的配置信息放到左边(称为参照计算机),右边的计算机信息可能相同或相似(称为差异计算机)。在两边运行命令之后,就可以开始对比两者的信息了。

运行“help diff”并阅读相关帮助信息。注意3个参数:-ReferenceObject,-DifferenceObject-Property

范例:

  1. PS D:\(Tmp> ps | Export-Clixml reference.xml
  2. PS D:\(Tmp> diff -ReferenceObject (Import-Clixml .\reference.xml) -DifferenceObject (Get-Process) -Property Name
  3. Name SideIndicator
  4. ---- -------------
  5. iexplore =>
  6. iexplore =>
  7. OpenConsole =>
  8. powershell =>
  9. svchost <=
  10. svchost <=
  11. WmiApSrv <=
  12. WmiPrvSE <=

说明:

  • 括号在PowerShell中用于控制执行的顺序。此处强制“Import-CliXML”和“Get-Process”先于“Diff”运行。
  • 接着从“Import-CLI”得到的结果被送到“-reference”参数中,而“Get-Process”的结果被送到“-difference”参数中。
  • 本例中,diff只用来比较Name列,通过-Property参数来指定。
  • 匹配结果将以表格形式展示:
    • 对存在于参照结果集,但是不存在于差异结果集的数据,会用“<=”标识符表示。
    • 对存在于差异结果集,但是不存在于参照结果集的数据,会用“=>”标识符表示。
    • 而两者均存在的,则不会出现在“Diff”输出的结果中。

这是一个不错的运维方法,特别是已经建立配置基线,可以对比现有计算机然后找出它们的差异。很多Cmdlets都能用于运维方面,并且都可以通过管道导出到CliXML文件中以便建立基线。这些基线一般包括服务、进程、操作系统配置、用户及群组等,并且可在任意时刻使用,从而比对现有系统的差异。

输出结果到普通文件

Cmdlet是直接输出到PowerShell所在的本地机器的屏幕上,但是可以通过如下方式修改输出位置。

  1. # cmd使用>
  2. PS D:\(Tmp> dir > DirectoryList.txt
  3. # PowerShell使用out-file
  4. PS D:\(Tmp> dir | Out-File OtherDirectoryList.txt

Out-File”提供了一些参数让你定制替代的字符编码(如UTF8或Unicode)、追加内容到现有文件等功能。默认情况下,用“Out-File”创建的文件有80列宽,意味着有时候使用PowerShell需要修改命令的输出,以便适应这80列的限制。

Out-Default

PowerShell有很多“Out- Cmdlets”,其中一个叫“Out-Default”。它是其中一个不需要额外指定的“Out- Cmdlets”,为什么?

当你运行“Dir”时,实际上是在运行“Dir | Out-Default”:

  1. PS D:\(Tmp> dir
  2. PS D:\(Tmp> dir | Out-Default

“Out-Default”只是把内容指向“Out-Host”,意味着你在无意中运行了:

  1. PS D:\(Tmp> dir | Out-Default | Out-Host

而“Out-Host”是显示结果到显示器中。

其他Out输出

“Out-Printer”可能是余下以“Out-”开头的Cmdlet中最有用的命令了,但该命令只能在Windows中使用。

“Out-GridView”也有类似功能,但是需要安装.NET Framework v3.5和Windows PowerShell ISE之后才能使用,这些在Server版本的Windows以及非Windows系统并不是默认就有。如果你安装了这些,可以尝试运行“Get-Service| Out-GridView”查看结果。

“Out-Null”和“Out-String”也非常有用,但是暂时不深入探讨。

转换成HTML

通过管道将结果传递给“ConvertTo-HTML”命令,可以生成HTML报告(非Windows系统可能兼容)。该命令可以生成结构良好的、通用的HTML数据,并可以在任何Web浏览器中打开。但是这只是原始数据,如果需要美观,需要引用CSS(Cascading Style Sheet)文件定制样式。
该命令不需要文件名:

  1. Get-Service | ConvertTo-Html
  2. # 默认会直接输出到屏幕,可以通过out-file导出导出到文件
  3. Get-Service | ConvertTo-Html | Out-File 123.html

Export和ConvertTo区别

在PowerShell世界里面,动词“Export”意味着你把数据提取出来,然后转换成其他格式,最后把转换后的格式以某种形式保存,如文件。而动词“ConvertTo”仅仅是处理过程的一部分,它仅转换不保存。

PowerShell附带其他“ConvertTo-Cmdlets”,包括“ConvertTo-CSV”和“ConvertTo-XML”等。正如“ConvertTo-HTML”一样,这些命令都不在磁盘上创建文件,只是把命令的输出结果分别转换成CSV或XML。你需要用管道把它们和“Out-File”连接起来以便存储到磁盘上。

ConvertTo优势:
在某些高级场景中,你可能不想把结果存到磁盘文件上。比如你想把数据转换成XML然后传输到Web服务,或者其他地方。通过使用不需要存储文件的“ConvertTo-Cmdlets”,你可以灵活地实现你的需求。

终止进程和停止服务

带有相同名词(本例中的进程)的Cmdlets,可以在彼此之间互传信息。

  1. Get-Process notepad | Stop-Process

服务也是类似的,“Get-Service”命令的输出结果能和其他Cmdlets(如Stop-Service、Start-Service、Set-Service等)一起被管道传输。

记住!不要运行以下命令,否则电脑会崩溃。
image.png
它会检索每一个进程,然后尝试逐个终止。该命令可能获取到关键进程,比如本地安全权限(Local Security Authority)。

影响级别

这些Cmdlets以某些方式修改系统,并且有一个内部定义的影响级别(impact level)。Cmdlet的创建者已经设定了这些影响级别,并且不允许修改。而Shell有一个相应的“$ConfirmPreference”设置,默认为“High”。

  1. PS D:\(Tmp> $ConfirmPreference
  2. High

工作原理:当Cmdlet的内部影响级别大于等于Shell的“$ConfirmPreference”设置时,不管Cmdlet正准备做什么,Shell都会自动询问“你确定要这样做吗?(Are you sure?)”。
当Cmdlet的内部影响级别小于Shell的“$ConfirmPreference”设置时,不会自动弹出这个提示。但可以指定-Confirm参数,来主动使其弹出:

  1. PS D:\(Tmp> Get-Process notepad | Stop-Process -Confirm
  2. 确认
  3. 是否确实要执行此操作?
  4. 正在目标“notepad (35932)”上执行操作“Stop-Process”。
  5. [Y] 是(Y) [A] 全是(A) [N] 否(N) [L] 全否(L) [S] 暂停(S) [?] 帮助 (默认值为“Y”):
  6. PS D:\(Tmp>

另外一个类似的参数是“-whatif”,可用于支持“-confirm”的Cmdlet。它会告诉你哪些Cmdlet会被执行,但是并不真正运行。

  1. # 此命令,并没有杀死notepad进程
  2. PS D:\(Tmp> Get-Process notepad | Stop-Process -WhatIf
  3. WhatIf: 正在目标“notepad (40996)”上执行操作“Stop-Process”。

这个功能为那些可能有潜在风险的Cmdlet的预览提供了很好的帮助,并且可以检查是否是你想要的结果。

Get-Content和Import

使用“Export-CSV”和“Export-CliXML”导出输出结果到文件后,使用哪个Cmdlet导入进行查阅,才是正确姿势?是Get-Content还是对应的Import-CSV或Import-CliXML?

加入我们通过如下导出了数据:
image.png
下面先使用“Get-Content”命令从Shell中读出来。
image.png
可以看到Get-Content输出了原始数据,该命令没有尝试解析、编译这些数据。现在对比一下“Import-CSV”的结果。
image.png
是不是好很多?“Import-Cmdlets”会关注文件中的内容,尝试解析它们,然后创建一个比原始命令(本例中的“Get-EventLog”)看上去更加顺眼的输出结果。
如果你使用“Export-CSV”创建文件,可以使用“Import-CSV”命令来读取它们。如果使用“Export-CliXML”命令创建文件,通常建议使用“Import-CliXML”命令读取。使用这些配套命令可以得到更好的结果。

仅在从一个文本文件中读取内容并且不需要PowerShell解析数据时,才使用“Get-Content”命令,也就是你仅需要原始内容。