SUMMARY: Truncating system log files

From: Chris Hines (chris@New.Paramax.COM)
Date: Fri May 20 1994 - 04:17:51 CDT

I sent this to the list almost a week ago, but never saw it come
across. If you receive this twice, I appologize. (Of course, the
first time I forgot to give credit to all those that responded to my
question, so this is a better message anyway. ;)

The original question:

> Hello worthy managers,
> I'm running Solaris 2.2 (with too many patches to list here). I'm
> interested in a clean method for truncating the /var/adm/wtmp and
> /var/adm/wtmpx files. I can delete clean them out without any bad
> side-effects, but I'd really like to truncate them to a certain number
> of the most recent entries.
> I'm open minded, so if you have any comments or suggestions about
> working with ANY of the system log files, send them to me, please.

I received many excellent responses, some of which prompted further
research in the system documentation. I now have a much better
understanding of the utmp, utmpx, wtmp, and wtmpx files and their
purposes. :)

Before I summarize the responses, I'll share something that my research
turned up. One of the responses to my question alluded to the system
accounting tools. The fwtmp (in /usr/lib/acct) command can read a
binary wtmp file and turn it into an ASCII format and vice versa. Thus
the following command will make a truncated copy of wtmp.

   fwtmp </var/adm/wtmp | tail -500 | fwtmp -ic >/var/adm/wtmp.trunc

I could not find an equivalent command for the wtmpx file however. :(

Summary of responses:

Some people said to copy /dev/null to the file. This method is simple,
but it obliterates all the information in the file; not what I had in
mind. Another suggestion was to make copies of the files before
cleaning them out, and maintaining a rotating set of history files.

Some people said to use the dd command to truncate the files. (Note
that the record size would need to be calculated to get this working.)

I received a few copies of C programs written to do exactly what I
wanted. :} After reading through the source, they look very
promissing, and I'll probably give them a try when I get some time.

Thanks to all that responded:

Mike Raffety <> (Peter Allan)
bern@penthesilea.Uni-Trier.DE (Jochen Bern)
Jim Redpath SRI Ft Bragg <>
Claude Marinier <> (Ayrton Sargusingh)
John T Wilson <>
Tom Reingold <> (Jeff Wade x5117)
homebase! (Steve Kapalko) (Jeff Victor) (Perry Hutchison)

| Chris Hines / If your expecting something |
| Unisys Government Systems Group / clever here, don't hold |
| Newington, VA USA / your breath. |

This is the cream of the crop of the C programs. It was written for
SunOS 4.1.3, but should work on Solaris. Making another version that
also handles the /var/adm/wtmpx file will be necessary, but should be
easy using this program as a template.

/* */
/* Name: wtmp_trim.c */
/* Author: Sue Spence */
/* Platform: SunOS 4.1.x */
/* */
/* Usage: wtmp_trim [cutoff_period in days] */
/* */
/* Description: This utility will trim the size of the wtmp file */
/* by removing all entries which are older than the */
/* CUTOFF_PERIOD value. The original wtmp file is */
/* copied to /tmp first. If no cutoff_period is */
/* given on the command line the default is 180 days. */
/* */
/* NOTE: This software is in the public domain, no warranty */
/* expressed or implied. */
/* */

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <utmp.h>
#include <time.h>
#include <errno.h>

#define CUTOFF_PERIOD (time_t) (180) /* in days */

int main(argc, argv)
int argc;
char **argv;
    struct utmp wtmp_rec;
    int old_fd, new_fd;
    int wtmp_rec_sz = sizeof(wtmp_rec);
    time_t cutoff_period, cutoff_time;

    if (argc > 1)
        cutoff_period = (time_t) atoi(argv[1]);
        cutoff_period = CUTOFF_PERIOD;

     * Move wtmp to /tmp/wtmp
    if (system("cp /var/adm/wtmp /tmp/wtmp") < 0) {
        fprintf(stderr, "Error copying wtmp to /tmp. Exiting.\n");

     * Calculate the cutoff time in time_t
     cutoff_time = time(NULL) - (cutoff_period * 24 * 3600);
     fprintf(stdout, "\nCutoff date is %s\n", asctime(localtime(&cutoff_time)));

     * Open new wtmp for writing
    if ((new_fd = open("/var/adm/wtmp", O_WRONLY | O_TRUNC)) < 0) {
        fprintf(stderr, "Error %d opening new wtmp file. Exiting.\n",
     * Open old wtmp for reading
    if ((old_fd = open("/tmp/wtmp", O_RDONLY)) < 0) {
        fprintf(stderr, "Error %d opening /tmp/wtmp file. Exiting.\n",

     * Start from top of file, compare dates to see if
     * they fall within the cutoff_time.
     * When they do, start a loop which copies the rest of
     * the old wtmp file to the new one.
    while (read(old_fd, &wtmp_rec, wtmp_rec_sz) == wtmp_rec_sz) {
        if (wtmp_rec.ut_time >= cutoff_time) {
            do {
                if (write(new_fd, &wtmp_rec, wtmp_rec_sz) != wtmp_rec_sz) {
                            "Error %d writing record to new wtmp file.\n",
            } while (read(old_fd, &wtmp_rec, wtmp_rec_sz) == wtmp_rec_sz );

This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:09:01 CDT