Linux笔记:1-基础知识

Linux读书笔记

Linux规划与磁盘分区

硬件在Linux中的文件名

在Linux系统中, 每个设备都被当成一个文件来对待。
在Linux这个系统当中, 几乎所有的硬件设备文件都在/dev这个目录内。

几个常见的设备与其在Linux当中的文件名:

设备设备在Linux内的文件名
SCSI/SATA/USB硬盘机/dev/sd[a-p]
USB闪存盘/dev/sd[a-p] ( 与SATA相同)
VirtI/O界面/dev/vd[a-p] ( 用于虚拟机内)
软盘机/dev/fd[0-7]
打印机/dev/lp[0-2] ( 25针打印机) /dev/usb/lp[0-15] ( USB 接口)
鼠标/dev/input/mouse[0-15] ( 通用) /dev/psaux ( PS/2界面) /dev/mouse ( 当前鼠标)
CDROM/DVDROM/dev/scd[0-1] ( 通用) /dev/sr[0-1] ( 通用, CentOS 较常见)/dev/cdrom ( 当前 CDROM)
磁带机/dev/ht0 ( IDE 界面) /dev/st0 ( SATA/SCSI界面) /dev/tape( 当前磁带)
IDE硬盘机/dev/hd[a-d] ( 旧式系统才有)

时至今日, 由于 IDE 界面的磁盘机几乎已经被淘汰, 太少见了! 因此现在连 IDE 界面的磁盘文件名也都被仿真成 /dev/sd[a-p] 了! 此外, 如果你的机器使用的是跟网际网络供应商( ISP) 申请使用的云端机器, 这时可能会得到的是虚拟机。 为了加速, 虚拟机内的磁盘是使用仿真器产生, 该仿真器产生的磁盘文件名为 /dev/vd[a-p] 系列的文件名

硬盘分区

正常的实体机器大概使用的都是 /dev/sd[a-] 的磁盘文件名;
虚拟机环境下面, 为了加速, 可能就会使用 /dev/vd[a-p] 这种设备文件名

同类型接口的硬盘文件名顺序,根据Linux核心侦测到磁盘的顺序。

PC上面有两个SATA硬盘以及一个USB硬盘, 而主板上面有六个SATA的插槽。
这两个SATA硬盘分别安插在主板上的SATA1, SATA5插槽上
由于是使用侦测到的顺序来决定设备文件名, 并非与实际插槽代号有关, 因此设备的文件名如下:

  1. SATA1插槽上的文件名: /dev/sda
  2. SATA5插槽上的文件名: /dev/sdb
  3. USB磁盘( 开机完成后才被系统捉到) : /dev/sdc

磁盘分区方案

普通硬盘(机械硬盘):知识提要
硬盘的组成主要有盘片、 机械手臂、 磁头与主轴马达所组成, 而数据的写入其实是在盘片上面。
盘片上面又可细分出扇区( Sector) 与磁道( Track) 两种单位,其中扇区为硬盘最小的组成单位和最小物理储存单位,容量设计有两种大小, 分别是 512Bytes 与 4KBytes。
不同盘面上的相同磁道称为柱面,最外磁道为0,通常是文件系统的最小单位, 也就是分区的最小单位。(在GPT的硬盘分区表标准下,可以使用扇区 ( sector) 号码来作为分区单位)

分区表目前有两种格式:MSDOS ( MBR) 分区表格和 GUID partition table(GPT) 分区表格式;
在MSDOS中磁柱 (Cylinder), 通常那是文件系统的最小单位,也就是分区的最小单位
GPT 可以使用 64bit 来纪录分区表(MBR中,每个分区16Bytes,实际记录分区表的空间为32bit), 现在我们甚至可以使用扇区 (sector)号码来作为分区单位;
因此分区的单位可以是磁柱或扇区。

MSDOS ( MBR)

Windows 的MBR( Master Boot Record, 主引导区记录) ,为磁盘的第一个扇区,这个扇区通常是 512Bytes 的大小 ( 旧的硬盘扇区都是 512Bytes ,新硬盘可为4KBytes) 。
第一个扇区 512Bytes 会有这两个数据:

  1. 主要开机记录区( Master Boot Record, MBR) : 可以安装开机管理程序的地方, 有446Bytes。
  2. 分区表( partition table) : 记录整颗硬盘分区的状态, 有64 Bytes。

由于分区表所在区块仅有64 Bytes容量, 且规定每个分区16Bytes,因此最多仅能有四组记录区, 每组记录区记录了该区段的启始与结束的柱面号码。

如一硬盘分四个区,硬盘设备文件名为/dev/sda时,则分区文件名如下:
P1:/dev/sda1
P2:/dev/sda2
P3:/dev/sda3
P4:/dev/sda4

分区类型为:主要( Primary) 或扩展( Extended) 分区

区别:
主分区能被格式化作为数据存储的分区。
扩展分区不能被格式化,主要作用是为创建逻辑(logical)分区,用以突破分区表只能创建4个分区的限制。扩展分区将使用该分区的一个区块保存逻辑分区表,然后逻辑分区格式化用以数据存储。扩展分区的文件编号是从5开始(1-4为主分区和逻辑分区的编号)。

分区总结:

  • 其实所谓的“分区”只是针对那个64 Bytes的分区表进行设置而已!
  • 硬盘默认的分区表仅能写入四组分区信息
  • 这四组分区信息我们称为主要( Primary) 或延伸( Extended) 分区
  • 分区的最小单位“通常”为柱面( cylinder)
  • 当系统要写入磁盘时, 一定会参考磁盘分区表, 才能针对某个分区进行数据的处理

分区、 延伸分区与逻辑分区总结:

  • 主要分区与延伸分区最多可以有四笔( 硬盘的限制)
  • 延伸分区最多只能有一个( 操作系统的限制)
  • 逻辑分区是由延伸分区持续切割出来的分区;
  • 能够被格式化后, 作为数据存取的分区为主要分区与逻辑分区。 延伸分区无法格式化;
  • 逻辑分区的数量依操作系统而不同, 在Linux系统中SATA硬盘已经可以突破63个以上的分区限制;

MBR 分区表格式对硬盘的限制:

  • 操作系统无法抓取到 2.2T 以上的磁盘容量(因为分区表大小64 Bytes,每组分区表仅有16Bytes);要想使用只能做个多逻辑分区。
  • MBR 仅有一个区块, 若被破坏后, 经常无法或很难救援。
  • MBR 内的存放开机管理程序的区块仅 446Bytes, 无法容纳较多的程序码。
GUID partition table(GPT)

GPT对硬盘的管理,以扇区为单位;因为扇区大小有 512Bytes和4K 的容量设计,为了相容于所有的磁盘。
因此在扇区的定义上面,大多会使用所谓的 逻辑区块位址(Logical BlockAddress LBA) 来处理。
GPT 将磁盘所有区块以此 LBA( 默认为 512Bytes ) 来管理,而第一个 LBA 称为 LBA0 ( 从 0 开始编号) 。

与 MBR 仅使用第一个 512Bytes 区块来纪录不同, GPT 使用了 34 个 LBA 区块来纪录分区信息
同时与过去 MBR 仅有一的区块, 被干掉就死光光的情况不同, GPT 除了前面 34 个LBA 之外, 整个磁盘的最后 33 个 LBA 也拿来作为另一个备份!

LBA0 ( MBR 相容区块)

与 MBR 模式相似的, 这个相容区块也分为两个部份, 一个就是跟之前 446 Bytes 相似的区块, 储存了第一阶段的开机管理程序!
而在原本的分区表的纪录区内, 这个相容模式仅放入一个特殊标志的分区, 用来表示此磁盘为 GPT 格式之意
而不懂 GPT 分区表的磁盘管理程序, 就不会认识这颗磁盘, 除非用户有特别要求要处理这颗磁盘, 否则该管理软件不能修改此分区信息, 进一步保护了此磁盘喔!

LBA1 ( GPT 表头纪录)

这个部份纪录了分区表本身的位置与大小, 同时纪录了备份用的 GPT 分区 ( 就是前面谈到的在最后 34 个 LBA 区块) 放置的位置, 同时放置了分区表的检验机制码( CRC32) , 操作系统可以根据这个检验码来判断 GPT 是否正确。
若有错误, 还可以通过这个纪录区来取得备份的 GPT( 磁盘最后的那个备份区块) 来恢复 GPT 的正常运行!

LBA2-33 ( 实际纪录分区信息处)

从 LBA2 区块开始, 每个 LBA 都可以纪录 4 笔分区纪录, 所以在默认的情况下, 总共可以有 4x32 = 128 笔分区纪录喔! 因为每个 LBA 有 512Bytes, 因此每笔纪录用到 128Bytes 的空间, 除了每笔纪录所需要的识别码与相关的纪录之外, GPT 在每笔纪录中分别提供了64bits 来记载开始/结束的扇区号码, 因此, GPT 分区表对於单一分区来说,他的最大容量限制就会在“ 264x512Bytes = 2631KBytes = 233TB = 8 ZB ”, 要注意 1ZB=230TB 。

开机流程中的 BIOS 与 UEFI 开机检测程序

BIOS 搭配 MBR/GPT 的开机流程

CMOS是记录各项硬件参数且嵌入在主板上面的储存器, BIOS则是一个写入到主板上的一个固件( 再次说明, 固件就是写入到硬件上的一个软件程序) 。 这个BIOS就是在开机的时候, 计算机系统会主动执行的第一个程序。

接下来BIOS会去分析计算机里面有哪些储存设备, 我们以硬盘为例, BIOS会依据使用者的设置去取得能够开机的硬盘, 并且到该硬盘里面去读取第一个扇区的MBR位置。MBR这个仅有446 Bytes的硬盘容量里面会放置最基本的开机管理程序, 此时BIOS就功成圆满, 而接下来就是MBR内的开机管理程序的工作了。

这个开机管理程序的目的是在载入( load) 核心文件, 由于开机管理程序是操作系统在安装的时候所提供的, 所以他会认识硬盘内的文件系统格式, 因此就能够读取核心文件, 然后接下来就是核心文件的工作, 开机管理程序与 BIOS 也功成圆满, 将之后的工作就交给大家所知道的操作系统。

简单的说, 整个开机流程到操作系统之前的动作应该是这样的:

  1. BIOS: 开机主动执行的固件, 会认识第一个可开机的设备;
  2. MBR: 第一个可开机设备的第一个扇区内的主要开机记录区块, 内含开机管理程序;
  3. 开机管理程序( boot loader) : 一支可读取核心文件来执行的软件;
  4. 核心文件: 开始操作系统的功能

由于 LBA0 仅提供第一阶段的开机管理程序码, 因此如果你使用类似 grub 的开机管理程序的话, 那么就得要额外分区出一个“ BIOS boot ”的分区, 这个分区才能够放置其他开机过程所需的程序码! 在 CentOS 当中, 这个分区通常占用 2MB 左右而已。

BIOS与MBR都是硬件本身会支持的功能, 至于Boot loader(开机管理程序)则是操作系统安装在MBR上面的一套软件了。 由于MBR仅有446 Bytes而已, 因此这个开机管理程序是非常小而美的。 这个boot loader的主要任务有下面这些项目:

  • 提供菜单: 使用者可以选择不同的开机项目, 这也是多重开机的重要功能!
  • 载入核心文件: 直接指向可开机的程序区段来开始操作系统;
  • 转交其他loader: 将开机管理功能转交给其他loader负责。

开机管理程序除了可以安装在MBR之外, 还可以安装在每个分区的开机扇区( boot sector)这个特色才能造就“多重开机”的功能

关于开机扇区( boot sector)和多重开机:

  • 每个分区都拥有自己的开机扇区( boot sector)
  • 实际可开机的核心文件是放置到各分区内的!
  • loader只会认识自己的系统盘内的可开机核心文件, 以及其他loader而已;
  • loader可直接指向或者是间接将管理权转交给另一个管理程序。

关于安装多重开机, 最好先安装Windows再安装Linux

  • Windows安装程序会主动的覆盖掉MBR以及自己所在分区的开机扇区, 你没有选择的机会, 而且他没有让我们自己选择菜单的功能。
  • Linux在安装的时候, 你可以选择将开机管理程序安装在MBR或各别分区的开机扇区, 而且Linux的loader可以手动设置菜单, 所以你可以在Linux的Bootloader里面加入Windows开机的选项。

总结:MBR只有一个,要想多重开机,MBR中开机管理系统需要有能提供转移loader的功能(及能提供开机选项)的开机管理程序,通过把不同的操作系统的Boot loader装载自有分区,再将一个可以转移loader的Boot loader装在MBR中,提供多重开机。
如果先安装Linux再安装Windows的话, 那MBR的开机管理程序就只会有Windows的项目, 而不会有Linux的项目 ( 因为原本在MBR内的Linux的开机管理程序就会被覆盖掉) 。 那需要重新安装Linux一次吗? 当然不需要, 你只要用尽各种方法来处理MBR的内容即可。 例如利用Linux的救援模式来挽救MBR!

UEFI BIOS 搭配 GPT 开机的流程

我们现在知道 GPT 可以提供到 64bit 的寻址, 然后也能够使用较大的区块来处理开机管理程序。 但是 BIOS 其实不懂 GPT还得要通过 GPT 提供相容模式才能够读写这个磁盘设备,而且 BIOS 仅为 16 位的程序, 在与现阶段新的操作系统接轨方面有点弱! 为了解决这个问题, 因此就有了 UEFI ( Unified Extensible Firmware Interface) 这个统一可延伸固件界面的产生。

UEFI 主要是想要取代 BIOS 这个固件界面, 因此我们也称 UEFI 为 UEFI BIOS 就是了。
UEFI 使用 C 程序语言, 比起使用组合语言的传统 BIOS 要更容易开发! 也因为使用 C 语言来撰写, 因此如果开发者够厉害, 甚至可以在 UEFI 开机阶段就让该系统了解 TCP/IP 而直接上网! 根本不需要进入操作系统! 这让小型系统的开发充满各式各样的可能性。

由于过去 黑客经常借由 BIOS 开机阶段来破坏系统, 并取得系统的控制权, 因此UEFI 加入了一个所谓的安全启动 ( secure boot) 机制, 这个机制代表着即将开机的操作系统必须要被 UEFI 所验证, 否则就无法顺利开机! 微软用了很多这样的机制来管理硬件。 不过加入这个机制后, 许多的操作系统, 包括 Linux , 就很有可能无法顺利开机喔! 所以, 某些时刻, 你可能得要将 UEFI 的 secure boot 功能关闭, 才能够顺利的进入 Linux。

与 BIOS 模式相比, 虽然 UEFI 可以直接取得 GPT 的分区表, 不过最好依旧拥有BIOS boot 的分区支持, 同时, 为了与 windows 相容, 并且提供其他第三方厂商所使用的UEFI 应用程序储存的空间, 你必须要格式化一个 vfat 的文件系统, 大约提供 512MB 到 1G左右的容量, 以让其他 UEFI 执行较为方便。

硬盘分区与挂载

目录树结构 ( directory tree)

Linux内的所有数据都是以文件的形态来呈现的, 所以, 整个Linux系统最重要的地方就是在于目录树架构。
所谓的目录树架构( directory tree) 就是以根目录为主, 然后向下呈现分支状的目录结构的一种文件架构。
所以, 整个目录树架构最重要的就是那个根目录( root directory) , 这个根目录的表示方法为一条斜线“/”, 所有的文件都与目录树有关。

如何结合目录树的架构与磁盘内的数据 ?

文件系统与目录树的关系( 挂载)
所谓的“挂载”就是利用一个目录当成进入点, 将磁盘分区的数据放置在该目录下
也就是说, 进入该目录就可以读取该分区的意思
这个动作我们称为“挂载”, 那个进入点的目录我们称为“挂载点”。
由于整个Linux系统最重要的是根目录, 因此根目录一定需要挂载到某个分区的
至于其他的目录则可依使用者自己的需求来给予挂载到不同的分区。

线上求助和正确关机

线上求助

help 求助说明

几乎 Linux 上面的指令(并不是所有指令都有 --help选项), 在开发的时候, 开发者就将可以使用的指令语法与参数写入指令操作过程中了!你只要使用“ --help ”这个选项, 就能够将该指令的用法作一个大致的理解。

再没有help选项的时候,可以使用help xxx的方式查看帮助;或者其他方式。

说明:
help xxx :只能用于内部命令,不能用于外部命令
xxx --help 用于外部命令
当一些命令无法用–help参数时候,可以使用help xxx 的方式
 
内部命令:Bash中的命令;

man page

除了 --help 之外,man指令(man是manual( 操作说明) 的简写)也能对指令或文件(一些特定文件)做说明

说明
–help:用在协助你查询你用过的指令的选项与参数
如果你要使用的是从来没有用过得指令, 或者是你要查询的根本就不是指令, 而是文件的“格式”时, 那就得要通过 man page

info page

在所有的Unix Like系统当中, 都可以利用 man 来查询指令或者是相关文件的用法; 但是, 在Linux里面则又额外提供了一种线上求助的方法, 那就是利用info。

基本上, info与man的用途其实差不多, 都是用来查询指令的用法或者是文件的格式。 但是与man page一口气输出一堆信息不同的是, info page则是将文件数据拆成一个一个的段落, 每个段落用自己的页面来撰写, 并且在各个页面中还有类似网页的“超链接”来跳到各不同的页面中, 每个独立的页面也被称为一个节点( node) 。 所以, 你可以将info page想成是文字模式的网页显示数据。

不过你要查询的目标数据的说明文档必须要以info的格式来写成才能够使用info的特殊功能( 例如超链接) 。 而这个支持info指令的文件默认是放置在/usr/share/info/这个目录当中的。

其他有用的文件( documents)

一般而言, 指令或者软件制作者, 都会将自己的指令或者是软件的说明制作成“线上说明文档”!
但是, 毕竟不是每个东西都需要做成线上说明文档的, 还有相当多的说明需要额外的文件!
此时, 这个所谓的 How-To( 如何做的意思) 就很重要啦!
还有, 某些软件不只告诉你“如何做”, 还会有一些相关的原理会说明呢。

这些说明文档就是摆在/usr/share/doc这个目录

举例:
要知道 grub2 这个新版的开机管理软件有什么能使用的指令?
那可以到下面的目录瞧瞧:
/usr/share/doc/grub2-tools-2.02

另外, 很多原版软件释出的时候, 都会有一些安装须知、 预计工作事项、 未来工作规划等等的东西, 还有包括可安装的程序等, 这些文件也都放置在 /usr/share/doc 当中喔! 而且/usr/share/doc这个目录下的数据主要是以套件( packages) 为主的, 例如 nano 这个软件的相关信息在 /usr/share/doc/nano-xxx( 那个xxx表示版本的意思! ) 。

线上求助总结:

  • 在终端机模式中, 如果你知道某个指令, 但却忘记了相关选项与参数, 请先善用 --help的功能来查询相关信息;
  • 当有任何你不知道的指令或文件格式这种玩意儿, 但是你想要了解他, 请赶快使用man或者是info来查询!
  • 而如果你想要架设一些其他的服务, 或想要利用一整组软件来达成某项功能时, 请赶快到/usr/share/doc 下面查一查有没有该服务的说明文档!

各种方式的差别:

  • help在内外命令上,使用有差别。
  • man得到的内容比用 help 更多更详细而且man没有内建与外部命令的区分因为 man 工具是显示系统手册页中的内容也就是一本电子版的字典这些内容大多数都是对命令的解释信息还有一些相关的描述。通过查看系统文档中的 man 也可以得到程序的更多相关信息和 Linux 的更多特性。
  • info 得到的信息比 man 还要多,info 来自自由软件基金会的 GNU 项目,是 GNU 的超文本帮助系统,能够更完整的显示出 GNU 信息。所以得到的信息当然更多。
  • man 和 info 就像两个集合,它们有一个交集部分,但与 man 相比,info 工具可显示更完整的 GNU 工具信息。若 man 页包含的某个工具的概要信息在 info 中也有介绍,那么 man 页中会有“请参考 info 页更详细内容”的字样。

正确关机

在 Linux 下面, 由于每个程序 ( 或者说是服务) 都是在在背景下执行的, 因此, 在你看不到的屏幕背后其实可能有相当多人同时在你的主机上面工作,如果你直接按下电源开关来关机时, 则其他人的数据可能就此中断。

此外, 最大的问题是, 若不正常关机, 则可能造成文件系统的毁损 ( 因为来不及将数据回写到文件中, 所以有些服务的文件会有问题! ) 。 所以正常情况下, 要关机时需要注意下面几件事:

  • 观察系统的使用状态: 如果要看目前有谁在线上, 可以下达“who”这个指令, 而如果要看网络的连线状态, 可以下达 “ netstat -a ”这个指令, 而要看背景执行的程序可以执行“ ps-aux ”这个指令。 使用这些指令可以让你稍微了解主机目前的使用状态! 当然啰, 就可以让你判断是否可以关机了 ( 这些指令在后面Linux常用指令中会提及喔! )
  • 通知线上使用者关机的时刻: 要关机前总得给线上的使用者一些时间来结束他们的工作, 所以, 这个时候你可以使用 shutdown 的特别指令来达到此一功能。
  • 正确的关机指令使用: 例如 shutdown 与 reboot 两个指令!

由于Linux系统的关机/重新开机是很重大的系统运行, 因此只有root才能够进行例如shutdown, reboot等指令。 不过在某些distributions当中, 例如我们这里谈到的CentOS系统,他允许你在本机前的tty1~tty7当中( 无论是文字界面或图形界面) , 可以用一般帐号来关机或重新开机! 但某些distributions则在你要关机时, 他会要你输入root的密码呢!

数据同步写入磁盘: sync

数据在计算机中运行的模式, 所有的数据都得要被读入内存后才能够被CPU所处理, 但是数据又常常需要由内存写回硬盘当中( 例如储存的动作) 。 由于硬盘的速度太慢( 相对于内存来说) , 如果常常让数据在内存与硬盘中来回写入/读出, 系统的性能就不会太好。

因此在Linux系统中, 为了加快数据的读取速度, 所以在默认的情况中, 某些已经载入内存中的数据将不会直接被写回硬盘, 而是先暂存在内存当中, 如此一来, 如果一个数据被你重复的改写, 那么由于他尚未被写入硬盘中, 因此可以直接由内存当中读取出来, 在速度上一定是快上相当多的!

如此一来也造成些许的困扰, 那就是万一你的系统因为某些特殊情况造成不正常关机( 例如停电或者是不小心踢到power) 时, 由于数据尚未被写入硬盘当中, 所以就会造成数据的更新不正常。

这个时候就需要sync这个指令来进行数据的写入动作! 直接在命令行下输入sync, 那么在内存中尚未被更新的数据, 就会被写入硬盘中! 所以, 这个指令在系统关机或重新开机之前, 很重要喔! 最好多执行几次!

虽然目前的 shutdown/reboot/halt 等等指令均已经在关机前进行了 sync 这个工具的调用, 不过, 多做几次总是比较放心点。

注意:
事实上sync也可以被一般帐号使用只不过一般帐号使用者所更新的硬盘数据就仅有自己的数据, 不像root可以更新整个系统中的数据了

惯用的关机指令: shutdown

由于Linux的关机是那么重要的工作, 因此除了你是在主机前面以实体终端机 ( tty1~tty7) 来登陆系统时, 不论用什么身份都能够关机之外, 若你是使用远端管理工具( 如通过pietty使用ssh服务来从其他计算机登陆主机) , 那关机就只有root有权力而已

我们较常使用的是shutdown这个指令, 而这个指令会通知系统内的各个程序 ( processes) , 并且将通知系统中的一些服务来关闭。 shutdown可以达成如下的工作:

  • 可以自由选择关机模式: 是要关机或重新开机均可;
  • 可以设置关机时间: 可以设置成现在立刻关机, 也可以设置某一个特定的时间才关机。
  • 可以自订关机讯息: 在关机之前, 可以将自己设置的讯息传送给线上 user 。
  • 可以仅发出警告讯息: 有时有可能你要进行一些测试, 而不想让其他的使用者干扰, 或
    者是明白的告诉使用者某段时间要注意一下! 这个时候可以使用 shutdown 来吓一吓使用
    者, 但却不是真的要关机!

重新开机, 关机: reboot, halt, poweroff

其实这三个指令调用的函数库都差不多, 所以当你使用“man reboot”时, 会同时出现三个指令的用法给你看。

这些指令都能够关机或重新开机, 那他有没有什么差异啊? 基本上, 在默认的情况下,这几个指令都会完成一样的工作! ( 全部的动作都是去调用 systemctl 这个重要的管理命令! ) 所以, 你只要记得其中一个就好了! 重点是, 你自己习惯即可!

实际使用管理工具 systemctl 关机

有个名为 init 的指令, 这个指令可以切换不同的执行等级~ 执行等级共有 0~6 七个, 其中 0 就是关机、 6 就是重新开机等等。 不过, 这个init 目前只是一个相容模式而已~ 所以在 CentOS 7 当中, 虽然你依旧可以使用“ init 0 ”来关机, 但是那已经跟所谓的“执行等级”无关了!

那目前系统中所有服务的管理是使用哪个指令呢? 那就是 systemctl 啦! 上面谈到的 halt, poweroff, reboot, shutdown 等等, 其实都是调用这个systemctl 指令。

Linux 的文件权限与目录配置

Linux一般将文件可存取的身份分为三个类别, 分别是 owner/group/others, 且三种身份各有 read/write/execute 等权限。

Linux 使用者身份与群组记录的文件

默认的情况下:
系统上的帐号与一般身份使用者以及root:保存再/etc/passwd;
个人的密码:保存在/etc/shadow;
群组名称:保存在/etc/group;

这三个文件可以说是Linux系统里面帐号、 密码、 群组信息的集中地! 不要随便删除这三个文件。

Linux 文件权限概念

Linux文件属性

指令提示:
su - # 切换root身份查看文件属性
需要管理文件属性时候可能需要 root权限;

文件属性如图:
在这里插入图片描述

  • 第一栏代表这个文件的类型与权限( permission):
    在这里插入图片描述

第一个字符代表这个文件是“目录、 文件或链接文件等等”:

  • 当为[ d ]则是目录;
  • 当为[ - ]则是文件;
  • 若是[ l ]则表示为链接文件( link file) ;
  • 若是[ b ]则表示为设备文件里面的可供储存的周边设备( 可随机存取设备) ;
  • 若是[ c ]则表示为设备文件里面的序列埠设备, 例如键盘、 鼠标( 一次性读取设备) 。

接下来的字符中, 以三个为一组, 且均为“rwx” 的三个参数的组合。
其中, [ r ]代表可读( read) 、 [ w ]代表可写( write) 、 [ x ]代表可执行( execute) 。
要注意的是, 这三个权限的位置不会改变, 如果没有权限, 就会出现减号[ - ]。

  • 第一组为“文件拥有者可具备的权限”
  • 第二组为“加入此群组之帐号的权限”;
  • 第三组为“非本人且没有加入本群组之其他帐号的权限”。
  • 第二栏表示有多少文件名链接到此节点( i-node):

每个文件都会将他的权限与属性记录到文件系统的i-node中, 不过, 我们使用的目录树却是使用文件名来记录, 因此每个文件名就会链接到一个i-node啰! 这个属性记录的, 就是有多少不同的文件名链接到相同的一个i-node号码去就是了。

  • 第三栏表示这个文件( 或目录) 的“拥有者帐号”;

  • 第四栏表示这个文件的所属群组;

在Linux系统下, 你的帐号会加入于一个或多个的群组中。

  • 第五栏为这个文件的容量大小, 默认单位为Bytes;

  • 第六栏为这个文件的创建日期或者是最近的修改日期;

  • 第七栏为这个文件的文件名:

这个字段就是文件名了。 比较特殊的是: 如果文件名之前多一个“ . ”, 则代表这个文件为“隐藏文件”,

改变文件属性与权限

  常用于群组、 拥有者、 各种身份的权限之修改的指令, 如下所示:

  • chgrp : 改变文件所属群组
  • chown : 改变文件拥有者
  • chmod : 改变文件的权限, SUID, SGID, SBIT等等的特性

chmod :
  权限的设置方法有两种, 分别可以使用数字或者是符号来进行权限的变更。

数字类型改变文件权限
权限分为三组,每三个为一组,可以使用数字来代表各个权限, 各权限的值对照表如下:
r:4 w:2 x:1
符号类型改变文件权限
可以借由u, g, o来代表三种身份的权限! 此外, a 则代表 all 亦即全部的身份。
设置如下

| chmod | u g o a | +( 加入) -( 除去) =( 设置) | r w x | 文件或目录 |
注意:
+( 加入) -( 除去):没有指定的权限,原权限不会变动(即只修改设置的权限)

目录与文件之权限意义

权限对文件的重要性

  文件是实际含有数据的地方, 包括一般文本文件、 数据库内容档、 二进制可可执行文件( binary program) 等等。 因此, 权限对于文件来说, 他的意义是这样的:

  • r ( read) : 可读取此一文件的实际内容, 如读取文本文件的文字内容等;
  • w ( write) : 可以编辑、 新增或者是修改该文件的内容( 但不含删除该文件) ;
  • x ( execute) : 该文件具有可以被系统执行的权限。

关于X(可执行)
在Windows下面一个文件是否具有执行的能力是借由“ 扩展名 ”来判断的, 例如: .exe,.bat, .com 等等;
但是在Linux下面, 我们的文件是否能被执行, 则是借由是否具有“x”这个权限来决定的! 跟文件名是没有绝对的关系的

关于W(可执行)
当你对一个文件具有w权限时, 你可以具有写入/编辑/新增/修改文件的内容的权限, 但并不具备有删除该文件本身的权限。
对于文件的rwx来说, 主要都是针对“文件的内容”而言, 与文件文件名的存在与否没有关系! 因为文件记录的是实际的数据嘛!

权限对目录(文件夹)的重要性

  文件是存放实际数据的所在,目录主要的内容在记录文件名清单文件名与目录有强烈的关连

  • r ( read contents in directory) :
    表示具有读取目录结构清单的权限, 所以当你具有读取( r) 一个目录的权限时, 表示你
    可以查询该目录下的文件名数据。 所以你就可以利用 ls 这个指令将该目录的内容列表显
    示出来!

  • w ( modify contents of directory) :
    表示你具有异动该目录结构清单的权限, 也就是下面这些权限:

    • 创建新的文件与目录;
    • 删除已经存在的文件与目录不论该文件的权限为何! )
    • 将已存在的文件或目录进行更名;
    • 搬移该目录内的文件、 目录位置。

    总之, 目录的w权限就与该目录下面的文件名异动有关!

  • x ( access directory) :
    目录只是记录文件名而已, 目录不可以被执行, 目录的x代表的是使用者能否进入该目录成为工作目录!所谓的工作目录( work directory) 就是你目前所在的目录。及能切换到该目录,然后做后续的操作。
    如通过cd命令切换到该目录;工作目录对于指令的执行是非常重要的, 如果你在某目录下不具有x的权限, 那么你就无法切换到该目录下, 也就无法执行该目录下的任何指令, 即使你具有该目录的r或w的权限。

用现实的例子做对比:
  文件是一堆文件数据夹:你可能可以在上面写/改一些数据。
  目录是一堆抽屉:你可以将数据夹分类放置到不同的抽屉去。

元件內容叠代物件rwx
文件详细数据data文件数据夹读到文件内容修改文件内容执行文件内容
目录文件名可分类抽屉读到文件名修改文件名进入该目录的权限(key)

总结:
对一般文件来说, rwx 主要是针对“文件的内容”来设计权限,对目录来说, rwx则是针对“目录内的文件名列表”来设计权限。
这个 x 权限设计, 就相当于“该目录, 也就是该抽屉的钥匙 ”! 没有钥匙你怎么能够打开抽屉呢?
工作目录对于指令的执行是非常重要的, 如果你在某目录下不具有x的权限, 那么你就无法切换到该目录下, 也就无法执行该目录下的任何指令, 即使你具有该目录的r或w的权限。

Linux文件类型与扩展名

  任何设备在Linux下面都是文件, 不仅如此, 连数据沟通的接口也有专属的文件在负责~所以, Linux的文件种类会很多。

文件类型
  • 正规文件( regular file ) [ - ]: 就是一般我们在进行存取的类型的文件。
    • 纯文本文件( ASCII)
      这是Linux系统中最多的一种文件类型啰, 称为纯文本文件是因为内容为我们人类可以直接读到的数据
    • 二进制档( binary)
      Linux当中的可执行文件 就是这种格式
    • 数据格式文件( data)
      有些程序在运行的过程当中会读取某些特定格式的文件,那些特定格式的文件可以被称为数据文件 ( data file) 。
  • 目录( directory) [ d ] : 目录类型
  • 链接文件( link) [ l ]:就是类似Windows系统下面的捷径。
  • 设备与设备文件( device) :
    与系统周边及储存等相关的一些文件, 通常都集中在/dev这个目录之下! 通常又分为两种:
    • 区块( block) 设备文件 :
      就是一些储存数据, 以提供系统随机存取的周边设备。举例来说, 硬盘与软盘等就是! 你可以随机的在硬盘的不同区块读写, 这种设备就是区块设备! 你可以自行查一下/dev/sda看看, 会发现第一个属性为[ b ]!
    • 字符( character) 设备文件:
      即是一些序列埠的周边设备, 例如键盘、 鼠标等等! 这些设备的特色就是“一次性读取”的, 不能够截断输出。 举例来说, 你不可能让鼠标“跳到”另一个画面, 而是“连续性滑动”到另一个地方! 第一个属性为 [ c ]。
  • 数据接口文件( sockets) [s]:
    既然被称为数据接口文件, 这种类型的文件通常被用在网络上的数据承接,最常在/run或/tmp这些个目录中看到这种文件类型了。
  • 数据输送档( FIFO, pipe) [p] :
    FIFO也是一种特殊的文件类型, 他主要的目的在解决多个程序同时存取一个文件所造成的错误问题。
文件扩展名

  基本上, Linux的文件是没有所谓的“扩展名”的,一个Linux文件能不能被执行, 与他的第一栏的十个属性有关, 与文件名根本一点关系也没有。

  在Windows下面, 能被执行的文件扩展名通常是 .com .exe .bat等等, 而在Linux下面, 只要你的权限当中具有x的话, 例如[ -rwxr-xr-x ] 即代表这个文件具有可以被执行的能力!

具有“可执行的权限”以及“具有可执行的程序码”是两回事:
一个文件可被执行,不一定是可以执行的程序。
X代表这个文件具有可执行的能力, 但是能不能执行成功, 当然就得要看该文件的内容。

  虽然如此,不过我们仍然希望可以借由扩展名来了解该文件是什么东西, 所以, 通常我们还是会以适当的扩展名来表示该文件是什么种类的。 下面有数种常用的扩展名:

  • *.sh : 脚本或批处理文件 ( scripts) , 因为批处理文件为使用shell写成的, 所以扩展名就编成 .sh 啰;
  • Z,.tar, .tar.gz, .zip, *.tgz: 经过打包的压缩文件。 这是因为压缩软件分别为 gunzip, tar等等的, 由于不同的压缩软件, 而取其相关的扩展名啰!
  • html, .php: 网页相关文件, 分别代表 HTML 语法与 PHP 语法的网页文件啰! .html 的文件可使用网页浏览器来直接打开, 至于 .php 的文件, 则可以通过 client 端的浏览器来server 端浏览, 以得到运算后的网页结果呢!

总结:
基本上, Linux系统上的文件名真的只是让你了解该文件可能的用途而已, 真正的执行与否仍然需要权限的规范才行
例如:虽然有一个文件为可执行文件, 如常见的/bin/ls这个显示文件属性的指令, 不过, 如果这个文件的权限被修改成无法执行时, 那么ls就变成不能执行
上述的这种问题最常发生在文件传送的过程中。
例如你在网络上下载一个可执行文件, 但是偏偏在你的 Linux系统中就是无法执行! 那么就是可能文件的属性被改变了! 不要怀疑, 从网络上传送到你的 Linux系统中, 文件的属性与权限确实是会被改变的

Linux目录配置

Linux目录配置的依据–FHS

Filesystem Hierarchy Standard ( FHS) -文件系统分层标准

根据FHS, 他们的主要目的是希望让使用者可以了解到已安装软件通常放置于那个目录下, 所以他们希望独立的软件开发商、 操作系统制作者、 以及想要维护系统的使用者, 都能够遵循FHS的标准。 也就是说, FHS的重点在于规范每个特定的目录下应该要放置什么样子的数据而已。

FHS将目录定义成为四种交互作用的形态:

项目可分享的( shareable)不可分享的( unshareable)
不变的( static)/usr ( 软件放置处)/etc ( 配置文件)
不变的( static)/opt ( 第三方协力软件)/boot ( 开机与核心档)
可变动的( variable)/var/mail ( 使用者邮件信箱)/var/run ( 程序相关)
可变动的( variable)/var/spool/news ( 新闻群组)/var/lock ( 程序相关)
  • 可分享的: 可以分享给其他系统挂载使用的目录, 所以包括可执行文件与使用者的邮件等数据, 是能够分享给网络上其他主机挂载用的目录
  • 不可分享的: 自己机器上面运行的设备文件或者是与程序有关的socket文件等, 由于仅与自身机器有关, 所以当然就不适合分享给其他主机了
  • 不变的: 有些数据是不会经常变动的, 跟随着distribution而不变动。 例如函数库、 文件说明文档、 系统管理员所管理的主机服务配置文件等等
  • 可变动的: 经常改变的数据, 例如登录文件、 一般用户可自行收受的新闻群组等

