Shell脚本编程:Linux自动化的瑞士军刀

导读:厌倦了重复执行相同的命令序列?想要让你的Linux系统自动完成繁琐任务?Shell脚本就是你的不二选择!本文将带你从零开始掌握Shell脚本编程,从基本语法到高级技巧,让你的工作效率提升10倍。无论你是Linux新手还是经验丰富的管理员,这篇文章都能帮你解锁Shell脚本的强大潜力!

本文是《从入门到精通渐进式学习Linux》系列的第12章。通过这篇文章,你将学会如何用Shell脚本实现系统管理自动化。

目录

  • 1. Shell脚本基础
  • 2. 变量与数据类型
  • 3. 条件判断与流程控制
  • 4. 循环结构
  • 5. 函数定义与使用
  • 6. 文本处理工具
  • 7. 实用脚本示例

1. Shell脚本基础

1.1 什么是Shell脚本?

Shell脚本是由Shell命令组成的文本文件,能够自动执行一系列的命令,就像一个小型程序一样。在Linux中,最常用的Shell是Bash (Bourne Again SHell)。

1.2 创建你的第一个Shell脚本

  1. 使用文本编辑器创建脚本文件:
nano hello.sh
  1. 输入以下内容:
#!/bin/bash
# 我的第一个脚本
echo "Hello, Shell世界!"
echo "当前时间是: $(date)"
echo "当前用户: $USER"
  1. 保存并退出

  2. 添加执行权限:

chmod +x hello.sh
  1. 运行脚本:
./hello.sh

1.3 Shell脚本结构

  • 第一行 (Shebang): #!/bin/bash 告诉系统使用哪个Shell解释器
  • 注释: 以#开头的行
  • 命令: 一行一条命令,按顺序执行
  • 最后一行: 通常留空,确保最后一条命令正确执行

2. 变量与数据类型

2.1 变量的定义与使用

在Bash中定义和使用变量非常简单:

# 定义变量 (注意=两边不能有空格)
name="小明"
age=28

# 使用变量 (使用$符号)
echo "你好,$name!你今年$age岁了。"

# 命令结果赋值
current_directory=$(pwd)
files_count=$(ls | wc -l)

echo "当前目录: $current_directory"
echo "文件数量: $files_count"

2.2 环境变量

系统中预定义的环境变量:

echo "用户名: $USER"
echo "主目录: $HOME"
echo "当前Shell: $SHELL"
echo "PATH: $PATH"

定义自己的环境变量:

export MY_VARIABLE="全局变量值"

2.3 特殊变量

Bash提供了一些特殊变量:

echo "脚本名称: $0"
echo "第一个参数: $1" # 脚本运行时传入的第一个参数
echo "参数个数: $#"
echo "所有参数: $@"
echo "上一条命令的退出状态: $?"
echo "当前进程ID: $$"

2.4 数组

Bash支持简单的数组操作:

# 定义数组
fruits=("苹果" "香蕉" "橙子" "葡萄")

# 访问数组元素
echo "第一个水果: ${fruits[0]}"
echo "所有水果: ${fruits[@]}"
echo "水果数量: ${#fruits[@]}"

# 添加元素
fruits+=("西瓜")

# 遍历数组
for fruit in "${fruits[@]}"; do
    echo "水果: $fruit"
done

3. 条件判断与流程控制

3.1 if-else语句

基本语法:

if [ 条件 ]; then
    # 如果条件为真,执行这里的代码
elif [ 另一个条件 ]; then
    # 如果另一个条件为真,执行这里的代码
else
    # 如果以上条件都不为真,执行这里的代码
fi

示例:

#!/bin/bash

age=25

if [ "$age" -lt 18 ]; then
    echo "你是未成年"
elif [ "$age" -ge 18 ] && [ "$age" -lt 60 ]; then
    echo "你是成年人"
else
    echo "你是老年人"
fi

# 文件判断
if [ -f "/etc/passwd" ]; then
    echo "/etc/passwd 文件存在"
fi

if [ -d "/etc" ]; then
    echo "/etc 是一个目录"
fi

3.2 条件测试

文件测试:

操作符 描述
-f 文件 如果文件存在且是普通文件,则为真
-d 目录 如果目录存在,则为真
-r 文件 如果文件存在且可读,则为真
-w 文件 如果文件存在且可写,则为真
-x 文件 如果文件存在且可执行,则为真
-s 文件 如果文件存在且不为空,则为真

字符串比较:

