一个 CS 基础薄弱的科班生的自白
上学的时候,我一直以为自己挺厉害。明明根本不知道CS基础有多重要,却只顾着拼命拿高分。
我也算认真上过专业课,还拿过校内编程竞赛和毕业设计比赛的奖。每当同学们被代码报错折磨得直皱眉时,我还会在旁边指点江山,心里暗暗觉得自己高人一等。但现在回头承认吧,我当时做出来的东西,不过是小孩子过家家。
因为觉得接入一个像样的数据库 (DB) 太难,我就把数据直接用逗号 (,) 分隔,存进记事本 (.txt) 文件里。需要操作系统级控制的 Raspberry Pi 也嫌麻烦,于是随便换成写几行代码就能跑起来的 Arduino。老师们看到那些表面上看起来还不错的成果便夸我,我也就误以为那真是自己的实力。
靠死记硬背闯过的面试,正是悲剧的开端
可一旦真正被扔进就业市场,这种毫无根据的自信立刻碎得一地都是。简历一份接一份地被拒。所谓竞赛获奖的头衔,根本遮不住我那贫弱的CS基础。
越是焦虑,我越执着于堆砌这种华而不实的知识。理解被我放到一边,我像机器一样死背标准答案,只求先把面试混过去。从技术博客里抄来的“面试高频 100 题”,成了我的教材。
当面试官问我“TCP 和 UDP 的区别是什么?”时,我像自动售货机一样开口就来:“TCP 是面向连接的,能保证可靠性,但更慢;UDP 是无连接的,更快,但可靠性更低。”
其实我根本不知道什么是数据包,也不知道 3-way handshaking 在真实场景里到底怎么发生。可讽刺的是,正是这种机械式背诵帮我糊弄过了面试官,拿到了还不错的分数,也顺利找到了工作。我以为那只是运气。却不知道,那正是我四年欠下的账即将一次性清算的悲剧开端。

小团队里的全栈求生记
我加入的是一个小团队。那里根本没有什么“前端”或“后端”这样体贴的分工。
入职第一天起,我就不得不直面像海啸一样扑来的技术栈。我原以为只要把 Java 或 JavaScript 其中一个学好就够了。可现实却是 Linux SSH 终端的黑色屏幕、来历不明的 Docker 容器、GitLab CI/CD pipeline,以及 Spring Boot、Vue.js、Redis……那些学生时代被我以“以后再学吧”推开的,或者被我用“这个不用懂也行”轻轻带过的技术,开始从四面八方向我袭来。
那些面试时背得滚瓜烂熟的知识,在实际工作里根本派不上用场。或者更准确地说,我根本不知道该怎么把它们用起来。想弄明白我启动的 Docker 容器为什么总是挂掉 (OOM),Redis 又为什么会不停蚕食内存,我真正需要的,恰恰就是那些曾经为了应付面试而死记硬背的CS基础。
建在沙地上的城堡
到头来,我成了一个见什么都复制粘贴 (Ctrl+C, V) 的“复制粘贴型开发者”。功能倒也勉强能跑起来,但我根本不知道它为什么能跑。
因为不懂那些藏在框架便利性背后的原理,一旦出问题,我就完全没有解决能力。我等于是在贫弱的CS基础这片土地上,用华丽的框架堆出一座摇摇欲坠的城堡。

Re: Booting,回到起点
所以,我决定重新回到最初的起点。比起现在马上再做一个花哨的作品集,我更迫切想先解决那个本质的问题:“计算机到底是怎么理解并执行我的代码的?”
这个博客记录的,就是一个只有文凭却没有扎实基础的科班生,如何从零重新搭建CS基础的过程。我不会只是罗列 Linux 命令或 Docker 安装教程,而是想把自己提出下面这些问题、再一步步找答案的过程写下来。

不止于 localhost
最终目标,是亲手搭建并掌控 Linux、Docker、CI/CD,乃至云环境本身。我要走出名为 localhost 的安全温室,成为一个即使置身野外般残酷的服务器环境里也能活下来的工程师。
如果你也和过去的我一样,总说“学校里学过,但现在想不起来了”,那我希望这份记录能成为一个小小的路标,让你在某个瞬间拍着大腿说出:“啊,原来老师当时讲的就是这个意思!”