
Shellcheck: a static analysis tool for shell scripts - pyotrgalois
http://www.shellcheck.net/
======
dpina
Just spent some time sending my scripts to this site for it to analyse and see
what it does. I can see that while it wasn't be able to tell me of more
efficient code to achieve my goal (wasn't really hopping for that), it did
spot 1) one liners where some commands are not needed, 2) variables which are
not used, 3) where I should use double quotes to prevent word splitting and 4)
lines where my ssh was eating up my stdin.

What a great sanity check for the days when I'm writing something on my own
without a second pair of eyes to proof-read it.

------
Chico75
Combine it with the sublime text plugin
([https://github.com/SublimeLinter/SublimeLinter-
shellcheck](https://github.com/SublimeLinter/SublimeLinter-shellcheck)) and
you got real time static analysis while without your shell scripts !

------
eridius
Shellcheck is great. The Vim Syntastic plugin already knows about Shellcheck
so if you use Syntastic and install Shellcheck you'll automatically start
getting warnings on your code.

BTW, it can be a little hard to figure this out, but if Shellcheck gives you a
warning that you want to ignore (because you intended to trigger that
behavior), you can put the following comment above the offending line:

    
    
      # shellcheck disable=SC1234
    

where "SC1234" is replaced with the actual error code that Shellcheck gives.

------
Munksgaard
This looks very helpful: bash scripts are notoriously difficult to get right.
I wish it'd suggest best practices like `set -e` and the like though.

~~~
koala_man
The jury's still out on whether `set -e` is worth it.

On paper it sounds like it's equivalent to `on error goto 0`, making a script
fail-fast -- which would have been awesome.

Instead, it makes a script fail sometimes for things that are sometimes
errors. The rules for how and when are unexpected and unintuitive, several
weird cases are described on
[http://mywiki.wooledge.org/BashFAQ/105](http://mywiki.wooledge.org/BashFAQ/105)

If enabling it just granted a free 50% chance of stopping on any given error,
it would have been worth it, but it triggers on false positives as well.

~~~
vetrom
Well, dealing with horrible exception handling is still better than just
silently running off the edge on errors.

Much like any language, you need to read and understand it to be able to truly
write, I think. bash is deceptive in this regard IMO, due to how low its
barrier to entry is.

Now if you want to see some truly horrible code, implement a shell script that
runs in bash and zsh and does exception printing in both.

------
nimrody
The real problem with shell scripts is that they usually tie together a few
external commands and tend to pass information around using the filesystem.

This, together with poor error handling is a recipe for disaster: Problems
with permissions, insufficient disk space, etc. Instead of stopping when
encountering an error, most shell scripts will happily continue break at some
other point in time (or worse - destroy valuable data).

------
grymoire1
The emacs interface is very nice as well, using flycheck

------
reedlaw
I ran it against a deploy script generated by Mina [1]. Only a few deprecation
warnings and notes about using find instead of ls to better handle non-
alphanumeric filenames. I've learned a lot about error handling by reading
Mina-generated scripts.

1\. [http://nadarei.co/mina/](http://nadarei.co/mina/)

------
rtpg
Isn't this a pretty good argument against shell scripts? I feel like we've
advanced far enough in PL research to think of something a bit safer

~~~
xiaq
Time for advertisement! You might like elvish
[https://github.com/elves/elvish](https://github.com/elves/elvish) which
proudly has optional typing and much more well-defined semantics than say,
bash. This is work in progress though.

Advertisement aside, there is some inherit unsafety in shell scripts that
cannot be easily resolved, namely the unsafety involved in interacting with
external commands.

Compared to other scripting languages, the greatest advantage of shell
languages is the convenience of interacting with external programs. However,
at least in Unix, there are few static constraints you can apply to them.
Everything we know is that the program will (probably) parse something in argv
which are just bytes, (probably) take something from stdin which are just
bytes, and (probably) put something to stdout which are again just bytes;
there is no universal method to check that the commands arguments are well-
formed, or the input format is correct, or the output format conforms to a
certain schema without running the actual program. A solution is to define
some kind of static protocols for external programs so that their invocations
can be statically checked, but it's already too late.

~~~
rtpg
I think a decent solution is to have a shell alternative that defines
interfaces for known programs (much like autocomplete scripts do now).

I know ls returns a list of files, so I should be able to use that. I don't
know foo, so it's basically string -> string or whatever, but if an
entrepreneuring spirit does know about foo, he could write an abstraction
layer for it.

The trick is making a simple interface for that

~~~
hyperpape
Also there's a question about whether you can properly deal with option hell.
Parsing every possible output of ls reliably in the face of malicious
filenames sounds...fun.

Edit: It's really impossible to avoid edge cases. Take find: you can't parse
it, because it's just a list of filenames separated by \n. But filenames can
contain just about any character. How do you handle /home/bar\n/tmp?

Maybe you just ignore pathological input, but now you're regressing towards
the state of bash.

~~~
xiaq
Option hell is indeed a problem.

The problem with `find` happens to have a solution (-print0). However it is a
PITA in deal with \0-separated strings in traditional shells, unless you pipe
it to another command that happens to recognize \0-separated strings.

With elvish you can parse the \0-separated strings outputted by `find ...
-print0` into a genuine _list_ \- not lines (which are \n-separated strings)
or \0-separated strings, but real lists that support indexing, iteration, etc.
and there is absolutely no chance that two consequent items will run together
or one item will be treated as two. Imagine how fantastic it is to deal with
that :)

------
ygra
As someone who regularly answers batch file questions on Stack Overflow, I
think this would be invaluable for all the mistakes people make there too.

------
xrstf
This is awesome. As a beginner when it comes to writing shellscripts, this is
my new jshint equivalent.

