[PATCH] dracut-logger: logging facility module for build- and boot-time

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



It's dash compatible to be used also at boot-time. For now it's included
by dracut-functions and replaces functions: dinfo(), dwarning() and
derror(). New options are introduced: -L|--stdlog, and -q|--quiet to
control stderr verbosity. Logging to file or syslog may be controlled by
options set in config file.

Note that code is not adjusted to the meaning of the new logging
functions, yet.

Doxygen formatted documentation (as a proposal, by the way) is included
in dracut-logger.
---
 dracut           |   22 ++++-
 dracut-functions |   30 +-----
 dracut-logger    |  266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dracut.conf      |    4 +
 4 files changed, 295 insertions(+), 27 deletions(-)
 create mode 100755 dracut-logger

diff --git a/dracut b/dracut
index 4c3394c..f60b854 100755
--- a/dracut
+++ b/dracut
@@ -59,7 +59,16 @@ Creates initial ramdisk images for preloading modules
   --nolvmconf           Do not include local /etc/lvm/lvm.conf
   -h, --help            This message
   --debug               Output debug information of the build process
-  -v, --verbose         Verbose output during the build process
+  -L, --stdlog [0-6]    Specify logging level (to standard error)
+                         0 - suppress any messages
+                         1 - only fatal errors
+                         2 - all errors
+                         3 - warnings
+                         4 - info (default)
+                         5 - debug info (here starts lots of output)
+                         6 - trace info (and even more)
+  -v, --verbose         Verbose output during the build process (info level)
+  -q, --quiet           Display only errors and fatal errors during build
   -c, --conf [FILE]     Specify configuration file to use.
                          Default: /etc/dracut.conf
   --confdir [DIR]       Specify configuration directory to use *.conf files 
@@ -184,6 +193,7 @@ while (($# > 0)); do
         -k|--kmoddir)  read_arg drivers_dir_l        "$@" || shift;;
         -c|--conf)     read_arg conffile             "$@" || shift;;
         --confdir)     read_arg confdir              "$@" || shift;;
+        -L|--stdlog)   read_arg stdloglvl_l          "$@" || shift;;
         -f|--force)    force=yes;;
         --kernel-only) kernel_only="yes"; no_kernel="no";;
         --no-kernel)   kernel_only="no"; no_kernel="yes";;
@@ -195,6 +205,7 @@ while (($# > 0)); do
         --nolvmconf)   lvmconf_l="no";;
         --debug)       debug="yes";;
         -v|--verbose)  beverbose="yes";;
+        -q|--quiet)    bequiet="yes";;
         -l|--local)    allowlocal="yes" ;;
         -H|--hostonly) hostonly_l="yes" ;;
         --fstab)       use_fstab_l="yes" ;;
@@ -236,6 +247,12 @@ export PATH
     set -x
 }
 
+# For compatibility with -v behaviour. Set to info level.
+[[ $beverbose ]] && (( $stdloglvl_l < 4 )) && stdloglvl_l=4
+
+# When quiet, display only errors and fatal errors.
+[[ $bequiet ]] && (( $stdloglvl_l > 2 )) && stdloglvl_l=2
+
 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
 
 [[ $allowlocal && -f "$(readlink -f ${0%/*})/dracut-functions" ]] && \
