Running Bash on Linux, macOS, WSL, and Git Bash
Bash runs on several operating environments, but those environments are not identical. A script that behaves correctly on Ubuntu may encounter an older Bash on macOS or different utilities in Git Bash. This lesson helps you build a predictable lab before deeper automation.
Learning objectives
By the end of this lesson
- Check whether Bash is installed and determine its exact version.
- Choose a recommended practice environment on Linux, macOS, or Windows.
- Understand important differences among GNU/Linux Bash, macOS Bash, WSL, Git Bash, and containers.
- Create a project directory with a repeatable layout for scripts, data, logs, and tests.
- Verify that core tools used later in the course are available before relying on them.
1. Choose a primary Bash lab
For a DevOps-focused Bash course, the clearest primary environment is a current Linux distribution with a recent Bash release. Ubuntu LTS or another mainstream Linux VM gives you a complete host environment while remaining easy to reset.
Linux VM
Closest to common server and CI environments. Snapshots provide safe rollback for later labs.
WSL 2
Provides a real Linux user space and is an excellent Bash environment on Windows.
Homebrew Bash
macOS includes Bash, but its bundled version is historically old. A newer Bash can be installed separately.
Git Bash
Useful for Git-oriented shell work on Windows, but it is not a complete Linux environment and some utilities differ.
2. Detect Bash and its version
Do not build a script around a feature until you know which Bash version is guaranteed on the target systems.
command -v bash || {
printf 'Bash is not available on PATH\n' >&2
exit 1
}
bash --version | head -n 1
printf 'current BASH_VERSION=%s\n' "${BASH_VERSION-<not running bash>}"
# Major version, when currently running Bash
if [[ -n ${BASH_VERSINFO+x} ]]; then
printf 'major=%s minor=%s patch=%s\n' "${BASH_VERSINFO[0]}" "${BASH_VERSINFO[1]}" "${BASH_VERSINFO[2]}"
fi
Features such as associative arrays and mapfile require Bash rather than generic POSIX sh, and very old Bash releases may lack improvements you expect.
3. Bash is only one part of portability
Many shell scripts fail across platforms because of external utility differences, not because of Bash itself. GNU and BSD variants of common commands can have different options.
dateGNU coreutilsBSD/macOS flags differsedGNU sedIn-place editing syntax differsreadlinkGNU options often assumedmacOS feature set differsDefine the supported platform matrix. “Runs in Bash” is not a sufficient compatibility statement if your script also depends on specific versions of grep, sed, find, jq, or other tools.
4. Bash choices on Windows
On Windows, two common options serve different goals:
Linux user space
Best when the target is Linux infrastructure, containers, cloud hosts, CI runners, and production operations.
Unix-like command environment
Convenient for Git and light shell workflows. Paths, process behavior, and tool availability do not exactly match Linux.
Disposable Linux shell
Good for version-specific tests, but not a replacement for full host labs involving services, boot, or persistent system state.
# In any environment, collect facts before assuming behavior:
printf 'bash=%s\n' "$BASH_VERSION"
printf 'ostype=%s\n' "$OSTYPE"
uname -srm
command -v sed
command -v awk
command -v grep
# WSL commonly exposes WSL-specific markers:
if grep -qi microsoft /proc/version 2>/dev/null; then
printf 'WSL-like Linux environment detected\n'
fi
5. Create a repeatable course workspace
Use a predictable directory tree so commands can be copied between lessons without depending on random working directories.
mkdir -p "$HOME/devops-academy/bash"/{bin,data,logs,tmp,tests}
cd "$HOME/devops-academy/bash"
printf '%s\n' '# Bash Course Workspace' '' '- bin/: scripts' '- data/: sample inputs' '- logs/: generated logs' '- tmp/: disposable lab state' '- tests/: later automated tests' > README.md
find . -maxdepth 1 -type d -print | sort
cat README.md
Verification checklist
6. Build a tool preflight instead of failing mysteriously
Production scripts should detect critical dependencies early and emit actionable errors.
required=(bash grep sed awk find)
missing=()
for tool in "${required[@]}"; do
command -v "$tool" >/dev/null 2>&1 || missing+=("$tool")
done
if ((${#missing[@]})); then
printf 'Missing required tools: %s\n' "${missing[*]}" >&2
exit 127
fi
printf 'Preflight passed\n'
You will learn arrays and robust error handling later. For now, focus on the principle: validate prerequisites explicitly.
7. Knowledge check
Question 1. Why is WSL generally preferable to Git Bash for Linux-focused DevOps labs?
Question 2. Why can the same Bash script still fail across Linux and macOS?
Question 3. Why should a production script check dependencies at startup?
8. Summary
A dependable Bash environment is defined by more than the presence of a bash executable. Bash version, operating system, external utility variants, filesystem behavior, line endings, and available dependencies all affect automation. Establish your supported platform matrix and verify it explicitly.
9. Further reading
- GNU Bash Reference Manual — Bash Invocation and Shell Compatibility Mode.
- Microsoft WSL documentation — Linux distributions, filesystems, and interop behavior.
- Apple shell scripting documentation and macOS manual pages.
- Git for Windows documentation — Git Bash environment and bundled tools.
- POSIX utility specifications for portable external-command behavior.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.