civodul pushed a commit to branch main in repository shepherd. commit d13739be17bc64aef72cafcd3bbdf9f9c59ee29e Author: Ludovic Courtès <l...@gnu.org> AuthorDate: Wed Feb 19 15:36:30 2025 +0100
shepherd: Add ‘--syslog’ option. * modules/shepherd.scm (main): Add ‘--syslog’ option. Define ‘syslog-requested?’ and honor it. * doc/shepherd.texi (Invoking shepherd): Document it. * tests/services/system-log-self.sh: New file. * Makefile.am (TESTS): Add it. * NEWS: Update. --- Makefile.am | 1 + NEWS | 9 +++++ doc/shepherd.texi | 8 +++- modules/shepherd.scm | 16 +++++++- tests/services/system-log-self.sh | 78 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index aa2edd9..3205729 100644 --- a/Makefile.am +++ b/Makefile.am @@ -298,6 +298,7 @@ TESTS = \ tests/services/log-rotation-internal.scm \ tests/services/system-log.sh \ tests/services/system-log-internal.scm \ + tests/services/system-log-self.sh \ tests/services/transient.sh TEST_EXTENSIONS = .sh .scm diff --git a/NEWS b/NEWS index e688533..8f584c7 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,15 @@ Copyright © 2013-2014, 2016, 2018-2020, 2022-2025 Ludovic Courtès <l...@gnu.or Please send Shepherd bug reports to bug-g...@gnu.org. +* Changes in 1.0.3 + +*** New ‘--syslog’ option of ‘shepherd’ + +This option forces shepherd to write its output to syslog (the /dev/log socket +by default). This is already the case when shepherd runs as root so this +option only makes sense for non-root shepherd instances, and its primary +purpose is testing. + * Changes in 1.0.2 ** ‘daemonize’ action preserves replacement bindings for ‘sleep’ etc. diff --git a/doc/shepherd.texi b/doc/shepherd.texi index 642d065..0c7d752 100644 --- a/doc/shepherd.texi +++ b/doc/shepherd.texi @@ -371,10 +371,14 @@ For unprivileged users, the default log file is @file{$XDG_STATE_HOME/shepherd/shepherd.log} with @file{$XDG_STATE_HOME} defaulting to @file{$HOME/.local/state}. +@item --syslog[=@var{file}] @cindex syslog +Force logging to @var{file} (@file{/dev/log} by default), a @dfn{syslog} +socket (@pxref{Overview of Syslog,,, libc, The GNU C Library Reference +Manual}). + When running as root, the default behavior is to connect to -@file{/dev/log}, the @dfn{syslog} socket (@pxref{Overview of Syslog,,, -libc, The GNU C Library Reference Manual}). A syslog daemon, +@file{/dev/log}. A syslog daemon, @command{syslogd}, is expected to read messages from there (@pxref{syslogd invocation, syslogd,, inetutils, GNU Inetutils}). diff --git a/modules/shepherd.scm b/modules/shepherd.scm index 1a860e9..eea306d 100644 --- a/modules/shepherd.scm +++ b/modules/shepherd.scm @@ -411,6 +411,7 @@ fork in the child process." (initialize-cli) (let ((config-file #f) + (syslog-requested? #f) (socket-file default-socket-file) (pid-file #f) (secure #t) @@ -472,14 +473,25 @@ fork in the child process." #:action (lambda (file) (set! socket-file (and (not (string=? file "-")) - file))))) + file)))) + (option + #:long-name "syslog" + #:takes-argument? #t #:argument-is-optional? #t + #:argument-name (l10n "FILE") + #:description + (l10n "log to the system log (syslog) at FILE or /dev/log") + #:action (lambda (file) + (when file + (system-log-file file)) + (set! syslog-requested? #t)))) ;; We do this early so that we can abort early if necessary. (and socket-file (verify-dir (dirname socket-file) #:secure? secure)) (define syslog? ;; Is shepherd logging to /dev/log? - (and (not logfile) (= 1 (getpid)))) + (or syslog-requested? + (and (not logfile) (= 1 (getpid))))) ;; By default, enable detailed deprecation warnings. (unless (getenv "GUILE_WARN_DEPRECATED") diff --git a/tests/services/system-log-self.sh b/tests/services/system-log-self.sh new file mode 100755 index 0000000..76062b9 --- /dev/null +++ b/tests/services/system-log-self.sh @@ -0,0 +1,78 @@ +# GNU Shepherd --- Test system logging service for shepherd itself. +# Copyright © 2025 Ludovic Courtès <l...@gnu.org> +# +# This file is part of the GNU Shepherd. +# +# The GNU Shepherd is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# The GNU Shepherd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the GNU Shepherd. If not, see <http://www.gnu.org/licenses/>. + +shepherd --version +herd --version + +socket="t-socket-$$" +conf="t-conf-$$" +pid="t-pid-$$" +syslog_file="$PWD/t-syslog-$$" +syslog_socket="$PWD/t-syslog-socket-$$" + +herd="herd -s $socket" + +trap "cat $syslog_file || true; + rm -f $socket $conf $syslog_socket $syslogfile; + test -f $pid && kill \`cat $pid\` || true; rm -f $pid" EXIT + +cat > "$conf" <<EOF +(use-modules (shepherd service system-log) + (shepherd endpoints)) + +(define %endpoints + (list (endpoint (make-socket-address AF_UNIX "$syslog_socket") + #:style SOCK_DGRAM))) + +(register-services + (list (system-log-service %endpoints + #:message-destination (const '("$syslog_file")) + #:kernel-log-file #f) + (service + '(logger) + #:requirement '(syslogd) + #:start (make-forkexec-constructor + '("$SHELL" "-c" "while true; do echo logging from \$\$; sleep 0.2; done")) + #:stop (make-kill-destructor) + #:respawn? #f))) +EOF + + +rm -f "$pid" + +# Log to syslog, with syslog implemented by shepherd itself. +shepherd -I -s "$socket" -c "$conf" --syslog="$syslog_socket" --pid="$pid" & + +# Wait till it's ready. +until test -f "$pid" ; do sleep 0.3 ; done + +$herd start system-log +$herd status system-log | grep running +grep "system-log started" "$syslog_file" + +$herd start logger +grep "logger started" "$syslog_file" + +logger_pid="$($herd status logger | grep "PID: [0-9]\+" \ + | sed -e's/^.* \([0-9]\+\)$/\1/g')" +kill -0 "$logger_pid" + +until grep "logging from $logger_pid" "$syslog_file"; do sleep 0.2; done + +$herd stop root +grep "Exiting" "$syslog_file"