Windows 上でのログハウスキープ

  • Windows Server でログファイルが溜まり続ける場合の削除用スクリプト
  • それなりに対象がいるので設定ファイルでとれるようにした。
  • 基本的には日付がついたログが溜まり続けることを想定。
    • 連番がつくタイプのファイルは連番が0パッドされていないと不正動作する(.1と.100ではなく.001と.100でなければならない)。
    • そういったログ名にしかできない場合は で最終書込日時からの経過日数を条件とすればよい。
  • 自動でスイッチしてくれないものをスイッチする機会として、スクリプトを実行できるようにした()
    • スクリプトはPowerShellで実行できるものであればよい(Invoke-Expressionで評価する)。
  • Windows Server 2008 R2 環境で動作確認( .Net Framework 3.5, PowerShell 2.0 )

呼び出し

powershell housekeep.ps1 housekeep.conf

housekeep.ps1

$conf = $args[0]
if ( !$conf ) {
    echo "usage: housekeep.ps1 <housekeep.conf>"
    exit
}

$xmldoc = [XML](cat $conf)

foreach ( $hk in $xmldoc.HouseKeeps.HouseKeep ) {
    # directory が未定義または不正なエントリは無視する
    $dir = $hk.directory
    if ( !$dir -or !$dir.Trim() -or !(Test-Path $dir -PathType Container) ) { continue }
    cd $dir

    # prescript実行
    if ( $hk.prescripts -ne $null ) {
        foreach ( $ps in $hk.prescripts.script ) {
            echo ("prescript... " + $ps)
            Invoke-Expression $ps
        }
    }

    # ハウスキープ実行
    $maxcount = $hk.maxcount
    $maxage   = $hk.maxage
    $value    = $null
    foreach ( $filter in $hk.filename ) {
        # ファイル数ベースの削除(maxcount指定時)
        if ( [int]::TryParse($maxcount, [ref]$value) ) {
            echo ("housekeep(maxcount=$maxcount)... on " + $dir + "\" + $filter)
            foreach ( $f in ls -filter $filter | sort Name -descending | select -skip $value ) {
                echo ("deleting(maxcount)... " + $f.PSPath)
                $f.delete()
            }    
        }
        # ファイルの最終書込日時からの経過日数ベースの削除(maxage指定時, maxcount指定時はmaxcount優先)
        elseif ( [int]::TryParse($maxage, [ref]$value) ) {
            echo ("housekeep(maxage=$maxage)... on " + $dir + "\" + $filter)
            foreach ( $f in ls -filter $filter | where { $_.LastWriteTime.addDays($value) -lt (Get-Date) } ) {
                echo ("deleting(maxage)... " + $f.PSPath)
                $f.delete()
            }
        }
    }
}

housekeep.conf

<?xml version="1.0" ?>
<HouseKeeps>
<!--Tomcat向け設定例-->
    <HouseKeep>
        <directory>c:\var\log\tomcat</directory>
        <maxcount>31</maxcount> <!-- ログファイル数でハウスキープする場合(ファイル名が辞書順で後にくるものを残す) -->
        <filename>catalina.????????.log</filename>
        <filename>localhost.????????.log</filename>
        <filename>manager.????????.log</filename>
    </HouseKeep>

<!--MySQL向け設定例-->
    <HouseKeep>
        <prescripts>
            <!-- 名前変更後にflush-logsを実行してログファイル切り替え -->
            <script>Move-Item general.log ("general." + (Get-Date).addDays(-1).toString("yyyyMMdd") + ".log")</script>
            <script>Move-Item error.log ("error." + (Get-Date).addDays(-1).toString("yyyyMMdd") + ".log")</script>
            <script>Move-Item slow.log ("slow." + (Get-Date).addDays(-1).toString("yyyyMMdd") + ".log")</script>
            <script>mysqladmin -u logswitch -ppasswd flush-logs</script>
        </prescripts>
        <directory>c:\var\log\mysql</directory>
        <maxage>14</maxage> <!-- 最終書込日時からの経過日数でハウスキープする場合 -->
        <filename>general.????????.log</filename>
        <filename>error.????????.log</filename>
        <filename>slow.????????.log</filename>
    </HouseKeep>
</HouseKeeps>