Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

#0: If you're writing scripts that are destined for other users, use POSIX sh instead.


I disagree with this.

There's nothing wrong with writing bash scripts, with a shebang like `#!/usr/bin/env bash`, just like there's nothing wrong with writing python scripts (with `#!/usr/bin/env python`), or Haskell scripts (with `#!/usr/bin/env runhaskell`), or whatever other language you like/think is appropriate/etc.

It's true that bash is unavailable by default on (say) microcontrollers, but I don't see the relevance given that loads of common scripting languages aren't available by default on microcontrollers (Python, Ruby, JS, PHP, etc.).

PS: With this said, don't start your bash scripts with a `sh` path like `#!/bin/sh` or `#!/usr/bin/sh`. In fact, don't use a hard-coded path like `#!/bin/bash` or `#!/usr/bin/bash` either, always use `#!/usr/bin/env bash` unless you have a good reason not to. (Whilst `/usr/bin/env` is a hard-coded path, it can also be treated as a single special-case by systems which don't follow FHS, like NixOS, GuixSD and GoboLinux).


Bash is a special case where there exists a similar tool which is standardized in POSIX, and for most cases where sh is insufficient bash is probably insufficient too. Therefore POSIX sh is almost always the better choice.


Are you writing your scripts in sh instead of bash, perl, python, JavaScript?


I prefer sh over bash for most of my scripts, but I will sometimes use Python instead.


So you use python instead of sh, but you argue that we should use sh instead of bash, perl, or python. I'm not convinced.

IMHO, we should use proper tool for the job instead of making artificial limitations. Bash is proper tool in lot of cases, unless old proprietary OS or very limited embedded OS are targeted.


> old proprietary OS or very limited embedded OS

i.e. all the *BSDs? Many Linux distros that ship with BusyBox only or FreeBSD/Linux type systems (AFAIK Debian and also maybe Gentoo allowed FreeBSD userlands)?

POSIX Sh is quite capable. I maintain even my bashrc POSIX compatible, in order to not have any problems when I want to run my config on some remote machine, or on some local BSD installation (and I did run FreeBSD for more than a year, quite feasible option for a workstation IMO).


>So you use python instead of sh

That's not what I said

>we should use proper tool for the job

This is the implication of what I said.

I do not think that bash is the proper tool in most cases.


So it boils down to your personal taste.


For most workloads where bash is suited, so is sh. For workloads where sh is insufficient, bash probably is too and you should just use a higher level language.

Chill. You don't have to hold bash so close to your heart.


I'm author of bash-modules project. It's my attempt to create set of libraries for easier scripting on bash in strict mode. Most bash libraries are not designed for strict mode, so I created my own. If you prefer sh over bash so much, you can help me to make it compatible with sh, or just fork it.

See https://github.com/vlisivka/bash-modules


Or option three: not care about your project because bash sucks and continue to write sh without it.


I see so many #!/bin/sh scripts with bashisms in them. These scripts are broken and will cause errors. /bin/sh is not always Bash even on Linux systems. It definitely is not on BSDs. There is no reason to use Bash for shell scripts when you can do the same thing portably.


Your example shows that advise to "use /bin/sh" doesn't help but creates problem. If someone wants to write portable script, then he must test it on significant subset of target systems.


Do you know of any learning resources that are strictly POSIX sh instead of a specific shell? I'm looking to learn and it will be very helpful.



Check out this presentation: https://youtu.be/olH-9b3VJfs

And the accompanying reference site: http://shellhaters.org/


No need to learn strict POSIX shell. If you learn bash from a good guide and it should explicitly inform you about bash specific features. This way you can learn both at the same time.

On top of that you can use `checkbashisms` tool to lint your script against bash specific syntax.


Can you explain why?


For portability. bash is not available everywhere, but POSIX sh is a requirement of POSIX so you can expect it to be there.


Exactly: GNU bash is on most GNU/Linux systems, but:

* mac OS uses an ancient version of bash

* Embedded systems use busybox sh

* Android uses its own version of sh

* None of the BSDs come with bash, since, y'know GNU licensing

EDIT: Formatting


And to make things interesting Ubuntu uses dash as sh

https://wiki.ubuntu.com/DashAsBinSh


`sh` is only supposed to be _a_ POSIX-compliant shell, it's not odd/interesting/confusing that Ubuntu uses dash any more than it is that something else uses bash.

The shebang line #!/bin/sh should only be used for POSIX-compliant scripts; if it needs {bash, dash, python, etc.} it should start #!/usr/bin/env {bash, dash, python, etc.}.


In fairness, that's just for sh; if for some reason you actually need bash you can just use `#!/usr/bin/env bash`


If you actually //need// bash ask for it, not sh.

This comes from more armature script authors not being precise enough with requirements, or not targeting the more common and portable spec.


Not all systems have bash.


Not all systems have POSIX, perl, python, javascript, C++, rust, go, etc., so should we write all our programs and scripts in sh?


The relevant point is that all systems running bash should also be POSIX compliant. So, taking some care to avoid bash-only constructs in a shell script can reap substantial gains in portability at fairly minor cost.


Why I should care about all systems? If targeted systems have bash4.x and GNU tools, why I should write scripts in sh? If you care about all systems, ANSI C is better choice, IMHO.


If you're targeting a limited set of systems and can reasonably assume the requirements won't change in the future, obviously use whatever tools you know will be available. I write Bash and Python all the time for those reasons.

But it's silly to think that there's nothing in between "complete control over target environment" and "use ANSI C so it can be compiled to any architecture and platform under the Sun." POSIX compliance will cover a lot. Try browsing /usr/bin on any Unix system you'll see plenty of use cases. I just looked at /usr/bin on my laptop and saw that mysqld_safe is a Bourne shell script, for just one example.


less magic (which you start to care for if you have to use other people's magic), easier to port stuff to zsh, etc.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: