使用 PoSh 和 7zip 组合多个日志文件进行归档
Combine multiple log files to archive using PoSh and 7zip
我正在尝试将多个日志文件合并到一个存档文件中,然后将该存档文件移动到另一个位置,以努力清理旧日志文件并保存硬盘 space。我们有一堆工具都记录到同一个根目录,每个工具都有一个文件夹用于存放它们的日志。 (例如,
- C:\ServerLogs
- C:\ServerLogs\App1
- C:\ServerLogsndApp
每个里面都有日志文件,比如
- C:\ServerLogs\App1\June1.log
- C:\ServerLogs\App1\June2.log
- C:\ServerLogsndApp\June1.log
- C:\ServerLogsndApp\June2.log
我想进入每个子文件夹,归档超过 5 天的所有文件,然后将归档移动到另一个(长期存储)驱动器并删除现在压缩的文件。我使用的工具是 PowerShell 和 7zip。下面的代码正在使用测试位置。
我在两个完整的轮班过程中从网上的各种来源拼凑了两个脚本,但没有一个是正确的。这是第一个:
# Alias for 7-zip
if (-not (test-path "$env:ProgramFiles-Zipz.exe")) {throw "$env:ProgramFiles-Zipz.exe needed"}
set-alias 7zip "$env:ProgramFiles-Zipz.exe"
$Days = 5 #minimum age of files to archive; in other words, newer than this many days ago are ignored
$SourcePath = C:\WorkingFolder\FolderSource\
$DestinationPath = C:\Temp\
$LogsToArchive = Get-ChildItem -Recurse -Path $SourcePath | Where-Object {$_.lastwritetime -le (get-date).addDays(-$Days)}
$archive = $DestinationPath + $now + ".7z"
#endregion
foreach ($log in $LogsToArchive) {
#define Args
$Args = a -mx9 $archive $log
$Command = 7zip
#write-verbose $command
#invoke the command
invoke-expression -command $Command $Args
这个问题是我在尝试调用表达式时遇到错误。我试过重组它,但后来出现错误,因为我的 $Args 有一个 "a"
所以我放弃了这种方法(尽管它是我的首选),并尝试了这套方法。
#region Params
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateScript({Test-Path -Path $_ -PathType 'container'})]
[System.String]
$SourceDirectory,
[Parameter(Position=1, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$DestinationDirectory
)
#endregion
function Compress-File{
#region Params
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateScript({Test-Path -Path $_ -PathType 'leaf'})]
[System.String]
$InputFile,
[Parameter(Position=1, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$OutputFile
)
#endregion
try{
#Creating buffer with size 50MB
$bytesGZipFileBuffer = New-Object -TypeName byte[](52428800)
$streamGZipFileInput = New-Object -TypeName System.IO.FileStream($InputFile,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)
$streamGZipFileOutput = New-Object -TypeName System.IO.FileStream($OutputFile,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write)
$streamGZipFileArchive = New-Object -TypeName System.IO.Compression.GZipStream($streamGZipFileOutput,[System.IO.Compression.CompressionMode]::Compress)
for($iBytes = $streamGZipFileInput.Read($bytesGZipFileBuffer, 0,$bytesGZipFileBuffer.Count);
$iBytes -gt 0;
$iBytes = $streamGZipFileInput.Read($bytesGZipFileBuffer, 0,$bytesGZipFileBuffer.Count)){
$streamGZipFileArchive.Write($bytesGZipFileBuffer,0,$iBytes)
}
$streamGZipFileArchive.Dispose()
$streamGZipFileInput.Close()
$streamGZipFileOutput.Close()
Get-Item $OutputFile
}
catch { throw $_ }
}
Get-ChildItem -Path $SourceDirectory -Recurse -Exclude "*.7z"|ForEach-Object{
if($($_.Attributes -band [System.IO.FileAttributes]::Directory) -ne [System.IO.FileAttributes]::Directory){
#Current file
$curFile = $_
#Check the file wasn't modified recently
if($curFile.LastWriteTime.Date -le (get-date).adddays(-5)){
$containedDir=$curFile.Directory.FullName.Replace($SourceDirectory,$DestinationDirectory)
#if target directory doesn't exist - create
if($(Test-Path -Path "$containedDir") -eq $false){
New-Item -Path "$containedDir" -ItemType directory
}
Write-Host $("Archiving " + $curFile.FullName)
Compress-File -InputFile $curFile.FullName -OutputFile $("$containedDir\" + $curFile.Name + ".7z")
Remove-Item -Path $curFile.FullName
}
}
}
这似乎确实有效,因为它为每个符合条件的日志创建了单独的存档,但我需要 "bundle" 将日志上传到一个大型存档中,但我似乎无法弄清楚如何到 recurse
(获取子级别项目)并执行 foreach
(确认年龄),而不是 foreach
生成个人档案。
我什至还没有进入移动和删除阶段,因为我似乎无法让归档阶段正常工作,但我当然不介意一旦弄清楚就继续努力(我已经花了整整两天时间来弄清楚这个!)。
我非常感谢任何和所有的建议!如果我没有解释什么,或者有点不清楚,请告诉我!
EDIT1:我完全忘记提及的部分要求是我需要将结构保留在新位置。所以新位置将有
- C:\ServerLogs --> C:\Archive\
- C:\ServerLogs\App1 --> C:\Archive\App1
C:\ServerLogsndApp --> C:\ArchivendApp
C:\存档
- C:\Archive\App1\archivedlogs.zip
- C:\ArchivendApp\archivedlogs.zip
而且我完全不知道如何指定 App1 的日志需要转到 App1。
EDIT2:对于后一部分,我使用了 Robocopy - 它维护文件夹结构,如果您将“.zip”作为参数提供给它,它只会处理 .zip 文件。
这一行 $Args = a -mx9 $archive $log
可能需要将右侧的值用双引号括起来,或者每个非变量都用引号括起来,每个非变量之间用逗号括起来,这样你就可以得到一个参数数组。
另一种方法是显式声明一个参数数组。像这样的......
$ArgList = @(
'a'
'-mx9'
$archive
$log
)
我还建议您不要使用自动 $Var 名称。看看 Get-Help about_Automatic_Variables
,您会发现 $Args
就是其中之一。强烈建议您不要将它们中的任何一个用于 阅读 以外的任何用途。给他们写信是不确定的。 [咧嘴一笑]
我正在尝试将多个日志文件合并到一个存档文件中,然后将该存档文件移动到另一个位置,以努力清理旧日志文件并保存硬盘 space。我们有一堆工具都记录到同一个根目录,每个工具都有一个文件夹用于存放它们的日志。 (例如,
- C:\ServerLogs
- C:\ServerLogs\App1
- C:\ServerLogsndApp
每个里面都有日志文件,比如
- C:\ServerLogs\App1\June1.log
- C:\ServerLogs\App1\June2.log
- C:\ServerLogsndApp\June1.log
- C:\ServerLogsndApp\June2.log
我想进入每个子文件夹,归档超过 5 天的所有文件,然后将归档移动到另一个(长期存储)驱动器并删除现在压缩的文件。我使用的工具是 PowerShell 和 7zip。下面的代码正在使用测试位置。
我在两个完整的轮班过程中从网上的各种来源拼凑了两个脚本,但没有一个是正确的。这是第一个:
# Alias for 7-zip
if (-not (test-path "$env:ProgramFiles-Zipz.exe")) {throw "$env:ProgramFiles-Zipz.exe needed"}
set-alias 7zip "$env:ProgramFiles-Zipz.exe"
$Days = 5 #minimum age of files to archive; in other words, newer than this many days ago are ignored
$SourcePath = C:\WorkingFolder\FolderSource\
$DestinationPath = C:\Temp\
$LogsToArchive = Get-ChildItem -Recurse -Path $SourcePath | Where-Object {$_.lastwritetime -le (get-date).addDays(-$Days)}
$archive = $DestinationPath + $now + ".7z"
#endregion
foreach ($log in $LogsToArchive) {
#define Args
$Args = a -mx9 $archive $log
$Command = 7zip
#write-verbose $command
#invoke the command
invoke-expression -command $Command $Args
这个问题是我在尝试调用表达式时遇到错误。我试过重组它,但后来出现错误,因为我的 $Args 有一个 "a"
所以我放弃了这种方法(尽管它是我的首选),并尝试了这套方法。
#region Params
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateScript({Test-Path -Path $_ -PathType 'container'})]
[System.String]
$SourceDirectory,
[Parameter(Position=1, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$DestinationDirectory
)
#endregion
function Compress-File{
#region Params
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateScript({Test-Path -Path $_ -PathType 'leaf'})]
[System.String]
$InputFile,
[Parameter(Position=1, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$OutputFile
)
#endregion
try{
#Creating buffer with size 50MB
$bytesGZipFileBuffer = New-Object -TypeName byte[](52428800)
$streamGZipFileInput = New-Object -TypeName System.IO.FileStream($InputFile,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)
$streamGZipFileOutput = New-Object -TypeName System.IO.FileStream($OutputFile,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write)
$streamGZipFileArchive = New-Object -TypeName System.IO.Compression.GZipStream($streamGZipFileOutput,[System.IO.Compression.CompressionMode]::Compress)
for($iBytes = $streamGZipFileInput.Read($bytesGZipFileBuffer, 0,$bytesGZipFileBuffer.Count);
$iBytes -gt 0;
$iBytes = $streamGZipFileInput.Read($bytesGZipFileBuffer, 0,$bytesGZipFileBuffer.Count)){
$streamGZipFileArchive.Write($bytesGZipFileBuffer,0,$iBytes)
}
$streamGZipFileArchive.Dispose()
$streamGZipFileInput.Close()
$streamGZipFileOutput.Close()
Get-Item $OutputFile
}
catch { throw $_ }
}
Get-ChildItem -Path $SourceDirectory -Recurse -Exclude "*.7z"|ForEach-Object{
if($($_.Attributes -band [System.IO.FileAttributes]::Directory) -ne [System.IO.FileAttributes]::Directory){
#Current file
$curFile = $_
#Check the file wasn't modified recently
if($curFile.LastWriteTime.Date -le (get-date).adddays(-5)){
$containedDir=$curFile.Directory.FullName.Replace($SourceDirectory,$DestinationDirectory)
#if target directory doesn't exist - create
if($(Test-Path -Path "$containedDir") -eq $false){
New-Item -Path "$containedDir" -ItemType directory
}
Write-Host $("Archiving " + $curFile.FullName)
Compress-File -InputFile $curFile.FullName -OutputFile $("$containedDir\" + $curFile.Name + ".7z")
Remove-Item -Path $curFile.FullName
}
}
}
这似乎确实有效,因为它为每个符合条件的日志创建了单独的存档,但我需要 "bundle" 将日志上传到一个大型存档中,但我似乎无法弄清楚如何到 recurse
(获取子级别项目)并执行 foreach
(确认年龄),而不是 foreach
生成个人档案。
我什至还没有进入移动和删除阶段,因为我似乎无法让归档阶段正常工作,但我当然不介意一旦弄清楚就继续努力(我已经花了整整两天时间来弄清楚这个!)。
我非常感谢任何和所有的建议!如果我没有解释什么,或者有点不清楚,请告诉我!
EDIT1:我完全忘记提及的部分要求是我需要将结构保留在新位置。所以新位置将有
- C:\ServerLogs --> C:\Archive\
- C:\ServerLogs\App1 --> C:\Archive\App1
C:\ServerLogsndApp --> C:\ArchivendApp
C:\存档
- C:\Archive\App1\archivedlogs.zip
- C:\ArchivendApp\archivedlogs.zip
而且我完全不知道如何指定 App1 的日志需要转到 App1。
EDIT2:对于后一部分,我使用了 Robocopy - 它维护文件夹结构,如果您将“.zip”作为参数提供给它,它只会处理 .zip 文件。
这一行 $Args = a -mx9 $archive $log
可能需要将右侧的值用双引号括起来,或者每个非变量都用引号括起来,每个非变量之间用逗号括起来,这样你就可以得到一个参数数组。
另一种方法是显式声明一个参数数组。像这样的......
$ArgList = @(
'a'
'-mx9'
$archive
$log
)
我还建议您不要使用自动 $Var 名称。看看 Get-Help about_Automatic_Variables
,您会发现 $Args
就是其中之一。强烈建议您不要将它们中的任何一个用于 阅读 以外的任何用途。给他们写信是不确定的。 [咧嘴一笑]