陈颂光
全栈工程师,能够独立开发从解释器到网站和桌面/移动端应用的各类软件。
关注我的 GitHub

了解GNU/Linux系统

我们讨论的是GNU/Linux系统,而不只是Linux内核。

历史背景

自由软件运动与GNU项目

Richard Stallman于一九七一年开始为麻省理工学院(MIT)人工智能实验室工作时,当时软件的分享还是普遍的:如果你看到某人正在使用一个你不熟悉但却有趣的程序时,你总可以要求参阅其源码,因此你可以读它、修改它、或者对它加以拆解拼装制成一个新的程序。这种情形在一九八○年代初期彻底地改变了:即使只是获得一个可执行代码拷贝,你也必须签署一个保密协议。但RMS坚持,如果他喜欢一个软件,他就应该与所有同样喜欢它的人分享它。

在RMS看来自由软件应当满足以下要求:

  • 你有自由为任何目的去运行该程序。
  • 你有修改该程序以满足你需求的自由。(为使该自由可以有效地实施,你必须可取得源码,因为在没有源码的情况下对一个程序做修改是非常困难的。)
  • 不论免费或收取一定费用,你有重新散布拷贝的自由。
  • 你有散布该程序修改过的版本,从而让社会得以受益於你的改进的自由。

RMS决心重建互助的黑客社群。为此,他首先需要的是一个操作系统,因为它是开始使用一台计算机的至关重要的软件:没有操作系统,你完全不能运行计算机。作为一个操作系统开发者,RMS有做这个工作的恰当技能。RMS选择将该系统做成与Unix兼容从而可移植,并使众多Unix用户可以容易地转换到它。 GNU 这个名字,依照黑客的传统选中,作为一个递归的“GNU’s Not Unix”首字母缩写。

由于GNU的目标是给用户自由,而不是仅仅流行,GNU禁止了剥夺用户自由的自由:阻止 GNU 软件被转变成私有软件。GNU给予每个人运行该程序、拷贝程序、修改程序和散布其修改版本的许可,但是没有增加他们自己的限制的许可,这方法被称为“copyleft”。大多数 GNU 软件使用GNU通用公共许可证(GNU GPL)。

一九八四年一月RMS辞去在 MIT 的工作并开始编写 GNU 软件。开发一个完整系统是一个很大的工程。一个操作系统指的不仅仅是一个刚足够运行其他程序的内核,还包括命令处理器、汇编程序、编译器、解释程序、调试器、文本编辑器、邮件程序以及其它许多程序。为了使其达成,RMS决定只要尽可能利用现有的自由软件。例如,用 TeX 作为主要的文本格式化程序、用 X Window 系统而不是为GNU写另一个窗口系统。开始时,RMS决定写一个多种语言、多种平台的编译器GCC。为此,RMS又开发了编辑器GNU Emacs,使得他可以开始使用 Unix 系统作编辑。

在一九八五年,RMS创立了自由软件基金会。 FSF 也接手了 Emacs 磁带发行工作,后来它通过往磁带上增加其它自由软件(既有 GNU 也有非 GNU ),也通过出售自由手册扩展了该业务。自由软件基金会员工们已经参与编写和维护了一系列的 GNU 软件包。一些其它组织也给予了支持。

随着越来越多人和资金的投入,一个又一个Unix部件有了自由的替代品,而且质量往往超越原来的。一九九○年, GNU 系统几乎已经完成:唯一主要遗漏的部件是其内核。他们决定将内核实现成在微内核Mach之上运行的服务器进程集合(GNU HURD)。开发的启动由於等待Mach如其许诺的那样被作为自由软件发行而延误,又因技术困难推迟了投入实用的步伐。

GNU Hurd 还没有准备好可以作为产品使用。幸运的是,另一个内核已经可以取得。在 一九九一年,Linus Torvalds 开发了一个与 Unix 兼容的内核并称之为 Linux 。大约在一九九二年,将 Linux 与不是非常完整的 GNU 系统相结合产生了一个完整的自由软件操作系统。由於 Linux ,我们今天因此可以实际运行一个 GNU 系统的版本。称此版本的系统为 GNU/Linux ,以表达它是 GNU 系统和以 Linux 作为内核的组合。

当一九九八年一些企业由于商业考虑决定停止使用术语“自由软件”并改为说“开放源码软件”时,GNU项目继续使用“自由软件”这个术语,因为在技术上优越性的侧面背后,根本的原则是自由。

即使面临私有标准、软件专利、规范保密的硬件等威胁,自由软件运动没有停步。当今有数千万的用户使用诸如 Debian GNU/Linux 和 Red Hat Linux 的 GNU/Linux 系统,连Window 10都有个Linux子系统。自由软件已经发展到了这样实用的优势,使得用户纯粹为了实用原因而聚集到它身边,但自由不能被遗忘。

