• 2 Posts
  • 366 Comments
Joined 1 year ago
cake
Cake day: September 24th, 2023

help-circle

  • You’ve essentially dissed people who use it for CI/CD and suggested that their pipeline is not robust because of their choice of using Bash at all.

    Yes, because that is precisely the case. It’s not a personal attack, it’s just a fact that Bash is not robust.

    You’re trying to argue that your cardboard bridge is perfectly robust and then getting offended that I don’t think you should let people drive over it.

    About shared libraries, many popular languages, Python being a pretty good example, do rely on these to get performance that would be really hard to get from their own interpreters / compilers, or if re-implementing it in the language would be pretty pointless given the existence of a shared library, which would be much better scrutinized, is audited, and is battle-tested. libcrypto is one example. Pandas depends on NumPy, which depends on, I believe, libblas and liblapack, both written in C, and I think one if not both of these offer a cli to get answers as well. libssh is depended upon by many programming languages with an ssh library (though there are also people who choose to implement their own libssh in their language of choice). Any vulnerabilities found in these shared libraries would affect all libraries that depend on them, regardless of the programming language you use.

    You mean “third party libraries” not “shared libraries”. But anyway, so what? I don’t see what that has to do with this conversation. Do your Bash scripts not use third party code? You can’t do a lot with pure Bash.

    If your temporary small script morphs into a monster and you’re still using bash, bash isn’t at fault. You and your team are.

    Well that’s why I don’t use Bash. I’m not blaming it for existing, I’m just saying it’s shit so I don’t use it.

    You could use Deno, but then my point stands. You have to write a function to handle the case where an env var isn’t provided, that’s boilerplate.

    Handling errors correctly is slightly more code (“boilerplate”) than letting everything break when something unexpected happens. I hope you aren’t trying to use that as a reason not to handle errors properly. In any case the extra boilerplate is… Deno.env.get("FOO"). Wow.

    What’s the syntax for mkdir? What’s it for mkdir -p? What about other options?

    await Deno.mkdir("foo");
    await Deno.mkdir("foo", { recursive: true });
    

    What’s the syntax for a dictionary in Bash? What about a list of lists of strings?




  • And I certainly am not proposing that we can abandon robustness.

    If you’re proposing Bash, then yes you are.

    You’ll probably hate this, but you can use set -u to catch unassigned variables.

    I actually didn’t know that, thanks for the hint! I am forced to use Bash occasionally due to misguided coworkers so this will help at least.

    But you can’t eliminate their dependence on shared libraries that many commands also use, and that’s what my point was about.

    Not sure what you mean here?

    Just want to copy some files around and maybe send it to an internal chat for regular reporting? I don’t see why not.

    Well if it’s just for a temporary hack and it doesn’t matter if it breaks then it’s probably fine. Not really what is implied by “production” though.

    Also even in that situation I wouldn’t use it for two reasons:

    1. “Temporary small script” tends to smoothly morph into “10k line monstrosity that the entire system depends on” with no chance for rewrites. It’s best to start in a language that can cope with it.
    2. It isn’t really any nicer to use Bash over something like Deno. Like… I don’t know why you ever would, given the choice. When you take bug fixing into account Bash is going to be slower and more painful.

  • I’m afraid your colleagues are completely right and you are wrong, but it sounds like you genuinely are curious so I’ll try to answer.

    I think the fundamental thing you’re forgetting is robustness. Yes Bash is convenient for making something that works once, in the same way that duct tape is convenient for fixes that work for a bit. But for production use you want something reliable and robust that is going to work all the time.

    I suspect you just haven’t used Bash enough to hit some of the many many footguns. Or maybe when you did hit them you thought “oops I made a mistake”, rather than “this is dumb; I wouldn’t have had this issue in a proper programming language”.

    The main footguns are:

    1. Quoting. Trust me you’ve got this wrong even with shellcheck. I have too. That’s not a criticism. It’s basically impossible to get quoting completely right in any vaguely complex Bash script.
    2. Error handling. Sure you can set -e, but then that breaks pipelines and conditionals, and you end up with really monstrous pipelines full of pipefail noise. It’s also extremely easy to forget set -e.
    3. General robustness. Bash silently does the wrong thing a lot.

    instead of a import os; os.args[1] in Python, you just do $1

    No. If it’s missing $1 will silently become an empty string. os.args[1] will throw an error. Much more robust.

    Sure, there can be security vulnerability concerns, but you’d still have to deal with the same problems with your Pythons your Rubies etc.

    Absolutely not. Python is strongly typed, and even statically typed if you want. Light years ahead of Bash’s mess. Quoting is pretty easy to get right in Python.

    I actually started keeping a list of bugs at work that were caused directly by people using Bash. I’ll dig it out tomorrow and give you some real world examples.





  • They definitely didn’t. Yes it is technically better to use their own new fancy system, but they’re a business. Backwards compatibility is killer, even if you don’t want it from a technical point of view.

    I guarantee they looked at the numbers, interviewed users and asked them why they weren’t using Deno, and the number one reason would have been “we’d love to but we need to be able to use the X node package”.

    They probably have to improve Node compatibility, but the Node API surface is actually not that big. They’ll get there.


  • Yes, and then pass the context from the call sites of that function, and all the way up to main(). Oh look you’re refactored the entire app.

    That’s best cases too, you’d better hope your program isn’t actually a shared library running in a SystemVerilog simulator with state instantiated from separate modules via DPI, or whatever.

    30 years my ass

    lol when you have 30 years experience you will have actually tried to do this a few times and realised it isn’t usually as trivial as you hope it would be.










  • There are arguments to be made either way, but normally you’d scope your variables in a way that the ones specific to a particular bit of code are not accessible from elsewhere.

    Sounds like you agree with that one to me? I’m not sure I follow their arguments about regions there (I’ve never used regions), but the example of declaring a variable in a block way before it is every used is spot on. I’ve seen code written like that and 99% of the time it’s a bad idea. I think a lot of it comes from people who learnt C where you have to do that (or maybe Javascript which has weird rules for var).

    Suggest writing a custom class to do what most languages can solve with inheritance or even better: the ? syntax.

    Yeah I’ll give you that one. They even suggest using Optional as a solution, which is what their “smelly” code did in the first place!

    Yes, it can be annoying. No, clarity is more important than insisting on removing that extra underscore.

    Not sure what your point is here. Of course inconsistent naming is a code smell. Do you want inconsistent names?

    They’re advocating the use of a function to replace an expression. Sometimes this works, but the task of a boolean expression is not always easily expressed in a couple words. And so you can end up with misleading function names. Instead, just put a comment in the code.

    Erm, yeah that’s why this is a code smell. They aren’t saying never have complex boolean expressions - just that if you do you’d better have a good reason because probably you’d be better off splitting it up into named parts.

    callback hell - Not even a code smell. It’s an issue from back when languages like JavaScript didn’t support promises yet, but callbacks were popular.

    Indeed, so now it is a code smell.