Files
linux-practice/COURSE_TASKS.json

286 lines
16 KiB
JSON
Raw Normal View History

{
"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因为这是文件定位问题不是文件内容搜索问题"}
]
}
]
}
]
}