分类 独立文稿 下的文章

视频点此

我已经说过不少服务器的应用了。日常来讲,你可以拥有自己的博客网站、自己的云盘、自己的离线下载服务、自己的RSS订阅工具、自己的软件下载站,甚至开一个自己的Minecraft服务器。这其实已经差不多了吧?

但有一点是肯定的,只要你想,那么一台服务器肯定就不止这点用处。就比如今天要来说说的——搭建一个自己的发件服务器。


一、几个解答

1、这个发件服务器有什么用

显摆。因为你的邮箱地址,@之后的内容是别人没有的。

当然,不只是这样。

举个例子:如果你去过我的博客,你就会看到公告,说评论邮件提醒服务已上线。这就是发件服务器应用的地方。因为使用第三方的smtp服务,一来,每天的发件数量有限制;二来,发件的频率有限制。可不要说什么我这博客到不了发件上限,那是因为有很多的垃圾评论被我给屏蔽掉了,你看不到而已。

2、为什么只发不收

我之前说过,这个系列一定程度上是我自己使用我VPS的记录。而对于邮件,我用不到收信功能,所以没有赋予这个功能。

3、可以有收信功能吗

当然可以。改多一些配置文件就可以了。

4、增加收信功能难吗

给你这么一个答案:可以难。

你可以在自己的服务里配置收件箱、邮件解析功能,从而实现一个完整的邮箱服务,这听起来就相当麻烦;但也可以搞成一个中继,所有发到这个地址的邮件,自己不做解析,而是直接转发到别的邮箱——比如说自己的hotmail邮箱——里边,用户通过hotmail来管理这些邮件,这样难度就下来了很多。所以说,增加收信功能,可以是难的。

5、我需要有什么基础条件

与之前介绍的不同,搞一个自己的信使服务还真需要你有几个基础条件:

  1. 25端口开放——如果你想远程使用这个邮箱,而不只是给部署在同一台服务器的博客来用的话。当然,你也可以把端口放到465,但如何做我就不说了。因为我也没弄过。
  2. 有自己的域名。这样才能显示一个正常的邮箱地址,并最大程度避免被邮箱服务商当做垃圾邮件的概率。
  3. 如果想随时随地使用,部署在VPS是必不可少的。但还是那句话,如果只是给部署在同一台服务器的博客来用的话,那便无所谓了。

6、有什么安全措施

像我已经在用的这个,因为官方的25端口是封闭的,所以从根源上便拒绝了非法用户通过这个服务向外派件的可能性;加之我这个方法最终会使用独立的用户名和密码,而不是默认的使用登录用户做用户名,登录密码做邮箱认证密码,所以不至于泄露自己服务器的用户名。只是要注意,这样得到的邮箱是不带有SSL加密的。所以传输过程中的信息就不保证安全了。

好,介绍了这么多,来看看到底要如何配置。


二、配置

1、调整组件

CentOS里边默认会安装postfix。而有些系统默认的邮件服务是sendmail而这个服务公认的差。所以为了调整服务,先来调整好组件。同时,也保证需要的用户组被创建。

yum remove sendmail #卸载sendmail
yum remove postfix #卸载postfix
yum install postfix #重新安装postfix
#yum安装会自动建立postfix用户组和用户名
yum install crontabs #因为卸载postfix的时候系统定时服务可能会被卸载所以也运行一次安装命令确保组件存在

2、增加组件

postfix默认的邮箱账户名是登录系统的用户名,密码则是登录系统用户的密码。所以为了得到独立的用户名密码,需要安装相应的服务。

yum install cyrus-sasl*  #提供smtp的虚拟账户和密码服务

3、配置MTA

MTA就是邮件发送端。刚刚卸载又安装的postfix就是为了完成这个任务的。因此现在,需要调整系统默认的MTA到postfix。

/usr/sbin/alternatives --set mta /usr/sbin/sendmail.postfix

alternatives --display mta #查看调整结果
#如果输出的最后一行显示如下:
#Current `best' version is /usr/sbin/sendmail.postfix.
#说明设置完毕

4、配置自启动

既然是服务,那自然希望它会在服务器重新启动后的第一时间上线。所以设置自启动。

systemctl enable postfix

5、配置postfix

编辑/etc/postfix/main.cf,更改下述内容。

