在 PowerShell 脚本的 While($true) 循环中使用作业 [英] Using a Job within the While($true) loop of a PowerShell script

查看:71
本文介绍了在 PowerShell 脚本的 While($true) 循环中使用作业的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If the Pattern "Idle" is found at the immediate run of the script - it successfully sends the email. The problem is it should be able to keep looking within the while($true) loop with the start-sleep interval. This is not happening - it will wait for 60 minutes and then exit - even when the pattern "Idle" was written as the last line.

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

do I need a while loop within the Start-Job? I tried this code using a Wait with no luck: Get-Content $file -Tail 1 -Wait | Select-string -Pattern "Idle" -Quiet

$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-Wait 开关,可以(近)实时地不断检查文件中的新内容(每秒检查一次新内容).

    • You indeed need Get-Content's -Wait switch to keep checking a file for new content in (near) real time (new content is checked for once every second).

      • 但是,这样做会无限期地等待,并且只有在目标文件被删除、移动或重命名时才会结束.
      • However, doing so waits indefinitely, and only ends if the target files is deleted, moved, or renamed.

      因此,应用 -Wait 后,您的工作可能永远不会达到 'Completed' 状态 - 但鉴于 Receive-Job 可以接收作业运行时的作业输出,因为它变得可用.

      Therefore, with -Wait applied, your job may never reach status 'Completed' - but there's no need to wait for that, given that Receive-Job can receive job output while the job is running, as it becomes available.

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

      However, you mustn't use Select-String's -Quiet switch, because it will only ever output one result, namely $true once the first match is found - and will produce no further output even if content added later also matches.

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

      Therefore, you probably want something like the following:

      $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 either produces no output, if none happens to be available, or one or more [Microsoft.PowerShell.Commands.MatchInfo] instances reported by Select-Object.

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

      Using this command as an if-statement conditional (combined with an assignment to $result) means that one or more [Microsoft.PowerShell.Commands.MatchInfo] instances make the conditional evaluate to $true, based on PowerShell's implicit to-Boolean coercion logic - see the bottom section of this answer.

      这篇关于在 PowerShell 脚本的 While($true) 循环中使用作业的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