圣诞节怎么过?看看历年圣诞节怎么过就知道了

每当过节这天,即使没有过这个节日的习惯,也总想着要做些什么。

怎么知道自己有没有过这个节日的习惯呢。

翻看一下自己的历史相册或是日记就知道了。

翻了一下相册,看看我每年的 12月23,24日都在干什么。

那年今日

2021

刚好到周末了,圣诞总想着做些什么,于是去商场逛逛,这是我认为当天最有气氛的一家店门口。

然后其他的一样的平平无奇。

2020

那天上班,还加了班,在公司楼下一家小店吃了烧饼夹菜,店面平平无奇确非常好吃,确实是此前此后再也很难吃到的味道。

晚上回家,点起宜家买的蜡烛,制造一些氛围,然后,睡觉。

2019

在食堂简单吃了一份忘了叫什么饭:

没记错的话,那段时间还在尝试使用 Zorin OS 当作自己的主力系统:

2018

去领取了一个意外的奖项,非常的意外。

2017

那天又是领奖。。。

2016

跟室友一起吃鸡公煲,那时候吃的鸡公煲还是这样子:

2015

看照片那天在班里拍摄点滴回顾当年的纪念视频。

2014

上课、晚自习,还记得那阵子家长开放日,作为班委等到最后我家长都没来,伤心了很久 ?

晚上,捕获一轮弯月。

2013

2012

背英语作文,,?

总结

简单总结一下,圣诞节那个时间,基本上是许多活动、赛事的最后阶段,因此是一个收获的时刻,参加活动较多的那几天,都是挺开心的。

后来随着时间的推移,氛围是归于平淡的。这不能说明什么,只能说是没有过这个节的习惯。

其他时刻基本都在该干嘛干嘛,该加班加班,该学习学习。

所以今天呢,想玩就玩一玩,想干啥就抓紧时间干。

就这样~

[摘录]《写作是最好的自我投资》 – Spenser

写作是最好的自我投资 Spenser 36个笔记

◆ 自序 没有写作,我可能要多奋斗十年

第一,写作是利用碎片化时间最好的方式。

你花两个小时看电影、看综艺、刷抖音,和花两个小时写一篇文章,结果是有本质区别的。前者是你在消费别人创造的产品,你是被接受、被喂养的姿态;而写作,是你在创造一个属于你自己的作品,你是创造者、供养者,写作是思想和灵魂的绽放,与前者完全不一样。

第二,写作让我摆脱了肤浅。

写作会让人摆脱肤浅。写作不是吸收,而是创造。而创造,让人走进内涵,走向思考,走向深刻和高级。

第三,写作是这个时代最好的自我投资。

而写作,就是打造你个人品牌最好的方式之一。

◆ 第一章 会说的人很多,能写的人太少

影响力怎么构成?有两个能力:第一是写作,第二是演讲。——罗振宇

很多人还没到中年危机呢,就已经陷入青年危机的泥潭。

我说的青年危机,不是指工资收入买不起房的财务收入危机,也不是指职场无法快速晋升的职业生涯规划危机,而是思维层面上更宏观的危机。

因为焦虑的本质是知道自己不知道,想要改变。而很多人是不知道自己不知道,这才是最可怕的。

会表达的人,是这个时代最大的红利收获者。

大多数人在职场上的困惑,无非就这么几点:·钱赚得不够多:薪水太低,买房太贵,买车太贵,买包太贵,简单来说,理想很丰满,现实很骨感。·职场地位不稳:没有行业江湖地位,随时都有可能被炒掉、被调岗,跳槽也跳不出一个好身价。·才华无人赏识:能力很强,业务很牛,觉得上司或者老板很蠢,自己的价值一直被低估,自己是千里马,但是找不到伯乐。·社交圈子不高级:工作场合的圈子有限,没有机会扩展社交圈,或者没有途径进入更牛的圈子。这四个问题,基本可以涵盖90%以上的职场问题。

职场影响力不行。

我表面上是在写作,其实本质上是在经营这个互联网时代全新的社交方式。

未来的职场上,可能会出现两类人。一类是会写作的人。

而另一类是不会写作的人。

他们其实错过了互联网时代给每个人的最大红利,很可惜。

◆ 第二章 坐下来,开始写

好内容永远不会过时。种一棵树最好的时候,一个是过去,一个是现在。

灵感来自对生活的敏感。

如果一个人说话没有逻辑,别人与他沟通会很费劲;如果一篇文章逻辑混乱,我们根本没耐心把它读完。

写作需要对生活有深度认知。

让学生学习一样东西最好的方式,就是让学生当老师。

因为只有输出,才是最好的输入。

真正的反人性,不是以克制天性为目的,而是通过克制天性的手段达到某种目的。

写作时比追求新意更重要的,是诚实。

不论起点高低,只有写自己真正熟悉、相信、感兴趣的东西,你才有足够的热情和底气去剖析自己、探索世界、面对质疑。

除了事物本身,尽量写下打动你的那些细节(包括听觉、触觉),细节越丰富,日后回想起来,对当时场景乃至心情的还原越真实、鲜活。

写作最重要的一点:只管去做(Just do it)。哪怕对自己充满怀疑,也要开始动笔。否则,朋友圈的小红点、翻了一半的书、刷了两集的剧,或者随便什么能让你逃避写作的事,都会变成火烧眉毛的大事。

美国作家约瑟夫·科纳尔说:“写作只有两件难事:开始写,不停手。”很多人在动笔之后很难坚持,在我看来主要有三个原因:第一,控制不住自己;第二,完美主义心理;第三,缺乏反馈和激励。

在人类的生存活动中,大脑思考其实比物理活动要更消耗能量,于是人类为了尽量减少消耗,就进化出了一套本能:拒绝或者减少思考。像写作这样一种脑力活动,本身就是一件逆人性、反本能的事情。

思想上的完美主义是只关注自己脑海中不断变换的完美画面,幻想着最完美的结果;对事情抱有过高的期望,但实际和现状差距很大,结果当然就会产生挫败感,然后就越来越不想做,最后思想上的完美主义就只能让自己成为“行动上的矮子”。

人是需要有反馈刺激的动物。这个问题的解决办法,就是自己给自己制造反馈。

◆ 第三章 写作,是注意力的争夺

写作的场景和种类有很多,大体来说,可以从两个维度去划分,一个是对象感,另一个是目的性。

传统写作是:从前车马很慢,书信很远,一生只够爱一个人。注意力写作是:生活太快,时间太少,不要绕圈子,给我来个痛快的。

◆ 第五章 如何写好一个故事

关于写作,有“凤头,猪肚,豹尾”一说。意指文章的开头要像凤头一样精美,引人入胜;主体部分要充实,有理有据,像猪肚;结尾则要像豹尾一般,简洁有力,又有平衡感。这对故事写作也是适用的。

◆ 第八章 你所理解的新媒体写作,也许都是错的

就算你在公众号上写了100万字,如果不能转化成订阅关系,这个传播是没有任何价值的。传统媒体就是因为没有高效的订阅关系,才没有太大的影响力和商业价值。

失眠,整理如何对抗焦虑

最近的几件事情再次让内心焦虑感上升到一个巅峰。

工作日心里抱怨睡不够,休息日可以好好睡,结果直接就失眠了,对于这件事应该不需要诧异,就像是吃饭一样稀疏平常。

睡不着,于是就看书、做题、设计、写文。看完半本书,做了几道题,简单设计了一下 BJ-PFD2,然后就来整理这篇小文章了。

对抗焦虑,首先要搞清楚焦虑的来源是什么。可能是同辈压力、现实压力、未来焦虑等等。

在这里我也整理了一些对抗焦虑的方法:

(1)去看书。在书中寻找宁静和道路。对未来迷茫的时候很有用; (2)去规划。焦虑什么就去规划打破什么。确立一个目标,短期目标、长期目标,做计划逐渐达成。规划到位了,焦虑感就能化身为动力;

睡眠可以治愈一些痛苦,来源于身体的、精神的都可以通过睡眠修复。但有些不行,比如人际矛盾、工作目标等。这些就需要养精蓄锐然后通过正确的行动去改善。

也就因此,能睡着固然是好的;偶然睡不着就睡不着了,无需焦虑。想想如何利用这段时间,失眠的时间就会越来越少了。

互联网的最大谎言——拿偶然当必然

“快来看,294上苏大”,这是某考验机构一次视频封面内容。看到这句话你第一反应是什么呢?

会不会有许多人跟我一样,“哇塞,不到300分就能上苏大,我也可以呀“。但转念一想,这其中有一个很大的漏洞。

这件事情是发生在过去,在今天来说就是必然。但现在开始做是未来式,未来充满不确定性。

我可以很有底气的说出自己曾经做成了什么事,但很少能很有底气的说我未来能做成什么事

因为过去的事情,是去除了所有不确定性的必然;但未来的不确定性,是一只伴随左右的。

回想如今看到的网络文章,是不是充斥着这样的套路呢?

前阵子看了一本书名叫《人人都能学会的刷屏文案写作技巧》,这本书讲述了作者自己盛产 10w+ 的秘诀。看过之后,只感觉,也许就是从这样的书开始流行,我们看到的网络文章就开始变得千篇一律了吧。

前阵子热播的电视剧《破事精英》第10集“一切为了流量”中也讲述了类似的事。为了流量,某些自媒体运营者毫无底线,吃着现代版“人血馒头”,还昂首挺胸介绍自己“农夫三拳”的邪术,这样的方法虽极大提升了流量,透支的是人性。

我个人很讨厌看网上的许多内容,包括新媒体推文和各类小视频。这些东西在我看来都是肤浅的,价值不高的。乍看收获,其实是被收割了自己最宝贵的注意力。

好的事情总是困难的,太容易得来的东西其背后定有玄机。我个人很认同可以通过这种方式减压和排忧,这种反向利用的想法很值得鼓励。

但最终,只有那些有特色的,意味深长的,有实际价值的内容,才能走的更高更远。

#creative

[摘录]《Linux系统命令及Shell脚本实践指南》 – 王军

Linux 系统命令及 Shell 脚本实践指南 王军 415 个笔记

◆ 点评