myhostname = #二级域名。如smtp.bwsl.wang
mydomain = #主域名,即删去二级域名剩下的东西。如bwsl.wang
myorigin=$mydomain
inet_interfaces=#localhost或本地回环地址
#填入公网ip会对外开放(25端口未封闭的话)
#默认应该是all,收发皆可
#如此更改即关闭收件功能
mydestination = $myhostname, localhost.$mydomain, localhost
#这里默认值应该就是这样,是则保持,不是则改
mynetworks=#公网地址,127.0.0.1
#填这两个就可以了

再新增下述内容,开启单独的登录名和密码服务

#SMTP Config
smtpd_client_restrictions = permit_sasl_authenticated
#指定可以向postfix发起SMTP连接的客户端的主机名或ip地址
#此处permit_sasl_authenticated意思是允许通过sasl认证(也就是smtp链接时通过了账号、密码效验的用户)的所有用户
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
#发件人在执行RCPT TO命令时提供的地址进行限制规则
smtpd_sasl_auth_enable = yes
#启用smtp并要求进行账号、密码效验
smtpd_sasl_security_options = noanonymous
#取消smtp的匿名登录
message_size_limit = 5242880
#指定通过postfix发送邮件的体积大小。单位字节

6、创建连接邮箱服务的用户名和密码

先来编辑/etc/sasl2/smtpd.conf。对于32位机,这个文件路径是/usr/lib/sasl2/smtpd.conf

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: plain login CRAM-MD5 DIGEST-MD5

现在,就可以创建账号了。使用命令:

saslpasswd2 -c -u `postconf -h mydomain` username

回车后,会提示输入密码。输入一次,重复一次,用户名为username的邮箱便建立好了。邮箱地址将会是[email protected]

你可以通过这个命令建立多个用户和密码。日后也可以通过命令sasldblistusers2来查看已有的用户名。密码不能看,只会显示userPassword

7、调整权限

需要调整sasl的用户数据权限,让postfix可以读取:

chmod 755 /etc/sasldb2

现在,设置几乎全部完成,可以启动信使服务了。使用命令

systemctl start postfix

三、测试服务

为避免网络端口封闭问题而导致的莫名其妙的问题,我们最好是通过服务器本机连本机来进行服务的测试。所以还是在服务器的窗口内,运行telnet命令(没有则先安装telnet):

telnet localhost 25

我们还需要额外准备两个内容:

  • 刚刚建立的邮箱用户(带@之后的内容)的base64编码
  • 用户对应密码的base64编码

这两个的获得很容易,百度base64就有很多转换工具,随便一个就好。

然后便可以回到服务器的命令行,进行验证过程

HELO bwsl.wang #尝试握手,返回消息后继续
AUTH LOGIN #请求smtp账户密码校验,返回消息后继续
#输入刚刚获得的用户名base64,返回消息后继续
#输入刚刚获得的密码base64

输入密码后回车,应该就可以看到Authentication successful认证成功的消息。这便证明,一个发件服务已经搭好了。

四、调整域名解析

别着急应用到博客里。现在应用,那发出去的邮件一定连垃圾箱都不进,直接就被拒收了。我们还需要进行最后一步:配置域名解析。

进入你的域名解析调整页面,新增三项:

  • myhostname对应的二级域名,A类解析到服务器IP
  • @域名,MX解析到myhostname对应的二级域名
  • @域名,TXT解析成v=spf1 a mx ip4:服务器ip -all

至此,一个发件服务便建立完成了。你可以通过linux的mail命令来尝试发送一个带有独一无二邮件后缀的邮件了。好好利用吧。


可以通过 https://www.mail-tester.com 对你的服务进行测试,并根据提示进行对应的修改以提高得分

视频点此

你要注意看这个标题。我并没有指定主语。这说明,不是我换回了Windows,也不是你换回了Windows。而是那些看过我这个视频之后,盲目的切换到了Linux而并没有做任何了解的用户。说到这儿我还得啰嗦一句:这个视频从简介到动态,都说明了只是我的感受,为什么还会有很多人把它当成一个推荐视频呢…既然这样,那我就再做一个与之相反的内容,让你看的更清晰一些吧。

1、硬件支持

