Hacker News new | past | comments | ask | show | jobs | submit login
ShellCheck: a static analysis and linting tool for sh/bash scripts (shellcheck.net)
93 points by pmoriarty on Dec 20, 2014 | hide | past | favorite | 20 comments



I still write and maintain a surprisingly large amount of sh code (it used to be bash, but when Ubuntu switched to defaulting to ash, I had to remove the bashisms). Sometimes a shell script is still the shortest line from point A to point B, and it's always there.

But, whenever I work on that code after a long time of not reading it, I'm always afraid I'm breaking something, introducing new bashisms, etc. and have to test it thoroughly across multiple systems to be sure I didn't break something. There is checkbashisms which catches most bashisms, but there's still a lot of weird stuff in shell scripts, and without block or function scope it can be challenging to stay on top of a large shell codebase.

In short, I've been working on more automatic testing (i.e. tests without explicitly written unit tests) of my code lately, and the shell stuff is pretty hard to do that for, compared to Perl and JavaScript. So, this is probably awesome.


My approach to bashisms is to put "#/bin/bash" on the first line unless I'm specifically trying to avoid them. It acts as a declaration of "yes I'm using bash, there are probably bashisms in this code".


That kinda defeats the purpose of my scripts, which are written in sh in order to run on any of our supported systems without any need to install any dependencies first. We can know that there will be a POSIX compatible sh on every system we support.

If I'm willing to make uses install something first (i.e. if it is used after an installation script runs rather than during), I build it in Perl.


What are you using for Perl and JavaScript?


I'm still working on it, but Perl::Critic is good (I've been using it in vim for a while, which checks every time you save), strict and warnings is good (which would be enabled on any new Perl program, but I'm working with a 15 year old codebase, so enabling these automatically creates a bunch of new failing "tests" that need fixing). There's a few different ways to use Perl::Critic in tests, the most promising seems to be Test::Perl::Critic::Progressive, which allows gradual introduction of Critic-friendly code without turning your whole smoker page red. (Which for me, is a problem...we'd have hundreds of failing tests, which would be overwhelming and make it hard to spot tests that will affect users.)

Devel::NYTProf is great for spotting performance regressions.

And, since we're pushing out HTML as the result of our application scripts running, I've been working on integrating HTML::Lint (I had to patch it to allow HTML::Pluggable::HTML5 to work, but I've sent a pull request to Andy, so the next version will likely support HTML5) into our test suite. This will tell us if any script breaks in such a way that it produces invalid HTML.

For JavaScript, jslint and jshint exist. I haven't started integrating or experimenting with either, yet. Our JavaScript is pretty minimal at the moment (a few thousand lines vs 500k+ lines of Perl), so it's not a priority compared to the Perl, and the Perl stuff is still in progress. JavaScript also has strict, which can catch some common problems, like the global scope "this".


Some help on spellcheck like stuff in perl would be perl-critic and perl-tidy.

Beware using this on old code though.

http://search.cpan.org/~thaljef/Perl-Critic-1.123/lib/Perl/C... http://search.cpan.org/~shancock/Perl-Tidy-20140711/lib/Perl...

I know nothing on javascript.


For javascript, eslint (http://eslint.org/) is now what I use. It's more configurable than what has come before it and has good, clear documentation.


For JavaScript, I like jshint: http://jshint.com , as I heard jslint was too opinionated.


This looks very useful, and there are some things on there I didn't know you had to do in bash. Here's a SublimeLinter plugin: http://github.com/SublimeLinter/SublimeLinter-shellcheck


Available as a Docker ShutIt module if you don't want to install it:

docker run -t -i -v /path/to/code/code.sh:/code.sh imiell/sd_shellcheck shellcheck /code.sh


There is this tools as well developed in OpenStack: https://github.com/openstack-dev/bashate


Awesome, thanks for this.


Cool tool but I'm really confused by the name choice. Sure choosing names is hard but by using a name of a common tool for an unrelated tool will just cause problems for people looking for bash spellcheck tools.


I'm the author! Since naming the tool, I've discovered that a significant segment of the population (such as yourself) repeatedly misread the name as "spellcheck".

The name is actually "shellcheck" (shell + check).

It's a fascinating effect because people seem to be very consistent in whether they read it one way or the other. If linguists don't already have a name for this sharp, binary classification, I propose "n-Gram staining".


Some ideas for the future:

Add support for the Firehose XML output format:

https://github.com/fedora-static-analysis/firehose

Checks for features that are specific to one shell (bashisms etc) when used with POSIX #!/bin/sh.

Checks for features that aren't implemented in the desired shell (for running on busybox sh for example).

Check for the various issues listed here:

http://mywiki.wooledge.org/BashPitfalls


Thanks!

ShellCheck already checks for bashism if the script is declared with #!/bin/sh, and finds most of the ones that checkbashisms does along with a few others. It's geared towards POSIX compliance though, and doesn't know which non-POSIX feature are available in e.g. busybox sh.

There is also some limited support for warning about features not available between non-POSIX shells, such as trying to use zsh =(temp files) in bash or bash ;;& case continuations in zsh, but this isn't as much of a focus as POSIX checks since it's not a common source of issues.

The Wooledge pitfall list was the original implementation checklist. About 38 out of the 46 are already covered in one form or another.

I haven't heard of Firehose before, but if you want to use it right now you can run shellcheck with -f gcc, to get gcc style error messages that Firehose can already parse.


Yes, I experienced this as well.

The way the human brain works is crazy. You take the very very strong expectation of reading "spellcheck", and then you swap out a "p" for something that looks a lot like an upside-down "p"...and it refuses to read it as anything else.


Thanks for clearing that up for me, I was reading it as "spellcheck" the whole time!


Looks like a pun on the shellshock bug.


shellcheck is significantly older than shellshock, in terms of naming date anyways.

https://github.com/koalaman/shellcheck




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: