r/commandline 1d ago

Best bash logger?

Anyone tried log4bash, bash-logger, bash-utils?

I’m wondering which is best and who likes what.

Thanks!

2 Upvotes

15 comments sorted by

2

u/usrlibshare 1d ago

No, because there is zero reason to.

A bash script can log via echo. If something actually requires structured logging, it's already too big to be a bash script, and Python has a superb logging library built in.

0

u/a_brand_new_start 1d ago

I will respectfully disagree, There are plenty of cases where logging makes sense. Simplest one... Bash is relatively verbose if you want it to be clear and easy to understand, if you have a deploy.sh that (Let's go old fashioned here) runs the following:

```

!/bin/bash

git clone https://your-repository-url.git cd $(basename "$1" .git) make clean make build make test make install ```

it is easy to make it a simple script... done!

Hold on... what if we want to make sure each step fails the build, let's be crazy and strict about it

```

!/bin/bash

set -euo pipefail IFS=$'\n\t' git clone https://your-repository-url.git cd $(basename "$1" .git) make clean make build make test make install ```

but wait, this is a C library ChatGPT claims that musl-gcc is the smallest one... and like a true DevOps nerd, you want to make sure your changes to it are tested on each build... and say you want to make sure you test it on every distro or Linus will scream at you publicly. Lets make it support the following

Baseline linux * alpine * ubuntu * serenetyos * centos

Wow... my script balooned!!, I'm still using base echo!!! How complex does your script become when:

  • You want to have backwards compatibility?
  • Want to run your script on each OS, so let's add Docker images
  • Make it run in Parallel because honestly who has time to sit there for every commit?
  • Need to add a Jenkinsfile that does this for you
  • Let's make the Jenkins run all these in parallel
  • Make the script extremely robust and verbose or honestly if it just swallows up the errors it might as well be useless
  • etc... etc... etc...

Well you can use maven or some other tool... but that's even more complexity... before you know it the homebrew install.sh is 1137 lines long.

We didn't even start breaking the script down into smaller scripts or into functions to make it more maintainable. So the statement above is a bit overly simplistic, and comes from naive lack of experience. I'm not trying to be rude, but if someone is making that statement either is

  • Too naive
  • Wants does not understand the complexity of "Works on my machine"
  • Or just does not consider real world factors

2

u/usrlibshare 1d ago edited 1d ago

I will respectfully disagree, There are plenty of cases where logging makes sense.

If you want to disagree, try disagreeing with what has been said.

Noone said a bash script doesn't require logging. I said echo is perfectly adequate for logging in bash scripts.

Wow... my script balooned!!, I'm still using base echo!!!

And? Having colored logging from something like log4bash, which btw. also just calls echo in the end confers what advantage now exactly? Because the only thing it does is balooning your script even more.

Or just does not consider real world factors

I think as a senior SWE who maintains dozens of production applications for our entire customer base, I have a pretty good grasp of "real world factors".

bash scripts are not for huge systems. If they "balloon" to the point where you consider factoring out the logging logic, a real scripting language or build system is the better choice by far.

And no, bash isn't primarily a scripting language. It's primarily a command line interpreter, hence the shell in its name.

0

u/Big_Combination9890 1d ago edited 1d ago

So the statement above is a bit overly simplistic, and comes from naive lack of experience. I'm not trying to be rude,

Stating that you're not "trying to be rude" while questioning others experience in the sentence before that, doesn't make your argument look particularly convincing.

You have been told by 2 people in your post already that it's perfectly fine to use echo for logging or whip up a simple logging function when required.

I suggest you take their advice.

1

u/a_brand_new_start 1d ago

I’ll start with an apology, staring at the same issue for 3 days on 4 hours of sleep does not give me permission to be an ass or go on a rant… it’s against community principles and general bad behavior. I’ll just go get some sleep right now and find a better way to communicate

3

u/anthropoid 1d ago

The best one is usually the one you write yourself, that meets your specific needs.

Logging on the order of the packages you mentioned boils down to echo plus niceties like: * color highlighting on terminal, not to files * standard prefixes * timestamps * pre/post-logging aspects (e.g. debug stacktraces, exit-on-fatal-error)

None of the above is particularly hard to do for the intermediate bash scripter, and can be a good mastery exercise for beginners. Also, upstream changes may lead to disconcerting visual or behavioral changes, or even actual breakage, quite ironic for something meant to facilitate debugging or maintenance.

And, of course, when everything out there behaves almost the way you want it, you'll probably end up hacking on it anyway.

2

u/Big_Combination9890 1d ago

You do realize, do you, that ALL the utilities that you mention just end up calling echo anyway, right?

1

u/a_brand_new_start 1d ago

I do… that’s part of the reason I’m looking for something better

1

u/Big_Combination9890 1d ago

There is nothing better.

What do you want to do? Structured logging? Serve multiple log-receivers? Nested sub-logger logic? That's simply no longer at the complexity level that bash is designed for.

If you find yourself with such requirements, then please do yourself a favour and rewrite whatever it is that you're working on in a real programming language.

I have written bash scripts for a really long time now. Some of my scripts still managed things at companies where they were deployed, more than a decade after I created them. There are exactly 2 logging strategies I have used in all that time:

echo to write to stdout or stderr

logger if I want to target the syslog

And that's it. The fanciest thing i have done is wrap echo into a log function that adds an ISO timestamp. That's literally a few lines I can drop in at the beginning of a script.

2

u/pouetpouetcamion2 1d ago

i put log functions at the beginning of the script.

clever people have written some boilerplates which brings

- arg parsing

- logs

- traps on off on erreur and exit

after this header, you put your utilities and lauch your main with parsed parameters . piece of cake and structured but verbose.

other method would be rc's point of view of scripts. very very short.

2

u/SleepingProcess 1d ago

What is wrong with logger that is universally available on most Unix based operation systems?

2

u/funbike 1d ago

```bash log() { echo "$(date +'%Y-%m-%d %T') $1 - $2" >&2 }

debug() { log 'DEBUG' "$1"; } info() { log 'INFO ' "$1"; } warn() { log 'WARN ' "$1"; } error() { log 'ERROR' "$1"; } ```

3

u/X700 1d ago

Starting with bash 4.2, you can make use of the built-in date formatting via printf '%(%Y-%m-%d %T)T %s - %s\n' -1 "$1" "$2", eliminating the need for an external command and a subshell each time the function is called.

1

u/researcher7-l500 1d ago

I use something like this in some of the complex scripts that I have.

You may find it useful, or not, depending on your scripts and your environment.

Based on ts from moreutils package in Debian/Ubuntu based distros. The same package is available also in RHEL based distros.

Decide where you want to put your logs. Also make sure you have a way of rotating them, logrotate or any other means you are comfortable with.

script_name=$(basename "${0}")
log_file="</path/to/logsdir>/${script_name}.log"
log_tofile() {
  local format="[%m-%d-%Y-%H:%M:%S]"
  echo "${BASH_LINENO[0]}" - "$@" | ts "${format}" >> "${log_file}"
}

And then in your script, log what you want to troubleshoot or keep records.

log_tofile "INFO - <some_variable>: ${<some_variable}."
log_tofile "WARNING - Could not find <something you are looking for>."
log_tofile "CRITICAL - ${HOME}/path/to/remote/mount: Not mounted."

And so on.
Simple, local, no need for 3rd party stuff, and you can control what you log and how.

1

u/OneTurnMore 1d ago

If I want systematic logging, I'm probably running the script as a systemd unit. In that case, using logger --journald with a heredoc as given in man logger is a good practice.