硬件支持总会是Linux的一个问题。通常是因为厂商不打算支持Linux,或尚未适配。如一些无线网卡,或者最新的硬件。但这其实不代表以后不会支持。最典型的就是英特尔的CPU,当新的CPU上市时,Linux通常要延后几个月才能获得相应的支持。所以如果你把Linux装在一台拥有最新CPU的电脑上,那么它通常是不能正常运行的,这一定会驱使你回到Windows。但几个月之后再安装Linux,由于有了新版本的内核,通常就可以了。

2、太多的选择

Windows只有Windows,而Linux有很多Linux。

Linux有各种各样的发行版,而你在这个基础上又有各种各样的选择权。包管理器用哪个、桌面环境用什么、观感主题怎么配、文件管理器装哪个…成千上万的方案对于新用户来说,压迫感很强——当然,也是选择困难症的地狱。

这便会导致一种情况:用户不喜欢这个发行版,因此去尝试一些其他的。试过一些之后:好了,我有了一些了解了,所以现在我想回到Windows了。因为Windows很棒、我很熟悉,并且我知道我要用什么来做什么;而Linux有很多东西要学,有很多东西要自定义。对于新用户来讲,我要怎么自定义是一个选择上的难题,自定义很可能会导致的一些问题则又是一个技术性难题。

3、游戏

你需要明白一件事:现在的Linux娱乐性已经强大很多了。

因为我也玩游戏——当然是使用我的Linux:欧卡2、call of the wild、gta5、csgo、喋血街头…但很多用户并不这么做,甚至连尝试都不尝试就给出“Linux娱乐性不高”的结论。这在几年前是很正确的,但现在再说这种话,我只想给他冠以“落后”、“云用户”这几个标签。因为他不知道protondb.com——一个告诉你Steam的游戏在Linux上运行状态的网站,也不知道lutris.net——一个帮你整理并且一键运行非steam游戏的应用,更不知道在Steam里边,通过Steam OS标签得到的游戏结果只是Linux可以运行的游戏的一小部分。至于为什么,以后再说。你只需要明白Linux的娱乐性不再是几年前的穷苦样便可以了。

但不可否认,无论如何,Linux可以游玩的游戏数量也是比不上——可能永远也比不上Windows的。所以仍然有一部分游戏会让你放弃Linux。比如PUBG,以及一些需要VR设备的游戏。

4、软件缺失

这可能是很多人换回Windows的一个问题所在。比较有代表性的软件就是Adobe Creative Cloud和Microsoft Office。这些虽然可以通过wine来运行旧版本的,但表现一般不会很好。所以如果你一定要使用它们而不愿意去使用替代品,那么最好的选择就是好好的待在Windows,不要再考虑Linux了。

同样的比如CAD制图,Linux下面与AutoCAD操作思路类似的一款替代软件叫做DraftSight,还有其他比如FreeCADOpenCAD等等替代品。

总之,软件缺失是大问题,但除非真的是小众的软件,通常并不会真的缺失,只是看你愿不愿意百度一下相关替代软件,想不想使用替代品——不需要适应新操作新思路便可上手的替代品,仅此而已。

5、缺少技能知识

没有对应的知识可能是最大的一个问题了。

只看日常使用的话,Windows相当易用——从它的观感以及广大的用户群就可以体现出来。但Linux,就像刚刚所讲,有太多的选择权和自定义权,学习每一种选择的操作方法需要大量的时间。

Linux就像Minecraft,你可以随心所欲的做任何想做的事情——前提是你要研究,你要有一些知识才能充分的利用它。

但很多用户只是想通过他们在Windows上已经获得的知识来使用他们的电脑,对学习一个新的操作系统并不感兴趣。所以,这便从根源上杜绝了他们更换操作系统的可能,进而形成了用户黏度。这对于其他软件、甚至是日常生活同样适用。


以上,是我总结的会让你放弃Linux的五点。在之前的视频里,我从动态到简介都说了:只适用于我自己,不要生搬硬套,所以你非要把它当成我推广Linux的视频,那我也没辙。我从来不会推荐人们去使用哪一个操作系统,因为这种东西最好的答案是去自己尝试。我只是我,我习惯它,所以我使用它;我把它推荐给你,你不习惯,那么你对它的第一印象便是差的,这很不好,甚至形成刻板印象。只有当你想的时候,再去了解它、熟悉它,这才是接触新事物应有的过程。人云亦云,盲目跟从,图一时新鲜,总不会是一个长久之计。

