I actually love listening to or reading someone else’s war story, and tbh the entire purpose of this post is to dig those up. Bash is one of those places where a lot about it is passed around as tribal knowledge. So I’d really love to hear how things have failed.
- Posts
- 1
- Comments
- 56
- Joined
- 3 yr. ago
- Posts
- 1
- Comments
- 56
- Joined
- 3 yr. ago
This is almost a strawman argument.
You don’t have to shell out to a db cli. Most of them will gladly take some SQL and spit out some output. Now that output might be in some tabular format with some pretty borders around them that you have to deal with, if you are about the output within your script, but that’s your choice and so deal with it if it’s within your comfort zone to do so. Now if you don’t care about the output and just want it in some file, that’s pretty straightforward, and it’s not too different from just some cli that spits something out and you’ve redirected that output to a file.
I’ve mentioned in another comment where if you need to accept input and use that for your queries, psql is absolutely not the tool to use. If you can’t do it properly in bash and tools, just don’t. That’s fine.
With web API calls, same story really; you may not be all that concerned about the response. Calling a webhook? They’re designed to be a fire and forget, where we’re fine with losing failed connections. Some APIs don’t really follow strict rules with REST, and will gladly include an “ok” as a value in their response to tell you if a request was successful. If knowing that is important to the needs of the program, then, well, there you have it. Otherwise, there are still ways you can get the HTTP code and handle appropriately. If you need to do anything complex with the contents of the response, then you should probably look elsewhere.
My entire post is not to say that “you can do everything in bash and you should”. My point is that there are many cases where bash seems like a good sufficient tool to get that simple job done, and it can do it more easily with less boilerplate than, say, Python or Ruby.
That’s my take on the use of bash too. If it’s something that people think it’s worth bring their pitchforks out for, then it’s something you should probably not write in bash.
To each their own really. You have what you’re familiar with, and I have mine. That said, I’m not proposing Bash as a good language. It is by no means that.
Now, to use Python for comparison. With a year of not using it, I’d be asking lots of questions. How do I
mkdir? How do Imkdir -p? What aboutcpormvand their flags? Did I use to bring in some library to make this less painful?Cause look, I already use many of these commands in the terminal, basically all the time cause I work in it.
Fwiw, there’s a
bash-language-serverthat can warn you of some syntactical errors.That is definitely not something I would do… for work (totally not implying that I miiiight do it outside of work for shits and giggles :P).
I didn’t create this post trying to be like “y’all should just use Bash”, nor is it an attempt to say that I like Bash, but I guess that’s how people boil others down to these days. Fanatics only. Normalcy is dead. (I’m exaggerating ofc)
I’m so glad we have madlads in rust land xD Thanks for referring me to that!
Your experiences are based on your familiarity with other languages. It may or may not apply to others. So to each their own I guess?
I do agree that the square bracket situation is not best though. But once you know it, you, well, know it. There’s also shellcheck to warn you of gotchas. Not the best to write in, but we have linters in most modern languages for a reason.
I actually like bash’s variable expansion. It’s very succinct (so easier to write and move onto your next thing) and handles many common cases. The handling is what I hope most stdlibs in languages would do with env vars by default, instead of having to write a whole function to do that handling. Falling back is very very commonly used in my experience.
There are cases where programming is an exercise of building something. Other times, it’s a language, and when we speak, we don’t necessarily want to think too much about syntax or grammar, and we’d even invent syntaxes to make what we have to say shorter and easier to say, so that we may speak at the speed of thought.
That’s definitely worth mentioning indeed. Bash variables, aside from arrays and hashmaps that you get with
declare, are just strings. Any time you need to start capturing a group of data and do stuff with them, it’s a sign to move on. But there are many many times where that’s unnecessary.To be fair, you don’t always have to use the
[[syntax. I know I don’t, e.g. if I’m just looking for a command that returns 1 or 0, which happens quite a bit if you get to usegrep.That said,
man testis my friend.But I’ve also gotten so used to using it that I remember
-zand-nby heart :PI can only imagine that macro crate being a nightmare to read and maintain given how macros are still insanely hard to debug last I heard (might be a few years ago now).
I find this argument somewhat weak. You are not going to run into the vast majority of those errors (in fact, some of them are not even errors, and you will probably never run into some of those errors as Postgres will not return them, eg some error codes from the sql standard). Many of them will only trigger if you do specific things: you started a transaction, you’ll have to handle the possible errors that comes with having a transaction.
There are lots of reasons to never use bash to connect to a db to do things. Here are a couple I think of that I think are fairly basic that some may think they can just do in bash.
- Write to more than 1 table.
- Write to a table that has triggers, knowing that you may get a trigger failure.
- Use transactions.
- Calling a stored procedure that will raise exceptions.
- Accepting user input to write that into a table.
One case that I think is fine to use bash and connect to a db is when all you need to do a
SELECT. You can test your statement in your db manager of choice, and bring that into bash. If you need input sanitization to filter results, stop, and use a language with a proper library. Otherwise, all the failure cases I can think of are: a) connection fails for whatever reason, in which case you don’t get your data, you get an exit code of 1, log to stderr, move on, b) your query failed cause of bad sql, in which case, well, go back to your dev loop, no?This is why I asked what sort of problems have you ran into before, assuming you haven’t been doing risky things with the connection. I’m sorry, but I must say that I’m fairly disappointed by your reply.
I’m going to read this with a big “/s” at the end there xD
As one other comment mentioned, unfamiliarity with a particular language isn’t restricted to just bash. I could say the same for someone who only dabbles in C being made to read through Python. What’s this
@decoratorthing? Or what’sf"Some string: {variable}"supposed to do, and how’s memory being allocated here? It’s a domain, and we aren’t expected to know every single domain out there.And your mention of losing typing and structure information is… ehh… somewhat of a weird argument. There are many cases where you don’t care about the contents of an output and only care about the process of spitting out that output being a success or failure, and that’s bread and butter in shell scripts. Need to move some files, either locally or over a network, bash is good for most cases. If you do need something just a teeny bit more, like whether some key string or pattern exists in the output, there’s grep. Need to do basic string replacements? sed or awk. Of course, all that depends on how familiar you or your teammates are with each of those tools. If nearly half the team are not, stop using bash right there and write it in something else the team’s familiar with, no questions there.
This is somewhat of an aside, but jq is actually pretty well-known and rather heavily relied upon at this point. Not to the point of say sqlite, but definitely more than, say, grep alternatives like ripgrep. I’ve seen it used quite often in deployment scripts, especially when interfaced with some system that replies with a json output, which seems like an increasingly common data format that’s available in shell scripting.
How easily can you start parsing arguments and read env vars? Do people import clap and such to provide support for those sorts of needs?
I find it disingenuous to blame it on the choice of bash being bad when goalposts are moved. Solutions can be temporary as long as goalposts aren’t being moved. Once the goalpost is moved, you have to re-evaluate whether your solution is still sufficient to meet new needs. If literally everything under the sun and out of it needs to be written in a robust manner to accommodate moving goalposts, by that definition, nothing will ever be sufficient, unless, well, we’ve come to a point where a human request by words can immediately be compiled into machine instructions to do exactly what they’ve asked for, without loss of intention.
That said, as engineers, I believe it’s our responsibility to identify and highlight severe failure cases given a solution and its management, and it is up to the stakeholders to accept those risks. If you need something running at 2am in the morning, and a failure of that process would require human intervention, then maybe you should consider not running it at 2am, or pick a language with more guardrails.
Could you explain those db connection hiccups you’ve seen?
What do you suppose bash could do here? When a program reaches some critical mass in terms of adoption, all your bugs and features are features of your program, and, love it or hate it, somebody’s day is going to be ruined if you do your bug fixes, unless, of course, it’s a fix for something that clearly doesn’t work in the very sense of the word.
I’m sure there’s space for a clear alternative to arise though, as far as scripting languages go. Whether we’ll see that anytime soon is hard to tell, cause yeah, a good lexer and parser in the scripting landscape is hard work.
If you need anything that complex and that it’s critical for, say, customers, or people doing things directly for customers, you probably shouldn’t use bash. Anything that needs to grow? Definitely not bash. I’m not saying bash is what you should use if you want it to grow into, say, a web server, but that it’s good enough for small tasks that you don’t expect to grow in complexity.
I don’t necessarily agree that all simple tasks will lead to the need for a test suite to accommodate more complex requirements. If it does reach that point,
- Your simple bash script has and is already providing basic value.
- You can (and should) move onto a more robust language to do more complicated things and bring in a test suite, all while you have something functional and delivering value.
I also don’t agree that you can just solder on whatever small task you have to whatever systems you already have up and running. That’s how you make a Frankenstein. Someone at some point will have to come do something about your little section because it started breaking, or causing other things to break. It could be throwing error messages because somebody changed the underlying db schema. It could be calling and retrying a network call and due to, perhaps, poorly configured backoff strategy, you’re tripping up monitoring alerts.
That said, I do agree on it suitable for temporary tasks.
I honestly don’t care about being right or wrong. Our trade focuses on what works and what doesn’t and what can make things work reliably as we maintain them, if we even need to maintain them. I’m not proposing for bash to replace our web servers. And I certainly am not proposing that we can abandon robustness. What I am suggesting that we think about here, is that when you do not really need that robustness, for something that may perhaps live in your production system outside of user paths, perhaps something that you, your team, and the stakeholders of the particular project understand that the solution is temporary in nature, why would Bash not be sufficient?
Wrong assumption. I’ve been writing Bash for 5-6 years now.
Maybe it’s the way I’ve been structuring my code, or the problems I’ve been solving with it, in the last few years after using
shellcheckandbash-language-serverthat I’ve not ran into issues where I get fucked over by quotes.But I can assure you that I know when to dip and just use a “proper programming language” while thinking that Bash wouldn’t cut it. You seem to have an image of me just being a “bash glorifier”, and I’m not sure if it’ll convince you (and I would encourage you to read my other replies if you aren’t), but I certainly don’t think bash should be used for everything.
You’ll probably hate this, but you can use
set -uto catch unassigned variables. You should also use fallbacks wherever sensible.Not a good argument imo. It eliminates a good class of problems sure. But you can’t eliminate their dependence on shared libraries that many commands also use, and that’s what my point was about.
And I’m sure you can find a whole dictionary’s worth of cases where people shoot themselves in the foot with bash. I don’t deny that’s the case. Bash is not a good language where the programmer is guarded from shooting themselves in the foot as much as possible. The guardrails are loose, and it’s the script writer’s job to guard themselves against it. Is that good for an enterprise scenario, where you may either blow something up, drop a database table, lead to the lost of lives or jobs, etc? Absolutely not. Just want to copy some files around and maybe send it to an internal chat for regular reporting? I don’t see why not.
Bash is not your hammer to hit every possible nail out there. That’s not what I’m proposing at all.