mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-27 16:39:08 +00:00
A slight bit of code and doco cleanup, but mostly:
Add the much-needed and long-desired ability to force the log rotation to take place on a specific day or time, and document same. This works by extending the syntax of the `when' field to allow a restricted ISO 8601 time specification, and performing the log rotation if newsyslog is run during the same hour as is specified.
This commit is contained in:
parent
5d2b50da3c
commit
8fba304b43
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=43071
@ -1,14 +1,7 @@
|
||||
# $Id: Makefile,v 1.4 1997/02/22 16:08:24 peter Exp $
|
||||
# $Id: Makefile,v 1.5 1998/09/19 22:42:11 obrien Exp $
|
||||
|
||||
PROG= newsyslog
|
||||
|
||||
CFLAGS+= -DOSF
|
||||
CFLAGS+= -DCONF=\"/etc/newsyslog.conf\"
|
||||
CFLAGS+= -DPIDFILE=\"/var/run/syslog.pid\"
|
||||
CFLAGS+= -DCOMPRESS_PATH=\"/usr/bin/gzip\"
|
||||
CFLAGS+= -DCOMPRESS_PROG=\"gzip\"
|
||||
CFLAGS+= -DCOMPRESS_POSTFIX=\".gz\"
|
||||
|
||||
MAN8= newsyslog.8
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -1,7 +1,7 @@
|
||||
.\" This file contains changes from the Open Software Foundation.
|
||||
.\"
|
||||
.\" from: @(#)newsyslog.8
|
||||
.\" $Id: newsyslog.8,v 1.13 1998/05/10 19:04:05 hoek Exp $
|
||||
.\" $Id: newsyslog.8,v 1.14 1998/06/09 18:24:04 ache Exp $
|
||||
.\"
|
||||
.\" Copyright 1988, 1989 by the Massachusetts Institute of Technology
|
||||
.\"
|
||||
@ -17,7 +17,7 @@
|
||||
.\" the suitability of this software for any purpose. It is
|
||||
.\" provided "as is" without express or implied warranty.
|
||||
.\"
|
||||
.Dd January 12, 1989
|
||||
.Dd January 22, 1999
|
||||
.Dt NEWSYSLOG 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -34,25 +34,41 @@ is a program that should be scheduled to run periodically by
|
||||
When it is executed it archives log files if necessary. If a log file
|
||||
is determined to require archiving,
|
||||
.Nm
|
||||
rearranges the files so that ``logfile'' is empty, ``logfile.0'' has
|
||||
the last period's logs in it, ``logfile.1'' has the next to last
|
||||
rearranges the files so that
|
||||
.Dq Va logfile
|
||||
is empty,
|
||||
.Dq Va logfile Ns Li \&.0
|
||||
has
|
||||
the last period's logs in it,
|
||||
.Dq Va logfile Ns Li \&.1
|
||||
has the next to last
|
||||
period's logs in it, and so on, up to a user-specified number of
|
||||
archived logs. Optionally the archived logs can be compressed to save
|
||||
space.
|
||||
.Pp
|
||||
A log can be archived because of two reasons. The log file can have
|
||||
grown bigger than a preset size in kilobytes, or a preset number of
|
||||
hours may have elapsed since the last log archive. The granularity of
|
||||
A log can be archived for three reasons:
|
||||
.Bl -enum -offset indent
|
||||
.It
|
||||
It is larger than the configured size (in kilobytes).
|
||||
.It
|
||||
A configured number of hours have elapsed since the log was last
|
||||
archived.
|
||||
.It
|
||||
This is the specific configured hour for rotation of the log.
|
||||
.El
|
||||
The granularity of
|
||||
.Nm
|
||||
is dependent on how often it is scheduled to run by
|
||||
.Xr cron 8 .
|
||||
Since the program is quite fast, it may be scheduled to run every hour
|
||||
without any ill effects.
|
||||
without any ill effects,
|
||||
and mode three (above) assumes that this is so.
|
||||
.Pp
|
||||
When starting up,
|
||||
.Nm
|
||||
reads in a configuration file to determine which logs should be looked
|
||||
at. By default, this configuration file is
|
||||
reads in a configuration file to determine which logs may potentially
|
||||
be archived.
|
||||
By default, this configuration file is
|
||||
.Pa /etc/newsyslog.conf .
|
||||
Each line of the file contains information about a particular log file
|
||||
that should be handled by
|
||||
@ -85,18 +101,98 @@ besides the log file itself.
|
||||
When the size of the log file reaches
|
||||
.Ar size ,
|
||||
the log file will be trimmed as described above. If this field
|
||||
is replaced by a
|
||||
.Ar * ,
|
||||
is replaced by an asterisk
|
||||
.Pq Ql \&* ,
|
||||
then the size of the log file is not taken into account
|
||||
when determining when to trim the log file.
|
||||
.It Ar interval
|
||||
When
|
||||
.Ar interval
|
||||
hours have passed, the log file will be trimmed. If this field is
|
||||
replaced by a
|
||||
.Ar * ,
|
||||
then the number of hours since the last time the log was
|
||||
trimmed will not be taken into consideration.
|
||||
.It Ar when
|
||||
The
|
||||
.Ar when
|
||||
field can consist of an interval, a specific time, or both. If
|
||||
the
|
||||
.Ar when
|
||||
field is an asterisk
|
||||
.Pq Ql \&*
|
||||
log rotation will depend only on the contents of the
|
||||
.Ar size
|
||||
field.
|
||||
Otherwise, the
|
||||
.Ar when
|
||||
field consists of an optional interval in hours, optionally followed
|
||||
by an
|
||||
.So Li \&@ Sc Ns No -sign
|
||||
and a time in a restricted
|
||||
.Tn ISO 8601
|
||||
format. If a time is specified, the log file will only be trimmed
|
||||
if
|
||||
.Nm newsyslog
|
||||
is run within one hour of the specified time. If an
|
||||
interval is specified, the log file will be trimmed if that many hours have
|
||||
passed since the last rotation. When both a time and an interval are
|
||||
specified, both conditions must be satisfied for the rotation to take
|
||||
place.
|
||||
.Pp
|
||||
The particular format of the time is
|
||||
.Sm off
|
||||
.Oo
|
||||
.Oo
|
||||
.Oo
|
||||
.Oo
|
||||
.Oo
|
||||
.Va \&cc
|
||||
.Oc
|
||||
.Va \&yy
|
||||
.Oc
|
||||
.Va \&mm
|
||||
.Oc
|
||||
.Va \&dd
|
||||
.Oc
|
||||
.Oo
|
||||
.Li \&T
|
||||
.Oo
|
||||
.Va \&hh
|
||||
.Oo
|
||||
.Va \&mm
|
||||
.Oo
|
||||
.Va \&ss
|
||||
.Oc
|
||||
.Oc
|
||||
.Oc
|
||||
.Oc
|
||||
.Oc .
|
||||
.Sm on
|
||||
Optional date fields default to the appropriate component of the
|
||||
current date; optional time fields default to midnight; hence if today
|
||||
is January 22, 1999, the following date specifications are all
|
||||
equivalent:
|
||||
.Pp
|
||||
.Bl -item -compact -offset indent
|
||||
.It
|
||||
.Sq Li 19990122T000000
|
||||
.It
|
||||
.Sq Li 990122T000000
|
||||
.It
|
||||
.Sq Li 0122T000000
|
||||
.It
|
||||
.Sq Li 22T000000
|
||||
.It
|
||||
.Sq Li T000000
|
||||
.It
|
||||
.Sq Li T0000
|
||||
.It
|
||||
.Sq Li T00
|
||||
.It
|
||||
.Sq Li 22T
|
||||
.It
|
||||
.Sq Li \&T
|
||||
.It
|
||||
.Sq Li \&
|
||||
.El
|
||||
.Pp
|
||||
There is no provision for specification of a timezone. There is
|
||||
little point in specifying an explicit minutes or seconds component in
|
||||
the current implementation, since the only comparison is `within the
|
||||
hour'.
|
||||
.It Ar flags
|
||||
This optional field specifies if the archive should have any
|
||||
special processing done to the archived log files.
|
||||
|
@ -27,41 +27,33 @@ provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$Id: newsyslog.c,v 1.20 1998/06/09 18:24:04 ache Exp $";
|
||||
"$Id: newsyslog.c,v 1.21 1998/12/23 12:03:33 peter Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef CONF
|
||||
#define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
|
||||
#endif
|
||||
#ifndef PIDFILE
|
||||
#define PIDFILE "/etc/syslog.pid"
|
||||
#endif
|
||||
#ifndef COMPRESS_PATH
|
||||
#define COMPRESS_PATH "/usr/ucb/compress" /* File compression program */
|
||||
#endif
|
||||
#ifndef COMPRESS_PROG
|
||||
#define COMPRESS_PROG "compress"
|
||||
#endif
|
||||
#define OSF
|
||||
#ifndef COMPRESS_POSTFIX
|
||||
#define COMPRESS_POSTFIX ".Z"
|
||||
#define COMPRESS_POSTFIX ".gz"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
#define kbytes(size) (((size) + 1023) >> 10)
|
||||
#ifdef _IBMR2
|
||||
/* Calculates (db * DEV_BSIZE) */
|
||||
@ -71,6 +63,8 @@ static const char rcsid[] =
|
||||
#define CE_COMPACT 1 /* Compact the achived log files */
|
||||
#define CE_BINARY 2 /* Logfile is in binary, don't add */
|
||||
/* status messages */
|
||||
#define CE_TRIMAT 4 /* trim at a specific time */
|
||||
|
||||
#define NONE -1
|
||||
|
||||
struct conf_entry {
|
||||
@ -81,6 +75,7 @@ struct conf_entry {
|
||||
int numlogs; /* Number of logs to keep */
|
||||
int size; /* Size cutoff to trigger trimming the log */
|
||||
int hours; /* Hours between log trimming */
|
||||
time_t trim_at; /* Specific time to do trimming */
|
||||
int permissions; /* File permissions on the log */
|
||||
int flags; /* Flags (CE_COMPACT & CE_BINARY) */
|
||||
int sig; /* Signal to send */
|
||||
@ -91,17 +86,13 @@ int verbose = 0; /* Print out what's going on */
|
||||
int needroot = 1; /* Root privs are necessary */
|
||||
int noaction = 0; /* Don't do anything, just show it */
|
||||
int force = 0; /* Force the trim no matter what*/
|
||||
char *conf = CONF; /* Configuration file to use */
|
||||
char *conf = _PATH_CONF; /* Configuration file to use */
|
||||
time_t timenow;
|
||||
#define MIN_PID 5
|
||||
#define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */
|
||||
char hostname[MAXHOSTNAMELEN+1]; /* hostname */
|
||||
char *daytime; /* timenow in human readable form */
|
||||
|
||||
#ifndef OSF
|
||||
char *strdup(char *strp);
|
||||
#endif
|
||||
|
||||
static struct conf_entry *parse_file();
|
||||
static char *sob(char *p);
|
||||
static char *son(char *p);
|
||||
@ -115,6 +106,7 @@ static void compress_log(char *log);
|
||||
static int sizefile(char *file);
|
||||
static int age_old_log(char *file);
|
||||
static pid_t get_pid(char *pid_file);
|
||||
static time_t parse8601(const char *s);
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
@ -155,11 +147,23 @@ static void do_entry(ent)
|
||||
if (verbose)
|
||||
printf("does not exist.\n");
|
||||
} else {
|
||||
if (ent->flags & CE_TRIMAT) {
|
||||
if (timenow < ent->trim_at
|
||||
|| difftime(timenow, ent->trim_at) >= 60*60) {
|
||||
if (verbose)
|
||||
printf("--> will trim at %s",
|
||||
ctime(&ent->trim_at));
|
||||
return;
|
||||
} else if (verbose && ent->hours <= 0) {
|
||||
printf("--> time is up\n");
|
||||
}
|
||||
}
|
||||
if (verbose && (ent->size > 0))
|
||||
printf("size (Kb): %d [%d] ", size, ent->size);
|
||||
if (verbose && (ent->hours > 0))
|
||||
printf(" age (hr): %d [%d] ", modtime, ent->hours);
|
||||
if (force || ((ent->size > 0) && (size >= ent->size)) ||
|
||||
(ent->hours <= 0 && (ent->flags & CE_TRIMAT)) ||
|
||||
((ent->hours > 0) && ((modtime >= ent->hours)
|
||||
|| (modtime < 0)))) {
|
||||
if (verbose)
|
||||
@ -177,7 +181,7 @@ static void do_entry(ent)
|
||||
} else {
|
||||
/* Only try to notify syslog if we are root */
|
||||
if (needroot)
|
||||
pid_file = PIDFILE;
|
||||
pid_file = _PATH_SYSLOGPID;
|
||||
else
|
||||
pid_file = NULL;
|
||||
}
|
||||
@ -230,7 +234,7 @@ static void PRS(argc,argv)
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
@ -341,14 +345,34 @@ static struct conf_entry *parse_file()
|
||||
else
|
||||
working->size = -1;
|
||||
|
||||
working->flags = 0;
|
||||
q = parse = missing_field(sob(++parse),errline);
|
||||
parse = son(parse);
|
||||
eol = !*parse;
|
||||
*parse = '\0';
|
||||
if (isdigit(*q))
|
||||
working->hours = atoi(q);
|
||||
else
|
||||
working->hours = -1;
|
||||
{
|
||||
char *ep;
|
||||
u_long ul;
|
||||
|
||||
ul = strtoul(q, &ep, 10);
|
||||
if (ep == q)
|
||||
working->hours = 0;
|
||||
else if (*ep == '*')
|
||||
working->hours = -1;
|
||||
else if (ul > INT_MAX)
|
||||
errx(1, "interval is too large:\n%s", errline);
|
||||
else
|
||||
working->hours = ul;
|
||||
|
||||
if (*ep != '\0' && *ep != '@' && *ep != '*')
|
||||
errx(1, "malformed interval/at:\n%s", errline);
|
||||
if (*ep == '@') {
|
||||
if ((working->trim_at = parse8601(ep + 1))
|
||||
== (time_t)-1)
|
||||
errx(1, "malformed at:\n%s", errline);
|
||||
working->flags |= CE_TRIMAT;
|
||||
}
|
||||
}
|
||||
|
||||
if (eol)
|
||||
q = NULL;
|
||||
@ -360,7 +384,6 @@ static struct conf_entry *parse_file()
|
||||
*parse = '\0';
|
||||
}
|
||||
|
||||
working->flags = 0;
|
||||
while (q && *q && !isspace(*q)) {
|
||||
if ((*q == 'Z') || (*q == 'z'))
|
||||
working->flags |= CE_COMPACT;
|
||||
@ -517,7 +540,7 @@ static void dotrim(log,pid_file,numdays,flags,perm,owner_uid,group_gid,sig)
|
||||
err(1, "can't add status message to log");
|
||||
}
|
||||
if (noaction)
|
||||
printf("chmod %o %s...",perm,log);
|
||||
printf("chmod %o %s...\n", perm, log);
|
||||
else
|
||||
(void) chmod(log,perm);
|
||||
|
||||
@ -583,8 +606,8 @@ static void compress_log(log)
|
||||
if (pid < 0)
|
||||
err(1, "fork");
|
||||
else if (!pid) {
|
||||
(void) execl(COMPRESS_PATH,COMPRESS_PROG,"-f",tmp,0);
|
||||
err(1, COMPRESS_PATH);
|
||||
(void) execl(_PATH_GZIP, _PATH_GZIP, "-f", tmp, 0);
|
||||
err(1, _PATH_GZIP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,20 +661,6 @@ static pid_t get_pid(pid_file)
|
||||
return pid;
|
||||
}
|
||||
|
||||
#ifndef OSF
|
||||
/* Duplicate a string using malloc */
|
||||
|
||||
char *strdup(strp)
|
||||
register char *strp;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL)
|
||||
abort();
|
||||
return(strcpy (cp, strp));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Skip Over Blanks */
|
||||
char *sob(p)
|
||||
register char *p;
|
||||
@ -669,3 +678,90 @@ char *son(p)
|
||||
p++;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a limited subset of ISO 8601.
|
||||
* The specific format is as follows:
|
||||
*
|
||||
* [CC[YY[MM[DD]]]][THH[MM[SS]]] (where `T' is the literal letter)
|
||||
*
|
||||
* We don't accept a timezone specification; missing fields (including
|
||||
* timezone) are defaulted to the current date but time zero.
|
||||
*/
|
||||
static time_t
|
||||
parse8601(const char *s)
|
||||
{
|
||||
char *t;
|
||||
struct tm tm, *tmp;
|
||||
u_long ul;
|
||||
|
||||
tmp = localtime(&timenow);
|
||||
tm = *tmp;
|
||||
|
||||
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||
|
||||
ul = strtoul(s, &t, 10);
|
||||
if (*t != '\0' && *t != 'T')
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Now t points either to the end of the string (if no time
|
||||
* was provided) or to the letter `T' which separates date
|
||||
* and time in ISO 8601. The pointer arithmetic is the same for
|
||||
* either case.
|
||||
*/
|
||||
switch (t - s) {
|
||||
case 8:
|
||||
tm.tm_year = ((ul / 1000000) - 19) * 100;
|
||||
ul = ul % 1000000;
|
||||
case 6:
|
||||
tm.tm_year = tm.tm_year - (tm.tm_year % 100);
|
||||
tm.tm_year += ul / 10000;
|
||||
ul = ul % 10000;
|
||||
case 4:
|
||||
tm.tm_mon = (ul / 100) - 1;
|
||||
ul = ul % 100;
|
||||
case 2:
|
||||
tm.tm_mday = ul;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if (tm.tm_year < 70 || tm.tm_mon < 0 || tm.tm_mon > 12
|
||||
|| tm.tm_mday < 1 || tm.tm_mday > 31)
|
||||
return -1;
|
||||
|
||||
if (*t != '\0') {
|
||||
s = ++t;
|
||||
ul = strtoul(s, &t, 10);
|
||||
if (*t != '\0' && !isspace(*t))
|
||||
return -1;
|
||||
|
||||
switch (t - s) {
|
||||
case 6:
|
||||
tm.tm_sec = ul % 100;
|
||||
ul /= 100;
|
||||
case 4:
|
||||
tm.tm_min = ul % 100;
|
||||
ul /= 100;
|
||||
case 2:
|
||||
tm.tm_hour = ul;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if (tm.tm_sec < 0 || tm.tm_sec > 60 || tm.tm_min < 0
|
||||
|| tm.tm_min > 59 || tm.tm_hour < 0 || tm.tm_hour > 23)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
|
||||
|
27
usr.sbin/newsyslog/pathnames.h
Normal file
27
usr.sbin/newsyslog/pathnames.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file contains changes from the Open Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Copyright 1988, 1989 by the Massachusetts Institute of Technology
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is
|
||||
hereby granted, provided that the above copyright notice
|
||||
appear in all copies and that both that copyright notice and
|
||||
this permission notice appear in supporting documentation,
|
||||
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||
used in advertising or publicity pertaining to distribution
|
||||
of the software without specific, written prior permission.
|
||||
M.I.T. and the M.I.T. S.I.P.B. make no representations about
|
||||
the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
|
||||
$Id$
|
||||
|
||||
*/
|
||||
|
||||
#define _PATH_CONF "/etc/newsyslog.conf"
|
||||
#define _PATH_SYSLOGPID _PATH_VARRUN "syslog.pid"
|
||||
#define _PATH_GZIP "/usr/bin/gzip"
|
Loading…
Reference in New Issue
Block a user