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.
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 world2. 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 182.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‑327672.3 User Variables
a=rivers
Httpd_sort=httpd-2.4.6-97.tar
BACK_DIR=/data/backup
IPaddress=10.0.0.13. 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
fiCommon 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
done3.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 # 50503.4 case Statements
# Basic case syntax
case $var in
1) echo "option 1" ;;
2) echo "option 2" ;;
*) echo "default" ;;
esac3.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
done4. 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
done5. 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_Backup5.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
fi5.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
doneThis collection demonstrates how to write, test, and combine shell scripts for everyday system administration tasks.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
