Fundamentals 23 min read

Master Linux Shell Scripting: From Basics to Real‑World Projects

This article provides a step‑by‑step guide to Linux shell scripting, covering the definition of a shell, common shells, naming rules, environment and user variables, control‑flow statements, functions, arrays, and several practical scripts such as a Hello World program, service checks, system backup, information collection, and one‑click LNMP deployment.

Linux Tech Enthusiast
Linux Tech Enthusiast
Linux Tech Enthusiast
Master Linux Shell Scripting: From Basics to Real‑World Projects

1. Shell Introduction

A shell is a command interpreter that lets users interact with the operating system. The most common shell on Linux is Bash (Bourne Again Shell), which is the default on most distributions.

1.2 Shell Programming Guidelines

Script names should consist of English letters, numbers or underscores and end with .sh.

Do not use special symbols or spaces in the name.

The first line of a script must be #!/bin/bash.

Variable names cannot start with a digit or special symbol; use underscores, not hyphens.

1.3 First Script – Hello World

# Create a file
touch HelloWorld.sh
# Edit the file
vim HelloWorld.sh
# Add content
#!/bin/bash
# This is our first shell script
# by author rivers 2021.09
echo "hello world"
# Make it executable
chmod +x HelloWorld.sh
# Run it
./HelloWorld.sh
# Output
hello world

2. Shell Variables

Shell variables are containers for values and fall into three categories:

System variables (e.g., $0, $1, $?).

Environment variables (e.g., PATH, HOME, SHELL, USER, PWD, TERM, HOSTNAME, RANDOM).

User (local) variables defined within the script.

Simple variable example:

a=18
echo $a   # prints 18

2.1 System Variables

# Script name
$0
# First argument
$1
# All arguments
$*
# Number of arguments
$#
# Exit status of last command
$?
# PID of the script
$$

2.2 Environment Variables

PATH      # command search path
HOME      # user home directory
SHELL     # current shell
USER      # current user name
ID        # user ID
PWD       # current working directory
TERM      # terminal type
HOSTNAME  # host name
RANDOM    # random integer 0‑32767

2.3 User Variables

a=rivers
Httpd_sort=httpd-2.4.6-97.tar
BACK_DIR=/data/backup
IPaddress=10.0.0.1

3. Control Flow Statements

3.1 if Statements

# Single‑branch
if [ condition ]; then
  command1
fi

# Double‑branch
if [ condition ]; then
  command1
else
  command2
fi

# Multi‑branch
if [ cond1 ]; then
  cmd1
elif [ cond2 ]; then
  cmd2
else
  cmd3
fi

Common test operators include -f, -d, -eq, -ne, -lt, -gt, -le, -ge, -a, -o, -z, -x, ||, &&.

3.2 for Loops

# Basic syntax
for var in list; do
  command
  # ...
  done

# Example: check multiple hosts in a LAN
Network=$1
for Host in $(seq 1 254); do
  ping -c 1 $Network.$Host > /dev/null && result=0 || result=1
  if [ "$result" == 0 ]; then
    echo -e "\033[32;1m$Network.$Host is up\033[0m"
    echo "$Network.$Host" >> /tmp/up.txt
  else
    echo -e "\033[31m$Network.$Host is down\033[0m"
    echo "$Network.$Host" >> /tmp/down.txt
  fi
done

3.3 while Loops

# Simple while loop
while true; do
  let N++
  if [ $N -eq 5 ]; then
    break
  fi
  echo $N
 done
# Output: 1 2 3 4

# Continue example
N=0
while [ $N -lt 5 ]; do
  let N++
  if [ $N -eq 3 ]; then
    continue
  fi
  echo $N
done
# Output: 1 2 4

# Sum 1‑100 using while
j=0
i=1
while ((i<=100)); do
  j=$((i + j))
  ((i++))
 done
echo $j   # 5050

3.4 case Statements

# Basic case syntax
case $var in
  1) echo "option 1" ;;
  2) echo "option 2" ;;
  *) echo "default" ;;
esac

3.5 select Statements

# Menu using select
PS3="Select a number: "
select i in http php mysql quit; do
  case $i in
    http) echo "Test Httpd" ;;
    php)  echo "Test PHP" ;;
    mysql) echo "Test MySQL" ;;
    quit) exit ;;
    *) echo "Invalid choice" ;;
  esac
done

4. Functions and Arrays

4.1 Functions

# Define a function
my_func() {
  VAR=$((1+1))
  echo "This is a function."
  return $VAR
}
my_func
 echo $?

4.2 Arrays

