Bash Script Basics for DevOps
In DevOps work, many daily tasks are repetitive: checking disk usage, verifying whether a service is still running, backing up configuration files, collecting logs, or running a simple deploy sequence. If you do everything manually step by step, it is easy to forget commands, mistype options, or lose time when you need to repeat the same work across multiple servers.
Bash Script helps package those commands into a file that can be run again and again. This is a foundational skill before going deeper into CI/CD, Docker, Kubernetes, Cloud CLI, or more complex automation.
What is Bash?
Bash stands for Bourne Again SHell — a popular shell program on Linux and macOS. A shell receives commands from users, interprets them, and asks the operating system to execute them.
When you type commands in a terminal such as:
| |
you are interacting with a shell. When you put multiple commands into a text file, that file becomes a shell script. According to the official GNU Bash documentation, a shell script is a text file containing shell commands; when Bash runs it, Bash reads and executes the commands in the file, then exits.
Why should DevOps engineers know Bash?
Bash does not replace tools like Ansible, Terraform, or Jenkins, but it is a very useful glue layer for connecting tools together.
| DevOps situation | How Bash helps |
|---|---|
| Quick server checks | Combine hostname, df, free, and uptime in a script |
| Small application deployment | Run code pull, build, and service restart in order |
| Log or temporary file cleanup | Automatically find and delete old files on a schedule |
| CI/CD pipeline | Write build/test/deploy steps with clear exit codes |
| Tool integration | Call docker, kubectl, aws, curl, and jq from one script |
The strength of Bash is that it is available on most Linux servers and does not require a complicated runtime installation. For small tasks, a 20–50 line script is often fast enough, easy to read, and simple to add to a pipeline.
Your first script with hello.sh
Create the hello.sh file:
| |
Add the following content:
| |
Run the script with Bash:
| |
Or grant execute permission and run it directly:
| |
What is the shebang for?
The first line:
| |
is called a shebang. It tells the operating system which program should be used to run this file. The #!/usr/bin/env bash form is often more flexible than #!/bin/bash because Bash may be installed in different locations depending on the system.
Working with variables
Variables help a script store values for reuse. In Bash, variable assignment syntax has no spaces around the = sign:
| |
You should use ${VAR} when combining variables with strings so Bash does not misunderstand the variable name:
| |
Common special variables
| Variable | Meaning |
|---|---|
$0 | Name of the script being executed |
$1 | First argument passed to the script |
$# | Total number of arguments |
$? | Exit code of the previous command |
$$ | Process ID of the current shell |
Example script that accepts an environment name:
| |
Try running it:
| |
If no argument is passed, ${1:-dev} uses dev as the default value.
Basic commands you will use often
echo
echo prints content to the screen and is very useful for showing status messages in scripts:
| |
read
read reads input from the user:
| |
In scripts, you should use read -r to prevent backslashes from being interpreted unexpectedly.
cat
cat is commonly used to quickly view file content or create a sample file:
| |
Create a configuration file with a here-document:
| |
ls
ls lists files and directories:
| |
In production scripts, be careful when processing complex file lists, especially file names containing spaces. Later articles about file handling will go deeper into this topic.
DevOps practice: check_system.sh
The example below creates a script for quickly checking system information: hostname, operating system kernel, uptime, CPU load, memory, and root disk usage.
Create the file:
| |
Script content:
| |
Grant permission and run it:
| |
The output may look like this:
| |
Notable points in this script:
set -euo pipefailhelps the script stop when it encounters an error, uses an undefined variable, or when a command in a pipeline fails.df -P /uses POSIX output format so the result is more stable when parsed withawk.command -v freechecks whether thefreecommand exists before calling it.exit 1when disk usage crosses the threshold helps CI/CD or cron jobs recognize that the script is reporting a problem.
Debug scripts with bash -n and bash -x
As scripts get longer, you need to check syntax errors and see how Bash executes each command.
Check syntax with bash -n
| |
The -n option tells Bash to read commands but not execute them. It is useful for detecting issues such as missing fi, missing quotes, or incorrect loop syntax.
Trace commands with bash -x
| |
The -x option prints each command after Bash expands variables and before executing it. This is a very quick way to see what values your script is receiving.
You can also enable and disable tracing for a specific section:
| |
Security note: Do not enable
set -xaround code that handles secrets or tokens, because sensitive values may be printed to logs.
Best practices when you are new to Bash
A few small habits will make scripts easier to read and less error-prone:
- Always quote variables: use
"${VAR}"instead of$VAR, especially when values may contain spaces. - Use meaningful variable names:
DISK_USAGE_PERCENTis clearer thanDorVALUE. - Use
set -euo pipefailintentionally: it is good for many automation scripts, but you should understand the error flow before using it in complex scripts. - Check commands before using them:
command -v docker,command -v jq,command -v kubectl. - Do not hardcode sensitive information: tokens, passwords, and private keys should come from environment variables or a secret manager.
- Return clear exit codes:
exit 0for success and non-zero values for errors so cron/CI/CD can detect the result. - Run
bash -nbefore deployment: it is a quick but very useful check.
Implementation notes
- When applying this to your project, start with small scripts that have clear goals:
check_system.sh,backup_config.sh,restart_service.sh. Do not try to write a very large script right away. - Best practices:
- Put scripts in a dedicated directory such as
scripts/orops/. - Add a short README describing how to run the script, its input parameters, and sample output.
- For scripts running in CI/CD, always check the exit code and log enough information for debugging.
- Put scripts in a dedicated directory such as
- Troubleshooting:
Permission denied? → Runchmod +x script.shor usebash script.sh.command not found? → Check whether the command is installed and whetherPATHis correct.- Script behaves differently between local and server? → Check the Bash version with
bash --versionand the operating system withcat /etc/os-release.
🎯 Conclusion
Bash Script is a foundational but very practical skill in DevOps. With only a few basic commands like echo, read, cat, and ls, combined with variables and exit-code checks, you can already automate many daily operations tasks.
In the next article, we will explore conditions in Bash with if/elif/else, comparison operators, file checks, and case...esac — the building blocks that help scripts start handling logic more flexibly. 🚀
References
- GNU Bash Manual — Official documentation for Bash, shell scripts, variables, builtins, and options such as
-nand-x. - GNU Bash Reference Manual - Shell Scripts — Describes how Bash reads and executes a shell script.
- GNU Bash Reference Manual - The Set Builtin — Reference for
setoptions, including-u,-x, and-n.
