A flexible, reusable logging module for shell scripts that provides standardized logging functionality with various configuration options. It runs in bash 3.2+, zsh, dash and busybox ash from one file.
Note
Upgrading from 2.x? 3.0 is a major release with some behaviour changes. See Upgrading to 3.0 before you update.
The core deliverable of this repository is logging.sh. It is intentionally kept
as a single, self-contained (and yes, long) shell file, written in POSIX sh plus local, so you can drop it next to your
scripts and source it (or . it in a POSIX sh script) without any packaging steps. The file keeps a #!/usr/bin/env bash line only so that
running it directly prints its usage message. Everything else in the repo - docs,
demos, and pipeline scripts - exists to support using that file.
Note
This is an expansion of the originally published bash_logging GitHub gist published by @GingerGraham.
- Runs in bash 3.2+, bash
--posix, zsh, dash and busybox ash from one file - Standard syslog log levels (DEBUG, INFO, WARN, ERROR, CRITICAL, etc.)
- Console output with color-coding by severity
- Configurable stdout/stderr output stream split
- Optional file output
- Optional systemd journal logging
- Customizable log format
- UTC or local time support
- INI configuration file support
- Runtime configuration changes
- Special handling for sensitive data
- Secure-by-default newline sanitization to prevent log injection
- Secure-by-default removal of terminal control sequences and other control characters to prevent terminal manipulation attacks (see Upgrading to 3.0 for the full list)
- Configurable log line length limits for DoS resistance
- TOCTOU race condition protection during log file creation
- Library (
logging.sh): written for POSIX sh pluslocal, so the same file works in:- bash 3.2 or later, including the bash 3.2 that macOS ships as
/bin/bash, and bash--posix - zsh
- dash (
/bin/shon Debian and Ubuntu) - busybox ash (
/bin/shon Alpine and other busybox-based images)
- bash 3.2 or later, including the bash 3.2 that macOS ships as
- Test suite (
tests/): Bash 3.2 or later, on Linux and on macOS with its BSD userland. The cross-shell suites run the library under each shell listed inTEST_SHELLS.
scripts/check-bash32-compat.sh rejects bash 4+ syntax and scripts/check-posix-compat.sh
rejects syntax that dash does not support. See Shell Compatibility
for the few documented differences between shells (script name detection and how truncation
counts multi-byte characters).
In a bash or zsh script:
#!/usr/bin/env bash
# Source the logging module
source /path/to/logging.sh
# Initialize the logger
init_logger
# Log messages
log_info "Application started"
log_error "Something went wrong"In a POSIX sh script (dash, busybox ash, or any /bin/sh on Debian, Ubuntu and Alpine), use . instead of source:
#!/bin/sh
# Source the logging module
. /path/to/logging.sh
init_logger
log_info "Application started"
log_error "Something went wrong"See Getting Started for detailed installation and basic usage instructions.
- Getting Started - Installation and basic usage
- Log Levels - Understanding severity levels
- Initialization - Configuring the logger at startup
- Configuration - Using configuration files
- Output Streams - Controlling stdout/stderr behavior
- Formatting - Customizing log message format
- Journal Logging - Integration with systemd journal
- Runtime Configuration - Changing settings on the fly
- Sensitive Data - Handling sensitive information securely
- API Reference - Complete function reference
- Examples - Comprehensive usage examples
- Troubleshooting - Common issues and solutions
- Shell Compatibility - Supported shells and their differences
- Upgrading to 3.0 - What changed from 2.x
source /path/to/logging.sh
init_logger
log_info "Script starting"See: Getting Started
init_logger --log "/var/log/myapp.log" --level INFOSee: Initialization
init_logger --config /etc/myapp/logging.confSee: Configuration
init_logger --journal --tag "myapp" --facility "local0"See: Journal Logging
The project includes a comprehensive test suite to verify all functionality. To run the tests:
make test
# Or directly:
cd tests && ./run_tests.shAdditional testing tools are available via the Makefile:
make coverage # Run tests with kcov code coverage
make test-junit # Generate JUnit XML report
make sonar-analysis # Full coverage + SonarQube analysisNote: Coverage and SonarQube targets require additional tools (kcov, sonar-scanner). See Testing Documentation for setup details.
See tests/README.md and Testing for more information.
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
The project uses pre-commit hooks for code quality checks (ShellCheck, MarkdownLint, etc.).
The CI lint workflow runs these same hooks, so tool versions are centralized in .pre-commit-config.yaml.
See docs/PRE-COMMIT.md for setup instructions.
This project is currently maintained by @GingerGraham.
The maintainer uses a combination of GitHub Copilot and Claude to assist with development, code review, and test design/execution in this repository. Final decisions, validation, and responsibility for merged changes remain with the maintainer.
This module is provided under the MIT License.