认为好看 此前一些似懂非懂的概念,经常使用却总感觉不得法的工具和系统特性,终于在这本书中系统性地找到了答案。

◆ 第 1 章 Linux 简介

1969 年 8 月左右,他的妻儿出门探亲了一个月,就在这一个月的时间里,Thompson 编写了一个操作系统,并成功地将“星际旅行”移植到了 DPD-7 上,而这个操作系统就是 UNIX 的原型。

Linux 的内核设计分成进程管理、内存管理、进程间通信、虚拟文件系统、网络 5 部分

Linux 采取了很多安全技术措施,包括读写权限控制、带保护的子系统、审计跟踪、核心授权等

多任务是现代化计算机的主要特点,指的是计算机能同时运行多个程序,且程序之间彼此独立,Linux 内核负责调度每个进程,使之平等地访问处理器

Grub 是一个系统引导工具,通过它可以加载内核,从而引导系统启动。

/boot 分区用于放置 Linux 启动所用到的文件,如 kernel 和 initrd 文件。

◆ 第 2 章 Linux 用户管理

Linux 系统中的用户分为 3 类,即普通用户、根用户、系统用户。

通常普通用户的 UID 大于 500,因为在添加普通用户时,系统默认用户 ID 从 500 开始编号。

根用户也就是 root 用户,它的 ID 是 0,也被称为超级用户,root 账户拥有对系统的完全控制权:可以修改、删除任何文件,运行任何命令。

root 用户也是系统里面最具危险性的用户,root 用户甚至可以在系统正常运行时删除所有文件系统,造成无法挽回的灾难

系统用户是指系统运行时必须有的用户,但并不是指真实的使用者。

在 RedHat 或 CentOS 下,系统用户的 ID 范围是 1~499

系统用来记录用户名、密码最重要的两个文件就是/etc/passwd 和/etc/shadow。

[插图]

[插图]

系统在添加用户时,需要预先为这个用户创建一些默认的“配置文件”,而默认配置的就是/etc/skel 目录下的几个隐藏文件。可以说,/etc/skel 实际上是创建用户时的“模板”。

创建用户后,该用户实际上还没有登录系统的权限,因为在不设置密码的情况下,在/etc/shadow 中该用户记录中以冒号分隔的第二列将显示为两个感叹号“!!”,这说明不允许该用户登录系统。

su 是切换用户的意思。在不加参数的情况下,su 命令默认表示切换到 root 用户

su 命令后面还可以加上一个“-”参数,就是键盘上的中横线。加上这个参数后,切换成 root 用户时,不但身份变成了 root,而且还能应用 root 的用户环境。

所谓“用户环境”就是/etc/passwd 中定义的用户家目录、使用的 Shell,以及关于这个用户的个性化设置等。

使用 su 命令虽然很方便,但还是有很明显的缺陷,就是切换成其他用户的前提是需要知道对方的密码

但是考虑到这个配置文件的重要性,Linux 提供了专门编辑这个文件的方式,就是使用命令 visudo 来编辑这个文件,它的好处是可以在编辑后保存退出时自动检查语法设置,以防止不小心配置错误而造成无法使用 sudo 命令。

加入的“john ALL=(ALL) ALL”这一行代表的意思是,john 这个用户(第一列)可以从任何地方登录后(第二列的 ALL)执行任何人(第三列的 ALL)的任何命令(第四列的 ALL)。还可以定义某一个组的 sudo 权限,比如“%john ALL=(ALL) ALL”可以让所有属于 john 用户组的用户从任何地方登录后执行任何人的任何命令。

只需要知道自己的密码就可以使用 sudo 执行任何命令,这样方便多了。但是每次都需要输入一遍密码也是比较麻烦的事情,想要实现不需要输入密码就可以执行命令,可以在最后一个 ALL 前添加“NOPASSWD:”,

严格来说,sudo 并不是真的切换了用户,而是使用其他用户的身份和权限执行了命令。

如果任务是周期性执行的,其命令为 cron;如果只是在某一个特定的时间执行一次,其命令为 at。

可以使用 atq 命令查看当前使用 at 命令调度的任务列表,第一列是任务编号;也可以使用 atrm 删除已经进入任务队列的任务

默认情况下,所有用户都可以使用 at 命令来调度自己的任务,如果由于特殊的原因需要禁止某些用户使用这个功能,可以将该用户的用户名添加至/etc/at.deny 中。

用户可通过 crontab 来设置自己的计划任务,并使用-e 参数来编辑任务

在下面的示例中,前面 5 个可以用来定义时间,第一个表示分钟,可以使用的值是 1~59,每分钟可以使用/1 表示;第二个表示小时,可以使用的值是 0~23;第三个表示日期,可以使用的值是 1~31;第四个表示月份,可以使用的值是 1~12;第五个表示星期几,可以使用的值是 0~6,0 代表星期日;最后是执行的命令。

          • command​​

与 at 类似,每个用户都可以设置自己的 crontab,如果由于特殊的原因需要禁止某些用户使用这个功能,可以将该用户的用户名添加至/etc/cron.deny 中。除了 root 之外,普通用户只可以设置、查看、删除自己的计划任务,root 可以使用-u 参数查看指定用户的任务。

事实上,系统也有自己的例行任务,而其配置文件是/etc/crontab

◆ 第 3 章 Linux 文件管理

根据 FHS 的定义,每个目录应该放置的文件如表 3-1 所示。 表 3-1 FHS 定义的目录结构 

一个点(.)代表的是当前目录,两个点(..)代表的是当前目录的上层目录

查看文件:cat 该命令是 concatenate 的简写,用户查看文件内容,后面跟上要查看的文件名即可

默认情况下,head 将显示该文件前 10 行的内容

文件格式转换:dos2unix 该命令是 DOS to UNIX 的简写,也许你从字面上可以大概猜到它的作用,就是可以把 DOS 格式的文本文件转变成 UNIX 下的文本文件

进入目录:cd 该命令是 change directory 的简写,方便用户切换到不同的目录

删除目录:rmdir 和 rm 该命令是 remove directory 的简写,用来删除目录。但是需要注意的是,它只能删除空目录,如果目录不为空(存在文件或者子目录),那么该命令将拒绝删除指定的目录

由于 root 用户在 Linux 系统中的权限非常高,甚至可以用 rm-rf /命令来删除全部的系统文件(这样做的后果是灾难性的),所以使用-rf 参数删除目录一定要慎之又慎!

在 Linux 下目录也是一种文件,所以如果 touch 一个目录,这个目录的创建时间也会被更新

第一列是文件类别和权限,这列由 10 个字符组成,第一个字符表明该文件的类型

目录文件的连接数是该目录中包含其他目录的总个数 +2

[插图]

Linux 下的文件还有一些隐藏属性,必须使用 lsattr 来显示

如果要设置文件的隐藏属性,需要使用 chattr 命令

这里介绍几个常用的隐藏属性,第一种是 a 属性。拥有这种属性的文件只能在尾部增加数据而不能被删除

还有一种比较常用的属性是 i 属性。设置了这种属性的文件将无法写入、改名、删除,即便是 root 用户也不行。这种属性常用于设置在系统或者关键服务中的配置文件,这对提升系统安全性有较大的帮助

[插图]

如果需要修改的不是一个文件而是一个目录,以及该目录下所有的文件、子目录、子目录下所有的文件和目录(即递归设置该目录下所有的文件和目录的权限),则需要使用-R 参数,

默认情况下,使用什么用户登录系统,那么该用户新创建的文件和目录的拥有者就是这个用户

改变文件的拥有组:chgrp 该命令用来更改文件的拥有组

文件特殊属性:SUID/SGID/Sticky

这就是奥秘所在—该命令是设置了 SUID 权限的,这意味着普通用户可以使用 root 的身份来执行这个命令

但是必须注意的是,SUID 权限只能用于二进制文件

SGID 就很容易了:如果某个二进制文件的用户组权限被设置了 s 权限,则该文件的用户组中所有的用户将都能以该文件的用户身份去运行这个命令

Sticky 权限只能用于设置在目录上,设置了这种权限的目录,任何用户都可以在该目录中创建或修改文件,但是只有该文件的创建者和 root 可以删除自己的文件。

可以给出一个结论:对于 root 用户,文件的默认权限是 644,目录的默认权限是 755;对于普通用户,文件的默认权限是 664,目录的默认权限是 775。

在 Linux 下,定义目录创建的默认权限的值是“umask 遮罩 777 后的权限”,定义文件创建的默认权限是“umask 遮罩 666 后的权限”。 系统在/etc/profile 文件中,通过第 51 行至 55 行的一段代码设置了不同用户的遮罩值。

[插图]

与 find 不同,locate 命令依赖于一个数据库文件,Linux 系统默认每天会检索一下系统中的所有文件,然后将检索到的文件记录到数据库中。

在执行这个命令之前一般需要执行 updatedb 命令(这不是必须的,因为系统每天会自动检索并更新数据库信息,但是有时候会因为文件发生了变化而系统还没有再次更新而无法找到实际上确实存在的文件。所以有时需要主动运行该命令,以创建最新的文件列表数据库)

which 用于从系统的 PATH 变量所定义的目录中查找可执行文件的绝对路径

使用 whereis 也能查到其路径,但是和 which 不同的是,它不但能找出其二进制文件,还能找出相关的 man 文件

gzip/gunzip 是用来压缩和解压缩单个文件的工具

tar 不但可以打包文件,还可以将整个目录中的全部文件整合成一个包,整合包的同时还能使用 gzip 的功能进行压缩

一般来说,整合后的包习惯使用.tar 作为其后缀名,使用 gzip 压缩后的文件则使用.gz 作为其后缀名。因为 tar 有同时整合和压缩的功能,所以可使用.tar.gz 作为后缀名,或者简写为.tgz

这里-z 的含义是使用 gzip 压缩,-c 是创建压缩文件(create),-v 是显示当前被压缩的文件,-f 是指使用文件名,也就是这里的 boot.tgz 文件。

上面的命令会直接将 boot.tgz 在当前目录中解压成 boot 目录,-z 是解压的意思。如需要指定压缩后的目录存放的位置,需要再使用-C 参数

使用 bzip2 压缩文件时,默认会产生以.bz2 扩展名结尾的文件,这里使用-z 参数进行压缩,使用-d 参数进行解压缩。

该命令一般是不单独使用的,需要和 find 命令一同使用。当由 find 按照条件找出需要备份的文件列表后,可通过管道的方式传递给 cpio 进行备份,生成/tmp/conf.cpio 文件,然后再将生成的/tmp/conf.cpio 文件中包含的文件列表完全还原回去。

◆ 第 4 章 Linux 文件系统

文件系统是操作系统用于明确磁盘或分区上相关文件的方法和数据结构,通俗的说法就是在磁盘上组织文件的方法。

大部分 Linux 系统都具有类似的通用结构,包括超级块(superblock)、i 节点(inode)、数据块(data block)、目录块(directory block)等

超级块包括文件系统的总体信息,是文件系统的核心,所以在磁盘中会有多个超级块,以防止由于磁盘出现坏块导致全部文件系统无法使用

i 节点存储所有与文件有关的元数据,也就是文件所有者、权限等属性数据以及指向的数据块,但是不包括文件名和文件内容

数据块是真实存放文件数据的部分,一个数据块默认情况下是 4KB

目录块包括文件名和文件在目录中的位置,并包括文件的 i 节点信息

Linux 最早引入的文件系统类型是 minix,由于其存在一定的局限性,比如说文件名最长仅支持 14 个字符,文件最大为 64MB 等因素,后来被 ext2(The Second Extended File System)文件系统所取代

但是 ext2 文件系统的弱点也是很明显的:它不支持日志功能。这很容易造成在一些情况下丢失数据,这个天然的弱点让 ext2 文件系统无法用于关键应用中,目前已经很少有企业使用 ext2 文件系统了。

那么为什么需要日志文件系统呢?因为日志文件系统使用了“两阶段提交”的方式来维护待处理的事务

比方说在写入数据之前,文件系统会先在日志中写入相关记录信息,然后再开始真实地写数据,写完数据后则会将之前写入日志中的内容删除

如果遇到问题需要检查文件系统或对 ext3 文件系统进行修复时,只需要检查日志即可

为了更好地使用磁盘空间,提高系统空间的可扩展性,此时就需要使用逻辑卷。

逻辑卷就是使用逻辑卷组管理(Logic Volume Manager)创建出来的设备,也是 Linux 操作系统可以认识的设备

LVM 是介于硬盘祼设备和文件系统的中间层

首先创建一个或多个物理卷,物理卷按照相同(或不同)的组名称聚集形成一个(或多个)物理卷组,而逻辑卷就是从某个物理卷组中抽象出来的一块磁盘空间。

在对逻辑卷创建文件系统的时候,其全路径是/dev/卷组名/逻辑卷名

硬链接(hard link)又称实际链接,是指通过索引节点来进行链接

在 Linux 文件系统中,所有的文件都会有一个编号,称为 inode,多个文件名指向同一索引节点是被允许的,这种链接就是硬链接

软链接(soft link)又称符号链接(symbolic link),是一个包含了另一个文件路径名的文件,可以指向任意文件或目录,也可以跨不同的文件系统

◆ 第 5 章 字符处理

在 Linux 中也存在着管道,它是一个固定大小的缓冲区,该缓冲区的大小为 1 页,即 4K 字节。

由于 grep 区分大小写,所以虽然第二行中含有大写的 NAME,但是也不会匹配到。如果希望忽略大小写,可以加上-i 参数。

如果想打印出文件中不包含 name 的行,可以使用 grep 的反选参数-v。

如果文件(或标准输出)中有多行完全相同的内容,我们很自然希望能删除重复的行,同时还可以统计出完全相同的行出现的总次数,uniq 命令就能帮助解决这个问题

uniq [-ic]
#-i 忽略大小写 
#-c 计算重复行数​​

需要说明的是,uniq 一般都需要和 sort 命令一起使用,也就是先将文件使用 sort 进行排序(这样重复的内容就能显示在连续的几行中),然后再使用 uniq 删除掉重复的内容(uniq 的作用就在于删除连续的完全一致的行)。

顾名思义,cut 就是截取的意思,它能处理的对象是“一行”文本,可从中选取出用户所需要的部分。

cut-f 指定的列-d’分隔符’​​

cut-c 指定列的字符​​

tr 命令比较简单,其主要作用在于文本转换或删除

paste 的作用在于将文件按照行进行合并,中间使用 tab 隔开

在 Linux 下使用 split 命令来实现文件的分割,支持按照行数分割和按照大小分割这两种模式

◆ 第 6 章 网络管理

nameserver 关键字后面紧跟着一个 DNS 主机的 IP 地址,可以设置 2~3 个 nameserver,但是主机在查询域名时会首先查询第一个 DNS,当该 DNS 不可用时才会查询第二个 DNS,以此类推

search 关键字后紧跟的是一个域名。每个主机严格来说都应该有一个 FQDN(全限定域名),所以往往域名就很长,如果这里写成 search google.com,那么 www 就代表 www.google. com 了,这个关键字后可以跟多个域名。

domain 关键字和 search 类似,不同的是 domain 后面只能跟一个域名。

host 命令是用来查询 DNS 记录的,如果使用域名作为 host 的参数,命令返回该域名的 IP

在 IP 包结构中有一个定义数据包生命周期的 TTL(Time To Live)字段,该字段用于表明 IP 数据包的生命值,当 IP 数据包在网络上传输时,每经过一个路由器该值就减 1,当该值减为 0 时此包就会被路由器丢弃。这种设计可用于避免出现一些由于某种原因始终无法到达目的地的包不断地在互联网上传递(可以形象地称之为“幽灵包”),减少无谓的网络资源耗用。

不过路由器也不是“无声无息”地将 TTL 值为 0 的 IP 包丢弃的,它会同时给发送该 IP 数据包的主机发送一个 ICMP“超时”消息,主机在接收到这个 ICMP 包后就同时能得到该路由的 IP 地址。

根据上面两个特点,人们写了一个检测数据包是如何经由路由器的工具—traceroute,我们可以想象一下该工具的工作原理:它先构造出一个 TTL 值为 1 的数据包发送给目的主机,这个数据包在经由第一个路由器时,路由器先将 TTL 值减 1 变为 0,然后将该 IP 包丢弃,同时给发送一个 ICMP 消息,这样就得到了经过的第一台路由器的 IP 地址;然后再构造出一个 TTL 值为 2 的数据包,以此类推,就能得到该 IP 包经历的整条链路的路由器 IP。

第一步是要确认网卡本身是否能正常工作?利用 ping 工具可以确认这点。输入 ping 127.0.0.1,然后看是否能正常 ping 通?这里的 127.0.0.1 被称为主机的回环接口,是 TCP/IP 协议栈正常工作的前提。

第二步是要确认网卡是否出现了物理或驱动故障,使用 ping 本机 IP 地址的方式,如果能 ping 通则说明本地设备和驱动都正常。

第三步要确认是否能 ping 通同网段的其他主机。这一步主要是确认二层网络设备(比如交换机或者 HUB)工作是否正常

第四步要确认是否能 ping 通网关 IP。如果数据包能正常到达网关,则说明主机和本地网络都工作正常。

第五步确认是否能 ping 通公网上的 IP,如果可以则说明本地的路由设置正确,否则就要确认路由设备是否做了正确的 nat 或路由设置。

第六步确认是否能 ping 通公网上的某个域名,如果能 ping 通则说明 DNS 部分设置正确。

◆ 第 7 章 进程管理

进程包括动态执行的程序和数据两部分

所有的进程都可能存在 3 种状态:运行态、就绪态、阻塞态

进程之间又存在互斥和同步的关系

现代计算机使用信号量机制来实现进程间的互斥和同步,它的基本原理是:两个或者多个进程可以通过简单的信号进行合作,一个进程可以被迫在某一位置停止,直到它接收到一个特定的信号。

进程是动态的,而程序是静态的,进程是程序以及数据在计算机上的一次执行,没有静态的程序也就没有动态的执行。

第三行是 CPU 信息,us 代表用户空间占用的 CPU 百分比,sy 代表内核空间占用的 CPU 百分比,ni 代表改变过优先级的进程占用的 CPU 百分比,id 代表空闲 CPU 百分比

wa 代表 I/O 等待百分比,hi 代表硬中断占用的 CPU 百分比,si 代表软中断占用的 CPU 百分比。

如果要显示更多的字段,可以在 top 显示界面中按字母键 f。

另外,默认情况下 top 显示的进程是按照 CPU 使用率来进行排序的,如果要另选排序规则怎么办呢?可以按大写字母 O 键进入排序选择页

比如按字母 P 键表示按照 CPU 的使用率排序,按字母 M 键表示按照 Memory 的使用率排序,按字母 N 键表示以 PID 排序,按字母 T 键表示按照 CPU 使用时间排序,按字母 K 键则表示 kill 进程,按字母 R 键表示可以 renice 一个进程等。

命令 kill 后可以跟的信号代码一共有 64 种,使用 kill-l 就可以看到具体有哪些

但是常用的一般只有 3 个,即 HUP(1)、KILL(9)、TERM(15),分别代表重启、强行杀掉、正常结束。

使用-9 参数强行停止该进程了,其效果是立即杀死进程,而且该信号无法被阻塞或忽略。但是这个命令也有其天然的危险,就是进程可能会直接被系统终止,而没有清理之前申请的内存,这会造成一定程度的“内存泄露”,因此一般情况下不建议使用。

而-15 这个参数就比较温和了,它会使进程正常退出,它也是 Linux 默认的程序中断信号(也就是在不加参数的情况下默认使用的信号)。

lsof(list open files)是一个列出当前系统中所有打开文件的工具。

在系统中,被打开的文件可以是普通文件、目录、网络文件系统中的文件、字符设备、管道、socket 等

输出的字段有 COMMAND、PID、USER、FD、TYPE、DEVICE、SIZE、NODE、NAME9 列,

COMMAND:进程的名称。 ▪ PID:进程标识符。 ▪ USER:进程所有者。 ▪ FD:文件描述符,应用程序通过文件描述符识别该文件。 ▪ TYPE:文件类型,如 DIR、REG 等。 ▪ DEVICE:磁盘的名称。 ▪ SIZE:文件大小。 ▪ NODE:索引节点。 ▪ NAME:打开文件的全路径名称。

