Posted by nick @ 15:44 on March 12th 2007

Poor man’s logrotate for Windows

Have you ever been bothered by the db2diag.log growing out of control? I have. While on Linux and Unix you have nice tools like logrotate and its analogs written in a number of script languages, no such luck if you run DB2 on Windows. There is no Windows port of logrotate, and your MSCE colleagues don’t always look favourably at you trying to install ActivePerl or Cygwin on a production server.

Having suffered enough from Notepad not being able to open a 300 megabyte db2diag.log, I have written a Windows command script to rotate the DB2 diagnostic log file. It uses only built-in Windows commands and therefore can run on any out of the box Windows 2000, Windows XP, or Windows 2003 system. By the way, it should work for any log files (with some limitations), not necessarily those generated by DB2.

The scipt, logrotatew.cmd, works like this: it reads a configuration file, where you specify the logs to be rotated and how many generations you want to keep. It then renames each specified log, for example, db2diag.log to db2diag.log.1, db2diag.log.1 to db2diag.log.2 etc. The oldest generation of the log is then deleted. Optionally, it can compress the rotated logs with any file compression utility with a command line interface, e.g. gzip, which has a Windows port. Check the sample configuration file for details.

Make sure you invoke the script with the following command line, otherwise it will not work properly:

cmd /v:on /c logrotatew.cmd [-f <configfile>]

<configfile> argument is optional; if it is not specified the script will look for logrotatew.conf in the current directory.

There are some limitations, of course. Unlike the original logrotate, logrotatew does not:

  • save its state, therefore doing the entire rotation cycle every time it is invoked;
  • check the file size; if your log is empty it will still be rotated;
  • have an option of mailing the rotated log;

Also, as mentioned, it does rename the active log file. DB2 will happily recreate its log file if it doesn’t find it where it was before. However, some programs may not be that robust. If you choose to use my script, test in your environment before attempting to implement it on a production system.

You can download the script and a sample configuration file here (right-click and Save As…). As usual, caveat emptor, no warranties express or implied, use at your own risk, etc. etc.