视频点此

之前说过了使用transmission搭建bt离线下载服务。但是这个的局限性在于只支持种子和磁力链的下载。那对于迅雷、百度网盘、FTP,或者仅仅是普通的http下载,有没有什么办法呢?

当然有。aria2,一款命令行操作,基本可以做到全速下载的强大的下载工具,并且支持迅雷离线以及百度云等常用网盘的多线程下载(甚至可以超过专用客户端的下载速度)。但就像我刚刚说的,Aria2是一个命令行软件,很多人嫌麻烦或者不会弄,就这样错过了一个下载神器,因此我们可以使用一个Aria2的控制前端,直接通过浏览器来操作下载。不但操作更加简单容易,还能架设在服务器上面,造就一个全功能的离线下载服务。来看看怎么弄。

一、部署前端

因为之前已经安装过宝塔面板,所以直接通过它来完成。
  • 登录面板,新建一个纯静态站
  • 进入这个静态站的根目录,远程下载WebUI项目到这个目录并解压(Download ZIP即可,不必git clone)
  • 进入刚刚解压出的文件夹,将里边的文件全部拷贝到网站根目录
  • 进入docs文件夹,将文件全部拷贝到网站根目录

至此,前端已经部署完毕了

二、部署后端

因为已经安装过宝塔面板,所以默认http的组件已经安装好了,否则请配置httpd以保证web页面可以正常显示
  • 安装aria2:yum -y install aria2

至此,后端就部署完毕了

三、运行

  • 先启动后端:aria2c --enable-rpc --rpc-listen-all --rpc-secret 你的密码
  • 进入宝塔面板 - 安全,放行6800端口
  • 现在,进入webUI,应该会提示无法连接服务。点击设置——连接设置,配置好主机、端口号(应该是6800)、密码令牌(启动后端时,rpc-serct后面的字符就是了)即可。

至此,一个几乎全能的离线下载服务已经搭建好了。只是需要注意一点,通过ssh启动后端时,需要让其在后台运行。你可以使用screen这个包来实现,或者直接在命令的结尾加一个&即可。

视频点此

利用服务器搭建一个BT种子/磁力链下载机,省去我们自己挂机的烦恼。如果你的VPS在国外,可能还会起到些许加速的作用。

请注意,我服务器的操作系统为CentOS7,安装有宝塔面板

一、安装并配置Transmission

Transmission 是一款开源、跨平台的BT文件下载客户端,同时也提供有服务器使用的离线下载方案。对于大多数Linux发行版来说,Transmission已经进入到软件源中,只需要安装并进行简单的配置便可以投入使用了。

1、如果之前没有配置epel源,需要先行添加

yum -y install epel-release
yum -y update

2、安装Transmission-daemon

yum -y install transmission-daemon

3、先运行一次,以产生配置文件

  • 先启动 systemctl start transmission-daemon
  • 再关闭 systemctl stop transmission-daemon

4、编辑文件/var/lib/transmission/.config/transmission-daemon/settings.json,查找并修改如下几句以保证可以在任意地方通过账户密码登陆管理transmission

"rpc-authentication-required": true,  
"rpc-enabled": true, 
"rpc-password": "远程调用的密码", 
"rpc-whitelist-enabled": false,
"rpc-username": "远程调用的用户名", 

5、如果想在服务器重启后这个服务可以自动启动,可通过命令systemctl enable transmission-daemon实现

二、配置宝塔面板

1、在安全页中,放行9091端口

注意:transmission默认使用9091端口。所以请保证9091没有被占用。否则请在刚刚提到的settings.json中修改端口号

2、配置一个nginx下载,指向transmission的下载目录。默认是 /var/lib/transmission/Downloads

nginx下载服务配置方法,参见 利用Nginx建立简单的下载服务器


现在,通过命令systemctl start transmission-daemon来启动,并在浏览器中输入服务器ip:9091来看看吧。

至此,一个基本的种子离线下载环境就搭建完成了。默认的界面有些简陋,可以自行进行美化。同时,settings.json文件中还有很多其他的设置向,根据需要修改即可。

视频点此

先来假设一个场景。

