Tutorial | Linux生存指南

Table of Contents

1. 序言

「如果你没有认真地去尝试另一个系统,你会错过本来能看到的许多风景。它们不一定真的很美,或者让你值回票价,但这个世界上大多数的人都在big companies限定的路上使用电脑使用了一辈子。你确实安逸,但你从没看过道路以外的事物,而那才是真正的自由。

当你试图跨出那一步的时候,一开始必定都很艰难,但你并不孤单。在使用Linux的路上,你会找到热心的良师益友,嘴臭的世外高人,无数跟你一样的初学者,以及更重要的,你找回了当初那个勇于选择新道路的自己。

——要是不能选择的话,这世界也太黑暗了。」

1.1. 序言

为什么要把这篇Linux入门指南作为自己博客的开篇呢?

我从2018年6月开始正式使用Linux,所谓「正式」,就是彻底告别Windows,将自己笔记本电脑的操作系统换成Linux。我初次接触Linux比这更早一些,是大一还是大二已经记不清了。因此我并不是一开始就粗暴地甩开Windows直接投入Linux的怀抱。这看起来也不太现实,因为Windows和Linux(或者说Unix)之间的差别实在太大,如果没有一定的了解,是无法顺利把思维转换过来的。

我起初学习Linux的理由也许和大多数人不一样。我猜想大部分人学习Linux的原因是自己不得不用到Linux,比如要做智能小车,要架设或管理一个服务器,要做深度学习等等。而我只是因为觉得Linux很有趣。大部分说出这类话的人可能都是天才,我肯定是个例外。(Linus Torvalds因为觉得编程很有趣,写一个操作系统很有趣,所以写出了Linux。当然现在的Linux早就不是Linus一个人的功劳了。)我不过是一个不怎么会编程的「普通用户」,对一个开放且未知的操作系统世界充满好奇而已。

自己最初看的,是一部是个查过Linux中文教材的人都知道的教材——鸟哥的Linux私房菜。这部教材大而全,关于Linux的很多细节都覆盖到了,但是我没法完整读下去,因为其中的内容对初学者而言过于细枝末节,且其面向的读者是学习Linux服务器运维的人,这显然和我的初衷不符。我看了必要的一些章节后就自己在虚拟机上把玩,但也仅此而已。

2018年初,我决定尝试把Linux装在物理机上,和Windows并存(dual boot)。安装过程自己早已驾轻就熟,然而装好后发现操作系统的音频控制会出现莫名其妙的bug。经过网上的搜索,发现是自己电脑声卡或声卡驱动的问题,导致无法支持双系统,无奈之下只好移除Linux。还是活在Windows的世界最安稳啊,当时的我就是这么想的。但是对Linux的好奇仍然没有离开我。2018年6月,自己下定决心,换了系统。就这么简单。

然而当我走进这个崭新的世界后,我发现这个世界将自己引向了一个更大的世界——自由软件。很难形容这种奇妙的感觉,用一个不恰当的比喻,这就像是一个从前一心想成为富豪的穷人看到了共产主义,同时也看到了自己在社群中无法用金钱衡量的重要价值。

在这大半年间,自己也换过Linux发行版(distro hopping),遇到过无数问题,也为了解决问题或是发掘新鲜事物看了无数博客和Youtube视频,积攒了很多笔记。笔记的内容包括了很多问题解决(trouble shooting)的方法,Linux基础知识和一些工具的配置使用方法。而让我真正写一个入门指南的的原因,是给同学装操作系统和帮同学解决问题的经历。我费了一番功夫给没有任何技术需求的室友推荐Linux,并帮他安装。现在看来这么做有点蠢,因为不能说Linux优于其他操作系统,Linux也不适用于所有人,更不能强迫别人接受Linux的一切。而值得欣慰的是他现在已经完全适应Linux,并且不喜欢Windows了(笑)。在这个过程中,我渐渐明白一个真正的「普通用户」到底希望在Linux中得到什么。此外,帮其他有需求的同学解决问题时,我也感受到经验分享的重要性。在Linux或者自由软件的世界,经验分享无疑会帮助他人少走很多弯路,而这也是社区存在的目的。

让我真正走出写博客这一步的,是Sacha Chua写的一本小书,叫做A No-Excuses Guide to Blogging。我曾犹豫过是否真的要以这种方式分享自己的经验,因为感觉自己对这么一个深不见底的领域的了解实在太少太少了。但这本书中的一些话确实鼓舞到了我,让我感到经验的分享的必要性。我在下笔的同时,也希望自己能产出一系列高质量的文章,拒绝CSDN式复制粘贴,拒绝琐碎和冗杂,拒绝只有自己看得懂的自言自语。

总之,希望能以自己的绵薄之力帮到大家。

1.2. 目标和为什么学

不同的人因为不同的目的学Linux。无论你的目标是什么,只要你对Linux不太了解,并且有了解的兴趣,我都希望你能够在我的系列博客中有所收获。但是我还是想事先说明,我的系列博客的目标是:

帮助大家将Linux作为日常使用的桌面操作系统。

很多对Linux有所了解的人都会认为这有些荒唐,尤其在知乎这个「反Linux」情绪严重的平台。为什么荒唐?主要的理由集中在:

  • 学习成本高
  • 容易遇到很多问题,都需要自己投入精力解决
  • Linux的桌面环境不稳定
  • 没有多数Windows软件的支持

光是这四条就足以把人吓跑了。那为什么还要学习Linux,还把它作为日常使用的操作系统?我也给出我的理由:

  • 虽然学习成本高,但掌握后能显著提升工作效率
  • 用户控制系统,而非系统囚禁用户(对比Windows根本无法关闭的强制更新)
  • 自由软件生态(Linux本身开源免费,且其使用的所有软件几乎都是自由软件(开放源代码、免费、可自由修改和分发),并且你会发现日常使用的90%的商业软件,都有自由软件的替代品,并且能满足多数人的日常需求,这样就用不着费尽心思装那些只能用到其5%的功能的几个G的商业软件还要想办法破解啦!)
  • 遇到的问题容易找到简洁明了的答案,对症下药,精准打击(对比Windows的重启、软件重装、系统重装三连)
  • 不会中病毒
  • *最重要的一点:有趣*(最奇妙的事情莫过于自己成功解决问题后的感叹:「原来还可以这样!」)

那Linux桌面环境不稳定的问题呢?我的答案是:

没有其他商业操作系统那么稳定,但够稳定。

Linux的桌面环境是Linux中一个可有可无的组件。当然啦,要是把它作为桌面操作系统,这必不可少。桌面环境的不稳定,主要来源于过高的可定制性,比如你可以自己写主题或插件把桌面改成任何你想要的样子。但根据亲身体会,桌面环境崩溃或出bug的发生频率实在太低,低到完全可以忽略。并且抛去桌面环境这个不稳定因素不谈,Linux实在太稳定了,不然为什么世界上大部分的服务器都在用Linux?这个优势完全可以弥补桌面环境的瑕疵。(桌面卡死?切到另一个TTY用命令行重启桌面环境就行了。)

最后,Windows软件的问题?我的答案是:

多数软件都能找到自由软件替代品,还有一些Windows软件可以用通过WINE来运行。

如果不知道WINE是什么,别着急,在后面的章节会提到。大家关心的国内鹅厂出品的中国特色即时聊天工具可以在Linux上运行。至于Microsoft Office,这的确是Linux的软肋。虽说是软肋,这也是Microsoft亲手造成的,和Linux本身并无多大关系。理论上最好的替代品是Office Online,可惜国内OneDrive被墙,因此最好的替代品实际上是WPS Office。我明白这套软件会给很多人造成困扰,不过首先它能满足最基本的Office文档编辑需求,其次你今后会爱上纯文本文件,越来越少用Office。

说到这里,我相信仍然有很多人对Linux并没有产生多大兴趣,或者依然抱有疑惑。这很正常,因为Linux并不适合所有人。什么样的人不适合日常使用Linux?

  • 认为Windows或macOS的功能完全满足需要,且对Linux的世界没有多少好奇
  • 需要在Windows或macOS下完成*专业的*影音制作和编辑工作
  • 需要经常在Windows下玩游戏(即便很多在Steam平台的游戏,甚至Steam上的Windows独占游戏都能在Linux下,但使用Windows游戏仍然是一个更好的选择)
  • 不希望花费任何精力学习关于操作系统的知识、工具,也不愿意trouble shooting
  • 不能接受英文搜索和查阅英文文档

什么样的人适合使用Linux?

  • 对Linux世界好奇
  • 希望提升工作效率(尤其是编程工作)
  • 学习工作上的硬性需求
  • 注重隐私、希望得到自由
  • 反感其它商业操作系统的强制更新对计算机和工作造成的影响
  • 想要真正掌控自己的计算机
  • 没钱买Windows正版(我是在开玩笑)

为什么开头要这么啰嗦写这么多呢?就是怕有人看了好久然后觉得自己被骗了!就像我在开头说的,用什么操作系统只是个人选择而已,我也不希望将自己的看法强加于他人。不过只要你真的感兴趣,就请看下去吧!

2. Linux简介

2.1. 什么是Linux

前面讲了这么多,都没说清楚Linux到底是什么。

Linux是一个操作系统*内核*。

什么是操作系统?

操作系统是作为计算机硬件和计算机用户之间的中介的程序。操作系统的目的是为用户提供方便且有效地执行程序的环境。

操作系统是管理计算机硬件的软件。硬件必须提供合适的机制来保证计算机的正常运行,以及确保系统不受用户程序干扰运行。1

也就是说,操作系统帮助我们屏蔽了硬件操作的细节,保护系统不因程序随意执行而无法正常工作,也让用户更方便地编写和执行程序。然而,不同的操作系统的架构不同,主导的使用逻辑不同,面向的用户群体也不一样。