尝试将其 umount 卸载,系统提示 device is busy,无法卸载。这时候使用 lsof 命令确认了一下,确实有进程在占用这个目录

使用 lsof 还可以查找使用了某个端口的进程

lsof-i:22

假设文件/var/log/messages 不小心被删除了,首先来确认一下当前是否有进程正在使用这个文件,如果有则可以继续,如果没有就无法使用该方法继续了。本例中看到有个 PID 为 2449 的进程正在使用该文件,那么接下来只要找到对应/proc 目录下的文件就可以了

在学习 top 时,我们看到其输出中有 NI 字段,标记了对应进程的优先级,该字段的取值范围是-20~19,数值越低代表优先级越高,也就能更多地被操作系统调度运行,如果一个进程在启动时并没有设定 nice 优先级,则默认使用 0

普通用户也可以给自己的进程设定 nice 优先级,但是范围只限于 0~19。

实际上,Linux 使用了“动态优先级”的调度算法来确定每一个进程的优先级,一个进程的最终优先级=优先级 +nice 优先级。

nice 命令仅限于在启动一个进程的时候同时赋予其 nice 优先级

对于已经启动的进程,可以用 renice 命令进行修改

除了使用 renice 外,还可以使用 top 提供的功能来修改

◆ 第 8 章 Linux 下的软件安装

