Powershell 命令超时



我正在尝试在powershell中执行函数或脚本块,并为执行设置超时。

基本上我有以下内容(翻译成伪代码):

function query{
    #query remote system for something
}
$computerList = Get-Content "C:scriptscomputers.txt"
foreach ($computer in $computerList){
    $result = query
    #do something with $result
}

查询的范围可以从使用 Get-WmiObject 的 WMI 查询到 HTTP 请求,并且脚本必须在混合环境中运行,其中包括并非都具有 HTTP 接口的 Windows 和 Unix 计算机。因此,某些查询必然会挂起或需要很长时间才能返回。在寻求优化的过程中,我写了以下内容:

$blockofcode = {
    #query remote system for something
}
foreach ($computer in $computerList){
    $Job = Start-Job -ScriptBlock $blockofcode -ArgumentList $computer
    Wait-Job $Job.ID -Timeout 10 | out-null
    $result = Receive-Job $Job.ID
    #do something with result
}

但不幸的是,工作似乎承担了很多开销。在我的测试中,一个在 1.066 秒内执行的查询(根据 $blockofcode 内部的计时器)在作为作业执行时需要 6.964 秒才能返回结果。当然它有效,但我真的很想减少开销。我也可以一起启动所有工作,然后等待它们完成,但工作仍然可能挂起或花费大量时间才能完成。

因此,关于这个问题:有没有办法执行语句、函数、脚本块甚至超时的脚本,而超时不包括作业带来的那种开销?如果可能的话,我想并行运行命令,但这不是一个交易破坏者。

任何帮助或提示将不胜感激!

编辑:在混合窗口/Unix环境中运行Powershell V3

今天,我遇到了一个类似的问题,并注意到这个问题没有实际答案。我创建了一个简单的PowerShell类,称为TimedScript。此类提供以下功能:

  • 方法Start()准备好时开始工作的方法
  • 方法GetResult()方法,检索脚本的输出
  • 构造函数:
  • 采用两个参数的构造函数
    • 要执行的ScriptBlock
    • [int]超时期限(以毫秒为单位)

它目前缺少:

  • 将参数传递给 PowerShell ScriptBlock
  • 您想到的其他有用功能

类: 定时脚本

class TimedScript {
  [System.Timers.Timer] $Timer = [System.Timers.Timer]::new()
  [powershell] $PowerShell
  [runspace] $Runspace = [runspacefactory]::CreateRunspace()
  [System.IAsyncResult] $IAsyncResult
  TimedScript([ScriptBlock] $ScriptBlock, [int] $Timeout) {    
    $this.PowerShell = [powershell]::Create()
    $this.PowerShell.AddScript($ScriptBlock)
    $this.PowerShell.Runspace = $this.Runspace
    $this.Timer.Interval = $Timeout
    Register-ObjectEvent -InputObject $this.Timer -EventName Elapsed -MessageData $this -Action ({
      $Job = $event.MessageData
      $Job.PowerShell.Stop()
      $Job.Runspace.Close()
      $Job.Timer.Enabled = $False
    })
  }
  ### Method: Call this when you want to start the job.
  [void] Start() {
    $this.Runspace.Open()
    $this.Timer.Start()
    $this.IAsyncResult = $this.PowerShell.BeginInvoke()
  }
  ### Method: Once the job has finished, call this to get the results
  [object[]] GetResult() {
    return $this.PowerShell.EndInvoke($this.IAsyncResult)
  }
}

TimedScript 类的示例用法

# EXAMPLE: The timeout period is set longer than the execution time of the script, so this will succeed
$Job1 = [TimedScript]::new({ Start-Sleep -Seconds 2 }, 4000)
# EXAMPLE: This script will fail. Even though Get-Process returns quickly, the Start-Sleep call will cause it to be terminated by its Timer.
$Job2 = [TimedScript]::new({ Get-Process -Name s*; Start-Sleep -Seconds 3 }, 2000)
# EXAMPLE: This job will fail, because the timeout is less than the script execution time.
$Job3 = [TimedScript]::new({ Start-Sleep -Seconds 3 }, 1000)
$Job1.Start()
$Job2.Start()
$Job3.Start()

代码也托管在GitHub Gist上。

我想你可能想使用Powershell运行空间进行调查:

http://learn-powershell.net/2012/05/13/using-background-runspaces-instead-of-psjobs-for-better-performance/

相关内容

  • 没有找到相关文章

最新更新