操作符 描述
-z 字符串 如果字符串长度为0,则为真
-n 字符串 如果字符串长度不为0,则为真
字符串1 = 字符串2 如果字符串相同,则为真
字符串1 != 字符串2 如果字符串不同,则为真

数值比较:

操作符 描述
-eq 相等
-ne 不相等
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于

逻辑操作:

操作符 描述
&& 逻辑与
|| 逻辑或
! 逻辑非

3.3 case语句

case语句类似于其他语言中的switch-case:

#!/bin/bash

fruit="苹果"

case "$fruit" in
    "苹果")
        echo "这是一个苹果"
        ;;
    "香蕉" | "芭蕉")
        echo "这是一个香蕉或芭蕉"
        ;;
    *)
        echo "未知水果"
        ;;
esac

4. 循环结构

4.1 for循环

基本语法:

for 变量 in 列表
do
    # 循环体
done

示例:

# 遍历数字
for i in 1 2 3 4 5
do
    echo "计数: $i"
done

# 使用序列生成器
for i in {1..10..2}  # 1到10,步长为2
do
    echo "序列: $i"
done

# 遍历文件
for file in /etc/*.conf
do
    echo "配置文件: $file"
done

# C风格for循环
for ((i=1; i<=5; i++))
do
    echo "C风格循环: $i"
done

4.2 while循环

语法:

while [ 条件 ]
do
    # 循环体
done

示例:

# 简单计数器
count=1
while [ $count -le 5 ]
do
    echo "While循环计数: $count"
    count=$((count + 1))
done

# 读取文件每一行
while read line
do
    echo "读取行: $line"
done < /etc/hostname

4.3 until循环

until循环与while循环相反,直到条件为真时停止:

count=1
until [ $count -gt 5 ]
do
    echo "Until循环计数: $count"
    count=$((count + 1))
done

4.4 循环控制

  • break: 跳出循环
  • continue: 跳过当前迭代,继续下一次循环
for i in {1..10}
do
    if [ $i -eq 5 ]
    then
        continue  # 跳过5
    fi
    
    if [ $i -eq 8 ]
    then
        break  # 循环到8就结束
    fi
    
    echo "数字: $i"
done

5. 函数定义与使用

5.1 定义函数

# 方法1
function greeting {
    echo "你好,$1!"
}

# 方法2
say_goodbye() {
    echo "再见,$1!"
}

5.2 调用函数

greeting "小明"
say_goodbye "小红"

5.3 函数参数

function calculate {
    local sum=$(($1 + $2))  # local关键字定义局部变量
    echo "计算结果: $sum"
    return 0  # 返回状态码
}

calculate 5 3
echo "函数返回值: $?"

5.4 函数返回值

Bash函数通过return只能返回状态码(0-255),如果要返回计算结果:

# 方法1: 使用echo
get_sum() {
    echo $(($1 + $2))
}

result=$(get_sum 10 20)
echo "和: $result"

# 方法2: 使用全局变量
calculate_product() {
    product=$(($1 * $2))
}

calculate_product 4 5
echo "乘积: $product"

6. 文本处理工具

Shell脚本经常需要处理文本数据,以下是几个常用工具:

6.1 grep - 搜索文本

# 在文件中搜索关键字
grep "root" /etc/passwd

# 递归搜索目录
grep -r "配置" /etc/

# 显示匹配行号
grep -n "bash" /etc/passwd

# 只显示匹配的文件名
grep -l "sshd" /etc/pam.d/*

6.2 sed - 流编辑器

# 替换文本
echo "hello world" | sed 's/world/linux/'

# 删除空行
sed '/^$/d' file.txt

# 打印特定行
sed -n '5,10p' file.txt

# 多个操作
sed -e 's/foo/bar/g' -e 's/hello/hi/g' file.txt

6.3 awk - 文本分析工具

# 打印特定列
echo "one two three" | awk '{print $2}'

# 使用不同的分隔符
awk -F: '{print $1, $6}' /etc/passwd

# 条件过滤
awk '$3 > 1000 {print $1}' /etc/passwd

# 求和
awk '{sum += $1} END {print sum}' numbers.txt

6.4 cut - 提取列

# 提取特定字段
cut -d: -f1,6 /etc/passwd

# 提取字符范围
echo "abcdefg" | cut -c1-3

6.5 sort - 排序

# 普通排序
sort names.txt

# 数值排序
sort -n numbers.txt

# 反向排序
sort -r names.txt

# 按特定字段排序
sort -t: -k3 -n /etc/passwd

7. 实用脚本示例

7.1 系统备份脚本

#!/bin/bash

# 简单备份脚本
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d)
BACKUP_FILE="$BACKUP_DIR/home_$DATE.tar.gz"

# 检查备份目录
if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
    echo "创建备份目录 $BACKUP_DIR"
fi

# 执行备份
echo "开始备份..."
tar -czf "$BACKUP_FILE" /home
echo "备份完成: $BACKUP_FILE"

# 保留最近7天的备份
find "$BACKUP_DIR" -name "home_*.tar.gz" -mtime +7 -delete
echo "已删除7天前的备份"

7.2 系统监控脚本

#!/bin/bash

# 监控CPU、内存和磁盘使用情况
echo "=== 系统监控报告 - $(date) ==="

echo -e "\n>>> CPU负载 <<<"
uptime

echo -e "\n>>> 内存使用情况 <<<"
free -h

echo -e "\n>>> 磁盘使用情况 <<<"
df -h

echo -e "\n>>> 占用CPU最多的5个进程 <<<"
ps aux | sort -rk 3,3 | head -6

echo -e "\n>>> 占用内存最多的5个进程 <<<"
ps aux | sort -rk 4,4 | head -6

echo "=== 监控报告结束 ==="

7.3 批量用户创建脚本

#!/bin/bash

# 批量创建用户
# 用法: ./create_users.sh users.txt

if [ "$#" -ne 1 ]; then
    echo "用法: $0 <用户列表文件>"
    exit 1
fi

if [ ! -f "$1" ]; then
    echo "错误: 文件 $1 不存在"
    exit 2
fi

# 逐行读取用户信息并创建用户
while IFS=: read -r username password
do
    echo "创建用户: $username"
    
    # 检查用户是否已存在
    if id "$username" &>/dev/null; then
        echo "警告: 用户 $username 已存在,跳过"
        continue
    fi
    
    # 创建用户
    useradd -m -s /bin/bash "$username"
    echo "$username:$password" | chpasswd
    
    echo "用户 $username 创建完成"
done < "$1"

echo "所有用户创建完毕"

7.4 网站状态监控脚本

#!/bin/bash

# 监控网站可用性
SITES=("https://www.baidu.com" "https://www.google.com" "https://www.github.com")
LOG_FILE="/var/log/website_check.log"
ADMIN_EMAIL="[email protected]"

check_website() {
    status_code=$(curl -s -o /dev/null -w "%{http_code}" "$1")
    
    if [ "$status_code" -eq 200 ] || [ "$status_code" -eq 301 ]; then
        return 0
    else
        return 1
    fi
}

echo "$(date): 开始网站检查" >> "$LOG_FILE"

for site in "${SITES[@]}"; do
    if check_website "$site"; then
        echo "$(date): $site 正常运行" >> "$LOG_FILE"
    else
        echo "$(date): $site 无法访问!" >> "$LOG_FILE"
        echo "网站 $site 不可访问,请检查!" | mail -s "网站故障警报" "$ADMIN_EMAIL"
    fi
done

echo "$(date): 完成网站检查" >> "$LOG_FILE"

总结

Shell脚本是Linux系统管理的强大工具,通过本文,你学习了:

  • ✅ Shell脚本的基础知识和创建方法
  • ✅ 变量定义、数据类型和特殊变量
  • ✅ 条件判断和流程控制结构
  • ✅ 多种循环结构的使用方法
  • ✅ 函数的定义与调用技巧
  • ✅ 强大的文本处理工具
  • ✅ 实用的脚本示例

掌握Shell脚本编程,你将能够自动化许多重复性工作,提高工作效率,并更加深入地理解Linux系统。随着经验的积累,你可以编写更加复杂和强大的脚本来解决实际问题。

实践练习

  1. 编写一个脚本,统计指定目录中各种文件类型的数量
  2. 创建一个系统信息收集脚本,显示主机名、内核版本、IP地址等信息
  3. 编写一个日志分析脚本,找出Apache访问日志中访问量最大的10个IP地址
  4. 实现一个自动化部署脚本,能够将网站代码更新到服务器并重启服务

如果你觉得这篇文章对你有帮助,请不要忘记点赞、收藏和关注!你的支持是我创作的最大动力!

❓ 有任何问题或建议,欢迎在评论区留言讨论!

本文是《从入门到精通渐进式学习Linux》系列的第12章。下一章我们将探讨Linux系统监控与性能优化,敬请期待!

你可能感兴趣的:(Linux,linux,自动化,chrome)