众所周知,Steam的软件一定是保存在某一个文件夹下面的。假如说,我有一个分区专门保存我的游戏,那么我如何才能将Steam的游戏都直接放在分区下面而不是在Steam库文件夹下面呢?

在看过我今天这个神奇的快捷方式之后,你就知道要怎么做了。


要注意,今天这个功能,Win、Linux、Mac都是可以使用的。只是Win与另外两者的命令有些不同。而Linux对文件之类的快捷方式本身就会用到这种。所以为了对比,我这次在Win下进行演示。直接上演示让你感受一下。

一、文件

我事先已经安装好了{{7z这个压缩软件:C:\Program Files\7-Zip}},是可以正常使用的。现在,我把安装目录下的7z.dll剪切到{{桌面:C:\Users\gameb\Desktop}}。显然,由于缺少了7z.dll这个库,尝试运行时候会提示出错。

如果我们把7z.dll复制一份普通的快捷方式放到安装目录下面,它可以运行吗?很明显,快捷方式只是一个很弱鸡的快捷方式,并不能行使dll文件本身的职能,所以还是出错的。顺便请你记住这个快捷方式的大小:1KB.

现在,用管理员身份打开命令提示符,使用mklink "C:\Program Files\7-Zip\7z.dll" C:\Users\gameb\Desktop\7z.dll的形式来召唤那个更强大的快捷方式。

可以看到,它的大小占用为0K. 然而,虽然体积近似于没有,但当我们尝试运行7z的时候,你会惊奇的发现:它可以运行了!这个比弱鸡快捷方式的体积还小的快捷方式竟然可以履行dll本身的职能!

二、文件夹

现在,我们在把目光转移到文件夹上。我事先在桌面建立了一个名字叫temp的文件夹。现在我们创建一个普通的快捷方式,放到这个文件夹内,双击,资源管理器的路径会显示到哪里?

没有错,还是它本身的位置没有动。

但是,通过命令mklink /D C:\Users\gameb\Desktop\test\test C:\Users\gameb\Desktop\test,为它创建那个强大的快捷方式,放到它自身目录下面。如果我们双击这个,资源管理器的路径会如何变化?

正如你所见,它真的多了一层!不断的双击还会不断的加多!这个快捷方式真的行使了文件夹的职能了!

这个快捷方式,叫做符号连接

至于它太细节的东西我不打算多说了,因为说了也没啥用。只通过这个图来给你简要说明一下符号连接与快捷方式的不同之处就好了。

正如你所见,一个文件被存放的时候,它会对应一个名称保存在分区开始的内容表中。而快捷方式其实是一个类型为快捷方式的文件。当我们双击快捷方式的时候,其实是访问了快捷方式这个文件,然后它再给引导到它所对应的文件上面。本质上快捷方式和它所对应的文件是不一样的。

但符号连接就不同了,它其实是文件的另一个名字,所以我们双击符号连接和双击文件本身的效果是相同的。

形象一点来说。假如我是用户,你是文件,我直接访问文件就是我直接找的你;而快捷方式就是你公司的传达室大爷,我通过快捷方式访问文件,就是我去找这个老大爷,让他帮我传个话;那么符号连接,就好比是你的电话号码。我通过符号连接访问文件就是我用电话来联系你。虽然看起来多了一层,但我还是直接找到你的。

通过这个比喻,我们还可以顺带着说明另一个问题:你只有一个,而且位置确定。所以直接访问文件必须到存放文件的位置;传达室大爷可以有很多个,可以被放在公司不同的门口。所以快捷方式可以有很多个,也可以放在不同的位置;电话号码同样可以有很多个,我只需要找到任何一个电话号码就行了。所以符号连接也可以有很多个,存放在任何位置。

现在,你应该对符号连接有一个大概的认识了吧。对于应用来讲,符号连接和文件本身是同一个东西。所以借助这个,我们可以很轻易的实现我开头说到的问题——将Steam的游戏直接放在分区下面而不是在Steam库文件夹下面:只需要把游戏文件夹剪切到分区下面,然后在Steam库文件夹建立对应的符号连接就可以了。

最后,说一下Linux和OSX的命令如何书写吧——这个命令很常用所以我觉得你应该挺熟悉的:ln -s 需要创建连接的目标 创建的位置

如果你翻看过Linux系统的根目录,你会发现很多符号连接。所以这个在Linux下面的用处是很大的。当然,对于Windows也一样。只要你有足够的创造力。

