Shell脚本编程入门

Shell脚本是Linux日常运维和自动化的基本功,掌握基础语法就能大幅提升效率。

基本结构

#!/bin/bash
# 第一行shebang声明解释器

echo "Hello, Shell!"

赋予执行权限后运行:

chmod +x hello.sh
./hello.sh

变量

# 定义(等号两侧不能有空格)
name="world"
count=42

# 使用
echo "Hello, $name"
echo "Count is ${count} items"

# 只读
readonly PI=3.14

# 命令替换
current_date=$(date +%Y-%m-%d)
file_count=$(ls | wc -l)

条件判断

if语句

#!/bin/bash
if [ -f "/etc/nginx/nginx.conf" ]; then
    echo "Nginx config exists"
elif [ -f "/etc/apache2/apache2.conf" ]; then
    echo "Apache config exists"
else
    echo "No web server config found"
fi

常用判断:

  • -f file:文件存在且是普通文件
  • -d dir:目录存在
  • -z "$str":字符串为空
  • -n "$str":字符串非空
  • $a -eq $b:数值相等
  • $a -gt $b:数值大于

case语句

#!/bin/bash
case "$1" in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    restart)
        echo "Restarting service..."
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac

循环

# for循环
for file in /var/log/*.log; do
    echo "Processing $file"
    wc -l "$file"
done

# 遍历序列
for i in $(seq 1 5); do
    echo "Number: $i"
done

# while循环:逐行读取文件
while IFS= read -r line; do
    echo "Line: $line"
done < /etc/hosts

# while计数
count=0
while [ $count -lt 10 ]; do
    echo $count
    count=$((count + 1))
done

函数

#!/bin/bash

check_disk() {
    local threshold=${1:-80}
    local usage=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
    
    if [ "$usage" -gt "$threshold" ]; then
        echo "WARNING: Disk usage ${usage}% exceeds ${threshold}%"
        return 1
    else
        echo "OK: Disk usage ${usage}%"
        return 0
    fi
}

# 调用
check_disk 90

实用示例:日志清理脚本

#!/bin/bash
# clean_logs.sh - 清理指定天数前的日志文件

LOG_DIR="/var/log/app"
DAYS=7

if [ ! -d "$LOG_DIR" ]; then
    echo "Directory $LOG_DIR does not exist"
    exit 1
fi

echo "Cleaning logs older than $DAYS days in $LOG_DIR"

deleted=0
while IFS= read -r -d '' file; do
    echo "Deleting: $file"
    rm -f "$file"
    deleted=$((deleted + 1))
done < <(find "$LOG_DIR" -name "*.log" -mtime +$DAYS -print0)

echo "Done. Deleted $deleted files."

实用示例:批量备份MySQL数据库

#!/bin/bash
# backup_mysql.sh

BACKUP_DIR="/data/backup/mysql/$(date +%Y%m%d)"
MYSQL_USER="backup"
MYSQL_PASS="secret"

mkdir -p "$BACKUP_DIR"

databases=$(mysql -u"$MYSQL_USER" -p"$MYSQL_PASS" -e "SHOW DATABASES;" |     grep -Ev "^(Database|information_schema|performance_schema|sys)$")

for db in $databases; do
    echo "Backing up $db..."
    mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASS" "$db" |         gzip > "${BACKUP_DIR}/${db}.sql.gz"
done

echo "Backup completed: $BACKUP_DIR"

写Shell脚本记住两点:加set -euo pipefail防止静默失败,变量加双引号防止分词问题。