事实上, FHS针对目录树架构仅定义出三层目录下面应该放置什么数据而已, 分别是下这三个目录的定义:

  • / ( root, 根目录) : 与开机系统有关;
  • /usr ( unix software resource) : 与软件安装/执行有关;
  • /var ( variable) : 与系统运行过程有关。

每层目录下面所应该要放置的目录也都又特定的规定。

根目录 ( /) 的意义与内容:

   根目录是整个系统最重要的一个目录, 因为不但所有的目录都是由根目录衍生出来的, 同时根目录也与开机/还原/系统修复等动作有关。 由于系统开机时需要特定的开机软件、 核心文件、 开机所需程序、 函数库等等文件数据, 若系统出现错误时, 根目录也必须要包含有能够修复文件系统的程序才行。 因为根目录是这么的重要, 所以在FHS的要求方面, 他希望根目录不要放在非常大的分区内, 因为越大的分区你会放入越多的数据, 如此一来根目录所在分区就可能会有较多发生错误的机会

  因此FHS标准建议: 根目录( /) 所在分区应该越小越好, 且应用程序所安装的软件最好不要与根目录放在同一个分区内, 保持根目录越小越好。 如此不但性能较佳, 根目录所在的文件系统也较不容易发生问题。

有鉴于上述的说明, 因此FHS定义出根目录( /) 下面应该要有下面这些次目录的存在才好即使没有实体目录FHS也希望至少有链接文件存在才好:

目录应放置文件内容
第一部份: FHS要求必须要存在的目录
/bin系统有很多放置可执行文件的目录, 但/bin比较特殊。 因为/bin放置的是在单人维护模式下还能够被操作的指令。 在/bin下面的指令可以被root与一般帐号所使用, 主要有: cat, chmod, chown, date, mv, mkdir, cp, bash等等常用的指令。
/boot这个目录主要在放置开机会使用到的文件, 包括Linux核心文件以及开机菜单与开机所需配置文件等等。 Linux kernel常用的文件名为: vmlinuz, 如果使用的是grub2这个开机管理程序, 则还会存在/boot/grub2/这个目录喔!
/dev在Linux系统上, 任何设备与周边设备都是以文件的型态存在于这个目录当中的。 你只要通过存取这个目录下面的某个文件, 就等于存取某个设备啰~ 比要重要的文件有/dev/null, /dev/zero, /dev/tty, /dev/loop, /dev/sd等等
/etc系统主要的配置文件几乎都放置在这个目录内, 例如人员的帐号密码档、各种服务的启始档等等。 一般来说, 这个目录下的各文件属性是可以让一般使用者查阅的, 但是只有root有权力修改。 FHS建议不要放置可可执行文件( binary) 在这个目录中喔。 比较重要的文件有: /etc/modprobe.d/,/etc/passwd, /etc/fstab, /etc/issue 等等。 另外 FHS 还规范几个重要的目录最好要存在 /etc/ 目录下喔: /etc/opt( 必要) : 这个目录在放置第三方协力软件 /opt 的相关配置文件 /etc/X11/( 建议) : 与 X Window 有关的各种配置文件都在这里, 尤其是 xorg.conf 这个 X Server 的配置文件。 /etc/sgml/( 建议) : 与 SGML 格式有关的各项配置文件 /etc/xml/( 建议) : 与 XML格式有关的各项配置文件
/lib系统的函数库非常的多, 而/lib放置的则是在开机时会用到的函数库, 以及在/bin或/sbin下面的指令会调用的函数库而已。 什么是函数库呢? 你可以将他想成是“外挂”, 某些指令必须要有这些“外挂”才能够顺利完成程序的执行之意。 另外 FSH 还要求下面的目录必须要存在: /lib/modules/: 这个目录主要放置可抽换式的核心相关模块( 驱动程序) 喔!
/mediamedia是“媒体”的英文, 顾名思义, 这个/media下面放置的就是可移除的设备啦! 包括软盘、 光盘、 DVD等等设备都暂时挂载于此。 常见的文件名有: /media/floppy, /media/cdrom等等。
/mnt如果你想要暂时挂载某些额外的设备, 一般建议你可以放置到这个目录中。在古早时候, 这个目录的用途与/media相同啦! 只是有了/media之后, 这个目录就用来暂时挂载用了。
/opt这个是给第三方协力软件放置的目录。 什么是第三方协力软件啊? 举例来说, KDE这个桌面管理系统是一个独立的计划, 不过他可以安装到Linux系统中, 因此KDE的软件就建议放置到此目录下了。 另外, 如果你想要自行安装额外的软件( 非原本的distribution提供的) , 那么也能够将你的软件安装到这里来。 不过, 以前的Linux系统中, 我们还是习惯放置在/usr/local目录下呢!
/run早期的 FHS 规定系统开机后所产生的各项信息应该要放置到 /var/run 目录下, 新版的 FHS 则规范到 /run 下面。 由于 /run 可以使用内存来仿真, 因此性能上会好很多!
/sbinLinux有非常多指令是用来设置系统环境的, 这些指令只有root才能够利用来“设置”系统, 其他使用者最多只能用来“查询”而已。 放在/sbin下面的为开机过程中所需要的, 里面包括了开机、 修复、 还原系统所需要的指令。 至于某些服务器软件程序, 一般则放置到/usr/sbin/当中。 至于本机自行安装的软件所产生的系统可执行文件( system binary) , 则放置到/usr/local/sbin/当中了。 常见的指令包括: fdisk, fsck, ifconfig, mkfs等等。
/srvsrv可以视为“service”的缩写, 是一些网络服务启动之后, 这些服务所需要取用的数据目录。 常见的服务例如WWW, FTP等等。 举例来说, WWW服务器需要的网页数据就可以放置在/srv/www/里面。 不过, 系统的服务数据如果尚未要提供给网际网络任何人浏览的话, 默认还是建议放置到 /var/lib下面即可。
/tmp这是让一般使用者或者是正在执行的程序暂时放置文件的地方。 这个目录是任何人都能够存取的, 所以你需要定期的清理一下。 当然, 重要数据不可放置在此目录啊! 因为FHS甚至建议在开机时, 应该要将/tmp下的数据都删除唷!
/usr第二层 FHS 设置, 参考下文
/var第二层 FHS 设置, 主要为放置变动性的数据, 参考下文
第二部份: FHS建议可以存在的目录
/home这是系统默认的使用者主文件夹( home directory) 。 在你新增一个一般使用者帐号时, 默认的使用者主文件夹都会规范到这里来。 比较重要的是,主文件夹有两种代号喔: ~: 代表目前这个使用者的主文件夹 ~dmtsai : 则代表 dmtsai 的主文件夹!
/lib<qual> 用来存放与 /lib 不同的格式的二进制函数库, 例如支持 64 位的 /lib64 函数库等
/root系统管理员( root) 的主文件夹。 之所以放在这里, 是因为如果进入单人维护模式而仅挂载根目录时, 该目录就能够拥有root的主文件夹, 所以我们会希望root的主文件夹与根目录放置在同一个分区中。

事实上FHS针对根目录所定义的标准就仅有上面的内容, 不过我们的Linux下面还有许多目录你也需要了解一下的。 下面是几个在Linux当中也是非常重要的目录:

目录应放置文件内容
/lost+found这个目录是使用标准的ext2/ext3/ext4文件系统格式才会产生的一个目录,目的在于当文件系统发生错误时, 将一些遗失的片段放置到这个目录下。不过如果使用的是 xfs 文件系统的话, 就不会存在这个目录了!
/proc这个目录本身是一个“虚拟文件系统( virtual filesystem) ”喔! 他放置的数据都是在内存当中, 例如系统核心、 行程信息( process) 、 周边设备的状态及网络状态等等。 因为这个目录下的数据都是在内存当中, 所以本身不占任何硬盘空间啊! 比较重要的文件例如: /proc/cpuinfo, /proc/dma,/proc/interrupts, /proc/ioports, /proc/net/* 等等。
/sys 这个目录其实跟/proc非常类似, 也是一个虚拟的文件系统, 主要也是记录核心与系统硬件信息较相关的信息。 包括目前已载入的核心模块与核心侦测到的硬件设备信息等等。 这个目录同样不占硬盘容量喔!

早期 Linux 在设计的时候, 若发生问题时, 救援模式通常仅挂载根目录而已, 因此有五个重要的目录被要求一定要与根目录放置在一起, 那就是 /etc, /bin, /dev, /lib, /sbin 这五个重要目录。 现在许多的 Linux distributions 由于已经将许多非必要的文件移出 /usr 之外了, 所以/usr 也是越来越精简, 同时因为 /usr 被建议为“即使挂载成为只读, 系统还是可以正常运行”的模样所以救援模式也能同时挂载 /usr ! 例如我们的这个 CentOS 7.x 版本在救援模式的情况下就是这样。 因此那个五大目录的限制已经被打破了例如 CentOS 7.x 就已经将/sbin, /bin, /lib 通通移动到 /usr 下面了!

/usr 的意义与内容:

依据FHS的基本定义, /usr里面放置的数据属于可分享的与不可变动的( shareable,static) , 如果你知道如何通过网络进行分区的挂载 , 那么/usr确实可以分享给区域网络内的其他主机来使用

FHS建议所有软件开发者, 应该将他们的数据合理的分别放置到这个目录下的次目录, 而不要自行创建该软件自己独立的目录。

因为是所有系统默认的软件( distribution发布者提供的软件) 都会放置到/usr下面, 因此这个目录有点类似Windows 系统的“C:\Windows\ ( 当中的一部份) + C:\Program files\”这两个目录的综合体, 系统刚安装完毕时, 这个目录会占用最多的硬盘容量。 一般来说, /usr的次目录建议有下面这些:

目录应放置文件内容
第一部份: FHS要求必须要存在的目录
/usr/bin/所有一般用户能够使用的指令都放在这里! 目前新的 CentOS 7 已经将全部的使用者指令放置于此, 而使用链接文件的方式将 /bin 链接至此!也就是说, /usr/bin 与 /bin 是一模一样了! 另外, FHS 要求在此目录下不应该有子目录!
/usr/lib/基本上, 与 /lib 功能相同, 所以 /lib 就是链接到此目录中的!
/usr/local/系统管理员在本机自行安装自己下载的软件( 非distribution默认提供者) , 建议安装到此目录, 这样会比较便于管理。 举例来说, 你的distribution提供的软件较旧, 你想安装较新的软件但又不想移除旧版,此时你可以将新版软件安装于/usr/local/目录下, 可与原先的旧版软件有分别啦! 你可以自行到/usr/local去看看, 该目录下也是具有bin, etc,include, lib...的次目录喔!
/usr/share/主要放置只读架构的数据文件, 当然也包括共享文件。 在这个目录下放置的数据几乎是不分硬件架构均可读取的数据, 因为几乎都是文字文件嘛! 在此目录下常见的还有这些次目录: /usr/share/man: 线上说明文档 /usr/share/doc: 软件杂项的文件说明 /usr/share/zoneinfo: 与时区有关的时区文件
第二部份:FHS 建议可以存在的目录
/usr/games/与游戏比较相关的数据放置处
/usr/include/c/c++等程序语言的文件开始( header) 与包含档( include) 放置处,当我们以tarball方式 ( *.tar.gz 的方式安装软件) 安装某些数据时, 会使用到里头的许多包含档喔!
/usr/libexec/某些不被一般使用者惯用的可执行文件或脚本( script) 等等, 都会放置在此目录中。 例如大部分的 X 窗口下面的操作指令, 很多都是放在此目录下的。
/usr/lib<qual> 与 /lib<qual>/功能相同, 因此目前 /lib<qual>就是链接到此目录中
/usr/src/一般源代码建议放置到这里, src有source的意思。 至于核心源代码则建议放置到/usr/src/linux/目录下
/var 的意义与内容:

如果/usr是安装时会占用较大硬盘容量的目录, 那么/var就是在系统运行后才会渐渐占用硬盘容量的目录。
因为/var目录主要针对常态性变动的文件, 包括高速缓存( cache) 、 登录文件( log file) 以及某些软件运行所产生的文件, 包括程序文件( lock file, run file) , 或者例如MySQL数据库的文件等等。
常见的次目录有:

目录应放置文件内容
第一部份: FHS要求必须要存在的目录
/var/cache/应用程序本身运行过程中会产生的一些暂存盘;
/var/lib/程序本身执行的过程中, 需要使用到的数据文件放置的目录。 在此目录下各自的软件应该要有各自的目录。 举例来说, MySQL的数据库放置到/var/lib/mysql/而rpm的数据库则放到/var/lib/rpm去!
/var/lock/某些设备或者是文件资源一次只能被一个应用程序所使用, 如果同时有两个程序使用该设备时, 就可能产生一些错误的状况, 因此就得要将该设备上锁( lock) , 以确保该设备只会给单一软件所使用。 举例来说, 烧录机正在烧录一块光盘, 你想一下, 会不会有两个人同时在使用一个烧录机烧片? 如果两个人同时烧录, 那片子写入的是谁的数据? 所以当第一个人在烧录时该烧录机就会被上锁, 第二个人就得要该设备被解除锁定( 就是前一个人用完了) 才能够继续使用啰。 目前此目录也已经挪到 /run/lock 中!
/var/log/重要到不行! 这是登录文件放置的目录! 里面比较重要的文件如/var/log/messages, /var/log/wtmp( 记录登陆者的信息) 等。
/var/mail/放置个人电子邮件信箱的目录, 不过这个目录也被放置到/var/spool/mail/目录中! 通常这两个目录是互为链接文件啦!
/var/run/某些程序或者是服务启动后, 会将他们的PID放置在这个目录下喔! 至于PID的意义我们会在后续章节提到的。 与 /run 相同, 这个目录链接到 /run去了!
/var/spool/这个目录通常放置一些伫列数据, 所谓的“伫列”就是排队等待其他程序使用的数据啦! 这些数据被使用后通常都会被删除。 举例来说, 系统收到新信会放置到/var/spool/mail/中, 但使用者收下该信件后该封信原则上就会被删除。 信件如果暂时寄不出去会被放到/var/spool/mqueue/中, 等到被送出后就被删除。 如果是工作调度数据( crontab) , 就会被放置到/var/spool/cron/目录中!

目录树( directory tree):

在Linux下面, 所有的文件与目录都是由根目录开始的! 那是所有目录与文件的源头~然后再一个一个的分支下来, 有点像是树枝状啊~因此, 我们也称这种目录配置方式为: “目录树( directory tree) ” ,他主要的特性有:

  • 目录树的启始点为根目录 ( /, root) ;
  • 每一个目录不止能使用本地端的 partition 的文件系统, 也可以使用网络上的 filesystem。 举例来说, 可以利用 Network File System ( NFS) 服务器挂载某特定目录等
  • 每一个文件在此目录树中的文件名( 包含完整路径) 都是独一无二的。

Linux 文件与目录管理

目录与路径

目录的相关操作

常用的特殊目录

目录意义
.代表此层目录
代表此层目录
-代表前一个工作目录
~代表“目前使用者身份”所在的主文件夹
~name代表 account 这个使用者的主文件夹( account是个帐号名称)

常见的处理目录的指令

  • cd: 变换目录
  • pwd: 显示目前的目录
  • mkdir: 创建一个新的目录
  • rmdir: 删除一个空的目录

cd ( change directory , 变换目录)

[dmtsai@study ~]$ su - # 先切换身份成为 root 看看!
[root@study ~]# cd [相对路径或绝对路径]
# 最重要的就是目录的绝对路径与相对路径, 还有一些特殊目录的符号啰!
[root@study ~]# cd ~dmtsai
# 代表去到 dmtsai 这个使用者的主文件夹, 亦即 /home/dmtsai
[root@study dmtsai]# cd ~
# 表示回到自己的主文件夹, 亦即是 /root 这个目录
[root@study ~]# cd
# 没有加上任何路径, 也还是代表回到自己主文件夹的意思喔!
[root@study ~]# cd ..
# 表示去到目前的上层目录, 亦即是 /root 的上层目录的意思;
[root@study /]# cd -
# 表示回到刚刚的那个目录, 也就是 /root 啰~
[root@study ~]# cd /var/spool/mail
# 这个就是绝对路径的写法! 直接指定要去的完整路径名称!
[root@study mail]# cd ../postfix
# 这个是相对路径的写法, 我们由/var/spool/mail 去到/var/spool/postfix 就这样写!

其实, 我们的提示字符, 亦即那个 [root@study ~]# 当中, 就已经有指出目前的目录了, 刚登陆时会到自己的主文件夹, 而主文件夹还有一个代码, 那就是“ ~ ”符号! 例如上面的例子可以发现, 使用“ cd ~ ”可以回到个人的主文件夹里头去! 另外, 针对 cd 的使用方法, 如果仅输入 cd 时, 代表的就是“ cd ~ ”的意思喔~ 亦即是会回到自己的主文件夹

pwd (print working directory , 显示目前所在的目录)

[root@study ~]# pwd [-P]
选项与参数:
-P : 显示出确实的路径, 而非使用链接 ( link) 路径。
范例: 单纯显示出目前的工作目录:
[root@study ~]# pwd
/root <== 显示出目录啦~
范例: 显示出实际的工作目录, 而非链接文件本身的目录名而已
[root@study ~]# cd /var/mail <==注意, /var/mail是一个链接文件
[root@study mail]# pwd
/var/mail <==列出目前的工作目录
[root@study mail]# pwd -P
/var/spool/mail <==怎么回事? 有没有加 -P 差很多~
[root@study mail]# ls -ld /var/mail
lrwxrwxrwx. 1 root root 10 May 4 17:51 /var/mail -> spool/mail
# 看到这里应该知道为啥了吧? 因为 /var/mail 是链接文件, 链接到 /var/spool/mail
# 所以, 加上 pwd -P 的选项后, 会不以链接文件的数据显示, 而是显示正确的完整路径啊!

pwd是Print Working Directory的缩写, 也就是显示目前所在目录的指令, 例如在上个表格最后的目录是/var/mail这个目录, 但是提示字符仅显示mail如果你想要知道目前所在的目录,可以输入pwd即可。 此外, 由于很多的套件所使用的目录名称都相同, 例如 /usr/local/etc还有/etc, 但是通常Linux仅列出最后面那一个目录而已, 这个时候你就可以使用pwd 来知道你的所在目录啰!
  
其实有趣的是那个 -P 的选项啦! 他可以让我们取得正确的目录名称, 而不是以链接文件的路径来显示的。 如果你使用的是CentOS 7.x的话, 刚刚好/var/mail是/var/spool/mail的链接文件, 所以, 通过到/var/mail下达pwd -P就能够知道这个选项的意义

mkdir ( make directory , 创建新目录)

[root@study ~]# mkdir [-mp] 目录名称
选项与参数:
-m : 设置文件的权限喔! 直接设置, 不需要看默认权限 ( umask) 的脸色~
-p : 帮助你直接将所需要的目录( 包含上层目录) 递回创建起来!
范例: 请到/tmp下面尝试创建数个新目录看看:
[root@study ~]# cd /tmp
[root@study tmp]# mkdir test <==创建一名为 test 的新目录
[root@study tmp]# mkdir test1/test2/test3/test4
mkdir: cannot create directory ‘test1/test2/test3/test4’: No such file or directory
# 话说, 系统告诉我们, 没可能创建这个目录啊! 就是没有目录才要创建的! 见鬼嘛?
[root@study tmp]# mkdir -p test1/test2/test3/test4
# 原来是要建 test4 上层没先建 test3 之故! 加了这个 -p 的选项, 可以自行帮你创建多层目录!
范例: 创建权限为rwx--x--x的目录
[root@study tmp]# mkdir -m 711 test2
[root@study tmp]# ls -ld test*
drwxr-xr-x. 2 root root 6 Jun 4 19:03 test
drwxr-xr-x. 3 root root 18 Jun 4 19:04 test1
drwx--x--x. 2 root root 6 Jun 4 19:05 test2
# 仔细看上面的权限部分, 如果没有加上 -m 来强制设置属性, 系统会使用默认属性。
# 那么你的默认属性为何? 这要通过下面介绍的 [umask](../Text/index.html#umask) 才能了解喔! ^_^

mkdir 在默认的情况下, 你所需要的目录得一层一层的创建才行

rmdir ( 删除“空”的目录)

[root@study ~]# rmdir [-p] 目录名称
选项与参数:
-p : 连同“上层”“空的”目录也一起删除
范例: 将于mkdir范例中创建的目录( /tmp下面) 删除掉!
[root@study tmp]# ls -ld test* <==看看有多少目录存在?
drwxr-xr-x. 2 root root 6 Jun 4 19:03 test
drwxr-xr-x. 3 root root 18 Jun 4 19:04 test1
drwx--x--x. 2 root root 6 Jun 4 19:05 test2
[root@study tmp]# rmdir test <==可直接删除掉, 没问题
[root@study tmp]# rmdir test1 <==因为尚有内容, 所以无法删除!
rmdir: failed to remove ‘test1’: Directory not empty
[root@study tmp]# rmdir -p test1/test2/test3/test4
[root@study tmp]# ls -ld test* <==您看看, 下面的输出中test与test1不见了!
drwx--x--x. 2 root root 6 Jun 4 19:05 test2
# 瞧! 利用 -p 这个选项, 立刻就可以将 test1/test2/test3/test4 一次删除~
# 不过要注意的是, 这个 rmdir 仅能“删除空的目录”喔!

目录需要一层一层的删除才行! 而且被删除的目录里面必定不能存在其他的目录或文件! 这也是所谓的空的目录( empty directory) 的意思。
 
这个时候就必须使用“ rm -r test ”, 不过, 还是使用 rmdir 比较不危险! 你也可以尝试以 -p 的选项加入, 来删除上层的目录。

关于可执行文件路径的变量: $PATH

默认指令是在PATH路径中查找。
指令的查找顺序,如果在PATH定义的目录中含有多个文件名为指令的可执行文件, 那么先搜寻到的同名指令先被执行。

范例: 先用root的身份列出搜寻的路径为何?
[root@study ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
范例: 用dmtsai的身份列出搜寻的路径为何?
[root@study ~]# exit # 由之前的 su - 离开, 变回原本的帐号! 或再取得一个终端机皆可!
[dmtsai@study ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 记不记得我们前一章说过, 目前 /bin 是链接到 /usr/bin 当中的喔!

范例:添加路径
[root@study ~]# PATH="${PATH}:/root" ==>添加 /root路径

总结:

  • 不同身份使用者默认的PATH不同, 默认能够随意执行的指令也不同( 如root与
    dmtsai) ;
  • PATH是可以修改的;
  • 使用绝对路径或相对路径直接指定某个指令的文件名来执行, 会比搜寻PATH来的正确;
  • 指令应该要放置到正确的目录下, 执行才会比较方便;
  • 本目录( .) 最好不要放到PATH当中。

文件与目录管理

文件与目录的管理上,不外乎“显示属性”、 “拷贝”、 “删除文件”及“移动文件或目录”等等。

文件与目录的查看: ls

默认显示的只有: 非隐藏文件的文件名以文件名进行排序及文件名代表的颜色显示

[root@study ~]# ls [-aAdfFhilnrRSt] 文件名或目录名称..
[root@study ~]# ls [--color={never,auto,always}] 文件名或目录名称..
[root@study ~]# ls [--full-time] 文件名或目录名称..
选项与参数:
-a : 全部的文件, 连同隐藏文件( 开头为 . 的文件) 一起列出来( 常用)
-A : 全部的文件, 连同隐藏文件, 但不包括 ... 这两个目录
-d : 仅列出目录本身, 而不是列出目录内的文件数据( 常用)
-f : 直接列出结果, 而不进行排序 ( ls 默认会以文件名排序! )
-F : 根据文件、 目录等信息, 给予附加数据结构, 例如:
	  *:代表可可执行文件; /:代表目录; =:代表 socket 文件; |:代表 FIFO 文件;
-h : 将文件大小以人类较易读的方式( 例如 GB, KB 等等) 列出来;
-i : 列出 inode 号码, inode 的意义下一章将会介绍;
-l : 长数据串行出, 包含文件的属性与权限等等数据; ( 常用)
-n : 列出 UID 与 GID 而非使用者与群组的名称 ( UID与GID会在帐号管理提到! )
-r : 将排序结果反向输出, 例如: 原本文件名由小到大, 反向则为由大到小;
-R : 连同子目录内容一起列出来, 等于该目录下的所有文件都会显示出来;
-S : 以文件大小大小排序, 而不是用文件名排序;
-t : 依时间排序, 而不是用文件名。
--color=never : 不要依据文件特性给予颜色显示;
--color=always : 显示颜色
--color=auto : 让系统自行依据设置来判断是否给予颜色
--full-time : 以完整时间模式 ( 包含年、 月、 日、 时、 分) 输出
--time={atime,ctime} : 输出 access 时间或改变权限属性时间 ( ctime)
						而非内容变更时间 ( modification time)
范例一: 将主文件夹下的所有文件列出来( 含属性与隐藏文件)
[root@study ~]# ls -al ~
total 56
dr-xr-x---. 5 root root 4096 Jun 4 19:49 .
dr-xr-xr-x. 17 root root 4096 May 4 17:56 ..
-rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg
-rw-------. 1 root root 6798 Jun 4 19:53 .bash_history
-rw-r--r--. 1 root root 18 Dec 29 2013 .bash_logout
-rw-r--r--. 1 root root 176 Dec 29 2013 .bash_profile
-rw-rw-rw-. 1 root root 176 Dec 29 2013 .bashrc
-rw-r--r--. 1 root root 176 Jun 3 00:04 .bashrc_test
drwx------. 4 root root 29 May 6 00:14 .cache
drwxr-xr-x. 3 root root 17 May 6 00:14 .config
# 这个时候你会看到以 . 为开头的几个文件, 以及目录档 ( .) ( ..) .config 等等,
# 不过, 目录档文件名都是以深蓝色显示, 有点不容易看清楚就是了。
范例二: 承上题, 不显示颜色, 但在文件名末显示出该文件名代表的类型( type[root@study ~]# ls -alF --color=never ~
total 56
dr-xr-x---. 5 root root 4096 Jun 4 19:49 ./
dr-xr-xr-x. 17 root root 4096 May 4 17:56 ../
-rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg
-rw-------. 1 root root 6798 Jun 4 19:53 .bash_history
-rw-r--r--. 1 root root 18 Dec 29 2013 .bash_logout
-rw-r--r--. 1 root root 176 Dec 29 2013 .bash_profile
-rw-rw-rw-. 1 root root 176 Dec 29 2013 .bashrc
-rw-r--r--. 1 root root 176 Jun 3 00:04 .bashrc_test
drwx------. 4 root root 29 May 6 00:14 .cache/
drwxr-xr-x. 3 root root 17 May 6 00:14 .config/
# 注意看到显示结果的第一行, 嘿嘿~知道为何我们会下达类似 ./command
# 之类的指令了吧? 因为 ./ 代表的是“目前目录下”的意思啊! 至于什么是 FIFO/Socket ?
# 请参考前一章节的介绍啊! 另外, 那个.bashrc 时间仅写2013, 能否知道详细时间?
范例三: 完整的呈现文件的修改时间 ( modification time)
[root@study ~]# ls -al --full-time ~
total 56
dr-xr-x---. 5 root root 4096 2015-06-04 19:49:54.520684829 +0800 .
dr-xr-xr-x. 17 root root 4096 2015-05-04 17:56:38.888000000 +0800 ..
-rw-------. 1 root root 1816 2015-05-04 17:57:02.326000000 +0800 anaconda-ks.cfg
-rw-------. 1 root root 6798 2015-06-04 19:53:41.451684829 +0800 .bash_history
-rw-r--r--. 1 root root 18 2013-12-29 10:26:31.000000000 +0800 .bash_logout
-rw-r--r--. 1 root root 176 2013-12-29 10:26:31.000000000 +0800 .bash_profile
-rw-rw-rw-. 1 root root 176 2013-12-29 10:26:31.000000000 +0800 .bashrc
-rw-r--r--. 1 root root 176 2015-06-03 00:04:16.916684829 +0800 .bashrc_test
drwx------. 4 root root 29 2015-05-06 00:14:56.960764950 +0800 .cache
drwxr-xr-x. 3 root root 17 2015-05-06 00:14:56.975764950 +0800 .config
# 请仔细看, 上面的“时间”字段变了喔! 变成较为完整的格式。
# 一般来说, ls -al 仅列出目前短格式的时间, 有时不会列出年份,
# 借由 --full-time 可以查阅到比较正确的完整时间格式啊!

复制、 删除与移动: cp, rm, mv

复制文件, 请使用 cp ( copy) 这个指令即可~不过, cp 这个指令的用途可多了~ 除了单纯的复制之外, 还可以创建链接文件 , 比对两文件的新旧而予以更新, 以及复制整个目录等等的功能!
 
至于移动目录与文件, 则使用 mv ( move) , 这个指令也可以直接拿来作更名 ( rename) 的动作
 
至于移除 那就是 rm ( remove) 这个指令。

cp ( 复制文件或目录):

[root@study ~]# cp [-adfilprsu] 来源文件( source) 目标文件( destination)
[root@study ~]# cp [options] source1 source2 source3 .... directory
选项与参数:
-a : 相当于 -dr --preserve=all 的意思, 至于 dr 请参考下列说明; ( 常用)
-d : 若来源文件为链接文件的属性( link file) , 则复制链接文件属性而非文件本身;
-f : 为强制( force) 的意思, 若目标文件已经存在且无法打开, 则移除后再尝试一次;
-i : 若目标文件( destination) 已经存在时, 在覆盖时会先询问动作的进行( 常用)
-l : 进行硬式链接( hard link) 的链接文件创建, 而非复制文件本身;
-p : 连同文件的属性( 权限、 用户、 时间) 一起复制过去, 而非使用默认属性( 备份常用) ;
-r : 递回持续复制, 用于目录的复制行为; ( 常用)
-s : 复制成为符号链接文件 ( symbolic link) , 亦即“捷径”文件;
-u : destination 比 source 旧才更新 destination, 或 destination 不存在的情况下才复制。
--preserve=all : 除了 -p 的权限相关参数外, 还加入 SELinux 的属性, links, xattr 等也复制了。

最后需要注意的, 如果来源文件有两个以上, 则最后一个目的文件一定要是“目录”才行!

复制( cp) 这个指令是非常重要的, 不同身份者执行这个指令会有不同的结果产生尤其是那个-a, -p的选项, 对于不同身份来说, 差异则非常的大。

范例一: 用root身份, 将主文件夹下的 .bashrc 复制到 /tmp 下, 并更名为 bashrc
[root@study ~]# cp ~/.bashrc /tmp/bashrc
[root@study ~]# cp -i ~/.bashrc /tmp/bashrc
cp: overwrite `/tmp/bashrc'? n <==n不覆盖, y为覆盖
# 重复作两次动作, 由于 /tmp 下面已经存在 bashrc 了, 加上 -i 选项后,
# 则在覆盖前会询问使用者是否确定! 可以按下 n 或者 y 来二次确认呢!
范例二: 变换目录到/tmp, 并将/var/log/wtmp复制到/tmp且观察属性:
[root@study ~]# cd /tmp
[root@study tmp]# cp /var/log/wtmp . <==想要复制到目前的目录, 最后的 . 不要忘
[root@study tmp]# ls -l /var/log/wtmp wtmp
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 /var/log/wtmp
-rw-r--r--. 1 root root 28416 Jun 11 19:01 wtmp
# 注意上面的特殊字体, 在不加任何选项的情况下, 文件的某些属性/权限会改变;
# 这是个很重要的特性! 要注意喔! 还有, 连文件创建的时间也不一样了!
# 那如果你想要将文件的所有特性都一起复制过来该怎办? 可以加上 -a 喔! 如下所示:
[root@study tmp]# cp -a /var/log/wtmp wtmp_2
[root@study tmp]# ls -l /var/log/wtmp wtmp_2
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 /var/log/wtmp
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 wtmp_2
# 瞭了吧! 整个数据特性完全一模一样! 真是不赖~这就是 -a 的特性!

这个 cp 的功能很多, 由于我们常常会进行一些数据的复制, 所以也会常常用到这个指令的。一般来说, 我们如果去复制别人的数据 ( 当然, 该文件你必须要有 read 的权限才行啊!) 时总是希望复制到的数据最后是我们自己的, 所以, 在默认的条件中, cp 的来源文件与目的文件的权限是不同的目的文件的拥有者通常会是指令操作者本身。 举例来说, 上面的范例二中, 由于我是 root 的身份, 因此复制过来的文件拥有者与群组就改变成为 root 所有了。

范例三: 复制 /etc/ 这个目录下的所有内容到 /tmp 下面
[root@study tmp]# cp /etc/ /tmp
cp: omitting directory `/etc' <== 如果是目录则不能直接复制, 要加上 -r 的选项
[root@study tmp]# cp -r /etc/ /tmp
# 还是要再次的强调喔! -r 是可以复制目录, 但是, 文件与目录的权限可能会被改变
# 所以, 也可以利用“ cp -a /etc /tmp ”来下达指令喔! 尤其是在备份的情况下!
范例四: 将范例一复制的 bashrc 创建一个链接文件 ( symbolic link)
[root@study tmp]# ls -l bashrc
-rw-r--r--. 1 root root 176 Jun 11 19:01 bashrc <==先观察一下文件情况
[root@study tmp]# cp -s bashrc bashrc_slink
[root@study tmp]# cp -l bashrc bashrc_hlink
[root@study tmp]# ls -l bashrc*
-rw-r--r--. 2 root root 176 Jun 11 19:01 bashrc <==与原始文件不太一样了!
-rw-r--r--. 2 root root 176 Jun 11 19:01 bashrc_hlink
lrwxrwxrwx. 1 root root 6 Jun 11 19:06 bashrc_slink -> bashrc

-l 就是所谓的实体链接( hard link) , 至于 -s 则是符号链接( symbolic link)
简单来说, bashrc_slink 是一个“捷径”这个捷径会链接到bashrc去! 所以你会看到文件名右侧会有个指向( ->) 的符号。
 
至于bashrc_hlink文件与bashrc的属性与权限完全一模一样, 与尚未进行链接前的差异则是第二栏的link数由1变成2了

范例五: 若 ~/.bashrc 比 /tmp/bashrc 新才复制过来
[root@study tmp]# cp -u ~/.bashrc /tmp/bashrc
# 这个 -u 的特性, 是在目标文件与来源文件有差异时, 才会复制的。
# 所以, 比较常被用于“备份”的工作当中喔! ^_^
范例六: 将范例四造成的 bashrc_slink 复制成为 bashrc_slink_1 与bashrc_slink_2
[root@study tmp]# cp bashrc_slink bashrc_slink_1
[root@study tmp]# cp -d bashrc_slink bashrc_slink_2
[root@study tmp]# ls -l bashrc bashrc_slink*
-rw-r--r--. 2 root root 176 Jun 11 19:01 bashrc
lrwxrwxrwx. 1 root root 6 Jun 11 19:06 bashrc_slink -&gt; bashrc
-rw-r--r--. 1 root root 176 Jun 11 19:09 bashrc_slink_1 <==与原始文件相同
lrwxrwxrwx. 1 root root 6 Jun 11 19:10 bashrc_slink_2 -> bashrc <==是链接文件!
# 这个例子也是很有趣喔! 原本复制的是链接文件, 但是却将链接文件的实际文件复制过来了
# 也就是说, 如果没有加上任何选项时, cp复制的是原始文件, 而非链接文件的属性!
# 若要复制链接文件的属性, 就得要使用 -d 的选项了! 如 bashrc_slink_2 所示。
范例七: 将主文件夹的 .bashrc 及 .bash_history 复制到 /tmp 下面
[root@study tmp]# cp ~/.bashrc ~/.bash_history /tmp
# 可以将多个数据一次复制到同一个目录去! 最后面一定是目录!

不同权限用户复制文件的差异

范例:
使用 dmtsai 的身份, 完整的复制/var/log/wtmp文件到/tmp下面, 并更名为dmtsai_wtmp
[dmtsai@study ~]$ cp -a /var/log/wtmp /tmp/dmtsai_wtmp
[dmtsai@study ~]$ ls -l /var/log/wtmp /tmp/dmtsai_wtmp
-rw-rw-r--. 1 dmtsai dmtsai 28416 6月 11 18:56 /tmp/dmtsai_wtmp
-rw-rw-r--. 1 root utmp 28416 6月 11 18:56 /var/log/wtmp

由于 dmtsai 的身份并不能随意修改文件的拥有者与群组因此虽然能够复制wtmp的相关权限与时间等属性但是与拥有者、 群组相关的, 原本 dmtsai 身份无法进行的动作, 即使加上 -a 选项, 也是无法达成完整复制权限的

总结:
由于 cp 有种种的文件属性与权限的特性, 所以, 在复制时, 你必须要清楚的了解到:

  • 是否需要完整的保留来源文件的信息?
  • 来源文件是否为链接文件 ( symbolic link file) ?
  • 来源文件是否为特殊的文件, 例如 FIFO, socket 等?
  • 来源文件是否为目录?

rm ( 移除文件或目录)

[root@study ~]# rm [-fir] 文件或目录
选项与参数:
-f : 就是 force 的意思, 忽略不存在的文件, 不会出现警告讯息;
-i : 互动模式, 在删除前会询问使用者是否动作
-r : 递回删除啊! 最常用在目录的删除了! 这是非常危险的选项! ! !
范例一: 将刚刚在 cp 的范例中创建的 bashrc 删除掉!
[root@study ~]# cd /tmp
[root@study tmp]# rm -i bashrc
rm: remove regular file `bashrc' ? 
# 如果加上 -i 的选项就会主动询问喔, 避免你删除到错误的文件名!

范例二: 通过万用字符*的帮忙, 将/tmp下面开头为bashrc的文件名通通删除:
[root@study tmp]# rm -i bashrc*
# 注意那个星号, 代表的是 0 到无穷多个任意字符喔! 很好用的东西!

范例三: 将 cp 范例中所创建的 /tmp/etc/ 这个目录删除掉!
[root@study tmp]# rmdir /tmp/etc
rmdir: failed to remove '/tmp/etc': Directory not empty <== 删不掉啊! 因为这不是空的目录!
[root@study tmp]# rm -r /tmp/etc
rm: descend into directory `/tmp/etc'? y
rm: remove regular file `/tmp/etc/fstab'? y
rm: remove regular empty file `/tmp/etc/crypttab'? ^C <== 按下 [crtl]+c 中断
.....( 中间省略) .....
# 因为身份是 root , 默认已经加入了 -i 的选项, 所以你要一直按 y 才会删除!
# 如果不想要继续按 y , 可以按下“ [ctrl]-c ”来结束 rm 的工作。
# 这是一种保护的动作, 如果确定要删除掉此目录而不要询问, 可以这样做:
[root@study tmp]# \rm -r /tmp/etc
# 在指令前加上反斜线, 可以忽略掉 alias 的指定选项喔! 至于 alias 我们在bash再谈!
# 拜托! 这个范例很可怕! 你不要删错了! 删除 /etc 系统是会挂掉的!

范例四: 删除一个带有 - 开头的文件
[root@study tmp]# touch ./-aaa- <==[touch](../Text/index.html#touch)这个指令可以创建空文件!
[root@study tmp]# ls -l
-rw-r--r--. 1 root root 0 Jun 11 19:22 -aaa- <==文件大小为0, 所以是空文件
[root@study tmp]# rm -aaarm: invalid option -- 'a' <== 因为 "-" 是选项嘛! 所以系统误判了!
Try 'rm ./-aaa-' to remove the file `-aaa-'. <== 新的 bash 有给建议的
Try 'rm --help' for more information.
[root@study tmp]# rm ./-aaa-

通常在Linux系统下, 为了怕文件被 root 误杀,所以很多 distributions 都已经默认加入 -i 这个选项了! 而如果要连目录下的东西都一起杀掉的话, 例如子目录里面还有子目录时, 那就要使用 -r 这个选项了! 不过, 使用“ rm -r ”这个指令之前, 请千万注意了, 因为该目录或文件“肯定”会被 root 杀掉!

mv ( 移动文件与目录, 或更名)

[root@study ~]# mv [-fiu] source destination
[root@study ~]# mv [options] source1 source2 source3 .... directory
选项与参数:
-f : force 强制的意思, 如果目标文件已经存在, 不会询问而直接覆盖;
-i : 若目标文件 ( destination) 已经存在时, 就会询问是否覆盖!
-u : 若目标文件已经存在, 且 source 比较新, 才会更新 ( update)
范例一: 复制一文件, 创建一目录, 将文件移动到目录中
[root@study ~]# cd /tmp
[root@study tmp]# cp ~/.bashrc bashrc
[root@study tmp]# mkdir mvtest
[root@study tmp]# mv bashrc mvtest
# 将某个文件移动到某个目录去, 就是这样做!
范例二: 将刚刚的目录名称更名为 mvtest2
[root@study tmp]# mv mvtest mvtest2 <== 这样就更名了! 简单~
# 其实在 Linux 下面还有个有趣的指令, 名称为 rename ,
# 该指令专职进行多个文件名的同时更名, 并非针对单一文件名变更, 与mv不同。 请man rename。
范例三: 再创建两个文件, 再全部移动到 /tmp/mvtest2 当中
[root@study tmp]# cp ~/.bashrc bashrc1
[root@study tmp]# cp ~/.bashrc bashrc2
[root@study tmp]# mv bashrc1 bashrc2 mvtest2
# 注意到这边, 如果有多个来源文件或目录, 则最后一个目标文件一定是“目录! ”
# 意思是说, 将所有的数据移动到该目录的意思!

取得路径的文件名称与目录名称

[root@study ~]# basename /etc/sysconfig/network
network <== 很简单! 就取得最后的文件名~
[root@study ~]# dirname /etc/sysconfig/network
/etc/sysconfig <== 取得的变成目录名了!

文件内容查阅

  • cat 由第一行开始显示文件内容
  • tac 从最后一行开始显示, 可以看出 tac 是 cat 的倒着写!
  • nl 显示的时候, 顺道输出行号!
  • more 一页一页的显示文件内容
  • less 与 more 类似, 但是比 more 更好的是, 他可以往前翻页!
  • head 只看头几行
  • tail 只看尾巴几行
  • od 以二进制的方式读取文件内容!

直接检视文件内容

一口气将所有数据输出

直接查阅一个文件的内容可以使用 cat/tac/nl 这几个指令
前面提到的 nl 与 cat, tac 等等, 都是一次性的将数据一口气显示到屏幕上面

cat ( concatenate , 连续)

cat 是 Concatenate ( 连续) 的简写, 主要的功能是将一个文件的内容连续的印出在屏幕上面!

[root@study ~]# cat [-AbEnTv]
选项与参数:
-A : 相当于 -vET 的整合选项, 可列出一些特殊字符而不是空白而已;
-b : 列出行号, 仅针对非空白行做行号显示, 空白行不标行号!
-E : 将结尾的断行字符 $ 显示出来;
-n : 打印出行号, 连同空白行也会有行号, 与 -b 的选项不同;
-T : 将 [tab] 按键以 ^I 显示出来;
-v : 列出一些看不出来的特殊字符
范例一: 检阅 /etc/issue 这个文件的内容
[root@study ~]# cat /etc/issue
\S
Kernel \r on an \m
范例二: 承上题, 如果还要加印行号呢?
[root@study ~]# cat -n /etc/issue
1 \S
2 Kernel \r on an \m
3
# 所以这个文件有三行! 看到了吧! 可以印出行号呢! 这对于大文件要找某个特定的行时, 有点用处!
# 如果不想要编排空白行的行号, 可以使用“cat -b /etc/issue”, 自己测试看看:
范例三: 将 /etc/man_db.conf 的内容完整的显示出来( 包含特殊字符)
[root@study ~]# cat -A /etc/man_db.conf
# $
....( 中间省略) ....
MANPATH_MAP^I/bin^I^I^I/usr/share/man$
MANPATH_MAP^I/usr/bin^I^I/usr/share/man$
MANPATH_MAP^I/sbin^I^I^I/usr/share/man$
MANPATH_MAP^I/usr/sbin^I^I/usr/share/man$
.....( 下面省略) .....
# 上面的结果限于篇幅, 鸟哥删除掉很多数据了。 另外, 输出的结果并不会有特殊字体,
# 鸟哥上面的特殊字体是要让您发现差异点在哪里就是了。 基本上, 在一般的环境中,
# 使用 [tab] 与空白键的效果差不多, 都是一堆空白啊! 我们无法知道两者的差别。
# 此时使用 cat -A 就能够发现那些空白的地方是啥鬼东西了! [tab]会以 ^I 表示,
# 断行字符则是以 $ 表示, 所以你可以发现每一行后面都是 $ 啊! 不过断行字符
# 在Windows/Linux则不太相同, Windows的断行字符是 ^M$ 啰。
# 这部分我们会在[第九章 vim 软件](../Text/index.html#tips_dos)的介绍时, 再次的说明到喔!

tac ( 反向列示)

tac 刚好是将 cat 反写过来, 所以他的功能就跟 cat 相反啦, cat 是由“第一行到最后一行连续显示在屏幕上”, 而 tac 则是“ 由最后一行到第一行反向在屏幕上显示出来 ”

[root@study ~]# tac /etc/issue
Kernel \r on an \m
\S
# 嘿嘿! 与刚刚上面的范例一比较, 是由最后一行先显示喔!

nl ( 添加行号打印)

nl 可以将输出的文件内容自动的加上行号! 其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计, 包括位数与是否自动补齐 0 等等的功能

[root@study ~]# nl [-bnw] 文件
选项与参数:
-b : 指定行号指定的方式, 主要有两种:
-b a : 表示不论是否为空行, 也同样列出行号( 类似 cat -n) ;
-b t : 如果有空行, 空的那一行不要列出行号( 默认值) ;
-n : 列出行号表示的方法, 主要有三种:
-n ln : 行号在屏幕的最左方显示;
-n rn : 行号在自己字段的最右方显示, 且不加 0 ;
-n rz : 行号在自己字段的最右方显示, 且加 0 ;
-w : 行号字段的占用的字符数。
范例一: 用 nl 列出 /etc/issue 的内容
[root@study ~]# nl /etc/issue
1 \S
2 Kernel \r on an \m
# 注意看, 这个文件其实有三行, 第三行为空白( 没有任何字符) ,
# 因为他是空白行, 所以 nl 不会加上行号喔! 如果确定要加上行号, 可以这样做:
[root@study ~]# nl -b a /etc/issue
1 \S
2 Kernel \r on an \m
3
# 呵呵! 行号加上来啰~那么如果要让行号前面自动补上 0 呢? 可这样
[root@study ~]# nl -b a -n rz /etc/issue
000001 \S
000002 Kernel \r on an \m
000003
# 嘿嘿! 自动在自己字段的地方补上 0 了~默认字段是六位数, 如果想要改成 3 位数?
[root@study ~]# nl -b a -n rz -w 3 /etc/issue
001 \S
002 Kernel \r on an \m
003
# 变成仅有 3 位数啰~

可翻页检视

more ( 一页一页翻动)

[root@study ~]# more /etc/man_db.conf
###
This file is used by the man-db package to configure the man and cat paths.
# It is also used to provide a manpath for those without one by examining
# their PATH environment variable. For details see the manpath( 5) man page.
#.
....( 中间省略) .....
--More--( 28%) <== 重点在这一行喔! 你的光标也会在这里等待你的指令

如果 more 后面接的文件内容行数大于屏幕输出的行数时, 就会出现类似上面的图示。 重点在最后一行, 最后一行会显示出目前显示的百分比, 而且还可以在最后一行输入一些有用的指令:

  • 键 ( space) : 代表向下翻一页;
  • Enter : 代表向下翻“一行”;
  • /字串 : 代表在这个显示的内容当中, 向下搜寻“字串”这个关键字;
  • :f : 立刻显示出文件名以及目前显示的行数;
  • q : 代表立刻离开 more , 不再显示该文件内容。
  • b 或 [ctrl]-b : 代表往回翻页, 不过这动作只对文件有用, 对管线无用

less ( 一页一页翻动)

[root@study ~]# less /etc/man_db.conf
###
This file is used by the man-db package to configure the man and cat paths.
# It is also used to provide a manpath for those without one by examining
# their PATH environment variable. For details see the manpath( 5) man page.
#.
....( 中间省略) .....
: <== 这里可以等待你输入指令!

可以输入指令:

  • 空白键 : 向下翻动一页;
  • [pagedown]: 向下翻动一页;
  • [pageup] : 向上翻动一页;
  • /字串 : 向下搜寻“字串”的功能;
  • ?字串 : 向上搜寻“字串”的功能;
  • n : 重复前一个搜寻 ( 与 / 或 ? 有关! )
  • N : 反向的重复前一个搜寻 ( 与 / 或 ? 有关! )
  • g : 前进到这个数据的第一行去;
  • G : 前进到这个数据的最后一行去 ( 注意大小写) ;
  • q : 离开 less 这个程序;

数据撷取

我们可以将输出的数据作一个最简单的撷取, 那就是取出文件前面几行 ( head) 或取出后面几行 ( tail) 文字的功能。
不过, 要注意的是, head 与 tail 都是以“行”为单位来进行数据撷取的。

head ( 取出前面几行)

[root@study ~]# head [-n number] 文件
选项与参数:
-n : 后面接数字, 代表显示几行的意思
[root@study ~]# head /etc/man_db.conf
# 默认的情况中, 显示前面十行! 若要显示前 20 行, 就得要这样:
[root@study ~]# head -n 20 /etc/man_db.conf
范例: 如果后面100行的数据都不打印, 只打印/etc/man_db.conf的前面几行, 该如何是好?
[root@study ~]# head -n -100 /etc/man_db.conf

tail ( 取出后面几行)

[root@study ~]# tail [-n number] 文件
选项与参数:
-n : 后面接数字, 代表显示几行的意思
-f : 表示持续侦测后面所接的文件名, 要等到按下[ctrl]-c才会结束tail的侦测
[root@study ~]# tail /etc/man_db.conf
# 默认的情况中, 显示最后的十行! 若要显示最后的 20 行, 就得要这样:
[root@study ~]# tail -n 20 /etc/man_db.conf
范例一: 如果不知道/etc/man_db.conf有几行, 却只想列出100行以后的数据时?
[root@study ~]# tail -n +100 /etc/man_db.conf
范例二: 持续侦测/var/log/messages的内容
[root@study ~]# tail -f /var/log/messages
<==要等到输入[crtl]-c之后才会离开tail这个指令的侦测!

例二中, 由于/var/log/messages随时会有数据写入, 你想要让该文件有数据写入时就立刻显示到屏幕上, 就利用 -f 这个选项, 他可以一直侦测/var/log/messages这个文件, 新加入的数据都会被显示到屏幕上。 直到你按下[crtl]-c才会离开tail的侦测

假如我想要显示 /etc/man_db.conf 的第 11 到第 20 行呢? 答: 这个应该不算难, 想一想, 在第 11 到第 20 行, 那么我取前 20 行, 再取后十行, 所以结果就是: “ head -n 20/etc/man_db.conf | tail -n 10 ”, 这样就可以得到第 11 到第 20 行之间的内容。

这两个指令中间有个管线 ( |) 的符号存在, 这个管线的意思是: “前面的指令所输出的讯息, 请通过管线交由后续的指令继续使用”的意思。

非纯文本文件: od

我们上面提到的, 都是在查阅纯文本文件的内容。 那么万一我们想要查阅非文本文件, 举例来说, 例如 /usr/bin/passwd 这个可执行文件的内容时, 又该如何去读出信息呢? 事实上, 由于可执行文件通常是 binary file , 使用上头提到的指令来读取他的内容时, 确实会产生类似乱码的数据! 那怎么办? 没关系, 我们可以利用 od 这个指令来读取

[root@study ~]# od [-t TYPE] 文件
选项或参数:
-t : 后面可以接各种“类型 ( TYPE) ”的输出, 例如:
	a : 利用默认的字符来输出;
	c : 使用 ASCII 字符来输出
	d[size] : 利用十进制( decimal) 来输出数据, 每个整数占用 size Bytes ;
	f[size] : 利用浮点数值( floating) 来输出数据, 每个数占用 size Bytes ;
	o[size] : 利用八进位( octal) 来输出数据, 每个整数占用 size Bytes ;
	x[size] : 利用十六进制( hexadecimal) 来输出数据, 每个整数占用 size Bytes ;
范例一: 请将/usr/bin/passwd的内容使用ASCII方式来展现!
[root@study ~]# od -t c /usr/bin/passwd
0000000 177 E L F 002 001 001 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 003 \0 &gt; \0 001 \0 \0 \0 364 3 \0 \0 \0 \0 \0 \0
0000040 @ \0 \0 \0 \0 \0 \0 \0 x e \0 \0 \0 \0 \0 \0
0000060 \0 \0 \0 \0 @ \0 8 \0 \t \0 @ \0 035 \0 034 \0
0000100 006 \0 \0 \0 005 \0 \0 \0 @ \0 \0 \0 \0 \0 \0 \0
.....( 后面省略) ....
# 最左边第一栏是以 8 进位来表示Bytes数。 以上面范例来说, 第二栏0000020代表开头是
# 第 16 个 byes ( 2x8) 的内容之意。
范例二: 请将/etc/issue这个文件的内容以8进位列出储存值与ASCII的对照表
[root@study ~]# od -t oCc /etc/issue
0000000 134 123 012 113 145 162 156 145 154 040 134 162 040 157 156 040
\ S \n K e r n e l \ r o n
0000020 141 156 040 134 155 012 012
a n \ m \n \n
0000027
# 如上所示, 可以发现每个字符可以对应到的数值为何! 要注意的是, 该数值是 8 进位喔!
# 例如 S 对应的记录数值为 123 , 转成十进制: 1x8^2+2x8+3=83。

修改文件时间或创建新文件: touch

每个文件在linux下面都会记录许多的时间参数, 其实是有三个主要的变动时间:

  • modification time ( mtime) : 当该文件的“内容数据”变更时, 就会更新这个时间! 内容数据指的是文件的内容, 而不是文件的属性或权限喔!
  • status time ( ctime) : 当该文件的“状态 ( status) ”改变时, 就会更新这个时间, 举例来说, 像是权限与属性被更改了, 都会更新这个时间
  • access time ( atime) : 当“该文件的内容被取用”时, 就会更新这个读取时间( access) 。 举例来说, 我们使用 cat 去读取 /etc/man_db.conf , 就会更新该文件的atime 了。
[root@study ~]# touch [-acdmt] 文件
选项与参数:
-a : 仅修订 access time;
-c : 仅修改文件的时间, 若该文件不存在则不创建新文件;
-d : 后面可以接欲修订的日期而不用目前的日期, 也可以使用 --date="日期或时间"
-m : 仅修改 mtime ;
-t : 后面可以接欲修订的时间而不用目前的时间, 格式为[YYYYMMDDhhmm]
范例一: 新建一个空的文件并观察时间
[dmtsai@study ~]# cd /tmp
[dmtsai@study tmp]# touch testtouch
[dmtsai@study tmp]# ls -l testtouch
-rw-rw-r--. 1 dmtsai dmtsai 0 Jun 16 00:45 testtouch
# 注意到, 这个文件的大小是 0 呢! 在默认的状态下, 如果 touch 后面有接文件,
# 则该文件的三个时间 ( atime/ctime/mtime) 都会更新为目前的时间。 若该文件不存在,
# 则会主动的创建一个新的空的文件喔! 例如上面这个例子!
范例二: 将 ~/.bashrc 复制成为 bashrc, 假设复制完全的属性, 检查其日期
[dmtsai@study tmp]# cp -a ~/.bashrc bashrc
[dmtsai@study tmp]# date; ll bashrc; ll --time=atime bashrc; ll --time=ctime bashrc
Tue Jun 16 00:49:24 CST 2015 &lt;==这是目前的时间
-rw-r--r--. 1 dmtsai dmtsai 231 Mar 6 06:06 bashrc <==这是 mtime
-rw-r--r--. 1 dmtsai dmtsai 231 Jun 15 23:44 bashrc <==这是 atime
-rw-r--r--. 1 dmtsai dmtsai 231 Jun 16 00:47 bashrc <==这是 ctime

touch 这个指令最常被使用的情况是:

  • 创建一个空的文件
  • 将某个文件日期修订为目前 ( mtime 与 atime)
  • 不能用来修改stime;该事件为权限等状态变化时间,只能用过修改权限等状态来改变。
     

要注意的是, 即使我们复制一个文件时, 复制所有的属性, 但也没有办法复制ctime 这个属性的。 ctime 可以记录这个文件最近的状态 ( status) 被改变的时间。

文件与目录的默认权限与隐藏权限

除了基本r, w, x权限外, 在Linux传统的Ext2/Ext3/Ext4文件系统下, 我们还可以设置其他的系统隐藏属性, 这部份可使用 chattr 来设置, 而以 lsattr 来查看, 最重要的属性就是可以设置其不可修改的特性! 让连文件的拥有者都不能进行修改! 这个属性可是相当重要的, 尤其是在安全机制上面 ( security) ! 比较可惜的是, 在 CentOS 7.x 当中利用 xfs 作为默认文件系统, 但是 xfs 就没有支持所有的 chattr 的参数了! 仅有部份参数还有支持而已!

文件默认权限: umask

umask 就是指定 “目前用户在创建文件或目录时候的权限默认值”。
通过不同类型的文件的默认值减去umask的设置值来设定文件默认权限。

范例一:
查看umask设定值
[root@study ~]# umask    <==以数字方式显示
0022  <==与一般权限有关的是后面三个数字!
[root@study ~]# umask -S <==以符号类型的方式显示
u=rwx,g=rx,o=rx

在默认权限的属性上, 目录与文件是不一样的:

  • 若使用者创建为“文件”则默认“没有可执行( x ) 权限”, 亦即只有 rw 这两个项目, 也就是最大为 666 分, 默认权限如下: -rw-rw-rw
  • 若使用者创建为“目录”, 则由于 x 与是否可以进入此目录有关, 因此默认为所有权限均开放, 亦即为 777 分, 默认权限如下: drwxrwxrwx
     

要注意的是, umask 的分数指的是该默认值需要减掉的权限! ”。
因为 r、 w、 x 分别是 4、 2、1 分, 所以, 也就是说, 当要拿掉能写的权限, 就是输入 2 分, 而如果要拿掉能读的权限, 也就是 4 分, 那么要拿掉读与写的权限, 也就是 6 分, 而要拿掉执行与写入的权限, 也就是 3 分。
 

如果以上面的例子来说明的话, 因为 umask 为 022 , 所以 user 并没有被拿掉任何权限, 不过 group 与 others 的权限被拿掉了 2 ( 也就是 w 这个权限) , 那么当使用者:

  • 创建文件时: ( -rw-rw-rw-) - ( -----w–w-) ==> -rw-r–r–
  • 创建目录时: ( drwxrwxrwx) - ( d----w–w-) ==> drwxr-xr-x
范例二:
设定用户的umask值
[root@study ~]# umask 002

在默认的情况中, root 的 umask 会拿掉比较多的属性root 的 umask 默认是 022这是基于安全的考虑至于一般身份使用者, 通常他们的 umask 为 002 , 亦即保留同群组的写入权力! 其实, 关于默认 umask 的设置可以参考 /etc/bashrc 这个文件的内容, 不过, 不建议修改该文件。

文件隐藏属性

隐藏的属性对于系统有很大的帮助~ 尤其是在系统安全 ( Security) 上面。
 

要先强调的是, 下面的chattr指令只能在Ext2/Ext3/Ext4的 Linux 传统文件系统上面完整生效其他的文件系统可能就无法完整的支持这个指令了, 例如 xfs 仅支持部份参数而已。

chattr ( 设置文件隐藏属性):

[root@study ~]# chattr [+-=][ASacdistu] 文件或目录名称

选项与参数:
+ : 增加某一个特殊参数, 其他原本存在参数则不动。
- : 移除某一个特殊参数, 其他原本存在参数则不动。
= : 设置一定, 且仅有后面接的参数。

A : 当设置了 A 这个属性时, 若你有存取此文件( 或目录) 时, 他的存取时间 atime 将不会被修改,
	 可避免 I/O 较慢的机器过度的存取磁盘。 ( 目前建议使用文件系统挂载参数处理这个项目)
S : 一般文件是非同步写入磁盘的( 原理请参考[前一章sync](../Text/index.html#sync)的说明) , 
	如果加上 S 这个属性时,当你进行任何文件的修改, 该更动会“同步”写入磁盘中。
a : 当设置 a 之后, 这个文件将只能增加数据, 而不能删除也不能修改数据, 只有root 才能设置这属性
c : 这个属性设置之后, 将会自动的将此文件“压缩”, 在读取的时候将会自动解压缩,
	但是在储存的时候, 将会先进行压缩后再储存( 看来对于大文件似乎蛮有用的! )
d : 当 dump 程序被执行的时候, 设置 d 属性将可使该文件( 或目录) 不会被 dump 备份
i : 这个 i 可就很厉害了! 他可以让一个文件“不能被删除、 改名、 设置链接也无法写入或新增数据! ”
	对于系统安全性有相当大的助益! 只有 root 能设置此属性
s : 当文件设置了 s 属性时, 如果这个文件被删除, 他将会被完全的移除出这个硬盘空间,
	所以如果误删了, 完全无法救回来了喔!
u : 与 s 相反的, 当使用 u 来设置文件时, 如果该文件被删除了, 则数据内容其实还存在磁盘中,
	可以使用来救援该文件喔!
	
注意1: 属性设置常见的是 a 与 i 的设置值, 而且很多设置值必须要身为 root 才能设置
注意2: xfs 文件系统仅支持 AadiS 而已

范例: 请尝试到/tmp下面创建文件, 并加入 i 的参数, 尝试删除看看。
[root@study ~]# cd /tmp
[root@study tmp]# touch attrtest <==创建一个空文件
[root@study tmp]# chattr +i attrtest <==给予 i 的属性
[root@study tmp]# rm attrtest <==尝试删除看看
rm: remove regular empty file `attrtest'? y
rm: cannot remove `attrtest': Operation not permitted
# 看到了吗? 呼呼! 连 root 也没有办法将这个文件删除呢! 赶紧解除设置!
范例: 请将该文件的 i 属性取消!
[root@study tmp]# chattr -i attrtest

lsattr ( 显示文件隐藏属性):

[root@study ~]# lsattr [-adR] 文件或目录
选项与参数:
-a : 将隐藏文件的属性也秀出来;
-d : 如果接的是目录, 仅列出目录本身的属性而非目录内的文件名;
-R : 连同子目录的数据也一并列出来!
[root@study tmp]# chattr +aiS attrtest
[root@study tmp]# lsattr attrtest
--S-ia---------- attrtest

文件特殊权限: SUID, SGID, SBIT

范例:

[root@study ~]# ls -ld /tmp ; ls -l /usr/bin/passwd
drwxrwxrwt. 14 root root 4096 Jun 16 01:27 /tmp
-rwsr-xr-x. 1  root root 27832 Jun 10 2014 /usr/bin/passwd

Set UID

当 s 这个标志出现在文件拥有者的 x 权限上时, 例如范例提到的 /usr/bin/passwd 这个文件的权限状态: “-rwsr-xr-x”, 此时就被称为 Set UID, 简称为 SUID 的特殊权限
 
基本上SUID有这样的限制与功能:

  • SUID 权限仅对二进制程序( binary program) 有效
  • 执行者对于该程序需要具有 x 的可执行权限
  • 本权限仅在执行该程序的过程中有效 ( run-time)
  • 执行者将具有该程序拥有者 ( owner) 的权限

例子:
Linux 系统中, 所有帐号的密码都记录在 /etc/shadow 这个文件里面, 这个文件的权限为: “---------- 1 root root”, 意思是这个文件仅有root可读且仅有root可以强制写入而已。 但是其他用户如:dmtsai,依然可以自行修改自己的密码;dmtsai对密码文件并没有任何权限,但是可以通过passwd指令来操作修改密码;

由SUID功能,分析得出:

  1. dmtsai 对于 /usr/bin/passwd 这个程序来说是具有 x 权限的, 表示 dmtsai 能执行passwd;
  2. passwd 的拥有者是 root 这个帐号;
  3. dmtsai 执行 passwd 的过程中, 会“暂时”获得 root 的权限;
  4. /etc/shadow 就可以被 dmtsai 所执行的 passwd 所修改。

 
但如果 dmtsai 使用 cat 去读取 /etc/shadow 时, 是不能读取的。 因为 cat 不具有 SUID 的权限, 所以 dmtsai 执行 “cat /etc/shadow” 时, 是不能读取 /etc/shadow 的。

SUID 仅可用在binary program 上, 不能够用在 shell script 上面! 这是因为 shellscript 只是将很多的 binary 可执行文件叫进来执行而已! 所以 SUID 的权限部分, 还是得要看shell script 调用进来的程序的设置, 而不是 shell script 本身。 当然, SUID 对于目录也是无效的

Set GID

当 s 标志在文件拥有者的 x 项目为 SUID那 s 在群组的 x 时则称为 Set GID, SGID
 
与 SUID 不同的是, SGID 可以针对文件或目录来设置
如果是对文件来说, SGID 有如下的功能:

  • SGID 对二进制程序有用
  • 程序执行者对于该程序来说, 需具备 x 的权限
  • 执行者在执行的过程中将会获得该程序群组的支持
     

如果是对目录 来说, SGID 有如下的功能:

  • 使用者若对于此目录具有 r 与 x 的权限时, 该使用者能够进入此目录;
  • 使用者在此目录下的有效群组( effective group) 将会变成该目录的群组;
  • 用途: 若使用者在此目录下具有 w 的权限( 可以新建文件) , 则使用者所创建的新文
    件, 该新文件的群组与此目录的群组相同。

Sticky Bit

这个 Sticky Bit, SBIT 目前只针对目录有效, 对于文件已经没有效果。
SBIT 对于目录的作用是:

  • 当使用者对于此目录具有 w, x 权限, 亦即具有写入的权限时;
  • 当使用者在该目录下创建文件或目录时, 仅有自己与 root 才有权力删除该文件

例子:
当甲这个使用者于 A 目录是具有群组或其他人的身份, 并且拥有该目录 w 的权限, 这表示“甲使用者对该目录内任何人创建的目录或文件均可进行 “删除/更名/搬移” 等动作。 ” 不过, 如果将 A 目录加上了 SBIT 的权限项目时, 则甲只能够针对自己创建的文件或目录进行删除/更名/移动等动作, 而无法删除他人的文件。

SUID/SGID/SBIT 权限设置

在通过数值方式设置文件或目录权限的方式上,在这三个数字之前再加上一个数字,最前面的那个数字代表的意义为:

  • 4 为 SUID
  • 2 为 SGID
  • 1 为 SBIT
     

假设要将一个文件权限改为“-rwsr-xr-x”时, 由于 s 在使用者权限中, 所以是 SUID , 因此,在原先的 755 之前还要加上 4 , 也就是: “ chmod 4755 filename ”来设置。

[root@study ~]# cd /tmp
[root@study tmp]# touch test <==创建一个测试用空档
通过数字设置特殊权限
[root@study tmp]# chmod 4755 test; ls -l test <==加入具有 SUID 的权限
-rwsr-xr-x 1 root root 0 Jun 16 02:53 test
[root@study tmp]# chmod 6755 test; ls -l test <==加入具有 SUID/SGID 的权限
-rwsr-sr-x 1 root root 0 Jun 16 02:53 test
[root@study tmp]# chmod 1755 test; ls -l test <==加入 SBIT 的功能!
-rwxr-xr-t 1 root root 0 Jun 16 02:53 test

特殊案例
[root@study tmp]# chmod 7666 test; ls -l test <==具有空的 SUID/SGID 权限
-rwSrwSrwT 1 root root 0 Jun 16 02:53 test

通过符号设置特殊权限
# 设置权限成为 -rws--x--x 的模样:
[root@study tmp]# chmod u=rwxs,go=x test; ls -l test
-rws--x--x 1 root root 0 Jun 16 02:53 test
# 承上, 加上 SGID 与 SBIT 在上述的文件权限中!
[root@study tmp]# chmod g+s,o+t test; ls -l test
-rws--s--t 1 root root 0 Jun 16 02:53 test

上面的特殊案例要特别小心:
因为 s 与 t 都是取代 x 这个权限的,但是案例中, 我们是下达 7666,也就是说, user,group 以及 others 都没有 x 这个可执行的标志,所以, 这个 S, T 代表的就是“空的”
SUID 是表示“该文件在执行的时候, 具有文件拥有者的权限”, 但是文件 拥有者都无法执行了, 哪里来的权限给其他人使用? 当然就是空的。

观察文件类型: file

如果你想要知道某个文件的基本数据, 例如是属于 ASCII 或者是 data 文件, 或者是 binary, 且其中有没有使用到动态函数库 ( share library) 等等的信息, 就可以利用 file 这个指令来检阅。

[root@study ~]# file ~/.bashrc
/root/.bashrc: ASCII text <==告诉我们是 ASCII 的纯文本文件啊!
[root@study ~]# file /usr/bin/passwd
/usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 ( SYSV) , 
dynamicallylinked ( uses shared libs) , for GNU/Linux 2.6.32,
BuildID[sha1]=0xbf35571e607e317bf107b9bcf65199988d0ed5ab, stripped
# 可执行文件的数据可就多的不得了! 包括这个文件的 suid 权限、 相容于 Intel x86-64 等级的硬件平台
# 使用的是 Linux 核心 2.6.32 的动态函数库链接等等。
[root@study ~]# file /var/lib/mlocate/mlocate.db
/var/lib/mlocate/mlocate.db: data <== 这是 data 文件!

通过这个指令, 我们可以简单的先判断这个文件的格式为何;包括你也可以用来判断使用 tar 包裹时, 该 tarball 文件是使用哪一种压缩功能。

指令与文件的搜寻

我们常常需要知道那个文件放在哪里, 才能够对该文件进行一些修改或维护等动作。
有些时候某些软件配置文件的文件名是不变的, 但是各 distribution 放置的目录则不同

指令文件名的搜寻

搜索指令对应的文件地址;

which ( 寻找“可执行文件”):

这个指令是根据“PATH”这个环境变量所规范的路径去搜寻“可执行文件”的文件名

[root@study ~]# which [-a] command
选项或参数:
-a : 将所有由 PATH 目录中可以找到的指令均列出, 而不止第一个被找到的指令名称
范例一: 搜寻 ifconfig 这个指令的完整文件名
[root@study ~]# which ifconfig
/sbin/ifconfig

范例二: 用 which 去找出 which 的文件名为何?
[root@study ~]# which which
alias which='alias &#124; /usr/bin/which --tty-only
 --read-alias --show-dot --show-tilde'
/bin/alias
/usr/bin/which
# 竟然会有两个 which , 其中一个是 alias 这玩意儿呢! 那是啥?
# 那就是所谓的“命令别名”, 意思是输入 which 会等于后面接的那串指令啦!
# 更多的数据我们会在 bash 章节中再来谈的!

范例三: 请找出 history 这个指令的完整文件名
[root@study ~]# which history
/usr/bin/which: no history in 
( /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[root@study ~]# history --help
-bash: history: --: invalid option
history: usage: history [-c] [-d offset] [n] or history -anrw [filename] 
or history -ps arg
# 瞎密? 怎么可能没有 history , 我明明就能够用 root 执行 history 的啊!

范例三中:
history 是Bash中的命令(内部命令);
which 是在PATH中查找,所以history命令没有查找到相关内容

文件文件名的搜寻

通常 find 不很常用的,因为速度慢之外, find 是直接搜寻硬盘。
一般我们都是先使用 whereis 或者是 locate 来检查, 如果真的找不到了, 才以 find 来搜寻。
因为 whereis 只找系统中某些特定目录下面的文件而已locate 则是利用数据库来搜寻文件名, 当然两者就相当的快速, 并且没有实际的搜寻硬盘内的文件系统状态, 比较省时间。

whereis ( 由一些特定的目录中寻找文件文件名):

[root@study ~]# whereis [-bmsu] 文件或目录名
选项与参数:
-l :可以列出 whereis 会去查询的几个主要目录而已
-b :只找 binary 格式的文件
-m :只找在说明文档 manual 路径下的文件
-s :只找 source 来源文件
-u :搜寻不在上述三个项目当中的其他特殊文件

范例一: 请找出 ifconfig 这个文件名
[root@study ~]# whereis ifconfig
ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

范例二: 只找出跟 passwd 有关的“说明文档”文件名( man page)
[root@study ~]# whereis passwd # 全部的文件名通通列出来!
passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
[root@study ~]# whereis -m passwd # 只有在 man 里面的文件名才抓出来!
passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

locate / updatedb:

[root@study ~]# locate [-ir] keyword
选项与参数:
-i : 忽略大小写的差异;
-c : 不输出文件名, 仅计算找到的文件数量
-l : 仅输出几行的意思, 例如输出五行则是 -l 5
-S : 输出 locate 所使用的数据库文件的相关信息, 包括该数据库纪录的文件/目录数量等
-r : 后面可接正则表达式的显示方式

范例一: 找出系统中所有与 passwd 相关的文件名, 且只列出 5 个
[root@study ~]# locate -l 5 passwd
/etc/passwd
/etc/passwd-
/etc/pam.d/passwd
/etc/security/opasswd
/usr/bin/gpasswd

范例二: 列出 locate 查询所使用的数据库文件之文件名与各数据数量
[root@study ~]# locate -S
Database /var/lib/mlocate/mlocate.db:
8,086 directories # 总纪录目录数
109,605 files # 总纪录文件数
5,190,295 Bytes in file names
2,349,150 Bytes used to store database

使用 locate 来寻找数据的时候特别的快, 这是因为 locate 寻找的数据是由“已创建的数据库 /var/lib/mlocate/” 里面的数据所
搜寻到的, 所以不用直接在去硬盘当中存取数据

但是会有限制
因为他是经由数据库来搜寻的, 而数据库的创建默认是在每天执行一次
( 每个 distribution 都不同, CentOS 7.x 是每天更新数据库一次! ) , 所以当你新创建起来的文件, 却还在数据库更新之前搜寻该文件, 那么 locate 会告诉你“找不到。
可以手动更新数据库:
更新 locate 数据库的方法非常简单, 直接输入“updatedb ”就可以了! updatedb 指令会去读取 /etc/updatedb.conf 这个配置文件的设置, 然后再去硬盘里面进行搜寻文件名的动作, 最后就更新整个数据库文件。

  • updatedb: 根据 /etc/updatedb.conf 的设置去搜寻系统硬盘内的文件名, 并更新/var/lib/mlocate 内的数据库文件
  • locate: 依据 /var/lib/mlocate 内的数据库记载, 找出使用者输入的关键字文件名

find:

[root@study ~]# find [PATH] [option] [action]
选项与参数:
1\. 与时间有关的选项: 共有 -atime, -ctime 与 -mtime , 以 -mtime 说明
-mtime n : n 为数字, 意义为在 n 天之前的“一天之内”被更动过内容的文件;
-mtime +n : 列出在 n 天之前( 不含 n 天本身) 被更动过内容的文件文件名;
-mtime -n : 列出在 n 天之内( 含 n 天本身) 被更动过内容的文件文件名。
-newer file : file 为一个存在的文件, 列出比 file 还要新的文件文件名

范例一: 将过去系统上面 24 小时内有更动过内容 ( mtime) 的文件列出
[root@study ~]# find / -mtime 0
# 那个 0 是重点! 0 代表目前的时间, 所以, 从现在开始到 24 小时前,
# 有变动过内容的文件都会被列出来! 那如果是三天前的 24 小时内?
# find / -mtime 3 有变动过的文件都被列出的意思!

范例二: 寻找 /etc 下面的文件, 如果文件日期比 /etc/passwd 新就列出
[root@study ~]# find /etc -newer /etc/passwd
# -newer 用在分辨两个文件之间的新旧关系是很有用的!

权限与指令间的关系

让使用者能进入某目录成为“可工作目录”的基本权限为何:

  • 可使用的指令: 例如 cd 等变换工作目录的指令;
  • 目录所需权限: 使用者对这个目录至少需要具有 x 的权限
  • 额外需求: 如果使用者想要在这个目录内利用 ls 查阅文件名, 则使用者对此目录还需要 r 的权限。

使用者在某个目录内读取一个文件的基本权限为何?

  • 可使用的指令: 例如本章谈到的 cat, more, less等等
  • 目录所需权限: 使用者对这个目录至少需要具有 x 权限;
  • 文件所需权限: 使用者对文件至少需要具有 r 的权限才行!

让使用者可以修改一个文件的基本权限为何?

  • 可使用的指令: 例如 nano 或未来要介绍的 vi 编辑器等;
  • 目录所需权限: 使用者在该文件所在的目录至少要有 x 权限;
  • 文件所需权限: 使用者对该文件至少要有 r, w 权限

让一个使用者可以创建一个文件的基本权限为何?

  • 目录所需权限: 使用者在该目录要具有 w,x 的权限, 重点在 w 啦!

让使用者进入某目录并执行该目录下的某个指令之基本权限为何?

  • 目录所需权限: 使用者在该目录至少要有 x 的权限;
  • 文件所需权限: 使用者在该文件至少需要有 x 的权限

Linux 磁盘与文件系统管理

Linux 文件系统

文件系统特性

磁盘分区完毕后还需要进行格式化( format) , 之后操作系统才能够使用这个文件系统。 这是因为每种操作系统所设置的文件属性/权限并不相同, 为了存放这些文件所需的数据, 因此就需要将分区进行格式化, 以成为操作系统能够利用的“文件系统格式( filesystem) ”。

传统的磁盘与文件系统之应用中, 一个分区就是只能够被格式化成为一个文件系统, 所以我们可以说一个 filesystem 就是一个 partition,但是由于新技术的利用, 例如我们常听到的LVM与软件磁盘阵列( software raid) , 这些技术可以将一个分区格式化为多个文件系统( 例如LVM) , 也能够将多个分区合成一个文件系统( LVM, RAID) ! 所以说, 目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区。

操作系统的文件数据除了文件实际内容外, 通常含有非常多的属性, 例如 Linux 操作系统的文件权限( rwx) 与文件属性( 拥有者、 群组、 时间参数等) 。 文件系统通常会将这两部份的数据分别存放在不同的区块权限与属性放置到 inode 中, 至于实际数据则放置到 data block 区块中。 另外, 还有一个超级区块 ( superblock) 会记录整个文件系统的整体信息, 包括 inode 与 block 的总量、 使用量、 剩余量等。

这三个数据的意义可以简略说明:

  • superblock: 记录此 filesystem 的整体信息, 包括inode/block的总量、 使用量、 剩余量,以及文件系统的格式与相关信息等;
  • inode: 记录文件的属性, 一个文件占用一个inode, 同时记录此文件的数据所在的 block号码;
  • block: 实际记录文件的内容, 若文件太大时, 会占用多个 block 。
     

由于每个 inode 与 block 都有编号, 而每个文件都会占用一个 inode , inode 内则有文件数据放置的 block 号码。 因此, 我们可以知道的是, 如果能够找到文件的 inode 的话那么自然就会知道这个文件所放置数据的 block 号码, 当然也就能够读出该文件的实际数据了。

Linux 的 EXT2 文件系统( inode)

Linux 文件系统 Ext2 就是使用 inode 为基础的文件系统

inode 的内容在记录文件的权限与相关属性, 至于 block 区块则是在记录文件的实际内容。 而且文件系统一开始就将 inode 与 block 规划好了, 除非重新格式化( 或者利用 resize2fs 等指令变更文件系统大小) , 否则 inode 与 block 固定后就不再变动。
 
如果我的文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定, 因为 inode 与 block 的数量太庞大, 不容易管理。
 
因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 ( blockgroup) 的, 每个区块群组都有独立的inode/block/superblock 系统。 感觉上就好像我们在当兵时, 一个营里面有分成数个连, 每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般! 这样分成一群群的比较好管理。

至于每一个区块群组( block group) 的六个主要内容说明:

data block ( 数据区块)

data block 是用来放置文件内容数据地方, 在 Ext2 文件系统中所支持的 block 大小有 1K, 2K及 4K 三种而已。 在格式化时 block 的大小就固定了, 且每个 block 都有编号, 以方便 inode的记录啦。

Ext2 文件系统的 block限制:

  • 原则上, block 的大小与数量在格式化完就不能够再改变了( 除非重新格式化) ;
  • 每个 block 内最多只能够放置一个文件的数据;
  • 承上, 如果文件大于 block 的大小, 则一个文件会占用多个 block 数量;
  • 承上, 若文件小于 block , 则该 block 的剩余容量就不能够再被使用了( 磁盘空间会浪费) 。
     

如上第四点所说, 由于每个 block 仅能容纳一个文件的数据而已, 因此如果你的文件都非常小, 但是你的 block 在格式化时却选用最大的 4K 时, 可能会产生一些容量的浪费
 

因为如果 block 较小的话, 那么大型文件将会占用数量更多的 block ,而 inode 也要记录更多的 block 号码, 此时将可能导致文件系统不良的读写性能。

inode table ( inode 表格)

inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内

基本上, inode 记录的文件数据至少有下面这些:

  • 该文件的存取模式( read/write/excute) ;
  • 该文件的拥有者与群组( owner/group) ;
  • 该文件的容量;
  • 该文件创建或状态改变的时间( ctime) ;
  • 最近一次的读取时间( atime) ;
  • 最近修改的时间( mtime) ;
  • 定义文件特性的旗标( flag) , 如 SetUID…;
  • 该文件真正内容的指向 ( pointer) ;

inode 的数量与大小也是在格式化时就已经固定了, 除此之外 inode 还有些什么特色:

  • 每个 inode 大小均固定为 128 Bytes ( 新的 ext4 与 xfs 可设置到 256 Bytes) ;
  • 每个文件都仅会占用一个 inode 而已;
  • 承上, 因此文件系统能够创建的文件数量与 inode 的数量有关;
  • 系统读取文件时需要先找到 inode, 并分析 inode 所记录的权限与使用者是否符合, 若符合才能够开始实际读取 block 的内容。

inode 要记录的数据非常多, 但偏偏又只有 128Bytes 而已, 而 inode 记录一个 block 号码要花掉 4Byte , 假设我一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万笔 block 号码的记录。inode 哪有这么多可记录的信息? 为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接, 一个间接, 一个双间接与一个三间接记录区。
在这里插入图片描述
上图最左边为 inode 本身 ( 128 Bytes) , 里面有 12 个直接指向 block 号码的对照, 这 12笔记录就能够直接取得 block 号码啦! 至于所谓的间接就是再拿一个 block 来当作记录 block号码的记录区, 如果文件太大时, 就会使用间接的 block 来记录号码

如果你的 Linux 依旧使用 Ext2/Ext3/Ext4 文件系统的话, 例如鸟哥之前的 CentOS 6.x系统, 那么默认还是使用 Ext4 的文件系统喔! Ext4 文件系统的 inode 容量已经可以扩大到256Bytes 了, 更大的 inode 容量, 可以纪录更多的文件系统信息, 包括新的 ACL 以及SELinux 类型等, 当然, 可以纪录的单一文件大小达 16TB 且单一文件系统总容量可达 1EB。

Superblock ( 超级区块)

Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock , 就没有这个filesystem 了。
他记录的信息主要有:

  • block 与 inode 的总量;
  • 未使用与已使用的 inode / block 数量;
  • block 与 inode 的大小 ( block 为 1, 2, 4K, inode 为 128Bytes 或 256Bytes) ;
  • filesystem 的挂载时间、 最近一次写入数据的时间、 最近一次检验磁盘 ( fsck) 的时间等文件系统的相关信息;
  • 一个 valid bit 数值, 若此文件系统已被挂载, 则 valid bit 为 0 , 若未被挂载, 则 valid bit为 1 。

一般来说,superblock 的大小为 1024Bytes。 相关的 superblock 讯息我们等一下会以 dumpe2fs 指令来调用出来观察。

每个 block group 都可能含有 superblock ! 但是我们也说一个文件系统应该仅有一个 superblock 而已, 那是怎么回事啊? 事实上除了第一个 block group 内会含有 superblock之外, 后续的 block group 不一定含有 superblock , 而若含有 superblock 则该 superblock主要是做为第一个 block group 内 superblock 的备份, 这样可以进行 superblock 的救援呢!

Filesystem Description ( 文件系统描述说明)

这个区段可以描述每个 block group 的开始与结束的 block 号码, 以及说明每个区段( superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间。 这部份也能够用 dumpe2fs 来观察的。

block bitmap ( 区块对照表)

block bitmap 当中可以知道哪些 block 是空的, 因此我们的系统就能够很快速的找到可使用的空间来处置文件。
 
如果你删除某些文件时, 那么那些文件原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为“未使用中”。

inode bitmap ( inode 对照表)

这个其实与 block bitmap 是类似的功能, 只是 block bitmap 记录的是使用与未使用的 block号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码。

查询 Ext 家族 superblock 信息的指令dumpe2fs

每个区段与 superblock 的信息都可以使用 dumpe2fs 这个指令来查询的!不过, CentOS 7 现在是以 xfs 为默认文件系统无法使用 dumpe2fs 去查询任何文件系统的

[root@study ~]# dumpe2fs [-bh] 设备文件名
选项与参数:
-b : 列出保留为坏轨的部分( 一般用不到吧! ? )
-h : 仅列出 superblock 的数据, 不会列出其他的区段内容!

范例: 鸟哥的一块 1GB ext4 文件系统内容
[root@study ~]# blkid <==这个指令可以叫出目前系统有被格式化的设备
/dev/vda1: LABEL="myboot" UUID="ce4dbf1b-2b3d-4973-8234-73768e8fd659" TYPE="xfs"
/dev/vda2: LABEL="myroot" UUID="21ad8b9a-aaad-443c-b732-4e2522e95e23" TYPE="xfs"
/dev/vda3: UUID="12y99K-bv2A-y7RY-jhEW-rIWf-PcH5-SaiApN" TYPE="LVM2_member"
/dev/vda5: UUID="e20d65d9-20d4-472f-9f91-cdcfb30219d6" TYPE="ext4" <==看到 ext4 了!
[root@study ~]# dumpe2fs /dev/vda5
dumpe2fs 1.42.9 ( 28-Dec-2013)
Filesystem volume name: &lt;none&gt; # 文件系统的名称( 不一定会有)
Last mounted on: &lt;not available&gt; # 上一次挂载的目录位置
Filesystem UUID: e20d65d9-20d4-472f-9f91-cdcfb30219d6
Filesystem magic number: 0xEF53 # 上方的 UUID 为 Linux 对设备的定义码
Filesystem revision #: 1 ( dynamic) # 下方的 features 为文件系统的特征数据
Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit
flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl # 默认在挂载时会主动加上的挂载参数
Filesystem state: clean # 这块文件系统的状态为何, clean 是没问题
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 65536 # inode 的总数
Block count: 262144 # block 的总数
Reserved block count: 13107 # 保留的 block 总数
Free blocks: 249189 # 还有多少的 block 可用数量
Free inodes: 65525 # 还有多少的 inode 可用数量
First block: 0
Block size: 4096 # 单个 block 的容量大小
Fragment size: 4096
Group descriptor size: 64
....( 中间省略) ....
Inode size: 256 # inode 的容量大小! 已经是 256 了喔!
....( 中间省略) ....
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3c2568b4-1a7e-44cf-95a2-c8867fb19fbc
Journal backup: inode blocks
Journal features: ( none)
Journal size: 32M # Journal 日志式数据的可供纪录总容量
Journal length: 8192
Journal sequence: 0x00000001
Journal start: 0
Group 0: ( Blocks 0-32767) # 第一块 block group 位置
Checksum 0x13be, unused inodes 8181
Primary superblock at 0, Group descriptors at 1-1 # 主要 superblock 的所在喔!
Reserved GDT blocks at 2-128
Block bitmap at 129 ( +129) , Inode bitmap at 145 ( +145)
Inode table at 161-672 ( +161) # inode table 的所在喔!
28521 free blocks, 8181 free inodes, 2 directories, 8181 unused inodes
Free blocks: 142-144, 153-160, 4258-32767 # 下面两行说明剩余的容量有多少
Free inodes: 12-8192
Group 1: ( Blocks 32768-65535) [INODE_UNINIT] # 后续为更多其他的 block group 喔!
....( 下面省略) ....
# 由于数据量非常的庞大, 因此鸟哥将一些信息省略输出了! 上表与你的屏幕会有点差异。
# 前半部在秀出 supberblock 的内容, 包括标头名称( Label) 以及inode/block的相关信息
# 后面则是每个 block group 的个别信息了! 您可以看到各区段数据所在的号码!
# 也就是说, 基本上所有的数据还是与 block 的号码有关就是了! 很重要!

利用 dumpe2fs 可以查询到非常多的信息, 不过依内容主要可以区分为上半部是superblock 内容下半部则是每个 block group 的信息

文件系统与目录树的关系

目录:

当我们在 Linux 下的文件系统创建一个目录时, 文件系统会分配一个 inode 与至少一块 block给该目录。 其中, inode 记录该目录的相关权限与属性, 并可记录分配到的那块 block 号码而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据。 也就是说目录所占用的 block 内容在记录如下的信息:在这里插入图片描述
例子:
如果想要实际观察 root 主文件夹内的文件所占用的 inode 号码时, 可以使用 ls -i 这个选项来处理:

[root@study ~]# ls -li
total 8
53735697 -rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg
53745858 -rw-r--r--. 1 root root 1864 May 4 18:01 initial-setup-ks.cfg`

目录并不只会占用一个 block 而已, 也就是说: 在目录下面的文件数如果太多而导致一个 block 无法容纳的下所有的文件名与 inode 对照表时, Linux 会给予该目录多一个 block 来继续记录相关的数据

文件:

当我们在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小的 block 数量给该文件。
 
例如: 假设我的一个 block 为 4 KBytes , 而我要创建一个 100KBytes 的文件, 那么 linux 将分配一个 inode 与 25 个 block 来储存该文件! 但同时请注意,由于 inode 仅有 12 个直接指向, 因此还要多一个 block 来作为区块号码的记录.

目录树读取:

inode 本身并不记录文件名, 文件名的记录是在目录的 block 当中
 
因为文件名是记录在目录的 block 当中, 因此当我们要读取某个文件时, 就务必会经过目录的 inode 与 block , 然后才能够找到那个待读取文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据。
 
由于目录树是由根目录开始读起, 因此系统通过挂载的信息可以找到挂载点的 inode 号码,此时就能够得到根目录的 inode 内容, 并依据该 inode 读取根目录的 block 内的文件名数据,再一层一层的往下读到正确的文件名。
 

举例来说, 如果我想要读取 /etc/passwd 这个文件时,系统是如何读取的呢?

[root@study ~]# ll -di / /etc /etc/passwd
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
33595521 drwxr-xr-x. 131 root root 8192 Jun 17 00:20 /etc
36628004 -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd

该文件的读取流程为( 假设读取者身份为 dmtsai 这个一般身份使用者) :

  1. . / 的 inode: 通过挂载点的信息找到 inode 号码为 128 的根目录 inode, 且 inode 规范的
    权限让我们可以读取该 block 的内容( 有 r 与 x) ;
  2. . / 的 block: 经过上个步骤取得 block 的号码, 并找到该内容有 etc/ 目录的 inode 号码( 33595521) ;
  3. . etc/ 的 inode: 读取 33595521 号 inode 得知 dmtsai 具有 r 与 x 的权限, 因此可以读取etc/ 的 block 内容;
  4. . etc/ 的 block: 经过上个步骤取得 block 号码, 并找到该内容有 passwd 文件的 inode 号码 ( 36628004) ;
  5. . passwd 的 inode: 读取 36628004 号 inode 得知 dmtsai 具有 r 的权限, 因此可以读取passwd 的 block 内容;
  6. . passwd 的 block: 最后将该 block 内容的数据读出来。

filesystem 大小与磁盘读取性能:

关于文件系统的使用效率上, 当你的一个文件系统规划的很大时, 例如 100GB 这么大时, 由于磁盘上面的数据总是来来去去的, 所以, 整个文件系统上面的文件通常无法连续写在一起( block 号码不会连续的意思) , 而是填入式的将数据填入没有被使用的 block 当中。如果文件写入的 block 真的分的很散, 此时就会有所谓的文件数据离散的问题发生了。
 
我们的 ext2 在 inode 处已经将该文件所记录的 block 号码都记上了, 所以数据可以一次性读取, 但是如果文件真的太过离散, 确实还是会发生读取效率低落的问题。 因为磁头还是得要在整个文件系统中来来去去的频繁读取! 果真如此, 那么可以将整个filesystme 内的数据全部复制出来, 将该 filesystem 重新格式化, 再将数据给他复制回去即可解决这个问题。

EXT2/EXT3/EXT4 文件的存取与日志式文件系统的功能

如果是新建一个文件或目录时, 这个时候就得要 block bitmap 及 inode bitmap 的帮忙了! 假设我们想要新增一个文件, 此时文件系统的行为是:

  1. 先确定使用者对于欲新增文件的目录是否具有 w 与 x 的权限, 若有的话才能新增;
  2. 根据 inode bitmap 找到没有使用的 inode 号码, 并将新文件的权限/属性写入;
  3. 根据 block bitmap 找到没有使用中的 block 号码, 并将实际的数据写入 block 中, 且更新 inode 的 block 指向数据;
  4. 将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap, 并更新superblock 的内容。

一般来说, 我们将 inode table 与 data block 称为数据存放区域, 至于其他例如 superblock、block bitmap 与inode bitmap 等区段就被称为 metadata ( 中介数据)因为 superblock,inode bitmap 及 block bitmap 的数据是经常变动的, 每次新增、 移除、 编辑时都可能会影响到这三个部分的数据, 因此才被称为中介数据。

数据的不一致 ( Inconsistent) 状态

在一般正常的情况下, 上述的新增动作当然可以顺利的完成。 但是如果有个万一怎么办? 例如你的文件在写入文件系统时, 因为不知名原因导致系统中断( 例如突然的停电啊、 系统核心发生错误啊~等等的怪事发生时) , 所以写入的数据仅有 inode table 及 data block 而已,最后一个同步更新中介数据的步骤并没有做完, 此时就会发生 metadata 的内容与实际数据存放区产生不一致 ( Inconsistent) 的情况了。
 
在早期的 Ext2 文件系统中, 如果发生这个问题, 那么系统在重新开机的时候, 就会借由 Superblock 当中记录的 valid bit ( 是否有挂载) 与 filesystemstate ( clean 与否) 等状态来判断是否强制进行数据一致性的检查! 若有需要检查时则以e2fsck 这支程序来进行的。
 
不过, 这样的检查真的是很费时~因为要针对 metadata 区域与实际数据存放区来进行比对,得要搜寻整个 filesystem ;这也就造成后来所谓日志式文件系统的兴起。

日志式文件系统 ( Journaling filesystem)

为了避免上述提到的文件系统不一致的情况发生, 因此我们的前辈们想到一个方式, 如果在我们的 filesystem 当中规划出一个区块, 该区块专门在记录写入或修订文件时的步骤, 那不就可以简化一致性检查的步骤。

  1. 预备: 当系统要写入一个文件时, 会先在日志记录区块中纪录某个文件准备要写入的信息;
  2. 实际写入: 开始写入文件的权限与数据; 开始更新 metadata 的数据;
  3. 结束: 完成数据与 metadata 的更新后, 在日志记录区块当中完成该文件的纪录。
     

在这样的程序当中, 万一数据的纪录过程当中发生了问题, 那么我们的系统只要去检查日志记录区块, 就可以知道哪个文件发生了问题, 针对该问题来做一致性的检查即可, 而不必针对整块 filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了! 这就是日志式文件最基础的功能。

dumpe2fs 输出的讯息, 可以发现 superblock 里面含有下面这样的信息:

Journal inode: 8
Journal backup: inode blocks
Journal features: ( none)
Journal size: 32M
Journal length: 8192
Journal sequence: 0x00000001

通过 inode 8 号记录 journal 区块的 block 指向, 而且具有 32MB 的容量在处理日志。

Linux 文件系统的运行

如果你常常编辑一个好大的文件, 在编辑的过程中又频繁的要系统来写入到磁盘中, 由于磁盘写入的速度要比内存慢很多, 因此你会常常耗在等待磁盘的写入/读取上
 
为了解决这个效率的问题, 因此我们的 Linux 使用的方式是通过一个称为非同步处理( asynchronously) 的方式。 所谓的非同步处理是这样的:
 
当系统载入一个文件到内存后, 如果该文件没有被更动过, 则在内存区段的文件数据会被设置为干净( clean) 的。 但如果内存中的文件数据被更改过了( 例如你用 nano 去编辑过这个文件) , 此时该内存中的数据会被设置为脏的 ( Dirty) 。 此时所有的动作都还在内存中执行, 并没有写入到磁盘中! 系统会不定时的将内存中设置为“Dirty”的数据写回磁盘, 以保持磁盘与内存数据的一致性。 你也可以利用sync指令来手动强迫写入磁盘
 
我们知道内存的速度要比磁盘快的多, 因此如果能够将常用的文件放置到内存当中, 这不就会增加系统性能吗? 没错! 是有这样的想法! 因此我们 Linux 系统上面文件系统与内存有非常大的关系:

  • 系统会将常用的文件数据放置到内存的缓冲区, 以加速文件系统的读/写;
  • 承上, 因此 Linux 的实体内存最后都会被用光! 这是正常的情况! 可加速系统性能;
  • 你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;
  • 若正常关机时, 关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
  • 但若不正常关机( 如跳电、 死机或其他不明原因) , 由于数据尚未回写到磁盘内, 因此重新开机后可能会花很多时间在进行磁盘检验, 甚至可能导致文件系统的损毁( 非磁盘损毁) 。

挂载点的意义 ( mount point):

每个 filesystem 都有独立的 inode / block / superblock 等信息, 这个文件系统要能够链接到目录树才能被我们使用。 将文件系统与目录树结合的动作我们称为“挂载”。
 
挂载点一定是目录, 该目录为进入该文件系统的入口。因此并不是你有任何文件系统都能使用, 必须要“挂载”到目录树的某个目录后, 才能够使用该文件系统的。

例子:

[root@study ~]# ls -lid / /boot /home
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
128 dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot
128 drwxr-xr-x. 5 root root 41 Jun 17 00:20 /home

由于 XFS filesystem 最顶层的目录之 inode 一般为 128 号因此可以发现 /,/boot, /home 为三个不同的 filesystem
 
使用文件系统的观点来看, 同一个 filesystem 的某个 inode 只会对应到一个文件内容而已( 因为一个文件占用一个 inode 之故) , 因此我们可以通过判断 inode 号码来确认不同文件名是否为相同的文件

[root@study ~]# ls -ild / /. /..
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /.
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /..

上面的信息中由于挂载点均为 / , 因此三个文件 ( /, /., /…) 均在同一个 filesystem 内, 而这三个文件的 inode 号码均为 128 号, 因此这三个文件名都指向同一个 inode 号码, 当然这三个文件的内容也就完全一模一样。

其他 Linux 支持的文件系统与 VFS

虽然 Linux 的标准文件系统是 ext2 , 且还有增加了日志功能的 ext3/ext4 , 事实上, Linux 还有支持很多文件系统格式的, 尤其是最近这几年推出了好几种速度很快的日志式文件系统,包括 SGI 的 XFS 文件系统, 可以适用更小型文件的 Reiserfs 文件系统, 以及 Windows 的FAT 文件系统等等, 都能够被 Linux 所支持! 常见的支持文件系统有:

  • 传统文件系统: ext2 / minix / MS-DOS / FAT ( 用 vfat 模块) / iso9660 ( 光盘) 等等;
  • 日志式文件系统: ext3 /ext4 / ReiserFS / Windows’ NTFS / IBM’s JFS / SGI’s XFS /ZFS
  • 网络文件系统: NFS / SMBFS

想要知道你的 Linux 支持的文件系统有哪些, 可以察看下面这个目录:

[root@study ~]# ls -l /lib/modules/$( uname -r) /kernel/fs

系统目前已载入到内存中支持的文件系统则有:

[root@study ~]# cat /proc/filesystems

Linux VFS ( Virtual Filesystem Switch):

了解了我们使用的文件系统之后, 再来则是要提到, 那么 Linux 的核心又是如何管理这些认识的文件系统呢?
其实, 整个 Linux 的系统都是通过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的
也就是说, 整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理, 我们使用者并不需要知道每个 partition 上头的 filesystem 是什么VFS 会主动的帮我们做好读取的动作
 
假设你的 / 使用的是 /dev/hda1 , 用 ext3 , 而 /home 使用 /dev/hda2 , 用 reiserfs , 那么你取用 /home/dmtsai/.bashrc 时, 有特别指定要用的什么文件系统的模块来读取吗? 应该是没有吧! 这个就是 VFS 的功能啦! 通过这个 VFS 的功能来管理所有的 filesystem, 省去我们需要自行设置读取文件系统的定义。

整个 VFS 可以约略用下图来说明:
在这里插入图片描述

XFS 文件系统简介

CentOS 7 开始, 默认的文件系统已经由原本的 EXT4 变成了 XFS 文件系统;
更换XFS系统的原因:
 
EXT 家族当前较伤脑筋的地方: 支持度最广, 但格式化超慢!

Ext 文件系统家族对于文件格式化的处理方面, 采用的是预先规划出所有的 inode/block/metadata 等数据, 未来系统可以直接取用, 不需要再进行动态配置的作法。 这个作法在早期磁盘容量还不大的时候还算 OK 没啥问题, 但时至今日, 磁盘容量越来越大, 连传统的 MBR 都已经被 GPT 所取代,! 现在都已经说到 PB 或 EB 以上容量了呢! 那你可以想像得到, 当你的 TB 以上等级的传统 ext 家族文件系统在格式化的时候, 光是系统要预先分配 inode 与 block 就消耗你好多好多的时间。

虚拟化的应用越来越广泛

作为虚拟化磁盘来源的巨型文件 ( 单一文件好几个GB 以上! ) 也就越来越常见了。 这种巨型文件在处理上需要考虑到性能问题, 否则虚拟磁盘的效率就会不太好看

因此, 从 CentOS 7.x 开始, 文件系统已经由默认的 Ext4 变成了xfs 这一个较适合大容量磁盘与巨型文件性能较佳的文件系统。

XFS 文件系统的配置:

基本上 xfs 就是一个日志式文件系统, 而 CentOS 7.x 拿它当默认的文件系统, 自然就是因为最早之前, 这个 xfs 就是被开发来用于大容量磁盘以及高性能文件系统之用, 因此, 相当适合现在的系统环境。
此外, 几乎所有 Ext4 文件系统有的功能, xfs 都可以具备。
 
xfs 文件系统在数据的分佈上, 主要规划为三个部份
一个数据区 ( data section)
一个文件系统活动登录区 ( log section)
一个实时运行区 ( realtime section)
这三个区域的数据内容如下:

数据区 ( data section)

基本上, 数据区就跟我们之前谈到的 ext 家族一样, 包括 inode/data block/superblock 等数据都放置在这个区块这个数据区与 ext 家族的 block group 类似, 也是分为多个储存区群组 ( allocation groups) 来分别放置文件系统所需要的数据。 每个储存区群组都包含了:
( 1) 整个文件系统的 superblock
( 2) 剩余空间的管理机制
( 3) inode的分配与追踪。
此外, inode与 block 都是系统需要用到时, 这才动态配置产生, 所以格式化动作超级快
 
与 ext 家族不同的是, xfs 的 block 与 inode 有多种不同的容量可供设置, block 容量可由 512Bytes ~ 64K 调配, 不过, Linux 的环境下, 由于内存控制的关系 ( 分页档pagesize 的容量之故) , 因此最高可以使用的 block 大小为 4K 而已。 至于 inode 容量可由 256Bytes 到 2M 这么大。
 
注意:
xfs 的这个数据区的储存区群组 ( allocation groups, AG) , 你就将它想成是 ext家族的 block 群组 ( block groups) 就对了! 本小节之前讲的都可以在这个区块内使用。 只是 inode 与 block 是动态产生, 并非一开始于格式化就完成配置的。

文件系统活动登录区 ( log section)

在登录区这个区域主要被用来纪录文件系统的变化, 其实有点像是日志区文件的变化会在这里纪录下来, 直到该变化完整的写入到数据区后, 该笔纪录才会被终结。 如果文件系统因为某些缘故 ( 例如最常见的停电) 而损毁时, 系统会拿这个登录区块来进行检验, 看看系统挂掉之前, 文件系统正在运行些啥动作, 借以快速的修复文件系统。
 
因为系统所有动作的时候都会在这个区块做个纪录, 因此这个区块的磁盘活动是相当频繁的。
在这个区域中, 你可以指定外部的磁盘来作为 xfs 文件系统的日志区块! 例如, 你可以将 SSD 磁盘作为 xfs 的登录区, 这样当系统需要进行任何活动时, 就可以更快速的进行工作。

实时运行区 ( realtime section)

当有文件要被创建时, xfs 会在这个区段里面找一个到数个的 extent 区块, 将文件放置在这个区块内, 等到分配完毕后, 再写入到 data section 的 inode 与 block 去这个 extent 区块的大小得要在格式化的时候就先指定, 最小值是 4K 最大可到 1G。 一般非磁盘阵列的磁盘默认为 64K 容量, 而具有类似磁盘阵列的 stripe 情况下, 则建议 extent 设置为与 stripe 一样大较佳。 这个 extent 最好不要乱动, 因为可能会影响到实体磁盘的性能喔。

XFS 文件系统的描述数据观察:

对于XFS系统的观察使用 xfs_info ;
对于EXT系统的观察使用 dumpe2fs ;

[root@study ~]# xfs_info 挂载点&#124;设备文件名
范例一: 找出系统 /boot 这个挂载点下面的文件系统的 superblock 纪录
[root@study ~]# df -T /boot
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/vda2 xfs 1038336 133704 904632 13% /boot
# 没错! 可以看得出来是 xfs 文件系统的! 来观察一下内容吧!
[root@study ~]# xfs_info /dev/vda2
1 meta-data=/dev/vda2 isize=256 agcount=4, agsize=65536 blks
2 = sectsz=512 attr=2, projid32bit=1
3 = crc=0 finobt=0
4 data = bsize=4096 blocks=262144, imaxpct=25
5 = sunit=0 swidth=0 blks
6 naming =version 2 bsize=4096 ascii-ci=0 ftype=0
7 log =internal bsize=4096 blocks=2560, version=2
8 = sectsz=512 sunit=0 blks, lazy-count=1
9 realtime =none extsz=4096 blocks=0, rtextents=0

上面的输出讯息可以这样解释:

  • 第 1 行里面的 isize 指的是 inode 的容量, 每个有 256Bytes 这么大。 至于 agcount 则是前面谈到的储存区群组 ( allocation group) 的个数, 共有 4 个, agsize 则是指每个储存区群组具有 65536 个 block 。 配合第 4 行的 block 设置为 4K, 因此整个文件系统的容量应该就是 4655364K 这么大!
  • 第 2 行里面 sectsz 指的是逻辑扇区 ( sector) 的容量设置为 512Bytes 这么大的意思。
  • 第 4 行里面的 bsize 指的是 block 的容量, 每个 block 为 4K 的意思, 共有 262144 个block 在这个文件系统内。
  • 第 5 行里面的 sunit 与 swidth 与磁盘阵列的 stripe 相关性较高。 这部份我们下面格式化的时候会举一个例子来说明。
  • 第 7 行里面的 internal 指的是这个登录区的位置在文件系统内, 而不是外部设备的意思。 且占用了 4K * 2560 个 block, 总共约 10M 的容量。
  • 第 9 行里面的 realtime 区域, 里面的 extent 容量为 4K。 不过目前没有使用。

文件系统的简单操作

磁盘与目录的容量

磁盘的整体数据是在 superblock 区块中, 但是每个各别文件的容量则在 inode当中记载的

  • df: 列出文件系统的整体磁盘使用量(针对整个文件系统或者分区)
  • du: 评估文件系统的磁盘使用量( 常用在推估目录所占容量)

df

[root@study ~]# df [-ahikHTm] [目录或文件名]
选项与参数:
-a : 列出所有的文件系统, 包括系统特有的 /proc 等文件系统;
-k : 以 KBytes 的容量显示各文件系统;
-m : 以 MBytes 的容量显示各文件系统;
-h : 以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H : 以 M=1000K 取代 M=1024K 的进位方式;
-T : 连同该 partition 的 filesystem 名称 ( 例如 xfs) 也列出;
-i : 不用磁盘容量, 而以 inode 的数量来显示

范例一: 将系统内所有的 filesystem 列出来!
[root@study ~]# df
[root@study ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
/dev/mapper/centos-root  10475520 3409408   7066112  33% /
devtmpfs                   627700       0    627700   0% /dev
tmpfs                      637568      80    637488   1% /dev/shm
tmpfs                      637568   24684    612884   4% /run
tmpfs                      637568       0    637568   0% /sys/fs/cgroup
/dev/mapper/centos-home   5232640   67720   5164920   2% /home
/dev/vda2                 1038336  133704    904632  13% /boot
# 在 Linux 底下如果 df 沒有加任何選項,那麼預設會將系統內所有的 
# 在 Linux 下面如果 df 没有加任何选项, 那么默认会将系统内所有的
# ( 不含特殊内存内的文件系统与 swap) 都以 1 KBytes 的容量来列出来!
# 至于那个 /dev/shm 是与内存有关的挂载, 先不要理他!

先来说明一下范例一所输出的结果讯息为:

  • Filesystem: 代表该文件系统是在哪个 partition , 所以列出设备名称;
  • 1k-blocks: 说明下面的数字单位是 1KB ! 可利用 -h 或 -m 来改变容量;
  • Used: 顾名思义, 就是使用掉的磁盘空间啦!
  • Available: 也就是剩下的磁盘空间大小;
  • Use%: 就是磁盘的使用率啦! 如果使用率高达 90% 以上时, 最好需要注意一下了, 免得容量不足造成系统问题! ( 例如最容易被灌爆的 /var/spool/mail 这个放置邮件的磁盘)
  • Mounted on: 就是磁盘挂载的目录所在
范例二: 将容量结果以易读的容量格式显示出来
[root@study ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   10G  3.3G  6.8G  33% /
devtmpfs                 613M     0  613M   0% /dev
tmpfs                    623M   80K  623M   1% /dev/shm
tmpfs                    623M   25M  599M   4% /run
tmpfs                    623M     0  623M   0% /sys/fs/cgroup
/dev/mapper/centos-home  5.0G   67M  5.0G   2% /home
/dev/vda2               1014M  131M  884M  13% /boot
# 不同于范例一, 这里会以 G/M 等容量格式显示出来, 比较容易看啦!
范例三: 将系统内的所有特殊文件格式及名称都列出来
[root@study ~]# df -aT
Filesystem              Type        1K-blocks    Used Available Use% Mounted on
rootfs                  rootfs       10475520 3409368   7066152  33% /
proc                    proc                0       0         0    - /proc
sysfs                   sysfs               0       0         0    - /sys
devtmpfs                devtmpfs       627700       0    627700   0% /dev
securityfs              securityfs          0       0         0    - /sys/kernel/security
tmpfs                   tmpfs          637568      80    637488   1% /dev/shm
devpts                  devpts              0       0         0    - /dev/pts
tmpfs                   tmpfs          637568   24684    612884   4% /run
tmpfs                   tmpfs          637568       0    637568   0% /sys/fs/cgroup
.....(中間省略).....
/dev/mapper/centos-root xfs          10475520 3409368   7066152  33% /
selinuxfs               selinuxfs           0       0         0    - /sys/fs/selinux
.....(中間省略).....
/dev/mapper/centos-home xfs           5232640   67720   5164920   2% /home
/dev/vda2               xfs           1038336  133704    904632  13% /boot
binfmt_misc             binfmt_misc         0       0         0    - /proc/sys/fs/binfmt_misc
# 系统里面其实还有很多特殊的文件系统存在的。 那些比较特殊的文件系统几乎
# 都是在内存当中, 例如 /proc 这个挂载点。 因此, 这些特殊的文件系统
# 都不会占据磁盘空间喔! ^_^
范例四: 将 /etc 下面的可用的磁盘容量以易读的容量格式显示
[root@study ~]# df -h /etc
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   10G  3.3G  6.8G  33% /
# 这个范例比较有趣一点啦, 在 df 后面加上目录或者是文件时, df
# 会自动的分析该目录或文件所在的 partition , 并将该 partition 的容量显示出来,
# 所以, 您就可以知道某个目录下面还有多少容量可以使用了! ^_^
范例五: 将目前各个 partition 当中可用的 inode 数量列出
[root@study ~]# df -ih
Filesystem              Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root    10M  108K  9.9M    2% /
devtmpfs                  154K   397  153K    1% /dev
tmpfs                     156K     5  156K    1% /dev/shm
tmpfs                     156K   497  156K    1% /run
tmpfs                     156K    13  156K    1% /sys/fs/cgroup
# 这个范例则主要列出可用的 inode 剩余量与总容量。 分析一下与范例一的关系,
# 你可以清楚的发现到, 通常 inode 的数量剩余都比 block 还要多呢

df 主要读取的数据几乎都是针对一整个文件系统因此读取的范围主要是在 Superblock内的信息所以这个指令显示结果的速度非常的快速。 在显示的结果中你需要特别留意的是那个根目录的剩余容量! 因为我们所有的数据都是由根目录衍生出来的, 因此当根目录的剩余容量剩下 0 时, 那你的 Linux 可能就问题很大了。

du

[root@study ~]# du [-ahskm] 文件或目录名称
选项与参数:
-a : 列出所有的文件与目录容量, 因为默认仅统计目录下面的文件量而已。
-h : 以人们较易读的容量格式 ( G/M) 显示;
-s : 列出总量而已, 而不列出每个各别的目录占用容量;
-S : 不包括子目录下的总计, 与 -s 有点差别。
-k : 以 KBytes 列出容量显示;
-m : 以 MBytes 列出容量显示;
范例一: 列出目前目录下的所有文件大小
[root@study ~]# du
4       ./.cache/dconf  <==每个目录都会列出来
4       ./.cache/abrt
8       ./.cache
....(中間省略)....
0       ./test4
4       ./.ssh          <==包括隐藏文件的目录
76      .               <==这个目录( .) 所占用的总量
# 直接输入 du 没有加任何选项时, 则 du 会分析“目前所在目录”
# 的文件与目录所占用的磁盘空间。 但是, 实际显示时, 仅会显示目录容量( 不含文件) ,
# 因此 . 目录有很多文件没有被列出来, 所以全部的目录相加不会等于 . 的容量喔!
# 此外, 输出的数值数据为 1K 大小的容量单位。
范例二: 同范例一, 但是将文件的容量也列出来
[root@study ~]# du -a
4       ./.bash_logout         <==有文件的列表了
4       ./.bash_profile
4       ./.bashrc
....(中間省略)....
4       ./.ssh/known_hosts
4       ./.ssh
76      .
范例三: 检查根目录下面每个目录所占用的容量
[root@study ~]# du -sm /*
0       /bin
99      /boot
....(中間省略)....
du: cannot access ‘/proc/17772/task/17772/fd/4’: No such file or directory
du: cannot access ‘/proc/17772/fdinfo/4’: No such file or directory
0       /proc      <==不会占用硬盘空间!
1       /root
25      /run
....(中間省略)....
3126    /usr       <==系统初期最大就是他了啦!
117     /var
# 这是个很常被使用的功能~利用万用字符 * 来代表每个目录, 如果想要检查某个目录下,
# 哪个次目录占用最大的容量, 可以用这个方法找出来。 值得注意的是, 如果刚刚安装好 Linux 时,
# 那么整个系统容量最大的应该是 /usr 。 而 /proc 虽然有列出容量, 但是那个容量是在内存中,
# 不占磁盘空间。 至于 /proc 里头会列出一堆“No such file or directory” 的错误,
# 别担心! 因为是内存内的程序, 程序执行结束就会消失, 因此会有些目录找不到, 是正确的!

与 df 不一样的是, du 这个指令其实会直接到文件系统内去搜寻所有的文件数据, 所以上述第三个范例指令的运行会执行一小段时间
 
如果你只想要知道该目录占了多少容量的话, 使用 -s 就可以;
至于 -S 这个选项部分, 由于 du 默认会将所有文件的大小均列出, 因此假设你在 /etc 下面使用 du 时, 所有的文件大小, 包括 /etc 下面的次目录容量也会被计算一次然后最终的容量( /etc) 也会加总一次, 因此很多朋友都会误会 du 分析的结果不太对劲。 如果想要列出某目录下的全部数据, 或许也可以加上 -S 的选项, 减少次目录的计算。
 
-s:计算该当前目录文件以及子目录总量
-S:计算该当前目录文件总量

实体链接与符号链接: ln

Linux 下面的链接文件有两种:
一种是类似 Windows 的捷径功能的文件, 可以让你快速的链接到目标文件( 或目录)
另一种则是通过文件系统的 inode 链接来产生新文件名, 而不是产生新文件。这种称为实体链接 ( hard link) 。

Hard Link ( 实体链接, 硬式链接或实际链接)

在前一小节当中, 我们知道几件重要的信息, 包括:

  • 每个文件都会占用一个 inode , 文件内容由 inode 的记录来指向;
  • 想要读取该文件, 必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。
     

也就是说, 其实文件名只与目录有关, 但是文件内容则与 inode 有关
hard link 只是在某个目录下新增一笔文件名链接到某 inode 号码的关连记录而已。

举个例子来说, 假设我系统有个 /root/crontab 他是 /etc/crontab 的实体链接, 也就是说这两个文件名链接到同一个 inode , 自然这两个文件名的所有相关信息都会一模一样( 除了文件名之外) 。 实际的情况可以如下所示:

[root@study ~]# ll -i /etc/crontab
34474855 -rw-r--r--. 1 root root 451 Jun 10 2014 /etc/crontab
[root@study ~]# ln /etc/crontab . <==创建实体链接的指令
[root@study ~]# ll -i /etc/crontab crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab

你可以发现两个文件名都链接到 34474855 这个 inode 号码, 所以您瞧瞧, 是否文件的权限/属性完全一样呢?
因为这两个“文件名”其实是一模一样的“文件”啦! 而且你也会发现第二个字段由原本的 1 变成 2 了!
那个字段称为“链接”, 这个字段的意义为: “有多少个文件名链接到这个 inode 号码”的意思”。
如果将读取到正确数据的方式画成示意图, 就类似如下画面:
在这里插入图片描述
最大的好处就是“安全”! 如同上图中, 如果你将任何一个“文件名”删除, 其实 inode 与 block都还是存在的! 此时你可以通过另一个“文件名”来读取到正确的文件数据喔! 此外, 不论你使用哪个“文件名”来编辑, 最终的结果都会写入到相同的 inode 与 block 中, 因此均能进行数据的修改。
一般来说使用 hard link 设置链接文件时, 磁盘的空间与 inode 的数目都不会改变! 由图中可以知道, hard link 只是在某个目录下的 block 多写入一个关连数据而已, 既不会增加 inode 也不会耗用 block 数量

事实上 hard link 应该仅能在单一文件系统中进行的, 应该是不能够跨文件系统才对 ! 所以hard link 是有限制的:

  • 不能跨 Filesystem
  • 不能 link 目录
     

hard link 链接到目录时, 链接的数据需要连同被链接目录下面的所有数据都创建链接, 举例来说, 如果你要将 /etc 使用实体链接创建一个 /etc_hd 的目录时, 那么在 /etc_hd 下面的所有文件名同时都与 /etc 下面的文件名要创建 hard link 的, 而不是仅链接到 /etc_hd 与 /etc 而已。 并且, 未来如果需要在 /etc_hd 下面创建新文件时, 连带的, /etc 下面的数据又得要创建一次 hard link , 因此造成环境相当大的复杂度。 所以, 目前 hard link 对于目录暂时还是不支持的。

Symbolic Link ( 符号链接, 亦即是捷径)

Symbolic link 就是在创建一个独立的文件, 而这个文件会让数据的读取指向他 link 的那个文件的文件名由于只是利用文件来做为指向的动作, 所以, 当来源文件被删除之后, symbolic link 的文件会“开不了”, 会一直说“无法打开某文件! ”。 实际上就是找不到原始“文件名”而已。

举例来说, 我们先创建一个符号链接文件链接到 /etc/crontab 去看看:

[root@study ~]# ln -s /etc/crontab crontab2
[root@study ~]# ll -i /etc/crontab /root/crontab2
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
53745909 lrwxrwxrwx. 1 root root 12  Jun 23 22:31 /root/crontab2 -> /etc/crontab

由上表的结果我们可以知道两个文件指向不同的 inode 号码, 当然就是两个独立的文件存在
而且链接文件的重要内容就是他会写上目标文件的“文件名”, 你可以发现为什么上表中链接文件的大小为 12 Bytes 呢? 因为箭头( -->) 右边的文件名“/etc/crontab”总共有 12 个英文, 每个英文占用 1 个 Bytes , 所以文件大小就是 12Bytes
 
关于上述的说明, 我们以如下图示来解释:
在这里插入图片描述
由 1 号 inode 读取到链接文件的内容仅有文件名, 根据文件名链接到正确的目录去取得目标文件的 inode , 最终就能够读取到正确的数据了。 你可以发现的是, 如果目标文件( /etc/crontab) 被删除了, 那么整个环节就会无法继续进行下去, 所以就会发生无法通过链接文件读取的问题了。

这个 Symbolic Link 与 Windows 的捷径可以给他划上等号, 由Symbolic link 所创建的文件为一个独立的新的文件, 所以会占用掉 inode 与 block
 
由上面的说明来看, 似乎 hard link 比较安全, 因为即使某一个目录下的关连数据被杀掉了,也没有关系, 只要有任何一个目录下存在着关连数据, 那么该文件就不会不见! 举上面的例子来说, 我的 /etc/crontab 与 /root/crontab 指向同一个文件, 如果我删除了 /etc/crontab 这个文件, 该删除的动作其实只是将 /etc 目录下关于 crontab 的关连数据拿掉而已, crontab 所在的 inode 与 block 其实都没有被变动。
 
不过由于 Hard Link 的限制太多了, 包括无法做“目录”的 link , 所以在用途上面是比较受限的! 反而是 Symbolic Link 的使用方面较广。

ln (制作链接文件指明)
[root@study ~]# ln [-sf] 来源文件 目标文件
选项与参数:
-s : 如果不加任何参数就进行链接, 那就是hard link, 至于 -s 就是symbolic link
-f : 如果 目标文件 存在时, 就主动的将目标文件直接移除后再创建!
范例一: 将 /etc/passwd 复制到 /tmp 下面, 并且观察 inode 与 block
[root@study ~]# cd /tmp
[root@study tmp]# cp -a /etc/passwd .
[root@study tmp]# du -sb ; df -i .
6602 . &lt;==先注意一下这里的容量是多少!
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109748 10376012 2% /
# 利用 du 与 df 来检查一下目前的参数~那个 du -sb 是计算整个 /tmp 下面有多少 Bytes 的容量啦!
范例二: 将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件, 并观察文件与容量
[root@study tmp]# ln passwd passwd-hd
[root@study tmp]# du -sb ; df -i .
6602 .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109748 10376012 2% /
# 仔细看, 即使多了一个文件在 /tmp 下面, 整个 inode 与 block 的容量并没有改变!
[root@study tmp]# ls -il passwd*
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd-hd
# 原来是指向同一个 inode 啊! 这是个重点啊! 另外, 那个第二栏的链接数也会增加!
范例三: 将 /tmp/passwd 创建一个符号链接
[root@study tmp]# ln -s passwd passwd-so
[root@study tmp]# ls -li passwd*
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd-hd
2668898 lrwxrwxrwx. 1 root root 6 Jun 23 22:40 passwd-so -&gt; passwd
# passwd-so 指向的 inode number 不同了! 这是一个新的文件~这个文件的内容是指向
# passwd 的。 passwd-so 的大小是 6Bytes , 因为 “passwd” 这个单字共有六个字符之故
[root@study tmp]# du -sb ; df -i .
6608 .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109749 10376011 2% /
# 呼呼! 整个容量与 inode 使用数都改变啰~确实如此啊!
范例四: 删除原始文件 passwd , 其他两个文件是否能够打开?
[root@study tmp]# rm passwd
[root@study tmp]# cat passwd-hd
.....( 正常显示完毕! )
[root@study tmp]# cat passwd-so
cat: passwd-so: No such file or directory
[root@study tmp]# ll passwd*
-rw-r--r--. 1 root root 2092 Jun 17 00:20 passwd-hd
lrwxrwxrwx. 1 root root 6 Jun 23 22:40 passwd-so -&gt; passwd
# 怕了吧! 符号链接果然无法打开! 另外, 如果符号链接的目标文件不存在,
# 其实文件名的部分就会有特殊的颜色显示喔!

关于目录的 link 数量

当我们创建一个新的目录时, 新的目录的 link 数为 2 , 而上层目录的 link 数则会增加 1 ;
当我们创建一个新目录名称为 /tmp/testing 时, 基本上会有三个东西:

  • /tmp/testing
  • /tmp/testing/.
  • /tmp/testing/…

而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的,都代表该目录。
而 /tmp/testing/… 则代表 /tmp 这个目录
所以 新的目录的 link 数为 2 , 而上层目录的 link 数则会增加 1

磁盘的分区、 格式化、 检验与挂载

对于一个系统管理者( root ) 而言, 磁盘的的管理是相当重要的一环, 尤其近来磁盘经渐渐的被当成是消耗品。
如果我们想要在系统里面新增一颗磁盘时, 应该有哪些动作需要做的呢:

  1. 对磁盘进行分区, 以创建可用的 partition ;
  2. 对该 partition 进行格式化 ( format) , 以创建系统可用的 filesystem;
  3. 若想要仔细一点, 则可对刚刚创建好的 filesystem 进行检验;
  4. 在 Linux 系统上, 需要创建挂载点 ( 亦即是目录) , 并将他挂载上来;
观察磁盘分区状态

由于目前磁盘分区主要有 MBR 以及 GPT 两种格式, 这两种格式所使用的分区工具不太一样,当然也可以使用 parted 这个通通有支持的工具来处理。

lsblk (list block device)列出系统上的所有磁盘列表

[root@study ~]# lsblk [-dfimpt] [device]
选项与参数:
-d : 仅列出磁盘本身, 并不会列出该磁盘的分区数据
-f : 同时列出该磁盘内的文件系统名称
-i : 使用 ASCII 的线段输出, 不要使用复杂的编码 ( 再某些环境下很有用)
-m : 同时输出该设备在 /dev 下面的权限数据 ( rwx 的数据)
-p : 列出该设备的完整文件名! 而不是仅列出最后的名字而已。
-t : 列出该磁盘设备的详细数据, 包括磁盘伫列机制、 预读写的数据量大小等
范例一: 列出本系统下的所有磁盘与磁盘内的分区信息
[root@study ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0              11:0    1 1024M  0 rom
vda             252:0    0   40G  0 disk             # 一整颗磁盘
|-vda1          252:1    0    2M  0 part
|-vda2          252:2    0    1G  0 part /boot
`-vda3          252:3    0   30G  0 part
  |-centos-root 253:0    0   10G  0 lvm  /           # 在 vda3 内的其他文件系统
  |-centos-swap 253:1    0    1G  0 lvm  [SWAP]
  `-centos-home 253:2    0    5G  0 lvm  /home

从上面的输出我们可以很清楚的看到, 目前的系统主要有个 sr0 以及一个 vda 的设备,而
vda 的设备下面又有三个分区, 其中 vda3 甚至还有因为 LVM 产生的文件系统。

从范例一我们来谈谈默认输出的信息有:

  • NAME: 就是设备的文件名啰! 会省略 /dev 等前导目录!
  • MAJ:MIN: 其实核心认识的设备都是通过这两个代码来熟悉的!
    分别是主要: 次要设备代码!
  • RM: 是否为可卸载设备 ( removable device) , 如光盘、 USB 磁盘等等
  • SIZE: 当然就是容量啰!
  • RO: 是否为只读设备的意思
  • TYPE: 是磁盘 ( disk) 、 分区 ( partition) 还是只读存储器 ( rom) 等输出
  • MOUTPOINT: 就是前一章谈到的挂载点!
范例二: 仅列出 /dev/vda 设备内的所有数据的完整文件名
[root@study ~]# lsblk -ip /dev/vda
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/vda                    252:0    0   40G  0 disk
|-/dev/vda1                 252:1    0    2M  0 part
|-/dev/vda2                 252:2    0    1G  0 part /boot
`-/dev/vda3                 252:3    0   30G  0 part
  |-/dev/mapper/centos-root 253:0    0   10G  0 lvm  /
  |-/dev/mapper/centos-swap 253:1    0    1G  0 lvm  [SWAP]
  `-/dev/mapper/centos-home 253:2    0    5G  0 lvm  /home      
   # 完整的文件名, 由 / 开始写

blkid 列出设备的 UUID 等参数

UUID 是全域单一识别码( universally unique identifier) , Linux 会将系统内所有的设备都给予一个独一无二的识别码, 这个识别码就可以拿来作为挂载或者是使用这个设备/文件系统之用
 
lsblk 已经可以使用 -f 来列出文件系统与设备的 UUID 数据

[root@study ~]# blkid
/dev/vda2: UUID="94ac5f77-cb8a-495e-a65b-2ef7442b837c" TYPE="xfs" 
/dev/vda3: UUID="WStYq1-P93d-oShM-JNe3-KeDl-bBf6-RSmfae" TYPE="LVM2_member"
/dev/sda1: UUID="35BC-6D6B" TYPE="vfat"
/dev/mapper/centos-root: UUID="299bdc5b-de6d-486a-a0d2-375402aaab27" TYPE="xfs"
/dev/mapper/centos-swap: UUID="905dc471-6c10-4108-b376-a802edbd862d" TYPE="swap"
/dev/mapper/centos-home: UUID="29979bf1-4a28-48e0-be4a-66329bf727d9" TYPE="xfs"

如上所示, 每一行代表一个文件系统, 主要列出设备名称、 UUID 名称以及文件系统的类型( TYPE)

parted 列出磁盘的分区表类型与分区信息

虽然我们已经知道了系统上面的所有设备, 并且通过 blkid 也知道了所有的文件系统! 不过,还是不清楚磁盘的分区类型。 这时我们可以通过简单的 parted 来输出。

[root@study ~]# parted device_name print

范例一: 列出 /dev/vda 磁盘的相关数据
[root@study ~]# parted /dev/vda print
Model: Virtio Block Device (virtblk)        # 磁盘的模块名称( 厂商)
Disk /dev/vda: 42.9GB                       # 磁盘的总容量
Sector size (logical/physical): 512B/512B   # 磁盘的每个逻辑/物理扇区容量
Partition Table: gpt                        # 分区表的格式 ( MBR/GPT)
Disk Flags: pmbr_boot

Number  Start   End     Size    File system  Name  Flags      # 下面才是分区数据
 1      1049kB  3146kB  2097kB                     bios_grub
 2      3146kB  1077MB  1074MB  xfs
 3      1077MB  33.3GB  32.2GB                     lvm
磁盘分区: gdisk/fdisk

MBR 分区表请使用 fdisk 分区GPT 分区表请使用 gdisk 分区
这个不要搞错~否则会分区失败的! 另外, 这两个工具软件的操作很类似, 执行了该软件后, 可以通过该软件内部的提示来操作, 因此不需要硬背。只要知道方法即可。

gdisk

[root@study ~]# gdisk 设备名称
范例: 由前一小节的 lsblk 输出, 我们知道系统有个 /dev/vda, 
请观察该磁盘的分区与相关数据
[root@study ~]# gdisk /dev/vda  <==仔细看, 不要加上数字喔!
GPT fdisk (gdisk) version 0.8.6

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.  <==找到了 GPT 的分区表!

Command (? for help):     <==这里可以让你输入指令动作, 
							可以按问号 ( ?) 来查看可用指令
Command (? for help): ?
b       back up GPT data to a file
c       change a partition's name
d       delete a partition           # 删除一个分区
i       show detailed information on a partition
l       list known partition types
n       add a new partition          # 增加一个分区
o       create a new empty GUID partition table (GPT)
p       print the partition table    # 印出分区表 ( 常用)
q       quit without saving changes  # 不储存分区就直接离开 gdisk
r       recovery and transformation options (experts only)
s       sort partitions
t       change a partition's type code
v       verify disk
w       write table to disk and exit # 储存分区操作后离开 gdisk
x       extra functionality (experts only)
?       print this menu
Command (? for help): 

你应该要通过 lsblk 或 blkid 先找到磁盘, 再用 parted /dev/xxx print 来找出内部的分区表类型, 之后才用 gdisk 或 fdisk 来操作系统。 上表中可以发现 gdisk 会扫描 MBR 与 GPT 分区表, 不过这个软件还是单纯使用在 GPT 分区表比较好。
 
不管你进行了什么动作, 只要离开 gdisk 时按下“q”,那么所有的动作“都不会生效
相反的, 按下“w”就是动作生效的意思
所以, 你可以随便玩gdisk , 只要离开时按下的是“q”即可。


Command (? for help): p  <== 这里可以输出目前磁盘的状态
Disk /dev/vda: 83886080 sectors, 40.0 GiB                     # 磁盘文件名/扇区数与总容量量
Logical sector size: 512 bytes                                # 单一扇区大小为 512 Bytes
Disk identifier (GUID): A4C3C813-62AF-4BFE-BAC9-112EBD87A483  # 磁盘的 GPT 识别码
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 83886046
Partitions will be aligned on 2048-sector boundaries
Total free space is 18862013 sectors (9.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name # 下面为完整的分区信息了!了!
   1            2048            6143   2.0 MiB     EF02       # 第一个分区数据
   2            6144         2103295   1024.0 MiB  0700
   3         2103296        65026047   30.0 GiB    8E00
# 分区编号 开始扇区号码  结束扇区号码   容量大小
Command (? for help): q
# 想要不储存离开吗? 按下 q 就对了! 不要随便按 w 啊!

使用“ p ”可以列出目前这颗磁盘的分区表信息, 这个信息的上半部在显示整体磁盘的状态。以鸟哥这颗磁盘为例, 这个磁盘共有 40GB 左右的容量, 共有 83886080 个扇区, 每个扇区的容量为 512Bytes。 要注意的是, 现在的分区主要是以扇区为最小的单位。
下半部的分区表信息主要在列出每个分区的个别信息项目。 每个项目的意义为:

  • Number: 分区编号, 1 号指的是 /dev/vda1 这样计算。
  • Start ( sector) : 每一个分区的开始扇区号码位置
  • End ( sector) : 每一个分区的结束扇区号码位置, 与 start 之间可以算出分区的总容量
  • Size: 就是分区的容量了
  • Code: 在分区内的可能的文件系统类型。 Linux 为 8300, swap 为 8200。 不过这个项目只是一个提示而已, 不见得真的代表此分区内的文件系统!
  • Name: 文件系统的名称等等。
     

从上表我们可以发现几件事情:

  • 整部磁盘还可以进行额外的分区, 因为最大扇区为 83886080, 但只使用到 65026047 号而已;
  • 分区的设计中, 新分区通常选用上一个分区的结束扇区号码数加 1 作为起始扇区号码!
     

注意:
这个 gdisk 只有 root 才能执行
请注意, 使用的“设备文件名”请不要加上数字, 因为partition 是针对“整个磁盘设备”而不是某个 partition
所以执行“ gdisk /dev/vda1 ” 就会发生错误啦要使用 gdisk /dev/vda 才对
不要在 MBR分区上面使用 gdisk, 因为如果指令按错, 恐怕你的分区纪录会全部死光光! 也不要在 GPT上面使用 fdisk 啦! 切记切记!

用 gdisk 新增分区

假设我需要有如下的分区需求:

  • 1GB 的 xfs 文件系统 ( Linux)
  • 1GB 的 vfat 文件系统 ( Windows)
  • 0.5GB 的 swap ( Linux swap) ( 这个分区等一下会被删除测试! )
[root@study ~]# gdisk /dev/vda
Command (? for help): p
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            6143   2.0 MiB     EF02
   2            6144         2103295   1024.0 MiB  0700
   3         2103296        65026047   30.0 GiB    8E00
# 找出最后一个 sector 的号码是很重要的!

Command (? for help): ?  # 查一下增加分区的指令为何
Command (? for help): n # 就是这个! 所以开始新增的行为!
Partition number (4-128, default 4): 4  # 默认就是 4 号, 所以也能 enter 即可!
First sector (34-83886046, default = 65026048) or {+-}size{KMGTP}: 65026048  # 也能 enter
Last sector (65026048-83886046, default = 83886046) or {+-}size{KMGTP}: +1G  # 決不要 enter
# 这个地方可有趣了! 我们不需要自己去计算扇区号码, 通过 +容量 的这个方式,
# 就可以让 gdisk 主动去帮你算出最接近你需要的容量的扇区号码喔!

Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):  # 使用默认值即可~直接 enter 下去!
# 这里在让你选择未来这个分区预计使用的文件系统! 默认都是 Linux 文件系统的 8300 啰!

Command (? for help): p
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            6143   2.0 MiB     EF02
   2            6144         2103295   1024.0 MiB  0700
   3         2103296        65026047   30.0 GiB    8E00
   4        65026048        67123199   1024.0 MiB  8300  Linux filesystem

重点在“ Last sector ”那一行, 那行绝对不要使用默认值因为默认值会将所有的容量用光!因此它默认选择最大的扇区号码!
因为我们仅要 1GB 而已, 所以你得要加上 +1G 这样即可。
每次新增完毕后, 请立即“ p ”查看一下结果喔! 继续处理后续的两个分区,结果如下:

Command (? for help): p
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            6143   2.0 MiB     EF02
   2            6144         2103295   1024.0 MiB  0700
   3         2103296        65026047   30.0 GiB    8E00
   4        65026048        67123199   1024.0 MiB  8300  Linux filesystem
   5        67123200        69220351   1024.0 MiB  0700  Microsoft basic data
   6        69220352        70244351   500.0 MiB   8200  Linux swap

基本上, 几乎都用默认值, 然后通过 +1G, +500M 来创建所需要的另外两个分区!
比较有趣的是文件系统的 ID 啦! 一般来说, Linux 大概都是 8200/8300/8e00 等三种格式, Windows几乎都用 0700 这样, 如果忘记这些数字, 可以在 gdisk 内按下: “ L ”来显示
如果一切的分区状态都正常的话, 那么就直接写入磁盘分区表

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/vda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
# gdisk 会先警告你可能的问题, 我们确定分区是对的, 这时才按下 y ! 不过怎么还有警告?
# 这是因为这颗磁盘目前正在使用当中, 因此系统无法立即载入新的分区表~

[root@study ~]# cat /proc/partitions
major minor  #blocks  name

 252        0   41943040 vda
 252        1       2048 vda1
 252        2    1048576 vda2
 252        3   31461376 vda3
 253        0   10485760 dm-0
 253        1    1048576 dm-1
 253        2    5242880 dm-2
# 你可以发现, 并没有 vda4, vda5, vda6 喔! 因为核心还没有更新!

因为 Linux 此时还在使用这颗磁盘, 为了担心系统出问题, 所以分区表并没有被更新!
这个时候我们有两个方式可以来处理:
其中一个是重新开机, 不过很讨厌。
另外一个则是通过partprobe 这个指令来处理即可

partprobe 更新 Linux 核心的分区表信息
[root@study ~]# partprobe [-s]  # 你可以不要加 -s ! 那么屏幕不会出现讯息!
[root@study ~]# partprobe -s    # 不过还是建议加上 -s 比较清晰!
/dev/vda: gpt partitions 1 2 3 4 5 6

[root@study ~]# lsblk /dev/vda  # 不过还是建议加上 -s 比较清晰!
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda             252:0    0   40G  0 disk
|-vda1          252:1    0    2M  0 part
|-vda2          252:2    0    1G  0 part /boot
|-vda3          252:3    0   30G  0 part
| |-centos-root 253:0    0   10G  0 lvm  /
| |-centos-swap 253:1    0    1G  0 lvm  [SWAP]
| `-centos-home 253:2    0    5G  0 lvm  /home
|-vda4          252:4    0    1G  0 part
|-vda5          252:5    0    1G  0 part
`-vda6          252:6    0  500M  0 part

[root@study ~]# cat /proc/partitions  # 核心的分区纪录
major minor  #blocks  name

 252        0   41943040 vda
 252        1       2048 vda1
 252        2    1048576 vda2
 252        3   31461376 vda3
 252        4    1048576 vda4
 252        5    1048576 vda5
 252        6     512000 vda6
# 现在核心也正确的抓到了分区参数了!

用 gdisk 删除一个分区

现在将刚刚创建的 /dev/vda6 删除。

[root@study ~]# gdisk /dev/vda
Command (? for help): p
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            6143   2.0 MiB     EF02
   2            6144         2103295   1024.0 MiB  0700
   3         2103296        65026047   30.0 GiB    8E00
   4        65026048        67123199   1024.0 MiB  8300  Linux filesystem
   5        67123200        69220351   1024.0 MiB  0700  Microsoft basic data
   6        69220352        70244351   500.0 MiB   8200  Linux swap

Command (? for help): d
Partition number (1-6): 6

Command (? for help): p
# 你会发现 /dev/vda6 不见了! 非常棒! 没问题就写入吧!

Command (? for help): w
# 同样会有一堆讯息! 在此就不重复输出了! 自己选择 y 来处理吧!

[root@study ~]# lsblk
# 你会发现! 怪了! 怎么还是有 /dev/vda6 呢? 没办法! 还没有更新核心的分区表啊! 所以当然有错!

[root@study ~]# partprobe -s
[root@study ~]# lsblk
# 这个时候, 那个 /dev/vda6 才真的消失不见了! 

注意:
不要去处理一个正在使用中的分区!
例如, 我们的系统现在已经使用了/dev/vda2 , 那如果你要删除 /dev/vda2 的话必须要先将 /dev/vda2 卸载, 否则直接删除该分区的话, 虽然磁盘还是慧写入正确的分区信息但是核心会无法更新分区表的信息的! 另外, 文件系统与 Linux 系统的稳定性, 恐怕也会变得怪怪的! 反正! 千万不要处理正在使用中的文件系统就对了。

fdisk

虽然 MBR 分区表在未来应该会慢慢的被淘汰, 毕竟现在磁盘容量随便都大于 2T 以上了。 而对于在 CentOS 7.x 中还无法完整支持 GPT 的 fdisk 来说, 这家伙真的英雄无用武之地了啦! 不过依旧有些旧的系统, 以及虚拟机的使用上面, 还是有小磁盘存在的空间! 这时处理MBR 分区表, 就得要使用 fdisk。
 
因为 fdisk 跟 gdisk 使用的方式几乎一样。
只是一个使用 ? 作为指令提示数据, 一个使用 m作为提示这样而已
此外, fdisk 有时会使用柱面 ( cylinder) 作为分区的最小单位, 与gdisk 默认使用 sector 不太一样
大致上只是这点差别! 另外, MBR 分区是有限制的( Primary, Extended, Logical…)

[root@study ~]# fdisk /dev/sda
Command (m for help): m   <== 输入 m 后, 就会看到下面这些指令介绍
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition            <==删除一个partition
   l   list known partition types
   m   print this menu
   n   add a new partition           <==新增一个partition
   o   create a new empty DOS partition table
   p   print the partition table     <==在屏幕上显示分区表
   q   quit without saving changes   <==不储存离开fdisk程序
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit  <==将刚刚的动作写入分区表
   x   extra functionality (experts only)
磁盘格式化( 创建文件系统)

分区完毕后自然就是要进行文件系统的格式化!
格式化的指令非常的简单, 那就“makefilesystem, mkfs” 这个指令。
这个指令其实是个综合的指令, 他会去调用正确的文件系统格式化工具软件
因为 CentOS 7 使用 xfs 作为默认文件系统, 先介绍 mkfs.xfs之后介绍新一代的 EXT 家族成员 mkfs.ext4, 最后介绍mkfs 这个综合指令。

XFS 文件系统 mkfs.xfs

我们常听到的“格式化”其实应该称为“创建文件系统 ( make filesystem)
我们要创建的是 xfs 文件系统, 因此使用的是 mkfs.xfs 这个指令。

[root@study ~]# mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-L label] [-f]  [-r parms] 设备名称
选项与参数:
关於单位: 下面只要谈到“数值”时, 没有加单位则为 Bytes 值, 可以用 k,m,g,t,p ( 小写) 等来解释
          比较特殊的是 s 这个单位, 它指的是 sector 的“个数”喔!
-b  :后面接的是 block 容量, 可由 512 到 64k, 不过最大容量限制为 Linux 的 4k 喔!
-d  :后面接的是重要的 data section 的相关参数值, 主要的值有:
      agcount=数值  :设置需要几个储存群组的意思( AG) , 通常与 CPU 有关
      agsize=数值   :每个 AG 设置为多少容量的意思, 通常 agcount/agsize 只选一个设置即可
      file          :指的是“格式化的设备是个文件而不是个设备”的意思! ( 例如虚拟磁盘)
      size=数值     :data section 的容量, 亦即你可以不将全部的设备容量用完的意思
      su=数值       :当有 RAID 时, 那个 stripe 数值的意思, 与下面的 sw 搭配使用
      sw=数值       :当有 RAID 时, 用于储存数据的磁盘数量( 须扣除备份碟与备用碟)
      sunit=数值    :与 su 相当, 不过单位使用的是“几个 sector( 512Bytes大小) ”的意思
      swidth=数值   :就是 su*sw 的数值, 但是以“几个 sector( 512Bytes大小) ”来设置
-f  :如果设备内已经有文件系统, 则需要使用这个 -f 来强制格式化才行!
-i  :如果设备内已经有文件系统, 则需要使用这个 -f 来强制格式化才行!
      size=数值 	:最小是 256Bytes 最大是 2k, 一般保留 256 就足够使用了!
      internal=[0|1]:log 设备是否为内置? 默认为 1 内置, 如果要用外部设备, 使用下面设置
      logdev=device :log 设备为后面接的那个设备上头的意思, 需设置 internal=0 才可!
      size=數值     :指定这块登录区的容量, 通常最小得要有 512 个 block, 大约 2M 以上才行!
-L  :后面接这个文件系统的标头名称 Label name 的意思!
-r  :指定 realtime section 的相关设置值, 常见的有:
      extsize=数值 : 就是那个重要的 extent 数值, 一般不须设置, 但有 RAID 时,
                      最好设置与 swidth 的数值相同较佳! 最小为 4K 最大为 1G 。

范例: 将前一小节分区出来的 /dev/vda4 格式化为 xfs 文件系统
[root@study ~]# mkfs.xfs /dev/vda4
meta-data=/dev/vda4       isize=256    agcount=4, agsize=65536 blks
         =                sectsz=512   attr=2, projid32bit=1
         =                crc=0        finobt=0
data     =                bsize=4096   blocks=262144, imaxpct=25
         =                sunit=0      swidth=0 blks
naming   =version 2       bsize=4096   ascii-ci=0 ftype=0
log      =internal log    bsize=4096   blocks=2560, version=2
         =                sectsz=512   sunit=0 blks, lazy-count=1
realtime =none            extsz=4096   blocks=0, rtextents=0
# 很快格是化完毕! 都用默认值! 较重要的是 inode 与 block 的数值

[root@study ~]# blkid /dev/vda4
/dev/vda4: UUID="39293f4f-627b-4dfd-a015-08340537709c" TYPE="xfs"
# 确定创建好 xfs 文件系统了!

使用默认的 xfs 文件系统参数来创建系统即可! 速度非常快! 如果我们有其他额外想要处理的项目, 才需要加上一堆设置值! 举例来说, 因为 xfs 可以使用多个数据流来读写系统, 以增加速度, 因此那个 agcount 可以跟 CPU 的核心数来做搭配! 举例来说, 如果我的服务器仅有一颗 4 核心, 但是有启动 Intel 超线程功能, 则系统会仿真出 8 颗 CPU 时, 那个 agcount 就可以设置为 8:

范例: 找出你系统的 CPU 数, 并据以设置你的 agcount 数值
[root@study ~]# grep 'processor' /proc/cpuinfo
processor       : 0
processor       : 1
# 所以就是有两颗 CPU 的意思, 那就来设置设置我们的 xfs 文件系统格式化参数吧! !

[root@study ~]# mkfs.xfs -f -d agcount=2 /dev/vda4
meta-data=/dev/vda4       isize=256    agcount=2, agsize=131072 blks
         =                sectsz=512   attr=2, projid32bit=1
         =                crc=0        finobt=0
.....( 下面省略) .....
# 可以跟前一个范例对照看看, 可以发现 agcount 变成 2 了喔!
# 此外, 因为已经格式化过一次, 因此 mkfs.xfs 可能会出现不给你格式化的警告! 因此需要使用 -f

EXT4 文件系统 mkfs.ext4

如果想要格式化为 ext4 的传统 Linux 文件系统的话, 可以使用 mkfs.ext4 这个指令即可

[root@study ~]# mkfs.ext4 [-b size] [-L label] 设备名称
选项与参数:
-b : 设置 block 的大小, 有 1K, 2K, 4K 的容量,
-L : 后面接这个设备的标头名称。

範例:將 /dev/vda5 格式化為 ext4 檔案系統
[root@study ~]# mkfs.ext4 /dev/vda5
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=                                  # 显示 Label name
OS type: Linux
Block size=4096 (log=2)                            # 每一个 block 的大小
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks             # 跟 RAID 相关性较高
65536 inodes, 262144 blocks                        # 总计 inode/block 的数量
13107 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=268435456
8 block groups                                     # 共有 8 个 block groups 喔!
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

[root@study ~]# dumpe2fs -h /dev/vda5
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          3fd5cc6f-a47d-46c0-98c0-d43b072e0e12
....(中間省略)....
Inode count:              65536
Block count:              262144
Block size:               4096
Blocks per group:         32768
Inode size:               256
Journal size:             32M

因为 ext4 的默认值已经相当适合我们系统使用, 大部分的默认值写入于我们系统的 /etc/mke2fs.conf 这个文件中,有兴趣可以自行前往查阅。 也因此, 我们无须额外指定 inode 的容量, 系统都帮我们做好默认值! 只需要得到 uuid 这个东西即可。

其他文件系统 mkfs

mkfs 其实是个综合指令而已, 当我们使用 mkfs -t xfs 时, 它就会跑去找 mkfs.xfs 相关的参数给我们使用
如果想要知道系统还支持哪种文件系统的格式化功能, 直接按 [tabl] 就很清楚

[root@study ~]# mkfs[tab][tab]
mkfs         mkfs.btrfs   mkfs.cramfs  mkfs.ext2    mkfs.ext3    mkfs.ext4    
mkfs.fat     mkfs.minix   mkfs.msdos   mkfs.vfat    mkfs.xfs

所以系统还有支持 ext2/ext3/vfat 等等多种常用的文件系统
那如果要将刚刚的 /dev/vda5重新格式化为 VFAT 文件系统呢?

[root@study ~]# mkfs -t vfat /dev/vda5
[root@study ~]# blkid /dev/vda5
/dev/vda5: UUID="7130-6012" TYPE="vfat" PARTLABEL="Microsoft basic data"

[root@study ~]# mkfs.ext4 /dev/vda5
[root@study ~]# blkid /dev/vda4 /dev/vda5
/dev/vda4: UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" TYPE="xfs" 
/dev/vda5: UUID="899b755b-1da4-4d1d-9b1c-f762adb798e1" TYPE="ext4"
文件系统检验

由于系统在运行时谁也说不准啥时硬件或者是电源会有问题, 所以“死机”可能是难免的情况( 不管是硬件还是软件) 。 现在我们知道文件系统运行时会有磁盘与内存数据非同步的状况发生, 因此莫名其妙的死机非常可能导致文件系统的错乱
如果文件系统真的发生错乱的话, 不同的文件系统救援的指令不太一样, 这里主要针对xfs 及 ext4 这两个主流来说明

xfs_repair 处理 XFS 文件系统

当有 xfs 文件系统错乱才需要使用这个指令
所以, 这个指令最好是不要用到啦! 但有问题发生时, 这个指令却又很重要。

[root@study ~]# xfs_repair [-fnd] 设备名称
选项与参数:
-f : 后面的设备其实是个文件而不是实体设备
-n : 单纯检查并不修改文件系统的任何数据 ( 检查而已)
-d : 通常用在单人维护模式下面, 针对根目录 ( /) 进行检查与修复的动作! 很危险! 不要随便使用

范例: 检查一下刚刚创建的 /dev/vda4 文件系统
[root@study ~]# xfs_repair /dev/vda4
Phase 1 - find and verify superblock...
Phase 2 - using internal log
Phase 3 - for each AG...
Phase 4 - check for duplicate blocks...
Phase 5 - rebuild AG headers and trees...
Phase 6 - check inode connectivity...
Phase 7 - verify and correct link counts...
done
# 共有 7 个重要的检查流程! 详细的流程介绍可以 man xfs_repair 即可!

范例: 检查一下系统原本就有的 /dev/centos/home 文件系统
[root@study ~]# xfs_repair /dev/centos/home
xfs_repair: /dev/centos/home contains a mounted filesystem
xfs_repair: /dev/centos/home contains a mounted and writable filesystem

fatal error -- couldn't initialize XFS library

xfs_repair 可以检查/修复文件系统, 不过, 因为修复文件系统是个很庞大的任务
因此, 修复时该文件系统不能被挂载
所以, 检查与修复 /dev/vda4 没啥问题但是修复/dev/centos/home 这个已经挂载的文件系统时就出现上述的问题了! 没关系, 若可以卸载, 卸载后再处理即可。

Linux 系统有个设备无法被卸载, 那就是根目录
如果你的根目录有问题怎办? 这时得要进入单人维护或救援模式, 然后通过 -d 这个选项来处理
加入 -d 这个选项后, 系统会强制检验该设备, 检验完毕后就会自动重新开机。

fsck.ext4 处理 EXT4 文件系统

fsck 是个综合指令, 如果是针对 ext4 的话, 建议直接使用 fsck.ext4 来检测比较妥当

[root@study ~]# fsck.ext4 [-pf] [-b superblock] 设备名称
选项与参数:
-p  :当文件系统在修复时, 若有需要回复 y 的动作时, 自动回复 y 来继续进行修复动作。
-f  :强制检查! 一般来说, 如果 fsck 没有发现任何 unclean 的旗标, 不会主动进入
      细部检查的, 如果您想要强制 fsck 进入细部检查, 就得加上 -f 旗标啰!
-D  :针对文件系统下的目录进行最优化配置。
-b  : 后面接 superblock 的位置! 一般来说这个选项用不到。 但是如果你的 superblock 因故损毁时,
       通过这个参数即可利用文件系统内备份的 superblock 来尝试救援。 一般来说, superblock 备份在:
      1K block 放在 8193, 2K block 放在 16384, 4K block 放在 32768

范例: 找出刚刚创建的 /dev/vda5 的另一块 superblock, 并据以检测系统
[root@study ~]# dumpe2fs -h /dev/vda5 | grep 'Blocks per group'
Blocks per group:         32768
# 看起来每个 block 群组会有 32768 个 block, 因此第二个 superblock 应该就在 32768 上!
# 因为 block 号码为 0 号开始编的!

[root@study ~]# fsck.ext4 -b 32768 /dev/vda5
e2fsck 1.42.9 (28-Dec-2013)
/dev/vda5 was not cleanly unmounted, check forced.
Pass 1: Checking inodes, blocks, and sizes
Deleted inode 1577 has zero dtime.  Fix<y>? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information

/dev/vda5: ***** FILE SYSTEM WAS MODIFIED *****  # 文件系统被改过, 所以这里会有警告!
/dev/vda5: 11/65536 files (0.0% non-contiguous), 12955/262144 blocks
# 好巧合! 鸟哥使用这个方式来检验系统, 恰好遇到文件系统出问题! 于是可以有比较多的解释方向!
# 当文件系统出问题, 它就会要你选择是否修复~如果修复如上所示, 按下 y 即可!
# 最终系统会告诉你, 文件系统已经被更改过, 要注意该项目的意思!

范例: 已默认设置强制检查一次 /dev/vda5
[root@study ~]# fsck.ext4 /dev/vda5
e2fsck 1.42.9 (28-Dec-2013)
/dev/vda5: clean, 11/65536 files, 12955/262144 blocks
# 文件系统状态正常, 它并不会进入强制检查! 会告诉你文件系统没问题 ( clean)

[root@study ~]# fsck.ext4 -f /dev/vda5
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
....(底下省略)....

无论是 xfs_repair 或 fsck.ext4, 这都是用来检查与修正文件系统错误的指令。
注意:
通常只有身为 root 且你的文件系统有问题的时候才使用这个指令, 否则在正常状况下使用此一指令, 可能会造成对系统的危害
通常使用这个指令的场合都是在系统出现极大的问题, 导致你在 Linux 开机的时候得进入单人单机模式下进行维护的行为时, 才必须使用此一指令

另外, 如果你怀疑刚刚格式化成功的磁盘有问题的时后, 也可以使用 xfs_repair/fsck.ext4 来检查一磁盘
其实就有点像是 Windows 的 scandisk !
此外, 由于 xfs_repair/fsck.ext4在扫瞄磁盘的时候, 可能会造成部分 filesystem 的修订所以执行 xfs_repair/fsck.ext4 时,被检查的 partition 务必不可挂载到系统上。 亦即是需要在卸载的状态

文件系统挂载与卸载

挂载点是目录, 目录是进入磁盘分区( 其实是文件系统 ) 的入口。
进行挂载前,需要注意的是:

  • 单一文件系统不应该被重复挂载在不同的挂载点( 目录) 中
  • 单一目录不应该重复挂载多个文件系统
  • 要作为挂载点的目录, 理论上应该都是空目录才是。
     

如果你要用来挂载的目录里面并不是空的, 那么挂载了文件系统之后, 原目录下的东西就会暂时的消失
举个例子来说, 假设你的 /home 原本与根目录 ( /)在同一个文件系统中, 下面原本就有/home/test 与 /home/vbird 两个目录。 然后你想要加入新的磁盘, 并且直接挂载 /home 下面, 那么当你挂载上新的分区时, 则 /home 目录显示的是新分区内的数据, 至于原先的 test 与 vbird 这两个目录就会暂时的被隐藏掉了! 注意喔! 并不是被覆盖掉, 而是暂时的隐藏了起来, 等到新分区被卸载之后, 则 /home 原本的内容就会再次的跑出来。

mount

而要将文件系统挂载到我们的 Linux 系统上, 就要使用 mount 这个指令。


[root@study ~]# mount -a
[root@study ~]# mount [-l]
[root@study ~]# mount [-t 挂载点 ] LABEL=''  挂载点
[root@study ~]# mount [-t 挂载点 ] UUID=''   挂载点 # 鸟哥近期建议用这种方式喔!
[root@study ~]# mount [-t 挂载点 ] 设备文件名 挂载点

选项与参数:
-a  :依照配置文件 [/etc/fstab] 的数据将所有未挂载的磁盘都挂载上来
-l  :单纯的输入 mount 会显示目前挂载的信息。 加上 -l 可增列 Label 名称!
-t  :可以加上文件系统种类来指定欲挂载的类型。 常见的 Linux 支持类型有: xfs, ext3, ext4,
      reiserfs, vfat, iso9660( 光盘格式) , nfs, cifs, smbfs ( 后三种为网络文件系统类型)
-n  :在默认的情况下, 系统会将实际挂载的情况实时写入 /etc/mtab 中, 以利其他程序的运行。
      但在某些情况下( 例如单人维护模式) 为了避免问题会刻意不写入。 此时就得要使用 -n 选项。
-o  :后面可以接一些挂载时额外加上的参数! 比方说帐号、 密码、 读写权限等:
      async, sync:   此文件系统是否使用同步写入 ( sync) 或非同步 ( async) 的
                     内存机制。 默认为 async。
      atime,noatime: 是否修订文件的读取时间( atime) 。 为了性能, 某些时刻可使用 noatime
      ro, rw:        挂载文件系统成为只读( ro) 或可读写( rw)
      auto, noauto:  允许此 filesystem 被以 mount -a 自动挂载( auto)
      dev, nodev:    是否允许此 filesystem 上, 可创建设备文件? dev 为可允许
      suid, nosuid:  是否允许此 filesystem 含有 suid/sgid 的文件格式?
      exec, noexec:  是否允许此 filesystem 上拥有可执行 binary 文件?
      user, nouser:  是否允许此 filesystem 让任何使用者执行 mount ? 一般来说,
                     mount 仅有 root 可以进行, 但下达 user 参数, 则可让
                     一般 user 也能够对此 partition 进行 mount 。
      defaults:      默认值为: rw, suid, dev, exec, auto, nouser, and async
      remount:       重新挂载, 这在系统出错, 或重新更新参数时, 很有用!

基本上, CentOS 7 已经太聪明了, 因此你不需要加上 -t 这个选项, 系统会自动的分析最恰当的文件系统来尝试挂载你需要的设备这也是使用 blkid 就能够显示正确的文件系统的缘故
那 CentOS 是怎么找出文件系统类型的呢? 由于文件系统几乎都有 superblock , 我们的Linux 可以通过分析 superblock 搭配 Linux 自己的驱动程序去测试挂载, 如果成功的套和了, 就立刻自动的使用该类型的文件系统挂载起来
 
那么系统有没有指定哪些类型的filesystem 才需要进行上述的挂载测试呢? 主要是参考下面这两个文件:

  • /etc/filesystems: 系统指定的测试挂载文件系统类型的优先顺序;
  • /proc/filesystems: Linux系统已经载入的文件系统类型。
     

怎么知道我的 Linux 有没有相关文件系统类型的驱动程序呢? 我们 Linux 支持的文件系统之驱动程序都写在如下的目录中:

  • /lib/modules/$( uname -r) /kernel/fs/

例如 ext4 的驱动程序就写在“/lib/modules/$( uname -r) /kernel/fs/ext4/”这个目录下
 
过去我们都习惯使用设备文件名然后直接用该文件名挂载, 不过比较建议使用 UUID 来识别文件系统, 会比设备名称与标头名称还要更可靠因为是独一无二的

挂载 xfs/ext4/vfat 等文件系统

范例: 找出 /dev/vda4 的 UUID 后, 用该 UUID 来挂载文件系统到 /data/xfs 内
[root@study ~]# blkid /dev/vda4
/dev/vda4: UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" TYPE="xfs"

[root@study ~]# mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs
mount: mount point /data/xfs does not exist  # 非正规目录! 所以手动创建它!

[root@study ~]# mkdir -p /data/xfs
[root@study ~]# mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs
[root@study ~]# df /data/xfs
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/vda4        1038336 32864   1005472   4% /data/xfs
# 顺利挂载, 且容量约为 1G 左右没问题!

范例: 使用相同的方式, 将 /dev/vda5 挂载于 /data/ext4
[root@study ~]# blkid /dev/vda5
/dev/vda5: UUID="899b755b-1da4-4d1d-9b1c-f762adb798e1" TYPE="ext4"

[root@study ~]# mkdir /data/ext4
[root@study ~]# mount UUID="899b755b-1da4-4d1d-9b1c-f762adb798e1" /data/ext4
[root@study ~]# df /data/ext4
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/vda5         999320  2564    927944   1% /data/ext4

挂载 CD 或 DVD 光盘

范例: 用光盘挂载到 /data/cdrom!
[root@study ~]# blkid
.....(前面省略).....
/dev/sr0: UUID="2015-04-01-00-21-36-00" LABEL="CentOS 7 x86_64" TYPE="iso9660" PTTYPE="dos"

[root@study ~]# mkdir /data/cdrom
[root@study ~]# mount /dev/sr0 /data/cdrom
mount: /dev/sr0 is write-protected, mounting read-only

[root@study ~]# df /data/cdrom
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sr0         7413478 7413478         0 100% /data/cdrom
# 怎么会使用掉 100% 呢? 是啊! 因为是 DVD 啊! 所以无法再写入了啊!

光驱一挂载之后就无法退出光盘片! 除非你将他卸载才能够退出
因为是光盘! 所以磁盘使用率达到 100% , 因为你无法直接写入任何数据到光盘当中!

挂载 vfat 中文U盘 ( USB磁盘)

你的U盘不能够是 NTFS 的文件系统,Linux默认不支持该系统。

范例: 找出你的U盘设备的 UUID, 并挂载到 /data/usb 目录中
[root@study ~]# blkid
/dev/sda1: UUID="35BC-6D6B" TYPE="vfat"

[root@study ~]# mkdir /data/usb
[root@study ~]#   mount -o codepage=950,iocharset=utf8 UUID="35BC-6D6B" /data/usb
[root@study ~]# # mount -o codepage=950,iocharset=big5 UUID="35BC-6D6B" /data/usb
[root@study ~]# df /data/usb
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/sda1        2092344     4   2092340   1% /data/usb

如果带有中文文件名的数据, 那么可以在挂载时指定一下挂载文件系统所使用的语系数据。
man mount 找到 vfat 文件格式当中可以使用 codepage 来处理。

万一你使用的 USB 磁盘被格式化为 NTFS 时那可能就得要动点手脚, 因为默认的 CentOS7 并没有支持 NTFS 文件系统格式
所以你得要安装 NTFS 文件系统的驱动程序后, 才有办法处理的

重新挂载根目录与挂载不特定目录

整个目录树最重要的地方就是根目录了, 所以根目录根本就不能够被卸载的;
如果你的挂载参数要改变, 或者是根目录出现“只读”状态时, 如何重新挂载呢?
最可能的处理方式就是重新开机 ( reboot) ! 不过你也可以这样做:

范例: 将 / 重新挂载, 并加入参数为 rw 与 auto
[root@study ~]# mount -o remount,rw,auto /

重点是那个“ -o remount,xx ”的选项与参数
请注意, 要重新挂载 ( remount) 时, 这是个非常重要的机制
尤其是当你进入单人维护模式时, 你的根目录常会被系统挂载为只读, 这个时候这个指令就太重要了

另外, 我们也可以利用 mount 来将某个目录挂载到另外一个目录去
这并不是挂载文件系统, 而是额外挂载某个目录的方法
虽然下面的方法也可以使用 symbolic link 来链接, 不过在某些不支持符号链接的程序运行中, 还是得要通过这样的方法才行。

范例: 将 /var 这个目录暂时挂载到 /data/var 下面:
[root@study ~]# mkdir /data/var
[root@study ~]# mount --bind /var /data/var
[root@study ~]# ls -lid /var /data/var
16777346 drwxr-xr-x. 22 root root 4096 Jun 15 23:43 /data/var
16777346 drwxr-xr-x. 22 root root 4096 Jun 15 23:43 /var
# 内容完全一模一样啊! 因为挂载目录的缘故!

[root@study ~]# mount | grep var
/dev/mapper/centos-root on /data/var type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

通过这个 mount --bind 的功能, 您可以将某个目录挂载到其他目录去
而并不是整块 filesystem 的啦! 所以从此进入/data/var 就是进入 /var 的意思

umount ( 将设备文件卸载)

[root@study ~]# umount [-fn] 设备文件名或挂载点
选项与参数:
-f : 强制卸载! 可用在类似网络文件系统 ( NFS) 无法读取到的情况下;
-l : 立刻卸载文件系统, 比 -f 还强!
-n : 不更新 /etc/mtab 情况下卸载。

直接将已挂载的文件系统给他卸载即是!
卸载之后, 可以使用 df 或 mount 看看是否还存在目录树中
载的方式, 可以下达设备文件名或挂载点, 均可接受

范例: 将本章之前自行挂载的文件系统全部卸载:
[root@study ~]# mount
.....(前面省略).....
/dev/vda4 on /data/xfs type xfs (rw,relatime,seclabel,attr2,inode64,logbsize=256k,sunit=512,..)
/dev/vda5 on /data/ext4 type ext4 (rw,relatime,seclabel,data=ordered)
/dev/sr0 on /data/cdrom type iso9660 (ro,relatime)
/dev/sda1 on /data/usb type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=950,iocharset=...)
/dev/mapper/centos-root on /data/var type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
# 先找一下已经挂载的文件系统, 如上所示, 特殊字体即为刚刚挂载的设备啰!
# 基本上, 卸载后面接设备或挂载点都可以! 不过最后一个 centos-root 由于有其他挂载,
# 因此, 该项目一定要使用挂载点来卸载才行!

[root@study ~]# umount /dev/vda4      <==用设备文件名来卸载
[root@study ~]# umount /data/ext4     <==用挂载点来卸载
[root@study ~]# umount /data/cdrom    <==因为挂载点比较好记忆!
[root@study ~]# umount /data/usb     
[root@study ~]# umount /data/var      <==一定要用挂载点! 因为设备有被其他方式挂载

由于通通卸载了, 此时你才可以退出光盘片、 软盘片、 U盘等设备。
如果你遇到这样的情况:

[root@study ~]# mount /dev/sr0 /data/cdrom
[root@study ~]# cd /data/cdrom
[root@study cdrom]# umount /data/cdrom
umount: /data/cdrom: target is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))

[root@study cdrom]# cd /
[root@study /]# umount /data/cdrom

由于你目前正在 /data/cdrom/ 的目录内, 也就是说其实“你正在使用该文件系统”的意思
所以自然无法卸载这个设备,“离开该文件系统的挂载点后就可以正常卸载。

磁盘/文件系统参数修订

某些时刻, 你可能会希望修改一下目前文件系统的一些相关信息;
举例来说, 你可能要修改Label name , 或者是 journal 的参数, 或者是其他磁盘/文件系统运行时的相关参数 ( 例如DMA 启动与否~) 。
这个时候, 就得需要下面这些相关的指令功能。

mknod

在 Linux 下面所有的设备都以文件来代表
但是那个文件如何代表该设备呢很简单, 就是通过文件的 major 与 minor 数值来替代的。
所以, 那个 major 与 minor数值是有特殊意义的, 不是随意设置的。
lsblk 指令中含有major 与 minor数值。

磁盘 /dev/vda 的相关设备代码如下:

[root@study ~]# ll /dev/vda*
brw-rw----. 1 root disk 252, 0 Jun 24 02:30 /dev/vda
brw-rw----. 1 root disk 252, 1 Jun 24 02:30 /dev/vda1
brw-rw----. 1 root disk 252, 2 Jun 15 23:43 /dev/vda2
brw-rw----. 1 root disk 252, 3 Jun 15 23:43 /dev/vda3
brw-rw----. 1 root disk 252, 4 Jun 24 20:00 /dev/vda4
brw-rw----. 1 root disk 252, 5 Jun 24 21:15 /dev/vda5

上表当中 252 为主要设备代码 ( Major) 而 0~5 则为次要设备代码 ( Minor)
我们的Linux 核心认识的设备数据就是通过这两个数值来决定的

举例来说, 常见的磁盘文件名**/dev/sda 与 /dev/loop0** 设备代码如下所示:

