Powershell:从Receive-Job获取输出 [英] Powershell: get output from Receive-Job

查看:144
本文介绍了Powershell:从Receive-Job获取输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组正在运行的作业.当他们完成时,我使用receive-job,它将输出写入屏幕.我想获取该输出并将其记录到文件中.我不想准备作业运行时产生的输出,因为一次运行多个作业会记录日志.求职Receive-Job以一种井井有条的方式打印输出.

I have a collection of jobs that are running. When they complete I use receive-job and it writes the output to the screen. I'd like to take that output and log it to a file. I don't want to tee the output produced while the jobs are running because with multiple jobs running at once the logging would be interspersed. Get-Job | Receive-Job prints the output in a nice organized manner.

我已经尝试了以下所有方法,但没有输出写入文件或存储在变量中,它只会显示在屏幕上:

I have tried all of the following and no output is written to the file or stored in a variable, it just goes to the screen:

#Wait for last job to complete
While (Get-Job -State "Running") {    
    Log "Running..." -v $info
    Start-Sleep 10        
}    
Log ("Jobs Completed. Output:") -v $info

# Getting the information back from the jobs
foreach($job in Get-Job){
    Receive-Job -Job $job | Out-File c:\Test.log -Append
    $output = Receive-Job -Job $job        
    Log ("OUTPUT: "+$output)
    Receive-Job -Job $job -OutVariable $foo
    Log ("FOO: "+$foo)
}

看到Keith的评论后,我在下面的foreach中删除了多余的Receive-Job调用:

I have removed the extra Receive-Job calls in the foreach to the following after seeing Keith's comment:

# Getting the information back from the jobs
foreach($job in Get-Job){
    Receive-Job -Job $job -OutVariable temp
    Write-Host ("Temp: "+$temp)
    $temp | Out-File -FilePath c:\Test.log -Append 
}

我还验证了我不在脚本中的其他任何地方使用Receive-Job.写入主机$ temp和输出文件仍然没有输出.

I also verified I'm not using Receive-Job anywhere else in the script. The write-host $temp and the out-file still produce no output though.

推荐答案

注意:经过一些实验,我发现使用write-output或仅直接输出变量也不是一个好的解决方案.如果您的函数使用这两种方法中的任何一种,并且还返回一个值,则输出将与返回值连接在一起!

NOTE: After some experimentation I have found that using write-output or just outputting a variable directly is not a good solution either. If you have a function that uses either of those methods and also returns a value the output will be concatenated with the return value!

我发现记录作业输出的最佳方法是将写入主机与Start-Transcript和Stop-Transcript cmdlet结合使用.有一些缺点,例如ISE不支持Transcript cmdlet.另外,我还没有找到一种方法,可以在不将其发送到主机的情况下将其输出到脚本中(我想要一个健壮的日志,并提供较少的用户体验),但这似乎是当前可用的最佳解决方案.这是我能够记录并发作业而不散布输出而不必为每个作业纠正多个临时日志文件然后将它们组合在一起的唯一方法.

The best way I have found to log output from jobs is to use write-host in combination with the Start-Transcript and Stop-Transcript cmdlets. There are some disadvantages such as the ISE does not support Transcript cmdlets. Also I haven't found a way to output to the transcript without it going to the host (I wanted a robust log with a less verbose user experience), but it seems to be the best solution available currently. It is the only way I've been able to log concurrent jobs without interspersing the output without having to right multiple temporary log files for each job and then combining them.

以下是我先前的回答,出于文档原因,我留下了答案:

Below was my previous answer that I left just for documentation reasons:

这里的问题不是从Receive-Job获取输出.我期望看到的作业的输出是由写入主机写入作业中的.当调用receive-job时,我在屏幕上看到了我的所有输出,但是没有其他内容可用于传递.看来,当我将所有那些写入主机cmdlet都调用了receive-job时,却没有任何东西可供我拾取和传送到文件外.以下脚本对此进行了演示.您会注意到睡眠时间"同时出现在日志文件和主机中,而睡眠"仅出现在主机中.因此,而不是尝试通过管道将Receive-Job传递给写主机,我需要修改Log函数以不使用写主机或拆分输出,如下所示.

The issue here was not getting output from Receive-Job. The output from the jobs I was expecting to see is being written in the job by write-host. When receive-job was called I saw all my output on the screen, but nothing was available to pipe elsewhere. It seems when I call receive-job all those write-host cmdlets execute, but there's nothing for me to pick up and pipe to out-file. The following script demonstrates this. You'll notice "Sleepy Time" appears in both the log file and the host, while "Slept" only appears in the host. So, rather than trying to pipe Receive-Job to write-host, I need to modify my Log function to not use write-host or to split the output as shown below.

cls
rm c:\jobs.log
$foo = @(1,2,3)
$jobs = @()

foreach($num in $foo){
    $s = { get-process -name "explorer"
           Start-Sleep $args[0]
           $x = ("Sleepy Time: "+$args[0])
           write-host $x
           $x
           write-host ("Slept: "+$args[0])
         }

    $id = [System.Guid]::NewGuid()
    $jobs += $id   
    Start-Job -Name $id -ScriptBlock $s -args $num
}

While (Get-Job -State "Running") {
    cls
    Get-Job
    Start-Sleep 1 
}
cls
Get-Job
write-host "Jobs completed, getting output"

foreach($job in $jobs){
    Receive-Job -Name $job | out-file c:/jobs.log -append    
}

Remove-Job *
notepad c:\jobs.log

下面是一个示例,该示例将运行并发作业,然后根据mbourgon的请求顺序记录这些作业.您会注意到时间戳指示工作是分散的,但日志按工作顺序显示.

Below is a sample that will run concurrent jobs and then log them sequentially as per mbourgon's request. You'll notice the timestamps indicate the work was interspersed, but the logging is displayed sequentially by job.

#This is an example of logging concurrent jobs sequentially
#It must be run from the powershell prompt as ISE does not support transcripts

cls
$logPath = "c:\jobs.log"
rm $logPath

Start-Transcript -Path $logPath -Append

#Define some stuff
$foo = @(0,1,2)
$bar = @(@(1,"AAA"),@(2,"BBB"),@(3,"CCC"))

$func = {
    function DoWork1 {
        Log "This is DoWork1"
        return 0
    }

    function DoWork2 {
        Log "This is DoWork2"
        return 0
    }

    function Log {
        Param([parameter(ValueFromPipeline=$true)]$InputObject)
        $nl = [Environment]::NewLine.Chars(0)
        $time = Get-Date -Format {HH:mm:ss} 
        Write-Host ($time+">"+$InputObject+$nl)
    }
}

#Start here
foreach($num in $foo){
    $s = { $num = $args[0]
           $bar = $args[1]           
           $logPath = $args[2]
           Log ("Num: "+$num) 

           for($i=0; $i -lt 5; $i++){
                $out = ([string]::$i+$bar[$num][1])
                Log $out
                start-sleep 1
           }
           Start-Sleep $num

           $x = DoWork1
           Log ("The value of x is: "+$x)           

           $y = DoWork2               
           Log ("The value of y is: "+$y)               
         }
    Start-Job -InitializationScript $func -ScriptBlock $s -args $num, $bar, $logPath
}

While (Get-Job -State "Running") {
    cls
    Get-Job
    Start-Sleep 1 
}
cls
Get-Job
write-host "Jobs completed, getting output"    

Get-Job | Receive-Job

Remove-Job *
Stop-Transcript
notepad $logPath

这篇关于Powershell:从Receive-Job获取输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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