25 Comments »

  1. The script doesn’t work with paths that have spaces in them, so use old 8.3 syntax like C:\Progra~1\ in stead of C:\Program Files\.

    Comment by Jan Aagaard — March 21, 2007 @ 06:14

  2. What to use to open/uncompress the file in Windows?

    Comment by Confused — December 19, 2007 @ 20:08

  3. The file is packaged as a gzip-ped tar archive. WinZip should be able to open it just fine. Alternatively, you can download the bsdtar utility, courtesy of the GNUWin32 project.

    Comment by nick — December 22, 2007 @ 18:24

  4. Hi Nick,
    since you want to simulate the log rotation, there must be a rotation logic in the script; the logic can be rotation by time or by log dimension.
    Where is the time or dimension reference in the logrotate.conf?
    Thanks in advance.

    NI >> I never said I wanted to simulate logrotate, so the only things that _must_ be there are those that I needed. You are free to modify the script as you see fit.

    The “time dimension”, as you call it, is determined by the script schedule: it will rotate the files every time you run the script. And you are right about the “size dimension” – it’s not there.

    Comment by Not really logrotate — April 2, 2009 @ 03:10

  5. Does not work with Tomcat. It states the process cannot access the file becuase it is being accessed by another process.

    Comment by James — April 16, 2009 @ 16:14

  6. Sorry to hear that. The script’s purpose was not to replace the original logrotate; I needed it to solve a very specific purpose, which it did. You could try modifying the script to copy the file instead of trying to rename it:

    copy old.log new.log
    echo . > old.log
    

    I did not try the above, so you’d have to do it yourself.

    Comment by nick — April 16, 2009 @ 20:02

  7. Well that sucks.

    I had planned to spend a fun hour or two writing my own version of this and finding that you’ve already done a very nice job spoiled that for me. :-)

    Thank-you, the script works very well and will be used reasonably often as time goes on.

    Nice job.

    Comment by Craig Massey — April 28, 2009 @ 17:55

  8. Instead of starting the script with “cmd /v:on /c” you may put “Setlocal EnableDelayedExpansion” as the first statement in the script.

    Comment by Christoph — May 14, 2009 @ 01:16

  9. Another hint: Instead of commenting with “rem” in the configfile and handle this token in the script you may specify e.g. “eol=#” in the “for” statement to not parse lines of the file with a preceding “#”-character.

    Comment by Christoph — May 14, 2009 @ 01:47

  10. ‘and your MSCE colleagues don’t always look favourably at you trying to install ActivePerl or Cygwin on a production server.’, you can package Perl scripts as EXE with PAR.

    Comment by Solli Honorio — May 15, 2009 @ 09:50

  11. You can use this command to rename/re-allocate the db2diag.log file:

    db2diag -A

    db2diag: Moving “/home/iidb2adm/sqllib/db2dump/db2diag.log”
    to “/home/iidb2adm/sqllib/db2dump/db2diag.log_2009-06-01-16.29.32″

    Comment by Me — July 1, 2009 @ 03:51

  12. I think for ‘Does not work with Tomcat. It states the process cannot access the file becuase it is being accessed by another process’ scenario – you could run as a service and make Tomcat dependent on logrote service runing.

    Comment by Jack Lyons — July 2, 2009 @ 08:48

  13. Hi,
    Nice job. Thanks. I’m using it for windows-apache’s (!) access.log files
    Some remarks, if you can update, I’d be grateful – sorry I can’t do it myself: I don’t really feel comfortable with all these %1!j!EXT stuff :)

    1) don’t like “spaces” as mentionned by someone else, use old 8.3 naming convention instead

    2) UNC paths are OK, provided there’s no space, again

    3) if a file does not exist (that might happen for some services/applications), we get an error message. Hopefully, the rotation occurs and there’s just a “hole” in the numbers, then.
    => It would be nice if it could check for file existence and create an empty file if needed
    (How would it react with wildcards? I don’t really care because I don’t use it, only single files.)

    Regards,

    Again, thank you

    Comment by michauko — July 9, 2009 @ 04:31

  14. How ’bout this for “poor man’s backup”…
    I have 10 machines that need ntbackup (client cannot pay $3k for Veritas or other quality solution) to get important files to server (long story of using VSS and cabarc on databases that cannot reside on remote drives, and cannot have Cygwin/ActivePerl, etc.)
    So…I tried to write what you’ve done about 2 years ago and failed. Was using *nix and SMB, but am now using logrotatew (successfully) to rotate *.bkf files so they don’t grow out of control from append.
    Thank you VERY much – Great Job!

    Comment by D Mix — September 20, 2009 @ 19:45

  15. I made the following modifications to logrotatew.cmd to allow for other compression tools like 7z (must be in your path):
    I added:
    if /I “%1″ == “compressmode” set _COMPRMD_=%2 & goto :eof
    if /I “%1″ == “compressflag” set _COMPRFLG_=%2 & goto :eof
    just below the one for “compresscmd”
    and changed these 2 sections:
    rem Rotate non-current files
    for /l %%i in (%2,-1,2) do (
    set i=%%i
    set /a j=i-1
    for /f %%f in (“%1″) do (
    if exist %1.!j!.!_EXT_! ren %1.!j!.!_EXT_! %%~nxf.%%i.!_EXT_!
    if exist %1.!j! (
    ren %1.!j! %%~nxf.%%i
    if not “_COMPRFLG_” == “” set _COMPRFLG_=%1.%%i.!_EXT_!
    if not “!_COMPR_!” == “” !_COMPR_! !_COMPRMD_! !_COMPRFLG_! %1.%%i !_COPTS_!
    )
    )
    )

    rem Rotate current file
    for /f %%f in (“%1″) do (
    ren %1 %%~nxf.1
    if not “_COMPRFLG_” == “” set _COMPRFLG_=%1.1.!_EXT_!
    if not “!_COMPR_!” == “” !_COMPR_! !_COMPRMD_! !_COMPRFLG_! %1.1 !_COPTS_!
    )

    Here’s the relevant lines to my changed conf file, note I’m doing this for Apache2.2 on a 64bit xp box:

    rem Optional command to compress rotated logs
    compresscmd 7z

    rem Optional command mode or to compress rotated logs (ex for 7z use “a” to add to archive, for gzip enter arguments like -v)
    compressmode a

    rem Optional setting for compression, set to 1 if the tool (like 7z) needs the archive specified before the file to be compressed, 0 otherwise (or rem it out)
    compressflag 1

    rem Extension that compressed files will have; “compressext” is required if you use “compresscmd”
    compressext 7z

    rem Optional command line arguments for the compression command appears at the end of the command line
    compressoptions -t7z

    rem Apache
    C:\PROGRA~2\APACHE~1\Apache2.2\logs\error.log 4

    Comment by Pelo88 — November 20, 2009 @ 11:01

  16. I almost forgot to mention, this is how I call the script:
    @echo off
    “C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin\httpd.exe” -w -n “Apache2.2″ -k stop
    cmd /v:on /c c:\logrotatew.cmd -f c:\logrotate.conf
    “C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin\httpd.exe” -w -n “Apache2.2″ -k start

    I saved the above in a file I called rotatelogs.cmd and I use the scheduler on that.

    Comment by Pelo88 — November 20, 2009 @ 11:04

  17. I just noticed that 7z doesn’t delete after compression and that’s not an option, so on we go!
    I added the following to my conf:
    rem Optional setting for compression, set to 1 if the tool (like 7z) doesn’t delete the file after compression, 0 otherwise (or rem it out)
    compressdel 1

    And I added the option to the conf parsing section of logrotatew.cmd:
    if /I “%1″ == “compressdel” set _COMDEL_=%2 & goto :eof

    I kept the order in tact, so I put the above after compressoptions, likewise in my conf.

    Then I added the following under the compression command in Rotate non-current files:
    if not “!_COMDEL_!” == “” del /q %1.%%i

    and the following under the compression command under Rotate current file:
    if not “!_COMDEL_!” == “” del /q %1.1

    Comment by Pelo88 — November 20, 2009 @ 11:24

  18. @Pelo88: Wow, that’s a lot of work! I suspect it might have been easier to create a wrapper script for 7z and invoke that, instead of editing the logrotate script itself.

    Comment by nick — November 20, 2009 @ 12:38

  19. EXCELLENT script, thanks for posting this, nick!

    I’m just curious — I wasn’t able to get the compression thing to work at all, have you made any edits to your script since your original post?

    Comment by mike — July 22, 2010 @ 16:19

  20. works great! thanks!

    Comment by joe — October 12, 2010 @ 18:52

  21. Looks like this has been updated by some one else here

    http://lorus.org/blog/2010/03/english-batch-logrotate-for-windows-xp-command-line-interpreter/

    I haven’t tried the other version yet.

    BTW Nick, love your work. Why this has never been implemented in windows properly is beyond me.

    Comment by Brett — March 17, 2011 @ 19:55

  22. Thank you, Nick! Was extremely surprised by the absence of this tool in Windows. Your script was very useful!

    Comment by backbone — September 20, 2011 @ 02:57

  23. I just created 2 different versions of your script:
    FileType – which rotate the log file in the same folder but with a different file type (.rlog by default)
    Subfolder – which rotate the log file to a subfolder instead (archive by default)

    I can send it to you for posting if you want.

    Thanks for sharing !

    Comment by Yves — November 25, 2011 @ 13:43

  24. I have referenced this site from my blog as I “borrowed” some ideas to create an Oracle XE alert log rotation script.

    http://lostbits.maxproit.com/?p=12

    Thanks for the posting.

    Comment by MiniPilote — July 17, 2012 @ 23:01

  25. Great,

    After a bit of tweaking (making both files logrotatew), it started working and did exactly what I wanted.

    I am in pretty much the same scenario (not able to install useful tools on a live Windows server)

    Thanks very much!

    Comment by Richard — November 9, 2013 @ 07:46

RSS feed for comments on this post. TrackBack URI

Leave a comment