Powershell - 顺序 foreach 循环压缩文件

Powershell - Sequential foreach loop zipping files

我有许多 IIS 服务器,每个服务器上都有许多站点,我想定期压缩所有 IIS 日志。

我在本网站和 google 的帮助下拼凑了以下 powershell 脚本:

$files = Get-ChildItem  "D:\logfiles\IIS-Logs\*.log" -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-7))} 
foreach ($file in $files) {& 'C:\Program Files\WinRAR\winrar.exe' a -tl -df -m5 "$file.rar" $File}

此脚本的问题在于,如果有...比如说...总共有 2,000 个日志文件,它会尝试同时启动 2,000 个 Winrar 副本,服务器将会崩溃。这是出乎意料的。我希望它一次压缩一个文件。依次.

有没有人有任何想法让这个工作像我想要的那样?

我真的很想使用 Winrar 而不是本机 Compress-Archive 选项,因为:

如果我能以其他方式实现这一点,我不会嫁给 Winrar。

您可能想使用 "Start-Process -Wait" 而不是 &。在 Start-Process 上使用 -Wait 标志会强制它等待完成,然后会使您的程序按顺序 运行。查看这篇关于如何使用 Start-Process 的文章:更好的 PowerShell 启动过程您可能还想使用 cmdlet Compress-Archive 而不是命令行程序 Winrar,后者可能会更好地集成并在脚本中为您提供更好的反馈。

WinRAR 有这样的东西吗?

$files = Get-ChildItem  "D:\logfiles\IIS-Logs\*.log" -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-7))}
foreach ($file in $files) {
    $args = 'a -tl -df -m5 "' + $file.rar + '" ' + $File
    Start-Process -Wait -filepath 'C:\Program Files\WinRAR\winrar.exe' -ArgumentList $args
}

或者使用 Compress-Archive

$files = Get-ChildItem  "D:\logfiles\IIS-Logs\*.log" -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-7))}
foreach ($file in $files) {
    Compress-Archive -Path $file.FullName -DestinationPath "$($File.FullName).rar"
{

以上内容未经测试,但应该可以,除非我打错了字。

出于测试目的,我创建了一个 LogFolder,其中包含 3 个独立的日志文件夹,Log1、Log2 和 Log3。这些日志文件夹中的每一个都有 2000 个文件,每个文件有 2MB 的数据。这是命令我运行分别压缩每个文件夹

如果性能太慢(从同一磁盘读取和写入时),您也可以 运行 串行。


$ElementsInLog = (Get-ChildItem C:\temp\LogFolder\*.txt -Recurse).Length
$ElementsInLog1 = (Get-ChildItem C:\temp\LogFolder\Log1\*.txt -Recurse).Length
$ElementsInLog2 = (Get-ChildItem C:\temp\LogFolder\Log2\*.txt -Recurse).Length
$ElementsInLog3 = (Get-ChildItem C:\temp\LogFolder\Log3\*.txt -Recurse).Length

Write-Output "Main: $ElementsInLog`nLog1: $ElementsInLog1`nLog2: $elementsInLog2`nLog3: $elementsInLog3"
Write-output "Total File Size: $((Get-ChildItem C:\temp\LogFolder\Log1\*.txt -Recurse | Measure-Object length -Sum).Sum / 1024 / 1024 / 1024) GB"


Write-Output "Starting Tasks..."

$job1 = Start-Job -ScriptBlock {
  Write-Output "Log1: $(Get-Date -Format G)"
  Get-ChildItem C:\temp\LogFolder\Log1 -Recurse | Compress-Archive -DestinationPath C:\temp\log1.zip -CompressionLevel Fastest
  Write-Output "Finished: $(Get-Date -Format G)"
}

$job2 = Start-Job -ScriptBlock {
    Write-Output "Log2: $(Get-Date -Format G)"
    Get-ChildItem C:\temp\LogFolder\Log3 -Recurse | Compress-Archive -DestinationPath C:\temp\log3.zip -CompressionLevel Fastest
    Write-Output "Finished: $(Get-Date -Format G)"
}

$job3 = Start-Job -ScriptBlock {
    Write-Output "Log2: $(Get-Date -Format G)"
    Get-ChildItem C:\temp\LogFolder\Log4 | Compress-Archive -DestinationPath C:\temp\log4.zip -CompressionLevel Fastest
    Write-Output "Finished: $(Get-Date -Format G)"
}

while($job1.State -eq "Running" -or $job2.State -eq "Running" -or $job3.State -eq "Running") { 
    Start-Sleep 5
}

Receive-Job $job1
Receive-Job $job2
Receive-Job $job3


收到输出

Main: 8000
Log1: 2000
Log2: 2000
Log3: 2000
Total File Size: 4.12791967391968 GB

Starting Tasks...
Log1: 2/10/2020 8:36:22 PM
Finished: 2/10/2020 8:37:30 PM
Log2: 2/10/2020 8:36:22 PM
Finished: 2/10/2020 8:37:27 PM
Log3: 2/10/2020 8:36:22 PM
Finished: 2/10/2020 8:37:28 PM