欢迎光临
我们一直在努力

Shell脚本(.sh)常用语法全解析:从入门到实战

文章目录

    • 一、脚本基础结构
      • 1. 解释器声明(Shebang)
      • 2. 注释语法
      • 3. 执行方式
    • 二、变量与数据类型
      • 1. 变量定义与使用
      • 2. 特殊变量
      • 3. 只读变量与删除变量
      • 4. 数值运算
      • 5. 字符串操作
    • 三、输入与输出
      • 1. 输出(echo)
      • 2. 输入(read)
      • 3. 重定向
    • 四、条件判断(if语句)
      • 基本语法
      • 常用判断条件
      • 实战示例:检查Nginx服务
    • 五、循环语句
      • 1. for循环
      • 2. while循环
      • 3. until循环(条件为假时执行)
    • 六、case分支语句
    • 七、函数
    • 八、错误处理与调试
      • 1. 错误中断
      • 2. 调试模式
      • 3. 检查命令执行结果
    • 九、实战案例:日志清理脚本
    • 十、新手避坑指南
    • 总结

一、脚本基础结构

1. 解释器声明(Shebang)

脚本首行必须指定解释器,告诉系统用哪个程序执行:

#!/bin/bash # 最常用,指定Bash解释器
#!/usr/bin/env bash # 跨平台兼容写法(推荐)
#!/bin/sh # POSIX标准Shell(部分系统sh是bash的简化版)

2. 注释语法

# 单行注释

: <<'EOF'
多行注释
可以写很多行
EOF

3. 执行方式

# 方式1:赋予执行权限后运行(推荐)
chmod +x script.sh
./script.sh

# 方式2:指定解释器运行(无需权限)
bash script.sh
sh script.sh


二、变量与数据类型

1. 变量定义与使用

# 定义变量(等号两侧绝对不能有空格!)
name="Alice"
port=8080
path="/var/log"

# 使用变量
echo $name # 基本用法
echo ${name}_backup # 推荐:用{}明确变量边界,避免歧义
echo "$name" # 双引号内会解析变量
echo '$name' # 单引号内原样输出,不解析

2. 特殊变量

$0 # 脚本文件名
$1 $2 # 第1、第2个位置参数
$# # 参数个数
$* # 所有参数(作为一个整体字符串)
$@ # 所有参数(每个参数独立,推荐用于循环)
$? # 上一条命令的返回码(0=成功,非0=失败)
$$ # 当前进程PID
$USER # 当前登录用户
$PWD # 当前工作目录

3. 只读变量与删除变量

readonly PI=3.14 # 只读,不可修改
unset name # 删除变量

4. 数值运算

a=10
b=3

# 方法1:$(()) 推荐
echo $((a + b)) # 13
echo $((a * b)) # 30
echo $((a % b)) # 1

# 方法2:expr(注意空格)
echo $(expr $a – $b) # 7

# 方法3:bc(支持浮点数)
echo "scale=2; 10 / 3" | bc # 3.33

5. 字符串操作

