Error Handling in Bash: 5 Essential Methods with Examples
Posted by jsdevspace@reddit | programming | View on Reddit | 53 comments
Posted by jsdevspace@reddit | programming | View on Reddit | 53 comments
eocron06@reddit
How to handle errors in bash: use python.
tes_kitty@reddit
A language where indentation is part of the syntax and where the syntax changes between major releases?
jug6ernaut@reddit
I am not a fan of python, but it is light years ahead of bash in every conceivable way.
The ONLY thing bash has going for it is it is ubiquitous.
tes_kitty@reddit
It depends on what you want to do. Most automation used in daily work can be done easily in bash, especially if you use the special bash features.
jug6ernaut@reddit
The newer bash features are definitely an improvement. In my experience tho most env/img’s have very old versions. So you are left developing against the least common denominator which usually for bash is pretty bad.
tes_kitty@reddit
As soon as you have bash 4.0 or better you're good for most features.
I found especially the parameter expansion tricks very useful.
shevy-java@reddit
And why could people not use ruby or python?
In fact: I use ruby literally for everything. It is the ultimate glue over C really. I also wrote a bash-replacement shell in ruby (syntax-wise it can accept most of what bash can work with, excluding some esoteric syntax I don't want to re-create / clone).
tes_kitty@reddit
> And why could people not use ruby or python for automation?
ruby might not be present on the system... And why use an extra language if I already have everything I need with bash and the usual collection of shell tools?
iamnotalinuxnoob@reddit
Still better than bash :)
tes_kitty@reddit
Uhm, no. I find python annoying, for the simplest things you need to import some module.
radiocate@reddit
Only if you're too lazy to figure out how to do it with the rich, powerful standard library in python.
tes_kitty@reddit
Hey, you need to import a module for something as basic as regular expressions.
radiocate@reddit
Are you taking issue with the literal
import
statement, having to write lines of imports to pull code into the script you're writing? Or 3rd party modules you install with pip?tes_kitty@reddit
Both. Why is something that is as basic as regular expressions not part of the language but needs an import?
shevy-java@reddit
That's mostly a trivial change really. I am sure some PEP can change that in python if they want to. Or people can just use ruby. Either way I think it is still such a small complaint compared to having to use bash in general as a "programming" language interface, through shell scripts.
tes_kitty@reddit
bash, especially if you use the special features like parameter expansion, is surprisingly easy to use for writing scripts.
Capable_Chair_8192@reddit
Is there a language where you don’t need to do that?
tes_kitty@reddit
In PERL you can do a lot of things (like regular expressions) needed for daily use before you need to start importing modules.
a_printer_daemon@reddit
RegEx handling in Perl was amazing. I wish more dynamic languages chose to model it's syntax there.
tes_kitty@reddit
Yes... I often used the regex in the if statement and there added backreferences so when the pattern matched and the code inside the if block got executed, I already had all data I wanted from the input data in $1, $2, $3 and so on ready to use. Saved soo much work.
Is there an equivalent in python for this?
shevy-java@reddit
In python I think it is covered via import re. I use ruby more frequently though; it's closer to my mind than python. I think both languages are great though. I forgot whether one can omit import re in python or not; been a while since I last used regexes in python.
tes_kitty@reddit
Yes, the module you need is 're'. But my question was whether you can use that neat PERL trick that when the pattern matches, you already have what you want to use from it waiting in variables for you. No more need to extract it with extra commands.
shevy-java@reddit
Ruby got you covered there.
a_printer_daemon@reddit
Huh. May have to look into it. After Perl I moved to Python for most of my scripting needs. Never really investigated Runy thet thoroughly.
shevy-java@reddit
In ruby too. I think in many languages you can.
The comparison is more between bash, and better real languages, not just between bash and python.
TomWithTime@reddit
Bash lol
shevy-java@reddit
For which functionality?
Also you can kind of build up a REPL evaluator by default, such as in mruby. Use it like busybox. Or, you simply put everything you want into a file that gets loaded automatically. It's literally then just one line of require (that file) or import (in python). You can use that ENV variable to point to custom files too, even in python. I know that because this is what happens when I start up python. In ruby this also works fine, I require tons of things when irb loads for instance.
What are the simplest things you need, though?
tes_kitty@reddit
I tend to use regex almost everywhere. No problem in PERL for example, it's part of the base language.
KrakenOfLakeZurich@reddit
Which has proper
try-catch
, data types and data structures (instead of treating everything as a string), functions that can actually compute and return useful results, syntax that is much less brittle than Bash, etc. etc. etc.Sorry. But Bash just sucks for scripting/programming.
Unfair-Rip-5207@reddit
But bash is something you must use only for scripting not programming, and bash is very good at that.
Syntax may be hard but I still prefer bash over python for simple scripts, especially for sysadmin stuff.
edgmnt_net@reddit
It's not that good for scripting either, whatever that means. Most scripts end up being either badly broken or doing horrendous amounts of quoting. We could definitely design a better language for that.
KrakenOfLakeZurich@reddit
I find the line between "scripting" and "programming" not very clearly drawn. Where does one end and the other begin?
Bash/Shell scripting quickly becomes a pain, as soon as I have to extract some piece of data from a previous output and start making decisicions based on that. E.g. something along the lines of:
This becomes needlessly hard, when all the language supports is string-type and the only way to extract some info is
grep
ingawk
ward.I mean, no doubt it's doable and I'm almost sure, somebody will post a solution to this, just to prove me wrong. But I'd still rather script this in a language, where the process list isn't some text but a proper list of "process" objects with typed properties like "name", "mem_size", "cpu", etc.
syklemil@reddit
Yeah, imo
jq
helps extend the manageable complexity of bash, but if I actually have to think about arrays or how bash splits strings or start having functions and nested control structures … it's likely safest to port it to python while it's still somewhat manageable.At this point I mostly use bash as a sort of weird config file. Just a bunch of env vars getting set before running the app.
tes_kitty@reddit
My daily experience differs. I have a lot of bash scripts that perform all kinds of automation tasks reliably.
And you want to calculate math stuff in a script? Easy, add a proper call to 'bc'.
shevy-java@reddit
I never found indentation to be a real issue in python; the only exception was that I can not easily copy/paste the xorg-buffer into it, whereas ruby does not care (via irb). But that's such a small aspect to consider, IMO. My bigger complaint with python is explicit self. I hate that a LOT. In ruby I don't have to worry because ruby knows where self is at all times, without me having to micro-tell it. One trade off is that I have to use "end" in ruby - I'd like to be able to omit it, at the least on a per .rb basis, but it's also not the end of the world either.
Syntax change can be a problem indeed, but python scripts tend to be cleaner than bash scripts, so there is a trade off, and the trade off means python still beats shell scripts hands down really.
tes_kitty@reddit
I prefer bash and find them easy enough to read. Python lacks a lot of visual clues when reading a script. Like the '$' in front of a variable name like in PERL or shell scripts.
a_printer_daemon@reddit
3.0 provided a much needed fix for syntactic and semantic inconsistencies. The late 2.X versions moved towards the features of 3.0, and tools were available to make the transition easier.
Personally I like the idea of our languages evolving vs. becoming a confusing hodgepodge of ideas collected over the course of decades. (Looking at you, C++.)
tes_kitty@reddit
It just means that if you have a lot of complex scripts written with the old version, you need to keep the old version around indefinetly. No one wants to migrate something that works, because it WILL cause problems and eat up your time until you fixed all of them.
3.0 could have fixed that 'indentation is part of the syntax' design flaw, but unfortunately didn't.
a_printer_daemon@reddit
By 2021 Python2 had drifted to about 5% share of Python development.. The numbers don't really support your assertions.
There is also no reason why you couldn't maintain a separate interpreter for other versions. I have multiple versions living side-by-side in
usr/bin
or something, and you can still download versions all the way back to 2.0.1.Because we largely don't consider it a flaw, it is a different approach that results in a very clean syntax.
Thst is sort of like saying Haskell's omission of Lisp-style parentheses is a design flaw. It isn't. It is a design choice that makes the code very clean and readable.
tes_kitty@reddit
I don't mean development of new stuff but use of existing, already written scripts.
But if indentation is used to mark code blocks, why do you still need the ':' as part of this as well?
a_printer_daemon@reddit
I know. I tackled that as well. Keep them, lol. The interpreter is still right there.
Why not? The colon don't look out of place to me, and differentiates control structures (which necessitate one or more additional lines) from other lines of code.
It also isn't an entirely unconventional syntax in pseudocode.
You are welcome to dislike Python and, while there are points of any language that are probably worth discussing/fixing, I dont think you've pointed out any specific inconveniences or syntax/semantic issues in Python that the majority of the community would find objectionable.
tes_kitty@reddit
To me it does. It doesn't make sense there, it's not a block start marker since that is indicated via indentation. It's also not a line end marker since it only happens on some commands. So what is it good for?
a_printer_daemon@reddit
But it clearly is a marker that, along with indentation, indicates the start of a block. You may dislike thst it was chosen for this purpose (or thst any choice was made for that matter), but you can't claim it doesn't serve a syntactic purpose.
Again, you are welcome to dislike Python, but this is an obscenely strange and minor nit to pick.
Pesthuf@reddit
Python's syntax could change 5 times per month and it would still be more intuitive to write than bash.
Excellent_Tubleweed@reddit
And everyone, for the love of god, install shellcheck. https://www.shellcheck.net/
Because it will help most people write better bash. Or at encourage you to least use it carefully.
Shellcheck can be integrated into most editors and IDE's.
Take the first step, the mind you save might be your own.
ben0x539@reddit
Surprised this doesn't point out the huge
set -e
gotcha where it has no effect when you're dynamically inside anif
-condition or the first half of a||
.You'd expect the
echo after false
to not go off becausefalse
fails and you literally just said to exit on failure, but it does! Every time!CramNBL@reddit
Great short, concise article.
These Python nerds must understand that Bash scripts becoming unwieldy after a few hundred lines is a feature, not a bug. I've seen too many 2000 line Python files that became way too important but totally buggy and unmaintainable.
I'll take a 50-100 line Bash scripts here and there that works for years and years, and can easily be identified as obsolete at some point and then safely deleted. Over those unwieldy Python scripts that depends on the intepreter being Python 3.7-3.9 and potentially even some non-std modules.
Also you wanna skip on the Python installation if you have an embedded target that needs a minimal (think 50 MiB) distro, in that case Bash could still be viable.
shevy-java@reddit
Some shell scripts are somewhat elegant. I liked the GoboLinux scripts or the old GNU Sorcery distribution "recipes". But I hate writing and maintaining shell scripts. I gave up on that quickly. Anything that can be done in e. g. ruby or python is a no-contest for me when compared to shell scripts. My time is too limited to waste with bash as a programming "language" (through shell scripts).
For embedded use you can e. g. use mruby and it would be acceptable still, as well as much more convenient than bash.
CramNBL@reddit
Well I use bash for embedded linux platforms (built with yocto). I try to write scripts that are posix compliant but if they are a bit more complicated I write them for bash.
danadam@reddit
But not when the command is inside a bash function and that function is called in
if
,&&
,||
or$()
.syklemil@reddit
At this point I just start my bash scripts with
set -euo pipefail
as a sort ofuse strict;
. After the whole "accidentally wipe people's $HOME" thing Steam went through I hope
-u` has become pretty standard.As far as verbose mode and dates in log lines go, for me that's a sign this script has graduated and should be in Python or some other language with a logging facility, not just
echo
with a$(date '+%F %T')
slapped in.IMO bash scripts should be small and simple, and if you get the feeling it isn't going to stay small and simple, rewrite in Python while it's still somewhat simple.
shellcheck
also helps keep the weirdness in bash to a minimum. The feeling of opening a dysfunctional bash script and finding that it is full of ambiguities is one I won't miss.shevy-java@reddit
Or we use a proper programming language.
Unfair-Rip-5207@reddit
Nice article, I already do all this but nice cheat sheet :)