深刻理解powershell的管道工作原理
在类Unix操作系统(以及一些扩展,Windows)中,管道(英语:Pipeline)是原始的软件管道:即是一个由标准输入输出链接起来的进程集合,所以每一个进程的输出(stdout)被直接作为下一个进程的输入(stdin)。
通俗来说,管道将一个命令(也可以是程序,PowerShell中叫做command-lets)的输出导向另一个命令的输入,从而让两个(或多个命令)共同处理the same thing。在命令行中,我们用 “|” 表示管道。
为什么说是the same thing呢?
其实,Windows的CMD控制台、UNIX/LINUX 的 bash shell、powershell 都有管道的概念,只不过前两者输入输出的是文本流(text),而powershell输入输出的则是对象(object)。对象是一种特殊类型,它由属性、方法、属性别名等成员组成。
Powershell的管道是如何利用对象(object)进行工作的?接下来,我们需要解决两个部分:
1、TypeName(ByValue):对象的类型名
2、ByPropertyName(对象的属性名)
首先TypeName、ByPropertyName是什么样的角色呢?
TypeName 的例子:
一群鸡、鸭、鹅,按照家禽种类分别放入不同圈中饲养, 也就是按照TypeName,不同的对象类型进行划分。
ByPropertyName 的例子:
一群鸡、鸭、鹅,按照性别,把公的和母的分别放到两个圈中饲养。虽然它们是三类家禽,属于不同的对象,却有着相同的属性——性别,也就是ByPropertyName进行划分。
PowerShell的命令行工具command-lets如何通过类型名TypeName(ByValue)进行匹配:
get-service | stop-service
1、get-service运行后返回一些对象objects。
2、stop-service运行前等待接收这些对象objects,也就是get-service返回的objects。
通过运行命令:
get-service | get-member
输出:
TypeName
System.ServiceProcess.ServiceController
获取到了Get-Service返回的类型名TypeName:
System.ServiceProcess.ServiceController
返回对象的属性:
CanPauseAndContinue、DisplayName、CanPauseAndContinue、RequiredServices、Name等。
当我们把该对象通过管道 “|” 传递给 stop-service 时,stop-service要么匹配类型名TypeName,要么匹配属性名ByPropertyName。
那么 stop-service 接收对象的类型名如何获取呢?通过运行命令:
get-help stop-service -full
在输出的内容中找到 -InputObject 这一节:
-InputObject (ServiceController[])
Accept pipeline input? true (ByValue)
可以看到ServiceController[]与System.ServiceProcess.ServiceController是相同的,换句话说,它们通过TypeName( ByValue)能够进行匹配。
PowerShell的命令行工具command-lets如何通过属性名ByPropertyName进行匹配:
依然是上一个例子:
get-service | stop-service
我们已经知道,get-service和stop-service可以成功匹配TypeName,进行对象的传递和接收,那么它的执行结果是什么呢?
首先需要知道get-service返回的都是什么。在没有指定计算机名的情况下,默认是本地计算机即local,并通过检索本地计算机所有服务,默认返回每一个服务的状态、服务名和服务的显示名。
然后,stop-service会接收每一个服务对象,并将其停止。
这时,如果想要指定某一个特定服务,例如calc.exe,只想将它进行关闭,我们就需要通过属性名name来指定了。
例如:
get-service -name calc | stop-service