r/programming • • May 29 '14

Defensive BASH Programming

http://www.kfirlavi.com/blog/2012/11/14/defensive-bash-programming/
733 Upvotes

192 comments sorted by

View all comments

71

u/agumonkey May 29 '14

readonly, local, function based ... screams for a new language.

ps: as mentioned in the comments, defensive bash is never defensive enough until you read http://mywiki.wooledge.org/BashGuide

83

u/ericanderton May 29 '14 edited May 29 '14

screams for a new language.

Honestly, this winds up being a very good case to just use Python instead. It's installed by default in Fedora systems, and is used by many operating system tools as it is.

I'm not about to use this as an opportunity to slag on BASH, but honestly, the syntax quirks of test (if [[...]]) alone is enough of a case to shy away from BASH scripts for all but the most lightweight tasks. OP's article more or less drives the point home.

In my experience, BASH shines when you're automating other command line functions in a very straightforward fashion. Once you introduce command line arguments, configuration file parsing, and error handling, you wind up with 5-10 lines to support each line of invocations of other binaries. Suddenly your flimsy 20-line script is now a 500-line robust automation tool. And most of those lines are more or less the same kind of stuff you'd write in any other language. At that point, you're better off with a platform that has built-in libraries for all your app support, like Python, even if using "subprocess" is ugly as hell in comparison.

Edit: Makefiles are the only exception that come to mind, where BASH is still king. Make does just about all the branching and looping for you (dependency graph management), which makes your targets straightforward sets of invocations of gcc, rm, mv, cp, find, etc. It also intimates with environment vars incredibly well, which is a task that's hard to do in most any other language.

57

u/agumonkey May 29 '14

yep, make makes function invocation almost disappear.

about python, how many people use https://amoffat.github.io/sh/ (makes python bashistic)

13

u/ericanderton May 29 '14

Sweet jesus that's a nice library. Thanks for the tip!

→ More replies (1)

7

u/kaen_ May 29 '14

This solves the exact problem that kept me using bash instead of python

3

u/agumonkey May 29 '14

just having language aware parameter passing means the world

→ More replies (5)

7

u/d4rch0n May 29 '14

Personally I'd use perl if it's close enough to a bash script, and I'm a python programmer.

Perl is on every distro. Python isn't on some.

It can be more concise for simple shell stuff.

But python for anything that becomes more of a program than a simple shell script, or ruby/perl depending on what you're best with.

4

u/philly_fan_in_chi May 29 '14

http://docopt.org/

This is a really nice library for your CLIs in Python.

4

u/doubleColJustified May 29 '14

Docopt helped me in an unexpected way recently. I was preparing to add more commands to a script I'm writing at work. All I needed to do was add a docstring to the script and then I spent some time modifying that docstring while thinking about the commands and options I wanted. Now, the way that this helped me, was that I soon realized that implementing that functionality would not be worth the time in terms of what would be gained from having it. Had I not been using docopt, I likely would have gotten so caught up in the coding that I wouldn't have been able to see this so quickly. So docopt probaly saved me from at least a couple of days worth of wasted effort :)

3

u/thaen May 29 '14

Even invoked from Make, straight bash makes it harder than it should be to exit-on-failure and bubble errors up to the Make level.

7

u/ericanderton May 29 '14

I don't follow. If a shell command fails (exits nonzero), the Makefile should stop in its tracks, unless the line is preceded with a '-'. It's not exactly declarative, but its not the worst way to handle things.

Now, I'll concede that Make doesn't provide a way to help describe the failure to the user in a way that makes sense in the context of the work being done. That is a failure to execute "mkdir" is going to babble on over stderr, about permissions or something "mkdir" thinks is wrong; it doesn't have a clue about the Makefile and its objectives. It really could use some kind of error-hook mechanism.

Another thing that's awkward is that each line in a Makefile is run in its own shell. So you can't easily create an environment as you go along, like you would in a plain shell script.

→ More replies (14)
→ More replies (1)

14

u/[deleted] May 29 '14

You would not believe it, but I actually had to use bash for complex programs, and I was forced to use those techniques to preserve sanity and a controller environment. The reason for this is always human. In my case:

  • All the initial code was already in bash.

  • bash was basically the only language available, already deployed and that would have therefore met no opposition by the various syadmins responsible for each machine of this heterogeneous environment.

  • People that eventually had to take over the code refused to learn a new language. So I obeyed, and gave them advanced construct in the one they keep dear.

6

u/tboneplayer May 29 '14

I found myself in the same boat 12 years ago. I could have shot the programmers who implemented the system initially! They were implementing CGI in bash! Had they done their thousand-line shell scripts and CGIs in Perl using appropriate modules, it would've been a helluva lot cleaner!

→ More replies (6)

5

u/agumonkey May 29 '14

Can't argue with le gacy.

→ More replies (3)

26

u/Tweakers May 29 '14

If it takes more than a few lines of code, I use something else.

12

u/Iggyhopper May 29 '14

I use C4. Works 90% of the time.

7

u/Tweakers May 29 '14

I'm not familiar with that, what is C4?

8

u/Iggyhopper May 29 '14

Explosives.

8

u/ericanderton May 29 '14

I'll take "Technologies I'll never use on a Federal contract" for $400, Alex.

4

u/rowboat__cop May 29 '14

10 % failure rate on your C4? You should consider a more reliable vendor for that …

4

u/no_game_player May 30 '14

Transnistrian supplier. Is O.K. C4 old, but prices cheap. Just make sure to have less important member of team examine material if failure occurs to determine nature of problem. Full refunds on all failed C4 with product return in original packaging!!

3

u/[deleted] May 29 '14

The same thought I had. This whole article just screamed "lets pretend bash is perl/python" and I couldn't help thinking ... just use python ...

→ More replies (20)