AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 773696
Accepted
HopelessN00b
HopelessN00b
Asked: 2016-04-29 11:00:55 +0800 CST2016-04-29 11:00:55 +0800 CST 2016-04-29 11:00:55 +0800 CST

如何使用 PowerShell 对早于 x 天的日志文件启用 NTFS 压缩?

  • 772

我有一个运行 Windows 2012 R2 的应用程序服务器,它会生成大量日志文件,以至于它会半定期地在可用空间之外运行应用程序卷。由于应用程序本身的限制,我无法移动或重命名日志文件或启用 NTFS 重复数据删除,并且由于它不再是十年前,我不想使用批处理或 vbscript 来执行此操作为了我。

日志文件都在应用程序安装目录的各个子文件夹中,扩展名不同(一个组件添加日期作为日志文件扩展名),并且应用程序安装目录中有一个空间,因为应用程序开发人员是恶意的。写入日志的子文件夹至少专门用于写入日志。这也是一个 CPU 密集型应用程序,因此我不想自己压缩日志文件夹并招致与为日志写入压缩文件相关的 CPU 损失。

如何使用 PowerShell 对早于 x 天的日志文件启用 NTFS 压缩?

windows powershell ntfs windows-server-2012-r2 powershell-v4.0
  • 5 5 个回答
  • 7758 Views

5 个回答

  • Voted
  1. Best Answer
    HopelessN00b
    2016-04-29T11:00:55+08:002016-04-29T11:00:55+08:00

    由于 PowerShell 对文件操作的支持仍然相当缺乏,最简单的解决方案是创建一个 PowerShell 脚本来调用该compact.exe实用程序并将其设置为计划任务。因为路径名中的空格,所以要compact.exe直接调用,而不是使用Invoke-WMIMethod和CIM_DataFile类(处理路径中的空格会导致很多额外的工作)。

    假设 X 的年龄为 3 天,您的 PowerShell 脚本将如下所示:

    $logfolder="[location of the first logging subfolder]"
    $age=(get-date).AddDays(-3)
    
    Get-ChildItem $logfolder | where-object {$_.LastWriteTime -le $age -AND $_.Attributes -notlike "*Compressed*"} | 
    ForEach-Object {
    compact /C $_.FullName
    }
    
    $logfolder="[location of the next logging subfolder]"
    
    Get-ChildItem $logfolder | where-object {$_.LastWriteTime -le $age -AND $_.Attributes -notlike "*Compressed*"} | 
    ForEach-Object {
    compact /C $_.FullName
    }
    
    ...
    

    第二个条件是通过跳过已经压缩的文件(在第一次运行此脚本后会出现)来加速脚本执行。如果您想要,或者有很多不同的日志记录子文件夹,那么从重复的 PowerShell 代码中创建一个函数可能是有意义的,这将是一个相当简单的练习。

    • 9
  2. boossy
    2016-05-24T23:04:06+08:002016-05-24T23:04:06+08:00

    使用数组和 foreach 循环可以避免重复代码:

    $logfolders=("D:\Folder\One","D:\Folder\Two")
    $age=(get-date).AddDays(-3)
    
    foreach ($logfolder in $logfolders) {
        Get-ChildItem $logfolder | where-object {$_.LastWriteTime -le $age -AND $_.Attributes -notlike "*Compressed*"} | 
        ForEach-Object {
        compact /C $_.FullName
        }
    }
    

    ......

    • 5
  3. Andrew Vawter
    2019-12-25T02:49:40+08:002019-12-25T02:49:40+08:00

    Invoke-WmiMethod -Path "Win32_Directory.Name='C:\FolderToCompress'" -Name compress

    • 0
  4. Joachim Otahal
    2022-05-17T13:54:44+08:002022-05-17T13:54:44+08:00

    无需依赖 compact.exe 即可做到这一点,这是一种通过直接调用 NTFS 压缩的“纯 powershell”方法。这也处理来自日本的文件名和 unicode 文件名中的空格,后者很难提供给 compact.exe 命令行。另请参阅https://docs.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_set_compression。

    $MethodDefinition= @'
    public static class FileTools
    {
      private const int FSCTL_SET_COMPRESSION = 0x9C040;
      private const short COMPRESSION_FORMAT_DEFAULT = 1;
      private const short COMPRESSION_FORMAT_DISABLE = 0;
    
      [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      private static extern int DeviceIoControl(
          IntPtr hDevice,
          int dwIoControlCode,
          ref short lpInBuffer,
          int nInBufferSize,
          IntPtr lpOutBuffer,
          int nOutBufferSize,
          ref int lpBytesReturned,
          IntPtr lpOverlapped);
    
      public static bool Compact(IntPtr handle)
      {
        int lpBytesReturned = 0;
        short lpInBuffer = COMPRESSION_FORMAT_DEFAULT;
    
        return DeviceIoControl(handle, FSCTL_SET_COMPRESSION,
            ref lpInBuffer, sizeof(short), IntPtr.Zero, 0,
            ref lpBytesReturned, IntPtr.Zero) != 0;
      }
      public static bool Uncompact(IntPtr handle)
      {
        int lpBytesReturned = 0;
        short lpInBuffer = COMPRESSION_FORMAT_DISABLE;
    
        return DeviceIoControl(handle, FSCTL_SET_COMPRESSION,
            ref lpInBuffer, sizeof(short), IntPtr.Zero, 0,
            ref lpBytesReturned, IntPtr.Zero) != 0;
      }
    }
    '@
    
    $Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name ‘Kernel32’ -Namespace ‘Win32’ -PassThru
    
    $logfilespec = "c:\Logfolder\*.log"
    
    # compact anything older than three days
    foreach ($File in (Get-ChildItem -Path $logfilespec -Recurse -File).Where({$_.LastWriteTime -lt (Get-Date).AddDays(-3) -and $_.Attributes  -notmatch [System.IO.FileAttributes]::Compressed})) {
        $FileObject = [System.IO.File]::Open($File.FullName,'Open','ReadWrite','None')
        $Method = [Win32.Kernel32+FileTools]::Compact($FileObject.Handle)
        $FileObject.Close()
    }
    
    # decompact
    foreach ($File in (Get-ChildItem -Path $logfilespec -Recurse -File).Where({$_.Attributes  -match [System.IO.FileAttributes]::Compressed})) {
        $FileObject = [System.IO.File]::Open($File.FullName,'Open','ReadWrite','None')
        $Method = [Win32.Kernel32+FileTools]::Uncompact($FileObject.Handle)
        $FileObject.Close()
    }
    
    • 0
  5. Joachim Otahal
    2020-01-31T20:52:24+08:002020-01-31T20:52:24+08:00

    如果这些日志文件不在 C: 上,请使用 Server 2012 R2 重复数据删除功能。然后,您可以将其配置为仅删除 3 天前的 .log 文件(默认设置)。控制它的第二种方法,或者当它在 C 上时:将日志目录移动到不同的驱动器并使用 JUNCTION 指向新位置,最容易使用https://schinagl的 Hardlink-Shell-Extension 创建.priv.at/nt/hardlinkshellext/linkshellextension.html - 然后在顶部使用 2012 R2 重复数据删除。我已经看到日志文件和 SQl-dump-for-backup 驱动器的重复数据删除率超过 90%。

    • -1

相关问题

  • 知道任何适用于 Windows 的快速可编写脚本的 ftp 客户端吗?[关闭]

  • 如果 Windows 服务崩溃,如何自动重新启动它?

  • 无法安排任务(访问被拒绝)

  • 物理机重启时自动重启虚拟机(VMWare)

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve