It is kind of like csharprepl[0] but more powerful for the scenarios it targets. However, since it only supports Windows it's a non-starter personally so I never used it much.
Next time you want to write a few lines of C# to verify a detail about syntax, count how many clicks you need to go through to create a new console app project / solution.
It's much faster to just hit the + in LINQPad.
It's quite useful when I'm reviewing someone else's code, or if I'm "in the zone" in a large change. I can verify some syntax in a few seconds, as opposed to the minutes it takes to make a throwaway console app project / solution.
For Java projects, scripts can be written in a JVM language like Clojure or JRuby. Can still leverage the Java code in the rest of your project, while writing in a more dynamic, interactive language.
> For example, writing scripts on JVM languages would require additional effort to build a toolchain that compiles and runs files on the fly, with a short start time.
That hasn't been true since at least Java 11. You can execute any .java file using `java foo.java`. No compilation required. You can reference dependencies using the usual classpath options etc.
Startup time is minimal.
Been using such scripts in exactly the way the author suggests for years. Much more pleasant than messing around with maven or gradle plugins.
> You can reference dependencies using the usual classpath options etc
I don't know anyone who thinks that a java script (being the main project language) is going to surpass:
#!/bin/sh
dep-start.sh
./gradlew clean bootRun
Maybe there are outliers with this "hot take". The result of years of projects (even changing hands), are a lot more instructive than someone posing theoretical value of reusability.
That example doesn't even need a script, it could literally be a single gradle task. Some things are lot easier to do in a platform independent way in Java (or Groovy) than in shell scripts. And unlike the latter, the former can be tested just like any other part of the code base.
It always bugged me that build scripts are hardly ever tested or engineered. They just grow into giant balls of mud.
I'll admit I'm not reading the article, but this is a hard no for C development. Yeah, it can be done not so terribly, but just use a normal scripting language.
Use the right tool for the job. The authors complaints seem to stem from not properly maintaining the supporting scripts in their project, which isn't at all a function of the language.
I encountered bugs and had to fix glaring problems in shell scripts literally everywhere I worked.
Most devs are not deeply steeped in Unix, and don't really know what they're doing with this as it's not their main job. They kinda clobber something together that "kinda works" – right up to the point it doesn't.
There is no shame in that; I do that with some stuff too – we all do – because there is no point learning something in-depth if you use it once a year. This is not a "zomg devs are stoopid" rant, it's just an observation of fact.
I've written tons of shell scripts and and I love how it enables you to do something useful very quickly in very little code. Last week I hacked together a "ncurses"-type terminal music player in less than 200 lines which actually works fairly well, which I thought wasn't too bad for an evening of work.
But in general I distrust other people's shell scripts, and I found that 9 times out of 10 that's warranted. I tend to push for zsh as it fixes the most egregious footguns and limitations, but there's still plenty of things to do wrong, and the syntax can be unfamiliar.
Something that “kinda works” actually does work. Fixing the edge case when it is actually a problem may actually save time compared to spending extra time up front on things that might never be a problem.
I should have been clearer about that: but I'm not talking about theoretical edge cases. I'm talking about "I tried to run it and it doesn't work", or worse (e.g wrong behaviour).
Shell scripts are often the peak of "works on my machine".
The problem mostly stems from the fact that MacOS folks don't have compatible Unix utils to the Linux folks, and the majority of developers are on MacOS but everything deploys on Linux. The easiest way to fix this is to install GNU utils on mac so you're using the same bash and system tools everywhere.
That is one problem, but there are others: assuming things like current working directory, assuming certain tools are installed and failing badly when it's not (e.g. doesn't do anything but no error, has the wrong behaviour and no warning), and things like that.
I’d agree: every critical shell script should work in all the places it currently needs to run. But, I think it’s reasonable to iterate here towards perfection: every time a new employee shows up or new environment comes up is a chance to uncover these problems and fix them.
There’s a balance here between solving the problem you actually have (YAGNI) and responsible engineering. Obviously you should test that your code works as expected in all the current environments but, sometimes, ensuring that all the edge cases are handled is just over-engineering.
But I worked with an extremely bash-skilled guy at IBM many years ago who went out of his way to write his scripts in the most arcane way possible. On purpose.
It was his form of job security, from rough memory when I asked wtf?. ;)
I wasn't project lead on that one, so we just had to put up with it... :(
People who say stuff like this must not have worked on enough Linux environments. Bash scripts aren't fully portable, and there are absolutely differences in environments which prevent portability of bash scripts. Since using Nix, I've realized the number of bash scripts which are only superficially portable are drastically higher than the number which are actually portable. As one trivial example, how many bash scripts use the more portable shebang of `#!/usr/bin/env bash`? Extremely few. And every one which hard codes `#!/bin/bash` has created a less portable script most likely without ever having realized it. Guess they are all muppets though right?
If you standardize the Unix utils you use and the bash version you use, it's really not hard to avoid a lot of the issues you're talking about. To get all developers in an org working on compatible ubuntu-like systems, just mandate use of WSL on Windows and GNU unix commands on mac so everything is the same for everyone.
That being said, if you and your team just don't have a lot of bash/unix experience, that is probably a good argument for writing your utility scripts in whatever you can actually write without a ton of bugs.
Would you complain about node bugs if your org wasn't standardizing the node version people used and some people were still on node 12??
Not true. Bash is filled with foot guns. In fact even HN has articles hitting the front page every other month about another bash footgun and how to avoid it. Any Muppet can write a bash script to do the thing, but only somebody with a lot of bash and unix experience can make sure it's dodging the hundreds of common and obvious but incorrect way of doing things.
When it comes to infra, someone's preferred language may not always be available. Infra and devops is more about plumbing, and plumbing gets messy.
It can go the other way as well. tcl was originally conceived as an embeddable scripting language that can drive GUI applications, and has been very successful in that use-case. It has a few flaws, but I would have preferred it to been embedded in the browser instead of making up Javascript back in the day.
Recognizing that “what language should a project’s scripts be in” is too broad of a question to have much more specific guidance that is applicable universally is not a problem.
yes, this. Engineers frequently try to converge everything into the one-true-way and go too far. (I blame this thinking for phones without buttons or touchscreen cars)
Makes no sense to write scripts in C++. I've worked on projects where people have tried to do this, and they end up being more fragile, cumbersome and not that useful.
I think python is ok for cross-platform.
a shell is good for command line/os logic.
seriously a shell script with 'set -e' at the top, and a lot of command invocations and not much else is pretty easy for a group to maintain.
> The authors complaints seem to stem from not properly maintaining the supporting scripts in their project, which isn't at all a function of the language.
That and often making the scripts overly complex and a software project in themselves. Changes are that if you're building/deployment scripts are this complex that you are not leveraging modern tooling and platforms efficiently and re-invented the wheel in script form.
A recent example I encountered was an Ansible environment. While looking how other teams had set up their playbooks for something, I came across an extremely complex one. It basically pulled a bunch of java apps from artifactory and wrapped them in complex bash logic. All of this to do some conditional checks and send out a mail through a custom java mail client.
This amounted to over a hundred lines of code that I could replace with a handful of lines in Ansible.
Tbh bash/sh don’t prioritise the experience of _writing_ commands, which might be worse. I’m decent with Bash, but to this day I don’t know how to properly document and parse flags (long and short form) and positional arguments (with validation, while we’re at it) so that it all works as I would expect.
I have a C++ project where the documentation is generated using a script that I wrote in C++. Woof. I didn't want to add a compile-time dependency on another programming language, but C++ is rough as a scripting language. If my script needs were any more complex, I'd be thinking hard about how bad a compile-time dependency on Python really is.
I'm not sure I've even seen a recent, large C++ project that didn't depend on Python or some other external scripting language just to build it, so it's kind of hard to imagine using C++ itself to solve the problem that using C++ creates.
I worked with a guy in a C++ RPC team (think Envoy, but proprietary). He wrote the build tool that was used by our team, which maintained several fairly large C++ programs and libraries. He wrote it all in C++. He was of the opinion that most scripting tasks on the team could be accomplished with a small C++ program. It helped that we had a portable kitchen sink of libraries at our disposal, but he wasn't above using std::system to avoid the hassle.
> If they can use the main language, awesome. If they can’t, a higher-level scripting language with native support (e.g., Python) should be adopted, since it provides the means to increase maintainability in the long run.
I think this point is especially important for C++ projects. It is my gut feeling that C++ and Python cluster very closely in terms of developer familiarity. That is, a C++ developer very likely is also a passable Python developer.
Given that it tends to take more time to write a C++ program than the equivalent Python program, the stable result is that many C++ projects 1) expose C++ to Python (via e.g. pybind11) and 2) write all scripts in Python.
And you get almost all of the benefits that the article suggests, because almost all C++ developers are also Python developers.
2. The language used for scripts necessarily is and should be treated as a project language, and the appropriateness of that choice should have all the factors that go into choosing a langauge for any other purpose, including the impact on complexity if it isn't the main language and fitness for purpose and any additional dev platform, tooling, etc., constraints it imposes, but...
This doesn't imply scripts should be in the main project language, any more than it is generally the case that projects must be monolingual.
Much more nuanced, thank you! For one thing, you need a language to bootstrap your environment in dev envs and CI. You wouldn't want to write a Python script which has to support a bunch of minor versions (with vastly different capabilities) just to run `poetry install`.
If you’re using a C++ project saying that all of your scripts related to that project must also be in C++ when Python would do fine is ridiculous. You should just pick a reasonable language
In fact my "scripts" are actually part of the main executable. I use cmd-line args to invoke the needed functionality.
For example, in the past I would have written a Python script to deploy my Go binary to a server, possibly using tools like Fabric that provide functionality to make it easier.
Today I add `-deploy-hetzner` cmd-line to my Go binary and it does the work. It builds itself, copies the binary to the server, kills the old instances, configures caddy if needed, starts newly uploaded instance etc.
I standardized on how I deploy things so deploy.go is mostly re-used among several projects.
Writing this code isn't much more difficult that what I used to write in Python.
This kind of code can be shorter because I don't have to handle errors, I just panic if something goes wrong.
I like that I don't have to switch between different languages and that I have full control and understanding over what happens. Fabric used to be a bit of a black box.
Im a big fan of //go:build exclude ... and having separate CLI scripts in a project where I can.
Candidly I think that it's much easier to do this in go (or rust), rather than say python/ruby/node as I can use complied binaries without needing a run time.
Go’s excellent for writing development tools and “scripts” if you have to support development on heterogenous platforms.
No per-platform install instructions, no “ok but you have to run this in WSL2… you don’t have that? Oh god, ok, let’s find those instructions…”, no “oh fuck the flags for that are different on BSD and Linux, so this breaks on macOS”. “Wait the command’s python3 not python, on your system? And also it’s erroring even after you fix that? Shit you’re still on 3.8, we use features that weren’t included until 3.10…”
“Unzip this single binary and run it. Tell your OS to trust it if it hassles you. That’s it.”
C# with mono might be close to as good? Not sure. Rust’s probably OK but a bit of an investment when you’re just trying to dash off some quick tool or script. C++ and C can do it but you definitely don’t want to. Java’s obviously out (ok, now update your JRE… wait, your env vars are all fucked up, hold on…).
Go’s also highly likely to be something another developer with or without Go experience can read and tweak after the person who wrote it leaves, without much trouble.
I use https://github.com/spf13/cobra religiously for this kind of thing - it handles all the annoying corner cases of parsing flags, and also has an intuitive notion of subcommands (with basic usage/help text generated) for picking which task you want to run with positional arguments.
I tend to use go for "scripts" in non-go repos (typescript, C, etc) just for the simplicity of "you only need to install go" and pretty much all functionality is included in the standard library (usually something like JSON/XML/CSV parsing).
I'm OK with python for scripts, but go "just works".
This seems like a terrible case of not separating concerns and needless optimization. It may work for you, but what if someone who does not know Go but wants to use your project on a provider that is not hetzner?
Yeah, this is the way to end up with ad-hoc, bug-ridden, half-baked implementation of fabric (or ansible, salt, helm, nix, or any tool that is more appropriate for this job)
And you haven't addressed the issue that whoever is performing the role of DevOps on this project must know Go.
You are erroneously invoking a fallacy that does not apply here. A qualified DevOps engineer will be able to pick up GoLang. I didn't claim that a DevOps engineer already knows GoLang, but that they're able to pick it up. If I'd say only true devops engineer's already know golang, you'd have a point.
Which is not something that one professional needs to be in order to have to perform some duties that fall within the role of DevOps.
I am, first and foremost, an application developer using Python and JavaScript. But I also have extensive experience:
- setting up Docker Swarm clusters
- managing cloud infrastructure with Terraform
- configuring deployments with Ansible
- setting up observability on Prometheus/Loki/Grafana stack
- putting up together CI servers for my team
- setting up backup/restore infrastructure.
- deploying and managing internal OSS tools for a dev/data team: Gitea, Taiga, Redash, Apache Airflow, Baserow...
These are all tasks that could be part of a "DevOps Engineer" job description, but if you tell me that "to work with a primarily Golang dev team you need to pick up Golang", I'd be assuming that you are not looking primarily for a DevOps Engineer, but a Go Developer who can do DevOps. And because I am not a Go Developer, you'd be putting my whole application on the bottom of the Stack.
Your point, that doing this ad-hoc in go results in a half-baked shitty reimplementation of ansible/chef/fabric/whatever, was well made. I totally agree with it.
My point was, is that the DevOps person needs to be smart enough to pick up Go, which I'm sure you are.
Any hiring manager that puts your whole application on the bottom of the stack because of a lack of experience isn't a good hiring manager and isn't worth your time.
Do fabric,ansible, salt, helm, or nix have the functionality of deploying to cloud infrastructures? There is a lot more to deploying to cloud infrastructures then just provisioning a server.
I've never seen these tools used in this capacity, especially nix.
I think such things have existed, but Nix deployment tools being relatively small projects with small teams or solo devs, a more common approach is to piggyback off of other IaC tools provisioning cloud infrastructure, e.g. by templating Terraform in Nix¹.
From a Nix user's perspective, this leaves a lot to be desired, because tools like Terraform are much less reliable than Nix tools that target local machines, and their management of, say, a VPC, is much less comprehensive than NixOS' management of an individual operating system. And they're slow as hell. But for the most part these issues are inherited from the APIs cloud providers expose, which don't meaningfully or uniformly support immutability.
One could argue that if you are at the stage of "provisioning a server", then you should be using something like Terraform or Pulumi, not configuration tools like the one I mentioned.
Anyway, for the specific case of "deploying to hetzner":
> It may work for you, but what if someone who does not know Go but wants to use your project on a provider that is not hetzner?
Well they'd run into the same problem if the script was Python, wouldn't they?
And Go is ultimately far far easier to read, modify[1] and debug for someone who doesn't know it than Python is.
[1] For example, adding a third-party library to handle new cases. I've never had a good time doing it with Python's various package management, but Go seems pretty good at it.
> Well they'd run into the same problem if the script was Python, wouldn't they?
No, they would just use whatever tool is more appropriate for the job.
Fabric would be fine, ansible would be fine, salt would be fine, putting it on Docker and deploying via compose would be fine. None of these tools force you to learn the implementation details of the application.
> Fabric would be fine, ansible would be fine, salt would be fine, putting it on Docker and deploying via compose would be fine.
That still leaves them the problem of "If I don't know this tech stack, what do I do?"
You are working on the assumption that everyone already knows Fabric, Ansible, salt or Docker.
Whichever poison you choose, people who don't know that particular poison won't know how to install to a different provider anyway!
You're making an argument against one particular poison, but I don't see it as any better or any worse than the others, which all have enough complexities to fill a book.
> "If I don't know this tech stack, what do I do?"
If you don't know how to use a tool that does one job, either you learn it or you just delegate that job to someone who knows it already. But defending the practice of having your application code also responsible in dealing with deployment and packaging smells a lot of "coders are gonna code".
You are being needlessly picky here, Golang is in fact a very viable replacement for both sh/bash/zsh and Python scripts, it compiles to a single static binary, can be cross-compiled to every supported OS on another host, and is thus easy to distribute.
I already started replacing parts of my shell scripts with Golang programs and the experience is miles ahead.
And if the project is already written in Golang, it makes even more sense if the dev is also partially the DevOps. Why wouldn't they make the experience as seamless as possible for themselves and the rest of the dev team? What good would Ansible do if everyone has to yet learn it?
As for the person you originally replied to, I'd definitely make a separate program that provides tooling related to the main program... but that's the only different thing I'd do.
Your snarky "coders gonna code" comment is detached from reality, we have jobs to do, and within deadlines.
> it compiles to a single static binary, can be cross-compiled to every supported OS on another host, and is thus easy to distribute.
You could say the same thing about Java or C++. Would you argue then that the best way to deploy java applications is by writing a java library and embed into your program?
> if the project is already written in Golang, it makes even more sense if the dev is also partially the DevOps.
I really don't see how that one follows from the other, and I really don't understand this conflation between roles and tooling. There is a lot more to "DevOps" than packaging/distributing/deploying. It's not just because your application code is in Go that your tooling needs to be as well.
> Why wouldn't they make the experience as seamless as possible for themselves and the rest of the dev team?
Because it's a fragile solution. You are tying the implementation of your problem to a very narrow space out of immediate convenience. I've had my share of projects with "experienced" node.js developers who are trying to do everything in node instead of reaching out of their comfort zone and looking for existing solutions elsewhere.
> we have jobs to do, and within deadlines.
Yeah, and a lot of those jobs could have been made in a fraction of the time if the developers were not trying to use their screwdrivers as hammers, and put some effort to figure out how to use the hammer in the first place.
> Yeah, and a lot of those jobs could have been made in a fraction of the time if the developers were not trying to use their screwdrivers as hammers
Did you deliberately ignore the part when I asked why would a team of devs learn Ansible if they don't know it? No, it's not fraction of the time at all, in fact it might balloon to weeks in the ideal bad conditions.
Most people would opt for something they already know and that's a fact of life. Learning Ansible or Fabric on-demand is not exactly an optimal expenditure of time and energy, not to mention that a proper DevOps professional would know various gotchas that a learning dev will absolutely miss. Sure the dev will EVENTUALLY get there. "Eventually" being the key word. Why risk botching stuff in the meantime?
> Because it's a fragile solution
Says you. I do Rust scripting in my Rust projects, Golang scripting in my Golang projects, and Elixir scripting in the Elixir ones. Works really well. Not necessarily for deploying and DevOps work, mind you, but for a lot of stuff like "populate me this sample data so I can experiment with the app" or "start only these parts of our app so we can do an integration test with them after" etc.
I also did part of the deployment actions, not all though, if that makes a difference. I don't know the exact situation of the person you replied to.
> You could say the same thing about Java or C++
Huge, huge disagree here, probably the biggest I ever expressed on HN. :D
So many environment variables, compiler switches, and various runtime dependencies and so many other things that it's not even worth starting, it can fill up a PhD thesis and have room for more after.
Your statement cannot be more wrong if it tried. I have several serious objections to the Golang the language that prevent me from adopting it as a main career choice -- but its portability and distribute-friendliness are one of the best in the world right now. You can criticize it for a lot but criticizing it for these two things would be severely uninformed.
> I really don't see how that one follows from the other, and I really don't understand this conflation between roles and tooling. There is a lot more to "DevOps" than packaging/distributing/deploying. It's not just because your application code is in Go that your tooling needs to be as well.
Sure there's more to DevOps, I agree, but I was under the impression that the guy you replied to was tasked with doing part of DevOps so he found a way of doing it with less friction.
Conflation between roles and tooling is unfortunate indeed and I sympathize with your statement there. It's simply an artifact of imperfect work conditions (so 99.999% of all work places).
I can relate to your frustration about non-optimal processes but you are overreacting a bit.
Can their homegrown solution backfire? Absolutely, of course it can. But often times we have to make do with what we have right now and can't optimize for the far future.
If a DevOps wants to pick up the torch and do the job properly they are free to do so but yet again, I was under the impression that the person in question was wearing several role hats at the time.
> "populate me this sample data so I can experiment with the app"
Which is well within the role of the developer. "Deploy to Hetzner" is not.
> I was under the impression that the person in question was wearing several role hats at the time.
Sure, I also have to do everything on my own in my own projects. But again, the function determines the tool, not the person performing the job. When I'm wearing my application developer hat, you'll see try to do as much as possible with Python, but that doesn't mean that I will try to turn every problem into a python script.
> Which is well within the role of the developer. "Deploy to Hetzner" is not.
Well, OK, I can't argue with that as much. Maybe the guy truly found it easier to do so? No clue. I know I'd definitely try with a shell script, then with the project's language, and only then with a dedicated tool. As much as I try to be a good senior backend dev -- and I know a lot of stuff and tooling that are not at all mandatory for my role -- I still can't find the time and energy to become a properly good DevOps; too much investment, and for specific cloud platforms. To this day I can't justify it and can't make myself "git gud" with AWS.
> When I'm wearing my application developer hat, you'll see try to do as much as possible with Python, but that doesn't mean that I will try to turn every problem into a python script.
No you really should not, Python is a nightmare in portability. I can trivially use venv-s and other tooling to make sure stuff is isolated and works fine but the whole house of cards is still always just one `brew upgrade` command away from falling apart. Eventually I've given up. If Python can't be trivially made portable then it's a bad tool for scripting, no matter what many people think and say (in fact, a lot of people using a tool often times speaks badly for its quality; to me "Python is good" is a mass delusion but that's a huge topic in itself that I won't tackle here). The fact that many people don't know anything else but Python is not an excuse.
Golang is a much better choice for quick scripting and that's a demonstrable fact. You can parse CLI flags and use their values and even throw some validation is some 10-15 coding lines and from then on you can use various super-useful libraries; there even exist a few that emulate a number of UNIX tools so you can still have a single binary that can do a lot without depending on anything except a kernel being present in the system (which also makes the resulting binary very convenient in constrained / container environments).
You might think I am getting hung up on details but I felt that I have to debunk the idea that Python is a good scripting tool. No it really isn't, and most Python devs never test on a random Mac or Linux machine where the dev is NOT using Python as a primary language. It's a fragile mess.
But now we're arguing in circles about familiarity. :) I recognize the irony. But for what it's worth, I didn't know Golang and made it a goal to learn it long time ago because I liked its distribution story and (mostly) ease of use (with a bunch of caveats nowadays, sadly).
> If you don't know how to use a tool that does one job, either you learn it or you just delegate that job to someone who knows it already.
How is that different from "If you don't know how to use the tool (Go), either you learn it or you just delegate that job to someone who knows it."?
> But defending the practice
Woah there cowboy, I wasn't advocating an architectural decision suitable for a FAANG. I was "defending" the position of "why you an extra tool for this one program that has no other dependencies?"
> of having your application code also responsible in dealing with deployment and packaging smells a lot of "coders are gonna code".
In much the same vein, switching to Ansible, Fabric, etc simply to install a single binary to a single place smells a lot like "resume-driven-development".
Well, maybe he never wants "someone" to deploy his project. I think it is perfectly legitimate to handle it this way for a one-man hobby project.
For a project where multiple people are involved, I think it's better to split concerns. Deployment should be handled transparently and reproducible in a CI pipeline that the team members who are allowed to deploy have access to.
If your argument can only be made in a very specific set of conditions and only applies to yourself, it's just a preference.
I don't care how you prefer to do things on your own, but if I were interviewing you for a senior position in a team with a handful of people, and you tell me that's how you want them to work, it would be an almost immediate NO HIRE.
Yes, but you are moving goalposts. I was under the impression we were talking about the one-man army case only, not how they conduct themselves on interviews which is a VERY different topic.
The blog post was about the context of a team with multiple people.
OP's comment was "I do this for my Go project's" and goes on to describe how to use a (open source) library that even deploys to Hetzner.
So, either the commenter was trying to extend their practice to the point of the blog post or the comment was just expressing a preference when working by themselves, which has little to do with the content of the post.
Sure, I don't think we disagree as much as I thought an hour or two ago, I am still little puzzled why you found it so bad though.
If a deployment procedure is easy for non-DevOps people then by definition that also makes it friendly to programmers, so why wouldn't they do it if it they can do it properly with minimal effort. But I do realize that "properly" is doing a lot of work in this sentence.
No! General purpose scripts should almost always be written in bash. It's basically the best language for doing simple things with files, it's universally available and it makes almost no assumptions about the environment in which it executes.
Have windows users use WSL (the VSCode integration is great!), and mac users should install GNU tools since the system tools are obnoxiously incompatible.
The only time I've found that scripts should be in another language is:
1. You need to call libs that to do something fancy and it would be too troublesome to make a small Unix style executable to do the thing.
2. The developers on your team lack Unix/bash experience, and you don't trust them to learn in a timely manner (sad).
Unless you're doing some extremely niche work, Bash >= 3.2 (because Mac) is nearly always going to be available. Even if it _isn't_, there will still be sh or dash, and it's not _that_ hard to stick with pure POSIX for most small uses.
The last time I (by which I mean my team) rewrote a script from Bash into Python was because it had gotten unwieldy over time, I was the sole maintainer, and very few other people at the company knew Bash well enough to understand some of it. The upside was testing frameworks in Python are way better than Bash.
First you write in shell without knowing the language, and blow your foot off. A few years go by. "I should use a _real_ language, I'm not an amateur anymore." So you write everything in Python. A few years go by. "I should learn shell, and use it only when appropriate."
Maybe this is what Perl is for, but I never learned it.
> Have windows users use WSL (the VSCode integration is great!), and mac users should install GNU tools since the system tools are obnoxiously incompatible.
At that point you might as well target Python 3.6. Seems like the same hassle for the developer to install and you don't have to worry about wonky differences for users who haven't installed GNU tools, but still think they can run your script because it says `.sh`
That's not correct, because then you have to make sure all your docker images and deployment environments have the correct version of python, and managing python installations for incompetent Mac devs is probably more work than managing a GNU utils install since python installs have been known to break easily whereas the core utils are rock solid. Plus writing file manipulation/subprocess scripts in python is really awkward compared to bash.
I've always found it weird that the NPM ecosystem doesn't have something like Rake from the Ruby world to run tasks. Javascript things tend to be VERY task heavy, with dev servers, bundlers, testing, and coverage all being defined in the project normally.
The package.json scripts "work", but it's quite clunky, and relying on shell scripts that run node.js scripts causes issues. (cross-env solving a problem that really shouldn't exist.)
I’m of the opinion that the package.json scripts was a mistake (although not a huge deal in the grand scheme of things): it solves 80% of the problem, which removes enough pain that there’s not enough incentive to solve the last 20%.
I’m sure there’s something like rake that exists for Node, but the community won’t standardise on it because it’s not enough a problem
I would have agreed more with this a couple of years ago when maintaining a script written in an alternative language required me to know that language.
These days I'm much more comfortable both writing and maintaining code in languages that aren't my daily driver (like Bash or jq or AppleScript or even Go) because I can get an LLM to do most of the work for me, and help me understand the bits that don't make sense to me.
Soon many projects will be written in LLM: a mix of whatever languages the models generated on given day + an LLM so that the maintainers can understand it.
I still find it hard to believe that LLMs provide any real edge over the kind of googling/man-paging that's necessary for understanding scripts, especially given the false positives chatbots are known for. Typically language + feature + library is enough to look something up in under ten seconds for me.
Granted, this probably takes a fair amount of experience to even know what you're looking at well enough to search for it.
The good ones (Claude 3 Opus, GPT-4) are really incredibly good at understanding scripts. It's very rare that they hallucinate anything, especially important details for the more widely used tools that I tend to stick to.
I trust LLMs with tools like Bash and jq and ffmpeg which have been around for years. I wouldn't trust them with anything released within the past 12-24 months.
How does that @latest reference mention? There's no branch or tag on that repo called "latest".
I tried and failed to find documentation. I gave up and asked GPT-4, which said:
> @latest: This specifies the version of the package you want to install. In this case, latest means that the Go tool will install the latest version of the package available. The Go tool uses the versioning information from the repository's tags to determine the latest version. If the repository follows semantic versioning, the latest version is the one with the highest version number. If there are no version tags, latest will refer to the most recent commit on the default branch of the repository.
Is that correct? I have no idea! But it still gave me more to go on than my failed attempts with the real documentation.
I appreciate the illustration! I can certainly see how this would be useful especially for tools like ffmpeg, which is both difficult to google and understand and doesn't have a large overlap with patterns other tools use.
I like to take this a step further and try to have all my most important tooling be written in my projects major languages. It's not a must have, but having a build system for a go project that is also go under the hood means I'm more comfortable diving into the source if needed.
I don't think it's a requirement, but it's an advantage
We should use YAML for all of our automation so that non-developers can build and maintain the automation, and then exclusively assign developers who are proficient in a general purpose programming language to build and maintain the YAML automation. </s>
For some languages this can make sense, but I think most languages aren't suited for installing things, manipulating the filesystem, etc.
I think of scripts as the middleware between the operating system and the shipped code. The code is controlled by the operating system, so the operating system's tools should be used to manage it. In many cases this means bash or make.
Plus, I don't want modern Javascript to do things on the filesystem that would require importing dozens of projects that I need to vet before using. Golang or Python perhaps, but the buildchain for modern Javascript is hell as-is; it doesn't need another layer of Javascript.
>> Scripts should be written using the project main language
... as long as that main language is a scripting language. Otherwise it's just dumb.
Also, tunnel vision by the author: "Almost all projects I’ve worked on have scripts we wrote to automate a repetitive process. "
Well almost all projects I’ve worked on have scripts we wrote to automate a ONE-TIME process. Like collect some data from the log to figure out a bug, fix it and forget about both the bug and the script. Automate it since can't manually process 30Gb of data and grep only can do so much. Sure as funk won't write the "script" in C++ but Python or Perl or something.
Ehhhhhh. I get the sentiment, but I think this really depends on what the "main" language is and how amenable it is to scripting.
Personally, I prefer writing shell scripts regardless of what the main language is in a given project. They're portable (more or less), and can e.g. detect missing dependencies and install them if necessary, which isn't possible with the main language if you're missing its compiler or interpreter.
171 comments
[ 3.0 ms ] story [ 212 ms ] threadhttps://github.com/oleg-shilo/cs-script
I have never understood the appeal of LinqPad whatsoever.
[0] https://github.com/waf/CSharpRepl
It's much faster to just hit the + in LINQPad.
It's quite useful when I'm reviewing someone else's code, or if I'm "in the zone" in a large change. I can verify some syntax in a few seconds, as opposed to the minutes it takes to make a throwaway console app project / solution.
Scala is a lot less exotic than Clojure or JRuby to most Java devs, as expressive as Groovy, yet fully type-checked.
That hasn't been true since at least Java 11. You can execute any .java file using `java foo.java`. No compilation required. You can reference dependencies using the usual classpath options etc.
Startup time is minimal.
Been using such scripts in exactly the way the author suggests for years. Much more pleasant than messing around with maven or gradle plugins.
I don't know anyone who thinks that a java script (being the main project language) is going to surpass:
#!/bin/sh
dep-start.sh
./gradlew clean bootRun
Maybe there are outliers with this "hot take". The result of years of projects (even changing hands), are a lot more instructive than someone posing theoretical value of reusability.
It always bugged me that build scripts are hardly ever tested or engineered. They just grow into giant balls of mud.
In C#, I could see doing this.
In Ruby/Rails, the concept of ad-hoc script execution is baked in via rake.
Bash makes everyone a muppet if you push it hard enough. (True of all tools, perhaps. But you don’t have to push very hard with bash.)
Unfortunately, the world's full of muppets, present company not excluded.
Most devs are not deeply steeped in Unix, and don't really know what they're doing with this as it's not their main job. They kinda clobber something together that "kinda works" – right up to the point it doesn't.
There is no shame in that; I do that with some stuff too – we all do – because there is no point learning something in-depth if you use it once a year. This is not a "zomg devs are stoopid" rant, it's just an observation of fact.
I've written tons of shell scripts and and I love how it enables you to do something useful very quickly in very little code. Last week I hacked together a "ncurses"-type terminal music player in less than 200 lines which actually works fairly well, which I thought wasn't too bad for an evening of work.
But in general I distrust other people's shell scripts, and I found that 9 times out of 10 that's warranted. I tend to push for zsh as it fixes the most egregious footguns and limitations, but there's still plenty of things to do wrong, and the syntax can be unfamiliar.
Fixed it for you. This is why they pay us the medium bucks.
Shell scripts are often the peak of "works on my machine".
But I worked with an extremely bash-skilled guy at IBM many years ago who went out of his way to write his scripts in the most arcane way possible. On purpose.
It was his form of job security, from rough memory when I asked wtf?. ;)
I wasn't project lead on that one, so we just had to put up with it... :(
That being said, if you and your team just don't have a lot of bash/unix experience, that is probably a good argument for writing your utility scripts in whatever you can actually write without a ton of bugs.
Would you complain about node bugs if your org wasn't standardizing the node version people used and some people were still on node 12??
It can go the other way as well. tcl was originally conceived as an embeddable scripting language that can drive GUI applications, and has been very successful in that use-case. It has a few flaws, but I would have preferred it to been embedded in the browser instead of making up Javascript back in the day.
Could you elaborate?
Pretending it is not, OTOH, is.
yes, this. Engineers frequently try to converge everything into the one-true-way and go too far. (I blame this thinking for phones without buttons or touchscreen cars)
Makes no sense to write scripts in C++. I've worked on projects where people have tried to do this, and they end up being more fragile, cumbersome and not that useful.
I think python is ok for cross-platform.
a shell is good for command line/os logic.
seriously a shell script with 'set -e' at the top, and a lot of command invocations and not much else is pretty easy for a group to maintain.
That and often making the scripts overly complex and a software project in themselves. Changes are that if you're building/deployment scripts are this complex that you are not leveraging modern tooling and platforms efficiently and re-invented the wheel in script form.
A recent example I encountered was an Ansible environment. While looking how other teams had set up their playbooks for something, I came across an extremely complex one. It basically pulled a bunch of java apps from artifactory and wrapped them in complex bash logic. All of this to do some conditional checks and send out a mail through a custom java mail client.
This amounted to over a hundred lines of code that I could replace with a handful of lines in Ansible.
I think this point is especially important for C++ projects. It is my gut feeling that C++ and Python cluster very closely in terms of developer familiarity. That is, a C++ developer very likely is also a passable Python developer.
Given that it tends to take more time to write a C++ program than the equivalent Python program, the stable result is that many C++ projects 1) expose C++ to Python (via e.g. pybind11) and 2) write all scripts in Python.
And you get almost all of the benefits that the article suggests, because almost all C++ developers are also Python developers.
/Serious!
1. Scripts should be maintained and tested, and
2. The language used for scripts necessarily is and should be treated as a project language, and the appropriateness of that choice should have all the factors that go into choosing a langauge for any other purpose, including the impact on complexity if it isn't the main language and fitness for purpose and any additional dev platform, tooling, etc., constraints it imposes, but...
This doesn't imply scripts should be in the main project language, any more than it is generally the case that projects must be monolingual.
But that does not imply you know how to get the creation date of a file or how to zip a directory.
> Internal language APIs can be leveraged, which drastically changes the mental model to write the script (for the better)
That sounds like a rather empty statement.
> Scripts feel more natural and eventually maintainability increases. Team members are familiarized with the language!
Don't you think familiarity with the OS (or OSes) comes first? And that knowledge usually comes with the knowledge of a shell or batch language.
> Development machines compatibility increases. Windows users can finally run all scripts.
Script development time increases, too. And Windows has WSL nowadays.
In fact my "scripts" are actually part of the main executable. I use cmd-line args to invoke the needed functionality.
For example, in the past I would have written a Python script to deploy my Go binary to a server, possibly using tools like Fabric that provide functionality to make it easier.
Today I add `-deploy-hetzner` cmd-line to my Go binary and it does the work. It builds itself, copies the binary to the server, kills the old instances, configures caddy if needed, starts newly uploaded instance etc.
For example my deploy.go is 409 lines of code, which is not that bad. You can see exactly how this works: https://github.com/kjk/edna/blob/main/server/deploy.go
I standardized on how I deploy things so deploy.go is mostly re-used among several projects.
Writing this code isn't much more difficult that what I used to write in Python.
This kind of code can be shorter because I don't have to handle errors, I just panic if something goes wrong.
I like that I don't have to switch between different languages and that I have full control and understanding over what happens. Fabric used to be a bit of a black box.
I even wrote an article about this idea: https://blog.kowalczyk.info/article/4b1f9201181340099b698246...
Candidly I think that it's much easier to do this in go (or rust), rather than say python/ruby/node as I can use complied binaries without needing a run time.
Edit: //go:build ignore is idiomatic
The best example of this, and a decent util is this: https://go.dev/src/crypto/tls/generate_cert.go
All of the real testing happens elsewhere this just provides utility.
No per-platform install instructions, no “ok but you have to run this in WSL2… you don’t have that? Oh god, ok, let’s find those instructions…”, no “oh fuck the flags for that are different on BSD and Linux, so this breaks on macOS”. “Wait the command’s python3 not python, on your system? And also it’s erroring even after you fix that? Shit you’re still on 3.8, we use features that weren’t included until 3.10…”
“Unzip this single binary and run it. Tell your OS to trust it if it hassles you. That’s it.”
C# with mono might be close to as good? Not sure. Rust’s probably OK but a bit of an investment when you’re just trying to dash off some quick tool or script. C++ and C can do it but you definitely don’t want to. Java’s obviously out (ok, now update your JRE… wait, your env vars are all fucked up, hold on…).
Go’s also highly likely to be something another developer with or without Go experience can read and tweak after the person who wrote it leaves, without much trouble.
go run cmd/server/main.go --task db --args migrate
go run cmd/server/main.go --task cron --args reset-trial-accounts
etc.
I'm OK with python for scripts, but go "just works".
I think Go scripts have a much better odd of “just working”with only the Go toolchain installed.
And you haven't addressed the issue that whoever is performing the role of DevOps on this project must know Go.
Unfortunately, you missed it too.
Which is not something that one professional needs to be in order to have to perform some duties that fall within the role of DevOps.
I am, first and foremost, an application developer using Python and JavaScript. But I also have extensive experience:
- setting up Docker Swarm clusters
- managing cloud infrastructure with Terraform
- configuring deployments with Ansible
- setting up observability on Prometheus/Loki/Grafana stack
- putting up together CI servers for my team
- setting up backup/restore infrastructure.
- deploying and managing internal OSS tools for a dev/data team: Gitea, Taiga, Redash, Apache Airflow, Baserow...
These are all tasks that could be part of a "DevOps Engineer" job description, but if you tell me that "to work with a primarily Golang dev team you need to pick up Golang", I'd be assuming that you are not looking primarily for a DevOps Engineer, but a Go Developer who can do DevOps. And because I am not a Go Developer, you'd be putting my whole application on the bottom of the Stack.
My point was, is that the DevOps person needs to be smart enough to pick up Go, which I'm sure you are.
Any hiring manager that puts your whole application on the bottom of the stack because of a lack of experience isn't a good hiring manager and isn't worth your time.
I've never seen these tools used in this capacity, especially nix.
From a Nix user's perspective, this leaves a lot to be desired, because tools like Terraform are much less reliable than Nix tools that target local machines, and their management of, say, a VPC, is much less comprehensive than NixOS' management of an individual operating system. And they're slow as hell. But for the most part these issues are inherited from the APIs cloud providers expose, which don't meaningfully or uniformly support immutability.
--
1: https://github.com/terranix/terranix
Anyway, for the specific case of "deploying to hetzner":
- ansible has a whole collection of modules for hetzner: https://docs.ansible.com/ansible/latest/collections/hetzner/...
- For Nix, there is NixOps
- if no one in the team wants to learn any of that, Hetzner provides a CLI to interact with their whole cloud.
To repeat: the last thing I'd want from an application is to have its own deployment system.
Well they'd run into the same problem if the script was Python, wouldn't they?
And Go is ultimately far far easier to read, modify[1] and debug for someone who doesn't know it than Python is.
[1] For example, adding a third-party library to handle new cases. I've never had a good time doing it with Python's various package management, but Go seems pretty good at it.
No, they would just use whatever tool is more appropriate for the job.
Fabric would be fine, ansible would be fine, salt would be fine, putting it on Docker and deploying via compose would be fine. None of these tools force you to learn the implementation details of the application.
That still leaves them the problem of "If I don't know this tech stack, what do I do?"
You are working on the assumption that everyone already knows Fabric, Ansible, salt or Docker.
Whichever poison you choose, people who don't know that particular poison won't know how to install to a different provider anyway!
You're making an argument against one particular poison, but I don't see it as any better or any worse than the others, which all have enough complexities to fill a book.
If you don't know how to use a tool that does one job, either you learn it or you just delegate that job to someone who knows it already. But defending the practice of having your application code also responsible in dealing with deployment and packaging smells a lot of "coders are gonna code".
I already started replacing parts of my shell scripts with Golang programs and the experience is miles ahead.
And if the project is already written in Golang, it makes even more sense if the dev is also partially the DevOps. Why wouldn't they make the experience as seamless as possible for themselves and the rest of the dev team? What good would Ansible do if everyone has to yet learn it?
As for the person you originally replied to, I'd definitely make a separate program that provides tooling related to the main program... but that's the only different thing I'd do.
Your snarky "coders gonna code" comment is detached from reality, we have jobs to do, and within deadlines.
You could say the same thing about Java or C++. Would you argue then that the best way to deploy java applications is by writing a java library and embed into your program?
> if the project is already written in Golang, it makes even more sense if the dev is also partially the DevOps.
I really don't see how that one follows from the other, and I really don't understand this conflation between roles and tooling. There is a lot more to "DevOps" than packaging/distributing/deploying. It's not just because your application code is in Go that your tooling needs to be as well.
> Why wouldn't they make the experience as seamless as possible for themselves and the rest of the dev team?
Because it's a fragile solution. You are tying the implementation of your problem to a very narrow space out of immediate convenience. I've had my share of projects with "experienced" node.js developers who are trying to do everything in node instead of reaching out of their comfort zone and looking for existing solutions elsewhere.
> we have jobs to do, and within deadlines.
Yeah, and a lot of those jobs could have been made in a fraction of the time if the developers were not trying to use their screwdrivers as hammers, and put some effort to figure out how to use the hammer in the first place.
Did you deliberately ignore the part when I asked why would a team of devs learn Ansible if they don't know it? No, it's not fraction of the time at all, in fact it might balloon to weeks in the ideal bad conditions.
Most people would opt for something they already know and that's a fact of life. Learning Ansible or Fabric on-demand is not exactly an optimal expenditure of time and energy, not to mention that a proper DevOps professional would know various gotchas that a learning dev will absolutely miss. Sure the dev will EVENTUALLY get there. "Eventually" being the key word. Why risk botching stuff in the meantime?
> Because it's a fragile solution
Says you. I do Rust scripting in my Rust projects, Golang scripting in my Golang projects, and Elixir scripting in the Elixir ones. Works really well. Not necessarily for deploying and DevOps work, mind you, but for a lot of stuff like "populate me this sample data so I can experiment with the app" or "start only these parts of our app so we can do an integration test with them after" etc.
I also did part of the deployment actions, not all though, if that makes a difference. I don't know the exact situation of the person you replied to.
> You could say the same thing about Java or C++
Huge, huge disagree here, probably the biggest I ever expressed on HN. :D
So many environment variables, compiler switches, and various runtime dependencies and so many other things that it's not even worth starting, it can fill up a PhD thesis and have room for more after.
Your statement cannot be more wrong if it tried. I have several serious objections to the Golang the language that prevent me from adopting it as a main career choice -- but its portability and distribute-friendliness are one of the best in the world right now. You can criticize it for a lot but criticizing it for these two things would be severely uninformed.
> I really don't see how that one follows from the other, and I really don't understand this conflation between roles and tooling. There is a lot more to "DevOps" than packaging/distributing/deploying. It's not just because your application code is in Go that your tooling needs to be as well.
Sure there's more to DevOps, I agree, but I was under the impression that the guy you replied to was tasked with doing part of DevOps so he found a way of doing it with less friction.
Conflation between roles and tooling is unfortunate indeed and I sympathize with your statement there. It's simply an artifact of imperfect work conditions (so 99.999% of all work places).
I can relate to your frustration about non-optimal processes but you are overreacting a bit.
Can their homegrown solution backfire? Absolutely, of course it can. But often times we have to make do with what we have right now and can't optimize for the far future.
If a DevOps wants to pick up the torch and do the job properly they are free to do so but yet again, I was under the impression that the person in question was wearing several role hats at the time.
Which is well within the role of the developer. "Deploy to Hetzner" is not.
> I was under the impression that the person in question was wearing several role hats at the time.
Sure, I also have to do everything on my own in my own projects. But again, the function determines the tool, not the person performing the job. When I'm wearing my application developer hat, you'll see try to do as much as possible with Python, but that doesn't mean that I will try to turn every problem into a python script.
Well, OK, I can't argue with that as much. Maybe the guy truly found it easier to do so? No clue. I know I'd definitely try with a shell script, then with the project's language, and only then with a dedicated tool. As much as I try to be a good senior backend dev -- and I know a lot of stuff and tooling that are not at all mandatory for my role -- I still can't find the time and energy to become a properly good DevOps; too much investment, and for specific cloud platforms. To this day I can't justify it and can't make myself "git gud" with AWS.
> When I'm wearing my application developer hat, you'll see try to do as much as possible with Python, but that doesn't mean that I will try to turn every problem into a python script.
No you really should not, Python is a nightmare in portability. I can trivially use venv-s and other tooling to make sure stuff is isolated and works fine but the whole house of cards is still always just one `brew upgrade` command away from falling apart. Eventually I've given up. If Python can't be trivially made portable then it's a bad tool for scripting, no matter what many people think and say (in fact, a lot of people using a tool often times speaks badly for its quality; to me "Python is good" is a mass delusion but that's a huge topic in itself that I won't tackle here). The fact that many people don't know anything else but Python is not an excuse.
Golang is a much better choice for quick scripting and that's a demonstrable fact. You can parse CLI flags and use their values and even throw some validation is some 10-15 coding lines and from then on you can use various super-useful libraries; there even exist a few that emulate a number of UNIX tools so you can still have a single binary that can do a lot without depending on anything except a kernel being present in the system (which also makes the resulting binary very convenient in constrained / container environments).
You might think I am getting hung up on details but I felt that I have to debunk the idea that Python is a good scripting tool. No it really isn't, and most Python devs never test on a random Mac or Linux machine where the dev is NOT using Python as a primary language. It's a fragile mess.
But now we're arguing in circles about familiarity. :) I recognize the irony. But for what it's worth, I didn't know Golang and made it a goal to learn it long time ago because I liked its distribution story and (mostly) ease of use (with a bunch of caveats nowadays, sadly).
How is that different from "If you don't know how to use the tool (Go), either you learn it or you just delegate that job to someone who knows it."?
> But defending the practice
Woah there cowboy, I wasn't advocating an architectural decision suitable for a FAANG. I was "defending" the position of "why you an extra tool for this one program that has no other dependencies?"
> of having your application code also responsible in dealing with deployment and packaging smells a lot of "coders are gonna code".
In much the same vein, switching to Ansible, Fabric, etc simply to install a single binary to a single place smells a lot like "resume-driven-development".
For a project where multiple people are involved, I think it's better to split concerns. Deployment should be handled transparently and reproducible in a CI pipeline that the team members who are allowed to deploy have access to.
I don't care how you prefer to do things on your own, but if I were interviewing you for a senior position in a team with a handful of people, and you tell me that's how you want them to work, it would be an almost immediate NO HIRE.
OP's comment was "I do this for my Go project's" and goes on to describe how to use a (open source) library that even deploys to Hetzner.
So, either the commenter was trying to extend their practice to the point of the blog post or the comment was just expressing a preference when working by themselves, which has little to do with the content of the post.
If a deployment procedure is easy for non-DevOps people then by definition that also makes it friendly to programmers, so why wouldn't they do it if it they can do it properly with minimal effort. But I do realize that "properly" is doing a lot of work in this sentence.
Have windows users use WSL (the VSCode integration is great!), and mac users should install GNU tools since the system tools are obnoxiously incompatible.
The only time I've found that scripts should be in another language is:
1. You need to call libs that to do something fancy and it would be too troublesome to make a small Unix style executable to do the thing. 2. The developers on your team lack Unix/bash experience, and you don't trust them to learn in a timely manner (sad).
Unless you're doing some extremely niche work, Bash >= 3.2 (because Mac) is nearly always going to be available. Even if it _isn't_, there will still be sh or dash, and it's not _that_ hard to stick with pure POSIX for most small uses.
The last time I (by which I mean my team) rewrote a script from Bash into Python was because it had gotten unwieldy over time, I was the sole maintainer, and very few other people at the company knew Bash well enough to understand some of it. The upside was testing frameworks in Python are way better than Bash.
Maybe this is what Perl is for, but I never learned it.
At that point you might as well target Python 3.6. Seems like the same hassle for the developer to install and you don't have to worry about wonky differences for users who haven't installed GNU tools, but still think they can run your script because it says `.sh`
The package.json scripts "work", but it's quite clunky, and relying on shell scripts that run node.js scripts causes issues. (cross-env solving a problem that really shouldn't exist.)
I’m sure there’s something like rake that exists for Node, but the community won’t standardise on it because it’s not enough a problem
These days I'm much more comfortable both writing and maintaining code in languages that aren't my daily driver (like Bash or jq or AppleScript or even Go) because I can get an LLM to do most of the work for me, and help me understand the bits that don't make sense to me.
Granted, this probably takes a fair amount of experience to even know what you're looking at well enough to search for it.
I trust LLMs with tools like Bash and jq and ffmpeg which have been around for years. I wouldn't trust them with anything released within the past 12-24 months.
An example from just the other day: https://til.simonwillison.net/go/installing-tools
I wanted to understand this:
How does that @latest reference mention? There's no branch or tag on that repo called "latest".I tried and failed to find documentation. I gave up and asked GPT-4, which said:
> @latest: This specifies the version of the package you want to install. In this case, latest means that the Go tool will install the latest version of the package available. The Go tool uses the versioning information from the repository's tags to determine the latest version. If the repository follows semantic versioning, the latest version is the one with the highest version number. If there are no version tags, latest will refer to the most recent commit on the default branch of the repository.
Is that correct? I have no idea! But it still gave me more to go on than my failed attempts with the real documentation.
I don't think it's a requirement, but it's an advantage
I think of scripts as the middleware between the operating system and the shipped code. The code is controlled by the operating system, so the operating system's tools should be used to manage it. In many cases this means bash or make.
Plus, I don't want modern Javascript to do things on the filesystem that would require importing dozens of projects that I need to vet before using. Golang or Python perhaps, but the buildchain for modern Javascript is hell as-is; it doesn't need another layer of Javascript.
Scripts should be testable.
Scripts should use functions with appropriately scoped variables. (This really helps with testability)
Scripts should list assumptions.
Scripts should CHECK assumptions.
Scripts should call commands with --long-style-options instead of -L, especially uncommon options.
---
As someone who migrated a couple hundred shell scripts over the past year, I'd rather have these done before I ask someone to write a script in C.
edit: and for ${deity} sake, use shellcheck.
Too bad `getopts` only supports single-char options. :p
And to be more specific - I meant when the script calls someone else, not how it handles options.
... as long as that main language is a scripting language. Otherwise it's just dumb.
Also, tunnel vision by the author: "Almost all projects I’ve worked on have scripts we wrote to automate a repetitive process. "
Well almost all projects I’ve worked on have scripts we wrote to automate a ONE-TIME process. Like collect some data from the log to figure out a bug, fix it and forget about both the bug and the script. Automate it since can't manually process 30Gb of data and grep only can do so much. Sure as funk won't write the "script" in C++ but Python or Perl or something.
Personally, I prefer writing shell scripts regardless of what the main language is in a given project. They're portable (more or less), and can e.g. detect missing dependencies and install them if necessary, which isn't possible with the main language if you're missing its compiler or interpreter.