35·Shell 基础入门

if 条件判断

ifconditionals

第 35 课:if 条件判断

学习目标

完成本课学习后,你将能够:

  1. 理解 Shell 脚本中 if 条件判断的基本语法和结构
  2. 掌握文件与目录的常见测试操作(如是否存在、是否可读等)
  3. 学会使用逻辑运算符组合多个条件
  4. 能够编写包含条件判断的简单运维脚本

核心概念

1. 什么是条件判断?

想象一下,你在写一个自动备份脚本:如果 /backup 目录不存在,就创建它;如果存在,就直接开始备份。这种“如果…就…”的逻辑,就是条件判断。在 Shell 脚本中,我们使用 if 语句来实现这个功能。

2. 基本语法结构

Shell 的 if 语句有几种形式,最常用的是:

if [ 条件 ]; then
    # 条件为真时执行的命令
fi

或者:

if [ 条件 ]; then
    # 条件为真时执行的命令
else
    # 条件为假时执行的命令
fi

还有更复杂的:

if [ 条件1 ]; then
    # 条件1为真时执行
elif [ 条件2 ]; then
    # 条件1为假且条件2为真时执行
else
    # 所有条件都为假时执行
fi

重要提醒[ 后面和 ] 前面必须有空格!这是初学者最容易犯的错误。

3. 文件与目录测试

在运维中,我们经常需要检查文件或目录的状态。以下是一些常用测试:

测试条件含义示例
-e文件/目录是否存在[ -e /etc/passwd ]
-f是否为普通文件[ -f /etc/passwd ]
-d是否为目录[ -d /home ]
-r是否可读[ -r /etc/shadow ]
-w是否可写[ -w /tmp ]
-x是否可执行[ -x /usr/bin/ls ]
-s文件是否非空(大小>0)[ -s /var/log/syslog ]

4. 字符串测试

[ "$str" = "hello" ]    # 字符串相等
[ "$str" != "world" ]   # 字符串不相等
[ -z "$str" ]           # 字符串为空
[ -n "$str" ]           # 字符串非空

5. 数值比较

[ 10 -eq 10 ]    # 等于 (equal)
[ 10 -ne 20 ]    # 不等于 (not equal)
[ 10 -gt 5 ]     # 大于 (greater than)
[ 5 -lt 10 ]     # 小于 (less than)
[ 10 -ge 10 ]    # 大于等于 (greater or equal)
[ 5 -le 10 ]     # 小于等于 (less or equal)

6. 逻辑运算符

我们可以用逻辑运算符组合多个条件:

# 逻辑与:两个条件都为真才为真
[ 条件1 ] && [ 条件2 ]

# 逻辑或:至少一个条件为真就为真
[ 条件1 ] || [ 条件2 ]

# 逻辑非:条件取反
[ ! 条件 ]

代码示例

示例 1:检查文件是否存在并给出提示

#!/bin/bash
# 文件名:check_config.sh
# 功能:检查配置文件是否存在

CONFIG_FILE="/etc/nginx/nginx.conf"

if [ -e "$CONFIG_FILE" ]; then
    echo "配置文件存在:$CONFIG_FILE"
    if [ -r "$CONFIG_FILE" ]; then
        echo "配置文件可读,可以进行分析"
    else
        echo "警告:配置文件不可读,需要权限提升"
    fi
else
    echo "错误:配置文件 $CONFIG_FILE 不存在"
    echo "请先安装 nginx 或创建配置文件"
    exit 1
fi

# 如果文件存在且可读,可以继续后续操作
if [ -e "$CONFIG_FILE" ] && [ -r "$CONFIG_FILE" ]; then
    echo "开始分析配置文件..."
    # 这里可以添加分析配置文件的命令
fi

示例 2:磁盘空间监控脚本

#!/bin/bash
# 文件名:disk_monitor.sh
# 功能:监控磁盘空间使用率

# 获取根分区的使用百分比(去掉%号)
USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
THRESHOLD=80

echo "当前磁盘使用率:${USAGE}%"

if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "警告:磁盘使用率超过 ${THRESHOLD}%!"
    echo "建议清理 /var/log 目录下的旧日志文件"
    
    # 检查是否还有足够的临时空间
    if [ -d "/tmp" ] && [ -w "/tmp" ]; then
        echo "临时目录 /tmp 可用,可以进行清理操作"
    else
        echo "错误:/tmp 目录不可用,请检查系统"
        exit 1
    fi
else
    echo "磁盘空间充足,系统运行正常。"
fi

示例 3:用户权限检查脚本

#!/bin/bash
# 文件名:user_check.sh
# 功能:检查当前用户是否有执行特定操作的权限

