286 lines
16 KiB
JSON
286 lines
16 KiB
JSON
{
|
||
"meta": {
|
||
"version": "4.0",
|
||
"title": "Linux 系统学习课程(重构版)",
|
||
"author": "OpenClaw Dev",
|
||
"updated": "2026-03-10",
|
||
"description": "强调知识理解、场景迁移与轻量练习的 Linux 学习课程",
|
||
"module_count": 6,
|
||
"total_lessons": 18,
|
||
"total_exercises": 54
|
||
},
|
||
"modules": [
|
||
{
|
||
"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": "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": "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,因为这是文件定位问题,不是文件内容搜索问题"}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|