第18章:Shell 脚本编程基础

恭喜你已经掌握了 Linux 系统管理的核心技能。现在,是时候将这些命令"串联"起来,通过 Shell 脚本 实现自动化,大幅提升运维效率。在 openEuler 环境中,Bash 脚本是自动化任务、系统维护、部署流程的基石。本章将带你从零开始,写出第一个"会思考"的脚本。

🌟 本章目标

  • 理解 Shell 脚本的作用与执行方式
  • 掌握脚本结构:#!/bin/bash 与权限设置
  • 学会定义和使用变量(普通变量、环境变量、位置参数)
  • 使用 if 语句进行条件判断(文件、字符串、数字)
  • 使用 forwhile 循环批量处理任务
  • 定义和调用函数,提高代码复用性
  • 实战:编写一个系统资源监控与告警脚本

18.1 什么是 Shell 脚本?

Shell 脚本 是一个包含一系列 Shell 命令的文本文件,可以像程序一样被批量执行

✅ 为什么需要脚本?

  • 自动化重复任务:备份、日志清理、服务检查
  • 减少人为错误
  • 提高效率:一键完成多步操作
  • 可复用、可分享:团队协作的"运维配方"

💬 类比:

  • 手动执行命令 = 一步步做菜
  • Shell 脚本 = 写下菜谱,让别人或机器照着做

18.2 第一个 Shell 脚本

步骤1:创建脚本文件

bash 复制代码
vim hello.sh

步骤2:编写内容

bash 复制代码
#!/bin/bash
# 这是我的第一个 Shell 脚本
echo "Hello, openEuler!"
echo "当前时间:$(date)"
echo "当前用户:$(whoami)"

步骤3:添加可执行权限

bash 复制代码
chmod +x hello.sh

步骤4:执行脚本

bash 复制代码
./hello.sh

输出:

复制代码
Hello, openEuler!
当前时间:2024年04月06日 星期六 10:30:00
当前用户:zhangsan

✅ 脚本成功运行!


18.3 脚本结构详解

