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

PowerShell runspace 的创建,使用和查错

[复制链接]
YunVN网友  发表于 2018-9-2 07:51:18 |阅读模式
  今天拜读了The Scripting Guy关于runspace的几篇大作,温故而知新,一些忽略的地方更为清楚。
  https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/26/beginning-use-of-powershell-runspaces-part-1/
  runspace这两年在PowerShell使用的频率越来越高,由于他的高效率,基本上很多时候已经取代了传统的Job后台操作。不管是多线程实现,或者是后台操作,亦或是***脚本,runspace 的性能可以是job的几十倍以上。
  现在由浅入深的看几个例子,到底是怎么实现的。
  例1 同步操作一个PowerShell实例
  创建一个PowerShell的实例,然后添加一段代码,然后invoke执行。
$PowerShell = [powershell]::Create()  
[void]$PowerShell.AddScript({
  
    Get-Date
  
    Start-Sleep -Seconds 10
  
})
  
$PowerShell.Invoke()
  注意几点:

  •   PowerShell不仅仅是一个脚本语言,我们可以通过这个类System.Management.Automation.PowerShell所提供的方法来创建实例,添加脚本和参数。
      Powershell 作为平台的使用方法参考https://blogs.msdn.microsoft.com/powershell/2013/10/01/paap-windows-powershell-as-a-platform-part-1/
  •   我使用了[void]的目的是避免输出太多乱起八糟的信息(比如当前runspace的信息等等)来污染我的输出结果
  •   我在这个脚本里面添加了一条等待10秒的命令,当我们执行invoke命令的时候,会看见屏幕上卡了10秒以后,才返回当前的时间。 这种同步的操作在执行多线程和后台操作的时候应该避免,后面我们会说如何实现异步操作。
DSC0000.png

  可以看见执行invoke之后直接返回了一个结果,事实上,这个和我直接在控制台输入Get-Date的效果一样,这样的脚本并不适合在后台操作。
  例2,异步操作Runspace和PowerShell实例。
$Runspace = [runspacefactory]::CreateRunspace()  
$PowerShell =[powershell]::Create()
  
$PowerShell.runspace = $Runspace
  
$Runspace.Open()
  
[void]$PowerShell.AddScript({
  
    Get-Date
  
    Start-Sleep -Seconds 10
  
})
  
$AsyncObject = $PowerShell.BeginInvoke()
  这一次,我们创建一个runspace的对象,然后把它绑定到一个PowerShell的实例中,运行这个runspace,然后和上面一样,给这个PowerShell的实例添加脚本。请注意,一个很重要的改进是这里使用了BeginInvoke()方法,这个会返回一个异步的对象。异步和同步的区别在于,同步会死等在某个环节,直到输出结果,而异步会自动切换出来,定期的检查结果,等操作结束之后,再切换回去获取结果。
  一个简单有趣的C#例子老王洗澡很生动了对比了同步和异步操作
  http://www.cnblogs.com/lxblog/archive/2012/12/11/2813893.html
  回到之前的脚本,我们来看看BeginInvoke返回的异步对象是什么样。因为我设置了要等10秒钟,所以可以看见他的IsComleted属性是False
DSC0001.png

  10秒钟以后再查看,就已经变成True,这表示操作已经结束。
DSC0002.png

  现在我们调用EndInvoke这个异步对象切换回去获取结果
$Data = $PowerShell.EndInvoke($AsyncObject)  
$Data
  成功获取结果
DSC0003.png

  最后别忘记关掉这个实例。
$PowerShell.Dispose()  例3 给PowerShell的平台传递参数
$name = 'James'  
$title = 'Manager'
  
$PowerShell =[powershell]::Create()
  
[void]$PowerShell.AddScript({
  
    Param ($Param1, $Param2)
  
    [pscustomobject]@{
  
        Param1 = $Param1
  
        Param2 = $Param2
  
    }
  
}).AddArgument($name).AddArgument($title)
  
#Invoke the command
  
$PowerShell.Invoke()
  
$PowerShell.Dispose()
  比如我定义了2个变量,我可以通过AddArgument来传递到脚本块里,当然脚本块里面也得定义对应的参数,然后按顺序传入变量。
  例4  如果参数过多,我可以通过定义hash表和 addParameters来传递参数,这样显得更为简洁。
$ParamList = @{  
    param1 = 'Kevin'
  
    Param2 = 'receptionist'
  
}
  
