Hacker News new | ask | show | jobs
by mbrock 3945 days ago
It's interesting why shell scripts are seen as so "fragile" or "flimsy." Why would bash be any more inherently flimsy than any other interpreted language? Why would the global mass of Ruby, JavaScript, Perl, Python, Java, C++, whatever be any less fragile? The whole world is held together by duct tape. At least most shell scripts keep it simple.
4 comments

> Why would bash be any more inherently flimsy than any other interpreted language?

I'd say that it at least feels this way, because the "global state" in a shell program depends on a lot more properties of the system than the "global state" of a Python program. C/C++ or even entirely static binaries from Go for example (I'm not a Go expert) all eliminate state being 'imported' from the host machine.

Sure, if the external tools used by the script change, the script's behavior will change... Other languages somewhat solve this with versioned dependencies, but even that's not quite sufficient, which is how come all the rage about reproducible builds. But yeah, good point.
Shell scripts have a lot of implicit dependencies.

They string together other programs with widely differing interfaces. For example BSD sed and GNU sed work very differently, at least when you accidentally use a non-standard option.

Ruby, JavaScript, Perl, Python, Java, C++ all have a stable base vocabulary (core library).

bash doesn't.

Speaking of implicit dependencies, here are a few: env, path, any executable file either in the current directory or in the search path. env = functions and aliases, and can be modified by any shell script. The path is an implicit dependency in the sense any chmod +x files in any of these directories can affect the shell. Which means the shell is also dependent on the file system itself.
True enough, though as soon as you have dependencies, you can't guarantee cross-platform or cross-version portability with those other languages either.
They all come with a dependency manager and the problem of sh (or bash? got your bashisms ready all the time?) is that the moment of introducing dependencies is "immediate".
One of my pet peeves about shell scripts (speaking as a former UNIX admin) is the lack of static typing or test frameworks. So not only is the language less elegant than modern programming languages, but it's harder to test for bugs and you don't even get type safety.
I'm currently in the process of putting together a first version of bash-specs, a Bash testing framework which provides features found in other languages' test frameworks, like

- a DSL for describing specifications

- the ability to mock functions and commands

- detailed, human-readable output

You can find some sample-tests in the spec/ folder (bash-specs eats its own dog food by testing itself ;)).

Dokumentation is lacking and the mocking is currently broken but both will be fixed within the next days.

https://github.com/helpermethod/bash-specs/

Testing might be less of a common practice for quick shell scripts, but it can be done and there's nothing particularly difficult about it, compared to other languages. Especially with "pure" scripts that don't revolve around system effects... which is the case with other scripting languages too.

As for static typing, agreed, though considering that shell is basically a scriptable FFI, real static typing would probably add a lot of complexity? Attempts at "typed shell" don't seem to go over well, maybe due to "worse is better" dynamics.

BTW, re: testing shell scripts: https://github.com/sstephenson/bats

The creator of bup (https://github.com/bup/bup/) also created wvtest (https://github.com/apenwarr/wvtest) to "unit test" any code in any combination of language on any platform. It's actually kind of cheating: all you do in your code is write lines with a specific format, and then the wvthing parses that to display stats.
Shell scripts are normally based on scraping the output of other commands via regexs. Properly made Python or Ruby scripts are not.
If a "properly made" Python or Ruby script uses more advanced parsers, what prevents you from "properly making" a shell script?
A few things:

- Most people who write shell scripts really don't want to write a 'ps' or 'ip' (or for non-Linux, 'ifconfig') replacement. On the other hand, Python and Ruby have libraries that talk to /proc and the network ioctls directly.

- most shell script authors don't even use bash arrays, and higher level data types don't exist. It's hard to represent a C struct in shell. C libraries are therefore exposed to shell scripts by scraping their stdout.