磁盘文件名MajorMinor
/dev/sda80-15
/dev/sdb816-31
/dev/loop070
/dev/loop171

基本上, Linux 核心 2.6 版以后, 硬件文件名已经都可以被系统自动的实时产生了, 我们根本不需要手动创建设备文件。
不过某些情况下面我们可能还是得要手动处理设备文件的例如在某些服务被关到特定目录下时( chroot) , 就需要这样做了。
此时这个 mknod 就得要知道如何操作才行。

[root@study ~]# mknod 设备文件名 [bcp] [Major] [Minor]
选项与参数:
设备种类:
   b  :设置设备名称成为一个周边储存设备文件, 例如磁盘等;
   c  :设置设备名称成为一个周边输入设备文件, 例如鼠标/键盘等;
   p  :设置设备名称成为一个 FIFO 文件;
Major :主要设备代码;
Minor :主要设备代码;

范例: 由上述的介绍我们知道 /dev/vda10 设备代码 252, 10, 请创建并查阅此设备
[root@study ~]# mknod /dev/vda10 b 252 10
[root@study ~]# ll /dev/vda10
brw-r--r--. 1 root root 252, 10 Jun 24 23:40 /dev/vda10
# 上面那个 252 与 10 是有意义的, 不要随意设置啊!

范例: 创建一个 FIFO 文件, 文件名为 /tmp/testpipe
[root@study ~]# mknod /tmp/testpipe p
[root@study ~]# ll /tmp/testpipe
prw-r--r--. 1 root root 0 Jun 24 23:44 /tmp/testpipe
# 注意啊! 这个文件可不是一般文件, 不可以随便就放在这里!
# 测试完毕之后请删除这个文件吧! 看一下这个文件的类型! 是 p 喔! ^_^