$PowerShell = [powershell]::Create()
  
[void]$PowerShell.AddScript({
  
    Param ($Param1, $Param2)
  
    [pscustomobject]@{
  
        name = $Param1
  
        title = $Param2
  
    }
  
}).AddParameters($ParamList)
  
#Invoke the command
  
$PowerShell.Invoke()
  
$PowerShell.Dispose()
  例5  整合上面的知识点,来个完整的例子,例如使用 runspace pool来实现多线程的Ping
  这个是我之前写过的一个例子。http://beanxyz.blog.51cto.com/5570417/1760880
$Throttle = 20 #threads  

  
#脚本块,对指定的计算机发送一个ICMP包测试,结果保存在一个对象里面,接收一个计算机名字的参数
  

  
$ScriptBlock = {
  
   Param (
  
      [string]$Computer
  
   )
  
   $a=test-connection -ComputerName $Computer -Count 1
  

  
   $RunResult = New-Object PSObject -Property @{
  
      IPv4Adress=$a.ipv4address.IPAddressToString
  
      ComputerName=$Computer
  

  
   }
  
   Return $RunResult
  
}
  

  

  
#创建一个资源池,指定多少个runspace可以同时执行,这里表示最低1个,最多20个
  

  
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $Throttle)
  
$RunspacePool.Open()
  
$Jobs = @()
  

  

  
#获取Windows 2012服务器的信息,对每一个服务器单独创建一个Powershell实例,每一个实例都异步的执行PING的操作,并把异步对象保存在Result里面
  
#最后把所有的结果都保存在一个Jobs的对象中。
  
#注意这里绑定的是RunspacePool,而不是单个的Runspace
  

  
(get-adcomputer -filter {operatingsystem -like "*2012*"}).name | % {
  

  
   #Start-Sleep -Seconds 1
  
   $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($_)
  
   $Job.RunspacePool = $RunspacePool
  
   $Jobs += New-Object PSObject -Property @{
  
      Server = $_
  
      Pipe = $Job
  
      Result = $Job.BeginInvoke()
  
   }
  
}
  

  

  
#循环输出等待的信息.... 直到所有的job都完成
  

  
Write-Host "Waiting.." -NoNewline
  
Do {
  
   Write-Host "." -NoNewline
  
   Start-Sleep -Seconds 1
  
} While ( $Jobs.Result.IsCompleted -contains $false)
  
Write-Host "All jobs completed!"
  

  

  
#解锁,输出异步操作的结果
  
$Results = @()
  
ForEach ($Job in $Jobs)
  
{   $Results += $Job.Pipe.EndInvoke($Job.Result)
  
}
  

  
$Results
  例6, 最后看看来怎么debug runspace。 PowerShell 5 以后提供了一个命令 Debug-Runspace可以像普通的debug一样来跟踪当前执行的命令或者脚本。
  先直接创建一个runspace,可以看见他的状态是available
$rs=[runspacefactory]::CreateRunspace()  
$rs.name="MyRunSpace"
  
$rs.open()
  
get-runspace
DSC0004.png

  把这个runspace绑定到一个powershell的实例,绑定某个脚本,异步执行
$ps=[powershell]::create()  
$ps.runspace=$rs
  
$ps.addscript('C:\users\yli\documents\github\Powershell\Restart-WSUSComputers.ps1') > $null
  
$async=$ps.BeginInvoke()
  
get-runspace
  可以看见他的状态变成了busy
DSC0005.png

  这个时候我们来debug一下
Debug-Runspace Myrunspace  他自动就切换到我的脚本页面了,按F10就会一行行的自动跟踪执行下去了
DSC0006.png

  如果需要终止debug,在控制台输入 detach 就可以了
  参考资料
  1. https://blogs.msdn.microsoft.com/powershell/2015/09/08/powershell-runspace-debugging-part-1/
  2. https://blogs.msdn.microsoft.com/powershell/2013/10/01/paap-windows-powershell-as-a-platform-part-1/
  3. http://www.cnblogs.com/lxblog/archive/2012/12/11/2813893.html
  4. https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/26/beginning-use-of-powershell-runspaces-part-1/



运维网声明 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-561316-1-1.html 上篇帖子: PowerShell 所需状态配置 (DSC) overview 下篇帖子: Powershell AWS 自动化管理 (7) - RDS
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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