Hacker News new | ask | show | jobs
by csmpltn 1288 days ago
> "why i moved mostly from writing node cmd tools to using bash"

You literally moved from one unmaintainable mess of an ecosystem (Node), to what is arguably an even worse unmaintainable mess of an ecosystem (bash). Glad to hear it wasn't Perl though.

For self-contained little tools or hobby projects that can run cross-platform, use Python. For anything beyond that - use a proper strongly typed language (C, C++, C#, Java, etc).

5 comments

Only use python if you plan on compiling it with something like docker or podman to pickle your resulting stew in epoxy for all time.

Otherwise you'll still be in some dependency heck as you run down why your library updated doesn't work (oh, switched to TLS encryption; that's good I guess) or you're thing uses v2 and everything now uses v3.

golang, rust, at least, make a static binary out of the gate. In 8 years it'll probably be full of hideous out-of-date code and full of security vulnerabilities, but at least you won't have to look at it and feel bad.

If static binaries were good enough for Ultrix, they're good enough for you.

I've been writing tools like this in Python for a very long time and haven't run into anything close to what you're describing. However, if this happened to me and I was annoyed enough to do something about it, I would use a tool (e.g. pip-compile) that creates a requirements.txt file, which specifies all the libraries and dependency version numbers explicitly. If something broke one day, you can stick that script in a directory with a venv and just run it from there. There's no need to resort to compiled languages like Go and Rust which will very likely give you a large raft of other unrelated problems (slower development velocity, comparatively limited libraries, etc.). Going through all of that just to have a binary in hand doesn't seem remotely worth it from my perspective (YMMV).
The OCI container is the binary. Docker is a tool to take any existing runtime and turn it into a static binary you can feed to any future linux(ish) kernel.

I on the other hand, have had plenty of situations where some system somewhere is managed with some config management tool (such as puppet) and it is told "make this application with these dependencies" and the application, such as "manage elasticsearch index rotation" uses the system python and does pip install to install all the things. This idiom seems fine, but ultimately ends up with a hideous mess where it worked one day and didn't work a year later, because either the system python is different or the dependencies are all messed up or the pip tool itself on the system python isn't compatible with modern package distribution.

You can (correctly) say "don't do that" but the same idiom in a shell script will almost certainly work across decades regardless of if "sh" is bash or ash or ksh, to some degree of "works" (again, you can _correctly_ say that no shell script ever works correctly).

It is interesting that the data science and ML folks are willing to weather Python’s dependency mess Vs. the huge momentum Golang and (increasingly) Rust have built around their static binary philosophy.

Perhaps this is the future of Kubernetes , to be the only thing brave enough to run epoxied globs of .NET, Java and Python.

Python and docker, with compose is a really good fit. Everything works, everything is boring, everything is stable all the time. And importantly, most problems are easily googled.
Just be sure to archive your artifacts. Both the ones you make and the ones you use to build output artifact.

Otherwise, your docker build tool will work today and be a screaming mess of broken dependencies tomorrow.

I think the trick is to not have any dependencies, except Python itself, when writing such command line tools. Python does have a large standard library after all. While Python itself surely could be nicer, it is still easier to maintain such a script than a script of similar size of GNU Bash code.
Bash scripts don’t break, when left unattended for months/years. Python scripts do.
It can’t break if it were never correct in the first place. Bash scripts are always chock-full of bugs, and only work when everything in its environment is the same. That folder now has two files instead of one? Now it just stops working.
In my experience, they don’t have more bugs than Python scripts. That’s assuming they’re shorter than 50 LOC. Long before my scripts reach this size I convert them straight to Go. That’s the most problem-free strategy.
Pin your versions. Also - to make the equivalent safe bash program compared to a typical python implementation is ... a lot of work. Enough that imo the python version is worth the maintenance.
Pinning versions doesn’t help when the old version of some dependency no longer works with your new OS or hardware.

I mostly only code in Python but this article really spoke to me. I have <10 personal Python scripts that I use heavily for my job, but they are such a bear to maintain.

Meanwhile my two old Autohotkey scripts that I wrote 10+ years ago and rarely touch still chug along perfectly.

The recent deprecation warning message of `egrep` is a prime example that bash scripts can break (depending on stderr processing). They will definitely break once the alias is removed.
egrep has been on a deprecation path for 15 years, and the replacement is incredibly straightforward. Also, I think egrep will generally just continue to work.

I'm not sure what you mean by "recent", but this is more longevity than we get in the node/JS world.

I'm primarily a JS (now TS) dev, who also throws bash at things when it makes more sense, but let's not kid ourselves that it's the same.

*Statically typed, not strongly typed
In the past years Java is a strong candidate for cmd tools.Using Quarkus + Picocli + GraalVM for native compiling, gives you a standalone binary which can be used on any platform.
The python build/install/distribute situation is so bad, XKCD made fun of it years ago https://xkcd.com/1987/