教授本科生 Unix 课程
作者:BENEDICT REUSCHLING
背景故事——接手 Unix 课程
2002 年,我还是一名计算机科学专业的本科生,那是我初次真正接触 Unix 系统。我清楚地记得,在我的第一堂编程课上,教授打开了他的 ThinkPad 笔记本,同时以这样一句话开始了讲座:
“本系的教授分为两种:一种使用 Unix——我属于这一类;另一种使用 Windows——那就是其他所有人。”
他不仅教我们编程,还完全在命令行中进行教学。他用 cat
命令展示程序,在 vi
编辑器中编写代码,使用 make
进行编译,在 X11 下播放幻灯片。所有这些都很基础,但却让我产生了浓厚的兴趣——或许是因为我从小用 DOS,却从未意识到终端还能带来什么样的体验。毕竟,在当时的计算机科学圈子里,能在自己的电脑上运行 Linux 或其他 Unix 系统,就意味着你是个“酷”家伙。
在他的课上,我学完了高级编程、操作系统,接着又修了分布式系统课程。到那时,我已经在自己的笔记本上安装了 Linux,并在发现 FreeBSD 后,很快就完全转向了它。
这位教授还开设了一门非必修课程,名为 Unix for Developers(面向开发者的 Unix)。在这门课上,Unix 本身就是主要的学习内容。虽然它的风格有些“老派”,但对我来说却非常有吸引力。我们学习了各种 Unix 工具,学会了如何高效地编辑文件,并使用 shell 和 awk
编写脚本,以便在需要时补充缺失的功能。这门课很有挑战性,但我渴望学习,并在自己的系统上尽可能多地尝试。
随着时间推移,教授最终换用了 Mac(许多学生也随之跟进),并且参与了更多的课程和项目工作,因而没有时间再教授 Unix for Developers 这门课了。那时,我已经毕业,并在系里担任实验室工程师。他可能还记得我对这门课的热情,于是问我是否愿意接手。我答应了,他向我介绍了课程的运作方式。
当时的课程内容已经有些过时,比如仍然讲授 Linux 2.4 版本的内核,而 Linux 2.6 早已发布。因此,我不仅对课程内容进行了更新,还在其中加入了一些 BSD 相关的内容。
几年后,我用德语教授了这门课程后,学校问我是否愿意用英语授课,以便让交换生也能学习。由于很多 Unix 相关的概念本身就是英语,翻译成德语反而不够准确,我便重新整理了一遍课程讲义并翻译成了英文。从那以后,我一直用英语授课,甚至偶尔在一些会议上将部分内容作为教程分享。
但让我们回到最初的那些日子……
课程组织结构
就这样,我接手了一门必修课,并需要安排一个学期的课程内容。这门课在冬季学期授课,大致覆盖 10 月到 1 月间的 15 周,中间有圣诞假期。书面考试安排在 2 月,这意味着从最后一节课到考试日,学生约有两周的时间进行复习。
课程包括每周一次的 90 分钟讲座,以及单次 3 小时的实验课。由于这门选修课很受欢迎,通常会有 40 名学生选修。因此,每个实验小组大约 16 人,每 14 天轮流上一次实验课,这样每个小组总共会有 5 次实验。实验课虽然不评分,但学生必须完成(通常是两人一组)才能获得考试资格。课程没有期中考核,最终成绩完全由考试结果决定。
这个评分体系曾被多次讨论,特别是是否应该对实验课进行评分,毕竟学生投入了不少精力。但在这所德国大学中,大多数课程都采用类似的结构(尽管有少数例外),因此它已成为一种固定模式。
由于这是门选修课,选修的学生都是对这个主题感兴趣的。没有任何学生必须选修这门课才能毕业——他们只需要在成绩单上修满一定数量的选修课程,而具体选哪几门完全由他们自己决定。这不仅减少了总体的学生数量,也导致选修这门课的学生大致可以分为两类:一类是想学习 Unix 但几乎没有基础的,另一类是已经熟悉 Unix,想进一步深入学习(或者只是想拿个轻松的学分)。稍后我们会看到,如何平衡这两类学生的需求并不总是那么容易……
讲座
正如前面提到的,当我接手这门课程时,它已经有些过时,并且在此之前已经停开了一段时间。我认为可以加入一些 BSD 相关的内容,使课程更具 Unix 通用性,反正我也需要重新制作幻灯片。
每学期的第一节课,总会有学生问:
“我们要用哪款 Linux 发行版?”
这个问题往往会引起争论,因为 Linux 发行版实在太多了。如果我说 Ubuntu,Linux Mint 用户会失望;如果我说 Mint,则 Arch Linux 用户会大跌眼镜。
为了避免这种情况(同时也让所有人有机会学习新知识,而不影响他们已有的习惯),我通常会这样回答:
“所有发行版,即没有特定的发行版。我们将使用 FreeBSD,但如果有人想用自己喜欢的发行版,我不会阻止你。毕竟,这是门入门课程,而不是填鸭课程。”
我向学生解释,如果他们是新手,那么从 FreeBSD 入门和使用所有 Linux 发行版的起点是一样的,概念也可以很好地迁移。而对于已经熟悉某款 Linux 发行版的学生,他们可以借此机会接触 BSD 系统,并会发现很多基础知识都是通用的。这通常能让所有人都满意,同时我也成功避开了发行版之争。
不过,如果学生选择使用自己喜欢的发行版,那他们就不能指望从我这里得到任何帮助。这是他们的系统,他们的选择,他们的管理工作,而非我的责任。
不同 Linux 发行版的流行程度随着学生一代代更替而变化,而 FreeBSD 一直保持相对稳定——无意外、易上手,而且免费。值得注意的是,我教授的很多内容实际上是与发行版无关的,因此在不同系统之间基本没有区别。有时候,在课堂演示时我们会对比不同系统的细节(稍后会提到),但本质上,我们使用的命令都能完成预期的任务。
课程内容
本课程包含以下内容:
Unix 概述(基础知识,如登录、
ls
、cp
等命令)编辑器(
vi/vim
速成)Shell(命令历史、Tab 补全、重定向、管道、Here 文档、后台作业)
Shell 脚本编程 I(变量、控制结构、循环、调试)
Shell 脚本编程 II(
cdialog
编程、函数、信号捕获trap
)grep
、sed
、awk
(从文件中提取数据,并进行各种处理,awk
编程)文件系统(在这一部分介绍 ZFS)
Ansible(安装、运行临时命令、编写 Playbook,并对多个 jail 并行更改)
这看起来可能不多,但对于 15 周的课程来说,内容已经相当紧张了。有人可能会质疑,“文件系统” 是否适合放在一门偏向编程的课程里。其实,这部分是我当年上这门课时留下的遗产,我认为用 ZFS 替代传统的文件系统概念是个不错的折中方案。
此外,Shell 脚本编程部分的内容被增补了,因为有些(但不是全部)教授会在操作系统必修课中讲解 Shell。我还增加了对话框编程(可以参考 FreeBSD 安装程序的界面来理解它的用途)、函数和信号捕获(trap)。这些内容相互配合得很好,因为 trap 机制通常需要在执行时调用特定的函数。
有些内容会随着时间推移而调整,这取决于我的兴趣和学生的反馈。从现实情况来看,在一节 90 分钟的课上,考虑到提问和讨论,每张幻灯片大约需要 2-3 分钟,因此大概只能舒适地展示 40 张幻灯片。
课堂教学模式
当疫情爆发后,这种传统的授课方式变得难以实施,所以我和大多数同事都转向了翻转课堂(Inverted Classroom)模式。
在这种教学模式下,学生需要提前自学课程内容,而课堂时间主要用于解答问题和讨论难点。这种方式让教师能够提供更丰富的材料,同时利用课堂时间来判断学生是否遇到了共性问题,并进行集中讲解。
当然,这种模式也对学生的主动性提出了更高的要求。如果课堂上没有太多问题,我会假设他们已经理解了(这对内向的学生可能不太友好),然后进行一两个演示——通过投影仪/视频会议共享我的终端。
我发现学生们很喜欢这种方式,因为他们可以立即在自己的机器上尝试,还能看到我犯错误(毕竟人无完人)。相较于传统的“逐张幻灯片讲解”方式,这样的课堂更加动态,也更具吸引力。
课程内容会根据学生的反馈不断添加和更新。如果我发现学生对某个概念感到吃力,我会额外准备几张幻灯片来帮助他们理解。这也取决于学生是否有相关的基础经验,或者完全是 Unix 新手。总体来说,即使是经验丰富的 Unix 用户,在课程中也能学到新东西,所以有些学生以前接触过 Unix 也没有太大影响。
通常,ZFS 和 Ansible 对学生来说都是新颖且令人兴奋的内容,尤其是 ZFS。很多学生在后来(比如进入硕士阶段时)都会告诉我,他们很高兴当初学了 ZFS,还在家用 NAS 上应用了它。
实验课
实验课的目的是让学生通过实际操作来证明他们理解了某个主题,并能够将其应用到具体问题中。学生通常以两人一组合作,并向我展示他们的成果进行评估。所有 5 次实验都必须完成,才能参加期末考试。
实验内容会紧跟课程讲授的内容,但有时也会涉及课堂上没有讲解的部分。这些内容可能是因为太细碎而不适合课堂讲解,或者是一个独立主题,不便纳入课程主线。
实验任务通常包括:
熟悉系统(了解 Unix 的基础概念)
编程练习(或者在此之前,创建有用的 shell 管道)
文本处理
修改系统配置 等类似任务
对我(教师)来说,最难的实验一直是第一个实验——安装 Unix 系统。
原因? 我们的学生通常分为两类:
一部分学生甚至连最基础的安装程序都会卡住;
另一部分学生则早已把系统配置得完美无缺,进入实验室 5 分钟就完成演示,然后直接离开。
如果学生之前安装过任意一款 Unix 发行版,那么 FreeBSD 的特定部分通常很好上手。但如果是初次接触 Unix,新手可能会觉得很难。
第一节实验课的目标是让所有学生最终都拥有一款能用的系统,以便后续课程跟上节奏。待所有人都成功安装了系统,后续实验的难度就会大大降低,因为大家都在同一基础环境上进行练习。
多年来,我尝试了不同的实验教学形式,以找到最适合的方法,既让新手不会被压垮,同时又不让有经验的学生感到无聊。
起初,我使用投影仪,在 VirtualBox 虚拟机里演示安装过程,边操作边讲解相关概念和术语。这种方法部分有效,但也存在问题——有经验的学生往往会直接跳到下一个步骤,而新手则还在听我讲解。这种情况最终让安装指导变成了一场额外的讲座,而不是实验课本身。
后来,我改用另一种方式——提供一份安装后的系统要求,例如:特定的分区布局、一个独立于 root 的本地用户,以及可用的网络连接。
然而,这种方法带来的结果五花八门,尽管所有学生都使用了相同的虚拟硬件平台。有些学生到了 14 天后的实验课忘记了自己的密码,有些人分区划得太小,导致无法安装任何软件。此外,作弊也变得更加容易,因为学生可以直接共享已经配置好的虚拟机映像,然后其他人只需导入即可。
更重要的是,学生并未真正理解安装过程。他们只是一路按回车键,完全不了解背后发生了什么(如分区操作、DHCP 网络配置等)。
手动安装方案
为了解决这些问题,同时让学生更深入理解系统安装的细节,我决定让他们手动安装系统:
进入 shell,手动设置分区
解压 FreeBSD 源码
配置基础网络
安装 bootloader
同时,我还提供了详细的说明,解释每个命令的作用。
为了防止作弊,我要求他们在 gpart 中用 VirtualBox 生成的唯一磁盘 ID 来标记分区。这样,每个系统都有自己的 ID,我可以轻松检查是否有重复的安装配置。
这套方案在一定程度上有效,但仍然有一些挑战:
有些学生安装完后重启,却发现系统无法启动,可能是因为不小心把引导代码写到了错误的分区(例如写到了 swap 分区)。
有些学生中途暂停虚拟机,做其他事情后再继续安装,结果发现 FreeBSD ISO 提供的虚拟 CD 盘已经被卸载,导致所有输入的命令都报 “command not found”。
还有些学生安装完后,一直只是挂起虚拟机而不重启,直到几周后第一次重启,才发现系统根本无法启动。而最糟糕的是,他们所有的解决方案都存储在这个无法启动的系统里。
这些学生通常会来问我如何修复他们的安装问题,而我则需要在几个月后回溯他们的具体安装步骤,来找出问题所在……
尽管我后来在手动安装指南中加入了虚拟机快照的建议,以便学生能随时回滚,但问题依然存在。很多学生不看我的讲解,而是直接翻到下一条命令输入,完全忽略 12 页的详细说明(包括示例图片)。这显然违背了手动安装的初衷——帮助他们理解 FreeBSD 安装过程及其组成部分。
当然,新手在这个实验上的挣扎远多于 Unix 经验丰富的学生。不过,好消息是,大多数学生最终都能顺利完成实验,只有少数学生遇到困难。
后续的新实验模式
目前,我正在和一个小型学生团队合作,尝试新的实验课模式。我们计划给每个学生提供一个预配置的 jail 服务器,其中运行着某个应用程序。
学生的任务是:保持该应用正常运行,而我的任务是在他们的系统中注入各种故障,让他们找到并修复问题。
为了增加挑战性,我们会引入全球排行榜,根据学生团队解决问题的速度进行排名。我们设计了自动检查程序,它会扫描系统,判断注入的错误是否已被修复,并给予相应分数。
此外,我还可以为每个团队注入不同类型的错误,甚至同时引入多个故障,例如:
关闭关键服务
移除执行权限
删除关键文件
这些故障的可能性几乎是无限的(至少在我的设想中是这样)。
核心目标是:
让学生学会如何维持系统的正常运行,而不是一开始就被安装过程绊住(这更符合企业环境的实际情况)。
让他们掌握常见错误的排查与修复,提升问题诊断能力。
目前,我们仍在完善实验细节,但我相信这将会是一种更有趣、更具挑战性的学习方式。
考试
要谈论考试,又不能透露太多具体内容,该怎么说呢?
自从几年前我改用全英文授课后,学生们一直担心自己听不懂考试题目。但事实证明,这并不是问题。考试题目通常与编程相关,比如:“找出这段短小的 shell 脚本中的错误”,这种形式能很好地弥合语言障碍。此外,考试还包括:
多项选择题
填空题
编写一个简短的脚本
解释 ZFS 里的 CoW(写时复制)是什么意思
到了这个阶段,学生们已经熟悉这些题型。从成绩来看,新手和有 Unix 经验的学生在本课程中获得好成绩的机会是相同的。我无法判断后者是否有认真复习,但可以肯定的是,完全不复习并不能保证好成绩。
考试通常是实验课内容的变形,这也让我能看出实验中谁真正做了练习,谁只是“搭顺风车”。虽然这对学生和我来说都是个迟来的真相,但有时候我的直觉也未必准确,考试成绩往往能带来意想不到的结果。
考试后的反思
评分完成后,学生可以查看自己的试卷(尽管他们很少会这样做),课程就算正式结束了。但这并不意味着老师的工作也就此告一段落。
由于这是一门每年开设的课程,我会在暑假期间反思和调整教学内容,基于课堂和实验课中的反馈,优化甚至完全重写某些部分。一般来说,我会重点修改:
在实验课上引发大量提问的内容
在考试中学生提出的小问题
同时,我也会关注 Unix 领域的新发展,寻找值得加入课程的新内容。在系统管理工作中,我偶尔会遇到一些有趣的代码片段或问题,之后就可能把它们改编成考试题目。暑假里收集这些材料,不仅能让我自己保持新鲜感,也能为下一届学生带来更丰富的课程体验。
因此,连续两年的课程很少会完全一样,否则不仅我自己会觉得无聊,学生们也可能通过往年的实验和考试答案轻松蒙混过关。
课程的局限性与调整
我是否能教授 Unix 的所有内容,或者所有我认为学生应该掌握的知识?当然不可能。我所能做的只是揭开 Unix 的一角,希望学生能对它产生兴趣,在课程结束后继续深入学习。
一些更高级的主题由其他老师负责,例如:
云应用开发管理
Rust 语言的系统编程
其他选修课涉及的进阶内容
偶尔也有学生抱怨我没有讲 Docker,但我会提醒他们,我们已经学习了 jail,它同样具备强大的功能。
课程内容也需要适应时代发展。例如,几年前,我们仍然需要在另一门课程中介绍 HTML 基础,但现在大多数学生已经在学校和业余时间接触过它了。类似的情况也发生在硬件知识上——许多学生从未自己组装过电脑,只使用过成品机器。因此,当我们讨论 CPU、RAM 和存储之间的交互时,这些内容对他们来说可能是全新的,尽管它们已经包含在操作系统必修课里。
如果学生只使用平板电脑,或者只熟悉图形界面,那么让他们适应纯文本的 shell 界面(一个闪烁的光标)可能会很困难。但这不仅仅是 FreeBSD 课程的问题,因为每种 Unix 系统最终都会依赖 shell 交互,即使它们运行在功能齐全的 GUI 上。
课程的意义
尽管 Unix 在操作系统课程中也有所涉及,但那些课程通常更关注:
调度器的工作原理
MMU(内存管理单元)的功能
系统调用在编程中的作用
相比之下,我的课程更贴近实际,专注于 Unix 作为日常操作系统的使用。
这门课程当然并不完美,需要不断适应变化。但我喜欢它现在的形式,学生们似乎也很喜欢。
Benedict Reuschling 是 FreeBSD 项目的文档提交者,同时是 文档工程团队 的成员。他曾连任两届 FreeBSD 核心团队 成员,并在德国达姆施塔特应用科技大学管理一个大数据集群。此外,他还为本科生教授《Unix for Developers》课程,并担任 BSDNow.tv 播客的联合主持人。
最后更新于
这有帮助吗?