Skip to main content
今日目标:完成 DevOps 最基础的两大基石学习——Shell 脚本的”Hello World” 与 MySQL 数据库的建表规范。今天不只是写代码,而是要彻底理解 “Shell 为什么是运维的核心工具”“如何正确编写 Shell 脚本” 以及 “如何设计一个合理的数据库表结构”

学习内容 (30 mins)

在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。
什么是 Shell?Shell 是用户与操作系统内核之间的”翻译官”。当你输入 ls 时,Shell 会:
  1. 解析你的命令
  2. 调用系统调用(system call)
  3. 将结果返回给你
为什么运维离不开 Shell?
  • 批量操作:一次命令处理成百上千台服务器
  • 自动化:编写脚本实现重复任务自动化
  • 系统管理:直接操作文件系统、进程、网络
  • 快速调试:通过命令行快速定位问题
基础语法详解
  • Shebang (#!/bin/bash)
    • 作用:告诉系统用哪个解释器执行脚本
    • 位置:必须是文件第一行
    • 原理:#! 是 magic number,系统读取后调用对应解释器
    • 常见值:#!/bin/bash(Bash)、#!/bin/sh(POSIX Shell)
  • 变量赋值
    • 语法:name="value"(等号两边不能有空格!)
    • 为什么不能有空格:Shell 会把 name = "value" 当作命令执行
    • 引用变量:$name${name}
    • 只读变量:readonly name="value"
  • 打印输出
    • echo "text":输出文本
    • echo $variable:输出变量值
    • 引号区别:
      • 单引号 'text':不解析变量,原样输出
      • 双引号 "text":解析变量,替换为变量值
      • 无引号:会被 Shell 解析,空格会被当作分隔符
  • 执行权限
    • chmod +x script.sh:添加执行权限
    • 为什么需要:系统需要知道这个文件是可执行的
    • 运行方式:
      • 有执行权限:./script.sh
      • 无执行权限:bash script.sh(显式指定解释器)
什么是数据库表?表是数据的结构化存储方式,类似于 Excel 表格。每一行是一条记录,每一列是一个字段。为什么需要设计表结构?
  • 数据完整性:确保数据的正确性和一致性
  • 查询性能:合理的结构能提高查询速度
  • 扩展性:好的设计便于后续扩展
  • 维护性:清晰的表结构便于维护
字段类型选择依据
  • 整数类型
    • TINYINT:-128 到 127(或 0 到 255,UNSIGNED)
    • INT:-2,147,483,648 到 2,147,483,647
    • INT UNSIGNED:0 到 4,294,967,295(范围更大,只能为正数)
    • BIGINT:更大的整数范围
    • 选择依据:根据数据范围选择,ID 通常用 INT UNSIGNED
  • 字符串类型
    • CHAR(n):固定长度,查询稍快但浪费空间
    • VARCHAR(n):可变长度,按需分配空间
    • 选择依据:长度固定用 CHAR,长度不固定用 VARCHAR
  • 日期时间类型
    • DATETIME:范围 1000-9999 年,不受时区影响
    • TIMESTAMP:范围 1970-2038 年,自动转换时区
    • 选择依据:创建时间用 DATETIME 更稳妥
数据完整性约束
  • 主键 (PRIMARY KEY):唯一标识每条记录,不能为空
  • 非空 (NOT NULL):字段必须提供值
  • 默认值 (DEFAULT):如果不提供值,使用默认值
  • 自增 (AUTO_INCREMENT):自动递增,常用于主键

代码任务 (90 mins)

1

环境准备

在开始之前,确保你的环境已准备好:
  • Shell 环境:macOS/Linux 自带,Windows 需要安装 Git Bash 或 WSL
  • 文本编辑器:需要学会使用命令行编辑器(vi/vim 或 nano)
  • MySQL 环境:使用 Docker 快速启动(推荐)
nano 是最简单的命令行编辑器,适合初学者。基本操作
  • 打开/创建文件nano filename.sh
  • 保存文件Ctrl + O(Write Out),然后按 Enter 确认
  • 退出编辑器Ctrl + X
  • 查找文本Ctrl + W
  • 复制行Alt + 6(标记开始),移动光标,Alt + 6(复制)
  • 粘贴Ctrl + U
提示:nano 底部会显示常用快捷键,^ 表示 CtrlM- 表示 Alt示例
# 创建并编辑文件
nano 01_hello.sh

# 在编辑器中输入代码,然后:
# 1. 按 Ctrl + O 保存
# 2. 按 Enter 确认文件名
# 3. 按 Ctrl + X 退出
vi/vim 是功能强大的编辑器,但学习曲线较陡。基本操作模式
  • 命令模式(默认):按 Esc 进入,用于执行命令
  • 插入模式:按 i 进入,用于输入文本
  • 退出:在命令模式下输入 :q(退出)或 :wq(保存并退出)
常用命令(命令模式下):
  • i:进入插入模式(在光标前插入)
  • a:进入插入模式(在光标后插入)
  • :w:保存文件
  • :q:退出(如果文件未修改)
  • :q!:强制退出(不保存)
  • :wq:保存并退出
  • dd:删除当前行
  • yy:复制当前行
  • p:粘贴
快速上手流程
# 1. 打开文件
vi 01_hello.sh

# 2. 按 i 进入插入模式(底部显示 -- INSERT --)

# 3. 输入代码

# 4. 按 Esc 退出插入模式

# 5. 输入 :wq 保存并退出
新手提示:如果不小心进入 vi,不知道如何退出,按 Esc 然后输入 :q! 强制退出。
# 检查当前 Shell 版本
echo $SHELL
bash --version
编辑器选择建议
  • 新手推荐使用 nano,操作简单直观
  • 如果熟悉后想提升效率,可以学习 vim
  • Windows 用户也可以使用 VS Code 等图形编辑器,但需要了解如何在终端中创建和编辑文件
如果 Docker 未安装,可以访问 Docker 官网 下载安装。或者使用本地 MySQL,但需要手动配置。
2

Shell 脚本实战

编写一个脚本 01_hello.sh,实现以下功能:任务分解
  1. 定义变量存储项目名称
  2. 提示用户输入日期
  3. 读取用户输入
  4. 格式化输出欢迎信息
#!/bin/bash
# Shebang:指定使用 bash 解释器
# 如果没有这行,系统不知道用什么解释器执行脚本
# 注意:必须是文件的第一行,且前面不能有任何空格

# 定义变量:项目名称
# 注意:等号两边不能有空格!
# 如果写成 project_name = "InsightfulOps",Shell 会报错
project_name="InsightfulOps"

# 提示用户输入
# echo 命令用于输出文本到终端
# 使用双引号可以包含空格,且会解析变量(虽然这里没有变量)
echo "Please enter today's date (YYYY-MM-DD):"

# 读取用户输入
# read 命令会等待用户输入,直到按回车键
# 输入的内容会存储在 current_date 变量中
# 如果用户直接按回车,变量值为空字符串
read current_date

# 输出格式化信息
# 使用 $variable 引用变量值
# 双引号内的 $variable 会被替换为变量值
# 如果使用单引号 '$variable',会原样输出字符串 "$variable"
echo "--------------------------------"
echo "Welcome to $project_name"
echo "System Check Date: $current_date"
echo "--------------------------------"
常见错误
  • project_name = "InsightfulOps" - 等号两边有空格,Shell 会报错
  • echo Welcome to $project_name - 缺少引号,空格会被当作参数分隔符
  • echo 'Welcome to $project_name' - 单引号不解析变量,会原样输出
  • project_name="InsightfulOps" - 正确写法
  • echo "Welcome to $project_name" - 正确写法
验证步骤
  1. 保存文件后,添加执行权限:
    chmod +x 01_hello.sh
    
  2. 运行脚本:
    ./01_hello.sh
    
  3. 输入日期(如:2024-01-15),查看输出是否正确
  4. 测试边界情况:
    • 直接按回车(不输入任何内容)
    • 输入错误格式的日期
3

SQL 建表实战

启动 MySQL 容器并创建用户表:设计思路在创建表之前,我们需要思考:
  1. 这个表存储什么数据?(用户信息)
  2. 每个字段应该用什么类型?(根据数据特点选择)
  3. 哪些字段是必需的?(用户名必须,邮箱可选)
  4. 如何保证数据完整性?(主键、非空约束、默认值)
# 连接到 MySQL 容器
# -it: 交互式终端
# mysql-learn: 容器名称
# mysql -uroot -proot: MySQL 客户端命令(用户名:root,密码:root)
docker exec -it mysql-learn mysql -uroot -proot
字段类型选择详解
  • INT:范围 -2,147,483,648 到 2,147,483,647
  • INT UNSIGNED:范围 0 到 4,294,967,295
  • 选择依据:用户ID 不会为负数,用 UNSIGNED 可以存储更多数据
  • 实际应用:ID、计数器等只可能是正数的字段,都用 UNSIGNED
  • CHAR(50):固定长度 50 个字符,查询稍快但浪费空间
  • VARCHAR(50):可变长度,最多 50 个字符,按需分配空间
  • 选择依据
    • 长度固定(如:手机号 11 位)→ 用 CHAR
    • 长度不固定(如:用户名)→ 用 VARCHAR
  • 实际应用:用户名、邮箱、地址等长度不固定的字段,都用 VARCHAR
  • DATETIME:范围 1000-9999 年,不受时区影响
  • TIMESTAMP:范围 1970-2038 年,自动转换时区
  • 选择依据
    • 创建时间、更新时间 → 用 DATETIME(更稳妥)
    • 需要时区转换的场景 → 用 TIMESTAMP
  • 实际应用:记录创建时间、更新时间等,通常用 DATETIME
验证步骤
  1. 查看表结构:
    DESCRIBE users;
    -- 或者
    SHOW CREATE TABLE users;
    
  2. 插入测试数据:
    -- 测试 1:只提供必需字段(username)
    INSERT INTO users (username) VALUES ('alice');
    
    -- 测试 2:提供所有字段
    INSERT INTO users (username, email, status) VALUES ('bob', 'bob@example.com', 1);
    
    -- 测试 3:使用默认值
    INSERT INTO users (username, status) VALUES ('charlie', DEFAULT);
    
  3. 查询验证:
    SELECT * FROM users;
    
  4. 检查默认值是否生效:
    -- 查看 created_at 是否自动填充
    SELECT id, username, created_at FROM users;
    
常见错误
  • Table 'infra_db.users' doesn't exist - 表不存在,检查是否执行了 CREATE TABLE
  • Unknown database 'infra_db' - 数据库不存在,先执行 CREATE DATABASE
  • Column 'username' cannot be null - 违反了 NOT NULL 约束
  • Duplicate entry '1' for key 'PRIMARY' - 主键重复,检查 AUTO_INCREMENT 是否正常工作

拓展任务 (30 mins)

Shell 挑战

任务:尝试使用 export 设置环境变量,并在脚本中读取。提示
  • 使用 export VARIABLE_NAME="value" 设置环境变量
  • 在脚本中使用 $VARIABLE_NAME 读取
  • 思考:环境变量和普通变量有什么区别?

SQL 挑战

任务:尝试使用 ALTER TABLE 命令给 users 表增加一个 phone 字段。提示
  • 使用 ALTER TABLE users ADD COLUMN phone VARCHAR(20) DEFAULT '' COMMENT '手机号';
  • 思考:为什么手机号用 VARCHAR(20) 而不是 CHAR(11)

今日产出物

  • day01/01_hello.sh - Shell 脚本文件
  • day01/01_create_user.sql - SQL 建表脚本

参考代码

查看参考代码

在 GitHub 查看完整的示例代码

在线运行

使用在线编辑器测试代码

实际应用场景

Shell 脚本在运维中的应用

  • 批量部署:编写脚本在多个服务器上部署应用
  • 日志分析:使用 Shell 脚本分析日志文件,提取关键信息
  • 备份自动化:定时执行备份脚本,确保数据安全
  • 监控脚本:检查服务状态,发现问题时发送告警
  • 配置管理:批量修改服务器配置,提高效率

SQL 表设计的最佳实践

  • 字段命名:使用有意义的名称,添加注释便于理解
  • 数据类型:根据实际需求选择合适类型,避免浪费空间
  • 默认值:为常用字段设置合理的默认值,简化插入操作
  • 约束设计:使用主键、非空等约束保证数据完整性
  • 索引设计:为经常查询的字段添加索引(后续课程会讲)
与 Day 02 的关联:今天学习的 Shell 变量和 SQL 表结构,明天会学习如何使用 Shell 流程控制操作数据库,以及如何编写 SQL 的增删改查语句。打好今天的基础,明天的学习会更轻松。

回到目录

查看完整进度

下一天: 流程控制

Day 02 | Shell 流程控制与 SQL CRUD