[root@study ~]# rm /dev/vda10 /tmp/testpipe
rm: remove block special file '/dev/vda10' ? y
rm: remove fifo '/tmp/testpipe' ? y

xfs_admin 修改 XFS 文件系统的 UUID 与 Label name

如果你当初格式化的时候忘记加上标头名称, 后来想要再次加入时, 不需要重复格式化。
直接使用这个 xfs_admin 即可。 这个指令直接拿来处理 LABEL name 以及 UUID 即可。

[root@study ~]# xfs_admin [-lu] [-L label] [-U uuid] 设备文件名
选项与参数:
-l : 列出这个设备的 label name
-u : 列出这个设备的 UUID
-L : 设置这个设备的 Label name
-U : 设置这个设备的 UUID 喔!

范例: 设置 /dev/vda4 的 label name 为 vbird_xfs, 并测试挂载
[root@study ~]# xfs_admin -L vbird_xfs /dev/vda4
writing all SBs
new label = "vbird_xfs"                 # 产生新的 LABEL 名称啰!
[root@study ~]# xfs_admin -l /dev/vda4
label = "vbird_xfs"
[root@study ~]# mount LABEL=vbird_xfs /data/xfs/

范例: 利用 uuidgen 产生新 UUID 来设置 /dev/vda4, 并测试挂载
[root@study ~]# umount /dev/vda4       # 使用前, 请先卸载!
[root@study ~]# uuidgen
e0fa7252-b374-4a06-987a-3cb14f415488    # 很有趣的指令! 可以产生新的 UUID 喔!
[root@study ~]# xfs_admin -u /dev/vda4
UUID = e0a6af55-26e7-4cb7-a515-826a8bd29e90
[root@study ~]# xfs_admin -U e0fa7252-b374-4a06-987a-3cb14f415488 /dev/vda4
Clearing log and setting UUID
writing all SBs
new UUID = e0fa7252-b374-4a06-987a-3cb14f415488
[root@study ~]# mount UUID=e0fa7252-b374-4a06-987a-3cb14f415488 /data/xfs

