Add new modifier - "R", when it is specified the path to pid file

will be considered as a path to a binary or a shell script to be executed
after rotation has been completed instead of sending signal to the process
id in that file.

Sponsored by:	Sippy Software, Inc.
From the:	FreeBSD hacking lounge at BSDCan
This commit is contained in:
Maxim Sobolev 2011-05-14 03:00:55 +00:00
parent a072b80e7e
commit ea640d778b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=221873
2 changed files with 76 additions and 32 deletions

View File

@ -125,6 +125,7 @@ __FBSDID("$FreeBSD$");
/* process when trimming this file. */
#define CE_CREATE 0x0100 /* Create the log file if it does not exist. */
#define CE_NODUMP 0x0200 /* Set 'nodump' on newly created log file. */
#define CE_PID2CMD 0x0400 /* Replace PID file with a shell command.*/
#define MIN_PID 5 /* Don't touch pids lower than this */
#define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */
@ -154,7 +155,7 @@ const struct compress_types compress_type[COMPRESS_TYPES] = {
struct conf_entry {
STAILQ_ENTRY(conf_entry) cf_nextp;
char *log; /* Name of the log */
char *pid_file; /* PID file */
char *pid_cmd_file; /* PID or command file */
char *r_reason; /* The reason this file is being rotated */
int firstcreate; /* Creating log for the first time (-C). */
int rotate; /* Non-zero if this file should be rotated */
@ -178,7 +179,8 @@ struct sigwork_entry {
int sw_pidok; /* true if pid value is valid */
pid_t sw_pid; /* the process id from the PID file */
const char *sw_pidtype; /* "daemon" or "process group" */
char sw_fname[1]; /* file the PID was read from */
int run_cmd; /* run command or send PID to signal */
char sw_fname[1]; /* file the PID was read from or shell cmd */
};
struct zipwork_entry {
@ -384,9 +386,9 @@ init_entry(const char *fname, struct conf_entry *src_entry)
err(1, "strdup for %s", fname);
if (src_entry != NULL) {
tempwork->pid_file = NULL;
if (src_entry->pid_file)
tempwork->pid_file = strdup(src_entry->pid_file);
tempwork->pid_cmd_file = NULL;
if (src_entry->pid_cmd_file)
tempwork->pid_cmd_file = strdup(src_entry->pid_cmd_file);
tempwork->r_reason = NULL;
tempwork->firstcreate = 0;
tempwork->rotate = 0;
@ -406,7 +408,7 @@ init_entry(const char *fname, struct conf_entry *src_entry)
tempwork->def_cfg = src_entry->def_cfg;
} else {
/* Initialize as a "do-nothing" entry */
tempwork->pid_file = NULL;
tempwork->pid_cmd_file = NULL;
tempwork->r_reason = NULL;
tempwork->firstcreate = 0;
tempwork->rotate = 0;
@ -441,9 +443,9 @@ free_entry(struct conf_entry *ent)
ent->log = NULL;
}
if (ent->pid_file != NULL) {
free(ent->pid_file);
ent->pid_file = NULL;
if (ent->pid_cmd_file != NULL) {
free(ent->pid_cmd_file);
ent->pid_cmd_file = NULL;
}
if (ent->r_reason != NULL) {
@ -1291,6 +1293,9 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
case 'n':
working->flags |= CE_NOSIGNAL;
break;
case 'r':
working->flags |= CE_PID2CMD;
break;
case 'u':
working->flags |= CE_SIGNALGROUP;
break;
@ -1324,10 +1329,10 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
*parse = '\0';
}
working->pid_file = NULL;
working->pid_cmd_file = NULL;
if (q && *q) {
if (*q == '/')
working->pid_file = strdup(q);
working->pid_cmd_file = strdup(q);
else if (isdigit(*q))
goto got_sig;
else
@ -1364,16 +1369,16 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
if ((working->flags & CE_NOSIGNAL) == CE_NOSIGNAL) {
/*
* This config-entry specified 'n' for nosignal,
* see if it also specified an explicit pid_file.
* see if it also specified an explicit pid_cmd_file.
* This would be a pretty pointless combination.
*/
if (working->pid_file != NULL) {
if (working->pid_cmd_file != NULL) {
warnx("Ignoring '%s' because flag 'n' was specified in line:\n%s",
working->pid_file, errline);
free(working->pid_file);
working->pid_file = NULL;
working->pid_cmd_file, errline);
free(working->pid_cmd_file);
working->pid_cmd_file = NULL;
}
} else if (working->pid_file == NULL) {
} else if (working->pid_cmd_file == NULL) {
/*
* This entry did not specify the 'n' flag, which
* means it should signal syslogd unless it had
@ -1388,7 +1393,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
working->flags &= ~CE_SIGNALGROUP;
}
if (needroot)
working->pid_file = strdup(path_syslogpid);
working->pid_cmd_file = strdup(path_syslogpid);
}
/*
@ -1826,7 +1831,7 @@ do_rotate(const struct conf_entry *ent)
* multiple log files had to be rotated.
*/
swork = NULL;
if (ent->pid_file != NULL)
if (ent->pid_cmd_file != NULL)
swork = save_sigwork(ent);
if (ent->numlogs > 0 && ent->compress > COMPRESS_NONE) {
/*
@ -1845,6 +1850,7 @@ do_sigwork(struct sigwork_entry *swork)
{
struct sigwork_entry *nextsig;
int kres, secs;
char *tmp;
if (!(swork->sw_pidok) || swork->sw_pid == 0)
return; /* no work to do... */
@ -1887,6 +1893,24 @@ do_sigwork(struct sigwork_entry *swork)
return;
}
if (swork->run_cmd) {
asprintf(&tmp, "%s %d", swork->sw_fname, swork->sw_signum);
if (tmp == NULL) {
warn("can't allocate memory to run %s",
swork->sw_fname);
return;
}
if (verbose)
printf("Run command: %s\n", tmp);
kres = system(tmp);
if (kres) {
warnx("%s: returned non-zero exit code: %d",
tmp, kres);
}
free(tmp);
return;
}
kres = kill(swork->sw_pid, swork->sw_signum);
if (kres != 0) {
/*
@ -2016,7 +2040,7 @@ save_sigwork(const struct conf_entry *ent)
sprev = NULL;
ndiff = 1;
SLIST_FOREACH(stmp, &swhead, sw_nextp) {
ndiff = strcmp(ent->pid_file, stmp->sw_fname);
ndiff = strcmp(ent->pid_cmd_file, stmp->sw_fname);
if (ndiff > 0)
break;
if (ndiff == 0) {
@ -2032,11 +2056,18 @@ save_sigwork(const struct conf_entry *ent)
if (stmp != NULL && ndiff == 0)
return (stmp);
tmpsiz = sizeof(struct sigwork_entry) + strlen(ent->pid_file) + 1;
tmpsiz = sizeof(struct sigwork_entry) + strlen(ent->pid_cmd_file) + 1;
stmp = malloc(tmpsiz);
set_swpid(stmp, ent);
stmp->run_cmd = 0;
/* If this is a command to run we just set the flag and run command */
if (ent->flags & CE_PID2CMD) {
stmp->run_cmd = 1;
} else {
set_swpid(stmp, ent);
}
stmp->sw_signum = ent->sig;
strcpy(stmp->sw_fname, ent->pid_file);
strcpy(stmp->sw_fname, ent->pid_cmd_file);
if (sprev == NULL)
SLIST_INSERT_HEAD(&swhead, stmp, sw_nextp);
else
@ -2113,7 +2144,7 @@ set_swpid(struct sigwork_entry *swork, const struct conf_entry *ent)
swork->sw_pidtype = "process-group";
}
f = fopen(ent->pid_file, "r");
f = fopen(ent->pid_cmd_file, "r");
if (f == NULL) {
if (errno == ENOENT && enforcepid == 0) {
/*
@ -2124,9 +2155,9 @@ set_swpid(struct sigwork_entry *swork, const struct conf_entry *ent)
* files that the process would have been using.
*/
swork->sw_pidok = 1;
warnx("pid file doesn't exist: %s", ent->pid_file);
warnx("pid file doesn't exist: %s", ent->pid_cmd_file);
} else
warn("can't open pid file: %s", ent->pid_file);
warn("can't open pid file: %s", ent->pid_cmd_file);
return;
}
@ -2139,9 +2170,9 @@ set_swpid(struct sigwork_entry *swork, const struct conf_entry *ent)
*/
if (feof(f) && enforcepid == 0) {
swork->sw_pidok = 1;
warnx("pid file is empty: %s", ent->pid_file);
warnx("pid/cmd file is empty: %s", ent->pid_cmd_file);
} else
warn("can't read from pid file: %s", ent->pid_file);
warn("can't read from pid file: %s", ent->pid_cmd_file);
(void)fclose(f);
return;
}
@ -2154,10 +2185,10 @@ set_swpid(struct sigwork_entry *swork, const struct conf_entry *ent)
rval = strtol(linep, &endp, 10);
if (*endp != '\0' && !isspacech(*endp)) {
warnx("pid file does not start with a valid number: %s",
ent->pid_file);
ent->pid_cmd_file);
} else if (rval < minok || rval > maxok) {
warnx("bad value '%ld' for process number in %s",
rval, ent->pid_file);
rval, ent->pid_cmd_file);
if (verbose)
warnx("\t(expecting value between %ld and %ld)",
minok, maxok);

View File

@ -301,9 +301,16 @@ log file using
.It Cm N
indicates that there is no process which needs to be signaled
when this log file is rotated.
.It Cm R
if this flag is set the
.Xr newsyslog 8
will run shell command defined in
.Ar path_to_pid_cmd_file
after rotation instead of trying to send signal to a process id
stored in the file.
.It Cm U
indicates that the file specified by
.Ar path_to_pid_file
.Ar path_to_pid_cmd_file
will contain the ID for a process group instead of a process.
This option also requires that the first line in that file
be a negative value to distinguish it from a process ID.
@ -319,7 +326,7 @@ can be used as a placeholder to create a
.Ar flags
field when you need to specify any of the following fields.
.El
.It Ar path_to_pid_file
.It Ar path_to_pid_cmd_file
This optional field specifies the file name containing a daemon's
process ID or to find a group process ID if the
.Cm U
@ -340,6 +347,12 @@ switch.
This field must start with
.Ql /
in order to be recognized properly.
When used with the
.Cm R
flag, the file is treated as a path to a binary to be executed
by the
.Xr newsyslog 8
after rotation instead of sending the signal out.
.It Ar signal_number
This optional field specifies the signal number that will be sent
to the daemon process (or to all processes in a process group, if the