From 99a1b72a26e5238c75eb6e67ee78806c8e43251d Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Fri, 22 May 2026 12:00:22 +0100 Subject: [PATCH 1/3] Add -g to set group to run under. --- lumberjack | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lumberjack b/lumberjack index ba8c798..cf3f486 100755 --- a/lumberjack +++ b/lumberjack @@ -8,7 +8,7 @@ # Script details. NAME="${0##*/}" -VERSION="0.3.2" +VERSION="0.4.0" # Functions. @@ -87,6 +87,14 @@ display_help() { -f Request flushing of the log file to disk after every write. This may significantly reduce performance and result in a lot of disk writes. Best to let the kernel do appropriate buffering. + -g Set name of the group to run with. With this option, as soon as + $NAME starts it will re-exec itself to run as this group. + Log files created by $NAME will be owned by this group. The + default is to run as a primary group of any user given by '-u' + or the user that executed $NAME, which is usually root. + When combind with '-u', the group $NAME will run under is no + longer the primary group of that user but will be this group. + This option is only available to root. -h Display this help. -i Read input from the pipe/FIFO at , rather than stdin. If the pipe/FIFO does not exist, it will be created. Use '-o' @@ -355,6 +363,7 @@ PIPE_UMASK="066" PIPE_OWNER="" SYSLOG_FACILITY="user" RUNAS_USER="" +RUNAS_GROUP="" FLAGS=([flush]=0 [raw]=0 [compress]=0 [make-parents]=0 [created-fifo]=0 [timed-out]=0 [basedir-vanished]=0 [basedir-notdir]=0) # trap signals. @@ -392,6 +401,14 @@ while :; do shift continue ;; + -g) + # Set the group to run as. + (( UID != 0 )) && die "only root can use -g" + getent group "$2" >/dev/null 2>&1 || die "invalid group given for -g: $2" + RUNAS_GROUP="$2" + shift 2 + continue + ;; -h|-help|--help) # Show the help screen and exit. display_help @@ -551,12 +568,12 @@ TEMPLATE="$2" } # Apply user and setting. -[[ -n "$RUNAS_USER" ]] && { +[[ -n "$RUNAS_USER" ]] || [[ -n "$RUNAS_GROUP" ]] && { SETPRIV="$(command -v setpriv)" if [[ -n "$SETPRIV" ]]; then - exec "$SETPRIV" --keep-groups --reuid "$RUNAS_USER" --regid "$RUNAS_USER" -- "$0" "${ORIG_ARGS[@]}" "$BASEDIR" "$TEMPLATE" || die "failed to exec to change user" + exec "$SETPRIV" --keep-groups --reuid "${RUNAS_USER:-$(whoami)}" ${RUNAS_GROUP:+--regid "$RUNAS_GROUP"} -- "$0" "${ORIG_ARGS[@]}" "$BASEDIR" "$TEMPLATE" || die "failed to exec to change user/group" else - die "cannot exec to change user: setpriv not found" + die "cannot exec to change user/group: setpriv not found" fi } From 6f89e169c8605e716e9e7b665ad00bbb796de0a1 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Fri, 22 May 2026 12:10:14 +0100 Subject: [PATCH 2/3] Remove fifo before creating it. Remove fifo on SIGTERM. --- lumberjack | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lumberjack b/lumberjack index cf3f486..5cf11a5 100755 --- a/lumberjack +++ b/lumberjack @@ -297,6 +297,9 @@ sigterm_handler() { close_fd "$SITE" done disown -a + (( FLAGS[created-fifo] == 1 )) && { + rm -f "$INPUT" 2>/dev/null || syslog "warn" "failed to remove pipe/fifo: $INPUT" + } exit 0 } @@ -557,14 +560,13 @@ TEMPLATE="$2" # If input is to be a pipe/FIFO, create it if necessary. [[ -n "$INPUT" ]] && { - if [[ ! -e "$INPUT" ]]; then + [[ ! -e "$INPUT" ]] || [[ ! -p "$INPUT" ]] && { umask "$PIPE_UMASK" + rm -f "$INPUT" mkfifo "$INPUT" 2>/dev/null || die "failed to create pipe/FIFO: $INPUT" FLAGS[created-fifo]=1 [[ -n "$PIPE_OWNER" ]] && { chown "$PIPE_OWNER" "$INPUT" >/dev/null 2>&1 || die "failed to chown pipe/FIFO: $INPUT"; } - elif [[ ! -p "$INPUT" ]]; then - die "not a pipe/FIFO: $INPUT" - fi + } } # Apply user and setting. From ba8d3b3eb7d032a4709c9be417b3fe8906793e65 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Fri, 22 May 2026 12:17:34 +0100 Subject: [PATCH 3/3] When die()ing, write message to syslog. --- lumberjack | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lumberjack b/lumberjack index 5cf11a5..2b70b42 100755 --- a/lumberjack +++ b/lumberjack @@ -68,6 +68,7 @@ die() { # $1 The text of the error message to display on stderr. (( DEBUG == 1 )) && printf "%s: %s: %s\\n" "$(date "+%Y%m%d %H%M%S.%N")" "die" "$1" >>"$DEBUG_FILE" + syslog "err" "$1" printf "%s: %s\\n" "$NAME" "$1" >&2 exit 1 } @@ -231,7 +232,7 @@ open_fd() { # shellcheck disable=SC1083 if ! { exec {FDS["$1"]}>>"$2"; } 2>/dev/null; then (( FLAGS[${1}_open-fd-fail] == 0 )) && { - syslog "error" "failed to open log file for writing: $2" + syslog "err" "failed to open log file for writing: $2" FLAGS[${1}_open-fd-fail]=1 } return 1 @@ -613,7 +614,7 @@ while :; do } elif (( ERR != 0 )); then # Unhandled error - log the issue and continue. - syslog "error" "unhandled return code from 'read': $ERR" + syslog "err" "unhandled return code from 'read': $ERR" continue fi @@ -621,7 +622,7 @@ while :; do # Note: We won't make this directory ourselves - as it's the base directory it should exist on the system to start with. if [[ ! -e "$BASEDIR" ]]; then (( FLAGS[basedir-vanished] == 0 )) && { - syslog "error" "base directory has vanished" + syslog "err" "base directory has vanished" FLAGS[basedir-vanished]=1 } continue @@ -635,7 +636,7 @@ while :; do # Make sure the base path is a directory. if ! is_dir "$BASEDIR"; then (( FLAGS[basedir-notdir] == 0 )) && { - syslog "error" "base path is no longer a directory" + syslog "err" "base path is no longer a directory" FLAGS[basedir-notdir]=1 } continue @@ -695,7 +696,7 @@ while :; do rm -rf "${BASEDIR:?}/${LINKFILE_EXPANDED//\{\}/$SITE}" if ! ln -sfr "$FILENAME" "$BASEDIR/${LINKFILE_EXPANDED//\{\}/$SITE}"; then (( FLAGS[${SITE}_fix-link] == 0 )) && { - syslog "error" "failed to fix link: $BASEDIR/${LINKFILE_EXPANDED//\{\}/$SITE}" + syslog "err" "failed to fix link: $BASEDIR/${LINKFILE_EXPANDED//\{\}/$SITE}" FLAGS[${SITE}_fix-link]=1 } continue @@ -719,7 +720,7 @@ while :; do # If in raw mode, we need a placeholder for the FDS array element as LOG_VHOST would normally be unset. if (( FLAGS[raw] == 0 )); then [[ ! "$LOG_VHOST" ]] && { - syslog "error" "empty VirtualHost site identifier" + syslog "err" "empty VirtualHost site identifier" continue } else @@ -772,7 +773,7 @@ while :; do rm -rf "${BASEDIR:?}/${LINKFILE_EXPANDED//\{\}/$LOG_VHOST}" if ! ln -sfr "$FILENAME" "$BASEDIR/${LINKFILE_EXPANDED//\{\}/$LOG_VHOST}" 2>/dev/null; then (( FLAGS[${LOG_VHOST}_create-link] == 0 )) && { - syslog "error" "failed to create link: $BASEDIR/${LINKFILE_EXPANDED//\{\}/$LOG_VHOST}" + syslog "err" "failed to create link: $BASEDIR/${LINKFILE_EXPANDED//\{\}/$LOG_VHOST}" FLAGS[${LOG_VHOST}_create-link]=1 } continue