У меня есть сценарий PowerShell, который я отлаживаю и хочу перенаправить все операторы Write-Host в файл. Есть ли простой способ сделать это?
Перенаправить операторы Write-Host в файл
Ответ 1
До PowerShell 4.0
Write-Host
отправлял объекты на хост. Он не возвращает никаких объектов.Начиная с PowerShell 5.0 и новее,
Write-Host
является оболочкой дляWrite-Information
, которая позволяет выводить в информационный поток и перенаправлять его с помощью6>> file_name
.
http://technet.microsoft.com/en-us/library/hh849877.aspx
Однако, если у вас много операторов Write-Host
, замените их все на Write-Log
, что позволит вам решить, выводить ли в консоль, файл или журнал событий, или все три.
Проверьте также:
Add-Content
- операторы перенаправления как
>, >>, 2>, 2>, 2>&1
Write-Log
- Ти-объект
Start-Transcript
.
Ответ 2
Вы можете создать функцию прокси для Write-Host, которая отправляет объекты в стандартный поток вывода, а не просто печатает их. Я написал ниже командлет только для этой цели. Он создаст прокси на лету, который действует только на время текущего конвейера.
Полная запись в моем блоге здесь, но я включил код ниже. Используйте переключатель -Quiet
для подавления записи консоли.
Использование:
PS> .\SomeScriptWithWriteHost.ps1 | Select-WriteHost | out-file .\data.log # Pipeline usage
PS> Select-WriteHost { .\SomeScriptWithWriteHost.ps1 } | out-file .\data.log # Scriptblock usage (safer)
function Select-WriteHost
{
[CmdletBinding(DefaultParameterSetName = 'FromPipeline')]
param(
[Parameter(ValueFromPipeline = $true, ParameterSetName = 'FromPipeline')]
[object] $InputObject,
[Parameter(Mandatory = $true, ParameterSetName = 'FromScriptblock', Position = 0)]
[ScriptBlock] $ScriptBlock,
[switch] $Quiet
)
begin
{
function Cleanup
{
# Clear out our proxy version of write-host
remove-item function:\write-host -ea 0
}
function ReplaceWriteHost([switch] $Quiet, [string] $Scope)
{
# Create a proxy for write-host
$metaData = New-Object System.Management.Automation.CommandMetaData (Get-Command 'Microsoft.PowerShell.Utility\Write-Host')
$proxy = [System.Management.Automation.ProxyCommand]::create($metaData)
# Change its behavior
$content = if($quiet)
{
# In quiet mode, whack the entire function body,
# simply pass input directly to the pipeline
$proxy -replace '(?s)\bbegin\b.+', '$Object'
}
else
{
# In noisy mode, pass input to the pipeline, but allow
# real Write-Host to process as well
$proxy -replace '(\$steppablePipeline\.Process)', '$Object; $1'
}
# Load our version into the specified scope
Invoke-Expression "function ${scope}:Write-Host { $content }"
}
Cleanup
# If we are running at the end of a pipeline, we need
# to immediately inject our version into global
# scope, so that everybody else in the pipeline
# uses it. This works great, but it is dangerous
# if we don't clean up properly.
if($pscmdlet.ParameterSetName -eq 'FromPipeline')
{
ReplaceWriteHost -Quiet:$quiet -Scope 'global'
}
}
process
{
# If a scriptblock was passed to us, then we can declare
# our version as local scope and let the runtime take
# it out of scope for us. It is much safer, but it
# won't work in the pipeline scenario.
#
# The scriptblock will inherit our version automatically
# as it in a child scope.
if($pscmdlet.ParameterSetName -eq 'FromScriptBlock')
{
. ReplaceWriteHost -Quiet:$quiet -Scope 'local'
& $scriptblock
}
else
{
# In a pipeline scenario, just pass input along
$InputObject
}
}
end
{
Cleanup
}
}
Ответ 3
Использование перенаправления приведет к зависанию Write-Host. Это связано с тем, что Write-Host имеет дело с различными проблемами форматирования, которые характерны для текущего используемого терминала. Если вы просто хотите, чтобы ваш сценарий имел гибкость для вывода в обычном режиме (по умолчанию для оболочки, с возможностью >
, 2>
и т.д.), Используйте Write-Output.
В противном случае, если вы действительно хотите уловить особенности текущего терминала, Start-Transcript - хорошее место для начала. В противном случае вам придется пройти тестирование вручную или написать несколько сложных наборов тестов.
Ответ 4
Вы можете запустить свой сценарий во вторичной оболочке PowerShell и записать вывод следующим образом:
powershell -File 'Your-Script.ps1' > output.log
Это сработало для меня.
Ответ 5
Это сработало для меня в моем первом скрипте PowerShell, который я написал несколько дней назад:
function logMsg($msg)
{
Write-Output $msg
Write-Host $msg
}
Использование в скрипте:
logMsg("My error message")
logMsg("My info message")
Вызов выполнения сценария PowerShell:
ps> .\myFirstScript.ps1 >> testOutputFile.txt
Это не совсем ответ на этот вопрос, но он может помочь кому-то, пытающемуся выполнить как вход в консоль, так и вывод в какой-либо файл журнала, делая то, что я достиг здесь :)
Ответ 6
Определите функцию Write-Host. Попросите его записать файл. У вас могут быть проблемы, если некоторые вызовы используют странный набор аргументов. Кроме того, это будет работать только для вызовов, которые не относятся к Snapin.
Ответ 7
Я только что добавил Start-Transcript вверху скрипта и Stop-Transcript внизу.
Выходной файл должен был называться <folder where script resides>-<datestamp>.rtf
, но по какой-то причине файл трассировки помещался туда, где я этого не ожидал &— рабочий стол!
Ответ 8
Вам не следует использовать Write-Host, если вы хотите иметь сообщения в файле. Он предназначен только для записи на хост.
Вместо этого вы должны использовать модуль регистрации или Set/Add-Content.
Ответ 9
Я обнаружил, что лучший способ справиться с этим - иметь функцию ведения журнала, которая будет определять, существует ли пользовательский интерфейс хоста, и действовать соответствующим образом. Когда скрипт выполняется в интерактивном режиме, он отображает детали в пользовательском интерфейсе хоста, но когда он запускается через WinRM или в неинтерактивном режиме, он переключается на Write-Output , так что вы можете захватить его, используя операторы перенаправления >
или *>
redirection operators
function Log-Info ($msg, $color = "Blue") {
if($host.UI.RawUI.ForegroundColor -ne $null) {
Write-Host "'n[$([datetime]::Now.ToLongTimeString())] $msg" -ForegroundColor $color -BackgroundColor "Gray"
} else {
Write-Output "'r'n[$([datetime]::Now.ToLongTimeString())] $msg"
}
}
В тех случаях, когда вы хотите получить полный вывод с помощью раскраски Write-Host, вы можете использовать скрипт Get-ConsoleAsHtml.ps1, чтобы экспортировать буфер прокрутки хоста в HTML или RTF файл.
Ответ 10
Используйте Write-Output вместо Write-Host и перенаправьте его в файл, подобный следующему:
Deploy.ps1 > mylog.log or Write-Output "Hello World!" > mylog.log
Ответ 11
Попробуйте использовать Write-Output вместо Write-Host.
Вывод идет по конвейеру, но если это конец конвейера, он отправляется на консоль.
> Write-Output "test"
test
> Write-Output "test" > foo.txt
> Get-Content foo.txt
test
Ответ 12
Если у вас всего несколько операторов Write-Host, вы можете использовать оператор перенаправителя "6>>"
для файла:
Write-Host "Your message." 6>> file_path_or_file_name
Это "Пример 5: Подавить вывод с Write-Host", предоставленный Microsoft, измененный в соответствии с about_Operators.