This guide helps you diagnose and resolve common issues with the Bash Logging Module.
- Installation Issues
- Initialization Issues
- Configuration File Issues
- File Logging Issues
- Journal Logging Issues
- Console Output Issues
- Output Stream Issues
- Runtime Configuration Issues
- Format Issues
- Debugging Tips
- Performance Issues
- Common Error Messages
- "command not found: init_logger"
- "permission denied" when writing log file
- "invalid log level"
- "Configuration file not found" / "Configuration file not readable"
- "Cannot create log directory" / "Cannot create log file"
- "Log file path is a symbolic link"
- "Log file is not writable" / "Failed to write to log file"
- Getting Help
- Related Documentation
Problem: bash: logging.sh: No such file or directory
Solutions:
# Check if file exists
ls -l /path/to/logging.sh
# Verify the path in your source command
source /correct/path/to/logging.sh
# Use absolute path
source /usr/local/lib/logging.sh
# Or relative to script location
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/logging.sh"Problem: bash: logging.sh: Permission denied
Solutions:
# Check file permissions
ls -l /path/to/logging.sh
# Make file readable
chmod +r /path/to/logging.sh
# Or set appropriate permissions
chmod 644 /path/to/logging.shProblem: Log functions don't work, no output appears
Solution:
# Always call init_logger before logging
source /path/to/logging.sh
init_logger # Don't forget this!
log_info "Now this works"Problem: init_logger returns error code 1
Common causes:
- Cannot create log file directory
# Check directory exists and is writable
ls -ld /var/log/myapp/
# Create directory if needed
sudo mkdir -p /var/log/myapp
sudo chown $USER:$USER /var/log/myapp
# Or use a directory you have access to
init_logger --log "$HOME/logs/app.log"- No write permission to log file
# Check file permissions
ls -l /var/log/myapp.log
# Fix permissions
sudo chown $USER:$USER /var/log/myapp.log
# Or use a different location
init_logger --log "$HOME/app.log"- Disk space full
# Check disk space
df -h
# Clean up or use different location
init_logger --log "/tmp/app.log"- Symbolic link or irregular file type
# Error: "Log file path is a symbolic link"
# This is a security protection against TOCTOU attacks
# Check what the file actually is
ls -l /path/to/logfile.log
# If it's a symlink:
file /path/to/logfile.log
# Solution: Remove the symlink and use a direct path
rm /path/to/logfile.log
init_logger --log "/path/to/logfile.log"
# Error: "Log file exists but is not a regular file (may be a directory or device)"
# This prevents logging to devices or directories
# Check the file type
ls -ld /path/to/logfile.log
# If it's a directory, use a file path instead:
init_logger --log "/path/to/logfile.log/app.log" # Add filename
# If it's a device or special file, use a regular file path
init_logger --log "$HOME/logs/app.log"Note: bash-logger rejects symbolic links for security reasons. This prevents attackers from redirecting your logs to sensitive system files. Always use direct file paths for log files.
Problem: Settings from config file are not applied
Solutions:
# Check file exists
ls -l /etc/myapp/logging.conf
# Verify file is readable
cat /etc/myapp/logging.conf
# Check file path in init_logger call
init_logger --config /etc/myapp/logging.conf
# Use absolute path
init_logger --config "$(pwd)/logging.conf"Problem: Config file has invalid values, logger sanitizes input or uses defaults
Common Validation Errors:
- Invalid Log Level
[logging]
# Incorrect - will use default (INFO) and display warning
level = INVALID_LEVEL
level = TRACE # Not a valid level name
# Correct values
level = DEBUG # or INFO, NOTICE, WARN, ERROR, CRITICAL, ALERT, EMERGENCY
level = 7 # Numeric values 0-7 are also validError message:
Warning: Invalid log level 'INVALID_LEVEL' at line 2, using INFO
Hint: Valid levels are: DEBUG, INFO, NOTICE, WARN, ERROR, CRITICAL, ALERT, EMERGENCY (or 0-7)
- Invalid File Path
[logging]
# Incorrect - must be absolute path
log_file = relative/path/file.log
# Incorrect - contains suspicious patterns
log_file = /tmp/$(whoami).log
log_file = /var/log/app.log; rm -rf /
# Correct - absolute path, no shell metacharacters
log_file = /var/log/myapp.log
log_file = /home/user/.local/share/myapp/logs/app.logError messages:
Error: Configuration value for 'log_file' at line 3 must be an absolute path (got: 'relative/path/file.log')
Hint: Skipping invalid log file path
Error: Configuration value for 'log_file' at line 4 contains suspicious patterns
Hint: Skipping invalid log file path
- Invalid Numeric Range
[logging]
# Incorrect - exceeds maximum (1MB = 1,048,576)
max_line_length = 999999999
# Incorrect - not a number
max_line_length = unlimited
# Correct
max_line_length = 8192
max_line_length = 0 # 0 means unlimitedError message:
Warning: Invalid max_line_length value '999999999' at line 2, expected integer 0-1048576
Hint: Using default value of 4096
- Invalid Journal Tag
[logging]
# Contains shell metacharacters - will be sanitized
tag = myapp-$(hostname)
# Too long - will be truncated
tag = this_is_a_very_long_tag_that_exceeds_the_sixty_four_character_maximum_length
# Correct
tag = myapp
tag = my_app-serviceWarning messages:
Warning: Journal tag at line 2 contains shell metacharacters (will be sanitized)
Hint: Sanitized journal tag to remove shell metacharacters
Error: Journal tag at line 3 exceeds maximum length of 64 (actual: 79)
Hint: Truncated journal tag to 64 characters
- Invalid Boolean Value
[logging]
# Incorrect - case-sensitive, must be lowercase
journal = True
verbose = YES
# Correct boolean values
journal = true # or false, yes, no, on, off, 1, 0
verbose = yesError message:
Warning: Invalid journal value 'True' at line 2, expected true/false
- Unknown Configuration Key
[logging]
# Typo or unsupported key
levl = INFO # Should be 'level'
debug_mode = true # Not a valid keyWarning message:
Warning: Unknown configuration key 'levl' at line 2
Hint: Valid keys are: level, format, log_file, journal, tag, utc, color,
stderr_level, quiet, console_log, script_name, verbose,
unsafe_allow_newlines, unsafe_allow_ansi_codes, max_line_length, max_journal_length
Resolution:
The logger will:
- Use default values for invalid settings
- Sanitize values that can be fixed (e.g., remove shell metacharacters from tags)
- Display warnings with hints about the correct format
- Continue initialization with corrected values
Validation Summary:
| Configuration Item | Validation | On Error |
|---|---|---|
level |
Valid level name or 0-7 | Use INFO, display warning with valid values |
log_file |
Absolute path, no control chars, no shell patterns | Skip file logging, display error |
tag |
Max 64 chars, no control chars | Truncate or sanitize, display warning |
max_line_length |
Integer 0-1,048,576 | Use default (4096), display warning |
max_journal_length |
Integer 0-1,048,576 | Use default (4096), display warning |
| Boolean values | true/false, yes/no, on/off, 1/0 (case-insensitive) | Display warning, keep previous value |
| All values | Max 4,096 characters | Truncate, display warning |
| Unknown keys | N/A | Display warning with list of valid keys |
Solution:
Check configuration file format and ensure all values meet the requirements listed above. Pay attention to:
- Log levels must be uppercase or numeric
- File paths must be absolute and start with
/ - Numeric values must be within valid ranges
- Boolean values must be lowercase
Problem: CLI arguments don't override config file values
Solution:
Ensure CLI arguments come after the --config option:
# Correct - CLI overrides config
init_logger --config logging.conf --level DEBUG
# Incorrect - config file might override CLI
init_logger --level DEBUG --config logging.confProblem: Console shows logs but file is empty
Solutions:
# 1. Check file was created
ls -l /var/log/myapp.log
# 2. Verify initialization succeeded
if ! init_logger --log "/var/log/myapp.log"; then
echo "Logger initialization failed" >&2
fi
# 3. Check you're logging at the right level
init_logger --log "/var/log/app.log" --level DEBUG
log_debug "This should appear" # Won't appear if level is INFO
# 4. Check log file path is correct
init_logger --log "/var/log/app.log"
echo "Log file location: $LOG_FILE" # If module exposes this variableProblem: Cannot write to log file
Solutions:
# Check current user
whoami
# Check file ownership and permissions
ls -l /var/log/myapp.log
# Fix ownership
sudo chown $USER:$USER /var/log/myapp.log
# Fix permissions
chmod 644 /var/log/myapp.log
# Or use a user-writable location
init_logger --log "$HOME/logs/app.log"
mkdir -p "$HOME/logs"Background: For security reasons (defense-in-depth against information disclosure, CWE-209), error messages from bash-logger do not disclose file paths. This prevents potential attackers from learning about your system's directory structure through error messages.
Problem: Error messages don't show the specific path that failed, making debugging harder
Solutions:
When you see errors like:
Error: Configuration file not foundError: Cannot create log directoryError: Log file is not writableError: Log file path is a symbolic link
Here's how to debug them:
1. Verify Your Configuration Sources
Check where your paths are defined:
# For configuration files, check the --config argument
init_logger --config /path/to/config.conf --verbose
# For log files, check the --log argument
init_logger --log /path/to/logfile.log --verbose
# Or check environment variables
echo "LOG_FILE: $LOG_FILE"
echo "LOG_CONFIG_FILE: $LOG_CONFIG_FILE"2. Test Path Components Individually
# Test if directory exists
test -d "$HOME/logs" && echo "Directory exists" || echo "Directory missing"
# Test if file is writable
test -w "$HOME/logs/app.log" && echo "Writable" || echo "Not writable"
# Test if path is a symlink
test -L "$HOME/logs/app.log" && echo "Is symlink!" || echo "Not a symlink"
# Test file type
test -f "$HOME/logs/app.log" && echo "Regular file" || echo "Not a regular file"
# Test directory permissions
ls -ld "$HOME/logs"3. Enable Verbose/Debug Mode
Debug messages include initialization details:
init_logger --log /path/to/app.log --verbose
# Output will show:
# Logger initialized with script_name='yourscript.sh': console=true,
# file=/path/to/app.log, journal=false, colors=auto, log level=DEBUG, ...4. Check Configuration File Contents
# Verify config file path and contents
cat /path/to/config.conf
# Check for typos in paths
grep -E 'log_file|logfile|file' /path/to/config.conf5. Look at the Hints
Error messages include actionable hints:
| Error Message | Hint Provided | What to Check |
|---|---|---|
| Configuration file not found | Check the --config argument | Verify path passed to init_logger |
| Configuration file not readable | Check file permissions | Run ls -l on config file |
| Cannot create log directory | Check --log argument and parent permissions | Verify parent directory is writable |
| Log file path is a symbolic link | Verify --log doesn't point to symlink | Security check, use regular file |
| Cannot create log file | Check directory permissions | Verify directory exists and is writable |
| Log file is not a regular file | Check --log argument | Might be pointing to directory or device |
| Log file is not writable | Check file permissions | Run chmod or use different location |
| Failed to write to log file | Check permissions, disk space, or if deleted | Check df -h for disk space |
6. Common Path Issues
# Issue: Relative path that doesn't exist
init_logger --log logs/app.log # ❌ May fail if 'logs' doesn't exist
# Solution: Create directory first or use absolute path
mkdir -p logs
init_logger --log logs/app.log # ✓ Works
# Or use absolute path
init_logger --log "$PWD/logs/app.log" # ✓ Works
# Issue: No permission to create parent directories
init_logger --log /var/log/myapp/app.log # ❌ May fail if /var/log/myapp doesn't exist
# Solution: Create directory with proper permissions first
sudo mkdir -p /var/log/myapp
sudo chown $USER:$USER /var/log/myapp
init_logger --log /var/log/myapp/app.log # ✓ Works
# Issue: Accidentally pointing to a directory
init_logger --log /tmp/myapp # ❌ If /tmp/myapp is a directory
# Solution: Add filename
init_logger --log /tmp/myapp/app.log # ✓ WorksWhy This Approach?
Not displaying paths in error messages is a security best practice:
- Prevents information disclosure (CWE-209)
- Reduces reconnaissance data for attackers
- Protects usernames in $HOME paths
- Provides defense-in-depth
The paths are still available through:
- Command-line arguments you passed
- Configuration files you created
- Environment variables you set
- Debug output when using
--verbose
Problem: No logs in journalctl output
Solutions:
# 1. Check if logger command exists
which logger
# If not found:
sudo apt-get install util-linux # Debian/Ubuntu
sudo dnf install util-linux # RHEL/Fedora
# 2. Test logger directly
logger -t test-tag "Test message"
journalctl -t test-tag -n 5
# 3. Check journal logging is enabled
init_logger --journal --tag "myapp"
# 4. Check systemd journal is running
systemctl status systemd-journald
# 5. View all recent journal entries
journalctl -n 50
# 6. Check for your tag specifically
journalctl -t myapp --since "1 minute ago"Problem: Logs appear with wrong tag
Solution:
# Explicitly set tag
init_logger --journal --tag "myapp"
# Verify in journal
journalctl -t myapp -n 5
# Change tag at runtime
set_journal_tag "new-tag"Problem: No logs appear on screen
Solutions:
# 1. Check if quiet mode is enabled
init_logger # Don't use --quiet
# 2. Check log level
init_logger --level DEBUG # or --verbose
# 3. Verify you're logging at or above the current level
init_logger --level WARN
log_info "Won't show" # INFO < WARN
log_warn "Will show" # WARN >= WARN
log_error "Will show" # ERROR > WARNProblem: Colors don't appear in console
Solutions:
# 1. Check if output is to a TTY
if [[ -t 1 ]]; then
echo "stdout is a TTY"
else
echo "stdout is not a TTY (colors disabled)"
fi
# 2. Force colors on
init_logger --color
# 3. Check terminal supports colors
echo $TERM
# Should be xterm-256color, screen, or similar
# 4. Verify colors aren't explicitly disabled
init_logger # Don't use --no-colorProblem: ANSI color codes in log file make it hard to read
Solution:
This should not happen normally - colors are auto-detected. If it does:
# Explicitly disable colors for file-only logging
init_logger --log "/var/log/app.log" --quiet --no-color
# Or remove color codes from existing file
sed 's/\x1b\[[0-9;]*m//g' app.log > app-clean.logProblem: ERROR messages on stdout instead of stderr (or vice versa)
Solution:
Check stderr-level configuration:
# Default: ERROR and above to stderr
init_logger
# If you want WARN to stderr too
init_logger --stderr-level WARN
# Verify stream behavior
./script.sh 2>&1 | grep "ERROR" # Should find errorsProblem: All output goes to same stream
Solution:
# Check script uses correct log functions
log_info "To stdout" # Below stderr-level
log_error "To stderr" # At or above stderr-level
# Verify stderr-level setting
init_logger --stderr-level ERROR
# Test stream separation
./script.sh > stdout.log 2> stderr.logProblem: Changing log level doesn't affect output
Solution:
# Verify function is called correctly
set_log_level DEBUG # Correct
set_log_level debug # Case-sensitive - might not work
# Check valid values
set_log_level DEBUG # Correct
set_log_level INFO # Correct
set_log_level 7 # Correct (numeric)
set_log_level INVALID # Won't work
# Verify change took effect
set_log_level DEBUG
log_debug "Should now appear"Problem: Changes made with set_* functions don't persist
Explanation:
This is expected behavior - runtime changes only affect the current script execution:
# Session 1
./script.sh
# set_log_level DEBUG called
# Script ends
# Session 2
./script.sh
# Log level is back to default (INFO)
# To persist changes, modify initialization or config fileProblem: Custom format not showing in output
Solutions:
# 1. Check format string is valid
init_logger --format "%d [%l] %m" # Correct
# 2. Verify you're using correct placeholders
# Valid: %d, %l, %s, %m, %z
# Invalid: %t, %L, %D, etc.
# 3. Check quotes
init_logger --format "[%l] %m" # Correct
init_logger --format [%l] %m # Might be interpreted as separate args
# 4. Verify at runtime
set_log_format "[%l] %m"
log_info "Test message"Problem: Multi-line messages are flattened into a single line
Cause: bash-logger sanitizes newline, carriage return, and tab characters by default to prevent log injection attacks.
Solutions:
# Preferred: Keep the secure default and sanitize input yourself if needed
safe_input=${user_input//$'\n'/ }
safe_input=${safe_input//$'\r'/ }
safe_input=${safe_input//$'\t'/ }
log_info "User input: $safe_input"
# If you fully control inputs and accept the risk (NOT RECOMMENDED):
init_logger --unsafe-allow-newlines
# Or enable it at runtime (NOT RECOMMENDED):
set_unsafe_allow_newlines trueWarning: Allowing newlines can enable log injection and audit log forgery.
Problem: Final log output exceeds the --max-line-length setting
Explanation: The --max-line-length option truncates the message portion before
formatting. The final output includes timestamp, level, and script name added after
truncation, which can push the total line length beyond the specified limit.
Example:
# With --max-line-length 50
init_logger --max-line-length 50 --format "%d [%l] [%s] %m"
log_info "This is a very long message that exceeds fifty characters"
# Output (approx 90 chars total):
# 2025-02-10 15:30:45 [INFO] [script.sh] This is a very lo...[truncated]
# The message is truncated to 50 chars, but prefix adds ~40 moreSolutions:
# Option 1: Account for prefix length when setting limit
# If format adds ~40 chars, use --max-line-length of 60 for ~100 char final lines
init_logger --max-line-length 60
# Option 2: Use simpler format to reduce prefix overhead
init_logger --format "[%l] %m" --max-line-length 100
# Option 3: Disable truncation if precise line length not critical
init_logger --max-line-length 0 # UnlimitedReferences: See Configuration for details on max_line_length setting.
Problem: Strange characters or missing parts in log messages
Solutions:
# Check for shell interpretation of format string
init_logger --format '%d [%l] %m' # Use single quotes
# Verify placeholders are correct
init_logger --format "%d [%l] [%s] %m" # Correct
init_logger --format "%d [$l] [$s] $m" # Wrong - use %
# Test with simple format first
init_logger --format "[%l] %m"# See all log messages including DEBUG
init_logger --verbose
# Or
init_logger --level DEBUG# Start simple
init_logger
log_info "Test"
# Add options one at a time
init_logger --log "/tmp/test.log"
init_logger --log "/tmp/test.log" --level DEBUG
init_logger --log "/tmp/test.log" --level DEBUG --journal# Check if logging functions are defined
type log_info
type init_logger
type set_log_level
# Should show: "log_info is a function"if ! init_logger --log "/var/log/app.log"; then
echo "Initialization failed!" >&2
exit 1
fi# For journal logging issues
logger -t test "Test message"
journalctl -t test -n 1Problem: Logging slows down script significantly
Solutions:
# 1. Reduce log level in production
init_logger --level WARN # Instead of DEBUG
# 2. Disable debug logging for performance-critical sections
set_log_level INFO
# ... performance-critical code ...
set_log_level DEBUG
# 3. Disable journal logging if not needed
set_journal_logging false
# ... fast operations ...
set_journal_logging true
# 4. Use quiet mode if console output not needed
init_logger --log "/var/log/app.log" --quietCause: Module not sourced
Solution:
source /path/to/logging.sh
init_loggerCause: No write permission to log file or directory
Solution:
# Use writable location
init_logger --log "$HOME/logs/app.log"
mkdir -p "$HOME/logs"Cause: Unrecognized log level name
Solution:
# Use valid log levels
init_logger --level DEBUG # Correct
init_logger --level WARN # Correct
init_logger --level ERROR # Correct
# Not: init_logger --level TRACECause: Config file path is incorrect or file has wrong permissions
Solution:
See Understanding Error Messages Without Path Disclosure for detailed debugging steps.
# Verify config file exists
ls -l /path/to/config.conf
# Check it's readable
cat /path/to/config.conf
# Use absolute path
init_logger --config "$(pwd)/config.conf"Cause: No permissions to create directory or file
Solution:
See Understanding Error Messages Without Path Disclosure for detailed debugging steps.
# Check parent directory exists and is writable
ls -ld /var/log/
# Create directory manually with proper permissions
mkdir -p "$HOME/logs"
init_logger --log "$HOME/logs/app.log"Cause: Log file path points to a symbolic link (security check)
Solution:
See Understanding Error Messages Without Path Disclosure for detailed debugging steps.
# Remove symlink and use direct path
rm /path/to/symlink.log
init_logger --log /path/to/actual.log
# Or find where symlink points and use target
ls -l /path/to/symlink.log # shows -> /actual/path.log
init_logger --log /actual/path.logNote: bash-logger rejects symbolic links for security reasons to prevent log redirection attacks.
Cause: File exists but lacks write permissions, or disk is full
Solution:
See Understanding Error Messages Without Path Disclosure for detailed debugging steps.
# Check file permissions
ls -l "$LOG_FILE_PATH"
# Fix permissions
chmod 644 "$LOG_FILE_PATH"
# Check disk space
df -h /path/to/log/directory/If you're still experiencing issues:
-
Check the documentation:
-
Review examples:
-
Test with minimal example:
#!/bin/bash
source /path/to/logging.sh
init_logger
log_info "Test message"- Check your Bash version:
bash --version
# Module requires Bash 3.0 or later- Verify file permissions:
ls -l /path/to/logging.sh
ls -ld /var/log/- Getting Started - Basic setup
- Initialization - Configuration options
- Configuration - Config file troubleshooting
- Journal Logging - Journal-specific issues
- Examples - Working examples to reference