现在想想,要是我能在从业早期掌握到 Linux 服务器基础管理知识就好了。其中最有价值的就是 Web 托管方面的技巧,肯定能让我自己编写的、或者直接从技术社区那边拿来的 Web 应用程序和 API 更上一层楼。
时至今日,很多人觉得服务器管理已经是过时的老一套——用不着学习设置 VPS、建立远程访问、部署防火墙,我们照样是个合格的软件开发者……真的是这样吗?
我发现如果不懂得如何自主管理基础设施,那我们就很难选择正确的工具方案。今天的文章将从多个维度,广泛地讨论这个颇具现实意义的问题。
首先是最直观的二元维度,新还是旧、购买还是自建?由此延伸出的真正问题,就是我们该选托管服务、还是非托管服务——这也正是本文的讨论核心。
在争论的一端,我们当然可以像千禧年之前那样自己动手管理一切:自己设置主机、安装并管理依赖项、建立备份等等。而在另一端,我们可以看到支持者列举出从 Amazon RDS 等轻度管理要素,一直到 AWS Amplify 或 Google App Engine 等充分发挥云优势的全功能应用框架,乃至 Heroku 等 Baas/PaaS 服务商给出的解决方案。
结合工作经历,我发现大多数人会默认选择托管方案,借此节约项目工程量。但倒退回十年前,一切便利选项还根本不存在的时候,开发者到底是怎么让项目顺利上线的?
事实上,那时候的小团队、甚至个人开发者也能顺利构建起高流量 Web 服务。Marco Arment 就在文章中回忆过 2010 年左右建立和运行 Tumblr 的经历,那时候他能指望的基本就只有自己:
Tumblr 项目经历让我了解到在缺人手、缺资金的开发早期,怎么才能更便宜、更轻松、更理性地开发并托管高流量 Web 服务。我得想办法减少服务器的维护需求,因为我确实没法在管理上分出太多精力——开头的几年里,我们连专门的服务器管理员都没有,所以我只能想办法让系统具备免管理特性。
好消息是,其中提到的工具和技术现在仍然可用、也适用。所以我建议大家能转变一下思路——别默认使用高度托管的服务,而是优先选择自管理服务。除非有明确的理由,否则别急着把掌控权交出去。
服务器管理的衰落
如果大家和我一样,都觉得服务器基础维护已经是门濒临失传的“秘技”,那这套秘技究竟是怎么发展完善、又逐渐衰落的?有些朋友肯定会把矛头指向大型云服务商,“他们就是要出傻瓜式方案,让我们变得越来越笨!”这就有点阴谋论了,不至于不至于。其实答案很简单,AWS、GCP 与 Azure 砸下了几十亿美元的营销预算,我们的观念哪经得起这样的银弹冲击。他们的开发布道师部队阵容强大,再加上每个人多少都有的“船货崇拜”与急于迭代的心态,现实就变成了现在这个样子。
在探讨学习 Linux 基础管理知识的好处之前,我想澄清一下——这绝对不是那种非黑即白的二元命题。工程挑战的实质永远在于权衡,比如在之前推荐的文章中,我们能看到很多开发者为了适应自己的规划而自建硬件,这就比较复杂了。除非真的需要性能,否则最好别进物理硬件这个坑。选择一家信誉良好的托管服务商,直接用 Linux VPS 应该更靠谱些。
但也别矫枉过正,抱持什么“云就是罪恶”的念头。我知道大家都多少读过这类文章,喜欢把云服务商一棒子打死。别傻了,这十年来大型云服务商们给我们带来了真切的助益与创新,这是不可否认的事实。总之,分清自己的实际需求,比如我肯定不想构建实时数据库,那就不妨学学如何自主托管 MySQL。
从 Linux 管理知识中获益
无论如何,现在很多开发者已经不知道怎么运行自己的服务器了。我们为什么要改变这样的现实?下面是我自己觉得比较重要的几个理由。
摆脱供应商锁定。如果大家在 Linux VPS 上运行整个系统,也就相当于选择对计算层进行了商品化。如果当前服务商出了什么问题,我们可以随时打包搬走、把工作负载转移到其他平台。
无限计算。Netlify 只能托管一个 repo,Lambda 只能运行一个函数。Linux 管理工作确实是件苦差事,但作为回报,我们的计算空间得以无限扩展。我们能够安装任何自己需要的软件,并按自己认为合适的方式进行设置。有时候,我们还能在同一套基础设施上运行全部自有应用程序,通过回避按应用计费来省下一笔开支。
历久弥新的基础技能。技术行业发展迅速,但纵观整个历程,我们总能发现一些历久弥新的基础技术。Bash、SSH、Nginx/Apache,也包括 Linux 本身。所以毫无疑问,这些基础技能将伴随我们的整个职业生涯。在技术行业,有些本事就是有用、就是该学。无论什么岗位,能早点掌握 Bash 脚本都是件好事。与之对应,云服务技能则显得比较“廉价”——我没有别的意思,只是这类技能确实过时得很快,其形态总在变化、早期版本会迅速被淘汰。
工具的速度和乐趣。这也是最打动我的一点。请注意,这里我把“工具”和“服务”区分了开来。锤子就是一种典型的工具,我可以完全按自己的方式使用锤子,所以它就成了我身体的延伸。相反,服务会反过来约束我、包围我,跟我争夺主体地位。现在的开发者服务用得太多,反而忘记了用工具的感觉。Linux 就是工具,Bash 也是工具,它们既安静、又听话,对使用者唯一的要求就是适当做一点贡献。而且只要使用娴熟,它们的效率也很高。所以我的理论是:学习这些工具能培养开发者的灵活性,锻炼我们通过自主托管发掘生产潜能的能力。
如何起步
起步并不难,但我们也需要制定计划。跟学习编程差不多,我建议大家把想学的 Linux 管理员技能整理成一个项目。为了推进项目,我们就会自然而然地完成学习。管理 Linux 服务器其实不需要太多编程技能。如果你已经是位程序员,那整个学习就像决定在 Linux VPS 上运行自有软件一样简单。如果你丝毫不懂编程,也可以从各类具有强大技术社区背景的开源项目中做出选择。对于实在没有思路的朋友,这里我向大家推荐 Home Assistant、Pi-hole 外加一份参考项目清单。
我还建议大家,选择并提交一套包含操作系统、Bash、脚本语言、Webserver 以及数据存储的“默认管理堆栈”。就像在 MacOS 或 Windows 上进行个人计算一样,大家还需要选择特定的 Linux 发行版作为默认服务器操作系统。每种系统的高效操作都需要一段时间的熟悉,所以最好认真选择、然后一直坚持下去。例如,我个人的首选操作系统就是 Ubuntu——它拥有庞大的技术社区,对初学者来说更易于上手,而且我想托管的一切几乎都有相应的官方 Ubuntu 支持。
至于脚本,建议大家先搞定 Bash。Bash 是大多数 Linux 发行版的默认“shell”。可能有的朋友不清楚,shell 是负责运行其他程序的程序,所以玩转 shell 层真的非常重要。
Bash 是命令行终端的主要界面,本身也是一种脚本语言。大家最好把终端命令保存在文件中以代后续使用,这样就能一次设置、随时运行。这种好习惯能不单能清晰记录下我们的设置选项,也能大大提高运营自动化水平。总之,一定要学好 Bash、一定要用好脚本!这里还建议大家完成一项随堂作业:尝试用单一 Bash 脚本重建整个主机。
在 Bash 当中,我只想强调一项功能:here documents。在服务器上,我们需要设置的大部分内容都要借助文本文件完成配置。Here documents 允许我们在脚本文件中指定“内联文件”。大家应该理解什么是字符串文字,而这里的文档可以理解成“文件文字”。这里有一个设置远程SSH访问的示例,你也可以点击此处参考另一个为 MySQL 创建数据库与管理员用户的示例。正是掌握了 here documents 之后,我才从普通 Bash 用户成长为初出茅庐的系统管理员。真希望自己能早几年就掌握这些知识。
Bash 的历史比较悠久,所以跟其他现代编程环境相比,它的很多设计确实比较粗糙。例如,如果你是一位程序员,很可能会理所当然地认为每种脚本语言都该有字典/哈希映射,对吧?但这种关联数组直到 Bash 4 才正式出现。而部分较早的系统将 Bash 3 作为默认版本,所以除非安装更新版本的 Bash,否则就没有字典可用。
关于 Bash 的优势,我特别赞同谷歌发布的 Shell Style 指南中的说法:
如果你正编写一个超过 100 行的脚本,或者使用某些非直观的控制流逻辑,则应该用更加结构化的语言进行重写。请记住,脚本一定会越来越长,所以早点重写脚本、你就能避免在未来必须重写时浪费更多时间和精力。
如果你不是专职程序员,那掌握 Bash 也就基本够用了。但如果大家需要编写更长的脚本,那在选择默认服务器操作系统之后,接下来要面对的问题就是选择默认脚本语言。
理论上,任何能与操作系统交互的语言都可以作为脚本语言,所以大多数编程语言都能完成任务。例如,MySQL 中附带一个名为 mysql_secure_installation 的脚本。其最初版本是用 Bash 编写的,但随着脚本的增长,它又经历了用 C++进行重写。这对该项目本身是个不错的选择,毕竟 MySQL 本体就是用 C/C++编写的;但在选择默认脚本语言时,C++绝对不是什么好主意。
在选择脚本语言时,我推荐大家优先那些不需要编译的语言,而且背后最好有个强大的技术社区。Python、Ruby 和 JavaScript 都是不错的选择。我个人最终选择了 JavaScript,两个理由:第一,它学习难度较低,不用花太多时间;第二,我的 Web 开发工作本来就要求掌握 JavaScript/TypeScript。如果还有其他更复杂的需求,Node 还通过 npm 提供了庞大的软件包库。
如果你身为 iOS 开发者,尽管我也很想推荐 Swift,但它真的不善于实现 Linux 管理。虽然 Linux 的支持效果越来越好,我们现在已经能像常规脚本语言那样使用 Swift 并回避编译步骤,但 Swift 的包管理器跟 NPM 相比还是差得太远,所以在 Linux 管理方面比较孱弱。
在选定了操作系统、学会 Bash 并指定了脚本语言(可选)之后,下面要面对的问题就是 Webserver 和数据层了。请注意,这一切只局限于服务器管理范畴之内。如果你不是专职程序员,就没必要迈进数据库这个“大坑”:)
我选择 Nginx 作为默认 webserver,但我听说 Apache 其实也不错。在掌握了 webserver 之后,它就能帮我们把流量引导到自己的应用程序。至于默认数据库,我选择了 MySQL。理由很简单,MySQL 的历史足够悠久,我的一切需求对它来说都是小菜一碟。
这里要重申一下,对于刚刚起步的朋友,选择托管什么、要比选择托管的工具更为重要。最好让应用程序指引我们需要优先学习哪些内容。如果实在不知道该用什么来托管第一个应用程序,那 WordPress 永远是个不会出错的选项。虽然很多托管服务都提供一键式 WordPress 安装选项,但一旦出现问题,我们根本搞不清要怎么调整设置来进行修复。所以作为初步目标,最好试着用单一脚本在新主机上安装 WordPress。