视频点此

在Windows下面,有一个默默工作,为机械硬盘做提速工作贡献一生的系统软件——碎片整理程序。
但是,随着固态硬盘的普及,越来越多的看到一句话:固态硬盘不要做碎片整理。
而在Win8以后的版本中,这个程序被默认设定成了每周自动整理所有分区,行踪变得更加隐蔽了。就仿佛是个特务,潜伏在广大不知情的用户的电脑当中,伺机整理掉你的固态硬盘。
所以,看到这里,如果你有固态,请先去你的“优化驱动器”程序看看,是不是每周整理的。如果是,就赶紧把固态硬盘的分区取消掉吧。
但是,为什么会出现碎片呢?碎片又是如何影响机械硬盘速度的呢?是所有的磁盘分区类型都会出现碎片吗?今天,我打算通过一些形象的手段,跟你说说这三个问题。


在说三个问题之前,先来介绍一下什么是碎片。

在Linux方面,碎片被分为“内部碎片”和“外部碎片”。现在我们假设一个磁盘的空间有20k,它的基本存储单位为簇。至于簇到底是什么我们就不深究了。现在有两个文件,一个7k,一个1k。当簇的大小为4k时,磁盘分为了5个簇,两个文件共占用3个簇,即使用了12k,其中浪费地空间就是4k,而浪费的这4k空间,就是内部碎片。因此我们就了解了:内部碎片主要是造成磁盘空间的浪费。要注意:windows的磁盘碎片整理功能所整理的碎片不是这个碎片,也无法对这个碎片进行操作,它所对应的碎片概念是外部碎片。

任何一种分区格式都离不开簇这个东西,只是有名称可能不一样。所以任何一种系统下的分区都会有内部碎片出现。那可以对内部碎片进行优化处理吗?可以。以上面的例子来说,如果把每一簇分成2k,那么20k的磁盘就分为了10个簇,7k和1k两个文件共占用了5个簇,10k的空间,浪费的空间——内部碎片为2k。

那么内部碎片说完了,我们来看Windows概念下面的碎片——在Linux这边被称作“外部碎片”。它是怎么产生的呢?我通过一个矩阵来解释。

a b c d e f g h i j k l m n o p q r s t u v w x y z
a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
b 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
i 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
k 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
m 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
n 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
o 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
q 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
r 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
u 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
v 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
w 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
z 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

这就可以简单的用来表示一个很小的硬盘,初始状态是空的,全部都被0填充。在矩阵顶部和左侧的a-z都是用来定位每一个数据的。最左上角的那个0就是aa,最右上角的那个0就是za,最左下角的就是az。

以FAT文件系统作为代表,NTFS类似。我现在在磁盘上加入一个文件,于是磁盘看起来会变成这个样子:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t a e l e 0 0 0 0 0 0 0 0 0 0
b 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e H e l l o , _ w o r l d 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

(为了看起来更加清楚,g-z的空行被省略了)

前4行是TOC(Table Of Contents),即所谓的内容表。TOC会存储磁盘上所有文件的位置。磁头会根据这个表来移动到对应的位置。在我上面的例子中,TOC包含了一个名字叫做“hello.txt”的文件,并且这个文件的内容是从ae到le的。往下看ae到le之间的内容,我们能看到这个文件的内容是“Hello,_world”

到目前为止,一切都正常对吗?好,那我们再来添加一个文件:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t a e l e b y e . t x t m e z
b e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e H e l l o , _ w o r l d G o o d b y e , _ w o r l d
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

正如你所见,第二个文件被紧接着放置在第一个文件之后。这样的好处是你所有的文件都会紧密地放置在一起,这样读取它们将会非常的迅速和方便。要知道磁盘上最慢的就是读写头的移动了,它移动的越少,则读取的速度越快。

但是,当需要修改第一个文件的时候,问题就出来了。现在假设我们需要在“hello.txt”文件的尾部加入两个感叹号,我们就会遇到问题:没有空间。文件“bye.txt”挡住了“hello.txt”的去路。这时候我们有两个解决方法,但是没有一个是完美的。

  • 把文件“hello.txt”删掉,然后再“bye.txt”后面加入修改过后的“hello.txt”。
  • 把文件“hello.txt”拆成两部分存储,这样在“bye.txt”之前就不会有空的磁盘空间了。

