Linux 新手村Linux 新手村
🏠 首页
📖 教程
  • Linux 官网
  • Ubuntu 官网
  • CentOS 官网
🏠 首页
📖 教程
  • Linux 官网
  • Ubuntu 官网
  • CentOS 官网
  • 🚀 入门篇 - 欢迎来到 Linux 世界

    • 📚 长安的教程导航
    • 🐧 什么是 Linux?
    • 💿 安装 Linux
    • 🎉 首次开机
  • 🎯 基础篇 - 必备生存技能

    • ⌨️ 基础命令
    • 🗂️ 文件系统
    • 📝 文件操作
    • 👥 用户与权限
  • ⚔️ 进阶篇 - 成为高手之路

    • ⚔️ Vim 编辑器
    • 🤖 Shell 脚本
    • ⚙️ 进程与服务
    • 🌐 网络基础
  • 🏆 高级篇 - 突破自我

    • 💡 高级技巧
    • 🔧 故障排查
    • 🎭 日常案例与血泪教训

🤖 Shell 脚本

大家好,我是长安!Shell 脚本是 Linux 自动化的利器,学会它你就能让电脑帮你干活了。

🎯 本章目标

跟着长安读完这一章,你将学会:

  • 编写简单的 Shell 脚本
  • 使用变量和参数
  • 条件判断和循环
  • 常用的脚本技巧

🤔 什么是 Shell 脚本?

Shell 脚本就是把一堆命令写在一个文件里,让它们自动按顺序执行。

就像你给电脑写了一张"待办事项清单",它会一项一项帮你完成。

为什么要学 Shell 脚本?

  • 🔄 自动化:重复的工作让电脑来做
  • ⏰ 定时任务:每天自动备份、清理
  • 🚀 批量操作:一键处理成百上千个文件
  • 💼 工作必备:运维、开发都要用

📝 第一个脚本

创建脚本文件

# 创建脚本文件
vim hello.sh

编写脚本内容

#!/bin/bash
# 这是我的第一个 Shell 脚本

echo "Hello World!"
echo "今天是: $(date)"
echo "当前目录: $(pwd)"

运行脚本

# 方法一:添加执行权限后运行
chmod +x hello.sh
./hello.sh

# 方法二:用 bash 解释器运行
bash hello.sh

# 方法三:用 source 运行(会影响当前 shell 环境)
source hello.sh

💡 #!/bin/bash 是什么?

这行叫做 shebang(发音:sha-bang),告诉系统用什么程序来执行这个脚本。

常见的 shebang:

  • #!/bin/bash - 用 Bash
  • #!/bin/sh - 用 sh
  • #!/usr/bin/python3 - 用 Python

📦 变量

定义变量

#!/bin/bash

# 定义变量(等号两边不能有空格!)
name="小明"
age=18
path="/home/xiaoming"

# 使用变量(加 $ 符号)
echo "我的名字是: $name"
echo "我今年 $age 岁"
echo "主目录: ${path}"    # 用 {} 更清晰

⚠️ 常见错误

# ❌ 错误:等号两边有空格
name = "小明"

# ✅ 正确:等号两边不能有空格
name="小明"

特殊变量

#!/bin/bash

echo "脚本名称: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "所有参数: $@"
echo "参数个数: $#"
echo "上一个命令的退出码: $?"
echo "当前进程 PID: $$"

运行测试:

./script.sh arg1 arg2 arg3

用户输入

#!/bin/bash

echo "请输入你的名字:"
read name

echo "你好, $name!"

# 带提示的输入
read -p "请输入年龄: " age
echo "你今年 $age 岁"

# 静默输入(输入密码时)
read -s -p "请输入密码: " password
echo ""  # 换行
echo "密码长度: ${#password}"

命令替换

#!/bin/bash

# 方法一:$() - 推荐
today=$(date +%Y-%m-%d)
files=$(ls -l | wc -l)

# 方法二:反引号 `` - 旧语法
today=`date +%Y-%m-%d`

echo "今天是: $today"
echo "当前目录有 $files 个文件"

🔀 条件判断

