merlin@hqda-ai.UUCP (03/02/87)
How old is your news? I wondered that, particularly after seeing a bunch of "file system full" errors :-( I know what the expire arguments were, but what was actually being done? AGEF (age files) is a program that can help. Feed it a list of directories. (Regular files are ok, but boring.) AGEF will recursively descend into each directory, and produce a table of file sizes according to age. The output can show you what's been filling up your disk :-(, or where you can increase the expiration time limit :-) As a sample, here's a run: % cd /usr/spool/news/news % agef * 7 days 14 days 30 days 45 days 46+ days Total Name ---------- ---------- ---------- ---------- ---------- ------------ ---- 20 83k 15 41k 26 61k 61 185k admin 3 4k 3 5k 15 21k 21 30k config 52 179k 49 141k 78 202k 179 522k groups 21 299k 4 42k 25 341k lists 7 26k 6 14k 18 58k 31 98k misc 5 6k 4 6k 20 28k 29 40k newsites 34 127k 32 90k 44 109k 110 326k software 5 21k 2 3k 3 14k 10 38k stargate 6 20k 2 3k 15 38k 23 61k sysadmin 153 765k 117 345k 219 531k 489 1641k Grand Total Columns are not cumulative. If a file is 26 days old, for example, it would only be listed in the 30-day column. Of course, the total row/column does the obvious thing. Warnings: AGEF does not know about hard links. If a file has multiple directory entries (i.e., it was cross-posted), it will be counted twice. AGEF does know about directories, and it does not count them. Who really wants to know how old a directory is, anyhow? If you add or delete age catetories, be sure to change the definition of AGES. David S. Hayes, The Merlin of Avalon PhoneNet: (202) 694-6900 ARPA: merlin%hqda-ai.uucp@brl.arpa UUCP: ...!seismo!sundc!hqda-ai!merlin ---------------------------------------------------------------------- # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # agef.c # #!/bin/sh echo x - agef.c cat > "agef.c" << '//E*O*F agef.c//' /* agef 02 March 1987 David S. Hayes, Site Manager Army Artificial Intelligence Center Pentagon HQDA (DACS-DMA) Washington, DC 20310-0200 Phone: 202-694-6900 Email: merlin@hqda-ai.UUCP dshayes@brl.ARPA +=======================================+ | This program is in the public domain. | +=======================================+ This program scans determines the amount of disk space taken up by files in a named directory. The space is broken down according to the age of the files. The typical use for this program is to determine what the aging breakdown of news articles is, so that appropriate expiration times can be established. Call via agef fn1 fn2 fn3 ... If any of the given filenames is a directory (the usual case), agef will recursively descend into it, and the output line will reflect the accumulated totals for all files in the directory. */ #include <sys/types.h> #include <sys/stat.h> #include <sys/dir.h> #include <sys/param.h> #include <stdio.h> char *program; /* our name */ #define SECS_DAY (24L * 60L * 60L) /* seconds in one day */ #define ceiling(x,y) ((x+y-1)/y) #define AGES 6 /* how many age categories */ #define TOTAL (AGES-1) /* column number of total column */ #define SAME 0 /* for strcmp */ char *header[] = { /* column headers */ "7 days", "14 days", "30 days", "45 days", "46+ days", "Total"}; int ages[] = { /* age categories */ 7, 14, 30, 45, 999999, 999999}; int inodes[AGES], /* inode count */ blocks[AGES]; /* block count */ char topdir[MAXPATHLEN]; /* our starting directory */ long today, time(); /* today's date */ main(argc, argv) int argc; char *argv[]; { int i; int summary; int total_inodes[AGES], /* for grand totals */ total_blocks[AGES]; program = *argv++; /* save our name for error messages */ argc--; summary = argc > 1; /* should we do a grant total? */ getwd(topdir); /* find out where we are */ today = time(0) / SECS_DAY; /* print our column headers */ for (i = 0; i < TOTAL; i++) printf("%10s ", header[i]); printf("%12s Name\n", header[TOTAL]); for (i = 0; i < TOTAL; i++) printf("---------- "); printf("------------ ----\n"); for (i = 0; i < AGES; i++) total_inodes[i] = total_blocks[i] = 0; /* now do some work */ for (; argc; argv++, argc--) { for (i = 0; i < AGES; i++) inodes[i] = blocks[i] = 0; chdir(topdir); /* be sure to start from the same place */ get_data(*argv); /* this may change our cwd */ display(*argv, inodes, blocks); for (i = 0; i < AGES; i++) { total_inodes[i] += inodes[i]; total_blocks[i] += blocks[i]; }; }; if (summary) { putchar('\n'); display("Grand Total", total_inodes, total_blocks); }; }; /* * Get the aged data on a file whose name is given. If the file is a * directory, go down into it, and get the data from all files inside. */ get_data(path) char *path; { struct stat stb; int i; long date, /* date of modification */ age; /* file age in days */ stat(path, &stb); if ((stb.st_mode & S_IFMT) == S_IFDIR) down(path); if ((stb.st_mode & S_IFMT) == S_IFREG) { date = stb.st_mtime / SECS_DAY; age = today - date; for (i = 0; i < TOTAL; i++) { if (age <= ages[i]) { inodes[i]++; blocks[i] += roundup(stb.st_size, 1024); break; }; }; inodes[TOTAL]++; blocks[TOTAL] += roundup(stb.st_size, 1024); }; } /* * We ran into a subdirectory. Go down into it, and read everything * in there. */ down(subdir) char *subdir; { DIR *dp; char cwd[MAXPATHLEN]; struct direct *file; if (strcmp(subdir, ".") == SAME || strcmp(subdir, "..") == SAME) return; if ((dp = opendir(subdir)) == NULL) { fprintf(stderr, "%s: can't read %s/%s\n", program, topdir, subdir); return; }; getwd(cwd); /* remember where we are */ chdir(subdir); /* go into subdir */ for (file = readdir(dp); file != NULL; file = readdir(dp)) get_data(file->d_name); chdir(cwd); /* go back where we were */ closedir(dp); /* shut down the directory */ } display(name, inodes, blocks) char *name; int inodes[], blocks[]; { char tmpstr[30]; int i; for (i = 0; i < TOTAL; i++) { tmpstr[0] = '\0'; if (inodes[i]) sprintf(tmpstr, "%d %4dk", inodes[i], blocks[i]); printf("%10s ", tmpstr); }; sprintf(tmpstr, "%d %5dk", inodes[TOTAL], blocks[TOTAL]); printf("%12s %-s\n", tmpstr, name); } //E*O*F agef.c// echo Possible errors detected by \'wc\' [hopefully none]: temp=/tmp/shar$$ trap "rm -f $temp; exit" 0 1 2 3 15 cat > $temp <<\!!! 201 677 4942 agef.c !!! wc agef.c | sed 's=[^ ]*/==' | diff -b $temp - exit 0 -- David S. Hayes, The Merlin of Avalon PhoneNet: (202) 694-6900 ARPA: merlin%hqda-ai.uucp@brl.arpa UUCP: ...!seismo!sundc!hqda-ai!merlin