str="Hello World"
echo ${#str} # 字符串长度:11
echo ${str:0:5} # 截取:Hello
echo ${str/World/Bash} # 替换:Hello Bash


三、输入与输出

1. 输出(echo)

echo "普通输出"
echo -e "换行\\n测试" # -e 支持转义符
echo "不换行" | tr -d '\\n'
echo "错误信息" >&2 # 输出到标准错误流

2. 输入(read)

read -p "请输入用户名:" username # 带提示
read -t 10 -p "请输入密码:" password # 10秒超时
read -s -p "密码:" pwd # -s 隐藏输入

3. 重定向

echo "内容" > file.log # 覆盖写入
echo "追加" >> file.log # 追加写入
./script.sh > out.log 2>&1 # 标准输出+错误输出都写入文件


四、条件判断(if语句)

基本语法

if [ 条件 ]; then
命令
elif [ 条件2 ]; then
命令
else
命令
fi

常用判断条件

# 文件判断
[ -f "$file" ] # 文件存在且是普通文件
[ -d "$dir" ] # 目录存在
[ -e "$path" ] # 路径存在(不区分类型)
[ -r "$file" ] # 可读
[ -w "$file" ] # 可写
[ -x "$file" ] # 可执行
[ -s "$file" ] # 文件非空

# 字符串判断
[ -z "$str" ] # 字符串为空
[ -n "$str" ] # 字符串非空
[ "$a" = "$b" ] # 字符串相等
[ "$a" != "$b" ] # 字符串不等

# 数值比较
[ $a -eq $b ] # 等于
[ $a -ne $b ] # 不等于
[ $a -gt $b ] # 大于
[ $a -lt $b ] # 小于
[ $a -ge $b ] # 大于等于
[ $a -le $b ] # 小于等于

实战示例:检查Nginx服务

if ps -ef | grep -v grep | grep -q nginx; then
echo "Nginx正在运行"
else
echo "Nginx未运行,正在重启…"
systemctl restart nginx
fi


五、循环语句

1. for循环

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

# 范围遍历
for i in {1..10}; do
echo "第 $i 次"
done

# C语言风格
for ((i=0; i<10; i++)); do
echo $i
done

# 遍历文件
for file in /var/log/*.log; do
echo "处理文件:$file"
done

2. while循环

count=0
while [ $count -lt 5 ]; do
echo "当前值:$count"
count=$((count + 1))
done

# 逐行读取文件
while IFS= read -r line; do
echo "行内容:$line"
done < file.txt

3. until循环(条件为假时执行)

count=0
until [ $count -ge 5 ]; do
echo $count
count=$((count + 1))
done


六、case分支语句

适用于多值匹配,替代多个if-elif:

case $1 in
start)
echo "启动服务…"
systemctl start nginx
;;
stop)
echo "停止服务…"
systemctl stop nginx
;;
restart)
echo "重启服务…"
systemctl restart nginx
;;
*)
echo "用法:$0 {start|stop|restart}"
exit 1
;;
esac


七、函数

# 定义函数
check_service() {
local service_name=$1 # local 局部变量
if systemctl is-active –quiet "$service_name"; then
echo "$service_name 正在运行"
return 0
else
echo "$service_name 未运行"
return 1
fi
}

# 调用函数
check_service nginx
result=$? # 获取函数返回值
echo "返回码:$result"


八、错误处理与调试

1. 错误中断

set -e # 任何命令失败立即退出脚本
set -u # 使用未定义变量时报错
set -o pipefail # 管道中任一命令失败则整体失败

2. 调试模式

# 运行时调试
bash -x script.sh

# 脚本内开启/关闭调试
set -x # 开启:显示每条执行的命令
set +x # 关闭调试

3. 检查命令执行结果

if ! command -v nginx &>/dev/null; then
echo "nginx未安装"
exit 1
fi


九、实战案例:日志清理脚本

#!/usr/bin/env bash
set -euo pipefail

# 配置
LOG_DIR="/var/log/app"
KEEP_DAYS=30
BACKUP_DIR="/backup/logs"

# 函数:清理过期日志
clean_logs() {
local dir=$1
local days=$2

if [ ! -d "$dir" ]; then
echo "目录不存在:$dir"
return 1
fi

echo "清理 $dir 中超过 ${days} 天的日志…"
find "$dir" -name "*.log" -mtime +$days -delete
echo "清理完成"
}

# 主逻辑
echo "===== 日志清理开始:$(date) ====="
clean_logs "$LOG_DIR" "$KEEP_DAYS"

# 备份今日日志
mkdir -p "$BACKUP_DIR"
tar -czf "${BACKUP_DIR}/logs_$(date +%Y%m%d).tar.gz" "$LOG_DIR"/*.log 2>/dev/null || true

echo "===== 清理结束:$(date) ====="


十、新手避坑指南

常见错误正确写法说明
name = "value" name="value" 等号两侧不能有空格
if [$a -eq $b] if [ $a -eq $b ] [ 和 ] 内侧必须有空格
echo $var_text echo ${var}_text 用{}明确变量边界
忘记加执行权限 chmod +x script.sh 否则./script.sh报权限错误
不检查返回值 `cmd
硬编码路径 使用变量 便于维护和跨环境部署

总结

Shell脚本的核心语法可以归纳为:变量 → 条件 → 循环 → 函数 → 错误处理。掌握这些基础模块,你就能构建出绝大多数自动化运维脚本。建议从简单的文件操作、服务检查脚本开始练习,逐步过渡到复杂的批量部署和监控告警场景。

💡 学习建议:多用bash -x调试,多写set -euo pipefail保底,养成检查$?的习惯,你的脚本会越来越健壮!

赞(0)
未经允许不得转载:171主机测评 » Shell脚本(.sh)常用语法全解析:从入门到实战
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址