Live data from Hacker News

Bash Debugging

wizardzines.com

71–78 of 78 posts

Re: Bash Debugging

#71

Earlier quoted context omitted.

I find such reasoning backwards. Indeed, shell scripting is not friendly to debugging. But ensuring correctness of shell scripts is essential: usually, they touch part of your "$HOME" or system folders and do tons of I/O, some of it destructive. I find it baffling to see people write careless scripts; sometimes using `rm` for cleanup with unquoted parameters, or much worse, dangerous uses of `mv`.

I believe OP's point was that any shell script complex enough to require debugging should not be a shell script any more.

I hear this argument occasionally and it’s very contextual. While it’s certainly possible to rewrite any given shell script in Python, Rust, or whatever language you prefer there are some things which are just clearer in Bash.

I wouldn’t want to write an entire application in Bash, but equally I wouldn’t want to write a script which does relatively simple file operations in Python. Bash is a language which has been honed over many decades for precisely that sort of thing, and so can communicate what’s happening far clearer than Python does in my view.

Re: Bash Debugging

#72

Is there a reason bash is still the de facto shell scripting language other than sheer momentum of legacy? I'm able to get what I need done in it, but it's clunky and the syntax is horrid. I guess it forces you to move to a proper language once scripts grow to a certain size/complexity, so perhaps it's by design?

Are you sure it's bash? Most scripts on FreeBSD's are written for sh, which I feel is much more widely supported due to being part of the POSIX standard. Bash is just popular I think.

FreeBSD's /bin/sh is based on ash, like NetBSD's, although I'm not sure how much they have in common these days. dash was forked from NetBSD's version of ash and then simplified considerably and fixed up to be fully (? or at least mostly) POSIX compliant. A while after that NetBSD's shell also had a bunch of POSIX fixes. I'm not sure how FreeBSD's shell is in terms of strict POSIX compliance.

In my opinion, bash has two things (at least vs NetBSD's shell, possibly a few more vs POSIX) that make the average shell script (that I write) much easier. The first is &> which makes it easy to redirect both stdout and stderr to a file for logging. The standard 2>&1 can work but needs to be placed correctly or it doesn't work. That place isn't always the obvious place like it is with &> and running bash seems much preferrable to me than figuring that one out.

The second is ${var@Q} which prints var quoted for the shell, which is nice to use all over the place to make sure any printed file names can be copied and pasted.

My sense is that targeting POSIX is usually done for maximum portability or for use on systems that don't have bash installed by default. However, bash is quite widely available even if not by default and very widely used so I wouldn't say it is unreasonable to look at bash as the de facto standard and POSIX and other shells as being used in more limited circumstances.

Re: Bash Debugging

#73
Very useful is:

    PS4='+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:L${LINENO:-}:   '
When using `set -x` this makes it so that it shows the filename, function name, and line number. Which in larger Bash scripts can be quite handy in debugging.

Re: Bash Debugging

#74
post #73

Very useful is: PS4='+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:L${LINENO:-}: ' When using `set -x` this makes it so that it shows the filename, function name, and line number. Which in larger Bash scripts can be quite handy in debugging.

WOW! Thanks! Power user of BASH for a long time and I did not know this.

Re: Bash Debugging

#75
post #4

I always put set -euxo pipefail at the top of my bash scripts. It makes some conditional testing more difficult but it has paid for itself many times over just because of pipefail

https://mywiki.wooledge.org/BashPitfalls#set_-euo_pipefail

Thanks for the reference! Seems like a really good resource. I disagree with the reasoning about pipefail though. If I expect a command to return non-zero exit code I'd rather be explicit about it.

Re: Bash Debugging

#76
post #54
post #39

Earlier quoted context omitted.

grep has a bad interaction with set -e, since it (infuriatingly) exits with 1 if no lines are matched.

You can `set +e` before and `set -e` after every such command. I indent those commands to make it look like a block and to make sure setting errexit again isn’t forgotten.

But you probably still want an error if the input file does not exist. To handle grep correctly in a robust manner requires many lines of boilerplate, set +e, storing $?, set -e, distinguishing exit values 0, 1, and 2.

Re: Bash Debugging

#78
The trap command with printing the lines didn't work.

Had to change it to drop the parantheses, then it worked, like this

trap 'read -p "[${BASH_SOURCE:-}:${LINENO:-}] ${BASH_COMMAND:-}"' DEBUG

Post reply on HN