Ответ 1
ПРИМЕЧАНИЕ. После некоторых экспериментов я обнаружил, что использование write-output или просто вывод переменной напрямую не является хорошим решением. Если у вас есть функция, которая использует любой из этих методов, а также возвращает значение, результат будет конкатенирован с возвращаемым значением!
Лучший способ найти выход из заданий - использовать write-host в сочетании с командлетами Start-Transcript и Stop-Transcript. Есть некоторые недостатки, такие как ISE не поддерживает командлеты Transcript. Кроме того, я не нашел способ вывода в расшифровку без его хостинга (мне нужен надежный журнал с менее подробным пользовательским интерфейсом), но, похоже, это лучшее решение, доступное в настоящее время. Это единственный способ, с помощью которого я мог регистрировать параллельные задания без вставки вывода без необходимости перебора нескольких временных файлов журнала для каждого задания, а затем их объединения.
Ниже был мой предыдущий ответ, который я оставил только по причинам документации:
Проблема здесь не была получена из Receive-Job. Вывод из заданий, которые я ожидал увидеть, записывается в задание с помощью write-host. Когда была получена задание на получение, я видел весь свой вывод на экране, но ничего не было доступно для прокладки в другом месте. Кажется, когда я вызываю get-job, все эти командлеты write-host выполняются, но мне нет ничего, что можно было бы забрать и вывести из файла. Это демонстрирует следующий script. Вы заметите, что "Сонное время" появляется как в файле журнала, так и на хосте, а "Спящий" появляется только на хосте. Поэтому вместо того, чтобы пытаться подключить Receive-Job к write-host, мне нужно изменить функцию Log, чтобы не использовать write-host или разделить вывод, как показано ниже.
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. Вы заметите, что временные метки указывают, что работа была перемежена, но ведение журнала отображается последовательно по заданию.
#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