Linux

来自芬兰的大学生Linus Torvalds希望在他的个人计算机上使用类Unix,他尝试过Andrew S. Tanenbaum的MINIX,但为教学目的设计的MINIX不能满足他的需要,于是他决定自己写一个。很快,他在1991年9月发布了Linux的0.0.1版。关于Linux更详细的缘起,请看Linus Torvalds的自传《Just For Fun》。

其实,有同样想法的人很多,于是人们开始聚集到Linux,通过修正错误、增加功能、移植等方式完善Linux。不久,许多企业也看到Linux的价值并积极支持其开发,Intel、IBM等企业投入了大量资金、机器和全职人员,红帽公司就凭Linux起家挤进500强企业。

很难说Linux本身有何优越性(至少其它Unix比),再说各系统在相互抄袭下趋同。很坦白地说,Linux的成功有太多机缘巧合的因素。

  • 如果GNU HURD更早可用或者BSD没有惹上AT&T的官非,Linux很可能不会获得注意,甚至也许Linux根本不会存在。
  • Linux为PC而生,但却在服务器(LAMP的L)和移动设备(Android)领域取得了主导地位。
  • 在提倡微内核的90年代初,Linux的模块化设计可谓逆潮流而动。

Linux的成功更多归因于历史因素:丰富的软件生态、支持硬件的多样、庞大的用户群和活跃的开发者群体,这些基础是前期投入的结果。也就是说,Linux在恰当的时候利用难得的机会立了脚跟,然后开始正反馈的惯性,正如微软的windows一样。

设计

GNU/Linux沿袭了Unix的精神。Unix出自1970年AT&T的贝尔实验室,由于吸收了Multics(Multiplexed Information and Computing Service)目标太大以致过于复杂,最终失败的教训,Unix(UNiplexed Information and Computing Service)采取了简化的设计。Unix的哲学是“Keep it simple, stupid”(KISS原则),所以Unix有很多细小的“做一件事并做好”的工具,用户把不同工具通过文本文件组合起来完成各种任务。在符合POSIX标准的意义下Linux可算是兼容unix。

Shell

Linux的常见命令见[[Linux命令简介 Linux命令简介]]。Shell则作为命令的粘合剂把命令组合起来,其中一种常用的shell参见[[BASH语言简介 BASH语言简介]]。其中,两部分不是分离的,而是密切配合的,Unix命令大多也被设计成过滤器就是为了便于用管道接起来。事实上,可组合性正是命令行界面与图形界面相比的核心优势。

作为一个例子,我们找出文本文件LICENSE中出现次数最多的十个单词:

$ tr "A-Z ,.\"\`\'()" "a-z\n" <LICENSE | tr -s "\n"| sort | uniq -c | sort -nr | head
    345 the
    220 of
    189 to
    184 a
    146 or
    128 you
    101 license
     97 work
     93 and
     91 that

这甚至给人一点函数式编程的感觉:命令即函数、标准输入对应自变量、标准输出对应因变量。协程和惰性求值也呼之欲出。管道可能比函数式编程语言的通常实现更有效地利用内存和CPU。值得注意的是,管道中各命令对应不同的并发进程,也就是说,我们不费吹灰之力就用上了多处理器或多核的能力。

由于在二进制格式上难以取得一致,所以UNIX严重依赖文本,从配置文件到通信协议。为了更有效地处理文本(首先是解析),UNIX还常与各种小语言结伴前行,不过这种紧凑的写法有时也会变得难以阅读。

Linux文件系统

一切皆文件是Unix的又一特点。Linux的文件系统是树状的(链接下面考虑),其节点叫文件,其中可以有子节点的也叫目录。要定位一个文件,可以用其路径:

  • 绝对路径由/开首,然后依次列出从根(不含)到该文件(含)的节点名称,用/分隔。例如登录密码存在于文件/etc/passwd
  • 给定当前目录,依次列出从当前目录(不含)到该文件(含)的节点名称,用/分隔。例如设当前目录为/usr,则文件/usr/include/stdio.h的相对路径为include/stdio.h

另外,可以用...分别指代当前目录和上一层目录。例如设当前目录为/bin,则文件/usr/include/stdio.h的相对路径为../usr/include/stdio.h。把...消去的过程称为路径的规范化(忽略这点已经导致不少安全漏洞)。

Linux中根目录的以下子目录约定用于特定用途:

目录 用途
bin 基本的可执行程序
boot 启动用文件(引导程序和内核映像)
cdrom 光盘
dev 设备
etc 全局配置
home 用户目录
lib 基本的库
lib64 基本的64位库
lost+found 没有正常链接的文件(如由于强行关机)
media 热拔插介质如U盘
mnt 常用其子目录作临时挂载点
opt 可选程序
proc 系统信息
root 根用户的用户目录
run 服务
sbin 基本的可执行程序(需特权)
srv 系统启动服务用
sys 存放内核文件
tmp 存放临时文件(重启不保留)
usr 大部分软件
var 存放常变的文件(如日志、信箱)