关于使用UUID挂载设备:
一般服务器都有多个硬盘分区,在重启后,这些分区的逻辑位置加载时可能会发生变动如果使用传统的设备名称(例如:/dev/sda)方式挂载磁盘,就可能因为磁盘顺序变化而造成混乱。
但是 UUID 可是很难重复的, 所以你可以确定该名称不会被重复;
这对系统管理上可是相当有帮助的,它也比 LABEL name 要更精准的多。

tune2fs 修改 ext4 的 label name 与 UUID

[root@study ~]# tune2fs [-l] [-L Label] [-U uuid] 裝置檔名
選項與參數:
-l  :类似 dumpe2fs -h 的功能~将 superblock 内的数据读出来~
-L  :修改 LABEL name
-U  :修改 UUID

范例: 列出 /dev/vda5 的 label name 之后, 将它改成 vbird_ext4
[root@study ~]# dumpe2fs -h /dev/vda5 | grep name
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   <none>   # 果然是没有设置的!

[root@study ~]# tune2fs -L vbird_ext4 /dev/vda5
[root@study ~]# dumpe2fs -h /dev/vda5 | grep name
Filesystem volume name:   vbird_ext4
[root@study ~]# mount LABEL=vbird_ext4 /data/ext4

设置开机挂载

开机挂载 /etc/fstab 及 /etc/mtab

通过mount挂载的设备是手动挂载重新开机后,系统不会自动挂载,还需要再次挂载
可将挂载信息,写入 /etc/fstab ( filesystem table) 开机配置文件,就可以开机自动挂载。

关于系统挂载的一些限制:

  • 根目录 / 是必须挂载的﹐ 而且一定要先于其它 mount point 被挂载进来。
  • 其它 mount point 必须为已创建的目录﹐ 可任意指定﹐ 但一定要遵守必须的系统目录架构原则 ( FHS)
  • 所有 mount point 在同一时间之内﹐ 只能挂载一次。
  • 所有 partition 在同一时间之内﹐ 只能挂载一次。
  • 如若进行卸载﹐ 您必须先将工作目录移到 mount point( 及其子目录) 之外。

/etc/fstab文件如下:

[root@study ~]# cat /etc/fstab
# Device                              Mount point  filesystem parameters    dump fsck
/dev/mapper/centos-root                   /       xfs     defaults            0 0
UUID=94ac5f77-cb8a-495e-a65b-2ef7442b837c /boot   xfs     defaults            0 0
/dev/mapper/centos-home                   /home   xfs     defaults            0 0
/dev/mapper/centos-swap                   swap    swap    defaults            0 0

其实 /etc/fstab ( filesystem table) 就是将我们利用 mount 指令进行挂载时, 将所有的需要自动挂载的选项与参数写入到这个文件中,即可自动挂载。
除此之外, /etc/fstab 还加入了 dump 这个备份用指令的支持与开机时是否进行文件系统检验 fsck 等指令有关。

各字段说明如下
  • 第一栏: 磁盘设备文件名/UUID/LABEL name:
    这个字段可以填写的数据主要有三个项目:
  • 文件系统或磁盘的设备文件名, 如 /dev/vda2 等
  • 文件系统的 UUID 名称, 如 UUID=xxx
  • 文件系统的 LABEL 名称, 例如 LABEL=xxx
  • 第二栏: 挂载点 ( mount point) : 挂载目录
  • 第三栏: 磁盘分区的文件系统:
    在手动挂载时可以让系统自动测试挂载但在这个文件当中我们必须要手动写入文件系统才行! 包括 xfs, ext4, vfat, reiserfs, nfs 等等。
  • 第四栏: 文件系统参数:
参数内容意义
async/sync 非同步/同步设置磁盘是否以非同步方式运行! 默认为 async( 性能较佳)
auto/noauto 自动/非自动当下达 mount -a 时, 此文件系统是否会被主动测试挂载。 默认为 auto。
rw/ro 可读 写/只读让该分区以可读写或者是只读的型态挂载上来, 如果你想要分享的数据是不给使用者随意变更的, 这里也能够设置为只读。 则不论在此文件系统的文件是否设置 w 权限, 都无法写入喔!
exec/noexec 可执行/不可执行限制在此文件系统内是否可以进行“执行”的工作? 如果是纯粹用来储存数据的目录, 那么可以设置为 noexec 会比较安全。 不过, 这个参数也不能随便使用, 因为你不知道该目录下是否默认会有可执行文件。 举例来说, 如果你将 noexec 设置在 /var , 当某些软件将一些可执行文件放置于 /var 下时, 那就会产生很大的问题喔! 因此, 建议这个 noexec 最多仅设置于你自订或分享的一般数据目录。
user/nouser 允许/不允许使用者挂载是否允许使用者使用 mount指令来挂载呢? 一般而言, 我们当然不希望一般身份的 user 能使用 mount 啰, 因为太不安全了, 因此这里应该要设置为 nouser 啰!
suid/nosuid 具有/不具有suid 权限该文件系统是否允许 SUID 的存在? 如果不是可执行文件放置目录, 也可以设置为 nosuid 来取消这个功能!
defaults同时具有 rw, suid, dev, exec, auto, nouser, async 等参数。 基本上,默认情况使用 defaults 设置即可!
  • 第五栏: 能否被 dump 备份指令作用:
    dump 是一个用来做为备份的指令, 不过现在有太多的备份方案了, 所以这个项目可以不要理会啦! 直接输入 0 就好了!
  • 第六栏: 是否以 fsck 检验扇区:
    早期开机的流程中, 会有一段时间去检验本机的文件系统, 看看文件系统是否完整( clean)
    不过这个方式使用的主要是通过 fsck 去做的, 我们现在用的 xfs 文件系统就没有办法适用, 因为 xfs 会自己进行检验, 不需要额外进行这个动作! 所以直接填 0 就好了。

自动挂载例子:将 /dev/vda4 每次开机都自动挂载到 /data/xfs;

首先,请用 nano 将下面这一行写入 /etc/fstab 最后面中;

[root@study ~]# nano /etc/fstab
UUID="e0fa7252-b374-4a06-987a-3cb14f415488"  /data/xfs  xfs  defaults  0 0

再来看看 /dev/vda4 是否已经挂载, 如果挂载了, 请务必卸载再说!

