个人用云计算学习笔记 --23(Shell 编程-2)

文章目录

  • [if 条件语句](#if 条件语句)
  • [Shell 函数](#Shell 函数)
    • [一、 Shell 函数介绍](#一、 Shell 函数介绍)
    • [二、 Shell 函数的语法](#二、 Shell 函数的语法)
    • [三、Shell 函数的执行](#三、Shell 函数的执行)
      • [1. 不带参数的函数](#1. 不带参数的函数)
      • [2. 带参数的函数](#2. 带参数的函数)
    • [四、Shell 函数的基础实践](#四、Shell 函数的基础实践)
    • [五、 企业级实践:URL 检测脚本](#五、 企业级实践:URL 检测脚本)
    • [六、 函数的递归调用](#六、 函数的递归调用)

if 条件语句

一、if 条件语句基础

1. 作用

类似汉语 "如果... 那么",是 Linux 运维中频繁使用的重要语句,用于根据条件执行不同指令。

2. 语法结构

  • 单分支结构

    bash 复制代码
    # 格式1
    if <条件表达式>
      then 
      指令
    fi
    
    # 格式2(本书主要使用)
    if <条件表达式>;then
      指令
    fi

    当条件表达式成立(真)时,执行 then 后的指令,否则忽略。

  • 双分支结构

    bash 复制代码
    if <条件表达式>;then
      指令集1
    else
      指令集2
    fi

    条件成立执行指令集 1,否则执行指令集 2。

  • 多分支结构

    bash 复制代码
    if <条件表达式1>;then
      指令1
    elif <条件表达式2>;then
      指令2
    else
      指令3
    fi

    依次判断条件,满足第一个条件后执行对应指令,都不满足则执行 else 后的指令。

3. 嵌套结构

if 条件语句可嵌套,每个 if 需对应一个 fi,建议缩进保持可读性:

bash 复制代码
if <条件表达式>;then
  if <条件表达式>;then
    指令
  fi
fi

二、条件表达式类型

if 条件语句中的<条件表达式>可采用以下类型:

  1. test 条件表达式

    bash 复制代码
    if test 表达式;then
      指令
    fi
  2. [] 条件表达式

    bash 复制代码
    if [ 字符串 或 算术表达式 ];then
      指令
    fi
  3. [[]] 条件表达式

    bash 复制代码
    if [[ 字符串 或 算术表达式 ]];then
      指令
    fi
  4. (()) 条件表达式

    bash 复制代码
    if ((算术表达式));then
      指令
    fi
  5. 命令表达式

    bash 复制代码
    if 命令;then
      指令
    fi

三、实践示例

  1. 检测并启动 sshd 服务

    bash 复制代码
    # 单分支:未运行则启动
    systemctl is-active sshd &>/dev/null
    if [ $? -ne 0 ];then
      echo "sshd is not running, I'll start sshd."
      systemctl start sshd
    fi
    
    # 双分支:运行则输出,否则启动
    systemctl is-active sshd &>/dev/null
    if [ $? -ne 0 ];then
      echo "sshd is not running."
      echo -n "Starting sshd ... ..."
      systemctl start sshd && echo DONE
    else
      echo "sshd is running"
    fi
  2. 通过传参控制 sshd 服务

    bash 复制代码
    if [ "$1" == "start" ];then
      systemctl start sshd
    elif [ "$1" == "stop" ];then
      systemctl stop sshd
    elif [ "$1" == "status" ];then
      systemctl status sshd
    elif [ "$1" == "restart" ];then
      systemctl restart sshd
    else
      echo "Usage: $0 start|stop|status|restart "
    fi
  3. 三个整数从大到小排序

    bash 复制代码

a=10; b=20; c=30

if [ $a -lt b ] ; t h e n n u m = b ];then num= b];thennum=b;b= a ; a = a;a= a;a=num;fi

if [ $b -lt c ] ; t h e n n u m = c ];then num= c];thennum=c;c= b ; b = b;b= b;b=num;fi

if [ $a -lt b ] ; t h e n n u m = b ];then num= b];thennum=b;b= a ; a = a;a= a;a=num;fi

echo " a > a> a>b>$c"

  1. 监控系统可用内存

    bash 复制代码
    FreeMem=$(free -m | awk 'NR==2 { print $4}')
    if [ $FreeMem -lt 100 ];then
     echo  "Mem is lower than 100M" | mail -s "FreeMem is ${FreeMem}M" root@localhost
    fi

配合 crontab 定时任务,每 3 分钟执行一次。

Shell 函数

一、 Shell 函数介绍

  • 与 alias 对比
    1. 功能复杂度
      • alias:仅能替换单条命令(含固定参数),无逻辑能力。
      • 函数:支持多命令、条件判断、循环等复杂逻辑。
    2. 参数处理
      • alias:不支持动态参数,易出问题。
      • 函数:原生支持 $1 等参数,灵活可靠。
    3. 适用场景
      • alias:简化高频单条命令(如 ll='ls -l')。
      • 函数:实现多步骤、带逻辑的任务(如文件备份 + 检查)。
  • 定义:将多次调用的相同代码组合为函数体并命名,调用时只需使用函数名

二、 Shell 函数的语法

  • 标准写法:

    bash 复制代码
    function 函数名 () {
      指令...
      return n
    }
  • 简化写法 1(不写 ()):

    bash 复制代码
    function 函数名 {
      指令...
      return n
    }
  • 简化写法 2(不写 function):

    bash 复制代码
    函数名 () {
      指令...
      return n
    }

三、Shell 函数的执行

1. 不带参数的函数

  • 执行方式:直接输入函数名(不带小括号)
  • 重要说明:
    • 执行时不携带 function 关键字和函数后的小括号
    • 函数必须在执行前定义或加载
    • 程序执行顺序:系统别名 -> 函数 -> 系统命令 -> 可执行文件
    • 函数与调用它的脚本共用变量,也可设定局部变量和特殊位置参数
    • return 用于退出函数,exit 用于退出脚本文件
    • return 返回值给当前程序,exit 返回值给当前 Shell
    • 外部函数文件需用 source. 加载
    • 函数内用 local 定义局部变量,离开函数后失效

2. 带参数的函数

  • 执行方式:函数名 参数1 参数2
  • 参数说明:
    • 可使用位置参数($1$2...、$#$*$?$@
    • 父脚本参数会被函数参数临时掩盖
    • $0 仍为父脚本名称
    • 函数执行完成后,原脚本参数恢复
    • 函数参数变量在函数体内定义

四、Shell 函数的基础实践

  • 示例 1 :简单 hello 函数(体现函数必须先定义后调用)
  • 示例 2 :调用外部函数(通过 source 加载外部函数文件)
  • 示例 3 :带参数的 print 函数(根据不同参数输出不同颜色文本)
  • 示例 4 :验证脚本参数与函数参数的关系(脚本参数需显式传递给函数,$0 为脚本名)

五、 企业级实践:URL 检测脚本

  • 包含函数:
    • usage:显示使用方法
    • check_url:通过 wget 检测 URL 可访问性
    • main:主函数,处理参数并调用检测函数
  • 执行逻辑:接收 URL 参数,调用检测函数输出结果

六、 函数的递归调用

  • 示例 1:计算 1 到 n 的和(递归累加)

  • 示例 2:计算 n 的阶乘(递归累乘)

  • 示例 3:fork 炸弹

    • 代码::(){ :|:& };:

      解析如下:

      1. : () { ... }:定义一个名为 : 的函数

      2. : | : &:函数内部递归调用自身两次:

        • 第一次调用 : 作为管道左半部分
        • 第二次调用 : 作为管道右半部分
    • & 表示将进程放入后台运行

  1. ; ::定义完成后立即调用这个函数,启动炸弹

工作过程:

  1. 初始调用 : 函数,创建 1 个进程
    2. 这个进程会同时创建 2 个新进程(左管道和右管道各一个)
  2. 每个新进程又会创建 2 个进程,以此类推...
    4. 进程数量以 2ⁿ 的指数级增长(1→2→4→8→16...),瞬间耗尽系统允许的最大进程数

危害:

  • 系统资源被耗尽,正常程序无法启动新进程

  • CPU 占用率飙升至 100%,系统响应极其缓慢

-可能导致系统死机,需要强制重启才能恢复

-解决办法:限制用户进程数量(如 ulimit -u 100

相关推荐
天才奇男子3 小时前
HAProxy高级功能全解析
linux·运维·服务器·微服务·云原生
小李独爱秋4 小时前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
学嵌入式的小杨同学4 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
ASKED_20194 小时前
Langchain学习笔记一 -基础模块以及架构概览
笔记·学习·langchain
酥暮沐4 小时前
iscsi部署网络存储
linux·网络·存储·iscsi
❀͜͡傀儡师5 小时前
centos 7部署dns服务器
linux·服务器·centos·dns
Lois_Luo5 小时前
Obsidian + Picgo + Aliyun OSS 实现笔记图片自动上传图床
笔记·oss·图床
Dying.Light5 小时前
Linux部署问题
linux·运维·服务器
S19015 小时前
Linux的常用指令
linux·运维·服务器
萤丰信息5 小时前
AI 筑基・生态共荣:智慧园区的价值重构与未来新途
大数据·运维·人工智能·科技·智慧城市·智慧园区