運行腳本以向所有日志輸出添加日期前綴時,是否可以在 powershell 中使用?
我知道可以執行以下操作:Write-Host "$(Get-Date -format 'u') my log output"
但是我不想每次輸出一行時都呼叫一些函式。相反,我想在運行任何腳本或命令時修改所有輸出,并為每一行添加時間前綴。
uj5u.com熱心網友回復:
要在所有輸出(即stdout、stderr和特定于
- 使用
Out-String我們使用標準的 PowerShell 格式化系統來使輸出看起來正常,因為它會在沒有重定向的情況下出現(例如,表格之類的東西保持不變)。該-Stream引數對于保持 PowerShell 的流式輸出行為至關重要。如果沒有這個引數,只有在整個腳本塊完成后才會收到輸出。 - 雖然輸出看起來已經相當不錯了,但還是有一些小問題:
- 詳細、警告和除錯訊息沒有像往常一樣著色。
- 第二行中的“文本”一詞應為綠色。由于使用了
$PSStyle.Reset. 洗掉后,錯誤訊息的顏色會泄漏到日期列中,看起來更糟。它可以修復,但它不是微不足道的。 - 換行不正確(它會換行到輸出中間的日期列中)。
作為更通用、可重用的解決方案,我創建了一個Invoke-WithDateLog運行腳本塊、捕獲其所有輸出、在每行前面插入日期并再次輸出的函式:
Function Invoke-WithDateLog {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[scriptblock] $ScriptBlock,
[Parameter()]
[string] $DateFormat = '[yy\/MM\/dd H:mm:ss] ',
[Parameter()]
[string] $DateStyle = $PSStyle.Foreground.BrightBlack,
[Parameter()]
[switch] $CatchExceptions,
[Parameter()]
[switch] $ExceptionStackTrace,
[Parameter()]
[Collections.ICollection] $ErrorCollection
)
# Variables are private so they are not visible from within the ScriptBlock.
$private:ansiEscapePattern = "`e\[[0-9;]*m"
$private:lastFmt = ''
& {
if( $CatchExceptions ) {
try { & $scriptBlock }
catch {
# The common parameter -ErrorVariable doesn't work in scripted cmdlets, so use our own error variable parameter.
if( $null -ne $ErrorCollection ) {
$null = $ErrorCollection.Add( $_ )
}
# Write as regular output, colored like an error message.
"`n" $PSStyle.Formatting.Error "EXCEPTION ($($_.Exception.GetType().FullName)):`n $_" $PSStyle.Reset
# Optionally write stacktrace. Using the -replace operator we indent each line.
Write-Debug ($_.ScriptStackTrace -replace '^|\r?\n', "`n ") -Debug:$ExceptionStackTrace
}
}
else {
& $scriptBlock
}
} *>&1 | ForEach-Object -PipelineVariable record {
# Here the $_ variable is either:
# - a string in case of simple output
# - an instance of one of the System.Management.Automation.*Record classes (output of Write-Error, Write-Debug, ...)
# - an instance of one of the Microsoft.PowerShell.Commands.Internal.Format.* classes (output of a Format-* cmdlet)
if( $_ -is [System.Management.Automation.ErrorRecord] ) {
# The common parameter -ErrorVariable doesn't work in scripted cmdlets, so use our own error variable parameter.
if( $null -ne $ErrorCollection ) {
$null = $ErrorCollection.Add( $_ )
}
}
$_ # Forward current record
} | Out-String -Stream | ForEach-Object {
# Here the $_ variable is always a (possibly multiline) string of formatted output.
# Out-String doesn't add any ANSI escape codes to colorize Verbose, Warning and Debug messages,
# so we have to do it by ourselfs.
$overrideFmt = switch( $record ) {
{ $_ -is [System.Management.Automation.VerboseRecord] } { $PSStyle.Formatting.Verbose; break }
{ $_ -is [System.Management.Automation.WarningRecord] } { $PSStyle.Formatting.Warning; break }
{ $_ -is [System.Management.Automation.DebugRecord] } { $PSStyle.Formatting.Debug; break }
}
# Prefix for each line. It resets the ANSI escape formatting before the date.
$prefix = $DateStyle (Get-Date -Format $DateFormat) $PSStyle.Reset
foreach( $line in $_ -split '\r?\n' ) {
# Produce the final, formatted output.
$prefix ($overrideFmt ?? $lastFmt) $line ($overrideFmt ? $PSStyle.Reset : '')
# Remember last ANSI escape sequence (if any) of current line, for cases where formatting spans multiple lines.
$lastFmt = [regex]::Match( $line, $ansiEscapePattern, 'RightToLeft' ).Value
}
}
}
使用示例:
# To differentiate debug and verbose output from warnings
$PSStyle.Formatting.Debug = $PSStyle.Foreground.Yellow
$PSStyle.Formatting.Verbose = $PSStyle.Foreground.BrightCyan
Invoke-WithDateLog -CatchExceptions -ExceptionStackTrace {
"Write $($PSStyle.Foreground.Green)colored`ntext$($PSStyle.Reset) to stdout"
[PSCustomObject]@{ Answer = 42; Question = 'What?' } | Format-Table
Get-Content -Path not-exists -EA Continue # produce a non-terminating error
Write-Host 'Write to information stream'
Write-Warning 'Write to warning stream'
Write-Verbose 'Write to verbose stream' -Verbose
Write-Debug 'Write to debug stream' -Debug
throw 'Critical error'
}
PS 7.2 控制臺中的輸出:

筆記:
該代碼需要PowerShell 7 。
日期格式可以通過引數
-DateFormat(請參閱格式說明符)和-DateStyle(用于著色的 ANSI 轉義序列)更改。默認情況下
Write-Error -EA Stop不記錄腳本終止錯誤,例如通過拋出例外或使用創建的錯誤。相反,它們像往常一樣從腳本塊中冒出來。您可以傳遞引數以捕獲例外并像常規的非終止錯誤一樣記錄它們。傳遞也記錄腳本堆疊跟蹤,這對于除錯非常有用。-CatchExceptions-ExceptionStackTrace腳本 cmdlet (例如這個)不會設定自動變數
$?,也不會在$Error通過Write-Error. 公共引數都-ErrorVariable不起作用。為了仍然能夠收集錯誤資訊,我添加-ErrorCollection了可以像這樣使用的引數:$scriptErrors = [Collections.ArrayList]::new() Invoke-WithDateLog -CatchExceptions -ExceptionStackTrace -ErrorCollection $scriptErrors { Write-Error 'Write to stderr' -EA Continue throw 'Critical error' } if( $scriptErrors ) { # Outputs "Number of errors: 2" "`nNumber of errors: $($scriptErrors.Count)" }
uj5u.com熱心網友回復:
生成的物件Write-Host已經帶有時間戳,您可以使用它Update-TypeData來覆寫類.ToString()中的方法,然后將資訊流的輸出重定向到成功流。InformationRecord
Update-TypeData -TypeName System.Management.Automation.InformationRecord -Value {
return $this.TimeGenerated.ToString('u') $this.MessageData.Message.PadLeft(10)
} -MemberType ScriptMethod -MemberName ToString -Force
'Hello', 'World', 123 | Write-Host 6>&1
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/482795.html
標籤:电源外壳
