设为首页 收藏本站
查看: 824|回复: 0

Powershell 管道原理分析

[复制链接]

尚未签到

发表于 2018-9-2 10:51:49 | 显示全部楼层 |阅读模式
  豆子一直以为管道其实是很简单的,无非就是把前一个的输出结果通过管道传给下一个命令的输入嘛,貌似很多网上教程也就这么解释一下,然后就是各种演示命令了。昨天看了一个MVA2年前的powershell快速入门课程,才发现很多细节都忽略掉了,这个细节对于理解管道怎么工作是非常重要的,因为有的时候不是所有的命令都支持互相管道传输。知道了他的工作方式,才能更有效的使用管道。
  下面的解释是基于Powershell V3以上的版本:
  Powershell 的管道传输有两种方式,byvalue和bypropertyname。
  byvalue的意思就是输出类型和输入的类型是一样,自然可以传递。
  比如我可以把get-service的结果传给stop-service,-whatif可以帮助我确认这个命令的效果,这样可以避免一些危险的操作。
PS C:\windows\system32> Get-Service bits | Stop-Service -whatif  
What if: Performing the operation "Stop-Service" on target "Background Intelligent Transfer Service (bits)".
  为什么他们可以传递呢,注意看get-service的类型是 servicecontroller
PS C:\windows\system32> Get-Service bits | gm  
   TypeName: System.ServiceProcess.ServiceController
  
Name                      MemberType    Definition
  
----                      ----------    ----------
  
Name                      AliasProperty Name = ServiceName
  
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn
  
Disposed                  Event         System.EventHandler Disposed(System.Object, System.EventArgs)
  
Close                     Method        void Close()
  
Continue                  Method        void Continue()
  
CreateObjRef              Method        System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
  
Dispose                   Method        void Dispose(), void IDisposable.Dispose()
  查看一下stop-service 的帮助文档 (小技巧,-show可以打开一个新的窗口),搜索byvalue
PS C:\windows\system32> get-help Stop-Service -show  结果如下,他接受管道输入,而且接受类型为serviceController,因此他可以接受get-service 的输入。
DSC0000.jpg

  bypropertyname 的意思是如果管道的输入对象里面有一个属性,他的名字和类型都和输出命令的某一个参数的名字和类型都对的上号,那么这样的管道也是成立的。
  下面看一个例子,这样执行是失败的。为什么呢,我们来分析一下
PS C:\windows\system32> get-adcomputer sydwsus | get-service bits  
Get-Service : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Provide an a
  
that is not null or empty, and then try the command again.
  
At line:1 char:26
  
+ get-adcomputer sydwsus | get-service bits
  
+                          ~~~~~~~~~~~~~~~~
  
    + CategoryInfo          : InvalidData: (CN=SYDWSUS,OU=C...om,DC=com,DC=au:PSObject) [Get-Service], Paramete
  
   gValidationException
  
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetServiceCommand
  首先看看输出类型,是一个ADComputer的类型
PS C:\windows\system32> get-adcomputer sydwsus | gm  
   TypeName: Microsoft.ActiveDirectory.Management.ADComputer
  
Name              MemberType            Definition
  
----              ----------            ----------
  
Contains          Method                bool Contains(string propertyName)
  
Equals            Method                bool Equals(System.Object obj)
  
GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEnumerator()
  
GetHashCode       Method                int GetHashCode()
  
GetType           Method                type GetType()
  
ToString          Method                string ToString()
  
Item              ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p.
  
DistinguishedName Property              System.String DistinguishedName {get;set;}
  查看一下get-service 的 帮助文档,byvalue需要的是serviceController类型,对不上,因此挂了
DSC0001.jpg

  那么我们看看bypropertyname,他接受一个管道对象的属性为computername ,类型为字符串的作为他的参数输入
DSC0002.jpg

  看看我们的管道对象,可以看见他有一个叫做name的属性,类型为字符串。因为名字不匹配,所以管道仍然无法传输。
DSC0003.jpg

  解决方式很简单,自定义一个属性,保证他的名字一样就行了,比如
