目录
什么是Shell脚本环境准备第一个Shell脚本变量的使用用户输入条件判断循环结构函数实战示例调试技巧总结
什么是Shell脚本
Shell脚本是一种自动化工具,它允许您将一系列Shell命令组合在一起执行。通过Shell脚本,您可以:
自动化重复性任务批量处理文件系统管理和维护创建复杂的工作流程
环境准备
1. 检查Shell环境
# 查看当前使用的Shell
echo $SHELL
# 查看系统支持的Shell
cat /etc/shells
2. 选择文本编辑器
推荐使用以下编辑器之一:
vim 或 vinanogedit(图形界面)VS Code + Bash插件
第一个Shell脚本
1. 创建脚本文件
# 创建脚本文件
touch hello.sh
# 使用编辑器打开
nano hello.sh
2. 编写脚本内容
#!/bin/bash
# 这是我的第一个Shell脚本
echo "Hello, World!"
echo "今天是:$(date)"
echo "当前用户:$(whoami)"
3. 给脚本添加执行权限
chmod +x hello.sh
4. 运行脚本
# 方法1:直接运行
./hello.sh
# 方法2:使用bash命令
bash hello.sh
变量的使用
1. 变量定义和赋值
#!/bin/bash
# 定义变量(注意:等号两边不能有空格)
name="张三"
age=25
city="北京"
# 数字变量
count=10
price=99.99
# 命令结果赋值
current_date=$(date)
file_count=$(ls -1 | wc -l)
echo "姓名:$name"
echo "年龄:$age"
echo "城市:$city"
echo "当前日期:$current_date"
echo "文件数量:$file_count"
2. 变量的使用规则
#!/bin/bash
name="李四"
# 变量引用的几种方式
echo $name # 简单引用
echo ${name} # 花括号引用(推荐)
echo "$name" # 双引号引用(保留变量)
echo '$name' # 单引号引用(不解析变量)
# 变量拼接
full_name="${name}同学"
echo "全名:$full_name"
# 变量长度
echo "姓名长度:${#name}"
3. 特殊变量
#!/bin/bash
echo "脚本名称:$0"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "所有参数:$@"
echo "参数个数:$#"
echo "上一条命令的退出状态:$?"
echo "当前进程ID:$$"
用户输入
1. read命令获取用户输入
#!/bin/bash
echo "请输入您的姓名:"
read name
echo "请输入您的年龄:"
read age
echo "您好,$name!您今年$age岁。"
2. 带提示的输入
#!/bin/bash
read -p "请输入您的姓名:" name
read -p "请输入您的年龄:" age
read -s -p "请输入密码:" password # -s 隐藏输入
echo # 换行
echo "姓名:$name,年龄:$age"
条件判断
1. if语句基本语法
#!/bin/bash
read -p "请输入一个数字:" number
if [ $number -gt 10 ]; then
echo "$number 大于 10"
elif [ $number -eq 10 ]; then
echo "$number 等于 10"
else
echo "$number 小于 10"
fi
2. 常用的条件测试
#!/bin/bash
# 数值比较
num1=10
num2=20
if [ $num1 -eq $num2 ]; then echo "相等"; fi
if [ $num1 -ne $num2 ]; then echo "不相等"; fi
if [ $num1 -lt $num2 ]; then echo "$num1 小于 $num2"; fi
if [ $num1 -gt $num2 ]; then echo "$num1 大于 $num2"; fi
if [ $num1 -le $num2 ]; then echo "$num1 小于等于 $num2"; fi
if [ $num1 -ge $num2 ]; then echo "$num1 大于等于 $num2"; fi
# 字符串比较
str1="hello"
str2="world"
if [ "$str1" = "$str2" ]; then echo "字符串相等"; fi
if [ "$str1" != "$str2" ]; then echo "字符串不相等"; fi
if [ -z "$str1" ]; then echo "字符串为空"; fi
if [ -n "$str1" ]; then echo "字符串不为空"; fi
# 文件测试
filename="test.txt"
if [ -f "$filename" ]; then echo "文件存在"; fi
if [ ! -f "$filename" ]; then echo "文件不存在"; fi
if [ -d "$filename" ]; then echo "是目录"; fi
if [ -r "$filename" ]; then echo "文件可读"; fi
if [ -w "$filename" ]; then echo "文件可写"; fi
if [ -x "$filename" ]; then echo "文件可执行"; fi
3. 逻辑运算符
#!/bin/bash
age=25
score=85
# 逻辑与 (&&)
if [ $age -ge 18 ] && [ $score -ge 80 ]; then
echo "年龄达标且成绩优秀"
fi
# 逻辑或 (||)
if [ $age -lt 18 ] || [ $score -lt 60 ]; then
echo "年龄不达标或成绩不及格"
else
echo "条件都满足"
fi
# 逻辑非 (!)
if [ ! -f "config.txt" ]; then
echo "配置文件不存在"
fi
循环结构
1. for循环
#!/bin/bash
# 基本for循环
echo "=== 基本for循环 ==="
for i in 1 2 3 4 5
do
echo "数字:$i"
done
# 范围for循环
echo "=== 范围for循环 ==="
for i in {1..10}
do
echo "计数:$i"
done
# 数组for循环
echo "=== 数组for循环 ==="
fruits=("苹果" "香蕉" "橙子" "葡萄")
for fruit in "${fruits[@]}"
do
echo "水果:$fruit"
done
# 文件for循环
echo "=== 文件for循环 ==="
for file in *.txt
do
if [ -f "$file" ]; then
echo "处理文件:$file"
fi
done
# C风格for循环
echo "=== C风格for循环 ==="
for ((i=1; i<=5; i++))
do
echo "第 $i 次循环"
done
2. while循环
#!/bin/bash
# 基本while循环
echo "=== 基本while循环 ==="
count=1
while [ $count -le 5 ]
do
echo "计数:$count"
count=$((count + 1))
done
# 读取文件内容
echo "=== 读取文件内容 ==="
while read line
do
echo "行内容:$line"
done < "data.txt"
# 无限循环
echo "=== 无限循环示例 ==="
while true
do
read -p "请输入命令(输入 'quit' 退出):" cmd
if [ "$cmd" = "quit" ]; then
break
fi
echo "您输入了:$cmd"
done
3. until循环
#!/bin/bash
# until循环(条件为假时继续执行)
count=1
until [ $count -gt 5 ]
do
echo "计数:$count"
count=$((count + 1))
done
4. 循环控制
#!/bin/bash
# break和continue示例
for i in {1..10}
do
if [ $i -eq 3 ]; then
continue # 跳过当前循环
fi
if [ $i -eq 8 ]; then
break # 跳出整个循环
fi
echo "数字:$i"
done
函数
1. 函数定义和调用
#!/bin/bash
# 函数定义方式1
function greet() {
echo "你好,$1!"
}
# 函数定义方式2
say_goodbye() {
echo "再见,$1!"
}
# 调用函数
greet "张三"
say_goodbye "李四"
2. 函数参数和返回值
#!/bin/bash
# 计算两个数的和
add_numbers() {
local num1=$1
local num2=$2
local sum=$((num1 + num2))
echo $sum
}
# 检查文件是否存在
check_file() {
local filename=$1
if [ -f "$filename" ]; then
return 0 # 成功
else
return 1 # 失败
fi
}
# 使用函数
result=$(add_numbers 10 20)
echo "10 + 20 = $result"
if check_file "test.txt"; then
echo "文件存在"
else
echo "文件不存在"
fi
3. 局部变量和全局变量
#!/bin/bash
global_var="我是全局变量"
test_scope() {
local local_var="我是局部变量"
global_var="全局变量被修改了"
echo "函数内部:"
echo " 局部变量:$local_var"
echo " 全局变量:$global_var"
}
echo "调用函数前:$global_var"
test_scope
echo "调用函数后:$global_var"
实战示例
1. 系统信息查看脚本
#!/bin/bash
echo "================= 系统信息查看器 ================="
# 系统基本信息
echo "主机名:$(hostname)"
echo "操作系统:$(uname -s)"
echo "内核版本:$(uname -r)"
echo "系统架构:$(uname -m)"
# 时间信息
echo "当前时间:$(date)"
echo "系统运行时间:$(uptime -p)"
# 磁盘使用情况
echo ""
echo "================= 磁盘使用情况 ================="
df -h | head -n 5
# 内存使用情况
echo ""
echo "================= 内存使用情况 ================="
free -h
# 网络信息
echo ""
echo "================= 网络信息 ================="
ip addr show | grep -E "inet.*global" | head -n 3
echo ""
echo "================= 报告生成完成 ================="
2. 文件批量重命名脚本
#!/bin/bash
# 批量重命名脚本
batch_rename() {
local source_dir=$1
local old_extension=$2
local new_extension=$3
if [ ! -d "$source_dir" ]; then
echo "错误:目录 $source_dir 不存在"
return 1
fi
count=0
for file in "$source_dir"/*."$old_extension"
do
if [ -f "$file" ]; then
# 获取文件名(不含路径和扩展名)
basename=$(basename "$file" ."$old_extension")
# 新文件名
new_file="$source_dir/$basename.$new_extension"
# 重命名文件
mv "$file" "$new_file"
echo "重命名:$file -> $new_file"
count=$((count + 1))
fi
done
echo "总共重命名了 $count 个文件"
}
# 使用示例
read -p "请输入目录路径:" dir_path
read -p "请输入原扩展名:" old_ext
read -p "请输入新扩展名:" new_ext
batch_rename "$dir_path" "$old_ext" "$new_ext"
3. 简单的备份脚本
#!/bin/bash
# 简单备份脚本
backup_files() {
local source_dir=$1
local backup_dir=$2
local timestamp=$(date +"%Y%m%d_%H%M%S")
# 创建备份目录
mkdir -p "$backup_dir"
# 备份文件名
backup_file="$backup_dir/backup_$timestamp.tar.gz"
# 创建压缩包
tar -czf "$backup_file" -C "$(dirname "$source_dir")" "$(basename "$source_dir")"
if [ $? -eq 0 ]; then
echo "备份成功:$backup_file"
echo "备份大小:$(du -h "$backup_file" | cut -f1)"
else
echo "备份失败"
return 1
fi
}
# 清理旧备份(保留最近5个)
cleanup_old_backups() {
local backup_dir=$1
local keep_count=5
# 获取备份文件列表(按时间排序)
backup_files=($(ls -t "$backup_dir"/backup_*.tar.gz 2>/dev/null))
# 如果备份文件数量超过保留数量,删除多余的
if [ ${#backup_files[@]} -gt $keep_count ]; then
echo "清理旧备份文件..."
for ((i=$keep_count; i<${#backup_files[@]}; i++))
do
rm -f "${backup_files[$i]}"
echo "删除:${backup_files[$i]}"
done
fi
}
# 主程序
main() {
echo "================= 文件备份工具 ================="
read -p "请输入要备份的目录:" source_directory
read -p "请输入备份存储目录:" backup_directory
if [ ! -d "$source_directory" ]; then
echo "错误:源目录不存在"
exit 1
fi
backup_files "$source_directory" "$backup_directory"
cleanup_old_backups "$backup_directory"
echo "备份任务完成"
}
# 运行主程序
main
调试技巧
1. 启用调试模式
#!/bin/bash
# 启用调试模式
set -x # 显示执行的每一条命令
set -e # 遇到错误立即退出
set -u # 使用未定义变量时报错
echo "这是调试模式下的脚本"
2. 错误处理
#!/bin/bash
# 错误处理函数
error_exit() {
echo "错误:$1" >&2
exit 1
}
# 检查命令是否存在
check_command() {
if ! command -v $1 &> /dev/null; then
error_exit "命令 $1 未找到,请先安装"
fi
}
# 使用示例
check_command "git"
check_command "curl"
echo "所有必要的命令都已安装"
3. 日志记录
#!/bin/bash
# 日志文件
LOG_FILE="script.log"
# 日志函数
log() {
local level=$1
shift
local message="$@"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# 使用示例
log "INFO" "脚本开始执行"
log "WARNING" "这是一个警告信息"
log "ERROR" "这是一个错误信息"
总结
通过本指南,您已经学会了:
基础知识:Shell脚本的基本概念和语法变量操作:如何定义、使用和操作变量用户交互:如何获取用户输入条件判断:if语句和各种条件测试循环结构:for、while、until循环的使用函数编程:如何定义和使用函数实战技能:通过实际例子学习脚本编写调试技巧:如何调试和优化脚本
下一步建议
多练习:编写更多的实用脚本学习高级特性:数组、正则表达式、信号处理等代码规范:养成良好的编程习惯性能优化:学习如何编写高效的脚本安全考虑:了解脚本安全最佳实践
常用资源
在线Shell脚本检查器:ShellCheckBash官方文档:GNU Bash Manual实用脚本示例:Awesome Shell
记住:编写好的Shell脚本需要不断的练习和经验积累。从简单的脚本开始,逐步增加复杂度,相信您很快就能成为Shell脚本专家!