5 ms·
Colodebug: a simple way to improve Bash script debugging
- usrme 5y agoHats off to the author! I've long been a proponent of the colon command due to its no-op properties, but this just takes it to another level. One would definitely have to provide add comments to the ":" function as there seems to a good amount of esoterica contained within.
- gforce_de 5y agoI see 2 problems here: major: it does not work on POSIX shells, because ':' is not a valid function name and minor: the function itself should be changed to use the builtin 'case' instead of the bashims [[ ... ]]
- jbbarth 5y agoHow is the POSIX non compliance a major problem? Does it have practical impacts when writing scripts that are not meant to be portable to other systems/shells?
- gforce_de 5y ago"Stick to portable constructs where possible, and you will make somebody's life easier in the future. Maybe your own."
- c0l0 5y agoHey, thanks for taking the time to read and commenting! :) Problem #1 (at least for the "advanced" part of the article's suggestion) is unfixable unless you boil the ocean and change the POSIX spec. I tried to make that clear in the prose, but might have failed at it. It's also the reason why I chose the title to refer to `bash` scripts in particular. Problem #2 becomes less relevant once you realize that problem #1 completely overshadows it. And in `zsh`, where you can also redefine `:` to invoke a custom function, tests via `[[` also work just like they do in bash.
- gforce_de 5y agowhat seems possible is: #!/bin/sh alias :=mydebug mydebug() { printf '%s\n' "$\*"; } foo=1 : this is a debugable comment bar=2
- jph 5y agoClever work, thank you for sharing! Here's how I do the equivalent with a POSIX function to print a message to STDOUT: out() { printf %s\\n "$*" }
- kwhitefoot 5y agoBrilliant! The most personally useful thing I have seen on HN in ages. And very nicely written too.
- timrichard 5y agoThat's a nice article. It prompted me to mention BashSupport Pro which I installed a couple of months back. It's a plugin for JetBrains IDEs that allows step debugging and variable inspection for Bash scripts in the same way as other supported languages. https://www.bashsupport.com/ https://www.bashsupport.com/
- kwhitefoot 5y agoUnfortunately it doesn't work if you forbid unbound variables with set -u. Like this (as suggested in the Unofficial strict mode article: https://news.ycombinator.com/item?id=8054440 https://news.ycombinator.com/item?id=8054440): $cat z #!/bin/bash set -u # fail if unset variable is used if [[ -n ${COLODEBUG} && ${-} != *x* ]] then :() { [[ ${1:--} != ::* ]] && return 0 printf '%s\n' "${*}" >&2 } fi echo hello $./z ./z: line 10: COLODEBUG: unbound variable $ The -n test should look like this: if [[ -n ${COLODEBUG:-} && ${-} != *x* ]]
- c0l0 5y agoYou are right, this change makes the drop-in snippet more robust: If one issues `set -u` before trying or deciding whether to redefine `:` (which would also be the effect of invoking the interpreter with the `-u` option), the variant presented in the article breaks. If the shall-we-redefine-: check has already been performed before `-u` is in effect, the alternative implementation of `:` itself will work fine. It's kinda unfortunate this slipped through, because before I tried to "formalize" this little trick in the article yesterday, I definitely remember having used variants that guarded against this little nasty trap you now independently rediscovered ;) Would you mind me updating the article accordingly, and crediting your HN account name/profile in the changelog? Thanks a lot for your rigorous reading and very constructive feedback! :)
- kwhitefoot 5y ago> Would you mind me updating the article accordingly, and crediting your HN account name/profile in the changelog? No problem. I'm retired now so my name doesn't appear in changelogs as often as it used to!
- kwhitefoot 5y agoI have another couple of suggestions. The first suggestion is to add export -f : just before the fi so that it is available to scripts called from the main script. The second is to add local IFS=" " # Insulate : from changes to IFS before the printf. because if I didn't then each word of the comment would appear on a separate line like this: :: a b c instead of this: :: a b c the reason for this is that I had defined IFS="/n/t" as suggested by the Unofficial Strict Mode.
- throwaway984393 5y agoSo basically it's a "_debug" function using the ":" function name and double bracket syntax