在 Linux 系统中,一般在/usr/local/src/目录里下载源码包(这不是硬规定,而是一个良好的习惯

一般来说建议自行编译安装的软件放置的目录为/usr/local/

源码编译的前提是系统中安装了 gcc 工具,对于注重安全生产环境的用户而言是不应该安装这个工具的

RPM 是 RedHat Package Manager 的简写,顾名思义是红帽软件包管理器的意思

Linux 中一切皆文件,所以说白了,RMP 其实是一种集成了文件管理和软件版本控制的工具

RPM 分为两类,第一类是二进制安装包(也就是预编译包)

如果将编译好的软件复制到相同软件环境(内核版本一致、软硬件运行环境一致)的服务器中,只要软件在原编译机中能运行,那么在新主机中也同样可以运行

第二类是 RPM 源码包,当希望自定义编译参数,自行制作二进制安装包的时候使用

使用 RPM 包管理的方式是通过 rpm 命令

默认情况下 RedHat 会因为未注册 RHN 而无法使用 yum

作为一个 Linux 工程师,不能把技术活做成体力活。

如果读者在网上搜索自建网络 yum 源的相关文档,可能会发现其中十有八九都有使用 createrepo 工具重新创建 repodata 这一步骤

RPM 包有两种,一种是二进制安装包,还有一种是源码包,这种包的后缀名一般以.src.rpm 结束(有时简称为 srpm),标识着这是一个“包含源码的 RPM 包”。

◆ 第 9 章 vi 和 vim 编辑器

vi 编辑器是 Visual Interface 的简称,是 Linux 系统中最基本的文本编辑器

◆ 第 10 章 正则表达式

sed 其实是以行为单位的文本处理工具,而 awk 则是基于列的文本处理工具

它的工作方式是按行读取文本并视为一条记录,每条记录以字段分割成若干字段,然后输出各字段的值。

◆ 第 11 章 Shell 编程概述

当你使用 ssh 客户端工具远程连接到系统,或坐在一台服务器前输入密码登录到系统中时,面前呈现的跳动的光标就是一个 Shell

在计算机语言中,Shell 是指一种命令行解释器,是为用户和操作系统之间通信提供的一种接口

图 11-1 显示了 Shell 在操作系统中的位置。 

cat /etc/Shells

为了对用户屏蔽这些复杂的技术细节,同时也是为了保护内核不会因用户直接操作而受到损害,有必要在内核之上创建一个层,该层就是一个“壳”,也就是 Shell 名称的由来。

Bash Shell 有两种工作模式,分别是互动模式和脚本模式

个 Shell 脚本永远是以“#!”开头的,这是一个脚本开始的标记,它是在告诉系统执行这个文件需要使用某个解释器,后面的/bin/bash 就是指明了解释器的具体位置。

为了更清晰地看到脚本运行的过程,还可以借助-x 参数来观察脚本的运行情况

为了更精细地调试运行 Shell,我们可以借助第三方工具 bashdb。这是一个类似于 GDB 的脚本调试软件,小巧而强大,具有设置断点、单步执行、观察变量等功能

所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件

通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。

不要试图用脑子记住所有的命令,这不可能也不需要。判断一个命令是不是内建命令只需要借助于命令 type 即可

点号用于执行某个脚本,甚至脚本没有可执行权限也可以运行

alias 可用于创建命令的别名,若直接输入该命令且不带任何参数,则列出当前用户使用了别名的命令。

任务前后台切换:bg、fg、jobs 该命令用于将任务放置后台运行,一般会与 Ctrl+z、fg、&符号联合使用

declare、typeset 这两个命令都是用来声明变量的,作用完全相同。

Shell 又被称为弱类型编程语言

若使用 declare 命令,可以用-i 参数声明整型变量,

使用-r 声明变量为只读

使用-a 声明变量

使用-F、-f 显示脚本中定义的函数和函数体,

echo 用于打印字符

该命令会打印出引号中的内容,并在最后默认加上换行符

使用-n 参数可以不打印换行符。

默认情况下,echo 命令会隐藏-e 参数(禁止解释打印反斜杠转义的字符)。比如“\n”代表新的一行,如果尝试使用 echo 输出新的一行,在不加参数的情况下只会将“\n”当作普通的字符,若要打印转义字符,则需要通过使用-e 参数来允许。

从一个循环(for、while、until 或者 select)中退出。break 后可以跟一个数字 n,代表跳出 n 层循环,n 必须大于 1,如果 n 比当前循环层数还要大,则跳出所有循环

continue 停止当前循环,并执行外层循环(for、while、until 或者 select)的下一次循环。continue 后可以跟上一个数字 n,代表跳至外部第 n 层循环

将所跟的参数作为 Shell 的输入,并执行产生的命令:eval

内建命令 exec 并不启动新的 Shell,而是用要被执行的命令替换当前的 Shell 进程,并且将老进程的环境清理掉,而且 exec 命令后的其他命令将不再执行

假设在一个 Shell 里面执行了 exec echo ”Hello”命令,在正常地输出一个“Hello”后 Shell 会退出,因为这个 Shell 进程已被替换为仅仅执行 echo 命令的一个进程,执行结束自然也就退出了

exec 典型的用法是与 find 联合使用,用 find 找出符合匹配的文件,然后交给 exec 处理,如下所示:

在 Shell 脚本中使用 exit 代表退出当前脚本

该命令可以接受的参数是一个状态值 n,代表退出的状态

如果不指定,默认状态值是 0

使用 $?可以取出之前命令的退出状态值

要说明的是,即便子 Shell 确实读取到了父 Shell 中变量 var 的值,也只是值的传递,如果在子 Shell 中尝试改变 var 的值,改变的只是 var 在子 Shell 中的值,父 Shell 中的该值并不会因此受到影响,你可以认为父 Shell 和子 Shell 都各自拥有一个叫 var 的变量,它们恰巧名字相同而已。

发送信号给指定 PID 或进程:kill

Linux 操作系统包括 3 种不同类型的进程

第一种是交互进程,这是由一个 Shell 启动的进程,既可以在前台运行,也可以在后台运行

第二种是批处理进程,与终端没有联系,是一个进程序列

第三种是监控进程,也称系统守护进程,它们往往在系统启动时启动,并保持在后台运行

let 是 Shell 内建的整数运算命令

pwd 命令会打印当前工作目录的绝对路径名

如果使用-P 选项,打印出的路径名中不会包含符号连接

如果使用了-L 选项,打印出的路径中可以包含符号连接

声明局部变量:local

该命令用于在脚本中声明局部变量,典型的用法是用于函数体内,其作用域也在声明该变量的函数体中。如果试图在函数外使用 local 声明变量,则会提示错误。

从标准输入读取一行到变量:read

实际上 read 可以使用-p 参数代替

如果不指定变量,read 命令会将读取到的值放入环境变量 REPLY 中

另外要记住,read 是按行读取的,用回车符区分一行,你可以输入任意文字,它们都会保存在变量 REPLY 中。

定义函数返回值:return

典型的用于函数中,常见用法是 return n,其中 n 是一个指定的数字,使函数以指定值退出

如果没有指定 n 值,则返回状态是函数体中执行的最后一个命令的退出状态。

向左移动位置参数:shift

假设一个脚本在运行时可以接受参数,那么从左到右第一个参数被记作 $1,第二个参数为 $2,以此类推,第 n 个参数为 $N

所有参数记作$@或$*,参数的总个数记作 $#,而脚本本身记作 $0。

shift 命令可以对脚本的参数做“偏移”操作

使用 ulimit 可以控制进程对可用资源的访问

默认情况下 Linux 系统的各个资源都做了软硬限制,其中硬限制的作用是控制软限制(换言之,软限制不能高于硬限制)

使用 ulimit-a 可以查看当前系统的软限制(使用命令 ulimit-a-H 可查看系统的硬限制)

使用 ulimit 直接调整参数,只会在当前运行时生效,一旦系统重启,所有调整过的参数就会变回系统默认值。所以建议将所有的改动放在 ulimit 的系统配置文件中。

测试表达式:test

该命令用于测试表达式 EXPRESSION 的值,根据测试结果返回 0(测试失败)或 1(测试成功)。

◆ 第 12 章 Bash Shell 的安装

Linux 是学习 Bash Shell 的天然环境,但是借助工具,在 Windows 下同样可以运行 bash

最著名的工具是 Cygwin,它是模拟类 UNIX 环境的软件,最初由 Cygnus Solution 公司开发,目的在于通过重新编译将 Linux 系统上的软件移植到 Windows 上。

◆ 第 13 章 Shell 编程基础

可以使用 local 内建命令来“显式”的声明局部变量,但仅限于函数内使用

每个 Shell 都有自己的变量空间,彼此互不影响

环境变量通常又称“全局变量”,以区别于局部变量

为了让子 Shell 继承当前 Shell 的变量,则可以使用 export 内建命令将其导出为环境变量

bash 中默认包含有几十个预设的环境变量,这里挑选常见的一些予以介绍

变量:BASH 说明:Bash Shell 的全路径。

变量:BASH_VERSION 说明:Bash Shell 的版本。

变量:CDPATH 说明:用于快速进入某个目录。

变量:EUID 说明:记录当前用户的 UID

变量:FUNCNAME 说明:在用户函数体内部,记录当前函数体的函数名。

变量:HISTCMD 说明:记录下一条命令在 history 命令中的编号

变量:HISTFILE 说明:记录 history 命令记录文件的位置

变量:HISTFILESIZE 说明:设置 HISTFILE 文件记录命令的行数。

变量:HISTSIZE

Shell 采用了“命令缓冲区”来记录所有已运行过的命令,在缓冲区满或退出 Shell 时才将缓冲区的记录写到 HISTFILE 文件中。缓冲区的大小使用 HISTSIZE 定义。

变量:HOSTNAME 说明:展示主机名。

变量:HOSTTYPE 说明:展示主机的架构,是 i386、i686,还是 x86_64 等。

变量:MACHTYPE 说明:主机类型的 GNU 标识,这种标识有统一的结构。一般来说是“主机架构-公司-系统-gnu”

变量:LANG 说明:设置当前系统的语言环境,其实就是 language 的意思。

变量:PWD 说明:记录当前目录。

变量:OLDPWD 说明:记录之前目录,这个值是什么由之前所在的那个目录决定。

变量:PATH

代表命令的搜索路径

变量:PS1 说明:命令提示符,默认值是[\u@\h \W]\$,其中\u 是用户名、\h 是主机名、\W 是当前工作目录的 basename、\$是用户 UID 的替换字符:如果 UID 是 0 则替换成“#”,否则替换成“$”,所以此处具体显示出来就是“[root@localhost ~]#”。该变量可以有很多种组合,可以根据自己的喜好进行定制。

[插图]

[插图]

Shell 中的变量必须以字母或者下划线开头,后面可以跟数字、字母和下划线,变量长度没有限制。

定义变量:变量名=变量值 

注意点一:变量名和变量值之间用等号紧紧相连,之间没有任何空格 

注意点二:当变量中有空格时必须用引号括起,否则会出现错误 

变量的取值也很简单,只需要在变量名前加上$符号既可,严谨一点的写法是${}

由于 Shell 具有“弱变量”的特性,因此即便在没有预先声明变量的时候也是可以引用的,而且没有任何报错或者提醒,这可能会造成脚本中引用不正确的变量,从而导致脚本异常,但是却很难找出原因。

#设置变量必须先声明再使用 
[root@localhost ~]# shopt-s-o nounset

取消变量指的是将变量从内存中释放,使用的命令是 unset,后面跟变量名

函数也是可以被取消的,所以 unset 后面还可以跟上函数名以取消函数

Shell 中还有一些预先定义的特殊只读变量,它们的值只有在脚本运行时才能确定

首先是“位置参数”,位置参数的命名简单直接,比如,脚本本身为 $0,第一个参数为 $1,第二个参数为 $2,第三个为 $3,以此类推。当位置参数的个数大于 9 时,需要用${}括起来标识,比如说第10个位置参数应该记为${10

$#表示脚本参数的个数总和,$@或 $*表示脚本的所有参数。

脚本或命令返回值:$?

Shell 中的数组对元素个数没有限制,但只支持一维数组,这一点和很多语言不同。

数组的定义方法如下:用 declare 命令定义数组 Array

最简单的操作就是数组取值,其格式为:${数组名[索引]}。

${Array[@]}得到的是以空格隔开的元素值,而${Array[*]}的输出是一整个字符串。

利用“@”或“*”字符,可以将数组扩展成列表,然后使用“#”来获取数组元素的个数,

可以截取某个元素的一部分,对象可以是整个数组或某个元素。

连接数组:将若干个数组进行拼接操作。

替换元素:将数组内某个元素的值替换成其他值。

取消数组或元素:和取消一般变量一样,取消一个数组的方式也使用 unset 命令。

只读变量又称常量,是通过 readonly 内建命令创建的变量。

变量的作用域又叫“命名空间”,表示变量(identifier,标识符)的上下文。

在 Linux 系统中,不同进程 ID 的 Shell 默认为一个不同的命名空间

Shell 中有两类字符,一类是普通字符,在 Shell 中除了本身的字面意思外没有其他特殊意义,即普通纯文本(literal);另一类即元字符(meta),是 Shell 的保留字符,在 Shell 中有着特殊意义

Shell 中的转义符是反斜线“\”,使用转义符的目的是使转义符后面的字符单纯地作为字符出现,而不解释其特殊的含义

[插图]

引用是指将字符串用某种符号括起来,以防止特殊字符被解析为其他意思

比如说上一小节中的转义符就是一种引用

Shell 中一共有 4 种引用符,分别是双引号、单引号、反引号(在键盘上和波浪号位于同一个键)和转义符。

其中双引号又叫“部分引用”或“弱引用”,可以引用除 $ 符、反引号、转义符之外的所有字符

单引号又叫“全引用”或“强引用”,可以引用所有字符

反引号则会将反引号括起的内容解释为系统命令

部分引用是指用双引号括起来的引用。在这种引用方式中,$ 符、反引号(`)、转义符(\)这 3 种特殊字符依然会被解析为特殊意义

全引用是指用单引号括起来的引用。单引号中的任何字符都只当作是普通字符(除了单引号本身,也就是说单引号中间无法再包含单引号,即便用转义符转义单引号也不行)

命令替换是指将命令的标准输出作为值赋给某个变量

Shell 中有两种方式可以完成命令替换,一种是反引号(`),一种是 $()

要注意的是,$()仅在 Bash Shell 中有效,而反引号可在多种 UNIX Shell 中使用。

Shell 中的运算符主要有比较运算符(用于整数比较)、字符串运算符(用于字符串测试)、文件操作运算符(用于文件测试)、逻辑运算符、算术运算符、位运算符、自增自减运算符等

算术运算符指的是加、减、乘、除、余、幂等常见的算术运算,以及加等、减等、乘等、除等、余等复合算术运算

要特别注意的是,Shell 只支持整数计算

常见的位运算有左移运算、右移运算、按位与、按位或、按位非、按位异或等运算。

按位与运算(&),是将两个整数写成二进制的形式,然后同位置相比较,只有当对应的二进制值都为 1 时,结果才为 1。

按位或运算(|),是将两个整数写成二进制的形式,然后同位置相比较,只要对应的位置有 1,结果就为 1。

按位异或运算(^),是将两个整数写成二进制的形式,然后同位置相比较,只要对应的位置同为 0 或同为 1,结果就为 0,否则为 1。

按位非(~)的计算方式比较麻烦,这里有个快捷的计算公式:“~a”的值为“-(a+1)”。

自增自减运算主要包括前置自增、前置自减、后置自增、后置自减等

$[]和$(())类似,可用于简单的算术运算

expr 命令也可用于整数运算

和其他算术运算方式不同,expr 要求操作数和操作符之间使用空格隔开(否则只会打印出字符串),所以特殊的操作符要使用转义符转义(比如*)。 expr 支持的算术运算符有加、减、乘、除、余等,

declare 是 Shell 的内建命令,通过它们也能进行整数运算

它和显式使用 declare 定义变量的差别是很大的。

1 里的变量 I 未经正式定义便赋值“1+1”,对 Shell 来说,此时的“1+1”只是一个字符串,和“abc”无异,所以打印出来也只是字符串。而例 2 中,使用 declare 显式地定义了整数变量 J(-i 参数指定变量为“整数”),此时再赋值“1+1”,Shell 会将后面的字符串解析成算术运算,所以打印出的值是算术表达式的计算值。

算术扩展是 Shell 提供的整数变量的运算机制,是 Shell 的内建命令之一

基本语法如下: ​​$((算术表达式))​​

其中的算术表达式由变量和运算符组成,常见的用法是显示输出和变量赋值

Linux 下的 bc 正是这样一款专门用于高精度计算的工具

与其说 bc 是一个命令或者工具,不如说它是一门语言,bc 的 man 文件对它的描述是:“一款高精度计算语言(An arbitrary precision calculator language)”。

设置显示的小数位数 
scale=3

默认情况下 bc 并不显示小数部分,必须设置要显示的小数位数

希望一次性处理多个计算,只需要创建一个文件,并按行写好需要计算的表达式就可以了

如果想让脚本变得更灵活,也可以使用 read 命令动态地给变量赋值。

Shell 中除了普通字符外,还有很多具有特殊含义和功能的字符,在使用它们时要特别注意其含义和作用。

通配符用于模式匹配,常见的通配符有*、?和用[]括起来的字符序列

Shell 使用#作为注释符。

如果出现#后连着!,也就是“#!”不会被理解成注释,因此,其后跟着的部分必须是某个解释器的路径,而且“#!”必须出现在整个脚本的第一行。

.通配符扩展 用于匹配多个排列组合的可能。

比如坐标,横坐标是 x1、x2、x3,纵坐标是 y1、y2、y3,那么所有可能的坐标就是{x1,x2,x3}{y1,y2,y3}。

还可以用于匹配不同的文件,文件名的特征是只有其中一部分不同。比如 file_A、fileB,就可以用 file{A,B}来匹配

控制字符即 Ctrl+KEY 组合键一起使用,用于修改终端或文本显示。但是控制字符在脚本中不能使用,也就是说控制字符是交互式使用的

[插图]

引号 反引号用于命令替换,和 $()的作用相同,表示返回当前命令的执行结果并赋值给变量。

位置参数的含义如下。 $0:脚本名本身。 $1、$2……${10}:脚本的第一个参数、第二个参数……第十个参数。 $#:变量总数。 $*、$@:显示所有参数。 $?:前一个命令的退出的返回值。 $!:最后一个后台进程的 ID 号。

◆ 第 14 章 测试和判断

测试的第一种使用方式是直接使用 test 命令,该命令的格式如下: ​​test expression​​

其中 expression 是一个表达式,可以是算术比较、字符串比较、文本和文件属性比较等

第二种测试方式是使用“[”启动一个测试,再写 expression,再以“]”结束测试。需要注意的是,左边的括号“[”后有个空格,右括号“]”前面也有个空格,如果任意一边少了空格都会造成 Shell 报错

增加代码的可读性,推荐使用第二种方式,而且这种方式更容易与 if、case、while 这些条件判断的关键字连用

​​#文件测试方法一 
test file_operator FILE
#文件测试方法二 
[ file_operator FILE ]​​

[插图]

Shell 中的字符串比较主要有等于、不等于、大于、小于、是否为空等测试

[插图]

整数测试是一种简单的算术运算,作用在于比较两个整数的大小关系,测试成立则返回 0,否则返回非 0 值

[插图]

逻辑测试主要有逻辑非、逻辑与、逻辑或 3 种

[插图]

[插图]

if expression; then
 command
fi​​ 如果 expression 测试返回真,则执行 command

if expression; then
 command
else
 command
fi​​

if expression1; then
 command1
else
 if expression2; then
 command2
 else
 command3
 fi
fi​​

case VAR in
var1) command1 ;;
var2) command2 ;;
var3) command3 ;;
…
*) command ;;
esac​​