@@ -311,6 +328,7 @@ if [[ ${#fw_dir_l[@]} ]]; then
     done
 fi
 
+[[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
 [[ $do_strip_l ]] && do_strip=$do_strip_l
 [[ $hostonly_l ]] && hostonly=$hostonly_l
@@ -411,7 +429,7 @@ trap 'exit 1;' SIGINT
 chmod 755 "$initdir"
 
 export initdir hookdirs dracutbasedir dracutmodules drivers \
-    fw_dir drivers_dir debug beverbose no_kernel kernel_only \
+    fw_dir drivers_dir debug no_kernel kernel_only \
     add_drivers mdadmconf lvmconf filesystems \
     use_fstab libdir usrlibdir
 
diff --git a/dracut-functions b/dracut-functions
index e321dc9..1df2dcb 100755
--- a/dracut-functions
+++ b/dracut-functions
@@ -20,6 +20,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+if [[ -f $dracutbasedir/dracut-logger ]]; then
+    . "$dracutbasedir/dracut-logger"
+    dlog_init
+fi
+
 IF_RTLD=""
 IF_dynamic=""
 
@@ -61,31 +66,6 @@ is_func() {
     [[ $(type -t $1) = "function" ]] 
 }
 
-# Log initrd creation.
-if ! [[ $dracutlogfile ]]; then
-    [[ $dracutbasedir = /usr/share/dracut ]] && \
-	dracutlogfile=/var/log/dracut.log || \
-	dracutlogfile=$HOME/dracut.log
-    if [[ -w ${dracutlogfile%/*} ]]; then
-        >>"$dracutlogfile"
-    fi
-fi
-
-dwarning() {
-    echo "W: $@" >&2
-    [[ -w $dracutlogfile ]] && echo $(date) "Warn:" $@ >>"$dracutlogfile"
-}
-
-dinfo() {
-    [[ $beverbose ]] && echo "I: $@" >&2
-    [[ -w $dracutlogfile ]] && echo $(date) "Info:" $@ >>"$dracutlogfile"
-}
-
-derror() {
-    echo "E: $@" >&2
-    [[ -w $dracutlogfile ]] && echo $(date) "Err:" $@ >>"$dracutlogfile"
-}
-
 # Function prints global variables in format name=value line by line.
 # $@ = list of global variables' name
 print_vars() {
diff --git a/dracut-logger b/dracut-logger
new file mode 100755
index 0000000..a20d6f8
--- /dev/null
+++ b/dracut-logger
@@ -0,0 +1,266 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 et filetype=sh
+#
+# logging faciality module for dracut both at build- and boot-time
+#
+# Copyleft 2010 Amadeusz ÅoÅnowski <aidecoe@xxxxxxxxxxxx>
+#
+# This program 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+## @brief Logging facility module for Dracut both at build- and boot-time.
+#
+# @section intro Introduction
+#
+# The logger takes a bit from Log4j philosophy. There are defined 6 logging
+# levels:
+#   - TRACE (1)
+#     The TRACE Level designates finer-grained informational events than the
+#     DEBUG.
+#   - DEBUG (2)
+#     The DEBUG Level designates fine-grained informational events that are most
+#     useful to debug an application.
+#   - INFO (3)
+#     The INFO level designates informational messages that highlight the
+#     progress of the application at coarse-grained level.
+#   - WARN (4)
+#     The WARN level designates potentially harmful situations.
+#   - ERROR (5)
+#     The ERROR level designates error events that might still allow the
+#     application to continue running.
+#   - FATAL (5)
+#     The FATAL level designates very severe error events that will presumably
+#     lead the application to abort.
+# Descriptions are borrowed from Log4j documentation:
+# http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html
+#
+# @section usage Usage
+#
+# First of all you have to start with dlog_init() function which initializes
+# required variables. Don't call any other logging function before that one!
+# If you're ready with this, you can use following functions which corresponds
+# clearly to levels listed in @ref intro Introduction. Here they are:
+#   - dtrace()
+#   - ddebug()
+#   - dinfo()
+#   - dwarn()
+#   - derror()
+#   - dfatal()
+# They take all arguments given as a single message to be logged. See dlog()
+# function for details how it works. Note that you shouldn't use dlog() by
+# yourself. It's wrapper with above functions.
+#
+# @see dlog_init() dlog()
+#
+# @section conf Configuration
+#
+# Logging is controlled by following global variables:
+#   - @var stdloglvl - logging level to standard error (console output)
+#   - @var sysloglvl - logging level to syslog (by logger command)
+#   - @var fileloglvl - logging level to file
+#   - @var logfile - log file which is used when @var fileloglvl is higher
+#   than 0
+# and one global internal variable @var _maxloglvl which <b>must not</b> be
+# overwritten. @_maxloglvl is set by dlog_init() and holds maximum logging level
+# of those three and indicates that dlog_init() was run.
+#
+# Logging level set by the variable means that messages from this logging level
+# and above (FATAL is the highest) will be shown. Logging levels may be set
+# independently for each destination (stderr, syslog, file).
+#
+# @see dlog_init()
+
+
+## @brief Initializes Dracut Logger.
+#
+# @retval 1 if something has gone wrong
+# @retval 0 on success.
+#
+# @note This function need to be called before any other from this file.
+#
+# If any of the variables is not set, this function set it to default:
+#   - @var stdloglvl = 4 (info)
+#   - @var sysloglvl = 0 (no logging)
+#   - @var fileloglvl is set to 4 when @var logfile is set too, otherwise it's
+#   set to 0
+#
+# @warning Function sets global variable @var _maxloglvl for internal use. Don't
+# overwrite it.
+dlog_init() {
+    [ -n "$_maxloglvl" ] && return 0
+    [ -z "$stdloglvl" ] && stdloglvl=4
+    [ -z "$sysloglvl" ] && sysloglvl=0
+
+    if [ -z "$fileloglvl" ]; then
+        [ -w "$logfile" ] && fileloglvl=4 || fileloglvl=0
+    elif [ $fileloglvl -gt 0 ]; then
+        ! [ -e "$logfile" ] && >"$logfile"
+        [ -w "$logfile" -a -f "$logfile" ] || {
+            logger -t dracut -p error -s "E: '$logfile' is not writable file"
+            return 1
+        }
+
+        # Mark new run in the log file
+        echo >>"$logfile"
+        if command -v date >/dev/null; then
+            echo "=== $(date) ===" >>"$logfile"
+        else
+            echo "===============================================" >>"$logfile"
+        fi
+        echo >>"$logfile"
+    fi
+
+    local lvl
+    _maxloglvl=0
+    for lvl in $stdloglvl $sysloglvl $fileloglvl; do
+        [ $lvl -gt $_maxloglvl ] && _maxloglvl=$lvl
+    done
+}
+
+## @brief Converts numeric logging level to the first letter of level name.
+#
+# @param lvl Numeric logging level in range from 1 to 6.
+# @retval 1 if @a lvl is out of range.
+# @retval 0 if @a lvl is correct.
+# @result Echoes first letter of level name.
+_lvl2char() {
+    case "$1" in
+        1) echo F;;
+        2) echo E;;
+        3) echo W;;
+        4) echo I;;
+        5) echo D;;
+        6) echo T;;
+        *) return 1;;
+    esac
+}
+
+## @brief Converts numeric level to logger priority defined by POSIX.2.
+#
+# @param lvl Numeric logging level in range from 1 to 6.
+# @retval 1 if @a lvl is out of range.
+# @retval 0 if @a lvl is correct.
+# @result Echoes logger priority.
+_lvl2syslogpri() {
+    case "$1" in
+        1) echo crit;;
+        2) echo error;;
+        3) echo warning;;
+        4) echo info;;
+        5) echo debug;;
+        6) echo debug;;
+        *) return 1;;
+    esac
+}
+
+## @brief Prints or/and writes to file or/and to syslog given message with given
+# level (priority).
+#
+# @param lvl Numeric logging level.
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+#
+# @note This function is not supposed to be called manually. Please use
+# dtrace(), ddebug(), or others instead which wrap this one.
+#
+# This is core logging function which logs given message to standard error, file
+# and/or syslog (with POSIX shell command <tt>logger</tt>). The format is
+# following:
+#
+# <tt>X: some message</tt>
+#
+# where @c X is the first letter of logging level. See module description for
+# details on that.
+#
+# Message to syslog is sent with tag @c dracut. Priorities are mapped as
+# following:
+#   - @c FATAL to @c crit
+#   - @c ERROR to @c error
+#   - @c WARN to @c warning
+#   - @c INFO to @c info
+#   - @c DEBUG and @c TRACE both to @c debug
+dlog() {
+    [ -z "$_maxloglvl" ] && return 0
+    local lvl="$1"; shift
+    local lvlc=$(_lvl2char "$lvl") || return 0
+
+    [ $lvl -le $_maxloglvl ] || return 0
+
+    local msg="$lvlc: $*"
+
+    [ $lvl -le $stdloglvl ] && echo "$msg" >&2
+    if [ $lvl -le $sysloglvl ]; then
+        logger -t dracut -p $(_lvl2syslogpri $lvl) "$msg"
+    fi
+    if [ $lvl -le $fileloglvl -a -w "$logfile" -a -f "$logfile" ]; then
+        echo "$msg" >>"$logfile"
+    fi
+}
+
+## @brief Logs message at TRACE level (6)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+dtrace() {
+    dlog 6 "$*"
+}
+
+## @brief Logs message at DEBUG level (5)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+ddebug() {
+    dlog 5 "$*"
+}
+
+## @brief Logs message at INFO level (4)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+dinfo() {
+    dlog 4 "$*"
+}
+
+## @brief Logs message at WARN level (3)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+dwarn() {
+    dlog 3 "$*"
+}
+
+## @brief It's an alias to dwarn() function.
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+dwarning() {
+    dwarn "$*"
+}
+
+## @brief Logs message at ERROR level (2)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+derror() {
+    dlog 2 "$*"
+}
+
+## @brief Logs message at FATAL level (1)
+#
+# @param msg Message.
+# @retval 0 It's always returned, even if logging failed.
+dfatal() {
+    dlog 1 "$*"
+}
diff --git a/dracut.conf b/dracut.conf
index c921a00..bf92a00 100644
--- a/dracut.conf
+++ b/dracut.conf
@@ -1,5 +1,9 @@
 # Sample dracut config file
 
+logfile=/var/log/dracut-build.log
+fileloglvl=6
+stdloglvl=3
+
 # Specific list of dracut modules to use
 #dracutmodules+=""
 
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe initramfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux