log
Log library that provides functions for logging messages, similar to the Python logging module. It supports different log levels, custom formatting, filtering, and output redirection.
Usage Guide¶
Basic Logging¶
The most common way to log is using the level-specific functions. They accept a single string or a printf format followed by arguments.
L_info "This is an info message"
L_error "Something went wrong with file: %s" "$filename"
L_debug "Variable x is: %d" "$x"
Available levels (from highest to lowest severity):
- L_critical
- L_error
- L_warning
- L_notice
- L_info
- L_debug
- L_trace
L_run and L_dryrun¶
L_run is a powerful wrapper for executing commands while logging them. It respects the L_dryrun variable.
L_dryrun=1
L_run rm -rf /important/dir
# Outputs: DRYRUN: +rm -rf /important/dir
# Command is NOT executed.
L_dryrun=0
L_run touch new_file
# Outputs: +touch new_file
# Command is executed.
Log Configuration¶
Use L_log_configure to change the behavior of the logging system.
The "First Call Wins" Principle¶
By default, L_log_configure follows a "configure-once" design. This means the first call to this function sets the global configuration, and all subsequent calls are ignored.
This prevents libraries or sourced scripts from accidentally overriding your application's logging setup (e.g., changing your JSON format back to plain text).
Reconfiguring with -r¶
If you need to change the configuration later (for example, after parsing command-line arguments to change the log level), you must use the -r (reconfigure) flag.
# Initial default setup (maybe in a library)
L_log_configure -l info
# This call will be IGNORED because logging is already configured
L_log_configure -l debug
# This call will WORK because -r forces a reconfiguration
L_log_configure -r -l debug
Setting Log Level¶
# Set level via name
L_log_configure -l debug
# Set level via integer constant
L_log_configure -l "$L_LOGLEVEL_ERROR"
Integration with Argparse¶
A common pattern is to set the verbosity via command-line flags.
main() {
local verbose=0
L_argparse -- \
-v --verbose action=count var=verbose help="Increase verbosity" \
---- "$@"
local level=INFO
if ((verbose >= 2)); then level=TRACE;
elif ((verbose >= 1)); then level=DEBUG; fi
L_log_configure -r -l "$level"
}
Predefined Formats¶
The library comes with several built-in formatters:
- Default: script:LEVEL:line:message
- Long (-L): Includes ISO8601 timestamp, source file, function name, and line number.
- JSON (-J): Outputs one JSON object per line, ideal for log aggregators.
# Default format
L_info "hi"
# Output: my_script:info:10:hi
# Use the long format
L_log_configure -L
L_info "hi"
# Output: 2026-02-06T12:56:25+0100 my_script:main:2 info hi
# Use JSON format for structured logging
L_log_configure -J
L_info "hi"
# Output: {"timestamp":"2026-02-06T12:56:20+0100","funcname":"main","lineno":1,"source":"my_script","level":20,"levelname":"info","message":"hi","script":"my_script","pid":15653,"ppid":1170}
Customization¶
You can fully customize how logs are filtered, formatted, and where they are sent.
my_formatter() {
# The message is in "$@", the result must be put in L_logline
printf -v L_logline "[%s] %s" "$L_logline_levelname" "$*"
}
my_outputter() {
# Print the formatted L_logline
echo "CUSTOM: $L_logline" >&2
}
L_log_configure -F my_formatter -o my_outputter
Available variables in callbacks:¶
$L_logline: The variable to be set by the formatter and read by the outputter.$L_logline_levelno: Numeric logging level.$L_logline_levelname: Text logging level.$L_logline_funcname: Function name.$L_logline_source: Source file path.$L_logline_lineno: Line number.
API Reference¶
log
¶
logging library
This library is meant to be similar to python logging library.
was log system configured?
_L_logconf_configured=0
int current global log level
_L_logconf_level=$L_LOGLEVEL_INFO
1 or 0 or ''. Should we use the color for logging output?
_L_logconf_color=
if this regex is set, allow elements
_L_logconf_selecteval=
default formatting function
_L_logconf_formateval='L_log_format_default "$@"'
default outputting function
_L_logconf_outputeval=L_log_output_to_stderr
Example
L_log_set_level ERROR
L_error "this is an error"
L_info "this is information"
L_debug "This is debug"
$L_LOGLEVEL_CRITICAL
¶
$L_LOGLEVEL_ERROR
¶
$L_LOGLEVEL_WARNING
¶
$L_LOGLEVEL_NOTICE
¶
$L_LOGLEVEL_INFO
¶
$L_LOGLEVEL_DEBUG
¶
$L_LOGLEVEL_TRACE
¶
$L_LOGLEVEL_NAMES
¶
convert log level to log name
$L_LOGLEVEL_COLORS
¶
get color associated with particular loglevel
Shellcheck disable= SC2153
L_log_configure
¶
Configure L_log module.
Example
L_log_configure \
-l debug \
-c 0 \
-f 'printf -v L_logline "${@:2}"' \
-o 'printf "%s\n" "$L_logline" >&2' \
-s '[[ $L_logline_source == */script.sh ]]'
Options:
-
-hPrint this help and return 0. -
-rAllow for reconfiguring L_log system. Otherwise the next call of this function is ignored. -
-l <LOGLEVEL>Set loglevel. Can be \$L_LOGLEVEL_INFO INFO or 30. Default: $_L_logconf_level -
-c <BOOL>Set to 1 to enable the use of color, set to 0 to disable the use of color.
Set to '' empty string to detect if stdout has color support. Default: ''
-
-f <FORMATEVAL>Evaluate expression for formatting. Default: 'L_log_format_default "$@"'
The function should format arguments and put the message into the L_logline variable.
-
-F <FORMATFUNC>Equal to -f '"$@"'. Shorthand to use a function. -
-s <SELECTEVAL>If eval "SELECTEVAL" exits with nonzero, do not print the line. Default: '' -
-o <OUTPUTEVAL>Evaluate expression for outputting. Default: L_log_output_to_stderr
The function should output the content of L_logline.
-
-LEqual to -F L_log_format_long -
-JEqual to -F L_log_format_json
Arguments: Takes no arguments
L_log_level_inc
¶
increase log level
Argument:
$1
L_log_level_dec
¶
decrease log level
Argument:
$1
L_log_level_to_int_to
¶
Convert log string to number
Arguments:
-
$1str variable name -
$2int|str loglevel likeINFOinfoor30
L_log_is_enabled_for
¶
Check if log of such level is enabled to log.
Argument:
$1
str|int loglevel or log string
L_log_format_default
¶
Default logging formatting
Arguments:
-
$1str log line printf format string -
$@any log line printf arguments
L_log_format_long
¶
Format logline with timestamp information.
Arguments:
-
$1str log line printf format string -
$@any log line printf arguments
L_log_format_json
¶
Output logs in json format.
Shellcheck disable= SC2059
L_log_output_to_stderr
¶
Output L_logline to stderr.
L_log_output_to_logger
¶
Output L_logline with logger.
Argument:
$@
message to output
L_log
¶
main logging entrypoint
Options:
-
-s <int>Increment stacklevel by this much -
-l <int|string>loglevel to print log line as
Argument:
$@
any log arguments
Shellcheck disable= SC2140
Return: 0 if nothing was logged, or the exit status of formatter && outputter functions.
L_critical
¶
output a critical message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_error
¶
output a error message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_warning
¶
output a warning message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_notice
¶
output a notice
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_info
¶
output a information message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_debug
¶
output a debugging message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_trace
¶
output a tracing message
Option:
-s <int>
stacklevel increase
Argument:
$1
message
L_fatal
¶
Output a critical message and exit the script with 2.
Argument:
$@
L_critical arguments
L_logrun
¶
log a command and then execute it
Is not affected by L_dryrun variable.
Argument:
$@
command to execute
L_ok
¶
Output a green information message
Options:
-
-s <int> -
-l <level>
Argument:
$1
message
$L_dryrun
¶
set to 1 if L_run should not execute the function.
L_run
¶
Logs the quoted argument with a leading +.
if L_dryrun is nonzero, executes the arguments.
Options:
-
-l <loglevel>Set loglevel. -
-s <stacklevel>Increment stacklevel by this number. -
-hPrint this help and return 0.
Argument:
$@
command to execute
Uses environment variable:
L_dryrun