Live data from Hacker News

Ask HN: Let's build Checkstyle for Bash?

news.ycombinator.com

51–60 of 71 posts

Re: Ask HN: Let's build Checkstyle for Bash?

#51
post #2

Out of pure curiosity, in what context do you write sufficient amounts of Bash scripts that style checking is a worry that needs your attention? While I also write small one-offs or bootstrap scripts here and there, in most cases it's my experience that developers opt for other languages for anything beyond small snippets.

What do you use the; if you want: - Self contained in one file - Easily edited with vi/nano (i.e. through a console ssh session) - Readily available on most Linux base installations - No crazy runtime installation requirements Edit: formatting)

Some context to my statements: I'm a SWE that works on infrastructure services and tooling, primarily on Linux but also Unixes.

It depends on what I'm doing but usually Go if an application requires any longevity at all.

I use Python or Java for things that require more dynamic typing. The main usecase here is big data or to prototype applications.

Bash I usually reserve for very small tasks. When I bootstrap services in containers, you'll usually find some Bash. A whole CLI written in Bash? I would not approve that PR. Bash lacks variable scoping for the most part, the ways in which you can implement it are hacky and non-obvious. Bash's syntax and the way it behaves varies by system, even installer scripts have to account for this. As I'm typing this, I realize the Bash code I write generally follows the same testing and constraints as the Makefiles I write.

I don't think I really understand the requirement for "a single document". This departs from programming practices I've built up over the years. When I come across large multi-thousand LOC documents (in any language, much less Bash) I'm usually concerned.

Re: Ask HN: Let's build Checkstyle for Bash?

#53
I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts.

Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WASM compiler targets, etc.) Via these languages/compilers, everybody who wants compile-time strictness can have it. And you can even get runtime strictness that Javascript itself doesn't have, as the checked semantics of these languages will often be "lowered" into the resulting Javascript by generating explicit assertions (usually this is on by default, unless you ask for an optimized build.) But the output is still just "Javascript", that any browser can run.

Why hasn't a similar thing happened for POSIX-standard Bourne shell? Why are we seemingly "satisfied" with writing + maintaining 5000-line install.sh scripts in our codebases, with a bunch of extra mental overhead / tooling required to keep the code sane and clean; when we could just be writing in a sane and clean language to begin with?

Is it just that nobody's bothered to create such a language/compiler? Do I need to be the one to step up, here?

Re: Ask HN: Let's build Checkstyle for Bash?

#54
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

I don't think I understand. Javascript is required in the browser as the end target, but the operating system exposes the APIs which are consumed by bash to do useful work. The normal solution to not wanting to use bash is to... use another language (including, ironically, javascript).

Re: Ask HN: Let's build Checkstyle for Bash?

#55
post #54
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

I don't think I understand. Javascript is required in the browser as the end target, but the operating system exposes the APIs which are consumed by bash to do useful work. The normal solution to not wanting to use bash is to... use another language (including, ironically, javascript).

Much of the time that people are writing shell scripts, they're writing them not because they prefer shell syntax to that of some other language, but rather because they're creating a script that needs to be widely disseminated/deployed to all sorts of machines with unpredictable toolchain availability.

This is why a large fraction of the shell scripts that exist in the world still hold to Bourne shell syntax, rather than using any of the syntax extensions from its descendant shells: Bourne shell (or at least, something at /bin/sh that interprets Bourne-shell syntax) is part of the POSIX standard. So you can expect any POSIX system — no matter how weird — to be able to run (Bourne) shell scripts. You can run them on Alpine. You can run them on Busybox. You can run them on your NAS. You can run them on your router. You can run them in your initramfs, on your Kubernetes nodes, on your Mosix cluster, on your smart TV, on your watch, whatever. They run on Windows; they run on macOS; they (obviously) run on Linux and BSD. New Bourne shell scripts written today, run on 40-year-old operating systems nobody even remembers.

(If you think about it, the whole way that GNU autotools does its job, is by relying on the portability of POSIX-compliant Bourne shell syntax — i.e. the ./configure script — to bootstrap out enough of an understanding of whatever system it lands on, to find the tools required to then probe the system for the availability + capabilities of its compilation toolchain.)

For a small example of the type of script I'm talking about — see e.g. the script you download+run when you run the command-line on https://rustup.rs: https://github.com/hsivonen/rustup.rs/blob/master/rustup-ini....

For a much better example (that I sadly can't link to), see the install.sh for VMWare Workstation for Linux.

There's absolutely no benefit that these scripts get from being developed directly in POSIX-compiliant Bourne shell syntax, rather than being developed in something that compiles to said syntax; any more than programs for your PC would benefit from being developed directly in ASM, rather than in something that compiles to it.

Re: Ask HN: Let's build Checkstyle for Bash?

#56
post #2

Out of pure curiosity, in what context do you write sufficient amounts of Bash scripts that style checking is a worry that needs your attention? While I also write small one-offs or bootstrap scripts here and there, in most cases it's my experience that developers opt for other languages for anything beyond small snippets.

I think linters are just as helpful for 10 lines as they are for 1000. I (try to) use style checks and formatters for anything and everything I version-control, especially when there’s more than one person working on it concurrently.

Re: Ask HN: Let's build Checkstyle for Bash?

#57
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

The niche for such a language would be extremely narrow compared to existing better-than-shell-script alternatives. Wasn't that perl's selling point? Compiling to bash doesn't seem like that much of a better option than shipping (or just requiring implicitly) a $BETTER_LANGUAGE runtime, and writing in that language. (I imagine someone might respond with some carefully constructed scenario where you can only use a shell script, but I'd expect that sort of scenario to be rare.)