那什么是操作系统内核?

内核,是一个操作系统的核心。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。2

操作系统内核是操作系统的一部分,它直接与硬件打交道,提供一个操作系统所需的最基础的那些功能。所以仅仅有一个内核是无法构成一个完整的操作系统的。在Linux内核发布前,GNU工程就已经完成了一个类Unix系统除内核外所需的其他组件。因此在Linux内核发布后,GNU工程的组件与Linux内核结合,就构成了GNU/Linux操作系统。

GNU/Linux这个名字初看上去有些奇怪,它好像是把两个工程的名字强行组合在了一起,而且把GNU放在了最前面。不过这也是GNU方面合理的诉求,毕竟GNU软件在GNU/Linux操作系统中的比重更大一些,并且也希望人们能明白他们所做的贡献。不过这里为了和当前普遍的叫法统一,也为了方便,在不引起歧义时就写做Linux操作系统。

Linux是Unix操作系统的一个克隆,因此被称为「类Unix操作系统」。这段历史是一个非常有趣的故事,大家如果有兴趣可以在网上找到许多详细的解释,这里就不再赘述了。需要提到的是,GNU工程的目的是制作一个自由(自由意味着开放源代码,允许软件的自由修改和分发)的类Unix操作系统,其名称就叫GNU(GNU本身就是GNU's Not Unix的递归缩写)。而GNU工程的发起人Richard Stallman也是自由软件运动的发起人,因此GNU自然采用了一套自由软件许可证-–—GPL(GNU General Public License),而Linux内核也使用了GPL发布。除此之外,其它的操作系统所需的组件也基本采用GPL发布。因此Linux操作系统基本上是一个自由的操作系统。之所以说「基本上」,是因为大多数的Linux发行版(下一节会解释什么是发行版)为了一些硬件支持和更好的用户体验,会包含少量的闭源软件。但总体而言,你所使用的Linux操作系统是自由的。

2.2. 选一个发行版

GNU/Linux就是个操作系统了!但是事实也没有那么简单。用户希望得到的是一个「开箱即用」的操作系统,预先包含了一些实用且必要的软件包(即便是简洁到连图形安装界面都没有的Arch Linux,也提供了一系列工具帮助和引导用户安装和配置操作系统),并且能免去用户到处找需要的软件包自行编译安装的麻烦(从头搭一个Linux操作系统可不是件容易事,有一个项目叫Linux From Scratch,可以让你体验这种感觉)。所以就有了Linux发行版这回事。Linux发行版囊括了GNU/Linux的基本组件和一些其他的应用软件,给用户提供方便舒适的体验。另外,不同的发行版也有不同的目标用户。比如Ubuntu面向普通的桌面用户,CentOS面向服务器用户,Arch Linux面向喜欢深度定制系统和滚动更新的进阶用户等等。

具体选择哪一个发行版是很个人化的事情,不过在这里我仍然推荐桌面用户基数最大的Ubuntu。原因有下面这几点:

参考资料多:因为用户基数大,所以99%自己遇到的问题别人早就遇到过,因此自己总能在网上找到相应的解答。不过如果你是一个Linux老鸟,一定知道Arch Wiki这个Arch Linux的官方维基。Ubuntu的官方文档相比之下逊色太多了。然而无论你是否是Arch用户,都一定能在Arch Wiki上找到有用的信息。

软件包丰富:Ubuntu基于全宇宙最大的发行版Debian,而Debian是最早的Linux发行版之一。Ubuntu的官方仓库中包数量是所有发行版中最多的,Debian位居第二。(这是因为Ubuntu在Debian包的基础上又加入了很多自己的包。有关软件仓库的内容之后会介绍。)此外,多数提供二进制包的Linux原生开源软件都提供deb包,而deb包正是Debian系操作系统的软件打包格式。

是许多软件唯一支持的Linux发行版:比如机器人操作系统ROS(Robot Operating System,虽说名字叫操作系统,实际上只是一个软件平台)只支持Ubuntu,还有Steam唯一官方支持的Linux发行版也是Ubuntu(这不是说其它发行版不能使用Steam)。

开箱即用,对新手友好:Ubuntu已经帮助用户预先安装了一系列软件,并对其做了优化配置,所以免去了对用户而言繁琐的安装和配置软件的过程。

需要说明的是,这个系列博客面向的是Ubuntu用户。 不过虽然如此,很多知识是与发行版无关的。所以无论你今后是希望使用Ubuntu还是其它发行版,都可以在这个系列博客中有所收获。

2.3. TODO 选择版本

如果你现在进入Ubuntu官方网站的下载页面,会看到两个版本。一个是Ubuntu 18.04.1 LTS,另一个是Ubuntu 18.10。这二者有什么区别?

首先你可能会奇怪,为什么一个低版本号的下载链接反而放在了最前面,而且做了很多说明,显然是想要用户去下载的样子。其次这个「LTS」是什么意思?

这两个问题其实可以一起解答。

Ubuntu采用的是point release(或称为fixed release)的策略。其版本号简单易懂,前两个数字代表年,后两个数字代表月。18.04就是2018年4月发布的版本,18.10就是2018年10月发布的版本。LTS是(Long Term Support,长期支持)的缩写。LTS版本支持5年的维护时间,在这期间操作系统只会提供必要的安全更新和bug修复,软件仓库中的软件不会加入新特性,这保证了操作系统在其支持期间的稳定性。而非LTS版本只有9个月的维护时间。LTS版本每两年发布一次,非LTS版本每6个月发布一次。也就是说,Ubuntu的下一个LTS版本是20.04,非LTS的下一个版本是19.04。

(这里的内容在正文中暂时删除,感觉有误 <2019-02-20 Wed>) 上游(upstream)的具有新特性的软件包先进入最近的非LTS版本官方仓库,经过测试后若认为稳定,且Ubuntu官方认为该特性可以加入下一个LTS版本,则再进入LTS版本的官方仓库。例如,某软件新版本在2018年10月先进入Ubuntu 18.10版本,若确认稳定且认为新特性可以加入,则将在2020年4月进入Ubuntu 20.04 LTS,否则会保留,继续进行测试。

我们知道Ubuntu是基于Debian的发行版。Debian仓库具有三个分支:unstable、testing和stable。Debian处理软件版本的策略与Ubuntu类似,软件包先进入unstable,确认较为稳定后进入testing,再经确认后才加入stable。Ubuntu的软件包主要来源于Debian的unstable分支,所以上文中的「上游」是Ubuntu的上游,指的是Debian的unstable仓库。而Debian的unstable仓库的上游就是软件作者了。Ubuntu采用Debian的unstable分支的目的是尽可能让其软件具有新特性。

所以说,如果自己想使用一个稳定的操作系统,那么使用LTS版本就是最好的选择。而如果你想体验新特性,或者想协助软件包的测试,那就去使用最新的非LTS版本吧。

2.4. 版本更新

Ubuntu支持从一个版本到下一个版本的更新,当然也包括从一个LTS版本直接跨越到下一个LTS版本的更新。一般而言这样的更新不会出现太大的问题,但如果你曾经根据某些网上的教学,使用了一些奇特的方法修复过你的系统,或对自己的系统做了较大的个性化设置(修改了系统文件),那要格外小心,因为可能会出现一些意想不到的错误。此时最好的方法就是重装系统。你没听错,就是重装(clean/fresh install)。然而重装不意味着你一定要丢失所有的数据。你可以将自己所有的个人数据放入一个指定分区,而在重装时不去格式化这个分区。不过,无论是哪一种方法,在更新前备份自己的数据都是必要的。

除了point release之外,还有一种版本迭代方式叫做rolling release(滚动更新)。这种更新策略的特点是:小范围、频繁、追求新特性。也许你每隔几天到几周就会有一次更新,并且你的软件包往往都是最新的。这种更新模式的优势是能拥有最新的软件特性,且软件的bug也会因上游的快速修复而迅速得到解决。而这也同样带来了风险。你不能保证此时的更新不会使你的某个重要软件出bug而无法正常工作,也不能肯定这次的更新会不会直接导致你无法启动系统(概率比较小,但仍存在)。另外,如果自己隔很长时间才进行下一次更新(记住Linux从不会强迫你更新),很有可能会搞坏你的系统,因为滚动更新模式默认用户的软件版本是平滑过渡的,一旦突然跨多个版本升级,很容易造成问题。这本身就是一种变相的强迫更新。因此这种更新策略对新手而言尤为不推荐。

2.5. Flavors

为什么Linux发行版还有flavors一说,难道Linux能吃吗!?当然不能啦!Flavors这个词在Linux世界中大致有两种含义:第一种是指不同的Linux发行版,第二种是指预置搭载不同桌面环境的同一个发行版。Flavors的第二种含义可以还用另一个词「spins」来表示。我们在这一节说的flavors,是它的第二种含义(因为Ubuntu官方就是用flavors称呼它的那些spins的)。

有关桌面环境的内容会在后面的一个章节单独介绍。这里只需要知道在Linux的世界中,桌面环境不止一种。当前使用最多的,也是被大多数发行版作为默认桌面环境的,是GNOME 3。还有一款人气很高的桌面环境叫做KDE。此外还有很多其他主流的桌面环境:Cinnamon、MATE、XFCE、LXDE、Budgie等等。

不同的桌面环境具有不同的特色。GNOME 3和KDE比较占用系统资源,但更为现代。LXDE主打轻量级的桌面环境,不吃资源。MATE是GNOME 2桌面环境的延续,沿用经典的设计和布局……

Ubuntu默认搭载的桌面环境是GNOME 3。那Ubuntu的其它flavors呢?比如默认搭载KDE的Kubuntu,搭载MATE的Ubuntu MATE,搭载XFCE的Xubuntu等等。在Ubuntu的相关页面上列出了所有其支持的flavors。

不同的flavors除了桌面环境的不同之外,也会对系统做出自己的调整。例如Ubuntu MATE主打的是用户友好(user-friendly)的使用体验。因此其在搭载MATE桌面环境的同时,精心设计自己的默认主题,使其具有与Ubuntu一致的视觉效果,并且提供了很多在Ubuntu中没有的对用户十分友好的功能。Ubuntu Studio是专为影音工作而设计的,因此对这方面的系统设置进行了特别优化,也预置了很多与影音制作相关的软件。(虽说当前Linux的影音制作能力还比不上Windows和macOS,但起码你能看到有许多人在努力。)

每个flavors都可以看作一个独立的发行版,因此也都会有自己的logo,下面这张图3展示ubuntu的一部分flavors。

不过需要明白的是,同一种发行版的不同flavors使用的是同一个官方软件仓库。也就说即便你使用了Ubuntu的一个flavor,你仍然能使用所有Ubuntu可以获得的软件,并且所有可用于Ubuntu的解决方案(只要其与桌面环境无关)也都适用与这个flavor。

我个人目前在使用的就是Ubuntu MATE,使用起来非常舒适哦!

不过具体选择哪一个flavor也是个人喜好,如果你喜欢某一款桌面环境,就去尝尝那个对应的flavor吧!

3. 文件系统与挂载

也许很多小伙伴都迫不及待想安装上Linux尝尝鲜,但是在介绍安装Linux前,还是想先把Linux的目录结构、文件系统和挂载讲明白。

这三点是很多初次使用Linux的小伙伴最迷惑的地方。首先在安装时,如果你是按照网上某些细心的教程操作,那么你会看到推荐在安装时进行手动分区(partition)。而在分区的时候,你会被要求给所划的分区选一个文件系统(file system),还需要把它挂载(mount)到某个特定的目录。记得当时自己初次分区时,完全不知道到底应该把某个分区划多大,那么多可选的文件系统是什么意思,也搞不明白那些目录是做什么用的。查阅了网上的很多博客或论坛,每个答案都不太相同。

另外在自己安装完成后,发现Linux的目录结构也和自己熟悉的Windows不太一样。打开一个名字类似于「主文件夹」的图标后,会看到好几个叫做「文档」、「下载」、「图片」之类的文件夹,有点像Windows的用户目录(其实在Linux也就是用户目录没错)。那软件装在哪里呢?往上级目录翻,发现居然有好多的目录,而且每个目录都是只读的!那每个目录到底是什么意思呢?里面存放着什么样的文件?

所以这一篇就先来讲讲Linux的目录结构、文件系统和挂载。我会先从容易理解的目录结构说起,然后再给大家介绍关于文件系统和挂载的一些必要知识。

不过「文件系统」和「挂载」两节对于初识Linux的小伙伴来说可能略显硬核,可以暂时略过不看,等到以后想要了解的时候,或者希望将Linux装在物理机上作为桌面操作系统时,再翻回来看。

3.1. 目录结构

3.1.1. 树状结构

Linux的目录结构是树状结构,与Unix一脉相承(谁让它是类Unix呢)。说句题外话,macOS也是类Unix操作系统,所以目录结构也是树状的。下面给出一张示意图4

我相信大多数小伙伴应该都知道什么叫「树状」。Linux的目录是一颗树,所以只有一个「根节点」,也就是「根目录」,用符号 / 来表示。注意Linux的路径(path)中,目录之间的分割符是「正斜杠」 / ,而大家熟悉的Windows使用是「反斜杠」 \ ,例如 C:\windows\system32\

根目录 / 下面有许多的目录,例如 /bin/dev/usr/home 等等,有20个左右(上面的示意图只列出了部分目录)。为什么要写成 /bin 呢?因为第一个字符 / 代表根目录,而后面三个字母 bin 是该目录的名称,所以如果要标示清楚这个目录的所在路径,就要写成 /bin 。如果只是写 bin ,你就只能把它当作一个「相对路径」而非「绝对路径」了(这两个概念如果不明白可以在网上轻松找到解答)。

3.1.2. 家目录与系统目录

这些目录中,最特别的是 /home ,因为看名字就知道,这是你的「家」!

/home 的下级目录是用户目录,这就是前面提到的「主文件夹」。比如我的用户名是 yilin ,那么我的用户目录就是 /home/yilin 。如果这台计算机有多个用户,比如还有 tomjerry ,那么就会有 /home/tom/home/jerry

需要注意的是,并非所有用户都会有自己的用户目录。在后面会有一个章节介绍有关用户的知识。现在假设用户 tomjerry 都是这台计算机的桌面用户,那么一般而言他们都会建立自己的用户目录。

根目录 / 下面除了 /home 目录以外的其他目录呢?它们都可以视为系统目录。一般我们所谓的「软件」就会安装在这些系统目录下面。除了软件外,系统目录下还存放许多与系统相关的配置文件、日志文件、共享库文件等等。Linux的这些系统文件都会分门别类地放在不同目录下。那么这些目录分别存放的是什么样的文件呢?这篇文章已经把它们讲得非常清楚了,大家可以看一看,在这里就不多说了。

3.1.3. 一切皆文件

如果你看了上面链接的那篇文章,可能会感觉不可思议。为什么硬件也可以当作文件?比如 /dev 下存放的都是代表各个硬件的一些文件。甚至 /proc 目录里面的文件压根不在硬盘里,你可以通过这些文件读取系统进程的信息,但这些文件的大小都是0。

这是因为在Unix或类Unix操作系统中,一切皆文件。硬件是文件,目录也是文件,甚至在内存中的信息也可以当作文件。

也就是说,操作系统以这种方式为用户提供了一套统一的接口。只要你想对某个对象进行操作,不论这个对象到底是什么,去读写文件就可以了。

3.1.4. 题外话之权限

用户对自己的用户目录是可读可写的。有关权限的问题在后面的章节会讲到,现在你可以简单地理解为:你可以在你的用户目录下查看文件,也可以新建、删除、修改文件。而用户对其他用户的用户目录是默认不可读写的,也就是说其他用户无法查看你的用户目录,更不能进行任何文件操作。

用户对系统目录只读,也就是说用户只能查看系统目录,但不能修改系统目录中的文件或目录。

奇怪了,前面明明说用户对系统文件只读,那如果要按上一节说的对 /dev 中的硬件进行操作,该如何写呢?

实际上在Linux中有一个真正的boss,那就是root用户。root用户可以做任何事,只要Linux允许,你就能做。你可以修改系统文件,也可以偷看 tom 的文件。甚至有权限把整个根目录删掉(我在网上看到有人这么做,但没成功,想想也是不太可能)。

不过,如果你真的想对 /dev 中的硬件读写,使用root并不是一个好办法。 实际上总是使用root权限是相当危险的 ,如果不是迫不得已,千万不要总是使用root权限。为什么危险?因为你不能保证自己永远不会误操作,也不能保证你给予权限执行的程序不会错误执行或包含恶意代码。你应当尽量保证所有的操作都在一定权限的控制下,这样才能最大限度保护系统的安全。

那该怎么办?「用户组」是一个比较合理的解决方案。这个问题会在之后讲用户和用户组的章节中得到解答。

就像开头说的,如果你初识Linux,可以跳过下面两节,安装时偷个懒吧!

3.2. 文件系统

理解了上面这些,大家对Linux的目录结构应该有些头绪了。我们还顺便了解了Unix中的「一切皆文件」的概念和关于root的小知识。接下来我们来了解一下与文件系统(file system)相关的知识。

3.2.1. 什么是文件系统

A filesystem is the methods and data structures that an operating system uses to keep track of files on a disk or partition; that is, the way the files are organized on the disk.5

你可以把你的硬盘比作一个大大的房间,里面放满了一个个小抽屉。这些小抽屉就是文件系统的基本操作单位——盘块(硬盘的最小操作单位是扇区,一个盘块由一个或多个扇区组成)。文件系统就像是这些小抽屉的管理员,它会来决定该以怎样的方式存放你的文件,并将你的文件很好地管理起来。不同的文件系统有不同的管理方法。

在Linux中,最常用的文件系统是Ext4(fourth extended filesystem,第四代扩展文件系统)。它最多支持1EiB的卷(volume)大小和16TiB的单个文件大小6,比Windows使用的NTFS文件系统支持的卷大小和单个文件大小都要大。

所谓的「卷」又是什么呢?我们先来看什么是「分区」。

3.2.2. 分区和卷

在安装Linux时,一般推荐的做法是手动分区,所以了解分区(partitioning)是必要的。

Disk partitioning or disk slicing is the creation of one or more regions on a hard disk or other secondary storage, so that an operating system can manage information in each region separately.7

简单来说,分区就是我们的硬盘被划分出来的逻辑存储区域。所谓的「逻辑」与「物理」相对。如果将一块硬盘划分为两个分区,那么虽然物理硬盘只有一块,但计算机能看到的逻辑硬盘有两块。分区不一定包含文件系统。

我们可以将一个分区「格式化(format)」为指定的文件系统,这样一来,这个分区就可以看作一个卷(volume)。注意一个卷只能有一个文件系统。

In computer data storage, a volume or logical drive is a single accessible storage area with a single file system, typically (though not necessarily) resident on a single partition of a hard disk.8

另外,在同一个硬盘,我们可以把其中的不同的分区格式化为不同的文件系统。

所以说,格式化本质上不是把硬盘上的文件删光光的意思,它只是格式化的一个副作用而已。

那么计算机是如何知道我们硬盘的分区情况的呢?在硬盘上会存储一个分区表,分区表记录了硬盘中各个分区的大小和物理位置。这样一来,计算机就可以通过读取分区表来了解硬盘分区的信息了。

当今存在两种主流的分区表,一种叫MBR(Master Boot Record,主引导记录),另一种叫GPT(GUID Partition Table,GUID分区表)。

MBR是硬盘最开始的512个字节。除了分区表,它还包括了操作系统的启动加载器(boot loader)。如果一个硬盘采用的是MBR分区表,那么它所支持的分区有三种类型:主分区(primary)、扩展分区(extened)和逻辑分区(logical)。MBR在一个磁盘上最多只支持4个主分区。如果想要4个以上的分区该怎么办?一般的做法是建立3个主分区和1个扩展分区,再在这个扩展分区中建立1个或多个逻辑分区。注意,扩展分区最多只能有1个,并且扩展分区和主分区加起来不能多于4个。扩展分区中的逻辑分区数没有限制。9

GPT分区表是一种更强大的分区表。它只支持主分区,但对其个数没有做限制。

这么一看,GPT分区表显然要方便得多,那我们就用GPT分区表吧!

但是实际情况没有那么简单。

在Arch Wiki10中,给出了选择MBR还是GPT时需要考虑的内容,在这里我直接引用过来:

  • 如果使用 GRUB legacy 作为bootloader,必须使用MBR。
  • 如果使用传统的BIOS,并且双启动中包含 Windows(无论是32位版还是64位版),必须使用MBR。
  • 如果使用 UEFI 而不是BIOS,并且双启动中包含 Windows 64位版,必须使用GPT。
  • 非常老的机器需要使用 MBR,因为 BIOS 可能不支持 GPT.
  • 如果不属于上述任何一种情况,可以随意选择使用 GPT 还是 MBR。由于 GPT 更先进,建议选择 GPT。
  • 建议在使用 UEFI 的情况下选择 GPT,因为有些 UEFI firmware 不支持从 MBR 启动。

那么如何确定自己的引导系统是BIOS还是UEFI?网上有非常多教你如何查看自己电脑引导系统的教程。如果你现在用的是Windows,可以查看这篇文章。如果你不了解什么是BIOS和UEFI,网上也有非常多的介绍可供学习,我在延伸阅读中也给出了Wikipedia对应词条的链接。

3.3. 挂载

当你成功地将硬盘分区后,事情还没结束,你还需要将各个分区挂载到不同的挂载点。

在讲这个问题之前,先来回顾一下大家熟悉的Windows操作系统。

3.3.1. Windows的「盘」

当我们的电脑上有多个分区时,你一般会看到所谓的「C盘」、「D盘」、「E盘」……每一个盘都代表一个分区。很直观不是吗?如果你有两块硬盘,还在第一块硬盘分了两个区,你的分区情况有可能是下面这个样子:

物理硬盘 分区 文件系统 盘符
硬盘1 分区1 NTFS C:
硬盘1 分区2 FAT32 D:
硬盘2 分区1 FAT32 E:

Windows是如何获得这些分区信息的?首先它会找到所有的硬盘,在这里是硬盘1和硬盘2,再去找硬盘中的分区,这里有三个分区:硬盘1的分区1和分区2,硬盘2的分区1,然后读取文件系统信息。11(盘符在分区格式化时指定,所以应该算作文件系统信息的一部分。)

3.3.2. Linux的挂载

那Linux呢?我们之前在目录结构一节讲到过,Linux的目录结构是树状结构,而且是 一棵树 。那该怎么办,难道我只能使用一个分区了吗?

其实不然。不过在把这件事搞清楚之前,我们需要了解一个概念-–—虚拟文件系统(Virtual File System, VFS)。想一想,为什么在Windows中,你的C盘是NTFS文件系统,D盘是FAT32文件系统(也许实际上不是,只是举个例子),而你却可以用相同的方式打开他们,创建、修改、删除文件?这是因为操作系统提供了一层在实体文件系统之上的「虚拟文件系统」,抽象了实体文件系统,给用户一套统一的接口去操作不同的文件系统。Windows使用的虚拟文件系统机制叫做(Installable File System)。8

Linux当然也有虚拟文件系统,而且它更进了一步。记得上文提到的「一切皆文件」吗?就是因为有了虚拟文件系统才能做到这一点。同时,Linux的虚拟文件系统还维护着一个树状结构目录,并且系统需要通过这个虚拟文件系统访问硬盘。也就是说,Linux为了获得分区信息,先通过虚拟文件系统访问硬盘,再访问分区,然后访问文件系统。11

现在我们就可以来了解Linux是怎么做的了。虽然Linux的目录结构只有 一颗树 ,但是有很多目录不是吗?如何将这些目录与硬盘关联起来呢?就是通过挂载。我们的各个分区就可以挂载到不同的目录上。这些被挂载的目录路径就称为「挂载点(mount point)」。

还是两块硬盘,并在第一块硬盘分了两个区,在Linux中挂载后会怎样呢?可能是下面这个样子:

物理硬盘 分区 文件系统 挂载点
硬盘1 分区1 EFI /boot/efi
硬盘1 分区2 Ext4 /
硬盘2 分区1 Ext4 /home

你可能还是会奇怪, /boot/efi/home 不是 / 的子目录吗,为什么可以这样作为挂载点?事实情况是, / 下面所有除了 /boot/efi/home 的目录和文件都存放在硬盘1的分区2。

虽然Linux的挂载方法乍一看没有Windows那么直观,但是理解后会发现十分巧妙。对于用户而言,你操作的永远是树状结构的目录,而无需关心具体的分区,而且你也不会因为分区损失结构上的层次性。

3.4. 安装时偷个懒

不过话说回来,真的有必要这么复杂吗?如果我只是想安装Linux体验一下,真的需要了解这么多有关文件系统和挂载的知识吗?

当然不用!前提是你真的只是「体验一下」,而不把它当作日常使用的桌面操作系统。(因为将 /home 单独分区才是最推荐的做法。否则如果系统要重装,你的个人文件就会被删掉了。)

怎么办呢?很简单,在安装的时让安装程序帮你一步搞定。安装的其中一步是让你选择把Linux装在磁盘的哪个地方。如果你想双系统,直接按照提示把Linux装在你预先腾出来的硬盘空间。如果你使用虚拟机,那就更轻松了,直接使用默认的选项就行了,你只需负责点击「下一步」。

难怪有很多小伙伴装完Linux后完全不知道有分区这回事!

这么做会发生什么?安装程序基本上会将你所指定的所有磁盘空间都分成一个区并挂载到根目录 / ,不过除此之外也可能创建一个swap分区(该分区比较特殊,没有挂载点,具体会在下一篇介绍)。

在下一篇,我会和大家正式介绍如何安装Linux。也许不会太详细,因为相关的教程已经太多太多,甚至你完全不需要教程也可以轻松安装。我主要会和大家分享一些必要的细节和在手动分区安装时踩过的坑。请持续关注哦!

4. 安装Ubuntu

终于到了安装Linux的时候了!不过在这里得先说明两点:

  • 就像第2篇所说,这个系列博客面向Ubuntu用户,所以安装过程的介绍也是按照Ubuntu的安装流程走。不过现在大多数桌面发行版都提供了图形化安装界面,安装的流程也大同小异。所以如果你想安装其它发行版,也可以在这里得到一定的参考。
  • 网络上有非常多关于Ubuntu安装的教程,因此在这里重复写并无意义。Ubuntu的安装程序也对用户非常友好,即便不看教程照样能顺利安装。所以这篇博客只提供一些安装过程中需要重点注意的内容。

那么现在开始吧!

4.1. 确认硬件兼容性

这是最要命的一点。即便当下Linux的硬件兼容已经比曾经好了很多,仍然远比不上Windows,毕竟后者才是最主流的操作系统,并且硬件厂商最先想到的还是做Windows的驱动。有些品牌的电脑对Linux的支持很好(比如Dell),而有些则不一定,有可能你电脑的某一个硬件(比如摄像头、触摸板、指纹识别等等)会无法正常工作。不过即便如此,大部分电脑都不会出现太大问题,只不过有些可能需要进行一定的配置调整。

想知道自己的电脑硬件是否兼容Ubuntu,可以进入这个页面搜索自己电脑的型号。上述网页中列出的是Canonical的OEM合作伙伴提供预装Ubuntu的计算机信息,也就是说如果你的电脑型号出现在其中,那么一定能保证硬件兼容性(但是不保证Ubuntu和Windows双系统时不会出问题,比如我自己的Dell XPS13 9343在双系统时,声卡不能正常工作)。而如果你的电脑并不在其中,或者你想知道更多有关自己计算机的可能出现的问题,可以使用搜索引擎查一查相关的讨论和评价。推荐使用英文搜索(比如Bing),这样能够找到更多的信息。

另外,大部分UEFI启动的计算机都会开启「secure boot」。它的本意是只允许经过签名授权的固件和驱动运行,帮助用户避免恶意程序的侵害。但是secure boot后来逐渐变成了微软的垄断工具。微软要求制造商,预装Windows 8的桌面计算机必须开启secure boot。虽然secure boot可以被用户关闭,但这样一来硬件厂商还是需要向微软付费以获得签名授权,让他们的硬件能使用secure boot启动。12(现在的Windows 10 也默认开启secure boot。)然而,Linux中许多固件和驱动并未获得授权,因此开启secure boot可能导致某些硬件在Linux下无法正常工作13,所以建议关闭secure boot再进入Linux。关闭secure boot一般不影响Windows的使用。微软官方也给出了关闭secure boot的方法

4.2. iso映像文件

4.2.1. 认识iso

一般发行版官方都会提供iso映像用于安装操作系统,Ubuntu也不例外。iso映像可以理解为将光盘上的内容未压缩地拷贝到一个二进制文件中。记得十多年前人们往往会使用光盘来安装操作系统。但是iso映像并不一定真的要刻录到光盘上才能使用,你可以将它写入其它外部存储设备,比如U盘或移动硬盘。而如果你只是想把它装到虚拟机上,直接让虚拟机的虚拟光驱读入这个iso文件就可以了。

4.2.2. 版本选择

具体有关版本选择的内容在第2篇已经详细介绍过了。当时的主要目的是让大家了解Ubuntu不同版本的含义和它版本迭代的机制,并推荐使用LTS版本。而这一节是关于一个细节的补充:32位和64位计算机的支持。 如果你想把Ubuntu装在64位计算机上,可以跳过这一节。

Ubuntu标准版(也就是默认搭载GNOME 3桌面环境的那款)的最新LTS版本是Ubuntu 18.04LTS。Canonical已经放弃了该版本和其后版本中对32位计算机的支持,这是因为经用户调查后发现,当今使用32位计算机的用户占比极少。但如果你的确想把Ubuntu装在32位计算机上,你可以尝试Ubuntu的那些flavors。Lubuntu、Xubuntu、Ubuntu MATE、Ubuntu Budgie都提供18.04LTS的32位版本。如果你一定要安装标准版Ubuntu,还是有办法的,因为当前32位的软件仓库仍存在(要不然那些flavors怎么支持32位呢),具体方法可以参考Stack Exchange中这个问题的解答。但是这么做实在没有必要,而且由于没有官方的维护,出现的问题很可能得不到修复,因此非常不推荐。

另外从18.10版本开始,这些flavors中除了Xubuntu和Lubuntu,都放弃了对64位计算机的支持。如果你确实想在旧电脑上使用Linux,来让老机器重获新生(当Windows把老爷机卡得欲仙欲死时,一款合适的Linux发行版可能让它箭步如飞),那当然没问题,再怎么样也总能找到支持32位计算机的Linux发行版。但是如果这是你的主力电脑……那真的可以考虑换新电脑啦!

4.2.3. Live操作系统

如果你有安装盗版Windows的经验,你可能听说过「PE系统」这种说法。你首先需要把这个所谓的「PE系统」写入到U盘或光盘上,然后在计算机启动前插入,调整启动顺序,让电脑通过这个外部存储设备启动,最后会来到一个操作系统界面。

其实这个时候,你运行的是这个外设给你提供的操作系统。你可以使用这个操作系统中的安装程序来将操作系统安装到你的硬盘上,也可以使用它为了方便用户而提供的一系列软件,用于修改分区和修复bootloader等等。

Ubuntu也是如此。当你将iso写入存储设备后,你就制作好了一个便携的,一般叫做「Live CD」或是「Live USB」(视你的存储设备是CD还是U盘而定)的东西。你可以像上面说的一样启动它,进入一个操作系统「一般叫做Live OS」。这个操作系统有什么用呢?下面列出了我认为比较重要的几个功能:

  1. 安装操作系统。这也是这个Live OS最主要的功能。
  2. 体验操作系统。Live OS能让你在不真正安装这个操作系统的情况下体验它。你可以体验一下这个桌面环境,调整一下它的设置,或是打开火狐浏览器上个网。同时这也是一个机会,让你检查计算机上的各个硬件能否正常工作。
  3. 修复系统。有时你想要重新设置你的分区大小或挂载点,而在你计算机上的Linux运行时,不能将挂载在主要目录上的分区卸载,因此只能使用Live OS,在那些分区不被挂载的情况下修改它们。又或者你的操作系统因为bootloader损坏而无法启动,这时你可以用Live OS修复bootloader。
  4. 数据恢复。如果你计算机上的操作系统因为种种原因而无法启动,而你想要拿出硬盘中的一些文件该怎么办?你可以使用这个Live OS来帮助你。你只要将硬盘上的分区挂载到这个Live OS上,就可以看到其中的文件了。此时你可以插入另一个存储设备,将这些文件拷贝过去。Linux的Live OS的另一个好处是,因为它的虚拟文件系统支持非常多种文件系统,所以Windows的NTFS分区照样能够被挂载。也就是说你不仅能拿到硬盘上Linux分区中的数据,也可以拿到Windows的。(如果你使用双系统,你会发现Linux可以拿到Windows硬盘上的文件,而反过来则不行。)

因此,LiveCD/LiveUSB是你的朋友,它不仅可以帮助你安装操作系统,也能让你的系统多一层保障。我个人建议在LiveCD/LiveUSB制作完成后把它保留在身边,以备不时之需。这不是因为Linux容易挂掉所以需要经常重装,而只是让你在遇到概率很小的意外时有一根救命稻草。(如果你使用滚动更新的发行版,这种风险会比较大,但是使用Ubuntu,只要不在自己的掌控外折腾系统,就完全不需要担心。在后面我也会写一篇文章来介绍良好的系统维护的方法。)

当然,如果自己只是想快速装好系统,你也可以不进入Live OS而直接开始安装。

4.2.4. 下载iso文件

有关下载iso文件,实际上也没什么好说明的,因为大家都知道去Ubuntu官方的下载页面下载。如果你想使用Ubuntu的其它flavors,可以在这里找到你喜欢的flavor。

另外,由于Canonical的服务器架设在国外,下载速度会比较慢。可以考虑去清华大学开源软件镜像站或是USTC open source software mirror下载iso文件。链接在网页的右侧。

4.3. 进入Live操作系统

4.3.1. 物理机

物理机的安装流程可以在网上找到太多太多了。这里只给出为了进入Live OS需要经历的大致步骤:

  • 如果希望装双系统,需要腾出至少25GB未使用的硬盘空间,建议备份数据,以防万一。如果是单系统就更要备份数据了,毕竟整个硬盘都将会被格式化。
  • 将iso文件写入外部存储器。一般推荐使用U盘,并使用一个叫Rufus的工具。
  • 关机,将U盘插入USB口,启动电脑,进入BIOS或UEFI,将U盘启动优先级设置为最高。
  • 语言选择「中文」,点击「试用Ubuntu」进入Live OS。

注意,如果你不是选择「最小安装」(只预装必要的软件),会需要在安装时下载所需的软件包,因此需要保证安装时的网络连接。 某些电脑的无线网卡驱动是专有驱动(比如我的电脑需要使用Broadcom的专有驱动),而这些专有驱动是不会包含在Live OS里的,所以你在安装过程中需要使用有线网络连接。不过系统在安装时会帮你下载安装专有驱动,所以等安装结束就可以正常使用无线网卡了。一般在Live OS中无法使用无线网络的计算机都是这种情况,因此要准备网线,并且如果你的电脑没有网线端口,还要准备一个扩展坞。

在上一篇中提到,在手动分区前需要知道自己的计算机到底使用的是BIOS还是UEFI。如果你在进入Live OS后还是不知道自己到底使用的是哪一个,看看自己的Live OS有没有 /sys/firmware/efi 这个目录。如果存在,那就是UEFI,否则就是BIOS。如果你并不需要手动分区,就无需关心这一点。

4.3.2. 虚拟机

虚拟机安装过程要简单得多。我推荐使用VirtualBox而不是VMware,后者是需要付费的商业软件,而且前者的功能十分强大,足够用了。

需要指出两点: - VirtualBox默认采用BIOS,如果你想使用UEFI需要进行设置。(在「设置」>「系统」>「主板」>「扩展特性」中,勾上「启用EFI」。)

  • 最小分配25G硬盘大小。

4.4. 分区

就像上一篇所说,如果你只是想体验和学习一下Linux,而不把它作为日常使用的操作系统,分区这一步可以忽略,否则还是非常建议手动做一下分区。

在网上你可以找到很多分区的方式,但是大多数都没有解释清楚这样分区的原因,也有些分区方式已经过时,或者对桌面用户来说完全没有必要。

对桌面用户而言,手动分区的主要目的是什么呢?就是将我们的 /home 目录单独分区。这么做的好处就是当我们重装系统的时候,该目录的数据不会丢失,因为你无需格式化这个分区。不过还是非常建议大家重装系统前把数据备份好,以防意外发生。

安装Ubuntu时,其中的一步就是询问用户的分区方式。默认选项是将Ubuntu和当前的操作系统并存(前提是你已经留出了足够的硬盘空间),还有一个选择是清除整个硬盘来安装Ubuntu,而手动分区的选项在最下面。

选择了手动分区后,具体该怎么操作呢?你会进入一个窗口,让你修改分区。如果你想装单系统,那直接先清除所有分区,再一个个创建分区就行了,而如果你想装双系统,那可得小心,别把当前系统的分区给删除了!

怎么分区呢?Arch Wiki的Partitioning词条已经解释得非常详尽了,主要参考「Example layouts」这一节的内容。(说句题外话,Arch Wiki的大多数词条都有中文版,只不过有些和英文版比较同步,而有些很久没有更新了,所以尽量以英文版为准。Partitioning这个词条当前中英文相同,所以也可以看中文版本。)

4.4.1. 根分区和家分区

最重要的分区是 //home ,一般只需要分这两个就可以了。

根分区 / 的大小个人建议按照Arch Wiki中建议的最大分区大小来分配(除非你的硬盘空间十分紧张,这时可考虑适当缩小),如果使用swap文件而非分区,则在此基础上加上swap文件的大小。这个分区不需要太大,因为虽然Linux的软件基本都装在该分区下(主要是 /usr 目录下),但是它们一般都不会很大(比Windows小得多)。 但根分区 / 一定要留够空间,因为如果其空间被占满,系统将无法启动。 (个人认为30~40GB就足够了,50GB显得太多。我当前在包含一个4GB的swap文件的情况下,只使用了23GB。)

家分区 /home 尽可能大。一般是将必要分区分完后,将所有剩余空间都分给 /home ,因为这是存放个人文件的地方。(而且如果你要玩Steam游戏,也会装在 /home 下面。)

4.4.2. Swap分区

上面提到的swap分区和swap文件是什么?有什么用?

Swap分区和swap文件可以统称为「swap space」,也就是「交换空间」。 交换空间位于硬盘,它有两个作用,一是为虚拟内存(virtual memory)提供额外的空间,二是为系统的休眠(hibernation)功能提供可能。

有关虚拟内存的内容,其实可以花掉一整篇博客的篇幅来写。这里我们只需要简单地理解成: 交换空间就是物理内存的扩充 。也就是当物理内存(RAM)不够用时,可以用交换空间来存储内存中暂时用不到的数据,释放物理内存空间。我们知道内存的存取速度比硬盘快得多,因此操作系统会尽可能优先使用物理内存。

「休眠」与「挂起(suspend)」是两个概念。内存是一种易失性存储器,必须在上电的情况下才能储存数据,如果掉电则会丢失数据。我们平时会经常将笔记本电脑合上,这时系统的操作是「挂起」,内存不掉电。如果我们把电脑重新打开,它会迅速从挂起状态恢复。而如果我们让系统「休眠」,那么电脑会将物理内存中的数据转移到交换空间,然后让内存掉电。要将电脑从休眠状态唤醒时,内存上电,交换空间中的数据再重新转移回内存。显然,「休眠」的整个过程相比「挂起」需要更多的时间。并且我们可以从休眠的整个过程中发现: 只有交换空间大于等于物理内存时,才能实现休眠。 虽然在Arch Wiki中提到:「就算交换空间小于物理内存空间,仍有很大几率能成功休眠」14,但是为了休眠功能的完整,还是推荐大于物理内存的交换空间。

Ubuntu的社区帮助Wiki,有一张物理内存大小和建议的交换空间大小的对照表格,包括了不需要休眠和需要休眠两种情况,可以给大家作为参考。可以发现,为了实现休眠,建议交换空间大小略大于物理内存。此外,Arch Wiki的Partition词条中也有相关的建议15

在拥有不足 512 MB 内存的机器上,通常为 swap 分区分配2倍内存大小的空间。如果有更大的内存(大于 1024 MB),可以分配较少的空间甚至不需要swap 分区。

因此你在网上经常看到的「两倍内存」原则,实际上是以前物理内存较小情况下的普遍原则,现在并不推荐,因为这显然浪费了很多硬盘空间。

那么选用swap分区还是swap文件呢?同样在Arch Wiki的Partition词条15也做了说明:

swap 分区提供能够被作为虚拟内存的内存空间。swap file 也可以实现同样的功能,并且它们之间没有明显的性能区别,但是后者更易于根据需要调整大小。如果没有使用休眠特性的话,swap 分区可以被多个系统共享。

一般来说不会用到多个系统共享同一个swap分区的情况,并且swap文件还可以在装完系统后创建,非常灵活, 因此使用swap文件是最方便的

如果在分区时不创建swap分区,Ubuntu会自动帮你创建swap文件。万一没有swap文件,还可以参照Arch Wiki的Swap词条Ubuntu社区Wiki的SwapFaq词条自行创建swap文件。

4.4.3. EFI分区

如果你是UEFI引导,必须有一个「EFI分区」 ,文件系统格式为FAT32。注意在Ubuntu中,其挂载点是 /boot/efi ,不是Arch Wiki中的 /boot/efi 。(因为Arch Wiki毕竟是Arch Linux的Wiki,并不是所有内容都可以不加甄别地使用,只不过大部分内容在Linux世界都通用。)另外对于EFI分区到底分多大这件事,你可以看到很多说法,有说100MB~250MB的,也有说512MB左右的。Stack Exchange上这个问题的解答解释了为什么会有这么多不同的推荐分区大小。如果你的硬盘容量足够,个人建议不妨就按照Arch Wiki分550MB。

4.4.4. 分区原则

个人建议对桌面用户而言,分区应满足下面两条原则:

  • 分区数尽量少,不创建没有必要的分区;
  • /home 分割出来。

也就是说,对BIOS引导的系统,至少创建两个分区,分别挂载到 //home ,至多再加一个Swap分区;对UEFI引导的系统,至少创建三个分区,分别挂载到 /boot/efi//home ,至多再加一个Swap分区。

「把 /home 分割出来」这一点应该没有什么疑问,因为这是我们手动分区的主要目的。而分区数尽量少则是因为对桌面用户来说,在同一个计算机一般不会安装多个Linux系统,也用不着挂载同一个分区到不同系统的目录,所以没有必要将其他目录专门分区。另外,Arch Wiki中提到可以将 /var 目录专门分区,「避免由于大量日志写入造成的磁盘空间耗尽等问题」16,但是一般桌面用户的 / 分区已经足够大,且即便磁盘空间耗尽也不会造成特别大的影响(相对服务器而言),用户可以利用Live OS清理磁盘空间。所以,额外的分区反而只会浪费磁盘空间。

4.4.5. B与iB

在使用分区软件,或者平时查看分区或文件大小时,你可能会看到两种单位,一种以B结尾,如MB、GB,另一种以iB结尾,如MiB、GiB。这二者实际上是有区别的。

iB结尾的单位以2为底,B结尾的单位以10为底。1KiB是1024Byte,1KB是1000Byte。但是人们经常混用这两个单位,导致现在以B结尾的单位很多时候其实表示以iB结尾。(我全文中所用的MB和GB实际上都指的是MiB和GiB。)

重点来了:许多分区软件默认MB、GB这些单位就是MiB、GiB,可是Ubuntu的安装程序使用的是MB、GB的原本定义。所以在分区时需要做一下MiB到MB,或GiB到MB的转换,以免最后分区的大小与预期不符。

这解释了为什么经常人们发现自己的分区比预期的小一些。我也很不理解为什么Canonical要这么做,为何不使用统一的标准呢?如果想区分B和iB,那完全可以将安装程序中的单位换成iB,现在这么做只会给不明真相的用户造成麻烦。

5. 包管理

5.1. 有关命令行

在原本的计划中,自己是打算写有关命令行的内容的,但是想到已有的很多资源都可以帮助到大家,自己再写一遍实在没有必要,而且也肯定不比优秀的教程出色;再者为了Linux的日常使用,只需要掌握基础的几个命令即可,没有必要花费整个章节去写,因此就放弃了这个想法。

我写博客的目标是站在初学者的角度,分享这大半年来使用Linux的经验。初学者往往会遇到类似的问题,而这些微妙的疑惑又经常被写教程的高手忽略,所以我希望自己的写作能把对初学者有特殊价值的经验分享出来。同时我也想表明,如果某些内容我不了解,而又有现成的学习资源,我不会做无谓的重复劳动,但会尽力把自己了解到的资源分享给大家,让大家共同学习。

有关命令行的知识,推荐一个叫做《The Linux Command Line》的很棒的教程,有英文原版中文版。推荐看前面几章了解文件查看、目录跳转、复制移动等基础操作即可,剩下的今后有需要再来看。这部教程涵盖了与命令行相关的方方面面,连如何编译程序都有介绍,非常实用。说实话我自己也没有看完,因为就算看完很多知识也会马上遗忘。最好的方法应该是在用中学。在介绍下面的内容之前,希望大家先把上面提到的教程的前几章看一看,熟悉一下命令行。

「命令行超酷的!」

5.2. 为什么需要包管理

不过这一篇的内容是包管理。说起这个话题,很多对此有些了解的小伙伴马上想到了一个命令—— apt-get

sudo apt-get install xxxx

真方便!你想要的软件就这样装上了!

但是这背后发生了什么呢?

记得之前在 Linux简介 一篇中提到过「软件仓库」这个词。软件仓库是什么?为什么需要软件仓库?

回想起用 Windows 的时候,软件的安装包一般是直接从软件提供者获得的,你需要在下载后双击打开,完成安装程序。而 Linux 却很不相同,大多数你需要的软件都在发行版所提供的官方软件仓库中,并通过包管理工具完成下载和安装的操作。

「软件仓库」的英文名是 repository ,也常被简称为 repo 。它的存在与 Linux 的开源软件生态有很大关系。Linux 操作系统是由世界各地的开发者共同协作完成的,在这种开发模式下,由于不像商业公司那样有能力做统一的管理,软件包之间的关系就显得相对松散了。假设今天开发者 A 想开发一款 Linux 下的音乐播放器,他当然不会去实现底层有关音频 IO 的代码,而开发者 B 已经实现了 A 所需要的组件,那么显然 A 会去使用 B 提供的组件。而开发者 B 为了实现自己的功能,可能需要更底层的组件,这时也许会使用开发者 C 提供的组件。开发者 A 当然还要开发图形界面,那还得用图形界面框架,图形界面框架也还依赖更底层的 X Window ……像这样一级一级依赖,就会形成一颗巨大的依赖树。Linux 发行版的存在,主要原因就是为了解决复杂的依赖关系。想象一下,如果操作系统的所有组件都需要自己一点点去找,还要在保证依赖关系(比如有些软件包依赖特定软件包的特定版本)的情况下,搭建起整个可用的操作系统,这样的工作量想想就觉得可怕。而 Linux 发行版通过从软件提供者手中获得软件并打包的方式,将绝大部分用户所需的软件放入其软件仓库,让用户可以轻松便捷地使用操作系统。

你可能会问,为什么 Windows 就没有类似的问题呢?那是因为微软作为商业公司,已经帮开发者完成了操作系统很多的依赖组件了,因此软件的开发和使用才会如此无痛。而 Linux 的依赖问题总是被人诟病,甚至出现了一个词叫做 dependency hell ,拿来形容操作系统的依赖关系无法满足时引发的令人炸毛的问题。

当然,解决办法总是有的。Linux 发行版已经为用户做了很多工作,比如 package maintainers 会负责检查并打包上游的软件包,标注好所需的依赖软件名称和版本号,以及和它冲突的软件名称等等。发行版也会让自己软件仓库中的软件满足好依赖关系。有了这些信息,满足用户系统上的依赖性问题无非是一个算法问题。当然这个问题不该由用户来做,而是让一个更加自动化的管理工具来完成,这就是「包管理器」。

Ubuntu 使用的包管理器是 APT ,实际上它也是 Debian 的包管理器(所有基于 Debian 的发行版都使用 APT 作为包管理器)。它的作用是帮助用户将本地软件包的信息与发行版软件仓库进行同步,下载、安装用户指定的软件,协助解决依赖足问题等等。我们可以把软件管理的任务统统交给包管理器解决,这样生活就轻松多了!

5.3. APT之超级牛力

5.3.1. 安装、卸载和搜索包

在命令行输入 apt ,按回车。

我是不是不用往下讲了!?重要的命令全在这里!

注意到最后一句话:

本 APT 具有超级牛力。

这个可是真的,处理好这么多软件包的依赖关系可不是容易的事情。我当前的系统有三千多个软件包,全部都被 APT 管理得井井有条。

不过 apt 与 APT 并不是一回事。APT 的全称是(Advanced Package Tool),实际上是用于管理 Debian 软件包的一系列工具。我们以前常用的 apt-get 是其中的工具之一。但以前的包管理工具对用户而言不太友好,因为用户常使用的命令分散在几个不同的工具中(比如用 apt-get 安装和卸载软件包,用 apt-cache 搜索和查看软件包信息),而一个统一的命令会让用户的使用更方便,这就是 apt 出现的原因。 apt 相比上述的两个工具还多了彩色进度条输出和细节提示,增强了用户体验,所以建议大家今后尽量使用 apt 而不是 apt-getapt-cache

那这么多包管理工具在一起不会打架么?实际上并不会,因为他们都属于「高层包管理器」,而实际用于安装、卸载软件包,反馈依赖关系是否满足的,是「中层包管理器」dpkg。也就是说,高层包管理器只是负责协助用户与软件仓库同步软件包信息,下载安装用户指定的软件包,计算出需要的依赖包并且一并下载安装等等任务,为用户提供了一套方便的交互前端。有「中层」那就一定有「底层」,这个底层就是 dpkg-deb ,只是用于查看软件包的控制信息和抽取软件包中的文件。

由于软件包需要安装在系统目录下,因此与包管理相关的操作(除了读取外)都需要 root 权限。

在安装包前,一般需要与仓库同步软件包信息:

sudo apt update

安装包命令:

sudo apt install <package name>

卸载包命令:

sudo apt remove <package name>

默认在卸载时不会删除包的配置文件信息,如果需要删除,在最后面加上 --purge 参数即可。

搜索包:

apt search <package name>

因为搜索只是做了读取操作,因此不需要 root 权限。

5.3.2. 自动安装、手动安装和孤儿包

自动安装的包和手动安装的包待遇是不同的。

手动安装的包就是用户指定安装的包,比如我想安装的记词软件 Anki ,那么我指定安装的软件包就是 anki ,而 APT 通过解析发现还需要图形库 python-pyqt5 ,并将其自动安装,那么 python-pyqt5 就是自动安装的软件包。

有什么区别呢?

如果我删除了 anki ,那么包管理器会认为既然 python-pyqt5 这个包是自动安装的,现在也不被任何手动安装的软件包依赖(当然实际有可能其他手动安装的软件包也依赖于它,这里只是假设),那么它就是一个「孤儿包」。(就好比 anki 生下了 python-pyqt5 ,现在 anki 走了,而且没人要 python-pyqt5 ,它就成了孤儿。)包管理器会自动提示用户, python-pyqt5 是自动下载且不被任何软件包需要,可以通过 apt autoremove 进行删除。

所以可以通过下面的命令删除当前所有的孤儿包:

sudo apt autoremove

如果想删除配置文件,一样可以在后面加上 --purge 参数。

一般来说,如果包管理器提示可以自动删除某些包,删除就是了,要不然会一直提示用户非常烦人,而且像我这样有些洁癖的人来说,孤儿包的存在是不可容忍的!

但是还是要小心,因为我在网上看到很多人因为自己删了某个软件包,导致自己的桌面环境也被当做孤儿包被删了(我倒是没有遇到这个情况,因为我使用的操作系统已经默认将桌面环境相关的包标记为手动安装)。我觉得很有可能是发行版打包的失误,或者用户动了某个不该动的元包(meta package,依赖于一系列包的软件包,也就是说安装一个元包就可以自动安装一系列相关的包,例如桌面环境的元包)。总之在 autoremove 前瞄一眼就行了,不过出现这种情况的概率实在太低太低了,而且即便真的删了桌面环境,照样能装回来!

还有一种情况和孤儿包无关,那就是手动删除了某个依赖包时,包管理器会自动删除依赖这个包的软件包,也就是说如果我删除了 python-pyqt5 ,也会自动把 anki 删除掉。

虽说会有出现意外的可能,但只要用户正常操作,这种情况完全能够避免。

5.3.3. 包从哪里来

  1. 本地包

    之前已经提到过,发行版会将上游的软件打包并纳入自己的仓库中。但是依然有两个问题存在:

    • Debian 系发行版一般采用的是 point release ,也就是每隔一段时间发布一个大版本,而在大版本中的软件包是已经经过一段时间的测试并确认稳定的,因此软件仓库的包普遍偏旧,无法满足用户使用新包的要求;
    • 有些软件根本没有纳入发行版的软件仓库中(压根没有被发行版打包),无法满足用户使用该软件的要求。

    这种情况下该怎么办呢?一个最容易想到的方法就是,直接去软件提供方找。在开源生态下,软件作者起码会提供源代码,能让用户自己编译安装。不过多数软件作者都会提供自行打包好的软件包,这样用户就可以把软件包下载到本地,并直接安装编译好的软件包了,而且由于是一个打包好的软件包,还能被包管理器所控制。

    Debian 的软件包格式是 deb ,你下载的 .deb 文件就是软件包了。实际上打包的方法非常简单,有兴趣的小伙伴可以去 Debian Wiki 看一看!

    如何安装呢?在网上你经常会看到推荐这种方法:

    sudo dpkg -i <package name>
    

    等一等!刚才说过,dpkg 是一个中层包管理器,并不负责帮用户「解决」依赖关系。也就是说,如果这个本地软件包需要的依赖包在系统中不存在,虽然 dpkg 会帮我们把软件装上,但它会标记为安装不完全,并且一直提醒用户有未满足的依赖关系。

    那该怎么办?在网上很多人会告诉你:

    sudo apt-get install -f
    

    像之前说的,实际上这里的 apt-get 可以被 apt 代替了。那么这行命令的作用是什么呢?重点是最后一个参数 -f ,它是 --fix-broken 的简写,顾名思义就是修复损坏的依赖关系。APT 会帮助我们在仓库中搜索对应的依赖包,并把它们装上。(如果依赖包并不在仓库里就比较麻烦了,不过一般不会出现这种情况。)

    可是这样不是绕了一个弯子吗?何不直接让 APT 帮我们安装本地软件包,顺便也帮我们装好依赖包,这样多好!

    方法也真的很简单,只是比较少的人提到:

    sudo apt install <package path>
    

    注意最后那个参数是 本地软件包的路径 ,举个例子:

    sudo apt install ./lsd_0.13.0_amd64.deb
    

    它安装的是当前目录下的 lsd_0.13.0_amd64.deb 软件包,别漏了 ./ 来表示当前目录,要不然它会去仓库中找软件包,而不是本地。也别忘了后缀名 .deb 。Linux 并不靠后缀名来区分文件类型,基本它的后缀名是 .txt 一样可以是个 deb 包。后缀名的作用主要是帮助用户识别不同的文件类型而已。

    当然你的系统可能也已经自带了「GDebi软件包安装程序」 ,这是一个图形界面前端,能让用户鼠标双击软件包轻松安装软件。

  2. 仓库和PPA

    但是这样还是太麻烦了,如果软件包有更新,用户还要自己去软件作者那里获得新版本重新安装。有没有更简单的办法呢?

    有的!那就是第三方软件仓库。任何人都可以搭建自己的软件仓库, Debian 和 Ubuntu 也从来没有限制这么做(Ubuntu 甚至提供了一个更便捷的平台)。

    比如我想安装一个 Windows 应用的兼容层 WINE (让用户可以运行 Windows 程序),我会选择去 WINE 的官方网站找到对应的发行版的安装指南,并一步步进行操作。主要会经历以下几个步骤:

    • 添加仓库密钥
    • 添加仓库
    • 更新软件包信息
    • 安装软件包

    实际上并不复杂不是吗!但作为软件作者,自行搭建一个软件仓库还是有些麻烦,所以 Ubuntu 提供了一个平台叫做 PPA(Personal Package Archives),软件作者可以免费将软件打包并发布在 PPA 上面。本质上 PPA 也是一个软件仓库。

    比如说一个月前自己想使用 Emacs 26 ,而 Ubuntu 仓库中的 Emacs 版本是25。后来我选择了一个 PPA ,它的维护者将最新的稳定版 Emacs 打包上传(即便他不是软件作者也可以打包上传,毕竟 Emacs 是自由软件),我只需要加入 PPA 信息,安装软件即可( add-apt-repository 已经把添加秘钥的工作做好了,所以不需要用户操心):

    sudo add-apt-repository ppa:kelleyk/emacs
    sudo apt update
    sudo apt install emacs26
    

    那么如何删除与软件仓库的连接呢?Ubuntu 预装了一个 GUI 工具叫做「软件和更新」,打开后在「其它软件」标签下就可以看到所有连接到的仓库了,想删除的话直接选中,点击「删除」就行了。

    实际上这个 GUI 工具做了什么事呢?

    所有与软件仓库有关的信息都存放在 /etc/apt 目录下面,其中 PPA 以外的软件仓库信息写在 sources.list 文件中,与 PPA 相关的信息在 sources.list.d 目录下,一般一个 PPA 的信息会单独写在这个目录的一个文件当中。另外,PPA 以外的仓库的秘钥信息存放在 trusted.gpg 文件中,PPA 的秘钥信息在 trusted.gpg.d 目录下。

    如果你只是想暂停使用某个仓库(在 GUI 工具中把对应仓库前的勾取消掉),那只是会把 souces.list 中或者 sources.list.d 目录下与该仓库相关的信息注释掉,而秘钥当然不会删除;但如果你在 GUI 工具中删除某个仓库,实际上它也只是把对应写有仓库信息的文件中的相关几行删除,秘钥也不会删除。

    如果你没有洁癖,实际上也无所谓,如果真的想完全删除干净,那直接去那个目录把文件删除就可以了,只不过也没有什么必要。

    除了用 GUI 工具外,使用命令行当然是可以的。有下面几种方法可以选择:

    1. 使用 add-apt-repository 删除软件仓库,但是它不会删除用该 PPA 安装的软件,以删除上面提到的 Emacs 仓库为例:

      sudo add-apt-repository --remove ppa:kelleyk/emacs
      

      要删除非 PPA 仓库也一样,只要在添加仓库的命令上加入 --remove 参数就行了。

    2. 一个好的选择使用 ppa-purge ,它不但能删除 PPA ,也能删除用这个 ppa 安装的软件,并且如果同样的在官方仓库,会换成官方仓库的版本:

      ppa-purge ppa:kelleyk/emacs
      
    3. 去除密钥可以使用命令 apt-key del xxx ,其中 xxx 是用 apt-key list 查到的密钥的16进制后8位。

    注意删除文件可以在命令 rm 后加上 -i 参数交互式删除,避免误删。

5.3.4. 手动解决依赖问题

这种情况一般出现在自行编译安装软件的时候。比如说在运行 configure 的时候说缺少某个 .h 头文件。

首先,软件作者很可能已经给出了所需要的依赖包,去软件仓库找到这些包安装就行了。但很多时候软件作者没有给这些信息,那该怎么办?除了上网搜索有没有其他人遇到同样的问题之外,还有一个方法是使用一个叫做 apt-file 的命令行工具,不过这个工具 Ubuntu 并没有预装,得自己额外安装。

如何使用呢?直接用 apt-file --help 看一下就行了。说明的最后一段提到:

Action: update Fetch Contents files from apt-sources. search|find <pattern> Search files in packages list|show <pattern> List files in packages

对于我们提出的问题,使用 search 或者 find 就行了:

apt-file search <file name>

如果已知所缺文件的准确路径,传入整个路径就行了。 apt-file 会帮我们返回所有包含这个文件的软件包,把对应软件包装上就可以了。

5.4. Synaptic

APT 工具的命令确实有点多,要是记不住也问题不大,因为有一个非常好用的 GUI 前端工具叫做 Synaptic,中文叫「新立得软件包管理器」(这个翻译不错!)。

使用方法很简单,你打开来就会用了。这个软件在打开时就需要输入 root 密码提升权限,在整个操作过程中都是有管理员权限的,所以操作得小心。

我觉得 Synaptic 奇妙的地方在于,你会发现原来所不知道的 APT 具有的功能,明白原来 APT 真的在管理一切和软件包相关的事情。它知道你装了哪些本地包,各种包的文件放在了哪些目录,哪些被删除的包的配置文件还被保留,软件来源是哪里等等。所以有了 APT 后就完全不需要担心系统中的软件一团糟了。

5.5. 别弄乱系统目录

5.5.1. 编译安装

对于想长期使用 Linux 的用户来说,管理好系统目录是很重要的一件事情。比如今天你通过编译安装的方式安装了某个软件,那么它虽然把文件放在了系统目录下,但却因为绕过了 APT 而无法被其管理。

举一个简单的例子,如果你昨天通过编译安装的方式安装了一个软件 A ,绕过了 APT 的管理,第二天想要更新系统,恰好也需要安装一个打包好的软件包 A ,由于 APT 并不知情,它不会略过这个软件包的安装。结果可想而知,由于先前编译安装时已经将软件的文件放在特定目录下,APT 会报错说文件冲突,无法安装软件包。这种情况尤其可能会在 point release 的大版本更新时出现,而且具体情况可能复杂得多。

如果你并不关心更新,那么如果你想删除呢?很多软件并不提供卸载软件的脚本,如果你是通过编译安装的方式安装,很可能会因为不清楚软件安装时把文件放在了哪里而无法卸载。

有什么好办法能解决这个问题呢?下面给出我个人的看法。

首先,能不编译安装就不编译安装,因为普通用户确实用不到很多编译的参数,编译安装还容易踩很多不必要的坑,而且直接使用打包好的软件包是最方便的方式。而如果某些情况下一定要编译安装,我会推荐一个命令行工具叫做 checkinstall

checkinstall 的功能是跟踪这个命令后的命令释放文件的路径,并打包成当前系统所使用的软件包格式。使用方法很简单,在它后面跟任何的安装命令都 ok 。Debian Wiki 上有这个工具的说明,如果想要查看详细文档可以去CheckInstall 的主页

从个人使用经验来看,最好像 Debian Wiki 中提到的那样,加入 --install=no 这个参数,先打包再安装。否则如果先安装再打包,可能会因为在打包阶段填写控制信息出错而无法生成软件包的情况,这样就要去系统文件夹手动删除已经释放的文件了。不过也不用太担心,因为在释放阶段已经详细输出了已经释放的文件的路径,所以不会找不到哪些文件。

总之,使用 checkinstall 就能将编译安装的软件通过打包的方式纳入 APT 的管理范围,这样就不怕出问题了!

5.5.2. 多个包管理器

除了编译安装外,也有其它弄乱系统目录的可能。以大家熟悉的 Python 做例子。可能大家会使用 Python 的包管理器 PyPI (也就是 pip )来安装 Python 的第三方库。但是容易出问题的事情是,很多人会使用系统的 Python 环境跑自己的代码(非软件开发性质的),并用 PyPI 安装自己想要的第三方库。这是不推荐的做法,因为 PyPI 的包管理绕过了管理系统软件包的 APT 。正确的做法是什么呢?如果想做软件开发,尽量使用软件仓库的软件包(deb 包),如果做科学计算等任务,最好使用一套与系统 Python 环境隔离的环境,比如 Anaconda 。前一种做法保证了 Python 库文件纳入 APT 的管理范围,后一种做法干脆就把 Python 环境放在用户目录下,与系统软件包不相干,这样最省事了。

可能出现类似情况的还有 Node.js 的包管理器 npm 。不过由于 nodejs 并不是系统自带的软件包,因此出现包管理冲突的可能性不大,不过最好还是不要用 npm 把全局包装在系统目录下,也就是避免使用 sudo npm install <package name> -g 。我的解决方法是在用户目录下的 .bashrc.profile 添加如下两行:

export NPM_CONFIG_PREFIX="$HOME/.npm-global"
export PATH="$HOME/.npm-global/bin:$PATH""

第一行告诉 npm 将全局包装在 ~/.npm-global 下,第二行将 ~/.npm-global 这个路径加入环境变量 PATH 。我参考的是这篇文章

5.6. 谨慎使用第三方仓库

第三方仓库终究只是第三方仓库,没有发行版的背书,不能保证软件的安全性和稳定性。因此作为用户,首先要甄别这个第三方仓库是否是值得信赖的仓库,否则出了问题可没人能负责。

5.7. Snap,Flatpak和Appimage

Linux 世界不只有 Debian 系发行版,还有 Redhat 系,Arch 系等等,各自使用不同的包管理机制,软件包的打包格式也不相同。对于软件开发者来说,这是一件比较头疼的事情,因为他们需要把自己的软件打包成各种各样的格式,来满足不同 Linux 发行版的需要。作为 Debian 系操作系统用户,一个福利是 deb 包的官方软件仓库是全宇宙最大的,而且多数软件都会优先提供 deb 包,但是对其他发行版用户来说就不是这么回事了(不过 Arch 用户有个 AUR 倒是很方便,软件总量也许加起来比 Debian 系的还多)。

对于这种分裂,一种可行的解决方案是,把软件本身所需要的依赖打成一个包,并把它放在一个相对隔离的环境下运行,做到一次发布,所有发行版都可使用的效果。

Snap,Flatpak和Appimage就是这种解决方案的三种实现。Snap 主要是 Canonical 在推,而 Flatpak 主要是 Redhat 在推。这三种实现的原理我并不了解,所以也没有办法和大家解释清楚。从表面上看,Snap 和 Flatpak 比较相似,而这两个中我只用过 Snap (因为 Ubuntu 自带 Snap)。Snap 看上去是在系统中划出了许多个虚拟的分区,你可以用 lsblk 命令看到这些分区的存在。它为每一个 Snap 应用划分一个虚拟分区作为容器,将应用程序放在这个容器中。

Appimage 的实现方式有所不同。它是这三者中最简单的。你在运行 Appimage 前什么都不用做,不像 Snap 或者 Flatpak 还需要额外安装一个使用框架,你只需要获得一个 Appimage 可执行文件就行了,打开就能使用。所以这三个中,Appimage 是我最喜欢的一种。

Flatpak 由于自己没有使用过,没有经验可以分享。而 Snap 我个人并不推荐,主要有几个原因:

  1. 服务器在国外,下载时连接速度非常慢;
  2. 用户与软件发行方直接关联,没有发行版的安全保障;
  3. 非自由软件生态;

我的看法是,deb > Appimage > Snap/Flatpak ,给大家参考。

6. 权限/用户与用户组

Footnotes: