【问题标题】:Combine multiple log files to archive using PoSh and 7zip使用 PoSh 和 7zip 将多个日志文件合并到存档
【发布时间】:2019-04-09 23:11:06
【问题描述】:

我正在尝试将多个日志文件合并到一个存档文件中,然后将该存档文件移动到另一个位置,以便清理旧的日志文件并节省硬盘空间。我们有一堆工具都记录到同一个根目录,每个工具的日志都有一个文件夹。 (例如,

  1. C:\ServerLogs
  2. C:\ServerLogs\App1
  3. C:\ServerLogs\2ndApp

每个里面都会有日志文件,比如

  1. C:\ServerLogs\App1\June1.log
  2. C:\ServerLogs\App1\June2.log
  3. C:\ServerLogs\2ndApp\June1.log
  4. C:\ServerLogs\2ndApp\June2.log

我想进入这些子文件夹中的每一个,将所有超过 5 天的文件存档,然后将存档移动到另一个(长期存储)驱动器并删除现在压缩的文件。我使用的工具是 PowerShell 和 7zip。以下代码正在使用测试位置。

在两个完整的轮班过程中,我从网上各种来源拼凑了两个脚本,但没有一个能正常工作。这是第一个:

# Alias for 7-zip 
if (-not (test-path "$env:ProgramFiles\7-Zip\7z.exe")) {throw "$env:ProgramFiles\7-Zip\7z.exe needed"} 
set-alias 7zip "$env:ProgramFiles\7-Zip\7z.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
        }
    }
}

这实际上似乎有效,因为它为每个符合条件的日志创建单独的存档,但我需要将日志“捆绑”到一个大型存档中,我似乎无法弄清楚如何recurse (获取子级别项目)并执行foreach(确认年龄),而无需foreach 生成个人档案。

我什至还没有进入移动和删除阶段,因为我似乎无法让归档阶段正常工作,但一旦解决了这个问题,我当然不介意继续努力(I'我已经花了整整两天时间试图弄清楚这一点!)。

我非常感谢任何和所有建议!如果我没有解释什么,或者有点不清楚,请告诉我!

EDIT1:我完全忘记提及的部分要求是我需要将结构保留在新位置。所以新的位置会有

  1. C:\ServerLogs --> C:\Archive\
  2. C:\ServerLogs\App1 --> C:\Archive\App1
  3. C:\ServerLogs\2ndApp --> C:\Archive\2ndApp

  4. C:\Archive

  5. C:\Archive\App1\archivedlogs.zip
  6. C:\Archive\2ndApp\archivedlogs.zip
    而且我完全不知道如何指定来自 App1 的日志需要转到 App1。

EDIT2:对于后面的部分,我使用了 Robocopy - 它维护文件夹结构,如果您将“.zip”作为参数输入,它只会执行 .zip 文件。

【问题讨论】:

  • 我认为这一行$Args = a -mx9 $archive $log 需要将值括在双引号中,或者将每个非变量括在引号中,每个非变量之间用逗号括起来,这样您就可以得到一个 args 数组。 ///// 还有,为什么不使用内置命令呢?列表见Get-Command *archive*
  • 你可以使用call operator代替invoke-expression:foreach ($log in $LogsToArchive) { & 7zip a -mx9 $archive $log }
  • @JamesC。我试过了,我(对于每个符合条件的日志文件)得到一个“警告:系统找不到指定的文件”和(奇怪的是!)目标目标中的一个空存档。总的来说,这是一种进步!
  • @Lee_Dailey 我会花一些时间在参数上加上引号,但至于使用 7zip,这是由上级决定的,所以我坚持使用它(我认为是也许是性能问题?)。但我会尝试摆弄它,看看我是否无法让“压缩存档”将多个文件接受到一个存档中。
  • @RSchreib - 您可能必须将文件移动到一个目录才能将它们放入一个存档中,而无需大量摆弄。至于内置存档 cmdlet ...它们总是存在于 ps4+ [或者可能是 3] 中,因此使用起来更容易预测。

标签: powershell logging archive 7zip


【解决方案1】:

这一行$Args = a -mx9 $archive $log 可能需要将右侧的值用双引号括起来,或者将每个非变量用引号括起来,每个非变量之间用逗号括起来,这样您就可以得到一个 args 数组。

另一种方法是显式声明一个 args 数组。像这样的……

$ArgList = @(
    'a'
    '-mx9'
    $archive
    $log
    )

我还建议您不要使用自动 $Var 名称。看看Get-Help about_Automatic_Variables,你会发现$Args 就是其中之一。强烈建议您不要将它们中的任何一个用于阅读以外的任何用途。写信给他们是不确定的。 [咧嘴一笑]

【讨论】:

    猜你喜欢
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 2016-05-13
    • 2013-03-29
    • 2011-08-24
    • 1970-01-01
    相关资源
    最近更新 更多