[root@study ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
/dev/vda4                 1038336   32864   1005472   4% /data/xfs
# 竟然不知道何时被挂载了? 赶紧给他卸载先!
# **因为, 如果要被挂载的文件系统已经被挂载了( 无论挂载在哪个目录) , 那测试就不会进行喔! **

[root@study ~]# umount /dev/vda4

最后测试一下刚刚我们写入 /etc/fstab 的语法有没有错误这点很重要
因为这个文件如果写错了, 则你的 Linux 很可能将无法顺利开机完成! 所以请务必要测试测试!

[root@study ~]# mount -a
[root@study ~]# df /data/xfs

最终有看到 /dev/vda4 被挂载起来的信息才是成功的挂载了

注意:
 
/etc/fstab 是开机时的配置文件, 不过, 实际 filesystem 的挂载是记录到 /etc/mtab 与/proc/mounts 这两个文件当中的。
每次我们在更动 filesystem 的挂载时, 也会同时更动这两个文件
但是, 万一发生你在 /etc/fstab 输入的数据错误, 导致无法顺利开机成功, 而进入单人维护模式当中, 那时候的 / 可是 read only 的状态, 当然你就无法修改 /etc/fstab , 也无法更新 /etc/mtab
可以利用下面指令:

[root@study ~]# mount -n -o remount,rw /
特殊设备 loop 挂载 ( 镜像文件不烧录就挂载使用)

如果有光盘镜像文件, 或者是使用文件作为磁盘的方式时, 那就得要使特别的方法(利用特殊设备)来将他挂载起来, 不需要烧录.=。

Loop设备是一种块设备,但是它并不指向硬盘或者光驱,而是指向一个文件块或者另一种块设备。
loop设备是一种伪设备,是使用文件来模拟块设备的一种技术文件模拟成块设备后, 就像一个磁盘或光盘一样使用。
 
在使用之前,一个 loop 设备必须要和一个文件进行连接。
 
这种结合方式给用户提供了一个替代块特殊文件的接口。因此,如果这个文件包含有一个完整的文件系统那么这个文件就可以像一个磁盘设备一样被 mount 起来
之所以叫loop设备(回环),其实是从文件系统这一层来考虑的,因为这种被 mount 起来的镜像文件它本身也包含有文件系统,通过loop设备把它mount起来,它就像是文件系统之上再绕了一圈的文件系统,所以称为 loop。
 
回环设备( ‘loopback device’)允许用户以一个普通磁盘文件虚拟一个块设备
设想一个磁盘设备,对它的所有读写操作都将被重定向到读写一个名为 disk-image 的普通文件而非操作实际磁盘或分区的轨道和扇区。(当然,disk-image 必须存在于一个实际的磁盘上,而这个磁盘必须比虚拟的磁盘容量更大。)回环设备允许你这样使用一个普通文件。

参考:Loop

挂载光盘/DVD镜像文件

对于镜像文件,直接挂在,不用刻录到光盘再挂载。
例子:挂载CentOS 7.x 的 DVD 镜像文件:


[root@study ~]# ll -h /tmp/CentOS-7.0-1406-x86_64-DVD.iso
-rw-r--r--. 1 root root 3.9G Jul  7  2014 /tmp/CentOS-7.0-1406-x86_64-DVD.iso
# 看到上面的结果吧! 这个文件就是镜像文件, 文件非常的大吧!

[root@study ~]# mkdir /data/centos_dvd
[root@study ~]# mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /data/centos_dvd
[root@study ~]# df /data/centos_dvd
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/loop0       4050860 4050860         0 100% /data/centos_dvd
# 就是这个项目! .iso 镜像文件内的所有数据可以在 /data/centos_dvd 看到!

[root@study ~]# ll /data/centos_dvd
total 607
-rw-r--r--. 1  500  502     14 Jul  5  2014 CentOS_BuildTag <==瞧! 就是DVD的内容
drwxr-xr-x. 3  500  502   2048 Jul  4  2014 EFI
-rw-r--r--. 1  500  502    611 Jul  5  2014 EULA
-rw-r--r--. 1  500  502  18009 Jul  5  2014 GPL
drwxr-xr-x. 3  500  502   2048 Jul  4  2014 images
.....(底下省略).....

[root@study ~]# umount /data/centos_dvd/
# 测试完成! 记得将数据给他卸载! 同时这个镜像文件也被鸟哥删除了...测试机容量不够大!

创建大文件以制作 loop 设备文件

既然能够挂载 DVD 的镜像文件, 那么我们能制作出一个大文件, 然后将这个文件格式化后挂载;
能够帮助我们解决很多系统的分区不良的情况。
 
举例:
如果当初在分区时, 你只有分区出一个根目录, 假设你已经没有多余的容量可以进行额外的分区的! 偏偏根目录的容量还很大! 此时你就能够制作出一个大文件然后将这个文件挂载如此一来感觉上你就多了一个分区。

需求:下面我们在 /srv 下创建一个 512MB 左右的大文件, 然后将这个大文件格式化并且实际挂载

创建个大文件:创建一个空的文件在 /srv/loopdev

[root@study ~]# dd if=/dev/zero of=/srv/loopdev bs=1M count=512
512+0 records in   <==读入 512 笔数据
512+0 records out  <==输出 512 笔数据
536870912 bytes (537 MB) copied, 12.3484 seconds, 43.5 MB/s
# 这个指令的简单意义如下:
# if 	是 input file , 输入文件。 那个 /dev/zero 是会一直输出 0 的设备!
# of 	是 output file , 将一堆零写入到后面接的文件中。
# bs 	是每个 block 大小, 就像文件系统那样的 block 意义;
# count 则是总共几个 bs 的意思。 所以 bs*count 就是这个文件的容量了!

[root@study ~]# ll -h /srv/loopdev
-rw-r--r--. 1 root root 512M Jun 25 19:46 /srv/loopdev

#dd 就好像在叠砖块一样, 将 512 块, 每块 1MB 的砖块堆叠成为一个大文件 ( /srv/loopdev)。
#最终就会出现一个 512MB 的文件

大型文件的格式化:
默认 xfs 不能够格式化文件的, 所以要格式化文件得要加入特别的参数才行。

[root@study ~]# mkfs.xfs -f /srv/loopdev
[root@study ~]# blkid /srv/loopdev
/srv/loopdev: UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" TYPE="xfs"
# 要注意 UUID 的数值, 未来会用到

挂载:
利用 mount 的特殊参数, 那个 -o loop 的参数来处理

[root@study ~]# mount -o loop UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" /mnt
[root@study ~]# df /mnt
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop0        520876 26372    494504   6% /mnt

提示:
通过这个简单的方法, 感觉上你就可以在原本的分区在不更动原有的环境下制作出你想要的分区就是
 
这东西很好用的! 尤其是想要玩 Linux 上面的“虚拟机”的话也就是以一部Linux 主机再切割成为数个独立的主机系统时, 类似 VMware 这类的软件在 Linux 上使用xen 这个软件, 他就可以配合这种 loop device 的文件类型来进行根目录的挂载

自动挂载

[root@study ~]# nano /etc/fstab
/srv/loopdev  /data/file  xfs  defaults,loop   0 0
# 毕竟系统大多仅查询 block device 去找出 UUID 而已, 因此使用文件创建的 filesystem,
# 最好还是使用原本的文件名来处理, 应该比较不容易出现错误讯息的!

[root@study ~]# umount /mnt
[root@study ~]# mkdir /data/file
[root@study ~]# mount -a
[root@study ~]# df /data/file
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop0        520876 26372    494504   6% /data/file

内存交换空间( swap) 之创建

以前的年代因为内存不足, 因此那个可以暂时将内存的程序拿到硬盘中暂放的内存交换空间( swap) 就显的非常的重要;
所以, 早期在安装 Linux 之前, 大家常常会告诉你: 安装时一定需要的两个 partition , 一个是根目录另外一个就是 swap( 内存交换空间)
 
一般来说, 如果硬件的配备资源足够的话, 那么 swap 应该不会被我们的系统所使用到,swap 会被利用到的时刻通常就是实体内存不足的情况
CPU 所读取的数据都来自于内存, 那当内存不足的时候, 为了让后续的程序可以顺利的运行, 因此在内存中暂不使用的程序与数据就会被挪到 swap 中了。 此时内存就会空出来给需要执行的程序载入。 由于 swap 是用磁盘来暂时放置内存中的信息, 所以用到 swap 时,你的主机磁盘灯就会开始闪个不停!

虽然目前( 2015) 主机的内存都很大, 至少都有 4GB 以上啰! 因此在个人使用上, 你不要设置 swap 在你的 Linux 应该也没有什么太大的问题。 不过服务器可就不这么想了~由于你不会知道何时会有大量来自网络的要求, 因此最好还是能够预留一些 swap 来缓冲一下系统的内存用量至少达到“备而不用”的地步

可以使用如下的方式来创建你的 swap :

  • 设置一个 swap partition(使用实体设备)
  • 创建一个虚拟内存的文件(使用Loop设备)

使用实体分区创建swap

创建 swap 分区步骤:

  1. 分区: 先使用 gdisk 在你的磁盘中分区出一个分区给系统作为 swap由于 Linux 的gdisk 默认会将分区的 ID 设置为 Linux 的文件系统, 所以你可能还得要设置一下 systemID 就是了。
  2. 格式化: 利用创建 swap 格式的“mkswap 设备文件名”就能够格式化该分区成为 swap 格式
  3. 使用: 最后将该 swap 设备启动, 方法为: “swapon 设备文件名”。
  4. 观察: 最终通过 free 与 swapon -s 这个指令来观察一下内存的用量

实例:512MB 的磁盘分区做成 swap

进行分区

[root@study ~]# gdisk /dev/vda
Command (? for help): n
Partition number (6-128, default 6):
First sector (34-83886046, default = 69220352) or {+-}size{KMGTP}:
Last sector (69220352-83886046, default = 83886046) or {+-}size{KMGTP}: +512M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8200
Changed type of partition to 'Linux swap'

Command (? for help): p
Number  Start (sector)    End (sector)  Size       Code  Name
   6        69220352        70268927   512.0 MiB   8200  Linux swap  # 重点就是产生这东西西!

Command (? for help): w

Do you want to proceed? (Y/N): y

[root@study ~]# partprobe
[root@study ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda             252:0    0   40G  0 disk
.....(中間省略).....
`-vda6          252:6    0  512M  0 part   # 确定这里是存在的才行
# 结果可以看到我们多了一个 /dev/vda6 可以使用于 swap 

开始创建 swap 格式

[root@study ~]# mkswap /dev/vda6
Setting up swapspace version 1, size = 524284 KiB
no label, UUID=6b17e4ab-9bf9-43d6-88a0-73ab47855f9d
[root@study ~]# blkid /dev/vda6
/dev/vda6: UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d" TYPE="swap"
# 确定格式化成功! 且使用 blkid 确实可以抓到这个设备了喔!

观察与载入

[root@study ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1275140      227244      330124        7804      717772      875536  # [root@study ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1275140      227244      330124        7804      717772      875536  # 实体内存
Swap:       1048572      101340      947232                                      # swap 相关
# 我有 1275140K 的实体内存, 使用 227244K 剩余 330124K , 使用掉的内存有
# 717772K 用在缓冲/高速缓存的用途中。 至于 swap 已经有 1048572K 啰! 这样会看了吧? !

[root@study ~]# swapon /dev/vda6
[root@study ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1275140      227940      329256        7804      717944      874752
Swap:       1572856      101260     1471596   <==有看到增加了沒?

[root@study ~]# swapon -s
Filename                 Type            Size    Used    Priority
/dev/dm-1                partition       1048572 101260  -1
/dev/vda6                partition       524284  0       -2
# 上面列出目前使用的 swap 设备有哪些的意思!

[root@study ~]# nano /etc/fstab
UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d"  swap  swap  defaults  0  0
# 当然要写入配置文件, 只不过不是文件系统, 所以没有挂载点! 第二个字段写入 swap 即可。

使用文件创建swap(Loop设备)

如果是在实体分区无法支持的环境下, 可以使用Loop设备。
与实体分区不一样的, 这个方法只是利用 dd 去创建一个大文件而已;

例子:通过文件创建的方法创建一个 128 MB 的内存交换空间。

使用 dd 这个指令来新增一个 128MB 的文件在 /tmp 下面

[root@study ~]# dd if=/dev/zero of=/tmp/swap bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1.7066 seconds, 78.6 MB/s

[root@study ~]# ll -h /tmp/swap
-rw-r--r--. 1 root root 128M Jun 26 17:47 /tmp/swap

使用 mkswap 将 /tmp/swap 这个文件格式化为 swap 的文件格式

[root@study ~]# mkswap /tmp/swap
Setting up swapspace version 1, size = 131068 KiB
no label, UUID=4746c8ce-3f73-4f83-b883-33b12fa7337c
# 这个指令下达时请“特别小心”, 因为下错字符控制, 将可能使您的文件系统挂掉!

使用 swapon 来将 /tmp/swap 启动


[root@study ~]# swapon /tmp/swap
[root@study ~]# swapon -s
Filename            Type            Size    Used    Priority
/dev/dm-1           partition       1048572 100380  -1
/dev/vda6           partition       524284  0       -2
/tmp/swap           file            131068  0       -3

使用 swapoff 关掉 swap file, 并设置自动启用

[root@study ~]# nano /etc/fstab
/tmp/swap  swap  swap  defaults  0  0
# 为何这里不要使用 UUID 呢? 这是因为系统仅会查询区块设备 ( block device) 不会查询文件!
# 所以, 这里千万不要使用 UUID, 不然系统会查不到喔!

[root@study ~]# swapoff /tmp/swap /dev/vda6
[root@study ~]# swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-1                               partition       1048572 100380  -1
# 确定已经回复到原本的状态了! 然后准备来测试! !

[root@study ~]# swapon -a
[root@study ~]# swapon -s
# 最终你又会看正确的三个 swap 出现啰! 这也才确定你的 /etc/fstab 设置无误!

因为系统仅会查询区块设备 ( block device) 不会查询文件,所以设置启动时使用设备名;

注意:
针对服务器或者是工作站这些常年上线的系统来说的话, 那么, 无论如何, swap 还是需要创建的。
 
因为 swap 主要的功能是当实体内存不够时, 则某些在内存当中所占的程序会暂时被移动到swap 当中, 让实体内存可以被需要的程序来使用
另外, 如果你的主机支持电源管理模式,也就是说, 你的 Linux 主机系统可以进入“休眠”模式的话, 那么, 运行当中的程序状态则会被纪录到 swap 去, 以作为“唤醒”主机的状态依据
另外, 有某些程序在运行时本来就会利用swap 的特性来存放一些数据段
所以, swap 来是需要创建的只是不需要太大

文件系统的特殊观察与操作

磁盘空间之浪费问题

EXT2 data block 介绍中谈到了一个 block 只能放置一个文件, 因此太多小文件将会浪费非常多的磁盘容量
但你有没有注意到, 整个文件系统中包括 superblock, inodetable 与其他中介数据等其实都会浪费磁盘容量
 
当你使用 ls -l 去查询某个目录下的数据时, 第一行都会出现一个“total”的字样;
那就是该目录下的所有数据所耗用的实际 block 数量 *block 大小的值


[root@study ~]# ll -sh
total 12K
4.0K -rw-------. 1 root root 1.8K May  4 17:57 anaconda-ks.cfg
4.0K -rw-r--r--. 2 root root  451 Jun 10  2014 crontab
   0 lrwxrwxrwx. 1 root root   12 Jun 23 22:31 crontab2 -> /etc/crontab
4.0K -rw-r--r--. 1 root root 1.9K May  4 18:01 initial-setup-ks.cfg
   0 -rw-r--r--. 1 root root    0 Jun 16 01:11 test1
   0 drwxr-xr-x. 2 root root    6 Jun 16 01:11 test2
   0 -rw-rw-r--. 1 root root    0 Jun 16 01:12 test3
   0 drwxrwxr-x. 2 root root    6 Jun 16 01:12 test4

从上面的特殊字体部分, 那就是每个文件所使用掉 block 的容量!
举例来说, 那个 crontab 虽然仅有 451Bytes , 不过他却占用了整个 block ( 每个 block 为 4K) , 所以将所有的文件的所有的 block 加总就得到 12KBytes 那个数值了。
如果计算每个文件实际容量的加总结果,其实只有不到 5K 而已
所以, 这样就耗费掉好多容量;未来大家在讨论小磁盘、 大磁盘, 文件大小的损耗时, 要回想到这个区块。

利用 GNU 的 parted 进行分区行为( Optional)

虽然你可以使用 gdisk/fdisk 很快速的将你的分区切割, 不过 gdisk 主要针对 GPTfdisk 主要支持 MBR , 对 GPT 的支持还不够
所以使用不同的分区时, 得要先查询到正确的分区表才能用适合的指令。
可以使用指令parted这个同时支持的指令。

parted 可以直接在一行命令行就完成分区, 是一个非常好用的指令。 它常用的语法如下:

[root@study ~]# parted [设备] [指令 [参数]]
选项与参数:
指令功能:
          新增分区:mkpart [primary|logical|extended] [ext4|vfat|xfs] 開始 結束
          显示分区:print
          删除分区:rm [partition]

范例一: 以 parted 列出目前本机的分区表数据
[root@study ~]# parted /dev/vda print
Model: Virtio Block Device (virtblk)         <==磁盘接口与型号
Disk /dev/vda: 42.9GB                        <==磁盘文件名与容量
Sector size (logical/physical): 512B/512B    <==磁盘文件名与容量
Partition Table: gpt                         <==磁盘文件名与容量
Disk Flags: pmbr_boot

Number  Start   End     Size    File system     Name                  Flags
 1      1049kB  3146kB  2097kB                                        bios_grub
 2      3146kB  1077MB  1074MB  xfs
 3      1077MB  33.3GB  32.2GB                                        lvm
 4      33.3GB  34.4GB  1074MB  xfs             Linux filesystem
 5      34.4GB  35.4GB  1074MB  ext4            Microsoft basic data
 6      35.4GB  36.0GB  537MB   linux-swap(v1)  Linux swap
[  1 ]  [  2 ]  [  3  ] [  4  ] [  5  ]         [  6  ]

字段说明:

  1. Number: 这个就是分区的号码啦! 举例来说, 1号代表的是 /dev/vda1 的意思;
  2. Start: 分区的起始位置在这颗磁盘的多少 MB 处? 有趣吧! 他以容量作为单位喔!
  3. End: 此分区的结束位置在这颗磁盘的多少 MB 处?
  4. Size: 由上述两者的分析, 得到这个分区有多少容量;
  5. File system: 分析可能的文件系统类型为何的意思!
  6. Name: 就如同 gdisk 的 System ID 之意。

例子:利用parted进行MBR和 GPT 分区表的互换;

范例二: 将 /dev/sda 这个原本的 MBR 分区表变成 GPT 分区表! ( 危险! 危险! 勿乱搞! 无法复原! )
[root@study ~]# parted /dev/sda print
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sda: 2148MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos    # 确实显示的是 MBR 的 msdos 格式喔!

[root@study ~]# parted /dev/sda mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on 
this disk will be lost. Do you want to continue?
Yes/No? y

[root@study ~]# parted /dev/sda print
# 你应该就会看到变成 gpt 的模样! 只是...后续的分区就全部都死掉了!

创建一个全新的分区,再次的创建一个 512MB 的分区来格式化为 vfat,且挂载于 /data/win

范例三: 创建一个约为 512MB 容量的分区
[root@study ~]# parted /dev/vda print
.....(前面省略).....
Number  Start   End     Size    File system     Name                  Flags
.....(中間省略).....
 6      35.4GB  36.0GB  537MB   linux-swap(v1)  Linux swap  # 要先找出来下一个分区的起始点

[root@study ~]# parted /dev/vda mkpart primary fat32 36.0GB 36.5GB
# 由于新的分区的起始点在前一个分区的后面, 所以当然要先找出前面那个分区的 End 位置!
# 然后再请参考 mkpart 的指令功能, 就能够处理好相关的动作!
[root@study ~]# parted /dev/vda print
.....(前面省略).....
Number  Start   End     Size    File system     Name                  Flags
 7      36.0GB  36.5GB  522MB                   primary

[root@study ~]# partprobe
[root@study ~]# lsblk /dev/vda7
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda7 252:7    0  498M  0 part      # 要确定它是真的存在才行!

[root@study ~]# mkfs -t vfat /dev/vda7
[root@study ~]# blkid /dev/vda7
/dev/vda7: SEC_TYPE="msdos" UUID="6032-BF38" TYPE="vfat"

[root@study ~]# nano /etc/fstab
UUID="6032-BF38"  /data/win  vfat  defaults   0  0

[root@study ~]# mkdir /data/win
[root@study ~]# mount -a
[root@study ~]# df /data/win
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/vda7         509672     0    509672   0% /data/win

注意:
事实上, 你应该使用 gdisk 来处理 GPT 分区
不过, 某些特殊时刻, 例如你要自己写一只脚本, 让你的分区全部一口气创建, 不需要 gdisk 一条一条指令去进行时, 那么 parted就非常有效果。因为他可以直接进行 partition 而不需要跟用户互动;这就是它的最大好处。

文件与文件系统的压缩 打包与备份

压缩文件的用途与技术

因为这些比较大型的文件通过所谓的文件压缩技术之后, 可以将他的磁盘使用量降低, 可以达到减低文件大小的效果。 此外, 有的压缩程序还可以进行容量限制, 使一个大型文件可以分区成为数个小型文件, 以方便携带和传输。

文件压缩原理:
简单的说, 你可以将他想成, 其实文件里面有相当多的“空间”存在, 并不是完全填满的,而“压缩”的技术就是将这些“空间”填满, 以让整个文件占用的容量下降。
不过, 这些“压缩过的文件”并无法直接被我们的操作系统所使用的, 因此, 若要使用这些被压缩过的文件数据,则必须将他“还原”回来未压缩前的模样, 那就是所谓的“解压缩”。
而至于压缩后与压缩的文件所占用的磁盘空间大小, 就可以被称为是“压缩比”

Linux 系统常见的压缩指令

这是因为 Linux 支持的压缩指令非常多, 且不同的指令所用的压缩技术并不相同, 当然彼此之间可能就无法互通压缩/解压缩文件
 
虽然 Linux文件的属性基本上是与文件名没有绝对关系的, 但是为了帮助我们人类小小的脑袋瓜子, 所以适当的扩展名还是必要

常见的压缩文件扩展名:

  • *.Z compress 程序压缩的文件;
  • *.zip zip 程序压缩的文件;
  • *.gz gzip 程序压缩的文件;
  • *.bz2 bzip2 程序压缩的文件;
  • *.xz xz 程序压缩的文件;
  • *.tar tar 程序打包的数据, 并没有压缩过;
  • *.tar.gz tar 程序打包的文件, 其中并且经过 gzip 的压缩
  • *.tar.bz2 tar 程序打包的文件, 其中并且经过 bzip2 的压缩
  • *.tar.xz tar 程序打包的文件, 其中并且经过 xz 的压缩

大多针对单个文件(或目录)的压缩指令gzip,bzip2 ,xz ,zip ,compress
Linux上常见的压缩指令就是 gzip, bzip2 以及最新的 xz , 至于 compress (不支持目录压缩)已经退流行了。
为了支持 windows 常见的 zip, 其实 Linux 也早就有 zip (不支持目录压缩)指令
gzip 是由 GNU 计划所开发出来的压缩指令, 该指令已经取代了 compress
后来 GNU 又开发出 bzip2xz 这几个压缩比更好的压缩指令。
以上指令通常仅能针对一个文件(或目录)来压缩与解压缩,对目录压缩也仅是压缩目录里的文件,且不具备打包功能
 
针对文件和目录压缩以及打包的指令tar
这个 tar 可以将很多文件“打包”成为一个文件甚至是目录也可以这么玩不过, 单纯的 tar功能仅是“打包”而已, 亦即是将很多文件集结成为一个文件, 事实上, 他并没有提供压缩的功能, 后来, GNU 计划中, 将整个 tar 与压缩的功能结合在一起, 如此一来提供使用者更方便并且更强大的压缩与打包功能。

gzip, zcat/zmore/zless/zgrep

目前 gzip 可以解开 compress, zip 与 gzip 等软件所压缩的文件。 至于 gzip 所创建的压缩文件为 *.gz 的文件名。

[dmtsai@study ~]$ gzip [-cdtv#] 文件名
[dmtsai@study ~]$ zcat 文件名.gz
選項與參數:
选项与参数:
-c	 : 将压缩的数据输出到屏幕上, 可通过数据流重导向来处理;
-d	 : 解压缩的参数;
-t	 : 可以用来检验一个压缩文件的一致性~看看文件有无错误;
-v	 : 可以显示出原文件/压缩文件的压缩比等信息;
-#	 : # 为数字的意思, 代表压缩等级, -1 最快, 但是压缩比最差、 -9 最慢, 但是压缩比最好! 默认是 -6

范例一: 找出 /etc 下面 ( 不含子目录) 容量最大的文件, 并将它复制到 /tmp , 然后以 gzip 压缩
[dmtsai@study ~]$ ls -ldSr /etc/*   # 忘记选项意义? 请自行 man 啰!
.....(前面省略).....
-rw-r--r--.  1 root root    25213 Jun 10  2014 /etc/dnsmasq.conf
-rw-r--r--.  1 root root    69768 May  4 17:55 /etc/ld.so.cache
-rw-r--r--.  1 root root   670293 Jun  7  2013 /etc/services

[dmtsai@study ~]$ cd /tmp 
[dmtsai@study tmp]$ cp /etc/services .
[dmtsai@study tmp]$ gzip -v services
services:        79.7% -- replaced with services.gz
[dmtsai@study tmp]$ ll /etc/services /tmp/services*
-rw-r--r--. 1 root   root   670293 Jun  7  2013 /etc/services
-rw-r--r--. 1 dmtsai dmtsai 136088 Jun 30 18:40 /tmp/services.gz

注意:
当你使用 gzip 进行压缩时, 在默认的状态下原本的文件会被压缩成为 .gz 的文件名, 原始文件就不再存在了。
 
此外, 使用 gzip 压缩的文件在 Windows 系统中, 竟然可以被 WinRAR/7zip 这个软件解压缩。

范例二: 由于 services 是文本文件, 请将范例一的压缩文件的内容读出来!
[dmtsai@study tmp]$ zcat services.gz
# 由于 services 这个原本的文件是是文本文件, 因此我们可以尝试使用 zcat/zmore/zless 去读取!
# 此时屏幕上会显示 servcies.gz 解压缩之后的原始文件内容!

范例三: 将范例一的文件解压缩
[dmtsai@study tmp]$ gzip -d services.gz
# 鸟哥不要使用 gunzip 这个指令, 不好背! 使用 gzip -d 来进行解压缩!
# 与 gzip 相反, gzip -d 会将原本的 .gz 删除, 回复到原本的 services 文件。

范例四: 将范例三解开的 services 用最佳的压缩比压缩, 并保留原本的文件
[dmtsai@study tmp]$ gzip -9 -c services > services.gz

范例五: 由范例四再次创建的 services.gz 中, 找出 http 这个关键字在哪几行?
[dmtsai@study tmp]$ zgrep -n 'http' services.gz
14:#       http://www.iana.org/assignments/port-numbers
89:http            80/tcp          www www-http    # WorldWideWeb HTTP
90:http            80/udp          www www-http    # HyperText Transfer Protocol
.....(底下省略).....

范例四的重点在那个 -c 与 > 的使用-c 可以将原本要转成压缩文件的数据内容, 将它变成文字类型从屏幕输出, 然后我们可以通过大于 ( >) 这个符号, 将原本应该由屏幕输出的数据, 转成输出到文件而不是屏幕, 所以就能够创建出压缩挡了。 只是文件名也要自己写, 当然最好还是遵循 gzip 的压缩文件名要求较佳。
 
cat/more/less 可以使用不同的方式来读取纯文本文件, 那个 zcat/zmore/zless 则可以对应于cat/more/less 的方式来读取纯文本文件被压缩后的压缩文件
 
由于 gzip 这个压缩指令主要想要用来取代 compress 的, 所以不但 compress 的压缩文件可以使用 gzip 来解开同时 zcat这个指令可以同时读取 compress 与 gzip 的压缩文件
如果你还有备份数据使用的是 compress 创建出来的 .Z 文件, 那也无须担心, 使用 znew 可以将该文件转成 gzip 的格式。
 
另外, 如果你还想要从文字压缩文件当中找数据的话可以通过 egrep 来搜寻关键字而不需要将压缩文件解开才以 grep 进行。 这对查询备份中的文本文件数据相当有用。

bzip2, bzcat/bzmore/bzless/bzgrep

若说 gzip 是为了取代 compress 并提供更好的压缩比而成立的, 那么 bzip2 则是为了取代gzip 并提供更佳的压缩比而来的
bzip2 的用法几乎与 gzip 相同:

[dmtsai@study ~]$ bzip2 [-cdkzv#] 文件名
[dmtsai@study ~]$ bzcat 文件名.bz2
選項與參數:
选项与参数:
-c	 : 将压缩的过程产生的数据输出到屏幕上!
-d	 : 解压缩的参数
-k	 : 保留原始文件, 而不会删除原始的文件喔!
-z	 : 压缩的参数 ( 默认值, 可以不加)
-v	 : 可以显示出原文件/压缩文件的压缩比等信息;
-#	 : 与 gzip 同样的, 都是在计算压缩比的参数, -9 最佳, -1 最快!

范例一: 将刚刚 gzip 范例留下来的 /tmp/services 以 bzip2 压缩
[dmtsai@study tmp]$ bzip2 -v services
  services:  5.409:1,  1.479 bits/byte, 81.51% saved, 670293 in, 123932 out.
[dmtsai@study tmp]$ ls -l services*
-rw-r--r--. 1 dmtsai dmtsai 123932 Jun 30 18:40 services.bz2
-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz
# 此时 services 会变成 services.bz2 之外, 你也可以发现 bzip2 的压缩比要较 gzip 好喔! !
# 压缩率由 gzip 的 79% 提升到 bzip2 的 81% 哩!

范例二: 将范例一的文件内容读出来!
[dmtsai@study tmp]$ bzcat services.bz2

范例三: 将范例一的文件解压缩
[dmtsai@study tmp]$ bzip2 -d services.bz2

范例四: 将范例三解开的 services 用最佳的压缩比压缩, 并保留原本的文件
[dmtsai@study tmp]$ bzip2 -9 -c services > services.bz2

xz, xzcat/xzmore/xzless/xzgrep

虽然 bzip2 已经具有很棒的压缩比,后来还推出了 xz 这个压缩比更高的软件!
这个软件的用法也跟 gzip/bzip2 几乎一模一样。

[dmtsai@study ~]$ xz [-dtlkc#] 文件名
[dmtsai@study ~]$ xcat 文件名.xz
选项与参数:
-d  : 就是解压缩啊!
-t  : 测试压缩文件的完整性, 看有没有错误
-l  : 列出压缩文件的相关信息
-k  : 保留原本的文件不删除~
-c  : 同样的, 就是将数据由屏幕上输出的意思!
-#  : 同样的, 也有较佳的压缩比的意思!

范例一: 将刚刚由 bzip2 所遗留下来的 /tmp/services 通过 xz 来压缩!
[dmtsai@study tmp]$ xz -v services
services (1/1)
  100 %        97.3 KiB / 654.6 KiB = 0.149

[dmtsai@study tmp]$ ls -l services*
-rw-rw-r--. 1 dmtsai dmtsai 123932 Jun 30 19:09 services.bz2
-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz
-rw-r--r--. 1 dmtsai dmtsai  99608 Jun 30 18:40 services.xz
# 各位观众! 看到没有啊! ! 容量又进一步下降的更多耶! 好棒的压缩比!

范例二: 列出这个压缩文件的信息, 然后读出这个压缩文件的内容
[dmtsai@study tmp]$ xz -l services.xz
Strms  Blocks   Compressed Uncompressed  Ratio  Check   Filename
    1       1     97.3 KiB    654.6 KiB  0.149  CRC64   services.xz
# 竟然可以列出这个文件的压缩前后的容量, 真是太人性化了! 这样观察就方便多了!

[dmtsai@study tmp]$ xzcat services.xz

范例三: 将他解压缩吧!
[dmtsai@study tmp]$ xz -d services.xz

范例四: 保留原文件的文件名, 并且创建压缩文件!
[dmtsai@study tmp]$ xz -k services

虽然 xz 这个压缩比真的好太多太多了;不过, xz最大的问题是…时间花太久

总结:
压缩时间:xz > bzip2 > gzip
如果你并不觉得时间是你的成本考虑, 那么使用 xz 会比较好;
如果时间是你的重要成本, 那么 gzip 恐怕是比较适合的压缩软件。

打包指令: tar

以上指令大多仅能针对单一文件来进行压缩虽然 gzip, bzip2, xz 也能够针对目录来进行压缩, 不过, 这两个指令对目录的压缩指的是“将目录内的所有文件 “分别” 进行压缩”的动作。而不像在 Windows 的系统, 可以使用类似 WinRAR 这一类的压缩软件来将好多数据“包成一个文件”的样式。
 
tar 可以将多个目录或文件打包成一个大文件同时还可以通过 gzip/bzip2/xz 的支持, 将该文件同时进行压缩
更有趣的是, 由于 tar 的使用太广泛了, 目前 Windows 的 WinRAR 也支持 .tar.gz文件名的解压缩

tar

常用参数如下:

[dmtsai@study ~]$ tar [-z|-j|-J] [cv] [-f 待创建的新文件名] filename... <==打包与压缩
[dmtsai@study ~]$ tar [-z|-j|-J] [tv] [-f 既有的 tar文件名]             <==察看文件名
[dmtsai@study ~]$ tar [-z|-j|-J] [xv] [-f 既有的 tar文件名] [-C 目录]   <==解压缩
选项与参数:
-c	 : 创建打包文件, 可搭配 -v 来察看过程中被打包的文件名( filename)
-t	 : 察看打包文件的内容含有哪些文件名, 重点在察看“文件名”就是了;
-x	 : 解打包或解压缩的功能, 可以搭配 -C ( 大写) 在特定目录解开
特别留意的是, -c, -t, -x 不可同时出现在一串命令行中。

-z	 : 通过 gzip 的支持进行压缩/解压缩: 此时文件名最好为 *.tar.gz
-j	 : 通过 bzip2 的支持进行压缩/解压缩: 此时文件名最好为 *.tar.bz2
-J	 : 通过 xz 的支持进行压缩/解压缩: 此时文件名最好为 *.tar.xz
特别留意, -z, -j, -J 不可以同时出现在一串命令行中

-v	 : 在压缩/解压缩的过程中, 将正在处理的文件名显示出来!
-f filename: -f 后面要立刻接要被处理的文件名! 建议 -f 单独写一个选项啰! ( 比较不会忘记)
-C 目录	   : 这个选项用在解压缩, 若要在特定目录解压缩, 可以使用这个选项。

其他后续练习会使用到的选项介绍:
-p( 小写)   : 保留备份数据的原本权限与属性, 常用于备份( -c) 重要的配置文件
-P( 大写)   : 保留绝对路径, 亦即允许备份数据中含有根目录存在之意;
--exclude=FILE: 在压缩的过程中, 不要将 FILE 打包!

其实最简单的使用 tar 就只要记忆下面的方式:

  • 压 缩 : tar -jcv -f filename.tar.bz2 要被压缩的文件或目录名称
  • 查 询 : tar -jtv -f filename.tar.bz2
  • 解压缩: tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录
     

如果不加 [-z|-j|-J] 的话, 文件名最好取为 .tar 即可。
如果是 -j 选项, 代表有 bzip2 的支持, 因此文件名最好就取为 .tar.bz2 , 因为 bzip2 会产生 .bz2 的扩展名之故;如果是加上了 -z 的 gzip 的支持, 那文件名最好取为 *.tar.gz
 
另外值得一提的是, tar 打包出来的文件有没有进行压缩对文件称呼不同;
如果 仅是打包 而已:这个文件我们称呼为 tarfile
如果还有 进行压缩 : 我们就称呼为 tarball

XFS 文件系统的备份与还原

使用 tar 通常是针对目录树系统来进行备份的工作
如果想要针对整个文件系统来进行备份与还原,需要其他指令;
CentOS 7 已经使用 XFS 文件系统作为默认值, 针对XFS ,可以使用 xfsdumpxfsrestore

XFS 文件系统备份 xfsdump

备份指令:xfsdump;
他除了可以进行文件系统的完整备份 ( full backup) 之外, 还可以进行累积备份 ( Incremental backup) .
 
累计备份:
你在第一次使用 xfsdump 进行完整备份后, 等过一段时间的文件系统自然运行后, 你再进行第二次 xfsdump 时, 就可以选择累积备份了! 此时新备份的数据只会记录与第一次完整备份所有差异的文件而已

使用 xfsdump 时, 请注意下面的限制:

  • xfsdump 不支持没有挂载的文件系统备份! 所以只能备份已挂载的!
  • xfsdump 必须使用 root 的权限才能操作 ( 涉及文件系统的关系)
  • xfsdump 只能备份 XFS 文件系统
  • xfsdump 备份下来的数据 ( 文件或储存媒体) 只能让 xfsrestore 解析
  • xfsdump 是通过文件系统的 UUID 来分辨各个备份文件的, 因此不能备份两个具有相同UUID 的文件系统

xfsdump 的选项虽然非常的繁复, 不过如果只是想要简单的操作时, 您只要记得下面的几个选项就很够用了

[root@study ~]# xfsdump [-L S_label] [-M M_label] [-l #] [-f 备份文件] 待备份数据
[root@study ~]# xfsdump -I
选项与参数:
-L : xfsdump 会纪录每次备份的 session 标头, 这里可以填写针对此文件系统的简易说明
-M : xfsdump 可以纪录储存媒体的标头, 这里可以填写此媒体的简易说明
-l : 是 L 的小写, 就是指定等级~有 0~9 共 10 个等级喔! ( 默认为 0, 即完整备份)
-f : 有点类似 tar 啦! 后面接产生的文件, 亦可接例如 /dev/st0 设备文件名或其他一般文件文件名等
-I : 从 /var/lib/xfsdump/inventory 列出目前备份的信息状态

注意:
特别注意, xfsdump 默认仅支持文件系统的备份并不支持特定目录的备份所以你不能用xfsdump 去备份 /etc 。 因为 /etc 从来就不是一个独立的文件系统。

用 xfsdump 备份完整的文件系统

案例:备份/boot 分区文件系统

# 1. 先确定 /boot 是独立的文件系统喔!
[root@study ~]# df -h /boot
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda2      1014M  131M  884M  13% /boot      # 挂载 /boot 的是 /dev/vda 设备!
# 看! 确实是独立的文件系统喔! /boot 是挂载点!

# 2. 将完整备份的文件名记录成为 /srv/boot.dump :
[root@study ~]# xfsdump -l 0 -L boot_all -M boot_all -f /srv/boot.dump /boot
xfsdump -l 0 -L boot_all -M boot_all -f /srv/boot.dump /boot
xfsdump: using file dump (drive_simple) strategy
xfsdump: version 3.1.4 (dump format 3.0) - type ^C for status and control
xfsdump: level 0 dump of study.centos.vbird:/boot              # 开始备份本机/boot系统
xfsdump: dump date: Wed Jul  1 18:43:04 2015                   # 备份的时间
xfsdump: session id: 418b563f-26fa-4c9b-98b7-6f57ea0163b1      # 这次dump的ID
xfsdump: session label: "boot_all"                             # 简单给予一个名字记忆
xfsdump: ino map phase 1: constructing initial dump list       # 开始备份程序
xfsdump: ino map phase 2: skipping (no pruning necessary)
xfsdump: ino map phase 3: skipping (only one dump stream)
xfsdump: ino map construction complete
xfsdump: estimated dump size: 103188992 bytes
xfsdump: creating dump session media file 0 (media 0, file 0)
xfsdump: dumping ino map
xfsdump: dumping directories
xfsdump: dumping non-directory files
xfsdump: ending media file
xfsdump: media file size 102872168 bytes
xfsdump: dump size (non-dir files) : 102637296 bytes
xfsdump: dump complete: 1 seconds elapsed
xfsdump: Dump Summary:
xfsdump:   stream 0 /srv/boot.dump OK (success)
xfsdump: Dump Status: SUCCESS
# 在指令的下达方面, 你也可以不加 -L 及 -M 的, 只是那就会进入互动模式, 要求你 enter!
# 而执行 xfsdump 的过程中会出现如上的一些讯息, 您可以自行仔细的观察!

[root@study ~]# ll /srv/boot.dump
-rw-r--r--. 1 root root 102872168 Jul  1 18:43 /srv/boot.dump

[root@study ~]# ll /var/lib/xfsdump/inventory
-rw-r--r--. 1 root root 5080 Jul  1 18:43 506425d2-396a-433d-9968-9b200db0c17c.StObj
-rw-r--r--. 1 root root  312 Jul  1 18:43 94ac5f77-cb8a-495e-a65b-2ef7442b837c.InvIndex
-rw-r--r--. 1 root root  576 Jul  1 18:43 fstab
# 使用了 xfsdump 之后才会有上述 /var/lib/xfsdump/inventory 内的文件产生喔!

这样很简单的就创建起来 /srv/boot.dump 文件, 该文件将整个 /boot/ 文件系统都备份下来了! 并且将备份的相关信息 ( 文件系统/时间/session ID等等) 写入/var/lib/xfsdump/inventory 中, 准备让下次备份时可以作为一个参考依据。

用 xfsdump 进行累积备份 ( Incremental backups)

你一定得要进行过完整备份( -l 0) 才能够继续其他累积备份 ( -l 1~9)

# 0. 看一下有没有任何文件系统被 xfsdump 过的数据?
[root@study ~]# xfsdump -I
file system 0:
    fs id:          94ac5f77-cb8a-495e-a65b-2ef7442b837c
    session 0:
        mount point:    study.centos.vbird:/boot
        device:         study.centos.vbird:/dev/vda2
        time:           Wed Jul  1 18:43:04 2015
        session label:  "boot_all"
        session id:     418b563f-26fa-4c9b-98b7-6f57ea0163b1
        level:          0
        resumed:        NO
        subtree:        NO
        streams:        1
        stream 0:
                pathname:       /srv/boot.dump
                start:          ino 132 offset 0
                end:            ino 2138243 offset 0
                interrupted:    NO
                media files:    1
                media file 0:
                        mfile index:    0
                        mfile type:     data
                        mfile size:     102872168
                        mfile start:    ino 132 offset 0
                        mfile end:      ino 2138243 offset 0
                        media label:    "boot_all"
                        media id:       a6168ea6-1ca8-44c1-8d88-95c863202eab
xfsdump: Dump Status: SUCCESS
# 我们可以看到目前仅有一个 session 0 的备份数据而已! 而且是 level 0 喔!

# 1. 先惡搞一下,建立一個大約 10 MB 的檔案在 /boot 內:
[root@study ~]# dd if=/dev/zero of=/boot/testing.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.166128 seconds, 63.1 MB/s

# 2. 开始创建差异备份文件, 此时我们使用 level 1 吧:
[root@study ~]# xfsdump -l 1 -L boot_2 -M boot_2 -f /srv/boot.dump1 /boot
....(中間省略)....

[root@study ~]# ll /srv/boot*
-rw-r--r--. 1 root root 102872168 Jul  1 18:43 /srv/boot.dump
-rw-r--r--. 1 root root  10510952 Jul  1 18:46 /srv/boot.dump1
# 看看文件大小, 岂不是就是刚刚我们所创建的那个大文件的容量吗?

# 3. 最后再看一下是否有记录 level 1 备份的时间点呢?
[root@study ~]# xfsdump -I
file system 0:
    fs id:          94ac5f77-cb8a-495e-a65b-2ef7442b837c
    session 0:
        mount point:    study.centos.vbird:/boot
        device:         study.centos.vbird:/dev/vda2
....(中間省略)....

    session 1:
        mount point:    study.centos.vbird:/boot
        device:         study.centos.vbird:/dev/vda2
        time:           Wed Jul  1 18:46:21 2015
        session label:  "boot_2"
        session id:     c71d1d41-b3bb-48ee-bed6-d77c939c5ee8
        level:          1
        resumed:        NO
        subtree:        NO
        streams:        1
        stream 0:
                pathname:       /srv/boot.dump1
                start:          ino 455518 offset 0
....(底下省略)....

XFS 文件系统还原 xfsrestore

备份文件就是在急用时可以回复系统的重要数据;
xfsdump 的复原使用的是 xfsrestore 这个指令。

[root@study ~]# xfsrestore -I                                       <==用来察看备份文件数据
[root@study ~]# xfsrestore [-f 备份文件] [-L S_label] [-s] 待复原目录 <==单一文件全系统复原
[root@study ~]# xfsrestore [-f 备份文件] -r 待复原目录              <==通过累积备份文件来复原系统
[root@study ~]# xfsrestore [-f 备份文件] -i 待复原目录                <==进入互动模式
选项与参数:
-I	 : 跟 xfsdump 相同的输出! 可查询备份数据, 包括 Label 名称与备份时间等
-f	 : 后面接的就是备份文件! 企业界很有可能会接 /dev/st0 等磁带机! 我们这里接文件名!
-L	 : 就是 Session 的 Label name 喔! 可用 -I 查询到的数据, 在这个选项后输入!
-s	 : 需要接某特定目录, 亦即仅复原某一个文件或目录之意!
-r	 : 如果是用文件来储存备份数据, 那这个就不需要使用。 如果是一个磁带内有多个文件,
需要这东西来达成累积复原
-i : 进入互动模式, 进阶管理员使用的! 一般我们不太需要操作它!

用 xfsrestore 观察 xfsdump 后的备份数据内容

要找出 xfsdump 的内容就使用 xfsrestore -I 来查阅即可;
这个查询重点找出到底哪个文件是哪个挂载点而该备份文件又是什么 level 等等的。

[root@study ~]# xfsrestore -I 
file system 0:
    fs id:          94ac5f77-cb8a-495e-a65b-2ef7442b837c
    session 0:
        mount point:    study.centos.vbird:/boot
        device:         study.centos.vbird:/dev/vda2
        time:           Wed Jul  1 18:43:04 2015
        session label:  "boot_all"
        session id:     418b563f-26fa-4c9b-98b7-6f57ea0163b1
        level:          0
                pathname:       /srv/boot.dump
                        mfile size:     102872168
                        media label:    "boot_all"
    session 1:
        mount point:    study.centos.vbird:/boot
        device:         study.centos.vbird:/dev/vda2
        time:           Wed Jul  1 18:46:21 2015
        session label:  "boot_2"
        session id:     c71d1d41-b3bb-48ee-bed6-d77c939c5ee8
        level:          1
                pathname:       /srv/boot.dump1
                        mfile size:     10510952
                        media label:    "boot_2"
xfsrestore: Restore Status: SUCCESS
# 鸟哥已经将不重要的项目删除了, 所以上面的输出是经过经简化的结果!
# 我们可以看到这个文件系统是 /boot 载点, 然后有两个备份, 一个 level 0 一个 level 1。
# 也看到这两个备份的数据他的内容大小! 更重要的, 就是那个 session label 喔!

简单复原 level 0 的文件系统

案例:将 /boot 整个复原到最原本的状态:
只要知道想要被复原的那个文件, 以及该文件的 session label name, 就可以复原;
从上面的观察已经知道 level 0 的 session label 是“boot_all”

# 1. 直接将数据给它覆盖回去即可!
[root@study ~]# xfsrestore -f /srv/boot.dump -L boot_all /boot
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.4 (dump format 3.0) - type ^C for status and control
xfsrestore: using online session inventory
xfsrestore: searching media for directory dump
xfsrestore: examining media file 0
xfsrestore: reading directories
xfsrestore: 8 directories and 327 entries processed
xfsrestore: directory post-processing
xfsrestore: restoring non-directory files
xfsrestore: restore complete: 1 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore:   stream 0 /srv/boot.dump OK (success)  # 是否是正确的文件啊?
xfsrestore: Restore Status: SUCCESS

# 2. 将备份数据在 /tmp/boot 下面解开!
[root@study ~]# mkdir /tmp/boot
[root@study ~]# xfsrestore -f /srv/boot.dump -L boot_all /tmp/boot
[root@study ~]# du -sm /boot /tmp/boot
109     /boot
99      /tmp/boot
# 咦! 两者怎么大小不一致呢? 没关系! 我们来检查看看!

[root@study ~]# diff -r /boot /tmp/boot
Only in /boot: testing.img
# 看吧! 原来是 /boot 我们有增加过一个文件啦!

因为原本 /boot 里面的东西我们没有删除, 直接复原的结果就是: “同名的文件会被覆盖, 其他系统内新的文件会被保留”
所以, 那个 /boot/testing.img 就会一直在里头~如果备份的目的地是新的位置, 当然就只有原本备份的数据而已;
diff -r 可以比较两个目录内的文件差异;通过该指令我们可以找到两个目录的差异处。

# 3. 仅复原备份文件内的 grub2 到 /tmp/boot2/ 里头去!
[root@study ~]# mkdir /tmp/boot2
[root@study ~]# xfsrestore -f /srv/boot.dump -L boot_all -s grub2 /tmp/boot2

如果只想要复原某一个目录或文件的话, 直接加上**“ -s 目录 ”**这个选项与参数即可。

复原累积备份数据

其实复原累积备份与复原单一文件系统相似;
如果备份数据是由 level 0 -> level 1 -> level2… 去进行的, 当然复原就得要相同的流程来复原! 因此当我们复原了 level 0 之后, 接下来当然就要复原 level 1 到系统内。

前一个案例复原 /tmp/boot 的情况来继续往下处理:

# 继续复原 level 1 到 /tmp/boot 当中!
[root@study ~]# xfsrestore -f /srv/boot.dump1 /tmp/boot

仅还原部分文件的 xfsrestore 互动模式

通过 -i 这个互动界面:
可以从备份文件里面找出你所需要的数据来复原;通过交互的方式。

# 1. 先进入备份文件内, 准备找出需要备份的文件名数据, 同时预计还原到 /tmp/boot3 当中!
[root@study ~]# mkdir /tmp/boot3
[root@study ~]# xfsrestore -f /srv/boot.dump -i /tmp/boot3
 ========================== subtree selection dialog ==========================

the following commands are available:
        pwd
        ls [ <path> ]
        cd [ <path> ]
        add [ <path> ]       # 可以加入复原文件列表中
        delete [ <path> ]    # 从复原列表拿掉文件名! 并非删除喔!
        extract              # 开始复原动作!
        quit
        help

 -> ls
          455517 initramfs-3.10.0-229.el7.x86_64kdump.img
             138 initramfs-3.10.0-229.el7.x86_64.img
             141 initrd-plymouth.img
             140 vmlinuz-0-rescue-309eb890d09f440681f596543d95ec7a
             139 initramfs-0-rescue-309eb890d09f440681f596543d95ec7a.img
             137 vmlinuz-3.10.0-229.el7.x86_64
             136 symvers-3.10.0-229.el7.x86_64.gz
             135 config-3.10.0-229.el7.x86_64
             134 System.map-3.10.0-229.el7.x86_64
             133 .vmlinuz-3.10.0-229.el7.x86_64.hmac
         1048704 grub2/
             131 grub/

 -> add grub
 -> add grub2
 -> add config-3.10.0-229.el7.x86_64
 -> extract

[root@study ~]# ls -l /tmp/boot3
-rw-r--r--. 1 root root 123838 Mar  6 19:45 config-3.10.0-229.el7.x86_64
drwxr-xr-x. 2 root root     26 May  4 17:52 grub
drwxr-xr-x. 6 root root    104 Jun 25 00:02 grub2
# 就只会有 3 个文件名被复原, 当然, 如果文件名是目录, 那下面的子文件当然也会被还原回来的!

其他常见的压缩与备份工具

dd

dd 的用途有很多,这里主要介绍dd在备份中的功能;
dd 可备份完整的 partition 或 disk , 因为 dd 可读取磁盘的 sector 表面数据
dd 可以读取磁盘设备的内容( 几乎是直接读取扇区"sector") , 然后将整个设备备份成一个文件

[root@study ~]# dd if="input_file" of="output_file" bs="block_size" count="number"
选项与参数:
if	 : 就是 input file 啰~也可以是设备喔!
of	 : 就是 output file 喔~也可以是设备;
bs	 : 规划的一个 block 的大小, 若未指定则默认是 512 Bytes( 一个 sector 的大小)
count: 多少个 bs 的意思。

范例一: 将 /etc/passwd 备份到 /tmp/passwd.back 当中
[root@study ~]# dd if=/etc/passwd of=/tmp/passwd.back
4+1 records in
4+1 records out
2092 bytes (2.1 kB) copied, 0.000111657 s, 18.7 MB/s
[root@study ~]# ll /etc/passwd /tmp/passwd.back
-rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd
-rw-r--r--. 1 root root 2092 Jul  2 23:27 /tmp/passwd.back
# 仔细的看一下, 我的 /etc/passwd 文件大小为 2092 Bytes, 因为我没有设置 bs ,
# 所以默认是 512 Bytes 为一个单位, 因此, 上面那个 4+1 表示有 4 个完整的 512 Bytes,
# 以及未满 512 Bytes 的另一个 block 的意思啦! 事实上, 感觉好像是 cp 这个指令啦~

范例二: 将刚刚烧录的光驱的内容, 再次的备份下来成为图像挡
[root@study ~]# dd if=/dev/sr0 of=/tmp/system.iso
177612+0 records in
177612+0 records out
90937344 bytes (91 MB) copied, 22.111 s, 4.1 MB/s
# 要将数据抓下来用这个方法, 如果是要将镜像文件写入 USB 磁盘, 就会变如下一个范例啰!

范例三: 假设你的 USB 是 /dev/sda 好了, 请将刚刚范例二的 image 烧录到 USB 磁盘中
[root@study ~]# lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda    8:0    0   2G  0 disk            # 确实是 disk 而且有 2GB 喔!

[root@study ~]# dd if=/tmp/system.iso of=/dev/sda
[root@study ~]# mount /dev/sda /mnt
[root@study ~]# ll /mnt
dr-xr-xr-x. 131 root root 34816 Jun 26 22:14 etc
dr-xr-xr-x.   5 root root  2048 Jun 17 00:20 home
dr-xr-xr-x.   8 root root  4096 Jul  2 18:48 root
# 如果你不想要使用 DVD 来作为开机媒体, 那可以将镜像文件使用这个 dd 写入 USB 磁盘,
# 该磁盘就会变成跟可开机光盘一样的功能! 可以让你用 USB 来安装 Linux 喔! 速度快很多!

范例四: 将你的 /boot 整个文件系统通过 dd 备份下来
[root@study ~]# df -h /boot
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda2      1014M  149M  866M  15% /boot       # 请注意! 备份的容量会到 1G 喔!
[root@study ~]# dd if=/dev/vda2 of=/tmp/vda2.img
[root@study ~]# ll -h /tmp/vda2.img
-rw-r--r--. 1 root root 1.0G Jul  2 23:39 /tmp/vda2.img
# 等于是将整个 /dev/vda2 通通捉下来的意思~所以, 文件大小会跟整颗磁盘的最大量一样大!

注意:
默认 dd 是一个一个扇区去读/写的而且即使没有用到的扇区也会倍写入备份文件中; 因此这个文件会变得跟原本的磁盘一模一样大;不像使用 xfsdump 只备份文件系统中有使用到的部份。
 
dd 还可以将原本旧的partition 上面, 将 sector 表面的数据整个复制过来; 当然连同 superblock, boot sector, metadata 等等通通也会复制过来。
如果你想要创建两颗一模一样的磁盘时, 只要下达类似: dd if=/dev/sda of=/dev/sdb就能够让两颗磁盘一模一样, 甚至 /dev/sdb 不需要分区与格式化因为该指令可以将 /dev/sda 内的所有数据, 包括 MBR 与 partition table也复制到 /dev/sdb
 
dd 就是因为不理会文件系统, 单纯有啥纪录啥因此不论该磁盘内的文件系统你是否认识它都可以备份、 还原

cpio

cpio 可以备份任何东西, 包括设备设备文件
不过 cpio 有个大问题, 那就是 cpio 不会主动的去找文件来备份。
一般来说, cpio 得要配合类似 find 等可以找到文件名的指令来告知 cpio 该被备份的数据在哪里。

[root@study ~]# cpio -ovcB  > [file|device] <==备份
[root@study ~]# cpio -ivcdu < [file|device] <==还原
[root@study ~]# cpio -ivct  < [file|device] <==察看
备份会使用到的选项与参数:
	-o : 将数据 copy 输出到文件或设备上
	-B : 让默认的 Blocks 可以增加至 5120 Bytes , 默认是 512 Bytes !
		这样的好处是可以让大文件的储存速度加快( 请参考 i-nodes 的观念)
还原会使用到的选项与参数:
	-i : 将数据自文件或设备 copy 出来系统当中
	-d : 自动创建目录! 使用 cpio 所备份的数据内容不见得会在同一层目录中, 因此我们
		必须要让 cpio 在还原时可以创建新目录, 此时就得要 -d 选项的帮助!
	-u : 自动的将较新的文件覆盖较旧的文件!
	-t : 需配合 -i 选项, 可用在"察看"以 cpio 创建的文件或设备的内容
		一些可共享的选项与参数:
	-v : 让储存的过程中文件名称可以在屏幕上显示
	-c : 一种较新的 portable format 方式储存

注意:
上述的选项与指令中没有指定需要备份的数据是需求其他指令找到需要备份的文件,然后数据重导向cpio
 
关于大于 ( >) 与小于 ( <) 符号
因为 cpio 会将数据整个显示到屏幕上, 因此我们可以通过将这些屏幕的数据重新导向 ( >) 一个新的文件;
至于还原, 就是将备份文件读进来 cpio ( <) 进行处理之意。

案例:这里的案例用到了后续才讲的数据流重导向

范例: 找出 /boot 下面的所有文件, 然后将他备份到 /tmp/boot.cpio 去!
[root@study ~]# cd /
[root@study /]# find boot -print
boot
boot/grub
boot/grub/splash.xpm.gz
....( 以下省略) ....
# 通过 find 我们可以找到 boot 下面应该要存在的文件名! 包括文件与目录! 但请千万不要是绝对路径!

[root@study /]# find boot | cpio -ocvB > /tmp/boot.cpio
[root@study /]# ll -h /tmp/boot.cpio
-rw-r--r--. 1 root root 108M Jul  3 00:05 /tmp/boot.cpio
[root@study ~]# file /tmp/boot.cpio
/tmp/boot.cpio: ASCII cpio archive (SVR4 with no CRC)

我们使用 find boot 可以找出文件名然后通过那条管线 ( |, 亦即键盘上的 shift+\ 的组合)就能将文件名传给 cpio 来进行处理, 最终会得到 /tmp/boot.cpio 那个文件。

范例: 将刚刚的文件给他在 /root/ 目录下解开
[root@study ~]# cd ~
[root@study ~]# cpio -idvc < /tmp/boot.cpio
[root@study ~]# ll /root/boot
# 你可以自行比较一下 /root/boot 与 /boot 的内容是否一模一样!

总结:
虽然cpio不是很好用,但是可以备份任何的文件, 包括 /dev 下面的任何设备文件。

vim 编辑器

vim 是进阶版的 vi , vim 不但可以用不同颜色显示文字内容, 还能够进行诸如 shell script, C program 等程序编辑功能, 你可以将 vim 视为一种程序编辑器。
 
vim 会依据文件的扩展名或者是文件内的开头信息,判断该文件的内容而自动的调用该程序的语法判断式, 再以颜色来显示程序码与一般信息。

参考链接:教你玩转Linux—vi/vim     Linux——vi命令详解

vi 的使用

基本上 vi 共分为三种模式, 分别是“一般指令模式”、 “编辑模式”与“命令行命令模式”。

  • 一般指令模式 ( command mode)
    以 vi 打开一个文件就直接进入一般指令模式了( 这是默认的模式, 也简称为一般模式) 。 在这个模式中, 你可以使用**“上下左右”按键来移动光标**, 你可以使用“删除字符”或“删除整列”来处理文件内容, 也可以使用“复制、 贴上”来处理你的文件数据。
  • 编辑模式 ( insert mode)
    在一般指令模式中可以进行删除、 复制、 贴上等等的动作, 但是却无法编辑文件内容的! 要等到你按下“i, I, o, O, a, A, r, R”等任何一个字母之后才会进入编辑模式。
    注意了! 通常在Linux 中, 按下这些按键时, 在画面的左下方会出现“ INSERT 或 REPLACE ”的字样, 此时才可以进行编辑。 而如果要回到一般指令模式时, 则必须要按下“Esc”这个按键即可退出编辑模式。
  • 命令行命令模式 ( command-line mode)
    在一般模式当中, 输入“ : / ? ”三个中的任何一个按钮, 就可以将光标移动到最下面那一列。 在这个模式当中, 可以提供你“搜寻数据”的动作, 而读取、 存盘、 大量取代字符、 离开 vi 、 显示行号等等的动作则是在此模式中达成的。
     
    在这里插入图片描述

注意:
由于一般帐号默认已经使用 vim 来取代如果使用一般帐号来测试, 得要使用绝对路径的方式来执行 /bin/vi 才好! 另外, 请注意, 记得 vi 后面一定要加文件名, 不管该文件名存在与否

按键说明:
vi 的三种模式只有一般指令模式可以与编辑、 命令行界面切换编辑模式与命令行界面之间并不能切换的

在这里插入图片描述

第一部份: 一般指令模式可用的按钮说明, 光标移动、 复制贴上、 搜寻取代等

移动光标的方法
h 或 向左方向键( ←)光标向左移动一个字符
j 或 向下方向键( ↓)光标向下移动一个字符
k 或 向上方向键( ↑)光标向上移动一个字符
l 或 向右方向键( →)光标向右移动一个字符
如果你将右手放在键盘上的话, 你会发现 hjkl 是排列在一起的, 因此可以使用 这四个按钮来移动光标。 如果想要进行多次移动的话, 例如向下移动 30 列,可以使用 "30j" 或 "30↓" 的组合按键,亦即加上想要进行的次数( 数字) 后,按下动作即可!
[Ctrl] + [f]屏幕“向下”移动一页, 相当于 [Page Down]按键 ( 常用)
[Ctrl] + [b]屏幕“向上”移动一页, 相当于 [Page Up] 按键( 常用)
[Ctrl] + [d]屏幕“向下”移动半页
[Ctrl] + [u]屏幕“向上”移动半页
[Ctrl] + [d]屏幕“向下”移动半页
+光标移动到非空白字符的下一列
-光标移动到非空白字符的上一列
n<space>那个 n 表示“数字”, 例如 20 。 按下数字后再按空白键, 光标会向右移动这一列的 n 个字符。 例如 20<space> 则光标会向后面移动 20个字符距离。
0 或功能键[Home]这是数字“ 0 ”: 移动到这一列的最前面字符处( 常用)
$ 或功能键[End]移动到这一列的最后面字符处( 常用)
H光标移动到这个屏幕的最上方那一列的第一个字符
M光标移动到这个屏幕的中央那一列的第一个字符
L光标移动到这个屏幕的最下方那一列的第一个字符
G移动到这个文件的最后一列( 常用)
nGn 为数字。 移动到这个文件的第 n 列。 例如20G 则会移动到这个文件的第 20 列( 可配合:set nu)
gg移动到这个文件的第一列, 相当于 1G 啊!( 常用)
n<Enter>n 为数字。 光标向下移动 n 列( 常用)
搜寻与取代
/word向光标之下寻找一个名称为 word 的字串。 例如要在文件内搜寻 vbird 这个字串, 就输入/vbird 即可! ( 常用)
?word向光标之上寻找一个字串名称为 word 的字串。
n这个 n 是英文按键。 代表“重复前一个搜寻的动作”。 举例来说, 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字串, 则按下n 后, 会向下继续搜寻下一个名称为 vbird 的字串。 如果是执行 ?vbird 的话, 那么按下 n则会向上继续搜寻名称为 vbird 的字串!
N这个 N 是英文按键。 与 n 刚好相反, 为“反向”进行前一个搜寻动作。 例如 /vbird 后, 按下 N 则表示“向上”搜寻 vbird 。
使用 /word 配合 n 及 N 是非常有帮助的! 可以让你重复的找到一些你搜寻的关键字!
:n1,n2s/word1/word2/gn1 与 n2 为数字。 在第 n1 与 n2 列之间寻找word1 这个字串, 并将该字串取代为 word2 ! 举例来说, 在 100 到 200 列之间搜寻 vbird并取代为 VBIRD则: “:100,200s/vbird/VBIRD/g”。 ( 常用)
:1,$s/word1/word2/g从第一列到最后一列寻找 word1 字串, 并将该字串取代为 word2 ! ( 常用)
:1,$s/word1/word2/gc从第一列到最后一列寻找 word1 字串, 并将 该字串取代为 word2 ! 且在取代前显示提示 字符给使用者确认 ( confirm) 是否需要取 代! ( 常用)
删除、 复制与贴上
x, X在一列字当中, x 为向后删除一个字符 ( 相当于 [del] 按键) , X 为向前删除一个字符( 相当于 [backspace] 亦即是倒退键) ( 常用)
nxn 为数字, 连续向后删除 n 个字符。 举例来说, 我要连续删除 10 个字符, “10x”。
ddn 为数字。 删除光标所在的向下 n 列, 例如20dd 则是删除 20 列 ( 常用)
nddn 为数字。 删除光标所在的向下 n 列, 例如20dd 则是删除 20 列 ( 常用)
d1G删除光标所在到第一列的所有数据
dG删除光标所在到最后一列的所有数据
d$删除光标所在处, 到该列的最后一个字符
d0那个是数字的 0 , 删除光标所在处, 到该列的最前面一个字符
yy复制光标所在的那一列( 常用)
nyyn 为数字。 复制光标所在的向下 n 列, 例如20yy 则是复制 20 列( 常用)
y1G复制光标所在列到第一列的所有数据
yG复制光标所在列到最后一列的所有数据
y0复制光标所在的那个字符到该列行首的所有数据
y$复制光标所在的那个字符到该列行尾的所有数据
p, Pp 为将已复制的数据在光标下一列贴上, P 则为贴在光标上一列! 举例来说, 我目前光标在第 20 列, 且已经复制了 10 列数据。 则按下 p 后, 那 10 列数据会贴在原本的 20 列之后, 亦即由 21 列开始贴。 但如果是按下 P呢? 那么原本的第 20 列会被推到变成 30列。 ( 常用)
J将光标所在列与下一列的数据结合成同一列
c重复删除多个数据, 例如向下删除 10 列, [10cj ]
u复原前一个动作。 ( 常用)
[Ctrl]+r重做上一个动作。 ( 常用)
这个 u 与 [Ctrl]+r 是很常用的指令! 一个是复原, 另一个则是重做一次~ 利用这两个功能按键, 你的编辑将很快捷。
.不要怀疑! 这就是小数点! 意思是重复前一个动作的意思。 如果你想要重复删除、 重复 贴上等等动作, 按下小数点“.”就好了! ( 常用)

第二部份: 一般指令模式切换到编辑模式的可用的按钮说明

进入插入或取代的编辑模式
i, I进入插入模式( Insert mode) : i为“从目前光标所在处插入”, I为“在目前所在列的第一个非空白 字符处开始插入”。 ( 常用)
a, A进入插入模式( Insert mode) : a为“从目前光标所在的下一个字符处开始插入”, A 为“从光标所在列的最后一个字符处开始插入”。 ( 常用)
o, O进入插入模式( Insert mode) :这是英文字母 o 的大小写。 o为“在目前光标所在的下一列处插 入新的一列”; O 为在目前光标所在处的上一列插入新的一列! ( 常用)
r, R进入取代模式( Replacemode) : r 只会取代光标所在的那一个字符一次; R会一直取代光标所在的文字, 直到按下 ESC 为止; ( 常用)
上面这些按键中, 在 vi 画面的左下角处会出现“--INSERT--”或“--REPLACE--”的字样。 由名称就知道该动作了吧! ! 特别注意的是, 我们上面也提过了, 你想要在文件里面输入字符时, 一定要在左下角处看到 INSERT 或 REPLACE 才能输入喔!

第三部份: 一般指令模式切换到命令行界面的可用按钮说明

命令行界面的储存、 离开等指令
:w将编辑的数据写入硬盘文件中( 常用)
:w!若文件属性为“只读”时, 强制写入该文件。 不过, 到底能不能写入, 还是跟你对该文件的文件权限有关啊!
:q离开 vi ( 常用)
:q!若曾修改过文件, 又不想储存, 使用 ! 为强制离开不储存盘案。
注意一下啊, 那个惊叹号( !) 在 vi 当中, 常常具有“强制”的意思~
:wq储存后离开, 若为 :wq! 则为强制储存后离开 ( 常用)
ZZ这是大写的 Z 喔! 若文件没有更动, 则不储存离开, 若文件已经被更动过, 则储存后离开!
:w [filename]将编辑的数据储存成另一个文件( 类似另存新文件)
:r [filename]在编辑的数据中, 读入另一个文件的数据。 亦即将“filename” 这个文件内容加到光标所在列后面
:n1,n2 w [filename]将 n1 到 n2 的内容储存成 filename 这个文件。
:! command暂时离开 vi 到命令行界面下执行 command 的显示结果! 例如 “:! ls /home”即可在 vi 当中察看 /home 下面以ls 输出的文件信息!
vim 环境的变更
:set nu显示行号, 设置之后, 会在每一列的字首显示该列的行号
:set nonu与 set nu 相反, 为取消行号!

特别注意:
在 vi 中, “数字”是很有意义的数字通常代表重复做几次的意思! 也有可能是代表去到第几个什么什么的意思。

vim 的暂存盘、 救援恢复与打开时的警告讯息

当你的系统因为某些原因而导致类似死机的情况时, 还可以通过某些特别的机制来让你将之前未储存的数据“救”回来。
vim 就是通过“暂存盘”来救援。

当我们在使用 vim 编辑时, vim 会在与被编辑的文件的目录下, 再创建一个名为.filename.swp 的文件。此文件就是暂存文件
当你在对文件做编辑操作时,所有动作就会被记录到这个 .filename.swp 当中;
如果你的系统因为某些原因断线了, 导致你编辑的文件还没有储存, 这个时候 .filename.swp 就能够发挥救援的功能了。

例子: man_db.conf 文件未正常保存,异常退出;当重新打开该文件时,代码如下:

[dmtsai@study vitest]$ vim man_db.conf

E325: ATTENTION  <==错误代码
Found a swap file by the name ".man_db.conf.swp"  <==下面数列说明有暂存盘的存在
          owned by: dmtsai   dated: Mon Jul  6 23:54:16 2015
         file name: /tmp/vitest/man_db.conf  <==这个暂存盘属于哪个实际的文件?
          modified: no
         user name: dmtsai   host name: study.centos.vbird
        process ID: 31851
While opening file "man_db.conf"
             dated: Mon Jul  6 23:47:21 2015

下面说明可能发生这个错误的两个主要原因与解决方案!
(1) Another program may be editing the same file.  If this is the case,
    be careful not to end up with two different instances of the same
    file when making changes.  Quit, or continue with caution.
(2) An edit session for this file crashed.
    If this is the case, use ":recover" or "vim -r man_db.conf"
    to recover the changes (see ":help recovery").
    If you did this already, delete the swap file ".man_db.conf.swp"
    to avoid this message.

Swap file ".man_db.conf.swp" already exists! 下面说明你可进行的动作
[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:  

由于暂存盘存在的关系, 因此 vim 会主动的判断你的这个文件可能有些问题, 在上面的例子中 vim 提示两点主要的问题与解决方案, 分别是这样的:

  • 问题一: 可能有其他人或程序同时在编辑这个文件:
    由于 Linux 是多用户多任务的环境, 因此很可能有很多人同时在编辑同一个文件。 如果在多人共同编辑的情况下, 万一大家同时储存, 那么这个文件的内容将会变的乱七八糟! 为了避免这个问题, 因此 vim 会出现这个警告窗口! 解决的方法则是:
  • 找到另外那个程序或人员, 请他将该 vim 的工作结束, 然后你再继续处理。
  • 如果你只是要看该文件的内容并不会有任何修改编辑的行为, 那么可以选择打开成为只读( O) 文件, 亦即上述画面反白部分输入英文“ o ”即可, 其实就是 [O]penRead-Only 的选项。
  • 问题二: 在前一个 vim 的环境中, 可能因为某些不知名原因导致 vim 中断( crashed) :
    这就是常见的不正常结束 vim 产生的后果。 解决方案依据不同的情况而不同喔! 常见的处理方法为:
  • 如果你之前的 vim 处理动作尚未储存, 此时你应该要按下“R”, 亦即使用 ( R)ecover 的项目, 此时 vim 会载入 .man_db.conf.swp 的内容, 让你自己来决定要不要储存! 这样就能够救回来你之前未储存的工作。 不过那个 .man_db.conf.swp 并不会在你结束 vim 后自动删除, 所以你离开 vim 后还得要自行删除.man_db.conf.swp 才能避免每次打开这个文件都会出现这样的警告!
  • 如果你确定这个暂存盘是没有用的, 那么你可以直接按下“D”删除掉这个暂存盘, 亦即 ( D) elete it 这个项目即可。 此时 vim 会载入 man_db.conf , 并且将旧的.man_db.conf.swp 删除后, 创建这次会使用的新的 .man_db.conf.swp。

至于这个发现暂存盘警告讯息的画面中, 有出现六个可用选项, 各选项的说明如下:

  • [O]pen Read-Only: 打开此文件成为只读文件, 可以用在你只是想要查阅该文件内容并不想要进行编辑行为时。 一般来说, 在上课时, 如果你是登陆到同学的计算机去看他的配置文件, 结果发现其实同学他自己也在编辑时, 可以使用这个模式;
  • ( E) dit anyway: 还是用正常的方式打开你要编辑的那个文件, 并不会载入暂存盘的内容。 不过很容易出现两个使用者互相改变对方的文件等问题! 不好不好!
  • ( R) ecover: 就是载入暂存盘的内容, 用在你要救回之前未储存的工作。 不过当你救回来并且储存离开 vim 后, 还是要手动自行删除那个暂存盘!
  • ( D) elete it: 你确定那个暂存盘是无用的! 那么打开文件前会先将这个暂存盘删除!这个动作其实是比较常做的! 因为你可能不确定这个暂存盘是怎么来的, 所以就删除掉他。
  • ( Q) uit: 按下 q 就离开 vim , 不会进行任何动作回到命令提示字符。
  • ( A) bort: 忽略这个编辑行为, 感觉上与 quit 非常类似! 也会送你回到命令提示字符。

vim 的额外功能

目前大部分的 distributions 都以 vim 取代 vi 的功能了! 如果你使用 vi 后, 却看到画面的右下角有显示目前光标所在的行列号码, 那么你的 vi 已经被 vim 所取代。
 
vim 具有颜色显示的功能, 并且还支持许多的程序语法 ( syntax) , 因此, 当你使用 vim 编辑程序时 ( 不论是 C 语言, 还是 shell script ) , 我们的 vim 将可帮你直接进行“程序除错 ( debug) ”的功能

区块选择( Visual Block)

之前 vi 操作过程中, 几乎提到的都是以列为单位的操作

区块选择的按键意义
v字符选择, 会将光标经过的地方反白选择!
V列选择, 会将光标经过的列反白选择!
[Ctrl]+v区块选择, 可以用长方形的方式选择数据
y将反白的地方复制起来
d将反白的地方删除掉
p将刚刚复制的区块, 在光标所在处贴上!

多文件编辑

多文件编辑的按键
:n编辑下一个文件
:N编辑上一个文件
:files列出目前这个 vim 的打开的所有文件

多窗口功能

多窗口情况下的按键功能
:sp[filename]打开一个新窗口, 如果有加 filename, 表示在新窗口打开一个新文件, 否则表示两个窗口为同一个文件内容( 同步显示) 。
[ctrl]+w+ j [ctrl]+w+↓按键的按法是: 先按下 [ctrl] 不放, 再按下 w 后放开所有的按键, 然后再按下 j ( 或向下方向键) , 则光标可移动到下方的窗口。
[ctrl]+w+ k [ctrl]+w+↑同上, 不过光标移动到上面的窗口。
[ctrl]+w+q其实就是 :q 结束离开啦! 举例来说, 如果我想要结束下方的窗口, 那么利用 [ctrl]+w+↓ 移动到下方窗口后, 按下 :q 即可离开, 也可以按下[ctrl]+w+q 啊!

vim 的挑字补全功能

组合按钮补齐的内容
[ctrl]+x -> [ctrl]+n通过目前正在编辑的这个“文件的内容文字”作为关键字, 予以补齐
[ctrl]+x -> [ctrl]+f以当前目录内的“文件名”作为关键字, 予以补齐
[ctrl]+x -> [ctrl]+o以扩展名作为语法补充, 以 vim 内置的关键字, 予以补齐
e9ba4535-a60a-451a-8141-f6330f17b070
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值