Shell Scripting for Beginners: Automate Tasks on Linux

Shell scripting is how Linux sysadmins stop doing the same task twice. If you have ever run a sequence of commands more than once, that sequence belongs in a script. Bash scripts are plain text files with Linux commands — no compiler needed, no runtime to install. This guide teaches you real scripting from the ground up.

Your First Script

#!/bin/bash
# myscript.sh
echo "Hello, $(whoami)!"
echo "Today is: $(date +'%A, %B %d %Y')"
echo "Current directory: $(pwd)"

Save it, make it executable, and run it:

chmod +x myscript.sh
./myscript.sh

The #!/bin/bash shebang line tells the OS which interpreter to use. Always include it.

Variables

#!/bin/bash
NAME="alok"
BACKUP_DIR="/var/backups"
TODAY=$(date +%Y-%m-%d)      # Command substitution

echo "User: $NAME"
echo "Backup dir: ${BACKUP_DIR}/daily"
echo "Date: $TODAY"

Rules for variables: no spaces around =; use ${VAR} when concatenating; single quotes suppress expansion.

Reading User Input

#!/bin/bash
read -p "Enter server hostname: " HOST
read -sp "Enter password: " PASS
echo
echo "Connecting to $HOST..."

Conditionals

#!/bin/bash
FILE="/etc/nginx/nginx.conf"

if [ -f "$FILE" ]; then
  echo "Config found."
elif [ -d "/etc/nginx" ]; then
  echo "Directory exists but config missing."
else
  echo "Nginx not installed."
fi

Common test operators:

  • -f — file exists and is a regular file
  • -d — directory exists
  • -z "$VAR" — string is empty
  • -n "$VAR" — string is not empty
  • -eq, -ne, -gt, -lt — integer comparisons
  • =, != — string comparisons
if [ "$USER" = "root" ]; then
  echo "Running as root."
fi

if [ $# -eq 0 ]; then
  echo "Usage: $0 filename"
  exit 1
fi

Loops

For Loop

for SERVER in web01 web02 db01; do
  echo "Pinging $SERVER..."
  ping -c 1 $SERVER &>/dev/null && echo "  OK" || echo "  UNREACHABLE"
done

for FILE in /var/log/*.log; do
  echo "Processing: $FILE"
  gzip "$FILE"
done

While Loop

COUNT=0
while [ $COUNT -lt 5 ]; do
  echo "Count: $COUNT"
  COUNT=$((COUNT + 1))
done

Functions

#!/bin/bash

log() {
  echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}

backup_dir() {
  local SRC="$1"
  local DEST="$2"
  log "Backing up $SRC to $DEST"
  tar -czf "$DEST/backup-$(date +%Y%m%d).tar.gz" "$SRC"
  log "Done."
}

backup_dir /etc/nginx /var/backups

Exit Codes and Error Handling

#!/bin/bash
set -e              # Exit on any error
set -u              # Treat unset variables as errors
set -o pipefail     # Catch errors in pipes

cp /etc/hosts /backup/ || { echo "Backup failed!"; exit 1; }

systemctl restart nginx
if [ $? -ne 0 ]; then
  echo "Nginx restart failed"
  exit 1
fi

Practical Script: Disk Space Alert

#!/bin/bash
THRESHOLD=80

df -h | grep -vE "^(Filesystem|tmpfs)" | while read LINE; do
  USAGE=$(echo "$LINE" | awk "{print $5}" | tr -d "%")
  MOUNT=$(echo "$LINE" | awk "{print $6}")
  if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "ALERT: $MOUNT is at ${USAGE}% on $(hostname)"
  fi
done

Script Arguments

#!/bin/bash
ENVIRONMENT=$1
VERSION=$2

if [ -z "$ENVIRONMENT" ] || [ -z "$VERSION" ]; then
  echo "Usage: $0 environment version"
  exit 1
fi

echo "Deploying version $VERSION to $ENVIRONMENT"
# $0=script name, $1 $2...=arguments, $#=count, $@=all args

Summary

Shell scripting turns repetitive work into repeatable, reliable automation. Start small — convert your most common command sequences into scripts. Add error handling with set -e, use functions to keep code organized, and always test on a non-production system first. Over time, your script library becomes one of your most valuable tools as a sysadmin.