Add logger(1) support for daemons that are logging to stdout/stderr (mostly from
authorajacoutot <ajacoutot@openbsd.org>
Sat, 27 Feb 2021 09:28:04 +0000 (09:28 +0000)
committerajacoutot <ajacoutot@openbsd.org>
Sat, 27 Feb 2021 09:28:04 +0000 (09:28 +0000)
the go ecosystem).
Properly handle failing daemon startup now that we have pipefail.

To take advantage of this new feature, just add foo_logger=facility to the
daemon rc.d(8) script or in rc.conf.local(8) or use rcctl:
rcctl set foo logger daemon.info

tweak for checking flags in rcctl(8) from martijn@
"this looks pretty good" deraadt@
ok sthen@

etc/rc.d/rc.subr
share/man/man8/rc.d.8
share/man/man8/rc.subr.8
usr.sbin/rcctl/rcctl.8
usr.sbin/rcctl/rcctl.sh

index 0268e0a..5bd7ba3 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: rc.subr,v 1.135 2020/07/12 14:35:38 jca Exp $
+#      $OpenBSD: rc.subr,v 1.136 2021/02/27 09:28:04 ajacoutot Exp $
 #
-# Copyright (c) 2010, 2011, 2014-2017 Antoine Jacoutot <ajacoutot@openbsd.org>
+# Copyright (c) 2010, 2011, 2014-2021 Antoine Jacoutot <ajacoutot@openbsd.org>
 # Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
 # Copyright (c) 2010, 2011, 2014 Robert Nagy <robert@openbsd.org>
 #
