add support for writing the pid of the daemon program to a pid file so
that daemon can be used w/ rc.subr and ports can use the additional functionality, such as keeping the ldap daemon up and running, and have the proper program to signal to exit.. PR: bin/181341 Submitted by: feld Approved by: re (glebius)
This commit is contained in:
parent
bd8277b4b2
commit
32b17786bd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=255521
@ -26,7 +26,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 4, 2012
|
.Dd September 13, 2013
|
||||||
.Dt DAEMON 8
|
.Dt DAEMON 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -35,7 +35,8 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl cfr
|
.Op Fl cfr
|
||||||
.Op Fl p Ar pidfile
|
.Op Fl p Ar child_pidfile
|
||||||
|
.Op Fl P Ar supervisor_pidfile
|
||||||
.Op Fl u Ar user
|
.Op Fl u Ar user
|
||||||
.Ar command arguments ...
|
.Ar command arguments ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -53,19 +54,39 @@ Change the current working directory to the root
|
|||||||
.It Fl f
|
.It Fl f
|
||||||
Redirect standard input, standard output and standard error to
|
Redirect standard input, standard output and standard error to
|
||||||
.Pa /dev/null .
|
.Pa /dev/null .
|
||||||
.It Fl p Ar file
|
.It Fl p Ar child_pidfile
|
||||||
Write the ID of the created process into the
|
Write the ID of the created process into the
|
||||||
.Ar file
|
.Ar child_pidfile
|
||||||
using the
|
using the
|
||||||
.Xr pidfile 3
|
.Xr pidfile 3
|
||||||
functionality.
|
functionality.
|
||||||
The program is executed in a spawned child process while the
|
The program is executed in a spawned child process while the
|
||||||
.Nm
|
.Nm
|
||||||
waits until it terminates to keep the
|
waits until it terminates to keep the
|
||||||
.Ar file
|
.Ar child_pidfile
|
||||||
locked and removes it after the process exits.
|
locked and removes it after the process exits.
|
||||||
The
|
The
|
||||||
.Ar file
|
.Ar child_pidfile
|
||||||
|
owner is the user who runs the
|
||||||
|
.Nm
|
||||||
|
regardless of whether the
|
||||||
|
.Fl u
|
||||||
|
option is used or not.
|
||||||
|
.It Fl P Ar supervisor_pidfile
|
||||||
|
Write the ID of the
|
||||||
|
.Nm
|
||||||
|
process into the
|
||||||
|
.Ar supervisor_pidfile
|
||||||
|
using the
|
||||||
|
.Xr pidfile 3
|
||||||
|
functionality.
|
||||||
|
The program is executed in a spawned child process while the
|
||||||
|
.Nm
|
||||||
|
waits until it terminates to keep the
|
||||||
|
.Ar supervisor_pidfile
|
||||||
|
locked and removes it after the process exits.
|
||||||
|
The
|
||||||
|
.Ar supervisor_pidfile
|
||||||
owner is the user who runs the
|
owner is the user who runs the
|
||||||
.Nm
|
.Nm
|
||||||
regardless of whether the
|
regardless of whether the
|
||||||
@ -79,27 +100,46 @@ Requires adequate superuser privileges.
|
|||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
If the
|
If the
|
||||||
.Fl p
|
.Fl p ,
|
||||||
|
.Fl P
|
||||||
or
|
or
|
||||||
.Fl r
|
.Fl r
|
||||||
option is specified the program is executed in a spawned child process.
|
option is specified the program is executed in a spawned child process.
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
waits until it terminates to keep the pid file locked and removes it
|
waits until it terminates to keep the pid file(s) locked and removes them
|
||||||
after the process exits or restarts the program.
|
after the process exits or restarts the program.
|
||||||
In this case if the monitoring
|
In this case if the monitoring
|
||||||
.Nm
|
.Nm
|
||||||
receives software termination signal (SIGTERM) it forwards it to the
|
receives software termination signal (SIGTERM) it forwards it to the
|
||||||
spawned process.
|
spawned process.
|
||||||
Normally it will cause the child to exit followed by the termination
|
Normally it will cause the child to exit, remove the pidfile(s)
|
||||||
of the supervising process after removing the pidfile.
|
and then terminate.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fl P
|
||||||
|
option is useful combined with the
|
||||||
|
.Fl r
|
||||||
|
option as
|
||||||
|
.Ar supervisor_pidfile
|
||||||
|
contains the ID of the supervisor
|
||||||
|
not the child. This is especially important if you use
|
||||||
|
.Fl r
|
||||||
|
in an rc script as the
|
||||||
|
.Fl p
|
||||||
|
option will give you the child's ID to signal when you attempt to
|
||||||
|
stop the service, causing
|
||||||
|
.Nm
|
||||||
|
to restart the child.
|
||||||
.Sh EXIT STATUS
|
.Sh EXIT STATUS
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
utility exits 1 if an error is returned by the
|
utility exits 1 if an error is returned by the
|
||||||
.Xr daemon 3
|
.Xr daemon 3
|
||||||
library routine, 2 if the
|
library routine, 2 if
|
||||||
.Ar pidfile
|
.Ar child_pidfile
|
||||||
|
or
|
||||||
|
.Ar supervisor_pidfile
|
||||||
is requested, but cannot be opened, 3 if process is already running (pidfile
|
is requested, but cannot be opened, 3 if process is already running (pidfile
|
||||||
exists and is locked),
|
exists and is locked),
|
||||||
otherwise 0.
|
otherwise 0.
|
||||||
|
@ -53,16 +53,17 @@ static void usage(void);
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct pidfh *pfh = NULL;
|
struct pidfh *ppfh, *pfh;
|
||||||
sigset_t mask, oldmask;
|
sigset_t mask, oldmask;
|
||||||
int ch, nochdir, noclose, restart;
|
int ch, nochdir, noclose, restart;
|
||||||
const char *pidfile, *user;
|
const char *pidfile, *ppidfile, *user;
|
||||||
pid_t otherpid, pid;
|
pid_t otherpid, pid;
|
||||||
|
|
||||||
nochdir = noclose = 1;
|
nochdir = noclose = 1;
|
||||||
restart = 0;
|
restart = 0;
|
||||||
pidfile = user = NULL;
|
ppfh = pfh = NULL;
|
||||||
while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
|
ppidfile = pidfile = user = NULL;
|
||||||
|
while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
nochdir = 0;
|
nochdir = 0;
|
||||||
@ -73,6 +74,9 @@ main(int argc, char *argv[])
|
|||||||
case 'p':
|
case 'p':
|
||||||
pidfile = optarg;
|
pidfile = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
ppidfile = optarg;
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
restart = 1;
|
restart = 1;
|
||||||
break;
|
break;
|
||||||
@ -89,7 +93,7 @@ main(int argc, char *argv[])
|
|||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
pfh = NULL;
|
ppfh = pfh = NULL;
|
||||||
/*
|
/*
|
||||||
* Try to open the pidfile before calling daemon(3),
|
* Try to open the pidfile before calling daemon(3),
|
||||||
* to be able to report the error intelligently
|
* to be able to report the error intelligently
|
||||||
@ -104,6 +108,18 @@ main(int argc, char *argv[])
|
|||||||
err(2, "pidfile ``%s''", pidfile);
|
err(2, "pidfile ``%s''", pidfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do same for actual daemon process */
|
||||||
|
if (ppidfile != NULL) {
|
||||||
|
ppfh = pidfile_open(ppidfile, 0600, &otherpid);
|
||||||
|
if (ppfh == NULL) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
errx(3, "process already running, pid: %d",
|
||||||
|
otherpid);
|
||||||
|
}
|
||||||
|
err(2, "ppidfile ``%s''", ppidfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (daemon(nochdir, noclose) == -1)
|
if (daemon(nochdir, noclose) == -1)
|
||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
@ -176,12 +192,17 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
err(1, "%s", argv[0]);
|
err(1, "%s", argv[0]);
|
||||||
}
|
}
|
||||||
|
/* write out parent pidfile if needed */
|
||||||
|
if (ppidfile != NULL)
|
||||||
|
pidfile_write(ppfh);
|
||||||
|
|
||||||
setproctitle("%s[%d]", argv[0], pid);
|
setproctitle("%s[%d]", argv[0], pid);
|
||||||
if (wait_child(pid, &mask) == 0 && restart) {
|
if (wait_child(pid, &mask) == 0 && restart) {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
pidfile_remove(pfh);
|
pidfile_remove(pfh);
|
||||||
|
pidfile_remove(ppfh);
|
||||||
exit(0); /* Exit status does not matter. */
|
exit(0); /* Exit status does not matter. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +261,7 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
(void)fprintf(stderr,
|
(void)fprintf(stderr,
|
||||||
"usage: daemon [-cfr] [-p pidfile] [-u user] command "
|
"usage: daemon [-cfr] [-p child_pidfile] [-P supervisor_pidfile] "
|
||||||
"arguments ...\n");
|
"[-u user]\n command arguments ...\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user