diff --git a/COURSE.md b/COURSE.md index 3de24d1..7d5b1bf 100644 --- a/COURSE.md +++ b/COURSE.md @@ -1,147 +1,274 @@ -# 📚 Linux 命令学习课程体系(入门 → 高手) +# Linux 学习平台课程设计(重构版) -> 学习路径:**理论 → 演示 → 沙盒练习 → 测试 → 徽章认证** +## 设计原则 + +这次课程重构,目标不再是“闯关刷题”,而是建立一套**适合系统学习 Linux 的知识结构**。 + +核心原则: +- **先理解,再操作** +- **先场景,再命令** +- **先最小可用,再扩展参数** +- **练习服务于理解,不反客为主** +- **每个模块都能迁移到真实工作场景** --- -## 🌱 Level 1:入门(新手村) +## 新课程结构 -### 🎯 目标:熟悉终端、查看文件、当前目录、简单操作 +课程分为 6 大模块,不再按简单等级推进,而按学习逻辑推进。 -| 课时 | 主题 | 学习内容 | 沙盒练习目标 | 测试场景 | -|------|------|---------|-------------|---------| -| 1 | `pwd` - 我在哪? | 当前工作目录 | `pwd` 返回 `/sandbox` | 问:你现在的位置是? | -| 2 | `ls` - 看看周围 | 列出目录内容 | `ls` 显示 `users projects logs` | 找出 `/sandbox` 下有几个子目录? | -| 3 | `cd` - 移动位置 | 切换目录 | `cd users` → 进入用户区 | 从 `/sandbox` 进到 `/projects` | -| 4 | `echo` - 说话 | 打印文本 | `echo "Hello Linux"` | 打印你的名字 | -| 5 | `cat` - 看内容 | 查看文件内容 | `cat users/alice.txt` | 读出 alice.txt 的内容 | +### 模块 1:建立 Linux 基本认知 +目标:先搞清楚“我在哪、我看到什么、我怎么移动”。 -**徽章**:` beginner_1 ← 目录旅行者` +包含内容: +- 什么是终端 / Shell +- 什么是当前目录 +- 什么是绝对路径 / 相对路径 +- `pwd` +- `ls` +- `cd` +- `echo` +- `cat` + +输出能力: +- 能在目录中定位自己 +- 能读懂基础路径 +- 能查看基础文件内容 --- -## 🚀 Level 2:文件操作(手艺人) +### 模块 2:文件与目录操作 +目标:建立文件系统操作能力。 -### 🎯 目标:创建、复制、移动、删除(安全版)、查看 +包含内容: +- 文件与目录的区别 +- 创建 / 复制 / 移动 / 删除 +- `mkdir` +- `touch` +- `cp` +- `mv` +- `rm` +- `stat` -| 课时 | 主题 | 学习内容 | 沙盒练习目标 | 测试场景 | -|------|------|---------|-------------|---------| -| 6 | `touch` - 创建空文件 | 创建新文件 | `touch mynote.txt` | 创建一个名为 `test.txt` 的文件 | -| 7 | `cp` - 复制 | 复制文件/目录 | `cp users/alice.txt backup/` | 复制 `project/backend/app.py` 到 `archive/` | -| 8 | `mv` - 移动/重命名 | 移动或重命名 | `mv old.txt new.txt` | 把 `logs/access.log` 重命名为 `old_access.log` | -| 9 | `mkdir` - 创建目录 | 创建级联目录 | `mkdir -p a/b/c` | 创建 `myproject/src/main` | -| 10 | `head/tail` - 看头尾 | 查看文件前/后几行 | `tail -n 5 logs/access.log` | 查看 `app.py` 最后 3 行 | - -**徽章**:` beginner_2 ← 文件管理员` +输出能力: +- 能完成日常文件整理 +- 能理解“创建、备份、迁移、清理”四种动作 --- -## 🔍 Level 3:搜索高手(情报员) +### 模块 3:阅读与筛选信息 +目标:学会从文件和日志中找信息。 -### 🎯 目标:快速定位、查找、筛选内容 +包含内容: +- `head` +- `tail` +- `grep` +- `wc` +- `sort` +- `find` +- 日志查看思路 +- 搜索与过滤思路 -| 课时 | 主题 | 学习内容 | 沙盒练习目标 | 测试场景 | -|------|------|---------|-------------|---------| -| 11 | `grep` - 搜索关键词 | 正则匹配文本 | `grep "Linux" *.txt` | 在 `users/` 下找包含 "Alice" 的文件 | -| 12 | `find` - 按条件找文件 | 时间/大小/类型 | `find /logs -type f -name "*.log"` | 找出所有 `.py` 文件 | -| 13 | `du` - 查看占用 | 磁盘使用情况 | `du -sh *` | 评估 `/projects` 每个子目录大小 | -| 14 | `sort` - 排序 | 排序输出 | `ls \| sort` | 按文件大小升序排列 `/logs` | -| 15 | `wc` - 统计 | 行/词/字节数 | `wc -l app.py` | `find /projects -type f \| wc -l` 有几个文件? | - -**徽章**:` intermediate_1 ← 情报专家` +输出能力: +- 能读日志 +- 能查关键词 +- 能定位配置文件 +- 能做基础统计 --- -## 🛠️ Level 4:文本编辑(文字工作者) +### 模块 4:系统状态与资源认知 +目标:知道系统现在在干什么。 -### 🎯 目标:预览/编辑文本(只读模式) +包含内容: +- 进程是什么 +- 磁盘 / 内存 / 挂载点是什么 +- `ps` +- `top` +- `df` +- `du` +- `free` +- `mount` +- `history` -| 课时 | 主题 | 学习内容 | 沙盒练习目标 | 测试场景 | -|------|------|---------|-------------|---------| -| 16 | `nano/vim` 基础 | 只读模式(演示) | `view project/backend/app.py` | 显示文件内容(用 `cat` 替代 vim) | -| 17 | `>`/`>>` 重定向 | 输出到文件 | `echo "test" > test.txt` | 把 `grep "def" app.py` 结果保存到 `methods.txt` | -| 18 | `|` 管道 | 连接命令 | `cat users/* \| grep Alice` | 找出所有包含 "Linux" 的内容 | - -**徽章**:` intermediate_2 ← 文字工匠` +输出能力: +- 能做基础排查 +- 能看懂资源占用 +- 能理解系统运行状态 --- -## 🔐 Level 5:高级技巧(小黑客) +### 模块 5:网络与服务基础 +目标:建立 Linux 运维里的连接意识。 -### 🎯 目标:权限、查找大文件、进程、自动化 +包含内容: +- 网络接口是什么 +- 端口与监听是什么 +- `ifconfig` / `ip addr` +- `ping` +- `ss` / `netstat` +- `curl` +- `wget` +- `which` / `whereis` -| 课时 | 主题 | 学习内容 | 沙盒练习目标 | 测试场景 | -|------|------|---------|-------------|---------| -| 19 | `find -size` - 找大文件 | 按大小查找 | `find / -size +100M` | 找出 `/logs` 下大于 10KB 的文件 | -| 20 | `chmod` 原理 | 权限概念(只读) | 解释 `rwxr-xr-x` | 问:`644` 是什么权限? | -| 21 | `ps`/`top` 基础 | 进程概念 | `ps aux \| grep python` | 找出所有 `java` 进程 | -| 22 | `history` - 命令历史 | 查看历史 | `history \| tail -n 10` | 看最近 3 条执行的命令 | -| 23 | `man` - 查手册 | 查帮助 | `man ls`(模拟) | 问:`ls -a` 是什么作用? | - -**徽章**:` advanced_1 ← 系统法师` +输出能力: +- 能判断服务通不通 +- 能理解“域名、端口、监听、请求”的基本关系 --- -## 🎓 Level 6:实战项目(通关玩家) +### 模块 6:权限、习惯与实际运维思维 +目标:从“会敲命令”过渡到“知道为什么这么做”。 -### 🎯 综合应用:解决真实场景 +包含内容: +- 权限模型基础 +- `chmod` +- `chown` +- `chgrp` +- `alias` +- `export` +- `tar` +- `crontab` +- 常见运维习惯 +- 风险命令认知 -| 场景 | 任务 | 所需命令 | 难度 | -|------|------|----------|------| -| 📁 备份项目 | 将 `/projects` 下所有 `.py` 文件备份到 `/backup` | `find`, `cp`, `mkdir` | ⚔️⚔️⚔️ | -| 🔎 搜索日志 | 找出所有包含 `"error"` 的日志行 | `grep`, `find`, `cat` | ⚔️⚔️⚔️⚔️ | -| 📏 磁盘分析 | 写出 `/projects` 中最大的 3 个文件 | `du`, `sort`, `tail` | ⚔️⚔️ | -| 📝 生成报告 | 把所有 `.py` 文件的行数统计保存到 `stats.txt` | `wc`, `find`, `>` | ⚔️⚔️⚔️⚔️⚔️ | -| 🔐 权限检查 | 找出所有`.sh` 脚本并检查权限是否为 `755` | `find`, `stat`, `grep` | ⚔️⚔️⚔️⚔️⚔️ | +输出能力: +- 能理解权限修改的意义 +- 能建立基础运维安全感 +- 能开始形成 Linux 使用习惯 --- -## 🏆 完整通关徽章体系 +## 每个课时的新结构 -```bash - beginner_1 ← 目录旅行者 (pwd/ls/cd) - beginner_2 ← 文件管理员 (touch/cp/mv/mkdir) - intermediate_1 ← 情报专家 (grep/find/du/sort/wc) - intermediate_2 ← 文字工匠 (cat/echo/pipe/redirection) - advanced_1 ← 系统法师 (find-size/chmod/ps/history/man) - expert_1 ← 实战大师 (综合项目通关) - legend ← Linux 大师 (所有课程 + 心得分享) -``` +每一课统一用下面 6 段结构: + +### 1. 学什么 +一句话说清这个命令/主题在解决什么问题。 + +### 2. 为什么重要 +它在真实 Linux 使用、开发、运维里有什么价值。 + +### 3. 核心知识点 +包括: +- 命令作用 +- 常见参数 +- 常见组合 +- 输出怎么看 +- 容易误解的点 + +### 4. 最小示例 +给 2~4 个最有代表性的示例。 + +### 5. 常见场景 +把命令放进真实场景里: +- 查配置 +- 查日志 +- 找文件 +- 看资源 +- 改权限 + +### 6. 练习题 +练习题不再喧宾夺主,而是用于确认理解。 --- -## 📝 测验模式设计 +## 练习设计原则 -每个课时结束后,自动弹出: +练习题分成 3 类: -```bash -🎯 当前任务:_____________ -💡 提示:_________________ -(stdin) > [输入命令] +### A. 理解题 +检验有没有理解命令用途。 +例: +- 查看当前目录应该用什么命令? +- 为什么 `ls -a` 会比 `ls` 多看到东西? -✅ 回答正确!获得经验值 +100 -❌ 还未达标!提示:试试 `xxx` -``` +### B. 操作题 +检验能否正确写出命令。 +例: +- 进入 `/tmp` +- 查找 `/etc` 下所有 `.conf` 文件 -答对 3 次 → 解锁下一关 +### C. 场景题 +检验是否能把命令放进真实问题中。 +例: +- 日志太大,不想全看,只看最后 20 行怎么办? +- 想找出包含 `error` 的日志应该怎么做? --- -## 🎯 课程特色 +## 页面呈现结构(学习优先) -- ✅ **零风险沙盒**:所有命令在虚拟环境中执行,不会影响真实系统 -- ✅ **闯关式学习**:从入门到高手,逐步解锁新技能 -- ✅ **即时反馈**:答对/错都有针对性提示 -- ✅ **实战导向**:每个级别都有真实业务场景 -- ✅ **徽章认证**:每完成一个阶段获得专属徽章 +前端页面不再以“终端交互”为主,而改为: + +### 左侧:课程目录 +- 模块 +- 小节 +- 学习进度 + +### 中间:学习正文 +- 概念讲解 +- 示例 +- 场景 +- 总结 + +### 右侧:知识辅助 +- 关键概念 +- 易错点 +- 相关命令 +- 推荐练习 + +### 底部:练习区 +- 简洁练习,不抢正文 +- 只做必要反馈 +- 重点是“学完再练” --- -需要我根据这个课程体系开始实现吗?包括: -1. `COURSE_TASKS.json`(所有练习题) -2. 沙盒模拟器 `sandbox.py` -3. 熟悉 `server.py` 重构 -4. UI 改造(闯关式界面) -5. `README.md` 使用文档 +## 新平台定位 -还是先调整下课程内容?😄 \ No newline at end of file +重构后的 Linux 平台定位为: + +> **Linux 系统学习平台 + 轻量练习环境** + +不是刷题站,也不是单纯命令模拟器。 + +目标用户看到平台后,应该感受到: +- 这是能认真学东西的 +- 不是只会点按钮 +- 不是只会猜答案 +- 学完真的能迁移到实际 Linux 使用场景 + +--- + +## 重构顺序 + +### 第一阶段:课程蓝图重构 +- 重写课程结构 +- 重写模块划分 +- 重写题目组织方式 + +### 第二阶段:前 3 个模块内容重写 +- Linux 基本认知 +- 文件与目录操作 +- 阅读与筛选信息 + +### 第三阶段:页面重构 +- 课程目录页 +- 学习正文页 +- 轻练习区 + +### 第四阶段:后续模块补齐 +- 系统状态 +- 网络基础 +- 权限与运维习惯 + +--- + +## 当前结论 + +这次不是“继续补旧平台”,而是: + +> **把 Linux 平台从“交互导向”改造成“知识导向”的系统学习平台。** + +后续所有改动,以这个文档为准。 diff --git a/COURSE_TASKS.json b/COURSE_TASKS.json index 1ec3d92..6c327e5 100644 --- a/COURSE_TASKS.json +++ b/COURSE_TASKS.json @@ -1,191 +1,284 @@ { "meta": { - "version": "3.0", - "title": "Linux 运维工程师完整教程", - "author": "PMClaw", - "updated": "2026-03-06", - "description": "覆盖菜鸟教程 Linux 全部内容,从入门到精通", - "total_levels": 12, - "total_challenges": 80 + "version": "4.0", + "title": "Linux 系统学习课程(重构版)", + "author": "OpenClaw Dev", + "updated": "2026-03-10", + "description": "强调知识理解、场景迁移与轻量练习的 Linux 学习课程", + "module_count": 6, + "total_lessons": 18, + "total_exercises": 54 }, - "levels": [ + "modules": [ { - "id": "level_1_basic", - "title": "🌱 Level 1: Linux 基础入门", - "description": "Linux 简介、目录结构、基本操作", - "challenges": [ - {"id": "l1_1_pwd", "title": "查看当前目录", "description": "使用 pwd 命令显示当前工作目录的完整路径", "hint": "直接输入 pwd", "success_test": "'/' in output", "solution": ["pwd"], "success_msg": "📍 定位成功!"}, - {"id": "l1_2_ls", "title": "列出目录内容", "description": "使用 ls 命令查看当前目录下的文件和文件夹", "hint": "输入 ls", "success_test": "len(output) > 0", "solution": ["ls"], "success_msg": "📂 目录内容已显示!"}, - {"id": "l1_3_ls_l", "title": "详细列表", "description": "使用 ls -l 显示详细信息,包括权限、所有者、大小等", "hint": "ls -l", "success_test": "'total' in output or '-' in output[:20]", "solution": ["ls -l"], "success_msg": "📋 详细信息已获取!"}, - {"id": "l1_4_ls_a", "title": "显示隐藏文件", "description": "使用 ls -a 显示包括隐藏文件在内的所有文件", "hint": "ls -a", "success_test": "'.' in output and '..' in output", "solution": ["ls -a"], "success_msg": "👻 隐藏文件已显示!"}, - {"id": "l1_5_cd", "title": "切换目录", "description": "使用 cd 命令进入 /tmp 目录", "hint": "cd /tmp", "success_test": "cwd == '/tmp'", "solution": ["cd /tmp"], "success_msg": "🚶 目录切换成功!"}, - {"id": "l1_6_cd_back", "title": "返回上级目录", "description": "使用 cd .. 返回上级目录", "hint": "cd ..", "success_test": "cwd != '/tmp'", "solution": ["cd .."], "success_msg": "⬆️ 返回成功!"}, - {"id": "l1_7_cd_home", "title": "返回用户主目录", "description": "使用 cd ~ 或 cd 返回用户主目录", "hint": "cd ~", "success_test": "'home' in cwd or cwd == '/'", "solution": ["cd ~", "cd"], "success_msg": "🏠 已回到家目录!"}, - {"id": "l1_8_clear", "title": "清屏", "description": "使用 clear 命令清屏", "hint": "clear", "success_test": "cmd == 'clear'", "solution": ["clear"], "success_msg": "🧹 屏幕已清空!"} + "id": "module_1_foundation", + "title": "模块 1:建立 Linux 基本认知", + "summary": "先理解终端、目录、路径和最基础命令,建立 Linux 使用的空间感。", + "lessons": [ + { + "id": "m1_l1_pwd", + "title": "认识当前目录:pwd", + "goal": "理解当前工作目录的意义,知道自己在文件系统中的位置。", + "why_it_matters": "很多 Linux 操作依赖路径。如果不知道自己当前在哪,后续命令容易出错。", + "concepts": [ + "当前工作目录", + "绝对路径与相对路径", + "为什么要先定位再操作" + ], + "command": "pwd", + "examples": [ + "pwd", + "cd /tmp && pwd" + ], + "pitfalls": [ + "以为终端默认总在同一个目录", + "不分清当前目录和目标目录" + ], + "scenarios": [ + "切目录后确认自己到了哪里", + "写脚本前确认当前运行位置" + ], + "exercises": [ + { + "id": "m1_l1_e1", + "type": "understanding", + "question": "查看当前工作目录应该使用什么命令?", + "answer": "pwd" + }, + { + "id": "m1_l1_e2", + "type": "operation", + "title": "输出当前目录", + "hint": "直接输入 pwd", + "success_test": "cmd == 'pwd'", + "solution": ["pwd"], + "success_msg": "你已经能确认自己所在的位置了。" + }, + { + "id": "m1_l1_e3", + "type": "scenario", + "question": "如果你不确定自己当前在哪个目录,第一反应应该做什么?", + "answer": "先执行 pwd 确认当前目录" + } + ] + }, + { + "id": "m1_l2_ls", + "title": "看见目录内容:ls", + "goal": "理解 ls 的作用,并掌握查看隐藏文件和详细信息的基本方式。", + "why_it_matters": "Linux 下很多探索行为都从 ls 开始,它决定你如何观察目录结构。", + "concepts": [ + "目录内容查看", + "隐藏文件", + "长列表信息" + ], + "command": "ls", + "examples": [ + "ls", + "ls -la", + "ls -lh /etc" + ], + "pitfalls": [ + "误以为 ls 看不到的文件就不存在", + "不会区分普通 ls 和 ls -l 的用途" + ], + "scenarios": [ + "排查目录里到底有哪些文件", + "检查配置目录中是否有隐藏文件" + ], + "exercises": [ + { + "id": "m1_l2_e1", + "type": "understanding", + "question": "为什么 ls -a 会比 ls 多看到一些文件?", + "answer": "因为它会显示隐藏文件,包括以点开头的文件" + }, + { + "id": "m1_l2_e2", + "type": "operation", + "title": "列出当前目录内容", + "hint": "输入 ls", + "success_test": "cmd == 'ls'", + "solution": ["ls"], + "success_msg": "你已经会观察目录内容了。" + }, + { + "id": "m1_l2_e3", + "type": "operation", + "title": "显示隐藏文件和详细信息", + "hint": "使用 ls -la", + "success_test": "cmd == 'ls -la' or cmd == 'ls -al'", + "solution": ["ls -la", "ls -al"], + "success_msg": "你已经会用更完整的方式查看目录了。" + } + ] + }, + { + "id": "m1_l3_cd_cat_echo", + "title": "移动、读文件、输出文本", + "goal": "掌握 cd、cat、echo 这些最基础但最常用的命令。", + "why_it_matters": "这三个命令几乎贯穿 Linux 入门阶段的所有练习。", + "concepts": [ + "切换目录", + "读取文件", + "输出文本与变量" + ], + "command": "cd / cat / echo", + "examples": [ + "cd /tmp", + "cat /etc/hosts", + "echo Hello Linux" + ], + "pitfalls": [ + "把 cd 和 ls 混用", + "用 cat 去看过大的文件", + "不知道 echo 也常用于脚本调试" + ], + "scenarios": [ + "进入指定目录继续操作", + "快速读取配置文件", + "验证变量和命令输出" + ], + "exercises": [ + { + "id": "m1_l3_e1", + "type": "operation", + "title": "进入 /tmp 目录", + "hint": "cd /tmp", + "success_test": "cmd == 'cd /tmp' and cwd == '/tmp'", + "solution": ["cd /tmp"], + "success_msg": "你已经能切换到目标目录了。" + }, + { + "id": "m1_l3_e2", + "type": "operation", + "title": "读取 hosts 文件", + "hint": "cat /etc/hosts", + "success_test": "cmd == 'cat /etc/hosts' and 'localhost' in output", + "solution": ["cat /etc/hosts"], + "success_msg": "你已经会读取基础文本文件了。" + }, + { + "id": "m1_l3_e3", + "type": "operation", + "title": "输出 Hello Linux", + "hint": "echo Hello Linux", + "success_test": "cmd == 'echo Hello Linux' and 'Hello Linux' in output", + "solution": ["echo Hello Linux"], + "success_msg": "你已经掌握了最基础的文本输出命令。" + } + ] + } ] }, { - "id": "level_2_file", - "title": "📁 Level 2: 文件与目录管理", - "description": "创建、删除、复制、移动文件和目录", - "challenges": [ - {"id": "l2_1_mkdir", "title": "创建目录", "description": "使用 mkdir 创建 /tmp/testdir 目录", "hint": "mkdir /tmp/testdir", "success_test": "exists('/tmp/testdir')", "solution": ["mkdir /tmp/testdir"], "success_msg": "📂 目录创建成功!"}, - {"id": "l2_2_mkdir_p", "title": "递归创建目录", "description": "使用 mkdir -p 创建 /tmp/a/b/c 多级目录", "hint": "mkdir -p /tmp/a/b/c", "success_test": "exists('/tmp/a/b/c')", "solution": ["mkdir -p /tmp/a/b/c"], "success_msg": "📁 多级目录创建成功!"}, - {"id": "l2_3_touch", "title": "创建空文件", "description": "使用 touch 创建 /tmp/test.txt 文件", "hint": "touch /tmp/test.txt", "success_test": "exists('/tmp/test.txt')", "solution": ["touch /tmp/test.txt"], "success_msg": "📄 文件创建成功!"}, - {"id": "l2_4_cp", "title": "复制文件", "description": "将 /etc/hosts 复制到 /tmp/hosts.bak", "hint": "cp /etc/hosts /tmp/hosts.bak", "success_test": "exists('/tmp/hosts.bak')", "solution": ["cp /etc/hosts /tmp/hosts.bak"], "success_msg": "📋 文件复制成功!"}, - {"id": "l2_5_cp_r", "title": "复制目录", "description": "使用 cp -r 复制 /etc/skel 到 /tmp/skel_backup", "hint": "cp -r /etc/skel /tmp/skel_backup", "success_test": "exists('/tmp/skel_backup')", "solution": ["cp -r /etc/skel /tmp/skel_backup"], "success_msg": "📁 目录复制成功!"}, - {"id": "l2_6_mv", "title": "移动文件", "description": "将 /tmp/test.txt 移动到 /tmp/testdir/", "hint": "mv /tmp/test.txt /tmp/testdir/", "success_test": "exists('/tmp/testdir/test.txt')", "solution": ["mv /tmp/test.txt /tmp/testdir/"], "success_msg": "🚚 文件移动成功!"}, - {"id": "l2_7_mv_rename", "title": "重命名文件", "description": "将 /tmp/hosts.bak 重命名为 /tmp/hosts.backup", "hint": "mv /tmp/hosts.bak /tmp/hosts.backup", "success_test": "exists('/tmp/hosts.backup')", "solution": ["mv /tmp/hosts.bak /tmp/hosts.backup"], "success_msg": "✏️ 重命名成功!"}, - {"id": "l2_8_rm", "title": "删除文件", "description": "删除 /tmp/hosts.backup 文件", "hint": "rm /tmp/hosts.backup", "success_test": "not exists('/tmp/hosts.backup')", "solution": ["rm /tmp/hosts.backup"], "success_msg": "🗑️ 文件删除成功!"}, - {"id": "l2_9_rm_r", "title": "删除目录", "description": "使用 rm -r 删除 /tmp/skel_backup 目录", "hint": "rm -r /tmp/skel_backup", "success_test": "not exists('/tmp/skel_backup')", "solution": ["rm -r /tmp/skel_backup"], "success_msg": "🗑️ 目录删除成功!"}, - {"id": "l2_10_rm_rf", "title": "强制删除", "description": "使用 rm -rf 强制删除 /tmp/a 目录及其所有内容", "hint": "rm -rf /tmp/a", "success_test": "not exists('/tmp/a')", "solution": ["rm -rf /tmp/a"], "success_msg": "💥 强制删除成功!"} + "id": "module_2_filesystem", + "title": "模块 2:文件与目录操作", + "summary": "围绕创建、复制、移动、删除和查看文件属性建立文件系统操作能力。", + "lessons": [ + { + "id": "m2_l1_create", + "title": "创建文件与目录:mkdir / touch", + "goal": "理解目录和文件的创建逻辑,学会递归创建多级目录。", + "why_it_matters": "很多项目初始化、环境准备都从创建目录结构开始。", + "concepts": ["目录创建", "多级目录", "空文件创建"], + "command": "mkdir / touch", + "examples": ["mkdir demo", "mkdir -p /tmp/a/b/c", "touch notes.txt"], + "pitfalls": ["忘记使用 -p 创建多级目录", "目标父目录不存在时 touch 失败"], + "scenarios": ["初始化项目目录结构", "创建占位文件和日志文件"], + "exercises": [ + {"id": "m2_l1_e1", "type": "operation", "title": "递归创建目录", "hint": "mkdir -p /tmp/a/b/c", "success_test": "cmd == 'mkdir -p /tmp/a/b/c' and exists('/tmp/a/b/c')", "solution": ["mkdir -p /tmp/a/b/c"], "success_msg": "多级目录创建成功。"}, + {"id": "m2_l1_e2", "type": "operation", "title": "创建空文件", "hint": "touch /tmp/a/b/c/readme.txt", "success_test": "cmd == 'touch /tmp/a/b/c/readme.txt' and exists('/tmp/a/b/c/readme.txt')", "solution": ["touch /tmp/a/b/c/readme.txt"], "success_msg": "空文件创建成功。"}, + {"id": "m2_l1_e3", "type": "scenario", "question": "为什么 mkdir -p 适合项目初始化?", "answer": "因为它可以一次创建多级目录,即使上层目录不存在也能自动补齐"} + ] + }, + { + "id": "m2_l2_move_copy_delete", + "title": "复制、移动与删除:cp / mv / rm", + "goal": "理解文件操作中的备份、迁移、重命名和清理。", + "why_it_matters": "日常 Linux 使用里最常见的就是处理文件的生命周期。", + "concepts": ["复制与备份", "移动与重命名", "删除风险"], + "command": "cp / mv / rm", + "examples": ["cp /etc/hosts /tmp/hosts.bak", "mv old.txt new.txt", "rm -r /tmp/testdir"], + "pitfalls": ["把删除当成移动", "对目录使用 cp 却忘记 -r", "rm -rf 风险极高"], + "scenarios": ["做配置备份", "整理日志文件", "清理无用目录"], + "exercises": [ + {"id": "m2_l2_e1", "type": "operation", "title": "复制 hosts 文件", "hint": "cp /etc/hosts /tmp/hosts.bak", "success_test": "cmd == 'cp /etc/hosts /tmp/hosts.bak' and exists('/tmp/hosts.bak')", "solution": ["cp /etc/hosts /tmp/hosts.bak"], "success_msg": "文件备份成功。"}, + {"id": "m2_l2_e2", "type": "operation", "title": "重命名备份文件", "hint": "mv /tmp/hosts.bak /tmp/hosts.backup", "success_test": "cmd == 'mv /tmp/hosts.bak /tmp/hosts.backup' and exists('/tmp/hosts.backup')", "solution": ["mv /tmp/hosts.bak /tmp/hosts.backup"], "success_msg": "文件重命名成功。"}, + {"id": "m2_l2_e3", "type": "understanding", "question": "为什么 rm -rf 是高风险命令?", "answer": "因为它会递归并强制删除文件和目录,执行错误会造成不可恢复的数据丢失"} + ] + }, + { + "id": "m2_l3_stat_permissions", + "title": "认识文件属性:stat 与权限基础", + "goal": "开始理解文件属性和权限表达。", + "why_it_matters": "文件权限是 Linux 系统安全和协作的重要基础。", + "concepts": ["文件元信息", "权限三元组", "目录与文件权限差异"], + "command": "stat / chmod", + "examples": ["stat /etc/hosts", "chmod 755 script.sh", "chmod +x run.sh"], + "pitfalls": ["不了解 755 / 644 的含义", "给不该执行的文件随意加执行权限"], + "scenarios": ["检查脚本是否可执行", "排查权限导致的运行失败"], + "exercises": [ + {"id": "m2_l3_e1", "type": "operation", "title": "查看 hosts 属性", "hint": "stat /etc/hosts", "success_test": "cmd == 'stat /etc/hosts' and 'File:' in output", "solution": ["stat /etc/hosts"], "success_msg": "你已经会查看文件属性了。"}, + {"id": "m2_l3_e2", "type": "understanding", "question": "755 和 644 最核心的区别是什么?", "answer": "755 允许拥有者读写执行,其他人读执行;644 没有执行权限"}, + {"id": "m2_l3_e3", "type": "operation", "title": "给文件添加执行权限", "hint": "chmod +x /tmp/a/b/c/readme.txt", "success_test": "cmd == 'chmod +x /tmp/a/b/c/readme.txt'", "solution": ["chmod +x /tmp/a/b/c/readme.txt"], "success_msg": "你已经完成了权限修改练习。"} + ] + } ] }, { - "id": "level_3_view", - "title": "👁️ Level 3: 文件内容查看", - "description": "cat、more、less、head、tail 等查看命令", - "challenges": [ - {"id": "l3_1_cat", "title": "查看文件内容", "description": "使用 cat 查看 /etc/passwd 文件内容", "hint": "cat /etc/passwd", "success_test": "'root' in output", "solution": ["cat /etc/passwd"], "success_msg": "📖 文件内容已显示!"}, - {"id": "l3_2_cat_n", "title": "显示行号", "description": "使用 cat -n 显示 /etc/passwd 并带行号", "hint": "cat -n /etc/passwd", "success_test": "'1 ' in output or ' 1 ' in output", "solution": ["cat -n /etc/passwd"], "success_msg": "🔢 行号已显示!"}, - {"id": "l3_3_head", "title": "查看开头", "description": "使用 head 查看 /etc/passwd 前 10 行", "hint": "head /etc/passwd", "success_test": "len(output.split('\\n')) >= 5", "solution": ["head /etc/passwd"], "success_msg": "👆 开头内容已显示!"}, - {"id": "l3_4_head_n", "title": "指定行数", "description": "使用 head -n 5 查看前 5 行", "hint": "head -n 5 /etc/passwd", "success_test": "len(output.split('\\n')) <= 7", "solution": ["head -5 /etc/passwd", "head -n 5 /etc/passwd"], "success_msg": "📏 指定行数已显示!"}, - {"id": "l3_5_tail", "title": "查看结尾", "description": "使用 tail 查看 /etc/passwd 最后 10 行", "hint": "tail /etc/passwd", "success_test": "len(output) > 10", "solution": ["tail /etc/passwd"], "success_msg": "👇 结尾内容已显示!"}, - {"id": "l3_6_tail_f", "title": "实时追踪", "description": "使用 tail -f 实时查看 /var/log/syslog(按 Ctrl+C 退出)", "hint": "tail -f /var/log/syslog", "success_test": "cmd.startswith('tail -f')", "solution": ["tail -f /var/log/syslog"], "success_msg": "👀 实时追踪模式!"}, - {"id": "l3_7_more", "title": "分页查看", "description": "使用 more 分页查看 /etc/passwd", "hint": "more /etc/passwd", "success_test": "cmd.startswith('more')", "solution": ["more /etc/passwd"], "success_msg": "📄 分页查看模式!"}, - {"id": "l3_8_less", "title": "可滚动查看", "description": "使用 less 查看 /etc/passwd(支持上下滚动)", "hint": "less /etc/passwd", "success_test": "cmd.startswith('less')", "solution": ["less /etc/passwd"], "success_msg": "📜 可滚动查看模式!"} - ] - }, - { - "id": "level_4_permission", - "title": "🔐 Level 4: 文件权限管理", - "description": "chmod、chown、chgrp 权限控制", - "challenges": [ - {"id": "l4_1_ls_l", "title": "查看权限", "description": "使用 ls -l /etc/passwd 查看文件权限", "hint": "ls -l /etc/passwd", "success_test": "'-' in output or 'r' in output", "solution": ["ls -l /etc/passwd"], "success_msg": "👀 权限信息已显示!"}, - {"id": "l4_2_chmod_755", "title": "修改权限为755", "description": "将 /tmp/testdir 权限改为 rwxr-xr-x (755)", "hint": "chmod 755 /tmp/testdir", "success_test": "cmd == 'chmod 755 /tmp/testdir'", "solution": ["chmod 755 /tmp/testdir"], "success_msg": "🔐 权限修改成功!"}, - {"id": "l4_3_chmod_644", "title": "修改权限为644", "description": "将 /tmp/testdir/test.txt 权限改为 rw-r--r-- (644)", "hint": "chmod 644 /tmp/testdir/test.txt", "success_test": "cmd == 'chmod 644 /tmp/testdir/test.txt'", "solution": ["chmod 644 /tmp/testdir/test.txt"], "success_msg": "🔐 权限修改成功!"}, - {"id": "l4_4_chmod_x", "title": "添加执行权限", "description": "给 /tmp/testdir/test.txt 添加可执行权限", "hint": "chmod +x /tmp/testdir/test.txt", "success_test": "cmd == 'chmod +x /tmp/testdir/test.txt'", "solution": ["chmod +x /tmp/testdir/test.txt"], "success_msg": "⚡ 执行权限已添加!"}, - {"id": "l4_5_chmod_r", "title": "移除读权限", "description": "移除 /tmp/testdir/test.txt 的读权限", "hint": "chmod -r /tmp/testdir/test.txt", "success_test": "cmd == 'chmod -r /tmp/testdir/test.txt'", "solution": ["chmod -r /tmp/testdir/test.txt"], "success_msg": "🚫 读权限已移除!"}, - {"id": "l4_6_chown", "title": "修改所有者", "description": "将 /tmp/testdir/test.txt 所有者改为 root", "hint": "chown root /tmp/testdir/test.txt", "success_test": "cmd.startswith('chown')", "solution": ["chown root /tmp/testdir/test.txt"], "success_msg": "👤 所有者已修改!"}, - {"id": "l4_7_chgrp", "title": "修改所属组", "description": "将 /tmp/testdir/test.txt 所属组改为 root", "hint": "chgrp root /tmp/testdir/test.txt", "success_test": "cmd.startswith('chgrp')", "solution": ["chgrp root /tmp/testdir/test.txt"], "success_msg": "👥 所属组已修改!"}, - {"id": "l4_8_chown_r", "title": "递归修改", "description": "递归修改 /tmp/testdir 及其所有内容的所有者为 root", "hint": "chown -R root /tmp/testdir", "success_test": "cmd.startswith('chown -R')", "solution": ["chown -R root /tmp/testdir"], "success_msg": "🔄 递归修改成功!"} - ] - }, - { - "id": "level_5_search", - "title": "🔍 Level 5: 搜索与过滤", - "description": "find、grep、which、whereis 搜索命令", - "challenges": [ - {"id": "l5_1_find_name", "title": "按名称查找", "description": "在 /etc 下查找所有 .conf 文件", "hint": "find /etc -name '*.conf'", "success_test": "'.conf' in output", "solution": ["find /etc -name '*.conf'"], "success_msg": "🔍 文件已找到!"}, - {"id": "l5_2_find_type", "title": "按类型查找", "description": "查找 /tmp 下的所有目录", "hint": "find /tmp -type d", "success_test": "cmd.startswith('find') and '-type d' in cmd", "solution": ["find /tmp -type d"], "success_msg": "📁 目录已找到!"}, - {"id": "l5_3_find_size", "title": "按大小查找", "description": "查找 /var/log 下大于 1M 的文件", "hint": "find /var/log -size +1M", "success_test": "cmd.startswith('find') and '-size' in cmd", "solution": ["find /var/log -size +1M"], "success_msg": "📏 大文件已找到!"}, - {"id": "l5_4_find_exec", "title": "执行操作", "description": "查找 /tmp 下所有 .log 文件并删除", "hint": "find /tmp -name '*.log' -exec rm {} \\;", "success_test": "'-exec' in cmd", "solution": ["find /tmp -name '*.log' -exec rm {} \\;"], "success_msg": "🗑️ 操作执行成功!"}, - {"id": "l5_5_grep", "title": "文本搜索", "description": "在 /etc/passwd 中搜索 root 用户", "hint": "grep root /etc/passwd", "success_test": "'root' in output", "solution": ["grep root /etc/passwd"], "success_msg": "🎯 搜索成功!"}, - {"id": "l5_6_grep_i", "title": "忽略大小写", "description": "使用 grep -i 搜索 ROOT(不区分大小写)", "hint": "grep -i root /etc/passwd", "success_test": "'-i' in cmd", "solution": ["grep -i root /etc/passwd"], "success_msg": "🔤 忽略大小写搜索成功!"}, - {"id": "l5_7_grep_v", "title": "反向匹配", "description": "显示 /etc/passwd 中不包含 nologin 的行", "hint": "grep -v nologin /etc/passwd", "success_test": "'-v' in cmd", "solution": ["grep -v nologin /etc/passwd"], "success_msg": "🔄 反向匹配成功!"}, - {"id": "l5_8_grep_n", "title": "显示行号", "description": "使用 grep -n 显示匹配行的行号", "hint": "grep -n root /etc/passwd", "success_test": "'-n' in cmd and ':' in output", "solution": ["grep -n root /etc/passwd"], "success_msg": "🔢 行号已显示!"}, - {"id": "l5_9_which", "title": "查找命令位置", "description": "查找 ls 命令的位置", "hint": "which ls", "success_test": "'/bin' in output or '/usr' in output", "solution": ["which ls"], "success_msg": "📍 命令位置已找到!"}, - {"id": "l5_10_whereis", "title": "查找相关文件", "description": "使用 whereis 查找 ls 命令的相关文件", "hint": "whereis ls", "success_test": "cmd.startswith('whereis')", "solution": ["whereis ls"], "success_msg": "📚 相关文件已找到!"} - ] - }, - { - "id": "level_6_user", - "title": "👥 Level 6: 用户和组管理", - "description": "useradd、usermod、passwd、group 管理", - "challenges": [ - {"id": "l6_1_whoami", "title": "查看当前用户", "description": "使用 whoami 查看当前登录用户名", "hint": "whoami", "success_test": "len(output.strip()) > 0", "solution": ["whoami"], "success_msg": "👤 当前用户已显示!"}, - {"id": "l6_2_id", "title": "查看用户ID", "description": "使用 id 查看当前用户的 UID、GID 和所属组", "hint": "id", "success_test": "'uid' in output.lower()", "solution": ["id"], "success_msg": "🆔 用户信息已显示!"}, - {"id": "l6_3_w", "title": "查看登录用户", "description": "使用 w 查看当前登录系统的用户", "hint": "w", "success_test": "'USER' in output or 'TTY' in output", "solution": ["w"], "success_msg": "👥 登录用户已显示!"}, - {"id": "l6_4_last", "title": "查看登录历史", "description": "使用 last 查看最近的登录记录", "hint": "last", "success_test": "len(output) > 10", "solution": ["last"], "success_msg": "📜 登录历史已显示!"}, - {"id": "l6_5_cat_passwd", "title": "查看用户列表", "description": "查看 /etc/passwd 文件了解系统用户", "hint": "cat /etc/passwd", "success_test": "':' in output", "solution": ["cat /etc/passwd"], "success_msg": "📋 用户列表已显示!"}, - {"id": "l6_6_cat_group", "title": "查看组列表", "description": "查看 /etc/group 文件了解系统用户组", "hint": "cat /etc/group", "success_test": "':' in output", "solution": ["cat /etc/group"], "success_msg": "📋 组列表已显示!"}, - {"id": "l6_7_passwd", "title": "修改密码", "description": "使用 passwd 修改当前用户密码(输入当前密码和新密码)", "hint": "passwd", "success_test": "cmd == 'passwd'", "solution": ["passwd"], "success_msg": "🔑 密码修改命令已执行!"}, - {"id": "l6_8_su", "title": "切换用户", "description": "使用 su - 切换到 root 用户", "hint": "su -", "success_test": "cmd.startswith('su')", "solution": ["su -", "su"], "success_msg": "🔄 用户切换命令已执行!"} - ] - }, - { - "id": "level_7_disk", - "title": "💾 Level 7: 磁盘管理", - "description": "df、du、fdisk、mount 磁盘操作", - "challenges": [ - {"id": "l7_1_df", "title": "查看磁盘空间", "description": "使用 df 查看文件系统磁盘空间使用情况", "hint": "df", "success_test": "'Filesystem' in output or '文件系统' in output", "solution": ["df"], "success_msg": "💾 磁盘空间已显示!"}, - {"id": "l7_2_df_h", "title": "人类可读格式", "description": "使用 df -h 以人类可读格式显示磁盘空间", "hint": "df -h", "success_test": "'G' in output or 'M' in output or 'K' in output", "solution": ["df -h"], "success_msg": "📊 磁盘空间(易读格式)!"}, - {"id": "l7_3_du", "title": "查看目录大小", "description": "使用 du 查看 /tmp 目录的大小", "hint": "du /tmp", "success_test": "len(output) > 0", "solution": ["du /tmp"], "success_msg": "📏 目录大小已显示!"}, - {"id": "l7_4_du_sh", "title": "查看总大小", "description": "使用 du -sh 查看 /tmp 的总大小", "hint": "du -sh /tmp", "success_test": "'-sh' in cmd", "solution": ["du -sh /tmp"], "success_msg": "📊 总大小已显示!"}, - {"id": "l7_5_du_sort", "title": "排序查看", "description": "查看 /tmp 下最大的 5 个目录", "hint": "du -sh /tmp/* | sort -rh | head -5", "success_test": "'sort' in cmd", "solution": ["du -sh /tmp/* | sort -rh | head -5"], "success_msg": "🏆 最大目录已排序!"}, - {"id": "l7_6_mount", "title": "查看挂载点", "description": "使用 mount 查看已挂载的文件系统", "hint": "mount", "success_test": "'on' in output or 'type' in output", "solution": ["mount"], "success_msg": "🔗 挂载点已显示!"}, - {"id": "l7_7_fdisk", "title": "查看分区表", "description": "使用 fdisk -l 查看磁盘分区表(需要 root 权限)", "hint": "fdisk -l", "success_test": "cmd.startswith('fdisk')", "solution": ["fdisk -l"], "success_msg": "💿 分区表已显示!"} - ] - }, - { - "id": "level_8_process", - "title": "⚙️ Level 8: 进程管理", - "description": "ps、top、kill、nohup 进程控制", - "challenges": [ - {"id": "l8_1_ps", "title": "查看进程", "description": "使用 ps 查看当前用户的进程", "hint": "ps", "success_test": "'PID' in output", "solution": ["ps"], "success_msg": "📋 进程列表已显示!"}, - {"id": "l8_2_ps_aux", "title": "查看所有进程", "description": "使用 ps aux 查看系统所有进程", "hint": "ps aux", "success_test": "'%CPU' in output or 'RSS' in output", "solution": ["ps aux"], "success_msg": "📊 所有进程已显示!"}, - {"id": "l8_3_ps_grep", "title": "查找特定进程", "description": "查找包含 ssh 的进程", "hint": "ps aux | grep ssh", "success_test": "'|' in cmd", "solution": ["ps aux | grep ssh"], "success_msg": "🎯 进程已找到!"}, - {"id": "l8_4_top", "title": "实时进程监控", "description": "使用 top 实时查看进程(按 q 退出)", "hint": "top", "success_test": "cmd == 'top'", "solution": ["top"], "success_msg": "📈 实时监控已启动!"}, - {"id": "l8_5_kill", "title": "终止进程", "description": "使用 kill 命令(查看 PID 后终止)", "hint": "kill PID", "success_test": "cmd.startswith('kill')", "solution": ["kill 1234"], "success_msg": "💀 终止命令已执行!"}, - {"id": "l8_6_kill9", "title": "强制终止", "description": "使用 kill -9 强制终止进程", "hint": "kill -9 PID", "success_test": "'-9' in cmd", "solution": ["kill -9 1234"], "success_msg": "💥 强制终止已执行!"}, - {"id": "l8_7_pkill", "title": "按名称终止", "description": "使用 pkill 按进程名终止", "hint": "pkill process_name", "success_test": "cmd.startswith('pkill')", "solution": ["pkill python"], "success_msg": "🎯 按名称终止已执行!"}, - {"id": "l8_8_nohup", "title": "后台运行", "description": "使用 nohup 让命令在后台运行", "hint": "nohup command &", "success_test": "cmd.startswith('nohup')", "solution": ["nohup sleep 10 &"], "success_msg": "🌙 后台运行已设置!"} - ] - }, - { - "id": "level_9_network", - "title": "🌐 Level 9: 网络管理", - "description": "ifconfig、ping、netstat、curl 网络命令", - "challenges": [ - {"id": "l9_1_ifconfig", "title": "查看网卡", "description": "使用 ifconfig 查看网络接口配置", "hint": "ifconfig", "success_test": "'inet' in output or 'eth' in output or 'lo' in output", "solution": ["ifconfig"], "success_msg": "🎴 网卡信息已显示!"}, - {"id": "l9_2_ip_addr", "title": "现代方式查看", "description": "使用 ip addr 查看网络接口", "hint": "ip addr", "success_test": "cmd.startswith('ip addr')", "solution": ["ip addr"], "success_msg": "🎴 网络接口已显示!"}, - {"id": "l9_3_ping", "title": "测试连通性", "description": "ping 127.0.0.1 测试本地网络", "hint": "ping -c 4 127.0.0.1", "success_test": "cmd.startswith('ping')", "solution": ["ping -c 4 127.0.0.1"], "success_msg": "📡 Ping 测试完成!"}, - {"id": "l9_4_netstat", "title": "查看网络连接", "description": "使用 netstat -tlnp 查看监听端口", "hint": "netstat -tlnp", "success_test": "'LISTEN' in output or 'tcp' in output.lower()", "solution": ["netstat -tlnp"], "success_msg": "🔗 网络连接已显示!"}, - {"id": "l9_5_ss", "title": "现代方式查看端口", "description": "使用 ss -tlnp 查看监听端口", "hint": "ss -tlnp", "success_test": "cmd.startswith('ss')", "solution": ["ss -tlnp"], "success_msg": "🔗 端口信息已显示!"}, - {"id": "l9_6_curl", "title": "HTTP 请求", "description": "使用 curl 访问 http://localhost:8080", "hint": "curl http://localhost:8080", "success_test": "cmd.startswith('curl')", "solution": ["curl http://localhost:8080"], "success_msg": "🌐 HTTP 请求已发送!"}, - {"id": "l9_7_wget", "title": "下载文件", "description": "使用 wget 下载网页", "hint": "wget http://localhost:8080 -O /tmp/test.html", "success_test": "cmd.startswith('wget')", "solution": ["wget http://localhost:8080 -O /tmp/test.html"], "success_msg": "📥 文件下载命令已执行!"}, - {"id": "l9_8_traceroute", "title": "路由追踪", "description": "使用 traceroute 追踪到目标的路由", "hint": "traceroute 8.8.8.8", "success_test": "cmd.startswith('traceroute') or cmd.startswith('tracepath')", "solution": ["traceroute 8.8.8.8"], "success_msg": "🛤️ 路由追踪已启动!"} - ] - }, - { - "id": "level_10_package", - "title": "📦 Level 10: 软件包管理", - "description": "yum、apt、rpm、dpkg 包管理", - "challenges": [ - {"id": "l10_1_yum_list", "title": "列出已安装包", "description": "使用 yum list installed 查看已安装的包", "hint": "yum list installed", "success_test": "cmd.startswith('yum')", "solution": ["yum list installed"], "success_msg": "📋 已安装包列表!"}, - {"id": "l10_2_yum_search", "title": "搜索包", "description": "使用 yum search 搜索 nginx", "hint": "yum search nginx", "success_test": "cmd.startswith('yum search')", "solution": ["yum search nginx"], "success_msg": "🔍 包搜索完成!"}, - {"id": "l10_3_rpm_q", "title": "查询包信息", "description": "使用 rpm -q 查询 bash 包", "hint": "rpm -q bash", "success_test": "cmd.startswith('rpm')", "solution": ["rpm -q bash"], "success_msg": "📦 包信息已显示!"}, - {"id": "l10_4_apt_update", "title": "更新包列表", "description": "使用 apt update 更新包列表", "hint": "apt update", "success_test": "cmd.startswith('apt update')", "solution": ["apt update"], "success_msg": "🔄 包列表已更新!"}, - {"id": "l10_5_dpkg_l", "title": "列出 Debian 包", "description": "使用 dpkg -l 列出已安装的包", "hint": "dpkg -l", "success_test": "cmd.startswith('dpkg')", "solution": ["dpkg -l"], "success_msg": "📋 Debian 包列表!"} - ] - }, - { - "id": "level_11_vim", - "title": "✏️ Level 11: Vi/Vim 编辑器", - "description": "vim 基本操作和常用命令", - "challenges": [ - {"id": "l11_1_vim", "title": "打开文件", "description": "使用 vim 打开 /tmp/test.txt", "hint": "vim /tmp/test.txt", "success_test": "cmd.startswith('vim') or cmd.startswith('vi')", "solution": ["vim /tmp/test.txt"], "success_msg": "📝 Vim 已启动!"}, - {"id": "l11_2_vim_i", "title": "插入模式", "description": "在 vim 中按 i 进入插入模式", "hint": "按 i 键", "success_test": "cmd == 'i'", "solution": ["i"], "success_msg": "⌨️ 插入模式!"}, - {"id": "l11_3_vim_esc", "title": "退出插入模式", "description": "按 Esc 退出插入模式", "hint": "按 Esc 键", "success_test": "cmd == 'esc' or cmd == 'Esc'", "solution": ["esc"], "success_msg": "🚪 退出插入模式!"}, - {"id": "l11_4_vim_wq", "title": "保存退出", "description": "输入 :wq 保存并退出", "hint": ":wq", "success_test": "cmd == ':wq'", "solution": [":wq"], "success_msg": "💾 保存并退出!"}, - {"id": "l11_5_vim_q", "title": "不保存退出", "description": "输入 :q! 强制退出不保存", "hint": ":q!", "success_test": "cmd == ':q!'", "solution": [":q!"], "success_msg": "🚪 强制退出!"} - ] - }, - { - "id": "level_12_shell", - "title": "🚀 Level 12: Shell 脚本编程", - "description": "Shell 脚本基础、变量、循环、条件判断", - "challenges": [ - {"id": "l12_1_echo_var", "title": "输出变量", "description": "使用 echo 输出环境变量 $HOME", "hint": "echo $HOME", "success_test": "'$HOME' in cmd or 'echo $' in cmd", "solution": ["echo $HOME"], "success_msg": "🔤 变量已输出!"}, - {"id": "l12_2_env", "title": "查看环境变量", "description": "使用 env 查看所有环境变量", "hint": "env", "success_test": "cmd == 'env'", "solution": ["env"], "success_msg": "🌍 环境变量已显示!"}, - {"id": "l12_3_export", "title": "设置环境变量", "description": "使用 export 设置 MYVAR=test", "hint": "export MYVAR=test", "success_test": "cmd.startswith('export')", "solution": ["export MYVAR=test"], "success_msg": "📤 环境变量已设置!"}, - {"id": "l12_4_alias", "title": "命令别名", "description": "创建别名 ll='ls -l'", "hint": "alias ll='ls -l'", "success_test": "cmd.startswith('alias')", "solution": ["alias ll='ls -l'"], "success_msg": "🏷️ 别名已创建!"}, - {"id": "l12_5_date", "title": "显示日期", "description": "使用 date 显示当前日期时间", "hint": "date", "success_test": "cmd == 'date'", "solution": ["date"], "success_msg": "📅 日期已显示!"}, - {"id": "l12_6_cal", "title": "显示日历", "description": "使用 cal 显示本月日历", "hint": "cal", "success_test": "cmd == 'cal'", "solution": ["cal"], "success_msg": "📆 日历已显示!"}, - {"id": "l12_7_bc", "title": "计算器", "description": "使用 bc 计算 1+1", "hint": "echo '1+1' | bc", "success_test": "'bc' in cmd", "solution": ["echo '1+1' | bc"], "success_msg": "🧮 计算完成!"}, - {"id": "l12_8_tar", "title": "打包压缩", "description": "将 /tmp/testdir 打包为 /tmp/testdir.tar.gz", "hint": "tar -czf /tmp/testdir.tar.gz /tmp/testdir", "success_test": "cmd.startswith('tar')", "solution": ["tar -czf /tmp/testdir.tar.gz /tmp/testdir"], "success_msg": "📦 打包完成!"}, - {"id": "l12_9_untar", "title": "解压", "description": "解压 /tmp/testdir.tar.gz 到 /tmp/extract/", "hint": "tar -xzf /tmp/testdir.tar.gz -C /tmp/extract/", "success_test": "'-x' in cmd or '--extract' in cmd", "solution": ["tar -xzf /tmp/testdir.tar.gz -C /tmp/"], "success_msg": "📂 解压完成!"}, - {"id": "l12_10_crontab", "title": "定时任务", "description": "使用 crontab -l 查看定时任务", "hint": "crontab -l", "success_test": "cmd.startswith('crontab')", "solution": ["crontab -l"], "success_msg": "⏰ 定时任务已显示!"} + "id": "module_3_searching", + "title": "模块 3:阅读与筛选信息", + "summary": "把 Linux 当成信息检索工具来学,围绕日志、配置和统计建立阅读能力。", + "lessons": [ + { + "id": "m3_l1_read_logs", + "title": "看文件头尾:head / tail", + "goal": "学会快速读取大文件的局部内容。", + "why_it_matters": "日志通常很大,不可能总是整份去看。", + "concepts": ["查看前几行", "查看后几行", "实时追踪"], + "command": "head / tail", + "examples": ["head -n 5 /var/log/syslog", "tail -n 20 /var/log/syslog", "tail -f /var/log/syslog"], + "pitfalls": ["大文件直接 cat 影响阅读效率", "不会区分查看历史和跟踪新增日志"], + "scenarios": ["看配置文件开头", "盯日志尾部排查实时错误"], + "exercises": [ + {"id": "m3_l1_e1", "type": "operation", "title": "查看 syslog 前 5 行", "hint": "head -n 5 /var/log/syslog", "success_test": "(cmd == 'head -n 5 /var/log/syslog' or cmd == 'head -5 /var/log/syslog') and len(output.split('\n')) >= 5", "solution": ["head -n 5 /var/log/syslog", "head -5 /var/log/syslog"], "success_msg": "你已经会局部查看大文件开头了。"}, + {"id": "m3_l1_e2", "type": "operation", "title": "查看 syslog 最后 3 行", "hint": "tail -n 3 /var/log/syslog", "success_test": "(cmd == 'tail -n 3 /var/log/syslog' or cmd == 'tail -3 /var/log/syslog') and len(output.split('\n')) >= 3", "solution": ["tail -n 3 /var/log/syslog", "tail -3 /var/log/syslog"], "success_msg": "你已经会快速查看日志尾部了。"}, + {"id": "m3_l1_e3", "type": "scenario", "question": "为什么排查线上报错时更常先用 tail 而不是 cat?", "answer": "因为日志通常很大,tail 可以更快聚焦最近发生的问题"} + ] + }, + { + "id": "m3_l2_grep", + "title": "关键词搜索:grep", + "goal": "理解 grep 作为日志排障和文本定位核心工具的价值。", + "why_it_matters": "没有 grep,查日志和配置会慢很多。", + "concepts": ["大小写忽略", "显示行号", "反向匹配", "递归搜索"], + "command": "grep", + "examples": ["grep error /var/log/syslog", "grep -in root /etc/passwd", "grep -v nologin /etc/passwd"], + "pitfalls": ["不会结合 -n 定位行号", "不知道 -i 和 -v 的常见用途"], + "scenarios": ["查错误日志", "找配置项", "过滤无效行"], + "exercises": [ + {"id": "m3_l2_e1", "type": "operation", "title": "查找 syslog 中的 error", "hint": "grep error /var/log/syslog", "success_test": "cmd == 'grep error /var/log/syslog' and 'error' in output.lower()", "solution": ["grep error /var/log/syslog"], "success_msg": "你已经会在日志里搜关键词了。"}, + {"id": "m3_l2_e2", "type": "operation", "title": "忽略大小写搜索 root", "hint": "grep -i root /etc/passwd", "success_test": "cmd == 'grep -i root /etc/passwd'", "solution": ["grep -i root /etc/passwd"], "success_msg": "你已经知道如何处理大小写差异了。"}, + {"id": "m3_l2_e3", "type": "understanding", "question": "grep -n 的意义是什么?", "answer": "显示匹配结果所在的行号,方便快速定位原文位置"} + ] + }, + { + "id": "m3_l3_find_wc_sort", + "title": "查找与统计:find / wc / sort", + "goal": "建立查找文件和做基础统计的能力。", + "why_it_matters": "Linux 的很多效率来自组合式查找与统计。", + "concepts": ["按名称查找", "行数字数统计", "排序输出"], + "command": "find / wc / sort", + "examples": ["find /etc -name '*.conf'", "wc -l /var/log/syslog", "ls | sort"], + "pitfalls": ["把 find 和 grep 混淆", "不会根据任务选文件查找还是内容查找"], + "scenarios": ["找配置文件", "统计日志行数", "整理输出结果"], + "exercises": [ + {"id": "m3_l3_e1", "type": "operation", "title": "查找 /etc 下所有 .conf 文件", "hint": "find /etc -name '*.conf'", "success_test": "cmd == \"find /etc -name '*.conf'\" and '.conf' in output", "solution": ["find /etc -name '*.conf'"], "success_msg": "你已经会用 find 定位文件了。"}, + {"id": "m3_l3_e2", "type": "operation", "title": "统计 syslog 行数", "hint": "wc -l /var/log/syslog", "success_test": "cmd == 'wc -l /var/log/syslog' and output.strip().isdigit()", "solution": ["wc -l /var/log/syslog"], "success_msg": "你已经会做基础统计了。"}, + {"id": "m3_l3_e3", "type": "understanding", "question": "找文件位置应该优先想到 find 还是 grep?为什么?", "answer": "优先用 find,因为这是文件定位问题,不是文件内容搜索问题"} + ] + } ] } ] diff --git a/index.html b/index.html index 1eb40a1..e40ef27 100644 --- a/index.html +++ b/index.html @@ -3,42 +3,39 @@
-内容更系统 · 练习更真实 · 判题更可靠
+以知识理解为中心,练习为辅,帮助建立真正可迁移的 Linux 能力。