个人用云计算学习笔记 --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

相关推荐
盐焗西兰花2 小时前
鸿蒙学习实战之路-Core Vision Kit人脸检测实现指南
android·学习·harmonyos
喜欢吃燃面2 小时前
算法竞赛中的数据结构:图
开发语言·数据结构·c++·学习·算法
iconball2 小时前
个人用云计算学习笔记 --26 OpenStack 核心服务
运维·笔记·学习·云计算·openstack
polarislove02142 小时前
9.1[ 定时器 ] 时基单元-嵌入式铁头山羊STM32笔记
笔记·stm32·嵌入式硬件
咕噜企业分发小米2 小时前
阿里云Milvus如何评估向量检索效果?
阿里云·云计算·milvus
HyperAI超神经2 小时前
【vLLM 学习】Profiling
人工智能·深度学习·学习·cpu·gpu·编程语言·vllm
三品吉他手会点灯2 小时前
STM32F103 学习笔记-21-串口通信(第1节)-串口通信协议简介
笔记·stm32·单片机·嵌入式硬件·学习
舰长1152 小时前
ubuntu挂载盘报错
linux·运维·ubuntu
风之子npu2 小时前
AXI 原子访问
arm开发·笔记·学习