if 语句

#!/bin/bash

age=18

if [ $age -ge 18 ]; then
    echo "你已成年"
else
    echo "你未成年"
fi

if-elif-else

#!/bin/bash

score=85

if [ $score -ge 90 ]; then
    echo "优秀"
elif [ $score -ge 80 ]; then
    echo "良好"
elif [ $score -ge 60 ]; then
    echo "及格"
else
    echo "不及格"
fi

条件测试操作符

数字比较:

操作符含义示例
-eq等于[ $a -eq $b ]
-ne不等于[ $a -ne $b ]
-gt大于[ $a -gt $b ]
-lt小于[ $a -lt $b ]
-ge大于等于[ $a -ge $b ]
-le小于等于[ $a -le $b ]

字符串比较:

操作符含义示例
=相等[ "$a" = "$b" ]
!=不相等[ "$a" != "$b" ]
-z字符串为空[ -z "$a" ]
-n字符串不为空[ -n "$a" ]

文件测试:

操作符含义示例
-e文件存在[ -e file ]
-f是普通文件[ -f file ]
-d是目录[ -d dir ]
-r可读[ -r file ]
-w可写[ -w file ]
-x可执行[ -x file ]

逻辑运算

#!/bin/bash

# && 和
if [ $age -ge 18 ] && [ $age -le 60 ]; then
    echo "劳动年龄"
fi

# || 或
if [ $status = "success" ] || [ $status = "done" ]; then
    echo "完成"
fi

# ! 非
if [ ! -f file.txt ]; then
    echo "文件不存在"
fi

💡 双中括号 [[ ]]

[[ ]] 是 Bash 的增强版条件测试,更安全、功能更多:

# 支持 && 和 || 在里面使用
if [[ $age -ge 18 && $age -le 60 ]]; then
    echo "劳动年龄"
fi

# 支持正则匹配
if [[ $email =~ ^[a-z]+@[a-z]+\.[a-z]+$ ]]; then
    echo "邮箱格式正确"
fi

🔄 循环

for 循环

#!/bin/bash

# 遍历列表
for fruit in apple banana orange; do
    echo "水果: $fruit"
done

# 遍历数字范围
for i in {1..5}; do
    echo "数字: $i"
done

# 遍历文件
for file in *.txt; do
    echo "文件: $file"
done

# C 语言风格
for ((i=1; i<=5; i++)); do
    echo "i = $i"
done

while 循环

#!/bin/bash

# 基本 while 循环
count=1
while [ $count -le 5 ]; do
    echo "计数: $count"
    ((count++))
done

# 读取文件每一行
while read line; do
    echo "行: $line"
done < file.txt

# 无限循环
while true; do
    echo "运行中..."
    sleep 1
done

until 循环

#!/bin/bash

# 直到条件为真才停止
count=1
until [ $count -gt 5 ]; do
    echo "计数: $count"
    ((count++))
done

循环控制

#!/bin/bash

# break - 跳出循环
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        break
    fi
    echo $i
done

# continue - 跳过本次迭代
for i in {1..5}; do
    if [ $i -eq 3 ]; then
        continue
    fi
    echo $i
done

🔧 函数

定义函数

#!/bin/bash

# 方式一
function greet() {
    echo "Hello, $1!"
}

# 方式二(更兼容)
say_bye() {
    echo "Goodbye, $1!"
}

# 调用函数
greet "小明"
say_bye "小红"

函数参数和返回值

#!/bin/bash

# 带参数的函数
add() {
    local result=$(( $1 + $2 ))
    echo $result    # 用 echo 返回结果
}

# 获取返回值
sum=$(add 10 20)
echo "10 + 20 = $sum"

# 使用 return(只能返回 0-255 的数字)
is_even() {
    if [ $(( $1 % 2 )) -eq 0 ]; then
        return 0    # true
    else
        return 1    # false
    fi
}

if is_even 4; then
    echo "4 是偶数"
fi

📋 实用脚本示例

示例 1:备份脚本

#!/bin/bash
# 每日备份脚本

