Shell scripting dos and don’ts

Shell scripting is like a room full of power tools: handy but dangerous.

Don’t:

  1. Build complex systems. There are just too many ways that external state can affect any piece of shell code. Do you know what your script will do if you change IFS before running it?  What if you give it a file name starting with a dash or containing a newline? How do you recover the state of the system if the script crashed somewhere in the middle? Complex shell script environments invariably end up looking like Rube Goldberg machines of chainsaws and power drills. Use languages and frameworks appropriate for the task.
  2. Expose them to the Internet. Safe input handling is just too damn hard. Unless you’re GreyCat or Stéphane Chazelas.
  3. Use eval. Don’t be evil. There are safer ways to do whatever you’re trying to do.
  4. Write portable code. (By this I mean code which works in multiple shells without change, as opposed to code which can easily be ported to other shells.) Writing portable code means limiting what language features you use and adding complexity to make sure it works the same way in all the supported shells. Because of this, the end result will be more complex and less flexible than the simplest script that supports the shell you have.
  5. Minimise the number of characters. The next maintainer will hate you.
  6. Create interactive menus. Very few shell tools like less and top only make sense interactively. Use command-line arguments instead, so that your tool will be useable both standalone and with other tools.

Do:

  1. Test everything automatically. This gives you and others the confidence that your script actually works. Bonus: Allows you to modify your code without having to test everything manually. Extra bonus: Experiencing how difficult it is to test shell scripts exhaustively will convince you to never use them for anything complex.
  2. Provide --long-names for every -s -h -o -r -t option. And if you can bear the screams of dogmatic developers, don’t support short options at all. As long as the names make sense this allows people to write readable scripts. Bonus: No wondering whether -n5f0 is two, three or four options.
  3. Use guard statements like the POSIX set -o errexit -o noclobber -o nounset. While there are some caveats to how these work, they can save a whole lot of headache. Bonus: Use -o xtrace to see what the script does in detail.
  4. Add an auto-complete script. The users will be grateful. Bonus: Gives an incentive to keep the structure of your options sane.
Advertisements

Ultimate unit of time

Everyone knows Y2K (or else you wouldn’t be reading past this parentesis), but there’s also Y2K38 (32-bit Unix timestamps run out) and the Y292B277M026K596 problem. Why not get rid of these problems through the power of science?

The Planck time, at roughly 5.39106×10-44 seconds, is the smallest time measurement that will ever be possible. The Universe is, at current reckoning, about 13.75 ± 0.11 billion years. Seems to me we could put these facts together, and create the last reckoning our computers will ever need. With a bit of generous rounding, we get to around 2.6×1053 Planck time units of time until now. Converting to binary, that’s 177 bits. But what about the future? Well, since computers generally work best when given data in sizes equal to a power of two, we might as well round up to the nearest – 256 – And have plenty of time. In fact, 256 bits (less than it takes to store your postal address) would be sufficient to store time units until way, way beyond the existence of the human race, or indeed, of the fundamental particles of the universe.