My go-to is either Python or Ruby when shell scripts start to get unwieldy - lately it's been Ruby but I'm mentioning Python because I have experience with the type-checking options for Python, and you mentioned that as a benefit. I'm sure someone will point out that type-checking exists for Ruby too (Sorbet, others?); I've just never tried it.

Re: Ask HN: Let's build Checkstyle for Bash?

#58
post #57
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

The niche for such a language would be extremely narrow compared to existing better-than-shell-script alternatives. Wasn't that perl's selling point? Compiling to bash doesn't seem like that much of a better option than shipping (or just requiring implicitly) a $BETTER_LANGUAGE runtime, and writing in that language. (I imagine someone might respond with some carefully constructed scenario where you can only use a she…

> I imagine someone might respond with some carefully constructed scenario where you can only use a shell script, but I'd expect that sort of scenario to be rare.

Not to comment on how frequent this is for other people, but my rare, obscure, and carefully constructed scenario is this one:

    docker run --rm -it ubuntu

Re: Ask HN: Let's build Checkstyle for Bash?

#59
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

I don’t think many are happy writing that much bash. I certainly wouldn’t be! I think this problem is completely solved by other languages though.

Bash is popular because it’s available (nearly) everywhere, is very portable, and has a massive “standard library.” (Technically, not a standard library, but you can basically guarantee that things like sed, curl, rsync etc. will be available or easy to get anywhere.) And its constructs are very well fitted to smaller scripts and automations.

You loose those benefits with a compilation step. Nearly all the scripts I interact with are just smaller automations put into a “bin” folder in the repo. These scripts are used for the build steps of other programs. So what would you write for automations related to building a compiled bash project? Probably bash lol

If you’re writing thousands of lines, you can just use any other language, right? Pretty much any other scripting language can execute commands in bash anyways. To my knowledge, stepping into a different language once you need more refined flow control and data structures is pretty normal. Afaik many languages can either produce output which can be run directly on the CLI (rust, C++, C), and others can be executed if you have the language runtime installed (JS via node, python, etc.)

Re: Ask HN: Let's build Checkstyle for Bash?

#60
post #53

I've always been confused that in ${current_year} people are still directly writing huge + complex shell scripts. Compare/contrast Javascript, another language we're "stuck with": while you can still directly write it, many people don't, instead using transpilers to target Javascript as an "object code" from some other, stricter language (e.g. TypeScript, ClojureScript, arbitrary native languages via Emscripten / WAS…

I don’t think many are happy writing that much bash. I certainly wouldn’t be! I think this problem is completely solved by other languages though. Bash is popular because it’s available (nearly) everywhere, is very portable, and has a massive “standard library.” (Technically, not a standard library, but you can basically guarantee that things like sed, curl, rsync etc. will be available or easy to get anywhere.) And…

> Nearly all the scripts I interact with are just smaller automations put into a “bin” folder in the repo.

What you're talking about are scripts you (or developers you work closely with) write to then use yourselves, in development workflows. These tend to be small and simple, and also places where the pain-points of shell-scripting (e.g. spaces screwing up path parsing) don't tend to come up, because developers have enough sense to not make their development environment actively hostile in these ways.

But this is not the only, or even the main, use-case of writing Bourne shell scripts. (If you have a development toolchain installed, you probably already have Perl and/or Python and/or Ruby — so why not script your development workflow in one of those? Or, if everyone is at least running a modern Linux or macOS+Homebrew, why not assume the existence of Bash or Zsh, and write for one of those, instead of Bourne shell?)

Instead, the main places where large, complex shell scripts are necessary, are in:

1. multi-platform software distribution;

2. systems-level glue code (think: initrd scripts; sysvinit back when that was a thing; etc) that must be runnable "at early boot" or in a "rescue environment" — i.e. one that can't guarantee that /usr is mounted, or that /lib is set up correctly to make non-static binaries work, etc. (Or in an "embedded environment" — in Busybox, /usr doesn't even exist!)

In the first case, the person writing the shell script is not the person running the shell script. Tons of different people run the shell script, on (sometimes drastically) different environments, and these are not developers, and their machines mostly aren't guaranteed to have anything like a development toolchain installed.

In the second case, despite targeting a single environment, said environment just happens to have a Bourne-shell compatible interpreter as its only scripting environment. (And probably even that was only included because the environment wanted to claim POSIX compatibility, never expecting people to want to script it rather than compiling native tools statically into the environment. Even though most sysadmins who might need to modify these environments, have no idea how to do that.) Mind you, some of these systems — e.g. UEFI — aren't POSIX-compatible at all, but rather require you to "script" them in something totally different, e.g. Forth.

> If you’re writing thousands of lines, you can just use any other language, right?

No, not if you can't make any assumptions about the target environment beyond "it's POSIX"; or if the target environment really doesn't offer anything not strictly required by POSIX. There is no POSIX-standard scripting environment other than Bourne shell. (And you can't just ship a binary, because you don't know the target architecture. Detecting the architecture you've landed on is probably part of what you're trying to do!)

Post reply on HN