# 配置
SOURCE_DIR="/home/xiaoming/documents"
BACKUP_DIR="/home/xiaoming/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_$DATE.tar.gz"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 执行备份
echo "开始备份: $SOURCE_DIR"
tar -czvf "$BACKUP_DIR/$BACKUP_FILE" "$SOURCE_DIR"

if [ $? -eq 0 ]; then
    echo "✅ 备份成功: $BACKUP_DIR/$BACKUP_FILE"
else
    echo "❌ 备份失败"
    exit 1
fi

# 删除 7 天前的备份
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +7 -delete
echo "已清理旧备份"

示例 2:系统监控脚本

#!/bin/bash
# 系统资源监控

echo "========== 系统监控报告 =========="
echo "时间: $(date)"
echo ""

# CPU 使用率
echo "【CPU 使用率】"
top -bn1 | grep "Cpu(s)" | awk '{print "使用率: " 100-$8 "%"}'
echo ""

# 内存使用情况
echo "【内存使用情况】"
free -h | awk 'NR==2{printf "已用: %s / 总计: %s (%.2f%%)\n", $3, $2, $3*100/$2}'
echo ""

# 磁盘使用情况
echo "【磁盘使用情况】"
df -h | awk '$NF=="/"{printf "根分区: %s / %s (%s)\n", $3, $2, $5}'
echo ""

# 负载
echo "【系统负载】"
uptime | awk -F'load average:' '{print "负载: " $2}'
echo ""

echo "========== 报告结束 =========="

示例 3:批量重命名

#!/bin/bash
# 批量重命名文件:给所有 jpg 文件添加前缀

PREFIX="photo_"
COUNT=1

for file in *.jpg; do
    if [ -f "$file" ]; then
        new_name="${PREFIX}$(printf "%03d" $COUNT).jpg"
        mv "$file" "$new_name"
        echo "重命名: $file -> $new_name"
        ((COUNT++))
    fi
done

echo "完成!共处理 $((COUNT-1)) 个文件"

示例 4:服务检测脚本

#!/bin/bash
# 检测服务是否运行

check_service() {
    local service=$1
    if systemctl is-active --quiet $service; then
        echo "✅ $service 正在运行"
        return 0
    else
        echo "❌ $service 未运行"
        return 1
    fi
}

# 检测多个服务
services=("nginx" "mysql" "ssh")

for svc in "${services[@]}"; do
    check_service $svc
done

🐛 调试脚本

调试技巧

# 方法 1:运行时调试
bash -x script.sh

# 方法 2:在脚本中开启调试
#!/bin/bash
set -x    # 开启调试
# ... 代码 ...
set +x    # 关闭调试

# 方法 3:遇错即停
set -e    # 命令出错就停止执行

# 方法 4:使用未定义变量报错
set -u

常见错误排查

# 错误 1:命令找不到
# 检查 PATH 环境变量,或使用绝对路径

# 错误 2:权限不足
# chmod +x script.sh

# 错误 3:换行符问题(Windows 文件)
# dos2unix script.sh

# 错误 4:语法错误
# bash -n script.sh  # 只检查语法不执行

📝 本章小结

脚本模板

#!/bin/bash
#
# 脚本名称: xxx.sh
# 描述: xxxx
# 作者: xxx
# 日期: xxxx-xx-xx
#

set -e  # 遇错即停

# 变量定义
VAR1="value1"

# 函数定义
my_function() {
    echo "doing something"
}

# 主逻辑
main() {
    echo "开始执行..."
    my_function
    echo "执行完成"
}

# 执行
main "$@"

常用速查

功能语法
变量name="value"
使用变量$name 或 ${name}
命令替换$(command)
if 判断if [ 条件 ]; then ... fi
for 循环for i in ...; do ... done
while 循环while [ 条件 ]; do ... done
函数func() { ... }

🚀 下一步

Shell 脚本学会了,接下来跟着长安了解 进程与服务 的管理!

—— 编程指南社区 · 长安

最后更新: 2025/12/1 15:56
Prev
⚔️ Vim 编辑器
Next
⚙️ 进程与服务