Files
linux-practice/COURSE_TASKS.json

286 lines
16 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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因为这是文件定位问题不是文件内容搜索问题"}
]
}
]
}
]
}