◆ 第 15 章 循环

在现实生活中,如果要某人不断地重复做某一件事情,那么他很快就会感觉到厌倦,并慢慢失去兴趣,随后效率也会渐渐降低,并越来越容易出错。而计算机在这方面就显得非常有“天赋”:它天生就适合做重复的事情,并乐此不疲。

Shell 中的循环主要有 for、while、until、select 几种。

​​for VARIABLE in (list)
do
 command
done​​

比如说上例中 1 到 5 可以用{1..5}表示

还可以使用 seq 命令结合命令替换的方式生成列表

其实列表 for 循环中 in 后面的内容可以是任意命令的标准输出

[root@localhost ~]# cat for_list05.sh
#!/bin/bash
for VAR in $(ls)
do
 ls-l $VAR
done​​

不带列表的 for 循环的结构如下所示: ​​for VARIABLE
do
 command
done​​

使用不带列表的 for 循环时,需要在运行脚本时通过参数的方式给 for 循环传递变量值

该语法虽然可以工作,但是可读性较差,所以不建议使用。可利用特殊变量 $@改写上述结构

Shell 支持类 C 的 for 循环

和 for 循环一样,while 循环也是一种运行前测试语句,相比 for 循环来说,其语法更为简单

while expression
do
 command
done​​

按行读取文件是 while 一个非常经典的用法,常用于处理格式化数据。

#方法一 
while ((1))
do
 command
done​​
​​#方法二 
while true
do
 command
done​​
​​方法三 
while :
do
 command
done​​

我们可以利用 while 的无限循环实时的监测系统进程,以保证系统中的关键应用一直处于运行状态。

until 循环也是运行前测试,但是 until 采用的是测试假值的方式,当测试结果为假时才继续执行循环体,直到测试为真时才停止循环

until expression
do
 command
done​​

和 while 的无限循环相反,until 的无限循环的条件是判断假成立时退出

​​#方法一 
until ((0))
do
 command
done
#方法二 
until false
do
 command
done​​

select 是一种菜单扩展循环方式,其语法和带列表的 for 循环非常类似,基本结构如下:

select MENU in (list)
do
 command
done​​

当程序运行到 select 语句时,会自动将列表中的所有元素生成为可用 1、2、3 等数选择的列表,并等待用户输入。用户输入并回车后,select 可判断输入并执行后续命令。如果用户在等待输入的光标后直接按回车键,select 将不会退出而是再次生成列表等待输入。

除了确实必要的情况下,不建议使用多层嵌套(三层以上的嵌套)。

break 用于终止当前整个循环体。

continue 语句用于结束当前循环转而进入下一次循环

◆ 第 16 章 函数

