介绍
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”中:
第二个Cmdlet有一个强制的位置参数,用于指定输出文件名称。因为“Export-CSV”是一个内置的PowerShell Cmdlet,它知道如何把通过“Get-Process”产生的常规表格转换到一个普通的CSV文件中。Get-Process | Export-Csv procs.csv
查看导出的文件:notepad .\procs.csv
文件的第一行是以“#”开头的注释,代表着文件中包含的信息类型。如上图,“System.Diagnostics.Process”是Windows用于标识一个正在运行的进程相关的底层名称。
如果要忽略文件头部“#”,可使用–NoTypeInformation
参数。
导入csv文件,可以使用Import--Csv procs.csv
。Shell会读取CSV文件然后展示,该输出并不是基于实时的信息,而是基于CSV创建时的快照。
分隔符
让“Export-CSV”使用当前系统默认的分隔符而不是逗号:get-service | Export-Csv services.csv -UseCulture
。
若要使用指定分隔符,可以用-Delimiter参数:
Get-Process | Export-Csv -Path .\Processes.csv -Delimiter ';' -NoTypeInformation
查看帮助信息:
PS D:\(Tmp> help Export-Csv -Parameter delimi*
-Delimiter <System.Char>
Specifies a delimiter to separate the property values. The default is a comma (`,`). Enter a character, such as a colon (`:`). To specify a sem
icolon (`;`), enclose it in quotation marks.
是否必需? False
位置? 1
默认值 comma (,)
是否接受管道输入? False
是否接受通配符? 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
。
范例:
PS D:\(Tmp> ps | Export-Clixml reference.xml
PS D:\(Tmp> diff -ReferenceObject (Import-Clixml .\reference.xml) -DifferenceObject (Get-Process) -Property Name
Name SideIndicator
---- -------------
iexplore =>
iexplore =>
OpenConsole =>
powershell =>
svchost <=
svchost <=
WmiApSrv <=
WmiPrvSE <=
说明:
- 括号在PowerShell中用于控制执行的顺序。此处强制“Import-CliXML”和“Get-Process”先于“Diff”运行。
- 接着从“Import-CLI”得到的结果被送到“-reference”参数中,而“Get-Process”的结果被送到“-difference”参数中。
- 本例中,diff只用来比较Name列,通过-Property参数来指定。
- 匹配结果将以表格形式展示:
- 对存在于参照结果集,但是不存在于差异结果集的数据,会用“<=”标识符表示。
- 对存在于差异结果集,但是不存在于参照结果集的数据,会用“=>”标识符表示。
- 而两者均存在的,则不会出现在“Diff”输出的结果中。
这是一个不错的运维方法,特别是已经建立配置基线,可以对比现有计算机然后找出它们的差异。很多Cmdlets都能用于运维方面,并且都可以通过管道导出到CliXML文件中以便建立基线。这些基线一般包括服务、进程、操作系统配置、用户及群组等,并且可在任意时刻使用,从而比对现有系统的差异。
输出结果到普通文件
Cmdlet是直接输出到PowerShell所在的本地机器的屏幕上,但是可以通过如下方式修改输出位置。
# cmd使用>
PS D:\(Tmp> dir > DirectoryList.txt
# PowerShell使用out-file
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
”:
PS D:\(Tmp> dir
PS D:\(Tmp> dir | Out-Default
“Out-Default”只是把内容指向“Out-Host”,意味着你在无意中运行了:
PS D:\(Tmp> dir | Out-Default | 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)文件定制样式。
该命令不需要文件名:
Get-Service | ConvertTo-Html
# 默认会直接输出到屏幕,可以通过out-file导出导出到文件
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,可以在彼此之间互传信息。
Get-Process notepad | Stop-Process
服务也是类似的,“Get-Service”命令的输出结果能和其他Cmdlets(如Stop-Service、Start-Service、Set-Service等)一起被管道传输。
记住!不要运行以下命令,否则电脑会崩溃。
它会检索每一个进程,然后尝试逐个终止。该命令可能获取到关键进程,比如本地安全权限(Local Security Authority)。
影响级别
这些Cmdlets以某些方式修改系统,并且有一个内部定义的影响级别(impact level)。Cmdlet的创建者已经设定了这些影响级别,并且不允许修改。而Shell有一个相应的“$ConfirmPreference
”设置,默认为“High”。
PS D:\(Tmp> $ConfirmPreference
High
工作原理:当Cmdlet的内部影响级别大于等于Shell的“$ConfirmPreference”设置时,不管Cmdlet正准备做什么,Shell都会自动询问“你确定要这样做吗?(Are you sure?)”。
当Cmdlet的内部影响级别小于Shell的“$ConfirmPreference”设置时,不会自动弹出这个提示。但可以指定-Confirm参数,来主动使其弹出:
PS D:\(Tmp> Get-Process notepad | Stop-Process -Confirm
确认
是否确实要执行此操作?
正在目标“notepad (35932)”上执行操作“Stop-Process”。
[Y] 是(Y) [A] 全是(A) [N] 否(N) [L] 全否(L) [S] 暂停(S) [?] 帮助 (默认值为“Y”):
PS D:\(Tmp>
另外一个类似的参数是“-whatif”,可用于支持“-confirm”的Cmdlet。它会告诉你哪些Cmdlet会被执行,但是并不真正运行。
# 此命令,并没有杀死notepad进程
PS D:\(Tmp> Get-Process notepad | Stop-Process -WhatIf
WhatIf: 正在目标“notepad (40996)”上执行操作“Stop-Process”。
这个功能为那些可能有潜在风险的Cmdlet的预览提供了很好的帮助,并且可以检查是否是你想要的结果。
Get-Content和Import
使用“Export-CSV”和“Export-CliXML”导出输出结果到文件后,使用哪个Cmdlet导入进行查阅,才是正确姿势?是Get-Content还是对应的Import-CSV或Import-CliXML?
加入我们通过如下导出了数据:
下面先使用“Get-Content”命令从Shell中读出来。
可以看到Get-Content输出了原始数据,该命令没有尝试解析、编译这些数据。现在对比一下“Import-CSV”的结果。
是不是好很多?“Import-Cmdlets”会关注文件中的内容,尝试解析它们,然后创建一个比原始命令(本例中的“Get-EventLog”)看上去更加顺眼的输出结果。
如果你使用“Export-CSV”创建文件,可以使用“Import-CSV”命令来读取它们。如果使用“Export-CliXML”命令创建文件,通常建议使用“Import-CliXML”命令读取。使用这些配套命令可以得到更好的结果。
仅在从一个文本文件中读取内容并且不需要PowerShell解析数据时,才使用“Get-Content”命令,也就是你仅需要原始内容。