# 检查是否以root用户运行
if [ "$(id -u)" -eq 0 ]; then
    echo "当前以root用户运行"
    echo "可以执行系统管理操作"
else
    echo "当前用户:$(whoami)"
    echo "非root用户,权限受限"
    
    # 检查是否在sudo组中
    if groups | grep -q "sudo\|wheel"; then
        echo "但当前用户在sudo组中,可以使用sudo提升权限"
    else
        echo "警告:用户不在sudo组中,某些操作可能无法执行"
    fi
fi

# 检查是否可以读取某个受保护的文件
SHADOW_FILE="/etc/shadow"
if [ -r "$SHADOW_FILE" ]; then
    echo "可以读取shadow文件(可能权限配置有问题)"
elif [ -f "$SHADOW_FILE" ]; then
    echo "shadow文件存在但不可读(正常)"
else
    echo "shadow文件不存在(异常情况)"
fi

实践练习

练习 1:基础文件检查(简单)

题目:编写一个脚本,检查 /etc/hostname 文件是否存在。如果存在,显示其内容;如果不存在,创建一个新的主机名文件,内容为 "my-server"。

要求

  • 脚本文件名:hostname_check.sh
  • 使用 if 条件判断
  • 创建文件时需要使用 sudo 权限(提示:使用 sudo tee 命令)

预期输出

如果文件存在:
主机名文件存在,内容:my-server.example.com

如果文件不存在:
创建新的主机名文件:my-server

练习 2:目录清理脚本(中等)

题目:编写一个清理脚本,检查 /tmp 目录下是否有超过7天的日志文件(扩展名为 .log),如果有则删除它们,并统计删除的文件数量。

要求

  • 脚本文件名:cleanup_logs.sh
  • 使用 find 命令查找文件
  • 在删除前显示找到的文件数量
  • 使用 if 判断是否有文件需要清理

预期输出

找到 3 个超过7天的日志文件
正在清理...
清理完成,共删除 3 个文件

或

没有找到需要清理的日志文件

练习 3:服务状态检查(较难)

题目:编写一个脚本检查 nginx 服务的状态。如果服务正在运行,检查其进程数是否超过10个;如果服务未运行,尝试自动启动它。

要求

  • 脚本文件名:nginx_status.sh
  • 使用 pgrep nginxsystemctl 检查服务状态
  • 记录操作日志到 /var/log/nginx_check.log
  • 包含错误处理

预期输出

nginx 服务正在运行,当前进程数:8

或

nginx 服务未运行,正在尝试启动...
nginx 服务启动成功

或

nginx 服务未运行,启动失败:端口80被占用

常见错误

1. 空格错误

# 错误写法 - 缺少空格
if [ -e"/etc/passwd" ]; then  # 错误!

# 正确写法
if [ -e "/etc/passwd" ]; then  # 正确

2. 变量未加引号

# 错误写法 - 如果变量为空会导致语法错误
if [ $FILE -e ]; then  # 如果 $FILE 为空,实际执行 [ -e ]

# 正确写法 - 变量加双引号
if [ -e "$FILE" ]; then  # 正确,即使变量为空也不会出错

3. 测试表达式错误

# 错误写法 - 使用了错误的数值比较
if [ $A > $B ]; then  # 这是字符串重定向,不是数值比较!

# 正确写法
if [ $A -gt $B ]; then  # 正确的数值比较

4. 混淆 Shell 类型

# 在某些 Shell 中可以使用双括号
if [[ $str == "hello" ]]; then  # bash/zsh 支持

# 但在某些 Shell 中只能使用单括号
if [ "$str" = "hello" ]; then   # 所有 Shell 都支持

5. 忘记结束标记

# 错误写法 - 缺少 fi
if [ 条件 ]; then
    echo "条件为真"

# 正确写法
if [ 条件 ]; then
    echo "条件为真"
fi  # 不能忘记这个结束标记

小结

本课我们学习了 Shell 脚本中最重要的控制结构之一:if 条件判断。关键要点包括:

  1. 基本语法:记住 if [ 条件 ]; then ... fi 的基本结构,注意空格
  2. 文件测试:使用 -e-f-d-r-w-x 等测试文件属性
  3. 字符串和数值:字符串用 =!=-z-n;数值用 -eq-gt-lt
  4. 逻辑组合&&(与)、||(或)、!(非)组合多个条件
  5. 实际应用:条件判断是运维脚本的基础,用于错误检查、权限验证、资源监控等

记住:好的运维脚本应该“防患于未然”,在执行操作前先检查条件是否满足。这能大大提高脚本的健壮性和可靠性。

下一课我们将学习 case 语句,它适用于多分支选择场景,是 if 语句的有力补充。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「case 多分支选择」 以巩固所学知识。