Shell脚本是Linux系统管理和自动化运维的必备技能。本文将带你从入门到进阶,掌握Shell脚本编程的核心知识。
1. 基础语法
Hello World
#!/bin/bash
# 这是一个注释
echo "Hello World"
变量
#!/bin/bash
# 定义变量(不能有空格)
name="Alice"
age=30
# 使用变量($前缀)
echo "Name: $name"
echo "Age: ${age}"
# 只读变量
readonly PI=3.14159
# 环境变量
export PATH=$PATH:/new/path
特殊变量
$0 # 脚本名称
$1-$9 # 第1-9个参数
${10} # 第10个参数
$# # 参数个数
$* # 所有参数
$@ # 所有参数(保持引用)
$? # 上一条命令的退出状态
$$ # 当前进程ID
$! # 后台进程ID
2. 条件判断
if语句
#!/bin/bash
if [ "$age" -gt 18 ]; then
echo "Adult"
elif [ "$age" -eq 18 ]; then
echo "Just turned 18"
else
echo "Minor"
fi
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
测试条件
# 文件测试
[ -f file.txt ] # 是普通文件
[ -d dir/ ] # 是目录
[ -r file.txt ] # 可读
[ -w file.txt ] # 可写
[ -x script.sh ] # 可执行
[ -e file.txt ] # 文件存在
[ -s file.txt ] # 文件非空
# 字符串测试
[ -z "$str" ] # 字符串为空
[ -n "$str" ] # 字符串非空
[ "$a" = "$b" ] # 字符串相等
[ "$a" != "$b" ] # 字符串不等
3. 循环
for循环
#!/bin/bash
# 遍历列表
for file in *.txt; do
echo "Processing $file"
done
# 遍历数字
for i in {1..10}; do
echo "Number: $i"
done
# C语言风格
for ((i=0; i<10; i++)); do
echo "i=$i"
done
while循环
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count: $count"
((count++))
done
until循环
#!/bin/bash
count=1
until [ $count -gt 5 ]; do
echo "Count: $count"
((count++))
done
4. 函数
#!/bin/bash
# 定义函数
function greet() {
local name=$1
echo "Hello, $name!"
}
# 调用函数
greet "Alice"
greet "Bob"
# 带返回值
function add() {
local result=$(( $1 + $2 ))
echo $result
}
sum=$(add 10 20)
echo "Sum: $sum"
5. 数组
#!/bin/bash
# 定义数组
fruits=("apple" "banana" "cherry")
# 访问元素
echo ${fruits[0]} # apple
echo ${fruits[@]} # 所有元素
echo ${#fruits[@]} # 数组长度
# 添加元素
fruits+=("orange")
# 遍历数组
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
6. 字符串处理
#!/bin/bash
str="Hello World"
# 长度
echo ${#str} # 11
# 子串
echo ${str:0:5} # Hello
echo ${str:6} # World
# 替换
echo ${str/World/Bash} # Hello Bash
echo ${str//l/L} # HeLLo WorLd
# 删除前缀
echo ${str#Hello} # World
echo ${str##Hello} # World
# 删除后缀
echo ${str%World} # Hello
echo ${str%%World} # Hello
7. 实战案例
批量重命名
#!/bin/bash
count=1
for file in *.jpg; do
new_name=$(printf "photo_%03d.jpg" $count)
mv "$file" "$new_name"
((count++))
done
日志分析
#!/bin/bash
logfile="/var/log/nginx/access.log"
# 统计状态码
echo "Status Code Distribution:"
awk '{print $9}' "$logfile" | sort | uniq -c | sort -nr
# 统计IP访问量
echo "\nTop 10 IPs:"
awk '{print $1}' "$logfile" | sort | uniq -c | sort -nr | head -10
自动备份
#!/bin/bash
backup_dir="/backup"
timestamp=$(date +%Y%m%d_%H%M%S)
archive="backup_$timestamp.tar.gz"
tar -czf "$backup_dir/$archive" /important/data
# 保留最近7天备份
find "$backup_dir" -name "backup_*.tar.gz" -mtime +7 -delete
系统监控
#!/bin/bash
# CPU使用率
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
# 内存使用率
mem_usage=$(free | grep Mem | awk '{print ($3/$2)*100}')
# 磁盘使用率
disk_usage=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1)
echo "CPU: $cpu_usage%"
echo "Memory: $mem_usage%"
echo "Disk: $disk_usage%"
8. 调试技巧
#!/bin/bash
# 调试模式
set -x # 开启调试
# 你的代码
set +x # 关闭调试
# 错误退出
set -e # 任何命令失败立即退出
set -u # 使用未定义变量时报错
# 检查语法
bash -n script.sh
# 跟踪执行
bash -x script.sh
9. 最佳实践
- 使用shebang:#!/bin/bash
- 变量引用加引号:"$variable"
- 使用函数:模块化代码
- 错误处理:检查命令返回值
- 日志记录:记录关键操作
- 注释清晰:说明复杂逻辑
10. 部署自动化
#!/bin/bash
# 部署脚本示例
APP_DIR="/var/www/myapp"
BACKUP_DIR="/backup"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 1. 备份当前版本
tar -czf "$BACKUP_DIR/app_$TIMESTAMP.tar.gz" -C "$APP_DIR" .
# 2. 拉取最新代码
cd $APP_DIR
git pull origin main
# 3. 安装依赖
pip install -r requirements.txt
# 4. 运行数据库迁移
python manage.py migrate
# 5. 收集静态文件
python manage.py collectstatic --noinput
# 6. 重启服务
sudo systemctl restart gunicorn
echo "Deployment completed at $(date)"
总结
Shell脚本虽然语法简单,但功能强大。掌握Shell脚本,可以实现:
- 自动化部署:CI/CD流水线
- 系统监控:定时检查系统状态
- 日志分析:批量处理日志文件
- 备份恢复:自动化备份策略
📖 进阶学习:学习Awk、Sed等文本处理工具,掌握Expect进行交互式自动化,以及使用Ansible进行配置管理。