Logging with shell script - catch STDERR to log with timestamp
1
vote
2
answers
2104
views
**SOLVED:**
A few months ago, I gain interest in logging in shell scripts.
The first idea was a manual logging function such as this one:
add2log() {
printf "$(date)\tINFO\t%s\t%s\n" "$1" "$2" >>"$logPATH"
}
But I wanted to automatise it, such as that STDERR would be automatically logged.
It's been some time now that I've found a satisfying answer, and I'm finally taking the time to share it.
---------
For each of my shell script, I now use a "main.sh" that holds the log functions as well as the config (setting up log and config files).
Here's what it looks like:
#!/bin/bash
###################################################################
# MY HEADERS
###################################################################
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~Global vars
mainScriptNAME=$(basename "$0")
mainScriptNAME="${mainScriptNAME%.*}"
mainScriptDIR=$(dirname "$0")
version="v0.0"
scriptsDIR="$mainScriptDIR/SCRIPTS"
addonsDIR="$mainScriptDIR/ADDONS"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOGGER FUNCS
manualLogger() {
# $1=PRIORITY $2=FUNCNAME $3=message
printf "$(date)\t%s\t%s()\t%s\n" "$1" "$2" "$3" >>"$logFilePATH"
}
stdoutLogger() {
# $1=message
printf "$(date)\tSTDOUT\t%s\n" "$1" >>"$logFilePATH"
}
stderrLogger() {
# $1=message
printf "$(date)\tSTDERR\t%s\n" "$1" >>"$logFilePATH"
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOG & CONF
createLog() {
# code to set and touch logFilePATH & confFilePATH
manualLogger "INFO" "${FUNCNAME}" "Log file created."
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~MAIN
#
createLog
#run scripts
{
#
source "$scriptsDIR/file1.sh"
doSomthing1
doSomthing2
#
source "$scriptsDIR/file2.sh"
anotherFunction1
anotherFunction2
...
} 2> >(while read -r line; do stderrLogger "$line"; done) \
1> >(while read -r line; do stdoutLogger "$line"; done)
In other words:
- all scripts/functions I want to run are in separate files in a ./SCRIPTS folder (so my main.sh is almost always the same)
- I call all these scripts in a group { ... } to catch their STDOUT and STDERR
- their STDOUT and STDERR are redirect to their respective logger functions
The log file looks like this (examples of one manual logger, one STDOUT logger, one STDERR logger):
Lun 23 mai 2022 12:20:42 CEST INFO createLog() Log file created.
Lun 23 mai 2022 12:20:42 CEST STDOUT Some standard output
Lun 23 mai 2022 12:20:42 CEST STDERR ls: sadsdasd: No such file or directory
The group makes it that ALL output is gathered in log.
Instead, you obviously could use the redirect 2> >(while read ...
and 1> >(while read ...
as you wish for each function.
Such as doSomthing1
as its STDOUT and STDERR going to log, but doSomthing2
only has its STDERR redirect.
Asked by YvUh
(31 rep)
Feb 28, 2022, 04:04 PM
Last activity: Aug 10, 2025, 04:05 AM
Last activity: Aug 10, 2025, 04:05 AM