# Declare an array
IP=(10.0.0.1 10.0.0.2 10.0.0.3)
# Iterate using index
for ((i=0;i<${#IP[@]};i++)); do
  echo ${IP[$i]}
 done
# Iterate directly
for ip in ${IP[@]}; do
  echo $ip
 done

5. Practical Scripts

5.1 System Backup Script

#!/bin/bash
# Auto backup Linux system files
SOURCE_DIR=($*)
TARGET_DIR=/data/backup/
YEAR=$(date +%Y)
MONTH=$(date +%m)
DAY=$(date +%d)
WEEK=$(date +%u)
A_NAME=$(date +%H%M)
FILES=system_backup.tgz
if [ -z "$*" ]; then
  echo -e "Usage: $0 /boot /etc"
  exit 1
fi
# Ensure target directory exists
if [ ! -d $TARGET_DIR/$YEAR/$MONTH/$DAY ]; then
  mkdir -p $TARGET_DIR/$YEAR/$MONTH/$DAY
fi
Full_Backup(){
  if [ "$WEEK" -eq 7 ]; then
    rm -rf $TARGET_DIR/snapshot
    cd $TARGET_DIR/$YEAR/$MONTH/$DAY && \
    tar -g $TARGET_DIR/snapshot -czvf $FILES ${SOURCE_DIR[@]}
  fi
}
Add_Backup(){
  if [ "$WEEK" -ne 7 ]; then
    cd $TARGET_DIR/$YEAR/$MONTH/$DAY && \
    tar -g $TARGET_DIR/snapshot -czvf ${A_NAME}$FILES ${SOURCE_DIR[@]}
  fi
}
sleep 3
Full_Backup
Add_Backup

5.2 System Information Collection

# Collect system info and optionally store in MySQL
ip_info=$(ifconfig | grep "Bcast" | tail -1 | awk '{print $2}' | cut -d: -f2)
cpu_info1=$(cat /proc/cpuinfo | grep 'model name' | tail -1 | awk -F: '{print $2}' | sed 's/^ //g' | awk '{print $1,$3,$4,$NF}')
cpu_info2=$(cat /proc/cpuinfo | grep "physical id" | sort | uniq -c | wc -l)
serv_info=$(hostname)
disk_info=$(fdisk -l | grep "Disk" | grep -v "identifier" | awk '{print $2,$3,$4}' | sed 's/,//g')
mem_info=$(free -m | grep "Mem" | awk '{print "Total",$1,$2"M"}')
load_info=$(uptime | awk '{print "Current Load: "$(NF-2)}' | sed 's/,//g')
mark_info='BeiJing_IDC'
# Print collected data
echo -e "\033[32m-------------------------------------------\033[0m"
echo "IPADDR: $ip_info"
echo "HOSTNAME: $serv_info"
echo "CPU_INFO: $cpu_info1 X $cpu_info2"
echo "DISK_INFO: $disk_info"
echo "MEM_INFO: $mem_info"
echo "LOAD_INFO: $load_info"
echo -e "\033[32m-------------------------------------------\033[0m"
read -p "You want to write the data to the database? (yes/no) " ensure
if [[ "$ensure" == "yes" || "$ensure" == "y" || "$ensure" == "Y" ]]; then
  mysql -uroot -p123456 -Dtest -e "INSERT INTO audit_system VALUES('','${ip_info}','${serv_info}','${cpu_info1} X ${cpu_info2}','${disk_info}','${mem_info}','${load_info}','${mark_info}')"
else
  echo "Exit without storing data."
  exit 0
fi

5.3 One‑Click LNMP Deployment

#!/bin/bash
# Variables for component sources
Nginx_url=https://nginx.org/download/nginx-1.20.1.tar.gz
Nginx_prefix=/usr/local/nginx
Mysql_url=https://downloads.mysql.com/archives/get/p/23/file/mysql-5.5.20.tar.gz
Mysql_prefix=/usr/local/mysql
Php_url=https://www.php.net/distributions/php-7.2.10.tar.gz
Php_prefix=/usr/local/php

function nginx_install(){
  if [[ "$1" == "1" ]]; then
    wget -c $Nginx_url && tar -zxvf $(basename $Nginx_url) && cd nginx-1.20.1 && \
    ./configure --prefix=$Nginx_prefix && make && make install
  fi
}
function mysql_install(){
  if [[ "$1" == "2" ]]; then
    wget -c $Mysql_url && tar -zxvf $(basename $Mysql_url) && cd mysql-5.5.20 && \
    cmake . -DCMAKE_INSTALL_PREFIX=$Mysql_prefix && make && make install
  fi
}
function php_install(){
  if [[ "$1" == "3" ]]; then
    wget -c $Php_url && tar -zxvf $(basename $Php_url) && cd php-7.2.10 && \
    ./configure --prefix=$Php_prefix --enable-fpm && make && make install
  fi
}
PS3="Please select component to install:"
select i in nginx mysql php quit; do
  case $i in
    nginx) nginx_install 1 ;;
    mysql) mysql_install 2 ;;
    php)   php_install 3 ;;
    quit)  exit ;;
    *) echo "Invalid choice" ;;
  esac
done

This collection demonstrates how to write, test, and combine shell scripts for everyday system administration tasks.

AutomationLinuxscriptingFunctionsVariablesArraysControl Flow
Linux Tech Enthusiast
Written by

Linux Tech Enthusiast

Focused on sharing practical Linux technology content, covering Linux fundamentals, applications, tools, as well as databases, operating systems, network security, and other technical knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.