title: POSIX sh and shebangs
date: 2021-01-17
layout: post
lang: en
ref: posix-sh-and-shebangs
As I [keep moving][posix-awk-0] [towards POSIX][posix-awk-1], I'm on the process of migrating all my Bash scripts to POSIX sh.
As I dropped [[
, arrays and other Bashisms, I was left staring at the first line of every script, wondering what to do: what is the POSIX sh equivalent of #!/usr/bin/env bash
?
I already knew that POSIX says nothing about shebangs, and that the portable way to call a POSIX sh script is sh script.sh
, but I didn't know what to do with that first line.
What I had previously was:
#!/usr/bin/env bash
set -Eeuo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
Obviously, the $BASH_SOURCE
would be gone, and I would have to adapt some of my scripts to not rely on the script location.
The -E
and -o pipefail
options were also gone, and would be replaced by nothing.
I converted all of them to:
#!/bin/sh -eu
I moved the -eu
options to the shebang line itself, striving for conciseness.
But as I changed callers from ./script.sh
to sh script.sh
, things started to fail.
Some tests that should fail reported errors, but didn't return 1.
My first reaction was to revert back to ./script.sh
, but the POSIX bug I caught is a strong strain, and when I went back to it, I figured that the callers were missing some flags.
Specifically, sh -eu script.sh
.
Then it clicked: when running with sh script.sh
, the shebang line with the sh options is ignored, as it is a comment!
Which means that the shebang most friendly with POSIX is:
#!/bin/sh
set -eu
- when running via
./script.sh
, if the system has an executable at/bin/sh
, it will be used to run the script; - when running via
sh script.sh
, the sh options aren't ignored as previously.
TIL.
[posix-awk-0]: {% link _tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.md %} [posix-awk-1]: {% link _tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md %}