PS C:\windows\system32> get-adcomputer sydwsus | select name, @{name="computername";expression={$_.name}}  
name                                                        computername
  
----                                                        ------------
  
SYDWSUS                                                     SYDWSUS
  再执行一次,就工作了
PS C:\windows\system32> get-adcomputer sydwsus | select name, @{name="computername";expression={$_.name}} | Get-Service  
bits
  
Status   Name               DisplayName
  
------   ----               -----------
  
Running  bits               Background Intelligent Transfer Ser...
  当然上面的写法比较复杂繁琐,一个小技巧在 computername 后面 指定一个大括号{},他会把管道前面的整个对象结果替换过来,然后直接在里面取name的属性就好了
PS C:\windows\system32> get-adcomputer sydwsus | Get-Service -ComputerName {$_.name} bits  
Status   Name               DisplayName
  
------   ----               -----------
  
Running  bits               Background Intelligent Transfer Ser...
  下面再来看几个例子
  我知道get-wmiobject 可以获取很多系统信息,比如
PS C:\windows\system32> Get-WmiObject -class win32_bios  
SMBIOSBIOSVersion : 3.11.0950
  
Manufacturer      : American Megatrends Inc.
  
Name              : 3.11.0950
  
SerialNumber      : 017349452253
  
Version           : OEMC - 300
  但是如果我通过管道执行就会报错
PS C:\windows\system32> get-adcomputer sydwsus | Get-WmiObject -ComputerName {$_.name} -class win32_bios  
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
  
At line:1 char:26
  
+ get-adcomputer sydwsus | Get-WmiObject -ComputerName {$_.name} -class win32_bios
  
+                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
  
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
  
Get-WmiObject : The input object cannot be bound to any parameters for the command either because the command does not
  
take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
  
At line:1 char:26
  
+ get-adcomputer sydwsus | Get-WmiObject -ComputerName {$_.name} -class win32_bios
  
+                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
    + CategoryInfo          : InvalidArgument: (CN=SYDWSUS,OU=C...om,DC=com,DC=au:PSObject) [Get-WmiObject], Parameter
  原因很简单,这个命令既不支持byvalue,也不支持bypropertyname, 尽管他有comptuername这个参数,这个参数拒绝接受管道的输入
DSC0004.jpg

DSC0005.jpg

  这种不支持管道的命令,豆子的一般处理方式要么要么直接运行,要么是在管道后面用foreach的方式。
  首先看看直接跑,报错
PS C:\windows\system32> get-wmiobject win32_bios -computername (Get-ADComputer -filter{operatingsystem -like "*2008 R2*"  
}| select name)
  
get-wmiobject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
  
At line:1 char:1
  
