【问题标题】:Using a Job within the While($true) loop of a PowerShell script在 PowerShell 脚本的 While($true) 循环中使用作业
【发布时间】:2021-06-16 18:37:37
【问题描述】:

如果在脚本立即运行时发现模式“空闲” - 它会成功发送电子邮件。问题是它应该能够以开始-睡眠间隔继续查看 while($true) 循环。这不会发生 - 它会等待 60 分钟然后退出 - 即使模式“空闲”被写为最后一行。

我需要在 Start-Job 中使用 while 循环吗?我尝试了使用等待但没有运气的代码:Get-Content $file -Tail 1 -Wait |选择字符串-模式“空闲”-安静

$job = Start-Job {
    # Note: $file should be the absolute path of your file
    Get-Content $File -Raw | Select-string -Pattern "Idle" -Quiet
}

while($true)
{
    # if the job has completed
    if($job.State -eq 'Completed')
    {
        $result = $job|Receive-Job

        # if result is True
        if($result)
        {
            $elapsedTime.Stop()
            $duration = $elapsedTime.Elapsed.ToString("hh\:mm\:ss")
            
            # .... send email logic here
            # for success result

            break #=> This is important, don't remove it
        }

        # we don't need a else here,
        # if we are here is because $result is false
        
        $elapsedTime.Stop()
        $duration = $elapsedTime.Elapsed.ToString("hh\:mm\:ss")

        # .... send email logic here
        # for unsuccessful result
        
        break #=> This is important, don't remove it
    }

    # if this is running for more than
    # 60 minutes break the loop
    if($elapsedTime.Elapsed.Minutes -ge 60)
    {
        $elapsedTime.Stop()
        $duration = $elapsedTime.Elapsed.ToString("hh\:mm\:ss")
        
        # .... send email logic here
        # for script running longer 
        # than 60 minutes

        break #=> This is important, don't remove it
    }
    
    Start-Sleep -Milliseconds 500
}

Get-Job|Remove-Job

【问题讨论】:

  • 这是因为get-content 只完成一次而不在循环内吗?

标签: powershell


【解决方案1】:
  • 您确实需要Get-Content-Wait 开关来持续(接近)实时检查文件中的新内容(每秒检查一次新内容)。

    • 但是,这样做会无限期地等待,并且只有在目标文件被删除、移动或重命名时才会结束。
  • 因此,应用-Wait 后,您的作业可能永远不会达到'Completed' 状态 - 但无需等待,因为Receive-Job 可以在作业运行时接收作业输出,因为它变得可用。

  • 但是,你不能使用Select-String-Quiet开关,因为它只会输出一个结果,即$true一次第一个找到匹配项 - 即使稍后添加的内容也不会产生进一步的输出匹配。

因此,您可能需要以下内容:

$job = Start-Job {
  # Use Get-Content with -Wait, but don't use Select-String with -Quiet
  Get-Content $File -Raw -Wait | Select-string -Pattern "Idle"
}

while ($true)
{
  # Check for available job output, if any.
  if ($result = $job | Receive-Job) {

      $duration = $elapsedTime.Elapsed.ToString("hh\:mm\:ss")
          
      # .... send email logic here
      # for success result
      break

  }

  # if this is running for more than
  # 60 minutes break the loop
  if($elapsedTime.Elapsed.Minutes -ge 60)
  {
      $elapsedTime.Stop()
      $duration = $elapsedTime.Elapsed.ToString("hh\:mm\:ss")
      
      # .... send email logic here
      # for script running longer 
      # than 60 minutes
      
      # Forcefully remove the background job.
      $job | Remove-Job -Force

      break
  }
  
  Start-Sleep -Milliseconds 500
}

注意:

  • $job | Receive-Job 要么不产生输出,如果碰巧没有可用的输出,或者Select-Object 报告的一个或多个[Microsoft.PowerShell.Commands.MatchInfo] 实例。

  • 将此命令用作if-statement 条件(结合对$result 的赋值)意味着一个或多个[Microsoft.PowerShell.Commands.MatchInfo] 实例使条件评估为$true,基于关于 PowerShell 的隐式 to-Boolean 强制逻辑 - 请参阅 this answer 的底部。

【讨论】:

    猜你喜欢
    • 2012-07-13
    • 1970-01-01
    • 2017-07-14
    • 2022-01-15
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多