有兴趣不妨浏览一下。

有一种称为符号链接的文件,大多数Linux工具会跟符号链接走到它指定的文件,符号链接可以跨越分区。硬链接则是更低层的手段,让多个文件平等地指向同一存储表示,删除其中一些文件后仍可通过未删文件访问内容(相反,删去符号链接的目标后,不能通过符号链接访问原来内容)。

另外,以.开首的文件默认是隐藏的。

值得一提的是,GNU/Linux支持的众多文件系统格式,不像Windows只原生支持FAT和NTFS,不过现在最常用ext4。

由于Unix是多用户系统,因此Unix有权限机制来防止用户间的意外干扰。基本的安全机制是,每个进程有一个有效用户ID和一个有效组ID(通常就是当前用户的用户ID和所在组ID,但有SUID机制),每个文件也有一个用户ID和组ID,并且指定了此用户、此组中用户和其它用户分别可以对文件做什么(读/写/执行)。只有root用户例外。

图形界面

虽然命令行有上述优势,但命令行下(即使有自动补全和文档系统)较缺乏可显性,用什么命令和如何用它往往不太明显,容易令新手手足无措。只有熟练后方能体现比图形界面方便高效之处,也要求少许记忆力。另外,一些任务如图像处理在图形界面下也许更自然。所以,UNIX下也有图形界面。

UNIX的图形界面多半基于始于1984年X windows系统,独立于内核。由策机分离原则,X window采用客户端-服务器设计,X window客户端向X window服务器发基本的绘图命令,由后者负责绘制。这种设计很灵活,如不同客户端可以完全不同的风格绘制窗口(看看GNOME、KDE、XFCE有多不同)、客户端和服务器可以在地球两端、一个服务器可对应多个客户端,但效率有时略为不及其它架构。现有X window的状态见X.org,一个雄心壮志取代X的项目是Wayland

处处让用户选择,这给予了用户自由,同时也会使他们不知所措。

使用GNU/Linux

GNU/Linux发行版

我们所说的GNU/Linux操作系统不仅有Linux内核,还包括大量的实用软件,从GNU的Unix工具到服务器软件或应用程序。为方便安装,人们把内核和各种软件打包成为可一次性完成安装的形式,这就是GNU/Linux发行版。现在较有影响力的有:

  • Debian是元老级发行版之一,对软件包管理做出重大贡献,其仓库中软件包的数量领先,很多其它发行版都基于它。
  • Fedora作为元老级发行版Redhat Linux的继续,软件版本选取较进取,是同门倾向服务器市场的Red Hat Enterprise Linux和CentOS的试验场。
  • OpenSUSE以华丽为卖点的发行版,可追溯到元老级发行版Slackware。
  • Ununtu是以容易入门为卖点的发行版,有时会作标新立异的选择,基于Debian unstable
  • Gentoo是一个强调定制性的发行版,大部分软件以源代码形式提供
  • Arch是一个强调定制性的独立发行版,采用滾动发布

关于大量GNU/Linux发行版的对比,请看distrowatch。一般而论,我推荐Debian的最新稳定版。由于常见的GNU/Linux的安装器有清晰提示,并且有官方文档手把手教,这里不多说。

软件安装

虽然GNU/Linux发行版预装了不少常用软件,但有时还是不够。

来自软件仓库(首选方法)

Debian可说是现在各种软件商店的鼻祖,后来Redhat之类的发行版、Android、iOS和Windows都抄了过去,但debian的似乎仍然是最完善的,不管是包的数量与质量,还是包依赖的管理机制。

在Debian的软件仓库可找到几乎所有你可能需要的软件(只有极少数版权有问题或非常不流行的例外),用不着在网上乱搜。图形界面的“新立得软件包管理器”或命令行的apt命令都可用于装卸软件包。为了下载软件更快,请设置个好的国内源。

二进制包

如果你有Debian的deb包,双击它或用dpkg命令就可以安装。Redhat用的rpm包也可用类似方式安装。

对于其它形式的包,按厂商指示办或进行试探。

从源代码安装

一些软件以源代码压缩包(通常后缀如.tar.gz或.tar.xz)形式发布,而未有人把它打包成可用的二进制包或者或者希望针对当前机器优化。这时,按惯例,解压后进入解压后目录,再运行以下三条命令即可完成安装:

./configure
make
make install

其中,make install可能需root权限。当然,安装小众软件可能出难缠的问题。

如果软件作者标新立异,就看看有没有名字形如README或INSTALL的文本文件并查看其中指示。

关键词 gnu linux 操作系统