@@ -49,6 +49,7 @@ _rc_write_runfile() {
                cat >${_RC_RUNFILE} <<EOF
 daemon_class=${daemon_class}
 daemon_flags=${daemon_flags}
+daemon_logger=${daemon_logger}
 daemon_rtable=${daemon_rtable}
 daemon_timeout=${daemon_timeout}
 daemon_user=${daemon_user}
@@ -149,7 +150,7 @@ _rc_parse_conf() {
                while IFS='     ' read -r _l; do
                        [[ $_l == [!#=]*=* ]] || continue
                        _key=${_l%%*([[:blank:]])=*}
-                       [[ $_key == *_@(flags|rtable|timeout|user) ]] ||
+                       [[ $_key == *_@(flags|logger|rtable|timeout|user) ]] ||
                                [[ " ${_allowed_keys[*]} " == *" $_key "* ]] ||
                                continue
                        [[ $_key == "" ]] && continue
@@ -170,7 +171,8 @@ _rc_parse_conf() {
 [ -n "${FUNCS_ONLY}" ] && return
 
 rc_start() {
-       ${rcexec} "${daemon} ${daemon_flags}"
+       ${rcexec} "${daemon_logger:+set -o pipefail; }${daemon} ${daemon_flags}${daemon_logger:+ 2>&1 |
+               logger -ip ${daemon_logger} -t ${_name}}"
 }
 
 rc_check() {
@@ -288,6 +290,7 @@ _RC_RUNFILE=${_RC_RUNDIR}/${_name}
 _rc_do _rc_parse_conf
 
 eval _rcflags=\${${_name}_flags}
+eval _rclogger=\${${_name}_logger}
 eval _rcrtable=\${${_name}_rtable}
 eval _rctimeout=\${${_name}_timeout}
 eval _rcuser=\${${_name}_user}
@@ -304,6 +307,7 @@ getcap -f /etc/login.conf ${_name} 1>/dev/null 2>&1 && daemon_class=${_name} ||
        unset _rcflags
 
 [ -n "${_rcflags}" ] && daemon_flags=${_rcflags}
+[ -n "${_rclogger}" ] && daemon_logger=${_rclogger}
 [ -n "${_rcrtable}" ] && daemon_rtable=${_rcrtable}
 [ -n "${_rctimeout}" ] && daemon_timeout=${_rctimeout}
 [ -n "${_rcuser}" ] && daemon_user=${_rcuser}
@@ -315,7 +319,7 @@ if [ -n "${_RC_DEBUG}" ]; then
 fi
 
 readonly daemon_class
-unset _rcflags _rcrtable _rctimeout _rcuser
+unset _rcflags _rclogger _rcrtable _rctimeout _rcuser
 # the shell will strip the quotes from daemon_flags when starting a daemon;
 # make sure pexp matches the process (i.e. doesn't include the quotes)
 pexp="$(eval echo ${daemon}${daemon_flags:+ ${daemon_flags}})"
index e0af340..95f5672 100644 (file)
@@ -1,5 +1,6 @@
-.\"    $OpenBSD: rc.d.8,v 1.35 2019/08/27 20:05:02 awolk Exp $
+.\"    $OpenBSD: rc.d.8,v 1.36 2021/02/27 09:28:05 ajacoutot Exp $
 .\"
+.\" Copyright (c) 2021 Antoine Jacoutot
 .\" Copyright (c) 2011 Robert Nagy, Antoine Jacoutot, Ingo Schwarze
 .\" All rights reserved.
 .\"
@@ -24,7 +25,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: August 27 2019 $
+.Dd $Mdocdate: February 27 2021 $
 .Dt RC.D 8
 .Os
 .Sh NAME
@@ -110,6 +111,10 @@ is set to
 .Dq NO ,
 it will prevent the daemon from starting even when listed in
 .Va pkg_scripts .
+.It Ar daemon Ns _logger
+Redirect standard output and error to
+.Xr logger 1
+using the configured priority (e.g. "daemon.info").
 .It Ar daemon Ns _rtable
 Routing table to run the daemon under, using
 .Xr route 8 .
index af7bd55..27f54be 100644 (file)
@@ -1,5 +1,6 @@
-.\"    $OpenBSD: rc.subr.8,v 1.37 2020/02/21 00:47:21 kn Exp $
+.\"    $OpenBSD: rc.subr.8,v 1.38 2021/02/27 09:28:05 ajacoutot Exp $
 .\"
+.\" Copyright (c) 2021 Antoine Jacoutot
 .\" Copyright (c) 2011 Robert Nagy, Antoine Jacoutot, Ingo Schwarze
 .\" All rights reserved.
 .\"
@@ -24,7 +25,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: February 21 2020 $
+.Dd $Mdocdate: February 27 2021 $
 .Dt RC.SUBR 8
 .Os
 .Sh NAME
@@ -247,6 +248,10 @@ If no such login class exists then
 will be used.
 .It Va daemon_flags
 Arguments to call the daemon with.
+.It Ar daemon Ns _logger
+Redirect standard output and error to
+.Xr logger 1
+using the configured priority (e.g. "daemon.info").
 .It Va daemon_rtable
 Routing table to run the daemon under, using
 .Xr route 8 .
@@ -333,6 +338,7 @@ Global defaults are provided by
 .Bd -literal -offset indent
 daemon_class=daemon
 daemon_flags=
+daemon_logger=
 daemon_rtable=0
 daemon_timeout=30
 daemon_user=root
@@ -352,6 +358,7 @@ site-specific values provided in
 .Xr rc.conf.local 8
 for
 .Va daemon_flags ,
+.Va daemon_logger ,
 .Va daemon_rtable ,
 .Va daemon_timeout ,
 and
index 9f7a90e..c6ed8b9 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: rcctl.8,v 1.35 2018/09/20 12:24:14 solene Exp $
+.\"    $OpenBSD: rcctl.8,v 1.36 2021/02/27 09:28:04 ajacoutot Exp $
 .\"
 .\" Copyright (c) 2014 Antoine Jacoutot <ajacoutot@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 20 2018 $
+.Dd $Mdocdate: February 27 2021 $
 .Dt RCCTL 8
 .Os
 .Sh NAME
@@ -58,6 +58,7 @@ The following commands are available
 can be one of
 .Cm class ,
 .Cm flags ,
+.Cm logger ,
 .Cm status ,
 .Cm timeout
 or
@@ -198,6 +199,7 @@ flags:
 # rcctl get apmd
 apmd_class=daemon
 apmd_flags=-A
+apmd_logger=
 apmd_rtable=0
 apmd_timeout=30
 apmd_user=root
index 954f328..699737f 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/ksh
 #
-# $OpenBSD: rcctl.sh,v 1.109 2021/02/18 06:17:35 ajacoutot Exp $
+# $OpenBSD: rcctl.sh,v 1.110 2021/02/27 09:28:04 ajacoutot Exp $
 #
-# Copyright (c) 2014, 2015 Antoine Jacoutot <ajacoutot@openbsd.org>
+# Copyright (c) 2014, 2015-2021 Antoine Jacoutot <ajacoutot@openbsd.org>
 # Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
 #
 # Permission to use, copy, modify, and distribute this software for any
@@ -251,7 +251,8 @@ svc_get()
        [ -n "${_svc}" ] || return
 
        local _status=0 _val _var=$2
-       local daemon_class daemon_flags daemon_rtable daemon_timeout daemon_user
+       local daemon_class daemon_flags daemon_logger daemon_rtable
+       local daemon_timeout daemon_user
 
        if svc_is_special ${_svc}; then
                daemon_flags="$(eval echo \${${_svc}})"
@@ -277,6 +278,12 @@ svc_get()
                                [ -z "${daemon_flags}" ] && \
                                        daemon_flags="$(svc_getdef ${_svc} flags)"
                        fi
+                       if [ -z "${_var}" -o "${_var}" = "logger" ]; then
+                               [ -z "${daemon_logger}" ] && \
+                                       daemon_logger="$(eval echo \"\${${_svc}_logger}\")"
+                               [ -z "${daemon_logger}" ] && \
+                                       daemon_logger="$(svc_getdef ${_svc} logger)"
+                       fi
                        if [ -z "${_var}" -o "${_var}" = "rtable" ]; then
                                [ -z "${daemon_rtable}" ] && \
                                        daemon_rtable="$(eval echo \"\${${_svc}_rtable}\")"
@@ -311,6 +318,7 @@ svc_get()
                else
                        echo "${_svc}_class=${daemon_class}"
                        echo "${_svc}_flags=${daemon_flags}"
+                       echo "${_svc}_logger=${daemon_logger}"
                        echo "${_svc}_rtable=${daemon_rtable}"
                        echo "${_svc}_timeout=${daemon_timeout}"
                        echo "${_svc}_user=${daemon_user}"
@@ -326,7 +334,8 @@ svc_getdef()
        [ -n "${_svc}" ] || return
 
        local _status=0 _val _var=$2
-       local daemon_class daemon_flags daemon_rtable daemon_timeout daemon_user
+       local daemon_class daemon_flags daemon_logger daemon_rtable
+       local daemon_timeout daemon_user
 
        if svc_is_special ${_svc}; then
                # unconditionally parse: we always output flags and/or status
@@ -367,6 +376,7 @@ svc_getdef()
                else
                        echo "${_svc}_class=${daemon_class}"
                        echo "${_svc}_flags=${daemon_flags}"
+                       echo "${_svc}_logger=${daemon_logger}"
                        echo "${_svc}_rtable=${daemon_rtable}"
                        echo "${_svc}_timeout=${daemon_timeout}"
                        echo "${_svc}_user=${daemon_user}"
@@ -386,7 +396,7 @@ svc_rm()
                ( svc_getdef ${_svc} status ) && \
                        echo "${_svc}=NO" >>${_TMP_RCCONF}
        else
-               grep -Ev "^${_svc}_(flags|rtable|timeout|user).*=" \
+               grep -Ev "^${_svc}_(flags|logger|rtable|timeout|user).*=" \
                        /etc/rc.conf.local >${_TMP_RCCONF}
                ( svc_getdef ${_svc} status ) && \
                        echo "${_svc}_flags=NO" >>${_TMP_RCCONF}
@@ -439,6 +449,10 @@ svc_set()
        fi
 
        if [ -n "${_args}" ]; then
+               if [ "${_var}" = "logger" ]; then
+                       logger -p "${_args}" </dev/null >/dev/null 2>&1 ||
+                               rcctl_err "unknown priority name: \"${_args}\""
+               fi
                if [ "${_var}" = "rtable" ]; then
                        [[ ${_args} != +([[:digit:]]) || ${_args} -lt 0 ]] && \
                                rcctl_err "\"${_args}\" is not an integer"
@@ -518,13 +532,13 @@ case ${action} in
                        rcctl_err "service ${svc} does not exist" 2
                if [ -n "${var}" ]; then
                        [ "${svc}" = "all" ] && usage
-                       [[ ${var} != @(class|flags|status|rtable|timeout|user) ]] && usage
+                       [[ ${var} != @(class|flags|logger|rtable|status|timeout|user) ]] && usage
                        if svc_is_meta ${svc}; then
                                [ "${var}" != "status" ] && \
                                        rcctl_err "/etc/rc.d/${svc} is a meta script, cannot \"${action} ${var}\""
                        fi
                        if svc_is_special ${svc}; then
-                               [[ ${var} == @(class|rtable|timeout|user) ]] && \
+                               [[ ${var} == @(class|logger|rtable|timeout|user) ]] && \
                                        rcctl_err "\"${svc}\" is a special variable, cannot \"${action} ${var}\""
                        fi
                fi
@@ -540,7 +554,7 @@ case ${action} in
                        svc_is_avail ${svc} || \
                                rcctl_err "service ${svc} does not exist" 2
                fi
-               [[ ${var} != @(class|flags|rtable|status|timeout|user) ]] && usage
+               [[ ${var} != @(class|flags|logger|rtable|status|timeout|user) ]] && usage
                svc_is_meta ${svc} && [ "${var}" != "status" ] && \
                        rcctl_err "/etc/rc.d/${svc} is a meta script, cannot \"${action} ${var}\""
                [[ ${var} = flags && ${args} = NO ]] && \