Linux Shell 脚本是一种用于在命令行环境中编写和执行批处理任务的脚本语言。它通过组合多条命令来实现复杂的任务自动化。
Shell 脚本基础
脚本结构
一个典型的 Shell 脚本包含以下几个部分:
- Shebang:指定脚本的解释器。
- 注释:使用
#
开头的行。 - 变量:定义和使用变量。
- 运算符:用于数学和逻辑运算。
- 条件语句:
if
、case
等。 - 循环语句:
for
、while
、until
等。 - 函数:定义和调用函数。
Shebang
Shebang 位于脚本的第一行,指定脚本由哪个解释器执行。
#!/bin/bash
注释
注释使用 #
开头。
# 这是一个注释
变量
变量可以是字符串、数字或其他类型。
name="John"
age=30
变量的引用使用 $
符号。
echo "Name: $name"
echo "Age: $age"
运算符
算术运算
使用 expr
或 $(( ))
进行算术运算。
a=10
b=20
sum=$(($a + $b))
echo "Sum: $sum"
逻辑运算
逻辑运算用于条件判断。
if [ $a -eq $b ]; then
echo "a 等于 b"
else
echo "a 不等于 b"
fi
条件语句
if 语句
if [ condition ]; then
# 当条件为真时执行
elif [ another_condition ]; then
# 当另一个条件为真时执行
else
# 当条件为假时执行
fi
case 语句
case $variable in
pattern1)
# 当变量匹配 pattern1 时执行
;;
pattern2)
# 当变量匹配 pattern2 时执行
;;
*)
# 默认情况下执行
;;
esac
循环语句
for 循环
for var in list; do
# 对于 list 中的每个 var,执行以下命令
done
while 循环
while [ condition ]; do
# 当条件为真时执行
done
until 循环
until [ condition ]; do
# 当条件为假时执行
done
函数
函数用于将一组命令封装在一起,以便多次调用。
function_name() {
# 函数体
}
调用函数:
function_name
数组
Shell 脚本支持一维数组。数组中的元素可以是任何数据类型。
定义数组
# 定义数组
my_array=(val1 val2 val3)
# 访问数组元素
echo ${my_array[0]} # 输出 val1
遍历数组
for element in "${my_array[@]}"; do
echo $element
done
字符串处理
Shell 脚本提供了多种字符串操作方法。
字符串长度
string="Hello, World!"
echo ${#string} # 输出 13
子字符串提取
string="Hello, World!"
echo ${string:7:5} # 输出 World
字符串替换
string="Hello, World!"
echo ${string/World/Bash} # 输出 Hello, Bash!
文件和目录操作
Shell 脚本可以轻松地处理文件和目录。
创建和删除文件
# 创建文件
touch myfile.txt
# 删除文件
rm myfile.txt
创建和删除目录
# 创建目录
mkdir mydir
# 删除目录
rmdir mydir
文件内容操作
# 读取文件内容
while read line; do
echo $line
done < myfile.txt
# 写入文件内容
echo "Hello, World!" > myfile.txt
# 追加文件内容
echo "Hello again!" >> myfile.txt
信号处理
Shell 脚本可以捕捉和处理信号(如终止信号)。
#!/bin/bash
# 定义信号处理函数
trap 'echo "捕捉到终止信号"; exit' SIGINT
# 主脚本
while true; do
echo "运行中..."
sleep 1
done
错误处理
使用 set
命令可以改变 Shell 的默认行为,以便更好地处理错误。
#!/bin/bash
# 在任何命令失败时退出
set -e
# 捕捉错误
trap 'echo "发生错误"' ERR
# 运行命令
cp non_existent_file.txt /tmp/
调试脚本
使用 -x
选项可以启用 Shell 脚本的调试模式,显示每一条命令及其参数。
#!/bin/bash
# 启用调试模式
set -x
# 示例命令
echo "Hello, World!"
内置命令和外部命令
Shell 脚本中可以使用许多内置命令和外部命令。
常见内置命令
# 输出字符串
echo "Hello, World!"
# 读取用户输入
read name
# 条件判断
if [ condition ]; then
# 命令
fi
# 循环
for var in list; do
# 命令
done
常见外部命令
# 列出目录内容
ls
# 显示当前目录
pwd
# 显示文件内容
cat myfile.txt
# 复制文件
cp source_file.txt dest_file.txt
# 移动文件
mv source_file.txt dest_file.txt
# 删除文件
rm myfile.txt
案例
案例 1:备份目录
编写一个 Shell 脚本,用于备份指定目录。该脚本将压缩目录并将其复制到备份目录。
#!/bin/bash
# 备份目录路径
SOURCE_DIR="/path/to/source"
BACKUP_DIR="/path/to/backup"
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
BACKUP_FILE="backup_$TIMESTAMP.tar.gz"
# 创建备份
tar -czf $BACKUP_DIR/$BACKUP_FILE $SOURCE_DIR
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功:$BACKUP_DIR/$BACKUP_FILE"
else
echo "备份失败"
fi
案例 2:监控系统资源
编写一个 Shell 脚本,用于监控系统的 CPU 和内存使用情况,并在使用率超过阈值时发送警报。
#!/bin/bash
# CPU 和内存使用阈值
CPU_THRESHOLD=80
MEMORY_THRESHOLD=80
while true; do
# 获取 CPU 使用率
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
# 获取内存使用率
MEMORY_USAGE=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
# 检查 CPU 使用率
if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
echo "警告:CPU 使用率超过阈值 ($CPU_USAGE%)"
fi
# 检查内存使用率
if (( $(echo "$MEMORY_USAGE > $MEMORY_THRESHOLD" | bc -l) )); then
echo "警告:内存使用率超过阈值 ($MEMORY_USAGE%)"
fi
# 每 5 秒检查一次
sleep 5
done
案例 3:自动化部署脚本
编写一个 Shell 脚本,用于自动化部署 Web 应用。该脚本将拉取最新代码、安装依赖、构建项目并重启服务器。
#!/bin/bash
# 项目目录
PROJECT_DIR="/path/to
/project"
# 进入项目目录
cd $PROJECT_DIR
# 拉取最新代码
git pull origin main
# 检查 git pull 是否成功
if [ $? -ne 0 ]; then
echo "拉取代码失败"
exit 1
fi
# 安装依赖
npm install
# 检查 npm install 是否成功
if [ $? -ne 0 ]; then
echo "安装依赖失败"
exit 1
fi
# 构建项目
npm run build
# 检查 npm run build 是否成功
if [ $? -ne 0 ]; then
echo "构建项目失败"
exit 1
fi
# 重启服务器
systemctl restart myapp.service
# 检查服务器是否重启成功
if [ $? -ne 0 ]; then
echo "重启服务器失败"
exit 1
fi
echo "部署成功"
案例 4:日志文件管理
编写一个 Shell 脚本,定期压缩和删除旧的日志文件。
#!/bin/bash
LOG_DIR="/var/log/myapp"
BACKUP_DIR="/var/log/myapp/backup"
DAYS_TO_KEEP=7
# 创建备份目录
mkdir -p $BACKUP_DIR
# 压缩日志文件
find $LOG_DIR -type f -name "*.log" -mtime +$DAYS_TO_KEEP -exec gzip {} \; -exec mv {}.gz $BACKUP_DIR/ \;
# 删除旧的压缩文件
find $BACKUP_DIR -type f -name "*.gz" -mtime +$DAYS_TO_KEEP -exec rm {} \;
echo "日志文件管理完成"
案例 5:数据库备份与恢复
编写一个 Shell 脚本,自动备份和恢复 MySQL 数据库。
#!/bin/bash
DB_USER="root"
DB_PASS="password"
DB_NAME="mydatabase"
BACKUP_DIR="/backup"
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
BACKUP_FILE="$BACKUP_DIR/$DB_NAME-$TIMESTAMP.sql"
# 创建备份
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE
if [ $? -eq 0 ]; then
echo "数据库备份成功:$BACKUP_FILE"
else
echo "数据库备份失败"
exit 1
fi
# 恢复数据库
# mysql -u $DB_USER -p$DB_PASS $DB_NAME < $BACKUP_FILE