From e6d01471fe2a8eb8a15bb906d7c91c11805d1bef Mon Sep 17 00:00:00 2001 From: William Hubbs Date: Fri, 15 Jun 2018 12:23:50 -0500 Subject: [PATCH] start-stop-daemon: add ability to log stdout or stderr to processes --- NEWS.md | 9 +++++++ man/openrc-run.8 | 17 ++++++++++++++ man/start-stop-daemon.8 | 27 ++++++++++++++++++++- sh/start-stop-daemon.sh | 2 ++ src/rc/Makefile | 2 +- src/rc/start-stop-daemon.c | 48 ++++++++++++++++++++++++++++++++++---- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 328247da..13c62d6e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,15 @@ OpenRC NEWS This file will contain a list of notable changes for each release. Note the information in this file is in reverse order. +## OpenRC 0.37 + +start-stop-daemon now supports logging stdout and stderr of daemons to +processes instead of files. These processes are defined by the +output_logger and error_logger variables in standard service scripts, or +by the -3/--output-logger or -4/--error-logger switches if you use +start-stop-daemon directly. For more information on this, see the +start-stop-daemon man page. + ## OpenRC 0.36 In this release, the modules-load service has been combined into the diff --git a/man/openrc-run.8 b/man/openrc-run.8 index f0750406..03f8b680 100644 --- a/man/openrc-run.8 +++ b/man/openrc-run.8 @@ -173,6 +173,23 @@ variable is set. The same thing as .Pa output_log but for the standard error output. +.It Ar output_logger +This is a process which will be used to log the standard output from the +service. If you are starting this service with +.Xr start-stop-daemon 8 , +, you must set +.Pa command_background +to true. Keep in mind that this command must be executable as a shell +command inside the chroot if the +.Pa chroot +variable is set. Keep in mind also that this command works by accepting +the stdout of the service on stdin. +An example of a command that can be run this way is logger if you want +your service output to go to syslog. +.It Ar error_logger +The same thing as +.Pa output_logger +but for the standard error output. .It Ar directory .Xr start-stop-daemon 8 and diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8 index 706a12ed..ecadb958 100644 --- a/man/start-stop-daemon.8 +++ b/man/start-stop-daemon.8 @@ -131,9 +131,34 @@ Modifies the scheduling priority of the daemon. .It Fl 1 , -stdout Ar logfile Redirect the standard output of the process to logfile when started with .Fl background . -Must be an absolute pathname, but relative to the path optionally given with +The logfile Must be an absolute pathname, but relative to the path +optionally given with .Fl r , -chroot . The logfile can also be a named pipe. +.It Fl 2 , -stderr Ar logfile +Redirect the standard error of the process to logfile when started with +.Fl background . +The logfile must be an absolute pathname, but relative to the path +optionally given with +.Fl r , -chroot . +The logfile can also be a named pipe. +.It Fl 3 , -stdout-logger Ar cmd +Run cmd as a child process redirecting the standard output to the +standard input of cmd when started with +.Fl background . +Cmd must be an absolute pathname, but relative to the path optionally given with +.Fl r , -chroot . +This process must be prepared to accept input on stdin and be able to +log it or send it to another location. +.It Fl 4 , -stderr-logger Ar cmd +Run cmd as a child process and +Redirect the standard error of the process to the standard input of cmd +when started with +.Fl background . +Cmd must be an absolute pathname, but relative to the path optionally given with +.Fl r , -chroot . +This process must be prepared to accept input on stdin and be able to +log it or send it to another location. .It Fl w , -wait Ar milliseconds Wait .Ar milliseconds diff --git a/sh/start-stop-daemon.sh b/sh/start-stop-daemon.sh index 35c642c0..69666ff7 100644 --- a/sh/start-stop-daemon.sh +++ b/sh/start-stop-daemon.sh @@ -47,6 +47,8 @@ ssd_start() ${directory:+--chdir} $directory \ ${output_log+--stdout} $output_log \ ${error_log+--stderr} $error_log \ + ${output_logger+--stdout-logger} \"$output_logger\" \ + ${error_logger+--stderr-logger} \"$error_logger\" \ ${procname:+--name} $procname \ ${pidfile:+--pidfile} $pidfile \ ${command_user+--user} $command_user \ diff --git a/src/rc/Makefile b/src/rc/Makefile index 4b0983b5..b09c5058 100644 --- a/src/rc/Makefile +++ b/src/rc/Makefile @@ -158,7 +158,7 @@ rc-service: rc-service.o _usage.o rc-misc.o rc-update: rc-update.o _usage.o rc-misc.o ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} -start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o +start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index 0b3b423f..fceb3058 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -59,13 +59,14 @@ static struct pam_conv conv = { NULL, NULL}; #include "queue.h" #include "rc.h" #include "rc-misc.h" +#include "rc-pipes.h" #include "rc-schedules.h" #include "_usage.h" #include "helpers.h" const char *applet = NULL; const char *extraopts = NULL; -const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \ +const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \ getoptstring_COMMON; const struct option longopts[] = { { "ionice", 1, NULL, 'I'}, @@ -93,6 +94,8 @@ const struct option longopts[] = { { "exec", 1, NULL, 'x'}, { "stdout", 1, NULL, '1'}, { "stderr", 1, NULL, '2'}, + { "stdout-logger",1, NULL, '3'}, + { "stderr-logger",1, NULL, '4'}, { "progress", 0, NULL, 'P'}, longopts_COMMON }; @@ -122,6 +125,8 @@ const char * const longopts_help[] = { "Binary to start/stop", "Redirect stdout to file", "Redirect stderr to file", + "Redirect stdout to process", + "Redirect stderr to process", "Print dots each second while waiting", longopts_help_COMMON }; @@ -276,6 +281,8 @@ int main(int argc, char **argv) int tid = 0; char *redirect_stderr = NULL; char *redirect_stdout = NULL; + char *stderr_process = NULL; + char *stdout_process = NULL; int stdin_fd; int stdout_fd; int stderr_fd; @@ -500,6 +507,14 @@ int main(int argc, char **argv) redirect_stderr = optarg; break; + case '3': /* --stdout-logger "command to run for stdout logging" */ + stdout_process = optarg; + break; + + case '4': /* --stderr-logger "command to run for stderr logging" */ + stderr_process = optarg; + break; + case_RC_COMMON_GETOPT } @@ -551,6 +566,9 @@ int main(int argc, char **argv) if (redirect_stdout || redirect_stderr) eerrorx("%s: --stdout and --stderr are only relevant" " with --start", applet); + if (stdout_process || stderr_process) + eerrorx("%s: --stdout-logger and --stderr-logger are only relevant" + " with --start", applet); if (start_wait) ewarn("using --wait with --stop has no effect," " use --retry instead"); @@ -563,6 +581,15 @@ int main(int argc, char **argv) if ((redirect_stdout || redirect_stderr) && !background) eerrorx("%s: --stdout and --stderr are only relevant" " with --background", applet); + if ((stdout_process || stderr_process) && !background) + eerrorx("%s: --stdout-logger and --stderr-logger are only relevant" + " with --background", applet); + if (redirect_stdout && stdout_process) + eerrorx("%s: do not use --stdout and --stdout-logger together", + applet); + if (redirect_stderr && stderr_process) + eerrorx("%s: do not use --stderr and --stderr-logger together", + applet); } /* Expand ~ */ @@ -603,7 +630,6 @@ int main(int argc, char **argv) *exec_file ? exec_file : exec); free(exec_file); exit(EXIT_FAILURE); - } if (start && retry) ewarn("using --retry with --start has no effect," @@ -886,6 +912,12 @@ int main(int argc, char **argv) eerrorx("%s: unable to open the logfile" " for stdout `%s': %s", applet, redirect_stdout, strerror(errno)); + }else if (stdout_process) { + stdout_fd = rc_pipe_command(stdout_process); + if (stdout_fd == -1) + eerrorx("%s: unable to open the logging process" + " for stdout `%s': %s", + applet, stdout_process, strerror(errno)); } if (redirect_stderr) { if ((stderr_fd = open(redirect_stderr, @@ -894,13 +926,21 @@ int main(int argc, char **argv) eerrorx("%s: unable to open the logfile" " for stderr `%s': %s", applet, redirect_stderr, strerror(errno)); + }else if (stderr_process) { + stderr_fd = rc_pipe_command(stderr_process); + if (stderr_fd == -1) + eerrorx("%s: unable to open the logging process" + " for stderr `%s': %s", + applet, stderr_process, strerror(errno)); } if (background) dup2(stdin_fd, STDIN_FILENO); - if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET"))) + if (background || redirect_stdout || stdout_process + || rc_yesno(getenv("EINFO_QUIET"))) dup2(stdout_fd, STDOUT_FILENO); - if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET"))) + if (background || redirect_stderr || stderr_process + || rc_yesno(getenv("EINFO_QUIET"))) dup2(stderr_fd, STDERR_FILENO); for (i = getdtablesize() - 1; i >= 3; --i)