第一种方式表现出来就是这样:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t a f n f b y e . t x t m e z
b e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e 0 0 0 0 0 0 0 0 0 0 0 0 G o o d b y e , _ w o r l d
f H e l l o , _ w o r l d ! ! 0 0 0 0 0 0 0 0 0 0 0 0

第二种方式表现出来就是这样:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t a e l e a f b f b y e . t x
b t m e z e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e H e l l o , _ w o r l d G o o d b y e , _ w o r l d
f ! ! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

而FAT采用了哪种方式呢?显然,第二种更快捷。我们只需要在TOC中读取到文件的起始位置,然后让这个作为起始的簇指向保存着这个文件的下一个簇,而下一个簇继续指向下下个簇,依次类推,便可以让磁头知道我要通过哪一个路径来读取这个文件了。这就是FAT保存文件的链式结构。

而这,就是为什么FAT格式的文件系统经常需要磁盘碎片整理的原因。所有的文件都紧挨着存放,所以任何时候,只要一个文件需要增大,就会产生碎片。而任何文件被删除了,就会留下一个空白区域。于是很快磁盘就会变成一堆乱糟糟的碎片和空白,效率就会变低了。

不知道你有没有听到我刚刚说过的一句话:要知道磁盘上最慢的就是读写头的移动了,它移动的越少,则读取的速度越快。所以整理碎片,让文件保存在一个连续的区域,减少磁头的摆动,这就是整理碎片加速磁盘读写的原因。而现如今的固态硬盘已经不需要磁头的概念了,反而会更关注每一块的读写次数,自然也就不需要,也不推荐进行碎片整理了。

那么,这种“外部碎片”是每一个操作系统对应的每种文件系统类型都会产生的吗?

不是。Linux就不会出现。因为它使用一种不同的方式来处理这种问题。当然,对于单用户来说Windows的文件系统已经够好的了,但是Linux生来就是为多用户设计的系统,它总是假设在同一时间有多个用户试图去操作不同的文件。所以Linux相对FAT文件系统,使用了另一种方法来设计自己的文件系统。Linux文件系统看起来是这样的:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t h n s n 0 0 0 0 0 0 0 0 0 0
b 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
i 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
k 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
m 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
n 0 0 0 0 0 0 0 H e l l o , _ w o r l d 0 0 0 0 0 0 0
o 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
q 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
r 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
u 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
v 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
w 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
z 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

当我们添加了文件以后就变成这样了:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t h n s n b y e . t x t d u q
b u 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
i 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
k 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
m 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
n 0 0 0 0 0 0 0 H e l l o , _ w o r l d 0 0 0 0 0 0 0
o 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
q 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
r 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
u 0 0 0 G o o d b y e , _ w o r l d 0 0 0 0 0 0 0 0 0
v 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
w 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
z 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

这种文件系统的好处是磁盘的磁头可以一直位于中间位置,而所有的文件平均下来都会非常近。

当我们仍然给“hello.txt”加入两个感叹号时:

a b c d e f g h i j k l m n o p q r s t u v w x y z
a T O C h e l l o . t x t h n u n b y e . t x t d u q
b u 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T O C
e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
g 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
i 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
k 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
m 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
n 0 0 0 0 0 0 0 H e l l o , _ w o r l d ! ! 0 0 0 0 0
o 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
q 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
r 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
u 0 0 0 G o o d b y e , _ w o r l d 0 0 0 0 0 0 0 0 0
v 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
w 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
z 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

没有任何的障碍。

Windows总是试图把文件存储在尽量靠近磁盘开始位置的地方,这导致当磁盘利用率变高的时候它经常会产生磁盘碎片。Linux却在整个磁盘上存储文件,所以当文件的大小需要改变的时候,总是有足够的空间。当然,想必你也可以看出来,当磁盘利用率接近饱和的时候Linux同样需要文件整理。但是根据linux.org的说法,只要磁盘还有5%以上的可用空间,那么这种碎片是基本不会出现的(Linux native file systems do not need defragmentation under normal use and this includes any condition with at least 5% of free space on a disk.)。而在实际使用中,磁盘在还有8%左右未使用时就会有警告产生,所以碎片整理是不用考虑的。