4 ms·
I've had a thought percolating (for many months?) but I haven't tried to phrase it and I'm leery it may sound condescending (this is also more of a public addre
by abathur 6y ago
I've had a thought percolating (for many months?) but I haven't tried to phrase it and I'm leery it may sound condescending (this is also more of a public address than direct response) ...
Shellcheck tends to steer us away from "weird" parts of Bash/shell and will happily suggest changing code that was correct as written. There are good reasons for this (and I still think most scripts/projects should use Shellcheck), but Bash is a weird language, and there's a lot of power/potential in some of the weird stuff Shellcheck walls off.
If I had to nail down some heuristics for working with it...:
- do lean heavily on Shellcheck for writing new code if you're unfamiliar with the language or are only writing it under duress
- don't implement its suggestions in bulk (the time you save on iterating can easily be blown later trying to debug subtle behavior changes)
- don't apply them to code you don't understand (if you have the time and interest to understand it but find yourself stuck on some un-searchable syntax, explainshell may help)
- don't adopt them without careful testing
- do take Shellcheck warnings about code that is correct-as-written as a hint to leave a comment explaining what's going on
- do leave Shellcheck off (or only use it intermittently) if you're trying to explore, play, or otherwise learn the language
- sedatk 6y agoThat advice is applicable to any kind of code analysis tool.
- abathur 6y agoFair :) but I think there's a degree difference here (and this is more about the language than Shellcheck itself). Also, maybe my original phrasing left room for misinterpretation? Shellcheck will happily suggest changes that break working code. I think I've had it happen ~4 times this year? Obviously it varies a little by tool type and ecosystem--it's obviously not much of a surprise if a dead-code analysis tool suggests removing things you can't actually cut, and likewise linters in most languages can point out unused variables/parameters that you can't cut. But I can't recall the last time another tool gave me specific do-x-not-y suggestions that just weren't anywhere close to fungible.
- acqq 6y ago> Shellcheck will happily suggest changes that break working code. Which is OK once it is known. Your example nicely shows that. The flagged behavior is often unexpected, so there where it is expected having shellcheck line that turns off the warning greatly improves readability of the whole script, essentially showing the reader "here is the dependence on non obvious behavior." Where such dependence exists, I prefer to see the "shellcheck" line before pointing to it (by turning that specific warning off exactly in that line). It's then a "vetted" and "explained" line.
- cle 6y agoFor me this is way too much to invest in Bash. Any non-trivial utilities should be written in a real programming language when possible, especially when they are used in a context where they are likely to accrete complexity over time. I’m sure there are good use cases for complex Bash programs, but we should be reaching for something with less footguns by default. (Shellcheck is an amazing utility and I use it for all Bash that I write.)
- abathur 6y agoWhat is? Did I suggest anyone write complex Bash programs? Shellcheck is amazing. As I suggested in the previous post, I use it for most of my own shell scripts/projects, especially stuff I intend to release. But, because shell and Bash are weird and full of pitfalls, I think it's worth making sure people know you can't just Shellcheck-and-ship.
- oblio 6y agoI think his nitpick was you promoting weird bash tricks. They're neat to use but usually a pain for someone else to maintain, as a general rule, don't use them, don't try to be clever unless you're 100% sure that it's code you'll be the only one to see (which can rarely be guaranteed).
- jtchang 6y agoWhat would you suggest for emdedded systems?
- xnyan 6y agolua, all day every day. It’s well understood, slim and plays very nicely with C which is how most embedded dev is done.
- jonahx 6y ago> and there's a lot of power/potential in some of the weird stuff Shellcheck walls off. Can you give an example? Something Shellcheck warns you away from but which, if you used it, would be better (more expressive / more powerful / more whatever) than a shellcheck-approved solution?
- abathur 6y agoIntentional word-splitting is a common one. So, for example: extract_nix_version(){ echo "$3" } get_nix_version(){ # shellcheck disable=SC2046 extract_nix_version $(nix --version) } $ nix --version nix (Nix) 2.3.4 $ get_nix_version 2.3.4 This gets the information without another external utility (grep, cut, sed, awk...) It's well-past bedtime, so for now I'm just leaving the first one I can think of (it's top-of-mind since I Shellchecked it in the last couple weeks... :])
- abathur 6y agoIt's a little contrived in this case, but another common example is a related suggestion for `read -r`: get_nix_version_parts(){ local major minor patch # shellcheck disable=SC2034,SC2162 IFS="." read major minor patch < <(get_nix_version) local -p } $ get_nix_version_parts major=2 minor=3 patch=4
- jonahx 6y agoUsing -r there works fine for me, though your SC2034 complaint is valid, in that it essentially prevents from you from using a very specific built in formatter provided by "local -p". This feels like a rare case, and I'd have no problem doing the "disable=SC2034" there, but I'd add a note explaining why. Even then, one could make an argument (I think I would, actually) that an explicit printf is clearer and more robust. For example, it gives you more control over the formatting, and it doesn't introduce implicit coupling between the output of "local -p" and our function, which in theory could change in the future or be different on different bash versions, etc. I suspect this probability is very low in the particular case of local -p, but still it's not a great practice. Not something I want to give the stamp of approval of inside my code base. get_nix_version_parts(){ local major minor patch IFS="." read -r major minor patch < <(nixv) printf '%s=%s\n' major "$major" minor "$minor" patch "$patch" }