+ get-wmiobject win32_bios -computername (Get-ADComputer -filter{operatingsystem - ...
  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
  
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
  

  
get-wmiobject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
  
At line:1 char:1
  
+ get-wmiobject win32_bios -computername (Get-ADComputer -filter{operatingsystem - ...
  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  原因很简单,类型不匹配,注意这个select的输出对象仍然是ADComputer, 但是wmi的computer输入要求是字符串
PS C:\windows\system32> Get-ADComputer -filter{operatingsystem -like "*2008 R2*"}| select name | gm  
   TypeName: Selected.Microsoft.ActiveDirectory.Management.ADComputer
  
Name        MemberType   Definition
  
----        ----------   ----------
  
Equals      Method       bool Equals(System.Object obj)
  
GetHashCode Method       int GetHashCode()
  
GetType     Method       type GetType()
  
ToString    Method       string ToString()
  
name        NoteProperty System.String name=SYDDC02
  更改一下输出方式,类型就变成字符串了,再次运行就成功了
PS C:\windows\system32> Get-ADComputer -filter{operatingsystem -like "*2008 R2*"}| select -ExpandProperty name | gm  
   TypeName: System.String
  
Name             MemberType            Definition
  
----             ----------            ----------
  
Clone            Method                System.Object Clone(), System.Object ICloneable.Clone()
  
CompareTo        Method                int CompareTo(System.Object value), int CompareTo(string strB), int IComparab...
  
Contains         Method                bool Contains(string value)
  
CopyTo           Method                void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int co...
  
EndsWith         Method                bool EndsWith(string value), bool EndsWith(string value, System.StringCompari...
  
Equals           Method                bool Equals(System.Object obj), bool Equals(string value), bool Equals(string...
  
GetEnumerator    Method                System.CharEnumerator GetEnumerator(), System.Collections.Generic.IEnumerator...
  
GetHashCode      Method                int GetHashCode()
  
GetType          Method                type GetType()
  
GetTypeCode      Method                System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
PS C:\windows\system32> get-wmiobject win32_bios -computername (Get-ADComputer -filter{operatingsystem -like "*2008 R2*"  
} |select -ExpandProperty name) | ft
  
SMBIOSBIOSVersion       Manufacturer            Name                    SerialNumber            Version
  
-----------------       ------------            ----                    ------------            -------
  
6.00                    Phoenix Technologies... PhoenixBIOS 4.0 Rele... VMware-42 1e 84 9f d... INTEL  - 6040000
  
6.00                    Phoenix Technologies... PhoenixBIOS 4.0 Rele... VMware-42 0d c3 19 1... INTEL  - 6040000
  
6.00                    Phoenix Technologies... PhoenixBIOS 4.0 Rele... VMware-42 0d ec 36 7... INTEL  - 6040000
  这种表达方式在2.0的时代很常见,3.0以后,可以直接当作数组处理,比如下面更简洁的方式也是可以的
PS C:\windows\system32> get-wmiobject win32_bios -computername (Get-ADComputer -filter{operatingsystem -like "*2008 R2*"  
}).name
  
SMBIOSBIOSVersion : 6.00
  
Manufacturer      : Phoenix Technologies LTD
  
Name              : PhoenixBIOS 4.0 Release 6.0
  
SerialNumber      : VMware-42 1e 84 9f d6 f6 b5 a0-01 6d 8a c0 13 ee e6 e4
  
Version           : INTEL  - 6040000
  
SMBIOSBIOSVersion : 6.00
  
Manufacturer      : Phoenix Technologies LTD
  
Name              : PhoenixBIOS 4.0 Release 6.0
  
SerialNumber      : VMware-42 0d c3 19 1b 3a d2 43-19 36 bb c5 00 5b 69 d2
  除了直接执行,通过foreach来接受管道信息,然后对每一个对象单独执行也是可以的
PS C:\windows\system32> Get-ADComputer -filter{operatingsystem -like "*2008 R2*"}| ForEach-Object{Get-WmiObject win32_bi  
os}
  
SMBIOSBIOSVersion : 3.11.0950
  
Manufacturer      : American Megatrends Inc.
  
Name              : 3.11.0950
  
SerialNumber      : 017349452253
  
Version           : OEMC - 300
  
SMBIOSBIOSVersion : 3.11.0950
  
Manufacturer      : American Megatrends Inc.
  
Name              : 3.11.0950
  
SerialNumber      : 017349452253
  
Version           : OEMC - 300
  
SMBIOSBIOSVersion : 3.11.0950
  
Manufacturer      : American Megatrends Inc.
  
Name              : 3.11.0950
  
SerialNumber      : 017349452253
  
Version           : OEMC - 300
  另外,3.0以后增加了get-ciminstance 的commandlet,这个是用来替代get-wmiobject,而且他支持管道,比如, 查看所有2008 R2 上次重启的时间
PS C:\windows\system32> get-adcomputer -filter {operatingsystem -like "*2008 R2*"} | select -ExpandProperty name |Get-Ci  
mInstance -class win32_operatingsystem  | select pscomputername,lastbootuptime | Out-GridView
DSC0006.jpg




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-561459-1-1.html 上篇帖子: 【Powershell】【静态数组】 数组的使用(一) 下篇帖子: 【Powershell】【动态数组】 数组的使用(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表