【问题标题】:How to Write to Log-File Without Writing to Console如何在不写入控制台的情况下写入日志文件
【发布时间】:2021-05-28 15:04:27
【问题描述】:

PowerShell 新手。 具有 Linux、bash 和编程(Java、C、HTML/CSS/JS)方面的一些经验。我刚开始实习。

我得到了一个 PowerShell 脚本来进行基本的磁盘清理。一部分贴在下面。它同时写入控制台和日志文件。我正在清理的一些服务器有数十万个文件。我想通过仅写入日志文件来提高脚本的性能。它通常开始时非常强劲,但一旦控制台输出变得足够大,事情就会开始急剧放缓。

我试图简单地删除 -verbose 标记,但它也没有写入。然后我的理解是“SilentlyContinue”将允许打印记录,但不允许控制台。但是代码已经有 SilentlyContinue 标志了?然后我尝试在一些 for-each 语句中添加 Verbose,但这也不起作用。

我现在只是在兜圈子。

有什么想法或建议吗?

function global:Write-Verbose
(
    [string]$Message
)
{ # check $VerbosePreference variable
    if ( $VerbosePreference -ne 'SilentlyContinue' )
    { Write-Host " $Message" -ForegroundColor 'Yellow' } 
}
Write-Verbose  
$DaysToDelete = 7
$LogDate = get-date -format "MM-d-yy-HH"
$objShell = New-Object -ComObject Shell.Application 
$objFolder = $objShell.Namespace(0xA) 
                    
Start-Transcript -Path C:\Windows\Temp\$LogDate.log
​
#Cleans all code off of the screen.
Clear-Host
​
$Before = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName,
@{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } },
@{ Name = "Size (GB)" ; Expression = { "{0:N1}" -f ( $_.Size / 1gb) } },
@{ Name = "FreeSpace (GB)" ; Expression = { "{0:N1}" -f ( $_.Freespace / 1gb ) } },
@{ Name = "PercentFree" ; Expression = { "{0:P1}" -f ( $_.FreeSpace / $_.Size ) } } |
Format-Table -AutoSize | Out-String                      
                    
## Stops the windows update service.
Get-Service -Name wuauserv | Stop-Service -Force -Verbose -ErrorAction SilentlyContinue
## Windows Update Service has been stopped successfully!
​
## Deletes the contents of windows software distribution.
Get-ChildItem "C:\Windows\SoftwareDistribution\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The Contents of Windows SoftwareDistribution have been removed successfully!
​
## Deletes the contents of the Windows Temp folder.
Get-ChildItem "C:\Windows\Temp\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The Contents of Windows Temp have been removed successfully!
​
## Deletes all files and folders in user's Temp folder.
Get-ChildItem "C:\users\$env:USERNAME\AppData\Local\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The contents of C:\users\$env:USERNAME\AppData\Local\Temp\ have been removed successfully!
                    
## Remove all files and folders in user's Temporary Internet Files.
Get-ChildItem "C:\users\$env:USERNAME\AppData\Local\Microsoft\Windows\Temporary Internet Files\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -le $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -recurse -ErrorAction SilentlyContinue
## All Temporary Internet Files have been removed successfully!
                    
## Cleans IIS Logs if applicable.
Get-ChildItem "C:\inetpub\logs\LogFiles\*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -le $(Get-Date).AddDays(-60)) } |
Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue
## All IIS Logfiles over x days old have been removed Successfully!
                  
## deletes the contents of the recycling Bin.
$objFolder.items() | ForEach-Object { Remove-Item $_.path -ErrorAction Ignore -Force -Verbose -Recurse }
## The Recycling Bin has been emptied!
## Starts the Windows Update Service
            
Get-Service -Name wuauserv | Start-Service -Verbose
​
$After = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName,
@{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } },
@{ Name = "Size (GB)" ; Expression = { "{0:N1}" -f ( $_.Size / 1gb) } },
@{ Name = "FreeSpace (GB)" ; Expression = { "{0:N1}" -f ( $_.Freespace / 1gb ) } },
@{ Name = "PercentFree" ; Expression = { "{0:P1}" -f ( $_.FreeSpace / $_.Size ) } } |
Format-Table -AutoSize | Out-String
​
## Sends some before and after info for ticketing purposes
Hostname ; Get-Date | Select-Object DateTime
Write-Host "Before: $Before"
Write-Host "After: $After"
​
Write-Verbose ( Get-ChildItem -Path C:\* -Include *.iso, *.vhd, *.vhdx -Recurse -ErrorAction SilentlyContinue | 
    Sort Length -Descending | Select-Object Name, Directory,
    @{Name = "Size (GB)"; Expression = { "{0:N2}" -f ($_.Length / 1GB) } } | Format-Table | 
    Out-String )
​
## Completed Successfully!
Stop-Transcript

【问题讨论】:

  • 我建议好好阅读一下Start-Transcript 的工作原理,以了解为什么您需要使用可能的自定义函数来重写脚本以写入日志文件。
  • Transcript 可以很好地进行调试,但它并不是真正旨在抑制任何内容,并且更难控制输出格式。查看重定向。

标签: powershell logging console diskspace


【解决方案1】:

您想查看重定向:https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-7.1

它对于记录您的 Catch 输出、将其包装在 ${} 中并指定您的流输出非常有用。例如:${ Write-Verbose ... } 4>&1 3>&1 2>&1 >> $logFile

尽管您拥有的大部分内容看起来都在尝试记录数据以供参考。就像您的之前:之后和最终 Get-ChildItem 声明一样。如果您边做边做,您可以通过管道将Out-File -Append 发送到日志文件。但是由于您将它放在最后一个块中,您可以简单地包装和重定向:

 &{ 
   Write-Host "Before: " $Before 
   Write-Host "After: " $After"

   Get-ChildItem -Path C:\* -Include *.iso, *.vhd, *.vhdx -Recurse -ErrorAction SilentlyContinue | 
   Sort Length -Descending | Select-Object Name, Directory,
   @{Name = "Size (GB)"; Expression = { "{0:N2}" -f ($_.Length / 1GB) } } | Format-Table | 
   Out-String
} *> C:\FilePath\File.txt

请注意,您甚至不需要将 Get-ChildItem 包装在 Write-Verbose 语句中。获取输出到控制台的 cmdlet,在使用重定向时只会将输出写入文件。唯一需要发出 Write 语句的情况是添加文本字符串/插入数据。

在不相关的说明中,我看到了一个 DRY 机会。你之前和之后的陈述是相同的。在返回语句的文件顶部放置一个函数,这样您就可以将 $Before$After 变量分配给返回输出。

【讨论】:

    猜你喜欢
    • 2021-07-26
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    相关资源
    最近更新 更多