✅ 1. Shebang(#!/bin/bash

  • 必须位于第一行
  • 告诉系统用哪个解释器运行脚本
  • 常见:
    • #!/bin/bash:Bash
    • #!/bin/sh:标准 Shell
    • #!/usr/bin/env python3:Python

⚠️ 如果没有 Shebang,需显式调用解释器:

bash 复制代码
bash hello.sh

✅ 2. 注释(#

  • # 后的内容为注释,不会被执行
  • 用于说明脚本功能、作者、修改记录
bash 复制代码
# Author: zhangsan
# Date: 2024-04-06
# Description: 系统信息收集脚本

✅ 3. 执行方式

方式 命令 特点
直接执行 ./script.sh x 权限
调用解释器 bash script.sh 无需 x 权限
源码执行 source script.sh. script.sh 在当前 Shell 环境执行,变量会保留

18.4 变量(Variables)

变量用于存储数据,是脚本的"记忆"。

🔧 定义变量

bash 复制代码
name="zhangsan"
age=25
pi=3.14
  • 变量名区分大小写
  • 不能有空格(name = "zhangsan" 错误!)
  • 可用 export 变为环境变量

🔍 使用变量

bash 复制代码
echo "姓名:$name"
echo "年龄:${age}岁"   # ${} 更安全,避免歧义

🧩 特殊变量

变量 说明
$0 脚本名
$1, $2, ... 第1、2个参数
$# 参数个数
$@ 所有参数(保留空格)
$* 所有参数(合并为一个字符串)
$$ 当前脚本的 PID
$? 上一条命令的退出状态(0=成功)

实战:参数传递脚本

bash 复制代码
vim greet.sh
bash 复制代码
#!/bin/bash
echo "脚本名:$0"
echo "参数个数:$#"
echo "第一个参数:$1"
echo "所有参数:$@"

执行:

bash 复制代码
chmod +x greet.sh
./greet.sh 张三 李四 王五

输出:

复制代码
脚本名:./greet.sh
参数个数:3
第一个参数:张三
所有参数:张三 李四 王五

18.5 条件判断:if 语句

if 让脚本具备"判断能力"。

基本语法

bash 复制代码
if 条件; then
    命令1
    命令2
elif 条件; then
    命令3
else
    命令4
fi

✅ 使用 test[ ]

bash 复制代码
if [ -f "/etc/passwd" ]; then
    echo "passwd 文件存在"
fi

⚠️ [ 后、] 前必须有空格!


🔍 常见判断条件

类型 条件 说明
文件 [ -f file ] 是普通文件
[ -d dir ] 是目录
[ -r file ] 可读
[ -w file ] 可写
[ -x file ] 可执行
字符串 [ -z str ] 字符串为空
[ -n str ] 字符串非空
[ "str1" = "str2" ] 相等
[ "str1" != "str2" ] 不等
数字 [ 1 -eq 1 ] 等于
[ 2 -gt 1 ] 大于
[ 1 -lt 2 ] 小于
[ 1 -ge 1 ] 大于等于
[ 1 -le 2 ] 小于等于

实战:检查服务状态

bash 复制代码
#!/bin/bash
service=$1

if systemctl is-active --quiet $service; then
    echo "$service 正在运行"
else
    echo "$service 未运行"
fi

保存为 check_service.sh,执行:

bash 复制代码
./check_service.sh sshd

18.6 循环:forwhile

🔁 for 循环(已知范围)

bash 复制代码
for i in 1 2 3 4 5; do
    echo "数字:$i"
done
遍历文件
bash 复制代码
for file in /tmp/*.txt; do
    if [ -f "$file" ]; then
        echo "处理文件:$file"
    fi
done
C 风格 for
bash 复制代码
for ((i=1; i<=5; i++)); do
    echo "计数:$i"
done

🔄 while 循环(条件满足时继续)

bash 复制代码
count=1
while [ $count -le 5 ]; do
    echo "当前:$count"
    count=$((count + 1))
done
实用:监控 CPU 使用率
bash 复制代码
while true; do
    cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
    echo "CPU 使用率:$cpu%"
    sleep 2
done

18.7 函数(Functions)

函数用于封装可复用的代码块。

定义函数

bash 复制代码
function backup() {
    echo "开始备份..."
    tar -czf /backup/etc-$(date +%F).tar.gz /etc
    echo "备份完成"
}

# 或省略 function 关键字
log() {
    echo "[$(date)] $1" >> /var/log/myscript.log
}

调用函数

bash 复制代码
backup
log "系统检查完成"

18.8 实战:系统资源监控脚本

需求

  • 检查磁盘、内存使用率
  • 超过 80% 时输出警告
  • 记录日志

脚本:monitor.sh

bash 复制代码
#!/bin/bash
# 系统监控脚本

LOG_FILE="/var/log/monitor.log"
THRESHOLD=80

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

check_disk() {
    usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
    if [ $usage -gt $THRESHOLD ]; then
        log "WARNING: 根分区使用率 $usage%"
        echo "警告:磁盘使用率过高!"
    else
        log "OK: 磁盘使用率 $usage%"
    fi
}

check_memory() {
    usage=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100)}')
    if [ $usage -gt $THRESHOLD ]; then
        log "WARNING: 内存使用率 $usage%"
        echo "警告:内存使用率过高!"
    else
        log "OK: 内存使用率 $usage%"
    fi
}

# 主程序
log "=== 系统监控开始 ==="
check_disk
check_memory
log "=== 系统监控结束 ==="

使用

bash 复制代码
sudo chmod +x monitor.sh
sudo ./monitor.sh
tail /var/log/monitor.log

✅ 一个实用的自动化监控工具诞生!


✅ 本章小结

结构 语法 说明
Shebang #!/bin/bash 指定解释器
变量 name="value" 存储数据
条件 if [ 条件 ]; then ... fi 判断执行
循环 for, while 重复执行
函数 function name() { ... } 代码复用
特殊变量 $1, $?, $@ 脚本元信息

📝 课后练习

  1. 编写一个脚本 greet_user.sh,接收用户名作为参数,输出"Hello, 用户名"。
  2. 编写一个 for 循环,创建 10 个文件:file1.txt ~ file10.txt
  3. 编写一个 while 循环,持续检查 nginx 服务状态,每 5 秒一次。
  4. 创建一个函数 create_user,接收用户名参数,自动创建用户并设置密码。
  5. 修改监控脚本,增加对 CPU 使用率的检查。
  6. (挑战)编写一个备份脚本,只在工作日(周一到周五)执行。

🔜 下一章预告:第19章《openEuler 中的容器支持(Docker 与 iSulad)》

我们将学习:

  • 什么是容器?Docker 与 iSulad 的区别
  • openEuler 默认容器引擎:iSulad 架构与优势
  • 安装与配置 iSulad
  • 镜像管理:pull、tag、push
  • 容器生命周期:run、start、stop、rm
  • 实战:在 openEuler 上运行 Nginx 容器

准备好进入云原生时代了吗?

相关推荐
江湖有缘4 小时前
基于华为openEuler搭建Coolmonitor监控服务
linux·华为云·openeuler
peng_YuJun15 天前
openEuler 虚拟机从零到一:完整部署指南
linux·运维·服务器·vmware·openeuler
EverydayJoy^v^15 天前
Linux Shell 高级编程(3)——awk
linux·运维·shell
dingdingfish18 天前
Bash学习 - 第10章:Installing Bash
bash·make·shell·install·configure·5.3
dingdingfish19 天前
Bash学习 - 第8章:Command Line Editing,第6-8节:Programmable Completion
bash·shell·completion·complete·compgen·compopt
白云偷星子20 天前
RHCSA笔记3
shell
dingdingfish20 天前
Bash学习 - 第7章:Job Control
bash·shell·wait·job
dingdingfish20 天前
Bash学习 - 第8章:Command Line Editing,第1-2节:Intro & Readline Interaction
bash·shell·readline
Re_Virtual21 天前
OpenEuler 20.03构建zabbix7.0 rpm包
linux·zabbix·openeuler