函数是 Shell 脚本中自定义的一系列执行命令,一般来说函数应该设置有返回值(正确返回 0,错误返回非 0。

使用函数最大的好处是可避免出现大量重复代码,同时增强了脚本的可读性

函数的返回值又叫函数的退出状态,实际上是一种通信方式。

除了在脚本运行时给脚本传入位置参数外,还可以使用内置命令 set 命令给脚本指定位置参数的值(又叫重置)。一旦使用 set 设置了传入参数的值,脚本将忽略运行时传入的位置参数(实际上是被 set 命令重置了位置参数的值)

对某些很常用的功能,必须考虑将其独立出来,集中存放在一些独立的文件中,这些文件就称为“函数库”。

为了和一般函数区分开来,在实践中建议库函数使用下划线开头。

由于 Shell 是一门面向过程的脚本型语言,而且用户主要是 Linux 系统管理人员,所以并没有非常活跃的社区

很多 Linux 发行版中都有/etc/init.d 目录,这是系统中放置所有开机启动脚本的目录,这些开机脚本在脚本开始运行时都会加载/etc/init.d/functions 或/etc/rc.d/init.d/functions 函数库(实际上这两个函数库的内容是完全一样的)

实际上 functions 函数库中定义了 27 个函数,表 16-1 中列举了常见的 17 个。

[插图]

具有“递归”功能的函数则被称为“递归函数”。递归函数的典型特征为:在函数体中继续调用函数自身。

递归函数一定要有结束递归的条件,当满足该条件时,递归就会终止

典型的递归函数的结构如下所示: ​​function recursion() {
 recursion
 conditionThatEndTheRecursion #停止递归的条件 
}​​

数学中有个经典的需要使用递归算法计算的公式是:阶乘。

递归另一个典型的例子是“汉诺塔”游戏

嵌套函数天生的结构就注定了其晦涩的可读性,在不少大公司内部的开发规范中也明确规定了不允许使用递归,所以在实际工作中要尽量避免使用递归。不过实际上你更可能根本没有使用递归的机会—从笔者多年从事 Linux 系统管理的经验来看,基本上不存在必须使用递归才能解决问题的场景。

◆ 第 17 章 重定向

计算机最基础的功能是可以提供输入输出操作

常见的输入设备有键盘、鼠标、扫描仪等,对于 Linux 系统来说,通常以键盘为默认输入设备,又称标准输入设备;计算机常见的输出设备有显示器、蜂鸣器、打印机等,而 Linux 系统则以显示器为默认的输出设备,又称标准输出设备

所谓“重定向”,就是将原本应该从标准输入设备(键盘)输入的数据,改由其他文件或设备输入;或将原本应该输出到标准输出设备(显示器)的内容,改而输出到其他文件或设备上。

文件标识符是重定向中很重要的一个概念,Linux 使用 0 到 9 的整数指明了与特定进程相关的数据流

系统在启动一个进程的同时会为该进程打开三个文件:标准输入(stdin)、标准输出(stdout)、标准错误输出(stderr),分别用文件标识符 0、1、2 来标识

如果要为进程打开其他的输入输出,则需要从整数 3 开始标识

默认情况下,标准输入为键盘,标准输出和错误输出为显示器。

简单来说,I/O 重定向可以将任何文件、命令、脚本、程序或脚本的输出重定向到另外一个文件、命令、程序或脚本。

[插图]

如果指定的重定向文件存在且内容不为空,重定向并不会清空原文件内容,而是将命令的输出新增到原文件的尾部。

标识输出重定向的作用是将一个标识的输出重定向到另一个标识的输入。

这时可以利用系统中的一个特殊设备/dev/null,将所有错误输出重定向到该设备中—系统会将任何输入到该设备的内容全部删除(就像一个宇宙黑洞)

标准输入重定向可以将原本应由从标准输入设备中读取的内容转由文件内容输入,也就是将文件内容写入标准输入中。

简单地说管道就是将一个命令的输出作为另一个命令的输入,借此方式可通过多个简单命令的共同协作来完成较为复杂的工作

exec 还可以用于 I/O 重定向

[插图]

实际上,文件标识符类似于很多编程语言中的“句柄”。在 Linux 中,文件标识符也是一种“设备”,这个标识符会出现在/dev/fd 目录中

进入这个目录,可以看到 3 是一个到该文件的软链接

主动打开的文件标识符需要主动关闭,否则除了系统重启,该文件标识符会一直被占用

由于在脚本中无法使用组合键,因此要终止输入就需要用到 Here Document

◆ 第 18 章 脚本范例

从字面上就能大概猜出 expect 的用途,即“期待”系统的输出,且对应地发送输入作为响应。

netcat 被誉为网络工具中的“瑞士军刀”,体积虽小但是功能强大。netcat 最简单的功能是用于端口扫描

系统在启动时将根据当前的运行级(runlevel X)确定运行在/etc/rc.d/rcX.d 目录下的脚本(都是到/etc/init.d 目录中的文件软链接)。

和一般的 shell 脚本不同,init 脚本需要满足一定的格式,最基本的要求是,脚本必须接收至少两个参数:start 和 stop,分别用于启动和停止服务。

LVM 的快照(snapshot)功能可以很好地解决这个问题。在对一个 LV 创建 snapshot 时,仅会复制其中的元数据,而不会有任何真实数据的复制,所以创建过程几乎是实时的

当原 LV 有写操作时,数据会写到快照中而不是原 LV 中(写时复制机制,Copy On Write, CoW),从而保证了原 LV 中数据的一致性。为了确保数据的一致(这里特指 MySQL 数据),在对其做快照之前也需要对数据库进行锁定操作,做完快照后再解除锁。

由于快照的过程极为迅速,所以短时间的数据库锁定并不会对前台应用造成影响。

[摘录]《Ceph分布式存储实战》 – Ceph中国社区

Ceph分布式存储实战 Ceph中国社区 135个笔记

◆ 本书赞誉

Ceph的CRUSH算法引擎,聪明地解决了数据分布效率问题

开源系统是Linux的世界,开源管理平台是OpenStack的世界,开源存储是Ceph的世界。

◆ 前言

美国雅虎公司使用Ceph构建对象存储系统,用于Flickr、雅虎邮箱和Tumblr(轻量博客)的后端存储;国内不少公有云和私有云商选择Ceph作为云主机后端存储解决方案。

◆ 第1章 初识Ceph

Ceph可以同时提供对象存储RADOSGW(Reliable、Autonomic、Distributed、Object Storage Gateway)、块存储RBD(Rados Block Device)、文件系统存储Ceph FS(Ceph Filesystem)3种功能

其对象存储可以对接网盘(owncloud)应用业务等;其块设备存储可以对接(IaaS)

以OpenStack为核心的云厂商:例如UnitedStack、Awcloud等国内云计算厂商。

在Ceph存储中,包含了几个重要的核心组件,分别是Ceph OSD、Ceph Monitor和Ceph MDS

一个Ceph的存储集群至少需要一个Ceph Monitor和至少两个Ceph的OSD。

运行Ceph文件系统的客户端时,Ceph的元数据服务器(MDS)是必不可少的

Ceph OSD:全称是Object Storage Device,主要功能包括存储数据,处理数据的复制、恢复、回补、平衡数据分布,并将一些相关数据提供给Ceph Monitor,例如Ceph OSD心跳等

每一个Disk、分区都可以成为一个OSD。

Ceph MDS:全称是Ceph Metadata Server,主要保存的是Ceph文件系统(File System)的元数据(metadata)。

RADOSGW功能特性基于LIBRADOS之上,提供当前流行的RESTful协议的网关,并且兼容S3和Swift接口,作为对象存储,可以对接网盘类应用以及HLS流媒体应用等。

RBD(Rados Block Device)功能特性也是基于LIBRADOS之上,通过LIBRBD创建一个块设备,通过QEMU/KVM附加到VM上,作为传统的块设备来用。

Ceph FS(Ceph File System)功能特性是基于RADOS来实现分布式的文件系统,引入了MDS(Metadata Server),主要为兼容POSIX文件系统提供元数据。一般都是当做文件系统来挂载。

Ceph底层核心是RADOS

[插图]

RADOS:RADOS具备自我修复等特性,提供了一个可靠、自动、智能的分布式存储。

LIBRADOS:LIBRADOS库允许应用程序直接访问,支持C/C++、Java和Python等语言

RADOSGW:RADOSGW是一套基于当前流行的RESTful协议的网关,并且兼容S3和Swift。

RBD:RBD通过Linux内核(Kernel)客户端和QEMU/KVM驱动,来提供一个完全分布式的块设备

Ceph FS:Ceph FS通过Linux内核(Kernel)客户端结合FUSE,来提供一个兼容POSIX的文件系统。

Ceph系统最终采用Crush、Hash环等方法更彻底地解决了这个问题。很显然Sage的眼光和设想还是很超前的。

◆ 第2章 存储基石RADOS

Cluster Map是整个RADOS系统的关键数据结构,管理集群中的所有成员、关系和属性等信息以及数据的分发。

对于RADOS系统,节点组织管理和数据分发策略均由内部的Mon全权负责,因此,从Client角度设计相对比较简单,它给应用提供存储接口

Ceph monitor map包括OSD Map、PG Map、MDS Map和CRUSH等,这些Map被统称为集群Map。

Monitor Map。Monitor Map包括有关monitor节点端到端的信息,其中包括Ceph集群ID,监控主机名和IP地址和端口号,它还存储了当前版本信息以及最新更改信息

可以通过以下命令查看monitor map。 ​​#ceph mon dump​​

OSD Map。OSD Map包括一些常用的信息,如集群ID,创建OSD Map的版本信息和最后修改信息,以及pool相关信息,pool的名字、pool的ID、类型,副本数目以及PGP,还包括OSD信息,如数量、状态、权重、最新的清洁间隔和OSD主机信息

可以通过执行以下命令查看集群的OSD Map。 ​​#ceph osd dump​​

PG Map包括当前PG版本、时间戳、最新的OSD Map的版本信息、空间使用比例,以及接近占满比例信息,同时,也包括每个PG ID、对象数目、状态、OSD的状态以及深度清理的详细信息

可以通过以下命令来查看PG Map。 ​​#ceph pg dump​​

CRUSH Map包括集群存储设备信息,故障域层次结构和存储数据时定义失败域规则信息

可以通过以下命令查看CRUSH Map。 ​​#ceph osd crush dump​​

MDS Map包括存储当前MDS Map的版本信息、创建当前Map的信息、修改时间、数据和元数据POOL ID、集群MDS数目和MDS状态

可通过以下命令查看集群MDS Map信息。 ​​#ceph mds dump​​

Ceph Monitor并未为客户提供数据存储服务,而是为Ceph集群维护着各类Map,并服务更新群集映射到客户机以及其他集群节点。客户端和其他群集节点定期检查并更新于Monitor的集群Map最新的副本。

一个典型的Ceph集群包含多个Monitor节点

一个多Monitor的Ceph的架构通过法定人数来选择leader,并在提供一致分布式决策时使用Paxos算法集群

在Ceph集群中有多个Monitor时,集群的Monitor应该是奇数;最起码的要求是一台监视器节点

由于Monitor工作在法定人数,一半以上的总监视器节点应该总是可用的,以应对死机等极端情况,这是Monitor节点为N(N>0)个且N为奇数的原因

所有集群Monitor节点,其中一个节点为Leader。如果Leader Monitor节点处于不可用状态,其他显示器节点有资格成为Leader

生产群集必须至少有N/2个监控节点提供高可用性。

Ceph OSD将数据以对象的形式存储到集群中每个节点的物理磁盘上,完成存储用户数据的工作绝大多数都是由OSD deamon进程来实现的

Ceph集群一般情况都包含多个OSD,对于任何读写操作请求,Client端从Ceph Monitor获取Cluster Map之后,Client将直接与OSD进行I/O操作的交互,而不再需要Ceph Monitor干预

Ceph的核心功能特性包括高可靠、自动平衡、自动恢复和一致性

对于Ceph OSD而言,基于配置的副本数,Ceph提供通过分布在多节点上的副本来实现,使得Ceph具有高可用性以及容错性

OSD中的每个对象都有一个主副本,若干个从副本,这些副本默认情况下是分布在不同节点上的

每个OSD都可能作为某些对象的主OSD,与此同时,它也可能作为某些对象的从OSD,从OSD受到主OSD的控制,然而,从OSD在某些情况也可能成为主OSD

在磁盘故障时,Ceph OSD Deamon的智能对等机制将协同其他OSD执行恢复操作。在此期间,存储对象副本的从OSD将被提升为主OSD,与此同时,新的从副本将重新生成,这样就保证了Ceph的可靠和一致。

Ceph OSD架构实现由物理磁盘驱动器、在其之上的Linux文件系统以及Ceph OSD服务组成

Ceph OSD操作必须在一个有效的Linux分区的物理磁盘驱动器上,Linux分区可以是BTRFS、XFS或者EXT4分区,文件系统是对性能基准测试的主要标准之一

BTRFS:在BTRFS文件系统的OSD相比于XFS和EXT4提供了最好的性能

XFS:一种高性能的日志文件系统,XFS特别擅长处理大文件,同时提供平滑的数据传输。目前CentOS 7也将XFS+LVM作为默认的文件系统

Ext4:第四代扩展文件系统,是Linux系统下的日志文件系统,是Ext3文件系统的后继版本

Ceph OSD把底层文件系统的扩展属性用于表示各种形式的内部对象状态和元数据

Ceph使用日志文件系统,如增加了BTRFS和XFS的OSD

在提交数据到后备存储器之前,Ceph首先将数据写入称为一个单独的存储区,该区域被称为journal,这是缓冲器分区在相同或单独磁盘作为OSD,一个单独的SSD磁盘或分区,甚至一个文件文件系统

journal允许Ceph OSD功能很快做小的写操作;一个随机写入首先写入在上一个连续类型的journal,然后刷新到文件系统。这给了文件系统足够的时间来合并写入磁盘。使用SSD盘作为journal盘能获得相对较好的性能。

文件映射到Object后,利用Cluster Map通过CRUSH计算而不是查找表方式定位文件数据到存储设备中的位置。优化了传统的文件到块的映射和BlockMap管理。

RADOS充分利用了OSD的智能特点,将部分任务授权给OSD,最大程度地实现可扩展。

◆ 第3章 智能分布CRUSH

对象存储中一致性Hash和Ceph的CRUSH算法是使用比较多的数据分布算法

在磁盘阵列中,数据是以条带(stripe)的方式贯穿在磁盘阵列所有硬盘中的

将条带单元(stripe unit)从阵列的第一个硬盘到最后一个硬盘收集起来,就可以称为条带(stripe)

从本质上讲,CRUSH算法是通过存储设备的权重来计算数据对象的分布的

在计算过程中,通过Cluster Map(集群映射)、Data Distribution Policy(数据分布策略)和给出的一个随机数共同决定数据对象的最终位置

PG在CRUSH策略的影响下,最终会被映射到OSD上。

◆ 第4章 三大存储访问类型

块是一个有序字节,普通的一个块大小为512字节

基于块的存储是最常见的存储方式,比如常见的硬盘、软盘和CD光盘等

RBD具有快照、多副本、克隆和一致性功能。

Format 1是原始格式,也是创建image的默认格式,Format 2支持RBD分层(layering),是实现COW(Copy-On-Write)的前提。

◆ 第5章 可视化管理Calamari

Calamari是一个管理和监控Ceph集群的Web平台,提供了漂亮的管理和监控界面,还提供了一套RESTful API接口,目的是为了简化Ceph集群管理

Calamari包括前端和后端两个部分,每个部分都有各自的代码库。

◆ 第6章 文件系统——高性能计算与大数据

在高性能计算领域,MPI是重要的分布式计算模型。MPI是一种基于消息传递的并行编程技术,其定义了一组具有可移植性的编程接口。通过MPI编程模型,程序员能编写基于消息通信的应用程序,而这个应用程序能在不同的节点上启动并协调工作,它们需访问共享存储,而Ceph FS正好提供共享存储的访问。

◆ 第7章 块存储——虚拟化与数据库

时,将qcow2转化成raw格式。这是由于KVM虚拟化访问Ceph RBD存储时将会配置raw的访问格式,故在此步骤中转换成raw格式

因为只有RAW格式的镜像才支持COW(Copy On Write)秒级创建。

CloudStack,项目地址http://cloudstack.apache.org/,提供一个开源的“基础设施即服务”(IaaS)的解决方案,特点是高可用和高扩展的能力。

CloudStack前身是Cloud.com, 2011年7月被Citrix思杰收购并100%开源。2012年4月,Citrix思杰宣布把CloudStack交给Apache软件基金会管理以及开发

目前CloudStack最新版本为4.6.0,支持虚拟化包含XenServer、KVM、LXC、VMware、HyperV和OVM3,同时支持物理服务器(Baremetal)。

1998年,iSCSI由IBM公司和Cisco公司开发,允许在硬件设备、IP协议上层运行SCSI指令集(SCSI over TCP)

iSCSI最大的特点就是,可以实现在IP网络上运行SCSI协议,使其能够在100/1000/10000Mbps的以太网上进行传输

Ceph通过Tgtd方式实现将RBD块存储转译为iSCSI存储访问协议,可以提供VMware ESXi、Citrix XenServer、Microsoft Hyper-V、oVirt和Oracle VM等虚拟化场景,也可以提供如Oracle RAC和Microsoft MSCS等高可用集群数据库场景。

◆ 第9章 Ceph硬件选型、性能测试与优化

超线程技术(Hyper-Threading, HT)就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高CPU的运行效率,

DPDK(Data Plane Deveploment Kit)抛弃了传统使用CPU中断处理数据包的方式,采用了轮询方式实现数据包处理过程:DPDK重载了网卡驱动,驱动在收到数据包后不使用中断通知CPU,而是直接使用零拷贝存入用户态内存中,使得应用程序可以通过DPDK提供的接口从内存中直接读取数据包

使用DPDK类似RDMA,避免了内存拷贝、上下文切换的时间

Ceph OSD进程在往数据盘上刷数据的过程中,是停止写操作的。

PG和PGP数量一定要根据OSD的数量进行调整,计算公式如下,但是最后算出的结果一定要接近或者等于2的指数。

要区分硬盘、SSD、RAID、SAN和云硬盘等,因为它们有不同的特点。

测试指标:IOPS和MBPS(吞吐率)

测试工具:Linux下常用Fio、dd工具,Windows下常用IOMeter。

块存储系统本质是一个排队模型

响应时间=服务时间+等待时间。

性能=单位时间内处理业务数量。

服务时间 = 寻道时间 + 旋转时间 + 传输时间

对于10000转速的SATA硬盘来说,一般寻道时间是7 ms,旋转时间是3 ms,64KB的传输时间是0.8 ms,则SATA硬盘每秒可以进行随机IO操作是1000/(7 + 3 + 0.8) = 93。所以,我们估算SATA硬盘64KB随机写的IOPS是93

一般的硬盘厂商都会标明顺序读写的MBPS(吞吐量)。

我们在列出IOPS时,需要说明IO大小、寻址空间、读写模式、顺序/随机和队列深度。一般常用的IO大小是4KB,这是因为文件系统常用的块大小是4KB。

在dd测试的同时也要对系统IO进行监控,使用iostat命令对系统IO进行查看。 ​​#iostat -x sdd 5 10

加大硬盘队列深度就是让硬盘不断工作,减少硬盘的空闲时间。

加大队列深度→提高利用率→获得IOPS和MBPS峰值→注意响应时间在可接受的范围内

增加队列深度的办法有很多,如下。 ❑使用异步IO,同时发起多个IO请求,相当于队列中有多个IO请求。 ❑多线程发起同步IO请求,相当于队列中有多个IO请求。 ❑增大应用IO大小,到达底层之后,会变成多个IO请求,相当于队列中有多个IO请求队列深度增加了。

现在,我们来测试SATA硬盘的4KB随机写的IOPS。因为环境是Linux,所以使用fio来测试。

​​$fio -ioengine=libaio -bs=4k -direct=1-thread -rw=randwrite -size=1000G-filename=/dev/vdb -name=”EBS 4K randwrite test” -iodepth=64-runtime=60​​ 简单介绍一下fio的参数如下。 ❑Ioengine:负载引擎,我们一般使用libaio,发起异步IO请求。 ❑bs:IO大小。 ❑direct:直写,绕过操作系统Cache。因为我们测试的是硬盘,而不是操作系统的Cache,所以设置为1。 ❑rw:读写模式,有顺序写write、顺序读read、随机写randwrite和随机读randread等。 ❑size:寻址空间,IO会落在[0, size)这个区间的硬盘空间上。这是一个可以影响IOPS的参数。一般设置为硬盘的大小。 ❑filename:测试对象。 ❑iodepth:队列深度,只有使用libaio时才有意义。这是一个可以影响IOPS的参数。 ❑runtime:测试时长。

硬盘厂商提高硬盘性能的方法主要是降低服务时间(延迟)。 ❑提高转速(降低旋转时间和传输时间)。 ❑增加Cache(降低写延迟,但不会提高IOPS)。 ❑提高单磁道密度(变相提高传输时间)。

我们首先进行4K随机写测试,具体如下。 ​​#fio -ioengine=libaio -bs=4k -direct=1-thread -rw=randwrite -size=100G-filename=/dev/vdb \
-name=”EBS 4KB randwrite test” -iodepth=32-runtime=60​​

◆ 第10章 自定义CRUSH

计算机界有句名言: 计算机的任何问题都可以通过增加一个虚拟层来解决,计算机硬件、计算机网络、计算机软件等方面概莫如此。

在Ceph里,PG是数据存储的管理单元,如果把PG当作一致性Hash里的存储节点,那么它就是最简单的数据分布(即取余算法)方式。不同的是,PG是抽象的存储节点,它不会随着物理节点的加入或者离开而增加或减少,因此数据到PG的映射是稳定的。

本章中列举了常用的CRUSH使用场景,通过灵活设计CRUSH方案,实现“指哪存哪”的目标,真正做到了软件定义存储

◆ 第11章 缓冲池与纠删码

传统上,Cache为了缓和CPU和IO设备速度不匹配的矛盾,提高CPU和IO设备的并行性而存在的

在计算机组成里,每个部件的设计都可以看到Cache的影子

Cache的设计原理是把读取过的数据保存起来,如果在以后的操作中重新读取时则命中(找到需要的数据),就不要去读较慢的设备,若没有命中就读较慢的设备。

Buffer的设计原理是把分散的写数据内容集中进行,按照一定周期写到目标设备。

我们可以暂且认为Cache是针对读优化,而Buffer是针对写优化。

在本地计算机结构组成里,相比CPU和内存之间的IO差距,内存和机械硬盘的IO差距较为明显

比较内存、固态硬盘和机械硬盘的每GB单位成本,得出的结果是内存>固态硬盘>机械硬盘

使用SSD固态硬盘这一类的高速且价格昂贵的存储介质组成高性能资源池,使用SATA机械硬盘这一类低速廉价的介质组成低速高容量资源池

要实现缓冲池技术,首先需要将整个存储系统按照存储介质的性能分为前端高速缓冲池和后端低速存储池,使用特定算法将数据写入和读取流程进行适当的调整,将访问次数比较频繁的热数据缓存储在前端高速缓冲池中(对应热数据上浮),而访问量比较低的冷数据则存储在后端低速存储池中(冷数据下沉),从而实现提高读写性能的目的

虽然纠删码能够提供和副本相近的数据可靠性,并降低冗余数据的开销,整体上能提高存储设备的可用空间。但是,纠删码所带来的额外开销主要是大量计算和网络高负载,优点同时伴随缺点

使用纠删码对硬件的设备性能是一个较大的考验,这点需要注意。另外,需要注意的是,使用纠删码所建立的存储资源池无法新建RBD块设备。

◆ 第12章 生产环境应用案例

Ceph FS主要对接于传统的应用,例如直接mount到服务器作为文件系统使用,另外就是用来对接Hadoop和对接OpenStack Manila项目

NFS(Network FileSystem)是类UNIX系统中最流行的网络共享文件系统之一。即使是不支持Ceph FS文件系统的类UNIX系统,也可以通过NFS来访问Ceph文件系统。

由于Ceph-Dokan只能正确读取UNIX格式的ceph.conf文件,因此你要用dos2unix把你的ceph.conf转换成UNIX格式。

OpenStack对接Ceph之后可以实现COW(Copy On Write)秒速开机,避免了Nova下载上传的一个动作,可以直接拷贝Glance存储池的镜像数据进行启动

HLS是Apple公司推出的一套基于HTTP的流媒体实时传输协议,全称是HTTP Live Streaming,同时能够跨多种平台和操作系统,在视频分享、在线教育等领域得到了广泛的应用

◆ 第13章 Ceph运维与排错

默认情况下,磁盘可以使用by-id/by-partlabel/by-parttypeuuid/by-partuuid/by-path/by-uuid等多种形式的名称对磁盘设备进行管理,但是在Ceph中,如果磁盘数量过多,加上为了更好区别每一个OSD对应的磁盘分区用途(比如filestore或journal),同时确保物理磁盘发生变更(故障盘替换后)后对应的名称不变,对OSD对应的磁盘设备命名提出新的管理需求

例使用udev的方式,将磁盘按照osd[N]的方式进行命名,比如/dev/osd5_filestore_1表示osd5的第一个filestore分区,/dev/osd5_journal_5表示osd5的第一个journal分区(表示该磁盘用于osd.5的filestore)

Cgroups是Control Groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(Process Groups)所使用的物理资源(如CPU、Memory和IO等)的机制。最初由Google公司的工程师提出,后来被整合进Linux内核。Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有Cgroups就没有LXC。

Virtual Storage Manager Virtual Storage Manager(VSM)是Intel公司研发并且开源的一款Ceph集群管理和监控软

Inkscope是一个Ceph的管理和监控系统,依赖于Ceph提供的API,使用MongoDB来存储实时的监控数据和历史信息

组件之间的通信都以保证时间同步为前提,否则,会导致数据不完整与不一致性

根据不少生产环境反映,调整抖动时间会引发一些未知的问题,在此建议设置时间强同步更为妥当。

默认的Crush Rule设置的隔离是Host级,即多副本(如三副本)情况下,每一副本都必须分布在不同的节点上。

当节点数不满足大于或等于副本数时,PG的状态自然就不能是active+clean,而会显示为“degraded”(降级)状态。

[插图]

计算的最终结果应该是2的幂次方。采用2的幂次方是为了提高CRUSH算法的效率