home *** CD-ROM | disk | FTP | other *** search
- Subject: v13i033: Print BSD accounting file
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Roy Smith <phri!roy>
- Posting-number: Volume 13, Issue 33
- Archive-name: printacct
-
- [ This package displays the contents of the /usr/adm/acct files in
- human-readable format, so you can use things like awk and perl to
- print "better" accounting records. It will probably need work to
- run with the SystemV accounting stuff. --r$ ]
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Contents: README Makefile pracct.1 pracct.c yesterday.c accounting
-
- echo x - README
- sed 's/^@//' > "README" <<'@//E*O*F README//'
- Mon Jan 25 23:15:18 EST 1988
-
- This is a little program I whipped up to help me do user cpu usage
- accounting. On the surface, /etc/sa (or /usr/etc/sa if you're on a Sun) does
- cpu usage accounting, but it does so much damn processing that I kept finding
- myself being frustrated because I couldn't get exactly the statistics I
- wanted. Very un-unix-like, sa is. Doesn't let the user get at the actual
- data to do what he wants with it.
-
- My answer was to just convert the fields in /usr/adm/acct to ascii and
- hack together awk scripts to pull out whatever bits of information I happened
- to want that month. Maybe not very efficient, but easy. Contained herein is
- the program to print the /usr/adm/acct file, a man page, and a sample shell
- script that we run out of crontab at 15 minutes past midnight every day. We
- run this on a network of Sun workstations, all of which remote mount a common
- /usr/local. Since root permissions don't apply accross NFS mount points, I
- made /usr/local/acct owned by user "acct", and su to that when it comes time
- to move the daily summary file there. You can't just make the whole script
- suid acct because it has to remove /usr/adm/acct (aka /private/usr/adm/acct),
- which needs root permission. Isn't NFS fun?
-
- One last note. I like to keep each day's stats in a file named for
- that day. Since we run the stats for day X a few minutes into day X+1, I
- can't just use date to generate file names, because the names would be off by
- one day. I whipped up yesterday.c to solve this problem. A nicer solution
- (but decidedly feeping creatureism) would be to expand the Sys5 date to accept
- a (signed) offset which is added to the current date before going through the
- variable output formatting code.
-
- This was developed on SunOS-3.[02] systems, and hasn't been tested on
- any other systems. I believe the format of /usr/adm/acct is BSD specific, so
- it probably won't run on Sys5 machines unmodified.
-
- This code is public domain. Do with it what you want, including
- selling it for profit if you can find somebody stupid enough to pay money for
- it. All I ask is that you retain this notice with the code, and keep my name
- on it.
-
- Roy Smith, System Administrator
- Public Health Research Institute
- 455 First Avenue, New York, NY 10016
-
- UUCP: {allegra,philabs,seismo!cmcl2}!phri!roy
- @//E*O*F README//
- chmod u=rw,g=r,o=r README
-
- echo x - Makefile
- sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
- #
- # Makefile for pracct
- #
- # $Header: Makefile,v 1.3 86/12/09 17:41:42 roy Exp $
- # Copyright 1986 Roy Smith
- #
- # $Log: Makefile,v $
- # Revision 1.3 86/12/09 17:41:42 roy
- # Added rules for yesterday. Deleted rules for lint.
- #
- # Revision 1.2 86/11/29 23:30:18 roy
- # Added rule to co source file if needed.
- # Added rule for "make lint"
- #
- # Revision 1.1 86/11/29 23:12:19 roy
- # Initial revision
- #
- #
-
- CFLAGS = -O
-
- programs: pracct yesterday
-
- pracct: pracct.o
- cc $(CFLAGS) -o pracct pracct.o
-
- pracct.o: pracct.c
- cc $(CFLAGS) -c pracct.c
-
- pracct.c: RCS/pracct.c,v
- co pracct.c
-
- yesterday: yesterday.o
- cc $(CFLAGS) -o yesterday yesterday.o
-
- yesterday.o: yesterday.c
- cc $(CFLAGS) -c yesterday.c
-
- yesterday.c: RCS/yesterday.c,v
- co yesterday.c
- @//E*O*F Makefile//
- chmod u=rw,g=r,o=r Makefile
-
- echo x - pracct.1
- sed 's/^@//' > "pracct.1" <<'@//E*O*F pracct.1//'
- @.TH DATE 1 "25 Jan 1988"
- @.SH NAME
- pracct \- print accounting information in human readable form
- @.SH SYNOPSIS
- @.B pracct
- [-v] [-a file] [-f [cvVsSxXeEbBuUgGmitTfF]]
- @.SH DESCRIPTION
- @.I Pracct
- prints out the system accounting file in human-readable form with a minimum
- of processing.
- This is sort of a RISC version of
- @.I /etc/sa.
- As the man page says,
- @.I sa
- has a near google of options; unfortunately, it is rare that it has exactly
- the right one.
- With
- @.I pracct,
- you can simply get an ascii dump of the fields of interest and
- use
- @.I awk
- (for example) to calculate whatever statistics you desire.
- The options are many:
- @.TP
- @.B -v
- Verbose output; each field is tagged with a (hopefully) descriptive label.
- @.TP
- @.BI -a " file"
- Alternate accounting file, used instead of default
- @.I
- /usr/adm/acct.
- @.TP
- @.BI -f " flags"
- Fields to print.
- Fields are printed in the order specified.
- Default is
- @.B UcXB.
- Fields are separated with spaces, and an attempt is made to ensure that no
- spaces appear within fields (i.e. -f F will give `F----' instead of
- `F\0\0\0\0').
- This may be defeated, however, by command, user, group, or tty names
- containing spaces within them.
- Also,
- @.B
- -B
- gives a date in ctime format, which has embedded spaces.
- The fields are:
- @.TP
- @.B
- c
- Command name
- @.TP
- @.B
- v
- Numeric user CPU time (seconds)
- @.TP
- @.B
- V
- Symbolic user time (DD+HH:MM:SS)
- @.TP
- @.B
- s
- Numeric system time (seconds)
- @.TP
- @.B
- S
- Symbolic system time (DD+HH:MM:SS)
- @.TP
- @.B
- x
- User+system time (seconds)
- @.TP
- @.B
- X
- Symbolic user+system time (DD+HH:MM:SS)
- @.TP
- @.B
- e
- Numeric elapsed time (seconds)
- @.TP
- @.B
- E
- Symbolic elapsed time (DD+HH:MM:SS)
- @.TP
- @.B
- b
- Numeric beginning time (seconds)
- @.TP
- @.B
- B
- Symbolic beginning time (ctime format)
- @.TP
- @.B
- u
- Numeric user I.D.
- @.TP
- @.B
- U
- Login name
- @.TP
- @.B
- g
- Numeric group I.D.
- @.TP
- @.B
- G
- Group name
- @.TP
- @.B
- m
- Average memory usage
- @.TP
- @.B
- i
- Disk I/O blocks
- @.TP
- @.B
- t
- Major/minor device for control tty
- @.TP
- @.B
- T
- Name of control tty (/dev/tty??); currently unimplemented
- @.TP
- @.B
- f
- Accounting flags in octal
- @.TP
- @.B
- F
- Flags as FSCDX
- @.SH "SEE ALSO"
- sa(8), acct(2)
- @.SH AUTHOR
- Roy Smith <phri!roy>
- @//E*O*F pracct.1//
- chmod u=rw,g=r,o=r pracct.1
-
- echo x - pracct.c
- sed 's/^@//' > "pracct.c" <<'@//E*O*F pracct.c//'
- /*
- * Pracct.c -- print out the system accounting file with a minimum of
- * processing. This is sort of a RISC version of /etc/sa. As the man page
- * says, sa has a near google of options; unfortunately, it is rare that
- * it has exactly the right one. With pracct, you can simply get an ascii
- * dump of the fields of interest and let awk do the the rest.
- */
-
- # ifndef LINT
- static char rcsid[] = "$Header: pracct.c,v 1.7 88/01/25 22:57:16 roy Exp $";
- # endif
-
- /*
- * $Log: pracct.c,v $
- * Revision 1.7 88/01/25 22:57:16 roy
- * Removed copyright notice; code placed in public domain.
- *
- * Revision 1.6 87/11/17 15:10:55 roy
- * Added uid/gid name caches.
- *
- * Revision 1.5 86/12/02 17:31:43 roy
- * Fixed but with printing ac_comm -- if command name is full
- * length of ac_comm[], it isn't null terminated; we now are
- * careful not to run past this. Changed symbolic flag format
- * to print '-' instead of ' ' for missing flags to keep the number
- * of fields on an output line constant.
- *
- * Revision 1.4 86/12/02 14:34:52 roy
- * Added support for -v (verbose) and -a
- * (alternate accounting file) options.
- *
- * Revision 1.3 86/12/02 00:33:21 roy
- * Added command-line option processing using getopt.
- *
- * Revision 1.2 86/11/29 23:29:16 roy
- * Fixed rcsid string (capitalized $ H e a d e r : $).
- * Added type casts to keep lint happy.
- *
- * Revision 1.1 86/11/29 23:07:16 roy
- * Initial revision
- *
- */
-
- # include <sys/types.h>
- # include <sys/acct.h>
- # include <sys/file.h>
- # include <sys/time.h>
- # include <pwd.h>
- # include <grp.h>
- # include <stdio.h>
-
- # define ACCT_FILE "/usr/adm/acct" /* raw accounting data file */
- # define DFLT_FLDS "UcXB" /* default fields to print */
- # define FIELD_SEP ' ' /* how to delimit fields on output */
- # define GETOPT_FMT "va:f:" /* permissible command-line flags */
- # define USAGE_MSG "pracct [-v] [-a file] [-f [cvVsSxXeEbBuUgGmitTfF]]"
-
- /*
- * Symbolic names and flags for fields in acct(5) structure
- */
- # define COMM 'c' /* command name */
- # define UTIME 'v' /* numeric user CPU time (seconds) */
- # define SYM_UTIME 'V' /* symbolic user time (DD+HH:MM:SS) */
- # define STIME 's' /* numeric system time (seconds) */
- # define SYM_STIME 'S' /* symbolic system time (DD+HH:MM:SS) */
- # define SUMTIME 'x' /* user+system time (seconds) */
- # define SYM_SUMTIME 'X' /* symbolic user+system time (DD+HH:MM:SS) */
- # define ETIME 'e' /* numeric elapsed time (seconds) */
- # define SYM_ETIME 'E' /* symbolic elapsed time (DD+HH:MM:SS) */
- # define BTIME 'b' /* numeric beginning time (seconds) */
- # define SYM_BTIME 'B' /* symbolic beginning time (ctime format) */
- # define UID 'u' /* numeric user I.D. */
- # define SYM_UID 'U' /* login name */
- # define GID 'g' /* numeric group I.D. */
- # define SYM_GID 'G' /* group name */
- # define MEM 'm' /* average memory usage */
- # define IO 'i' /* disk I/O blocks */
- # define TTY 't' /* major/minor device for control tty */
- # define SYM_TTY 'T' /* name of control tty /dev/tty?? */
- # define FLAG 'f' /* flags in octal */
- # define SYM_FLAG 'F' /* flags as FSCDX */
-
- /*
- * Name cache stuff.
- */
- # define NC_NUID 256 /* size of uid cache; power of 2 */
- # define NC_UIDMASK 0xff /* log base 2 (NC_NUID) - 1 */
- # define NC_NGID 64 /* size of gid cache; power of 2 */
- # define NC_GIDMASK 0x3f /* log base 2 (NC_NGID) - 1 */
-
- struct nc
- {
- int nc_n; /* numeric uid or gid */
- char *nc_name; /* user or group name; NULL if unused */
- } unc[NC_NUID], gnc[NC_NGID];
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- struct acct ac;
- int fd, acsize, first, nbytes, verbose, n, maxcom;
- long utime, stime, etime, sumtime, btime;
- char *fields, *f, *ct, *ctime(), *dhms(), *uid2name(), *gid2name();
- char c, *afile;
- extern int optind;
- extern char *optarg;
-
- fields = DFLT_FLDS;
- verbose = 0;
- afile = ACCT_FILE;
-
- /*
- * figure out the maximum number of characters
- * stored for each command name.
- */
- maxcom = sizeof (ac.ac_comm) / sizeof (*ac.ac_comm);
-
- while ((c = getopt (argc, argv, GETOPT_FMT)) != EOF)
- {
- switch (c)
- {
- case 'f':
- fields = optarg;
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- case 'a':
- afile = optarg;
- break;
-
- case '?':
- fprintf (stderr, "pracct: illegal option (-%c)\n", c);
- fprintf (stderr, "pracct: usage: %s\n", USAGE_MSG);
- exit (1);
-
- default:
- fprintf (stderr, "bad return from getopt (%o)!\n", c);
- abort ();
- }
- }
-
- /*
- * Open accounting file for reading.
- */
- if ((fd = open (afile, O_RDONLY, 0)) < 0)
- {
- perror ("pracct: can't open accounting file");
- exit (1);
- }
-
- /*
- * Flush name cache.
- */
- for (n = 0; n < NC_NUID; n++)
- unc[n].nc_name = NULL;
-
- for (n = 0; n < NC_NGID; n++)
- gnc[n].nc_name = NULL;
-
- /*
- * Read the accounting file, one accounting-structure-worth
- * at a time, until EOF or error.
- */
- acsize = sizeof (ac) / sizeof (char);
- while ((nbytes = read (fd, (char *) &ac, acsize)) == acsize)
- {
- /*
- * Convert from snazzy compressed floating point format to
- * plain old integers. It's easier to just do all the
- * conversions than to check to see which ones we actually
- * need. We often want sumtime, so we rarely lose big.
- * This may get changed later if it proves to be important.
- */
- utime = expand (ac.ac_utime);
- stime = expand (ac.ac_stime);
- sumtime = utime + stime;
- etime = expand (ac.ac_etime);
-
- /*
- * Step though the desired fields in the order specified.
- * Insert a field delimiter in front of every field except
- * for the first one. Warning: fields may have internal
- * blanks, i.e. those in ctime format.
- */
- first = 1;
- for (f = fields; *f != NULL; f++)
- {
- if (first)
- first = 0;
- else
- putchar (FIELD_SEP);
-
- switch (*f)
- {
- case COMM:
- /*
- * We have to be careful not to print past
- * the end of the string because the command
- * name is only null terminated if it is
- * less than maxcom characters long.
- */
- printf ("%-*.*s", maxcom, maxcom, ac.ac_comm);
- continue;
-
- case UTIME:
- printf ("%8ld", utime);
- if (verbose)
- printf ("user");
- continue;
-
- case SYM_UTIME:
- printf ("%11s", dhms (utime));
- if (verbose)
- printf ("user");
- continue;
-
- case STIME:
- printf ("%8ld", stime);
- if (verbose)
- printf ("sys");
- continue;
-
- case SYM_STIME:
- printf ("%11s", dhms (stime));
- if (verbose)
- printf ("sys");
- continue;
-
- case SUMTIME:
- printf ("%8ld", sumtime);
- if (verbose)
- printf ("u+s");
- continue;
-
- case SYM_SUMTIME:
- printf ("%11s", dhms (sumtime));
- if (verbose)
- printf ("u+s");
- continue;
-
- case ETIME:
- printf ("%8ld", etime);
- if (verbose)
- printf ("real");
- continue;
-
- case SYM_ETIME:
- printf ("%11s", dhms (etime));
- if (verbose)
- printf ("real");
- continue;
-
- case BTIME:
- printf ("%10ld", (long) ac.ac_btime);
- if (verbose)
- printf ("begin");
- continue;
-
- case SYM_BTIME:
- /*
- * Beginning time in ctime format. Ctime
- * does us a favor and sticks a newline at
- * the end of the string, which we then have
- * to be careful not to print.
- */
- btime = ac.ac_btime;
- ct = ctime (&btime);
- while (*ct != '\n' && *ct != NULL)
- putchar (*(ct++));
- if (verbose)
- printf (" begin");
- continue;
-
- case UID:
- printf ("%5d", ac.ac_uid);
- if (verbose)
- printf ("uid");
- continue;
-
- case SYM_UID:
- printf ("%-8s", uid2name (ac.ac_uid));
- continue;
-
- case GID:
- printf ("%5d", ac.ac_gid);
- if (verbose)
- printf ("gid");
- continue;
-
- case SYM_GID:
- printf ("%-8s", gid2name (ac.ac_gid));
- continue;
-
- case MEM:
- printf ("%5d", ac.ac_mem);
- if (verbose)
- printf ("mem");
- continue;
-
- case IO:
- printf ("%10ld", (long) expand (ac.ac_io));
- if (verbose)
- printf ("io");
- continue;
-
- case TTY:
- if (verbose)
- {
- printf ("%3d", major (ac.ac_tty));
- printf ("/%3d", minor (ac.ac_tty));
- }
- else
- {
- printf ("%3d", major (ac.ac_tty));
- printf (" %3d", minor (ac.ac_tty));
- }
- continue;
-
- case SYM_TTY:
- printf ("no SYM_TTY yet");
- continue;
-
- case FLAG:
- printf ("%03o", ac.ac_flag);
- continue;
-
- case SYM_FLAG:
- putchar (ac.ac_flag & AFORK ? 'F' : '-');
- putchar (ac.ac_flag & ASU ? 'S' : '-');
- putchar (ac.ac_flag & ACOMPAT ? 'C' : '-');
- putchar (ac.ac_flag & ACORE ? 'D' : '-');
- putchar (ac.ac_flag & AXSIG ? 'X' : '-');
- continue;
- }
- }
- /*
- * After all the required fields, end the line.
- */
- putchar ('\n');
- }
-
- if (nbytes > 0)
- {
- fprintf (stderr, "pracct: short read on accounting file\n");
- exit (1);
- }
- if (nbytes < 0)
- {
- perror ("pracct: read error on accounting file");
- exit (1);
- }
- exit (0);
- }
-
- /*
- * Dhms -- convert time in seconds to DD+HH:MM:SS format. If
- * time is negative or greater than 99+23:59:59, return all ?'s.
- * Result is returned as a fixed-width, null-terminated, static
- * string which is overwritten on each call.
- */
- char *dhms (time)
- register long time; /* , no see :-) */
- {
- int sec, min, hour, day;
- static char buf[(sizeof ("DD+HH:MM:SS") / sizeof (char)) + 1];
-
- sec = time % 60;
- time = time / 60;
- min = time % 60;
- time = time / 60;
- hour = time % 24;
- time = time / 24;
- day = time;
-
- if (time < 0 || day > 99)
- sprintf (buf, "??+??:??:??");
- else
- sprintf (buf, "%02d+%02d:%02d:%02d", day, hour, min, sec);
-
- return (buf);
- }
-
- /*
- * Expand -- convert time from compressed floating point format to normal
- * integer. This routine is based on one in the 4.2BSD /etc/sa.c source
- * file. Warning: this depends on the format of t being exactly as in
- * 4.2BSD -- 3 bit power-of-8 exponent in high-order bits and 13 bit
- * mantissa in low-order bits.
- */
- time_t expand (t)
- comp_t t;
- {
- register time_t xtime;
- register exp;
-
- /*
- * Get mantissa and exponent.
- */
- xtime = t & 017777;
- exp = (t >> 13) & 07;
-
- /*
- * Compute time = mantissa * 8^exp.
- */
- while (exp != 0)
- {
- exp--;
- xtime <<= 3;
- }
-
- return(xtime);
- }
-
- /*
- * Uid2name -- convert a numeric user i.d. to a login name by looking it
- * up in /etc/passwd. The login name is returned as a null-terminated,
- * static string which is overwritten on each call. A name cache speeds
- * this up many fold (without it, over two-thirds of the user cpu time can
- * be spent here).
- */
- char *uid2name (uid)
- register int uid;
- {
- struct passwd *getpwuid(), *pw;
- register struct nc *entry;
- char *malloc();
- register char *name, *temp;
- register int l;
-
- entry = &unc[uid & NC_UIDMASK];
- if (entry->nc_name == NULL || entry->nc_n != uid)
- {
- entry->nc_n = uid;
- if (entry->nc_name != NULL)
- free (entry->nc_name);
-
- if ((pw = getpwuid (uid)) == NULL)
- name = "???";
- else
- name = pw->pw_name;
-
- l = 0;
- for (temp = name; *temp != NULL; temp++)
- l++;
- if ((entry->nc_name = malloc (l+1)) == NULL)
- {
- fprintf (stderr, "out of memory in uid2name\n");
- exit (1);
- }
- temp = entry->nc_name;
- while ((*(temp++) = *(name++)) != NULL)
- ;
- }
- return (entry->nc_name);
- }
-
- /*
- * Gid2name -- convert a numeric group i.d. to a group name by
- * looking it up in /etc/group. Similar to uid2name, q.v.
- */
- char *gid2name (gid)
- register int gid;
- {
- struct group *getgrgid(), *gr;
- register struct nc *entry;
- char *malloc();
- register char *name, *temp;
- register int l;
-
- entry = &gnc[gid & NC_GIDMASK];
- if (entry->nc_name == NULL || entry->nc_n != gid)
- {
- entry->nc_n = gid;
- if (entry->nc_name != NULL)
- free (entry->nc_name);
-
- if ((gr = getgrgid (gid)) == NULL)
- name = "???";
- else
- name = gr->gr_name;
-
- l = 0;
- for (temp = name; *temp != NULL; temp++)
- l++;
- if ((entry->nc_name = malloc (l+1)) == NULL)
- {
- fprintf (stderr, "out of memory in gid2name\n");
- exit (1);
- }
- temp = entry->nc_name;
- while ((*(temp++) = *(name++)) != NULL)
- ;
- }
- return (entry->nc_name);
- }
- @//E*O*F pracct.c//
- chmod u=r,g=r,o=r pracct.c
-
- echo x - yesterday.c
- sed 's/^@//' > "yesterday.c" <<'@//E*O*F yesterday.c//'
- /*
- * Yesterday -- print out yesterday's date.
- */
-
- # ifndef LINT
- static char rcsid[] = "$Header: yesterday.c,v 1.3 88/01/25 22:57:34 roy Exp $";
- # endif
-
- /*
- * $Log: yesterday.c,v $
- * Revision 1.3 88/01/25 22:57:34 roy
- * Removed copyright notice; code placed in public domain.
- *
- * Revision 1.2 86/12/09 17:40:44 roy
- * Fixed typo (prerror->perror) and added missing arguments to printf.
- *
- */
-
- # include <sys/time.h>
- # define SEC_PER_DAY (60*60*24) /* Let's see them change this one! */
-
- char *months[] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- char *days[] =
- {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
-
- main ()
- {
- register struct tm *timebuf;
- struct timeval t;
- struct timezone tz;
- long yesterday;
- int status;
-
- status = 0;
- if ((status = gettimeofday (&t, &tz)) < 0)
- {
- perror ("yesterday: gettimeofday failed");
- yesterday = 0;
- }
- else
- {
- yesterday = t.tv_sec - SEC_PER_DAY;
- }
-
- timebuf = localtime (&yesterday);
-
- printf ("%s %s %2d 19%02d\n", days[timebuf->tm_wday],
- months[timebuf->tm_mon],
- timebuf->tm_mday,
- timebuf->tm_year);
- exit (status);
- }
- @//E*O*F yesterday.c//
- chmod u=r,g=r,o=r yesterday.c
-
- echo x - accounting
- sed 's/^@//' > "accounting" <<'@//E*O*F accounting//'
- #!/bin/sh
-
- #
- # Generate per-user cpu time stats. Stats are kept in $acctdir/hostname/date.
- # Note that since we do this a few minutes after midnight, date is yesterday,
- # not today. If $acctdir/hostname doesn't exist, we create it.
- #
-
- #
- # Change these to put things in different places
- #
- pracct=/usr/local/etc/pracct
- yesterday=/usr/local/etc/yesterday
- acctdir=/usr/local/acct
-
- #
- # Make a copy of the accounting file, then do the normal daily summary
- # and truncate the accounting file. Accounting is temporarily turned
- # off while we snarf a copy of the file and do the statistics to keep
- # things in sync.
- #
- /usr/etc/accton
- cp /usr/adm/acct /tmp/acct1.$$
- /usr/etc/sa -s > /dev/null
- rm /usr/adm/acct
- touch /usr/adm/acct
- /usr/etc/accton /usr/adm/acct
-
- #
- # Generate the per-user stats.
- #
- $pracct -a /tmp/acct1.$$ -f Ux | awk '
- {time[$1] = time[$1] + $2}
- END {for (name in time) print name, time[name]}
- ' > /tmp/acct2.$$
-
- rm -f /tmp/acct1.$$
-
- #
- # Make sure a directory exists for this machine. If not, try to create it.
- # Move daily summary temp file to accounting directory. This must be done
- # as user "acct" so we can write on the common accounting directory.
- #
- su acct << EOF_SU_ACCT
- if test ! -d $acctdir/`hostname`
- then
- mkdir $acctdir/`hostname`
- fi
- cp /tmp/acct2.$$ $acctdir/`hostname`/`$yesterday | tr ' ' '-'`
- EOF_SU_ACCT
-
- rm -f /tmp/acct2.$$
- @//E*O*F accounting//
- chmod u=rwx,g=rx,o=rx accounting
-
- echo Inspecting for damage in transit...
- temp=/tmp/shar$$; dtemp=/tmp/.shar$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 43 405 2316 README
- 40 114 755 Makefile
- 135 366 2061 pracct.1
- 499 1907 11883 pracct.c
- 59 170 1153 yesterday.c
- 52 215 1364 accounting
- 828 3177 19532 total
- !!!
- wc README Makefile pracct.1 pracct.c yesterday.c accounting | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if [ -s $dtemp ]
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
- --
- Roy Smith, {allegra,cmcl2,philabs}!phri!roy
- System Administrator, Public Health Research Institute
- 455 First Avenue, New York, NY 10016
-
-