1
0
wiki/static/contentIndex.json

1 line
4.5 MiB
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"Personal/Blog/2018/11月28日晚-星期三-霾":{"title":"11月28日 晚 星期三 霾","links":[],"tags":["生活/日记","博客/原创"],"content":"总是很想写一些东西,却又不知从何下笔。\n学习笔记感觉写的很拖沓就跟小时候写日记打流水账一样。今天早上吃了饭然后上了学然后放学又吃饭然后又上学哈哈。感觉一直在重复搞一些事情对博客写笔记的定义理解的还不够透彻。一直在做前人做过的东西Git 相关的笔记,命令一搜一大堆。应该改变一下自己记录学习博客的方式。要秉承着宁要好梨一个,不要烂梨一筐的想法。多写一些更有营养的东西,少做重复的事情。多吸取前辈们的笔记作品书籍,领悟作者的思想,站在作者的角度去思考问题。读一本书就是跟作者对话。更要有会当凌绝顶的感悟。\n最近也在看计算机文化丛译Git 这两方面的书。计算机文化丛译系列的书籍,真的超级无敌崇拜计算机的先辈们。上个世纪我国还处于吃饱饭是第一要务的地方,而他们已经开始搞人工智能,算法,个人计算机,互联网等等。确实还是有很多需要学习的地方,不过吃饱饭确实是搞任何事情的前提。\n同时也是感觉很浮躁个人很浮躁环境很浮躁整个社会都很浮躁。到处充斥着快餐文化都想一夜暴富只关乎结果不在乎过程及质量。看了阮一峰前辈的一些散文以及平时生活感觉有的国人要走的路还很长。抗战打了十四年改革开放搞了四十多年感觉有的国人的思想可能要走八十年。无论需要走的路有多远多长我还是无比热爱我的国\n坚信自己能够不忘初心善始善终\n加油\n\n此文著于 2018 年 11 月 28 日,仅供留存。"},"Personal/Blog/2018/BombSquad-炸弹人小分队":{"title":"BombSquad-炸弹人小分队","links":[],"tags":["游戏/炸弹人小分队","博客/原创"],"content":"今天推荐一个好玩的游戏,炸弹小分队。\n简介\n首先它的界面是下面这个样子。\n\n具体怎么玩下面有新手帮助同时自己摸索摸索你会爱上这款游戏的\n\n下载\n\n下载地址点击打开\n官方网址点击打开\n安卓版本点击打开\n选择你用的操作系统版本下载注意区分安装包与服务器部署包以及 Linux32 位与 64 位。\n注如果游戏无法运行或运行错误可能是缺少运行库运行解压包内 vc_redist.x86.exe 就可以解决。\n个人房间7Wate\n\n注2021.2.12 服务器恢复运营\n注2022.1.10 服务器停止运营\n此文著于 2018 年 12 月 6 日,仅供留存。"},"Personal/Blog/2018/如何免费创建一个属于自己的网站":{"title":"如何免费创建一个属于自己的网站","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"分享这篇文章,主要是给室友栋哥写的。嘿嘿,有其他需要尝试的也可以自己尝试一下,免费空间不用安装服务器软件,也不用担心域名注册备案访问问题,用来学习建站最好不过。如果真的想建设一个网站,还是不要嫌麻烦,找好的服务器和域名,这样也就不用担心其他有的没的问题。\n免费主机网站\n网址ccaeo.com\n注册页面ccaeo.com/free-hosting-signup.php\n技术支持www.mizuiren.com\n技术教程www.mizuiren.com/10.html\n原博主也有注册教程大家多多支持\n注册\n根据提示注册务必想好域名前缀。因为注册后不可更改!注册信息,例如用户名,密码等等,在注册成功后会发送到邮箱一份!其他选项默认即可!\n\n注册成功后显示的页面如果接收不到邮件可以点蓝色链接重新发送一次。\n\n邮箱激活点击链接激活。如果无法点击复制到浏览器地址栏访问。\n\n激活页面不要关闭。等待激活成功\n\n激活成功\n\n相关信息会发送到邮箱\n\n到此账户已经注册成功域名已经可以访问初始页面\n网址zhou20181031.ccaeo.com\n部署网站\n了解过相关知识就知道创建一个网站需要网站程序和数据库类似于 WordpressDiscuz以及我使用的 Typecho 简称网站程序吧,一时间也想不起来术语了。这些都是开源的!这次我创建一个 Typecho 的博客,其他的也类似!首先下载博客主程序。\n网址typecho.org/\n下载地址typecho.org/downloads/1.1-17.10.30-release.tar.gz\n下载好文件解压如下\n\n然后登陆网站后台创建一个数据库。\n后台网址cpanel.ccaeo.com\n账户以及密码信息邮箱文件都有。语言选择简体中文。\n\n第一次出现这个页面点击我同意即可\n\n进入网站后台主页面\n\n第一次进入 phpMyAdmin 需要创建一个数据库。\n\n然后创建数据库填写数据库名字。\n\n创建成功后会显示数据库信息。这里数据库信息是博客安装必须要用的\n\n数据库到这一步已经创建成功然后用 FTP 工具上传博客主程序。\nFTP 工具www.smartftp.com/download\n\n登陆成功以后按照图片操作。\n\n上传速度比较慢耐心等待一下。等待上传完成\n\n上传成功以后打开自己的网站地址开始安装\n\n\n博客网站管理员信息\n\n\n安装成功\n\n这一步网站就已经安装成功了写的有点仓促有什么笔误大家可以留言关联微信了实时收到多多留言支持不介意给个赞助哈哈哈哈哈哈哈\n网址zhou20181031.ccaeo.com2022.01.10 - 失效)\n管理员admin\n密码123456\n\n此文著于 2018 年 10 月 31 日,仅供留存。"},"Personal/Blog/2018/英雄联盟-S8-全球总决赛":{"title":"英雄联盟 S8 全球总决赛","links":[],"tags":["游戏/英雄联盟","博客/原创"],"content":"2018 年 11 月 3 日 英雄联盟 S8 全球总决赛 IG 夺冠\n\n\n此文著于 2018 年 11 月 3 日,仅供留存。"},"Personal/Blog/2018/螺蛳粉":{"title":"螺蛳粉","links":[],"tags":["美食/螺蛳粉","博客/原创"],"content":"螺蛳粉是广西壮族自治区柳州市的小吃米粉,具有辣、爽、鲜、酸、烫的独特风味。是柳州最具地方特色的名小吃。螺蛳粉的味美还因为它有着独特的汤料。汤料由螺蛳、山奈、八角、肉桂、丁香、多种辣椒、等天然香料和味素配制而成。\n\n嘿嘿嘿螺蛳粉。\n以前对这些东西是很拒绝的吃过以后真香定律哈哈哈\n我最喜欢吃配品和汤汁的味道豆皮把应该是还有酸汁自己起的名字很刺激味蕾。特别是酸的山西老陈醋哈哈哈。\n感觉佐料才是默默无名的王者刺激着味蕾\n分享一下郑州的螺蛳粉。\n阿生哥柳州螺蛳粉\n\n地址郑州市二七区永安街 6 号 (郑州四十四中学与郑州永安街小学中间)\n\n平时去只顾吃了哈哈哈哈哈哈哈哈。\n没有想过拍照喜欢吃的自己去尝试一下\n不喜欢吃也别找我嘿嘿\n\n此文著于 2018 年 11 月 4 日,仅供留存。"},"Personal/Blog/2020/Don`t-Starve-饥荒":{"title":"Don't Starve-饥荒","links":[],"tags":["游戏/饥荒","博客/原创"],"content":"饥荒Dont Starve是一个让玩家在荒野的环境中尽力生存、类 Rogue 暗黑系幻想生存游戏,由 Klei Entertainment 于 2013 年四月发表;同时它还是我最爱的游戏,也是借此纪念一下口袋版饥荒 100 天存档,再拉你入坑哈哈哈!\n剧情\n\n游戏剧情以一个绅士科学家 威尔森(图中呆呆的就是威尔森)为中心,他被神秘的麦斯威尔欺骗而创造一台机器,而机器把他带到一个陌生的且充满怪物及挑战的世界。随着游戏的进行,玩家必须在更困难的冒险模式中,帮助威尔森探索这个世界。威尔森将会明白为什么麦斯威尔把他带到这个世界,还有他可怕力量的秘密。玩家会在冒险模式中解锁仅存在冒险模式中的角色,而他最终必须对付麦斯威尔。\n玩法\n游戏开始你会被麦斯威尔带到一片森林中第一天你需要在附近捡一些浆果、胡萝卜、燧石、干草、树枝。浆果和胡萝卜用来填饱肚子燧石和树枝可以制作斧子砍伐树木到了晚上使用甘草和树枝制作火把如果晚上没有火把或者发光的物体就会在黑夜中被杀死。当我们成功活过第一天后饥荒这扇大门就为你打开\n环境\n游戏拥有春夏秋冬四个季节。如同我们实际生活一样春天下雨多一些、夏天太热容易发生火灾、秋天万物成长收获、冬天就是缺少食物并且很冷同时也继承了冬夏昼夜长短不一的情况。\n每个季节都会有 BOSS 随机出现来攻击我们,确实挺惨的。而且每隔一段时间都会有野狗来攻击我们,每当听到主角提示「有没有听到什么奇怪的声音?」,我们就赶紧背上全家老小开始跑~~~\n角色\n我们拥有生命值、饥饿值、脑残值也可以叫理智值来直接影响我们生存 ,生命值和饥饿值都通俗易解;脑残值就如我们工作多了就会很累没有精力,游戏中角色也是(晚上不睡觉呀,砍树砍多了呀等)这样,不过游戏中脑残值过低就会容易被影怪攻击!\n我建议刚开始玩这个游戏不要看攻略当你死的不能再死的时候再看攻略。\n分享\n以下就是我最近口袋版饥荒的百天存档反正胳膊是废了。\n\n\n\n\n\n版本\n饥荒目前可在 Windows、Mac OS X、Linux 、Android、ios 等独立作业程序上执行,可经由 Steam、WeGame 等多种方式购买。目前拥有 2 个地图、3 个 DLC 拓展、5 个版本、21 个角色供大家尽情游玩,在此不一一赘述了。\n新手小白建议 WeGame 选购饥荒 PC 联机版仅售 24 元,手机版可以在苹果商店和谷歌商店购买正版,\n邀约\n我玩饥荒时间很早很早大概是 15 年入的坑,当时在吾爱破解论坛下载的破解版。当时只是因为画风才下载了这款游戏,现在依然清晰记得当时用鼠标玩的手酸胳膊痛的。\n后来有机会接触到正版便第一时间入了正版断断续续玩到现在通过开挂顺利完成剧情模式。现在玩了有几百个小时自认为还可以。不过还是很想能有稳定的小伙伴一起入坑哈哈一起盖房子自己一个人实在是太太太没趣了。\n最后欢迎各位入坑~~~\n\n\n一开始你一无所有。\n你采了一把路边的浆果胡乱地塞进了嘴里伴着火把微弱的光线惴惴不安地活过了第一天。\n不久你造出了第一把斧子。\n接着你找到了猪村你决定和二师兄一起生活。\n从此你在这个世界有了一个家。\n有一天你造出了一把长矛。于是你在采集之外又学会了狩猎。\n又有一天你开发了自己的农场你学会了经营农业……\n你的食物开始丰富起来: 蔬菜、烤肉、烙饼、饺子、肉丸……\n家里的设备也越来越先进: 避雷针、冰箱、灭火器、传送门……\n你挑拨二师兄、牛哥、鱼人、蜘蛛等各个物种发生冲突然后坐收渔翁之利。\n夜晚你的营地灯火通明你看着冰箱里吃不完快要坏掉的卤肉自言自语道:“早知道少做一点了……”\n“明天吃点什么好呢”\n你想起了自己到这儿的第一天那个举着火把战战兢兢的夜晚。\n“来把浆果吧……”\n作者乌有卿\n链接[原文地址][www.zhihu.com/question/26350809/answer/889521287 ]\n"},"Personal/Blog/2020/中国传统历法":{"title":"中国传统历法","links":[],"tags":["文化/民俗","博客/原创"],"content":"一寸光阴一寸金、寸金难买村光阴。从小熟背的谚语,时间固然珍惜可贵,到现在我连历法都不太清楚,未免过的太糊涂了点……\n我国民间现施行的传统历法分为两种格里历阳历、农历。\n格里历拉丁语Calendarium Gregorianum又译国瑞历、额我略历、格列高利历、格里高利历、葛瑞格里历、格列高历也称基督历 [1]),是由意大利医生兼哲学家阿洛伊修斯·里利乌斯改革儒略历制定的历法,亦是一个被当今国际社会最广泛地使用的历法。公历是阳历的一种,于 1912 年在中国引进采用,因农历等中国传统历法是阴阳历,故公历在中文中又称阳历、西历、新历、公历。\n农历是现今东亚地区民间传统广泛使用的阴阳合历。古代相传为黄帝时代或者夏朝创制又称黄历、夏历中国以外的语言和地区普遍称为中国历。农历广泛应用于生日标记、各种民俗活动节日等比如“年节”、“元宵节”、“端午节”、“中秋节”、“重阳节”等节庆活动被视为中华文化象征。\n公历\n公历历年平均长度为 365.2425 日、一年共有 12 月,分大小月,大月 31 天,小月 30 天。每四年置一闰,闰年 2 月为 29 天。\n\n农历\n历法是记录时间的坐标系统多数民族根据天象来确定历法。年就是四季周期即地球围绕太阳公转就是月相盈亏周期即月球围绕地球公转。准确测量回归年和朔望月之长度会发现一年比十二个月多大约 10.875 日,即单个阴历或阳历无法同时满足年和月的准确周期。\n通俗来说月即为月亮对地球的一个完整的运动周期大月 30 天,小月 29 天。一年 12 个月,那么一年的长度大概在 354 到 355 天之间。年即为地球对太阳的一个完整的运动周期,约为 365 天。故一年会比十二个月多大约 10 日。而农历罕有地同时考虑到太阳及月球运动,兼顾了年和月之准确周期,是为阴阳合历。\n农历根据观测月相变化严格按照月亮盈亏确定月份定朔为农历阴历部分。通过观测太阳与黄道的关系影响地表气候环境的不同定出 24 节气,为农历阳历部分。为了时彼此的长度更加接近,自春秋时代起就有了“十九年置七闰月”;又排定了闰月规则。如此既达到年合四季、月合圆缺,即新月固定于初一,新年固定于冬春之交,达成阴阳和谐。\n农历阴历\n农历阴历一年 12 月,大月 30 天,小月 29 天。这也是通常我们所说的农历几月初几,正月初几。因为置闰的原因,所以农历阴历一年的天数并不固定,最长有达 384 天。\n农历阳历\n在古代通常以冬至到冬至之间约 365+1/4 日),分割为 24 段(每段约 15+7/32 日),每段起始于一个节气,依次为:冬至、小寒、大寒、立春、雨水、惊蛰、春分、清明、谷雨、立夏、小满、芒种、夏至、小暑、大暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪。\n二十四节气中冬至、大寒、雨水、春分、谷雨、小满、夏至、大暑、处暑、秋分、霜降、小雪为中气通常用来确定月份。冬至所在月份为冬月、大寒所在月份为腊月、雨水所在月份为正月、春分所在月份为二月、…、小雪所在月份为十月立春到立夏前为春季立夏到立秋前为夏季立秋到立冬前为秋季立冬到立春前为冬季。\n中气之间的时间约为 30+1/5 日时,因此中气日之间的间隔(含前不含后)为 30 或 31 日。而一个月的时间为 29 日或 30 日,一个月内要么一个中气,要么没有中气。因此,中气可以直接来确定月份及闰否。\n\n农历闰月\n19 个回归年的时间长度和 235 个朔望月几乎相同。所以阴阳历若采十九年七闰法,每 19 年加入 7 个闰月,就可以协调回归年(太阳的周期)与朔望月(月亮的周期)间的时间差距,以较为简易的方式制历。中国古称此周期为一章。\n现行历法采无中置闰法。若两冬月间有 13 个月(不计第二个冬月),则置闰于两冬月间第一个无中气之月(有时一岁可能会有两个无中气之月,只取第一个),月序与前一个月相同(闰月在几月后面,就称闰几月)。采用现行之定朔法,有可能会出现无中气月但无须置闰之状况。\n\n参考维基百科格里历、农历、章"},"Personal/Blog/2020/初号机,起飞!":{"title":"初号机,起飞!","links":[],"tags":["记忆/童年","博客/原创"],"content":"半个多世纪来,互联网改变了世界,也彻底地改变了我们的生活。每个人都拥有了属于自己的个人电脑、笔记本、智能手机,享受着它给我们带来的一切,同时我也借此讲述一个故事。\n初号机\n\n我父亲在 2010 年初夏买了我家的第一台电脑,它是由我和我姐共同努力得来的。因为我和我姐一整个学年拿了 No.1 的好成绩,所以我父亲便买了它:海尔极光 D5\n时至今日它就像潘多拉魔盒我不知道它给我带来的究竟是好是坏。\nQQ\n那时候流行 QQ第一件事情也是注册 QQ不过注册了好久才注册成功。\n第一个网名叮当、想必大家和我一样干着同样的事情添加好友、发说说、写日志、装饰空间。\n当然还有那个年代不可缺少的东西QQ 农场。现在已经鲜有人玩了,毕竟这已经是十年前的东西。\n\n\n除了这些还有抢车位、Q 宠大乐斗、QQ 牧场、胡莱三国、你画我猜、QQ 宠物,以及 4399、7K7K、1399。如果全部说完怕是整篇都是游戏了哈哈那时它包揽了我和小伙伴们全部的欢乐。\n把玩初号机\n「初号机」除了用来玩以外还可以用来「拆」。那时系统大多都是 Windows XP蓝屏时代想必都知道。电脑总是蓝屏自己好奇心比较强总是谋求各种方法拆、看、研究。拆了无数次装了无数次跌跌撞撞。最后小小少年成功的步入「IT 行业」,学会了重装电脑系统。还知道了什么是处理器、显卡、内存等等。每次解决问题后的成就感,总是兴奋的想吃「奥里给」哈哈!\n虽然这台电脑配置不好、网速不快、画质很渣现在几百块的电脑性能都可以甩它十八个街道。但是纵然它有千千万万不如意之处它依旧是我的「初号机」。因为它承载了我少年时代最美好的时光因为它承载了我最初的梦。\n因特尔\n在 2015 年的时候,我的「初号机」已经有点步履蹒跚走不动路了。系统从 Windows XP 升级到了 Window 7变得爱卡起来了。也满足不了我的需求便计划换一台新的电脑。\nE3 神教\n卡吧、图吧、垃圾佬、i3 默秒全、E3 神教,我是一名合格的图钉哈哈。当时为了给自己配置一台性能强、性价比高的电脑,疯狂学习 IT 知识。\nCPUIntel Xeon E3-1230 v3\n主板技嘉 B85M-D3H\n内存DDR3 1600 4G*2\n显卡GeForce GTX 750\n\n当时这份配置可以完美满足我的学习需求撸啊撸需求啊哈哈不过后来因为各种原因便搁置了。父母也没有同意我自己组装电脑更没有同意资金支持完美错过了 E3 神教。\n\n错过往往可能都是为了更好的相遇\n\nI3 8100\n步入大学后虽然已经有了一台笔记本但还是更想自己组装一台台式电脑。经过几个月的攒钱、筹备、观察价格、网购终于全部到货。准备装机了\n\n配置清单\nCPUIntel i3 8100\n主板微星 B360M MORTRAR\n显卡微星 HD7850 2G\n内存威刚 万紫千红 DDR4 2666 8G\n硬盘惠普 EX900 128G\n硬盘希捷新酷鱼 2TB\n电源安钛克 VP450P\n散热酷冷至尊 T400i\n机箱金河田 家悦 3302B\n\n第一台电脑是和好朋友 CarryMan 一块装的,某一天的晚自习没有去上课,然后它就诞生了!\n总体下来花了 3000 多,性能方面基本满足了我的需求。室友开黑,敲代码啊,没错全靠它了!这台电脑没有用的特别久,因为什么?你看看下面的标题就知道了!\nAMDYes\n装机圈的朋友应该都知道「i3 默秒全」「一核有难、八核围观」这些埂,不懂得请自行百度哈哈,因为讲不完。\n2017 年 AMD Ryzen 横空出世,瞬间 AMD 真香AMD Yes我当时配第一台电脑得时候就很想配 AMD 的电脑,奈何荷包不足。只能 i3 8100 将就一下了,后来因特尔鬼才营销,将 i3 8100 推到 800 元以上。然后我就把 CPU 主板卖了,还小赚了一笔。\n锐龙一代存在一些小东小西的问题以及二代的推出导致后来价格迅速跌落至 900 元左右。是的,没错!八核十六线程主频 3.0 还可以超频,想啥呢?赶紧上车!\n配置清单\nCPUAMD Ryzen 1700\n主板微星 B450M MORTRAR\n显卡蓝宝石 AMD RX580 8G 超白金\n内存威刚 万紫千红 DDR4 2666 8G * 4 条\n硬盘三星 PM981 256G * 2 块\n硬盘西数 500G 蓝盘\n硬盘希捷新酷鱼 2TB\n网卡intel 9260 AC\n电源安钛克 VP450P\n散热东海 X6\n机箱爱国者极光 E20\n\n\n这就是我目前的工作站完美的满足了我的各项需求。目前还打算把笔记本小小升级一下换个 1T 固态、加个 32G 内存(狗头)。\n初号机起飞\n写这篇博客的时候我和我姐的 QQ 好友已经 3630 天了,也算十年了。零零散散的十年,同时即将迎来全新的十年。\n\nSometimes all we can do is turn the page … Let it go.\n\n\n图片\n本文图一来自海尔官网、图二来自 QQ 农场、图三来自洛克王国"},"Personal/Blog/2020/吉普赛满天星":{"title":"吉普赛满天星","links":[],"tags":["生活/园艺","博客/原创"],"content":"谨以记录 2020 年 7 月 21 日栽种的吉普赛满天星(于 2020 年 11 月 2 日暂停记录)。\n9 月 2 日 周三 多云\n铛铛铛、我又来了。Come On\n\n\n9 月 7 日 周三 狂风暴雨\n发芽啦发芽啦感觉有点徒长但是又怕晒死……\n傍晚突如其来的狂风暴雨晚上顺带给仙人球搬了 Big House累了溜了溜了🙃\n\n\n9 月 21 日 周一 中雨\n耐不住山区将近 20℃ 的温差,加上我也无心照养。\n来年再种。\n11 月 2 日 周一 大风\n2020 年仅剩的三盆小生命!\n\n\n7 月 21 日 周二 小雨转中雨\n\n打扫房间发现了一包吉普赛满天星种子还是粉色的吉普赛满天星。便想起来是大学时种花遗留下来的谨以此记录它的成长\n7 月 27 日 周一 多云\n\n前几天回郑州了虽然一周了但满天星还没有发芽还长了些许杂草。网购的仙人球和含羞草也到了不过有点坑。\n8 月 32 日 周八 地球毁灭\n铛铛铛、发芽失败。Over"},"Personal/Blog/2020/夏日花记":{"title":"夏日花记","links":[],"tags":["生活/园艺","博客/原创"],"content":"夏天种花怕是只有我这样的憨憨了,但是依旧要记录一下。我呢、从小就蛮喜欢种花的,不是因为我有一颗少女心哈哈哈。而是因为种花是付出就一定有回报的,而且开花的时候成就感爆棚!\n桃红\n\n\n凤仙花学名Impatiens )、又名指甲花、指甲桃、急性子、凤仙透骨草,是凤仙花科凤仙花属的植物。\n\n印象里第一次开始种花是在十岁左右种的凤仙花。我们这里喜欢叫它桃红因为可以用它开的花包指甲所以又名指甲花。它很容易成活开花每天春天播撒完种子就完全不用管了安心等待夏天开花包指甲就可以了。但是如果想让它长得如人一般高那你便要好好松土、施肥、浇水了。\n那时候家家户户基本上都会种桃红并且到开花的时候都会包「红指甲」。同时用包红指甲还有很多风俗迷信如「男生不能包小拇指头将来怕老婆」等等。\n波斯菊\n\n高三临近毕业我再次拾起了养花。当时除了照顾这颗波斯菊我还在网上买了多肉、满天星、文竹多肉比较讨人喜爱而吉普赛满天星则是我最喜欢的花文竹则是刷单送的。\n像小草一样的是假的满天星当时被气死了。因为第一次种植没有想到满天星还会有假的也不算是假的同属一科目的植物但是远远没有吉普赛满天星好看之后便它全拔了。波斯菊呢由于一些失误被太阳晒死了。还有三颗多肉多肉倒是一直活得好好的毕业后都送给朋友了。\n当时种花用的两个洗脸盆是我们小寝室独特的一道风景线。\n\n黄金万年草\n因为高三种花很仓促各种准备都不充分有点小失败所以在大一学年的春天又开始了种花之旅。经过上一次失败的经验这次认真学习了各种养花知识打算做一名辛苦的园丁。\n我多方讨教最后成功买到了真·吉普赛满天星的种子同时在花卉市场淘到了最爱的花盆还意外收获到了一种全新的多肉黄金万年草。它不是很妖艳的多肉很普通、绿油油的。但每当我看到它就会很舒心整个人由内而外洗涤过后般的轻松、释然。\n\n吉普赛满天星\n\n\n\n\n\n仙人球\n\n前阵子收拾屋子时翻出来了大学时遗留下的粉色吉普赛满天星当时便种下了不过这夏天也不知道能不能发芽。然后逛淘宝买了一些仙人球收到货后拼西西的感觉……因为它实在太小了不过还好卖花盆的商家也没有令我失望刚刚好不过花盆是真的丑不要吐槽了。\n买了十个仙人球、两颗含羞草在我写这个博客的时候已经害羞死掉了……、两盆黄金万年草。个人建议不要在网上买花可以适当买一些种子因为在运输过程中特别是夏天死亡率太高了。虽然我在夏天种花确实有点憨憨的感觉但是喜欢一件事就立马去干呗。\n简单的记录一下并希望每年春天都可以种下自己喜欢的花。\n\n凤仙花图片及其介绍来自 百度百科"},"Personal/Blog/2020/幸福的事情都是需要等待的":{"title":"幸福的事情都是需要等待的","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"买蛋糕的时候,排了很长的队。\n前面小孩等的不耐烦了。\n妈妈、我不想买了。\n你每次都是这样幸福的事情都是需要等待的。\n\n\n是啊幸福的事情都是需要等待的。\n"},"Personal/Blog/2020/开源软件之道":{"title":"开源软件之道","links":[],"tags":["社区/开源","博客/原创"],"content":"源代码开放的软件并不一定是开源软件开源软件有着严格统一的的定义封闭软件Closed Software、自由软件Free software和开源软件Open source software有着显著地区别。\n开源软件的定义\n开源软件促进协会 OSI 对开源软件有明确的定义OSI 对开源软件的定义一共有十个条款:\n1. 自由再发布Free Redistribution\n2. 源代码Source Code\n3. 派生作品Derived Works\n4. 作者源代码的完整性Integrity of The Author's Source Code\n5. 不能歧视任何个人和团体No Discrimination Against Persons or Groups\n6. 不能歧视任何领域No Discrimination Against Fields of Endeavor\n7. 许可证的发布Distribution of License\n8. 许可证不能针对某个产品License Must Not Be Specific to a Product\n9. 许可证不能约束其他软件License Must Not Restrict Other Software\n10. 许可证必须技术中立License Must Be Technology-Neutral\n\n通过开源软件定义的十个条款可以清楚的看到 OSI 所坚持的原则:\n\n坚持开放鼓励最大化地参与和协作\n尊重作者权利同时保证程序的完整性\n尊重独立和中立避免任何可能影响这种独立性的事物\n\n有了这样一个清晰而又完整的定义在法律层面保证了开源软件的开放性独立性和继承性。\n开源软件的优点\n\n高质量\n零许可证费用\n开放和自由\n灵活可定制\n公开透明\n良好的学习平台\n\n开源软件的风险\n开源软件主要风险在于 管理维护 和 技术支持 以及 许可证法律纠纷,由于开源软件采用的协作方式,你可能无法追究某一处代码的作者(部分协议要求作者著名)。以及如果出现问题,你可能无法寻找官方的技术支持,更多的支持可能来自于社区,可这种支持不是每次都有好人跳出来帮忙。还有如果你不了解许可证可能会带来的法律风险(部分国家法律不同,如果源代码无许可证,默认著作权属于作者)。\n开源许可证简介\n开源许可证并不只是保护作者的权利更多是赋予用户各项权利许可证规定了使用主体方式用途。明确说明了用户可以是个人或者公司等怎么修改和运行以及是否可以用来进行其他合法用途。\n在使用开源软件要做的第一步就是找出开源软件中所涉及的所有许可证。每个开源软件的不同版本可能会使用不同的许可证同时还有注意许可证的版本以及有些开源软件会采用双重或多重许可dual-license的模式。\n在 OSI 的网站上列出的 流行并广泛使用且拥有广泛社区的许可证,分别是:\n\n[Apache 许可证 2.0][opensource.org/licenses/Apache-2.0 ]\n[BSD 许可证 3-Clause][opensource.org/licenses/BSD-3-Clause]\n[BSD 许可证 2-Clause][opensource.org/licenses/BSD-2-Clause]\n[GUN 通用公共许可证(简称 GPL][opensource.org/licenses/gpl-license]\n[GUN 宽通用公共许可证(简称 LGPL][opensource.org/licenses/lgpl-license]\n[MIT 许可证][opensource.org/licenses/MIT]\n[Mozilla 公共许可证 2.0(简称 MPL][opensource.org/licenses/MPL-2.0]\n[通用开发和发布许可证 1.0(简称 CDDL][opensource.org/licenses/CDDL-1.0]\n[Eclipse 公共许可证 2.0(简称 EPL][opensource.org/licenses/EPL-2.0]\n\n许可证的兼容性\n目前经过 ISO 认证的许可证多达 70 多种,被自由软件基金会认可的自由软件许可证也有数十种,而它们的条款又各不相同,有些甚至互相矛盾。这种兼容性问题被称为 许可证增值问题License proliferation。\n怎么样才算兼容呢如果使用许可证 A 的代码和使用许可证 B 的代码能在一个广域作品中结合在一起,那么 A 和 B 就是兼容的,否则就是不兼容的。更近一步,如果结合后的广义作品可以用许可证 A 发布,那么许可证 B 就是许可证 A 兼容的A-compatible。反之亦然但需要注意的是兼容性并不可逆。\n如何选择许可证\n\n开源许可证选择工具\n如今开源软件早已经成为了软件领域不可或缺的重要组成部分要以辨证的观点看待开源软件。它自由平等协作的精神实践了信息和知识共享的理念并且实现了知识产权保护和分享之间的微妙平衡。同时开源带来的自由免费有可能也是最贵的。\n\n参考\n《开源软件之道》\n开源社——开源许可证选择器\nOpen Source Initiative\n阮一峰《如何选择开源许可证》"},"Personal/Blog/2020/我的小羊肖恩":{"title":"我的小羊肖恩","links":[],"tags":["记忆/洛阳","博客/原创"],"content":"建厂来产下的第一只小绵羊——肖恩!\n\n\n\n非常 nice 的一只小绵羊365 天看着长大的。结果越长越惨……\n\n\n\n\n古灵精怪的小山羊、嘿嘿嘿~~~"},"Personal/Blog/2020/数据恢复杂谈":{"title":"数据恢复杂谈","links":[],"tags":["生活/随笔","博客/原创"],"content":"昨天下午一位公务人员通过朋友联系到我,需要我帮忙恢复执法记录仪中的视频文件。因为他不知道执法记录仪的工作原理,所以导致一个重要的执法视频被覆盖。我了解后,觉得有几率恢复,便有了这次数据恢复的经历。\n数据恢复基本常识\n首先对于电子文件的损坏无外乎以下两种损坏的方式。\n物理损毁\n就是指存储电子文件的物理硬件磁带、磁盘、光盘等损毁因为物理元件的损毁导致文件修复难度极大所及基本上 99% 的物理损毁很难被修复,同时文件的价值也可能不值得我们去修复(物理损毁修复价格及其昂贵)。\n逻辑损坏\n逻辑损坏有很多种常见的就是电子文件被删除覆盖格式化等。逻辑损坏修复的可能性较大同时修复的价值相对物理损毁较低所以大部分的逻辑损坏都是可以尝试修复的这也是我觉得能恢复上述的原因。\n恢复方式\n大多逻辑损坏可以通过市面上常见的数据恢复软件修复例如 DiskGenius 就一款专业级的数据恢复软件,同时也不乏其他好用的软件,需要各位自行体验了。\n文件修复过程\n\n执法记录仪是惠普的 DSJ 系列之一,拥有官方的桌面管理工具,通过阅读说明书发现连接记录仪需要禁用驱动程序签名强制,具体操作可以 Google。\n连接执法记录仪登录软件进入 U 盘模式。\n通过使用数据恢复软件查找到近两年的视频文件。\n恢复视频文件发现视频文件无法打开。\n猜测视频文件头可能损坏使用视频修复工具修复。\n文件修复成功但视频错乱只修复了部分帧数。\n\n首先在成功连接执法记录仪后便先用了 DiskGenius但发现恢复的是一些无用文件。便找到了另外一款该软件成功恢复了视频文件的目录所以我觉得还是挺有希望的。26G 的视频恢复了一个多小时,但是恢复之后只有几个视频文件可以打开。\n这个时候心凉了一半觉得可能要出糗了。但是根据我多年的行业经验和直觉我觉的还有救。使用十六进制编辑工具打开视频果不其然有救。至于为什么有救因为我之前逆向研究过 GIF 的文件格式,所以我猜测,文件头可能是损坏的,但是视频的部分帧数可能还没有被覆盖。但是现在去哪里找一个这样的工具,总不能现成写一个吧。\n不过还真就找到了这样的一个工具Video Repair Tool通过它我成功的修复了部分未覆盖的视频帧数 。后来还是没能帮上忙,执法视频文件在 1 月 17 日,我只找回来到 1 月 31 日的部分视频文件。\n杂谈\n简单的描述了一下这次的文件恢复其实我没有这项技能的。只是凭借多年的行业经验和直觉我才揽下这个小 case 的。\n后来 Google 了一下,看到了挺多对数据恢复和销毁的观点。这里我也简单谈一下自己的看法,欢迎各位交流。\n对于销毁文件因为电子文件是被人为的创造出来的所以它不存在销毁的决无踪迹。但是你可以销毁它存在的记录使其恢复的成本提高。为什么要这样说因为毕竟猴子算法都存在可能性所以任何文件都有被修复或创造范本的可能性存在。\n但是如何提高文件的恢复成本网上有很多种说法全覆盖 35 次0 填充一次,扔进火堆哈哈。我认为在不损害物理硬件的前提下,理论上三次全覆盖擦写,找回的可能性就如同猴子算法的平均时间复杂度一样 O(n × n!)。\n希望大家多了解一下相关的知识务必不要让自己的文件损毁。我之前一块 2T 移动硬盘坏掉了给我心疼的,心疼着心疼着我还是没想起来里面到底存了啥哈哈哈。\n\n硬盘有价、数据无价\n"},"Personal/Blog/2020/注定不平凡的一年":{"title":"注定不平凡的一年","links":[],"tags":["生活/感悟","博客/原创"],"content":"乙亥末,庚子春,荆楚大疫,染者数万,众惶恐,举国防,皆闭户。\n道无车舟万巷空寂。然外狼异动垂涎而侯神州腹背受刺。幸龙魂不死风雨而立。\n医无私警无畏民齐心。政者、医者、兵者抗疫逆行勇战。商客、戏子、邻家百姓、仁义者、邻邦献物捐资。\n叹山川异域风月同天喜曰无衣与子同裳能者竭力万民同心。\n四月末疫除终获胜。此后三十余年风调雨顺国泰民安。\n2020 年注定是不平凡的一年,今日更是国家公祭日。前事不忘、后事之师。\n乌合麒麟前辈的作品更是让我充满震撼借此分享。\n国家公祭\n\n民国十大汉奸\n\n丰碑\n\n剑来\n\n和平之师\n\n致莫里森\n\n白宫粉刷匠\n\n你能呼吸吗\n\n群体免疫\n\n炮灰\n\n为弄臣加冕\n\n伪神\n\n\n引用《庚子春.鼠年.荆楚大疫》\n作者欧阳小川\n地址www.jianshu.com/p/a79de84e949f\n图片《乌合麒麟作品集》\n作者乌合麒麟\n地址weibo.com/1566936885/J5I6de3An\n本站禁止评论任何有关时政、热点、反动、违法、暴力、恐吓、赌博或淫秽的内容故本文关闭评论。"},"Personal/Blog/2020/浅谈个人服务器架构":{"title":"浅谈个人服务器架构","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"大一上学年购买了第一台服务器,并且搭建了网站。当时购买的腾讯云学生主机,搭建了一个 WordPress 个人博客网站。后续购买并备案了域名,服务器系统也由 Windows 转为 Linux也第一次接触到了服务器管理面板……\n直至今天服务器配置也是由当初的 1 核心 1G 内存 1M 带宽升级到 2 核心 4G 内存 5M 带宽;博客也由 WordPress 更换成 Typecho。熬了数不清的夜晚折腾了不少的时间经过不断地打怪升级经验宝宝也含泪成为了天线宝宝。简单总结了个人服务器的痛点如下\n\n服务器性能底下\n服务器续费太贵\n网站域名备案繁琐\n网站访问速度过慢\n容易遇到各种各样的攻击\n更换服务器网站各种问题\n\n服务器架构\n现如今也设计并搭建了个人认为较为完善、成熟、轻便的服务器架构。\n\n推荐将把服务器与安全组、COS、镜像备份、服务器监控合理搭配使用这将省掉我们大部分的麻烦与痛点。然后服务器完全 Docker 化,所有程序都使用 Docker 部署,省掉了我们网站环境的麻烦,同时可以随时打包带走任意站点。其次由于使用反向代理服务器控制所有流量,加以部署防火墙便可以控制整个服务器站点的流量。\n痛点解决方法\n\n遇到问题不好解决怎么办那就把提出问题的人解决掉\n\n服务器性能低下\n在我们只有学生云主机的情况下推荐服务器仅部署一个网站推荐使用 宝塔云面板,方便整个服务器的运维和网站的部署。\n服务器续费太贵\n这个我们只能努力工作改变现状或者退而求其次选择性能较次的服务器。\n网站域名备案繁琐\n由于国内相关政策网站必须备案以后才可以正确解析。备案方面目前相对比较轻松时间上大约要一个月时间。如果不想备案可以选择使用国外主机及域名不过访问速度可能有所影响。\n如果你在一家云服务厂商备案了域名然后使用另外一家云服务厂商主机需要进行域名转移相当于重新备案比较麻烦。所以在进行域名备案之前一定要选择好云服务厂商。\n网站访问速度过慢\n可以选择使用 CDN 或者部署静态网站。\n容易遇到各种各样的攻击\n很多时候站点容易遭受各种各样的攻击我们要怎么防御这些攻击\n\n\n设置网站访问策略。\n\n\n自己动手搭建服务器防火墙。\n\n\n宝塔面板搭建免费的网站防火墙。\n\n\n腾讯云安全组严格控制服务器出入端口。\n\n\n更换服务器网站各种问题\n合理利用云服务器镜像COS 备份等。一劳永逸可以参考上述服务器架构。\n个人服务器推荐程序\ngitea\nGitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证.\n兰空图床\nYour photo album on the cloud. 一款优秀的个人图床。\nBitwarden\n解决您的密码管理问题。\n个人团队和业务组织存储共享和同步敏感数据的最简单最安全的方法。\nNextcloud\nNextcloud 是一个免费专业的私有云存储网盘「开源」项目,可以让你简单快速地在个人/公司电脑、服务器甚至是树莓派等设备上架设一套属于自己或团队专属的云同步网盘,从而实现跨平台跨设备文件同步、共享、版本控制、团队协作等功能。"},"Personal/Blog/2020/球鞋日记":{"title":"球鞋日记","links":[],"tags":["记忆/高中","博客/原创"],"content":"扣篮是每个男孩少年时的梦,我也不例外。曾经刻到骨子里的热爱,现如今也都飘散如烟。\n李宁 音速三 鸳鸯色\n严格意义上来说这是我的第一双篮球鞋李宁音速三、鸳鸯色。\n因为它是第一双鞋所以纵使它有千万个缺点也都无所谓了没有任何的黑科技没有出色的回弹硬的要死的足底更不用说透气性可言了。同时李宁为了防止足底断裂加了一块钢板也被我给草开了。不过 499 元的售价,让我好是心疼,也是至此不在买任何一双国产篮球鞋。\n\n\n\nNike 外场训练鞋\n也是因为音速三的不如意买了没过多久就买了这双 Nike 篮球鞋。我记不起它的名字,但它是仅次于 KD5 EP II 最舒服的一双篮球鞋。\n相对音速三它坐拥 Nike 的 zoom 黑科技,出色的前脚掌回弹、更好的贴合性、轻盈的脚感。实战中更是拥有不俗的启动速度,唯一的缺点就是低帮鞋的通病。\n这也是我草的最狠的一双篮球鞋也让我第一次感觉到这才是真正的篮球鞋的感觉。不需要它很贵出色只要给我想要的即可。\n\n\n\nNike KD5 EP II\n\n\nNike KD5 EP II无比喜爱的一双的鞋。它不仅仅给了我想要的极致的贴合、回弹、轻盈当然还有配色也是让我大为赞赏。\n我跟它一起拿下了不俗的成绩高中篮球赛冠军、最好弹跳成绩 330cm。当时也仅仅在实战、比赛、状态很好的时候才会穿它。\n现如今也曾再穿过它一起战斗不只是我累了还是它老了已力不从心。\nNike LBJ 11 南海岸\n\n\n梦寐以求的一双篮球鞋LBJ 南海岸。虽然我的球衣是 1 号,源自特雷西麦克格雷迪,就是那个 35 秒 13 分的男人;但是也阻挡不住我对詹姆斯的喜爱,一个将暴力美学演绎到极致的男人。\n南海岸风情配色、宛如机甲一样的鞋体、全脚掌 zoom。不过高达 1599 元的售价,俨然阻挡了我对它的喜爱。曾做梦生日谁会送我一双哈哈哈~\n后来自己打工用第一桶金买了它没有任何犹豫至此不再有任何遗憾。\n梦\n通篇都在说篮球鞋似乎忘记了开篇的第一句话扣篮是每个男孩少年时的梦我也不例外。不过现如今半月板二级损伤、腰椎间盘膨出、无穷无尽的生活似乎要杀死这该死的梦\n\n\n暑假在家偷偷训练\n曾努力学习篮球技巧\n曾为了它六七个小时不知疲惫\n更为了它加入田径队、不知疲惫的训练\n自从那个夏天詹姆斯为克利夫兰带去了属于他的荣耀\n自从高考结束曾经曾经的这一切\n似乎转眼间都飘散如烟\n"},"Personal/Blog/2020/記拾月":{"title":"記拾月","links":[],"tags":["生活/日记","博客/原创"],"content":"阿巴阿巴……感觉上个月跟做梦一样,稀里糊涂的十月。\n九月底厂里卖到广西南宁一车毛驴让我押车去了。1700 公里、30 小时的旅程,司机是山西人,操着一口流利的山西话对我而言就像开头般:阿巴阿巴……\n各行各业都有不成文的潜规则这次押车也便是因此。为了防止居心拨测的司机半路狸猫换太子我熬了 30 个小时没有睡觉。不过这次的两位司机,虽然只接触了两天,感觉对我还不错,没有想象的那么糟糕。\n这一路上最能感受到南北差异的不是窗外的风景而是独具特色的饮食文化。由饺子换成了热干面热干面又变成了粉丝不过我还是很喜欢吃南方美食的。同时因为厂里装车的失误导致牦牛和毛驴全部跑乱了。有一些毛驴被踩踏的很严重需要时不时的赶它们站起来导致我们浪费了非常多非常多的时间。\n抵达广西南宁已经是晚上九点多了天色已晚只知道自己处在大山里。从大山里走出来又走到大山里去也是别有一番趣味。卸完车、检查一下毛驴便早早休息了。第二天早上还是死了一头毛驴因为牦牛角戳进了腹部导致死亡。\n第二天趁着晚上住在酒店忙里偷闲吃了一份螺蛳粉总的来说我不太喜欢吃南方的螺蛳粉不过也有也可能因为我吃的第一份螺蛳粉有点先入为主的意思。不过螺蛳肉是真的流口水……\n\n因为姥姥农历七月十四生日所以我又慌慌张张地从广西南宁赶了回来。本来还打算去北海看日出了哈哈哈结果北海没有日出哈哈。因为北海东边是陆地很难看到很棒的日出我的天哪笑死我了。\n因为还需要去洛阳接妈妈所以我要来一次史诗级大联动机场——城铁——高铁。\n下午 5 点的飞机7 点 30 到新郑机场。坐上 7 点 55 的城铁8 点 10 分到郑州东站。等待 9 点的高铁,中途还不慌不忙的吃了顿开封菜。心里再一次佩服我党之伟大哈哈哈,这就非常 good 了。\n在等高铁的时候我发现大家眼神都在看我。心里的一顿飘飘然啧啧啧……\n殊不知我口罩带反了真的是个瓜皮。\n10 月 9 日,我国第七次人口普查,而我作为一名光荣的普查员,自然紧接着又开始了人口普查。\n\n\n\n忙忙碌碌半个月才终于把人口普查的摸底入户工作完成期间我又掺杂了三次小面试。\n打算回郑州工作啦感觉厂里依旧不适合我我也没有更多的耐心继续呆下去了。\n\n第一份面试是家门口的上汽配套厂主要生产汽车座椅招聘一名桌面运维人员。看着很诱人的哈五天八小时国家节假日五险一金就不说了主要专业对口信心满满的便去面试了说实话也是粗心大意了我没有想到这是一份很很很正式的工作。主要因为我第一份工作面试造航母……然后你懂的。期间还简单用英语口语交流……我这蹩脚的口语啧啧啧。\n第二份面试是家具定制的厂商平时工作主要负责 Excel 的整理维护。面试官是一位大叔,简单聊了几句,月薪 2500六歇一更不是技术岗位我便说考虑考虑回复消息。主要还是薪资确实……招聘信息 3500 - 4500可能大叔也是看我年轻罢了。\n第三份面试圆通速递河南郑州分拣中心。也算是技术岗位面试也还 ok。妈的考试没过……你说我当初把那三本 TCP/IP 啃完那不啥事没有。不过后来人事姐姐还是让我留下办入职,日后再重新考试进 IT 部。但是身不由己啊,估计没办法入职了。时至今天人事还再联系我什么时候入职……\n\n转眼十月便过去啦今天来到了厂区。高速路边早已是满眼金黄秋天来了。\n"},"Personal/Blog/2020/长安游记":{"title":"长安游记","links":[],"tags":["游记/洛阳","游记/南阳","博客/原创"],"content":"庚子年夏,吾同莫逆,南下鸾州、意登景室,求道老君。谓道生一,一生二,二生三,三生万物,惑,吾二十有一,混沌未开,宜览众山小,会当凌绝顶。\n年轻人总是要来一场说走就走的旅行的不过这次旅行是在一次酒足饭饱之后大家相约一起来爬山游玩。然后我们五个田径队的「姐妹」在经过长达半个月的等待终于觅得空闲。\n行程\n\n南阳宝天曼大峡谷漂流\n洛阳栾川老君山\n洛阳老城\n\n\n一路上欢歌笑语好久不见的我们纷纷打开了话匣子。\n进入南阳界后都是山路一路蜿蜒曲折高低起伏的。那么偏远的山区有的甚至只有一两户村民国家依旧修的有国道、县道、以及正在建设的高速公路不禁感叹「基建狂魔」名副其实。\n宝天曼大峡谷漂流\n在经过 5 个多小时的路程之后,第一站到达的是南阳宝天曼大峡谷漂流。大家都有点疲惫了,可能是因为天气不太好,几十公里的山路仅仅只碰见了一位老大爷、一辆摩托车;我们还挺怕漂流不营业了,那样就太 der 了。到达目的地之后,发现人还不少,提起兴致赶紧换衣服、买装备准备出发。\n\n\n\n\n\n\n\n\n除了我大家都是第一次漂流哈哈所以吃了不少亏。一路上大喊大叫船还被人家给掀翻了某个人喝了不少水哦泼水用的盆也扔光了全程下来只剩被欺负了到最后我也是很迷茫出来漂流了半路上大家把盆都给仍光我的天哪真的是最惨的组合不过大家玩的都挺开心的\n真心话大冒险\n漂流过后我们赶到了栾川住在老君山脚下的一间民宿。一顿酒饱饭足之后回到民宿开始了真心话大冒险哈哈哈。\n某些人竟然是海王某些人……\n栾川豆腐汤\n一直耳闻栾川的豆腐非常有名豆腐汤也是及其好喝。第二天一早起来便点了一份外卖尝一尝这栾川豆腐汤。\n豆腐汤的豆腐介于嫩老之间口感 Q 弹,入口轻嚼即化;汤汁鲜美,不过对于口味重的可能有些淡。配上饼丝和辣椒油口感甚好,符合口味重的我,栾川豆腐汤果然不失所望!\n\n\n老君山\n\n\n老君山The Laojun Mountain原名景室山位于十三朝古都洛阳的栾川县县城东南三千米处八百里伏牛山脉的主峰海拔 2217 米。是国家 AAAAA 级旅游景区、世界地质公园、国家地质公园、国家级自然保护区、省级重点文物保护单位、省级风景名胜区,中国北方道教信众拜谒圣地,中原山水文化杰出代表。\n\n临近中午我们才开始爬山年轻人嘛出来旅游那个不是睡到十一二点的哈哈哈。\n在售票处买完票后我们开车到了云景索道当时在下雨还挺大的我们换好雨衣便出发坐缆车。缆车是真的高对于有点恐高的我无法直视~\n\n缆车下来便是中天门这里是老君山的第一站。不过中天门后的阶梯可是把「姐妹花」给累坏了一个个累的气喘吁吁的。阶梯顶部的寺庙内有一位老道士老道士可能是伙食有点好全然没有仙风道骨的样子。\n接着就开始爬山啦林间小道、云海栈道、仙境隧道出来仙境隧道便是十里画廊路大家时不时的在开玩笑把对方推下去一个个吓得都挺寒颤了。本来计划着十里画廊可能要走三四个小时毕竟听名字十里十里那不得给我们安排一下子结果走着走着就走一半多了大家便开始吐槽哈哈哈。\n临近伏牛极顶我们买了一块祈福牌祝大家友谊地久天长天长地久~\n\n\n从伏牛极顶下来后再走不远便到了南天门。可能北极以南都是南所以都是南天门哈哈。\n南天门后方就是金殿老君山的标志性建筑当时由于天气不好所以并没有惊艳到我们因为那天的天气是这样的。在金殿短暂停留之后我们就下山去了。\n\n\n攻略\n\n住宿\n老君山山脚附近有超级多的民宿、酒店的景区内部同样有很多住宿的地方价格美丽。\n爬山\n从售票处到云景索道估计有七八公里没有开车的可以做游览车过去。云景索道和钟灵索道选择一个即可我们去得时候只开了云景索道实际上这两个索道一个都不用做有一条盘山路可以直接开车到但是路被封了。\n从中天门开始登山一路林间小道、云海栈道穿过仙境隧道后就是十里画廊。十里画廊听名字觉得有十里实际上走了不到一个小时就到了金殿。如果想直接去金殿坐两个缆车然后走很短一段路就到了。\n山路上有很多卖吃的、水啊、泡面等等价格相对合理所以不必带很多零食啦。\n洛阳\n晚上匆匆忙忙的赶到了洛阳安顿好住宿以后就去应天门转了转晚饭当然是吃水席啦。吃完饭逛逛街刮刮彩票喝喝咖啡大半夜几个人去喝咖啡哈哈哈然后又在住宿的地方打牌直到早上 5 点!\n应天门\n\n到了应天门后人家出来旅游都是看景点我们几个出来就是打架了。碰到扫码送东西的买了两个大锤就在应天门干起来了真的是哈哈哈。\n老街\n\n当时刚下过雨。鲜红的晚霞映衬着丽景门仿佛回到了千年前的长安古城迫不及待地要找李白吟诗一首。\n丽景门后面紧接着就是老街了仿佛现在所有景区地商业街都是一个模子刻出来的没有所谓的特产风味更多的是世风日下人们浮躁的内心。\n水席\n洛阳最有名的便是水席了我们也是直奔一家水席。第一次也不知道那个好吃那个不好吃只能选择一个美团评价比较高的。也不知道怎么点菜只能让老板推荐了。\n\n具体的菜名也忘记了可能要再吃一次哈哈。刚开始吃的时候就像吃炒菜一样用筷子夹着吃始终吃不出来洛阳水席的独特之处甚是疑惑。后来想起来洛阳一位老友说「水席之所以名叫水席是因为汤汤带水、汤汤有水」我便带着汤水一起吃。\n那真就完全是天壤之别汤汁混合着菜品一起咽下后。各种味道疯狂刺激着味蕾使你为之沦陷真的是只顾着吃了也真的是太好吃了哈哈哈。这种感觉没有办法描述可以亲身体验一下。\n咖啡店\n\n路上见到一家咖啡店便进去讨了杯咖啡。相对于老城的风格店里显得就更独具一格花花草草、古筝风琴、鹦鹉伴着猫猫甚是放松惬意。\n我们分别点了自己爱喝的饮品细细品着咖啡。想必也都很羡慕店家这大隐隐于市淡然世外的心境没错我猜的哈哈哈。不过我倒是很羡慕这样的生活干着自己热爱的事情养些猫猫狗狗如更有良人相伴那自是更好。\n小街天府\n最后一天中午我们去了小街天府吃了蛮多的小吃。临近分别小吃也显得索然无味了。\n\n生活\n\n时间也是过的飞快三天两夜的游玩也是要结束了。都说分别是了为了更好的相遇不过已经约好了要去爬泰山了哈哈哈奥里给。我倒觉得啥都不是还是一直在一块比较 der。\n好久不见的我们这几天不知道是游玩的开心、还是一起共度时光的开心都很开心哈。所以我想两者皆有吧。\n接着大家也是要各奔生活了期待下次相聚\n\n图片\n老君山风景图来自百度百科 老君山\n老君山全景图来自老君山官方微信公众号"},"Personal/Blog/2020/骑行在路上":{"title":"骑行在路上","links":[],"tags":["游记/骑行","游记/开封","游记/洛阳","博客/原创"],"content":"始于\n中学\n最开始打算骑行是在中学那时我每周末上学都是步行去学校的。在当时我们班有一个市区的同学总是骑行来学校年少的我觉得很酷便开始对骑行有很大的兴趣。中学大家总是会谈论到去哪个高中、环境怎么怎么样、实力怎么样。从小我就没有出过远门更是很少去市区所以一直对繁华的市区有很大的憧憬。然后就梦想着可以自己去外国语、省实验这些好学校走走看看。\n想着骑自行车去拿着自己的大头机去拍照集成册。然后再出书分享给很多和我一样的想去看看却没有机会去看看的。不过那时候对于年少的我很多事情是无法做到的。\n高中\n上了高中之后浑浑噩噩的踏入高三毕业班。每天依旧是在课堂上刷手机看贴吧。当时特别喜欢看两个人的帖子更新了上万楼。\n\n\n非洲务工\n楼主是去非洲务工的一名工作人员每天都会在贴吧上更新自己在非洲的所见所闻。这也是第一次真真切切地感受到外面的人文生活风景世俗每天都看的特别起劲\n\n\n西藏骑行\n楼主是一名河南的老乡打工多年看到很多吧友骑行便也计划去骑行。没有断更一直更新到底我也就一直追到了底。\n\n\n少年的我无疑再次对这个世界、祖国的山川大河充满了幻想。骑行的种子就彻底在我心中萌了芽不依靠任何人走遍心中每一个角落。\n大学\n来到大学一直在忙自己热爱的事情。临近毕业还是对骑行念念不忘。下定决心一定要骑行骑行川藏线。攒钱看单车制定计划······最后毕业了面对着生活工作家人还是没有走出这一步。感觉自己就像被牵着线风筝只能随风摇摆而不能随风漂扬。\n我父亲和他的好朋友在洛阳创业。我也就随之来到这里工作帮忙打下手干一些力所能及的事情。后来见到父亲的好朋友有一辆捷安特的山地车。我的天心中的小火山直接喷发了。便聊起了关于骑行的一些事了解到他也是对骑行感兴趣之前也从洛阳骑行回家了一次。\n我便也计划着一定要骑行回家一次种种原因直至今年才正式开始了骑行也终于迈出了那一步。\n春节期间武汉爆发了新冠肺炎。五月份局面初步稳定了下来我便计划着骑行回家。\n准备\n五月中旬厂里也不再那么忙。我便把山地车骑了过来好好的给它洗了个澡、精心的擦拭每一个角落、涂好润滑油、调试设备。\n心里大概规划了一下因为骑行到家将近 200 公里。所以必须要提前锻炼一下,否则身体会承受不了。\n计划如下\n1. 高山镇 —— 洛河 \n2. 高山镇 —— 半坡山\n3. 高山镇 —— 古城\n4. 高山镇 —— 陆浑水库\n5. 高山镇 —— 郑州\n\n第一站洛河\n洛河古称雒水黄河右岸重要支流。因河南境内的伊河为重要支流亦伊洛河即上古时期河洛地区的洛水。\n\n路线图\n\n海拔示意图\n\n宜阳县\n\n\n总结\n很长时间第一次骑行。没有做好充足的准备导致体力有点透支。特别是回来的路上连续 7 公里的上坡,高度差将近 300 米。着实给我上了一课,不过路上的风景很美。一切都是值得的!\n第二站半坡山\n路线图\n\n海拔示意图\n\n山顶\n\n\n总结\n去的时候跟着导航去的路况不好浪费了很多体力。上山途中碰见了很多老大爷在筛油菜籽、老大妈在割油菜、生活的甚是安逸。\n临近山脚终于瞻仰到了山顶的寺庙。主峰名叫圣母山594 级台阶直通庙宇。我去的时候有几位老人家刚下山,待我登到山顶。山顶上只有一位大娘在守庙敬佛,拜佛之后稍作歇息便离去。临走大妈给我指了一条路,一路全程下坡,滑行到了家里。\n第三站古城\n略\n第四站陆浑水库\n陆浑水库位于黄河流域伊河中游洛阳市嵩县境内是国家六十年代修建的是一座以防洪为主的大型水库。\n\n路线图\n\n海拔示意图\n\n沿途风景\n\n总结\n这次骑行相对来说没有前两次强度大其次经过前两次训练这次骑行更有把握。到了陆浑水库那刻真的震惊了。宛如西藏一般的天水一色群山连绵给我带来的太多的震撼\n第五站 开封\n是的没错我骑行到了开封。\n全程 230 公里,花费 13 小时,平均时速约 18 公里。共计喝了 16 瓶尖叫、3 瓶红牛。一路火腿肠、面包补充体力。\n路线图\n\n海拔示意图\n\n路书\n\n\n单车\n\n总结\n一路上计划着赶路便没有拍照。之前听说骑行回郑州要 13 个小时,高德地图导航也是需要 18 个小时才可以到开封,便做好了持久的打算。\n早上 5 点出发。\n上午 7 点便出了伊川县城。仅有两个坡,剩下全是下坡。\n上午 9 点 30 分到达登封市。三个大上坡,合计将近 30 公里。\n上午 10 点 40 到达新密市。上午全程山路,起伏较大,体力耗费也比较多。同时因为速度太快,自己太过兴奋(山路 21 km/h 巡航)。导致接下来路程浪费了更多的体力,因为上午不到 12 点就到了新密市区,所以打算到郑州再休息。同时因为路书的错误,导致新密至郑州段消耗了几乎全部体力!\n下午 2 点到达郑州市区,南三环郑密路段。补充体力休息 30 分钟。此时距离开封还有 81 公里,跟原本计划的正好相反。本以为山路会很不好骑行,体力会浪费过多。没有想到出发的时候,因为体力充沛,所以刚开始的山路倒没什么。但骑行了 10 个小时之后,体力、精力、屁股已经消耗殆尽。特别是屁股,根本就坐不下来了。\n下午 3 点 30 分到达郑开大道金水路段,准备出发前往开封!骑行下穿过京港澳高速,郑开大道全程逆风,估计有三级上下。巡航速度艰难保持在 21 km/h同时屁股难以支撑。\n下午 5 点,骑行至中牟县刘集。距离目的地还有 40 公里。由于全程逆风,消耗了更多的体力。同时根据身体状况,不敢再贸然的去喝功能性饮料。只能喝苏打水和矿泉水。巡航速度由 21 km/h 逐步降低至 13 km/h。此时骑行 10 公里已经变得很艰难。只有不停的休息。\n晚上 7 点,距离目的地还有 18 公里,已经是骑行 + 滑行。最后 23 公里,完全没有了任何体力。只有机械式的往复运动,感觉不到疲惫,感觉不到屁股的疼痛。\n晚上 8 点,距离目的地还有 7 公里,自我感觉有点昏沉。下车推行 1 公里,检查了身体状况。\n晚上 8 点 30 分,到达目的地!\n简单的描述了整段的骑行过程首先不推荐大家盲目的去像我一样骑行。要根据自己身体的实际情况来骑行否则会容易发生意想不到的情况。高中时我是校田径队的有体育训练基础所以可以尽量避免同时也知道自己身体极限。\n骑行结束后在家里休息了两天。因为一路上喝了太多的功能性饮料所以在家喝了将近 10 升的矿泉水。所以再次说明,不了解自己身体状况的,请勿盲目的去骑行。特别是新手!\n一路上的感想也只有自己知道了没有什么要感慨的。\n我们的征途是星辰大海\n希望下次骑行是 2100 公里的川藏线!等我!\n\n\n图片\n本文路线图、海拔示意图来自 Google Earth Pro"},"Personal/Blog/2021/2021":{"title":"2021","links":[],"tags":["年度/2021","博客/原创"],"content":"2020 年平安夜前夕,有幸加入到「十年之约」,更是我平安夜最值得纪念的一份礼物。十年之约的宗旨是:十年之约,即从加入这个活动起,我们的博客十年不关闭,保持更新和活力! 所以我也想做一件有意义的事情,就想到了这个点子。\n无论 2020 究竟多么阴晦隳颓,凡是过往、皆为序章。\n小高\n\n\n考过专四\n\n\n考过教师资格证\n\n\n学会理财\n\n\n年底存款 5000\n\n\n小王\n\n\n健身锻炼控制体重 105 斤\n\n\n一次出省旅行\n\n\n取得教师资格证\n\n\n两个月看一本书\n\n\n学习计算机操作、Pr、Ps、做饭\n\n\n存 10000 元\n\n\n小雪\n\n\n不谈恋爱\n\n\n远离拖延\n\n\n考过四级\n\n\n做出选择过有目标的生活\n\n\n存钱年末毕业旅行\n\n\n小吴\n\n\n想和朋友出去旅行最好是能去海边\n\n\n存 2 万块钱 哈哈哈哈哈哈哈哈哈\n\n\n努力买一辆属于自己的小车车🚗\n\n\n赐我一个男朋友\n\n\n读一本书\n\n\n一份喜欢的工作\n\n\n抹茶派派\n转眼间 2020 年已经过去了,这一年于国于民都是非常具有挑战性的一年,在这一年里我也算是遇到了人生的转折点——专升本成功上岸。我现在还清楚的记得考完回去寝室收拾东西的路上的心情,非常绝望,因为老师讲的没考,所以在家的一段时间我已经给自己做好心理准备要去幼儿园工作了,甚至是考招教的书都买好了,成绩出来的那天半夜 12 点就扒拉手机查,结果说延迟一个多小时,我就又等待了一个多小时,后来还是查不成,就睡了。可能心里记挂着,四点多我又醒了,这次查到了,说实话考的分数也在我的预料之中(教案写完之后偷偷算了分),英语也是和平常做的往年卷子分数相差不大。我当时特别激动的又核对了招收学校的分数,在确定自己有学上之后,把还在睡梦中的爸妈叫醒,告诉他们这个消息,全家人都很开心,我也松了一口气,就好像是人生的台阶又往上上了一步一样,很满足。伴随着备考专升本,因为疫情只能在家,我也不知道那段时间是怎么了,就是特别自律,除了上课学习的时候,其他的时间基本上都被我安排做在 b 站上找的健身视频(哔哩哔哩真是个宝藏哈哈哈),甚至是课间十分钟休息也是一样,所以我也成功的瘦下来了,从 2xl 到 lm 甚至有的衣服款式 s 我都能穿,随便穿什么衣服都很合适的感觉真是太爽了!人家不都是说不要小看能减肥成功的人,我也很棒啊哈哈。这两件事是 2020 年最让我印象深刻的事了,也是改变我人生的两件事,现在回味一下,真像是做梦一样。\n快过年了新的一年还是有些规划的。有些事情是必须要做的第一件事就是学校组织的创新引飞的活动在 9 月份能够取得好成绩吧。第二件事那必须得是要和之前专科的室友们会面一次。第三件嘛,继续坚持减肥,争取到 100 斤并且保持下去。\n第一件事其实这个活动我当时是不太想参加的可无奈必须必当时也是加班加点的备教案说课做课件什么的这件事算是在本科第一学期相当重要的一件事了最初的时候我特别的迷茫因为专科学的是学前教育现在是小学教育关于小学教育的一切我都不知道课文啊上课形式板书设计等等当时都觉得无从下手不过事实证明人还是要逼一逼的不逼一下自己都不知道自己有多厉害在确定要讲的内容后我就找了人家的教学视频再加上室友们东一句西一句的指导最后艰难的完成了任务就在我特别开心的准备走了我们创新引导老师叫我留下她说她看上我了准备让我参加这个活动OMG 我都惊呆了,我本想着今天终于结束了,我终于可以好好休息了,又出来这么一出,唉,当时也没敢说啥就跟老师说说我之前学的不是小学教育,可能有很多地方不太行,老师说没事,那就没事吧,不过不管怎么说,这件长脸的事那必须得好好干,毕竟也算是磨炼自己的一个机会,不说能晋级到参加省级的吧,起码得混个校级比赛吧嘿嘿,等开学去实习了还可以累积教学经验,加油加油我可以的哈哈~\n第二件事我和一个室友已经策划了好久从 20 年暑假的时候就在讨论了,这群室友,有时候对于他们的一些行为还是看不过去的,但是还是特别喜欢他们,都是特别实在的人,没有什么坏心眼,没有什么心机,跟他们在一块的时候非常开心,有啥说啥这种感觉很舒服,吵吵闹闹的三年,唯一一点就是每次出去都得我指路,人工智能探路雯,害,一群没有方向感不记路的家伙。像这种都坦诚相见过的感情,天天见面烦的慌,不见面了又想的慌,毕业了,也从天天见面到一年才见一次面,机会就很少了,所以今年必须要见一次,看看我养的这群猪猪都有什么新的变化~\n第三件事那不必须得减肥成功100 斤不过分吧,不过说实话,冬天真不适合减肥啊,天天穿的都不想动,太难了,只能一遍又一遍的给自己做心里辅导,不过现在的运动量还是比着之前夏天的时候少的太多了,夏天最多的时候可以一天连续三个小时锻炼,现在可好,连续半个小时以上我都不想动了,看着镜子里自己穿的跟企鹅一样在那运动,没有一点美感,做着做着就不想动了,但是我妈说了不能再胖回去了,我也是这么觉得,我还要继续瘦嘞。不过马上就要过年回老家了,这是一个大关卡,去年回去就胖十斤,今年可不敢再造次了,管住嘴,迈开腿,挺一挺就过去了,没什么大不了的,我可以的!等回来了每天坚持锻炼 1-2 小时吧,天气也慢慢暖和了,不能光嘴上说要瘦到 100 斤,不行动等于零 。等我瘦到 100 斤,我要好好的奖励自己一下,哼哼~\n好了 2021 年三件大事情罗列完了,就等我完成这三件大事后发朋友圈吧哈哈哈哈哈哈哈哈\n小张\n\n\n欠款还完\n\n\n存一笔不小于 10000 的小钱\n\n\n涨薪涨薪\n\n\n学习一些 SpringBoot 和 SpringCloud 的新技术\n\n\n脱单脱单可能性不大😑\n\n\n小付\n\n\n确定工作\n\n\n坚持跑步健身\n\n\n看一些想看的书 (目前看了《意志力》《云边有个小卖部》)\n\n\n如果工作的事情顺利今年博客技术学习重新启动\n\n\n有时间多回老家陪陪老人\n\n\n老舅\n\n\n找对象\n\n\n发表一篇 10 分以上的文章\n\n\n找到工作\n\n\n老姐\n\n\n瘦到 105 斤\n\n\n升职加薪✌\n\n\n想清楚 30 岁以后干啥\n\n\n读书 * 10\n\n\n去三个没去过的城市\n\n\n小周\n\n\n一份稳定工作 ------------------------------------- 转正啦6 月 18 日)\n\n\n增加摩托车 D 证 ---------------------------------- 科目四进行中……\n\n\n买一辆小电车 / 小踏板 --------------------------- 上班买过啦2 月 28 日)\n\n\n学习摄影 ------------------------------------------- 学习中……\n\n\n拍 100 张摄影作品 -------------------------------- 50 张 +\n\n\n尼康 D610 + 镜头 --------------------------------- 翻车两次……5 月 6 日)\n\n\n学习钢琴 ------------------------------------------ 学习中 ~\n\n\n雅马哈 P45 电钢琴 -------------------------------- 买过啦6 月 18 日)\n\n\n健身 ------------------------------------------------- 尽快落地6 月 30 ri\n\n\n篮球 ------------------------------------------------- 从加入公司篮球队开始5 月 18 日)\n\n\nPs、Pr --------------------------------------------- 学习中\n\n\nLeetCode 100 题\n\n\n开发维护 1 个开源项目\n\n\n贡献维护 10 个开源项目\n\n\n拥有一个 100 星星的开源项目\n\n\n1000 张字帖\n\n\n10 本文学作品\n\n\n骑行北岳恒山\n\n\n每周最少给父母打一次电话 - ∞\n\n\n每两个月最少回家见父母一次 - ∞\n\n\n\n望大家心想事成、万事如意\n"},"Personal/Blog/2021/VIVO-IQOO-Neo3-开箱测评":{"title":"VIVO IQOO Neo3 开箱测评","links":[],"tags":["写作/测评","博客/原创"],"content":"爸妈的手机太卡了,就考虑换手机。最后决定买了 VIVO IQOO3 Neo。OPPO 和 VIVO 作为蓝绿大厂,高价低配,主营三四线城市饱受诟病。现如今积蓄了足够的资本,也开始冲击中高端市场。那便简单写篇开箱测评!\n展示图\n\n硬件\nIQOO Neo3 是 VIVO 一款搭载了高通骁龙 865 处理器,支持双模 5G 全网通,采用 Wifi6 标准的中高端机型。同时 Neo3 还搭载了新一代 UFS 3.1 闪存,屏幕方面 Neo3 则采用了 6.57 英寸挖孔全面屏,拥有 90.4% 屏占比,并且配置 144Hz 高刷新率,显示顺滑流畅。\n续航方面Neo3 拥有一颗 4500mAh 容量电池,采用 44W Super FlashCharge 闪充技术58 分钟可充入 100% 的电量,足够日常使用。\n摄影方面Neo3 使用了前置 1600 万像素单摄,后置 4800 万像素主摄 + 800 万像素超广角 + 200 万像素微距摄像头的三摄方案。\n\n相机\n\n\n不知道如何测评比较好简单的使用两款手机专业模式下相同参数拍的同一时刻的照片。\n第一张图为 VIVO IQOO Neo3、第二张图为小米 MIX3\n总结\nVIVO IQOO Neo3 于 2 月 14 日 2600 元购于京东,总体来说这个价位,拥有着骁龙 865 + 8G 运行内存 + 128 储存内存和双模 5G少有媲美者了。不要跟我抬杠抬杠你就是对的哈哈哈。总之给父母用再也不会出现卡顿什么乱七八糟的事加上父母也比较中意 OPPO 和 VIVO 的手机。\n第一次测评期待继续努力"},"Personal/Blog/2021/上有天堂、下有苏杭":{"title":"上有天堂、下有苏杭","links":[],"tags":["游记/杭州","游记/西湖","摄影/作品","博客/原创"],"content":"上上个月,五月二十日去了杭州,果不其然如诗所述:上有天堂、下有苏杭。时至今日,现代化的杭州更加让人着迷!\n西湖\n\n\n\n\n\n\n\n第一天围着西湖转了一大圈拍下的这些照片。\n第一张西湖的划船队在训练。场景很不错但是没有找到更好的角度要不一定是一幅不错的成片。✌\n第二张大爷大妈的退休生活可真是太美了西湖边散散步钓钓鱼啧啧啧。那鱼是真大碰见个小孩还说爷爷你好厉害鱼可以送给我么😀\n后面就是寺庙、雷峰塔、断桥等等都去过了西湖边寺庙是真的多。一天的游玩让我感触良多特别是杭州市政府对西湖开发和城市发展之间存在的冲突处理的很好点赞👍\n最后晚上的夜景感觉下班后去西湖散步是对生活的享受 ~ 😍\n阿里巴巴\n\n\n\n\n第二天跟老姐、老哥去了阿里巴巴总部园区转了转互联网大厂让天下没有难做的生意 ~\n说点什么\n🙃Hahhh ~\n写的及其敷衍\n主要是分享一下买完相机刚去杭州的时候拍的几幅摄影作品。"},"Personal/Blog/2021/我开发的第一款软件":{"title":"我开发的第一款软件","links":[],"tags":["记忆/高中","博客/原创"],"content":"无意间发现 CSDN 显示自己拥有九年码龄,就勾起了很深的记忆。那时刚开始接触程序设计的时候,经常接触到易语言、精益论坛、吾爱破解、看雪论坛等等。所以就一个一个登录查看有没有当年留下的痕迹……\n邮箱群发\n\n当时是在精益论坛接的一个 200 元的一个单子,然而写好以后又被放鸽子……\n最后就开源放了出来找不到源码了蛮简单的一个邮件群发助手简单测试功能还可以用\n\n\n附件功能应该是有 BUG 了,其他的正常使用;顺带附一下帖子地址和软件地址,满足一下各位好奇心。\n帖子地址QQ群发利器_精易论坛 (125.la)\n软件地址QQ群发利器软件\nAlgorithm : SHA256\nHash : 01E1E277B9BC173BA5E3A75E3D42E1AF18EA974AC91F42E8940AAE6FD1473452\nPath : C:\\Users\\ZZP\\Downloads\\Compressed\\QQ群-发利器\\QQ群发利器.zip\n\n洛克王国\n其实一开始我是做外挂出身的哈哈哈其中洛克王国辅助外挂做的时间最长简单记述分享一下当年巧遇 BUG 的事情,防止多年以后遗忘。\n洛克王国是一款网页游戏如果了解过相关的知识就会知道这种游戏离不开数据包所有游戏的操作都是基于数据包来完成的。当然所有类型的游戏互动都是基于数据包的但是外挂不只有单一的数据包类型的外挂在此仅简述数据包类型辅助外挂。\n洛克王国简单来说就是一个宠物养成游戏最枯燥的事情就是宠物升级需要不停的打怪。因此诞生了许多辅助外挂当时最快的外挂辅助从 1 级到 100 级满级需要 2 小时 15 分钟左右;\n因为洛克王国是一个偏向青少年的游戏在其更新过防沉迷机制后只有 4 个小时可以正常获取打怪经验。但是官方存在这样一个机制,就是在一个特定的场景:大剧院(就是在游戏内观看各种官方的电影等……),不会增加游戏时间。所以很多辅助外挂根据这个机制,衍生了很多延长获取经验时间的相关功能。\n而我这当时发现这个 BUG只需 12 分钟,对于当时游戏机制及其他辅助外挂是颠覆性的。\n一个简单的打怪场景\n如果在游戏内与场景怪物战斗升级就会与服务器进行数据包通信。类似于 TCP 的三次握手、四次挥手。例如\n\n客户端我要与编号 0001 怪物战斗。\n服务器收到编号 0001 怪物战斗请求,当前地图场景编号是否 0001 的我需要确认一下?\n客户端我确定在编号 0001 怪物的地图场景,我要开始战斗了。\n服务器战斗开始校验……\n客户端我要用技能 A干它。\n服务器技能 A 使用成功。\n客户端我要用技能 B干它。\n服务器技能 B 使用成功。\n服务器怪物死亡……\n服务器宠物 A 获取 100 exp经验。\n\n这是一个简单的战斗过程实际校验以及数据包通信比较复杂繁琐。这时你可能想我直接给服务器说怪物死亡获取经验不完了。你想要的可能结果是这样的\n\n客户端怪物死亡……\n服务器战斗异常这玩意脑子抽风了客户是上帝我还是委婉点。\n\n当时基本上 95% 的外挂辅助都是基于此原理开发的,通过不断重复的与服务器进行数据包通信,借此达到宠物升级的目的。\n大剧院机制\n不过后来大剧院的机制很多外挂辅助便在进入战斗确认战斗场景以后。更换场景进入大剧院接着完成剩下的数据通信。简单来说就是在上述第 5 步之前,与服务器进行数据包沟通更换场景,然后继续战斗,以便达到节省正常游戏经验获取时间。因为并不影响游戏体验,所以官方是默许此机制存在的。\n而且官方其实开发的也有外挂辅助只是以民间的名义存在罢了。当时手动升级一个宠物需要一周左右太影响游戏体验了而且当时市面的游戏辅助并不影响 TX 挣钱,所以……\n检测机制\n当时作为外挂辅助开发者我是不满足长达 2 个小时的时间,就一直在摸索官方的检测机制。因为数据包通信必须存在一定间隔,因为你不可能这样通信:\n\n客户端我要与编号 0001 怪物战斗。\n客户端我确定在编号 0001 怪物的地图场景,我要开始战斗了。\n客户端我要用技能 A干它。\n客户端我要用技能 B干它。\n服务器傻 X ……\n\n所以当时每个数据包通信间隔最少需要 600ms约为 0.6 秒),正是因为这个机制所以一只宠物需要 2 个小时才可以升到 100 级。\n发现 BUG\n当时反向思维搞了一波就是如果数据包通信间隔过快官方是如何检测我的违规操作并进行封禁处理呢\n简单尝试一下发现官方并不是检测到你状态异常直接对你的用户状态进行封禁。而是很莫名其妙的用这个机制进行封禁……\n\n客户端我要与编号 0001 怪物战斗。\n\n100ms\n\n服务器收到编号 0001 怪物战斗请求,当前地图场景编号是否 0001 的我需要确认一下?\n客户端我确定在编号 0001 怪物的地图场景,我要开始战斗了。\n\n100ms\n\n封禁服务器这 B 太快了,封禁。\n封禁服务器这 B 在那个地图?跟谁战斗?找到他封禁!\n客户端已被封禁\n\n可能是因为每个功能具体分工不同而且也不明白为什么要在游戏内找到这个角色再进行封禁……\n基于这个机制我是这样搞得哈哈 h\n\n客户端我要与编号 0001 怪物战斗。\n服务器收到编号 0001 怪物战斗请求,当前地图场景编号是否 0001 的我需要确认一下?\n客户端我确定在编号 0001 怪物的地图场景,我要开始战斗了。\n服务器战斗开始校验……\n客户端我要用技能 A干它。\n客户端哎、我跑到这个地图了。\n\n1ms\n\n客户端我要用技能 B干它。\n客户端哎、我跑到这个地图了。\n\n1ms\n\n客户端我要用技能 C干它。\n客户端哎、我跑到这个地图了。\n\n1ms\n\n\n服务器技能 A 使用成功。\n\n\n服务器技能 B 使用成功。\n\n\n服务器技能 C 使用成功。\n\n\n服务器怪物死亡……\n\n\n服务器宠物 A 获取 100 exp经验。\n\n\n封禁服务器这 B 太快了,封禁他\n\n\n封禁服务器这 B 在那个地图?跟谁战斗?找到他封禁!\n\n\n地图服务器在 001 地图(此时用户又更换了地图场景 002\n\n\n封禁服务器找不到啊赶紧告诉我位置\n\n\n地图服务器在 002 地图(此时用户又更换了地图场景 003\n\n\n封禁服务器找不到啊赶紧告诉我位置\n\n\n……\n\n\n简述如上封禁服务器一直在屁股上追着你而且永远追不到你就这样每个数据包通信为 1ms升级时间从两个小时缩短到 12 分钟。\n后续\n后续我还没有发布这个版本官方便停服维护了进入战斗后 10 秒吧,禁止移动游戏场景……\n我现在不开发外挂Over游戏外挂和逆向破解挺有成就感的不过可不要贪杯哦哈哈\n接下来的日子砥砺前行\n"},"Personal/Blog/2021/我站立的地方是中国":{"title":"我站立的地方是中国","links":[],"tags":["生活/日记","博客/原创"],"content":"向四位卫国戍边英雄致敬!!!\n陈红军烈士\n\n陈祥榕烈士\n\n肖思远烈士\n\n王焯冉烈士\n\n\n清澈的爱、只为中国\n\n\n图片引用自百度百科"},"Personal/Blog/2021/我还在……":{"title":"我还在……","links":[],"tags":["生活/随笔","游记/开封","博客/原创"],"content":"最近现实生活比较充实、也就没有太多闲暇时光写博客了……放几张最近生活照,期待下一篇博客。\n\n\n\n二十三岁你好\n"},"Personal/Blog/2021/星光不问赶路人":{"title":"星光不问赶路人","links":[],"tags":["游记/洛阳","游记/老君山","摄影/作品","博客/原创"],"content":"距离上次写博客已经过去近一个月了,这期间发生了好多事情好多事情呀。一直在忙啊忙啊忙啊,其实也是在瞎忙,适应新的生活,分享一下我最近一个月都在忙什么……\n找工作呀找工作\n过完年后就一直在投简历找工作。投了很多很多简历结果都是石沉大海心态蛮低落的。期间收到的第一份工作面试是一家玻璃制品公司的信息维护员岗位主要负责信息的维护整理。我并不是很喜欢这份工作简单面试通过后就只能先将就干着毕竟养活自己最重要。\n当时计划着是换一座城市尝试一下新的环境和生活。为此投了很多简历无限制的拉低自己要求可生活总是这样当你处处妥协它便处处压迫。抱着无所谓的心态乱投简历收到了好几份面试通知。\n面试那天对我依旧记忆犹新早上收到了通知下午面试。中午休息请了两个小时假走完人事流程便去面试了。很激动也很无所谓很激动是这份工作挺符合我的想法的双休不加班管吃管住无所谓是觉得人家不一定会要我啊。\n简单做了一个自我介绍面试官考答我了一些 SQL 的知识,对我来说问题不大。\n最后听到面试官跟部门负责的谈话内容“这个底子不错基础知识各个方面都很扎实硬件软件都不错没什么问题。”\n这么长时间以来的的委屈就瞬间爆发一走出去眼泪就在不停的打转。\n入职准备前的小插曲\n入职除了正常的必备东西外还需要提供上一份工作的离职证明。说来话长也不想赘述感慨万千。\n\n生活中充满了不确定性我们无法去改变外界的不确定那就试着改变自己。储备了足够的能量就不会被生活打垮。只有变得越来越强才不会错过每一个翻盘的机会。\n认真准备考试缺总是失败没有信心继续再战。别气馁之前的失败都是在积累经验认真分析原因朝着成功继续发力默默无闻工作多年看不到晋升的机会。别灰心从手头上最简单的事情做起把简单做成专业你一定能突破职业“天花板”。\n—— 佚名\n\n第一天工作\n3 月 5 日是我第一天工作,我很努力的去学习,尽力做好每一件事情。但是很累,也不知道怎么调节,慢慢的劳逸结合咯。\n在信息部我是年龄最小的一位算上我新来的部门一共有 7 位,分别是:路哥、代哥、松哥、鹏哥、振哥、豪哥。直到今天部门共有 9 个人,队伍也是越来越壮大。\n工作中遇到了很多奇葩的事情不过慢慢就习惯了。\n喏我的工牌和工位\n\n\n建民哥竞选队长\n建民哥队长落选这件事挺颠覆我的认知的一笔带过吧。\n再游洛阳\n振哥我们俩工位挨着接触到也最多。爱好也比较相同他也喜欢摄影。这又让我重燃了对摄影的热爱我的尼康 D610 哎!\n有次周末去了二七塔、火车站附近乱逛、拍照。偶然就碰到了一个旧货市场的就是藏在小巷里的街市。买了两本旧书我比较喜欢老物件哈哈蛮开心的。\n后来又相约拍星空心心念念的。清明假期的时候跟着苗胜相约一块去了老君山。天气本来就不好然后还下着雨。就感觉可能就跟上一次去老君山一样吃闭门羹。先去的洛阳十字街、洛阳博物馆、小街天府、中国国花园就跟我上次跟老友去洛阳一样哈哈不过这一次是反着来的没有喝到心心念念的咖啡\n洛阳博物馆对于我来说、呃……对我们来说一点都不好玩哈哈哈。\n因为下雨牡丹也不好看。\n\n\n我与振哥的星空之旅\n下午赶路到栾川安顿好一切酒饱饭足后出发\n晚上 10 点出发的,山路预计 15 公里左右,高度差 1800 米左右。刚开始出发的时候,夜色不算太暗,还能看得到路。走着走着山雾就越来越大,直至最后手电筒也不管用了,用手机,手机照明也不管用,能见度毫不夸张只有一两米。山路挺危险的,遇到了滑坡落石和莫名其妙的断头路!\n\n走了近两个小时感觉就像是在做梦一样走的也很累。就是很突然、刹那间山雾皆散我们两个兴奋的尖叫起来\n拍照拍照下面这是在凌晨 12 点在半山腰盘山公路拍的\n\n继续赶路走到南天门稍作歇息继续出发凌晨三点到达金顶还有一只小猫迎接我们找到避风的地方后。自热小火锅搞起小酒搞起\n还记得小猫不它跟着我们走了蛮久我给它分享了梅菜扣肉把肉全给它了。它吃的蛮香的吃饱就溜了。\n\n吃完小火锅后喝过小酒后。\n振哥就突然说中平、你抬头。\n哇哦心里一颤竟是漫天繁星。宛如芝麻撒地一般心里就在想也许这就是小猫给我们带来的幸运。本来我们在山腰看到雾散了明天可以看到日出就很兴奋觉得不虚此行了没想到很意外还能看到星空真的是太幸运了\n\n\n老君山日出\n看到星空后相机设置延时摄影。我跟振哥便下山避风了太冷了真的太冷了……\n差点就在厕所睡觉避风了不过老君山厕所真臭还害我摔了。找了纸箱子坐地上背靠背取暖了终于挨到了早上五点多……\n不想用语言描述诺、看日出吧\n\n\n\n道教金殿\n\n\n这是在下那个小金顶的时候用屁股挪着下的。期间拍到了这两张用手机拍的像素太低了成片效果其实可以更好的\n日出后的金殿是真的美就像路人说的一样来老君山是需要运气的\n我们的照片\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n感情就是要互相理解、互相包容才可以长久的。还是祝福你俩长长久久\n不虚此行、来日方长\n\n星光不问赶路人\n"},"Personal/Blog/2021/济南呀济南的泰山之旅":{"title":"济南呀济南的泰山之旅","links":[],"tags":["游记/济南","游记/泰山","博客/原创"],"content":"啦啦啦~~~是的、没错我又去爬泰山了。今年中岳嵩山、西岳华山、东岳泰山都已经搞定!接下来就是南岳衡山和北岳恒山了,游记一类的博文,很多时候写的都是流水账……其实我也想挂几张照片完事哈哈哈。\n赶路 Ing\n出发前大家是真的好墨迹墨迹连我平时磨磨唧唧的都感觉是真的墨迹。我们五个人她们四个没啥事我是最晚的 6 点下班。然后磨磨唧唧的搞到 8 点才上高速,极其平淡的 5 个小时路程,真的是极其平淡的 5 个小时。一路上我开车,然后她们都是死气沉沉的……\n凌晨终于到达济南然后呢。吃饭的地方没有找到、住宿的地方也没有找到Oh my god\n无论如何干饭人的第一要则先吃饭。找到了一家酒吧烧烤24 小时营业的那种,边吃边找住宿的地方。一切安顿好之后,淦饭喝酒哈哈哈。\n大家都喝了不少的酒聊天讨论生活聊聊感情。当代恶臭年轻人最丧的事情就是聊感情其中一位也是很刚结束一段感情。\n最后感觉都有点麻木了用一句话表达我们酒后的状态\n山东菏泽曹县牛逼 666 我嘞宝贝!!!(原谅我等粗俗之人哈哈 h\n济南呀济南\n\n\n第二天一早醒来简单洗漱以后趴在窗户眺望天气是真的好呀\n出门的时候已经快中午了找一家鲁菜馆好像是被坑了。准确来说就是被坑了小红书上是这样说的专坑外地人的。店名我忘记了就在大明湖前边一个商业广场那里。\n大明湖畔\n\n\n大明湖有点类似于每个城市都会有的人民公园没有想象中的景区购物呀什么的是个饭后散步的好地方\n刚进去就直奔坐船去了大明湖嘛。然后看见了游乐场便起劲尝试流星大摆锤哈哈哈很带感某些人说他在再也不会玩这个了。然后呢紧接着坐船就是刚才的某些人因为大摆锤的原因有点晕船。一直像个小孩在吵闹上岸。\n我吐槽他你可以吐在大明湖里这将是你一辈子的回忆哈哈哈哈哈。越着急船晃动的起伏便越大最后上岸连忙去找卫生间吐得那叫昏天暗地呀。\n芙蓉街\n\n\n啊······\n这就是我对芙蓉街的感叹……犹如天下所有的商业街一般完全没有一点特色更没值得人流恋的感觉。至少对我来说是这样的西安的回民街济南的芙蓉街感觉还不如登封的小吃夜市街。\n古建筑、泉眼等似乎都差那么点感觉急急忙忙的逛了一边想买一点特色的纪念品仿佛都是奢望只有遍地的大葱卷饼。\n泰山\n\n济南离泰山只有一个小时的路程因为我们是开车所以比较轻松自在。临近泰山脚下打卡 5 元纸币!\n简单吃过饭后收拾了一下登山的物品。这个时节天气还是比较冷的都穿的有羽绒服而我作为一登山老手单薄便衣便一起出发了。夜爬泰山的人真的是超级无敌多感觉就像是在菜市场买菜真的是好多人。大家伙除了我很快便体力不支了我也是走走停停。爬过中天门后我也是跟小伙伴在中天门这分离了开始独自一人登山。\n\n\n这张图是在十八盘哪里拍的想拍出来流浪地球的感觉拍的不好见谅哈哈。\n简单谈一下登泰山的感想泰山相对并不算很高海拔 1520 米。从红门到中天门再到南天门,我用了 3 个小时多。正常来说需要 5 个小时左右才可以登顶,体力不支的情况下可能需要六七个小时。由于夜爬,并没有办法欣赏很多路上的风景,天亮后发现,路上实际上也并没有太美的风景。作为五岳之首,泰山自然是有它的魅力的,对于我来说,差那么一点意思。\n泰山的登山路上只有一眼望不到头的台阶和两三百米一个的泡面店哈哈哈。真的是感觉就像店家好贴心怕你饿着累着然后一路都是卖吃的。不过对于泰山顶的商家可能有点以偏概全印象完全不好一点点都不好。景区商业化正常理解但是泰山顶上感觉就是你花钱来当孙子了……\n日出\n\n感觉可能是爬泰山执念太深或者是没有计划好攻略导致不太完美。爬山的时候有点冲动的跟小伙伴分开单独爬。然后在占位置等日出的时候在山顶又不小心睡着了。导致回到郑州头痛三天……\n硬是扛到日出没有云海没有很惊艳的感觉。就像是草草打卡便走了……\n写的草草流水账一样主要是心无波澜。但还是总想留下些什么不算是草草应付的博客只怪泰山没有惊艳到我\n\n友谊万岁\n"},"Personal/Blog/2021/涝疫结合":{"title":"涝疫结合","links":[],"tags":["记忆/郑州","博客/原创"],"content":"2021 年上半年已过,迎接下半年的便是酷暑、洪水、疫情,天灾人祸,地处郑州的我最近也是经历蛮多,触目惊心……\n酷暑\n一步入七月份便是酷暑那是真的热。每天午休过后到办公室的一段路程犹如横跨了撒哈拉沙漠我更是宛如晒干的咸鱼……\n还没入伏都这么可怕入伏岂不凉凉……\n好在天气预报有将近半个月的下雨天便期盼起了雨天。下雨天在家睡大觉就像猫咪吃小鱼干那般快乐。\n世事难料谁想到这场大雨竟成为郑州人挥之不去的梦魇……\n洪水\n7 月 19 日郑州下了一整天雨。\n7 月 20 日雨依旧下的很大、所有人都只认为这是一场久旱逢甘露的大雨。\n7 月 20 日雨势越来越大\n路面开始积水……\n汽车开始抛锚……\n地势低洼的地方被倒灌……\n城市主要河道即将漫堤……\n所有的一切来得那么突然来的那么让人措手不及……\n7 月 21 日防汛应急响应级别由Ⅱ级提升为Ⅰ级。\n人们开始产生恐慌……\n停水停电手机无信号城市也失去了本属于夜晚的色彩……\n7 月 21 日天亮了,雨依旧在下……\n地铁五号线被淹……\n市区内隧道全部被淹……\n部分道路出现塌陷人民受灾……\n以前总感觉天灾人祸离自己蛮远的。生活的主旋律也是平凡、简单但仿佛这一切都在告诉你醒醒吧孩子哈哈哈你在经历疫情洪水\n那天我也是正常下班公司离家挺近的。但由于雨势大有些司机不敢走堵车堵得……\n最后还是把车扔了徒步回家。路上也是淌过了齐腰的水也见了很多抛锚的车。到了家早已经淋得不成样子了手机也进水了。报个平安熬着熬着便睡着了。\n相信你也看了很多关于郑州洪水的报道我也就不一一赘述了。\n不过这次对小区物业点赞 100 分,洪水期间:无断电、无停水、无断网。\n疫情\n啊啊啊···\n疫情零零散散马上都两年了感觉大家都习惯了。\n可是就是突然给你来一个王炸\nOooooooH ~\n现在是 2021 年 8 月 2 日 00:30刚被 tong 完上来。迷迷糊糊睡了一天了,明天也没法上班,超市也被搬空,人心惶惶的……\n自古多难兴邦还是愿你我平平安安。\n"},"Personal/Blog/2021/申请-Jetbrains-开源项目授权":{"title":"申请 Jetbrains 开源项目授权","links":[],"tags":["生产力工具/Jetbrains","博客/原创"],"content":"作为宇宙第二 IDEJetbrains业内很多 ITer 肯定都了解一二。不过相对于宇宙第一 VSJetbrains 严格的正版授权和高昂的售价,让很多人望而却步。不过也肯定有不少细心的小伙伴发现了,如果你拥有一个开源项目便可以申请 Jetbrains 正版的授权!已经申请成功的我来分享一下过程!\n很多使用 Jetbrains 系类产品的小伙伴肯定知道学生和老师是可以通过 .edu 邮箱免费获得授权,不过很多小伙伴毕业了才发现,更是悔恨相见恨晚。但 Jetbrains 提供了很多优惠,其中一项便是开源项目授权。\n申请条件\n\n申请过程\n1.填写项目具体信息\n\n这里需要注意是\n\n第一项是否已经有关于此项目的授权如果你一年的授权到期了项目也正常工作就可以输入上一年的授权 ID 申请继续授权。\n第二项授权数目根据仓库贡献人数填写。\n第三项填写的邮箱一定是项目拥有者邮箱而且如果使用的 github 必须公开此邮箱。\n\n2.申请反馈\n\n正确填写申请成功以后我们便可以静静等待一至两周了。\n没错幸福的事情都是需要等待的\n申请结果\n在我申请的过程中出现了一个小插曲我是 2 月 14 日申请的,直至 2 月 24 日都没有收到反馈结果。我便向 opensource@jetbrains.com 询问了是否收到申请,不久便答复了我。随后授权也一并下来了,很开心。\n\n授权证书\n\n\n开源的精神永远是被值得尊敬心存向往之心的\n\n估计很多看到这的小伙伴该有疑问了开源项目三个月持续贡献这容易申请么别辛辛苦苦三个月 push 再申请失败了。\n如果可以你去我的 github 个人主页查看 Index 仓库。它不过也只是一个简单的不能再简单的静态 H5 网站,但是我也一直在不停的贡献。\n记住梦想是不分大小的每个拥有梦想的小伙伴也都是值得尊敬的\n不过申请成功的小伙伴谨记**此授权是不可以用在商业项目上的!**所以拿到公司用是不可以的,不过通过自己努力得到的正版授权一定别有一番意义!"},"Personal/Blog/2021/真·长安游记":{"title":"真·长安游记","links":[],"tags":["游记/西安","游记/华山","博客/原创"],"content":"难道真的就没人发现,我···上次写的长安游记是错误的么?这次是去了真的长安!因为最近一直在忙着工作,所以这篇文章放了好久,再不放出来就要落灰了。\n前夕\n初五晚上我们到了鼓楼回民街到的时候已经是晚上 11 点多了,但依旧人潮涌动。随便逛了逛感感觉缺少了该有的土色土香,遍地充斥着商业化气息。找到一家饭店,我们都想喝一点小酒,却忘了这是回民街,几番折腾也是没能喝成。凉皮很不错,肉串也可以。就是羊肉泡馍有点小贵,没怎么点几个人就花了大几百……\n\n\n\n民风淳朴\n来的时候因为路不熟所以开车比较拘束右转走了直行便想打灯右转结果就被摩托小哥滴滴滴……摁喇叭顺带投来恶狠狠的眼神想干一架似的。因为我们的失误所以也就没想多。\n酒没饱饭足了但回去路上发生了一件很有趣的事情滴滴司机要右转摩托小哥要左转本就相安无事摩托小哥骑车比较随意两车便相对停下来了。滴滴司机便想说两句公道话但是两个人越说越着急互相问候一下双亲结果滴滴司机说话有点不顺溜摩托小哥说了一句伤害性不大侮辱性极强的话。\n先把你的舌头捋直了在说话把舌头都捋不直……\n妈耶滴滴司机直接爆炸降低车窗手搭在门把手上一气呵成给摩托小哥来了一口唾沫……两个大男人就这样在路口红绿灯下疯狂吐唾沫最后摩托小哥猛吐一口拧油门走了。我们四个在疯狂的憋笑都憋出内伤了\n还有一段路才到酒店路上死一样的寂静。滴滴司机先开口说话了你看这人不讲道理……\n我们终究是忍不住了哈哈哈哈\n终究是民风淳朴啊哈哈哈\n攀登华山\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n爬华山是真的很累本来几个大男生出来旅游就没人研究攻略。然后买票还差点买不到最后通过黄牛买到了。这次的黄牛倒是挺顺心妈妈般的呵护照料你们把车停在那里那里那里上山方便乌拉乌拉个不停哈哈哈。\n华山上的东西确实不便宜初六本来是我发小的生日打算在山上给他来首生日歌结果实力劝退\n一路上欢声笑语的不过有些人是怨声载道的。天气特别好碰到了一只猫一只狗不知道它俩在山头论剑么\n华山是真的险很想尝试一下华山栈道各种原因还没没能走一遭。临近下山一路上也是饿的肚子呱呱直叫好想吃好吃的哈哈哈。下山后开车觅食就看到了这个马踏飞燕我们说这是爬完山消费过了让我们立马滚蛋哈哈。\n干饭回家\n\n\n最后还是吃到了 biang biang 面,还有肉夹馍便踏上了回家的路程!"},"Personal/Blog/2021/记拾月":{"title":"记拾月","links":[],"tags":["生活/日记","博客/原创"],"content":"生活很充实,便没有太多闲暇时光来续写博客。好忙呀好忙呀……\n工作\n近来比较浮躁在成为老油条的路上越走越远。想换一份开发的工作也许都是围城罢了。\n工作中同事沟通协作有困难、导致工作没效率。重复来重复去都是那些事没有活力。创新也没有很好的反馈积极性更不提了 ~\n争取早日走进高一些、大一点的围城。\n生活\n腰疼天天坐班真的是不可避免地腰疼……\n胖了 30 斤 🤣"},"Personal/Blog/2021/贰号机、落幕":{"title":"贰号机、落幕","links":[],"tags":["生活/随笔","博客/原创"],"content":"自己经手的第二台主机、与初号机的不同、这次是贰号机的落幕。借此留念,贰号机!\n咸鱼偶遇\n上半年比特币引起的一波狂潮。导致我对电脑主机的显卡起了贪念便寻思出售了……\n闲来无事逛到了一台 1950x 主机,卖主是搞 3D 设计了。看着价格直流口水 ~\n做个二道贩子能挣 2K但是打小心心念念的极致性能主机。依然是触手可及便寻思留下来。\n经过一周的折腾收货验机重新布线系统安装等等等······\n经过一个月的闲鱼出售两台电脑。最后终于是折腾完了那是真的累。咸鱼上遇到了不少的小可爱玩意令交易充满了很多令人开心的事情。\n贰号机\n\n配置清单\nCPUAMD Ryzen Threadripper 1950X 16-Core\n主板华硕 ROG ZENITH EXTREME\n显卡GT 730 ( 2 GB / 戴尔 )\n内存海盗船 DDR4 3200MHz 16GB * 4条\n硬盘三星 PM981 256G * 2 块\n硬盘西数 500G 蓝盘\n硬盘机械硬盘 2TB * 3\n网卡intel 9260 AC\n电源航嘉 1000W 80 PLUS 全模组\n散热撕裂者 (Wraith Ripper) 散热器\n机箱SAMA 中塔机箱\n\n性能当属天花板级别了本来打算留着有机会升级至 2990WX、32 核心、64 线程,再加几根内存条,换个 U.2 的固态。\n再战十年 @贰号机"},"Personal/Blog/2022/2022":{"title":"2022","links":[],"tags":["年度/2022","博客/原创"],"content":"感觉时间过得好快呀,新的一年又要开始了。去年的目标完成了 2/3今年新的目标也需要制定了。\n工作\n\n\n今年争取全年工作日无请假\n\n\n年中可以谈一次绩效\n\n\n同事关系融洽愉快哈\n\n\n存 1 万块钱\n\n\n生活\n\n\n今年大家不要扎堆来结婚好嘛给我一点时间挣份子钱\n\n\n处理好自己的朋友圈抛弃无关紧要的社交\n\n\n需要更好的去处理收纳家里亲戚的关系这个超级重要\n\n\n今年会忙一点累一点生活质量暂不放在第一位\n\n\n学习\n\n\n5 月程序员初级职业资格\n\n\n5 月初级会计师资格证\n\n\nPAT 乙级证书\n\n\nPAT 甲级证书\n\n\n11 月软件设计师中级职业资格\n\n\n腾讯云云架构师\n\n\n阿里云安全工程师\n\n\nRHCE 工程师(结合物质基础,因为需要花好多钱呀)\n\n\n华为路由方面认证工程师同上这些证书好贵呀\n\n\n摄影\n\n\n希望真的超级希望真的巨希望今年可以拍到星空好嘛\n\n\n可以去青岛一趟 ~\n\n\n可以积攒一些入会河南省摄影家协会的积分\n\n\n提高自己的摄影基本功\n\n\n学习 PR & PS 技术\n\n\n钢琴\n\n\n学好最基础的乐理知识哈这个必须有\n\n\n争取报一个老师领进门教一些基础知识 ~\n\n\n感情\n\n希望自己可以给自己一个情感支柱\n\n支出\n\n\n70-300 镜头,如果可以的话,虽然虽然需求不大,但是谁又嫌多呢。\n\n\n无人机这个更多只能期盼于中彩票了……\n\n\ngopro 好吧,这个同上\n\n\n今年注定是要自给自足的一年严格的控制好支出。今年务必要养活住自己不问家里张嘴要一分钱。\n去年没有完成的一些硬性要求更多的局限于 GitHub 上面了,今年不再做更多的硬性要求了。\n今年物质基础方面更多注重的是自给自足不再着重于大的开支。如果物质基础充足更希望可以出去玩几趟 ~\n今年不再为自己增加不确定性的工作生活。首先是工作今年无论如何工作不会有一丝一毫的变动其次是生活方面将更注重学习其次是生活。\n主要就是弃繁就简提高质量让自己更加的成长"},"Personal/Blog/2022/Halo-主题-Redemption-首发版":{"title":"Halo 主题 Redemption 首发版","links":[],"tags":["开源项目/Redemption","博客/原创"],"content":"\nRedemption 一款专注阅读、写作的 Halo 博客 主题。主要设计思想即是专注阅读、写作,是一款极简类型的博客主题。\nRedemption 部分设计灵感借鉴 Halo 博客 Zozo 主题,感谢各位前辈的无私开源。特意针对首屏加载进行优化,无需 CDN首屏 0.7s 内加载完成。全尺寸媒体自适应查询以及自适应深/浅色模式,让你专注写作,不带感情!\n预览\n\n在线7Wates blog\n\n\n主要功能\n\n专注阅读写作设计\n深 / 浅色自适应模式\n全尺寸布局媒体自适应\nMarkdown 样式设计\n社交链接展示\n支持独立页面\n\n安装方法\n\n远程拉取github.com/7Wate/halo-theme-Redemption 复制地址点击下载\n本地上传在 Github国内 gitee 下载) 页面,下载压缩包然后上传安装。\n\n主题配置\n\n自定义博客标题以及短语并填写对应备案号。\n自定义显示 开往 和 十年之约 的 logo。\n\n社交链接\n\n自定义关于页面、Github、哔哩哔哩、邮箱链接。\n\n评论设置\n\n自定义开启评论默认关闭。\n\n正常启用评论需要编辑主题在 /source/plugins/comment/halo-comment.min.js 文件中修改 {baseUrl:"blog.7wate.com/"} 双引号内的地址为你的博客地址。\n为了适配主题风格Fork 了官方仓库的评论组件。\n组件仓库7Wate/halo-comment-normhalo-theme-Redemptional\n图库设置\n\n自定义是否显示图库。\n自定义图库页面标题以及短语。\n\n许可证\nGPL-v3.0 协议开源,请遵守开源协议。\n\n来源Halo 主题 Redemption 首发版 - 7Wates blog非商业引用著作权归作者所有。\n"},"Personal/Blog/2022/Hello-Halo":{"title":"Hello Halo","links":[],"tags":["博客/原创"],"content":"Hello Halo\n如果你看到了这一篇文章那么证明你已经安装成功了感谢使用 Halo 进行创作,希望能够使用愉快。\n相关链接\n\n官网halo.run\n文档docs.halo.run\n社区bbs.halo.run\n主题仓库halo.run/themes.html\n开源地址github.com/halo-dev/halo\n\n在使用过程中有任何问题都可以通过以上链接找寻答案或者联系我们。\n\n这是一篇自动生成的文章请删除这篇文章之后开始你的创作吧\n"},"Personal/Blog/2022/Redemption-主题-0.2.1-版本":{"title":"Redemption 主题 0.2.1 版本","links":[],"tags":["开源项目/Redemption","博客/原创"],"content":"这次 0.2.1 版本是基于博友的发现,简单处理了以下两个问题、并添加适配了文章页 Markdown 渲染 CSS 样式。\n点击打开 Git 仓库下载主题\n自适应媒体查询无法正确适配屏幕\n基于 870px 作为阈值,划分了移动端和桌面端;移动端暂未发现明显问题,未修改 ~\n桌面端现在 8K 分辨率以下的无障碍阅读可能存在未知错误5K 分辨率及以下完美阅读;同时支持任意百分比缩放不失真。\n评论区适配存在部分问题因为需要调用 Halo 官方的评论组件,所以简单适配了一下。\n如果存在问题请告诉我 ~\n适配了文章页 Markdown 样式\n基于开源的 Github CSS 样式,二次修改得到 Redemption 原生文章样式,根据系统自适应浅色 / 暗色模式。\n关于 Redemption\nRedemption 比较符合个人审美,核心理念是回归阅读;来日方长期待日后更加精进。"},"Personal/Blog/2022/Redemption":{"title":"Redemption","links":[],"tags":["开源项目/Redemption","博客/原创"],"content":"一款 Halo 博客主题,前前后后增删改了总计近万行;借鉴 halo-theme-zozo 主题样式,自定义了一些特色。也算圆了自己想独立开发一款博客主题的念想……\nRedemption\n目前支持如下将来根据需求开发。并不打算做大做强哈哈再创辉煌 🙄。以阅读为第一要素,所以并未明显提供较现代化功能按钮,丰富了字体、字号的选择(未提供设置选项)。\n\n 深色模式\n 媒体自适应\n Markdown 样式设计\n 导航栏\n\n功能介绍\n主要页面\n\n\n首页站点标题点击返回首页点击打开首页\n\n\n归档首页文章列表块右下角日期徽标点击打开归档\n\n\n分类分类目录 点击打开分类目录,点击打开默认分类\n\n\n标签首页文章列表块右下角标签徽标点击打开对应标签点击打开标签目录\n\n\n顶部徽标\n就是主页面右上角那一组小图标提供了拓展功能和页面跳转。\n\n关于脚印徽标点击打开关于页面\n摄影相机徽标点击打开摄影页面\n日志消息徽标点击打开日志页面\n归档抽屉徽标点击打开归档页面\n邮箱邮箱徽标点击发送邮件至博主\n开往火车徽标点击打开开往页面\n友链曲别针徽标点击打开友链页面\n\n沉浸式阅读\n博客以阅读为第一要素故文章页面未提供功能按钮返回和留言在页面最底部为了表面符合国内备案要求留言需要点击才可以显示功能区。提供了字体和字号的选择未提供功能按钮目前仅可在 F12 配置),为符合各个时区的阅读舒适性,深色模式为自适应模式。\n页面预览\n桌面端\n首页\n\n\n\n\n\n\n\n移动端\n\n\n\n\n\n\n\n救赎之路\n为什么取 Redemption 呢,源自我最爱的一部电影《肖申克的救赎》。\n博客自 2018 年至今第四年、1337 天,说长不长说短不短,心中的执念、情绪的发泄地。\n😈"},"Personal/Blog/2022/「引用」博客的本质是电线杆子":{"title":"「引用」博客的本质是电线杆子","links":[],"tags":["生活/感悟","博客/原创"],"content":"也是看到友博的文章《正经人谁写博客》,然后翻阅了一下近两个月来的博客流量访问数据。今年年初也是被纳入了几个订阅合集,分享讨论一下关于个人博客流量。\n目前主要维护的网站有三个分别是站点首页、个人博客、知识维基。其中两个网站做了流量统计实际看来还是较惨的……\n经常来逛的老朋友可能没有关注过站点首页顶级域名是做了一个站点导航博客则是二级域名。\n首页\n\n\n\n站点首页的数据极其惨淡可以说无人问津……\n大多可能是自己或者老朋友大学同学来逛的比较多。\n说来也是有趣很多友博可能想不明白为什么我的顶级域名是 7wate.com说来话长。因为大学同学说我脑子瓦特掉了然后 wate.com 这个域名又被注册了,然后选一个幸运数 7主域名就这样来了 \n博客\n\n\n\n\n\n\n总的趋势来说主要流量来源于今年加入了一些订阅合集剩下的就归功于友博了哈哈蹭着你的每日金句也是掌握了流量密码哈哈 \n从来访地区来看北上广深杭这些一线城市最多。\n桌面端的话MS 还是老大,零零散散还有些许 Linux。话说我也想尝试换成 Linux 工作MS 真的是槽点满满!\n移动端还是 iphone 居多,紧接着是华为和小米,跟手机销量排行基本相同。\n百度现在基本可以正确检索了完全 ok所以目前是不再打算做访客信息统计了。\n最后引用友博的标题《博客的本质是电线杆子所以难免会遇到乱尿的》欢迎大家来「尿」。\n哈哈哈哈哈哈哈哈哈哈哈哈"},"Personal/Blog/2022/一线城市拥有一亩三分地是什么体验":{"title":"一线城市拥有一亩三分地是什么体验","links":[],"tags":["生活/园艺","博客/原创"],"content":"最近突然很喜欢这种类型的标题,就感觉标题党能打翻调味瓶,勾起想要阅读的欲望。不过我确确实实在一线城市拥有自己的一亩三分地,费了好大功夫收拾整理,才把废置的田地复耕出来。种花种菜种软妹币,相信我已经获得了财富密码!\n我居住生活在中部省会城市所以嘛也是新一线城市中的一员。由于历史原因和城市发展的影响所以我很幸运的享受着城市化的生活还可以拥有自己的一亩三分地。\n\n\n\n去年的时候就有在复耕已经废弃了很久的土地今年已经初具规模了。当时还养了小兔子还有尝试种植了一些蔬菜不过蚊子实在是太多后来由于生活工作也太忙就又闲置了。今年过完年工作生活步入正轨后便又开始我的园林生活。\n以前这块地是我家的果园种了好多好多的果树有梨树、杏树、樱桃树、核桃树、葡萄树等等。小时候这块地简直是我的噩梦因为每个假期都要去地干农活、割草、浇地、摘果子。纵使现在我又开始尝试耕作但是我依旧觉得当初的时候很不开心。\n主要工作砍树、清扫垃圾、搬运杂物、施肥翻地待进行育苗、种植、浇水等等。基本工作已经搞定不过还需要完善一下细节后花园的氛围感就来了。\n\n\n\n\n这块土地总的下来有近 6 亩地,全部整理出来的话今年就要再加把劲了。目前整理出来了有 1/4后续工程量还是比较大的。目前主要规划种花、种菜、养鱼会按照先后顺序来的因为我比较喜欢种花 ~\n\n已经松地施肥等待周末花的到来 ~\n持续记录 ing"},"Personal/Blog/2022/三步为你博客文章分析情感关键字":{"title":"三步为你博客文章分析情感关键字","links":[],"tags":["开源项目/EndOfYear","博客/原创"],"content":"最近闲来无事(其实真的不能说自己闲,有毒……),便想着用 Python 分析一下博客文章关键字,看看平时博客主要写了些什么,能不能从中探寻到什么?\n如何使用\n项目地址git.7wate.com/zhouzhongping/BlogWordCloud\n\n\n克隆项目到本地\n\n\n爬取或拷贝数据至 data 目录\n\n\n运行 index.py\n\n\n具体细节请阅读项目 README\n莫比乌斯\n\n我的词云图\n\n\n如果、所以习惯性使用连词看来我说话还是比较有逻辑的 🙄\n需要、感觉看来平时博客还是流露了不少情绪在里面 🤐\n我们、事情、工作平时还是挺喜欢社交和工作的 🤓\n可以、就是联系平时经常说这话的语境可以看得出自己还是有一定能力的 😎\n自己、一个我是独狼哈哈 😩\n可能、因为果不其然我还是比较喜欢联想和猜测的 😛\n问题、但是我确实比较喜欢表述自己的观点这点还需要进步 😶\n不过、已经、没有联想语境上下文、对待事情还是比较中肯🤔\n\n一个一个解读关键字挺有趣的哈哈。\n这些关键字结合具体实际情况确实能映射出自己的主要性格还是挺有用的哈哈 😈\n有点点水文章的意思确实是水了。但是不想拖到明天再写了……\n哈哈关于项目如果有什么问题可以留言、提 issue 、发送邮件(微信实时 🎉🎉🎉)。\n刚开完会我觉得下班开会还有开会说废话巨傻逼简直就是在浪费生命\n忙了一整天有点累有点累……\n我要回家拥抱大床了奥里给 ~"},"Personal/Blog/2022/不要在饿的时候吃螺蛳粉!":{"title":"不要在饿的时候吃螺蛳粉!","links":[],"tags":["美食/螺蛳粉","博客/原创","成长/个人"],"content":"螺蛳粉源于广西柳州,由柳州特有的米粉,加上酸笋、木耳、花生、油炸豆皮、黄花菜、青菜等配料及适度的酸辣味和煮淡水石螺的汤水调合而成,具有酸、辣、鲜、爽、烫的风味及酸笋的特殊气味。\n第一次吃是高中参加市田径运动会比赛结束后被队友带去吃的从此便开始了螺狮粉的不归之路。自此螺蛳粉贯穿了我的青春虽然臭是真的臭但是好吃是真的好吃。\n至于为什么不要在饿的时候吃螺蛳粉我是因为饿的时候饥不择食、吃到最后会很撑。全然只是为了吃丝毫体会不到螺蛳粉的快乐。只有真正不饿的时候想不起它时候。突然它的出现产生出让你想要进去吃一份的欲望那么这份螺蛳粉才是真真的好吃。\n至此以后每每再吃螺狮粉总会对比曾经的味蕾巅峰。这家的差点意思、这家的有点辣、妈的酸醋呢不好吃还是去那家吧、这家是不是换老板了\n说实话螺狮粉的味道差异真的会有那么大么我觉得不然现代工业社会我们从味蕾上几乎很难分辨出公牛、母牛肉。同样我们也很难分辨出螺蛳粉的味道差距所以到底是什么在作怪。\n当我很饿的时候我几乎觉得螺狮粉都挺好吃的。不过这种情况下、除了💩不好吃其他都会很好吃。当我不开心的时候再好吃的螺蛳粉也吃不到我的心里。当我没有钱的时候理智告诉我你去吃霸王餐会被摁到💩里但是我的口水会流三里地……\n那么如果螺狮粉的因素是可控的那么就剩下本能、情绪、理智这三种因素是不可控的了。所以我们要想吃一份巅峰螺狮粉那么我就要在不是太饿的时候情绪稳定的情况下口袋里也刚好有粉的钱那么这份螺狮粉一定不差。\n如果恰好这种情况下是我第一次吃螺狮粉那么这次螺狮粉也将会是我的味蕾巅峰"},"Personal/Blog/2022/习惯养成第一步":{"title":"习惯养成第一步","links":[],"tags":["成长/个人","博客/原创"],"content":"最近践行早起、阅读、写作、运动、冥想、子弹笔记近两个月了,简单复盘并针对现有问题提出对应解决方案。\n早起\n我所认为的早起并不是成功学所定义的早起每日早上四点啊五点啊弱弱的感觉这种成功学大部分都有病……\n早起可以延申为规律生活规律作息并不是单纯意义上的四点起床五点起床。结合个人实际情况我所定制的休息时间为 23:00 休息6:00 左右自然醒。不过大多时候都是 7:00 左右起床,偶尔 6:00 左右,一般只要醒了就不会再睡了,否则我是越睡越困、越困越睡……\n这两个月总体来说坚持得不错相对于之前有较大的改善不过还是偶尔会被外部原因所打乱作息。下一阶段性目标继续坚持非必要不打破作息。\n阅读\n每周阅读一本书还是完全 ok 的,但是吸收归纳产出的话,一个月可能才会啃烂一本书,有些书真的需要细嚼慢咽,慢慢回味。\n读书这件事真的会上瘾但是感觉很拉闸的一点就是目前为止还没有找到比较有效利用碎片化时间的方法。所以虽然每日都在阅读但是需要最少 15 分钟以上的空闲时间,才可以进入沉浸式阅读。\n目前暂时停止了读书计划因为前几本书的产出还未完成所以打算再产出后再开始新书阅读。下一阶段性目标提高产出效率保持阅读频率。\n写作\n产出效率较低一直是我比较头疼的地方也许是没有找到正确的方法论感觉也是写的太少想得太多。不想写流水账感觉有点敷衍未来还是需要不断尝试寻找适合自己的方法。\n\n曾经完成过一次 500 日写作,如今又开始新一轮 500 日写作的人帮你总结道:写作开始的时间,并不是你准备、收集、思考、规划、大纲等等过程,写作开始的时间就是你开始写下第一个字的时间,然后继续下去。\n—— ONO\n\n目前还是参考 ONO 的建议,但是先写在 wiki 上,然后每周甄选一篇博客发表,暂时就这样尝试。下一阶段性目标:实现每周产出。\n运动\n运动还是需要保持在生活中留出一部分时间去运动、散步然后继续坚持。不能这几天猛怼接下来几天偷懒要把运动当成吃饭一样 ~\n工作日的时候早起的话就会去跑跑步晚上下班也会在宿舍撸撸铁不追求马上看到成绩主要还是培养习惯。同时搭配良好的饮食习惯拥有一个健康的身体才士革命的本钱呐。\n下一阶段性目标继续保持争取早日养成运动习惯。\n冥想\n浅尝了一下这玩意真不是玄学YYDS\n子弹笔记\n子弹笔记也可以理解为复盘总结目前每日、每周、每季度都会进行工作生活的复盘。本来是一提起日记就会头痛的但是结合自己的情况尝试了多种方法最终找到了适合自己的工具和方法。\n日志总结归纳在 wiki 上边了,可以 点击打开 浏览。最重要的就是每日任务、复盘、习惯养成,有想法的朋友可以尝试一番。目前发现的几个问题是:任务完成效率不高、习惯养成容易被打破、子弹笔记容易中断。首先必须肯定这两个月来的进步,但是仍然需要继续保持,直至习惯的养成。\n任务完成效率不高同时带有拖延主要原因还是对任务难易的估量偏差过大。目前针对此情况的解决方法是主线任务、支线任务、其他任务主线任务是具有一定难度和时间成本的但是无论如何必须完成支线任务相对主线任务较简单的所以最少完成一个其他任务则是换脑子的很容易就完成的可以在疲惫的情况下换换脑子。\n这样的话每日都能切实感受到自己的进步并且持续保持正反馈\n子弹笔记和习惯养成容易被打破这方面主要还是降低心理预期毕竟都不是圣人。\nTake easy慢慢来 ~"},"Personal/Blog/2022/人在囧途——青海湖":{"title":"人在囧途——青海湖","links":[],"tags":["游记/青海湖","博客/原创"],"content":"一直以来对大西北都拥有莫名的向往,更是憧憬有朝一日漫步在青海湖。在十一假期的第二天晚上,去打球的路上莫名的想去青海湖。\n\n叔、突然那么一瞬间咱去青海湖吧\n速度回电话明天去\n\n就这样第二天四个成年人加三个小孩出发了来了一场自由与热爱的旅行……\n一路吃着火锅唱着歌仿佛自从坐上车那刻已经踏入青海湖了。\n\n而且而且最最最 BT 的事是什么?临出发的时候,旭鹏要骑摩托去,我们都觉得是开玩笑了;我日哦,直接拿着头盔就下楼了……手套也不带,骑行服也不带,总之就是头铁。\n毕竟莎士比亚曾经说过不气盛还叫年轻人么\n\n疯狂疾驰上千公里后即将进入甘肃境内我们在宝鸡服务区稍作歇息吃着泡面聊着有的没的此时我们还没意识到角落的大白才是最后的王者。此时旭鹏依旧兴致不减打算一路干到青海湖很显然他也没意识到有什么在等着他🐶。\n休整好再出发已经是后半夜了下起了大雨雨刷器都刮不及的大雨路上也没有一辆车了。我俩都在心疼旭鹏这会不会吃席啊哈哈哈更是一致认定他这辈子是忘不了这次骑行了\n<video controls style="width:100%;"><source src="static.7wate.com/img/2022/10/10/61949924fde73.mp4" type="video/mp4">您的浏览器不支持 HTML5 视频请下载Chrome或者Edge浏览器。</video>\n原谅我笑得这么没心没肺哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。\n没有办法自己选择的路哭着也要走完后续加把劲可算一路干到了西宁。临近青海湖虽然天气很差很差但是结合以往的经历更期待成为欧皇\n\n\n\n\n我们这里暂时不让下高速请你前往 XXX 高速口下高速!\n啊哈疫情防控办发布的通告符合规定允许下高速啊。\n抱歉我们这里禁止下高速请你自行折返\n……\n\n我日哦就是 TM 这么戏剧化;我们奔袭了 1700km临近青海湖 15km禁止下高速。\n简单来说当地省市疫情防控办发布的公告符合规定可以下高速当地卡口工作人员无任何正当理由禁止下高速……我们不死心继续折腾。在折腾了近 4 个小时后,无能为力、无可奈何、无无无,总之就是说破天就不让你下!(但是 TM 的当地有关系的人,你就可以随便下!)\n考虑人生地不熟加上无水无粮食纵有万般不舍也只能原地折返。\n<video controls style="width:100%;"><source src="static.7wate.com/img/2022/10/10/5c6f5846c43cb.mp4" type="video/mp4">您的浏览器不支持 HTML5 视频请下载Chrome或者Edge浏览器。</video>\n\n就这样Fuck\n我还能有什么好说的呢来日方长罢了。\n最后的最后虽然有时候我们去经历一件美好的事、尝试做好一件美好的事哪怕我们竭尽所能也总是事与愿违。但是终究无论如何我们终应该死在这自由和热爱里"},"Personal/Blog/2022/人格类型测试":{"title":"人格类型测试","links":[],"tags":["生活/随笔","博客/原创","成长/个人"],"content":"有看到很多人在做这个评测,我也闲来无事尝试了一下 ~\n\n“指挥官” 人格\n\n你的时间是有限的所以不要浪费它为别人而活。 不要陷入教条 — 活在其他人的思想成果之中。 不要让他人意见产生的噪音淹没你自己的心声。 最重要的是,要拥有追随你的内心和直觉的勇气。 他们已经知道你真正想成为什么。 其他所有都是次要的。\nSTEVE JOBS\n\n指挥官人格类型的人是天生的领导者。 这种人格类型的人天生具有魅力和信心,他们所散发的权威性能召集大家为着一个共同目标努力。 但与领导者人格类型有所不同的是,他们的性格中有着近乎残酷的理性,用强大的动力、坚定的决心和锋芒毕露的思想实现为自己制定的一切目标。 好在只有 3% 的人口具有这种人格类型,否则就会无情碾压那些剩下的大多数胆小又敏感的人格类型 — 但是对于许多我们习以为常的公司和机构,我们都要感谢他们的贡献。\n幸福来自于获得成就时的喜悦\n如果有什么东西是“指挥官”们所热爱的那一定非挑战莫属无论挑战大小他们都会坚定地相信只要有足够的时间和资源就没有无法达成的目标。 这种品质让指挥官型人格类型的人成为睿智的企业家,他们高瞻远瞩,能够将精力长期集中在自己的目标上,并且按部就班地执行自己的计划,矢志不移,目标明确,最终成为强大的企业领导者。 这种决断通常是一种自我实现的预言,因为指挥官型人格类型的人会凭借纯粹的意志力努力达成目标,如果换成其他人则可能半途而废,另寻出路,而他们拥有的社交技能也会督促激励着他们身边的人,并取得丰硕的成果。\n\n在谈判桌上无论是在公司环境下还是购买一辆汽车“指挥官”们始终处于主导地位毫不留情且锱铢必较。 这不是因为他们冷血无情或者是恶魔的化身,更重要的原因在于,指挥官人格类型的人天生喜欢挑战,喜欢斗智斗勇,拥有在这种环境下造就的智慧,如果对方难以招架,那就休怪“指挥官”让自己成为最后赢家的野心一览无遗。\n\n指挥官”脑子里想的是“我才不在乎你是否把我看作一个冷漠无情的“* 球”,只要我一直做个志在必得的“* 球”就行。\n\n如果问起指挥官会尊重什么那就是能够在智力上与之比肩的人行事的准确度和质量能够与之旗鼓相当的人。 指挥官人格类型的人在发现他人的才能方面可谓天赋异禀,这对他们的团队建设(因为即便一个人聪明绝顶,也不可能单打独斗就能成功)大有助益,也能让指挥官们有所收敛,无需时时展现自己的傲慢和屈尊态度。 但是他们也非常善于以令人发指的后知后觉唤起他人的失败感,而这也确实会让指挥官人格类型的人陷入麻烦当中。\n培养人际关系技巧\n在 Analyst Role 集团里,无论何种人格类型,情绪表达都不是他们的强项,但由于他们的社会属性,指挥官人格类型的人所展现的情绪尤其公开,会有更多的人直接感知到他们的情绪。 尤其是在专业的环境下,指挥官人格类型的人动辄就会粉碎一些人敏感的神经,在他们眼里,这些人效率低下,资质平庸或者浑浑噩噩。 对于具有指挥官人格类型的人来说,表露情绪就是在展示自己的弱点,他们很容易因此树敌 — 他们必须牢记一点,自己的成功绝对离不开一个正常运转的团队,这不仅是为了实现他们自己的目标,更是为了得到认可和反馈,而奇怪的是,指挥官人格类型的人对于这些极为敏感。\n指挥官人格类型的人是名副其实的能量库他们树立了一种英雄般的形象 — 事实上,他们也担得起英雄这一称谓。 对这种人格类型的人的忠告:他们的地位不仅仅是通过自己的奋斗得来的,也有团队成员在背后的大力支持,因此,必须要承认团队成员的贡献、才能和需要,尤其是从情感的角度,认可团队成员的支持协作,这一点至关重要。 即便他们奉行的是“假装可以,直到自己真正做到”,如果指挥官人格类型的人能够将情绪方面的健康关注点与自身的各项优势结合起来,他们将收获深刻而又令人满意的人际关系,以及所有值得拥有的艰难胜利。\nENTJ-A\n客观感觉确实有较大的吻合感兴趣的也可以去测试一下 ~\nwww.16personalities.com/ch"},"Personal/Blog/2022/你还记得曾经的梦想么?":{"title":"你还记得曾经的梦想么?","links":[],"tags":["生活/感悟","博客/原创"],"content":"看到了一篇博客,有一段视频,也算是广告很有意味。然后想顺带测试一下博客的 Bilibili 视频功能,再水一篇哈哈哈\n[bilibili:53239786,1,1]\n\n生活没有终点、最美的风景永远在路上 ~\n"},"Personal/Blog/2022/使用-Docusaurus-搭建优秀个人wiki":{"title":"使用 Docusaurus 搭建优秀个人wiki","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"Docusaurus 是一款静态站点生成器。 可以搭建带有快速客户端导航的单页应用,充分利用了 React让你的网站具有交互能力。 它提供了开箱即用的文档功能,不过也可用于搭建各种网站:个人网站、产品、博客、营销主页等等。\n当下个人知识的整理归纳已经及其重要了废话不多说。可以先体验一下我的个人 wikiwiki.7wate.com/ ,相信我你一定会爱上它!\n安装\n\nDocusaurus 官网\nDocusaurus 官网(中文版)\n\n因为中国官网文档更新相对滞后所以这里推荐使用英文官网进入后选择中文。\n环境\n\nNode.js (中文网) v16.14 或以上版本\n本文使用 Docusaurus 2.0.0-rc.1 作为演示\n\n初始化\n使用命令行工具可以帮助你快速简单地安装 Docusaurus 并搭建网站框架。 你可以在空仓库或现有仓库的任何地方运行这个命令,它会创建一个包含模板文件的新目录。\nnpx create-docusaurus@latest my-website classic\n项目结构\n命令行工具成功运行后你将会在新目录 my-website/ 下看到下列文件:\nmy-website\n├── blog\n│ ├── 2019-05-28-hola.md\n│ ├── 2019-05-29-hello-world.md\n│ └── 2020-05-30-welcome.md\n├── docs\n│ ├── doc1.md\n│ ├── doc2.md\n│ ├── doc3.md\n│ └── mdx.md\n├── src\n│ ├── css\n│ │ └── custom.css\n│ └── pages\n│ ├── styles.module.css\n│ └── index.js\n├── static\n│ └── img\n├── docusaurus.config.js\n├── package.json\n├── README.md\n├── sidebars.js\n└── yarn.lock\n\n\n/blog/:包含博客的 Markdown 文件。\n\n\n/docs/:包含文档的 Markdown 文件。\n\n\n/src/:如页面或自定义 React 组件一类的非文档文件。\n\n/src/pages - 所有放在此目录中的 JSX/TSX/MDX 文件都会被转换成网站页面。\n\n\n\n/static/ - 静态目录。\n\n\n/docusaurus.config.js - 站点配置文件。\n\n\n/package.json - Docusaurus 网站是一个 React 应用。 你可以安装并使用任何 npm 包。\n\n\n/sidebars.js - 由文档使用,用于指定侧边栏中的文档顺序。\n\n\n运行网站\ncd my-website\nnpm run start\n默认情况下浏览器会自动打开 http://localhost:3000 的新窗口。\n\n项目构建\nnpm run build\n网站内容会被生成在 /build 目录中,随后可以被上传到 GitHub Pages、Vercel、Netlify 等静态网页托管服务。\n配置\n配置文件为项目目录下 docusaurus.config.js配置字段官方文档点击打开。\n一定要参考官方文档因为项目组贡献者有一位厉害的中国大学生所以中文文档更新很及时。\n设置中文\ndocusaurus.config.js 中找到 i18n 配置节点,如下是原配置(其实看得懂英文就知道咋改 🤣):\n// Even if you don't use internalization, you can use this field to set useful\n// metadata like html lang. For example, if your site is Chinese, you may want\n// to replace "en" with "zh-Hans".\ni18n: {\n defaultLocale: 'en',\n locales: ['en'],\n},\n修改为如下配置设置为中文\ni18n: {\n defaultLocale: "zh-Hans",\n locales: ["zh-Hans"],\n},\n搜索\n在使用官方插件中 Algolia DocSearch 搜索时候,会有几率踩坑,可以参考我的部署经验。\n\n正确启用 sitemap 插件参考文档sitemap 插件。\n正确启用 Algolia DocSearch 插件参考文档Algolia DocSearch 插件。\n构建项目确认插件是否显示。\n\n注册账号\n在 Algolia官网 注册账号后,打开控制台新建数据源,填写数据名(后面会用到),并选择免费计划。\n\n\n获取 API Keys\n控制台打开设置页面点击 API keys拷贝 Application ID、Search-Only API Key、Admin API Key。\n\n\n配置 Docusaurus\n打开项目配置文件 docusaurus.config.js填写如下配置\nmodule.exports = {\n // ...\n themeConfig: {\n // ...\n\talgolia: {\n\t\tapiKey: "Search-Only API Key",\n\t\tappId: "Application ID",\n\t\tindexName: "数据源名称",\n\t},\n }\n}\n推送数据\n由于 Algolia 限制开源项目才可以免费试用爬虫,所以我们要自己推送数据。需要如下环境:\n\nDocker谷歌一堆安装教程\njq使用包管理器直接安装\n\n环境安装好以后按照如下步骤操作\n\n新建 .env 文件(键值不带双引号)\n\nAPPLICATION_ID=Application ID\nAPI_KEY=Admin API Key\n\n新建 docsearch.json爬虫配置文件\n\n{\n "index_name": "wiki",\n "start_urls": [\n "wiki.7wate.com/"\t\t\t\t\t# wiki 网址\n ],\n "sitemap_urls": [\n "wiki.7wate.com/sitemap.xml"\t\t# sitemap.xml 地址\n ],\n "stop_urls": [\n "/search",\n "/v3me",\n "/playground",\n "/inspector"\n ],\n "sitemap_alternate_links": true,\n "selectors": {\n "lvl0": {\n "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",\n "type": "xpath",\n "global": true,\n "default_value": "Documentation"\n },\n "lvl1": "header h1",\n "lvl2": "article h2",\n "lvl3": "article h3",\n "lvl4": "article h4",\n "lvl5": "article h5, article td:first-child",\n "lvl6": "article h6",\n "text": "article p, article li, article td:last-child"\n },\n "strip_chars": " .,;:#",\n "custom_settings": {\n "separatorsToIndex": "_",\n "attributesForFaceting": [\n "language",\n "version",\n "type",\n "docusaurus_tag"\n ],\n "attributesToRetrieve": [\n "hierarchy",\n "content",\n "anchor",\n "url",\n "url_without_anchor",\n "type"\n ]\n },\n "js_render": true,\n "nb_hits": 856\n}\n\n运行 Docker\n\ndocker run -it --env-file=.env -e "CONFIG=$(cat docsearch.json | jq -r tostring)" algolia/docsearch-scraper\n\n如果数据抓取异常推送到 algolia 的索引条目过少。可以尝试多次运行 Docker即可解决。至于为什么我也不知道反正就能搞定 ~\n总结\n如果想要稳定运行项目请务必一定仔细阅读官方文档。官方文档维护的相当好主要就是 algolia 搜索哪里,刚开始很容易无从下手……\n因为被 Docusaurus 官方 Showcase 收录了,所以产出一篇文章推广一下 ~\n更多优秀 Docusaurus 站点请访问:展示站点"},"Personal/Blog/2022/关于感情的事情":{"title":"关于感情的事情","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"抖音最近新东方甄选流量火爆,被动接收了这份热点。其中也真的被董宇辉聊到初恋时的这段话触动了……\n\n当时我一直觉得肯定是因为我没有钱才给两个人平添了那么多的痛苦。其实我后来觉得不一定、不一定可能那刻我既没有钱也没有其他的东西。\n那时候我也没有丰富的思想也没有深刻的智慧也没有跟别人交流时候体现出一种让人舒服的态度什么都没有。\n现在我再看自己当时就像一个摆烂的青年一样什么都没有。却要求这世界一如既往的包容我却要求身边的人照单接受地去接纳我。\n只要他们不愿意我就说是他们不好。\n指责多容易呀我们都喜欢做容易地事情就是职责别人对吧\n现在觉得其实可能当时并不是因为我没钱因为好多年后你还是没钱所以可能跟钱地关系不大。\n你即给不了生活上的安全感其实很多时候你也给不了精神上的陪伴。你不够有吸引力、你没有什么美丽坦诚来说因为你读了足够多的爱情故事所以你就会发现其实幸福的爱情里头金钱不是最重要的。它可以是因素之一但它不是唯一。它是之一它不是唯一。\n我们都喜欢一个非常健全完美的人不能把爱情等于金钱所以后来我就懂了……\n\n还有最近我接触到身边朋友的两个故事关于感情的大致如下\n\n朋友 A\n背景A 年少辍学跟随父亲多年打拼又恰逢家里拆迁随后父母包办婚姻孕育两子A 的妻子主职家庭夫妇,其姐姐曾多次再婚。\n离婚原因不清楚婚姻期间家庭矛盾不断。听来 A 说来得知主要原因是妻子太过悠闲,加上其姐姐的影响。在一次争吵下,一气之下签了离婚合同。\n合同内容大致如下A 获得儿子抚养权女方获得女儿抚养权。A 一次性赋予 18.8w 抚养费 + 108 平房产,并由女方承担所有抚养权,无探视无任何联系(合同暂未履行)。\n当时 A 以为是开玩笑了,觉得还会复合再加上法盲,觉得无所谓……女方因为其姐姐“经验丰富”所以可以理解为有备而来。\n\nA 离婚后一个月认识现任妻子(无婚姻历史)并怀孕,期间曾想过打掉,但是女方坚持留下。\n\nA 被前妻起诉期间没能藏住被现任妻子发现。现任妻随有想法打掉孩子但是客观原因无法打掉。A 的离婚官司被法院要求一个月内履行A 无可奈何。现任妻子家人也是拒绝接受 A ……\nA 一直很苦闷,后来也未去了解更多。\n\n分享这个故事不是背后讨论朋友的选择只是坚定的认为感情上的事情务必一定善始善终处理好自己干干净净的去迎接下一份感情。\n\n朋友 B\n背景酒局上认识朋友的朋友无过多了解单方面倾听得来的。\nB 和妻子从男女朋友开始就比较坎坷,双方出身都挺贫困,后努力努力再努力终于走进婚姻的殿堂。\n由于物质基础并不好B 极度的想要给妻子更好的生活,期间尝试创业和不断换工作。但是生活依旧不如所愿,将生活推向了更低谷。\nB 和妻子面对这生活的不如意,就如一句话:夫妻本是同林鸟、大难临头各自飞。随后 B 和妻子争夺孩子抚养权,打了 3 年官司,都已经麻木了……\nB 说:我努力为了这个家,是为了追求我想要的生活,她陪着我奋斗也是为了想要的生活。但是生活越过越不如意,人总不能在一颗树上吊死呀。\n但是我生活已经破灭了活着感受不到希望只剩下眼前的这两个孩子。也许真是贫贱夫妻百事衰……\n\n当代大家都有追求幸福生活的方式你不能祈求的另一半陪你一起奋斗就如你不能否定女方要车子、要房子是不对的。没有物质基础的感情就是一盘散沙柴米油盐酱醋茶更会抹去鲜花的浪漫。\n十字路口相遇谁也不能保证下个十字路口是否会分开但是如果当下我还牵着你的手的话那就好好珍惜在一起的时光。\n相遇不容易、相守更难。物质基础很重要精神富足也少不了。丰富自己的思想并去拥有深刻的智慧学会热爱生活并为之奋斗。但不要委屈求全更不要弄丢自己。一份感情不快乐、甚至不幸福的话那她一定不适合你。\n要拿得起放得下学会爱自己再去爱她人。新事物必将取代旧事物我们终将拥有幸福生活。\n来日方长 i💕"},"Personal/Blog/2022/关于花":{"title":"关于花","links":[],"tags":["生活/园艺","博客/原创"],"content":"春天来了,在万物复苏的季节,空气中到处弥漫着荷尔蒙的气息!跑偏了跑偏了哈哈哈 ~ 春天来了,种些花花草草也是甚好。周末闲来无事,便去花卉市场闲逛乱吃哈哈\n乱逛\n我也不知道到底要买什么栀子花月季等等就是闲逛随眼缘。\n花卉市场一逢周末便是人山人海的由于靠近大学城小情侣也是不少耶。\n想买一些小鱼实在是太小巧可爱了不过感觉买回来可能就是为了让它尽快升天……\n最后还是决定买一些净化空气带有香味的花顺带买了几个小摆件 ~\n中途买了根烤肠再来个冰淇淋真 TM 的贵……\n不花钱的快乐精神疲惫花钱的快乐精神难受哈哈哈。\n最后买了月季桂、文竹、一个不知名的摆件、一个多肉共花费 100 🤑。\n上次春节前买的花我妈美名其曰为了让它来年活得更好来了个光头行动。果不其然活得很好就是花说下辈子不要这样了……\n我最喜欢餐桌的那个干花和小小的一只多肉不过室内放桂花是真的好香啊 ~\n那两个摆件我觉得也很不错 😏。\n\n花\n\n\n\n\n"},"Personal/Blog/2022/关于郑州的互联网记忆":{"title":"关于郑州的互联网记忆","links":[],"tags":["记忆/郑州","博客/原创"],"content":"好在互联网是有记忆的,简单记录一下关于郑州的互联网记忆。本打算附录一些相关视频,不作死了,更不发表任何评论了。河南明明是一望无际的平原,却有着一座座无法逾越的高山。\n郑州 7·20 洪水\n\n\n地铁 5 号线溺亡\n\n\n京广路隧道全线淹没\n\n\n郑州烂尾楼\n\n全国第一\n\n郑州 120 接线员\n\n导致河大学生无法及时救治死亡\n\n河南村镇银行暴雷\n\n\n储户赋红码\n\n\n暴力冲突\n\n\n郑州富士康\n\n\n万人徒步回家\n\n\n强制招工\n\n\n暴力冲突\n\n\n郑州疫情\n\n\n表演式解封\n\n\n全国文物二沙方舱改造\n\n\n刘书记错过女儿成人礼\n\n\n郑州大雾\n\n黄河大桥 400 车相撞\n"},"Personal/Blog/2022/再游嵩山":{"title":"再游嵩山","links":[],"tags":["游记/嵩山","摄影/作品","博客/原创"],"content":"冲冲冲,我觉得还是很有必要再次记录一下。为何是再游嵩山,因为我爬了两次,不过每次都会有不一样的感触。\n说真的这次原本我不是太想爬嵩山。\n因为爬嵩山是真的很痛苦这种痛苦不同于泰山的痛苦一路上零零散散的游客景区开发也很差劲更提不上美如画的景色。但是为了星空银河还有露营最终还是决定去嵩山积累经验争取为下次银河之旅做好铺垫。\n前阵子天天吹泡泡今天拍星轨明天拍银河却始终停留在嘴上哈哈。周三的时候一看天气还不错其实天气很差然后拍板这周说啥也得去嵩山露营。\n为啥子去爬嵩山\n我们的目标是为了四、五月份的银河季做准备主要想法还是提前积累经验免得到银河季了搞个措手不及什么也没拍到最后定的方向是决定中午登山主要拍日落银河日出。\n回来后才想起来前半夜还可以拍星轨可真是个呆瓜……\n主要还是前半夜给我冻的帐篷尺寸还虚标我根本就伸不开腿无良商家请原地升天\n过程是美好的\n就这前半夜还给我激动的睡不着其实我也真的不知道为啥睡不着哈哈。\n郑州至登封仅一个小时的路程很快就到了嵩山脚下。简单吃了点那个酸汤小酥肉是真的好好吃。个人建议登山尽量吃一些带汤汤水水的主食这样登山过程中会比较舒服。\n\n因为这次登山要露营所以装备巨多我们俩的负重足足有近 60 斤。出发前的准备具体如下:\n\n我们带的东西实在是太多了也太重了。本来是超级累并且无敌折磨的一路。\n但是碰见了一个小女孩超级活泼并且很讨人喜爱。然后一路就变得开心、快乐许多回想起来感觉还是一路结伴而行登山这段过程才是最快乐的 ~\n从 12 点爬到 4 点才接近登顶,马上登顶的时候支起了凳子让小女孩休息了一会。小女孩一路上都在激励(要是我理解,这就是吐槽哈哈哈)我朋友,给他累的呀。小女孩还时不时的帮忙提东西,边爬边说:\n\n叔叔你快点呗 ~\n叔叔你不行呀 ~\n走咱俩不管他了\n那个叔叔已经丢了\n走走走不要他了\n\n哈哈哈甚是欢乐 ~\n只记得小女孩妈妈吐槽说\n\n唉迟早被拐走。\n女儿你怎么不帮妈妈拿东西呀\n\n说起来也是就刚认识小女孩便对我们如此之放心与信任。世界上最可爱的果然是人类幼崽\n\n\n现实是残酷的\n小女孩很想和我们一块看银河、云海并且想和我们一块露营。可是实际情况并不允许最后恋恋不舍的帮我们支起帐篷便下山了。不过最后答应拍到的照片分享给她 ~\n一切安顿好都五点多了马上日落了。不过云雾太多并不抱有过高的期望。其实像日落日出银河这种延时一类的支起来相机就没有一点事了。\n到点了俺俩也都要饿死了自热小火锅和红酒搞起来 ~\n\n\n我带了红酒独自喝个微醺。便一直坐着慢慢等月升人生嘛不过如此。\n不过我朋友很无趣这大好山河不来享受视觉盛宴就只知道睡觉。他一整晚都是这样到点了支起来相机设置好就滚回帐篷了。\n我便独自做到十点左右感觉已经有点微微醉了回去睡觉 ~\n还不如不睡睡的巨 TM 痛苦。主要前半夜又下雨了,没有带睡袋,就很冷。然后帐篷尺寸还虚表,我只能蜷缩着腿,完全是在受罪!😭\n念念不忘的银河\n一点多都睡不着了便想着起来坐坐。天气预报显示有雨云层高度也是近万米所以期望并不高。\n风光摄影师果然是靠老天爷吃饭的唉 😔\n可是挡不住我是欧皇哈哈哈拉开帐篷那刻漫天繁星震撼到我了。马上便拍醒我朋友睡个屁呀睡起来拍银河。\n由于那天有雾月亮产生了很独特的光环。\n\n运气是真 TM 的好,还遇见了流星!!!看,这就是银河!!!\n\n这是我第一次看见银河不过除了流星并不震撼。就是这个银河只能在相机里看见因为光污染太严重能见度太差。所以就很拉跨……\n一直心心念念能和爱人拥在银河下看一场流星雨 ~\n回首往事\n后半夜也睡不着自己就坐在椅子上葛优躺仰望星空。\n第一次登嵩山到如今真的给我留下了太多太多太多的回忆了满满一大箩筐。放电影一般回忆着所有的事情心酸和痛楚一瞬间就涌上头忍不住就哭了反正没人看得到哭的是真 TM 的爽。\n偷一句电影台词戏精一下。\n五年你知道我这五年怎么过的么你挑的嘛偶像\n下山回家\n日落和日出太拉跨了云海也一般般……\n不是我挑剔是因为我见的云海日出太多了哈哈哈有点凡尔赛。\n说实话写的好敷衍不过照片已经洗过啦接下来就是分享照片的时候了 ~\n\n\n\n\n\n"},"Personal/Blog/2022/写十万字的博客是一种什么感觉":{"title":"写十万字的博客是一种什么感觉","links":[],"tags":["生活/日记","博客/原创"],"content":"年初的时候就粗略统计了一下,快要突破十万字了。还想着十万字的时候浪漫一下子 ~ 但是现在也没有太大的感觉。在我求学期间我很烦写文章的,基本就是最低分和极少数情况下的近满分,想不到运营博客这第五个年头也是破十万字了。\n\n统计可能有出入吧但是因为一些事自己也删了好多文章。十万字是一定有的\n希望在投胎之前突破一百万字哈哈哈"},"Personal/Blog/2022/写博客的正确姿势---先行版":{"title":"写博客的正确姿势 - 先行版","links":[],"tags":["写作/技巧","博客/原创"],"content":"依稀记得当初定下的目标,月更博客哈哈哈。不过这几年来陆陆续续只断了一次,想不起来那次断更的原因了。这次好久没更新,其实是在憋大招。\n从 18 年正式运营博客开始,时至今日马上迎来第五个年头。无论是技术还是运营都有了长足的进步,不过我还是苦博客久矣……\n\n每次必须要正襟危坐地坐在电脑前才可以输出。\n偶尔闪现的灵感纵使通过笔记软件记下后来也是只记得这个灵感的名字了。\n周末了我更是不想打开电脑再打开 Typora 写文章。\n如果因为一些事情我没有办法使用电脑那完了更不用提了。\n虽然我是运维但是我不喜欢博客宕机……\n\n综合以上痛点还有我那舍弃不掉的老友们所以憋大招研究姿势最重要\n不过综上所述一定会有人问为什么不用第三方客户端为什么不写手机上为什么不开发个小程序……\n我不想回答我只想说这不是懒这是极简专注生活因为不想浪费自己的一丝一毫精力哈哈哈。\n目前已经出关了具体实现方式待我娓娓道来。当下还是先说博客的事情哈哈哈。\n草稿箱\n\n这个年纪\n遗憾最小化框架 —— 如何做决定\n1000 天计划\n如何纯粹地活在当下\n一命二运三风水\n天时地利人和\n是非对错\n生活导向\n如何拍好一张照片这个已经鸽了一年……不两年了\n还有读书笔记 😭\n\n现在是只记得题目了少部分还记得灵感也不是输出这些文章对我来说很难就是单纯姿势不对。\n日后慢慢补上把毕竟来日方长"},"Personal/Blog/2022/写博客的正确姿势---测试版":{"title":"写博客的正确姿势 - 测试版","links":[],"tags":["写作/技巧","博客/原创"],"content":"上文说到《如何写博客的正确姿势 - 先行版》,今天继续测试版,顾名思义测试版就是想听听各位的意见,避免个人闭门造车,同时进一步改造提升。\n我平时不仅仅写文章还会写技术类博客。但是我一般不会把技术类博客放在 blog 上,因为我觉得如果什么都往博客上放的话,过于混乱而且也不是我的风格,所以我只在 blog 上写日常文章,在 wiki 上写综合体。\n关于 Blog\nblog 是我最早的出发点,也是我与互联网上的博友最紧密的联系点。因为我热爱它,所以更不想去折腾来蒸腾去让它满足我各种奇奇怪怪的要求。\nblog 目前采用 halo 搭建,跑在了 docker 上,现在主要负责日常的文章输出、摄影展示、书写日志这三个方面。\n\n摄影页面\n日志页面\n\n摄影和日志页面已经停滞好久了疫情原因今年没咋出去拍照片日志则用了另一种方式故弃用。\n关于 Wiki\n因为工作原因学习原因所以我平时需要涉及技术方面要学习新技术涉猎新知识写到本本上又不方便检索放在第三方平台上又不放心而且没有办法 web 展示和交流。\n虽然博客时而写得多写得少但是 wiki 则是一直输出,今年截至目前为止输出了 150 篇左右技术笔记30 万字左右。\n\nwiki 页面\n\n关于日志\n为什么要把日志单独拿出来谈呢请慢慢看。\n\n上图是我采用 Nextcloud 搭建的一套属于自己的生产力工具,它是我目前工作、学习的核心要素。\n\n仪表每日一目了然的知道需要处理的事情很方便很直观。\n文件负责 Linux、Win、Android 之间的工作文件同步及备份。\n照片负责平时摄影的分类、归档、备份。\n邮件7wate.com 域名邮箱,平时基本只在这里处理邮件。\n联系人目前用得比较少虽然国内也不怎么喜欢用邮件沟通交流但是我是很喜欢邮件的 ~\n日历 + 任务:目前工作、学习中的规划以及代办都基于这两个实现,贼好用哦 ~\n新闻Rss 阅读器。基于我又自建了 RssHub同时又是 RssHub 贡献者,所以想看什么自己写个爬虫就好,不会有任何的广告啊,乱七八糟的,是目前 90% 以上的信息来源。\n\n虽然这套生产力工作目前被我打磨的得心应手但是每日复盘及工作记录有点不爽。关于每日复盘和工作记录我就想咋简单咋来也不想草草两句话就发在博客上。直至看到了可爱的 DIYgod的 《基于 Obsidian 的生活记录系统》,瞬间来了灵感。\n我是怎么解决这些痛点的\n还记得上篇我说的那些痛点么\n\n\n每次必须要正襟危坐地坐在电脑前才可以输出。\n偶尔闪现的灵感纵使通过笔记软件记下后来也是只记得这个灵感的名字了。\n周末了我更是不想打开电脑再打开 Typora 写文章。\n如果因为一些事情我没有办法使用电脑那完了更不用提了。\n虽然我是运维但是我不喜欢博客宕机……\n\n\n再加上刚才所描述的痛点\n\n\n想保持 blog 和 wiki 的独立性。\n想持续产出博客不想放鸽子 🙄。\n寻求一个好用的日志记录。\n\n\n基于综上所述目前采用了 Obsidian + Docusaurus + Git 交叉融合起来的、我认为及其强大、完美、贴合我个人的超级小怪兽 ~\n奥里给 🥳🥳🥳\n1. 每次必须要正襟危坐地坐在电脑前才可以输出\nObsidian 拥有全平台客户端,而且保持界面一致性。所以彻彻底底解决了这个问题,我工作用桌面端,下班用手机端。吃饭也能写,被窝也能写,甚至 💩 也能写!!!\n2. 偶尔闪现的灵感纵使通过笔记软件记下后来也是只记得这个灵感的名字了\n关于碎片化的知识目前还在探索不过已经有对应的生产工具了体验了一下还不错先留坑日后再填。\n3. 周末了,我更是不想打开电脑,再打开 Typora 写文章\n因为我只爱 MarkDown 格式,所以虽然手机能打开网页版 blog但是这感觉太难受了……\n坚决不为工具服务\n4. 如果因为一些事情,长时间没有办法使用电脑,那完了更不用提了\n请看上一条 ~\n5. 虽然我是运维,但是我真不喜欢博客宕机……\n我之前特别喜欢折腾大言不惭的说我的博客跑在百万架构上哈哈哈哈哈哈哈哈哈哈哈哈 🤣。\n因为我也不喜欢宕机和折腾所以静态网页是最好的选择。不过静态博客有好多让人无法忍受的缺点好不好还好都已经统统搞定🥱\nObsidian + Docusaurus 已经决定 wiki 只能采用静态网页方式实现的了。接着我采用了版本控制、分支合并、持续构建、持续部署这套比较成熟的 IT 生产流程。\n\n\n日常采用 Obsidian 进行所有技术类、非技术类、工作日志的写作输出,同时采用 Git 进行版本控制。\n\n\n通过使用 Git 作为版本控制利用分支功能目前衍生出四个分支master、dev、pc、pp 分支。\n\nmaster 分支:发布分支,平时 wiki 的 web 版本由此构造。\ndev 分支:测试分支,进行 pc、pp 分支的日常合并wiki 预览版基于此构造。\npc 分支:桌面端分支,主要使用 Windows + Linux 进行写作。\npp 分支:移动端,主要使用 Android 进行写作,使用 MGit 进行同步。\n\n\n\n日常多分支并行前进每周日早上 2 点dev 分支会自动对 pc&pp 分支进行快进合并。同时构建 dev 预览测试版,构建成功后对网站进行测试并报告。\n\n\n如果 dev 合并产生冲突、或构建失败,则会提醒我进行手动合并。如果我不主动打断合并,就等待执行下一步。\n\n\n最后周一早上 2 点 master 分支将会快进合并 dev 分支,自动进行网站构建并且刷新 CDN。\n\n\n综上所述我利用上述工具 + 流程就可以全平台、全天候、进行持续高效的产出了。虽然有折腾的嫌疑,但是绝对不瞎折腾。\n这套具有高通用、高效率、高容错的特定让我可以无惧任何服务器的维护、忒涩社徽的封禁、随时随地的书写发布了。\n\n6.想保持 Blog 和 Wiki 各自的独立性\n因为 wiki 承载着我所有的知识笔记、文章、日志记录,所以我就可以像挑衣服一样选择写好的文章,记录好的日志,稍加修改就可以输出到 blog。\n主要我越来越不喜欢在 blog 上写技术文章了,感觉是 ONO 影响的,打钱!🤯\n这样就满足我对博客独立性的要求了 ~\n7.寻求一个好用的日志记录\n好了我又来激动的 BB 了哈哈。\n还记得小时候写流水账日记今天天气巴拉巴拉干了啥巴拉巴拉但是现在我就想这样写日志因为我喜欢哈哈哈。\n\n\n在 Obsidian 下,我利用第三方 Templater 插件快速生成子弹笔记。这是真的好用,我都激动哭了 😭。\n在右侧日历页面点击周数就可以快速生成周报点击日期则可以快速生成日报。利用模板工具就可以快速生成今日信息今日诗词、今日摄影作品。\n然后可以记录一下今天完成的 Todo List最后再说一些有的没的总之很香哦 ~\n就是这个 Templater 插件,我还可以快速生成博客、技术笔记。\n最后最后\n打磨这套工具费了我不少心思第一要性还是为了让我更好的书写博客。也许你会觉得改变一下我的习惯会有更多比这简单的方式不至于这么繁琐。\n但是我认为这些工具都是要为我所用的就如我觉扫地机器人它就应该自己学会倒垃圾、换水、充电否则他就不是一个合格的机器人。我要坚持拥有自己的个性和适合自己的生活方式。\n感谢你看到最后 😏,看都看完了,提个建议再走呗 ~"},"Personal/Blog/2022/原点":{"title":"原点","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"记录一下自己的状态,也发发牢骚……\n工作\n2021 年 3 月 5 日是我拥有第一份很正式的工作,很幸运也很开心呀。一路走过来不容易 ~\n当时找到这份工作真得激动的要哭了……离家超级近仅 10 分钟的路程。而且公司很正规:五天八小时、双休、法定节假日年假、从不加班!\n薪资的话平均每个月到手 3500 左右,年末刚谈了绩效🤩,新的一年到手应该是 4000 左右。加班双倍工资可以摸到 4500 的屁股了。正常满勤是 14 薪,上半年请了好多好多的假期,所以今年 13 薪😭。公司管吃管住省了好多好多好多😛\n过完假期有很多新项目会上线应该会忙一阵子不过平时是真得很划水 ~\n唯一的缺点就是没有发展潜力部门的老同事很多大家都是一个萝卜一个坑很少很少裁员所以就需要熬 si 同事才有晋升机会。😫\n新的一年好好工作努力学习\n爱好\n今年新增了两个爱好摄影和钢琴摄影是一直都在拍拍拍钢琴倒是学习的少。不过好喜欢钢琴曲超级解压\n今年趁周末好好把郑州转转再学习学习 PR、PS 尝试一下自媒体。\n趁年轻多做加法搞不动了再说\n生活\n感觉跟自己的朋友特别是结完婚成家立业的朋友似乎是越来越远了……\n没有办法呀人家孩子都多大了自己还在这挂着嘞……\n就感觉大家已经不是在一个圈子里了而且产生了一次最奇葩的矛盾更颠覆了我的认知……\n事情是这样的\n朋友 A 喊我吃饭,朋友 B 去了C 是后来去的。我和 A、B 的关系比较好,然后呢 B 平时经常找我买药我在医药行业工作买药比较实惠。我就聊起来说可以尝试刷社保并买一些小额度的保险这样下来一年也能省不少钱你也不用那么累了。B 说不太懂,我就深入讲了几句。\nC 这时候听着感觉不爽,说大过年提这丧气的事情。然后呢,我听出来他的意思了。我也想我表达方式可能有问题,毕竟大家都不想生病。我赔了不是,说没注意场合很抱歉哈。\n然后呢C 蹬鼻子上脸,我也没啥说的了,丢下一句话:兄弟实在是佩服。便走了……\n事后 A、B 并不觉得 C 很过分,只是说 C 喝了酒别往心里去。我也知道我说话方式可能不妥,大家并接受不了这样的方式。\n我的出发点在于 B 是从事体力劳动,无五险一金和商业保险,平时医药支出也大,我作为好朋友想替他省点钱。大家觉得我可能在丧人家的气,然后我就觉得大家好像已经不是一个圈子的人了……\n事后我也反思了一下我说话场合不太合适但是我出发点没错不过以后还是尽量少说点……\n感情\n客观的来说我不是在恋爱就是在恋爱的路上……\n以前也是好不懂事总是很喜欢恋爱带来的热闹感呵护感和安全感。也不知道自己究竟为什么这样而且每一段感情都很不愉快……\n认真的来说我想结婚、想成家似乎都是因为小时候家里的琐碎带来的阴影自己也不知道如何正确的处理和消化。企图通过恋爱来修复这块伤痕所以就超级想成家结婚似乎结婚就可以解决这所有的问题。\n然而呢并不是这样的稚嫩的时候无法正确的认知和辨别事务的对错还带着些许的迷信偏执自以为是。\n没有领路人没有伯乐似乎就在这条路上错的越来越远了。\n上一次很痛的恋爱后家里的催婚各个方面又开始了一段新的感情。似乎问题解决了似乎也在重蹈覆辙。现如今这段感情也到此结束了今年确确实实成长成熟了很多由内而外的成长。也能去看清事物本质结合客观实际去做选择。\n现在对我来说稳定的工作、稳定的生活、稳定的情绪都是非常重要的而且是及其重要的虽然还带着些历史包袱。但是质变需要一个过程最后也会带来一个结果。\n去年一年都在努力向前看今年依旧要努力向前看。\n过去的很多事情都无法弥补有时候也会困扰着我。再次真诚的希望伤害过我的和我伤害过的人大家都可以过的很好越来越好。\n父母\n老爸老妈还是那个样子咯自己需要调整好自己啦。父母也很在乎自己的孩子只是生活、环境造就成了这个样子。希望自己能更好的处理好家庭、父母的关系\n老姐\n在老姐这似乎都是个不懂事的孩子伴着成长。以后自己多加把劲努力生活也替老姐愤愤忧\n新年快乐\n看到这了你也很有耐心哈哈。愿不开心和不愉快都离我们而去幸福哈🥰"},"Personal/Blog/2022/如何免费获得-Jetbrains-正版授权":{"title":"如何免费获得 Jetbrains 正版授权","links":[],"tags":["生产力工具/Jetbrains","博客/原创"],"content":"最近 Jetbrains 的授权又到期了,之前有些写过相关的文章。但是那时候没有加入到相关的博客订阅,阅读量也不大。现在有一定的阅读量了,便想再次分享给大家如何免费获得个人正版授权。\n关于授权模式\nJetbrains 主要面对用户为个人和组织,官方其实对于个人授权还是比较暧昧的,主要收入还是靠组织。\n在此可以很明确的告诉各位如果你所在组织使用 Jetbrains 系列工具做开发,但 Jetbrains 授权并不是组织为你购买支付并授权的,而是通过其他渠道(包括个人购买等等)授权的,都可以理解为非法授权用户。\n不过国内版权意识原谅我多 BB 了。今天最核心的事情还是免费哈哈哈\n准备工作\n官方提供了很多特惠方式在此我只阐述门槛最低的一种方式——开源项目。\n官方的条件要求是\n\n了解 开源 定义。\n正在积极开发例如在过去 3 个月内定期提交新代码。\n不提供开源软件的付费版本也不提供与开源项目相关的任何商业服务例如付费支持、咨询等。\n未获得商业公司或组织NGO、教育、研究或政府组织的资助。\n不为他们的核心项目开发者支付工资。\n\n对于白嫖最重要的事情其实只有在过去 3 个月内定期提交新代码,项目拥有开源协议。\n我多次的经验发现可以很明确的告知各位。Jetbrains 并不注重你的开源质量和影响力,只要你满足上述加重字体的条件,放心大胆的申请即可。\n你在这可能有疑问了还要等三个月嘛。你的小脑袋瓜那么聪明我相信你可以时光逆流嘿嘿。\n申请表单\n\n注册 Jetbrains 官方账户\n符合要求的开源项目\n打开 申请网址 填写表单\n等待邮件授权激活\n\n如果超过七天未收到授权邮件可以邮件联系官方由于时差原因所以不要着急。官方不会磨磨唧唧一般直接就给了\n\n授权书\n\n官方授权的仪式感满满的 ~\n有什么疑问可以下方留言为各位解答 ~"},"Personal/Blog/2022/我是关系户":{"title":"我是关系户","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"我最近加了一个《低调务实优秀中国好青年》微信群,其是 Github 上一位开源作者《阿里巴巴·冴羽》创建的。当然不是靠关系户才可以进这个群,只是因为一件事引发了这个思考。\n在一个周末闲来无事收拾书柜整理出来几本闲置的书籍。思来想去不知道如何处理不想送到回收站因为那样我觉得知识被埋没了所以便想着送人好了。\n在群里发布了这个消息后马上就有好几个群友加我微信预定书籍。直到最后共 3 位朋友预定了 8 本书籍,随后我就在周日下午寄出了。对于我来说这件事情并不奢求任何回报,也不希望谁感激我,我只是想让这几本书继续“活下去”。\n但是后续发生的事情很有意思其中一位朋友非常有礼貌从始至终你都能感受到尊敬与感恩另外两位朋友也是感谢至极但是远没有那位朋友“更礼貌”。最后收到货后那位朋友更是如获至宝似的发朋友圈言谢这是令我没有想到的。\n首先澄清一点我与他们并无任何利益相关更是非亲非故。仅是缘分把我们送到了一起。那么借这件事延伸出一个问题如果面临三选一的升职问题加上这个事情作为既定前提的情况下你会做出更加理智公平的选择么\n也需这个问题有些不成熟但是如果还是这三个人其中一个 A 技术、管理能力都不错,但是脾气臭,爱骂人。其余两个都不如他,你会怎么做抉择?抽丝剥茧出来就是一个问题:面临问题时,你到底是在凭借理智做选择,还是情感?喜好?\n不要下意识理智了完全不可能因为我们没有办法完全剥离情感喜好去做选择所以我们会去均衡利弊尝试做出最优选择做出你能获得最大利益的选择。\n\n我们无法做到理智选择只能尽力尝试去做出最优解。\n\n基于这个结论下关系户也只是其一撮表现形式钱权交易更是必然存在的。不过谈论这些对我们来说太遥远了。"},"Personal/Blog/2022/我要拔智齿!!!":{"title":"我要拔智齿!!!","links":[],"tags":["生活/随笔","博客/原创"],"content":"啊啊啊、莫名其妙的智齿引起了牙周炎……\n起因\n前几天都有点炎症不过没太注意……\n今天一天心情被这个智齿搞得痛不欲生还导致了吞咽也很痛张嘴都有些困难。\n依稀记得去年体检的时候医生都说智齿可能有点问题需要注意一下……\n还好有药吃了点甲硝锉立帖为证灭了智齿全家啊啊啊······\n😭😭😭\n三月二十五\n吃了药感觉可能会好一点但是一阵一阵的。\n到家还是给我疼的嗷嗷叫吃了药躺床。\n然后就从 7 点躺到凌晨 5 点,我觉得痛的处于半昏迷状态(又瞌睡又痛的睡不着)\n拿了好几个雪糕放在脸颊上冰的都没有知觉了······\n三月二十六\n本来是没有打算今天拔牙的只是想着去看看。\n到了医院后医生说没问题可以直接拔。风风火火拍了片然后开始拔牙。\n我的牙长的巨整齐医生都说是不是做了矫正。而且没有网上那种什么阻生齿呀更没有很奇怪的样子最长牙根 28 mm都很乖巧。\n打了麻药有点痛和木拔牙还好来了一群实习生观摩……\n拔牙痛感约为指尖采血的 1/2麻药劲过后痛感为 1/10可以理解并不痛只是麻药劲比较不舒服。\n不过牙痛的感觉有指尖采血的 3 - 5 倍,真的是巨痛苦(痛感时间巨长!!!)\n为什么没有照片因为我全程懵逼状态、等待接受痛苦……\n\n拔完牙下午去看机车了然后傍晚回家家被抄了……\n离家 100 米确诊一例来自上海的司机,我还是灰溜溜的回公司吧 ~"},"Personal/Blog/2022/数字文化遗产":{"title":"数字文化遗产","links":[],"tags":["开源项目/数字文化遗产","博客/原创"],"content":"当下随着工业社会的进步和发展,让我们拥有了丰富多彩的生活方式。书写博客便是其中之一,但博客作为个体的文化资产,百年之后又该何去何从呢?\n2001 年中国互联网协会成立,姑且暂定个人互联网于 2002 年兴起。今年也恰好是 2022 年,个人互联网的第二十年,那么最早一批拥有个人博客的前辈目前应该也临近退休。\n接下来再过二十年、乃至再一个二十年。最早的这一批个人博客拥有者也许就要换个地方书写博客了……\n那么这些文化遗产如何传承下去呢\n下面是个人的一些想法期待能够实现的那天。\n核心思想\n数字文化遗产的核心战略从如下两个方面出发文化传承、数字化。\n文化传承\n自古以来无论是客观存在的还是口口相传的只有能被传承下来的才可以称之为文化。这个项目从实际上出发也是为了博客文化的传承和图文的记录宏观上就不吹牛皮为人类做贡献了哈哈哈。\n数字化\n数字化只是一种实现方式并不能拘泥于某一种实现方式。\n毕竟如果可以的话我觉得刻在石头上似乎更靠谱一些\n客观价值\n博客既然能作为一种无形的文化资产如何通过某种方式让博客文化资产绑定实际货币借以实现文化资产可交易那么我想它也许会吸引更多的参与者加入传承。\n例如现在的数字货币 NFT不过具体的实现细节还需要进一步论述。\n共认机制\n文化也区分优胜略汰糟糠文化注定味同嚼蜡流传不久。所以既要符合当下主流文化趋势更要尊重小众个体。我认为可以通过采用共认机制、主 / 次时间线来拥有对文化资产的民主自治权。\n例如原始创建者 7 名,只要 4 名以上同意即可纳入时间线。这并不意味着独裁,只是为了过滤无用文字。并且你也可以拥有自己的独立时间线并传承下去。\n严格意义上并不存在主次时间线谁的”生命力“更强谁即是主时间线主时间线简单来说就是当下的主流文化。\n赋予生命\n生命机制是数字文化遗产最为重要的核心机制如果文化脱离了人类个体也就不存在任何意义了。\n如果时间线上超过 144 小时未收纳新的文化,时间线即自动消亡毁灭。\n这也就是为什么在共认机制里面谁的”生命力“更强谁即是主时间线。\n技术实现\n技术实现最具争论性质了说实话我也不知道用那种方式比较好。但是既然要传承下去那么分布式是必须的。\n我觉得 git 分支的实现方式挺不错的,如何再加上区块链技术不可回写?\n不过这方面造诣太浅还是来日方长吧。\n表现形式\n现如今刻在石头上终究还是不太现实既然是数字文化遗产本质上还是要基于数字媒体来实现。\n例如 H5 网页、音视频等等……\n思维导图\n\n笔者\n仅此记录一下本人天马星空的想法不具有任何专业性的调研和科学性。\n不过我的第六感告诉我这应该会在将来某天得以实现。"},"Personal/Blog/2022/新冠笔记":{"title":"新冠笔记","links":[],"tags":["生活/随笔","博客/原创"],"content":"新冠疫情从开始的温华大革命式封禁,到现在的大跃进式解封让人直呼受不了。郑州也在封禁了近三个月经历了大大小小令人唏嘘的事情后,全国竟然直接放开了……时代的车轮碾压而过,脆弱的个体实在没有任何选择的权力。\n十月份还在封禁的时候我通过电报等多方渠道获得的信息新冠的感染在未来是必然的了最有效的准备就是买退烧片屯感冒药。然后我就通知身边的亲朋好友买药可惜没人信。最后我自己屯了点给家里人备了点。后来的后来想必各位也都经历了退烧药嘎嘎难买莲花清瘟胶囊妥妥智商税……简单记录一下我和身边人的新冠历程以及建议和未来的准备希望能对你有帮助。\n我自己\n第一天中午左右发烧到第二天早上然后就再也没有发烧。想着新冠疫情不过如此但是发烧仅仅标志着你确诊新冠了特别是当下这个时间节点发烧意味着 90% 的可能阳性。\n第三天开始水泥鼻子溺水的感觉只能通过嘴巴呼吸紧接着咳嗽流鼻子嗓子疼。第四五天明显好转感觉差不多就好了。第七天嗅觉、味觉完全消失。\n你可能感觉新冠还行但其实不然从发烧到现在半个月了我还是很虚弱嗅觉味觉也未完全恢复。从个人体验来说新冠绝对不是普通感冒也不是发烧结束就好了。\n室友 A&B&C\n第一天到第四天几乎都在反反复复的发烧都超过了 38.5°,只能通过吃布洛芬降温止痛。期间有一天室友退烧,甚至还打了一天游戏……\n退烧之后就是水泥鼻子咳嗽嗓子疼第七天左右恢复精力。后续是否虚弱也没有过多咨询。\n我和室友 7X24 小时完全呆在一块,所以对抗新冠个人免疫力还是最重要的。\n家人 A&B&C\n家里人基本上都是发烧半天后续症状较轻部分嗅觉消失。但是从发烧的第一天算起后续一定会有相对应的症状存在的例如水泥鼻子嗓子疼流鼻涕等。\n但是家里人都感觉好了之后很虚弱所得症状大致相同。主观感觉可能基因遗传的因素也有问了叔叔表哥也都症状较轻。\n总结\n新冠绝对不是普通的感冒并且从发烧第一天算起最少需要 15 天左右的时间恢复,切勿盲目自信乱得瑟!(个人主观体验)\n新冠不存在任何特效药发烧超过 38.5° 吃布洛芬类降温止痛药是最好的选择,同时多喝热水除此之外没有任何直接有效的办法。(硬抗的有效方法)\n新冠确诊 3 - 5 天反复发烧不退,建议直接去医院做肺部 CT 并且抽血化验。切勿盲目相信社区诊所,大部分社区诊所只会一味的打糖皮质激素和抗生素。(咨询过医师朋友)\n新冠退烧以后必然会迎来各种各样的后遗症因人而异。但是退烧真真真的不意味着身体好了一定要注意防护保养身体。个人主观建议\n未来的准备\n综合各种渠道可以获得的信息首先能明确的事情就是新冠管控放开很大程度是不可逆的除非那天新冠致死率提升。新冠并不是一次阳性永久抗体如果感染了毒株 A 那么并不能直接免疫毒株 B。\n新冠抗体大多 3-6 个月保持在高峰,现在是 12 月,那么就意味着明年 5-6 月份一定会再有一次感染高峰。也许是复阳,也许是感染不同的毒株。到时为了防止医疗挤兑,建议各位有机会提前备好相对应的药品。如果线性思维去考虑的话,明年 10 月份左右也会在有一次感染高峰,但未来是不可控的。\n现如今的大环境下我们也没有任何选择的权力去拒绝感染。只有平时多运动保持良好情绪多喝牛奶多吃鸡蛋开心快乐每一天才是最有效的。如果各位博友有需要布洛芬N95抗原等可以无偿友情代买。虽然不保证时刻有货但是工作原因可以第一时间一手拿货。\n如果有需要的可以直接留言或者邮箱联系我望安康"},"Personal/Blog/2022/新手村村长":{"title":"新手村村长","links":[],"tags":["工作/经验","博客/原创"],"content":"最近在带新员工,也是再记录总结一下,我们应该如何度过新手村?想想去年这个时候俺也是小白,没想到今年就开始带新员工了。内容主要偏向于技术岗位,各抒己见欢迎来怼,不说废话,赶紧上车。😏\n公司\n从公司角度来说入职后第一件事情务必先熟悉公司组织架构最好可以记忆下来。其次了解公司的主营业务及战略方向知道火车往哪开不过一般不会往家里开。🤐 如果不是管理层的话,建议不要对公司的管理文化及战略方向指指点点,其他的也没啥需要过度了解的了。\n毕竟打工人打工魂带薪拉 💩 才是你的使命。\n部门\n部门方面的话肯定得摸好你老板的屁股不然谁给你发工资但也不要当二腿子他又不是你的皇阿玛。简单来说就是熟悉领导的办事风格保守派还是改革派这点很重要自行体会自行体会 ~\n同事的话刚入职还是建议全当成路人甲、路人乙。本质上来说同事其实和你坐公交遇见的路人一样所以请勿过多加戏。基本上维持良性的部门氛围当下人情留一线日后好相见就行。\n还有就是在你熟悉公司组织架构和主营业务的基础上可以再进一步熟悉部门所负责的业务模块因为这就是你工作内容的集合基本上你的工作范畴不会超出这个集合。\n初出象牙塔的学生一定要不卑不亢耕好自己的一分田护好自己的一亩地就可以啦。\n工作\n最最最核心的事情来了工作方面主要分为五个部分办公用品、协同办公、工作内容、工作手册、日常总结。\n办公用品\n一个耐用的笔记本和黑色签字笔一定会伴随你的工作生涯所以可以买好点的。还有就是常见的移动存储U 盘啊、移动硬盘啊都可以,如果有个人电脑也可以带着,这样会更方便。\n协同办公\n这方面能说的可大了去了不过最基础的就是通讯软件了。一般了解掌握常用的几款例如企业微信、钉钉一些公司也会拥有内部专用的通讯工具会用就行。不过一般在这上边找组织架构最方便了 ~\n还有就是现在大部分公司应该都集成了单点门户系统拿小本本记下来就好。再加上企业 OA 系统,走申请啊、预留会议室啊、报销费用啊,一般都在这上面搞定。如果是做开发,还会有 git 啊等等等等等。初期建议都记在小本本上,供你方便使用。\n就如开头所说这方面太多了所以请根据实际情况来。\n工作内容\n这个最简单了哈哈哈还记得小本本嘛刚入职初期一定要有一个 ToDoList这个一定能帮上你大忙。其他的嘛回答保安大爷的问题就行你是谁到哪去\n工作手册\n初期工作内容会巨零散更无从下手。尤其是在大量阅读公司内部文档后我极其建议用笔记本写写画画因为初期一定会遵循否定之否定规律的所以用笔记本写写画画后期整理起来会很方便。\n我们在熟悉工作内容后可以尝试搭建个人文档提升自己的摸鱼水平。🐟\n日常总结\n你写日记么正经人谁 TM 写日记。\n话虽这样说不过工作日志还是需要滴该配合老板的演出你不能视而不见啊。时间地点人物、起因经过结果哈哈哈不好意思走偏了。😛\n只要前面 ToDoList 履行好,简单记录一下当天工作历程就可以啦。然后每周总结一下,月度汇报一下,毕竟你骗骗我,我哄哄你,坚持一贯的友好往来 ~\n\n如果你的工作岗位没有对公司直接产出价值那么请不要觉得你的薪水是与你产出的价值成正比的。所以在完成自己的本质工作之外偶尔来个小亮点即可。毕竟工作是为了生活生活不是为了工作。\n杜绝内卷、杜绝自杀式奉献从你我做起全世界的无产阶级联合起来世界终将属于我们。\n"},"Personal/Blog/2022/是微风、是晚霞、是来日方长":{"title":"是微风、是晚霞、是来日方长","links":[],"tags":["游记/巩义","博客/原创"],"content":"自打增加了 D 证,就没有正儿八经的骑一次摩托车,心心念念的终于在这个周末搞定了。借了一辆小踏板,然后两天疯狂骑行了 300 km属实有点疯狂。\n去了郑铁那的小破街买了酷酷的眼镜 😎\n时隔多年又回到大学校园 🤨,坐在龙子湖边吃泡芙、喝奶茶、啃鸡腿、看大妈唱歌确实惬意的不能行 ~\n后来又跑到玉米楼不过已经很晚了。整根烤肠麻溜回家 ~\n第二天一块吃了凉皮确实不错然后出发\n最最最刺激的来了我带着她在城市快速路上飞奔然后被交警开着警车抓我们。\n经过我的一顿操作躲开了交警哈哈哈。\n真 TM 刺激······\n后来又去了藤原豆腐店主要就是为了这个视频才写的这个博客哈哈哈 🤪🤪🤪\n "},"Personal/Blog/2022/最近在折腾什么……":{"title":"最近在折腾什么……","links":[],"tags":["生活/日记","博客/原创"],"content":"两个多月没更新博客了,也不是忙吧,各种烦心事感觉乱糟糟的,负能量满满……容易传递不好的情绪。还是简述记录一下最近在干嘛好了 ~\n参加婚礼\n郑州疫情散去便迎来了婚礼黄金周参加了 7 场婚礼,我的天哪哈哈哈。有发小的、同事的、同学的,看的我也是心痒痒。\n多学习多了解婚礼仪式的进行得到了如下总结\n\n司仪很重要\n如果能准备一些小视频、小短片会让现场变得很温馨 ~\n新郎免不了会多几个爹 👦👦👦\n很多人是来吃饭的所以吃的也很重要可以把控上菜的时间提升体验感\n作为参与者感觉新郎新娘应该像做梦一样\n\n学习\n参加了成人高考学习进步好好工作。压力时时刻刻存在疯狂内卷\n网站\n最近又折腾了一下网站、服务器弃繁就简将是以后一贯的宗旨。\n弃用了 typecho换成了 halo以实际需求为宗旨。\n整合归纳了个人知识库更系统化结构化。\n其他的暂时也没了有时间会细说分享一下 ~\n疫情\n邪魔退散\n邪魔退散\n💪💪💪\n平时生活中一忙博客就更的少了。\n马上迎来春节了祝大家新年新气象新年赚大钱🎉🎉🎉"},"Personal/Blog/2022/最近的生活":{"title":"最近的生活","links":[],"tags":["生活/日记","博客/原创"],"content":"又是一个月没写博客了,比较随心所欲。不过还是简单流水账记录一下最近的事情 ~\n五一假期都没能完整的过完就通知要静态管理……大半夜连忙跑到单位毕竟单位有吃有喝还能工作忙起来。在家待半个月怕是都待傻了。\n每天划划水学学习撸撸铁也是挺自在的但是巨想出去解放一下。\n还有就是在封城前的几个小时我是真的好运气。顶着大中午的太阳把地给浇了浇水要不然这么多天的辛苦劳作全部泡汤了……\n小菜园呢最近长得很不错。就是最近天气越来越热浇水有点麻烦。\n希望疫情可以人性化一些我觉得已经很严重的影响生活了……\n这个月生活巨充实每天都感觉时间不够用。所以也都没怎么写博客了如果有机会出去玩还是会好好记录一下。\n今年的银河季也紧剩不多了一年又一年。\n希望可以去白云山 ~\n冲啊奥里给"},"Personal/Blog/2022/月季到了":{"title":"月季到了","links":[],"tags":["生活/园艺","博客/原创"],"content":"心心念念了好久的月季终于到啦 ~ 因为疫情的影响,所以快递都不能按时发货耽搁了好久。不过还不算晚,赶快种下去生根发芽!\n关于花、绿植购买推荐\n\n如果有条件的话还是建议去当地花卉市场买现成的毕竟更好活也不容易出错需要接受一定的溢价。\n如果有一定动手能力和不错的心态可以尝试网上入手。推荐的四家店铺都有买过个人觉得挺好的目前还未翻车 ~\n这次买了月季花还有绣球花绣球花目前还在老家打包行囊……\n\n种花\n\n地早早的翻好了、也施肥了不一会儿就种完了。这几天有点热稳妥起见搭个遮阳网增加成活率。\n春天来了花花草草长的真快。也就几天没去把野草野花长的估计得一下午收拾了 ~\n还有就是今年的菜价是真的不便宜粗略计算了一下一亩地小米辣净利润应该不少于一万元……\n五一假期一定要把菜种下待到开花结果时给各位安排一下 ~"},"Personal/Blog/2022/浅谈一下自己折腾的网站":{"title":"浅谈一下自己折腾的网站","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"折腾了好久网站了,也折腾了好久的服务器了。网络拓扑图也不想画了,总之就是弃繁就简了,一切以使用、需求为出发点。\n网站\n\nBitwarden\n开源的密码管理器平时自己的密码全都放在这个上面了。\n密码提示密码填充等等。密码安全性也提高了总之就是真香 ~\nDocusaurus\n开源知识维基用来系统化、结构化归纳自己知识。基于自建 Gitea 服务,腾讯云 web 托管。平时记录完笔记就自动推送 Gitee国内和 GitHub国外界面好看也挺好用的暂且打个 8 分把。\nGitea\n版本控制器私有化的 GitHub不过没有 GitHub 支持的功能丰富。搭建的原因主要就是放在第三方平台,莫名的没有安全感……\nLskyPro\n图床图床更规范的管理图片了。图片也不怕丢了总之很好用。自建博客不推荐博客自带的附件管理不具有可移植性。\nNextcloud\n网盘私有化百度云。主要还是备份同步以及放一些私人资料横向拓展比较丰富不只是单单的网盘。邮箱、订阅、日历、看板等等及其推荐私人开发者搭建一个。这个也是真香 🤪\nRSSHub\n主要信息获取渠道不喜欢被动的接受信息。碎片化信息太多网文也太多。我觉得现在杂志也挺香的不过就是要花钱。一般推荐官方提供的也够用。\n总结\n感觉越来越懒了特别是服务器这块。不想再折腾了也不能再单纯的靠爱发电了。能自动化就自动化能少点一下就少点一下……"},"Personal/Blog/2022/番茄开花啦-~":{"title":"番茄开花啦 ~","links":[],"tags":["生活/园艺","博客/原创"],"content":"当下没有诗和远方,只能更新一下我的小菜园了。现在的小菜园已经颇具规模啦,吃上可口的蔬菜已经指日可待了,奥里给!!!\n5 月 3 日\n \n五一假期本来打算大干一场不过这该死的疫情。大半夜跑路到单位幸好提前漫灌式的浇了一遍地不然真的就死翘翘了。\n还记得是早上十点多去地了奇奇怪怪的第六感让我在大中午硬着头皮把地浇了浇水。然后郑州市准备静态管理……\n感谢真主、感谢斗战胜佛、感谢第六感哈哈哈\n\n临走还采摘了一束月季用来插花美极了 ~\n5 月 13 日\n终于终于部分区域解封了这半个月算是在单位待麻木了……\n管控期间也挺快乐的下班了经常偷偷跑会议室投影看电影体验感巨棒堪比影院吃着西瓜唱着歌美滋滋。\n不过单位食堂的饭菜简直了给你机会你不中用啊啊啊……\n\n\n下班后一路小跑到菜地看到还活着就放心了 ~\n封控管理的这段时间下了两场雨本来以为不会发芽的朝天椒竟然给了个小惊喜。不错不错 😎\n\n然后俺俩一块去搞吃点期间她问为什么这个菜叫小黄鱼鱼真的给我笑死哈哈哈。\n\n周日上班前我又去清理了一下杂草。清理干净舒服多了 ~\n5 月 18 日\n\n工作日期间怕旱死就又跑来浇了一次水看这样子又需要漫灌式浇水了。\n5 月 22 日\n\n本来和鹏哥约好的一块浇地了可惜地头的水井坏掉了最后还是跑了好远拉的水。\n期间长辈建议辣椒移植一下种的太过于密集然后又把番茄苗用棍子加固了一下。\n我感觉我真的是个欧皇。因为接下来几天都是大风如果不加固的话全部都倒伏了……\n也是再次深刻体验到种地真的好辛苦面临这些灾难真的是无能为力。\n5 月 25 日\n\n\n下班了想着去地转转然后邻居正好在浇地趁着机会我也铺好水带浇地\n这次有经验刚好天黑之前搞定\n5 月 29 日\n\n\n\n不知不觉瓜苗长的真快也该施肥了。还有就是病虫害本来打算搞点农药打打但是又感觉没必要。所以一直都是手动把虫扒拉下来或者捏死想跟我抢吃的没门 🙂。\n这个月小菜园里的各位同志明显长个长大了等待端午假期再好好休整一番 ~\n冲冲冲奥里给"},"Personal/Blog/2022/种下了一些瓜果蔬菜":{"title":"种下了一些瓜果蔬菜","links":[],"tags":["生活/园艺","博客/原创"],"content":"五一调休导致周末只休息一天,到底是谁发明的调休,自觉一点挂电线杆子。上周月季花种下了,期间去浇了一次水,到现在已经盛开啦。不过绣球花可能就夭折了,疫情原因导致已经在分拣中心停留十天了……\n因为这周只有一天所以同事也不回家看孩子了在我的邀请下和我一块去开垦新大陆了 ~\n本来只是打算翻翻地松松土整理一下五一再种菜。但老庄的街坊辈邻居去地看我俩劳动闲聊之下便一块骑着电动小三轮去农机站买菜苗了 ~ 农机站大妈这有青椒、黄椒、西瓜、番茄、茄子等,一顿商讨下来买了 20 棵青椒苗、6 颗番茄苗、6 颗茄子苗还有 6 棵西瓜苗。\n期间有件趣事哈哈哈。我本来打算就是买如上的数量但是苗都是成双成对的不好分割。然后我就说要 20 棵青椒、5 棵番茄、5 棵番茄、5 颗西瓜苗,大妈裁着裁着就感觉不对劲哈哈哈。我顺势一说,买镇些了送个,也不起些啥(方言)。最后还白嫖大妈的纸箱装菜苗,大妈可能心想:卧槽、这年轻人……\n返回菜园继续翻地同事好久未曾干农活不一会喜提三个水泡连连认怂哈哈哈。\n我们两个干的还挺快不一会就都种下去了就是挑水浇菜可是真累着我们俩了。因为目前规模不大农田里灌溉式浇水完全不值当水带还没展开我这都浇完回家了哈哈哈。\n目前菜园已经初具规模了不过五一假期将会是个大工程。因为我没有办法描述的很生动所以很多事后来就又忘了就写的比较拉跨。在考虑用 vlog 形式记录种菜文。同时还有一个想法,就是因为种植的菜还是比较多了,送送亲朋好友还会有余。打算到时候免费寄给各位博友,为了不让你们感觉白嫖我哈哈哈,可以回赠你们的闲置书籍于我。\n最后的就是照片分享 ~\n\n\n\n\n"},"Personal/Blog/2022/罪恶应该被遗传么":{"title":"罪恶应该被遗传么?","links":[],"tags":["生活/感悟","博客/原创"],"content":"罪恶应该被遗传吗?这个标题还是源自看到的两个视频《四天工作制》、《为什么德国年轻人选择不上大学,直接去工作?》,进而延伸出来的思考。\n英国作为老牌强国曾更是被称为日不落帝国作为世界上第一个工业革命和工业化的国家西方资本主义的倡导者并且是早期议会民主制的诞生地。但在资本主义原始积累阶段它也是罪恶累累现如今作为发达国家其国民更是享受发达国家带来的高福利德国更是如此那么它们曾经所作下的罪恶应该被遗传吗\n日本于上个世纪对我国进行侵略战争两千万人的抛头颅洒热血赶走了侵略者。那么现在日本应该遗传曾经所犯下的罪恶吗清朝闭关锁国是直接导致近现代中国的侵略原因之一那么现代的中国人就需要承担这些侵略带来的血与泪吗\n小时候村里有很多大沙岗村里的老书记也是趁着建筑行业的高速发展私自将全村的公共财产变卖发家其子孙后代也是享受充分的物质基础所带来的便利拥有常人所难得的资源与机遇。那么老支书的子孙后代应该遗传他曾经所犯下的罪恶吗\n人类作为智慧动物的一支站在动物金字塔顶端期间更是充满了原罪与杀戮那么其后代应该遗传所犯下的罪恶么如果动物就因为它母亲是猪那么它生下来就应该承受将来被吃吗\n就这个问题也与朋友展开了辩论问题的中线在于遗传父母给予孩子生命那么孩子应该遗传父母曾经所犯下的恶么最后所得的结论是\n\n客观上如果孩子享受父母曾犯下的恶所带来的利益那么孩子是必须要遗传或者继承这份所谓的恶。\n\n但是进而又存在的问题可以推翻这个结论孩子生下来作为独立个体有选择的权力吗如果父母就是想通过自己曾犯下的恶让自己的孩子获得利益呢就如动物生下来是猪小猪仔说它不想被吃我能重新投胎吗很明显这是不能的也是做不到的。\n综上所述最后还需要再加一条简单粗暴的结论**强者拥有最终解释权,因为我得拳头比你大,所以我的规矩就是规矩。**可是我以为我以为的就是我以为的吗?"},"Personal/Blog/2022/自律的痛苦······":{"title":"自律的痛苦······","links":[],"tags":["生活/感悟","博客/原创"],"content":"最近因为疫情,家也回不去了,一直在住在公司。去年考的专升本也通知让开始上课了,工作也比较清闲,生活、学习、锻炼及其自律,自律的有点痛苦······\n去年通宵一周考上的函授专升本不谈有用没用。因为我开心哈哈最近通知又开始上课了。\n为什么要提一嘴这个了就是很奇葩。高考第一志愿就是这个学校然后又莫名其妙的考到了这个学校……\n人生兜兜转转真是个圈子但我觉得这只是心理暗示在作俑\n简单叙述一下最近一周来的生活节奏目前我是已经平静不下去了······\n\n740 起床洗漱\n800 公司食堂早餐\n830 打卡\n830 - 1000 阅读 RSS 订阅,浏览各大友博,看看 B 站的更新,欣赏一下别人的摄影作品。\n1030 看完就会错点去打水,冲咖啡,泡茶喝\n1030 - 1230 昨天剩下的事情忙一下,同事聊聊天,随便逛逛,饿了会去小卖铺买吃的,当然带薪拉屎是一定的嘿嘿嘿,不过还是会做一个 todolist明确一下下午要忙的事情。\n1230 - 1300 下班不积极,脑壳有问题 ~ 打卡吃饭!\n1300 - 1330 回宿舍刷抖音,睡觉前看一些搞笑抖音哈哈\n1350 起床打卡上班\n1400 - 1700 主要以工作和学习为主,打工人嘛,累了该摸鱼摸鱼。\n1700 - 1800 讨论一下晚上吃啥,下班干啥(疫情哪都去不了)\n1800 - 1900 食堂的饭好吃不好吃,都会很认真的吃一顿。\n1900 - 2100 学习,刷课,撸代码,因为没人打扰,所以可以做一些需要专注的事情\n2100 - 2200 回宿舍撸铁,嗨歌,洗漱,冲澡\n2200 - 2330 刷韩剧,首先明确一下。我是一个很直很直的男生哈哈,但是韩剧真的好甜 😍\n\n可能和很多努力工作奋斗的人不一样目前我的工作属于企业级运维每天如果看我很忙的话可能领导比我都着急。每天实质性的工作最多一个小时除了打卡没有任何硬性要求你干啥都行……\n更多的时间安排了学习和生活不过感觉真得很惬意。最近过完年幸福度倒是直线上升 ~ 不过,我已经要过不下去了。\n躁动的心 ~\n我想要出去转转我想睡大床我想吃好吃的我想吃火锅我想喝小酒我想看好看的妹子哈哈哈哈哈哈哈哈哈哈哈哈"},"Personal/Blog/2022/论成年人的睡眠":{"title":"论成年人的睡眠","links":[],"tags":["生活/感悟","博客/原创"],"content":"一直想写这篇文章,却又不知从何下笔。闲聊闲聊 ~\n失眠\n我其实还好并没有失眠到影响生活。只是大多时候因为情绪不好所以带来抗拒性的入眠。不过失眠确实很可怕我之前有一段时间没有办法正确处理自己的情绪和压力然后算是失眠了吧。也带来了失眠的躯体反应心慌、心搏、手抖、暴躁、情绪的恶循环。\n正确、乐观的处理情绪和压力很重要堵不如疏很多时候一味的压制自己的情绪和压力只会越来越糟糕。所以目前我的解决办法就是合理的发泄做自己条件允许下相干的任何事情。\n大多时候会出去扫街、拍拍照、弹钢琴、听音乐。适当饮酒和吸烟确实能立刻带来效果缓解压力不过真得挺容易成瘾的。我一直自认为不会成瘾但是物质反作用于意识意识又决定物质……所以还是尽量不要采取这种方式。\n放松自己 🤔\nTake easy ~\n抗拒性入眠\n这个我还真的不知道要怎么解决不过目前方法是随它去吧哈哈。\n有时候工作一天到家就只想刷刷抖音看看 B 站等等……\n有时候老友相聚就只想玩玩玩玩玩该睡也不睡……\n这种熬夜真得很快乐、很自由 [手动狗头]。\n熬夜一时爽过后火葬场……这种熬夜牺牲的大多是第二天的工作生活然后习惯性的熬夜之后。时差倒不过来过度的享受快乐提高开心阈值又会导致干好多事情都没意思……\n适当性的熬夜需要合理的处置否则就容易造就恶性循环。\n例如熬夜完后第二不睡懒觉增加熬夜的成本让自己感觉到熬夜很痛苦 😭\n沙雕式失眠\n这个是关于我本人的……\n\n开灯睡觉……\n穿衣睡觉……\n蹬被子冻醒……\n半夜醒了不睡玩手机……\n······\n\n睡觉很重要还是好好洗洗睡了。\n最近一直在调整睡眠11 点前睡觉!\n👻👻👻"},"Personal/Blog/2022/谈谈我的「数字文具盒」---NextCloud":{"title":"谈谈我的「数字文具盒」 - NextCloud","links":[],"tags":["开源项目/数字文具盒","生产力工具/NextCloud","博客/原创"],"content":"接下来两篇主要谈论 Nextcloud 和 Obsidian因为篇幅较长所以单出罗列出来。本文主要介绍 Nextcloud 以及使用中的技巧和心得体会。\nNextcloud\nNextcloud 是一套用于创建网络硬盘的客户端-服务器软件。其功能与 Dropbox 相近,但 Nextcloud 是自由及开放源代码软件,每个人都可以在私人服务器上安装并执行它。\nNextcloud 的主要特性支持 WebDAV、日历CalDAV、联系人CardDAV、计划工作与流媒体同时拥有大量的插件增强了 Nextcloud 的功能和多样性例如在线的文本编辑、书签服务、相册、RSS 阅读器、文件查看器等。\n仪表盘\n\nNextcloud 登录成功后,主界面是可以通过插件自定义的面板。例如 Google、Github、邮件、任务等汇总到一起让你对一天工作的重心和任务了如指掌。\n文件\n\nNextcloud 支持 WebDAV 同时支持全平台客户端同步备份,可以方便快捷的同步文档、照片等。我平时比较重要的文件都会同步备份在 Nextcloud如果网络和存储容量够大还可以备份影音媒体资源。\n在能够访问互联网的情况下可以随时随地全平台访问 Nextcloud 快速开展工作。相较于百度云网盘最明显的优点就是拥有数据自由权以及不差的拓展性,而且实际体验根据服务器性能各不相同。同时文件管理支持链接 OnlyOffice可以获得不输腾讯云文档的在线体验。\n相册\n\nNextcloud 的相册插件提供了基本的相册管理,可以把手机视频、摄影作品、截图等等按照日期分类浏览。我平时鉴于执行把工作和生活分开,所以 Nextcloud 就没有怎么使用相册功能。平时的摄影作品会存放在 Nextcloud 来备份,手机上的生活相片则用手机提供的云备份功能。\n邮件\n\nNextcloud 邮件功能提供了基本的收发邮件,综合体验不如第三方提供的服务。但是好在我登录了 Nextcoud 后就可以方便快速的处理邮件,而不用再登录第三方客户端。\n任务\n\n任务是和日历相辅相成、互相结合使用的。通过合理的制定任务控制任务状态监控任务进度。简直是 ToDoList 的升级版,嘎嘎好用呀!\n日历\n\nNextcloud 的日历功能则显示任务中指定的计划,同时可以通过 CalDAV 进行同步备份,如果是 Linux 或 Mac 操作系统就可以方便快捷的绑定日历Windows 目前则需要第三方软件才可以实现同样的效果。日历的主要功能规划、提醒,合理的使用可以让你事半功倍,再也不会无所事事了。\n看板\n\nNextcloud 的看板就类似于甘特图甘特图Gantt Chart是条状图的一种流行类型显示项目、进度以及其他与时间相关的系统进展的内在关系随着时间进展的情况是由亨利·甘特于 1910 年开发出。在项目管理中,甘特图显示项目的终端元素的开始和结束,概要元素或终端元素的依赖关系,管理者可透过甘特图,监控项目当前各任务的进度。若想要同时显示多个不同的项目开始与结束的时间,就可以利用甘特图呈现,监控项目当前各任务的进度。\n新闻\n\nNextcloud 提供了 RSS 订阅插件,如果你阅读了生产力工具(上),那么我相信你对 RSS 已经有了初步的了解。Nextcloud 的 RSS 订阅插件,相对于其他功能各异的 RSS 阅读器,我只需要打开 Nextcloud 就可以使用,而无需再打开其他的应用。\n心得\n现在我每天的工作流程就是打开电脑登录 Nextcloud 后:\n\n主页快速浏览重要信息\n阅读浏览 RSS 订阅资讯\n日历查看了解当下所处阶段\n任务更新昨日进度\n看板监控当下任务\n开始今日任务\n\nNextcloud 相对于其他的应用并无特别明显的优点,例如邮件功能就不如第三方服务的好用,但是 Nextcloud 好在没有明显的短板。在一些常用的工作、学习属性较强的应用中Nextcloud 通过插件的方式实现了 ALL in one。这点是我非常喜欢的我不用再搭建功能各异的应用服务也免得应用间来回的登录。\n如果对数据隐私和自由度有一定的需求Nextcloud 是小型团队私有化协作的首选,但是虽然 Nextcloud 工具很好用,但是很多小型团队并没有数字化协同办公的意识。例如企业微信提供了非常优秀且具有本土特色化的 All in one 办公协同,但是很多小型团队虽然用了企业微信但是也仅仅是换了一个通讯工具而已。\n如果想直接形成生产力、提质增效就学习使用企业微信快速帮助小型团队实现数字化如果企业微信满足不了需求建议尝试企业微信的插件功能来丰富拓展共同推进数字化的应用。毕竟信息化的发展现如今已经迈入了新的台阶——数字化数字化不仅仅是应用软件的单项升级更是思维模式的转变\n解疑\nNextcloud 安装后一堆报错\n善用搜索引擎很多前辈已经走过的路都留下了脚印摸着石头过河就行。\nNextcloud 无法安装应用\n因为网络问题Nextcloud 确实没有办法直接安装;所以可以尝试通过离线安装或者改善网络问题来解决。\n引用\n\n来源Nextcloud - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源甘特图 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」---Obsidian":{"title":"谈谈我的「数字文具盒」 - Obsidian","links":[],"tags":["生产力工具/Obsidian","开源项目/数字文具盒","博客/原创"],"content":"这篇关于 Obsidian 是生产力工具的终篇了,因为目前涉及 Obsidian 的文章特别多,所以我就不啰里啰唆叙述重复的文字了。本文主要涉及到 Obsidian 和 Docusaurus 如何进行有机的结合。\nObsidian\n\n\nObsidian is a powerful and extensible knowledge base that works on top of your local folder of plain text files.\n\nObsidian 是一款基于本地文件夹保存的 Markdown 文件的强大知识库,旨在打造你的第二大脑!简单来说 Obsidian 提供的功能和语雀、有道笔记等笔记软件的核心功能都是一致的,但是 Obsidian 作为一款开源产品,其插件系统提供了丰富的功能和可拓展性。\nObsidian 的正式 1.0.0 版本于 2022 年 10 月 13 日正式发布。Obsidian 虽然作为一款很新的产品但是却拥有一众信徒。Google 上关于 Obsidian 的搜索词条高达 2000w 条,同时各种各样的入门教程更是层出不穷。\n在此主要介绍几个我认为特别好用的插件模板、 日记、Git、XMind 思维导图。每个人对于 Obsidian 的需求和用法大同小异,但终归都是为了高效的记录笔记,切勿折腾本末倒置。适合自己的就是最好的!\n模板\nObsidian 核心插件提供了基础的模板,第三方市场也提供了功能更加丰富的模板插件。模板插件对于文章的元信息,日记的固定模板、周报的固定模板、知识文章的快速生成提供了便捷,同时提高了效率。\n文章元信息\ntitle: 谈谈我的「数字文具盒」 - Obsidian\ndescription: 谈谈我的「数字文具盒」 - Obsidian\nkeywords:\n- 数字文具盒\n- 生产力工具\ntags: \n- 数字文具盒\nauthors:\n- 7Wate\ndate: 2022-11-30\n\n日记模板\n# <% tp.date.now() %>\n\n## Info\n\n| Date | Weather | Moon |\n| -------------- | ------------ | ---- |\n| <% tp.date.now("ddd HH:mm") %> | <% tp.web.daily_weather("郑州","zh") %> | <% tp.web.daily_weather("郑州","zh","?format=%m") %> |\n\n## Daily\n\n<% tp.web.daily_poetry() %>\n\n\n## Habits\n\n- [ ] 早睡早起 🌃\n- [ ] 健康饮食 🥗\n- [ ] 多喝热水 ☕️\n- [ ] 保持运动 💪\n\n## To-do List\n\n- [ ] 阅读资讯 📺\n- [ ] 每日必做 ✨\n- [ ] 今日读书 📖\n- [ ] 今日计划 ✏\n- [ ] 今日分享 📌\n\n## Notes\n\nMarkdown 文件不同于其他 Word、语雀等提供了元信息所以这里需要手动维护便于查阅和展示。子弹笔记也可以通过日记模板快速实现不必拘泥于种种繁琐的细节。我使用 Obsidian 的模板功能主要是方便和 Docusaurus 进行有机的结合。\n日记\n\n日记功能则是由 Calendar、Periodic Notes、Templater 共同组合实现的。简单来说就是通过 Calendar 插件(右侧日历)点击任意一天,即可通过 Periodic Notes 快速创建至对应文件夹并且生成文件名,然后 Templater 模板插件快速生成今日信息(自定义模板),最后简单写下今日总结即可实现一份完美的日报。\nGit\nObsidian 提供了多种同步插件,但是作为一个 Coder我还是喜欢 Git。\n\nXMind 思维导图\nObsidian 的 XMind 思维导图插件在写完文章后可以快速生成思维导图。\n\nDocusaurus\n\nDocusaurus 是 Facebook 的一款开源产品Docusaurus 能够帮助你快速创建并发布美观的文档网站。因为 Obsidian 的开源版本不提供 web 展示,所以我借助 Docusaurus 实现了知识库的 web 展示。\n平时在 Obsidian 客户端的帮助下我可以随时随地快速的记录知识。Obsidian 提供的 Git 插件,方便我同步到远程 Git 仓库,最后使用 Github 等第三方服务进行自动构建部署。\n在工作学习中打造个人的 wiki 知识库是必不可少的,其在经过不断的积累后可以产生质的变化。总的来说 Obsidian 和 Docusaurus 并不是每个人的最优选,我前期刚开始使用的时候也是好一顿折腾,经历了一段时间的使用后才慢慢形成生产力。\n结语\n\n至此生产力工具篇结束整个「数字文具盒」系列也算进入了终篇。目前还有两篇文章关于心得体会和网络环境的。希望这 2w 字的「数字文具盒」对你有所启发和帮助!"},"Personal/Blog/2022/谈谈我的「数字文具盒」---心得体会":{"title":"谈谈我的「数字文具盒」 - 心得体会","links":[],"tags":["工作/效率","开源项目/数字文具盒","博客/原创"],"content":"谈谈我的「数字文具盒」系列文章更多的是作为指南针,总的来说并不全面也不包含具体的操作细节,我的「数字文具盒」核心指导思想:适合自己的才是最好的、数据自主权、提高效率切勿折腾。\n适合自己的才是最好的\n你也许在用语雀、有道、Notion 等各式各样的生产力工具,已经形成了生产力,务必坚信适合自己的才是最好的。「数字文具盒」系列文章更多的是我对生产力工具的经验之谈,不存在普遍适用性。我的初衷是「数字文具盒」系列文章可以拓宽你生产力工具的边界,如果你刚好需要从零打造生产力工具,当然最好不过。\n切勿纸上谈兵猴子下山。打造生产力工具一定要结合实际需求出发更不要盲目创造需求。就如同书买了是要读的、读的时候是要思考的、最后的时候是需要总结升华的并不是买了书知识就到脑子里了。生产力工具的打造更是如此在满足基本需求的情况下不断使用、提炼总结、反复实践一步一个脚印、层层递进才可以打造出适合自己的生产力工具。\n数据自主权\n互联网精神开放、平等、协作、快速、共享 它更是互联网生命力之所在。因为现在的互联网科技公司商业行为一味的跑马圈地不断的吸食互联网的血液。虽然我崇尚极致的自由尊重 GUN 计划;但是不可否认商业公司是互联网发展中的极为重要的推动者。所以综上所述,我更愿意掌握数据自主权,同时和互联网科技公司业务进行有机的结合。\n例如我私有化部署的 Gitea 可以同时使用 Github、GitLab、Cloudflare 进行自动备份、持续集成、持续部署等。静态网站更是利用腾讯云的活动一直免费使用CDN 等更是羊毛都薅秃噜皮了。最后这所有的数据完全掌握在自己的手中who 怕 who 哈哈哈 ~\n提高效率切勿折腾\n不忘初心方得始终初心易得始终难守。我也见过很多很多很多博友在折腾工具的路上一去不复返了似乎忘了最初的本意完全沉浸在折腾的乐趣里了。并不是要论个谁对谁错我其实也非常喜欢折腾真的嘎嘎快乐 ~\n因为我对于「数字文具盒」的定义就是为了提高学习、工作效率并以结果为导向以实现需求为目标的。所以如果你打造「数字文具盒」是为了提高效率那么就切勿折腾如果是为了快乐那就好好折腾 ~"},"Personal/Blog/2022/谈谈我的「数字文具盒」---数字基建":{"title":"谈谈我的「数字文具盒」 - 数字基建","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"万丈高楼平地起,只有打好地基才能更好的实现数字文具盒。传统意义上的基础设施主要是公路、电网、供水等设施;数字基建则是互联网、数据中心等数字化设施。本文的数字基建主要是:云服务器 + 域名。\n云服务器\n云服务器Cloud Virtual MachineCVM 提供安全可靠的弹性计算服务。 可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。现如今已经并不需要去购买物理服务器,然后拉根网线连上网来实现数字基建了。云计算的发展带来效率的提升,仅需在服务商买一台足够用的服务器,就也、不用担心停电,断网,硬件损坏等边际成本了。\n例如腾讯云、阿里云等等在活动打折的时候低廉的价格就可以拥有一台个人云服务器。结合实际的国情云服务器除了性能上的差距还存在如下的问题\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n境内服务器境外服务器带宽低较高网络无法访问境外无法访问境内速度速度快无法保证备案支持不支持域名备案才可以正常访问无限制\n综合来说境内服务器优点速度快支持域名备案。境外服务器优点免备案访问网站。当然并不存在境内差不值的境外好买买买的两者也是有很多坑的。\n云服务器什么配置更适合我\n根据实际需求和钱包。 我这次购买的服务器,实现所有需求日常内存占用 70%,留下了一定的冗余量保证突发情况。一般情况下,云服务器处理器闲置率较高,内存则为重要指标,网络带宽则体现在访问、下载速度上。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n内存容量适用场景1GB博客、静态网站、迷你论坛。2GBNextCloud、RssHub、Gitea、Docker 等。4GB 及以上常见生产力工具、论坛等等。\n如何区分境内、境外服务器\n无论是境内还是境外服务器首先必须要明白一点不能触犯云服务商「商业执照」所在地的法律条规。 如果服务商隶属于中国,例如阿里云、腾讯云。哪怕你买的云服务器在美国、欧盟也必须遵守中国法律;同样如果你买的美国服务商的服务器就必须遵守美国法律。\n根据《互联网信息服务管理办法》第十五条互联网信息服务提供者不得制作、复制、发布、传播含有下列内容的信息\n反对宪法所确定的基本原则的。\n危害国家安全泄露国家秘密颠覆国家政权破坏国家统一的。\n损害国家荣誉和利益的。\n煽动民族仇恨、民族歧视破坏民族团结的。\n破坏国家宗教政策宣扬邪教和封建迷信的。\n散布谣言扰乱社会秩序破坏社会稳定的。\n散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的。\n侮辱或者诽谤他人侵害他人合法权益的。\n含有法律、行政法规禁止的其他内容的。\n例如我买的腾讯云 - 硅谷云服务器,虽然是境外物理服务器,但还是不能违反中国法律条规所不允许的事情,违规擦边依然会面临无条件封禁。务必结合实际需求来购买,避免买了境内服务器又想要境外服务器的优点。如果有额外的需求,请务必花一点钱转移风险,而不是头铁试试会不会被封。\n境内 / 境外云服务器买哪个?\n非必要需求建议买国外。 云服务器相同配置情况下,境内境外服务器性能无明显差距,主要还是网络访问。境内云服务器访问一些网站,例如 githubdockerhub 等等太慢了,甚至是无法访问。并且可能会因为网络问题产生各种意外的错误。国外服务器还可以免备案域名绑定,同时带宽也相对较高,实际体验速度也不比国内慢太夸张。\n我的上一台腾讯云 - 上海云服务器 ping 值 50 左右,现在的这台腾讯云 - 硅谷云服务器 200 左右,实际应用体验基本无感。但是国外服务器不支持备案,所以务必注意这点。\n那个云服务厂商比较好用\n优先买大厂的云服务然后买优惠享折扣。例如常见的境内腾讯云、阿里云、华为云等等境外的亚马逊云、搬瓦工等等太多了。我用了大概 5 年左右腾讯云的服务器,目前整体来说腾讯云对个人还是不错的,暂时并未遇到太大问题。\n如果你有经常蹲折扣例如双 11黑色星期五那么一定是真香定律。例如我这次升级云服务器则是蹲到了腾讯云 - 轻量云两周年活动。仅花费了 1400 元左右,购买了 7 年的 2 核心 4GB 的云服务器。\n群晖、树莓派会不会更省钱、更好用\n不一定、看情况。 如果你有家庭数据中心的需求,那么群晖、树莓派等会更好的满足你的需求。但就大部分情况来说,建议购买云服务器。因为家庭数据中心太折腾、太折腾、太折腾,需要无法计量的时间精力和成本。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n家庭数据中心云服务器网络速度快、不稳定速度慢、稳定可弹性升级存储容量大容量小可弹性升级性能高性能低性能可弹性升级电费0.5 元 - 10 元无费用同性能价格低同性能价格高运维边际成本极高无\n两者单就电费来说家庭数据中心设备挂 4 块硬盘,综合功耗 50w。一天 5 毛钱的电费7 年就是 1277.5 元。我的服务器 7 年也才 1400 元,并且免维护。如果家里意外停电了,硬盘还可能会挂。硬盘如果组件了阵列模式,阵列重组也需要时间,而且存在失败几率。网络更是不用提了,国内很少能有个人用户享受完美的固定 IP 地址,商业带宽更是费用爆炸。\n当然家庭数据中心并不是一无是处它在网络、存储、性能方面可以秒杀云服务器。家庭数据中心动辄上 T 的数据存储容量8 核心的处理器和 16GB 的运行内存是云服务器所不能的。想必折腾家庭数据中心的应该不会看我这篇文章。🤣🤣🤣\n域名\n网域名称Domain NameDomain简称域名、网域是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称用于在数据传输时标识计算机的电子方位。域名可以说是一个 IP 地址的代称目的是为了便于记忆后者。例如wikipedia.org 是一个域名。人们可以直接访问 wikipedia.org 来代替 IP 地址然后域名系统DNS就会将它转化成便于机器识别的 IP 地址。这样,人们只需要记忆 wikipedia.org 这一串带有特殊含义的字符,而不需要记忆没有含义的数字。\n既然域名是为了方便记忆那么就注册一些有意义、好记的域名同时喜欢什么就注册什么 ~\n免费域名好用么\n免费的往往是最贵的如果你有云服务器就不要注册使用免费域名例如 .xyz 后缀的域名一年也就十几块钱,所以务必不要注册使用免费域名。免费域名解析起来存在一定的不稳定性,同时那天可能就停止你的访问了,其次对 SEO 不太友好。\n那个域名后缀好一些\n建议注册 .com、.org、.dev 等常用后缀。 因为域名是存在一定价值的,所以不要乱注册域名浪费钱。就注册这些大家常用的域名后缀。\n国内域名好备案么\n看情况而且一些域名无法备案。 例如 .org 域名无法在国内备案,所以如果你想要备案,务必清楚那些域名可以备案。而且备案成功后,并不意味着可以一劳永逸了。工信部门会随机抽查,如果你是幸运儿又得折腾啦。域名备案时间大概需要 10 - 20 天左右,国内的云服务商都会协助你一起备案的,整体难度一般。\n\n中国互联网域名体系domain.miit.gov.cn/\n\n域名续费多久的好\n域名续费 8 年时间最好。 活动的时候会有折扣,然后就想着直接续费 10 年。在此忠告尽量不要续费 10 年,因为如果未来有转移域名的需求,你可能就要等一年或者两年才可以了。因为转移域名大部分情况必须在域名接收服务商再续费一年,所以域名续费 8 年时间最好。\n哪里购买域名有优惠\n谷歌域名购买选择土耳其地区付款。 我买了 8 年 org 域名,仅仅花费 200+,真的白捡似的。例如 .xyz 域名 10 年也才百十来块钱,所以冲啊!买垮谷歌域名!!!\n\n谷歌域名地址domains.google.com/\n\n引用\n\n来源云服务器CVM_云主机_云计算服务器_弹性云服务器- 腾讯云;仅学术引用,著作权归作者所有。\n\n\n来源政策与规范 违规信息类型说明-腾讯云安全违规处理-文档中心-腾讯云;仅学术引用,著作权归作者所有。\n\n\n来源域名 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」---生产力工具(上)":{"title":"谈谈我的「数字文具盒」 - 生产力工具(上)","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"在完成了数字基建、运行平台的搭建后,迎来应用服务 - 生产力工具的搭建;生产力工具主要从公共服务、工具、程序开发三个方面来说。由于全文篇幅字数较多,故分为上下两篇分开阅读。\n博客\n博客Blog是一种在线日记形式的个人网站借由博文、图片或视频来记录生活、抒发情感或分享信息能够让读者以互动的方式留下意见是许多博客的重要要素。\n我所有的一切都源于博客第一次写博文是在 2012 年、第一次搭建博客系统是在 2018 年、并于 2020 年底加入十年之约社区。截至到 11 月 30 日已经走过了 1626 天,现在博客已经是我生命中不可或缺的一项。\nWordPress\n\n2003 年 5 月 27 日Matt Mullenweg 和 Mike Little 创建了 b2/cafelog一个博客系统的一个分支宣告了 WordPress 的诞生。到了 2011 年 12 月3.0 版本已经被下载了超过 6500 万次。目前,互联网上超过 43% 的网站是 WordPress 创建的。\nWordPress 是一个以 PHP 和 MySQL 为平台的自由开源的博客软件和内容管理系统。WordPress 提供主题、插件、多作者协同、移动设备等特性,同时 WordPress 也是目前因特网上最流行的博客系统。\nWordPress 是我第一次搭建博客所使用的系统,后来没用多久便被 Typecho 吸引了。主要是因为云服务器孱弱的性能导致 WordPress 运行不流畅,所以 Typecho 便是我最优的选择。\nTypecho\n\nTypecho 这个名字来源于团队内部的头脑风暴Type有打字的意思Echo意思是回声、反馈、共鸣也是 PHP 里最常见、最重要的函数。将这两个词合并在一起,就有了 Typecho。\nTypecho 的程序设计逻辑与 Wordpress 相似通过插件与模板机制对程序进行扩展。Typecho 主要支持 MarkDown 语法、响应式设计;同时 Typecho 程序本体不到 500KB仅仅 7 张数据表带来了 WordPress 不可比拟的响应速度。\n我用了 Typecho 很长一段时间,但是我认为官方似乎停止了支持,仅仅有一些零散的缝缝补补;不过时隔三年 Typecho 迎来了 1.2.0 版本,但缺少新鲜血液的注入是我放弃 Typecho 的最大原因。\nHalo\n\nHalo 一款现代化的开源建站 / CMS 系统,其社区背后运营主体是 飞致云。现在的开源项目在靠爱发电和商业化运行的权衡中总是难以取舍,终究一旦是没有新鲜血液的注入就会渐渐没落。\nHalo 作为开源项目同时拥有商业化运营,其易于部署、完善的模板系统、附件系统、评论系统正是我所想要的。因为 Halo 基于 Java 开发,所以相对于 PHP 开发系统资源占用较高,勉强还可以接受。 不过现在 Github 有位作者基于 Halo 的开源组件,使用 Go 语言重构了 Halo 并改名为 sonicsonic 相对于 Halo 最大的优点就是系统资源占用缩减了 50 倍,仅仅占用 10mb 左右内存。目前一直在用 Halo将来可能会更换到 sonic。以后的事情以后再说 ~\n那个博客系统好\n喜欢那个就用那个没有喜欢的自己写一个。 因为我见太多太多博客折腾了很久,但是并没有持续的产出文字,所以不要忘记初心是为了什么!\n静态博客好用么\n静态博客最大的弊端就是评论。 因为博客最重要的属性就是能与读者通过有限的评论互动,所以如果能解决掉评论的问题,静态博客也许会是最好的选择!\n碎片化知识\n二十一世纪信息大爆炸不同以往信息传递更新慢现在各种各样的碎片化信息充斥着生活其更易学、更易用但是管理起来却很不方便针对这个问题我使用了 memos 和 massCode分别用来管理文字和代码。\nMemos\n\nmemos 是 flomo 的一款开源孪生 web 应用,其无需格式、无需排版、无需分类,可以通过多种方式,随时随地记录你的想法。\n\nFlomo 只专注于记录与整理想法,拒绝 All in one\n\nmassCode\n\nmassCode 是一款开源代码片段管理软件,类似于 Github 的 Gist支持 Markdown、演示模式、搜索、自动保存、截图分析、WebDav 同步等特性。同时 massCode 支持全客户端一致体验,无须担心多端协同的问题。\n维基\n个人知识体系是学习、工作生活中必不可少的四库全书通过不断完善、管理、精进个人的知识体系可以让我们在工作生活中更得心应手。我的维基知识库主要分两个知识脉络架构清晰的个人知识库、网页报告等零散资料的维基知识库分别使用了 Obsidian 和 Zotero 来实现和管理。\nObsidian\n\nObsidian 是一款支持 Zettelkasten 笔记法的笔记管理软件,同时支持 Windows、Mac 和 Linux 三大平台。Obsidian 的关键词第二大脑、本地文件管理、Markdown 格式、丰富的插件等。\n目前我的知识体系就由 Obsidian 作为基石,利用 Docusaurus 作为展示平台开放在 wiki.7wate.com 。目前通过不断地尝试、实践、总结已经形成了高效的生产力!\nZotero\n\nZotero 是一款自由及开放源代码的文献管理软件,用以管理书目信息(如作者、标题、出版社、摘要、阅读笔记等)及相关材料(如 PDF 文件)。其最著名的特性是作为浏览器插件、在线同步、与文档编辑软件如 Microsoft Word、LibreOffice、OpenOffice.org Writer、NeoOffice 等集成,可生成文内引用、生成页面脚注或文后的参考文献。\nZotero 在我这里主要的作用就是收集、整理、归纳零散的资料例如网页好文、研究报告、书籍文档等。Zotero 支持多终端平台使用,可以通过 WebDav 方式同步。\nRSS\nRSSRDF Site Summary / Really Simple Syndication中文译作简易信息聚合也称内容聚合是一种消息来源格式规范用以聚合多个网站更新的内容并自动通知网站订阅者。使用 RSS 后,网站订阅者便无需再手动查看网站是否有新的内容,同时 RSS 可将多个网站更新的内容进行整合,以摘要的形式呈现,有助于订阅者快速获取重要信息,并选择性地点阅查看。\n\nRSS 为打破信息茧房而生\n\nRssHub\n\nRSSHub 是一个开源、简单易用、易于扩展的 RSS 生成器,可以给任何奇奇怪怪的内容生成 RSS 订阅源。RSSHub 借助于开源社区的力量快速发展中,目前已适配数百家网站的上千项内容。\n目前我所有的新闻、资讯来源全部由 RSSHub 贡献,同时定期管理添加新的订阅源以有效杜绝信息茧房。现在我每天早上的第一件事就是阅读 RSS 订阅源!\n导航\n\n导航服务完全是我个人强迫症开发的浏览器首页主要还是忍受不了现在奇奇怪怪、各式各样的浏览器首页那还等什么动手燥起来\n网盘\n\n网盘平时主要是用于和朋友分享较大的文件、网络移动 U 盘的作用网络上有很多很多很多的实现方案例如Alist、ZFile、H5ai 等,我们喜欢那个用哪个。\n引用\n\n来源博客 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源WordPress - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源Typecho - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源Halo仅学术引用著作权归作者所有。\n\n\n来源flomo · 浮墨笔记;仅学术引用,著作权归作者所有。\n\n\n来源massCode | A free and open source code snippets manager for developers仅学术引用著作权归作者所有。\n\n\n来源玩转 Obsidian 01打造知识循环利器 - 少数派;仅学术引用,著作权归作者所有。\n\n\n来源Zotero - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源RSS - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源介绍 | RSSHub仅学术引用著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」---生产力工具(下)":{"title":"谈谈我的「数字文具盒」 - 生产力工具(下)","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"下文接着生产力工具继续说起,主要涉及到一些非常好用、事半功倍的工具!\n思维脑图\n思维导图mind map是一种用图像整理信息的图解。它用一个中央关键词或想法以辐射线形连接所有的代表字词、想法、任务或其它关联项目。它可以利用不同的方式去表现人们的想法如引题式、可见形象化式、建构系统式和分类式。它普遍地用作在研究、组织、解决问题和政策制定中。\n思维脑图是工作生活中梳理、划分、具象化问题中必不可少的方法论。在思维脑图的基础上我又进一步划分了分支型和流向型的思维脑图。\n\n分支型常见的思维脑图从巨到细一层一层划分梳理。\n流向型流程、分支预测图推演问题的可能性和结果走向。\n\nXmind\n\nXmind 是一款全功能的思维导图和头脑风暴软件。Xmind 可以快速整理思绪、延展思维、结构化呈现想法;同时结合多种思考方式,快速的提炼思维要点。其像大脑的瑞士军刀一般,助你理清思路,捕捉创意。\nXmind 平时我用的最多的一款工具了,简直太好用;整理思绪、提炼要点的一把好手。虽然有很多的开源项目可以实现 Xmind 的大部分功能,但是我真的是用习惯了,所以没有搭建私有的工具。\nExcalidraw\n\nexcalidraw 是一个开源 web 项目主要用于素描手绘图的虚拟白板。excalidraw 不仅拥有基础的白板功能,还拥有丰富的第三方形状库,同时还可以多方协作绘画。\nGithub 类似于 excalidraw 的开源项目有很多,功能也都大同小异,我就是选了一个自己喜欢的。自己部署 excalidraw 工具服务无法在线协同绘画excalidraw 官网提供此服务。\n数据统计\n数据统计只是自己平时想满足一下虚荣心看看有多少读者浏览博客。网络上很多大厂都提供数据统计例如谷歌、百度等等在这里我使用的是 Umami。\nUmami 是一款简单、快速、注重隐私的数据统计Google Analytics替代品。其通过一行 JS 代码就可以实现网络大部分的数据行为统计,而且拥有美观的 UI 设计。\n\n静态文件\n静态文件主要涉及到多平台易用、方便管理备份。例如博客的图片资源、维基的 xmind 脑图资源、视频资源,虽然都提供的有附件管理功能,但是谁能保证未来不会更换博客,更换网站呢?我在这里的解决方案就是搭建一个静态文件管理系统,负责所有的静态文件分类、归纳处理。\n兰空图床\n\nLskyPro 是一款开源 web 图床管理系统,其采用 Laravel 框架开发使系统拥有稳定、高效和安全性。LskyPro 现在拥有开源 1.x、2.x 和商业版,这种选择也许是开源最好的方向。我主要使用开源版本,更新了 2.x 以后我也尝试了新的版本。但是总的来说 1.x 可以很完美的满足我的需求,因为我不仅仅只管理图片,还需要视频、文档等等,所以 2.x 不能便捷自定义文件后缀就不是我的菜!\n我利用 LskyPro 管理静态资源的具体方法是通过 LskyPro 进行分类归纳存储,挂载腾讯云对象存储策略,再使用 CDN 自定义域名转发,既保证了速度又固定了静态资源的唯一 url 链接。\n密码管理\n密码管理器是一类用于生成、检索、保存及管理复杂密码、数字签名的措施可以由硬件或软件实现。复杂密码的生成一般按需要以随机算法产生而密码资料则保存于一个以密码、数字签名等方式加密的数据库内。它的作用类似于钥匙圈方便个人或企业组织集中管理密码、数字签名等身份管理要素。\n如今常见的密码管理器有三类\n\n本机安装并在本机访问的应用程序如 KeePass\n在线服务通常经网站访问如客户端、网络应用程序等\n经本机访问的外挂硬件设备如 U 盾、FIDO 等 USB Key。\n\n它们的主要区别是保存密码及数字签名的加密数据库是保存在本机使用的还是保存在在线存储服务的还是保存在特定存储设备的。一些密码管理器如 GNOME 钥匙圈、钥匙串、大部分浏览器内置的密码窗体存储功能等,既可在本机访问,也可在用户经过设置以后能使用在线存储服务的。一般密码管理器会要求用户至少需要一个主控密码来解锁经过该主控密码加密的存有账号密码信息的数据库。\n密码管理器这个范畴太大了我平时用的最多的就是管理各个网站的密码登录的时候一键填充密码服务。现在国外成立的 FIDOFast IDentity Online联盟其宗旨是为解决强制认证设备的交互性和用户面临大量复杂的用户名和密码。我比较看好 FIDO也许这就是以后密码管理的最终解决方案。\nBitwarden\n\nBitwarden 是一款自由且开源的密码管理服务用户可在加密的保管库中存储敏感信息例如网站登录凭据。Bitwarden 平台提供有多种客户端应用程序包括网页用户界面、桌面应用浏览器扩展、移动应用以及命令行界面。Bitwarden 提供云端托管服务,并支持自行部署解决方案。\nBitwarden 除了拥有基础且丰富的密码管理功能同时支持自动填写登录信息、用户名密码生成器、2FA 验证、数据泄露报告、跨平台客户端、支持私有部署等其他优点。Bitwarden 真的是密码管理器的一大杀手,但是官方提供的私有部署系统资源消耗较大。这时 vaultwarden 便闪亮登场vaultwarden 是 Bitwarden 的完美复刻版但是资源占用更少更易于部署。Docker run 一下就完成了服务搭建,真的嘎嘎好用、嘎嘎香呀!\n浏览器的密码管理器好用么\n只要是密码管理器都好用 如果你使用了密码管理器,我相信在绝大多数密码填充场景上省去了不少麻烦事情。现在 Chrome、FireFox 等都提供了基础的密码管理功能,但是相对来说功能不健全,密码安全得不到保证。\n还有其他的密码管理器么\n密码管理器真的是多如牛毛了形式各样的都有。 谷歌检索一下关键字,各式各样的都有,没有最好的密码管理器,只有最适合你的密码管理器。\n邮箱服务\n电子邮件electronic mail简称电邮email、e-mail是指一种由寄件人将数字信息发送给一个人或多个人的信息交换方式一般会通过互联网或其他电脑网络进行书写、发送和接收信件目的是达成发信人和收信人之间的信息交互。\n\n《互联网周刊》报道认为“1969 年 10 月,世界上的第一封电子邮件是由计算机科学家 Leonard K. 教授发给他的同事的一条简短消息。”\n\n电子邮件广为商业界使用是第一个广域的电子介质也是商业通信的第一次“e 化革命”。电子邮件发送信息方便、不需要同步进行,但是随着邮件越来越多,垃圾邮件、信息重载等等也令人苦恼。\n我个人非常喜欢邮件进行工作沟通首先相对于即时通讯邮件不需要秒回沟通起来更省劲、效率更高。但是大环境似乎并没人喜欢邮件沟通更喜欢秒回……本来也是打算自建邮箱服务器但是权衡之后还是选择了第三方服务。主要原因如下\n\n云服务商对邮箱端口的封禁\n可能会遭受莫名奇妙的封禁\n可能会被主流邮箱拉黑\n\n最主要的原因是因为现在邮箱服务的滥用导致人人自危所以我最终使用了腾讯企业邮箱。虽然注册绑定的时候麻烦一些但是可以在微信收到通知、同时拥有相对的自由权、也不会那么容易被拉黑故此我最终没有选择自建邮箱服务\n那个邮箱服务更好\n根据自己实际需求来满足你的需求就是最好的。 现在各个邮箱服务商都提供了各具特色的第三方服务,喜欢那个用哪个。\n版本控制\n在 21 世纪,如果计算机界没有了版本控制就如同西方失去了耶路撒冷! 版本控制是用来跟踪、记录、维护、回溯工程的重要工具,确保由不同的人共同协作的工程从诞生到定案的过程记录下来。\n我相信版本控制的概念很多人都已经接触了例如大名鼎鼎的 GitSVN 等。社区托管服务中 Github、GitLab 也都耳熟能详,这里主要介绍一下 Gitea 和 Gogs。\nGitea\n\nGitea 是一个开源社区驱动的轻量级代码托管解决方案后端采用 Go 编写采用 MIT 许可证Gitea 是从 Gogs 分支过来的,其主要优点开源、易于安装、跨平台、轻量级运行。\nGit 社区托管不好用么?\n社区托管非常好用但我在意数据自由。 因为社区托管说封了你账户可能那天就封了,不让你访问就没有一点办法了;所以自建 Gitea 就是我拥有对数据的绝对控制权,我可以选择性的同步到社区托管做备份。\n运维工具\n运维工具的主要目的就是舍弃第三方的 Shell 工具同时更便于服务器的运营维护。很多人用不到所以主要介绍两个运维工具Spug 和 JumpServer。\nSpug\n\nSpug 是一款灵活、强大、易用的开源运维平台,其面向中小型企业设计的轻量级无 Agent 的自动化运维平台,主要支持批量执行命令、文件管理、计划任务、发布部署、配置、监控、报警等综合一体化运维服务。\n平时我有一些小主机都会使用 Spug 来进行统一的管理挺方便的。Spug 相对于 JumpServer 的主要优点就是性能要求不高可以跑在小主机上。JumpServer 专业程度更高Github 更是 19.5K 的星星,真的是让人流口水 ~\nJumpServer\n\nJumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpServer 的特色优势是开源、分布式、无插件、多租户、多云、审计、多应用支持。\n企业级运维使用 JumpServer 的更多,提供的性能更强大。我在本地管理虚拟化主机也在使用 JumpServer但是云服务器孱弱的性能还是不要折腾了。\nCI/CD\nCI/CD 这个敞开嗓子聊怕是要说个三天三夜,爱你不停歇了~ 如果不做 DevOps 的话,很少会用到 CI/CD。目前我专业知识还达不到输出的程度所以就不误导人了。\n目前我在使用 Jenkins 进行持续集成和持续部署Github Action 等其他 CD/CD 工具也很好用,根据自己实际需求来,需要哪个用哪个就好啦 ~\n引用\n\n来源思维导图 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源Xmind思维导图 | Xmind中文官方网站仅学术引用著作权归作者所有。\n\n\n来源密码管理器 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源FIDO联盟 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源电子邮件 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源版本控制 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」---番外篇":{"title":"谈谈我的「数字文具盒」 - 番外篇","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"互联网时代开放、自由、无感的网络访问环境极其重要。基于天朝特色社会主义,「数字文具盒」特地衍生出番外篇——涉及网络环境的建设。主要从 DNS 和 网络 两个点切入,最终打造开放、自由、无感的数字生活。\nDNS\n域名系统Domain Name SystemDNS是互联网的一项服务。它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。其实 DNS 的作用非常简单,就是根据域名找到对应的 IP 地址。你可以把它想象成一本巨大的电话本。\n基于天朝的国情DNS 存在不同程度的污染情况以及法律法规的约束。例如前阵子 github 的 IP 地址被解析为天朝反诈骗中心、私自搭建公开 DNS 服务器更是违法行为。你想想,你带着老婆,坐着火车吃着火锅唱着歌。突然想给黄四郎打个电话,却被麻匪接到了。自建 DNS 就可以完美地解决这个问题。\nAdGuard Home\nAdGuard Home 是一款用于拦截广告和跟踪的全网软件。设置完成后它将覆盖您所有的家庭设备您不需要为此安装任何客户端软件。随着物联网和连接设备的兴起能够控制整个网络变得越来越重要。AdGuard Home 中提供了自定义 DNS 上游服务器以及 DNS 改写的功能,其他类似功能的软件可以达到同样的效果。\nAdGuard Home 以及其他类似功能的应用部署场景应该局限于家庭网络、局域网络,切记非必要勿公开。下面是推荐的上游 DNS 服务器:\n# 加密 DNS-over-TLS\ndns.alidns.com/dns-query\ndoh.pub/dns-query\ndns.google/dns-query\ndns.cloudflare.com/dns-query\n\n# Bootstrap DNS 服务器\n223.5.5.5\n119.29.29.29\n8.8.8.8\n1.1.1.1\n\n网络\n网络就是老生常谈的天朝局域网与世界局域网之间存在链接不稳定、网站无法访问等问题。网络问题的解决方案实在是太多了我简单说一下心得。\n\n狡兔三窟一常多备。\n切勿违法反复横跳。\n巧用代理嘎嘎嘎香。\n\n服务商\n首先介绍几个常用的网络服务商附有推广链接不喜勿喷。😍\n\nTAG我用了好几年体验最好的服务商。\nWgetCloud备用服务商年付费 12 元 10GB 流量。\nHutao备用服务商年付费 90 元 600GB 流量。\nRelayCloud备用服务商年付费 15 元 每季度 32GB 流量。\n一元机场备用服务商年付费 11 元 每月 100GB 流量。\n\n# TAG\ntagss.pro/(官网)\ntagss.pro#/register?invite=WB9TeKhc推广链接\n# WgetCloud\nwgetcloud.ltd官网\ninvite.wgetcloud.ltd/auth/register推广链接\n# Hutao\nhutao.cloud/(官网)\nhutao.cloud/auth/register推广链接\n# RelayCloud\nrelaycloud.pro/(官网)\nrelaycloud.pro/auth/register推广链接\n# 一元机场\nhttps://一元机场.com/(官网)\nxn--4gq62f52gdss.com/#/register?code=TeInX4mK推广链接\n\n每家网络服务商生怕新手小白不会用各平台都提供了对应的教程。如果条件允许的情况下可以在一台硬件设备路由器服务器部署代理和 DNS然后每台客户端链接代理服务器访问网络。\n\nAdGuard Home 安装及使用指北 - 少数派\nAdGuard Home 自建 DNS 防污染、去广告教程 #2 - 优化增强设置详解 - P3TERX ZONE\nClash上网软件 | Linux Mint学习笔记\nClash Web 管理\n\n代理服务器部署成功后例如 Linux、Shell、pip、docker 等各种需要稳定的网络访问环境下都可以使用这几条命令解决:\n# 代理 IP 地址更换为本地代理 IP 地址\nexport http_proxy="http://10.0.0.199:7890/"\nexport https_proxy="http://10.0.0.199:7890/"\nexport no_proxy="127.0.0.1,localhost"\n最后切记网络也不是法外之地开始尽情地享受互联网时代开放、自由、无感的数字生活吧 ~\n\n来源域名系统 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源DNS 原理入门 - 阮一峰的网络日志;仅学术引用,著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」---运行平台":{"title":"谈谈我的「数字文具盒」 - 运行平台","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"数字基建准备工作完成以后,就要准备搭建运行平台;简单来说运行平台是云服务器与应用服务的中间层起着承上启下的作用。例如操作系统的选择、运行模式的规划、数据存储的模式、系统安全的完善。\n因为我只有一台性能有限的云服务器所以运行平台达到的最终目的是应用服务高内聚低耦合。\n操作系统\nWindows Server\nWindows Server 是 Microsoft 专门创建用于服务器的一系列操作系统,旨在持续运行并为其他计算机提供资源。其提供便捷的 GUI 界面Winodws 用户学习成本较低,可以快速上手。\n除非特殊需求绝大部分情况下都很少使用 Windows Server 系列操作系统。 因为其系统资源占用相对于 Linux 较高,通用性稍差以及社区文档支持较少。同时 Windows Server 作为一款商业化操作系统,高昂的授权费用也是令人头痛。但并不是不能用,只是我没有尝试过所以就不深入展开讲述了。\nLinux\nLinux 是一种自由和开放源码的类 UNIX 操作系统。该操作系统的内核由林纳斯·托瓦兹在 1991 年 10 月 5 日首次发布。Linux 具有跨平台、低资源占用、可靠的安全性、社区的支持以及开源授权等优点,在服务器操作系统领域让众多 ITer 爱不释手。Linux 在低性能云服务器领域几乎是绝对的王者,同时 Linux 丰富的发行版本和社区支持,基本上可以满足你 90% 的需求。Linux 发行版本最明显的差异就是社区的运营方式,可以分为开源基金支持和商业化运营。\nLinux 那个发行版本好?\n选择你最喜欢的综合来说 Debian、Ubuntu 的使用率更高。 我会在不同的情况下选择不同的社区版本使用,目前最常用的就是 Debian。\n\nLinux 主流社区\n\nLinux 怎么安装软件?\n根据发行版本使用包管理器可以方便快捷安装软件 Linux 不同于 Windows 的图形化界面,大部分服务器管理方式也都是黑黑的命令行终端。但是 Linux 的日常系统更新,软件安装却只需要一条命令即可。\n# apt 安装 git\napt install git\nLinux 安装软件很慢\n可以设置境内 Linux 镜像源或者使用代理服务。 因为大部分 Linux 的官方源的服务器都在境外,所以境内使用 Linux 官方源安装软件就会超级慢,使用体验和百度云没开会员差不多。国内的开源爱好者为了解决这个问题,维护了《一键更换国内软件源》仓库。\n# root 用户\nbash <(curl -sSL gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)\n \n# Sudo 用户\nsudo bash <(curl -sSL gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)\n运行模式\n云服务器的操作系统安装完成后规划合理的运行模式依旧很重要。因为我的目的是应用服务高内聚低耦合所以我使用的是容器模式最常用的就是大名鼎鼎的 Docker。除了容器模式还有裸机运行模式同时低门槛上手文档完善的管理面板就是 宝塔 了。可以结合实际情况来选择,但是我真的不建议用宝塔。🤐🤐🤐\n裸机\n裸机模式就是应用服务直接跑在操作系统上性能利用率高、性能损耗少。但是环境管理难容易出现莫名其妙的问题而且还不容易找到原因。而且你需要面对黑黑的命令行管理终端面对新手朋友及其不友好。\n我就曾遇见一个网友学习使用 MySQL当时他安装了两个版本的 MySQL端口分别是 33063307。然后在数据库管理软件使用的 3307命令行终端使用的 3306。最后命令行终端执行的 SQL 操作语句,在数据库管理软件中完全查不到数据。向我们提问这是为什么?最后真的无力吐槽了······\n宝塔\n宝塔面板 作为国内一款安全高效的服务器运维面板,宝塔提供的 Web 管理页面让运维简单高效。可以一键配置LAMP/LNMP、网站、数据库、FTP、SSL通过 Web 端轻松管理服务器。但是但是它翻过车,曾有一个更新导致众多站长的数据库被爆,损失惨重! 虽然曾经翻过车,但是宝塔的学习成本低,上手容易入门快。所以就结合实际情况,理性使用。\n容器\n\n容器 Container 是一种基础工具。泛指任何可以用于容纳其它物品的工具,可以部分或完全封闭,被用于容纳、储存、运输物品。物体可以被放置在容器中,而容器则可以保护内容物。\n\nDocker 是一个开放源代码的开放平台软件用于开发应用、交付应用、运行应用。Docker 允许用户将基础设施中的应用单独分割出来,形成更小的颗粒,从而提高交付软件的速度。 Docker 容器与虚拟机类似,但二者在原理上不同。容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。\nDocker 容器的特性就是虚拟化,提供一个隔离的环境。 例如你可以运行多个版本的应用服务,其环境不会产生任何冲突。现在绝大部分的应用服务都提供了 Docker 镜像,可以方便快捷的搭建、运行应用服务;例如搭建一个 nginx 服务:\ndocker run --name nginx -d nginx\n数据存储\n因为数据就如同水一样应用服务缺失了数据也就失去了它的意义所以数据存储尤为重要。数据库的选择静态资源的管理备份等。数据存储备份还可以减少数据损失造成的价值损坏最小化。\n\n小心使得万年船常备份多备份\n\n数据库\n数据库简而言之可视为电子化的文件柜——存储电子文件的处所用户可以对文件中的资料执行新增、截取、更新、删除等操作。所谓数据库是以一定方式储存在一起、多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。\nMySQL / MariaDB 哪个好?\n应用服务需要那个就用那个尽量选择通用版本。 MariaDB 是 MySQL 关系数据库管理系统的一个复刻,由社区开发,有商业支持,旨在继续保持在 GNU GPL 下开源。简单来说 MariaDB 就是 MySQL 的儿子。\n其他的数据库管理系统可以用么\n结合实际情况 虽然数据库管理系统千千万,但是常用的就是那几个呀。\n备份\n数据一样要多备份、常备份 所有云厂商的云服务器都提供了相对基础的数据备份,但是他们不会保证你的数据一定不会损坏丢失。所以可以通过以下方式低成本备份:\n\n下载备份电脑里。\n下载备份硬盘里。\n加密备份云盘里。\n\n总之就是一定要多备份常备份管它冷备、热备、异地多活总之就是多备份一定不会错。淘宝上 500GB 的机械硬盘 25 元左右一块,买 4 块回来都做成冷备;公司扔一块、学校扔一块、家里扔一块、老家扔一块,理论上来说数据全部丢失损坏的机率为 (2^4+N)≤6.25%。\n系统安全\n系统安全是老生常谈的话题了但是系统安全门槛高各种问题层出不穷最后也许你也不知道该怎么做好系统安全。基本从下面的两方面出发就可以快速杜绝大部分系统安全问题。\n网络防火墙\n网络服务最常用的端口例如22、80、443 等;如果你购买的是云服务器,那么你可以利用云服务商的防火墙管理面板只放开应用服务的端口。在使用 nginx 做代理的情况下,所有的应用服务基本都可以走 80 或 443 端口,那么服务器就可以只打开这两个端口,其他的包括 22 端口需要用到的时候再打开。Docker 容器模式下更可以使用网桥做内外网隔离,纵使攻击者进入了服务器,能进行的操作也只是有限的。\n最最最坏的一种情况就是全军覆没了。这种情况下如果你做好了完全的、充分的数据备份任由它随便攻击。\n无所谓 ~ 谁会爱上谁 ~\nDDOS\n网络攻击最有效最常见的一种方法就是分布式拒绝服务攻击DDOS。其目的在于使目标电脑的网络或系统资源耗尽使服务暂时中断或停止导致其正常用户无法访问。这种情况下我们可以通过使用 CDN 来隐匿云服务器真实物理 IP 地址,让攻击者找不到攻击目标从而放弃攻击。\n引用\n\n来源容器 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源Docker - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n\n来源拒绝服务攻击 - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n"},"Personal/Blog/2022/谈谈我的「数字文具盒」":{"title":"谈谈我的「数字文具盒」","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"最近耗费了一周的时间迁移服务器,升级打造 V3 版本的「数字文具盒」。从 2018 年第一次尝试搭建博客,期间尝试各种生产力工具到现如今的第三次迁移服务器,终于打造了一个完美契合,效率至上的数字文具盒。在这期间踩了无数大大小小的坑,折腾了一次又一次;虽然折腾浪费时间,但是依旧是收获满满。\n希望「数字文具盒」系列能帮到各位减少踩坑的几率并尝试打造、升级个人的数字文具盒。本文先从需求出发以提高生产力为导向再以数字基建、运行平台、软件服务三个层次来递进实现最终打造成适合的数字文具盒。\n\n适合自己的才是最好的\n\n需求\n\n博客 所有的一切源于第一场是搭建博客,通过博客也认识了更多网络上志同道合的博友。\n图床 为了更好的管理静态资源,更可以减轻博客未来的迁移负担。\n网盘用来给身边的朋友分享、下载文件。\ngit 托管: 个人代码的托管、镜像、同步。\nrss 订阅: 信息聚合窗口,其可以有效打破信息茧房。\n文件备份 平时工作、学习、生活中的文件异地同步备份。\n碎片笔记减轻第三方平台的依赖。\n书签管理减轻第三方平台的依赖。\n统计服务减轻第三方平台的依赖。\n密码管理器 这都二十一世纪了,密码管理器是人人都必须、人人都必要的生产工具!\n\n以上内容就是第三次升级罗列出来的需求加粗项目为务必实现的需求剩下的为非必要项目。\n目标\n以过程为导向\n如果你没有需要的专业知识或者经验不足从来没有尝试折腾过这些东西那么建议你参考我的经验然后花费有限的时间、精力成本去累积经验。并且在折腾的过程中善用搜索引擎、社区提问、深度阅读官方文档。\n\n这世上本没有路走的人多了便有了路。\n\n以结果为导向\n因为这次数据文具盒的升级打造我是整理好明确的需求来的更专注结果的达成所以在攒够了经验之后务必带着明确的需求去实现结果切勿一通乱折腾\n\n管他黑猫白猫抓到老鼠的就是好猫\n\n倡导\n如果在折腾的过程中你发现了一个新的并不存在于互联网上的问题那么恭喜你走在了其他人的前面。你可以尝试通过各种平台输出自己的经验贴为他人提供帮助创造一份属于自己的价值\n互联网精神即开放、平等、协作、快速、共享 。"},"Personal/Blog/2022/这个周末":{"title":"这个周末","links":[],"tags":["记忆/高中","博客/原创"],"content":"这个周末公司年会、老同学聚会。虽然没有在家躺尸(现在真得越来越懒了),但是蛮快乐滴 🤪\n公司年会\n疫情不断……然后公司的春节晚会就和年会一块举办了表演的节目也是笑点爆棚。期间抽了好多轮红包真的是一个都没有抽到。\n由于不是业务部门对公司业务数据汇报也没有兴趣关注一直在打瞌睡。\n开门红发了 88 元红包,况且算加班费(周六举办),很好奇是不是每一个公司都有家文化哈哈。\n\n\n老同学聚会\n高中同学聚会虽然虽然都是郑州的。但是大家都是在为生活奋斗着所以也是很少聚会……\n\n杯酒下肚大家就开始聊天了。由于生活不再有太多的交集所以便是老故事和将面临的婚姻居多。\n去年我们中已经有结婚的了这次聚会也是因为今年准备结婚提前联系告知一声。\n大家也都高中毕业好久了大学毕业也都步入工作了一年多了。所以都在面临婚姻这件事情不过大家的感情似乎都不顺利哈哈。\n结过婚的是没有出来所以无从得知哈哈。婚后的男人不如狗 🤣\n即将结婚的是俨然一副被生活蹂躏的样子。彩礼、仪式、酒店、车、房……\n单身狗是在赞份子钱和老婆本哈哈或者是在留恋前任……\n随着年纪的增长对于婚姻这件事。大家都在提家庭、彩礼、三金、酒店、车、房似乎再也不提感情了……\n酒饱饭足电竞酒店搞起\n\n小黄人永远的坑壁石头人大招抢人头锤死他了。\n玩了几把实在是输的惨不忍睹……\n\n打游戏的打游戏玩牌九的玩牌九。玩的倒是不亦乐乎哈哈哈请忽视裸男哈哈。反正只要是这一群老家伙无论干啥都很快乐。总之大家好像都变了又好像都没变哈哈哈\n玩到了凌晨三点头巨痛……不玩了不玩了\n早上起来发现有的小伙伴已经跑路回家了。睡到中午又一块去吃了个🐟然后跑路回家。\n路上送亮亮的途中吐槽他是个痴情种哈哈哈\n最后相约夏天有机会要一块去漂流美滋滋"},"Personal/Blog/2022/通货膨胀的猪":{"title":"通货膨胀的猪","links":[],"tags":["生活/随笔","博客/原创"],"content":"最近公司食堂饭的质量相对之前越来越差了,虽然我很理解物价飞涨,但是以前物价低的时候也没见你给我做的多好啊,万恶的食堂哈哈哈。\n那么通货膨胀的猪究竟是什么首先是通货膨胀虽然高中政治涉及到一些但是不多。根据维基百科《通货膨胀》的释义为「货币流通数量增加整体物价水平持续上涨人们的购买力下降的经济现象。」。猪不就是二师兄嘛国民第一肉类摄入忽高忽低的价格比油价还坑……\n2022 年 08 月 29 日根据《中国农业农村部》公布的《农产品批发价 200 指数》,畜牧产品和蔬菜分别涨了 0.76 和 3.82 个点,其采用的帕氏指数编制方法作为权重,我也是看不懂。只是知道终端价格涨了不少 ~\n\n因为蔬菜蛋奶类即使涨价也是极少数变态式的疯涨所以价格变化最明显的就是二师兄了。再加上身边朋友多从事养殖、屠宰、零售行业更能获得终端的一手信息。那么猪价究竟是由什么来构成的这个流通环节是什么因素会导致猪肉价格忽高忽低\n接下来我先简单叙述一下一只猪从诞生至餐桌的全流程。\n\n接下来咱一个环节一个环节的细细道来首先小猪仔出生时到成猪 200 天期间的费用,这一环节的损溢价由养殖场承担。\n\n养殖厂房一次投资费用固定每年小修小补开销不大影响因素为 1。\n人员工资劳动力市场丰富人员工资固定市场价格小幅度波动影响因素为 3。\n日常开销水、电价格每月固定数额上下浮动有限市场价格波动较小影响因素为 1。\n玉米饲料受天灾市场影响市场价格波动不稳定影响因素为 7。\n养殖损耗根据养殖场技术和效率以及不可抗拒的天灾决定抛去天灾因素影响因素为 5。\n猪仔价格小猪仔的来源有市场采购和自繁自育所以价格相对稳定影响因素为 3。\n贷款利息因为根据猪价格以及利润不可控所以利息浮动较大影响因素 5。\n政府开支初始建厂三年内费用较多后续费用开支稳定影响因素 3。\n\n这一闭环下玉米饲料、养殖损耗和贷款利息为最大影响因素虽然市场供需因素不可控但是国家对市场的宏观调控还是比较可靠的。紧接着就是屠宰场环节小型屠宰场最重要的就是现金流以及业务量了。\n\n\n屠宰厂房因为国家会倒逼整个行业的进步所以每年都需要投资新增设备厂房小屠宰场影响因素 0。\n\n\n人员工资影响因素 0。\n\n\n日常开支影响因素 0。\n\n\n······\n\n\n你是不是觉得很奇怪为什么都是 0 呢,因为屠宰场没有定价权,所以这些影响因素为 0那为什么养殖场有呢因为养殖场可以决定养殖数量所以可以拥有部分初始定价权毕竟赔本了我就晚会再卖嘛。\n如上所述如果各个环节保持相对稳定那么猪肉价格也会维持在一个稳定的区间。但是呢养殖场环境的影响因素不可能让猪肉价格翻倍的啊如果真的能我估计做梦都能笑醒。屠宰场更不用说了走的就是业务量和现金流。终端零售店就是打工人不要指望房东减租了哈哈。这样的话每个环节的费用和利润都是环环相扣的大家都是吃这一个蛋糕你多吃一点我就少一点但是蛋糕没变大啊所以当下的猪肉价格影响因素只有市场因素。\n事实也是如此一直以来影响猪肉价格的因素也只有市场因素这也是由市场经济体制决定的。下图是 2022 年 3 月份至 7 月份的生猪采购价格走势图。\n\n如果按照成猪周期是 200 天左右,也就是 7 个月左右。其他所有因素稳定的情况下,线性预测猪肉价格最快也要明年开春 3 月份左右才会回落。\n本文不具有科学性和普遍性只是个人的一些瞥见。我其实想说的不是这我想说的是工资工资工资5 个月猪头价格翻倍,我他妈工资没涨好嘛,一家四口每个月按照 20 斤猪肉的情况下,我要比之前多花一倍的价钱。\n不仅仅是猪肉好嘛油价、鸡蛋等等等虽然价格可以接受但是赤裸裸的剥削我等无产阶级。小猪仔我们养的二师兄我们杀的工作我们做的我们的购买力就莫名其妙的降低了\n最后也告诫我们一个道理追求可以把握的优质资产学会理性消费并且控制财务开支。"},"Personal/Blog/2022/闭门锁网":{"title":"闭门锁网","links":[],"tags":["生活/感悟","博客/原创"],"content":"最近临近天朝高层会议,公司也迎来了网安大队的检查,网安大队来了不少人,掺带着三方公司的技术员。简单询问了一些问题,并告诫临近会议不要出乱子,随后三方公司的技术员象征性的扫了扫漏洞。\n其中一位警长深有意味说道我们来不是吃拿卡要的是为了保护人民、企业信息财产安全。有点那种去嫖娼不是犯法而是为了救济失足少女挽救背后成千上万的家庭哈哈哈。因为我们上了等保所以问题不大。\n前辈说 2019 年以前公司信息安全一度是裸奔状态,只有简单的杀毒和域控。后来国家《网络安全顶级保护 2.0》标准实施,集团信息总部将其列入了工作重点后;于 2021 年 12 月开始试点上线等保 2.0,并于 2022 年 6 月份正式上线。\n等保 2.0 是什么\n简单来说等保就是国家对于信息安全出台的一项标准等保 2.0 是于 2019 年开始正式实施,其简单来说有 5 个等级,主要基于信息系统受到破坏后,所造成的影响来划分的。\n\n自主保护级一般适用于小型团体信息系统遭到破坏后不损害国家安全、社会秩序和公共利益。\n指导保护级一般适用于对信息安全有要求的中大型团体信息系统遭到破坏后对社会秩序和公共利益造成损害但不损害国家安全。\n监督保护级一般适用于地市级以上国家机关、企业、事业单位内部重要的信息系统信息系统遭到破坏后会对社会秩序和公共利益造成严重损害或者对国家安全造成损害。\n强制保护级一般适用于国家重要领域、重要部门中的特别重要系统以及核心系统。信息系统受到破坏后会对社会秩序和公共利益造成特别严重损害或者对国家安全造成严重损害。\n专控保护级一般适用于国家重要领域、重要部门中的极端重要系统。信息系统受到破坏后会对国家安全造成特别严重损害。\n\n内网与外网\n内网就是内部专用网络简单理解家里的 wifi 就是内网,仅限于当下环境的网络通讯,外网可以简单理解为互联网;互联网的雏形就是基于内网衍生出的。虽然互联网精神自始贯彻开放、平等、协作、快速、共享,但是现如今越来越拉闸。\n微信与小程序\n微信是国民级通讯工具小程序现在哪里都是遍地都是干啥都离不开这俩。微信还算好可是这小程序究竟是什么鬼……\n大部分浏览器下运行开发者工具就可以看到该网站的全部源码做了什么操作都一览无余。这也秉承了互联网的开放精神可是你微信一个通讯工具有啥功能放在网页不好吗再内嵌一个小程序浏览器美名其曰方便用户扫个码点开就能用可是我以前打开浏览器输入网址什么都可以访问啊\n小程序违背了互联网的精神产品经理一拍桌子就做出来的东西感觉好牛批背地里强奸用户。这种内网不要也罢微信公众号也是就连很多网站也是最基本的注册都不提供了必须微信登录。\n各大网站的跳转 APP\n手机上打开个网站就连 TM 的颜色网站也请你安装 APP然后继续访问。就不说各大流氓厂商了更是毛都没有你有毛么\n例如知乎、CSDN 等等,内容难道不是各位创造的?各位既然都无私地放在互联网上了,我 TM 看还得下载个 APP然后注册用户否则无法享受全部功能。商业产品是为了挣钱这啦哪啦毕竟都不能靠爱发电是吧\n这都别提互联网精神了妥妥的互联网流氓、碧池。敢问你们当初不就是靠着互联网起家的吗\n公网 IP 与 ICP 备案\n各大网站提供地平台确实方便大家可以相对自由的分发、共享互联网资源。可是运营商你给我开放个公网 IP 不就完事了?我自己搭个博客,搞个聊天室,整个论坛不也是香饽饽的?\n现在是你就算买了云服务、申请了 ICP 备案,也是这不能说,那不能说。还不如回到原始人时期,让我站在山头吼两嗓子。\n抖音推送和信息茧房\n抖音也是喜欢看什么就给你推什么也是存在内网与外网。例如你是上海人估计挺难刷到新疆人的抖音公共热点外网也是每个人都能刷到的。\n权威媒体的推送更是让我们没有了思考能力更不提理解力了说什么你听着就好了。\n天朝网与世界网\n不多 BB 了,我最痛恨至极的就是访问 GitHub 和 Google 以及包管理器拖库,哎西吧,毁灭吧世界!!!\n最后的最后\n我只是简单发一下牢骚并不是抨击祖国任何事情都是具有多面性的\n最初互联网的诞生带来了生活方式的改变但是现如今商业化公司的跑马圈地与互联网精神越来越背道而驰原本互联网精神带来的信息资源本就是开放的、无限复制、随处共享的但是某些人似乎并不想让我们享受这些。\n不仅仅是因为在天朝这种《特色》意识形态下孪生出了无数《特色》的事物。就连外部的互联网世界也在发生着巨大的改变大部分信息资源紧紧攥在少部分人手中"},"Personal/Blog/2022/非黑即白":{"title":"非黑即白","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"上学的时候我特别喜欢数理化这些科目,因为这些科目对就是对、错就是错,然而文史类科目需要你 get 到它的点,然后由老师主观的评分;所以我当时偏科极其严重。\n生活中也是如此青少年时代的叛逆、懵懂无知、无畏无惧。固执偏见只坚信自己的“道”并认为其他都是错的淋漓尽致的展现着年轻人的棱角。后来的碰壁让我开始思考并且深刻认识到非黑即白之间还存在无尽的灰色地带。\n我停留在这个黑白灰认知很久以至于深深的认为并不存在所谓的白。一叶障目不见泰山当我们认定一件事情的时候我们的思想就会变得很片面。\n步入社会以后随着阅历的增长加上生活的锻炼开始慢慢的认识并打破了这个观点。生活不仅只有黑白灰其充斥着各式各样的色彩更夹杂着无数的中间地带。其没有所谓的标准答案更没有非黑即白。\n唯一能做的就是做一个不那么错的选择仅此而已。"},"Personal/Blog/2022/首页加载速度优化方案":{"title":"首页加载速度优化方案","links":[],"tags":["开源项目/Redemption","博客/原创"],"content":"自己一条龙研发的 Halo 博客主题 Redemption 最近也是发布了首个正式版,在博友 杜郎俊赏 提供的 CleanCSS 工具下麻溜地搞定了,同时又添加了一些自己的想法。主要思路是首页做减法:删减无用代码文件、压缩静态资源体积,同时完全不影响首页的内容展示。\n问题场景\n\n如上图博客首页未优化的加载速度需要 2.03 秒并且存在可优化的余地。优化方案主要从静态资源、样式表、字体这三个方面出发。整套操作步骤下来,实测速度提升了近 5 倍。\n0.内容分发CDN\n傻瓜式优化就是 CDN各个云服务厂商都有提供。最简单最省事最有效CDN 具体优化步骤可根据厂商提供的文档操作。(有的要钱有的不要钱,有的好用有的不好用)\n1.静态媒体资源\n\n首页如果有媒体资源例如图片、Logo 等。那么最简单的方法就是压缩图片体积,便捷高效的提升首页加载速度。\n2.CSS/JS 代码\n如果想优化 CSS/JS 代码文件,可以尝试在博友 杜郎俊赏 提供的 CleanCSS 中一键优化代码。\nCleanCSS 第一次直接优化了之后提升明显,但是发现 remixicon.css 字体图标有问题。然而这个优化还是最大问题,毕竟加上字体 1.3s,遂又找了其他方法实现(后来发现是我没用明白 CleanCSS 🤣)。\n后来在 GitHub 上找到开源项目 UnCSS ,其提供了简单的在线优化,使用了一下满足需求足够用了。最后再利用在线 CSS/JS 压缩体积工具,就大功告成!\n\n3.优化字体\n常见的优化就是 CDN、静态资源、CSS/JS 代码,这里我为了追求更极致的速度,将字体文件也进一步优化。优化方向稍微偏激了,根据实际情况来。\n因为 remixicon.css 的字体图标文件只用了几个,所以我利用 Github 上 font-spider 将无用的字符进行删减。如下图所示可以发现,字体删减优化是质的改变,体积缩减了近 70 倍!\n\n优化后\n\n在特定问题场景下通过一套操作优化后的首页体积仅仅 35kB加载时间 597 毫秒。就连 CDN 都不用套,全国平均访问延时 0.6s。需要注意的地方是,优化字体比较偏激可能导致页面显示不正常。其次我为了避免其他页面出现未知错误,利用代码进行判断仅仅对首页进行了优化。\n现在 H5 的 CSS 样式库越来越多了,网页效果越来越优美了,同时也变得臃肿了起来。不过只要网速快,优化个毛线!奥里给!!!"},"Personal/Blog/2023/2023-年度微信读书报告":{"title":"2023 年度微信读书报告","links":[],"tags":["博客/原创","年度/2023"],"content":"2023 年阅读量显著提升,不过主要是技术类书籍。\n对于 2024 年,我计划拓宽阅读的种类,并致力于写读书笔记。 同时设定一个小目标:阅读 365 小时!\n🥸🥸🥸\n\n"},"Personal/Blog/2023/Docusaurus-搭建":{"title":"Docusaurus 搭建","links":[],"tags":["开源项目/数字文具盒","博客/原创"],"content":"Docusaurus 是一款静态站点生成器。 可以搭建带有快速客户端导航的单页应用,充分利用了 React让你的网站具有交互能力。 它提供了开箱即用的文档功能,不过也可用于搭建各种网站:个人网站、产品、博客、营销主页等等。\n当下个人知识的整理归纳已经及其重要了废话不多说。可以先体验一下我的个人 wikiwiki.7wate.com/,相信我你一定会爱上它!\n安装\n\n\nDocusaurus 官网\n\n\nDocusaurus 官网(中文版)\n\n\n因为中国官网文档更新相对滞后所以这里推荐使用英文官网进入后选择中文。\n环境\n\n\nNode.js (中文网) v16.14 或以上版本\n\n\n本文使用 Docusaurus 2.0.0-rc.1 作为演示\n\n\n初始化\n使用命令行工具可以帮助你快速简单地安装 Docusaurus 并搭建网站框架。 你可以在空仓库或现有仓库的任何地方运行这个命令,它会创建一个包含模板文件的新目录。\nnpx create-docusaurus@latest my-website classic\n项目结构\n命令行工具成功运行后你将会在新目录 my-website/ 下看到下列文件:\n \nmy-website\n├── blog\n│   ├── 2019-05-28-hola.md\n│   ├── 2019-05-29-hello-world.md\n│   └── 2020-05-30-welcome.md\n├── docs\n│   ├── doc1.md\n│   ├── doc2.md\n│   ├── doc3.md\n│   └── mdx.md\n├── src\n│   ├── css\n│    └── custom.css\n│   └── pages\n│       ├── styles.module.css\n│       └── index.js\n├── static\n│   └── img\n├── docusaurus.config.js\n├── package.json\n├── README.md\n├── sidebars.js\n└── yarn.lock\n \n\n\n/blog/:包含博客的 Markdown 文件。\n\n\n/docs/:包含文档的 Markdown 文件。\n\n\n/src/:如页面或自定义 React 组件一类的非文档文件。\n\n\n  - /src/pages - 所有放在此目录中的 JSX/TSX/MDX 文件都会被转换成网站页面。\n\n\n/static/ - 静态目录。\n\n\n/docusaurus.config.js - 站点配置文件。\n\n\n/package.json - Docusaurus 网站是一个 React 应用。 你可以安装并使用任何 npm 包。\n\n\n/sidebars.js - 由文档使用,用于指定侧边栏中的文档顺序。\n\n\n运行网站\ncd my-website\nnpm run start\n默认情况下浏览器会自动打开 http://localhost:3000 的新窗口。\n\n项目构建\nnpm run build\n网站内容会被生成在 /build 目录中,随后可以被上传到 GitHub Pages、Vercel、Netlify 等静态网页托管服务。\n配置\n配置文件为项目目录下 docusaurus.config.js配置字段官方文档点击打开。\n一定要参考官方文档因为项目组贡献者有一位厉害的中国大学生所以中文文档更新很及时。\n设置中文\ndocusaurus.config.js 中找到 i18n 配置节点,如下是原配置(其实看得懂英文就知道咋改 🤣):\n// Even if you don't use internalization, you can use this field to set useful\n// metadata like html lang. For example, if your site is Chinese, you may want\n// to replace "en" with "zh-Hans".\ni18n: {\n  defaultLocale: 'en',\n  locales: ['en'],\n},\n \n修改为如下配置设置为中文\ni18n: {\n  defaultLocale: "zh-Hans",\n  locales: ["zh-Hans"],\n},\n \n搜索\n在使用官方插件中 Algolia DocSearch 搜索时候,会有几率踩坑,可以参考我的部署经验。\n\n\n正确启用 sitemap 插件参考文档sitemap 插件。\n\n\n正确启用 Algolia DocSearch 插件参考文档Algolia DocSearch 插件。\n\n\n构建项目确认插件是否显示。\n\n\n注册账号\n在 Algolia官网 注册账号后,打开控制台新建数据源,填写数据名(后面会用到),并选择免费计划。\n\n\n获取 API Keys\n控制台打开设置页面点击 API keys拷贝 Application ID、Search-Only API Key、Admin API Key。\n\n\n配置 Docusaurus\n打开项目配置文件 docusaurus.config.js填写如下配置\nmodule.exports = {\n  // ...\n  themeConfig: {\n    // ...\n algolia: {\n  apiKey: "Search-Only API Key",\n  appId: "Application ID",\n  indexName: "数据源名称",\n },\n  }\n}\n推送数据\n由于 Algolia 限制开源项目才可以免费试用爬虫,所以我们要自己推送数据。需要如下环境:\n\n\nDocker谷歌一堆安装教程\n\n\njq使用包管理器直接安装\n\n\n环境安装好以后按照如下步骤操作\n1. 新建 .env 文件(键值不带双引号)\nAPPLICATION_ID=Application ID\nAPI_KEY=Admin API Key\n2. 新建 docsearch.json爬虫配置文件\n{\n  "index_name": "wiki",\n  "start_urls": [\n    "wiki.7wate.com/"     # wiki 网址\n  ],\n  "sitemap_urls": [\n    "wiki.7wate.com/sitemap.xml"  # sitemap.xml 地址\n  ],\n  "stop_urls": [\n    "/search",\n    "/v3me",\n    "/playground",\n    "/inspector"\n  ],\n  "sitemap_alternate_links": true,\n  "selectors": {\n    "lvl0": {\n      "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",\n      "type": "xpath",\n      "global": true,\n      "default_value": "Documentation"\n    },\n    "lvl1": "header h1",\n    "lvl2": "article h2",\n    "lvl3": "article h3",\n    "lvl4": "article h4",\n    "lvl5": "article h5, article td:first-child",\n    "lvl6": "article h6",\n    "text": "article p, article li, article td:last-child"\n  },\n  "strip_chars": " .,;:#",\n  "custom_settings": {\n    "separatorsToIndex": "_",\n    "attributesForFaceting": [\n      "language",\n      "version",\n      "type",\n      "docusaurus_tag"\n    ],\n    "attributesToRetrieve": [\n      "hierarchy",\n      "content",\n      "anchor",\n      "url",\n      "url_without_anchor",\n      "type"\n    ]\n  },\n  "js_render": true,\n  "nb_hits": 856\n}\n3. 运行 Docker\ndocker run -it --env-file=.env -e "CONFIG=$(cat docsearch.json | jq -r tostring)" algolia/docsearch-scraper\n\n如果数据抓取异常推送到 algolia 的索引条目过少。可以尝试多次运行 Docker即可解决。至于为什么我也不知道反正就能搞定 ~\n总结\n如果想要稳定运行项目请务必一定仔细阅读官方文档。官方文档维护的相当好主要就是 algolia 搜索哪里,刚开始很容易无从下手……\n因为被 Docusaurus 官方 Showcase 收录了,所以产出一篇文章推广一下 ~\n更多优秀 Docusaurus 站点请访问:展示站点"},"Personal/Blog/2023/Obsidian-使用-Templater-插件的个性化脚本":{"title":"Obsidian 使用 Templater 插件的个性化脚本","links":[],"tags":["生产力工具/Obsidian","开源项目/数字文具盒","博客/原创"],"content":"Templater 是 Obsidian 的一个模板插件,它定义了一种模板语言,可将变量和函数结果插入到笔记中。它还将允许执行 JavaScript 代码来操作这些变量和函数。\n\nTemplater 仓库\nTemplater 文档\n\nTemplater 插件允许执行用户个性化脚本,我基于 Templater 利用 ChatGPT 开发完善了三个脚本,简单分享一下,最终实现日志自动获取每日天气,月相,每日诗词开发的三个小脚本,实现效果如下:\n\n\n每日天气基于 wttr 的天气获取,可自定义城市、参数。\n每日诗词根据时间、地点、天气、事件智能推荐诗词。\n每日一言基于一言获取每日随机美句。\n\n/**\n * 获取指定城市的天气信息\n * @param {string} city - 城市名\n * @param {string} params - wttr.in 的查询参数\n * @returns {Promise<string>} 天气信息\n */\n \n郑州 +31°C ⛅️ \n \n \n/**\n * 获取今日诗词并格式化输出\n * @returns {Promise<string>} 返回格式化后的诗词\n */\n \n接天莲叶无穷碧映日荷花别样红。——杨万里宋代\n \n/**\n * 获取一言\n * @param {Object} options - 请求的参数\n * @returns {Promise<string>} 返回一言的句子\n */\n 明明只是活着,哀伤却无处不在…\n \n脚本地址\n\nWiki 仓库 src/js 目录下\n\n\n使用方法\n\n前置条件脚本载入成功可以正常刷新出来。\n模板文件中使用脚本函数可以参考我的 Wiki 项目目录下的 Templater 文件夹\n\n\n"},"Personal/Blog/2023/YubiKey-漂流记":{"title":"YubiKey 历险记","links":[],"tags":["写作/测评","博客/原创"],"content":"2022 年 9 月 29 日 CloudFlare 与 Yubico 开展了周年活动合作,可以为用户提供最低 10 美元购买 YubiKey 5 的机会。 YubiKey 活动力度这么大,啥也不说了赶紧上车。\nYubiKey 是一种小巧安全的令牌,主要用于两步验证和数据加密。对于 YubiKey 从功能上简单来说就是类似于银行的 U 盾,但是 YubiKey 相较于 U 盾拥有更多的功能。YubiKey 支持多种验证协议FIDO U2F 和 FIDO2 协议可以用来登录网站和应用程序;而 Yubico OTP 协议可以用来生成一次性密码OpenPGP 和 PIV 协议可以用来加密数据和电子邮件。\n虽然 YubiKey 适用的场景非常广泛,但是在国内却是非常小众的产品,只有相关的技术爱好者才有所了解。国内目前清华大学技术团队推出了 YubiKey 的替代品 CanoKeyCanoKey 的目标是从零开始再造一个 YubiKey即支持 OpenPGP、PIV、TOTP、FIDO 等多种功能的安全密钥。目前 CanoKey 的实现和文档都在 GitHub 上公开,并已经经过了小规模的生产测试。\n我呢说实话听都不想听到这些乱七八糟的协议更不用提给各位科普这些乱七八糟的协议了。但是这次 Yubico 的活动实在是太具有诱惑力了,没有需求也要创造需求!简单记录分享一下顺丰转运的过程。领取优惠码什么的都不唠叨了,主要就是关于电子产品的转运。\n\n总之因为各种各样的原因YubiKey 属于对华禁运产品,主要的坑在于 AES 申报,有可能会被拒单,然后就很恶心了。我也是在阅读了很多经验帖后,优惠码马上到期的时候选择顺丰国际上车的。总的来说大部分常用的转运都可以运回,但是时效特别长,甚至有的需要两个月才可以。顺丰国际转运有概率被 AES而且运费偏高一定被收税。\n\n12 月 10 日Yubico 提交订单。\n12 月 21 日Yubico 订单发货。\n12 月 23 日:到达顺丰国际美国仓,收货处理中。\n12 月 24 日:出库资料审核中。\n12 月 28 日:顺丰出库。\n12 月 31 日:美国纽约分部航班起飞。\n1 月 9 日:抵达口岸,清关完成。\n1 月 10 日:收到 YubiKey\n\n\n刚刚好花费了一个月的时间也算是正常的速度。关于是否会被 AES 的问题,只能说有概率。全程顺丰转运快递费 83 元,税费 63 元(共产主义好);算下来总共花费 458 元,平均每个 115 元。咸鱼包邮 190 元一个,还是嘎嘎的香呀。目前 YubiKey 相较于 CanoKey 产品成熟度更高,淘宝上 CanoKey 是 169 元包邮,想要了解的可以尝试一下。\n\n转运经验帖Yubikey 5C NFC SFBUY 顺丰转运 全流程体验分享 - 问谛居;仅引用,著作权归作者所有。\n"},"Personal/Blog/2023/不要把幸福建立在别人的痛苦之上":{"title":"不要把幸福建立在别人的痛苦之上","links":[],"tags":["博客/原创","成长/个人"],"content":"我们经常讨论三观,常常被问及关于是非对错的看法,可是如果真的深入展开讲讲又不知从何说起。长久以来我也非常想深入探讨一下个人价值观。何为是非对错,以及如何在生活中把持这杆秤。\n在这我相信很多人都是起始于二极管式的黑白判断——对就是对错就是错容不得半点马虎。然而在成长的过程中我们不可避免地会接触到灰色地带我也曾因此感到迷茫。直到我领悟到世界不仅仅是黑白灰更多的是五颜六色的世界。毕竟人间自有真情在宜将寸心报春晖。\n小时候我总是在问什么是对的什么又是错的我坚信万事万物终有对错都应该有一个标准答案。在《你愿意嫁给自己么?》我有提到,从小特别不擅长语言类科目,为何极其热爱数学——因为它总能给我一个确切的答案。并且如果一旦做错选择,那么我就会陷入深深的懊悔,开始内耗。可实际上,生活中的选择和决策远比数学题复杂,它们往往没有标准答案。我们处在的每一个时间节点都受限于时间、空间和认知的局限性。毕竟,一叶障目,怎见泰山?\n我的这种认知第一次受到挑战是在我了解到实际现象的复杂性时。以前家乡因经济条件受限听说一些家庭无法正常娶妻生子于是这种环境催生了买卖妇女儿童的需求。从法律和道德的角度来看这无疑是错误的。但假设卖方愿意被卖方也接受虽然本质上是一场金钱交易可结果却是双方都接受这一交易。这让我开始怀疑之前坚定的黑白判断是否过于简化了人性的复杂和社会的现实。以及后来看到有些买来的妇女和家庭其乐融融我也不禁开始怀疑自己。\n学生时期我也有遇到过大大小小不公平的事情以及步入社会遇到的各种人情世故让我进一步意识到事物的多面性。每一个决策和判断都不可能仅仅分为对错而是需要在复杂的社会背景和个人经历中进行权衡。例如前段时间分享的 V2Ex 老哥由于其纯粹的性格,与新工作的职场环境格格不入,最后闹得大家都不欢喜。我相信,大多数人也曾遇到过类似的事情。我逐渐意识到,万事万物似乎没有天平可以衡量,更像是一个跷跷板,时而上时而下。在动态发展中的事物,用绝对的眼光去衡量是不可能的。\n我曾陷入黑白灰价值观很久甚至以为掌握了人世间的法宝想用它去敲打每一个人。\n工作后我开始见山观海看世界。不断的经历和体验让我看到了同一个世界处于不同时空的众生相。特别是年初的川西之旅短短几天跑了万里路体验了许多人的生活。这不是我第一次了解文化的差异毕竟山在哪里和山在眼前天壤之别。\n在旅程中我体验到了完全不同的文化习俗。比如云南丽江纳西族的男士在家带小孩而女士在外为生活拼搏奋斗。川西路上步行前往拉萨的藏民他们的虔诚信仰深深触动了我。还有骑行者沿 318 国道前往拉萨,我也曾梦想着骑行 318。河南延津的戍边英雄肖思远他清澈的爱只为中国。这些五彩斑斓的众生相击碎了我过去的黑白灰世界观。\n是啊如果你只认为存在黑、白、灰总有人会用纯粹的信仰、爱来挑战你的观点。那么究竟什么样的价值观才能让我们少走弯路呢我不断思考询问朋友但每个人的回答都不尽相同。有人说做大家都认为对的事有人说在对的时间做对的事还有人说只有做错了才知道什么是对的。\n有一次我和女朋友争吵后冷静下来思考这并不是第一次恋爱为什么感情中还是容易发生争执可是感情中除了原则性问题其实并不存在绝对的对错。每个人从小的原生家庭、教育经历、生活阅历加上经历的磨难构成了独一无二的个体。我喜欢苹果给喜欢梨的你一个苹果期待你接受我的爱。但你却在想为何不是梨\n有些人早早辍学打工养家我们可能会说他们应该追求更多。但对他们来说能够维持家庭的基本生活已是成功。还有一些人苦学十八载最后 996 工作,我们可能羡慕他们的收入。但对他们来说,这样的工作可能充满了无声的苦楚。\n生活中的决策和判断往往不可能简单分为黑白灰也不存在绝对的是非。事实上很多问题复杂多变涉及多种因素和不同角度。世界上超过 70 亿人口,近 200 个国家,超过 5000 种地方语言,成千上万种文化习俗,更难区分所谓的是非对错。\n我们唯一能做到的是不要把幸福建立在别人的痛苦之上。虽然运动是物质的基本属性但人生每个阶段的幸福本质上是内心的充盈和精神力的富足。一定会有人反驳我也没有选择把快乐建立在别人的痛苦之上可是别人的选择却给我带来了的痛苦那我应该怎么办\n我们应该向内修心向外求助。充分理解当下社会的公序良知借助法律和道德的力量。毕竟除了身体上的痛苦大部分的痛苦源于认知的局限我们内心应向善向美。如果无法自行解决就寻求家人、朋友、教师或社会的爱心帮助。虽然可能遇到一两个坏人但并非所有人都是坏人。\n我们的决策不仅影响当前还潜移默化地塑造长期的影响。像那些一出生就在富裕家庭享有优质教育和资源的人他们可以先睹为快地看看这个世界。你可能羡慕他们的选择自由但其实你也可以放心大胆地去追求你的梦想只要切记不要把幸福建立在别人的痛苦之上。同时一路上我们也不能总是只追求果而忽略了过程中最重要的因。\n《你愿意嫁给自己么》是我对内心的审视一份关于内在价值观的导向。而《不要把幸福建立在别人的痛苦之上》则是对外部世界的价值观导向。实际上并没有一个标准的价值观。我认为我们应该首先让自己内心充盈精神富足坚信真善美。同时进一步理解全球主流文化尊重非主流文化包容弱小群体。\n最后我们应执着于理想纯粹于当下不在别人的痛苦之上寻找幸福。"},"Personal/Blog/2023/为什么不推开那扇门?":{"title":"为什么不推开那扇门?","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"最近下班后发现了一件很有趣的事情,情况如下:我在七楼工作,每天中午下班后都是走着步梯下楼。楼梯尽头一层有一个右拐角,再由楼梯门可到达大厅内打卡位置。由于楼梯门为一对门,可能是因为设计原因或别的缘故,反正经常只有一扇门打开,所以道路突然变窄,就造成每天下班的人流在这里堵塞。\n我就纳闷了为啥不能把另一扇门也推开呢就是有些人宁愿排队宁愿等都不愿意用手指头戳开它。可能是有些人认为那一扇门打不开可能是有些人根本就没有意识到这个问题可能是有些人坐着电梯下来从来不知道有这扇门。就算有人打开了这一扇门也并不会有人注意到它可能会感觉今天怎么不堵了。它好像是薛定谔的猫一样处于一种叠加态除非哪天另外的一扇门也关上就会有人发现最初只打开了一扇门。\n当初在郑州疫情放开管控一个月后我们公司领导层都未决定放开管控。原因是公司作为大型医药流通企业必须保证药品流通供应承担应有的社会责任但是集团内部论坛上充斥着种种骂声。大环境如此纵使不放开管控谁又能拒绝感染呢不出所料公司上上下下将近两千个人在三天之内几乎都被感染。就这样公司都不放开管控后来为了稳定情绪一些距离很近的回家了其余不能回家的如果坚持发烧上岗体温不低于 38.5°,每人每天奖励 100 元。\n疫情感染过后临近年底物流子公司的业务繁忙公司领导要求所有部门去仓库支援。并且口头保证将根据出勤次数奖励现金。部门老同事说这都是老传统了一边劝着你去一边自己又不去人力资源部门最后统计支援出勤次数各位同事又是积极证明自己去了多少次甚言不信看监控但人力资源部门表示仅奖励支援次数最多的 1000 元,于是又有人恨自己去的次数少了。\n随着时间的推移这些事情似乎像并没有发生过一样不再被人所提起。\n我受限自小成长的环境争强好胜的心理格外强烈什么事都爱拔得头筹。当取得了某种成就并站上了一个新台阶时总是喜欢指点一二的。因此当时我特别喜欢改变别人比如同学啊田径队友啊甚至女朋友啊亲人啊等等就像哥伦布发现了新大陆一样开始到处奔走相告传递新思想。我很偏执地认为人生必须要追求生命的意义创造生命的价值你应该怎么怎么样去做你这样做不行。以至于到处碰壁头上磕满了包或许叫醒人的只有南墙吧。\n下学踏入社会求职工作伴随着阅历的增加、智慧的充实。我开始变得越来越理解每一个人所处的环境和社会阅历都不一样认知也是大相径庭。我凭什么把一株小草变成参天大树更甚至我凭什么让大树有花香我就想吃一口苹果你给我说葡萄多甜多甜可我就想吃一口苹果。她可能已经很开心、快乐、幸福了但是我对她说离开这个浪浪山外面会更美好。\n楼梯拐角处的那一扇门可能不仅仅是我觉得只有一扇门是开着的或许哪一天我路过的时候也不会看两扇门是否同时开着。公司领导层对员工不尊重的决策和赤裸裸的剥削只需拿 100 元便可以弄人性。对我来说,这是一种极致傻逼,但或许有一些人每月还清房贷本来就不剩多少钱,还可以多花 100 元来改善自己的生活。默默恨自己支援次数不是第一的人,或许存了一年钱就差这 1000 元买到心仪的相机。\n这世间万物终究是让花成花让树成树。子非鱼安知鱼之乐但人啊难得糊涂更难得一世糊涂。"},"Personal/Blog/2023/你愿意嫁给自己么?":{"title":"你愿意嫁给自己么","links":[],"tags":["生活/感悟","博客/原创","成长/个人"],"content":"去年和朋友一起露营野炊的时候,发生了一些事情,让我对感情和婚姻的意义产生了深思,当时朋友 A 刚刚离婚不久后,却又快速奉子成婚;而朋友 B 也时常抱怨婚后生活的琐事。\n这些事情让我在想你愿意嫁给自己么\n让我从我第一次真正意识到自己的时候说起那大概是在我十岁左右我开始真正意识到自己是谁、爸爸妈妈是谁、我们住在哪个庄、世界是什么样子。\n我从小就有点聪明当时是村里优秀的孩子。然而我从小却似乎缺乏感知力对于语文和英语的学习一直难以把握其中的抽象概念。就导致我的成绩忽高忽低可爸妈对我要求非常高于是就总是会有矛盾冲突。可是包括老师他们真的以为我都懂认为我态度不行没有好好学习。\n于是我就成了那个谁都想锤一下的钉子。我也努力尝试学习过语言科目但我凡事都想问个为什么于是就导致根本无法理解抒发了什么什么感情写了十篇作文就有八篇跑题。\n如果无法形成正反馈就只能不断迎接负反馈的挑战。爸妈的原生家庭也都有缺陷同时还带有些许封建色彩。再加上家里物质条件不好生活带来的各种家庭矛盾经常上演。我就成了个受气包整天担惊受怕不敢回家以至于噩梦连连。就连老妈也时不时恐吓我学习不好就丢出去更是大半夜把我锁到家门外以至于寒暑假都不能和我的小伙伴一起玩耍。\n不过回忆起小时候最快乐的时光斌蛋香蛋猪头航蛋我们几个曾在一起度过了非常快乐的童年时光。\n斌蛋年龄比我们都大小时候个子最高是一个爱吹牛的孩子王。因为他有三个姐姐所以每次都能拥有令我们羡慕的玩具和零食。香蛋和我一样大小时候做事横冲直撞但是很单纯每次我们一起玩都离不开那标志性的小电驴和虎子还有他那喜欢留一大串鼻涕的小外甥。猪头和航蛋比我小比较喜欢和我一起玩。后来斌蛋和香蛋去登封武术学校就剩我们仨一起放羊打扑克。那时候我们疯狂痴迷一款叫洛克王国的游戏为了刷级我第一次接触编程开始尝试编写游戏外挂。后来无意发现了个 BUG直接导致游戏停服一天……\n由于学习成绩时好时坏我的这些快乐就无法正常续期。特别是那时候的我根本无法理解如何消除抹去这些负面情绪。于是在家庭环境的影响下种下了叛逆、偏执的种子。同时由于缺乏和谐、亲密的家庭环境导致我很渴望亲密的关系以至于后来间接导致了早恋。\n终于要上初中了终于不用在家担惊受怕了我暗自发喜。一开始学习成绩还是很好的但后来因为早恋、叛逆成绩直线下滑。我也不知道为什么会早恋可能是青春期的懵懂吧总之就是我很沉溺于那亲密关系。于是年少时的我就开始了一场青涩、懵懂、无知奇奇怪怪的早恋行为完全被情绪所驱使。\n现在回过头来看当时物质上的缺乏精神世界的贫瘠加之环境的影响和塑造即使再来一次我依旧也会犯错。而且家庭成绩老师早恋之间逐渐形成了无法调和的尖锐对立。自始至终我也不知道该怎么办内心充满了抗拒各种矛盾的爆发导致叛逆的种子彻底发芽。\n我做了些什么为什么所有人都要管我\n后来稀里糊涂地进了高中后就彻底放开了自我。逃课、玩手机、翻墙上网、抽烟喝酒、打架斗殴除了不好好学习我什么都干。后来还通过好哥们加入了校田径队美曰其名训练实打实逃课。每天就是吃吃喝喝、打打篮球、逃逃课、谈谈恋爱那时候可谓是我年少时候最快乐的日子。\n甚至高中也谈恋爱了……\n但现在我觉得高中时期的恋爱更多的是一种带着恋爱名义的社交。幻想对方也许就是彼此的命中注定稀里糊涂的认识老脸一红的在一起加之莫名其妙的争吵最后又稀里糊涂地分开。那时候家庭条件有所改善相对以前不再显得那么局限。然而我的精神世界依旧贫瘠早恋的经历以及年少时的心结未解。使我对于成家结婚拥有了近乎癫狂的执念。\n后来一天一天地临近高考说实话我也不知道未来干什么学学不进去整天就只锻炼身体了。不过有一说一我个人身体素质还是蛮不错的体育高考还过了线不过也就在这时候认识了如梦。当时如梦是一个很奇奇怪怪的女生刚开始在一块也很幸福。不过后来我近乎病态地执着于结婚导致我们彼此互相伤害渐行渐远。其实如梦没什么大问题只是我从小淤积的情绪、经历、执念迎来了爆发的时刻而我更不能奢求她能照亮我的人生。\n当时大学是牧院的计算机专业学校也不是很好。我也犯了象牙塔里每个人都会犯的错误极度的理想主义。毕业后上工地下工厂兼职临时工啥都干无所不尽其能。最后我选择折返和老爸创业更是一路艰辛险阻与此同时我和如梦也分开了。那段时间真是极致的痛苦……\n现在客观地看待当时众多问题的核心原因在于我缺乏独立的人格导致我一把好牌打得稀烂。\n我不想在这待了。在山里喂了两年羊后我最终还是选择了走自己的路。经过一段时间的过渡期间也做了很多傻事最终来到了现在的公司满心期待的开始了这份工作。这是一份正式稳定的工作也让我有机会去看看这个世界体验他人的生活。后来的疫情导致我也没得选择于是我就开始主动阅读、思考、复盘总结并付诸实践这也是我成长最快的一个阶段。我不断从生活的点点滴滴做起追求健康生活努力进步整理自己。\n我花了近一个月的时间才写下了这篇文章写了又删删了又写。这磕磕撞撞的一路终究是多少字都无法记录下来的到头来我却只能轻描淡写。\n有时候会想后悔么可说实话其实没有什么可以后悔的我从小出身贫寒更不是天才阶级的局限性使我很难不犯错。再加上原生家庭的不美满性格自幼存在缺陷情绪不稳定个人能力欠缺……\n谁又会愿意嫁给我呢不过去年在我深刻地认识到这个问题后经过长达一年的自我改造迭代和修复目前已经可以拿个及格分了。但我很不想回溯这些事只是偶尔会受影响。我也想借此文章打个快照放在这里好了。\n人生南北多歧路最是人间留不住……"},"Personal/Blog/2023/写博客的正确姿势":{"title":"写博客的正确姿势","links":["Blog/写博客的正确姿势---测试版","Blog/写博客的正确姿势---先行版","Blog/写十万字的博客是一种什么感觉"],"tags":["写作/技巧","博客/原创"],"content":"上半年一直在卷,博客也是又被闲置了。去年写了两篇关于写博客的正确姿势,通过一年的实践,总结,再实践,现在已经卓有成效。这一次主要就是聊聊这个「姿势」的问题,更重要的是把写作实实在在的融入生活。😏\n写作胡编乱写可是不行的要先有点东西可写。尝试着从点线面获取信息源进一步糅合构成体既不抛弃碎片化知识更要拥抱多样化信息源。\n所谓的「点」主要就是抖音小红书这些刷一刷的信息源。当前人们对于碎片化知识褒贬不一如果辩证的去审视总是不会错那么离谱的。碎片化的知识获取快易于消化范围广毕竟是知识流经大脑再流出来的感觉可实在是太爽了哈哈。可质量不一存在偏见容易遗忘也是个问题。\n\n关于碎片化知识我选择的是每月定期的去整理归纳碎片化知识。在以往的《谈谈我的「数字文具盒」 - 生产力工具》我有提到过 memos 这个工具,如果刷抖音的时候灵光一闪,要立刻马上记录在 memos ,以便日后写作。\n「线」性信息源就更像是公众号论坛帖子抖音评论头脑风暴等这些拥有上下文以时间为尺度呈线性增长的信息。通常先有人把线头扔出去你一下我一下地拽出来。有没有营养没有人知道。但是丰富多样广泛交流的形式很容易掉进去毕竟是个人都能随意发表两句。最后「线」织出来的毛衣可以穿么好不好看谁也说不准。在没有一手信息源超出认知范围的情况下我是不会在任何地方评论的只会默默无闻的做一名潜水员。\n对于「线」性信息源而言大致来说有三种往左往右往中。虽然大部分人都是我行我素我以为我以为的就是我以为快乐就完事了但「线」性信息源能够为我们的思维带来多元化的碰撞可以有效地帮助我们缓解思维困境打开新局面。\n毕竟三个臭皮蛋顶一个诸葛亮\n\n对于「线」性信息源我利用 Zotero 的快照功能先收藏,再结合 ChatGPT 定期进行主题阅读。主要没营养的文章、帖子实在太多了。我们要学会利用 ChatGPT 输出摘要,带着问题进入,有选择性地精读,同时输出三两句记录在 Memos 用来日后写作。\n在信息大爆炸的时代像传统媒体、新媒体以视频语音形式提供极大的信息「面」。可这些只有看完了才知道好坏。并且算法的加持喜欢什么就给你推什么。而且大部分信息还难以分清描述事实还是抒发观点。我建议是要永远怀着批判性思维永远保持怀疑\n我平时在油管和 Bilibili 待的时间最多,毕竟可以听到不同声音的地方少。偶尔也会无痕浏览一些新媒体网站,主动调整推荐算法。永远保持好奇心。\n「点」连成线「线」动成「面」无数的「面」交织重叠就形成了体。\n我给「体」下的定义就是书籍、论文等。书籍可以帮助我抹平时间、空间的限制毕竟生活中大部分人朋友圈都有限再有时间、空间的限制导致我们交流门槛较高。我是喜欢通过针对性的专题阅读带着问题在一定时间内疯狂阅读相关领域内大量的书籍快速、高效的汲取大量精华信息源。\n当我们寻求大量优质信息源时探索不同的观点、保持好奇心积极主动打破信息茧房持有批判性思维永远保持怀疑。日积月累长久以来便可以洗涤精神世界开拓思维为写作积攒下海量素材。\n说起博客开始于 18 年,断断续续写了 5 年,可也才写了 10 万多字。想当年月月难产,半天蹦不出来一个屁,想起什么就写什么,啥都往上发。可说实话写博客其实一点都不简单,分享流水账又觉得太敷衍,所有东西都往博客上放,又会显得很凌乱。\n前段时间为了解决这一「姿势问题」专题阅读了写作方面的书籍最后决定要创造一种秩序上的美\n\n选择主题确定方向 🎯\n收集整理信息源 📚\n头脑风暴交谈 💭\n思维导图 🗺️\n编写整理提纲 📝\n草稿写作 🖋️\n润色修改 ✨\n校对编辑 📎\n输出分享 📤\n\n动笔前首先要选择一个主题并确定探索的方向或视角。收集整理相关的素材和信息源也可以与朋友进行头脑风暴来丰富思路。然后编写一份整齐的提纲并草拟初稿。接下来进行润色修改确保语法、拼写和逻辑的准确性以及连贯性最好还可以朗读几遍。然后再使用第三方工具进行校对和编辑最后在合适的平台分享文章如博客、维基等。\n纵使这样有时候也会难以下笔因为不知从何说起。可我在阅读时发现许多作者对于这个问题不约而同说了同样一句话**写,万事万物先干了再说。**想想也是,毕竟没有哪个人生下来就会写得一手好文。毕竟写作是一辈子的事情,我有写出世界上最烂的垃圾的自由。\n在博客的第六年我也浅浅地定下一个小目标**每个月最少写 6 篇文章,总字数不少于 1 万字。**可是,说到底写作最后又能有什么意义呢?我也不知道。可能如同生命一般,没有任何意义。\n可当下我就是想说想写。毕竟高度够了看什么都是风景。\n写博客的正确姿势 - 测试版\n写博客的正确姿势 - 先行版\n写十万字的博客是一种什么感觉"},"Personal/Blog/2023/唯有热爱可抵岁月漫长":{"title":"唯有热爱、可抵岁月漫长","links":[],"tags":["历史/计算机科学","博客/原创","成长/个人"],"content":"二十一世纪,计算机与互联网的快速发展重塑了每一个人的生活。在我十二岁时,家里买了第一台电脑,从此相伴,或许将会是一生的热爱。但是我一直很好奇,这个小小的方盒子怎么就能链接世界的每个角落?尤其是过去的三十年间,计算机科学就像是一辆赛车驶向未来,而我们也不知道将要开往何方。它潜在的巨大能量更是为我们创造了无尽的财富和机遇。特别是最近几年,计算机科学已经不仅仅是一场技术革命,而是逐渐成为了地缘政治博弈中重要的一环,那我们为什么不能主导现代计算机科学发展?\n俗话说「历史是最好的教科书」既然我们在当下找不到问题的答案时那么就有必要深入了解过去。\n《信息简史》一书透过历史的纬度揭示了信息如何从简单的符号演变成了今天全球互联的复杂网络。在人类文明之前信息主要通过肢体动作、面部表情和图像等非文字方式传播然而这样的方式并未能有效地保存和传承文化遗产。古代文字的诞生无疑是信息传播历史上的一个里程碑随后书写、印刷、纸张和算盘等各种工具和媒介进一步推动了信息的广泛传播。自文艺复兴时代之后近现代科学技术的快速发展为信息技术注入强大的推动力。电报、电话和电力等后续出现的技术手段极大地加速了传输信息的速度。\n特别是近现代两次世界大战极大地推动了科学技术的高速发展继而孕育出许多划时代的科学发明。在第一次世界大战中无线电广泛的军事应用具有巨大的战略价值同时也为现代通信技术打下了坚实的基础。进入第二次世界大战后出现了可以用于计算导弹弹道和破译加密通讯的计算机技术这一进展无疑为现代信息技术的蓬勃发展铺平了道路。\n在第二次世界大战期中以艾伦·图灵领导的密码破译团队成功地解密了德国的 Enigma 密码机,这一成就对战局产生了深远的影响。更重要的是,图灵 1936 年提出的图灵机模型为现代计算机的逻辑运行方式奠定了基础。此外,图灵 1950 年 提出的图灵测试也成为了人工智能领域一个标志性的概念。或许是天妒英才的缘故,图灵于 1954 年自杀。\n两次世界大战期间美国作为一个主要的参与国受益于其主要国土远离亚欧大陆的地理位置未曾遭受到严重的军事侵害同时也获得了战争带来的巨量经济利益。特别是在第二次世界大战中众多的全球顶级科学家为了逃离战乱选择了移民美国。其中就包括冯·诺依曼他是一位在多个领域内拥有卓越贡献的科学家如现代计算机科学、博弈论、核武器以及生物化学武器被后人尊称为现代「计算机之父」和「博弈论之父」。\n在第二次世界大战结束后AT&T 作为美国最大的固定和移动电话电信服务供应商崭露头角,更是在 1950 年代和 1960 年代达到了其历史高峰。在这一期间,该公司雇佣了多达 100 万的员工,年收入也从 1950 年的 30 亿美元(按照今天的货币价值相当于 347 亿美元)猛增至 1966 年的 120 亿美元(按照今天的货币价值达到了惊人的 979 亿美元)。\n更值得一提的是AT&T 旗下 1925 年创建的贝尔实验室。经过多年的研究和发展即将迎来其最为辉煌的三十年。1947 年,约翰·巴丁、沃尔特·布拉顿和威廉·肖克利等人联合研制出共同发明了改变世界的晶体管。紧接着在 1948 年克劳德·香农又发表了名为《A Mathematical Theory of Communication》的论文标志着信息论的诞生并在同年引入了「熵」的概念。进一步地贝尔实验室在 1969 年还推出了具有里程碑意义的 C 语言和 Unix 操作系统。\n尤其是在《贝尔实验室与美国革新大时代》一书中其中有一段内容描述了上世纪 60 年代的美国繁荣情景。与此同时,我们还在面临吃不饱肚子的问题。而在这一阶段,美国家庭普遍拥有小汽车并住进了舒适的洋房,与之形成鲜明对比。贝尔实验室的多位科学家也都有机会全心全意地投入到自己的研究工作中,这一点实在令人充满羡慕。\n综合来看当时的 AT&T 不仅准确地把握住了社会需求,获得了可观的商业利润同时,而且持续地投资于贝尔实验室,其聚集了全球顶级的科学家,从而推动了计算机科学和通讯行业的巨大发展。\n至此美国可谓占尽了「天时地利人和」即将迎来腾飞\n在随后的美苏冷战时期军事竞争又为美国的科技发展注入了新的活力继续给科技的熊熊烈火增添薪柴。同时美国社会普遍对美好生活的追求也进一步激发了市场需求。这种需求不仅推动了消费也为需要大量资金投入的科学研究提供了经济基础。继而形成了完美的正反馈循环社会需求催生科技进步而科技进步反过来又推动了更高层次的社会需求。\n这一切构成了一个自我强化的生态系统推动了美国在多个科技领域的持续繁荣和领先地位。这种独特的动态平衡不仅加速了科技革新也为在经济、文化和社会福利等多个层面的全面发展创造了良好的土壤。因此美国得以在全球舞台上维持其超级大国的地位持续走在创新和进步的前沿。\n然而贝尔实验室正在步入其历史的黄昏。尽管该实验室一度是科技创新的先锋但因多种复杂因素AT&T 最终被美国政府拆分,贝尔实验室也因此走向了颠沛流离的命运。\n贝尔实验室作为 UNIX 操作系统和 C 语言的发源地对后世计算机操作系统的发展产生了深远影响。《UNIX 传奇:历史与回忆》一书中详尽地讲述了 UNIX 的传奇故事,这个操作系统最初由肯·汤普逊、丹尼斯·里奇和道格拉斯·麦克罗伊于 1969 年在 AT&T 的贝尔实验室中开发。\n1965 年,贝尔实验室参与了一项由通用电气和麻省理工学院共同进行的计划,旨在开发一个多用户、多处理器、多层次的 MULTICS 操作系统。据说因为 MULTICS 的过度设计,该操作系统始终未能发布。到了 1969 年,贝尔实验室决定退出该项目,但肯·汤普逊和丹尼斯·里奇仍然以满足个人需求为目的,秘密开发了 UNIX。\n起初肯·汤普逊和丹尼斯·里奇并没有计划开发一个完整的操作系统他们只是参照 MULTICS 的失败经验并加入自己的创新思想。但他们很快发现只需不到三周的时间UNIX 就能发展成一个完整的操作系统。在接下来的十年里UNIX 在学术界和企业中广泛应用,多家机构基于原始代码进行了拓展和改良,形成了各种 Unix 变种,其中最著名的就是由加州大学伯克利分校开发的 BSD。\n随后AT&T 开始看中 UNIX 的商业潜力,并修改了 UNIX 的版权规定。这促使理查德·斯托曼于 1983 年 9 月 27 日在麻省理工学院公开发起 GNU 计划。GNU 计划的根本目标是创建一个 100% 自由的、与 Unix 兼容的操作系统。这个操作系统被命名为 GNU是 “GNUs Not Unix” 的递归缩写——既是对 Unix 技术思想的致敬,也表达了 GNU 与 Unix 的不同。\n到了 1991 年Linus Torvalds 发布了与 UNIX 兼容的 Linux 内核,并在 GPL 协议下开源。Linux 后来与 GNU 软件结合,诞生了一个完全自由的操作系统,吸引了大量程序员参与开发和改进,成为 GNU 软件开发的重要平台。这个操作系统通常被称为 GNU/Linux 或简称为 Linux。\n与此同时我们结束内乱、改革开放、步入属于自己的三十年。就更不要提即将诞生的谷歌、英特尔、微软、苹果等这些改变世界的企业了。直至今日我们许多人的基本生活需求尚未得到满足更不用说社会需求了。毕竟造不如买买不如租致使我们现在还有几个十年。\n相比之下贝尔实验室科学家的终生热爱。尽管如今政策大力支持许多人却初心易得始终难守玩弄于股掌之中殊不知我们究竟是「真聪明」还是「假聪明」。相比之下我们不仅丢了天时失了地利更不要提人和了。\n为了找到这些问题的答案我读了很多的书走了很远的路尽管我觉得已经找到了想要的答案。但一想或许又没有所谓的标准答案就好比人真有「命」这一说法么还是所有的一切都仅仅只是偶然但我想这个答案的方向应该不会错得那么离谱。\n余生唯有热爱可抵岁月漫长。\n\n为什么这个小小的方盒子可以链接世界的每个角落\n这个问题的回答我就是写 10 万字,也没有办法通俗易懂的讲述清楚 😭,**建议直接啃书!**推荐阅读:\n\n\n《计算机是怎样跑起来的》\n\n\n《网络是怎样连接的》\n\n\n《Linux 是怎样工作的》\n\n\n《程序是怎样跑起来的》\n\n\n《面对对象是怎样工作的》\n\n\n如果你可以按照顺序通读一遍那么对于现代计算机科学已经拥有了系统全面的初步认识了。我已经给你做好了微信读书的书单「计算机科学科普」奥里给快冲冲冲 \n为什么漂亮国引领现代科技潮流我们却不可以\n\n\n《信息简史》James Gleick 的《信息简史》透过历史的纬度,为我们揭示了信息如何从简单的符号演变成了今天全球互联的复杂网络。\n\n\n《计算机一部历史》Peter J. Bentley《连线》杂志特约编辑。英国伦敦大学学院UCL计算机系教授、荣誉资深研究员。\n\n\n《贝尔实验室与美国革新大时代》乔恩·格特纳《纽约时报》的记者、历史学家和专题作家。\n\n\n《UNIX 传奇历史与回忆》Brian W. Kernighan 《C 程序设计语言》和《UNIX 编程环境》等 10 多部计算机著作的合著者。他曾在贝尔实验室计算科学研究中心 Unix 开发组工作超过 30 年,见证了 Unix 的诞生。\n\n\n《硅谷之火个人计算机的诞生与衰落》迈克尔·斯韦是知名 IT 作家,最早投入 IT 行业的媒体人之一,与盖茨等众多硅谷大佬有着良好的关系。\n\n\n《芯片简史》汪波资深芯片研究专家。早年留学法国获法国里昂国立应用科学学院集成电路硕士学位和利摩日大学高频微电子学博士学位分别在华为公司、法国里昂纳米国家实验室和北京大学深圳研究生院从事集成电路设计的教学与科研工作积累了二十余年经验。\n\n\n《芯片战争》余盛战略咨询专家、消费品营销专家及财经作家。\n\n\n《开源之迷》适兕、「开源之道」主创Linux 基金会亚太区开源布道者团队主席Apache Local community Beijing 成员CCF 开源技术丛书编委会委员 。\n\n\n《世界前沿技术发展报告 2022》国务院发展研究中心国际技术经济研究所。\n\n\n如果你想阅读这些书我已经在微信读书生成了「计算机科学简史」的书单奥里给快冲冲冲\n为什么漂亮国将高新科技视为制裁天朝的尚方宝剑\n关于政治问题我不懂不过有一些相关资料可以帮助形成一个初步的认知。\n\n\n漂亮国-天朝 Relations TimeLine\n\n\n漂亮国制裁天朝的维基百科\n\n\n漂亮国制裁天朝实体名单 - 官方\n\n\n\n资料链接需要全球上网。\n"},"Personal/Blog/2023/回首-2022-展望-2023":{"title":"回首 2022 展望 2023","links":[],"tags":["年度/2023","年度/2022","博客/原创"],"content":"说实话我今年是压根没有一点点欲望写年终总结,每次年初洋洋洒洒定下目标,年末畏畏缩缩祈求不被雷劈,装逼遭雷劈呀!但这是我博客的第 100 篇博文,该死的仪式感蛊惑着我。\n春\n春天经历了很多有意义的事情尝试开荒了小菜园又爬了嵩山拍星空、还认识了小雅 ~ 老家的闲置荒地开发小菜园,信誓旦旦的夸下海口,种菜送给各位博友吃,抱歉又装逼了。嵩山的星空之旅收获满满,但是真的好冷啊。还有就是和小雅骑摩托进山,一路躲避警察叔叔的追赶,真 TM 的刺激······\n夏\n夏天的时候我一直沉浸在学习中无法自拔。因为软考一次又一次的取消考试所以真的让我好烦。不过好在春天种下的蔬菜和夏天专属的西瓜安慰了我的灵魂西瓜真好吃嘎嘎甜 ~\n后续又加入了中国好青年社群总的来说很幸运也很值得学习到了非常多的新知识收获了更多的成长。在此感谢人生路上每一位相伴的好友 ~\n秋\n传统印象里秋天应该是收获的季节但是软考也是真的又一次黄了……这该死的疫情啊什么时候恢复正常生活啊。不过现在回想起来似乎整个秋天都在读书、思考、写作不断的充实自己的大脑头好痒感觉要长脑子了。\n对对对还有就是我 TM 自驾去青海被劝返了。疫情你可真该死啊啊啊!\n冬\n冬天还没过完呢接下来就希望开开心心过个大年印象深刻的就是稀里糊涂的疫情解封然后稀里糊涂的阳性然后稀里糊涂的恢复了以往的生活总之过得非常稀里糊涂。\n回首\n每次年终回首都似乎觉得这是生命里最重要的一年但是哪一年又何尝不是呢。2022 年最开心幸福的事情就是认识了我的女朋友——小雅;最幸运的事情就是加入了中国好青年社群;最痛苦的事情就是在嵩山顶回首过往哭的稀里哗啦;最憎恶的事情就是疫情和该死的软考。\n收获\n2022 年最大的收获便是读书,从 7 月份开始尝试微信读书直至 2023 年总共阅读了 17 本书;其中涉及各种认知成长、人文社科等等,更是开辟了新的爱好——围棋。\n展望\n说实话再也不敢装逼了也不会洋洋洒洒的写下一堆目标了。期望 2023 年拥有稳定的生活,持续的进步成长就知足了。具体的目标就是今天比昨天好一点点,活在当下。\n2023 年目标只有一件事,也只做这一件事。"},"Personal/Blog/2023/大学回忆录":{"title":"大学回忆录","links":[],"tags":["记忆/大学","博客/原创"],"content":"整理书柜翻出来一块 500gb 的机械硬盘,插上电脑一看,竟然是大学时期的资料备份。双击文件夹打开,瞬间回忆涌上心头,借此分享记录一下。\n\n极客精神\n\n文档、学习视频、源代码文件夹里边全是关于 c++、asm、逆向的资料一种沙雕的极客精神哈哈。那时候学习计科没有人指点就像只无头苍蝇一样乱撞再加上考的学校较差最终还是海里淘沙两手皆空。\n从 12 年第一次接触中文程序设计语言:易语言,随后又自学 vb、c、c++、asm、java、JavaScript、php、算法、密码学、网络、系统、硬件等。尽管那时候局限性很大在技术实践上缺乏深度但在技术的广度上思路上绝对不差\n关于计算机科学这门学科我建议很多新手小白在规划入门、进阶学习的时候一定要理解学习计算机科学其实是一个渐进式的过程。大致如下\n\n不求甚解的学习一门语言不应该仅仅局限于语言自身更重要的是理解编程思想与范例。\n要求对算法与数据结构有一个深刻的了解这也是编程的基础并且算法在不同语言中是相通的。\n学习系统、网络、数据库和架构设计等更高级别的概念这些需要很强的抽象思维和系统思考。\n数学与英语两门基础学科必须重修、精修为进一步学习做准备。\n必须要不断地反复练习应用测试和优化尝试 win、linux 和 h5 编程,试着写出 100 行1000 行乃至 100000 行代码。\n左手学数学右手学英语脚踩互联网努力走进某个领域最深处去磨刀。\n成就取决于天赋造化所能达到的境界。\n\n如果你能理解这段话那么它实际上就是一种递归的计算机思想。说到底研究计算机科学不应该只限于某种语言真正重要的是递归封装面向对象、协议等等的思想。拿我来说如果我现在要学一门新语言那么在正常的情况下两个星期的时间就可以从 0 到 11 到 100+ 并进行开发,而如果想进一步 1000+ 的话,则需要用时间换取空间。\n学习生活\n\n中国软件杯设计大赛那时候是攻关《工商执照识别》项目需要深度学习方面的知识那时候能力还不够强老师也指导不了最后烂尾了哈哈。也参加过中国程序设计大赛河南省软件设计大赛等总之是挺多各种各样的比赛经历的。\n淘宝小店很好玩那时候总是觉得生活费不够用想着靠自己计科专业知识来提供相应的服务赚点外快后来也是烂尾了。团员管理系统是毕业设计那时候要随便交一个项目应付毕业的再加时间不够总之挺垃圾。\n《17 软件周中平社会实践报告终极版》记得去过二七塔和郑州烈士博物馆的但是还是很过瘾的记得就是公费报销吃喝拉撒哈哈。《2018 十个目标》都是吹牛逼的。《企业计划书》这是最蠢的哈哈,那时候我可是吹牛逼的一把好手啊。\n\n《新时代新梦想创业大赛》是最 sb 的,那时候好几个专业的学生都是智障似的被老师骗去比赛,最后还有个学生用情太深,就投了 10w+ 进去,赔个精光。那时候真的是苦口婆心的相劝,怎奈何大学生就是大学生,良言难劝该死鬼呀……\n还有我当时被半路任命为班长这就导致了 B 事可多。最 TM 气的是,我勤勤恳恳地冲了国家奖学金两年,基本上十拿九稳的,那时候成绩专业排名前 2%、在校外各项比赛活动中获得了大大小小的奖项校内的活动更让院篮球队拿到了有史以来的最佳战绩亚军、运动会跳远第一名虽然这些得奖主要是因为我高中生是体育生哈哈。结果呢最后国奖连参加评选都没有主要是院党委书记打电话不让我参选CTMDB 内幕。\n还有很多记忆碎片但暂时先停止吐槽和 bb 哈哈。虽然因为自己没有努力学习而导致去了一个很差的学校,但是大学生活两年来也很充实。纵然有很多的遗憾和不愉快也都到此为止了 ~\nDelete\n"},"Personal/Blog/2023/如何不写错别字!":{"title":"如何不写错别字!","links":[],"tags":["写作/技巧","博客/原创"],"content":"岁末年初,万象更新的 2023 年,首先是从怎样不写错字说起。我从学生时期就超容易写错别字,而且特别爱“一逗到底”!也不知是为什么,更不知该怎么摆脱这臭毛病。\n如今随着博文越写越多如何不写错别字渐渐成为一个大难题。有次博文刚刚发出来没多久就被人指出错字连篇脸上可真是火的通红 🤪。在新的一年里为了不再脸红,我会从两个方面抓起,逐步纠正不写错别字的毛病。\n\n输入读正版书籍锻炼错字的识别能力和语法及标点的用法。\n输出第三方文字校验工具同时结合自己认真看朋友简单审。\n\n以后博文将由第三方工具进行文字校验并且我认真阅读后再发表。虽然可能还会存在错别字但是相较而言已经大大减少。我个人感觉语法的错误相较于字词的错误还是可以接受毕竟文言文可是连个逗号都没有。我一直认为文言文的通假字其实就是错别字🙄\n目前我一直在使用的文字校验工具\n\nLanguageTool支持超过 20 种语言的文本校对,包括中文。可以检测拼写、语法、标点符号等错误。 www.languagetool.org/\n爱校对依托清华大学人机交互实验室的技术成果致力于文字校对公文校对论文纠错文档查错错别字检查敏感词检测错别字筛查校稿。www.ijiaodui.com/\nJCJC 错别字在线检测专注使用人工智能技术应用于文本纠错领域拥有华为、浪潮、长沙晚报等知名客户。www.cuobiezi.net/\n写作猫AI 写作文章自动生成。xiezuocat.com/\n火龙果AI 驱动的文字生产力工具。mypitaya.com/\n\n博客的第五年先从不写错别字开始毕竟这个“文字”的东西让我的生活变得更加丰富多彩 ~"},"Personal/Blog/2023/如何拍好一张照片":{"title":"如何拍好一张照片","links":[],"tags":["摄影/技巧","博客/原创"],"content":"最近又把之前买的摄影教材再拿出来翻翻看看,打算系统地复习摄影,同时给身边的朋友简单明了地分享一些关于摄影的基础知识。\n现在拍张照片其实很简单。摄影经过胶片时代、数码时代、到智能手机曾经离我们非常遥远的东西如今触手可及。生活中随时拿出手机一拍转手发在朋友圈也是早就习以为常的事情。但如何拍一张好看的照片却是一门深奥的艺术\n一副好照片是怎么来的\n每次看到书籍、杂志、影展上那些令人惊艳、向往的照片我们都会心生向往。毕竟谁不想拍出那样的照片呢😎\n实际上生活中美景无处不在。 只要我们具备了一定的摄影技巧,便能捕捉到那些瞬间,拍出令人心动的照片。\n然而一张真正出色的照片首先要满足三项基本原则鲜明的主题、引人注目的内容以及简练的构图。 如果满足了这三项原则,那这就是一张好照片,或者说、它已经朝向了更高的艺术方向前进。\n鲜明的主题\n首先一副好照片要有一个鲜明的主题。这个主题可以是表现一个人、一个事物、甚至是一个故事情节。主题必须明确、不容忽视让任何层次的观赏者都能一眼看出。\n其次一个鲜明的主题并不意味着它必须是大而华丽的或者是引人注目的。有时日常生活中的微小细节、一个简单的手势或一个短暂的眼神都可以成为深入人心的主题。关键在于如何捕捉和表达这些瞬间使其引起大家的共鸣。\n再者鲜明的主题往往与情感紧密相连。我们不仅要能够捕捉到物体的形态更能捕捉到背后的情感和故事。这种情感的传达使得照片不再是单纯的图像而是能够触动人心的艺术品。\n总的来说鲜明的主题是摄影的灵魂也是我们表达自己观点和情感的载体。\n引人注目的内容\n内容的选择是摄影中的核心支柱它不仅仅是视觉上的吸引更是对观赏者心灵的触动。好的内容能够迅速吸引观赏者的注意力使其深入探索照片的每一个细节。\n在这个图片泛滥的时代内容的原创性和独特性显得尤为重要。我们应追求那些鲜为人知或少有人捕捉的主题或者尝试从全新的角度展现常见场景。\n与此同时内容与其环境的交互也极为关键。我们需思考如何巧妙地运用光线、背景、天气和季节等元素以增强主题的魅力。有时一个平凡的物体在特定的环境下会展现出意想不到的美。\n内容不仅是摄影中的重要支柱更反映了我们对世界的独到见解。捕捉那些令人铭记的瞬间更需要我们有敏锐的观察力、创新的思维和扎实的技术。\n简练的构图\n构图的简练性是摄影中的基石。它决定了照片的整体感觉它确保了画面的每一部分都有其存在的价值无任何多余元素从而使观赏者的注意力集中于主题。\n为了实现这种简练我们可以依赖于基本的构图原则如三分法、黄金比例和领导线等。但关键在于我们应能够根据实际情境灵活运用这些原则而非僵化地遵循。\n此外画面空间的巧妙利用也是不可忽视的。通过恰当的留白、前景和背景处理照片将展现出更丰富的深度和层次。在有限的空间中展现主题的魅力同时确保整体和谐。\n简练的构图融合了摄影的艺术与技术需要我们不断地实践和学习才能真正创作出简洁、有力、吸引人的作品。\n此外后期处理在摄影中也占据了不可或缺的位置。 毕竟我们在拍摄时可能无法完美控制每一个细节,但后期的裁剪和调色为我们提供了调整画面比例和焦点的机会,使得照片的构图更为精炼和有力。通过细致的色彩调整、对比度的增强和特效的应用,我们能进一步提升照片的视觉冲击力,让其更具吸引力。\n摄影不仅是对技术的追求也不止于简单地记录生活。它更是一种对生活的深度感悟是通过镜头捕获的情感和故事是我们与拍摄对象之间的情感交流。\n正如著名摄影师安塞尔·亚当斯所言这句话深得我心\n「你拍的照片不仅仅是照片它更包含了你经历的每一段旅程读过的每一本书听过的每一首歌以及你深爱过的每一个人。」"},"Personal/Blog/2023/家里的三块地":{"title":"家里的三块地","links":[],"tags":["记忆/童年","博客/原创"],"content":"前几天,终于和老朋友约到一起吃了顿饭,聊了会天。大家即便都是在郑州,约个饭也变得如此困难。工作时间不同,休息时间也不一样,更别提将来有了孩子以后了。后来东一句西一句地聊到了学生时代的寒暑假,那时光可真是太美好了。不过,提起寒暑假,我不禁想起来小时候的那些日子。毫无疑问,寒暑假是学生时代最欢乐的时光,可我的暑假当时一点都不快乐……\n小时候我家在郑州市郊区去市区只有一班公交车还需要将近一个小时。我和姐姐每年的寒假过年时候妈妈才会领着进城。那时候家里生活也比较拮据更别提有零花钱了。为数不多的收入就是那三块地西地、岗陆liù、北地。\n田家少闲月五月人倍忙。麦子熟后不久种下花生我和姐姐就放暑假了。因为姐姐比我大六岁所以和姐姐最多的时光就是寒暑假一块呆着的日子。然而暑假一开始就意味着我和姐姐就要开始割草、浇地、摘花生那时候我和姐姐相较于其他孩子一直是邻居口中「别人家的孩子」。聪明、懂事、学习还好每年都领回家一堆奖状可是我却渴望其他孩子的自由自在。\n一般等姐姐放假回来后老妈就会要求我们俩写 OKR需要明确到我俩能为这个家庭做些什么接下圣旨之后我和姐姐不一会就把工作表规划出来姐姐负责做饭、割草我则负责割草、放羊。我喜欢放羊因为可以借机和其他小伙伴一起玩耍。但我一看到割草头都大了割草、割草为什么会有草这种东西……\n难道就没有人发明一些神奇药水让草从这个世界消失土地上发什么就让它长什么长什么就吃什么不行主要是前脚刚割完后脚草就又长起来了。周而复始无穷无尽割不完根本就割不完还是寒假好呀冬天来了就不用割草了。可是冬天来了春天还会远么每次走在去西地的路上我都会想这些无厘头的问题。\n西地算是村里为数不多的宝地因为有许多枣树下面还可以种花生。我家旁边的邻居还总是喜欢偷偷侵占一些。我就会在浇地的时候就会偷偷开个口流水试图淹死邻居种的花生。割草倒不是什么技术活就是把所谓长得不对的野草除掉留下能结果的花生。花生开花后向土地里生长的触须就是花生结果的茎。我不想割草就会马虎地把草连带着茎一块割掉老妈见状就会数落我。不过长时间在花生垄蹲伏前进站起来不免两面发黑我就会申请回家\n还不让我回家还不让我回家每次不让我回家我就拿着铲向土地发泄着怨气不过有时候还会挖出一些陶粒、碎片我就会装到口袋带回家向小伙伴炫耀说是唐三彩碎片。「啥垃圾碎片啊你着不着咱庄岗陆挖出来个墓地走去那看看吧」。我心里却是想着得亏岗陆被占了要不然还得去岗陆割草了。\n岗陆离西地不远却土地贫瘠到处都是起伏的沙土岗不过却是我家最大的一块地。后来不知道因为地理位置特殊还是因为沙土多岗陆从不想要的破地成为了香饽饽。在我七八岁的时候村里队长就和一些人合伙私自就把沙土卖了据说还挣了几百万。然后不仅修了高速还修了国道和大大小小一堆道路可算是把岗陆挖了个底朝天。只剩下了一块被路围着的地方又被堆放了几十米高的建筑垃圾据说未来还要被改造成市民体育公园。\n北地是我和二爷两家的听说二爷是伯祖父去抗美援朝回来后领养的。后来伯祖父去世后二爷因为从小佝偻也不能耕种这份地稀奇古怪的就让我家种了。村里后来流行种植梨树据说是比种麦子挣钱。家里也买了几百颗梨树苗我心里倒是想这能挣钱都到啥时候了。果不其然一年又一年钱还没挣着就有割不完的草叮不完的包。高中的时候北地的梨树终于迎来了大丰收。可惜又大又甜的黄梨一斤才卖一块多钱。\n时光荏苒因为家里的地陆续被占了我也终于不用割草了。不过我也换了一个地方继续「割草」——开始工作了。那些日子虽然辛苦但每每回顾却总能让我心生暖意仿佛那就是成长的代价和收获的开始。"},"Personal/Blog/2023/岁月是把猪饲料,把我喂的嘎嘎胖":{"title":"岁月是把猪饲料,把我喂的嘎嘎胖","links":[],"tags":["生活/日记","博客/原创"],"content":"上班两年多了,工资没见上涨,体重却是蹭蹭蹭的长。小肚腩,气喘吁吁,干啥事都不想动弹。日常工作、生活琐事搞得每天都精疲力竭,更别提回来再运动运动了。然而,然而……尽管现在实现了当初梦想体重 80kg但这是虚假的 80kg满满肥肉的 80kg。\n\n岁月可真是把猪饲料啊😔😔😔\n三年你知道我这三年怎么过的么27 斤27 斤五花肉啊!😵😵😵\n之前高中的时候体育特长生身材还算一级棒。如今呢猪饲料 y 越吃越多,真的是毁灭吧!天天拍着日渐丰满的小肚腩啧啧啧。平时也不是没有锻炼,主要就是吃的饲料太多了,运动强度达不到,吃的又多,只能一路小跑的发胖了……\n下班之后我是懒得去健身房的练完之后还要通勤我就想洗个澡直接躺了。再有就是上班的时候跟一群吊毛斗智斗勇没有心力来场高强度锻炼了。而且如果高强度训练没有坚持下来非常打消积极性。毕竟要学会尊重人性啥事单靠毅力是坚持不久的。\n目前我正在践行《三一计划》家里也买了一些精巧好用的健身器材。未来体重还是要保持在合理的区间范围内的简单来说《三一计划》是这样的\n\n\n小于 140 斤:不减肥,要吃吃吃了。\n\n\n150 斤左右:正好,继续保持。\n\n\n大于 160 斤:必须要控制饮食,保持运动了。\n\n\n三每周 3 次 1.5 倍基础心率 30 分钟的运动。\n\n\n一周末 1 次 2 倍基础心率 30 分钟的运动。\n\n\n冲冲冲GGBOY 在行动!"},"Personal/Blog/2023/拾月游记":{"title":"拾月游记","links":[],"tags":["游记/云台山","游记/神农架","博客/原创"],"content":"我最近是真的懒,也是真的忙,不过凑巧还出去转了两趟,上个月去了云台山,国庆又去了神农架。\n郑州七八月份太热天天窝在家里终于凉快了就想着和小雅一起出去快乐一下。旅游这种事目前我已经有了极致的心得去哪里不重要玩什么不重要最重要的是开心开心还是开心\n现在各地的旅游模式大同小异诸如黄山云台山神农架等都可以理解为一个超级大的公园每个小场馆都需要门票然后整体需要花几天时间在里面溜达更适合旅居一段时间。不过要是能在当地有一个小院就好了闲暇时光就来待几天。\n开车返回郑州时碰见一个老大爷叫卖焦作铁棍山药寻思着这总不能是从郑州万邦批发的吧结果回家一秤八两称足足少了近百十块。\n🙃🙃🙃 糟老头子,坏滴很……\n\n今年更是疫情后的第一个国庆节依旧哪哪都是人哪哪都是结婚的。不过相较于前两年今年我参加的婚礼不多只有三场。\n本来国庆是没有打算出去玩的恰巧湖边露营临时起意。神农架说走就走出发晚上下了高速后神农架 80 公里的山路却要两个半小时。最近又是雨期到处都有落石,第二天还现场目击了前车被一块巨石撞击,不过还好没啥大事,想了解的看看四川观察发布的抖音三十几万点赞……\n神农架之旅本以为依旧欧皇附体云海日落事实却是好不给面子。下了好几天的雨云海也不尽人意但又似乎是我对于感受美的阈值越来越高了。\n\n\n\n🥰🥰🥰"},"Personal/Blog/2023/揭晓你的博客一年之最,尽在-EndOfYear":{"title":"揭晓你的博客一年之最,尽在 EndOfYear","links":[],"tags":["开源项目/EndOfYear","博客/原创"],"content":"🔥 揭晓你的博客一年之最,尽在 EndOfYear\n为你的博客一年的辛勤付出画上一个完美的句号让 EndOfYear 为你点亮写作之路!\n你是一个热爱写作的博主想知道你的博客一年来的表现如何吗EndOfYear 它能通过 RSS 抓取你的博客文章数据,然后进行统计、分析和整理,最终生成一份全面、客观的年度报告。\n无论你是想了解哪篇文章最受读者欢迎还是想统计你一年下来的写作量或是想获得你的读者人群画像EndOfYear 都能帮你轻松获取。\n使用 EndOfYear你**只需要简单配置你的 RSS 地址(博客设置 RSS 输出文章数量),无需复杂的编程知识,无需繁琐的操作步骤。**无论是通过 GitHub 还是 Docker我都为你提供了详尽的使用指南。\n预览地址7wate.github.io/blog23/\nGitHub 地址github.com/7Wate/EndOfYear\nGitee 地址gitee.com/wate7/end-of-year\nEndOfYear 是开源的,欢迎每一位对此项目感兴趣的朋友参与进来,一起为它的成长贡献力量。无论是测试、数据分析、主题开发,还是插件的探索,你都可以在这个项目中找到挑战和乐趣。\n关于\n这个项目的构思已有段时间了我实现了一个初步版本并计划在未来继续进行更新主要看是否有足够的时间。从技术方面来说这个项目并无高难度我欢迎各位博友尝试贡献。\n并给 EndOfYear 点个 star 😘😘😘"},"Personal/Blog/2023/早起、阅读、写作、运动、冥想":{"title":"早起、冥想、阅读、写作、运动","links":[],"tags":["成长/个人","博客/原创"],"content":"周岭在《认知觉醒》一书中提出了快速改变人生的五件事,即:「早起」、「冥想」、「阅读」、「写作」、「运动」。低调务实优秀中国好青年交流群也正是从这 5 件事入手,帮你养成好习惯。我也试着实践了有将近一年的时间,今谈谈收获与心得。\n早起\n一日之计在于晨一年之计在于春早起是个老生常谈的话题了鲁迅先生小时候为了上课不迟到还把「早」刻在桌上告诫自己。我小时候每天晚上吃完饭没什么事早早地就睡了甚至觉得十点睡觉都是一件很可怕的事。如今呢自从步入互联网时代十点不好意思十点夜生活才刚刚开始。\n秉承着先僵化、后优化、再固化的原则我决定尝试一段时间。起初几天是真的很难受白天浑浑噩噩的完全提不起精神。不过慢慢的晚上倒是越来越早的睡了。差不多半个月时间几乎都习惯了 10 点左右睡觉6 点前起床。正常早上六点起床后,稍微锻炼一会回来坐那下下汗,冲个凉水澡,然后吃个早饭就去工作了。\n持续了有半年时间直观感受就是身体越来越好精神头越来越棒但我并不认为这是早起带来的潜移默化改变了我的是生活规律。毕竟美国人时差和咱们完全反着来也没见几个英年嗝屁的。现在为止我想早起也许就真的只是早点起来罢了。\n但有一天我翻看着旧日的朋友圈星光不问赶路人豁然开朗。也深刻地认识到了自己的肤浅早起其实并不只意味着早点起来罢了。想象一下如果明天要和女神约会或者新工作的第一天不用考虑肯定早早的就起来收拾了因为你开心快乐幸福甚至要迎来人生新阶段了。所以早起真谛可能不仅仅是早点起来更重要的是进一步寻找人生的意义创造生命的价值为我所热爱奋斗终生\n冥想\n关于冥想老实说太高端了高端到有点不接地气反正 100 个人有 100 个见解。刚开始还看了各种视频、翻了有关的书、试了各种动作体验冥想、有没有效果我不清楚,不过睡得倒很快。\n感受呼吸、扫描身体、提升专注力但越努力就越凌乱……由于不能形成持续的正反馈所以我有点消极。去你的冥想浪费生命。后续冥想也是断断续续的持续了好久那天想起来就尝试一下想不起来就算了。\n直到有阵子忘记具体在做什么总之就是在写代码。从上班来坐那要不是同事喊我还真没感觉一个上午都过去了……也是瞬间明白了《十分钟冥想》中心流。\n我把冥想定义为心无杂念、极致专注。但是早期的努力只是停留在表面上而没有透彻地理解。我认为冥想最重要的一点感知力、尝试学会深入感受身体各个部位体会情绪在大脑波动品尝茶水在身体流淌体会世间万物。\n一个小和尚问得道的师父“您得道之前做什么”\n \n老和尚说“砍柴、挑水、做饭。”\n \n“那得道之后呢”小和尚继续问道。\n \n老和尚回答“还是砍柴、挑水、做饭。”\n \n小和尚一脸疑惑“师父这不是一样吗”\n \n老和尚说“当然不一样。得道前我砍柴时惦记着挑水挑水时惦记着做饭得道后砍柴即砍柴挑水即挑水做饭即做饭。”\n阅读\n生命是有限的但书籍却是无限的怎么用有限的生命阅读无限的书籍呢根据不科学统计人的一生最多只能阅读 15000 本书籍,那估计是没有一个人可以活着读完。所以我们应该要追求精读细阅和高质量的阅读。\n首先要会读书读好书。《如何阅读一本书》就非常详细的讨论了怎么样阅读一本书尽管有关读书的方法论确实很好但我觉得阐述得太过重复啰嗦。其实读书喜欢什么就读什么不要拘泥于阅读世界名著人文哲理。但我建议少读都市言情穿越爽文其可吸收的营养价值较少。具体想怎么读就怎么读咬文嚼字、一目十行都无所谓但是这一种读法仅限于是一本好书的情况下。可是究竟什么是好书呢追随那些走的快的人阅读其推荐的书单。\n假如面临的是一本新书那么你可以尝试\n\n深入了解书的作者、写作的背景。\n详细阅读书的自序、引言、大纲、目录等重要信息。\n快速翻阅书中的部分章节。如果感觉这本书很有价值那就接着继续。\n带着疑问追随作者的步伐选择最适合的方式阅读。\n\n这本书讲了什么\n作者细说了什么\n作者的观点是否正确\n作者讲的和我有什么关系\n\n\n收获体会记录笔记。\n\n再分享一种进一步的阅读方法主题阅读。在某个类目中挑选同方向的若干本书然后确认自己研究的主题和方向。\n\n依次阅读每本书。\n理清问题、界定主题。\n与不同作者达成共识。\n分析讨论。\n\n写作\n\n我学生时期其实最厌恶写作了……为什么会是你给我段话让我来研究一下它怎么想的然后再为你阐述一下自己的观点。我 TM 怎么知道他想什么,爱想什么想什么。\n\n写作实际上可以和阅读相结合从而构成完美的闭环。\n不知道是不是只有自己写作效率低感觉自己就像间歇泉总是时不时的迸发灵感。但有时候喷多了我还写不下来。所以我一般阅读书籍的时候总是会主动掺杂一些技术类目书籍这样既有助于提高专业技能又能留足思考时间。\n写作我倒没啥可分享心得的随心所欲不必整的很累。但必须重视以下三点\n\n务必不要出现错字。\n一定要正确地运用标点符号和合理地分段。\n确保文章整体阅读流畅性。\n\n运动\n生命在于运动如只老乌龟一样冲击活 100 年!\n运动锻炼不局限于任何形式爬楼梯也可以最重要的是生活态度。千万不要眼高手低今天运动明天就想超越博尔特持续保持正反馈日拱一卒冲吧骚年\n如果不知道如何下手可以参考我的 wiki 手册:健身手册\n\n其实吧哪怕你尝试了「早起」、「冥想」、「阅读」、「写作」、「运动」也不可能立刻获得收获。过去既然无法改变未来更不知道何去。\n那么请尝试着慢一点慢一点再慢一点也许当你回头那刻轻舟已过万重山。"},"Personal/Blog/2023/最近半年的生活":{"title":"最近半年的生活","links":[],"tags":["生活/日记","博客/原创"],"content":"最近半年的生活多姿多彩,博客也被闲置了,不过这段时间积攒了很多的想法,最近可能会喷发一下哈哈哈。\n二月\n\n高中好友田径队友老马结婚啦。以前是老家朋友结婚的多现在高中同学也开始了。各种臭鸡蛋老抽乱七八糟的糅合在一起老马只能坦然接受哈哈哈毕竟出来混总是要还的哈哈哈。天天不是在参加婚礼就是在参加婚礼的路上哈哈希望大家还是一起开心快乐幸福把哈哈。\n\n还有就是老朋友装修的房子我滴妈那个门真的是巨大哈哈哈。无敌了小偷来了都望门生畏哈哈哈。不过自己设计装修真的很 nice老朋友父亲全权设计超级多人性化的地方真的是让人爱了。我对于装修第一要求就是住着舒服就行很多反人类的设计真的是恼火。毕竟房子是用来住的不是用来看的 ~\n\n简直了。郑州市动物园的动物都跟马上要死了一样抑郁的很。可能是每天上班也不快乐哈哈所有的动物都以屁股示人。大象是真的抑郁了一直在那转圈圈。所以什么是快乐星球\n\n还有就是晚上吃寿喜锅的时候遇见两个学生。让我想起来一句话最遥远的距离不是万水千山而是坐在我面前玩手机。我高度怀疑他们在手机上聊天哈哈哈。年轻人可不能早恋呀。😏😏😏\n三月\n\n前前后后半个月买了一套我很喜欢的特别实用的功夫茶具焚香品茗下棋吹牛逼哈哈 。\n绿茶、白茶、黄茶、绿茶、乌龙茶、黑茶、花茶中国 6+1 茶叶可算是喝过来一遍了,也不算是小白了。我比较喜欢红茶、绿茶、乌龙茶、黑茶、花茶,感觉白茶,黄茶相对比较小众,也不是太合我的口味。未来有时间的话会系统、全面的学习一下茶文化。不过泡茶真是一门手艺活,不会泡再好的茶叶也是糟践。\n\n大伯家的哥哥30 岁历经坎坷可终于结婚了。这一大家子一路以来太多烦恼,太多痛苦,太多的太多都随风化成雨吧。\n\n还有就是很恶心很恶心超级无敌让人烦的一件事。整件事的原委大概如下\n22 年 10 月份疫情封城期间,洗手间的水管接口处漏水。然后联系装修负责人(大姨家儿子),上门查看后说是水管质量问题。我就联系金牛水管售后,各种撕逼,要求维修。主要是因为我不懂,而且对于装修的负责人很信任。还有就是因为我自己一个人住,有两个卫生间所以不影响生活,前前后后撕逼了有半年,一闲了就去撕逼哈哈哈。后来金牛水管总公司从武汉派了工程师,全程摄像记录,最终确定漏水原因是因为拧错内丝(人为)了……\n好吧我真傻逼。还是年轻……可能成长就是不断发现自己的傻逼行为。\n四月\n\n抽空面基了一下大学同学不禁感叹时光荏苒希望我们都越过越好这个月最爽的就是去了一趟心心念念的黄山奥里给我还是要秀一下银河 ~\n爷爷生病了嗨。我都懒得吐槽…… 糟老头子坏得很!\n爷爷生病真的是给我磨的没有一点点脾气生活琐事最磨人呀只能感觉自己的韧性还是有点差虽然情绪控制的很好但是有些时候还是会因为一些傻逼的事情无语真的是忠告大家远离糟糕的事情、糟糕的人让自己活得快乐洒脱一些\n五月\n老家多年的发小也是终于结婚了我也不知道为什么要用终于哈哈。\n亲爱的老姐也是这个月举行婚礼家人一起去了泉州晋江参加婚礼。从小到大和老姐记忆最多的时候就是寒暑假和过年了往后也是拥有了自己的小家想必日后也少不了被生活牵绊希望我们都可以健健康康开开心心的过小日子不过老哥的头发还是要多补补哈哈哈。🎃🎃🎃\n\n\n月末和小雅一起去了胖东来胖东来依旧是数十年如一日的服务品质买了一些生鲜水果茶叶饮品。晚上又去了曹魏古城转转感觉还行就是有点累。\n本来五月底六月计划去青甘大环线呢结果一言难尽在可预料的上半年中果真如我猜想的那般忙的要死这些事并不是说压力呀烦躁啊主要就是可磨人很多事不想再唧唧哇哇的说一些乱七八糟没用的了。就连这篇博客也是拖拖拉拉的写了一个多月。\n六月\n六月刚刚开始有条不紊的恢复着慢慢来吧 ~\n看着难受是吧说实话我写着也挺难受的磨磨唧唧的写了两个月哎西吧。感觉真的写作方法有问题需要系统性的学习一下写作方法了\n2023 年下半年,冲冲冲!!"},"Personal/Blog/2023/浅尝-Gitea-的-Actions":{"title":"浅尝 Gitea 的 Actions","links":[],"tags":["博客/原创","Git/高级"],"content":"前言\nGitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,它都能够高效而轻松地帮助团队和开发者,实现包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD 等功能。它与 GitHub、Bitbucket 和 GitLab 等 比较 类似。\nGitea 的主要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。通常我把 Gitea 称为 GitHub 的青春版,但一直以来它缺少 CI/CD 功能,因此一直只被用作代码托管的中转站。\nGitea 最初是从 Gogs 分支而来,有关分支原因的详细信息可以在 这里 找到。然而,自从 Gogs 分叉后Gitea 的社区壮大,但对内置 CI/CD 的需求也在不断增加。终于在 2020 年 11 月 13 日,南开大学软件学院的毕业生肖伦文( Lunny )提出了 #13539 提案:\n\nAn internal CI/CD system compatible with Github actions workflow yaml syntax, action yaml syntax and most action plugins.\n\n经过社区长达两年的不懈努力从 Gitea 1.19 版本开始Gitea Actions 已经成为内置的 CI/CD 解决方案(需要手动启用)。然后又经过两个版本的迭代,从 1.21.0 版本开始,默认情况下启用了 Actions。总体而言Gitea Actions 与 GitHub Actions 相似且兼容,它的名称也受到了 GitHub Actions 的启发,可以简单地将 Gitea Actions 视为 GitHub Actions 的子集。尽管 Gitea Actions 旨在与 GitHub Actions 兼容,但它们之间仍存在一些 差异。\n与其他 CI/CD 解决方案一样Gitea 不会自行运行 Job而是将 Job 委托给 Runner。Gitea Actions 的 Runner 被称为 act runner它是一个独立的程序使用 Go 语言编写。它是基于 nektos/act 的一个软分叉,而 nektos/act 是一个开源工具,用于在本地模拟 GitHub Actions 工作流程。\n如果您非常熟悉 GitHub Actions几乎可以无缝迁移到 Gitea Actions。我想分享这篇文章主要是因为互联网上相关经验贴子较少同时分享一些我的心得体会。\n基本概念\n\n工作流Workflows在两者中工作流是自动化过程的定义描述了一系列任务如构建、测试和部署应用的执行方式。\n事件Events工作流可以由各种事件触发如代码推送、拉取请求、定时事件等。\n作业Jobs作业是工作流中运行的一系列步骤。作业可以并行运行或按顺序运行。\n步骤Steps步骤是作业中的单个任务可以执行脚本命令或者使用特定的动作actions。\n动作Actions动作是在步骤中执行的独立任务可以是内置的、来自市场的或者是自定义的。\n变量与密钥Variables & Secrets可以设置环境变量来管理配置和共享数据。\n缓存Caching缓存依赖项和其他常用资源可以帮助加快构建和部署过程。\n日志与监控Logging & Monitoring可以提供详细的执行日志帮助监控和调试工作流。\n\n环境配置\n\n\nGitea 安装\n\n\nGitea Actions 的 Runner 部署\n\n\n由于 Gitea 提供了非常丰富的文档,所以我就不一一赘述了 ~\n在实际体验中将 Gitea 和 Act Runner 部署在一台 1 核心 2GB 的云服务器也是可以的。Act Runner 的日常运行仅占用约 30MB 左右的内存。不过每个 Runner 的具体资源消耗取决于仓库中的工作流脚本。\n此外您还可以将 Gitea 部署在公网服务器上,将 Act Runner 部署在本地服务器上。即使是一台二手服务器,只要满足以下网络架构要求,都可以使用。\n网络架构\ngraph LR\n subgraph internet[Internet]\n github_com[github.com]\n docker_hub_com[hub.docker.com]\n other\n end\n subgraph server1[Server 1]\n gitea[Gitea]\n end\n subgraph server2[Server 2]\n act_runner[Act runner]\n job_container[Job container 1<br>Job container 2<br>...]\n end\n act_runner -->|1| gitea \n job_container -->|2| gitea \n act_runner -->|3| internet\n job_container -->|4| internet\n\n使用 Gitea Actions 只需要确保 Runner 能够连接到 Gitea 实例。互联网访问是可选的,但如果没有互联网访问,将需要额外的工作。换句话说,当 Runner 能够自行查询互联网时,它的工作效果最好,但您不需要将其暴露给互联网(无论是单向还是双向)。\n工作流脚本\n要求\n\n默认情况下Gitea 需要手动启用 Actions也可以 手动配置默认启用 Actions 单元以适用于所有新仓库。\nGitea Actions 需要一个以 .yaml 扩展名的文件,放在存储库的 .gitea/workflows/ 目录中,例如 .gitea/workflows/demo.yaml。\n\n示例\nname: Gitea Actions Demo\nrun-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀\non: [push]\n \njobs:\n Explore-Gitea-Actions:\n runs-on: ubuntu-latest\n steps:\n - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."\n - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"\n - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."\n - name: Check out repository code\n uses: actions/checkout@v3\n - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."\n - run: echo "🖥️ The workflow is now ready to test your code on the runner."\n - name: List files in the repository\n run: |\n ls ${{ gitea.workspace }}\n - run: echo "🍏 This job's status is ${{ job.status }}."\n语法\n目前 Gitea 官方尚未提供 Actions 语法的标准文档,但官方建议直接参考 GitHub Actions 工作流语法。\n变量\n目前 Gitea 支持在用户、组织和仓库级别创建变量,变量的可见性级别取决于它们的创建位置。\n\n用户级别适用于用户所有仓库的 Actions。\n组织级别适用于组织内所有用户仓库的 Actions。\n仓库级别适用于仓库内所有 Actions。\n\n变量名称有特定的命名规则例如只能包含字母、数字字符和下划线不能以数字开头不能以 GITHUB_ 和 GITEA_ 开头,并且必须是唯一的。创建后,变量会自动填充到 vars 和 secrets 上下文中,并可在工作流中使用。\n变量的语法为 ${{ vars.xxx }} 和 ${{ secrets.xxx }}。\n进阶功能\n指定 Act 运行 Runner\n如果你有多个 Act 节点,希望将某个工作流程运行在特定的 Runner 上,你可以在不同的 Runner 上分配不同的标签(可在 Runner 管理面板编辑标签),例如,你可以创建两个 Runner分别标记为 linux_runner 和 windows_runner。\njobs:\n My-Gitea-Actions:\n runs-on: linux_runner\n runs-on: windows_runner\n复用 Github 的脚本\n在编写步骤配置时通常会引用其他人编写的脚本例如\n- name: Login to DockerHub\n uses: docker/login-action@v2\n \n- name: Login to DockerHub\n uses: my_custom/other-action@v2\n然而对于 Gitea Actions默认情况下在 1.19 之前,它会尝试访问 Gitea.com 这个代码托管仓库,因此,如果脚本位于 GitHub 上,它将无法下载脚本内容。而在 1.20 及以后版本中,默认会访问 GitHub.com。\n因此如果在下载脚本时遇到问题建议明确指定脚本地址例如\n- name: Login to DockerHub\n uses: github.com/my_custom/other-action@v2\n或者通过修改 Gitea 的 app.ini 配置,将下载源指定为相应的仓库:\n[actions]\n# 1.19 可直接填写任意url如github.com\n# 1.20起,不填默认从 github填self表示从自建仓库下载\nDEFAULT_ACTIONS_URL = self\n使用 Docker 等工具\n在 GitHub Actions 中,默认工作环境可以直接使用 Docker 命令,但在 Gitea Actions 中无法运行,因为 gitea act_runner 默认运行在 node:16-bullseye 镜像上,不支持 Docker 命令。这个问题在 Gitea act_runner issue 中有详细讨论。\n因为 Act Runner 可以部署在本地服务器上,因此最简单有效的解决方法是通过 SSH 直接操作本地主机。\n心得体会\nDevOps 平台软件繁多,但轻量级的 DevOps 平台软件却寥寥无几。虽然 GitHub 也支持自托管的 Runner但它的可访问性受限。GitLab 则过于重量级。\n目前 Gitea 官方社区表示 Gitea Actions 仍然在开发中,因此可能存在一些错误和缺失的功能。 并且在稳定版本v1.20 或更高版本)之前可能会进行一些重大的更改。\n总而言之Gitea 的 Actions 为开发者提供了一种实用的解决方案,特别适用于日常使用场景。值得一试!\n本文借鉴了 seepine 博主在 Gitea 系列文章中的部分内容不过请注意seepine 博主的文章撰写于 2023 年 3 月份,主要现在 Gitea 已经更新了。\n\nGitea - 搭建属于自己的代码仓库\nGitea Actions 搭建\nGitea Actions 构建 SpringBoot Docker镜像\nGitea Actions 构建 Quarkus native Docker镜像\nGitea Actions 构建 Vue Docker 镜像\n"},"Personal/Blog/2023/独立生活能力清单":{"title":"独立生活能力清单","links":[],"tags":["生活/经验","博客/原创"],"content":"这几年一直自己居住嘎嘎锻炼独立生活能力呀。本想整理一下分享可最近浏览到了青衫出品的《独立生活能力清单》超级具有指南意义和参考价值。同时再结合《中国居民膳食指南2022恭喜你离自由更进一步 ~\n自我审视《独立生活能力清单》中可以满足 90%,目前职业发展、财务管理、情绪控制,需要继续保持,进一步完善!让我们一起奔赴美好的明天 ~\n\n\n中国居民膳食指南2022版图示集\n独立生活能力清单 pdf - 来自:青衫 Aspie青衫 Aspie官网\n中国居民膳食指南2022pdf\n"},"Personal/Blog/2023/电脑坏了,我换了-Ubuntu":{"title":"电脑坏了,我换了 Ubuntu","links":[],"tags":["博客/原创","Linux/安装"],"content":"使用了将近十年的笔记本,前段时间因为太热,机械硬盘掉盘了。不过还有一块固态硬盘是装的系统,但是 Windows 系统却崩了,许多软件也都打不开了。尽管这台笔记本已经快十年了,但它的 32GB 内存和 1TB 固态硬盘仍然非常给力。然而,日常开发需要使用 Docker 和 WSL 以及 Jetbrains 的全家桶32GB 的内存在 Windows 系统下仍然感觉不够,经常会用满……\n想想以前我总是特别爱重装系统现在真的懒得折腾了。对于 Windows 11 也不太想用,而 Windows 12 似乎还很远。所幸就圆了自己曾将想用 Linux 的梦。\n不得不说现在的 Linux 桌面生态确实与过去大不相同。\n我也犹豫过 Linux 众多发行版本选哪个,不过最终还是坚定的选择了 Ubuntu。我也推荐一个 distrochooser.de 网站,可以帮助你结合自己需求选择最合适的发行版本。\n第一个坑关于电脑硬件驱动的问题\n这个是一定要清楚的虽然 Linux 是开源的,但一些硬件驱动却是闭源的。如果你的电脑硬件比较新,而你选择了 debian折腾起来会有些许麻烦。甚至有些硬件例如 Windows 的指纹解锁和 LED 发光键盘可能根本没有驱动。\n\n在这方面Ubuntu 做得非常好,系统自带的 ubuntu-drivers 能够傻瓜式安装驱动。\n第二个坑关于更新频率的问题\n\n在使用了将近十年的笔记本后它在不久前因为过热而停止运作机械硬盘也出现了问题。虽然我还有一块装有系统的固态硬盘但 Windows 系统却崩溃了,许多软件也无法打开。尽管这台笔记本已经快十年了,但它的 32GB 内存和 1TB 固态硬盘仍然非常强劲。然而,在日常的开发工作中,我常常需要使用 Docker、WSL 以及 Jetbrains 的全家桶即便如此32GB 的内存在 Windows 系统下仍然感觉不够用,经常会用满……\n回想起以前我总是喜欢重新安装系统但现在真的感觉懒得折腾了。对于 Windows 11 我并不太感兴趣,而 Windows 12 似乎还遥不可及。幸运的是,这让我终于实现了使用 Linux 的梦想。不得不说,现在的 Linux 桌面生态确实与过去大不相同。\n在选择 Linux 的众多发行版本时,我也曾犹豫不决,但最终还是坚定地选择了 Ubuntu。同时我也想推荐一个网站 distrochooser.de它可以帮助你根据自己的需求选择最合适的发行版本。\n第一个挑战电脑硬件驱动的问题\n这是一个必须要清楚的问题。虽然 Linux 是开源的,但一些硬件驱动却是闭源的。如果你的电脑硬件比较新,而你选择了 debian可能会遇到一些麻烦。甚至有些硬件例如 Windows 的指纹解锁和 LED 发光键盘可能根本没有驱动。\n\n在这方面Ubuntu 做得非常好,系统自带的 ubuntu-drivers 能够傻瓜式安装驱动。\n第二个挑战更新频率的问题\n\nLinux 的发行版本众多,更新频率主要分为两种:定期更新和滚动更新。它不会像 Windows 那样强制要求更新,选择权完全在你。但是,你必须学会使用 sudo 而非默认使用 root这样在大多数情况下就不会出问题。\n毕竟 Linux 可是出了名的稳定!\n第三个坑关于桌面环境的问题\n\n在 Linux 中,一切都是文件,桌面运行环境也只是一个软件包。可以根据自己的喜好选择喜欢的桌面环境,不必再担心内存占用的问题。毕竟现在是 2023 年了,你的电脑不会连 8GB 运行内存都没有吧?\n第四个坑关于软件生态的问题\n这是一个非常重要的问题。首先我们可以将软件生态分为国内和国外两种情况。从我的主观感受来看国外的主流软件有 90% 都有 Linux 客户端,而国内的主流软件只有 40% 有 Linux 客户端。不过针对国内的特殊情况deepin 结合 wine 适配了 90% 的国内主流软件,虽然使用起来有些不足,但基本上已经够用了。\n接下来只需要使用以下两种方法你就可以解决 80% 的常用软件问题。\n\ndeepin-wineDebian/Ubuntu 上最快的 QQ/微信安装方式,作者提供了简单,快捷的使用 deepin 的 wine 应用方法。\nFlathub一个开源的应用程序分发平台旨在为 Linux 操作系统提供简便的软件安装和更新方式。它基于 Flatpak 技术Flatpak 是一种容器化的应用程序打包和分发格式,可以在不同的 Linux 发行版上运行。\n\n第五个坑关于打游戏的问题\n\n也许你可能还想玩游戏比如玩玩《饥荒》、《缺氧》或是一些 3A 大作。没关系,安装了 Linux 并不意味着你必须放弃游戏Steam 已经为你准备好了一切。\n心得体会\n说实话从多年的 Windows 切换到 Ubuntu阵痛感确实非常强烈。一开始使用时很多地方都感觉不舒服特别是一些小细节的折腾会让你感觉发狂例如输入法和显卡驱动的问题。但是一旦你度过了这个阵痛期你会发现一切都变得非常舒适简直是完美\n首先老笔记本又焕发了新生32GB 的内存根本用不完。各种开发工具只需要一个 apt install 命令就能安装系统运行非常流畅特别是字体渲染Windows 字体优化的跟 💩 一样。\n然而Ubuntu 在很多细节上还是不如 Windows 和 Mac。我也使用 MacMac 的体验确实非常好,但高配置的 Mac 对于我的荷包来说实在是太贵了,而且内存的价格简直比黄金还贵。\n不过作为开发者的神器Mac 的地位是毋庸置疑的Linux 还需要时间来追赶。\n🥰🥰🥰 多尝试总归是好的。对了,中秋节快乐 "},"Personal/Blog/2023/看-V2Ex-的-ChatGPT-老哥浅谈办公室政治":{"title":"看 V2Ex 的 ChatGPT 老哥浅谈办公室政治","links":[],"tags":["工作/经验","博客/原创"],"content":"前段时间 V2Ex 论坛有几篇关于职场政治的帖子特别经典耐人寻味值得多读几遍。整个事情大概是这样的GPT 老哥入职一家新公司,由于他的工作理念没有天朝特色,最后一步步以黑色幽默的结局惨淡收尾。\n整件事情的时间线大致是这样的链接需要全球上网\n\n我给公司部署了一套 ChatGPT, 老板说没有目的性, 给我这件事的绩效打了个 C, 如何评价这一现象?\n\n\n我主动给公司部署了一套 ChatGPT, 也给公司所有员工展开 AI 及 ChatGPT 的入门使用培训, 希望大家能更好地利用 AI 工具 来提高工作效率, 现在每天不同岗位提问的数量有 200~400 条左右 (公司有 100 人左右), 老板自己也用它来翻译各种文档和写各种文档的大纲等等, 结果老板给我的月度绩效考核时说这件事没有目的性, 也没有对业务到底帮助多少的数据支撑, 就这件事本身给我打了个 C, 我心里是不服气的, 但不知道如何反驳, 如何评价我做的这件事以及老板对我的绩效考核?\n第 1 条附言\n补充点信息: 公司有 2 个老板, 给我打 C 的是二老板, 面试时候 2 个老板都面过我, 面完本来他们觉得我管理能力不行 (我估计是 2 老板觉得的), 过了 1 个月后大老板加我微信, 又约我聊了下, 说他还是比较倾向于技术纯粹的人, 他说他是长沙人, 觉得 ” 辣椒不管怎么样还是辣最重要 ”, 于是我进这家公司了, 做技术经理, 进公司后归二老板管, 大老板比较闲云野鹤, 不怎么管公司内部具体事宜。\n我部署 ChatGPT 这件事, 也是大老板微信我说他朋友的公司用 ChatGPT 做了很多好玩的事, 当时我正好在研究自己部署 ChatGPT, 就和老板说了我打算给公司部署一套, 大老板给我了肯定和支持, 说 AI 优先, 逐步推广起来。等到周一我也和二老板说了,他没什么态度,就说试试看,后来我开展培训的时候大老板也来听了, 二老板没来听。\n\n\n我就是上次给公司部署 ChatGPT 的, 今天被开了\n\n\n除了这件事, 还有另外一件也是我主动发现, 然后开发进行优化的事\n背景: 我发现投放部门每天每个人都要花费 1 个多小时去做重复劳动力的事, 并且做出来的月报数据不准确。\n目标: 开发 RPA 帮助投放部门释放生产力。\n**行动:**用 1 周的时间完成 RPA 的开发上线, 交付给投放小组使用\n效果: 用户给出的评价: 使用频率: 每天满意度: 非常满意响应速度: 非常快数据准确性: 非常准确\n“在查询日报、周报、月报及回本数据时大大减少了人工查询成本并且增加了 7 日、14 日、30 日数据情况,因此便于每日查看当日回本进度,便于投放把控投产及回本情况。”\n第 1 条附言\n这次来吐槽主要也是想快点找到工作, 就像我最后截图说的, 现在一个人养家, 压力大, 我想找架构师工作 (我老婆也说我性格幼稚不成熟, 不适合做管理, 我个人自我评价也是对技术对人都是 ” 赤子之心 ”), 开发经验 10 年, 坐标杭州, 各位 V 友如果有推荐的岗位, 不胜感激 [抱拳]\n第 2 条附言\n回复各位网友我的岗位和职责:\n\n我的岗位是技术经理 (技术负责人), 面试时候就说进来后所有技术都是我这边管理; 我想着既然是技术 leader, 就应该用技术服务于大家, 立好技术团队的旗帜;\n进来试用期就定了 2 个目标:\n\n1). 制定技术团队人效框架 (背景是二老板需要有一个相对客观的产出评估工具给所有员工打绩效), 我花了 2 周左右时间也做出了, 现在也在按这个框架管理所有的开发同学, 但是二老板后来说我没有继续跟进改进框架;\n2). 研发 AI 智能客服机器人, 我们是 2c 的电商互联网公司, 所以客服团队人员也是较多的, 老板希望用 AI 来解决客服团队的效率问题, 当时定的计划是 8 月底 AI 回答采用率达到 90%, 其实这件事我就用了 v 友推荐的 dify 这个开源产品 +gpt 的能力, 就做好了, 本身不需要写什么代码, 结果采用率已经到 95% 以上了; 二老板说如果没有 gpt 怎么办, 那我说就是要自研模型, 需要算法工程师岗位来做公司内部模型这件事, 但是公司没有算法工程师, 招聘又迟迟没有结果, 于是这件事在二老板看来我就没有继续做下去了;\n其实大家可以看出来, 如果只是这两件事, 我其实事情并不多 (特别是技术上面), 所以想主动做点事, 想充分发挥自己的价值, 结果现在就这样了\n第 3 条附言\n二老板喜欢否定和踩人, 这是公司员工基本都感受过的感觉, 很多人都怕和他开会, ” 我一开始真的以为自己没做好, 后来发现好像不是这样的, 而且就算下次我改进了, 他也不会说好的地方, 继续挑刺说我其他不好的地方 ”, 这是其他同学的原话, 还有同学说我 ” 直脾气, 只做事不做人,在这里吃亏的, 老板只喜欢听话的 ”, 我脾气是真的直, 如果否定, 指责我时完全子虚乌有, 指鹿为马, 我会会上当场怼回去\n第 4 条附言\n很多同学让我下掉我主动做的两个服务, 二老板昨天让 2 个开发来交接我这两个服务, 我没有拆, 不过…, 我也下掉了自己的 api-key\n第 5 条附言\n希望大家不要抓些敏感信息, 甚至去 ” 定位 ” 到公司或人, 这样可能对我不利, 我希望所有吐槽就在 V2 这个小圈子里消化掉, 拜托各位 V 友啦🙏🏻\n第 6 条附言\n我想过了, 其实我被老板开, 和我主动多少事没有一点儿关系, 我主动做的对其他部门, 对公司有价值的事也不会在他心里留下什么不开的理由。本质上来说, 就是我面对一个喜欢 PUA 的又不实事求是的领导, 选择了怼回去, 这才有这样的结局, 不管以后在哪家公司, 我如果有技术上能帮大家的还会继续去做;如果我面对一个喜欢 PUA 的又不实事求是的领导, 我可能还会怼回去, 也可能会更成熟地去面对;\n\n\n我是 GPT 老哥, 现在公司因为我下了自己的 API-KEY 威胁我, 我可以怎么办\n\n\n关于我的情况详情见: v2ex.com/t/966243 交接时已经和技术同学说了我要下掉自己的 key, 因为用的是我的钱, 只是之前找公司报销, 以后不可能再用我的钱, 也告诉他应该怎么申请 OPENAI 的账号和 key, 结果我收到这样一份邮件, 请问各位 V 友我可以怎么保护自己\n\n第 1 条附言\n大家讨论怎么解决, 不要网暴, 否则那公司会更恶心, 谢谢\n第 2 条附言\nHR 经理说提前三天通知, 没有赔偿, 我想仲裁就去好了\n第 3 条附言\n刚才我联系了以前同事, 原来是他们 VPN 到期了, 然后碰巧遇到我的事, 那些老板和高层不明所以就怪到我的头上, 所以发了这封邮件, 现在 vpn 恢复了, 他们用新申请的账号可以继续用了\n第 4 条附言\n刚打电话给律师了, 他说因为我签的是主动离职, 所以现在也无能为力了, 这个亏我吃过记住了\n\n\n一开始 GPT 老哥因为工作中绩效被打了个 C郁闷得想在 V2Ex 寻求安慰和解决方法。不过后续事情发展的节奏,我甚至一度以为是钓鱼贴。不过其中最有趣的就是评论,开始的一边倒,以及后续种种声音的出现,完美地诠释了群体的愚蠢。\n我也只是刚度过职场的新手期开始真切的体会到所谓的职场政治。我是一直都认为职场就是打工的地方打工就是为了填饱肚子我们都是打工的为什么大家就不能团结一致一起奋斗而是总窝里搞斗争呢\n先说一件曾让我苦恼许久的事吧。在大一的时候前班长的种种原因机缘巧合下我被选为班长据说是因为我学习好……毕竟对计算机科学数十年如一日的热爱因此我在系里成绩一直都是前几加上许多事情班长要身先士卒还有高中体育特长生的经历那真是德智体全面发展各种荣誉奖状一摞摞。\n事情就发生在大二报名竞选国家励志奖学金的时候。现在我的记忆还很清晰那天早上还没睡醒院系书记给我打电话\n\n\nXX醒了没\n\n\n咋啦老师有什么事情你说\n\n\n没啥事最近班里情况怎么样\n\n\n老师你放心没什么问题。\n\n\n当初看各方面能力都很强推荐你当班长这么长时间办事一直让我很放心。最近不是要报名竞选国家励志奖学金么你做好宣传工作鼓励大家积极参与。\n\n\n好没问题宣传部长已经通知到位了。\n\n\n你上次国家程序设计大赛是不是拿了个二等奖\n\n\n是上次主要因为准备时间不足下次一定提早准备争取得奖。\n\n\n上次校田径会你是不是跳远季军还有篮球赛和其他系一块拿了个季军\n\n\n是咋拉\n\n\n最近国家励志奖学金我看了看要求你的很多奖项不够加分的标准我觉得你还是不要报名竞选了避免到时候选不上下不来台。\n\n\n我尝试尝试吧也不一定能选得上。我不知道怎么回答\n\n\n行那你好好考虑考虑。\n\n\n挂了电话顿了很久我理解了话里有话却又无法接受。她一位院系书记给我打电话暗示不要参加竞选最终我还是没有报名但毕业后我意外地收到了一笔 5000 元大学生创业奖金。\n后来正式工作的第一年是 DBA 职位,主要负责业务系统数据维护和企业数据分析方面。直属领导性格比较闷,有着技术人的偏执。实际工作中并没有所谓的传帮带,默许你是一个工作经验十分丰富的人,一开始经常会直接把问题丢给你,不懂就是自己学会去阅读文档。\n可是大哥这文档都是多长时间没有更新了……\n从集团到分公司仅有一份年久失修的 OneNote 文档,登录成功全凭运气。 数据库表中还有拼音命名法,一个表中几十个字段没有备注,字段命名就更随心所欲了,甚至连业务逻辑都写到存储过程中。而且我还遇见过一个最变态的诉求:业务部门的一位同事,需要导出数据进行分析,我 count(*) 了一下数据量上千万行。我怀疑自己代码写错了,都没有怀疑他业务需求存在问题。在三确认后,没问题我就直接导出来了,大概有十几个 GB 的 Excel 表格。最后,她过来拿 U 盘拷贝走的,我滴妈,你就是能打开,你又能干啥?\n还有其他很多奇葩的事情你都难以想象这是中国 100 强民营企业……\n期间直属领导正好新婚部门大 Boss 表示大家都是同事多少都行100-1000 不等哈。我想了想决定随 500 元,婚后上班直属领导对我的态度就有了很大的改善,也不再叼我了。\n第二年部门人员满编需要定岗定编时在部门会议上我主动申请转网络组。那时候部门 Boss 再三确认,可我当时是真没明白什么意思。\n网络组主要维护公司本地数据中心并兼职许多其他的事情。主要是由 A 和 B 两个人负责,后来加上我一共只有三个人。我一直以为男生之间的关系相对于异性容易处理,毕竟三个女人一台戏,没想到三个男人更是一台大戏。\n先简单的介绍一下 A 同事A 是部门的老前辈,在公司干了十几年,同时是部门 Boss 的校友他平时工作极其悠闲堪比养老。B 同事关系户,之前公司老总的外侄子。先从宏观层面说一下网络组的问题,就是所有的事情只要 A 和 B 没有点头,那么这件事再好也干不下去,辞退谁都辞退不了 A 和 B。整个公司的数据中心维护只有他俩能处理离了他俩就不能转。\n到这就明白当初为什么部门大 Boss 再三确认了吧,可那时的我真的不不明白……\n而我作为新来的干劲十足充分根据网络组现有问题做出了大量改进和优化创造了许多可以量化的价值。这些事情并不像前面的 GPT 老哥那样,而是事先打好招呼,分析好问题,规划具体,设计方案,实施总结。别的不说,就这些改进优化,至少为公司把我一年的工资赚了回来。而且我做这些事情的目的,也不是为了争夺利益,主要是因为许多事情效率极其低下,我真的不想浪费生命。\n于是我后续进一步推进很多其他事情阻力就特别大是所有的事情不是一两件小事。无论你提出什么都会在第一时间反驳你借口你是年轻人为由想法不成熟打压你总是喜欢拿公司安全来否定你想干的事情。\n\n\n例如某个事情可以花小钱办大事结果说我想法不成熟不成熟就不成熟呗。可是后来自己又拿这个出来风风火火地搞了起来。\n\n\n例如我都来三年了现在我只能处理一些边边角角繁琐杂事。所有与数据中心相关系统没有任何访问权限需要进行权限操作的事情都需要联系 A 或者 B 处理。\n\n\n例如企业微信的自建应用需要企业主体域名绑定认证然后才能进行开发。部门会议我提出申请一个公司域名是的我们这么大的公司没有可以让开发用的域名。更可笑的是同事 A 怕公司因为这个域名导致停业,理由是信息安全。\n\n\n例如去年底部门大 Boss 绩效面谈,客套话说尽。最后来了句,同事 B 今年也不小了29 岁),买房子还贷款,所以今年绩效就不给我了。争取明年给你……\n\n\n例如某次部门会议上部门大 Boss 要求我们搞一些创新。我实在忍不住就硬刚了 A 同事,大概意思就是阻力太大,事情干不下来。部门大 Boss 碍于场合的关系,要我必须做出成绩,于是乎大家不得不配合我。后续两三个小项目做成了,创新项目也交给了集团,进了创新月报,最后还有奖品哈哈哈。\n\n\n于是乎我们彼此在工作中你恶心恶心我我恶心恶心你。还有许多类似的事情再一一赘述我就真的变成怨妇了。\n你肯定要问为什么不离职换家公司主要原因是\n\n\n公司是该行业民营龙头主要做业务。不局限于技术我能学习的东西实在是太多了。\n\n\n周末双休每周实际工作时间不超过 8 小时,平均 4 小时,其他时间自由安排。\n\n\n基于上述两点大多时候我还是很喜欢这份工作的毕竟有一份可以养活自己的工作无限的学习时间。还有之前疫情期间可以正常工作管吃管住。不过现在也到了快要离开的时候了……\n客观来说现在这份工作的职场环境我们只是存在一些观点上的冲突并算不上什么政治。同事 A 和 B 其实也没有错,大家都没有错,**只是我不应该在这个地方搞这些事情。**事实上我们也并没有产生大的冲突,毕竟我做得再好,也许还抵不上他们之间的那层关系,毕竟这么大的公司离了谁都能转。\n终究是屁股决定脑袋重要的是说你行的人要行你也许才是真的行。\n生活处处是围城职场政治可能在当下根本无法避开。我呢通过咨询老前辈深度阅读 V2Ex 帖子,询问 ChatGPT 总结了一些法则,希望对你有些许帮助。\n\n\n了解环境每到一个新环境没有系统全面的了解前不要站队。\n\n\n建立良好关系每位领导都是不是圣人投其所好好好经营关系。\n\n\n保持专业态度有能力没关系不可怕最怕的是没关系还没能力。\n\n\n透明且谨慎任何没有正式通知的事情都谨慎对待谨慎处理。\n\n\n保护自己大部分人不会在一个地方工作一辈子永远相信自己保护自己。\n\n\n明智地选择战场君子不立于危墙之下职场博弈务必选择自己擅长的事情一击必胜。\n\n\n倾听和观察充分熟悉了解每个部门办公室的政治和文化。从而灵活适应不同的工作环境。\n\n\n寻求外部指导如果陷入职场漩涡不知所措。寻找一个行业内有经验的导师付费咨询。\n\n\n保持真实性不必为了一份工作平衡自己的价值观努力寻找适合自己的地方生根发芽。\n\n\n人生在世读懂人心理解人性尊重利益"},"Personal/Blog/2023/破万卷书,行万里路!":{"title":"破万卷书,行万里路!","links":[],"tags":["游记/川西","游记/重庆","游记/丽江","博客/原创"],"content":"正所谓破万卷书、行万里路;现在虽然离万卷书还有 9987 卷但已经是行万里路了我呢心里早就对滇川藏充满了极大的渴望更对雪山、草原、森林和江海憧憬已久。春节后的大年初四1 车 8 人 9 天说走咱就走,风风火火闯九州!\n在重庆\n下午出发在经历了 12 个小时的奔袭后,次日早上七八点到了重庆解放碑某不知名地下停车场。那时候实在是困的要死,就想找个钟点房洗洗休息一下;可我至少打了 30+ 个酒店电话,说是都没有房间,最快也要等到 10 点之后。\n这样、还睡个溜溜球收拾一下占领重庆。我们的计划是先去江边溜一圈、感受一下长江索道中午再吃个重庆小吃、之后乘游轮晚上再吃个重庆火锅就前往下一站。但后来才知道重庆的人实在是太多了好像中国 14 亿人中有 20 亿人来了重庆······\n\n停车场一出来就看见好多人聚集在街边小店吃重庆小面我们也一起去凑了个热闹。小面对于重庆来说就好像河南离不开胡辣汤一样哪里都有重庆小面。随后一路跟着导航来到了江边也是真正的体验到了山城的精髓你以为你在一楼其实你在十楼你以为你在最底层了其实下面还有一层……\n总体来说就是平原城市的导航是前后左右的重庆的导航是上下前后左右的。\n\n当然这并不是我男朋友给画的但是画得好重庆大部分景点都是以解放碑为中心我们也是从解放碑出发来到江边再走到洪崖洞。重庆洪崖洞堪称重庆必打卡的景点形如《千与千寻》的汤屋。尽管白天的洪崖洞像个素面朝天的灰姑娘但一到晚上摇身一变换上水晶鞋披着灯红酒绿的外衣令人流连忘返\n\n> chatGPT 给大家讲解一下中国重庆洪崖洞的历史。\n> 重庆洪崖洞是一个位于中国重庆的洞穴景点,有着悠久的历史。它始建于明朝,是一个重要的寺庙和避难所,也是当地犯罪分子的藏身之处。洪崖洞因其特殊的历史和文化价值而受到了广泛的关注,如今已成为重庆的一个旅游胜地。\n我们买了夜游船票准备徒步到长江索道感受长江的魅力。乍看路程也就 900 来米,分分钟不就过去了,但这 900 米是上上下下的 900 米。我们几人硬是半个小时才到,但谁也不知道更恐怖的在后面。\n游客中心的屏幕提示前面等待 8000+ 人,最快 2000+ 可以坐上缆车(当时早上 10 点多)\n> 大哥,这长江索道的缆车票是不是买不到了?\n> 你现在买只能明天坐了,索道有啥子好玩的;都是骗外地人的,江对岸来回 30 块,打个车才 10 来块。你以为三四个人一个缆车?那六七十个人挤在一个缆车里,最里面的人看个篮子。\n> 大哥,你有没有 vip 通道,可以加钱的那种?\n> 没有。你现在还不如去云端之眼了,一个人 50 元。还不用排队,比坐索道好玩多了。\n> 我······\n> 你们现在还是到老城区吃个火锅,不然晚上站在那看着别人吃,可能等到最后连个菜毛都没有了。\n> 这么恐怖么?\n> 昨天还是前天,洪崖洞最少来了 15 万人,这么一点地方,还能干啥?要想去景点就预约明天的票,今天是不可能了!\n我就想做个缆车重庆的人属实给我上了一课这还能咋地吃火锅呗 ~\n来到老城区感情还没进门呢空气中弥漫的辛辣味我仿佛已经被”七上八下“了。不过重庆火锅确实美味对比内地的火锅其香辛辣更纯粹在食材方面并没有质的差距形式上也更为丰富。不过只有油碟可能会有人不习惯饭后暗暗感觉重庆的肛肠医院绝对很挣钱 🤣🤣🤣\n\n饭后小憩一会不过在见识到重庆的人山人海之后四点我们就出发去坐六点半的邮轮卷死他们来到江边后找到个桌位点上一壶茶叶吹过来的江风是真 TM 的冷啊。时间一到就去排队登船,最后使出浑身解数才换得好位置。\n嘟··· 一声汽笛打破了所有的喧闹,看、这就是重庆!\n\n\n\n\n上岸后我直接愣住了这人也太多了吧连长江大桥全都是人重庆真是无愧于网红城市称号中国 14 亿人全来重庆过年了哈哈哈 ~\n重庆之旅不虚此行毕竟要满足对网红城市的好奇心但重庆可能并不会给你太多的惊喜必须要去老城区去吃火锅\n下一站丽江。\n丽江古城\n\n云南丽江是一个充满历史文化和自然美景的城市其中以玉龙雪山最为著名这座高耸的山峰是该地区最高的山峰。另一个不可错过的景点是丽江古城这是一个充满生机和活力的古老城市拥有众多历史遗迹、寺庙和古建筑其中包括南诏皇宫和木府等。再有就是茶马古道这是一条连接中国和西藏的古老道路穿越了壮丽的山脉和河流。它曾经是一条重要的商业道路现在已经成为了一条热门的旅游路线吸引了许多历史、自然和户外运动爱好者前来参观。\n\n来自 ChatGPT 的介绍\n\n丽江这次给我的印象就是用烫水冲泡的茉莉花茶香味四溢口感发涩。以往云南省旅游宰客可是出了名的狠正所谓靠山吃山靠水吃水虽然现在整改得非常规范、透明但是这次去了也并没有留下多少好感。\n我们从郑州出发经过重庆到达丽江路程超过了 2000 公里。下午两点左右到达丽江的时候已经是要累死了。只想立刻马上入住酒店睡觉!民宿老板服务倒是挺周到,拉着小车过来帮我们搬运行李。但第一个吐槽的就是住宿,价格贵就不说了,毕竟一个愿打一个愿挨。但是一定不要听信民宿老板的屁话,总之赚钱赚钱就是为了赚钱。建议问问题之前先说:中国人不骗中国人!\n\n民宿出门就是丽江古城古城虽然古色古香、小桥流水但却容易产生审美疲劳大街上卖来卖去的就那几样东西。而且还感觉人都是重庆连夜跑了过来的好多人啊😭。我们走着走着就容易腰疼腰疼得厉害哈哈。\n古城里有许多穿着少数民族服饰的姑娘拍摄写真。想必未来有机会和心上人在这里拍婚纱照也是浪漫至极吧。一路上一间挨着一间的商铺塞满了琳琅满目的商品。尽管商品明码标价但是胡乱标价还是有的。就比如银子一克 21.9 元不能谈价,国际银价才五块左右,这不是妥妥坑人的么?感情这手工费金手打造的吧。\n这次来云南滇红和普洱茶是必须安排好的。但望着满大街的茶叶一时间无从下手。返回民宿的路上发现了一家看起来不错的店铺随便走进去逛逛。老板非要留下品茗交个朋友最后还是按奈不住买了共计一斤的滇红我都惊呆了严重怀疑朋友喝多了。这一斤茶叶喝到猴年马月了……\n我们走了之后寻思着得占占便宜不能就这么爽快走了转头回来表示要尝一下普洱茶。\n> 老板,尝尝你的普洱茶。\n> 来来,坐;老板自顾自地 abcdefg\n品茶……\n> 有没有更好点的?\n> 刚才这款普洱茶饼是 1200 元的,你想要什么价位的?\n> 送领导的,不能太差。\n> 那我建议你送这款xx 年的普洱,只要领导一尝就知道绝对不便宜;这个售价 2800 元。\n品茶……\n品茶……\n品茶……\n> 确实不错,我们虽然不太懂茶,但是风味差距确实很大,方便加个微信日后联系么。\n🤣🤣🤣\n\n\n晚上就想去古城最高点观赏夜色到了才发现被各种楼房给挡得严严实实连一条缝儿都没有想看就掏茶水费。还有就是云南的任何一家过桥米线味道都差不到哪去各位理性打卡网红店吧。在丽江呆了两天吃了好几顿米线有些米线给你搞的花样蛮多仪式感嘎嘎的有些就是朴实无华端上来开造我感觉真的大差不差并没有质的差距。\n\n本来还是要去玉龙雪山但官方的票也是订到三天之后了。据说当地的旅游团事先屯好门票然后就得必须走团购团购票人均 600 左右了。罢了罢了,来日方长。但茶马古道还是需要体验一番的,作为一条古老的商业道路,始建于明朝,跨越了中国和西藏的山脉。主要用于运送茶叶、马匹和其他商品,故地重游骑着马、坐着船也是逍遥。\n下山之后我们在纳西族村民家里听胖金妹少数民族姑娘的称呼讲解倒是挺有趣\n\n我们纳西族崇尚圆润美在这里男人是不用干活的和你们内地是不一样的我们结婚也不需要房子、车子、彩礼倒是要送给男家几十头牦牛。就像这个小伙朋友 200+ 斤),也只有村长家的姑娘才配得上咯。\n我们这里男方虽然只会抽烟喝酒打打牌看看孩子不用干活但是男人是不上桌的任何事男人都是没有话语权的。我们这里结婚有点类似于你们哪里的上门女婿要不要考虑留在这里当上门女婿呀\n······\n\n胖金妹后来宣传起了茶叶和牦牛干试尝牦牛肉干的时候。我们硬生生给胖金妹上了一课足足一斤多的牛肉直接干完哈哈哈 ~ 结果大家真的不好意思了,还是买了点牛肉干。胖金妹表示你们真的是太好意思了!\n丽江呢如茉莉花茶沁人心脾可惜好茶也需要好茶艺啊古朴悠闲小桥流水与慢生活的感受只宜久居。虽然这次来丽江槽点一大堆不过古色古香的丽江值得一来但是丽江并不是我的菜溜溜球 ~\n下一站香格里拉。\n香格里拉\n香格里拉本为一个虚拟地名最早出现在 1933 年英国小说家詹姆斯·希尔顿的小说《消失的地平线》中、这个小村庄神秘而和谐,位于昆仑山脉西方,群山包围,由一个藏传佛教僧院统治。这个村庄的居民,长生不老,过着快乐的生活。香格里拉后来被当成为世外桃源与乌托邦的同义词。\n香格里拉位于云南省迪庆藏族自治州原名云南丽江中旬。于 2001 年 12 月 17 日申请夺得头筹被中国国家民政部批准易名香格里拉县,从此名声大噪。香格里拉这个名字的含义与中旬县古城藏语地名「尼旺宗」一致,意思为「心中的日月」。\n\n来源香格里拉 - 维基百科,自由的百科全书;\n\n\n我们早早地就离开丽江启程前往香格里拉——独克宗古城。香格里拉独克宗古城的尽头是月光广场而广场东面的小山就是著名的香格里拉龟山公园。龟山公园里有全世界最大最重的转经筒由纯铜镀金打造重达 60 吨,这里是藏人心中非常神圣的日月。\n转经筒又叫嘛呢转经轮藏传佛教信徒人人持有不停地摇转。转动经轮的功德转动一周者即等同于念诵《大藏经》一遍。转动二周者等同于念诵所有的佛经转动三周者可消除所作身、口、意、罪障。我们一起转动了九周以表敬意说实话实际转动起来挺重的。\n\n前往梅里雪山的途中经过了纳帕海我们非常想体验水上公路的风采但是只有雨季丰水期的时候才会出现水漫公路。在纳帕海简单停留拍照后我们又继续踏上了下一站梅里雪山。路上的时候我想不清楚为什么湖被称为海了解到后才知道过去藏区的少数民族就像我们渴望雪山高原一样向往大海穷极一生几乎没有看到海的机会。故此称比较大的湖泊为海、海子。\n\n正所谓得不到的永远都是最好的哈哈哈\n\n\n214 国道上 U 型弯随处可见,一路上胆战心惊地开着车。路过白马雪山的时候,忍不住国粹了起来哈哈。我是生长在内地的小孩,也都是第一次看到雪山高原。毕竟山就在那里和山就在眼前,终究是天翻地覆的差距。请想象一下照片中也有我哈哈;毕竟,摄影师都是把美好留给他人 ~\n其实我是懒得吐槽就让你们看看朋友给我拍的照片真是 TM 的一绝。我 180+ 的个子,颜值也算过得去吧?你看看这是人拍的么???🤯🤯🤯\n\n\n傍晚抵达位于梅里雪山脚下的德钦县城寻找旅馆住宿的地方时发现藏民真淳朴啊哈哈。\n> 朋友:老板,标准间住宿多少钱?\n> 320元\n> 朋友:能便宜不?\n> 最低价了,不搞价。\n> 我:能按照美团 260 么?我们开三间。\n老板娘在和大爷进行加密通话······\n> 最低 180 元\n我们留下了惊呆的眼神还可以这样子搞价\n后续来了其他客人都是 320 元开的······\n\n从重庆经过丽江去香格里拉一路上都在吃火锅我真的是要吃吐了。我们信誓旦旦的说这是最后一顿火锅也是希望明天可以顺利看到日照金山出来这些天也是不停在开车没有时差的赶路虽已微醉但觉的夜里依旧无法入睡。我就寻思着喊上朋友一起看梅里雪山的星空凌晨三点月落后我们俩就开车出发到达观景台时漫天梦幻般的繁星直让朋友头皮发麻。\n\n观看梅里雪山的日照金山有两个不错的观景台浓雾顶和飞来寺浓雾顶相较于飞来寺更适合摄影爱好者。初次来看日照金山推荐直接去飞来寺。飞来寺是国家旅游景点门票 30 元,但可以趁人多的时候浑水摸鱼溜进去。飞来寺的人会非常多,无人机也会非常多,摄影爱好者也会非常多,但日照金山可以消散这一切。美其名曰日照金山,实际上就是太阳照山头哈哈。\n下一站川西\n\n川西\n提到雪山、草原、高山和星空或许大多数人只会联想到西藏但现实中并非人人都有富裕的时间自驾 318 国道去畅游西藏。如果时间有限,又想浅尝雪山、高原和星空的话,那么川西就是不二之选!川西地处四川西部,其坐拥稻城亚丁,康定情歌,四姑娘山,贡嘎雪山等,让你不到西藏的情况下也能欣赏到视觉天堂!\n\n我们由梅里雪山出发折回稻城亚丁前往最后一站理塘——天空之城整个行程也随之慢慢步入尾声。从丽江一路走过来雪山、高原、庙宇、星空、日照金山一次又一次地不断刷新着审美阈值老实说我已经严重的审美疲劳、腻了。但川西却总是能让人有意想不到的惊喜\n废话就不多说上视频\n\nbilibili 主页space.bilibili.com/223211771\n丽江www.bilibili.com/video/BV1ER4y1q7ij\n古城www.bilibili.com/video/BV1Ay4y1f7Nf\n川西www.bilibili.com/video/BV1584y1J78R\n日照金山www.bilibili.com/video/BV1rY411Y754\n"},"Personal/Blog/2023/谈谈我的「数字文具盒」---个人工作流":{"title":"谈谈我的「数字文具盒」 - 个人工作流","links":[],"tags":["工作/效率","开源项目/数字文具盒","博客/原创"],"content":"谈谈我的「数字文具盒」系列是我一直不断打磨的个人生产力工具经验分享贴。尽管前期有些折腾,可实际用起来却是嘎嘎好用。数字文具盒一贯宗旨倡导以结果为导向,切勿盲目折腾,适合自己的才是最好的。\n我一直很重视数据自主权的数字文具盒系列中用到的工具全都是以开源项目为基础结合 Docker 运行的。本篇《个人工作流》主要分享:数字文具盒系列工具如何高效使用的流程?\n工作区\nIT 工作中大多数都会使用两个以上显示器,一台团队协作,一台写代码,扭扭脖子就可以快速「切换」工作区。而虚拟桌面功能就可以不用买显示器,变相满足「工作区」的需求,目前 Win、Mac、Linux 都已经支持了虚拟桌面功能。\n\n虚拟桌面可以理解为一台新的拓展显示器但同时只可以使用一个显示器不过你可以在多个虚拟桌面中快速切换。每新建一个虚拟桌面就像打开了一个全新的工作空间。在一个全新的工作空间中你可以安排同样性质的任务。例如\n\n\n通讯桌面运行企业微信、钉钉、QQ 等通讯工具。\n\n\n开发桌面运行 IDE、Docker、虚拟机等开发工具。\n\n\n学习桌面运行 Obsidian、Typora、Memos 等笔记工具。\n\n\n冲浪桌面当然还可以设置一个摸鱼专用的桌面。\n\n\n虚拟桌面在一定程度上可以满足多工作区的需求但是同时只可以显示一个桌面也是其痛点。工作区的最终解决方案还是建议购买 2 个以上的显示器,同时结合虚拟桌面使用。工作区的优点就是避免多个软件,来回切换窗口带来的打断感,使我们可以专心工作,学习和摸鱼。目前 Linux、Win、Mac 的虚拟桌面功能都已经非常成熟,可以参考以下文章学习使用。\n\n来源Windows 虚拟桌面的高效启动技巧 - 少数派;仅学术引用,著作权归作者所有。\n\n\n来源在 Mac 上的多个空间中工作 - 官方 Apple 支持 (中国);仅学术引用,著作权归作者所有。\n\n\n来源多个桌面Windows - Microsoft 支持;仅学术引用,著作权归作者所有。\n\n工作流\n公司中通常工作占比多的一定是沟通、协作、会议、任务、项目等。每个公司结合自身情况实际使用的工具大同小异无论是企业微信、钉钉、飞书等基本上都还是以下几方面\n\n\n通讯实时聊天、群组功能和邮件集成。\n\n\n协作任务和待办事项管理团队日程管理。\n\n\n会议音频和视频会议功能创建和共享会议日程。\n\n\n任务看板、ToDoList、任务进度任务报告。\n\n\n文档维基知识库、需求文档功能、团队资料等。\n\n\n项目项目日程安排、项目进展和任务分配。\n\n\n但企业微信、钉钉、飞书这些用在个人工作流中太过臃肿。而 NextCloud 对我来说,可以通过第三方插件量身定制属于自己的工具,例如常用的 draw.io、Mind、Mail、Cale、Deck、Task、News 等插件。关于 NextClouod 在《谈谈我的「数字文具盒」 - NextCloud》已经详细的全面介绍过了。\n我日常在 NextCloud 上的工作流程:\n\nDashboard仪表盘提供了全局概览可以快速了解工作状况。\nMail提供了基础性的邮件处理功能。我主要是用来收、看邮件。\nCalendar日历展示了月度视角的任务。我主要快速浏览一下本月的工作方向、里程碑以及本月剩下的时间。\nDeck看板展示了全局任务的状态。我可以快速地切入工作中去今天有代办是什么在做什么事情到了什么程度哪些干完了有点类似于虚拟桌面避免了每天早上不知道当天要干啥。\nTask任务提供了 ToDoList 的特性。我平时用来管理任务启动、结束、归档,可以和 Cale、Deck 进行联动。俗话说,好记性不如烂笔头嘛。\nNewsNextCloud 的 Rss 阅读应用,结合 RssHub 给我提供了平时大部分的信息源。我日常最喜欢的就是阅读 Rss 订阅源了,可以快速了解各种咨询。\n如果阅读 RSS 订阅源文章的时候,有一些想法 or 感悟,我就会随手记录在 Memos文字类 和 MassCode代码类并在每个月的第一个周日前定时整理。\n如果有一些文章篇幅太长需要花时间阅读。我把文章就会加入到 WallaBag 中有空了再进行深入阅读WallaBag 也提供了移动端,可以让我们随时随地的阅读。\n如果有精华文章需要收录。我会在 Zotero 中添加文章,并且按照文章的主题进一步分类归档。并在每个月第一个周日前定时整理,如果有 idea 就会记录在 Memos 中,加入到 NextCloud 的 Task 中落实写作。\n每天我还会结合 Obsidian 进行复盘总结一下。尽管有时候会写,有时候不会写……但是复盘确实嘎嘎有用,定期地审视一下自己最近的收获,哪些做得好、哪些做得不好、哪些需要改进、哪些需要坚持,进一步修正发展方向。除了每日复盘,还有每周、季度的复盘总结,复盘总结可真是项目管理,风险把控的一大神器。\n\n如上就是我个人日常的工作流程整体来说已经非常成熟了完全满足了我的个人需求。以后细节上可能会有一些变化但是方向是不会调整了。\n数据自主、开源这两个理念未来将会依旧始终贯穿数字文具盒系列其中。主要是因为如今许多商业产品的数据都是闭环流通如果那天产品无法盈利或者被官方关闭就只能如同魔兽世界一样领取电子骨灰盒了这也是我如此看重数据自主权的理由。与此同时开源运动的流行全世界开发者创造了越来越多优秀的产品也给我们提供了许多选择。\n目前个人工作流对我的日常学习已经带来了极大的帮助未来也将继续践行下去。最后也希望我个人的一些经验分享可以给你带来 Wow 的感叹,看到了就要去想,想好了就尝试去用,不用用怎么知道好用不好用呢?\nAlways For Freedom."},"Personal/Blog/2023/长安三万里":{"title":"长安三万里","links":[],"tags":["写作/影评","博客/原创"],"content":"周末和小雅一起观看了《长安三万里》,《长安三万里》讲述的是安史之乱爆发后数年,吐蕃大军攻打西南。大唐节度使高适交战不利,长安岌岌可危。困守孤城的高适向监军太监回忆起自己与李白的一生往事。\n《长安三万里》给我留下印象最深的一句台词**只要诗在,长安就会在。**最令我惊叹的是《将进酒》的画面,它满足了我对盛唐「浪漫主义」的全部幻想。还有就是李白如果搁在现代,那可真是妥妥的富二代、大网红了。高适则是高干家庭,至于剧中和高适相识于洞庭湖无从查起。杜甫出身于没落的名门世家,而且和他俩比起来一辈子真是嘎嘎惨。\n而我就是一个现代刁民 \n《长安三万里》的剧情中李白因为商人出身无法考取功名生性洒脱虚掷光阴。高适虽满腔热血追求功名一心报国但却处处事与愿违整部剧中他俩形成了鲜明的对比。李白后来因为皇帝赏识被召进宫但因性格洒脱不甘心成为笼子中的金丝雀便弃官寻求得道成仙。高适依旧坐冷板凳。杜甫科举不中在长安待了数十年最后落得一个屈辱般的芝麻官但为了生活还是不得不接受。剧中最后李白颠沛流离杜甫一生凄苦剧中甚至连画面都不见了……后高适虽然大器晚成但终究还是取得了功名。\n\n片子很长长到将近三个小时长到身边有小朋友已经坐不住了片子很短短到王维张旭李龟年也只能匆匆一瞥短到装不下李白高适以及盛唐灿烂的几十年前半场鲜衣怒马少年郎与烈火烹油极尽繁华的盛唐后半场前途困窘的中年人和高楼倾覆满目疮痍的河山将进酒把片子推上的貌似是高潮更是无限悲凉好在悲凉后是两岸猿声啼不住轻舟已过万重山。\n——豆瓣书评 momo\n\n\n在年少时我们一心向往功名可求得功名却又憧憬洒脱怀念少时。终其一生都游走在痛苦和麻木中留恋于可望而不可即的美好。但高适却给我们演绎了不忘初心方得始终可现实却往往是初心易得始终难守。我们当下所处的时空致使认知极其有限。或沉浸于往事、或者迷失在未来。然而往事终不可改前程更不知所踪。可人生就是如此到站就要下车当下即永恒。\n可终究万般皆是命半点不由人啊\n李白\n李白字太白又号青莲居士出生于 701 年,逝世于 762 年,盛唐时期一位辉煌的诗人。他自称陇西成纪(今甘肃静宁西南)的李广和西凉武昭王李暠的后裔,与唐朝皇室同宗。有关他的出生地,存在两种流传:一说他的童年在剑南道绵州昌隆(今四川江油市青莲镇)度过,一说他的祖先在隋朝末年被放逐到碎叶(今吉尔吉斯斯坦共和国楚河州托克马克市),他也在那里出生。\n**李白作为盛唐的浪漫主义诗人,他的一生充满了色彩斑斓的旅程和传奇般的经历。**他生于商人家庭在唐朝这个以农为贵、商为卑的时代他的身份并没有给他带来多大的优势。李白从小热衷于作赋、剑术、奇书以及神仙少年时期便已遍游蜀地。25 岁时,他独自离开蜀地,云游了邺、汴、越、吴、齐、鲁等地(现河南、河北、山东、浙江一带)。\n进入中年李白被唐玄宗召入朝中任职。在朝廷生涯中他创作了《侍从宴翰林饯别》《听董大弹胡笳声赋诗》等诗篇。然而他对朝廷内的权臣争斗感到厌恶决定辞官归隐。据传是因为他的《清平调》得罪了宠冠后宫的杨贵妃——李白命高力士脱靴高力士深感耻辱故以言语诱使杨贵妃以为李白是在讽刺她从而李白被排斥于宫中。天宝三年他请愿归山皇帝赐金李白离开长安。\n晚年李白北上游历广平郡的邯郸、临洺、清漳等地10 月抵达幽州。初衷是在边疆立功,也在那里练习骑射。后来发现了安禄山的叛乱野心,曾在黄金台上痛哭。不久后离开幽州南下。安史之乱爆发时,李白被永王李璘三次邀请入幕。后来永王得罪唐肃宗被杀,李白也因此获罪入狱。幸得郭子仪力保,免于一死,被流放至夜郎(今贵州关岭县一带)。在途经巫山时,因得赦免而作出了「两岸猿声啼不住,轻舟已过万重山」这样的名句。\n无论如何李白的才华和作品都使他在盛唐时期崭露头角被后世尊称为「诗仙」、「诗侠」、「酒仙」、「谪仙人」。李白的诗才横溢风格独特是浪漫主义诗人的杰出代表。更被贺知章赞誉为「天上谪仙」、「李谪仙」。他的诗篇展现了对生活的热爱对世界的理解对人性的洞察让他在中国文学历史上留下了深深的痕迹。\n杜甫\n杜甫字子美号少陵野老出生于 712 年,逝世于 770 年,盛唐末期的一位杰出诗人。他自称是东汉名将杜微的后裔。他在当时的首都洛阳出生,这座城市的深厚文化背景对他的成长产生了重大影响。\n**杜甫被誉为盛唐时期的现实主义诗人,与李白相比,他的一生充满了困苦和悲剧。**虽然他出生于世家大族,但家境并不富裕。他天赋异禀,接受了高质量的儒家教育,但各种原因在科举考试中屡遭失败。他在长安流浪了十年,努力实现自己的政治理想,甚至亲眼目睹了自己的孩子因饥饿而去世。这段期间,杜甫生活贫困,内心充满了失落和挫败。\n在经历了长期的等待和努力之后杜甫在四十四岁那年被任命为河西尉。然而他认为这个职位将使他的生活更加凄苦和无望因此他拒绝了这个职位。之后朝廷将他任命为右卫率府兵曹参军这是一个负责管理军事装备和门禁的低级官职。虽然杜甫对这个职位感到不满但在生活的压力下他仍接受了这个职位。\n杜甫的生活在安史之乱之后进一步陷入困境。他被叛军俘虏并在压力下接受了他认为无意义的官职。后来他因政治纷争被贬至华州远离了朝廷的中心。在华州期间他亲眼目睹了唐军的惨败并在他的名篇「三吏三别」中记录下了这段经历。\n在经历了连续的流离失所和极度困苦之后杜甫和他的家人陷入了几乎无法挽回的困境。然而即使在如此艰难的情况下杜甫仍然保持着对生活的热爱和对诗歌的热情。在 762 年,杜甫迁居成都,在那里他得到了好友严武的帮助,生活开始有了一些稳定。然而,由于不断的政治风波,杜甫再次被迫离开他的家,开始在梓州和阆州之间过着流浪的生活。\n杜甫被誉为「诗圣」他的诗才和独特的风格使他在中国文学史上占据了重要的地位。他的作品深刻揭示了他对社会的敏锐洞察对生活的深情厚谊以及对人性的深刻理解。他的诗句深入人心对后世产生了深远的影响。他与李白并称为「李杜」二人的作品被誉为中国古代诗歌的两大高峰。\n高适\n高适又名达夫或仲武是唐朝边塞诗的著名诗人被誉为边塞四诗人之一。\n高适的一生经历了许多的波折。他年轻时随父亲在广东韶关生活但在父亲去世后家道中落。曾有尝试在长安寻求职位但却未能成功。这次失败之后他选择在宋城现在的河南商丘从事农耕和捕鱼以为生甚至一度陷入乞讨的困境。在稍长些的岁数后高适北上至幽州寻求朔方节度大使信安王李祎的庇护与他一同出征对抗契丹。在这段战争期间他创作了一系列的诗篇这标志着他边塞诗创作的开始。尽管他在战争中表现出色但他觉得自己的才能未被充分利用因此决定返回宋州。\n随后在公元 735 年,他前往长安参加官方考试,但并未通过,因此再次回到了宋州。在长安期间,他与王昌龄、王之涣等人结为知己。接下来的几年,他创作了众多知名的诗篇,包括《燕歌行》和《画马篇》等。后来,他开始游历四方,与诸如李白、杜甫等名家共同赞美古人,并创作了更多的诗篇。到了天宝八载(公元 749 年),高适被提拔为有道科,并在长安中举。在担任职务期间,他被任命为封丘县尉,但在之后的工作中并未得到满意,他选择了辞职,并最终进入了哥舒翰的幕府。\n在安史之乱爆发后高适的诗歌创作速度明显减缓但他在文赋创作上却取得了新的突破。在这段时期他被任命为左拾遗转任监察御史并辅佐哥舒翰守卫潼关。\n虽然高适在晚年享有富贵但他直言不讳的性格激怒了权臣李辅国因此被降职为太子少詹事被派往东都。尽管如此他仍然被提拔为彭州刺史后来又被调任为蜀州刺史。在任期间他曾主张合并剑南东川、西川节度使但未获批准。后来在唐代宗的召唤下他代替严武出任剑南西川节度使直至 765 年去世,享年 72 岁。"},"Personal/Blog/2023/黄山归来不看岳":{"title":"黄山归来不看岳","links":[],"tags":["游记/黄山","游记/徽州","博客/原创"],"content":"最近几年我登了不少山,还曾希望在一年的时间里爬完五岳;更是非常想去看看,归来黄山不看岳的气派。黄山的种子早就是已经种下了,现在也是终于圆了梦。但不知道是爬的山多了,还是咋了,对于黄山的感受并没有特别惊艳。\n行程\n自从疫情放开以来满世界景点都是人抖音上黄山也是刷屏了人山人海的。同时黄山最近还免门票然后就一直在犹豫去还是不去了不过最后也是说走就走直达徽州。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n时间行程备注4 月 14 日 14:00出发郑州自驾前往徽州古城预计行程约 870 公里,耗时约 9 小时。4 月 14 日 23:00到达徽州选择附近的酒店住宿休息。4 月 15 日 8:00徽州古城游览古城风貌了解徽州文化。时长约 4 小时4 月 15 日 13:00出发宏村前往宏村欣赏徽派建筑风格拍摄美丽的乡村风光。时长约 2 小时。4 月 15 日 18:00黄山温泉泡温泉放松身心。时长约 2 小时。4 月 16 日 10:00开始爬山从云谷寺门户进山途径白鹅岭、始信峰等景点.4 月 16 日 17:30黄山日落在光明顶观看日落预计日落时间为 17:30。4 月 17 日 22:00银河升起预计银河升起时间为 22:00可以在光明顶附近拍摄星空 。4 月 17 日 05:30黄山日出黄山山顶观看日出预计日出时间为 05:30。4 月 17 日 10:00返回郑州黄山出发返回郑州预计行程约 800 公里,耗时约 9 小时。\n我们是自驾的方式一共 3.5 天左右的时间。然后计划第一站徽州古城,接着宏村,最后再登黄山。行程表是 ChatGPT 在我的引导下制定的,真香 ~\n徽州\n\n徽州古城作为中国四大古城之一位于安徽省黄山市歙县中部。徽城镇始建于秦代设置歙县之时六朝时期升为新安郡郡治隋代为歙州治宋徽宗时又改为徽州治明清时为徽州府治直到民国初年废府存县定名“徽城镇”。\n我们快凌晨的时候来到徽州古城边上落脚刚下车就感受到了江南烟雨弥漫细雨纷纷宛如牛毛在漫天飞舞。啊觅食觅食开了快十个小时的车都饿坏了。在徽州古城前走来走去再也不知道该吃什么了。一位老者站在徽菜馆的门口揽客我们索性也就不挑了。\n\n要数徽菜最让我印象深的就是竹笋了老板说现在是竹笋的季节基本都是当天挖当天吃真的嘎嘎好吃。臭鳜鱼还是啥鱼我也忘了鱼刺不少导致没吃多少妥妥浪费。总的来说这家饭馆菜量不少食材也蛮新鲜味道也不错色香味俱全哈哈。\n酒饱饭足睡觉 ~\n\n\n早上起来继续觅食竹笋包子真的很好吃种草好巧当天正好还是黄山徽州古城百公里越野赛不过人也太多了……导致我们只能逆着人流游玩然后像个街溜子似的无所事事的乱溜达。\n\n徽州古城是徽派建筑中具有代表性的一座城市素以结构严谨比例美观雕刻精美著称。其通常以木材、石头、青砖为主要材料以墙、柱、梁、瓦为主要构件建筑形态多样包括门楼、府邸、园林、墓葬、城池等建筑类型。徽派建筑布局狭窄黑白灰色调乍一看挺新奇的。\n\n正所谓站得高看得远随后我们直奔徽州古城的最高点一座不知其名的山。可山上却莫名其妙的荒凉山顶一所废弃学校也显得阴森诡异后背直发凉。赶紧溜溜球 ~\n\n山下有很多摩拜电车哈哈于是我们纷纷骑上各自心爱的小摩托飞奔在徽州古城。要是没有遇摩拜电车我们真的是怕要累死在徽州古城。最巧的是我叔刚好还遇见了曾在抖音上关注卖砚台的一个博主真是奇奇怪怪的缘分哈哈。\n\n江南歙州徽州的砚是中国四大名砚之一与甘肃洮砚、广东端砚、山西澄泥砚齐名。\n\n\n\n徽商大宅院本不在行程规划中我们也是在歙县乱逛然后遇见了决定进去参观一下。\n徽商大宅院位于歙县县城。整座古建筑群集牌坊、戏台、亭阁、花园、水榭等于一体 为组合式的宅第群体,有宅第 26 座、房屋数百间、天井 36 个、柱子 1580 根。徽商大宅院气势宏伟,马头墙层层昂起,飞檐翘首,亭阁桥榭、牌坊宅第浑然一体,三雕精品比比皆是。\n向导当时对徽商大宅院的解说让我感触最深的有以下几个方面\n\n过高的院墙极小的窗户仅仅两三个拳头那么宽。\n前世不修生在徽州。十三四岁往外一丢。\n大门不出二门不迈裹脚从不下二楼。\n\n因徽商终年在外经商家中仅有妻子持家。为了避免遭遇飞贼和囚禁妇女所设计极小的窗户、超高的院墙仅仅只通过天井采光。主要是在封建社会中男尊女卑的观念非常普遍在这种观念下男子被赋予了更多的社会和政治权力而妇女则被限制在私人领域之内。徽商更是为了家族财富的传承、宗祠地位的延续早早的就把男孩扔出去经商采取优胜略汰的自然法则继承并把妇女则被作为一种财产和工具一方面同达官贵人联姻一方面展示自己雄厚的实力。\n宏村\n\n因为徽州距离宏村还不到一百公里的路程所以我们决定不走高速深入体验一下江南烟雨人家。我们穿流在各个徽州村落尽肆意地吮吸着空气中弥漫的炒茶香气。那儿好就下车饱饱眼福可真想在这个小河边上整点烧烤小啤酒仅仅是想想都自在 ~\n不像以前打卡式旅游现在特别喜欢到一个新地方住一段时间十天半个月的深度体验原汁原味的乡土生活。有时候想想尽管都生活在同一个世界但是各自却又仿佛处在平行时空等有朝一日相遇。总会不禁发出感叹哇哦原来生活还可以这个样子。\n\n\n宏村有世外桃源的感觉最后开车穿过一条隧道就到了。但宏村人真的太多了密密麻麻的全都是人我也没有带三脚架随便捏了两张。还有就是商业化太严重没有感受到浓厚的人文气息建议去过一次就行了。毕竟进这个村就得 100 元的门票……\n不知道为什么徽派建筑总给我一种直观感受压抑压抑还是压抑深墙窄院、天井小窗无不处处透露着压抑。例如这口水塘我就不信历史上没有女性在这被沉过塘还有古代交通不发达生活资料不足缺吃少穿的普通老百姓肯定生活在水深火热中。\n心里默默感叹幸好生活在二十一世纪不然早就是封建社会制度的刀下亡魂了……\n黄山\n\n原本打算在黄山脚下泡个温泉了但攻略没做好就泡汤了。我们在去吃饭的路上碰见一个姑娘推销要不要登山杖随后就买了一个结果在饭店吃饭的时候又偶遇了哈哈奇奇怪怪的缘分。\n秉承着今朝有酒今朝醉大家喝的很开心拍拍屁股睡觉明天登黄山。\n\n\n黄山古名黟山史书载中华民族始祖黄帝带领部下大臣容成子和浮丘公到这里炼丹最后得道升天。唐天宝六年747 年),根据这一传说,信奉道教的唐玄宗将黟山改为黄山。黄山地处安徽省南部,介于歙县,黟县,太平县和休宁县之间,属传统徽州地区。黄山的主峰为莲花峰,海拔 1864 米。黄山素以奇松、怪石、云海、温泉四绝著称。明朝旅行家、地理学家徐霞客曾两次登临黄山,赞叹说:“五岳归来不看山,黄山归来不看岳”。\n\n\n关于黄山的攻略我推荐大家看这个2021保姆级 黄山 全攻略,亲绘黄山地图比官方要好。\n我们计划在 10 点左右从云谷寺出发爬山,然后依次始信峰、狮子顶峰、丹霞峰、最后傍晚到达光明的看日落。山顶过夜,凌晨拍银河,次日早上看日出下山,纯徒步路线,而且可以完美避开人流。\n\n黄山比泰山、华山要爬的轻松些保持好节奏感慢慢来就 ok我们从云谷寺去白鹅岭大约 3 个小时左右。同时为了弥补上次在川西没有堆玛尼堆的愿望,我们在黄山脚下堆了一个,为每个看到的人祈福 ~\n中午 1 点左右,我们到达白鹅岭,然后就开始了真正的黄山之旅!如上图中可以看出,黄山实际上就是一块巨大的花岗岩,正中有一处凹地,山峦环抱西海水库。于是我们就从这个山头走向那个山头,最著名的奇石景观是猴子观海。\n\n\n临近日落我们实在是爬不动了。但是有句老话说得好来都来了哈哈哈。那就冲冲冲四驱战士在行动当爬上光明顶的时候只顾着兴奋了却全然不知道巨大的痛苦还在后边。原本我们打算住山顶酒店的可一直预定不到房间。就想着先上山吧上去了啥都好说实在没办法的话就去睡厕所。\n\n山顶的风巨大我们又累又饿又困看看给我叔难为的哈哈哈哈哈哈哈哈哈哈哈哈。尽管这次黄山我们已经很尽力避开人流了可是就这都找不到合适的拍照位置人真的太多了……\n\n\n好了现在日落看完了。我们的心也要开始凉了本以为住在山顶没想到没有一间房然后厕所门也都不开。我们连个落脚的地方都没有只能蜷缩在一个小亭子里还是三面透风的那种遭老罪了。山风呼呼呼的吹人都站不住。地面上冰凉刺骨坐一会屁股都麻了……\n我们想尽一切办法来保暖穿上雨衣背上书包大家一起挤暖和呀。最后实在没办法了我俩就去环卫工人的小房子里借用了一些废纸板挡风取暖。最恐怖的还有那两个大学生特种兵还是女生就那么孤零零的坐在风口直到凌晨。后来我们喊她们来避风简单聊了几句真不愧是大学生特种兵就是头铁啥都没带就准备在山上硬坐到早上看日出。\n\n毕竟痛苦只是暂时的幸福却是长久可回味的。终究还是前半夜的风吹来了下半夜的银河 ~\n\n\n莲花峰、天都峰各依两侧银河就肉眼可见的在天上挂着每看到这些照片就会头皮发麻。何其有幸经历过这么多的绝美风光无不感叹中国的地域辽阔风景秀丽。\n\n山顶这一夜真的是遭老罪了好不容易熬到清晨。结果凌晨日出乌压压的全都是人日出都不想看了只想下山吃顿好的……\n天都峰也不去了只想一眨眼滚到山脚下了。不过迎客松还是必须得去了早上 6 点多,前往迎客松方向已经乌压压的都是人了。最后打卡迎客松,然后回家咯!\n\n这趟黄山之旅整体感觉挺不错。唯一不足就是哪哪都是人山顶那一夜遭老罪了。景区商业化严重可能是各景区的通病但是有些景区真的是去一次就够了。\n我想黄山之所以如此有名地理位置因素占有相当大的比重以奇松怪石和云海为例华山奇松怪石更堪称一绝在我心里排第一。云海的话南方相对北方看到的概率更大一些这次黄山也是奔着云海去的本想配合天气计划的是刚刚好。但是雨却延迟了一天在我们走后的第二天果不其然就迎来了云海 ~\n或许没有人可以一直在路上但是永远会有人在路上 ~"},"Personal/Blog/2024/2023-年终问答":{"title":"2023 年终问答","links":[],"tags":["博客/原创","年度/2023"],"content":"1.你今年做了哪些之前从未做过的事?\n爬雪山拍银河。\n2.你有没有遵守年初时和自己许下的约定?\nYes一直在路上。\n3.你身边有人生孩子了吗?\n有17 岁都有了……\n4.你身边有人去世了吗?\n有……\n5.你去了哪些城市/州/国家?\n云南、重庆、洛阳、安徽黄山、福建泉州、河南焦作、湖北神农架、浙江杭州、河南信阳、河南商丘。有机会想出国 \n6.明年你想要获得哪些你今年没有的东西?\n目前还没有想到比较顺其自然。\n7.今年的哪个或哪些日子会铭刻在你的记忆中,为什么?\n云南的梅里雪山、安徽黄山的银河、泉州老姐结婚、河南商丘。\n8.你今年最大的成就是什么?\n读书 50 +、更好地处理生活琐事。\n9.你今年最大的失败是什么?\n没有好好地学习 XX ,丢人……\n10.你今年还遇到过哪些困难?\n特别困难的事情倒是没有就是反反复复的因为呼吸道、感冒等影响身体状态。\n11.你今年是否生过病或受过伤?\n生病特别是换季季节各种甲流感冒头疼死了还是要学会带口罩。\n12.你今年买过的最好的东西是什么?\n最好的想不起来。买了个小书桌倒是非常 ok。\n13.谁的行为值得去表扬?\n今年需要表扬自己哈哈哈。\n14.谁的行为令你感到震惊?\n爷爷 + 舅舅。\n15.你大部分的钱都花到哪里去了?\n生活。\n16.有什么事让你感到超级、超级、超级兴奋?\n爬雪山看银河家人团聚。\n17.哪首歌会永远让你想起这一年?\n那首歌凤凰传奇吧今年听得巨多。\n18.与去年的这个时候相比,你是:感到更快乐还是更悲伤了?变得更瘦还是更胖了?变得更富还是更穷了?\n快乐与悲伤同在同比快乐一些。稍微胖了一丢丢哈哈哈。目前一直穷得比较稳定。\n19.你希望自己能做得更多的是什么?\n多挣钱吧。\n20.你希望自己能做得更少的是什么?\n减少无关紧要的事情对自己的干扰。\n21.你是如何度过节假日的?\n随心所欲。\n22.你今年坠入爱河了吗?\n一直在河里。\n23.你是否有讨厌某个你去年此时不觉得讨厌的人呢?\n有。\n24.你最喜欢的电视节目是什么?\n不看电视。\n25.你读过最好的一本书是什么?\n《实践论》\n26.你今年发现的最好听的一首歌是什么?\n东北的东。\n27.你今年看过最喜欢的一部电影是什么?\n长安三万里。\n28.你今年吃过最好吃的一顿饭是什么?\n姐姐在泉州的婚宴嘎嘎好吃。\n29.有什么是你想要且得到了的?\n想要拍银河而且还拍到了。\n30.有什么是你想要却没有得到的?\n西北大环线没有去。但是又感觉不去也没啥……\n31.你生日那天做了什么?\n家人团聚。\n32.有什么还未发生的事,如果发生了,会让你的这一年变得无比满足?\n中\n33.你会如何描述你今年的个人时尚风格?\n轻熟风喜欢穿着的版正一些。\n34.是什么让你保持理智?\n家人内心。\n35.你最欣赏哪个名人/公众人物?\n毛教员。\n36.哪个政治问题最令你有感而发?\n没有接触不到也参与不到。\n37.你想念哪些人?\n家人朋友。\n38.在你新认识的人之中,谁是最好的?\n没有。\n39.你尝试过哪些新的运动或锻炼方式?\n三一计划跑步早起家庭锻炼。\n40.你今年学到了哪些新的技能或知识?\n围棋准备学习钢琴。\n41.你是否有新的爱好或兴趣?\n没有太多就学不过来了。\n42.你是否有了新的住所或改变了居住环境?\n没有新住所但极大改善了生活居住环境。疫情几年集体宿舍住得想吐……\n43.你是否有新的心理健康或情绪管理技巧?\n深呼吸抽根烟冷静一下。\n44.你是否有新的人生观或价值观?\n目前在总结新的还没有。\n45.你是否有新的商业或职业机会?\n有\n46.你是否有新的家庭成员加入?\n马上就有哈哈哈。\n47.你是否有新的自我改进或成长计划?\n方向有计划暂定。\n48.今年你是否有新的冒险或探险经历?\n没有倒是想尝试爬雪山或者穿越秦岭。\n49.今年你学到了什么宝贵的人生经验?\n人生无常世事难料。\n50.能够总结你这一年的一句话是什么?\n不忘初心砥砺前行。"},"Personal/Blog/2024/CityWalk——公车挑战":{"title":"CityWalk——公车挑战探索未知的城市","links":[],"tags":["博客/原创","生活/随笔"],"content":"周末,我和小雅一起尝试了一种新颖的 CityWalk——公车挑战。公车挑战是一种通过随机选择公交车线路的方式让我们可以在未知中探索城市的魅力。\n至于公车挑战的规则是什么我当时也是在某位博友的博客上看到的。虽然现在我找不到原文了但大致的规则我还记得\n\n选定某个公交站点作为起点。\n随机上下一辆到站的公交车。\n随机坐 3-5 站后下车。\n重复上述步骤尝试进行 10 次。\n最后如果公交车驶出三环或四环自动结束以避免距离过远。\n\n公车挑战这个想法在我心中萦绕了整整一年却一直没有实施。所以新年伊始我决定一定要安排上公车挑战\n我选择的是高中时期坐 307 路公交车回家路线,起点是郑州市第三人民医院。这么多年,我都快忘了是 16 年,还是 17 年高中毕业。但是我永远记得毕业那一年克利夫兰 VS 骑士队让三追一最终夺冠!这一次,我也是想看看这么久过去了变化如何,感受一下物是人非。\n我从西大街地铁站下车绕经商城遗址来到了阜民里。郑州商城遗址是中国最早的城市遗址之一是商朝早期的都城遗址可以追溯到公元前 16 世纪至前 11 世纪。当天下过雪,不然能站在大土堆(城墙)上观赏风景。阜民里是河南省文旅局打造的郑州老城新名片,它重新建造了上世纪八九十年代的街区风貌,让人仿佛置身于怀旧的老街巷中。\n从西大街地铁站下车绕经商城遗址来到了阜民里。郑州商城遗址是公元前 16 世纪至前 11 世纪商朝早期的都城遗址,被誉为中国最早的城市遗址之一。去那天刚好下过雪,也没能上大土堆上看看哈哈。阜民里是河南省文旅局打造的郑州老城新名片,新建还原了郑州上世纪八九十年代风貌的街区,可以让你置身其中感受乡愁的老街巷,\n过去这个地区是银基商圈非常脏乱差。但经过老城区的改造现在真的变得很不错呢\n\n\n\n\n不管是过去的还是新生的都在积极向上努力生长\n\n经过南关街我们沿着曲折的道路来到了高中。一切似乎还是那么熟悉但围墙上却布满了新安装的电子围栏。回忆起当初高中夜里拼了命想要跳墙出去打游戏的日子现在却也再也跳不过去了。\n我看了一眼手机时间都 4 点多了,得抓紧开始公车挑战了。\n\n206 路\n我俩在郑州市第三人民医院公交站足足等了 20 分钟才来了第一班车——206 路。在城南路上我们经过了 4 站,然后在商城遗址站下车。本来我还带着相机想在公交车上拍照,可实在是太晃了。\nS162 路\n下了 206 路不久,我们又上了 S162 路,商量好了要坐 3 站下车。本来我以为会朝着家的方向前进,但没想到它在城东路经过陇海路后往西行驶,最后在紫竹小区下车~\nG62 路\n刚下了 S162 路,我们又上了 G62 路,这次终于是往家的方向了。不过这次我们商量好要坐 5 个站才下车。我还在想,难道坐两趟车就能离开三环吗?谁知道,就在这第 5 站,它从紫荆山路经过航海路开始往郑州西行驶。\n要是真把我带到大西郊那就完蛋了……\n277 路\n由于从 G62 路下来后是在航海路东往西方向,所以我们只能一直往西走。\n等了一会儿我们坐上了 277 路公交车,做了三站就下车了。\n213 路\n就在我以为又要继续往西走的时候一辆 213 路公交车来了,坐了 5 站,结果直接把我们拉到了火车站。就这样,我们绕了个圈,又回到了最初的起点。真是出乎意料啊……\n我们在火车站的公交月台等待下一班车的到来但是先记住这辆 213 路哈哈哈。\n176 路\n紧接着我们又坐上了 176 路,这已经是第 6 辆公交车了。原计划是不超过 10 辆,结果已经是第 6 辆了,我们还没有离开火车站……\n176 路出门后沿着京广路往南行驶,结果真是巧了,坐了三站下来,又坐上了之前的那辆 213 路。\n213 路\n公交车司机是位大姐看到我们又坐上了车一脸不可思议。她肯定在想这两个年轻人怎么又上来了哈哈哈哈\n我当时还故意等 213 路先走了,然后才坐上了 176 路,结果 176 路司机居然超过了 213 路,我们就又坐上了 213 路。\n这次我们一定要坐 5 站,看看它会带我们去哪里。\nS162 路\n213 路下车后,我们到了祥云路公交站,除了 S162 路之外已经没有其他公交车了。我们上了 S162 路,我还在想会不会是最开始的那辆公交车哈哈哈。\nS162 路最后出了南三环,公车挑战就到此结束。回家吃饭 \n路线图\n\n\n一开始我脑海里闪过了无数种可能的结局。我最担心的是兜到大西郊所以一开始我们决定朝西往东的方向出发。我还信誓旦旦地和小雅吹泡泡如果我们一开始选择往东那往西的可能性就会很小。所以我们打赌最后的方向一定是东北。小雅则说那我就选西南方向。\n然而结果我们一上了 S162 路,就又绕回了原点。而且这个 G62 路真的只多那一站,让我们让去西郊成为最有可能的结果。但我们没有坐上去西郊的公交车,而是又坐上了 213 路,又回到了最开始的起点。\n当时我下车后说「这都到火车站了咱俩也别打赌了。最后到哪就是哪吧这根本就不可能预测的到」\n就在我以为也许会有一个新的开始时却万万没想到我们又误打误撞地坐上了之前的 213 路,被拉回了南三环的方向。就这样,公车挑战最终结束了。\n其实想想人生不也是恰恰如此么\n我们总是认真规划好方向憧憬着走下去梦想着到达彼岸。可是明天在哪终究是雾里看花水中望月可望不可即。\n然而恰恰也正是这种未知性和不确定性赋予了人生无限的可能性和惊喜。有时候我们会迷失在追寻的过程中发现原本设定的方向并不是自己的道路。而有时候正是在迷茫中我们才能找到真正属于自己的出路。\n人生并不是一条笔直的道路而是一段曲折而精彩的旅程。在这个旅程中我们会遇到成功和失败喜悦和痛苦但人生的意义不在于到达彼岸而在于沿途的风景和成长。\n那么对于未知的明天相信自己继续前行去探索那些等待我们发现的美好吧。"},"Personal/Blog/2024/Python-项目终极部署解决方案":{"title":"Python 项目终极部署解决方案","links":[],"tags":["博客/原创","Python/项目"],"content":"Python 作为一门历史悠久的编程语言,起初角色定位于 Liunx 下的脚本语言。最初作为 Linux 下的脚本语言诞生。随着时间推移Python 不断引入新特性逐步演变成一种功能强大、用途广泛的语言。目前被广泛应用于数据科学、Web 应用开发等多个领域。\n特别是自 2019 年 6 月起Python 采用了 PEP 602——Python 的年度发布周期。从 Python 3.9 开始,这个策略规定了 Python 版本的发布计划,确保每年 10 月发布新的特性版本。每个版本的开发周期长达 17 个月包括无版本、Alpha、Beta 和候选发布阶段。此外Python 版本将获得两年的全面支持,包括错误修复,随后是三年的安全修复。\ngantt\n title Python 3.12 发布周期\n dateFormat YYYY-MM\n section 开发周期\n 无版本期 :2022-10, 2023-05\n Alpha 阶段 :2023-05, 2023-07\n Beta 阶段 :2023-07, 2023-09\n 候选发布阶段 :2023-09, 2023-10\n 正式发布 Python 3.12.0 :2023-10, 2023-10\n 全面支持期 :2023-10, 2025-10\n 安全更新期 :2025-10, 2028-10\n\n\n但是目前在 Python 项目部署方面,依然还面临着许多问题和挑战,如环境一致性、依赖管理、版本控制、跨平台部署、性能优化、安全性、自动化部署、配置管理、离线部署、容器和虚拟化、资源管理和监控、文档和支持等等等。差点一口气顺不下来哈哈哈 ~\n目前我的主要策略是遵循 DevSecOps 原则,实现标准化和流程化部署。\n仓库分支\n\n主分支main 或 master用于稳定版本的代码和产品发布。\n开发分支从主分支分出用于日常开发和测试工作。\n依赖分支从开发分支分出专门管理和更新项目依赖。\n功能分支从开发分支分出用于开发新功能或修复错误。\n发布分支从主分支分出用于新版本的准备和发布。\n文档分支专注于文档编写和更新建议与发布分支合并。\n\n开发环境\n项目开发应基于项目需求和目标平台选择适当的 Python 版本,并根据需求评审更新。同时利用 pyenv 可灵活管理 Python 版本,而 Pipenv 则用于依赖管理,其 Pipfile 和 Pipfile.lock 确保依赖在所有环境中的一致性。同时,使用 Git 作为版本控制系统,保持代码的组织和可追溯性。此外,尤其是依赖更新应通过专门的依赖分支来管理。\n测试环境\n**测试环境的构建应尽可能模拟生产环境,以确保测试的有效性。**使用如 GitHub Actions 或 Jenkins 的自动化工具可以自动执行单元测试、集成测试等。同时,引入代码审查工具,如 SonarQube进行静态代码分析有助于发现代码质量问题和安全漏洞。测试环境中的配置管理应与生产环境保持一致例如通过环境变量或使用 Ansible 工具进行配置管理。\n构建部署\n在部署方面根据是否联网和部署形式源代码或二进制可以采取不同的策略\n\n联网环境 & 源代码部署\n在联网环境中进行源代码部署时使用 Github、GitLab 等版本控制系统VCS配合持续集成/持续部署CI/CD工具如 GitHub Actions、GitLab CI/CD是一种高效的方法。这些工具可以自动化测试、构建和部署过程从而提高部署效率和减少人为错误。\n同时为了确保环境和依赖的一致性可以采用 Pipenv 和 Pyenv。Pipenv 提供了项目依赖的清晰定义和锁定机制,而 Pyenv 允许在同一系统中安装和使用多个 Python 版本,非常适合处理多项目环境。此外,可以集成静态代码分析和代码质量检测工具,如 SonarQube以提高代码质量和安全性。\n无网环境 & 源代码部署\n在无网环境下虽然可以使用 Pipenv、Pyenv 等工具来管理 Python 版本和依赖,但无法直接从外部源下载依赖。因此,关键步骤是提前准备好所有必需的依赖包。这可以通过在联网环境中预先下载所有依赖并将其存储在一个本地仓库(如 PyPI 目录)中来实现。\n此外还可以构建一个 Python 独立版本,并将 Python 解释器与应用程序一起打包,确保环境的一致性。为此,可创建一个包含所有依赖的可执行文件。这种方法有助于减少环境差异和部署复杂性。\nDemoProject 项目结构参考:\nDemoProject\n├── ProjectSrc\n├── Script\n├── PyPI\n└── Python3.10\n\n\nProjectSrc项目代码\nScript项目运行脚本\nPyPI项目依赖包\nPython3.10:独立版本 Python\n\n联网环境 & 二进制部署\n二进制部署在联网环境下提供了更多的灵活性和可扩展性。使用 Docker 和 Kubernetes 可以实现应用程序的容器化,从而简化部署过程、增加应用程序的可移植性和可伸缩性。容器化还使得应用程序在不同环境之间的迁移变得更加容易,同时提供了隔离和安全性。\n此外可以利用现代化的部署策略如蓝绿部署、金丝雀发布和灰度发布。这些策略通过逐渐引入新版本的方式来减少风险允许在完全部署之前监控应用程序的表现并回滚至旧版本如有必要。\n无网环境 & 二进制部署\n在无网环境中二进制部署通常依赖于将应用程序及其所有依赖打包成单个可执行文件。可以使用 PyInstaller 等工具来创建独立的二进制文件,这样就不需要在目标系统上单独安装 Python 或依赖包。\n另外针对特定的操作系统可以考虑将应用程序打包成 APT (.deb) 包或 YUM (.rpm) 包。这种方法适合于在特定类型的 Linux 发行版上部署应用程序,可以利用操作系统的包管理器来处理依赖和升级。\n运维监控\n部署后的监控和维护同样重要。使用如 Prometheus 和 Grafana 的工具组合可以有效进行性能监控,帮助及时发现和解决问题,保证系统的稳定运行。业内拥有多种一体化运维监控系统及开源软件,可以根据具体需求进行统一化安装配置管理。\n日志管理\nELK 堆栈是一种流行的日志管理解决方案,由 Elasticsearch、Logstash 和 Kibana 三个组件组成。\n\nElasticsearch 作为核心,提供高效的数据存储、搜索和分析能力。\nLogstash 负责日志数据的收集和处理,可以从多种来源获取数据,并转换后传输到 Elasticsearch。\nKibana 作为这套系统的前端界面,提供数据的实时可视化和分析功能。\n\n这套组合因其出色的灵活性和扩展性适合用于各种规模的项目帮助组织有效管理和分析大量日志数据提升系统性能和安全性同时支持更好的业务决策。"},"Personal/Blog/2024/「救赎之路」更名「向阳而生」":{"title":"「救赎之路」更名「向阳而生」","links":[],"tags":["博客/原创"],"content":"2018 年创建博客时,我最开始想注册 dons.comDream of night sky却发现被一家书店注册了。后在于朋友聊天寻找新的域名时一句无心的玩笑话——你脑子瓦特了吗整天想这些干嘛随便找一个不就行了\n意外地给了我灵感——瓦特好名字。\n我就立刻去查 wate.com 被注册了没,结果也被人注册了。这时,另一个朋友建议我:要不加个数字试试?于是我选择了 7wate.com并为之赋予了一个新的概念「wate」与「瓦特」谐音那「七瓦特」的功率足以点亮一盏灯泡其发出的光就可以照亮世界。\n\n实际上无论是九瓦特十瓦特还是一百瓦特都能点亮一盏灯泡。现在想想真是挺蠢蛋的哈哈。\n\n一开始从「7wates blog」到「救赎之路」再到如今的「向阳而生」博客名也经历了几番变化。虽然我对于域名和博客名并不十分执着最初创建博客也是出于一时兴起多是无心之举但这个无心之举却带来了意想不到的收获记录了我一路来的酸甜苦辣咸并同时也即将迎来第六年。\n「救赎之路」这个名字的灵感来源于我最爱的电影《肖申克的救赎》——我百看不厌的影片。因为过去我也曾经历了许多迂回与苦难总梦想着能够像肖申克那样一锤一锤地凿开属于自己的救赎之路。\n但在现实中我却常常不知如何是好……\n因此我通过文字记录这几年的心路历程并希望能够写出一篇让自己感动流涕的博文以此完成「自我救赎」。虽然到现在我也未能写出那样的博文但多年的思考和沉淀不应该被浪费就借此深入展开论述我的三观吧。\n前前后后经过近两年的思考阅读交流实践后。终于系统地阐述了我的三观同时也算是为了学习哲学打个快照。\n\n\n价值观于内你愿意嫁给自己么\n\n\n价值观于外不要把幸福建立在别人的痛苦之上\n\n\n人生观穷则独善其身达则兼济天下\n\n\n世界观一命二运三风水\n\n\n你可能会问这是否就是标准答案么\n实际上不存在所谓的标准答案我也只是借助博文阐述方向。从某种程度上来讲我也算完成了自己的「救赎之路」。那也就没必要继续以救赎之路为名了可我又不知道想个什么比较好。\n\n直到有天下班回家时我低头无意间看到了一株生长在下水道里的椿树它竟然生长得如此旺盛。我想如果它生长在山里可能便会成为苍天大树即便是在公园里也能会为人庇荫。\n然而它却生长在了下水道里隐藏在井盖之下虽然每次一露头就可能被无情踩碎但它仍不甘心只是默默无闻地生长。尽管井盖限制了它的成长空间却也在无形中为它给予庇护。\n故此我选择了「向阳而生」作为新的博客名象征新的起点。无论环境如何都应该勇敢生长追寻光明。\n\n此心光明亦复何言。\n"},"Personal/Blog/2024/一命二运三风水":{"title":"一命二运三风水","links":[],"tags":["博客/原创","成长/个人"],"content":"一命\n\n万物负阴而抱阳\n\n现如今大部分人们对于「命」的理解呈现出鲜明的对立。一方面有些人坚信我命由我不由天认为人的意志和努力能够改变「命」。但是同时也存在着过度强调主观能力从而忽视客观条件的风险。\n例如在历史上大跃进时期就曾试图利用群众热情在农业工业等多个领域盲目追求脱离现实的「跃进」其过度乐观和盲目自信就是一个极端表现。\n另一方面宿命论者认为人生是预定好的并一味地强调「命」的逻辑必然性和生活中不可避免的巧合而且无法通过个人意志改变。以至于在面对困境时缺乏主动改变的动力。\n其实我们可以尝试从物质哲学的角度来探讨「命」的概念。物质的基本属性是运动这说明实际上不存在绝对的真理万事万物都处于不断的变化之中。然而人的生命是有限的因此「命」也可以被视为运动的阶段性状态并且拥有上限和下限。\n现如今被网友戏称穿越者的王莽。其在统治期间推行的一系列货币、土地、官僚体系的改革措施被认为是超越了当时社会的认知和实践水平。导致不仅在当时社会中引起了巨大的震动并与当时社会的实际情况脱节以至于执行困难引发了社会动荡和经济问题。\n然而在半封建半殖民地的旧中国我们的毛教员虽然受到时空的限制但通过不断的正确决策和持续的行动力历经长征、抗日战争并最终取得国内革命的胜利毛教员不仅改变了自己的命运更重塑了中国的历史轨迹。\n故此「命」可以看作是由个体内在特质性格爱好、生辰八字与外部环境社会结构、历史规律的交互作用而组成。整体由内在的阴个体特性和外在的阳社会环境共同构成的并且它们深深受限于所处时空带来的约束性。\n二运\n\n南美的一只蝴蝶挥动翅膀有可能引起北美的一场龙卷风。\n\n这句耳熟能详的话虽然是描述蝴蝶效应的但是它也形象地描绘了运气的不可预测性和微小因素可能引发系统的巨大变化。\n运气这个神秘而复杂的事物既难以捉摸又充满变数。有些人运气好的楼下买张彩票几块钱都能中上千万而有些人吃个花生米呛得差点把命都丢了真的是让你不服都不行\n借用混沌学的话说一切事物的原始状态都是由看似不相关的碎片组成。然而随着时间的推移这些碎片将有机地汇集成一个整体。这一理论不仅适用于物理世界也适用于帮助我们进一步理解运气。\n正如盘古开天辟地一样人类在发展的历史长河中虽然一直努力着在混沌中创造并维护秩序但其仍被不可预测的因素所左右。那么在这一切对事情结果产生影响的因素当中运气到底占据了多少呢\n正态分布在自然和社会科学中常用来代表不明的随机变量其实也客观反映了生活中运气成分的分布情况这意味着极端的幸运与不幸大致遵循同样的概率规律。\n但不过人类的心理暗示往往会加强对于运气的感知从而使这些不受人为意志所转移的部分因素进一步影响我们的决策和行为最终导致我们的生活轨迹发生变化。\n特别是在现代社会中不同文化背景下理解和应对运气变得更加复杂。对运气的看法和应对方式更存在明显差异。尤其在一些文化中运气被视为命运的主导者而在其他文化中则被看作是可通过努力和智慧来影响的因素。\n另外心理学研究也表明运气可以极大地影响我们的心态和行为。对于一个经历了坏运的人来说保持积极和乐观的心态可以帮助其更好地应对挑战并抓住转机。\n所以在面对运气时我们还是要采取一个理性的态度。当好运来临时我们应该保持感恩而在遭遇不幸时则需要进一步保持坚韧和乐观。最重要的是要认识到运气仅仅只是人生众多影响因素的一种我们不能完全依赖它也不应过分恐惧它。\n应始终秉承不以物喜不以己悲的心态看待运气。因为这是根本无法控制的事情。尤其不要祈求运气会给你的生活雪中送炭实际运气更多的是锦上添花。\n三风水\n\n风水是一种古代中国的传统习俗和术数其试图凭借墓地、屋宅的所处位置、坐向方位以及和周遭山、水形势的关系来改变个人、家族的气运并为宅邸、店家招来好运。\n——维基百科\n\n不过我所理解的风水是人与自然之间微妙而又错综复杂的关系以及它如何在无形中影响着我们的生活与成长。就像在图书馆学习可以使人更加专注一样寺庙的肃穆安静帮助我们清净心灵环境时时刻刻地影响着我们并不知不觉地塑造着我们的内心世界。\n古代中国的皇宫设计比如紫禁城的布局充分体现了风水学的原则旨在达到天人合一的和谐状态。其选择的位置、方向以及内部的空间布局都旨在促进积极的能量流动进而保证皇族的繁荣和国家的稳定。\n此外风水在现代的生活中也处处可见。例如在选择办公室位置和布局时考虑风水因素以创造一个有利于团队合作与创新思维的环境。可以通过优化空间布局增强自然光的利用以及在办公区设置绿植等方面入手。不仅提升工作效率也增强了整体氛围和文化。\n在这一过程中我们的积极心态不仅能塑造我们对环境的感知还能进一步改善这些环境。这一正反馈机制说明实际上并不只是环境塑造人人亦能塑造环境。大至一室小至一城风水的作用范围广泛其精髓在于把握人与自然和谐共生的智慧。\n一方水土养育一方人而环境是塑造人的决定性力量。虽然我们无法控制自然界的所有力量但通过理解和尊重自然规律我们就可以创造出更加和谐、健康的生活环境。\n四积阴德\n\n但行好事莫问前程。\n\n阴德一个深植于中国传统文化之中的观念强调的是通过行善积德不以求取回报为目的并且始终保持一颗无私的心坚信善行最终会有正面的果报。\n毕竟有时善举虽小但却能在不经意间播下希望的种子可能带来意想不到的正面改变相反一时的恶念或恶行同样能引发连锁反应最终带来长久的悔恨和不良后果。\n拿古代的医圣张仲景为例他所著《伤寒杂病论》无偿传授医术本着医者仁心的信念不求名利他的善行让他成为了一位受到后世尊敬的医圣对中医的发展产生了深远的影响。\n在现代随着社交媒体的广泛使用网络欺凌已成为一个严重的社会问题。表面看似无伤大雅的恶意评论或侮辱性消息可能对受害者的心理造成长远的伤害导致抑郁、自伤乃至自杀的悲剧。\n总而言之阴德重在人际的微妙联系和相互作用。在这种视角下每个人都不是孤立的个体我们的每一个行为都与周围的人息息相关。我们要珍视人与人之间的相互关系注重每一次行为选择的影响。\n五读书\n\n万般皆下品唯有读书高。\n\n在中国古代「读书」被看作是通往功名富贵的必经之路科举制度更是将这一观念深深植根于社会文化之中。然而随着时代的发展我认为「读书」的真正意义已经发生了深刻的变化它不再仅仅是为了谋取功名而是成为了持续学习和不断迭代自我的重要方式。\n在飞速发展的当今社会中知识更新的速度前所未有仅凭过去的知识和经验已难以应对新的挑战和机遇。因此「读书」不仅作为获取新知、拓宽视野的重要手段之一我们还可以通过视频、博客、AI 等多种方式来帮助我们不断学习,适应社会的变化,而不仅仅是获取书本上的知识。\n「读书」的意义已经超越了单纯的读书它更多地反映了持续学习的能力。其使我们能够站在巨人的肩膀上借助前人的智慧看得更远思考得更深。另外还能培养我们的批判性思维能力。尤其在信息爆炸的时代面对海量的信息和观点能够独立思考、辨别是非成为了一项重要的能力。通过「读书」我们可以接触到不同的观点和论述学会分析和评价这些信息从而培养出批判性思维能力。\n更重要的是读书是自我迭代的过程。任何一本书任何一场谈话都可能成为我们思想和认知的催化剂促使我们不断反思和审视自己的行为和思想推动我们向更优秀的自我演进。这种自我迭代不仅限于知识的层面还涉及道德修养、审美情趣和思维方式等方面的提升。\n我们通过不断「读书」、自我迭代来更好地适应社会变迁。并提升个人综合素养实现自我价值的最大化。在这一过程中我们不仅获取知识更获得了成长和变革的可能。\n六名\n\n名不正则言不顺言不顺则事不成。\n\n名或称声誉是个人影响力和威望的体现。其往往与个人的道德品质、学识成就和社会地位紧密相关。在儒家文化中名更是个人品德和社会责任的外在体现。\n一个人的名声不仅仅是对其个人特质的认可更是对其影响力范围的一种衡量。但影响力和威望的建立不是一朝一夕的事情而是长期一致性行为的结果。当一个人其外在形象与内在品质统一时便能在社会中获得良好的声誉影响力随之增大。\n比如诺贝尔奖得主屠呦呦她凭借对青蒿素的发现不仅救助了全球数百万患者也为中国赢得了世界范围内的尊重和认可。屠呦呦的名声正是她长期坚持科学研究和对人类健康的贡献的结果。\n随着时间的推移现如今名的概念虽然没有根本性的变化但其背后的价值观和实现途径已经发生了深刻的变革。在现代社会中名的获得不再仅限于通过科举等传统途径而是多种多样的。科技、艺术、体育、教育、互联网等领域均可成就一人的声誉。\n然而名的获得和维持还需要符合道德和社会的期待名的追求也应当基于正确的价值观。历史和现实中不乏因失德行为而名声扫地的例子。\n例如在社会和职场中短期的成就或许可以迅速提升个人名声但只有那些基于长期贡献、对社会有持续正面影响的人其名声才更加稳固和深远。因此对于每个人而言追求名声不应该是为了名声本身而是作为自己不断进步、助人为乐的自然反映。\n名在当代社会依然重要但其真正的价值在于它反映的个人品质和社会贡献。无论时代如何变迁持之以恒的努力、不懈的追求和道德的行为准则始终是构建和维护良好名声的基石。\n七相\n\n善心生善相恶心生恶相。\n\n相由心生一个人的内心状态会直接影响到其外在的表现常常被视为内心世界的外在反映。这一概念深植于中国人的价值观和生活哲学之中强调个人的内在品德、情感状态和思想观念如何通过外在表象展现出来。\n相由心生不仅是一种物质层面上的映射更是精神与物质相互作用的结果。\n以佛教中的观音菩萨为例她以无限的慈悲和智慧帮助众生解脱苦难。观音菩萨的形象通常被描绘为面带慈笑神态温和这不仅体现了她慈悲为怀的内心也让信徒们感受到心灵的平静和安宁。这种形象的塑造传递了一个深刻的信息一个人的内在美如善良、慈悲、正直和勇敢能够通过外在相貌和行为表现出来对他人产生积极的影响。\n在现代社会这一概念依然适用。例如一位乐观积极的领导者他的自信和开朗不仅能在其外表和言行中体现更能激励团队成员营造出积极向上的工作氛围。另一方面心怀善意和同情的人他们的温暖眼神和和蔼可亲的态度往往能够让人感到亲近和舒适从而建立起良好的人际关系。\n同样公众人物如演员、政治家或商业领袖他们的公众形象往往是他们内在品质的反映。他们如何处理危机、对待他人以及展现自己的价值观都会通过他们的外在表现被公众所感知和评价。因此他们需要不断地在内心修为和外在形象之间寻求平衡以确保两者的一致性。\n我们通过培养积极、善良和慈悲的内心品质不仅能够改善自己的外在表现也能够对周围的人和环境产生正面的影响。在这个过程中每个人都应当努力成为最好的自己内外一致从而在人生的道路上行得更远。\n八敬神\n\n举头三尺有神明\n\n举头三尺有神明人生于天地间在这浩瀚宇宙中是非常渺小的千万不要狂妄自大应始终怀有一颗敬畏之心。这种敬畏不仅仅是对于超自然力量的尊重更是一种对生命、对自然规律深刻理解和尊重的体现。\n这种敬畏之心也是一种深层次的自我意识它要求我们在面对自然界和生命时保持谦卑和尊重。如同哲学家、诗人和科学家在探索自然奥秘时所持有的态度他们深知人类智慧的局限敬畏着自然的力量这种态度促使他们在探索过程中更加谨慎和尊重。\n另外这一概念也强调了个人在社会中的行为准则。真正的大师不论其在技艺或学问上达到何等高度总是保持一颗学徒的心态永远谦卑学习永不自满。这种永远怀着敬畏之心的态度是他们能够不断进步和成长的关键。\n例如爱因斯坦曾言“一个人越是了解宇宙他就会越发敬畏。”\n总之无论在哪个领域无论达到何种高度都应保持对自然、对知识、对生命的敬畏之心。这种敬畏是我们与众生和谐相处持续进步和发展的基石。通过培养这种敬畏之心我们可以更好地理解自己的位置尊重自然规律促进个人与社会的和谐发展。\n九交贵人\n\n读万卷书不如行万里路行万里路不如高人指路。\n\n如果在个人成长和事业发展的旅程中遇到能够给予指导、支持和机遇的贵人往往至关重要。因为这些贵人往往拥有丰富的经验、广泛的资源和深厚的影响力能够在关键时刻为我们指明方向提供帮助。\n然而吸引并得到贵人的青睐并非偶然。这需要个人不断地提升自身的能力和价值成为一个“有拿得出手的本事”的人。这种能力不仅仅是专业技能的精进还包括良好的人格魅力、积极的人生态度和不断追求卓越的精神。当这些品质在个人身上得到体现时便会自然而然地散发出正能量吸引那些与之共鸣的贵人前来。\n历史和现实中不乏因遇到贵人而人生转折的例子。比如古代的刘邦他能够从一个布衣平民成为汉朝的开国皇帝除了自身的努力外张良、萧何等一系列贵人的辅佐和支持也是不可或缺的。\n因此不仅要遇贵人更重要的是内在素质和能力的培养。只有不断提升自我才能在适当的时候吸引到真正能够对自己产生积极影响的贵人。\n同时保持一颗感恩的心珍惜与贵人的每一次交往用自己的成长和成功来回报他们的帮助和信任。这样我们不仅会得到贵人的支持更会在与他们的交往中学习到宝贵的经验和人生智慧从而实现自己的人生价值和事业发展。\n十养生\n\n天有三宝日月星人有三宝精气神。\n\n这句话其实深刻揭示了养生的核心要素精力、气生命力、神心灵和意志。养生不仅仅是为了延年益寿更是为了达到身心和谐。毕竟健康是生命之本养生是修身的基础身心健康才有快乐和福分。\n修身是儒家思想中的一个重要概念它要求个人不断自我完善提升道德品质。而养生则是修身的物质基础和前提条件。只有当身体处于健康状态精力充沛心灵平和时人才能够更好地进行自我完善实现个人价值。\n现代社会随着生活节奏的加快和工作压力的增大我们越来越意识到健康的重要性。养生再也不仅仅是老年人的事情越来越多的年轻人也开始关注如何保持身心健康。\n例如现代养生理念强调食疗的重要性提倡通过食物的自然属性来调养身体如季节性食材的选择以及五谷杂粮的均衡摄入这些都是古代养生智慧在现代社会的应用。同时瑜伽、冥想等古老的修身养性方法在帮助现代人减压、提高生活质量方面发挥着重要作用。\n例如马云阿里巴巴集团的创始人他不仅在商业上取得了巨大成功也非常重视养生。马云热衷于太极拳将其作为一种养生之道和企业文化的一部分强调太极拳在提高精气神、实现身心平衡方面的作用。\n健康是实现生命价值和个人发展的基础。我们应该注重身体和心灵的平衡发展通过持续的自我修养和养生实践提升生命的质量和层次。\n\n\n一命二运三风水\n四积阴德五读书\n六名七相八敬神\n九交贵人十养生\n\n那么现如今如果我们想要影响「命」关键在于充分理解自我的成长历程、性格特质以及所处时代背景。并在当今这个快速变化的时代中可以做到充分了解全球历史、经济动态、各国发展现状和未来趋势并结合对自我的深刻认知开阔眼界透过现实的迷雾摆脱命赋予的枷锁。并且始终尊重客观规律顺应时代潮流即可在命运的河流中找到属于自己的航道乘风破浪\n这里我是借用这十条因素来具体地阐述人与自然、社会之间相互联系和相互作用体系中的一部分。不过如果你能洞悉其蕴含着的深刻奥秘定能取得非凡的成就毕竟玄妙只在颠倒颠。"},"Personal/Blog/2024/乌兰哈达火山银河之旅":{"title":"乌兰哈达火山银河之旅","links":[],"tags":["博客/原创","游记/山西","游记/内蒙古"],"content":"可谓念念不忘,必有回响。\n2022 年《再游嵩山》的时候,**就一直心心念念能和爱人拥在银河下,看一场流星雨。**现在 24 年了,疫情都结束了,小雅我俩在一块也两年多了,正好端午节三天加上年假,说走就走,看银河去!\n如果想看银河必须满足两个条件**万里无云 + 零光污染。**因为小雅是不愿意爬山的,而且更不愿意晚上爬山,所以就只能选择开车可达,且没有光污染的地方。大西北虽然满足,但是太远开车的累死,最后决定──内蒙古乌兰哈达火山,一个我俩从未去过的地方 \n在乌兰哈达的时候我就碰到很多人不知道银河什么时候升起银河在哪里只会看到星空哇哇哇虽然也很快乐但我们毕竟是来看银河的对吧\n那么如果想看一次就看到银河还是建议提前研究一下相关天文知识。我一直用的都是 巧摄、Windy 来观测天气、光污染,银河等天文气象,不过有一定的门槛,第一次可以考虑 天文通。\n\n可以看到乌兰哈达光污染只有 2 级,已经非常不错了,而且火山还可以作为银河前景,简直是美滋滋。现在已经 6 月份了,今年银河季马上也结束了,小伙伴可以考虑冲一波了。\n郑州距离乌兰哈达火山虽然不到 1000 公里,但我不想直接开车过去。就策划了如下行程,全程 2200 公里 +,除非你有金刚不坏的腰子,否则不建议参考路线。\n从平遥出来看银河经过云冈石窟最后到五台山的两天一夜我都没有咋睡过。一路上我开车兼导游加摄像都不困小雅却困得飞起真是个菜狗 ~\n\n平遥古城 🤩\n\n下午 2 点从郑州出发,山西刚好雨过天晴,天高云淡。一路上欢声笑语,逃离都市的旅行就此拉开帷幕。\n山西平遥古城与安徽徽州古城、云南丽江古城、四川阆中古城并称为中国四大古城。平遥古城位于中国山西省中部始建于公元前 827-782 年,是一座历史悠久的古代城市,且是保存最为完好的古城之一,更于 1997 年被联合国教科文组织列为世界文化遗产。\n\n我们俩晚上 7 点到达酒店办好入住后,就直冲平遥古城!\n平遥古城占地 1500 亩,面积跟大学校园差不多,逛起来也不费劲。我们俩本来打算看看灯光秀,然后吃点美食最后去看「又见平遥」,结果没想到灯光秀提前半小时关闭城门,我俩被锁在城内了,想想作罢就去干饭了。\n所有的景区 80% 的美食,我感觉都是一样的。不过相比之下平遥面食特别丰富,还有山西必不可少的醋。为了避免踩坑,我们俩选择了一家人多的,点了四个菜:碗托、栲栳栳、孜然羊肉、老醋闷牛肉,主打一个吃不完带走。\n\n碗托很神奇口感有点像凉粉但不是凉粉。我问了服务员她说碗托是用荞面同水揉到一块儿加热熬成粥糊状晾凉以后加上料汁而成。还有栲栳栳竟然是蓧面和成面团再揉搓成小卷或者小酒盅的形状在蒸笼中蒸熟后蘸特殊的酱料就成了。\n我两都感觉不是太好吃但我疯狂加醋成了黑暗料理感觉还不错主要是醋很香。那个老醋闷牛肉就是因为醋很香所以非常好吃而且牛肉口感软糯咸香醋味在口中四溢真的很赞我还点了两个不同价位的汾酒说是自酿的感觉纯属扯淡……\n酒饱饭足后小雅见平遥古城街上到处都是晋家少奶奶便想找家古装店打算明天美一美就没有去看「又见平遥」。第二天一早我俩就出发前往古装店古装店生意可是真火爆直到十点多才收拾好。\n\n平遥古城通票 125 元,所以两个人就是「二百五」啦哈哈 ~\n参考官方推荐路线我俩从迎熏门上城墙溜达了一段就下来去了城隍庙本来打算请个导游不过我还是更想尝试 AI。一路体验下来我感觉现在的普通导游相较于 AI 毫无还手之力,毕竟景点历史已然无法改变,大部分导游其实也是台词,剧本。如果收集全世界导游的语料训练 AI ,再加上 GPT-4o 的视觉交互还可以实现「指哪打哪」,未来 80% 的导游可能就要回家种地了。\n平遥古城的城隍庙、县衙、镖局、市楼、日昇昌等逛过来都下午两点了微信步数两万多真的是累麻了 ~\n下一站乌兰哈达火山\n\n\n\n乌兰哈达火山 😎\n\n乌兰哈达火山地质公园位于中国内蒙古自治区锡林郭勒盟苏尼特右旗境内是一片典型的火山群地质遗迹。火山群由多座火山锥、火山口、熔岩流和火山碎屑堆积物组成形成于新生代 (距今 1 万年),也是唯一有过喷发的火山群。\n平遥古城到乌兰哈达火山地址公园 600+ 公里,预计晚上十点到,所以在最后一个服务区休整了一下。原计划在野外露营,但是考虑到不安全,我俩就车中泊了 \n\n吃饱喝足、换好装备后前往乌兰哈达火山的途中我们走错路了……\n我不太理解为什么导航五号火山却在乌兰哈达地质公园的入口处却结束了伸手不见五指的野外我只能求助于谷歌地球出于错误的判断我走上了一条崎岖小路车也很难开。突然面前出现了两头骆驼站在了小路正中间等了一会也不走怎么都过不去荒郊野外的我也感到瘆人。早有耳闻「生灵拦路必有缘故」本着宁可信其有不可信其无我还是倒了回来。\n上网一阵检索我发现只能通过乌兰哈达地址公园的入口才可以进去。在折返的路上看到来的时候那只差点被我撞死的小刺猬已经被车撞得死翘翘了……\n\n如果你要去乌兰哈达火山地址公园下了高速在 G208 国道上经过——创业就业中心后,马上左转就该到了。\n这一通折腾等到达五号火山的时候都已经凌晨了。荒郊野外我本以为不会有啥人但毫不夸张地说乌乌泱泱的都是人。好吧看来中国人还是太多了。下了车抬头看向夜空我浑身一哆嗦每次看到星空银河都是这么令我激动。\n冲冲冲拿上装备冲向既定坐标——49°3000”N,113°0639”E。抬头向南看火山银河、漫天星空就呈现在你面前。\n\n没错还有流星雨\n不过感觉大概率是卫星因为拖尾不明显。但真的有流星雨主要因为我没拍到很好的成片这里你可以臆想一下。右下角似乎是黄道光但是我不确定。\n\n黄道光Zodiacal light是指在夜空中靠近太阳的地方沿着黄道或黄道带泛出略呈三角形的白色微光。在北半球的中纬度地区最适合观察黄道光的时段是春季的暮光完全消失之后的西方天空或是秋季曙光出现之前的东方天空。因为黄道光非常黯淡月光或光污染很容易盖住黄道光。黄道光的强度会随着远离太阳而减弱但在非常黑暗的夜晚也能观察到黄道光笼罩着整个黄道。\n——维基百科\n\n这样一看欧皇就是我每次银河之旅都会运气爆棚。\n\n滴银河相拥达成\n即使临近盛夏乌兰哈达火山夜里的温度也只有十度左右。我还记得出发的时候小雅信誓旦旦向我表示看了天气预报还特地准备了两件厚外套。结果到了才发现外套薄得像纸一样相机 25 秒的快门纷纷冻成狗。我担心小雅生病,就先把小雅送下山回车里了。\n随后我又来拍银河延时碰到了几个驴友还在不知所措找机位拍银河。无心的手电筒直接毁了我的延时想想算了最后送了他们银河照 \n凌晨三点多银河开始落下我也扛着相机回到了车上。本来打算一早看日出呢看到小雅睡得像猪仔一样感觉没戏了。\n睡觉\n\n五点多我翻了个身看到天亮了。砰立马坐了起来还要看日出呢推了推小雅起来看日出了小雅哼哼拧拧的也不知道说的是啥……\n我下车一看乖乖哪都是帐篷哪都是车人跑的哪都是。我又飞了一会无人机但是太冷了就回车里待着了。虽然我也没看到日出但是天高云淡草原一望无际火山各色各异实在是美不胜收 \n不行得把小雅喊起来不然太亏了但小雅也不起床我就拉着她在火山地质公园转了一趟又一趟。途中碰到一大哥在晨跑那真是给我羡慕的直流口水。终于在溜达第三圈的时候小雅起来了不过看了一会就又倒下了……\n其实我特别享受独自欣赏大自然风光的时刻。去年的黄山之旅也是一大早也没有那么多人一切仿佛都是为了我而存在独自享受着灵魂和身体的交歌相融。\n下一站👇🏻👇🏻👇🏻👇🏻👇🏻👇🏻👇🏻\n辉腾锡勒草原 🥰\n\n从乌兰哈达火山地质公园前往辉腾锡勒草原需要走两个小时的国道我可是非常喜欢自驾走国道的毕竟最美的风景永远在路上一路上可以慢慢悠悠的对比着内心中的内蒙。\n我路过的地方生态退化严重大部分草场存在不同程度的荒漠化好一些的地方还可以打井种地差一些地就草都不长。村庄城镇的规模相比较内地小得多而且一路上几乎没有碰到年轻人。不过那会才七点多也有可能我起来得太早了。而且草原上天气多变西边下雨东边放晴中间还给你来个大彩虹。\n旅游景点我认为到哪里都一个样只有深入地了解当地人们的生活习俗才可以真正地了解地方文化。而且我其实特别好奇在中国五千年历史上扮演重要角色之一的内蒙古现如今是什么一个样子\n在山西曾路过了雁门关雁门关在历史上与函谷关、仙霞关、剑门关并称中国四大古关口并且雁门关一直是中原抵御北方游牧民族南下的前线要塞。历史上关内关外严重的意识形态的对冲致使来来回回打了几千年的仗现如今随处可见的政治标语似乎解决了这个问题。但一想这却又是不可能的意识形态很大程度取决于客观条件而这些条件在某些方面并没有根本性的改变。\n不过身处在这片土地上我能够感受到一种跨越时空的共鸣。\n\n本来有考虑去呼伦贝尔大草原但是行程就又多出 1000+ 公里,自驾实在太不适合了。就选择了辉腾锡勒草原,但实际体验感很差,破坏了我对草原的美好幻想。\n我以为的草原——风吹草低见牛羊但说实话到处都是粪便虫子枯草……\n我以为的骑马——策马奔腾、草原巡游实际地骑马草场主人牵着马带你在遛两圈……\n我以为的终究是我以为的还是上美照吧 \n\n\n\n\n\n\n\n云冈石窟 🤯\n云冈石窟位于中国山西省大同市西郊的武周山南麓是中国著名的古代佛教石窟群之一与洛阳龙门石窟、敦煌莫高窟和天水麦积山石窟并称为中国四大石窟。\n云冈石窟始建于北魏时期约公元 460 年至 525 年间,是中国第一处由皇室显贵主持开凿的大型石窟。又历经多个朝代的扩建与修缮,共有主要洞窟 252 个,内有佛像 51,000 余尊,涵盖了佛教艺术的各个流派,展示了从北魏到宋元各时期的雕刻艺术风格。\n内蒙古乌兰察布与山西大同相邻驱车不到两个小时就到了。不过我俩在路上干仗了云冈石窟啥子都木得拍。白瞎了我巨资聘请的导游……\n五台山 😏\n\n五台山位于中国山西省东北部中国佛教四大名山之首以其悠久的宗教历史、丰富的文化遗产和秀美的自然风光著称。五台山名因山上有五座主峰而得名分别代表五方佛的居所。\n这座山以文殊菩萨为主尊被视为文殊菩萨的道场吸引了无数朝圣者和游客。五台山有着极为丰富的寺庙建筑包括著名的菩萨顶、塔院寺、显通寺等。\n五台山地形有点像我们的手掌五座山形似手指掌心则是台怀镇。而且五台山天气诡异多端一会艳阳高照一会乌云密布一会狂风骤雨。\n\n我来五台山主要是因为当舅舅了所以带着给团子的宝物来开光祈福。不过这几天爆肝式的特种兵之旅小雅算是彻底废了。\n端午假期最后一天了时间有限我俩从南门入山直达五爷庙随后溜达溜达就准备下山回家了。\n\n最后\n这次特种兵终极爆肝自驾旅我既做攻略又要开车还要摄影最后都顶了下来。实在是没想到小雅是个菜鸡一路上吃饭睡觉打豆豆结果还顶不住。这样一看我俩还是躺平式旅游最合适。\n自打买了单反到现在两年多的时间虽然还依旧是停留在「玩」的阶段但这次我也是有了更加深刻的认识\n\n\n摄影和旅游完完全全是两件事情。\n\n\n目前的理论知识已经阻碍了摄影水平的进一步提高。\n\n\n切实地感受到了器材对于我的约束。\n\n\n因为我是特别热衷于能够把美好的一瞬间留给他人所以未来会继续精进摄影知识和实践水平 \n这篇博文我花费了不少的精力和耐心例如摄影后期修图阅读删减繁琐的内容从近 1W 字到最后还是来到了 5K 字左右。我并不是不快乐,只是说实话写得很蛋疼。\n对于游记而言我认为流水账式的内容不太适合文字书写。Vlog 的信息密度更大,通过视频和声音可以更直观地展示旅行中的美景和体验,而 Blog 的文字虽然可以精简,但却难以生动地传达出旅行中的细节和氛围。\n未来的旅行中我会开始更多的尝试用 Vlog 来记录。最近琐碎事也很多,生活更是无敌充实。周更博主,也马上变成月更了哈哈 \n不过终于发表出来了好爽。\n🫣🫣🫣"},"Personal/Blog/2024/冰箱,让你我错过了多少新鲜的生活?":{"title":"冰箱,让你我错过了多少新鲜的生活?","links":[],"tags":["博客/原创","成长/个人"],"content":"下班后逛超市,买了些水果和面包回到家里,发现冰箱早已被老妈塞满,一包不知道几天前的蔬菜,还有四处散落着的剩饭。整个人瞬间都不好了,老妈,冰箱真的不是万能永久保鲜的……\n不过如果世界没有冰箱我们每天吃的岂不都是新鲜蔬菜细细一想却不无道理。\n生活中我们经常把新鲜蔬菜放进冰箱这些新鲜蔬菜则期待着某天被我们吃掉而实际情况是大多数新鲜蔬菜都难逃冻僵、腐烂的结局。\n如果没有了冰箱那么我们或许会每天跑超市、逛菜市场买最新鲜的蔬菜过上每天都能吃到新鲜蔬菜的生活。\n但真的会这样吗\n可以想象一下在这个没有冰箱的世界里我们每天都在吃新鲜蔬菜似乎生活变得更美好了。\n然而这个美好的假象背后是我们不得不面对的现实每天重复的劳累和时间的浪费。\n早晨你得早起去市场和一群同样为了新鲜蔬菜而争抢的人们斗智斗勇。中午菜市场的吆喝声此起彼伏晚饭后你发现刚买的菜已经开始蔫了。\n这时你才意识到原来冰箱不仅仅是保鲜的神器更是偷懒的温床。\n我们总是习惯于把新鲜蔬菜放进冰箱幻想着某天能享用它们。\n实际上我们却把很多「新鲜蔬菜」都「冷冻」了期待未来有一天能「吃掉」。而大多数情况下这些「新鲜蔬菜」都难逃被遗忘和荒废的命运。\n那如果真的没有「冰箱」你真的会每天吃到「新鲜蔬菜」吗\n或者你只会发现自己每天在疲于奔命打开冰箱才发现「新鲜蔬菜」早已腐烂\n关掉冰箱出去走走「新鲜的生活」比「新鲜的蔬菜」更值得追求。"},"Personal/Blog/2024/回读者信──240816":{"title":"回读者信──240816","links":[],"tags":["博客/原创","写作/技巧","成长/个人"],"content":"\n中平你好\n你的博客有一段时间没有更新了近况如何在上一篇博文中注意到你的人生要进入下一个阶段了提前向你祝贺\n四个月前我在评论中提到你的博客对我的影响现在我开通自己的博客啦~\n这份邮件的目的关于博客一是分享体会二是征求意见三是请教问题。\n这是我的博客地址金色河流 | Golden River\n套用 NotionNext 的模板,刚建站的时候我曾花大量时间折腾(主要是主题哈哈),但是奈何水平不够看不懂代码也没调试环境,折腾了半天努力努力白努力,无数次报错后最后还是回到了极简的风格。逛其他人的博客时再自己的对比起来有种毛坯房的感觉。但极简风格挺好的,有助于我专注内容。只是毕竟是毛坯房,我觉得不搞花里胡哨的,在主题颜色、页面布局或者行文的排版上还能做一些调整。\n\n你的浏览体验如何呢\n有何关于形式以及内容上的意见或建议\n\n我想请教的问题主要是写作上的。\n博客是我的互联网自留地我目前不期待任何曝光这也是我选择独立建站而不是平台的原因。但毕竟是公开写作和放在自己私人笔记本里的点状笔记还是有很大的差别。写给自己看的笔记只需写下要点即可但公开写作预设除自己外的读者就需要对条理逻辑捋得更清晰。我离高考写作已经非常多年了这个要求现在对我来说是一件难事。\n我注意到你的博文行文非常流畅娓娓道来情感充沛非常吸引人。内容也很有趣。我喜欢阅读这样的文字。\n所以想向你请教\n\n你写作时是如何想象自己的读者的呢\n如何转换私人笔记上的生硬的、要点式的语言到博客上生动性的、叙述性的语言呢\n能否分享一下你写作上的经验\n\n感谢。\n\n感谢来信最近整体还算不错订了婚领了证完成了一件人生大事哈哈哈。\n博客没有更新一方面是生活琐事太忙导致没有精力输出了一方面是没有很好的命题创作。\n既然选择开通了博客那就共赴十年之约\n关于博客主题的看法\n什么毛坯不毛坯的自己不满意就折腾折腾累了就不折腾。曾经我也疯狂折腾过主题还开发了一款呢这是博客必经之路哈哈哈。对于博客主题事实上我觉得自己开心才是最重要的如果你都不想看更别提读者了……\n不过从读者的角度出发阅读者并不会关心你使用的博客系统就是你喜欢用啥系统都行。\n其次就是博客的第一印象很重要但不过千人千面不存在完美的博客主题。那么我们能做的就只有访问速度、整体观感。\n\n\n访问速度可以考虑国内服务器一些原因我是国外的再套 CDN另外再来一些小魔法就会很好的提高访问速度。\n\n\n整体观感\n\n\n博客主题如同人穿衣穿衣的第一要义就是干净整洁。\n\n\n第二要义是鲜明的主题、引人注目的内容以及简练的构图。这是我之前写的《如何拍好一张照片》中提到的我认为博客主题应该同样如此。\n\n\n如下是我对于《金色河流》现在的一些具体建议仅供参考 ~\n\n\n我对 Notion 使用不多NotionNext 模板也了解不多。不过建议选择成熟度高的主题,这样加上 AI 的帮助,你修改起来很容易的。\n\n\n可以考虑拥有一个符合站点的 Logo这样可以更好地留下第一印象可以考虑 AI 创作,然后稍微修改一下)。首页的图片有点夺焦,可以考虑转化成 Logo。\n\n\n首页展示建议不要超过个位数篇文章我认为 3-7 个最好。\n\n\n建议拥有一个关于页面这样可以留下沟通渠道或者更加深入地了解你。\n\n\n文章页面建议只使用 Markdown 语法,并且不使用富文本编辑器。\n\n\n文章页面只可以拥有一个 H1 标题,其余标题从 H2 开始,并且标题次第排序,建议不超过 H4可以参考阅读 技术文档写作。\n\n\n建议删除站点鼠标浮动的特效。\n\n\n建议站点域名更换 .com 后缀(结合实际情况决定)。\n\n\n虽然日后你可能也会摸索到这些但是当下的开心比日后的快乐更重要\n博客是我的互联网自留地我目前不期待任何曝光这也是我选择独立建站而不是平台的原因。\n这不是一个可以回答的好问题我更建议你抛弃这个想法。\n我离高考写作已经非常多年了\n高考和写作之间没有任何关系。建议关注当下平常心对待过去和未来。\n你写作时是如何想象自己的读者的呢\n我没有想象过我的读者但我是每次写完之后的第一个读者。一篇文章我甚至会通读数十遍然后再改了又改最终发表出来。\n如何转换私人笔记上的生硬的、要点式的语言到博客上生动性的、叙述性的语言呢\n对于生硬、生动应该如何去定义呢\n我觉得不骂人都算是好文章哈哈不过文章内容还是要避免出现病句错字并且避免过多使用互联网流行词。\n如果你觉得『硬』就多读多改其实这也是你的风格更是独一无二的你。\n能否分享一下你写作上的经验\n说实话你问我关于写作的经验我有种受宠若惊的感觉哈哈哈 ~\n这个问题我也探索过而且还读了很多的关于写作的书不过最终也没有找到我想要的答案但是每本书的作者都不约而同地表示写作最重要的事情是──写。\n至于你想要的『经验』我觉得应该是过往应试教育的毒害。\n写作要什么经验写就完事了\n一些我想说的\n生活中我非常喜欢爬山三山五岳大多都已征服。\n每次站在山脚下我总想着下一秒就能站在山顶俯瞰群山一览众山小。\n然而只有当我真正走进这座山时才开始真正享受它带给我的一切。\n写作同样也是如此。\n在我博客的前三年里没有任何互动纯粹是我自己的独白。\n无论是折腾主题也好倒腾系统也罢这是每个博主都会经历的过程。\n毕竟爬山的时候我们不也是会选择不同的路线吗\n有时候坐缆车轻松愉快但少了些挑战和乐趣有时候走崎岖陡峭的小径虽然步履艰难但却能让我们感受到山的每一寸脉动。\n写作同样也是如此。\n登山最重要的并不是结果而是每一次踏出的脚步。\n写作最重要的不是到达顶峰的那一刻而是每一次思考的瞬间。\n无论是爬山还是写作都是一场与自我的对话。让我们学会了坚持学会了享受孤独学会了与自己和解。\n最终当我们回首过去时才会发现正是这些路途中的点点滴滴造就了如今的我们最终成就了我们内心的那座山峰。\n──仲平"},"Personal/Blog/2024/回顾-2023":{"title":"2023 年终总结","links":[],"tags":["年度/2023","博客/原创"],"content":"我喜欢在农历新年后总结一年的收获,因此,我又一次地写下了年终总结。今年的总结较往年更加客观,并回顾了是否完成了之前设定的年度目标。\n\n\n2021 年度目标完成度80%\n\n\n2022 年度目标完成度60%\n\n\n2023 年度虽未设立具体目标,但有明确方向,自评 60 分,勉强算是及格。\n\n\n关于 2023 年没有设立具体目标的原因,主要是因为以往年度目标的打脸,以及不可预测的因素实在太多。因此,从 2023 年开始,我选择设定大方向,努力前进,顺其自然。\n可量化部分\n2023 年的一些可量化成果如下:\n\n\n微信读书 213 小时,阅读完成 50 本书,做了 1921 条笔记。\n\n\n发布博客 30 篇,月访问量超过 1000维基文章累计 20+ 万字,月访问量同样超过 1000。\n\n\n贡献了 2 个开源项目,获得了 100+ 的星标。\n\n\n去了 10 多个城市。\n\n\n不可量化部分\n2023 年不可量化的部分主要涉及工作、生活和健康等方面,我还是喜欢按照春夏秋冬四季来回顾。\n春\n新年过后我的川西环线之旅非常难忘。回来后工作和学习的实际进展一般。\n这期间表哥结婚了、爷爷生病住院。其中爷爷生病期间一系列的骚操作再次刷新了我的认知糟老头子坏得很\n可谓生活琐事磨人心\n夏\n初夏时去了安徽黄山一趟然后参加了姐姐在福建的婚礼。\n那段时间我坚持的生活习惯如早睡早起、健康饮食、持续锻炼和冥想让我身心达到了一个新的高度。工作学习效率特别高情绪也嘎嘎稳定。\n秋\n秋天去了焦作云台山登封少林寺然后我们又一起去杭州看望姐姐。\n秋天整个人都是闷闷呼呼的不知道是不是因为绿茶喝多了导致脾胃变得更虚弱了。还是久思伤脾久坐伤胃\n秋天整体状态不如夏天然后感觉身体状态有所下滑换季导致的呼吸道疾病多发虽然对我影响不大但还是感到有些不适。\n冬\n冬天参加了大学室友的婚礼并协助朋友规划了一些公司上的具体事务。期间乱七八糟的事情蛮多学习也搁置了。\n年末终于去了对象家里拜访父母整体感觉顺利为 2023 年画上了一个圆满的句号。\n健康\n健康始终都是第一位今年上半年做得不错下半年则有所放松。整体来说需要更注重习惯的养成和持续的打卡。\n例如合理健康的饮食计划的安排还有《三一计划》的执行。有时候感觉工作一天了也很累就压根不想动就感觉有点无解。\n新的一年重拾良好的饮食习惯和运动计划好好锻炼身体。如果可以的话就搞辆自行车 City Walk。\n工作\n工作一直都是老样子没什么可展开讲讲的。有就是帮朋友公司做出了许多有价值的决策深度体验了现代企业中各种角色哈哈哈。\n今年还有一个心得就是在大多数企业能力不是最重要的。大部分企业 80% 的工作岗位负责内容只要是个人,并愿意学都能做到 60 分,总的来说人脉 > 资源 > 平台 > 机遇 > 能力。\n新的一年工作争取迈向新台阶同时也多尝试一些副业深度锻炼一下自己。\n生活\n今年生活中的事情相对来说比较多繁琐的事情也比较多不过经历过后让我更加成熟。\n心的即是远离遭人烂事千万不要妄想改变任何人。如果遇见遭人烂事就抓紧跑路\n新的一年就尽可能地远离遭人烂事积极拥抱正能量。\n阅读\n23 年读了很多技术书籍,并和 GPT 聊了很久。读书加写作带来的成长是不可小视的,但 ChatGPT 带来的成长更加显著。\n新的一年阅读的主要方向是哲学并复读一些书籍。\n成长\n23 年经历的事情也不少,心智阅历增加许多。但是还是会有一些不足的地方,不过人嘛,毕竟不是圣人。\n新的一年就逐渐完善自己巩固已经获得的成果。\n社交\n有些人就是很棒有些人就是很恶心。有些人就是很优秀有些人就是很垃圾。\n新的一年减少无效社交双向奔赴。\n爱好\n在编程之外我近几年培养了基于琴棋书画诗酒花茶进而衍生出的钢琴围棋书法摄影写作等。\n钢琴已经好久没有碰了。围棋方面有了不小的进步希望自己的水平能更上一层楼。书法主要是硬笔书法毛笔书法目前还没有尝试。摄影的基本功还在但真的很懒。写作也是一中断就容易捡不起来。至于饮酒我现在很少喝了。喝茶方面我几乎品尝了国内所有常见的茶种特别偏爱乌龙茶中的凤凰单丛以及红茶和绿茶还喜欢尝试混合品饮如红茶 + 少量凤凰单纵。我还阅读了不少与茶相关的书籍,有机会也会分享我的品茗心得。\n新的一年我想主要专注于写作和摄影。如果有时间的话也包括练字和下围棋。至于其他爱好就看实际情况了。\n情感\n过去一年我与小雅的相处越发和谐愉快哈哈哈。情侣间的相处毕竟是一个相互磨合、理解和共同成长的过程嘛。\n至于老爸老妈就维持现状。毕竟随着年龄的增长追求的是怎样快乐就怎样生活。老姐因为不在一起就尽可能地多一些关心和呵护。期待未来能有机会共同生活 \n对于其他人将心比心就好。\n目标\n24 年新的一年,各个方面都争取迈向新的台阶,同时利用年轻的优势多尝试,拓宽发展的可能性。\n在生活上就尽可能地追求简单和快乐——让生活方式尽量减少不必要的复杂和紧张寻找属于自己的幸福和快乐。"},"Personal/Blog/2024/夜泊西湖听雨声":{"title":"夜泊西湖听雨声","links":[],"tags":["博客/原创","游记/杭州"],"content":"自从姐姐在杭州定居后,我每年都会往返这里。而这次是为了迎接我们家的新成员——团子 ~\n每次独坐湖边的长椅上都会陷入过往与未来的思绪之中。从三年前我第一次来杭州至今经历了诸多的变化和成长。每一次来到西湖仿佛都能倾诉我的情感。\n\n任由灵魂随着湖面荡漾的涟漪远飘听雨、观湖、抚风。\n\n上有天堂、下有苏杭 ─ 2021\n"},"Personal/Blog/2024/如何开好一场会?":{"title":"如何开好一场会?","links":[],"tags":["博客/原创","工作/经验"],"content":"如今,作为打工人的我们经常需要主持和参加各种类型的会议。然而,由于有些人并不擅长这方面的工作,导致参与者的「生命」被浪费。那么,我们究竟应该如何才能有效地开好一场会议,避免浪费「生命」呢?\n什么类型的会议值得开\n头脑风暴和决策会议是最有价值的会议类型也是最应该开的类型。\n其他类型的会议如果可以避免参加的话就尽量避免吧。毕竟有时候一场本应只需要 30 分钟的会议,但参与者有 100 人。由于会议主持者无法有效控制进度,可能会延长到了 60 分钟。这意味着浪费了 3000 分钟的生命!\n因此首先要对开会有一个明确、清晰的定义。相对于邮件等异步沟通方式会议是一种面对面、同步且信息密度更高的沟通方式更适用于需要通过沟通达成具体目标的场景。所以我强烈建议不要参加那些乱七八糟的会议因为那很可能会变成毫无目的的闲聊。\n开会应该多少人比较好\n理想的会议人数应该控制在 3 到 7 人之间,这样可以保证沟通效率和会议质量。毕竟人太少也没必要开会了,可人太多的情况下,你一嘴,我一嘴的也沟通不出来什么结果。\n举个例子如果有 7 个人参加会议,每个人平均发言 5 分钟,那么发言环节就需要 35 分钟,再加上其他时间可能需要 1 个小时左右。在会议中1 个小时的时间节点非常重要,因为大部分人的注意力超过 1 个小时后就会明显下降,从而导致会议效率降低。\n如果会议人数过多会议就会变成一场单向的演讲参会者很难有实质性的参与和交流。如果一场会议有几十上百人那更多是一种需要共情的演讲一种单方面的信息灌输。实际在现场和会议结束后看 PPT 的差距不大,完全就是浪费生命。\n开会前都需要准备什么\n作为一名合格的会议主持者你应该提前准备好会议所需的基础设施比如会议室和设备并确保会议流程和人员安排妥当。同时会议的主题和流程应提前至少一小时通知给所有参与者。通知会议主题的内容最好不要超过一张 A4 纸,因为如果真的需要那么冗长的会议,那就真的没必要开了。\n如果你没有提前做好任何会议准备匆匆忙忙地拉起一场会议然后会议期间又因为各种突发事件导致浪费大部分人的时间那就是一种可耻的行为。\n开会中都需要做什么\n首先要批评一万遍那些只会读 PPT 的人。我们都认识字,有这个时间听你读 PPT还不如干点其他的事情。还有那些重复讲一个观点 3456789 遍的人,我真的不想听你念经,念经念得这么 6你为什么不去出家\n在你通知相关人员参加会议时大部分人对会议内容都有初步的了解并且知道会议的主题。会议中你只需要深入地解释一下会议的目的和依据比如为什么要这么做支持你这么做的决策因素是什么在与参会者反复沟通和确认后就可以开始行动了。\n有些人可能会说他们根本不看会议主题。但请记住那是他们的事情。如果他们连会议主题和内容都不去了解那就只有两种可能性一是你邀请了错误的人二是他本来就不该参加会议。\n临近会议结束时一定要再次确认沟通的结果如果可能的话可以要求参与人员签字。因为你开会的目的就是想面对面及时沟通和确认。\n会议结束后需要做什么\n会议中还有一项非常重要的工作那就是会议记录。现在很多人开会时压根不做会议记录或者只记录对自己有用的内容导致会议结束后可能会感到一头雾水只能通过查看 PPT 来回顾。\n现在已经是 21 世纪了,我们应该学会利用现代化工具,高效快捷地做会议记录。比如讯飞听见,这是一款专门为会议场景设计的录音拍照应用。无论你是会议主持人还是参与者,我都强烈建议你使用这样的工具。\n讯飞听见不仅具备录音功能还可以将语音实时转换为文字并支持拍照。你可以在会议期间边录音边拍照最后一键生成会议内容和会议纪要。此外你还可以与 AI 进行沟通,确认一些细节内容。这样,会议结束后的一分钟内,你就可以快速分享会议内容和会议纪要,并根据这些内容快速确定下一步需要执行的任务以及相关的负责人。通过任务管理系统快速分发任务,并监督控制任务的执行。\n在现实生活中我们经常会被各种低效率、无价值的会议所浪费。唉有这个时间还不如玩玩手机乐呵乐呵而不是听你们说一些有的没的。\n啊毁灭吧世界"},"Personal/Blog/2024/如何打破信息茧房?":{"title":"如何打破信息茧房?","links":[],"tags":["博客/原创","成长/个人"],"content":"现如今信息茧房的概念,大家已经非常熟悉了,但我也想再啰嗦一遍。\n\n信息茧房是指个体由于个人偏好仅接触到限定范围内的信息这种现象会导致个体的视野逐渐缩窄。这个概念由凯斯·桑斯坦提出与回声室效应和过滤泡泡有相似之处主要关注信息多样性的缺失问题。信息茧房的形成受到大数据、用户行为及推荐算法的共同影响虽然这增加了用户粘性却同时限制了信息的多样性进而可能催生群体之间的极化现象。\n—— 信息茧房\n\n在此我想先重申一下「互联网精神」即开放、平等、协作、快速、分享。虽然互联网的快速发展似乎逐渐偏离了这一初衷我们也不能否认商业化为其发展所做出的贡献。\n关于信息茧房我们同样应持辩证的观点来看待。一方面算法定制化提供的高密度信息源让我们能够足不出户就了解世界各地的新闻例如对骑行有浓厚兴趣的人可以通过抖音迅速找到志同道合的圈子何乐而不为呢然而另一方面长时间接受这种定制化和高密度的信息推送不仅剥夺了我们独立思考的能力还可能导致思想的极端化。\n我们长期只接触有限的信息源最终就可能导致思维的僵化。虽然个人思维的固化并非不可逆转但若是群体性地出现这种现象则其后果无疑是非常可怕的。\n因此打破信息茧房的关键在于我们是否愿意主动寻求和接触多样化的信息源。\n碎片信息源\n我的碎片信息源主要由 RSS 订阅提供。首先 RSS 是一种公开,异步,需要手动维护的信息源,它不仅可以用来订阅独立博客,还包括论坛帖子,时政新闻,财政报道,官方通知等多种内容。\n基于我个人的实践经验下面我将分享如何利用 RSS 作为载体,高效打破信息茧房。\n\n如图我基于 FreshRSS 阅读器打造的 V2 版本 RSS 阅读器,关于 V1 版本在之前博文专题《数字文具盒》中有详细讲到。V2 版本主要针对使用流程和管理方法做了进一步优化。\n关于 FreshRSS 阅读器搭建,互联网许多相关教程,这里我就不再叙述了。但我特别推荐兼容 FreshRSS 的移动客户端——FocusReader无论是颜值还是实用性都是非常 ok 的。\n前面我有说到 RSS 源是需要手动维护的可千万别低估这一过程的复杂性我相信很多人一定曾被折腾的头一个比两个大。例如有些独立博客三天两头换域名、RSSHub 路由三天两头不能用、公开分享的 RSS 源乱七八糟、新的 RSS 源又不知道去哪里找。\nRSS 信息源去哪里寻找?\n我的 RSS 信息源主要来自三个渠道互联网搜索RSSHub 以及个人爬虫。这里我需要强调一点,务必要学会尝试不同语种的 RSS 信息源,融入全球互联网是非常有必要的。\n通过谷歌使用主题 + 关键字,可以简单、高效找到所需信息源,并且通常是稳定的官方信息源。\n\n\nRSSHub 是专门为那些本身不提供 RSS 的网站提供订阅功能。我还开发了一个基于 Python 的 RSSHub 青春版,解决了 RSSHub 的一些不足,还可以满足一些特殊订阅需求。\n\nRSS 信息源如何管理维护?\n\n熵增定律如果没有外力作用系统内部会逐渐趋于混乱。\n\n如果想要形成可靠优质的 RSS 信息源,学会管理维护是至关重要的。主要包括如下步骤:\n\n\n根据需求划分信息源主题。\n\n\n分类整理 RSS 信息源。\n\n\n定期更新维护无效信息源。\n\n\n定期不断探索新的信息源。\n\n\n如果是刚开始使用 RSS 的朋友,我建议维护一个每日能提供大约 3000 条信息更新的 RSS 源集合。注意,这并不是说 3000 个不同的信息源。因为有些 RSS 源一天能更新很多条内容,而有些一周可能只更新一次。然后随着慢慢深入使用可以自行调整删减。\n目前我的 RSS 信息数量维持在 1000 ± 500 条左右,日常阅读大概需要花费我 45 ± 15 分钟左右。不过这个信息量具体取决于个人时间,可以自行调整。\n对于随机尝试了解新的信息源我是不喜欢漫无目的地阅读容易左耳进右耳出。只有我了解到新主题后就会开始尝试搭建对应的 RSS 信息源体系。\nRSS 信息源如何高效阅读?\n首先如果 1000 条信息源,一条一条划着看,同时遇见优质信息再深入阅读,两个小时都不一定够。\n下面分享三个我用来提高阅读效率的 Chrome 插件:\n读点东西 一个开源的 Chrome 插件,可以将网页转成阅读模式,并且内置了 AI 总结、翻译、Markdown 转换等功能。\n这个插件目前不支持自定义 OpenAI 接口,作者似乎放弃了项目。其实也可以去 Github 替换一下接口地址, 然后 Chrome 安装自定义插件就行哈哈哈。如果有熟悉 TypeScript + Chrome 插件开发的,可以 Fork 一下造福全人类。\n\n ChatGPT 总结助手 可以对任何网页进行总结,支持 GPT 3.5、GPT-4 等模型。如果你没有 ChatGPT 的 API可以使用 one-api 反向代理使用国产大模型替代 OpenAI。\n\nKimi Copilot 同样支持一键总结网页内容。Kimi 是最近发布的国产大模型,对于上面的 ChatGPT 总结助手,多了可以继续深入沟通的功能。并且 Kimi 支持 20 万上下文,目前 Kimi 暂时免费使用。\n\nChrome 还有非常多类似的插件,主要就是可以快速判断一篇长文是否值得阅读,避免浪费生命,读得稀碎。\nRSS 信息源如何收藏整理?\n纵使你有再丰富的 RSS 信息源,了解到了足够的新知识。如果不做好整理归纳依旧无法形成生产力,毕竟 RSS 信息源属于碎片化知识,\n如果遇见优秀的文章一般我都是先使用 wallabag 标记保存稍后深入阅读。如果发生灵感还可以顺手使用 memos 快速记录灵感,以便日后写作整理使用。\n\n\n当然如果需要进一步深度归档方便日后查阅可以借助 Zotero 文献管理工具。\n\n深度信息源\n深度信息源指那些可以提供系统性知识结构、深入分析和全面讨论的信息源。这类信息源的载体主要为书籍、学术论文、研究报告、政策文件等它们能够提供比碎片化信息更全面的知识和见解有助于帮助我们深入理解和研究特定领域。\n如何读好一本书\n我特别推荐《如何阅读一本书》一定要尝试深入实践书中关于「主题阅读」的部分。如果读完一遍后可以通过复读和刻意练习对于加深理解是非常有帮助的。\n我依旧是强烈建议带着问题的阅读这对知识的内化至关重要。读完后可以通过分享读书笔记的方式来进一步加深印象和理解。我在这方面也有一些实践经验尤其是如何更好地「数字化」处理阅读时的思考和笔记。很多人应该会发现阅读时的思考往往难以在写笔记的时候完整回溯想不起来了。而且从微信读书中一个个整理划线的内容也比较繁琐。\n我是采用了 Obsidian + Weread 微信读书插件,将微信读书的划线笔记和评价同步至我的 Wiki 内,然后通过我的 X·Eden 分享。如下图所示,这种方法完美解决了我在阅读和思考过程中的笔记「数字化」问题,同时书评也可以同步哦。这样一来,实际上也就不需要写读书笔记了 \n关于 Zotero 和 Obsidian 的具体使用方法这里我就不具体的展开讲解了。如有感兴趣可以深入探索东半球强大的知识管理社区——PKMer。\n\n\n如何研究学术论文专题报告\n至于如何高效开展学术研究目前我是没有能力为你解答的。但是我想强调的是如果工作生活遇见某一领域具体的问题不妨问问这个领域内专业的人士或者学会如何阅读学术论文、研究报告。\n毕竟这个世界上 80% 的人,所遇见 99.9% 的问题都是存在现成的标准答案。\n高密度信息源\n高密度信息源是深度信息源的延伸它主要通过人与人之间的交流互动来实现。例如专题视频、面对面沟通、研讨座谈会等形式。与深度信息源相比具有更加直接和全面的信息传递能力。\n例如抖音直播连线就是一种简单高效的方式。尽管很多时候社会舆论抨击抖音 = 奶头乐,但实际上,也有一些非常优秀的人,曾经被大家广泛认可过。我们可能只需要花费几百块钱,就可以直接连线沟通交流。当然如果线下也想结交这样优秀的人,首先自己一定要拥有相应的潜力,这样更容易吸引和融入到优秀的圈子里。\n其实博客也是一种非常简单高效的方式而且不止博客有十年之约高校教授们也有 科学网博客。尽管网站有「研究生」门槛限制,不过都能围观了解,进而接触到高密度的信息源。\n\n同时中国大学 Mooc 和世界顶尖大学的公开课,都是互联网时代的重要信息源。如果放在二十年前,这样的资源绝对是想都不敢想的事情。虽然线上课堂缺少了交互性,可是现如今几乎所有的教授都会基于邮箱沟通交流,关键在于你愿不愿意?\n还可以广泛认识社会中各层次各种角色的人并通过交流不断尝试换位思考我们可以深入体会每个人的思想。与优秀和高能量的人交流会潜移默化地影响改变我们的思想及行为模式。更进一步如果你可以广结善缘三百六十行结交各路好汉足够击穿任何形式的隔阂所谓的「信息茧房」不过只是一层窗户纸罢了。\n正如古语所言「三人行必有我师焉择其善者而从之其不善者而改之。」\n我们应该始终保持一种开放的心态无论是好的还是不好的都应该主动寻求和接触多样化的信息源。"},"Personal/Blog/2024/富人的红灯与穷人的绿灯":{"title":"富人的红灯与穷人的绿灯","links":[],"tags":["博客/原创","生活/感悟"],"content":"在这个社会中,存在一种神奇的社会实验,名为「自由流动」或者更贴切的说,是「生死由命」。在一个不起眼的城市角落,有一个十字路口,每天都在上演着一出生死交响曲。这里,车流如织,人流如潮,每个奔跑的生命都在这个无红绿灯的舞台上,翩翩起舞。\n是的您没听错这个十字路口没有红绿灯。\n政府显然是采取了一种创新的交通管理策略——不干预。这是不是意味着要等到十字路口出现足够的悲剧政府才会发现投放一个红绿灯的经济效益和人命价值\n让我们换一个场景想象一下那些有权有势的地方比如富人住宅区。哦那里的每个角落都安装了最先进的红绿灯还有巡逻的保安确保每一位富人的宝贝孩子都能安全上学、下课。在那里红绿灯不仅仅是交通工具更是一种身份的象征是对生命尊严的肯定。\n这样的对比不禁让人思考难道只有生活在光鲜亮丽别墅里的孩子他们的生命安全才值得被保护吗而普通老百姓、穷人的孩子们他们的生命就只能任由命运摆布像是一场没有规则的赌博\n在这个舞台上红绿灯不仅仅控制着交通它更是揭示了那些被忽视的生命的轻重。如果说财富和权力可以买到生命的安全那么这场游戏的规则显然是残酷的。\n于是我们不禁要问这样的社会这样的政策这样的人生我们真的满足吗还是我们应该更加关注那些在生活的底层挣扎的人们给他们一个公平的生存机会而不是等到悲剧发生后才惊觉「原来红绿灯也是有生命的」。\n或许某天当每一个十字路口都安装了红绿灯我们才能真正说这是一个每一个生命都被尊重的社会。\n\n如果你经常翻阅我的博客会很明显发现这不是我的写作风格。 不知道老莫能不能看见哈哈哈,这是我基于「莫比乌斯」的文字通过 AI 训练出来的「赛博老莫」,借用老莫的文笔风格「爽」一下。\n但是这是真实在我身边的一件事居民区在右学校在左十字路口没有红路灯这条路又恰恰是非常重要的主干道。每天上学时间无数的学生拿着生命在这个无红绿灯的舞台上翩翩起舞。虽然我目前没有孩子但是我也尝试通过各种渠道反馈了。\n希望、也许真的在尽快落实吧"},"Personal/Blog/2024/师从-ChatGPT":{"title":"师从 ChatGPT","links":[],"tags":["成长/个人","博客/原创"],"content":"我最近遇见的很多问题处理起来感觉效率太低,总认为是因为没有熟练掌握方法论的具体应用——思维模型,才导致效率不高。所以就想系统全面地学习一下常见的思维模型。可是却又无从下手,毕竟思维模型实在是太多了。遂去问了问 ChatGPT但又感觉 ChatGPT 的答案总是没有灵魂,似是非是的回答让我头大。然后几乎每天都在带着这个问题思考,不过也是功夫不负有心人。最终串联起来许多在书中读到的内容,并且进一步领悟到了最核心的点在于——元认知。\n我第一次学习了解到元认知是在《认知觉醒》中当时只觉得这只是一种方法论。但是又回过头来再次复读现在我说实话能理解作者想表达的意思但是其文字对于我来说增加了理解成本。或者当初的我只停留在感性认识并且没有去实践可我感觉这又很难去实践。就好像只有恶龙诞生了人们才会锻造出屠龙宝刀。但如果一开始没有恶龙那么它就是一把普普通通的剑。\n如果想认识元认知首先要理解认知是什么认知是人们获得知识或应用知识的过程认知的对象是外在的具体的。认知是感性认识转换理性认识的过程并尝试通过不断的实践总结、迭代优化最终尝试达到知行合一的境界。\n例如当你第一次尝试骑自行车可能会在父母的帮助下保持平衡并尝试踩踏板来前进。如果父母放开手你可能会跌倒几次并开始思考为什么会失去平衡是否是因为速度太慢或转向太急可能你也会观察其他小朋友如何骑车并尝试调整自己的速度和转向方式学习如何更好地保持平衡。\n当你学会骑自行车后可能就会有朋友来向你请教。你就会根据自己的经验教导他们如何调整速度并保持平衡。在教导他人的过程中你可能会发现自己之前没注意到的技巧或细节从而进一步改善自己的骑行技术。\n一开始对自行车的两个轮如何保持平衡如何运动。你会形成直观的感性印象。这一阶段的认识是具体的、零散的只能把握事物的外部特征和表面现象。期间通过实践进一步将感性材料加以整理、抽象形成概念、判断和推理从而揭示事物的内部联系、本质特征和规律性。这一阶段的认识是抽象的、系统的能够深入到事物的本质。\n认知过程是由感性认识开始通过实践再收获理性认识最后又回到实践中去的迭代过程。在这一过程中实践活动会不断产生新的感性认识并通过加工不断收获新的理性认知并再应用于实践。认知在这一过程中不断被纠正和发展从而使认知逐步深化逐渐接近于客观事物的真实状态。\n而元认知相较于认知则是内在的抽象的是基于我们自身的认知活动是关于自己认知过程的认知是我们如何认知这个世界并进一步抽象所来的事物。元认知就像学习骑自行车的过程一样是一个持续反思和调整的过程。在这个过程中我们不仅要关注行动的直接结果还要持续监控和调整自己的认知策略和方法。\n所以元认知关键涉及自我监控和自我调节两大能力。\n自我监控是指在认知活动中对自己的理解、注意力、记忆等进行监督和评估。例如当你阅读新的文章时你可能会不时地停下来回顾自己理解的内容检查是否有误解的地方。这就是一种元认知监控的具体体现。\n自我调节则是指在认知过程中根据自我监控的结果来调整自己的学习行为。如果你在阅读过程中发现某些概念理解得不够深入可能就会选择重新阅读相关段落或者寻找更多资源来加深理解。这种能力不仅有助于提高学习效率也使得学习过程更加适应个人的需求。\n如果在实践中发展元认知能力首先需要培养对自己认知过程的意识。这可以通过日常的反思练习开始比如每天结束时回顾一下自己的学习和工作思考哪些方法有效哪些需要改进此外可以尝试在做决策时有意识地思考自己的认知过程评估自己的思维是否合逻辑是否受到了情绪的影响想必通过这些方法你就可以开始慢慢地培养出对自己认知过程的敏感度并逐渐提高元认知能力。高水平的元认知能力会让你在面对充满挑战性的情境时能更加自如地调整策略以达到最佳的认知和学习效果。\n我认为如果能充分理解提高运用元认知能力那么认知的成长将不再是 1+1 的积累,而是指数级的倍增。这种能力就像是锻造了一把屠龙宝刀,使你能够更有效地面对生活和工作中的各种挑战。\n而方法论则是作为认知过程的宏观指导它提供了一套全面的框架和步骤帮助我们如何进行科学的思考和研究方法方法论是提高认识水平、解决实际问题能力的重要工具。方法论涉及的不仅是科学研究方法还包括思维方法、工作方法等。而思维模型则更多作为认知过程的具体参考通过具体的模型帮助我们理解复杂现象或问题并为决策提供理论支持。\n通俗来说方法论就像是开车时候的地图导航帮助我们规划出最优路线而思维模型则相当于在这条路线上指导我们如何选择两点间的最短或最快路径。就像在开车时如果面对磨磨唧唧的车流我们就会根据各种实际因素来决定如何快速地超车。\n就拿张雪峰老师作为具体的例子来说张雪峰老师拥有非常丰富的中国教育考试知识和海量的实践经验。但如果你说我要从 0 开始研究中国教育考试,最终达到张雪峰老师的水平也不是没有可能。可这个水平需要你大量的学习,实践,总结,再实践,迭代无数版本后才可能有机会达到。\n正是因为张雪峰老师在中国教育考试方面的认知大部分家长就会找到张雪峰老师咨询如何规划孩子的大学志愿毕竟家长在中国教育考试的认知不如张雪峰老师。可虽然张老师会针对具体问题提出了合理的建议但大部分家长可能仍然揣着「旧」想法半信半疑并依旧会走弯路那是为什么\n因为张雪峰老师的方法论和思维模型属于「黑盒理论」我们无法透过表象深入理解本质故此你可能就会持怀疑态度。毕竟实践才是检验真理的唯一标准。可高考只有一次如果你检测成功了皆大欢喜检测失败了那就自己承担。\n\n不过题外话我认为张雪峰老师还是属于拿钱办事的。例如有个高考状元 700+ 分的人。他也是不会给出太具体的建议,但不过大部分普通水平,反倒是会给出非常中肯的建议。\n\n对于方法论及思维模型我的一点心得无论是自上而下还是自下而上的学习和实践都是需要耗费不少的精力来内化的请务必坚信「能量守恒定律」。 而且我认为高效的路径是在某一专业领域深入研究,达到一定高度并且拥有一定造诣之后,在新的领域尝试从头再来,那么定会融会贯通!\n最后回到《师从 ChatGPT》这个标题之所以我选择这个标题是因为过去一年多长时间与 ChatGPT 的交流深刻改变了我的认知和思考方式。\n我认为 **AI 几乎是完美的,它永远不会受到思维定式的束缚。**并且只要你愿意教它,它可以迅速学习并适应新事物,而且 AI 认知的进化是不会受肉体的约束,毕竟我们随着年龄越来越大,很难再拥有青少年时期的学习精力。但是 AI 却不会,它可以通过不断地优化升级模型,并拥有几乎无限的学习精力。\n我对于元认知的部分理解也是源于 ChatGPT因为非常多具体的问题如果你直接把问题丢给它它回答得也并不出色。于是我开始各种尝试各种 Prompt但是又发现 Prompt 虽各有不同,但还都是那几句套话。因此,我开始尝试构思更加深入的 Prompt。例如在探讨特定问题时我会先定义问题的范围让 AI 先行解释其相关领域,再深入到该领域专家应具备什么样的知识,最终通过精心设计的对话,使 AI 能够在新的语境中发挥其最大的潜力。\n目前主流的 AI 都是基于神经网络——一种受人脑启发的计算模型,其可以通过海量数据的喂养,调整神经单元突触的权重,进而从复杂的、高维的原始数据构成向低维度的投影,便于我们更容易去理解,有点类似于手指投影。不过,纵使目前 AI 再厉害,或者未来的 AGI 发布,我对于其是否可以拥有情感持怀疑态度。虽然我们的大脑与 AI 本质都是建模,可我们却拥有了无法解释来源的意识、情感、创造力。\n可成也情感败也情感。我们充斥着七情六欲时常被情感控制。而 AI 却可以不被情感左右,针对问题可以不被干扰并尝试做出最优解。\n自从去年 AI 的横空出世,让我们高估了其短期内的影响。不过到现在逐渐被普遍接受,从而又让我们低估其长远带来的变革。我坚定认为 AI 不再仅仅是提升生产力的一个工具,更是内化知识、拓宽认知边界的「导师」。\n我非常、非常建议每个人都应该学会接纳变化拥抱 AI师从 ChatGPT\n\n依旧是写了很久也不多两周时间写的我脑仁疼…… 🤯🤯🤯\n《富人的红灯与穷人的绿灯》是这篇文章的药引子说实话当我通过「赛博莫比乌斯」输入想表达的主题。AI 一行一行的输出内容,那「真的」就是莫比乌斯!\n虽然也尝试了各种奇奇怪怪的姿势体验 ChatGPT 的功能,例如部署未审查版本 AI 尝试写色情小说等哈哈哈。但是这次元认知能力的提升也让我也更深入理解想要什么AI 缺什么?怎么通过 AI 拿到想要的答案?\n现在不要再单纯觉得 AI 呆瓜了,其实神经网络模型理论上可以模拟输出任意问题的结果,只是目前的 AI 在用我们可以理解的方式进行沟通。我不是宣扬 AI 可以创造一切,以及未来 AI 毁灭世界的信徒。只是通过 AI 更进一步的拓宽了认知的边界,拿到了我想要的答案。\n至于未来如何那就该吃吃该喝喝明天去做桌哈哈满月酒的家乡话。\n\n\n下图是创作过程中的文章草稿也是本文的思维逻辑导图。基于 Obsidian 的原生插件——白板实现,原始文件可以在 github 主页 wiki 仓库下 Canvas 目录找到哈 \n\n"},"Personal/Blog/2024/我又从-Ubunut-换成了-Fedora":{"title":"我又从 Ubunut 换成了 Fedora","links":[],"tags":["博客/原创","Linux/安装"],"content":"去年我从 Windows 换到了 Linux并选择了新手友好发行版——Ubuntu并介绍了一些关于 Linux 桌面使用中的坑和解决方法。尽管现在我仍更推荐使用 MacOS或 Windows但既然你点开了这篇文章那就坚定地接受 Linux 的缺点吧哈哈哈。\n至于为什么我又从 Ubuntu 换成了 Fedora纯粹是为了学习。期间除了 OpenBSD 没尝试过,基本上都试过一遍了。我也不是在虚拟机里尝试,直接就是主力机刷哈哈哈。另外,基于《数字文具盒》系列的工具打造,我现在所有的工作几乎都基于 Web 形式进行。所以即使随便折腾一下,也不会影响太多,纯粹只是花费一些时间而已。\n不过还是有一些问题想分享一下。可以结合《电脑坏了我换了Ubuntu》作为上篇这篇文章作为下篇相信对于你选择 Linux 桌面会有一定的帮助和解惑。\n关于硬件和驱动\n我其实非常希望有一种专门适配 Linux 的硬件,最好像 MacOS 一样。虽然现在确实有一些,比如 Pop!_OS但感觉比较小众而且需要海购。\n总之我不建议购买新硬件来刷 Linux很可能会遇到各种奇奇怪怪的问题。一般来说越老的硬件越稳定但也不要太老旧。同时尽量选择一些商业发行版本提高稳定性减少折腾。\n关于系统更新\nUbuntu 经常弹出提示用户更新,开机就会弹出更新窗口,看来它也喜欢把用户当小白鼠,而 Fedora 则完全是手动更新。\n关于桌面系统\n至于具体的桌面环境喜欢哪个就用哪个。但是我强烈建议只使用 Wayland 显示服务器协议,我在 Ubuntu 上使用的是 X11容易出现各种奇奇怪怪的窗口问题。\n\nWayland 是为了克服 X11 的缺点而设计的一个现代化的显示服务器协议。它旨在提供更简洁、更高效和更可靠的窗口管理和渲染方式,特别是在直接渲染视频内容和图形应用程序方面。\n\n关于桌面软件应用\n我建议使用 Flathub听我一句劝别折腾乱七八糟的 Wine 了,有那时间装个 Remmina 直接远程吧,铁铁,我爱说实话。不过也可以使用 AppImage但需要自己创建桌面图标。没有 Flathub 那么傻瓜式方便快捷~\n\nFlathub 是一个开源的应用程序分发平台,旨在为 Linux 操作系统提供简便的软件安装和更新方式。它基于 Flatpak 技术Flatpak 是一种容器化的应用程序打包和分发格式,可以在不同的 Linux 发行版上运行。\n\n关于游戏\n我几乎不玩游戏纵使装了 Steam 也没怎么尝试过……\n关于 Fedora\n\nLinus Torvalds 代言,你值得一试。\n\n作为主力机使用了快一年的 Linux我认为 Linux 相较于 Windows 和 MacOS 最大的优势在于原生的 shell。基于此我也更加理解为什么 Windows 开发了 WSL因为其他任何地方 Linux 总会有让你不舒服的地方。\n还有不要再说 Ubuntu 是最适合新手入门的 Linux 发行版本了,尽情拥抱 Fedora拥抱现代化。对于安装完 Fedora 后,我推荐以下几件事:\n\n更新 DNF 源:可以手动更换各大镜像源,或者使用 LinuxMirrors 一键更换,然后更新系统和应用程序软件包。\n基于 Flathub 安装应用Fedora 39 默认预装了 Flatpak搜索并安装你常用的软件吧。\n安装 zsh 终端:手动安装 zsh 和 oh-my-zsh然后配置一些常用的插件。开始享受 Linux 下 Shell 带来的快感吧~\n简单地调整一下你的桌面环境然后就可以开始工作了\n\n\n我没有提供具体的操作步骤因为互联网上已经有很多相关文章了就不重复造轮子了。\n"},"Personal/Blog/2024/我的一天":{"title":"我的一天","links":[],"tags":["博客/原创","生活/日记"],"content":"[7:00 am] 睡醒,迷迷瞪瞪地洗漱完。\n[7:30 am] 可能会尝试稀奇古怪的早饭,出门前会一直听书。\n[8:00 am] 出门上班,大约 20 分钟到公司。\n[8:30 am] 来到工位,开始浏览 RSS、X、Telegram、Youtube 等了解世界发生了什么。\n[9:30 am] 阅读结束,活动一下泡壶茶,顺带所里办个事。💩\n[10:00 am] 回到工位,看看有没有工作需要处理。\n[10:30 am] 利用 NextCloud 简单规划一下今日任务,随后开始刻意练习。\n[11:30 am] 第一个番茄钟结束,活动一下伸个腰。\n[12:30 pm] 第二个番茄钟提前 10 分钟结束,准备下班吃饭。\n[1:00 pm] 吃完饭后回办公室,休息一会,或者看书,娱乐一下。\n[2:00 pm] 伸个懒腰,泡壶新茶,准备开始下午的工作学习。\n[3:00 pm] 第三个番茄钟结束,起来走动走动放松一下。\n[4:00 pm] 第四个番茄钟结束,继续起来走动走动放松一下。\n[4:30 pm] 视情况,可能会出去跑步运动一下。\n[5:00 pm] 评估一下工作量,并考虑是否停止开始新的任务。\n[6:00 pm] 第五个番茄钟结束。跑路走人,下班干饭。\n[7:00 pm] 到家后,简单运动一下或者玩手机聊天。\n[8:00 pm] 运动后,泡个脚或者玩电脑,同时再简单工作一会。\n[9:00 pm] 开始洗漱,然后躺床看书。\n[10:30 pm] 通常这个时候就困了,准备睡觉。\n[11:30 pm] 大多数时候,我在这个时间已经睡着了。晚安 "},"Personal/Blog/2024/打工三年记":{"title":"打工三年记","links":[],"tags":["博客/原创","工作/经验","成长/个人"],"content":"不知不觉在九州通工作三年,捎带收获了一份纪念品哈哈。简单介绍一下九州通,九州通医药集团股份有限公司是一家以西药、中药和医疗器械批发、物流配送、零售连锁以及电子商务为核心业务的大型股份制企业。\n省级公司不如集团总部个人负责的真是又多又杂。我在省级公司信息部门作为基层员工前期负责核心业务系统的数据维护、数据分析及技术支持偏平台服务和应用服务。后内部主动转岗负责本地数据中心的管理及运维偏基础服务和平台服务。\n记录一段人生旅程分享一些个人收获和心得 \n\n学会认清时代和周期\n\n站在风口上猪都会飞。──雷军\n\n现实生活中打工往往是 80% 的人第一选择。而对于选择正确的行业和企业尤为重要,可千万别干那 49 年入国军的事。\n毕竟在村里你可能听不见罗马的钟声但在罗马钟声无处不在。曾经互联网 Android 应用开发火爆,不也笑谈理发师培训短短三个月也能月入过万么?\n在 2022 年疫情即将结束时,我们一个下属子公司预计全年亏损 XXX 万,而最后一个月,业务根据市场需求推出一款组合销售产品包,一个月内狂赚 XXX 万,直接扭亏为盈。该板块员工月薪至少翻了三倍,年终奖也翻了一番。\n他们也没有做出什么特殊的改变只是出卖自己的时间打包药品。不知道各位还记不记得疫情时候的核酸检测小屋正是这个产品让对应的下属子公司在第二季度就直接完成了全年的销售业绩真是纯纯躺赢。\n再比如中美贸易战的影响结合市场需求不足产能过剩的背景下。许多企业纷纷响应政府号召搞提质增效和数字化转型。我们集团新来的 CTO 年薪据说 500 万 +。如果你处在数字化相关行业或领域,这无疑也是一次职业发展的上升周期。\n至于如何学会认清时代老实说我也没能力认清但我想表达有时候如果在公司个人能力不错但就是感觉个人价值没有兑现。千万不要总怀疑是自己的问题。\n树挪死人挪活选择往往大于努力\n\n永远选择追求利益\n打工人应当永远选择追求利益这既是一种「道」。 可谓,道生一,一生二,二生三,三生万物。\n企业无论是做产品、还是做业务的如果没有遵循追求利益的基本原则反而违背这个原则那么一定另有所求然而我发现企业通常会在追求利益的原则上演绎出任何选择但是打工人却往往会找各种理由放弃自己的利益。\n2022 年底疫情刚刚放开后,大家疯狂抢购各种药品。当时因为无法从外部找来足够兼职工,药品积压仓库无法发货。企管部便通过各种方式号召「家人们」支援,并口头承诺给予双倍工资,第一批排上队支援的「家人们」确实收到了双倍工资的现金支付。\n于是「家人们」蜂拥而上仓库支援人员络绎不绝但过了一周后企管部以员工考勤表缺失和工作量不够为由表示需要重新考核后所谓双倍工资也不了了之。可是竟然有「家人」表示支援的初心是为了服务客户为了实现公司的使命价值观可能他们也在追求某种形式的利益。诋毁某些「家人」仅仅只是为了工资才去的格局太小。\n最经典的就是一次领导层会议讨论是否应该放开公司的封禁。一位领导直言放开 TM 的放开放开了我的业务奖谁来给当时社会面都放开了但领导层为了追求年底目标奖励的达成担心「家人们」都会感冒发烧影响业绩所以迟迟不肯放开公司提供基本的食宿80% 的人都住在公司)。\n但仅仅几天后「家人们」就都开始感冒发烧……\n企管部又出来再次号召「家人们」带病上岗并承诺发放现金奖励。但离谱到哪怕是差 0.1°C 都没有现金奖励。回头再看看公司的 KPI 考核,你觉得 KPI 是为了让你完成,还是为了让你完不成?\n最后我也不是在挑拨打工人和公司之间的对立而是希望如果作为打工人不要吃大饼应切记永远选择追求利益。\n\n利益是维护感情的法宝\n现实生活中大部分人都认为同事之间没有感情其实社会上大多数成年人之间也都少有真挚的感情。当然也不能全盘否认毕竟「君子之交淡如水」。\n其实这里我写了好多不过最后还是选择删掉哈哈。只要记住「利益是维护感情的法宝」就好。🫤🫤🫤\n\n千万不要盲目地站队\n哪怕一把手也是打工人如果关系不硬干得不好同样也是得麻溜滚蛋。\n在我们新来的一把手上任后几乎换了业务部门的领导随后就是领导嫡系的大量离职。你说他们真的是能力不够更多的是一朝天子一朝臣罢了\n假设你是新来的一把手你会选择继续任用上任领导的部下吗除非他们无法替代否则这几乎不可能。 基层员工可能认为与我无关,除非你甘愿永远只做一名大头兵,否则想得实在是太简单了!\n因为如果你不「站队」那么意味着你连餐桌都上不了\n职场攻略都是在分享如何讨好领导、处理同事关系的技巧但这些方法并不总是具有可复制性只需要深刻理解其背后的底层逻辑就行。\n无论何时你都应该首先与公司的利益深度绑定再与具体的人利益绑定最后的最后再决定站队。\n实际上 大部分领导层的利益都是和公司深度绑定的,那么你只剩下和具体的人利益绑定就行。但最好不要只绑定一个,但也不要傻乎乎的脚踩两只船……\n不要总是想着「添」领导舔狗舔到最后不一定应有尽有。例如直属领导总想搞一些偷鸡摸狗的事情而你作为最忠诚的下属最后一定会死得最惨。\n在进行利益交换时一定要学会使用杠杆而不是老老实实存定期。\n因为在沙漠中的一瓶水可能值千金而在音乐会上的水也能值几十元但在小卖铺里面它仅仅值几块钱……\n\n一定要学会优雅的犯错\n我逐渐认识到学会犯错其实是一件非常优雅的事情因为可以帮我们换取非常多有价值的信息。\n在工作中当你开始尝试独当一面的时候最好选择一个恰当的时机来「优雅地犯错」。这样的错误可以帮你深入了解团队的文化内核让你感受团队对于利益的真实态度。\n通过这样可以帮你更好地调整自己的行为和策略一方面更好地融入团队一方面更好地「下刀子」但是务必要确保犯一场「优雅」的错误。\n在我工作初期我与同事之间并没有直接的利益冲突关系也非常融洽感觉彼此非常投机。当我开始独当一面并创造价值的时候大家也都表示支持新人鼓励我大胆尝试放开手脚去做。可当我再进一步创造价值并且还收获集团嘉奖的时候。开始有人阴阳怪气风向明显变了……\n此时我才意识到。一方面我并没有和领导利益深度绑定所创造的价值显著但也并不像业务部门那样直接产生可以量化的经济价值。对于利益有冲突的同事他们毕竟是领导的多年部下不可能为了支持我放弃已有的利益。而那些与我利益不冲突的同事则选择置身事外与我无关。\n至此我才真正地理解了部门的文化内核和每个人的利益点。\n\n如果挨打请立正\n在工作中犯错是难免的毕竟「人非圣贤孰能无过」。可当发生的错误可能影响到职业生涯时面临的选择往往是要么忍要么离开。\n自证是伟大的命题「千万不要证明肚子里有几碗粉」。毕竟这世上欲加之罪何患无辞\n如果选择忍那么挨打请立正 但是,必须要学会背有价值的黑锅,这也是一种高效利用杠杆撬动利益的方式。\n作为 ENTJ-A 的一员,我个人的工作操守和职业素养一直都是在线的。过去三年中,主观上我没有犯过严重的错,客观上也仅有一些微不足道的错误。\n\n虽然我也没挨过打但是我真的很想暴揍那群猪\n\n\n能力不是最重要的\n\n尝试用公式而不是文字来解释「能力不是最重要的」是不是非常完美\n我最初也是认为「能力至关重要」甚至不可替代。然而随着时间的推移我逐渐意识到能力只是影响成就的众多因素之一。总的来说一个人要想取得不俗的成就首先需要的是合适的平台适合的机会以及足够的能力。\n当机会过大而能力不足会极其危险因为系数为负会放大失败的影响同时平台也并不是越大越好如果平台过于大而导致系数小于 1往往会适得其反阻碍利用资源实现倍数增长至于人脉我们不总是常说「世常有千里马而不常有伯乐」可遇不可求 \n而且在实际工作生活中我们常常还过度相信努力可以一直带来倍增但事实上人越努力就会越「平庸」。\n因为最初的努力可能会让你快速摆脱平庸但毕竟人外有人天外有天当你是聪明人那么就注定会遇见更多的聪明人最终当你再也无法前进时可能就成为了这个圈子中的平庸之人。\n\n有两把刷子到哪都能混口饭吃\n假设一个男生从 20 多岁开始工作,目前的法定退休年龄是 60 岁,意味着至少要工作 35 年,而且这还不考虑未来可能会推迟退休年龄的情况。那么在国内,我想很少有人能在一家公司一直工作到退休……\n尤其是 IT 行业所谓的「35 岁魔咒」和「退休危机」,让我们不得不思考如何混口饭吃 。不过 IT 行业喜欢搞副业的特别多,许多人在获得一些成果后,会将副业转换成主业,尝试做大做强、再创辉煌。\n但我的感悟是在第一曲线尚未衰退之前就应该开始布局第二曲线确保未来持续的增长并适应不断变化的环境。虽然我的第一曲线目前还未达到想要的高度第二曲线也还没窜出地平线但是我还年轻年轻就是资本哈哈哈 \n目前我的第二曲线方向是摄影师或者 Vloger。\n摄影我倒是一直在学习和实践但是还没有系统化的整理知识还处于摸索阶段的末尾至于 Vloger 还没有开始,主要是我觉得现在的功利心比较重,还是要有一些热爱,才能支撑我走得更远。\n说不定未来哪天找到了热爱我就开始 Vloger 了 \n\n开心工作快乐生活\n最后这条对于工作的建议我反复想了很久。从一开始的《要么忍、要么滚》再到《健康自由 > 时间自由 > 财务自由》,最终还是选择借用冴羽在《怎么平衡工作与生活?》中的一句话作为标题。\n一直在纠结的原因是每个人对于工作的理解和定义是完全不同的而且发展方向也是难以预测的。\n例如我村里的一位邻居从未上过学年龄也大了只能打扫一些卫生。尽管如此也总是笑呵呵的觉得能有个工作就非常不错了。当代中年人也许因为生活的挑战而任劳任怨希望可以一直稳定工作到退休。而 00 后的年轻人,他们喜欢追求公平正义,就开始尝试如何整顿职场。\n毕竟人生无处不围城。你所厌恶的对他人可能是宝贵的机会你所珍视的对他人也许毫无意义。\n而我就希望你们在哪里都可以「尿尿和泥」开心工作、快乐生活 \n"},"Personal/Blog/2024/新奇的-HR-经历":{"title":"新奇的 HR 经历","links":[],"tags":["博客/原创","工作/面试"],"content":"前段时间,好友让我在招聘软件上帮他找几个财务方面的人员,主要涉及财务助理和财务经理两个岗位。虽然从没有担任过面试官,但我恰巧阅读了一些与人力资源相关的书籍,遂想尝试尝试体验一下。\n一开始我借助 ChatGPT 快速学习了解面试的基本流程,并且一起制定了精简的招聘方案。主要是涉及岗位职责,面试题目,薪资待遇。然后我在网上下载了一些常见的招聘软件,就开始 GoGoGo 了。\n开始前两天我尝试有针对性地邀请一些面试者进行沟通交流如院校背景、从业经验、薪资期望过滤。但整体效果不佳没有获得任何面试机会。不禁感叹大家都说找工作难实际应聘一名合格的员工更是难上加难。后来我想着三个臭皮还顶一个诸葛亮呢转而采取了海投的方式除了设置一些基本的过滤选项然后向所有符合要求的人发出招呼。\n然后求职者就哗哗哗纷至沓来。前后我沟通了 500+ 求职者,深入沟通了解 50 个左右,确定面试的有 10+。果然还是基数上来了,比例就不是问题。\n分享我遇到的一些问题\n关于招聘软件的筛选\n我只能说比你上大学报考志愿筛选的都细致什么 985,211双一流都能筛指定学校都可以就不说工作年限薪资待遇了。前两天我筛选得很细致但是效果不佳。后来我就设置了基础的过滤并且点进去看看然后打招呼。社会化招聘敲门砖真的很重要。\n关于求职者的学历\n因为我是在郑州招聘所以遇到最好的就是省内的郑大河大财大等这些。但就我感觉来说这些求职者无论是大专也好本科也罢。特别是刚毕业的一两年工作经验的求职者并不存在天上地下的差距。这个观点也许有些片面毕竟没有遇到清华北大985 的。\n我认为的是大部分刚毕业的年轻人不存在质的差距但是教育资源倾斜的体现尤其明显。毕竟有时候顶着一个好的头衔也有可能迎来一句名校毕业的就这水平么\n至于为什么说教育资源的倾斜尤其明显呢主要是从简历质量方面一眼就看得出来对比起来完全就是正规厂家和手工作坊的差距但实际沟通体现出来的能力倒是大差不差。\n关于求职者的简历\n我浏览了 500+ 求职者,详细看得不多。主要是从三个方面:自我介绍,简历关键字,工作经验来匹配。\n有些人自我介绍写的你都怀疑 TA 是说相声的。比如上地能种菜,下海能摸鱼;还有的写能吃苦,能干活的,还有的就写个专业名字的;这些离谱的不仅仅有刚毕业的,工作三五年的也有!\n说实话自我介绍是最直接的态度体现良好的开头能影响最终的走势。并且招聘一名员工也不是让 TA 来坐牛作马,吃苦受累的,本质上是一种互相成就的行为。也有些就写得很不错,既表达了态度,也体现了思维逻辑能力,并且展示了个人优点。\n还有就是简历关键字有时候 HR 并不理解岗位需求中的专业技能,至少我是这样认为的。很多时候求职者需要了解现代化企业,以及岗位描述的具体关键字,就是炒作业都行。岗位关键字一定要匹配,就比如要招聘一个 Java 开发工程师,那么 Java 开发工程师中高频率出现的关键字一定要有。但是关键字太多也不好,增加面试难度,整体保持岗位关键字匹配度的 60% - 80% 就行。\n最后还有就是工作经验和学历一样重要。学历敲门工作经验迈步两者缺一不可。世界 500 强与家喻户晓的大公司和名校头衔带来的价值几乎相同。\n关于求职者的能力\n其实找工作面试求职招聘真的就和相亲一模一样。优秀者是不流通的即使优秀者流通出来也会很快找到新的工作。求职者实际大多都是高不成低不就的。\n例如有能力的高手薪资要价太高中小公司根本接不住。况且有能力的人后期也根本留不住他想走你又能怎么办对于零基础的小白你又不愿意倾斜太多资源培养培养完跑了又是血亏。最好的就是中等水平彼此能够互相成就的最好。\n而且求职者最好满足岗位基本需求还能突出自己的差异点。毕竟一个岗位会有多个求职者还是得全靠同行衬托。\n关于求职者的沟通\n其中还有一个很蛋疼的问题就是有些求职者可能是海投吧。但是开场白就是双休么缴五险一金么工作时间我倒是觉得有点不认同毕竟现在会有哪家企业会把刀架在脖子上逼着你每天工作 16 小时么?并且还不给你发工资?\n而且薪资待遇的博弈需要的是双方平等的地位才有可能谈妥。一开始求职者甚至连乙方都不算你需要做的是加大自身筹码直至坐上谈判桌甚至成为甲方再开始讨论薪资待遇。开始只需要简单的开场白并且礼貌介绍一下自己并发送个人详细简历就好了其他的无须多言。\n如果后续能利用面试充分展示个人能力吓到 HR什么薪资待遇不都是手拿把掐你要明白 HR 也是打工人,也有绩效考核,完不成任务更是可怜巴巴。而且经过这几轮面试,大部分公司也付出了一定的成本,更不愿意放手优秀的人才。\n面试流程\n\n我利用 ChatGPT 制定了针对财务经理、财务助理面试题目,旨在全面考察求职者的综合素质、理论知识、行业经验以及项目管理能力。\n线上初试环节我会重点核查简历中的从业经验和项目经历并评估其职业发展规划的明确性。此外我还会提出一些实际操作问题例如对现代财务管理软件的熟悉程度以此来考察应聘者的实际操作能力。并通过深入探讨其项目经验和处理特定场景的方法进而评估求职者的逻辑思维和问题解决能力。\n回想我刚毕业时的面试经历当时我对 HR 提出的关于职业规划、家庭状况等问题感到不解认为走形式主义。后来我明白HR 在面试中询问这些问题是有其逻辑的,目的是通过你的回答来进一步了解你。然而,由于这些问题很主观,没有标准答案,应对时需要根据实际情况灵活应变。\n例如谈到职业规划实际上很难有一个确切的答案因为未来充满不确定性。一份所谓的“科学”和“完整”的职业规划实质上可能是不切实际的。目前在我看来职业规划的讨论更多是关于求职者对职位的理解而询问家庭情况则可以间接了解一个人的成长背景。\n面对多数 HR我建议采取废话文学应对一种既表达了观点又留有余地的策略让回答既全面又模糊以便根据情况作出调整。然而面对一些经验丰富的 HR坦率真诚地展示自己的个性可能是更好的选择。灵活应对因人而异是关键。\n在面试财务经理的过程中由于我对财务专业知识的了解有限只能说通过场景模拟和思维逻辑能力的考察。并结合科大讯飞的语音转文字和 ChatGPT 的深度分析,然后通过主观的分数来量化,就能够全面评价应聘者的能力。线下复试则是多人面试,通过具体的场景和问题来深入评估求职者的综合能力。\n成功通过初试和复试之后薪资待遇的谈判就成了与 HR 的一场博弈。在这个阶段,建议从公司的角度出发,考虑不同发展阶段和成熟度的公司对人才的需求差异。对于大型成熟企业,博弈空间可能较小;而对于正处于快速成长阶段的中型企业,则可能有更大的谈判空间。博弈的关键在于理解双方的实力和底线,但建议不要过分斤斤计较。\n此外我深刻体会到立场往往影响着我们的思考和判断往往是屁股决定脑袋。当我处于求职者的时候常常会想打工人何必难为打工人然而当我体验 HR 的时候,我发现自己又会在可控的范围追求最优解。\n罢了罢了哈哈哈 "},"Personal/Blog/2024/穷则独善其身,达则兼济天下":{"title":"穷则独善其身,达则兼济天下","links":[],"tags":["博客/原创","成长/个人"],"content":"每个人成长的路上都曾铺满过梦想,或成为探索宇宙的宇航员,或成为传授智慧的老师,或许还有那些伟大的科学家。这些年幼时的梦想,是我们最初对人生意义的探索。\n从小我就好奇学习究竟是为了什么好好学习天天向上成为了每个大人的口头禅可是身边的大人一个个也都没有上过所谓的大学。可是在成长的路上老师和家长们的期望像接力棒一样递给了我——先是一个好高中然后是一个好大学仿佛只要踏入那扇门人生就有了意义更会一帆风顺。\n后来我开始更深入地追问自己人生的意义究竟是什么我也曾极度渴望活得有价值但生活中总有些让人困惑和迷茫的时刻它们不断地挑战着我的信念。我也不断在追寻中徘徊可是未来却似乎总是遥不可及这不禁让我陷入了深深的内耗。\n当踏出校门的那一刻我以为自己终于可以摆脱学习的枷锁。然而社会的压力又如影随形——好好工作结婚生子仿佛人生的每个阶段都被预设了一条必须要走的路。但在我的心中有一个声音在反问这个世界这么大难道我就不能有自己的选择吗\n于是我曾长时间沉浸在对自由的崇尚中。然而精神上的自由和物质是紧密相连的想要达到三分超脱七分入世的境界实非易事。毕竟我们每个人一出生就背负着原罪在这复杂的世界中漂泊如情绪的寄生体般漫无目的地游走。\n可生活中又不断有朋友步入婚姻成为父母而有些朋友则在不经意间离我远去。二十多年的友情转眼间似乎只剩下回忆。在这样的生活中我甚至不知道下一步该做些什么……\n在无数次的深夜思考之后我明白了人生本就没有任何的意义真正的意义和价值都是我们在不断探索和创造中寻得的。也许人生最美好的状态就是永远在路上不断寻求新的风景。\n现在我将人生的意义寄托于积极的入世态度。努力工作赚钱提升物质生活条件这是我为自己设定的短期目标。与此同时不断地学习和成长接纳新鲜事物抛弃不再适合的旧观念并且学会享受生活的每一分每一秒。活在当下着眼于未来。同时进一步改善家人的生活条件温暖他们的精神世界让他们感受到我的爱。\n未来我也希望自己的能力能百尺竿头更进一步不仅仅为自己和家人带来更好的生活也能帮助身边的人让他们感受到幸福。也许每个人的提升和快乐都能成为这个世界变得更美好的一部分。这就是我现在对人生的理解也是我前行路上的动力和目标。\n希望未来平静且自由地度过这一生。\n新年快乐 "},"Personal/Blog/2024/继续开荒我那一亩三分地":{"title":"继续开荒我那一亩三分地","links":[],"tags":["博客/原创"],"content":"家里的梨树园长期闲置导致杂草重生,在 2022 年初经过开荒种下了一些瓜果蔬菜,最后因为疫情原因,还有无法浇水导致停摆了。\n关于浇水我是真 TMD 的无语,那个浇地的机井需要刷卡才可以开机。当时负责人说暂时没有卡了,需要等一段时间,\n然后我就借用村里人的卡然后冲了 50 元,寻思下次继续用(每次大概 5-10 元)。结果,第二次不让用了,导致瓜果蔬菜差点死完,最后还是我开着小三轮一车一车地拉水,搞了整整一下午……\n借我卡的那个糟老头子年轻的时候逼死妻子后来村里拆迁又找了二老婆三老婆直至把钱全部败光。最后在地里盖了个简易房独自居住结果又出了车祸目前只剩半条命吊着了。\n我知道这个人名声不好想想几十块钱也不至于还是年轻……\n\n历史文章\n\n\n\n一线城市拥有一亩三分地是什么体验\n\n\n种下了一些瓜果蔬菜\n\n\n番茄开花啦 ~\n\n\n这一次的契机是大伯年龄大找不到合适工作了闲着也是闲着就雇人把梨树园所有的树都伐了。\n不过现在还需要挖树根但疫情不存在了同时浇水的问题也解决了。就想着再尝试尝试哪怕最后没有收获也权当锻炼了。\n目前的具体情况如下图\n\n蓝色简易生产房当初存放农具的。\n黄色计划平整的地方。\n绿色已经平整并且种上了花生。\n浅黄色当初 2022 年已经平整过的。\n白虚线梨园大概 4.5 市亩 = 3000 平方 = 0.3 公顷\n\n\n大伯预计明年会把全部的地平整出来目前计划空闲的时候先去帮忙挖树根然后根据具体情况择机种一些时令蔬菜。上次种地可花不少钱而且最后的停摆真是巨大的浪费\n同时这回为了避免浪费约定每月不超过 100 元的支出。冲冲冲!\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n物品费用备注挖树根神器28 元我也不知道神不神哈哈劳保手套一包12 元"},"Personal/Blog/2024/記伍月":{"title":"記伍月","links":[],"tags":["博客/原创","成长/个人"],"content":"我一直在用 Obsidian 写子弹笔记复盘,只是最近状态比较差,直接摆烂了。不过每当状态不好,我都会来一次全面深入的复盘尝试「脉动」回来。\n这样一看平时偷的懒总归是要还回来的 \n「自己过得最爽是非常重要的」所以复盘的主题都是非常主观的自我检讨以及部分的客观认识。虽然平时也复盘但不会分享出来这次确实是需要「脉动」回来\n主要从健康、情感、家庭、事业、学习、阅读、生活、娱乐等方面尝试深入的自我剖析。再通过不断的自我心理暗示尝试通过行动做出改变让自己可以变得更爽一些 \n健康\n自我感觉目前身体处于亚健康状态大概是如下几个问题\n\n睡眠障碍主要是睡眠浅、多梦以及睡眠不足。\n运动不足运动量减少体重从 70kg → 80kg。\n换季困扰自从疫情后每次换季时都会患呼吸道疾病……\n\n我认为睡眠障碍主要因为睡眠浅、多梦、质量不高导致第二天无精打采。然后一下班就只想瘫着从而陷入恶性循环。而睡眠浅、多梦、质量不高的主要成因是思维活跃、体力剩余。因为如果某天特别忙或者充分运动了之后睡眠质量就会不错。总之就是一旦精力、体力可以得到充分的释放那么晚上的睡眠质量一定会睡得特别棒。\n不过神奇的是我没有入眠障碍只需三十秒就可以入睡……\n期间我尝试了各种睡眠策略目前比较适合的就是早睡早起同时消除各种因素影响。再就是可以泡泡脚手机勿扰模式白噪音等等。\n运动依旧是老样子继续坚持三一计划哈哈。不过下班后要是折腾一些事可能到家都七八点了。运动太晚了又容易导致延迟睡意。目前也有在考虑骑自行车上下班不过感觉还是顺其自然好了哈哈。体重其实倒也没有胖很多就是没有上学时那么苗条了多了一些肥肉保持运动就会瘦下来哈哈 \n呼吸道疾病是我最无语的一个地方\n自从新冠放开之后每次换季哪怕戴了口罩有症状马上吃药我也会断断续续难受小半个月。而且郑州每次换季的天气都是魔鬼么今天 35°C+,明天可能就最高温 20°C 了。而且几乎从来不下雨,哪怕喝再多水,空气依旧是无敌的干燥!\n我是真的……\n这几个问题总是反反复复但只要认识到问题就可以慢慢花时间修正毕竟身体是革命的本钱。未来继续坚持三一计划同时尽可能地提高睡眠质量。如果你有很好的提升睡眠质量的方法可以分享给我 \n情感\n我俩现在就是日常生活中的磕磕绊绊碎碎念那阵子很闲的时候也会拌两句嘴。不过有时我就会很不爽毕竟也不想回回都当受气包那就索性一起吵个痛快。\n特别是临近生理期被激素控制的女人狗都得绕道\n但最搞笑的就是拌嘴的时候如果她突然发现我似乎是对的就会直接哑火然后找一些奇奇怪怪的借口转移话题哈哈 \n未来的事情保持平常心顺其自然就好。\n家庭\n爷爷真的是糟老头子坏得很每年都会挑起各种事端所有人一起搞内耗。结果爷爷自己还不管事疯狂和稀泥。姥姥那边更是一团糟不过因为离得远距离产生美相比之下也就没有那么多乱七八糟的事情这里就不细讲传播负能量了……\n\n我们家目前只有我在老家所以很多事情都需要我出面来应对。\n\n爸妈也都还是老样子时代的烙印加上长久以来的惯性太大了我也不再去想着能有什么改变了。总之就是定期体检只要身体健康吃嘛嘛香其他都不是问题。\n老姐嘛马上搬新家了再加上现在我也是当舅舅的人了哈哈。以后不让姐姐过多担心大家一起开心工作快乐生活就好 \n家庭中就是各种鸡毛蒜皮的小事情不过目前我已经有了十足的韧性。未来主打一个距离产生美并尽可能地远离一些不必要的糟人烂事。\n事业\n本职工作目前依旧是不温不火加之在 JZT 我也没有太多的激情四射哈哈。依旧是趁着悠闲,多多提升自己,争取可以来到新的高度。除了本职工作,今年初还浪费了大量精力。不过,好在及时止损,避免陷入太深。\n这件事大概是这样的\n老家的远房亲戚虽然按辈分叫叔叔但实际只比我大几岁。这个创二代叔叔的公司属于民生行业十多年来从小作坊一路发展到现在年销售大几亿不过常常苦恼于如何把企业做得更上一层楼。我们也是从小认识只不过近几年联系的特别多。平时我也会力所能及地帮忙解决一些问题例如前段时间《新奇的 HR 经历》。\n企业目前主要问题就是历史诟病太多传统作坊式已经无法更好地走下去了。迫切地需要进行组织架构改革提高生产力重塑生产关系跨越作坊式阶段成为一家现代化企业。但现如今国内经过多年的改革开放我认为中小企业的 90% 的问题,最好的解决办法就是照抄成功经验。并结合自身实际情况进行调整和改进。此外,还需要一位优秀的领导者来推动改革,实现破冰。\n在叔叔的软磨硬泡下虽然我婉拒了入职的邀请但愿意协助出谋划策。因此在工作之外我花费大量时间、精力进行了深入的调研例如领导人的访谈、历史资料的整理、市场研究、同行业调查和主要矛盾分析等工作最终撰写了一份近 3 万字的企业计划书。2023 年底,我与核心领导人进行了多次沟通,并了进一步修正了计划书,最终定于 2024 年正式开始实施。\n客观来说第一季度是有成效的虽然收获不大但整体势头良好。主观来说虽然很有成就感但我真的非常疲惫主职工作外几乎所有的时间都在处理这些事情周末也都用于调研和开会。\n就是这样因为自我感觉陷入太深了所以在第二季度开始我就有意地推掉了一些会议和工作。结果没过几周便受到了各种事情的冲击同时加上历史诟病和惯性太大第二季度竟直接陷入停滞大家一起摆烂了……\n不过这次经历我是挺有收获的毕竟作为一个打工人第一次可以站在这样的高度去思考、看待和处理企业的问题。但具体来说我并没有取得显著成绩还受到了许多不理解加上又损失大量时间和精力最终我选择了止损。\n在这个改革过程中还发生了很多有意思的事情过段时间再详细讲讲哈哈。\n未来事业方面保持心态继续冲冲冲。\n学习\n目前主要是计算机科学、基础学科、兴趣爱好这三方面了计算机科学暂时就先不说了。\n现在我是深有体会到基础学科在实际生活中的广泛应用。如果熟练掌握并应用这些基础学科可以使我们在处理生活中的事情时起到事半功倍的作用。\n例如物理知识可以帮助我更轻松地理解和解决一些简单的家用电器故障化学反应原理让我可以自行制作一些简单的清洁用品地理知识在旅行时能够帮助我了解当地的地形和气候特征。再比如历史知识也非常实用能让我更好地理解一些社会现象。这些仅仅是冰山一角还有许多其他如医学、心理学、经济学等通识同样可以帮助我们更好地生活。\n我特别推荐《牛津通识读本中文版》系列这个系列涵盖了上百本不同领域的通识书籍每本书 10 万字左右,非常值得一读,读到简直就是赚到!\n兴趣爱好方面就是摄影、围棋、品茗了不过目前大多还停留在玩的程度争取钻研一下更上一层楼。兴趣爱好怎么说呢虽然可能无法量化产出但可以帮助我更好的生活毕竟玩耍的快乐也是非常赞的\n除此之外还有一个心得体会**建议每年参加一次相关的大型考试,无论是什么类型的考试都可以。**一方面避免陷入自嗨型学习,一方面更好地保持专注力。毕竟现在的你,还能坐在那一动不动的答题 3 小时么?\n《师从 ChatGPT》帮我构建了高效的元认知并重塑了认知过程以至于学习效率飙升。不过目前暂时也没有什么具体的问题不开新坑了。未来继续终身学习活到老学到老。\n阅读\n我认为读书有用但不那么有用相比较其他而言只是一种高性价获取知识和信息的方式。\n这两年微信读书总时长也来到了 450+ 小时,马上就获得《连续阅读 365 天》的勋章了。阅读量相较于几年前可真是一个天上一个地下,也成为了我每天必不可少的第四顿饭。这个阅读量不算很多,但是我以前不敢想的,不过确确实实也做到了,就很棒!\n目前阅读也没有什么具体的问题不过在构思分享自己的读书心得。\n未来就继续保持阅读 \n生活\n我倒不是特别追求极致的生活质量但非常需要可控的生活条件。例如私人空间自主饮食并且生活自由无拘无束就行。疫情的时候都是在公司挤集体宿舍吃大食堂不能说很差但是质量不高。自从疫情放开后就一直在家里住了生活质量也提升了不少。\n一直作为忠实的米家 Boy近半年也购置了大量小米的智能家电改造生活全屋进行了智能联动实际生活体验感非常哇噻。目前暂时倒也没有什么问题就是这几天比较痴迷三星的回音壁……\n未来计划继续保持现有的生活质量并且尝试进一步提高 \n娱乐\n不打游戏、不追剧、不痴迷许许多多的东西。虽然也不断地尝试许多新的娱乐方式但是几天就乏味了。因为我是一个快乐阈值很高的人……\n不过我特别热衷爬山拍照看银河或者去一个新的地方旅游尝试某种重新活一次的方式。事实上读书写代码挖地种花也是很快乐的但我是一个需要不断的新事物持续刺激神经系统才有机会获得足量的「快乐」人。\n这个问题可大可小但娱乐毕竟是生活非常重要的一部分无法享受娱乐迟早变成大傻瓜。\n最后\n自我感觉有一个非常严重的问题就是干一些事情太用力了或者说我迫切地想要一个结果。其实一些事情不需要太用力也不应该太用力更需要一些适当的摆烂来灵活调节。\n我也不知道应该如何改善暂时还是随心所欲吧。\n就这样复盘结束"},"Personal/Book/个人成长/习惯的力量(新版)":{"title":"习惯的力量(新版)","links":[],"tags":["阅读/个人成长","阅读/笔记"],"content":"简介\n\n书名《习惯的力量新版》\n作者 查尔斯·都希格\n分类 个人成长-认知思维\nISBN9787508674421\n出版社中信出版集团\n\n概述\n本书作者综合了近20年科学家与商业对于“习惯学”的研究包括数百篇学术研究、300多位科学家与企业管理者的访谈以及数十家企业的实践研究成果分三个部分探讨了个人的习惯、成功组织的习惯以及社会群体的习惯作者都希格认为只要掌握“习惯回路”学习观察生活中的暗示与奖赏找到能获得成就感的正确的惯常行为无论个人、企业还是社会群体都能改变根深蒂固的习惯。学会利用“习惯的力量”就能让人生与事业焕然一新。\n划线\n\n她以爱和鼓励教会我如何以合适的语言服务于他人。\n\n笔记\n书评\n点评"},"Personal/Book/个人成长/以极简的方式去生活":{"title":"以极简的方式去生活","links":[],"tags":["阅读/个人成长-认知思维","阅读/笔记"],"content":"简介\n\n书名《以极简的方式去生活》\n作者 杨志华\n分类 个人成长-认知思维\nISBN9787518045853\n出版社中国纺织出版社有限公司\n\n概述\n关于断舍离和极简生活的图书市场上已经有很多了可简叔这本《以极简的方式去生活》显然更适合我们中国的读者首先书中极简的道理不是灌输的而是通过阅读一个故事我们内心自然生发的极简概念其次有关极简的实操性简叔也做了不耐其烦、走心的解说你在实践极简过程中可能遇到的疑问简叔也作了细致的回答。如果你像我一样单是春夏秋同的睡衣就有8件不知如何精简的话还可以私信简叔求指导。简叔跟大张伟在北京电视台录制的生活相对论节目相当逗趣一定会加深你对极简生活的向往另外简叔设计的黑白款简帽也是极好的。《以极简的方式去生活》极简主义、断舍离已经成为当今人们向往的生活方式遗憾的是目前市场上大部分图书反映的都是欧美或者日本的生活方式。中国青年自身的生活方式与他们既有相同也有不同。这本书聚焦中国青年的生活特点通过讲故事的方式讲述一个都市女孩繁漪的人生成长过程。内容不仅涉及有形的断舍离如服装、空间、书籍、纪念品、身材等也包括无形的断舍离如信息、职业、目标、语言、妒忌、旅行等涵盖了一个人生活和工作的方方面面。本书最大的特点就是不仅提供道理更提供方法让读者既可以明白其中蕴含的理论也可以跟随阅读即时行动起来。读完此书相信你也会收获一个更好的自己。更专注、更投入、更幸福。杨志华简叔极简主义者北京断舍离文化公司创始人践行极简生活多年潜心研究生活美学。创办微信公众号“极简断舍离”目前拥有数万粉丝。极简理念足够少、足够好。Slogan世界很大我很小有人爱多我爱少。使命让足够多的家庭和个人过上“足够少、足够好”的极简生活。坚持每天扔掉一样无用的物品。坚持365天不买衣服已经成功一年现进行第二年实践。目前一年四季衣服总计20件。接受《北京卫视》邀请与艺人大张伟同居48小时录制《生活相对论》节目。并接受《北京晚报》采访、北京文艺广播专访、担任北京卫视《暖暖的新家》录制场外嘉宾。\n划线\n\n极简的关键在于选择选择什么、丢弃什么其实是一种智慧。\n\n\n第一种是逃避。比如网瘾、烟瘾、酒瘾大部分时候是因为生活压力过大在这种上瘾的习惯里能够短暂地脱离原来的生活空间获得一种假性的轻松感。第二种就是空虚\n\n\n哪个都行本质上都是一样的这些爱好没有你特别喜欢的如果有其他的爱好就不可能存在了也没有你特别不喜欢的如果有你早就卸载了所以没有十分的也没有零分的大部分都是五到七分的。\n\n\n“不役于物自在随心”\n\n\n极简的三种境界是1.扔掉所有不喜欢的扔掉所有好像喜欢好像不喜欢的只留下喜欢的用喜欢的人事物一起自然欢乐2.有欢喜的知己可以开怀大笑可以相拥而泣那么物品是否欢喜已经不那么重要3.放下对一切外在的依赖,家徒四壁,席地而卧,且饮且歌,自由自在。\n\n\n任由生活蹂躏不如翻身站起来去把握自己的人生。\n\n\n杨振宁先生说学海无涯“乐”作舟要去做自己喜欢的事情如果是苦的话坚持下来是很难的。甚至世界上根本没有坚持这个事情我只是持续地做自己喜欢的事情这是很大的幸福不需要坚持。从来没有人说“坚持享乐”因为享乐是很美的啊只有在痛苦无奈的时候才提到“坚持”这个词。\n\n\n1.吃饭不玩手机\n\n\n2.手机不进卧室\n\n\n3.上厕所不带手机\n\n\n4.每天固定时间看手机\n\n\n优秀的人都在现实生活里做事而不在网络上刷手机。\n\n\n完美主义者要么不开始要开始就希望迅速达成这都是病。我们不需要等一切都完美才开始行动实际上没有这样的时刻所以永远不会开始。我们要做的是马上开始边做边学在实践中发现问题、解决问题。\n\n\n原来不看手机最紧张的不是别人而是自己。\n\n\n人和人的活法不一样这样甘于平淡也许是一种天生的智慧。\n\n\n犹豫就扔掉不需要经过任何考虑因为你如果真的很喜欢你就不会犹豫。所以原则就是犹豫的东西就把它扔掉\n\n\n这个时候你要看这个物品带给你的是美好的回忆还是悲伤的回忆。如果是美好的当然可以留下如果是悲伤的就应该逐渐舍弃。\n\n\n其实每个时代有每个时代的问题但是我们只会怀念过去的美好不会怀念过去的苦难。\n\n\n怀念过去担忧未来。\n\n\n“简”就是把东西减掉简化掉“极”就是简到不能再简\n\n\n这就是我讲的六个原则此刻、喜欢、最少、自我、呼吸、深广。\n\n\n衡量物品的价值卖家总是以当时购买的价格来计算买家永远以当下市场的价格来衡量所以天然是矛盾的吧。\n\n\n人的意志力是有限的今天已经用完了该充电或者加油了\n\n\n一旦我们拥有了某样东西从那一刻起我们也被这个东西所拥有。\n\n\n甚至拥有了知识我们也被知识所拥有限制了自己思维。这是最为可怕的拥有\n\n\n书不在多在精在学以致用。\n\n\n第八读到一本书甚至读到一段话感觉有道理就赶紧拿来用。知识可以学来智慧却不能只能用了之后内化成自己的才是智慧否则还是别人的\n\n\n所谓有初看山是山、再看山不是山、再看山还是山的三种境界。\n\n\n读书追求一个数字就好像经济去追求一个GDP电视去追求一个收视率在一段时间里这是好的但如果不从这个为了数字而数字的陷阱里跳出来就会产生恶性循环。\n\n\n就是在自己擅长的领域发挥自己的天赋。无论是否赚取了财富这样的一生都是精彩的。\n\n\n追求新鲜是人无法克服的弱点耐得住寂寞者往往有大成\n\n\n人是脆弱和感性的一本书、一部电影就可以轻易影响自己的选择但那一定是暂时的几天甚至几小时以后还会回到现实的琐碎中来。\n\n\n一辈子只做的一件事就是把今天的事情做到极致付出自己最大的努力。\n\n\n最终吃饱的一定不是因为有第三个包子前面两个也同样重要。我们走过的所谓弯路也是为了找到正途所必须付出的代价。\n\n\n一个信仰。一份事业。一个家庭。一个知己。一个爱好。一个空间。\n\n\n盛世经商乱世从军\n\n\n如果没有那么纸和笔是最好的知己它永远不嫌弃你也随叫随到。\n\n\n她觉得这是大城市的特点之一既然享受着城市生活的各种便利就要接受随之而来的缺点。\n\n\n一次扔完是彻底清理每日一扔是日常保养。\n\n\n极简不是苦行而是为了追求更好的生活而存在的所以它的核心是“提高生活品质\n\n\n根据自己的实际情况拥有满足生活所需的足够少的物品同时达到足够好的质量。也就是“更少的物品更有诗意的生活。”\n\n\n他们的典型思维就是全有全无或者非黑即白。喜欢一个人这个人全是优点不喜欢一个人这个人全是缺点。\n\n\n如果不能温暖记得也不要苛责每个人都做到了自己生活状态下的最好他已经很辛苦、很努力。当然你也并没有义务去拯救每一个人这种拯救的圣母情结不仅会惹恼对方也会连累自己。\n\n\n一个人在知道又能沉默的时候最接近神。\n\n\n有理不在声高\n\n\n所以说第一个不需要声音太大太大也伤神第二个不需要说太多说重点。\n\n\n第一个就是我们在说话的时候先思考再表达不要本能地去表达。\n\n\n如果是真正爱阅读的人智能手机的出现只能是提供了一种便利而不是造成一种干扰。\n\n\n一个哈尔滨的群友淘汰了冰箱吃的都是新鲜美味的东西。现在我们去买菜是很近的可以把这种往返的路程当作一种锻炼。其实我们每天没有那么忙自己去做饭、洗衣服其实是一个刻意地慢下来的过程。\n\n\n僧人修行的时候要抄经为什么抄经绝对不让用草书一定是楷体。它是要让你慢下来因为你只有慢下来的时候才有时间去思考问题。\n\n\n所有的情绪都有积极的作用除非你滥用。\n\n\n指出电影的毛病并不难难的是你要告诉我该怎么改进。\n\n\n最好的纪念是投入地去经历。\n\n\n我们太容易沉湎于过去希望从过去的岁月里找到一种安慰。\n\n\n如果当下越充实、越丰盈越能够占领精神这座房子过去和未来自然就没有立足之地。所谓的纪念品所谓的沉湎于过去所谓的过往等都会不攻自破。\n\n\n静以修身俭以养德非淡泊无以明志非宁静无以致远。\n\n\n简单所以专注。专注所以投入。投入所以幸福。\n\n\n只是持续地做自己喜欢的事情这是很大的幸福\n\n\n11.想一想,我们生活在一个舒服的空间,有一个和睦的家庭,一份喜欢的工作,有一两个知己,深信某一个理念,有一个爱好。这样的人生,还有什么可遗憾的。这就是极简生活所追求的所有、所追求的最高。\n\n\n当遇到这样的事情时坦然地接受是最好的方式然后再去寻找一些方法寻找一些朋友的帮助相信我太多的伤口根本不是谁治愈的而是自愈的是时间的功劳。到了花期花朵自然开放太阳出来雪自然融化自然而然全是时间老人的馈赠所以不要怕你也会好起来的。\n\n\n厦门一座极美的城市繁漪尤其喜欢海边长长的路可以在这里骑行也喜欢厦门大学里面的人文气息。\n\n\n柴米油盐酱醋茶是此地琴棋书画诗酒花是外地。\n\n\n每个人都会死亡知道这一点才会更珍惜人生。每个人也都会分离知道这一点会格外珍惜对方吧。\n\n\n我们常常活在过去认为过去的日子都很美好而讨厌现在。再过几年会怀念现在认为今天是黄金时代吗\n\n\n就这样往复怀念按照这个推论下去猿猴是最快乐的。如果猿猴也怀念的话可能最早的那片水是最快乐的。既然如此你愿意回到那一片荒芜吗显然不愿意所以我们还活在过去是多么可笑的事情啊。\n\n\n最美的永远是自己的阅历尤其是和不确定起舞的阅历。\n\n笔记\n\n否则中东局势、燕郊房价、邓超与孙俪换脸、如何刷牙、怎样装修这林林总总的信息都袭来一时半刻还真的很难安静下去。\n\n💭 嗨,说真的这些远在千里的事和我又有什么关系呢?\n\n如果你不喜欢读书就不要读书人生苦短去做自己喜欢的事情。\n\n💭 真实\n\n最后但是最重要的一个原则是除非他向你寻求帮助否则不要出手。成年人是很固执的若他自身意识不到问题你的爱心就会遭遇寒流甚至会被误解。\n\n💭 度人?律己!\n书评\n\n✨认识极简尝试断舍离提升专注力做一名长期主义者。\n\n点评"},"Personal/Book/个人成长/写出我心:普通人如何通过写作表达自己":{"title":"写出我心:普通人如何通过写作表达自己","links":[],"tags":["阅读/个人成长-情绪心灵","阅读/笔记"],"content":"简介\n\n书名《写出我心普通人如何通过写作表达自己》\n作者 娜塔莉·戈德堡\n分类 个人成长-情绪心灵\nISBN9787555106425\n出版社广西科学技术出版社\n\n概述\n30年前《写出我心》出版后立刻登上畅销榜成为北美教授写作及写作治疗的人必读、必引述的经典占据同类书籍的顶端被列入美国高中读本影响深远。在书中作者将写作和修行结合分享在写作中找到的驯服自己和释放心灵的方法。如何开始写作如何寻找题材如何应对逃避和拖延如何突破瓶颈……指导读者通过写作全面探讨自己的生命重新注视生命的细节。作者认为任何人都可以通过写作了解自己、用笔表达喜悦和疼痛如童年时的愉快暑假、面对父亲生命垂危时的痛不欲生、离婚的煎熬……在勾勒生活事件的过程中领会生命的奥义。这本书谈论的不只是写作更是生活哲学、生命智慧。通过写作给生活赋予光芒、色彩和故事使我们再次审视这趟凡尘之旅为平凡的生活心醉神迷。\n划线\n\n逝去之事不可留万事三平二满休。字句人间皆无惧一生有爱无尽头。\n\n\n相信你所爱的事物坚持做下去它便带你到你需要去的地方。”别太过担忧安全与否的问题一旦你开始去做自己想做的事内心深处终将获得很大的安全感。\n\n\n我很喜欢教入门班因为我必须重回初写者的心灵状态重拾我对写作最初的想法和感受。\n\n\n1手应当不停地写。不要停下来重读你刚才写的那一行那只是在拖时间并在设法掌控你正在说的话。2不要删除。那是在编辑你写的东西就算写出来的并不是你原本打算写的东西也随它去。3别担心拼错字、标点符号和文法。甚至别去管是否把字写出了格子或超出线。4放松控制。5别思考别想着要合乎逻辑。6直捣要害。倘若你写出了可怕或太过赤裸裸的东西那就一头钻进去其中说不定蕴藏了很多能量。\n\n\n“我有写出世上最烂的垃圾的自由。”\n\n\n我规定自己一个月写完一本笔记本。我总是为自己设下写作的行动纲领。把本子填满就算那便是练习。我的理想状况是每天都写。我说了那是理想状况要是没达到理想我会小心地不责难自己或慌张着急没有人能事事符合理想。\n\n\n8写关于“离开”随便你想用哪种方法写都行。写你离婚、今天早上离开家门或朋友即将不久于人世的事。9你最初的记忆是什么10哪些是你曾爱过的人11写你居住城市的大街小巷。12描绘祖父或祖母。13写写看游泳星星你最害怕的一次经历绿地你如何知道有关性的事你的第一次性经验感到与神或大自然最接近的一次经验改变你的人生的文章或书籍肉体的耐力你以前的一位老师别沦于抽象把真实的东西写出来诚实地写并写出细节。\n\n\n有段禅语说“说话时便说话行走时便行走死亡时便死亡。”该写作时便写作别让自己和内疚、控诉及暴力的威胁战斗。\n\n\n不妨使出各式各样无伤大雅的小伎俩只是别陷入无止境的罪恶感、逃避和压力的恶性循环里。\n\n\n把“你很乏味”当成远处微风吹动洗好的白衣服所发出的啪啪声。衣服终究会晒干远方的某个人会把它们叠好并收进屋里。\n\n\n就在那一刻你写出的文字终于和你内心所感联结在一起就在那一刻你获得解放因为你已不再与你的内心争斗你已接受它们与它们为伴。\n\n\n我有首诗诗名叫做《无望》那是一首长诗。我总认为那是一首喜悦的诗因为我借以写出了沮丧和空虚从而让我重拾生机且一无所惧。然而当我\n\n\n我告诉他“慢慢来先让自己写一阵子熟悉一下写作是怎么回事再说。”写作是一辈子的事并且需要做很多很多练习。我了解他为何迫不及待我们往往想要让自己以为正在做件有用的事、去某个地方、完成某个目标——“我正在写一本书”。\n\n\n写作并不是麦当劳汉堡写作必须慢火细炖\n\n\n作家必须肯定生活肯定生活中的一切\n\n\n作家有两条命。他们平时过着寻常的日子在蔬果杂货店里、过马路时和早上更衣准备上班时手脚都不比别人慢。然而作家还有受过训练的另一部分这一部分让他们得以再活一次。那就是坐下来再次审视自己的生命复习一遍端详生命的肌理和细节。\n\n\n上乘的艺术几乎沦为煽情可是终究并不是。认清这只苍蝇想要的话甚至可以爱上它就是别和它结婚。\n\n\n我们想要诚实无欺的支持和鼓励一旦得到了却又偏偏不相信反而轻易听信苛责以强化心底根深蒂固的一个想法那就是其实我们根本不行根本不会写作。\n\n\n你有什么深远的梦想\n\n\n不要概念而要具体的事物。\n\n\n我们必须牢记一切事物都是既平凡又不凡事物平凡与否全看我们的心灵是开放还是闭塞的。细节无所谓好或坏它们就只是细节而已。\n\n\n最好当个部落作家为所有的人写作反映人群当中许多不同的声音不要只是做个隐士型作家只追索个人心灵中微不足道的真理。提笔写作时应视野恢宏胸怀全世界。\n\n\n不过倘若你能捕捉那种感觉或者嗅到、瞥见你与那感觉合为一体的刹那那么你就很可能会写出一首好诗。\n\n\n女性总是在寻求别人附和她们的感受和见解她们并不是在提出声明后便坚守声明“这很美”或“这很糟糕\n\n\n这世界并非总是黑白分明人不见得能确定自己可不可以去某个地方然而务必作出清楚、斩钉截铁的声明这一点对写作新手来讲尤其重要。“这很好”、“那是匹蓝色的马”而不是“呃我晓得这事听来很怪不过我想那八成是一匹蓝色的马”。提出声明不啻在练习信任自己的心学习坚持自己的意念。\n\n\n写作是在焚尽你心灵中的迷雾别把雾气带到纸上。就算有件事你并不是很确定表达的时候也得做出对自己胸有成竹的样子。如此这般地多多练习最后你会真的胸有成竹。\n\n\n试试看把名词和动词连在一起会形成什么样的新组合然后据此造出完整的句子需要的话可以用过去式。\n\n\n……在那儿天使与剑兰走过你的肌肤/睡在地上[插图]…\n\n\n引述一句戈尔·维达尔[插图]的名言:“每位作者和每位读者都知道,好的写作是最棒的旅行。”别担心写得好不好,只要写,便足以使你置身天堂。\n\n\n海明威曾说过“为什么不重要是什么才重要。”讲出切实且详尽的情报至于为什么就留给心理学家去伤脑筋。知道自己想要写就行了提笔写吧。\n\n\n先写十分钟可收到很好的暖身或清醒作用从“我是……的朋友”开始写但列出的名单必须是无生命的事物。\n\n\n由于他们写得的确不错因此不愿意脱离熟悉的事物打破自己的世界闯入新领域进入未知的天地。\n\n\n“你是为自己写作还是为读者而写”写作时想象你正与他人分享你的看法走出寂寞的深壑向另外一个人表达自己。\n\n\n你需要去做平常不会做的事。\n\n\n了解真正的自己并从那里着手写起你将增进世人彼此的了解从而帮助这个世界。\n\n\n写稿朗读再写再读通常你会停止东想西想变得越来越不自觉。每个人都在同一条船上而且因为没有人会在旁批评议论你会觉得越能自由自在、随心所欲地写。\n\n\n在那个星期当中有人从题目盒里抽到“你的第一次性经验”。有位女士自此在剩下来的几天里没写过其他题材。她写她第一次的性经验还有第二、第三次等等。我相信这会儿她仍坐在明尼苏达州丘市的彩虹酒馆里写她的第七百零八次性经验。\n\n\n她最后一次举行朗读会时不但座无虚席连站票都销售一空。她告诉我朗读会结束以后她回到家心情非常沮丧因为大家都那么喜欢她的诗她说“我又用我的作品愚弄了一群人。”\n\n\n片桐老师有一次对我说“我们都是佛我看得出你是佛但你并不相信我。等你看到自己是佛就会醒觉了。那便是悟道。”我们很难去理解并珍视自己的生活却能比较轻易地看到自身以外的事物。\n\n\n时间最能检验作品要是你对某件作品没有把握就暂且搁置一段时间六个月以后再重看届时想法会比较清楚。\n\n\n因为写作有时像是件一无是处的事只是在浪费时间。突然之间你会坐在椅子上为自己的尘俗生活心醉神迷。艺术伟大的价值便在这里——化平凡为不凡。我们唤醒了自己觉察到我们正在体验的生活。\n\n\n日本武士一位凡遇非属当下的事物即勇于出手铲除的伟大战士就像一位心灵空白清净把对手一砍为二的日本武士不感情用事用澄澈且洞悉的心灵来阅读。不\n\n\n首先我觉得地点和环境非常重要。\n\n\n对真实的自己还暂时没这个勇气。”“我想写的都是心里最深最隐私的梦不知如何下笔。”“哎呀有孩子了都是当爹当妈的人了没精力写啊”“哎呀我得上班挣钱啊天天要上班哪有时间写啊”“就我这点功底差太远了还是别献丑了。”“我想写我爸的故事可我要写出来非被他打死不可……”\n\n\n不否认这些都是事实。但如果你真心投入你就总能找到时间去写作哪怕每周只能抽出半小时的时间去写都是好的。一个真心想去写作的人不会把写作的梦想拖到60岁——因为你可能活到59岁就去见上帝了。你必须找到一种方式去掌控你的全部人生。所谓“明日复明日明日何其多”。\n\n\n“心猿”其实是来自中国的词语。我们经常说心猿意马。心猿会让我们忙碌不安很难去静心做事。\n\n\n我觉得天赋就像地下水——你要用自己的努力先挖一口井它才会喷发出来所谓“才思泉涌”。\n\n\n我写作是为了取悦读者。我希望自己如实写作既不是为了讨好别人也不是为了孤芳自赏地取悦自己。\n\n\n我们在现实中会有很多个年头来了又走了没有什么特殊含义。但一个小说家在写故事的时候就必须创造“特殊含义”——因为读者读小说时会期待你所说的一切是有“特殊含义”的。所以一个小说需要有结构有开头有经过有结尾虽然每一步的过渡可能并不那么明显。\n\n\n对我们自身而言当我们写作时去挖掘自己过去的经历也很重要因为过去本无处可躲也没什么可躲的。如果你无法面对真实的自己你笔下的一切也都是假情假意。你需要接纳自己的人生接纳自己的心念。\n\n\n人活着就面临着很多“失控”。比如坠入爱河这就是一种失控当我们的至亲至爱离世我们又会面临一种巨大的失控。\n\n\n写作的好处是你可以暂时性陷入一种巨大的“空性”和“无我”状态中然后当你放下笔去外边散散步你会从“无我”中跳脱出来回到一个安全的自我模式然后再继续进入“无我”的写作状态循环往复\n\n\n我的身体现在开始准备写某个主题的一本书但其实这可能是我大脑中积攒了很多年的潜意识想法。虽然当时这些潜意识并未浮出水面但我却悄然地在做这些准备了。可能当我真正决定下笔之前我的大脑已经在不知不觉中打了半年的腹稿了。这样当我动笔之时我才能保证这个主\n\n\n只是在回望过去时对当时的自己充满了极大的爱与同情。她当时的自己很认真很努力很纯粹。在某种程度上她很聪明却又经历过很大的破碎我想如果没有过那么多的破碎也许她看事情可以更清晰。虽然并不知道后来的结果如何但她从不害怕。她相信尽心即可结果要来的时候自然会来。\n\n\n相比较于作品成果而言我更关注每个学生在写作中的健康心态。这种可持续性的健康心态我觉得比一部短期作品更加重要。\n\n笔记\n\n我们甚至必须对椅子、空气、纸张和街道怀有善念。人心必须变得如此宽阔有肚量。当佛陀在菩提树下悟道成佛时说“我与众生皆成佛。”他并不是说“我成佛了而你没有”或“我看到佛了”好像他归他佛归佛似的。\n\n💭 正心善念\n\n对世世代代生活在那儿的霍比族印第安人来说村落四周那片广袤的大地实在平凡得可以他们天天都看到宏伟的台地。可惜的是很多年轻人都想离开想到比较刺激的城市去闯天下。\n\n💭 得不到的才是最好的\n\n这并不表示你在写作时应该停下沉思一个小时好想出一个新动词。只是要留意动词以及动词的力量并以新的方式来运用动词。你对语言的各种面向越是注意文笔就会越生动。\n\n💭 反差\n书评\n点评"},"Personal/Book/个人成长/刻意练习:如何从新手到大师":{"title":"刻意练习:如何从新手到大师","links":[],"tags":["阅读/个人成长-认知思维","阅读/笔记"],"content":"简介\n\n书名《刻意练习如何从新手到大师》\n作者 安德斯·艾利克森 罗伯特·普尔\n分类 个人成长-认知思维\nISBN9787111551287\n出版社机械工业出版社\n\n概述\n本书是两位作者合作撰写的一位是心理学家另一位是科学作家。10多年前我们开始经常探讨杰出人物和“刻意练习”这个主题并在5年前开始认真地围绕这个主题写书。在那段时间本书在我们两人的思想碰撞中慢慢成形以至于我们现在都难以分辨书中的哪一部分观点由谁提出。我们只知道本书由我们两人合写比由我们单独去写要好得多也完全不同。\n划线\n\n练习就是不断重复吗不是。不断重复只是“天真的练习”无法带来进步。“正确的练习”需要好导师、有目标、有反馈……\n\n\n没有勤奋就没有一切至于天才我将其理解为一种无限的伸展性也许一个人只要具备一丁点儿天才就可以扩展成很大。——郎朗国际著名钢琴家\n\n\n我发现身边的高人他们有两项高于常人的本领一是洞察问题的本领二是解决问题的本领。\n\n\n对于大多数人很努力却得不到希望的结果很多事有态度却茫然于拿不出解决问题的具体方法。\n\n\n认知复杂性高与认知复杂性低的学习活动的差异在很大程度上表现为隐性知识的多少与比重。\n\n\n认知复杂度cognitive complexity是指你建构“客观”世界的能力。认知复杂度高的人具有高度复杂化的思维能力更善于同时使用互补与互不相容的概念来理解客观世界。真实世界中黑白对错并非截然分明。\n\n\n在许多领域通往卓越的道路不是精确计算时间的结果而是模糊与含糊不清的。没有简单的模型通向伟大。\n\n\n天才更懂得利用大脑的适应能力\n\n\n不论基因遗传可能在“天才”取得的成就中发挥着什么作用这些人拥有的重要才华与我们每个人都拥有的才华是一样的。也就是说他们和我们一样大脑和身体都具有适应能力只是比我们更多地利用了那一能力而已。\n\n\n学习不再是挖掘某人潜力的方式而是发展这种潜力的方式。我们可以创造自己的潜力。\n\n\n不论在什么行业或领域提高表现与水平的最有效方法全都遵循一系列普遍原则。我们把这种通用的方法命名为“刻意练习”。\n\n\n我们的大脑对于可以将多少事物立即保存在短时记忆中有着严格的限制这一限制通常约为7件事物\n\n\n在任何行业或领域之中最有效的和最强大的那类练习都通过充分利用人类的身体与大脑的适应能力来逐步地塑造和提升他们的技能以做到一些过去不可能的事情。\n\n\n而且对刻意练习原则的运用是为任何行业或领域策划和设计训练方法的最佳方式。\n\n\n人类的身体有一种偏爱稳定性的倾向。\n\n\n负荷。老鼠还被逼着走出了舒适区而肌肉对此的顺应方式是变得足够强壮以建立新的舒适区。这样就重新建立了体内平衡。这就是体育\n\n\n那么身体就能轻松应对以前感到十分艰难的那些体育锻炼活动了它会再度感到舒服。改变也停止了。因此要使改变不断进行下去你必须不断地加码跑得更远一些、更快一些并且爬坡跑。如果你不继续给自己施加一些压力身体将会保持体内平衡尽管此时的体内平衡不同于以前但你将停下改进的脚步。\n\n\n大脑对于处在舒适区之外却离得并不太远的“甜蜜点”上的挑战改变最为迅速。\n\n\n而对吉他来说主要是拨弹或捏住弦。简单地讲对这类乐器演奏者的训练重点是加强他们对左手手指的控制\n\n\n音乐训练以各种不同方式改变了大脑的结构与运行使人们的音乐演奏能力进一步增强。\n\n\n那些科学家发现爱因斯坦的顶下小叶比常人大许多而且形状也格外异常这些发现使得科学家们推测爱因斯坦的顶下小叶可能在他进行抽象数学思考方面发挥着至关重要的作用。\n\n\n一般说来“足够好”就是足够好。但重要的是记住选择总是存在。\n\n\n他们经过年复一年的练习已经改变了大脑中的神经回路以创建高度专业化的心理表征这些心理表征反过来使得令人难以置信的记忆、规律的识别、问题的解决等成为可能也使得他们能够培养和发展各种高级的能力以便在特定的专业领域中表现卓越。\n\n\n杰出人物运用心理表征来提高技能水平监测并评估自己的技能水平在必要时调整心理表征使之更加有效。这反过来使我们能够更好地解释刻意练习了。\n\n\n这一法则具有无法抗拒的吸引力。它很容易被记住。\n\n\n王牌训练计划海军设计的这个计划在许多方面都有刻意练习的元素。特别是它给学生飞行员机会在不同的局面下尝试不同的战法并由教官对其表现提供反馈然后将他们所学的知识运用到实战中去。\n\n\n议者目的是教他人如何提高绩效。他们称自己为顾问、咨询师或教练他们\n\n\n任何人都可以进步但需要正确的方法。\n\n\n如果你没有进步并不是因为你缺少天赋而是因为你没有用正确的方法练习。\n\n\n2012年5月丹尼斯开始计算并记录他的差点时差点为8.7对只玩了几年高尔夫球的人来说这已经是十分不错的成绩。到2014年下半年他的差点在3和4之间浮动那真的能给人留下深刻印象。在我写这本书时也就是2015年下半年丹尼斯在受过一次伤后恢复练习那次受伤的经历在一段时间内妨碍了他继续进步。他已经练习了6000余小时因此他已经在自己确定的1万小时训练的目标上完成了超过60%的部分。\n\n我们依然不知道丹尼斯能否实现他参加美国职业高尔夫巡回赛的目标但他的经历清晰地表明一个年龄已达30岁、从来没有真正打过高尔夫球的人通过正确的练习可以将自己变为一位高尔夫大师。\n\n改变运动训练\n\n当我和全职运动员以及他们的教练交谈时总是不无震惊地了解到他们从来没有花时间辨别自己在哪些方面还可以改进然后去设计出有针对性的训练方法。在事实上运动员特别是团体运动项目中的运动员的大部分训练是在团体中进行的并没有试图搞清楚每一位运动员应当着重训练些什么。\n此外几乎没有人去了解杰出运动员运用的心理表征。纠正这种现象的理想方法是让运动员口头报告他们在比赛时一直在想些什么这可能使研究人员、教练或者甚至运动员自己能设计一些训练任务来改进他们对比赛情景的心理表征而且会运用我们在第3章中描述过的同样方式。当然有些十分杰出的运动员自己创建了有效的心理表征但这些一流运动员中的大多数人甚至不知道他们的想法与那些成就不那么杰出的运动员之间有何不同。\n\n知识本身绝不是学习的目的\n\n\n一旦学生懂得了在某个领域中要达到那种足够高的技能水平必须要做些什么那么他们至少从原则上理解了在其他领域追求卓越也需要做些什么。\n\n\n当我们意识到在各行各业中最杰出的人物之所以占据那些地位并不是因为他们天生具有某种才能而是因为他们通过年复一年的练习充分利用人类的身体与大脑的适应能力而提升和发展了自己能力那么这种颠覆就开始了。\n\n\n心流\n\n笔记\n\n天才存在吗\n为什么有些人对他们所做的事情如此擅长擅长到令人不可思议的地步\n\n💭 如果可以换一种说法,天才其实是人对于某件事情具有极高的契合度,进而展现出不同于一般人的表现。\n\n“天才”是训练的产物\n\n💭 天才不只是训练的产物,必须有客观存在的基础,同时进行主观的训练提升,才会产生天才。\n\n这些人拥有的重要才华与我们每个人都拥有的才华是一样的。也就是说他们和我们一样大脑和身体都具有适应能力只是比我们更多地利用了那一能力而已。\n\n💭 向内了解自我,向外认知世界,寻找到最合适自己的成长方式。\n\n刻意练习的任务难度要适中能收到反馈有足够的次数重复练习学习者能够纠正自己的错误。\n\n💭 打破自己的舒适圈,一步一个脚印一步一个台阶,持续的正反馈。\n\n尽管我们不能确定地知道是什么导致这种现象的发生但是似乎那些密集的训练导致受训者的大脑将越来越大的部分专门用于这种记忆从而留给其他类型记忆的脑灰质变少了。\n\n💭 脑容量是有限的,只有腾出空间才可以放进新东西\n\n大部分人做不到这些事情并不是因为他们不具备做这些事情的能力而是因为他们满足于在舒适区中生活从来没有尝试走出舒适区。\n\n💭 打破舒适区\n\n他们的视力与常人无异反应也不会比常人快。他们只是拥有了一系列心理表征。这些心理表征的形成是经过多年的击球训练而且获得即时反馈比如教练在旁边指出应当如何预测对方怎样抛球的结果。心理表征使击球员能迅速意识到对方抛出了什么样的球并且马上判断在击中此球后球可能会朝哪个方向飞去\n\n💭 潜意识,心里表征可以尝试理解为潜意识\n\n“如果有人愿意花1万小时去做同一件事情我认为他一定有病心理不正常。\n\n💭 一万小时的迭代\n\n王牌训练计划\n\n💭 王牌训练计划\n\n只有把飞行员逼出舒适区他们才有可能最大限度地学会怎么战斗。\n\n💭 舒适区是不会成长的\n\n。他谈道为了训练人们的新技能并拓展他们的能力需要把人们逼出舒适区。他强调了反馈的重要性还研究了世界上一些最杰出商界领袖的特点比如长期担任通用电气董事局主席和首席执行官的杰克·韦尔奇Jack Welch以思考其他的商界人士要成为杰出领袖需要发展哪种类型的领导风格、销售技能和自我管理技能。\n\n💭 打破舒适区,保持节奏感,持续正反馈\n\n这使得他们体验到“很嗨”(high)的感觉,这种感觉,除了专家之外,很少有人能体会。\n\n💭 心流\n\n成为“练习人”\n此外我还坚持认为当我们在提高自己时我们才最像是人类。和其他任何动物不同我们可以有意识地改造自己以我们选择的方式来提高自己。这使得我们和当今世界以及有史以来的其他物种区别开来。\n\n💭 有意识的改造自己?\n书评\n点评"},"Personal/Book/个人成长/十分钟冥想":{"title":"十分钟冥想","links":[],"tags":["阅读/个人成长-人生哲学","阅读/笔记"],"content":"简介\n\n书名《十分钟冥想》\n作者 安迪·普迪科姆\n分类 个人成长-人生哲学\nISBN9787111639824\n出版社机械工业出版社\n\n概述\n冥想是一种奇妙的技能它有改变我们人生的潜力但是怎样运用这种技能则取决于你自己。随着媒体对冥想和正念的报道越来越多许多人似乎急于确定冥想的用途。事实上你只有确定了如何用它你才能确定它的用途。在学骑自行车的时候你所了解的是如何骑车而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具有些人用它跟朋友闲逛还有极少数人可能以它为终身事业。对所有人来说技能是一样的安稳地坐在车座上别掉下来。所以虽然别人可以教你如何骑车但骑车对你而言到底意味着什么你要拿它做什么以及它怎样才能最符合你的生活方式这完全取决于你自己。冥想技能也是如此你可以将它应用到生活中的任何方面它的价值取决于你赋予它的价值。\n划线\n\n你上一次坐下来安静不动不分心不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰没有任何你需要思考和解决的事情是什么时候\n\n\n在正念环境中冥想不是要去阻止想法、控制心灵。它是一个过程在这个过程中我们放弃控制不插手不介入学会以被动的方式集中注意力同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手容许心灵以自己的节奏、自己的方式展开你才能找到真正的头脑空间。\n\n\n你知道如果你坐上飞机从那些云的一端穿过另一端就没有阴云而只有蓝色的天空了。就算有大片阴沉沉的乌云蓝色的天空也始终存在。\n\n\n我得到了这样一种理念天空总是蓝的。云相当于我们的思想当心灵忙于这些想法的时候蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何心灵的深层本质就像蓝色的天空一样并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候云会变得更加阴沉更令人烦扰。也许整个天空中只有那么一个想法然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走而是搬把椅子到花园里坐看云卷云舒。有时候蓝色的天空会穿过阴云展露出来令人备感美好。如果我能耐心地坐在那里不过分执着于那些阴云那么蓝色的天空会显露得更多。\n\n\n。最重要的是你可以想象心中有一片始终宁静、始终澄澈的区域想象心中有一片你随时都可以依归的地方想象无论生活中发生什么事心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事就指望它突然静静地在某个地方站定因此当你跟这匹野马也就是你的心灵一起坐下来的时候你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上相反要给你的心灵一点时间让它安定下来放松一点。你急什么呢”\n\n\n关注它的同时试着温和地将它分享给他人。同样如果你的注意力集中在令人不快的感受上那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的必将浮上来\n\n\n就情感而言凡是被压制的必会再浮上来。也许它会突出到表面来就像情感本身一样也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央即一块开放田野的中央。现在缰绳的一端系着这匹马另一端在你手里。不过缰绳是松弛的这匹马有它所需要的一切空间它并没有觉得被困住或者受到约束\n\n\n你有没有注意过当你真正专注于某个事物的时候你的心灵会变得多么平静你有没有注意过即便你的心灵之前还凌乱如麻但是一旦专注于自己喜欢做的事情并且全身心地沉浸在那项活动中时心灵会开始安定下来会感到非常宁静\n\n\n所以对任何可能会令人分心的事物进行限制正是修习开始的第一步。\n\n\n当心灵像这样被完全扰乱时我们就几乎不可能看清正在发生的事也不可能看到表面之下隐藏着什么。\n\n\n如果要对这些让我们的生活变得既复杂又丰富的感受和情绪进行研究那么我们需要使水面足够平静因为只有这样我们才能看到它们。\n\n\n在那个时候似乎一切都被愤怒染上了色彩。我不知道你有没有过这种体验感觉就像是所有从脑海中闪过的想法都带上了这种愤怒底色这种底色改变了你看待周围世界的视角。\n\n\n奇怪的是与此同时我好像开始不那么专注于自己的那些想法而更多地开始专注于自己手头的活。虽然我同意用剪刀来剪草不见得每个人都喜欢然而剪了一会儿之后我发现这个过程其实可以使人平静。事实上这个过程本身就成了一种冥想过程。\n\n\n“你的心灵就是这个样子。你看到了这些陷阱但是惯性太强大了你没法阻止自己掉进去。但是\n\n\n“如果你分心走神了那就不是冥想了。只有在你不分心不走神的时候才是冥想。没有好的冥想或者坏的冥想之说只有分心和不分心之说以及觉醒和不觉醒之说。”事实上他常常把冥想比作去剧院\n\n\n你甚至会被台上的故事所激发坐在那里计划着如何向你5年来一直想告白的人告白。\n\n\n冥想根本不起作用。我感觉糟透了。进来的时候我心情还好而现在我感觉心情很差那么冥想的意义何在呢\n\n\n我们其实很少能做到身心的时空合一。\n\n\n理念是不要试图去阻止想法而要顺其自然任由想法在你完全觉醒的状态下来来去去。\n\n\n跟非冥想者相比冥想者的大脑中管理痛苦和情感的区域要更厚实\n\n\n我们中有多少人一直都是这样生活的沉浸在对过去的回忆和对未来的规划中如此全身沉浸在思考中而完全没有意识到当\n\n\n无论你在做什么它就在这里它就在普通平常的日常活动中如就在你吃三明治的动作中就在你喝水的动作中就在你洗碗的动作中……这就是正念、心在、觉醒的要义所在。\n\n\n我们对身体的运动如此熟悉以至于在跑的时候根本不需要太专注。正因为这一点心灵往往很容易游离。\n\n\n研究正念有效性的研究者发现哪怕参与者每天只冥想很短的时间只做了5天就有更多血液流向他们大脑中帮助控制情感和行为\n\n\n冥想的最佳时间是早上醒来的第一时间\n\n\n他们不断地把冥想加入下一个“待办事项清单”中结果却是“未完成”状态。他们用来减轻自己压力的事情反倒不知怎么成了他们的另一个压力来源。这可不是冥想的目的\n\n\n研究冥想和正念的好处的神经科学家发现了重复的重要性。他们说日复一日地做冥想练习这个简单的举动就足以促使大脑做出积极的改变。事实上他们认为这对于建立新的突触关系和神经路线来说极其重要。\n\n\n某一天你登上一列拥挤的火车却没有为之感到过于困扰而另一天同样拥挤的列车却好像触发了你的各种情绪。你会很清楚地意识到并不是外在的事物给我们带来了最大的麻烦而是我们心灵里面的事物给我们带来了困扰——幸好心灵里的这些东西是可以改变的。留意视角在每时每刻的转变这会为你的日常冥想提供强有力的支持。\n\n笔记\n\n“天空总是蓝的。”\n\n💭 生活总是美好的\n\n现在想象一下你将石头一块接一块地扔进水中看看整个水面同时被搅动起来的情景。当水面变成这个样子的时候你几乎就不可能看到水里的任何东西更不用说看见水底的东西\n\n💭 静心\n\n如果我一门心思专注在一件事上那么我不可能同时分心到另一件事上。因此在没有刻意忽略或抗拒内心想法的情况下当我的心思专注在别处的时候这些想法自然地自行消失了。\n\n💭 活在当下,体验内心的宁静和愉悦\n💭打水即是打水劈柴即是劈柴烧饭即是烧饭\n\n以正念的形式将觉醒应用到日常生活的杂务中。\n\n💭 正念即是专注力\n\n行走是一种确定的、受习惯驱使的行为它几乎不需要专注力。\n\n💭 潜意识\n\n冥想只有在你去做的时候才会起作用只有当你坐下来冥想的时候你才会看到它的好处\n\n💭 实践是检验真理的唯一标准\n书评\n点评"},"Personal/Book/个人成长/即兴表达":{"title":"即兴表达","links":[],"tags":["阅读/个人成长","阅读/笔记"],"content":"简介\n\n书名《即兴表达》\n作者 王达峰\n分类 个人成长-沟通表达\nISBN9787308199025\n出版社浙江大学出版社\n\n概述\n本书针对当代人的表达痛点从即兴表达者必备的基本素质出发提炼适用于不同场合的万能表达结构总结沟通中常见的陷阱及应对策略助力表达者精进表达自信把握临场机遇从容掌控每一个沟通瞬间。\n划线\n\n但需要注意一个关键点这个目的一定要是基于对方的。\n\n笔记\n\n1这个项目能给公司带来哪些好处\n2与同行的其他公司相比我们公司做这个项目有多紧迫\n3如果拿到预算你会如何花这些钱、如何监控财务\n\n💭 项目创造的价值\n书评\n点评"},"Personal/Book/个人成长/学习之道":{"title":"学习之道","links":[],"tags":["阅读/个人成长-人生哲学","阅读/笔记"],"content":"简介\n\n书名《学习之道》\n作者 芭芭拉·奥克利\n分类 个人成长-人生哲学\nISBN9787111552062\n出版社机械工业出版社\n\n概述\n《学习之道》则是一本真正面向大众、指导实践以及科学可信的学习方法手册。这本书的优点主要有以下几个方面。学习方法领域的图书主要分为两类。一类走的是学院派路线主要是梳理学习心理学中的各种理论在这些书中我们能看到不同流派的观点能看到心理学家对学习本质的讨论但是这些内容对于学习者来说有些过于抽象了较难在学习的具体实践中加以应用另一类走的是实践派路线作者往往靠个人的天赋和努力摸索出了一些基于经验的学习方法这些书有一定的参考价值但缺点也比较明显一方面其中部分观点可能不符合学习心理学中的科学结论另一方面某些方法只适合特定的场景无法迁移应用在更广阔的学习领域中。\n划线\n\n还有另外一种直观的方式来看待专注模式和发散模式之间的区别想象从手电筒里打出来的光。专注模式下的光束更紧密穿透力更强径直打在一小块区域上。而如果你拨到发散模式光柱会分散开照亮的范围更广但各处的光强都会降低。\n\n\n有的人是左脑主导的有的人是右脑主导的”\n\n\n总要有来有往才能打赢乒乓球\n\n\n他是指专注与发散的思维过程经过长年累月地细火慢炖产生创造性的突破。\n\n\n“慢直觉”的关键就是要用多角度思维感知一个概念。那样概念的方方面面会临时而随机地组合在一起直到最终你的创意如出水芙蓉般诞生。\n\n\n解决数学和科学难题就像在钢琴上弹一首曲子。你练得越多,神经模型就越坚实,颜色就越深、越强壮。\n\n\n[插图]\n\n长达几个世纪以来杀人者都对砒霜青睐有加。只要在早餐面包上撒一点用不了一天你就会痛苦地一命呜呼。然而在1875年的德国文理协会第48届会议上有两个人坐在观众面前轻松从容地服下了两倍于致命剂量的砒霜。可想而知那时大家有多震惊可第二天他们又面带微笑健康如故地回到了会场。尿检显示二人并没有使诈他们确实服食了毒药。[插图]\n但是怎么可能有人服毒却不死甚至看起来若无其事呢\n这个看似无关的故事与我们将要讲到的拖延问题有许多可以类比之处。了解一些拖延症的认知心理学原理就如同了解毒药的化学原理一样能够帮助我们形成有益健康的预防机制。\n\n但如果你开始对某件事游刃有余自然就会乐在其中了。\n\n\n习惯可以帮我们节省力气它能为我们的大脑腾出空间进行别的活动。\n\n\n而你心里明白这5道题可能会是艰巨的任务。你幻想自己能在最后一秒搞定这5道题或者20页的报告之类),而活在这样的幻想里会比较轻松。\n\n\n如同拖延习惯有四个组成部分■ 信号;■ 反应程序;■ 奖励机制;■ 信念。\n\n\n你要给发散模式留出足够的时间\n\n\n一位小提琴演奏大师不会把一个曲子从头到尾练上无数遍。相反她会集中攻克最难的乐段比如那些让人指法笨拙、脑中浑然无序的部分。\n\n\n备考的时候把你的问题和答案梳理整齐会方便你快速浏览。\n\n\n培养灵活专业的思维关键在于构建属于你的思维方案库。这是一个你能快速读取的数据库在紧要关头总能派上用场。这个做法不仅可以用于解决数学和科学问题它还适用于生活的许多方面。比如这就是为什么要去观察紧急出口相对飞机座椅或宾馆房间的位置这样做总是上策。\n\n\n习惯突击完成工作的人通常比那些合理安排时间、定时定量完成工作的人效率低很多。[插图]突击完成工作的时间如果太长,会让你精疲力竭。\n\n\n你自带的超大视觉空间记忆\n\n\n研究表明越是聪明的人越容易在繁芜复杂的问题上迷失自我。而头脑略逊一筹的人反而更容易找到更简单的解决方法。[插图]\n\n\n训练尤其是对学习材料中最困难的部分更要刻意训练这样才能让那些拥有普通智力的人有机会上升到“天赋异禀”的境界。\n\n\n在科学、数学、技术领域取得成功的专业人士逐渐习得的一个特质就是学会如何组块——提炼关键思想。\n\n\n毕竟只有数学是理性的诗歌而诗是心灵的数学。\n\n\n努力学习数学和科学的时候我们能做的最重要的一件事就是给脑中的抽象概念赋予生命。\n\n\n你是自己的骄傲尤其应该骄傲于那些让你“与众不同”的特质并把它用作你成功的秘密法宝。借你与生俱来的逆反心理反抗偏见不要轻信他人对你下的结论。\n\n\n考试本身就是一种效果非凡的学习经历\n\n\n开始做题时就先做看起来最难的那道。不过要做好准备一旦你发现自己已经一两分钟没有进展或者感觉可能想偏了就要立刻抽身出来。\n\n\n对于考试恐慌人群来说还有一个好建议就是把注意力暂时转移到自己的呼吸上来。\n\n笔记\n\n发散模式对学数学和科学也同样必不可少。如果我们在一个问题上挣扎了许久而不得思路它会冷不防地提供一个新点悟。\n\n💭 潜意识,好读书不求甚解\n\n利用专注思维模式来处理数学和科学问题通常会比处理语言和人际交往相关问题费劲得多。[插图]这也许是因为上千年来,人类操控数学概念的能力并没有进化,并且数学概念往往比传统语言问题更加抽象隐晦。[插图]\n\n💭 抽象能力\n\n如果给你两个三角形要求你把它们拼成一个正方形这非常容易就像左图那样。但如果再给你两个三角形让你把四个放在一起拼出一个正方形你的第一反应会是错误地把它们拼成一个长方形就像中间图示那样。这是因为你的大脑里已经有了专注模式下的模型使你囿于成见。\n\n💭 认知偏见\n\n用一个计时器设定25分钟在这25分钟里全神贯注于一项任务什么任务都行。不用担心能不能完成它专心去做就好。25分钟的时限一到你就停下来奖励一下自己看看网页翻一下手机做任何你想做的事情。注意奖励和工作本身一样重要。\n\n💭 番茄时钟工作法\n\n我们的大脑有两种截然不同的思维模式——专注模式和发散模式。你会在两种模式之间转换择一而用。\n\n💭 本意识,潜意识\n\n你怎么才能意识到自己处于发散模式中那是一种什么感觉\n\n💭 思维活跃,极致联想\n\n首先要记住陷入拖延很简单但获得顽强的意志力可就难得多了。因为后者需要动用大量的神经资源。可以说用意志力来对抗拖延就像在空中喷洒廉价劣质的空气清新剂一样完全徒劳无功。除非万不得已否则不要把意志力浪费在抵抗拖延上。\n\n💭 意志力是最宝贵的消耗品\n\n同样拖延症患者起初也只是拖延了一点点。可一次又一次地拖延最终让他们泥足深陷。他们也许暂时看上去毫无问题但长此以往呢\n恐怕不会太好。\n\n💭 拖延的问题在于节奏感的保持,一步登山,一口吃成胖子都是不现实的。只有日拱一卒,持续的正反馈才是可行的\n\n让自己享用一杯拿铁或去浏览自己最爱的网站能否奖励自己毫无愧疚地看一晚上电视或上一晚上网能不能在有更大收获时给自己更大的奖励比如电影票、毛衣或是买点浮夸的小礼物\n\n💭 反馈奖励\n\n刚坐下投入工作前有点负面小情绪是正常现象。如何应对这些情绪是才是关键。研究者发现“快人”和“慢人”的不同就在于“快人”毫不拖沓地把负面想法放在一边对自己说“别浪费时间了现在就动手吧。只要你动手做事情感觉就会好很多了”。\n\n💭 问题是问题,情绪是情绪,永远不要带着情绪去解决问题。\n书评\n点评"},"Personal/Book/个人成长/学会写作:自我进阶的高效方法":{"title":"学会写作:自我进阶的高效方法","links":[],"tags":["阅读/个人成长-人生哲学","阅读/笔记"],"content":"简介\n\n书名《学会写作自我进阶的高效方法》\n作者 粥左罗\n分类 个人成长-人生哲学\nISBN9787115510556\n出版社人民邮电出版社\n\n概述\n大多数人都理解错了写作认为只有依靠写作为生的人才需要学习这门技能。其实写作是生存技能人人都需要人人都能学好。如今普通人改变命运、实现阶层越迁的机会越来稀缺写作正是当下一个很好的机会不需要强大的资源和背景以及人脉积累只需要一台电脑和一颗想要改变、敢于尝试的心。2018年3月在人人都说微信红利殆尽时作者创立自媒体粥左罗仅靠写原创文章1年就积累了40万粉丝基于3年爆文写作经验他系统总结了非常具有操作性的写作技巧希望让更多人学会写作而且能靠写作赚钱。如何从零开始成为写作高手《学会写作自我进阶的高效方法》给出很好的解释而你需要做的就是马上行动开始学习开始写作。因为这项具有明显复利的技能越早开始学习越好一旦形成别人无法在短时间内超过你时间就是壁垒。\n划线\n\n写作是倒逼成长的绝佳方法\n\n\n写作是抗攻击性最强的技能\n\n\n别废话直接开始写。别废话直接开始写。别废话直接开始写。\n\n\n这个行业影响力非常重要。有一个可以快速提升影响力的方法就是经常在知乎和公众号上发表文章文章内容不限可以是研究报告、行业见解等。\n\n\n若只是这样练习你可能一辈子都写不好。因为在写作方面新手与高手的差距除了遣词造句能力还有一个更核心的东西——思考水平。\n\n\n知道了写作的内核是思考水平于是你开始每天绞尽脑汁地思考训练思维、提升认知以求提高写作水平。但若只是这样练习我依然可以说你可能一辈子也写不好。因为在写作方面拉开大家思考水平的也有一个核心指标——你的输入。\n\n\n持续、大量、优质的输入\n\n\n讲完这些我们可以给写作重新下一个定义写作是对输入进行思考后的输出。因此提升写作能力的三个核心要素是输入、思考、输出。\n\n\n要带着目标和预期阅读要养成边读边思考甚至做笔记的习惯要更聚焦进行主题式阅读好内容要反反复复读阅读时要带着批判性思维和学习的心态在阅读过程中要不断代入自己的工作和生活场景。\n\n\n只有公开写作才是真正完整的写作\n\n\n只有进行公开写作你的文字才能帮助你打造个人品牌帮助你高效连接人脉和资源。\n\n\n提供新知创造价值\n\n\n我用换脑、主动娱乐、被动娱乐、自控力、心流、边际效应、峰终定律等概念\n\n\n比如在最后一个维度上我写的是如果你是一个“怪物”一线城市允许你做自己。\n\n\n30岁不结婚你就是“怪物”。结了婚不生孩子你就是“怪物”。好好的事业单位不干你就是“怪物”。你大学毕业后不考研你就是“怪物”。你夏天穿个超短裙你就是被人说闲话的“怪\n\n\n容易理解不能高冷\n\n\n就大众阅读来说好的内容是那些社会中大多数人踮起脚尖恰好够得着的内容它不会对大多数人的智力和学识构成严峻的挑战同时又能让大多数人感受到阅读比自己水平高一点点的内容时的美好。\n\n\n真诚沟通不端不装\n\n\n《写给每一个渴望向上生长的你》\n\n\n但几乎篇篇是精华在这里我不用费尽心思想标题只需要把内容做好就可以。为什么呢因为在知识星球里写文章核心目的只有一个用最好的文章服务好社群成员。所以对于所写的文章不用考虑阅读量不用考虑后续传播我安心写好内容即可。\n\n\n有目的地写作要做到三点一是明确写作目的二是明确阅读对象三是明确阅读场景。\n\n\n双方既是信息发送者又是信息接收者。\n\n\n写作是典型的单向沟通。你写对方读或者对方写你读这就是写作最大的缺陷。\n\n\n1采用平等的姿态、分享的口吻\n\n\n我们写文章时不论写的是故事型的、观点型的还是干货型的都要以分享的口吻来写不要以说教的姿态。\n\n\n写作的时候一定要记住作者没有智力优越感时才能给读者创造阅读愉悦感。\n\n\n我的助理写过一篇有点失败的文章题目是《放不下手机你可能是“屏幕上瘾症”》这篇文章的一大败笔就是中间有一大部分内容看起来像产品说明书没有对象感没有聊天感只是单纯地传递信息文章读起来枯燥无味。\n\n\n这一节我们是以沟通的角度讲写作时的用户思维那么沟通的效果有几层最高一层是什么\n\n\n个心理学概念叫“孕妇效应”\n\n\n因为我写文章时的出发点不是卖产品而是回答这样几个问题考虑读者看到题目点进来后我能给予他什么他能得到什么然后再去想在这个基础上我如何自然而然地把我的产品推出来。\n\n\n写作者常有一个思维误区我只管把文章写好看不看是读者的事不看是他的损失。\n\n\n用户思维的背后是产品思维产品思维里非常重要的一项是服务思维。比如你开一家火锅店你的食材再新鲜味道再美味但服务很糟糕你的生意也不可能红火。\n\n\n写作者的服务逻辑应该从哪些方面入手1更直接易懂又有吸引力的标题。2颜值更高的封面图和文章配图。3提高读者阅读效率的排版设计。4更及时地在评论区和读者互动。\n\n\n我也想写但总是不知道该写什么怎么办\n\n\n你对这个世界要有点意见\n\n\n包装得更犀利《是金子得选对地方才会发光》改成《职场最大的谎言是金子在哪都会发光》包装得更有品位《孩子的教育是对未来的投资》改成《投资孩子教育就是投资你的未来》包装得更有优越感《培养自己的“静能量”》改成《高手都在培养的自己的“静能量”》\n\n\n罗振宇们靠不住薛兆丰们靠不住》一文中我要论证“再好的方法都不能适用于所有人”\n\n\n做加法是为了提高文章的信息总量做减法是为了提高文章的价值密度。\n\n\n这个技巧需要你的耐心、细心。对于文章你要一句一句地去读然后一点点修改。但只要你这样做了你的文章立马会上一个档次。\n\n\n其实所有事情的发生都是从因到果从过程到目的从方法到成绩。我们梳理事情时也是如此但当我们表达出来的时候就要全倒过来。所以写文章时一定要记住一句话用演绎推理来构思用归纳推理来呈现。\n\n\n1按重要程度排序\n\n\n2按因果关系排序\n\n\n3按结构关系排序\n\n\n4按时间顺序排序\n\n\n5按推进步骤排序\n\n\n摆事实讲道理\n\n\n某天你等红灯时一个失明的人站在路口不知所措。你正准备去帮他一位姑娘跑过去扶着他过了马路你心里会有遇到“同类”的感觉因为她做了你认为对的事情这就是共鸣。\n\n\n帮你表达了内心的观点。所以这件事会让你感到“与我相关\n\n\n职场潜规则做得越多死得越快。你的勤奋才是你失败的真正原因。痛苦是你的天分。\n\n\n犀利犀利就是要一针见血要足够震撼人心。永远都要建立做事的优先级除了最重要的事其他都不重要。你的拼命努力只是别人的工作标配。我真的瞧不起你因为你不思考。在中国有2000万大学生在假装上课。\n\n\n这个案例就是证明“坏运气是好运气开始”的绝佳案例很多用户看了都被说服了尤其是正在经历坏运气的用户看完会觉得受到安慰说不定就会转发朋友圈也去表达你要论证的这个观点。\n\n\n因为一切文章的初稿都是狗屎这句话是作家海明威的金句之一虽然有点极端但很有道理。\n\n\n茅盾说“练习写作的秘诀是不怕修改。”\n\n\n看结尾有没有扣题能不能制造共鸣、引发话题等以及最核心的——能不能刺激读者主动分享文章。\n\n\n“陪衬机制”的概念。但它在论证这一观点时用了这样一段话。比如你给领导写报告如果时间充足第一稿可以糙一点因为无论怎样领导看完都会提出意见让你改所以第二稿要憋足劲搞得完美一些对比之下比第一稿好那么多通过率自然也高。再比如如果你是女孩找闺蜜逛街就不能找和你颜值差不多的要找比你差一点的道理你自然懂。这个案例就有价值观不正的嫌疑容易招来非议。\n\n\n我们应当先把不必要的话、不必要的字狠狠地删去像农人锄草那样。不要心疼一句好句子或一个漂亮字假若那一句、那一字在全段全句中并不起什么好的作用。文章正像一个活东西全体都匀称调谐就美孤零仃的只有一处美可是跟全体不调谐就不美。\n\n\n这是我们打磨细节的第一步删、改。删无用的改能用的。你要记住一篇好的文章不是一句话好也不是一段话好而是细节、整体上都很好。\n\n\n结果刷朋友圈时我越刷越委屈甚至气愤这期间他竟然更新了5条朋友圈。\n\n\n第二读给别人听按别人听后的反应来修改。唐代诗人白居易为了把文章改得通俗易懂常常把写好的诗文读给老婆婆听一直要修改到让她听懂为止。\n\n\n著名主持人杨澜说过一句广为流传的话没有人有义务透过你糟糕的外表去发现你内在的美。\n\n\n服装搭配方面有一个三色原则指的是全身上下的衣着应当保持在三种颜色之内否则就容易混乱。\n\n\n以我们按手机屏幕大小总结出一个大概标准不超过5行字为一段会有比较好的阅读体验三四行一段是比较舒服的一段文字最好不要超过8行。一般手机屏幕显示的行数大概是20行加上留白的空间一般控制在一屏显示34个段落比较合适。\n\n\n对很多人来说写作最大的阻碍不是技巧而是一种病一种时髦的病——拖延症。\n\n\n第一明确截止时间因为截止时间就是“第一生产力”。一件事如果没有最后期限没有非做不可的理由就很容易造成拖延症。\n\n\n当你设定了截止时间后你要预估你的能力设想你以最高的效率多久可以完成然后从截止时间往前推推出你的开始时间。从开始时间到截止时间就是你的写作周期在这个周期内你的效率处于爆发状态。\n\n\n当时我看到李安的一段话他说他是不可知论者世上没什么定论任何可以讲出来的道理都是一种偏见。\n\n\n想在写文章之前就想清楚怎么写就能写得好这不可能。我写了300多万字还是想不清楚一篇文章还要打磨半天所以不要抱有完美主义倾向你要记住写完之前完成最重要写完后完美最重要。\n\n\n第4节 如何用动词、名词、形容词\n\n神经心理学认为人的爬行脑也就是控制人欲望的那部分大脑更喜欢视觉化的信息而不是抽象的信息。所以我们进行内容表现时要多做视觉化表达少用抽象化表达。具体来说就是两个技巧少用形容词多用名词、动词。\n少用形容词\n文案广告圈有个不成文的定律最好不用形容词。\n你想想看在经典的广告中我们确实几乎看不到形容词。\n笔记\n\n它不能高冷不能让大多数人望而却步它不能低俗不能只迎合人们的欲望。\n\n💭 雅俗共赏\n\n但越不去做就越觉得难最终陷入死循环。\n\n💭 节奏感,正反馈\n书评\n点评"},"Personal/Book/个人成长/底层逻辑":{"title":"底层逻辑","links":[],"tags":["阅读/个人成长-人生哲学"],"content":"简介\n\n书名《底层逻辑》\n作者 吕白\n分类 个人成长-人生哲学\nISBN9787572603174\n出版社湖南文艺出版社\n\n概述\n95后毕业新人从月薪3000到年入百万的人生蜕变写给迷茫又有野心的年轻人。普通人学习方法厉害的人直击本质比别人更快速更高效。想得多、盲目干、怕犯错……如果你想成功却找不到方法请翻开这本书未经思考的盲目努力是一种自我消耗。年轻人最大的问题并不是懒恰恰是太努力却没用对力想得太多却不得要领普通人只知道学习努力的方法而聪明人懂得研究事情的底层逻辑。写给非常迷茫又非常有野心的年轻人的人生逆袭指南。作者吕白分享了自己从一个普通“95后”小镇青年成长为行业精英的蜕变过程。通过介绍人生逆袭、突破阶层、向上进阶、锚定未来4大模块传授非常实用的45个思维方法帮助年轻人跳出时间管理、埋头苦干、逃避犯错、盲目结交人脉等努力的误区更新认知系统真正做到一眼看穿事物背后的本质规律比别人行动更快速、成果更高效。\n划线\n\n你需要断舍离做人生的减法。专注是稀缺品人能在一段时间内专注地做好一件事就很好了少就是多请务必坚持且专注。\n\n\n我们出走半生其实都是为了找到那个出发时的自己。\n\n\n河森堡说的一段话他说他的切身经验是如果你觉得某件事让你特别焦虑压得你喘不过气来那么最好的排解方法就是直接去做这件事什么都别管就是使劲做努力去推动进度。你每往前推进一点这件棘手的事情你的焦虑就会减少一分。同时你的焦虑越少推进工作的速度也就越快。只要咬紧牙关不停地推进总会有解脱的那一天。\n\n\n人生不能像做菜把所有的料准备好了才下锅毕竟成年人的世界不会事事都等你准备充分。\n\n\n所谓自律就是以积极主动的态度去解决人生痛苦的重要原则主要包括四个方面推迟满足感、承担责任、尊重事实、保持平衡。\n\n\n时间管理和自律一样本身就是一个伪命题因为你无法也不必高效地利用好每一分钟。\n\n\n请记住不要分散而要聚焦。\n\n\n慢慢做好一件事胜过毛毛躁躁地做一堆事。\n\n\n将一件事情做好并且做到极致就够了。\n\n\n尽早全力以赴打造属于你自己的启动轮你的时间价值会远远超过同龄人。并且因为你的启动轮更有意义你也能更早地为这个社会做贡献。\n\n\n相信时间的复利。做很多事情都是坚持坚持再坚持然后才会爆发……”\n\n\n“他写了一星期。你可以看看这些是他当时打印的关于这个话题的其他公众号文章其中他觉得有用的便用红笔圈出来。这是他当时标记的微博、知乎上关于这个问题的获赞最高的语句。看到一些特别好的回答他还会去找回答者私聊。\n\n\n现在是一个连傻瓜都会努力的时代。没有思考、没有总结的努力是不会带来回报的反而会让你越来越累。只有少数人才愿意停下脚步思考一下自己的目标是什么怎样可以用最低的成本达到自己的目标。这就是做事的底层逻辑学会关注事物的本质用最小成本去解决一件事。\n\n\n一个人未来成就的大小并不取决于他现在的年龄、收入、学历而取决于他内心真正的渴望。\n\n\n即使你觉得写起来吃力也很正常因为你的心被不重要的事情蔽盖太久了。现在你可以试试从事业、工作、生活、家庭、享乐5个方面入手每个方面写够20条将它们拼在一起100条就出来了。\n\n\n一个人自信的程度和他内心对成功的渴望程度成正比你不是缺乏自信你只是对成功的渴望程度还不够。\n\n\n互利互惠才能建立人脉如果你无法给予对方同等的回馈那就只是别人在施舍你罢了。”\n\n\n将欲取之必先予之。想要进入一个圈子首先要学会让利。”\n\n\n在得到之前你得先学会让利。\n\n\n每一次与不同领域的人对话我都仿佛在跟一个手握武功秘籍的人过招在一次次提问和你来我往的回答中我逐渐明白了如何将创造出爆款文案的秘籍延伸到短视频领域在小红书上怎么“从0到1”地做内容。\n\n\nLess is more\n\n\n梧高凤必至花香蝶自来只有自己变得优秀你才能遇到更优秀的另一半。\n\n\n工作能力是这个世界上最不值钱的东西。我听很多人说过这句话。他们说自己工作能力最强的时候最有创造力的时候却是工资最低、最赚不到钱的时候。反而到了后面通过行业红利、房地产红利和各种跳槽才赚到了钱。\n\n\n其实不管是谁只要在一个行业里待久了思维就会有局限性所以我们要多和不同行业的人聊天他们思考问题的方式和思路跟我们是不一样的。他们的一句无心之言也许就能成为我们破局的关键。思维落地培养你的跨界思维前不久一个做环保\n\n\n任何时候向领导或其他人做汇报、讲事情都要结论先行以上统下归类分组逻辑递进。\n\n\n领导喜欢的是省心的员工把一件事交给他之后他就能不拖泥带水地去做而且不需要领导过问就懂得及时汇报反馈最后出色地完成任务。\n\n\n少部分人主宰着社会发展一部分人维持着社会发展还有一部分人只能在社会中随波逐流最后结束自己平庸的一生。\n\n\n身处二三线城市的好处是你的人力、物力成本会很便宜但要记住你的大脑要在一线城市。\n\n\n包含着最真实的切身体验这其中的艰难困苦、喜怒哀乐、酸甜苦辣都只能自己去感受因为世上本就没有感同身受这回事。\n\n\n你们知道了但是我们做到了。\n\n\n在思考之前过去的只是时间在思考之后过去的才是光阴。\n\n笔记\n\n脸书的创始人扎克伯格的办公室里有这么一句标语Done is better than perfect。\n意思是完成比完美更重要。\n\n💭 不要让完美成为绊脚石\n\n丰田“五问法”的故事\n\n💭 第一性原理\n\n就像爱因斯坦说的那样世界上最强大的力量不是原子弹爆炸的威力而是“复利”。\n\n💭 复利就是惯性\n\n我坚信自己将来会成为一个很厉害、很厉害、很厉害——三个“很厉害”一个都不能少——的人。\n\n💭 永远相信心想事成的力量\n\n一个人自信的程度和他内心对成功的渴望程度成正比你不是缺乏自信你只是对成功的渴望程度还不够。\n\n💭 自信源于通透\n\n我人生中的第一个100万是我把握住行业风口赚到的因为站在风口更容易赚到钱。\n2014年我开始运营微信公众号时还没有什么人涉足这个领域。我发现在一个行业中如果竞争对手比较少你就更容易脱颖而出。\n\n💭 蓝海\n书评\n点评"},"Personal/Book/个人成长/底层逻辑:看清这个世界的底牌":{"title":"底层逻辑:看清这个世界的底牌","links":[],"tags":["阅读/个人成长-认知思维"],"content":"简介\n\n书名《底层逻辑看清这个世界的底牌》\n作者 刘润\n分类 个人成长-认知思维\nISBN9787111691020\n出版社机械工业出版社\n\n概述\n如果只教给你各行各业的“干货”方法论那只是“授人以鱼”一旦环境出现任何变化“干货”就不再适用。但如果教给你的是底层逻辑那就是“授人以渔”你可以通过不变的底层逻辑推演出顺应时势的方法论。所以只有掌握了底层逻辑只有探寻到万变中的不变才能动态地、持续地看清事物的本质。在这本书中我把在《5分钟商学院》中讲述的底层逻辑的内容进行了总结与你分享是非对错、思考问题、个体进化、理解他人、社会协作五个方面的底层逻辑带你看清世界的底牌。\n划线\n\n底层逻辑+环境变量=方法论\n\n\n一个人心中应该有三种“对错观”①法学家的对错观②经济学家的对错观③商人的对错观见图1-1。\n\n\n举个例子坏人A诱骗好人B进入C的没有锁门的工地B失足摔死了。请问这是谁的错法学\n\n\n如果你是评论家可以选择法学家的立场如果你是政策制定者可以选择经济学家的立场如果将要失足摔死的就是你自己我建议你选择商人的立场——“我的错都是我的错”因为“我的损失最大”。总之谁的损失大就是谁的错。\n\n\n“法律特别可爱。它不管你能好到哪儿就限制你不能恶到没边儿。它清楚每个人心里都有那么点脏事儿想想可以但做出来不行。法律更像人性的低保是一种强制性的修养。它就踏踏实实地告诉你至少应该是什么样儿。”\n\n\n图1-2 人性、道德和法律\n\n\n法律是道德的子集是一旦触犯必然受到惩罚的道德。\n\n\n人生的三层智慧博弈、定力、选择\n\n\n每个人都是独立的个体与世界进行价值交换。价值交换只有一个原则——共赢即合作双方都可以获得价值。“我一定\n\n\n请记住雪中送炭永远比锦上添花难得多。\n\n\n人生的轨迹往往就是由那么几次关键的选择决定的。遗憾的是大多数人不知道自己有的选也没有勇气选择\n\n\n在绝望中选择生存态度的自由是人最后的自由。\n\n\n学会选择常常就是学会放弃选择一个放弃其他。选择有时比努力重要但放弃有时比选择更重要。我们应勇敢选择然后享受好处承担坏处。\n\n\n在人生中博弈是第三层智慧定力是第二层智慧选择是第一层智慧。如何博弈如何保持定力如何做出选择都决定着人生的走向——选择做某件事情凭借长期主义形成自己的定力和这个世界重复博弈。\n\n\n这时我要送给你罗曼·罗兰的一句话了“这个世界上只有一种真正的英雄主义那就是认清了生活的真相后还依然热爱它。”\n\n\n“谁用得好就归谁”。从这个角度来说钱也是一种资源谁能把钱用好钱就会归谁。\n\n\n事实、观点、立场和信仰\n\n\n我们常说一个人的表述大概可以分为两种事实和观点。事实有真假观点无对错。\n\n\n举个例子“今天很热”是不是事实这不是事实。“今天30摄氏度”才是事实。热是你的观点。\n\n\n观点观点是你对一个事实的看法。观点和你的关系比它和事实的关系更加密切。\n\n\n立场什么是立场立场就是被位置和利益影响的观点。\n\n\n信仰信仰是一套完全自洽的逻辑体系。\n\n\n每个人都有自己的信仰不要攻击别人的信仰。因为第一你不可能获胜第二你会失去这个朋友。\n\n\n[插图]\n\n\n你想把什么想法注射到别人脑中把它放在“为什么”这三个字后面就可以了。\n\n\n把谣言放在“为什么”后面是传播谣言的最佳方法。\n\n\n[插图]\n\n\n辩论的目的不是说服对方而是说服观众。\n\n\n对方的表达只是你的素材而不是你的打击对象。你的目的是利用这些素材说服观众。就算说服不了观众也要影响他们。就算影响不了全部也要影响一部分。就算影响不了他们的观点也要影响他们对你的态度。\n\n\n辩论的目的甚至不是改变观众的观点而是改变观众的态度。态度改变了他们会自己改变观点。\n\n\n普通和优秀的差距在于解决问题的方式不同\n\n\n假设—验证—结论—调整\n\n\n[插图]\n\n\n为了印证假设而不辞辛苦、不嫌麻烦地去验证假设然后得出结论最后做出调整。\n\n\n就事论事不要被立场左右。\n\n\n一是抛弃经验放弃想当然不要轻易下结论要怀着空杯心态去看问题。二是运用“假设—验证—结论—调整”大胆假设小心求证得出结论最后做出调整。三是不要被利益、立场左右要就事论事。\n\n\n[插图]\n\n\n系统=要素×连接关系什么是系统?系统,就是一组相互连接的要素。这个定义中,有两个关键词:(1)要素;(2)连接关系。\n\n\n增强回路追求极端调节回路回归平衡。\n\n\n再比如你高考填志愿的时候高考咨询机构告诉你“国际金融专业是热门”。于是你报了国际金融专业。然而大学毕业时你才发现最热门的是人工智能而国际金融专业毕业的很多学生找工作很难。是高考咨询机构骗了你吗不是。是因为在你上大学的这四年里商业世界发生了重大的变化。\n\n\n分析问题的时候记住五个关键步骤一是找到核心存量。二是找到关键因果链。三是找到增强回路。四是找到调节回路。五是考虑滞后效应。\n\n\n凡事皆有流程只是效率有高低之分。\n\n\n制度是规定是契约关注的是结果流程是基于时间线做一件事的过程关注的是过程而系统是内部各个要素、变量之间相互关系、相互作用的整体关注的是各要素之间的关系。无论是流程、制度还是系统其实都是用来解决问题的。普通的人改变结果优秀的人改变原因顶级优秀的人改变模型。改变制度是改变结果改变流程是改变原因改变系统则是改变模型。\n\n\n你看从赤道的小实验不停地刨根问底可以有很多不一样的发现得出很多结论这就是刨根问底的逻辑思维。\n\n\n证有不证无以偏不概全证有靠举例概全靠推理\n\n\n[插图]\n\n\n进化岛社群里曾有同学问我“真正凭良心做生意到底能不能赚到钱”我回答他“也许你的心中有个错误的归因。凭良心做生意的人没赚到钱问题通常不是因为他有良善的而是因为他没有商业的。不能把脑的问题归于心。”\n\n\n“读书有什么用那个××一本书也没读过不也身家几千万了吗”你怎么回答你可以说“他的财富撒了谎。终身学习才能大概率成功。我羡慕他但是他的运气不一定会降临在我身上。”\n\n\n[插图]\n\n\n一个人一旦在低层次形成了逻辑闭环可能就无法前进了。因为所有的问题在他的逻辑闭环之中都是可以解释的。\n\n\n离事实越远离阴谋论就越近。\n\n\n这个公式的最大谬误是用“天”作单位使人们产生对期数的过度高估\n\n\n本金1+收益率)时间-欲望=财富自由简单来说,这个公式指的是只要非劳动收入大于消费欲望,就达到了财富自由。\n\n\n大家要有一个清醒的认识创业成功非常重要的因素之一就是运气。\n\n\n要有自己独立的战略坚定地执行自己的模型。\n\n\n概率思维是你要心平气和地承认就算你做对了所有事情你成功的概率也不高比如在今天的互联网行业成功的概率可能只有约5%;在认识到这一点之后,再思考应该用什么方式提高成功的概率\n\n\n吴军老师在得到开设了六门课程分别是《硅谷来信》《谷歌方法论》《信息论40讲》《科技史纲60讲》《吴军讲5G》以及《数学通识50讲》。从信息论到科技史到5G通信技术到数学吴军老师的涉猎之广、研究之深让人深深叹服。\n\n\n(1)任意两个点可以通过一条直线连接。(2)任意线段能无限延长成一条直线。(3)给定任意线段,可以以其一个端点作为圆心,该线段作为半径作圆。(4)所有直角都彼此相等。(5)若两条直线都与第三条直线相交,并且在同一边的内角之和小于两个直角和,则这两条直线在这一边必定相交。\n\n\n一家公司的愿景、使命、价值观其实就相当于这家公司的公理。公理直接决定了这家公司的各种行为往哪个方向发展。所有的规章制度、工作流程、决策行为都是在愿景、使命、价值观这些公理上生长出来的定理。它们构成了这家公司的公理体系。\n\n\n而在生活中有一类决策是需要涉及别人的。涉及别人的决策逻辑我们把它叫作博弈论。\n\n\n在零和博弈中你要一直保持清醒你要的是全局的最优解而不是局部的最优解。\n\n\n要素是系统中你看得见的东西关系是系统中你看不见的、要素之间相互作用的规律。我们要看到要素看到要素之间的关系更要看到这些关系背后的规律。\n\n\n在这个世界上有一些人一旦在某个领域获得了成功就几乎可以在任何一个领域都获得成功。\n\n\n可是怎样才能获得更大的影响力呢你需要三种能力演讲能力、写作能力以及建立人脉的能力。演讲和写作是\n\n\n最可怕的能力是获得能力的能力。最可怕的效率是伸缩时间的效率。最可怕的杠杆是撬动人心的杠杆。\n\n\n愿你拥有最可怕的能力达到最可怕的效率撬动最可怕的杠杆。用它们换回属于你的全世界\n\n\n总体来说边际交付时间越高的越不可能获得指数级增长边际交付时间为零的才有可能实现指数级增长。对于边际交付时间不为零的行业有一种方法可以获得指数级增长就是把边际交付时间不为零的服务的部分切掉跟别人合作自己只做那些抽象的、边际交付时间为零的部分。\n\n\n什么是服务业我们先来定义“产品”和“服务”边际交付时间为零的叫产品边际交付时间不为零的边际交付时间越高的越是服务。\n\n\n我对她说当你比他人只强一点时或许他人会嫉妒、不服会攻击你甚至诋毁你。然而当你足够强大以至远远超越他人时他人连嫉妒的勇气都没有剩下的只是对你的仰望和深深的敬畏他们会爱你、怕你、敬你。\n\n\n当你想增长10%时你是希望在原有路径上获得自然增长。逻辑不变血战向前并不容易。但是如果你想获得的是10倍的增长那一定不是在原有道路上走出来的你必须寻找一条新道路。苦思冥想不断尝试只要找到优化的战略就可能瞬间提高10倍。\n\n\n创业时更重要的是选择而不是努力更重要的是思辨而不仅仅是执行。用我的“千百十个”逻辑去理解那就是百位战略上进一步抵得上个位管理上进百步。你不是要比别人强10%而是要强1000%。\n\n\n当你觉得生活中到处是“烂人”时那是因为你生活在“烂人”的圈子里。你要做的不是改造那些“烂人”更不是变成比他们更烂的人而是遵循特劳特先生的教诲让自己不断“涨价”让自己配得上更好的圈子。这才是正道。\n\n\n你站在1楼有人骂你你听到了很生气。你站在10楼有人骂你你听不太清楚你还以为别人在和你打招呼。你站在100楼有人骂你你根本看不见也听不见。\n\n\n只有优秀的人才拥有有效的人脉。\n\n\n一个人的财富基本盘由两个组成部分第一你自己的本事第二你和其他人联结的本事。\n\n\n如果想要积累人脉你能做的就是不断积累自己的价值并不断输出自己的价值。当你能够帮到越来越多厉害的人时你的人脉才会越来越广人脉的质量也会越来越高。\n\n\n谈恋爱也是技能但很可惜你一辈子也谈不了几次恋爱所以因为缺乏练习自古以来地球人都是不擅长谈恋爱的等你真的“习”得了这种能力估计已经用不上了。\n\n\n什么叫君子自污就是你浑身雪白地出门就会有人忍不住往你身上泼脏水对你满满的恶意。人们不相信“洁白无瑕”或者不能忍受有人洁白无瑕。\n\n\n对方问公司的愿景是什么价值观是什么战略方向是什么未来要做什么事情谁知道他公司的五个高管的回答都不一样。\n\n\n所以只知道What却不知道Why就没有动力。理解了Why才有可能做到知行合一。但知道What也知道Why这也不够你还得知道How。How就是做事的方法和步骤。\n\n\n如果你的员工是松木你就把他做成“门窗”好了是樟木你就把他做成“箱子”是黄花梨那一定要把他打造成“精美的家具”。\n\n\n[插图]\n\n\n金老师说“企业就像一棵大树树根就是系统结构树干就是战略树冠就是市场果实就是产品叶子就是品牌。”\n\n\n“打比方”的能力本质上是一个人洞察事物本质的能力。\n\n\n打好一个比方要经过三个步骤第一步洞察复杂、陌生事物的本质第二步匹配到大家熟悉的事物第三步用熟悉的解释陌生的。\n\n\n小米的智能家居有很多设备比如电视机、路由器、门禁、电饭煲、扫地机器人、空气净化器等它们都可以用一个统一的App来控制。这个App就相当于所有小米家居产品的遥控器\n\n\n“遥控器电商”。你是不是一下子就明白了这个管控所有小米设备的入口的价值并且还感觉特别透彻和形象他深刻洞察了这件事情的本质然后联系到人们耳熟能详的某个东西上让你更好、更快地理解。这是一种非常强大的能力。\n\n\n“遥控器电商”“烤红薯生意”“生活耗材”\n\n\n而一旦把公司做上市了他脑中的多巴胺就没了。这个目标达成后他就需要重新寻找更高的目标。\n\n\n而多巴胺是支撑着我们攀上去的重要物质。\n\n\n世界三大法则自然法则、族群法则、普遍法则\n\n\n什么是自然法则物竞天择适者生存。或者说弱肉强食。\n\n\n因为这个大于个体目标的目标大家必须出让一部分自己的选择权和决策权给集体。这时定义出来的新的法则就是族群法则。\n\n\n遵守规矩利用规矩\n\n\n自然法则、族群法则、普遍法则。从自然法则到族群法则再到普遍法则是世界不断进步、文明不断发展的标志。\n\n\n你用的法则越高级你能换到的东西就越多。但同时你也更脆弱。\n\n\n我们要懂得用族群法则、普遍法则和世界进行价值交换同时在必要的时候用自然法则来保护自己。\n\n\n从本质上来理解水攻这个过程就是把一个军队吃了三年的化学能量转化为能一举冲垮一座城池能量的过程。\n\n\n科技又是什么呢科技也是势能。当一家公司拥有了许多专利就相当于有了许多工具利用这些工具的势能、科技的势能就能形成商业竞争中的“水攻”\n\n\n你陪客户喝的酒是做产品时没有流的汗\n\n\n如果你做的是功能型产品高性价比或许可以成为你的竞争优势。\n\n\n不是。这0.3元,其实只是社会付给你的辛苦费,我们把它叫作社会工资。\n\n\n只有别人拿不走的才是你真正的利润。\n\n\n利润来自没有竞争。\n\n\n利润来自没有竞争。任何一个行业所有的红利最终都会被竞争拉平最后大家只能赚社会工资。这时候只能通过创新来创造利润空间。否则说句扎心的话你以为你在创业其实你只是在为社会打工。\n\n\n没有KPI没有考核但是团队很有创造力公司发展得非常迅猛。这些公司让我开始相信在某些情况下没有KPI没有考核也能管好公司。优秀的人不用管理他们会自我驱动。\n\n\n为了不让规章制度限制员工工作奈飞甚至取消了考勤和休假制度。员工在认为需要休假的时候只需要与上级领导沟通好即可且天数没有上限。\n\n\n最有创造力的工作一定来自热爱来自他内在的自驱力和创造性。所以凡是从事与认知有关工作的人就不能用KPI的方法来进行激励而应该让他有更明确的愿景。\n\n\n脑子里天天想着钱的人是干不出漂亮事的。\n\n\n如果说这个世界上的管理有儒家和法家之分儒家用道德文化管理公司法家用规则(KPI)管理公司,那么,这三家公司就是典型的儒家式管理公司。\n\n\n财富=劳动×生产率。\n\n\n所以如果你想要拥有更多财富就应该想尽一切办法提高自己的稀缺性。\n\n\n——我是否在公司最稀缺的部门——我是否在部门最稀缺的岗位——我是否拥有最稀缺的资源——我现在拥有的稀缺性未来还能继续稀缺吗\n\n\n因为前面05万元那部分已经全部给她把她投入的时间和精力成本覆盖了。这时5万25万元这部分收益的分配就应该以你为主以资本为主所以应该资本优先人力劣后。\n\n\n因为在第二阶段赚到25万元你们就已经非常满意了。但是你们合伙做这个项目当时有个预期觉得如果做得好大概能赚到100万元。现在真的实现了那么这25万100万元部分就应该按照基本均衡的方式分配。所以你拿60%她拿40%。\n\n\n一切的商业模式都必须有全局性增量。如果没有全局性增量那所谓的商业模式就是把你口袋里的钱换到我的口袋里。\n\n\n一切的分钱方式无外乎优先和劣后。一切的分配方式都是固定、剩余、分成的万千组合。\n\n\n信用是一个人最大的资产\n\n\n信任是一种能力。被信任是一种更重要的能力。\n\n\n在人生的信用账户里每一次言出必行、每一次真诚待人都是对未来的储蓄。\n\n\n这个德高望重的乡绅扮演了担保的角色成为两个人信用的中介否则纷争无法调解交易无法完成。这个信用中介在商业世界中是非常重要的角色大家都愿意信任他说的话大家会听。乡绅文化就是一种信用文化。有信用的人受到尊敬有话事权。\n\n\n从本质上看我觉得人的一生是赢得信任的一生是勇敢地用责任换取信任的一生。\n\n\n那就要看高考是不是用“同一把”尺子丈量千万学生。答案是是的。高考用“分数”这把唯一的尺子丈量所有学生。高一分你就可以上清华或北大低一分你就只能明年再来。谁也不能作弊学生作弊退考老师作弊坐牢。\n\n\n公平——用“同一把”尺子丈量万物公正——选“哪一把”尺子来丈量公开——把丈量的过程展示给公众让同意公正者监督公平。\n\n\n这也是为什么诺贝尔经济学奖获得者、著名经济学家科斯说“资源总会落到用得最好的人手里。”\n\n\n初次分配负责效率再分配负责公平。\n\n\n劝酒的本质是服从性测试\n\n\n当然是无条件服从的员工更好管。让员工服气要靠领导力而让员工服从只要靠权力就行。\n\n笔记\n\n很多时候事物之间的关系并非“非黑即白”的关系而是存在着博弈和多样性。\n\n💭 逻辑跨度太大,甚至毫无逻辑可言\n\n价值观就是为共同的梦想工作哪怕公司不给你工资不给你奖金全世界的人都拦着你你也一定要做成这件事。这时你和公司不再是利益共同体不再是事业共同体而是命运共同体同甘共苦同生共死。\n\n💭 士为知己者死\n\n认知科学就像神农尝百草不断测试摸索经验最终总结出结论。而神经科学则是从基因、原理级的角度去进行思考和研究的。\n\n💭 又看到了归纳法,演绎法的一种理解方式\n\n新人“杀”进市场他的生产成本也是3元但他发现你已经把市场占领了怎么办他是不是只要卖得比你便宜一点就有优势\n\n💭 门槛\n\n润来自没有竞争\n\n💭 利润来自垄断\n书评\n点评"},"Personal/Book/个人成长/当下的力量(白金版)":{"title":"当下的力量(白金版)","links":[],"tags":["阅读/个人成长","阅读/笔记"],"content":"简介\n\n书名《当下的力量白金版》\n作者 埃克哈特·托利\n分类 个人成长-励志成长\nISBN9787508661766\n出版社中信出版集团\n\n概述\n《当下的力量白金版》堪称心灵读物经典作者埃克哈特·托利指出了我们日常痛苦的主要来源——被大脑思维所控制、焦虑过去和未来而非活在当下。但实际上我们只能活在当下活在此时此刻。通过向当下的臣服你才能找到真正的力量获得内在的智慧和真正的喜悦。作者在《当下的力量》中提出了几个非常实用的方法让自己认清时间的幻象活在当下。《当下的力量》对于普遍焦虑、抑郁、压力大的现代大众读者来说是一本切实有用的好书将让我们认清时间的幻象活在当下找到真正的力量发现平和与宁静的入口。\n划线\n\n你生存在这个世界就是要使宇宙的神圣目标得以实现。你看你是多么重要\n\n\n我们都知道ABC理论A是引发你情绪的事件B是你的信念或你对事情的诠释C就是结果即你的负面情绪。通常当人们不喜欢C的时候都会去找A的碴儿尤其是与创造A有关的人。\n\n\n。与其去改变外在的人、事、物不如改变我们自己的内心来得省事省力。而你会发现当你转变了内心的状态之后环境也会随之转变这就是所谓的“境由心转”\n\n\n活在当下。\n\n\n但是我们多少人还是活在过去之中不肯放下未来还没有来临你也根本不可能去掌握它。你所能拥有的不就是当下这一刻吗\n\n\n像《当下的力量》这样的书十年甚至几十年才能产生一本。它不仅仅是一本书在这本书中还有活生生的能量当你读这本书时你可能会感受到这种能量。它有一种惊人的力量\n\n\n我生命中的每一刻都是奇迹。这绝对是真的不管我是否能够去实现它。\n\n笔记\n\n他认为所有人类的疯狂行为都是出自无意识受到我们从小被制约的人生模式操控。比如说你对一件事情的反应、看法、做法等通常都有一定的轨迹可循但是你不一定喜欢或赞同它们。所以从某种程度上来说我们都是一台被编好了程序的计算机\n\n💭 潜意识\n\n在书中作者还提到了一个我们受苦的肇因痛苦之身pain body第二章。痛苦之身是我们内在的一个能量场它是我们过去未被合理表达和适当释放而累积下来的负面情绪能量场。\n\n💭 痛苦需要缓释\n\n人类受苦的根源来自我们大脑的思维第一章。思维其实也不是问题问题出在我们无法控制自己的思维反倒成为思维的奴隶成为自己“强迫性思维”的受害者。\n\n💭 除了身体上的痛苦,其它任何痛苦都是虚无缥缈的\n书评\n点评"},"Personal/Book/个人成长/我的第一本人生规划手册":{"title":"我的第一本人生规划手册","links":[],"tags":["阅读/个人成长-励志成长","阅读/笔记"],"content":"简介\n\n书名《我的第一本人生规划手册》\n作者 柏永辉\n分类 个人成长-励志成长\nISBN9787520814669\n出版社中国商业出版社\n\n概述\n作者用解剖学教科书的理念分别在人生规划大方向资源配置时间管理专业知识学习以及职场实战落地的五个角度针对同一个“人生规划”的问题做了深入浅出的系统性交代能帮助读者快速走出人生迷茫的盲区。全书主要阐述如何基于自身的情况来快速定位自己的人生规划的不同阶段位置制定接下来中长期的发展规划然后逐步盘活自己的人生\n划线\n\n10%的规划原则当你想要去做十年规划的时候我们建议用一年的时间去思考规划当你想要去做一年规划的时候我们建议你用365天中的36天去思考规划\n\n\n真正原因是你的后防线你的系统能够支撑你有多少时间来成就自己很多人富有才华却因为后防线不稳定没有修炼自己技能的机会最后错过了时间遗憾终身。\n\n\n学和习的比例1:61:10的比例\n\n\n你就知道从知道知识到掌握知识再到应用最后到内化成自己的至少需要6小时的训练时间。\n\n\n人生规划可分为四个规划阶段首先是学业规划之后是职业规划接着是事业规划最后是创业规划四者合起来称为人生规划。\n\n\n我们的一生究竟应该怎么过如何平衡自己的工作和生活如何找到自己的人生方向对应的答案也是五花八门\n\n\n我如何修改自己的命运剧本尤其是在资源极度匮乏的情况下。\n\n\n想要锁定某一个问题的话我们可以用不同维度的分析来交叉验证。\n\n\n从大量对标和案例中定位自己\n\n\n人类社会的永恒挑战是如何应对各种未知信息带来的不确定性。学会如何在不确定的环境下进行人生决策一直是我们的永恒话题。\n\n\n你永远都猜不到以后的生活是什么样子。\n\n\n如何基于每一个人的当前状态通过什么样的改变来逐步盘活自己的人生\n\n\n不少人看上去在非常努力地学习其实是在努力学习各种“不劳而获”的投机性技巧好最终达到获得更高收入的目的所以当不少人开始学习自身能力无法承载的知识体系的时候打着“以学习目的来偷懒”的谎言也变得堂而皇之了。\n\n\n你父辈的收入决定了你的起跑线而你的收入同时决定了你孩子的起跑线和父母辈的晚年归属。\n\n\n为什么一生下来父母就帮我们决定我们长大要做什么从来没人问我们想做什么。\n\n\n先生存再发展后实现自我价值”评估自己现在定位在哪里以及现阶段的自己应该做什么。\n\n\n因为你的两条腿的长短其实是有一两厘米长短的细微偏差的\n\n\n走直线是最快逃出草原的最佳方法即便草原的植被和树木都在悄悄移动只要无视它们的位移干扰沿着直线就可以走出去了。\n\n\n我们基本上能够感受到大多数低收入家庭的困窘在于他们每天要花费海量的时间来为生活琐事奔波忙碌光是维持生存就已经很辛苦了更别说改善生活条件了。\n\n\n你的\n\n\n家庭人均月收入\n\n\n当自己的家庭人均月收入还停留在1万元人民币以下的时候这时候你需要思考的是谋生级别的修炼这个阶段主攻专业知识的修炼当自己的家庭人均月收入在1万2万元人民币的时候你可以开始考虑中层管理者的管理能力修炼这个阶段主攻项目管理的投入产出比以及组建团队的修炼当自己的家庭人均月收入在2万3万元人民币的时候你可以开始考虑眼界和格局的修炼这个阶段主攻战略地图中的项目组合收益和成就他人的修炼当自己的家庭人均月收入在3万元人民币以上之后你可以试试看去做一些有情怀实现自我价值的事情了。\n\n\n先生存再发展后实现自我价值”的三步骤\n\n\n第一个里程碑累积50万元。第一个50万元的财富获取代表你在这个社会上存活下来的标志。\n\n\n在这个阶段你唯一能够和同行拼的能力就是反馈速度和反馈效率以及结果的专业度然后逐渐让自己变得值钱。\n\n\n于是我们会问一下咨询者你看了多少本关于自己行业所在的岗位专业书籍理解程度是多少每月看多少本专业书\n\n\n到了这个阶段是开始冲刺累积1000万元的阶段了有些人会很快赚到但是有些人一辈子都挣不到这笔钱毕竟资源协作分工的时候总资源就这么点儿这就是现实。\n\n\n我需要学习政治和打仗然后我的儿子才能学习地理、自然、造船、航海、商业、农业再之后我儿子的儿子才有机会学习绘画、诗歌、音乐、雕塑、挂毯和瓷器。——美国第二任总统约翰·亚当斯\n\n\n你没办法好好创业成功是因为你没有一支执行力非常强悍的团队来落地结果如果想养一个团队你必须有一个特别好的营利性项目而且你得负责协同和跟进如果你没有跟进和管控一个项目的能力是因为你不懂统筹协调没有相关的管理能力如果你统筹协调的能力不好就无法带好团队如果你听话照做都做得一塌糊涂那必然是你专业知识没有很好地掌握为什么你很努力地学习专业知识却又学不会很可能是你不知道自己的天赋优势是什么如果自己发挥不出来自己的天赋优势自己的童年大概率过得不怎么好。\n\n\n生命时钟模型——人生资金收支占比细分\n\n\n当你的创业生涯规划无法开启的时候那说明你的事业生涯还需要重修。当你的事业生涯规划无法发力的时候那说明你的职业生涯规划没有做好积累。当你在困惑自己的职业生涯规划的时候那说明你的学业生涯规划没有做好规划。当你在迷茫学什么专业的时候那说明你自己都还没有想明白自己的天赋是什么。\n\n\n任何你想要跳过的基本功都会在下一个关卡非常有耐心地等着你来补课和重修。你以为你可以弯道超车来加速结局却是拐弯的时候栽倒在阴沟里。\n\n\n因为岗位薪酬设计和工作价值的关系你大概率可能会被锁死在某一个范围内。如果你想要破局的话唯一的方式就是重新学习可以承载310倍及以上收入的知识体系或者切换到更高收益的行业跑道或公司。\n\n\n所谓的“终身学习者”的痴迷学习其实是一种逃避真实世界的历练而社会其实已经无形中制定好了各种规则来一轮又一轮筛选你并且暗中给你标记好了你的估价而你自己却不自知\n\n\n每个人都是自己人生的设计师。\n\n\n其实很多人的命运没有无限可能光是活着就已经耗尽很多力气更不要说梦想了任何超越自身能力范围的跃迁成长弯道超车都会在下一个阶段栽跟头。\n\n\n在1%的关键时刻选择比努力更重要在99%的日常生活中,努力比选择更重要。\n\n\n不要将必要开销和你的欲望混为一谈。你自己和你家人的欲望永远不是你的薪水所能满足的。因此假如你的收入是用来满足这些欲望的话那么钱必定会花光。\n\n\n你所知道的就是我希望你知道的于是你以为你知道了很多\n\n\n第一步寻找。请到搜狗微信网站搜索和“人力资源”相关的各种关键字看看能对标上多少个公众号\n\n\n它们是一个月更新一次还是一周更新一次还是一周更新三四次还是日更新的这个阶段你需要注意的是哪些是假勤快哪些是真勤快。\n\n\n第三步收集。找到自认为觉得不错的1050个人力资源的公众号用Word文档复制粘贴一个公众号里面的最近50100篇关于人力资源的公众号文章重复50遍直到收集全这些文章为止\n\n\n第四步分析。这些专业文章都在讲什么人力资源有哪些高频词汇哪些是我自己一直在工作中用到的模块那些年薪30万50万元的人力资源经理都在做什么样的工作内容我的岗位和他的岗位之间的匹配度和差别是什么\n\n\n唯一需要注意的就是尽可能找知识的源头而不是在自媒体和信息流媒体上找那些低质量的口水文章这类文章多半是刷浏览量的不具备科学性和严谨性。\n\n\n如果你想要“思想越狱”的话自己也可以试试看在购书网站上查找100本专业书在靠谱的行业网站上查找100篇相关的文章然后整理成资料合集配合上我在第一章节说的“信息10问”来不断校验自己的思维偏差。\n\n\n一代人有一代人的使命。\n\n\n这三条命分别是生理意义上的生命、行业范畴上的天命、人类范畴上的使命。\n\n\n用一辈子的时间投入两辈子的精力去成就一个可以影响三辈子人的事业最后让第四辈的玄孙都引以为傲的那么这辈子就值了。\n\n\n你的规划思考能够到达多远呢是10天的规划还是100天还是10个月还是10个季度还是10年甚至是100年呢为什么很多人的计划只能是短期计划而不是中长期计划呢\n\n\n当你明白了传承背后的意义你就可以明白了另一半的重要性另一半在做家庭稳定器时的重要性配偶的言行举止以及精神世界和认知观对家庭对长辈对下一代的思想构建至关重要。\n\n\n先生存后发展再实现自我\n\n\n如果你的年薪在15万元以下基本代表你还在生存线上挣扎建议你每月把70%的精力放在专业知识上无论是在公司还是下班后。因为当你还没有夯实自己的专业知识的时候月收入一定没有过万于是70%的精力放在专攻专业知识上,一定有用。\n\n\n家庭人均月收入1万元的生存关”、“家庭人均月收入2万元的发展关”以及“家庭人均月收入3万元的自我实现关”\n\n\n探索阶段、学习阶段、适应阶段、收获阶段、完成阶段\n\n\n生存关冲发展关的20%进度探索阶段生存关冲发展关的40%进度学习阶段生存关冲发展关的60%进度适应阶段生存关冲发展关的80%进度收获阶段生存关冲发展关的100%进度:完成阶段。\n\n\n通过这些年的记录我会察觉了什么我发现了什么\n\n\n记录下来自己在这半年中学习了哪些知识体系见了哪些高人帮助了哪些朋友和陌生人参加了什么样的活动推进了什么样的人生主线任务。\n\n\n同样的道理也可以给你省下很多焦虑的时间你可以记录下来然后等时光流逝让10天后的你100天后的你10个月后的你10年后的你去思考这事情重要吗还能真的感同身受那一天你的感受吗说不定第二天大脑自动清库存又嘻嘻哈哈像一个没事人一样了根本不知道昨天发生了什么。\n\n\n首先切换到“今天明天后天待办事项清单”不断获得自己人生的三天自我控股权其次不断用压力测试自己的能力上限和能力下限再次保持节奏让自我指挥权变得越来越强逐步去做能够改变自己命运的事情最后盘活自己的人生。\n\n\n2016年因为在沪江CCtalk上无法继续录制课程所以我转战网易云课堂职场专栏录制课程先从免费课程开始积累人气然后慢慢开始构思录制付费课程并在2016年的月中辞职准备全身心投入进去同年年底我的“职器”课程录制完成。\n\n\n只要用心打磨好属于自己的核心产品自然而然就会有越来越多的收益让我能够养得起一个团队同时一个团队也可以助力我加速产品的推广和传播\n\n\n第一阶段好点子。第二阶段最小可行性模型。第三阶段好产品。第四阶段好产品+附属产品搭建产品组合。第五阶段:有全职团队为我助力。第六阶段:建立公司的规章制度。\n\n\n工作赚钱类计划、日常生活类计划、学习投资类计划以及娱乐休闲类计划。总的来说工作赚钱类需要占比60%左右日常生活类需要占比25%左右学习投资类需要占比10%左右娱乐休闲类需要占比5%左右。\n\n\n一般每个月都能将规划运营得很好的人基本上都是项目经理和运营经理级别的高手。因为一个月的统筹调度能力是如何投入成本和精力来创造价值并逐步实现的过程。\n\n\n作为一个××××角色我想做×××意图这样我就可以得到××××预期结果。\n\n\n作为一个××××角色我想做×××意图并且希望在××××时间期限××××多少资源投入的成本下完成这个任务这样我就可以得到××××预期结果。\n\n\n作为配偶的角色我每周的五个工作日少掉了10个小时的时间在陪伴家人上那么作为相应的补偿机制我就得在周末的家庭角色上至少多承担些家务以及和孩子陪伴的时间在这个时间段就不可以时时刻刻关注工作的事宜。\n\n\n一套好的解决方案是能够共赢并且互惠互利的一套坏的解决方案是自己利益最大化别人没有任何利益。\n\n\nMo-S-Co-W是四个优先级别的首字母的缩写发音谐音为“莫斯科”。Must必须做的Should应该做的Could可以做的Would not不要做的。\n\n\n而能够抓住事物核心的止损的基本点就是这个底线思维的核心思想你做什么都没用除非你完成了某一个核心任务、核心技能这是在时间、资源都不够的情况下做最快速决断的最佳起始点。\n\n\n什么是可以有的Could可以有可以有时间了再给。\n\n\n什么是可以没有Would not可以没有等有时间了再说。\n\n\n永远给自己留出来一部分缓冲的时间缓冲的金钱缓冲的冗余资源来让自己从容不迫而不是卡着点儿去做各种事情。\n\n\n第一类事情是创造价值的工作创作过程中不可以被他人干扰。\n\n\n第二类事情是你需要和他人协同互动才能推进的工作另一方不在无法推进。第三类事情是附加值相对低的碎片任务即使随时被打断都可以继续做的并且有别于前两者必须你自己去做的事情可以理解为番茄工作法。\n\n\n所以一天上班的9小时的时间会被拆分成3小时创造性任务、3小时沟通类任务以及3小时左右的琐碎任务。当你开始用这样的分类方法量化自己的工作内容的时候你就会知道工作待办事项的性质是什么了。\n\n\n一天至少需要找到一个连续23小时中途不可以被打扰的创造性工作任务\n\n\n当然还是有一个非常值得上班族借鉴的职场经验。一般情况下优先面对面沟通或者直接打电话说明白要做什么事情然后双方沟通协商一致之后再发一封邮件定为正式函附上相关的表格和公文附件。\n\n\n其实当你站在周计划的维度去认真思考问题的时候这个问题就变得非常简单了你只要问自己这一周想要做多少个创造类任务和哪些部门的人内部沟通和哪些客户外部沟通以及为了完成这周的主要任务和沟通工作得做哪些准备工作。\n\n\n学习的最终目的是不断纠正自己对世界的认知偏差只有看懂了客观世界的发展规律才能适应其中的趋势\n\n\n目标明确学会权衡收益与代价付出与收获。\n\n\n独立自主希望独立学习自主思考而不是被灌输。\n\n\n经验学习带入以往的经验具有特定的思维和习惯。功利性意识到学习的必要性时才会准备投入学习不喜欢被强迫。任务驱动跟工作任务相关的学习喜欢实践性主题。问题驱动喜欢现实的问题解决愿意学习解决思路。\n\n\n也就是说成人学习是以解决当前具体问题为最终目的带着困惑去学习特定知识来优化自己的技能并且通过行动来解决自身的困境而不是单纯意义上的信息积累否则和听相声、侃大山没有任何区别给你再多的信息和知识都是无意义的重复。\n\n\n比如如何让自己每月多10003000元收入如何让自己每天节约2小时时间如何让自己的工作效率加快如何管理510人的小团队下个月的营业额如何达标如何准备跳槽到收入高的公司这些都是非常实际的问题。\n\n\n废掉一个成年人到底有多简单只要不停给他新知识让他忙于学却从不实践就可以了。\n\n\n相信我们会在朋友圈看到不少工作5年以上依旧还在打卡学习的上班族用着“无效努力”来麻痹自己好给自己一个心理安慰这类人我们称为“学习爱好者”。\n\n\n“闲坐小窗读周易不知春去几多时。”\n\n\n不断试错直到找到感觉的过程称为“习”。\n\n\n但是非常可惜的是我们经常看到这样的情况一旦误会了“学习”的最终目的是什么而只是一味学新知识不是“学以致用”的话了无止境的狂热的填鸭式教育将会大行其道。\n\n\n这个禅机一般的秘密已经在《道德经》中说得非常明白了《道德经》第三十九章有云“昔之得一者天得一以清地得一以宁神得一以灵谷得一以盈万物得一以生侯王得一而以为正。”因此你“得一”了吗\n\n\n他们在年少的时候看懂了各种行业的效率转换规则各种技术白皮书知道如何让这些规则为我所用撬动杠杆得到自己想要的结果。\n\n\n用这些规则来解决专业领域的特定问题然后优化资源与资源之间的协同效率达到提升投入产出比的结果\n\n\n因为企业背后面临的真实挑战是如何拿着这些原有资源通过优化配置的方式在未来的不确定风险下赚到高于同行的收益比如如何提升设备单位时间内产出量如何提高仓库的周转率如何降低残次品的生产如何缩短研发周期如何提升客户满意度。\n\n\n所以你是自己所在领域的专家吗你的电脑里你的书架上是否有关于这个领域问题的10本以上书籍\n\n\n我们真的有必要报名学习这么多课程这么多知识吗这些知识背后的源代码的脉络和起源知识是什么整个专业知识地图的边界是什么\n\n\n先思考知识框架和分支脉络以及不同分支之间的区别和关联当看懂骨架之后再来思考不同分支专业知识的应用场景\n\n\n于是我开始停止买书有意识地给我想看的书籍进行排序和归纳慢慢我开始找到它们之间的规律了然后进行大规模的重复性剔除工作重建专业认知框架这时候要看的书籍越来越少同时看的书籍越来越专业、精深。其实没什\n\n\n这样的反向拆解能力可以理解为“逆向工程思维”。\n\n\n这会有两种呈现方式一种是所有元素全部呈现的完成时态另一种是你自己可以理解的分级状态包含你已经掌握的简单状态、入门状态还有中高级较难的状态。\n\n\n通过系着一根羊毛线时时刻刻都可以定位自己在迷宫中的方位以及被探索过地方的路线通过不断排查的方式最终找到目标这种方法其实就是计算机的经典算法中的暴力遍历的算法简称“迷宫寻路算法”或者叫作“回溯算法”。\n\n\n右手原理。\n\n\n从起点出发一直往里走遇到岔路口就做一个节点记录然后利用右手原理一直优先选择右边的路线。只要还能往里走继续推进前行直到走不下去碰壁为止于是沿着路线返回最近的上一个节点选择还没有被探索过的路线进行探索直到所有的可能性都被探索到为止。\n\n\n如何防止自己迷失其实定期做复盘工作是一件特别有用的事情。\n\n\n当你把这几年来的复盘笔记、工作日志以及任务清单都拼接起来再结合自己所在领域和专业知识框架之后整个地图全貌就会越来越清晰\n\n\n很多学习英语的“壮士”们都有一道无法逾越的心理魔障那就是心平气和看完一本英语小说或期刊。这是检验是否掌握英语的一个里程碑式的考核。\n\n\n我遇到过不少学员想要通过记录心情日记的方式来复盘自己的情绪最后发现根本没有任何效果原因就在于只是记录自己的情绪而不是记录影响自己情绪的事情步骤最后咬牙切齿在自己的日记本上写下“我永远也忘不了这一天结果过了一两个月之后再看压根也不知道那一天到底发生了什么。\n\n\n1.0阶段定性定量分析研究。2.0阶段样本库分析思考。3.0阶段学习专业知识。4.0阶段开始行动验证。5.0阶段:最终改变命运。\n\n\n你做什么事情会让你有成就却对别人没好处呢只要你想不明白这一点你就无法建立自己的“专业护城河”无法让自己变得更加强大。有时候个人成就太多对自己未必是有好处反而会因为对他人没有任何好处而招致他人的嫉恨。\n\n\n但是如果你能全方位了解各种消息你就可以更多维度地深入理解历史中的每一个人他们的所思所想所作所为没有绝对的好人坏人只是立场不同。\n\n\n知识边界、统计学、高频词汇以及练习时间。\n\n\n就是衣食无忧级别没有任何功利心没有考核指标长时间浸淫在文学世界的闲情雅致超强的鉴赏功底以及拥有这样一个氛围的家庭。\n\n\n有两种可能一方面他自己通关了但是总结不清楚其中的道理所以弟子也听不懂另一方面就是老师在教徒弟的时候有意留一手。于是一个非常棘手的问题摆在你面前如何让自己超越自己的老师\n\n\n如果你想要突飞猛进地修炼成专家甚至超越你的老师你需要的是一套更加先进的思维框架以及海量的对标数据样本再加上足够时间的“刻意练习”\n\n\n所以AlphaGo Zero通过向规则学习再加上时间的积累以及自我快速迭代学习的方式让围棋规则变化出新的排列组合而自主研发的规则成了它甩开同行的杀手锏让自己快速成了行业中的佼佼者。\n\n\n不少特别努力的小伙伴都在非常努力地在自家“自留地”上种着从别人手中得到“转基因郁金香”而只有少数派在耕耘自家的“土豆田”\n\n\n这个老师的思想启蒙了多少因此而受启发的学生、读者这些弟子中有多少弟子始终是弟子又有多少弟子是超越老师的不管这个老师有没有名先看看这个老师门下有多少个毕业通关开枝散叶自成一派的弟子\n\n\n电影中小马同学是一个经验丰富的植物学家所以他会用另一个思考维度去思考携带的土豆既是口粮又是庄稼如果计算机专家困在火星有可能就死翘翘了。正\n\n\n当你还在提桶的时候需要建造管道。——《管道的故事》\n\n\n出售自己的时间换取金钱使用自己的技术换取金钱整合自己的资源换取金钱搭建自己的平台换取金钱。\n\n\n所以无论你修炼哪一条跑道你最终都会发现只要坚持下去你都会有收获。很多人因为没有“人生钱”的时间积累、业务量积累、经验值积累贸然进入“钱生钱”的市场想要一劳永逸结果一场空我只能说成年人的世界风险收益自行承担。\n\n\n无法复盘经验教训\n\n\n从来就没什么速成出来混迟早要还的。世上从来都没有什么逆袭所有的奇迹和伟大都是熬出来的。\n\n\n因为这一类的工种没有任何核心技术含量只要培训上一个礼拜甚至半天就可以胜任剩下的都是重复劳动因此想提升收入很难但是被呼来唤去折腾的概率极高而且无法掌握自己的命运很容易因为客户或者上级一两句话而被扣奖金甚至会丢工作。\n\n\n其实吃苦的本质是让自己变得更强让自己的生活变得更幸福而在此期间如何让自己的精力保持专注而不分心才是修炼的过程。\n\n\n在你还不是核心人才之前谁都可以改变你的命运这种感觉就像踩死一只蝼蚁一样甚至没有人知道你是谁这是绝大多数“拿时间换钱”的人的普遍命运。\n\n\n成为一个专家的第一件事情是闭嘴倾听然后思考如此往复才能让自己越来越接近专家级别的思考。而经过复杂的实践和推理加上理论的高度反思和总结才称得上是“专家”所以别人随便抛出去一个问题专家是可以直接用浅显易懂的话给对方说明白并且可以情景再现的。\n\n\n月收入过万的第一个壁垒专业知识是不是过关\n\n\n因为计算机的发明释放了无效工作量的瓶颈因为行业软件的发明释放了经验值累积的瓶颈因为互联网的发明释放了思想与思想互动的瓶颈因为人工智能的发明释放了脑力深度思考的瓶颈。\n\n\n年轻人不要老想着改变世界而应该从改变自己做起。\n\n\n你能不能翻身算一下修炼成本就知道了\n\n\n但是如果我们把互联网公司的加班时长额外算进去之后你就会发现有些互联网公司的收入其实也是很惨烈的我们在前文中给大家普及了一个知识薪水除以劳动时间等于时薪成本。\n\n\n技术能力、销售能力、市场推广能力、售后服务能力、物流、采购、人力资源、资金调配、产品管理、产品质量、成本管控、生产能力以及政府关系、上下游关系协调能力\n\n\n那么怎么做才能拿资源换钱呢\n\n\n我们先试着将自己资源系的人脉不管是贵人、牛人、恩人还是有钱人统统分为三大类长期人脉、中期人脉以及短期人脉。再结合他们的时间和精力分布是否愿意参与某个项目来计算我就知道这个人是愿意一起参与干活儿并且一起拿钱还是只愿意拿资源出来不愿意干活儿只想着分钱的。\n\n\n故事中的杰里·斯特宁在承认数百万名越南儿童大都是营养不良的大数据样本前提下他关注的不是这个已知的事实而是坚信在自己已知以及其他人已知的大前提下还能够找到大家都没有找到的第三方的解决方案——“虽然穷但也可以健康成长”的可能性。\n\n\n如何在现实生活中拿到对于自己而言相对高薪的收入就得知道身边10多个和自己收入差距在13倍的同行在哪里他们在做什么样的工作以及他们在哪里上班同样每天812小时他们都在用什么样的专业知识和技能来完成工作中有了这些“我自己也能够得上的参考对标”那么我只要找到这些专业知识以及我自己能够承受得了的学习范围剩下的就是时间磨炼和练习量的积累了。\n\n\n其实很多“资源”大都是“无效资源”\n\n\n因为他特别爱惜自己的羽毛不愿意多花时间修炼专业知识不愿意多花精力用心在服务他人上不断为自己找借口他希望他人给他提供各种优质服务但是自己又给不了对方同等的置换而且还要通过撒泼打滚耍赖的方式不断毁约那么长此以往他将会被他的朋友圈、社交圈所唾弃社会就会把他边缘化。\n\n\n满足对方的十个以上需求对方会愿意帮你实现所有的梦想。\n\n\n很多人只想着别人对自己不好却从不思考自己能够为别人做点什么\n\n\n长时间的孤独修行的经验值积累直到把这个维度拉升到成为行业顶尖。\n\n\n按照自然常数e的切分规则来拆分自己未知领域的学习进度38%的时间先认真积累经验剩下的50%时间实践12%时间复盘总结经验。\n\n\n成功人士是这么定义“失败”的这不是失败也不是犯错而是试错所以试错的结果和数据对他们很重要而不是失败之后的心情和感受。\n\n\n有了足够多的积累才能进化\n\n\n人类吃到了易于消化吸收的熟食消化吸收食物的“能量红利”之后打猎时间一下子就被释放出来了人类从此不再为生存而劳碌奔波可以静下心来思考了。\n\n\n这个人完成“大爆炸”之前的准备要素都在某一个时间段收集全了正好他的教育经历和人生经历给了他这个软性条件正好他身边的资源和圈子给了他硬性条件正好这个行业趋势和时代给了他这个展现和成就的条件而且古今中外无一例外\n\n笔记\n\n这就是你在经历第一个50万元里程碑之前必定会经历的过程请问刚踏入职场或者已经工作好多年的读者你这一个关卡过去了吗\n\n💭 50万的标准也许并不适应每个人存够5年的生存金也不错\n\n人类几千年来发展至今一直遇到的问题是如何在有限的资源和信息下对不确定的未来进行生死攸关的决策。\n\n💭 做一个不那么错的选择\n\n即What什么——做这件事情的目的、内容。Who——做这件事情的相关人员。Where何处——具体实施场所。When何时——做这件事情的开始时间和结束时间。Why为什么——做这件事情的缘由、前景。How如何——具体方法和操作步骤。How much多少——准备动用多少预算和相关资源。Effect效果——最后预测结果如何有什么样的效果。\n\n💭 量化\n书评\n点评"},"Personal/Book/个人成长/超级面试官:快速提升识人技能的面试实战手册":{"title":"超级面试官:快速提升识人技能的面试实战手册","links":[],"tags":["阅读/个人成长-人在职场","阅读/笔记"],"content":"简介\n\n书名《超级面试官快速提升识人技能的面试实战手册》\n作者 曾双喜\n分类 个人成长-人在职场\nISBN9787115538253\n出版社人民邮电出版社\n\n概述\n面试是人才招聘过程中的重要一环面试官的水平直接影响到所招人员的素质高低。 那么,面试官该具备哪些基本素质和技能呢? 本书从面试环节出发,介绍了面试官定位、人才画像、面试准备、面试提问与追问、非语言信息观察、面试评分以及面试官的修养等与面试相关的内容。书中不仅穿插了大量的真实案例,便于读者快速理解和掌握知识点,而且在每一讲中都提供了对应的实操小工具,如人才画像分析表、面试提纲表和面试评语表等,帮助人力资源从业者快速掌握面试技巧,成为超级面试官。\n划线\n\n面试官定位、人才画像、面试准备、面试提问与追问、非语言信息观察、面试评分以及面试官的修养\n\n\n管理者最重要的事情就是招聘人才。\n\n\n招聘就像谈恋爱一样要找到一个合适的人是很难的。找错对象会很痛苦招错人才的代价也很大。\n\n\n如果招聘到不合适的人公司就要付出相当于该员工15倍薪水的代价。\n\n\n1面试标准不清晰不知道自己要招什么样的人2提问无章法想到什么就问什么3仓促判断只和应聘者交流了10多分钟就决定要不要这个人4提出各种奇葩的问题如询问星座、生肖等5高高在上提出各种问题刁难应聘者6高谈阔论说的比应聘者还多7不知道怎样判断应聘者表述的真实性8面试结束后感觉应聘者挺好的但是不知道具体好在哪里。\n\n\n传统面试招到的多是面试能力强的人并不一定是工作能力强的人因此很多优秀人才与公司失之交臂。\n\n\nHR和业务经理在选人方面很难达成共识对于HR推荐的候选人业务部门认为他专业能力不行而业务部门认可的候选人HR又说他的价值观或动机不符合要求。\n\n\n从技术层面来说一次成功的招聘需要具备四个因素分别是科学的评价标准、严谨的面试流程、科学的面试方法、专业的面试评委。\n\n\n高管们年龄较大学习创新能力下降思维比较固化对新鲜事物的接受度低由于短时间内他们适应不了公司的氛围也没做出什么业绩所以只好离开公司。\n\n\n董事长听了后略有所思表示“过去我面试了很多高管总觉得面试时这些高管表现得光彩照人招进来之后却发现他们的能力、个性、态度与面试时判若两人其实最需要参加面试官培训的是我呀。”\n\n\n美国心理学家麦克利兰提出的冰山理论把人的素质划分为“冰山”以上的基准性素质和“冰山”以下的鉴别性素质其中鉴别性素质包括内驱力、社会动机、个性品质、自我形象、态度等它是区分绩效优异者与绩效平平者的关键因素。\n\n\n谷歌公司认为由优秀人才组成的员工团队不仅能做出令人满意的成绩还能引来更多的优秀人才这就是所谓的“羊群效应”。\n\n\n普通员工离职时企业承担的直接成本是员工总收入的1.3倍而管理人员离职企业承担的直接成本则是其总收入的2.5倍。\n\n\n滴滴出行创始人程维说“我每天把30%的时间和精力用于面试,面试工作是第一优先级的……所有总监级以上的应聘者我都要见。”\n\n\n雷军说“如果你招不到人才那是因为你投入的精力不够多。”\n\n\n费罗迪曾表示“大多数公司用2%的精力招聘却用75%的精力弥补当初错误招聘造成的失误。”\n\n\n他在面试的时候只看重应聘者的学历、资历等却不会辨别真伪经常把一些会“忽悠”的人招进来结果他们并不能创造好的业绩。\n\n\n第四是面试效果评估认证。以复试通过率或试用期员工流失率等数据对面试官的技能进行认证。\n\n\n“欣赏一个人始于颜值敬于才华合于性格久于善良终于人品”。\n\n\n阿里招聘新员工时主要看他们是否诚信、是否能融入企业、能否接受企业的使命感和价值观业务能力并不是最重要的。\n\n\n2岗位需要什么样的人这是“硬”的条件人力资源部门通过职位分析明确该岗位的任职者需要具备的学历、年龄、经验和技能等。\n\n\n面试官知道自己需要什么样的人也知道对方是什么样的人但不知道在市场上有多少类似的人才同类型人才的薪酬水平如何。所以面试官给出的条件并不能吸引他或者与他的期望值不匹配。\n\n\n不同发展阶段对人才的要求是不同的从0到1需要的是创业型人才善于建立新的模式从1到N需要的是开拓型人才善于建章立制从N到N+需要的是运营型人才注重细节管理和规范化运营从N+到N++,需要的是变革型人才,帮助企业打破原有边界进行转型升级。\n\n\n第一是公司外部环境包括产业链、竞争对手、目标客户、主要产品及服务、行业发展趋势等\n\n\n第二是公司战略规划。每家企业都有自己的经营战略不同的战略对人才的数量和质量要求不同实施发展型战略的公司需要的是开拓型人才实现稳定型战略、成本领先型战略的公司需要的是运营型人才实施多元化战略的公司需要的是复合型人才实施差异化战略的公司需要的是创新型人才。\n\n\n[插图]\n\n\n你在面试的时候提问比较随性就像聊天一样想到哪儿问到哪儿完全没有章法和逻辑所以面试了半天也不知道如何评价应聘者不确定到底能不能录用他。\n\n\n第一类是不能问的问题如政治、宗教信仰、商业机密以及个人隐私的话题。2019年国家出台相关规定企业面试时不得询问妇女婚育情况[插图]。面试官提出这类问题,不仅会引起应聘者的反感,还可能会导致面试的失败。\n\n\n因此面试官应当先充分了解应聘者同时让应聘者对企业及岗位有一定程度的认识。然后面试官要先询问应聘者目前或上一份工作的薪资得到一个较合理的参考标准。\n\n\n在面试过程中面试官要尽量采用行为化问题、情景化问题或将两者结合起来进行提问\n\n\n什么是行为面试行为面试和情景面试有什么区别行为面试和结构化面试有什么关系电话面试、视频面试、无领导小组讨论算不算面试\n\n\n结构化面试也叫标准化面试是指按统一制定的标准和要求进行的面试。\n\n\n严格来说结构化面试不是一种面试技术而是一种面试形式。\n\n\n一个人的行为模式是相对稳定的不会在较短的时间内发生大的变化特别是在遇到类似的情景时人的行为反应倾向于重复过去的方式。\n\n\n说到行为面试就不得不说STAR原则“STAR”是SITUATION背景、TASK任务、ACTION行动和RESULT结果四个英文单词的首字母组合如图3-4所示。在行为面试的过程中面试官要按照“STAR”原则提问也就是要求应聘者对每一个问题讲一个小故事必须是自己经历的真实的故事包括1发生的时间、地点、内容和涉及的人员2要完成的任务或遇到的问题3自己采取了哪些行动4得出了什么样的结果取得了什么样的成绩。这四部分内容缺一不可。所以也有人把行为面试法叫作“STAR面试法”。\n\n\n情景面试主要考察应聘者的思维灵活性与敏捷性、语言表达能力、沟通技能、处理冲突的能力、组织协调能力、人际关系处理能力等素质特征。\n\n\n面试官通过提出生硬的、不礼貌的问题故意使应聘者感到不舒服针对某一事项或问题做一连串的发问直至应聘者无法回答。\n\n\n。这一方法的特点是让应聘者回忆过去的经历通俗地说就是让应聘者讲故事讲完整的故事讲真实的故事讲自己的故事讲已经发生的故事\n\n\n[插图]\n\n\n培训界有一个“721法则”即能力提升的70%来自工作实践中的锻炼20%来自向有经验的人学习10%来自培训课堂和书本的学习。所谓读万卷书不如行万里路,行万里路不如阅人无数,阅人无数不如高人指路,高人指路不如自己去悟。自己去悟,就是指在行动中感悟、领悟和觉悟,这是学习的最高境界。\n\n\n为了使追问的问题更加细化可将STAR原则细化为5W2H方法。What:发生了什么事情面临的任务是什么要解决的问题是什么结果如何造成了什么样的影响When什么时候发生的什么时间开始什么时候结束多长时间一次Where在哪里发生的Who哪些人参与了你的角色是什么Why为什么会发生这样的事为什么要这么做当时你是怎么想的How你是怎么做的具体经过是怎样的How many/much花了多少钱用了多长时间追问越深入、越有针对性面试官就越能获得应聘者真实、丰富的信息同时追问也是一个复杂的、高难度的工作面试官必须注意把握追问的时机和尺度尽量使追问适时、适度。\n\n\n以探询离职原因为例面试官可以从应聘者的职务变动和升迁的轨迹、公司业务发展情况、对加班和出差等的承受程度、对上司领导风格和企业文化的偏好、对权力和地位的欲望、对物质和精神激励的侧重程度等多个角度了解应聘者是由于对哪些方面不满意而离职的。常用的追问示例如下。\n\n\n[插图]\n\n\n企业在招聘过程中强调学历、名牌大学毕业、名企工作经历等便是陷入这种陷阱的体现。须知即使在知名大公司中也有三分之一的人不称职。\n\n\n等级0不合格等待别人吩咐才行动。等级1合格向领导询问该做什么。等级2良好提出建议然后采取相应的行动。等级3优秀自己主动行事然后定期汇报。\n\n\n等级0不合格没有表现出相应的行为。等级1合格大多数人都会采用的常规行为。等级2良好根据存在的问题采取有针对性的行为。等级3优秀有创新、超常规的行为。\n\n\n这些负面事件往往隐藏了应聘者的价值观、求职动机和性格特征等因素是面试官需要深入挖掘的但是不能因为有失败经历就全面否定一个人而应当重点关注应聘者是否能够从失败经历中汲取教训在之后的工作中是否有明显改善。\n\n\n[插图]\n\n\n[插图]\n\n\n[插图]\n\n\n[插图]\n\n\n[插图]\n\n\n面试是双向的了解过程面试官和应聘者只是角色不同而已\n\n\n早上好我叫张××是这家公司的人力资源部经理。到目前为止我已经在这个岗位上工作8年了面试过许多应聘者。在我的职业生涯中我主持、参与了超过300场面试。希望今天我们能进行愉快的交流。\n\n\n要成长为超级面试官一方面要争取更多的面试机会并及时总结面试经验另一方面平时要注意多观察人的行为表现不断进行总结提炼。\n\n\n会写文章的人至少具有以下两个强于一般人的优点。第一善于用简明扼要的语言阐述深奥的问题。第二看问题的深度、高度比一般人要强\n\n\n凡是有小才华的人都是比较有潜力的人。这是因为第一才华能反映一个人的聪明程度有小才华的人的学习能力、创新能力比一般人要强第二只有在一个领域持续地投入和付出才会有产出才能表现出相应的才华因此有小才华的人不仅勤奋而且具备一定的专注度和坚韧性。\n\n\n第一种是类比。当需要向一个外行人讲述一个很专业和深奥的内容时有幽默感的人非常善于利用类比手法通过一些生活中容易理解的案例来解释这些道理让听众易于理解和接受。善用类比手法的人通常总结归纳能力强能够看穿问题的本质在表达方面可以做到深入浅出。\n\n\n从古至今树上的苹果砸中了无数人的头为什么只有牛顿发现了万有引力因为他提出了一个核心问题苹果为什么会落地\n\n\n人的成长在很大程度上是由周围优秀的人推动的。有一个研究显示一个人的水平约等于与他交往最多的五个人的水平的平均值。\n\n\n[插图]\n\n笔记\n\n谈恋爱最大的烦恼是爱我的人我不爱、我爱的人不爱我招聘面试最大的烦恼是我要的人不来、来的人不是我要的谈恋爱与招聘面试都是双向选择需要双方情投意合才能走到一起。\n\n💭 互相选择,彼此成就\n\n人类学家雷·博威斯特指出在一次面对面的交流中语言传递出的信息量在总信息量中所占的份额还不到35%剩下超过65%的信息都是通过非语言交流方式传递出去的。\n\n💭 肢体语言,行为举止\n\n面试的目的是选出合适的人而不是把应聘者难倒。\n\n💭 没有人天生就是契合具体工作岗位,只需要方向一致,尽可能的合适就好。\n书评\n点评"},"Personal/Book/医学健康/你是你吃出来的套装共2册":{"title":"你是你吃出来的套装共2册","links":[],"tags":["阅读/医学健康-健康","阅读/笔记"],"content":"简介\n\n书名《你是你吃出来的套装共2册》\n作者 夏萌\n分类 医学健康-健康\nISBN\n出版社江西科技出版社\n\n概述\n本书由《你是你吃出来的吃对少生病病了这样吃》《你是你吃出来的2慢病康复的饮食密码》构成的套装。《你是你吃出来的吃对少生病病了这样吃》高血压、高血脂、糖尿病、冠心病等慢病人群都曾陷入同一个误区——误以为低油低脂保健康其实多是蛋白质缺乏式营养不良误以为只能终生服药或手术忽略了饮食等生活方式改变带来的真正康复。《你是你吃出来的2慢病康复的饮食密码》本书是一本针对高血压、高脂血、糖尿病、痛风等慢病患者、亚健康人群从临床医学角度提出营养治病调理思路和方案的临床营养实践类图书。营养专家夏萌老师总结几十年临床经验从营养学角度辨别诊治多种慢病和亚健康的成因破除营养认知误区深入浅出地剖析疾病的饮食根源带给慢病患者科学的营养指导。\n划线\n\n我不禁问自己为什么这个奇迹会发生营养素到底在我体内起了什么作用肾炎的种类很多我的疾病的治愈是运气使然还是有什么规律可循\n\n\n问题最为集中的是饮食习惯不良。\n\n\n在很多糖尿病患者身上我发现他们太喜欢喝粥、吃米和面了满脑子都是“没有主食就不叫吃饭”。\n\n\n吃好三顿饭\n\n\n有时候我也会遇到解释不了的问题就去看书、找资料在患者复诊时再把新的营养知识传授给他们他们会毫无保留地信任我告诉我他们自己的问题、感受按时去做检查和化验又会按照新的营养方案去调整。\n\n\n这种情况我过去在神经内科的时候常常遇到那时我和大多数医生一样把可以想到的方法都用遍后唯一能做的就是一遍一遍地下病危通知。但现在的我认为这一刻还可以有所作为——给生命最基本的营养支持。\n\n\n一问患者家属他夫人告诉我他吃素从来不吸烟不饮酒每天都运动。我明白了他由于长年缺乏蛋白质导致大血管变得很脆弱手术前已经营养不良经过大手术的打击体内营养储备已被全部掏空。\n\n\n我给他做了饮食调查发现他平时会吃很多米面尤其爱吃面条每天晚上如果不吃面条就很担心夜里会饿醒。\n\n\n他很疑惑“不是吃了降糖药就不能停了吗”我耐心地解释“因为你已经开始运动并且控制了饮酒现在又开始从饮食上努力调整这些都是降血糖的有效方法此时如果加上药物降血糖的力量很容易出现低血糖的症状轻则昏迷重则死亡。”\n\n\n医生如果学会了营养学将如虎添翼普通人如果学会了营养学将受益终身。\n\n\n中国在此次报告中的人均寿命为女性77岁男性74岁。咱们的邻居日本人均寿命在全世界排名第一国民平均寿命为84岁。\n\n\n人体自身无法合成维生素而且各种维生素之间不能相互转化当某一种或几种维生素缺乏时很容易出现问题因此怎么强调维生素的重要性也不为过\n\n\n中国居民膳食指南及平衡膳食宝塔(2007)\n\n[插图]\n2007—2016年这10年人们的生活方式变得更加方便快捷糖尿病、高血压等慢病成为非常严重的社会问题更多研究资料显示工业化加工食品对人体健康产生了严重的副作用。同时蛋白质、维生素A、铁、钙的普遍缺乏仍然存在营养不平衡成为普遍现象。大家在享受各种美味食品时往往忘记了食物多样化以及正确的膳食结构给健康带来的益处所以这一版的膳食指南除了宝塔外还增加了膳食餐盘提醒人们重视食物结构。\n\n第一种是经济发达国家模式也称富裕型模式主要以动物性食物为主粮食类中等蔬菜水果比较少。富裕型模式属于高能量、高脂肪、高蛋白、低膳食纤维型如大家经常看到的麦当劳、肯德基、星巴克等都是这类典型模式。\n\n\n“看咱们自己国家的膳食宝塔上面写得清清楚楚。”\n\n\n所以各国膳食指南都只适用于本国居民。再者每个国家的饮食指南都是与时俱进的历经一段时间后又发现了很多营养问题而且与全民健康明显相关下一次的指南就会有所调整所以要动态地看待这些饮食指南\n\n\n世上最好的药早餐、午餐和晚餐\n\n\n晚餐的真正价值补足全天没吃够的营养\n\n\n少吃多餐能够减轻以往大量进食时肠胃的压力减轻胃肠道负担减少肌肉损害促进新陈代谢减少体脂排毒养颜。\n\n\n下午茶的时候可以喝些牛奶、酸奶、咖啡加上水果和小点心\n\n\n一方水土养一方人你到了一个新的地方就应该按照当地的饮食习惯吃顺应当地的气候条件要求这样才能保证健康。\n\n\n脑内需求最多的脂类为卵磷脂因此要增加磷脂食物\n\n\n长期面对电脑工作要特别注意维生素A的补充这对提高视力、防止眼睛干涩有好处。而补充维生素A最好的方法是吃动物肝脏另外也可以补充植物中的胡萝卜素。\n\n\n女士每个月有月经血的输出所以应该更多地补充些动物肝脏、血制品和有补铁效果的植物性食物比如猪肝、猪血、鸭血、芝麻、蘑菇、木耳、海带、紫菜、桂圆等。补铁同时补充维生素C可以促进铁吸收所以要多吃水果。\n\n\n[插图]\n\nPART 04\n我们到底应该怎么吃\n\n水果吃得实在太少了\n\n2013年国际组织发布各国水果年人均消费指标中国年人均64千克日本年人均54千克印度年人均37千克巴西年人均109千克俄罗斯年人均71千克美国年人均110千克。\n为什么我们没有美国人、俄罗斯人水果吃得多因为在吃水果的问题上全国差距太大有很多人根本不吃有条件的人和有健康观念的人要好一些。尤其是男同胞大多认为水果是零食不爱吃甚至我在出诊时还遇到过这种说法“水果不都是女人吃的吗”\n2002年中国营养学会有关中国膳食与健康的调查结果显示中国城乡居民的膳食中每人每天平均食用水果的数量是45.\n\n肌肉组织肠胃、心脏等器官动力不足都可以由此入手\n\n肌肉不仅代表着健美还代表着力量。常见的肌肉被分成骨骼肌、平滑肌和心肌。\n骨骼肌很好理解主要指四肢的肌肉。\n平滑肌主要分布在胃肠道这类肌肉多不受自主意识的控制有自己的收缩节律。也就是说胃肠道蠕动多少次你无法控制。平滑肌在各种管道的中间层前面介绍上皮细胞时讲了人体中所有的管道凡是有管道的地方就会有平滑肌比如消化道、呼吸道、生殖道等。\n心肌不用多说大家也知道就在心脏。\n便秘很可能因为身体缺肉\n\n我在书中详细地介绍了我的思路轨迹和大致营养原则希望你能通过了解我的思路建立一个属于自己的营养治疗方案。\n\n信息爆炸的年代知识更迭得飞快临床营养学方面还有很多内容没有被研究透彻。我不敢说我讲的都对我只是写出了基于自己大量治疗经验对营养的理解和我现在采用的方法。与你分享本书愿共同进步、共同受益。\n夏萌\n2019年5月\n\n[插图]\n\n\n[插图]\n\nPART 03\n吃对了降血脂哪有那么难\n\n低密度脂蛋白在血液中游走携带着肝脏合成的脂肪、磷脂和胆固醇寻找低密度脂蛋白的受体。低密度脂蛋白的受体遍布于血管内皮细胞、动脉壁平滑肌细胞、肝细胞、肾上腺皮质细胞、淋巴细胞、单核细胞、巨噬细胞。当低密度脂蛋白找到载脂蛋白B的受体后互相识别一下信号对上然后顺利登陆把货物卸下来。甘油三酯成为能量供细胞应用磷脂和胆固醇成为细胞的结构成分或者激素的合成原料。\n\n综上当看到化验单上低密度脂蛋白胆固醇旁边有个向上的箭头时我们最好采用这样的思路至少我们要知道三点。\n第一来源于肝脏的胆固醇合成比较多说明肝脏的功能还不错。\n第二低密度脂蛋白胆固醇的接收点在血管内皮、动脉壁平滑肌、肾上腺、免疫细胞等周围组织这些组织需要肝脏合成的胆固醇。\n\n人在焦虑的状态下肾上腺素、去甲肾上腺素、肾上腺皮质激素分泌都会增多血糖值也会随之升高。\n\n\n“三足鼎立”的三个“足”是指蔬菜类、蛋白质类和碳水化合物类。蔬菜占总数量的一半蛋白质类占1/4碳水化合物类占1/4最好选择低碳水化合物的主食。中餐、晚餐可以是主食蔬菜肉类早餐可以是包子+鸡蛋+牛奶+蔬菜。\n\n笔记\n\n食物是最好的药物。也真正明白了“健康掌握在自己手中”这句大俗话所言不虚。\n\n💭 食物是最好的药物\n书评\n点评"},"Personal/Book/医学健康/小小药箱护健康教您用好家庭小药箱":{"title":"小小药箱护健康教您用好家庭小药箱","links":[],"tags":["阅读/医学健康-医学","阅读/笔记"],"content":"简介\n\n书名《小小药箱护健康教您用好家庭小药箱》\n作者 中华医学会临床药学分会组织编写\n分类 医学健康-医学\nISBN9787117306959\n出版社人民卫生出版社\n\n概述\n随着人民生活水平的提高人民群众的健康意识也得到不断提高群众对医药科普的刚性需求出现了急速增长。本套丛书从老百姓需求出发解决现在困扰百姓的合理用药问题。涵盖老少孕幼更年期各类人群以及普通人群在各种情况下用药的困惑和误区切实以老百姓用药需求为牵引以期做最“懂你”的科普希望以此套药学科普书铸造连接药师和患者的“桥梁”。本书为《一生健康的用药必知》科普丛书之一内容力求深入浅出图文并茂旨在向大众普及合理用药知识助力全民健康。\n划线\n\n为家人准备一个“专属”小药箱\n\n\n一、列出家里每个成员的“个人简历”\n\n\n二、根据“个人简历”列药品清单\n\n\n▲ 家庭常备药品少且精每类需要备12种药品。▲ 如果没有特殊要求建议选择非处方药。▲ 除了外用药外常备药品基本以口服治疗为主。\n\n\n[插图]\n\n\n常用药品专用药箱、儿童药品专用药箱、急救药品专用药箱、慢性病药品专用药箱。\n\n\n并不是备上药箱就可以不去医院了对不能确诊或症状较重的疾病不能擅自用药应该及时去医院诊治。切不可因为有了家庭小药箱自己给自己看病拒绝就医耽误病情。\n\n\n按照药品说明书吃药不要混用含有相同成分的抗感冒药。\n\n\n建议发热超过38.5℃时才使用含有退热成分的抗感冒药餐后吃46小时后如果体温还超过38.5℃可以再次服药但24小时内不超过4次。\n\n\n预防感冒的最佳做法是通过健康的生活方式增强身体免疫力。\n\n\n而且山楂对妇女子宫有收缩作用如果孕妇大量服用含有山楂成分的健胃消食片会刺激子宫收缩\n\n\n汞溴红溶液就是我们俗称的“红药水”因含有汞这种重金属对人体有害现在已不建议使用。龙胆紫溶液俗称“紫药水”因为容易导致痂下的伤口愈合不良且对人体有致癌性现在也不建议使用。而且这两种药水都容易引起伤口颜色改变影响伤口的观察因此不建议使用“红药水”和“紫药水”。\n\n\n夏秋季保存药品防暑防潮春冬季保存药品防冻防风\n\n\n▲ 不随意增减药量要根据药品说明书或医嘱服药。▲ 不要随意听信他人的话更换自己的用药方案或乱买药品。▲ 自己无法判断药品是否合适时需听取医师或药师的意见。▲ 在医师开具处方前应向医师告知现在使用的药品。▲ 不要因为担心药品副作用而随意停药但如果真出现了副作用应及时咨询医师或药师并停药。\n\n笔记\n\n科普跑不过谣言\n\n💭 太真实了,科普跑不过谣言\n\n感冒药过量而出现肝功能不全\n\n💭 感冒药务必不能多吃\n书评\n\n✨家庭药箱科普类的优秀书籍5w字值得一读。\n\n点评"},"Personal/Book/历史/信息简史":{"title":"信息简史","links":[],"tags":["阅读/历史-历史文化","阅读/笔记"],"content":"简介\n\n书名《信息简史》\n作者 詹姆斯·格雷克\n分类 历史-历史文化\nISBN9787115331809\n出版社人民邮电出版社\n\n概述\n人类与信息遭遇的历史由来已久。詹姆斯·格雷克笔下的这段历史出人意料地从非洲的鼓语讲起。非洲土著部落在尚未直接跨越到移动电话之前曾用鼓声来传递讯息但他们是如何做到的呢后续章节进而讲述了这段历史上几个影响深远的关键事件包括文字的发明、罗伯特·考德里的第一本英语词典、查尔斯·巴贝奇的差分机与爱达·拜伦的程序、沙普兄弟的信号塔与摩尔斯电码。但人类开始自觉地理解和利用信息始于克劳德·香农在1948年创立的信息论。香农的信息论不仅推动了信息技术的发展也引发了许多学科的信息转向改变了人们对于诸如麦克斯韦妖、生命的编码、模因、随机性、量子信息论等的理解。部分科学家甚至认为构成世界的基础不是物质不是能量而是信息。正如物理学家约翰·惠勒所说“万物源自比特”。现如今信息如洪流般淹没了我们使我们深陷信息焦虑、信息过载、信息疲劳的困扰。但回顾历史这并不是件新鲜事人们也总是能想出应对手段。维基百科、Google便是我们的应对之一。无论对于信息的未来持何态度有一点是确定无疑的即我们人类是信息的造物。\n划线\n\n我们称为过去的东西其实是由比特构成的。\n\n\n在这三十年间信息极大地释放了人类的能量它所创造的价值超过了之前五千年的财富总和\n\n\n在这三十年间产业化的信息就像一部两百迈的汽车行驶在未来之路上但我们并不知道它要开往何方。\n\n\n它对“冗余信息的价值”给出了不同以往的解释。那些看似有损于精炼和简洁的冗余信息反而提升了信息传播的精准性。而今当我们对碎片化、无序化的信息头痛不已时我们是否意识到在依托大数据系统的组织与传播模式下碎片可以为我们描绘出事物的全貌\n\n\n当对话取代听讲当个性取代共性当封闭转向开放人的思想力得到了空前的释放信息成为了社会的第一生产力。\n\n\n但其实更为重要的互联网所打破的实际是以纸书为代表的知识凝聚与传播方式\n\n\n也许当我们忘记书是“一本本”的时候我们才会看到互联网时代图书的未来。\n\n\n“科技的互联网”不能描述信息的全部信息只有作用于思维才能显示出强大的力量。\n\n\n信息则成为第一位的资源其地位远超出传统的生产资料。\n\n\n这本书可以让人多一个视角来看待和理解世界即“信息视角”。\n\n\n1信息贯穿了人类的发展史今天的成果是过去一点点积累而来的2计算通信理论突破后带来的近五十年的变革是指数级的3我们正在走向下一个指数级阶段即信息世界和物理世界的统一融合。\n\n\n生物体中的所有细胞都是一个错综复杂的通信网络中的节点它们一刻不停地传输和接受信息不停地编码和解码。进化本身正是生物体与环境之间持续不断的信息交换的具体表现。\n\n\n它不仅微小而且抽象——它存在于一个个二进制数字、一个个触发器、一个个“是”或“否”的判断里\n\n\n而解开这个谜团的关键就是不见于经典物理学的所谓量子纠缠quantum entanglement现象。一旦粒子之间或量子系统之间发生了量子纠缠那么即便相隔广袤的时空它们的基本属性也仍然相互关联。即使相隔数光年它们仍然能够共享某些实际存在但又不只是实际存在那么简单的东西。\n\n\n信息吞噬者——黑洞。惠勒因而宣称“未来我们将学会用信息的语言去理解和表达全部物理学。”\n\n\n很少有信息技术会彻底过时每一种新兴技术都会为其前辈技术赋予新的理解\n\n\n这种编码后来被称为点-划字母表,但没有提及的停顿也同等重要,因此,摩尔斯电码并不是一种二进制语言。\n\n\n但它也要解决与设计电报编码时所面临的同样问题即怎样将整个语言映射到单一维度的最简单的一连串鼓声上。这个设计问题是经过一代代鼓手、数个世纪的社会演进才得到解决的。\n\n\n音素\n\n\n非洲语言的口语把声调作为举足轻重的一部分鼓语则更进一步——它仅使用声调。这是种只有一对音素的语言完全通过高低音的变化构成。鼓的原材料和制作手艺各有不同。比如梆鼓slit gong就是取一段花梨木掏成中空再切出个长而狭的口子就可以一端发高音而另一端发低音还有一些鼓是蒙皮的可以成对使用\n\n\n引入冗余不言而喻效率肯定会打折扣但它是避免混淆的一剂良药它提供了第二次机会。\n\n\n他眼见洛克勒族的年轻人中练习敲鼓的人越来越少而上学的孩子们甚至连鼓语中的名字也没有了。他为此感到十分惋惜因为对他而言会说话的鼓已经成了他生活中的一部分\n\n\n“森林里的白种男人精灵回来回来回到属于森林里的白种男人精灵的高高的木屋。女人和洋芋在等待着你。回来回来。”\n\n\n文字成了我们获取知识的机制和组织思维的手段。我们希望采用历史和逻辑的方法来理解文字的起源可是历史和逻辑本身就是文字思维的产物。\n\n\n柏拉图是第一个长期受益于这项技术的人本不太可能成为反技术的卢德分子但他借不立文字的苏格拉底之口警告说文字带来的将是思想的贫瘠你这个发明结果会使学会文字的人们善忘因为他们就不再努力记忆了。他们就信任文字只凭外在的符号再认并非凭内在的脑力回忆。所以你所发明的这剂药只能医再认不能医记忆。至于教育你所拿给你的学生们的东西只是真实界的形似而不是真实界的本身。\n\n\n口语符号会立刻消弭于无形。即使它真的存在也只存在于听到了这些符号的人的思维中。\n\n\n文字的持久性使得他能够把有关这个世界的已有知识加以结构化进而他可以总结关于知识的知识。\n\n\n群众无法接受美的观念本身只知道各种美的事物。他们也不会思考事物的本质只能理解各种具体事物。因此群众不可能成为哲学家。\n\n\n这些泥板不仅记录下了处于萌芽时期的商业和官僚政治的日常活动而且也是最初使这些活动得以出现的条件。\n\n\n杰恩斯评论说“征服和影响之所以能够层层推进正是借助了前所未有的众多字母、泥板和石碑。文字是进行社会控制的新方法实际上其模式也是今天我们基于备忘录进行沟通的政府的开端。\n\n\n听觉空间是有机的、综合的通过所有感官的同步互动才能感受到理性空间或图文空间则是单一的、序列化的、连续的它制造的是一个封闭世界其中缺失了部落时代的回音世界里那种丰富的回声。\n\n\n扉页上没有写作者罗伯特·考德里的名字却写了一条拉丁文格言——“不理解不如不读”Legere, et non intelligere, neglegere est\n\n\n“外国人和外族人对于我们文字的不确定性以及我们拼写的随意性确实感到十分惊奇\n\n\n”从此以后语言再也不像空气那样看不见摸不着了。\n\n\n“千万不要借用外国语”“花点心思去使用常见的词来说话只有这样才能让大多数未受过教育的人听得懂”\n\n\n有些出过远门的绅士回到家乡以后除了爱穿外国的奇装异服四处招摇外还喜欢在说话时夹杂外语。比如最近从法国归来者就满口带法国腔的英语并且也居然不以为耻。\n\n\n所谓字母表就是一个离散的小型符号集有其约定俗成的排列顺序“abecedarie字母的前后顺序或使用字母的人”。但即便在当时这种机制在人们看来是不自然的因为它迫使读者将信息从单词的意义中剥离出来把单词严格地视为字符串集中精力于单词的字母组合上。\n\n\n但是没有人知道英语中有多少单词。\n\n\n一旦他们创造了一个新说法任何人都可能听见\n\n\n巴贝奇的雄心也在高涨。动工十年后巴贝奇的机器只有0.61米高有六根轮轴、数十个数轮可以进行六位数的运算。但再过十年后机器的规模虽然只是在图纸上已经达到4.53立方米重15吨有25000个零件而图纸平铺开来能覆盖超过37平方米的面积\n\n\n而当他展望未来时他预见有一条真理将高于一切那就是“知识就是力量”。他是从字面上理解这句话的认为知识“本身是物理作用力的发生器”\n\n\n速度可以用两种方式度量以距离来度量或以符号和字词来度量。\n\n\n这种将意义从一种抽象转换为另一种抽象的过程在数学中早已有之。并且从某一方面上说这恰是数学的本质所在。\n\n\n而在对保密性要求不那么高的场合韦尔建议将常用短语加以缩写。比如在要发送“give my love to”请问候某人他建议只发送gmlt即可。他还给出了更多的例子\n\n\n那些使用电报编码的用户慢慢发现编码虽然高效而简洁但它也有始料未及的副作用那就是极易受到哪怕是最微小的错误的破坏。由于缺乏一般的英语散文乃至扼要的电报体散文所天然具有的冗余度这些经过精心编码的讯息可能会因为一个字符或点划的差异而面目全非。\n\n\n1婴儿是不讲逻辑的2没有一个会调教鳄鱼的人被鄙视3不讲逻辑的人被鄙视。\n\n\n在第一次世界大战后麻省理工学院成为了美国电气工程应用科学的三大孵化中心之一另两个是贝尔电话实验室和通用电气\n\n\n数学家还倾向于把他们面对的任何情况都加以理想化。他的气体是“理想气体”他的导体是“全导体”他的表面是“光滑表面”。他会把这称为“直抵本质”工程师则恐怕会说这是“无视事实”。\n\n\n而讯息接收者知道该过程使用的密钥从而可以借此反推整个替换过程。因此即便敌方知道了所用的加密过程只要密钥没有泄露整套安全系统仍然有效\n\n\n在香农看来模式就等同于冗余。在日常语言中冗余可以辅助理解。可在密码分析中冗余就是密码的阿喀琉斯之踵。\n\n\n信息是不确定性是出人意料是困难程度是熵。\n\n\n就像用移动物体所需的力来定义质量一样。不过换个角度看质量的确可以用这种方式定义。●信息是熵。这是各个说法当中最奇怪也最强大的一个。熵的概念早已有之在研究热量和能量的热力学中它被用来度量系统的无序程度。但对于这个概念一直以来人们的理解有限。\n\n\n通信的基本问题是在一点精确地或近似地复现在另一点所选取的讯息。\n\n\n[插图]\n\n\n香农提出的基本思想是“把信息量视为负熵”\n\n\n信息就是信息既不是物质也不是能量。\n\n\n模拟的就像计算尺数用间距来表示而数字的则像算盘算珠要么被计数要么不被计数没有介于两者之间的状态。同样用来调节光线的变阻器是模拟的而墙上的开关则是数字的。杰勒德认为神经系统的化学活动和电活动都是模拟的。\n\n\n香农和维纳的侧重点有所不同。维纳用熵来度量无序程度而香农用熵度量的则是不确定性。不过正如他们所意识到的两者从根本上说是一回事。一个书面英语样本中的内在有序性越强有序性表现为为语言使用者有意识或下意识所知悉的统计特征其可预测性也就越高换用香农的话来说也就是后续字母所传递的信息量越少。如果受试者对下一个字母是什么信心十足那么这个字母就是冗余的它的出现没有贡献新的信息。信息是出人意料。\n\n\n信息可被认为是从无序中夺得的有序。\n\n\n他的做法是用一个测试来代替这个问题他称之为“模仿博弈”也就是后来鼎鼎有名的“图灵测试”。\n\n\n图灵认为数字计算机包括三个部分一个“信息仓库”相当于人类计算员的记忆或纸张一个“执行单元”负责完成一个个操作以及一个“控制器”管理一个指令列表以确保各指令按照正确顺序被执行。这些指令被编码成数它们有时被称为一个“程序”而构建这样一个列表的工作通常被称为“编程”。\n\n\n在其中他会解释基本思想比如调皮地引用《新约·马太福音》第5章第37节的话“你们的话就说是不是就说不是若再多说就是出于那恶者”\n\n\n比如他在宾夕法尼亚大学的一次演讲中就说道“总而言之我认为这一整个信息产业将在本世纪快速崛起和发展其中包括信息的采集、信息从一点到另一点的传输以及恐怕是最为重要的信息的处理。”[插图][插图]克劳德·香农1963\n\n\n然而香农经过粗略计算后指出一盘典型的国际象棋棋局涉及的可能组合数目超过了10120——这个数要远大于以纳秒计的宇宙年龄。因此在香农看来计算机不能靠蛮力搜索来下国际象棋而是要像人下棋那样进行推理。\n\n\n信息论正开始改变理论物理学和生命科学的研究轨迹而熵正是促成了这种改变的原因之一。\n\n\n热力学“定律”能被简洁地加以表达第一定律宇宙的能量守恒。第二定律宇宙的熵恒增。\n\n\n而在信息论中熵度量的是一条讯息的不确定程度即身为由信源发出的所有可能讯息中的一条的概率。这些可能讯息的出现概率不一定相等因此香农的公式是H=-Σpi log pi。\n\n\n信息正是讨论和度量诸如复杂度与有序度、组织性与特异性等生物学属性时所需的概念\n\n\n行数十亿次的自我复制而仍然保持数据的完整可靠。\n\n\nDNA不仅进行自我复制分离开后它还控制着另一种完全不同的物质的制造。而生成的这些极其复杂的蛋白质是生物体的构成材料\n\n\n“我给你举个例子。二十年前如果你去问一名生物学家蛋白质是如何合成的他会回答这个问题太过复杂我不知道。如果你去问一个生物化学家他会说关键的问题在于从哪得到制造肽键的能量。而分子生物学家对此则会说关键不在那关键在于组装氨基酸序列的指令从何而来让能量见鬼去吧它自己会想办法的。”\n\n\n母鸡不过是一只蛋用来制造另一只蛋的工具。\n\n\n然而如果转而从个体是为了将体内的各种基因延续下去的角度思考那么许多解释便说得通了。同一物种的其他个体拥有这些基因中的大部分而亲属拥有的相同基因就更多了。\n\n\n地球上的生命史始于复制子的偶然出现。复制子是一种信息载体它通过自我复制而生存和传播。副本必须自洽且可靠但无需完美。相反为了实现进化错误倒是必不可少。\n\n\n生命史是用负熵写就的他继续写道“真正在进化的是以各种形态和载体存在的信息。如果有那么一本指导生物进化的手册的话我想里面第一句大概应该是这样的它读起来像句圣经诫命应使你的信息更丰富。”\n\n\n正如在无生命世界之上有生物圈在生物圈之上也有个“抽象王国”。那么这个王国的居民又是什么呢是思想。\n\n\n“我不知道你会怎么想但我本人一开始并不喜欢这样的想法我的大脑不过类似某种粪堆\n\n\n无知是主观的它是观察者的一种属性。而随机性如果它真实存在的话应当是事物本身的性质。这样的话排除掉人为因素我们就可以说一个事件、一次选择、一个分布、一次博弈或者最简单的一个数是随机的。\n\n\n当然任何考虑用算术方法来生成随机数的人都犯下了僭越之罪。因为正如已经被多次指出的不存在一个随机数这样的东西——有的只是生成随机数的方法而一种严格的算术方法显然不属于其中之一。\n\n\n这恰好从一个方面表明了即便借助了机械的帮助人类在生成随机数方面也是能力低下。研究也证明人类直觉在预测随机性和识别随机性上都毫无助益。无论愿意与否人类总是偏好模式。\n\n\n但香农还进一步考虑了讯息中的冗余讯息中的模式、规律和秩序等因素使得讯息可压缩。讯息越有规律就越可预测越可预测就越冗余越冗余含有的信息就越少。\n\n\n但我们为什么说π不是随机的呢蔡廷给出了一个明确的回答一个数只要是可计算的即它能够被一个可定义的计算机程序生成那它就不是随机的。因此可计算性是随机性的一种量度。\n\n\n1920年安德烈·柯尔莫哥洛夫进入莫斯科大学数学系就读。在随后十多年里他做出了一系列影响深远的成果尤其他的《概率论基础》\n\n\n信息、随机性和复杂度这三者本质上是等价的——三个威力强大的抽象就像地下情人一般如胶似漆。\n\n\n香农最先证明了讯息中任何非随机的部分都可以被压缩。\n\n\n窗台上的两盏灯笼可能毫无意义也可能表示“英国人走海路”\n\n\n信息并不是讯息价值的一个好的量度。\n\n\n这就是空气它杂乱却永恒地记录下了人类说过的每一句话。\n\n\n阿兰·图灵或许是注意到这一点的第一人像宇宙一样计算机也最好被视为状态的组合机器在一个瞬间的状态决定了下一瞬间的状态因此根据其初始状态和输入信号机器的全部未来状态应当是可预测的。换言之宇宙在不断地计算自己的命运。\n\n\n印刷术作为一场通信革命在从中世纪到现代社会的转型中所发挥的不可或缺的作用。\n\n\n在“信息论”一词问世后相继又出现了“信息过载”、“信息过量”、“信息焦虑”、“信息疲劳”等说法。\n\n\n焦虑感取代了满足感渴求与失落循环往复。人们刚开始一种体验其他还会有什么的想法就又随即萌生。”这是富足的窘境无疑也再次提醒了我们信息不是知识知识不是智慧。\n\n\n他们由于同时生活在两种反差强烈的社会和经验之中而产生的困惑和犹豫我们现在也感同身受。\n\n\n我们不要独裁君主我们也不要寡头政治或阶级统治我们要一个遍及全球、拥有自我意识的智能。\n\n\n但无限可能性是件好事而非坏事。无意义的无序是我们要勇于挑战的局面而不是我们畏葸不前的借口。\n\n\n一直以来是选择塑造了我们。选出真正的信息需要做功而后遗忘它们也需要做功。\n\n\n这座图书馆将继续存在它就是宇宙。但对于我们来说一切都还没有被写完我们也还没有变成虚无的存在。\n\n笔记\n\n文字使得复用和“回忆”成为可能——这是全新的模式。它允许信息以全新的架构加以组织分成诸如历史、法律、商业、数学和逻辑等。\n\n💭 文化得到了传承\n\n皮克林在波士顿作了下数学计算“如果现在我们以两天或更少的时间换句话说以每小时十二到十六公里的时速获取到纽约的情报就能占据可观的商业优势那么当我们利用远距离传讯系统传递同样的信息以每分钟六公里的速度换句话说只需一个小时就足以从纽约传到波士顿时任何人都能意识到这其中包含着成比例的获利机会。”\n\n💭 信息资源\n\ngive my love to”请问候某人他建议只发送gmlt即可。他还给出了更多的例子\n\n💭 可能是互联网缩写的由来\n\n就像用移动物体所需的力来定义质量一样。不过换个角度看质量的确可以用这种方式定义。\n●信息是熵。这是各个说法当中最奇怪也最强大的一个。熵的概念早已有之在研究热量和能量的热力学中它被用来度量系统的无序程度。但对于这个概念一直以来人们的理解有限。\n\n💭 熵\n\n正如《爱丽丝镜中奇遇》里的红皇后所说的我们只有全力奔跑才能留在原地。\n\n💭 我们只有全力奔跑才能留在原地,逆水行舟,不进则退!\n\n随机性也许可以用秩序来定义——严格地说是秩序的缺失。\n\n💭 不存在绝对的随机正如不存在绝对的秩序。\n\n在混乱中找出秩序找出模式这也正是科学家的工作。\n\n💭 混乱中寻找秩序,秩序中制造混乱\n\n香农在《通信的数学理论》一开头就直言不讳宣称意义“与其工程学问题无关”。因此忘记心理学放弃主观性吧。\n\n💭 意义具有主观性\n书评\n点评"},"Personal/Book/历史/这里是中国2":{"title":"这里是中国2","links":[],"tags":["阅读/历史","阅读/笔记"],"content":"简介\n\n书名《这里是中国2》\n作者 星球研究所\n分类 历史-中国史\nISBN9787521731224\n出版社中信出版集团\n\n概述\n《这里是中国2》以近代以来一百年为时间尺度讲述现代化进程之下中国的地理变迁和中国人的创造呈现这个蓝色星球上伟大的地表塑造。 通过原创摄影图片及充满情感温度的文字,描绘中国具有代表性的地理人文景观和自然风貌,让我们享受视觉盛宴的同时,了解自身所处的自然世界,并以可感知的方式收藏大自然的美好。 100年我们重塑了一片山河 100年我们振兴了一个民族 100年我们改变了一个国家。从没有一根钢轨到铁路、公路纵横四方从没有一盏电灯到14 亿人全民通电以及西气东输、南水北调、国土绿化、载人航天、北斗导航、登陆火星……《这里是中国2》一书尽览中国建设之美、家园之美、梦想之美。逆天改命的中国人告诉世界什么叫大国崛起。 超级工程,超级风景。百年重塑山河,建设改变中国!\n划线\n\n人口迁移、产业聚集、北粮南运、南果北上、北煤南运、西电东送、西气东输、南水北调一个个大范围、大规模的资源重组让这个原本资源分布极不平衡的国家得以释放潜力高速运转。\n\n\n冰冻三尺非一日之寒破冰之功非一春之暖\n\n笔记\n书评\n点评"},"Personal/Book/哲学宗教/半小时漫画中国哲学史套装全2册":{"title":"半小时漫画中国哲学史套装全2册","links":[],"tags":["阅读/哲学宗教","阅读/笔记"],"content":"简介\n\n书名《半小时漫画中国哲学史套装全2册》\n作者 陈磊·半小时漫画团队\n分类 哲学宗教-东方哲学\nISBN\n出版社江苏凤凰文艺出版社\n\n概述\n儒家就像HR最会处理人际关系把国家秩序安排得明明白白道家向往自由推崇无为而治offer送到手里都不接法家都是职业经理人他们用开公司的套路把国家一步步做大做强墨家的核心思想“非攻兼爱”用一句话来概括就是“peace and love”玄学就是摸鱼哲学清谈就像在公司例会上扯淡理学是儒学的全新款式说社会秩序也是自然规律要追求“天理”心学专门跟理学抬杠说人心就是“天理”要知行合一追求“良知”。本书延续了半小时漫画系列严谨又搞笑的风格从孔孟老庄到程朱陆王程颐、程颢、朱熹、陆九渊、王阳明各门派宗师爆笑登场。让你在哈哈大笑中秒懂各大门派的思想主张和历史发展不知不觉就入门国学、爱上国学\n划线\n\n哲学其实是一首经典老歌回荡在每一条大街小巷每个人都会唱!\n\n\n智慧是通过思考得来的。\n\n\n所以当时的部落里女人才是老大也就是族长这就是传说中的母系社会。\n\n笔记\n书评\n点评"},"Personal/Book/哲学宗教/第一性原理":{"title":"第一性原理","links":[],"tags":["阅读/哲学宗教-西方哲学"],"content":"简介\n\n书名《第一性原理》\n作者 李善友\n分类 哲学宗教-西方哲学\nISBN9787115542649\n出版社人民邮电出版社\n\n概述\n什么是第一性原理亚里士多德说“任何一个系统都有自己的第一性原理它是一个根基性命题或假设不能被缺省也不能被违反。”第一性原理好比树木的根基没有人会看到繁茂枝干下的树根但它决定了树的一切。本书将“第一性原理”的思想引入创新与商业领域用8个思维模型和实践方法帮助企业与个人厘清问题的本质直达本源。我们常问未来十年什么会变化这个问题很重要但更重要的问题可能是未来十年什么不变如果能找到不变的把所有的资源和精力毫无保留地投入在不变的事物上其力量不可同日而语。让我们用第一性原理重新认识世界。探索内在的力量创造非凡的人生。\n划线\n\n如果再往后看千年我们不禁要问哲科思维在今天还重要吗当代高速的社会发展是否仍然与哲科思维有关\n\n\n柏拉图把人类的认识分为4个等级由低到高依次为想象、信念、理智和知识。类似地我将人类的思维分为4层由低到高依次为感性思维、理性思维、哲科思维和觉性智慧。\n\n\n人类日常生活中常用的两种基本逻辑方式一种是归纳法另一种是演绎法。\n\n\n虽然在科学领域中归纳法以所谓的“独立可重复性”作为标准从而确保实验结果的有效性但这并不意味着我们通过归纳法总结出来的规律就一定是真实的。\n\n\n还是以我们之前提到的天鹅的认知问题为例我们在欧洲看到的天鹅是白色的在非洲看到的天鹅是白色的真的就意味着所有的天鹅都是白色的吗答案当然是否定的因为在澳大利亚还分布着少量但确实存在的黑天鹅种群。\n\n\n总而言之归纳法只能证伪却不能证明。\n\n\n推翻一个结论不要从结论入手而是要从它的隐含假设开始如果根基的隐含假设不成立结论自然不成立。这也是辩论高手的常用方法从基石和结构切入不要从内容入手。\n\n\n在我们的经验里未来总是和过去一样。\n\n\n对管理者来说经验是决定经营效果的重要因素对员工来说经验是决定工作能力的关键指标。这种认知仿佛已经成了行业的共识所以越来越多的企业在提拔管理者和招聘员工的时候会以经验作为主要的考查项目。但几乎没有人去深究过经验的指导意义真的可以贯穿一家企业发展的始终吗。实际上在“过去的经验在未来依然有效”这个命题下隐藏着未来与过去一样的时间维度连续性。\n\n\n演绎法不是我们熟悉的思维方式并且需要有一定的思考能力。归纳法是将眼睛看得到的事实归纳为规律基本上用的是感性思维而演绎法是理性思维的主要用智形式。\n\n\n他提出的力学公式也不是从蒸汽机发明和改善的经验中归纳出来的。他只是发现了一个抽象的逻辑\n\n\n我的启蒙得益于当年在斯坦福大学求学期间有幸听到美国华裔物理学家、中国科学院外籍院士张首晟教授讲课。有一次张首晟教授讲到所有大科学家都用演绎法。\n\n\n第一性原理是哲科思维中的重中之重因为如果没有第一性原理所有理性系统的建立就都无从谈起。在不同的系统中第一性原理存在的形式也有所不同。在科学领域科学家总是把第一性原理称为第一因在哲学领域哲学家常常将第一性原理与逻辑奇点画上等号。但无论是在什么系统中第一性原理作为系统的根基性命题的地位始终都无法被撼动。\n\n\n当然演绎法的链条不能无限地倒推下去最终必须有一个基石即一个能够自确定的元起点——第一性原理\n\n\n早在2300年前亚里士多德认为在每一系统的探索中存在第一原理它是一个最基本的命题或假设不能被省略或删除也不能被违反。这里的“第一原理”[5],就是我们所说的第一性原理。\n\n\n在哲科思维中有一个最底层、最根基性的算法公式\n\n\n第一性原理+演绎法==>理性系统\n\n\n由于边界条件只能由宇宙外的造物主给定所以宇宙的命运就操纵在造物主的手中。这就是从牛顿时代起一直困扰人类智慧的第一推动力的问题而在哲学领域也有着追究终极的概念当我们不断地向系统的源头追溯时总能找到答案。无论是第一动力因还是追究终极从本质上来说它们都属于基石假设或者说第一性原理。不过受限于人类当前的认知水平我们很难准确地找到所有系统最终的元起点。\n\n\n中国古代的思想家、哲学家老子曾经提出“道生一一生二二生三三生万物”的说法。这里所谓的道其实就是道家思想的基石假设也可以说是第一性原理在道存在的前提下我们才能推导出有关道的一切认知及学问。\n\n\n不是系统之内而是系统之外在这里我们要特别注意很多人在理解第一性原理时经常会将其误解为系统的中心思想。实际上第一性原理并不是系统的中心思想而是这个系统之外、之前的一个元前提。比如在“所有人都会死苏格拉底是人所以苏格拉底也会死”这个命题中第一性原理位于元前提所有人都会死的位置而不是小前提苏格拉底是人或者结论苏格拉底会死的位置。\n\n\n如果用更加贴切的词来表示第一性原理那么“第一前提”或“逻辑奇点”会更加合适。\n\n\n第一性原理的层级之分\n\n\n在演绎法中大系统的中心思想可以作为小系统的第一性原理这意味着第一性原理是有层级之分的。\n\n\n所以系统之间是有层级之分的最简单、直接的划分方式就是“母系统”和“子系统”。某一个系统的第一性原理既可以是一个不证自明的元起点也有可能是一个更大的母系统的中心思想作为子系统的第一性原理。\n\n\n但从实际应用的角度出发我们没有必要去找到那个终极的第一性原理所有比我们想要推导的理性系统范围更大、层级更高的母系统其中心思想或者推导结论都可以作为子系统第一性原理的来源。\n\n\n“道生一一生二二生三三生万物”。问问自己的“一”是什么只有找到并践行属于自己的“一”我们才能很幸福、很笃定、很踏实地生活和工作。\n\n\n有时候逻辑推导过程比最终结果更重要。我们需要培养公理化思维以第一性原理为根基运用逻辑去找到超出我们认知极限问题的答案进而建立其他理性思维体系。\n\n\n从某种程度上讲我们可以把“公理”看作第一性原理在实际生活中的一种表现形式。\n\n\n请大家充分相信理论。\n\n\n实际上欧几里得最重要的身份是哲学家他之所以会开创“几何”这门学科也是为了创造一种哲学思考的工具帮助自己更加深入地研究哲学。\n\n\n此外除了5个公设和5个公理欧氏几何中还包括23个定义诸如点、线、面的基础定义。5个公设、5个公理再加上23个定义欧几里得通过演绎法的推导一共推出了48条定理和467个命题而这些内容最终构成了平面几何系统并且一直沿用至今。\n\n\n德国的思想家、哲学家弗里德里希·恩格斯Friedrich Engels说过“数学上的所谓公理是数学需要用作自己出发点的少数思想上的规定”。换句话说数学这门学科是在公理的基础上通过逻辑推导而得到的比如欧氏几何。\n\n\n正是因为一切学问都是证明系统所以在一些理性学科中我们会发现人们对逻辑推导过程的重视甚至超过了对最终结果的重视。\n\n\n欧几里得对人类科学发展的贡献不仅在于建立几何学更重要的是他首创了一种演绎法思维方式从为数不多的公理出发推导出所有定理和命题从而构建了整个平面几何体系。这种基于演绎法的公理化思维方式才是欧几里得留给后世的巨大财富是人类思维的神迹。\n\n\n也就是说如果你不了解几何学没有数学思维甚至缺乏纯粹逻辑的思维你只能活在你眼前可见的这个世界中。但这个世界太狭小了无论是个人的发展还是人类的进步我们都需要不断地打破物质的限制从不可知的未来中找到前行的道路。从本质上讲几何学是一种哲学同时也包含了某种世界观。\n\n\n为此他进行了一个伟大的思想实验最后推导出一个结论——我思故我在。这句话被称为整个形而上学[8]的第一性原理,也是唯一的第一性原理。\n\n\n所有的顶级科学家都使用演绎法。如果不会演绎法没有公理化的思维方式你只能在实验室里做实验帮助大科学家证明或证伪他们的假设。\n\n\n遗憾的是从某个角度来说公理化思维并不是某些东方人擅长使用的思维方式。自古以来我们的思想家的思维方式就是微言大义。我们遵循圣人之言圣人说过的话就是我们的行为准则圣人也许没有对他的结论进行严密的推理大众通常满足于知道并认同结论就行了。而在古希腊的哲学里任何结论都不重要中间的推理过程才是重要的实体这是一种与东方的传统思维恰恰相反的思维方式。\n\n\n对于这个问题爱因斯坦是这样解释的“西方科学的发展是以两项伟大成就为基础的古希腊哲学家发明的形式逻辑体系在欧几里得几何学文艺复兴时期发现通过系统性实验有可能找到因果关系。在我看来中国贤哲没有做到那些不足为奇。倒是西方科学做出的那些发现才是令人惊奇的事情”。\n\n\n因为我们没有受过几何学背后这种公理化思维的训练。我们从小学习几何却不知道原来欧氏几何是训练顶级思维的教本这无异于买椟还珠。晚清时期面对西方国家坚船利炮的打击清政府发起了洋务运动想要“师夷长技以制夷”。但学习了坚船利炮的技术之后发现其背后还有数学、物理学、化学等基础学科作为支撑。\n\n\n任何时候我们都是被关进自己认知框架的囚徒\n\n\n。就像以色列历史学家尤瓦尔·赫拉利Yuval Noah Harari在《人类简史》中说过的一样“身为人类我们不可能脱离想象所建构出的秩序。每一次我们以为自己打破了监狱的高墙、迈向自由的地方其实只是到了另一间更大的监狱把活动范围稍稍加以扩大。”\n\n\n在企业的创新模型中有一个非常重要的组成部分叫作颠覆式创新Disruptive Innovation事实上破界创新才是一种真正意义上的颠覆式创新。\n\n\n所谓的破界不是破外在现实的边界而是破内在认知的边界\n\n\n。破界创新则是通过打破内在认知边界引起外在现实变化是一种由内而外的创新方式。\n\n\n第一性原理并不在理性系统之内我们作为系统内部的组成部分在大多数情况下很难发现第一性原理更遑论打破它。第一性原理如同系统的“黑洞”一般它既是系统的能量又是系统的禁锢任何系统和个人都很难摆脱这样的“黑洞”。所\n\n\n需要注意的是你重构的“基石假设”一定要比原有的第一性原理层次更深、强度更大这决定了新系统的边界和强度否则便是白费力气。而更深、更大的系统通常都存在于基础学科中如果你仅仅是在商言商就无法提出破界创新的方法论只有基于基础学科的基石假设才会构建出一个更大的系统。\n\n\n敢于打破群体信念这是破除隐含假设的方法之一。\n\n\n欧氏几何建立在5个公设之上基于这5个公设可以推导出这个系统中的全部命题从这个角度来说这5个公设就是欧氏几何的第一性原理。\n\n\n因为我们生活在一个三维世界中所以人类的大脑也习惯于以三维模型的方式去认知事物也就是说我们可以想象出一条弯曲的线或者一个弯曲的平面但很难想象出一个四维环境中弯曲的空间。\n\n\n“我们不是生活在客观世界中而是生活在思想家为我们打造的思想世界中。”\n\n\n破界创新的难点和重点在于如何识别并打破现有系统的“隐含假设”。每个巨头都有自己的隐含假设这也构成了他们的事业边界。因此识别并打破隐含假设是破界创新的关键点也是企业增长和个人成长的不二法门。\n\n\n那次市场调查最大的问题是它的出发点建立在错误的“隐含假设”之上——计算机只可被用于先进的科学研究这是当时人们的共识。这样看来销售量的确有限。\n\n\n它们的不同之处在于IBM很快便发现了计算机在商业领域中的商机因此打破了原有的“隐含假设”重构了属于自己的新的“基石假设”——企业市场是个潜力巨大的新兴市场见图3-4。\n\n\n故事到此我们看看IBM做对了什么。第一步先打破科研市场的隐含假设第二步重构基石假设——计算机在商用市场的潜力巨大第三步升维第一性原理在新基石假设之上重新构架全力投入、将单一要素最大化最终形成新的市场。\n\n\n苹果公司的破界创新也遵循三部曲的典型模式。第一质疑并打破原有隐含假设——凭什么计算机只能用于商业。第二重构“基石假设”——每个家庭都可以拥有一台计算机。第三建立全新系统——既然计算机应该进入家庭那么计算机的所有相关要素都应在家庭使用的大前提下展开如价格、软件、体积等。当第一性原理确定之后所有的细枝末节都会自然地发生变化从而构筑起一个全新的系统。\n\n\n如果把心智和思维打开就会有灵感流淌出来。\n\n\n隐含假设对应到组织时往往表现为使命、文化所以发现并打破隐含假设的过程往往是重建使命、文化和战略的过程我们称其为“组织刷新”。\n\n\n比尔·盖茨是微软第一曲线的建立者founder回顾微软从起步到2000年的这段时间可以用3个关键词串联成的一句话来描述那就是“主营业务是Windows+Offic e运行在P C之上。”这3个关键词几乎代表了盖茨那个时代微软的业务边界而比尔·盖茨也在微软名声大噪时功成身退。\n\n\n创始人的认知边界是一家企业发展的真正边界\n\n\n在以PC时代为基石假设的前提下推导出正确的企业发展路径。但这种基石假设最终成为微软无力挣脱的发展边界。很多人认为微软死于强大的竞争对手实际上微软从来没有被任何竞争对手打败而是被它自己内在的隐含假设被PC时代的第一性原理禁锢。\n\n\n“每一个人、每一个组织乃至每一个社会在到达某一个点时都应该点击刷新——重新注入活力、重新激发生命力、重新组织并重新思考自己存在的意义。”\n\n\n纳德拉用“刷新”这个词指代了企业从第一曲线转换到第二曲线的方法论我个人认为非常贴切\n\n\n[插图]\n\n\n结合微软当时所处的时代特点纳德拉敏锐地发现盖茨对微软使命的定义在逻辑上存在一个极限点微软并没有考虑到一旦目标达成公司接下来的发展方向。\n\n\n同时没有新的目标指引公司的发展方向员工感受不到使命愿景的激励而旧使命反而禁锢了公司的发展。\n\n\n我们往往为了某个目的、某个初心往前走但走着走着就忘了自己的初心是什么这个世界由于我们的存在会有什么不同或者换成更极端的一句话如果你的公司明天消失了会对这个世界有什么影响吗。一般来讲大家会用盈利衡量公司存在的目的而像乔布斯、纳德拉这些顶级的管理者则会从企业存在的意义方面进行深度思考。\n\n\n微软存在的意义是为了打造可以赋能他人的产品。\n\n\n赋能全球每一人、每一个组织帮助他们成就不凡。\n\n\n是把世界的思维分成两种思维一种思维叫固化型思维即内容定下来之后就不会发生变化另外一种思维是成长型思维这种思维相信人是动态的是以动态为“一”的一种思维方式。卡罗尔认为整个世界分为学习者和非学习者两种人固化型思维会限制你的发展成长型思维则会推动你不断前进见图4-3。\n\n\n我们的文化原本是固化死板的。每一名员工都需要向其他人证明自己无所不知证明自己是屋子里最聪明的人不能出一点差错永远不能不敢落后于他人。\n\n\n“固化型思维的公司总在逃避风险却又期待创新的出现。而成长型思维则会把关注点从到底做错了什么转变到我们从中学到了什么。”固化型思维与成长型思维相比一个是看结果一个是看过程。\n\n\n即我们为什么而存在活着的意义是什么\n\n\n第五章 第一创新:基于第一性原理进行创新何谓“第一创新”?如果说破界创新的关键词是“破”,那么第一创新的关键字则是“立”。它是公理化思维在创新中的应用,是从一个抽象的第一性原理出发,用逻辑思维将其拆解,进而推导出这个系统的基本原理,打破原有认知,寻找并建立新系统的过程。\n\n\n破界创新有3个步骤识别隐含假设建立基石假设构建全新系统。\n\n\n其中最难的是第一步是它从具象到抽象的过程。第一创新是基于重要学科的重要理论第一性原理。这里的重要原理不一定只有一个它有可能是几个然后被组合成多元思维模型\n\n\n第一创新的重点是找到第一性原理是从抽象到具象的过程这是两种创新模型不同的要点\n\n\n从归纳创新到演绎创新\n\n\n在所有的科学家中我个人最推崇的就是爱因斯坦。在爱因斯坦之前大多数科学研究都是建立在归纳法的基础上的科学家通过观察和反复实验从某些事物中归纳出定理或规律。随着发现的定理和规律的数量增多科学家发现这些定理和规律都符合某种根基性的第一性原理。\n\n\n如果从更大的范围、更深层次的分析角度来看你会发现所有从经验中归纳、总结出来的创新模型最终都会符合某种第一性原理\n\n\n使用演绎的方法直接定位到某种对企业发展有根源性促进作用的第一性原理然后从第一性原理出发推导出新的创新模型最后我们就可以把这些模型应用到实际的工作中去指导创新实践。\n\n\n比如基于物理学的还原论[1],我们以此作为商业系统的第一性原理,推导出了组合创新[2]的思维模型;基于生物学的进化论,我们在商业系统中推导出了分形创新[3]的思维模型;基于哲学的本体论,我们推导出了破界创新。\n\n\n但现实是在我们的群体认知中哲科思维属于“无用”的学问。\n\n\n并不是哲科思维“无用”而是我们还没有学会如何去应用这种根基性的学问。\n\n\n美国著名的投资家查理·托马斯·芒格Charlie Thomas Munger在《穷查理宝典》一书中说过“如果你只是在商业领域思考你的视野将会非常狭窄。如果你想更好地投资必须更深刻地理解世界。”此外查理·芒格在这本书中还提到了一个重要的概念——多元思维模型。混沌大学经常提及的教学理念——思维模型、刻意练习便来源于此。\n\n\n多元思维模型\n\n\n“锤子综合征”。简单来讲如果你的手中只有一把锤子你满世界看到的都是钉子。\n\n\n在现实生活中我们接受的教育基本都是从普通知识到专业知识即随着受教育水平的提升我们会在一个相对狭窄的领域向前发展。但在进入社会之后我们就会发现很多问题并不能通过一个狭窄领域的工具轻易解决而我们在受教育的过程中已经被植入了某种固定的思维模式所以在离开学校之后大多数人很难快速地融入社会。\n\n\n并不是要求我们深入地学习每个学科而只是学习每个学科中真正的大道理。实际上在每个学科中真正的大道理可能只占全部内容的5%但它却代表着95%的重要性。\n\n\n学习不同学科的差异化思维方式\n\n\n芒格也列举了一些他认为的重要学科的重要理论比如有数学的复利模型、物理学的临界质量模型、生物学的现代综合进化论、化学的自我催化模型以及工程学的备份模型等。芒格认为掌握100个模型就差不多可以拥有通识智慧了而其中非常重要的不超过10个。\n\n\n当然在学习了不同学科的大道理、拥有了多种不同的思维模型之后多元思维模型的建立依然没有结束。我们还要把这些思维植入自己的大脑并用毕生的时间去培养它们让它们变成你随时能够调用的本领。这是一个需要持续一生的训练我把这种训练方式称为“刻意练习”。\n\n\n将这些定式植入思维你会发现在下棋时即便你不去刻意地回想你也能按照定式找到最佳的落子方位\n\n\n换个角度思考我们正处于哲科时代不同的学科都有自己的第一性原理实际上这些第一性原理就是人类的文化基因。\n\n\n人类文明发展至今科技飞跃、信息爆炸但真正能够被称为元知识、元信息的内容就是各个学科的基础理念。\n\n\n国内知名的游戏公司昆仑万维的董事长周亚辉曾在文章中写道“我认为未来30年能做到百亿美元公司的CEO都是科学家、经济学家、历史学家、哲学家他们的思考能力足够深优势很明显。”对于这句话我深表赞同\n\n\n我们习惯于在不同领域中提炼不同的方法论马斯克并没有沿用这个套路他是将同一种底层思维运用到所有领域。迄今为止他的商业实践已经涉及很多领域所以在常人看来马斯克是典型的多元化经营但对他来说其实一直在做同样的事情因为将这些事情拆解到最后我们会发现他用的都是同一种思维方式即马斯克的第一性原理。\n\n\n马斯克曾在接受TED主持人采访时阐述了他的“第一性原理”“我们运用第一性原理而不是用比较思维去思考问题这是非常重要的。我们在生活中总是倾向于比较别人已经做过或者正在做的事情我们也去做这样只能产生细小的迭代发展。第一性原理的思想方式是用物理学的角度看待世界也就是说一层层拨开事物表象看到里面的本质再从本质一层层往上走。”\n\n\n接下来我们用几个案例来展示一下马斯克是如何将这样一个基本原理用同一种方法论在所有涉足的领域中去创造奇迹的即基于物理学的还原论进行组合创新应用到突破性技术上去实现了十倍好的结果。\n\n\n这个角度来讲马斯克提出这个假设充分地说明了他能够站在系统之外看问题所以他才能顺理成章地提出打破群体认知的假设——如果火箭可重复利用制造、人工等各方面成本自然也能够得到有效的控制\n\n\n马斯克的终极梦想是让人类有朝一日能够移居火星而他自己可以在“火星上退休”。为此他创立了Space X并立下了一个看似疯狂的目标“预计40~100年后让100万人移民火星。”他人眼中的夸张之举在马斯克看来仅需两件事即可实现。第一件是拥有过人的意志据马斯克的传记作者阿什利·万斯Ashlee Vance在《硅谷钢铁侠埃隆·马斯克的冒险人生》一书中所述“马斯克的意志无人能比。”第二件是用适当的方法降低成本。不过要想移民火星“十倍好”或“100倍好”的标准肯定远远不够马斯克提出了新的目标——2.5万倍好。\n\n\n马斯克用了18年的时间凭借一家私营企业完成了世界上大多数国家都无法做到的事情。\n\n\n个过程中他的还原论思考模式依然发挥着重要作用。\n\n\n“大多数人都是厨子而马斯克是厨神。千万不要小看这一字之差厨子很多厨神却难得。厨子和厨神的最大区别是厨子是菜谱训练出来的按部就班地做菜厨神则是不按菜谱做菜的。不按菜谱做菜就是不甘于照搬前人的做法不受既有规则的束缚致力于创新。我原以为我们是正常的而他是天才。在我研究之后才发现他是正常的而我们被遮蔽住了。遮蔽我们的恰恰像那些哲人所说的是我们的思维方式本身啊”\n\n\n我们的父母和老师教会我们各种事情是非和黑白、安全和危险以及你应该做什么样的人而不应该做什么样的人。宗旨就是我是大人我走过的桥比你走过的路都多没有商量的余\n\n\n小孩这时候就会开启我们熟悉的“十万个为什么”模式马斯克称之为“连锁为什么”。\n\n\n我将这种学习方式称为“迁移式学习”即把在一个环境中学到的知识应用到另一个环境中既可以把在学校或一本书中学到的原理应用于真实世界也可以把从某一个行业中所学的东西应用于另一行业。\n\n\n在科技界他与其他硅谷大亨进行连续对话后决定共同创建OpenAI旨在推动人工智能发挥积极的作用\n\n\n马斯克说过实现任何大目标都可以分为两步走第一步就是“意志”。敢于梦想大目标并实现它其实是极度孤独的需要极大的意志力因为在实现目标之前由于目标的“不切实际”没有人会相信你也没有人会支持你。\n\n\n所以我们应该敢于敲碎每一个人的玻璃罩子敲碎每一个生命的局限性敢于去碰触那些大问题和本质问题敢于在无限的思维张力中去呈现生命的无限精彩。\n\n\n若将整个宇宙当作一个系统那么这个系统也有它的第一性原理科学家们把它称为“万物至理”。爱因斯坦推导相对论的过程就是他打破物理学的隐含假设建立全新基石假设不断探寻万物至理的过程。\n\n\n爱因斯坦认为第二步从公理出发去推导结论只要勤奋和聪明就一定能够成功而第一步发现公理有完全不同的性质。言外之意发现公理更难。\n\n\n这些定理并不存在于某个物理学的细分系统中而是作为整个物理学的学科基础存在的。爱因斯坦发现这件事情之后如获至宝认为这些规律就是发现公理的前提。在这种思维的指导下爱因斯坦顺利地以一些定律中的定律为前提成功地推导出相对论相关的理论。\n\n\n为了解决这个问题爱因斯坦用哲学推导的方式发现如果在光速运动的情况下时间不再是绝对参考系光速不变才是绝对参考系。在光速运动的环境下时间的地位从绝对参考系降级为“相对时间”而时间也应该建构在光速不变的基础之上。在这个理论的支撑下爱因斯坦提出了一个新的公式即[插图]\n\n\n如果我们把时间和空间合为一体形成时空Spacetime的概念就会发现时空在任何惯性系中都保持不变。换句话说时间是相对的空间是相对的但“时空”作为一个整体是绝对的见图6-2。\n\n\n在组织中我们很容易被群体的信念影响甚至会因此而怀疑并改变自己的观点与他人保持一致以寻求安心这就是“从众效应”。破界创新的难点就是隐含假设而最重要的隐含假设之一就是“从众效应”。对我们来说只有认知到这个桎梏才有机会从中跳出。\n\n\n但悖论是对人而言根本没有独立于“主观信念”之外的“客观事实”或者说所有的客观事实都存在于我们的主观信念当中。\n\n\n也就是说所谓的客观事实都是用主观信念覆盖于其上而且根本无法与主观信念相剥离。如果你没有主观信念你就无法感受到客观事实而一旦你用主观信念去处理那么“客观”两个字就不存在了。\n\n\n事实上人类对客观世界的感知有且只有眼、耳、鼻、舌、身5条感官通道分别产生视觉、听觉、嗅觉、味觉和触觉。其中视觉和听觉最为重要人类一生中获得的所有认知80%来自视觉18%来自听觉。\n\n\n其实明朝著名的心学家王阳明先生也说过这样的话“心外无物心外无理。”意思是说所有的事物和道理都存乎于心。\n\n\n人类用这种简化和扭曲了物态的感官系统有效地建立了我们的生存辨识系统但同时也付出了永远无法认知世界“真相”的代价。我们只能感受到我们主观感受到的东西永远不能直接感受到所谓客观存在的客体。从这个角度理解我们从小到大学习的一切知识都是人类的主观思维模型而不是客观世界的真实反映。\n\n\n我们再来看人类判别真理的第二条路径——真理连贯论也就是根据信念与群体信念的一致性判断信念是否为真理的方法。简单来讲如果某个信念与群体信念一致那么这个信念就被认为是“真理”。\n\n\n对群体而言“做出简洁有力的断言不理睬任何推理和证据是让某种观念进入群众头脑最可靠的办法之一”。而“夸大其词不断重复言之凿凿绝对不以说理的方式证明任何事情是说服群众的不二法门”。\n\n\n在群体中个体不再是原本的那个自己而变成了不再有独立思想的傀儡\n\n\n英国的哲学家伯特兰·罗素Bertrand Russell“很多人宁可死也不愿意独立思考。”因为群体中的独立思考等同于用自己的意识去对抗天性用思想去对峙身体。\n\n\n第八章 批判性思维:我讲的可能都是错的科学革命并不是知识的革命,而是无知的革命,商业领域的创新也是如此。批判性思维是创新精神的第一特征,也是打破认知边界的必要条件。只有学会独立思考、普遍怀疑,愿意承认自己的“无知”、敢于质疑群体共识的观点,才可以打破原有的认知藩篱,突破创新。\n\n\n在逻辑学领域信念“正确”的判断标准是“逻辑三洽”即自洽、他洽和续洽。\n\n\n热力学第二定律即熵增定律是不太容易被推翻\n\n\n首先逻辑三洽虽然听起来简单但它是一门高深的逻辑学技能没有学过逻辑学专业知识或受过专业逻辑训练的人很难自如地应用这种方法其次在逻辑和理性之上始终存在一个更强大的力量它阻碍了我们对理念正确的判断这个力量叫作“我执”而破除“我执”的过程需要应用批判性思维。\n\n\n在我们的生活中99%的争吵其实都不是为了捍卫“我的思想”,而是一种出于本能的对自身存在性的防卫。\n\n\n他认为占星术实际上也是在利用人们习惯于对事物进行归纳的解读再加上一些放之四海皆准的广泛性描述从而激发人们的共鸣。所以占星术从某种程度上可以被定义为一种语言艺术既不能证伪也与科学无关。\n\n\n所谓反共识其实就是将批判性思维、普遍怀疑、不可知论运用到工作和生活中。\n\n\n。我们的案例都是“借假修真”不用在意具体的内容而应该通过案例去理解思维的框架。罗素说“这个世界的问题不在于聪明人充满疑惑而是傻子们坚信不疑。”王东岳老师也提出“大多数人的共识一定是愚蠢的。\n\n\n质疑一切特别是权威勇于尝试上路流浪无所畏惧创造一个更美好的世界。”\n\n\n走入混沌是为了走出混沌。柏拉图在著名的“洞穴隐喻”里\n\n\n所以柏拉图说真正的教育不是把墙上被投射出来的光告诉洞穴里的人而是把洞穴里的人带到洞穴之外让他自己沐浴在真理的阳光之下。\n\n笔记\n\n我们突然发现已经适应的环境突然改变脚下赖以生存的根基正在坍塌要想生存下来只有两条路可以选一是在原有的基础上加固即将坍塌的根基这一条路相对容易一些这也是大多数人的选择二是找到新地基。\n\n💭 一定要学会拥抱变化,迎接未来!\n\n我想起了英国前首相丘吉尔的一句话“永远不要浪费一场好危机。”也许脚底的根基坍塌了未必是件坏事\n\n💭 风险与机遇往往是并存的\n\n纳德拉说“我说的不是宗教意义上的灵魂而是一种最自然的、表露内心的声音。我们必须回答一个问题这家公司是做什么的我们为什么而存在”\n\n💭 我们是谁?从哪来?到哪去?\n\n纳德拉认为AWS是公有云的策略主要客户是中小型客户而除了这些中小型客户市场上还有一定数量的大客户在云服务方面的需求未能得到满足。所以微软巧妙地避开了AWS的强势领域从大客户入手量身定制了符合大客户需求的云服务解决方案其中包括混合云、智能云等。微软甚至还为大客户提供了一些独一无二的工具比如办公软件一键引入功能等。微软作为后起之秀在云技术方面并不比AWS做得更好但它的服务是相对独一无二的。\n\n💭 差异化竞争\n\n2015年纳德拉把Windows连同Xbox主机、Surface PC等一系列业务打包划入“More Personal Computer”这一业务类别迈出了“去Windows化”的第一步。2018年3月微软宣布了纳德拉上任以来最大的公司重组计划将Windows部门分拆后并入两个新成立的部门中。至此Windows这个词甚至都已经在微软内部消失了。\n\n💭 我们要有打破传统思想的勇气,冲破思维定势的束缚。\n\n每一个系统都有自己的第一性原理但是系统有大系统和子系统之分因此不同系统的第一性原理之间也有层次关系。\n\n💭 递进关系\n\n软件方面Space X“猎鹰9号”和龙飞船用的都是Intel双核的X86处理器操作系统用的是Linux还有LabView和Matlab此外它的软件开发基础语言是C++偶尔也用Python并且整个主控程序只有几十万行代码。\n\n💭 我……\n\n基于第一性原理的第一创新是将同一种思维方式运用于不同的领域。\n\n💭 打破常规\n\n当她看到这棵苹果树并形成了对苹果树的印象时这个印象是绝对客观的苹果树还是她脑海中的苹果树呢\n\n💭 很好理解,她看到了这棵苹果树,背身过去瞬间砍掉,问她苹果树什么样?答案显然是 脑海中的苹果树。\n\n他认为有一种特别的虚构故事叫“主体间共识”即使只是虚构的故事但经过群体的认可这个故事就成了所谓的真理。\n\n💭 三人成虎 🐯🐯🐯\n\n波普尔认为“能够认识到并承认自己错了是证明一个科学家仍旧还是科学家的标志”。量子物理学领域的顶尖学者朱利叶斯·奥本海默Julius Oppenheimer也说过“在科学界犯错并不是罪过。生活中也需要这种能力即脸不红心不跳地说我当时搞错了。这与人们没完没了地去寻找一些合理化说法来为自己先前的错误辩解的做法完全不同”。\n\n💭 学会认错\n书评\n\n✨第一次了解相关概念整体阅读下来还是有收获的值得一读。 整体有些读者味,内容东拼西凑,甚至毫无关联。而且底层逻辑站不住脚,看不到逻辑推演…\n\n点评"},"Personal/Book/哲学宗教/结构化思维":{"title":"结构化思维","links":[],"tags":["阅读/哲学宗教-思维科学","阅读/笔记"],"content":"简介\n\n书名《结构化思维》\n作者 黎甜\n分类 哲学宗教-思维科学\nISBN9787514227697\n出版社文化发展出版公司\n\n概述\n学会结构化思维让人生从此提效。《结构化思维》可以帮助我们在陈述问题、表达核心观点的时候能少说废话将复杂问题简单化清晰准确地表达观点建构条理清晰的思考模式。学会有结构、有规律地整理复杂信息让人生从此提效。拯救无效努力成为你想成为的自己。有些人看起来很努力但是却不出成果。高效的思考力并非天生而是长期自我训练的结果。系统化的思维方式让深陷思维泥沼的人走出思维误区达到事半功倍的效果。全书干货满满是一本比较实用的思维进阶实修课。万事万物皆有结构皆成框架皆成系统。本书在搭建结构化思维关键方法的基础上介绍了八种升级版的思维结构具体方法配合落地训练每个人都能从中找到适合自己的思维模式。\n划线\n\n一段时间以后人们惊奇地发现这些幼儿园的5岁的小朋友语文能力超过外面10岁的小朋友最让人诧异的是小朋友的情商EQ竟然能超过外面的青少年。\n\n\n让思考过程更加有逻辑让思考结果更加有价值。\n\n\n构建结构化思维让零散、无序的思维方式变得系统化、有序经得起深入分析和推敲的思维结构是改善思维方式的必经之路。\n\n\n人生不如意事十之八九\n\n\n思维是我们解读事实的起点是产生行为的源头是决定结果的根本。\n\n\n在一次又一次的思维循环里思维过程重复多次就会形成固定的思维方式\n\n\n认知心理学认为一个人的情绪并非由事件引起而是由个体的思维方式决定即思维方式决定情绪。\n\n\n所以与其说“选择决定未来”“努力创造成功”都不如说“思维方式决定命运”。\n\n\n是什么What是什么划破了我的手、为什么Why为什么草能划破我的手、怎样做How我的工作怎样运用小齿的2W1H结构来全面思考问题的。\n\n\n就像玩积木每块积木都是一个思考部分搭建房子就需要把多种不同形状的积木按照房子的模型搭建起来房子的模型就是系统结构按照系统结构搭建思维的过程就是结构化思维。\n\n\n获取信息当大脑接收到外界的信息或调取自身存储的信息又或者迸发出灵感时就完成了获取信息的过程。加工处理面对不同的信息大脑会做出不同的反应常见的有分类定性、分解、理解、筛选、联想、想象、归纳、演绎等。呈现结果对信息加工处理后对信息输出的过程包括在大脑内的存储和用言行表达。迁移运用把加工后的信息“变形”或者运用在其他事务上也就是我们通常说的“举一反三”。\n\n\n大脑可能随时产生灵感不需要外界的刺激。灵感的产生具有随机性、偶然性即典型的“有心栽花花不开无心栽柳柳成荫”。\n\n\n关键点包含事件的六要素人物、地点、时间、起因、发展、结果。\n\n\n但是有一点必须注意那就是我们最容易获得的信息通常是别人希望我们看到的信息。\n\n\n其实A和B手机从来没变过是什么在影响我们的判断是信息的全面性。\n\n\n定性就是确定属性分类就是区分类别。\n\n\n这个例子充分说明了我们对事物的理解不能只停留在表面的感官上还要深入了解本质、规律才是真的理解。\n\n\n2独立操作理解的另一个标志是根据对信息的理解能独立完成所需要的动作或任务。仅根据他人的指导完成任务不能认为是真正的理解。对客体进行实际操作常能帮助理解。在\n\n\n没错就是大脑的自动筛选功能。大脑会自动帮我们从海量信息中筛选出符合我们关注的信息。这些信息都是与我们自身息息相关的也许是自己的现状、需求或者是自己认为对的事物。\n\n\n标准化、格式化虽然能大大提高效率但会扼杀想象力不容易创造出跨时代的艺术或产品。\n\n\n[插图]\n\n\n想要提高信息的存储量和时长首先我们在记忆时要集中注意力筛选信息留住想要存储的信息其次要充分调动原有的信息并产生联想让信息存入多个“抽屉”最后刻意复习按照遗忘曲线定期复习。记忆周期\n\n\n有效沟通包含三大要素这三个要素对沟通结果的重要性占比分别为肢体语言55%语音、语气、语调38%而文字内容仅有7%的意义。\n\n\n第三借用新资源整合现有资源就是创新。\n\n\n时代在不断地进步和变化我们要勇于拥抱新事物、整合多种资源让自己的效率得到更大的提升。\n\n\n“感觉”则是人对事实的认知不同的人会产生不同的主观感受也就是说“感觉=事实+经验+主观感受”。\n\n\n二、从他人的表达里发现真相\n\n\n我反思自己1993年出生的人在2018年是25岁我对25岁已经没有概念了只能回想我在这个年龄的时候干了什么。\n\n\n思维的过程复杂多变虽然我们能用获取信息、加工处理、呈现结果、迁移运用这四步来概括\n\n\n思维方式会随着年龄的增长经历、阅历的增加而改变。唯一庆幸的是这种改变对于绝大部分人而言都是在更系统、更高级的思维结构上的进步。\n\n\n归纳和演绎可以帮助我们认识事物、升级认知然而在以往的学习中我们却并没有经过专业的学习和训练。\n\n\n所以我们有相当一部分人因为缺乏高度归纳和演绎的思维没有独立判断事物的能力往往导致人云亦云或者跟随媒体或者“网络愤青”也称“键盘侠”的步伐赞同或者怒斥某些人或者行为当真相最终被揭露时又经常推翻自己先前的结论。\n\n\n表达时我们应该尊重对方考虑对方的感受。\n\n\n做完上边的两个练习你会发现难的并不是归纳本身而是缺乏“提炼信息并归纳”的思维。\n\n\n“完全归纳”具有严谨性而“不完全归纳”则存在一定的猜测所以我们不能用“不完全归纳”来取代或者混淆“完全归纳”这样会造成“黑天鹅效应”。\n\n\n一手信息和二手信息之间往往差别很大其中有两个关键因素第一大部分人往往分不清事实和感觉。\n\n\n第二不是人人都具备严谨的逻辑思考能力。\n\n\n演绎是逻辑学中的演绎推理是从一般性的前提出发进行推导得出具体或个别结论的过程。\n\n\n大前提一个客观事实。小前提属于事实的子范畴子范畴就是圆中的一部分被包含。结论根据相关性得出的结论。\n\n\n这意味着如果一个人的价值观、认可的规则是错的在不同情境、不同的外因下做出的决策就都是错误的。\n\n\n不同的大前提价值观才是导致言行相去甚远的关键因素。我们的自我成长、培养下属、给孩子的教育都应该是以正确为大前提价值观。\n\n\n所以我们要对事物能描述出可以衡量的标准、期望的状态再对照现实才能发现问题。\n\n\n逻辑树的方式本质上也是一种结构化思维关于如何构思和搭建结构化思维可见第四章\n\n\n常用的方法有“堵”“疏”“斩”“替”。\n\n\n“问题—原因—解决方案”的运用就是\n\n\n归纳的本质是情况—结果—规则。\n\n\n演绎的本质是规则—情况—结果\n\n\n因此归纳为演绎指导了方向演绎为归纳提供了理论依据。在工作生活中归纳和演绎总是互为因果。\n\n\n在线性思维之上我们还需要学会用多个线性思维组成结构化思维用多角度、系统化的思维方式来思考和解决问题。\n\n\n结构化思维是一个建立清晰、稳定、有序的思考结构\n\n\n结构化思维是一个建立清晰、稳定、有序的思考结构我们学到这个结构之后知识体系从零散化到系统化从无序到有序从低效到高效。\n\n\n喜欢做菜的人在做菜之前一定会先想好做什么菜准备什么配料用什么锅、多大的火以什么方式来烹饪\n\n\n结构化思维每个人都在用只是很多人是在潜意识里使用的而不是有意识地用这种思维指导自己在缺乏经验的领域里进步。\n\n\n金字塔结构是将结构化思维具象成一幅画后形成的类似三角形结构的树状图它直观地体现了由结论、论点、论据组成“先总后分”的结构。\n\n\n金字塔结构的4个原则·结论先行。·以上统下。·归类分组。·逻辑递进。\n\n\n没错就是结论先行。因为一旦结论先行大脑对于后来接收到的信息就不再是逐句分析推理出结论而是判断论据能否支撑论点。\n\n\n结论先行能够帮助我们聚焦中心。\n\n\n结论先行就是先给出具体的结论放在金字塔的顶端统领整个中心思想和表达。\n\n\n归类分组是根据信息的共同属性分组的共同属性包括但不限于性质、功能、方向、层次、对象、时间等。\n\n\n“MECE原则”\n\n\nMECE原则”来自麦肯锡咨询公司中文意思是“相互独立、完全穷尽”。简单来说就是各个要素之间要保证不能有交叉也不能有遗漏也就是“不重不漏”。\n\n\n二分法\n\n\n2矩阵法。就是将二分法运用两次第一次是一个维度第二次就是另一个维度。\n\n\n流程法。按照事情发展的时间、流程、程序对信息进行逐一分类。\n\n\n结构法。即把事物拆分为不同的构成部分。\n\n\n我们可以把自己做事过程中的流程、方法、技巧总结成标准化的步骤完成对自己工作的梳理和总结从而迁移到做其他任何事都能井井有条、抓住重点、直面核心。\n\n\n工作总结描述现状—总结要点—改进方案。工作汇报描述现状—给出多种选择方案—建议选择的方案。\n\n\n竞聘演讲工作经历—竞聘优势—竞聘成功后的工作设想。\n\n\n经验分享提出观点—说明原因—阐述对策。\n\n\n5公式法。按照公式设计的要素进行分类只要公式成立这个分类就符合MECE原则。\n\n\n归类分组需要符合MECE原则有5种方法可以做到“不重不漏”①二分法②矩阵法③流程法④结构法⑤公式法。\n\n\n当信息的排列不具有逻辑性时大脑就会陷入混乱不知道如何进行加工处理所以信息排列需要按照一定的顺序。\n\n\n时间顺序\n\n\n空间顺序\n\n\n重要性顺序\n\n\n演绎顺序\n\n\n介绍了4种逻辑递进的排序方式之后相信大家已经对排序有了比较深的认知但是很多朋友可能没有意识到排序需要考虑对方的需求和利益\n\n\n只是每个人看问题的角度不一样而已。站在当下福利待遇确实最重要毕竟不饿死的人才有未来可是站在十年后的角度来看呢排序又不一样了所以要以谁的排序为准呢\n\n\n判断一个人的认知水平的高低有两个简单的标准第一看他在谈论一件事的时候能够熟练地运用多少概念工具越多越好。第二看他在评价人的时候能否少用概念越少越好。\n\n\n我们尝试对7个论据分组①②⑤都是说该员工服从性强只是服从的不同维度分中心、规章制度、领导③是说性格活泼、易相处④⑥都是在说执行力执行力强是概况具体的表现就是提前规划、迅速行动、今日事今日毕。⑦是业务结果恰恰是领导最重视的应该放在最前面如果能有数据佐证会更加打动人心。\n\n\n注逻辑方式有很多种也可以将离职原因前置只要符合逻辑排序合理即可\n\n\n我们一直强调要多阅读、多学习、多了解最新信息目的就是要学会和掌握各种思维框架。这样可以有效提升我们的工作效率框架越多我们的工作能力就越强。\n\n\n在此我们要问几个问题1结构是否清晰明确2论据能否支撑论点论点能否支撑结论3归类分组是否符合МЕСЕ原则4排序是否符合逻辑\n\n\n其他思维结构与金字塔结构最大的区别有两种一是在画图的方向上的区别决定了以上统下、以左统右还是以中心统四周二是归类分组上是否有既定的类别和属性。\n\n\n①5W2H思维②认知圈思维③流程思维④人事物思维⑤故事思维⑥客户思维⑦水平思维与垂直思维⑧T字思维。\n\n\n在处理任何事情时第一步不应是如何做How而是谁来做Who、做什么What。\n\n\n①认清事实②找回初心③重新行动。\n\n\n有成本意识这是主管与经理之间质的差别之一。\n\n\n[插图]\n\n\n是什么What、为什么Why、如何做How是人类认知事物的过程。所谓认知事物就是从未知到已知再到建立对这个事物的看法的全过程因此称其为认知圈思维。\n\n\n查理·芒格有一句话是“手上拿着锤子的人看什么都像钉子。\n\n\n请各位一定要理解每一种定目标的方式都是对的也都是错的。因为任何一种理论、方法它都有它的适用边界也就意味着我们每个人在不同的阶段定目标的方式和方法也不一样。\n\n\nA是什么适合谁在什么情况下使用达到什么目标。\n\n\n询问“为什么”往往不是一次就可以的我们要连续问几次“为什么”以达到追根溯源、找到底层逻辑的效果。\n\n\n这是一个保温杯它的纳米材质和嵌入式封闭接口可以让它的保温效果达到最高级84摄氏度的水倒进去24小时之后还能有70摄氏度半夜起床也能喝到一口温热的水。无论是出差还是旅行都能一路温暖。\n\n\nWhat—Why—How模式是一个比较完整的认知过程我们在实际运用中常常会忽略其中一个或者两个环节。\n\n\n建立完整的认知过程能让我们思考全面不会陷入牛角尖里。\n\n\n所以认知的顺序是What—Why—How这个顺序适用于我们对已知事物的认知清晰的情况那么对于未知事物的认知顺序是什么呢\n\n\n黄金圈思维模式\n\n\n但是Airbnb则是反其道而行之旅行为什么一定要住酒店人们需要的真是酒店吗可能很多人需要的就是一张床和一顿早餐。这就是黄金圈思维的威力把“Why优先”的思考方式当成习惯能更深层次地理解用户的真实需求直击问题的本质。\n\n\n[插图]\n\n\n我需要的是系统的会议管理制度而不是打补丁式的会议制度。否则一个会议管理我都不知道你要整出多少制度这种管理太散了让人不放心。”\n\n\n提出问题、分析问题然后去解决问题是李先生的强项。\n\n\n由此可见李先生在制度完善的外企担任经理一职是在完善的制度之下落实执行的工作。而正在高速发展的民营企业制度还没有完善即使完善也是阶段性完善随着企业的发展还需要继续完善各种制度他需要做的是使用全面解决问题的思维由小至大由点到面自始至终。\n\n\n流程是把一个或者多个输入转化为对客户有价值的输出的活动。\n\n\n在流程中一共有6个要素需要我们进行把控\n\n\nPDCA的含义是将管理分为四个阶段即计划Plan、执行Do、检查Check、调整Action。第一阶段做出计划第二阶段实施计划第三阶段在实施过程中要检查实施效果第四阶段根据检查情况不断调整行动方案之后进行复盘总结优缺点指导下一次活动。\n\n\n我们的目标是从整体出发解决问题当我们已经养成了会思考前沿和后沿的习惯后最终的顺序是P—DC—A前沿—主活动—后沿。\n\n\n规划指的是策略、计划、预算、政策、标准。\n\n\n在优化流程时我们应该遵循ESIA法。E——Eliminate清除S——Simply简化I——Integrate整合A——Automate自动化。\n\n\n在处理客户投诉时有一个“黄金24小时”的说法即客户投诉的24小时内是妥善处理的黄金时间这样能提高客户的满意度避免客户投诉升级。\n\n\n[插图]\n\n\n流程思维适用于还没有建立流程想要对事情进行整体把控的时候比如活动流程、销售流程也适用于需要标准化的时候比如新店开业流程、工厂作业流程。\n\n\n流程思维的重点在于事人事物思维的重点在于人要先明确参与人员把人安排清楚满足人的需求因为事和物是由人来行动和操作的搞定人事和物自然水到渠成\n\n\n相处建立情感沟通获得理解为对方争取利益。\n\n\n在人事物思维中分析人的时候难免会带上所要处理的事情和物品因为人是主语要形成一个完整的分析或者指令主语后面必然要有谓语和宾语。宾语是什么就是我们要对接的人或处理的事情、准备的物品。在分析完人之后再罗列事和物可能会出现重复。\n\n\n但是让人事经理出马就不一样了因为他掌握着员工晋升、加薪的建议权所以在这件事上员工面对节目瞬间变得重视起来。\n\n\n忘记做事的核心价值是在培养人。\n\n\n电影《后会无期》有句很经典的台词“听过很多道理依然过不好这一生。”\n\n\n运用故事的力量无论理解、记忆还是说服、行动都会事半功倍。\n\n\n讲一个故事首先要把背景交代清楚。因为其他人不是我们肚子里的蛔虫在不知道事情的背景之下他们很难理解主人公的选择和心里的矛盾。\n\n\n冲突是建立在背景之上与我们的预期、常识、主流价值观不符之处。\n\n\n那是一颗可爱的、俏皮的甚至有一点点蛮横的但是从不遮掩、从不伪装的少女的心啊。这个世界上还有什么比一颗愿意陪伴你到老的真诚的少女的心更宝贵的东西吗\n\n\n编完了一个故事不知道大家是否开始建立起故事思维呢我们在表达观点时可以尝试用故事的方式反复练习当需要表达观点、劝说、具象化理念时我们可以用故事的方式凸显。\n\n\n讲故事有四种方式分别是标准式、开门见山式、突出忧虑式、突出信心式。\n\n\n4突出信心式问题—背景—冲突—回答。\n\n\n建立故事思维灵活运用故事化的各种模式让表达更有感染力、说服力对方才会更认同也更易于接受记忆更深刻更容易转化为行为这就是故事思维的魅力。\n\n\n由于背景、教育程度、经验、立场不一样人们面对同一件事的态度、想法和需求也不一样我们拿自己的需求去要求其他人是无法让他人来接受和埋单的只有我们站在对方的角度去考虑才能理解对方。当对方知道我们是理解他、懂他、认可他的他才会反过来认同我们。\n\n\n不同的人、不同的角度面对同一个问题就会有不同的思考和解答我们不要被自己单方面的思维局限去固化一个问题的答案。世界本就多姿多彩有无限可能。我们站在对方的角度不仅能理解对方还能因为满足了对方情感或者物质的需求进而获得对方的认同。\n\n\n客户思维是一种思维观念渗透在一个人的言行里渗透在一个人的价值观里。\n\n\n[插图]\n\n\n1对方的需求是什么明白了对方的需求我们才能对症下药。\n\n\n2对方的特点是什么特点包括性格、才华、嗜好、为人处世的方式等。\n\n\n3对方忌讳什么忌讳的事情尽量不做了解这一点我们可以少走弯路。\n\n\n直奔主题的人必然拥有结构化思维喜欢说故事的人必然拥有故事思维。\n\n\n所以对方是否容易吸收信息不是取决于我们自己的表达习惯而是取决于对方的表达习惯。\n\n\n我们用对方喜欢的表达方式能更顺畅地与之沟通也能做到情感上的共鸣。\n\n\n笔者建议知识类的信息借助文字或者图画传达技能类的信息用道具或演示方法类的信息除了告知步骤、注意事项还要举例加深印象。\n\n\n大多数人的思维是“你说的对但我想要的是……”这种“yes,but…”的否定式思维往往不会受到对方的认可我们要转变为“先承认对方的需求再提出自己的目标”这种“yes,and…”肯定式思维。\n\n\n“yes,and…”提供的是双赢的解决方案我们不仅要满足对方的需求还要明确自己的目标。\n\n\n“你眼中的问题就是别人眼中的解决方案。”\n\n\n客户思维不是纠正自己看到的问题而是要和对方一起面对他所要解决的问题。\n\n\n我们在舒服的范围里增加一点点的工作难度不仅有安逸的舒服而且还是有成就感的舒服。\n\n\n慢慢增加工作能力既安逸舒服又能有成就感慢慢也有了抵抗风险的能力。\n\n\n[插图]\n\n\n1汇报工作时直接说结果。\n\n\n2请示工作时说方案。\n\n\n3总结工作时说关键点。\n\n\n4规划工作时说标准。\n\n\n在上下级关系中上级用“为什么”发问时往往容易使下属产生负担。\n\n\n用授权的方式让下属放手去做事虽然我们不会完全放心却可以培养下属的能力这才是真正地“为他们好”。\n\n\n水平思维强调的是寻求看待事物的不同角度和不同方法是求创意、求数量的浅层思维方式。\n\n\n而水平思考关注的是“可能性”。\n\n\n任何一个患上不治之症的投保人都可以立即获得去世后所得金额的75%。\n\n\n水平思维往往意味着绝处逢生在一片红海中厮杀找到一条通向蓝海之路。\n\n\n当我们为实现一个设想思考时很有必要摆脱掉一直被认为是正确的、固有的观念束缚\n\n\n随意输入法\n\n\n反向型激发\n\n\n摆脱型激发\n\n\n我们不必把咖啡的价格定得很高以补偿时间损失而是以便宜的价格售卖咖啡但在咖啡桌中间摆一个计时器以便于计时收费在客户落座时记录时间离开时结算。\n\n\n妄想型激发\n\n\n垂直思维则是把眼镜的某一方面深入分析。以品牌为例目前市场上有哪些眼镜品牌把这些品牌各自的历史、经营理念、专利技术、特色款式、产品优缺点、营销渠道等了解清楚我们能整理出一份行业说明书。垂直思维能让我们在某一领域或者专业技术上精通透彻成为专家。\n\n\n选择某一方向后以“What—Why—How”“Why—Why—Why”流程思维等形式的线性思考方式进行深入探讨以解决问题实现目标的结果。\n\n\n六项思考帽\n\n\n垂直思维法是以逻辑与数学为代表的传统思维模式。这种思维模式最根本的特点是根据前提一步步地推导既不能逾越也不允许出现步骤上的错误。它有非常强的逻辑性、推理性能够让我们专注于一个点深入分析\n\n\n可以充分说明垂直思维与水平思维的区别。垂直思维集中考虑的是姑娘必须取出一块石子而水平思维是把注意力集中在口袋里剩下的那块石子。\n\n\n水平思维是一种既非逻辑性又非因果性而是属于超越性的思考方法。它可以从答案出发对问题进行思考\n\n\n水平思维具有创造性适用于寻找多种解决方案的情况垂直思维能帮助我们深入分析问题、认知事物在较短的时间内对事物有深刻的认知。\n\n\n水平思维和垂直思维各有优缺点把两种思维方式结合使用就能扬长避短变成新的思维模型先水平再垂直。\n\n\n水平思维和垂直思维的结合运用既能够扩大视野又能提高分析能力。有的人习惯用水平思维思考凡事有很多想法却没有落地分析和行动有的人习惯用垂直思维思考关注局部、沉迷细节却没有看到整体结构或者周围环境。\n\n\n重点工作和新项目则建议水平思维和垂直思维结合\n\n\nТ字思维是“横向思维”和垂直思维的结合把思维的过程外显出来可以画成一个Т字图案。\n\n\n垂直思维具有深入性。垂直思维是解决流程思维中间的某一环节、某一问题所以垂直思维是结果导向以解决问题为目标。\n\n\n用流程管理来把控横向节奏用垂直思维深入透彻分析每一个关键事项以达到从全局的角度掌控复杂工作推动工作发展的目的。\n\n\n[插图]\n\n\n[插图]\n\n\n第九节 刻意练习,终成思维高手\n\n\n学习完这些思维方法之后要刻意地在生活中运用\n\n\n认真负责地做好自己手上的每一件事情这也是一种学习一种和听课、读书、作业同样重要的学习。\n\n\n是把简单的事情重复做、认真做。\n\n\n而是因为它能将简单的事情持续做、坚持做。\n\n\n第三工作要做好记录及时总结收益。什么样的总结能打动人心一定不是那些空虚的话也不是喊一些“好好工作坚持干踏实干”的标语而是有具体的内容和收益。上文那位同事的总结之所以优秀最大的原因在于她把入职以来几年的工作都进行一一罗列内容很充实、具体、有场景这样才有说服力。\n\n\n每做完一个新项目或者贡献值大的项目就应该有一个专门的文档进行记录需要总结的时候随时复制、粘贴。\n\n\n灵活自如地运用结构也就能自己建立思维模型对自己的知识体系进行升级和重构甚至创造属于自己的思维模型\n\n\n只有把“道”研究清楚把总结出来的机制、规律、原理放到自己的问题里我们才会融合变通地解决自己的问题最后形成自己的“术”。\n\n\n“道”是规律是万事万物运行的轨迹“术”是人遵行自然规律的做事方式。“道”是万变不离其宗的根源“术”是因时制宜、因事制宜的做事方式、解决方法。\n\n\n只有我们理解并掌握了运营之“道”才能迁移到自己的工作和产品上。\n\n\n举办这样的活动、活动开展的过程遵循了什么规律、什么人性\n\n笔记\n\n我们可以看到鲁班的思维方式是比较成熟的在手被草划破时思考“为什么”之后还联想到了“蝗虫”找到共同的规律之后再将其运用到实践中。\n[插图]\n图1-4 鲁班的思维过程\n\n💭 举一反三。触类旁通\n\n人和人最大的差距便是思维方式\n\n💭 夏虫不可语冰,井蛙不可语海。\n\n行动要遵循的思维结构有很多因为不同的行动而变化其中PDCA却是任何行动都可以遵循的原则和思维P是计划PlanD是执行DoC是检查CheckA是调整Act。\n\n💭 做一个行动派,先僵化再优化。\n\n我们不缺乏解决问题的思维而是缺乏事实界定的思维。\n\n💭 实践是检验真理的唯一标准\n💭输入思考实践复盘。\n\n归纳就是从个别到一般演绎则是从一般到个别。\n\n💭 一般到特殊,特殊到一般\n\n总而言之\n\n💭 总而言之,言而总之哈哈哈\n\n对于复合型信息要先提炼核心思想再归纳出结论。\n\n💭 抽象\n\n真实情况是各种前因后果不连贯的事件零散无序地出现我们能不能把它们放在一起对它们进行归纳总结。所以我们要经常把具有同样因素的事件放在一起尝试对它们进行归纳按照相似的人、相似的事、相似的客观环境、相似的步骤流程进行归纳。\n\n💭 复合型信息\n\n就像前文举例的小明的成绩笔者列举了小明的三门主科成绩在90分以上如果归纳出“小明成绩优异”其实是属于“不完全归纳”这并不能代表小明的地理、生物等其他科目的成绩也都在90分以上。\n\n💭 具体和抽象\n\n尽量寻找一手信息对二手信息心存疑虑\n\n💭 信息本身就是一种资源,一手信息谈何容易,都是垃圾堆里找宝贝罢了。\n\n第一大部分人往往分不清事实和感觉。\n\n💭 二手信息自带主观臆断just feel。\n\n调查显示住学区房的孩子比不住学区房的孩子平均成绩高。这个数据是随机调查198户人家得出的结论。所以为了孩子我们一定要买学区房\n\n💭 当你判定一个因素可能决定一件事的时候,可以试着反推,例如文中的例子就是:成绩高的都是住学区房么?\n0.影响学习成绩的因素都有哪些?\n1.内在因素都有什么?\n2.外在因素都有什么?\n3.学区房直接,间接影响了那些因素?\n4.这些影响因素决定成绩高低的比重多大?\n答案一目了然要学会分析问题看清问题的本质。\n当你思考完这个问题后可以尝试跳出来重新看待这个问题。\n毕竟低纬度复杂性问题往往是高纬度简单问题的投影。\n冲冲冲奥利给\n\n结论只能代表当下不能代表未来因为世界一直是变化的\n\n💭 经验总结代表过去,拥抱变化才是真的。\n学会不断的输入实践复盘改变。\n\n对得出的结论进一步用事实验证从多个角度证实或证伪\n\n💭 看待事物始终要多层次,多角度,全方位的思考。\n\n对得出的结论进一步用事实验证从多个角度证实或证伪\n\n💭 输入,实践,复盘,改变。由此往复,实践才是检验真理的唯一标准!\n\n记得每位下属的生日提前准备小礼物记得每位下属的家乡过年过节会安排能同行的员工一起结伴回家……\n\n💭 尊重人性\n\n所有的A=B\nC=A\n所以C=B。\n\n💭 数学中的集合关系哈哈哈哈\n\n归纳是从生活中总结常见事物而得出的一个结论这个结论就会成为公理、规定、规律。演绎的前提就是我们得出的公理、规定、规律。因此演绎以归纳为基础归纳为演绎准备了条件。\n2归纳为演绎提供了指导\n\n💭 输入\n公式\n输出\n数学真的yyds\n\n点状思维就是学习和思考的过程中信息点没有发生连接而是像一座一座的独岛单独存在于你的大脑中。\n\n💭 点成线,线成面,面成体\n\n从点状思维升级到线性思维的常见方式除了第二章中的联想\n\n💭 点状思维,线性思维,方面思维,立体思维\n\n因为我们的大脑会默认我们说话的前后句具有某种逻辑关系大脑会一句一句地推导和理解前后句的逻辑关系。\n\n💭 上下文关联\n\n检查思维结构是否以上统下的方式就是提炼关键词画出上下分层结构然后判断下层能否支撑上层并且做到主语一致。\n\n💭 一句话,说重点\n\n大脑理解记忆才容易。\n\n💭 信息熵\n\n串联关系。\n\n💭 串联,并联。\n\n人主要是明确关键责任人分析人的态度、性格、知识、技能等善加利用。\n\n💭 物尽其用,人尽其才。\n\n我的上司看完之后对我说“你一点都不了解你的客户人家不会为了你的辛苦付出而埋单只会为自己能收获什么而埋单。\n\n💭 没有人会为垃圾买单,切勿自我感动\n\n客户想要什么他们想要的课程要轻松、易学要有用所以我就要给他们轻松容易学的感觉以及在具体场景使用的画面感。\n\n💭 描述情况需要营造一个直观,容易相信的场景。\n\n相信大家在工作中都有过收发表格的经验。比如行政发一份表格给全员让大家填写资料发回给她。好多人打开表格填完自己的信息就直接发回给行政。\n这时候我们可以想一想行政遭遇的场景她收到了很多个表格在保存的时候计算机就会告诉她文件名重复是否覆盖原文件于是她保存每一个文件都需要更改一个文件名。\n如果我们运用客户思维就会想到当我们把表格发回给行政的时候她需要一个个更改文件名为了方便她的工作我们应该怎样做没错我们应该把文件名改成自\n\n💭 收集表就派上用场了哈哈\n\n如果我们拥有客户思维我们就会想到客户使用产品的场景怎样能更便捷、更舒适。\n如果我们拥有客户思维我们发出去的每一个文件、每一则通知就一定会让受众看得清、听得懂、轻松做。\n\n💭 从用户的立场,角度出发,看待问题。\n\n“yes,and…”提供的是双赢的解决方案我们不仅要满足对方的需求还要明确自己的目标。\n\n💭 yes and\n\n水平思维与垂直思维是一种复合性思维也就是两种思维结合使用。\n\n💭 水平散发,具有广度,需要举一反三。\n垂直深入具有深度需要系统思考。\n书评\n点评"},"Personal/Book/心理/乌合之众(果麦经典)":{"title":"乌合之众(果麦经典)","links":[],"tags":["阅读/心理-心理学研究"],"content":"简介\n\n书名《乌合之众果麦经典》\n作者 居斯塔夫·勒庞\n分类 心理-心理学研究\nISBN9787533941963\n出版社浙江文艺出版社\n\n概述\n本书细致考察群体的一般性心理特征探讨群体的道德观、情感、想象力、信念等诸多层面指出个人进入群体之后容易丧失自我意识在集体意志的压迫下成为盲目、冲动、狂热、轻信的“乌合之众”的一员。以非法私利为行为动机的群体通常是犯罪团体而“为信仰而战”的暴民团体会表现出崇高的献身精神。影响群体观念和信仰的因素有种族、传统、制度等此外极具感染性的语言、理想国的召唤、领袖人物的煽动等也对群体行为产生积极或者消极的作用。\n\n划线\n\n这本书原名《群体心理学》(Psychologie des foules),英文版改作《大众心理研究》(A Study of the Popular Mind),并加了一个主书名(The Crowd),中文版大多将其译为《乌合之众》。\n\n\n这个书名非常吸引眼球而且恰到好处地反映了该书的主题和作者的情绪。\n\n\n在他看来许多人偶然集合在一起比如说市场上买菜的、看热闹的、小贩和保安他们哪怕人数再多也不构成群体。他所说的群体是一个特殊的心理整体指的是受某一事件、演说、激情、恐惧、爱恨的刺激而聚集在一起为某个目标或某些精神需求而有所行动的人。\n\n\n人一加入群体原先的个性便会消失他不再独立思考而是随大流无意\n\n\n在群体当中任何情绪和行为都具有感染性\n\n\n受无意识的支配\n\n\n威望是成为领袖的必要条件\n\n\n《乌合之众》的意义在于勒庞首次阐明了社会心理学中的一些重要问题研究了群体特征和种族特征的不同之处指出了群众运动的性质分析领袖与群众、民主与独裁的关系\n\n\n我发现群体在精神上极为低劣甚至包括精英群体\n\n\n不管这种变革在理论上显得如何伟大。只有当它能立即改变民族的深层心理时它才是有用的。然而只有时间拥有这种力量。支配人类的是思想、感情和习俗是存在于我们自身的东西。制度和法律是人们内心精神的表现形式反映了它的需要既然是人们的内心精神诞生了制度和法律制度和法律自然就无法改变它。\n\n\n群体也许永远是无意识的但这种无意识本身可能就是它力量强大的秘密之一。在自然界绝对服从本能的生物其行为会复杂得让我们不敢相信。理智是人类新近才有的东西太不完美了不能向我们揭示无意识的规律更不能替代它。在我们的行为举止中无意识部分占的比重很大理智所占的比例却很小。无意识现在仍作为未知的力量在起作用。\n\n\n如果说大事件显得那么罕见那是因为在一个种族中没有比世代相传的思维定势更稳定的东西了。\n\n\n人们的思想正在发生变化。两个基本要素构成了这种变化的基础。一是宗教、政治和社会信仰遭到破坏那是我们这个文明的组织成分二是现代的科学和工业发明创造了新的生存和思想条件。\n\n\n它们从来没有自己的主张只接受别人强迫给它们的观点。不能跟它们在理论上空谈平等用规章制度来领导它们而是要研究什么东西能打动它们、吸引它们。\n\n\n比如说立法者想增加一个税种他会选择理论上最正确的税种吗绝对不会。对群体来说最不公正的东西在现实生活可能是最好的。如果它同时还很不显眼表面上看来很轻松那就更容易被接受。\n\n\n那是教育的结果尤其是不同遗传的结果。人在智力上相差很大却会有非常相似的本能和感情。在感情方面宗教感情、政治感情、道德感情以及爱憎方面最杰出的人物也不见得比最普通的人做得更好。就知识而言在大数学家和一个鞋匠之间可能存在着天壤之别但就性格而言他们的区别微乎其微甚至往往可以忽略不计。然而在群体中被变成共性的\n\n\n群体中的个人是沙漠中的一粒沙子风想把它吹到哪里就可以吹到哪里。\n\n\n独处的个人能控制自己的反应能力而群体却缺乏这种能力。\n\n\n人们注意到作出这类指认的往往是妇女和儿童也就是说最容易轻信的人。这事同时也告诉我们这种证明在法庭上并没什么价值。尤其是孩子他们的指认不应该被采纳。法官们不断地说在那个年龄人不会撒谎。稍微学过一点心理学的人都应该知道恰恰相反在那个年龄人往往撒谎也许那种撒谎是无辜的但仍然是撒谎。\n\n\n判决一个被告宁可掷硬币猜正反来决定也不要相信孩子的证词这是经过无数事实证明的\n\n\n群体表现出来的感情不管好坏都有极简单化和夸大化这双重特点。\n\n\n在群体中蠢人、白痴和妒忌者不会再感到自己平庸和无能而是产生了一种强烈、短暂却巨大的力量。\n\n\n群体对什么是错什么是对旗帜鲜明\n\n\n个人可以容忍矛盾和争论群体却绝不允许。\n\n\n人们经常说起那家大众剧院它只演令人压抑的戏剧散场后必须保护扮演叛徒的演员免得他遭到观众的暴打。他所犯的罪行当然是想象出来的引起了群众的巨大愤怒。我觉得这是群体精神状态最显著的表现之一这清楚地说明要给他们什么暗示是一件多么容易的事情。对他们来说假与真几乎同样奏效。他们明显地表现出真假不分的倾向。\n\n\n影响大众想象力的不是事实本身而是它所扩散和传播的方式。\n\n\n要说明传统对群体灵魂的巨大威力没有比这更好的例子了。最可怕的偶像并不在庙堂里也不是宫殿中那些最专制的暴君。这些人一下子就可以消灭但统治我们思想的那些看不见的主人任何反抗对他们来说都不起作用只能用数百年时间慢慢消磨他们。\n\n\n掌握他们命运的是民族的性格而不是政府。\n\n\n事实上起作用的并不是制度因为我们知道无论是成功还是失败制度本身都没有好坏之分。影响群体精神的是幻想和词语。\n\n\n几个小独裁者们开会议事统治着一群唯命是从的奴隶\n\n\n词语的威力太强大了只要好好选择就可以给最讨厌的东西取个好名让大家都接受。\n\n\n18世纪的哲学家无情地破坏我们的祖辈经历了几百年的宗教、政治和社会幻觉。在破坏的同时他们也让希望和屈从的源泉干涸了。在这些被牺牲的幻觉中他们找到了大自然的力量。那些力量装聋作哑对弱者冷酷无情根本不懂得怜悯。\n\n\n民族发生演化的主要原因不是真理而是谬误。社会主义今天之所以这么强大是因为这是至今仍然活跃的唯一幻想。\n\n\n群体从来不渴望真理。\n\n\n群体不会受理性的影响只明白粗粗地拼凑起来的观念。所以懂得如何影响他们的演说家从来只针对他们的感情而绝不理会他们的理性\n\n\n像荣誉、自我牺牲、宗教信仰、光荣和爱国这类感情不是因理性而产生的恰恰相反很多时候正因为没有理性这类迄今仍为各种文明强大动力的感情才成为可能。\n\n\n一定数量有生命的东西聚集在一起不管是动物还是人都会本能地处于一个首领的领导之下。\n\n\n群体是群温顺的羊决不能没有首领。\n\n\n领头人并不总是思想者而是行动者。\n\n\n创造信仰不管是宗教信仰、政治信仰、社会信仰还是对一部作品、一个人物、一种主张的信奉这是伟大领袖的主要作用也正因为如此他们的影响才如此之大。在人类拥有的所有力量当中信仰的力量永远是最强大的《圣经》里说它有排山倒海的力量这是有道理的。给人信仰就是给他增添力量。\n\n\n随着公共权力部门受到的质疑越来越多力量越来越小领袖越来越倾向于代替它们。新主子的专制让群体更温顺地服从他们远比服从任何政府温顺。\n\n\n我们经常阅读另一份意见相反或说法完全不同的报纸。断言和重复都很强大只有它们可以互相一博。\n\n\n断言重复到一定的次数就得到了大家的一致认可就像某些著名金融机构富裕得可以收购所有竞争者一样形成了所谓的倾向性意见这时强大的传染机制就开始起作用了。在人群中观念、感情、激情和信念拥有的传染力跟细菌一样厉害\n\n\n被这种思想折服的领袖占有了它对它进行歪曲创造了一个宗派这个宗派又对它进行歪曲然后在群体当中传播而群体则继续歪曲它越来越甚。成为普遍的真理之后它又以某种方式回到源头对一个民族的高层产生影响\n\n\n声望其实是一个人、一部作品或是一种思想对我们的精神统治。这种统治麻痹了我们的批评能力让我们的灵魂充满惊讶和崇敬。这种被激发出来的情绪像所有的感情一样是难以解释的但应该与迷恋某种神奇的东西属于同样性质。声望是获得权威的最有效手段没有它神灵、国王和女性都无法进行统治。\n\n\n把各种声望归纳成两类获得的声望和个人本身的声望。\n\n\n要得到群众的敬仰就要永远与他们保持距离。\n\n\n它会改变这种文明直到找到可以接受的新的普遍信念。在这之前它当然会处于无政府状态。\n\n\n1 异质性群体我们在本书中研究过这些集体的特点。它们可以由任何人组成不管其职业或文化程度如何。我们现在知道有行动的群体中的成员他们的集体心理与\n\n\n种族的精神越是强大群体的次要特征越不明显\n\n\n我在别的地方指出过这种本能是如何产生的群体总是能够把它发挥到极致。不过他们同时也会表现出相反的情绪比如说同情这种同情往往非常极端他们有多残酷他们的同情心就会有多泛滥。\n\n\n我们害怕群体的力量但某些身份团体的权力更可怕。前者可以被说服后者绝对不会让步。\n\n\n群体时时处处都表现出来的特征是推理能力差缺乏批评精神易怒轻信头脑简单。我们也发现他们作决定时受领袖人物的影响前面列举过的种种因素如断言、重复、声望和传染在起作用。\n\n\n也许普选的缺点太明显了人们不可能看不到。谁也不能否认文明是少数精英的作品他们组成了金字塔的顶部下面的几层思想价值越低便越宽组成了一个民族的深厚底层。\n\n\n议会制是现在所有文明民族的理想。它反映了一种心理上错误但被普遍认同的观点即对某个问题许多人聚在一起比一小部分人更能做出明智而独立的决定。\n\n\n人如果自身缺乏活力他必然会到别人身上去找。随着公民越来越麻木越来越无能政府的作用将被迫继续强化它必须拥有个人已经失去的主动性、积极性和行动意识。它什么都得做要领导一切保护一切。国家成了一个无所不能的神。经验告诉我们这样的神他们的权力从来不能持久也不会强大。\n\n\n从野蛮到文明一路追逐着梦想而当这种梦想失去了力量便开始衰落走向死亡。这就是一个民族的生命周期。\n\n笔记\n\n同样群体和民主也没有必然的关系恰恰相反。他们缺乏主见所以需要领袖需要被管理、被领导。\n\n💭 群体是需要被管理的\n\n群体只有破坏的能力它们就像细菌加速病体或尸体的解体。当文明的大厦被虫蛀时让它轰然倒塌的永远是群众。只有在那个时候群体的真正作用才显现出来人数的多少似乎成了唯一的历史法则。\n\n💭 谁赢帮谁\n\n大家将看到声望是说服他人的最基本要素。不管有意无意拥有声望的人、主张或物品会通过传染的方式被人迅速模仿把某种感觉和表达思想的方式强加给一代人。这种模仿往往是无意识的正因为如此它才是完美的。\n\n💭 我们更愿意相信权威,而不是真理。\n\n大家可以清楚地看到有些因素会成为获得声望的根源其中最重要的永远是成功。所有的成功人士所有被人接受的主张都不会再受到质疑。成功是声望的基础之一因为成功一旦消失声望几乎也会同时消失。人们前一天还欢呼的英雄如果遭到了失败第二天就会被群众喝倒彩。声望越大反弹便越强烈。那时群众会把跌下来的英雄当作是自己的同类为之前对他的卑躬屈膝进行报复因为他现在已不再高人一等。\n\n💭 对,它们还是谁赢帮谁 (✌️≖‿≖)\n书评\n点评"},"Personal/Book/心理/十分钟冥想":{"title":"十分钟冥想","links":[],"tags":["阅读/心理","阅读/笔记"],"content":"简介\n\n书名《十分钟冥想》\n作者 安迪·普迪科姆\n分类 心理-心理学应用\nISBN9787111639824\n出版社机械工业出版社\n\n概述\n冥想是一种奇妙的技能它有改变我们人生的潜力但是怎样运用这种技能则取决于你自己。随着媒体对冥想和正念的报道越来越多许多人似乎急于确定冥想的用途。事实上你只有确定了如何用它你才能确定它的用途。在学骑自行车的时候你所了解的是如何骑车而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具有些人用它跟朋友闲逛还有极少数人可能以它为终身事业。对所有人来说技能是一样的安稳地坐在车座上别掉下来。所以虽然别人可以教你如何骑车但骑车对你而言到底意味着什么你要拿它做什么以及它怎样才能最符合你的生活方式这完全取决于你自己。冥想技能也是如此你可以将它应用到生活中的任何方面它的价值取决于你赋予它的价值。\n划线\n\n你上一次坐下来安静不动不分心不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰没有任何你需要思考和解决的事情是什么时候\n\n\n在正念环境中冥想不是要去阻止想法、控制心灵。它是一个过程在这个过程中我们放弃控制不插手不介入学会以被动的方式集中注意力同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手容许心灵以自己的节奏、自己的方式展开你才能找到真正的头脑空间。\n\n\n你知道如果你坐上飞机从那些云的一端穿过另一端就没有阴云而只有蓝色的天空了。就算有大片阴沉沉的乌云蓝色的天空也始终存在。\n\n\n我得到了这样一种理念天空总是蓝的。云相当于我们的思想当心灵忙于这些想法的时候蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何心灵的深层本质就像蓝色的天空一样并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候云会变得更加阴沉更令人烦扰。也许整个天空中只有那么一个想法然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走而是搬把椅子到花园里坐看云卷云舒。有时候蓝色的天空会穿过阴云展露出来令人备感美好。如果我能耐心地坐在那里不过分执着于那些阴云那么蓝色的天空会显露得更多。\n\n\n。最重要的是你可以想象心中有一片始终宁静、始终澄澈的区域想象心中有一片你随时都可以依归的地方想象无论生活中发生什么事心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事就指望它突然静静地在某个地方站定因此当你跟这匹野马也就是你的心灵一起坐下来的时候你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上相反要给你的心灵一点时间让它安定下来放松一点。你急什么呢”\n\n\n关注它的同时试着温和地将它分享给他人。同样如果你的注意力集中在令人不快的感受上那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的必将浮上来\n\n\n就情感而言凡是被压制的必会再浮上来。也许它会突出到表面来就像情感本身一样也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央即一块开放田野的中央。现在缰绳的一端系着这匹马另一端在你手里。不过缰绳是松弛的这匹马有它所需要的一切空间它并没有觉得被困住或者受到约束\n\n\n你有没有注意过当你真正专注于某个事物的时候你的心灵会变得多么平静你有没有注意过即便你的心灵之前还凌乱如麻但是一旦专注于自己喜欢做的事情并且全身心地沉浸在那项活动中时心灵会开始安定下来会感到非常宁静\n\n\n所以对任何可能会令人分心的事物进行限制正是修习开始的第一步。\n\n\n当心灵像这样被完全扰乱时我们就几乎不可能看清正在发生的事也不可能看到表面之下隐藏着什么。\n\n\n如果要对这些让我们的生活变得既复杂又丰富的感受和情绪进行研究那么我们需要使水面足够平静因为只有这样我们才能看到它们。\n\n\n在那个时候似乎一切都被愤怒染上了色彩。我不知道你有没有过这种体验感觉就像是所有从脑海中闪过的想法都带上了这种愤怒底色这种底色改变了你看待周围世界的视角。\n\n\n奇怪的是与此同时我好像开始不那么专注于自己的那些想法而更多地开始专注于自己手头的活。虽然我同意用剪刀来剪草不见得每个人都喜欢然而剪了一会儿之后我发现这个过程其实可以使人平静。事实上这个过程本身就成了一种冥想过程。\n\n\n“你的心灵就是这个样子。你看到了这些陷阱但是惯性太强大了你没法阻止自己掉进去。但是\n\n\n“如果你分心走神了那就不是冥想了。只有在你不分心不走神的时候才是冥想。没有好的冥想或者坏的冥想之说只有分心和不分心之说以及觉醒和不觉醒之说。”事实上他常常把冥想比作去剧院\n\n\n你甚至会被台上的故事所激发坐在那里计划着如何向你5年来一直想告白的人告白。\n\n\n冥想根本不起作用。我感觉糟透了。进来的时候我心情还好而现在我感觉心情很差那么冥想的意义何在呢\n\n\n我们其实很少能做到身心的时空合一。\n\n\n理念是不要试图去阻止想法而要顺其自然任由想法在你完全觉醒的状态下来来去去。\n\n\n跟非冥想者相比冥想者的大脑中管理痛苦和情感的区域要更厚实\n\n\n我们中有多少人一直都是这样生活的沉浸在对过去的回忆和对未来的规划中如此全身沉浸在思考中而完全没有意识到当\n\n\n无论你在做什么它就在这里它就在普通平常的日常活动中如就在你吃三明治的动作中就在你喝水的动作中就在你洗碗的动作中……这就是正念、心在、觉醒的要义所在。\n\n\n我们对身体的运动如此熟悉以至于在跑的时候根本不需要太专注。正因为这一点心灵往往很容易游离。\n\n\n研究正念有效性的研究者发现哪怕参与者每天只冥想很短的时间只做了5天就有更多血液流向他们大脑中帮助控制情感和行为\n\n\n冥想的最佳时间是早上醒来的第一时间\n\n\n他们不断地把冥想加入下一个“待办事项清单”中结果却是“未完成”状态。他们用来减轻自己压力的事情反倒不知怎么成了他们的另一个压力来源。这可不是冥想的目的\n\n\n研究冥想和正念的好处的神经科学家发现了重复的重要性。他们说日复一日地做冥想练习这个简单的举动就足以促使大脑做出积极的改变。事实上他们认为这对于建立新的突触关系和神经路线来说极其重要。\n\n\n某一天你登上一列拥挤的火车却没有为之感到过于困扰而另一天同样拥挤的列车却好像触发了你的各种情绪。你会很清楚地意识到并不是外在的事物给我们带来了最大的麻烦而是我们心灵里面的事物给我们带来了困扰——幸好心灵里的这些东西是可以改变的。留意视角在每时每刻的转变这会为你的日常冥想提供强有力的支持。\n\n笔记\n\n“天空总是蓝的。”\n\n💭 生活总是美好的\n\n现在想象一下你将石头一块接一块地扔进水中看看整个水面同时被搅动起来的情景。当水面变成这个样子的时候你几乎就不可能看到水里的任何东西更不用说看见水底的东西\n\n💭 静心\n\n如果我一门心思专注在一件事上那么我不可能同时分心到另一件事上。因此在没有刻意忽略或抗拒内心想法的情况下当我的心思专注在别处的时候这些想法自然地自行消失了。\n\n💭 活在当下,体验内心的宁静和愉悦\n💭打水即是打水劈柴即是劈柴烧饭即是烧饭\n\n以正念的形式将觉醒应用到日常生活的杂务中。\n\n💭 正念即是专注力\n\n行走是一种确定的、受习惯驱使的行为它几乎不需要专注力。\n\n💭 潜意识\n\n冥想只有在你去做的时候才会起作用只有当你坐下来冥想的时候你才会看到它的好处\n\n💭 实践是检验真理的唯一标准\n书评\n点评"},"Personal/Book/心理/认知觉醒:开启自我改变的原动力":{"title":"认知觉醒:开启自我改变的原动力","links":[],"tags":["阅读/心理-认知与行为","阅读/笔记"],"content":"简介\n\n书名《认知觉醒开启自我改变的原动力》\n作者 周岭\n分类 心理-认知与行为\nISBN9787115543424\n出版社人民邮电出版社\n\n概述\n为什么我们做事总是急于求成、避难趋易所谓有耐心就是要“咬牙坚持、死磕到底”如何不再用“三分钟热情”和“打鸡血”的方式做事如何保持极度专注如何消除焦虑如何提高学习能力这是一部可以穿透时间的个人成长方法论。7大底层概念20个成长关键词助你彻底走出焦虑与迷茫拥有清醒的认知、清楚的目标、清晰的路径、清爽的情绪。通过“大脑构造、潜意识、元认知”等思维规律你将真正看清自己通过“深度学习、关联、反馈”等事物规律你将真正看清世界提升自控力、专注力、学习力……只有洞悉底层的内在规律我们才能真正开启自我改变的原动力。\n划线\n\n有一样东西却始终无法直接传递那就是心智\n\n\n所谓心智通俗地说就是我们看待人和事的态度以及由此做出的判断与选择。每一个人来到这个世界时其人生观、世界观、价值观全部都是从零开始的所有习性、习惯、模式也要从人性的初始状态开始发展你、我、我们的父辈和孩子都是如此没有人能够直接跨越这一阶段。而不少人的初始状态是混沌的他们天然追求简单、轻松、舒适、确定这种天性支配着他们成为他们喜怒哀乐的生理起点然而身陷其中的大多数人对此知之甚少。\n\n\n大多数人发现自己并没有变得特别而是在不断地服从社会规则和应对生活烦恼开始随波逐流该玩手机玩手机、该打游戏打游戏没有多少压力也没有多少动力觉得反正日子还过得去希望也还在心里偶尔挣扎呐喊一声而后继续做着短视的选择沉溺于眼前的安逸。\n\n\n不知道事物的构成、框架不知道努力的路径、方法也不知道自己真正想要什么、能做什么、最后会成为什么样的人……\n\n\n一时间他们焦虑急躁又如梦初醒“为什么没有早点知道这个世界的真相为什么没有在最好的年纪及时觉醒”但即使含泪拷问也似乎错过了最佳时机毕竟人生是个单行道无法从头再来。最后他们不得不敲碎那颗高傲的心在无奈和叹息中默默接受平庸的人生。\n\n\n直到有一天因为意外身边两位与我关系极好的朋友的命运轨迹发生了巨变。我忍不住问自己如果这些意外发生在自己身上如果现有的一切被“剥夺”我还有什么、会什么又曾在这个世界上留下了什么\n\n\n我发现每天有事情做不代表觉醒每天都努力也不代表觉醒真正的觉醒是一种发自内心的渴望立足长远保持耐心运用认知的力量与时间做朋友我发现人与人之间的根本差异是认知能力上的差异因为认知影响选择而选择改变命运所以成长的本质就是让大脑的认知变得更加清晰\n\n\n从混沌到警醒从迷茫到清晰我慢慢解开了“愿望觉醒”和“方法觉醒”的秘密知道了如何激发和保持自我提升的内在动力如何变苦涩的毅力支撑为科学的认知驱动。当我\n\n\n我看到无数渴望成长的人于是决定在自我成长的同时帮助他人。\n\n\n2018年5月的最后一天我在个人公众号“清脑”上开通了问答专栏从此多了一个成长咨询师的身份。虽然是业余的但我也因此有了大量接触“困惑样本”的机会\n\n\n如果你觉得自己已经错过所谓的最好年纪其实也没有关系因为“现在”永远都是开始的最好时机——这不是什么安慰人的话这是事实。\n\n\n从大脑开始重新认识自己我们会再“进化”一次。\n\n\n起初地球上并没有生命。但在数十亿年前远古的海洋中出现了一些“复制子”在进化的力量下它们逐渐成为单细胞生物接着又演化为动物、植物和微生物等之后动物这条分支进化成各种原始鱼类遍布大海。\n\n\n爬行动物演化出了最初的“本能脑”。本能脑的结构很简单只有一个原始的反射模块可以让爬行动物对环境快速做出本能反应比如遇到危险就战斗或逃跑遇到猎物就捕食遇到心仪的异性就追求等。爬行动物既没有情感也没有理智\n\n\n有了情绪的加持哺乳动物就能在恶劣的环境中趋利避害大大提升了其生存优势比如恐惧情绪可以让自己远离危险兴奋情绪可以让自己专注捕猎愉悦情绪可以增强同伴间的亲密度伤心情绪能引来同情者的关爱等。\n\n\n在我们的大脑里由内到外至少有三重大脑年代久远的本能脑、相对古老的情绪脑和非常年轻的理智脑。\n\n\n理智脑虽然高级但比起本能脑和情绪脑它的力量实在是太弱小了。\n\n\n。同时它们距离心脏更近一旦出现紧急情况可以优先得到供血这也是为什么当我们极度紧张时往往会感觉大脑一片空白这是因为处于最外层的理智脑缺血了。\n\n\n种种迹象表明理智脑对大脑的控制能力很弱所以我们在生活中做的大部分决策往往源于本能和情绪而非理智。\n\n\n为了生存他们必须借助本能和情绪的力量对危险做出快速反应对食物进行即时享受对舒适产生强烈欲望才不至于被吃掉、被饿死。\n\n\n自然成了目光短浅、即时满足。又因它们主导着大脑的决策所以这些天性也就成了人类的默认天性。\n\n\n不过在现代社会用避难趋易和急于求成来代指它们显然更加贴切。\n\n\n这样的大脑构造导致我们总是陷入“明明知道但就是做不到特别想要但就是得不到”的怪圈比如\n\n\n迫使经理为他们糟糕的选择做出合理的解释\n\n\n大多数时候我们以为自己在思考其实都是在对自身的行为和欲望进行合理化这正是人类被称作“自我解释的动物”的原因。\n\n\n习惯之所以难以改变就是因为它是自我巩固的——越用越强越强越用。要想从既有的习惯中跳出来最好的方法不是依靠自制力而是依靠知识\n\n\n换一个角度看也没有必要抹杀因为本能脑强大的运算能力和情绪脑强大的行动能力都是不可多得的宝贵资源只要去深入了解、循循善诱就能为己所用甚至这些力量还是成就我们的关键。\n\n\n无论个体还是群体人类的安全感都源于自己在某一方面拥有的独特优势或能力或财富或权力或影响力。\n\n\n那段时间我心里总是回响着一句话来不及了太晚了一切都太晚了……直面焦虑\n\n\n归结起来焦虑的原因就两条想同时做很多事又想立即看到效果。王小波说人的一切痛苦本质上都是对自己无能的愤怒。焦虑的本质也契合这一观点自己的欲望大于能力又极度缺乏耐心。焦虑就是因为欲望与能力之间差距过大。\n\n\n·克制欲望不要让自己同时做很多事\n\n\n·面对现实看清自己真实的能力水平\n\n\n·要事优先想办法只做最重要的事情\n\n\n·接受环境在局限中做力所能及的事\n\n\n·直面核心狠狠逼自己一把去突破它。\n\n\n避难趋易的天性\n\n\n那就是他的故事击中了人类天性中最原始、最本能的部分——即时满足。\n\n\n正是这种不用付出巨大努力就能获得超强能力的快感让人心驰神往因为现实生活中无论读书、考试还是工作、赚钱要想表现出色都必须经受长时间的磨炼。\n\n\n复利效应显示了价值积累的普遍规律前期增长非常缓慢但到达一个拐点后会飞速增长。\n\n\n耐心不是毅力带来的结果而是具有长远目光的结果。\n\n\n学习知识的目的是“消除模糊”而获取知识的方法也是“消除模糊”目的和方法相统一这几乎成了这个世界上所有能人共同遵守的学习法则这类例子能举出很多比如\n\n\n提升思考能力的方法正是不断明确核心困难和心得感悟并专注于此。\n\n\n但有些事一旦进入潜意识可能很难消除比如童年的不幸经历虽然意识早已将其淡忘但潜意识却始终保留着这些印记并隐蔽地影响着我们的性格和行为。\n\n\n要想不受其困扰唯一的办法就是正视它、看清它、拆解它、化解它不给它进入潜意识的机会不给它变模糊的机会即使已经进入潜意识也要想办法将它挖出来。所以当你感到心里有说不清、道不明的难受的感觉时赶紧坐下来向自己提问。\n\n\n在诸多可能性中建立一条单行通道让自己始终处于“没得选”的状态。\n\n\n熔断不读书法”。所谓“熔断不读书法”意思就是在读书时一旦看到有启发的内容就触发熔断点立刻停止读书。停止读书之后做什么呢围绕这个触发点对自己提问。\n\n\n在另一篇文章中他又提出无论在生活中还是在学习上凡是被某件事击中“动了感情”就要有意识地提醒自己追问原因。\n\n\n先用感性能力帮助自己选择再用理性能力帮助自己思考。\n\n\n小事听从你的脑大事听从你的心。\n\n\n它能对自身的“思考过程”进行认知和理解见图3-1。\n\n\n它们依旧无法从自我和当前的情境中脱离假想出“另一个自己”—\n\n\n被动元认知和主动元认知。\n\n\n遭遇指责、批评时才不得已去反思纠正\n\n\n而有些人即使在没有威胁的情况下也会尝试练习扇动翅膀让自己不断进化彻底远离危险。\n\n\n从被动到主动这是一个转折点。当一个人能主动开启第三视角、开始持续反观自己的思维和行为时就意味着他真正开始觉醒了他有了快速成长的可能。\n\n\n你能意识到自己在想什么进而意识到这些想法是否明智再进一步纠正那些不明智的想法最终做出更好的选择。\n\n\n第三如果说学习和反思是静态的那处于当下的、动态的自已又该如何主动运用元认知呢很简单启用你的“灵魂伴侣”啊\n\n\n元认知能力总能让你站在高处俯瞰全局不会让你一头扎进生活的细节迷失其中。如果你足够细心还会发现未来视角总是当前行动的指南针它可以在茫茫的生命中为你导航让你主动选择去做那些更重要而不是更有趣的事情。\n\n\n第四提高元认知能力的方法有很多但最让人意想不到是下面这条——冥想。是的冥想就是那种只要静坐在某处然后放松身体把注意力完全集中到呼吸和感受上的活动。\n\n\n不难发现这些活动本质上都在做同一件事监控自己的注意力然后将其集中到自己需要关注的地方。\n\n\n反馈是这个世界的进化机制。\n\n\n可以说元认知能力就是觉察力和自控力的组合。所以从实用角度讲元认知能力可以被重新定义为自我审视、主动控制防止被潜意识左右的能力。\n\n\n每当遇到需要选择的情况时我们要是能先停留几秒思考一下就有可能激活自己的理智脑启用元认知来审视当前的思维然后做出不一样的选择。\n\n\n一定要在选择节点上多花“元时间”。\n\n\n因为一天24小时看起来每分每秒都一样但实际上并不相同有些时间的权重要远远大于其他时间我把这些权重大的时间叫作“元时间”。元时间通常分布在“选择的节点”上比如一件事情、一个阶段或一天开始或结束时。善用这些时间会极大程度地优化后续时间的质量。\n\n\n在选择的节点审视自己的第一反应并产生清晰明确的主张。\n\n\n要想清楚不仅要审视第一反应同时还要有清晰明确的主张。\n\n\n·针对当下的时间保持觉知审视第一反应产生明确的主张·针对全天的日程保持清醒时刻明确下一步要做的事情·针对长远的目标保持思考想清楚长远意义和内在动机。\n\n\n走神时我们要么沉浸过去要么担忧将来要么幻想不可能实现的情况走神可以让我们活在任何时候唯独不能让我们活在当下。\n\n\n可见分心走神的本质是逃避所以面对困难时身心分离的人总会不自觉地退回舒适区而身心合一的人则更容易跳出舒适区直面困难。\n\n\n身体感受永远是进入当下状态的最好媒介而感受事物消失的过程更是一种很好的专注力训练。它提示我们身心合一的要领不仅是专注于当下更是享受当下而这种享受必将使我们更从容不慌张。\n\n\n老和尚说“得道前砍柴时惦记着挑水挑水时惦记着做饭得道后砍柴即砍柴担水即担水做饭即做饭。”\n\n\n注意力的感知精度就会越高精力越集中技能越精进。如果目标太大那就将它分解成小目标这样做也是为了使目标更具体、精细。\n\n\n所以变聪明的秘诀就是先保持极度专注想不出答案时再将注意力转换到另一件与此毫不相干的事情上。即事前聚精会神让意识极度投入事后完全忘记让意识彻底撒手。这样灵感和答案就会大概率地出现。\n\n\n清的习惯对能力提升伤害很大。李大钊也说过“要学就学个踏实要玩就玩个痛快”说明界线分明的习惯对人性情和能力的培养都很有好处。\n\n\n跳出舒适区避开困难区处在拉伸区。\n\n\n“你在孩子的学习上有没有采取什么特别的方法”没想到他干脆地说“有的”我竖起耳朵继续听他说“就两条一是像对待考试一样对待家庭作业二是有问题只找主观原因。”\n\n\n距离我们太远的事物我们通常无法把握无论它们是令人痛苦的还是令人享受的。\n\n\n做选择是一件极为耗能的事情如果没有与之匹配的清醒和定力绝大多数人最终都会被强大的天性支配去选择娱乐消遣。在有约束的环境下我们反而效率更高生活更充实。\n\n\n因此跳出舒适区的最好办法就是去发现和收集那些要点也就是每次行动的小目标。比如练习弹钢琴的时候不是一遍一遍地重复而是只练出错最多的地方\n\n\n我隐约看到一小部分知识精英依旧直面核心困难努力地进行深度钻研生产内容而大多数信息受众始终在享受轻度学习消费内容。如果我们真的希望在时代潮流中占据一席之地那就应该尽早抛弃轻松学习的幻想锤炼深度学习能力逆流而上成为稀缺人才否则人生之路势必会越走越窄。\n\n\n人的学习分为被动学习和主动学习两个层次\n\n\n。更糟的是这种努力会让人盲目追求阅读的速度和数量让人产生勤奋的感觉实际上这是低水平的勤奋投入越多损失越大。\n\n\n从知道到做到是一种巨大的进步然而自己知道或做到是一回事\n\n\n请注意遇到这种困难才是深度学习真正的开始因为你必须动用已有的知识去解释新知识当你能够把新学的知识解释清楚时就意味着把它纳入了自己的知识体系同时达到了可以教授他人的水平并可能创造新的知识。\n\n\n可见“缝接”是深度学习的关键而大多数人只完成了“获取知识”却忽略了“缝接知识”这一步因此他们的学习过程是不完整的。\n\n\n所以逼迫自己获取高质量的知识以及深度缝接新知识再用自己的语言或文字教授他人是为深度学习之道。\n\n\n每日反思。\n\n\n深度学习除了能让我们不再浮躁能磨炼理智还能带来诸多好处比如跨界能力的提升。\n\n\n娱乐热点并非没有价值浅层知识也同样具有意义但前提是你需要具备一定的认知深度——深度之下的广度才是有效的。\n\n\n我们可以把浅学习作为了解新信息的入口但不能把成长的需求全部寄托于此更合理的态度是专注于深度学习同时对浅学习保持开放。\n\n\n这正是大师创作的普遍手法——把远处不起眼的A关联到近处需解决的B然后爆发出惊人的力量。\n\n\n无关联不学习\n\n\n·用自己的语言重述信息即找到触动自己的信息点·描述自己的相关经验即关联生活中的其他知识·我的应用即转化为行动让自己切实改变。\n\n\n所以写作就是一条深度学习的自然路径。\n\n\n绝大多数人习惯以孤立的思维看待事物喜欢花大量时间收集和占有信息而另一批先行者则更喜欢拨弄信息之间的关联从而在不知不觉间变得聪明了起来。\n\n\n知识的获取不在于多少而在于是否与自己有关联以及这种关联有多充分。\n\n\n当然还有一个更重要的隐蔽条件不能忽视你需要明确的目标或强烈的需求。张\n\n\n人生没有白走的路每一步都算数。\n\n\n但凡收获一个感悟、了解一个观点或是学到一个知识只要触动了自己就要想办法让它效率最大化而效率最大化的办法就是主动关联到别处并让自己的行动发生改变。所以你不妨也把这句话当作口头禅时常问自己这个道理还能用在什么地方\n\n\n根据能力圈法则可知人的能力是无法跳跃发展的只能在现有基础上一点一点向外扩展而扩展的最佳区域就在舒适区边缘。\n\n\n体系的本质就是用独特的视角将一些零散的、独立的知识、概念或观点整合为应对这个世界的方法和技巧。\n\n\n打碎各家的认知体系只取其中最触动自己的点或块然后将其拼接成自己的认知网络。\n\n\n触动是最好的筛选器\n\n\n每日反思不是记流水账而是留意每天最触动自己的那件事不管是好的启发还是坏的体验都写下来复盘写得越细越好。一个触动点若是能转化成一个认知晶体我们的生命质量和密度将远远超过那些不反思的人。\n\n\n产生“触动”不意味着“连接”紧密\n\n\n一是用自己的语言重新解释新知识这会促使自己原有的知识体系对新知识做出反应。\n\n\n三是在生活中能够经常练习或使用这些知识因为实践是产生强关联的终极方法。学习不是为了知道而是为了发生真实的改变。当你运用那些知识践行那些道理\n\n\n第五节 打卡莫迷恋打卡打卡打不出未来\n\n\n大脑“解释系统”的逻辑虽然很荒谬但强大的天性会迫使理性这样解释而有的人还真接受了于是有人去网上购买刷步神器坐在家中就可以让自己运动步数名列前茅有人早上5点闹钟一响就在早起群里打个卡然后倒头继续睡有人翻开书拍张照然后将照片发到朋友圈以示自己今天读过书了……\n\n\n动机已经转移\n\n\n其实对于学习来说偶尔中断又有什么关系呢\n\n\n所谓认知闭合需求就是指当人们面对一个模糊的问题时就有给问题找出一个明确的答案的欲望。比如古时候人们不知道为什么会下雨于是下雨这个问题就没有闭合会让人很难受所以古人就用雷公、电母、龙王解释下雨的成因这些说法虽然没什么根据但满足了认知闭合需求。将这一概念扩展到行为上也是一样的一件事若迟迟没有完成心里就总是记挂期盼着早点结束此事一旦完成做这件事的动机就会立即趋向于零。\n\n\n因为人类的大脑喜欢确定性不喜欢未知或不确定性。\n\n\n这就是打卡心态的特性学不到假装一下学到了立即停止。\n\n\n任务心态身心分裂\n\n\n世界上有些事情很奇怪你直接去追求反而得不到。\n\n\n但你若是安静地专注于一件事情真正的美就出现了。所谓“大美不自知”我想破除任务心态的方法正是如此——集中心力做眼前的事就好。\n\n\n用记录代替打卡\n\n\n图5-9 用记录代替打卡\n\n\n同时我们在任务设置时要使用新策略设下限不设上限。\n\n\n作者斯蒂芬·盖斯为了养成好习惯要求自己每天只做一个俯卧撑、每天只读一页书、每天只写50个字这种无负担的习惯养成法最终促使他拥有了良好的身材养成了阅读习惯还写出了自己的书。他称这种方法简单到不可能失败。\n\n\n是否有及时、持续的正向反馈正是产生学习效果差异的关键。\n\n\n他们似乎从来没有考虑过要尽快产出点什么以换取反馈通过另一种方式来激励自己。也许是因为在人造的学习体制内待久了有些人很难相信“跳过原理直接实操”的方式是有效的\n\n\n但它们超强的欲望和情绪力量却是非常宝贵的行动力资源如果能让它们感受到学习的乐趣它们同样会展现强大的行动力让自己像沉迷娱乐一样沉迷于学习。\n\n\n所以科学的学习策略是产出作品、获取反馈驱动本能脑和情绪脑去“玩玩玩”而不是一味地努力坚持让理智脑苦苦地去“学学学”。\n\n\n真正比你强的人往往没空打击你\n\n\n所有痛苦都是上天给我们的成长提示。无论是身体不适、情绪低落还是学业落后、事业受挫有痛苦出现说明哪里出了问题这不就是在告诉我们应该努力的方向吗\n\n\n这印证了古典的跃迁理论打磨作品—到达一个小山的头部—受到更多关注—移动到一个更大山头的头部—借助系统推力实现人生跃迁。\n\n\n真正的学习成长不是“努力努力再努力”而是“反馈反馈再反馈”只有不断产出获得反馈我们的人生才会发生真正的变化。\n\n\n刘传的学琴理念即跳过原理直接实操的方式仅适用于学习的初级阶段。也就是说采用这一方式你快速达到60分的水平是可以的但到了中级或高级阶段仍然需要系统学习原理否则走不远。\n\n\n问题就出在这里那些持续刻苦、争分夺秒、舍不得休息一下的人他们的精力总量势必呈一条持续下降的曲线见图5-11。\n\n\n于是他们舍不得浪费一点时间认为在痛苦中前行才是努力的表现越痛苦、越坚持越刻苦、越感动\n\n\n高效学习的关键在于保持极度专注而不是靠意志力苦苦支撑谁能保持长时间的专注谁就能够在竞争中胜出。\n\n\n极度专注+主动休息,如此反复。\n\n\n因为太容易的内容会让人因无聊而走神太困难的内容会让人因畏惧而逃避\n\n\n毕竟克服困难和抵制诱惑都需要消耗意志力。\n\n\n所以一个真正的自控高手不是一个只知道冲刺的人而是一个善于主动休息、保持平衡的人。\n\n\n刻苦是一种宏观态度轻松是一种微观智慧。\n\n\n人的惰性实在是太强大了\n\n\n与天性对抗是没有出路的也隐约感觉到自制力强并不代表行动力强。\n\n\n珍惜每天的礼物\n\n\n注意力的使用同样遵循这个规律最初的选择会影响行为自动增强的方向。\n\n\n注意力的增强回路是正向的还是负向的很大程度上取决于你最初的选择这也是老生常谈的道理要事第一\n\n\n在初始阶段强迫自己先做重要的事情一旦进入正向的增强回路你便能拥有强大的行动力——这正是增强自制力、提升行动力的秘密。\n\n\n清晰力也就是把目标细化、具体化的能力——行动力只有在清晰力的支撑下才能得到重构。\n\n\n只有真正做过的人才能体会到写与不写完全不同。很多时候人与人之间真正的差距可能就体现在最后那一点点行动上。\n\n\n因为做规划的目的并不是让自己严格地按计划执行而只是为了让自己心中有数。如果当天计划有变也没关系有了这份预案你能够在处理完临时任务后把自己迅速拉回正轨但如果没有这份预案\n\n\n因为成长是一个系统工程必然是多要素共同作用的结果。\n\n\n你陷入怠惰、懒散、空虚的情绪中动弹不得时往往是因为你的大脑处于模糊状态。\n\n\n认知越清晰行动越坚定。\n\n\n一是凡事必须在看到明确的结果后才行动如果前景不确定、不明朗即使别人说得再有道理我也不愿意投入二是如果一个道理或方法不能让自己快速发生变化就不是最优的所以要不断寻找这样才有希望找到最好的方法。\n\n\n想先看到结果再行动的人往往无法看到结果。耍小聪明的人会因为结果不明朗担心付出没有回报所以不愿行动以致永远停留在原地\n\n\n这个世界是有认知层次的。处在下一个认知层次的人往往看不到上一个认知层次的风景因而只能用狭隘的视角来判断\n\n\n很多人总是希望先找到自己的人生目标再行动事实上如果不行动我们可能永远也找不到自己的人生目标毕竟依靠低维度的认知和经历我们很难看清自己真正想要什么。只有先依据前人的假设走到更高的层次人生目标才可能慢慢浮现。\n\n\n现实结果才是最好的“评判师”\n\n\n如果你觉得别人讲的道理有理有据而自己暂时无法反驳碰巧自己又非常想做这件事那就相信他们说的是对的然后笃定地行动\n\n\n同样的道理摆在面前有的人觉得那是鸡汤没什么用而有的人却觉得那是干货好用得不得了。如果你能够持续行动我相信这个世界一定会特别偏爱你。\n\n\n认知其实是一种技能\n\n\n学习任何一门技能本质上都是大脑中的神经细胞在建立连接。\n\n\n不发生真正改变的学习都是无效的学习。\n\n\n对成长来讲道理都是“空头支票”改变才是“真金白银”。\n\n\n我们经历的一切都是这个星球上前所未有的。\n\n\n稀缺心态让人变笨\n\n\n在一定的前提下贫穷确实会使人变笨这不是因为贫穷让人能力不足而是因为贫穷造成的稀缺俘获了人的注意力进而降低了人的心智带宽。\n\n\n任何能制造压力的事件都会挤占我们的心智带宽\n\n\n只要我们的注意力被某一个巨大的事物吸引我们就有可能进入稀缺状态进而降低心智带宽做出不明智的行为。\n\n\n当一个人同时面临很多任务的时候他的心智带宽就会降低反而没有了行动力和自控力。\n\n\n脑子里存在大量任务和念头的时候往往是我们行动力最弱的时候。\n\n\n我脑袋里一团乱麻的时候就会坐下来拿出笔和纸把心中的念头全部列出来。无论是后台隐藏的还是前台运行的只要把它们清晰地列出来并逐一审视自己立马就会神清气爽行动力十足。\n\n\n真正的行动力高手不是有能耐在同一时间做很多事的人而是会想办法避免同时做很多事的人。\n\n\n第四帖保持情绪觉知谨慎决定。\n\n\n不要在最兴奋的时候做决定也不要在最愤怒的时候做决定尤其是重大决定。大喜大悲的时候我们的心智带宽往往很窄判断力也很弱。\n\n\n一个心智带宽富足的人也会是一个心平气和的人。\n\n\n如果你的人生有如此好运一切都很富足不妨想办法给自己设限适当制造稀缺以成就自己。\n\n\n事实上在面对各种困境的时候多角度看问题的能力往往是考验解决问题能力的关键它不仅能帮助人们获取智慧、成就事业还能帮助人们在生活中拓展格局、化解烦恼。只是很多人意识不到这一点习惯用原始的单一视角对待所有问题。\n\n\n世界是多维的而我们只有一双眼睛\n\n\n不难推断像这辆摩托车一样世界上任何一个人、任何一件物、任何一件事都是多维立体的。\n\n\n如果不能强烈地意识到这一点我们就很容易以偏概全地对待这个世界然后产生各种偏误。\n\n\n本书和其他所有书籍一样也存在偏见和不完整性。我在本书中阐述的内容可能只是系统思考领域的九牛一毛如果你有兴趣去探索你会发现一个更加广阔的世界而远不止本书所展现的这个小世界。”\n\n\n向下兼容\n\n\n在“相机”这件事情上我们一定要保持觉知要清醒地意识到自己的视角偏误时刻做好向上升级、向下兼容的准备。拥有这种心态不仅我们自己能越来越完善还能与其他人都合得来。\n\n\n只是有的人面对再好的事情时都盯着一点瑕疵不放而有的人却能从任何一件糟糕的事情中找到闪光点并放大忽视其他不足之处。\n\n\n大师修炼之路\n\n\n三是要开放。更准确地说是保持客观、不臆断。很多人情绪不好是因为他们把自己做的假设当成了事实在不确定对方真实想法的情况下直接把情绪发泄了出来。\n\n\n第一步忘我地聆听对方的想法。过程中没有判断、没有辩论、没有对错把自己完全置身在对方的位置以对方的眼睛来看世界第二步从“我”的角度来分享过程中只说自己的客观感受而不指责对方或告诉对方该怎么做。\n\n\n如果一个人在不明就里的情况下把负面情绪发泄出来就会把其他人也带入单一视角要么被压制处于恐惧中要么反抗双方都受伤。\n\n\n不要让事情本身束缚了你的情绪和注意力。\n\n\n人类有三种天生的内在需求关系需求、能力需求和自主需求\n\n\n困难和压力总能把人的情绪和注意力抓得死死的让你很难看到其他角度。\n\n\n我并不是在做这件事我只是在做另外一件事。\n\n\n事情本身并不重要我们只是在通过它获取另外一种乐趣顺便把这件事给做了。在心理学上这个方法叫作“动机转移”。\n\n\n而真正希望通过写作建立影响力的人是不会完全被“稿酬”“流量”等外部动机束缚的他们往往是为自己的成长而写、为众人的需求而写、为长远的价值而写、为创造一个属于自己的世界而写。即使没有鲜花和掌声他们也会坚持输出和成长收获的反馈和奖励都只是意外和惊喜不是必然和期待。这样的心态能让他们的笔尖持续释放力量最终收获梦想因为选择权始终在自己手上。\n\n\n为自己而做通常是为了应对外部的压力和要求为玩而做则是为了应对重复、枯燥的事情。\n\n\n怕什么真理无穷进一寸有进一寸的欢喜。\n\n\n一、规划。利用10分钟左右的时间罗列全天的工作对它们进行排序这样可以让自己保持头脑清晰对全天的时间产生一种掌控感保证自己的工作不会走弯路。\n\n\n清晰的时间安排、强健的体魄、良好的精神状态、不受干扰的锻炼氛围、专注的学习环境、从容的工作心态、持续的个人成长等。\n\n\n六、提前准备。除了晚上提前准备好衣物更重要的是要提前想好起床之后具体要做什么比如第二天早上要是下雨了不能外出跑步应该怎么调整事项如果晚醒了半个小时又该安排哪些学习内容……总之要针对各种可能出现的情况做好预案。当脑中有具体清晰的目标、规划和步骤时第二天起床才不会犹豫否则很容易临时改变主意再睡一会儿。情绪脑追求舒适的意愿是很强烈的但如果理智脑提前和它沟通好行动的阻力就会小很多。\n\n\n成功人士一旦发现别人的好习惯就会立刻将这个习惯变成自己的。\n\n\n能够迅速进入专注状态以及能够长期保持专注状态是高效学习的两个最重要的习惯。\n\n\n闭眼静坐专注于自己的呼吸每天持续15分钟以上……你会感受到它的效果。\n\n\n人做决定时分两个层次。第一个是“情绪决定”比如看到人家健身、摄影、画画时自己的肾上腺素开始飙升马上表示自己也想做第二个是“理智决定”理智决定同样表示想要一样东西但表示人必定已经想好了为什么要做、怎样去做以及可能遇到的困难等问题。\n\n\n那么多书却没有任何改变甚至脑子更乱了。\n\n\n想要快速成为一个行业的高手最好的方法就是和行业专家交流直接向他们请教\n\n\n读书就是用最低廉的成本获取最高级的成长策略\n\n\n脚步不能丈量的地方文字可以眼睛无法看到的地方文字可以\n\n\n几乎所有的书籍都是智者看待事物、做选择、决策的过程。\n\n\n在现代社会人与人之间的根本差异是认知能力上的差异而认知能力极度依赖思考能力可以说思考能力是我们立足现代社会的根本竞争力。所以目光长远的人都会主动、刻意地磨炼自己尽力提高每天的思考密度。\n\n\n一、读书要先学会选书。\n\n\n选书比读书本身更重要。书籍是精神食粮我们“吃进”的东西会在我们身上表现出来如果不分好坏见书就读可能会“读出一身病”这样读书还不如不读。所以选书\n\n\n二、阅读是为了改变。很多人以为一本书只要读完读书的过程就结束了。事实上阅读只是整个过程的开始阅读之后的思考、思考之后的实践比阅读本身更加重要这里主要指非虚构类书籍。很多人的阅读仅停留在表面读的时候觉得这里好有道理、那里好有道理读完之后就不闻不问了然后迅速转移到下一本书中这种满足于录入的阅读造成的一个直接后果便是一段时间之后再去翻这本书就好像之前没有看过一样所有的痕迹都烟消云散了。真正读好一本书往往需要花费数倍于阅读的时间去思考和实践并输出自己的东西——可能是一篇文章也可能是养成一个习惯——这个过程比阅读本身要费力得多。\n\n\n所谓费曼技巧就是通过自己的语言用最简单的话把一件事情讲清楚最好让外行人也能听懂。\n\n\n先用合适的故事引起对方“感性小人”的兴趣和注意然后把想要表达的道理通过“感性小人”转达给“理性小人”\n\n\n若是你把写作当成是与一位老朋友聊天\n\n\n说来说去能用简单的语言就不要用复杂的这就是费曼技巧的核心之一\n\n\n以一种事物认知另一种事物恰恰是学习的本质因为人类只能通过已知事物来解释未知事物我们很难凭空去理解一个自己从未见过的东西。而类比正是连接未知事物与已知事物的桥梁。\n\n\n用自己的语言重新表达就是在调动自己的千军万马。\n\n\n所以一个人想要真正成长一定要学会写作因为“只读不写”的学习是不完整的是低效的。而写作时如果不学会用自己的语言转述则是无用的。\n\n\n时常运动的人体内生态系统犹如一汪清泉而久坐不动的人体内生态系统则更像是一潭死水。\n\n\n这表明一个长期缺乏运动的人可能会变“笨”。\n\n\n运动能够使大脑长出更多的新的神经元这意味着运动可以在物理上让人变得更“聪明”。\n\n\n好的模式是“运动+学习”\n\n\n所以运动不是关键运动之后的活动安排及环境刺激才是关键。有效的模式是这样的在运动后的1~2小时内进行高强度、高难度的脑力活动\n\n\n每天只需花一点点时间对当天最触动自己的事情或感悟进行复盘\n\n\n而复盘的方式也极为简单通常只需3点①描述经过——以便日后回顾时能想起当时的场景②分析原因——多问几个为什么直到有深度的启发③改进措施——尽可能提炼出一个认知点或行动点。\n\n\n无论何时都要把对方的情绪和意见分开对待这样即使在最糟糕的事情中也能学到有用的东西。\n\n\n如果你去练习反思也必然会关注身体、情绪和思维三个层面进而不断优化和改进自己。当然也会产生很多灵感、顿悟和创意只要你去实践就会有很多发现。\n\n\n所以当头脑中有什么想法或念头冒出来的时候一定要及时记下来哪怕是记一两个关键词也行回头再整理打磨把这个认知放大就相当于节省了一段生命。\n\n\n越是好的反思着眼点往往越细微\n\n\n三是它可以让我们正视痛苦。\n\n\n痛苦哪里是什么坏事那简直是上天给我们的成长信号与提示\n\n\n一是不要被形式所缚。\n\n\n谨记反思的最终目的是改变而不是形式的完美\n\n\n二是尽量提炼认知点或行动点。\n\n\n三是列行动清单。\n\n\n四是对自己极度坦诚。\n\n\n五是要多阅读。\n\n\n六是选择合适的记录载体。\n\n\n觉知自古以来都是精英的自我修炼方式。\n\n\n如果你想要的东西还不存在那就亲自动手将它创造出来。\n\n\n一个人若是学会了用知识和智慧驱动理性和感性这两种力量就可以获得认知觉醒。\n\n\n首先我要感谢时代和命运如果我早生、晚生几年或人生轨迹稍有差池可能都无法达成此事我知道一个人无论获得什么样的成绩都不能忽略时代、运气和环境这样的大背景只看到自身的努力和付出是狭隘和不客观的其次我要感谢我的爱人她为我分担了太多如果没有她的支持我肯定无法完成此书再次感谢寇佳颖的发现、感谢陈锐的引荐、感谢陈素然编辑的慧眼感谢人民邮电出版社的厚爱是你们的热情让这本书得以面世最后我要特别感谢卫蓝、王世民、师北宸、一稼、易仁永澄几位老师对我这位不知名作者的提携感谢你们对《认知觉醒》的认可让它有机会借助你们的力量去帮助更多的人当然最需要感谢的人是你们——我所有的读者你们最终的触动、改变和反馈才是我最大的、真正的收获。\n\n笔记\n\n大脑“解释系统”的逻辑虽然很荒谬但强大的天性会迫使理性这样解释而有的人还真接受了于是有人去网上购买刷步神器坐在家中就可以让自己运动步数名列前茅有人早上5点闹钟一响就在早起群里打个卡然后倒头继续睡有人翻开书拍张照然后将照片发到朋友圈以示自己今天读过书了……\n\n💭 我们会自己骗自己,但是要学会机智的骗自己。\n\n所谓认知闭合需求就是指当人们面对一个模糊的问题时就有给问题找出一个明确的答案的欲望。比如古时候人们不知道为什么会下雨于是下雨这个问题就没有闭合会让人很难受所以古人就用雷公、电母、龙王解释下雨的成因这些说法虽然没什么根据但满足了认知闭合需求。将这一概念扩展到行为上也是一样的一件事若迟迟没有完成心里就总是记挂期盼着早点结束此事一旦完成做这件事的动机就会立即趋向于零。\n\n💭 好奇自己为什么要给自己一个看起来合理的答案?\n\n所有痛苦都是上天给我们的成长提示。无论是身体不适、情绪低落还是学业落后、事业受挫有痛苦出现说明哪里出了问题这不就是在告诉我们应该努力的方向吗\n\n💭 痛苦就是痛苦,并不是痛苦拯救了我们,对痛苦的思考才是最重要的,但阅读也可以做到思考,所以切勿美化痛苦。\n\n控制学习和工作内容的难度也是保证专注的重要方式因为太容易的内容会让人因无聊而走神太困难的内容会让人因畏惧而逃避\n\n💭 我比较喜欢攻击困难的事情,它会使我沉浸在里面\n\n对大多数人来说打卡只是一场充满激情的欢娱盛宴无须多日他们就会出现在另一轮打卡活动中或是无疾而终了。\n\n💭 为了打卡而打卡?\n书评\n点评"},"Personal/Book/心理/认知驱动:做成一件对他人很有用的事":{"title":"认知驱动:做成一件对他人很有用的事","links":[],"tags":["阅读/心理-认知与行为","阅读/笔记"],"content":"简介\n\n书名《认知驱动做成一件对他人很有用的事》\n作者 周岭\n分类 心理-认知与行为\nISBN9787115569455\n出版社人民邮电出版社\n\n概述\n做成一件有价值的事成为一个有价值的人 成长的根本是做成事情、创造价值。 做到,是更高等级的成长。一个人的成长也是通过主动做成一件对他人很有用的事来实现的。但在现实生活中,很多人虽然内心强烈希望变好,行动也非常努力,却始终无法做成事情,这背后的原因通常是缺少价值意识、输出意识、创造意识、作品意识、利他意识…… 《认知驱动:做成一件对他人很有用的事》将通过“做成一件事”的心法和技法两部分内容,和大家一起探索如何通过创造个人价值获取人生的成功、幸福和意义。 从“习惯养成”到“技能培养”,从“对内输入”到“对外输出”,从成为“更好的人”到成为“更有价值的人”,这些刻意的转变会让我们走出焦虑的怪圈。 单纯依靠意志力的努力往往是盲目的,所以人们会反反复复地起念,又反反复复地失败。一个人只有了解做成一件事的来龙去脉、看清事情本质后,才能走出反复尝试却劳而无功的困境。 学会用认知来驱动自己,我们才能更好地到达成长的彼岸——做成一件对他人很有用的事,成为一个有价值的人。\n划线\n\n内向成长即围绕自身展开的成长活动比如早起、跑步、阅读等。\n\n\n外向成长即围绕外界展开的成长活动比如写作、画画、编程等。\n\n\n享受努力奋斗的状态却少有产出作品的意识。\n\n\n重技能辅习惯重输出辅输入。\n\n\n人生的差异往往源于人们看待生活的不同视角。当你掌握了“复制”和“转换”这两个底层概念时或许会看到一个不同的世界。\n\n\n“转换”和“复制”的最大区别在于边际成本不同——“转换”的边际成本越来越高“复制”的边际成本越来越低。\n\n\n并非所有的“复制”类活动都具有无限可能因为“复制”只是一种渠道获得无限可能的关键依旧在于价值。\n\n\n要想获得无限可能“复制”和“价值”缺一不可且价值越高可能性越大。如果你对自己的人生有追求那就应该激励自己去创造“可复制的价值”。\n\n\n更重要的是每次提笔时我都要问自己这样一个问题这篇文章在三年、五年甚至十年后再看还有价值吗如果没有那就没必要写了。仅这一问就能消除一切浮躁的动机。\n\n\n产对别人有用的东西永远是写作的指南针其他事情亦是如此价值交换规律放在哪里都会起作用。\n\n\n永远走价值积累之路\n\n\n社会在巨变但价值交换规律不变。\n\n\n而本节的意义就是想告诉你无论你选择写作还是其他“价值产出”之路永远适合每一个人无论何时都有效。\n\n\n而一个人要是能放弃自己的小九九能发自内心地为社会发展、为人民福祉去做事他就会真的充满力量完成难以达成的任务。\n\n\n我们是为了实现人类理想而努力奋斗。\n\n\n利他的途径是创造价值\n\n\n是误把牺牲和讨好当成利他以致得到的反馈和体验极其不好。最典型的表现就是无原则地对他人好或是有目的地付出\n\n\n情侣在关爱对方的同时也要不断提升自己用自身的优秀去带动对方同步成长这才是健康的爱。\n\n\n同样的话从你和牛人的嘴里说出来效果就是不一样这显然不取决于对或不对而取决于说话的那个人是谁\n\n\n更好的关系不是付出而是吸引\n\n\n擅打组合牌的人往往会在条件允许的情况下尽可能先把目光聚焦到自己身上他们会维护自己的形象增加自己的学识提升自己的智慧稳定自己的情绪丰富自己的爱好结交理想的朋友追逐自己的梦想……这样就可以始终向别人传达自己的魅力和自信让喜欢的人主动靠近。\n\n\n这背后的原因大同小异从短期看是对方的素质和修养不够高从长期看是自身的能力和表现还不够好。因为所有的社交都是一面镜子外界如何给你反馈根源在于自身长期的综合表现。\n\n\n在和别人结婚之前不妨先和自己“结一次婚”。不管你是男是女、已婚未婚都可以给自己做一次这样的假设你愿意和自己这样的人共度一生吗无论贫穷、疾病也不离不弃事实上和自己结婚也只能不离不弃。你喜欢自己的外在表现吗喜欢自己的言行举止吗喜欢自己的能力和上进心吗喜欢自己对未来的追求吗如果你对自己尚不满意就不要指望别人会尊敬和喜欢你了。\n\n\n想要更好请停止追逐\n\n\n这就是所谓的“被动社交”——通过产出独一无二的、具有长久价值的作品或产品来与这个世界保持连接。\n\n\n内向者更有创造优势\n\n\n因为内向成长者的生理特点决定了他们更擅长与事物而非与人物打交道。\n\n\n内向者更倾向于使用理智脑与外界互动而外向者更倾向于用本能脑和情绪脑与外界互动。\n\n\n越是在传播手段发达的社会里越要坚守价值。因为这个世界已经不缺乏传播途径了但价值依旧稀缺\n\n\n所谓“自我意识”就是从自己的身份定位开始思考问题即“我是一个什么样的人所以我应该去做什么样的事”。在这个视角之下所有的选择、方法、努力都会主动围绕自我身份的建设而自动转换为合适的状态。这样的人可以说是真正的觉醒者了。\n\n\n现在我们可以脱离这一模型记住“环境、努力、方法、选择、身份、意义”这几个词就行了\n\n\n对个体来说最重要的事情莫过于找到人生目标和意义想清楚自己应该成为什么样的人。\n\n\n身份改变自己的终极力量\n\n\n我经常对自己说一句话你是个干大事的人。\n\n\n若你还没富请先让自己像一个富人。用富人的思考方式、富人心态、富人思维武装自己改变自己的气质让自己看起来更具“富人气”……\n\n\n这种行为触及了我们人类成长的终极力量——心理建设。\n\n\n即人的行为改变可分为身份、过程、结果三个层次不同层次的努力会带来不同的结果\n\n\n因此那些能明确自己身份的人才是真正的高手他们肯花时间进行心理建设能从上而下或从里到外地改变自己。\n\n\n你的世界是你所关注事物的产物。”“我们的大脑是依据我们关注的事物来构建世界观的。”我们选择去关注哪些事物、忽略哪些事物会对我们的生活质量起到关键的作用。\n\n\n做最好的准备做最坏的打算\n\n\n所以坚定信念和降低期待并不矛盾因为坚定信念就是做最好的准备而降低期待就是做最坏的打算。它们的目的是一致的促使自己更好地行动并最终产生好的结果见图2-6。[插图]图2-6 做最好的准备,做最坏的打算\n\n\n成长注定是一个将内在身份不断揉碎并重塑的动态过程。\n\n\n语言是幸福人生的开端\n\n\n语言和思维之间其实是双向车道而非单向车道。如果你知道自己还可以在思维和语言之间“逆向行驶”你的生活就会多出很多主动的选择。\n\n\n穷爸爸总是习惯说“我可付不起”而富爸爸则禁止我们说这样的话他坚持让我们说“我怎样才付得起”\n\n\n如果你再细心观察就会发现像肯德基、麦当劳这样的门店进门时常常需要拉开门而不是推开门。因为拉门时手臂收缩这个动作可以让我们进入一种“简单满足”的心理状态。而柜台上方展示食物的电子屏幕通常是从上往下而不是从左往右滚动因为当人们的目光跟随屏幕从上到下移动时像在点头称是。这种隐蔽的设计会对我们形成心理暗示但我们很难察觉。\n\n\n美好人生从好好说话开始\n\n\n·无论遇到什么事情说积极的话不说消极的话·无论遇到什么人物说和善的话不说刻薄的话·无论遇到什么问题说开放的话不说绝对的话……\n\n\n乐观构想、悲观计划、乐观实行\n\n\n理性思维的局限正在于此——它只相信自己所见所闻的一切事情对于已知之外的未知它会主动怀疑并排斥。\n\n\n乐观构想、悲观计划、乐观实行\n\n\n这与《人生算法》的作者喻颖正说的“人生最好的模式是长期乐观、短期悲观、当下愉悦”如出一辙。\n\n\n即使勉强起步了却又在过程中过于乐观、急于求成希望很快看到成果结果频遭打击以致在接下来的具体行动中萎靡不振、痛苦煎熬没过多久就放弃了。归结起来正好是“长期悲观、短期乐观、当下痛苦”的模式。细细想来这或许正是很多人无法成事的原因之一吧。\n\n\n理性思维是把双刃剑\n\n\n人生还需要浪漫、无畏和勇气\n\n\n有时候我们无法达成目标不是因为我们不够理性而是因为我们不够感性。\n\n\n动物对威胁及讨厌事物的反应要比对机会及喜好事物的反应更快、更强烈、更持久。换句话说生命对坏事的反应要强于对好事的反应。这种“负面偏好”\n\n\n“负面偏好”会使我们更多地注意负面信息和事件不自觉地忽略大多数正面、美好的事情。\n\n\n要想对冲一件坏事的影响我们往往需要制造多件同等规模的好事。比如在夫妻关系中一句批评的话所造成的伤害起码需要5个善意的行为才能弥补\n\n\n善用不同的视角看问题——既然基因和本能让我们不自觉地关注坏事那我们不妨反其道而行之试着多看看好事毕竟我们生活在现代社会生存不再是最重要的主题生存得更好才是。\n\n\n但它是对冲人类“负面偏好”的利器因为它可以帮助我们主动发现自己和生活中的亮点弥补我们大脑天生的缺陷。\n\n\n一个智慧的人不会等到自己真正失去了才后悔当初没有珍惜他们在拥有的时候就会主动平衡注意力更多地关注自己已经拥有的快乐和幸福。\n\n\n幸福的人各有各的幸福而不幸的人都是相似的因为他们都是“身在水中却看不到水的鱼”。\n\n\n“三十而立”意即到了三十岁才懂得要立志做一件事情。\n\n\n四十而不惑”意即到了四十岁才不犹豫才不疑惑。\n\n\n五十而知天命”意即五十岁也没达到目标才知道这是天意啊\n\n\n六十而耳顺”意即到了六十岁什么话听起来都心情顺畅不生气都无所谓。\n\n\n七十而从心所欲不逾矩”意即到了这个岁数才真正得到了自由\n\n\n我们来自非黑即白的世界\n\n\n童话有确定而美好的结局试题有确定而标准的答案而父母也经常这样教育孩子“你管好自己的学习就行了其他的事不用你操心。”\n\n\n我们终究要走向复杂的世界\n\n\n成人可以忽略复杂和忍受混乱甚至积极地改变自己去发掘不利中的有利比如忽略对方的情绪化但学习对方健谈的品质或是尝试创造契机营造所有人都和谐、亲密的氛围。这样一来讨厌的事情不仅消耗不了你你还能从中得到成长和滋养或者说你根本就不会对这些事情感到厌烦——这才是高级的逍遥自在。\n\n\n在非黑即白的世界里人们只能容纳自己喜欢的事物只能接受自己喜欢的秩序。\n\n\n如果只输入不输出就会堵塞如果只输出不输入就会断流。\n\n\n好的生活是始终游走在舒适区边缘\n\n\n能力圈法则告诉我们一个人成长进步最快的区域在自己能力舒适区的边缘太困难或太舒适的区域都容易让我们止步不前。\n\n\n熵是表示无序程度的量度时就能理解了因为正值大于负值所以正熵表示更无序负熵表示更有序而熵增和熵减自然是指趋向无序和趋向有序的过程。\n\n\n人无远虑必有近忧。这句话反过来说也是成立的人无近忧必有远虑。\n\n\n我的一个减压秘诀就是尽量不要同时设定很多目标主动降低期待不急于看到成果。\n\n\n因为真正的目标和动力来自我们对一件事情清晰而长远的认知而非某个特殊的时间点\n\n\n大多数人无法成功戒烟的主要原因是不清楚烟瘾形成的真正机制只好依靠意志力戒烟。\n\n\n事实上真正开启我主动成长机制的契机是我从《暗时间》这本书中得知了人类大脑原来是由本能脑、情绪脑和理智脑构成的。这个三重大脑理论让我一下子看到了人们成长过程中面临的几乎所有的困惑诸如缺乏耐心、急于求成、无法专注、沉迷娱乐、低效学习等这些问题都能从中得到解释。\n\n\n长期乐观、短期悲观、当下愉悦\n\n\n他们不知道做成一件事的方法论只能凭感觉行事任由欲望驱动自己\n\n\n看清机制防止盲目努力寻找意义注入长久动力感受好处体验当下愉悦。\n\n\n第二节 写下来我们都低估了“写下来”的力量\n\n\n在自己无法消化情绪的时候她就用笔一条条写下自己真实的想法写下自己到底在难过什么。\n\n\n运用书写来表达自己情绪的人更加健康。\n\n\n假设是一切进步的开始\n\n\n但困难之时正是进步之机。如果此时有人敢直视模糊、敢于对不确定性做出脑力范围内最大程度的“假设”那他就能更大概率地突出重围获取更多人生优势。\n\n\n只要书中有一个点触动了自己并让自己的生活发生了真实的改变这次阅读就是有效的这本书就是超值的。\n\n\n假设是一切进步的开始现实结果是最好的评判师。\n\n\n命运一定钟爱那些愿意慢慢变好的人\n\n\n不过可以肯定的是几年后他一定会像我们一样走得既快又好可以轻松准确地控制自己的身体。\n\n\n我们总想同时做很多事又想马上看到结果还特别在意他人的评价以致看不到进步就会烦躁遇到退步就自我否定。如此说来现在的我们要想更好地改变自己还得回头向幼时的自己学习呢。\n\n\n我们长大后的多数烦恼都来自对自己和他人的过高期待。\n\n\n我回想起技能学习的本质就是通过大量的练习使大脑中相关神经元产生连接并形成强关联的过程。这个过程在初期必然是非常缓慢的因为它们之前还没有形成顺畅的通路。但只要持续练习这些连接就会越来越多、越来越强最终形成一张高效的网络使自己在某天开始加速并突破。\n\n\n所谓的耐心或好脾气很多时候就是适当降低期待\n\n\n你要一开始就把自己想成是一个人没有父母、没有子女、没有配偶、没有朋友、没有任何人的帮助这样后面的一切都会让你觉得无限惊喜。\n\n\n人生的幸福不是寻求快乐而是没有痛苦。\n\n\n我认为检验一流心理的标准也是如此——看一个人能不能在心中同时容纳两种相反的期待还能正常行事。\n\n\n换句话说就是将剧中的情景对话强化为“大脑的肌肉记忆”直到在类似的场景下不用思考就能脱口说出极为准确和地道的外语。\n\n\n因为真正的对手不怕你会一万招就怕你把一招练一万次。\n\n\n学习无非两种一种是认知上的学习另一种是技能上的学习。\n\n\n德国哲学家叔本华说过这样的至理名言“人类幸福的两个死敌就是痛苦和无聊。当我们成功远离其中一个死敌的时候也就在同等程度上接近了另一个死敌反之亦然。所以我们的生活确实就是在这两者之间或强或弱地摇摆。”\n\n\nB计划是人生幸福的保障所谓B计划就是我们在主业之外还有另一个人生目标或追求它可以让我们填充闲暇、排解无聊甚至创造成就。\n\n\n在某个技能或者说“某个维度”上死磕确实是一个策略但更好的策略是“多维度打造竞争力”。因为在单个维度上比的是长度在两个维度上比的是面积在三个维度上比的是体积。所以每次跨界都是给自己拓展一个新的维度维度多了竞争力自然就强了。\n\n\n首先独自潜行可以让我们保持圈外人的独特视角防止自己的思想或风格被主流同化。\n\n\n那就是B计划最好是一个秘密的项目至少在开始的时候是这样的。\n\n\n人生就是在痛苦与无聊之间摇摆”。不过在如今这个世界我倒是更愿意将其演化为人活着就是为了对抗无聊。\n\n\n所以无论何时我们都要在本职工作之外培养一个甚至多个全新的技能去创造一个或多个外界无法剥夺的价值和优势。\n\n\n这正是环境赋予一个人的力量它能让一个人产生变好的念头并愿意去努力还能让这份努力的效果得到放大。从某种程度上说环境的力量其实远超个人努力只是很多人会天然地无视或忽略这一点认为只要努力就可以成就自己毕竟努力是看得见的而环境因素却会因为自己身在其中而很难觉察。\n\n\n我们的生活环境决定了我们每天要见哪些人、做哪些事这些人和事会直接影响我们的思维与言行因为人类大脑中有镜像神经元它会让我们无意识地模仿身边的人和事所以若是周围的人经常做某些事情我们也会不自觉地学着做。\n\n\n因为我们很难在无意识的状态下表现出高于所处环境的言行或追求我们只会在当前环境中保持最舒适的状态。\n\n\n一是信息爆炸了但知识并没有爆炸。海量的信息不仅增加了我们甄别筛选知识的难度还让我们随时随地处于即时信息和肤浅信息的包围中。\n\n\n二是被称为人体新器官的手机随时可以把我们的时间撕成碎片。\n\n\n只是暂时\n\n\n移动到更好的环境中是借力“偷懒”的上上策。\n\n\n让孩子置身于那个真实的、优秀的环境之中这是极为明智的。这会调动孩子的多维度感官让他们发自内心地产生学习动力而这种真实环境的激励远比父母每天苦口婆心的劝说要好得多。\n\n\n小环境借力主动掌控\n\n\n如果不希望受某些环境的影响最好的方式就是避免让自己置身其中。\n\n\n那些看起来有强大自控能力的人并非真的比常人更自律而是因为他们会尽量避免置身于充满诱惑的环境中——这才是他们保持自律的真正“秘诀”。\n\n\n跳出空间\n\n\n跳出时间”\n\n\n学习的秘密在于同时调动多维度感官\n\n\n但是感知不到不代表它们不存在或不重要。事实上那些我们感知不到的信息可能更重要。就拿那些平时不怎么读书却依然成就很大的人来说他们虽然很少通过阅读来进行思维活动但是他们有机会经历很多大事见到很多高人。在那些经历和环境中他们能看到高人们如何应对复杂的情景听到高人们切中要害的言论感受成就一件事的辛酸和不易……\n\n\n所以介入阅读更理想的时机或许正是一个人既有一定的人生经历又有一些人生困惑的时候此时读书往往会以解决问题为目的知识和阅历能相互融合意识和潜意识的所有维度也能有效结合可塑性最强。\n\n\n一是“愿望觉醒”即一个人从不知道要变好到想要变好从“浑浑噩噩”的状态转而开始对“美好生活”有了强烈的向往。\n\n\n二是“方法觉醒”即一个人从不知道怎么变好到知道怎么变好其行动力从盲目的毅力支撑升级到科学的认知驱动。\n\n\n三是“目标觉醒”即一个人开始寻找自己的人生目标并努力去做成一件或多件对自己和他人有用的事让自己成为一个很有价值的人。\n\n\n正如一个人从睁眼到完全清醒不是一瞬间的事它是一个逐渐实现的过程。所以“目标觉醒”就是我们判断一个人是否真正觉醒的最终依据同时它也是个体成长的高级阶段因为做到是最高等级的成长。\n\n\n至少主动做成一件对他人很有用的事。\n\n\n在没有外力的要求下自发地做一件事并让它成为自己的一部分或形成一定的影响力。\n\n\n总之你想养成习惯那就让习惯成为自己的一部分你想培养技能那就让技能形成一定的影响力。\n\n\n“我做哪件最重要的事之后会让其他事情变得更简单或者不必要”\n\n\n人生更高级的驱动力是主动的喜悦。\n\n\n在刚开始进入一个新领域时主动开启“苍蝇模式”让自己尽情地试错这样才有机会找到“出口”\n\n\n周期·如何保持耐心、不焦虑\n\n\n一是它能让人彻底告别焦虑不再急于求成。\n\n\n但是自从我把心理标尺拉长到7年之后所有的焦虑、浮躁一下子都消失了我突然觉得时间很充裕一点都不着急了。\n\n\n二是它能让人聚焦目标并拥有真正的成果。\n\n\n如果我们真能在每个7年彻底做成一件事那这一生的成就也将非常璀璨。\n\n\n三是它能够让人持续学习终身成长。\n\n\n顶级的生活不是奢华而是创造\n\n\n人类幸福感的本源只有两个一个是基因的传承另一个就是影响力。\n\n\n我们要想有影响力就一定要有输出因为有输出才能被别人看见然后还要让输出有价值因为价值足够大才能被别人强烈需要而在输出和价值双重标准的驱动下我们就必然能获取反馈并借助反馈持续迭代最终创造出独一无二且对自己和他人有长期价值的原创作品。\n\n\n因为一流的生活是觉知是内修它可以让我们自身变得更好而顶级的生活是创造是外修它可以让别人过得更好。而生命的意义在于利他因为只有从他人的正面反馈中我们才能照见自己。\n\n\n努力成为一个对他人很有用、被他人强烈需要的人\n\n\n从大范围看个人努力固然重要但大环境、大趋势更重要从小范围看我们仍然要强调个人努力因为价值会吸引好运。\n\n笔记\n\n我们的生活环境决定了我们每天要见哪些人、做哪些事这些人和事会直接影响我们的思维与言行因为人类大脑中有镜像神经元它会让我们无意识地模仿身边的人和事所以若是周围的人经常做某些事情我们也会不自觉地学着做。\n\n💭 人是环境的产物\n\n但是感知不到不代表它们不存在或不重要。事实上那些我们感知不到的信息可能更重要。就拿那些平时不怎么读书却依然成就很大的人来说他们虽然很少通过阅读来进行思维活动但是他们有机会经历很多大事见到很多高人。在那些经历和环境中他们能看到高人们如何应对复杂的情景听到高人们切中要害的言论感受成就一件事的辛酸和不易……\n\n💭 读万卷书行万里路\n\n《见识》的作者吴军曾在书中提到人类幸福感的本源只有两个一个是基因的传承另一个就是影响力。\n\n💭 归属感,价值感\n书评\n点评"},"Personal/Book/心理/谈性说爱写给女性的性心理24讲":{"title":"谈性说爱写给女性的性心理24讲","links":[],"tags":["阅读/心理-认知与行为","阅读/笔记"],"content":"简介\n\n书名《谈性说爱写给女性的性心理24讲》\n作者 甄宏丽\n分类 心理-认知与行为\nISBN9787521743241\n出版社中信出版集团\n\n概述\n现代社会女性的社会地位与自我认知都得到了很大提升但在性的问题上依然存在很多说不清道不明的羞耻感。性一直都属于禁忌话题虽然不说或者很少说但现实生活中对性的理解与认知会在很大程度上影响女性的亲密关系幸福度理解或认知不当甚至会造成悲剧。 《谈性说爱》一书作者甄宏丽深耕女性性心理治疗与科普领域,深谙中国女性的性困境,书中从揭开女性的身体奥秘开始,讲述了女性性生理和性心理唇齿相依的关系;强调了尊重性本能的重要意义;对性与爱的关系、性与亲密关系等敏感话题展开了详细分析,阐述了全新的观念:性与爱合久必分,分久必合。作者在书的最后指出,懂性、爱性是性福女人的基石,活出性感真我是女性魅力的核心。 对于中国的新女性来说,需要这么一本书来刷新自己在性问题上的认知,补上这堂迟来的性教育课。\n划线\n\n把处女膜献给我未来的丈夫。\n\n\n处女膜是长在我身上的是属于我的我想什么时候拿出来用就用处女膜绝不是我留着献给男人的礼物”。\n\n\n女性太压抑自己的性欲望不敢放开自己。\n\n\n“不要性骚扰要性高潮”\n\n\n性爱是两个平等、独立的主体间的双人舞。\n\n\n处女膜的概念属于性医学范畴婚前性行为属于社会学范畴体会性冲动的兴奋程度属于性生理学范畴要不要发生婚前性行为属于性心理学和性教育学范畴坚守处女情结婚后因为怕疼无法完成性生活属于性心理治疗学范畴。\n\n\n中国女性追求性福已经不再遮遮掩掩但是她们的性生活满意度很低依然是个不争的事实。\n\n\n性道德、性权利、性价值观等核心问题上依然存在严重的男尊女卑观念。\n\n\n生理、心理、社会\n\n\n生殖器官正常存在才能让我们拥有性别身份即是男还是女。\n\n\n为什么会有处女膜这个名字实际上这是男权社会用来管理女人的一种手段。\n\n\n“处女”这个词已经不仅仅局限于没有发生过性行为的女性这个概念了。它衍生出的意义是任何非常值得珍惜的第一次经历。这是非常美好的概念。\n\n\n第一性道德观点压抑女性性能力。\n\n\n第二女性对自己的定位存在偏差。\n\n\n第三很多女性认为只有在爱的基础上才有权利享受性愉悦也就是所谓的性和爱是不可分割的。\n\n\n第四有的女性觉得自己性魅力不够。\n\n\n因此女性在性爱中长期处于一种被检验的状态无法自然放松下来脑子里充满问号他觉得我的胸够大吗他觉得我的皮肤白皙吗我的腿太粗了吧我的臀部是下垂的他发现了吧等等。\n\n\n真正男女平等、彼此尊重的和谐社会对于男性和女性应该是同样的标准男女的性权利都值得尊重男女的性行为都不可以乱来都要有做人的行为底线都有权利获得性愉悦都有权利获得性的隐私保护等等。\n\n\n客观地去感受积极地去接纳。\n\n\n吃甜品不仅可以疏解消极情绪还可以产生积极情绪。\n\n\n人类最大的性器官可能被我们忽视了那就是皮肤。\n\n\n我们知道了皮肤是人类最大的性器官当你想要被拥抱或者想去触碰对方的时候是有一种明显的性需求在里面的不要去否定它。我们要抓住这种信号让自己更加鲜活起来。\n\n\n性与爱是分久必合、合久必分的关系。\n\n\n我个人认为分久必合、合久必分的观点恰恰体现了性与爱之间的和谐但性和爱又是完全不同的两个东西。\n\n\n青春期时对某个人的爱慕就像一股清流让人感到新奇而美妙这种精神世界的美好已经让人很满足不需要通过性交实现。\n\n\n男性从来都是把性能力放在第一位这种性能力就是接受刺激就要勃起对女性就得征服不能输要是阳痿那就完了。所以在男性看来性能力是高于性道德的。\n\n\n只要女性不再自己物化自己就有可能真正地实现男女平等。\n\n\n女性面对自己喜欢的男性容易活在自己的想象中\n\n\n受中国几千年封建文化的影响女性把自己物化男性也把女性物化了。\n\n\n赤裸裸地坦诚相对是恋人走进彼此内心世界的唯美途径是其他任何关系都无法替代的。\n\n\n这里的熟女指的是懂得了人间情爱滋味的女人。这种在岁月中成长起来的魅力实际上是源于懂男人。所谓懂男人其实很大程度上是懂得男人的需求懂得他们喜欢什么样的女性魅力。\n\n\n现实生活中我们也看到如果女性有了婚外性行为大多数丈夫都会选择离婚而且很多女性也能接受离婚的现实甚至有可能是女性主动提出离婚。很多人都问过我为什么会这样。其实这一点都不奇怪跟我们传统性观念中性道德的男女双重标准有关。\n\n\n社会约束男性和女性的性道德有双重标准。\n\n\n。为什么女性对其他方面的包容度极高而对婚外性行为零容忍呢婚后的守贞难道是丈夫们的护身符吗可以抵过其他所有的婚姻义务婚姻意味着你们是合理合法的性伴侣、经济收入与债务的共同承担者、孩子的父母有很多功能我们不能把性看得这么重。\n\n\n丈夫跟妻子谈论性话题会显得很没面子应该直接干就行了妻子跟丈夫谈论性话题又会很不好意思。\n\n\n无论是男性还是女性我们都应该关注亲密动作——亲密动作可以表示好感表示相互的安慰表示相互的喜欢也可以表示相互的性的需要。\n\n\n用激情换来的相互了解与和谐平稳那种互相熟悉的默契是常年在一起的伴侣特有的。这种默契可能是一个眼神对方就知道你要什么或者说通过女性体位的小小的变化伴侣都能知道你有没有兴致等等\n\n\n只有外阴也润滑了才是足够润滑这是性兴奋导致的润滑液的分泌。\n\n笔记\n\n有时候你可能特别想抱抱\n\n💭 没事多拥抱身边的人\n\n如果你在恋爱之前对自己的评价分数能够达到80分以上也就是说你绝大多数时候是接纳自己的、是自信的那你就基本处于心理健康的状态。\n\n💭 你愿意嫁给你自己么\n书评\n点评"},"Personal/Book/政治军事/实践论":{"title":"实践论","links":[],"tags":["阅读/政治军事-政治","阅读/笔记"],"content":"简介\n\n书名《实践论》\n作者 毛泽东\n分类 政治军事-政治\nISBN7010011648\n出版社人民出版社\n\n概述\n毛泽东的《实践论》是为着用马克思主义的认识论观点去揭露党内的教条主义和经验主义——特别是教条主义这些主观主义的错误而写的。因为重点是揭露看轻实践的教条主义这种主观主义故题为《实践论》。毛泽东曾以这篇论文的观点在延安的抗日军事政治大学作过讲演。\n划线\n\n马克思主义者认为只有人们的社会实践才是人们对于外界认识的真理性的标准。实际的情形是这样的只有在社会实践过程中物质生产过程中阶级斗争过程中科学实验过程中人们达到了思想中所预想的结果时人们的认识才被证实了。\n\n\n实践高于理论的认识因为它不但有普遍性的品格而且还有直接现实性的品格\n\n\n马克思主义的哲学辩证唯物论有两个最显著的特点一个是它的阶级性公然申明辩证唯物论是为无产阶级服务的再一个是它的实践性强调理论对于实践的依赖关系理论的基础是实践又转过来为实践服务。\n\n\n看到了各种文件这些就是事物的现象事物的各个片面以及这些事物的外部联系。这叫做认识的感性阶段就是感觉和印象的阶段。\n\n\n这个概念、判断和推理的阶段在人们对于一个事物的整个认识过程中是更重要的阶段也就是理性认识的阶段。认识的真正任务在于经过感觉而到达于思维到达于逐步了解客观事物的内部矛盾了解它的规律性了解这一过程和那一过程间的内部联系即到达于论理的认识。\n\n\n感性的认识是属于事物之片面的、现象的、外部联系的东西论理的认识则推进了一大步到达了事物的全体的、本质的、内部联系的东西到达了暴露周围世界的内在的矛盾因而能在周围世界的总体上在周围世界一切方面的内部联系上去把握周围世界的发展。\n\n\n认识过程中两个阶段的特性在低级阶段认识表现为感性的在高级阶段认识表现为论理的但任何阶段都是统一的认识过程中的阶段。\n\n\n我们的实践证明感觉到了的东西我们不能立刻理解它只有理解了的东西才更深刻地感觉它。感觉只解决现象问题理论才解决本质问题。\n\n\n马克思、恩格斯、列宁、斯大林之所以能够作出他们的理论除了他们的天才条件之外主要地是他们亲自参加了当时的阶级斗争和科学实验的实践没有这后一个条件任何天才也是不能成功的。\n\n\n为了明了基于变革现实的实践而产生的辩证唯物论的认识运动——认识的逐渐深化的运动下面再举出几个具体的例子。\n\n\n战争的领导者如果他们是一些没有战争经验的人对于一个具体的战争例如我们过去十年的土地革命战争的深刻的指导规律在开始阶段是不了解的。他们在开始阶段只是身历了许多作战的经验而且败仗是打得很多的。然而由于这些经验胜仗特别是败仗的经验使他们能够理解贯串整个战争的内部的东西即那个具体战争的规律性懂得了战略和战术因而能够有把握地去指导战争。\n\n\n第一个在前面已经说过的这里再重复说一说就是理性认识依赖于感性认识的问题。\n\n\n第二是认识有待于深化认识的感性阶段有待于发展到理性阶段——这就是认识论的辩证法[插图]\n\n\n理性认识依赖于感性认识感性认识有待于发展到理性认识这就是辩证唯物论的认识论。\n\n\n抓着了世界的规律性的认识必须把它再回到改造世界的实践中去再用到生产的实践、革命的阶级斗争和民族斗争的实践以及科学实验的实践中去。\n\n\n理论的东西之是否符合于客观真理性这个问题在前面说的由感性到理性之认识运动中是没有完全解决的也不能完全解决的。要完全地解决这个问题只有把理性的认识再回到社会实践中去应用理论于实践看它是否能够达到预想的目的。\n\n\n人们原定的思想、理论、计划、方案毫无改变地实现出来的事是很少的\n\n\n因为从事变革现实的人们常常受着许多的限制不但常常受着科学条件和技术条件的限制而且也受着客观过程的发展及其表现程度的限制客观过程的方面及本质尚未充分暴露\n\n\n许多时候须反复失败过多次才能纠正错误的认识\n\n\n。无数相对的真理之总和就是绝对的真理\n\n\n世界到了全人类都自觉地改造自己和改造世界的时候那就是世界的共产主义时代。\n\n\n这就是辩证唯物论的知行统一观。\n\n笔记\n\n其中尤以各种形式的阶级斗争给予人的认识发展以深刻的影响。在阶级社会中每一个人都在一定的阶级地位中生活各种思想无不打上阶级的烙印。\n\n💭 阶级局限性\n\n一个人的知识不外直接经验的和间接经验的两部分。而且在我为间接经验者在人则仍为直接经验。因此就知识的总体说来无论何种知识都是不能离开直接经验的\n\n💭 读万卷书是间接经验,理论知识;行万里路是直接经验,实践所得。毕竟山在哪里和山在眼前,天差地别。\n\n我们的结论是主观和客观、理论和实践、知和行的具体的历史的统一反对一切离开具体历史的“左”的或右的错误思想。\n\n💭 手握理论去实践,复盘总结继续实践。\n书评\n点评"},"Personal/Book/教育学习/如何阅读一本书":{"title":"如何阅读一本书","links":[],"tags":["阅读/教育学习-教育","阅读/笔记"],"content":"简介\n\n书名《如何阅读一本书》\n作者 莫提默·艾德勒 查尔斯·范多伦\n分类 教育学习-教育\nISBN9787100106184\n出版社商务印书馆有限公司\n\n概述\n这是一本关于阅读的永不褪色的经典。本书是一本阅读指南一本指导人们如何阅读的名作曾高踞全美畅销书排行榜榜首自问世以来好评甚多重版多次。书中介绍了阅读的方法、技巧阅读所应具备的广阔视野。\n划线\n\n如果没有经历这么多年的寻觅与颠簸发现与失落我读这本书的感受不会这么深刻收获也不会这么丰富。\n\n\n法国学者帕斯卡尔Pascal在三百年前就说过“读得太快或太慢都一无所获。”\n\n\n全国性的狂热\n\n\n提出不同速度的阅读法才是解决之道。我们的目标是要读得更好永远更好不过有时候要读得慢一点有时候要读得快一点。\n\n\n掌握一段文字的中心思想是什么或是论述文的重点及次要重点在哪里\n\n\n第一篇介绍四种不同层次的阅读——基础阅读elementary reading、检视阅读inspectional reading、分析阅读、主题阅读syntopical reading\n\n\n读书的主要目的当作是增进理解能力的人\n\n\n太精心的设计\n\n\n第一提醒读者阅读可以是一件多少主动的事。第二要指出的是阅读越主动效果越好。\n\n\n作者就很像是一位投手。有些作者完全知道如何“控球”他们完全知道自己要传达的是什么也精准正确地传达出去了。\n\n\n阅读的目标为获得资讯而读以及为求得理解而读\n\n\n这本书是某个人用文字书写的想要与你沟通一些想法。你要能成功地阅读这本书完全看你能接获多少作者想要传达的讯息。\n\n\n只有一种方式是真正地在阅读。没有任何外力的帮助你就是要读这本书。你什么都没有只凭着内心的力量玩味着眼前的字句慢慢地提升自己从只有模糊的概念到更清楚地理解为止。这样的一种提升是在阅读时的一种脑力活动也是更高的阅读技巧。这种阅读就是让一本书向你既有的理解力做挑战。\n\n\n这是一个凭借着头脑运作除了玩味读物中的一些字句之外不假任何外助以一己之力来提升自我的过程。\n\n\n因为一种是读得懂的东西另一种是必须要读的东西二者之间的界限通常是很模糊的。\n\n\n第二种意义是一个人试着读某样他一开始并不怎么了解的东西。这个东西的水平就是比阅读的人高上一截。这个作者想要表达的东西能增进阅读者的理解力。\n\n\n这里的“学习”指的是理解更多的事情而不是记住更多的资讯——和你已经知道的资讯在同一水平的资讯。\n\n\n在什么样的状况下我们会为了增进理解而阅读有两种状况第一是一开始时不相等的理解程度。在对一本书的理解力上作者一定要比读者来得“高杆”写书时一定要用可读的形式来传达他有而读者所无的洞见。其次阅读的人一定要把不相等的理解力克服到一定程度之内虽然不能说全盘了解但总是要达到与作者相当的程度。一旦达到相同的理解程度就完成了清楚的沟通。\n\n\n简单来说我们只能从比我们“更高杆”的人身上学习。我们一定要知道他们是谁如何跟他们学习。\n\n\n本书是关于阅读的艺术是为了增强理解力而写的。\n\n\n事实上任何一本书能增进理解或增加资讯时也就同时有了消遣的效果。\n\n\n阅读就是学习指导型的学习以及自我发现型的学习之间的差异\n\n\n为什么会发生与其他的事实有什么关联有什么类似的情况同类的差异在哪里等等。\n\n\n只有真正学习到的人才是主动的学习者。\n\n\n学生却必须自己能学习才行\n\n\n思考只是主动阅读的一部分。\n\n\n阅读的艺术包括了所有非辅助型自我发现学习的技巧敏锐的观察、灵敏可靠的记忆、想象的空间再者当然就是训练有素的分析、省思能力。\n\n\n因为倾听是从一位出现在你眼前的老师学习——一位活生生的老师——而阅读却是跟一位缺席的老师学习。\n\n\n如果你问一本书一个问题你就必须自己回答这个问题。\n\n\n如果我们打算继续学习与发现我们就要懂得如何让书本来教导我们。事实上这就是本书最主要的目的。\n\n\n阅读的规则是努力越多效果越好。\n\n\n因为我们大多数人在阅读时都经常是没有人在旁边帮助的。阅读就像是非辅助型的自我发现学习是跟着一位缺席的老师在学习。只有当我们知道如何去读时我们才可能真正读懂。\n\n\n种类是样样都不相同的而层次却是再高的层次也包含了较低层次的特性。\n\n\n阅读的层次是渐进的。\n\n\n书中写的却是我们不太熟悉的外国文字这样的问题就发生了。\n\n\n第四章我们还会详细讨论这个层次的阅读现在就不作进一步的说明了。我们想要强调的是大多数人即使是许多优秀的阅读者都忽略了检视阅读的价值。他们打开一本书从第一页开始读起孜孜不倦甚至连目录都不看一眼。因此他们在只需要粗浅翻阅一本书的\n\n\n分析阅读就是全盘的阅读、完整的阅读或是说优质的阅读——你能做到的最好的阅读方式。\n\n\n第一是美国在继续推行全民教育这就是说当然最少要做到全国没有文盲。\n\n\n总括而言要教育少数具有高度学习动机的孩子阅读通常他们的父母都是知识分子和教育一些不管动机有多微弱或家庭有多贫困的孩子阅读是完全不同的两码事——一百年前如此今天依然如此。\n\n\n基础阅读的第一个阶段——阅读准备阶段——相当于学前教育或幼稚园的学习经验。第二阶段——认字——相当于一年级学生典型的学习经验尽管相当多正常的孩子在某方面来说并非都很“典型”。\n\n\n一个人文素养优良的高中就算什么也没做也该培养出能达到分析阅读的读者。一个优秀的大学就算什么也没贡献也该培育出能进行主题阅读的读者。大学的文凭应该代表着一般大学毕业生的阅读水平不但能够阅读任何一\n\n\n我们的历史一直强调无限制的受教育机会是一个社会能提供给人民最有价值的服务——或说得正确一点只有当一个人的自我期许能力与需要受限制时教育机会才会受到限制。\n\n\n检视阅读一有系统的略读或粗读\n\n\n第一你并不知道自己想不想读这本书。你也不知道这本书是否值得做分析阅读。\n\n\n1先看书名页然后如果有序就先看序。\n\n\n2研究目录页\n\n\n3如果书中附有索引也要检阅一下\n\n\n4如果那是本包着书衣的新书不妨读一下出版者的介绍。\n\n\n完成这四个步骤你对一本书已经有足够的资讯让你判断是想要更仔细地读这本书还是根本不想读下去了。\n\n\n5从你对一本书的目录很概略甚至有点模糊的印象当中开始挑几个看来跟主题息息相关的篇章来看。\n\n\n6最后一步把书打开来东翻翻西翻翻念个一两段有时候连续读几页但不要太多。\n\n\n头一次面对一本难读的书的时候从头到尾先读完一遍碰到不懂的地方不要停下来查询或思索。\n\n\n阅读的速度\n\n\n所谓阅读速度理想上来说不只是要能读得快还要能用不同的速度来阅读——要知道什么时候用什么样的速度是恰当的。\n\n\n你可以自己做这样的训练将大拇指与食指、中指合并在一起用这个“指针”顺着一行一行的字移动下去速度要比你眼睛感觉的还要快一点。强迫自己的眼睛跟着手部的动作移动。一旦你的眼睛能跟着手移动时你就能读到那些字句了。继续练习下去继续增快手的动作等到你发觉以前你的速度已经可以比以前快两三倍了。\n\n\n在著名的第二段里的一些字句如“不可剥夺的”、“权利”、“自由”、“幸福”、“同意”、“正义的力量”值得再三玩味、推敲、沉思。\n\n\n这么说来速读的问题就出在理解力上。\n\n\n在阅读一本书的时候慢不该慢到不值得快不该快到有损于满足与理解。\n\n\n1整体来说这本书到底在谈些什么\n\n\n作者细部说了什么怎么说的\n\n\n这本书说得有道理吗是全部有道理还是部分有道理\n\n\n4这本书跟你有什么关系如果这本书给了你一些资讯你一定要问问这些资讯有什么意义。\n\n\n1画底线\n\n\n2在画底线处的栏外再加画一道线\n\n\n在空白处做星号或其他符号\n\n\n在空白处编号——作者的某个论点发展出一连串的重要陈述时可以做顺序编号。\n\n\n5在空白处记下其他的页码\n\n\n将关键字或句子圈出来\n\n\n7在书页的空白处做笔记\n\n\n你已经在书后的空白页做过这件事了\n\n\n第一这是什么样的一本书第二整本书在谈的是什么第三作者是借着怎样的整体架构来发展他的观点或陈述他对这个主题的理解\n\n\n男孩遇到女孩男孩失掉女孩男孩又得到女孩。这真的是每一个罗曼史的情节。认清这一点也就是要明白为什么所有的故事情节不过那几个的道理。同样的基本情节一位作者写出来的是好故事或坏故事端看他如何装点这副骨架。\n\n\n分析阅读的第一阶段找出一本书在谈些什么的四个规则1依照书本的种类与主题作分类。2用最简短的句子说出整本书在谈些什么。3按照顺序与关系列出全书的重要部分。将全书的纲要拟出来之后再将各个部分的纲要也一一列出。4找出作者在问的问题或作者想要解决的问题。\n\n\n语言并不是完美的传递知识的媒介\n\n\n当我们谈到“阅读”时可能是指1为娱乐而阅读2为获得资讯而阅读3为追求理解力而阅读。\n\n\n5诠释作者使用的关键字与作者达成共识。6从最重要的句子中抓出作者的重要主旨。7找出作者的论述重新架构这些论述的前因后果以明白作者的主张。8确定作者已经解决了哪些问题还有哪些是未解决的。在未解决的问题中确定哪些是作者认为自己无法解决的问题。\n\n\n人是情绪与偏见的动物\n\n\n第一要求读者先完整地了解一本书不要急着开始批评。第二恳请读者不要争强好辩或盲目反对。第三将知识上的不同意见看作是大体上可以解决的问题。\n\n\n这个规则再进一步的话就是要求读者要为自己不同的意见找到理论基础这样这个议题才不只是被说出来而且会解释清楚。只有这样才有希望解决这个问题。\n\n\n1你的知识不足uninformed2你的知识有错误misinformed3你不合逻辑——你的推论无法令人信服。4你的分析不够完整。\n\n\n如果你不能用相关证据显示作者是知识不足、知识有误或不合逻辑你就不能反对他。你不能像很多学生或其他人说的“你的前提都没有错推论也没问题但我就是不同意你的结论。”这时候你唯一能说的可能只是你“不喜欢”这个结论。你并不是在反对。你只在表达你的情绪或偏见。\n\n\n三、分析阅读的第三阶段像是沟通知识一样地评论一本书的规则A智慧礼节的一般规则9除非你已经完成大纲架构也能诠释整本书了否则不要轻易批评。在你说出“我读懂了!”之前不要说你同意、不同意或暂缓评论。10不要争强好胜非辩到底不可。11在说出评论之前你要能证明自己区别得出真正的知识与个人观点的不同。B批评观点的特别标准12证明作者的知识不足。13证明作者的知识错误。14证明作者不合逻辑。15证明作者的分析与理由是不完整的。注意关于最后这四点前三点是表示不同意见的准则如果你无法提出相关的佐证就必须同意作者的说法或至少一部分说法。你只能因为最后一点理由对这本书暂缓评论。\n\n\n许多伟大的作品不只是互相有关联而且在写作时还有特定的先后顺序这都是不该忽略的事。后人的作品总是受到前人的影响。如果你先读前一位的作品他可能会帮助你了解后人的作品。阅读彼此相关的书籍依照写作的时间顺序来读对你了解最后写的作品有很大帮助。这就是外在辅助阅读的基本常识与规则。\n\n\n人类的住所是什么”、“人类缺乏的是什么”、“人类何以为生\n\n\n知识的顺序是随着时代而变迁的。在过去所有相关的知识是以七种教育艺术来排列的——文法、修辞、逻辑三学科与算术、几何、天文、音乐四学科组合而成。\n\n\n就算一开始不太清楚也不要焦虑。事实上一开始本来就是不清楚的。故事就像我们的人生一样在生命中我们不可能期望了解每一件发生在我们身上的事或把一生全都看清楚。但是当我们回顾过去时我们便了解为什么了。所以读者在阅读小说时全部看完之后再回顾一下就会了解事件的关联与活动的前后顺序了。\n\n\n阅读历史的两个要点是第一对你感兴趣的事件或时期尽可能阅读一种以上的历史书。第二阅读历史时不只要关心在过去某个时间、地点真正发生了什么事还要读懂在任何时空之中尤其是现在人们为什么会有如此这般行动的原因。\n\n\n最重要的是在阅读当前事件的报导时要知道是谁在写这篇报导。这里所说的并不是要认识那位记者而是要知道他写作的心态是什么。\n\n\n1这个作者想要证明什么2他想要说服谁3他具有的特殊知识是什么4他使用的特殊语言是什么5他真的知道自己在说些什么吗\n\n\n这个警告就是读者要擦亮眼睛Caveat lector\n\n\n浓缩的唯一功能就是激励我们去阅读原著。\n\n\n任何自然科学的分支都要包含三个部分在这个科学主题中的连续事实呈现这些事实的想法以及表达这些事实的语言……因为想法是由语言来保留与沟通的如果我们没法改进科学的本身就没法促进科学语言的进步。换个角度来看也一样我们不可能只改进科学的语言或术语却不改进科学的本身。\n\n\n数学其实是一种语言我们可以像学习自己的语言一样学习它。在学习自己的语言时我们要学两次第一次是学习如何说话第二次是学习如何阅读。幸运的是数学只需要学一次因为它完全是书写的语言。\n\n\n数学是如何优美、如何满足智力的一门学问。如果任何人愿意费点力气来读数学要领略数学之美永远不嫌晚。你可以从欧几里得开始他的《几何原理》是所有这类作品中最清晰也最优美的作品。\n\n\n第一你至少可以把一些比你想象的基础程度的数学读得更明白。\n\n\n如果你阅读数学书的企图是要了解数学本身当然你要读数学从头读到尾——手上还要拿支笔这会比阅读任何其他的书还需要在书页空白处写些笔记。但是你的企图可能并非如此而是只想读一本有数学在内的科学书这样跳着略读反而是比较聪明的。\n\n\n最伟大的哲学家所提出来的深刻问题正是孩子们所提出的问题。能够保留孩子看世界的眼光又能成熟地了解到保留这些问题的意义确实是非常稀有的能力\n\n\n存在与不存在的区别在哪里所有存在事物的共同点是什么每一种存在事物的特质是什么事物存在的方法是否各有不同——各有不同的存在形式是否某些事物只存在心中或只为了心灵而存在而存在于心灵之外的其他事物是否都为我们所知或是否可知是否所有存在的事物都是具体的或是在具体物质之外仍然存在着某些事物是否所有的事都会改变还是有什么事是永恒不变的是否任何事物都有存在的必要还是我们该说目前存在的事物不见得从来都存在是否可能存在的领域要大于实际存在的领域\n\n\n哲学家提出这样的问题就是从注意事物的存在到注意事物的转变并试着将存在与改变的关系建立起来。\n\n\n我们所讨论的两种问题区分出两种主要不同的哲学领域。第一组关于存在与变化的问题与这个世界上存在与发生的事有关。这类问题在哲学领域中属于理论或思辨型的部分。第二组关于善与恶好与坏的问题和我们应该做或探寻的事有关我们称这是隶属于哲学中实用的部分更正确来说该是规范normative的哲学。\n\n\n要回答哲学的问题除了思考以外别无他法。\n\n\n这个领悟就是幸福是善的完整whole of the good而不是最高的highest因为如果是那样那就只有一种善了。\n\n\n假装相信一些其实你并不相信的事是很好的心智训练。当你越清楚自己的偏见时你就越不会误判别人的偏见了。\n\n\n哲学家在面对问题时除了思考以外什么也不能做。读者在面对一本哲学书时除了阅读以外什么也不能做——那也就是说要运用你的思考。\n\n\n的确哲学问题的最大特色就在每个人必须为自己回答这些问题。采用别人的观点并没有解决这些问题只是在逃避问题而已。\n\n\n经书的范围不只这些明显的例子。任何一个机构——教会、政党或社会——在其他的功能之外如果1有教育的功能2有一套要教育的课本a body of doctrine to teach3有一群虔诚又顺服的成员那么属于这类组织的成员在阅读的时候都会必恭必敬。他们不会——也不能——质疑这些对他们而言就是“经书”的书籍的权威与正确的阅读方法。信仰使得这些信徒根本不会发现“神圣的”经书中的错误更别提要找出其中道理不通的地方。\n\n\n只有在报纸头版出现简短的“谁——发生了什么事——为什么发生——何时何地发生”新闻提要才是以事实为主。一般来说记者都会将事实加上诠释、评论、分析再成为新闻报导。这些诠释与评论都是来自社会科学的观念与术语。\n\n\n爱只是一种占有的欲望通常是性的欲望也就是说爱只是一种所有动物在面对异性时会产生的吸引力。但是你也会发现另一个作者所谈的爱是不包含占有的欲望而是一种慈善。如果说占有的欲望总是暗示着想要为自己追求好东西而慈善却暗示着要为别人追求好东西。那么占有的欲望与慈善之间是否有相通之处\n\n笔记\n\n简单来说我们只能从比我们“更高杆”的人身上学习。我们一定要知道他们是谁如何跟他们学习。\n\n💭 向上阅读\n\n在阅读一本书的时候慢不该慢到不值得快不该快到有损于满足与理解。\n\n💭 就如同去动物园里游玩,看见孔雀就可以多停留,遇见嘈杂的人群就赶忙走开啦\n\n一个作者在写作时可能会用不同的字来说明同样的主旨。读者如果不能经由文字看出一个句子的主旨就容易将不同的句子看作是在说明不同的主旨。这就好像一个人不知道2+2=4跟4-2=2虽然是不同的算式说明的却是同一个算术关系——这个关系就是四是二的双倍或二是四的一半。\n你可以下结论说这个人其实根本不懂这个问题。同样的结论也可以落在你身上或任何一个无法分辨出用许多相似句子说明同一个主旨的人或是当你要他说出一个句子的主旨时他却无法用自己的意思作出相似的说明。\n\n💭 横看成岭侧成峰,远近高低各不同\n书评\n点评"},"Personal/Book/教育学习/赖世雄的英语学习法":{"title":"赖世雄的英语学习法","links":[],"tags":["阅读/教育学习","阅读/笔记"],"content":"简介\n\n书名《赖世雄的英语学习法》\n作者 赖世雄\n分类 教育学习-外语\nISBN9787213085802\n出版社浙江人民出版社\n\n概述\n《赖世雄的英语学习法》是一本对英语学习者切实有效的方法指南。自学成才的赖世雄老师怀着帮助英语学习者少走弯路的初衷在本书里详细讲解了自己在英语学习的每个阶段所采用的方法。从初学时如何通过反复模仿音标来塑造自己纯正的口音、如何通过自我对话的方式来增强讲英语的密度到小有所成时如何通过大量阅读英文文章来大幅增加自己的词汇量如何学习语法、划分句子结构从而为自己日后的写作打下坚实基础再到英语学习的高级阶段中如何练习英汉互译做口译练习的相关经验……凡此种种赖世雄老师都结合自己的经验逐一进行了解释并且细致地举出了在英语学习的各个阶段中学习者可能采用的错误方法。\n划线\n\n善用零星时间\n\n\nDont bite off more than you can chew.\n\n\n别咬下超过你能嚼得动的分量\n\n\n接下来我不是用背的方式去把这则会话背出来而是一人扮演两个角色把会话的内容自导自演进行实际的演练也就是一遍又一遍地把会话“演”出来。\n\n\n1善用零星时间2少就是多慢就是快3持之以恒永不放弃\n\n\n与“读”。我要说的是看到英语文章就要开口念出声音来而不是只默读也不是马上查词典。我是一小段一小段地攻克新闻文章的而不是一次把一整篇念完这就是我所说的“少就是多”的原则。我再强调一次我这里讲的阅读是“阅”与“读”。也就是说当你的眼睛“看”到英语文章时你的嘴巴就必须要同时把英文句子“念”\n\n\n我则是只要有零星时间就拿起《英文中国邮报》边看新闻文章news stories边念出声来。这么一来我的嘴巴一天到晚讲的都是英语我相信这会比在培训班里讲英语的机会多得多。Luther Burbank卢瑟·伯班克曾说过“Time cannot be added to a persons lifebut it can be made more valuable by avoiding waste.”(时间不能加进一个人的生命里,但是珍惜光阴却可使生命变得更有价值。)\n\n\nTo err is humanto forgive divine.”翻译成中文是:“人非圣贤,孰能无过。\n\n笔记\n书评\n点评"},"Personal/Book/文学/凤凰项目一个IT运维的传奇故事修订版":{"title":"凤凰项目一个IT运维的传奇故事修订版","links":[],"tags":["阅读/文学-散文杂著","阅读/笔记"],"content":"简介\n\n书名《凤凰项目一个IT运维的传奇故事修订版》\n作者 吉恩·金 凯文·贝尔 乔治·斯帕福德\n分类 文学-散文杂著\nISBN9787115516763\n出版社人民邮电出版社\n\n概述\n本书讲述了一位IT经理临危受命在未来董事的帮助和自己“三步工作法”理念的支撑下最终挽救了一家具有悠久历史的汽车配件制造商的故事。小说揭示了管理现代IT组织与管理传统工厂的共通之处让读者不仅能对如何管理IT组织心领神会更重要的是将以完全不同于以往的视角来看待自己的工作环境。\n划线\n\n在当年我还想着成为IT人的学生时代阅读各种IT类书籍是一件苦差需要在月明风清的晚上备好香茶点心沐浴更衣鼓足勇气才能翻开书本而且预想的彻夜苦读经常以一夜好梦而告终——书还翻在一开始的几页似乎字里行间都散发着不可思议的催眠魔力。\n\n\n信息技术与核心业务的“黏性”正成为公司竞争力至关重要的构成因素。\n\n\n所以如果你的老板还觉得IT运维部就是“修电脑的”那么给他/她这本书,或者趁早换一个老板。\n\n\n过去十年间CIO每两年肯定会轮换一次就像钟表一样有规律。他们在位的时间仅够理解各种首字母缩写的含义知道卫生间在哪里推行一堆计划和倡议然后梦想破灭再然后走人。\n\n\n你以为我们会把那样的奖励随便颁给什么人吗”他认真地说“那是一个重要的项目。为了做成那个并购我们必须做好那个项目。你和你的团队干得好极了\n\n\n“这我相信”史蒂夫笑起来“我也在军队里待过八年比我的义务服役期略长一点。不过我不介意。我只有参加预备役军官训练营才能付得起大学学费而且他们待我不错。”\n\n\n绝地武士控心术”\n\n\n我很难从他们提出的那些不依不饶、歇斯底里、自以为是的要求中找出与切实提高环境防御有什么关联。\n\n\n导致周二的SAN事故和工资核算故障之类的事件了。一开始只是个中等规模的工资核算故障最后像滚雪球一样演变为非常严重的乌龙SAN事故。\n\n\n但是现在大家显然都知道不应该根据第一个工作站的效率来安排工作而是根据瓶颈资源所能完成工作的速度来安排工作。”\n\n\n作为IT运维部的副总裁你的工作是确保形成一条迅速、可预测、持续不断的计划内工作流从而向业务部门交付工作价值同时尽可能降低计划外工作的影响和破坏那样你才能提供稳定的、可预期的、安全的IT服务。\n\n\n第一步帮助我们理解在工作从开发部移向IT运维部时该如何建立快速工作流因为那就是业务部门与客户之间的衔接。第二步告诉我们如何缩短及放大反馈环路从而在源头上解决质量问题避免返工。第三步告诉我们如何建立一种文化既能鼓励探索、从失败中吸取教训又能理解反复实践是精通工作的先决条件。\n\n\n在白板上可以清楚地看到将近一半变更都安排在周五剩下的变更又有一半安排在周四其他的零零散散地排在上半周。\n\n\n“我不是说周五碰巧有173个变更不好我担心的是变更冲突以及可用资源矛盾。周五也是部署凤凰的日子。”\n\n\n“好极了。”帕蒂说“每解决一个问题我们的知识库里就会多一篇关于如何解决某个疑难杂症的文章而且能够实施修复的人会越来越多。”\n\n\n我担任CEO以来一直都听到这样的投诉。IT拖累了每一项重要举措。与此同时竞争对手们却把我们远远甩在身后让我们备受羞辱。该死的我们做屁大点事儿都有IT的人在那里碍手碍脚\n\n\n上周参加了一个会议那个项目已经积压了很多待处理功能产品经理们却还在讨论三年后哪个功能会更有用我们连有效制定一年计划都做不到更别说三年了都有什么用\n\n\n尽管无法请出一整天的假我还是带佩奇出去吃了早餐。在我每天两眼一睁就投入工作的那段时间里是她独自一人撑起了这个家。\n\n\n海军陆战队里的一个同僚曾经告诉我他对自己的定位是养家者家长伴侣然后是突发事件的应变者。以此为序。\n\n\n“高德拉特教育我们在大多数工厂里总有那么一小部分资源不论是人、机器还是原材料决定了整个系统的产出。我们称之为约束点或者瓶颈。任何一项团队工作都是如此。\n\n\n在你建立起一个可信赖的系统用以管理通向约束点的工作流之前约束点经常是被闲置的也就是说约束点可能在很大程度上未被充分利用。”“那就意味着你没有向业务部门交付全部的可用资源。也可能意味着你没有还清技术债务因此随着时间的推移你遇到的问题和计划外工作量会不断增加。”他说。\n\n\n你现在听上去和吉米一样对你无法控制的事情怨天尤人。”他叹了口气“当然是凤凰导致了所有的问题。在其位谋其政\n\n\n我用以前训练出来的方法应付这么气急败坏的人。我冷静地重申了之前所说的话“如我所言我今天早些时候和迪克谈过了。他已经把所有利害关系都强调得很清楚了。我们已经启动了新的事故处理流程而且我们正在有条不紊地调查可能造成故障的原因。他们正在做我要求他们做的事因为面对这么多不确定因素妄下结论实在太容易把事情弄得更糟了。”\n\n\n“好吧你走后我们彻底搞砸了。”韦斯说听上去十分窘迫这证实了我最担心的事情“史蒂夫坚持要我们把所有工程师都叫过来包括布伦特。他说他要每个人都有紧迫感并且要手不离键盘不能有闲人。显然我们没能有效整合起每个人的力量而且……”\n\n\n我叹了口气。我永远不会告诉他们我和史蒂夫之间那些沮丧荒唐的会面。那是他和我之间的事。\n\n\n在过去一个月里我学到了两件事。第一件事IT很重要。IT不是一个可以轻易委托外包的部门。公司的每一项重大活动都有IT的参与而且IT对日常运作的方方面面都起着关键作用。”\n\n\n一个伟大的团队并不代表他们拥有最聪明的人。使团队变得伟大的因素是每个人都互相信任。当那种神奇的动力出现就会让整个团队充满力量。\n\n\n史蒂夫继续说“我最喜欢的一本关于团队动力学的书是帕特里克·兰西奥尼的著作《团队发展的五大障碍》。他在书中写道想要在团队中达成相互信任你需要展现出自己脆弱的一面。所以我要告诉你们一些关于我个人的事情以及是什么让我有动力走到今天。\n\n\n我们给你们付工资是为了让你们思考而不只是执行”\n\n\n如果你或者其他任何人知道某个项目会失败我需要你们说出来。而且我需要你们的观点有数据支撑。就像那个车间协调员给你们看的数据我就需要那样的数据那样我们就能明白缘由。对不起比尔我很看好你但只根据直觉说是不够的。”\n\n\n因为你完全不知道你们的实际工作能力有多少。你就像个一直在开空头支票的家伙因为你不知道自己有多少钱而且从不费心打开邮件。”\n\n\n“每个人都知道在生产中半成品增加交期性能就会下降。”\n\n\n大幅度地做了个手势第二工作法的一个关键部分是让等待时间可视化那样就能知道你的工作何时在某人那里排了几天的队或者还有更糟的情况工作必须往后退因为没有完成所有的部件或者需要返工。”\n\n\n无极限零部件公司最大的风险是停业破产。而你似乎一心想用你那些不周全的考虑和无关紧要的技术细节让它加速倒闭。怪不得你会被边缘化其他人至少都在想方设法帮助公司存活下去。\n\n\n和应用程序然后安放到机架上。接着我们会确认它安装完毕。每一个步骤通常都是由不同的人完成的。也许每个步骤就好比是一个工作中心每个工作中心都有自己的机器、方法、人员和测评。”\n\n\n别逗我了伙计们。”韦斯说“首先我们的工作不是重复性劳动。其次和那些只是安装部件或者拧螺丝的人不同从事我们的工作需要非常多的知识。我们招聘的都是头脑灵活、经验丰富的人。相信我我们没法像制造部门那样把各项工作标准化。”我考虑着韦斯的观点“如果是在上一周我想我会赞同你的观点韦斯。但上周我用了十五分钟时间考察了生产车间的一个总装工作中心。我被那里所进行的一切征服了。老实说我几乎跟不上它。尽管他们已经尽可能地让每件工作都可复制、可重复但是为了达成每日生产目标他们仍然担负着很大的应变处置和故障处理的工作量。他们做的事比拧螺丝多得多。他们用点点滴滴的经验和智慧每一天都在谱写着传奇。”\n\n\n我不管每个人觉得自己的项目有多重要。我们要知道的是项目能否提高我们在约束点上的工作能力这个约束点指的还是布伦特。除非一个项目能够减少他的工作量或者可以让其他人接手否则的话我们也许就不应该开展这个项目。另一方面如果一个项目并不需要布伦特参与那我们就没有理由不开展它。”\n\n\n没错。他们每个人都拿到了。最早拿到电脑的几个人遇到了一些配置错误或者缺了些东西。我们已经在工作指南里改正了这两天我们的电脑正确送达率好像已经达到100%了。”\n\n\n首先布伦特的任务原来远不止是一个任务。其次我们发现那是涉及多个人员的多个任务而相关人员都有自己的紧急工作要做。每一次工作交接都是在损失我们的时间。按照这样的速度如果没有大规模的干预QA就得等上好几周才能拿到需要的东西。”\n\n\n上次我们需要一个防火墙变更约翰的团队几乎花了一个月时间才弄好。一个30秒的变更花了整整四个星期”\n\n\n如果我们能够把所有的经常性部署工作标准化最终就能达到产品配置的一致性。我们现在的基础架构过于多样化就像雪花一样没有两片重样的。布伦特之所以会成为布伦特是因为我们允许他建立起只有他能理解的基础架构。我们不能再让这样的事情发生。\n\n\n告知真相是一种爱的表现。隐瞒真相是一种恨的表现。甚至更糟是一种冷漠的表现。”\n\n\n“好吧这些年里我大部分时间都在负责中型机工作组你不太参与这方面的事。”我冷静地解释“我们在网上找到了自己的安全指南。当我们和你沟通的时候你只想把一大堆工作压给我。看我很在乎安全性我们一直在查找系统和数据的风险但我们总是忙于先解决最紧急的事情勉强维持生存。而我的新使命就是要帮助公司生存下去\n\n\n我把约翰的钱包还给他又掏出自己的钱包付了钱。我帮约翰站起身把他塞进出租车又确认了一遍钱包和钥匙都在他的口袋里。我不想让约翰和出租车司机打交道于是把车钱也付了。\n\n\n再没什么比吐槽IT更能让人团结一致的了。\n\n\n理想状态下工作流应该只朝一个方向移动向前。一旦看到工作向后移动我就会想到浪费。也许是由于不合格品、缺少规范或者返工……无论是哪一种情况我们都得开展修复工作。\n\n\n我们把四个工作中心合而为一排除了三十多个容易出错的人工步骤使整个工作周期完全实现了自动化形成了单一工作流并且去掉了所有的准备时间。生产能力一飞冲天。”\n\n\n你们应该创建亨伯尔和法利所说的部署管道。那是从代码签入到投产的整个价值流。那不是一种技术而是生产。你们应该对所有东西都进行版本控制。所有东西不只是代码而是创建环境所需的每一样东西。然后你们应该把整个环境创建流程自动化。\n\n\n令人惊讶的是克里斯的反应最为激烈。“什么我们究竟为什么要一天开展十个部署我们的部署冲刺周期是三个星期。我们拿不出那么多东西来一天部署10次”\n\n\n返工和准备时间过长问题的另一个显著来源是代码打包流程在此阶段IT运维部对经过开发部检查的内容进行版本控制然后生成部署包。尽管克里斯和他的团队尽可能地记录代码和配置总还有东西会遗漏这些东西只有在部署之后代码无法在环境中运行时才会被发现\n\n\n“这看起来很有希望。如果能把环境标准化并把这些环境投入开发部、QA和IT运维部的日常使用我们就能消除大部分在部署流程中因差异而导致的悲剧。”\n\n\n我对威廉和布伦特说“好吧伙计们你们有魔法棒了。你们要身先士卒。告诉我你们会怎样设计生产线让工作永远不会往回走让工作流快速高效地向前移动”他们俩都一脸茫然地看着我我有些恼火地说“你们有一根魔法棒用它啊”“这根魔法棒有多强”威廉问。我重复了之前对玛姬说的话“这是一根非常强大的魔法棒。它能做任何事。”\n\n\n从很多方面来看开发人员简直就是我所青睐的性情的对立面。我喜欢创造并遵守流程的人喜欢重视严谨与纪律的人。而这些人偏偏喜欢心血来潮、异想天开跳开流程办事。\n\n\n“我们不需要任何新硬件。”这个开发人员回答“我们投入了很多精力来建立我们能够部署的计算机图像。为什么不把它们发送到云上在我们需要的时候可以运转成百上千个计算实例完成后再销毁它们成本只是我们所用的计算时间。”\n\n\n结果大放异彩超过20%的受访者访问了我们的网站超过6%的人购买了商品。这个转化率高得令人难以置信,可能比我们之前开展过的所有活动都要高出五倍。\n\n\n玛姬很快同意了但是开发人员仍然花了两个小时进行变更和部署。现在可以通过一个配置设定来禁用这个功能因此下一次我们就能在几分钟内弄好而不需要一整套代码上线了。这才是IT运维友好型的研发设计嘛在生产中管理代码变得越来越容易了。\n\n\n独角兽团队简直棒极了。他们已经从每两周开展一次部署过渡到每周开展一次部署而且我们正在尝试每天开展部署。由于批量规模缩小了很多我们可以很快做出小型变更。我们正在随时开展A/B测试。简而言之我们从未这样迅速地响应市场而且我相信我们一定会大有可为。”\n\n\n从“库存型生产”转变为“订单型生产”\n\n\n。根据“改善形”这让我不会觉得自己完全无用武之地。让我尤为骄傲的是整整一个月来我的团队都达到了把15%的时间用于预防性基础架构项目的目标,并且体现出了成果。\n\n\n我们需要建立起一种文化强调勇于冒险以及从失败中汲取教训的价值观并强调通过反复实践以致炉火纯青的必要性。\n\n\n我不希望张贴宣传质量与安全的海报。我希望我们的改进能够体现在日常工作的所需所用上应用到日常工作之中。\n\n\n“你帮助我认识到IT不只是一个部门。相反它就像电力一样无处不在。IT是一种技能就像能读会算一样。\n\n\n希望每一个雇员都多少掌握这些技能。理解技术能够做什么、不能做什么已经成为这家公司里每个部门必须具备的一种核心竞争力。要是业务经理领导了一个不具备这种技能的团队或项目他们就会失败。\n\n\n要是你能做到我就准备培养你。我想把你放上一个两年计划的快车道。你将在销售和市场营销部门轮岗管理一家工厂积累国际经验维护关键供应商的客户关系以及管理供应链。相信我这可不像度假那么轻松。你需要帮助很多很多帮助。埃瑞克很好心地答应会指导你因为我们俩都相信这将会是你做过的最困难的事。\n\n\n每一个称职的COO都会是从IT部门出来的。任何尚未精通IT系统就负责管理公司运行的COO都只会是金玉其外的傀儡需要依靠别人来开展工作。\n\n\n史蒂夫就像是知道我在想什么一样他说“在好几个月之前埃瑞克和我第一次见面的时候他说IT部门和业务部门之间的关系就像是一场不协调的婚姻双方都感到无能为力并且被对方所挟持。我对此思考了好几个月终于想清楚了一些事。”\n\n\n所谓一场不协调的婚姻是假定业务部门和IT部门是两个分离的实体。IT要么融入到公司的日常运行之中要么融入到公司的业务内容之中。瞧就是这样。没有矛盾没有婚姻也许连IT部门也没有\n\n\n时的救世主固然好但普世的圣经则更有用。”\n\n\nDevOps的很多做法都是反直觉的与常规认知相悖甚至有争议。\n\n\n鲁兹先生分析了布伦特的两面性独食者和分享者。他写道“我也碰到过一些非常聪明的人他们秉持这种错误理念即只有他们自己知道解决方案才能永葆职位。这些人就是知识独食者。这个观念不对。没有人无可替代无论这人有多优秀。当然可能特殊情况下解决问题需要的时间更长些但缺了谁地球都能转。”\n\n\nDevOps原则和模式就是通过整合企业文化、企业架构和技术实践让下降式螺旋变成上升式螺旋。\n\n\n以前的经济环境里商业通过移动原子创造价值如今则通过移动比特创造价值。\n\n\n正如爱德华·戴明博士的名句所言“没人会强迫你学习……学习也并非生存必需。”技术的美好年代在等着我们而非已经走远。进入技术领域永远都不晚成为终身学习者也永远都不晚。\n\n\n任何一个领域或学科想要取得进步和成熟就需要认真反思它的起源在反思中寻求不同的观点并把这些不同观点的来龙去脉思考清楚这对预见未来发展是非常有帮助的。\n\n\nDevOps实践可以与ITIL流程兼容。然而为了支持DevOps所追求的更短的发布周期和更频繁的部署ITIL流程的许多方面需要完全自动化以解决配置和发布管理流程相关的许多问题例如保持配置管理数据库和最终软件库是最新的。由于DevOps需要在服务事件发生时进行快速的定位和恢复因此这些其实还是和ITIL的服务设计、事件和问题管理方面的原则相一致。\n\n\n在这个竞争优势需要被快速验证和持续实验的时代那些还不能应用DevOps实践的公司注定会在市场上败给敏捷的竞争对手并可能会倒闭和当年那些没有采取精益原则和实践的制造厂的后果类似。\n\n\n大多数公司都不能在几分钟或几小时内完成变更需要的所有部署往往需要几周甚至几个月的时间。他们更不可能每天在生产环境中做到成百上千次的部署而是在以月甚至以季度为单位进行部署。对他们而言生产环境的部署并不是日常工作因此服务中断和各种事故总是与部署如影随形“填坑侠”们总是前赴后继。\n\n\n技术债务是指我们当前所做出的决定会导致一些问题而这些问题随着时间的推移会越来越难解决未来可采取的措施也越来越少。即使我们审慎地承担技术债务也依然会产生利息。\n\n\n第一部曲开始于IT运维我们的目标是让应用程序和基础设施持续运行以便公司向客户交付价值。我们日常工作中的很多问题源于应用程序和基础设施过于复杂、异常脆弱、文档不完备。这就是我们背负的技术债务这就是我们每天所处的工作环境。我们总是承诺一有时间我们一定会处理这个烂摊子但是这个时刻永远都不会到来。\n\n\n这样的背景下我们进入了第三部曲也就是最后一部曲。在这里所有事情都变得更加困难所有人都越来越忙工作所消耗的时间越来越多沟通变得更加缓慢工作积压得越来越多。我们的工作耦合得更加紧密即使是很小的行动也会导致较大的事故我们更加害怕和拒绝做出变更。工作需要更多的沟通、协调和审批团队必须等待更长的时间等待相关的工作完成我们的工作质量持续恶化。车轮开始嘎嘎作响地缓慢移动要想使之继续转动就需要付出\n\n\n许多心理学家认为创建一个让人感觉无能为力的系统是我们能对人类同胞做的最具破坏性的一件事——我们剥夺了他人控制自己成果的能力甚至营造了一种文化让人们因为害怕遭受惩罚、失败或危及生存而不敢做正确的事。这创造了“习得性无助”的环境人们变得不愿或无法采取行动来避免未来遇到同样的问题。\n\n\n想要让新功能生效我们只需要改变一个功能开关或者配置项即可而不再需要经历数天或者数周的辛苦工作。这个小变更使新功能对更大规模的客户群可见一旦出现错误就会自动地回滚。因此发布新功能变得可控、可预测、可逆且压力也小了。\n\n\n。我们的团队文化体现了高度的信任与合作而不是指责\n\n\n人们会因为冒险而获得回报。他们可以无所畏惧地讨论问题而不是把问题隐藏起来或者往后拖延。毕竟我们只有先认识到了问题才能解决问题。\n\n\n而且因为所有人都需要对自己的工作质量负完全的责任所以每个人在日常的工作中都创建自动化测试并且使用同行评审的方式来保证在问题影响到客户之前就解决它。与从管理层向下授权审批的方式相反上述过程降低了风险让我们能快速、可靠、安全地交付价值甚至可以在挑剔的评审人员面前证明我们拥有一个高效的内部控制系统。\n\n\n因为注重质量所以我们甚至会故意在生产环境中注入故障从而了解系统是怎样以预期方式发生故障的。\n\n\n❏ 吞吐量指标;❏ 代码和变更部署次数频繁30倍❏ 代码和变更部署前置时间快200倍❏ 可靠性指标;❏ 生产环境部署变更成功率高60倍❏ 平均服务恢复时间快168倍❏ 组织性能指标;❏ 生产力、市场份额以及营业目标大约2倍以上❏ 市值增长3年内高出50%)。\n\n\n当我们增加开发人员的数量时由于沟通、集成以及测试开销单个开发人员的生产力通常会显著下降。弗雷德里克·布鲁克斯在其著名的《人月神话》一书中强调过这一点。他解释说当项目延迟时增加更多的开发人员不仅降低了单个开发人员的生产力而且也降低了整体的生产力。\n\n\n“三步工作法”的原则流动、反馈和持续学习与实验。\n\n\nDevOps基于精益、约束理论、丰田生产系统、柔性工程、学习型组织、安全文化、人员优化因素等知识体系并参考了高信任管理文化、服务型领导、组织变动管理等方法论。\n\n\n在敏捷宣言中一个重要的原则是“频繁地交付可工作的软件交付周期可以是数星期也可以是数月推荐更短的周期”并强调使用小批量任务进行增量发布而非大规模的作业和瀑布流程的发布。同时强调建立自组织的小团队让成员在高度信任的环境中愉悦地工作。\n\n\n因为前置时间是客户能够体验到的时间所以我们把重点放在缩短前置时间而不是处理时间上。不过处理时间与前置时间的比率是十分重要的效率指标为了实现快速的流动并缩短前置时间必须缩短工作在队列中的等待时间。\n\n\n但是技术工作者很容易被打断因为对所有人而言这个中断的后果似乎是不可见的即便它对生产效率的影响比制造业更甚。例如将一个工程师同时分配到多个项目里他不得不在多个任务、认知规则和目标之间来回切换付出重新进入角色的成本。\n\n\n通过限制在制品数还能更容易地发现工作中的阻碍。[插图]例如,当限制在制品时,可能会发现居然没什么工作可干的,因为要等待其他人。虽然进行一项新工作(即“干点什么总比什么都不干强”)可能很诱人,但此时更好的做法是查明导致等待的原因,并协助解决那个等待的问题。实际上,糟糕的多任务处理发生的原因,通常是同时给一个人分配多个项目,造成了很多优先级冲突问题。\n\n\n一项工作在团队之间交接时需要大量的沟通——请求、委派、通知、协调而且经常需要排优先级、调度、消除冲突、测试和验证。这些工作可能还需要使用不同的工单系统或项目管理系统编写技术规范文档用会议、电子邮件或电话的形式进行沟通可能还涉及文件共享服务器、FTP服务器和Wiki页面的使用。\n\n\n例如在瀑布型软件项目中代码的开发可能花上一整年在开始测试之前甚至在向客户发布软件前我们得不到任何质量反馈。在反馈稀少且滞后的情况下工作结果是很难达到预期的。相反我们的目标应该是在技术价值流的每个阶段包括产品管理、开发、QA、信息安全和运维在所有工作执行的过程中建立快速的反馈和前馈回路。这包括创建自动化的构建、集成和测试过程以便尽早检测出那些可能导致缺陷的代码变更。\n\n\n斯皮尔博士认为群策群力的目的是遏制住问题防止蔓延然后定位和处理问题避免复发。他说“这样做可以让所有参与者都得到更深入的知识理解如何管理系统把无法规避的、早期的无知阶段变成学习的过程。\n\n\n这就是休哈特提出的循环即PDCA环——计划Plan、实施Do、检查Check、改进Act后来由爱德华兹·戴明推广并得到了迅猛发展”。\n\n\n触发了安灯绳时我们就聚集在一起解决问题停止开展任何新工作直到问题解决。[插图]这给价值流中的每个人提供了快速反馈(特别是那个导致系统故障的人),让我们能够快速地隔离和定位问题,避免出现更复杂的状况,导致问题的因果关系变得模糊。\n\n\n尽可能多用自动化方式执行通常由QA和信息安全人员来进行的质量检查\n\n\n要在问题发生时识别问题群策群力解决问题并构建新的知识在源头控制质量并且不断地为下游工作中心做优化。\n\n\n第一步建立了从左到右的工作流第二步建立了从右到左的快速、持续的反馈第三步要建立持续学习与实验的文化。\n\n\n工人犯了错就会受到惩罚那些提出建议或指出问题的工人则会被认为是告密者或管闲事的人。当发生了上述情况时领导层会故意压制甚至进行惩罚这导致了质量和安全问题的进一步恶化\n\n\n4.3 把局部发现转化为全局优化\n\n\n一旦在局部范围内取得了成果就应当把它分享给组织里的其他人让更多的人从中获益\n\n\n这样带来的结果是在任何一组新船员出海时他们都能迅速地从集体长期积累的智慧中获得成长。\n\n\n在技术价值流中我们也应该通过类似的机制建立全局知识库。例如把所有事故报告转化成可搜索的知识库让有需要的团队能更加方便地使用它去解决类似问题同时建立起组织级的共享源代码库让所有人可以方便地使用整个组织的代码、库和配置。这些机制有助于把个人的专业知识转化为服务更多成员的集体智慧。\n\n\n另外还可以通过演习的方式来预演大规模故障比如关闭某个数据中心。或者在生产环境中注入大规模故障如Netflix著名的“捣乱猴”它会随机杀死生产环境中的进程和服务器来验证系统的可靠性是否达到了预期。\n\n\n领导者通过“做出所有正确的决定”来领导团队。\n\n\n领导者可以使用下列问题来帮助和辅导实验者。❏ 上一步做了什么?发生了什么?❏ 你从中学到了什么?❏ 现状如何?❏ 下一个目标条件是什么?❏ 当前工作有什么阻碍?❏ 下一步做什么?❏ 期望的结果是什么?❏ 什么时候能进行复查?\n\n\n三步工作法的第三步原则实现了学习型组织实现了职能部门之间的高度信任和跨部门合作接受了“复杂系统中总会发生故障”的事实并鼓励谈论任何问题以建立一个安全的工作系统。它还要求将日常工作的改进制度化把局部成果转化为可供整个组织全局使用和学习的知识以及不断向日常工作中注入张力\n\n\n参与者所面临的游戏复杂性和工作量会逐轮递增。每一轮游戏结束后教练都将帮助参与者“回顾”上一轮发生了什么参与者做了什么参与者从中学到了什么“思考”哪些可以做得更好或者采用其他方式以及“决策”下一轮游戏应该如何做。只有这样参与者才能够学习到如何持续不断地提升他们的业绩和工作能力从而在面对更复杂的工作环境和更大工作量的情况下仍然能够游刃有余。\n\n\n产品负责人不应该只关注具有创新性的产品和功能还需重视维护工作和移除技术债务等优先级。\n\n\n我从八年前就开始尝试用沙盘去进行培训教学在教学过程中我最大的感触是用沙盘教学能给学员带来无以伦比的感受这种感受很可能会颠覆学员顽固的思维、接受我们的理念。\n\n\n国际最佳实践管理联盟源于欧洲是由欧洲最佳实践联学会携手国际知名出版机构、资格认证机构、咨询机构和行业专家共同发起的一家推广国际最佳实践管理体系和框架标准的非营利性组织\n\n笔记\n\n搞死你的不是前期投入而是后台的运行和维护。”\n\n💭 任何事物都必须存在生命周期\n\nDevOps是把精益原则应用到技术价值流中的结果并探讨DevOps的三步工作法流动、反馈以及持续学习与实验。\n\n💭 正反馈\n书评\n点评"},"Personal/Book/文学/老舍谈写作":{"title":"老舍谈写作","links":[],"tags":["阅读/文学-文学鉴赏","阅读/笔记"],"content":"简介\n\n书名《老舍谈写作》\n作者 老舍\n分类 文学-文学鉴赏\nISBN9787550032262\n出版社百花洲文艺出版社\n\n概述\n老舍是中国现代著名作家和语言大师著有《骆驼祥子》《四世同堂》《茶馆》等颇具分量、雅俗共赏的经典作品也留下了丰富的文学理论普及读物如《和工人同志们谈写作》《老牛破车》《写与读》等。《老舍谈写作》精选其关于写作的论述从写作的基本原则、写与读的关系语言的运用、描写的技巧、结构的方法等方面深入浅出地阐述“如何写作”这个主题。对于初学写作或希望在写作方面有所进益的读者来说有很强的指导性和可操作性。\n划线\n\n我们从一篇作品里可以看出作家怎样运用文字语言怎样描写风景刻画人物怎样布置全局怎样安排各处的情节。这些都是我们应当细心体会的。\n\n\n练习基本功对初学写作者来说是很重要的事\n\n\n一个完完整整的人、一件完完整整的事做起。\n\n\n写小说的人也不妨练习写写诗写写诗文字就可以更加精炼因为诗的语言必须很精炼一句要表达好几句的意思。\n\n\n字的本身没有好或坏要看用在什么地方。用得恰当就生动有力。\n\n\n简练就是话说得少而意思包含得多\n\n\n我认为在学习过程中出废品是很难免的。\n\n\n临时去观察一个人总不如随时注意一切的人更为重要。自己心里没有一个小的人海创作起来就感到困难。\n\n\n只说这三点吧我的那些缺点即暂不谈留作另一篇小文的材料。\n\n\n凡是能写些文艺作品的人都是先在语文上用过功夫的。\n\n\n应当先去进修语文。把文字写明白了就有了表现能力会把心中的话写到纸上去。有了这种能力再进一步学习剧本与小说的写作就必定很顺利。反之还没有把心里的话明明白白地写在纸上的本事就想去写剧本或小说必定劳而无功。\n\n\n他们的生活经验是这些作品的资料。\n\n\n不会写就是半个哑巴只会用嘴说而不会把话写在纸上。\n\n\n有思想有生活而表达不出来问题也极为严重。\n\n\n语文是随时可以练习的。写日记、写信、纪录报告等等都是练习语文的机会不可错过。\n\n\n读书而外一个作家还须熟读社会人生。\n\n\n并没有看过另一本专写人力车夫的生活的书\n\n\n词汇较为丰富了可是文笔反倒更显着平庸因为说到什么都有个人云亦云的形容词大雨必是滂沱的火光必是熊熊的溪流必是潺潺的……。这样穿戴着借来的衣帽的文章是很难得出色的。\n\n\n我们用文字表达我们的思想、感情不以文字表达文字。字典里的文字最多但字典不是文学作品。\n\n\n所谓不将就即是不随便找个词汇敷衍一下。我们要想想了再想以便独出心裁地找到最恰当的字。假若找不到就老老实实地用普通的字不必勉强雕饰。\n\n\n写作技巧至少包括三方面语言的运用描写的能力和作品的结构。\n\n\n只有自己也去生活对人的了解才会深刻。因此我们第一须和人民生活在一起第二要在生活中表现得好即使写不出好作品仍不失为好人。\n\n\n文学修养必须包括思想。\n\n\n功到自然成欲速则不达\n\n\n第二写东西时用字造句必须先要求清楚明白。\n\n\n要老老实实先把话写清楚了然后再求生动\n\n\n就是要少用“然而”“所以”“但是”不要老用这些字转来转去。\n\n\n第三我们应向人民学习。人民的语言是那样简练、干脆。\n\n\n第四我写文章不仅要考虑每一个字的意义还要考虑到每个字的声音。\n\n\n上句末一个字用了一个仄声字如“他去了”下句我就要用个平声字如“你也去吗”让\n\n\n第五我们写话剧、写电影的同志要注意这个问题我们写的语言往往是干巴巴地交代问题。\n\n\n第六中国的语言是最简练的语言。\n\n\n其实文艺工作者的本事就是用浅显的话说出很深的道理来。这就得想办法。必定把一个问题想得透彻了然后才能用普通的、浅显的话说出很深的道理。\n\n\n人物要固定事情要有范围\n\n\n我们记住语言还须注意它的思想感情注意说话人的性格、阶级、文化程度和说话时的神情与音调等等。这就是说必须注意一个人为什么说那句话和他怎么说那句话的。通过一些话我们可以看出他的生活与性格来。这就叫连人带话一齐来。\n\n\n“塞水不成河”是客观的观察“月是故乡明”是主观的情感。\n\n\n这样尽管我没写出过完美的相声段子我可是得到一个写文章的好方法句句要打埋伏。\n\n\n明白了作文要前呼后应脉络相通才不厌修改不怕删减。狠心地修改、删减正是为叫部分服从全体。\n\n\n语言练习不专仗着写剧本或某一种文体而是需要全面学习。在写戏写小说之外还须练基本功诗词歌赋都拿得起来。\n\n\n高深的思想与精辟的语言应当是互为表里相得益彰的。\n\n\n对话不能性格化人物便变成剧作者的广播员。\n\n\n剧本的语言应是语言的精华不是日常生活中你一言我一语的录音。\n\n\n喜剧语言必须馅儿多而皮薄一咬即破而味道无穷。\n\n\n第三我的生活知识与艺术知识都太少所以笔下枯涩。思想起来好不伤心音乐不懂绘画不懂芭蕾舞不懂对日常生活中不懂的事就更多了没法在这儿报账。\n\n\n最容易看出来的是学生腔里爱转文有意或无意地表示作者是秀才。\n\n\n生活是最伟大的一部活语汇。\n\n\n后来稍稍学了一点拉丁及法文我就更爱英文也就翻回头来更爱华语了因为以英文和拉丁或法文比较才知道英文的简单正是语言的进步而不是退化那么以华语和英语比较华语的惊人的简单也正是它的极大的进步。\n\n\n文字的感动力是来自在某个场合中必然的说某种话——这个话是最普遍常用的绝难借用外国文法的。一个哲学家与一个工友在他痛苦的时节是同样的只会叫“妈”的。\n\n\n写自己真知道的事不写自己不十分知道的事。\n\n\n假若机智是感诉理智的闹戏则仗着身体的摔打乱闹。喜剧批评生命闹戏是故意招笑。\n\n\n今天贴了标语明天中国就强起来——反语。君子国的标语“之乎者也”——讽刺。标语是弱者的广告——机智。张三把“提倡国货”的标语贴在祖坟上——滑稽再加上些贴标语时怎样摔跟头等等招笑的行动就成了闹戏。张三把“打倒帝国主义走狗”贴成“走狗打倒帝国主义”——幽默这个张三贴一天的标语也许才挣三毛小洋贴错了当然要受罚我们笑这种贴法可是很可怜张三。\n\n\n叙述不是枝枝节节地随便说而是把事物的本质说出来使人得到确实的知识。\n\n\n叙述不怕细致而怕不生动。在细致处要显出才华。文笔如放风筝要飞起来不可爬伏在地上。要自己有想象而且使读者的想象也活跃起来。\n\n\n内容决定形式。但形式亦足左右内容。\n\n\n描写人物要注意他的四围把时间地点等跟人物合在一处。要有人还有画面。\n\n\n我们必须去深刻地了解人。知道他的十件事而只写一件事容易成功。只知道一件就写一件很难写出人物来。\n\n\n写两千多字不多写这可只是大概的说有时候三天连一个字也写不出我不知道天下还有比这更难受的事没有。我看着纸纸看着我彼此不发生关系\n\n\n不经过自己思索、创造出来的就不会有风格。要出语惊人就要表达出自己的感情自己的想法自己的笔调。这样的文章才会是独具风格的。\n\n\n初学者可以做个学习规划可以从写日记开始把自己看到的东西能最简单地、如实地记下来就是本领。日积月累这就是宝贵材料。这样的练习就是记录生活是创作的原材料。\n\n\n创造人物是小说家的第一项任务。\n\n\n一个小说家是人生经验的百货店货越充实生意才越兴旺。\n\n\n这不是政策而是不得不如此。自己觉得很对不起文艺可是钱与朋友也是不可得罪的。\n\n\n为艺术而牺牲是很好听的可是饿死谁也是不应当的为什么一定先叫作家饿死呢我就不明白\n\n\n一、散文是用加过工的语言组织成篇的。\n\n\n二、散文中的每个字都要用得适当。\n\n\n一句中不单重要的字要斟酌就是次要的字也要费心想一想甚至于用一个符号也要留神。写散文是件劳苦的事信口开河必定失败。\n\n\n三、选择词与字是为造好了句子。\n\n\n一段中的句子要有变化不许一边倒老用一种结构。\n\n\n无论是写一部小说还是一篇杂文都须有组织。有组织的文字才能成为文艺作品。因此无论是写一部小说还是一篇短的杂文我们都须事先详细计划一番作出个提纲。写了一段临时现去想下段是很危险的。最好是一写头一段的时候就已经计划好末一段说什么。\n\n\n我觉得通俗文艺有三难不易通俗不易有趣与不易悦耳。\n\n\n大家也许就推举他主编。自傲心是最普遍的毛病甲既受人推重也许就难免傲然以文学家自居了。\n\n\n假若你不明白科学你就连这样的小说或诗也读不懂还说什么自己成为文艺家呢\n\n\n无论中外许多有名的文艺写家都并不是学文学的人医生、律师……都有成为名写家的而大学文学系毕业生反倒不一定能创作出什么来。\n\n\n学问、经验、修养、努力加上文艺天才方能产生一个作家。\n\n\n把事情看得太容易的人大概不易成功。\n\n\n在许多原因之中恐怕大家把文艺看得太轻而易举也是个重要的原因。我不敢批评别人只说我自己吧我根本就不够格以我的学问、经验、天才公公道道的说我只能作个相当好的小学校长或初中的国文教员文艺写家差得太多太多了\n\n\n假若你不相信我我说你将来的后悔与苦痛也必不减于我我向来不说谎话\n\n笔记\n\n尽管我们要只写二三千字也须先写出个提纲安排好头一段说什么第二段说什么……。有了提纲心里有了底写起来就能顺理成章先麻烦点后来可省事。\n\n💭 大纲!\n\n有不少初学写作的人感到苦恼写不出来\n我的看法是加紧学习先别苦恼。\n怎么学习呢我看哪第一步顶好是心中有什么就写什么有多少就写多少。\n\n💭 总之万事万物都要先干了再说!\n\n一开始就写小说、剧本这种情况好比没练习过骑车的人就去参加骑车竞赛。\n\n💭 循序渐进慢慢来\n\n我写的不好但写的很勤。勤是好习惯。\n\n💭 勤能补拙,笨鸟先飞。\n\n3各派的小说我都看到了一点我有时候很想仿制。可是由多读的关系我知道摹仿一派的作风是使人吃亏的事。看吧从古至今那些能传久的作品不管是属于哪一派的大概都有个相同之点就是它们健康崇高真实。反之那些只管作风趋时而并不结实的东西尽管风行一时也难免境迁书灭。在我的长篇小说里我永远不刻意的摹仿任何文派的作风与技巧我写我的。\n\n💭 我写我的,艺术文学不应该被定义\n\n我的文章写的那样白那样俗好象毫不费力。实际上那不定改了多少遍有时候一千多字要写两三天。\n\n💭 共勉哈哈哈,我也是得几个小时……\n\n在你写东西的时候要要求清楚少用那些乱七八糟的修辞。你要是真看明白了一件事你就能一针见血地把它写出来写得简练有力\n\n💭 一针见血,入门三分\n\n第一是作者的眼睛要老盯住书中人物不因事而忘了人事无大小都是为人物服务的。第二是到了适当的地方必须叫人物开口说话对话是人物性格最有力的说明书。\n\n💭 开口说话可以鲜明的表达人物性格\n\n现成不现成就是通大路不通大路大家都那么说就现成只有我们自己那么说就不现成。我们不能独创语言语言本是大家伙的。\n\n💭 约定俗成的东西\n书评\n点评"},"Personal/Book/生活百科/聂卫平围棋教程从15级到10级":{"title":"聂卫平围棋教程从15级到10级","links":[],"tags":["阅读/生活百科","阅读/笔记"],"content":"简介\n\n书名《聂卫平围棋教程从15级到10级》\n作者 聂卫平\n分类 生活百科-体育\nISBN9787115478528\n出版社人民邮电出版社\n\n概述\n“聂卫平围棋道场系列”丛书是我国围棋职业运动员聂卫平同聂卫平围棋道场的明星教师团队联合编写的适合少儿的零基础围棋启蒙书籍。 聂卫平围棋道场系列教材设置了基础知识、例题精讲、随堂练习、围棋人物、学习园地等板块内容全面、系统难度循序渐进分为“从入门到15级”、“从15级到10级”、“从10级到5级”、“从5级到1段”四本进价教程。书中的知识点讲解清晰、易懂选取了经典的例题及难度适宜练习题目且知识点与课后练习一一对应方便小朋友课后进行自测查缺补漏。此外书中还配有围棋名人故事让小朋友在学习围棋知识的同时也能学习围棋文化提升围棋素养。\n划线\n\n围棋有句口诀“金角银边草肚皮。”\n\n\n基本守角在占角的棋子旁下一手棋两颗子一起围住角上的地盘。守角是围空的基本下法之一\n\n\n基本挂角在对方占角之后我方下在占角附近限制对方角部发展。\n\n\n失败后仍选择继续前行的人才是真正的强者\n\n笔记\n书评\n点评"},"Personal/Book/生活百科/聂卫平围棋教程从入门到15级":{"title":"聂卫平围棋教程从入门到15级","links":[],"tags":["阅读/生活百科","阅读/笔记"],"content":"简介\n\n书名《聂卫平围棋教程从入门到15级》\n作者 聂卫平主编\n分类 生活百科-体育\nISBN9787115467782\n出版社人民邮电出版社\n\n概述\n“聂卫平围棋道场系列”丛书是我国知名围棋职业运动员聂卫平同聂卫平围棋道场的明星教师团队联合编写的适合少儿的零基础围棋启蒙书籍。“聂卫平围棋道场系列”系列教材设置了基础知识、例题精讲、随堂练习、围棋人物、学习园地等板块内容全面、系统难度循序渐进分为“从入门到15级”、“从15级到10级”、“从10级到5级”、“从5级到1段”四本进价教程。书中的知识点讲解清晰、易懂选取了经典的例题及难度适宜练习题目且知识点与课后练习一一对应方便小朋友课后进行自测查缺补漏。此外书中还配有围棋名人故事让小朋友在学习围棋知识的同时也能学习围棋文化提升围棋素养。\n划线\n\n围棋是我一生的至爱我曾不止一次说过对围棋有利的事情我就会去做。\n\n\n棋的块数棋盘上的块数越多越有可能被吃掉块数少的棋保护起来越容易气也比较长。\n\n\n所以我们下棋的时候要注意在开始的时候尽量不要把棋下在一路线与二路线\n\n\n围棋有句口诀“敌之要点我之要点。”破眼的位置就是对手做眼的位置。\n\n\n有的棋型为一点死意思就是说一旦被对手包围对方只要点一下眼就能将自己杀死。特点有个中心点。\n\n笔记\n\n落子无悔\n\n💭 人生如棋,落子无悔\n书评\n\n✨干掉人机\n\n点评"},"Personal/Book/社会文化/人体简史":{"title":"人体简史","links":[],"tags":["阅读/社会文化-社科","阅读/笔记"],"content":"简介\n\n书名《人体简史》\n作者 比尔·布莱森\n分类 社会文化-社科\nISBN9787549631780\n出版社文汇出版社\n\n概述\n你的身体30亿岁了一部从头讲到脚、从里讲到外、从30亿年前讲到今天的人体百科全书翻开本书从单细胞斑点讲起看看30亿年来你的身体的进化史全球销量超千万册的科普巨著《万物简史》作者比尔·布莱森重磅新作被誉为“当今在世的最有趣的非虚构类作家”人有几百万年前在树上睡觉的记忆所以现在在床上睡觉也不会掉下来只有人把空气和食物送往同一通道所以生来容易被噎死人的大脑比一万年前小了很多但它30秒处理的信息比哈勃望远镜30年的还多Y染色体可能在460万年后灭绝但不用担心男性并不会因此灭亡癌症也是进化的代价没有细胞的变异人类就不会得癌症《星期日泰晤士报》2019年度科普书 登顶《星期日泰晤士报》图书畅销榜雄踞《纽约时报》图书畅销榜18周之久提名《华盛顿邮报》2019年度图书入围2019年爱德华·威尔逊科学写作奖长名单翻开本书从单细胞斑点讲起看看30亿年来你的身体的进化史\n划线\n\n你每天眨眼14,000次[6]——相当于你在清醒的一天里闭着眼长达14分钟。\n\n\n想一想这件事吧光靠你自己就足够离开太阳系了。从字面意义来看你就是宇宙。\n\n\n生命的基本单位是细胞——人人都同意这一点。细胞里充满了各种忙忙碌碌的东西核糖体和蛋白质、DNA、RNA、线粒体\n\n\n它本身没有生命就跟其他所有的房间一样。然而天知道怎么回事所有这些东西聚拢到一起你就拥有了生命。这是科学无法解释的部分。我有点儿希望它永远保持这种神秘状态。\n\n\nDNA分子由两条梯级相连、呈著名双螺旋形状的长链构成。一段DNA可分为名叫染色体的片段及名为基因的较短单位。你所有基因的总和就是基因组。\n\n\nDNA以非凡的保真度传递信息。它每复制10亿个字母只产生一个错误。即便按照这样的精确度运行每次细胞分裂大概也会出现三个错误或突变。身体可以忽略大多数的突变但偶尔突变也会带来持久的影响。这就是演变(evolution)。\n\n\n胰岛素是一种小蛋白质对维持体内血糖的微妙平衡至关重要。太多或太少都会产生可怕的后果。我们需要大量的胰岛素。胰岛素每个分子只能持续5~15分钟因此人体对它有着不间断的补给需求。\n\n\n1型糖尿病是身体完全停止产生胰岛素。2型糖尿病是胰岛素效果变差一来是因为生成数量下降二来是因为胰岛素所作用的细胞没有做出正常的响应。这叫作胰岛素抗性。1型糖尿病多为遗传2型通常是生活方式导致的结果。\n\n\n尽管胰岛素改变了数百万糖尿病患者的生活但它并非完美的解决方案。最主要的是它不能口服因为口服的话它将先在肠道里分解无法得到吸收和利用。因此必须采用注射的方式这是个既烦琐又粗鲁的过程。在健康的人体里胰岛素水平受监控且逐秒调整。在糖尿病患者中只有在患者自我治疗的时候胰岛素才定期调整。这意味着胰岛素水平[6]在大多数时候都不怎么对头,有可能产生累积的负面效应。\n\n\n如此庞大的身躯竟然是一处微小的腺体发生故障所致显然十分讽刺。垂体腺通常被称为主腺因为大部分激素都受它控制。它生成(或调解生成)生长激素、皮质醇、雌激素和睾酮、催产素、肾上腺素,等等。\n\n\n这可能是一种很悲伤的疾病因为症状主要是食欲不振和体重减轻很容易遭到误诊。\n\n\n瘦素不是内分泌腺产生的而是脂肪细胞所产生。这是一个最惊人的发现。没有人曾想过除了专属的腺体激素也能在别的部位产生。事实上我们现在知道激素遍布人体胃里、肺里、肾里、胰腺里、大脑里、骨骼里到处都是。\n\n\n就是为什么患有厌食症的年轻人青春期大多来得很迟。“如今青春期开始得比历史上任何时期都更早原因也必定在这里。”沃斯说“在亨利八世的统治时期人们到了十六七岁才进入青春期。如今更常见的是11岁。几乎可以肯定这是因为营养得到了改善。”让问题变得更\n\n\n对人类男性来说睾酮主要由睾丸产生少量来自肾上腺并且要做三件事它赋予男性生育能力带给他低沉的嗓音和胡子等第二性征还深刻地影响他的行为让他产生性冲动偏好冒险和攻击。对女性而言卵巢和肾上腺各生成大约一半的睾酮但数量少得多它虽然提升了女性的性欲却仁慈地让她们的常识不至于因此受到干扰。\n\n\n但它拥有这种能力对我们中的一些人来说真的很幸运。”\n\n\n问题是如果你要求肾脏过长时间进行过滤它们会感到疲倦无法正常运转。随着肾脏效率降低血液中的钠含量变高你的血压也会危险地升高。随着年龄的增长肾脏功能衰减得比大多数其他器官更快。从40岁到70岁之间它们的过滤能力下降了约50。\n\n\n膀胱、胆囊和肾脏有一个共同的不幸特征那就是容易形成结石。结石是钙和盐变成的硬球。\n\n\n淋巴细胞、细胞因子、趋化因子、组胺、中性粒细胞、B细胞、T细胞、NK细胞、巨噬细胞(macrophages)、吞噬细胞(phagocytes)、粒细胞、嗜碱性细胞、干扰素、前列腺素、多功能造血干细胞,以及更多——我的意思是,还要多得多。\n\n\n免疫系统不仅仅对付细菌它还必须对毒素、药物、癌症、外来物体甚至对你自己的精神状态做出响应。比方说要是你压力过大或者疲惫不堪[3],就更容易受感染。\n\n\n你的免疫系统正不断受到以前从没见过的东西的轰炸这些东西兴许才刚刚问世——比如不断变异成新形式的流感病毒。因此你的免疫系统必须能够识别并抗击几乎可以说数量无限多的东西。”\n\n\n免疫系统的核心是五类不同的白细胞淋巴细胞、单核细胞、嗜碱粒细胞、中性粒细胞和嗜酸粒细胞。\n\n\n从本质上说发炎是身体为保护自己免受伤害而战斗所产生的热度。受伤部位附近的血管会扩张让更多的血液流向受伤部位同时也会带来白细胞抵御入侵者。这导致该部位肿胀增加周围神经的压力导致敏感压痛。\n\n\n更快。梅达沃随后发现免疫系统在生命早期就学会了不攻击自己健康正常的细胞。戴维斯向我解释说\n\n\n如果一只老鼠在很小的时候就接触过另一只老鼠的皮肤那么等前一只老鼠长大它就能够接受后一只老鼠的皮肤移植。”\n\n\n哪怕到了19世纪末科学家仍普遍认为性别不是由化学物质决定的而是由外部因素如饮食、气温甚至女性怀孕初期的情绪等决定的。\n\n\n人类实际上根本就不再生[8][3]。壁虎是再生,我们是重组。\n\n\n性别可能会稀释我们对后代的个体贡献但它对整个物种来说功莫大焉。靠着基因的混合和匹配我们获得了多样性这带给我们安全和适应力。基因多样性让疾病难以在整个种群内蔓延还意味着我们可以不断演变。我们可以保留有益的基因抛弃那些妨碍人类共同幸福的基因。\n\n\n我们对威胁性刺激非常敏感大脑甚至还来不及收到信息我们的身体就会按照程序做出反应从疼痛事件中往后撤。\n\n\n只有当大脑感受到疼痛时疼痛才出现[2]。疼痛或许始于大脚趾,但让你哎哟一声叫起来的,是大脑。在那之前,它不是疼痛。”\n\n\n所有的疼痛都是私人的而且强烈个性化\n\n\n他提出了肌肉的交互神经支配定律即一块肌肉收缩时另一块肌肉必然放松——这基本上解释了肌肉的运作原理。\n\n\n人类神经有个奇怪的地方周边神经系统里的神经要是受到损坏可以愈合并再生而大脑和脊髓中更为关键的神经则不能。\n\n\n一种疾病是否会成为流行病[10],取决于四个因素:它的致命性有多强、它是否擅长寻找新的受害者、控制它是容易还是困难、它对疫苗是否敏感。\n\n\n。埃博拉病毒的传染性简直可谓荒唐一滴比字母“O”大不了多少的血就可包含一亿个埃博拉病毒颗粒每一个颗粒都像手榴弹一般。但它传播的速度却非常缓慢。\n\n\n不太擅长置人于死地又能广泛传播的病毒才算是成功的病毒[11],这就是为什么流感是一种长年不断的威胁。\n\n\n在我们所生活的时代人多多少少死于自己的生活方式之手。会怎么死实际上是我们自己在做选择尽管当事者或许并没有怎么仔细思考、反省过。\n\n笔记\n\n痛苦有一种空白的性质\n无法回忆起\n它是何时开始的或者\n哪一天它不再存在。\n\n💭 人总是习惯于好了伤疤忘了疼\n\n所有疼痛里最严重、最棘手的一种是所谓的幻肢疼痛也就说患者感受到来自已经因为事故或截肢而丧失的身体部位的疼痛。我们觉得最厉害的一种疼痛居然是从已经不再属于身体的部位传来的这真是太讽刺了。\n\n💭 幻痛\n\n一种来自军团菌属的新型细菌。它蔓延到了酒店的空调管道那些不幸的过路人感染是因为从酒店排出的废气中穿了过去。\n\n💭 空气是疾病传输的主要媒介\n书评\n点评"},"Personal/Book/社会文化/你不可不知的法律常识":{"title":"你不可不知的法律常识","links":[],"tags":["阅读/社会文化-法律","阅读/笔记"],"content":"简介\n\n书名《你不可不知的法律常识》\n作者 张志强\n分类 社会文化-法律\nISBN9787515819556\n出版社中华工商联合出版社\n\n概述\n酒后出事同席者承担多大责任样品误当新品卖是否构成消费欺诈车借给朋友出了事故责任由谁承担是不是所有的合同都可以采用电子签名“小三”有权分得遗产吗夫妻购买的小产权房离婚时如何分割父债子还天经地义吗借款人跑了如何讨债如何约定民间借贷的利息才合法购买学区房卖房人不迁走户口怎么办老赖的住房不会被执行吗这些问题都是生活中大家非常关注的也是常常厘不清的。《你不可不知的法律常识》从生活与消费夫与妻关系、父母与子女、资产与理财、企业经营与管理、诉讼与仲裁、犯罪与刑罚这7个方面入手选取了与日常生活密切相关的100个问题用非常接地气的语言生动而严谨地进行点对点的讲解非常适合大家查阅式阅读。\n划线\n\n如果商家在办卡时没有故意向消费者虚构事实隐瞒真相最初的确向消费者提供了服务只是由于经营不善导致企业倒闭的并不构成诈骗。\n\n\n按照要求盘查一般由两名以上民警进行应当身着警服未穿警服的应当出示警察证应当向被盘查人敬礼并告知“我是xxx单位民警现依法对你进行检查请你配合。”\n\n\n如果没有正当理由拒绝警察查验身份的警察可能会将当事人带到派出所继续盘查留置时间一般不超过24小时。\n\n\n对被盘问人的留置时间自带至公安机关之时起不超过二十四小时在特殊情况下经县级以上公安机关批准可以延长至四十八小时并应当留有盘问记录。对于批准继续盘问的应当立即通知其家属或者其所在单位。对于不批准继续盘问的应当立即释放被盘问人。\n\n\n未办理结婚登记而同居生活的男女关系可分为两种一是事实婚姻二是同居关系。事实婚姻是指没有配偶的男女未办理结婚登记即以夫妻名义同居生活周围的人也认为是夫妻关系。\n\n\n1994年2月1日以后即民政部《婚姻登记管理条例》公布实施以后我们国家不再承认事实婚姻只按照“同居关系”处理。\n\n\n实际上随意借车给他人要承担很多法律风险一旦发生事故还可能要承担赔偿责任。\n\n\n目前对于行人闯红灯在人行道斑马线上发生交通事故如果机动车不存在超速、没有避让行人等情况一般是行人负主要责任驾驶员负次要责任驾驶员不承担任何责任的情况非常小\n\n\n《中华人民共和国道路交通安全法》的立法主旨偏向保护弱者\n\n\n当然如果机动车存在违法驾驶行为没有避让行人驾驶员要承担主要责任一般在70%80%之间,如有酒驾、毒驾情况的,当然由驾驶员负全责。\n\n\n一般的“知假买假”案件主要分为两种情况一种是属于普通的消费欺诈经营者需要“退一赔三”即除返还消费者已经支付的金额外还要额外支付相当于商品或服务费用3倍的赔偿不足500元的需要赔偿500元。另一种是食品安全领域方面的生产或者销售不符合食品安全标准的产品消费者除要求赔偿损失外还可以向生产者或者销售者要求支付价款10倍的赔偿金即“假一赔十”。所以职业打假人的收益丰厚即便是单价不高的食品如果购买数量较多的话赔偿数额也不是一笔小数目。\n\n\n过度医疗是医生违背医学规范和伦理准则脱离病情实际需求实施不恰当、不规范、不道德的医疗行为比如过度检查、过度治疗、过度用药等。\n\n\n电子签名的作用主要有一是证明文件的来源即识别签名人二是表明签名人对文件内容的确认三是构成签名人对文件内容正确性和完整性负责的根据。可靠的电子签名和数据电文与手写签名和书面文件具有同样的法律效力。\n\n\n根据《中华人民共和国电子签名法》第3条的规定有几类文书不得使用数据电文的形式即不能采用电子签名包括1涉及婚姻、收养、继承等人身关系的2涉及土地、房屋等不动产权益转让的3涉及停止供水、供热、供气、供电等公用事业服务的4法律、行政法规规定的不适用电子文书的其他情形。\n\n\n“买卖不破租赁”是民法上的一项重要制度它是指在租赁合同有效期间租赁物因买卖、继承等使租赁物的所有权发生变更的租赁合同对新的所有权人仍然有效。\n\n\n第二百二十九条 租赁物在租赁期间发生所有权变动的,不影响租赁合同的效力。\n\n\n在职场上遭遇性骚扰可以采取以下救济方法一是自力救济。可以主动向本人所在单位、行为人所在单位、各级妇联等举报。二是民事救济。可以通过提起民事诉讼的方式要求骚扰人停止骚扰、道歉并且赔偿精神损失。三是行政救济。《中华人民共和国治安管理处罚法》规定多次发送淫秽、侮辱或其他信息干扰他人正常生活的处5日以下拘留或者500元以下罚款情节较重的处5日以上10日以下拘留可以并处500元以下罚款。性骚扰行为构成违反治安管理行为的受害人可以要求公安机关按照此规定给予行政处罚。四是刑事救济。根据现行《中华人民共和国刑法》的规定如果侵害人的骚扰行为出现了强制、暴力等情况那么有可能构成的罪名包括故意伤害罪一般是轻伤、猥亵、侮辱妇女罪或者强奸罪一般是未遂。受害人可以进行举报由司法机关按照《中华人民共和国刑法》规定追究其刑事责任。比如案例中的刘某就构成了强制猥亵妇女罪。\n\n\n1寻找人证。找到能够证明骚扰发生的目击者而且目击者最好愿意出庭作证至少要能够提供书面的证言。2保存物证。比如收到的骚扰短信、电子邮件、视频、微信、QQ聊天记录等。3收集视听资料。录音、录像和照片等都可作为证据。若长期被性骚扰可以随身携带录音机和摄像机、照相机进行取证。即使是偷录偷拍的资料只要不侵犯对方合法权益或者违反法律禁止性规定一般也会取得法院的认可。\n\n\n公证业务种类繁多但并不是所有的公证申请都能受理。公证本身的目的在于预防纠纷、维护权利一旦公证质量出现问题公证就会失去公信力因为公证首先要求的是公证内容必须真实、合法。\n\n\n违反了《中华人民共和国婚姻法》的规定也与社会的公序良俗相背离因此公证员会拒绝做公证。\n\n\n父母与子女之间的关系是自然形成的血缘关系涉及伦理道德是与生俱来的不能通过法律或其他手段人为地加以解除。断绝父子关系、母女关系等要求有悖于法律和人伦常理自然无法公证。\n\n\n《中华人民共和国继承法》规定代书遗嘱必须要求有两个以上见证人在场见证由其中一人代书并需代书人、其他见证人和遗嘱人共同签名确认且遗嘱见证人不能与继承人有利害关系。\n\n\n最后建议签名后再写上身份证号码避免同名同姓情况的发生确保身份的唯一性。为了保险起见还可以将身份证复印件附在文件的后面。\n\n\n离婚是以“夫妻感情是否确已破裂”作为依据\n\n\n夫妻关系的现状和有无和好的可能等方面综合判断而不会单纯以能不能生育子女作为判决离婚的理由。\n\n\n1重婚或有配偶者与他人同居的2实施家庭暴力或虐待、遗弃家庭成员的3有赌博、吸毒等恶习屡教不改的4因感情不和分居满2年的5其他导致夫妻感情破裂的情形。所以不能生育不是法院判决离婚的法定理由但可以作为确认夫妻感情破裂的因素之一予以着重考虑。\n\n\n第一要求双方连续两年分居互不履行夫妻义务。这种分居期限必须是不间断、持续性的分居通俗讲就是连续两年没有见面经济上没有互相帮助生活上也互不关心也没有履行夫妻义务。\n\n\n第二双方因感情不和而分居。分居的原因不能是工作、学习等客观上造成夫妻异地居住。比如夫妻双方或一方外出打工由于交通、收入等因素的限制而不能在一起虽然有分居的事实但却不是由于感情不和造成的。第三需经法院调解且无和好可能。法院审理离婚案件必须综合双方的婚姻基础、婚后感情、离婚原因、夫妻关系的现状以及有无和好可能等因素。长时间的分居是法院考虑的重要因素之一但是分居两年并不会自动离婚。\n\n\n按照《中华人民共和国老年人权益保障法》和《中华人民共和国婚姻法》的规定赡养人的范围非常明确包括婚生子女、非婚生子女、养子女、有抚养关系的继子女以及有负担能力的孙子女、外孙子女但不包括儿媳、女婿。\n\n\n《中华人民共和国继承法》第12条就规定丧偶儿媳对公婆丧偶女婿对岳父母尽了主要赡养义务的可以作为第一顺序继承人。\n\n\n保证书的内容是金某的真实表示属于合法的赠与行为真实有效遂判决准许离婚张某同时获得全部财产。\n\n\n某甲与妻子某乙于2002年6月结婚双方于2002年7月签订了一份协议其主要内容为任何一方都要洁身自好不得发生婚外性行为否则违约方应向对方补偿名誉损失费及精神损失费30万元。2003年8月某甲与其他女性发生男女关系被妻子某乙发现。不久某乙起诉离婚主张夫妻平分财产的同时要求某甲按协议另补偿其30万元。法院经过审理确认双方达成的忠诚协议合法有效判决某甲支付某乙“违约金”30万元。\n\n\n自由和忠实义务不仅仅是法律上的义务更多的是道德上的义务。婚姻应该由法律规范法律对于爱情或者情感就无能为力了\n\n\n对于年满10周岁的子女还会征求参考子女本人的意愿。如果孩子已年满18周岁无须任何人的监护与抚养此时也就不再存在抚养权变更的问题。\n\n\n拟制血亲是指本来没有血缘关系或没有直接的血缘关系但法律上确定其地位与血亲相同的亲属。\n\n\n在亲子鉴定确认为非婚生子后法院一般会准予离婚还会应男方的要求作出以下的判决一是子女由女方抚养并由女方承担子女的抚育费二是女方向男方支付一定数额的精神赔偿金三是女方返还男方之前所负担的子女抚养费。\n\n\n。但债务人老叶已死亡而叶家两兄弟明确表示放弃对其父遗产的继承吴某也未能举证证明两兄弟继承其父的遗产所以两被告无须对其父生前借款承担清偿义务遂驳回原告吴某的诉讼请求。\n\n\n吴某也并非没有救济手段在老叶的两个儿子放弃继承后吴某可以向法院起诉直接申请执行老叶的遗产用于偿还所欠自己的债务不过前提是老叶尚有遗产可供执行。\n\n\n公序良俗\n\n\n一般而言按照《中华人民共和国合同法》的规定日常生活的开支以及小额的、不以结婚为目的的馈赠属于赠与性质赠与物的所有权自交付时起转移受赠方成为赠与物的所有权人一般不予返还。对于贵重的珠宝首饰、购房、购车等大额的支出是以双方结婚为目的因恋爱失败分手而不能结婚的应当返回赠与一方。\n\n\n第一债权人在3年的诉讼时效期限内尽快向债务人原居住地或者财产所在地的人民法院提起诉讼追讨债款。\n\n\n不当得利是指一方没有合法根据获得利益而致使他方利益受到损失\n\n\n订金属于预付款而定金是签约的保证属于“违约”定金。也就是定金不可退订金是可以退还的。\n\n\n借条是借款人向出借人出具的借款书面凭证它证明双方建立了一种借款合同关系而欠条是双方基于以前的经济往来而进行结算的一种结算依据\n\n\n第一证明效果不同。借条证明的是借款关系而欠条证明的是欠款关系。借条形成的原因是特定的借款事实欠条形成的原因很多可以基于多种事实而产生如因买卖产生的欠款、因劳务产生的欠款、因损害赔偿产生的欠款等。“欠”字与“借”字有很大的区别“欠”反映的是一种“状态”,“借”表明了债权关系是因为借贷而形成欠条则无法表明债权关系形成的真正原因因此有欠条不等于一定有借款。所以在诉讼过程中出借人必须首先证明欠条形成的事实向法庭说明欠款形成的原因及提供相关的证据。而拿着借条到法院去起诉就能比较容易认定借款事实一般他只需向法院陈述借款的事实经过即可对方要抵赖很困难。第二对诉讼时效的影响不同。注明了还款期限的借条和欠条诉讼时效没有区别都是从注明的还款期限之日起3年。但是如果没有注明还款期限两者的诉讼时效差别就大了。没有注明还款期限的欠条自债务人出具时起债权人即享有向其主张还款的权利诉讼时效就开始计算而一般诉讼时效期间是3年3年以后再去主张就会丧失了时效期间而对于没有注明还款期限的借条出借人的权利只有在其要求借款人偿还而被借款人拒绝时才被侵害诉讼时效期间应从借款人拒绝偿还之次日起开始计算3年的诉讼时效这对保护出借人的利益更为有利。\n\n\n法院最终判决由尤某承担偿付20万元借款的连带责任\n\n\n按照我国现行法律规定担保责任分为一般担保和连带责任担保。一般担保是指在债务人通过诉讼仍不能承担债务时担保人应当承担担保责任连带担保责任是指债权人可以直接要求债务人和担保人任何一方承担责任不受债务人有无能力的限制。如果合同上没有注明是一般担保还是连带担保法律推定为连带担保。\n\n\n在签订担保合同时要看清楚自己承担的是一般担保还是连带担保以及担保的期限在允许的情况下尽可能让债务人为自己提供反担保\n\n\n仅凭录音无法确定谈话时间、地点、谈话者身份录音的真实性无法确认且录音所涉及谈话内容未正面提及本案款项无法证明与本案款项的关联性所以驳回原告的诉讼请求。\n\n\n银行转账的凭证能够说明一方当事人将借款打款给了另一方并不能证明两人之间的债权债务关系是因为什么而成立的即只完成了“钱款已付”的举证而没有完成“借款合同成立”的举证。\n\n\n借条、欠条等借据是证明双方存在借贷合意和借贷关系实际发生的直接证据具有较强的证明力。\n\n\n法院经审理认为房屋买卖合同签订前1个月涉案房屋内确曾发生过非正常死亡事件但原房主未能主动披露违背了诚实信用原则对田女士构成欺诈最终判决撤销双方的房屋买卖合同。\n\n\n法定代表人是公司的全权代表在国家法律、法规以及公司章程规定的职权范围内行使职权、履行义务代表公司参加民事活动对公司的生产经营和管理全面负责。法定代表人的权力主要包括对外签字权、财务的控制权、参与诉讼权等。从某种意义上讲担任了公司的法定代表人即掌控了公司的核心权力。\n\n\n驰名商标\n\n\n社会保险属国家强制性法定义务是不可免除、放弃的。公司将应当缴纳的社保费用直接支付给劳动者本人即使是双方自愿有员工的书面承诺书因为违法了法律的强制性规定也是一种无效的法律行为其承诺不具备法律效力。\n\n\n劳动者不能胜任工作经过培训或者调整工作岗位仍不能胜任工作的用人单位可以提前解除劳动合同。\n\n\n《中华人民共和国劳动合同法》规定用人单位招用尚未解除劳动合同的劳动者对原用人单位造成经济损失的该用人单位应当依法承担连带赔偿责任。\n\n\n用人单位在试用期解除劳动合同必须有证据、有理由并且承担举证责任否则需承担违法解除后果。公司在录取时就应当明确告知劳动者录用条件并且要加强考核管理对于试用期间的表现进行记录与评价发现不符合录用条件的要通知员工最好采用书面形式告知其解除的理由。\n\n\n原告杨某提供的电子邮件和QQ记录能够反映出其在休息日、法定节假日存在加班工作情况但无法说明加班时间的长短\n\n\n劳动合同期满处于孕期、产期、哺乳期的女职工的劳动合同应当续延至相应的情形消失时终止。\n\n\n如果连续两次签订了固定期限劳动合同那么第三次签订时就可要求与公司签订无固定期限合同。\n\n\n未经司法行政机关批准的公民个人与他人签订的有偿法律服务合同法院不予保护\n\n\n原则上诉讼费用由败诉方负担这是通行的规则也是常识。\n\n\n因此被告人程某的行为属正当防卫宣判被告人程某无罪。检察院抗诉后二审法院驳回抗诉维持原判。\n\n\n正当防卫是指为了使国家、公共利益、本人或者他人的人身、财产和其他权利免受正在进行的不法侵害而采取的制止不法侵害的行为通俗讲就是就是有人来惹事儿时自己出手做出的自卫。\n\n\n目前我国刑法并没有将虐待动物列入犯罪因此虐待动物不能判刑不会被追究刑事责任但却有可能招致民事责任。\n\n笔记\n\n根据《中华人民共和国消费者权益保护法》的规定如发生欺诈行为经营者需“退一赔三”即退还消费者已经支付的金额同时按照消费者购买商品的价款或者接受服务的费用的3倍标准支付赔偿。\n\n💭 好想尝试尝试\n\n车主有过错主要是指其明知车辆有缺陷并且此缺陷易导致交通事故发生知道借车人没有驾驶资格仍然出借车辆知道借车人缺少驾驶能力比如饮酒、吸毒、生病等无法安全驾驶车辆等情况。\n\n💭 主观行为\n\n《中华人民共和国侵权责任法》第50条对此情况予以了明确规定该条规定当事人之间转让并交付机动车但未办理所有权转移登记发生交通事故后属于该机动车一方责任的由受让人承担赔偿责任。这是因为从法理上讲因车辆已交付原车主仅仅是名义上的所有人既不能实际支配该车也不能从该车的营运中获得利益所以原车主不应对机动车发生交通事故致人损害承担责任。\n\n💭 尊重事实\n\n纪某所立下的遗嘱也是基于同居关系这有悖于公序良俗应属无效行为。在审判实践中法院一般也支持这一观点会驳回“小三”要求继承遗产的诉讼请求。\n\n💭 有悖公良就会考虑事实\n\n我国实行婚姻自由根据《中华人民共和国婚姻法》的规定只要婚姻双方当事人依法在民政部门办理了离婚登记手续双方当事人的婚姻关系即宣告解除所以法律上不存在“假离婚”的概念。\n\n💭 法律尊重事实,不谈感情\n\n1986年宋先生与朱女士登记结婚宋先生没有孩子朱女士是再婚带着一对儿女与宋先生共同生活二人婚后也未再生育子女。1993年朱女士带来的儿女相继离家外出打工2012年2月朱女士去世。这时已经65岁的宋先生没有经济来源生活困难而两个继子女都不愿赡养自己。无奈他将与自己没有血缘关系的这对儿女告上法庭要求他们赡养自己。法院经审理认为两被告随其母朱女士与原告宋先生长期共同生活接受原告的抚养教育与原告之间形成继父母子女关系对原告宋先生负有赡养义务最终酌情判决两被告每人每年分别向宋先生支付赡养费1500元。\n\n💭 尊重事实,不能违背社会伦理道德\n\n“订金”与“定金”虽一字之差但是在法律意义上却相差甚远。\n\n💭 定金不退,约定协议\n\n显然“凶宅”肯定会影响买房人的居住心情产生一种恐惧的心理。此外当事人订立履行合同应当遵循诚实信用原则尊重社会公德。\n\n💭 尊重公序良知\n\n法院启动拍卖程序将房屋拍卖了70多万元随后法院从差额款中预留20万元作为保障被执行人孙某的生活费用剩余的款项支付给了邹某。\n\n💭 哈哈,生活费\n\n两人及多人打架斗殴一方先动手后动手的一方实施的所谓反击他人的行为属于互殴行为不属于正当防卫因为斗殴双方都在积极追求非法伤害对方的结果。\n\n💭 先跑再还击否则就是互殴\n书评\n\n✨公序良知、主观臆断、客观事实都是法律衡量的重要参考。\n\n点评"},"Personal/Book/社会文化/半小时漫画《论语》":{"title":"半小时漫画《论语》","links":[],"tags":["阅读/社会文化-文化","阅读/笔记"],"content":"简介\n\n书名《半小时漫画《论语》》\n作者 陈磊·半小时漫画团队\n分类 社会文化-文化\nISBN9787549636358\n出版社上海文汇出版社\n\n概述\n担心《论语》看不下去那是因为不知道孔子原来这么爱吐槽通过手绘漫画和爆笑段子陈磊笔名混子哥领衔的半小时漫画团队一边向我们展示孔子和弟子们的花式卖萌和吐槽一边串讲《论语》里的经典章句让我们在哈哈大笑中学到《论语》里的人生哲理。为什么颜回一生贫困潦倒没做过什么大事却获得了孔子“不迁怒不贰过”的赞赏并成为孔子最喜欢的学生我们耳熟能详的“知之为知之不知为不知是知也”其实是孔子对子路学习态度不端的吐槽宰我到底做了什么逼得孔子爆出了“朽木不可雕也粪土之墙不可圬也”这样的粗口翻开本书看孔子和弟子们卖萌吐槽人生哲理全学到\n划线\n\n子曰“有教无类。”——《论语·卫灵公》\n\n\n子曰“默而识zhì学而不厌诲人不倦何有于我哉”——《论语·述而》\n\n\n子曰“人而不仁如礼何人而不仁如乐何”——《论语·八佾》\n\n\n称作孔门十哲。\n\n\n都说缘分天注定相遇是命运\n\n\n所以各位家长看见了吗想要让自己的孩子赢在起跑线上自己得先跑起来\n\n\n但颜回总是表现得十分低调从不显山露水孔子甚至一度以为他是一个傻子……故事是这样的。\n\n\n但关键的一点是要看这个人能否做到也能穷得开心。\n\n\n安贫乐道。\n\n\n颜回就不这样。他能设身处地地理解别人对他人的喜怒哀乐感同身受。\n\n\n子路会把陷入困境视作自己的问题然后开始自我怀疑这是不自信的表现。\n\n\n子曰“三军可夺帅也匹夫不可夺志也。”——《论语·子罕》\n\n\n不迁怒不贰过。从来不迁怒于别人犯过的错绝不再犯第二次。\n\n\n作为鲁国政坛上的过来人孔子给冉雍支了三招\n\n\n子曰“夫人不言言必有中。”——《论语·先进》孔子说“这个人平日不大开口一开口一定中肯。”[插图]成语言必有中就出自上文,意思是一个人说话总是能说到重点。\n\n\n所以马德好才是骥能称为千里马的关键把马换成人也是一样的道理比起才华和颜值德行才是最重要的。\n\n\n\n要解决问题得先找到问题的根本\n\n\n\n\n为了解决问题可以转移矛盾\n\n\n\n\n多次转移矛盾彻底把水搅浑\n\n\n\n第一课要充分了解对方的痛点并给予不露声色的试探\n\n\n入“伯夷、叔齐何人也”[插图]曰:“古之贤人也。”[插图]曰:“怨乎?”[插图]曰:“求仁而得仁,又何怨?”——\n\n\n如切如磋如琢如磨。\n\n\n第二课面对自己的无知要虚心而积极地改正\n\n\n子贡问曰“孔文子何以谓之”子曰“敏而好学不耻下问是以谓之也。”[插图]——《论语·公冶长》\n\n\n第三课对自己的老师要给予家人般的温暖\n\n\n子曰“莫我知也夫”[插图]子贡曰:“何为其莫知子也?”[插图]子曰:“不怨天,不尤人,下学而上达。知我者其天乎!”——《论语·宪问》\n\n\n宰我逼得孔子爆粗口的“杠精”学生\n\n\n子曰“知者不惑仁者不忧勇者不惧。”——《论语·子罕》孔子说“聪明的人不迷惑仁德的人不忧虑勇敢的人无所畏惧。”\n\n\n只有痛苦大于欢乐才能体现出子女对父母去世的悲伤。\n\n\n子曰“予之不仁也子生三年然后免于父母之怀。夫三年之丧天下之通丧也予也有三年之爱于其父母乎”——《论语·阳货》\n\n\n二、老师主张天下太平宰我建议世界大战\n\n\n子闻之“成事不说遂事不谏既往不咎。”——《论语·八佾》\n\n\n老师说不要逃课、睡觉宰我说不睡觉会变丑\n\n\n宰予昼寝。子曰“朽木不可雕也粪土之墙不可圬也。于予与何诛”——《论语·公冶长》\n\n\n子曰“由诲女知之乎知之为知之不知为不知是知也。”——《论语·为政》\n\n\n子曰“衣敝yùn与衣狐貉者立而不耻者其由也与不忮zhì不求何用不臧”\n\n\n他永远活在了《论语》里\n\n\n这就是孔子教学方法的厉害之处针对学生的不同情况制订不同的课程方案。\n\n\n子曰“不患寡而患不均不患贫而患不安。”——《论语·季氏》\n\n\n子曰“举直错诸枉能使枉者直。”——《论语·颜渊》\n\n\n子夏曰“博学而笃志切问而近思仁在其中矣。”\n\n\n子谓子夏曰“女为君子儒无为小人儒”——《论语·雍也》孔子对子夏说“你要去做一个像君子一样的读书人而不是去做那种像小人一样的读书人。”\n\n\n活在充满谎言的家庭孩子长大后就不会诚实守信做人的三观都不正了早晚会闯大祸。所以这猪必须得宰\n\n\n今天给老板打工有没有尽心尽力是不是上班摸鱼了\n\n\n士不可不弘毅任重而道远。\n\n\n他还要教育老百姓让他们懂道理提高个人素质大家相亲相爱不搞内讧\n\n\n曰“莫春者春服既成冠者五六人童子六七人浴乎沂风乎舞雩咏而归。”——《论语·先进》\n\n\n\n兴趣是最好的老师\n\n\n\n\n脑筋要动起来啊\n\n\n\n学而不思则罔思而不学则殆\n\n\n子曰“三人行必有我师焉。择其善者而从之其不善者而改之。”\n\n\n见贤思齐\n\n\n子曰“见贤思齐焉见不贤而内自省也。”\n\n\n别看只是小小一筐但它只是个开始只要坚持不懈每天填一点儿都是进步。[插图]这就叫譬如平地,虽覆一篑,进,\n\n\n二、怎样做才能成为君子1. 格局要大\n\n\n\n多读书但不要读死书\n\n\n\n\n不理解我又怎样开心最重要\n\n\n\n三、仁究竟是个啥仁是孔子思想的核心在《论语》中出现了一百多次。对于仁要把握住一个关键点那就是孔子给所有弟子讲的全不一样\n\n\n子曰“非礼勿视非礼勿听非礼勿言非礼勿动。”\n\n\n这叫朝闻道夕死可矣。很明显道比生命还重要。\n\n\n逝者如斯夫不舍昼夜。”\n\n笔记\n\n结果三家知道了这件事认为孔子打算害自己于是不断排挤孔子最终把孔子赶出了鲁国。\n孔子只能带着学生们出去找工作这段经历就是著名的周游列国。\n\n💭 原来周游列国是混不下去了哈哈\n\n子曰“饭疏食饮水曲肱而枕之乐亦在其中矣。不义而富且贵于我如浮云。”\n\n💭 安贫乐道\n\n作为鲁国政坛上的过来人孔子给冉雍支了三招\n\n💭 先有司、赦小过、举贤才\n\n所以马德好才是骥能称为千里马的关键\n把马换成人也是一样的道理比起才华和颜值德行才是最重要的。\n\n💭 心灵美才是真的美\n\n入“伯夷、叔齐何人也”\n[插图]\n曰“古之贤人也。”\n[插图]\n曰“怨乎”\n[插图]\n曰“求仁而得仁又何怨”\n——\n\n💭 求仁得仁\n\n名分这玩意儿非常重要。历史上有很多事在做之前都要先喊个口号\n[插图]\n[插图]\n原文及译文\n\n💭 明正言顺\n\n这就是孔子教学方法的厉害之处针对学生的不同情况制订不同的课程方案。\n\n💭 因材施教\n\n孔子说无论是钱财还是粮食拿来帮助富人那只能叫锦上添花人家不一定需要拿来援助穷人才叫雪中送炭能救人性命。\n\n💭 现如今只能锦上添花,难得雪中送炭\n\n三、仁究竟是个啥\n仁是孔子思想的核心在《论语》中出现了一百多次。\n对于仁要把握住一个关键点那就是\n孔子给所有弟子讲的全不一样\n\n💭 因材施教\n书评\n\n✨\n\n点评"},"Personal/Book/社会文化/民法典与百姓生活100问":{"title":"民法典与百姓生活100问","links":[],"tags":["阅读/社会文化","阅读/笔记"],"content":"简介\n\n书名《民法典与百姓生活100问》\n作者 中共重庆市委宣传部 西南政法大学\n分类 社会文化-法律\nISBN9787229156572\n出版社重庆出版社\n\n概述\n2020年5月28日第十三届全国人大三次会议以98.5%的高票表决通过《中华人民共和国民法典》这是新中国成立以来第一部以“法典”命名的法律其意义注定非凡。《中华人民共和国民法典》即将在2021年1月1日起施行。在此背景下《民法典与百姓生活100问》一书的推出展示了《民法典》是如何作为社会生活百科全书为人民群众实现美好生活保驾护航。书稿依据《民法典》的篇章体例分为七篇分别是总则编14问、物权编18问、合同编20问、人格权编10问、婚姻家庭编10问、继承编12问、侵权责任编16问总共100问共计9万余字。写作风格方面书稿以案例故事加图文解说的趣味方式将《民法典》送到人民群众的身边走进人民群众的心里。\n划线\n\n“定金”和“订金”一字之差含义却大相径庭\n\n\n定金”是金钱担保是指合同当事人于合同订立时或合同履行前由一方向另一方交付的具有担保性质的资金。\n\n\n交付定金的一方不履行义务的丧失定金收受定金一方不履行义务的双倍返还定金。而“订金”不具有担保性支付订金通常是预付款或先期支付行为。因此订金支付方不能依据定金罚则要求收取方双倍返还订金。\n\n\n婚前财产公证也有利于夫妻双方纯粹、良好感情的维系稳定婚姻生活。\n\n笔记\n书评\n点评"},"Personal/Book/社会文化/这里是中国":{"title":"这里是中国","links":[],"tags":["阅读/社会文化-文化","阅读/笔记"],"content":"简介\n\n书名《这里是中国》\n作者 星球研究所 中国青藏高原研究会\n分类 社会文化-文化\nISBN9787521701579\n出版社中信出版集团\n\n概述\n这本书集结星球研究所近3年来中国主题文章的精华按照中国地势三级阶梯顺序呈现出荒原到人间的变化全书收录300余张精致摄影作品涵盖诗词、动植物、人文等丰富内容以广阔的地理视角和宏大的时间尺度重新解读中国故事。以18个关于中国的独特话题365张具有地域代表性的高清摄影作品串联起中国的地理科普和人文故事。了解中国在时间长河中的起源和变迁、生命和文明的孕育及成长。\n划线\n\n有了水生命也开始绽放。\n\n\n王昌龄诗云青海长云暗雪山孤城遥望玉门关。黄沙百战穿金甲不破楼兰终不还。王昌龄《从军行七首·其四》\n\n\n每个人心中都有一个西安。或是秦皇的兵马俑或是汉唐的长安城又或是明清的古城墙。\n\n\n西安城墙是中国现存规模最大、保存最完整的古代城垣是第一批全国重点文物保护单位。\n\n\n这也许要归因于它对三教九流、各个阶层的容纳。三千年以来上至王侯将相下至升斗小民无数人逐一登临成都这个舞台共同营建出了一个中国最具人间烟火气的城市。\n\n\n窗含西岭千秋雪门泊东吴万里船。杜甫《绝句》\n\n\n甫在《赠花卿》一诗中记录道锦城丝管日纷纷半入江风半入云。此曲只应天上有人间能得几回闻\n\n\n人们会说豪爽山东、天府四川却很难用一个词来准确表述河南。\n\n\n不南不北不偏不倚相当“中庸”。\n\n\n若问古今兴废事请君只看洛阳城。司马光《过故洛阳城》\n\n\n造山、造水、造中华这就是河南。\n\n\n最为经典的则是“对景”的运用。对景是中国古代园林设计的经典手法即从一处景观欣赏另一处景观两景相对会产生非常奇妙的视觉美感。\n\n\n[插图]西湖“曲院风荷” / 摄影 肖奕叁“曲院风荷”位于苏堤北端西侧,是西湖十景之一。除此之外,西湖十景还包括“苏堤春晓”“断桥残雪”“花港观鱼”“柳浪闻莺”“雷峰夕照”“三潭印月”“平湖秋月”“双峰插云”“南屏晚钟”。\n\n笔记\n\n“五星出东方利中国”织锦 / 摄影 刘玉生\n\n💭 太神奇了\n书评\n\n✨值得一看\n\n点评"},"Personal/Book/科学技术/贝尔实验室与美国革新大时代":{"title":"贝尔实验室与美国革新大时代","links":[],"tags":["阅读/科学技术-自然科学","阅读/笔记"],"content":"简介\n\n书名《贝尔实验室与美国革新大时代》\n作者 乔恩·格特纳\n分类 科学技术-自然科学\nISBN\n出版社中信出版集团\n\n概述\n20世纪20年代初创开始到20世纪80年代拆分结束作为美国电话电报公司的研发部门贝尔实验室一直是世界上创新领域规模最大而且可以说是最好的实验室。从晶体管到激光从数字通信到蜂窝电话现代生活与贝尔实验室可谓息息相关。 在《贝尔实验室与美国革新大时代》中乔恩·格特纳对20世纪一些最重要的发明进行了追根溯源。文中描绘了数位对当代通信和计算机技术做出过决定性贡献的科学家。他们是默文·凯利、比尔肖克利、克劳德·申农、约翰·皮尔斯以及比尔·贝克。这些天才宅男才华横溢、行为不合常规在贝尔实验室度过了自己的职业生涯。同时本书也赞誉了贝尔实验室那些宽敞且与世隔绝的工作场所因为天才们可以在那里进行各种尝试无须担心复杂的人际关系、股民利益或公司收益。 在创新成为一句口头禅的今天。贝尔实验室为我们提供了一条途径,帮助我们丰富对面临的技术革新挑战和解决方案的理解。毕竟贝尔实验室正是管理创新的基本思路的源头。\n划线\n\n在谷歌出现之前的那个时代贝尔实验室被称为美国知识分子的天堂。正是这个地方孕育设计出了当时的未来——也就是如今我们所谓的现在。\n\n\n一些当代思想家认为21世纪的创新只能靠头脑聪明、追逐利润的企业家在激烈的市场竞争中实现。\n\n\n巧的是大萧条时代却让科学知识的发展硕果累累。贝尔实验室被迫缩短员工的工作时间一些年轻员工因为有空闲时间就到位于曼哈顿上城的哥伦比亚大学注册攻读学术课程。通常这些员工会选择学习伊西多·艾萨克·拉比教授在哥伦比亚大学讲授的一门课此人后来也获得了诺贝尔奖\n\n\n“我认为当时我们并没意识到后来成为技术核心的一些东西已经近在咫尺当时很难预料它们还要多久才会出现。”\n\n\n多年以后有时候人们会这样认为——这在一定程度上要归功于美国电话电报公司庞大的宣传系统——20世纪三四十年代科学家加盟贝尔实验室的目的是为了科学的发展但这其实只是他们工作回报的附属品。\n\n\n贝尔系统是商界有史以来单一私人企业控制的、最庞大的资本集团资金规模超过了宾夕法尼亚铁路公司和美国钢铁有限公司之和。\n\n\n不知道该做什么的时候你就做点儿事情。\n\n\n与此相反所有建筑都连接在一起以避免部门间那种固定的地理划分鼓励员工自由交流和密切接触。”\n\n\n跨学科团队\n\n\n到1月下旬的时候他已经提出了一套晶体管的理论和设计方案其外观和功能都不同于巴丁和布拉顿的晶体管\n\n\n凯利想方设法让布拉顿在贝尔实验室享受无拘无束的自由。布拉顿不再参与晶体管工作但是他也不必再向肖克利汇报工作因为他实在无法忍受作为主管的肖克利\n\n\n科学并没有神奇之处。我们的研究人员遵循的是明确的计划而计划则是整个系统的一部分其中并没有什么魔法。”很少有人当面对凯利的观点提出异议。但在来访者看来有时候甚至就连科学家也认为贝尔实验室已经呈现了一丝具有魔力般的风范。而且我们也很难否认一些完全不科学的因素——比如运气和机遇——在贝尔实验室的创新方面发挥了一定程度的作用。\n\n\n当时世界上没有更好的地方适合研究电子继电器而继电器是整个贝尔系统的转换支柱\n\n\n如果你要发送一条信息你只是从一系列可能会被选中的信息中选择你需要的。接收者对接下来要收到的信息知道得越少你传给他的信息就越多。\n\n\n凯利经常在新员工入职的第一天这样告诉他们“每天在这里工作7个半小时你们就能拿到报酬但升职和加薪取决于你在另外16个半小时里所做的事。\n\n\n如果事后认真分析我们从任何公司取得的最伟大进展中也许都能找到让这项技术灭亡的开端。\n\n\n来改变世界的成果。\n\n\n克劳德·申农信息时代之父\n\n笔记\n\n运气和时机似乎也很重要因为经常出现的情况是正确的答案、合适的人、合适的地方——甚至是这三者同时出现——也需要与合适的问题不期而遇。\n\n💭 天时地利人和缺一不可\n\n战争带来了紧迫感\n\n💭 战争按下了快进,加速了科技发展\n\n每间办公室、每个实验室的规格都是6英尺的整数倍由于间隔墙使用的都是隔音的钢结构材料可以在很短的时间内做出调整因此空间随时可以根据需求扩展或缩小。只要空间允许18英尺长的实验室可以迅速扩展到24英尺长。每段6英尺长的空间都配备有各种管道以满足实验人员的基本需求压缩空气、蒸馏水、蒸汽、天然气、真空装置、氢气、氧气和氮气而且还有直流电源和交流电源。\n\n💭 饥荒\n\n首先如果你的新设备没有大规模量产那就不算创新其次如果你没能找到市场销售这种产品那么也不算创新。\n\n💭 当今的伪需求\n\n不过凯利并没告诉大家这个创意竟然源自一个在工作过程中睡觉的人。\n\n💭 灵感来自生活\n\n当然这两种理念并不相互排斥因为个体和集体对创新都是必要的\n\n💭 黑猫白猫能抓老鼠就是好猫\n\n他提出这种机器既实用又有经济效益最终会在某些自动化任务中代替人类。\n\n💭 自动化\n\n创造性技术的研发机构需要稳定的资金支持。物理学家菲尔·安德森说过“永远不要低估金钱的重要性。\n\n💭 资源的重要性不言而喻!\n\n技术的角度看没有理由马上应用晶体管——至少现在如此。复杂程度令人生畏的电话系统并不欢迎突然的变化即使这些变化能让系统明显有所改善也是如此。\n\n💭 新老交接需要一个缓冲期\n\n光纤会是未来通信舞台上的主角儿\n\n💭 现如今已经成为了必不可缺的主角儿\n书评\n点评"},"Personal/Book/科学技术/高性能Linux服务器运维实战shell编程、监控告警、性能优化与实战案例":{"title":"高性能Linux服务器运维实战shell编程、监控告警、性能优化与实战案例","links":[],"tags":["阅读/科学技术","阅读/笔记"],"content":"简介\n\n书名《高性能Linux服务器运维实战shell编程、监控告警、性能优化与实战案例》\n作者 高俊峰编著\n分类 科学技术-工业技术\nISBN9787111655497\n出版社机械工业出版社\n\n概述\n《高性能Linux服务器运维实战shell编程、监控告警、性能优化与实战案例》以Linux运维平台下的开源应用软件为中心涉及Linux运维的各个方面主要从系统基础运维、系统性能调优、智能运维监控、运维实战案例4个方面展开介绍。本书贯穿实战、实用、通俗、易懂的特点在内容上注重实战化通过真实的生产环境从多个方面介绍运维工作中的方方面面。通过真实案例的学习可以使读者深入地掌握Linux运维技术的各种经验和技巧从而真正提高企业的实战能力。\n划线\n\n构建一个智能的运维监控平台必须以运行监控和故障告警这两个方面为重点将所有业务系统中所涉及的网络资源、硬件资源、软件资源、数据库资源等纳入统一的运维监控平台中并通过消除管理软件的差别数据采集手段的差别对各种不同的数据来源实现统一管理、统一规范、统一处理、统一展现、统一用户登录、统一权限控制最终实现运维规范化、自动化、智能化的大运维管理。\n\n笔记\n书评\n\n✨内容滞后生搬硬套只有实际生产的事例和思维还凑合吧\n\n点评"},"Personal/Book/经济理财/人力资源管理从入门到精通":{"title":"人力资源管理从入门到精通","links":[],"tags":["阅读/经济理财-管理","阅读/笔记"],"content":"简介\n\n书名《人力资源管理从入门到精通》\n作者 张明辉\n分类 经济理财-管理\nISBN9787302392002\n出版社清华大学出版社\n\n概述\n本书是一本企业人力资源管理实务书由浅入深地介绍了人力资源管理的具体内容在企业中人力资源部门员工具体做什么、怎么做。职位不同所需具备的知识和能力也是不同的纵向职位层级的划分构成了本书的框架入门篇——人力资源专员的应知应会提升篇——人力资源主管的工作技巧精通篇——人力资源部经理的管理技术。全书共20章。从HR入行须知讲起入门篇介绍了一个基本不懂业务的新手如何快速成长为熟手提升篇介绍了人力资源主管的工作技巧在专员、主管的层级按五大模块人事、招聘、培训、薪资、考核具体介绍精通篇介绍了人力资源部经理的管理技术包括组织架构、人力资源预算、体系审核、猎头合作、人力资源软件选型、人力资源规划、经营计划与预算。本书是作者12年企业HR从业经历的全面总结适合企业人力资源部专员、主管、副经理、部门经理、总监等阅读也可供本科生、研究生等作为参考书。\n划线\n\n在企业中人力资源管理具体做什么、怎么做。这个问题很容易被模块化为人事、招聘、培训、薪资、考核五大模块以及岗位、HR规划两大基础。\n\n\nHR人力资源人力资源部人力资源专业人员。HRM人力资源管理人力资源部经理。HRD人力资源开发人力资源总监。HRVP人力资源副总裁。HRBP人力资源业务合作伙伴派驻到各业务部门的HR。HR Unit人资单位人力资源部门。\n\n\n新员工报到入职当天先由人力资源部按照正常流程办理入职手续。可能包括提交核对身份证、相关证件签订劳动合同领取门禁卡饭卡、员工牌开通公司邮箱、办公系统OA账号办理工资卡发放员工手册、电脑、必要的办公用品等。可通过邮箱发放通讯录请新员工去OA下载并自学公司规章制度、财务报销流程等还可以直接把职位说明书发给他。然后人力资源部经理或直接主管找新员工谈话。除了表示欢迎还要交代他尽快熟悉情况包括公司、本部门、本岗位的情况。\n\n\n第一种意思熟悉办公环境。\n\n\n第二种意思熟悉人头。\n\n\n第三种意思熟悉公司规章制度。\n\n\n第四种意思熟悉工作情况。\n\n\n总之HR新手的工作可以概括为办事跑腿打电话录数据做表单。\n\n\n每做一件事情之前都要想一想依据法规政策公司内部规章制度是什么需要准备哪些材料、是否齐全相关领导、岗位人员是否签字确认投入\n\n\n所以直接主管在布置任务时要把意图讲解、交代清楚并向其确认我刚才提到的事情、任务你再重复下有没有问题新手也要在领任务时多问一句领导主管您刚才交代的任务我理解是这样的对吗这就可以在源头上避免方向上的偏差。\n\n\n甚至在晚上或周末时也可以做些额外的工作。现在的工作节奏快新手没有在额外时间投入准备在8小时内把事情做完有时是不现实的而经过阶段性的工作历练在工作中学习熟手是可以在8小时内把工作基本做完的。\n\n\n一个成功的人需要四种人来帮助他高人指点、贵人相助、爱人激励、小人监督\n\n\n[插图]\n\n\n1假设你所在的部门下设6个科你是某科的科员在你们科里除了科长之外大家公认你的业务能力最强。有一天部门经理交给你一份刚收到的会议通知让你去参加某个会议。请你谈谈从你接到通知那一刻到参加会议前你会做些什么2如果你入选了但你的岗位级别定得较低而你的主管在学历、资历、能力等方面都不如你你该怎么办3请你说说与领导相处和与同事相处的不同点。4你和你的上司有过意见不一致的情况吗如果有且你觉得自己理由充分你会据理力争吗如果不会为什么你是否担心今后他给你“穿小鞋”5企业管理人员的选择可以采用外部招聘和内部提升两种方式你认为各有何优缺点6面对客户除工作之外的要求如暗示要财务旅游、招待你如何对待7你管理的员工及时处理了工作中发生的紧急情况但违反了规章制度事后你会怎么办8请你为我们这次面试做个小结或提个建议好吗你对我们几个面试人员有什么看法和建议9原单位的领导对你的离开会持什么态度会不会挽留你10请用三个词评价你自己考虑半分钟\n\n\n1请谈谈你现在的工作情况和工作业绩。或在你最近的工作中最突出的业绩是什么2你认为现在的工作对你的发展有何影响你为什么想换工作对于这个岗位你有哪些优势和不足你打算怎样弥补不足3你怎样理解你所应聘的岗位你觉得如果我们录用你你能为我们带来的最直接的效益是什么4你需要多长时间来适应一个新工作岗位最难处理的是什么事情为什么5你最富有创造性的工作成果是什么6对你而言“成功”有何含义在你以前的工作经历中什么事令你最有成就感7最不喜欢怎样的工作觉得自己最大的失败是什么从中吸取了哪些教训\n\n\n1你为什么应聘我们公司你对我们公司有哪些了解你最看好公司哪些方面2你向往怎样的工作环境欣赏怎样的领导风格最反感怎样的领导风格3你觉得至今为止什么事情或什么人对你的影响最大如何影响你为什么4你平时最喜欢什么休闲活动最喜欢哪部文学作品或者哪个人物为什么5请结合自己的情况谈谈你对公司晋升制度的建议6你是如何看待事业和家庭之间的关系的平时周末做什么如经常需要周末加班会有什么问题为什么7在你看来当今最优秀的或最成功的企业是哪一家为什么请考虑一分钟8你选择工作时薪酬的重要性排在第几位排在第一位的是什么为什么\n\n\n第一章总则。介绍部门职能说明书的使用、岗位职责说明书的使用、名称定义。第二章公司组织结构图。第三章部门职能说明书。包括13个部门。第四章岗位结构。包括董事会机构岗位结构图、集团职能部门岗位结构图。第五章岗位职责说明书。包括63个岗位。\n\n\n1A猎头公司的寻访流程包括6个阶段需求分析、企业了解、综合分析、寻访猎取、人才推荐、跟踪服务具体见表17.1。表17.1 猎头寻访流程[插图]\n\n笔记\n书评\n点评"},"Personal/Book/经济理财/十分钟冥想":{"title":"十分钟冥想","links":[],"tags":["阅读/经济理财-理财","阅读/笔记"],"content":"\n简介\n\n书名《十分钟冥想》\n作者 安迪·普迪科姆\n分类 经济理财-理财\nISBN9787111639824\n出版社机械工业出版社\n\n概述\n冥想是一种奇妙的技能它有改变我们人生的潜力但是怎样运用这种技能则取决于你自己。随着媒体对冥想和正念的报道越来越多许多人似乎急于确定冥想的用途。事实上你只有确定了如何用它你才能确定它的用途。在学骑自行车的时候你所了解的是如何骑车而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具有些人用它跟朋友闲逛还有极少数人可能以它为终身事业。对所有人来说技能是一样的安稳地坐在车座上别掉下来。所以虽然别人可以教你如何骑车但骑车对你而言到底意味着什么你要拿它做什么以及它怎样才能最符合你的生活方式这完全取决于你自己。冥想技能也是如此你可以将它应用到生活中的任何方面它的价值取决于你赋予它的价值。\n划线\n\n你上一次坐下来安静不动不分心不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰没有任何你需要思考和解决的事情是什么时候\n\n\n在正念环境中冥想不是要去阻止想法、控制心灵。它是一个过程在这个过程中我们放弃控制不插手不介入学会以被动的方式集中注意力同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手容许心灵以自己的节奏、自己的方式展开你才能找到真正的头脑空间。\n\n\n你知道如果你坐上飞机从那些云的一端穿过另一端就没有阴云而只有蓝色的天空了。就算有大片阴沉沉的乌云蓝色的天空也始终存在。\n\n\n我得到了这样一种理念天空总是蓝的。云相当于我们的思想当心灵忙于这些想法的时候蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何心灵的深层本质就像蓝色的天空一样并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候云会变得更加阴沉更令人烦扰。也许整个天空中只有那么一个想法然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走而是搬把椅子到花园里坐看云卷云舒。有时候蓝色的天空会穿过阴云展露出来令人备感美好。如果我能耐心地坐在那里不过分执着于那些阴云那么蓝色的天空会显露得更多。\n\n\n。最重要的是你可以想象心中有一片始终宁静、始终澄澈的区域想象心中有一片你随时都可以依归的地方想象无论生活中发生什么事心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事就指望它突然静静地在某个地方站定因此当你跟这匹野马也就是你的心灵一起坐下来的时候你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上相反要给你的心灵一点时间让它安定下来放松一点。你急什么呢”\n\n\n关注它的同时试着温和地将它分享给他人。同样如果你的注意力集中在令人不快的感受上那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的必将浮上来\n\n\n就情感而言凡是被压制的必会再浮上来。也许它会突出到表面来就像情感本身一样也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央即一块开放田野的中央。现在缰绳的一端系着这匹马另一端在你手里。不过缰绳是松弛的这匹马有它所需要的一切空间它并没有觉得被困住或者受到约束\n\n\n你有没有注意过当你真正专注于某个事物的时候你的心灵会变得多么平静你有没有注意过即便你的心灵之前还凌乱如麻但是一旦专注于自己喜欢做的事情并且全身心地沉浸在那项活动中时心灵会开始安定下来会感到非常宁静\n\n\n所以对任何可能会令人分心的事物进行限制正是修习开始的第一步。\n\n\n当心灵像这样被完全扰乱时我们就几乎不可能看清正在发生的事也不可能看到表面之下隐藏着什么。\n\n\n如果要对这些让我们的生活变得既复杂又丰富的感受和情绪进行研究那么我们需要使水面足够平静因为只有这样我们才能看到它们。\n\n\n在那个时候似乎一切都被愤怒染上了色彩。我不知道你有没有过这种体验感觉就像是所有从脑海中闪过的想法都带上了这种愤怒底色这种底色改变了你看待周围世界的视角。\n\n\n奇怪的是与此同时我好像开始不那么专注于自己的那些想法而更多地开始专注于自己手头的活。虽然我同意用剪刀来剪草不见得每个人都喜欢然而剪了一会儿之后我发现这个过程其实可以使人平静。事实上这个过程本身就成了一种冥想过程。\n\n\n“你的心灵就是这个样子。你看到了这些陷阱但是惯性太强大了你没法阻止自己掉进去。但是\n\n\n“如果你分心走神了那就不是冥想了。只有在你不分心不走神的时候才是冥想。没有好的冥想或者坏的冥想之说只有分心和不分心之说以及觉醒和不觉醒之说。”事实上他常常把冥想比作去剧院\n\n\n你甚至会被台上的故事所激发坐在那里计划着如何向你5年来一直想告白的人告白。\n\n\n冥想根本不起作用。我感觉糟透了。进来的时候我心情还好而现在我感觉心情很差那么冥想的意义何在呢\n\n\n我们其实很少能做到身心的时空合一。\n\n\n理念是不要试图去阻止想法而要顺其自然任由想法在你完全觉醒的状态下来来去去。\n\n\n跟非冥想者相比冥想者的大脑中管理痛苦和情感的区域要更厚实\n\n\n我们中有多少人一直都是这样生活的沉浸在对过去的回忆和对未来的规划中如此全身沉浸在思考中而完全没有意识到当\n\n\n无论你在做什么它就在这里它就在普通平常的日常活动中如就在你吃三明治的动作中就在你喝水的动作中就在你洗碗的动作中……这就是正念、心在、觉醒的要义所在。\n\n\n我们对身体的运动如此熟悉以至于在跑的时候根本不需要太专注。正因为这一点心灵往往很容易游离。\n\n\n研究正念有效性的研究者发现哪怕参与者每天只冥想很短的时间只做了5天就有更多血液流向他们大脑中帮助控制情感和行为\n\n\n冥想只有在你去做的时候才会起作用只有当你坐下来冥想的时候你才会看到它的好处\n\n\n冥想的最佳时间是早上醒来的第一时间\n\n\n他们不断地把冥想加入下一个“待办事项清单”中结果却是“未完成”状态。他们用来减轻自己压力的事情反倒不知怎么成了他们的另一个压力来源。这可不是冥想的目的\n\n\n研究冥想和正念的好处的神经科学家发现了重复的重要性。他们说日复一日地做冥想练习这个简单的举动就足以促使大脑做出积极的改变。事实上他们认为这对于建立新的突触关系和神经路线来说极其重要。\n\n\n某一天你登上一列拥挤的火车却没有为之感到过于困扰而另一天同样拥挤的列车却好像触发了你的各种情绪。你会很清楚地意识到并不是外在的事物给我们带来了最大的麻烦而是我们心灵里面的事物给我们带来了困扰——幸好心灵里的这些东西是可以改变的。留意视角在每时每刻的转变这会为你的日常冥想提供强有力的支持。\n\n笔记\n\n“天空总是蓝的。”\n\n💭 生活总是美好的\n\n现在想象一下你将石头一块接一块地扔进水中看看整个水面同时被搅动起来的情景。当水面变成这个样子的时候你几乎就不可能看到水里的任何东西更不用说看见水底的东西\n\n💭 静心\n\n如果我一门心思专注在一件事上那么我不可能同时分心到另一件事上。因此在没有刻意忽略或抗拒内心想法的情况下当我的心思专注在别处的时候这些想法自然地自行消失了。\n\n💭 活在当下,体验内心的宁静和愉悦\n💭打水即是打水劈柴即是劈柴烧饭即是烧饭\n\n以正念的形式将觉醒应用到日常生活的杂务中。\n\n💭 正念即是专注力\n\n行走是一种确定的、受习惯驱使的行为它几乎不需要专注力。\n\n💭 潜意识\n\n冥想只有在你去做的时候才会起作用只有当你坐下来冥想的时候你才会看到它的好处\n\n💭 实践是检验真理的唯一标准\n书评\n点评"},"Personal/Book/经济理财/半小时漫画股票实战法":{"title":"半小时漫画股票实战法","links":[],"tags":["阅读/经济理财","阅读/笔记"],"content":"简介\n\n书名《半小时漫画股票实战法》\n作者 财经杂质\n分类 经济理财-理财\nISBN9787545552140\n出版社天地出版社\n\n概述\n任何一个可以在股市稳定盈利的人背后都有一套自己的交易系统。本书漫画主角王老师是个基层职员他收入平平生活普通。但他靠炒股实现了人生大翻转个人资产超过5亿元完全实现财务自由每天工作4小时不需看人脸色在全世界多个国家拥有多套海滨度假别墅而且夫妻恩爱……王老师说“要不是股市我们这种人将一事无成日子也过得紧巴巴更别妄想住别墅、开大奔了。”那么王老师是怎么从血本无归摸索到自己的固定交易系统的呢本书从指标、均线、成交量、盘口、战法、选股这6个方面复盘了王老师的成功过程。其中既有基础知识、又有实操技巧搞笑的漫画配上风趣的语言读者在轻松阅读中就完成了知识积累可谓实战扫盲利器非常适合自学者。\n划线\n\n单个股票短时间内暴涨暴跌时有发生按图索骥的技术推导和预测会完全失效但是在整体市场长周期的完整趋势中逆转的意义仍然不容小觑。\n\n\n因为执行力远比对错更重要对错只是让你心动的过客执行力才是伴你一生的另一半。\n\n笔记\n书评\n点评"},"Personal/Book/经济理财/小米创业思考":{"title":"小米创业思考","links":[],"tags":["阅读/经济理财-商业","阅读/笔记"],"content":"简介\n\n书名《小米创业思考》\n作者 雷军 徐洁云\n分类 经济理财-商业\nISBN9787521745276\n出版社中信出版集团\n\n概述\n雷军首部作品完整解析创办和经营小米的商业思考。 雷军系统梳理30年创业心法和经营哲学深度复盘“小米模式”认为取得持续成功的核心在于只干了一件事坚持“互联网+制造”路线,推动效率革命,实现用户利益和经济效率的最 大化。 雷军在书中首度全面公开包括产品三大铁律、互联网七字诀、高效率模型、爆品模式、生态链要素等,涉及管理、投资、工作等多维度经验,为创业者和管理者提供借鉴和指导,也可以为普通人提供持续精进的头部思维。\n划线\n\n我的职业生涯经历了30多年的沉浮摔打\n\n\n商业的目的是什么如何让商业实现最大化的现实意义我的答案是效率。它能给最多的人带来最大化的美好幸福感。\n\n\n互联网作为技术工具没有善恶对错但互联网理想、精神和方法从互联网出现的第一天开始就是为了高效、透明、公平和普惠。\n\n\n在我看来互联网终于脱离了幼儿期开始走向青春期真正走入苍茫人世为所有人、所有事赋能。\n\n\n数据属于用户\n\n\n人家三顾茅庐我可以三十顾茅庐不管什么办法搞得定人才的就是好办法。\n\n\n经过认真研究和讨论我们发现在智能手机刚起步的当下打电话、发短信、通讯录和桌面是人们最常用的功能我们只要集中精力专注把这4个核心功能模块做好做透就行。一个极其复杂的系统工程就这样被我们高度简化了。\n\n\n用户的参与加上互联网开发模式让MIUI团队实际上拥有了一支10万人规模的产品开发团队让MIUI成了体验打磨最细、改进最快的手机操作系统被人们称为“活的系统”。\n\n\n从程序员到管理者从创业者到投资人从互联网到硬件都是认知结构和人生阅历的巨大翻新。这几次重大的蜕变有的是被动的应变有的是主动的选择。但无论哪一种都需要无畏的勇气、坚定的意志、超强的学习能力以及对抗巨大痛苦的韧性。\n\n笔记\n\n永远相信美好的事情即将发生\n\n💭 永远相信美好的事情即将发生\n\n“答案在风中飘荡”。一路求索关于商业思考不同时期的答案一直在我的脑海中回响飘荡。\n\n💭 不同的时期,不同的环境,不同的答案\n\n我始终坚信互联网应该是尊重人的而不是束缚人的互联网应该是解放生产力的推动思维和技术动力而不是以邻为壑的割裂藩篱\n\n💭 我想点名小程序哈哈哈\n\nMIUI成了全球第一个每周更新的操作系统。\n\n💭 敏捷开发\n书评\n点评"},"Personal/Book/经济理财/底层逻辑:半秒钟看透问题本质":{"title":"底层逻辑:半秒钟看透问题本质","links":[],"tags":["阅读/经济理财-管理"],"content":"简介\n\n书名《底层逻辑半秒钟看透问题本质》\n作者 张羽\n分类 经济理财-管理\nISBN9787505748392\n出版社中国友谊出版公司\n\n概述\n2个5寸的披萨肯定会大于1个9寸的披萨只要埋头苦干做出业绩迟早会被提拔城市基础设施按照人口数量直接配比公司销售业绩越好存活期就会越长“底层逻辑”告诉你这些观点需要质疑。所谓底层逻辑就是从事物的底层、本质出发寻找解决问题路径的思维方法。底层逻辑越坚固解决问题的能力也就越强。本书从结果逻辑、学习逻辑、团队逻辑等10个维度出发用“手术刀”一样的文字帮助我们跳出思维的陷阱和盲目勤奋的误区将实际工作中的问题放于困惑的熔炉中反复冶炼提炼出知识背后的知识、方法背后的方法。《底层逻辑》将帮助你重新思考生命、认识自身、了解自己的工作与生活并告诉你看似复杂的世界其实充满简单的逻辑只要跳脱思维陷阱打破学科限制就可以重新看清周遭的一切。\n\n划线\n\n具体表现在他们缺乏长远的职业发展规划没有脚踏实地与全力以赴的心态也不想为了一份事业便废寝忘食并永不言弃。当然他们也拿不出不可替代的真本事。\n\n\n优秀的人如果不够努力必然竞争不过天赋一般却十分勤奋的人。\n\n\n“表演努力”是什么呢就是有的人看着特别勤奋地工作埋头苦干一分钟也不闲着其实碰上关键问题的时候他却解决不了。他的努力更像是一种演出根本没有深入工作之中以求获得成效。\n\n\n当你有一天把“学习比面子更重要”这句话作为自己的工作原则时你才能在竞争中立于不败之地。\n\n\n躺在学历上睡大觉早晚都会闪了腰\n\n\n过去的经验对我们来说既是资产也是负债\n\n\n这时我们多数人的想法是这样的1既定目标完成了我要好好休息其他事与我无关2干得再多老板也看不见为何多此一举呢3我已经很努力了我对自己很满意要对自己好一点4钱是赚不完的但时间是自己的享受生活吧\n\n\n任何面子的后面都是人情但人情的后面是权力和利益的运行规则。\n\n\n仔细探究你会发现工作中的人情也很简单符合他的利益你就是好朋友违背他的利益那你就是讨厌鬼。\n\n\n。当利益驱动力消失时再坚固的人情也会变得一文不值了。\n\n\n有些国企之所以不死不活有个重要的原因就是严重缺乏内部的竞争干好干坏一个样人们没有危机感企业自然如同一潭死水。\n\n\n不过即便是自己最擅长的工作在与人合作交流时也不能像上面那样表现得过于自信必须给事情留有余地体现出一种谦虚和谨慎的态度。\n\n\n我们每个人在工作中都有自己的局限性缺经验缺钱缺人脉缺运气等碰到挫折是难以避免的。\n\n\n2019年任正非的论断得到了验证当美国宣布中止对华为提供芯片、禁止华为使用谷歌的安卓系统时华为立刻公布了自己早已准备多年的B计划推出了自己的鸿蒙操作系统。\n\n\n一个有能力的强者他总能在关键时刻准备多套有效的方案以便应对种种突发情况使自己立于不败之地。\n\n\n我需要的是一个对工作有想法和方法而且敢说敢干的人而这些是要你来亲口告诉我的用行动证明出来的不能等我问。如果你想在公司有所发展消极等待与一味默默地工作都是不可取的你要努力找机会让我明白你的想法知道你工作的思路和结果这才是积极的做法懂了吗”\n\n\n在请假的方式上也应用请求的方式批准而不是让上司听起来就像通知坚决避免通知式的请假更不要妄图既请了假还不损失工资。\n\n\n在这个过程中有一条原则是我们要牢记的能简单就不要复杂能三言两语就不要长篇大论能务实就不要务虚。老板的时间是公司的稀缺资源他很忙没有精力关注你“如何做”大部分时间内他只想知道你“做得如何”。\n\n\n我说“都说新官上任三把火新上司通常会对现有的工作方式进行调整或变更这个时候你要做的不是提意见也不是告诉他以前的上司是如何做的而是带动其他的同事积极配合。”\n\n\n现代管理中我们正面临“全面预算管理”的问题这已经成为一家企业能否在激烈的竞争环境中有所发展的重要模式。\n\n笔记\n\n我说“你填写申请书是表明一个愿意学习的态度我一高兴加一个名额也有可能就算这次不能加上让我知道你有积极进步的愿望总不是什么坏事吧下次我也会想着你的。”\n\n💭 态度很重要\n\n我需要的是一个对工作有想法和方法而且敢说敢干的人而这些是要你来亲口告诉我的用行动证明出来的不能等我问。如果你想在公司有所发展消极等待与一味默默地工作都是不可取的你要努力找机会让我明白你的想法知道你工作的思路和结果这才是积极的做法懂了吗”\n\n💭 🤦‍♂️🤦‍♂️🤦‍♂️\n\n上司都有一种权威心理他们都希望得到员工的尊重和敬畏而且上司做的决定要合乎公司的规定不能对你个人搞特殊化。\n\n💭 爹味\n书评\n点评"},"Personal/Book/艺术/江湖丛谈(注音注释插图本)":{"title":"江湖丛谈(注音注释插图本)","links":[],"tags":["阅读/艺术","阅读/笔记"],"content":"简介\n\n书名《江湖丛谈注音注释插图本》\n作者 连阔如著 贾建国著 连丽如整理\n分类 艺术-民艺\nISBN9787101138504\n出版社中华书局有限公司\n\n概述\n《江湖丛谈》可谓一本不可多得的奇书。它是我国现存仅有的一部全面介绍江湖行当、行话和内幕的书。作者是已故评书大家连阔如。20世纪30年代他以云游客的笔名在北平《时言报》发表长篇连载《江湖丛谈》。1938年由时言报社结集出版共三集。这本书除了介绍北平天桥、天津三不管等地的变迁以及艺人小传、艺人生活状况外还以大量的篇幅着重记述和揭露了清末至20世纪30年代这一时期江湖行当的内幕以及危害社会的种种骗术劝诫人们不要贪便宜上当受骗。\n划线\n\n第一身为江湖中人而又内心纯正所谓“出污泥而不染”熟悉江湖内幕和行话以及一切行规。\n\n\n父亲只上了半年私学、两年小学十二岁就当学徒进过北京的首饰楼、照相馆天津的杂货铺、中药店到烟台、大连做过小买卖摆过卦摊饱尝了人世间的酸、甜、苦、辣。\n\n\n买卖人有三不卖不够本不卖赔钱不卖不赚钱不卖。\n\n\n到了乡间不论是哪个地方要是有人提倡在那里创立个集场或是在那里创办个庙会为首开办的人得先邀生意档子吸引观众。兴隆方面要是没有生意档子参加任他办理得多善也吸引不住人儿\n\n\n远来的和尚会念经”。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/Flask-Web开发基于Python的Web应用开发实战第2版":{"title":"Flask Web开发基于Python的Web应用开发实战第2版","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《Flask Web开发基于Python的Web应用开发实战第2版》\n作者 米格尔·格林贝格\n分类 计算机-编程设计\nISBN9787115489456\n出版社人民邮电出版社\n\n概述\n本书共分三部分全面介绍如何基于Python微框架Flask进行Web开发。第一部分是Flask简介介绍使用Flask框架及扩展开发Web程序的必备基础知识。第二部分则给出一个实例真正带领大家一步步开发完整的博客和社交应用Flasky从而将前述知识融会贯通付诸实践。第三部分介绍了发布应用之前必须考虑的事项如单元测试策略、性能分析技术、Flask程序的部署方式等。第2版针对Python 3.6全面修订。\n划线\n\nFlask自开发伊始就被设计为可扩展的框架它具有一个包含基本服务的强健核心其他功能则可通过扩展实现\n\n\n这两个过程分别称为业务逻辑和表现逻辑。\n\n\n不过近年来文档数据库和键值对数据库成了流行的替代选择这两种数据库合称NoSQL数据库。\n\n\nNoSQL数据库一般使用集合代替表使用文档代替记录\n\n\n选择数据库框架时不一定非得选择已经集成了Flask的框架但选择这样的框架可以节省编写集成代码的时间。使用集成了Flask的框架可以简化配置和操作所以专门为Flask开发的扩展是你的首选。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/IT基础架构系统运维实践":{"title":"IT基础架构系统运维实践","links":[],"tags":["阅读/计算机-理论知识","阅读/笔记"],"content":"简介\n\n书名《IT基础架构系统运维实践》\n作者 赵旻\n分类 计算机-理论知识\nISBN9787111597780\n出版社机械工业出版社\n\n概述\n本书涵盖了数据中心规划、基础服务、系统运维等多个方面。作者以十多年的经验告诉各位读者弯路一定是会走的但是如何能够尽早避免并通过行之有效的方法进行解决才是运维管理的王道。虽然IT界一直在不停地变化但是运维的核心精神并没有变。本书就是作者多年的运维经验的积累和沉淀总结出一套颇具心得的IT基础架构管理法。\n划线\n\n第一要消灭异构形式。不论是通信协议、接口规范抑或实现方式最忌讳的事情就是大家各玩儿各的。\n\n\n第二要消灭重复组件。底层功能的实现在业界大多有成熟的解决方案应当尽可能地去复用或者在此基础上进行改进而不是重复造轮子。\n\n\n第三要消灭紧耦合关系。解耦工作要从不同的角度入手子系统和模块的紧耦合因素是不同的。\n\n\n一般来说送货之前都要提前看天气预报尽量避开可能降雨的日子。\n\n\n建议大家平时要多积累一些周边知识做一名T型人才。\n\n\n按照应用的角度划分我们可以把整个空间分为三个部分——生产区、非生产区和基础设施。\n\n\n我们还可以将这三个空间进一步细分成九种不同类型的区域。详细情形如图3-1所示。\n\n\n因此数据中心低于三层的倾向于选低层的机房反之就尽可能地挑高层使用。\n\n\n在小地方徘徊会陷入一个无底洞。如果业务A要考虑那么业务B、业务C和业务D呢这样一弄自己就把自己给搞死了。\n\n\n让业务地址和带外管理地址之间的对应关系清晰化实现相互间的直接转译。\n\n\n经典的三层网络架构是由核心、汇聚和接入三部分组成的。\n\n\n一款服务器产品而言我们可以从三个角度去评估它——质量、功能和服务。\n\n\nCMDB是一切运维的基石存储了所有日常工作中必不可少的、有价值的信息所有上层系统的完美运行都离不开它的支撑。就某种程度上而言CMDB模型的能力成熟度决定了运维团队的水平。运维团队的管理者应当对此给予足够的重视。CMDB在建设过程中需要分层设计不同层级的CMDB交由不同的团队去构建。在表结构设计的时候要充分考虑今后业务使用的需求尽可能预留出足够的扩展空间相关数据要确保在第一时间存入CMDB不能在后期依靠人工补救。\n\n\n~—代表用户家目录。·{}/[]/—在Shell操作时具有合并同类项、标识界限和修改执行顺序的特殊功能。·>/>>—输出重定向。·</<<—输入重定向。·&—将命令置于后台运行。·&&—与连接符,用于连接前后两条命令。当前面的命令返回成功,后面的命令才会执行。·||—或连接符,用于连接前后两条命令。当前面的命令返回失败,后面的命令才会执行。·;—无条件连接符,用于连接前后两条命令。两条命令会按照顺序无条件地相继执行。·|—管道符,用来连接前后两条命令。前一条命令的输出结果将作为后一条命令的输入参数来使用。·$—美元符,用于求取变量的值。·`—反引号是命令替换符反引号内的字符会被Shell当作命令来执行并返回执行结果。·—叹号是histroy替换符叹号后面加数字代表执行第几条历史命令双叹号则代表执行最后一条历史命令。\n\n\n16.2.2 从现在开始就要改变自己你不改变自己,就要被别人改变。如果你觉得难受了,觉得疼了,哭闹是没用的,请当下立即做出改变。曾经的我也有过类似的困惑,所以作为过来人,我想给大家一些好的建议。\n\n\n1.放大格局\n\n笔记\n书评\n\n✨18 年出版,目前来看参考价值有限。 整本书专业程度一般,感觉更多是像一本个人多年工作笔记,而对于行业未来的发展方向以及趋势阐述有限。 不过最后的经验建议还是值得细细品味的,毕竟计算机行业的发展日新月异。 我们一定要努力拥抱变化 💪\n\n点评"},"Personal/Book/计算机/Linux命令行与shell脚本编程大全第4版":{"title":"Linux命令行与shell脚本编程大全第4版","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《Linux命令行与shell脚本编程大全第4版》\n作者 理查德·布卢姆 克里斯蒂娜·布雷斯纳汉 著\n分类 计算机-编程设计\nISBN9787115592514\n出版社人民邮电出版社有限公司\n\n概述\n这是一本关于Linux命令行与shell脚本编程的系统性教程主要包括四大部分 Linux命令行、shell脚本编程基础、高级shell脚本编程以及创建和管理实用的脚本。本书这一版针对Linux系统的新特性进行了更新不仅涵盖了详尽的动手教程和现实世界中的实用信息还提供了与所学内容相关的参考信息和背景资料。通过本书的学习你能轻松写出自己的shell脚本。 本书适合Linux系统管理员及相关开发人员阅读。\n划线\n\nLinux系统可划分为以下4部分。·Linux内核·GNU工具·图形化桌面环境·应用软件\n\n\nLinux内核采用虚拟文件系统virtual file systemVFS作为和各种文件系统交互的接口\n\n\n构成完整Linux系统所需要的4个关键组件\n\n\n我们将完整的Linux系统包称为发行版。\n\n\n命令echo$0会显示当前shell的名称提供必要的参考。\n\n\nbash shell中有两种环境变量。·全局变量·局部变量\n\n\n全局环境变量对于shell会话和所有生成的子shell都是可见的。局部环境变量则只对创建它的shell可见。\n\n\n可以使用env命令或printenv命令来查看全局变量\n\n\n你定义的局部变量用的是小写字母而系统环境变量用的都是大写字母。\n\n\n·/etc/profile·HOME/.bash_profile·HOME/.bashrc·HOME/.bash_login·HOME/.profile\n\n\n/etc/profile文件是系统中默认的bash shell的主启动文件。系统中的每个用户登录时都会执行这个启动文件。\n\n\n大多数Linux发行版只用这4个启动文件中的一两个。·HOME/.bash_profile·HOME/.bashrc·HOME/.bash_login·HOME/.profile\n\n笔记\n书评\n点评"},"Personal/Book/计算机/Linux是怎样工作的":{"title":"Linux是怎样工作的","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《Linux是怎样工作的》\n作者 武内觉 著\n分类 计算机-编程设计\nISBN9787115581617\n出版社人民邮电出版社有限公司\n\n概述\n本书结合大量实验程序和图表通俗易懂地介绍了Linux操作系统的运行原理和硬件的基础知识涉及进程管理、进程调度器、内存管理、存储层次、文件系统和外部存储器等。实验程序使用C语言和Python编写读者可亲自动手运行程序来确认系统的行为。另外以图解的方式介绍各知识点简明且直观能够帮助读者加深理解。读者只需对Linux基本命令有所了解即可轻松阅读。 本书适合应用程序开发人员、系统设计师、运维管理人员和技术支持人员等人士阅读。\n划线\n\n负责任意一层的人只需了解比他负责的那一层更深的一层就可以了。\n\n\n●中间件将对大部分应用程序通用的功能分离出来以辅助应用程序运行的程序例如Web服务器、数据库系统\n\n\n[插图]图3-2 启动另一个程序的流程下面来详细说明这一流程。首先,读取可执行文件,以及创建进程的内存映像所需的信息。可执行文件中不仅包含进程在运行过程中使用的代码与数据,还包含开始运行程序时所需的数据。●包含代码的代码段在文件中的偏移量、大小,以及内存映像的起始地址●包含代码以外的变量等数据的数据段在文件中的偏移量、大小,以及内存映像的起始地址\n\n笔记\n书评\n点评"},"Personal/Book/计算机/Python工匠案例、技巧与工程实践":{"title":"Python工匠案例、技巧与工程实践","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《Python工匠案例、技巧与工程实践》\n作者 朱雷\n分类 计算机-编程设计\nISBN9787115584045\n出版社人民邮电出版社有限公司\n\n概述\n本书基于受欢迎的“Python工匠”系列开源文章。全书从工程实践角度出发通过剖析核心知识、展示典型案例与总结实用技巧帮助大家系统进阶Python写好工程代码做好实践项目。 本书共计13章分为五大部分变量与基础类型、语法结构、函数与装饰器、面向对象编程、总结与延伸涵盖Python编程的方方面面。本书的写作方式别具一格核心知识点都会通过三大板块来阐述基础知识、案例故事、编程建议。其中基础知识帮助大家快速回顾Python基础案例故事由作者经历的编程项目与案例改编而来兼具实战性与趣味性编程建议以大家喜闻乐见的条目式知识点呈现短小精悍可直接应用于自己的编程实践中。\n划线\n\n即便两个人实现同一个功能最终效果看上去也一模一样但代码质量却可能有着云泥之别。\n\n\n我前前后后读过一些书——《代码大全》《重构》《设计模式》《代码整洁之道》——毫无疑问它们都是领域内首屈一指的经典好书我从中学到了许多知识至今受益匪浅。\n\n\n编程是一个通过代码来表达思想的过程。\n\n\n变量与注释是作者表达思想的基础是读者理解代码的第一道门它们对代码质量的贡献毋庸置疑。\n\n\n除了上面的普通解包外Python还支持更灵活的动态解包语法。只要用星号表达式*variables作为变量名它便会贪婪[插图]地捕获多个值对象并将捕获到的内容作为列表赋值给variables。\n\n\n在常用的诸多变量名中单下划线_是比较特殊的一个。它常作为一个无意义的占位符出现在赋值语句中。_这个名字本身没什么特别之处这算是大家约定俗成的一种用法。\n\n\n相比编写Sphinx格式文档我其实更推荐使用类型注解因为它是Python的内置功能而且正在变得越来越流行。\n\n\n因此我强烈建议在多人参与的中大型Python项目里至少使用一种类型注解方案——Sphinx格式文档或官方类型注解都行。\n\n\n计算机科学领域只有两件难事缓存失效和命名。\n\n\n描述代码为什么要这么做而不是简单复述代码本身。\n\n\n指引性注释。这种注释并不直接复述代码而是简明扼要地概括代码功能起到“代码导读”的作用。\n\n\n这些变化让整段代码变得更易读也让整个算法变得更好理解。所以哪怕是一段不到10行代码的简单函数对变量和注释的不同处理方式也会让代码发生质的变化\n\n\n喜欢把所有变量初始化定义写在一起放在函数最前面\n\n\n总是从代码的职责出发而不是其他东西。\n\n\n直接翻译业务逻辑的代码大多不是好代码。优秀的程序设计需要在理解原需求的基础上恰到好处地抽象只有这样才能同时满足可读性和可扩展性方面的需求\n\n\n定义一个临时变量”是诸多方式里不太起眼的一个但用得恰当的话效果也很巧妙。\n\n\n函数内变量的数量太多通常意味着函数过于复杂承担了太多职责。只有把复杂函数拆分为多个小函数代码的整体复杂度才可能实现根本性的降低。\n\n\n这样的代码就像删掉赘语的句子变得更精练、更易读。\n\n\n在编写了许多函数以后我总结出了一个值得推广的好习惯先写注释后写代码。\n\n\n在写出一句有说服力的接口注释前别写任何函数代码。\n\n\n在定义数值字面量时如果数字特别长可以通过插入_分隔符来让它变得更易读\n\n\nTrue和False这两个布尔值可以直接当作1和0来使用\n\n\nf-string格式化方式用起来最方便\n\n\n首先创建一个空列表然后把需要拼接的字符串都放进列表最后调用str.join来获得大字符串\n\n\n把数字字面量改成常量和枚举类型后我们就能很好地规避输入错误问题。同样把字符串字面量改写成枚举类型也可以获得这种好处\n\n\n如果需要验证某个“经验之谈”dis和timeit两个优秀的工具可以帮到你前者能让你直接查看编译后的字节码后者则能让你方便地做性能测试。\n\n\nPython里的字典在底层使用了哈希表hash table数据结构。当你往字典里存放一对key: value时Python会先通过哈希算法计算出key的哈希值——一个整型数字然后根据这个哈希值决定数据在表里的具体位置。\n\n\n集合只能存放可哈希对象\n\n\n当我们把某个对象放进集合或者作为字典的键使用时解释器都需要对该对象进行一次哈希运算得到哈希值然后再进行后面的操作。\n\n\n虽然都是返回结果但yield和return的最大不同之处在于return的返回是一次性的使用它会直接中断整个函数执行而yield可以逐步给调用方生成结果\n\n\n我们有时会过于喜欢用not关键字反倒忘记了运算符本身就可以表达否定逻辑。最后代码里会出现许多下面这种判断语句\n\n\n异常处理对于我来说就是一些不想做却又不得不做的琐事\n\n\n在Python世界里EAFP指不做任何事前检查直接执行操作但在外层用try来捕获可能发生的异常。如果还用下雨举例这种做法类似于“出门前不看天气预报如果淋雨了就回家后洗澡吃感冒药”。\n\n\nPython里的函数可以一次返回多个值通过返回一个元组实现。所以当我们要表明函数执行出错时可以让它同时返回结果与错误信息。\n\n\n新函数拥有更稳定的返回值类型它永远只会返回Item类型或是抛出异常。· 虽然我们鼓励使用异常,但异常总是会不可避免地让人“感到惊讶”,所以,最好在函数文档里说明可能抛出的异常类型。· 不同于返回值异常在被捕获前会不断往调用栈上层汇报。因此create_item()的直接调用方也可以完全不处理CreateItemError而交由更上层处理。异常的这个特点给了我们更多灵活性但同时也带来了更大的风险。具体来说假如程序缺少一个顶级的统一异常处理逻辑那么某个被所有人忽视了的异常可能会层层上报最终弄垮整个程序。\n\n\n上下文管理器功能强大、用处很多其中最常见的用处之一就是简化异常处理工作。\n\n\n除了应该避免抛出高于当前抽象级别的异常外我们同样应该避免泄露低于当前抽象级别的异常\n\n\n在数据校验这块pydantic模块是一个不错的选择。\n\n\n在编写代码时我们应当尽量避免手动校验任何数据。因为数据校验任务独立性很强所以应该引入合适的第三方校验模块或者自己实现让它们来处理这部分专业工作。\n\n\n可迭代对象不一定是迭代器但迭代器一定是可迭代对象· 对可迭代对象使用iter()会返回迭代器,迭代器则会返回其自身;· 每个迭代器的被迭代过程是一次性的,可迭代对象则不一定;· 可迭代对象只需要实现__iter__方法而迭代器要额外实现__next__方法。\n\n\n生成器generator利用其简单的语法大大降低了迭代器的使用门槛是优化循环代码时最得力的帮手。\n\n\nenumerate()是Python的一个内置函数它接收一个可迭代对象作为参数返回一个不断生成(当前下标,当前元素)的新可迭代对象。\n\n\n“修饰可迭代对象”是指用生成器或普通的迭代器在循环外部包装原本的循环主体完成一些原本必须在循环内部执行的工作——比如过滤特定成员、提供额外结果等以此简化循环代码。\n\n\nproduct()接收多个可迭代对象作为参数,然后根据它们的笛卡儿积不断生成结果:\n\n\n用product()优化函数里的嵌套循环\n\n\ntakewhile(predicate, iterable)会在迭代第二个参数iterable的过程中不断使用当前值作为参数调用predicate()函数并对返回结果进行真值测试如果为True则返回当前值并继续迭代否则立即中断本次迭代。\n\n\nfor循环和while循环后的else关键字代表如果循环正常结束没有碰到任何break便执行该分支内的语句。因此老式的“循环+标记变量”代码,就可以利用该特性简写为“循环+else分支”\n\n\n因为Python语言不支持“带标签的break”语句[插图]无法用一个break跳出多层循环。\n\n\n为了规避这个问题使用None来替代可变类型默认值是比较常见的做法\n\n\n当你要调用参数较多超过3个的函数时使用关键字参数模式可以大大提高代码的可读性。\n\n\n每个函数只返回一种类型变得更简单易用。\n\n\n适合返回None的函数需要满足以下两个特点1函数的名称和参数必须表达“结果可能缺失”的意思2如果函数执行无法产生结果调用方也不关心具体原因。\n\n\n除了“搜索”“查询”几个场景外对绝大部分函数而言返回None并不是一个好的做法。\n\n\n在编写函数时请不要纠结函数是不是应该只有一个return只要尽早返回结果可以提升代码可读性那就多多返回吧。\n\n\n为了简化函数调用让代码更简洁我们其实可以定义一个接收单个参数的double()函数让它通过multiply()完成计算def double(value): # 返回 multiply 函数调用结果 return multiply(2, value)# 调用代码变得更简单result = double(value)val = double(number)\n\n\n原来在使用re.sub(pattern, repl, string)函数时第二个参数repl不光可以是普通字符串还可以是一个可调用的函数对象。\n\n\n截至上一个问题小R所写的mosaic_matchobj()函数只是一个无状态函数。但为了满足新需求小R需要调整mosaic_matchobj()函数,把它从一个无状态函数改为有状态函数。\n\n\n闭包是一种非常有用的工具非常适合用来实现简单的有状态函数。\n\n\n权衡了这三种方案的利弊后\n\n\n别写太复杂的函数\n\n\nPython里的递归因为缺少语言层面的优化局限性较大。当你想用递归来实现某个算法时请先琢磨琢磨是否能用循环来改写。如果答案是肯定的那就改成循环吧。\n\n\n装饰器并不提供任何独特的功能它所做的只是让我们可以在函数定义语句上方直接添加用来修改函数行为的装饰器函数\n\n\n装饰器是一种通过包装目标函数来修改其行为的特殊高阶函数绝大多数装饰器是利用函数的闭包原理实现的。\n\n\n添加@wraps(wrapped)来装饰decorated函数后wraps()首先会基于原函数func来更新包装函数decorated的名称、文档等内置属性之后会将func的所有额外属性赋值到decorated上\n\n\n所以装饰器的优势并不在于它提供了动态修改函数的能力而在于它把影响函数的装饰行为移到了函数头部降低了代码的阅读与理解成本。\n\n\n1 运行时校验:在执行阶段进行特定校验,当校验通不过时终止执行。· 适合原因:装饰器可以方便地在函数执行前介入,并且可以读取所有参数辅助校验。· 代表样例Django框架中的用户登录态校验装饰器@login_required。2 注入额外参数:在函数被调用时自动注入额外的调用参数。· 适合原因:装饰器的位置在函数头部,非常靠近参数被定义的位置,关联性强。· 代表样例unittest.mock模块的装饰器@patch。3 缓存执行结果:通过调用参数等输入信息,直接缓存函数执行结果。· 适合原因:添加缓存不需要侵入函数内部逻辑,并且功能非常独立和通用。· 代表样例functools模块的缓存装饰器@lru_cache。4 注册函数:将被装饰函数注册为某个外部流程的一部分。· 适合原因:在定义函数时可以直接完成注册,关联性强。· 代表样例Flask框架的路由注册装饰器@app.route。5替换为复杂对象将原函数方法替换为更复杂的对象比如类实例或特殊的描述符对象见12.1.3节)。· 适合原因在执行替换操作时装饰器语法天然比foo = staticmethod(foo)的写法要直观得多。· 代表样例:静态类方法装饰器@staticmethod。在设计新的装饰器时你可以先参考上面的常见装饰器功能列表琢磨琢磨自己的设计是否能很好地发挥装饰器的优势。切勿滥用装饰器技术设计出一些天马行空但难以理解的API。吸取前人经验同时在设计上保持克制才能写出更好用的装饰器。\n\n\n私有属性是“君子协定”\n\n\n在Python里所有的类属性和方法默认都是公开的不过你可以通过添加双下划线前缀__的方式把它们标示为私有。\n\n\n和普通方法相比静态方法不需要访问实例的任何状态是一种与状态无关的方法因此静态方法其实可以改写成脱离于类的外部普通函数。\n\n\n使用@property装饰器你可以把上面的get_basename()方法变成一个虚拟属性,然后像使用普通属性一样使用它\n\n\n@property是个非常有用的装饰器它让我们可以基于方法定义类属性精确地控制属性的读取、赋值和删除行为灵活地实现动态属性等功能。\n\n\n在超过90%的情况下你能找到的合理的Python代码就如上所示没有任何类型检查想做什么就直接做。你肯定想问假如调用方提供的fp参数不是文件对象怎么办答案是不怎么办直接报错就好。示例如下。\n\n\n总结一下抽象类通过__subclasshook__钩子和.register()方法实现了一种比继承更灵活、更松散的子类化机制并以此改变了isinstance()的行为。\n\n\nsuper()使用的其实不是当前类的父类而是它在MRO链条里的上一个类。\n\n\n大多数情况下你需要的并不是多重继承而也许只是一个更准确的抽象模型在该模型下最普通的继承关系就能完美解决问题。\n\n\n元类控制着类的创建行为就像普通类控制着实例的创建行为一样。\n\n\n但继承是一种类与类之间紧密的耦合关系。让子类继承父类虽然看上去毫无成本地获取了父类的全部能力但同时也意味着从此以后父类的所有改动都可能影响子类。继承关系越复杂这种影响就越容易超出人们的控制范围。\n\n\n针对事物的行为建模而不是对事物本身建模。\n\n\n在多数情况下基于事物的行为来建模可以孵化出更好、更灵活的模型设计。\n\n\n即使B和A是同类那它们真的需要用继承来表明类型关系吗要知道Python是鸭子类型的你不用继承也能实现多态。\n\n\n多态polymorphism是面向对象编程的基本概念之一。它表示同一个方法调用在运行时会因为对象类型的不同产生不同效果。\n\n\nSOLID单词里的5个字母分别代表5条设计原则。· Ssingle responsibility principle单一职责原则SRP。· Oopen-closed principle开放关闭原则OCP。· LLiskov substitution principle里式替换原则LSP。· Iinterface segregation principle接口隔离原则ISP。· Ddependency inversion principle依赖倒置原则DIP。\n\n\n单一职责是面向对象领域的设计原则通常用来形容类。而在Python中单一职责的适用范围不限于类——通过定义函数我们同样能让上面的代码符合单一职责原则。\n\n\n这世间唯一不变的只有变化本身。\n\n\n虽然继承功能强大但它并非通往OCP的唯一途径。除了继承外我们还可以采用另一种思路组合composition。更具体地说使用基于组合思想的依赖注入dependency injection技术\n\n\n但是如果少了PostFilter抽象类当编写HNTopPostsSpider类的__init__方式时我就无法给post_filter增加类型注解了——post_filter: Optional[这里写什么?],因为我根本找不到一个具体的类型。\n\n\n但数据驱动也有一个缺点它的可定制性不如其他两种方式。举个例子假如我想以“链接是否以某个字符串结尾”来进行过滤现在的数据驱动代码就做不到。影响每种方案可定制性的根本原因在于各方案所处的抽象级别不一样。比如在依赖注入方案下我选择抽象的内容是“条目过滤行为”而在数据驱动方案下抽象内容则是“条目过滤行为的有效站点地址”。很明显后者的抽象级别更低关注的内容更具体所以灵活性不如前者。\n\n\nLSP认为所有子类派生类对象应该可以任意替代父类基类对象使用且不会破坏程序原本的功能。\n\n\n在Python 3.8版本里类型注解typing模块增加了一个名为“协议”Protocol的类型。从各种意义上来说Protocol都比抽象类更接近传统的“接口”。\n\n\n更丰富的接口协议意味着更高的实现成本也更容易给实现方带来麻烦。\n\n\n描述符descriptor是Python对象模型里的一种特殊协议它主要和4个魔法方法有关 get、set、delete__和__set_name。从定义上来说除了最后一个方法__set_name__以外任何一个实现了__get__、__set__或__delete__的类都可以称为描述符类它的实例则叫作描述符对象。\n\n\n现在你应该明白了一个对象的__del__方法并非在使用del语句时被触发而是在它被作为垃圾回收时触发。del语句无法直接回收任何东西它只是简单地删掉了指向当前对象的一个引用变量名而已\n\n\nTDDtest-driven development测试驱动开发是由Kent Beck提出的一种软件开发方式。在TDD工作流下要对软件做一个改动你不会直接修改代码而会先写出这个改动所需要的测试用例。TDD的工作流大致如下1写测试用例哪怕测试用例引用的模块根本不存在2执行测试用例让其失败3编写最简单的代码此时只关心实现功能不关心代码整洁度4执行测试用例让测试通过5重构代码删除重复内容让代码变得更整洁6执行测试用例验证重构7重复整个过程。\n\n\n你应该了解这些理论越多越好但是千万不要陷入教条主义。因为在现实世界里每个人参与的项目千差万别别人的理论不一定适用于你如果盲目遵从反而会给自己增加麻烦。\n\n笔记\n\n编程最初带给我们的快乐已悄然远去写代码这件事现在变得有些痛苦。更有甚者一想到项目里的烂代码每天起床后最想干的一件事就是辞职。\n\n💭 哈哈哈真实\n\n如果某个函数的圈复杂度超过10就代表它已经太复杂了代码编写者应该想办法简化。优化写法或者拆分成子函数都是不错的选择。\n\n💭 代码复杂度\n\n所以简单来说抽象就是一种选择特征、简化认知的手段。接下来我们看看抽象与软件开发的关系。\n\n💭 抽离出来普遍具有的特征现象\n\n当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子那么这只鸟就可以称为鸭子。\n——来自“鸭子类型”的维基百科词条\n\n💭 鸭子类型\n\n所有与数据模型有关的方法基本都以双下划线开头和结尾它们通常被称为魔法方法magic method。\n\n💭 魔法方法\n\n所以写单元测试不是浪费时间也不会降低开发效率。你在单元测试上花费的那点儿时间会在未来的日子里为项目的所有参与者节约不计其数的时间。\n\n💭 重要的单元测试\n\n不要掉进完美主义的陷阱。\n\n💭 不要让完美主义成为你的绊脚石!\n书评\n点评"},"Personal/Book/计算机/Python编程轻松进阶":{"title":"Python编程轻松进阶","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《Python编程轻松进阶》\n作者 阿尔·斯维加特 著\n分类 计算机-编程设计\nISBN9787115592422\n出版社人民邮电出版社有限公司\n\n概述\n本书分为三大部分共计17章。第一部分第12章介绍了基础知识包括如何配置开发环境和在网上寻求帮助。第二部分第314章介绍了Python编程的最佳实践、实用工具和技巧不仅涵盖了如何编写高质量的Python代码、什么是高级的Python语法、如何使用专业开发者所用的命令行工具还介绍了性能测量和大O算法分析并用游戏实例演示了什么是最佳实践。第三部分第15~17章介绍了面向对象的Python内容包括如何编写类、什么是类的继承以及Python独有的面向对象功能。\n划线\n\n在面对错误信息中的一大段技术性文本时很多程序员会下意识地选择忽略。但程序出错的原因就在其中我们需要用以下两个步骤找到它检查回溯信息[插图],以及在网上搜索错误信息。\n\n\n借助linter避免错误修复错误的最佳方式是压根儿不犯错。静态代码格式分析工具也称作linter是通过分析源代码来报告潜在错误的一类程序。\n\n\n使用timeit模块衡量性能\n\n\n使用enumerate()而不是range()\n\n\n使用with语句代替open()和close()\n\n\n用is跟None做比较而不用==\n\n\n在字典中使用get()和setdefault()\n\n\nPython风格的示例if 42 < spam < 99:\n\n\n但大体上看所有的编程错误都可以被分为3类语法错误、运行时错误和语义错误。\n\n\n库、框架、SDK、引擎、API\n\n\n上述代码的执行演示过程见autbor.com/addingloopfixed/。\n\n\n但是正如变量包含的只是值的引用而非实际值列表包含的也是值的引用。\n\n\ngetPlayerMove()函数是唯一会被程序其他部分调用的函数其他5个函数仅被getPlayerMove()调用。由于函数数量比较多,因此这个事实并不那么明显。\n\n\n函数最好少于30行至多不超过200行。\n\n\n副作用是指函数对自身代码和局部变量之外的其他部分所做的任何改变。\n\n笔记\n\n·先询问是否可以提问而非直接提出问题。\n·拐弯抹角而非直截了当地提问。\n·在不适合的论坛或网站上提出问题。\n·帖子名称或者邮件主题不够具体比如“我有一个问题”或“求助”这样的主题。\n·只说程序不能正常工作但不解释预期的正确行为是什么。\n·不提供完整的错误信息。\n·不分享代码。\n·分享的代码格式不好。\n·不说明你已经尝试过的方案。\n·不提供操作系统或者版本信息。\n\n💭 沟通的艺术\n\n在阐述问题时你会下意识地认为别人听得懂你在说什么但编程是一个非常宽泛的领域别人有可能在你所遇到的问题的具体领域中缺乏经验所以用实际问题的形式陈述问题是很有必要的。\n\n💭 问题背景\n书评\n点评"},"Personal/Book/计算机/Python编程从入门到实践第2版":{"title":"Python编程从入门到实践第2版","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《Python编程从入门到实践第2版》\n作者 埃里克·马瑟斯\n分类 计算机-编程设计\nISBN9787115546081\n出版社人民邮电出版社\n\n概述\n本书是针对所有层次Python读者而作的Python入门书。全书分两部分第一部分介绍用Python编程所必须了解的基本概念包括强大的Python库和工具以及列表、字典、if语句、类、文件与异常、代码测试等内容第二部分将理论付诸实践讲解如何开发三个项目包括简单的2D游戏、利用数据生成交互式的信息图以及创建和定制简单的Web应用并帮助读者解决常见编程问题和困惑。第2版进行了全面修订简化了Python安装流程新增了f字符串、get()方法等内容并且在项目中使用了Plotly库以及新版本的Django和Bootstrap等等。\n划线\n\n要关闭该终端会话可按Ctrl + Z、再按回车键也可执行命令exit()。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/SQL必知必会第5版":{"title":"SQL必知必会第5版","links":[],"tags":["阅读/计算机-数据库","阅读/笔记"],"content":"简介\n\n书名《SQL必知必会第5版》\n作者 本·福达\n分类 计算机-数据库\nISBN9787115539168\n出版社人民邮电出版社\n\n概述\nSQL是使用最为广泛的数据库语言几乎所有重要的DBMS都支持SQL。本书是麻省理工学院、伊利诺伊大学等众多大学的参考教材由浅入深地讲解了SQL的基本概念和语法涉及数据的排序、过滤和分组以及表、视图、联结、子查询、游标、存储过程和触发器等内容实例丰富便于查阅。与其他同类图书不同本书没有过多阐述数据库基础理论而是专门针对一线软件开发人员直接从SQLSELECT开始讲述实际工作环境中最常用和最必需的SQL知识实用性极强。新版对书中的案例进行了全面的更新并增加了章后挑战题便于读者巩固所学知识。\n划线\n\nSQL是使用最为广泛的数据库语言。\n\n\n数据库database保存有组织的数据的容器通常是一个文件或一组文件。\n\n\n数据库软件应称为数据库管理系统DBMS。数据库是通过DBMS创建和操纵的容器\n\n\nSQL发音为字母S-Q-L或sequel是Structured Query Language结构化查询语言的缩写\n\n\nWindows用户可以使用Microsoft SQL Server Express。这是强大的SQL Server的一个免费版本它还包括一个用户友好的客户端叫SQL Server Management Studio。\n\n\n办法就是使用DISTINCT关键字顾名思义它指示数据库只返回不同的值。\n\n\nLIMIT 5 OFFSET 5\n\n\n重要的是理解在按多个列排序时排序的顺序完全按规定进行。\n\n\n如果prod_price列中所有的值都是唯一的则不会按prod_name排序。\n\n\n提示按非选择列排序显然当根据不出现在SELECT清单中的列进行排序时不能采用这项技术。但是如果有必要可以混合使用实际列名和相对列位置。\n\n\n在很多DBMS中AS关键字是可选的不过最好使用它这被视为一条最佳实践。\n\n\nWHERE在数据分组前进行过滤HAVING在数据分组后进行过滤\n\n\n使用HAVING时应该结合GROUP BY子句而WHERE子句用于标准的行级过滤。\n\n\n在SELECT语句中子查询总是从内向外处理。\n\n\n关系表的设计就是要把信息分解成多个表一类数据一个表。各表通过某些共同的值互相关联所以才叫关系数据库。\n\n\n将数据分解为多个表能更有效地存储更方便地处理并且可伸缩性更好。但这些好处是有代价的。\n\n\n由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。\n\n\n目前为止使用的联结称为等值联结equijoin它基于两个表之间的相等测试。这种联结也称为内联结inner join\n\n\n不要联结不必要的表。联结的表越多性能下降越厉害。\n\n\n自联结self-join、自然联结natural join和外联结outer join。\n\n\n联结包含了那些在相关表中没有关联行的行。这种联结称为外联结。\n\n\nUNION几乎总是完成与多个WHERE条件相同的工作。UNION ALL为UNION的一种形式它完成WHERE子句完成不了的工作。如果确实需要每个条件的匹配行全部出现包括重复行就必须使用UNION ALL而不是WHERE。\n\n\n视图是虚拟的表。与包含数据的表不一样视图只包含使用时动态检索数据的查询。\n\n\n事务处理是一种机制用来管理必须成批执行的SQL操作保证数据库不包含不完整的操作结果。\n\n\n管理事务的关键在于将SQL语句组分解为逻辑块并明确规定数据何时应该回退何时不应该回退。\n\n\n一般的SQL语句都是针对数据库表直接执行和编写的。这就是所谓的隐式提交implicit commit即提交写或保存操作是自动进行的。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/SREGoogle运维解密":{"title":"SREGoogle运维解密","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《SREGoogle运维解密》\n作者 贝特西·拜尔等\n分类 计算机-计算机综合\nISBN9787121297267\n出版社电子工业出版社\n\n概述\n在本书中不仅展示了 Google 是如何运用各种计算机工具软件、硬件以持续部署和监控一些世界上最大的软件系统的。还展示了在运维过程中Google 工程师团队是如何学习、成长、反复修改,最后定义出一套完整的工具和科技体系的过程。本书适合各种水平的运维工程师参考使用。\n划线\n\n大型软件系统生命周期的绝大部分都处于“使用”阶段而非“设计”或“实现”阶段。\n\n\nSRE就是运行和管理这百万台服务器和众多分布式系统的关键。\n\n\nSRE强调的是对问题和故障的自动处理而非人工干预再者按照SRE的约定开发人员自行负责程序上线部署更新毕竟开发人员对自己开发的程序更熟悉易于处理程序上线过程中遇到的问题。\n\n\n100%的可用性是不现实的需要达到这个目标的成本通常远超于所能获得的价值所以Google会针对每种产品设定一个错误预算容错率既能保证用户体验又不影响创新和部署的速度。\n\n\nSRE是一群天生的怀疑论者我们怀疑一切宣传起来“高大上”的技术以及任何“神奇”的产品——我们只想看具体的设计架构、实现细节以及真实的监控图表。\n\n\nSRE其实是一群崇尚工匠主义的人我们坚信只要不断地解决根源问题服务质量就一定会得到提升。而SRE正是用这种“日拱一卒”的方法造就了Google这个世界级的奇迹。\n\n\n本书体系化地覆盖了运维工作的方方面面是一本运维行业的教科书。\n\n\n更重要的是我们展示了在建设过程中Google 工程师团队是如何学习、成长、反复修改最后定义出一套完整的工具和科技体系的过程。IT 行业大多自我封闭交流过少很多从业人员都或多或少地受教条主义的限制。如果Google 工程师团队能克服这个惯性,保持开放的精神,那么我们也能够一起和他们面对 IT 行业内最尖端的挑战。\n\n\n今天我们能感受到整个行业都在鼓吹厚颜无耻的 “代码拿来主义”just show me the code。开源软件社区内部正在形成一种“不要问我问题”的风气过于强调平等却忽略领域专家的意见。Google 是行业内为数不多的,愿意投入精英力量钻研本质问题的公司,而且这些公司精英很多都有工学博士学位。工具永远只是解决方案中的一个小小组件,用来链接日益庞杂的软件、人和海量的数据。\n\n\n一个公司的成长意味着整个公司商业模式和工作模式的扩展而不是简单的资源扩张\n\n\n有统计显示一个软件系统的40%90% 的花销其实是花在开发建设完成之后不断维护过程中的。[1]\n\n\n从这个视角出发我们认为如果软件工程职业主要专注于设计和构建软件系统那么应该有另外一种职业专注于整个软件系统的生命周期管理。从其设计一直到部署历经不断改进最后顺利退役。\n\n\n有的时候SRE 和产品研发团队共同工作,其他时候我们需要开发这些系统的额外组件:例如备份系统和负载均衡系统等。理想情况下,同时推进这些组件在多个项目中复用。还有的时候,我们的任务是想出各种各样的办法用现有组件解决新的问题。\n\n\n这与盖房子有些类似如果一开始将整个地基打好并保持继续修缮要比盖好房子之后再重新修改设计要容易得多\n\n\n团队文化就是从一切经历中不断学习包括来自那些我们最意想不到的地方的经历。\n\n\n只有靠着对细节的不懈关注做好充足的灾难预案和准备工作时刻警惕着不放过一切机会去避免灾难发生。这就是SRE 最重要的理念欢迎加入SRE的大家庭\n\n\n不能将碰运气当成战略。\n\n\n极端来说研发部门想要“随时随地发布新功能没有任何阻拦”而运维部门则想要“一旦一个东西在生产环境中正常工作了就不要再进行任何改动。”\n\n\n由于两个部门使用的语境不同对风险的定义也不一致。\n\n\n开发团队宣称他们不再进行大规模的程序更新而是逐渐转为功能开关调整、增量更新以及补丁化。采用这些名词的唯一目的就是为了绕过运维部门设立的各种流程从而能更快地上线新功能。\n\n\n目前来看UNIX 系统内部细节和13层网络知识是Google最看重的两类额外的技术能力。\n\n\n所有的SRE团队成员都必须非常愿意、也非常相信用软件工程方法可以解决复杂的运维问题。\n\n\na对重复性、手工性的操作有天然的排斥感。b有足够的技术能力快速开发出软件系统以替代手工操作。\n\n\nSRE团队应该倾向于将基本的运维工作全部消除全力投入在研发任务上\n\n\n我们可以认为DevOps是SRE核心理念的普适版可以用于更广范围内的组织结构、管理结构和人员安排。同时SRE是DevOps模型在Google的具体实践带有一些特别的扩展。\n\n\n“错误预算”起源于这样一个理念任何产品都不是也不应该做到100% 可靠显然这并不适用于心脏起搏器和防抱死刹车系统等。一般来说任何软件系统都不应该一味地追求100% 可靠。因为对最终用户来说99.999% 和 100% 的可用性是没有实质区别的详见附录A\n\n\n一个需要人工阅读邮件和分析警报来决定目前是否需要采取某种行动的系统从本质上就是错误的。监控系统不应该依赖人来分析警报信息而是应该由系统自动分析仅当需要用户执行某种操作时才需要通知用户。\n\n\n但是长久看来一个手持“运维宝典”经过多次演习的on-call工程师才是正确之路\n\n\n由一个简单的想法“我是一名软件工程师这是我如何来应付重复劳动的办法”而生\n\n\nGoogle的大部分计算资源都存放在自主设计的数据中心中。这些数据中心拥有自己设计的供电系统、制冷系统、网络系统以及计算机硬件参见文献[Bar13])。\n\n\n一个典型的Google数据中心的拓扑结构● 约10台物理服务器组成了一个机柜Rack● 数台机柜组成一个机柜排Row● 一排或多排机柜组成了一个集群Cluster● 一般来说一个数据中心Datacenter包含多个集群● 多个相邻的数据中心组成了一个园区Campus\n\n\n因为一个集群中包括很多硬件设备每天硬件设备的损坏量很高。在一年内一个单独集群中平均会发生几千起物理服务器损坏事件会损失几千块硬盘。\n\n\n如果一个工程师遇到了他工作的项目之外的一个基础组件的问题他可以直接修改这个问题向管理者提交一份改动申请changelist,CL等待代码评审最后直接提交。\n\n\n任何对自己项目代码的改动也需要代码评审。\n\n\n有些项目组甚至在实践自动部署机制提交一个新版本测试通过后将直接部署于生产环境。\n\n\n监控系统都是运维生产环境必不可少的组件。如果没有针对服务的监控就无从得知目前服务的状态如果不知道服务的状态就无从谈起维护服务的可靠性。\n\n\n极端的可靠性会带来成本的大幅提升过分追求稳定性限制了新功能的开发速度和将产品交付给用户的速度并且很大程度地增加了成本这反过来又减少了一个团队可以提供的新功能的数量。\n\n\n尽管当时YouTube已经有了一个很出色的产品但它仍然在不断变化和快速发展着。因此我们为YouTube设定了一个相比我们企业的产品更低的可用性目标因为快速发展更加重要。\n\n\n一种在符合成本效益条件下满足这些竞争性约束的方式就是将基础设施分割成多个服务在多个独立的服务水平上提供该服务。\n\n\n对意外事件的容忍程度有多高做得太少我们就只能设计出一个脆弱无用的产品。做得太多我们的产品可能没有人会使用但运行非常稳定\n\n\nSLI是指服务质量指标indicator—该服务的某项服务质量的一个具体量化指标。\n\n\n如果系统正常运转中需要人工干预应该将此视为一种Bug。\n\n\nSRE的一个公开目标是保持每个SRE的工作时间中运维工作即琐事的比例低于50%。SRE至少花50%的时间在工程项目上,以减少未来的琐事或增加服务功能。\n\n\n让我们多创新少干琐事吧\n\n\n监控系统应该解决两个问题什么东西出故障了以及为什么出故障。\n\n\n“现象”和“原因”的区分是构建信噪比高的监控系统时最重要的概念。\n\n\n监控系统的4个黄金指标分别是延迟、流量、错误和饱和度saturation。\n\n\n● 每当收到紧急警报时,应该立即需要我进行某种操作。每天只能进入紧急状态几次,太多就会导致“狼来了”效应。● 每个紧急警报都应该是可以具体操作的。● 每个紧急警报的回复都应该需要某种智力分析过程。如果某个紧急警报只是需要一个固定的机械动作,那么它就不应该成为紧急警报。● 每个紧急警报都应该是关于某个新问题的,不应该彼此重叠。\n\n\n-mail警报的价值通常极为有限很容易变成噪声。我们应该倾向于构建一个良好的监控台页面直接显示所有的非紧急的异常情况。\n\n\n一致性地执行范围明确、步骤已知的程序—是自动化的首要价值。\n\n\n在行业内普遍认同的是在产品生命周期中一个问题越晚被发现修复代价越高\n\n\n自动化是“元软件”也就是操作其他软件的软件。\n\n\n广泛使用的工具有Puppet、Chef、cfengine甚至 Perl都提供了自动化完成特定任务的方法主要区别在于对帮助进行自动化的组件的抽象层次不同。\n\n\n如何管理包的版本应该采用持续构建和部署的模型还是应该定期构建发布的频率应该怎样应该使用什么策略管理配置文件哪些发布过程的指标比较有用\n\n\n可靠性只有靠对最大程度的简化不断追求而得到。\n\n\n我们的工作最终是在系统的灵活性和稳定性上维持平衡\n\n\n有的时候为了灵活性而牺牲稳定性是有意义的。我在面临一个不熟悉的问题域时经常进行“探索性编码”—给我写的任何代码设置一个明确的保质期我清楚地知道自己需要先探索以及失败才能真正理解需要完成的任务。这种带保质期的可以在测试覆盖和发行管理上更宽松因为它永远不会被发布到生产环境或被用户使用。\n\n\n某种程度上这与面向对象编程中的类设计类似正如普遍认同的编写一个其中包含无关功能的“大杂烩”类是一个糟糕的实践。构建和发布“util”或“misc”二进制文件同样也是个糟糕的实践。一个设计良好的分布式系统是由一系列合作者组成的每一个合作者都具有明确的、良好定义的范围。\n\n\n我们可以将一个服务的健康程度指标分为低级需求能够正常对外提供服务和高级需求SRE能够主动控制服务状态而不是被动救火。\n\n\n[插图]\n\n\non-call轮值是很多运维和研发团队的重要职责这项任务的目标是保障服务的可靠性和可用性。\n\n\nSRE团队和纯运维团队十分不一样的地方在于SRE团队非常强调用工程化手段来应对运维问题。而这些运维问题当达到一定规模时也确实只有采用软件工程化手段才能解决。\n\n\n我们强调至少将SRE团队50%的时间花在软件工程上。在其余时间中不超过25%的时间用来on-call另外25%的时间用来处理其他运维工作。\n\n\n1.对通用的故障排查过程的理解不依靠任何特定系统。2.对发生故障的系统的足够了解。\n\n\n当所有的可能都存在的时候我们应该优先考虑最简单的解释\n\n\n更糟的是随着系统部署规模的不断增加复杂性也在不断增加监控指标越来越多。不可避免的纯属巧合一些现象会和另外一些现象几乎同时发生。\n\n\n在大型问题中你的第一反应可能是立即开始故障排查过程试图尽快找到问题根源。这是错误的不要这样做\n\n\n正确的做法应该是尽最大可能让系统恢复服务。\n\n\n在大型系统中逐个检查可能太慢了可以采用对分法bisection将系统分为两部分确认问题所在再重复进行。\n\n\n将你的想法明确地记录下来包括你执行了哪些测试以及结果是什么。[35]尤其是当你处理更加复杂的问题时,良好的文档可以让你记住曾经发生过什么,可避免重复执行。[36]如果你修改了线上系统,例如给某个进程增加了可用资源。系统化和文档化这些改变有助于将系统还原到测试前的状态,而不是一直运行在这种未知状态下。\n\n\n东西早晚要坏的这就是生活。\n\n\n时间和经验一再证明系统不但一定会出问题而且会以没有人能够想到的方式出问题。\n\n\n事故总控负责人最重要的职责就是要维护一个实时事故文档。该文档可以以wiki的形式存在但是最好能够被多人同时编辑。大部分Google团队使用Google Docs但是Google Docs 团队使用Google Sites做这件事利用你正要修复的服务来修复该服务恐怕不是什么好主意。\n\n\nGoogle团队依靠下面几个宽松的标准——如果下面任何一条满足条件这次事故应该被及时宣布。● 是否需要引入第二个团队来帮助处理问题?● 这次事故是否正在影响最终用户?● 在集中分析一小时后,这个问题是否依然没有得到解决?\n\n\n划分优先级控制影响范围恢复服务同时为根源调查保存现场。事前准备事先和所有事故处理参与者一起准备一套流程。信任充分相信每个事故处理参与者分配职责后让他们自主行动。反思在事故处理过程中注意自己的情绪和精神状态。如果发现自己开始惊慌失措或者感到压力难以承受应该寻求更多的帮助\n\n\n考虑替代方案周期性地重新审视目前的情况重新评估目前的工作是否应该继续执行还是需要执行其他更重要或者更紧急的事情。练习平时不断地使用这项流程直到习惯成自然。换位思考上次你是事故总控负责人吗下次可以换一个职责试试。鼓励每个团队成员熟悉流程中的其他角色。\n\n\n最佳实践公开奖励做正确事的人\n\n\nGoogle使用Outalator—一个故障跟踪工具来做这件事。Outalator系统被动收集监控系统发出的所有报警信息同时提供标记、分组和数据分析功能。\n\n\n如果你还没有亲自试过某件东西那么就假设它是坏的。\n\n\n合并通用型人才generalist和领域专家组成一个种子团队通用型人才可以很快地开始工作而资深领域专家可以提供更广阔的知识和经验。这样一个多样化的团队可以避免设计盲点。\n\n\n每个项目都有正确的时间点来引入领域专家。\n\n\n按照QPS来规划服务容量或者是按照某种静态属性认为其能指代处理所消耗的资源例如某个请求所需要读取的键值数量一般是错误的选择。\n\n\n如何给新手带上喷气背包同时保证老手的速度不受影响\n\n\n[插图]图28-1培养SRE加入on-call的计划图\n\n\n这个团体活动每个季度会进行一次有助于在生产环境中发现亟待解决的新Bug—系统并不会像我们想象的那样优雅降级。\n\n\n紧急警报主要是通过设置专门的主on-call工程师来处理的。也就是说让一个工程师独立接收和响应紧急警报处理发生的事故或者故障。\n\n\n从某种意义上讲人类可以被称为不完美的机器。人会感觉无聊人的处理器指思维方式工作原理不清楚用户界面指沟通方式也不太友好效率也不高。\n\n\n极化时间意味着当每个人来上班时他们应该清晰地知道自己今天是否只是做项目工作还是只是做中断性工作\n\n\n工单处理应该由全职人员负责同时保证占用合理的时间。如果团队目前的工单主oncall和副on-call都处理不完那么需要重新架构整个工单的处理流程保障任何时间都有两个全职员工处理工单。不要将复杂分散到整个团队中去。人不是机器这样做只会干扰员工降低他们的工作效率\n\n\n如果团队中需要很多人同时进行中断性任务那么可能这种负载是不能持久的。有一系列方式可以降低整体的工单负载。\n\n\n第一阶段了解服务了解上下文\n\n\n日益增加的工单不应需要更多的SRE来处理。SRE模型的目标是仅仅在系统复杂度上升的时候才增加新人。你应该尝试引导团队建立健康的工作习惯这样能够减少花费在工单上的时间。这与指出该服务目前还可以自动化或者进一步简化同样重要。\n\n\n对“未来的一件大事”的过度依赖\n\n\n第二阶段分享背景知识\n\n\n书写一个好的事后总结作为示范\n\n\n第三阶段主导改变保持团队健康是一个持续的过程。正因为此这不是你可以通过个人英雄主义来解决的问题。为了确保团队在未来可以进行自我调节我们需要帮助他们建立一个良好的SRE心理模型。\n\n\n● 从技术角度,最好是量化的角度指出团队需要改变的原因。● 提供一个详细、具体的“改变”作为例子。● 解释SRE经常采用的“常识”背后的逻辑推理过程。● 提供以可伸缩的方式来解决崭新情况所必需的核心理念。你的最后一个任务是书写一份报告。报告中应该重申你的观点、例子和逻辑推理过程。同时,该报告应该向团队提供一些待办事项,来保证他们会实践你所传授的东西。你应该将报告组织成一份检查报告[12],解释成功路上的每一个重要的决策。\n\n\n就像数据必须围绕生产流动那样数据也要围绕SRE团队流动—关于项目的数据关于服务状态、生产环境状态以及个人状态的数据。团队的最佳运行状态是数据可靠地从一个感兴趣的团队流动到另一个团队。思考这种流动的一个方法是思考SRE团队与其他团队建立的接口API。和设计一个API一样好的设计对于有效性是至关重要的。如果API的设计是错误的后续改正它将是非常痛苦的。\n\n\n。生产会议是一种特殊的会议。在这个会议中SRE团队向自己—以及邀请的嘉宾—描述服务的目前状态。这样那些关心服务的人对服务状态的了解程度得到了提高同时也能提高服务自身的运维质量。\n\n\n一般来说单人项目最终肯定会失败除非此人个人能力超强或者待解决的问题是非常简单直接的。做成任何高价值的事情都需要很多人共同协作\n\n\n因为人与人之间的沟通方式差异很大第一次见面时书面表达习惯和口语表达习惯中隐含的微妙暗示很容易被误解。在项目开始之初那些不在总部工作的团队成员经常会错过会议开始之前和结束之后立刻进行的即兴讨论现在的沟通渠道已经大大改善了。\n\n\n其次也许是最好的方式与其创造很多各异的个体系统交给SRE运维不如直接让研发团队在一个通过SRE验证的基础设施平台上进行产品开发。\n\n\n最佳实践代码化将生产环境中运行良好的最佳实践代码化这样服务可以通过简单地使用这些代码自然而然地成为“生产就绪”。可重复使用的解决方案常见并易于共享的技术实现用于改善可扩展性和可靠性的问题。带有通用控制界面的通用生产操作平台生产设施的统一接口统一的运维控制机制以及统一的监控、日志以及服务配置。更简易的自动化和更智能的系统通用的控制接口使自动化和智能化达到一个以前不可能达到的水平。例如SRE可以用一个统一的视图查看关于一次故障的全部相关信息不用收集和分析来自不同数据源的原始数据日志、监控数据等等。\n\n\n建立了一系列SRE支持的平台和服务框架\n\n\n服务框架以一个标准化的方式实现了基础设施部分的代码并且预先解决了常见的各种生产问题\n\n\nSRE通过构建框架模块来实现这些关注重点的标准解决方案。其结果是因为该框架已经考虑了正确的基础设施的使用所以研发团队可以更专注于业务逻辑的开发\n\n\n● 究竟发生了什么● 响应的有效程度● 下次是否可以采用其他方案解决问题● 如何确保这次故障不会再次发生\n\n\n纠结于“谁”造成了这个故障是没有意义的。事后总结在每次事故发生之后都会进行同时会在整个SRE团队内部传阅以便让所有人都能从中受益。\n\n\n采用的标准是如果整个发电站需要在少于30分钟的时间内响应某种情况那么这种响应必须要自动化进行。\n\n\n某项决策的基本方向是事先决定的而不是事后得出的。● 决策时考虑的信息源是清楚的。● 任何假设都应该明确说明。● 数据驱动决策要优于情感驱动的决策、直觉驱动的决策,以及资深人士的意见。\n\n\n飞机上布满了非常可靠的、冗余度非常高的系统。这就是不断重视安全与可靠性的后果\n\n\n高可用性、性能极度优化、变更管理、监控与报警、容量规划以及应急处理。\n\n\n越精简越好他们所操作的东西应该更抽象而非更具体\n\n\n[插图]\n\n\n紧急警报某个人必须执行某项操作。工单某个人必须在几天之内执行某种操作。日志没有人会马上看这些日志但是以后需要的时候可以用来分析。\n\n\n每次on-call轮值应该处理不超过两起事故平均每12小时1个\n\n\n泄洪集群\n\n笔记\n\n系统运维长久以来都依赖实践积累之上的口口相传经验通常是领域从业者手里掌握的秘诀。\n\n💭 人肉运维哈哈哈\n\n我们无法按照传统方式运维Google系统必须要思考一种新的模式但是同时我们也没有时间等待其他人验证和支持我们的理论。\n\n💭 适合自己的才是最好的\n\n有统计显示一个软件系统的40%90% 的花销其实是花在开发建设完成之后不断维护过程中的。[1]\n\n💭 就像生孩子一样,十月怀胎一朝分娩,一辈子成人。\n\n从本质上来说SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的任务。这些SRE倾向于通过设计、构建自动化工具来取代人工操作。\n\n💭 yaml 工程师哈哈哈\n\n从本质上来说SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的任务。这些SRE倾向于通过设计、构建自动化工具来取代人工操作。\n\n💭 标准化,流程化,自动化\n\n如果100% 不是一个正确的可靠性目标,那么多少才是呢?这其实并不是一个技术问题,而是一个产品问题。\n\n💭 技术服务于客户\n\n到底什么是琐事琐事就是运维服务中手动性的重复性的可以被自动化的战术性没有持久价值的工作。\n\n💭 人肉运维哈哈哈\n\n如果事先没有针对可能发生的紧急事故进行过演习那么当事故发生时一切管理理念都起不了作用\n\n💭 演习,演习,还是演习。\n\n我们将之前的某篇事后总结的场景再现一批工程师负责扮演这篇文档中提到的各种角色。经常当时的事故总控负责人也参与其中确保这次演习越真实越好。\n在引入事后总结机制\n\n💭 事后总结\n\nSRE团队最需要的就是技能的多样性成员多元化的背景和多样化的解决问题的方式可以避免在团队中出现盲点。\n\n💭 广度\n\n不要过于关注完美和解决方案的纯粹性尤其是当待解决问题的边界不够清晰时。我们应该更快地发布和迭代。\n\n💭 更快的去做,更多的去尝试。知行合一!\n\nGoogle SRE团队通过一个老传统—“故障处理分角色演习”来解决这些问题。这个活动同时也被称为“命运之轮”wheel of misfortune或者 “走木板”walk the plank这些名字对新加入的SRE来说不会那么吓人。\n\n💭 沙盘模拟经营很重要!\n\n为了限制干扰数量我们应该减少上下文切换指工作类型、环境等的改变。某些中断性任务是无法避免的。然而将工程师当成是可以随时中断、上下文切换没有成本是不正确的。给每次上下文切换加上成本的考虑。在项目工作中一次20分钟的中断性任务需要进行两次上下文切换而这种切换会造成数个小时的生产力的丧失。为了避免这种经常性的生产力丧失我们应该延长每种工作模式的时间一天甚至半天都可以。这种策略与“挤时间”参见文献[Gra09])策略工作得很好。\n\n💭 上下文切换\n\nSRE则恰恰相反。他们通过编写软件系统或者消除系统瓶颈的方法来解决这个问题。\n\n💭 熵减\n\nSRE团队陷入Ops模式的原因是过分关注如何快速解决紧急事件而不是如何减少紧急事件的数量。\n\n💭 治标也要治本!\n\nSRE团队成员拥有系统工程或架构能力见文献[Hix15b]、软件工程技术、项目管理能力、领导才能各种行业背景的人都有参见第33章\n\n💭 扫地僧\n\n在本章中我们会讨论到许多SRE的核心指导思想。为了简化与其他行业最佳实践的比较我们将这些理念分为4大类\n● 灾难预案与演习\n● 书写事后总结的文化\n● 自动化与降低日常运维负载\n● 结构化的、理智的决策\n\n💭 标准化,流程化,自动化\n书评\n点评"},"Personal/Book/计算机/UNIX传奇历史与回忆":{"title":"UNIX传奇历史与回忆","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《UNIX传奇历史与回忆》\n作者 布莱恩·W.克尼汉\n分类 计算机-计算机综合\nISBN9787115557179\n出版社人民邮电出版社\n\n概述\n自1969年在贝尔实验室的阁楼上诞生以来Unix操作系统的发展远远超出其创造者们的想象。它带动了许多创新软件的开发影响了无数程序员改变了整个计算机技术的发展轨迹。本书不但书写Unix的历史而且记录作者的回忆一探Unix的起源试图解释什么是UnixUnix是如何产生的以及Unix为何如此重要。除此之外本书以轻松的口吻讲述了一群在贝尔实验室工作的发明天才的有趣往事本书中每一个故事都是鲜为人知却又值得传播的宝贵资源。本书适合对计算机或相关历史感兴趣的人阅读。读者不需要有太多的专业技术背景就可以欣赏Unix背后的思想了解它的重要性。\n划线\n\n自1969年在贝尔实验室的阁楼上诞生以来Unix操作系统的发展远远超出其创造者们的想象。\n\n\n你的能力不可能超越你的鉴赏力。\n\n\n软件技术的“皇冠明珠”就是操作系统。\n\n\nUnix的创造者奠定了操作系统的标准基石Unix的“分而治之”设计哲学——让每个程序做好一件事要做一件新的工作就构建新程序而不是通过增加新“特性”使旧程序复杂化——被优秀程序员奉为圭臬。\n\n\n一大批天才人物聚集在一起没有生活的压力没有KPI的烦恼自由地探索科学的发展和应用。\n\n\n愿原力与你同在\n\n\n格蕾丝•霍珀Grace Hopper1906—1992她在UNIVAC I大型机上开发出了一个名为A-0Arithmetic Language version 0的特殊软件这个软件可以把人类书写的程序自动编译为可以在计算机上执行的程序。这样的程序很快被赋予一个专有的名称——编译器。\n\n\n软件世界变得日益复杂之后这个世界亟待出现一个优秀的“管理者”它能很好地统筹宝贵的硬件资源为不同功能的应用软件提供丰富的基础设施和安全公平的“生存”环境为不同身份的用户提供简单易用的人机接口。\n\n\n以我之见程序员的追求就是让机器听话让工作自动化让人类生活更美好。\n\n\n回忆往往披着玫瑰色的光晕令人欢欣。回忆常驻于美好而持久的事物上也常驻于因努力改善人类生活而获得的愉悦之中。”\n\n\n带动了许多创新软件的开发影响了无数程序员改变了整个计算机技术的发展轨迹。\n\n\n例如Unix软件哲学倡导合用既有软件完成很多不同任务而不是从头写个新软件。这个例子简明又生动它在编程领域体现了“分而治之”的故技将大任务切分为多个小任务每个小任务都变得更可控然后再以各种不可思议的方式将之整合到一起。\n\n\n一套策略一个系统普遍服务\n\n\n1961年的贝尔实验室贝尔实验室供图\n\n\n真不少。谁给他们发工资呢\n\n\n持续的资金投入是研究工作的关键保障\n\n\n我出生于多伦多曾就读于多伦多大学专业是工程物理后来改名为工程科学这是为那些自己也不知道想学什么的人准备的“大杂烩”专业。\n\n\n我的代码充斥着没完没了的IF语句在我想到要做什么事时将执行流程分支到另外某处。\n\n\n我在麻省理工学院名义上的老板是费尔南多·科巴托Fernando Corbató教授人人都叫他“科尔比Corby”。他创建了CTSS负责Multics是一位了不起的绅士。1990年科尔比因其为分时系统做的基础工作获得图灵奖。他于2019年去世享年93岁\n\n\n“我们给他们一本词典和一套语法规则孩子你已经是伟大的程序员了。”\n\n\n在编程时“乱抖机灵”并非良策。\n\n\n于是我得到编程风格的第一条规则写明白别炫技。\n\n\n如何将员工分配到不同楼层才能让经常交谈的人在同一个楼层\n\n\n把你介绍给其他人让你随意晃荡去寻找自己的研究课题和协作者\n\n\n后来他们奇迹般地找到了之前没系领带的照片并且刊印了。\n\n\n尽管大多数研究员都有博士学位但没人称呼“博士”因为每个人都是博士。\n\n\n多数管理人员都是“赶鸭子上架”因为这虽然没有终结个人研究生涯但必然会拖慢进度而且照料麾下部门颇具挑战性。\n\n\n从加薪池中为每位MTS分配次年加薪幅度。\n\n\n因为管理层在晋升过程中保持了技术能力而且都有基层经历。整个系统看起来并不过于偏重实践或理论起码对于我们1127中心这帮人是这样的——优秀的程序和优秀的论文都很受重视。\n\n\n对未来工作的提议或计划一概欠奉这是件好事。每个人都会大略预估年终成果但不管做错多少次都没关系。对于那些年复一年做同一件事的人管理层会保持耐心以待长远。我想科研部门管理层级较少也有好处这样一来大多数人在大多数时候就不会去考虑晋升问题。如果有人立志做官最好选择其他部门。\n\n\n专精某一领域的人可能会得到其直接上级的高度评价但再上一层就未必了解其工作成果。另外跨学科的工作在更高层眼中更突出因为更多管理人员看得到它。协作越广泛就会有越多管理者看得到结果就形成了一个极其偏重协作与跨学科研究的组织。\n\n\n贝尔实验室绩效考核方式的好处在于它基于由理解某项工作的人的共同评估做出。如道格·麦基尔罗伊所言“合议是这套体系的极妙之处。谁都不必依赖与单个老板的关系。”\n\n\n在某一时刻我发现离实现一个操作系统仅有3周之遥了。\n\n\n几位贝尔实验室员工在其他操作系统和语言上积累了多年经验这才有了Unix\n\n\n操作系统的任务是控制所有其他要运行的程序并管理它们与计算机其他部分的交互。\n\n\n每张卡片能保存最多80个字符容纳一行程序的内容\n\n\n操作系统看顾每位登录用户在用户之间快速切换令每位用户误以为整台计算机都为我所用。这种技术叫作“分时”\n\n\n所谓第二系统效应意思是在首个系统如CTSS创建成功后打算创建一个新系统修正旧系统的遗留问题还要添加每个人期望的新特性结果常常是塞了太多不同东西进去最终得到过于复杂的系统。\n\n\n很多好点子滥觞于Multics但它最持久的贡献却完全没人预料到它影响了一个叫Unix的小操作系统这个小系统诞生的部分原因是想摈弃Multics的复杂架构。\n\n\n正在那时肯的太太休了3周假带着一岁大的儿子去加利福尼亚探望公婆这样肯就有了3周不受打扰的工作时间。\n\n\n1992年12月肯和弗雷德·格兰普Fred Grampp到莫斯科驾驶一架米格29战机比他们平时开的赛斯纳飞机更上一层级。图2-5和图2-6展示了肯起飞前和落地滑行的情形。\n\n\n2006年他加入谷歌公司和罗布·派克及罗伯特·格里塞默Robert Griesemer一起发明了Go语言\n\n\nPDP-7的Unix系统实在有趣即使它只是运行在一台小型计算机上而且还没有很多软件人们还是开始使用了\n\n\n有人认为管理层的积极作用之一就是随时保持警醒让要求资源的人打磨申请专注提案。相比没有资源限制资源紧张更有机会促成好的、经过深思熟虑的结果。\n\n\n这里的管理原则是雇用聪明人帮他们融入环境指出大致的需求方向给他们很多自由空间。不是说他们想要多少钱就给多少钱。有所投有所不投。就算你误判了好东西如果它够强仍然会脱颖而出。\n\n\n除了简洁还有几个特点在当时来说也很新颖。例如“缺陷”部分它坦承程序会有缺陷或谓“特性”即使不能立即修复至少也该记录下来。\n\n\ncat命令50年来没有变过只添加了很少的可选也许并不必要的参数修改了其操作行为它仍然是Unix核心命令之一。\n\n\n第6版Unix其手册发布于1975年5月首次拓展到贝尔实验室以外。它对世界产生了重大影响。\n\n\nUnix是一个通用、多用户、交互式操作系统运行在数字设备公司PDP-11/40和11/45计算机上。它提供了一些即使在大型操作系统中也罕见的功能包括1包含可拆卸卷的分层文件系统2可兼容的文件、设备和进程间I/O输入/输出3初始化异步进程的能力4每个用户可选择不同的系统命令语言5100多个子系统包括十几种语言\n\n\nUnix目录也是文件系统中的一个文件但其内容由系统本身维护不由用户程序维护。目录中包含了其下文件的信息而这些文件又可以是目录。\n\n\n因为目录可以包含子目录所以文件系统可以深入至任意层。这种嵌套目录和文件的组织方式被称为“分层”文件系统\n\n\nshell的另一主要服务是I/O重定向。\n\n\nshell脚本shell script是存储在文件中的一系列命令。用该文件作为输入源运行shell实例如同直接输入命令一样运行脚本中的命令\n\n\n我现在还在用一些三四十年前写的脚本这在Unix的长期用户中一点也不稀奇。\n\n\n“像花园水管那样”把程序接在一起。图4-1的第一幅图来自我在贝尔实验室的办公室墙上挂了30年的陈旧纸页。\n\n\n他只花了一小时就在操作系统中添加了管道系统调用。他形容管道是“超级小菜”因为I/O重定向的机制早已存在了。\n\n\n同样一些命令以简单方式持续使用构成了Unix管道这恰恰是管道的天才之处。实在需要脑洞大开才能看到这种可能性并创造出这个概念。\n\n\n它能实现图形界面无法实现的自动化功能命令序列可以从脚本中运行输入单个指令就能作用于大量文件。\n\n\n再加上另外十几个其他类别的工具你就有了20个或30个命令可以轻松完成各种基本任务\n\n\n正则表达式就是一种描述文本模式的小型语言\n\n\n正则表达式还可以通过赋予某些字符特殊含义来指定更复杂的模式这些字符称为元字符metacharacter\n\n\n第6版内核有大约9 000行C语言代码和大约700行汇编语言代码。汇编代码用于设置寄存器、设备和内存映射等与特定机型相关的操作\n\n\n邀请丹尼斯一起写这本书是我在技术生涯中做过的最聪明或者说最幸运的事情——因为丹尼斯是合著者的缘故该书尤显权威而且我也就能在书里引用他的参考手册了。\n\n\nC语言很重要但它对标准库的使用也很重要\n\n\nC语言既古怪又有缺点却获得了巨大的成功。虽然历史上的意外事件肯定有帮助但C语言显然满足了人们对一种系统实现语言的需求这种语言需要足够高效足以取代汇编语言但又足够抽象和流畅足以描述各种环境下的算法和交互。\n\n\n可以说实验室里有很多优秀人士常有人认为自己不过是“暴得大名”。想要力争上游就得紧追不舍。\n\n\n在之后的多年里更多的功能被添加进来BashBourne Again Shell的简写意为“伯恩再来shell”已经成为大多数Linux和macOS用户事实上的标准shell。\n\n\n优秀的编程语言能降低人类与计算机沟通的成本。计算机领域的大量研究都关乎如何创造富有表达能力的语言。\n\n\n计算机语言的特点主要有两个方面语法和语义。语法规定了语言是怎样的什么符合语法什么不符合语法。语法还定义了语句和函数如何写算术和逻辑运算符是什么它们如何组合成表达式什么名称是合规的哪些词是保留字文本字符串和数字如何表达程序如何格式化等规则。\n\n\n“埃里克·施密特Eric Schmidt在暑期实习时几乎重写了Lex。\n\n\n程序帮你写的代码会比你自己手写的更正确、更可靠。\n\n\nmakefile文件有点像shell脚本但它采用声明式语言说明依赖关系和如何更新组件但不会明确检查文件创建时间。\n\n\n我们都是自己软件的用户这给了我们改进软件的真正动力。\n\n\n每个人都慷慨奉献出自己的时间对同事写的东西不吝给出意见这不过是文化使然。在其他地方这种情况并不常见所以贝尔实验室才能那么伟大。\n\n\n也许今天不会有很多人记得当机器容量以千字节而不是千兆字节为单位时时间和空间的利用效率乃是重中之重。每个字节都得斟酌使用所以在某种程度上每条指令也得再三推敲因此一种能在这两方面都节约的语言不仅优秀而且是实际需要。\n\n\n万勿相信不是完全由你自己创建的代码尤其是来自雇我这种人的公司的代码。再多的源码级验证或审查也无法保护你免遭不受信任的代码之害。\n\n\n当时大多数终端只能显示24行80个固定宽度和高度的ASCII字符。\n\n\nPWB用户拿shell当编程语言来用已经能够免除大部分苦差。许多手动操作被快速、廉价、方便地自动化了。\n\n\n从SCCS到RCS、CVS和Subversion再到今天默认的标准版本控制系统Git有一条清晰的演化路径。\n\n\n比尔后来为Unix设计了至今仍在使用的TCP/IP网络接口。有了他的socket接口就能用与文件和设备I/O相同的读写系统调用来读写网络连接因此很容易添加网络功能。\n\n\n肯一直完全赞同这样的观点好代码不需要过多注释。以此类推伟大的代码根本不需要注释。\n\n\nUnix和C语言是终极计算机病毒。\n\n\n经理“你们必须修复C++编译器的所有错误,但你不能以任何方式改变编译器行为。”我:“这不可能。修复缺陷必然导致行为变化,天经地义。”经理:“布莱恩,你没明白。必须修复错误,但编译器的行为不能改变。”\n\n\n1990年12月11日我在贝尔实验室观看乔布斯演示NeXT。机器非常漂亮。记忆中那是我唯一一次对科技小玩意儿产生“想要一台”的想法。我显然是被著名的“乔布斯现实扭曲场”所魅惑。\n\n\n今天Minix依然“健在”用于操作系统的教学和实验。\n\n\nUnix取得了巨大的成功。Unix或Linux或macOS或其他变种运行在数十亿台计算机上持续为数十亿人服务当然也为在它之上构建业务的人赚取了数十亿美元尽管其创造者并未从中获利。后来的操作系统受它影响极深。\n\n\n肯·汤普森和丹尼斯·里奇的部分天才之处在于他们善于挑选既有的好点子而且能够洞察普遍概念或统一主题将软件系统加以简化。人们有时会用代码行数来评价软件的生产力。在Unix的世界里生产力却往往以删除了多少特殊情况或代码行数来衡量。\n\n\nUnix的高明之处在于选择了足够普适的抽象概念既能发挥巨大的作用又不至于在性能上付出太大代价。\n\n\n管道是典型的Unix发明是临时连接程序的一种优雅而高效的方式。\n\n\niii设计和构建软件甚至是操作系统要尽早试用最好是在几周内就用起来。大刀阔斧砍掉笨拙的部件重建它们。\n\n\nUnix哲学当然不能解决所有编程问题但它确实为系统设计和实现提供了有益的指导。\n\n\n稳定的环境至关重要资金、资源、任务、组织结构、管理、文化都应持续和可预测。\n\n\n这意味着研究人员可以长期甚至年复一年地探索他们认为重要的想法而不必每隔几个月就向人证明自己在努力。\n\n\n贝尔实验室的文化强烈鼓励合作和帮助。走进别人的办公室寻求帮助绝对是标准做法大多数情况下被请求者都会放下手头的一切来协助。实验室还有一流的技术图书馆每天24小时开放订阅大量期刊并可远程访问其他图书馆它相当于高校的图书馆但重点放在科学和技术方面。\n\n\n乐趣。享受你的工作以及与你的同事一起工作的时光这很重要。1127中心几乎总是个有趣的地方。人们在这里不仅仅是为了工作更是因为希望留在卓越团队里。\n\n\n“Unix系统的成功源于其高品位的关键概念选择及优雅的实现。Unix系统模式引领了一代软件设计者对编程的新思考。Unix系统的天才之处在于其框架它使程序员能够相互倚重。”\n\n\n会不会有另一个Unix会不会有新操作系统横空出世在几十年内占领世界当我谈到Unix时经常会被问到这样的问题。我的回答是不会至少目前不会。不会有革命发生。更有可能的是操作系统将继续发展同时携带大量的Unix DNA。\n\n\n理由是伟大的创意总来自个体。\n\n\n做好研究的最大秘诀是雇用优才确保让他们做有趣的事情着眼长久而且不横加干涉。\n\n\nUnix可能是一个奇点它是改变计算机世界的各种因素的独特组合结果。\n\n笔记\n\n道格•麦基尔罗伊神来一笔提出了管道的想法肯实现完后自己玩了一下叹道“好震撼”\n\n💭 管道流水线,真正的低耦合高内聚。\n\nUnix操作系统诞生于1969年但它不是从石头缝里蹦出来的。\n\n💭 厚积薄发\n\n每个制造商生产的硬件全无共通之处有时甚至来自同一厂商的硬件都会有很大不同所以操作系统也各自不同。\n\n💭 分久必合合久必分呀\n\n管道是一种机制由操作系统提供并通过shell轻松访问。它将程序的输出与另一程序的输入连接起来。\n\n💭 流水线设计\n\n任何你必须重复做的事都有待自动化。\n\n💭 自动化解放生产力\n\n1968年秋天开始写毕业论文时我真的很需要Runoff这样的工具否则就得自己用手动打字机打出论文每改一次都要重打或者付钱请人帮我打。我打字速度快但常打错所以前者不切实际由于我又穷又不怎么能挣钱后者也不切实际。\n\n💭 创新往往发生于资源受限的条件下\n\n在20世纪70年代中期迈克尔·莱斯克编写了UUCP即Unix到Unix的拷贝程序Unix to Unix copy program。它用于在Unix系统之间一般通过普通电话线传送文件。虽然电话线传数据速度很慢有时还很昂贵但电话线无处不在而且当时大多数Unix系统都具备某种拨号访问功能。不过具有外拨能力的较少因为这需要支付话费。\n\n💭 Unix 最初是为了文件的处理,互联网最初是为了文件的传输。就如同活字印刷术一样,信息传递效率的提升促进人类文化大爆炸式发展。\n\n杰勒德·霍尔兹曼维护着一份1127中心老同事的在线名单。太多的人已经离世活着的人里面许多去了谷歌公司其他人则在别的公司工作也有人教书或退休。只有极少数人留在贝尔实验室。\n\n💭 www.spinroot.com/gerard/1127_alumni.html\n\n将程序当作工具并组合使用是Unix的特色。编写各自做好一件事的小程序而不是功能繁多的单个大程序有很多好处。\n\n💭 做好一件事\n书评\n点评"},"Personal/Book/计算机/VMware-vSphere-7.0云平台运维与管理第2版":{"title":"VMware vSphere 7.0云平台运维与管理第2版","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《VMware vSphere 7.0云平台运维与管理第2版》\n作者 杨海艳 张文库 王印主编\n分类 计算机-计算机综合\nISBN9787121417870\n出版社电子工业出版社\n\n概述\n本书是一本以VMware vSphere 7.0平台为基础的从入门到精通的项目任务化教程项目1介绍虚拟化与云计算的基本概念项目2介绍搭建VMware企业级虚拟化平台的全过程项目3以StarWind和openfiler为例介绍iSCSI存储的搭建与配置项目4介绍部署vCenter Server的过程项目5介绍vCenter Server的高级应用项目6详细介绍VMware云桌面服务的搭建。本书不仅可以作为高等院校计算机网络技术、云计算技术专业的学生教材还可以作为对VMware vSphere云平台运维与管理技术感兴趣的读者的参考用书。\n划线\n\n裸金属架构\n\n\n寄居架构\n\n笔记\n\n计算的边界可能不是技术局限而是经济合理性。\n\n💭 效率\n书评\n点评"},"Personal/Book/计算机/人人都懂设计模式从生活中领悟设计模式Python实现":{"title":"人人都懂设计模式从生活中领悟设计模式Python实现","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《人人都懂设计模式从生活中领悟设计模式Python实现》\n作者 罗伟富\n分类 计算机-编程设计\nISBN9787121361128\n出版社电子工业出版社\n\n概述\n设计模式Design Pattern是一套被反复使用、多数人知晓、无数工程师实践的代码设计经验的总结它是面向对象思想的高度提炼和模板化。 本书带你一起从生活的角度思考设计模式,以轻松有趣的小故事开始,由浅入深地讲解每一种模式,思考每一种模式,总结每一种模式!力求用更通俗的语言阐述难懂的概念,用更简单的语法实现复杂的逻辑,用更短小的代码写出强悍的程序! 使枯燥乏味的概念变得更有乐趣和意义,希望能带给读者一种全新的阅读体验和思考方式。 本书首先讲解了23种经典设计模式其中19 种在现今的软件开发中常用的设计模式分别用单独的章节进行了详细讲解剩余设计模式作为一个合集放在一章中进行了讲解其次讲解了对基础设计模式的衍生也是各大编程语言中非常重要而常见的各种编程机制如过滤器模式、对象池技术、回调机制和MVC模式最后作者结合自身的工作经验和项目积累分享了他对设计模式、设计原则、项目重构的理解和看法。Python作为AI时代最重要的一种计算机语言其在各大语言中的排名也逐年上升本书所有示例代码均用Python编写将会是国内不可多得的一本用Python来讲解设计模式的书。 本书适合的读者一线互联网软件开发者、有一定编程基础的IT新人、对设计模式和编程思想感兴趣的人士。\n划线\n\n设计模式作为面向对象程序的设计思想和方法论本身是非常抽象和难以理解的需要有一定的代码量和编程经验才能更深入地理解。\n\n\n设计模式与编程语言没有关系它是对面向对象思想的灵活应用和高度概括\n\n\nUML 的这一整套图被分为两组,一组叫结构性图,包含类图、组件图、部署图、对象图、包图、组合结构图、轮廓图;一组叫行为性图,包含用例图、活动图(也叫流程图)、状态机图、序列图、通信图、交互图、时序图。\n\n\nUML 类图中最常见的几种关系有泛化Generalization、实现Realization、组合Composition、聚合Aggregation、关联Association和依赖Dependency。这些关系的强弱顺序为泛化=实现 > 组合 > 聚合 > 关联 > 依赖。\n\n\n在对象间定义一种一对多的依赖关系当这个对象状态发生改变时所有依赖它的对象都会被通知并自动更新。\n\n\n允许一个对象在其内部状态发生改变时改变其行为使这个对象看上去就像改变了它的类型一样。\n\n\n状态模式是说一个对象在其内部状态发生改变时其表现的行为和外在属性不一样这个对象看上去就像改变了它的类型一样。因此状态模式又称为对象的行为模式。\n\n\n状态模式的核心思想就是一个事物对象有多种状态在不同的状态下所表现出来的行为和属性不一样。\n\n\n浅拷贝只拷贝引用类型对象的指针指向而不拷贝引用类型对象指向的值深拷贝则同时拷贝引用类型对象及其指向的值。\n\n\n在使用克隆模式时除非一些特殊情况如需求本身就要求两个对象一起改变尽量使用深拷贝的方式我们称其为安全模式。\n\n\n为子系统中的一组接口提供一个一致的界面称为外观模式外观模式定义了一个高层接口这个接口使得这一子系统更容易使用。\n\n\n外观模式的核心思想用一个简单的接口来封装一个复杂的系统使这个系统更容易使用。\n\n\n对于10万行以下的代码量的汉子来说设计模式=玄学对于1050万行代码量的汉子来说设计模式=科学对于50万行以上代码量的汉子来说设计模式=文学。\n\n\n软件的设计是一个循序渐进、逐步优化的过程。\n\n\nRule of three 称为“三次法则”,指的是当某个功能第三次出现时,再进行抽象化,即事不过三,三则重构。\n\n\n1重复的代码太多没有复用性难以维护需要修改时处处都得改。2代码的结构混乱注释不清晰没有人能清楚地理解这段代码的含义。3程序没有拓展性遇到新的变化不能灵活处理。4对象结构强耦合业务逻辑太复杂牵一发而动全身维护时排查问题非常困难。5部分模块性能低随着用户数量的增长已无法满足响应速度的要求。\n\n\n一是对现有项目进行代码级别的重构二是对现有的业务进行软件架构的升级和系统的升级。\n\n\n创建型模式、结构型模式和行为型模式\n\n\n创建型即关注的是对象的创建和初始化过程结构型即关注的是对象的内部结构设计行为型即关注的是对象的特性和行为。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/从0到1HTML+CSS快速上手":{"title":"从0到1HTML+CSS快速上手","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《从0到1HTML+CSS快速上手》\n作者 莫振杰\n分类 计算机-编程设计\nISBN9787115510327\n出版社人民邮电出版社\n\n概述\n作者根据自己多年的网站开发及教学经验站在零基础读者的角度详细介绍了HTML和CSS的基础知识以及大量的前端开发技巧。 全书分为2大部分第1部分是HTML基础主要介绍各种标签的使用第二部分是CSS基础主要介绍样式布局操作。此外作者还结合实际工作及前端面试精心挑选了大量高质量的练习题放在每章最后读者可以边学边练更好地掌握本书内容。 本书提供了所有案例的源代码、配套视频课程以及各种工具手册。另外为方便老师教学还提供了配套的PPT教学课件。 本书适合零基础的初学者使用,可以作为前端开发人员的参考书,也可作为培训学校、大中专院校相关专业的教学参考书。\n划线\n\nHTML用于控制网页的结构CSS用于控制网页的外观而JavaScript控制着网页的行为。\n\n\nHTML→CSS→JavaScript→jQuery→HTML5→CSS3→ES6→移动Web→Vue.js\n\n\nHTML全称是“Hyper Text Markup Language超文本标记语言是网页的标准语言。HTML并不是一门编程语言而是一门描述性的标记语言。\n\n\ntitle标签是head标签的内部标签其中标签内定义的内容是页面的标题。这个标题不是文章的标题而是显示在浏览器栏目的那个标题。\n\n\n在HTML中一般来说只有6个标签能放在head标签内。title标签。meta标签。link标签。style标签。script标签。base标签。\n\n\n文字。图片。超链接。音频和视频。\n\n\n在HTML中我们可以使用“文本标签”来对文字进行修饰如粗体、斜体、上标、下标等。常用的文本标签有以下8种。\n\n\n在HTML中我们可以使用“div标签”来划分HTML结构从而配合CSS来整体控制某一块的样式。\n\n\n想要在一个页面引入CSS共有以下3种方式。外部样式表。内部样式表。行内样式表。\n\n\n因此我们只会讲解最实用的5种选择器。元素选择器。id选择器。class选择器。后代选择器。群组选择器。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/从0到1HTML5+CSS3修炼之道":{"title":"从0到1HTML5+CSS3修炼之道","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《从0到1HTML5+CSS3修炼之道》\n作者 莫振杰\n分类 计算机-编程设计\nISBN9787115525055\n出版社人民邮电出版社\n\n概述\n作者根据自己多年的前后端开发经验站在完全零基础读者的角度详尽介绍了HTML5和CSS3的基础知识、新技术及各种高级开发技巧。 全书分为两大部分第一部分介绍HTML5的新技术主要包括新增元素、新增属性、元素拖放、文件操作、本地存储、音频视频、离线应用等第二部分介绍CSS3的新技术主要包括新增选择器、CSS3变形、CSS3过渡、CSS3动画、多列布局、滤镜效果、弹性盒子模型等。 为了方便高校老师教学本书不但配备了所有案例的源代码还提供了配套的PPT 课件。本书适合作为前端开发人员的参考书,也可以作为大中专院校相关专业的教学参考书。\n划线\n\n4允许属性值不加引号\n\n\nHTML5新增的主要结构元素有6个header、nav、article、aside、section、footer。\n\n\n在HTML5中我们可以使用contenteditable属性来定义某个元素的内容是否可以被编辑。\n\n\n不同浏览器的localStorage数据是不可以共用的\n\n笔记\n书评\n点评"},"Personal/Book/计算机/从0到1JavaScript-快速上手":{"title":"从0到1JavaScript 快速上手","links":[],"tags":["阅读/计算机-数据库","阅读/笔记"],"content":"简介\n\n书名《从0到1JavaScript 快速上手》\n作者 莫振杰\n分类 计算机-数据库\nISBN9787115513007\n出版社人民邮电出版社\n\n概述\n本书分为2大部分第1部分是Javascript基本语法主要介绍流程控制、函数、字符串、数组等基本语法第2部分是Javascript核心技术主要介绍DOM操作、事件操作、window对象、document对象等核心技术。为了让读者更好地掌握本书还结合实际工作以及前端面试精心挑选了大量高质量的练习题。此外本书还专门配套了课件PPT以及各种工具手册以便各大高校老师教学使用。\n划线\n\nHTML用于控制网页的结构CSS用于控制网页的外观而JavaScript控制着网页的行为。\n\n\n从本质上讲Java是一门面向对象的语言而JavaScript更像是一门函数式编程语言。\n\n\n想要在HTML中引入JavaScript一般有3种方式。外部JavaScript。内部JavaScript。元素事件JavaScript。\n\n\n所有JavaScript变量都由var声明。\n\n\n在JavaScript中数据类型可以分为两种一种是“基本数据类型”另外一种是“引用数据类型”\n\n\nDOM操作可以简单地理解成“元素操作”。\n\n\n元素节点。属性节点。文本节点。\n\n\ngetElementById 。getElementsByTagName 。getElementsByClassName 。querySelector 和querySelectorAll 。getElementsByName 。document.title和document.body。\n\n\ngetAttribute 。setAttribute 。removeAttribute 。hasAttribute 。\n\n\n鼠标事件。键盘事件。表单事件。编辑事件。页面事件。\n\n\n在JavaScript中常用的表单事件有3种。onfocus和onbluronselect。onchange。\n\n\n在JavaScript中常用的页面事件只有下面2个。onload。onbeforeunload。\n\n\n哪个DOM对象元素节点调用了this所在的函数那么this指向的就是哪个DOM对象。\n\n\n在JavaScript中一个浏览器窗口就是一个window对象\n\n笔记\n书评\n点评"},"Personal/Book/计算机/从0到1jQuery快速上手":{"title":"从0到1jQuery快速上手","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《从0到1jQuery快速上手》\n作者 莫振杰\n分类 计算机-编程设计\nISBN9787115526335\n出版社人民邮电出版社\n\n概述\n作者根据自己多年的前后端开发经验站在完全零基础读者的角度基于jQuery 1.12.x版本详尽介绍了jQuery的基础知识及开发技巧。 《从0到1 jQuery快速上手》分为14章前10章主要介绍jQuery的基本技术包括常用选择器、DOM操作、事件操作、jQuery动画、过滤方法、查找方法等后4章主要介绍jQuery的进阶技巧包括工具函数、开发插件、Ajax操作以及高级技巧。 此外本书不但配备了所有案例的源代码作者还结合实际工作和前端面试的经验精选了很多高质量的练习题。为了方便高校老师教学本书还提供了配套的PPT课件。本书适合作为前端开发人员的参考书也可以作为大中专院校相关专业的教学参考书。\n划线\n\n·代码简洁。·完美兼容。·轻量级。·强大的选择器。·完善的Ajax。·丰富的插件。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/明解Python":{"title":"明解Python","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《明解Python》\n作者 柴田望洋\n分类 计算机-编程设计\nISBN9787115583765\n出版社人民邮电出版社\n\n概述\n本书图文并茂、示例丰富采用全彩印刷方式通过299段代码和165幅图表系统地讲解了Python的基础语法和编程知识内容涉及分支/循环语句、对象、字符串、列表、集合、函数、类、模块、异常处理和文件处理等。针对初学人士难以理解和容易误解的地方本书均采用平实的语言辅以精心设计的版式循序渐进、清晰直观地进行了讲解。跟随本书的讲解读者可以扎实掌握Python的基础知识并具备实际使用Python进行编程的能力。\n划线\n\n编程语言各自有擅长的领域有的擅长数值计算有的擅长数据库和事务处理。\n\n\n从这方面来说Python 可以说是一个“全能型选手”。\n\n\n有两个操作数的运算符称为二元运算符(binary operator)。除了二元运算符还有存在3个操作数的运算符—— 三元运算符(trinary operator)以及只有1个操作数的一元运算符(unary operator)。试着使用我们平时计算常用的一元运算符+和-例1-5。\n\n\n另外Python的float型相当于C语言和Java的double型而非float型。Python没有double型。\n\n\nPython从版本3.6起可以在数值字面量字符间的任意位置插入下划线“_”实际上Python程序会忽略下划线例1-8。这样可以让位数较多的数值更易于阅读。\n\n\n'''和"""能以程序代码中的字符串为基础生成类似于用户手册的程序文档。Python使用"""形式的字符串字面量来生成这种程序文档。\n\n\n以r或R开头的字符串字面量叫作原始字符串字面量(raw string literal)。原始字符串字面量中的转义字符按照原本含义解释。\n\n\n但是变量的类型并不是固定的。试着输入例1-17中的代码确认一下结果。[插图]变量x先后“变身”为整数int型、浮点数float型和字符串str型。\n\n\n前面讲的变量名都只有1个字符。关于变量名其实并不是任意名称都可以使用。命名规则大致如下。·可使用的字符包括字母、数字和下划线。·字母区分大小写。·数字不能放在变量名开头。\n\n\n交互式shell最后显示的值可以用变量“_”来表示。该变量在运算结果需要用于下次运算时非常有用。\n\n\n·作为一种迅速普及的脚本语言Python支持多种编程范式包括命令式编程、过程式编程、函数式编程和面向对象编程。\n\n\n在Python中变量、函数、类和模块皆为对象。·对象会占一定的存储空间内存并且拥有标识值用于判断是否为同一个对象、类型和值等属性。可以使用id函数获取标识值使用type函数获取类型。·变量只是一个和对象绑定引用对象的名字。·is运算符和is not运算符是身份运算符用于判断对象是否为同一个标识值是否相等。在Python中根据值是否可以改变类型可分为两类。·可变类型 列表、字典、集合等     ※值可以改变。·不可变类型数字、字符串、元组等    ※值不可以改变。如果对不可变类型的变量引用的对象的值进行变更则会生成新的对象然后变量重新引用新的对象。赋值语句复制的是对象的引用而不是值。另外赋值的对象即等号左边的变量名如果是首次使用程序则生成新的变量并与等号右边的对象进行绑定。[插图]与赋值语句相对应的是del语句它用于删除作为名字的变量名。·None与任何对象都不同是NoneType类型的特殊值。·其他编程语言使用存储期存储空间生命周期对变量和对象进行管理。Python与之不同它使用引用计数即引用对象的变量的个数对变量和对象进行管理。·内置类型包括数值型int型、bool型、float型和complex型、序列型str型、list型和tuple型等、集合型set型、frozenset型和映射型dict型。·浮点型float型可以表示的值在大小和精度方面存在限制。使用sys.float_info可以查看浮点型的属性。·在进行算术运算时程序会根据操作数的类型进行算术转换。·复数型是用表示实数部分和虚数部分的两个浮点数来表示值的类型。例如3.2 +5.7j。其中5.7j称为虚数字面量。·因为在计算机内部数值用位的ON/OFF来表示所以Python可以轻易地表示二进制数。Python提供了求逻辑与的运算符&、求逻辑或的运算符|、求逻辑异或的运算符^和生成取反后的值的运算符~等按位逻辑运算符。[插图]位移运算符<<和>>将整数中的所有的位向左或向右移动后生成相应的值。[插图]\n\n\n不包含扩展名的文件名被直接当作模块名使用。\n\n\n两个程序必须放在同一个文件夹中。\n\n\n脚本文件·直接执行时 变量__name__等于main·导入时   变量__name__等于原本的模块名在上述程序中是min_max\n\n\n如果用作包的文件夹内放置了名为init.py的文件那么具备这种标准结构的包就称为标准包(regular package)。\n\n\n文件init.py用于告知Python程序当前的包是标准包。如果没有该文件程序就无法识别出标准包代码清单10-10也将无法执行。·程序导入包后会初始化并执行模块init.py。因此我们也会看见在模块init.py中插入下一章讲解的类定义这样的编程技巧。·在init.py如果将名称__all__定义为一个列表其中包含对象名称的字符串程序就可以通过*的形式导入该名称的对象。例如在文件夹pack内的文件init.py中编写定义__all__ = [abc, xyz]程序就可以通过from pack import *导入pack.abc和pack.xyz。\n\n\n脚本程序是模块不包含扩展名的文件名是模块名。模块是较大的代码块。·模块是一种对象又称模块对象。在直接执行模块对象或导入模块对象时会生成并初始化模块对象。在直接执行脚本程序时__name__的值是main。当其他脚本程序导入脚本程序时__name__的值是模块名。\n\n\n异常处理的优点之一是可以分离原本的处理代码和处理错误的代码。\n\n\n[插图]\n\n笔记\n\n要点 变量就像一个箱子用来存储整数、浮点数和字符串等值。把相应的值放入变量后可以随时取出。\n\n💭 Python 称为标志也许更合适\n书评\n点评"},"Personal/Book/计算机/每天5分钟玩转Docker容器技术":{"title":"每天5分钟玩转Docker容器技术","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《每天5分钟玩转Docker容器技术》\n作者 CloudMan\n分类 计算机-计算机综合\nISBN9787302479703\n出版社清华大学出版社\n\n概述\nDocker和容器技术是当下最火的IT技术无论是互联网还是传统企业都在研究和实践如何用容器构建自己的 IT 基础设施。学习本书能够让读者少走弯路,系统地学习、掌握和实践 Docker 和容器技术。 本书共分为三部分。第一部分介绍容器技术生态环境。第二部分是容器核心知识,包括架构、镜像、容器、网络和存储。第三部分是容器进阶知识,包括多主机管理、跨主机网络方案、监控、日志管理和数据管理。读者在学习的过程中,可以跟着教程进行操作,在实践中掌握 Docker 容器技术的核心技能。在之后的工作中,可以将本教程作为参考书,按需查找相关知识点。 本书主要面向微服务软件开发人员,以及 IT 实施和运维工程师等相关人员,也适合高等院校和培训学校相关专业的师生教学参考。\n划线\n\n目前OCI发布了两个规范runtime spec和image format spec。\n\n\n容器OS是专门运行容器的操作系统。与常规OS相比容器OS通常体积更小启动更快。因为是为容器定制的OS通常它们运行容器的效率会更高。\n\n\nkubernetes是Google领导开发的开源容器编排引擎同时支持Docker和CoreOS容器。\n\n\nDocker分为开源免费的CECommunity Edition版本和收费的EEEnterprise Edition版本。\n\n\n容器使软件具备了超强的可移植能力。\n\n\n其实“集装箱”和“容器”对应的英文单词都是“Container”。\n\n\nDocker的核心组件包括● Docker客户端Client● Docker服务器Docker daemon● Docker镜像Image● Registry● Docker容器Container\n\n\n每个容器都有一个软件镜像相当于集装箱中的货物。容器可以被创建、启动、关闭和销毁。和集装箱一样Docker在执行这些操作时并不关心容器里到底装的什么它不管里面是Web Server还是Database。\n\n\nbase镜像有两层含义1不依赖其他镜像从scratch构建2其他镜像可以以之为基础进行扩展。\n\n\n如果docker run指定了其他命令CMD指定的默认命令将被忽略。● 如果Dockerfile中有多个CMD指令只有最后一个CMD有效。\n\n\n对于服务类容器我们通常希望在这种情况下容器能够自动重启。启动容器时设置 —restart就可以达到这个效果\n\n\ncgroup和namespace是最重要的两种技术。cgroup实现资源限额namespace实现资源隔离。\n\n\nVLAN是现代网络常用的网络虚拟化技术它可以将物理的二层网络划分成最多4094个逻辑网络这些逻辑网络在二层上是隔离的每个逻辑网络即VLAN由VLAN ID区分VLAN ID的取值为14094。\n\n\nELK是三个软件的合称Elasticsearch、Logstash、Kibana。\n\n\n无状态是指容器在运行过程中不需要保存数据每次访问的结果不依赖上一次访问比如提供静态页面的Web服务器。\n\n\n[插图]\n\n笔记\n书评\n点评"},"Personal/Book/计算机/流畅的Python":{"title":"流畅的Python","links":["/"],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《流畅的Python》\n作者 卢西亚诺·拉马略\n分类 计算机-编程设计\nISBN9787115454157\n出版社人民邮电出版社\n\n概述\n本书致力于帮助Python开发人员挖掘这门语言及相关程序库的优秀特性避免重复劳动同时写出简洁、流畅、易读、易维护并且具有地道Python风格的代码。本书尤其深入探讨了Python语言的高级用法涵盖数据结构、Python风格的对象、并行与并发以及元编程等不同的方面。\n划线\n\nPython官方教程的开头是这样写的“Python是一门既容易上手又强大的编程语言。”这句话本身并无大碍但需要注意的是正因为它既好学又好用所以很多Python程序员只用到了其强大功能的一小部分。\n\n\n不成熟的抽象和过早的优化一样都会坏事。\n\n\n数据模型其实是对Python框架的描述它规范了这门语言自身构建模块的接口\n\n\n序列类型还能按照能否被修改来分类。可变序列list、bytearray、array.array、collections.deque和memoryview。不可变序列tuple、str和bytes。\n\n\nlist是一个可变序列并且能同时存放不同类型的元素\n\n\n在Python中函数用*args来获取不确定数量的参数算是一种经典写法了。\n\n\nseq[start:stop:step]进行求值的时候Python会调用seq.getitem(slice(start, stop, step))。\n\n\n如果在a * n这个语句中序列a里的元素是对其他可变对象的引用的话你就需要格外注意了因为这个式子的结果可能会出乎意料。比如你想用my_list= * 3来初始化一个由列表组成的列表但是你得到的列表里包含的3个元素其实是3个引用而且这3个引用指向的都是同一个列表。这可能不是你想要的效果。\n\n\nPython Tutor是一个对Python运行原理进行可视化分析的工具\n\n\n不要把可变对象放在元组里面。增量赋值不是一个原子操作。我们刚才也看到了它虽然抛出了异常但还是完成了操作。查看Python的字节码并不难而且它对我们了解代码背后的运行机制很有帮助。\n\n\nPython序列类型最常见的分类就是可变和不可变序列。但另外一种分类方式也很有用那就是把它们分为扁平序列和容器序列。\n\n\n散列表则是字典类型性能出众的根本原因\n\n\n集合的本质是许多唯一对象的聚集。\n\n\n不要忘了如果要创建一个空集你必须用不带任何参数的构造方法set 。如果只是写成{}的形式,跟以前一样,你创建的其实是个空字典。\n\n\ndict的实现是典型的空间换时间字典类型有着巨大的内存开销但它们提供了无视数据量大小的快速访问——只要字典能被装在内存里。\n\n\nPython 3明确区分了人类可读的文本字符串和原始的字节序列。\n\n\n我指的是b\\xff\\xfe。这是BOM即字节序标记byte-order mark指明编码时使用Intel CPU的小字节序。\n\n\n__doc__属性用于生成对象的帮助文本。\n\n\nmap函数返回一个可迭代对象里面的元素是把第一个参数一个函数应用到第二个参数一个可迭代对象这里是range(11))中各个元素上得到的结果。\n\n\n接受函数为参数或者把函数作为结果返回的函数是高阶函数higher-order function\n\n\nall(iterable)如果iterable的每个元素都是真值返回Trueall([])返回True。any(iterable)只要iterable中有元素是真值就返回Trueany([])返回False。\n\n\nPython简单的句法限制了lambda函数的定义体只能使用纯表达式。换句话说lambda函数的定义体中不能赋值也不能使用while和try等Python语句。\n\n\nlambda句法只是语法糖与def语句一样lambda表达式会创建函数对象。这是Python中几种可调用对象的一种。下一节会说明所有可调用对象。\n\n\n不仅Python函数是真正的对象任何Python对象都可以表现得像函数。为此只需实现实例方法__call__。\n\n\n与用户定义的常规类一样函数使用__dict__属性存储赋予它的用户属性。\n\n\nPython最好的特性之一是提供了极为灵活的参数处理机制而且Python 3进一步提供了仅限关键字参数keyword-only argument。\n\n\n函数装饰器用于在源码中“标记”函数以某种方式增强函数的行为。\n\n\nPython不要求声明变量但是假定在函数定义体中赋值的变量是局部变量。\n\n\nPython内置了三个用于装饰方法的函数property、classmethod和staticmethod。\n\n\n因为lru_cache使用字典存储结果而且键根据调用时传入的定位参数和关键字参数创建所以被lru_cache装饰的函数它的所有参数都必须是可散列的。\n\n\n首先我们要抛弃变量是存储数据的盒子这一错误观念\n\n\nPython变量类似于Java中的引用式变量因此最好把它们理解为附加在对象上的标注。\n\n笔记\n\n在运行时创建\n能赋值给变量或数据结构中的元素\n能作为参数传给函数\n能作为函数的返回结果\n\n💭 感觉这个一等函数好抽象或者是翻译的问题……\n书评\n点评"},"Personal/Book/计算机/硅谷之火个人计算机的诞生与衰落第3版":{"title":"硅谷之火个人计算机的诞生与衰落第3版","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《硅谷之火个人计算机的诞生与衰落第3版》\n作者 迈克尔·斯韦因 保罗·弗赖伯格\n分类 计算机-计算机综合\nISBN9787115516824\n出版社人民邮电出版社\n\n概述\n本书是一部微型计算机发展史让读者了解整个20世纪以及至21世纪初计算机从兴起到鼎盛直至今天受到平板电脑和手机等电子产品冲击的整个过程是一本集历史故事与小说风格于一体的硅谷纪传体书籍。最新第3版重新修订了全书内容增加了计算机发展史上的几位大佬退出舞台后的计算机行业现状分析。\n划线\n\n一切事物都会随着时间而变化不变也是一种变化。\n\n\n个人计算机行业的创业者几乎什么错误都犯过。他们的前车之鉴可以为你省下不少的金钱、时间和精力。\n\n\n乔布斯冲着弗赖伯格怒吼因为弗赖伯格打算抢先刊登出苹果公司Lisa项目和麦金塔计算机的故事乔布斯指责他这是在给日本人占领美国计算机市场做帮凶。\n\n\n这个传奇故事的主角是一群了不起的、信奉无政府主义的工程师、黑客和他们的同道中人他们起初是一种真正的反主流文化但最终改变了世界。\n\n\n计算机行业在20世纪70年代诞生出现在围绕斯坦福大学的郊野地带是那个非凡时期的直接产物。\n\n\n史蒂夫·乔布斯也曾对本书的第一版赞誉有加“这本书让我回想起那些旧时光读着读着我不禁潸然泪下。”\n\n\n与他们谈工作是我们工作的一部分但当我们撇开当天的议事日程放下采访提纲对他们说“跟我们说说你当初是怎么开始的吧”时谈话氛围就会立刻发生明显的变化。他们会就此开始讲述而且通常知无不言、言无不尽。\n\n\n个人计算机的起源也颇具革命性因为它并不是由那些搞研发的专业团队在成本昂贵、设备精良的实验室研制出来的。它始于企业和学术机构之外由黑客、计算机发烧友和误打误撞的创业者利用业余时间在车库、地下室和卧室等地方创造出来。\n\n\n因为奥古斯塔·艾达·拜伦所做的这些工作许多人视她为世界上第一位计算机程序员。\n\n\n最好能让自己的听众放心巴贝奇的分析机并没有独立思考的能力。\n\n\n计算机将披着逻辑的嫁衣“嫁”给电力。\n\n\n霍列瑞斯的公司最终被一家企业合并了这家企业后来更名为国际商用机器公司简称IBM\n\n\n克劳德·香农在其麻省理工学院的博士论文中解释了如何利用电力开关电路模拟布尔逻辑\n\n\n美国圣何塞计算机博物馆历史中心\n\n\n晶体管是一小片惰性晶体具有有趣的电气特性一面世即被视为一项革命性技术发明\n\n\n英特尔完全有资历完成此事它是仙童半导体公司的衍生公司其总裁罗伯特·诺伊斯曾为集成电路的发明贡献过力量。\n\n\n英特尔的市场部对微处理器客户支持工作量巨大的担忧不无道理。比如说用户需要芯片功能的说明文档、芯片能识别语言的说明文档、芯片使用的电压、发热情况和其他一系列问题的说明文档。总得有人来编写使用手册吧。\n\n\nDEC公司本可以成为第一家创造个人计算机的公司却未能抓住这个机会。这在某种程度上反映了20世纪70年代初期计算机公司董事会成员的保守观念。\n\n\n阿尔的兴趣越来越浓厚他已不再能容忍DEC公司的保守作风。DEC公司视计算机为一种工业产品。阿尔后来回忆说“在他们看来计算机就如同一块生铁。他们只对卖铁感兴趣”\n\n\n阿尔沮丧到了极点。先前他就常接到猎头公司寻聘高层人员的电话他决定再有猎头找他他就接受。于是他像沃兹尼亚克、阿尔布莱特和许多其他人一样走出了公司大门投身到革命的浪潮中。\n\n\nMITS公司开创了一个完整的个人计算机产业链从商店、出版物、展会、用户群、软件盗版到关于开放标准与封闭标准的辩论一应俱全。\n\n\n新改名为微型软件公司Micro-Soft后来又改为微软公司Microsoft的Traf-O-Data公司终于作为软件厂家做成了第一笔交易。\n\n\n此后一段时间里纸带成了传播这种语言的主要手段。盖茨后来十分痛恨这些纸带因为纸带成了非法传播BASIC的媒介。\n\n\n创立计算机俱乐部是很自然的毕竟当时的设备时常不能运转或不能正常运转软件要么不能用要么根本没有软件可用。虽然买家多半是发烧友但极少有人能完全掌握微型计算机所需的所有技能和知识。俱乐部鼓励那些精于机器不同方面的人相互交流协同合作。若是没有这种互动和互助计算机产业不可能发展得这样繁荣。\n\n\n发烧友看到4K存储板如此不值钱而BASIC又卖得那么昂贵于是纷纷购买了Proc Tech公司的存储板复制BASIC纸带并私自传播。到1975年年底大多数Altair上使用的BASIC都是盗版的。\n\n\n罗伯茨在佐治亚州买了一个农场并告诉所有人他打算成为一个乡绅去务农或者去学医。最后罗伯茨拿出当初创办MITS公司时的精气神两样都做到了。\n\n\n没有大公司愿意制造微型计算机。只有那些全然盲目地被计算机和电子学迷了心窍的狂热分子才愿意设计并亲手制造一台计算机并忍受那些繁复而乏味的工作\n\n\n以姆赛公司是比尔·米勒德在1975年1月Altair宣告问世的几个月后创办的其创业故事和企业理念都是独一无二的。\n\n\n在工程部、生产部和客户支持部看来销售团队在盲目推销这就是在拆公司的台。以姆赛公司重视成功这没什么问题。但管理层衡量成功的标准首先是销售额而不是生产或客户服务的质量。以姆赛公司成了专门卖东西的机器若从这个角度看它确实干得很好。\n\n\n因此大多数的“商业”用户其实就是一些希望能将这些机器用于商业的发烧友这些人之所以能够忍受机器的缺陷是因为他们在学习如何使用机器来办公并乐在其中。\n\n\n承认有问题就等于承认失败而以姆赛公司的企业文化是不允许承认失败的。不愿承认失败的态度以及对“伟大的业务目标”一根筋的执着最终导致以姆赛公司对目标客户的定位出现偏差与市场的本质渐行渐远。\n\n\n发烧友是一场草根运动。这些发烧友清楚地知道他们所引燃的不仅是一场技术革命还是一场社会革命。\n\n\n因为英特尔公司的芯片的名称里通常会有“8”这个数字而摩托罗拉公司则通常用“6”这个数字所以双方的支持者就分别被称为“8字头用户”和“6字头用户”。\n\n\n许多公司的创办初衷与其说是为了挣大钱不如说是为了寻求刺激。这些事情都说明一些无法从经济利益的视角解释的事情正在发生。\n\n\n就这样这帮富于创造、独断专行的人为了整个微型计算机领域的利益一点一点地放下了自我的固有成见也摒弃了任何短期的经济利益。\n\n\n公司里没人认为这是一种正常的商业模式也许连埃里森自己也不相信但是无论如何在成立后的前十年甲骨文公司确实每年都实现了销量翻倍的目标。\n\n\n如果说Q&A程序体现了试水软件市场的易用性战略那么Framework就体现了“瑞士军刀”式的软件营销方式。\n\n\n盖茨已有将近4年没写过代码了。他上一次写代码还是为Tandy公司TRS-80100型便携式计算机做软件的时候那是一台书本大小的便携式计算机来访者对那台机器赞不绝口。盖茨很紧张通宵达旦地熟悉QuickBASIC。一位名叫杰夫·邓特曼的记者是个编程高手他将使用Turbo Pascal邓特曼对Turbo Pascal非常了解。比赛结果是盖茨和QuickBASIC赢了。这件事很疯\n\n\n它们在一开始时主要是基于社区构建的。\n\n\n相继开辟了揭发黑幕的专栏提醒购买者注意特定产品的缺点。《人民计算机公司》通信的分支机构《多布博士》杂志坚定地站在消费者的立场上引导读者不要购买今后会让自己后悔的那些产品。\n\n\n正如赫尔默斯所言如果说那些杂志界定了微型计算机社区那么沃伦等人举办的电脑展则为这个社区提供了聚会的场所。\n\n\n乔布斯似乎在摆脱生活中的琐事寻求某种彻底的简单。\n\n\n乔布斯给了沃兹尼亚克350美元作为工作报酬这个数字远少于乔布斯留给自己的6650美元。和乔布斯友谊也就值这么多。\n\n\n乔布斯告诉科特克“我会给你一份工作。我们要做一件惊人的事这事叫作30天内付款。”\n\n\n乔布斯意识到要想提高竞争力苹果计算机必须美观。\n\n\n沃兹尼亚克设计计算机是为了追逐自己的梦想机器但Apple III有点儿像很多人七拼八凑而成的大杂烩是由委员会操刀设计的。作为委员会的典型产物各方成员都对结果不太满意。\n\n\n斯科特被沃兹尼亚克反复无常的工作习惯以及Apple III的上市延误激怒了于是开始对沃兹尼亚克施加压力。沃兹尼亚克没日没夜地工作每天都忍受着斯科特对他进度缓慢的抱怨。\n\n\n一旦你没什么可以失去的那就追逐月亮吧。于是我们追逐着月亮而且我们一直知道如若成功这要同时归功于苹果公司和IBM公司。\n\n\n与美国社会上的大多数情况一样计算机行业里的人变得越来越喜欢打官司\n\n\nJava明明是编程语言而不是操作系统为什么能对微软构成如此巨大的威胁呢原因很简单。编写跨平台的程序能有效地增加浏览器取代操作系统的可能性。拥有太阳工作站、IBM PC、麦金塔计算机或其他什么计算机都没关系反正你能用浏览器运行Java程序就行了。\n\n\n阿尔伯克基和硅谷的电子发烧友并没有发明万维网但万维网的问世在很大程度上归功于信息共享精神这种精神点亮了个人计算机革命的前十年。实际上我们可以认为万维网是共享精神在软件领域的体现。\n\n\n1991年芬兰一位名叫林纳斯·托瓦兹Linus Torvalds的年轻程序员开始开发Unix内核在操作系统中负责处理内存、文件及外部接口等基本操作的新变体。托瓦兹将他的操作系统命名为Linux并公开了源代码邀请编程社区对其加以改进。\n\n\n开放”和“免费”并不是一回事。\n\n\n网景公司的Mozilla项目完成了一个新版本的浏览器。\n\n\n没有乔布斯苹果公司不过是硅谷一家普通的计算机公司而没有苹果公司乔布斯也只是硅谷一名普通的百万富翁。\n\n\n乔布斯回到了苹果公司。他告诉我微软赢得了个人计算机之战而且那是不可逆转的这一切已经过去了。但他认为如果他能让苹果公司足够强健支撑到下一轮重大科技洗牌到那时苹果公司就能打胜仗。\n\n\n图形化用户界面由帕洛阿尔托研究中心发明由苹果公司引入市场又由微软公司发扬光大。\n\n\n“我记得约翰·斯卡利谈到过技术S型曲线……这就是说一种技术会有一段长而平缓的酝酿期然后会有一段突然的飞速发展期接着在市场饱和或技术成熟时达到顶点。此时这种技术在市场上将变得不再有趣如果你的公司为那种技术赌上了一切的话……你最终会被仿造产品逼上绝路。”\n\n\n如果说个人计算机产业的控制之战已经结束那么乔布斯相信苹果公司的希望就是尽量拖下去撑到成为下一波浪潮的弄潮儿。\n\n\niPod的销售进展则要慢一些但到2004年年底苹果公司和它的iPod在不断发展的数字音乐播放器市场上获得了大约2/3的份额。市场很大利润很高。2007年苹果公司的收入大约有一半都来自iPod的销售。苹果已经找到了一个新兴市场并且主导了它乔布斯知道苹果公司一定能够做到这一点。\n\n\n而苹果公司的iOS系统则是其自身产品的专有平台。\n\n\n现在移动设备的两种不同模式展开了竞争开放的安卓模式和封闭的iOS模式。\n\n\n2010年苹果公司终于回归平板市场和iPod、iPhone一样iPad成为另一种定义类的产品。\n\n\n2014年一手创办甲骨文公司的拉里·埃里森不再担任公司的CEO。很多划时代的个人计算机公司现已消失其中包括被甲骨文公司收购的太阳微系统公司。在硅谷大家普遍感到元老派已经谢幕一群年轻聪明的黑客控制了产业。在产品方面这些年轻聪明的黑客正驾驶着技术的列车驶入一个新的时代。\n\n\n我们能阻止计算机带走我们的隐私、自主权和自由吗\n\n\n改变世界无时无刻不在发生。\n\n笔记\n\n许多热衷于让个人计算机成为现实的人同样热衷于为大众普及晦涩的计算机技术。“让大众拥有计算机的力量”是他们的战斗口号同时这确实也是塑造个人计算机时代的力量之一。\n\n💭 唯有热爱可抵岁月漫长\n\n我认为全世界的计算机需求量大概是五台左右。\n——托马斯·沃森IBM公司主席\n\n💭 时代局限性\n\n盖茨后来回忆坐着蓝鹅车队四处游历的经历时这么说“蓝鹅就是通用汽车公司所谓的移动的家车型。我们开着蓝鹅到全美各地宣传每到一个地方就动员当地的人成立计算机俱乐部。\n\n💭 酒香也怕巷子深\n\n“一旦你经历过那种失败”罗伯茨说“每天晚上都睡不着担心第二天能不能发得出工资……你就会像我这样草木皆兵做出一些不合逻辑的决策。”\n\n💭 情绪,压力\n\n这种心理后来被称为“创业者症”指不管他人开价多高创始人都不愿将公司的控制权分给其他任何人的心理。\n\n💭 创业者症状\n\n“我有一个车库。”马什告诉英格拉姆。听起来这就足以开始创业了。\n\n💭 我有30年的房贷奥利给\n\n如果用现金结账当场就可以打八折。令马什颇感失望的是会中和会后都没有人去找他\n\n💭 道路是曲折的,前途是光明的\n\n编写一个紧凑到仅占用几百字节内存的国际象棋程序\n\n💭 有限的资源更能激发无限的能量\n\n我努力让大众看到我所看到的事物如果要管理一家公司那么你必须让大众相信你的想法。\n\n💭 信任感\n\n在一些情况下这些早期公司失败的原因是计算机方面的技术问题但更多原因是这些公司缺少管理、市场营销、分销以及产品销售等方面的专业技能。这些企业的领导者基本都不是经济管理人员而是工程师他们并不精通生意之道而且经常与其客户和经销商格格不入。\n\n💭 打江山不易,守江山更难\n\n沃兹尼亚克自己制作了控制驱动器的电路板。连续两周他每晚都工作到凌晨2点。\n\n💭 热血激情\n\n在盖茨看来只有永不停止地工作、积极地参与竞争和不知疲倦地发挥聪明才智他本人和微软公司才能保持行业的领先地位。盖茨总觉得在某些地方肯定有几个聪明而有干劲的黑客能在短短几个月内就编写出好几千行精致的代码从而在一夜之间改变竞争规则将微软挤下舞台。\n\n💭 保持危机感\n书评\n点评"},"Personal/Book/计算机/秒懂设计模式":{"title":"秒懂设计模式","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《秒懂设计模式》\n作者 刘韬\n分类 计算机-编程设计\nISBN9787115549365\n出版社人民邮电出版社\n\n概述\n本书共计25章以轻松、幽默、浅显易懂的文风从面向对象编程、面向对象三大特性的理论基础开篇然后系统且详细地讲解了单例、原型、工厂方法、抽象工厂、建造者、门面、组合、装饰器、适配器、享元、代理、桥接、模板方法、迭代器、责任链、策略、状态、备忘录、中介、命令、访问者、观察者及解释器等23种设计模式的概念及结构机理最后以六大设计原则收尾全面地解析归纳了软件设计准则参透设计模式的本质。本书引入了很多贴近生活的真实范例并配有大量生动形象的插图再结合相关例程代码实战演练循序渐进、深入浅出引导读者探究设计模式的哲学真谛。本书面向广大的软件设计工作者包括但不限于各个层次从事面向对象编程语言开发的软件开发、设计、架构等工程技术人员也可以作为大专院校相关专业教学用书和培训学校的教材。\n划线\n\n代码量大并不能代表系统功能多么完备更不能代表程序员多么努力与优秀反之作为有思想高度的开发者一定要培养“偷懒”意识想方设法以最少的代码量实现最强的功能这样才是优秀的设计。\n\n\n设计模式主要研究的是“变”与“不变”以及如何将它们分离、解耦、组装将其中“不变”的部分沉淀下来避免“重复造轮子”而对于“变”的部分则可以用抽象化、多态化等方式增强软件的兼容性、可扩展性。\n\n\n优秀的系统不单单在于其功能有多么强大更应该将各个模块划分清楚并且拥有一套完备的框架像开放式平台一样兼容对各种插件的扩展让功能变动或新增变得异常简单一劳永逸这离不开对各种设计模式的合理运用。\n\n\n从某种意义上讲设计模式并不是指某种具体的技术而更像是一种思想一种格局。\n\n\n“封装”“继承”和“多态”便是面向对象的三大特性\n\n\n如果把一些不相干的对象硬生生封装在一起就会使代码变得莫名其妙难于维护与管理所谓“物极必反过犹不及”所以封装一定要适度。\n\n\n继承可以使父类的属性和方法延续到子类中这样子类就不需要重复定义并且子类可以通过重写来修改继承而来的方法实现或者通过追加达到属性与功能扩展的目的。从某种意义上讲如果说类是对象的模板那么父类或超类则可以被看作模板的模板。\n\n\n我们知道任何类都有一个toString()方法但我们根本没有声明它这是为什么呢其实这是从Object类继承的方法因为Object是一切类的祖先类。\n\n\n多态化的外设使计算机功能更加强大、灵活、可扩展、可替换。其实这就是设计模式中非常重要的一种“策略模式”接口的定义是解决耦合问题的关键所在。\n\n\n我们都知道有一种设备叫转换器它能轻松地将老旧的接口设备调制适配到新的接口以达到兼容的目的这就是“适配器模式”。\n\n\n单例即单一的实例确切地讲就是指在某个系统中只存在一个实例同时提供集中、统一的访问接口以使系统行为保持协调一致。\n\n\n这就是“饿汉模式”(eager initialization),即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。\n\n\n这就是“懒汉模式”(lazy initialization\n\n\n这样的好处是如无请求就不实例化节省了内存空间而坏处是第一次请求的时候速度较之前的饿汉初始化模式慢因为要消耗CPU资源去临时造这个太阳即使速度快到可以忽略不计。\n\n\n我们一共用了2个嵌套的判空逻辑这就是懒加载模式的“双检锁”外层放宽入口保证线程并发的高效性内层加锁同步保证实例化的单次运行。\n\n\nSingleton单例包含一个自己的类实例的属性并把构造方法用private关键字隐藏起来对外只提供getInstance()方法以获得这个单例对象。\n\n\n原型模式可以用对象创建对象而不是用类创建对象以此达到效率的提升。\n\n\n对于第一份打印出来的原文稿我们可以称之为“原型文件”而对于复印过程我们则可以称之为“原型拷贝”\n\n\n程序设计中的工厂类往往是对对象构造、实例化、初始化过程的封装\n\n\n制造逻辑只是被换了个地方挪到了简单工厂中而已并且客户端还要告知产品种类才能产出这无疑是另一种意义上的耦合。\n\n\n大量的产品判断逻辑代码会被堆积在制造方法中看起来好像功能强大、无所不能其实维护起来举步维艰简单工厂就会变得一点也不简单了。\n\n\n多态化后的工厂多样性不言而喻每个工厂的生产策略或方式都具备自己的产品特色不同的产品需求都能找到相应的工厂来满足\n\n\n工厂方法模式不但能将客户端与敌人的实例化过程彻底解耦抽象化、多态化后的工厂还能让我们更自由灵活地制造出独特而多样的产品。\n\n\n需要注意的是抽象工厂模式一定是基于产品的族系划分来布局的其产品系列一定是相对固定的故以抽象工厂来确立工业制造标准各产品系列生产接口。\n\n\n建造者模式又称为生成器模式主要用于对复杂对象的构建、初始化它可以将多个简单的组件对象按顺序一步步组装起来最终构建成一个复杂的成品对象。与工厂系列模式不同的是建造者模式的主要目的在于把烦琐的构建过程从不同对象中抽离出来使其脱离并独立于产品类与工厂类最终实现用同一套标准的制造工序能够产出不同的产品。\n\n\n建造者的各制造步骤与逻辑都应该被抽离出来独立于数据模型\n\n\n我们可以用组合模式来表达“部分/整体”的层次结构,提取并抽象其相同的部分,特殊化其不同的部分,以提高系统的可复用性与可扩展性,最终达到以不变应万变的目的。\n\n\n优雅、巧妙的方式将两侧“对立”的接口“整合”在一起顺利化解双方难以调和的矛盾最终使它们顺利接通\n\n\n当系统存在大量的对象并且这些对象又具有相同的内部状态时我们就可以用享元模式共享相同的元件对象以避免对象泛滥造成资源浪费。\n\n\n其实路由器本质上并不具备上网功能而只是充当代理角色对访问进行监管、控制与转发。\n\n\n如代码清单12-4所示客户端终端设备一开始创建的并不是“猫”而是实例化路由器来连接互联网。简单来讲就是用户只需要知道连接路由器便可以上网了至于“猫”是什么用户完全可以无视\n\n\n桥接模式(Bridge)能将抽象与实现分离,使二者可以各自单独变化而不受对方约束,使用时再将它们组合起来\n\n\n拿手机制造来说芯片可以由美国设计制造屏幕可以由韩国制造摄像头则可以由日本制造……最后由中国制造其他半导体组件并完成手机的组装从而形成手机制造产业链并使产品高效生产\n\n\n抽象方”与“实现方\n\n\n桥接模式将抽象与实现彻底解耦使形状与颜色的纠葛终被化解各自为营互不侵扰。劳动分工实现了各种产品制造的自由扩展使其能够在各自维度上达成多态无限延伸。\n\n\n需求分析、软件设计、代码开发、质量测试、上线发布。\n\n\n模板方法模式巧妙地结合了抽象类虚部方法与实部方法分别定义了可变部分与不变部分其中前者留给子类去实现保证了系统的可扩展性而后者则包含一系列对前者的逻辑调用为子类提供了一种固有的应用指导规范从而达到虚中带实、虚实结合的状态。\n\n\n如代码清单16-9所示一开始我们在第4行构造了财务专员接着组装了责任链其实这里还可以交给工作流工厂去构造责任链\n\n\n策略模式让策略与系统环境彻底解耦通过对算法策略的抽象、拆分再拼装、接入外设使系统行为的可塑性得到了增强\n\n\n变化是世界的常态唯一不变的就是变化本身。\n\n\n备忘录模式(Memento)则可以在不破坏元对象封装性的前提下捕获其在某些时刻的内部状态,并像历史快照一样将它们保留在元对象之外,以备恢复之用。\n\n\n中介模式(Mediator)为对象构架出一个互动平台,通过减少对象间的依赖程度以达到解耦的目的\n\n\n众所周知对象间显式的互相引用越多意味着依赖性越强同时独立性越弱不利于代码的维护与扩展。中介模式很好地解决了这些问题\n\n\n命令模式(Command)能够将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,以使命令的请求方与执行方解耦,双方只通过传递各种命令过象来完成任务\n\n\n命令模式能使我们在不改变任何现有系统代码的情况下实现命令功能的无限扩展\n\n\n观察者模式(Observer)可以针对被观察对象与观察者对象之间一对多的依赖关系建立起一种行为自动触发机制,当被观察对象状态发生变化时主动对外发起广播,以通知所有观察者做出响应。\n\n\n总之不是自己分内之事绝不该负责这就是单一职责原则(Single Responsibility Principle)。\n\n\n所以我们需要把闪烁控制电路独立出来灯泡与闪烁之间的通信应该通过接口去实现从而划清界限各司其职这样类封装才变得有意义\n\n\n其中“开”指的是对扩展开放而“闭”则指的是对修改关闭。简单来讲就是不要修改已有的代码而要去编写新的代码。\n\n\n所以说符合开闭原则的设计一定要通过抽象去实现高层抽象的泛化保证了底层实现的多态化扩展而不需要对现有系统做反复修改。\n\n\n当系统升级时如果为了增强系统功能而需要进行大量的代码修改则说明这个系统的设计是失败的是违反开闭原则的。\n\n\n此原则指的是在任何父类出现的地方子类也一定可以出现也就是说一个优秀的软件设计中有引用父类的地方一定也可以替换为其子类。\n\n\n接口隔离原则要求我们对接口尽可能地细粒度化拆分开的接口总比整合的接口灵活\n\n\n世界上并不存在无所不能的设计而且任何事物都有其两面性任何一种设计模式都有其优缺点所以对设计模式的运用一定要适可而止否则会使系统臃肿不堪。满足目前需求并在未来可预估业务范围内的设计才是最合理的设计。当然在系统不能满足需求时我们还可以做出适当的重构这样的设计才是切合实际的。\n\n笔记\n\n究其本质克隆操作时Java虚拟机会进行内存操作直接拷贝原型对象数据流生成新的副本对象绝不会拖泥带水地触发一些多余的复杂操作如类加载、实例化、初始化等所以其效率远远高于“new”关键字所触发的实例化操作\n\n💭 池复用模式\n\n众所周知对象间显式的互相引用越多意味着依赖性越强同时独立性越弱不利于代码的维护与扩展。\n\n💭 插件系统也是类似\n\n在面向对象的软件设计中人们经常会遇到一些重复出现的问题。为降低软件模块的耦合性提高软件的灵活性、兼容性、可复用性、可维护性与可扩展性人们从宏观到微观对各种软件系统进行拆分、抽象、组装确立模块间的交互关系最终通过归纳、总结将一些软件模式沉淀下来成为通用的解决方案这就是设计模式的由来与发展。\n\n💭 效率\n\n单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则它们通常被合起来简称为“S.O.L.I.D”原则也是最为流行的一套面向对象软件设计法则。最后我们再附加上迪米特法则简称“LoD”。接下来我们将依次研究这六大原则。\n\n💭 设计模式的根本依据\n\n设计模式绝不可以被滥用以免陷入“为了设计而设计”的误区导致过度设计。\n\n💭 切勿让设计模式成为开发的绊脚石\n书评\n点评"},"Personal/Book/计算机/程序员的README":{"title":"程序员的README","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《程序员的README》\n作者 克里斯·里科米尼 德米特里·里亚博伊\n分类 计算机-计算机综合\nISBN9787115599438\n出版社人民邮电出版社有限公司\n\n概述\n对于刚刚成为软件工程师的新手来说知道如何编写代码只是成功了一半。你可能很快就会发现学校并没有教授在现实世界中至关重要的技能和工作中必要的流程。本书恰恰填补了这一环节它是作者十多年来在大型公司指导初级工程师工作的教程涵盖软件工程的基础知识和best实践。 本书第12 章讲解当你在公司开启你的职业生涯时会发生什么第311 章会扩展你的工作技能教你如何使用现有代码库、解决和防止技术债、编写生产级软件、管理依赖关系、有效地测试、评审代码、交付软件、处理On-Call 时的事故和构建可演进的架构等;剩余章节涵盖管理能力和职业阶梯的提升等相关内容,例如敏捷计划、与管理者合作以及成长为资深工程师的必经之路。本书中非常重要的一部分内容是教你如何应对糟糕的管理,以及如何调整自己的节奏。 本书内容不仅浅显易懂,还覆盖整个软件开发周期,是一本技术主管希望每名新入行的工程师在开始工作之前都能阅读的书。\n划线\n\n本书中非常重要的一部分内容是教你如何应对糟糕的管理以及如何调整自己的节奏。\n\n\n还覆盖整个软件开发周期是一本技术主管希望每名新入行的工程师在开始工作之前都能阅读的书。\n\n\n一名成熟的软件开发者的标志是打破固有的习惯批判性地回顾旧代码发现瑕疵做到自省且为没多做些什么而感到羞愧。\n\n\n在本书的前几章中“提问”就被高度重视这让我感到非常高兴。向同事提问和学习是快速成长和习得新技能的有效方式。为你的工作成果感到自豪通常是件好事但当自己在持续改进和交付中比以前做得更好时你应该优先感到自豪。\n\n\n软件开发本身带来的欣喜是一种“尤里卡时刻”的幸福体验尤其是在无数个面对调试器“狂按”F10键的夜晚自己提交的特性成功上线时的喜悦抑或是眼看着自己设计的技术架构方案从纸面上的框图到代码实现再到最终交付的满足感。\n\n\n在实际的工作中成功地交付软件并不是只有唯一的路径可走。如何衡量与之匹配的需求、成本和风险才是考验团队的地方。\n\n\n翻译完本书的最后一章时正好是我踏入软件行业的12年整此时的我却觉得自己的职业生涯好像才刚刚开始。\n\n\n知道如何编写代码——也就是如何使用计算机去解决问题仅仅是“战斗的一半”。\n\n\n然而要成为一名高效的软件工程师你还需要那些学校里没有教授过的技能。而本书将会教你这些技能。\n\n\n撰写设计文档、如何维护旧代码、如何On-Call待命、如何规划你的工作以及如何与你的管理者和团队互动\n\n\n当你能够安全地交付代码并与你的团队无缝协作时你就会到达这个里程碑。\n\n\n你知道如何使用集成开发环境(IDE)、构建系统、调试代码和测试框架。你熟悉持续集成、系统指标和监控、配置和打包系统。你积极主动地创建和改进测试代码。在做架构决策时,你会考虑到长期运维。\n\n\n在模棱两可的情况下你会主动寻求帮助并得到明确的结果。你能以建设性的方式提出问题和定义课题。\n\n\n你会文档化你的工作。\n\n\n重点并不是要写一份完美的文档而是要写得足够多以引发讨论充实细节。这是坎宁安定律的一个应用该定律认为“在互联网上获得正确答案的最好方法并不是提出问题而是发布错误的答案。”\n\n\n了解如何编译、测试和部署代码。阅读那些提交代码的请求和代码评审意见\n\n\n不要满足于你的第一版设计。反复斟酌要随时做好准备因为你的系统会随着时间的推移而不断变化。\n\n\n你要开始学习在必要的维护和重构中间寻找平衡。不要试图重构一切。\n\n\n能力的4个阶段“无意识的无能力”(unconscious incompetence)、“有意识的无能力”(conscious incompetence),“有意识的有能力”(conscious competence)和“无意识的有能力”(unconscious competence)。\n\n\n我们还将准备一些提示方便你在“万事都求人”和“独行侠”之间取得平衡\n\n\n冒充者综合征和邓宁-克鲁格效应,这可能会导致新工程师感到自信不足或自信爆棚,\n\n\n无论你是一名刚毕业的学生还是一名经验丰富的老手如果你不学习你就会落后。\n\n\n因为你总会希望尽快将软件上线而花时间阅读文档和摆弄工具却会让你慢下来。别担心大家都预料到你会需要些时间来成长。前置学习是一项有价值的投资许多公司会专门为新员工设计学习课程\n\n\n错误难免会发生。每名工程师都有类似的故事。尽你所能努力理解你在做什么但要知道这种事情总会发生\n\n\n错误是不可避免的。成为一名软件工程师的路途艰辛我们有时会失败。这几乎是所有人都知道的事情。降低系统风险并使这些错误不那么致命是你的管理者和团队的工作。如果你失败了也不要被击垮写下经验教训然后继续前行。\n\n\n文档可能会过期同事们也会忘记某些事情但是实例代码是安全的\n\n\n请每周都花一部分时间去阅读。可供阅读的内容有很多团队文档、设计文档、代码、积压的任务票、书籍、论文和技术网站。不要试图一下子把所有东西都读完。请从团队文档和设计文档入手。这些文档会就事情是如何组合在一起的给你一个整体的概念。要特别注意那些关于如何权衡取舍和背景的讨论。接下来你就可以深入研究那几个与你最初任务相关的子系统了\n\n\n仔细研究代码的数据结构和算法\n\n\n留意那些惯用写法和风格也就是去学习“本地方言”(local dialect)\n\n\n尝试自己寻找答案。即使你的同事知道答案你也要付出努力这样你会学到更多。如果你没有找到答案当你寻求帮助时你的调查仍然会成为你的起点\n\n\n限制你研究一个问题时预期花费的时间。在你开始研究之前就应该设定好时间限制这样可以鼓励你遵守这个限制防止收益递减研究最终会拖累生产性。\n\n\n如果你在第二个时限之后仍然找不到确定的答案就应该及时止损并寻求帮助。及时止损需要自律和练习因为你要对自己负责。\n\n\n在提出问题时描述你已经知道的情况。不要只是分享你的原始笔记。简要地描述你所做的尝试和发现这表明你已经花了很多时间去试图自己解决这个问题。这样做也会给别人一个回答你的起点。\n\n\n在你设置的会议议程中应包括这个清单不要只靠脑袋来记问题也不要事前不做功课就来参加。\n\n\n一般有两个常见的障碍会影响许多工程师即“冒充者综合征”和邓宁-克鲁格效应。如果你了解这些现象是什么,以及如何克服它们,你会成长得更快。\n\n\n他们总是到处批判公司的技术栈抱怨代码的质量贬低设计。他们确信自己的想法是正确的。他们的默认模式是直接回绝或无视反馈\n\n\n当你浏览代码时你就会注意到它的缺点。混乱的代码是变化的自然副作用不要把代码的不整洁归咎于开发者。这种走向无序的趋势被称为软件的熵(software entropy)。\n\n\n幸运的是软件的熵可以被管理\n\n\n本金是那些需要修复的原始不足。利息是随着代码的发展没有解决的潜在不足因为实施了越来越复杂的变通方法。随着变通办法的复制和巩固利息就会增加。复杂性蔓延开来就会造成bug。未支付的技术债很常见遗留代码里有很多这样的债务。\n\n\n这种类型的债务更像是在出问题的领域反思学习或作为软件架构师成长的必经之路而不是未做功课这么简单。健康的团队使用诸如项目回顾等做法来发现无心之债并讨论何时以及是否偿还。\n\n\n要边做边解决着手去做小幅的重构。在小幅的、独立的提交(commit)和拉动请求(pull request)中推动问题的修改。\n\n\n下面是讨论技术债的一个优秀的模板1.按事实陈述情况2.描述技术债的风险和成本3.提出解决方案4.讨论备选方案不采取行动也是备选方案5.权衡利弊。\n\n\n3.3 变更代码\n\n变更代码和在新代码库中写代码完全不一样你必须在不破坏现有行为的情况下进行这些修改。你必须理解其他开发者的想法坚持原有的代码风格和设计模式。而且你必须在工作中温和地改进代码库。\n无论是添加新特性、重构、删除代码还是修复bug变更代码的技术大体上一致。事实上不同类型的变更经常被结合起来使用。所谓重构是指在不改变软件行为的情况下改进内部代码结构。它经常发生在添加新特性的时候因为它使新特性可以更容易地被添加。而在修复bug的过程中则经常删除代码。\n改变现有的大型代码库是一项需要经过多年甚至几十年锤炼的专业技能。下面的小技巧在你开始的时候就会帮助到你。\n3.3.1 善于利用现有代码\n\n改变现有的大型代码库是一项需要经过多年甚至几十年锤炼的专业技能\n\n\n互联网上的编程传说经常引用童子军的原则“住过的营地要比住之前更干净”。\n\n\n当你修复错误或增加新的特性时只清理有关联性的代码。不要不顾一切地去找“脏”代码要“随缘”一些。\n\n\n。在你的工作中要随时定位有异味的代码。代码异味(code smell)是一个术语专指那些不一定是bug但采用了已知会导致问题的代码模式通常“闻起来很怪”\n\n\n。利用一切你所拥有的工具。如果你的编程语言有一个优秀的IDE就去使用它。\n\n\n重置你的分支压缩你的提交并在提交代码修改供评审之前写一份清晰的提交信息。\n\n\n品在做某件事情时至少要比目前流行的方式好十倍。两倍或三倍的改进不足以让人们快速或大量地转向新事物。\n\n\n所有的技术都会发生故障但旧的东西以可预测的方式发生故障新东西往往会以令人惊讶的方式发生故障。缺乏成熟度意味着更小的社区、更低的稳定性、更少的文档以及更差的兼容性。新技术甚至在Stack Overflow[插图]上有更少的答案。\n\n\n有时新技术会解决你公司的问题有时则不会。要辨别何时使用新技术需要明确的规则和经验。新技术的收益必须超过其成本。\n\n\n不要以为重构工作会很轻松这将是一个艰难的过程\n\n\n编写拥有良好防御性的代码是一种对那些运行你的代码的人包括你自己富有同情心的表现\n\n\n现在都对类型提示和静态类型检查器有越来越强大的支持\n\n\n代码清单4-1所示的Python 3.5的方法就使用了类型提示来接收和返回一个字符串。\n\n\n如果一个参数应该大于0那就要确保它大于0如果一个参数是IP地址那就要检查它是否是一个有效的IP地址。\n\n\n计算机硬件并不总值得信赖网络和磁盘可能会损坏数据。如果你需要强大的耐久性保证使用校验和的方式来检查数据没有意外的变化。\n\n\n也不要忽视安全问题外部输入是危险的。恶意用户可能试图在输入中注入代码或SQL或撑爆缓冲区以获得对你的应用程序的控制权限。使用成熟的类库和框架来防止跨站脚本攻击总是强制转义输入的字符来防止SQL注入攻击。\n\n\n如果一个内置的异常可以描述问题就不要创建自定义的异常。开发人员有经验去处理现有的异常类型他们会知道这些异常具体是什么意思。\n\n\n当你创建自己的异常时不要把它们弄得太通用。通用的异常很难处理因为开发人员并不知道他们正面临什么样的具体问题。如果开发人员没有得到已发生错误的精确信息他们就会迫使整个应用程序以失败结束这将是一个重大的动作。对于你引发的异常类型的描述要尽可能具体这样开发人员就能对程序失败做出适当的反应\n\n\n跟踪这类错误是令人“抓狂”的——你修复了一个bug却发现真正的问题出在上游。\n\n\n谨慎的做法是使用一种叫作“退避”(backoff)的策略。退避会非线性地增加休眠时间(通常使用指数退避,如(retry number)^2。\n\n\n如果一个网络服务器发生了一起突发事件而且所有的客户端也都同时经历了这起突发事件那么就用同样的方法进行退避。\n\n\n处理重试的最好方法是构建幂等系统。一个幂等的操作是可以被进行多次并且仍然产生相同结果的操作。\n\n\n通过允许客户端单独为每个请求提供一个唯一ID的方式远程API就可以变为幂等API。当客户端重试时它提供的唯一ID与失败时的相同。如果该请求已经被处理过了服务器可以移除重复的请求。让你的所有操作都成为幂等操作这可大大简化系统的交互同时也可消除一大类潜在的错误。\n\n\n当故障发生后要确保清理所有的资源释放你不再需要的内存、数据结构、网络套接字和文件句柄。\n\n\n一个资源已经接近其容量上限就应该是一个WARN。每当你记录一个WARN时应该对应一个你希望看到这个日志的人去采取的具体行动。\n\n\n日志信息不应该包括任何私人数据如密码、安全令牌、信用卡号码或电子邮件地址。\n\n\n应用程序的系统指标可以被汇总到一个集中式可视化系统中如Datadog、LogicMonitor或Prometheus。\n\n\n分布式调用跟踪。对上游API的一次调用可能会导致对下游的数百次不同服务的RPC调用\n\n\n对人友好的配置文件、环境变量和命令行参数是最常见的方法\n\n\n通常动态配置带来的收益往往比不上它引入的复杂性你需要仔细考虑运行过程中因为各种配置变化而产生的所有影响。它还会使你更难跟踪哪项配置被改变了谁改变了它以及它的值是什么这些信息在调试运维问题时可能是至关重要的。它还会增加对其他分布式系统的外部依赖性。这听起来很简单但重新启动一个进程来获取新的配置通常在操作上和架构上都更好一些。\n\n\n不要盲目地从其他文件中复制配置一个被称为船货崇拜的例子在没有真正理解它们的作用或原理的情况下就复制东西。\n\n\n脚本化的工具很容易实现自动化。如果你打算构建一个基于用户界面的工具那就把逻辑抽象成一个共享库或服务这样基于CLI的工具也可以使用。\n\n\nleft-pad的软件包消失后成千上万的JavaScript项目开始无法编译。\n\n\n● 唯一性(unique):版本不应该被重复使用。构件会被分发、缓存,并被自动化工作流拉取。永远不要在现有版本下重新发布更改的代码。● 可比性(comparable):版本应该帮助人们和工具对版本的优先顺序进行推断。当一个构建依赖于同一构件的多个版本时,可以使用优先顺序来解决冲突。● 信息性(informative):版本信息区分了预先发布的代码和已发布的代码,将构建流水号与构件相关联,并设置了稳定性和兼容性的合理预期。\n\n\n这是版本管理中最常用的方案之一。官方的SemVer规范可在其网站中找到。该规范定义了3个数字主版本号、次版本号和补丁版本号有时也称作微版本号。这3个数字被合并为“主版本号.次版本号.补丁版本号”的版本号格式。httpclient版本4.3.6意味着主版本号、次版本号和补丁版本\n\n\n比较常见的相依性地狱的罪魁祸首是循环依赖、钻石依赖和版本冲突。\n\n\n在现实中兼容性是一个“美丽的愿望”。项目经常在没有检查兼容性的情况下就发放版本即使是自动化也不能完全保证其兼容性。\n\n\n大多数团队会在合并代码的修改之前进行代码评审。高质量的代码评审文化有助于所有具有不同经验水平的工程师的成长并促进他们对代码库的共同理解。糟糕的代码评审文化会抑制创新减慢开发速度并且导致滋生怨恨情绪。\n\n\n评审整个代码库的变更可以确保不止一个人熟悉生产环境中代码的每一行对代码库的共同理解有助于团队更有凝聚力地扩展代码。\n\n\n不要执着于那些你提交评审的代码要期待它在评审过程中发生变化有时甚至是重大的变化\n\n\n一些开发者通过提交代码评审的方式来触发持续集成(continuous integrationCI)系统来绕过这个问题,这是一种糟糕的做法。\n\n\n不要试图让你的队友在预排会议中实际地进行代码评审参加者应该把他们的评论留到未来真正的代码评审环节。预排会议的目的是帮助你的团队理解为什么要提出修改并给他们一个良好的心理模型以便他们可以自行去进行详细的代码评审。\n\n\n从你的代码上得到的那些批评性的评论可能让你很难接受。切记应该保持一些情感上的距离——这些评审意见是针对代码\n\n\n首先审视你自己的反应你本能地保护你的代码只是因为你编写了它们还是因为你的方式事实上更好清楚地解释你的观点如果你们还是不能达成一致咨询一下你的管理者下一步该怎么做。团队处理代码评审冲突的方式各不相同有的服从提交者有的服从技术负责人还有的服从小组的法定人数。应该遵循团队惯例。\n\n\n在你的日历上划出代码评审时间。预定的评审时间会使你很容易继续你的其他任务因为你知道你以后会有集中的时间段进行代码评审。这也会使你的评审保持高质量——当你有专门的时间时你就不会对需要切换回其他任务而感到有那么大的压力。\n\n\n你需要对代码修改的正确性、可实施性、可维护性、可读性和安全性提供反馈\n\n\n如果你从阅读代码中学到了一些新的东西请明确地传达给作者。\n\n\n即使是一项令你讨厌的修改你也可以对它说些好话——如果没有别的原因就承认它的意图和努力。\n\n\n代码评审通常在一个专门的UI中处理比如GitHub中的拉取请求界面。不要忘记代码评审本身也只是代码而已。你仍然可以迁出或下载那些拟议的修改并在本地处理它们。\n\n\n尊重正在进行的修改的范围。在你阅读的过程中你会发现改进相邻代码的方法并产生一些关于新特性的想法不要坚持将这些修改作为现有评审的一部分来进行。另开一张任务票来改进代码把工作留到以后。确定严格的范围将提高速度并保持增量更改。\n\n\n你的团队可能把整个流程——从打包到展开统称为发布(release)。他们可能把打包一个构件称为发布,而把构件交付下载的过程称为发行(publishing)。直到一个特性在生产环境中被打开时才能称其为被“发布”了,而在这之前的一切行动都是部署(deploy)。在本章中我们将提到软件交付的4\n\n\n构建(build)、发布、部署和展开(rollout)\n\n\nGitflow使用开发分支、热修复分支和发布分支。\n\n\n你应该尽可能频繁地发布。较长的发布周期给人一种错误的安全感两次发布之间的漫长周期感觉像是有充足的时间来测试变化。在实践中快速的发布会产生更稳定的软件当发现bug时更容易修复。\n\n\n每个周期的变化较少所以每个版本的风险都较小。当一个bug出现在生产环境中时在调试时要回顾的代码变化就会更少。代码在开发人员的头脑中是新鲜的这将使bug更容易和更迅速地被修复。\n\n\n发布经理使用加密密钥对构件进行签名这样用户就可以验证下载的软件包是否来自Apache。\n\n\nPuppet、Salt、Ansible和Terraform等现成的解决方案可以与现有的工具集成并且它们是专门为了自动化部署而设计的。\n\n\n为了避免失败的那部分部署操作应使部署要么全部完成要么什么都没做即原子性。\n\n\n特性开关、熔断器、“摸黑启动”、“金丝雀部署”和“蓝绿部署”。\n\n\n特性开关有时被用于A/B测试这是一种测试用户对新特性反应的技术。如果以具有统计意义的方式对用户进行分组用特性开关进行A/B测试是可行的。\n\n\n金丝雀部署不同的是流量的切换是原子化的蓝色和绿色环境尽可能地保持一致\n\n\n亚马逊的构建者库也是一个伟大的免费资源可用于交付最佳实践。该库位于亚马逊构建者的主页那上面有关于持续交付、自动部署和回滚的帖子。\n\n\n然而大概每名On-Call人员最终都会遇到一起运维事故生产软件的关键问题。事故是由自动监控系统发出的警报或由支持工程师观察到问题并报告给值班人员的。On-Call的开发人员必须对事故分流、缓解症状和最终解决。\n\n当关键警报发生时On-Call的开发人员会被呼叫。“呼叫”是手机出现之前的一种过时的称呼。现在警报是通过聊天软件、电子邮件、电话或文本信息等渠道发出的。如果你像我们一样不接听任何来自未知号码的电话请确保将警报服务的电话号码添加到你的联系人白名单。\n所有的On-Call轮换的工作都应该以交接开始和结束。上一名On-Call的开发人员总结当前的所有运维事故并为下一名On-Call的开发人员提供任何未解决任务的背景。如果你已经很好地跟踪了你的工作交接工作就不是什么大事了。\n\n创建一个你在紧急情况下可以依赖的资源清单可以直接链接到你的服务的关键仪表盘和运行手册、访问日志的说明、重要的聊天室以及故障排除指南。创建一个单独的“On-Call”书签文件夹并保持更新这会很方便。与团队分享你的清单以便其他人可以使用和改进它。\n\n\n开发人员会感到压力和变得暴躁——这是人的本性\n\n\n简洁确保你的沟通容易被阅读和理解。如果你并不知道答案就说出来如果你知道答案就大声说出来。回应请求要迅速。回应不一定代表解决方案。告诉请求者你已经看到了他们的请求并确保你理解问题所在。\n\n\n后续行动(follow-up):对事故的根本原因——为什么会发生,进行调查。如果事故很严重,就会进行正式的事后调查,或进行回顾性调查。建立后续任务,以防止那个(或那些)根本原因的再次出现。团队要寻找流程、工具或文档中的任何漏洞。在所有的后续任务完成之前,相应事故的处理不应该被认为已经结束了\n\n\n设计工作被分成两种活动单独的深入思考和协作的小组讨论。研究、头脑风暴和写作构成了深度工作。设计讨论和对设计文件的评论构成了合作的部分。这个过程的有形产出是一份设计文档。\n\n\n当你在撰写文档的过程中你发现了更多的未知因素。你创建了一些小的原型来验证你的设计、回答问题并帮助你在可行的替代方案中做出选择。你进行更多的研究并请专家提供意见。你充实了设计文档的草稿\n\n\n你现在处于圆锥体的顶部。你在你的设计中已经投入了大量的工作而且对你的方案充满信心。你将设计方案在整个组织内传阅。安全、运维、相关的团队和架构师都需要了解你所承诺的变更这不仅仅是为了提供反馈也是为了更新他们对整个系统工作方式的心理模型。\n\n\n询问利益相关者他们认为问题究竟是什么。这些利益相关者可能是你的管理者、队友、产品经理或技术负责人\n\n\n不会在你锁定的整段时间内进行“设计”。你的大脑需要时间来放松休息一下给自己一个呼吸的空间允许你的思想放松和游荡去散步、泡茶、阅读、写作、画画。\n\n\n并非每一项变更都需要设计文档更不用说正式的设计评审过程了。你的组织可能有自己的指导方针。如果没有指导方针就用这3个标准来决定是否需要设计文档。● 该项目将需要至少一个月的工程时间。● 这一变更将对软件的扩展和维护产生长期的影响。● 该变更将显著影响其他团队。\n\n\n写作作为一项技能就像其他技能一样是通过实践来进步的。充分利用写作的机会——设计文档、电子邮件、代码评审意见——努力写得清晰。\n\n\n不要让人惊讶你需要有礼貌地并且渐进地让人们了解你的设计方案。如果正式的设计文档是其他团队和技术负责人第一次了解你的工作你就是在为自己的失败埋下伏笔。每一方都有不同的视角和不同的利益诉求他们可能会对一份突然出现的、他们没有发言权的设计文档做出强烈的反应。\n\n\n当一个问题特别多元或有争议时要选择更大、更有包容性的头脑风暴会议。对于更直接的讨论应保持较少的被邀请者人数使谈话更容易进行。\n\n\n会议结束后以白板上的图片为指导根据你的回忆写一份总结。把这些笔记发给与会者和其他相关的队友。\n\n\n[插图]\n\n\n《软件设计的哲学》(A Philosophy of Software Design)中写到:“复杂性是与系统结构有关的东西,复杂性使人难以理解和修改系统。”按照奥斯特霍特的说法,复杂系统有两个特点:高依赖性和高隐蔽性\n\n\n面对未来未知的需求工程师们通常会选择下面两种策略中的一种试图预判未来的需求或者建立抽象模型作为逃生舱门使后续的代码修改更容易。\n\n\n避免过早优化避免不必要的灵活抽象模型以及避免最小可行产品(minimum viable productMVP)所不需要的产品特性——你需要那些可以获得用户反馈的最低限度的功能集。\n\n\n按技术领域进行分组的代码在单一业务领域内效果很好但随着业务的发展就会变得很混乱\n\n\n个人和互动高于流程和工具工作的软件高于详尽的文档客户合作高于合同谈判响应变化高于遵循计划\n\n\n一旦敏捷开发模型流行开来“黑带忍者”、权威认证和流程顾问就会笼罩在一些组织之上。人们迷恋于“做敏捷”的“正确”方法而往往损害了第一个原则“个人和互动高于流程和工具”。\n\n\n会让每个人都了解你的进展让你负起责任和保持专\n\n\n队友们围成一圈介绍自上一次站会以来他们所做的工作他们计划在未来做什么\n\n\n你对公司的方向有什么疑问你对组织变革有什么疑问\n\n\n反馈我们可以在哪些方面做得更好你对团队的计划流程有什么看法你最大的技术难题是什么你希望你能做什么而你却做不到你最大的问题是什么公司的最大问题是什么你或团队中的其他人遇到了什么阻碍职业生涯你的管理者对你都有哪些职业建议你有哪些可以改进的地方你希望自己有哪些技能你的长期目标是什么你觉得你在这些目标上的进展如何个人事务你的生活中有什么新鲜事你的管理者应该注意你的哪些个人问题\n\n\nPPP中的每个P进展、计划与问题都有自己的小节。每个小节应该有3到5个要点每个要点应该很简短只有1到3个句子。\n\n\n定义了目标目的并为每个目标附上衡量标准关键结果\n\n\n在写自我评价时不要凭记忆行事。记忆是不稳定的你可能只关注某些难忘的项目。务必保有一份最新的在整个一年中完成的工作的清单——一份已完成的待办事项清单、一套PPP或一份“子弹日记”以唤起你的记忆。看看你在公司的问题跟踪系统中已完成的任务。你完成了哪些里程碑、史诗和用户故事已合并的代码拉动请求和代码评审也显示了你所做的工作。还有不要忘记你的非工程类的项目辅导实习生、代码评审、参与面试、博客文章、演讲、文档——所有的这些都应该被认可使用你所拥有的一切来写一份诚实的自我评价。\n\n\n可以使用一对一面谈的方式来获得反馈。\n\n\n不要听信表面上的反馈。你的管理者仅仅是视角之一尽管是一个重要的视角试着把管理者的反馈纳入你的观点而不是直接采用管理者的反馈\n\n\n我们今天能谈谈职业生涯的路径吗老实说我不确定我能看到自己五年后在哪里甚至我的选择是什么。你看到的一些常见的职业路径是什么它们之间有什么区别吗我很喜欢我目前的项目但我也对安全领域感到好奇。是否有机会可以让我做一些与安全有关的工作呢\n\n\n培养T型技能参加工程师训练营主导晋升过程不要过于频繁地更换工作并多自我调节。\n\n\n软件工程有许多专业领域前端、后端、运维、数据仓库和机器学习等。“T型”工程师在大多数领域内都能有效地工作并且至少是某一个领域的专家。\n\n\n你的职业生涯是一场马拉松而不是短跑冲刺——你有几十年的时间。给自己定下节奏享受这段旅程吧\n\n\n与你喜欢的人一起工作并解决你所热衷的问题你就可以完成伟大的事情\n\n笔记\n\n技术债\n\n💭 技术债务大多是时空局限性带来的产物,整体来是一个熵增的过程。别妄想永远消除技术债务,只需要平时定期审计,重构,从而维持一个相对平衡的状态即可。\n\nOn-Call\n\n💭 处理故障首先确定范围,然后定义性质。\n\n一名成功的软件工程师究竟是什么样子的呢以及如何成为一名成功的软件工程师呢\n\n💭 活在当下,着眼未来\n\n如果你的公司没有安排新人入职培训那需要你自己去向你的管理者要一份公司的“组织架构图”了解清楚谁负责什么谁向谁汇报都有哪些不同的部门以及它们之间的关系。记得做好笔记。\n\n💭 公司的战略方向,核心业务,市场地位,组织架构都是入职之后需要迅速了解,代入的重要因素!\n\n这样做的目的是让你去了解那些步骤而不是去打动谁。\n\n💭 充分把握生产流程中的每一个环节\n\n本节将列举各种各样的学习方法。切勿试图同时去做本章中列出的所有事情因为那样会让你感到倦怠。切记善用个人的时间——虽然说持续进步非常重要但是把所有清醒的时间都花在工作上是不健康的。\n\n💭 一定要学会摸鱼学习,这才是自己的!😎\n\n错误是不可避免的。成为一名软件工程师的路途艰辛我们有时会失败。这几乎是所有人都知道的事情。降低系统风险并使这些错误不那么致命是你的管理者和团队的工作。如果你失败了也不要被击垮写下经验教训然后继续前行。\n\n💭 兼容性,容错性,而不是矫枉过正,一棒子打死🔨😥\n\n潘卡给出了一些背景描述了问题告诉艾丽斯他已经尝试了什么然后才请求帮助。\n\n💭 场景,因素,问题,目的,结果\n\n谨慎的、有意的技术债右上是技术债的典型形式在代码的已知不足和交付速度之间进行务实的取舍。只要团队有规划地解决这个问题这就是好的债务。\n\n💭 平衡点\n\n不要把你的呼吁建立在价值判断上“这代码又老又难看”将重点放在技术债的成本和修复它带来的好处上。\n\n💭 不能光说,也得去做\n\n在不影响整个项目持续运转的情况下[插图]要持续地重构工程,这样重构的成本就会平摊在多次的版本更迭中。\n\n💭 隐形成本\n\n不要因为你不喜欢你公司或行业的标准就忽视它们编写非标准的代码意味着它将无法适应公司的环境。因为持续集成检查、IDE插件、单元测试、代码校验、日志聚合工具、指标仪表盘和数据管道都已经集成在一起了你自定义的方案肯定会代价高昂。\n\n💭 系统化,标准化的技术设施建设才可以让万丈高楼平地起\n\n分叉(fork)是对一个代码库进行完整的、独立的复制分叉之后的代码库有自己的主干、分支和标签。在GitHub这样的代码共享平台上在向上游代码库提交拉动请求之前就可以分叉上游代码库。分叉操作可以让那些对主代码库没有写入权限的人仍然可以对项目做出贡献这是一种正常而健康的做法。\n\n💭 目前分叉可以划分为硬分叉和软分叉,硬分叉则是完全独立出来,上下游无关。软分叉则是为了满足某些非社区主流特性,上下游关联。\n\n[插图]\n\n💭 生活不是一天天变好的,日子也不是一天过完的。病来如山倒,病去如抽丝,技术债务根本无法消除,只能渐进式改进,尽可能地维持平衡。\n\n配置即代码(configuration as codeCAC)的哲学认为,配置应该受到与代码同样严格的要求。配置错误可能是灾难性的,一个错误的整数或缺失的参数就可以毁掉一个应用程序。\n\n💭 配置同样需要接受版本控制\n\n优秀的代码评审可以作为一个教学工具传播认识记录实现的决策并提供代码的更改记录以确保安全性与合规性。\n\n💭 信息对称,深度交流\n\n代码修改由准备、提交、评审、最后批准和合并这几个环节组成。\n\n💭 流程化标准化管理建设\n\n每个人的记忆都会“消失”你回应得越快你得到他人回应的速度就越快。\n\n💭 不要考虑,直接去干\n\n一个快捷方式或软链接就可以被原子化地翻转。\n\n💭 Linux 软连接\n\n摸黑启动的软件其实仍然启用了代码也被调用了只是结果被丢掉了。摸黑启动可帮助开发者和运维人员在生产环境中了解他们的软件对用户的影响最小。\n\n💭 镜像流量\n\n随时响应”并不意味着立即放下你正在做的事情来解决最新的问题。对于许多请求完全可以先承认你已经收到了询问并回答你应该在什么时候能看一下这个问题“我现在正在协助其他人我可以在15分钟内给您答复吗”一般来说人们希望On-Call工程师能做出快速反应但不一定需要快速解决问题。\n\n💭 先承接情绪价值\n\n有些支持请求异常紧急而有些请求则在一周内完成就可以。如果你无法判断一个请求的紧急程度请询问该请求的影响是什么。影响范围将决定优先级。如果你不认可请求者对于某个问题的优先级次序的看法请与你的管理者讨论一下。\n\n💭 划分范围,确定性质。\n\n它影响了多少人有多大的危害性在SLI和触发警报的指标如果适用的话的帮助下使用你公司的优先级分类和SLO/SLA定义来确定问题的优先级。\n\n💭 划范围,定性质。\n\n你在应急方案的阶段目标是降低问题的影响。应急方案并不是要彻底地解决这个问题而是要降低其严重性。修复一个问题可能需要很多时间而应急方案通常可以很快完成。\n\n💭 尽可能的减少损失,影响\n\n工程师们从原来的连接器中移除所有健康的数据流试图重现这个问题。\n\n💭 复现错误\n\n负责连接器的工程经理安排了后续工作On-Call工程师撰写了一份“尸检”文件的草稿。安排一次“尸检”会议。最终通过“尸检”这一过程新开了3张任务票分别调查为什么APM要使用消息头、为什么连接器的消费者节点不能反序列化、为什么手动的消费者节点不能输出空字符串的头。\n任何事故都是一件大事所以需要后续行动来继续跟进。目的是从事故中学习防止它再次发生。要写一份事后总结的文档并进行评审同时开启新任务以防止其再次发生。\n\n💭 复盘总结\n\n你的首要任务是定义和理解你要解决的那个或那些问题。你需要了解问题的边界以便知道如何解决它并避免构建错误的东西。\n\n💭 理解问题,定义性质,确定边界🤔\n\n当你写代码的时候要使用最小惊讶原则和封装原则。这些设计原则将使你的代码易于演进。\n\n💭 封装,继承,多态三板斧\n\n保持代码灵活性的最佳方法之一是减少代码的总量。对于你所构建的一切问问自己哪些是绝对必要的其余的就舍弃掉。\n\n💭 断舍离\n\n解决大局观上的偏差\n\n💭 不能掉队\n\n如果你已经给出了反馈意见并保持了耐心但事情仍然没有进展那就起身离开。\n\n💭 无法形成正反馈,就需要接受无尽的消极。\n\n一名软件工程师的职业曲线是漫长的本书将带你走完旅程的开端。接在后面的是终身学习、技术领导力甚至可能是走上管理岗位或创业。无论你选择何种职业路径你都必须继续成长。\n\n💭 持续学习,技术领导(•̀ᴗ•́)و̑̑\n\n了解晋升的流程确保你的工作是有价值的和可见的当你认为自己接近下一个级别时要大声说出来。\n\n💭 主动出击\n\n反过来说不要待得太久。工作僵化、停滞不前是改变现状的正当理由。在一家公司工作时间长的工程师自然会成为“历史学家”他们教导工程师事情是如何运转的、谁知道什么以及为什么事情是按照他们的方式完成的。这样的知识是有价值的甚至是一名主任工程师职责的一部分但如果你的价值更多来自过去的工作而不是现在的贡献那么它就会阻碍你的成长。更换公司并在一个新的环境中找到自己可以重启你的成长。\n\n💭 谨防温水煮青蛙\n书评\n\n✨其实应该更早一些读到这本书。 实际工作中最好是在职场的第二年开始的时候,首先经过一年的成长已经度过了新手期,同时经过这本书的指导,可以让我们更容易地走好下一阶段的路,从而最低成本试错,减少走弯路,争取到达新高峰!\n\n点评"},"Personal/Book/计算机/精通Python设计模式第2版":{"title":"精通Python设计模式第2版","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《精通Python设计模式第2版》\n作者 卡蒙·阿耶娃 萨基斯·卡萨姆帕利斯\n分类 计算机-编程设计\nISBN9787115526861\n出版社人民邮电出版社\n\n概述\nPython是一种面向对象的脚本语言设计模式是可复用的编程解决方案二者在各种现实场景中应用都十分广泛。本书是针对Python代码实现设计模式的经典作品着重讨论了用于解决日常问题的所有GoF设计模式它们能帮助你构建有弹性、可伸缩、稳健的应用程序并将你的编程技能提升至新的高度。第2版探讨了桥接模式、备忘模式以及与微服务相关的几种模式。\n划线\n\n在《设计模式》中“四人组”向我们呈现了23种设计模式并分为3类创建型、结构型和行为型。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/网络安全等级保护2.0:定级、测评、实施与运维":{"title":"网络安全等级保护2.0:定级、测评、实施与运维","links":[],"tags":["阅读/计算机-理论知识","阅读/笔记"],"content":"简介\n\n书名《网络安全等级保护2.0:定级、测评、实施与运维》\n作者 李劲等编著\n分类 计算机-理论知识\nISBN9787115549976\n出版社人民邮电出版社\n\n概述\n网络安全等级保护按照网络安全等级保护核心标准的要求及网络安全建设要求对网络安全建设流程、安全评估和测评、物理安全、网络和通信安全、设备和计算安全、应用和数据安全、安全管理机构和人员、运维管理、云计算安全、移动互联网安全、工业控制系统安全等方面提出解决方案并紧密结合工程实际通过具体项目案例介绍了网安全规划设计方案为网络安全建设人员和管理人员提供了清晰的思路和可操作的方法。\n划线\n\n等保2.0的适时推出,体现了国家积极应对新技术引发的新风险,变被动防御为主动保障,解决了中国网络安全存在的主要问题。\n\n\n《中华人民共和国网络安全法》第二十一条要求国家实行网络安全等级保护制度第二十五条要求网络运营者应当制定网络安全事件应急预案第五十九条明确了网络运营者不履行本法第二十一条、第二十五条规定的网络安全保护义务的由有关主管部门责令改正给予警告。总而言之不开展等级保护等于违法\n\n\n第一层法律。第二层行政法规。第三层规章、地方性法规以及规范性文件。\n\n\n从基础分类角度出发可以分为基础标准、技术标准以及管理类标准从对象角度出发可以分为基础标准、系统标准、产品标准、安全服务标准以及安全事件标准等从网络安全等级保护生命周期出发可以分为通用/基础标准、系统定级标准、建设标准、等级测评标准、运行维护及其他标准。\n\n\n[插图]\n\n\n没有攻不破的网络没有绝对的信息安全\n\n\n接入控制、安全隔离、边界检测/防御、终端防御、网络审计、访问控制等\n\n\n快速响应安全事件是安全运营的关键\n\n\n一个完整的信息安全体系应该是安全技术、安全管理、安全运营的结合三者缺一不可。\n\n\n机房内部署机房空调24小时运行设置温度为24°恒温。\n\n\n在系统建设完成后按照等级保护的要求必须选择国家认可的测评机构对信息系统进行等级测评并在系统运行过程中定期进行测评。\n\n\n① 规定统一的应急预案框架,如启动预案的条件、应急组织构成、应急资源保障、事后教育和培训等。② 制定重要事件的应急预案,如应急处理流程、系统恢复流程等。③ 定期对系统相关的人员进行应急预案培训,并进行应急预案的演练。④ 定期对原有的应急预案重新评估,修订完善。\n\n\n[插图]\n\n笔记\n\n2019年是中国全功能接入国际互联网25周年。\n\n💭 1994年中国全功能接入国际互联网\n\n等保2.0标准不再自主定级,而是通过“确定定级对象→初步确定等级→专家评审→主管部门审核→公安机关备案审查→最终确定等级”这种线性的定级流程,系统定级必须经过专家评审和主管部门审核,才能到公安机关备案,整体定级更加严格。\n\n💭 流程化\n\n对于大型工业控制系统可根据系统功能、责任主体、控制对象和生产厂商等因素划分为多个定级对象。\n\n💭 具体情况具体分析\n\n[插图]\n\n💭 最基础的物理环境影响在特定场景下非常致命,亲身经历过……\n\n传统的以防为主的安全架构受到了极大挑战安全防御手段也明显不足需要重新分析当前信息系统的架构评估安全措施的有效性实施以积极防御为主导思想的新的安全架构。\n\n💭 企业蜜罐🍯引诱攻击者利用,进而拖延抓捕攻击者。\n\n机房场地应避免设在建筑物的顶层或地下室否则应加强防水和防潮措施。\n\n💭 最好在中间楼层或者1/3楼层以上\n书评\n点评"},"Personal/Book/计算机/网络工程师红宝书:思科华为华三实战案例荟萃":{"title":"网络工程师红宝书:思科华为华三实战案例荟萃","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《网络工程师红宝书思科华为华三实战案例荟萃》\n作者 周亚军\n分类 计算机-计算机综合\nISBN9787121376627\n出版社电子工业出版社\n\n概述\n当今是“互联网+”的时代许多事物都建立在网络技术之上很多时候要求网络工程师熟悉并能应用多个厂商的产品按需求搭建网络并负责其维护和升级。本书就是为帮助业界同人轻松达到这一目的而编写的。本书是多厂商技术融合的产物以思科和华为为主华三为辅阐述和演示了多个厂商的技术案例实验。对于网络工程师而言这些案例可以帮助其更好地应付日常工作对于初学者来说案例中详尽的命令解释和排错思路可以帮助其更快地入门。本书围绕搭建和维护一个中型企业网络展开实施可以称之为网络技术常用项目命令大全。作者在书中将在搭建网络和运维网络时最常用的技术分为39个案例进行介绍同时对相关命令做了注解说明其作用和结果以帮助读者来理解网络。另外本书还为读者准备了实验环境即模拟器和视频教程这是实际操作网络设备的重要工具。在读者完成本书学习之后搭建和维护一个中型企业网也变得简单起来。\n划线\n\n思科、华为和华三这三家著名企业。\n\n笔记\n\n其次要感谢我的夫人能够容忍我在半夜写书的时候打扰她和孩子能够容忍叫我三遍后才吃午饭能够容忍我因为思考技术问题走神而摔倒了还是幼儿的孩子能够容忍我每周休息1天而没时间陪伴家人。\n\n💭 感谢感谢哈哈哈\n书评\n点评"},"Personal/Book/计算机/网络是怎样连接的":{"title":"网络是怎样连接的","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介\n\n书名《网络是怎样连接的》\n作者 户根勤\n分类 计算机-计算机综合\nISBN9787115441249\n出版社人民邮电出版社\n\n概述\n本书以探索之旅的形式从在浏览器中输入网址开始一路追踪了到显示出网页内容为止的整个过程以图配文讲解了网络的全貌并重点介绍了实际的网络设备和软件是如何工作的。目的是帮助读者理解网络的本质意义理解实际的设备和软件进而熟练运用网络技术。同时专设了“网络术语其实很简单”专栏以对话的形式介绍了一些网络术语的词源颇为生动有趣。本书图文并茂通俗易懂非常适合计算机、网络爱好者及相关从业人员阅读。\n划线\n\n本书以探索之旅的形式从在浏览器中输入网址开始一路追踪了到显示出网页的内容为止的整个过程以图配文讲解了网络的全貌并重点介绍了实际的网络设备和软件是如何工作的。\n\n\n从在浏览器中输入网址到屏幕上显示出网页的内容在这个只有几秒钟的过程中很多硬件和软件都在各自的岗位上相互配合完成了一系列的工作。\n\n\n虽然Web服务器在收到订单数据之后和销售系统一起对订单进行实际处理的操作很复杂但其实浏览器和Web服务器之间的交互却很简单概括如下。\n\n\n不过没有文件名服务器怎么知道要访问哪个文件呢其实我们会在服务器上事先设置好文件名省略时要访问的默认文件名。这个设置根据服务器不同而不同大多数情况下是index.html或者default.htm之类的文件名。\n\n\n像前面这样省略文件名时服务器就会访问/dir/index.html或者/dir/default.htm。\n\n\n生成HTTP消息之后接下来我们需要委托操作系统将消息发送给Web服务器。尽管浏览器能够解析网址并生成HTTP消息但它本身并不具备将消息发送到网络中的功能因此这一功能需要委托操作系统来实现[插图]。\n\n\n这就是我们平常经常见到的IP地址格式但仅凭这一串数字我们无法区分哪部分是网络号哪部分是主机号。\n\n\n网络号和主机号连起来总共是32比特\n\n\nIP地址的长度为32比特也就是4字节相对地域名最短也要几十个字节最长甚至可以达到255字节。换句话说使用IP地址只需要处理4字节的数字而域名则需要处理几十个到255个字节的字符这增加了路由器的负担传送数据也会花费更长的时间[插图]。\n\n\nClass在最早设计DNS方案时DNS在互联网以外的其他网络中的应用也被考虑到了而Class就是用来识别网络的信息。不过如今除了互联网并没有其他的网络了因此Class的值永远是代表互联网的IN\n\n\n创建套接字阶段\n\n\n只要指定了事先规定好的端口号就可以连接到相应的服务器程序的套接字。\n\n\n将网络包发送给通信对象的操作就是由IP来负责的。此外IP中还包括ICMP[插图]协议和ARP[插图]协议。ICMP用于告知网络包传送过程中产生的错误以及各种控制消息ARP用于根据IP地址查询相应的以太网MAC地址[插图]。\n\n\n在协议栈看来要发送的数据就是一定长度的二进制字节序列而已。其次协议栈并不是一收到数据就马上发送出去而是会将数据存放在内部的发送缓冲区中并等待应用程序的下一段数据。\n\n\n图3.4 双绞线对噪声的抑制a通过两根信号线的缠绕抵消外源性噪声b通过改变节距抑制内源性噪声。\n\n\n[插图]\n\n\n从设备整体的转发能力来看交换机要高于集线器。\n\n\n因为路由器是基于IP设计的而交换机是基于以太网设计的[插图]。\n\n\n路由器判断下一个转发目标的方法如下。●如果路由表的网关列内容为IP地址则该地址就是下一个转发目标。●如果路由表的网关列内容为空则IP头部中的接收方IP地址就是下一个转发目标。路由器也会使用ARP来查询下一个转发目标的MAC地址。\n\n\n规定某些地址是用于内网的这些地址叫作私有地址而原来的固定地址则叫作公有地址[插图]。\n\n\n距离的不同和路由的维护方式就是互联网与家庭、公司网络之间最主要的两个不同点。\n\n\n用户名和密码通过RADIUS[插图]协议从RAS[插图]发送到认证服务器认证服务器校验这些信息是否正确。当确认无误后认证服务器会返回IP地址等配置信息并将这些信息下发给用户图4.17②-3。用户的计算机根据这些信息配置IP地址等参数完成TCP/IP收发网络包的准备工作接下来就可以发送TCP/IP包了\n\n\n这个路由信息交换的过程是由路由器自动完成的这里使用的机制称为BGP[插图]。\n\n笔记\n\n像浏览器、邮件等一般的应用程序都是使用TCP收发数据的而像DNS查询等收发较短的控制数据的时候则使用UDP。\n\n💭 TCP打电话UDP写信\n\n部署防火墙[插图]。防火墙的作用类似于海关,它只允许发往指定服务器的指定应用程序的网络包通过,从而屏蔽其他不允许通过的包。\n\n💭 防火墙类似于海关\n\n除了使用多台功能相同的Web服务器分担负载之外还有另外一种方法就是将整个系统按功能分成不同的服务器[插图]如Web服务器、数据库服务器。缓存服务器就是一种按功能来分担负载的方法。\n\n💭 水平扩展,垂直扩展\n书评\n点评"},"Personal/Book/计算机/网络运维亲历记-(网络运维纪实文学)":{"title":"网络运维亲历记 (网络运维纪实文学)","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介\n\n书名《网络运维亲历记 (网络运维纪实文学)》\n作者 王刚耀\n分类 计算机-理论知识\nISBN9787302429845\n出版社清华大学出版社\n\n概述\n本书共包括8 章36 个网络运维实例。首先介绍常用的网络二、三层协议包括IP、HSRP、 GVRP、VTP 协议和Trunk 技术及网络运维中的一些技巧如最简单的Ping 和Telnet 工具等。其次 介绍当前用户比较关注的网络问题和热门的网络技术如网络安全、虚拟化、IPv6 和无线网络等。 最后介绍与网络运维相关的其他计算机应用技术,如应用系统和网络排查工具等。 本书深入浅出地介绍了计算机网络的多方面知识,注重应用实践,可作为网络从业人员的专业 学习和参考用书,也可供高校计算机、通信、网络等专业的师生阅读参考。\n划线\n\n这7层是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而TCP/IP通信协议采用了四层的层级结构每一层都呼叫它的下一层所提供的网络来完成自己的需求。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/虚拟化工程师运维实战VMware服务器虚拟化+Citrix桌面应用虚拟化+Veeam备份+Zabbix监控":{"title":"虚拟化工程师运维实战VMware服务器虚拟化+Citrix桌面/应用虚拟化+Veeam备份+Zabbix监控","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介\n\n书名《虚拟化工程师运维实战VMware服务器虚拟化+Citrix桌面/应用虚拟化+Veeam备份+Zabbix监控》\n作者 孟鹏编著\n分类 计算机-编程设计\nISBN9787111673248\n出版社机械工业出版社\n\n概述\n《虚拟化工程师运维实战VMware服务器虚拟化+Citrix桌面/应用虚拟化+Veeam备份+Zabbix监控》详细介绍了实际运维工作中虚拟化工程师应该熟练掌握的虚拟化技术。全书共7章分别是虚拟化技术概述、虚拟化工程师应知必会的六件事、部署IT基础架构服务器、实现服务器虚拟化—基于VMwarevSphere、实现桌面/应用虚拟化—基于CitrixVirtualAppsandDesktops、虚拟化备份—基于VeeamBackup&Replication实现对虚拟化环境的灵活监控。本书图文并茂步骤详细介绍了大量的实用知识能够让读者清晰地理解虚拟化项目部署中的操作细节。本书适合于从事企业信息化运维工作的虚拟化工程师学习也可以作为项目管理人员实施企业虚拟化项目的参考书还可作为高等院校虚拟化技术相关课程的教材。\n划线\n\n虚拟化技术在企业中的应用主要涉及服务器虚拟化、桌面虚拟化和应用程序虚拟化三方面\n\n\n云计算分成3个层次分别是IaaSInfrastucture as a Service基础架构即服务、PaaSPlatform as a Service平台即服务和SaaSSoftware as a Service软件即服务\n\n\n根据云计算资源所在的位置分成公有云、私有云和混合云3种。公有云是指所有的资源都放在厂商建设的数据中心用户通过互联网接入获取到相应的云资源使用便捷按需付费。私有云是指所有的资源都由用户方进行建设放在自有的数据中心中。资源固定安全性高。混合云是私有云和公有云的结合。\n\n\n在各大招聘网站上搜索。从各个招聘渠道去搜索虚拟化工程师、系统工程师、IT工程师、IT技术支持等\n\n\n1IT管理管理技术团队、ITIL、PMP。2IT基础架构微软Active Directory、DNS、DHCP、WSUS、NTP、GPO、Exchange。3数据库SQL Sever、MySQL、Oracle。4虚拟化VMware vSphere、VSAN、NSX、Citrix XenServer、XenDesktop、XenApp、Openstack、KVM。5备份Veritas、Acronis、Veeam。6监控Tivoli、Zabbix。\n\n\n·制定蓝图——规划企业整体IT架构方案。·搭建IT基础架构——部署和配置各类服务器。·配置服务器虚拟化——提供基础服务功能。·配置企业云桌面/云应用虚拟化——实现统一的办公环境管理。·安全第一——构建虚拟化场景下的备份系统。·搭建监控系统——力求系统稳定运行。\n\n\n·AD域架构服务器。·虚拟桌面/应用服务器。·DNS服务器。·备份服务器。·DHCP服务器。·监控服务器。·邮件服务器。·目录服务器。·虚拟化服务器。·数据库服务器。\n\n\n比如NTP服务器会提供时间同步服务其他计算机的时间会与该NTP服务器保持时钟同步WSUS服务器会提供Windows的补丁服务其他计算机会从WSUS服务器获取微软发布的最新补丁避免因漏洞、后门等引发安全问题。\n\n\n在硬件层上添加了虚拟化层这种架构也被称为裸金属架构。\n\n\n目前市场上主流的服务器虚拟化产品有VMware vSphere、Citrix Hypervisor原Citrix Xenserver、Microsoft Hyper-V等。对于虚拟化工程师来说掌握12种常见的服务器虚拟化产品的部署、调试和维护是必不可少的技能。\n\n\n服务器提供了计算资源网络设备将服务器之间连通存储设备提供了数据存储的空间。\n\n\n常见的监控软件有IBM Tivoli、SolarWinds、Zabbix、Cacti、Nagios、Ganglia等。\n\n\n基础架构的范围比较广泛广义上包含服务器等计算机设备、路由器、交换机等网络设备存储阵列、防火墙等安全设备机房制冷设备等狭义上特指微软相关的基础架构服务器例如域控制器、DNSDomain Name System域名系统服务器、DHCPDynamic Host Configuration Protocol动态主机配置协议服务器、WSUSWindows Server Update ServicesWindows Server更新服务服务器等。\n\n\n这就好比是一个部门的员工大家各自负责一方面的工作内容有人负责服务器有人负责网络也有人负责安全。但随着员工数量的增多老板没有更多的精力管理所有员工于是指定了一个部门经理专门管理其中一部分员工。这样一来部门经理来统一规定本部门员工的工作内容和指定规章制度等。针对大规模的计算机来说也要实现统一的管理就需要借助AD来帮忙。域控制器担任了“部门经理”的角色部门经理的存在就决定了整个部门的成立而其他的计算机由域控制器进行统一管理。\n\n笔记\n书评\n点评"},"Personal/Book/计算机/计算机:一部历史":{"title":"计算机:一部历史","links":[],"tags":["阅读/计算机-理论知识","阅读/笔记"],"content":"简介\n\n书名《计算机一部历史》\n作者 彼得·本特利\n分类 计算机-理论知识\nISBN9787121255113\n出版社中信出版集团\n\n概述\n《计算机一部历史》给大众读者写的计算机科普读物零门槛入门计算机科学。讲述计算机背后鲜为人知的故事普及关于计算机和互联网你不得不了解的知识。在过去数十年里除非你一直与世隔绝否则就不可能不受到信息革命的影响。我们身处技术演进史上的计算机时代无论你是计算机和互联网的拥护者、反对者还是旁观者无论你是否具备计算机专业背景只要你使用计算机这本书就是你的案头必备。\n\n划线\n\n显然无论从事哪一个行业要想赚取巨额财富通晓计算机是必不可少的条件。\n\n\n计算机或许是我们无声的奴隶盲目地执行每一项指令但是我认为我们可以从计算机上学到很多东西通过它们了解这个世界乃至人类自身。\n\n\n计算机科学主要涉及到编程、工程学和数学\n\n\n德国的著名密码系统——“恩尼格玛”9Enigma\n\n\n1954年图灵被发现死在家中身边放着咬了一口的苹果。\n\n\n开创计算机革命的中心人物是艾伦·图灵他杰出的创见和视野使这一切成为了可能。变革始于20世纪30年代尽管我们现在难以预见计算机革命的极限究竟何在但是图灵本人指出了这种理论局限性的存在。\n\n\n复杂即是简单\n\n\n通用图灵机Universal Turing Machine已成为世界上所有电子计算机的理论蓝图。\n\n\n现代的计算机系统虽然日新月异但万变不离其宗大框架都是冯·诺依曼1952年在普林斯顿构建起来的。\n\n\n被剥夺了思考的权利比死还难受\n\n\n公司意识到其庞大的数据中心通常只有10%的容量得到了有效利用因此在2006年该公司开始推出亚马逊网络服务Amazon Web Services ),出售数据中心的闲置容量。其他公司可以按需购买亚马逊提供的任何计算服务、软件和存储空间,而不需要维护或升级任何计算机\n\n\n1951年计算机开始搭载好几个层次的软件。第一层是微代码它完全依赖于芯片内部的硬件连接。第二层是机器代码它比微代码更抽象一些。第三层是汇编语言它比机器代码可读性稍强。\n\n\n1957年IBM 的约翰·巴库斯John Backus 发明了另一种编译型高级编程语言称为福传FORTRAN )。\n\n\n软件设计师的角色类似于建筑师和土木工程师尤其是规划城市、工厂等复杂建筑的设计师。因此我们应该学会从这些领域吸取灵感攻克我们遇到的设计问题。”\n\n\n这一概念在模块化编程和面向对象的编程领域举足轻重它可以确保数据及相关函数封装在对象内与其他的数据和函数分隔开来\n\n\n集成开发环境Integrated development environment简称IDE )的发明,就是为了让编程变得更加轻松。\n\n\n研究人员很快意识到要做到这一点必须确立一个明确的软件生命周期。首先你必须合理定位产品和项目需求。接下来要做的就是设计、运行和测试软件并将其运行情况清晰地记录下来。最后要做的就是发布软件或许在这个阶段你还需要指导用户如何高效地使用软件、如何进行必要的维护工作。\n\n\n因为顾客往往并不知道自己真正的需求到底是什么因此可能会举棋不定、自相矛盾甚至改变主意。他们往往不具备编程人员的思维方式因此不知道如何从软件开发的角度表达自己的需求。\n\n\n统一建模语言Unified Modelling Language简称UML )将多种建模概念融合在一起,如今已成为软件系统建模的标准方式。\n\n\n维尔特定律的内容是软件变慢的速度永远快过硬件变快的速度。\n\n\n优化软件就相当于优化一切。\n\n\n上面所说的老板就相当于计算机的应用程序比如网页浏览器和网页服务器通信总监相当于TCP传输控制协议收发室相当于IP互联网协议邮递员相当于地址层也就是低层次的传输方法比如以太网Ethernet 、IEEE 802等局域网协议以及点对点协议Point—to—Point Protocol简称PPP )等框架协议。\n\n\n计算机需要有地址这样才能确定信息的发送方和接收方\n\n\n我儿子今年十岁他现在不看广播电视只看iPlayer。他对电视节目的固定播放时间已经没有概念了因为现在想看什么节目随时都可以看。\n\n\n譬如密码的长度有最低限制必须采用大小写字母、数字及标点符号混合的密码而且最好每过几周更换一次。\n\n\n如果过去的一项决策让我们更快乐那么在未来遇到相似的情形时我们就更倾向于做出相似的决策\n\n\n既然人类能够凭借神经元释放的数十亿个电脉冲产生思维活动计算机为什么不能如法炮制利用电子电路释放的电脉冲来产生思维活动进而完成各种各样的智能任务呢\n\n\n冯·诺依曼在研究经济学和博弈论时就已经预见到了这个问题。他证明了最小最大定理minimax ),该定理表明,博弈双方的任何一方都会采取最有利于自己、而最不利于对方的策略。香农在会下棋的计算机中应用了这一思想\n\n\n英文等自然语言能否用于编程可模拟人脑神经元的程序能否编写出来计算机能否通过学习而不断进步计算机应该如何表达信息在算法中增加随机性是否就能提高创造力\n\n\n从很早的时候开始科学家就开始为计算机智能的发展方向争论不休。他们分成三派第一派以麦卡锡为代表认为逻辑推理是计算机智能化的必由之路。第二派以麦卡洛克、皮茨为代表认为构建神经元模型才是正道。第三派以明斯基为代表认为计算机要想实现智能化就必须首先具备现实世界的知识。\n\n\n一系列新的计算机程序在此基础上相继问世引起了巨大的轰动。一款叫做“专家系统”expert system 的新程序走进了人们的视野。它能够有效地运用某个领域的专家多年积累的有效经验和专门知识通过模拟专家的思维过程解决一系列问题。它的用途非常广泛可用于诊断疾病也可用于推荐合适的理财产品这取决于每个专家系统的专长是什么。研究人员渐渐认识到他们可以用计算机来处理自然语言即自动对句子结构进行划分和处理。“聊天机器人”Chauerbot 是一款用于模拟人类对话或聊天的程序“Eliza ”和“Parry ”都是早期非常著名的聊天机器人,这些程序整合了大量语言学资料,使计算机可以对用户的输入语言进行处理,然后做出相对较为可信的回复。有时候,它们的表现着实令人称奇,短时间内甚至会让人误以为它们是真人。\n\n\n你其实知道这是一把勺子虽然你并没有看到它的全部只是看到了它的柄和勺尖。但是感知机做不到它不能把这些信息汇总起来得出一个真实可靠的结论\n\n\n传统的人工智能观点包含了一个中心假设那就是所有的行为都是通过对环境建模然后依据模型进行逻辑推理后才产生的。\n\n\n自由意志表现在很多方面比如不可预知性、目标搜寻、自我调节、趋利避害、前瞻性、记忆力、学习能力、遗忘性、联想能力、形状识别还有就是一些能使它适应社会的要素。这才叫生命。”\n\n\n比如胚胎的形成、生物的发育过程等生长过程怎样才能用进化算法实现在此基础上怎样才能开发出更加复杂的算法如今进化学习已经成为人工生命和机器人学领域的重要组成部分。很多公司利用它的成果开发出了多种多样的应用性产品手机的天线设计还有存储芯片就是两个典型案例。\n\n\n必须存在一种环境使人工智能体可以与它互动换句话说就是人工智能体要在环境的压力下生存下来。我从一开始就是这样想的。我不相信机器可以不通过学习和适应就获得真正的智能。\n\n\n自上而下的逻辑编程也好自下而上的进化适应方法也好无论采用哪种方案都无法解决所有的问题。没有任何一款程序能够通过图灵测试。我们还是很难制造出一台具备智能的机器无法在不可预测的环境中操控机器人。\n\n\n感知机和反向传播算法该算法可以自动调整神经元输入信号的权重的局限性曾经引发过学术界的猛烈批判\n\n\n在探索的旅途中人们得以从全新的视角审视了困扰哲学家数百年的问题人为什么存在生命的起源是什么生命体何以进化出了如此复杂多样的形式智能是什么意识是什么\n\n\n复杂的经济活动是由无数较为简单的交易活动构成\n\n\n“假如有一台巨型计算机它不仅能够模拟人脑中的所有电信号还能够对突触所在环境的化学物质及其浓度变化进行建模那么这台计算机就应该可以称得上是具备思考能力了”\n\n\n“毕竟它模拟了真实的大脑活动既然真实的大脑在思考那么为什么不能说模拟的大脑也在思考呢这就是我的观点。”\n\n\n也许我们会意识到其实智慧并不是什么重要的东西真正重要的是经验。\n\n\n虽然前进的道路只有一小段是明晰的但纵使是这一小段探索的道路也充满了艰险的挑战\n\n\n“想象力的桎梏一下子被打破了”他说“它还破除了你的偏见、成见和思维定势。利用进化式的生成过程艺术家能与机器形成合力。这就好比一种创造力倍增器无论是人类无法想象的作品还是单靠计算机无法创作的作品它都能创作出来。我现在都还在想这个主意实在是太厉害、太令人振奋了。”\n\n\n归根到底艺术圈也是门生意作品还是要拿来卖的所以它讲究一个稀缺性。\n\n\n艺术不是什么神秘的东西。真正的艺术家只不过是眼光稍微比普通人高一点罢了。”\n\n\n生命是如何从非生命物质中产生的它们是如何进化的简单的相互作用是怎么导致如此复杂的生物行为的\n\n\nDNA 层次的突变首先要反映到生物的整体层面上——譬如反映到生物的形状、生理以及行为学上,只有经历了这样的层次转化以后,才会进入自然选择的过程。\n\n\n从能量的角度看我们合并图像的目的就是要将信息熵降低合并后图像的熵应该要比两张独立图像的信息熵之和要小。\n\n\n兵贵精而不贵多\n\n笔记\n\n“我的个人理想就是赚足够的钱给自己买一间办公室再在办公室里配上一块白板白色的金属板材料制的书写平面这样我就可以随心所欲地研究P=NP问题了。”\n\n💭 唯有热爱可抵岁月漫长\n\n现在我们意识到网络安全不仅仅关乎科技还关乎于人。”\n\n💭 技术并不能解决所有问题\n\n假设两个房间里分别有一个人、一台计算机你作为提问人进入第三个房间通过一些装置如键盘对他们随便提问。假如过了五分钟你还判断不出谁是人、谁是计算机那么这台计算机就通过了图灵测试。\n\n💭 图灵测试\n\n这种经过人为设计的景观是否比原生态的自然景观更美\n\n💭 美,是非常主观的判断\n\n有时候你不一定要自己具备专业知识要学会借助别人的力量。相反如果你自信满满以为自己已经掌握了某方面的知识那就得当心说不定你只是一知半解而已。所以你得找到可以合作的人而且要让自己表现得值得信赖这才是最关键的。\n\n💭 一个人可以走的嘎嘎快,但是几个人可以走的非常远。\n书评\n点评"},"Personal/Journal/2022/W34/2022-08-24":{"title":"2022-08-24","links":[],"tags":[],"content":"2022-08-24\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 17:03郑州 +32°C ☀️🌘\ndaily\n\n接天莲叶无穷碧映日荷花别样红。\n— 晓出净慈寺送林子方·杨万里(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n今天依旧是忙碌且充实的一天哈哈。\n折腾了两天的微信推送终于搞定了先跑再说。\n学习了好久的 obsidian 也是终于和 Docusaurus 结合在了一起,推出了个人知识管理库 1.0.0 的第一个正式版本,奥利给 \n今天是个好日子等下班溜溜球啦。"},"Personal/Journal/2022/W34/2022-08-25":{"title":"2022-08-25","links":[],"tags":[],"content":"2022-08-25\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 21:05郑州 +21°C ☀️🌑\ndaily\n\n洛阳相君忠孝家可怜亦进姚黄花。\n— 荔枝叹·苏轼(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n刚洗漱完躺床上 \n昨天回家住了一对比集体宿舍太吵了……\n早上纠结吃鸡蛋饼还是三明治还是烤肠还是煎蛋最后小孩子才做选择三明治真香警告⚠\n最近整的微信推送早上起来一看 windows 更新中断了……\n万恶的 windows只能再等一天了……\n今天把软考交了费报名一年了万恶的疫情……\n不过还好今天终于继续输出算法系列了争取下周日前过一遍。\n又输出了一篇博客继续继续继续奥利给\n今天好多奇奇怪怪事情意大利什么主席加我微信了说我是天才哈哈。\n不说了看书了不要问我为啥没工作日志问就是在摸鱼在剥削资本家。"},"Personal/Journal/2022/W34/2022-08-26":{"title":"2022-08-26","links":[],"tags":[],"content":"2022-08-26\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 20:42郑州 +23°C 🌦🌑\ndaily\n\n大漠孤烟直长河落日圆。\n— 使至塞上·王维(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n今天上午又折腾了一番微信推送重构了程序并且增强了程序的健壮性。后续的日后再说吧 \n下午的时候也不知道忙啥了看看资讯东看看西看看就想等下班了\n今天看到了一个视频很有深意不要在饿的时候去超市也不要在孤单的时候恋爱。我这周看了一本书也是关于此的蛮有哲理的。\n下班和小雅一起吃了螺蛳粉好好吃😋\n张天爱的男友出轨了贵圈真乱。\n洗洗睡了晚安各位"},"Personal/Journal/2022/W34/2022-08-27":{"title":"2022-08-27","links":[],"tags":[],"content":"2022-08-27\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周六 21:08郑州 +21°C ☀️🌑\ndaily\n\n藕花珠缀犹似汗凝妆。\n— 临江仙·雨停荷芰逗浓香·阎选(五代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n周末周末你快乐嘛 ~ 我很快乐!\n懒懒散散的睡了个大懒觉搞了点吃的继续睡。不过今天通过技术手段帮别人抢到了一所小学的入学名额奥里给真是技术改变生活 ~\n下午磨磨唧唧的可算出门了去了省博物馆转了转本来想请个导游讲解了没人……租了个电子讲解哦~~~ 是真得拉闸,最后胡乱逛吧。\n吃了烤肉超级好吃早早的就回家啦周末快乐奥里给\n工作热水抱歉周末了好吧"},"Personal/Journal/2022/W34/2022-08-28":{"title":"2022-08-28","links":[],"tags":[],"content":"2022-08-28\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 22:51郑州 +16°C 🌦🌑\ndaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n今天周末的最后一天、下雨了、依旧是颓废的一天。\n啥都没干看了看 RSS 订阅、温习了一下 git 分支,等待着周一的到来 ~\n晚饭吃了馒头夹辣条满满的都是我俩的回忆杀。接着一起看了《隐入尘烟》若有所思但又不想回忆……\n晚安啦gogogo"},"Personal/Journal/2022/W34/2022-W34":{"title":"2022-W34","links":[],"tags":[],"content":"2022-W34\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 09:50郑州 +17°C 🌦🌒\nDaily\n\n可怜楼上月徘徊应照离人妆镜台。\n— 春江花月夜·张若虚(唐代)\n\n\nProcess\n\n微信推送0 → 1经过数次迭代目前已经稳定运行待增加推送信息多样性。\nWiki & Obsidian 的个人知识库 1.0.0 版本正式推出。\n阅读《认知觉醒》一书。\n周末去河南省博物馆玩啦 ~\n\nProblem\n\n算法笔记未更新、被打断\n读书笔记未输出\n\nNotes\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价4 分效率一般,产出比较低,\n落实项目《微信推送》较为顺利周五前完成测试版填补了实际的项目经验。简单来说\n\n分离整理项目需求\n一定要让程序能跑起来\n就上线在实际运行中去发现问题\n再去寻求最优解\n\n目前打造的个人知识库工具较为成熟期待工具带来的效率提升\n周末去河南省博物馆准备也不充分没有导游只是在散步 ~\n算法笔记拖延了好久。\nNextWeek\n\n软考前两章 + 算法笔记\n微信推送消息多样性\n数学 + 英语的学习规划\n周末待定\n"},"Personal/Journal/2022/W35/2022-08-29":{"title":"2022-08-29","links":[],"tags":[],"content":"2022-08-29\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 21:56郑州 +19°C ☀️🌒\nDaily\n\n洛阳亲友如相问一片冰心在玉壶。\n— 芙蓉楼送辛渐·王昌龄(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n早上来了写了上周的工作总结并且尝试了对 wiki 多分支进行合并,新的一周感觉开始还不错。\n今天工作上沙雕太多感觉总是影响情绪。沟通效率太低我也不想把耐心都给他们总之很拉闸。\n容易偶发性的浮躁不过今天情绪稳定下班一起逛了逛超市买了些早点。\n早上刷软考通的题目真的是绕……\n我要看书去了各位晚安💤"},"Personal/Journal/2022/W35/2022-08-30":{"title":"2022-08-30","links":[],"tags":[],"content":"2022-08-30\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 10:01郑州 +22°C ☀️🌒\nDaily\n\n一番荷芰生池沼槛前风送馨香。\n— 临江仙·一番荷芰生池沼·尹鹗(五代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n周二忘记写啦忙的稀里糊涂……\n早上看看新闻整理了一下周一没有搞定的 wiki工作效率比较差因为中途发现了一个好用的工具折腾了一会。\n坚决不折腾、尝试贯彻番茄工作法。\n晚上去蝶湖散散步又吃了宵夜。\n今天周三冲冲冲"},"Personal/Journal/2022/W35/2022-08-31":{"title":"2022-08-31","links":[],"tags":[],"content":"2022-08-31\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 23:24郑州 +22°C ☀️🌒\nDaily\n\n即从巴峡穿巫峡便下襄阳向洛阳。\n— 闻官军收河南河北·杜甫(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n今天从早到晚上都在努力学习尝试应用了番茄工作法。一天的体验下来确实没有以往那样下班了懵懵的效率也提升了不少。\n新增完善了信息安全-权限控制这块,还有 MySQL 也完善了一下。写了一篇博客还被人发现并且嘲笑了错字,脑瓜子懵懵的,仔细检查了一番确实存在明显的错误。\n秉承有则改之无则加勉以后发表博文先机器文字检验一遍人工再检验一遍然后 7 天以后再检验一次发表到博客,不能再出现这么低级,明显的错误了。\n同时不再盲目的追求数量了一周产出一篇文章即可。\n今天月末公司值班到现在脑瓜子已经懵懵的了怕自己忘记什么就在车里写了一下日记。\n新的一个月9 月加油。\n晚安💤"},"Personal/Journal/2022/W35/2022-09-01":{"title":"2022-09-01","links":[],"tags":[],"content":"2022-09-01\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 10:52郑州 +22°C ☀️🌓\nDaily\n\n兰有秀兮菊有芳怀佳人兮不能忘。\n— 秋风辞·刘彻(两汉)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n因为周三是八月份最后一天所以业务部门要冲业务量导致加班到 11 点,然后周四一整天都是蒙蒙的,没有任何工作效率……\n简单温习了一下 git 分之,随心所欲无所事事,直至下班。\n我俩一块去吃了蜜雪冰城的冰淇淋奥里给然后又去尝了旁边新开的一家油泼面面做的还不错就是其他菜品差强人意不过最后两个人才吃了 35 块钱。\n晚上有点失眠也不算是失眠看书看的快瞌睡了然后过了那个点就不想睡了……打开淘宝做任何可以让我选择的事情这种被本能驱使的快感还是被抖音毒害的不浅啊。\n周五了最后一天算法笔记还没写……"},"Personal/Journal/2022/W35/2022-W35":{"title":"2022-W35","links":[],"tags":[],"content":"2022-W35\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 11:59郑州 +31°C ☀️🌔\nDaily\n\n西风酒旗市细雨菊花天。\n— 秋怀·欧阳修(宋代)\n\n\nProcess\n\n软考 前两章 笔记完成。\nGit 分支温习完成。\n读书笔记输出中。\n\nProblem\n\n软考算法笔记未完成。\n《认知觉醒》未读完。\n\nNote\n啊啊啊、这周产出极低没有干成什么比较有用的事只去快乐了哈哈哈。\n这周下学期的课程也要开始了安排规划一下数学、英语、刷课程。然后软考的算法笔记输出每天刷刷题。还有就是读书笔记的输出同时在寻找一本新书去阅读。\n如果想 coding 的时候,就去重构一下微信推送,还有就是了解一下公共广播!\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价1无效率产出极低\nNextWeek\n\n算法笔记更新完成\n读书笔记输出\n微信推送重构\n寻找一本新书阅读\n数学 + 英语的学习规划\n下班学习的刷课计划\n"},"Personal/Journal/2022/W36/2022-09-05":{"title":"2022-09-05","links":[],"tags":[],"content":"2022-09-05\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 21:39郑州 +31°C ☀️🌔\nDaily\n\n细雨春芜上林苑颓垣夜月洛阳宫。\n— 书愤二首·陆游(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n周一周一永不懵逼。\n今天早上总结了一下上周的工作学习虽然但是不过新的一周已经开始了。\n整个一天都比较悠闲主要还是喝酒搞得有点费有点难受还是不频繁的喝酒好呀。否则喝酒一时爽酒后难受死。\n下班运动了运动但是好想吃好吃的 🤯。小雅又要开始加班啦,俺要小心行事。\n看书了看书了溜溜球 "},"Personal/Journal/2022/W36/2022-09-06":{"title":"2022-09-06","links":[],"tags":[],"content":"2022-09-06\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 08:35郑州 +20°C ☀️🌔\nDaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天早上莫名奇怪的小雅就爆炸了……男人好难、真的好难 ~\n上午完成了部分学习进度下午使用剪影剪了个视频下班也是继续哄小雅啦啦啦啦啦啦啦。\n然后去打球了虽然自己还是有一点真功夫的但是感觉自己没有好胜心了。一直都在思考自己究竟是怎么了以前是一个好胜心巨强的人感觉环境原因很重要吧。\n晚上很晚才睡有点情绪泛滥就一直在熬夜熬夜熬夜顺应自己天性好啦新的一天又将是快乐的生活 ~\n向前冲冲冲"},"Personal/Journal/2022/W36/2022-09-07":{"title":"2022-09-07","links":[],"tags":[],"content":"2022-09-07\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 23:12郑州 +22°C ☀️🌔\nDaily\n\n乡书何处达归雁洛阳边。\n— 次北固山下·王湾(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n今天没干成什么事情上午呢一直在看露营的东西不对露营喝茶的东西。荒废放松放松哈哈哈我的算法笔记芜湖……\n中午吃的挺好嘞晚上也是加餐能吃到好吃的就很不错了。\n下午就去参加中秋节联谊晚会了节目效果什么都挺不错嘞就是红包没抽到我又开始了一本新书冲啊\n下班的一个小时来了点思路和灵感⚠关于企业数字化建设的期待后续的完善。\n晚上又加了一会会班然后回来锻炼刷抖音了刷抖音真爽哈哈哈。\n明天呢开始算法笔记并且尝试完善企业数字化建设。\n看书啦晚安晚安💤"},"Personal/Journal/2022/W36/2022-09-08":{"title":"2022-09-08","links":[],"tags":[],"content":"2022-09-08\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 17:07郑州 +26°C ☁️🌕\nDaily\n\n可怜楼上月徘徊应照离人妆镜台。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n无学习、今天玩的很开心 ~"},"Personal/Journal/2022/W36/2022-W36":{"title":"2022-W36","links":[],"tags":[],"content":"2022-W36\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 17:13郑州 +29°C ⛅️🌖\nDaily\n\n人成各今非昨病魂常似秋千索。\n— 钗头凤·世情薄·唐婉(宋代)\n\n\nProcess\n\n开始了一本新书\n买了便携式茶具\n\nProblem\n\n微信推送未完成\n读书笔记未完成草稿\n算法笔记未完成未开始\n刷课计划+英语+数学(未开始)\n\nNote\n这周零零散散的工作产出极低可以说是无整体只是在吸收整理碎片化的知识而且脱离了环境产出无受环境影响极大。\n早起作息在公司比较规律但是中秋节回到家就有点太放肆了。以后可以尝试换一个合适的环境例如周末了去公园散散步、去图书馆读读书、或者拍照都是很不错的选择。总之就是换一个适合的环境做适合的事情习惯培养初期还是容易受环境的影响。\n学习学习还是无法按照每日执行的计划去做总是会被支线任务、或者是日常任务所打破造成主线任务无法按时推进。\n强调主线任务的重要性每日必须要先完成主线任务再去完成支线任务碎片化时间以及富裕时间再去进行日常任务和临时任务。\n阅读和早起拥有一毛一样的毛病就是脱离了合适的环境就没办法坚持下去或者说是环境因素影响过大还是可以去尝试换个环境或者坚持阅读。\n协作目前协作效率太低归纳输出总结一篇读书笔记总是会耗费很长时间还是要每日定下必须完成一项笔记输出无所谓时间然后慢慢加快速度。或者在阅读的时候尝试加上笔记笼统的描述一下心得最后升级整理一下会更快一些。\n运动工作日运动保持的不错休息日就不行了。\n总的问题还是主 / 次区分不够明显,每日必完成项目没有完成,容易被其他任务打破,无法获得正反馈;解决方法就是每日必须完成一项主线任务,接着再完成两项支线任务,最后再完成日常任务。划分主次,主线任务必须完成,支线任务尽量完成,日常任务碎片化时间完成。\n一到休息日就容易懈怠然后工作日还需要时间恢复状态。以后要坚持休息日也正常作息做一些喜欢的事情拍拍照读读书出去转转总之就是换个环境换个大脑多从事一些艺术类创造工作离开家里这个容易懈怠的环境。\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价0效果很差\nNextWeek\n\n软考 - 算法笔记(主线)\n微信推送重构上线支线\n数学 + 英语学习规划(支线)\n读书笔记输出两篇支线\n成人本科刷课计划支线\n阅读书籍支线\n"},"Personal/Journal/2022/W37/2022-09-12":{"title":"2022-09-12","links":[],"tags":[],"content":"2022-09-12\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 22:49郑州 +21°C ☀️🌖\nDaily\n\n忆对中秋丹桂丛花也杯中月也杯中。\n— 一剪梅·中秋元月·辛弃疾(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划\n 今日分享\n\nNotes\n中秋节过得很拉闸这阵子过得很拉闸。简单复盘一下。\n任务执行上效率没问题就是有时候没有明确任务有点猴子下山的感觉。接下来每天明确一项主线任务然后副线任务可以有多个日常任务但是必须完成一项主副任务。贵在坚持周六周日也要完成任务。不仅仅局限于学习可以是生活拖地等等每天一定要做出一些事情。\n生活习惯上受环境影响很大。一回到家一周末就懒散的不能行这个目前来说有点困难……家里的这个环境实在是太差强人意了没有一个合适的工作环境和学习环境很容易就懒散起来。以后尝试走出去周末尽量不在家待着没事出去溜达溜达。尽快搞定家里沙发周末不在卧室度过可以去踏春图书馆逛街总之周末离开家。\n情绪上啊啊啊啊感觉和父母还是很难似乎已经形成了潜意识了。其他地方处理的还蛮不错感觉改不了或者说很难有成效以后还是逃避这种意识形态的交流日常生活多关心一下就好不要在交流意见了糊弄了事好啦。\n这一个月的日志还是能够看到问题所在以及需要提升的地方贵在坚持知行合一"},"Personal/Journal/2022/W37/2022-09-13":{"title":"2022-09-13","links":[],"tags":[],"content":"2022-09-13\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 22:25郑州 +25°C ️🌖\nDaily\n\n乡书何处达归雁洛阳边。\n— 次北固山下·王湾(唐代)\n\n\nHabits\n\n 早睡早起\n 健康饮食 🥗\n 多喝热水 \n 保持运动\n\nTo-do List\n\n 阅读资讯\n 今日读书\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天复盘总结了一下最近的学习工作生活也思考了对应的解决方案期待执行效果。\n今天球场竟然不开灯打消我运动的积极性。不过现在左手投篮是越来越熟练了冲啊\n看书去了溜溜球嘿嘿嘿嘿嘿😈"},"Personal/Journal/2022/W37/2022-09-14":{"title":"2022-09-14","links":[],"tags":[],"content":"2022-09-14\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 20:21郑州 +26°C ⛅️🌖\nDaily\n\n江天一色无纤尘皎皎空中孤月轮。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天临时起意更新了博客主题哎西吧。又欠了好久的读书笔记和算法笔记真的是东一榔头、西一棒子。\n明天清零All In。"},"Personal/Journal/2022/W37/2022-09-15":{"title":"2022-09-15","links":[],"tags":[],"content":"2022-09-15\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 22:57郑州 +22°C ☀️🌗\nDaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天状态不错就是最近可能要换季节了咽喉会有点难受天气也是干的要死。\n今天正确执行了任务但是呢晚上回家休息不是太好所以就到今天来写了。不错不错良好的开端慢慢修正航线"},"Personal/Journal/2022/W37/2022-09-16":{"title":"2022-09-16","links":[],"tags":[],"content":"2022-09-16\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 22:59郑州 +22°C ☀️🌗\nDaily\n\n浔阳江头夜送客枫叶荻花秋瑟瑟。\n— 琵琶行 / 琵琶引·白居易(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天贯彻执行了周计划中的目标这两天《羊了个羊》活得不行也是玩了几把好虐啊。\n今天算是彻彻底底把程序设计语言和算法笔记框架更新完了画出的思维导图需要填充那么多知识头都大了……不过要有愚公移山的精神慢慢来嘛 ~\n明天就是周六啦打算明天早上起来吃个饭锻炼一下。然后去公园看书光是脑海中想象一下晒太阳看书就会很自在睡到自然醒然后就去\n今天还有两项支线任务没有完成打算干完虽然状态不好但是这两项任务不需要太好的状态微信推送项目继续增强程序健壮性还是容易死……成人教育的刷课计划大致浏览一下 ~\n差不多就要凌晨了然后躺床看会书就睡觉啦 ~"},"Personal/Journal/2022/W37/2022-09-17":{"title":"2022-09-17","links":[],"tags":[],"content":"2022-09-17\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 00:55郑州 +22°C ☀️🌗\nDaily\n\n低声问向谁行宿城上已三更。\n— 少年游·并刀如水·周邦彦(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天做的很好呀早上起来收拾收拾整了点好吃的。然后就出门啦去蝶湖公园坐了坐拉个躺椅摆个桌子开始了一大上午的快乐 ~\n中午的时候点了个外卖很不错真的好惬意喜欢这种感觉 ~\n下午同学又来找我打球了哎西吧我的这个脚趾甲真的是烦死人了\n好端端的怎么会脱甲呢又得半个月不能打球了……估计跑步也是够呛\n小雅今天加班然后感觉可能是我没陪她情绪也不对闷着气在甩脸色给我的心情搞得很糟糕……时不时的断联我也是很烦\n情绪有点泛滥了洗洗澡看会书睡觉啦明天还得早起去厂里一趟呢最近开头很好做的非常不错\n我不开心我不开心我不开心 😭😭😭"},"Personal/Journal/2022/W37/2022-09-18":{"title":"2022-09-18","links":[],"tags":[],"content":"2022-09-18\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 12:14郑州 +28°C ☀️🌗\nDaily\n\n秋阴重西山雪淡云凝冻。\n— 渔家傲·临水纵横回晚鞚·苏轼(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天是周一昨天晚上没有写日志不过还是很清楚的记得昨天干嘛啦。\n早上起来去叔叔的厂里了然后喝喝茶、聊聊天同时帮一位长辈备份转移了一下手机中午还蹭了一顿好吃的。\n下午回家倒头就睡了实在是太困了没有休息好然后呢还睡得特别早睡醒也不算太晚就和大学同学联系了一下拉了个会议沟通了一下昨天的事情帮助他人自己也能获得很大的成长我觉得是非常不错的 ~\n晚上找小雅去啦然后一起干饭又去湖边喝喝茶、聊聊天 ~"},"Personal/Journal/2022/W37/2022-W37":{"title":"2022-W37","links":[],"tags":[],"content":"2022-W38\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 15:05郑州 +28°C ☀️🌗\nDaily\n\n梅子黄时日日晴小溪泛尽却山行。\n— 三衢道中·曾几(宋代)\n\n\nProcess\n\n微信推送项目已完成\n算法笔记已完成\n成人教育刷课计划 10.10 开始\n英语+数学学习计划 11.05 开始\n读书笔记草稿已完成\n茶具设备已搞定\n公园阅读已搞定\n\nProblem\n\n读书笔记未输出\n\nNote\n这周的工作效率及产出相对于 36 周是极高的36 周的总结发现的很多问题在这周基本都解决了,这周的任务重点在于保持状态,持续产出!\n早起这周基本每日都是正常早期周末在家也是早早的就起来了。总之状态很不错相对于前几个周末有较大的改善继续保持\n学习任务完成较好产出也不低。继续加强保持每日主 / 支 / 日任务完成!加油加油奥里给!!!\n阅读这周阅读了一本新书尝试贯彻了《如何阅读一本书》的方法初步感觉拥有不错的效果但是《如何阅读一本书》的笔记还是处在草稿状态争取这周输出完成\n写作产出较上周有进度但是相对较低。继续加油持续回暖增加产出早日投稿人命日报\n这周总体的状态相对于 36 周有非常明显的改进和产出,做的已经非常棒了。第 37 周继续保持这个状态,培养好习惯 ~\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价6.0较大的改善,不错继续保持!\nNextWeek\n\n《中级软件设计师》第 6、7、8、11、12 章节知识笔记输出\n信息收集实验 - 数字化落实实验 in 微信阅读\n数学 + 英语具体执行计划落实\n微信推送多样化落实\n《程序员的猫》博客阅读\n简历网站构思、打磨\n"},"Personal/Journal/2022/W38/2022-09-19":{"title":"2022-09-19","links":[],"tags":[],"content":"2022-09-19\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 23:18郑州 +24°C ☀️🌗\nDaily\n\n榆柳萧疏楼阁闲月明直见嵩山雪。\n— 洛桥晚望·孟郊(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周一总是懵逼的晚上睡眠质量不好所以早上也是浑浑噩噩的。\n早上接了个小单子企业官网建设。信息差好值钱啊1k 只需要一个小时就可以。再次验证了信息资源是看不到的钱,确实真金白银的钱。\n上午状态一般而且脚指头是真的痛。下午忙的还可以算法笔记也是终于开始慢慢有了头绪不过感觉这是个大工程需要更多的时间。\n时间一溜烟的就过去了……\n今天下班得回家折腾到好久才搞定。还要洗洗衣服收拾收拾好累懒死了。今日任务完成情况可以就是脚指头真的痛。\n看会书睡觉啦早睡早起每一天啦啦啦。"},"Personal/Journal/2022/W38/2022-09-20":{"title":"2022-09-20","links":[],"tags":[],"content":"2022-09-20\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 12:10郑州 +21°C ☀️🌘\nDaily\n\n落日心犹壮秋风病欲疏。\n— 江汉·杜甫(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周一晚上没有休息好然后周二精神又很差所以工作产出不比上周但是依旧有进度存在\n一整天脑瓜子萌萌哒晚上也是放松了一下喝了一瓶口服液睡了个好觉今日周三继续努力工作、努力产出\n《如何阅读一本书》需要本周继续产出"},"Personal/Journal/2022/W38/2022-09-21":{"title":"2022-09-21","links":[],"tags":[],"content":"2022-09-21\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 10:55郑州 +26°C ☀️🌘\nDaily\n\n日下长秋城乌夜起。\n— 六丑·杨花·彭元逊(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今日状态不错全都来源于昨天晚上的口服液哈哈。\n更新了一下职场攻略然后继续学习《软考》感觉信息量有点大需要好好消化。但是软考的信息又有点老又找了一些关于软考的学习资源让我好好磨争取一次性搞定\n下班又出去转了转买了点水果挺不错很甜 ~最近晚上看书总是看着看着就睡着了,日志也都挪到了第二天才完成,以后躺床上就复盘总结一下今日。\n加油加油"},"Personal/Journal/2022/W38/2022-09-22":{"title":"2022-09-22","links":[],"tags":[],"content":"2022-09-22\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 21:30郑州 +26°C ☀️🌘\nDaily\n\n乡书何处达归雁洛阳边。\n— 次北固山下·王湾(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天早起跑步去了然后整了早饭做了一堆好吃的很喜欢这种感觉元气满满的一天。\n上午照旧浏览资讯看书学习。下午花了两个小时折腾了一下新的微信推送然后学习了新的知识点需要归纳一下 \n不想折腾 Windows 了,但是又离不开 Windows 的便利,继续加油加油加油!\n晚安💤"},"Personal/Journal/2022/W38/2022-W38":{"title":"2022-W38","links":[],"tags":[],"content":"2022-W38\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 11:38郑州 +20°C ☀️🌒\nDaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nProcess\n\n《中级软件设计师》知识笔记未完全输出\n《程序员的猫》博客阅读完成\n《提问老哥老姐》已完成\nGit 知识库整理完成\n\nProblem\n\n信息收集实验 - 数字化落实实验 in 微信阅读未进行\n数学 + 英语具体执行计划落实未进行\n微信推送多样化落实\n简历网站构思、打磨\n\nNote\n这周刚开始践行的还不错但是因为生活上的一些事导致周五周六周一太累了真的是心力交瘁……\n计划的任务未有效的完成直至今天周三了才刚刚把状态调整过来。简单说一下这周遇见的问题吧 ~\n主要就是生活和情绪上外部原因导致的。自己也不是圣人所以也没有想太多权当给自己放个假咯。说实话满不开心的终归还是自己心里期望过大然后就容易受影响无所谓啦毕竟谁也没办法还是要多一些抗压能力再深入学会理解悦纳接受。\n学习计划上期待国庆拥有一个完美的表现。\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价4.0有待继续保持\nNextWeek\n\n《中级软件设计师》持续跟进\n简历网站构思、打磨\n信息收集实验 - 数字化落实实验 in 微信阅读\n数学 + 英语具体执行计划落实\n微信推送多样化落实\n"},"Personal/Journal/2022/W39/2022-09-28":{"title":"2022-09-28","links":[],"tags":[],"content":"2022-09-28\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 11:58郑州 +24°C ☀️🌒\nDaily\n\n不如随分尊前醉莫负东篱菊蕊黄。\n— 鹧鸪天·寒日萧萧上琐窗·李清照(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n浑浑噩噩的一天感觉被什么咬了蒙蒙的……\n休息也很差慢慢调整吧 ~"},"Personal/Journal/2022/W39/2022-09-29":{"title":"2022-09-29","links":[],"tags":[],"content":"2022-09-29\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 19:24郑州 +28°C ☀️🌒\nDaily\n\n西风酒旗市细雨菊花天。\n— 秋怀·欧阳修(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天的状态依旧是蒙蒙的昨晚没休息好然后一整天都是头蒙的……\n今天任务完成的还可以零零散散的整理了一些东西。然后下午就因为头蒙中止学习了 ~\n晚上再看会书今天就结束啦。明天最后一天迎来十一假期奥里给@zzp"},"Personal/Journal/2022/W39/2022-W39":{"title":"2022-W39","links":[],"tags":[],"content":"2022-W39\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周六 16:17郑州 +17°C ☀️🌕\nDaily\n\n西风酒旗市细雨菊花天。\n— 秋怀·欧阳修(宋代)\n\n\nProcess\n\nNull\n\nProblem\n\n信息收集实验 - 数字化落实实验 in 微信阅读未进行\n数学 + 英语具体执行计划落实未进行\n微信推送多样化落实\n建立网站构思、打磨\n\nNote\n最近践行早起、阅读、写作、运动、冥想、子弹笔记近两个月了简单复盘并针对现有问题提出对应解决方案。\n早起\n我所认为的早起并不是成功学所定义的早起每日早上四点啊五点啊弱弱的感觉这种成功学大部分都有病……\n早起可以延申为规律生活规律作息并不是单纯意义上的四点起床五点起床。结合个人实际情况我所定制的休息时间为 23:00 休息6:00 左右自然醒。不过大多时候都是 7:00 左右起床,偶尔 6:00 左右,一般只要醒了就不会再睡了,否则我是越睡越困、越困越睡……\n这两个月总体来说坚持得不错相对于之前有较大的改善不过还是偶尔会被外部原因所打乱作息。下一阶段性目标继续坚持非必要不打破作息。\n阅读\n每周阅读一本书还是完全 ok 的,但是吸收归纳产出的话,一个月可能才会啃烂一本书,有些书真的需要细嚼慢咽,慢慢回味。\n读书这件事真的会上瘾但是感觉很拉闸的一点就是目前为止还没有找到比较有效利用碎片化时间的方法。所以虽然每日都在阅读但是需要最少 15 分钟以上的空闲时间,才可以进入沉浸式阅读。\n目前暂时停止了读书计划因为前几本书的产出还未完成所以打算再产出后再开始新书阅读。下一阶段性目标提高产出效率保持阅读频率。\n写作\n产出效率较低一直是我比较头疼的地方也许是没有找到正确的方法论感觉也是写的太少想得太多。不想写流水账感觉有点敷衍未来还是需要不断尝试寻找适合自己的方法。\n\n曾经完成过一次500日写作如今又开始新一轮500日写作的人帮你总结道写作开始的时间并不是你准备、收集、思考、规划、大纲等等过程写作开始的时间就是你开始写下第一个字的时间然后继续下去。\n—— ONO\n\n目前还是参考 ONO 的建议,但是先写在 wiki 上,然后每周甄选一篇博客发表,暂时就这样尝试。下一阶段性目标:实现每周产出。\n运动\n运动还是需要保持在生活中留出一部分时间去运动、散步然后继续坚持。不能这几天猛怼接下来几天偷懒要把运动当成吃饭一样 ~\n工作日的时候早起的话就会去跑跑步晚上下班也会在宿舍撸撸铁不追求马上看到成绩主要还是培养习惯。同时搭配良好的饮食习惯拥有一个健康的身体才士革命的本钱呐。\n下一阶段性目标继续保持争取早日养成运动习惯。\n冥想\n浅尝了一下这玩意真不是玄学YYDS\n子弹笔记\n子弹笔记也可以理解为复盘总结目前每日、每周、每季度都会进行工作生活的复盘。本来是一提起日记就会头痛的但是结合自己的情况尝试了多种方法最终找到了适合自己的工具和方法。\n日志总结归纳在 wiki 上边了,可以点击打开浏览。最重要的就是每日任务、复盘、习惯养成,有想法的朋友可以尝试一番。目前发现的几个问题是:任务完成效率不高、习惯养成容易被打破、子弹笔记容易中断。首先必须肯定这两个月来的进步,但是仍然需要继续保持,直至习惯的养成。\n任务完成效率不高同时带有拖延主要原因还是对任务难易的估量偏差过大。目前针对此情况的解决方法是主线任务、支线任务、其他任务主线任务是具有一定难度和时间成本的但是无论如何必须完成支线任务相对主线任务较简单的所以最少完成一个其他任务则是换脑子的很容易就完成的可以在疲惫的情况下换换脑子。\n这样的话每日都能切实感受到自己的进步并且持续保持正反馈\n子弹笔记和习惯养成容易被打破这方面主要还是降低心理预期毕竟都不是圣人。\nTake easy慢慢来 ~\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价3.0复盘总结问题,吸取经验成果。\nNextWeek\n首先今日是周六下周一之前将未完成的任务收尾同时进入工作状态\n\n中级软件设计师的学习及考试复习\n信息收集实验 - 数字化落实实验 in 微信阅读\n数学 + 英语具体执行计划\n微信推送多样化落实\n建立网站构思、打磨\n"},"Personal/Journal/2022/W41/2022-10-10":{"title":"2022-10-10","links":[],"tags":[],"content":"2022-10-10\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:49郑州 +9°C ☀️🌕\nDaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n最近疫情搞得人心惶惶的然后又接了几个流调电话我真是的会无语……\n今天学习任务完成 50%,主线任务没有完成。下午接到流调电话之后就没有一点点心情学习了,最近忙着小雅妹妹来郑州的事情,然后又是这疫情,也是心神晃晃的。\n放松放松保持心情提高抗压能力。最近就先住在公司了等疫情彻底平静了再跑着玩吧 ~\n下班啦下班啦回宿舍看会书收拾收拾睡觉了 ~"},"Personal/Journal/2022/W41/2022-10-11":{"title":"2022-10-11","links":[],"tags":[],"content":"2022-10-11\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 20:56郑州 +20°C ☀️🌕\nDaily\n\n谁家今夜扁舟子何处相思明月楼\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n昨天晚上没盖好被子然后早上就没睡好。疫情也更严重了需要连续好几天做核酸了……\n最近调整了一下时间打算一整个上午不进行主线任务转而将整个下午留给主线任务上午阅读完资讯后尝试一些新鲜的事情或者完成一些支线任务。具体为什么这样子调整是因为 14:00 开始工作,如果任务量比较大我可以一直工作到 21:00这样经过午休充足的精力可以提高学习效率。\n最近还是需要多看软考视频听老师讲考点争取一次过。下班去超市买了些好吃好喝的吃好喝好继续努力奋斗\n奥里给 ~"},"Personal/Journal/2022/W41/2022-10-12":{"title":"2022-10-12","links":[],"tags":[],"content":"2022-10-12\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 20:50郑州 +17°C ☀️🌖\nDaily\n\n昨夜闲潭梦落花可怜春半不还家。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天早上起来吃了牛肉、火腿、鸡蛋、牛奶啧啧啧 ~\n上午阅读咨询忙一些零散的事情下午就狂搞主线任务冲击软考如果这次软考还取消了未来一年内不再考虑报名了有更重要的事情要忙\n今天学的头蒙但是不知道为什么最近莫名其妙的休息不好可能也和情绪有关可能也需要运动了。但是我想一定是需要休息了 ~\n哦哦哦我的笔记输出还未搞定……真的是吐了先把思维导图搞上后续再说吧 ~\n下班啦下班啦一会回去运动一下然后刷刷题读读书睡觉"},"Personal/Journal/2022/W41/2022-10-13":{"title":"2022-10-13","links":[],"tags":[],"content":"2022-10-13\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 14:04郑州 +21°C ☀️🌖\nDaily\n\n兰有秀兮菊有芳怀佳人兮不能忘。\n— 秋风辞·刘彻(两汉)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周四的日志周五下午才写……\n周三周四丰富了伙食然后就感觉很不错我之前一直疑惑或者迷茫与为什么有时候身体会影响到我得情绪反之我倒是挺理解情绪会影响到身体。\n不过身体不会说话你也不能天天去做检查把……我越来越感觉每个人都要和身体做个好朋友虽然它不会说话但是它是从出生伴随你到死亡的人。虽然它不会说话但是它的要求也很低。\n每日按时吃饭适量运动规律作息补充水果和蛋白质我能感觉到它在说兄弟你很 man 哦。我也会做好自己不影响你情绪的,一起共赴 299 岁!!!\n昨天北京也发生了一件大事算是切身实际的第一次这么经历看了之后满身冷汗。这两天情绪总是会被外界因素影响但是自己已经能感受到了。\n我越来越清晰明了的感觉到内心的小建树虽然有时候还会被影响但是一颗小树苗成长为一片森林总是需要时间需要历练的。\n慢慢来 Take easy"},"Personal/Journal/2022/W41/2022-10-14":{"title":"2022-10-14","links":[],"tags":[],"content":"2022-10-14\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周六 17:03郑州 +22°C 🌫🌖\nDaily\n\n落日心犹壮秋风病欲疏。\n— 江汉·杜甫(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周五啦连着上了 7 天的班,然后周末又被封了,麻木了……\n没错周五的日志周六写最近状态很差导致么有心思学习……"},"Personal/Journal/2022/W41/2022-10-16":{"title":"2022-10-16","links":[],"tags":[],"content":"2022-10-16\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 19:54郑州 +20°C 🌫🌗\nDaily\n\n西风酒旗市细雨菊花天。\n— 秋怀·欧阳修(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n这个周末都在公司然后呢情绪不太稳定也有点上火。学习效率也低感觉干啥都是蒙蒙的封傻了……\n明天就是新的一周啦调整状态适应环境继续奥里给"},"Personal/Journal/2022/W41/2022-W41":{"title":"2022-W41","links":[],"tags":[],"content":"2022-W41\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 15:51郑州 +19°C ☀️🌗\nDaily\n\n桂花香雾冷梧叶西风影。\n— 菩萨蛮·何须急管吹云暝·高观国(宋代)\n\n\nProcess\n\n备考软件设计师\n\nProblem\n\n备考软件设计师\n\nNote\n最近两周因为国庆的过于放纵导致状态一直忽高忽低学习效率很差。\n最近的问题就是持续稳定的学习和输入较难自己主动就打破了而且这种打破的后续多久能恢复也是未知真是一鼓作气、再而衰、三而竭。\n保持一个持续稳定的学习输入输出尽量不要打破。\n加油加油我是最棒的\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价2.0状态差、效率低\nNextWeek\n\n备考软件设计师\n"},"Personal/Journal/2022/W42/2022-10-17":{"title":"2022-10-17","links":[],"tags":[],"content":"2022-10-17\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:22郑州 +13°C ☀️🌗\nDaily\n\n昨夜闲潭梦落花可怜春半不还家。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天没有看软考视频因为有点小感冒所以明天吧\nOver"},"Personal/Journal/2022/W42/2022-10-18":{"title":"2022-10-18","links":[],"tags":[],"content":"2022-10-18\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 20:32郑州 +12°C ☀️🌗\nDaily\n\n人闲桂花落夜静春山空。\n— 鸟鸣涧·王维(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n感冒了头疼明天赶紧活过来"},"Personal/Journal/2022/W42/2022-10-19":{"title":"2022-10-19","links":[],"tags":[],"content":"2022-10-19\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 10:13郑州 +13°C ☀️🌘\nDaily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n经过一晚上的恢复今天状态不错虽然周三的日志周四才写哈哈哈。\n今天状态不错周四周五加把劲继续努力\n冲啊奥里给"},"Personal/Journal/2022/W42/2022-10-21":{"title":"2022-10-21","links":[],"tags":[],"content":"2022-10-21\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 21:48郑州 +18°C ☀️🌘\nDaily\n\n西风酒旗市细雨菊花天。\n— 秋怀·欧阳修(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周四又忘记写啦每次周报更新以后手机端的 git 拉取就会有问题,尽快搞定!!!\n周四和周五的两天持续性的学习发现了如下问题\n\n只要临近 deadline 专注力就会加强!\n预期的时间实际的时间 = 11.5~2。\n还是容易被零散的事情或者关注点打破。\n工作时间8:00 - 18:00 的学习效率为预期的 1/2。\n每日高效工作时间 19:00 - 23:00\n早上资讯和日常处理时间可以在 10:30 前搞定!\n每日必做和刻意联系需要继续坚持\n\n具体的解决方案和应对思路明日再写啦还有就是这周的博客还没有输出嘞\n《内卷是个真问题还是假问题》《认知觉醒》等等这周周末还是要留两天的晚上来输出写作总结"},"Personal/Journal/2022/W42/2022-W42":{"title":"2022-W42","links":[],"tags":[],"content":"2022-W42\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 20:38郑州 +23°C 🌫🌘\nDaily\n\n兰有秀兮菊有芳怀佳人兮不能忘。\n— 秋风辞·刘彻(两汉)\n\n\nProcess\n备考软件设计师\nProblem\n备考软件设计师\nNote\n最近还是有很多的问题简单来说就是两点保持节奏减少影响。\n这次最大的原因还是减少影响郑州疫情了导致被迫改变了生活习惯所以就很容易焦躁烦躁感觉还是性格原因就是我比较喜欢自由可控的感觉而不是这种被迫接受总之就是还是容易被影响。\n吃不好喝不好休息也有点差然后呢看书也少学习效率还行。就是很浮躁感觉压力大还是间接性的上火。就是很浮躁\n还有一个最大的问题就是预期学习时间和实际学习时间出入较大未来的事情太不可控了。生活唯一确定的是生活是不确定的哎西吧不能太理想化当然能统一最好不过有困难。\n最近状态很差导致精力也不好可能需要运动但是我认为最核心的问题就是正反馈减少了……\n生活被打乱了正反馈减少了就导致这种落差有点倒退有点烦\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价4.0情绪不稳定,学习效率低\nNextWeek\n\n备考软件设计师\n"},"Personal/Journal/2022/W43/2022-10-24":{"title":"2022-10-24","links":[],"tags":[],"content":"2022-10-24\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:07郑州 +21°C ☀️🌑\nDaily\n\n江水流春去欲尽江潭落月复西斜。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\nKeep it @7wate\n今天状态不错慢慢来保持好自己的节奏"},"Personal/Journal/2022/W43/2022-10-26":{"title":"2022-10-26","links":[],"tags":[],"content":"2022-10-26\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 20:48郑州 +14°C ☀️🌑\nDaily\n\n江流宛转绕芳甸月照花林皆似霰。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天状态不错哦调整的还可以软考的题目刷的也越来越得心应手了keep it"},"Personal/Journal/2022/W43/2022-W43":{"title":"2022-W43","links":[],"tags":[],"content":"2022-W43\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:05郑州 +21°C 🌫🌓\nDaily\n\n人闲桂花落夜静春山空。\n— 鸟鸣涧·王维(唐代)\n\n\nNote\n每日复盘日记也践行了一个季度说快也快就是软考这个该死的事情他妈的又给取消了玩我呢。仔细复盘一下这三个月以来的得与失以及出现的问题和对应的解决方案。\n关于阅读\n三个月读了 7 本书,不算多更不算少。主要问题如下:\n\n阅读完一本书没有选择趁热打铁保持输入输出主要原因是因为懒惰和拖延同时还有一点就是追求阅读数量和速度。接下来的阅读要注重质量和输出不在规定要求一周读一本然后再输出了。既然手机都可以随时随地的输出那么就不要拘泥于形式了感悟来了就写下来\n没有办法坚持每日阅读节奏很重要。但是有时候一忘记就会好几天不读书所以养成阅读习惯很重要。目前主要阅读时间就是晚上收拾好躺床后夜读读着读着也就困了。想白天读书但是环境又有点差劲保持现状继续努力 ~\n\n关于学习\n\n学习这块最主要的问题就是主次不分很多时候容易被其他事情打乱不过这是上班时间哎也能理解。以后每天下午一来就开始处理主线任务不处理完绝对不干其他事情。下午2点直至晚上10点都是主线任务的时间。学会任务分级别主 / 支线 / 日常。掌握好精力和人任务重要层次就能很好的完成任务。\n还有就是预估时间因为总是会出现各种各样的问题和各种各样不可预测的时间所以预测一周完成的事情总是会多出那么几天。第一感觉自己不重视不上心其次就是不可预测的事情太多了。解决方案就是预留充足的时间1.2倍 ~ 1.5 倍为宜。\n\n关于习惯\n\n生活习惯很重要重要的事情三个感叹号。如果经常性吃辣的就会容易上火玩手机太晚就会没精神等等等这些真的很重要任务紧迫的时候尽量避免饮食作息不规律。\n还有就是保持节奏节奏节奏否则就会再一次的推倒重来不过好习惯也是没有那么容易就养成的当下做的很不错继续保持好节奏。\n\n关于感情\n\n目前没有太大的问题就是小雅加班很忙容易情绪不稳定。我作为男朋友平日的行动和支持做的非常好非常棒。我做的很优秀而且会一直优秀下去。\n\n最近这三个月做的很不错很棒。看见的摸得着的成长与进步期待继续进步加油加油加油\nNextWeek\n\n主线任务成人高考学习刷课考试11.10\n支线任务数学 + 英语学习规划st准备工作信息收集实现数字化\n其他任务个人简历微信群助手\n"},"Personal/Journal/2022/W44/2022-11-02":{"title":"2022-11-02","links":[],"tags":[],"content":"2022-11-02\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 19:33郑州 +16°C ☀️🌓\nDaily\n\n秋菊堪餐春兰可佩留待先生手自栽。\n— 沁园春·带湖新居将成·辛弃疾(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n郑州因为疫情封禁了一个月了很烦很烦很烦。特别容易烦躁每天日复一日的重复性工作我已经烦了只期待能顺顺利利解封吧。\n软考不出意外又很出意外的取消了这已经是第三次取消了放了我无数次鸽子了我已经吐了……。有时间再报名准备吧来日方长。\n最近的学习重心将是成人本科刷课考试准备学习英语好烦哦状态也是一好一坏。先搞成人本科搞完再说其他的。\n周二的时候更新了一下 Halo 的博客主题,优化了一部分。也遇见了一些问题就是使用 git 进行版本控制如何划定版本。简单思考了一下,大致如下。\n此方案主要解决的就是重复性的推送有时候推送到服务器又发现错了就很麻烦故暂时以此解决。如果从开发群体来区分主要为个人和组织。\n\n个人容易反反复复的修改和重复性提交建议以固定日期进行推送和提交日、周充分利用工作流和分支模型进行开发尽量避免重复性提交。热修复则随时随地发布其他的则固定日期推送提交。\n组织如果是团队协作模式则由大家约定俗成。如果是领导者模式则拉到本地以固定的日期进行推送和提交充分利用工作流和分支模型进行开发。热修复则随时随地的发布。\n\n此方案主要解决的是版本号的划定有时候刚推送上去就错了然后还要修复再推送就很容易徒增版本号。如果以结果为导向主要为路线图和需求。\n\n路线图开源社区英雄主义主要是以作品为方式呈现以产品节点为版本号每个大版本号都是根据路线图划定的故不存在太大问题。\n需求建议固定日期每周或每个月进行版本号的划定。如果以需求完成为版本号界定则容易出现版本号徒增。\n\n核心主要的思想坚决执行工作流和分支模型开发模式固定窗口进行推送和版本号划定可根据实际情况约定俗成。"},"Personal/Journal/2022/W44/2022-W44":{"title":"2022-W44","links":[],"tags":[],"content":"2022-W44\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 22:00郑州 +16°C ️🌕\nDaily\n\n洛阳亲友如相问一片冰心在玉壶。\n— 芙蓉楼送辛渐·王昌龄(唐代)\n\n\nNote\n日记断更了许久但还是很清晰自己当下可为不可为。还是适应不了封禁感觉焦虑的源泉还是经济压力。\n路漫漫其修远兮关关难过关关过。\n软考暂时告一段落了高效学习的方法论也俞来俞精进。目前针对个人的高效学习需要从以下方面入手\n\n番茄工作法\n任务分级\n思维导图\n费曼学习法\n\n务必坚持贯彻番茄工作法这样可以持续拥有较高的学习精力同时也不会太累。一个小时休息 5-15 分钟左右,然后再继续工作学习。\n任务分级是坚决执行每日只完成一项的主线任务不超过三项的支线任务以及日常任务。无论如何当日的主线任务必须完成支线任务最少完成一项持续保持正反馈。评估任务工时尽量是预估时间的 1.2-1.5 倍,拥有一定的容错能力能有效完成任务。\n思维导图法是在学习过程中尊重结果但是以过程为导向。精简提炼知识结构书写思维导图细读精写填充主干知识。重过程要结果不能一味的要求结点和里程碑。\n费曼学习法的前提是时间充足的前提下提供一种通俗易懂用自己的话的方式输出自己学习的知识。\n里程碑\n关于软考暂时取消关注明年不准备再考试了。\n服务器迁移后稳定使用一年停止折腾。\n成人高考刷课就12.15后一次性刷完。\n准备 dt 计划准备阶段\n工作生活\n目前工作很稳定将来 8 个月内不换工作。生活上需要把疫情纳入考量范围,坚决不能出现现在这种短缺生活物资的情况。足量准备 1-2 个月的生活物资和生活用品。\n家人平时多关心照顾没事电话联系一下一定要多照顾关心小雅生活情绪循序渐进过年的时候准备去拜访小雅父母。还有就是过年前准备买一下家里的家具。精简社交圈不需要无用的就不联系不社交酒肉朋友什么时候想有什么时候就有了。st 周六前制定一份完成度较高的实施计划争取15号之前开始实施。\n以下从早起运动阅读写作冥想这五方面说起。\n关于早起早起并不是单纯的早上起来很早而且找到自己的方向。最近坚持了很久的早起还是拥有一定效果的感悟更多了。\n运动的话量还是不够。你的腹肌腹肌腹肌哈哈哈每天保持30-60分钟的运动吧争取早日重现腹肌@周中平。\n阅读啊很喜欢阅读但是环境和时间这个影响真的很烦哦碎片化时间丰富但是阅读进入状态需要30分钟左右慢慢来每周保留一定量的阅读持续养成好习惯。\n写作最近把握的还不错找到适合自己的速度就可以完美的兼得阅读与写作了找到适合自己的频率。\n冥想是个伪命题没有怎么深入接触但是浅浅的感觉这个非常有用\n走到现在不容易开始一段新的路程更是艰难险阻。两句话送给自己吧。\n路漫漫其修远兮吾将上下而求索。\n穷则独善其身达则兼济天下。"},"Personal/Journal/2022/W45/2022-11-10":{"title":"2022-11-10","links":[],"tags":[],"content":"2022-11-10\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 21:03郑州 +14°C 🌫🌖\nDaily\n\n江流宛转绕芳甸月照花林皆似霰。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n啊西巴感觉要被封傻了。\n打游戏好菜不玩了不玩了今日玩游戏玩傻了走了走了回宿舍睡觉啦 ~"},"Personal/Journal/2022/W45/2022-11-11":{"title":"2022-11-11","links":[],"tags":[],"content":"2022-11-11\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 23:20郑州 +14°C ☀️🌖\nDaily\n\n斜月沉沉藏海雾碣石潇湘无限路。\n— 春江花月夜·张若虚(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天一整天情绪都不稳定疫情搞得人都要封傻了不废话了晚安晚安。"},"Personal/Journal/2022/W45/2022-11-12":{"title":"2022-11-12","links":[],"tags":[],"content":"2022-11-12\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周六 23:53郑州 +12°C ☀️🌖\nDaily\n\n好段东风好轮明月尽教封侯误。\n— 青玉案·丝丝香篆浓于雾·高鹗(清代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n周六了天气不好早上抓紧时间洗洗衣服收拾收拾中午吃完饭去办公室坐了坐。\n今天读完了《极简》类型的书籍整体来看一般但是部分闪光点还是值得细细品味的。今年年中的时候便是一直在尝试断舍离部分方面做的和好。\n但是由于对于极简和断舍离没有很充分的认知所以不够全面。例如每天这么粘手机每天被各种各样的信息流吸引注意力。\n其不止讨论了生活极简还有目标极简工作极简学习极简。认识极简贯彻断舍离到方方面面尝试做一名长期主义者。\n说完啦说完啦晚安晚安💤"},"Personal/Journal/2022/W45/2022-11-13":{"title":"2022-11-13","links":[],"tags":[],"content":"2022-11-13\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 00:28郑州 +7°C ☀️🌖\nDaily\n\n寒随一夜去春逐五更来。\n— 应诏赋得除夜·史青(唐代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天了解到一个新的论坛《虫部落》感觉又发现了新大陆还需要慢慢研究。简单了解了新的知识和新的规划在尝试在试错。\n今天晚上和小雅在一起讨论了前几天吵架的原因简单来说我管的有点多招人烦了。以后就佛系一些不再多管任何事了这样你开心我开心大家都开心。\n学会与孤独作伴、在黑夜里前行。星光不问赶路人@仲平"},"Personal/Journal/2022/W46/2022-11-18":{"title":"2022-11-18","links":[],"tags":[],"content":"2022-11-18\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 21:30郑州 +11°C 🌫🌗\nDaily\n\n雾失楼台月迷津渡。\n— 踏莎行·郴州旅舍·秦观(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n郑州的疫情算是没完没了心情也被各种各样的事情搞得心疲力竭。\n很烦真的很烦最近状态很差效率很低无所事事。\n希望这个周末可以调整过来最起码改善一些 ~"},"Personal/Journal/2022/W46/2022-11-20":{"title":"2022-11-20","links":[],"tags":[],"content":"2022-11-20\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 20:59郑州 +12°C 🌫🌘\nDaily\n\n空惹猿惊鹤怨误薜萝秋月。\n— 好事近·富贵本无心·胡铨(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天上午睡个回笼觉也是睡得混混噩噩的集体宿舍住着太难受了……\n中午吃过饭来办公室学习啦下午对 Python 的学习进度还不错,丰富和完善了学习笔记。\n还是要安排 ST 计划呀,学烦了可以小学这些但是 ST 计划才是最终的目的地@仲平"},"Personal/Journal/2022/W47/2022-11-21":{"title":"2022-11-21","links":[],"tags":[],"content":"2022-11-22\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 00:02郑州 +9°C 🌦🌘\nDaily\n\n新寒中酒敲窗雨残香细袅秋情绪。\n— 菩萨蛮·新寒中酒敲窗雨·纳兰性德(清代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天早上学习了温习了一下 python下午也是无所事事的乱忙。想着写写博客也是写的有点浮躁写了一会就不想写了。\n晚上回来洗洗衣服收拾收拾就看书啦发现了一本关于 python 的好书。最近还是有很多书需要慢慢来看呀。\n最近需要开始把每日任务上线恢复之前的工作学习生活节奏该睡啦该睡啦。\n晚安💤"},"Personal/Journal/2022/W47/2022-11-22":{"title":"2022-11-22","links":[],"tags":[],"content":"2022-11-22\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 23:39郑州 +8°C 🌫🌑\nDaily\n\n桂花香雾冷梧叶西风影。\n— 菩萨蛮·何须急管吹云暝·高观国(宋代)\n\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天依旧是在瞎忙嘞下午去了一趟仓库忙了一大下午。疫情封禁没玩没了状态是真的不好。\n疯狂看书看书看书有点瞌睡了睡啦睡啦。\n明天排班继续努力 😎"},"Personal/Journal/2022/W47/2022-W47":{"title":"2022-W47","links":[],"tags":[],"content":"2022-W47\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 11:06郑州 +6°C ☁️🌒\nDaily\n\n昨夜闲潭梦落花可怜春半不还家。\n— 春江花月夜·张若虚(唐代)\n\nNote\n算下来也是很久没有写周报了最近疫情导致的生活的不稳定以及习惯的转变都需要时间去适应不过感觉也已经习惯新的生活了。总的来说还是从以下五个方面来复盘总结。\n早起\n天冷了也容易懈怠了。目前存在的问题就是每日学习工作任务不清晰明确有时候就不知道要干嘛就会导致一整天都被琐碎的事情吸引导致最后无所事事。\n解决方案执行 主/支线 任务,每日早上必须划分今日 主/支线 任务。这是必须完成而且是一定要高质量完成的事情,持续保持正反馈!!\n运动\n最近天冷了再加上无所事事导致的效率低有时候就会下班了哎西吧怎么这么多事还没搞定导致直接压缩了运动的时间。\n必须要改善早起的问题然后再解决运动的问题。保持每周 3-5 次的运动频率,同时加上合理的饮食搭配快速练出好身材!\n阅读\n阅读倒是一直没有停止已经养成习惯了。唯一的问题就是阅读时间看到别人每周阅读 20+ 小时以上,觉得很难以置信;后来经过实际尝试,发现也并不是不可能。\n不要为了阅读而阅读阅读完一本书总会有心得体会。保持好阅读输出的节奏持续正反馈\n冥想\n这个话题还未深入学习和研究暂时不展开\n写作\n唉我的写作总是会有很大的问题一时想写的非常多有时候半个月就写不出来一个字。没有稳定的产出效率。总是会拖更然后导致文章难产。\n解决方案保持 wiki 的持续输出,然后手里多存几篇稿子。这样博客可以持续稳定的输出,同时 wiki 也能记录一些乱七八糟的文字。暂时认为这是比较好的解决方案。\n极简\n结合最近阅读的一本书虽然评价不高但是觉得很有必要为这五点再加上一点就是极简。期待践行后的体验总结\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价1.0keep it"},"Personal/Journal/2022/W48/2022-11-28":{"title":"2022-11-28","links":[],"tags":[],"content":"2022-11-29\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 08:33郑州 +5°C ☁️🌓\nDaily\n\n携壶酌流霞搴菊泛寒荣。\n— 九日·李白(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天做的很不错虽然现在才写主要是因为昨天晚上稀里糊涂才睡着哈哈哈。昨天早上把托更了很久的数字文具盒更了两章月度总结Python 模块和包等等擦屁股任务都完成啦!\n很不错很不错无所谓解封不解封了。已经习惯并且适应了Come on"},"Personal/Journal/2022/W48/2022-11-29":{"title":"2022-11-29","links":[],"tags":[],"content":"2022-11-29\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 20:36郑州 +0°C ☀️🌓\nDaily\n\n紫塞门孤金河月冷恨谁诉\n— 长亭怨慢·雁·朱彝尊(清代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天本来是打算完成擦屁股的事情但是偶发性的事又中断了。\n早上把数字文具盒又输出了一章明天继续。下午做了一件相对来说有价值的事晚上又打了会游戏。\n看会书睡觉啦晚安晚安"},"Personal/Journal/2022/W48/2022-12-01":{"title":"2022-12-01","links":[],"tags":[],"content":"2022-12-01\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 20:37郑州 +0°C ☀️🌓\nDaily\n\n乌鹊倦栖鱼龙惊起星斗挂垂杨。\n— 一丛花·溪堂玩月作·陈亮(宋代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n最近都在擦屁股收拾以前没有完成的事情。不过有一点心得很真实封闭自己的信息来源就会让自己不那么焦虑也终于理解了一部分人为什么喜欢闭关和冥想了。\n主动关闭自己的五感总会在其他地方收获你所得不到的东西就宛如盲人失去了眼睛那么就会更加专注于耳朵和感知力。学会丢下包袱轻装上路\n这周一直在持续产出第一次感觉自己还是有这份能力的。不能说是实力把我认为是肚子有墨水了。而且终于能摸索到合适的方法去阅读学习了总结下来一个词就是张弛有度。\n例如我之前一直在看成长类的书籍然后就会有很多的感悟但是贪多嚼不烂看得多就想收获的多就宛如种地一样。其实中间掺杂一些科普类的书籍地理类的书籍就是纯看看也挺好的。这样留足了时间去充分的思考也没有浪费阅读的时间同时还能保持阅读的劲头。果然只有不断的反复尝试、实践、总结才可以获得收获。\n还有一个问题就是本末倒置的学习问题还是要尝试学习基础学科。痴迷于学习花里胡哨的 IDE哦哦哦。总归是摆对位置知道想要啥而不要猴子下山的行为。看见啥就拿啥看见啥就想要啥。切勿本末倒置切勿忘记自己的方向。\n这周的产出和收获已经保底了调整状态\n正式出发"},"Personal/Journal/2022/W48/2022-12-04":{"title":"2022-12-04","links":[],"tags":[],"content":"2022-12-04\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 20:19郑州 -27°C ☀️🌔\nDaily\n\n漫留得尊前淡月西风。\n— 满庭芳·南苑吹花·晏几道(宋代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n终于的终于我算是把所有的屁股擦干净了。而且目前没有拖延太多的事情剩下一丢丢的小事情。\n这周正式步入 12 月份,疫情的好转也终于有了眉头。所有的一切再变得简单起来,目前正式开启 ST 计划。\n冲啊"},"Personal/Journal/2022/W49/2022-12-06":{"title":"2022-12-06","links":[],"tags":[],"content":"2022-12-06\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 23:53郑州 +2°C 🌫🌕\nDaily\n\n乡书何处达归雁洛阳边。\n— 次北固山下·王湾(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n今天研究了一下英语学习的方法论心里也大概有个底。主要核心思想就是注重大量输入、思考、大量输出。\n公司的会议精神也很让人气氛想走走想留留没有人拦着你我不得不说确实厉害👍🏻。搞得我都有些情绪化了真的挺厉害的。\n不忘初心寒夜里砥砺前行星光不问赶路人你我自有归期。"},"Personal/Journal/2022/W49/2022-W49":{"title":"2022-W49","links":[],"tags":[],"content":"2022-W49\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:26郑州 +5°C ☀️🌖\nDaily\n\n已喜佳辰更怜清夜。\n— 踏莎行·秋入云山·张抡(宋代)\n\nNote\n现在的第 50 周2022 年已经马上要过去啦,主要谈论一下最近的问题和收获吧,主要从 8 个方面说起,总结复盘一下。\n工作\n首先是工作方面的最近对工作的态度确实很不爽赤裸裸的压榨和职场文化但是最恶心的倒不是这大家明明可以争取一些东西却一个个的敢怒不敢言。所有人就如同绵羊一样那种感觉就是清末的中国国民也许似乎真的骨子里带着的吧。\n这种情况真的让我很不爽我有一点点冲动想 change但是可能有点情绪化再加上我实在是没有能力解决好这种事情。无奈吧收起自己的怜悯心随它去吧。管好自己圆滑一些的去面对所有的事情与我无关。\n最主要的就是这个环境它会影响你然后呢容易被带进来。我觉得还是要主动的找到事情干两耳不闻窗外事。总之针对于工作环境这个问题的处理方法就是事不关己高高挂起\n生活\n生活最明显的就是质量下降而且质量下降的特别明显这点真的让我很烦可是苦于当下这个环境又没有任何的办法。疫情已经封禁了第三个月了头发长的也是没有一点办法总之就是很烦\n目前针对于工作和生活的苦恼考虑在公司短租房子但是又需要时间去折腾目前暂时也放不开。啊啊啊我只想要稳定的生活这样子搞的人都好烦呀\n早起\n苦恼于开始又不知道如何开始善用每日计划把一定要把每日计划做好保持好每日的节奏只有这样才能持续性的正反馈\n运动\n天一冷真的是不想运动呀顺其自然吧。现在疫情当下谁也不想贸然的发烧感冒。\n阅读\n最近阅读倒是找到最优解之前一直苦于写作输出效率过低现在终于找到了最适合我的方法。简单来说就是阅读完感悟类书籍就阅读技术类书籍这样换换脑子同时技术也在进步。感悟类书籍经过时间的发酵和酝酿更能收获心得体会。\n写作\n上周应该就是前阵子的写作持续性的技术输出感觉写伤了哈哈哈。但是呢感觉自己的写作水平已经有了明显的进步需要持续性保持 ~\n争取成为一名作家。\n冥想\n还未开始一直都未开始\n总结\n主观认为环境的因素、生活的改变导致这两个月真的是各种问题一下子爆发出来了。\n\n\n稳定的生活\n\n\n稳定的环境\n这两点真的是太重要了坏消息是现在我一个都没有或者说是一个都不适应。好消息是我已经充分的意识到这个问题了所以我要尝试去改变。同时又为以后面对这种生活的不确定性有更好的解决办法\n\n\n营造相对稳定的生活\n\n\n减少环境对我的影响\n\n"},"Personal/Journal/2022/W50/2022-12-12":{"title":"2022-12-12","links":[],"tags":[],"content":"2022-12-12\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:24郑州 +5°C ☀️🌖\nDaily\n\n梧桐树三更雨不道离情正苦。\n— 更漏子·玉炉香·温庭筠(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n很久没有写周报总结了最近又暴露出很多特别重要的问题。一句话来说就是被环境影响过大造成情绪的失控。\n今天周一碌碌无为的一天然后同事好像也是确诊了。总感觉很烦哦"},"Personal/Journal/2023/W10/2023-W10":{"title":"2023-W10","links":[],"tags":[],"content":"2023-W10\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 17:15郑州 +24°C ☀️🌗\nDaily\n\n暖雨晴风初破冻柳眼梅腮已觉春心动。\n— 蝶恋花·暖雨晴风初破冻·李清照(宋代)\n\nProcess\n\n专题一中小企业数字化基础建设——已完成\n专题二中小企业数字化标准建设——已完成\n专题三Linux 基础加强、进阶及冲击大师——待开始\n\nProblem\n\n没有引路人导致做了很多尝试却已经有人做了而且做得更好。\n\n一定不能闭门造车多利用搜索引擎咨询前辈阅读书籍结合 chatgpt 讨论规划。进一步更应该检索相关论文,杂志等专业知识文章,同时结合实际情况反思。\n阅读前辈的论文、文章一定要以辩证的眼光去看待秉承着先僵化、后优化、再固化的原则。硬套实际情况进去思考其中的所以然并且提取共同点论证。\n规划或者设计书写好了以后一定要发出去多征求意见并论证是否符合需求。\n\n资源利用率较低前期存在纸上谈兵……\n\n买了这个服务器怎么说呢……闲置率比较高想办法利用起来不能浪费\n\n生活稳定性不够持续产出忽高忽低。\n\n没有办法特别是有些不以人的意志为转移的事情只能尽力增加个人的韧性降低心态并拥抱任何变化。\n\n目前没有形成实际的产出\n\n不会写论文也没有尝试写过总之就是这是一项很重要的课题。必须要学会写论文做科研\nNote\n前两个专题的缺点如上所述生活中的琐事也是一大堆。尽力就好切勿贪杯。\n新的一周冲击 linux 专题,准备好纸质书籍,规划好详细的大纲,一步一个脚印冲冲冲!\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价5.0继续努力\nNextWeek\n\n专题三Linux 基础加强、进阶及冲击大师\n"},"Personal/Journal/2023/W12/2023-03-20":{"title":"2023-03-20","links":[],"tags":[],"content":"2023-03-20\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 10:30郑州 +13°C 🌫🌑\nDaily\n\n庭院深深深几许云窗雾阁春迟。\n— 临江仙·梅·李清照(宋代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日字帖 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n日报丢了好久生活琐事太多整个人状态很差。\n日报还是不能丢的生活琐事这些需要增加个人的生活人性状态很差还是一累就啥都不想动然后进入一个恶性循环。\n\n日报不能丢\n增加生活韧性\n恢复规律生活\n\n冲冲冲 "},"Personal/Journal/2023/W12/2023-03-21":{"title":"2023-03-21","links":[],"tags":[],"content":"2023-03-21\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 12:21郑州 +14°C 🌫🌑\nDaily\n\n记年时、偷掷春心花间隔雾遥相见。\n— 薄幸·青楼春晚·吕渭老(宋代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日字帖 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n头疼难受身体不舒服……\n草"},"Personal/Journal/2023/W12/2023-W12":{"title":"2023-W12","links":[],"tags":[],"content":"2023-W12\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 16:41郑州 +22°C ☀️🌓\nDaily\n\n沾衣欲湿杏花雨吹面不寒杨柳风。\n— 绝句·古木阴中系短篷·志南(宋代)\n\nProcess\n\n专题三Linux 基础加强、进阶及冲击大师——进行中\n\nProblem\n暂时没有什么问题就是上周病毒性感冒然后导致白白浪费了一周的时间……\n目前还在考虑自考 RHCE 还是报名相关培训班考试。\nNote\n保持身体、情绪的持续稳定是非常重要的\nThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\n分数评价6.0加油冲冲冲\nNextWeek\n\n专题三Linux 基础加强、进阶及冲击大师——进行中\n"},"Personal/Journal/2023/W14/2023-04-08":{"title":"2023-04-08","links":[],"tags":[],"content":"2023-04-08\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周六 21:11郑州 +20°C ☀️🌖\n📖 Daily\n\n沾衣欲湿杏花雨吹面不寒杨柳风。\n— 绝句·古木阴中系短篷·志南(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天早上考试去了JumpServerV3 的课程结业考试,考的非常不错哦 ~\n中午去找老朋友了聊聊天又一起去湖边喝茶许久未见感觉还是非常不错的\n下午本来计划着明天进行公车挑战嘞结果临时通知爷爷要出院然后小雅晚上还要吃饭奥里给……\n看看新闻读读书锻炼一下就睡了明天要早起\n冲冲冲 ~"},"Personal/Journal/2023/W14/2023-W14":{"title":"2023-W14","links":[],"tags":[],"content":"2023-W14\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 10:16郑州 +16°C ☀️🌖\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records健康饮食5Exercise log日常锻炼3Sleep log完美睡眠2\n🚀 Process\n\nLinux 系统学习:进行中,进度 30%。\n读书笔记&博客:进行中,进度 1%。\n\n🚧 Problem\n\n生活琐事爷爷住院我要忙前忙后\n\n解决方案不再参与此事。\n\n\n写作需要安排学习系统化写作。\n\n解决方案Python 学完后安排此事或者穿插进去。\n\n\n情绪容易因为外部原因影响情绪理性处理理性看待。\n\n解决方案无解毕竟是人。学会寻找合适的方式发泄。\n\n\n\n📝 Note\n一直在忙于学习 Linux 和 JumpServerLinux 因为身体原因和生活琐事导致进度较为缓慢JumpServer 掌握较快这周就顺利拿证了。\n生活琐事真的挺烦的打算问问 chatgpt 如何理性解决此事。\n新的一周继续冲冲冲务必要多运动哦 ~\n📊 ThisWeek\n\nLinux 学习专题进阶\n读书笔记&博客写作\nmonica 继续完善\n| Score | Evaluation |\n| ----- | ---------- |\n| B | 整理行装,继续上路 |\n\n🎯 NextWeek\n\nLinux 学习专题:进行中,预计进度 70% 左右。\n读书笔记&博客写作:进行中,预计进度 100%。\nmonica 继续完善:进行中,预计进度 30%。\n"},"Personal/Journal/2023/W16/2023-04-21":{"title":"2023-04-21","links":[],"tags":[],"content":"2023-04-21\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周五 17:09郑州 +12°C ☀️🌑\n📖 Daily\n\n春风桃李花开日秋雨梧桐叶落时。\n— 长恨歌·白居易(唐代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n上周五去爬黄山了周二正式上班恢复了两天周四晚上开会忍不了直接开怼。目前各项工作学习任务进度不及预期压力稍微有点大。生活琐事也有点多很多事情都需要亲历亲为。\n目前的季度总结还没有写Linux 的学习效率太低,啊好多东西都需要复盘。\n明天就和小雅热恋一周年了说快也快细水长流 ~"},"Personal/Journal/2023/W16/2023-04-23":{"title":"2023-04-23","links":[],"tags":[],"content":"2023-04-24\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 10:02郑州 +8°C 🌫🌒\n📖 Daily\n\n记年时、偷掷春心花间隔雾遥相见。\n— 薄幸·青楼春晚·吕渭老(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n上周五开会针对部门的情况和问题做了一个反馈周日也把项目计划书输出了一下感觉阻力会很大不过无所谓 ~\n生活琐事真的好烦人啊乱七八糟的事真的心累不管了无所谓了爱咋咋吧\n多看书注意情绪波动持续性的学习这周好好的把博客写了 ~"},"Personal/Journal/2023/W2/2023-W2":{"title":"2023-W2","links":[],"tags":[],"content":"2023-W2\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 19:58郑州 -1°C ☀️🌗\nDaily\n\n千点寒梅晓角中一番春信画楼东。\n— 鹧鸪天·元宵后独酌·杨慎(明代)\n\nNote\n算起来好久没有写日志了总的来说也是过的浑浑噩噩的因为疫情的管控放开所以不出意外的阳了。各种各样的发烧和后遗症以及生活的不稳定导致各式各样的工作生活开展不利。客观原因确确实实存在但是主观原因也是一方面。心乱了……\n工作方面不出意外的还是那个老样子总的来说还是考虑跳槽然后谋求更高更大的平台继续前进。但是综合各方面的情况明年六七月份会进行集中的面试寻求更好的工作。主要担心的原因还是疫情马上也临近过年同时需要一定的时间去准备。如果今年不能顺利跳槽的话下半年的方向就是考证书增加筹码明年一定跳\n学习方面主要原因是客观因素掺杂主观因素心有点乱同时节奏也乱了。静心然后尝试恢复节奏是最重要的还有就是重新捡起日志和每日任务。这个习惯是真的没有养成还是处在反反复复的阶段。\n早起、阅读、写作、冥想、运动这五方面总的来说已经养成良好的习惯了同时也打下了不错的基础。0 - 1 的阶段已经跨过了,今年一定是一个增量的过程,一句话来说就是要拿出成绩,拿出数字!阅读和写作刚刚摸到门槛子,期待更一步精进。再给予一些时间去缓冲,实践。\n最最最重要的问题就是稳定的生活、稳定的感情、稳定的情绪稳定的节奏稳定的收入。今年一定要稳中有进紧紧握住已经有的积极追求可以拿到的。保持好节奏持续正反馈。\n加油共勉本命年"},"Personal/Journal/2023/W22/2023-05-31":{"title":"2023-05-31","links":[],"tags":[],"content":"2023-06-01\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 09:28郑州 +26°C ☀️🌔\n📖 Daily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n早上起来继续刷路飞学城的 Linux 视频教程汲取行业大佬的经验值。\n下午对五月份的创新项目做了个总结汇报并且连同其他部门同事一起开了个会宣导一下。\n晚上回家运动了运动然后继续看书。我感觉看到了一本好书就很容易无法自拔内心也不知道为什么一直蠢蠢欲动的想买一台新电脑 ~\n还有就是我需要好好的详细规划一下运动饮食健康计划 ~\n努力搬砖挣钱买电脑买相机哈哈哈"},"Personal/Journal/2023/W22/2023-06-01":{"title":"2023-06-01","links":[],"tags":[],"content":"2023-06-01\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 22:05郑州 +23°C ☀️🌔\n📖 Daily\n\n月明船笛参差起风定池莲自在香。\n— 纳凉·秦观(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天上午没有干什么事情然后呢下午学了一会儿学累了就不想学了。总之感觉今天一整天都在摸鱼工作效率也不高也没有学到太多的东西。\n不过昨天晚上有一个网友加我微信向我请教关于知识库的问题。而且今天有个同事问问题也感觉很烦躁。就是有一个通病我发现很多人是不会沟通的。\n今天一直看的那个Linux相关的视频感觉知识体系相对完整但更多的是听的行业经验。\n今天晚上下班儿和宝贝儿一起去吃了螺蛳粉。镇上新开了一家阿生哥螺蛳粉感觉非常的哇塞。吃完饭碰见个沙雕把车停在通道上真他娘的傻逼。\n好了我要看看书睡觉了奥利给冲冲冲。"},"Personal/Journal/2023/W22/2023-W22":{"title":"2023-W22","links":[],"tags":[],"content":"2023-W23\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 12:14郑州 +19°C 🌫🌕\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records还在调整吃的有点乱。3-5Exercise log打了球做了无氧器械冲冲冲3Sleep log周末睡得时间一长就贼难受……5\n🚀 Process\n\n\nLinux 专题:进行中,进度 50%。\n\nLinux 专题目前主要是刷视频汲取经验,动手实践操作。第 22 周将是里程碑的一周,进阶内容基本完成。\n\n\n\nOBCA 考试:未开始,进度 0%6.106.11考试\n\n凑活动领取了考试券一定要先考过 OBCA。\n\n\n\n博客未开始进度 0 %\n\n进行中攒了很多博客还是需要补坑。\n\n\n\n🚧 Problem\n\n\n效率不稳定有时候一被打断效率就很容易被终止。主要就是上班等时候一被打断就完蛋了。\n\n解决方案充分利用番茄工作法偷时间提高效率学习\n\n\n\n生活琐事没有出去玩然后周末朋友满月酒晚上又聚餐了怎么说呢感觉很差。\n\n解决方案远离一切负能量的人和场合。\n\n\n\n日志复盘总是中断日志中断复盘还是必须要持续性的记录\n\n解决方案手机语音转文字提升日志便捷性。\n\n\n\n📝 Note\n早起呢总是感觉怪怪的早上总是起不来哈哈感觉小爱同学的起床铃声太魔性了还好调整了一下\n周一到周五一直处于心流状态高效学习周六周日处理了一些生活琐事就没有怎么学习。不过有一说一定期大扫除收拾家里卫生断舍离丢弃东西真的是很不错的\n阅读方面这周一直在读结构化思维一本好书真的是和作者撞在一起了。后续会进行深度的总结复盘输出阅读笔记。\n写作的话感觉一直在拖延哈哈哈。我挺喜欢说的下次会尝试说一篇博客。写字的话更喜欢写一些 wiki 知识库。\n运动这周倒是运动了几次写周报的时候浑身上下还疼着呢。这周继续保持冥想感觉情绪稳定加强专注力高效的休息时时刻刻都会处于一种动态冥想的境界。\n总的来说最重要的事情就是保持每日复盘这周呢主要就是继续忙 Linux 学习的事情,同时准备一下 OBCA 的考试。\n还有就是准备端午节去洛阳需要准备的东西\n\n药箱\n音响\n振兴计划\n\n新的一周继续冲冲冲 ~\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation4.5尽快恢复,冲冲冲~\n🎯 NextWeek\n\nLinux 学习:进行中,进度 70%。\nOBCA 考试:拿证。\n博客托更的完成 70%,五月的复盘 和 Linux 专题阅读的读书笔记。\n"},"Personal/Journal/2023/W23/2023-06-05":{"title":"2023-06-05","links":[],"tags":[],"content":"2023-06-05\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 12:14郑州 +19°C 🌫🌕\n📖 Daily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天上午月初公司晨会回来忙着收尾计划开始新的一周不知不觉就下班了。\n下午也是忙了一会工作然后才开始学习感觉没有学多少博客也在难产中哈哈。\n今天晚上刚好我值班然后就准备把博客收尾。计划已经设立好最主要的就是执行了\n还有就是不能乱写 shell 了,码字的感觉真爽真痛苦 ~\n一码字就不想学习哈哈哈赶快抓紧把 linux 收尾,然后 python + database \n晚上下班回家简单运动运动读读书然后继续开心每一天 ~"},"Personal/Journal/2023/W23/2023-06-08":{"title":"2023-06-08","links":[],"tags":[],"content":"2023-06-08\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 22:18郑州 +27°C ☀️🌖\n📖 Daily\n\n小荷才露尖尖角早有蜻蜓立上头。\n— 小池·杨万里(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天终于及时止损音响本来是打算这周搞定结果遇见了沙雕我是真的佩服了……\nLinux 学习这周算是停滞了OBCA 的考试这周要搞定,下周还要刷课,马上就是 24 岁生日啦,很开心有你真好。\n头疼😣感觉有点劳累过度好好休息休息明天继续努力"},"Personal/Journal/2023/W23/2023-W23":{"title":"2023-W23","links":[],"tags":[],"content":"2023-W24\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 17:38郑州 +30°C ☀️🌗\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records吃的很不错今天需要逛逛超市买东东哈哈.7Exercise log这周没有运动还是很懒哈哈2Sleep log睡得还行晚上总是熬夜看书不太好3\n🚀 Process\n\nLinux 专题:进行中,进度 50%。\n\n这周没刷多少这个月月底前必须完成\n\n\nOBCA 考试:未开始,进度 90%6.106.11考试\n\n刷题正确率 93%,等待考试\n\n\n博客未开始进度 10 %\n\n补坑……\n\n\n\n🚧 Problem\n\n效率不稳定有时候一被打断效率就很容易被终止。主要就是上班等时候一被打断就完蛋了。\n任务不明确没有量化任务规划时间单位导致一再拖延拖延……\n\n解决方案充分利用番茄工作法偷时间提高效率学习严格锻炼规定时间内完成指定任务\n\n\n烦人琐事垃圾音响产品浪费我一周的时间……又被莫名其妙的惹生气反正总是乱七八的事情。\n\n解决方案增加韧性远离一切负能量的人和场合。\n\n\n日志复盘上一周日志复盘还行完全 ok 的。\n\n解决方案继续保持加油\n\n\n\n📝 Note\n感觉最近状态一直很差总是各种乱七八糟的事情没有一个持续的正反馈导致越来越堕落……\n早起饮食运动都还ok慢慢在调整恢复。阅读也是养成了好习惯就是写作感觉磨磨唧唧的拖延症。写作最主要的原因就是不太喜欢打字的形式因为很慢效率很差所以不容易形成稳定的正反馈\n复盘还是很重要的这周末也是太放荡了哈哈坚持复盘养成习惯还有就是拖延拖延拖延真的令人很烦哦。\n感觉拖延最重要的印象因素就是没有尝试量化任务量化时间导致无法把握进度然后就一拖二二拖三……\n新的一周尝试量化任务时间提高效率减少拖延\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation5.0保持住!!!\n🎯 NextWeek\n\nLinux 学习:进行中,进度 70%本周争取85%\nOBCA 考试:刷题拿证。\n博客托更的完成 100%。\n成考刷题准备考试\n音响二开项目\n"},"Personal/Journal/2023/W24/2023-06-12":{"title":"2023-06-12","links":[],"tags":[],"content":"2023-06-12\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 23:24郑州 +25°C ☀️🌗\n📖 Daily\n\n小荷才露尖尖角早有蜻蜓立上头。\n— 小池·杨万里(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天伴随着上周日的拖延症状开始了新的一周。拖延症终究是我的一大问题生活琐事更是令我头疼……\n上周因为音响周末偷懒睡觉导致整个计划安排都没有如实完成不过还好周报总结出来原因就是量化任务完成时间。\n毕竟没有压力哪里来的动力\n上午针对艳阳牧业的音响进行了调试技术选型稳定性测试等。整体来说比较顺利期待周四五和周末的测试运行。\n下午也是想起来啥搞了点毕竟没办法还是要工作的。临下班完成了第23周的周报晚上更是完成了拖延已久的博客。\n总的来说循序渐进的节奏感持续不断的正反馈才是王道。不过每日规划任务主线任务支线任务日常任务定时定量的完成尤为重要\n明天周二调整一下继续出发"},"Personal/Journal/2023/W24/2023-06-13":{"title":"2023-06-13","links":[],"tags":[],"content":"2023-06-13\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 23:11郑州 +27°C ☀️🌘\n📖 Daily\n\n有三秋桂子十里荷花。\n— 望海潮·东南形胜·柳永(宋代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天状态很棒早早地起来吃早饭了OBCA 说考就考一次通过。\n今天相较于之前计划充足实施完美。上午主要进行了 Linux 的继续学习,下午则先进行了 OBCA 的复习与考试,然后继续学习 Linux。晚上回家给小雅买了计划已久的保险拖了拖地收拾衣服可惜就是没有运动一下。\n明天周三继续冲击 Linux 学习,上午刷视频,下午完成 Linux 学习笔记。周四暂定 linux 学习和 音响项目 的开发。周五同样,但是要把 音响项目 上线,周六日进行测试运行。周六体检,然后收拾家里,办公打印照片。周日的话就顺其自然,公车挑战或者另有安排。\n早起还是特别重要的节奏感和持续的正反馈更为重要冲冲冲四驱战士在行动"},"Personal/Journal/2023/W24/2023-06-15":{"title":"2023-06-15","links":[],"tags":[],"content":"2023-06-15\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 23:33郑州 +29°C ☀️🌘\n📖 Daily\n\n乡书何处达归雁洛阳边。\n— 次北固山下·王湾(唐代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n我经过两天的严格执行计划即将于明天完成 Linux 中阶的学习计划和 音响开发的计划。\n虽然也是遇见了很多乱七八糟的事但是状态很不错效率也不低目前有两个问题\n\n博客博文读书笔记的继续输出计划周末进行。\n信息茧房的打破rss订阅过期了很久然后rsshub靠社区更新的很慢……\n运动习惯的养成生活笔记的调整\n\n这周的状态调整的很不错这样看来上半年乱七八糟的琐事还是很锻炼韧性的保持节奏感继续加油"},"Personal/Journal/2023/W24/2023-W24":{"title":"2023-W24","links":[],"tags":[],"content":"2023-W24\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 00:43郑州 +22°C 🌦🌑\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records吃的不错状态也很好。4Exercise log没有运动各种乱七八糟的事再加上每天学习完精力很差0Sleep log调整了作息时间不太适应需要中午补觉不得不说睡眠质量还是很高的5\n🚀 Process\n\nLinux 专题学习:进行中,进度 75%。视频算是看的七七八八,基本上看完了。下周就需要看书和总结笔记实践了。\nOBCA考试已完成进度100%。解决拖延完成的就是嘎嘎快。已经约考了 OBCP计划9月份前考完。\n音响音响项目进展的特别顺利上个音响的及时止损尤为重要。事态发展不好及时止损当断则断\n博客未完成还是写作的问题。\n\n🚧 Problem\n\n博客写作思路出了问题不能为了写作而写作不能太注重一些虚无的事。解决方案希望这周的专题阅读能带来一些改变目前还不知道如何做。\n音响项目需要进一步完善细节二次调试等等。\n继续教育这周三天的主要事情就是刷课备考争取高分通过倒数第二学期的课程\n\n📝 Note\n调整状态的一周值得肯定的是状态相较于之前恢复的很快几乎无感。主要原因分为两方面\n\n饮食作息情绪健康高效稳定促使精力旺盛充沛。\n主观能动性很强说干就干干完再说。\n\n由此可见健康良好的生活状态极其重要身体始终是革命的本钱积极主动的心态更是不可或缺的一环一切只管努力剩下的交给天意。\n这周最大的问题就是和小雅发生了很多事情。说来话长更是一言难尽同时深深地感觉自己变化也很大有点精致利己。但是有些事对我来说感觉到很痛苦了似乎是教育的遗留导致这样的而且又离奇的复现了抑郁症时候的症状表现。\n未来几天保持好自己的情绪多吃甜的多运动减少焦虑多和朋友联系开开心心迎接自己的二十四岁生日。\n周你可以的一直都很可以继续加油不忘初心方得始终。\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation6不错及格了\n🎯 NextWeek\n\n成人教育未开始三天进度100%。\n音响项目完善细节部署项目。\n药箱购买补充家庭小药箱看看老爸那里缺啥准备过生日。\n"},"Personal/Journal/2023/W25/2023-W25":{"title":"2023-W25","links":[],"tags":[],"content":"2023-W25\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 23:22郑州 +24°C ☀️🌓\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records饮食管理较乱2Exercise log锻炼也没有0Sleep log睡眠不错5\n🚀 Process\n\n本科刷课已完成。\nLinux学习进行中70%。\n博客写作进行中0%\n音响项目进行中50%\n\n🚧 Problem\n\n生活琐事生活琐事导致情绪\n\n解决方案远离糟人烂事保持顿感。\n\n\n生活管理良好的生活习惯依旧需要养成。\n\n解决方案不断的尝试锻炼继续加油\n\n\n\n📝 Note\n端午放假同时也是24岁生日2023 年上半年也是即将画上一个句号。\n23年上半年整体来说预期内不可控的生活琐事较多情绪波动相对较大精力不足导致学习效率忽高忽低。学习效率1/3生活琐事1/3生活管理1/3。\n很多事情会计划在季报里写一下目前来说成长迅速继续前行\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation6及格继续加油\n🎯 NextWeek\n\nLinux 学习:进行中,进度 100%。\n博客写作10万字计划。\n音响项目完善使用。\n"},"Personal/Journal/2023/W26/2023-06-26":{"title":"2023-06-26","links":[],"tags":[],"content":"2023-06-26\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 23:14郑州 +30°C ☀️🌓\n📖 Daily\n\n榆柳萧疏楼阁闲月明直见嵩山雪。\n— 洛桥晚望·孟郊(唐代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天没有按计划行事主要还是擦屁股把之前遗留的问题搞定。自从 ChatGPT 出世,以前需要 2 周才可以搞定的微论文,现在只需要 2 个小时了。效率直接提升 40 倍……\n明天将进行收尾工作然后继续刷 Linux 的相关课程。同时进行一下 音响项目的完善重构工作。\n对了还有一点小事情就是订阅计算机相关文献。好了我要去读书啦晚安晚安"},"Personal/Journal/2023/W3/2023-01-16":{"title":"2023-01-16","links":[],"tags":[],"content":"2023-01-16\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 08:33郑州 -1°C ☀️🌘\nDaily\n\n牛困人饥日已高市南门外泥中歇。\n— 卖炭翁·白居易(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n新的周一把遗留的坑都给填填暂时不开新坑了。\n下班一起吃了火锅算是年夜饭啦。马上就要开始过年了但是感觉过年的气氛并不是那么的浓厚。\n工作工作 ~"},"Personal/Journal/2023/W3/2023-01-18":{"title":"2023-01-18","links":[],"tags":[],"content":"2023-01-18\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 09:29郑州 +2°C ☀️🌘\nDaily\n\n晨起开门雪满山雪晴云淡日光寒。\n— 山中雪后·郑燮(清代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n临近过年就无心忙碌了顺其自然 ~\n送走小雅回老家然后昨天晚上部门聚餐。总是感觉过的好快好快 ~\n这两天主要忙的事情就是 Python 的虚拟环境,不对应该是 Python 的项目实践,考虑过年期间手撸一个简单的小项目。\n今天上班的最后一天需要规划准备一下带去洛阳的东东。然后也没啥事了放松享受一下过大年 ~\n新年快乐 ~"},"Personal/Journal/2023/W31/2023-W31":{"title":"2023-W31","links":[],"tags":[],"content":"2023-W31\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 22:07郑州 +28°C ⛅️🌖\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records吃的一般……2Exercise log没怎么锻炼杂事太多1Sleep log睡得一般可以认为很差0\n🚀 Process\n\n\nPython 学习:\n\n基础已过这周夯实进阶主要是深入语法范式常用模块项目实践三方面。\n\n\n\n英语学习\n\n未开始进度 0%,一定要开始!先背单词,学语法,然后写作,读书。\n\n\n\n博客写作\n\n进行中进度 15%,还是有一些拖延😮‍💨,需要继续坚持输出。\n\n\n\n振兴计划\n\n未开始去洛阳之前搞定\n\n\n\n🚧 Problem\n\n\n生活琐事\n\n生活中乱七八糟的琐事太多了间歇性状态不好🙁🙁🙁。\n\n\n\n解决方案\n\n多多锻炼自己吧毕竟这不是我能拒绝或者逃避的问题。\n\n\n\n📝 Note\n23 年的第 31 周,很久没有复盘分析了。简单地说 23 年上半年生活,工作,学习都处于失控边缘,客观原因居多,主观原因其次。复盘总结还是一定要搞起来,否则真的不知道问题在哪里。\n生活中上半年鸡毛蒜皮的琐碎事太多了总是被种种意想不到的事情打破。我也不是圣人不断地被打破只能不断地重新拾起倒是提升了不少韧性。\n当然还有做得好的需要持续保持下去的。当下已经可以游刃有余的面对生活中的一切琐事了韧性十足当然遇见坏事还是赶紧跑及时止损减少对自己的影响。\n总的来说生活的基础面已经做得很不错了今后需要继续保持。未来需要加强「生活隔离」和「顿感佛系」。不好的事情及时切割减少影响无关的事少操心。\n学习方面整体做得不错主要在于保持和量化。必须量化而不是只讲过程不讲结果。这就需要定期的复盘分析实践总结日拱一卒持续发展。学习方面做得比较好的地方是和 ChatGPT 结合,效率带来了质的提升。未来需要保持现有的优点,多多实践总结,成长锻炼。然后就是多读书、多看报,目前阅读量已经是有的,今年更有望冲击 200 小时!不过阅读中最重要问题就是思考的量化,未来需要持续性的写作。\n工作方面依旧是老样子很多事情我无力改变只能尝试在条件有限的环境尽力创造价值。未来方向依旧是继续像海绵一样汲取公司宝贵的经验知识。牢牢把握当下的条件环境资源取其精华弃其糟粕\n整体上对于我个人来说上半年做的不错可以打5.5分。尽管还是有不足之处,但于前一年相比进步神速。生活管理有序,情绪稳定,工作态度给力,学习不断进步,整体表现非常出色。毕竟外在因素不是我能说了算的的,只能在雨天了打把伞,天气晴朗了多晒晒太阳。\n上周六发小因为车祸走了才刚结婚不到两年……那天早上接到电话大脑是空白的忍不住哭得像个孩子。人生的记忆拼图就这么硬生生地被撕扯下来。\n其他糟糕的事情就不一一再说了过去的事情就随风飘散吧。\n人生在世世事难料且行且珍惜。\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation3.0收拾行装,继续出发。\n🎯 NextWeek\n\nPython 学习:进行中,进度 50%。\n英语学习200 个单词。\n博客3 篇\n振兴计划确定方向敲定方案\n"},"Personal/Journal/2023/W32/2023-08-07":{"title":"2023-08-07","links":[],"tags":[],"content":"2023-08-07\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 23:50郑州 +26°C ☀️🌗\n📖 Daily\n\n洛阳亲友如相问一片冰心在玉壶。\n— 芙蓉楼送辛渐·王昌龄(唐代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天周一晨会竟然还荣获奖书。这个创新项目倒是可以哈哈哈最近打算尝试再搞一个。\n上午写了一下周报然后算了算账练练字写写代码就下班了。晚上逛超市买了一顿吃的结果呢吃的撑的睡不着。🔨😥\n所以今天没有好好吃饭更是没有好好运动明天尽量早起锻炼健康饮食。\n晚安啦"},"Personal/Journal/2023/W32/2023-08-08":{"title":"2023-08-08","links":[],"tags":[],"content":"2023-08-08\n📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 23:07郑州 +29°C ☀️🌗\n📖 Daily\n\n可怜楼上月徘徊应照离人妆镜台。\n— 春江花月夜·张若虚(唐代)\n\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n\n📋 To-do List\n\n 📰 Read news\n 🖋️ Calligraphy practice\n 📖 Read a book today\n 📝 Make a plan for today\n 📌 Share something today\n\n📝 Notes\n今天做的很不错继续保持。\n就是下午因为一个小事乱了阵脚没有把博客写完不过不耽误今天是个好日子。\n明天继续加油努力奋斗"},"Personal/Journal/2023/W32/2023-W32":{"title":"2023-W32","links":[],"tags":[],"content":"2023-W32\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 11:51郑州 +31°C ⛅️🌑\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountContentDiet records5养成习惯了继续保持Exercise log3周末在家有点颓废Sleep log3一般\n🚀 Process\n\n\nDBA 学习:\n\n基础这周主要学习基础知识分为两部分sql 和 nosql预期目标 30%\nSQLite、PostgreSQL、MySQL、Oracle Database、OceanBase 、TiDB。\nRedis、MongoDB、Elasticsearch。\n\n\n\nPython 学习:\n\n进阶已过这周主要实践写代码尝试写几个小项目玩玩。\n\n\n\n英语学习\n\n未开始进度 0 %,暂时规划以后每天上午的时间都留给英语。\n\n\n\n博客写作\n\n效率低上周仅仅写了一篇这周需要继续加强。\n\n\n\n振兴计划\n\n未开始这周一定要安排上多打电话沟通26、27号安排。\n\n\n\n🚧 Problem\n\n\n英语学习英语学习一直没有找到节奏感正反馈积极性不高\n\n解决方案以后每天上午的时间全部留给英语。\n\n\n\n博客写作的积极性高但是总是想追求写好文章无论如何都是要写。\n\n解决方案保持月度 1w+ 字6 篇文章以上\n\n\n\n振兴计划加强沟通尽快落实。\n\n沟通反馈设计落实抓紧脚步。\n\n\n\n📝 Note\n上周对于 Python 的进阶学习做的非常不错,整体状态也很好,主要就是情绪问题,需要及时调整。\n过去的事情就随风飘散未来的事情更不知所踪紧握当下\n新的一周冲冲冲\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation5.0你可以做的更好的!\n🎯 NextWeek\n\nDBA 学习:进行中,进度 30%。\nPython 学习:三个小项目。\n博客写作两篇+\n英语学习落实\n振兴计划草稿\n"},"Personal/Journal/2023/W33/2023-W33":{"title":"2023-W33","links":[],"tags":[],"content":"2023-W33\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 23:47郑州 +27°C ☀️🌒\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeContentDays/CountDiet records饮食还行2Exercise log没有时间1Sleep log睡眠不好2\n🚀 Process\n\nDBA 基础:进行中 ,进度 20%。有一部分收尾工作没完成,需要抽时间完成。\nPython 学习: 进行中,进度 35%,需要进行 1w 代码实践。\n英语学习: 进行中,进度 5%。继续保持,日拱一卒,上午 All in 英语。\n博客写作: 进行中,进度 60%。继续保持。\n振兴计划: 未开始,需要和老姐,老爸沟通一下,然后落实。\n\n🚧 Problem\n\n\n生活不可控任务虽然量化了可是生活确实不可控的抵御风险能力有限可以说较差。\n\n解决方案暂时没有比较好的想法提高效率或者周末花时间弥补也许是最好的选择。\n\n\n\n状态不稳定: 上周胡吃海喝比较多,导致休息不好,进而状态不好。\n\n解决方案: 避免不必要社交,不能随便胡吃海喝,按时作息,规律生活\n\n\n\n📝 Note\n上周胡吃海喝的多运动量也只完成了 25%,休息也不好,感觉胡吃海喝占了最大的影响因素。\n生活不可控任务完成效率忽高忽低任务风险暂时没法规避需要再想想办法。\n振兴计划还是要落实然后执行下去。\n📊 ThisWeek\n\n\n\n\n\n\n\n\n\n\n\n\n\nScoreEvaluation4.5放轻松,慢慢来\n🎯 NextWeek\n\nPython 一万行:未开始,计划进度 100%。\n英语学习: 100 个单词。现在 4687需要背到 4587。\n博客: 两篇,完成月度计划。\nDBA: 基础收尾。\n振兴计划: 务必落实。\n"},"Personal/Journal/2023/W35/2023-W35":{"title":"2023-W35","links":[],"tags":[],"content":"2023-W35\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 17:36郑州 +31°C ☀️🌗\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy😢 Sad😡 Angry😔 Disappointed状态很差感觉生病了……😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records5一直吃的都不错Exercise log0乱七八糟的事情身体状态也很差没有锻炼Sleep log0睡得很差Hydration5每天都在喝水 ~Mental Relaxation0新增项目以后每周要安排娱乐时间。\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription博客写作100%8 月份完成 1w 字写作!振兴计划终止待定\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible SolutionDBA 基础75%进度失控一刻工作法Python 学习25%进度失控一刻工作法英语学习5%没有持续锻炼,形成正反馈每日继续保持,早上英语学习\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationDBA 基础收尾⏲Python 原生库&subprocess⏲Python 原生库&sys⏲Python 原生库&socket⏲Python 原生库&threading⏲Python 原生库&multiprocessing⏲Python 原生库&asyncio⏲Python 原生库&sqlite3⏲Python 原生库&sqlalchemy⏲Python 原生库&requests⏲Python 原生库&flask⏲Python 爬虫大纲⏲Python 原生库&pylint&flake8&black⏲DBA 进阶& Postgres 视频学习⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️英语单词&语法&听力♾️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客&浅谈职场政治⏲️⏲️⏲️⏲️⏲️⏲️博客&职场三部曲⏲️⏲️⏲️⏲️⏲️⏲️博客&你愿意嫁给你自己么?⏲️⏲️⏲️⏲️⏲️⏲️博客&浅谈 ChatGPT⏲博客&我们怎么开好一场会议?⏲️⏲️⏲️⏲️⏲️⏲️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation梳理 JD♾\n📝 Notes\n依旧是老样子先从快速改变人生的五件事开始。\n早起\n最近状态很差不知道是又阳了还是甲减反正是睡眠质量很差导致早上根本起不来也达不到所谓的好好休息状态。每天早上身心俱疲如果再有类似的情况就一定要去医院看医生了。\n运动\n运动积极性一直挺高的就是身体状态不行一些意料之外乱七八糟的杂事也有点多。总之就是多运动就完事了 ~\nKeep 三一计划!!\n阅读\n阅读一直维持的特别好已经是特定场景下的默认习惯了。就是最近感觉太忙了也没有尝试安排休息时间抖音刷的有点多以后要安排一些打游戏时间\n最近主要阅读一些技术类书籍暂时先这样\n写作\n写作就依照如何写好一篇博客尽力有条不紊的执行下去\n六篇博客 or 1万字\n冥想\n这么长时间的实践倒是越来越有专属独立的冥想体验了。主要就是两方面\n\n专注力提升\n心流状态\n静坐\n\n未来继续实践慢慢琢磨 ~\n接下来说一说其他方面的复盘总结。\n\n学习\n以前一直苦恼没有办法很好的掌控任务规划、时间安排具体的问题如下\n\n任务划分不够具体致使无法具体规划时间量。\n无法具体规划时间量任务进度失控……\n\n目前寻找到一个合理的时间安排方案《一刻工作法》简单来说就是任何具体的任务量由至少一刻15分钟构成一天两个小时8 个。一周最少 12 小时学习时间,满负荷安排就是 24 小时。这样简单的规划下来共有 48~96 个时间片。关于任务规划,需要具体到需要多少时间片,单个任务时间片不允许超过 8 个(防止错误估量)。\n这样一来学习方法论雏形基本形成。简述下来是这样的\n\n番茄工作法15 分钟为一个切片,最多不超过 8 个切片2-4 个切片需要安排 15 分钟的休息时间。\n任务规划采用主、支、日常三等级规划任务每日以主任务为主支任务为辅。\n看板利用看板快速存档恢复学习环境避免每天无法快速开始学习。\n计划目前采取周计划、季度计划安排工作。\n\n工作\n一直是老样子咯不过还是要产出两个项目否则过年工作总结没法交代。\n\nWindowsCloudInit\nShowCSV\n\n社交\n减少无效社交稳步学习成长\n健身\n三一计划继续加持\n娱乐\n有时候学一周就容易累以后要合理的安排一些游戏时间。\n\n饥荒\n缺氧\n城市天际线\n\n我来啦~\n情绪\n情绪一直比较稳定的不过有一说一旧创伤在特定场景还是容易会回溯。\n不着急慢慢来 ~\n目标\n调整好状态继续前行\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others7《一刻工作法》期望 yyds暂无"},"Personal/Journal/2023/W36/2023-W36":{"title":"2023-W36","links":[],"tags":[],"content":"2023-W36\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 10:06郑州 +25°C 🌫🌘\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy😢 Sad😡 Angry不开心一点都不开心吵架干仗😔 Disappointed😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records0早上没有好好吃饭Exercise log0没有锻炼身体Sleep log0因为睡得很差导致没有好好吃饭没有好好锻炼Hydration5每天都在好好喝水Mental Relaxation0暂时没有打游戏安排娱乐\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescriptionDBA 基础收尾已完成基础性 SQL 语言Python 标准库学习35%进行中,完成了 3+2 个\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution博客写作未开始没有时间写这周要根据月初定的写两篇英语学习未开始积极性不够继续调整\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationPython 原生库&threading⏲Python 原生库&multiprocessing⏲Python 原生库&asyncio⏲Python 原生库&sqlite3⏲Python 原生库&sqlalchemy⏲Python 原生库&requests⏲Python 原生库&flask⏲Python 原生库&pylint&flake8&black⏲Postgres & 基础概念、引言、背景⏲Postgres & 系统架构⏲Postgres & 存储系统⏲Postgres & 事务管理⏲Postgres & 并发控制⏲Postgres & 查询处理⏲Postgres & 索引⏲Postgres & 扩展⏲Postgres & 安装、编译⏲Postgres & 性能优化⏲Postgres & 备份恢复⏲Postgres & 高可用与复制⏲DBA 数据库设计规范大纲♾Python 爬虫大纲♾️英语单词&语法&听力♾️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客&浅谈职场政治⏲️⏲️⏲️⏲️⏲️⏲️博客&职场三部曲⏲️⏲️⏲️⏲️⏲️⏲️博客&你愿意嫁给你自己么?⏲️⏲️⏲️⏲️⏲️⏲️博客&浅谈 ChatGPT⏲博客&我们怎么开好一场会议?⏲️⏲️⏲️⏲️⏲️⏲️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation梳理 JD♾\n📝 Notes\n上一周很不爽没有睡好导致所有的事情陷入了恶循环真的是无敌\n这周尽力调整吧不过《一刻工作法》实践效果很不错的哦。\n新的一周继续冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others3没有睡好导致所有的事情都陷入了恶循环很差"},"Personal/Journal/2023/W37/2023-W37":{"title":"2023-W37","links":[],"tags":[],"content":"2023-W37\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 16:21郑州 +30°C ⛅️🌒\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy开心周末去了云台山两日游 ~😢 Sad😡 Angry😔 Disappointed不知道咋地了一上班就头痛……😂 Laughing😭 Crying心情还是很沉重唉……😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records3休息的不好就没有自己作饭吃了。Exercise log2周末爬山了状态不好没有运动。Sleep log3睡眠不好主要还是状态不好。Hydration5一直都有在好好喝水。Mental Relaxation2周末旅游了游戏暂时不玩了\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription---------\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution没有做好0%电脑坏了……上周的任务顺延\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationPython 原生库&threading⏲Python 原生库&multiprocessing⏲Python 原生库&asyncio⏲Python 原生库&sqlite3⏲Python 原生库&sqlalchemy⏲Python 原生库&requests⏲Python 原生库&flask⏲Python 原生库&pylint&flake8&black⏲Postgres & 基础概念、引言、背景⏲Postgres & 系统架构⏲Postgres & 存储系统⏲Postgres & 事务管理⏲Postgres & 并发控制⏲Postgres & 查询处理⏲Postgres & 索引⏲Postgres & 扩展⏲Postgres & 安装、编译⏲Postgres & 性能优化⏲Postgres & 备份恢复⏲Postgres & 高可用与复制⏲DBA 数据库设计规范大纲♾Python 爬虫大纲♾️英语单词&语法&听力♾️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客&浅谈职场政治⏲️⏲️⏲️⏲️⏲️⏲️博客&职场三部曲⏲️⏲️⏲️⏲️⏲️⏲️博客&你愿意嫁给你自己么?⏲️⏲️⏲️⏲️⏲️⏲️博客&浅谈 ChatGPT⏲博客&我们怎么开好一场会议?⏲️⏲️⏲️⏲️⏲️⏲️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation梳理 JD♾\n📝 Notes\n意外总是来的很突然电脑坏了前前后后折腾了将近三天所有的事情都停摆了。\n不过周末和小雅一起去旅游啦焦作云台山。开心开心奥利给\n这周主要任务就是上周的任务顺延完毕。\n早上依旧要开始好好学习英语呀\n同时晚上学习软考中级的知识准备考试\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others3电脑坏了这周顺延上周任务冲冲冲"},"Personal/Journal/2023/W40/2023-W40":{"title":"2023-W40","links":[],"tags":[],"content":"2023-W40\n🗓 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 15:07郑州 +24°C ☀️🌘\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy国庆出去玩啦😢 Sad学习项目没有完成😡 Angry有时候莫名其妙的当受气包也是挺无奈的😔 Disappointed工作照就……😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records2每天都有好好吃饭但是没有自己做。Exercise log0前段时间感觉是阳了浑浑噩噩的一个月没有锻炼。Sleep log3睡的还可以。Hydration5每天都有好好喝水哈哈哈。Mental Relaxation2折腾 Ubuntu 然后玩了饥荒和缺氧\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation学士学位——成人英语⏲软考——网络工程师⏲\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationPostgreSql⏲Python⏲\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation简历整理♾\n📝 Notes\n上个月主要因为 身体不舒服,状态不好 导致所有的事情进展缓慢。\n复盘\n主要从工作学习生活早起阅读写作运动冥想方面总结。\n工作\n没啥好说的得过且过努力早期脱离苦海。\n学习\n目前两点问题生活琐事身体状态。生活琐事真的很难把握最主要的还是身体状态有时候就是莫名其妙的不舒服啥都不想干。至此也终于理解了为什么很多下学以后很难再进行学习了。\n对于生活琐事做减法减少无效社交避免环境内耗。\n对于身体状态调节生活节奏多运动好睡眠身体始终是革命的本钱。\n我认为目前这两点已经不是初步培养期了主要就是巩固并且坚决的执行下去。\n生活\n生活方面不可控因素太多了主要就是家人感情社交。\n老爸老妈是真的不图能改变什么了主要还是自己多付出一些多理解一些主动调整心态。\n老姐也有了 baby我呢暂时主打一个精神陪伴不添麻烦就好。\n感情方面目前没有特别尖锐的问题顺其自然 \n社交方面问题很多真的是一定要避免无效社交远离负能量人群\n早起\n早起一直都很随意主要是睡得好就一定能起得来前段时间睡不好是真的起不来。以后呢睡前泡个脚少玩会手机调整心态晚饭后情绪稳定不争执。\n阅读\n阅读是一直在进行的目前主要针对技术阅读同时给写作留下充分的时间。后续动态调整不过阅读真的是一个好习惯下一年继续冲击 365 阅读。\n写作\n坚持了两个月的写作勉强及格这个月需要继续坚持呀不能说是坚持写就完事了\n运动\n运动真的是需要坚持三一计划一定要保证\n冥想\n一直很好奇小孩子的精力为什么那么充沛专注力。未来几个月减少无效干扰提升专注力\n计划\n未来两个月有两件很重要的事情软考英语。\n软考主要是涉及未来的一个伏笔下点功夫争取一次性过。\n英语调整心态争取一次性过。\n未来一个月重心以软考为主英语为辅IT 方面随机。等软考结束,主抓英语,提起 IT 方面。\n冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others3调整心态"},"Personal/Journal/2023/W45/2023-11-12":{"title":"2023-11-12","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 20:52郑州 +6°C ☀️🌑\n📖 Daily\n田家秋作苦邻女夜舂寒。——李白唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n闭关了一段时间也有了一些新的体会和感悟。需要逐步释放出来\n家里的沙发终于到位了美滋滋。过几天我的小桌子也都到位了再也不用一到家就躺床了 \n加油加油"},"Personal/Journal/2023/W46/2023-11-15":{"title":"2023-11-15","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 17:33郑州 +12°C 🌫🌒\n📖 Daily\n昨夜闲潭梦落花可怜春半不还家。——张若虚唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n这几天天气很差步入冬天也变得更懒了。\n方向不变目前主要任务明年毕业及学习英语技术方面主要设计企业信息化建设以及成果整理。\n对了还有写作\n小周继续冲冲冲"},"Personal/Journal/2023/W48/2023-W48":{"title":"2023-W48","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 20:25郑州 +11°C ☀️🌗\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy去杭州找姐姐玩了😢 Sad莫名其妙的吵架😡 Angry莫名其妙的生气😔 Disappointed莫名其妙的生病😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records2天冷起不来早上都是买着吃而且还长胖了Exercise log0几乎没有锻炼……Sleep log2睡得都比较晚导致起来的也比较晚Hydration5工作日几乎天天喝水休息日就比较懒散Mental Relaxation2没怎么放松光刷抖音了\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription生活用品采购已完成终于有了沙发和小桌子\n📝 Notes\n最近 8 周或者说最近两个月,主观原因很大,客观原因也有。主要就是懒了,真的天冷了就懒了。还有就是莫名其妙的生命,感冒。自打立秋后,各种呼吸道疾病导致反反复复的生病,难受,耽误工作进度。还有就是成人本科的学习任务没有践行到位。还有其他一些零碎的小事情,所以需要一次全面系统的总结复盘。\n工作\n工作方面没什么好说的但是有点太飘了。本来计划沉下心做的数据分析企业经营学习可是由于如上问题整体拖延。还有就是相关的学习进度失控主要罗列如下\n\n企业战略经营数据未开始学习。\n网络相关知识未开始系统化复习。\n企业信息化基建论文未开始撰写以及相关实践未开始。\n\n预计即将进行的项目\n\n面试的准备\n\n九州通的工作没什么好说的主要就是整体项目管理进度的失控导致具体任务的拖垮。目前计划按照明年 3 月 5 日的倒计时,工作方面主要是高效利用现有资源,珍惜有限时间,充分进行实践。\n主要优先开展如下项目\n\n企业战略经营数据分析信息化基础建设。\n企业网络相关知识面试的准备。\n\n健康\n目前来说健康是真的黄色预警了主要问题如下\n\n饮食不注意胡吃海塞。\n体重飙升即将超出红线。\n运动量较少导致睡眠不好等等负面反应。\n\n算是整体的进入负面循环了很可怕的。不能这么任性下去必须要尽快的恢复。目前主要的解决方法就是恢复三一计划合理控制饮食。\n\n三一计划\n控制饮食\n\n还有最最最重要的就是以后立春立秋前后学会戴口罩否则感冒生病一次就浪费好多的时间真的是令人沮丧。\n财务\n目前来说个人财务没有短期问题但是可能会有长期压力。生活中需要用钱的地方太多了单纯的节省并不能有效的解决问题需要多方面介入同时结合长期的增长。不过目前苗头正好剩下的交给时间。\n\n长期看好\n\n社交\n社交倒是没有什么太大的问题整体来说都很不错主要还是选择个人喜欢的圈子减少负能量圈子的摄入防止进一步影响个人生活和成长。\n\n一个月不少于两次的社交。\n\n同时还有的就是进一步更新迭代个人网络圈子结交优秀圈层认识优秀朋友拓宽个人信息渠道。\n爱好\n目前摄影的基本盘已经很不错了主要还是要走出去每个月规划不少于两次的摄影同时进一步系统深入的学习争取长期获利。\n\n一个月不少于两次的摄影。\n\n感情\n从我的角度出发我是没有任何的问题的。非常坚定的认为我是没有问题的可是偶尔还是会有争执同时授以前的影响导致偶尔我也会被调动情绪。放轻松一些慢慢来以幸福生活快乐相处为目标。\n家庭\n有时候还是和老爸老妈打电话的时间有些少还是调整一下尽量多一些。\n本周计划和目标\n48 周计划实际在 49 周记录,所以是本周计划和目标,本周的主题就是尽量的恢复之前高效工作的 80%。\n\n主线任务公司战略经营数据分析学习及应用。\n支线任务明年 3 月份成人英语学习及 12 月份的线下考试。\n日常任务rss 源的上线及应用,还有写作。\n\n具体的任务暂不规划主要就是恢复恢复还是恢复。然后本周周末根据本周实际情况规划本月的项目任务。\n冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others2期待本周恢复"},"Personal/Journal/2023/W49/2023-12-07":{"title":"2023-12-07","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon12月 7 日☀️🌘\n📖 Daily\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n周一安排计划周二周三执行效果还是不错的整体恢复很快。\n今天稀里糊涂的车又坏了明天上午依旧是浪费时间的修车。有时候理想状态的效率和工作真的是老天爷赏赐的时间总是感觉习惯被打破以后莫名其妙的恢复困难。\n今天的情绪处理的也还算好但是总是会因为七七八八的杂事影响心情。\n总是就是我太想进步了沉下心来继续前行总结复盘进步\n对了还有每日习惯的养成冲啊"},"Personal/Journal/2023/W49/2023-W49":{"title":"2023-W49","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周日 21:44郑州 +1°C 🌦🌘\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy想不起来了😢 Sad没有😡 Angry没有😔 Disappointed这周还是没有运动😂 Laughing没有😭 Crying没有😱 Scared车车在洗车的时候坏了真的是……\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records3这周基本都是买的还是要自己做买的饭油水太大了。Exercise log0这周依旧是没有运动下周需要继续冲冲冲。Sleep log3这周大部分时候睡得都挺爽的需要持续记录睡眠质量从而进一步调整。Hydration7这周喝水很不错哦基本上天天都在多喝水。Mental Relaxation1还是刷抖音哈哈哈没有进行其他的娱乐活动。\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescriptionWindows Server 实验部署进行中草草地进行了实验,没有进行记录和规划。\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution运动未完成积极性不够杂事太多每日上班的时候结合番茄工作法多转转。下班的时候主动出去打球或者在家跳绳撸铁。饮食进行中光买着吃了买着吃油水太大吃了很不爽还是要早起自己做着吃。\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation英语单词♾英语语法♾金斗生猪企业规划书♾\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationWindows Server 实验部署记录♾️企业数字化监控体系设计,搭建,部署♾️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationRSS 信息源重构2 小时博客:人生观的论述♾️摄影文件整理♾️\n📝 Notes\n这周整体来说状态恢复及调整还算及格。但是运动和饮食以及具体的工作规划还是不够好。\n首先说睡眠方面整体睡得还是不错的。但是不能多睡睡得多反而会更困暂时规划个人休息时间晚上 11 点左右睡觉,早上 6 点起床。中午结合实际情况小憩一会,同时进行一个月实验。对于冬天太冷,特别是客厅,就结合小爱同学,自动打开空调解决。\n还有就是运动方面积极性不够客观时间也不充足感觉总是会有各种各样的事情下一周一定要积极运动。同时结合饮食计划一定要拥有一个良好的身体状态同时积极的运动。这样才可以有充足的精力进行阅读生活学习。\n学习方面结合番茄工作法还是可以很有效的分配精力控制进度的。这周继续保持工作方面暂时没有什么好说的。\n这周主要是冲击同时习惯的养成。\n冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others6不错这周继续努力"},"Personal/Journal/2023/W5/2023-W5":{"title":"2023-W5","links":[],"tags":[],"content":"2023-W5\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 16:45郑州 +10°C 🌫🌕\nDaily\n\n行人日暮少风雪乱山深。\n— 寄内·孔平仲(宋代)\n\nNote\n年前心就散了等待着开开心心过大年。\n年后又自驾游了一趟满足了~ 正式工作的第一周,尽快调整进入工作状态!\n未忙完的事情尽快搞定不开新坑。全新的一年提升专注力拉高效率。冲冲冲"},"Personal/Journal/2023/W50/2023-12-12":{"title":"2023-12-12","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周二 21:37郑州 -1°C 🌫🌑\n📖 Daily\n小楼昨夜又东风故国不堪回首月明中。——李煜五代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天周二这周计划的很完美不过突如其来的虚拟化迁移真是浪费了不少的时间。而且成人教育老师通知周末可能要去信阳考试又得着手准备考试真的是好多意想不到的事情。\n不过这两天有好好吃饭运动学习进步。不过就是好像中招了我丢真的是。这周调整计划准备可能的考试然后做好手头的事情抗寒避免感冒争取明天把 rss 源的事情搞定!\n调整的很不错哦小周冲冲冲"},"Personal/Journal/2023/W6/2023-W6":{"title":"2023-W6","links":[],"tags":[],"content":"2023-W6\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 10:45郑州 +1°C 🌫🌗\nDaily\n\n浓雾知秋晨气润薄云遮日午阴凉不须飞盖护戎装。\n— 浣溪沙·江村道中·范成大(宋代)\n\nNote\n在经过上一周的调整和准备2023 年正式开课!目前的方向是七八月份的跳槽、成人本科的英语、数学的学习。新的一年冲冲冲!\n跳槽面试的标志性节点位于于生日过后如果按照 15 天一个主题,那么将拥有 9 个主题的富裕时间。将以运维、开发两个方面为重点。前三个 15 天是运维基础,后三个 15 天是开发基础,留下三个 15 天作为冗余。\n成人本科的英语和数学是今年稳步发力因为明年就毕业了所以需要提前打好基础。\n未来的 90 天重心就在于冲刺和主题专项!目前的工具:服务器,路由,硬件密钥等已经准备就绪,其他的暂时不缺!\nThisWeek\n这周攻坚的主题是中小型企业信息化基础建设基于理论侧重于实践。"},"Personal/Journal/2023/W7/2023-02-14":{"title":"2023-02-14","links":[],"tags":[],"content":"2023-02-14\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 09:02郑州 +3°C ☀️🌘\nDaily\n\n雾窗寒对遥天暮暮天遥对寒窗雾。\n— 菩萨蛮·雾窗寒对遥天暮·纳兰性德(清代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n情人节快乐 ~\n企业信息化基础建设专题已经开始寻找到一篇非常具有知道意义的论文。经过这两天的消化吸收越来越感觉理论知识的重要性与目前的不足。特别是项目管理水平的不足需要时间进行学习同时还有财务知识。\n今天是周三为了避免盲目的纸上谈兵今天务必完成绪论进行企业信息化基础建设专题的前期调研现状分析工作。\n加油冲冲冲"},"Personal/Journal/2023/W7/2023-02-15":{"title":"2023-02-15","links":[],"tags":[],"content":"2023-02-15\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 12:14郑州 +7°C ☀️🌘\nDaily\n\n香雾云鬟湿清辉玉臂寒。\n— 月夜·杜甫(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n最近总是休息不好天冷也是不想运动呀希望天气赶快温暖起来这样就可以动起来\n专题一企业数字化基础建设的准备工作已经做完了目前暂时没有遇见处理不了的问题。接下来就是详细的书写实施计划然后进行实操\n加油冲冲冲"},"Personal/Journal/2023/W7/2023-02-16":{"title":"2023-02-16","links":[],"tags":[],"content":"2023-02-16\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 21:55郑州 +5°C ☀️🌘\nDaily\n\n细雨春芜上林苑颓垣夜月洛阳宫。\n— 书愤二首·陆游(宋代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n这两天不断摸索实践同时进行计划的设计。收获非常不错明天就是完善实施计划然后完成所有的部署。\n最近总是休息不好感觉和饮食不规律不健康以及缺少运动有关。需要好好处理生活呀。\n最近总是莫名其妙的情绪旋涡Take easy "},"Personal/Journal/2023/W8/2023-02-20":{"title":"2023-02-20","links":[],"tags":[],"content":"2023-02-20\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周一 21:21郑州 +11°C ☀️🌑\nDaily\n\n榆柳萧疏楼阁闲月明直见嵩山雪。\n— 洛桥晚望·孟郊(唐代)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n专题一经过上周的规划、摸索、实践周末的物理服务器上架工作。现在发现的几个问题如下\n\n缺少大量的实践经验辅助\n前期的规划缺少经验的佐证存在纸上谈兵。\n需求的具体实现可能会跟实际情况结合动态改变。\n无法把握能用就好和锦上添花的临界点。\n工作起来太投入不知道休息。容易效率底下并且很累。\n\n问题一缺少经验\n针对于缺少大量实践经验辅助这个问题没有办法只能自己花时间多请教老师。主要还是自顾自单打独斗导致容易走弯路但是结合当下项目的局限性所以暂时只能请教网络朋友。\n能力强很重要找对师傅结合起来走的更远\n问题二存在纸上谈兵\n前期规划存在纸上谈兵主要问题在于需求调查不到位缺乏实践经验。两者更需要互相结合才能保证方向正确。\n纵使需求调查的全面到位更需要多探讨发现不足填充个人局限性。实践经验不足与问题一重合不再叙述。\n问题三无法把握临界点\n虽然不能让完美成为成功路上的绊脚石但是有一些事情不存在回溯的可能性所以就很难抉择。还是要具体情况具体分析区分导向进行选择\n问题四工作狂魔\n主要还是没有细致划分任务量把控任务进度导致有些失控进而忙起来忘记休息。\n任务管理项目管理是一个需要学习成本的事当下只能尽力去做好期待日后专业化的学习了\n项目一进度不错值得鼓励加油加油冲冲冲"},"Personal/Journal/2023/W8/2023-02-22":{"title":"2023-02-22","links":[],"tags":[],"content":"2023-02-22\nInfo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周三 20:13郑州 +4°C ☁️🌒\nDaily\n\n雾露夜侵衣关山晓催轴。\n— 答柳恽·吴均(南北朝)\n\nHabits\n\n 早睡早起 🌃\n 健康饮食 🥗\n 多喝热水 ☕️\n 保持运动 💪\n\nTo-do List\n\n 阅读资讯 📺\n 每日必做 ✨\n 今日读书 📖\n 今日计划 ✏\n 今日分享 📌\n\nNotes\n中小型企业数字化信息基建主题用十二个字总结就是理论欠缺、经验不足、盲人摸象。首先由于是模拟操练并不存在实际问题所以效果一般。总的来说中小型企业满足基本需求是可以实现的但是顾及长远发展就必须专业的事情找专业的人来干。\n纸上谈兵不可取模拟操练欠真实。必须要以解决问题满足需求为导向切勿空中楼阁迈大步。务必根据不同的需求和场景选择最合适的解决方案。\n理论欠缺\n首先是存在眼高手低问题自以为掌握了丰富的理论仅仅欠缺实际经验但是实操过程中依旧发生了很多理论知识准备不充足的情况。例如vmware 大版本兼容性问题,数据中心高可用问题等等。总是想通过搜索引擎解决片面的一个问题,殊不知需要仔细阅读官方文档手册进行模拟实践。\n正常的理论学习应该是通读官方文档熟读重点部分绘画操作过程熟悉操作步骤。理论实践更应该不局限于客观条件尽可能的利用已有的条件最小成本的模拟实践。\n经验不足\n在拥有基础的理论知识后一定要寻求验证请教老师傅。验证设计中的想法减少实操的成本。一句话就是三个诸葛亮顶一个臭皮匠切勿闭门造车\n经验不足就要多问、多听、多讲\n盲人摸象\n首先对中小型企业数字化基建没有足够的认知同时加上没有实际需求、具体场景的问题存在。导致实践的成果就是想象的果实华而不实大而不甜。\n首先务必以满足需求解决问题为第一原则设计良好持续发展为第二要务。切勿创造需求捏造需求画龙点睛不可取\n理想固然美好现实才是重要"},"Personal/Journal/2024/W10/2024-03-05":{"title":"2024-03-05","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 20:15甲辰龙年 丁卯月 戊辰日 农历正月廿五郑州 +6°C 🌫🌘\n📖 Daily\n夜寒不近流苏只怜他、后庭梅瘦。——毛滂宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n墨迹了很久的日报又来啦感觉就是需要坚持不应该说是坚持更多的是习惯养成更好的沉淀自己。\n目前的问题就是状态的回归以及生活健康好习惯的养成还有每天工作的效率和进度。\n目前 3 月份留点时间给自己,继续保持每天的工作习惯和良好的工作劲头。\n第二季度忙完生活上的事情就加把劲努力冲冲冲"},"Personal/Journal/2024/W10/2024-03-06":{"title":"2024-03-06","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周四 09:58甲辰龙年 丁卯月 庚午日 农历正月廿七郑州 +6°C 🌫🌘\n📖 Daily\n日出三竿春雾消江头蜀客驻兰桡。——刘禹锡唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天工作进展还不错整体来说执行力还是很强的。\n主要就是上午的关于金斗的 BI 分析以及下午的 Docker 和 Ansible 还有 PXE 等自动化的学习处理。\n生活习惯需要进一步恢复还有就是软考的学习安排都要做起来了。\n明天好好规划一下冲冲冲"},"Personal/Journal/2024/W10/2024-03-07":{"title":"2024-03-07","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周四 23:19甲辰龙年 丁卯月 庚午日 农历正月廿七郑州 +8°C ☀️🌘\n📖 Daily\n恻恻轻寒翦翦风小梅飘雪杏花红。——韩偓唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天工作行程安排的比较集中上午看完新闻后就处理了一下金斗厂里的事情。然后下午就处理了 PVE 虚拟机的事情,学习的事情完全 ok问题不大。\n明天就周五了这周必须要写周报了。\n还有就是天气也逐渐回暖了所有的运动健康习惯都要开始安排上了\n阅读也是要规律生活。\n周末见"},"Personal/Journal/2024/W10/2024-W10":{"title":"2024-W10","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 14:23甲辰龙年 丁卯月 甲戌日 农历二月初二郑州 +23°C ☀️🌑\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy基本上都挺开心的哈哈哈😢 Sad😡 Angry😔 Disappointed对于工作上的事情确实挺厌烦的。😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records5周末懒惰了平时都在好好吃饭。Exercise log1周末走了 1w 步平时也得加强训练。Sleep log7睡得都挺不错的就是偶尔夜里会醒。Hydration7那必须天天都在喝水。Mental Relaxation0没有怎么玩游戏感觉放松就是刷抖音哈哈哈。\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription恢复计划已完成过年期间的放松也是时候收尾了。\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution运动未开始懒惰+天冷二月二了都,万物复苏冲冲冲!\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation英语学习♾面试准备♾\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationK8S+Docker 学习实践⏲Linux + Net 学习实践⏲Python +Shell + Ansible + iPXE+CloudInit⏲Windows Server 实践总结\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation如何快速处理OnCall——博客♾思维模型——博客♾\n📝 Notes\n24 年的第一次周总结,新的一年新气象,所有的事情都准备好了。需要继续冲冲冲!!!\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others6调整不错继续冲"},"Personal/Journal/2024/W11/2024-03-11":{"title":"2024-03-11","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 21:27甲辰龙年 丁卯月 甲戌日 农历二月初二郑州 +20°C ☀️🌑\n📖 Daily\n暖雨晴风初破冻柳眼梅腮已觉春心动。——李清照宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天上午阅读新闻看书刻意练习都是完全 ok 的,下午呢就了解了 Linux 自动化部署方面的内容,回到家发现刚好有这方面的书籍,并且通过多种的方式深入的理解了 Linux 自动化部署的知识和内容。\n晚上回家也运动啦慢慢来 \n该睡觉了看书晚安 "},"Personal/Journal/2024/W11/2024-03-12":{"title":"2024-03-12","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 22:27甲辰龙年 丁卯月 乙亥日 农历二月初三郑州 +13°C ☀️🌒\n📖 Daily\n春蚕食叶响回廊禹门已准桃花浪月殿先收桂子香。——辛弃疾宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天上午进展很不错下午学习 Linux 部署方面的知识,感觉我还是不习惯于去提问,然后浪费比较多的时间。并且 ChatGPT 也是对的,但是感觉知识都是点状的,不知道如何连成线,连成正确的线。\n洗洗收拾睡啦明天早起继续冲冲冲"},"Personal/Journal/2024/W11/2024-03-13":{"title":"2024-03-13","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周三 22:41甲辰龙年 丁卯月 丙子日 农历二月初四郑州 +14°C ☀️🌒\n📖 Daily\n春还草阁梅先动月满虚庭雪未消。——王守仁明代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n今天虽然没有如愿按照计划行事不过关于 Linux 自动化部署也了解了更多。主要还是工作上的一些杂事,目前进度推迟比较慢。\n晚上回来把家里打扫的非常干净明天就把企业常见应用继续搭建摸索一下。然后写一篇博客回家准备准备周五去洛阳 \n晚安晚安 "},"Personal/Journal/2024/W11/2024-W11":{"title":"2024-W11","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 10:49甲辰龙年 丁卯月 壬午日 农历二月初十郑州 +14°C ☀️🌔\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy一起去洛阳啦😢 Sad对于 XX 的边界感还是很无语……😡 Angry😔 Disappointed😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records3一般没有怎么好好吃饭Exercise log3日常运动了几次然后周末还爬了一次山。Sleep log5睡得还不错就是运动一下会睡得更好。Hydration4去洛阳的几天没有怎么好好喝水。Mental Relaxation0光刷抖音了……\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescriptionPython +Shell + Ansible + iPXE+CloudInit进行中 50%系统全面深入了了解 Linux 部署体系\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solutio英语学习& 面试准备未开始沉迷于技术,还有生活琐事占用了几天。这周必须把面试准备的基本要素准备好,英语学习续上。天也不冷了,需要逐步早起运动了。待开始无逐步运动博客没写代开始懒!这周必须完成两篇博客的输出。\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation英语学习♾面试 - 简历⏲️⏲️⏲️⏲️面试 - 自我介绍⏲️⏲️⏲️⏲️面试 - 薪资计划⏲️⏲️⏲️⏲️面试 - 行业研究⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️面试 - 题目准备⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️面试 - AI 练习⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️⏲️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationK8S+Docker 学习实践⏲Linux + Net 学习实践⏲Python +Shell + Ansible + iPXE+CloudInit⏲Windows Server 实践总结⏲️⏲️⏲️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation如何快速处理 OnCall——博客♾思维模型——博客♾\n📝 Notes\n这周因为周五请假去洛阳了实际的工作日只有 4 天。\n目前没有什么特别多的问题主要就是没有规划好以及实行过程中的不可预测还有个人的懒惰共同造成的。这周必须要把既定计划做完。\n还有就是涉及到 JD 公司的一些事物,怎么说呢。感觉说不清,也理不清。保持初心,在其位谋其职吧。不要投入过多,保持适当的距离。\n新的一周继续冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others3很多可以做好的地方都没有做好。"},"Personal/Journal/2024/W12/2024-03-20":{"title":"2024-03-20","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周三 22:23甲辰龙年 丁卯月 癸未日 农历二月十一郑州 +17°C ☀️🌔\n📖 Daily\n几日不来春便老开尽桃花。——吴琚宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n说实话被恶心的很烦我真的是完全不想搭理那么多的事情。但是总喜欢命令式的指挥我……\n然后又莫名其妙的嗓子疼看来是真的不能抽烟。戒了戒了……\n重新调整一下节奏恢复一下运动训练。\n明天周四冲冲冲"},"Personal/Journal/2024/W12/2024-W12":{"title":"2024-W12","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 14:54甲辰龙年 丁卯月 己丑日 农历二月十七郑州 +16°C ☀️🌕\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy😢 Sad乱七八糟厂区里的事情。😡 Angry😔 Disappointed扁桃体嗓子又冒烟了……😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records5吃的还不错只要起来都吃的很好。Exercise log2下班锻炼了几次没有开始力量训练。Sleep log4最近半夜没有醒还不错感觉就是肺火。Hydration7喝水的好习惯可算是养成啦 ~Mental Relaxation2虽然没有打游戏但是偶尔下下围棋还是不错的。\n📝 Notes\n上周三开始不舒服难受生病然后周末又忙碌了两天。所有的计划都没有完成差评\n最近做的不好的地方\n\n换季的时候一定要注意防护不然容易生病一周的时间都没有了……\n关于 JD 的事情,核心问题还是没有权利,财政。名不正言不顺所有的事情都没有办法很好的落地。核心领导人执行力不够,领导力不够,团队组织能力不够。总之就是很多核心的问题都暴露了出来。主要原因还是主观的,不愿意成长。\n关于求职面试的事情不建议在办公室处理。这周还是下班了回家自己琢磨最好。\n下个月就需要安排去姐姐那的时间。\n\n总体来说每个部分都做的不太好。缺乏运动吃得不好也睡的不好有点恶循环的性质。还是要一方面一面的做起来。\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others2不及格"},"Personal/Journal/2024/W14/2024-W14":{"title":"2024-W14","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 20:47甲辰龙年 戊辰月 壬寅日 农历二月三十郑州 +19°C ☀️🌑\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy一般杂事比较多😢 Sad很多工作没有成效😡 Angry自己的惰性需要进一步改善😔 Disappointed冲冲冲啊😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records5吃这一方面目前做的非常不错。Exercise log3运动习惯也在养成中。Sleep log3睡眠状态一般不是很好。Hydration5喝水那必然是天天的。Mental Relaxation0感觉默认成习惯了……\n📝 Notes\n24 年的第一个季度也过去了,需要系统全面的总结评价一下了。\n生活\n生活方面目前整体做的都很不错势头很好继续保持\n工作\n工作方面依旧是老样子不过暴露出一个非常巨大的问题。关于 JD 的事情,我牺牲了太多的个人精力和时间,目前来说除了一些实践经验,除此之外毫无收获。自我感觉跨度太大,短期来看这些收获毫无价值……\n可是却占据我了 1/3 的精力和时间,目前短期来说是一个非常错误的决定!所以未来将会完全抛弃这方面的工作任务及精力安排。\n面试方面感觉一直被杂事拖拖拖整体就搞得力不从心。务必需要尽快落实实践还有就是关于 软考 的事情,明天务必决定是否参加软件,如果参加就必须调整时间准备考试!\n一季度的工作整体来说很差劲\n学习\n目前来说学习又跨过了一个台阶但是感觉似乎总是最低效率的再去学习。整体事物推进的太满不过主要是两方面的原因工作时间不可控以至于总会被杂七杂八的事情拖累。下班之后的时间又不富裕。这目前是一个比较大的问题目前就是调整一下非工作时间尽可能的干正事工作时间能干到正事最好干不到谁也没办法。\n健康\n必须要好好运动了 \n天气也慢慢的热起来了一切都需要有条不紊的进行。新的一年冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others1很差劲需要尽快调整"},"Personal/Journal/2024/W16/2024-W16":{"title":"2024-W16","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 19:55甲辰龙年 戊辰月 丙辰日 农历三月十四郑州 +25°C ☀️🌕\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy😢 Sad😡 Angry😔 Disappointed莫名其妙的不是太开心状态一般……😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records3吃的一般Exercise log3运动保持的还不错……Sleep log3总感觉睡不好睡不好难受……Hydration5每天都在喝水Mental Relaxation0\n📝 Notes\n我总感觉最近状态很差莫名其妙的差劲……\n缺乏运动吃的不规律烦心事太多。各个方面的很多事情都需要我来处理然后就有点累了……\n健康\n切实的感受到工作这三年带来的身体变化每天的坐班已经成为了一种痛苦\n而且身体状态的改变时时刻刻的在影响着自己需要突破一下\n运动起来\n工作\n工作方面依旧是老样子没有什么可值得说的。\n这个月底需要把很多方面的具体工作落实一下\n学习\n准确来说需要学习的东西实在是太多了。严格意义上来说是根本学习不完的。\n未来需要大量的实践实践再进一步的实践。\n爱好\n品茗、摄影、围棋目前的需要整理一下规范一下梳理一下脑子中的知识。\n生活\n生活上的事情说实话真的是烦还是老方针尽可能的远离远离再远离\n自我\n目前整体上来说已经做的很不错的似乎就是瓶颈的突破以及无法控制的事情导致的心情状态的影响。\n就这样慢慢来\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others不太好调整一下尽快恢复"},"Personal/Journal/2024/W17/2024-04-24":{"title":"2024-04-24","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周三 01:09甲辰龙年 戊辰月 戊午日 农历三月十六郑州 +14°C ☀️🌕\n📖 Daily\n洛阳城东桃李花飞来飞去落谁家——刘希夷唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n甲辰龙年 戊辰月 戊午日 农历三月十六\n今天是非常高兴的一天因为我们迎来了团子🎉(‘ω’)🎉\n休息休息晚安"},"Personal/Journal/2024/W22/2024-06-02":{"title":"2024-06-02","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周日 23:08甲辰龙年 己巳月 丁酉日 农历四月廿六郑州 +26°C ☀️🌘\n📖 Daily\n藕花珠缀犹似汗凝妆。——阎选五代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n\n商丘—郑州长途驾驶很棒哦。\n去公司处理点事也很不错。\n简单打扫卫生✌\n\n📝 Notes\n这周浑浑噩噩的过了周末去拜访了小雅长辈一切顺利(≖_≖✌)。\n新的一周要合理安排继续规划\n冲冲冲💪💪💪"},"Personal/Journal/2024/W22/2024-W22":{"title":"2024-W22","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 15:41甲辰龙年 己巳月 戊戌日 农历四月廿七郑州 +33°C ☀️🌘\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy忙完一件是一件五月份是躺平而又充实的一个月。😢 Sad😡 Angry😔 Disappointed😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records5一般一般自己做饭的次数不是太多Exercise log3锻炼次数不多但是有进步Sleep log5睡眠质量一般一般把Hydration7喝水倒是已经养成了非常好的习惯Mental Relaxation2需要学会放松\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription修正了开发的思维定式转向云开发待开始以后切换至 cloud ide 进行开发工作\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution运动健身未开始没有养成习惯恢复开始三一计划睡眠质量开始需要进一步优化睡眠条件尽可能的提高睡眠质量\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationRHCSA/RHCE 考试8 周英语学习♾️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation网络规划师22 周面试准备4 周\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客写作♾区块链、虚拟币学习♾\n📝 Notes\n本周已经复盘不再进行总结。\n未来安排及计划如上具体的工作规划结合实际情况。\n学习分配以工作外时间为主工作内时间为辅助。\n继续冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others6期待新的一周"},"Personal/Journal/2024/W23/2024-06-03":{"title":"2024-06-03","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 23:04甲辰龙年 己巳月 戊戌日 农历四月廿七郑州 +25°C ☀️🌘\n📖 Daily\n一番荷芰生池沼槛前风送馨香。——尹鹗五代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n\n今天有做好本职工作\n执行力很强\n向领导汇报\n\n📝 Notes\n今天周一客观来说没有干太多事情还是有点无所事事。\n本质原因还是日志的丢弃导致有点无所事事……\n明天初步计划早上阅读完 rss 就开始学习英语,下午学习 linux然后根据实际情况写博客。\n总之还是要捡起子弹笔记和计划调整不然所有的一切都很容易荒废。\n还有就是饮食和运动计划早睡早起锻炼身体吃好喝好开心不少。\n明天好好调整一下继续冲"},"Personal/Journal/2024/W23/2024-06-04":{"title":"2024-06-04","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 23:19甲辰龙年 己巳月 己亥日 农历四月廿八郑州 +24°C ☀️🌘\n📖 Daily\n一番荷芰生池沼槛前风送馨香。——尹鹗五代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n练习英语\n外出散步\n摸索新方向\n📝 Notes\n今天最大的成果就是解决了目前短期干啥短期就是深入的学习各大云服务厂商的文档和产品然后考 RHEL 并最后考试软考。\n目前大致就是这样一个台阶一个台阶的来。\n该睡啦明天继续晚安。"},"Personal/Journal/2024/W24/2024-06-12":{"title":"2024-06-12","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周三 23:07甲辰龙年 庚午月 丁未日 农历五月初七郑州 +33°C ☀️🌓\n📖 Daily\n荷风送香气竹露滴清响。——孟浩然唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n多喝水\n多行动\n多朋友\n📝 Notes\n经过两天时间终于是恢复过来了这次出去玩很赞的一次\n不过目前也需要调整好以及进一步的学习和提升了。冲冲冲\n明天规划一下学习还有成考的事情然后收拾一下残局尽可能的开始战斗\n加油💪"},"Personal/Journal/2024/W24/2024-W24":{"title":"2024-W24","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 11:10甲辰龙年 庚午月 壬子日 农历五月十二郑州 +25°C ☀️🌔\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy感冒总算是快好了开心😢 Sad每次总是莫名其妙的吵架……😡 Angry老妈为什么总喜欢把家里搞得像猪窝……😔 Disappointed😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records3还行吧老妈在家都是买着吃的Exercise log2感冒了没有怎么运动这周恢复起来Sleep log5感觉心宽了怎么睡都会很爽反正挺不错的 ~Hydration7每天都在好好喝水Mental Relaxation1周日和朋友一起 BBQ 聊天了~\n⏭ Next Steps\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime AllocationRHCSA/RHCE 考试8 周英语学习♾️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation网络规划师22 周面试准备4 周\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客写作♾区块链、虚拟币学习♾\n📝 Notes\n24周不能说是浪费掉的一周一方面是身体恢复的一周一方面是调整策略的一周整体来说为了未来几个月提供了基础一些主要的学习计划尽快的落实并且实行。\n未来的 10 周20周应该是充实并且忙碌的一段日子继续冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others5新的一周继续冲冲冲"},"Personal/Journal/2024/W29/2024-W29":{"title":"2024-W29","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周日 19:57甲辰龙年 辛未月 丙戌日 农历六月十六郑州 +35°C ⛈🌕\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy开心订婚啦 ~😢 Sad最近确实忙的身心疲惫不过已经休息恢复的七七八八了 ~😡 Angry😔 Disappointed😂 Laughing😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records2最近很懒早饭都是对付午饭和晚饭还行。Exercise log0没有怎么运动也确实需要多多运动了Sleep log5睡眠很不错几乎每天都在睡懒觉哈哈。Hydration5每天都在疯狂喝水 Mental Relaxation0目前唯一的娱乐方式还是刷手机哈哈。\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescriptionKVM 虚拟化已完成很棒,一周的时间完成了 KVM 虚拟化的学习和实践。\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution每天的日志总结未完成虽然每天的工作学习习惯早已养成但是日志还是不太习惯书写。每天还是尽可能的写日志。博客进行中博客的书写频率还是偏低懒得写还是不想写还是……尝试录音等多种方式保持文字输出。\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation阿里云 ACP 考试一周腾讯云 TCP 考试一周\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation网络规划师♾面试准备♾\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation博客写作♾\n📝 Notes\n整体来说这周的状态恢复的很快表现也不错值得鼓励继续前进\n未来几周是努力出成绩的几周一定要努力冲冲冲\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others6继续努力"},"Personal/Journal/2024/W30/2024-07-22":{"title":"2024-07-22","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 23:14甲辰龙年 辛未月 丁亥日 农历六月十七郑州 +30°C ☀️🌕\n📖 Daily\n藕花珠缀犹似汗凝妆。——阎选五代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n送了订婚喜糖\n又很好的完成了工作\n📝 Notes\n今天状态不错就是没有那么悠闲了。阿里云的 ACP 考试这周安排拿下了。\n今天也看书了整体来说恢复的不错。明天早起拿着电脑平板冲冲冲"},"Personal/Journal/2024/W30/2024-07-25":{"title":"2024-07-25","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周四 23:52甲辰龙年 辛未月 庚寅日 农历六月二十郑州 +27°C 🌦🌖\n📖 Daily\n雾露夜侵衣关山晓催轴。——吴均南北朝\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n清理卫生\n计算机存储方面的学习\n📝 Notes\n今天真的无敌气生活真的是一地鸡毛蒜皮。我也是真的非常之无奈\n不知道咋说了瞎几把过吧。\n晚安"},"Personal/Journal/2024/W33/2024-08-12":{"title":"2024-08-12","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周一 23:42甲辰龙年 壬申月 戊申日 农历七月初九郑州 +28°C ☀️🌓\n📖 Daily\n月明船笛参差起风定池莲自在香。——秦观宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n\n 速战速决,绝不拖延\n 早起吃好吃的😍\n\n📝 Notes\n不知道怎么了最近莫名其妙的烦躁不安。似乎过去的很多事情又席卷重来的困扰自己。\n最近也是躺平没有任何的总结复盘整体变得更加随性洒脱。\n领证啦但是并没有想象中的激动。但是却很真实的感觉到了充实的幸福。\n难说再见这个憋了好久的博文题目似乎很难提笔。我想写但是真的不知道如何开始第一句第一个字。\n从小学中学大学工作整体记一个流水账还是不管三七二十一写就完事了\n最近确实有点迷失但是却又能真真切切的感受到我来到了一个新的阶段。\n周中平加油为了幸福生活而去努力。"},"Personal/Journal/2024/W35/2024-08-31":{"title":"2024-08-31","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周六 02:09甲辰龙年 壬申月 丁卯日 农历七月廿八郑州 +29°C ☀️🌘\n📖 Daily\n多情为谢残阳意与展晴霞片片红。——佚名唐代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n\n重构 Wiki\n\n📝 Notes\n最近总是莫名其妙的就失眠了一切的一切也不知道是因为什么……\n我好像是有点累了也不知道如何休息才好也许就是累了……\n消磨时间然后睡觉码下一些文字 \n就这样了玩去了 🫤🫤🫤"},"Personal/Journal/2024/W40/2024-W40":{"title":"2024-W40","links":[],"tags":[],"content":"🗓️ Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周二 15:35甲辰龙年 甲戌月 乙巳日 农历九月初六郑州 +22°C ☀️🌒\n😊 Emotions\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEmotionReason or Trigger😊 Happy忙得也差不多了一直躺平的很开心哈哈。😢 Sad没有实质性的进步 or 成果,也确实不爽。😡 Angry没有什么太愤怒的事情比较愤怒的就是老妈不喜欢干净……😔 Disappointed人生总是充满着无奈😂 Laughing全民买股票倒是挺牛皮的哈哈😭 Crying😱 Scared\n🍎 Health\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTypeDays/CountDescriptionDiet records2没有好好做饭吃不能说没有好好吃饭。Exercise log0完全没有锻炼哈哈哈懒惰腹肌归来Sleep log0睡得还行不过没有早睡。Hydration5不喝水不行必须喝水Mental Relaxation2抖音精选让我继续快乐哈哈哈\n✅ What Went Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription躺平已完成躺平的很爽确实没啥说的。\n❌ What Didnt Go Well\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nChallenge/IssueProgressDescriptionPossible Solution没有彻底躺平已完成以后坚决玩的时候玩爽躺的时候躺平。一心一用不要纠结拧巴\n⏭ Next Steps\n⭐⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation1. 阿里云 ACP 云计算认证⏲2. 阿里云 OBCP 数据库认证⏲3. Linux RHCE 认证⏲️\n⭐⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation软考高级 - 网络规划师⏲25 面试准备工作⏲️\n⭐\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityTime Allocation区块链/虚拟币学习应用♾RSSKY 项目开发♾️\n📝 Notes\n临近 6 个月,最近 3 个月,主打一个躺平摆烂,主要感觉心力不足,无法多方面应对。\n生活中的许多事情倒是处理的不错工作学习中的很多事情全部摁下了暂停键终究是鱼与熊掌不可兼得舍得舍得\n工作\n工作方面依旧是老样子还有一个问题就是坚决舍弃任何在工作中创新付出的想法既然决定要走就铁定不要想着可能会留下。\n学习\n学习没有停止但是需要更多小而美的实践大而全的实践纯粹的理论学习无法更好的内化还是要更加倾向于多实践少理论。\n生活\n生活中方方面面确实做的非常不错几乎所有的精力也全都放在这上面了。还有三个月就是新的一年了最后一个季度更应该全身心的投入学习并且取得应有的成果\n生活就是一地鸡毛捡起扫干净然后再创造一地鸡毛。生活就应该瞎鸡巴乱过而不是整天纠结这纠结那的……\n感情\n平凡、安好既是大成。\n健康\n说实话健康真的是非常需要拾起的一方面。\n自从毕业后几乎没有高强度的体育运动躺平长肉哈哈。\n多运动健康工作 50 年!\n总结\n无论是摆烂也好躺平也罢。目前对于我来说线性的发力进步似乎是不可行的事情。辩证的看待停下来也是为了更好的前进。\n但是但是但是最重要的事情就是纯粹一些玩就是好好玩学就是好好学不要为明天而忧虑更不要为昨天而怠慢。\n纯粹一些尽力做好自己该做的就可以同时也别忘了多运动\n📊 ThisWeeks Overview\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others2未来继续努力很棒"},"Personal/Journal/2024/W41/2024-10-09":{"title":"2024-10-09","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon周三 23:55甲辰龙年 甲戌月 丙午日 农历九月初七郑州 +23°C ⛅️🌓\n📖 Daily\n有三秋桂子十里荷花。——柳永宋代\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n🌟 Best Things\n早起做饭工作运动\n📝 Notes\n很不错哦🤓\n保持持续正反馈\n晚安 🌙"},"Personal/Journal/2024/W8/2024-02-22":{"title":"2024-02-22","links":[],"tags":[],"content":"📅 Info\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateWeatherMoon周四 21:13郑州 -1°C ☀️🌕\n📖 Daily\n衔霜当路发映雪拟寒开。——何逊南北朝\n😊 Emotions\n\n 😊 Happy\n 😢 Sad\n 😡 Angry\n 😔 Disappointed\n 😂 Laughing\n 😭 Crying\n 😱 Scared\n\n🍎 Habits\n\n 🌅 Early to bed, early to rise\n 🥕 Healthy eating\n ☕️ Drink more hot water\n 💪 Keep exercising\n 🧘‍♂️ Meditation\n\n📋 To-do List\n\n 📰 Read news\n 📖 Read a book today\n 📝 Make a plan for today\n 🖋️ Calligraphy practice\n 🎯 deliberate practice\n\n📝 Notes\n这两天状态很差劲明天周五这个周末好好的调整恢复一下。同时还有年终总结未来的规划都需要好好的做做下班回家"},"Professional/Company/数字化/规范/企业域名分配规范":{"title":"域名分配规范","links":[],"tags":["数字化/规范"],"content":"1. 引言\n1.1 背景\n随着全球企业数字化转型的加速推进信息技术IT已成为企业运营的核心驱动力。 从传统的本地数据中心逐渐向云计算、自动化和智能化转型,企业的 IT 基础设施变得更加复杂且灵活。在这一转型过程中,企业不仅需要处理大量的数据,还需要更高效的管理和维护其网络资源,以便在激烈的市场竞争中保持敏捷性和竞争优势。\n在现代化企业中云计算服务模型的广泛应用将企业的 IT 服务按需求划分为不同的层级。主要的云服务模型包括IaaSInfrastructure as a Service基础设施即服务、PaaSPlatform as a Service平台即服务*和*SaaSSoftware as a Service软件即服务。这三种模型为企业提供了不同层次的服务从基础的硬件资源到高级的软件应用各层次都具备灵活性和可扩展性。\n\nIaaS为企业提供虚拟化的计算资源包括服务器、存储和网络等。它允许企业像管理物理资源一样管理云端的基础设施但无需负责硬件的维护。\nPaaS在 IaaS 之上PaaS 为企业提供了开发和部署应用程序的平台,企业可以专注于应用程序的开发,而不需要管理底层基础设施。这极大地提高了应用开发的效率。\nSaaSSaaS 进一步抽象化直接向企业用户提供了完整的应用程序如办公套件、客户关系管理CRM系统等用户只需使用不需关注底层的维护。\n\n尽管这些服务模型为企业的 IT 运营带来了巨大的灵活性和效率,但它们也增加了系统管理的复杂性。企业在采用多层次云服务的同时,面临着如何有效管理其网络资源、应用程序和数据的挑战。尤其在企业规模扩展、资源多样化的情况下,合理规划并分配域名,确保各类服务、系统和应用之间的高效协作,显得尤为重要。\n域名分配不仅仅是企业外部访问的窗口它还影响着内部的资源组织、访问控制和网络结构的优化。在数字化企业中域名用于标识各种内部系统、应用程序、服务接口API以及不同部门或子公司的网络资源。因此设计和分配合理的域名系统是确保企业 IT 运营顺畅的重要环节。\n此外随着企业对云服务的依赖日益加深管理多层次、多类型的网络资源变得更为复杂域名分配问题逐渐凸显。例如当企业同时使用 IaaS、PaaS、SaaS 的服务时,若没有一套清晰且灵活的域名分配策略,不同服务之间的互通性和资源管理将变得混乱且低效。域名规划不仅仅需要解决技术层面的访问问题,还要为运维、开发、安全等多个团队提供清晰的逻辑结构和标准化的管理方式。因此,域名分配不仅是网络访问层面的技术问题,还是企业资源管理和内部运营效率提升的关键之一。\n1.2 目标\n本白皮书的目标是为现代化企业设计一套高效、灵活且安全的域名分配规范帮助企业更好地组织和管理其内部网络资源。通过这一规范企业可以在 IaaS、PaaS、SaaS 三层服务模型下,将复杂的 IT 资源进行逻辑化的分类与管理,确保不同层次的服务能够有效协作,同时提升内部系统的可管理性和可扩展性。\n具体而言本白皮书希望通过以下目标实现企业内部网络资源的优化\n\n高效管理通过系统化的域名分配企业可以更容易地管理其内部网络资源包括虚拟机、数据库、应用程序和用户终端。域名规划为各类资源提供了唯一且清晰的标识使得资源管理和访问控制变得更加直观和高效。\n灵活性考虑到企业 IT 环境的动态性,域名分配规范应具备足够的灵活性,以适应不断变化的需求。无论是新服务的上线、业务的扩展,还是技术的迭代升级,域名系统都应能够轻松调整,并且在不影响现有服务的情况下实现无缝扩展。\n一致性域名分配规范将确保企业内部所有 IT 服务和资源的命名遵循统一的标准。这不仅有助于跨部门、跨团队的沟通和协作,还能避免命名冲突、歧义或混乱,有效减少管理难度和运维成本。\n安全性在域名管理过程中安全性也是关键要素之一。通过明确的域名分配和命名规则企业可以更好地控制不同资源之间的访问权限防止未授权访问提升整体的网络安全性。同时合理的域名分配还能减少安全漏洞如 DNS 劫持、缓存中毒等风险。\n可扩展性随着企业业务的扩展和技术需求的变化域名分配系统应具备良好的可扩展性以支持未来的增长。无论是增加新的应用服务还是引入新的云计算模型如 Serverless、边缘计算等域名规范应能灵活适应并确保系统的稳定性和兼容性。\n\n通过建立这一套域名分配规范企业不仅能够提高其 IT 系统的管理效率,还能通过清晰的命名和分配策略确保各类资源的安全与可持续性。最终,这一白皮书将为企业在复杂的多层次云环境下,提供一套可行的解决方案,帮助企业优化其网络架构,提升业务运营效率,并保持技术和业务发展的灵活性。\n2. 域名分配的总体架构\n域名分配的总体架构是现代化企业内部网络资源管理的重要组成部分。一个清晰、系统的域名分配结构不仅能帮助企业高效管理复杂的 IT 基础设施,还能在不同层次上为服务的部署和维护提供明确的指引。通过构建合理的域名分层结构,企业能够在不同的业务场景中实现灵活、稳定和安全的访问控制。\n2.1 域名分层结构\n域名的分层结构是企业内部网络资源组织和命名的重要基础。通常企业内部的域名分层可分为一级域名、二级域名和三级域名这些层次共同构成了完整的命名体系用于区分和标识企业内的不同服务、应用和资源。\ngraph TD\n A[一级域名: 7wate.dev]\n \n A --> B[二级域名: compute.7wate.dev]\n A --> C[二级域名: storage.7wate.dev]\n A --> D[二级域名: network.7wate.dev]\n\n B --> B1[三级域名: dev.compute.7wate.dev]\n B --> B2[三级域名: prod.compute.7wate.dev]\n\n C --> C1[三级域名: backup.storage.7wate.dev]\n C --> C2[三级域名: archive.storage.7wate.dev]\n\n D --> D1[三级域名: vpn.network.7wate.dev]\n D --> D2[三级域名: cdn.network.7wate.dev]\n\n\n一级域名顶级域名TLD通常用于标识企业的网络边界。对于企业而言一级域名是最外层的标识用于区分企业与外界的网络访问。以企业 7wate 为例7wate.dev可以作为企业的顶级域名用于承载企业的所有内部网络服务。该域名是企业网络资源的根节点所有二级和三级域名都将以此为基础进行分配和管理。\n二级域名主要用于区分不同的服务类型或业务功能。通过将 IaaS、PaaS、SaaS 等云服务的不同模块划分为独立的二级域名,企业可以在逻辑上对服务进行分类和管理。例如,可以根据企业的 IT 服务模型对资源进行划分生成如compute.7wate.dev用于计算资源、storage.7wate.dev用于存储服务等域名。这种结构不仅简化了服务的标识和访问还为后续的三级域名提供了清晰的框架。\n三级域名用于进一步细化管理通常用于标识具体的子服务或业务模块。三级域名的引入允许企业在更复杂的场景下对资源进行精细化管理。比如企业在网络管理模块下可能会有多个子服务如 VPN 服务、内容分发网络CDN通过引入三级域名可以将这些子服务细分为vpn.network.7wate.dev、cdn.network.7wate.dev等。这种结构增强了域名的灵活性使得企业在扩展业务时能够轻松调整和增加服务。\n\n2.2 IaaS、PaaS、SaaS 三层服务模型下的域名分配\n现代企业的 IT 服务通常采用 IaaS、PaaS 和 SaaS 三层服务模型,每一层都有其独特的功能和特性,因此在域名规划上需要根据各层的特点进行合理划分。下面我们将详细说明每一层的域名分配策略。\nIaaS 层域名规划\nIaaS基础设施即服务为企业提供虚拟化的计算资源、存储资源、网络管理和安全服务。在 IaaS 层中,资源往往以基础设施为中心,域名规划需要反映这一特性,确保对基础设施资源的精细化管理。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n资源类型二级域名三级域名示例说明计算资源compute.7wate.devvm.compute.7wate.dev虚拟机管理用于管理虚拟机、容器化服务、裸金属服务器等计算资源。存储资源storage.7wate.devbackup.storage.7wate.dev数据备份存储资源包括对象存储、文件存储、块存储等。网络管理network.7wate.devvpn.network.7wate.devVPN 管理)用于管理 VPC、负载均衡、内容分发网络等网络资源。安全管理security.7wate.devfirewall.security.7wate.dev防火墙管理管理身份验证、访问控制、防火墙等安全服务。\nPaaS 层域名规划\nPaaS平台即服务主要用于支持应用开发、测试和部署的技术平台。这一层的域名分配应考虑到开发环境、运行时环境、容器编排和中间件服务等需求。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n资源类型二级域名三级域名示例说明应用开发与运行时app.7wate.devtest.app.7wate.dev测试环境用于管理应用开发与运行时环境包括开发、测试、生产环境。容器管理container.7wate.devk8s.container.7wate.devKubernetes 管理)管理 Kubernetes 或 Docker 容器化服务。数据库管理database.7wate.devsql.database.7wate.dev关系型数据库用于管理数据库服务区分关系型数据库和 NoSQL 数据库。中间件与消息队列middleware.7wate.devkafka.middleware.7wate.devKafka 队列)用于管理中间件和消息队列服务。\nSaaS 层域名规划\nSaaS软件即服务主要提供企业级的应用软件帮助企业实现办公协作、客户关系管理、资源规划等功能。SaaS 层的域名规划应关注应用的最终用户,并确保每个应用有明确的域名标识。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n资源类型二级域名三级域名示例说明办公协作collab.7wate.devemail.collab.7wate.dev电子邮件服务办公协作服务包括电子邮件、文档共享、视频会议等。客户关系管理CRMcrm.7wate.devsales.crm.7wate.dev销售管理管理销售、客户支持和营销服务。企业资源规划ERPerp.7wate.devfinance.erp.7wate.dev财务模块ERP 系统管理涵盖财务、供应链、制造、采购等领域。人力资源管理系统HRMShrms.7wate.devpayroll.hrms.7wate.dev薪资管理管理人力资源流程涵盖员工档案、薪酬福利等。财务与会计管理finance.7wate.devbilling.finance.7wate.dev账单管理用于管理企业财务与会计流程。项目管理project.7wate.devtracking.project.7wate.dev项目进度追踪管理项目进度和任务分配。电子商务管理ecommerce.7wate.devcatalog.ecommerce.7wate.dev产品目录管理管理电子商务平台的产品目录和订单处理。\n三级域名的引入在复杂服务下细分子服务的命名规则\n随着企业 IT 基础设施的复杂化,仅靠一级域名和二级域名无法完全涵盖企业的多层次、多业务模块需求。因此,三级域名的引入成为细分和管理子服务的有效手段。通过在二级域名下进一步引入三级域名,企业可以对每个独立的子服务进行更精准的管理,同时保持命名的结构化和逻辑性。\n三级域名允许企业在现有的域名层次结构中细化管理同时为未来的业务扩展留有足够的灵活性。以下是三级域名的几种常见使用场景\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n场景二级域名三级域名示例说明服务细分network.7wate.devvpn.network.7wate.devVPN 服务)用于细分网络管理下的不同服务,如 VPN 和 CDN。环境区分app.7wate.devtest.app.7wate.dev测试环境用于区分应用的不同运行环境如开发、测试、生产。多业务模块支持erp.7wate.devfinance.erp.7wate.dev财务模块ERP、CRM 等系统的多业务模块支持。地域或数据中心区分compute.7wate.devus-east.compute.7wate.dev美国东部数据中心用于区分不同地理区域或数据中心的资源。\n引入三级域名的好处在于它不仅能够有效提升网络资源的组织结构还为企业的未来扩展留有充分的空间。随着企业业务的发展新的服务、新的模块、新的地理区域可能不断加入而通过三级域名的方式企业可以灵活地将这些新元素纳入现有的网络体系中确保网络结构的可扩展性。\n3. 域名分配规范原则\n在现代化企业中域名分配不仅仅是技术层面的操作它承载了网络资源的组织、访问路径的设计以及各个业务模块之间的交互。一个高效且规范的域名分配策略能够有效提高资源管理的效率简化跨部门和跨团队的协作并为未来的扩展留有余地。因此制定一套合理的域名分配规范原则至关重要。\n3.1 一致性原则\n域名的命名规则必须具有一致性这样可以确保企业内不同部门、不同团队之间的理解没有歧义。一致性原则的核心在于同一类服务或资源在任何场景下都应遵循相同的命名规范无论是一级域名、二级域名还是三级域名。\n一致性不仅有助于减少误解和混淆还能够提升管理的简便性。举例来说在一个跨部门的协作项目中开发团队和运维团队如果使用不一致的命名规则可能会导致资源访问不便、出错率增高。因此企业应在域名分配时制定统一的命名模板涵盖不同服务类型和资源类型。\n举例\n\n所有的开发环境域名以 dev. 开头(如 dev.app.7wate.dev。\n生产环境则统一以 prod. 开头(如 prod.app.7wate.dev。\n\n通过这样统一的命名标准任何团队在面对不同环境时都能清晰分辨服务类型避免因命名混淆导致的误操作。\n3.2 简洁性与可读性\n域名的简洁性与可读性是另一个重要的设计原则。一个简洁、易读的域名不仅能减少用户输入时的错误还能提高对资源的辨识度。域名设计应避免过长、冗余的命名结构确保域名在视觉上清晰易懂同时能够直观地反映出其所指代的资源或服务类型。\n在设计域名时企业需要找到简洁性与信息量之间的平衡。虽然过于简短的域名可能显得抽象和模糊但过长的域名则会造成复杂性增加降低可读性。因此域名应简洁明了且足够传递必要的含义。\n良好的例子\n\napi.dev.7wate.dev通过简短的 api能够清晰传达出其服务的类型为应用编程接口API并通过 dev 标识这是开发环境。\n\n不良的例子\n\napplicationinterface.development.environment.7wate.dev虽然表达的信息完整但过于冗长增加了访问难度且降低了可读性。\n\n简洁性与可读性的重要性在于其对日常管理的影响。管理员在处理大量域名时一个简明的结构可以大幅减少管理成本提高工作效率同时便于系统自动化工具如 DNS 管理工具)的使用和部署。\n3.3 灵活性与扩展性\n企业的 IT 系统和业务需求随着时间的推移而不断变化,域名分配策略必须具有足够的灵活性和扩展性,才能适应未来的技术和业务发展。这意味着域名结构不仅要适应现有的需求,还必须为未来可能引入的新服务、新技术做好准备。\n在设计域名时尤其要考虑到新兴技术的发展趋势。例如随着Serverless 架构和边缘计算的普及,传统的域名分配方式可能无法很好地支持这些新架构。因此,企业应预留足够的灵活性来容纳这些新服务,并通过合理的命名结构确保可扩展性。\n举例\n\n在 Serverless 架构下函数即服务FaaS可以使用 function. 前缀,如 function.compute.7wate.dev。\n在边缘计算场景中可以通过引入地域标识如 us-west.edge.7wate.dev表示美国西部的边缘节点确保地域性资源与其他资源的区分。\n\n此外在多云环境中企业可能同时使用多个云服务提供商的资源。通过在域名中引入云提供商的标识如 aws.、azure. 等前缀可以有效区分不同平台上的资源提升资源管理的灵活性。例如aws.compute.7wate.dev 和 azure.compute.7wate.dev 可分别指代 AWS 和 Azure 上的计算资源。\n3.4 简拼与全拼的使用规范\n在域名设计中企业可能会使用全拼和简拼两种方式命名不同的资源。全拼通常能够提供更高的信息透明度用户一目了然可以判断出资源类型。而简拼则更为简短便于记忆和快速输入尤其适用于操作频繁的场景。然而简拼的使用必须遵循明确的规范以防止跨部门、跨团队的理解混淆。\n简拼与全拼的使用规范应考虑以下几个要点\n\n明确简拼和全拼的使用场景一般来说重要的、核心的服务可以使用全拼来增强可读性而次要或频繁使用的服务可以考虑简拼。例如database.7wate.dev 清晰表明是数据库服务,而 db.7wate.dev 可以用于更高频的场景下快速访问数据库资源。\n提供简拼表和常用缩写对照表企业应制定统一的简拼缩写对照表明确哪些服务可以简拼如何简拼。例如app 可以代表应用程序Applicationdb 可以代表数据库Databasenet 可以代表网络服务Network。这种标准化的对照表可以避免由于部门各自命名而造成的命名混乱。\n避免歧义有些简拼可能在不同场景下具有不同的意义例如 app 既可以代表应用程序也可能代表某些特殊业务名称。因此在简拼的设计中必须确保不会引发歧义。通过明确的规则和命名前缀可以有效避免这类问题。例如在应用程序上下文中app.7wate.dev 代表应用服务,而在业务流程中,可能使用 businessapp.7wate.dev 表示某一特定的应用。\n\n简拼与全拼的应用示例\n\ndatabase.7wate.dev 与 db.7wate.dev前者全拼清晰表明为数据库服务适用于文档、管理界面等场景后者适合频繁查询和操作。\napplication.7wate.dev 与 app.7wate.dev全拼用于正式的、面向管理层或广泛用户的场景简拼适用于开发人员或内部使用。\n\n通过全拼和简拼的结合使用企业既可以保持命名规则的简洁性又不失可读性。为了确保命名规则的一致性和规范化企业应建立一个专门的简拼/全拼管理制度,并定期审查以适应不断变化的业务需求和技术环境。\n4. 域名分配的实施策略\n在一个现代化企业中域名分配不仅需要一套清晰的规划和规范还需要通过合理的实施策略来确保系统的安全性、可扩展性以及管理的高效性。为了保证域名分配能够顺利支持企业的日常运营和业务扩展实施过程中必须考虑到 DNS 解析、扩展性、安全性以及自动化管理等多个方面。以下将详细讨论域名分配的具体实施策略。\n4.1 本地 DNS 解析与管理\n本地 DNS 解析Local DNS Resolution是指企业在内部设置并管理自己的 DNS 服务器,用于解析企业内部资源的域名。与使用外部公共 DNS 服务器相比,本地 DNS 解析可以提供更快的响应速度、更多的控制权以及更高的安全性,特别是在处理内部网络流量时。\n优点\n\n性能提升通过本地 DNS企业内部域名的解析速度明显加快因为请求不需要通过互联网路由到外部 DNS 服务器。对于频繁使用的域名,尤其是与内部资源相关的服务(如数据库、内部应用系统等),本地 DNS 解析能够有效减少网络延迟,提高访问效率。\n更高的控制权使用本地 DNS 服务器,企业可以完全掌控域名解析规则和策略。例如,可以通过本地 DNS 实现访问控制、流量监控和内部域名分配。企业还可以根据具体业务需求,灵活地修改域名解析的记录,确保内部网络资源的最佳分配。\n安全性提升通过本地 DNS 解析,企业能够保护其网络流量,避免 DNS 请求暴露给外部 DNS 服务器,这能够减少潜在的攻击面。同时,企业能够使用防火墙、入侵检测系统等工具来监控和防护 DNS 服务器,确保内部网络的安全性。\n\n本地 DNS 管理策略:\n\n内部域名的集中管理企业可以通过设置一个或多个本地 DNS 服务器来集中管理所有内部域名。这种集中化的管理方式不仅简化了运维流程,还能通过一站式配置解决域名冲突和解析问题。\n缓存机制本地 DNS 服务器可以对频繁请求的域名进行缓存从而减少外部查询的频率提升解析速度。合理设置缓存时间TTL, Time To Live可以在提高性能的同时确保域名解析的准确性和及时性。\n\n4.2 DNS 扩展性设计\n随着企业规模的扩大尤其是多地域、多数据中心的部署DNS 的扩展性设计变得至关重要。扩展性确保 DNS 能够支持更多的流量、更复杂的服务以及分布式的基础设施,同时不会影响性能和安全性。\n多数据中心的 DNS 设计: 在多数据中心环境下DNS 必须能够处理来自不同地理区域的流量,并确保每个区域都能高效解析域名。常见的设计方案包括混合 DNS和云 DNS。\n\n混合 DNS混合 DNS 是指本地 DNS 和公共 DNS 服务相结合的一种解决方案。在这种设计下,企业可以将内部的解析请求通过本地 DNS 处理,而外部请求则通过公共 DNS如 AWS Route 53、Google Cloud DNS 等)处理。这种方式能够同时享受到本地 DNS 的快速响应和公共 DNS 的全球覆盖能力。\n云 DNS对于跨国运营的企业云 DNS 服务提供了全球范围的域名解析服务。云 DNS 能够自动根据用户的地理位置将请求路由到最近的数据中心提高跨区域的访问速度。例如地理负载均衡Geo Load Balancing能够根据用户位置自动选择最近的服务器减少延迟并提高服务可用性。\n\n跨区域、多云环境下的 DNS 管理策略:\n\n多云环境的 DNS 策略:在多云环境中,不同的云提供商提供的服务可能需要独立的 DNS 配置。企业可以通过设置独立的域名或子域来管理不同云平台的资源,例如 aws.compute.7wate.dev 和 azure.compute.7wate.dev 分别指向 AWS 和 Azure 上的计算资源。通过这种方法,企业能够灵活地管理多云环境中的域名解析,避免平台之间的冲突。\n冗余与容错为了确保 DNS 的高可用性,企业可以采用冗余的 DNS 架构。在每个数据中心或云平台中部署多个 DNS 服务器,确保在某一服务器故障时,其他服务器能够继续提供解析服务,从而提高系统的容错性。\n\n4.3 安全性考虑\nDNS 作为互联网的基础服务之一,长期以来一直是攻击的目标,尤其是对企业内部网络而言,确保 DNS 安全至关重要。安全性主要体现在防止恶意攻击、数据篡改和未经授权的访问。\n常见的 DNS 安全威胁:\n\nDNS 缓存中毒DNS Cache Poisoning攻击者通过向 DNS 缓存注入伪造的解析记录,使得用户请求被重定向到恶意网站。为了防止这种攻击,企业应确保本地 DNS 服务器的安全配置,定期清理缓存并使用可信的上游 DNS 服务器。\nDNS 劫持DNS 劫持是一种攻击方式,攻击者通过篡改 DNS 记录,将合法流量重定向到虚假网站。防止 DNS 劫持的关键在于对 DNS 服务器的安全性加强保护,并引入加密和签名技术。\n\n安全措施\n\nDNSSEC域名系统安全扩展DNSSEC 是一种安全扩展协议,允许 DNS 响应中的数据进行数字签名,从而防止 DNS 记录被篡改或伪造。企业可以在本地 DNS 服务器上部署 DNSSEC确保域名解析的安全性。通过验证签名DNSSEC 可以有效防止缓存中毒和 DNS 劫持等常见攻击。\n入侵检测系统为了防止 DNS 服务器被攻击企业可以部署入侵检测系统IDS实时监控 DNS 服务器的网络流量,检测异常的请求和潜在的攻击行为。通过结合防火墙和 IPS入侵防御系统企业能够更好地保护其 DNS 基础设施。\n访问控制与监控企业应设置严格的访问控制策略确保只有授权的用户和系统能够修改 DNS 配置。定期对 DNS 服务器的日志进行审查,及时发现并修复潜在的安全漏洞。\n\n4.4 自动化域名管理工具\n随着企业业务的增长手动管理大量的域名和 DNS 配置将变得非常复杂且低效。因此,自动化工具的引入可以显著提升域名管理的效率,减少人为错误的发生,并加快变更的实施速度。\n自动化工具的应用\n\nAnsible、Terraform 等自动化工具这些基础设施即代码Infrastructure as Code, IaC工具可以帮助企业自动化管理和部署 DNS 记录。通过配置代码,企业可以轻松地创建、更新和删除 DNS 记录。例如,使用 Terraform 脚本可以自动生成 DNS 配置文件并部署到 DNS 服务器中,从而避免手动配置时的重复性工作和错误。\nCI/CD 工具与 DNS 集成:现代化的 DevOps 流程可以通过 CI/CD 工具自动化域名的配置和更新。在每次应用部署时CI/CD 流水线可以自动生成相应的 DNS 记录,并将其更新到本地或云 DNS 服务器中。例如当应用的运行环境或域名需要修改时CI/CD 工具可以自动执行更新,确保 DNS 配置与应用部署保持一致。这不仅提升了管理效率,还减少了因手动操作引发的错误。\n\n自动化域名管理的优点\n\n快速响应业务需求在自动化工具的支持下企业可以根据业务变化快速创建和更新域名解析记录无需手动干预。这种方式不仅能够加快新服务的上线速度还能够灵活应对技术变革。\n降低人为错误自动化配置减少了手动操作的环节从而降低了因操作失误导致的域名解析错误。通过精确的自动化脚本所有的变更都可以提前测试并通过版本控制系统进行跟踪和审查确保配置的可靠性。\n\n5. 未来技术趋势与域名规划的扩展\n随着企业技术架构的快速演变域名规划的方式必须灵活适应新的技术趋势。无服务器架构Serverless、边缘计算Edge Computing以及多云策略的广泛应用给传统的域名管理带来了新的挑战和机遇。为了确保未来的技术发展能够得到充分支持企业需要在域名规划中做出前瞻性的布局。以下将详细探讨在这些新兴技术环境下如何设计灵活的域名体系来应对未来的发展需求。\n5.1 无服务器架构Serverless域名规划\n无服务器架构Serverless是一种新兴的计算模型在该模型中开发人员无需管理底层服务器或基础设施而是将计算资源的管理交由云服务提供商。Serverless 应用通过按需执行来处理任务常见的应用包括云函数Function as a Service, FaaS和事件驱动的微服务架构。由于 Serverless 架构不依赖固定的服务器或虚拟机,域名规划必须能够灵活应对动态的资源调用和自动扩展的服务。\n域名规划策略\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n规划策略示例域名说明专用二级域名serverless.7wate.dev为无服务器应用设计专用的二级域名确保与传统服务的命名空间隔离。事件驱动的子域名结构upload.serverless.7wate.dev处理文件上传的无服务器函数基于事件类型创建子域名。process.serverless.7wate.dev处理数据处理事件的函数。动态扩展与命名约定v1.dev.serverless.7wate.dev支持不同版本和环境的动态扩展如开发环境中的 v1 版本。prod.serverless.7wate.dev用于生产环境的无服务器应用。\n无服务器架构的优势在于其高度自动化和动态扩展的能力因此域名规划必须灵活适应这种动态性确保每个服务调用都能快速、精准地对应到相应的资源。\n5.2 边缘计算Edge Computing域名规划\n边缘计算Edge Computing是在网络边缘处理数据的技术特别适用于低延迟、高带宽需求的应用场景如物联网IoT、实时数据处理和视频流传输。在边缘计算环境中设备通常分布在地理上分散的多个位置传统的集中式计算无法有效满足这些设备的需求。因此域名规划必须考虑如何有效地管理分布在不同地理区域、数据中心和网络边缘节点的资源。\n域名规划策略\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n规划策略示例域名说明地理区分的二级域名us-west.edge.7wate.dev表示位于美国西部的边缘计算节点便于地理位置区分。eu-central.edge.7wate.dev表示位于欧洲中部的边缘节点或数据中心。设备类型的细分sensor1.us-west.edge.7wate.dev标识位于美国西部的传感器设备便于设备类型和地理位置的管理。gateway.eu-central.edge.7wate.dev标识位于欧洲中部的边缘网关设备。IoT 设备的域名分配device123.iot.edge.7wate.dev根据设备 ID 生成唯一的域名适用于大规模物联网设备的标识和管理。camera1.edge.7wate.dev用于标识摄像头设备确保物联网设备有唯一的域名。\n由于边缘计算节点的部署是动态且分散的域名规划应预留足够的空间以适应设备的大规模增长和地理分布的变化。\n5.3 多云策略下的域名管理\n随着企业逐渐采用多云策略即同时使用多个云服务提供商的资源域名管理面临新的挑战。不同云平台上的资源需要在命名上加以区分同时又要保持一致的管理方式以避免管理的混乱。通过设计合理的域名结构企业能够有效地组织和管理多云环境中的资源并提高不同云平台之间的互操作性。\n域名规划策略\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n规划策略示例域名说明云提供商区分的二级域名aws.compute.7wate.dev标识 AWS 上的计算资源便于区分不同云提供商的资源。gcp.compute.7wate.dev标识 Google Cloud 上的计算资源。跨云服务的命名一致性aws.database.7wate.dev标识 AWS 上的数据库服务保持多云平台的命名结构一致。azure.database.7wate.dev标识 Azure 上的数据库服务。多云资源的自动化管理terraform.aws.compute.7wate.dev使用自动化工具如 Terraform管理 AWS 上的计算资源的域名配置。ansible.gcp.compute.7wate.dev使用 Ansible 管理 Google Cloud 上的计算资源的域名配置,确保配置一致性。\n在多云环境下企业可以通过域名冗余实现高可用性。使用多个云服务提供商的域名配置确保当一个云平台的资源不可用时流量可以无缝转移到另一个平台。例如通过配置 failover.aws.compute.7wate.dev 和 failover.azure.compute.7wate.dev确保服务的高可用性。\n6. 域名管理的最佳实践\n为了确保企业在域名管理方面具备良好的组织性、可操作性和一致性必须制定一套完善的最佳实践。这些实践不仅能够有效规范域名的命名、分配、生命周期管理还能提升跨部门的协作和沟通效率。通过这些措施企业可以确保域名资源的长期可用性、减少管理中的冲突和错误并为未来的扩展做好准备。\n6.1 域名命名的标准化流程\n域名命名的标准化是确保一致性和易管理的基础。一个清晰、合理的域名命名流程可以帮助企业减少混淆避免命名冲突并确保所有部门和团队对命名规则有统一的理解。\ngraph LR\n A[确定域名结构] --> B[制定命名规则]\n B --> C[审批与变更管理流程]\n C --> D[版本控制与变更记录]\n\n A --> A1[一级域名:如 7wate.dev]\n A --> A2[二级域名:如 app.7wate.dev]\n A --> A3[三级域名:如 db.7wate.dev]\n\n B --> B1[服务类型:如 prod., dev., test.]\n B --> B2[地域:如 us., eu.]\n\n C --> C1[申请表单标准化]\n C --> C2[命名规则审核]\n C --> C3[审批通过后注册]\n\n D --> D1[使用 Git 记录变更]\n D --> D2[确保追踪历史记录]\n\n标准化流程的步骤\n\n确定域名结构首先明确域名的层次结构通常包括一级、二级和三级域名。一级域名通常是企业的根域名如 7wate.dev二级和三级域名根据服务类型、部门、地域等进行分类。这种结构应满足企业内部资源管理的需求并具备灵活性以应对未来的扩展。\n\n例如app.7wate.dev 用于应用服务db.7wate.dev 用于数据库服务。\n\n\n制定命名规则确定域名的命名规则包括哪些服务使用全拼哪些使用简拼如何处理不同服务、环境如开发、测试、生产和地域的命名。例如可以使用 prod.、dev. 或 test. 前缀区分环境,使用 us. 或 eu. 区分地域。\n\n示例prod.api.us-west.7wate.dev美国西部生产环境的 API 服务)和 test.db.eu-central.7wate.dev欧洲中部测试环境的数据库服务。\n\n\n审批与变更管理流程为了确保命名规范的一致性域名的分配与修改需要经过审批流程。所有新域名的申请、命名规则的更新、域名的回收都应通过明确的审批流程进行。变更管理流程应包括\n\n域名申请表单的标准化记录申请的理由、命名方案和预期用途。\n审批人如网络管理员、运维经理对域名的命名是否符合标准化规则的核查。\n审批通过后域名的注册和变更记录归档以便未来追溯和管理。\n\n\n版本控制与变更记录在大规模的企业中域名的变更必须通过版本控制系统如 Git 等)记录。每次域名分配、修改或删除的操作都应有详细的变更记录,确保所有操作都有历史记录可追踪。这样不仅有助于问题排查,也能提升管理的透明度。\n\n命名流程的效果 通过标准化流程,企业能够实现跨部门、跨团队的一致性,减少误解或错误。同时,制定审批流程确保了命名规范和变更管理的透明性,减少不必要的命名冲突,并能够对未来的域名规划进行系统性调整。\n6.2 域名生命周期管理\n域名的生命周期管理是确保域名资源合理分配、有效使用和及时回收的重要措施。企业的域名从创建到废弃经历多个阶段每个阶段都需要清晰的管理流程和监控机制。\ngraph LR\n A[域名的创建] --> B[域名的使用]\n B --> C[域名的修改]\n C --> D[域名的废弃]\n\n A --> A1[分配新域名]\n A1 --> A2[如 api.7wate.dev]\n A2 --> A3[经过审批后创建]\n\n B --> B1[持续监控使用情况]\n B1 --> B2[使用 DNS 解析日志、流量监控]\n B2 --> B3[确保访问频率与性能]\n\n C --> C1[调整域名以反映新用途]\n C1 --> C2[标准化变更管理]\n C2 --> C3[更新配置文件]\n\n D --> D1[域名进入停用期]\n D1 --> D2[回收或删除域名]\n D2 --> D3[更新 DNS 记录]\n D3 --> D4[如 project1.dev.7wate.dev 废弃]\n\n域名生命周期的阶段\n\n域名的创建在企业内需要新资源或新服务时首先根据命名标准和业务需求分配新的域名。在域名创建阶段必须遵循标准化流程确保命名符合企业命名规则并进行审批。\n\n例如开发团队需要为新上线的 API 服务申请域名 api.7wate.dev经过审批后正式创建。\n\n\n域名的使用在域名的使用阶段企业应持续监控其使用情况确保资源的合理利用。监控工具如 DNS 解析日志、网络流量监控)可以帮助跟踪域名的访问频率和性能,确保服务的可用性。\n\n通过工具监控 api.7wate.dev 的流量,确保其响应时间符合业务需求,并检测异常访问。\n\n\n域名的修改当服务调整、资源转移或架构升级时可能需要对域名进行修改。例如将服务从开发环境迁移到生产环境时需要修改域名以反映新的用途。在这种情况下域名的修改必须通过标准化的变更管理流程确保所有相关方都知悉变更并同步更新相关配置文件。\n域名的废弃当服务不再使用时应及时将相关域名回收。废弃的域名需进入停用期确保不会误删有效的服务。停用期结束后域名可以重新分配或完全删除。回收的域名需在管理系统中标记为废弃并更新相关的 DNS 记录,防止继续解析。\n\n例如某个项目结束相关的域名 project1.dev.7wate.dev 应该进入停用状态,相关的 DNS 记录也应被移除。\n\n\n\n域名生命周期监控工具 为了确保资源的有效利用,企业应使用专门的监控工具(如 Nagios、Zabbix 或自定义脚本)来跟踪域名的状态、性能和使用情况。这些工具可以提供实时的数据,帮助运维团队及时发现未使用的或被滥用的域名资源,确保资源优化利用,并通过定期审查报告判断是否有废弃域名需要回收。\n6.3 跨部门沟通与培训\n在企业中域名不仅是技术团队的关注点也与业务部门、产品团队密切相关。为了确保域名规划的有效执行跨部门的沟通与培训是关键的一环。\ngraph TD\n subgraph 跨部门沟通建议\n A[建立跨部门的沟通机制] --> B[技术与业务的双向沟通]\n B --> C[透明化的审批流程]\n A1[业务部门提前通知IT] --> A\n B1[技术团队解释命名规则] --> B\n B2[业务部门反馈命名合理性] --> B\n C1[定期沟通会或邮件通知] --> C\n end\n \n subgraph 培训计划\n D[域名管理培训] --> E[简拼缩写的使用规范]\n E --> F[持续性学习与更新]\n D1[培训内容包括命名规则、申请与审批流程] --> D\n E1[提供简拼与全拼对照表] --> E\n F1[定期更新域名命名规则] --> F\n F2[确保掌握最新域名管理标准] --> F\n end\n\n跨部门沟通建议\n\n建立跨部门的沟通机制确保 IT 部门与业务部门之间的紧密协作。例如,业务部门在规划新服务时,应该提前通知 IT 部门,确保域名能够合理分配,并为即将上线的服务做准备。域名命名和分配需要业务部门的参与,以确保命名符合业务目标并具有实际意义。\n技术与业务的双向沟通技术团队应向业务部门解释域名命名和分配的标准和规则确保业务部门理解其重要性。同时业务部门也应向技术团队反馈命名方案的合理性确保域名命名符合产品需求和用户体验。\n透明化的审批流程通过透明的域名申请与审批流程业务团队能够清楚了解域名分配的状态和审批进度。技术团队应通过定期的沟通会或邮件通知向业务部门汇报域名管理的状态与进展。\n\n培训计划\n\n域名管理培训所有相关团队如开发、运维、产品和安全团队应接受关于域名管理的基本培训。培训内容应包括域名命名规则、申请与审批流程、如何监控和维护域名以及简拼缩写的使用规范。\n简拼缩写的使用规范由于不同部门可能对简拼和全拼的理解存在差异培训应明确简拼的使用场景和规则。提供统一的简拼对照表并通过实例演示如何正确使用简拼和全拼。例如app.7wate.dev 代表应用服务,而 db.7wate.dev 代表数据库服务,这些命名规则必须在培训中详细解释。\n持续性学习与更新随着企业的业务变化和技术更新域名管理的规范也会不断演进。因此企业应定期组织培训更新域名命名规则和管理流程并确保所有团队都能掌握最新的域名管理标准。\n\n培训效果的评估企业可以通过定期的反馈机制评估培训效果确保所有团队对域名管理有足够的理解和应用能力。通过内部问卷或测试评估培训效果及时调整培训内容确保培训能够跟上技术和业务需求的变化。\n7. 企业 A 实例分析\n在企业的日常运营中域名规划和分配起到了至关重要的作用。通过合理的域名规划企业可以更高效地管理其内部资源优化 IT 基础设施,提升运营效率。本节将通过实例分析和常见问题的讨论,深入探讨企业在域名管理中面临的挑战及其解决方案。\n7.1 企业 A 的域名规划实例\n背景 企业 A 是一家全球性的互联网技术公司,拥有庞大的 IT 基础设施。企业 A 的业务涵盖多个领域包括云计算服务、电子商务、客户关系管理CRM和物联网IoT设备管理。为了确保各个业务模块的网络资源管理清晰、灵活并且可扩展企业 A 决定为不同的业务模块制定一套合理的域名规划体系。\n域名规划目标\n\n简化管理通过清晰的命名规范简化不同业务模块的资源管理确保不同部门能够快速识别和访问所需资源。\n支持全球部署企业 A 的业务遍布全球,因此需要域名体系能够反映不同地理区域的数据中心和服务节点。\n适应多云和边缘计算环境随着企业 A 逐步采用多云策略和边缘计算技术,域名规划必须支持这些新技术的发展和管理。\n安全性和一致性确保所有域名规划遵循统一的规则并且具备足够的安全性以应对网络攻击。\n\n域名规划示例\n企业 A 选择了其顶级域名 enterpriseA.com并根据不同业务模块、地域和服务类型划分二级和三级域名。\nIaaS 服务\n企业 A 的基础设施服务IaaS主要涵盖全球多个数据中心的计算、存储和网络资源。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n服务类型二级域名三级域名示例说明计算资源compute.enterpriseA.comus.compute.enterpriseA.com北美数据中心企业 A 的计算资源管理ap.compute.enterpriseA.com亚太数据中心存储资源storage.enterpriseA.comus-east.storage.enterpriseA.com美国东部存储企业 A 的存储资源管理eu.storage.enterpriseA.com欧洲存储网络资源network.enterpriseA.comvpn.network.enterpriseA.comVPN 服务)企业 A 的网络资源管理cdn.network.enterpriseA.comCDN 服务)\nPaaS 服务\n企业 A 为其开发团队提供了丰富的 PaaS 平台,支持应用开发、测试和运行。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n服务类型二级域名三级域名示例说明应用开发平台app.enterpriseA.comdev.app.enterpriseA.com开发环境支持应用开发、测试和生产环境prod.app.enterpriseA.com生产环境数据库管理db.enterpriseA.comsql.db.enterpriseA.com关系型数据库管理企业 A 的数据库服务nosql.db.enterpriseA.comNoSQL 数据库)\nSaaS 服务\n企业 A 提供的 SaaS 服务涵盖电子商务、CRM 和其他企业应用服务。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n服务类型二级域名三级域名示例说明电子商务平台ecommerce.enterpriseA.comus.ecommerce.enterpriseA.com北美电商平台管理企业 A 的电子商务平台eu.ecommerce.enterpriseA.com欧洲电商平台CRM 系统crm.enterpriseA.commarketing.crm.enterpriseA.com营销自动化管理企业 A 的 CRM 系统support.crm.enterpriseA.com客户支持\n优化效果\n通过这一域名规划体系企业 A 在以下方面取得了显著提升:\n\n提升管理效率每个服务和资源都有明确的域名运维团队能够快速识别并访问所需资源减少了查询和管理的复杂性。\n全球化支持通过引入地理标识企业 A 能够有效管理不同区域的服务节点,确保全球用户能够获得最佳的访问速度和服务质量。\n灵活的扩展性域名规划为多云环境和边缘计算的扩展预留了足够的灵活性随着业务增长企业可以轻松添加新的资源和服务而不会影响现有的命名体系。\n安全性提升通过严格的命名规则和统一的域名管理企业 A 减少了命名冲突,提升了网络安全性。\n\n7.2 域名分配中的常见问题\n尽管域名分配体系在现代企业中发挥着重要作用但在实际应用中企业仍然面临诸多挑战。以下列出了企业在域名分配中常见的问题及其解决方案。\n1. 命名冲突\n问题命名冲突是企业域名分配中的常见问题尤其是在大型企业中不同部门或团队可能会为相似的服务申请相同或类似的域名。这不仅会导致访问混淆还可能造成不必要的业务中断。\n解决方案\n\n标准化命名规则通过制定明确的命名规范确保每个域名都包含独特的标识符如地域、环境、功能等。引入标准化的审批流程确保所有新域名的申请都经过审查以防止重复命名。\n命名空间隔离在二级或三级域名中加入部门或服务前缀确保不同部门的服务在逻辑上独立。例如开发部门使用 dev.app.enterpriseA.com运维部门使用 ops.app.enterpriseA.com。\n\n2. 域名过长\n问题为了确保域名的独特性和可读性有时域名会变得过长导致输入不便、易于出错。这种情况在多层次的命名结构中尤为常见例如跨部门、跨地域的资源管理。\n解决方案\n\n简化命名结构通过合理的命名缩写和前缀减少域名的长度。例如us-east-ecommerce-production.enterpriseA.com 可以简化为 prod.ecom.us-east.enterpriseA.com确保域名在传达信息的同时保持简洁。\n简拼与全拼结合可以通过全拼命名重要核心服务如 ecommerce.enterpriseA.com而对于次要或内部服务使用简拼命名如 ecom.enterpriseA.com。\n\n3. 管理不善导致的资源混乱\n问题在缺乏有效管理机制的情况下企业可能会出现域名过度分配、资源命名不统一以及废弃域名未及时回收等问题。这不仅浪费了域名资源还可能导致安全隐患。\n解决方案\n\n生命周期管理建立域名的生命周期管理系统确保每个域名从创建到使用、修改、废弃都有明确的管理流程。定期审查域名的使用情况回收不再使用的域名减少资源浪费。\n自动化管理工具使用自动化工具如 Ansible、Terraform进行域名的批量管理和更新。通过自动化工具企业可以定期检查域名的使用情况识别未使用或重复的域名并自动执行清理和更新操作。\n\n4. 跨部门协作不足\n问题不同部门对域名的理解和需求不同往往会导致命名不统一、资源分配冲突以及沟通不畅。特别是在多个部门共享相同基础设施的情况下缺乏协作会导致命名混乱。\n解决方案\n\n跨部门协作与培训建立跨部门的域名管理委员会或工作组确保各部门能够参与域名的分配和管理。同时定期进行域名管理的培训确保各部门对命名规则有一致的理解。\n透明的审批流程通过透明化的域名申请和审批流程确保跨部门的沟通畅通减少重复和冲突。\n\n8. 总结与展望\n域名规划是现代化企业 IT 管理中的关键环节。一个灵活、规范且可扩展的域名分配体系,不仅能够帮助企业高效地管理网络资源,还能提升整体运营效率,支持企业的业务增长和技术变革。随着企业逐步采用云计算、多云策略、无服务器架构和边缘计算,域名管理的重要性愈加凸显。\n8.1 域名规划的重要性\n在现代化企业中域名不仅是访问资源的入口更是企业网络架构中至关重要的组织工具。域名规划决定了企业如何在复杂的 IT 环境下高效管理资源、支持不同业务模块、确保网络安全并保持灵活的扩展性。\n随着企业逐步转向云计算环境尤其是在采用IaaS、PaaS和SaaS三层服务模型的情况下合理的域名规划可以确保不同服务和资源的有序管理。通过制定清晰的命名规则和分配策略企业能够快速定位、访问并管理其全球范围内的网络资源。域名的规划在跨部门协作、资源分配以及数据中心管理中也扮演着至关重要的角色它为企业的技术团队、业务部门提供了标准化的管理框架减少了混淆和命名冲突确保了服务的可用性和一致性。\n在云计算和复杂的多层服务环境中域名规划的核心作用体现在\n\n简化资源管理通过明确的命名规则企业能够快速识别、管理和维护其内部资源减少复杂系统中的管理负担。\n提升协作效率在跨团队和跨部门协作中统一的域名分配策略能够提高沟通效率减少命名冲突带来的管理问题。\n支持业务扩展域名规划为企业提供了可扩展的架构支持业务和技术的快速增长确保企业能够轻松应对未来的技术发展。\n\n8.2 持续优化与改进\n尽管域名分配策略能够为企业提供有效的管理工具但由于技术环境和业务需求的动态变化企业的域名管理策略必须具备足够的灵活性并且需要不断进行优化和改进。\n1. 灵活应对技术与业务变化: 企业的业务和技术需求在不断发展。例如,随着企业逐步扩展到新的地域、采用新的技术架构(如无服务器架构或边缘计算),现有的域名分配体系可能不再完全适用。因此,域名分配策略需要具备足够的灵活性,能够根据企业的新需求进行动态调整。\n\n无服务器架构带来了动态资源的管理需求域名分配需要更加灵活以适应自动扩展的服务。\n边缘计算增加了对地理分布广泛的资源管理的需求域名策略应支持基于地域和节点的细化管理。\n\n2. 定期审查与更新: 企业应定期对其域名分配策略进行审查,确保命名规则和管理流程依然符合业务需求。定期的审查和更新不仅可以优化现有的域名结构,还能确保过时的域名被及时回收,从而保持网络资源的有序管理。审查过程中应关注以下方面:\n\n是否有过时的域名或未使用的域名需要清理。\n是否有新业务模块需要引入新的命名规则。\n是否存在命名冲突或复杂的命名结构需要简化。\n\n3. 自动化与工具优化: 借助自动化工具(如 Terraform、Ansible 等),企业能够提高域名管理的效率,减少手动配置引发的错误。自动化不仅可以加速域名的分配和管理,还能够实时监控域名的使用情况,自动执行清理和更新操作。这一趋势将继续推动域名管理的效率提升。\n8.3 展望未来\n随着全球企业的数字化转型深入发展云计算、边缘计算和物联网的广泛应用企业的 IT 基础设施变得越来越复杂,域名管理的重要性也将继续上升。展望未来,域名分配规范有几个值得期待的改进方向:\n1. 多云环境下的统一域名管理: 未来的企业将越来越多地采用多云策略,这意味着企业需要同时管理多个云服务提供商的资源。为了应对这一挑战,域名管理将逐步实现跨云平台的统一管理。通过引入跨云的命名规则和自动化工具,企业能够在不同平台之间无缝管理其资源,并确保每个平台上的资源具备清晰的命名结构。\n2. 边缘计算与物联网的广泛应用: 随着边缘计算和物联网IoT的普及数以百万计的设备和节点需要被管理和监控。未来的域名规划将进一步细化支持大量分布式设备的管理。企业需要为其边缘节点和物联网设备制定专门的命名规则确保这些设备能够在全球范围内被有效监控和管理。\n3. 自动化与智能化管理: 未来的域名管理将进一步依赖自动化和智能化工具。这些工具不仅能够帮助企业批量管理域名还能够通过人工智能AI技术预测资源需求自动分配合适的域名资源。通过引入智能化域名管理企业将能够更高效地应对复杂的技术架构和动态的业务需求。\n4. 增强的安全性: 随着网络攻击日益复杂域名管理的安全性也将成为未来发展的重点。企业将逐步采用更高级的安全协议如DNSSEC域名系统安全扩展和加密 DNS确保域名解析的安全性并防止域名篡改和攻击。未来的域名管理系统不仅需要具备强大的防护能力还需要提供实时监控和预警功能帮助企业抵御潜在的安全威胁。\n附录\n\nA. 常见简拼缩写对照表\n为确保企业内各部门在域名命名中的一致性与清晰性以下提供常见简拼与全拼的对照表。此表适用于常见服务、资源和功能模块的命名避免不同团队间的命名混乱。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n服务/功能全拼简拼应用程序applicationapp数据库databasedb开发环境developmentdev测试环境testingtest生产环境productionprod网络networknet容器containerctr存储storagesto无服务器serverlesssrvless电子商务ecommerceecom客户关系管理customer relationship managementcrm企业资源规划enterprise resource planningerp人力资源管理系统human resources management systemhrms内容分发网络content delivery networkcdn负载均衡load balancerlb边缘计算edge computingedge虚拟专用网络virtual private networkvpn\n通过该简拼对照表企业可以有效减少命名冲突并在命名时保持简洁与一致。\nB. 域名规划工具与资源\n为了提高域名管理的效率和可靠性企业可以借助多种工具来实现自动化的域名分配、管理和监控。以下是一些推荐的 DNS 管理和自动化部署工具:\n1. DNS 管理工具:\n\nBind一种广泛使用的开源 DNS 服务器软件,提供灵活的域名解析功能,适用于中大型企业的本地 DNS 部署。它支持多种安全功能,如 DNSSEC 和防缓存中毒。\nPowerDNS另一款高性能的开源 DNS 服务器,具备灵活的后端支持,包括数据库和 API 管理功能。适合需要高可用性和集成灵活性的企业。\nAmazon Route 53AWS 提供的云 DNS 服务,支持全球范围的域名解析,具有自动化功能,并且与 AWS 生态系统深度集成,适合使用 AWS 云服务的企业。\nGoogle Cloud DNSGoogle 提供的云 DNS 服务,支持地理负载均衡和自动化管理,适合使用 GCP 的企业。\n\n2. 自动化部署工具:\n\nAnsibleAnsible 是一款流行的自动化工具支持基础设施即代码IaC能够快速实现批量的 DNS 记录管理和域名配置。其简洁的 YAML 语法使得复杂的任务易于编写和管理。\nTerraformTerraform 提供了强大的多云管理功能,支持 AWS Route 53、Google Cloud DNS 等云 DNS 服务的自动化管理。它通过声明式配置文件来定义 DNS 记录,使得变更管理更加直观和可控。\nPuppetPuppet 是另一种基础设施自动化工具,适用于复杂环境下的 DNS 管理。它支持模块化管理,能够通过编写配置文件来自动部署和更新 DNS 记录。\n\n3. 域名监控工具:\n\nNagiosNagios 是一款开源的网络监控工具,能够帮助企业实时监控 DNS 服务器的状态和性能,并及时发现潜在问题。它支持通过自定义脚本监控域名解析的可用性。\nZabbixZabbix 同样是一款强大的监控工具,支持 DNS 解析监控,能够生成实时的性能报告并自动通知故障情况。\n\n4. 域名管理平台:\n\nCloudflareCloudflare 不仅是 DNS 服务提供商还提供内容分发网络CDN、DDoS 防护等功能,适合对安全性要求较高的企业。其管理界面简洁,自动化集成方便。\nDNSimpleDNSimple 是一款简单易用的域名管理服务,适合中小企业进行 DNS 自动化管理和 API 集成。\n\n这些工具能够大大简化企业的域名管理任务减少手动操作的复杂性并且提高整体运维效率。\nC. 域名分配相关的标准和合规性要求\n在全球化运营背景下企业的域名管理需要遵循相关法律法规和行业标准确保合法合规的域名使用。以下是企业在域名管理中需要关注的主要标准和合规性要求\n1. GDPRGeneral Data Protection Regulation通用数据保护条例\n\n背景GDPR 是欧盟于 2018 年实施的一项隐私保护法规,旨在保护欧盟公民的个人数据。尽管它与域名管理没有直接关联,但企业在域名使用过程中会涉及数据收集和存储,特别是关于 WHOIS 信息的收集和处理。\n合规要求企业需要确保在域名注册和管理过程中遵守 GDPR 关于数据隐私和数据保留的规定。尤其是在公开 WHOIS 信息时,企业需要保护相关域名持有者的信息,避免泄露个人数据。\n\n2. ICANN互联网名称与数字地址分配机构\n\n背景ICANN 是全球范围内管理域名分配的非营利组织负责协调域名系统、IP 地址的全球唯一性。ICANN 制定了一系列的域名注册、管理和争议解决政策。\n合规要求所有域名注册和分配必须遵守 ICANN 的政策。包括域名争议解决机制UDRP确保企业在全球范围内的域名注册具有合法性和唯一性。此外企业还需根据 ICANN 规定,维护准确的域名注册信息。\n\n3. WHOIS 隐私保护:\n\n背景WHOIS 是一个公开的数据库,用于存储域名的注册信息。域名持有者的信息可以通过 WHOIS 查询获得。\n合规要求为了防止域名持有者的信息被滥用企业可以选择启用 WHOIS 隐私保护服务。这些服务将域名持有者的信息隐藏,并使用中介信息代替个人信息发布。\n\n4. DNSSEC域名系统安全扩展协议\n\n背景DNSSEC 是用于确保 DNS 查询数据完整性和真实性的安全扩展协议。它通过数字签名机制,防止域名系统中的数据被篡改或伪造。\n合规要求为了提高企业域名解析的安全性企业应考虑采用 DNSSEC 来保护其域名。特别是在涉及金融、医疗等高安全性要求的领域,使用 DNSSEC 已成为行业标准之一。\n\n5. ccTLDs国家及地区顶级域名管理\n\n背景不同国家和地区对其国家代码顶级域名ccTLD的管理规则各不相同例如 .cn中国、.de德国、.jp日本等。\n合规要求企业在申请和使用 ccTLD 时,必须遵守相应国家或地区的域名管理规定。这些规定通常包括注册流程、信息披露和争议解决机制等。\n\n通过遵守上述法律法规和行业标准企业不仅能确保其域名管理的合规性还能提高网络安全性和业务合法性。"},"Professional/Company/数字化/规范/企业计算机命名规范":{"title":"企业计算机命名规范","links":[],"tags":["数字化/规范"],"content":"引言\n目的和重要性\n在现代企业数字化基础建设中建立一套统一的计算机命名规范具有重要意义。这一规范的目的是提高网络管理的效率和准确性便于 IT 团队和用户快速识别和定位设备。同时,规范化的计算机命名有助于简化设备管理、维护和故障排除,同时增强网络安全性和文档记录的清晰度。\n适用范围\n\n适用于企业中所有计算机和网络设备包括但不限于服务器、工作站、笔记本电脑、移动设备及其他网络连接设备。\n适用于企业总部、分公司、办公地点以及任何企业运营的地点包括临时项目办公室和远程工作环境。\n适用于所有部门和团队确保在整个企业范围内实现设备命名的标准化和一致性。\n\n基本原则\n简洁性\n\n设备命名应尽可能简短同时包含必要的信息。\n避免冗余和不必要的字符以确保命名的高效性。\n\n易于理解\n\n命名应使用直观的缩写和标识以确保即使是非技术人员也能理解。\n命名必须与设备的实际用途或位置相关联以增强辨识度。\n\n一致性\n\n在全公司范围内实施统一的命名规则。\n公司范围内的设备应保持命名格式的一致。\n\n安全性\n\n核心业务信息不应在命名中使用敏感或直接揭露设备角色的信息。\n尽可能保持一定的匿名性以免暴露关键基础设施信息。\n\n扩展性和灵活性\n\n设计命名规则时考虑未来的扩展如新设备的加入和组织结构的变化。\n确保规则足够灵活以适应新技术和不断变化的业务需求。\n\n基本语法\n[企业地理位置]-[设备类型]-[分公司/部门/项目组]-[用途或角色]-[编号]\n\n\n有效字符ASCII 字母A 到 Z数字 0 到 9以及连字符 (-),不得以连字符开头。\n最大长度原则上不应超过 32 个字符。如果是在包含 Windows、Linux 和 Mac 设备的网络环境中,建议遵守 Windows 的 15 字符限制,以避免潜在的兼容性问题。\n\n组成要素\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n要素要求长度限制是否可选企业地理位置基于附录中《中国一级行政区简拼》4 位以内❌设备类型基于附录中《现代企业常用设备类型简拼》3 位以内✔️分公司/部门或项目组基于附录中《汉字词语简拼》5 位以内❌用途或角色基于附录中《汉字词语简拼》5 位以内✔️编号系统提供唯一性增序标识数字号最少 3 位❌\n命名示例\n考虑以下示例来演示如何根据规范为设备命名\n\n假设你的企业总部位于北京市你需要命名一台用于开发的服务器。\n地理位置根据附录北京市的简拼为 “BJ”。\n设备类型服务器的简拼为 “SVR”。\n部门/项目组:这台服务器属于信息部,简拼为 “XXB”。\n用途/角色:这台服务器的用途是开发,简拼为 “DEV”。\n编号分配唯一的增序数字号例如 “001”。\n组合命名根据语法将这些元素组合成最终的命名 “BJ-SVR-XXB-DEV-001”。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n地理位置设备类型部门/项目组用途/角色编号命名示例北京服务器信息部开发001BJ-SVR-XXB-DEV-001上海笔记本财务部-003SH-LT-CWB-003贵州台式机市场部茅台007GZ-DT-SCB-MT-007河南-企管部-005HN-QGB-005\n实施指南\n\n规范制定 由企业的 IT 团队和网络管理员共同制定和审核计算机命名规范,确保满足企业的特定需求和业务要求。\n员工培训 所有员工,特别是 IT 支持和设备管理人员,应接受培训以了解并正确应用此命名规范。\n文档传达 确保命名规范的文档在整个企业范围内广泛传达,以便所有相关方都能访问并遵守规则。\n\n命名审查和更新\n\n定期审查定期审查命名规范的适用性和有效性确保其与企业发展和技术变革保持一致。\n定期修改 如果设备的地理位置、类型、部门/项目组、用途或角色发生变化,需要相应地修改设备命名。\n异常情况 对于一些特殊情况,如暂时无法分配编号或需要临时调整命名规则,应在文档中记录并获得管理部门的批准。\n\n常见问题解答\n1. 为什么需要统一的命名规范?\n统一的命名规范有助于提高网络管理的效率、准确性和安全性。它还简化了设备管理和故障排除过程有助于维护一个清晰的文档记录。\n2. 如何确保命名的唯一性?\n命名规范中的编号系统确保了设备在同一类别中具有唯一标识以防止冲突。\n3. 我应该如何适应新的设备类型或组织结构变化?\n规范中的灵活性原则允许在未来添加新的设备类型或适应组织结构变化。当需要时可以修改命名规则并确保所有相关人员了解并遵守新规则。\n4. 我是否需要为所有设备都遵循此规范?\n是的规范的一致性原则要求在整个企业范围内实施统一的命名规则以确保网络管理的效率和准确性。\n附录\n术语解释\n\n企业地理位置 指设备所在地的一级行政区划简拼,用于指示设备的地理位置。\n设备类型 设备的类型缩写,用于快速识别设备的基本种类。\n分公司/部门或项目组: 设备所属的部门、分公司或项目组的简拼,用于标明设备的所属组织。\n用途或角色 设备的用途或角色的简拼,有助于明确设备的功能或任务或进一步区分所属组织。\n编号系统 用于唯一标识设备的数字号,确保每个设备都有唯一标识。\n\n中国一级行政区简拼\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n行政区简拼河北省HB山西省SX黑龙江省HLJ吉林省JL辽宁省LN江苏省JS浙江省ZJ安徽省AH福建省FJ江西省JX山东省SD河南省HN湖北省HUB湖南省HUN广东省GD海南省HAIN四川省SC贵州省GZ云南省YN陕西省SHX甘肃省GS青海省QH台湾省TW内蒙古自治区NMG广西壮族自治区GX西藏自治区XZ宁夏回族自治区NX新疆维吾尔自治区XJ北京市BJ天津市TJ上海市SH重庆市CQ香港特别行政区HK澳门特别行政区MAC\n现代企业常用设备类型简拼\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n设备类型简拼全拼描述服务器SVRServer用于数据处理和存储网络服务提供工作站WSWorkstation高性能个人电脑用于专业任务笔记本电脑LTLaptop便携式电脑适用于移动办公台式电脑DTDesktop常规办公用途的个人电脑移动设备MBMobile Device包括智能手机和平板电脑网络设备NETNetwork Device包括路由器、交换机等网络基础设施打印机PRNPrinter文档打印设备存储设备STGStorage用于数据备份和存储的外部或内部存储安全设备SECSecurity包括防火墙、VPN 设备等安全相关设备\n汉语词组简拼\n为避免英语简拼和汉语简拼产生歧义结合汉语中本土化词语较多。汉语简拼法是取词语中每个汉字拼音第一个字母转换为大写。例如以下示例\n\n市场部 SCB\n信息部 XXB\n"},"Professional/Project/RSSky/项目计划书":{"title":"项目计划书","links":[],"tags":["RSSky/项目计划书"],"content":"1. 引言\n1.1 项目背景\n在信息爆炸的时代互联网用户面对海量信息时常常陷入信息茧房。这一现象指的是用户的接收信息渠道受到算法推荐的限制导致其只能接触到与自己兴趣、观点一致的信息从而失去了多元视角。这不仅影响了个人的全面认知也限制了社会整体的多样化对话。\n《穹顶之下》项目RSSky旨在通过为用户提供多维度的信息获取渠道打破信息茧房提升信息获取的质量和效率。RSSky 的核心理念是建立一个开放、透明、自由的信息获取平台,依托 RSS 技术和社区协作,为用户带来高质量、全面的内容订阅服务。\n1.2 项目愿景\n愿景打破信息茧房提供多元信息获取渠道提升用户对世界的理解和信息辨别能力。通过社区协作提供开放、透明、自由的 RSS 资源代理与管理服务。\n2. 项目概述\n2.1 项目目标\n\n无限可能为自由而生\n\n《穹顶之下》RSSky 的主要目标是为用户提供高质量的 RSS 订阅资源,并通过开源社区协作管理和代理这些资源,确保信息获取的稳定性和高效性。具体目标包括:\n\n信息开放打破信息茧房提供多元化、全面的信息获取渠道。\n社区协作通过社区成员共同贡献和管理 RSS 资源,实现分布式、协作式的信息提供。\n自动化管理使用自动化技术实现 RSS 资源的更新、验证、路由与缓存管理,确保数据的实时性和稳定性。\n用户需求满足支持个性化需求定制帮助用户根据兴趣选择、管理和获取内容。\n\n2.2 阶段性目标\n\n阶段一完成社区平台的搭建实现 100 个高质量的 RSS 资源代理,并通过 Cloudflare Workers 进行路由管理。\n阶段二扩展到 100 名活跃用户,代理 1000 个 RSS 资源,并支持用户需求定制,优化路由系统性能。\n\n3. 技术方案\n3.1 总体架构设计\nRSSky 的核心是 RSS 资源代理与路由管理,它通过社区协作者提交的 RSS 资源地址,社区仓库对这些资源进行代理和缓存,所有的爬虫及 RSS 生成工作由协作者独立完成,社区负责数据的流通与路由映射管理。\n架构核心模块包括\n\nCloudflare Workers用于代理和缓存 RSS 请求。\n社区 GitHub 仓库:用于管理 RSS 路由映射和自动化任务。\n协作者独立爬虫由社区协作者独立运行爬虫生成 RSS 资源。\n\n3.1.1 核心架构图\ngraph TD;\n subgraph Community GitHub Repository ["Community GitHub Repository"]\n B1[PR: Collaborator submits new RSS feed URL]\n B2[GitHub Actions: Validate RSS feed URL]\n B3[GitHub Actions: Merge PR and update mappings]\n end\n \n subgraph Cloudflare Workers ["Cloudflare Workers"]\n A1[Handles routing requests]\n A2[Caches RSS feed responses]\n A3[Proxies requests to RSS providers]\n end\n \n subgraph Collaborator RSS Providers ["Collaborator RSS Providers"]\n C1[Collaborator's crawler generates RSS XML]\n C2[RSS XML file hosted on collaborator's server]\n end\n \n subgraph Users ["Users"]\n D1[User requests RSS feed]\n D2[Receives RSS feed response]\n end\n \n B1 --> B2 --> B3\n B3 --> A1\n A1 --> A2\n A1 --> A3\n A3 --> C2\n C1 --> C2\n A2 --> D2\n D1 --> A1\n\n3.1.2 核心流程图\nsequenceDiagram\n participant Collaborator as 协作者\n participant GitHub as GitHub Repository\n participant GitHubActions as GitHub Actions\n participant Cloudflare as Cloudflare Workers\n participant Cache as Cache\n participant CollaboratorServer as 协作者服务器\n participant User as 用户\n\n 用户请求和处理流程\n User->>Cloudflare: 请求 RSS 源 (代理地址)\n Cloudflare->>Cache: 检查缓存是否存在\n alt 缓存命中\n Cache-->>Cloudflare: 返回缓存的 RSS 文件\n Cloudflare-->>User: 返回缓存的 RSS 文件\n else 缓存未命中\n Cloudflare->>CollaboratorServer: 请求协作者服务器获取最新 RSS 文件\n CollaboratorServer-->>Cloudflare: 返回最新的 RSS 文件\n Cloudflare->>Cache: 缓存新的 RSS 文件\n Cloudflare-->>User: 返回最新的 RSS 文件\n end\n\n3.1.3 核心功能模块\nCloudflare Workers 路由管理\nCloudflare Workers 是整个系统的核心代理模块,负责处理所有用户的 RSS 资源请求,并代理协作者提供的真实 RSS 地址。\nsequenceDiagram\n participant User as 用户\n participant Cloudflare as Cloudflare Workers\n participant Cache as Workers 缓存\n participant CollaboratorServer as 协作者服务器\n\n User->>Cloudflare: 请求代理 RSS 地址\n Cloudflare->>Cache: 检查 RSS 是否已缓存\n alt 缓存命中\n Cache-->>Cloudflare: 返回缓存的 RSS 文件\n Cloudflare-->>User: 返回 RSS 文件\n else 缓存未命中\n Cloudflare->>CollaboratorServer: 请求协作者服务器获取最新 RSS 文件\n CollaboratorServer-->>Cloudflare: 返回最新 RSS 文件\n Cloudflare->>Cache: 缓存新的 RSS 文件\n Cloudflare-->>User: 返回最新的 RSS 文件\n end\n\n它的主要职责包括\n\n处理路由请求\n\nCloudflare Workers 接收用户请求并通过路由映射找到相应的 RSS 资源地址。\n当用户访问代理的 RSS 地址时Cloudflare Workers 负责转发请求并获取真实的 RSS 资源。\n\n\n缓存管理\n\n为提高效率Cloudflare Workers 会将已请求的 RSS 文件进行缓存,下一次请求同样的资源时,直接从缓存中返回结果。\n缓存策略会根据 RSS 内容的更新频率进行动态调整,确保用户始终获取最新的 RSS 信息。\n\n\n代理与负载均衡\n\n当缓存失效或 RSS 源地址不可访问时Cloudflare Workers 通过代理访问协作者服务器以获取最新 RSS 文件。\n\n\n\n社区 GitHub 仓库\n社区 GitHub 仓库作为系统的核心协作平台,管理所有 RSS 资源的路由映射文件及更新。每一个 RSS 资源由社区成员通过 PR 提交。\nsequenceDiagram\n participant Collaborator as 协作者\n participant GitHub as GitHub Repository\n participant GitHubActions as GitHub Actions\n participant Cloudflare as Cloudflare Workers\n\n Collaborator->>GitHub: 提交 PR (新 RSS 源/更新源)\n GitHub-->>GitHubActions: 触发 GitHub Actions\n GitHubActions->>GitHubActions: 验证 RSS 源(可访问性、格式正确性)\n GitHubActions-->>Collaborator: 验证通过/失败反馈\n GitHubActions->>GitHub: 合并 PR\n GitHubActions->>Cloudflare: 更新 Cloudflare Workers 路由映射\n\n社区具体功能包括\n\nPR 提交与验证:\n\n协作者可以通过 GitHub PR 提交新的 RSS 资源地址或更新已有的地址。\nGitHub Actions 自动触发对 RSS 资源的验证,确保提交的地址能够正常访问,并且格式正确。\n\n\n自动化管理\n\n验证通过后GitHub Actions 会自动合并 PR 并更新路由映射文件。这些映射文件由 Cloudflare Workers 使用,确保用户请求能够正确路由到真实的 RSS 地址。\nGitHub Actions 定期执行健康检查,验证现有 RSS 资源的可用性,若发现失效资源,将通知相关贡献者修复或删除。\n\n\n社区协作与贡献激励\n\n社区成员通过贡献 RSS 资源或修复现有问题提升社区的活跃度。GitHub 仓库提供公开的贡献历史,社区可以通过排行榜、积分等机制激励成员贡献。\n\n\n\n协作者独立爬虫\n协作者独立爬虫是系统的基础数据来源由各个社区贡献者负责编写、维护并托管。\nsequenceDiagram\n participant Collaborator as 协作者\n participant Crawler as 爬虫脚本\n participant CollaboratorServer as 协作者服务器\n participant GitHub as GitHub Repository\n participant GitHubActions as GitHub Actions\n\n Collaborator->>Crawler: 定期运行爬虫抓取数据\n Crawler->>CollaboratorServer: 生成 RSS 文件并托管\n Collaborator->>GitHub: 提交新的 RSS 地址/更新地址至 GitHub\n GitHub-->>GitHubActions: 触发自动化验证\n GitHubActions->>GitHubActions: 验证 RSS 文件并更新映射\n\n其主要功能和责任如下\n\nRSS 生成与托管:\n\n协作者可以使用任意编程语言编写爬虫负责抓取目标网站的内容并生成 RSS 文件。每个协作者独立运行自己的爬虫,系统不会集中管理爬虫任务。\n生成的 RSS 文件由协作者服务器托管,协作者需要定期维护爬虫,确保 RSS 文件的时效性。\n\n\n自动化生成与更新\n\n协作者可以通过 GitHub Actions 或其他定时任务自动生成和更新 RSS 文件。例如,协作者可以设置每天定时运行爬虫,抓取最新的内容并更新 RSS 文件。\nRSS 文件生成后,协作者将地址提交至社区 GitHub 仓库,系统自动更新对应的路由映射。\n\n\n灵活性与兼容性\n\n系统允许协作者使用多种语言编写爬虫例如 Python、Node.js 或 Rust 等。不同协作者可以根据自己熟悉的开发环境选择合适的技术栈,提升社区贡献的灵活性。\n为确保统一标准建议社区提供爬虫编写的模板和代码规范确保不同语言编写的爬虫都能顺利集成到系统中。\n\n\n\n3.2 技术选型\n\n语言与开发工具\n\nJavaScript用于编写 Cloudflare Workers 路由逻辑。\nPython、Node.js、Rust协作者可以自行选择开发 RSS 爬虫的语言,项目不限制爬虫开发语言。\nGitHub Actions用于处理自动化任务如提交的 RSS 资源验证、合并、定期更新等。\n\n\n数据库与存储\n\nGitHub 仓库:社区不直接存储 RSS 数据,仅存储 URL 映射文件,数据存储由提供者决定。\n缓存机制Cloudflare Workers 通过缓存管理 RSS 资源,确保访问效率。\n\n\n代理与路由管理\n\nCloudflare Workers用于动态代理协作者提供的 RSS 资源。\n\n\n\n3.3 核心功能实现\n项目的核心功能围绕自动化工作流、用户界面与订阅管理、以及健康监控与通知展开。这些功能不仅确保 RSS 资源的自动更新和管理,还提供了一种用户友好的交互方式,以便轻松管理和订阅内容。\n3.3.1 自动化工作流\nGitHub Actions 在整个项目中扮演了自动化管理的关键角色,通过其强大的 CI/CD 流程,协作者提交的 RSS 资源能够得到快速验证、自动化处理和更新。自动化工作流的几个关键部分包括:\n\nPR 提交与自动化处理:\n\n当协作者提交新的 RSS 资源或更新现有资源时GitHub Actions 会自动触发,进行以下步骤:\n\n验证提交的 RSS URL 是否能够正常访问。\n检查 RSS 源的内容格式是否正确。\n验证通过后自动合并 PR 到主仓库。\n\n\n如果验证失败GitHub Actions 会通过评论通知提交者,并提供失败原因及修复建议。\n\n\n自动化健康监控\n\n定期任务GitHub Actions 通过定期执行的任务,检查所有已代理的 RSS 资源的可用性。确保每个资源能够在特定时间窗口内正常访问。\n自动修复当某个 RSS 资源无法访问时GitHub Actions 可以通知协作者修复或更新资源。如果资源未能在规定时间内恢复,系统将自动标记为失效,并建议用户切换到备用资源。\n\n\n版本管理与发布\n\n自动化版本发布每周发布新版本包含所有新提交的 RSS 资源及改进。每日生成体验版本,用于测试和持续改进系统功能。\nGitHub Releases每个稳定版本会自动发布到 GitHub Releases社区开发者和用户可以获取最新的资源映射和路由信息。\n\n\n\n3.3.2 用户界面与订阅管理\n项目通过基于 Markdown 文件来构建一个用户友好的静态站点界面,帮助用户轻松管理和订阅 RSS 资源。静态站点的优点是结构简单、维护方便、性能优越,并且可以与 GitHub Pages 无缝集成。以下是核心功能模块的详细说明:\n\n基于 Markdown 的静态站点:\n\n使用静态站点生成器基于 Markdown 文件构建一个简单直观的 Web 界面。每个 RSS 源都有一个对应的内容,文件中包含 RSS 源的详细信息、使用说明、订阅地址等。\n该静态站点将托管在 GitHub Pages 上,用户可以直接访问,并通过搜索或分类功能查找感兴趣的订阅源。\n\n\n订阅管理与搜索功能\n\n搜索功能用户可以通过站点内置的搜索引擎如 Lunr.js 或 Algolia搜索 RSS 资源。关键词搜索能够快速找到符合条件的 RSS 订阅源,极大提高了用户查找效率。\n分类展示每个 RSS 资源根据类别(如新闻、科技、娱乐等)进行分类展示,用户可以通过分类标签快速找到自己感兴趣的资源。每个分类页面使用 Markdown 文件生成,简单明了,方便用户浏览。\n\n\n个性化推荐与管理\n\nRSS 管理面板:为用户提供简单的订阅管理面板,用户可以收藏、标记或取消订阅 RSS 源。管理面板将依靠客户端存储(如 LocalStorage保持用户偏好便于浏览器持久化用户的订阅记录。\n一键订阅每个 RSS 资源都提供一键复制订阅地址功能,用户可以快速将订阅地址复制并粘贴到其 RSS 阅读器中。\n\n\nRSS 资源展示与说明:\n\n每个 RSS 资源的详细页面包含资源的介绍、更新频率、内容预览、订阅地址等详细信息。\n通过模板化 Markdown 文件生成资源页面,确保所有 RSS 源的展示信息一致且规范。\n\n\n\n3.3.3 健康监控与通知\n系统通过自动化健康监控机制确保所有代理的 RSS 源在服务期间始终可用,并提供多层次的通知机制以便及时处理出现的任何问题。以下是功能模块的详细说明:\n\n自动化健康检查\n\n定期任务通过 GitHub Actions 定期执行健康检查任务,验证所有 RSS 资源的可访问性和格式是否正确。\n内容验证检查每个 RSS 文件是否符合标准格式,如 <channel>, <item> 等必要的标签。确保 RSS 资源可以正常解析和使用。\n更新频率检测通过分析 RSS 源中的 <pubDate> 或 <lastBuildDate>,检测资源是否定期更新。对于长时间未更新的资源,标记为需要维护或替换。\n\n\n问题通知与修复建议\n\n协作者通知当发现某个 RSS 源失效时,系统会通过 GitHub Issues 自动生成问题报告,并通知协作者进行修复。协作者会收到问题的详细说明,包括失效原因和修复建议。\n邮件与推送通知协作者还会收到邮件通知或推送消息确保他们能够及时修复问题维持资源的可用性。\n问题报告所有检测结果会生成报告并记录在 GitHub 中,便于社区成员审查和后续维护。\n\n\n备用资源支持\n\n备用源配置为一些重要或高访问量的 RSS 资源设置备用源,确保在主 RSS 资源失效时,系统可以自动切换到备用资源。\n自动切换当健康检查发现主源失效时系统会自动启用备用源保障服务的连续性。用户无需任何手动操作系统会自动处理切换。\n备用源管理协作者可以通过提交 PR 方式更新或增加备用 RSS 源,确保资源在出现问题时能够顺利切换。\n\n\n用户反馈与问题报告\n\n用户通知当系统切换到备用资源时用户将收到简要的通知告知当前资源的状况。用户可以在资源页面查看详细信息并选择是否手动更新订阅。\n问题反馈渠道用户可以通过静态站点的反馈功能报告失效的 RSS 资源。提交的反馈会转化为 GitHub Issues供协作者查看并处理。\n\n\n\n3.3.4 社区协作与贡献者管理\n社区协作是 RSSky 项目的基础,协作者通过贡献 RSS 资源并不断完善系统,维持项目的高活跃度。为了确保项目长期健康发展,系统提供了一套协作和管理机制,帮助社区成员更高效地参与项目。\n\n贡献者管理与激励机制\n\n贡献者排行榜每个贡献者的贡献包括提交的 RSS 源、修复的问题等)都会被记录,并根据贡献量进行积分评定。贡献者可以通过排行榜查看自己的排名,激励社区成员更加积极地参与。\n贡献奖励与徽章系统为激励活跃的贡献者项目引入了社区徽章和奖励系统。核心贡献者可以获得“活跃贡献者”、“修复专家”等徽章这些徽章会展示在贡献者的 GitHub 个人资料上,增加社区声望。\n长期贡献者的社区影响力核心贡献者可以被邀请参与项目的长期规划帮助制定新功能的路线图并参与项目的重大决策进一步增强社区归属感。\n\n\n贡献者协作流程\n\nGitHub PR 审核流程:贡献者通过 PR 向项目提交新功能或 RSS 资源。系统通过 GitHub Actions 自动验证 PR 的正确性(如 RSS URL 的有效性、内容格式的正确性等)。社区维护者或管理员在自动验证通过后,可以进一步进行手动审查和合并。\n社区反馈与讨论贡献者提交的 PR 可以通过 GitHub Discussions 或 Issues 进行社区讨论,确保提交的功能或 RSS 资源符合社区共识。这种开源协作的模式可以确保所有变更都能被详细审查和讨论。\n\n\n协作模板与文档支持\n\n贡献指南为协作者提供详细的贡献指南帮助新加入的贡献者快速上手。指南中包含如何提交 PR、如何编写 RSS 源格式、以及如何通过 GitHub Actions 进行自动化测试等。\n模板与代码规范为确保不同贡献者提交的代码和 RSS 源符合统一标准,项目提供了模板和代码规范文档。所有贡献者在提交代码或 RSS 源之前,需要使用这些模板和规范进行检查,确保代码的可维护性和一致性。\n\n\n定期社区活动与黑客松\n\n社区黑客松项目可以定期组织在线黑客松活动邀请全球开发者参与推动新功能的开发和讨论。黑客松不仅能够激发创新也能为项目引入更多新贡献者。\n反馈与路线图讨论项目管理员可以定期发起社区讨论听取社区成员的意见和建议并根据讨论结果调整未来的开发路线图。\n\n\n\n3.4 项目路线图\n3.4.1 短期目标0-6 个月)\n\n实现基础的 RSS 资源代理和路由管理功能,使用 Cloudflare Workers 处理 RSS 资源请求。\n吸引社区成员贡献 RSS 资源,完善 PR 流程,实现自动化更新和验证。\n提供用户订阅管理的基本 Web 界面,支持一键订阅和管理功能。\n\n以帮助项目更好地监控和追踪进展。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n主任务子任务状态完成基础 RSS 资源代理与路由管理构建 Cloudflare Workers 路由逻辑实现 RSS URL 到真实源地址的路由映射实现基本缓存管理机制(支持频繁更新的 RSS 缓存刷新)配置负载均衡机制,处理高并发 RSS 请求创建基础状态页面,展示路由和缓存状态实现自动化工作流与 PR 管理集成 GitHub Actions自动触发 PR 检查编写 PR 验证脚本,检查 RSS 源可用性和格式自动合并通过验证的 PR更新路由映射创建状态页面展示 PR 提交、验证、合并的实时状态搭建用户界面与订阅管理使用 Hugo 或 Jekyll 构建静态站点创建 RSS 源详细页面(包含订阅地址、说明)集成 Lunr.js 或 Algolia 搜索引擎,支持 RSS 源关键词搜索按类别展示 RSS 源,提供分类筛选功能为每个 RSS 源创建一键复制订阅地址的功能创建状态页面,展示站点更新和页面访问数据吸引社区协作者贡献 RSS 资源编写贡献指南,详细描述如何编写爬虫和提交 RSS 源提供爬虫模板支持多种语言Python、Node.js、Rust开展社区推广活动通过开发者论坛和社交媒体吸引贡献者设置贡献排行榜展示贡献者提交的 RSS 源和参与度创建状态页面,展示社区成员贡献的统计数据\n3.4.2 中期目标6-12 个月)\n\n扩展到 1000 个高质量的 RSS 订阅源,优化路由管理功能,提升系统的稳定性和性能。\n引入个性化推荐功能通过分析用户的订阅历史为用户提供更多相关 RSS 资源推荐。\n完善用户界面增加 RSS 资源的可视化管理和分类功能,帮助用户更好地管理信息。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n主任务子任务扩展 RSS 资源与优化缓存策略扩展至 1000 个高质量的 RSS 资源为不同类型的 RSS 源优化缓存策略(高频、低频源不同缓存时间)对路由映射进行优化,减少处理时间设置缓存刷新状态页面,实时展示缓存命中率和缓存刷新周期开发个性化推荐功能通过分析用户订阅历史,开发个性化 RSS 源推荐算法在用户界面增加推荐模块,提供相关推荐 RSS 源开发订阅管理面板,支持收藏、标记已读、取消订阅等操作健康监控与备用资源支持开发 GitHub Actions 任务,定期检查 RSS 源的可用性和更新频率为高访问量的 RSS 源设置备用资源,自动切换到备用源为协作者提供 RSS 源状态通知,提醒源失效或需更新创建状态页面,展示 RSS 源健康状态(可用性、频率、错误报告等)完善社区激励与协作机制引入贡献者排行榜,展示贡献者的提交、修复等贡献记录增加贡献徽章系统,奖励活跃贡献者定期举办线上黑客松活动,激励新功能开发和修复任务创建状态页面,展示社区活动的参与情况和贡献者活跃度\n4. 用户体验与社区运营\n4.1 用户体验\n\n稳定性与高可用性\n\n通过 Cloudflare Workers 的缓存机制,用户可以快速访问代理的 RSS 资源,确保信息流的稳定性和高效性。\n健康监控机制确保 RSS 源始终有效,用户可以获得高质量的订阅体验。\n\n\n个性化推荐\n\n系统通过用户订阅行为分析为用户推荐与其兴趣相关的 RSS 源,帮助用户避免信息过载,并提升信息获取的效率。\n\n\n多维度管理\n\n用户可以通过 Web 界面轻松管理订阅源,并根据个人需求进行订阅源分类和筛选。\n\n\n\n4.2 社区协作与运营\n\n贡献者管理与激励\n\n通过贡献者排行榜和积分机制激励社区成员提交优质的 RSS 资源。贡献者可以通过定期提交和维护获得社区认可和奖励。\n核心贡献者将有机会参与项目的长期发展规划提升社区的参与度和活跃度。\n\n\n运营成本管理\n\n初期依赖 Cloudflare Workers 进行代理和路由,随着用户规模扩大,可以逐步引入自建 Nginx 反向代理,优化系统的流量管理,降低运营成本。\n项目也可以通过与云服务提供商建立合作利用免费资源进一步降低成本。\n\n\n\n4.3 社区增长策略\n\n推广和营销通过社交媒体、开发者论坛、开源社区等渠道推广项目吸引更多用户和开发者参与。\n合作伙伴计划与相关的 RSS 订阅平台、信息流工具建立合作伙伴关系,增加 RSSky 的知名度。\n社区激励计划引入贡献者奖励机制通过排行榜、徽章、积分等方式激励更多开发者和贡献者积极参与项目建设。\n\n4.4 持续创新\n\nAI 驱动的个性化推荐:引入基于 AI 的算法模型,进一步优化个性化推荐功能,让用户能够快速找到感兴趣的订阅源。\n分布式缓存与优化随着用户规模的扩展引入分布式缓存和 CDN 技术,进一步提高系统的响应速度和稳定性,确保全球范围内用户都能高效访问内容。\n新技术引入密切关注前沿技术的发展如去中心化的内容发布协议、更加高效的内容聚合工具等并探索这些技术如何与 RSSky 项目结合,推动项目的技术革新。\n\n5. 开发者文档与协作\n5.1 开发者支持\n\n详细文档\n\n提供详细的开发者文档包含如何编写爬虫、如何通过 GitHub Actions 自动生成 RSS 源,以及如何提交 PR。\n\n\n标准化工具链\n\n制定统一的代码规范和测试标准确保不同语言的爬虫代码具有一致性便于项目的长期维护和扩展。\n\n\n\n5.2 贡献指南\n\n贡献流程\n\n开发者可以通过 GitHub 提交 PRRSS 源的提交和更新将由 GitHub Actions 自动化处理。贡献者可以通过贡献文档了解详细的贡献指南。\n\n\n贡献激励\n\n通过贡献者的活跃度和代码质量进行评估为高质量贡献者提供社区认可和奖励增强社区凝聚力。\n\n\n\n6. 安全性与合法性\n6.1 数据安全\n\n用户隐私保护项目不存储用户的个人数据所有 RSS 资源的获取通过代理完成,确保用户信息的隐私性。\n\n6.2 法律合规\n\n内容版权保护原则上所有提交的 RSS 资源必须经过社区审核,确保其合法合规,避免侵犯目标网站的版权和知识产权。\n"},"Professional/Work/data-engineer/home":{"title":"数据工程师data-engineer","links":[],"tags":[],"content":"数据工程师data-engineer\n数据工程师data-engineer是现代数据驱动的企业中的核心角色他们专注于设计、构建和维护能够处理各种规模数据集的系统从 GB 级别到 PB 级别。这些系统通常用于数据存储、查询和分析,支持企业的决策制定、产品创新和运营优化。\n职责与工作内容\n\n数据处理与存储设计和实施数据存储解决方案如关系型数据库、Hadoop、HBase 和 Cassandra。\n数据流处理与 ETL使用工具如 Apache Kafka、Apache Flink 进行实时数据流处理,同时设计和实现 ETL 流程。\n数据集成整合来自不同来源的数据确保数据的一致性和完整性。\n性能优化优化数据查询和处理的性能确保系统的高效运行。\n系统维护与监控监控数据系统的健康状况进行故障排除和性能调优。\n跨团队协作与数据科学家、业务分析师、BI 专家和其他团队合作,确保他们可以轻松访问和使用数据。\n\n必备技能与知识\n\n数据技术栈熟悉数据库技术如 MySQL、PostgreSQL、Hadoop 生态系统(如 HDFS、MapReduce、Hive和 Spark。\n分布式系统理解分布式系统的原理和挑战如数据一致性、分区容错等。\n编程与脚本如 Java、Scala、Python 等,用于数据处理和自动化任务。\n数据建模与设计能够设计高效、可扩展的数据模型和架构。\n系统监控与维护使用工具如 Grafana、Prometheus 进行系统监控和告警。\n沟通与团队合作与各团队沟通协作理解业务需求为其提供所需的数据支持。\n\n总的来说数据工程师确保数据系统的稳定、高效和可扩展从而支持企业做出数据驱动的决策。他们的专业知识和技能使得企业能够充分利用其数据资产为客户和业务提供价值。"},"Professional/Work/roadmap/home":{"title":"求职之路","links":[],"tags":[],"content":"\n主要记录个人的求职之路、职业规划以及经验分享。\n如果有类似的经验贴接受 PR 及经验分享,共同进步早日实现财富自由!\n冲啊奥里给 😍😍😍"},"Professional/Work/roadmap/权益保障/仲裁指南":{"title":"仲裁指南","links":[],"tags":["工作/权益"],"content":"在劳动合同签订的过程中,用人单位往往处于极其强势的地位。对应的,劳动者毫无疑问属于弱势的一方。在双方就劳动合同的履行产生争议时,依靠友好协商有时并不能达成让人满意的结果,于是便有了劳动争议仲裁委员会。无论劳动者是否有与用人单位进行协商,只要产生劳动争议,均可以提交劳动仲裁申请。本文接下来将专注于因裁员导致产生劳动仲裁的情形。\n1. 公司可以合法解除劳动合同的情形\n除开试用期外以下情形公司可以单方面解除劳动合同不需要支付补偿金或者赔偿金过失类\n\n劳动者严重违反用人单位的规章制度。\n劳动者严重失职营私舞弊给用人单位造成重大损害。\n劳动者同时与其他用人单位建立劳动关系对完成本单位的工作任务造成严重影响或者经用人单位提出拒不改正。\n具有以欺诈、胁迫的手段或者乘人之危使对方在违背真实意思的情况下订立或者变更劳动合同的情形致使劳动合同无效。\n劳动者被依法追究刑事责任。\n\n\n基本是主观原因造成的公司可以单方面解除劳动合同。\n\n以上这些情形相信大家应该不太能够遇到同时如果提出过失类解除需要用人单位进行举证这里便不展开介绍了。\n2. 公司需要支付补偿金才能解除劳动合同的情形\n以下这些情形是大家常说的 N 或者 N+1 补偿的情形:\n\n双方协商一致解除劳动合同**(由公司提出)**\n劳动者患病或者非因工负伤医疗期满后不能从事原工作也不能从事由用人单位另行安排的工作\n劳动者不能胜任工作经过培训或者调整工作岗位仍不能胜任工作\n劳动合同订立时所依据的客观情况发生重大变化致使原劳动合同无法履行经当事人协商不能就变更劳动合同达成协议\n用人单位濒临破产进行法定整顿期间或者生产经营状况发生严重困难确需裁减人员的应当提前三十日向工会或者全体职工说明情况听取工会或者职工的意见经向劳动行政部门报告后可以裁减人员\n\n其中适用第二、三、四条进行劳动关系解除时用人单位需要提前 30 日书面告知劳动者,否则需要支付额外的一个月工资,即 N+1 。其他情形需要支付 N 补偿,具体如何计算后面还会讲到。\n看到这里可能有人已经开始打退堂鼓了是否只要公司提出劳动者不能胜任工作并以绩效完成情况作为证明就能适用 N 或 N+1 辞退呢?其实并不是,如果需要适用第三条的不能胜任工作,公司需要首先进行培训或者调整工作岗位,且能够提供对应的证明材料。其次公司需要提供的证明材料较多,包括:首次不能胜任的相关证明,进行了合理的培训或者调整岗位的证明,再次不能胜任的相关证明。\n故虽然此点可能作为人事的托词但实际举证难度较大且绩效考核标准的订立可操作空间大在实际仲裁乃至诉讼过程中用人单位被判定为不利的概率极高。一旦此点认定失败将直接被认定为非法解除劳动合同从而致使补偿金 N+1 升级为赔偿金 2N 。\n其中的第四条客观情况发生重大变化也比较喜欢被某些人事加以利用。需要明确的是此点包含两条重要约束即客观和重大变化。即变化所产生的原因并非用人单位所能主观决定和控制而非单纯的因为组织架构调整就能够引用此条予以辞退。另外在解除劳动合同前也需要与劳动者进行协商提供相近或类似的工作岗位并且待遇不能低于原岗位。在劳动者拒绝的情况下才能适用本条。\n最后对于调岗的情形需明确调岗后的职级、工作内容与原岗位相近且待遇不低于原岗位新岗位不存在任何歧视性、侮辱性。用人单位行使法定调岗权应对调岗的合理依据承担举证责任。\n3. 违法解除劳动合同的情形\n所有不适用以上情形的情况由公司提出解除劳动合同的情形均属于违法解除。如果公司方面主张因为以上情形解除劳动关系则需要由公司进行举证。在公司无法拿出充分证据予以证明的情况下同样会被认定为违法解除。\n所有的违法解除劳动合同的情形赔偿金为 2N 。\n4. 补偿金或赔偿金如何计算\n补偿金 = 在职年限Nx 工资基数\n赔偿金 = 2 x 在职年限Nx 工资基数\n无论是第二节中提到的补偿金还是第三节中提到的赔偿金其金额基数均为劳动合同解除或者终止前十二个月的平均工资含奖金、津贴和补贴。如工作不满十二个月按照实际工作的月数计算平均工资。\n其中的在职年限除去整年部分后满六个月以上的计一年不满六个月的计半年。例一年三个月按照 1.5 年计算,两年十个月按照 3 年计算。\n对于第二节中有提到需提前 30 日书面告知劳动者的情形,如有进行告知则无需再额外补偿一个月工资。如未告知则需补偿 N+1 。\n综上对于法定范围内的补偿金或赔偿金仅有N, N+1, 2N 三种情形。在递交劳动仲裁申请时,务必按照对应的情形计算可能的最大补偿(或赔偿)金额。具体金额在仲裁审理时会进行重新计算,但不会超过仲裁申请时所提交的金额。\n5. 申请劳动仲裁需要提交哪些材料\n如果我们已经确定要提交劳动仲裁申请必然要先知道所需材料。各地对于劳动仲裁申请所需的材料略有出入但大体上包含以下这些\n\n身份证复印件\n工作证明复印件如劳动合同\n离职证明\n公司工商信息\n劳动仲裁申请表\n相关证明材料\n工资条工资流水\n\n具体的要求可以在网上搜索当地地名加劳动仲裁或直接前往劳动仲裁庭咨询了解。其中的公司工商信息可在当地的“企业信用信息公示系统”网站按照企业名称搜索并打印即可劳动仲裁申请表一般在当地政府政务网站或仲裁机构的网站上可以下载。\n对于裁员请求经济补偿或赔偿的情况离职证明属于必要材料需由公司开具。如公司推脱或者拒绝开具一般可以向当地劳动监察大队举报。\n劳动仲裁申请的部分可参照参考信息中的链接二也可以在网上搜索当地地名加劳动仲裁指南。\n多数情况下工作证明即劳动合同如未有签订劳动合同也可以提交其他证明材料如社保缴纳记录工资条打卡考勤记录等。\n其他可能用得上的证明材料如培训记录、调岗记录、绩效考核标准、绩效考核邮件、其他内部邮件、沟通记录截图等均可以提交。\n6. 后续流程\n在材料递交后仲裁庭首先会告知是否受理以及受理后的开庭时间。劳动者本人只需按时出庭即可用人单位是否出席不影响裁定。这里我并没有实操经验但大家只需要据实应对争取合法权益即可。正因为我们之前一直有提到劳动者在合同关系中处于弱势方仲裁庭基本上还是会尽量出于维护劳动者权益的角度进行裁定。\n另外一方面在劳动仲裁中用人单位方掌握并且控制了大量的信息所以相关法条也有进行规定与争议事项有关的证据属于用人单位掌握管理的用人单位应当提供用人单位不提供的应当承担不利后果。\n既然大家已经选择了进行劳动仲裁就应该充分信任仲裁庭能够给予公正客观的裁定结果。毕竟设立劳动仲裁庭的目的就是为了保护劳动者的合法权益总不会有哪个用人单位去申请仲裁吧\n裁定结果出来后如果对于我们的主张诉求予以支持直接找公司要钱即可。如公司拒绝在超过限定时间后可以向法院申请强制执行。这些后续细节裁定书中应该会有说明不用太担心。\n任意一方对于裁定结果不服都可以提起诉讼。涉及到打官司已经超出本文的科普范围了建议咨询律师。\n在实际操作过程中可能存在仲裁开庭前公司注销的情况发生reizhi 对此类问题没有操作经验,同样建议咨询律师,有可能需要通过诉讼解决。\n7. 协商\n上面这些信息对于人事来说都是必知必会但对方有可能利用信息差在协商中占据优势。在我们了解全部的相关知识后便可以从容的与人事展开协商谈判了。如果你已经做好了劳动仲裁的决心以下是一些常见托词的应对逻辑\n无法胜任需由公司举证且举证难度大需先调岗或培训绩效考核存在主观性可操作空间大置信度低\n客观情况发生重大变化需要是客观的不可抗力重大变化足以影响公司经营或合同执行需提供调岗机会\n时间周期长结果不确定仲裁庭的本质是劳动者保护组织公司举证责任多、难度大劳动仲裁记录在企查查等网站均可查到无论结果对于公司都没有好处\n如果公司方已经斩钉截铁的表示无法给到应有的标准但可以适当降低进行补偿则是否接受需要取决于自身。\n8. 参考信息\n\n劳动法全文\n劳动法解释\n浙江省劳动争议仲裁委员会\n劳动合同解除的法律规定\n益阳市劳动争议仲裁委员会\n赣州市中级人民法院劳动争议审判庭\n关于劳动争议仲裁程序的规定\n\n本文转载自「 reizhi 的博客 」原文url.hi-linux.com/KXvBv版权归原作者所有。"},"Professional/Work/roadmap/权益保障/职场维权实战经验":{"title":"职场维权实战经验","links":[],"tags":["工作/权益"],"content":"这是我第一次尝试写个人年度总结。\n我的 2023 年与 2022 年不可分割,一直走在维权的路上。\n早在 2022 年初,我的职业生涯发生重大转变,公司在未与我协商的情况下,单方面将我待岗,降低工资,移交工作。我从熟悉的工作环境被迫成为了一个「半自由职业者」。我之所以自认为是半自由,是因为公司未与我解除劳动合同,所以劳动关系还在原公司。法律规定劳动者只能和一家用人单位签订劳动合同,所以我在与公司存在劳动争议的情况下,无法入职下家公司。\n除此之外公司隔几个月后停发我的工资切断了我唯一的经济来源。我开始尝试学习《劳动法》及相关法律知识查阅和自己案件类似的裁判文书整理书面材料为的是跟公司对簿公堂讨回做为劳动者的尊严和权益。\n在劳资关系中公司具有优势地位而劳动者处于弱势的一方。尤其是面对老板、人事、法务组成的流氓团伙时会更加被动、愤怒、迷茫、无助。希望大家在面对公司的恶意时可以更加从容是我写下这些文字的初衷。\n在职仲裁 or 离职仲裁\n以前一直以为遇到劳动争议问题要离职后才能提起仲裁但后来从网络了解到我的案件情况更适合在职仲裁在职期间可以随时申请所以我**尝试提起在职仲裁。**仲裁期间可以正常上班,自己也有机会尽可能地多搜集一些证据。因为公司取消了我的办公权限,我目前已经不需要去公司打卡了。\n相比在职仲裁选择离职仲裁是最为常见的情况可固定和搜集的证据空间有限适合情况简单的案子。需要注意离职仲裁有时效性期限为一年。也就是说发生劳动争议后需在劳动关系终止之日离职当天起一年内提出。否则既不能仲裁也不能诉讼。\n\n劳动人事争议仲裁流程图图源附件材料\n员工不能提供离职证明的解决办法\n如果已经和公司解除劳动合同 但公司不配合,我们无法在入职新公司时提供证明该怎么办?\n正常的法律渠道\n依照法律规定用人单位有义务在解除劳动合同时出具离职证明。所以我们可以打电话向当地劳动监察大队投诉或者通过劳动仲裁要求公司出具离职证明并赔偿由此带来的损失。但这么做要花费一定的时间成本。\n相对简单的解决办法\n虽然我们不能提供离职证明但若是在客观事实中与上一家用人单位的劳动合同已经解除或终止则公司录用我们时已无法律障碍。我们可以提供与原公司劳动合同解除或终止的相关证明例如向原公司提出的《离职申请》、《工作交接记录》、《社保减员证明》等。\n我们还可以向将要入职的公司出具《承诺函》\n本人 A身份证号xxx向 B 公司郑重承诺,本人已经与 C 公司劳动合同解除,若因本人做虚假承诺,给 B 公司造成任何不利后果都由本人承担。落款承诺人签名x 年 x 月 x 日。\n提起劳动仲裁前需要注意什么\n分享一个我在仲裁前来自律师的建议在准备《仲裁申请书》的请求事项中可以把能想到的都写上未休年假、加班费、绩效提成等每项要写清楚详细的计算方式然后对应去搜集证据围绕诉求中的主张和证据阐述事实和理由。\n仲裁委不一定支持当事人的全部主张但没写在请求事项中的内容一定不会得到支持。\n我将注意事项的重点内容简单做了如下总结\n\n确认本人与用人单位签署了正式劳动合同排除劳务合同、劳务派遣合同等并确认自己是否保留了入职以来的全部合同原件。\n如签订劳动合同、请确认合同中是否明确约定了薪酬情况、薪酬构成、工作岗位名称、工作内容、入职时间、工作地点。\n完整保存了与公司沟通协商的往来邮件、微信聊天记录。\n整理好手中现有的证据列出清单。\n劳动仲裁是必经前置流程不可直接去法院起诉。\n\n提高法律意识留心法律风险\n在遇到突发性岗位变动或工作安排调岗、转岗、待岗等一定要留心这当中的法律风险不要在任何书面材料上签字劳动者有权拒绝公司任何不合理不合法的行为。如果跟公司有协商和谈判空间**可以尝试为自己争取一个不低于心理预期的好结果。**但如果公司想裁员,话 HR 找你谈话,连 N 都没有,要诚意没诚意,还不好好说,想套路你,故意搞你心态。别犹豫,拿起法律武器吧。\n法律是每个公民都可以用来保护自己的权利做为一名普通劳动者我觉得维权最重要的除了证据和诉讼策略更重要的是维权的勇气和决心。\n经济补偿金N与 经济赔偿金2N的区别\n经常遇到这样一个问题「员工被公司辞退了应该赔偿 2N 还是 N+1」\n经济补偿金就是我们大家口中常说的「 N 」,「 N 」是工作年限,用来指代劳动合同法中的经济补偿,计算方式是:经济补偿金= 工作年限 x 月工资。\n「工作年限」也叫司龄是补偿金和赔偿金的基数。工作满 1 年支付 1 个月工资。不满 6 个月的,支付 0.5 个月的经济补偿;满 6 个月以上但不满 1 年的,按 1 年支付。\n「月工资」是指劳动者在劳动合同解除或终止前 12 个月的平均工资(包含奖金、绩效、年终奖等应得收入)。\n经济赔偿金公司「违法解除」劳动合同产生的惩罚性赔偿计算方式是经济补偿金中「N」的 2 倍也就是「2N 」。如果存在违法解除的情况,\n据我了解包括大厂在内的绝大多数公司都不守规矩并不会按照法律标准去执行。有基础法律意识的公司想要裁员时会尽量规避「违法解除」劳动合同所以一般来说「2N」的案子会越来越难打员工三期孕期、产期、哺乳期内遭到公司违法解除劳动合同的情况能相对简单一些。公司会更倾向在「协商解除」的法律框架内做文章。\n《劳动合同法》只规定了「协商解除」的最低标准是「 N 」另外就是「N +1 」, 1 是指额外支付的 1 个月工资代通知金即时解除。除此之外「N + 2 」 还是「 N + 3 」都没有法律依据。在 N 的基础上,公司想额外支付多少都没有法律限制, 只要双方协商一致「N + 任何数字」都可以。\n举个例子公司想裁员找你协商但你不同意若公司一意孤行就要裁你说你绩效不达标单方面解除了劳动合同此时就是违法解除最低是「 2N 」。当然,劳资关系很复杂,公司可以找很多解除劳动合同的理由。如果想打「 2N 」你需要提供充分的证据证明公司的行为违法才有可能拿到「2N 」 。\n以下是我整理的关于「2N」的常见情形\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n用人单位解除劳动合同情形情形性质赔偿金劳动者被依法追究刑事责任用人单位解除劳动合同。合法解除0劳动者在试用期间被证明不符合录用条件用人单位解除劳动合同。合法解除0劳动者严重违反用人单位的规章制度用人单位解除劳动合同。合法解除0劳动者严重失职营私舞弊给用人单位造成重大损害用人单位解除劳动合同。合法解除0劳动者同时与其他用人单位建立劳动关系对完成本单位的工作任务造成严重影响或者经用人单位提出拒不改正用人单位解除劳动合同。合法解除0劳动者以欺诈、胁迫的手段或者趁人之危使对方在违背真实意思表示的情况下订立或者变更劳动合同的情形致使劳动合同无效用人单位解除劳动合同。合法解除0劳动者处于法定保护期如孕期、产期、哺乳期用人单位解除劳动合同。违法解除2N未经劳动者同意用人单位滥用解除权试用期解除权擅自解除合同。违法解除2N在本单位连续工作满 15 年,且距法定退休年龄不足 5 年用人单位解除劳动合同。违法解除2N在本单位患职业病或因工负伤并被确认丧失或者部分丧失劳动能力用人单位解除劳动合同。违法解除2N从事接触职业病危害作业的劳动者未进行离岗前职业健康检查或者疑似职业病病人在诊断或者医学观察期间用人单位解除劳动合同。违法解除2N患病或者非因工负伤在规定的医疗期内用人单位解除劳动合同。违法解除2N连续签订 2 次固定期限劳动合同并且劳动者没有严重过错、没有「不胜任岗位」「不能从事原岗位工作」的情况合同期满用人单位不同意不续签。违法解除2N\n《劳动法》的有效学习工具\n中国裁判文书网\n中国裁判文书网简称“裁判文书网”是由最高人民法院主办的官方网站主要目的是公开全国各级法院生效裁判文书以促进司法公正和透明度。\n这是我日常使用频率最高的工具之一是非常实用的司法实践参考。这个网站提供了丰富的研究素材和数据可以检索到全国各地法院各类案件的一审、二审或再审判决书细分选项特别多。\n虽然劳动仲裁裁决书不公开只允许当事人及其代理人查阅。但我们依然可以从公开的他人判决书中看到一些仲裁信息如当事人的主张及理由。\n我们可以通过裁判文书网查询和研究先前的判例了解当地法律趋势解析审判口径。例如劳动者和公司双方的争议点是什么哪些主张和证据被法院支持为什么会支持为什么会驳回。以及在结案陈词中法官是如何看待问题的。\n\n小红书\n因为小红书有很多人将自己劳动仲裁的相关经历经验以笔记的形式分享也有很多律师在平台上分享一些办案经验和法律知识所以我觉得将它非常适合搜索高质量的信息提前做好功课多方验证信息也可以让自己少走些弯路。\n中国法律快查手册\n中国法律快查手册 是一个 Github 上的开源项目,内容来源于国家法律法规数据库,这个项目的作者将数据库做了整合和搜索等功能,排版简洁,使用起来简单方便,非常适合平时查询和学习。作者仅提供了手机版( iOS、iPadOS和网页版并未提供电脑端版本但我在 M1 MacBook Pro 也可以通过 App Store 应用商店安装使用。\n劳动争议的话建议主要关注《中华人民共和国劳动法》《中华人民共和国劳动合同法》这两个法规。\n\n图源 / GitHub\n靠谱律师怎么找\n通过研究司法案例以及本地近期公开的劳动争议相关判决书我学到了一些劳动法基础知识开始尝试梳理自己的案件情况并希望可以得到律师的一些专业建议。先说说找律师来代理案子的 2 个常见误区\n误区 1 :律所越大越好,名气越高越好。\n名气高的大律所服务的对象一般是大公司因为劳动者的案子都是标的金额低的小案子不赚钱。\n术业有专供不是所有律师都擅长打劳动仲裁的案子。所以正确的方式是找主要做劳动争议案件的律所或是主要代理劳动争议的律师。\n可以是通过熟人朋友、同事、家人推荐这样有一定的信任基础也可以在小红书搜索看看其他人选择的律师是否口碑好案例多。\n如果在律师的履历介绍中可以看到他擅长的领域很多那不一定是好事。我们需要的是履历介绍中更多和劳动争议相关的律师。\n误区 2 :花了钱请律师代理,就可交由律师全权负责\n我们的劳动争议案件虽然标的小且不赚钱但不妨碍它很复杂。需要投入大量时间研究准备和开庭跑仲裁或法院。\n律师也是如此。律师作为法律工作者是提供专业的法律帮助而不是代替处理相关全部事项。关于案件中的取证、和有关部门交涉都需要自己来完成律师只是在这个过程中提供指导。律师可以帮忙争取最好的结果但不能避免所有的风险。\n作为当事人我们对公司和自身情况最为了解庭审时法官会围绕每个细节进行详细询问这也是为什么自己要重视开庭并亲自参加庭审的原因。为了降低诉讼中存在的风险我们需要多和律师交流讨论自己要先厘清思路整理好证据做好充足准备在开庭时才能自如应答不会因为紧张而遗漏重点。\n通过以上 2 个误区,我们可以对这部分做个小总结:\n\n专业领域的重要性我们需要考虑自己的案子类型和律师的专业领域是否匹配\n选择合适的律所和律师选择有良好声誉和口碑的律师\n律师的角色请律师并不意味着可以完全放手律师的角色是指导和争取最佳结果而不是替代自己处理所有事物。\n当事人的参与我们做为当事人应对自己的案件有深入了解并积极参与庭审准备与律师充分沟通整理证据清晰思路尽可能降低诉讼风险。\n\n找律师途径之一中国法律服务网12348 中国法网)\n\n这个由司法部建设的网站是于 2018 年 5 月 20 日正式上线运行。网站整合并收录了全国范围内的「法律服务机构」和「法律人员数据」。\n我们可以在里面选择律所或律师也可以通过网站查询从其他渠道了解到的某家律所或某位律师可查询律师执业证号。\n\n为找律师我做了哪些尝试\n算下来我前后共咨询了 3 位律师(不包含法律援助)。我寻求律师帮助的路径是:在线咨询律师 A付费—— 线下咨询律师 B (付费)—— 线下咨询律师 C (付费)\n在线咨询律师 A\n最开始我先尝试了在网上找律师付费咨询\n虽然付费价格支付 168 元)比线下咨询律师便宜很多,但是与价格相对等的是提问有次数、字数、时间限制(只能文字沟通不能语音),如果在律师不了解相关背景情况下进行提问,这将导致律师因无法判断案情而无法提供合理化建议。\n于是我尝试尽量精简文字表述将提问内容分为事件背景时间线、我的现状、核心问题制作成一张图片发送给律师。律师对我提问的内容一一做了解答但是我结合自身情况判断出律师提出的解决方案存在的风险比较高所以我没有采纳。\n线下咨询律师 B\n在律师朋友的介绍下我联系上了一位主要代理劳动争议案件的律师律所离我也不算远约了时间线下面谈。这次收获蛮大的之前担心的问题基本都得到了解决心里也更踏实了只不过我的情况比较被动需要看公司下一步的动作。\n线下咨询律师 C\n律师 C 是同事推荐,对于劳动仲裁案件的经验非常丰富。也是我综合考量后,选择了律师 C 委托代理我的一审案子。\n关于律师咨询费。北京这边 200 - 3000 元 / 小时不等,我在线下咨询律师 B 两次,每次都是 500 元 / 小时。\n关于律师代理费。根据案子标的额的百分比收取不同审判阶段仲裁、一审、二审费用也不同。\n少走弯路准备证据和录音技巧\n准备证据\n一键下载仲裁所需的全部材料\n包含劳动仲裁立案申请、证据交换、出庭使用的材料模板可以通过 北京市朝阳区人民政府官网 页面底部的「点击此处下载相关附件」获取。文档中还有相关办理流程、注意事项,内容非常全面,可以仔细查阅。\n\n自助打印银行工资流水凭证\n本人带上身份证原件直接去附近银行营业厅的自助机上打印可自行在机器上操作省去拿号排队去窗口的过程在使用银行自助机的过程中有任何问题都可以找身边的银行经理帮忙解决非常高效。建议在打印前了解相关费用标准并做好准备有的银行会限制每月免费打印次数超过则按张收取费用。我的工资是由公司通过 3 家银行(北京、交通、招商)发放,所以我需要去 3 家银行分别打印流水,北京银行和交通银行的自助机没有对流水单设立打印限制,但招商银行的打印限制我记得是 4 张 / 月,超过按 20 元 / 张收费。\n在银行自助机操作时我总结了 3 个重点:选择时间范围、筛选交易类型、包含银行盖章。\n选择时间范围依据劳动争议涉及的时间来选择流水打印范围需按年选择不可跨年。\n筛选交易类型要在筛选栏勾选交易类型工资指定筛选条件的目的是为了方便自己和他人在查看银行流水单时让工资发放情况一目了然我们只需要工资流水的相关证明不需要其他交易记录。\n包含银行公章银行自助机打印的工资明细一般默认包含公章但也有个别银行需要在打印前勾选相关选项后才可打印出盖了章的流水单。公章名称一般叫「回单专用章」或「会计业务章」。打印前后一定要留意打印的流水单是否包含银行的公章如果没有公章则证据无效。\n\n\n我的银行流水单盖章北京银行 ;右:交通银行)\n利用 iPhone 备忘录扫描《劳动合同》复印件\n因为打印出来的纸张是黑白效果如果直接使用手机将《劳动合同》拍照、会导致部分信息模糊不清这里有个便捷好用的小技巧利用 iPhone 备忘录中的「扫描」功能,逐页将《劳动合同》扫描成 PDF 文件后再打印(相比直接打印效果更清晰,相比复印更省事)。可以避免因提交材料不合格导致返工的情况(不要重蹈我的覆辙)。\n\niPhone 备忘录中的「扫描文稿」功能\n打工人必备 App —— 权利卫士\n这是一款由国家知识产权局推出具有法律效率的 电子取证工具(仅支持 iOS、Android ),被法律工作者广泛使用。可生成不可篡改的带有时间戳的电子证据。取证范围包含:拍照、录像、录音、录屏、网页。在 App 中实名认证就可正常使用。\n如果有些证据比较重要可以选择这个工具。例如在公司对我的办公软件停用前我就使用了权利卫士的录屏功能对组织架构、个人信息等情况进行了证据固定。法律规定谁主张谁举证的原则在提起仲裁或诉讼时我就有了通过权利卫士保存的电子版基础证据。\n权利卫士可以很大程度上代替传统的公正取证方式。正确使用权利卫士可以在价格低廉的同时让取证变得更快捷。但它终归只是一个取证工具证据的真实性没问题但是否会被采纳能发挥多大作用是需要深度思考的问题。如果拿不准可以在律师的指导下使用毕竟每次取证都需要付费。\n\n录音技巧\n\n时间录音证据宜早不宜晚\n设备无论面谈与否要全程录音能清晰听清双方谈话内容的设备皆可。如果是电话沟通并且是苹果手机没有通话录音功能可以向朋友借一台手机用来录音。\n操作手机可以开启飞行模式防止突然来电导致录音中断\n\n注意事项\n录音证据大多情况都不能被仲裁庭采纳主要原因是录音中的谈话内容缺少适格主体等关键信息例如公司法人张三、人力资源负责人李四。录音属于锦上添花能有更好如果获取不到有用信息也没有关系。\n录音的目的是通过谈话问清事实情况便于进一步固定证据。不能威胁恐吓对方态度友好否则证据无效。值得一提的是录音证据的目的是为了佐证其他关联证据形成证据链不能单独使用。\n谈话中不仅问题要清晰明确还需要做到谈话人身份明确内容清晰具有客观真实和连贯性。可以先理清思路再写成书面材料通话前尝试练习几遍。\n提交录音\n需要注意的是录音做为证据时要做两件事一是要将未被剪接或者伪造内容未被改变无疑点的完整音频文件刻录成光盘二是要将全部对话内容整理成文字版书面材料。\n**录音内容文字版:**建议写明这些信息:时间、地点、设备、时长、当事人信息(本人名字、公司负责人职称和名字)。最后,在《证据目录》中标记好录音文件的位置,将录音光盘、文字版随其他证据一起提交。\n另外录音原视文件和载体如手机要保留好用于庭审时查验。\n我的录音沟通提纲\n\n确认双方主体和身份\n确认相关的事实\n履行友好协商的态度明确提出自己的主张\n\n我的通话前录音内容\n\n对着录音自我介绍并陈述事实我是 xxx身份证号 xxx自 x 年 x 月 x 日在 x 公司x 部门,担任 x 职位。\nx 年 x 月 x 日起,公司 xx简短陈述事实内容我现在要给公司人力资源部总监 xx 全名拨打电话协商解决方案。Ta 的电话是 xxx。\n\n\n证据材料清单样表图源附件材料)\n寻求免费的法律援助\n法律援助更像是针对「特殊群体」设立的专项服务主要服务于农民工或年纪较大的人。\n朝阳劳动仲裁委员会也设立了法律援助咨询窗口在服务总台领号排队与仲裁立案窗口同在一个大厅。或许是我的案子具有复杂性也可能窗口的工作人员并没太多时间帮我深度分析我将手里的证据给到对方尝试了解对于我这种情况的政策和裁判口径但我并未收获到有用的信息和指导性建议。\n所以大家可以尝试性去咨询但不要对法援抱有太大期望。也不要轻信仲裁委门口主动发卡片的律师咨询我从没见过有执业证的律师需要揽客这些卡片上的律师很可能就不是律师十有八九不靠谱有很多被人被骗。\n我的完整仲裁流程\n在仲裁阶段我选择的是自己走完全流程委托律师代理的是一审诉讼。\n一是因为北漂多年有过仲裁经历。\n二是因为之前外籍二房东不退押金并大放厥词可以去法院告他。于是我就听了他的建议自己写诉状去法院起诉所以有一些民事诉讼的经验。\n劳动仲裁的立案、交换证据流程和法院诉讼在某些方面有相似之处。所以我觉得仲裁相比诉讼来说在准备充分的情况下要简单很多我的劳动争议案子偏复杂需要经过法院审理。\n以北京朝阳区为例可以在北京人社局官网提前预约预约后会短信告知线下提交立案材料的时间。疫情时官网预约后需要等 1 个月以上,现在要等的时间不好说。\n也可以选择可以直接去线下领号立案更推荐这种方式更高效。建议准备好材料在 8 点前到门口排队, 10 点前拿到号。否则可能会由于人多无法当天立案。我在疫情时和疫情后分别成功立案 2 次,是针对劳动争议中的不同时间段的仲裁请求。现在疫情已经过去,流程也简化了不少,相对来说更省事儿了。\n仲裁地点\n北京市朝阳区劳动人事争议仲裁院\n电 话010-87983310\n地 址:北京市朝阳区将台路 5 号院 15 号楼 B 座、C 座\n准备材料\n\n身份证原件\n身份证复印件 x 3\n申请书 x 3\n地址确认书 x 1\n\n建议检查好相关材料并将电子版备份到 U 盘,最好是带上笔记本电脑,若书面材料不符合立案窗口要求,可以即时用自己电脑修改,若有漏打材料,也可在服务台旁边的打印区付费打印。\n立案流程\n\n去总服务台领取地址确认书填好领取初审号码可以提前打印好直接领 A 开头初审号码)\n初审后收到 B 开头立案号码,等待叫号。\n立案窗口工作人员可能会让填一个劳动调解表。这步可以直接放弃调解直接走程序省时间因为开庭前仲裁员还会再次调解\n\n完成立案\n成功立案后窗口会现场出具举证通知等书面材料立案后有 30 天的调解时间,期间会有工作人员打电话给当事人(公司、劳动者)双方,询问是否同意调解。接下来会收到朝阳仲裁委关于交换证据的通知邮件,以及短信提醒。\n交换证据\n需要注意自己和公司方的交换时间是一样的务必要按照规定时间内到达指定窗口办理举证及证据交换必须是本人否则过时不候。提交完成并签字确认后就可以离场了如果在现场遇到公司的人也必理会。\n等待庭审\n接下来等待开庭通知就好。开庭时要携带身份证原件、证据原件。需要注意开庭时间 **如果开庭当天本人迟到,会被视为撤诉。**仲裁开庭也比较简单,不会法院审理案件那样细致。主要是仲裁员通过问询双方当事人,录入双方确认的一些信息,如争议时间、质证理由、社保状态、薪资情况等。\n仲裁案件都是随机分别仲裁员我是 2022 年底立案, 2023 年初开庭,直到 2023 年 10 月才收到裁决书。大家可以多联系自己案件的仲裁员,催问进度。\n仲裁结果\n身边总有朋友认为收到的劳动仲裁裁决书上支持了相关请求事项就是胜利的信号但仲裁是以调解为主并不能最大限度维护劳动者自身权益。例如法律规定协商解除劳动合同的最低标准是 N ,假设 N 是 10 个月,仲裁员会和公司、劳动者分别协商,讨价还价后,最终 N 可能是 6 或者 4甚至更低看似减少了劳动者维权的时间成本实际最大受益者却是公司一方公司试图用远低于法律规定的标准带有恶意性、针对性、侮辱性的手段低成本实现裁员目的。\n所以劳动仲裁对劳动者来说只是维权之路的起点还要经历一审诉讼、二审诉讼即使最终赢了官司还可能面临向法院申请强制执行的情况。\n写在最后\n遇见过一些 HR ,千方百计地学习裁员套路和话术。一个员工为企业服务这么多年,非但不感谢员工多年的辛苦付出,反而为了达成裁员目的搞手段,扣帽子。想法设法压榨剥削打工人,员工不和你死磕跟谁磕?员工就是一个个普普通通的人,不止看重钱,还很在乎你怎么对他。\n这个世界很奇妙。代理我案子的律师最近就遇见了一个离谱案件将这个真实案例用一句话概括就是职场当中套路虽多但涉及底线的东西并不适用于套路。谁也说不准后面被搞心态以及被裁的会不会是自己。\n\n本文转载自「 少数派 」原文url.hi-linux.com/jpw6C ,版权归原作者所有。\n"},"Professional/Work/roadmap/求职经验/互联网行业-郑州":{"title":"互联网行业-郑州","links":[],"tags":["工作/面试"],"content":"大家好呀,我是大白,在我咨询了一些朋友并且经过好几位郑州当地读者补充后,终于整理出来一篇比较全面的介绍郑州互联网环境的文章,希望大家支持呀!\n工作机会\n郑州的互联网资源还是比较匮乏的究其原因我觉得和教育资源的匮乏有非常大的关系。\n教育资源极度匮乏导致好的企业不来好的企业不来又导致人才外流恶性循环。\n\n数字郑州\n这个是阿里和郑州的政府合作的目前评价大家对数字郑州的评价很不错呀薪资也挺给力的大家可以看下 Boss 上数字郑州的招聘岗位以及薪资报价呀。\n\n中原银行\n中原银行的工资比较高在郑州生活的话去中原银行是很不错的选择不过想进中原银行的话不是校招想进去有点难。薪资水平可以看下 Boss 上的招聘薪资水平。\n\n浪潮\n浪潮在郑州的研发中心法定节假日加班是有加班费的但平时加班就没有加班费了每月要求加够 50 个小时的班。薪资水平大家也可以参考下 Boss 上放出的招聘薪资水平。\n\n新华三\n新华三大部分情况下能双休周末加班也有加班费不过涨薪很缓慢。在网上看到一个帖子有人问 offer 选西安中兴还算郑州新华三,中兴和华三的职工都在互相劝退,说这是一个送命题。薪资水平大家还是参考下 Boss 上的招聘薪资水平吧。\n\nUU 跑腿\nUU 跑腿主要提供同城送件服务,是郑州本土最大的互联网公司,隶属于郑州时空隧道信息技术有限公司,地址位于郑州市金水区。\nUU 跑腿的工作环境以及各种福利都还算不错!\n面试的话总体体验还不错技术面试一般问的还比较全面。拿 Java 后端开发来说,像 SQL 优化、分布式、缓存这些一般都会问到。\n薪资的话看准网上的平均薪资是 10k 附近,其中后端开发的薪资在 14k 附近,前端开发的薪资在 10k 附近,软件测试的薪资在 10k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入)。\n\n中原消费金融\n河南中原消费金融股份有限公司是一家全国性非银行金融机构地址位于郑州市郑东新区。\n中原消费金融的办公环境非常不错薪资福利相对也还不错。\n整体面试体验不错效率也非常高像技术面试的话一般是三轮或者四轮。不过中原消费金融比较看重学历985/211 上岸的几率比较大。\n薪资的话看准网上的平均薪资是 16k 附近,其中后端开发的薪资在 17k 附近,前端开发的薪资在 16k 附近,软件测试的薪资在 14k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入,应该到不了这么高)。\n注意大家注意一个情况中原消费的软件研发岗位大部分都搬迁到上海了目前在郑州的大部分是行政岗位只有少部分研发岗位。\n\n刀锋互娱\n刀锋互娱是一家专注游戏服务市场的互联网公司2019 年完成 A+ 轮融资,平台注册用户量突破千万。\n旗下比较出名的产品有租号玩、一派陪玩都是和游戏领域相关的产品。相信比较喜欢玩游戏的小伙伴应该对这个两个产品有了解。\n整体面试不是很难薪资相对来说也还可以。\n薪资的话看准网上的平均薪资是 16k 附近其中后端开发C++)的薪资在 20k 附近,前端开发的薪资在 8.5k 附近,软件测试的薪资在 9.5k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入)。\n\n新开普\n新开普也是郑州的一家本土互联网公司成立于郑州高新技术产业开发区主要做 NFC 近场移动支付、金融 IC 卡等业务。\n新开普是目前国内一卡通行业唯一一家上市公司已经为全国千所高校千万名大学生提供服务。\n技术面试的话一般第一面是笔试笔试之后会再问你一些相关的技术问题。\n薪资的话看准网上的平均薪资是 7.6k 附近其中后端开发Java的薪资在 9k 附近,前端开发的薪资在 9k 附近,软件测试的薪资在 5.5k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入)。\n\n中移在线\n中国移动旗下的一家“互联网”公司实际不像是“互联网”公司。\n对于技术开发来说去中移在线一是对技术没有提升或者挑战二是工资是真的低看准网上的 Java 开发薪资在 8k 附近)。\n真心不太建议去除非你没有其他更好的选择。\n我能想到唯一的优势可能是公司相对来说能提供给你的一个相对稳定的工作。\n爱云校\n爱云校常见于 2014 年,主要做的是在校教育这块,致力于通过 AI 建一所云上的学校。\n单看公司所做的业务方向来说发展相对来说还是不错的。不过据说公司的管理真的是渣到了一定程度。\n另外根据大部分面试求职者的反馈来看这家公司的整体面试体验比较差。\n薪资的话看准网上的平均薪资是 12k 附近其中后端开发Java的薪资在 14k 附近,前端开发的薪资在 8k 附近,软件测试的薪资在 10k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入)。\n\n妙优车\n妙优车主要做的是汽车方面的业务涵盖整车销售、汽车金融、汽车保险、汽车用品、汽车美容等方面。\n公司发展一般网上也有一些黑历史 (可以自己查一下)。\n不过根据大部分面试求职者的反馈来看这家公司的整体面试体验还是可以的。\n薪资这块的一般偏上看准网上的平均薪资是 11k 附近其中后端开发Java的薪资在 12k 附近,前端开发的薪资在 10k 附近 (薪资水平仅供参考,实际情况因人和岗位或许会有一些出入)。\n\n腾河\n腾讯是河南腾河网络科技有限公司的最大股东第二大股东是河南日报。\n主要做的业务方向是河南城市生活第一网。\n工资比较低另外后端这块好像只招 PHP。\n真二网\n不得不说这个名字有点东西\n真二网创立于 2014 年,也是郑州本土的一家互联网公司,主要做 C2C 模式的 0 中介费真实二手房交易平台。\n工资比较低另外后端这块好像只招 PHP。\n硕诺科技\n硕诺科技创立于 2014 年,总部位于上海,主要做物流软件系统高端定制的软件开发。\n网上可以查到的消息比较少感兴趣的小伙伴可以自己去查一下相关信息啊\n另外如果有小伙伴对这家公司比较了解也可以在评论区说一下啊\n科大讯飞\n科大讯飞在郑州金水区有一个小分部大部分招聘的都是和技术无关的岗位不过也有一个 Java 开发岗。\n\n类似的还有美团、华为、阿里巴巴等大厂这些公司在郑州招聘的基本也都是非技术岗位。\n其他\n其他还有像郑州点读电子科技有限公司旗下产品有咿啦看书、羲和网络河南唯一一家游戏上市企业、米宅中国知名的楼市自媒体新三板上市企业等互联网公司感兴趣的小伙伴可以自行查阅相关信息呀\n读者补充海康威视、APUS、云鸟、亚信科技、牧原食品、小鱼易联、神州信息、云智慧都在郑州招开发工程师。\n\n转载自 CS 指南 zhuanlan.zhihu.com/p/412688735\n"},"Professional/Work/roadmap/求职经验/写给软件工程师的建议":{"title":"写给软件工程师的建议","links":[],"tags":["工作/面试"],"content":"前言\n最近一段时间通过和不同的人对话脑海中涌现出了一些想法。另一方面也意识到自己正处在职业生涯的某个节点上回顾从业的这几年有得有失所以想借这篇文章聊一下工程师成长这个话题旨在能给大家带来一点点思考。受自身经验所限这些观点不一定对希望朋友们可以辩证的去思考。因为自己的职业属性这里讨论的仅限于软件工程师这个群体。当然如果下面这些经验之谈能帮助到更多其他领域的同学那我也荣幸之至。下面是正文会分享几个个人认为工程师成长之路上很重要的点。\n基础很重要\n我之前作为一个求职者在面试的时候喜欢问面试官一个问题“你觉得优秀的工程师有哪些特质”不同的面试官给出的答案不尽相同但是他们几乎全都肯定了基础的重要性。\n究竟什么是基础我理解的基础大体上可以分为两类一种是硬性的、可以被量化的另一种是软性的、不可被量化的。这两者在你踏入职场前身上就已经具备了其中部分才能或者潜质。\n前者就是技术基础对于这一点不同岗位的要求是不一样的。比如以前招前端工程师时会要求你会 JavaScript、CSS、HTML 三剑客随着现在行业越来越卷要求的东西也越来越多React、Vue、TypeScript、数据结构、网络等等等等。这里面有很多都是计科或者软工专业的同学在大学里学过的课程。这些也是比较容易被后天习得的只要你肯踏踏实实静下心来学习几个月肯定会收获很大。\n而后者不可被量化的那一类则相对来说要难一些不是所有人都可以短时间速成的。有些人生下来就具备这些特质而有些人就算时隔多年也是在原地踏步。这些特质包括但不限于学习能力、解决问题的能力、沟通能力、领导力。工作时你会发现跟有的同事讲话非常顺畅一点就通而跟有的人沟通起来却很辛苦恨不得把一句话扳开揉碎了喂到他的嘴边这其实就是一种软素质较差的体现。\n说了这么多那么怎么样培养建立基础呢我的答案是刻意练习。明确自己的弱项然后不停地反复地去刻意练习它。我刚上大学那会儿每次上台讲话都会超级紧张紧张到发抖冒汗。后来我做了个尝试去学校的电信营业厅卖手机。这样每天都要被迫和许多人讲话慢慢地学会了比较从容地面对人群讲话。有一个著名的一万小时定律它说的是要成为某个领域的专家需要 10000 小时。其实如果能在某一项上,坚持练习 1000 小时,就已经非常非常厉害了。\n培养技术品味\n品味这个东西很难讲清楚。对设计师来说审美品味是必备的对于软件工程师来说同样也要有对于技术的审美需要知道什么是好的是优雅的。而且我发现技术品味跟工作年限并没有太大的关系更多跟个人的眼界有关系。当你看到的优秀的东西足够多慢慢地也会具备识别能力。\n所以提升技术品味的方法无它唯有开拓眼界多去阅读优秀的项目从中汲取养分。当然这里并不是推荐大家去阅读各种晦涩难懂的源码前端社区经常见各种源码分析的文章很多文章在我看来都只是在翻译代码用中文描述这些代码干了什么而甚少去研究别人为什么这么写背后的设计思想是什么。代码会过时而先进的思想永不过时。\n另外想推荐一本书《重构改善既有代码的设计》。很庆幸我在学校图书馆某个角落翻到了这本书让我知道了什么是好的代码。\n从错误中成长\n人非圣贤是人都会犯错尤其是对软件开发者来说犯错更是一件再正常不过的事。之前听公司里一位前辈分享他说现在的年轻人越来越谨慎不敢犯错怕承担责任但其实犯错有它的积极意义。\n刚参加工作那会儿记得是一个周五的下午。我匆忙提完代码准备上完线早早下班。结果一个操作失误把测试环境的代码发布到了线上。没过多久办公室开始炸了所有人都发现我们的首页白屏了因为线上请求全打到了测试环境的一台机器上整个事故持续了半小时。事后做了参加工作以来第一次 case study总结出了几点让我到现在也受用\n  1. 不要在周五下午上线。因为一旦出事,可能也会连累你的同事跟你一起加班。减少上线频率肯定是可以减少事故发生概率的。\n  2. 对上线保持敬畏之心,做好各个环节的线上验证。这样就算不能拦截问题,也可以早一点发现问题。\n  3. 机器比人可靠。对于上线这种高危操作,应该将过程尽量自动化,交给机器来完成,而不是人手动的操作。机器要比人可靠得多。这其实就涉及到一个公司的基础技术设施的建设,大公司在这方面做的要比小公司好很多。\n这种可以让人铭记终身的 case对个人的成长是很有帮助的。所以我想说不要害怕犯错犯错后积极总结经验避免同样的错误发生第二次才是最重要的。顺便还想说一下找工作时团队对于新人的宽容度或者说容错率我觉得也是求职者需要考虑的一个因素好的团队氛围会给予新人充足的试错空间这对于新人成长是很重要的。\n不要设限\n不要给自己设限这一点可以决定自己的成长天花板。比如对于前端工程师如果限定自己只在这一个范畴那么你可能会错过很多精彩的东西。三年前是切图仔三年后还是一个切图仔只是可能切图更快了这样可以做的事情会非常局限。而如果把自己放到一个更大的领域做一个软件工程师或者去接触产品运营去了解金融知识会发现世界又变大了一些。\n不断去接触新的事物可以让我们的思路更加开阔避免成为井底之蛙、坐井观天。一直以来不是很喜欢程序员这个称号不管是程序还是开发程序的技术本质上都只是工具。要去驾驭使用工具而不是成为工具的信徒。经常见社区争论不同框架哪个更牛还有 React 粉、Vue 粉,他们之间甚至还互相攻击,这就好像两个工人争论哪个牌子的大锤更好用。管它是黑猫还是白猫,能抓到老鼠就是好猫。\n多了解不同领域跳出固有思维模式换一个角度来思考有些问题或许会有不一样的答案。促使我们去了解学习这些的动力可以是对未知的好奇心可以是兴趣可以就是单纯为了赚更多的钱。\n以终为始\n“以终为始”Begin With The End In Mind是《高效能人士的七个习惯》里提到的一个习惯。这个习惯讲的是先在脑海里酝酿然后进行实质创造换句话说就是想清楚了目标然后努力实现之。一位美团工程师在一篇叫《写给工程师的十条精进原则》的文章里也将这一条作为原则之一。\n做一件事情前先想清楚做这件事的目标然后围绕这个目标去制定实施方案。虽然道理很简单但遗憾的是很多时候我们都忽略了这一点。这样导致的后果是我们可能花费了很大的工夫但最后收效甚微甚至事情做一半就黄了。这一点在技术项目上体现比较明显我自己之前就犯过这种错误。某一天发现可以在项目中引入一些性能优化技巧来提升首屏渲染速度于是很快就开始写代码然后迅速上线。后来在准备述职材料时发现我甚至不知道那次究竟优化了多少性能保不齐还是个负优化。对于这个例子当我们提出要优化项目首屏性能那么首先需要知道性能现状需要知道性能的瓶颈在哪基于这些信息来合理制定我们的优化目标例如把首屏时间从 3s 优化到 2s。然后才是制定优化方案最后才是写代码。\n最近几年国内互联网公司盛行 OKR 文化OKR 算是以终为始这个原则的有力实践。这个制度本身是好的,只不过在实践过程中,慢慢流于形式,变成了披着 OKR 外壳的 KPI这也招致很多人的吐槽。这个话题可以另写一篇文章来聊了。\n保持身体健康\n这一点也是我认为最重要的一点所以放在了最后。身体是革命的本钱没健康的身体其他任何事情都无从谈起。健康这个东西只有在失去了它之后才会真正意识到它有多么重要。一些俗套的祝福语“身体健康”、“幸福快乐”等等我发现确实是人最需要也最重要的东西。所以加强体育锻炼多出去走走吧。人生路还很漫长有强健的身体才能正常走完这漫漫长路。\n总结\n以上是我认为工程师成长路上很重要的几点。有些想法可能会随着年龄的增长、阅历的提升而改变也希望最好会变化毕竟如果一成不变意味着也就没有成长了。\n\n转载《写给软件工程师的几条成长建议》\n作者FrankXiong 地址:点击打开\n"},"Professional/Work/roadmap/简历攻略/IT-类简历":{"title":"IT 类简历","links":[],"tags":["工作/面试"],"content":"思维导图\n\n"},"Professional/Work/roadmap/简历攻略/简历原则":{"title":"简历原则","links":[],"tags":["工作/面试"],"content":"思维导图\n\n思维导图下载"},"Professional/Work/roadmap/职业规划/开发者职业路线图":{"title":"开发者职业路线图","links":[],"tags":["工作/规划"],"content":"必经路线\n\n前端路线图\n\n后端路线图\n\nDevOps 路线图\n\n关于\n中文仓库结合实际情况仅翻译了部分路线图推荐使用英文仓库因为较为全面。\n\n中文仓库地址chinese-developer-roadmap\n英文仓库地址developer-roadmap\n"},"Professional/Work/roadmap/职业规划/职业宏观规划图":{"title":"职业宏观规划图","links":[],"tags":["工作/规划"],"content":"职业选择\n\n\n结合实际情况决定\n\n职业观\n\n此图引用自知乎 陈思炜 发表的 回答。\n总结\n反推即可知当下可为不可为\n祝愿看到这篇文章的每一位好友\n早日暴富富富富富富富\n💰💰💰"},"Professional/Work/roadmap/职业规划/职业宏观路线图":{"title":"职业宏观路线图","links":[],"tags":["工作/规划"],"content":"从整体上看,程序员的职业发展可以分为 4 条路线分别是工作、SOHO、创业和投资它们的难度逐次递增人生阶层也逐次递增。当然这个路线也不是固定的可能随时切换比如你放弃了工作可以 SOHO你创业失败了可以继续工作。\n路线图\n\n1. 工作\n这是大部分程序员都会选择的职业发展路线即使那些功成名就的程序员往往也都是从工作开始。\n工作的风险最小心理压力也最小只要你不删库跑路基本每个月都能领到稳定的薪水。如果你有房贷或者已经为人父母工作会给你一种安全感。\n程序员凭借自身实力找工作而不是凭借社会关系只要你努力学习踏实钻研技术就能获得不错的报酬。相比其它职业来说程序员是非常公平的。\n如果你有幸进入大厂或者就职于独角兽企业几年以后年薪三四十万是非常现实的此时你就成了资深程序员。\n没有一个程序员想当一辈子码农大家都想当领导此时你有两个细分方向可以选择专家线路和管理线路。两条线路最大的区别就是\n\n专家线路主要和机器打交道需要不断地迭代项目优化数据和性能\n管理线路主要和人打交道需要控制资源和进度随时要和下属谈心向上级汇报。\n\n如果觉得自己情商不高搞不定领导和女人或者觉得和人打交道非常内耗需要很多时间恢复精力那可能不太适合走管理路线。\n注意能不能当领导不仅仅看技术实力有时候也看公司发展、机遇、情商、站队等这都是不确定的事情。\n对于工作的程序员来说在大型互联网公司当一个小领导年薪就能 40~50 万;如果你技术给力,情商也高,那么年薪百万也不是不可能。我的一个朋友,毕业五六年,跳槽到快手,年薪超过 150 W。\n如果你比较幸运较早进入一个有潜力的独角兽企业并获得股票或者期权那么当公司上市或者被收购你的回报可能超越别人十年的收入甚至直接财务自由。\n工作并不代表没前途选择不同的公司和岗位十年以后的差别是巨大的有人财务自由有人还是一线码农。\n如果你进入了一家大厂技术能力持续增长而且掌握了跳槽技巧那么年薪百万也并不只是梦想这足以干掉很多 SOHO 的程序员,甚至干掉很多小公司的利润。\n不要一味地追求创业好好经营工作也能成为人生赢家。\n2. SOHO\n所谓 SOHO就是自由职业者或者小老板。很多程序员所谓的创业其实不过是 SOHO一个人搞定产品或者销售即使有一个小团队自己也是团队的顶梁柱。\n我有时候也说自己是创业者其实我也是在 SOHO过着养家糊口的日子。\nSOHO 的原因有很多,比如:\n\n不想长期钻研技术担心身体健康\n情商不高在公司不容易混下去\n一二线城市买不起房回老家发展但是机会太少\n觉得工资不够想得到更多的回报\n喜欢折腾不管成功失败经历也是人生重要的一部分。\n\nSOHO 的风险和收益都很高,如果你的产品和服务卖不出去,那你就赚不到钱,生活会变得艰辛,如果你的切入点正确,而且具备相应的能力,那么年入百万也不多。\n不太推荐的 SOHO 模式就是外包接单,吃了上顿没下顿,也不能持续积累资源;说白了,干就有,不干就没有。\n我推荐读者打造自己的产品或者个人品牌虽然起点很低但是它能够持续积累最终达到不错的收益并且这个收益可以持续很久即使你半年不干活买单的人也不断这就是被动收入。\nSOHO 是比较自由的,没有人可以约束你,你可以十点起床,也可以三点休息,所以你需要有一些自控力,不能太放纵。\n一个人一旦选择 SOHO也就很难再去工作因为受不了工作带来的束缚觉得失去了选择权。有一些程序员 SOHO 收入其实不多,但是他一直坚挺着,其中一个重要的原因就是不愿意去工作。\n这一点是非常危险的如果你的项目迟迟不能发展那么五六年以后你将和工作着的程序员拉开差距。这个差距不仅仅是收入上的还有技术上的。很多 SOHO 的程序员技术不再进步,几年以后可能失去工作能力。\n3. 创业\n创业和 SOHO 不一样:\n\nSOHO 是过日子,一般规模不大,收入也不多,团队中往往只有创始人生活得比较潇洒,员工还在温饱线上挣扎。\n创业是干大事要追求规模不断拿投资直到上市或者被收购它的营收规模是 N 个亿,足够让团队中的很多人实现人生目标。\n\n如果你只是想多挣点钱改善生活水平那我劝你不要去创业SOHO 就挺好的,压力不大,精神舒适。\n创业是一个非常艰辛的过程你首要追求的不是利润而是规模所以你要快速地扩张一年翻 10 倍。从 0 到 1 是一座山,从 1 到 10再到 100、1000…… 也都是一座山,要想创业成功,你需要跨越很多障碍。\n创业的过程中你需要持续融资不断打动多个投资人融资能力是 CEO 必须具备的,这是一个至关重要,甚至决定生死的能力。\n那些只爱钻研技术不善于与各种角色打交道的程序员一般比较抵触融资过程不适合担任 CEO但是可以胜任 CTO做一个敲代码的美男子。\n如果你确认自己只适合当 CTO那么有一条比较稳妥的发展路径就是选择一家创业公司做 CTO\n\n如果创业公司能够快速成长起来那你就是人生赢家登上了人生顶峰\n如果创业公司经营不善而倒闭那也主要是 CEO 的责任,不是 CTO 的责任,你换一家创业公司继续做 CTO 就行。\n\n如果你有大厂工作经验而且能独当一面那么很容易进入初始创业公司担任 CTO。大厂工作经验是一生的光环它和学历一样熠熠发光。\n另外如果你 SOHO 做出的产品非常 NB被投资人看上那么也可以进入创业模式。\n4. 投资\n如果创业成功或者公司期权兑现你很有可能财务自由此时你需要考虑的一个重要问题是如何让自己的资产保值甚至增值。于是你开始研究一个新的课题就是投资。有人投资买房有人投资股市有人投资比特币也有人开始做天使投资人。\n天使投资人其实是一个风险很高的职业因为创业成功是小概率事件你的钱打水漂是大概率事件。但是一旦你投资的公司创业成功你将获得 10 倍、100 倍甚至 1000 倍的回报,这也是天使投资人愿意冒险的原因。\n你需要有足够的资金池投资多个项目用成功的项目填补亏损的项目以保证总体收入。作为技术出身的程序员投资时可以在一定程序上规避技术风险这也是程序员的一个优势。\n总结\n性格决定命运你是什么样的人就会选择去什么样的公司就会做什么样的事情就能获得多少回报。比如有些程序员就是耐不住寂寞就是想折腾就是想经历不同的过程谁也劝不住那么他大概率会 SOHO 或者创业。\n条条大路通罗马找准自己的定位选择适合自己的职业路线持续努力和积累人生终将绽放光芒。"},"Professional/Work/roadmap/职场心得/华为新员工的-8-个阶段":{"title":"华为新员工的 8 个阶段","links":[],"tags":["工作/经验"],"content":"新员工的前 6 个月的培养周期往往体现出企业对于人才培养的重视程度。然而,许多公司往往只关注前 15 天,导致年轻员工在入职第 6 个月至第 1 年之间的离职率较高。这对公司造成了重大成本损失。新员工能力的快速提升取决于管理者在前 180 天内所做的工作。\n第 1 阶段新员工入职让他们了解自己的角色3~7 天)\n为了确保员工在 7 天内迅速融入,管理者需要遵循以下七点:\n\n为新员工安排座位和办公桌让他们有自己的空间并介绍周围的同事每人介绍时间不少于 1 分钟);\n举行欢迎会或聚餐介绍部门的每个人促进相互了解\n与直接上司进行一对一沟通帮助新员工了解公司文化、发展战略了解员工的技能、背景、职业规划和兴趣\n人力资源主管向新员工解释工作职责以及他们自身的发展空间和价值\n直接上司明确安排第一周的工作任务包括每天做什么、如何做以及负责不相关任务的部门负责人\n及时发现和纠正日常工作中的问题不是批评及时肯定和表扬反馈原则评估每天的工作量和难点\n鼓励年长员工工作 1 年以上)与新员工多接触,消除新员工的陌生感,帮助他们尽快融入团队。关键是一起午餐、聊天,不要在第一周过多地讨论工作目标或施加工作压力。\n\n第 2 阶段新员工过渡帮助他们表现出色8~30 天)\n过渡可能是痛苦的但也是必要的。管理者需要帮助新员工快速完成角色过渡。以下是五个关键方法\n\n使新员工熟悉公司环境和各部门教他们如何写规范的公司邮件、发送传真遇到电脑问题找谁如何处理内部电话等\n最好将新员工安排在经验丰富的同事附近以便更好地观察和指导\n监测他们的情绪状态及时调整对下属的方方面面保持敏感。回答负面或幼稚的问题时从积极角度解答\n适时地分享个人经验让他们在实际操作中学习实践中学习学以致用因为新员工看重这种学习方式\n及时肯定和赞扬他们的成长和进步并提高期望。重点是四个方面4C和反馈技巧。\n\n第 3 阶段分配有挑战性的任务给新员工31~60 天)\n在适当的时候施加适当的压力往往能促进新员工的成长但大多数管理者选择了错误的方法。\n\n了解新员工的优势和技能明确工作要求和考核标准\n开展公司团队活动观察他们的优点和能力加强长处改进短处\n当出现错误时为他们提供改进的机会观察他们面对困境时的心态和行为评估他们的培养价值\n如果他们无法胜任当前岗位是否适合其他部门给予更多机会避免一刀切的错误。\n\n第 4 阶段表扬和建立信任61~90 天)\n有效表扬常常成为管理者的难题。表扬遵循三个原则及时性、多样性和开放性。\n\n当新员工完成有挑战性的任务或取得进步时及时表扬和奖励确保及时性\n多样化的表扬和奖励形式带来惊喜感创造不同的表扬方式\n向公司展示员工的成就分享成功经验。\n\n第 5 阶段融入团队合作完成工作91~120 天)\n年轻员工通常缺乏团队合作经验。管理者需要耐心地指导他们有效合作。\n\n鼓励员工积极参与团队会议鼓励他们发言在发言后表扬和奖励\n开展讨论关于激励机制、团队建设、工作流程、个人成长等的会议加强团队合作强调坦诚、赏识、情感、诚信\n鼓励员工探索解决问题的方法支持员工的创新思维。当员工提出好的建议时要及时肯定\n及时处理同事间的矛盾确保团队和谐。\n\n第 6 阶段赋予员工使命适度授权121~179 天)\n在前 3 个月过后,新员工通常会转正,带来新的挑战。管理者的重点需要转向以下方面:\n\n帮助员工重新认识工作的价值、意义、责任、使命和高度帮助员工重新定位自己\n持续关注员工及时调整情绪对员工的方方面面保持敏感。对员工的问题要积极转换方式从积极的角度解决问题\n强调公司的使命、愿景、文化价值聚焦团队凝聚力、方向明确和高效沟通促进绩效提升和职业素质\n在公司有重要事件或激励人心的消息时鼓励员工分享随时激励员工\n逐步授权让员工自主完成工作让他们体验工作价值的喜悦。授权需要逐步进行不要一步到位。\n\n第 7 阶段总结与制定发展计划180 天)\n在过去的 6 个月中,是时候进行正式评估并制定发展计划了。绩效面谈应包括以下六个步骤:\n\n每个季度至少进行 1-2 次 1 小时以上的正式绩效面谈,谈前进行充分调查,确保谈话有据可查;\n绩效面谈目的明确员工进行自我评价回顾完成的任务和取得的成绩指出不足和改进计划\n领导评价涵盖成果、能力和日常表现。先肯定成果再提出不足提供具体例子支持\n协助员工制定目标和措施鼓励员工承诺目标并监督目标的完成进度\n为员工争取发展机会每 3-6 个月评估一次员工;\n鼓励员工参加培训鼓励持续学习制定成长计划定期检查进度。\n\n第 8 阶段:全方位关注员工成长(每一天)\n在前 90 天过后,员工通常会正式转正,面临新的挑战。管理者需要持续关注员工的成长:\n\n关注员工的生活当员工遇到挫折、疾病、感情问题、生活变故等时提供支持、沟通、关心和帮助\n记住部门同事的生日以及部门的重要事件和突破表扬每一次进步\n每月组织多种形式的团队活动增强团队凝聚力强调坦诚、赏识、情感和诚信。\n"},"Professional/Work/roadmap/职场心得/如何平衡工作和生活":{"title":"如何平衡工作和生活","links":[],"tags":["工作/经验"],"content":"这个问题让我想起可口可乐曾经的首席执行官布莱恩·戴森 (Brian Dyson) 在 1996 年乔治亚理工学院的毕业致词:\n\n想像人生是一场在空中不停抛接五个球的游戏这五个球分别是工作、家庭、健康、朋友以及心灵而你不能让任何一个球落地。\n你很快会发现工作是一个橡皮球如果它掉下来会弹回去而其他四个球是玻璃做的如果失手它们有无法挽回的刻痕、损坏甚至破碎将不再和以前一样。\n\n想想自己如果要表演杂技抛接五个球还真是有一点难度。这不禁让人觉得平衡人生的这 5 件事情是一件多难的事情,但可恶的是,那些成功者往往做的都很好。\n就比如说扎克伯格作为 Facebook 的 CEO工作虽然忙碌但依然坚持跑步、旅行、陪伴家人一样也没有落下。又比如 Facebook 的 COO 雪柔‧桑德伯格Sheryl Sandberg在她的 《Lean In: Women, Work, and the Will to Lead》 这本书中,更是对工作和生活的平衡,分享了诸多理念和技巧。\n你说他们真的做到了吗具体我也不知道但就算抛掉工作上的成就而言各方面的表现也比我们强太多了。\n但成功人士终究是成功人士就比如很多问题都可以用钱来解决家务可以找保姆解决而我舍不得花钱只能自己收拾家三餐可以找专人做而我自己做费时间点外卖感觉又不健康出行有专车司机而我出行因为打不起专车只能挤地铁健身有顶级的教练指导而我还在犹豫办不办卡买不买私教课……\n这样一想虽然大家的时间是一样多但无论是能用在事情上的时间还是完成事情的效率其实都远不如他们。同样的事情对于他们来说是 normal 模式,对我可能就是 hard 模式,这多少会减弱一点参考性。\n而从我这样一个普通人的角度来看工作和生活平衡与其说是一种愿景不如说是一个谎言。\n首先绝大部分的人想象的“平衡”是将每天的事情完全掌控无论是工作中的任务还是生活中的事情全都能装下一个都不落下。但是人的时间呢就那么多每天 24 小时,这边增加了,那边必然减少,而如果某件事情完不成,就开始有负罪感,完美主义在心中作祟。\n这种想法的本质是期望用一套框架装下所有的事情这显然是对于人生难度的低估同时也是对自己的过分高估终究会被现实教育。\n为什么我们要追求平衡呢想一想我们之所以追求平衡是因为我们的当下并不平衡但其实从人生的维度来看我们的当下就不会是平衡的。\n在《你的幸福曲线》这本书中讲到了一个人生幸福曲线通过对收入、性别、教育、工作、婚姻、健康等进行调整后也就是过滤掉其他对生活满意度的影响因素年龄和生活满意度的关系看起来如图\n\n你可以发现人生的幸福度和年龄的关系遵循微笑曲线从年轻时的积极乐观到中年的长期低迷再到退休后幸福感逐渐回升我想说的是尽管个体的差异是有的但就对我们而言我们在这个年龄段就是会处在一个倾向于“失衡”的状态中。有太多的事情要做有太多的责任需要肩负事情汹涌而来而你的能力又有限痛苦是一种必然状态。\n但是引用这个调查不是让大家放弃抗争而是很多事情你只有在接受后才会有重新出发的勇气才会在面对失败的时候多一份淡然才会在认清生活真相的时候依然热爱生活。\n说回工作与生活我们很多时候会刻意的将工作和生活分开建立明确的界限之所以这样做很可能是因为在我们看来工作和生活就是对立的事情。有的人觉得工作是痛苦的只有放松享乐和陪伴家人是快乐的由此引申开来工作是一种必须要承受的痛苦就是说工作是一种累赘我只有尽快的完成它才能享受我的人生。\n这种说法是否对自己有益呢这其实要看很多情况。不过我想先聊聊工作这件事情什么是“工作”呢\n最一开始肯定没有工作这种东西更没有上班这种说法只是到了工业时代为了更高的生产效率为了方便管理才使拿工资的人必须每天去固定一个地点干活。\n那我们可以不工作吗这主要是因为我们生活在一个高度分工的社会我们需要工作付出劳动力和时间来换取我们生活所需的物质资料。所以你看“工作”并不是人类的天性它的本质是双向交换人类个体付出时间和劳动换取物质资料、精神愉悦比如各种享乐的活动。\n单从这个角度来思考的话那得出来的结论很可能就是我们工作就是为了享受工作换取的片刻欢愉。如果你能接受这样的现实倒也很好但这样的结论有一个让人难过的点就是它否认了我们工作的意义它认为工作是带来不了精神愉悦的这就很因人而异了。\n我们一天 24 小时,有至少 1/3 的时间都在工作,而我又把工作当成“累赘”,这无疑加速了自己的精神内耗。工作的时候,感觉很累很累,然后产生看似本能性的反感和排斥,生活开始变得煎熬起来。\n这就是为什么要强调工作一定要找到它有意义的地方这听起来有一种资本家的语气但这样做不是为了别人恰恰的是为了自己。每天三分之一的时间都在痛苦中度过亦或者是在无聊中煎熬谁又愿意过这样的生活呢所以我们能做的也就是从自己的工作中找到一点意义感了。\n然而大部分的人对此是绝望的因为很多人认为绝大多数的工作其实不是自我能力的提升而是剩余价值的压榨。这样的概述对于总体也许是成立的但对于个体来说却仿佛在说着改变不了自己的命运。\n所幸我的读者基本都是前端大部分在互联网公司工作哪有那么多的稳定性在各个城市漂泊的同时也多了一份选择的自由。只是希望大家能够找到自己喜欢的、有价值感的工作并能因此有所成长。你可以为了一时的成长忍耐暂时的薪水你可以为日后进大厂蛰伏在一家小公司这都没有什么关系尼采说人如果知道自己为什么而活什么样的生活都可以忍耐。\n我想说的是当你感觉这份工作带来的更多是精神的内耗时你应该勇敢的选择换一个环境了。很多人面对这种内耗依然蜷缩在自己的舒适区里一边为自己的不离开找借口一边叹息于自己的工作毫无意义。畏手畏脚在看似两难的选择中犹豫不前拖延决定备受煎熬。你的内心毫无疑问的知道正确的选择只是正确的路往往 too damn hard。\n考虑到我的读者各种年龄段都有这里多说一点那就是我会更建议刚毕业的同学不要去考虑什么平衡你就应该投入所有的精力在工作上做一个工作狂也比一个躺平咸鱼好。\n人生是不均衡的初中的你一天可以毫无顾忌的投入学习但成家后的你的一天都充满了生活琐事你以为这是可用的时间亦或者体力精力上的差距吗? 不止如此,我觉得最重要的就是,工作、成家后的精神内耗要远比上学时强烈的多,而且年轻的时候做错了就当试错,但成家后,你会发现时间就那么点,你就只能更谨慎的将时间花在刀刃上,这是一件好事情,但也会带来部分人的选择困难,反而浪费了更多的时间。\n再者我觉得刚毕业的时候是自由的上学的时候你所学习的内容很多是你被迫学习的内容但是毕业后你可以自由选择学习的内容没有比现在更有兴趣的时候了。\n还有就是二八定律人生的回报 80% 的回报来自于你 20% 的努力,你越早努力,在时间的加成下,你就会越多的享受到好处。想一想,很多人不就是因为高中的努力,一直吃到现在吗?高中努力了,上了个好大学,于是在面试的时候凭借学校刷掉了一大堆对手,因此去了好公司,又凭借着第一家好公司,跳槽到了第二家更好的公司吗。写博客也是这样,你越早写,你前期积攒的影响力会带来更多的影响力。所以没有什么比这更好的时间了,你就该投入其中,你只用拼那么一两年,其实你就可以吃很多年的老本了,你就已经赚了。\n你把时间花在哪里最后的收获就在哪里这种牺牲一种的做法也只有在特殊的时候才会起到很好的作用。这种选择虽然可以有效的降低心智成本不纠结但也不是维持之道。\n说完工作我们说说生活我觉得很多年轻人是没有“生活”这个概念的大部分人理解的生活是事务性的工作比如洗脸、刷牙、洗澡、做饭、洗碗、打扫卫生、上班、开车或者就是躺平活动比如刷动漫、看电视、打游戏、去网吧、短视频等等。\n个人选择是一部分社会压力也是一部分。对年轻时的我们而言就是能力低工资低。能力低导致加班工资低导致租房远交通成本高两边都在积压我们的时间工作的疲惫通勤的疲惫我们已然没有精力去享受所谓的下班后的生活到了家就变成了葛优躺我知道我要学习我知道我要奋斗但是有了空闲时间我就只想用在奶头乐上。\n这种问题是很多人的常态破解之道就是保持学习不早一点掌握工作上的专业技能平衡工作和生活说起来就是镜花水月。\n但是关于生活我倒不是想说这个事务性的内容很枯燥无聊只能说尽力减轻工作量躺平活动很有意思但引用《心流》的说法它只能帮助我们恢复我们的内在秩序却无助于创造新的秩序。就像饿了吃饭一样它帮助我们恢复了身体平衡但却不能帮助我们变得更好。我们如果要做到“生活”必不可少的就是爱好换句话说生活你要做些有意思的事情它才是生活。\n有一个休息法则就做莫法特休息法则它认为一个人如果长时间持续同一项工作内容就会感到疲惫效率降低所以我们可以适时切换为不同的工作类型。就比如我们每天工作写代码消耗了大量的脑力但是回到家你却还想着继续学习往往就因为过分的疲惫而坚持不下来。所以与其学习不如选择偏体力的活动比如打扫卫生、运动或者偏感性的活动如练琴、唱歌、绘画之类的。到了周末再进行学习。\n所有有的时候我们需要审视一下自己每天干的事情。列一个清单各自花费了多少时间浪费了多少时间有多少时间花在了自己感兴趣的事情上无论多忙多累都要抽点时间做点爱好而非享乐的事情。那种投入自己的注意力全身心的沉浸在一件事情中它带来的那种深沉的快乐能给你的生活带来很多的振奋。\n关于工作和生活讲了那么多在我看来我们追求工作与生活平衡的背后其实还是为了总体的幸福但幸福不来自于平衡本身而是来自于工作与生活中的幸福。所以如果你只是追求平衡却忽略了工作和生活的意义这就是一种舍本逐末。\n所以与其追求什么平衡我想说的是开心工作快乐生活。尽管这句话很阿里味但不得不承认这其实就是该有的状态。\n关于工作和生活再提供一些其他的小建议\n\n少喝咖啡\n\n很多人对咖啡上瘾据说开在阿里园区的第一家星巴克是全国营业额最高的星巴克店面足以看出阿里同学对咖啡的喜爱程度。咖啡确实很不错通过咖啡可以获得所谓的精神但结果往往是需要的量越来越大但能获得的精神却越来越少。\n在我看来咖啡是一种透支只是把你未来的精力短暂的放到现在而已但你的身体本身并没有得到休息要是真的想调整精力冥想和健身其实是更好的选择。\n\n提升专注力\n\n很多人解决事情的方式是堆时间所谓堆时间把其他事情的时间都尽力挤压掉留出大量的时间专门用于一件事情的完成颇有一种牺牲一切没必要的事情只为一件事情完成的魄力但真到具体做这件事情的时候则会各种分神找个借口休息一下查点相关的资料结果越查越远不自觉地拿起手机点开了微信消息事情还没干多少无论是内部打断还是外部打断都打断了几十回。这样的事情即便完成了享受过短暂的成就感之后心理上依然感到十分疲惫。\n所以对于这种较大时间块一定要明确的划分出做事和休息的时间否则就会自己主动陷入 996 的陷阱之中。\n而做具体的活动之时可以采用比如番茄工作法。\n关于番茄工作法也多说一句这个名字想必大家都听过很多遍本身并不复杂但是也没有大家了解的那么简单什么“每工作 25 分钟,然后休息 5 分钟,第 4 个休息的时候,休息 30 分钟”,那这其中,为什么番茄工作法很有效,背后的原理是什么?对于干扰的情况如何处理?每天结束时统计和处理哪些内容?对于这些问题,大家可能都没有了解过,更多的是看一两篇二手的文章大致的了解了下。\n关于番茄工作法具体包含哪些内容我在这里也不多说我只想说要学习这个番茄工作法不用去看什么二手的文章都是别人总结过的少了点意思直接看原书微信读书搜《番茄工作法》免费阅读这是番茄工作法的作者写的还有一本《番茄工作法图解》也很不错番茄工作法的作者作的序微信读书上也是免费阅读看完这两本书加起来都不超过 5 个小时,但是你却可以对番茄工作法,这个非常经典的方法有更加全面深刻的了解。\n作为一个备受很多人推崇的方法大家都是傻瓜的可能性是比较小的更大的可能性是自己傻瓜所以失败过的同学也要多看看最少坚持两周试一试。\n\n断舍离\n\n我认为“断舍离”这个概念涵盖的内容非常的多。我们生活充满了各种无用的物品这些物品的存在不能给我们带来幸福感只会让我们越发无力去收拾。\n我们的想法中充满了太多没用的情绪担心、多虑、徘徊、怀疑、恐惧、受伤挣扎、固守、困惑、焦虑、低落、愤愤不平、自卑自贱、牢骚、抱怨、呻吟、挑剔、吹毛求疵往往外界什么事情还没有发生我们的内心已经无数种情绪翻江倒海汹涌而来。\n我们日常要做的事情也是不断地趋向于更多即便今天看似完美的度过了明天后天也只会加入更多的事情不断地做加法但却不肯收手放自己一马最终让自己疲惫不堪。\n所以日常生活中在你察觉到负面情绪的时候及时的反思背后导致的原因当断不断反受其乱但也不用一直的断加加减减才是人生的常态。\n\n原作者冴羽答 - 读者问:怎么平衡工作与生活\n文章地址github.com/mqyqingfeng/Blog/issues/298\n文章采用 知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 进行许可。\n"},"Professional/Work/roadmap/职场心得/如何度过新手村":{"title":"如何度过新手村","links":[],"tags":["工作/经验"],"content":"最近在带新员工,也是在记录总结一下,我们应该如何度过新手村?想想去年这个时候俺也是小白,没想到今年就开始带新员工了。内容主要偏向于技术岗位,各抒己见欢迎来怼,不说废话,赶紧上车。😏\n公司\n从公司角度来说入职后第一件事情务必先熟悉公司组织架构最好可以记忆下来。其次了解公司的主营业务及战略方向知道火车往哪开不过一般不会往家里开。🤐 如果不是管理层的话,建议不要对公司的管理文化及战略方向指指点点,其他的也没啥需要过度了解的了。\n毕竟打工人打工魂带薪拉 💩 才是你的使命。\n部门\n部门方面的话肯定得摸好你老板的屁股不然谁给你发工资但也不要当二腿子他又不是你的皇阿玛。简单来说就是熟悉领导的办事风格保守派还是改革派这点很重要自行体会自行体会 ~\n同事的话刚入职还是建议全当成路人甲、路人乙。本质上来说同事其实和你坐公交遇见的路人一样所以请勿过多加戏。基本上维持良性的部门氛围当下人情留一线日后好相见就行。\n还有就是在你熟悉公司组织架构和主营业务的基础上可以再进一步熟悉部门所负责的业务模块因为这就是你工作内容的集合基本上你得工作范畴不会超出这个集合。\n初出象牙塔的学生一定要不卑不亢耕好自己的一分田护好自己的一亩地就可以啦。\n工作\n最最最核心的事情来了工作方面主要分为五个部分办公用品、协同办公、工作内容、工作手册、日常总结。\n办公用品\n一个耐用的笔记本和黑色签字笔一定会伴随你的工作生涯所以可以买好点的。还有就是常见的移动存储U 盘啊、移动硬盘啊都可以,如果有个人电脑也可以带着,这样会更方便。\n协同办公\n这方面能说的可大了去了不过最基础的就是通讯软件了。一般了解掌握常用的几款例如企业微信、钉钉一些公司也会拥有内部专用的通讯工具会用就行。不过一般在这上边找组织架构最方便了 ~\n还有就是现在大部分公司应该都集成了单点门户系统拿小本本记下来就好。再加上企业 OA 系统,走申请啊、预留会议室啊、报销费用啊,一般都在这上面搞定。如果是做开发,还会有 git 啊等等等等等。初期建议都记在小本本上,供你方便使用。\n就如开头所说这方面太多了所以请根据实际情况来。\n工作内容\n这个最简单了哈哈哈还记得小本本嘛刚入职初期一定要有一个 ToDoList这个一定能帮上你大忙。其他的嘛回答保安大爷的问题就行你是谁到哪去\n工作手册\n初期工作内容会巨零散更无从下手。尤其是在大量阅读公司内部文档后我极其建议用笔记本写写画画因为初期一定会遵循否定之否定规律的所以用笔记本写写画画后期整理起来会很方便。\n我们在熟悉工作内容后可以尝试搭建个人文档提升自己的摸鱼水平。🐟\n日常总结\n你写日记么正经人谁 TM 写日记。\n话虽这样说不过工作日志还是需要滴该配合领导的演出你不能视而不见啊。时间地点人物、起因经过结果哈哈哈不好意思走偏了。😛\n只要前面 ToDoList 履行好,简单记录一下当天工作历程就可以啦。然后每周总结一下,月度汇报一下,毕竟你骗骗我,我哄哄你,坚持一贯的友好往来 ~\n\n如果你的工作岗位没有对公司直接产出价值那么请不要觉得你的薪水是与你产出的价值成正比的。所以在完成自己的本质工作之外偶尔来个小亮点即可。毕竟工作是为了生活生活不是为了工作。\n杜绝内卷、杜绝自杀式奉献从你我做起全世界的无产阶级联合起来世界终将属于我们。"},"Professional/Work/roadmap/职场心得/如何有效应对职场政治":{"title":"如何有效应对职场政治","links":[],"tags":["工作/经验"],"content":"了解环境\nAlice 加入了一家知名的软件公司,初到职场的她很快就意识到公司内部有不少政治游戏。每个团队都有自己的利益和目标,而且有时会相互竞争。\n\n兵者诡道也。知彼知己百战不殆不知彼而知己一胜一负不知彼不知己每战必殆。\n\nAlice 没有立即参与任何一方,而是花了一段时间去观察和了解各个团队的风格、优势,以及公司的整体文化。她参与各种会议,悄悄观察人们的行为和沟通方式。这使她能更准确地判断哪些人是真正有影响力的,哪些是潜在的盟友或敌人。\n建立良好关系\nBob 在一个非常竞争激烈的销售环境中工作。他注意到,一名经验丰富的同事常常与公司高层共进午餐。\n\n故用兵之法无驱势之宾悬权而行之。\n\nBob 意识到这是一个建立关系的好机会。他不仅主动参加了这些午餐,还用心准备了一些与高层可能感兴趣的行业话题。他的努力得到了回报,不仅与高层建立了良好关系,还因此获得了一些关键项目的支持。\n保持专业态度\nCatherine 在一个大型媒体公司工作,在一个项目中与几个有「八卦」倾向的同事合作。\n\n故兵者一污二穴三趋四难。\n\n尽管很容易陷入这些八卦和不健康的竞争中Catherine 选择了避开这一切。她始终保持专业,对所有人都礼貌但保持距离。这使她在项目发生争议时能保持中立,赢得了更多同事的信任。\n透明但谨慎\nDaniel 在一家快速发展的科技公司工作。某一天,他听到关于即将有一轮大规模裁员的传闻。\n\n兵无常势水无常形\n\nDaniel 选择在这个敏感问题上保持谨慎。他没有参与传播这一消息,但与他信任的同事和上级进行了探讨。这种谨慎和负责任的态度得到了领导的认可。\n保护自己\nEmma 在一个大型金融机构工作,她发现一个同事试图通过散播关于她不负责任的谣言来抢她的项目。\n\n故其兵之虚实以化待之\n\nEmma 首先确保自己的工作质量,然后收集所有可能证明自己能力和责任心的证据。当她感到有必要解释时,她拿出这些证据与上司和人事部进行了坦率的沟通,最终成功地保护了自己的职位和声誉。\n通过这些具体的案例我们可以看到应对职场政治并非一蹴而就的事情而是需要综合运用多种策略和技巧。重要的是要有清晰的认识和目标同时也要根据情况的变化随时做出调整。这样你不仅可以更有效地应对职场政治还可以在其中找到发展和成功的机会。\n明智地挑选战场\nFrank 在一个内容丰富但资源有限的出版公司工作。公司有多个项目和团队,各自都在争夺有限的资金和人力。\n\n兵之情主速乘敌不及准备出其不意此兵之胜不可常也。\n\nFrank 意识到,如果他试图参与每一个可能的竞争和争论,他将很快耗尽自己的精力。于是他决定聚焦在几个最能体现他专业技能和兴趣的项目上。这样,他不仅提高了工作效率,也更容易获得资源和支持。\n倾听和观察\nGrace 在一个全球化的制造公司工作,这里有多种文化和工作风格。\n\n因其具来制胜故兵变化如水水因地制壁兵因敌制胜\n\nGrace 采用了一个观察者的角度,努力了解各个团队或地区办公室的政治和文化动态。她注意到,不同的文化和环境有着不同的权力结构和决策方式。通过倾听和观察,她能够更加灵活地适应不同的工作环境,从而更有效地推进她的项目和职业生涯。\n寻求外部指导\nHarry 觉得自己陷入了职场的政治漩涡,不知所措。于是,他开始寻找一个行业内有经验的导师。\n\n凡战者以地生死。故地或可走或不可走或可战或不可战或可居或不可居或可击或不可击或可取或不可取\n\n通过这种外部的视角和建议Harry 得以更全面地理解他所面临的挑战和机会。导师的经验教训也帮助他避开一些潜在的陷阱,为他提供了在复杂环境中取得成功的策略。\n维持真实性\nIrene 在一个创意产业工作,发现自己常常需要平衡自己的价值观和职场政治。\n\n故火攻有五一曰火人二曰火财三曰火粮四曰火仓五曰火队。\n\nIrene 决定,尽管职场政治是必不可少的,但她不会因此而妥协自己的核心价值观。她坚持真实自我,并在与人交往时保持一致性。长远看来,这种真诚和一致性让她赢得了同事和上司的尊重,也让她在公司中建立了积极和健康的影响力。\n总结而言成功地应对职场政治需要策略性思维、观察力、和人际交往能力。最重要的是你需要明确自己的目标和价值观并根据这些来制定和调整你的行动计划。这样不仅可以保护自己不受负面影响还可以在复杂的职场环境中找到成功和满足。"},"Professional/Work/roadmap/薪酬攻略/社会保障":{"title":"社会保障","links":[],"tags":["工作/面试"],"content":"五险一金\n五险一金是指中国大陆地区劳动者所享有的社会保险福利的一种通俗化称呼其中五险是指包括养老保险、医疗保险、工伤保险、失业保险、生育保险在内的五种社会保险一金是指住房公积金是中国政府为保障职工权利而采取的一项基本措施。五险一金中的工伤保险与生育保险全部由用人单位缴纳其他由用人单位与劳动者共同缴纳的四种也被称为四金。\n五险一金受中华人民共和国劳动法保护\n养老保险\n基本养老金也称退休金、退休费是一种最主要的养老保险待遇分社会统筹和个人缴纳两类由基础养老金、过渡性养老金、调节金和个人账户等部分组成。\n职工达到法定退休年龄男性 60 周岁,女性 55 周岁),个人累计社保缴费满 15 年,且工龄(包括缴费年限)满 10 年,可按月领取养老金;达到法定退休年龄时累计缴费不足十五年的,可以补缴费至满十五年。\n医疗保险\n医疗保险待遇是指用人单位和职工按照一定的费率和费基缴纳医疗保险费形成医疗保险基金由基金对参保职工因疾病支付医疗费用所造成的经济损失给予一定的补偿。职工一般可选择在与社会保险经办机构签订医疗保险合同的定点医院就医。\n其保险待遇项目主要有规定范围内的药品费用、规定的检查费用和治疗费用、规定标准的住院费用。其中医疗保险按统筹管理分成 2 个帐户,即统筹帐户和个人帐户,职工个人账户用于支付小额医疗费用,社会统筹基金用于支付大额医疗费用。\n工伤保险\n当月参保可选当月生效次月生效即次月 1 号生效。\n\n医疗康复待遇医疗康复待遇包括工伤治疗及相关补助待遇康复性治疗待遇人工器官、矫形器等辅助器具的安装、配置待遇等等。\n停工留薪期待遇在停工留薪内工伤职工原工资福利待遇不变由所在单位按月支付生活不能自理的工伤职工在停工留薪期需要护理的由所在单位负责。\n伤残待遇工伤职工根据不同的伤残等级享受一次性伤残补助金、伤残津贴、伤残就业补助金以及生活护理费等待遇。其中既有一次性待遇也有长期待遇。\n工亡待遇职工因工死亡其直系亲属可以领取丧葬补助金、供养亲属抚恤金和一次性工亡补助金。\n\n失业保险\n失业保险连续缴纳一年以上可以享受失业保险待遇。\n失业保险金是指失业保险经办机构按规定支付给符合条件的失业人员的基本生活费用它是最主要的失业保险待遇。\n生育保险\n生育保险连续缴纳一年以上可以享受失业保险待遇。\n可以报销与生育有关费用。报销范围包括生育津贴、生育医疗费用、计划生育手术医疗费用、国家和本市规定的其他与生育有关的费用。\n六险二金\n六险二金是指在五险一金的基础上增加了意外伤害保险或者大额补充医疗保险和企业年金。\n大额补充医疗保险\n大额补充医疗保险是指在居民医保统筹基金之外参保人按规定缴费由医保经办机构作为投保人集体向商业保险公司投保超过居民医保基金最高支付限额以上的费用由商业保险公司按规定赔付的医疗费用。\n企业年金\n企业年金是指企业及其职工在依法参加基本养老保险的基础上自愿建立的补充养老保险制度是多层次养老保险体系的组成部分由国家宏观指导、企业内部决策执行。"},"Professional/Work/roadmap/薪酬攻略/绩效考核":{"title":"绩效考核","links":[],"tags":["工作/面试"],"content":"对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度KPIOKR方向业务产品架构自上而下自下而上领导强弱员工弱强绩效强弱驱动力要我做什么我能做什么\nKPI\n关键绩效指标Key Performance IndicatorsKPI又称主要绩效指标、重要绩效指标、绩效评核指标等是指衡量一个管理工作成效最重要的指标是一项数据化管理的工具必须是客观、可衡量的绩效指标。\n设计方法\n常用的方法是鱼骨图分析法和九宫图分析法。\n依据公司级的 KPI 逐步分解到部门,再由部门分解到各个职位,依次采用层层分解,互为支持的方法,确定各部门、各职位的关键业绩指标,并用定量或定性的指标确定下来。\n提取原则\n确定关键绩效指标有一个重要的 SMART 原则。SMART 是 5 个英文单词首字母的缩写:\n\nS 代表具体Specific指绩效考核要切中特定的工作指标不能笼统\nM 代表可度量Measurable指绩效指标是数量化或者行为化的验证这些绩效指标的数据或者信息是可以获得的\nA 代表可实现Attainable指绩效指标在付出努力的情况下可以实现避免设立过高或过低的目标\nR 代表关联性Relevant指绩效指标是与上级目标具明确的关联性,最终与公司目标相结合;\nT 代表有时限Time bound注重完成绩效指标的特定期限。\n\n关键绩效指标的制定\n关键绩效指标的制定通常是基于组织的使命、价值观、关键结果领域、愿景、阶段性目标、工作规划、人员发展等方面来制定。\nOKR\n目标和关键成果Objectives and Key ResultsOKR是企业进行目标管理的一个简单有效的系统能够将目标管理自上而下贯穿到基层。这套系统由英特尔公司制定在谷歌成立不到一年的时间被投资者约翰 · 都尔引入谷歌,并一直沿用至今。\n基本方法\n制定 OKR 的基本方法是首先要设定一个目标Objective这个目标不必是确切的、可衡量的例如我想让我的网站更好然后设定若干可以量化的 3 至 5 个关键结果Key Results用来帮助自己实现目标例如让网站速度加快 30%;融入度提升 15% 之类的具体目标。\n原则\n\nOKRs 要是可量化的(时间&数量),比如不能说使 gmail 达到成功,而是在 9 月上线 gmail 并在 11 月有 100 万用户。\n目标要是有野心的有一些挑战的有些让你不舒服的。一般来说1 为总分的评分,达到 0.6-0.7 是较好的了,这样你才会不断为你的目标而奋斗,而不会出现期限不到就完成目标的情况。\n每个人的 OKRs 在全公司都是公开透明的。比如每个人的介绍页里面就放着他们的 OKRs 的记录,包括内容和评分。\n"},"Professional/Work/roadmap/薪酬攻略/薪酬制度":{"title":"薪酬制度","links":[],"tags":["工作/面试"],"content":"\n薪酬福利体系思维导图"},"Professional/Work/roadmap/面试法则/反向面试":{"title":"反向面试","links":[],"tags":["工作/面试"],"content":"\n大部分翻译自github.com/viraptor/reverse-interview ,亦有其他网友补充。\n译者总结的一份适合突击记忆的简洁版 LeetCode 题解和面试问题,也欢迎 Star。github.com/yifeikong/interview\n下面列表里的问题对于参加技术面试的人来说可能有些用。\n列表里的问题并不一定适用于某个特定的职位或者工作类型也没有排序\n最开始的时候这只是我自己的问题列表但是慢慢地添加了一些我觉得可能让我对这家公司亮红牌的问题。\n我也注意到被我面试的人提问我的问题太少了感觉他们挺浪费机会的。\n\n如果你问过的问题没有被列出来请提交一个 PR。\n翻译\nEnglish\nKorean\nPortuguese\n预期使用方式\n\n检查一下哪些问题你感兴趣\n检查一下哪些是你可以自己在网上找到答案的\n找不到的话就向面试官提问\n\n绝对不要想把这个列表里的每个问题都问一遍。尊重面试官的时间而且你可以通过查找已经发布的答案来显示\n你的主动性\n请记住事情总是灵活的组织的结构调整也会经常发生。拥有一个 bug 追踪系统并不会保证高效处理 bug。\nCI/CD (持续集成系统) 也不一定保证交付时间会很短。\n职责\n\nOn-call (电话值班)的计划或者规定是什么?值班或者遇到问题加班时候有加班费吗?\n我的日常工作是什么\n有给我设定的特定目标吗\n团队里面初级和高级工程师的比例是多少有计划改变吗\n入职培训 (onboarding) 会是什么样的?\n每个开发者有多大的自由来做出决定\n在你看来这个工作做到什么程度算成功\n你期望我在最初的一个月 / 三个月能够完成什么?\n试用期结束的时候你会怎么样衡量我的绩效\n自己单独的开发活动和按部就班工作的比例大概是怎样的\n一个典型的一天或者一周的工作是怎样安排的\n对我的申请你有什么疑虑么\n在这份工作上我将会和谁紧密合作\n我的直接上级他们的上级都是什么样的管理风格事无巨细还是着眼宏观\n我在这个岗位上应该如何发展会有哪些机会\n每天预期 / 核心工作时间是多少小时?\n我入职的岗位是新增还是接替之前离职的同事是否有技术债需要还(zh)\n入职之后在哪个项目组项目是新成立还是已有的(zh)\n\n技术\n\n公司常用的技术栈是什么\n你们怎么使用源码控制系统\n你们怎么测试代码\n你们怎么追踪 bug?\n你们怎样监控项目\n你们怎么集成和部署代码改动是使用持续集成和持续部署吗 (CI/CD)\n你们的基础设施搭建在版本管理系统里吗或者是代码化的吗\n从计划到完成一项任务的工作流是什么样的\n你们如何准备故障恢复\n有标准的开发环境吗是强制的吗\n你们需要花费多长时间来给产品搭建一个本地测试环境分钟 / 小时 / 天)\n你们需要花费多长时间来响应代码或者依赖中的安全问题\n所有的开发者都可以使用他们电脑的本地管理员权限吗\n介绍一下你们的技术原则或者展望。\n你们的代码有开发文档吗有没有单独的供消费者阅读的文档\n你们有更高层次的文档吗比如说 ER 图,数据库范式\n你们使用静态代码分析吗\n你们如何管理内部和外部的数字资产\n你们如何管理依赖\n公司是否有技术分享交流活动有的话多久一次呢(zh)\n你们的数据库是怎么进行版本控制的(zh)\n业务需求有没有文档记录是如何记录的(zh)\n\n团队\n\n工作是怎么组织的\n团队内 / 团队间的交流通常是怎样的?\n你们使用什么工具来做项目组织你的实际体会是什么\n如果遇到不同的意见怎样处理\n谁来设定优先级 / 计划?\n如果团队没能赶上预期发布日期怎么办\n每周都会开什么类型的会议\n会有定期的和上级的一对一谈话吗\n产品 / 服务的规划是什么样的n 周一发布 / 持续部署 / 多个发布流 / …)\n生产环境发生事故了怎么办是否有不批评人而分析问题的文化\n有没有一些团队正在经历还尚待解决的挑战\n你们如何跟踪进度\n预期和目标是如何设定的谁来设定\nCode Review 如何实施?\n给我介绍下团队里一个典型的 sprint\n你们如何平衡技术和商业目标\n你们如何共享知识\n团队有多大\n公司技术团队的架构和人员组成(zh)\n团队内开发、产品、运营哪一方是需求的主要提出方哪一方更强势(zh)\n\n问未来的同事\n\n开发者倾向于从哪里学习\n你对在这里工作最满意的地方是\n最不满意的呢\n如果可以的话你想改变哪里\n团队最老的成员在这里多久了\n在小团队中有没有出现成员性格互相冲突的情况最后是如何解决的\n\n公司\n\n公司为什么在招人产品发展 / 新产品 / 波动…)\n有没有会议 / 旅行预算?使用的规定是什么?\n晋升流程是怎样的要求 / 预期是怎样沟通的?\n绩效评估流程是怎样的\n技术和管理两条职业路径是分开的吗\n对于多元化招聘的现状或者观点是什么\n有公司级别的学习资源吗比如电子书订阅或者在线课程\n有获取证书的预算吗\n公司的成熟度如何早期寻找方向 / 有内容的工作 / 维护中 / …)\n我可以为开源项目做贡献吗是否需要审批\n你认为公司未来五年或者十年会发展成什么样子\n公司的大多数员工是如何看待整洁代码的\n你上次注意到有人成长是什么时候他们在哪方面成长了\n在这里成功的定义是什么如何衡量成功\n有体育活动或者团建么\n有内部的黑客马拉松活动吗\n公司支持开源项目吗\n有竞业限制或者保密协议需要签吗\n你们认为公司文化中的空白是什么\n能够跟我说一公司处于不良情况以及如何处理的故事吗\n您在这工作了多久了您觉得体验如何(zh)\n大家为什么会喜欢这里(zh)\n公司的调薪制度是如何的(zh)\n\n社会问题\n\n你们关于多元化招聘什么看法\n你们的公司文化如何你认为有什么空白么\n这里的工作生活平衡地怎么样\n公司对气候变化有什么态度吗\n\n冲突\n\n不同的意见如何处理\n如果被退回了会怎样“这个在预计的时间内做不完”\n当团队有压力并且在超负荷工作的时候怎么处理\n如果有人注意到了在流程或者技术等其他方面又改进的地方怎么办\n当管理层的预期和工程师的绩效之间有差距的时候如何处理\n能给我讲一个公司深处有毒环境以及如何处理的故事吗\n如果在公司内你的同事因涉嫌性侵犯他人而被调查请问你会如何处理\n假设我自己很不幸是在公司内被性侵的受害者在公司内部有没有争取合法权益的渠道\n\n商业\n\n你们现在盈利吗\n如果没有的话还需要多久\n公司的资金来源是什么谁影响或者制定高层计划或方向\n你们如何挣钱\n什么阻止了你们挣更多的钱\n公司未来一年的增长计划怎样五年呢\n你们认为什么是你们的竞争优势\n你们的竞争优势是什么\n公司未来的商业规划是怎样的有上市的计划吗(zh)\n\n远程工作\n\n远程工作和办公室工作的比例是多少\n公司提供硬件吗更新计划如何\n使用自己的硬件办公可以吗现在有政策吗\n额外的附件和家具可以通过公司购买吗这方面是否有预算\n有共享办公或者上网的预算吗\n多久需要去一次办公室\n公司的会议室是否一直是视频会议就绪的\n\n办公室布局\n\n办公室的布局如何开放的 / 小隔间 / 独立办公室)\n有没有支持 / 市场 / 或者其他需要大量打电话的团队在我的团队旁边办公?\n\n终极问题\n\n该职位为何会空缺\n公司如何保证人才不流失\n这份工作 / 团队 / 公司最好和最坏的方面是?\n你最开始为什么选择了这家公司\n你为什么留在这家公司\n\n待遇\n\n如果有奖金计划的话奖金如何分配\n如果有奖金计划的话过去的几年里通常会发百分之多少的奖金\n有五险一金 (zh)/401k(us) 或者其他退休养老金等福利吗?\n五险一金中补充公积金一般交多少比例/401k 一般交多少比例?我可以自己选择这一比例吗?\n有什么医疗保险吗如果有的话何时开始\n有额外商业保险吗例如人寿保险和额外的养老/医疗保险?\n更换工作地点公司付费吗\n\n休假\n\n带薪休假时间有多久\n病假和事假是分开的还是一起算\n我可以提前使用假期时间吗也就是说应休假期是负的\n假期的更新策略是什么样的也就是说未休的假期能否滚入下一周期\n照顾小孩的政策如何\n无薪休假政策是什么样的\n学术性休假政策是怎么样的\n\n其他资源\nFind more inspiration for questions in:\n\nThe Joel Test: 12 Steps to Better Code by Joel Spolsky\nQuestions Im asking in interviews by Julia Evans\n\nLicense\n\nThis work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License."},"Professional/Work/roadmap/面试法则/面试-10-大常见问题":{"title":"面试 10 大常见问题","links":[],"tags":["工作/面试"],"content":"前言\n这份文档是鹅姐结合了自己做为求职者 & 累计面试超过 1000 人的业务面试官的经验,总结出的《面试最常见 10 大问题》。每一个问题,都从面试官提问目的、同学们回答时容易踩的坑或要注意的事项、回答思路几个角度给出了分析建议。\n不同于市面上各种个人经验主义的面经鹅姐非常注重剖析问题和解答建议背后的逻辑而不会随意给到一个“回答 xx 面试问题,就用 xx 公式”这种不负责任的断言,却又不说清背后的原因和道理。也友情提醒大家:如果某个所谓的求职导师跟你说“ xx 问题,一定要 xxx 这样回答”,却又讲不出其所以然来,一定要警惕。因为面试没有“唯一正确的公式”或者“必过诀窍”。生搬硬套,容易把大家带到坑里去。\n如果非要要说面试有什么“诀窍”那就是请牢记**我们在面试中的核心目的,是说服面试官:“我和目标岗位很匹配”。这个匹配度,体现在能力、态度和价值观三个层面。**也请牢记:\n\n\n面试不是伪装成别人而是展示最好的自己。\n\n\n面试不是靠现场发挥而是呈现好过往成就。\n\n\n面试不是跪舔面试官而是平等的对话交流。\n\n\n本文档大家也不要只是“读一读”就完事儿。针对每个问题把自己的回答逐字稿写下来再比照建议的回答思路反复打磨。持续思考“哪里还可以优化反复问自己“我还可以怎样讲得更好” “我说清楚了事情的背景吗” “如果我是面试官,我听下来觉得这个人怎么样”。多次实践后,一方面自己回答的质量更高,另一方面对自己的经历也更加熟悉,在面试中的发挥也会更稳定。\n加油\n\n这份文档配合鹅姐 B 站“面试常见问题系列”讲解,使用效果更好(戳> > > 鹅姐职场@B站\n来源【鹅姐出品】10大面试常见问题解析&参考答案;仅学术引用,著作权归作者所有。\n\n面试 10 大常见问题\n1. 请你自我介绍一下\n提问目的\n\n面试官想给自己留点时间来快速扫描简历、了解应聘同学背景同时思考面试中问什么问题。\n了解求职者有无想重点沟通的经历、事项。\n初步判断应聘者的沟通能力。\n\n常见错误\n\n自我介绍过于简单时间太短 / 纯粹念简历,没有提供任何额外信息)\n自我介绍过于冗长导致面试官掉线 / 后续面试时间背压缩)\n没有重点过往经历每个都蜻蜓点水讲一遍没有突出与目标岗位相关性高的经历体验\n自我介绍全是笼统的自我表扬缺乏数据或事实作为支撑。\n过于自我贬低显得不自信 / 让面试官怀疑自己能力水平低。\n\n回答注意事项\n\n突出和目标岗位的匹配度主动讲出能佐证自己“具有岗位相关经验或技能”的信息。\n表达有结构有重点。结构建议学历信息 + 工作经历 + 求职原因。\n调动状态调整自己的身体语言和情绪让自己处在一种适度兴奋的积极状态中。\n\n回答示例\n背景某应届同学面试某 500 强企业销售的岗位。同学只有一段与销售不相关的客服实习经历和一段不算特别成功的校内创业经历\n面试官您好我叫xx。我毕业于xx大学xx专业GPAxx排名前20%。\n我对于销售工作非常有热情曾经在A公司担任过售后支持实习生期间通过电话沟通和实地拜访累计帮助了超过200名客户解决产品使用问题客户满意度95%以上,在同届实习生中排名靠前。\n我还有一段创业经历在团队里我负责的也是销售类的工作主要是拜访用户、为产品拉新。我通过优化拜访话术和引导用户注册的诱饵设计把拉新成功率从最早的不足3%提升到了13%。几段经历中,我锻炼了沟通表达能力和对用户需求的理解能力。\n未来我希望系统地学习和提升自己的销售能力也非常期望有机会加入xx公司做销售为公司贡献价值的同时也自己收获成长谢谢。\n2. 说说你的过往工作经历\n提问目的\n\n根据候选人过往经历中实际做的事情判断候选人经历与岗位的匹配度。\n通过挖掘候选人处理问题、冲突等的方式方法了解候选人的能力水平。\n\n常见问法\n\n请你介绍岗位职能相关的信息\n“你主要负责做什么”\n“你/你的这个岗位,为什么指标负责?”\n“你日常的工作分成哪几个板块”\n请你分享取得过的成绩\n“你的目标达成情况怎么样”\n“你取得过最骄傲的成就是什么”\n“你工作中遇到过什么困难挑战怎么解决的”\n请你描述某个项目的具体情况\n“给我举一个你上份工作做的项目的例子讲一个比较能体现你能力的”\n“你 xx 项目,具体是怎么做的?”\n\n回答注意事项\n\n讲和所应聘的岗位相关度高的经历。\n从听众的角度思考降低面试官的理解难度尤其是跨行业、跨岗位的面试要主动想到补充必要的背景信息让面试官更轻松地理解自己所做的事及其意义\n主动争取讲出能体现自己价值、能力的信息即使面试官没有直接问面试官问有没有 xx 经验技能,即使自己没有,最好也不要干巴巴地回复说“没做过”。想一想,自己有没有一些可迁移的经验拿来讲)\n用 STAR 法则回答问题situation背景情形 + task你的任务或者目标+ 具体描述 action你做了什么+ result取得的结果\n\n回答示例\n背景某应届同学面试市场营销岗位给面试官介绍自己过去在音乐 APP 做频道运营的经历\n错误示范\n我实习期间做过《xxxx》《abcabc》等歌曲的视频传播策划取得了xxx的站内播放量和xxx的站外播放量。”\n \n点评面试官听过这段话可能会有疑惑“为什么运营音乐APP频道要搞视频的传播策划两件事之间的逻辑关系是什么” “音乐频道运营,为什么要做站外传播?”\n建议回答思路\n我在xx音乐APP实习期间主要负责在像B站、小红书这样一些年轻人聚集的站外平台投放我负责的歌曲的视频类素材目的是提升它们的站外知名度同时为站内引流。\n我通过调研各平台热点设计过像对口型、手势舞等一系列爆款传播素材不仅素材本身播放量不错、属于团队里类似曲目中较高的还拉动了平台内这些歌曲的播放量播放量平均提升了30%以上。\n3. 说一个你过去做过、让你感到骄傲的事\n提问目的\n\n让应聘者分享自己“最拿得出手”的经历根据其所解决问题的复杂程度/取得成就的大小,判断应聘者能力水。\n基于具体事件深挖了解应聘者的专业技能、思维逻辑能力、认知水平、抗压能力等等同时排除候选人“在简历上对经历造假”的可能性。\n听取候选人对过往经历的反思总结判断候选人自我迭代成长的能力。\n\n常见错误\n\n把重心放在了对成就大小的描述渲染上却没有讲出为什么它让自己骄傲没有讲出“克服了多大的困难” “这个成就为什么来之不易”)\n讲出的案例离现在太远e.g. 工作 5 年了,分享的最大成就却是工作第 1 年的成就,会让面试官担心最近几年工作成绩都不好)\n个人相关度低如鹅姐视频中举的例子“产品经理分享了一个自己做秒杀功能的案例。那个秒杀活动确实很成功但活动实际是由运营团队策划的产品经理实现这个功能的难度并不大并不能体现产品经理在自身职能上的能力有多强。”\n\n回答注意事项\n\n提供必要的背景信息让面试官理解你所做的事情的重要度 / 难度 / 对业务的价值等等。\n用 STAR 法则回答问题situation背景情形 + task你的任务或者目标+ 具体描述 action你做了什么+ result取得的结果\n有余力时可以再增加一个自己的心得和收获说明这样的经历对于自己未来做 xxx 也有帮助,以及自己思考了可以怎么样做得更好。\n\n回答示例\n背景某应届同学面试管培分享自己大学参加比赛获奖的例子\n我在大学期间曾经在56支参赛队伍中获得过xx商业分析比赛第2名的成绩。这件事让我骄傲的原因倒不是最终取得的名次而是我在过程中应对挑战的方式和体现出的快速学习能力。\n \n具体来说当时这个比赛要求我们4人团队在3周内产出一份行业分析报告。所分析的行业是电子硬件这个我们之前完全不了解的行业。所以它对于我的时间管理和学习速度都是一个挑战。\n \n为了应对这些挑战我首先制定了一个三周作战时间表把娱乐时间等都拿掉。但光这样不够为了提高比赛筹备的效率我和团队一起去采访了往届参加比赛的学长学姐了解了他们主要在哪些板块花的时间比较多、有困难以及他们的建议。我们还去找到了电子相关专业的同学咨询他们如何快速入门电子硬件的行业甚至还请他们吃饭、请教他们行业相关的基础知识。\n \n这之后我们再结合团队4个同学各自的擅长点把任务做了拆分。我提出了“以两个人为1个行动小组来完成细分的工作”。一方面这样省时间另一方面每件事团队成员也还有个人商量。\n \n事实证明这样的做法非常有帮助。我们在保证学业的同时高质量地完成了比赛。我也从中提升了自己如何快速搭建学习框架、如何向他人有效获取帮助以及如何推进团队协作的能力。\n4. 说一下你对这个(应聘)岗位的理解\n提问目的\n\n了解你对行业、岗位、业务的理解度从而推测你能否胜任这个工作。\n判断你的求职诚意看看你有没有做功课。\n\n常见问法\n\n请你说出岗位要求的关键能力。\n新媒体岗位为例“你认为要写出爆款文章的要点是什么”\n销售岗位为例“你觉得提高成交率有哪些方法”\n请你提出对公司业务的具体改进意见。\n共享出行运营为例“如果我们想提高日订单量你觉得有哪些机会点”\nAPP 投放为例)“如果我们想维持 CAC 相对稳定、同时提升 20% 的日消耗金额,你觉得有什么办法?”\n\n常见错误\n\n回答时只能背诵或引用 JD职位描述中的用词没有反映出自己对行业的关注或理解。\n缺乏事先对行业、公司、岗位的调研导致说不出任何具体想法或建议。\n\n回答注意事项\n\n面试前完成对于所求职的岗位、公司、行业事先体验产品记录产品现有的设计、内容和运营方式等。尤其关注与所应聘岗位相关的信息思考相关机会点。\n尤其对社招有用有机会时引用自己之前工作中“证明了有效”的方法并指出其可迁移性让面试官知道自己在这方面是有一定经验可以贡献的。\n回答时尽量让自己的思路有结构、成体系。而不是东一榔头西一棒子地说很多散点。\n\n回答示例\n背景某社招同学面试某本地生活大厂的用户增长策略岗位。同学之前没有在本地生活行业做过有在线教育行业从业经验。面试官问“你觉得我们在提升日活上有些什么机会点”\n我理解要提升日活可以从两个大的角度切入。第一个是新用户的获取第二个是已有用户的留存、或者说使用频次。\n \n针对新用户我们可以从不同细分人群的渗透率上找机会点。比如基于我有限的了解和观察咱们产品的主要使用人群从年龄上可能是集中在20-40岁人群那是不是40岁以上的用户还有一些提升空间我们能否通过增加一些适用于他们的品类来拉升渗透比如xxx\n \n另外从城市梯度上我们的用户目前应该还是主要集中在一二线城市。三线及以下城市的用户是不是可以通过一些相对价格更低廉的入门款产品来激发这类用户下载和尝试我们\n \n从留存角度我看到咱们产品目前已经推出了会员和积分机制应该目的都是激励用户多次使用我们、提升留存。但可能有一个机会点是目前积分制度的规则看着还是比较复杂。我有尝试让身边朋友体验会员积分但他们都反应不太搞得懂自己具体有哪些权益。我们可以尝试把积分机制再简化一些让用户清晰知道我花了多少钱就可以返我多少钱之类的而不是我花了多少钱对应是多少的积分这些积分又可以抵销多少钱而且积分还有使用门槛这种比较难理解的机制。之前我在教育公司做过类似的尝试发现机制简化对于用户的体验会好很多也能激发他们更多消费我们的产品。\n \n所以总结一下我觉得提升日活在40岁以上、三线及以下城市的新用户获取上以及用户留存的机制上都可以尝试。\n5. 你的优点是什么\n提问目的\n\n了解候选人有无自我认知和反思的习惯。\n判断候选人的优势有多显著如果优势都没啥特色说明这个人没啥能力\n\n常见错误\n\n没有提前思考过自己的优势临时给出一个仓促的答案。\n缺乏佐证讲出的优势没有事实支撑。\n\n回答注意事项\n\n建议回答结构优点是什么 + 支撑自己优点的事实 + (加分项)该优势对应聘岗位的价值。\n可以讲的优势类型专业能力 或 自己的性格特质。但尽量选择“能给出比较有说服力的事实佐证”的项目,避免“空洞地声称自己有多好,却举不出多特别的例子来”。\n\n回答示例\n我的一个优势特质是沟通能力不错。\n \n体现在工作中是我能够比较快速准确地理解对方的意思和需求以及在有冲突时我能够很好地管理自己的情绪从双方的共同目标出发、高效找到解决冲突的办法。\n \n我之前在做茶叶销售的时候每天要面对不同类型、不同需求的用户。我通过总结客户类型和常见问题开发出了一套高转化的销售话术。比如来咨询的客户如果是女性我会更多从健康的角度推荐用户购买给自己和家人而如果咨询的客户是男性我则会从口味角度切入、推荐用户买给自己或者从送礼的角度切入、推荐用户购买给客户或者长辈。这样我所经手的客户平均转化率比其他同事稳定高出10%。\n \n而我之前在做客服的时候每天要处理超过200位用户的求助和投诉其实情绪上的压力是很大的。但我一直可以保持平静的工作状态并且在面对情绪激动的客户时我可以通过共情、倾听的方式从他们的情绪中梳理出他们的真实需求再通过引导和疏导让他们感受到我是来帮助解决问题的。这样我能够把客户的注意力从发泄转移到解决问题并帮他们找到对应的解决方案。所以我的客服好评率一直是团队里排名前三的。\n6. 你的缺点是什么\n提问目的\n\n了解候选人有无自我认知和反思的习惯。\n判断候选人和岗位的匹配度避免“缺点”成为“导致不能胜任岗位的重大坑点”。\n判断候选人的真诚度是不是愿意暴露自己真实不足的地方。\n了解优选人有无自我提升的意识和意愿。\n\n常见错误\n\n\n讲不出缺点或者说自己“没有缺点”。\n\n\n讲的缺点太假或者过于无关。\ne.g. “我的缺点是追求完美” “我的缺点是做饭不好吃”。\n\n\n讲的缺点对岗位胜任力构成了重大威胁。\n\n\n只说缺点在被追问“有没有尝试改进之后”说不出任何自己的改进和提升导致面试官认为候选人没有自我提升的动力和能力。\n\n\n回答注意事项\n\n建议回答结构缺点是什么 + 缺点具体的体现 + (加分项)现在采取了什么改善措施 + (加分项)改善措施目前产生的效果。\n选取真实、同时对于目标岗位不构成重大影响的点。\n缺点可以是 “个人特质型”(如:性格内向,沟通不太主动)或者 “客观经验型”(如:之前没有管理 5 人及以上团队的经验)\n\n回答示例\n背景一位程序员同学被面试官问“你觉得自己有什么缺点”。\n我的缺点是性格比较内向。体现在工作中是有时候我和产品经理、测试同事或者其他程序员同事沟通不够积极主动。我也不太爱表达自己的想法或者观点。\n \n这导致我在日常和大家对需求、讨论问题时因为没有充分理解对方的意思、解决问题的效率比较低。我也曾经出现过因为没有及时和团队同事沟通、导致两个人都重复干了同一个活儿的情况造成了团队劳动力的浪费。\n \n我在意识到这个问题之后有主动跟我的上级主管沟通、反思自己的问题之后也有刻意向身边善于沟通的程序员学习。现在我还会设置定期提醒逼我自己主动找相关同事沟通工作进步、确认最新的工作需求。虽然我个性上仍是内向的但现在我不会让它影响我和团队的工作效率。\n7. 为什么投递这份工作\n提问目的\n\n\n评估求职者的职业规划是否合理\n\n\n判断求职者对岗位的预期以及预期是否和实际情况匹配\n\n\n让求职者给自己提供“为什么要选择 ta”的理由\n\n\n常见错误\n\n\n回答时表现没有体现出自己对所投递岗位的兴趣或者流露出“没有想在此稳定工作”的想法\n\n\n回答随意没有展现出自己对职业发展的思考e.g. “我的灵活性很高,运营、产品、销售类的岗位都可以做”)\n\n\n表现出“什么火就往什么行业/岗位凑”的倾向,让人担心稳定度\n\n\n把重心全部放在了吹捧公司或者岗位上没有从“自己为什么适合这份工作”的角度作答。\n\n\n回答注意事项\n\n\n建议回答结构自己看重行业/公司/岗位的点 + 岗位所要求的关键能力 + 自己具备哪些能力、使得适合这个岗位。\n\n\n从“个人兴趣”、“能力”和“岗位价值”几个维度综合论证为什么自己应聘这个机会。\n\n\n虽然这个问题看上去是面试官在问求职者“为什么选择该行业/公司/岗位”,但事实上面试官希望听到的是求职者告诉自己“为什么我适合这个岗位”。\n\n\n回答示例\n背景某运营同学转行面试产品经理岗位被面试官问“为什么应聘这个岗位”。\n我想从两个角度来回答这个问题。\n \n首先是为什么产品经理这个岗位吸引我。原因是我很享受发现需求、并且通过设计产品来解决和满足用户需要的过程。之前我从事在线教育行业运营工作的时候一定程度上也涉及过相关的工作比如我曾经发现用户在学习的过程中需要各种激励方式来帮助他们坚持学习。我当时通过运营的方式设计出了一个组团PK学习打卡的玩法有效提升了用户的学习率。但是通过运营的方式能影响的人是有限的所以我希望自己可以用产品的方式影响更多人。\n \n从能力的匹配的角度我理解画原型图、和研发沟通需求这些技能是基础技能我也自学了使用Axure、Sketch等工具的技能。但我认为产品经理最内核的能力其实是需要有较强的用户洞察、商业分析和逻辑能力。我自己过去做运营的经验里在用户的定量、定性调研上都有比较丰富的经验能够洞察用户真实需求而不是自己臆想。同时我的逻辑分析能力不错过去在解决业务运营上的不同问题时都能用合理的框架拆解和定位问题、找到机会点。\n \n第二个角度是为什么选择咱们公司。其实最重要的原因是我很认同咱们公司的产品我认为它给用户创造了xxx价值我自己也是它的典型受众和忠实用户。我很期待能在公司贡献自己的业务价值和咱们的产品一起成长。\n8. 为什么从上一份工作离职\n提问目的\n\n\n了解候选人是否因异常原因离职e.g. 被辞退)\n\n\n了解候选人想要什么看自己能否给到\n\n\n了解候选人对什么不满意看是否在新公司也可能遇到类似问题\n\n\n通过候选人的归因方式侧面了解候选人的价值观/人品/个人稳定性/自我认知等;\n\n\n常见错误\n\n\n吐槽前司/前老板/前团队,让面试官担心求职者人品不佳/沟通能力差/稳定性低/自我认知有问题。\n\n\n说薪资低让面试官担心求职者过于看重利益 且 能力不足(所以未争取到想要的利益);\n\n\n自曝其短表现出自己能力不足/工作质量差等问题。\n\n\n回答注意事项\n\n建议回答结构\n\n\n\n表明对上一份工作的感激和认可 + 强调个人职业发展,在意 xxx 方面 + 说明前司在 xxx 方面无法满足自己\n\n\n肯定自己在上一份工作中自己的收获 + xxx 客观因素对自己很重要(客观因素如工作地点等) + 前司无法在 xxx 上满足自己的需求\n\n\n\n不要让面试官觉得是自己的问题而是客观匹配度的问题\n从正面的视角解读这个问题更多展现自己对更好机会和更多成长的期待而非对过去种种问题的不爽\n\n回答示例\n背景某教育平台公司运营同学面试某教育公司运营岗位。\n我在上一家公司做了2年多的时间还是收获了很多成长也对公司充满感激。选择离职的原因主要是它的业务出现了较大的转型和我长期职业发展的规划不再匹配了。\n \n具体来说我加入公司的时候是明确想要做to C的用户运营的。但公司今年初调整了业务发展方向未来打算更多做to B或者to School的业务而会降低对to C业务的关注度。而我自己仍然是希望更多服务于C端用户的所以选择离开。\n9. 你的职业规划是什么\n提问目的\n\n\n判断求职者的自我认知\n\n\n了解求职者的岗位了解程度、职业理解度\n\n\n了解个人发展追求和公司规划的匹配度\n\n\n判断候选人稳定性、上进心和对潜在对工作的投入程度\n\n\n常见错误\n\n\n没有思考过这个问题回答不上来自己的长期规划\n\n\n说自己很灵活、考虑多个相关性并不大的职业方向导致面试官担心同学没有规划、对自己的职业发展不上心\n\n\n只谈自己对职级的野心想做到 xx 岗位,想承担 xx 角色),没有体现对专业度的追求\n\n\n回答注意事项\n\n\n想发展的岗位方向 + 原因 + 3 年后预期自己具备的职业能力\n\n\n虽然客观上一个人的职业路径很可能会变尤其对于刚毕业不久的同学但这也不能成为我们不去思考“职业规划”的理由。一定要思考职业规划哪怕只是未来 3 年、不是长期的\n\n\n结合自己的兴趣、能力、特长等说明自己对什么行业、岗位感兴趣\n\n\n对未来的展望侧重在专业技能上而非职级的提升\n\n\n回答示例\n背景某应届生面试快消市场岗位被问“长期职业规划是什么预期自己 3 年后是什么样的状态”。\n我长期希望从事消费品市场岗位的工作因为我非常喜欢快消行业喜欢生产和营销这种看得见、摸得着的商品的感觉。\n \n我对于市场岗位很感兴趣之前的实习也是围绕这个职能有一些初步的探索。我理解市场经理其实是操盘生意的重要大脑要关注品牌的生意表现、管理品牌产品线、制定品牌发展策略而并不是仅仅做营销类的工作。我非常希望学习这些技能并且最终成长为一个能够独立操盘一个品牌的业务人才。\n \n对自己3年后状态的设想我希望自己能在这些市场核心技能上横向对各个主要模块均有所涉猎同时纵向能有一技之长比如能独立负责品牌的某个年度营销推广项目并且产出对生意有显著帮助的成果。\n10. 你的薪资预期是什么\n提问目的\n\n\n了解候选人薪资预期判断双方预期差异大小&能否谈拢的可能性\n\n\n试探候选人对薪资预期的底线\n\n\n管理薪资预期为公司争取更低的人才成本\n\n\n常见错误\n\n\n过早开启对薪资的讨论模糊了“面试中双方对彼此了解”这个重点\n\n\n过早亮底牌e.g. “我最低要求是 xxx”导致招聘方比着底线给 offer\n\n\n给出一个薪资预期期间e.g. “我希望自己的薪资在 15k-20k 之间”然后希望对方取个【中间值】。但事实上招聘方只会关注【最低值】e.g. 会比着 15k 谈)。\n\n\n预期过于不切实际、缺乏支撑e.g. 预期相较于上一份工作涨幅 100%),导致招聘方认为自己没诚意\n\n\n回答注意事项\n\n\n如果还在面试过程中、对方尚未明确表示会给自己发 offer可以直接用委婉的话术拒绝现在谈薪资。e.g. “我理解目前咱们双方还在彼此了解的过程中,公司对我的价值判断,可以在走完面试流程之后,再综合我的能力情况来给到;我也可以在那个时候根据自己对公司各方面的了解,具体沟通我的薪资预期,您看可以吗?”\n\n\n尽量避免自己先量底牌把问题抛给对方。\n\n\n\n\ne.g. “我可以先了解下这个岗位的薪酬区间吗?”\n\n\ne.g. “我可以先听下您这边的想法吗?”\n\n\ne.g. “我可以先了解下咱们薪酬的构成吗,比如基础薪资是多少、有无绩效奖金、年终奖构成、五险一金如何缴纳等等?”\n\n\n\n可以适当利用“其他家的 offer 更高” “其他家五险一金缴纳比例更高” “(若未离职)目前公司有计划给自己涨薪” 等事实,给自己争取更高薪资。\n\n谈薪示范\n背景HR 已经向候选人确认面试通过,进入薪资沟通阶段。\nHR你的薪资预期是怎样的\n候选人能先了解一下咱们公司的薪资构成具体情况以及您这边的提议吗\n \nHR介绍公司薪酬结构但没有给出工资提议关于薪资也是想先了解下你上一份工作的工资情况。\n候选人(介绍上一份工作的薪酬情况。补充沟通对自己有利的信息,如:期权 / 不定期的项目奖金 / 较高的五险一金缴纳比例等的)\n \nHR那你对这一份工作的薪酬预期是怎样的\n候选人我期望有符合市场情况的合理涨幅。\n \nHR具体预期是怎样的呢\n候选人这个其实我也想听一下公司的想法。包括基于面试下来对我的价值判断等。\n \nHR给到一个低于自己预期的薪酬报价\n候选人这个坦率讲是有点低于我的预期的。因为其实我目前也拿到了xxx的offer而他们给到的package是xxx是比咱们家高的。但因为我确实也是很喜欢咱们公司整个面试过程中对同事也好、上级经理也好、整个公司也好感受都是很正向的也是期待有机会共事。所以还是想问问看薪资能否上调到xxx呢这个可能是属于我比较底线的一个预期了。\n \nHR这个会超出我们对岗位的预算我需要内部了解一下看看有没有给你争取的机会。\n候选人感谢我也是很有诚意地和公司聊确实还是很希望有机会共事。"},"Professional/Work/sre-engineer/home":{"title":"SRE (站点可靠性工程师)","links":[],"tags":[],"content":"SRE (站点可靠性工程师)\n站点可靠性工程师 SRE、Site Reliability Engineering是现代互联网企业中的核心角色他们致力于确保在线服务的稳定性和可用性。SRE 的存在,是为了将软件工程与系统运维的最佳实践结合,从而构建和维护高效、可靠的分布式系统。\n职责与工作内容\n\n监控与故障排除SRE 工程师持续对系统进行实时监控,确保其性能和可用性。一旦出现故障,他们会迅速定位并解决问题。\n自动化与工具开发通过编程和自动化技术SRE 工程师简化和优化系统管理,提高效率并增强系统的可靠性。\n容量规划他们评估系统资源的需求确保系统能够应对预期的负载和流量。\n故障分析与预防对系统故障进行深入分析识别并解决潜在问题从而提高系统的稳定性。\n紧急响应在系统出现紧急故障时SRE 工程师会迅速采取行动,最大程度地减少停机时间和业务影响。\n跨团队协作与软件开发、产品团队等进行合作共同解决系统和运维问题。\n\n必备技能与知识\n\n系统与网络基础这是 SRE 的基础,包括算法、数据结构、网络编程等。\n编程与脚本如 Python、Go 等,用于自动化和工具开发。\n容器化与云计算如 Docker、Kubernetes这些技术在现代互联网企业中被广泛采用。\n运维工具与技术如监控系统、配置管理和自动化部署帮助 SRE 更高效地管理系统。\n故障排除与分析能够迅速定位问题并找出解决方案。\n沟通与团队合作与各团队沟通协作共同解决问题。\n\n综上所述SRE 工程师是一个综合性极强的角色,他们既需要软件工程技能,又要具备系统运维知识。他们的存在,确保了在线服务的高可靠性,为用户提供了卓越的服务体验。"},"SocialSciences/English/字母音标":{"title":"字母音标","links":[],"tags":["英语/口语"],"content":"字母\n\n\n在线网址en-letter.xiao84.com/\n\n音标\n\n\n在线网址en-yinbiao.xiao84.com/\n"},"SocialSciences/English/语法基础":{"title":"语法基础","links":[],"tags":["英语/语法"],"content":"词性Parts Of Speech\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n词性 (Parts of Speech)简拼 (Abbreviation)定义 (Definition)功能 (Function)例子 (Example)名词 (Nouns)n.表示人、地点、事物或概念。作为主语或宾语。book, China, happiness动词 (Verbs)v.描述动作、状态或发生的事件。构成句子的谓语表示行为或状态。run, think, is, have形容词 (Adjectives)adj.用来描述或修饰名词。位于名词前提供额外信息如大小、颜色、形状等。beautiful, tall, red副词 (Adverbs)adv.用来修饰动词、形容词或其他副词。提供如何、何时、何地、何种程度等信息。quickly, very, well代词 (Pronouns)pron.用来替代名词避免重复。替代具体的名词。she, they, it, ours介词 (Prepositions)prep.表示事物之间的关系常与名词或代词组合。形成介词短语表示时间、地点、方向、原因等。in, on, at, from连词 (Conjunctions)conj.用来连接单词、短语或句子。连接句子成分表示逻辑关系。and, but, because, if感叹词 (Interjections)int.用来表达强烈的情感或反应。独立于句子结构表达情感。wow, ouch, hey\n名词Nouns, n.\n\n定义表示人、地点、事物或概念。\n例子在句子“Tom loves coffee.”汤姆喜欢咖啡。“Tom”和“coffee”都是名词分别指一个人和一种饮料。\n\n动词Verbs, v.\n\n定义描述动作、状态或发生的事件。\n例子“She runs every morning.”她每天早上都去跑步。这里“runs”是动词描述了她的动作。\n\n形容词Adjectives, adj.\n\n定义用来描述或修饰名词。\n例子“The beautiful scenery.”美丽的风景。“beautiful”是形容词修饰名词“scenery”。\n\n副词Adverbs, adv.\n\n定义用来修饰动词、形容词或其他副词。\n例子“He speaks very clearly.”他说话非常清楚。这里“very”是副词用来加强“clearly”这个副词。\n\n代词Pronouns, pron.\n\n定义用来替代名词避免重复。\n例子“She is a writer.”她是一名作家。“She”代替了某个具体的女性名词。\n\n介词Prepositions, prep.\n\n定义表示事物之间的关系常与名词或代词组合。\n例子“The book on the table.”桌子上的书。“on”是介词表示书和桌子之间的空间关系。\n\n连词Conjunctions, conj.\n\n定义用来连接单词、短语或句子。\n例子“I like tea and coffee.”我喜欢茶和咖啡。“and”是连词用来连接“tea”和“coffee”这两个词。\n\n感叹词Interjections, int.\n\n定义用来表达强烈的情感或反应。\n例子“Wow! This is amazing!”这太神奇了“Wow”是感叹词表达了惊讶的情感。\n\n句子成分Elements Of a Sentence\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n成分 (Element)定义 (Definition)功能 (Function)例子 (Example)主语 (Subject)句子谈论的主体通常是名词或代词。表明句子是关于谁或什么的。“The cat sleeps.”(猫在睡觉。)谓语 (Predicate)描述主语的动作或状态通常包含动词。说明主语做了什么或如何。“The cat sleeps.”(猫在睡觉。)宾语 (Object)动作的接受者通常跟在动词后面。接受动作或与动作有关。“She likes music.”(她喜欢音乐。)定语 (Attribute)修饰或描述名词的词或短语。描述或限定名词。“The red apple.”(红色的苹果。)状语 (Adverbial)提供关于动作发生的时间、地点、方式或原因的信息。修饰动词、形容词或整个句子。“He sings loudly.”(他大声地唱歌。)补语 (Complement)提供关于主语或宾语的额外信息。完成、解释或补充主语或宾语。“He is a teacher.”(他是一名教师。)同位语 (Appositive)通常紧跟在名词后面对名词进行解释或补充。详细说明或强调前面的名词。“My brother Tom is a teacher.”(我的兄弟汤姆是一名教师。)表语 (Predicative)位于系动词(如 be, become, seem 等之后用于对主语进行说明或补充。对主语进行补充说明说明主语的性质或状态。“The sky becomes dark.”(天空变得暗淡。)\n句子结构Sentence Structure\ngraph TD\n A[句子 Sentence] --> B[主语 Subject]\n A --> C[谓语 Predicate]\n C --> D[动词 Verb]\n C --> E[宾语 Object]\n C --> F[补语 Complement]\n B --> G[定语 Attribute]\n C --> H[状语 Adverbial]\n\n B --- I((名词或代词 Noun or Pronoun))\n E --- J((名词或代词 Noun or Pronoun))\n G --- K((形容词或短语 Adjective or Phrase))\n H --- L((副词或短语 Adverb or Phrase))\n\n基本句型Basic Sentence Structures\n简单句Simple Sentences\n简单句包含一个主语和一个谓语表达一个完整的思想。\n\n"The dog barks."(狗在叫。)\n\ngraph TD\n A[简单句 Simple Sentence] --> B[主语 Subject]\n A --> C[谓语 Predicate]\n B --> D[名词 Noun]\n C --> E[动词 Verb]\n D --> F["The dog"(狗)]\n E --> G["barks"(叫)]\n\n并列句Compound Sentences\n并列句由两个或更多的简单句通过并列连词如 and, but连接。\n\n"The dog barks, and the cat meows."(狗在叫,而猫在喵喵叫。)\n\ngraph TD\n A[并列句 Compound Sentence] --> B[简单句 Simple Sentence 1]\n A -->|并列连词 Conjunction| C[简单句 Simple Sentence 2]\n B --> D["The dog barks"(狗在叫)]\n C --> E["The cat meows"(猫在喵喵叫)]\n\n复合句Complex Sentences\n复合句包含一个主句和至少一个从句。\n\n"When the dog barks, the cat hides."(当狗叫时,猫就躲起来。)\n\ngraph TD\n A[复合句 Complex Sentence] --> B[主句 Main Clause]\n A --> C[从句 Subordinate Clause]\n B --> D["The cat hides"(猫躲起来)]\n C --> E["When the dog barks"(当狗叫时)]\n\n复合并列句Compound-Complex Sentences\n复合并列句包含至少两个主句和至少一个从句。\n\n"The dog barks, the cat hides, and the mouse runs away."(狗在叫,猫躲起来,老鼠逃跑了。)\n\ngraph TD\n A[复合并列句 Compound-Complex Sentence] --> B[主句 Main Clause 1]\n A --> C[主句 Main Clause 2]\n A --> D[从句 Subordinate Clause]\n B --> E["The dog barks"(狗在叫)]\n C --> F["the cat hides"(猫躲起来)]\n D --> G["the mouse runs away"(老鼠逃跑了)]\n\n从句类型Types Of Clauses\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n句型类型定义能否独立存在类型主句Main Clause能够独立存在表达完整的意思。是-从句Subordinate Clause不能独立存在依赖主句来表达完整的意思。否名词性从句、形容词性从句、副词性从句\n名词性从句Noun Clauses\n名词性从句Noun Clauses在句子中充当名词的角色。\n\n"What you said is interesting."(你所说的很有趣。)\n\ngraph TD\n A[名词性从句 Noun Clause] --> B[主句 Main Clause]\n B --> C["is interesting"(很有趣)]\n A --> D["What you said"(你所说的)]\n\n形容词性从句Adjective Clauses\n形容词性从句Adjective Clauses在句子中充当形容词的角色通常跟随并修饰名词。\n\n"The book that I read was fascinating."(我读的那本书很吸引人。)\n\ngraph TD\n A[形容词性从句 Adjective Clause] --> B[被修饰的名词 Modified Noun]\n B --> C["The book"(那本书)]\n A --> D["that I read"(我读的)]\n\n副词性从句Adverbial Clauses\n副词性从句Adverbial Clauses在句子中充当副词的角色说明时间、地点、原因等。\n\n"I will call you when I arrive."(我到达时会给你打电话。)\n\ngraph TD\n A[副词性从句 Adverbial Clause] --> B[主句 Main Clause]\n B --> C["I will call you"(我会给你打电话)]\n A --> D["when I arrive"(当我到达时)]\n\n特殊语句\n感叹句Exclamatory Sentences\n感叹句用来表达强烈的感情或情绪如惊讶、兴奋、快乐等。\n\n"What a beautiful day!"(多么美丽的一天啊!)\n\n祈使句Imperative Sentences\n祈使句用来发出命令、请求或建议。\n\n"Please close the door."(请关门。)\n\n疑问句Interrogative Sentences\n疑问句用来提问或询问信息。\n\n"Are you coming to the party?"(你会来参加派对吗?)\n\n倒装句Inverted Sentences\n倒装句中主语和谓语的正常顺序被颠倒或改变。\n\n"Rarely have I seen such bravery."(我很少见到这样的勇敢。)\n\n省略句Elliptical Sentences\n省略句中省略了某些成分但意思仍然清晰。\n\n"I can play piano, and she can too."(我会弹钢琴,她也会。)\n\n条件句Conditional Sentences\n条件句表达假设的情况及其可能的结果。\n\n"If it rains, we will stay home."(如果下雨,我们就待在家里。)\n\n语序Word Order\n\n定义标准的英语语序是主语 - 谓语 - 宾语SVO。\n例子"She (S) loves (V) music (O)."(她喜欢音乐。)\n\n时态和语态Tenses And Voice\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n时态结构用途例子现在简单时do/does + 基本形式表达习惯性动作、普遍真理She writes every day.现在进行时am/is/are + 现在分词表达正在进行的动作She is writing a letter now.现在完成时have/has + 过去分词表达过去发生的动作对现在的影响She has written a letter.现在完成进行时have/has + been + 现在分词表达从过去开始持续到现在的动作She has been writing a letter.过去简单时did + 基本形式表达过去某一具体时间的动作或状态She wrote a letter yesterday.过去进行时was/were + 现在分词表达过去某一时刻正在进行的动作She was writing a letter when I called.过去完成时had + 过去分词表达在过去某一动作之前已经完成的动作She had written the letter by then.过去完成进行时had + been + 现在分词表达在过去某一时间点之前开始并持续的动作She had been writing a letter for an hour.将来简单时will + 基本形式表达将来的动作或状态She will write a letter tomorrow.将来进行时will be + 现在分词表达将来某一时刻正在进行的动作She will be writing a letter at 8 PM.将来完成时will have + 过去分词表达在将来某一时间点之前已经完成的动作She will have written the letter by noon.将来完成进行时will have been + 现在分词表达在将来某一时间点之前开始并持续的动作She will have been writing a letter for two hours.\n语态\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n语态结构用途例子主动语态主语 + 动词 + 宾语表达主语执行动作She writes a letter.被动语态主语 + be动词 + 过去分词 + 由…进行表达主语接受动作A letter is written by her.\n直接与间接引语Direct And Indirect Speech\n直接引语和间接引语是英语中报告他人话语的两种方式它们在使用时有明显的区别和转换规则。\n直接引语Direct Speech\n\n定义原样引用说话人的原话通常放在引号内。\n用法用于报告说话人的具体言辞保留原话的时态、人称和地点时间指示词。\n**例子:**She said, “I am writing a letter.”\n\n间接引语Indirect Speech\n\n定义转述说话人的话不使用引号并根据上下文调整时态、人称和指示词。\n用法用于报告说话内容的概述需要根据主句的时态对从句的时态进行相应调整。\n转换规则\n\n时态后移直接引语的现在时变为间接引语的过去时过去时变为过去完成时等。\n人称调整根据上下文将第一人称转换为第三人称第二人称根据情况转换。\n指示词调整如“today”变为“that day”“now”变为“then”等。\n\n\n例子\n\nDirect: He said, “I will visit Paris tomorrow.”\nIndirect: He said that he would visit Paris the next day.\n\n\n\n条件句Conditional Sentences\n条件句用于表达一个条件以及该条件的结果。它们主要分为四种类型每种类型用于表达不同程度的可能性。\n零条件句Zero Conditional\n\n用途表达普遍真理或自然规律。\n结构if + 现在简单时, 现在简单时。\n例子If water reaches 100 degrees Celsius, it boils.\n\n第一条件句First Conditional\n\n用途表达将来可能发生的情况及其结果。\n结构if + 现在简单时, 将来简单时will + 动词原形)。\n例子If it rains tomorrow, we will cancel the trip.\n\n第二条件句Second Conditional\n\n用途表达不太可能发生的假设情况及其假设结果。\n结构if + 过去简单时, would + 动词原形。\n例子If I were a millionaire, I would buy a mansion.\n\n第三条件句Third Conditional\n\n用途表达过去未发生的假设情况及其假设结果。\n结构if + 过去完成时, would have + 过去分词。\n例子If I had studied harder, I would have passed the exam.\n"},"SocialSciences/Government/中国/标准/标准组织":{"title":"标准组织","links":[],"tags":["中国/标准"],"content":"国家标准\n\n中国标准化研究院官网专注于标准化理论、政策、技术研究及标准开发旨在推进中国标准化事业发展。\n中国标准化杂志社官网出版《中国标准化》等杂志提供标准化领域的新闻、政策、研究成果等信息。\n国家标准化管理委员会负责全国标准化工作的管理和监督发布国家标准和相关政策。\n国家认证认可监督管理委员会负责国家认证认可的监督管理工作包括产品、服务的认证体系和认可体系。\n中国标准在线服务网提供标准查询、下载服务支持标准化信息的检索和获取。\n国家标准全文公开系统公开发布国家标准的全文信息用户可以免费查询和下载国家标准。\n全国标准信息公共服务平台提供国内所有的国家标准 (5 万多)、行业标准7 万多、地方标准4 万多)、团体标准、企业标准、国际标准(近 8 万)的查阅,提供大部分国家标准的在线阅读。\n\n行业标准\n\n国家工程建设标准化信息网工程建设的国家标准特别是强制性标准及工程建设行业标准。\n住房和城乡建设部提供国家、行业标准发布公告随公告提供部分标准全文的免费阅读及下载。\n生态环境部提供 1700 余项生态环保国家标准、行业标准的全文免费阅读及下载。\n商务部流通标准制修订信息管理系统96 项商业行业标准可下载(页面右侧)。\n水利部国际合作与科技司水利部水利技术标准查询系统系统全文公开了水利部已发布实施的所有水利行业标准其中推荐性标准684 条可在线阅读强制性标准93 条)可下载使用。\n国家广播电视总局广电总局标准信息查询系统公开广播电视工程建设标准可下载其他标准提供主要内容和适用范围等信息。\n国家粮食和物资储备局粮食和物资储备局公开现行粮油国家标准目录、行业标准目录。\n中国气象局中国气象局公开 497 余项行业标准,可免费下载。\n全国金融标准化技术委员会中国人民银行金融标准全文公开系统63 项推荐性国标标准358 项推荐性金融行业标准可查询、浏览。\n国家林业和草原局中国林业网公开林业行业标准 1523 项。\n自然资源部自然资源标准化信息服务平台可提供查阅浏览国家标准 469 条,行业标准 804 条。\n国家卫生健康委员会食品安全国家标准数据检索平台准提供查询下载 1312 条食品安全国家标准。\n体育标准化信息平台提供 85 项体育领域的国标和行标查询服务,部分标准可在线浏览,部分只有摘要信息。\n农业农村部农产品质量安全监管局的“农业标准”板块随公告公开农业行业标准和国家标准目录。\n交通运输标准化信息平台提供 2410 个交通运输相关国家标准、行业标准免费阅读服务。\n工业和信息化部统一检索平台数据库提供各领域标准规范数据。\n国家铁路局标准规范平台提供铁路技术标准、工程建设标准、工程造价标准目录。\n公安部信息公开板块中的公共安全行业标准公告提供公安行业标准目录没有在线浏览和下载服务。\n\n地方标准\n\n地方标准信息服务平台在这个平台可以看到各地已备案的地方标准查询。\n\n各省份地方标准查询网址\n\n北京市地方标准1779 项可在线查看文本IE 浏览器)。\n上海市地方标准上海质量发展与标准信息公共服务平台。\n广东省地方标准公开系统1883 项可在线查看文本IE 浏览器)。\n重庆市地方标准重庆地方标准信息公开 1096 项,部分标准可在线浏览。\n天津市地方标准天津市地方标准在线阅读 890 项,可免费下载。\n山东省地方标准山东省地方标准公开共 3461 项,可在线阅读。\n江苏省地方标准江苏现行地方标准服务平台包括综合类、工业类、农业类等共 2726 项。\n浙江省地方标准浙江省地方标准网共 884 项。\n陕西省地方标准陕西省地方标准公共信息服务平台共 1365 项。\n湖南省地方标准2392 项,可在线浏览。\n江西省地方标准可在线阅读。\n福建省地方标准需要登录才能阅览。\n广西地方标准1954 项,只有目录、不能阅读和下载。\n贵州省地方标准1591 项(现行有效 984 项),可在线阅读和下载。\n云南省地方标准可在线阅读。\n甘肃省地方标准可在线阅读。\n青海省地方标准1791 项,只有目录,不能阅读和下载。\n宁夏地方标准可以阅读。\n吉林省地方标准1962 项标准,可下载文本。\n内蒙古地方标准内蒙古标准文献共享服务平台。\n新疆地方标准现行有效的新疆维吾尔自治区地方标准目录。\n\n三方平台\n\n行业标准信息服务平台提供行业标准的查询、下载服务便于各行业主体获取标准化信息。\n全国团体标准信息平台集中展示全国团体标准信息支持标准查询、查看和下载。\n企业信息标准服务平台针对企业标准化工作提供标准查询、制定、管理等服务促进企业标准化建设。\n\n下载\n\n学兔兔 (原标准分享网):提供国内外标准文档的搜索与下载服务,便于用户快速获取所需标准文件。\n"},"SocialSciences/Government/中国/法律/法律文书":{"title":"法律文书","links":[],"tags":["中国/法律"],"content":"官方\n\n中国裁判文书网提供全国各级法院生效裁判文书的检索、查看和下载。\n中国法律服务网网站整合并收录了全国范围内的「法律服务机构」和「法律人员数据」。\n国家法律法规数据库国家法律法规数据库目前提供中华人民共和国现行有效的宪法含修正案、法律、行政法规、监察法规、地方性法规、自治条例和单行条例、经济特区法规、司法解释电子文本。\n合同示范文本库 - 国家市场监督管理总局:合同示范文本库收集了市场监管部门制定发布的合同示范文本,供社会公众查阅下载。\n\n三方\n\n\n北大法宝北大法宝是一个涵盖法律法规、立法沿革、条文释义、相关案例、法学期刊和实务专题等内容的综合性法律检索网站\n\n\n法天使-中国合同库:秉承着“推广中国合同标准,提升中国社会合同水平”的使命,以“中国合同标准”为核心。\n\n\n中国法律快查手册 - Github 地址:法律内容来源于 国家法律法规数据库,该项目仅做整合和搜索等功能\n\n"},"Technology/CloudService/基础/IT-基础架构":{"title":"IT 基础架构","links":[],"tags":["技术/云计算","云计算/基础"],"content":"概述\n**信息技术IT基础架构是指运行和管理企业 IT 环境所需的组件。**IT 基础架构可以部署在云计算系统中,也可以部署在企业自己的设施中。\n这些组件包括硬件、软件、网络组件、操作系统OS和数据存储它们共同提供了各种 IT 服务和解决方案。IT 基础架构产品可以是运行于现有 IT 资源之上的可下载软件应用例如软件定义存储也可以是服务提供商提供的在线解决方案例如基础架构即服务IaaS。\nIT 基础架构的组件\n硬件物理\n硬件包括服务器、数据中心、个人电脑、路由器、交换机及其他设备。\n基础架构也包括存放数据中心以及为其提供冷却和供电服务的设施。\n软件逻辑\n软件是指企业使用的各种应用例如 Web 服务器、内容管理系统和操作系统(如 Linux®。操作系统负责管理系统资源和硬件并在所有软件与相关的物理资源之间建立连接。\n网络通信\n相互连接的网络组件可实现内部和外部系统之间的网络操作、管理和通信。网络由互联网连接、网络支持、防火墙与安全防护以及路由器、交换机和电缆等硬件组成。\nIT 基础架构的类型\n传统基础架构\n在传统基础架构中组件如数据中心、数据存储及其他设备全部由企业自己所有在自己的设施中管理。传统基础架构通常被认为运行成本高昂并且需要大量硬件例如服务器以及相应的系统用电和物理空间。\n云基础架构\n云基础架构是指云计算所需的组件和资源。您可以利用您的专有资源来自行构建私有云也可以通过从云提供商如阿里巴巴、Amazon、谷歌、IBM 或 Microsoft那里租用云基础架构的方式来使用公共云。而通过在多个云之间组合一定程度的工作负载可移植性、编排和管理您还可以创建混合云。\n超融合基础架构\n超融合基础架构能让您用一个界面就能管理您的计算、网络和存储资源。通过将软件定义型计算与数据存储捆绑在一起您可以借助行业标准硬件上的可扩展架构来支持更多的现代工作负载。\nIT 基础架构管理\nIT 管理是对各种 IT 资源、系统、平台、人员和环境进行协调统筹。以下是一些最常见的技术基础架构管理类型:\n\n操作系统管理通过提供内容、补丁、置备和订阅的管理监督运行相同操作系统的环境。\n云管理通过管理资源部署、使用情况、集成和灾难恢复使云管理员可以控制云中运行的所有内容最终用户、数据、应用和服务。\n虚拟化管理与虚拟环境和底层物理硬件对接以简化资源管理、增强数据分析并简化运维。\nIT 运维管理:也称为业务流程管理,是指对经常重复、正在进行或可预测的业务流程进行建模、分析和优化的实践。\nIT 自动化:创建可重复的指令和流程,以取代或减少人与 IT 系统之间的交互。也称为基础架构自动化。\n容器编排自动化容器的部署、管理、扩展和联网。\n配置管理让计算机系统、服务器和软件保持所需的一致状态。\nAPI 管理分配、控制和分析跨企业和云连接应用与数据的应用编程接口API。\n风险管理识别和评估风险并制定相关计划从而最大程度降低或控制这些风险及其潜在影响。\n数据管理收集、存储和使用数据使组企业能够了解他们拥有哪些数据、数据位于何处、谁拥有这些数据、谁可以看到数据以及如何访问数据。\n"},"Technology/CloudService/基础/云计算":{"title":"云计算概述","links":["Tech/cloud-service/基础/基础架构即服务IaaS","Tech/cloud-service/基础/平台即服务PaaS","Tech/cloud-service/基础/软件即服务SaaS","Tech/cloud-service/基础/功能即服务FaaS"],"tags":["技术/云计算","云计算/基础"],"content":"云计算\n云计算是指由第三方提供商托管的基础架构、平台或软件通过互联网提供给用户。\n云服务有助于用户数据从前端客户端诸如用户的服务器、平板电脑、台式机、笔记本电脑等任何用户端设备通过互联网流向提供商的系统然后再返回。云服务促进了云原生应用的构建和在云端工作的灵活性。用户只需借助计算机、操作系统和互联网连接即可访问云服务。\n云计算的选项\n凡是用户无需下载其他软件而是直接通过互联网就能访问的所有基础架构、平台、软件或技术都可以视为云计算服务包括以下即服务类解决方案。\n\n\n基础架构即服务IaaS 为用户提供计算、网络和存储资源。\n平台即服务PaaS 为用户提供一个可运行应用的平台,以及运行所需的所有 IT 基础架构。\n软件即服务SaaS 为用户提供必备的云应用、应用运行平台以及平台的底层基础架构。\n功能即服务FaaS 是一种事件驱动型执行模型,它允许开发人员以功能的形式来构建、运行和管理应用包,无需维护基础架构。\n\n云是一种 IT 环境,可以抽象、汇集和共享整个网络中的可扩展资源。云的主旨是用于进行云计算,也就是在云环境中运行工作负载。云是一种 PaaS因为硬件和应用软件平台由另一方提供。\n云计算服务的运作原理是什么\n与其他所有 IT 解决方案一样,云服务也依赖于硬件和软件。但是,与传统的硬件和软件解决方案不同,用户只需计算机、网络连接和操作系统即可访问云服务。\n云基础架构\n在为用户提供云基础架构时云服务提供商会将计算功能与硬件组件分离开例如\n\n将处理能力与中央处理器CPU分离开\n将活动内存与随机存取存储器RAM芯片分离开\n将图形处理与图形处理单元GPU分离开\n数据存储空间与数据中心或硬盘分离开\n\n**这种抽象通常是通过虚拟化和虚拟机来实现的。**分离后,存储、计算和网络组件将通过互联网以基础架构(或 IaaS的形式提供给用户。这种云服务促进了云存储的兴起后者是将大数据作为物联网IOT的一部分进行存储。RackSpace 就是 IaaS 提供商的一个例证。\n云平台\n云服务提供商还可以使用其硬件资源来创建云平台这是一种用户可以在其中开发代码或运行应用的在线环境。构建云平台不仅需要从硬件组件中抽象计算机功能还需要提供云基础架构。提供云平台需要更高级别的开发工作以整合诸如容器化、编排、应用编程接口API、路由、安全、管理和自动化等技术。用户体验设计UX也是营造可控在线体验的重要考虑因素。\n云平台是一种 PaaS。如果支持 PaaS 的基础架构组件具有高度可扩展性和可共享性则可以将其视为云。PaaS 云的最佳例证包括公共云和托管私有云。\n公共云\n**公共云是一个虚拟资源池,可自动置备并通过自助服务界面在多个客户端间进行分配,其中的虚拟资源来自第三方公司所有和管理的硬件设备。**当工作负载出现意外需求波动时,可直接通过公共云进行横向扩展。\n如今公共云通常不会作为独立的基础架构解决方案来部署而是被作为异构混合环境的一部分部署这样既可以提高安全性和性能降低成本还可以提高基础架构、服务和应用的可用性。\n公共云提供商会从其拥有的硬件中抽象自己的基础架构、平台或应用将它们汇集到数据湖中并与许多租户共享。他们还可提供公共云服务如 API 管理、基于云的操作系统、或被称为框架的开发模板库。一些热门公共云包括阿里云、Microsoft Azure、Google 云、Amazon Web ServicesAWS及 IBM Cloud。\n私有云\n**私有云是一种专为最终用户而创建,而且通常位于用户的防火墙内的云环境。**尽管传统上私有云在本地运行,但现在许多企业构建的私有云位于供应商租赁的外部数据中心内。\n如果底层 IT 基础架构归某个拥有完全独立访问权限的客户专有,那这种云就是私有云。\n私有云提供商也称为托管云提供商他们向客户提供私有云但私有云由客户以外的其他方进行部署、配置和管理。这种云交付方案适合 IT 团队人手不足或技能欠缺的企业或小型企业,能为用户提供更为出色的私有云服务和基础架构。\n云软件\n**提供商可以提供并最终被广泛接受的云服务是一个完整的 Web 应用,也称云软件或 SaaS。**这需要最大规模的开发投资,因为云提供商实际上是在为客户提供在线应用。\n**云软件可以通过云原生方法提供,云原生是一种结合了小型、独立和松散耦合的微服务的应用架构。**多个微服务可以打包至由容器编排引擎(如 Kubernetes 或红帽® OpenShift®管理的单个 Linux® 容器中。最终产品是一个云应用,可通过微服务进行优化,而不会对整个应用中的其他微服务造成影响。"},"Technology/CloudService/基础/功能即服务FaaS":{"title":"功能即服务FaaS","links":[],"tags":["技术/云计算","云计算/基础"],"content":"概述\n功能即服务FaaS是一种云计算服务它允许开发人员以功能的形式来构建、计算、运行和管理这些应用包无需维护自己的基础架构。\nFaaS 是一种在无状态容器中运行的事件驱动型执行模型,这些功能将利用 FaaS 提供商的服务来管理服务器端逻辑和状态。\nFaaS 解决方案可通过主流公共云提供,并可在内部置备,这样就为企业 IT 应用开发新增了一些重要的功能。获取云原生策略指南,为借助 FaaS 实施无服务器方案做好准备。\n以下是 FaaS 的一些常见示例:\n\nIBM 云功能\nAmazon 的 AWS Lambda\nGoogle 云功能\nMicrosoft Azure 功能(开源)\nOpenFaaS开源\n\nFaaS 和无服务器\nFaaS 是一种实现无服务器计算的方法,藉此开发人员可以编写业务逻辑,然后在完全由平台管理的 Linux 容器中执行这些业务逻辑。\n虽然通常只是一个使用云计算服务的云计算平台但该模型还在扩展中包含内部部署和混合部署。\n无服务器会对基础架构问题进行抽象处理例如管理或置备服务器及开发人员的资源分配并将其提供给平台如红帽® OpenShift®这样开发人员就可以专注于编写代码和实现业务价值。\n功能是操作系统上的一个运行业务逻辑的软件。应用可以由许多功能组成。\n使用 FaaS 模型是通过无服务器架构来构建应用的方法之一,但随着无服务器模式的日渐普及,开发人员正在寻找支持构建无服务器微服务和无状态容器的解决方案。\n功能即服务是如何运行的\n**FaaS 为开发人员提供了一种运行 Web 应用的抽象方式,可以在无需管理服务器的情况下响应事件。**例如,上载文件可触发自定义代码,从而将文件转码为各种格式。\nFaaS 基础架构通常是由服务提供商按需计量的,主要通过事件驱动型执行模型进行,因此它会随时待命,但不需要任何服务器进程在后台持续运行(这一点与平台即服务 PaaS不同。\n现代 PaaS 解决方案提供了无服务器功能(作为通用工作流的一部分),藉此开发人员可以实现应用的部署,从而模糊了 PaaS 和 FaaS 之间的界线。\n实际上整个应用将由以下解决方案混合而成功能、微服务和长期运行的服务。\nFaaS 动态扩展\n**提供商会通过应用编程接口API让您的功能处于可用状态并管理资源分配。**由于功能是事件驱动而不是资源驱动的,因此它们很容易进行扩展,这种扩展允许提高效率和价值。\n为了发挥部分优势其体系架构会受到一定制约例如对功能执行施加时间限制因此需要做到功能的快速启动和运行。\n功能会在毫秒内启动并处理各个请求。如果您的功能有多个同步请求系统将创建尽可能多的功能副本来满足需求。\n当需求下降时应用会自动减少功能副本的数量。动态扩展是 FaaS 的一项优势,而且颇具成本效益,因为提供商仅对使用的资源收费,而不对空闲时间收费。\n在内部运行时这种动态特性还可以提高平台密度从而允许运行更多工作负载并优化资源消耗和功能。\n需要横向扩展的事件驱动型服务可作为功能和 RESTful 应用进行工作。\n**FaaS 非常适合大数据量的交易、经常发生的工作负载,例如报表生成、图像处理或任何计划任务。**常见的 FaaS 用例包括数据处理、IoT 服务、移动和 Web 应用。\n您可以使用 FaaS 构建完全无服务器化的应用,也可以打造部分无服务器、部分传统微服务组件的应 用 ,以便利用更新的技术和容器编排系统,如 Kubernetes。\nFaaS 的优势是什么?\n\n提高开发人员的生产率并缩短开发时间\n不负责服务器管理\n易于扩展且横向扩展由平台管理\n仅在必要和需要时消耗资源或支付费用\n几乎可以用任何编程语言来编写功能\n"},"Technology/CloudService/基础/基础架构即服务IaaS":{"title":"基础架构即服务IaaS","links":["Tech/cloud-service/基础/IT-基础架构"],"tags":["技术/云计算","云计算/基础"],"content":"IaaS 概述\n基础架构即服务IaaS让您从本地 IT 基础架构 往轻松迈进了一步。这是一种即付即用的服务,由外部的第三方提供商根据您的需要,利用互联网(通过云)为您提供基础架构服务(如存储和虚拟化)。\n作为用户您只需负责操作系统以及任何数据、应用、中间件和运行时而提供商会给您访问和管理所需网络、服务器、虚拟化和存储的权限。\n**您无需维护或更新自己的本地数据中心,因为提供商会为您代劳。**此外您可以通过应用编程接口API或控制面板来访问和控制基础架构。\n**IaaS 可以让您享受较大的灵活性:您可以仅购买所需的组件,然后根据需要进行扩展或缩减。**这样不仅开销低,而且无维护成本,从而使 IaaS 成为一种经济实惠的方案。\n**IaaS 的一大用途就是快速、灵活地构建和拆解开发与测试环境。**您可以仅使用创建开发环境所需的基础架构,并在需要时进行扩展或缩编,完成后,您可以立即停用,这样就只需为所使用的内容付费。\n**IaaS 的主要短板在于可能存在的提供商安全问题、多租户系统问题(提供商必须与多个客户端共享基础架构资源)以及服务可靠性。**但选择可靠且可信赖的提供商(具有可靠的历史和声誉)就可以避免这些问题。\nIaaS 与虚拟化、自动化和容器化的关系\nIaaS 提供商可以免除在设置管理服务器方面的开销来简化开发人员体验。这通常依赖于虚拟化、容器和自动化所支持的云计算架构。对于开发人员来说,不必再考虑服务器管理工作,可以大刀阔斧地构建和部署应用。\n通过虚拟化虚拟机VM来提供完整的环境这些环境充当具有其自身 CPU、内存、网络接口和存储的虚拟计算机系统。在 IaaS 中,这些是在数据中心的物理硬件系统上创建的。通过名为虚拟机监控程序的软件,用户可以将机器的资源与硬件分开并进行适当置备,以供虚拟机使用。\nIT 自动化在每个 IaaS 产品的服务下工作,使底层虚拟机和其他基础架构能够无缝部署,并根据需要进行扩展和缩减以满足需求。跨系统或计算机组的多个任务和配置的自动化称为编排。\nIaaS 产品还可以支持容器化,其中软件代码及其所有必要的组件(如库、框架和其他依赖项)均打包在自己的 Linux® 容器中,可以随时部署到计算环境(可以是 VM中。与虚拟机相比容器不包含自己的操作系统OS因此规模可能要小得多。\n特定的 IaaS 解决方案可以帮助开发人员使用容器。其中一种解决方案是 Kubernetes这是一个开源容器编排平台可帮助大规模地管理分布式、容器化的应用。Kubernetes 负责自动化部署和管理容器。一些 IaaS 提供商可提供 Kubernetes 即服务。\nIaaS 与 DevOps 有什么共同点?\n**DevOps 描述了一种在开发和运维交叉点的工作方式。**这种工作方式强调减少软件改进推进到部署所需要的时间以便用户更快地访问新应用。DevOps 方法要求开发团队和运维团队频繁沟通并作为队友进行协作。\n**DevOps 时刻关注代码和动态基础架构使用的频繁变更,因此非常适合于 IaaS。**DevOps 强调在应用的整个生命周期中,确保日常运维任务自动化和环境的标准化。因此 DevOps 团队经常会使用微服务架构来构建软件,并通过 API 将这些服务彼此相连。这些都有助于团队更快地交付软件,专注于创建较小的功能,然后使用敏捷方法等策略将其整合在一起。\nIaaS 通过减少维护服务器基础架构的需求,同时强调更简单的自动化开发人员体验,因此有助于支持 DevOps 工作流。\nIaaS 和 无服务器之间的区别\n无服务器计算描述了一种云原生开发模型其中服务器从应用开发中抽离出来并且通常会与 IaaS 相关联。\n无服务器依靠云提供商来管理基础架构和应用扩展。无服务器应用部署在容器中这些容器在被调用时会自动按需启动。\n在 IaaS 下,用户通常自行负责在需求旺盛时扩展服务器容量,并在不再需要该容量时缩减服务器容量。即使在应用闲置不用期间,运行该应用所需的云基础架构也要保持就绪。\n无服务器架构则与之相反应用仅在需要时启动。有事件触发应用代码运行时公共云提供商才会为这一代码分配资源。该代码执行结束后用户便不再付费。使用无服务器时管理操作系统和文件系统、安全补丁、负载平衡、容量管理、扩展、日志和监控等例行任务都由云服务提供商分担。\n在选择 IaaS 提供商时要考虑的事项\n\n**灵活性:**仅购买用例所需的组件,然后根据业务需要进行扩展或缩减。\n**经济性:**低开销、无维护成本使 IaaS 成为一种价格实惠的方案。您只需按实际用量和使用频次付费,就像支付水电费那样。\n**可控:**用户可以控制其基础架构。\n**安全性:**提供商是否值得信赖?是否有用于防范和管理任何安全威胁的资源?是否有记录在案的灾难恢复协议来确保业务连续性?\n**多租户系统:**由于 IaaS 提供商倾向于根据需要将基础架构资源分配给多个客户端,因此提供商需要确保客户无法访问彼此的数据。让多个客户使用提供商的基础架构也会造成失衡,称之为 ” 相邻干扰 “(单个用户垄断特定资源会降低其他用户的效能),因此提供商需要谨慎规划资源分配。为此,要了解提供商将如何根据用户的负载进行扩展,这一点很重要。\n**服务:**什么是服务提供商的服务级别协议SLA是提供商承诺解决资源置备问题所付出的最短时间和最小精力吗\n**可靠性:**性能和速度在很大程度上要取决于提供商。任何软件或硬件问题最终都会影响到用户的运行时。\n"},"Technology/CloudService/基础/平台即服务PaaS":{"title":"平台即服务PaaS","links":[],"tags":["技术/云计算","云计算/基础"],"content":"概述\n平台即服务PaaS是一种由第三方提供应用软件平台的云计算形式。PaaS 主要面向开发人员和程序员,它允许用户开发、运行和管理自己的应用,而无需构建和维护通常与该流程相关联的基础架构或平台。\nPaaS 平台可在云端或本地基础架构中运行。对于托管的产品PaaS 提供商会将硬件和软件托管在自己的基础架构上,并通过互联网以集成解决方案、解决方案堆栈或服务的形式将该平台交付给用户。\nPaaS 的优势\n使用 PaaS 环境的优势包括转移部分职责如维护服务器、更新基础架构软件以及设置用于构建应用的自定义平台。PaaS 提供商可托管平台,并为正在运行的应用提供环境。\n软件团队可专注于开发和部署应用不必担心底层基础架构的维护和更新。这样就为进一步的开发和创新减少了干扰同时也缩减了基础架构设置和写代码的工作量。由于 PaaS 位于云端,因此也便于进行扩展和迁移。\n选择 PaaS 环境进行应用开发的企业可享受诸多好处。\n\n**使用现有技能和投资。**开发人员可访问操作系统、中间件、框架及其他开发工具,并使用熟悉的编程语言快速进行编码。\n**降低成本。**PaaS 定价意味着按实际用量付费,不必投资购置大量本地计算基础架构,免得大多数时候闲置不用。\n**缩短应用开发周期。**PaaS 可帮助开发团队加速应用开发,并减少部署新软件所需的时间。\n**实现高效的开发运维。**开发运维策略将开发人员和 IT 运维相结合,因此您可以通过持续交付来快速开发和部署应用。\n**维护安全措施。**与 PaaS 提供商合作有助于确保以统一的方式管理与安全实践相关的决策。基于云的服务将受益于专门研究安全问题的训练有素的团队。\n**提高工作效率。**开发人员可通过自助服务功能,快速获得所需工具与资源。开发环境自动置备,因此团队可专注于能够增值的工作,而不是常规的基础架构管理。\n\nPaaS 如何发挥作用?\n企业为了适应业务的快速变更需要考虑不计其数的工具和策略组合而其中一些组合只能产生很小的影响。究其根本平台生态系统是一种以富有意义的方式支持转型的中央工具。\n平台不仅与技术有关也关乎人员和流程。平台生态系统包括数字平台、将平台作为产品进行创建和管理的平台团队\n以及帮助平台生态系统蓬勃发展和实现可持续发展目标的平台社区。\n数字平台在许多情况下是 PaaS成为了转型的焦点。数字平台是基础由自助服务 API、工具、服务、知识与支持作为令人信服的内部产品进行安排组成。\n自主开发和交付团队可利用该平台以更高的速度、更少的协调工作提供业务功能。企业的数字平台可用作不同团队之间的接口以便改进通信和协作同时减少对锁步协调的需求。\n有效使用该平台可减轻技术人员的负担交付方面的压力和越来越多的技术债务导致技术人员负担沉重在转型工作面临的众多障碍中这是其中两个主要障碍。该平台可促进学习和形成新行为。\n选择 PaaS 提供商时要考虑的事项\n在做出有关 PaaS 解决方案的决策前,您应该注意以下几点:\n\n**要涵盖哪些功能?**您的应用能够与之协调工作吗?随着您的应用不断成长和发展,用户数量会越来越多,您需要确保能够在提供商的协助下轻松实现扩展并提供所需的选项。\n**它是否已针对您所使用的语言和框架进行了优化?**如果没有,运行时可能会成为问题。\n**提供商能否提供随叫随到的贴心服务?**您需要确保自己的提供商长期拥有可靠可信的客户服务,从而保障您可以享受周到的服务。\n**您预计会有多少用户使用您的应用?**用户越多,代码越具体,应用运行就越慢,而从一个服务提供商迁移到另一服务提供商的难度也就越大。\n"},"Technology/CloudService/基础/软件即服务SaaS":{"title":"软件即服务SaaS","links":[],"tags":["技术/云计算","云计算/基础"],"content":"概述\n**软件即服务SaaS是一种云计算形式可通过网络浏览器为终端用户提供云应用及其所有的底层 IT 基础架构和平台。**对于符合以下条件的大型企业、小型企业或个人而言SaaS 可能是理想的解决方案:\n\n\n想避免购买或维护基础架构、平台和本地软件的麻烦。\n\n\n更喜欢通过运营支出OPEX进行更简单的成本管理而不是通过资本支出投资CAPEX。\n\n\n需要尽可能减少自定义。\n\n\n青睐软件订阅模式。\n\n\nSaaS 是如何运作的?\n不再像传统软件那样需要永久购买软件或投资可靠的本地 IT 基础架构SaaS 可以降低用户的前期成本。然而由于服务性能取决于互联网连接速度SaaS 用户应投资购买高速的网络硬件。\nSaaS 的示例包括一些应用服务提供商ASP如 Google Docs 和 Microsoft Office 365以及一些提供人力资源软件、电子商务系统、客户关系管理工具和集成开发环境IDE的企业服务。\n常见部署模式有两种软件供应商通常会选择其一或两者皆选\n\n数据中心\n公共云服务提供商如 AWS、Azure 或 IBM Cloud管理托管 SaaS 解决方案的云环境。\n\n**SaaS 应用利用多租户架构来隔离用户数据。**软件更新、漏洞修复以及其他常规应用维护都是由 SaaS 提供商负责用户通过网络浏览器与软件交互。SaaS 解决方案通常功能齐全但有时通过应用编程接口API如 REST 或 SOAP融入自定义集成以连接其他功能。\n**SaaS 的特性使提供商更容易向客户推出新功能。**大多数 SaaS 应用都是预配置的即插即用产品SaaS 提供商将管理这些应用背后的所有内容,包括:\n\n硬件组件例如网络、存储和数据中心服务器\n平台例如虚拟化、操作系统和中间件\n各种软件要求例如运行时、数据和应用本身\n\nSaaS 模式\n**SaaS 应用在很大程度上依赖于订阅模式置备软件许可证。**和永久许可证不同,该软件交付模式是将每个帐户与订阅进行关联,而后者则在一段时间内(通常是每年或每月)授予 SaaS 相应的访问权限。缴纳订阅费后通常帐户会获得对产品文档和服务级别协议SLA规定的持续支持的访问权限但有些 SaaS 提供商会收取额外的支持费用,才能进行源代码级别上的自定义代码更改。"},"Technology/ComputerNetwork/Nginx/内容缓存":{"title":"内容缓存","links":[],"tags":["Nginx/内容缓存","技术/计算机网络"],"content":"Nginx作为一种高效的 Web 服务器和反向代理服务,提供了一系列功能以优化和加速内容的交付。其中,内容缓存是其核心功能之一,它能显著提升网站的响应速度和后端服务的效率。\n缓存基础\n缓存是什么\n缓存是一种存储技术它保存数据副本以便快速访问。在 Web 环境中,缓存可以是页面、图片、文件等内容,存储在服务器或客户端。当用户再次请求相同的内容时,系统可以直接从缓存中提取,避免了重复的数据检索或计算过程,从而加快了交付速度。\n缓存能解决的问题\n\n减轻服务器负担 通过缓存常请求的内容,减少对后端服务器的请求次数。\n提高响应速度 缓存的内容直接从内存或快速存储中提供,比从后端服务器处理和传输要快得多。\n提升用户体验 快速加载的页面和资源提升了用户的浏览体验。\n\nNginx 缓存原理\n当用户首次请求网站的某个页面时Nginx 会将请求转发到后端服务器(例如你的网站应用)。后端服务器处理请求后,将页面内容等资源返回给 NginxNginx 再将这些内容发送给用户。在这个过程中Nginx 会将收到的内容保存在缓存中。\n当另一个用户请求同一个页面时Nginx 会检查缓存。如果找到了之前保存的内容并且内容还没有过期Nginx 就会直接从缓存中取出内容发送给用户,而不是再次请求后端服务器。这样大大减少了处理时间和服务器负载。\nNginx 不是随意缓存所有内容,它通过一套规则来确定哪些内容应该被缓存,哪些不应该。这套规则可以非常灵活,你可以指定根据页面类型、用户的某些行为,甚至特定时间和日期来缓存内容。\n缓存的内容并不是永远有效的。有时候网站内容会更新如果用户还是接收到旧的缓存内容那就会出现问题。因此Nginx 允许设置缓存的有效期一旦超过这个期限缓存的内容就会被认为是过时的Nginx 会从后端服务器获取最新的内容,并更新缓存。\nsequenceDiagram\n participant 用户\n participant Nginx\n participant 缓存\n participant 后端服务器\n\n 用户->>Nginx: 发起请求\n alt 缓存存在且有效\n Nginx->>缓存: 检查请求对应的缓存\n 缓存->>Nginx: 返回缓存内容\n Nginx->>用户: 提供缓存内容\n else 缓存不存在或过期\n Nginx->>缓存: 检查请求对应的缓存\n 缓存->>Nginx: 无有效缓存\n Nginx->>后端服务器: 转发请求\n 后端服务器->>Nginx: 处理请求并返回结果\n Nginx->>缓存: 保存新的缓存内容\n Nginx->>用户: 提供后端服务器内容\n end\n\nNginx 缓存配置\n1. 配置缓存区域\n首先你需要在 Nginx 配置文件中定义一个或多个缓存区域:\nhttp {\n proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置指令描述proxy_cache_path指定缓存的存储路径定义了缓存文件存放的文件系统路径。levels定义缓存目录的层级用于创建多级目录结构来存储缓存文件。keys_zone定义缓存区域的名称和大小为缓存键和元数据分配内存。max_size缓存可以占用的最大磁盘空间限制缓存目录可以使用的最大空间大小。inactive在此时间内未被访问的缓存内容将被删除用于清理长时间未访问的缓存。use_temp_path是否使用临时路径存储缓存内容控制是否先写入临时文件再移动到缓存路径。\n2. 启用缓存\n在适当的位置块中启用缓存并指定缓存区域\nlocation / {\n proxy_cache my_cache;\n proxy_pass http://my_backend;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置指令描述proxy_cache在 location 块中使用指定该位置的请求应使用哪个缓存区域。proxy_cache_key定义如何为请求生成缓存键通常包含请求的元素如 URL、请求方法等。proxy_cache_valid设置不同 HTTP 状态码的响应的缓存有效期。proxy_cache_use_stale允许在后端服务器不可用时提供过期的缓存内容。proxy_ignore_headers指示 Nginx 忽略后端服务器发送的某些 HTTP 头常用于控制缓存。proxy_cache_lock在处理缓存项时防止对同一个资源的并发请求只让第一个请求查询后端并缓存其他请求等待。proxy_cache_bypass设置条件在满足条件时请求将绕过缓存直接转发给后端服务器。proxy_no_cache设置条件在满足条件时不对响应进行缓存。proxy_cache_revalidate每次请求都会验证缓存内容的新鲜度适用于需要高度一致性的场景。proxy_cache_min_uses指定一个响应在被缓存前需要被请求的最小次数适用于控制不经常访问的内容的缓存。proxy_cache_methods指定哪些请求方法的响应应该被缓存默认是 GET 和 HEAD。\n示例配置\nhttp {\n # 定义缓存存储路径及相关参数\n proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;\n \n server {\n listen 80;\n \n location / {\n # 指定使用哪个缓存区域\n proxy_cache my_cache;\n \n # 定义缓存键\n proxy_cache_key "$scheme$request_method$host$request_uri";\n \n # 设置缓存有效期\n proxy_cache_valid 200 302 10m;\n proxy_cache_valid 404 1m;\n \n # 使用陈旧的缓存响应\n proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;\n \n # 忽略后端的Cache-Control和Expires头\n proxy_ignore_headers Cache-Control Expires;\n \n # 防止对同一个资源的并发请求\n proxy_cache_lock on;\n \n # 当特定条件满足时绕过缓存\n proxy_cache_bypass $http_cache_control;\n \n # 当特定条件满足时不缓存响应\n proxy_no_cache $http_pragma;\n \n # 验证缓存内容的新鲜度\n proxy_cache_revalidate on;\n \n # 指定一个响应在被缓存前需要被请求的最小次数\n proxy_cache_min_uses 3;\n \n # 指定哪些请求方法的响应应该被缓存\n proxy_cache_methods GET HEAD POST;\n \n # 转发请求到后端服务器\n proxy_pass http://my_backend;\n \n # 添加自定义头部以监控缓存状态\n add_header X-Cache-Status $upstream_cache_status;\n }\n }\n}\n浏览器缓存控制配置\n合理的浏览器缓存策略可以减少服务器负载、减少网络延迟、加快页面加载速度并节省用户的数据使用量。浏览器缓存主要通过 HTTP 响应头来控制,以下是一些最常用的 HTTP 缓存控制头:\n\nCache-Control这是最重要的缓存控制头。它允许指定多种指令来控制资源的缓存策略例如 max-age、no-cache、no-store、must-revalidate 等。\nExpires一个日期/时间值,告诉浏览器在这个时间点之前可以直接从缓存读取资源,而不需要去服务器检查。\nETag资源的唯一标识符。浏览器可以通过发送带有 If-None-Match 的请求来检查 ETag判断资源是否已更改。\nLast-Modified表示资源最后修改的日期和时间。浏览器可以通过发送带有 If-Modified-Since 的请求来检查资源是否已更改。\n\nCache-Control\n现代应用倾向于使用 Cache-Control 头,因为它提供了更多的灵活性和控制。以下是一些常用的指令:\n# 应用中不会改变的文件,通常可以再发送响应头前添加积极缓存\nlocation ~* \\.(js|css|png|jpg|gif)$ {\n add_header Cache-Control public,max-age=31536000;\n}\n \n# 禁止缓存\nlocation ~* \\.(js|css|png|jpg|gif)$ {\n add_header Cache-Control no-store,no-cache,must-revalidate;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项描述no-store指示请求或响应中的信息不能被缓存到任何地方。此设置适用于包含敏感信息的数据。no-cache缓存不应该存储未经验证的响应。即使有缓存每次请求都需要向源服务器进行验证。public表示任何响应都可以被缓存即使是通常不可缓存的内容如经过身份验证的响应。private响应是为单个用户私有的不能由共享缓存存储但可以由私有缓存存储。比如用户的个人信息页。max-age=<seconds>指定资源可以在本地缓存存储并被重用的最长时间以秒为单位。s-maxage=<seconds>类似于 max-age但它仅适用于共享缓存如 CDN。覆盖 max-age 或者 Expires 头但仅在共享缓存中。must-revalidate一旦资源过期即超过 max-age在使用旧的资源之前缓存必须去服务器验证。对于某些需要保持最新的资源很有用。proxy-revalidate与 must-revalidate 类似但它仅适用于共享缓存。immutable指示响应体不会随时间改变。在资源的缓存有效期内浏览器不需要为了验证资源的新鲜度而发送条件请求。stale-while-revalidate=<seconds>表示客户端愿意接受超过 max-age 时间的响应同时在后台异步检查新鲜度。stale-if-error=<seconds>表示如果源服务器在指定的时间内出错(如服务器宕机),客户端愿意接受一个过期的响应。\nExpires\nExpires 头是 HTTP/1.0 的遗留特性,但在 HTTP/1.1 中仍被广泛支持和使用。它用于指定资源的过期时间,告诉浏览器在这个时间点之前可以直接从本地缓存获取资源,而不必去服务器再次请求。一旦过了这个时间,浏览器会向服务器发送请求以检查资源是否有更新。尽管 Cache-Control 的 max-age 指令通常优先于 Expires但在一些老旧的浏览器中可能仍然需要设置此项。\nserver {\n listen 80;\n \n location /images/ {\n root /path/to/images;\n expires max;\n }\n \n location /css/ {\n root /path/to/css;\n expires 30d;\n }\n \n location /js/ {\n root /path/to/js;\n expires 24h;\n }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n时间单位描述示例说明max未来expires max;通常被解释为将资源的过期时间设置远在未来的时间点。y年expires 1y;表示资源应在一年后过期。M月expires 1M;表示资源应在一个月后过期。w周expires 1w;表示资源应在一周后过期。d天expires 30d;表示资源应在 30 天后过期。h小时expires 24h;表示资源应在 24 小时后过期。m分钟expires 45m;表示资源应在 45 分钟后过期。s秒expires 30s;表示资源应在 30 秒后过期。\nLast-Modified\nLast-Modified 头表示资源最后被修改的时间。它是一个日期/时间戳告诉浏览器资源最后一次更改的时间。Nginx 默认会为静态文件发送 Last-Modified 头。如果你的资源是静态文件比如图片、CSS 或 JavaScript 文件,通常你不需要做任何特别的配置。\n当浏览器第一次请求一个资源时服务器响应中会包含 Last-Modified 头。浏览器在下次请求相同资源时,会发送一个 If-Modified-Since 头,其值为之前收到的 Last-Modified 日期。\n如果服务器发现资源自那以后没有被修改它会返回一个 304 Not Modified 状态码,而不是资源内容,告诉浏览器可以安全地使用缓存的版本。\n但是如果你需要确保这个行为是打开的可以确保 http 块中有以下指令:\nhttp {\n server {\n location / {\n root /path/to/your/files;\n add_header Last-Modified $date_gmt;\n }\n }\n}\nETag\nETag实体标签提供了一种资源的唯一标识符通常是一个散列值或版本号。与 Last-Modified 相比,它可以更精确地判断资源是否变化。当浏览器第一次请求一个资源时,如果服务器配置了 ETag响应中会包含一个 ETag 头。浏览器在后续请求相同资源时会发送一个 If-None-Match 头,其值为之前收到的 ETag 值。\n如果服务器发现 ETag 匹配(即资源未更改),它会返回一个 304 Not Modified 状态码,告诉浏览器可以安全地使用缓存的版本。\nNginx 不会默认发送 ETag 头,你需要使用第三方模块或自定义配置。以下是一个示例配置,使用 Nginx 的 ngx_http_headers_module 模块来添加 ETag。\nhttp {\n server {\n location / {\n root /path/to/your/files;\n etag on; # 开启ETag\n }\n }\n}\nGzip 压缩配置\ngzip 是一种数据格式和文件压缩程序,使用 Lempel-Ziv 编码LZ77和 32 位循环冗余校验。当 Web 服务器启用了 gzip 压缩时,它会在发送文件到浏览器之前先将其压缩。支持 gzip 的浏览器会在 HTTP 请求头中包含 Accept-Encoding: gzip表示它可以接收 gzip 压缩的内容。服务器响应这些请求时,会添加 Content-Encoding: gzip 头部,并发送压缩后的内容。\n\n减少文件大小通常可以减少 70% 左右的文件大小,从而减少网络传输时间。\n提高加载速度较小的文件可以更快地下载和解析提升用户体验。\n节省带宽资源对于网站运营者来说减少数据传输可以降低带宽成本。\n\nNginx 中配置 Gzip 压缩\n在 Nginx 中启用 gzip 压缩相对简单。以下是一些基本的配置指令:\nhttp {\n gzip on;\n gzip_buffers 16 8k;\n gzip_comp_level 5;\n gzip_min_length 256;\n gzip_http_version 1.1;\n gzip_proxied any;\n gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;\n gzip_vary on;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n指令描述默认值/示例gzip启用或禁用 gzip 压缩。on / offgzip_buffers设置用于压缩的缓冲区数量和大小。16 8kgzip_comp_level设置 gzip 压缩级别,范围是 1最快到 9最优。较高的压缩级别可以提供更好的压缩率但会消耗更多 CPU 资源。1gzip_disable禁用 gzip 压缩的浏览器正则匹配。用于兼容不支持 gzip 的老旧浏览器。"msie6"gzip_min_length设置触发压缩的最小响应体大小。较小的文件可能不值得压缩。20 字节gzip_http_version设置启用压缩的最低 HTTP 协议版本。1.1gzip_proxied设置在何种代理请求情况下应用压缩。offgzip_types设置哪些 MIME 类型应该被压缩。通常包括文本文件如 HTML, CSS, JavaScript 等。text/htmlgzip_vary启用或禁用根据请求头中的 Accept-Encoding 发送 Vary: Accept-Encoding 响应头。off\nGzip 压缩适合哪些内容\n\n文本文件HTML、CSS、JavaScript、XML 和 JSON 等文本文件通常能获得很好的压缩效果。\nAPI 响应:对 JSON 或 XML 格式的 API 响应进行压缩,能加快移动应用或 Web 服务的响应速度。\n\n注意事项\n\n不要压缩已经压缩过的文件对于 JPEG、PNG、MP3 和 PDF 等已经压缩过的文件,再次压缩不仅效果不佳,甚至可能使文件变大。\n考虑 CPU 资源:虽然 gzip 压缩可以减少带宽使用,但它会增加服务器端的 CPU 负担。在负载较高的服务器上,应合理设置压缩级别。\n客户端支持几乎所有现代浏览器都支持 gzip但在配置服务器时仍需考虑兼容性问题。\n\n高级缓存策略\n缓存预热\n缓存预热是指在缓存启动后系统自动访问特定的 URL 列表以填充缓存的过程。这确保了当真实用户请求到达时,他们需要的内容已经在缓存中可用,从而避免了冷启动时的延迟。\n内容无效化\n内容无效化是指在内容更新或变得不再有效时有选择性地移除或更新缓存中的这些内容。这可以通过设置适当的缓存过期策略或使用 API 调用来手动清除特定的缓存项来实现。\n智能缓存层\n根据内容的类型和访问频率智能缓存层可以自动决定将内容缓存在哪个层级内存、SSD、HDD 等)。对于经常访问的热门内容,应优先存储在速度更快的存储中。\n缓存调试与优化\n缓存命中率优化\n\n精细化缓存键调整 proxy_cache_key确保相似请求共享缓存不同请求分开缓存提高缓存利用率。\n使用缓存分级对不同类型或大小的内容使用不同的缓存策略可以更细致地控制缓存行为提高命中率。\n\n动态与静态内容的处理\n\n使用微缓存对动态内容使用极短时间的缓存例如 1 秒),可以在不牺牲实时性的情况下减轻后端负载。\n内容分发网络CDN将静态内容部署到 CDN 可以加速全球访问速度,并减轻主服务器的压力。\n\n安全性和隔离\n\n用户敏感数据处理确保不会将含有用户敏感信息的动态内容错误地缓存。\n缓存隔离为不同的应用或网站配置独立的缓存区域避免缓存污染和数据泄露。\n\n资源优化\n\n最小化资源在服务器端压缩和最小化 CSS、JS 等文件,可以减少传输的数据量。\n有效的图片格式使用 WebP 等现代图片格式替代传统格式,可以在不牺牲质量的前提下大幅减少图片大小。\n\n监控和调试\n通过分析 Nginx 的访问和错误日志,可以获取关于缓存行为的宝贵信息。\nlog_format cache '*** $remote_addr - $upstream_cache_status [$time_local] '\n '"$request" $status $body_bytes_sent '\n '"$http_referer" "$http_user_agent"';\naccess_log /var/log/nginx/access.log cache;\n\n缓存状态码 Nginx 在响应头中提供了 X-Cache-Status表示缓存命中、未命中或过期等状态。\n\n配置示例\nhttp {\n # 开启gzip压缩\n gzip on;\n # 设置最小压缩长度为1000字节小于此大小的文件不进行压缩\n gzip_min_length 1000;\n # 设置gzip缓冲区大小\n gzip_buffers 4 32k;\n # 指定哪些MIME类型的响应应该被压缩\n gzip_types text/plain application/x-javascript text/css application/xml;\n # 当浏览器支持gzip压缩时添加Vary: Accept-Encoding头\n gzip_vary on;\n # 设置gzip压缩级别范围是1最快到9最优推荐6作为一个平衡点\n gzip_comp_level 6;\n \n # 设置缓存路径,缓存键区域名,内存大小,缓存最大磁盘空间,缓存过期时间和临时路径使用\n proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;\n \n server {\n listen 80;\n server_name example.com;\n \n # 静态内容的浏览器缓存配置\n location ~* \\.(jpg|jpeg|png|gif|ico|css|js)$ {\n # 设置静态资源的过期时间为30天\n expires 30d;\n # 关闭访问日志记录\n access_log off;\n # 设置Cache-Control头使浏览器和中间缓存服务器都可以缓存内容\n add_header Cache-Control "public";\n }\n \n # 动态内容的缓存和浏览器缓存配置\n location / {\n # 代理传递到后端服务器\n proxy_pass http://my_backend;\n # 启用缓存区域\n proxy_cache my_cache;\n # 对缓存内容进行验证,确保内容是最新的\n proxy_cache_revalidate on;\n # 设置资源在被缓存前需要被请求的最小次数\n proxy_cache_min_uses 3;\n # 当后端服务器错误时,使用过期的缓存内容\n proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;\n # 防止多个相同的请求同时更新缓存\n proxy_cache_lock on;\n \n # 为动态内容设置Cache-Control头指示浏览器和代理服务器应该如何缓存内容\n add_header Cache-Control "public, must-revalidate, proxy-revalidate";\n \n # 启用gzip压缩\n gzip on;\n # 允许对代理的响应进行gzip压缩\n gzip_proxied any;\n # 指定哪些MIME类型的响应应该被压缩\n gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;\n }\n }\n}"},"Technology/ComputerNetwork/Nginx/基础配置":{"title":"基础配置","links":[],"tags":["Nginx/基础配置","技术/计算机网络"],"content":"安装使用\n\nLinux在大多数 Linux 发行版中,可以通过包管理器(如 APT、YUM来安装 Nginx。对于希望有更细粒度控制的高级用户可以选择从源代码编译安装。\nWindows可从 Nginx 官方网站下载预编译的 Windows 版本进行安装。\nMacOS通常通过包管理器如 Homebrew 来安装。\n\n主要目录和文件\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n路径类型描述/etc/nginx/, /etc/nginx/conf.d, /etc/nginx/nginx.conf目录/配置文件存放 Nginx 的主要配置文件。/etc/nginx/conf.d/default.conf配置文件默认的服务器配置文件。/etc/logrotate.d/nginx配置文件用于 logrotate 服务的日志轮转配置。/etc/nginx/{fastcgi_params, scgi_params, uwsgi_params}配置文件特定于 cgi 的配置文件。/etc/nginx/{koi-utf, koi-win, win-utf}配置文件编码映射转换文件。/etc/nginx/mime.types配置文件定义 HTTP Content-Type 与文件扩展名的映射。/etc/sysconfig/nginx, /etc/sysconfig/nginx-debug配置文件配置系统守护进程管理器。/usr/lib/systemd/system/{nginx.service, nginx-debug.service}配置文件Systemd 服务文件,用于管理 Nginx 服务。/etc/nginx/modules, /usr/lib64/nginx/modules目录存放 Nginx 模块的目录。/usr/sbin/{nginx, nginx-debug}命令Nginx 服务的可执行文件。/usr/share/doc/nginx-1.12.2, /usr/share/man/man8/nginx.8.gz文件/目录包含 Nginx 的手册和帮助文件。/var/cache/nginx目录Nginx 的缓存目录。/var/log/nginx目录存放 Nginx 日志的目录。/usr/share/nginx/html/{404.html, 50x.html, index.html}文件Nginx 默认的静态资源文件。\nNginx 及其模块的工作方式由配置文件决定。默认情况下,配置文件名为 nginx.conf通常位于 /etc/nginx/ 或其子目录中。\n使用和管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令描述启动 Nginxsudo systemctl start nginx在 Linux 系统上启动 Nginx 服务。停止 Nginx快速sudo nginx -s stop立即终止 Nginx 服务。停止 Nginx优雅sudo nginx -s quit等待当前处理的请求结束后再终止 Nginx 服务。重新加载配置sudo nginx -s reload在不中断服务的情况下重新加载配置文件。测试配置文件sudo nginx -t测试 Nginx 配置文件的语法正确性。查看 Nginx 版本nginx -v显示已安装的 Nginx 版本。查看 Nginx 编译选项nginx -V显示 Nginx 编译选项和配置参数。重启 Nginxsudo systemctl restart nginx在 Linux 系统上重启 Nginx 服务。启用 Nginx 开机自启sudo systemctl enable nginx设置 Nginx 在系统启动时自动启动(仅限 Linux。禁用 Nginx 开机自启sudo systemctl disable nginx禁止 Nginx 在系统启动时自动启动(仅限 Linux。\n注意如果您的系统开启了防火墙可能需要配置防火墙规则来允许访问 Nginx 服务的端口。\n基础配置\nNginx 的配置文件通常位于 /etc/nginx/nginx.conf。它包含几个关键部分\n\nevents 块:配置与 Nginx 服务器及客户端网络连接相关的参数。\nhttp 块:定义全局 HTTP 服务器配置,例如文件类型、日志格式、默认文件类型等。\n\nserver 块:定义虚拟主机及其行为,例如监听的端口和服务器名称。\nlocation 块:根据请求的 URI 匹配并定义处理特定类型请求的行为。\n\n\nmail 块(可选):配置邮件代理服务,如 SMTP、IMAP 和 POP3。\nstream 块(可选):为非 HTTP 协议(例如 TCP 和 UDP提供配置。\n\n层级\nmain (1) # Nginx 的全局配置,适用于所有的服务器和连接\n├── events (1) # 配置影响 Nginx 服务器或与用户的网络连接的参数\n├── http (1) # 用于配置代理、缓存、日志等绝大多数功能和第三方模块,只能定义一个 http 块\n│ ├── server (多个) # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块\n│ │ └── location (多个) # 配置请求路由和各种页面处理情况,每个 server 块可以包含多个 location 块\n│ └── ... # 可配置多个 server 块\n├── mail (1) # 配置邮件服务(可选)\n└── stream (1) # 配置流处理(可选)\ngraph TD\n A[Nginx配置] -->|顶级块| B[events]\n A -->|顶级块| C[http]\n A -->|顶级块| K[stream]\n A -->|顶级块| L[mail]\n\n C -->|子块| D[server]\n C -->|子块| J[upstream]\n D -->|子块| E[location]\n D -->|子块| F[SSL配置]\n D -->|子块| G[负载均衡配置]\n D -->|监听| H[IPv4端口]\n D -->|监听| I[IPv6端口]\n\n K -->|子块| M[server - TCP/UDP]\n M -->|监听| N[IPv4端口 - TCP/UDP]\n M -->|监听| O[IPv6端口 - TCP/UDP]\n\n语法\n\n配置文件由指令与指令块构成。\n每条指令以分号;)结尾,指令与参数间以空格符号分隔。\n指令块以大括号{})将多条指令组织在一起。\ninclude 语句允许组合多个配置文件以提升可维护性。\n通过 # 符号添加注释,提高可读性。\n通过 $ 符号使用变量。\n部分指令的参数支持正则表达式例如常用的 location 指令。\n\n简单指令\n简单指令由名称和参数组成中间用空格分开并以分号结束。\n#简单指令\nroot /data/www;\n块级指令\n块级指令结构类似于简单指令但末尾不是分号而是用大括号 {} 包裹的额外指令集合。如果一个块级指令中包含其他指令,则 - 配置文件由指令与指令块构成。\n\n每条指令以分号;)结尾,指令与参数间以空格符号分隔。\n指令块以大括号{})将多条指令组织在一起。\ninclude 语句允许组合多个配置文件以提升可维护性。\n通过 # 符号添加注释,提高可读性。\n通过 $ 符号使用变量。\n部分指令的参数支持正则表达式例如常用的 location 指令。它被称为一个上下文例如events、http、server 和 location。\n\n# 块级指令示例\nhttp {\n server {\n listen 80;\n server_name example.com;\n access_log /path/to/log/example.access.log;\n root /path/to/root;\n \n location ~ \\.php$ {\n fastcgi_pass 127.0.0.1:9000;\n }\n }\n}\n匹配规则\nlocation 指令用于匹配请求 URI忽略查询参数可以使用字符串或正则表达式。\nlocation [ = | ~ | ~* | ^~ | 空] uri {\n ……\n}\n\n=:精确匹配。\n^~:前缀匹配,如果匹配成功,不再进行后续正则匹配。\n~:区分大小写的正则匹配。\n~*:不区分大小写的正则匹配。\n空无修饰符的匹配匹配以 uri 开头的字符串。\n\n匹配优先级\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n优先级类型描述修饰符1精确匹配完全匹配整个 URI=2最长非正则前缀匹配匹配最长的前缀字符串但不包括正则表达式^~3正则表达式匹配按定义顺序匹配正则表达式~ (区分大小写) 或 ~* (不区分大小写)4普通匹配匹配以指定字符串开始的 URI无修饰符\n请注意以下几点\n\n精确匹配=)具有最高优先级。如果找到匹配项,则立即处理请求并停止搜索。\n最长非正则前缀匹配^~)在没有精确匹配时使用,并且如果找到匹配项,将不会检查后续的正则表达式。\n正则表达式匹配~ 或 ~*)根据它们在配置文件中出现的顺序进行匹配。第一个成功匹配的正则表达式将停止搜索。\n普通匹配无修饰符具有最低的优先级。如果以上所有类型都没有匹配将使用这个匹配规则。\n\n匹配过程示例\nserver {\n listen 80;\n server_name example.com;\n \n # 精确匹配\n location = /exact {\n # 处理 /exact 精确请求\n }\n \n # 最长非正则前缀匹配\n location ^~ /static/ {\n # 处理以 /static/ 开头的请求\n }\n \n # 正则表达式匹配\n location ~ \\.php$ {\n # 处理以 .php 结尾的请求\n }\n \n # 普通匹配\n location / {\n # 处理所有其他请求\n }\n}\ngraph TD;\n A[开始匹配] -->|接收请求| B[尝试精确匹配 '=' ];\n B -- 匹配成功 --> C[处理请求 '/exact'];\n B -- 匹配失败 --> D[尝试最长非正则前缀匹配 '^~'];\n D -- 匹配成功 --> E[处理以 '/static/' 开头的请求];\n D -- 匹配失败 --> F[尝试正则表达式匹配 '~' 或 '~*'];\n F -- 匹配成功 --> G[处理以 '.php' 结尾的请求];\n F -- 匹配失败 --> H[尝试普通匹配(无修饰符)];\n H -- 匹配成功 --> I[处理所有其他请求];\n H -- 匹配失败 --> J[无法处理请求];\n\n\n在这个配置和流程图中\n\n精确匹配Nginx 首先尝试精确匹配 location = /exact。\n最长非正则前缀匹配如果精确匹配失败Nginx 尝试最长非正则前缀匹配 location ^~ /static/。\n正则表达式匹配如果最长非正则前缀匹配失败Nginx 接着尝试正则表达式匹配 location ~ \\.php$。\n普通匹配如果所有正则表达式都不匹配Nginx 最后尝试无修饰符的普通匹配 location /。\n处理请求根据匹配的类型Nginx 将处理相应的请求。\n无法处理请求如果所有类型的匹配都失败请求无法被处理。\n\n全局变量\nNginx 提供了多种内置变量,可以在配置的任何地方使用。以下是一些常见的 Nginx 全局变量及其描述:\nHTTP 相关变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述$host请求行中的 Host如果有 Host 请求头,则用其值替换掉请求行中的主机名。如果请求中没有 Host 行和 Host 请求头,则等于请求匹配的 server 名称。值为小写,不包含端口。$uri请求中的当前 URI不包括 ? 后面的请求参数,它可以通过内部重定向或使用 index 指令进行修改。$document_uri当前请求在 root 指令中指定的值,与 $uri 相同,存在于历史问题中。$request_uri完整的原始请求 URL包括 URI 和参数,无法修改。$scheme请求模式如 http 或 https。$request原始的 URL 请求,包含方法和协议版本。$request_method客户端请求类型如 GET、POST。$request_length所有请求内容的大小包括请求行、头部、包体等。$request_body请求中的包体当使用反向代理并设定用内存暂存包体时有效。$request_body_file临时存放请求包体的文件可以通过特定指令强制所有包体存入文件。$remote_user由 HTTP Basic Authentication 协议传入的用户名。$args请求中的参数可以被修改。$arg_PARAMETERGET 请求中特定参数 PARAMETER 的值。$is_args如果请求有参数则为 ”?”,否则为空字符串。$query_string与 $args 相同,表示请求的查询字符串。$content_length请求头中的 Content-Length 字段值。$content_type请求头中的 Content-Type 字段值。$http_HEADER特定 HTTP 请求头的内容HEADER 需转为小写,破折号变为下划线。$http_user_agent客户端的 user-agent 信息。$http_cookie客户端的 cookie 信息。$cookie_COOKIE获取特定 cookie 的值。\nTCP 相关变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述$binary_remote_addr客户端地址的整型格式对于 IPv4 是 4 字节,对于 IPv6 是 16 字节。$remote_addr客户端的 IP 地址。$remote_port客户端的端口。$connection递增的连接序号。$connection_requests当前连接上执行过的请求数对 keepalive 连接有意义。$proxy_protocol_addr如果使用了 proxy_protocol 协议,则返回协议中的地址(原始用户的地址),否则返回空。$proxy_protocol_port如果使用了 proxy_protocol 协议,则返回协议中的端口(原始用户的端口),否则返回空。$server_addr服务器端地址。$server_port服务器端端口。$server_protocol服务器端协议例如 HTTP/1.1。$TCP_INFOTCP 内核层参数,包括各种 TCP 信息。\nNginx 处理请求过程中产生的变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述$request_time请求处理到现在的耗时单位为秒精确到毫秒。$server_name匹配上请求的 server_name 值。$https如果开启了 TLS/SSL则返回 on否则返回空。$request_completion若请求处理完则返回 OK否则返回空。$request_id以 16 进制输出的请求标识 id共含有 16 个字节,随机生成。$request_filename待访问文件的完整路径。$document_root由 URI 和 root/alias 规则生成的文件夹路径。$realpath_root将 document_root 中的软链接等换成真实路径。$limit_rate客户端响应时的速度上限单位为每秒字节数。可以通过 set 指令修改。\n发送 HTTP 响应时相关的变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述$sent_http_HEADERHTTP 响应头中的内容HEADER 需转为小写,破折号变为下划线。$statusHTTP 响应状态。$body_bytes_sent传送页面的字节数即响应中 body 包体的长度。$bytes_sent全部 HTTP 响应的长度。$sent_trailer_名字把响应结尾内容里的值返回。\nNginx 系统变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述$time_local以本地时间标准输出的当前时间。$time_iso8601使用 ISO 8601 标准输出的当前时间。$nginx_version当前运行的 Nginx 版本号。$pid所属 worker 进程的 id。$pipe如果使用了管道则返回 p否则返回 .。$hostname所在服务器的主机名与 hostname 命令输出一致。$msec从 1970 年 1 月 1 日到现在的时间,单位为秒,小数点后精确到毫秒。\nNginx 的配置文件使用的是一门微型的编程语言,其中变量存放的是字符串类型的值。使用 $ 符号来表示变量,并且在引用时需要带上 $ 前缀。特殊情况下,如变量名紧跟字符时,使用特殊语法来消除歧义。如果需要输出 $ 符号本身,则可以使用特定方法,如上述 geo $dollar 示例所示。\n模块化配置\n在 Nginx 配置中include 指令允许您包含其他配置文件或片段,实现配置的模块化和简化管理。以下是如何有效使用 include 指令的步骤和示例:\n\n\n定义共享配置文件首先创建一个新的配置文件来存储可重复使用的配置片段。例如您可以创建 /etc/nginx/shared_config.conf 并在其中定义通用的 server 块、location 块或其他配置指令。\n示例 shared_config.conf 内容:\nserver {\n listen 80;\n server_name example.com;\n location / {\n root /var/www/html;\n index index.html;\n }\n}\n\n\n在主配置文件中包含共享配置在您的主 Nginx 配置文件(通常是 /etc/nginx/nginx.conf使用 include 指令引入共享配置文件。这可以在 http 块或 server 块内进行,取决于您的具体需求。\n在 http 块内包含共享配置:\nhttp {\n include /etc/nginx/shared_config.conf;\n # 其他 http 块配置...\n}\n或者在 server 块内包含共享配置:\nserver {\n # 其他 server 块配置...\n include /etc/nginx/shared_config.conf;\n}\n\n\n重新加载或重启 Nginx为了使新的配置生效您需要重新加载或重启 Nginx。通常可以使用以下命令来重新加载配置\nsudo nginx -s reload\n\n\n通过使用 include 指令,您可以将常用配置抽象成独立的文件,简化主配置文件的复杂度,并提高配置的可维护性。此方法尤其适用于需要在多个虚拟主机或环境之间共享配置的场景。\n完整示例\nuser nginx; # 定义Nginx运行的用户\nworker_processes auto; # 工作进程数建议设置为CPU核心数auto表示自动检测\nerror_log /var/log/nginx/error.log warn; # 错误日志文件的位置和记录级别\npid /var/run/nginx.pid; # 存储Nginx主进程ID的文件位置\n \nevents {\n worker_connections 1024; # 单个工作进程的最大连接数\n multi_accept on; # 设置为on表示一个工作进程可以同时接受多个新连接\n use epoll; # 使用epoll事件模型这是在Linux上的一种高效的事件处理机制\n}\n \nhttp {\n include mime.types; # 包含MIME类型设置\n default_type application/octet-stream;\n \n # 日志格式定义,包括自定义变量\n log_format main '$remote_addr - $remote_user [$time_local] "$request" '\n '$status $body_bytes_sent "$http_referer" '\n '"$http_user_agent" "$http_x_forwarded_for"';\n \n # 应用自定义日志格式\n access_log /var/log/nginx/access.log main;\n \n # 文件传输优化\n sendfile on; # 开启高效文件传输模式\n tcp_nopush on; # 开启防止网络拥塞的优化\n tcp_nodelay on; # 开启不延迟发送数据的优化\n \n # 保持长连接的超时时间\n keepalive_timeout 65;\n \n # SSL 配置\n ssl_certificate /path/to/cert.pem;\n ssl_certificate_key /path/to/cert.key;\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_ciphers HIGH:!aNULL:!MD5;\n \n # 服务器定义\n server {\n listen 80; # 监听IPv4端口\n listen [::]:80; # 监听IPv6端口\n \n server_name localhost; # 服务器名称\n \n # 根目录和索引文件设置\n location / {\n root /usr/share/nginx/html; # 网站根目录\n index index.html index.htm; # 默认页面\n }\n \n # 负载均衡配置\n location /load_balanced_app {\n proxy_pass http://my_load_balancer; # 反向代理到负载均衡器\n }\n \n # SSL 服务端配置\n listen 443 ssl;\n ssl_certificate /path/to/ssl/cert.pem;\n ssl_certificate_key /path/to/ssl/key.pem;\n }\n \n # 负载均衡器定义\n upstream my_load_balancer {\n server backend1.example.com;\n server backend2.example.com;\n server backend3.example.com;\n }\n}\n \nstream {\n # TCP/UDP流设置示例\n server {\n listen 12345;\n proxy_pass backend.example.com:12345;\n }\n \n # IPv6 TCP/UDP 代理\n server {\n listen [::]:12345;\n proxy_pass backend.example.com:12345;\n }\n}\n \nmail {\n # 邮件服务设置(示例)\n server_name mail.example.com;\n auth_http localhost/auth_http;\n}"},"Technology/ComputerNetwork/Nginx/概述":{"title":"Nginx 概述","links":[],"tags":["Nginx/概述","技术/计算机网络"],"content":"概述\nNginx发音为“Engine-X”是一款开源的高性能 HTTP 和反向代理服务器,同时也充当了 IMAP/POP3 代理服务器的角色。Nginx 的诞生旨在解决 C10k 问题,即同时处理 10,000 个客户端连接的挑战。由俄罗斯的程序员 Igor Sysoev 于 2004 年首次发布自那时起Nginx 凭借其卓越的稳定性、丰富的功能集、简单的配置文件和卓越的性能,迅速赢得了广泛的用户赞誉。\n**Nginx 的设计理念着重于高效利用资源,采用异步、事件驱动的体系架构来处理大量并发连接。**与传统的同步、多线程或多进程服务器模型不同Nginx 的非阻塞方式使其在高并发环境中表现出色,尤其在服务静态内容、执行负载均衡和处理反向代理请求等方面表现突出。\nNginx 的发展历程可以追溯到 2002 年,于 2004 年 10 月 4 日首次发布版本 0.1.0。从 2005 年开始Nginx 不断发展壮大,支持了 Windows 系统,逐渐趋于稳定。重要的里程碑包括 2011 年发布的 1.0 版本,它引入了上游 keepalive HTTP 长链接。此后Nginx 还支持了诸如 websocket、TFO 等协议,提供了 thread pool 和 stream 四层反向代理等功能,同时也支持了 reuseport 特性和 HTTP2 协议。在 2016 年Nginx 还引入了动态模块的支持,而在 2018 年则加入了对 TLSv1.3 的支持。\nNginx 长久以其开源、高性能、高可靠性以及支持热部署而闻名。它几乎可以实现 7x24 小时不间断运行即使运行数月也不需要重新启动。此外Nginx 还支持动态模块,使得功能扩展变得更加灵活。总之 Nginx 是一款性能卓越、资源消耗低廉的 Web 服务器,而且易于配置和使用。\n主要特性\n高并发处理\n\n事件驱动架构Nginx 采用非阻塞、事件驱动的方式处理请求,允许单个工作进程处理数千个并发连接,这使得 Nginx 在高并发环境下表现出色。\n\n反向代理与负载均衡\n\n反向代理支持Nginx 可以作为反向代理服务器将请求转发到后端服务器支持负载均衡、缓存静态和动态内容、SSL 终端等功能。\n负载均衡算法提供多种负载均衡方法包括轮询、权重、IP 哈希等。\n\n高度可配置\n\n灵活的配置语法Nginx 的配置文件清晰、灵活,可以精细地控制到每个请求的处理方式,易于理解和修改。\n模块化设计提供丰富的模块如 HTTP、mail、stream 等,并支持第三方模块扩展,使功能高度可定制。\n\n性能优化\n\n高效的静态内容服务对于静态资源Nginx 可以直接从内核缓存中提供文件,减少磁盘 IO 操作。\n缓存机制Nginx 提供强大的缓存功能,可以缓存来自后端服务器的内容,减少重复请求的处理时间。\n\n安全特性\n\nSSL/TLS 支持:可以为 HTTP 服务提供 SSL/TLS 加密,保护数据传输安全。\n限制与认证支持基于 IP、密码的访问控制以及限制请求频率等安全功能。\n\n高度可扩展\n\n第三方模块Nginx 支持第三方模块的扩展,允许添加自定义功能和特性,以满足特定需求。\n动态模块加载可以在运行时动态加载和卸载模块无需重新编译 Nginx提高了灵活性和可扩展性。\n\n日志与监控\n\n丰富的日志记录Nginx 可以记录详细的访问日志,包括客户端信息、请求时间、响应代码等,有助于分析和监控。\n实时性能监控支持实时性能监控工具如 stub_status 模块,可以查看当前服务器状态和性能指标,帮助及时发现问题。\n\n热部署与高可用\n\n热部署支持Nginx 允许在不中断现有连接的情况下重新加载配置文件或更新软件版本,确保连续性。\n高可用性架构通过配置主备服务器或使用专业的高可用方案可以实现 Nginx 的高可用性,防止单点故障。\n\n基本概念\n如果要理解 Nginx首先需要掌握**它采用的是多进程(单线程)+ 多路 IO 复用模型。**这一特性使得 Nginx 成为一个并发事件驱动的服务器。\n工作模式\n**Nginx 使用单一的主进程master process和多个工作进程worker processes来处理连接。**这种多进程模型有效地分担了负载,并充分利用了多核服务器的性能。\n**Nginx 启动成功后,在 Linux 系统中存在两个进程:一个主进程和多个工作进程。**主进程负责管理工作进程,包括接收外部信号、向工作进程发送信号以及监控工作进程的运行状态。如果工作进程异常退出,主进程会自动重新启动新的工作进程,确保持续的服务。\n主进程\n主进程master process是 Nginx 的核心管理组件之一。它的主要职责是协调、监控和管理多个工作进程worker processes以确保 Nginx 服务器的正常运行。以下是主进程的关键功能和特点:\n\n进程管理主进程负责启动、停止和管理工作进程。它会在服务器启动时创建工作进程并在需要时重新启动它们以应对异常情况或配置更改。\n接收外部信号主进程监听外部信号这些信号可以是管理员通过命令行发送的用于控制 Nginx 的行为。例如nginx -s reload 命令会发送 SIGHUP 信号,通知主进程重新加载配置文件,而不中断现有连接。\n工作进程监控主进程会监控工作进程的运行状态。如果某个工作进程异常退出主进程会感知到并启动新的工作进程来替代它以确保服务的连续性。\n配置文件加载主进程负责最初加载和解析配置文件。它会读取配置文件中的配置项并将其传递给工作进程以确保所有进程都使用相同的配置信息。\n核心功能不处理请求与工作进程不同主进程不处理客户端请求它主要负责协调和管理工作进程的活动。因此主进程通常只有一个线程不会阻塞在处理请求上。\n单一进程通常情况下每个 Nginx 实例只有一个主进程。这个主进程是整个服务器的控制中心,确保工作进程的协同工作,同时也负责与管理员进行通信。\n\n工作进程\n工作进程worker process是 Nginx 中的关键组件之一,它的主要任务是处理客户端请求并与后端服务进行通信。以下是工作进程的关键功能和特点:\n\n并发请求处理每个工作进程独立处理客户端的请求。Nginx 的多进程模型允许多个工作进程同时运行,每个进程都可以处理数千个并发连接,从而实现高并发性能。\n事件驱动模型工作进程使用事件驱动模型来处理请求。它们不会阻塞在等待一个连接的输入或输出上而是能够同时处理多个连接的事件包括接收请求、发送响应、读取数据和写入数据等。\n请求分发主进程将客户端的请求分发给工作进程。工作进程之间通过竞争的方式来处理任务获得任务的工作进程会将请求传递给后端的服务例如 Tomcat、Node.js 或其他应用程序,用于请求转发、反向代理、访问数据库等任务。\n热部署Nginx 支持热部署,这意味着可以在不中断现有连接的情况下重新加载配置文件或更新软件版本。工作进程可以在不停机的情况下被重新启动,从而保持服务的连续性。\n独立运行每个工作进程都是独立的进程它们不共享内存空间。这意味着如果其中一个工作进程出现问题不会影响其他工作进程的运行从而提高了服务器的稳定性。\n节省资源工作进程的数量通常设置为服务器的 CPU 核数,以充分利用系统资源。由于每个工作进程只有一个主线程,它们可以将一个 CPU 的性能发挥到极致,同时减少了不必要的上下文切换。\n\n交互图\nsequenceDiagram\n participant Client as 客户端\n participant Master as 主进程\n participant Worker1 as 工作进程1\n participant Worker2 as 工作进程2\n\n Client->>Master: 发起连接请求\n Note right of Master: 主进程选择工作进程处理请求\n Master->>Worker1: 指派连接到工作进程1\n Worker1->>Client: 确立连接并处理请求\n Client->>Master: 发起另一连接请求\n Master->>Worker2: 指派连接到工作进程2\n Worker2->>Client: 确立连接并处理请求\n\n事件驱动模型\nNginx 的事件驱动模型是其高性能和高并发处理的关键。这个模型使得 Nginx 能够同时处理大量的并发连接,并且在高负载下表现出色。以下是事件驱动模型的关键特点和原理:\n\n非阻塞操作在事件驱动模型中工作进程不会阻塞在等待连接的输入或输出操作上。这意味着工作进程可以同时处理多个连接并在等待某个连接的数据时继续处理其他连接的事件而不会停顿等待。\n异步处理处理请求的各个阶段如接收请求、处理请求、发送响应可以异步进行。这使得工作进程能够高效地在不同的请求之间切换而不必等待前一个请求完全处理完毕。\n事件监听工作进程不断监听事件这些事件包括新的连接请求、已连接套接字上有数据可读、已连接套接字上有数据可写等。当这些事件发生时工作进程会非阻塞地响应并执行相应的处理操作。\n多路复用技术Nginx 使用多路复用技术(如 epoll、kqueue、select 等,具体取决于操作系统)来有效地管理和处理大量的连接。这些技术允许 Nginx 一次性监听多个事件,而不是为每个连接创建一个线程或进程,从而减少了资源开销。\n事件驱动循环工作进程在事件驱动循环中等待事件的发生一旦事件发生它们会调用相应的处理函数来处理事件。这种循环机制允许 Nginx 高效地响应各种类型的事件,包括新连接的到达、请求的到达、响应的发送等。\n\nsequenceDiagram\n participant Worker as 工作进程\n participant EventQueue as 事件队列\n participant Connection as 连接\n participant Request as 请求\n\n Worker->>EventQueue: 监听事件\n Note right of EventQueue: 事件包括新连接、<br/>数据接收、超时等\n EventQueue->>Worker: 传递新连接事件\n Worker->>Connection: 确立新连接\n Connection->>Worker: 发送数据\n Worker->>EventQueue: 监听更多事件\n EventQueue->>Worker: 传递数据接收事件\n Worker->>Request: 处理请求\n Request->>Worker: 发送响应\n Worker->>Connection: 返回数据给客户端\n\n Note left of Connection: 连接建立后<br/>通过套接字交换数据\n Note left of Request: 请求处理包括<br/>解析、处理、响应生成\n\n模块化管理\nNginx 的模块化管理机制是其设计的关键特点之一,它允许将功能按模块化的方式组织和扩展,使得 Nginx 可以轻松地适应不同的需求和场景。以下是模块化管理机制的关键特点和作用:\n\n内部结构Nginx 的内部结构由核心部分和一系列功能模块组成。这种划分使每个模块的功能相对简单,便于开发和维护。核心部分提供了基本的服务器功能,而功能模块则提供了特定的功能,如 HTTP、mail、stream 等。\n模块独立性Nginx 的模块是相互独立的,它们之间低耦合高内聚。这意味着每个模块可以独立开发、测试和维护,而不会影响其他模块的正常运行。这种设计使得 Nginx 的扩展和定制变得更加灵活和可控。\n模块的丰富性Nginx 提供了丰富的标准模块,涵盖了各种常见的服务器功能,包括 HTTP、mail、stream、负载均衡、缓存、访问控制、压缩等。这些标准模块可以根据需要动态启用或禁用以构建具有特定功能的 Nginx 实例。\n第三方模块除了标准模块Nginx 还支持第三方模块的扩展。这些第三方模块由社区或第三方开发者提供可以用于实现各种定制化的功能和需求。通过第三方模块Nginx 可以在不改变核心代码的情况下实现额外的功能。\n配置管理Nginx 的配置文件采用了模块化的设计,每个模块可以定义自己的配置块和指令。这使得配置文件清晰、灵活,可以精细地控制每个请求的处理方式。管理员可以根据需要启用或禁用特定模块,并根据业务需求进行配置。\n\n系统模块\n\n核心模块nginx 最基本最核心的服务,如进程管理、权限控制、日志记录;\n标准 HTTP 模块Nginx 服务器的标准 HTTP 功能;\n可选 HTTP 模块:处理特殊的 HTTP 请求;\n邮件服务模块邮件服务\n第三方模块作为扩展完成特殊功能\n\n核心模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块作用ngx_core提供核心服务包括进程管理、权限控制、日志记录等ngx_errlog记录错误日志ngx_conf处理配置文件ngx_events处理事件循环ngx_http支持 HTTP 服务ngx_mail支持邮件服务ngx_stream支持流媒体服务ngx_regex支持正则表达式\n标准 HTTP 模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块作用ngx_http_core配置端口、URI 分析服务器响应错误处理等ngx_http_log自定义 access 日志ngx_http_upstream负载均衡和代理ngx_http_status提供服务器状态信息ngx_http_autoindex自动生成目录列表ngx_http_index处理请求的默认页面ngx_http_auth_basic基于 HTTP 的身份认证ngx_http_access基于 IP 地址的访问控制ngx_http_limit_conn限制连接速率ngx_http_geo根据客户端 IP 创建变量ngx_http_map创建键值对变量ngx_http_rewrite重定向请求ngx_http_proxy支持 HTTP 代理ngx_http_fastcgi支持 FastCGIngx_http_uwsgi支持 uWSGIngx_http_memcached支持 Memcachedngx_http_empty_gif生成 1x1 的透明 GIF 图片ngx_http_browser解析 User-Agent 头部信息ngx_http_charset指定网页编码ngx_http_headers_filter设置 HTTP 响应头ngx_http_upstream_ip_hash使用 IP 哈希进行负载均衡ngx_http_upstream_least_conn使用最少连接数进行负载均衡ngx_http_upstream_keepalive保持连接的模块ngx_http_write_filter写过滤器ngx_http_header_filter头部过滤器ngx_http_chunked_filter分块过滤器ngx_http_range_header处理范围请求ngx_http_gzip_filterGzip 压缩过滤器ngx_http_postpone_filter延迟响应过滤器ngx_http_ssi_filterSSI 过滤器ngx_http_charset_filter字符集过滤器ngx_http_userid_filter用户 ID 过滤器ngx_http_copy_filter复制过滤器ngx_http_range_body_filter范围请求体过滤器ngx_http_not_modified_filter未修改响应过滤器\n可选 HTTP 模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块作用ngx_http_addition在响应页面开始或结尾添加文本信息ngx_http_degradation在低内存情况下处理请求并返回适当的错误码ngx_http_perl支持 Perl 脚本处理 HTTP 请求ngx_http_flv支持 Flash 多媒体信息按流传输ngx_http_geoip解析客户端请求的地理位置信息ngx_http_perftools性能工具支持用于性能分析ngx_http_gzip响应内容压缩ngx_http_gzip_static使用预压缩的文件代替一般文件响应客户端请求ngx_http_image_filter处理图片尺寸和旋转方向的模块ngx_http_mp4处理多媒体信息按流传输通常与 ngx_http_flv 一起使用ngx_http_random_index随机选择目录下的文件作为索引页ngx_http_secure_link支持请求链接的有效性检查ngx_http_ssl支持 HTTPSngx_http_stub_status提供服务器状态监控信息ngx_http_sub_module替换响应中的文本信息ngx_http_dav支持 HTTP 和 WebDAV 协议中的文件操作ngx_http_xslt使用 XSLT 转换 XML 响应信息\n代理模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块名称用途ngx_stream_core_module处理 TCP/UDP 服务的核心功能ngx_stream_ssl_module支持 SSL/TLS 加密通信ngx_stream_proxy_module支持 TCP/UDP 代理功能ngx_stream_upstream_module定义一组服务器用于 TCP/UDP 负载均衡和代理ngx_stream_limit_conn_module限制来自客户端的连接速率ngx_stream_geo_module根据客户端 IP 地址创建变量ngx_stream_map_module创建键值对变量ngx_stream_split_clients_module分流请求到不同的后端服务器ngx_stream_return_module用于修改响应的状态码和内容ngx_stream_upstream_ip_hash_module使用 IP 哈希进行负载均衡ngx_stream_upstream_least_conn_module使用最少连接进行负载均衡ngx_stream_upstream_keepalive_module保持与后端服务器的长连接ngx_stream_access_module基于 IP 地址的访问控制ngx_stream_realip_module修改客户端 IP 地址的配置ngx_stream_block_module阻塞指定 IP 地址范围的连接ngx_stream_hash_module使用哈希分配请求到后端服务器ngx_stream_limit_req_module限制请求的速率和并发连接数ngx_stream_log_module自定义日志记录ngx_stream_lua_module支持使用 Lua 脚本处理 TCP/UDP 请求\n邮件服务\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块作用ngx_mail_core处理邮件服务的核心功能ngx_mail_pop3支持 POP3 协议的邮件服务ngx_mail_imap支持 IMAP 协议的邮件服务ngx_mail_smtp支持 SMTP 协议的邮件服务ngx_mail_auth_http通过 HTTP 进行邮件服务的认证ngx_mail_proxy支持邮件服务的代理功能ngx_mail_ssl支持邮件服务的 SSL 加密\n第三方模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块作用echo-nginx-module支持在 Nginx 配置文件中执行 Shell 命令memc-nginx-module支持 memcached 缓存rds-json-nginx-module支持处理 JSON 数据lua-nginx-module支持 Lua 脚本处理请求\n发行版本\nNginx 的不同发行版本满足了各种用户需求,从稳定性到高级功能,以下是各个版本的特点和获取方式:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n版本特点获取方式Nginx Mainline包含最新功能和改进但不够稳定单数版本nginx.orgNginx Stable经过严格测试稳定可靠双数版本nginx.orgNginx Open Source免费、开源适合基本需求nginx.orgNginx Plus商业版提供高级功能和支持需要订阅详细信息可在 nginx.com 获取OpenResty基于 Nginx 的增强版本,使用 Lua 语言进行开发开源版,商业版\n产品对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性/性能ApacheNginx架构多进程/多线程模型事件驱动模型并发处理预先生成线程/进程处理请求,适合低至中等并发单线程处理多个请求,高并发性能优异性能动态内容处理优秀,静态内容相对较慢静态内容处理极快,动态内容需要与其他应用配合内存与 CPU 效率较高的内存和 CPU 消耗更低的内存和 CPU 消耗配置.htaccess 文件提供灵活的目录级配置集中式配置,更易于维护但初学者可能觉得复杂模块丰富的模块,灵活性高丰富的模块,但安装和配置较为复杂负载均衡模块较少,通常需要额外软件支持内置支持,且配置简单强大文件描述符每个连接一个文件描述符一个工作进程处理多个连接,减少文件描述符消耗安全稳健的模块和社区支持,但配置不当可能有风险较低的历史漏洞记录,配置较为安全可靠性长期稳定,广泛应用高并发下更稳定,但相对较新社区与文档庞大的社区,丰富的文档资源社区活跃,文档日渐完善适用场景适合动态重的应用,需要灵活的配置静态内容、高并发和反向代理优势显著\n使用场景\n以下是 Nginx 主流使用场景和优势:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n使用场景描述优势静态内容的 Web 服务器直接向用户提供静态资源如图片、HTML、CSS 和 JavaScript 文件。高效处理静态内容:快速响应,支持高并发连接。反向代理与负载均衡将用户的请求代理到内部的一个或多个服务器,并将结果返回给用户。提高可扩展性和可用性:实现请求的分发和负载均衡。动态内容的缓存缓存后端服务器的动态内容,如通过 FastCGI 为 PHP 应用提供的内容。减少后端负载:提高响应速度和整体性能。前端性能优化通过压缩、缓存优化等手段改善前端资源的加载速度。改善用户体验:提高页面加载速度。安全网关提供 SSL/TLS 加密实现安全的数据传输。确保传输安全防止中间人攻击等安全威胁。API 网关管理和控制对后端服务的 API 调用。统一 API 管理:支持请求路由、身份验证、限流等功能。"},"Technology/ComputerNetwork/Nginx/负载均衡":{"title":"负载均衡","links":[],"tags":["Nginx/负载均衡","技术/计算机网络"],"content":"基础理论\n负载均衡是什么\n\n负载均衡是现代高可用、高性能网站架构的核心组件。\n\n负载均衡Server Load Balancer简称 SLB是一种网络负载均衡服务它在多个服务器通常称为后端服务器之间分配网络或应用程序流量。这样做的目的是优化资源使用最大化吞吐量最小化响应时间并确保高可用性。\ngraph TD;\n subgraph Client\n A[客户端] --> B[负载均衡器]\n end\n subgraph LoadBalancer\n B --> C[服务器1]\n B --> D[服务器2]\n B --> E[服务器3]\n end\n\n负载均衡的重要性\n\n可靠性如果一个服务器失败负载均衡器可以将流量重定向到健康的服务器确保服务的持续性。\n可扩展性随着需求的增加可以轻松地添加更多的服务器来处理增加的流量。\n性能通过分配请求确保没有单个服务器承受过多的负载。\n灵活性负载均衡器可以动态地添加或删除服务器以应对不同的负载需求。\n\n负载均衡的方法\n\n\n轮询Round Robin每个请求按顺序轮流分配到不同的服务器。这种方法简单且易于实现适用于服务器性能大致相同的场景。\nsequenceDiagram\n participant Client\n participant LoadBalancer\n participant Server1\n participant Server2\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server1: 将请求转发给Server1\n Server1->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server1的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server2: 将请求转发给Server2\n Server2->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server2的响应返回给Client\n\n Note right of LoadBalancer: 下一轮请求会轮询到Server1\n\n\n\n\n最少连接Least Connections新的请求会被发送到连接数最少的服务器。这种方法适用于处理长时间运行的连接或会话。\nsequenceDiagram\n participant Client\n participant LoadBalancer\n participant Server1\n participant Server2\n participant Server3\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server1: 将请求转发给Server1\n Server1->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server1的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server2: 将请求转发给Server2\n Server2->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server2的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server3: 将请求转发给Server3\n Server3->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server3的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server1: 将请求转发给Server1因为Server1连接数最少\n Server1->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server1的响应返回给Client\n\n Note right of LoadBalancer: 使用最小连接数策略\n\n\n\n哈希Hash根据请求的参数如客户端 IP 地址、URL、Cookie 等Hash 决定将请求发送到哪个服务器,确保来自同一客户端的请求总是被发送到同一服务器。这种方法有助于实现会话持久性,适用于需要维持用户状态的应用。\nsequenceDiagram\n participant Client\n participant LoadBalancer\n participant Server1\n participant Server2\n participant Server3\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server1: 根据客户端IP哈希值选择Server1\n Server1->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server1的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server2: 根据客户端IP哈希值选择Server2\n Server2->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server2的响应返回给Client\n\n Client->>LoadBalancer: 发送请求\n LoadBalancer->>Server3: 根据客户端IP哈希值选择Server3\n Server3->>LoadBalancer: 处理请求并响应\n LoadBalancer->>Client: 将Server3的响应返回给Client\n\n Note right of LoadBalancer: 使用IP哈希策略\n\n\n\n\nNginx 负载均衡\nNginx 是一个轻量级的 Web 服务器/反向代理服务器及电子邮件IMAP/POP3代理服务器并在一个 BSD-like 协议下发行。由于其高性能、稳定性、丰富的功能集、简单的配置以及低资源消耗Nginx 在全球范围内被广泛使用,包括知名的大型网站和服务。\n**在 Nginx 中负载均衡通常可以分为两大类七层HTTP 负载均衡和四层TCP/UDP负载均衡。**每种类型都有其特定的用途和配置方法。\n七层HTTP )负载均衡\n七层负载均衡操作于应用层直接处理消息内容。它主要处理基于 TCP 的流量,如 HTTP。通过分析消息内容例如 URL 或 cookie进行更精细的路由决策。Nginx 提供了以下关键特性:\n\n灵活的负载均衡算法包括轮询、最少连接和 IP 哈希等。\n健康检查周期性地检查后端服务器的健康状态确保流量仅被路由到健康的服务器。Nginx Plus 版本提供更高级的健康检查功能,包括被动和主动健康检查。\nSSL 终止:在负载均衡器层面处理 SSL 连接,有效减轻后端服务器的加密和解密负担。\n会话持久性通过特定的策略如 cookie 或 IP 哈希)保持用户会话与同一后端服务器的连接。\n动态内容处理能够根据请求路径URI或请求头等条件将流量智能地路由到不同的应用或服务。\n高级缓存功能提供高效的缓存机制减少后端服务器的压力并加快内容的响应速度。\n\n配置示例\nhttp {\n upstream myapp {\n server backend1.example.com;\n server backend2.example.com;\n server backend3.example.com;\n }\n \n server {\n listen 80;\n \n location / {\n proxy_pass http://myapp;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n }\n }\n}\n在这个配置中所有到达端口 80 的 HTTP 请求都会被转发到 myapp 这个上游服务器组Nginx 将会轮询 backend1、backend2、和 backend3 服务器。\n四层TCP/UDP负载均衡\nNginx 在作为四层负载均衡器时,处理非 HTTP 流量,如数据库连接、邮件服务或其他自定义 TCP/UDP 协议。这一功能自 Nginx 1.9.0 版本起被引入,后续版本中增加了对 UDP 的支持。\n四层负载均衡器在 OSI 网络模型的传输层上操作,直接处理网络数据包。不同于应用层的七层负载均衡,四层负载均衡通过转发 TCP/UDP 流量,提供高效率和高可用性的服务。\n\n通用性支持所有基于 TCP 或 UDP 的协议。\n流量透传直接传递 TCP/UDP 流量,保持数据的原始状态。\n简单的健康检查通过检查 TCP 端口是否能接受连接来判断后端服务的健康状态。\nSSL/TLS 穿透:实现 SSL/TLS 穿透,即直接将加密的流量转发给后端的 SSL/TLS 终点。\n高效率因为不需要处理复杂的应用层内容所以转发效率高于七层负载均衡。\n\n配置示例\nstream {\n upstream myapp_tcp {\n server backend1.example.com:1234;\n server backend2.example.com:1234;\n }\n \n server {\n listen 1234;\n\t\t\n proxy_pass myapp_tcp;\n }\n}\n内置策略\n轮询\n默认策略按时间顺序逐一分配到不同的后端服务器如果后端服务挂了能自动剔除。\nupstream backend {\n server 127.0.0.1:3000;\n server 127.0.0.1:3001;\n}\n加权轮询\n与轮询相似但可以指定权重weight 值越大,分配到的访问几率越高。\nupstream backend {\n server 127.0.0.1:3000 weight=2;\n server 127.0.0.1:3001 weight=1;\n}\n关键值 Hash\n自定义 key如 IP 地址、请求头、cookie 等)作为 hash 的依据,决定请求应该转发到哪个服务器。\nupstream backend {\n hash $remote_addr; # 使用客户端IP地址作为hash键值\n server 127.0.0.1:3000;\n server 127.0.0.1:3001;\n}\nip_hash\n每个请求按访问 IP 的 hash 结果分配,可以解决动态网页 session 共享问题。\nupstream backend {\n ip_hash;\n server 127.0.0.1:3000;\n server 127.0.0.1:3001;\n}\nleast_conn\n最少连接数策略那个机器连接数少就分配到那个机器适用于处理长时间运行的连接。\nupstream backend {\n least_conn;\n server 127.0.0.1:3000;\n server 127.0.0.1:3001;\n}\n配置选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项描述语句示例backup标记服务器为备份服务器仅在主服务器不可用时使用upstream backend { server server1; server server2 backup; }down标记服务器为永久离线状态upstream backend { server server1 down; server server2; }max_fails允许请求失败的次数默认为 1upstream backend { server server1 max_fails=3 fail_timeout=30s; }fail_timeout经过 max_fails 失败后,服务暂停的时间同上,通常与 max_fails 一起配置weight设置服务器的权重默认为 1upstream backend { server server1 weight=2; server server2; }max_conns限制最大的接收的连接数upstream backend { server server1 max_conns=100; }\n常见示例\n# 基本的加权和备份服务器配置\nupstream backend {\n server 127.0.0.1:3000 weight=3;\n server 127.0.0.1:3001 weight=2;\n server 127.0.0.1:3002 backup; # 备份服务器\n}\n \n# 组合健康检查和备份\n# 当它们连续失败超过max_fails次后在fail_timeout时间内被认为是不可用的。\nupstream backend {\n server 127.0.0.1:3000 max_fails=2 fail_timeout=30s;\n server 127.0.0.1:3001 max_fails=2 fail_timeout=30s;\n server 127.0.0.1:3002 backup; # 备份服务器\n}\n \n# 使用权重、连接数限制和离线状态\nupstream backend {\n server 127.0.0.1:3000 weight=3 max_conns=100;\n server 127.0.0.1:3001 weight=2 max_conns=150;\n server 127.0.0.1:3002 down; # 暂时离线的服务器\n}\n \n# 综合使用所有配置\nupstream backend {\n server 127.0.0.1:3000 weight=3 max_fails=2 fail_timeout=30s max_conns=100;\n server 127.0.0.1:3001 weight=2 max_fails=2 fail_timeout=30s max_conns=150;\n server 127.0.0.1:3002 backup; # 备份服务器\n}"},"Technology/ComputerNetwork/公共服务/IPv4-DNS-服务":{"title":"IPv4 DNS 服务","links":[],"tags":["技术/计算机网络","公共服务/DNS"],"content":"中国公共 DNS 服务器\n114 DNS\n\n114 DNS: 114.114.114.114, 114.114.115.115\n114 DNS 安全版: 114.114.114.119, 114.114.115.119\n114 DNS 家庭版: 114.114.114.110, 114.114.115.110\n\n阿里 DNS\n\n阿里 DNS: 223.5.5.5, 223.6.6.6\n\nDoH: https://223.5.5.5/dns-query, https://223.6.6.6/dns-query, dns.alidns.com/dns-query\nDoT: dns.alidns.com\n\n\n\n华为 DNS\n\n华为 DNS: 122.112.208.1, 139.9.23.90, 114.115.192.11, 116.205.5.1, 116.205.5.30, 122.112.208.175, 139.159.208.206\n\n百度 DNS\n\n百度 BaiduDNS: 180.76.76.76\n\n腾讯 DNS\n\n腾讯 DNS: 119.29.29.29, 182.254.116.116, 119.28.28.28, 182.254.118.118\n\nDoH: doh.pub/dns-query, https://1.12.12.12/dns-query, https://120.53.53.53/dns-query\nDoH (国密): sm2.doh.pub/dns-query\nDoT: dot.pub, 1.12.12.12, 120.53.53.53\n\n\n\n360 DNS\n\n360 DNS:\n\nDoH: doh.360.cn/dns-query\nDoT: dot.360.cn\n\n\n\n字节跳动 DNS\n\n火山引擎 DNS: 180.184.1.1, 180.184.2.2\n\nCNNIC SDNS\n\nCNNIC SDNS: 1.2.4.8, 210.2.4.8\n\nOneDNS\n\nOneDNS 拦截版: 117.50.11.11, 52.80.66.66\nOneDNS 纯净版: 117.50.10.10, 52.80.52.52\nOneDNS 家庭版: 117.50.60.30, 52.80.60.30\n\nDoH (拦截版): doh.onedns.net/dns-query\nDoH (纯净版): doh-pure.onedns.net/dns-query\nDoT (拦截版): dot.onedns.net\nDoT (纯净版): dot-pure.onedns.net\n\n\n\nDNS 派\n\nDNS PAI 电信/移动/铁通: 101.226.4.6, 218.30.118.6\nDNS PAI 联通: 123.125.81.6, 140.207.198.6\n\n港澳台公共 DNS 服务器\n台湾 Quad 101\n\n台湾 Quad 101: 101.101.101.101, 101.102.103.104\n\nDoH: dns.twnic.tw/dns-query\n\n\n\n香港宽频 DNS\n\n香港宽频 DNS: 203.80.96.10, 203.80.96.9\n\n香港网上行宽频 DNS\n\n香港网上行宽频 DNS: 218.102.23.228, 203.198.7.66\n\n香港有线宽频 i-Cable DNS\n\n香港有线宽频 i-Cable DNS: 61.10.0.130, 61.10.1.130\n\n和记环球电讯 DNS\n\n和记环球电讯 DNS: 202.181.240.44, 210.0.255.251\n\n香港 HKNet 宽频 DNS\n\n香港 HKNet 宽频 DNS: 202.67.240.222\n\n香港 PCCW DNS\n\n香港 PCCW DNS: 202.153.97.2, 202.153.97.130\n\n香港 Pacific DNS\n\n香港 Pacific DNS: 202.14.67.4, 202.14.67.14\n\n香港 CPCNet DNS\n\n香港 CPCNet DNS: 202.76.4.1, 202.76.4.2\n\n香港 KDDI DNS\n\n香港 KDDI DNS: 202.177.2.2, 202.177.2.3\n\n香港 iAdvantage DNS\n\n香港 iAdvantage DNS: 202.85.128.32, 202.85.128.33, 203.194.239.32, 202.85.170.89\n\n台湾中华电信\n\n台湾中华电信: 168.95.192.1, 168.95.1.1\n\n西门子服务器香港\n\n西门子服务器香港: 112.121.178.187\n\n世界公共 DNS 服务器\nGoogle DNS\n\nGoogle DNS: 8.8.8.8, 8.8.4.4\n\nDoH: dns.google/dns-query\nDoT: dns.google\n\n\n\nIBM Quad9\n\nIBM Quad9: 9.9.9.9, 149.112.112.112\n\nDoH (默认): dns.quad9.net/dns-query\nDoH (安全&支持 ECS): dns11.quad9.net/dns-query\n\n\n\nOpenDNS\n\nOpenDNS: 208.67.222.222, 208.67.220.220\n\nDoH (默认): doh.opendns.com/dns-query\nDoH (家庭保护): doh.familyshield.opendns.com/dns-query\n\n\n\nLevel3 DNS\n\nLevel3 DNS: 4.2.2.1, 4.2.2.2\n\n韩国 KT DNS\n\n韩国 KT DNS: 168.126.63.1, 168.126.63.2\n\nCloudflare DNS\n\nCloudflare DNS: 1.1.1.1, 1.0.0.1\n\nDoH: https://1.1.1.1/dns-query, https://1.0.0.1/dns-query, cloudflare-dns.com/dns-query\nDoT: one.one.one.one, 1dot1dot1dot1.cloudflare-dns.com\n\n\n\nFree DNS\n\nFree DNS: 37.235.1.174, 37.235.1.177\n\nDynDNS\n\nDynDNS: 216.146.35.35, 216.146.36.36\n\nComodo DNS\n\nComodo DNS: 8.26.56.26, 8.20.247.20\n\nVerisign DNS\n\nVerisign DNS: 64.6.64.6, 64.6.65.6\n\nYandex DNS\n\nYandex DNS: 77.88.8.8, 77.88.8.1\n\nFreenom DNS荷兰\n\nFreenom DNS荷兰: 80.80.80.80, 80.80.81.81\n\nAdGuard DNS\n\nAdGuard DNS默认: 94.140.14.14, 94.140.15.15\nAdGuard DNS家庭保护: 94.140.14.15, 94.140.15.16\n\nDoH (默认): dns.adguard.com/dns-query\nDoH (家庭保护): dns-family.adguard.com/dns-query\nDoT (默认): dns.adguard.com\nDoT (家庭保护): dns-family.adguard.com\n\n\n\nNeustar UltraDNS\n\nNeustar UltraDNS: 156.154.70.1, 156.154.71.1, 156.154.70.5, 156.154.71.5\n\n柬埔寨 DNS\n\n柬埔寨 DNS: 103.197.104.178, 103.197.106.75, 203.189.136.148\n\nUCOM DNS日本东京\n\nUCOM DNS日本东京: 203.112.2.4\n\nDNS.WATCH\n\nDNS.WATCH: 84.200.69.80, 84.200.70.40\n\nSafeDNS\n\nSafeDNS: 195.46.39.39, 195.46.39.40\n\npuntCAT DNS\n\npuntCAT DNS: 109.69.8.51\n\nUncensoredDNS\n\nUncensoredDNS: 91.239.100.100, 89.233.43.71\n\nGreenTeamDNS\n\nGreenTeamDNS: 81.218.119.11, 209.88.198.133\n\nDNS.SB\n\nDNS.SB: 185.222.222.222, 45.11.45.11\n\nDoH: doh.dns.sb/dns-query, doh.sb/dns-query\nDoT: dot.sb\n\n\n\nHurricane ElectricHE\n\nHurricane ElectricHE: 74.82.42.42, 66.220.18.42\n\nDNSReactor\n\nDNSReactor: 104.236.210.29, 45.55.155.25\n\nCleanBrowsing DNS\n\nCleanBrowsing DNS (Security Filter): 185.228.168.9, 185.228.169.9\nCleanBrowsing DNS (Adult Filter): 185.228.168.10, 185.228.169.11\nCleanBrowsing DNS (家庭保护): 185.228.168.168, 185.228.169.168\n\nDoH (家庭保护): doh.cleanbrowsing.org/doh/family-filter/\nDoT: dns.cleanbrowsing.org\n\n\n\nPowerDNS\n\nPowerDNS:\n\nDoH: doh.powerdns.org\n\n\n\nWorldlink DNS\n\nWorldlink DNS: 202.79.32.33, 202.79.32.34\n\n日本 IIJ DNS\n\n日本 IIJ DNS:\n\nDoH: public.dns.iij.jp/dns-query\n\n\n\nBlahdns 日本节点\n\nBlahdns 日本节点:\n\nDoH: doh-jp.blahdns.com/dns-query\n\n\n\nMullvad Public DNS\n\nMullvad Public DNS: 194.242.2.2\n\nDoH: dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (去广告 + 跟踪器)\n\nMullvad Public DNS (去广告 + 跟踪器): 194.242.2.3\n\nDoH: adblock.dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (去广告 + 跟踪器 + 恶意软件)\n\nMullvad Public DNS (去广告 + 跟踪器 + 恶意软件): 194.242.2.4\n\nDoH: base.dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (完全)\n\nMullvad Public DNS (完全): 194.242.2.9\n\nDoH: all.dns.mullvad.net/dns-query\n\n\n\n高校公共 DNS 服务器\n中科大 DNS\n\n中科大 DNS中国电信: 202.141.162.123\n中科大 DNS教育网: 202.38.93.153\n中科大 DNS中国移动: 202.141.176.93\n\n清华大学 TUNA\n\n清华大学 TUNA: 101.6.6.6\n\n中国电信 DNS\n安徽电信 DNS\n\nIPv4: 61.132.163.68, 202.102.213.68\n\n北京电信 DNS\n\nIPv4: 219.141.136.10, 219.141.140.10\n\n重庆电信 DNS\n\nIPv4: 61.128.192.68, 61.128.128.68\n\n福建电信 DNS\n\nIPv4: 218.85.152.99, 218.85.157.99\n\n甘肃电信 DNS\n\nIPv4: 202.100.64.68, 61.178.0.93\n\n广东电信 DNS\n\nIPv4: 202.96.128.86, 202.96.128.166, 202.96.134.133, 202.96.128.68, 202.96.154.8, 202.96.154.15\n\n广西电信 DNS\n\nIPv4: 202.103.225.68, 202.103.224.68\n\n贵州电信 DNS\n\nIPv4: 202.98.192.67, 202.98.198.167\n\n河南电信 DNS\n\nIPv4: 222.88.88.88, 222.85.85.85\n\n黑龙江电信 DNS\n\nIPv4: 219.147.198.230, 219.147.198.242\n\n湖北电信 DNS\n\nIPv4: 202.103.24.68, 202.103.0.68\n\n湖南电信 DNS\n\nIPv4: 59.51.78.211, 59.51.78.210, 222.246.129.80\n\n江苏电信 DNS\n\nIPv4: 218.2.2.2, 218.4.4.4, 61.147.37.1, 218.2.135.1\n\n江西电信 DNS\n\nIPv4: 202.101.224.69, 202.101.226.68\n\n内蒙古电信 DNS\n\nIPv4: 219.148.162.31, 222.74.39.50\n\n山东电信 DNS\n\nIPv4: 219.146.1.66, 219.147.1.66\n\n陕西电信 DNS\n\nIPv4: 218.30.19.40, 61.134.1.4\n\n上海电信 DNS\n\nIPv4: 202.96.209.133, 116.228.111.118, 202.96.209.5, 180.168.255.118\n\n四川电信 DNS\n\nIPv4: 61.139.2.69, 218.6.200.139\n\n天津电信 DNS\n\nIPv4: 219.150.32.132, 219.146.0.132\n\n云南电信 DNS\n\nIPv4: 222.172.200.68, 61.166.150.123\n\n浙江电信 DNS\n\nIPv4: 202.101.172.35, 61.153.177.196, 61.153.81.75, 60.191.244.5\n\n中国联通 DNS\n吉林联通 DNS\n\nIPv4: 202.98.0.68, 202.98.5.68\n\n浙江联通 DNS\n\nIPv4: 221.12.1.227, 221.12.33.227\n\n北京联通 DNS\n\nIPv4: 123.123.123.123, 123.123.123.124, 202.106.0.20, 202.106.195.68\n\n重庆联通 DNS\n\nIPv4: 221.5.203.98, 221.7.92.98\n\n广东联通 DNS\n\nIPv4: 210.21.196.6, 221.5.88.88\n\n河北联通 DNS\n\nIPv4: 202.99.160.68, 202.99.166.4\n\n河南联通 DNS\n\nIPv4: 202.102.224.68, 202.102.227.68\n\n黑龙江联通 DNS\n\nIPv4: 202.97.224.69, 202.97.224.68\n\n辽宁联通 DNS\n\nIPv4: 202.96.69.38, 202.96.64.68\n\n江苏联通 DNS\n\nIPv4: 221.6.4.66, 221.6.4.67\n\n内蒙古联通 DNS\n\nIPv4: 202.99.224.68, 202.99.224.8\n\n山东联通 DNS\n\nIPv4: 202.102.128.68, 202.102.152.3, 202.102.134.68, 202.102.154.3\n\n山西联通 DNS\n\nIPv4: 202.99.192.66, 202.99.192.68\n\n陕西联通 DNS\n\nIPv4: 221.11.1.67, 221.11.1.68\n\n上海联通 DNS\n\nIPv4: 210.22.70.3, 210.22.84.3\n\n四川联通 DNS\n\nIPv4: 119.6.6.6, 124.161.87.155\n\n天津联通 DNS\n\nIPv4: 202.99.104.68, 202.99.96.68\n\n中国移动 DNS\n湖北移动 DNS\n\nIPv4: 211.137.58.20, 211.137.64.163, 211.136.17.107, 211.136.20.203\n\n广东移动 DNS\n\nIPv4: 211.136.192.6, 211.136.20.204, 211.139.163.6, 211.139.136.68, 211.136.18.171\n\n上海移动 DNS\n\nIPv4: 211.136.112.50, 211.136.150.66\n\n天津移动 DNS\n\nIPv4: 211.137.160.50, 211.137.160.185\n\n北京移动 DNS\n\nIPv4: 221.130.33.52, 221.130.33.60, 211.136.28.231, 211.136.28.234, 211.136.28.237, 211.136.28.228, 221.130.32.103, 221.130.32.100, 221.130.32.106, 221.130.32.109, 221.176.3.70, 221.176.3.73, 221.176.3.76, 221.176.3.79, 221.176.3.83, 221.176.3.85, 221.176.4.6, 221.176.4.9, 221.176.4.12, 221.176.4.15, 221.176.4.18, 221.176.4.21, 211.138.30.66\n\n重庆移动 DNS\n\nIPv4: 218.201.4.3, 218.201.21.132, 218.201.17.2\n\n四川移动 DNS\n\nIPv4: 211.137.82.4\n\n陕西移动 DNS\n\nIPv4: 211.137.130.3, 211.137.130.19, 218.200.6.139\n\n江西移动 DNS\n\nIPv4: 211.141.90.68, 211.141.90.69, 211.141.85.68\n\n广西移动 DNS\n\nIPv4: 211.138.245.180, 211.136.17.108, 211.139.5.30\n\n湖南移动 DNS\n\nIPv4: 211.142.210.98, 211.142.210.99, 211.142.210.100, 211.142.210.101, 211.142.236.87\n\n浙江移动 DNS\n\nIPv4: 211.140.13.188, 211.140.188.188, 211.140.10.2\n\n江苏移动 DNS\n\nIPv4: 221.131.143.69, 112.4.0.55, 221.130.13.133, 211.103.55.50, 221.130.56.241, 211.103.13.101, 211.138.200.69\n\n山西移动 DNS\n\nIPv4: 211.138.106.2, 211.138.106.3, 211.138.106.18, 211.138.106.19, 211.138.106.7\n\n山东移动 DNS\n\nIPv4: 218.201.96.130, 211.137.191.26, 218.201.124.18, 218.201.124.19\n\n安徽移动 DNS\n\nIPv4: 211.138.180.2, 211.138.180.3\n\n福建移动 DNS\n\nIPv4: 211.138.151.161, 211.138.156.66, 218.207.217.241, 218.207.217.242, 211.143.181.178, 211.143.181.179, 218.207.128.4, 218.207.130.118, 211.138.145.194\n\n香港移动 DNS\n\nIPv4: 203.142.100.18, 203.142.100.21\n\n青海移动 DNS\n\nIPv4: 211.138.75.123\n\n西藏移动 DNS\n\nIPv4: 211.139.73.34, 211.139.73.35\n\n新疆移动 DNS\n\nIPv4: 218.202.152.130, 218.202.152.131\n\n内蒙古移动 DNS\n\nIPv4: 211.138.91.1, 211.138.91.2\n\n海南移动 DNS\n\nIPv4: 221.176.88.95, 211.138.164.6\n\n云南移动 DNS\n\nIPv4: 211.139.29.68, 211.139.29.69, 211.139.29.150, 211.139.29.170, 218.202.1.166\n\n辽宁移动 DNS\n\nIPv4: 211.137.32.178, 211.140.197.58\n\n吉林移动 DNS\n\nIPv4: 211.141.16.99, 211.141.0.99\n\n甘肃移动 DNS\n\nIPv4: 218.203.160.194, 218.203.160.195\n\n河北移动 DNS\n\nIPv4: 211.143.60.56, 211.138.13.66\n\n贵州移动 DNS\n\nIPv4: 211.139.5.29, 211.139.5.30\n\n黑龙江移动 DNS\n\nIPv4: 211.137.241.34, 211.137.241.35\n\n其它运营商 DNS\n广东铁通 DNS\n\nIPv4: 61.235.70.252, 211.98.4.1\n\n广东广电 DNS | 珠江宽频 DNS\n\nIPv4: 116.116.116.116, 116.199.0.200\n\n广东长城宽带 DNS\n\nIPv4: 211.162.78.1, 211.162.78.2\n\n广东天威视讯 DNS\n\nIPv4: 211.148.192.141\n"},"Technology/ComputerNetwork/公共服务/IPv6-DNS-服务":{"title":"IPv6 DNS 服务","links":[],"tags":["技术/计算机网络","公共服务/DNS"],"content":"中国公共 DNS 服务器 IPV6 地址\n阿里 IPv6 DNS\n\n阿里 IPv6 DNS: 2400:3200::1, 2400:3200:baba::1\n\nDoH: https://2400:3200::1/dns-query, https://2400:3200:baba::1/dns-query\n\n\n\nDNSPod DNS+\n\n腾讯 DNS: 2402:4e00::\n\n百度 BaiduDNS\n\n百度 BaiduDNS: 2400:da00::6666\n\nCNNIC SDNS\n\nCNNIC SDNS: 2001:dc7:1000::1\n\nChinaipv6 PDNS\n\nchinaipv6 PDNS: 240C::6666, 240C::6644\n\nDoT: dns.ipv6dns.com\nDoH: dns.ipv6dns.com/dns-query\n\n\n\n中科院网络信息中心 DNS\n\n中科院网络信息中心 DNS: 2001:cc0:2fff:1::6666\n\n科技网 IPV6 DNS\n\n科技网 IPV6 DNS: 2001:cc0:2fff:2::6\n\nOneDns IPv6 DNS\n\nOneDns IPv6 DNS (拦截版): 2400:7fc0:849e:200::4, 2404:c2c0:85d8:901::4\nOneDns IPv6 DNS (纯净版): 2400:7fc0:849e:200::8, 2404:c2c0:85d8:901::8\n\n港澳台公共 DNS 服务器 IPV6 地址\n台湾 Quad 101\n\n台湾 Quad 101: 2001:de4::101, 2001:de4::102\n\n世界公共 DNS 服务器 IPV6 地址\nGoogle IPV6 DNS\n\nGoogle IPV6 DNS: 2001:4860:4860::8888, 2001:4860:4860::8844\n\nDoH: https://[2001:4860:4860::64]/dns-query, https://[2001:4860:4860::6464]/dns-query\n\n\n\nCloudflare IPV6 DNS\n\nCloudflare IPV6 DNS: 2606:4700:4700::1111, 2606:4700:4700::1001\n\nDoH: https://[2606:4700:4700::1111]/dns-query, https://[2606:4700:4700::1001]/dns-query\nDoH: https://[2606:4700:4700::64]/dns-query, https://[2606:4700:4700::6464]/dns-query\n\n\n\nAdGuard IPV6 DNS\n\nAdGuard IPV6 DNS (默认): 2a00:5a60::ad1:0ff, 2a00:5a60::ad2:0ff\nAdGuard IPV6 DNS (家庭保护): 2a00:5a60::bad1:0ff, 12a00:5a60::bad2:0ff\n\nDNS.WATCH\n\nDNS.WATCH: 2001:1608:10:25::1c04:b12f, 2001:1608:10:25::9249:d69b\n\npuntCAT IPV6 DNS\n\npuntCAT IPV6 DNS: 2a00:1508:0:4::9\n\nOpenDNS\n\nOpenDNS: 2620:119:35::35, 2620:119:53::53\n\nNeustar UltraDNS\n\nNeustar UltraDNS: 2610:a1:1018::1, 2610:a1:1019::1, 2610:a1:1018::5, 2610:a1:1019::1\n\nQuad9\n\nQuad9: 2620:fe::fe, 2620:fe::9\n\nDoH (默认): dns.quad9.net/dns-query\nDoH (安全&支持 ECS): dns11.quad9.net/dns-query\n\n\n\nVerisign\n\nVerisign: 2620:74:1b::1:1, 2620:74:1c::2:2\n\nUncensoredDNS\n\nUncensoredDNS: 2001:67c:28a4::, 2a01:3a0:53:53::\n\nNTT DNS\n\nNTT DNS: 2001:418:3ff::53, 2001:418:3ff::1:53\n\nDNS.SB\n\nDNS.SB: 2a09::, 2a11::\n\nDoT: 2a09::@853, 2a11::@853\n\n\n\nCleanBrowsing DNS\n\nCleanBrowsing DNS (Security Filter): 2a0d:2a00:1::2, 2a0d:2a00:2::2\nCleanBrowsing DNS (Adult Filter): 2a0d:2a00:1::1, 2a0d:2a00:2::1\nCleanBrowsing DNS (家庭保护): 2a0d:2a00:1::, 2a0d:2a00:2::\n\n高校公共 DNS 服务器 IPV6 地址\n清华大学 TUNA 协会 IPV6 DNS\n\n清华大学 TUNA 协会 IPV6 DNS: 2001:da8::666\n\n上海交大 IPV6 DNS\n\n上海交大 IPV6 DNS: 2001:da8:8000:1:202:120:2:101\n\n北京邮电大学 IPV6 DNS\n\n北京邮电大学 IPV6 DNS: 2001:da8:202:10::36, 2001:da8:202:10::37\n\n北京科技大学 IPV6 DNS\n\n北京科技大学 IPV6 DNS: 2001:da8:208:10::6\n\n中科大 IPV6 DNS\n\n中科大 IPV6 DNS: 2001:da8::666\n\n电信公共 DNS 服务器 IPV6 地址\n\n中国电信 IPv6 DNS: 240e:4c:4008::1, 240e:4c:4808::1\n\n联通公共 DNS 服务器 IPV6 地址\n\n中国联通 IPv6DNS\t2408:8899::8 2408:8888::8\n\n移动公共 DNS 服务器 IPV6 地址\n\n中国移动 IPv6DNS\t2409:8088:: 2409:8088::b\n"},"Technology/ComputerNetwork/公共服务/Mirror-镜像站":{"title":"Mirror 镜像站","links":[],"tags":["技术/计算机网络","公共服务/Mirror"],"content":"企业镜像\n阿里云\n\n镜像站地址: developer.aliyun.com/mirror\n\n腾讯云\n\n镜像站地址: mirrors.cloud.tencent.com\n\n网易\n\n镜像站地址: mirrors.163.com\n\n华为\n\n镜像站地址: mirrors.huaweicloud.com\n\n高校镜像\n中国校园网联合镜像\n\n镜像站地址mirrors.cernet.edu.cn/\n\n中国科学技术大学\n\n镜像站地址: mirrors.ustc.edu.cn\n\n上海交通大学\n\n镜像站地址: mirrors.sjtug.sjtu.edu.cn\n\n清华大学 TUNA\n\n镜像站地址: https:/mirrors.tuna.tsinghua.edu.cn\n镜像站地址: opentuna.cn\n\n北京大学\n\n镜像站地址: mirrors.pku.edu.cn/Mirrors\n\n哈尔滨工业大学\n\n镜像站地址: mirrors.hit.edu.cn\n\n浙江大学\n\n镜像站地址: mirrors.zju.edu.cn\n\n北京交通大学\n\n镜像站地址: mirror.bjtu.edu.cn\n\n北京外国语大学\n\n镜像站地址: mirrors.bfsu.edu.cn\n\n大连东软信息学院\n\n镜像站地址: mirrors.neusoft.edu.cn\n\n南京大学\n\n镜像站地址: mirrors.nju.edu.cn\n\n南京邮电大学\n\n镜像站地址: mirrors.njupt.edu.cn\n\n山东大学\n\n镜像站地址: mirrors.sdu.edu.cn\n\n华中科技大学\n\n镜像站地址: mirror.hust.edu.cn\n\n东北大学\n\n镜像站地址: mirror.neu.edu.cn\n\n大连理工大学\n\n镜像站地址: mirror.dlut.edu.cn\n\n南洋理工学院\n\n镜像站地址: mirror.nyist.edu.cn\n\n南方科技大学\n\n镜像站地址: mirrors.sustech.edu.cn\n\n重庆大学\n\n镜像站地址: mirrors.cqu.edu.cn\n\n山东女子学院\n\n镜像站地址: mirrors.sdwu.edu.cn\n\n西安交通大学\n\n镜像站地址: mirrors.xjtu.edu.cn\n镜像站地址: mirrors.xjtuana.com\n\n北京邮电大学\n\n镜像站地址: mirrors.bupt.edu.cn\n镜像站地址: mirrors.byrio.org\n\n西北农林科技大学\n\n镜像站地址: mirrors.nwsuaf.edu.cn\n镜像站地址: mirrors.nwafu.edu.cn\n\n同济大学\n\n镜像站地址: mirrors.tongji.edu.cn\n\n华南农业大学\n\n镜像站地址: mirrors.scau.edu.cn\n\n东莞理工学院\n\n镜像站地址: mirrors.dgut.edu.cn\n\n云南大学\n\n镜像站地址: mirrors.ynu.edu.cn/index\n\n中国科学院软件研究所\n\n镜像站地址: mirror.iscas.ac.cn\n\n武昌首义学院\n\n镜像站地址: mirrors.wsyu.edu.cn\n"},"Technology/ComputerNetwork/公共服务/NTP-服务器":{"title":"NTP 服务器","links":[],"tags":["技术/计算机网络","公共服务/NTP"],"content":"中国 NTP 服务器\n国家授时中心 NTP 服务器\n\nNTSC NTP Server: ntp.ntsc.ac.cn\n\n中国 NTP 快速授时服务\n\nNTP ORG CN: cn.ntp.org.cn\n中国教育网专用: edu.ntp.org.cn\n\n阿里云公共 NTP 服务器\n\nAliyun NTP Server: ntp1.aliyun.com, ntp2.aliyun.com, ntp3.aliyun.com, ntp4.aliyun.com, ntp5.aliyun.com, ntp6.aliyun.com, ntp7.aliyun.com\n\n腾讯公共 NTP 服务器\n\nTencent Cloud NTP Server: ntp.tencent.com, ntp1.tencent.com, ntp2.tencent.com, ntp3.tencent.com, ntp4.tencent.com, ntp5.tencent.com\n\n高校 NTP 服务器\n\n上海交大 NTP 服务器: ntp.sjtu.edu.cn\n东北大学 NTP 服务器: ntp.neu.edu.cn\n北京邮电大学 NTP 服务器: ntp.bupt.edu.cn\n上海大学 NTP 服务器: ntp.shu.edu.cn\n清华大学 NTP 服务器: ntp.tuna.tsinghua.edu.cn\n\n国际 NTP 快速授时服务 (中国片区)\n\n中国片区: cn.pool.ntp.org, 0.cn.pool.ntp.org, 1.cn.pool.ntp.org, 2.cn.pool.ntp.org, 3.cn.pool.ntp.org\n\n港澳台公共 NTP 服务器\n中国香港\n\n香港: hk.ntp.org.cn\n\n中国台湾\n\n台湾: tw.ntp.org.cn\n\n香港天文台公共 NTP 服务器\n\nHong Kong Observatory NTP Server: stdtime.gov.hk\n\n中华电信 NTP 服务器\n\n中华电信 NTP 服务器: tock.stdtime.gov.tw, watch.stdtime.gov.tw, time.stdtime.gov.tw, clock.stdtime.gov.tw, tick.stdtime.gov.tw\n\n世界公共 NTP 服务器\n全球 NTP 授时服务器\n\npool.ntp.org\n\nCloudFlare NTP 授时服务器\n\nCloudFlare NTP Server: time.cloudflare.com\n\n谷歌公共 NTP 服务器\n\nGoogle NTP Server: time.google.com, time1.google.com, time2.google.com, time3.google.com, time4.google.com\n\n苹果公共 NTP 服务器\n\nApple NTP Server: time.apple.com, time1.apple.com, time2.apple.com, time3.apple.com, time4.apple.com, time5.apple.com, time6.apple.com, time7.apple.com\n\n微软 Windows NTP 服务器\n\nMicrosoft Windows NTP Server: time.windows.com\n\n美国标准技术研究院 NTP 服务器\n\nNIST NTP Server: time.nist.gov, time-nw.nist.gov, time-a.nist.gov, time-b.nist.gov\n\n各洲 NTP 授时服务器\n\n非洲: africa.pool.ntp.org\n南极洲: antarctica.pool.ntp.org\n亚洲: asia.pool.ntp.org\n欧洲: europe.pool.ntp.org\n北美洲: north-america.pool.ntp.org\n澳洲: oceania.pool.ntp.org\n南美洲: south-america.pool.ntp.org\n\n各国 NTP 授时服务器\n\n美国: us.ntp.org.cn\n新加坡: sgp.ntp.org.cn, sg.pool.ntp.org\n韩国: kr.ntp.org.cn, kr.pool.ntp.org\n日本: jp.ntp.org.cn, jp.pool.ntp.org\n德国: de.ntp.org.cn\n印度尼西亚: ina.ntp.org.cn, id.pool.ntp.org\n\nNTT NTP 授时服务器\n\nNTT NTP Server: time.gin.ntt.net\n"},"Technology/ComputerNetwork/应用服务/CDN-内容分发网络":{"title":"CDN 内容分发网络","links":[],"tags":["计算机网络/CDN应用","技术/计算机网络"],"content":"引言\n\n内容分发网络Content Delivery Network, CDN是一种遍布全球的分布式服务器网络。它的主要任务是将网页和其他类型的网络内容如图片、视频、CSS 和 JavaScript 文件)尽可能近的地方传送给用户,从而大大提高加载速度。这不仅提升了用户体验,减少了加载时间和网络延迟,也降低了源服务器的压力。\n比如说CDN 的工作方式可以和京东的本地仓库次日达服务相类比。如果你在京东上购买了一台电视,京东会从离你最近的仓库发货,而不是从远离你的仓库。这样可以极大地缩短你的等待时间,从而提供更好的用户体验。\n发展历史\n内容分发网络CDN的发展历程可以划分为三个主要阶段\n\n第一代 CDN在这个阶段CDN 的重点主要在于智能网络流量管理和数据中心间的联网原理,其核心任务是通过优化网络,确保数据能够快速且稳定地传输。\n第二代 CDN随着音频和视频流媒体服务的兴起第二代 CDN 应运而生。这个阶段的 CDN 的工作重点转向了处理大量的音频和视频数据,确保用户能享受到流畅的媒体播放体验。\n第三代 CDN目前我们正处在第三代 CDN 的发展阶段。随着移动设备的普及用户的访问模式变得更加多元化因此CDN 不仅需要确保内容能快速传输,还需要应对网络环境的多样性和移动设备的特殊性。\n\n工作原理\n\n加速内容分发CDN 将内容分发到全球的边缘服务器,当用户请求内容时,会选择离用户最近或者性能最优的服务器来处理请求,以此提高加载速度和用户体验。\n边缘服务器的作用边缘服务器接近用户能够直接返回缓存的内容避免从源服务器获取这样能减少响应时间和网络拥塞。\n缓存和内容复制CDN 在边缘服务器上缓存内容,从而可以快速响应用户的请求,减少内容的加载时间和网络延迟。\n加速和优化策略CDN 利用一系列策略如动态站点加速、CDN 缓存规则、HTTPS 自定义域支持、诊断日志、文件压缩和地理过滤等,来优化内容分发并提高性能。\n处理大流量通过分布式设计和流量调整CDN 能够轻松处理大流量的情况,保证高性能和高可用性。\n\n主要优势\n\n提升用户体验通过全球分布的服务器CDN 能够减少加载时间和网络延迟,提升用户体验。\n减轻源服务器负担通过边缘服务器直接提供内容CDN 能够减轻源服务器的压力,保持其性能和稳定性。\n提供内容的地理分发CDN 能够将内容快速地分发给全球的用户,特别适合那些拥有全球用户基础的网站或应用。\n提高网站的可靠性和可用性通过全球范围内的服务器分布和网络流量管理CDN 能保证网站的高可用性。\n增强数据安全性和防护 DDoS 攻击能力CDN 提供了防护 DDoS 攻击的功能,并提供 SSL/TLS 加密,能够保护数据的安全性。\n\n适用场景\n阿里云 CDN 服务提供以下适用场景。\n网页站点加速\n\nCDN 是一个全球化的服务系统能够应对网站流量激增时的挑战。其通过全球化的服务节点和智能调度系统让用户就近访问大量静态资源提升网站响应速度。CDN 的费用远低于独享带宽,从而有效降低运营成本。同时,其分布式架构和高性能缓存软件保证了稳定性和效率。还具备灵活调度功能,能根据实际需求调整资源分配。\n下载加速\n\nCDN 提供了高性价比的稳定高速下载服务,支持各类大文件的下载、分发和在线点播加速。主要应用场景包括视音频点播和大文件下载。配合 OSS 接入CDN 可以节约近 2/3 的回源带宽成本。其分布式架构和自研高性能缓存软件保证了服务的稳定性和效率。还能提供基于域名的全量实时监控和智能调度,以适应不同的服务需求。\n视频点播\n\nCDN 为用户提供一站式音视频点播解决方案包括音视频上传、自动转码、媒体资源管理和分发加速帮助快速搭建安全、弹性、高可定制的点播平台和应用。其特色在于提供灵活自动的媒体处理功能用户可零开发自定义云端音视频处理流程支持转码、截图、水印等。CDN 还提供访问控制和版权保护功能,能通过 refer 黑白名单和 URL 鉴权防止盗链。另外,其高效稳定的性能保证了播放流畅无卡顿,具有 95% 以上的命中率和毫秒级的响应时间。\n结论\n总的来说CDN 是实现全球快速、安全、稳定的网络内容分发的关键工具,无论对于大型互联网公司还是个体网站开发者,都是一项重要的基础设施服务。"},"Technology/ComputerNetwork/网络协议/DHCP-动态主机配置协议":{"title":"DHCP 动态主机配置协议","links":[],"tags":["计算机网络/DHCP协议","技术/计算机网络"],"content":"简介\n定义\n动态主机配置协议Dynamic Host Configuration ProtocolDHCP是一个网络协议它能够**动态地分配 IP 地址和其他网络配置参数给网络设备。**该协议由网络工作组Network Working Group所开发是在 TCP/IP 网络环境中的标准化服务。\n历史\nDHCP 的前身是 Bootstrap 协议BOOTP这是一个在 1980 年代为无盘工作站设计的协议,用来动态分配 IP 地址。然而随着网络环境的不断变化和复杂化BOOTP 无法满足新的需求。为了解决这个问题DHCP 在 1993 年被标准化为 RFC1531。\n作用\nDHCP 最主要的功能是自动分配 IP 地址。网络管理员不需要手动为每台设备配置 IP 地址从而极大地简化了网络管理工作。除此之外DHCP 还可以提供其他网络配置信息如子网掩码、默认网关、DNS 服务器等。\n工作原理\n工作流程\nDHCP 的工作流程包括四个步骤发现Discover、提供Offer、请求Request、和应答Acknowledge。\n\n发现当 DHCP 客户端启动时,会在本地网络上广播一个 DHCP 发现消息,以寻找 DHCP 服务器。\n提供收到发现消息的 DHCP 服务器会向客户端提供一个 IP 地址和其他网络配置信息。\n请求客户端在收到提供消息后会向服务器发送一个请求消息以接受这个 IP 地址。\n应答服务器在收到请求消息后会确认这个 IP 地址已被分配给该客户端。\n\n消息格式\nDHCP 消息是基于 UDP 的其主要包括以下四个字段操作码op、硬件类型htype、硬件地址长度hlen以及跳数hops。此外消息还包含一些选项如 IP 地址的租赁时间、子网掩码等。\n地址租赁过程\n当 DHCP 客户端首次连接到网络时,它会开始一个新的地址租赁过程。客户端会首先发送一个 DHCP 发现消息,然后服务器会提供一个 IP 地址。在客户端发送请求消息并得到服务器的确认后,该 IP 地址的租赁就开始了。\n续租和地址释放过程\n在租赁期到达一半时DHCP 客户端会尝试续租 IP 地址。客户端会向分配该 IP 地址的 DHCP 服务器发送一个 DHCP 请求消息。如果服务器同意续租,它会发送一个 DHCP 应答消息,然后新的租赁期就开始了。\n当 DHCP 客户端不再需要该 IP 地址时,它会发送一个 DHCP 释放消息,通知服务器该地址已经空闲,可以分配给其他设备。\n组成部分\n客户端\nDHCP 客户端是请求和使用 DHCP 服务的设备,这些设备通常包括但不限于个人计算机、服务器、路由器以及其他网络设备。当设备连接到网络时,它就成为了一个 DHCP 客户端。客户端负责发送 DHCP 发现、请求和释放消息,并使用由服务器分配的 IP 地址和其他网络配置信息。\n服务器\nDHCP 服务器是提供 DHCP 服务的设备,可以是专门的物理设备,也可以是软件服务器。它管理着一个或多个 IP 地址池并且还管理着与这些地址相关的配置参数如子网掩码、默认网关、DNS 服务器等。服务器负责响应 DHCP 发现、请求和释放消息,同时负责分配和管理 IP 地址租赁。此外,服务器还需要维护网络配置的一致性,以防止 IP 地址冲突。\n中继代理\nDHCP 中继代理(也称为 DHCP Relay Agent是一种特殊的网络设备通常位于与 DHCP 服务器不在同一个子网的地方。它的主要作用是在多个子网之间转发 DHCP 消息。当 DHCP 客户端在本地子网上找不到 DHCP 服务器时,中继代理会将客户端的广播请求消息转发给远程子网上的 DHCP 服务器。同样,中继代理也会将 DHCP 服务器的响应消息转发给本地子网的 DHCP 客户端。通过这种方式DHCP 中继代理使 DHCP 服务器能够为多个不同的子网提供服务。\nDHCP 与其他技术的关系\nDHCP 与 DNS\n动态主机配置协议DHCP和域名系统DNS在网络配置中扮演着重要的角色。DHCP 负责为网络设备分配 IP 地址,而 DNS 则将域名解析为 IP 地址,使得用户可以通过友好的域名来访问互联网上的服务器。在 DHCP 服务器中可以配置 DNS 服务器的 IP 地址,当 DHCP 客户端请求 IP 地址时DHCP 服务器可以同时向 DHCP 客户端提供 DNS 服务器的地址。\nDHCP 与 IPv4/IPv6\nDHCP 协议不仅支持 IPv4也支持 IPv6。对于 IPv4DHCP 可以动态分配 IP 地址、子网掩码、网关以及 DNS 服务器等网络参数。而对于 IPv6引入了无状态地址自动配置SLAAC和有状态地址配置两种方式。在有状态配置中DHCPv6 扮演与 DHCP 在 IPv4 网络中相同的角色,负责分配 IPv6 地址以及其他网络配置信息。\nDHCP 与静态 IP 地址\nDHCP 服务可以动态分配 IP 地址,这意味着设备每次连接网络时,可能会得到不同的 IP 地址。相对的,静态 IP 地址是由网络管理员手动配置的,它不会改变。虽然静态 IP 地址在某些情况下(如服务器)是必需的,但在大多数情况下,使用 DHCP 更为方便,因为它可以自动管理网络配置,从而避免了 IP 地址冲突等问题。\nDHCP 与网络安全\n尽管 DHCP 提供了很大的便利性,但如果配置和管理不当,也可能带来安全问题。比如,未经授权的 DHCP 服务器可能会向网络中的设备分配错误的网络配置,从而导致网络服务中断。或者,恶意用户可能通过伪装 DHCP 服务器来进行网络攻击。因此,实施合理的网络策略和安全措施(如 DHCP Snooping对于保障 DHCP 服务的安全性是必要的。\n问题诊断与解决方法\n常见问题及解决方案\n一些常见的 DHCP 问题包括 IP 地址冲突、租赁期过短,以及 DHCP 服务器无法响应请求。这些问题通常可以通过检查 DHCP 服务器的配置来解决,比如检查 IP 地址池的大小,租赁时间的长度,以及服务器的网络连接状态等。\n故障排除工具和技巧\n网络管理员可以利用一些工具来帮助他们诊断和解决 DHCP 问题。例如,使用网络嗅探器(如 Wireshark可以捕获和分析 DHCP 消息,以帮助确定问题的来源。此外,管理员还可以查看 DHCP 服务器的日志,这可以提供关于 DHCP 操作和可能的错误的信息。他们也可以使用命令行工具(如 ipconfig 和 dhcping来测试 DHCP 服务器的响应。"},"Technology/ComputerNetwork/网络协议/DNS-域名系统":{"title":"DNS 域名系统","links":[],"tags":["计算机网络/DNS协议","技术/计算机网络"],"content":"简介\n定义和目的\n**域名系统Domain Name SystemDNS是一个用于将域名如 www.example.com转换为 IP 地址的分布式数据库。**当我们在浏览器中输入一个网站的 URL 时DNS 系统就会被调用,将 URL 中的域名转换为对应的 IP 地址从而使用户能够访问到正确的网站。DNS 的存在使得用户无需记住复杂的 IP 地址,只需要记住易于理解和记忆的域名就可以访问互联网,大大提升了用户的使用体验。\n发展历程\nDNS 在 1980 年代由 Paul Mockapetris 发明,以解决当时互联网上主机名和 IP 地址管理的问题。原来的主机名和 IP 地址的对应关系是存储在一个叫做 HOSTS.TXT 的文件中,随着互联网的发展,这个文件变得越来越大,难以管理。\n因此DNS 被设计出来以提供一种可扩展的名称解析系统。DNS 提供了一种分布式的解决方案,允许主机名和 IP 地址的对应关系在各个服务器上进行存储和管理。\n工作原理\ngraph LR\nA[客户端] -->|DNS 请求| B[递归服务器]\nB -->|查找缓存| C{找到结果?}\nC -->|是| D[返回结果]\nC -->|否| E[向根服务器查询]\nE --> F[根服务器返回顶级服务器]\nF --> G[向顶级服务器查询]\nG --> H[顶级服务器返回权威服务器]\nH --> I[向权威服务器查询]\nI --> J[权威服务器返回IP]\nJ --> K[缓存结果并返回给客户端]\n\n当客户端发出域名解析请求时DNS 服务器会响应这个请求,提供相应的 IP 地址。具体来说,这个过程涉及到递归查询和迭代查询两个步骤。\n\n用户在浏览器中输入网址。\n客户端你的计算机向 DNS 递归服务器发送请求。\n递归服务器首先在缓存中查找结果。\n如果缓存中没有结果递归服务器会向其他 DNS 服务器查询。\n服务器之间进行一系列查询最后在权威服务器上找到正确的 IP 地址。\n权威服务器将 IP 地址返回给递归服务器。\n递归服务器将 IP 地址缓存并返回给客户端。\n客户端通过接收到的 IP 地址访问网站。\n\n域名架构\nDNS 的域名架构是分层次的,每个级别的域名都由特定的实体管理。例如,.com 是顶级域由全球的域名系统管理example.com 是二级域,可能由一个组织或个人管理。每个层级的域名管理者负责维护其域名下的所有记录。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n域名描述.com通用顶级域名经常用于商业网站.org通用顶级域名经常用于非营利组织.net通用顶级域名经常用于互联网服务提供商.edu限制顶级域名仅用于教育机构.gov限制顶级域名仅用于美国政府.mil限制顶级域名仅用于美国军事部门.co.uk英国的国家代码顶级域名.de德国的国家代码顶级域名.ca加拿大的国家代码顶级域名.cn中国的国家代码顶级域名\n系统组成\nDNS 系统由多种服务器和各种类型的 DNS 记录组成。\n服务器\n\n权威服务器存储特定域名与其关联 IP 地址的服务器。权威服务器是 DNS 查询的最终目的地。\n递归服务器接收来自客户端的 DNS 查询,与其他服务器进行交流以解析查询。\n缓存服务器存储 DNS 查询结果,加快解析速度,减少网络延迟。\n根服务器全球仅有 13 组 IPv4 根服务器,它们知道所有顶级域的权威服务器的位置。\n\n记录\nDNS 记录是存储在 DNS 服务器上的数据,用于定义域名的各种属性。以下是一些常见的 DNS 记录类型:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n记录类型使用目的A将域名指向一个 IP 地址外网地址。CNAME将域名指向另一个域名再由另一个域名提供 IP 地址外网地址。MX设置邮箱让邮箱能收到邮件。NS将子域名交给其他 DNS 服务商解析。SPF将域名指向发送邮件的服务器是一种以 IP 地址认证电子邮件发件人身份的技术是非常高效的垃圾邮件解决方案。AAAA将域名指向一个 IPv6 地址。SRV用来标识某台服务器使用了某个服务常见于微软系统的目录管理。TXT对域名进行标识和说明绝大多数的 TXT 记录是用来做 SPF 记录反垃圾邮件。CAA授权指定 CA 机构为域名签发 SSL 证书,以防止 SSL 证书错误签发。HTTPS将域名指向另一个域名指定值再由另一个域名提供 IP 地址,就需要添加 HTTPS 记录。SVCB新型服务绑定记录类型允许服务指向多个客户端并关联自定义参数值。隐、显性 URL将一个域名指向另外一个已经存在的站点。\n安全\n威胁\n\n欺骗和缓存污染攻击者可能会伪造 DNS 响应,导致用户被重定向到恶意网站。如果递归服务器收到一个伪造的 DNS 响应并将其缓存,就会导致缓存污染,影响到所有使用这个递归服务器的用户。\n针对基础设施的 DDoS 攻击:通过发送大量的查询请求,可以使 DNS 服务器瘫痪,影响用户访问互联网的能力。\n\n措施\n\nDNSSEC域名系统安全扩展这是一种通过在 DNS 查询结果中添加数字签名的技术,可以保证 DNS 查询结果的真实性和完整性,防止 DNS 欺骗和缓存污染。\n过滤和黑名单通过设置过滤规则和黑名单可以阻止恶意网站的 DNS 查询,保护用户免受恶意网站的攻击。\n\n管理\n配置和管理 DNS 服务器也是一个重要的工作。有很多种类型的 DNS 服务器软件可以选择,例如 BIND、Microsoft DNS、PowerDNS 等。不同的软件有不同的特点和优点需要根据实际需要来选择。DNS 服务器可以通过命令行界面或基于 Web 的界面进行管理。命令行界面更灵活,但需要一定的技术知识;基于 Web 的界面更易于使用,但可能没有命令行界面那么强大。\n在管理 DNS 服务器时,保护服务器安全是非常重要的。定期更新软件,严格限制访问权限,可以有效地防止攻击。特别是在面对 DDoS 攻击时,限制查询的频率和数量是一种有效的防御手段。此外,实时监控 DNS 服务器的状态,可以及时发现和解决问题。使用一些专门的监控和故障排除工具,可以大大提高工作效率。\n扩展\n\nDoHDNS over HTTPS和 DoTDNS over TLS这两种新技术可以实现 DNS 查询的加密传输从而提高用户的隐私保护。DoH 和 DoT 都可以防止 DNS 查询被窃听或篡改,保护用户的互联网使用安全。\n国际化域名IDNs国际化域名是一种新的域名类型允许使用非拉丁字符的域名如中文、阿拉伯文等。这大大扩展了域名的使用范围使得更多的人可以方便地使用互联网。\n基于 DNS 的服务发现DNS-SDDNS-SD 是一种使用 DNS 协议在网络上自动发现可用服务的技术。例如,打印机、文件共享、网络摄像头等设备和服务,可以通过 DNS-SD 自动地在网络上宣告其存在,用户可以方便地发现和使用这些服务。\n\n结论\n**DNS 是互联网的基础设施之一,它将用户可以理解和记忆的域名转换为计算机可以理解的 IP 地址。**这个过程涉及到多个不同类型的服务器和记录,每一个部分都在整个解析过程中扮演着重要的角色。在 DNS 查询过程中,客户端发出请求,递归服务器处理这个请求,并从权威服务器获取响应,然后将响应返回给客户端。为了提高效率,这些查询结果会被缓存在各个层级的服务器上。\n尽管 DNS 已经有了几十年的历史,但它仍在不断发展和创新。新的技术如 DoH 和 DoT使得 DNS 查询可以在加密的通道中传输提高了用户的隐私保护。国际化域名则使得更多的人可以方便地使用互联网。同时DNS 也面临着一些挑战,如安全威胁、管理复杂性等,这需要我们不断地学习和改进,以保护互联网的安全和稳定。"},"Technology/ComputerNetwork/网络协议/IP-网际协议":{"title":"IP 网际协议","links":[],"tags":["计算机网络/IP协议","技术/计算机网络"],"content":"IP 协议基础理论\n互联网协议IP是一种无连接的网络层协议它是互联网的基础。IP 协议主要负责将数据包从源主机传送到目的主机无论这两台主机位于何处。IP 协议是一个路由协议,意味着它可以动态地选择数据包从一个网络节点到另一个网络节点的路径。\nIP 协议在 OSI 模型中的位置\nOSI 模型是一个参考模型用于描述和理解复杂的网络通信过程。在这个模型中IP 协议位于第三层,即网络层。网络层负责数据包的路由和转发,确保数据能够通过网络找到正确的目的地。\n与 TCP/UDP 的关系\n\nTCP传输控制协议位于传输层与 IP 协议结合使用,提供可靠的、面向连接的数据传输服务。\nUDP用户数据报协议也位于传输层但提供的是简单的、无连接的服务。与 IP 结合时UDP 允许数据包在不同的网络设备间传送,但不保证数据包的可靠传输。\n\nIPv4 地址\n\n32 位二进制数IPv4 地址由 32 位二进制数字组成,通常分为四个 8 位的部分,每部分称为一个字节。\n点分十进制表示法为了便于阅读IPv4 地址通常以点分十进制格式表示,例如 192.168.1.1。每个字节的二进制数被转换成十进制数,并用点分隔。\n网络部分和主机部分IPv4 地址分为网络部分和主机部分。网络部分标识特定的网络,而主机部分标识该网络上的特定设备。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组件描述例子说明整体结构32 位二进制数字11000000.10101000.00000001.00000001分为 4 个字节表示法点分十进制192.168.1.1每个字节转换为十进制用点分隔网络部分标识特定网络192.168.1取决于类别A, B, C或子网掩码主机部分标识网络上的设备.1剩余部分\nIPv6 地址\n\n128 位二进制数IPv6 地址是由 128 位二进制数字组成,以解决 IPv4 地址空间不足的问题。\n十六进制表示法IPv6 地址通常以 16 个字符的组(每组 4 个字符)表示,如 2001:0db8:85a3:0000:0000:8a2e:0370:7334。\n更大的地址空间IPv6 提供了几乎无限的地址空间,支持更复杂的网络结构和更多的网络设备。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组件描述例子说明整体结构128 位二进制数字2001:0db8:85a3:0000:0000:8a2e:0370:7334分为 8 组,每组 16 位表示法十六进制表示2001:0db8:85a3:0000:0000:8a2e:0370:7334每 16 位一组用冒号分隔网络部分标识特定网络2001:0db8:85a3前缀长度不固定主机部分标识网络上的设备:0000:0000:8a2e:0370:7334剩余部分\n子网掩码\n子网掩码用于区分 IP 地址的网络部分和主机部分。它对网络设计和管理至关重要。\n功能\n\n划分网络子网掩码确定了 IP 地址中哪部分是网络地址,哪部分是主机地址。这对于 IP 地址的有效分配和网络流量的适当路由至关重要。\n子网划分子网掩码允许网络管理员将大型网络划分为更小、更高效的子网。\n\n结构\n\n二进制表示子网掩码是一串二进制数字其中网络部分全为 1主机部分全为 0。例如255.255.255.0 的子网掩码在二进制中表示为 11111111.11111111.11111111.00000000。\nCIDR 表示法在无类别域间路由CIDR子网掩码表示为斜线后跟数字数字表示网络部分中的连续 1 的数量。例如,/24 表示前 24 位是网络地址,相当于 255.255.255.0。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组件描述例子说明整体结构与 IP 地址同长度的二进制数11111111.11111111.11111111.00000000对应 IPv4表示法点分十进制255.255.255.0对应每 8 位二进制CIDR 表示法斜线后跟数字/24表示网络部分中的连续 1 的数量功能划分网络和主机部分-决定哪部分是网络地址,哪部分是主机地址\nIP 地址分配和管理\n静态与动态 IP 地址\n\n静态 IP 地址:这是固定分配给网络设备的 IP 地址,一旦设置,除非管理员手动更改,否则不会变化。静态 IP 地址适用于服务器、打印机等需要固定 IP 以便轻易访问的设备。\n动态 IP 地址:动态 IP 地址由网络服务器自动分配,通常每次设备连接到网络时都可能更改。动态地址分配主要通过 DHCP 实现,适用于临时客户端设备,如员工的笔记本电脑。\n\nDHCP\n\n动态主机配置协议DHCP这是一个网络管理协议用于自动分配 IP 地址和其他相关配置信息给网络设备。DHCP 服务器在收到设备的请求时,从一个定义好的地址池中分配 IP 地址,并设置有效期(租期)。\n工作原理当设备连接到网络时它向网络广播一个 DHCP 请求。DHCP 服务器接收到请求后,从地址池中分配一个 IP 地址,并发送回应,包含 IP 地址、子网掩码、默认网关以及 DNS 服务器信息。\n\nIP 地址分配策略\n地址池管理\n\n子网划分根据网络规模和需求合理划分子网。小型网络可能只需要一个子网而大型或分布广泛的网络可能需要多个子网。通过子网划分可以更有效地管理 IP 地址。\n地址池规模评估网络内部设备的数量包括不仅限于工作站、服务器、打印机和无线设备等预测未来扩展需要确保地址池有足够的地址可以分配。\n留白地址在地址池中预留一定数量的 IP 地址,用于未来扩展或临时需要。\n\n租期设置\n\n动态地址分配租期针对普通客户端设备可以设置较短的租期例如 24 小时),以保证 IP 地址能够有效循环利用。租期过短可能会增加网络流量,而过长则可能导致 IP 地址浪费。\n租期续订策略设定合理的续订策略例如当租期过半时尝试续订以减少因租期到期而导致的网络中断。\n\n保留地址\n\n静态地址分配对于服务器、网络打印机、路由器等关键设备分配静态 IP 地址。这样做可以确保这些设备的网络路径稳定可靠。\nDHCP 保留:在 DHCP 服务器上为特定的 MAC 地址保留 IP 地址。即使是在使用动态地址分配的环境中,也可以确保某些特定设备总是获得相同的 IP 地址。\n\n子网划分和超网\n子网划分目的在于将大型网络划分成更小、更易管理的网络段。可以通过更改子网掩码将一个大型网络的 IP 地址空间划分成多个小网络。每个子网有自己的网络地址和广播地址,以及一系列可用于分配给设备的 IP 地址。\nCIDR无类别域间路由选择\nCIDR 是一种用于创建更灵活的网络地址分配方法的 IP 地址分配和路由选择方法。它允许更细粒度的子网划分,优化 IP 地址的使用。\n\n实现方式CIDR 通过消除传统的 A、B、C 类网络划分,使用可变长度的子网掩码来定义网络。例如,一个 CIDR 地址如 192.168.100.14/24其中“/24”指示网络部分占前 24 位。\n应用CIDR 使得 IP 地址分配更加灵活,减少了 IP 地址的浪费,是互联网中广泛使用的技术。\n\n路由和交换\n路由原理\n路由是指在网络中转发数据包从源头到目的地的过程。路由原理包括两种主要类型静态路由和动态路由。\n\n静态路由管理员手动配置路由表指定网络中数据包的具体传输路径。适用于小型或稳定的网络环境因为它不会自动适应网络变化。\n动态路由路由器根据当前网络状态自动选择和调整路由路径。它通过使用各种路由协议来实现适合大型或经常变化的网络。\n\n动态路由协议\n\nOSPF开放最短路径优先一种链路状态路由协议通过构建网络的拓扑结构来确定数据包的最短路径。OSPF 可以快速适应网络的变化,适用于大型企业或机构网络。\nBGP边界网关协议一种路径向量路由协议主要用于互联网服务提供商ISP之间的路由决策。它能够处理大规模网络的复杂路由和策略。\n\n交换技术\n交换技术是在数据链路层对网络流量进行管理的技术用于优化网络性能和提高效率。\n\n网络分段通过使用交换机来分隔大型网络从而降低了每个段内的数据拥塞提高了网络的整体性能。\n流量管理交换机根据 MAC 地址表来决定数据包的转发,从而减少了不必要的数据广播,提高了网络的效率。\n\n路由器和交换机配置\n\n基本配置步骤包括设置设备的 IP 地址、子网掩码、默认网关、路由协议和相关的安全配置如访问控制列表ACL和网络地址转换NAT。\n实践和模拟通过使用模拟软件如 Cisco Packet Tracer 或 GNS3或真实设备来进行实践操作可以帮助理解和掌握复杂的网络配置和故障排除技巧。\n\nIP 协议的安全性\n网络攻击类型\n\nIP 欺骗:黑客伪造 IP 地址以模拟另一台设备。这可能导致非授权访问数据泄露或服务拒绝DoS攻击。\nARP 欺骗攻击者伪造地址解析协议ARP消息欺骗网络中的设备导致流量被错误地重定向或网络通信中断。\nSYN 泛洪发送大量半开放的同步SYN请求耗尽服务器资源导致服务拒绝。\nMan-in-the-MiddleMitM攻击攻击者插入到通信双方之间秘密拦截或篡改数据。\n\n防火墙\n\n基础概念网络安全系统用于监控和控制进出网络的流量基于一系列定义的安全规则。\n配置方法定义安全规则来允许或阻止基于 IP 地址、端口号、协议类型等的特定流量。包括有状态和无状态过滤。\n应用实例部署在网络边界如网关用于保护内部网络不受外部威胁。\n\n访问控制列表ACL\n\n功能定义哪些类型的流量可以进入或离开网络用于增强网络安全和控制。\n应用在路由器和交换机上配置 ACL用于过滤流量实现基于 IP、MAC 地址等的访问控制。\n\nVPN虚拟私人网络\n\n概念通过公共网络如互联网创建加密的数据通信隧道用于保护数据传输的隐私和安全。\n配置和应用设置 VPN 协议(如 OpenVPN、IPSec配合安全认证如 SSL/TLS实现。广泛应用于远程办公和跨地域网络连接。\n\n故障排除和性能优化\nWindows 平台\n故障诊断工具\n\n\nPing是用来测试网络连通性的可以通过发送 ICMP (Internet Control Message Protocol) 回显请求给目标主机,并监听回显应答来检测网络连通性。\nping google.com\n\n\nTracert (Trace Route) 用于显示数据包到达目标主机所经过的路径。\ntracert google.com\n\n\nIPConfig 用于查看和刷新 IP 配置,如获取当前的 IP 地址、子网掩码、默认网关等。\nipconfig /all\nipconfig /renew\n\n\nNetstat显示网络连接、路由表、接口统计信息等常用于检查进出端口状态。\nnetstat -an\n\n\nWireshark 抓取和分析网络数据包。\n\n\nPerformance Monitor (PerfMon) 监控系统和网络性能。\n\n\nLinux 平台\n故障诊断工具\n\n\nLinux 下的 ping 和 traceroute 与 Windows 下相似,用于测试网络连通性和显示数据包路径。\nping google.com\ntraceroute google.com\n\n\nip 命令替代用于查看和配置网络接口。\nip addr show\nip link set dev eth0 up\n\n\nss 是 netstat 的现代替代品,用于查看网络连接和端口状态。\nss -tulnp\n\n\nTcpdump用于抓取网络数据包类似于 Wireshark 但是在命令行下运行。\n\n\nNagios 或 Zabbix是网络和系统监控工具用于实时监控和生成性能报告。\n\n\n持续学习与前沿技术\n在网络工程领域持续学习和关注前沿技术是非常重要的。这不仅有助于保持技能的现代性还能确保在快速发展的技术环境中保持竞争力。下面深入探讨一些关键的前沿技术和行业动态。\nIPv6 的发展\nIPv6 的推出主要是为了解决 IPv4 地址耗尽的问题,但它带来的好处远不止于此。\n\n更大的地址空间: IPv6 使用 128 位地址,理论上可以提供 21282128 个独立的网络地址,远远超过 IPv4 的 232232 个地址。这对于物联网 (IoT) 设备快速增长的时代尤为重要,每个设备都需要独立的网络地址。\n改进的路由和自动配置特性: IPv6 提高了路由的效率和灵活性。它支持直接自动配置,减少了网络设置的复杂性,使设备能够自动获得 IP 地址,简化了网络管理。\n安全性增强: IPv6 在设计之初就考虑到了安全问题,它原生支持 IPsec为数据传输提供加密和身份验证而在 IPv4 中,这是一个可选项。\n\nSDN软件定义网络\nSDN 是近年来网络技术领域的一大创新,它改变了传统网络架构的限制,提供了更高效和灵活的网络管理方法。\n\n架构和应用: SDN 的核心思想是将控制层从数据层分离,使网络管理变得更加集中和灵活。这一架构使网络管理员能够通过编程方式控制网络行为,而不是通过手动配置单个设备。\n灵活的网络管理和自动化: SDN 通过提供集中的网络控制功能,使得网络变更、优化和管理变得更加快捷和自动化。例如,网络流量可以根据实时需求自动重路由,以优化性能和资源使用。\n\n行业动态\n了解最新的行业动态对于网络工程师至关重要以下是一些值得关注的领域\n\n5G: 作为下一代移动通信标准5G 不仅提高了数据传输速度,还大大减少了延迟,这对于实时应用如在线游戏、自动驾驶汽车和远程手术等领域将产生深远影响。\n边缘计算: 随着 IoT 设备的增多,数据产生的地点越来越靠近用户,边缘计算通过在数据产生地点附近进行数据处理,可以减少延迟,提高处理速度。\n网络安全趋势: 网络安全是一个持续演进的领域。了解最新的安全趋势,如使用机器学习和人工智能来预测和防御网络攻击,对于保护网络安全至关重要。\n"},"Technology/ComputerNetwork/网络协议/TCP-传输控制协议":{"title":"TCP 传输控制协议","links":[],"tags":["计算机网络/TCP传输控制协议","技术/计算机网络"],"content":"概述\nTCP传输控制协议始于 1970 年代,由 Vint Cerf 和 Bob Kahn 两位 DARPA美国国防高级研究计划局的科学家共同开发。TCP 作为互联网协议套件的核心部分,最初是为了在网络节点之间分享资源而设计的,采用了分组交换技术。\n最初的 TCP 协议在 1974 年由 Vint Cerf、Yogen Dalal 和 Carl Sunshine 提出,并于 1974 年底公布了 RFC 675 文件,这是 TCP 的首次正式规范。TCP 最早是作为一个统一的传输控制程序出现的,后来被分解为模块化的架构,形成了 TCP 和 IP 两个独立的协议。这一过程最终演变成了非正式称呼的 TCP/IP 模型。\nTCP/IP 在 1983 年被采纳为 ARPANET互联网的前身的协议标准标志着 TCP/IP 正式成为互联网的基础。2004 年Vint Cerf 和 Bob Kahn 因其在 TCP/IP 上的基础性工作而获得了图灵奖。\nTCP 作为一种面向连接的协议,其建立连接的过程采用了三次握手机制,确保了连接的可靠性。 它还实现了重传和错误检测机制提高了数据传输的可靠性。与此同时TCP 也提供了网络拥塞避免的机制。TCP 头部通常包含 20 字节大小,用于连接和数据传输的控制信息,后面可以跟随最多 40 字节的额外信息。\n随着互联网的发展TCP 经历了多次更新和改进以适应不断变化的网络环境和需求。总的来说TCP 作为互联网的关键部分,对计算机网络的发展历史产生了深远的影响\nTCP传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议广泛用于互联网上的数据传输。以下是对 TCP 协议的系统全面讲解:\nTCP 核心特性\n\n面向连接 TCP 是一种面向连接的协议,意味着在数据开始传输之前,必须先在发送方和接收方之间建立一个稳定的连接。\n可靠性 TCP 提供可靠的数据传输服务。这是通过序列号、确认应答、数据重传以及校验和机制来实现的。如果数据在传输过程中丢失或出错TCP 将重新发送这些数据。\n流量控制 TCP 使用滑动窗口机制进行流量控制,以防止网络拥堵。这确保了发送方不会超过接收方处理能力的速度发送数据。\n拥塞控制 TCP 实现了拥塞控制算法(如慢启动、拥塞避免、快速恢复和快速重传),以应对网络中的拥塞情况。这些机制有助于动态调整数据传输速率,以避免网络过载。\n三次握手机制 TCP 连接的建立采用三次握手机制SYNSYN-ACKACK确保双方都准备好进行数据传输。\n四次挥手断开连接 TCP 连接的终止是通过四次挥手过程来实现的,确保双方都已完成数据传输并同意关闭连接。\n有序传输 TCP 保证数据按照发送的顺序到达接收端。如果接收到的数据片段不是按顺序的TCP 将重新排序,以确保数据的正确顺序。\n端到端通信 TCP 提供端到端的通信。每个 TCP 连接唯一地被定义为包含源 IP 地址、源端口、目的 IP 地址和目的端口的四元组。\n\nTCP 连接建立和终止\nsequenceDiagram\n participant 客户端\n participant 服务器\n\n Note over 客户端,服务器: TCP连接建立三次握手\n 客户端->>服务器: SYN (初始化连接)\n Note right of 服务器: 服务器接收SYN\n 服务器->>客户端: SYN-ACK (确认SYN)\n Note left of 客户端: 客户端接收SYN-ACK\n 客户端->>服务器: ACK (完成连接建立)\n Note right of 服务器: 连接建立成功\n\n Note over 客户端,服务器: 数据传输\n Note left of 客户端: 客户端发送数据\n Note right of 服务器: 服务器接收并处理数据\n Note right of 服务器: 服务器发送数据\n Note left of 客户端: 客户端接收并处理数据\n\n Note over 客户端,服务器: TCP连接终止四次挥手\n 客户端->>服务器: FIN (请求关闭连接)\n Note right of 服务器: 服务器接收FIN\n 服务器->>客户端: ACK (确认FIN)\n Note left of 客户端: 客户端接收ACK\n Note right of 服务器: 服务器准备关闭\n 服务器->>客户端: FIN (请求关闭连接)\n Note left of 客户端: 客户端接收FIN\n 客户端->>服务器: ACK (确认并关闭连接)\n Note right of 服务器: 连接关闭成功\n\n\nTCP 连接建立(三次握手)\n\nSYN同步\n\n客户端发送一个 SYN同步数据包到服务器并在数据包中指定客户端的初始序列号ISN。这个序列号是随机生成的用于标识传输的数据段。\n这表示客户端希望建立连接并开始序列号计数。\n\n\nSYN-ACK同步确认\n\n服务器接收到 SYN 数据包后,回复一个 SYN-ACK 数据包。这个数据包同时承载着服务器的初始序列号,以及对客户端 SYN 的确认。\n服务器的确认号是客户端序列号加一表示服务器已经准备好接收客户端从该序列号开始的数据。\n\n\nACK确认\n\n客户端收到 SYN-ACK 后,发送一个 ACK 数据包给服务器。这个 ACK 数据包包含客户端对服务器 SYN-ACK 的确认。\n客户端的确认号是服务器序列号加一表示客户端已准备好接收服务器从该序列号开始的数据。\n此时连接建立完成双方可以开始数据传输。\n\n\n\nTCP 连接终止(四次挥手)\n\nFIN结束\n\n当客户端完成数据发送后它发送一个带有 FIN 标志的数据包给服务器,表明客户端已经没有数据要发送了,并希望关闭连接。\n\n\nACK确认\n\n服务器收到 FIN 后,发送一个 ACK 数据包给客户端,确认已经收到客户端的结束请求。\n服务器此时可能还有数据需要发送给客户端。\n\n\n服务器的 FIN\n\n一旦服务器也完成了数据发送它同样发送一个带有 FIN 标志的数据包给客户端,表示希望终止连接。\n\n\n客户端的 ACK\n\n客户端接收服务器的 FIN 后,发送 ACK 来确认收到服务器的结束请求。\n在发送最后一个 ACK 后,客户端会进入 TIME_WAIT 状态,持续一段时间以确保服务器收到了 ACK防止网络延迟造成的数据包丢失。\n\n\n\nTCP 头部结构\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字段名称大小描述源端口16标识发送方的端口号。目的端口16标识接收方的端口号。序列号32数据段的序列号用于保证数据的顺序传输。确认号32确认接收到的数据通常是期望收到的下一个数据段的序列号。数据偏移4指示 TCP 头部的长度以便确定数据内容的起始位置。保留6为将来使用保留的位目前必须设置为 0。标志位6包含多个控制标志如 SYN、ACK、FIN 等,用于控制 TCP 的状态。窗口大小16控制发送方的数据量用于流量控制。校验和16用于错误检测的校验和。紧急指针16当 URG 标志位为 1 时标识紧急数据的结束位置。选项可选可变可选字段用于不同的扩展功能如最大报文段长度MSS、窗口扩大因子等。填充可变确保 TCP 头部长度是 32 位字的整数倍,仅在必要时添加。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n标志位名称描述URG紧急指针当设置为 1 时表示紧急指针字段有效。通常用于传输紧急数据。ACK确认应答当设置为 1 时,表示确认号字段有效。几乎所有的 TCP 包除了最初的 SYN 包都会设置这个标志。PSH推送函数当设置为 1 时建议接收方应尽快将这个报文段交给应用层而不是等缓冲区满了再发送。RST复位当设置为 1 时表示连接中出现严重错误如因主机崩溃或其他原因必须释放连接然后重新建立传输。SYN同步序列号在连接建立时用来同步序列号。当一个端点希望建立连接时SYN 标志被设置为 1。FIN结束当设置为 1 时,表示发送端没有数据再发送,即希望结束连接。\n数据传输\n\n序列号和确认号序列号用于标识从 TCP 源端向目的端发送的数据字节流的每一个字节,确保数据的有序传递。确认号用于确认收到的数据,并且请求下一个预期的序列号,从而实现对丢失数据的重传。\n数据分段和重组TCP 将较大的数据块分割成更小的段进行传输,这样做可以提高网络的效率和可靠性。接收端负责将这些小段按照序列号重新组装成原始数据。\n可靠传输机制TCP 通过使用校验和、序列号、确认应答以及超时重传等机制,确保数据完整性和可靠性。\n\n流量控制\n\n滑动窗口机制滑动窗口是一种流量控制技术它允许发送方根据接收方的处理能力和缓冲区大小调整其发送速率从而避免接收方被过量数据淹没。\n窗口更新TCP 通过不断调整窗口大小(即可发送或接收的数据量)来适应网络条件和接收端的处理能力。\n阻塞控制在接收端缓冲区满时它会通过设置窗口大小为零来通知发送端停止发送数据直到缓冲区有足够的空间再次接收数据。\n\n拥塞控制\n\n慢启动和拥塞避免TCP 通过慢启动算法开始传输过程,逐渐增加拥塞窗口的大小来探测网络容量。当达到一个阈值后,便转换到拥塞避免阶段,这时窗口的增长会变得更加保守。\n快速重传和快速恢复在发生丢包时TCP 通过快速重传机制重新发送丢失的包,而不是等待超时重传计时器的到期。快速恢复算法则是在检测到丢包后调整拥塞窗口和阈值,以快速恢复正常的传输速率。\n拥塞窗口拥塞窗口大小是根据网络的拥塞程度动态调整的以控制在任一时刻发送到网络上的数据量从而减少整体网络的拥塞。\n\nTCP 与 UDP 的比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性/协议TCPUDP类型面向连接的协议无连接的协议可靠性可靠保证数据正确传输不可靠无法保证数据的正确传输连接建立需要三次握手建立连接无需建立连接直接发送数据速度/效率相对较慢因为要求确认和错误恢复较快适用于对实时性要求高的应用数据传输方式字节流数据报顺序传递保证是保证数据按顺序到达否拥塞控制有如慢启动、拥塞避免无流量控制有使用滑动窗口机制无头部开销较大20 字节最小较小8 字节最小)用途示例网页浏览、文件传输、电子邮件等实时视频会议、在线游戏、语音通话等错误检测和修正有(通过序列号和确认应答)有错误检测,但无修正(只有校验和)数据包排序自动重新排序乱序到达的数据包不对数据包进行排序实时性适用于对可靠性要求高的场景适用于对实时性要求高的场景\n应用场景\nTCP 广泛应用于需要可靠数据传输的场景,如 Web 浏览HTTP/HTTPS、文件传输FTP、电子邮件SMTP、IMAP、POP3等。\nTCP 协议的设计使其成为互联网中最可靠的数据传输协议之一,适用于大多数需要高可靠性的网络应用。虽然在某些方面(如实时性和传输效率)可能不如 UDP但其稳定和可靠的特性使其在网络通信中占有极其重要的地位。"},"Technology/ComputerNetwork/网络协议/UDP-用户数据报协议":{"title":"UDP 用户数据报协议","links":[],"tags":["计算机网络/UDP用户数据报协议","技术/计算机网络"],"content":"概述\nUDP用户数据报协议是一种无连接的网络协议由 David P. Reed 设计并于 1980 年在 RFC 768 中首次描述。它是互联网协议套件的一部分,与 TCP 同属于传输层协议,但相较于 TCPUDP 的设计更为简单,提供更快的数据传输速度。\nUDP用户数据报协议是一种无连接的网络协议由 David P. Reed 设计并于 1980 年在 RFC 768 中首次描述。它是互联网协议套件的一部分,与 TCP 同属于传输层协议,但相较于 TCPUDP 的设计更为简单,提供更快的数据传输速度。\n**UDP 的主要特点是它不像 TCP 那样提供可靠性保证。UDP 不进行连接建立,不保证数据包的顺序,也不检测重复或丢失的数据包。**这意味着它能够提供更高效的数据传输服务,尤其适用于那些可以容忍一定数据丢失但对实时性要求较高的应用,如视频会议、实时多人游戏和语音传输。\n尽管 UDP 本身在设计上保持不变,但在其基础上开发了许多其他协议来增强功能或满足特定需求,例如 RTP实时传输协议和 QUIC快速 UDP 互联网连接)。后者结合了 TCP 和 UDP 的优点,并增加了加密功能。\n在安全性方面UDP 由于其简单性,可能容易受到网络攻击,如洪水攻击和反射攻击。因此,通常需要额外的安全措施,比如使用防火墙和入侵检测系统来保护基于 UDP 的应用。\n总体而言UDP 由于其低延迟和高效率的特点,在现代互联网通信中仍然扮演着关键角色,并且随着新技术和新应用的发展,它可能会继续演化以适应未来的网络环境和需求。\nUDP 基本特性\n\n无连接性UDP 是无连接的,意味着在数据传输前不需要建立连接。这减少了建立和维护连接的开销,使得数据传输更为迅速。\n轻量级协议UDP 头部开销小,只有 8 字节,相较于 TCP这使得 UDP 在网络传输中更高效,特别是对于小数据包的传输。\n快速传输由于无连接和低开销的特点UDP 能够提供快速的数据传输服务。这对于实时应用(如实时视频流、在线游戏或语音通话)来说非常重要。\n不保证可靠性UDP 不提供数据包的到达确认、顺序保证或重传机制,因此它可能不适合那些需要高可靠性的应用。\n无流量控制和拥塞控制UDP 不进行流量控制和拥塞控制,这意味着在网络条件不佳时,它可能会导致数据丢失。\n支持广播和多播UDP 支持向多个目的地发送数据包,这使得它适用于需要广播或多播功能的应用,如某些类型的网络服务和实时数据传输。\n错误检测尽管 UDP 不保证数据传输的完整性,但它通过校验和提供了基本的错误检测功能,可以识别数据在传输过程中的错误。\n应用层控制更多由于 UDP 本身的功能较少,许多控制机制(如重传策略、数据排序等)需要由应用层实现。这为应用程序开发人员提供了更大的灵活性。\n\nUDP 头部结构\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字段名称大小字节描述源端口2表示发送端的端口号。如果发送端是客户端这通常是一个临时端口。目的端口2表示接收端的端口号。这告诉系统哪个应用程序应该接收进来的 UDP 数据包。长度2指的是 UDP 头部和数据总共的长度(以字节为单位)。最小值为 8仅头部。校验和2用于错误检测。它计算整个 UDP 数据包(包括伪头部、头部和数据)的校验和。\n数据传输\nsequenceDiagram\n participant 客户端\n participant 服务器\n\n Note over 客户端,服务器: UDP数据传输开始\n 客户端->>服务器: UDP数据包(源端口 -> 目的端口)\n Note right of 服务器: 服务器处理数据包\n 服务器->>客户端: UDP响应数据包(源端口 -> 目的端口)\n Note left of 客户端: 客户端处理响应数据包\n Note over 客户端,服务器: UDP数据传输结束\n\n应用场景\n\n实时应用例如在线游戏、实时视频会议等这些应用更注重速度而非数据的绝对完整性。\n简单查询如 DNS 查询通常使用 UDP因为它需要快速获得响应。\n广播和多播UDP 支持广播和多播传输。\n\nTCP 与 UDP 的比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性/协议TCPUDP类型面向连接的协议无连接的协议可靠性可靠保证数据正确传输不可靠无法保证数据的正确传输连接建立需要三次握手建立连接无需建立连接直接发送数据速度/效率相对较慢因为要求确认和错误恢复较快适用于对实时性要求高的应用数据传输方式字节流数据报顺序传递保证是保证数据按顺序到达否拥塞控制有如慢启动、拥塞避免无流量控制有使用滑动窗口机制无头部开销较大20 字节最小较小8 字节最小)用途示例网页浏览、文件传输、电子邮件等实时视频会议、在线游戏、语音通话等错误检测和修正有(通过序列号和确认应答)有错误检测,但无修正(只有校验和)数据包排序自动重新排序乱序到达的数据包不对数据包进行排序实时性适用于对可靠性要求高的场景适用于对实时性要求高的场景\n使用场景和限制\n虽然 UDP 提供了更快的数据传输速度,但缺乏 TCP 的许多关键特性,如可靠性和数据顺序保证。因此,在选择 UDP 时,需要考虑应用对数据传输质量的具体要求。\n总结来说UDP 以其简单和高效的特点适用于那些对实时性有较高要求但对数据丢失相对宽容的场景。在设计网络应用或服务时,正确选择 TCP 或 UDP 协议非常关键,这取决于应用的具体需求和特性。"},"Technology/ComputerNetwork/网络基础/网络基础":{"title":"网络基础","links":[],"tags":["计算机网络/网络基础","技术/计算机网络"],"content":"网络概述\n互联网是一个由全球各种计算机网络相互连接而成的大型网络可以让人们在任何时间、任何地点连接并交换信息。它是人类历史上最重要的信息革命之一对人们的生活、工作和学习都产生了深远的影响。\n互联网的发展历史可以追溯到 20 世纪 60 年代初,当时美国国防部研究项目 ARPA高级研究计划署为了解决军用计算机之间的信息共享问题开发了一种名为 ARPANET 的计算机网络。在此基础上,随着互联网技术的不断发展,越来越多的计算机网络加入了互联网,并形成了现在的全球互联网。\n\n20 世纪 60 年代美国国防部高级研究计划局ARPA开展研究设计出了一种分组交换网络的方案称为 ARPANET。\n20 世纪 70 年代ARPANET 逐渐扩展到美国各地的大学和研究机构,并且开始出现了电子邮件和文件传输等应用。\n20 世纪 80 年代TCP/IP 协议成为互联网的标准协议,互联网的规模进一步扩大,并且开始商业化运营。\n20 世纪 90 年代Web 浏览器的出现,使得互联网的应用变得更加易用和普及,互联网的用户数量开始飞速增长。\n21 世纪以后:互联网的规模继续扩大,出现了移动互联网、云计算、大数据等新技术,互联网的应用也从简单的信息传递演变成了涵盖生活、工作、学习等方方面面的综合性平台。\n\n互联网实现的关键在于互联网协议族Internet Protocol Suite通常称为 TCP/IP 协议。TCP/IP 协议提供了一种标准化的方法来在不同的计算机之间进行通信。它由两个协议组成:\n\n传输控制协议TCP负责将数据包分解成若干个小数据包并在接收端重新组装。\n互联网协议IP负责将数据包从一个网络传输到另一个网络。\n\n在互联网中每个设备都被分配了一个唯一的 IP 地址,用于标识该设备在网络中的位置。当设备发送数据包时,它会将数据包传送到本地网络上的路由器,然后路由器会根据 IP 地址将数据包传送到目标设备所在的网络上的路由器,直到数据包到达目标设备。\nOSI开放式系统互联模型\n\ngraph TD;\n subgraph 数据传输路径\n A2(主机A应用层) -- HTTP请求 --> A3(主机A传输层);\n A3 -- TCP连接 --> A4(主机A网络层);\n A4 -- IP数据报 --> A5(主机A数据链路层);\n A5 -- 以太网帧 --> R1(路由器A数据链路层);\n R3(路由器A应用层) -- HTTP请求 --> R4(路由器A传输层);\n R4 -- TCP连接 --> R5(路由器A网络层);\n R5 -- IP数据报 --> R6(路由器A数据链路层);\n R6 -- 以太网帧 --> R1;\n R7((路由器 A)) --- R3;\n R7 -- 路由 --> R12((路由器 B));\n R8(路由器B应用层) -- HTTP响应 --> R9(路由器B传输层);\n R9 -- TCP连接 --> R10(路由器B网络层);\n R10 -- IP数据报 --> R11(路由器B数据链路层);\n R11 -- 以太网帧 --> R2(路由器B数据链路层);\n R12 --- R8;\n B2(主机B应用层) -- HTTP响应 --> B3(主机B传输层);\n B3 -- TCP连接 --> B4(主机B网络层);\n B4 -- IP数据报 --> B5(主机B数据链路层);\n B5 -- 以太网帧 --> R2;\n end\n\nOSI开放式系统互联模型是一个概念性的框架用于理解和设计网络协议的架构。这个模型由国际标准化组织ISO在 1984 年发布,将网络通信分为七个抽象层,每层负责不同的网络功能。下面是对 OSI 七层协议的系统性解释:\n1. 物理层Physical Layer\n\n功能负责在物理媒介上传输原始的比特流。这涉及到数据的物理连接、电压水平、数据传输速率和物理连接的激活与维护。\n设备例如网线、光纤、中继器、集线器等。\n\n2. 数据链路层Data Link Layer\n\n功能在两个相邻节点之间的物理链路上提供可靠的数据传输。它负责帧同步、错误检测和修正、流量控制和帧序列化。\n设备例如网桥、交换机等。\n\n3. 网络层Network Layer\n\n功能负责在多个网络之间建立、维护和终止连接。它处理数据包的路由选择和转发。\n协议例如 IPInternet Protocol、ICMPInternet Control Message Protocol等。\n\n4. 传输层Transport Layer\n\n功能为端到端的通信提供服务。它负责数据的分割、传输、错误检测和恢复。\n协议例如 TCPTransmission Control Protocol、UDPUser Datagram Protocol等。\n\n5. 会话层Session Layer\n\n功能管理和控制两个网络节点之间的会话连接负责建立、管理和断开会话。\n应用例如 API、Socket 编程等。\n\n6. 表示层Presentation Layer\n\n功能确保从一个节点发送的数据可以被另一个节点的应用层读取和理解。它负责数据格式转换、数据加密和解密、数据压缩等。\n例子ASCII、JPEG、MPEG 等数据格式。\n\n7. 应用层Application Layer\n\n功能提供网络服务给最终用户的应用程序。它定义了用于与网络服务交互的各种协议。\n协议和服务例如 HTTPHyperText Transfer Protocol、FTPFile Transfer Protocol、电子邮件、远程登录等。\n\n网络协议\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nOSI 模型层级功能协议/设备应用层Application提供高级服务例如文件传输、电子邮件和虚拟终端HTTP、SMTP、FTP、SSH表示层Presentation将数据转换为网络标准格式SSL/TLS、JPEG、ASCII会话层Session管理连接、交换数据NetBIOS、RPC、SSH传输层Transport提供端到端的可靠数据传输TCP、UDP网络层Network处理分组在网络中的传输与路由IP、ICMP、OSPF、BGP数据链路层Data Link处理帧在网络中的传输和检错Ethernet、Wi-Fi、HDLC物理层Physical处理比特流在物理媒介中的传输RJ45、Fiber、802.11\n应用层协议\nSSH\nSSH (Secure Shell) 是一种加密的网络协议,用于在不安全的网络上安全地运行命令行 shell。SSH 通常用于远程登录到远程计算机或服务器,并提供文件传输和加密会话功能。\nFTP\nFTP (File Transfer Protocol) 是一种标准的文件传输协议用于在网络上传输文件。FTP 在 TCP/IP 协议中的传输层上运行,支持两种工作模式:主动模式和被动模式。\nSMTP\nSMTP (Simple Mail Transfer Protocol) 是一种在计算机网络上发送和接收电子邮件的协议。SMTP 定义了电子邮件如何通过网络传输的标准。SMTP 服务器负责接收和发送邮件。\nHTTP\nHTTP (Hypertext Transfer Protocol) 是一种用于在计算机网络上传输超文本文档的协议。HTTP 是万维网的基础协议,支持 Web 浏览器和 Web 服务器之间的通信。\nDNS\nDNS (Domain Name System) 是一种将域名映射到 IP 地址的分布式命名系统。DNS 是在互联网上执行名称解析的基本协议,使用户可以使用易于记忆的域名来访问网络资源。\n传输层协议\nTCP\nTCP (Transmission Control Protocol) 是一种面向连接的协议用于在网络上可靠地传输数据。TCP 保证传输的数据的可靠性,使用三次握手来建立连接,四次握手来终止连接。\nUDP\nUDP (User Datagram Protocol) 是一种面向无连接的协议用于在网络上传输数据包。UDP 不保证数据的可靠性,因此常用于传输实时数据,如音频和视频。\n网络层协议\nIPv4\nIPv4 (Internet Protocol version 4) 是一种网络层协议用于在网络上传输数据。IPv4 定义了 IP 地址的格式和分配方式,并为互联网上的每个设备分配唯一的 IP 地址。\nIPv6\nIPv6 (Internet Protocol version 6) 是 IPv4 的下一代协议用于在网络上传输数据。IPv6 地址长度更长,提供更多的地址空间,并支持更多的协议选项,使网络更加灵活和可扩展。\nICMP\nICMP (Internet Control Message Protocol) 是一种在网络上传输控制消息的协议。ICMP 用于发送诊断信息,如 ping 和 traceroute 命令所使用的信息。\n数据链路层与物理层协议\nEthernet\nEthernet 是一种常用的局域网技术,其物理层使用双绞线或光纤传输数据,数据链路层采用 CSMA/CD 技术实现多个设备共享网络资源。Ethernet 还定义了 MAC 地址格式、帧格式等标准,是 TCP/IP 协议族的重要组成部分。\nWi-Fi\nWi-Fi 是一种基于无线电波的局域网技术采用无线信号传输数据常用于家庭和公共场所的无线网络。Wi-Fi 还定义了各种标准,如 802.11b、802.11g、802.11n 等,以支持不同的无线传输速率和距离要求。\nBluetooth\nBluetooth 是一种短距离无线通信技术通常用于连接手机、平板电脑、耳机、键盘等设备。Bluetooth 定义了自己的物理层和数据链路层协议,使用频段为 2.4GHz。\n路由协议\nRIP\nRIPRouting Information Protocol是一种基于距离向量的内部网关协议IGP用于在小型网络中选择最佳路由。RIP 协议采用 Hop Count 作为路径计算标准,当路由表中某个目的地址的距离超过 15 个跳时,该地址将被认为是不可达的。\nOSPF\nOSPFOpen Shortest Path First是一种基于链路状态的内部网关协议IGP用于在大型网络中选择最佳路由。OSPF 协议将网络划分为多个区域每个区域拥有自己的链路状态数据库LSDB可以实现快速收敛和路由分级。\nBGP\nBGPBorder Gateway Protocol是一种外部网关协议EGP用于在不同自治系统之间交换路由信息。BGP 协议可以实现路由的动态学习和选择支持多路径和路由策略等功能。BGP 是互联网核心路由器之间的主要协议。\nIS-IS\nIS-ISIntermediate System to Intermediate System是一种基于链路状态的内部网关协议IGP用于在大型网络中选择最佳路由。IS-IS 协议类似于 OSPF 协议但使用的是双向链路可以提供更高效的路由选择。IS-IS 协议常用于 ISP 内部网络和数据中心网络。\n网络设备\n\n\n网络设备是用于组建计算机网络的硬件。它们用于确保数据在网络中的正确传输并在不同设备之间建立连接。以下是一些常见的网络设备及其功能\n路由器Router\n路由器是用于在网络中转发数据包的设备它根据数据包的目的地和网络的拓扑结构来决定数据包应当沿哪条路径传输。路由器连接多个网络并在这些网络之间传输数据从而实现网络互联。此外路由器还可以执行网络地址转换NAT以及其他网络层功能以确保数据包的安全传输。\n交换机Switch\n交换机用于连接网络中的设备并在它们之间传输数据。交换机通过存储和转发机制将数据包发送到目标设备。与集线器相比交换机具有更高的效率因为它只将数据包发送到目标设备而不是广播到所有连接的设备。\n无线接入点Wireless Access PointWAP\n无线接入点是用于将有线网络扩展到无线网络的设备。WAP 在有线网络与无线网络设备之间建立一个桥接,允许无线设备通过无线信号与有线网络通信。它们通常用于扩展网络覆盖范围,提高无线设备的连接性能。\n网络集线器Hub\n网络集线器是一种基本的网络设备用于连接多台计算机或其他网络设备。集线器接收来自一个设备的数据包然后将其广播到所有连接的设备。然而由于这种广播方式网络集线器在大型网络中效率较低容易导致网络拥堵。\n网络防火墙Firewall\n网络防火墙是一种用于保护网络安全的设备它可以阻止未经授权的访问和数据包的传输。防火墙可以在硬件和软件层面实现通过检查传入和传出的数据包确定它们是否符合特定的安全规则。防火墙有助于保护网络中的设备免受恶意软件和攻击的侵害。\nVPN 网关VPN Gateway\nVPN 网关是一种用于实现虚拟专用网络VPN的设备。它允许远程用户通过加密的通道访问内部网络资源从而提高数据安全性。VPN 网关可以实现企业内部资源的安全共享,以及保护远程办公用户的数据安全。\n网络拓扑\n\n\n总线拓扑所有设备都连接到一条公共总线上每个设备可以发送和接收数据包总线会将数据包广播给所有设备。\n星型拓扑所有设备都连接到一个集线器或交换机中心设备负责转发和分配数据包。\n环型拓扑所有设备连接成一个环形链路数据包沿着环形链路进行传输每个设备负责将数据包从一个端口传递到另一个端口。\n树型拓扑将多个星型拓扑连接起来形成一个树状结构中心节点可以是一个路由器或交换机每个子节点连接到中心节点。\n网状拓扑所有设备之间都可以直接相互连接没有中心节点数据包可以通过多条路径进行传输具有高度的冗余和可靠性。\n混合拓扑不同拓扑结构的组合如星型 - 总线拓扑、星型 - 环型拓扑等。\n\n网络服务\nWeb 服务\nApache\nApacheApache HTTP Server是一个开源的 Web 服务器软件。它由 Apache 软件基金会 维护,起源于 1995 年。Apache 支持多种操作系统,如 Linux、Unix、Windows 等。Apache 使用模块化的架构,可以通过安装和配置不同的模块来扩展其功能。\nApache 适用于各种规模的网站和应用;未来方向将继续优化性能,提高安全性,支持新的 Web 技术和标准。\nNginx\nNginx 是一个轻量级的 Web 服务器、反向代理服务器和电子邮件代理服务器。起源于 2002 年其设计目标是提供高性能、高并发和低内存占用。Nginx 在处理静态资源、负载均衡和反向代理等方面表现出色。\nNginx 适用于高并发、高流量的网站和应用,以及作为反向代理和负载均衡器。\nIIS\nIISInternet Information Services是微软推出的 Web 服务器软件,起源于 1995 年。IIS 只支持 Windows 操作系统。IIS 支持 ASP.NET、PHP 等多种语言,并且可以通过模块扩展其功能。\nIIS 适用于依赖于 Windows 平台和 Microsoft 技术的网站和应用。\nDHCP 服务\nISC DHCP\nISC DHCPInternet Systems Consortium Dynamic Host Configuration Protocol是一款开源的、广泛使用的 DHCP 服务器软件,起源于 1999 年。它支持 IPv4 和 IPv6 地址分配,适用于各种规模的网络环境。\nISC DHCP 适用于需要稳定可靠的 DHCP 服务的企业和数据中心。未来将继续优化性能,提高稳定性和安全性,增加新功能。\nDnsmasq\ndnsmasq 是一个轻量级的 DHCP 和 DNS 服务软件,起源于 2000 年。它的设计目标是为小型网络提供简单易用的服务。dnsmasq 支持 IPv4 和 IPv6 地址分配,以及 DNS 缓存功能。\ndnsmasq 适用于家庭、小型企业和实验室等小型网络环境。未来将继续保持轻量级特点,优化性能,增加新功能。\nDNS 服务\nBIND\nBINDBerkeley Internet Name Domain是一款开源的 DNS 服务器软件,起源于 1980 年代。它是目前最广泛使用的 DNS 服务器软件,支持各种操作系统,如 Linux、Unix、Windows 等。\nBIND 适用于需要完整功能的 DNS 服务的企业和数据中心。\nUnbound\nUnbound 是一个开源的、专注于安全和高性能的 DNS 服务器软件,起源于 2004 年。它采用了模块化的设计,支持 DNSSEC 和其他安全相关功能。\nUnbound 适用于需要高性能和安全的 DNS 服务的企业和数据中心。\nPowerDNS\nPowerDNS 是一个开源的、功能强大的 DNS 服务器软件,起源于 2000 年。它支持多种后端数据库,如 MySQL、PostgreSQL、SQLite 等。PowerDNS 提供了灵活的 API方便进行二次开发和集成。\nPowerDNS 适用于需要与数据库集成、自定义开发和高度可配置的 DNS 服务的企业和数据中心。\nNTP 服务\nChrony\nChrony 是一个开源的 NTPNetwork Time Protocol服务器和客户端软件起源于 1997 年。它具有高度可配置的特点,可以在各种网络环境中提供精确的时间同步服务。\nChrony 适用于需要精确时间同步服务的企业、数据中心和科研机构。\nNTPd\nNTPdNetwork Time Protocol daemon是一款开源的 NTP 服务器和客户端软件,起源于 1985 年。它广泛应用于各种规模的网络环境,支持各种操作系统。\nNTPd 适用于各种规模的网络环境,需要可靠的时间同步服务。\nVPN 服务\nOpenVPN\nOpenVPN 是一个开源的 VPNVirtual Private Network软件起源于 2001 年。它基于 SSL/TLS 协议,提供安全稳定的远程访问和站点间连接功能。\nOpenVPN 适用于需要安全远程访问和站点间连接的企业和个人用户。\nIPSec\nIPSecInternet Protocol Security是一组用于保护 IP 数据包的协议,起源于 1990 年代。IPSec 提供了认证、完整性和加密功能,广泛应用于 VPN 场景。\nIPSec 适用于需要安全通信和网络互联的企业和数据中心。\nWireGuard\nWireGuard 是一个简单、高性能的 VPN 软件,起源于 2016 年。它使用现代加密技术,具有易于配置和部署的特点。\nWireGuard 适用于需要简单易用、高性能 VPN 的企业和个人用户。\n负载均衡\nHAProxy\nHAProxyHigh Availability Proxy是一个开源的、高性能的负载均衡软件起源于 2000 年。它可以用于分发 TCP 和 HTTP 流量,广泛应用于大型网站和云计算环境。\nHAProxy 适用于需要高性能、高可用性负载均衡服务的大型网站和云计算环境。\nLVS\nLVSLinux Virtual Server是一个开源的、基于 Linux 内核的负载均衡软件,起源于 1998 年。它支持 TCP 和 UDP 协议,可以用于分发各种网络服务。\nLVS 适用于需要高性能、高可用性负载均衡服务的大型网站和数据中心。\n文件共享服务\nSamba\nSamba 是一个开源的文件共享服务软件,起源于 1992 年。它允许在不同操作系统(如 Linux、Windows 和 macOS之间共享文件和打印机。\nSamba 适用于需要在不同操作系统之间共享文件和打印机的企业和家庭网络环境。\nNFS\nNFSNetwork File System是一种分布式文件系统协议起源于 1984 年。它允许在 UNIX/Linux 系统之间共享文件。\nNFS 适用于需要在 UNIX/Linux 系统之间共享文件的企业和数据中心。\nSFTP\nSFTPSSH File Transfer Protocol是一种基于 SSH 协议的文件传输协议,起源于 1990 年代。它提供安全的、加密的文件传输服务。\nSFTP 适用于需要安全传输文件的企业和个人用户。\n邮件服务\nPostfix\nPostfix 是一个开源的邮件传输代理MTA起源于 1997 年。它用于接收、路由和发送电子邮件。\nPostfix 适用于需要高性能、可靠的邮件传输服务的企业和数据中心。\nSendmail\nSendmail 是一个经典的邮件传输代理MTA起源于 1981 年。它用于接收、路由和发送电子邮件。\nSendmail 适用于需要灵活、可定制的邮件传输服务的企业和数据中心。\nDovecot\nDovecot 是一个开源的邮件传输代理MTA起源于 2002 年。它主要用于提供邮件接收和存储服务。\nDovecot 适用于需要高性能、可靠的邮件接收和存储服务的企业和数据中心。\nExim\nExim 是一个开源的邮件传输代理MTA起源于 1995 年。它用于接收、路由和发送电子邮件。\nExim 适用于需要灵活、可定制的邮件传输服务的企业和数据中心。"},"Technology/ComputerSecurity/信息安全/OpenPGP/GnuPG-简明指南":{"title":"GnuPG 简明指南","links":[],"tags":["计算机安全/信息安全","技术/计算机安全"],"content":"简介\nGnuPGGNU Privacy GuardGPG是一款开源软件用于非对称加密。它是满足 GPL 协议的 PGPPretty Good Privacy加密软件实现。GnuPG 依照由 IETF 制定的 OpenPGP 技术标准设计用于加密、数字签章及产生非对称密钥对。GPG 与 PGP 功能兼容。\n如果你想发送加密信息首先你需要得到接收者的公钥然后通过该公钥对信息进行加密传输接收者使用私钥就可解密并读取文件。同时你也可以在公共网络用数字签章表明身份和安全性。\nGPG\n安装\n在 Linux 系统中GnuPG 通常已经被默认安装。在 Windows 和 macOS 系统中,你可以从 GnuPG 官方网站 下载安装。\n配置\n~/.gnupg - GPG 配置目录\n~/.gnupg/gpg.conf GPG 配置文件\n~/.gnupg/trustdb.gpg GPG 信任库,用于存储你信任的其他 GPG 密钥\n~/.gnupg/pubring.gpg GPG 公钥库,用于存储你的公钥和他人的公钥\n~/.gnupg/secring.gpg GPG 私钥库,用于存储你的私钥\n生成密钥\n# 正常模式\ngpg --gen-key\n \n# 专家模式\ngpg --expert --full-gen-key\n1.请选择您要使用的密钥种类:\n (1) RSA and RSA (default)\n (2) DSA and Elgamal\n (3) DSA (仅用于签名)\n (4) RSA (仅用于签名)\n您的选择 1\n \n2.RSA 密钥长度应在 1024 位与 4096 位之间。\n您想要用多大的密钥尺寸(2048)4096\n您所要求的密钥尺寸是 4096 位\n请设定这把密钥的有效期限。\n 0 = 密钥永不过期\n <n> = 密钥在 n 天后过期\n <n>w = 密钥在 n 周后过期\n <n>m = 密钥在 n 月后过期\n <n>y = 密钥在 n 年后过期\n密钥的有效期限是(0) 0\n密钥永远不会过期\n以上正确吗(y/n)y\n \n \n3. You need a user ID to identify your key; the software constructs the user ID\nfrom the Real Name, Comment and Email Address in this form:\n "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"\n \n真实姓名zhouzhongping\n电子邮件地址zhouzhongping@7wate.com\n注释测试使用\n您正在使用utf-8字符集。\n您选定了这个用户标识\n “zhouzhongping (测试使用) <zhouzhongping@7wate.com>”\n \n4.更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)o\n \n5.您需要一个密码来保护您的私钥。\n \n我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动\n鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。\n常用命令\n查看\n# 查看公钥\ngpg --list-keys\ngpg -k\n \n# 查看私钥\ngpg --list-secret-keys\ngpg -K\n编辑\n# 编辑密钥页面\ngpg --edit-key [密钥ID]\nGPG 以下命令需要进入编辑密钥页面。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例quit退出此菜单无需示例直接输入 quit 即可save保存并退出无需示例直接输入 save 即可help显示此帮助无需示例直接输入 help 即可fpr显示密钥指纹fprlist列出密钥和用户标识listuid选择用户标识 Nuid 1key选择子密钥 Nkey 1check检查签名checksign为所选用户标识添加签名uid 1, 然后 signlsign为所选用户标识添加本地签名uid 1, 然后 lsigntsign为所选用户标识添加信任签名uid 1, 然后 tsignadduid增加一个用户标识adduid, 然后按提示操作deluid删除选定的用户标识uid 1, 然后 deluidaddkey增加一个子密钥addkey, 然后按提示操作delkey删除选定的子密钥key 1, 然后 delkeyexpire变更密钥或所选子密钥的使用期限key 1, 然后 expire, 接着按提示输入新的到期日passwd变更密码passwd, 然后按提示输入新密码trust变更信任度trust, 然后按提示选择新的信任级别revsig吊销所选用户标识上的签名uid 1, 然后 revsigrevuid吊销选定的用户标识uid 1, 然后 revuidrevkey吊销密钥或选定的子密钥key 1, 然后 revkeyenable启用密钥enabledisable禁用密钥disableclean压缩不可用的用户标识并从密钥上移除不可用的签名cleanminimize压缩不可用的用户标识并从密钥上移除所有签名minimize\n导出\n# 导出公钥\ngpg --armor --output public-key.txt --export [密钥ID]\n \n# 导出私钥\ngpg --armor --output private-key.txt --export-secret-keys [密钥ID]\n在这里--armor 选项会生成.asc 后缀的 ASCII 类型的文本文件,如果不使用该选项,则会生成.gpg 后缀的二进制文件。\n导入\n# 从本地文件导入密钥\ngpg --import [密钥文件]\n \n# 从服务器导入密钥\ngpg --keyserver [服务器] --search-keys [用户ID]\n公布\n# 将密钥发布到公开服务器\ngpg --send-keys [密钥ID] --keyserver [服务器]\n \n# 发布用户指纹\ngpg --fingerprint [密钥ID]\n删除\n# 删除指定公钥\ngpg --delete-key [密钥ID]\n \n# 删除指定私钥\ngpg --delete-secret-keys [密钥ID]\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令选项描述示例—list-keys列出所有的密钥gpg --list-keys—gen-key生成新的密钥对gpg --gen-key—delete-key删除密钥gpg --delete-key [key-id]—import导入密钥gpg --import [key-file]—export导出公钥gpg --export -a "User Name" > public.key—armor创建 ASCII 字符格式的输出用于在邮件等场合gpg --armor --export [key-id]—encrypt加密文件gpg --encrypt --recipient [key-id] [file]—decrypt解密文件gpg --decrypt [file]—sign生成只有你自己可以识别的签名文件gpg --sign [file]—verify验证签名文件gpg --verify [file]—edit-key编辑密钥的详细设置例如添加/删除别名、设置过期时间等gpg --edit-key [key-id]—send-keys将密钥发送到 keyservergpg --send-keys [key-id]—recv-keys从 keyserver 接收密钥gpg --recv-keys [key-id]—refresh-keys从 keyserver 更新所有密钥的信息gpg --refresh-keys—full-generate-key使用全面设置来生成新的密钥对gpg --full-generate-key—quick-add-uid快速添加新的用户 ID 到现有的密钥gpg --quick-add-uid [key-id] [User ID]—change-passphrase改变密钥的保护密码gpg --change-passphrase [key-id]\n加密和解密\n# 加密文件\ngpg --recipient [密钥ID] --output demo.en.txt --encrypt demo.txt\n \n# 解密文件\ngpg --decrypt demo.en.txt --output demo.de.txt\ngpg demo.en.txt\n \n# 签名文件GPG格式\ngpg --sign test.txt\n \n# 签名文件ASCII格式\ngpg --clearsign test.txt\n \n# 生成单独签名\n# -a 选项会生成 ASCII 格式的签名\ngpg -a --detach-sign test.txt\n \n# 验证签名\ngpg --verify test.txt.asc test.txt"},"Technology/ComputerSecurity/密码学/简明指南":{"title":"简明指南","links":[],"tags":["计算机安全/密码学","技术/计算机安全"],"content":"这篇文章不涉及密码学的数学原理,只提及相关概念和应用\n概念\n\n\n古典密码 基于字符的替换或移项,或者两者混合使用。\n\n\n现代密码 使用计算机技术的,在比特和字节上操作。\n\n\n明文 = 在密码学中是指传送方想要接收方获得的可读信息\n\n\n密文 = 经过加密的明文\n\n\n加密 = 把明文转换为密文的过程\n\n\n解密 = 把密文转换为明文的过程\n\n\n密钥 = 指某个用来完成加密、解密、完整性验证等密码学应用的秘密信息\n\n\n密码 约等于 密钥\n\n\nHash = 哈希,又被翻译为 离散\n\n按照不同的语境可以理解为的 哈希值hash value 或 哈希函数hash function\n哈希值就是指一段信息经过哈希函数处理后输出的值\n哈希函数无法逆向演算回原本的数值\n对于大多数情况下哈希值不一样原本的值也不一样\n\nmd5 和 sha-1 都存在哈希冲突的情况,就是哈希值一样但原本的值不一样\n\n\n这是一些常见的哈希函数\n\nmd5\nsha-1\nsha-256\nsha-512\n\n\n\n\n\n数字摘要 = 一段信息的哈希值,一般情况下是指明文的哈希值\n\n\nMD = 消息摘要 (Message Digest) ,就是数字摘要\n\n\nMAC = 消息验证码 (Message Authentication Code) ,就是明文 + 密钥 + MAC 算法生成的一段数据这里的密钥一般是对称加密的密钥MAC 算法有很多种,但最常用的是 hash 算法,就是明文加上密钥的数字摘要\n\n\nHMAC = 使用 hash 算法的 MAC\n\n\nNonce 是 Number used once 或 Number once 的缩写,数字使用一次,在密码学中 Nonce 是一个只被使用一次的任意或非重复的随机数值\n\n\n时间戳 timestamp 表示的是从世界标准时间UTCCoordinated Universal Time的 1970 年 1 月 1 日 0 时 0 分 0 秒开始到现在的秒数,时间戳大部分情况下是 10 位的,但有时也会用 13 位的时间戳\n\n\n块加密 又称为 分块加密 或 分组加密 是将明文分成多个等长的模块block使用确定的算法和对称密钥对每组分别加密解密。块加密通常有三个参数算法 密码强度 模式,例如 aes-256-gcm aes 是对称加密的算法, 256 是密码强度, gcm 是分组密码的工作模式通常只有块加密的算法有工作模式的参数。DES 和 AES 都是块加密\n\n\n流加密 加密和解密双方使用相同伪随机加密数据流pseudo-randomstream作为密钥明文数据每次与密钥数据流顺次对应加密得到密文数据流。实践中数据通常是一个位bit并用异或xor操作加密。RSA 是流加密\n\n\n对称加密 = 加密和解密都用同一个密钥。\n\n\n非对称加密 = 加密和解密使用不同的密钥。\n\n公开的密钥用于加密和验证签名称为公钥不公开的密钥用于解密和签名称为私钥\n一般是一对密钥加密用其中一个密钥那么解密就要用另一个密钥。一般两个密钥的长度是不一样的一般长度较短的密钥会公开称为公钥长度较长的密钥不会公开称为私钥 (这个其实只适用于 RSA ,其它非对称加密算法不是这样的)\n\n\n\n公开密钥密码学 (Public-key cryptography) 就是 非对称加密\n\n\n公钥 = 在非对称加密中,可以公开的密钥\n\n\n私钥 = 在非对称加密中,不能公开的密钥\n\n\n数字签名 = 在非对称加密中,由私钥和签名算法生成的信息。在 RSA 中数字签名是由私钥加密后的数字摘要,但其它非对称加密算法不是这样的。\n\n\n密钥密文 一般是指,对称加密和非对称加密组合使用下,使用公钥 加密 对称加密的密钥\n\n\n数字信封 一般是指,对称加密和非对称加密组合使用下,内容是 密钥密文 + 密文 (使用对称加密的密文) 的信息。数字信封既发挥了对称加密算法速度快的优点,又发挥了非对称加密算法密钥管理方便的优点。\n\n\nCKE = 内容密钥 (Contents Encrypting Key) ,就是用于加密明文的密钥,是和 KEK 相对的\n\n\nKEK = 加密密钥的密钥 (Key Encrypting Key)\n\n\nPBE = 基于口令的密钥 (Password Based EncryptionPBE) ,在 PGP 里会用 PBE 加密私钥\n\n\n盐Salt在密码学中是指在散列之前将散列内容例如密码的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同在不同的应用情景中这个处理可以增加额外的安全性。在大部分情况盐是不需要保密的。盐可以是随机产生的字符串其插入的位置可以也是随意而定。\n\n\n数字证书 = 用户信息csr + 用户公钥 + 公钥指纹 + 其它相关信息 + (颁发机构私钥 加密 前面提及的 相关数据的 数字摘要 所得到的数字签名)\n\n\nhttps 里的 ssl 证书就是数字证书\n\n\n这是数字证书的一般格式\n```\n 证书\n 版本号\n 序列号 由证书颁发者分配的本证书的唯一标识符。颁发者和证书序列号配合起来就能唯一地标识一张数字证书。\n 签名算法\n 颁发者\n 国家CCountry\n 州/省SState\n 地域/城市LLocation\n 组织/单位OOrganization\n 通用名称CNCommon Name\n 证书有效期\n 此日期前无效\n 此日期后无效\n 主题\n 国家CCountry\n 州/省SState\n 地域/城市LLocation\n 组织/单位OOrganization\n 通用名称CNCommon Name 在 TLS 应用上,此字段一般是域名\n 主题公钥信息\n 公钥算法\n 主题公钥\n 颁发者唯一身份信息(可选项 AKID , authority key identifier 颁发者公钥的数字摘要\n 主题唯一身份信息(可选项 SKID , subject key identifier 主题公钥的数字摘要\n 扩展信息(可选项)\n 主题别名Subject Alternative Name 在 TLS 应用上,如果一个证书需要支持多个域名,则其它域名会填在这里\n 授权密钥标识符 颁发者的公钥\n ...\n 证书签名算法\n 数字签名\n```\n\n\n\n\n\nPKC = 公钥证书 (Public-Key CertificatePKC) ,就是数字证书\n\n\n公钥指纹 = 公钥的数字摘要,是用于标识较长公共密钥字节的短序列。由于指纹较比生成它们的密钥短得多,因此可以用来简化某些密钥的管理任务。\n\n\n颁发证书 = CA 用私钥加密 CSR 和 用户公钥然后生成数字证书的过程\n\n\ncsr 是 cerificate signing request 的英文缩写,即证书请求文件,内容是 公钥 + 用户信息(例如 域名之类的),一般是向 CA 申请数字证书用的。 X.509 证书申请的格式标准为 PKCS10 和 rfc2314 。 cerificate 证书 signing 签署 request 请求\n\n\nCA = 数字证书认证 (Certificate Authority)\n\n\nCA 中心 = 数字证书认证机构,一般情况下 CA 和 CA 中心 都是指 数字证书认证机构\n\n\nCA 系统 = 用于颁发数字证书的系统,由 CA 中心管理和运营\n\n\nCAA = 数字证书认证授权 (Certificate Authority Authorization) CAA 是一种 DNS 记录它允许站点所有者指定允许哪些证书颁发机构CA颁发包含其域名的证书。\n\n\ncrt 和 cert 都是 certificate 的缩写\n\n\n最终实体证书 = 普通用户向 CA 申请后使用的证书\n\n\n自签证书 = 用户信息csr + 用户公钥 + 私钥加密前面两个数据所得到的数字签名(用户私钥)\n\n\n证书链是从终端用户证书后跟着一系列的 CA 证书,而通常最后一个是自签名证书,并且有如下关系:\n\n在证书链上除最后一个证书外证书颁发者等于其后一个证书的主题。\n除了最后一个证书每个证书都是由其后的一个证书签名的。\n最后的证书是信任主题由于是通过可信过程得到的所以可以信任。\n\n\n\n根证书 = 证书链里最后一个证书,一般是自签证书,一般是 CA 的自签证书,根证书一般是直接内置在客户端(内置在浏览器或操作系统里)的\n\n\n中间证书 = 一个 CA 向另一个 CA 颁发的证书,又或者说证书链中处于中间位置的证书,一个证书链里可以有多个中间证书\n\n\n在线证书状态协议英语Online Certificate Status Protocol缩写OCSP是一个用于获取 X.509 数字证书撤销状态的网际协议,在 RFC 6960 中定义作为证书吊销列表CRL的替代品解\n\n\n证书吊销列表英文Certificate revocation list缩写CRL或译作证书废止清册是尚未到期就被证书颁发机构吊销的数字证书的名单。这些在证书吊销列表中的证书不再会受到信任。目前在线证书状态协议OCSP已经替代证书吊销列表CRL成为检查证书状态的主流。\n\n\n证书链的验证\n\n从证书里获取颁发者信息 → 从仓库里获取颁发者的公钥 → 公钥验证数字证书的数字签名\n重复这个过程一直到根证书为止\n这个过程中还会查询 CRL 和 OCSP ,确认证书没有过期。还可能会验证密钥用法,证书策略等属性\n\n\n\nPKI = 公开密钥基础设施 (Public Key Infrastructure) PKI 包含 PKIX 和 PKCS\n\nPKI 的核心是数字证书的发行,一般来说,构成 PKI 的主要要素就是下面三个概念\n\n数字证书\n认证机关 (CA)\n证书库\n\n\n\n\n\nPKCS = 公钥密码学标准 (The Public-Key Cryptography Standards)\n\n是由美国 RSA 数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。\n\n\n\nX.509 = PKIX\n\n\nPKIX = 公钥基础设施 X.509 (Public Key Infrastructure X.509) X.509 是密码学里公钥证书的格式标准,证书组成结构标准用 ASN.1 来进行描述\n\n\nX.509 是密码学里公钥证书的格式标准, PKCS 是一系列密码学的标准, PKCS 有十几个标准, X.509 大致相当于 PKCS1 和 PKCS12\n\n\nPKCS #12 定义了一种存档文件格式,用于实现存储许多加密对象在一个单独的文件中。通常用它来打包一个私钥及有关的 X.509 证书,或者打包信任链的全部项目。一个 PKCS #12 文件通常是被加密的,同时单独存在(存档文件格式)。\n\n可以打包密钥对和数字证书\n\n\n\nPFX = PKCS#12 ,其实也不算是严格相等,但大多数语境下可以相等\n\n\nPKCS 比较常用的是 1 7 8 10 12\n\n\nASN.1 抽象语法符号 Abstract Syntax Notation OneASN.1\n\nASN.1 是一种用来定义数据结构的接口描述语言\nASN.1 有一套关联的编码规则,这些编码规则用来规定如何用二进制来表示数据结构, DER 是其中一种\n\n\n\nDER = 可辨别编码规则 (Distinguished Encoding Rules) ,是一种二进制的用于保存证书和密钥的文件编码格式, windows 和 java 是用这种格式的\n\n\nPEM = 私密 增强 邮件 (Privacy Enhanced Mail) ,是一种纯文本的用于保存证书和密钥的文件编码格式,而 DER 编码的内容是二进制的,不适合与邮件传输(早期 email 不能发送附件), nginx apahce php 是用这种格式的\n\n\nJKS = Java Key Storage JAVA 的专属格式,利用 JAVA 的一个叫 keytool 的工具可以进行格式转换。一般用于 Tomcat 服务器。\n\n\nPKCS 和 X.509 是格式标准,而 DER 和 PEM 是文件编码格式\n\n\nCA/浏览器论坛 CA/Browser Forum ,是一个证书颁发机构、网页浏览器软件供应商、操作系统,以及其他采用 PKI 的应用程序的自愿联合体,其颁布 X.509 v.3 电子证书的签发与管理的行业治理方针,在诸多应用程序中链接到信任锚。其方针涵盖用于 SSL/TLS 协议和代码签名的证书,以及系统和证书颁发机构的系统和网络安全。\n\n\n会话密钥加密会话内容的密钥大多数情况下只用一次。\n\n\n主密钥会被重复使用的加密会话密钥的密钥。\n\n\nPSK = 预共享密钥 (pre-shared key)\n\n\n常用的算法\n\n对称加密\n\ndes\n3des\naes\n\n\n非对称加密\n\nRSA\nElGamal\nECDSA\n\n\n数字摘要\n\nsha2\nmd5\n\n\n\n\n\n密码套件 (cipher suite) 或者称为密码包,是 https 中各种算法的集合,一般包括 密钥交换算法 身份验证算法 加密算法(加密方法 - 加密强度 - 模式) 哈希算法 。一般情况下密码包里的算法不能重复出现,例如 密钥交换算法用了 RSA ,那么身份验证算法就不能用 RSA\n\n\nPR = 伪随机数 (Pseudo Random) ,计算机里生成真正的随机数其实挺麻烦的,所以一般都是用伪随机数\n\n\nPRF = 伪随机数函数 (Pseudo Random Function) ,就是用于生成伪随机数的方法\n\n\nPRNG = 伪随机数生成器 (Pseudo Random Number Generator) ,就是用于生成伪随机数的方法\n\n\nTRNG = 真随机数生成器 (True Random Number Generator)\n\n\nHRNG = 硬件随机数生成器 (Hardware Random Number Generator) ,大部分语境下 HRNG == TRNG ,单靠软件无法生成真随机数\n\n\nCSPRNG = 密码学安全伪随机数生成器 (Cryptographically secure pseudo-random number generator)\n\n\nTTP 可信赖的第三者 (Trusted third party) ,在 PKI 里通常是指 CA\n\n\nOTP 一次性密码本 (one-time pad)\n\n\nHTTPS = HTTP + TLS 或 HTTP + TLS HTTP + SSL 已经被弃用,现在的都是 HTTP + TLS ,有些时候也会称为 HTTP + TLSSSL\n\n\nWSS = WebSocket + TLSSSL\n\n\nSSL = 安全套接层 (Secure Sockets Layer) 网景公司Netscape在 1994 年推出首版网页浏览器-网景导航者时,推出 HTTPS 协议,以 SSL 进行加密\n\n\nTLS = 传输层安全性协议 (Transport Layer Security) IETF 将 SSL 标准化,并将其称为 TLS 1999 年公布 TLS 1.0 标准文件RFC 2246。其实大多数 TCP 的协议都可以在上面套一层 TLS\n\n\n除了 HTTP 之外 TSL/TLS 可以跟很多常用的应用层协议比如FTP、SMTP、POP、Telnet搭配使用\n\n\nTLS 服务器证书,就是启用 HTTPS 时需要用到的数字证书,也称为 SSL 证书,一般是从 CA 申请后部署在 HTTP 服务器的\n\n\n一般语境下的 SSL 证书,就是 Common Name 是域名的数字证书\n\nSSL 证书按照域名的数量可以分为\n\n单域名证书\n多域名证书 除了 Common Name 是域名之外,其它域名都填在 扩展信息可选项里的主题别名Subject Alternative Name\n通配符证书 Common Name 的域名最后一级是通配符 * ,但只能匹配一级的域名\n\n\nSSL 证书按照审核的内容可以分为\n\n域名验证证书 (Domain Validation Certificate DV) ,验证域名的所有权,通常是免费的,颁发速度很快,十分钟左右就能完成颁发\n组织验证证书 (Organization Validation Certificate OV) ,验证域名所有权,也要验证企业或组织身份, 因为 CA 会验证企业或组织的身份,一般需要几天才完成颁发\n扩展验证证书 (Extended Validation Certificate EV) ,除了验证域名所有权, CA 验证企业或组织身份之外,还会引入第三方审核,可能牵涉专业法律人员的调查及独立审计人员\n\n\n\n\n\nS/MIME ,安全的多用途 Internet 邮件扩展Secure Multipurpose Internet Mail Extensions简称 S/MIME是一种 Internet 标准,它在安全方面对 MIME 协议进行了扩展,可以将 MIME 实体(比如数字签名和加密信息等)封装成安全对象,为电子邮件应用增添了消息真实性、完整性和保密性服务。 S/MIME 不局限于电子邮件,也可以被其他支持 MIME 的传输机制使用,如 HTTP\n\n\n证书颁发机构浏览器论坛也称 CA/浏览器论坛(英语: CA/Browser Forum 缩写: CA/B、证书机构与浏览器论坛它是一个证书颁发机构、网页浏览器软件供应商、操作系统以及其他采用 PKI 的应用程序的自愿联合体,其颁布 X.509 v.3 电子证书的签发与管理的行业治理方针,在诸多应用程序中链接到信任锚。其方针涵盖用于 SSL/TLS 协议和代码签名的证书,以及系统和证书颁发机构的系统和网络安全。\n\n\n证书透明度英语Certificate Transparency简称 CT也称证书透明、证书透明化它是一个实验性的 IETF 开源标准和开源框架目的是监测和审计数字证书。通过证书日志、监控和审计系统证书透明度使网站用户和域名持有者可以识别不当或恶意签发的证书以及识别数字证书认证机构CA的作为。\n\n\n向前保密前向安全性或前向保密性英语Forward Secrecy缩写FS有时也被称为完美前向安全英语Perfect Forward Secrecy缩写PFS是密码学中通讯协议的安全属性指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。\n\n\n零知识证明Zero Knowledge Proof是这样的一个过程证明者在不向验证者提供任何额外信息的前提下使验证者相信某个论断Statement是正确的。证明过程包括交互式Interactive和非交互式Non-interactive两种。\n\n\n各类编码的转换例如 base64 和 urlencode ,这类编码的转换虽然可以把一般的字符串转换成一堆看上去是乱码的字符串,但实质上并没有加密的功能,只是增加了普通人的阅读障碍。有些时候也可以用这类方式来规避一些内容的审查\n\n\n数字指纹 主要用于版权保护,其研究具有重要的意义。数字指纹是将不同的标志性识别代码——指纹,利用数字水印技术嵌入到数字媒体中,然后将嵌入了指纹的数字媒体分发给用户。发行商发现盗版行为后,就能通过提取盗版产品中的指纹,确定非法复制的来源,对盗版者进行起诉,从而起到版权保护的作用。\n\n\ne2ee 端到端加密 End-to-end encryption 是一种只有参与通讯的用户可以读取信息的通信系统。总的来说,它可以防止潜在的窃听者——包括电信供应商、互联网服务供应商,获取能够用以解密通讯的密钥。此类系统被设计为可以防止潜在的监视或篡改企图,因为没有密钥的第三方难以破译系统中传输或储存的数据。\n\n\nSSH = Secure Shell\n\nSecure Shell Protocol (rcf 4251) 由 IETF 的网络小组所制定,专为远程登录会话和其他网络服务提供安全性的协议。\nOpenSSH 是 SSH 的开源实现,多数语境下 SSH 指的是 OpenSSH 里的 ssh 命令\nSSH 只是加密的 shell ,最初是用来替代 telnet 的。通过 port forward ,也可以让其他协议通过 SSH 的隧道而起到加密效果。\nSSH 和 TLS 是两种不一样的协议,但都能为其它协议提供加密效果\n\n一般用 SSH 的,会称为 xxx over SSH 会把 s 加在前面,例如 sftp (ftp over SSH)\n一般用 TLS 的,会称为 xxx over TLS 会把 s 加在后面,例如 ftps (ftp over TLS)\nSSH 能代理 UDP\nTLS 是建立在 TCP 上的,要代理 UDP 会有一点困难\n\n\n\n\n\nDoH 和 DoT\n\nDNS over HTTPS 基于 HTTPS 的 DNS\nDNS over TSL 基于 TLS 的 DNS\nDoH 的安全原理与 DoT 一样他们之间的区别只在于DoH 有了 HTTP 格式封装,更加通用。\n\n\n\nDNSSEC = 域名系统安全扩展DNS Security Extensions简称 DNSSEC。通过数字签名来保证 DNS 应答报文的真实性和完整性,能够防止 DNS 欺骗和缓存污染等攻击。\n\n\n信息安全\n信息安全五要素\n\n信息的保密性Confidenciality、真实性Authenticity、完整性Integrity、不可否认性Non-repudiation、可用性Availability\n其中保密性Confidenciality、完整性Integrity、可用性Availability称为 CIA 三要素\n这些要素是原子的不能进一步分解或重合代表信息安全的一个方面。任何信息安全漏洞都可以描述为影响这些要素一个或多个\nCIA 三要素之间存在互相牵制的关系,过度强化保密性时,将造成完整性与可用性的降低,需要高可用性的系统则会造成机密性与完整性的降低,因此在有限资源的前提下,在 CIA 三要素中获取适当的平衡是信息安全管理层次结构的重要课题。\n\n各个密码学概念对应的要素\n\n数字摘要 → 完整性\n消息认证码 → 完整性 真实性\n数字签名 → 完整性 真实性 不可否认性\n加密 → 保密性\n\n各种攻击所对应的要素\n\n完整性 → 篡改\n真实性 → 伪装\n保密性 → 窃听\n可用性 → 阻断\n\n以 Https 为例解释信息安全的五要素\n\nhttps 的连接过程\n\ntcp 三次握手建立连接\n客户端和服务器协商密码包\n服务器发送证书给客户端客户端验证证书这里会验证证书的数字签名有效时间颁发者等信息还会逐级验证证书链上的证书证书链的验证会查询 OCSP 和 CRL \n客户端生成一个对称加密的密钥\n客户端把对称加密的密钥发送给服务端密钥交换协议有好多种其中最容易理解的就是 RSA 了,客户端公钥加密 对称加密的密钥,然后服务器用私钥解密\n客户端和服务器在后续的通讯都使用对称加密\n\n\n数字证书和证书链是保证信息源的真实性\n数字证书中的数字签名是保证数字证书的完整性真实性不可否认性\nhttps 完成握手后的通讯使用对称加密是保证消息的保密性\n对称加密的通讯会在消息的末尾加上 MAC 校验数据,保证消息的完整性,真实性\n但这些都不能保证可用性以下是针对可用性的攻击例子\n\n拒绝服务攻击\n旁观者攻击\n\n\n\n信息安全常识\n\n不要使用保密的密码算法\n使用低强度的密码比不进行任何加密更危险\n\n低强度的密码和没有加密同样不安全。但是使用了密码会给用户一种错误的安全感导致用户容易泄露一些机密的信息。\n\n\n任何密码总有一天都会被破解\n密码只是信息安全的一部分\n\n3A\n\n认证Authentication\n\n识别信息用户的身份可记录信息被谁所访问使用例如透过密码或证书方式验证用户身份。 实务做法:\n\n你所知道的Something you know账号密码\n你所拥有的Something you haveIC 卡、数字设备、数字签名、一次性密码 (OTP)\n你所具备的Something you are指纹、虹膜、声纹、脸部特征、静脉脉纹、DNA\n\n\n\n\n授权Authorization\n\n依照实际需求给予实体适当的权限一般建议采最小权限Least privilege意即仅给予实际作业所需要的权限避免过度授权可能造成的信息暴露或泄漏。 信息系统层面的实务访问控制方法分类如下:\n\n强制访问控制Mandatory Access Control\n自由选定访问控制Discretionary Access Control\n以角色为基础的访问控制Role-Based Access Control\n以规则为基础的访问控制Rule-Based Access Control\n\n\n\n\n记录Accounting\n\n内容项目包含量测Measuring、监控Monitoring、报告Reporting与日志案 (Logging) 以便提供未来作为审核Auditing、计费Billing、分析Analysis与管理之用 主要精神在于收集用户与系统之间交互的资料,并留下轨迹纪录。\n\n\n\n信息安全的基本原则\n为了达到信息安全的目标各种信息安全技术的使用必须遵守一些基本的原则。\n\n最小化原则。\n\n受保护的敏感信息只能在一定范围内被共享履行工作职责和职能的安全主体在法律和相关安全策略允许的前提下为满足工作需要。仅被授予其访问信息的适当权限称为最小化原则。敏感信息的“知情权”一定要加以限制是在“满足工作需要”前提下的一种限制性开放。\n可以将最小化原则细分为知所必须need to know和用所必须need to use的原则。\n\n\n分权制衡原则。\n\n在信息系统中对所有权限应该进行适当地划分使每个授权主体只能拥有其中的一部分权限使他们之间相互制约、相互监督共同保证信息系统的安全。\n如果一个授权主体分配的权限过大无人监督和制约就隐含了“滥用权力”、“一言九鼎”的安全隐患。\n\n\n安全隔离原则。\n\n隔离和控制是实现信息安全的基本方法而隔离是进行控制的基础。信息安全的一个基本策略就是将信息的主体与客体分离按照一定的安全策略在可控和安全的前提下实施主体对客体的访问。\n在这些基本原则的基础上人们在生产实践过程中还总结出的一些实施原则他们是基本原则的具体体现和扩展。\n包括整体保护原则、谁主管谁负责原则、适度保护的等级化原则、分域保护原则、动态保护原则、多级保护原则、深度保护原则和信息流向原则等。\n\n\n\n随机数\n随机数的性质\n\n随机性不存在统计学偏差是完全杂乱的数列\n不可预测性不能从过去的数列推测出下一个出现的数列\n不可重现性除非将数列本身保存下来否则不能重现相同的数列\n\n随机数的分类\n\n随机数\n\n伪随机数\n\n统计学伪随机数弱伪随机数 - 满足 随机性\n密码学伪随机数强伪随机数 - 满足 随机性 不可预测性\n\n\n真随机数 - 满足 随机性 不可预测性 不可重现性\n\n\n\n随机数的作用\n\n生成密钥\n\n用于对称密码和消息认证码\n\n\n生成公钥密码\n\n用于生成公钥密码和数字签名\n\n\n生成初始化向量 IV\n\n用于分组密码中的 CBC、CFB、OFB 模式\n\n\n生成 nonce\n\n用于防御重放攻击和分组密码中的 CTR 模式\n\n\n生成盐\n\n用于基于口令密码的 PBE 等\n\n\n\n\n用随机数的目的是为了提高密文的不可预测性\n\n在 Linux 下生成随机数\n/dev/random 在类 UNIX 系统中是一个特殊的设备文件,可以用作随机数生成器。\n/dev/random 的随机数的提供是依赖与外部中断事件的,如果没有足够多中断事件,就会阻塞。 /dev/random 生成的是真随机数。\n/dev/urandom“unblocked”非阻塞的随机数生成器是 /dev/random 的一个副本 ,它会重复使用熵池中的数据以产生伪随机数据。 这表示对 /dev/urandom 的读取操作不会产生阻塞,但其输出的熵可能小于 /dev/random 的。 它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。\n/dev/random 和 /dev/urandom 会输出二进制数据流,可以用 od 命令转换,或者用 base64 命令转换。\n/dev/random 和 /dev/urandom 生成的都是符合密码学安全的随机数。因为 /dev/random 可能会阻塞,所以大部分情况下用 /dev/urandom 就可以了。\n大部分情况下都是用 TRNG 生成的随机数作为种子,然后再用 CSPRNG 生成密码学安全的随机数。这样既能保证安全也能效率也不会太低。\n命令行下的使用示例\n# 不能直接用 cat ,因为 /dev/random 会一直输出\nhead -n 1 /dev/random | od -x\nhead -n 1 /dev/urandom | od -x\n# 生成随机字符串\nhead -n 1 /dev/urandom | base64 | head -n 1\nhead -n 1 /dev/urandom | base64 | head -n 1\n# 只生成数字\nhead -n 1 /dev/urandom | base64 | head -n 1 | tr -dc '0-9'\n# 环境变量里的 $RANDOM 是一个随机数字\necho $RANDOM"},"Technology/ComputerSecurity/用户安全/权限设计/主流权限系统的设计":{"title":"主流权限系统的设计","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"权限管控可以通俗的理解为权力限制,即不同的人由于拥有不同权力,他所看到的、能使用的可能不一样。对应到一个应用系统,其实就是一个用户可能拥有不同的数据权限(看到的)和操作权限(使用的)。\n主流的权限模型主要分为以下五种\n\nACL 模型:访问控制列表\nDAC 模型:自主访问控制\nMAC 模型:强制访问控制\nABAC 模型:基于属性的访问控制\nRBAC 模型:基于角色的权限访问控制\n\nACL 模型:访问控制列表\nAccess Control ListACL 是最早的、最基本的一种访问控制机制,是基于客体进行控制的模型,在其他模型中也有 ACL 的身影。为了解决相同权限的用户挨个配置的问题,后来也采用了用户组的方式。\n原理每一个客体都有一个列表列表中记录的是哪些主体可以对这个客体做哪些行为非常简单。\n例如当用户 A 要对一篇文章进行编辑时ACL 会先检查一下文章编辑功能的控制列表中有没有用户 A有就可以编辑无则不能编辑。再例如不同等级的会员在产品中可使用的功能范围不同。\n缺点当主体的数量较多时配置和维护工作就会成本大、易出错。\nDAC 模型:自主访问控制\nDiscretionary Access ControlDAC 是 ACL 的一种拓展。\n原理在 ACL 模型的基础上,允许主体可以将自己拥有的权限自主地授予其他主体,所以权限可以任意传递。\n例如常见于文件系统LINUXUNIX、WindowsNT 版本的操作系统都提供 DAC 的支持。\n缺点对权限控制比较分散例如无法简单地将一组文件设置统一的权限开放给指定的一群用户。主体的权限太大无意间就可能泄露信息。\nMAC 模型:强制访问控制\nMandatory Access ControlMAC 模型中主要的是双向验证机制。常见于机密机构或者其他等级观念强烈的行业,如军用和市政安全领域的软件。\n原理主体有一个权限标识客体也有一个权限标识而主体能否对该客体进行操作取决于双方的权限标识的关系。\n例如将军分为上将 > 中将 > 少将,军事文件保密等级分为绝密 > 机密 > 秘密,规定不同军衔仅能访问不同保密等级的文件,如少将只能访问秘密文件;当某一账号访问某一文件时,系统会验证账号的军衔,也验证文件的保密等级,当军衔和保密等级相对应时才可以访问。\n缺点控制太严格实现工作量大缺乏灵活性。\nABAC 模型:基于属性的访问控制\nAttribute-Based Access Control能很好地解决 RBAC 的缺点,在新增资源时容易维护。\n原理通过动态计算一个或一组属性是否满足某种机制来授权是一种很灵活的权限模型可以按需实现不同颗粒度的权限控制。\n属性通常有四类\n\n主体属性如用户年龄、性别等\n客体属性如一篇文章等\n环境属性即空间限制、时间限制、频度限制\n操作属性即行为类型如读写、只读等。\n\n例如早上 9:0011:00 期间 A、B 两个部门一起以考生的身份考试,下午 14:0017:00 期间 A、B 两个部门相互阅卷。\n缺点规则复杂不易看出主体与客体之间的关系实现非常难现在应用的很少。\nRBAC 基于角色的权限访问控制\nRole-Based Access Control核心在于用户只和角色关联而角色代表对了权限是一系列权限的集合。\nRBAC 三要素:\n\n用户系统中所有的账户\n角色一系列权限的集合管理员开发者审计管理员等\n权限菜单按钮数据的增删改查等详细权限。\n\n在 **RBAC **中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。\n角色是为了完成各种工作而创造用户则依据它的责任和资格来被指派相应的角色用户可以很容易地从一个角色被指派到另一个角色。\n角色可依新的需求和系统的合并而赋予新的权限而权限也可根据需要而从某角色中回收。角色与角色的关系同样也存在继承关系防止越权。\n优点便于角色划分更灵活的授权管理最小颗粒度授权\n\nRBAC 的深度拓展\nRBAC 模型可以分为RBAC0、RBAC1、RBAC2、RBAC3 四个阶段,一般公司使用 RBAC0 的模型就可以。另外RBAC0 相当于底层逻辑,后三者都是在 RBAC0 模型上的拔高。\n我先简单介绍下这四个 RBAC 模型:\n1. RBAC0 模型\n用户和角色、角色和权限多对多关系。\n简单来说就是一个用户拥有多个角色一个角色可以被多个用户拥有这是用户和角色的多对多关系同样的角色和权限也是如此。\nRBAC0 模型如下图:没有画太多线,但是已经能够看出多对多关系。\n\n2. RBAC1 模型\n相对于 RBAC0 模型,增加了角色分级的逻辑,类似于树形结构,下一节点继承上一节点的所有权限,如 role1 根节点下有 role1.1 和 role1.2 两个子节点\n\n角色分级的逻辑可以有效的规范角色创建主要得益于权限继承逻辑我之前做过 BD 工具(类 CRM BD 之间就有分级(经理、主管、专员),如果采用 RBAC0 模型做权限系统,我可能需要为经理、主管、专员分别创建一个角色(角色之间权限无继承性),极有可能出现一个问题,由于权限配置错误,主管拥有经理都没有权限。\n而 RBAC1 模型就很好解决了这个问题,创建完经理角色并配置好权限后,主管角色的权限继承经理角色的权限,并且支持针对性删减主管权限。\n3. RBAC2 模型\n基于 RBAC0 模型,对角色增加了更多约束条件。\n\n如角色互斥比较经典的案例是财务系统中出纳不得兼管稽核那么在赋予财务系统操作人员角色时同一个操作员不能同时拥有出纳和稽核两个角色。\n如角色数量限制例如一个角色专门为公司 CEO 创建的,最后发现公司有 10 个人拥有 CEO 角色,一个公司有 10 个 CEO ?这就是对角色数量的限制,它指的是有多少用户能拥有这个角色。\nRBAC2 模型主要是为了增加角色赋予的限制条件,这也符合权限系统的目标:权责明确,系统使用安全、保密。\n4. RBAC3 模型\n同样是基于 RBAC0 模型,但是综合了 RBAC1 和 RBAC2 的所有特点\n这里就不在多描述读者返回去看 RBAC1 和 RBAC2 模型的描述即可。\nRBAC 权限管理的在实际系统中的应用\nRBAC 权限模型由三大部分构成,即用户管理、角色管理、权限管理。\n用户管理按照企业架构或业务线架构来划分这些结构本身比较清晰扩展性和可读性都非常好。\n角色管理一定要在深入理解业务逻辑后再来设计一般使用各部门真实的角色作为基础再根据业务逻辑进行扩展。\n权限管理是前两种管理的再加固做太细容易太碎片做太粗又不够安全这里我们需要根据经验和实际情况来设计。\n1. 用户管理\n用户管理中的用户是企业里每一位员工他们本身就有自己的组织架构我们可以直接使用企业部门架构或者业务线架构来作为线索构建用户管理系统。\n\n需要特殊注意实际业务中的组织架构可能与企业部门架构、业务线架构不同需要考虑数据共享机制一般的做法为授权某个人、某个角色组共享某个组织层级的某个对象组数据。\n2. 角色管理\n在设计系统角色时我们应该深入理解公司架构、业务架构后再根据需求设计角色及角色内的等级。\n一般角色相对于用户来说是固定不变的每个角色都有自己明确的权限和限制这些权限在系统设计之处就确定了之后也轻易不会再变动。\n1. 自动获得基础角色\n当员工入职到某部门时该名员工的账号应该自动被加入该部门对应的基础角色中并拥有对应的基础权限。这种操作是为了保证系统安全的前提下减少了管理员大量手动操作。使新入职员工能快速使用系统提高工作效率。\n2. 临时角色与失效时间\n公司业务有时需要外援来支持他们并不属于公司员工也只是在某个时段在公司做支持。此时我们需要设置临时角色来应对这种可能跨多部门协作的临时员工。\n如果公司安全级别较高此类账号默认有固定失效时间到达失效时间需再次审核才能重新开启。避免临时账号因为流程不完善遗忘在系统中引起安全隐患。\n3. 虚拟角色\n部门角色中的等级可以授权同等级的员工拥有相同的权限但某些员工因工作原因需要调用角色等级之外的权限相同等级不同员工需要使用的权限还不相同。\n这种超出角色等级又合理的权限授予我们可以设置虚拟角色。这一虚拟角色可集成这一工作所需的所有权限然后将它赋予具体的员工即可。这样即不用调整组织架构和对应的角色也可以满足工作中特殊情况的权限需求。\n4. 黑白名单\n白名单某些用户自身不拥有某部门的顶级角色但处于业务需求需要给他角色外的高级权限那么我们可以设计限制范围的白名单将需要的用户添加进去即可。\n在安全流程中我们仅需要对白名单设计安全流程即可审核在白名单中的特殊用户做到监控拥有特殊权限的用户减少安全隐患。\n黑名单比较常见的黑名单场景是某些犯了错误的员工虽然在职但已经不能给他们任何公司权限了。这种既不能取消角色关联也不能完全停用账号的情况可以设置黑名单让此类用户可以登录账号查看基本信息但大多数关键权限已经被黑名单限制。\n3. 权限管理\n权限管理一般从三个方面来做限制。页面/菜单权限,操作权限,数据权限。\n\n1. 页面/菜单权限\n对于没有权限操作的用户直接隐藏对应的页面入口或菜单选项。这种方法简单快捷直接对于一些安全不太敏感的权限使用这种方式非常高效。\n2. 操作权限\n操作权限通常是指对同一组数据不同的用户是否可以增删改查。对某些用户来说是只读浏览数据对某些用户来说是可编辑的数据。\n3. 数据权限\n对于安全需求高的权限管理仅从前端限制隐藏菜单隐藏编辑按钮是不够的还需要在数接口上做限制。如果用户试图通过非法手段编辑不属于自己权限下的数据服务器端会识别、记录并限制访问。\n4. 数据权限如何管控\n数据权限可以分为行权限和列权限。行权限控制看多少条数据。列权限控制看一条数据的多少个字段。\n简单系统中可以通过组织架构来管控行权限按照角色来配置列权限但是遇到复杂情况组织架构是承载不了复杂行权限管控角色也更不能承载列的特殊化展示。\n目前行业的做法是提供行列级数据权规则配置把规则当成类似权限点配置赋予某个角色或者某个用户。\n\n\n用户管理系统权限设计中的更多实践细节\n1. 超级管理员\n超级管理员是用来启动系统配置系统的账号。这个账号应该在配置好系统创建管理员之后被隐藏起来。超级管理员账号拥有系统中全部权限可穿梭查看各部门数据如果使用不恰当是系统管理的安全隐患。\n2. 互斥角色如何处理\n当用户已经有用的角色和即将添加的角色互相互斥时应该在添加新角色时提示管理员因角色互斥的原因无法进行新角色添加。如需添加要先撤销掉前一个角色再添加新角色。\n3. 用户管理权限系统设计一定要简单清晰\n在设计权限系统之处一定要理清思路一切从简能不增加的多余角色和权限逻辑就一定不要增加。因为随着公司业务的扩大权限和角色也会随之增多如果初期设计思路不严谨那么权限系统会随着业务的扩大而无限混乱下去此时再来整理权限已经太晚了。所以初期设计就一定要条理清晰简单明了能避免后续非常多不必要的麻烦。\n4. 无权提示页\n有时员工 A 会直接给员工 B 分享他当下正在操作的页面,但有可能员工 B 无权查看。此时我们应该在这里考虑添加「无权提示页」,避免粗暴的 404 页面让员工 B 以为是系统出错了。"},"Technology/ComputerSecurity/用户安全/用户鉴权/HTTP-基本鉴权":{"title":"HTTP 基本鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"HTTP 基本鉴权\n在 HTTP 中,**基本认证方案Basic Access Authentication**是允许客户端(通常指的就是网页浏览器)在请求时,通过用户提供用户名和密码的方式,实现对用户身份的验证。\n流程图\n\n步骤解析\n\n客户端 向服务器请求一个受限的列表数据或资源。\n\n GET /list/ HTTP/1.1 \n Host: www.baidu.com \n Authorization: Basic aHR0cHdhdGNoOmY=\n\n服务器客户端你好这个资源在安全区 baidu.com 里是受限资源,需要基本认证。并且向客户端返回 401 状态码 Unauthorized未授权以及附带提供了一个认证域 www-Authenticate: Basic realm="baidu.com" 要求进行身份验证;其中 Basic 就是验证的模式,而 realm="baidu.com" 说明客户端需要输入这个安全域的用户名和密码,而不是其他域的。\n\n HTTP/1.1 401 Unauthorized \n www-Authenticate: Basic realm= "baidu.com"\n\n\n客户端 服务器,我已经携带了用户名和密码给你了,你看一下(如果客户端是浏览器,那么此时会自动弹出一个弹窗,让用户输入用户名和密码);\n输入完用户名和密码后则客户端将用户名及密码以 Base64 加密方式发送给服务器\n传送的格式如下其中 Basic 内容为:用户名 + 密码的 AES 64 形式):\n\n\n GET /list/ HTTP/1.1\n Authorization: Basic Ksid2FuZzp3YW5n==\n\n服务器 客户端你好,我已经校验了 Authorization 字段你的用户名和密码,是正确的,这是你要的资源。\n\n HTTP/1.1 200 OK \n ...\n优点\n简单易用基本所有流行的浏览器都支持。\n缺点\n不安全\n\n\n由于是基于 HTTP 传输,所以它在网络上几乎是裸奔的,虽然它使用了 Base64 来编码,但这个编码很容易就可以解码出来。\n\n\n即使认证内容无法被解码为原始的用户名和密码也是不安全的恶意用户可以再获取了认证内容后使用其不断的享服务器发起请求这就是所谓的重放攻击。\n\n\n无法主动注销\n\n由于 HTTP 协议没有提供机制清除浏览器中的 Basic 认证信息,除非标签页或浏览器关闭、或用户清除历史记录。\n\n使用场景\n内部网络或者对安全要求不是很高的网络。"},"Technology/ComputerSecurity/用户安全/用户鉴权/JWTJSON-Web-Token鉴权":{"title":"JWT 鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"JWTJSON Web Token鉴权\n通过第三节我们知道了 Token 的使用方式以及组成,我们不难发现,服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户基本信息,然后验证 Token 是否有效;这样每次请求验证都要查询数据库,增加了查库带来的延迟等性能消耗。\n那么这时候业界常用的 JWT 就应运而生了!!!\nJWT 的定义\nJWT 是 Auth0 提出的通过对 JSON 进行加密签名来实现授权验证的方案。\n就是登录成功后将相关用户信息组成 JSON 对象,然后对这个对象进行某种方式的加密,返回给客户端; 客户端在下次请求时带上这个 Token 服务端再收到请求时校验 token 合法性,其实也就是在校验请求的合法性。\nJWT 的组成\nJWT 由三部分组成Header 头部、Payload 负载和 Signature 签名。它是一个很长的字符串,中间用( . )分隔成三个部分。\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\nHeader 头部\n在 Header 中通常包含了两部分:\n\ntyp代表 Token 的类型,这里使用的是 JWT 类型。\nalg使用的 Hash 算法,例如 HMAC SHA256 或 RSA。\n\n{\n "alg": "HS256",\n "typ": "JWT"\n}\nPayload 负载\n它包含一些声明 Claim实体的描述通常是一个 User 信息还包括一些其他的元数据用来存放实际需要传递的数据JWT 规定了 7 个官方字段:\n\nississuer签发人\nexpexpiration time过期时间\nsubsubject主题\naudaudience受众\nnbfNot Before生效时间\niatIssued At签发时间\njtiJWT ID编号\n\n除了官方字段你还可以在这个部分定义私有字段下面就是一个例子。\n{\n "sub": "1234567890",\n "name": "John Doe",\n "admin": true\n}\nSignature 签名\nSignature 部分是对前两部分的签名,防止数据篡改。\n首先需要指定一个密钥secret。这个密钥只有服务器才知道不能泄露给用户。然后使用 Header 里面指定的签名算法(默认是 HMAC SHA256按照下面的公式产生签名。\nHMACSHA256(\n base64UrlEncode(header) + "." +\n base64UrlEncode(payload),\n secret)\nJWT 的使用方式\n客户端收到服务器返回的 JWT可以储存在 Cookie 里面,也可以储存在 localStorage。\n此后客户端每次与服务器通信都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息 Authorization 字段里面。\n Authorization: Bearer <token>\nJWT 的认证流程图\n\nJWT 的优点\n\n不需要在服务端保存会话信息RESTful API 的原则之一就是无状态),所以易于应用的扩展,即信息不保存在服务端,不会存在 Session 扩展不方便的情况。\nJWT 中的 Payload 负载可以存储常用信息,用于信息交换,有效地使用 JWT可以降低服务端查询数据库的次数。\n\nJWT 的缺点\n\n加密问题 JWT 默认是不加密,但也是可以加密的;生成原始 Token 以后,可以用密钥再加密一次。\n到期问题 由于服务器不保存 Session 状态,因此无法在使用过程中废止某个 Token或者更改 Token 的权限。一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/OAuth-鉴权":{"title":"OAuth 鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"OAuth 2.0\nOAuth 协议又有 1.0 和 2.0 两个版本2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。\nOAuth 2.0 定义\nOAuth 是一个开放标准,允许用户授权第三方网站(例如 CSDN、思否等获取用户数据。而不需要将用户名和密码提供给第三方网站常见的提供 OAuth 认证服务的厂商: 支付宝、QQ、微信、微博。\n简单说OAuth 就是一种授权机制。数据的所有者告诉系统同意授权第三方应用进入系统并获取这些数据。系统从而产生一个短期的进入令牌Token用来代替密码供第三方应用使用。\n令牌与密码的差异\n令牌Token与密码Password的作用是一样的都可以进入系统但是有三点差异。\n\n**令牌是短期的,到期会自动失效,**用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。\n令牌可以被数据所有者撤销会立即失效。\n令牌有权限范围scope 对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。\n\nOAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权模式 Authorization Grant ,适用于不同的互联网场景。\n\n授权码authorization-code\n隐藏式implicit\n密码式password\n客户端凭证client credentials\n\n无论哪个模式都拥有三个必要角色客户端、授权服务器、资源服务器有的还有用户资源拥有者。\n授权码模式\n授权码Authorization Code Grant) 方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。\n这种方式是最常用的流程安全性也最高它适用于那些有后端服务的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。\n一句话概括客户端换取授权码客户端使用授权码换 Token客户端使用 Token 访问资源。\n步骤详解\n1. 客户端\n打开网站 A点击登录按钮请求 A 服务A 服务重定向 (重定向地址如下) 至授权服务器(如 QQ、微信授权服务。\nqq.com/oauth/authorize\n response_type=code&\n client_id=CLIENT_ID&\n redirect_uri=CALLBACK_URL&\n scope=read\n上面 URL 中response_type 参数表示要求返回授权码codeclient_id 参数让 B 知道是谁在请求redirect_uri 参数是 B 接受或拒绝请求后的跳转网址scope 参数表示要求的授权范围(这里是只读)\n\n2. 授权服务器\n授权服务网站会要求用户登录然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务网站就会跳回 redirect_uri 参数指定的网址。跳转时会传回一个授权码就像下面这样code 参数就是授权码。\na.com/callback\n\n3. 网站 A 服务器\n拿到授权码以后就可以向 授权服务器 (qq.com) 请求令牌。\nqq.com/oauth/token\n client_id=CLIENT_ID&\n client_secret=CLIENT_SECRET&\n grant_type=authorization_code&\n code=AUTHORIZATION_CODE&\n redirect_uri=CALLBACK_URL\n上面 URL 中client_id 参数和 client_secret 参数用来让授权服务器 确认 A 的身份client_secret 参数是保密的因此只能在后端发请求grant_type 参数的值是 AUTHORIZATION_CODE表示采用的授权方式是授权码code 参数是上一步拿到的授权码redirect_uri 参数是令牌颁发后的回调网址。\n\n4. 授权服务器\n收到请求以后验证通过就会颁发令牌具体做法是向 redirect_uri 指定的网址,发送一段 JSON 数据。\n{ \n "access_token":"ACCESS_TOKEN",\n "token_type":"bearer",\n "expires_in":2592000,\n "refresh_token":"REFRESH_TOKEN",\n "scope":"read",\n "uid":100101,\n "info":{...}\n}\n上面 JSON 数据中access_token 字段就是令牌A 网站在后端拿到了,然后返回给客户端即可。\n\n隐藏式模式Implicit Grant\n有些 Web 应用是纯前端应用,没有后端;这时就不能用上面的方式了,必须将令牌储存在前端。\nOAuth2.0 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)” 隐藏式 “implicit。\n一句话概括客户端让用户登录授权服务器换 Token客户端使用 Token 访问资源。\n步骤详解\n1. 客户端\n打开网站 A然后 A 网站提供一个链接,要求用户跳转到授权服务器,授权用户数据给 A 网站使用。\nqq.com/oauth/authorize\n response_type=token&\n client_id=CLIENT_ID&\n redirect_uri=CALLBACK_URL&\n scope=read\n上面 URL 中response_type 参数为 token表示要求直接返回令牌。\n2. 授权服务器\n用户跳转到授权服务器登录后同意给予 A 网站授权。这时,授权服务器就会跳回 redirect_uri 参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。\na.com/callback#token=ACCESS_TOKEN\n上面 URL 中token 参数就是令牌A 网站因此直接在前端拿到令牌。\n\n还有需要注意的地方如下\n\n令牌的位置是 URL 锚点fragment而不是查询字符串querystring这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在 ” 中间人攻击 ” 的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。\n这种方式把令牌直接传给前端是很不安全的。因此只能用于一些安全要求不高的场景并且令牌的有效期必须非常短通常就是会话期间session有效浏览器关掉令牌就失效了。\n\n用户名密码式模式Password Credentials Grant\n如果你高度信任某个应用OAuth 2.0 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为 ” 密码式 “password。\n一句话概括用户在客户端提交账号密码换 Token客户端使用 Token 访问资源。\n步骤详解\n1. 客户端\nA 网站要求用户提供 授权服务器qq.com的用户名和密码。拿到以后A 就直接向授权服务器请求令牌。\noauth.b.com/token\n grant_type=password&\n username=USERNAME&\n password=PASSWORD&\n client_id=CLIENT_ID\n上面 URL 中grant_type 参数是授权方式,这里的 password 表示 ” 密码式 “username 和 password 是授权服务器的用户名和密码。\n2. 授权服务器\n授权服务器验证身份通过后直接给出令牌。注意这时不需要跳转而是把令牌放在 JSON 数据里面,作为 HTTP 回应A 网站因此拿到令牌。\n这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。\n客户端模式Client Credentials Grant\n客户端模式指客户端以自己的名义而不是以用户的名义向授权服务器进行认证。主要适用于没有前端的命令行应用。\n一句话概括客户端使用自己的标识换 token客户端使用 token 访问资源。\n步骤详解\n1. 客户端\n客户端向授权服务器进行身份认证并要求一个访问令牌。\noauth.b.com/token\n grant_type=client_credentials&\n client_id=CLIENT_ID&\n client_secret=CLIENT_SECRET\n上面 URL 中grant_type 参数等于 client_credentials 表示采用凭证式client_id 和 client_secret 用来让授权服务器确认 A 的身份。\n2. 授权服务器\n授权服务器验证通过以后直接返回令牌。这种方式给出的令牌是针对第三方应用的而不是针对用户的即有可能多个用户共享同一个令牌。\n授权模式对比\n按授权需要的多端情况\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模式需要前端需要后端需要用户响应需要客户端密钥授权码模式 Authorization Code✅✅✅✅隐式授权模式 Implicit Grant✅❌✅❌密码授权模式 Password Grant✅✅✅✅客户端授权模式 Client Credentials❌✅❌✅\n授权模式分类\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/Session-Cookie-鉴权":{"title":"Session-Cookie 鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"Session-Cookie 鉴权\nSession-Cookie 认证是利用服务端的 Session会话和 浏览器(客户端) 的 Cookie 来实现的前后端通信认证模式。\n在理解这句话之前我们先简单了解下什么是 Cookie以及什么是 Session \nCookie 是什么\n众所周知HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息);所以为了让服务器区分不同的客户端,就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器,而这个状态可以通过 Cookie 去实现。\n特点\n\n\nCookie 存储在客户端,可随意篡改,不安全。\n\n\n有大小限制最大为 4kb。\n\n\n有数量限制一般一个浏览器对于一个网站只能存不超过 20 个 Cookie浏览器一般只允许存放 300 个 Cookie。\n\n\nAndroid 和 IOS 对 Cookie 支持性不好。\n\n\nCookie 是不可跨域的,但是一级域名和二级域名是允许共享使用的(靠的是 domain。\n\n\nSession 是什么\nSession 的抽象概念是会话,是无状态协议通信过程中,为了实现中断 / 继续操作,将用户和服务器之间的交互进行的一种抽象;具体来说,是服务器生成的一种 Session 结构,可以通过多种方式保存,如内存、数据库、文件等,大型网站一般有专门的 Session 服务器集群来保存用户会话;\n流程\n\n\n客户端 用户向服务器首次发送请求。\n\n\n服务器 接收到数据并自动为该用户创建特定的 Session / Session ID来标识用户并跟踪用户当前的会话过程。\n\n\n客户端 浏览器收到响应获取会话信息,并且会在下一次请求时带上 Session / Session ID。\n\n\n服务器 服务器提取后会与本地保存的 Session ID 进行对比找到该特定用户的会话,进而获取会话状态。\n\n\n至此客户端与服务器的通信变成有状态的通信。\n\n\n特点\n\n\nSession 保存在服务器上。\n\n\n通过服务器自带的加密协议进行。\n\n\nSession 与 Cookie 的差异\n\n\n安全性 Cookie 由于保存在客户端可随意篡改Session 则不同存储在服务器端,无法伪造。所以 Session 的安全性更高。\n\n\n存取值的类型不同 Cookie 只支持字符串数据Session 可以存任意数据类型。\n\n\n有效期不同 Cookie 可设置为长时间保持Session 一般失效时间较短。\n\n\n存储大小不同 Cookie 保存的数据不能超过 4K。\n\n\nSession-Cookie 的认证流程图\n\nSession-Cookie 认证步骤解析\n\n\n客户端 向服务器发送登录信息用户名 / 密码来请求登录校验。\n\n\n服务器 验证登录的信息,验证通过后自动创建 Session将 Session 保存在内存中,也可以保存在 Redis 中),然后给这个 Session 生成一个唯一的标识字符串会话身份凭证 session_id通常称为 sid并在响应头 Set-Cookie 中设置这个唯一标识符。\n\n注可以使用签名对 sid 进行加密处理,服务端会根据对应的 secret 密钥进行解密 (非必须步骤)\n\n\n\n客户端 收到服务器的响应后会解析响应头,并自动将 sid 保存在本地 Cookie 中,浏览器在下次 HTTP 请求时请求头会自动附带上该域名下的 Cookie 信息。\n\n\n服务器 接收客户端请求时会去解析请求头 Cookie 中的 sid然后根据这个 sid 去找服务端保存的该客户端的 sid然后判断该请求是否合法。\n\n\nSession-Cookie 的优点\n\n\nCookie 简单易用。\n\n\nSession 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理。\n\n\n只需要后端操作即可前端可以无感等进行操作。\n\n\nSession-Cookie 的缺点\n\n\n依赖 Cookie一旦用户在浏览器端禁用 Cookie那么就 GG 思密达了。\n\n\n非常不安全Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)。\n\n\nSession 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能。\n\n\n对移动端的支持性不友好。\n\n\n使用场景\n\n\n一般中大型的网站都适用除了 APP 移动端)。\n\n\n由于一般的 Session 需集中存储在内存服务器上(如 Redis这样就会增加服务器的预算所以预算不够请谨慎选择。\n\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/Token-鉴权":{"title":"Token 鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"Token 鉴权\n现在我们已经得知Session-Cookie 的一些缺点,以及 Session 的维护给服务端造成很大困扰,我们必须找地方存放它,又要考虑分布式的问题,甚至要单独为了它启用一套 Redis 集群。那有没有更好的办法?\n于是 Token 就应运而生了\nToken令牌\nToken 是一个令牌客户端访问服务器时验证通过后服务端会为其签发一张令牌之后客户端就可以携带令牌访问服务器服务端只需要验证令牌的有效性即可。一句话概括访问资源接口API时所需要的资源凭证\nToken 的组成\n一般 Token 的组成由 uid (用户唯一的身份标识)+ time当前时间的时间戳) + sign 签名Token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)\nToken 的认证流程图\n\nToken 认证步骤解析\n\n客户端 输入用户名和密码请求登录校验。\n服务器 收到请求验证用户名与密码;验证成功后,服务端会签发一个 Token并把这个 Token 发送给客户端。\n客户端 收到 Token 以后需要把它存储起来Web 端一般会放在 localStorage 或 Cookie 中,移动端原生 APP 一般存储在本地缓存中。\n客户端 再次向服务端请求 API 资源的时候,将 Token 通过 HTTP 请求头 Authorization 字段或者其它方式发送给服务端。\n服务器 收到请求,然后去验证客户端请求里面带着的 Token 如果验证成功就向客户端返回请求的数据否则拒绝返还401。\n\nToken 的优点\n\n服务端无状态化、可扩展性好 Token 机制在服务端不需要存储会话Session信息因为 Token 自身包含了其所标识用户的相关信息,这有利于在多个服务间共享用户状态。\n支持 APP 移动端设备。\n安全性好 有效避免 CSRF 攻击(因为不需要 Cookie。\n支持跨程序调用 因为 Cookie 是不允许跨域访问的,而 Token 则不存在这个问题。\n\nToken 的缺点\n\n配合 需要前后端配合处理。\n占带宽 正常情况下比 sid 更大,消耗更多流量,挤占更多宽带。\n性能问题 虽说验证 Token 时不用再去访问数据库或远程服务进行权限校验,但是需要对 Token 加解密等操作,所以会更耗性能。\n有效期短 为了避免 Token 被盗用,一般 Token 的有效期会设置的较短,所以就有了 Refresh Token。\n\nRefresh Token刷新 Token\n业务接口用来鉴权的 Token我们称之为 Access Token。为了安全我们的 Access Token 有效期一般设置较短,以避免被盗用。但过短的有效期会造成 Access Token 经常过期,过期后怎么办呢?\n一种办法是刷新 Access Token让用户重新登录获取新 Token会很麻烦。另一种办法是再来一个 Token一个专门生成 Access Token 的 Token我们称为 Refresh Token。\n\nAccess Token 用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活;\nRefresh Token 用来获取 Access Token有效期可以长一些通过独立服务和严格的请求方式增加安全性由于不常验证也可以如前面的 Session 一样处理;\n\nRefresh Token 的认证流程图\n\nRefresh Token 认证步骤解析\n\n客户端 输入用户名和密码请求登录校验。\n服务端 收到请求,验证用户名与密码;验证成功后,服务端会签发一个 Access Token 和 Refresh Token 并返回给客户端;\n客户端 把 Access Token 和 Refresh Token 存储在本地;\n客户端 请求数据时,携带 Access Token 传输给服务端;\n服务端\n\n验证 Access Token 有效:正常返回数据\n验证 Access Token 过期:拒绝请求\n\n\n客户端 ( Access Token 已过期) 则重新传输 Refresh Token 给服务端;\n服务端 ( Access Token 已过期) 验证 Refresh Token ,验证成功后返回新的 Access Token 给客户端;\n客户端 重新携带新的 Access Token 请求接口;\n\nToken 和 Session-Cookie 的区别\nSession-Cookie 和 Token 有很多类似的地方,但是 Token 更像是 Session-Cookie 的升级改良版。\n\n存储地不同 Session 一般是存储在服务端Token 是无状态的,一般由前端存储。\n安全性不同 Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击。\n支持性不同 Session-Cookie 认证需要靠浏览器的 Cookie 机制实现,如果遇到原生 NativeAPP 时这种机制就不起作用了,或是浏览器的 Cookie 存储功能被禁用,也是无法使用该认证机制实现鉴权的;而 Token 验证机制丰富了客户端类型。\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/一键登录适用于原生APP":{"title":"一键登录","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"一键登录(适用于原生 APP\n账号密码登录\n大家都知道最传统的登录方式就是使用账号加密码登录简单粗暴一般也不会出现什么问题但这种方式的缺点如下\n\n但这种方式要求用户要记住自己的账号和密码也就是有一个记忆成本。用户为了降低记忆成本很可能会在不同平台使用同一套账号密码。从安全角度考虑一旦某个平台的账号密码泄露了会连累到该用户使用的其他平台。\n另外由于账号和个人身份无关意味着同一个用户可以注册多个不同的账号也就是可能会有恶意注册的情况发生。\n\n最后直到手机卡的强制实名制才得以解决\n手机号验证码登录\n随着无线互联的发展以及手机卡实名制的推广手机号俨然已成为特别的身份证明与账号密码相比手机号可以更好地验证用户的身份防止恶意注册。\n但是手机号注册还是需要一系列繁琐的操作输入手机号、等待短信验证码、输入验证码、点击登录。整个流程少说二十秒而且如果收不到短信也就登录不了问题有可能导致潜在的用户流失。\n从安全角度考虑还存在验证码泄漏的风险。如果有人知道了你的手机号并且窃取到了验证码那他也能登录你的账号了。\n所以就有了一键登录操作\n一键登录的定义\n我们想一下为什么我们需要验证码验证码的作用就是确定这个手机号是你的那除了使用短信是否还有别的方式对手机号进行认证于是就有了咱们的主角一键登录。\n短信验证码的作用证明当前操作页面的用户与输入手机号的用户为相同的人那么实际上只要我们能够获取到当前手机使用的手机卡号直接使用这个号码进行登录不需要额外的操作这就是一键登录。\n一键登录能不能做取决于运营商是否开放相关服务随着运营商开放了相关的服务我们现在已经能够接入运营商提供的 SDK 并付费使用相关的服务。\n一键登录流程图\n\n一键登录步骤详解\n\nSDK 初始化: 调用 SDK 方法,传入平台配置的 AppKey 和 AppSecret\n唤起授权页 调用 SDK 唤起授权接口SDK 会先向运营商发起获取手机号掩码的请求,请求成功后跳到授权页。授权页会显示手机号掩码以及运营商协议给用户确认。\n同意授权并登录 用户同意相关协议点击授权页面的登录按钮SDK 会请求本次取号的 Token请求成功后将 Token 返回给客户端\n取号 将获取到的 Token 发送到自己的服务器,由服务端携带 Token 调用运营商一键登录的接口,调用成功就返回手机号码。服务端用手机号进行登录或注册操作,返回操作结果给客户端,完成一键登录。\n\n三大运营商开放平台移动 - 互联网能力开放平台、电信 - 天翼账号开放平台、联通 - WO+ 开放平台。\n由于国内三大运营商各自有独立的 SDK所以会导致兼容方面的工作会特别繁琐。如果要采用一键登录的方案不妨采用第三方提供了号码认证服务下列几家供应商都拥有手机号码认证能力阿里 - 号码认证服务、创蓝 - 闪验、极光 - 极光认证、mob - 秒验\n在认证过程中需要用户打开蜂窝网络如果手机设备没有插入 SIM 卡、或者关闭蜂窝网络的情况下,是无法完成认证的。所以就算接入一键登录,还是要兼容传统的登录方式,允许用户在失败的情况下,仍能正常完成登录流程。"},"Technology/ComputerSecurity/用户安全/用户鉴权/单点登录Single-Sign-On":{"title":"SSO 单点登录","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"单点登录Single Sign On\n现在随着企业的发展一个大型系统里可能包含 n 多子系统用户在操作不同的系统时需要多次登录很麻烦那么单点登录SSO就可以很好的解决这个问题的在多个应用系统中只需要登录一次就可以访问其他相互信任的应用系统。\n例如登录天猫淘宝也会自动登录登录百度贴吧百度网盘也会自动登录。\n同域下的 SSO主域名相同\n当百度网站存在两个相同主域名下的贴吧子系统 tieba.baidu.com 和网盘子系统 pan.baidu.com 时,以下为它们实现 SSO 的步骤:\n\n客户端 用户访问某个子系统时(例如 tieba.baidu.com如果没有登录则跳转至 SSO 认证中心提供的登录页面进行登录。\n服务端 登录认证后,服务端把登录用户的信息存储于 Session 中,并且附加在响应头的 Set-Cookie 字段中,设置 Cookie 的 Domain 为 .baidu.com \n客户端再次发送请求时携带主域名 Domain 下的 Cookie 给服务器,此时服务端就可以通过该 Cookie 来验证登录状态了;\n\n跨域下的 SSO主域名不同\n在我们常见的购物网站天猫tmall.com和 淘宝taobao.com我们只需要登录其中某一个系统另外一个系统打开后就会默认登录那么这是怎么做的呢\n那么就有了 CASCentral Authentication Service中央授权服务那么我们先主要说下 CAS 的流程。\n单点登录下的 CAS 认证流程图\n\n单点登录下的 CAS 认证步骤详解\n\n客户端 访问系统 A。\n系统 A 发现用户未登录,重定向至 CAS 认证服务sso.com同时 URL 地址参数携带登录成功后回跳到系统 A 的页面链接 sso.com/login…\nCAS 认证服务: 发现请求 Cookie 中没有携带登录的票据凭证TGC所以 CAS 认证服务判定用户处于未登录状态,重定向用户页面至 CAS 的登录界面,用户在 CAS 的登录页面上进行登录操作。\n客户端 输入用户名密码进行 CAS 系统认证;\nCAS 认证服务: 校验用户信息,并且生成 TGC 放入自己的 Session 中,同时以 Set-Cookie 形式写入 Domain 为 sso.com 的域下 ;同时生成一个授权令牌 ST (Service Ticket),然后重定向至系统 A 的地址,重定向的地址中包含生成的 ST重定向地址 www.taobao.com\n系统 A 拿着 ST 向 CAS 认证服务发送请求CAS 认证服务验证票据 (ST) 的有效性。验证成功后,系统 A 知道用户已经在 CAS 登录了(其中的 ST 可以保存到 Cookie 或者本地中),系统 A 服务器使用该票据 (ST) 创建与用户的会话,称为局部会话,返回受保护资源。\n\n到这里客户端就可以跟系统 A 愉快的交往啦 ~\n\n客户端 开始访问系统 B。\n系统 B 发现用户未登录,重定向至 SSO 认证服务,并将自己的地址作为参数传递,并附上在 sso.com 域下的 cookie 值是第五步生成的 TGC。\nCAS 认证服务: CAS 认证服务中心发现用户已登录,跳转回系统 B 的地址,并附上票据 (ST) ;\n系统 B 拿到票据 (ST),去 CAS 认证服务验证票据 (ST) 的有效性。验证成功后,客户端也可以跟系统 B 交往了 ~\n\n单点登录下需要注意的地方\n如图中流程所示我们发现 CAS 认证服务在签发的授权令牌 ST 后,直接重定向,这样其实是比较容易容易被窃取,那么我们需要在系统 A 或者系统 B 在向 CAS 验证成功 (如图中的第 14 步和第 11 步) 后,再生成另一个新的验证 Token 返回给客户端保存。\nCAS 常用接口\n\nlogin登录接口用于登录到中央授权服务\nlogout登出接口用于从中央授权服务中登出\nvalidate用于验证用户是否登录中央授权服务\nserviceValidate用于让各个 Service 验证用户是否登录中央授权服务\n\nCAS 生成的票据\n\nTGTTicket Grangting Ticket TGT 是 CAS 为用户签发的登录票据,拥有了 TGT用户就可以证明自己在 CAS 成功登录过。\nTGCTicket Granting Cookie CAS Server 生成 TGT 放入自己的 Session 中,而 TGC 就是这个 Session 的唯一标识SessionId以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。\nSTService Ticket ST 是 CAS 为用户签发的访问某个 Service 的票据。\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/唯一登录":{"title":"唯一登录","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"唯一登录\n唯一登录定义\n唯一登录是指禁止多人同时登录同一账号后者的登录行为会导致前者掉线。\n通俗点讲就是A 账号在 A 电脑上登录后A 账号此时又用 B 电脑再次登录,则 A 电脑请求页面时,提示“重新登录”的信息,并跳转到登录页面\n唯一登录流程图\n\n唯一登录步骤详解\n用户 - 客户端 A 操作\n\n输入账号请求登录接口。\n后端生成对应 Token 并且返回给客户端 A并且在服务端保存一个登录状态。\n客户端 A 保存 Token并且每次请求都在 header 头中携带对应的 Token。\n\n用户 - 客户端 B 操作\n\n输入账号请求登录接口。\n……\n\n用户在客户端 B 上开始登录操作时,我们会发现,步骤和在客户端 A 上面的操作几乎是一致的。只是后端在生成新的 Token 时,要先验证登录状态,然后再生成对应新的 Token"},"Technology/ComputerSecurity/用户安全/用户鉴权/扫码登录":{"title":"扫码登录","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"扫码登录\n扫码登录定义\n扫码登录通常见于移动端 APP 中,很多 PC 端的网站都提供了扫码登录的功能,无需在网页上输入任何账号和密码,只需要让移动端 APP如微信、淘宝、QQ 等等)中已登录用户主动扫描二维码 ,再确认登录,以使 PC 端的同款应用得以快速登录的方式就是扫码登录 。\n二维码定义\n二维码又称二维条码常见的二维码为 QR CodeQR 全称 Quick Response是一个近几年来移动设备上超流行的一种编码方式它比传统的 Bar Code 条形码能存更多的信息,也能表示更多的数据类型。\n扫码登录的认证流程图\n\n扫码登录的步骤详解\n1. 待扫码阶段\n\n**桌面端:**打开某个网站(如 taobao.com或者某个 APP 的扫码登录入口;就会携带 PC 端的设备信息向服务端发送一个获取二维码的请求。\n**服务端:**服务器收到请求后,随机生成一个 UUID 作为二维码 ID并将 UUID 与桌面端的设备信息关联起来存储在 Redis 服务器中,然后返回给 PC 端;同时设置一个过期时间,在过期后,用户登录二维码需要进行刷新重新获取。\n**桌面端:**收到二维码 ID 之后,将二维码 ID 以二维码的形式展示,等待移动端扫码。并且此时的桌面端开始轮询查询二维码状态,直到登录成功。\n如果移动端未扫描那么一段时间后二维码会自动失效。\n\n2. 已扫码待确认阶段\n\n\n**移动端:**打开手机端对应已登录的 APP (微信或淘宝等),开始扫描识别桌面端展示的二维码;移动端扫描二维码后,会自动获取到二维码 ID并将移动端登录的信息凭证Token和二维码 ID 作为参数发送给服务端,此时手机必须是已登录(使用扫描登录的前提是移动端的应用为已登录状态,这样才可以共享登录态)。\n\n\n**服务端:**收到手机端发来的请求后,会将 Token 与二维码 ID 关联为什么需要关联呢因为当我们在使用微信时移动端退出时PC 端也应该随之退出登录,这个关联就起到这个作用。然后会生成一个临时 Token这个 Token 会返回给移动端,一次性 Token 用作确认时的凭证。\n\n\n3. 已确认阶段\n\n\n**移动端:**收到确认信息后,点击确认按钮,移动端携带上一步中获取的临时 Token 发送给服务端校验;\n\n\n**服务端:**服务端校验完成后,会更新二维码状态,并且给 PC 端生成一个正式的 Token后续 PC 端就是持有这个 Token 访问服务端。\n\n\n**桌面端:**轮询到二维码状态为已登录状态,并且会获取到了生成的 Token完成登录后续访问都基于 Token 完成。\n\n"},"Technology/ComputerSecurity/用户安全/用户鉴权/联合登录和信任登录":{"title":"联合登录和信任登录","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"联合登录和信任登录\n联合登录定义\n联合登录指同时包含多种凭证校验的登录服务同时也可以理解为使用第三方凭证进行校验的登录服务。\n通俗点讲对于两个网站 A 和 B在登录 A 网站的时候用 B 网站的帐号密码,就是联合登录,或者登录 B 网站的时候使用 A 网站的帐号密码,也是联合登录。\n这样的概念其实与上面所讲的 OAuth2.0 的用户名密码式模式认证方式类似。最经典的莫过于 APP 内嵌 H5 的使用场景,当用户从 APP 进入内嵌的 H5 时,我们希望 APP 内已登录的用户能够访问到 H5 内受限的资源,而未登录的用户则需要登录后访问。\n这里思路主要有两种一种是原生跳转内嵌 H5 页面时,将登录态 Token 附加在 URL 参数上,另一种则是内嵌 H5 主动通过与原生客户端制定的协议获取应用内的登录状态。\n信任登录定义\n信任登录是指所有不需要用户主动参与的登录例如建立在私有设备与用户之间的绑定关系凭证就是私有设备的信息此时不需要用户再提供额外的凭证。信任登录又指用第三方比较成熟的用户库来校验凭证并登录当前访问的网站。\n通俗点讲 在 A 网站有登录状态的时候,可以直接跳转到 B 网站而不用登录,就是信任登录。\n目前比较常见的第三方信任登录帐号如QQ 号淘宝帐号、支付宝帐号、微博帐号等。我们不难发现 OAtuth 2.0 其实就是信任登录的缩影,因为正是有了 OAuth我们的信任登录才得以实现。"},"Technology/ComputerSecurity/用户安全/简明指南":{"title":"简明指南","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"认证\n**认证Identification**是指根据声明者所特有的识别信息,确认声明者的身份。你需要用身份证证明你自己是你自己。比如我们常见的认证技术:身份证、用户名和密码、用户手机:手机短信、手机二维码扫描、手势密码、电子邮箱、指纹、语音、眼睛虹膜、大数据识别等等\n授权\n授权Authorization在信息安全领域是指资源所有者委派执行者赋予执行者指定范围的资源操作权限以便对资源的相关操作。\n\n\n现实生活领域银行卡由银行派发、门禁卡由物业管理处派发、钥匙由房东派发这些都是现实生活中授权的实现方式。\n\n\n互联网领域 Web 服务器的 Session 机制、Web 浏览器的 Cookie 机制、颁发授权令牌Token等都是一个授权的机制。\n\n\n鉴权\n鉴权Authentication在信息安全领域是指对于一个声明者所声明的身份权利对其所声明的真实性进行鉴别确认的过程。若从授权出发则会更加容易理解鉴权。授权和鉴权是两个上下游相匹配的关系先授权后鉴权。\n\n\n现实生活领域 门禁卡需要通过门禁卡识别器,银行卡需要通过银行卡识别器;\n\n\n互联网领域 校验 Session / Cookie / Token 的合法性和有效性\n\n\n鉴权是一个承上启下的一个环节上游它接受授权的输出校验其真实性后然后获取权限Permission这个将会为下一步的权限控制做好准备。\n权限控制\n权限控制Access/Permission Control 将可执行的操作定义为权限列表,然后判断操作是否允许/禁止。对于权限控制,可以分为两部分进行理解:一个是权限,另一个是控制。权限是抽象的逻辑概念,而控制是具体的实现方式。\n\n\n现实生活领域 以门禁卡的权限实现为例,一个门禁卡,拥有开公司所有的门的权限;一个门禁卡,拥有管理员角色的权限,因而可以开公司所有的门。\n\n\n互联网领域 通过 Web 后端服务,来控制接口访问,允许或拒绝访问请求。\n\n\n认证、授权、鉴权和权限控制的关系\n\n认证、授权、鉴权和权限控制这四个环节是一个前后依次发生、上下游的关系需要说明的是这四个环节在有些时候会同时发生。 例如在下面的几个场景:\n\n\n使用门禁卡开门 认证、授权、鉴权、权限控制四个环节一气呵成,在瞬间同时发生。\n\n\n用户的网站登录 用户在使用用户名和密码进行登录时,认证和授权两个环节一同完成,而鉴权和权限控制则发生在后续的请求访问中,比如在选购物品或支付时。\n\n"},"Technology/ComputerSecurity/系统安全/防火墙/网络端口大全":{"title":"网络端口大全","links":[],"tags":["计算机安全/系统安全","技术/计算机安全"],"content":"引言\n网络端口是在网络通信中用于标识特定服务或应用程序的数字标识符。它们用于在计算机之间建立连接和传输数据。网络端口分为硬件设备中的端口和 TCP/IP 协议中的端口两种含义。\n硬件设备中的端口是指交换机、路由器等网络设备中用于连接其他设备的接口例如 SC 端口等。\nTCP/IP 协议中的端口是指在网络通信中使用的端口号用于标识特定的服务或应用程序。TCP/IP 协议是互联网使用的基本协议之一它定义了数据如何在网络中进行传输和通信的规则。为了满足网络通信的需求TCP/IP 协议引入了软件端口的概念,允许计算机跨越空间限制进行连接和通信。\n根据端口号的范围网络端口可以分为以下三类\n\n**公认端口Well-Known Ports范围从 0 到 1023也被称为常用端口。**这些端口与一些特定的服务紧密绑定,例如 FTP 服务的 21 端口、HTTP 服务的 80 端口等。\n**注册端口Registered Ports范围从 1024 到 49151这些端口松散地绑定于一些服务。**许多服务可能使用这些端口,并且这些端口也可能用于其他目的。\n**动态和/或私有端口Dynamic and/or Private Ports范围从 49152 到 65535。**根据理论,常用服务不应分配到这些端口上。然而,实际上,一些特殊的程序,特别是一些恶意软件(如木马程序),经常使用这些端口。\n\n此外端口还可以根据所使用的传输协议分为 TCP 协议端口和 UDP 协议端口。TCP传输控制协议和 UDP用户数据报协议是 TCP/IP 协议族中常用的传输层协议。一些常见的端口和它们所对应的协议包括 FTP使用 21 端口TCP 协议、SMTP使用 25 端口TCP 协议、HTTP使用 80 端口TCP 协议、DNS使用 53 端口UDP 协议)等。\n端口\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n端口服务描述0Reserved通常用于分析操作系统。1tcpmux用于寻找 SGI Irix 机器。7Echo发送信息到广播地址的端口。19Character Generator仅发送字符的服务。21FTPFTP 服务器所开放的端口用于上传和下载文件。22Ssh用于寻找 ssh。23Telnet远程登录入侵者搜索远程登录 UNIX 的服务。25SMTPSMTP 服务器所开放的端口用于发送邮件。31MSG Authentication木马 Master Paradise、Hackers Paradise 开放此端口。42WINS ReplicationWINS 复制端口。53DNSDNS 服务器所开放的端口用于域名解析。67Bootstrap Protocol Server通过广播请求地址的端口。69Trivial File Transfer用于从系统下载启动代码的服务。79Finger Server用于获得用户信息的服务。80HTTP用于网页浏览的端口。99Metagram Relay后门程序 ncx99 开放此端口。102Message transfer agent (MTA)-X.400 over TCP/IP消息传输代理。109Post Office Protocol - Version 3用于接收邮件的 POP3 服务器端口。110SUN 公司的 RPC 服务所有端口SUN 公司的 RPC 服务开放的端口。113Authentication Service用于鉴别 TCP 连接的用户的服务。137NETBIOS Name Service用于传输文件的服务。138NETBIOS Name Service用于传输文件的服务。139NETBIOS/SMB 服务用于 Windows 文件和打印机共享的服务。143Interim Mail Access Protocol v2用于电子邮件的 IMAP 服务。161SNMP用于远程管理设备的协议。177X Display Manager Control Protocol用于访问 X-windows 操作台的服务。389LDAP, ILS轻型目录访问协议和 NetMeeting Internet Locator Server 的共用端口。443HTTPS提供加密和通过安全端口传输的 HTTP 服务。456[NULL]木马 HACKERS PARADISE 开放此端口。513Login, remote login从使用 cable modem 或 DSL 登陆到子网中的 UNIX 计算机发出的广播。548Macintosh, File Services (AFP/IP)用于 Macintosh 文件服务的端口。553CORBA IIOP (UDP)CORBA 面向对象的 RPC 系统的端口。555DSF木马 PhAse1.0、Stealth Spy、IniKiller 开放此端口。568Membership DPA成员资格 DPA 的端口。569Membership MSN成员资格 MSN 的端口。635mountdLinux 的 mountd Bug 的端口。636LDAPSSL 端口。666Doom Id Software木马 Attack FTP、Satanz Backdoor 开放此端口。993IMAPSSL 端口。1001[NULL]木马 Silencer、WebEx 开放此端口。1011[NULL]木马 Doly Trojan 开放此端口。1024Reserved动态端口的开始许多程序使用此端口连接网络。1025network blackjack[NULL]1033[NULL]木马 netspy 开放此端口。1080SOCKS以通道方式穿过防火墙的协议允许防火墙后面的人通过一个 IP 地址访问 INTERNET。1170[NULL]木马 Streaming Audio Trojan、Psyber Stream Server、Voice 开放此端口。1234[NULL]木马 SubSeven2.0、Ultors Trojan 开放此端口。1243[NULL]木马 SubSeven1.0/1.9 开放此端口。135Location ServiceMicrosoft 的 DCOM 服务运行的端口。1370[NULL]木马 DeltaSource 开放此端口。1390[NULL]木马 Gatecrasher、Priority 开放此端口。1433SQLMicrosoft 的 SQL 服务开放的端口。1492stone-design-1木马 FTP99CMP 开放此端口。1500RPC client fixed port session queries用于固定端口会话查询的 RPC 客户端。1503NetMeeting T.120NetMeeting T.120 端口。1600issd木马 Phineas Phucker 开放此端口。1720NetMeetingNetMeeting H.233 呼叫设置。1731NetMeeting Audio Call ControlNetMeeting 音频调用控制。1807[NULL]木马 SpySender 开放此端口。1981[NULL]木马 ShockRave 开放此端口。1999cisco identification port木马 BackDoor 开放此端口。2000[NULL]木马 GirlFriend 1.3、Millennium 1.0 开放此端口。2001[NULL]木马 Millennium 1.0、Trojan Cow 开放此端口。2023xinuexpansion 4木马 Pass Ripper 开放此端口。2049NFSNFS 程序常运行于此端口。2115[NULL]木马 Bugs 开放此端口。2140[NULL]木马 Phineas Phucker 开放此端口。2583[NULL]木马 Wincrash 2.0 开放此端口。2801[NULL]木马 Phineas Phucker 开放此端口。3024[NULL]木马 WinCrash 开放此端口。3129[NULL]木马 Master Paradise 开放此端口。3150[NULL]木马 The Invasor 开放此端口。3210[NULL]木马 SchoolBus 开放此端口。3333dec-notes木马 Prosiak 开放此端口。3389超级终端WINDOWS 2000 终端开放此端口。3700[NULL]木马 Portal of Doom 开放此端口。3996[NULL]木马 RemoteAnything 开放此端口。4000QQ 客户端腾讯 QQ 客户端开放此端口。4092[NULL]木马 WinCrash 开放此端口。4590[NULL]木马 ICQTrojan 开放此端口。5000[NULL]木马 blazer5 开放此端口。5001[NULL]木马 Sockets de Troie 开放此端口。5321[NULL]木马 Sockets de Troie 开放此端口。5400[NULL]木马 Blade Runner 开放此端口。5401[NULL]木马 Blade Runner 开放此端口。5402[NULL]木马 Blade Runner 开放此端口。5550[NULL]木马 xtcp 开放此端口。5569[NULL]木马 Robo-Hack 开放此端口。5631pcanywhere-dataSymantec pcAnywhere 远程控制软件使用的数据端口。5632pcanywhere-udpSymantec pcAnywhere 远程控制软件使用的 UDP 端口。5742[NULL]木马 WinCrash 开放此端口。5822[NULL]木马 KillU2 开放此端口。5900VNCVirtual Network Computing 远程控制软件使用的端口。6000X WindowX-Window 系统默认的端口。6667IRCInternet Relay Chat 使用的端口。7000[NULL]木马 Remote Grab 开放此端口。7215[NULL]木马 PSX 开放此端口。8080HTTP另一种用于网页浏览的端口。8222[NULL]木马 Prosiak 开放此端口。8443HTTPS提供加密和通过安全端口传输的 HTTP 服务。8888[NULL]木马 Blazer5 开放此端口。9898[NULL]木马 Dabber 开放此端口。9988[NULL]木马 MassDestruction 开放此端口。9989[NULL]木马 iNi-Killer 开放此端口。11000[NULL]木马 SennaSpy 开放此端口。11223[NULL]木马 Progenic trojan 开放此端口。12076[NULL]木马 Telecommando 开放此端口。61466[NULL]木马 Telecommando 开放此端口。12223[NULL]木马 Hack99 KeyLogger 开放此端口。12345[NULL]木马 NetBus1.60/1.70、GabanBus 开放此端口。12346[NULL]木马 NetBus1.60/1.70、GabanBus 开放此端口。12361[NULL]木马 Whack-a-mole 开放此端口。13223PowWowPowWow 是 Tribal Voice 的聊天程序。16969[NULL]木马 Priority 开放此端口。17027Conducent公司内部安装了带有 Conducent”adbot” 的共享软件。19191[NULL]木马蓝色火焰开放此端口。20000[NULL]木马 Millennium 开放此端口。20001[NULL]木马 Millennium 开放此端口。20034[NULL]木马 NetBus Pro 开放此端口。21554[NULL]木马 GirlFriend 开放此端口。22222[NULL]木马 Prosiak 开放此端口。23456[NULL]木马 Evil FTP、Ugly FTP 开放此端口。26274[NULL]木马 Delta 开放此端口。47262[NULL]木马 Delta 开放此端口。27374[NULL]木马 Subseven 2.1 开放此端口。30100[NULL]木马 NetSphere 开放此端口。30303[NULL]木马 Socket23 开放此端口。30999[NULL]木马 Kuang 开放此端口。31337[NULL]木马 BO (Back Orifice) 开放此端口。31338[NULL]木马 BO (Back Orifice)、DeepBO 开放此端口。31339[NULL]木马 NetSpy DK 开放此端口。31666[NULL]木马 BOWhack 开放此端口。33333[NULL]木马 Prosiak 开放此端口。34324[NULL]木马 Tiny Telnet Server、BigGluck、TN 开放此端口。40412[NULL]木马 The Spy 开放此端口。40421[NULL]木马 Masters Paradise 开放此端口。40422[NULL]木马 Masters Paradise 开放此端口。40423[NULL]木马 Masters Paradise 开放此端口。40426[NULL]木马 Masters Paradise 开放此端口。43210[NULL]木马 SchoolBus 1.0/2.0 开放此端口。54321[NULL]木马 SchoolBus 1.0/2.0 开放此端口。44445[NULL]木马 Happypig 开放此端口。50766[NULL]木马 Fore 开放此端口。53001[NULL]木马 Remote Windows Shutdown 开放此端口。65000[NULL]木马 Devil 1.03 开放此端口。"},"Technology/ComputerSecurity/网络安全/OpenSSH/OpenSSH-使用方法":{"title":"OpenSSH 使用方法","links":[],"tags":["计算机安全/网络安全","技术/计算机安全"],"content":"入门\n下载和安装\n在大多数基于 Linux 的操作系统中OpenSSH 都已经预安装。如果没有可以使用系统的包管理器进行安装。\n# 在 Ubuntu 或 Debian 上\nsudo apt-get update\nsudo apt-get install openssh-server\n \n# 在 CentOS 或 Fedora 上\nsudo yum install openssh-server\nsudo dnf install openssh-server\n\nMacOS 系统:在 MacOS 上OpenSSH 已经预安装。\nWindows 系统:在 Windows 10 上,你可以阅读官方文档《安装 OpenSSH》\n\n安装验证\n如果 OpenSSH 已经成功安装,这个命令将输出你安装的 OpenSSH 版本。\n$ ssh -V\nOpenSSH_8.4p1 Debian-5+deb11u1, OpenSSL 1.1.1n 15 Mar 2022\n配置\n配置文件\nOpenSSH 的配置文件在 /etc/ssh 目录中,以下是该目录中的部分重要文件及其功能的简述:\n\nmoduli该文件包含了用于 Diffie-Hellman 密钥交换的大素数群,它们用于在客户端和服务器之间安全地协商出一个共享的对称密钥。\nssh_config这是 SSH 客户端的全局配置文件,定义了默认的 SSH 客户端行为。每个用户可以在他们的 ~/.ssh/config 文件中覆盖这些默认设置。\nssh_config.d这个目录包含了 ssh_config 文件的碎片,这些碎片在加载 ssh_config 时一起被读取,使得配置管理更加模块化。\nsshd_config这是 SSH 服务器的全局配置文件,定义了 SSH 服务器的行为。可以在这个文件中进行多项设置,如允许的身份验证方法,是否允许 root 登录,使用的端口号等。\nsshd_config.d类似于 ssh_config.d这个目录包含了 sshd_config 文件的碎片,这些碎片在加载 sshd_config 时一起被读取。\nssh_host_ecdsa_key 和 ssh_host_ecdsa_key.pub这是服务器的 ECDSA 密钥对。私钥 ssh_host_ecdsa_key 代表服务器的身份证明,不应该被公开,而公钥 ssh_host_ecdsa_key.pub 在客户端首次连接时发送给客户端,客户端将其存储为已知的主机密钥。\nssh_host_ed25519_key 和 ssh_host_ed25519_key.pub这是服务器的 Ed25519 密钥对,其作用与 ECDSA 密钥对相似。\nssh_host_rsa_key 和 ssh_host_rsa_key.pub这是服务器的 RSA 密钥对,其作用与 ECDSA 密钥对相似。\nssh_import_id该文件用于导入其他系统中的公钥例如可以从 GitHub 中导入公钥。\n\n常用配置\nOpenSSH 的配置文件中有许多可用的选项,你可以根据自己的需要进行设置。以下是一些常用配置的详细介绍:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置项描述示例Port定义 OpenSSH 服务器监听的端口,通常为 22Port 2222PermitRootLogin控制是否允许 root 用户通过 SSH 登录PermitRootLogin noPubkeyAuthentication控制是否允许使用公钥认证PubkeyAuthentication yesPasswordAuthentication控制是否允许使用密码认证如果已使用公钥认证可以关闭此项增加安全性PasswordAuthentication noAllowUsers / AllowGroups定义允许 SSH 登录的用户或用户组AllowUsers user1 user2 AllowGroups group1 group2DenyUsers / DenyGroups定义禁止 SSH 登录的用户或用户组,如果用户同时出现在 Allow 和 Deny 列表中Deny 优先DenyUsers user3 user4 DenyGroups group3 group4AuthorizedKeysFile定义存储用户公钥的文件路径用于公钥认证AuthorizedKeysFile .ssh/authorized_keys\n每次修改了配置文件后你都需要手动重启 SSH 服务来使更改生效。\nsudo systemctl restart ssh\n生成 SSH 密钥\n使用 ssh-keygen 命令可以来生成 SSH 密钥对:\n$ ssh-keygen -t rsa -b 4096\nGenerating public/private rsa key pair.\nEnter file in which to save the key (/home/sevenwate/.ssh/id_rsa):\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in /home/sevenwate/.ssh/id_rsa\nYour public key has been saved in /home/sevenwate/.ssh/id_rsa.pub\nThe key fingerprint is:\nSHA256:pgYyQB1Xcw4eZPtY/7ejynt9u5svQWkiRksKfi4diIo sevenwate@ubuntu\nThe key's randomart image is:\n+---[RSA 4096]----+\n| .....oB . |\n|. .. + B o |\n|. o = * . . |\n| . . o B = . + |\n| .o.. =S+ o + |\n|E .o ..oo . . |\n| o. ..o |\n| . . .oo+|\n| ++..BO|\n+----[SHA256]-----+\n这个命令会在 ~/.ssh/ 目录下生成两个文件id_rsa私钥和 id_rsa.pub公钥。你可以将公钥添加到远程服务器的 ~/.ssh/authorized_keys 文件中,然后就可以使用密钥对进行认证了。\n防火墙配置\n如果服务器启用了防火墙需要服务器开放 SSH 端口(默认为 22才能接受 SSH 连接。在使用 iptables 的系统中,可以使用以下命令:\nsudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT\n工具\nSsh\nssh 是用于远程登录或者在远程主机上执行命令。\n# 远程登录\n$ ssh [options] [user@]hostname\n# 在远程主机上执行命令\n$ ssh [options] [user@]hostname [command]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-p <port>指定连接服务器的端口,如果 SSH 服务器没有使用默认端口 22-i <identity_file>指定用于连接服务器的私钥文件-l <user>指定登录远程主机的用户名-X启用 X11 转发,这样可以在远程主机上运行图形程序-N不执行远程命令这通常与 -L, -D, -w 等选项一起使用-f后台运行 SSH-q安静模式不显示连接、认证的相关信息-v, -vv, -vvv调试模式输出详细的调试信息-L <port:host:hostport>设置本地端口转发,把本地的某个端口的流量转发到远程的某个端口-R <port:host:hostport>设置远程端口转发,把远程的某个端口的流量转发到本地的某个端口-D <[bind_address:]port>设置动态端口转发,创建 SOCKS 代理\nScp\nscp 是用于在本地主机和远程主机之间,或者两个远程主机之间复制文件的命令行工具。\n# 从本地复制文件到远程主机\n$ scp [options] source_file user@remote:/path/to/destination\n# 从远程主机复制文件到本地\n$ scp [options] user@remote:/path/to/source /path/to/local/destination\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-P <port>通过指定端口连接到远程主机-p保留原文件的修改时间和访问时间-r递归复制用于目录的复制-v详细模式显示出处理过程-q安静模式不显示复制过程-c <cipher>指定加密算法,如 aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, etc.-i <identity_file>选择私钥文件,用于密钥认证\nSftp\nsftp 是一个用于安全地传输文件的网络协议。可以使用 sftp 命令在你的计算机和远程服务器之间传输文件,就像使用 FTP 一样。\n# 连接到远程服务器\n$ sftp [user@]hostname\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-b <batchfile>指定一个批处理文件执行一系列的 sftp 命令-C启用压缩功能-l <limit>限制使用的带宽,单位是 Kbit/s-o ssh_option可以指定任何 ssh 命令接受的选项-P <port>指定连接服务器的端口,如果 SSH 服务器没有使用默认端口 22-R <num_requests>指定并行请求的最大数量-s subsystem指定要在远程主机上启动的 sftp 子系统-v显示详细的调试信息\n在 sftp 命令行界面,可以使用一系列的命令来操作文件,比如 ls、cd、get、put 等。请注意,虽然这些命令和 Unix shell 中的命令相似,但它们实际上是 sftp 命令的一部分,可能会有一些差异。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令示例描述lssftp> ls列出远程目录的文件cdsftp> cd /path/to/remote/directory更改远程目录lcdsftp> lcd /path/to/local/directory更改本地目录pwdsftp> pwd显示当前远程目录getsftp> get remoteFile下载单个文件mgetsftp> mget remoteFile1 remoteFile2下载多个文件putsftp> put localFile上传单个文件mputsftp> mput localFile1 localFile2上传多个文件mkdirsftp> mkdir /path/to/remote/directory在远程服务器上创建目录rmdirsftp> rmdir /path/to/remote/directory在远程服务器上删除目录renamesftp> rename oldname newname在远程服务器上重命名文件或目录rmsftp> rm /path/to/remote/file在远程服务器上删除文件bye 、 exitsftp> bye 、 sftp> exit退出 sftp 会话helpsftp> help显示帮助信息\nSsh-keygen\nssh-keygen 是一个用于创建、管理和转换认证密钥的工具ssh-keygen 是 OpenSSH 套件中的一个重要组成部分。\n# 不带任何参数运行 ssh-keygen 会创建一个新的 RSA 密钥对\n$ ssh-keygen\n# 或者你可以明确指定生成密钥的类型和密钥长度\n$ ssh-keygen -t <type> -b <bits>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-t <type>生成指定类型的密钥,比如 rsa、dsa、ecdsa、ed25519 等-b <bits>指定密钥长度,对于 RSA 密钥,建议至少使用 2048 位-f <filename>指定生成的私钥文件的名称和位置-C <comment>为密钥添加注释,这对于区分密钥非常有帮助-N <new_passphrase>为生成的私钥设置一个新的密码-P <old_passphrase>提供现有私钥的密码,用于更改私钥的密码或者生成无密码私钥-y输出私钥文件对应的公钥-q安静模式不输出多余信息-p更改现有私钥的密码-l -f <filename>显示指定公钥文件的 fingerprint-e -f <filename>以 RFC4716 SSH 公钥文件格式或者 PEM 公钥文件格式输出公钥-i -f <filename>读取未知类型的 SSH2 或者 PEM 公钥文件,转换为 SSH2 公钥文件格式\n注意如果你想要创建一个没有密码的私钥你可以在 -N 选项后面留空,或者在运行 ssh-keygen 命令时直接按 Enter 跳过输入密码的步骤。\nSsh-agent\nssh-agent 是一个帮助管理 SSH 私钥的程序,用于保存所有私钥,并在需要进行 SSH 认证时提供这些私钥。ssh-agent 通过在后台运行并维护一个已解锁的私钥列表,可以让你在使用 SSH 客户端进行多个 SSH 连接或操作时避免频繁输入密码。\n# 在后台启动 `ssh-agent`\n$ ssh-agent\n# 在新的 shell 中启动 `ssh-agent`\n$ ssh-agent bash\n# 杀死当前运行的 `ssh-agent` 进程\n$ ssh-agent -k\n\nSsh-add\nssh-add 可以把你的私钥添加到 ssh-agent 的密钥列表中,这样你就可以避免频繁输入密码。一旦你的私钥被添加到 ssh-agent 中,你在使用 SSH 客户端进行认证时就可以直接从 ssh-agent 中获取私钥,无需再手动输入。\n# 尝试添加默认的私钥\n$ ssh-add\n# 添加指定的私钥文件\n$ ssh-add [options] [file ...]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-l列出 ssh-agent 中所有已加载的私钥-L列出 ssh-agent 中所有已加载的私钥,同时输出公钥部分-d <file>从 ssh-agent 中删除指定的私钥-D删除 ssh-agent 中的所有私钥-t <life>为添加的私钥设置生存期,单位是秒-x锁定 ssh-agent需要密码才能解锁-X解锁 ssh-agent\nSsh-keyscan\nssh-keyscan 是一个方便的工具,它允许用户获取和管理公开的 SSH 密钥。当需要扫描和收集远程服务器的 SSH 公钥以用于以后的身份验证时ssh-keyscan 是一个非常有用的工具。\nssh-keyscan [options] host [host2] [host3]...\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-t <type>指定要获取的密钥类型,如 rsa、dsa、ecdsa、ed25519 等-p <port>指定连接服务器的端口,如果 SSH 服务器没有使用默认端口 22-T <timeout>设置连接超时时间,单位是秒-v显示详细输出有助于调试-H将结果中的主机名哈希化这可以防止主机名被保存在已知主机文件中-o <file>将输出写入到指定的文件中\nSsh-copy-id\nssh-copy-id 是一个非常有用的命令,它可以把你的 SSH 公钥复制到远程服务器,以便实现无密码登录。这个命令会自动处理公钥的安装和权限设置。\nssh-copy-id [options] [user@]hostname\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-i <identity_file>指定要复制的身份文件,如果你不使用默认的 ~/.ssh/id_rsa.pub-p <port>指定连接服务器的端口,如果 SSH 服务器没有使用默认端口 22-f强制复制即使远程主机上已经存在相同的公钥-n不实际复制公钥而是只检查和显示远程主机上的公钥-h显示帮助信息\n使用\ngraph LR\nA[开始] --> B{获取服务器公钥}\nB --> C[生成公钥指纹并验证]\nC --> D{添加公钥到 known_hosts}\nD --> E[SSH 登录]\nE --> F[结束]\n\n1. 获取服务器公钥\n你可以在连接前预先使用 ssh-keyscan 命令来获取服务器的公钥:\nssh-keyscan hostname >> hostname.pub\n这将把服务器的公钥保存在 hostname.pub 文件中。记住,这个步骤是可选的,如果你选择直接 SSH 连接到服务器SSH 客户端将会在初次连接时自动获取服务器的公钥。\n2. 生成公钥指纹\n使用 ssh-keygen 命令生成公钥的指纹:\nssh-keygen -lf hostname.pub\n这将输出公钥的指纹你需要通过一个安全的渠道例如通过 HTTPS 的网站或者电话等)获取服务器管理员提供的公钥指纹,然后手动比对这两个指纹是否一致。如果两者一致,你可以确认你将要连接的是正确的服务器。否则,可能存在中间人攻击的风险。\n3. 添加公钥到 known_hosts\n一旦验证了服务器的公钥指纹你可以把公钥添加到 ~/.ssh/known_hosts 文件中这样在下次连接时SSH 客户端就可以自动验证服务器的公钥了。\nssh-keyscan hostname >> ~/.ssh/known_hosts\n4. SSH 登录\n在公钥验证成功后你可以通过 SSH 命令进行登录:\nssh username@example.com\n在登录过程中你可能需要输入用户的密码或者如果你已经设置了 SSH 密钥对,那么可能需要输入私钥的密码。\n请注意所有这些步骤都是为了确保你在 SSH 连接中的安全,通过预先验证服务器的公钥,**可以有效防止中间人攻击。**然而,这并不能替代其他的安全措施,如使用强密码、定期更新密码、使用防火墙和 IDS 等。"},"Technology/ComputerSecurity/网络安全/OpenSSH/OpenSSH-概述":{"title":"OpenSSH 概述","links":[],"tags":["计算机安全/网络安全","技术/计算机安全"],"content":"引言\nSSHSecure Shell安全外壳是一种用于通过互联网或其他不受信任的网络进行安全的系统管理、文件传输和其他通信的工具。它加密身份、密码和传输的数据使其无法被窃听和窃取。\n\n**OpenSSH 是 SSH 协议的开源实现。**它基于 Tatu Ylonen 的免费版本,并由 OpenBSD 团队和用户社区进一步开发。\nTatu Ylonen 创建了 SSH 通信安全公司,为企业提供商业支持,原始版本演变为 Tectia SSH。商业版本还支持 Windows 和 IBM 主机z/OS平台并全面支持 X.509 证书和智能卡认证(例如美国政府使用的 CAC 和 PIV 卡)。\n开源版本 以源代码或预编译的二进制文件的形式提供,使用 BSD 风格的许可证。项目团队不为最终用户提供支持服务,但各种安全网络论坛提供基于社区的支持(基于自愿的基础)。\n组成\nOpenSSH (Open Secure Shell) 是一个为安全网络通信提供的套件,包括以下主要工具:\n\n\nssh一个用于远程登录到服务器的程序它可以替代 telnetrlogin 等非安全的远程 shell。SSH 使用加密技术确保所有在本地主机和远程主机之间的通信都是安全的。\n\n\nscp一个用于在本地和远程主机之间复制文件的程序。它也可以替代 rcp 和其他非安全的文件复制程序。\n\n\nsftp一个安全的 FTP 客户端,它可以替代非安全的 FTP 客户端。\n\n\nssh-keygen一个用于创建、管理和转换认证密钥的工具。\n\n\nssh-agent一个用于存储私钥的程序这样用户就可以避免频繁输入密码。\n\n\nssh-add一个用于向 ssh-agent 添加私钥的命令。\n\n\nssh-keyscan一个用于扫描和收集公共 SSH 密钥的工具。\n\n\nssh-copy-id一个用于把本地的 ssh 公钥复制到远程主机的命令,以便无密码登录。\n\n\n以上就是 OpenSSH 套件的主要组成部分。它们共同为网络通信提供了一个安全的框架,防止了数据被窃取或篡改。\n安全性\n加密技术\n\n\n对称密钥加密在对称密钥加密中加密和解密过程中使用的是同一把密钥。\n这种方式在处理大量数据时非常高效但其安全性依赖于密钥的保密性。如果密钥在传输过程中被拦截那么加密的数据就可以被解密。因此对称密钥加密通常与其他加密技术结合使用以保证密钥的安全传输。\n\n\n非对称密钥加密非对称密钥加密使用一对公钥和私钥其中公钥可公开私钥必须保密。私钥和公钥是配对的使用一个加密另一个可以解密。\n这种方式在 OpenSSH 中主要用于两个目的:一是在建立连接时,客户端使用服务器的公钥加密一个随机生成的会话密钥,然后发送给服务器,服务器使用私钥解密得到会话密钥,这样双方就共享了一个密钥,可以使用对称密钥加密进行通信;二是在使用公钥认证时,客户端使用私钥对一段数据进行签名,服务器使用公钥验证签名,以此确认客户端拥有私钥,从而验证其身份。\n\n\nHash 函数Hash 函数可以把任意长度的数据映射到一个固定长度的唯一值,这个值也称为数据的指纹。\n在 OpenSSH 中Hash 函数用于多处,如生成密钥的指纹,验证数据的完整性等。使用 Hash 函数可以在不暴露原始数据的情况下比较两个数据是否一致,或者验证数据是否被篡改。\n\n\n认证方法\n\n\n密码认证密码认证是最基础的认证方式用户需要提供用户名和密码服务器会验证密码是否正确。这种方式简单易用但是密码可能被窃听或者通过暴力破解获取。\n\n\n公钥认证公钥认证是一种更为安全的认证方式用户需要在服务器上提前存储公钥在进行认证时客户端使用私钥对一段数据进行签名服务器使用公钥验证签名以此确认客户端拥有私钥从而验证其身份。这种方式的安全性较高因为私钥不需要在网络上传输而且即使公钥被窃取也无法伪造签名。\n\n\n防范攻击\n\n\n中间人攻击OpenSSH 通过在建立连接时使用非对称密钥加密传输会话密钥,以及在公钥认证时使用私钥签名,公钥验证的方式,防止了中间人攻击。即使中间人能够截获通信数据,也无法获取会话密钥,或者伪造签名。\n\n\n重放攻击在建立连接的过程中客户端和服务器都会生成一个随机数这个随机数只用于当前的会话下一次连接会重新生成。这样即使旧的通信会话被截获也无法被重放因为随机数已经改变。\n\n\n拒绝服务攻击OpenSSH 通过各种机制,如限制并发连接数,限制每秒认证请求的次数,使用 TCP Wrapper 等方式,防止拒绝服务攻击。这样可以防止恶意用户通过大量的无效连接,耗尽服务器的资源。\n\n\n结论\nOpenSSH 提供了一种安全、稳定且灵活的方法,用于通过不安全的网络进行远程登录,文件传输和其他通信。它的开源特性使得它可以被广大的社区审查,并且快速地修复可能存在的安全问题。\n无论是用于个人的远程工作还是用于组织内部的系统管理OpenSSH 都是一个值得信赖的工具。"},"Technology/ComputerSecurity/网络安全/OpenSSL/简明指南":{"title":"简明指南","links":[],"tags":["计算机安全/网络安全","技术/计算机安全"],"content":"OpenSSL 的一般使用\nOpenSSL 是一个开放源代码的软件库包。这个包广泛被应用在互联网的网页服务器上。 其主要库是以 C 语言所写成,实现了基本的加密功能,实现了 SSL 与 TLS 协议。\n\n以下命令均在 cygwin 或 linux 下运行\n以下命令是在这个版本 OpenSSL 1.1.1g 21 Apr 2020 下的 OpenSSL 运行的\n\n\n\n查看 openssl 的版本信息\nopenssl version -a\n\n\n查看帮助这里会输出 openssl 支持的算法\nopenssl help\n\n\n查看某个命令的帮助\nopenssl 某个命令 --help\n\n\n查看密码套件\nopenssl ciphers -v\n\n\n数字摘要\necho "123" | openssl dgst -sha256\nopenssl dgst -sha256 文件路径\necho "123" | openssl dgst -sha256 | awk '{print $2}'\nopenssl dgst -sha256 文件路径 | awk '{print $2}'\n\n\n输出当前时间戳\ndate +%s\n\n\n输出纳秒 这是一个 9 位的数字 一些简单的伪随机数算法会使用纳秒作为种子\ndate +%N\n\n\n生成 32 位随机字符串\nopenssl rand -base64 32\n\n\n输出随机数字\n# 输出随机数字,但无法确定数字的长度\nopenssl rand -base64 32 | tr -dc '0-9'\nopenssl rand -base64 64 | tr -dc '0-9'\n# 生成16位随机数 有可能不足16位\nopenssl rand -base64 128 | tr -dc '0-9' | cut -c1-16\n\n\n查看 对称加密命令和可以使用的算法\nopenssl enc -help\n\n\nenc 使用对称加密算法\nopenssl enc -aes-256-cfb -e -in a.txt -a -out b.txt -pass pass:123\nopenssl enc -aes-256-cfb -d -in b.txt -a -out c.txt -pass pass:123\n# -aes-256-cfb 使用的算法\n# -e 加密\n# -d 解密\n# -in 输入的文件路径\n# -out 输出文件的路径\n# -a 把输出转换成 base64 加密时有这个参数,解密时也要有这个参数\n# -pass 数入密码和输入密码的方式\n# pass\n# file\n# stdio\n# env\n# fd\n\n\n生成 rsa 私钥\nopenssl genrsa -out rsa_private_key.pem 4096\n# 默认是 pem 格式的\n# -out 指定生成文件的路径\n# 最后的 4096 是生成密钥的长度\n# 生成的密钥对是 pkcs1 格式的, openssl 有相应的命令转成 pkcs8 或 pkcs12 格式\n\n\n从私钥中提取公钥\nopenssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem\n# -pubout 提取公钥\n# -out 指定生成文件的路径\n# -in 私钥路径\n\n\n公钥加密文件\nopenssl rsautl -encrypt -in a.txt -inkey rsa_public_key.pem -pubin -out b.txt\n# -out 加密后的文件路径\n# -in 需要加密的文件路径\n# -inkey 公钥路径\n\n\n私钥解密文件\nopenssl rsautl -decrypt -in b.txt -inkey rsa_private_key.pem -out c.txt\n# -out 解密后的文件路径\n# -in 需要解密的文件路径\n# -inkey 私钥路径\n\n\n使用私钥生成签名\nopenssl dgst -sha256 -sign rsa_private_key.pem -keyform PEM -out sign.sha256 a.txt\n# -sha256 哈希算法\n# -sign 私钥路径\n# -keyform 私钥的格式\n# -out 签名生成的路径\n# 最后的 a.txt 是需要生成签名的文件路径\n\n\n使用公钥验证签名\nopenssl dgst -sha256 -verify rsa_public_key.pem -keyform PEM -signature sign.sha256 a.txt\n\n\n对文件的内容进行 base64 编码\nopenssl enc -base64 -e -in sign.sha256 -out sign.sha256.base64\n\n\n对文件的内容进行 base64 解码\nopenssl enc -base64 -d -in sign.sha256.base64 -out sign.sha2562\n\n\n比较两个文件的内容如果两个文件内容一致则不会有输出\ndiff 文件1的路径 文件2的路径\n\n\n生成一个 csr 文件\n\n启动一个问题/回答的交互式会话其它随便填就好extra attributes 可以留空\n其实 openssl 有一键生成密钥对, csr 和 证书的命令\n\n\n\nopenssl req -new \\\n -key rsa_private_key.pem \\\n -keyform PEM \\\n -out myserver.csr\n# -new 生成一个新的 csr 文件\n# -key 私钥文件路径\n# -keyform 私钥的格式\n# -out 生成的 csr 文件路径\n\n\n查看 csr 文件内容\nopenssl req -text -in myserver.csr -noout -verify\n# -in csr 文件路径\n\n\n使用 csr 和 私钥生成自签证书\nopenssl x509 \\\n -sha256 \\\n -signkey rsa_private_key.pem \\\n -in myserver.csr \\\n -req -days 365 -out domain3.crt\n# x509 生成 x509 格式的证书\n# -sha256 证书采用的哈希算法\n# -signkey 私钥路径\n# -in csr 文件路径\n# -days 证书有效天数\n# -out 生成的证书路径\n\n\n一条命令生成密钥和证书\nopenssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt\nopenssl req -newkey rsa:4096 -nodes -keyout rsa_private_key.pem -x509 -days 365 -out domain.crt -subj "/C=CN/ST=State/L=City/O=Ltd/OU=Section/CN=localhost"\n\n\n查看证书内容\nopenssl x509 -in domain.crt -noout -text\n\n\n查看证书序列号\nopenssl x509 -in domain.crt -noout -serial\n\n\n查看证书有效时间\nopenssl x509 -in domain.crt -noout -dates\n\n\n生成多个域名的证书\n一般使用 OpenSSL 生成证书时都是 v1 版的,不带扩展属性。 多域名证书需要用到 v3 版的 extensions 的 Subject Alternative Name (SAN 主题替代名称)\n\n\n寻找默认配置文件\nfind / -name openssl.cnf\n\n\n复制一份默认配置文件\ncp /usr/ssl/openssl.cnf openssl.cnf\n\n\n编辑 openssl.cnf\n\n\n[ req ] 字段下加入 req_extensions = v3_req\n\n\n[ v3_req ] 字段下加入 subjectAltName = @alt_names\n\n\n在配置文件的最后最后新建一个字段 [ alt_names ]\n\n\n在 [ alt_names ] 里按以下格式写入多个域名\n [ alt_names ]\n DNS.1 = 3.example.com\n DNS.2 = 4.example.com\n\n\n\n\n新建私钥\nopenssl genrsa -out rsa_private_key.pem 4096\n\n\n生成 csr 文件\nopenssl req -new \\\n -key rsa_private_key.pem \\\n -keyform PEM \\\n -config openssl.cnf \\\n -out myserver.csr\n\n\n生成数字证书\nopenssl x509 \\\n -sha256 \\\n -signkey rsa_private_key.pem \\\n -in myserver2.csr \\\n -extensions v3_req \\\n -extfile openssl.cnf \\\n -req -days 365 -out domain.crt\n\n\n自建 CA\n\n\n创建 CA 目录\nmkdir -p ~/ssl/demoCA/{certs,newcerts,crl,private}\ncd ~/ssl/demoCA\nTouch index.txt\necho "01" > serial\n\n\n寻找默认配置文件\nfind / -name openssl.cnf\n\n\n复制一份默认配置文件\ncp /usr/ssl/openssl.cnf ~/ssl/openssl.cnf\n\n\n修改 openssl.cnf 文件\n\n\n把 [ CA_default ] 的 dir 修改成 ~/ssl/demoCA/ 的绝对路径,类似于这样\n [ CA_default ]\n dir = /root/ssl/demoCA # Where everything is kept\n\n\n\n\n生成 CA 根证书及密钥\nopenssl req -new -x509 -newkey rsa:4096 -nodes -keyout cakey.key -out cacert.crt -config openssl.cnf -days 365\n\n\n生成客户端私钥\nopenssl genrsa -out client.key 4096\n\n\n用该客户端私钥生成证书签名请求\nopenssl req -new -key client.key -out client.csr -config openssl.cnf\n\n\n使用 CA 根证书签发客户端证书\nopenssl ca -in client.csr -out client.crt -cert cacert.crt -keyfile cakey.key -config openssl.cnf\n\n\n\n\n注意默认要求 国家,省,公司名称三项必须和 CA 一致\n\n\n如果不想一致可以修改 openssl.cnf 的 [ CA_default ] 的 policy 为 policy_anything\n policy = policy_anything\n\n\n证书链合并\n一些情况下从 CA 那里申请到的 SSL 证书需要配置证书链,因为颁发的 CA 只是一个中间 CA 。 这个时候,需要把 CA 的证书和 SSL 证书都转换成 pem 格式。 然后新建一个文件,按照 最终实体证书 → 中间证书 → 根证书 这样的顺序,把证书的 pem 格式的内容复制进去,证书之间用一个空行隔开。 例如这样\n-----BEGIN CERTIFICATE-----\n这是 最终实体证书\n------END CERTIFICATE------\n \n-----BEGIN CERTIFICATE-----\n这是 中间证书\n------END CERTIFICATE------\n \n-----BEGIN CERTIFICATE-----\n这是 根证书\n------END CERTIFICATE------\n根证书大多数情况下都会内置在客户端所以大多数情况下都只需要 最终实体证书 和 中间证书。 有时 中间证书 可能有多个,按照签发顺序排列就好,反正就是下面的证书颁发上面的证书。\n有时还需要把私钥和证书合并成一个文件一般是把私钥放在前面证书放在后面例如 这样\ncat server.key server.crt > server.pem\n其它命令\nopenssl s_time 用于测试 TSL 服务\nopenssl s_server 用于测试 TSL 客户端,例如浏览器对各个加密套件的支持情况\nopenssl s_server -accept 2009 -key rsa_private_key.pem -cert domain.crt -www -debug -msg\n# -accept 监听的端口 -key 私钥路径 -crt 证书路径 -www http请求返回状态信息\n# 可以用浏览器输测试,直接输入网址 https://127.0.0.1:2009\n# 可以用 curl 测试 curl -k -i -v https://127.0.0.1:2009\n# 可以用 openssl s_client 测试 openssl s_client -connect 127.0.0.1:2009 -showcerts\nopenssl s_client 用于测试 TSL 服务端\n\n\n可以像 telnet 那用测试端口\n # 测试 example.com 的 80 端口是否有开启\n openssl s_client -connect example.com:80\n\n\n可以像 telnet 模拟 http 那样,模拟 https\n # 输入这个命令后,会进入一个命令行交互界面,这时快速地输入 GET / HTTP/1.O 然后连续输入两个回车,就能返回网页内容\n openssl s_client -connect www.baidu.com:443 -showcerts\n\n\nopenssl smime 用于处理 S/MIME 邮件,它能加密、解密、签名和验证 S/MIME 消息\nopenssl ca ca 命令是一个小型 CA 系统。它能签发证书请求和生成 CRL。它维护一个已签发证书状态的文本数据库。"},"Technology/ComputerStorage/0.-大纲":{"title":"0. 大纲","links":[],"tags":[],"content":"第一部分:基础知识\n1. 计算机存储基础\n1.1 存储概念与术语\n1.2 存储介质类型\n\n磁盘\nSSD\n光盘\n磁带\n\n1.3 存储单元与数据表示\n\n比特\n字节\n文件系统\n\n1.4 存储性能指标\n\nIOPS\n带宽\n延迟\n\n1.5 存储寿命和耐久性\n1.6 存储访问模式\n\n顺序访问\n随机访问\n\n2. 存储硬件\n2.1 磁盘驱动器HDD工作原理\n\n垂直记录\n叠瓦式磁记录SMR\n\n2.2 固态驱动器SSD工作原理\n\nNVMe SSD 与 SATA SSD 的对比\n\n2.3 RAID独立磁盘冗余阵列技术\n2.4 磁带机与光盘存储\n2.5 硬盘缓存技术\n3. 存储架构\n3.1 直接附加存储DAS\n3.2 网络附加存储NAS\n3.3 存储区域网络SAN\n3.4 存储架构的演变与发展\n3.5 存储网关和中继技术\n第二部分中级知识\n4. 文件系统与数据管理\n4.1 文件系统类型\n\nLinux 主流文件系统\n\nEXT 系列EXT2、EXT3、EXT4\nBtrfs\nXFS\nZFS\n\n\nWindows 主流文件系统\n\nNTFS\nFAT32\nexFAT\nReFS\n\n\nMacOS 主流文件系统\n\nHFS+\nAPFS\n\n\n\n4.2 文件系统结构与管理\n\n文件系统结构\n\n文件系统层次结构\n超级块、索引节点Inode、数据块\n\n\n文件系统管理\n\n文件系统的创建与挂载\n文件系统的格式化和修复\n文件权限与用户管理\n\n\n\n4.3 数据冗余与备份策略\n\n数据冗余技术\n\nRAID 类型与应用\n镜像、奇偶校验与分布式冗余\n\n\n备份策略\n\n全量备份、增量备份与差异备份\n本地备份与远程备份\n备份的恢复与验证\n\n\n\n4.4 分布式文件系统与本地文件系统的对比\n\n分布式文件系统\n\nHadoop Distributed File System (HDFS)\nGoogle File System (GFS)\nGlusterFS\nCephFS\n\n\n本地文件系统\n\n单机文件系统的特性与应用场景\n\n\n对比分析\n\n性能\n可扩展性\n数据一致性\n容错性\n\n\n\n4.5 数据完整性与校验技术\n\n数据完整性\n\n数据一致性检查\n数据腐败检测与恢复\n\n\n校验技术\n\n校验和Checksum\n哈希函数\nECCError Correction Code\n\n\n\n4.6 存储空间配额管理\n\n配额管理概述\n\n配额管理的意义与作用\n\n\n配额管理技术\n\n用户配额与组配额\n软配额与硬配额\n\n\n管理工具与实践\n\nLinux 下的配额管理工具(如 quota 命令)\nWindows 下的配额管理工具(如 FSRM\n\n\n\n5. 存储虚拟化\n5.1 存储虚拟化概念与原理\n\n定义存储虚拟化是一种将物理存储资源抽象为虚拟存储资源的技术使得存储设备可以更灵活和高效地被管理和使用。\n基本原理通过在存储资源和主机之间引入一个虚拟层存储虚拟化将多个物理存储设备整合为一个或多个虚拟存储池。虚拟层负责管理和分配存储资源提供统一的存储访问接口。\n优势\n\n提高存储利用率通过整合分散的存储资源减少未使用的存储空间。\n简化存储管理提供集中化的管理界面简化存储设备的配置和维护。\n提高灵活性能够动态调整和分配存储资源满足不同应用的需求。\n提高数据保护通过快照、复制等技术增强数据的可靠性和可用性。\n\n\n\n5.2 虚拟存储设备与 LUN逻辑单元号\n\n虚拟存储设备\n\n是由存储虚拟化软件创建的抽象存储单元可以映射到物理存储设备或存储池。\n为主机和应用程序提供统一的存储访问接口。\n\n\n逻辑单元号LUN\n\nLUN 是存储虚拟化环境中用于标识虚拟存储设备的唯一标识符。\n主机通过 LUN 访问虚拟存储设备,将其视为普通的存储卷。\nLUN 的创建、分配和管理由存储虚拟化软件控制,能够灵活调整大小和性能参数。\n\n\n\n5.3 软件定义存储SDS\n\n定义SDS 是一种通过软件实现存储资源管理和控制的技术,将存储硬件和软件解耦。\n关键特性\n\n硬件独立性支持多种存储硬件不受特定厂商限制。\n灵活扩展性通过添加软件和硬件资源可以线性扩展存储容量和性能。\n自动化管理利用软件自动完成存储资源的配置、分配和优化减少人工干预。\n数据服务提供高级数据服务如快照、复制、压缩和重删增强数据保护和效率。\n\n\n主要组件\n\n控制层负责存储资源的管理和调度包括存储池的创建和管理。\n数据层实际存储数据的物理存储设备通常包括磁盘、SSD 等。\n管理层提供集中化的管理界面和 API供管理员配置和监控存储系统。\n\n\n\n5.4 存储虚拟化在数据中心的应用\n\n资源整合将分散的存储设备整合为统一的存储池提高存储资源利用率。\n高可用性通过虚拟化技术实现存储的冗余和故障转移确保数据的高可用性和可靠性。\n动态资源分配根据业务需求动态调整存储资源的分配优化性能和成本。\n数据保护利用快照、复制和备份等技术增强数据的保护能力防止数据丢失和损坏。\n简化管理集中化的管理界面和自动化工具简化了存储设备的配置、监控和维护降低了管理复杂度。\n\n5.5 常见的存储虚拟化解决方案\n\nVMware vSAN\n\n概述VMware vSAN 是集成在 VMware vSphere 中的软件定义存储解决方案,通过将服务器的本地存储资源整合为共享存储池。\n特性\n\n高性能利用闪存和 SSD 提高存储性能。\n高可用性提供存储冗余和自动故障转移。\n可扩展性支持线性扩展存储容量和性能。\n集中管理通过 vSphere 管理界面进行统一管理。\n\n\n\n\nMicrosoft Storage Spaces Direct (S2D)\n\n概述S2D 是 Microsoft Windows Server 中的一项功能,通过聚合本地存储资源提供高性能、高可用性的存储解决方案。\n特性\n\n高性能支持使用 NVMe、SSD 和 HDD 实现多层次存储。\n高可用性通过镜像、条带化和纠删码提供数据保护。\n可扩展性支持从两个节点扩展到多个节点的集群。\n集成管理与 Windows Server 深度集成,提供统一的管理和监控工具。\n\n\n\n\n\n6. 存储网络\n6.1 网络存储协议\n\n\niSCSIInternet Small Computer System Interface\n\n定义一种基于 IP 网络的存储协议,通过 TCP/IP 传输 SCSI 指令,使存储设备可以通过网络连接到主机。\n优势低成本、易于配置和扩展适用于中小型企业。\n应用场景虚拟化环境、远程备份和恢复、灾难恢复等。\n\n\n\nFibre ChannelFC\n\n定义一种高速网络协议专门用于存储区域网络SAN通过光纤或铜缆传输数据。\n优势高带宽、低延迟、可靠性高适用于大规模数据中心。\n应用场景企业级存储网络、大型数据库和高性能计算等。\n\n\n\nNFSNetwork File System\n\n定义一种网络文件系统协议允许不同操作系统的计算机通过网络共享文件。\n优势跨平台兼容、易于配置和管理适用于文件共享和协作。\n应用场景企业文件共享、网络附加存储NAS设备、虚拟化环境等。\n\n\n\nSMBServer Message Block\n\n定义一种网络文件共享协议允许计算机通过网络访问和共享文件、打印机和串行端口。\n优势与 Windows 系统深度集成、易于使用,适用于 Windows 环境的文件共享。\n应用场景企业文件共享、家庭网络、网络附加存储NAS设备等。\n\n\n\n6.2 存储网络架构与配置\n\n\n存储区域网络SAN\n\n定义一种专用的高性能网络用于连接存储设备和服务器提供块级存储访问。\n架构由存储设备、交换机、HBA主机总线适配器和光纤通道组成。\n配置包括存储设备的分配和管理、交换机的配置和优化、HBA 的安装和配置。\n\n\n\n网络附加存储NAS\n\n定义一种通过网络提供文件级存储访问的设备通常包含一个或多个硬盘连接到网络并提供文件共享服务。\n架构由 NAS 设备、网络交换机和客户端设备组成。\n配置包括 NAS 设备的设置、网络连接和文件共享配置。\n\n\n\n6.3 数据传输与吞吐量优化\n\n带宽管理确保存储网络有足够的带宽处理数据传输避免网络拥堵。\n负载均衡分配数据流量到多个路径优化网络资源利用率减少单点故障。\nQoS服务质量设置网络服务质量参数优先处理关键任务的数据流提高传输效率。\n缓存技术使用缓存设备或技术如 SSD 缓存)加速数据读取和写入,提高整体吞吐量。\n\n6.4 存储网络的拓扑结构设计\n\n星型拓扑所有存储设备和服务器通过中央交换机连接便于管理和扩展。\n树型拓扑分级连接多个交换机适用于大规模网络提高网络的扩展性和容错性。\n环型拓扑设备之间通过环形连接提供冗余路径提高网络的可靠性。\n网状拓扑每个设备都与多个其他设备连接提供高度冗余和灵活性但管理复杂度高。\n\n6.5 存储网络的安全性与防护\n\n访问控制通过用户身份验证和访问控制列表ACL限制对存储资源的访问。\n数据加密在传输和存储过程中对数据进行加密防止数据泄露和未授权访问。\n防火墙和 VPN使用防火墙保护存储网络免受外部攻击通过 VPN 实现安全的远程访问。\n日志和审计记录所有访问和操作日志定期审计以发现和处理安全威胁。\n\n6.6 存储网络的监控与故障排除\n\n监控工具使用存储网络监控工具如 Nagios、SolarWinds实时监控网络性能和健康状态。\n性能分析定期分析网络性能指标如带宽利用率、延迟、吞吐量识别潜在问题。\n故障排除\n\n诊断工具使用网络诊断工具如 Wireshark捕获和分析网络流量。\n日志分析检查设备日志和错误报告定位问题源。\n冗余路径利用网络冗余路径和设备快速恢复故障提高网络可用性。\n\n\n\n第三部分高级知识\n7. 高性能存储技术\n7.1 NVMe非易失性内存快车\n\n定义NVMeNon-Volatile Memory Express是一种专为 SSD 设计的高性能接口协议,通过 PCIe 总线直接与 CPU 通信,减少了传统 SATA/SAS 接口的瓶颈。\n优势\n\n低延迟直接访问闪存减少了中间层带来的延迟。\n高吞吐量通过并行处理大量 I/O 请求,提高了数据传输速度。\n高并发性支持多个并发命令队列适用于高性能计算和大数据处理。\n\n\n应用场景高性能数据库、虚拟化环境、大数据分析和实时应用等。\n\n7.2 3D NAND 闪存技术\n\n定义3D NAND 是一种垂直堆叠的闪存技术,通过将多个闪存单元垂直堆叠在一起,增加存储密度和容量。\n优势\n\n高密度相比传统 2D NAND3D NAND 能够在相同面积上提供更多的存储容量。\n高耐久性改进的制造工艺和材料使用延长了闪存的寿命。\n低成本更高的存储密度和更低的单位存储成本。\n\n\n应用场景消费级 SSD、企业级存储设备和移动设备等。\n\n7.3 储存级内存SCM\n\n定义储存级内存Storage Class MemorySCM是一种介于 DRAM 和传统存储设备之间的存储技术,结合了内存的高速度和存储设备的非易失性特点。\n类型\n\nIntel Optane基于 3D XPoint 技术的 SCM具有高速度和高耐久性。\nMRAM磁性随机存取存储器利用磁性材料实现数据存储具有高速度和非易失性。\n\n\n优势\n\n低延迟接近 DRAM 的速度,适用于高性能应用。\n高耐久性相比传统闪存具有更高的写入耐久性。\n数据持久性断电后数据不会丢失。\n\n\n应用场景实时数据处理、内存密集型应用和高性能计算等。\n\n7.4 低延迟存储技术\n\nOptane 存储:\n\n定义基于 3D XPoint 技术的存储解决方案,提供了接近 DRAM 的速度和传统存储的非易失性。\n优势\n\n超低延迟大大降低了读取和写入延迟提高了系统响应速度。\n高耐久性支持大量的写入操作适用于高负载环境。\n大容量提供了比传统 DRAM 更高的容量选择。\n\n\n应用场景高频交易、实时分析、内存数据库和高性能计算等。\n\n\n\n7.5 存储缓存层和 Tiering 技术\n\n\n存储缓存层\n\n定义在存储系统中引入高速缓存层将经常访问的数据存储在高速设备上提高数据访问速度。\n技术\n\nSSD 缓存:将部分数据缓存到 SSD提高传统 HDD 的访问速度。\nRAM 缓存:利用内存作为缓存,加速数据的读取和写入操作。\n\n\n优势提高系统的整体性能减少数据访问延迟。\n应用场景数据库加速、虚拟化环境和高性能存储系统等。\n\n\n\nTiering 技术:\n\n定义将存储系统中的数据根据访问频率和重要性分层存储在不同性能和成本的存储设备上。\n技术\n\n自动分层通过存储管理软件自动识别和移动数据到合适的存储层。\n手动分层管理员根据业务需求手动调整数据存储位置。\n\n\n优势优化存储资源利用提高存储系统的性能和成本效益。\n应用场景企业存储系统、大数据分析和混合存储环境等。\n\n\n\n8. 数据保护与安全\n8.1 数据加密技术\n\n定义数据加密是通过算法将明文数据转换为密文只有授权用户才能解密和访问数据。\n类型\n\n对称加密使用同一个密钥进行加密和解密如 AES、DES。\n非对称加密使用公钥加密私钥解密如 RSA、ECC。\n\n\n应用\n\n存储加密对存储设备中的数据进行加密保护静态数据的安全。\n传输加密对网络传输的数据进行加密保护传输过程中的数据安全。\n\n\n实施\n\n硬件加密利用硬件设备如硬件安全模块HSM进行数据加密。\n软件加密通过软件工具如 OpenSSL实现数据加密。\n\n\n\n8.2 存储安全策略与实施\n\n定义存储安全策略是为保护存储系统及其数据免受威胁和攻击而制定的规则和措施。\n主要策略\n\n访问控制通过身份验证和授权管理限制对存储系统和数据的访问。\n数据隔离将敏感数据与其他数据隔离减少数据泄露风险。\n审计和监控对存储系统的访问和操作进行记录和监控及时发现和应对安全事件。\n\n\n实施步骤\n\n风险评估识别存储系统的安全风险和漏洞。\n策略制定根据风险评估结果制定存储安全策略。\n部署和实施将安全策略应用于存储系统并定期更新和优化。\n\n\n\n8.3 数据灾难恢复与业务连续性\n\n定义数据灾难恢复和业务连续性是为确保在灾难发生后快速恢复数据和业务运营而采取的措施。\n主要措施\n\n备份策略定期备份重要数据确保数据在灾难发生后可以恢复。\n容灾方案建立异地灾难恢复中心确保在主数据中心发生灾难时业务可以快速切换到备用中心。\n业务连续性计划BCP制定详细的业务连续性计划包括灾难应对措施、恢复步骤和责任分工。\n\n\n实施步骤\n\n风险评估识别可能影响业务连续性的灾难和威胁。\n策略制定根据风险评估结果制定备份和容灾策略。\n演练和测试定期进行灾难恢复和业务连续性演练确保计划可行。\n\n\n\n8.4 数据防篡改技术\n\n定义数据防篡改技术是为保护数据的完整性防止未经授权的修改而采取的措施。\n主要技术\n\n数字签名利用公钥加密技术生成数据的数字签名验证数据的完整性和来源。\n哈希函数生成数据的唯一哈希值用于检测数据是否被篡改。\n区块链技术利用区块链的不可篡改性和分布式账本技术保护数据的完整性。\n\n\n应用\n\n文件完整性验证使用哈希值验证文件的完整性。\n数据审计利用数字签名和区块链技术记录和验证数据操作的合法性。\n\n\n\n8.5 安全合规性标准与法规\n\n\nGDPRGeneral Data Protection Regulation\n\n定义GDPR 是欧盟颁布的《通用数据保护条例》,旨在保护欧盟公民的个人数据隐私。\n主要要求\n\n数据收集和处理需获得用户明确同意。\n用户有权访问、修改和删除其个人数据。\n企业需采取适当措施保护用户数据并在数据泄露时及时通知用户。\n\n\n实施企业需制定隐私政策进行数据保护影响评估DPIA确保数据处理符合 GDPR 要求。\n\n\n\nHIPAAHealth Insurance Portability and Accountability Act\n\n定义HIPAA 是美国颁布的《健康保险携带和责任法案》,旨在保护患者的健康信息隐私。\n主要要求\n\n医疗机构需确保患者的健康信息机密性和安全性。\n采取技术和管理措施防止数据泄露和未经授权访问。\n提供数据访问和修改权限给患者并在数据泄露时通知患者。\n\n\n实施医疗机构需制定和实施数据保护策略进行定期安全审计和风险评估确保符合 HIPAA 要求。\n\n\n\n9. 云存储\n9.1 云存储概念与架构\n\n定义云存储是一种通过互联网提供的在线存储服务允许用户将数据存储在远程服务器上随时随地访问和管理数据。\n架构\n\n前端接口用户通过 API、控制台或客户端应用访问云存储服务。\n存储层包括分布式文件系统、对象存储和块存储负责数据的存储和管理。\n管理层提供数据管理、监控、备份和恢复等功能。\n网络层通过高速网络连接用户和存储服务器确保数据传输的稳定性和安全性。\n\n\n\n9.2 公有云、私有云与混合云存储\n\n公有云存储\n\n定义由第三方云服务提供商提供的存储服务用户通过互联网访问和管理存储资源。\n优势无需购买和维护硬件设备按需付费具备高可扩展性和灵活性。\n应用场景中小企业、初创公司、动态负载应用等。\n\n\n私有云存储\n\n定义在企业内部或由第三方托管的数据中心部署的专用存储服务企业独享存储资源。\n优势更高的安全性和控制性满足合规性要求性能可控。\n应用场景大型企业、政府机构、金融和医疗行业等。\n\n\n混合云存储\n\n定义结合公有云和私有云的存储解决方案允许数据和应用在公有云和私有云之间自由迁移和管理。\n优势兼具公有云的灵活性和私有云的安全性优化资源利用降低成本。\n应用场景需要同时满足高安全性和高灵活性需求的企业。\n\n\n\n9.3 云存储服务\n\nAWS S3Amazon Simple Storage Service\n\n特点高可用性、高持久性、可无限扩展的对象存储服务提供多种存储类型标准、智能分层、Glacier。\n功能数据加密、访问控制、版本控制、跨区域复制、事件通知等。\n应用场景数据备份和恢复、大数据分析、内容分发、应用存储等。\n\n\nAzure Blob Storage\n\n特点适用于非结构化数据存储的对象存储服务提供热存储、冷存储和存档存储三种层级。\n功能数据加密、访问控制、生命周期管理、静态网站托管等。\n应用场景备份和归档、流媒体存储、日志存储和分析、数据湖等。\n\n\nGoogle Cloud Storage\n\n特点全球统一命名空间的对象存储服务提供标准、近线、冷线和存档四种存储类型。\n功能数据加密、访问控制、版本控制、跨区域复制、对象生命周期管理等。\n应用场景数据分析、机器学习、媒体内容存储、灾难恢复等。\n\n\n\n9.4 云存储的数据迁移策略\n\n定义将数据从本地存储或其他存储平台迁移到云存储的过程和方法。\n策略\n\n离线迁移通过物理设备如硬盘将数据离线传输到云服务提供商的数据中心。\n在线迁移通过网络直接将数据传输到云存储常用工具包括 AWS Snowball、Azure Data Box、Google Transfer Appliance。\n混合迁移结合离线和在线迁移方法根据数据量和传输速度选择合适的策略。\n\n\n步骤\n\n评估和规划分析数据量、传输速度、安全性要求制定迁移计划。\n数据准备对数据进行清理、压缩和加密确保数据完整性和安全性。\n迁移执行按照计划进行数据迁移监控迁移过程处理异常情况。\n验证和优化迁移完成后验证数据完整性和可访问性进行性能优化和成本管理。\n\n\n\n9.5 云存储的成本管理与优化\n\n定义通过优化资源使用和费用支出提高云存储的成本效益。\n方法\n\n选择合适的存储类型根据数据访问频率选择合适的存储层级如热存储、冷存储、存档存储。\n生命周期管理设置数据生命周期策略自动将不常访问的数据转移到低成本存储层级。\n数据压缩和重删减少存储空间占用降低存储成本。\n监控和分析使用监控工具如 AWS Cost Explorer、Azure Cost Management实时监控存储费用分析成本构成优化资源使用。\n按需付费和预留实例结合按需付费和预留实例平衡灵活性和成本效益。\n\n\n\n9.6 混合云环境下的数据管理\n\n定义在混合云环境中对分布在公有云和私有云的数据进行统一管理和协调。\n方法\n\n统一管理平台使用混合云管理平台如 VMware Cloud Foundation、Microsoft Azure Arc实现跨云的数据管理和协调。\n数据同步和复制设置数据同步和复制策略确保公有云和私有云之间的数据一致性和高可用性。\n数据安全和合规在混合云环境中确保数据传输和存储的安全性符合相关法规和标准如 GDPR、HIPAA。\n性能优化监控和优化跨云数据传输性能减少延迟提高访问速度。\n成本管理通过统一管理和监控工具优化混合云环境中的存储成本。\n\n\n\n10. 大数据存储\n10.1 大数据存储需求与挑战\n\n数据量随着数据量的爆炸式增长传统存储系统难以应对海量数据的存储需求。\n数据类型大数据不仅包括结构化数据还包括半结构化和非结构化数据如文本、图像、视频等。\n数据访问需要高效的数据读取和写入性能以支持大数据分析和实时处理。\n成本控制在满足性能需求的同时控制存储系统的成本是一个重要挑战。\n数据安全与隐私在存储和传输过程中确保数据的安全性和隐私保护。\n数据管理有效地管理和维护大量的数据包括数据备份、恢复和生命周期管理。\n\n10.2 分布式文件系统\n\n\nHDFSHadoop Distributed File System\n\n架构NameNode 和 DataNode 的角色分工,主从架构。\n数据存储数据分块存储和副本机制提高数据的可靠性和可用性。\n优缺点高容错性和可扩展性但对小文件支持不佳。\n\n\n\n其他分布式文件系统\n\nCeph一种统一的分布式存储系统支持对象、块和文件存储。\nGlusterFS开源的分布式文件系统具备高可用性和高扩展性。\n\n\n\n10.3 对象存储系统\n\n概念对象存储将数据作为对象进行管理每个对象包含数据、元数据和唯一标识符。\n优势高扩展性、支持海量数据存储、灵活的数据管理和检索方式。\n常见对象存储系统\n\nAmazon S3AWS 提供的对象存储服务,具有高可用性和高耐久性。\nOpenStack Swift开源的对象存储系统支持大规模集群部署。\nMinIO高性能的对象存储系统兼容 Amazon S3 API。\n\n\n\n10.4 大数据存储的典型案例\n\n\nHadoop\n\n架构基于 HDFS 进行数据存储,利用 MapReduce 进行数据处理。\n应用场景适用于批量数据处理、大规模数据分析。\n优缺点强大的数据处理能力但实时性较差。\n\n\n\nCassandra\n\n架构去中心化、无主节点的分布式数据库支持多数据中心的高可用性。\n数据模型基于列族存储适合处理高吞吐量的写操作。\n应用场景实时数据分析、事务处理、日志记录。\n优缺点高扩展性和可用性但查询复杂性较高。\n\n\n\n10.5 大数据存储的性能优化\n\n数据分区通过数据分区提高数据访问的并行度。\n缓存机制利用缓存机制减少磁盘 I/O提高访问速度。\n压缩技术通过数据压缩减少存储空间占用和数据传输时间。\n硬件优化使用高速硬盘如 SSD和高带宽网络设备提升整体性能。\n数据预处理在数据写入前进行预处理减少后续的处理负担。\n\n10.6 大数据存储的扩展性设计\n\n水平扩展增加节点来扩展存储容量和计算能力确保系统能处理越来越多的数据。\n负载均衡通过负载均衡机制均匀分配数据和请求避免单点瓶颈。\n自动化运维利用自动化工具进行运维管理确保系统在扩展过程中的稳定性和可靠性。\n容错机制设计健壮的容错机制确保在硬件故障或网络中断时数据不丢失且系统能快速恢复。\n弹性计算结合云计算资源实现按需扩展满足动态变化的业务需求。\n\n第四部分现代化与分布式存储\n11. 自建分布式存储系统\n11.1 分布式存储概念与优势\n\n分布式存储的定义介绍分布式存储系统的基本概念数据分布在多个节点上通过网络进行访问和管理。\n优势\n\n扩展性能够根据需要增加存储节点实现存储容量的线性扩展。\n高可用性通过数据冗余和多副本机制确保系统在部分节点故障时仍能正常工作。\n高性能分布式存储能够利用多节点并行处理提升数据读写速度。\n成本效益利用普通硬件构建高性能存储系统降低成本。\n\n\n\n11.2 MinIO 安装与配置\n\nMinIO 简介:介绍 MinIO 的特点和应用场景。\n安装步骤\n\n环境准备系统要求和依赖安装。\n下载和安装从官网下载 MinIO 并进行安装。\n配置配置 MinIO 的存储路径、访问密钥等。\n\n\n启动和访问\n\n启动 MinIO 服务。\n通过 Web 界面或命令行工具访问 MinIO。\n\n\n\n11.3 Ceph 存储集群部署\n\nCeph 简介Ceph 的架构和核心组件(如 OSD、Monitor、MDS 等)。\n部署步骤\n\n环境准备系统要求、网络配置和依赖安装。\n集群初始化安装 Ceph 部署工具(如 ceph-deploy初始化集群。\n节点部署添加 OSD 节点、Monitor 节点等。\n配置和调优配置 Ceph 的存储池、CRUSH map 等。\n\n\n使用和管理\n\n数据存储和访问通过 RADOS、CephFS、RBD 等方式访问存储数据。\n集群管理常用管理命令和操作如监控、扩展、维护。\n\n\n\n11.4 GlusterFS 架构与使用\n\nGlusterFS 简介:介绍 GlusterFS 的架构、特点和应用场景。\n安装与配置\n\n环境准备系统要求和依赖安装。\n安装 GlusterFS在各节点上安装 GlusterFS 软件包。\n配置卷创建和配置分布式卷、复制卷等。\n\n\n使用与管理\n\n挂载和访问客户端挂载 GlusterFS 卷,读写数据。\n管理操作卷扩展、缩减、迁移等操作。\n\n\n\n11.5 分布式存储系统的负载均衡\n\n负载均衡的概念介绍负载均衡在分布式存储系统中的作用。\n实现策略\n\n数据分片将数据分散存储在不同节点上实现负载均衡。\n读写分离将读写操作分离分别处理减少单节点负担。\n动态调整根据节点负载情况动态调整数据分布和请求路由。\n\n\n工具与实践\n\n常用负载均衡工具如 HAProxy、LVS 等。\n实际案例分析分析具体分布式存储系统中的负载均衡实现。\n\n\n\n11.6 数据复制与同步策略\n\n数据复制的必要性确保数据的高可用性和可靠性。\n复制策略\n\n同步复制实时同步数据保证数据一致性。\n异步复制延迟同步减少实时同步带来的性能开销。\n多副本机制设置多个数据副本提高数据冗余度。\n\n\n同步工具与技术\n\n常用同步工具如 rsync、DRBD 等。\n实际应用在具体分布式存储系统中的数据同步实现。\n\n\n\n11.7 分布式存储系统的监控与维护\n\n监控的必要性实时了解系统运行状态预防和快速响应故障。\n监控工具\n\n常用监控工具如 Prometheus、Grafana、Zabbix 等。\n日志管理工具如 ELKElasticsearch、Logstash、Kibana栈。\n\n\n维护实践\n\n常见问题排查识别和解决存储系统中的常见问题。\n系统升级和扩展无缝升级系统和增加存储节点。\n备份与恢复定期进行数据备份制定灾难恢复计划。\n\n\n\n12. 分布式文件系统与对象存储\n12.1 分布式文件系统原理与实现\n\n基本概念\n\n分布式文件系统的定义和作用。\n常见的分布式文件系统如 HDFS、Ceph、GlusterFS 等)。\n\n\n体系结构\n\n分布式文件系统的整体架构和组成部分如客户端、元数据服务器、数据节点。\n数据存储和访问机制。\n\n\n实现原理\n\n文件切分和分块存储。\n数据冗余和副本机制。\n负载均衡和数据分布策略。\n\n\n关键技术\n\n数据分片和分布算法。\n元数据管理和一致性模型。\n容错和恢复机制。\n\n\n\n12.2 对象存储与块存储的区别与应用场景\n\n基本概念\n\n对象存储、块存储和文件存储的定义。\n三者的主要区别和各自的优缺点。\n\n\n对象存储\n\n对象存储的架构和实现方式。\n对象存储的特点如可扩展性、元数据自描述、扁平化存储结构。\n常见的对象存储系统如 Amazon S3、OpenStack Swift、MinIO 等)。\n典型应用场景如大数据分析、备份和归档、内容分发网络。\n\n\n块存储\n\n块存储的架构和实现方式。\n块存储的特点如高性能、低延迟、适合结构化数据存储。\n常见的块存储系统如 iSCSI、Fibre Channel、NVMe-oF。\n典型应用场景如数据库、虚拟机存储、事务处理。\n\n\n\n12.3 高可用与数据一致性策略\n\n高可用性\n\n高可用性的定义和重要性。\n实现高可用的技术如副本机制、自动故障转移、负载均衡。\n分布式文件系统和对象存储的高可用设计。\n\n\n数据一致性\n\n数据一致性的基本概念和类型如强一致性、最终一致性、因果一致性。\n一致性协议和算法如 Paxos、Raft。\nCAP 定理及其影响。\n数据一致性在分布式文件系统和对象存储中的实现策略。\n\n\n\n12.4 分布式文件系统的元数据管理\n\n元数据管理的作用\n\n元数据的定义和重要性。\n元数据在分布式文件系统中的角色。\n\n\n元数据架构\n\n集中式元数据管理和分布式元数据管理的对比。\n常见的元数据管理方式如主从复制、一致性哈希。\n\n\n元数据操作\n\n元数据创建、更新和删除的操作流程。\n元数据的高效查询和检索机制。\n\n\n元数据一致性\n\n元数据一致性的挑战和解决方案。\n元数据的一致性模型和实现策略。\n\n\n\n12.5 对象存储的生命周期管理\n\n生命周期管理的概念\n\n对象存储生命周期的定义和重要性。\n生命周期管理的基本操作如创建、修改、归档、删除。\n\n\n生命周期策略\n\n自动化生命周期管理策略的制定和应用。\n生命周期管理规则的配置和优化。\n\n\n版本控制\n\n对象存储的版本控制机制。\n版本管理和恢复操作。\n\n\n数据迁移和归档\n\n数据迁移策略和工具。\n数据归档和删除策略。\n数据治理和合规性管理。\n\n\n\n12.6 分布式文件系统和对象存储的实际应用案例分析\n\n案例选择\n\n选择具有代表性的分布式文件系统和对象存储案例。\n分析案例的背景和需求。\n\n\n系统架构\n\n详细描述系统的架构设计。\n分析系统的组件和功能模块。\n\n\n实现过程\n\n描述系统的实现过程和技术选型。\n分析系统在实施过程中遇到的问题和解决方案。\n\n\n性能和优化\n\n系统的性能评估和优化策略。\n系统的可扩展性和维护性分析。\n\n\n总结和反思\n\n总结案例的成功经验和不足之处。\n提出改进建议和未来发展方向。\n\n\n"},"Technology/ComputerStorage/1.-存储基础":{"title":"1. 存储基础","links":[],"tags":["技术/计算机存储","计算机存储/基础"],"content":"存储概念\n存储指的是保存和检索数据的过程和技术。计算机存储包括各种介质和技术用于保存数据和程序以便在需要时快速访问。\n常见的存储术语有\n\n存储设备用于保存数据的硬件如硬盘、SSD 等。\n存储介质存储数据的物理材料如磁盘、光盘等。\n存储单元存储数据的最小单位如比特和字节。\n文件系统管理和组织数据存储的系统如 NTFS、EXT4 等。\n\n存储介质类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n存储介质特点优点缺点应用磁带传统的存储介质使用磁带保存数据存储容量大、成本低、适合长期保存读写速度慢、随机访问困难大规模数据备份、归档、灾难恢复光盘通过激光在光敏材料上读取和写入数据保存寿命长、便于多媒体数据分发读写速度慢、容量有限备份、多媒体数据分发、软件和游戏分发磁盘通过磁性材料保存数据硬盘驱动器HDD是最常见的磁盘存储设备容量大、价格低廉机械结构导致读写速度较慢易损坏桌面和笔记本电脑、服务器、大容量数据存储SSD使用闪存芯片存储数据没有机械部件速度快、高 IOPS、耐用性好价格较高、容量较小需要快速数据访问的应用、操作系统驱动器、数据库\n存储单元与数据表示\n存储单元是计算机存储系统的基本组成部分用于表示和存储数据。常见的存储单元和数据表示方法包括\n基本存储单元\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n存储单元定义描述比特Bit最小的数据存储单位表示二进制的 0 或 1字节Byte由 8 个比特组成通常用于表示一个字符,如字母或数字\n数据存储的更大单位\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n存储单元大小关系描述千字节KB1 KB = 1024 字节通常用于表示较小的文件大小兆字节MB1 MB = 1024 KB常用于表示文档、图片文件大小千兆字节GB1 GB = 1024 MB常用于表示视频文件或硬盘容量太字节TB1 TB = 1024 GB用于表示大容量硬盘或存储设备拍字节PB1 PB = 1024 TB用于大型数据中心存储艾字节EB1 EB = 1024 PB用于极大型数据中心或云存储\n数据表示\n字符编码用于将字符转换为计算机可以处理的二进制形式。常见的字符编码方式包括 ASCII、Unicode、UTF-8 等。\n文件系统\n文件系统是用于管理和组织存储设备上数据和文件的方法。文件系统负责文件的存储、命名、访问和保护。不同的文件系统在性能、可靠性、安全性和兼容性方面有所不同常见的文件系统包括\n\nFAT32File Allocation Table 32一种较老的文件系统广泛用于 USB 闪存驱动器和小型存储设备,最大文件大小为 4 GB分区最大为 8 TB。\nNTFSNew Technology File System微软 Windows 操作系统的默认文件系统,支持大文件和大容量分区,具有文件和目录的权限管理、安全性高、支持加密和压缩等特点。\next4Fourth Extended File SystemLinux 操作系统常用的文件系统,支持大文件和大容量分区,具有高效的磁盘空间管理和良好的性能。\nAPFSApple File System苹果公司用于 macOS 和 iOS 的文件系统,支持快照、克隆、加密、空间共享和崩溃保护等特性。\n\n存储性能指标\n存储性能指标是衡量存储设备效率和能力的关键参数。了解这些指标有助于评估存储系统的性能并根据具体需求进行优化配置。以下是一些常见且重要的存储性能指标。\nIOPS\n**IOPSInput/Output Operations Per Second表示存储设备每秒能够处理的输入输出操作次数。**它是衡量存储设备处理小型随机读写操作能力的重要指标。IOPS 越高,存储设备在高负载下处理请求的能力越强。\n主要影响因素\n\n存储介质类型SSD 的 IOPS 通常远高于 HDD。\n工作负载小块随机读写操作对 IOPS 要求较高,而顺序读写操作对 IOPS 要求较低。\n队列深度较高的队列深度可以提高 IOPS因为存储设备可以同时处理多个请求。\n\n实际应用\n\n数据库系统需要高 IOPS 以快速处理大量小型事务。\n虚拟化环境多个虚拟机共享存储资源高 IOPS 有助于提高整体性能。\n\n带宽\n**带宽表示单位时间内可以传输的数据量通常以兆字节每秒MB/s或千兆比特每秒Gbps为单位。**带宽是衡量存储设备顺序读写能力的重要指标。\n主要影响因素\n\n存储介质类型SSD 的带宽通常比 HDD 高,因为 SSD 没有机械部件限制。\n接口类型不同接口如 SATA、SAS、NVMe支持的最大带宽不同NVMe 接口通常提供最高带宽。\n数据块大小顺序读写大数据块时带宽利用率更高。\n\n实际应用\n\n视频编辑需要高带宽以快速读取和写入大文件。\n大数据分析需要高带宽以处理大规模数据集的连续读写操作。\n\n延迟\n**延迟是指从发出数据请求到开始接收到数据的时间通常以毫秒ms为单位。**延迟是衡量存储设备响应速度的重要指标。\n主要影响因素\n\n存储介质类型SSD 的延迟远低于 HDD因为 SSD 没有寻道和旋转延迟。\n网络延迟在网络存储如 SAN、NAS网络传输时间也会影响整体延迟。\n队列深度较高的队列深度可能会增加延迟因为需要等待的请求更多。\n\n实际应用\n\n实时交易系统需要低延迟以确保快速响应用户请求。\n在线游戏低延迟可以提供更流畅的用户体验。\n\n吞吐量\n**吞吐量是指单位时间内成功传输的数据量通常以每秒兆字节MB/s或千兆字节GB/s为单位。**吞吐量反映了系统在高负载下的处理能力。\n主要影响因素\n\n数据块大小大数据块传输时吞吐量更高。\n并发用户数量更多用户同时访问会影响吞吐量。\n网络带宽网络条件影响整体吞吐量。\n\n实际应用\n\n数据备份和恢复需要高吞吐量以缩短备份和恢复时间。\n大规模数据传输如数据中心之间的同步。\n\n数据完整性\n**数据完整性确保存储系统在读写数据时不会发生错误。**对于金融、医疗等对数据准确性要求高的行业,数据完整性至关重要。\n主要影响因素\n\n纠错码ECC用于检测和纠正数据错误。\n校验和用于验证数据的完整性。\n数据冗余通过冗余存储提高数据可靠性。\n\n实际应用\n\n数据库系统需要高数据完整性以确保事务的准确性。\n企业数据存储保障关键业务数据的可靠性。\n\n可扩展性\n**可扩展性是指存储系统能够轻松扩展以应对不断增长的数据需求。**高可扩展性使得存储系统能够适应业务的增长和变化。\n主要影响因素\n\n存储架构模块化设计更易于扩展。\n扩展接口如支持更多存储设备的接口。\n软件支持如分布式文件系统的扩展能力。\n\n实际应用\n\n云存储需要高可扩展性以支持动态扩展。\n大型企业存储系统随业务增长灵活扩展存储容量。\n\n可靠性\n**可靠性表示存储系统在各种条件下持续正常工作的能力。**高可靠性的存储系统可以减少数据丢失和系统停机时间。\n主要影响因素\n\n冗余设计如 RAID 技术,通过数据冗余提高可靠性。\n容错机制如热备份和容错设计。\n备份方案定期备份数据以防止数据丢失。\n\n实际应用\n\n关键业务应用如金融交易系统需要高可靠性以确保业务连续性。\n灾难恢复系统通过可靠的存储系统实现快速恢复。\n\n能效比\n能效比是指存储系统在提供性能的同时消耗的能量。 高能效比意味着在提供相同性能的情况下,系统消耗的能量更少,有助于降低运营成本和环保。\n主要影响因素\n\n硬件设计高效的硬件设计可以减少能耗。\n冷却系统高效冷却系统可以降低整体能耗。\n功耗管理智能功耗管理可以在不影响性能的情况下降低能耗。\n\n实际应用\n\n数据中心需要高能效比以降低运营成本。\n绿色 IT 解决方案:通过高效能的存储系统实现环保目标。\n\n存储寿命和耐久性\n存储寿命指存储介质在正常使用条件下能够保持数据完整性的时间。不同的存储介质具有不同的寿命\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n存储介质一般寿命耐久性主要影响因素HDD3-5 年机械部件易磨损抗震能力差机械磨损、环境因素如温度、湿度SSD5-10 年无机械部件抗震能力强写入次数TBW、环境因素光盘10-20 年光敏材料稳定耐久性较好存储环境如温度、湿度、光照磁带30 年以上磁性材料稳定,适合长期存储存储环境(如温度、湿度)、磁带质量\n耐久性是指存储介质在使用过程中的可靠性和抗损坏能力。SSD 由于没有机械部件,耐久性优于 HDD。\n存储介质寿命的延长方法\n\n优化存储环境保持适宜的温度和湿度避免极端环境对存储介质的损害。\n定期维护和检查对于 HDD定期进行健康检查和碎片整理对于 SSD避免不必要的写入操作。\n合理使用和管理根据数据的重要性和访问频率选择合适的存储介质避免过度使用导致寿命缩短。\n\n存储访问模式\n\n存储访问模式是指数据在存储设备上的读写方式。不同的访问模式适用于不同的应用场景影响系统的性能和效率。\n顺序访问\n**顺序访问是指数据按顺序依次读写的过程。**这种模式下,数据按固定顺序存储和访问,常用于磁带存储和部分光盘存储。顺序访问的优点是读写速度较快,适用于大文件的连续读写操作,但不适合频繁的小数据块读写。\n随机访问\n**随机访问是指数据可以在存储设备上的任意位置读写,而不必按顺序进行。**这种模式下,存储设备可以快速访问任意数据块,适用于 SSD 和 HDD。随机访问的优点是灵活性高适合需要频繁读写小数据块的应用如数据库和操作系统文件的访问。\n结论\n计算机存储是计算机系统的核心组成部分涵盖了从基础概念到具体技术的方方面面。了解存储介质的类型、存储单元与数据表示、存储性能指标、存储寿命和耐久性以及存储访问模式能够帮助我们更好地选择和使用存储设备以满足不同应用场景的需求。无论是传统的磁盘和磁带还是现代的 SSD 和光盘,每种存储介质都有其独特的优缺点和适用场景,在实际应用中需要根据具体需求进行合理的选择和配置。"},"Technology/ComputerStorage/2.-存储硬件":{"title":"2. 存储硬件","links":[],"tags":["技术/计算机存储","计算机存储/基础"],"content":"磁带Tape\n\n\n来源录音磁带图片_百度百科仅学术引用著作权归作者所有。\n\n磁带存储是一种利用磁性材料存储数据的存储技术具有可靠性高、容量大、成本低的特点被广泛应用于数据备份、存档、长期存储等领域。\n磁带存储的历史可以追溯到上世纪 50 年代,当时的磁带存储容量较小,读写速度较慢,主要用于存储机器指令和数据备份等应用。随着磁头技术、磁性材料技术的不断发展,磁带存储的容量和速度得到了大幅提升,使得其在数据备份、存档等领域得到了广泛应用。\n\n\n来源计算机组成原理\n\n磁带存储的实现是通过将数据记录在磁带表面的磁性颗粒上通过磁头读取磁带表面的磁性信号实现数据的读写。磁带存储一般采用串行读写的方式因此其读写速度相对较慢但磁带存储的容量较大可以达到数百 TB 的级别,且数据可靠性较高,可以长期保存数据。\n**磁带存储的主要应用场景是数据备份、存档和长期存储等领域。**在数据备份领域,磁带存储被广泛应用于数据中心、云服务提供商等场景,用于备份大量的数据和应用程序。在存档和长期存储领域,磁带存储可以用于保存重要的历史文档、音乐和影像等资料,具有容量大、可靠性高、成本低等优点。\n在一些应用场景中磁带存储的性能和特性比硬盘和固态硬盘更加适合例如需要长期存储大量数据的场景或者是需要备份和归档大量数据的场景。另外在一些监管和合规性要求比较高的行业如金融、医疗等领域磁带存储也被广泛应用因为磁带存储具有防篡改、数据安全等特点。\n总的来说磁带存储虽然在读写速度和可靠性等方面不如硬盘和固态硬盘但是由于其容量大、成本低和长期可靠性等特点使得其在某些特定的场景下仍然具有很大的应用前景。\n光盘Optical Disc\n如 CD、DVD 和 Blu-ray通过激光在光盘上刻录和读取数据适合长期存储和数据备份但读写速度较慢容量有限。\n\n\n来源File:Melody 90min PLATiNUM CD disc.jpg - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n光盘存储是一种基于激光技术的数字存储介质主要由光盘、CD-ROM、DVD 和 Blu-ray 等几种类型组成。它是一种非易失性存储介质,可以长期保存数据。\n光盘存储的历史可以追溯到 20 世纪 80 年代初期当时的光盘主要是音频光盘主要用于存储音乐。随着激光技术的发展和数字化技术的普及光盘存储也逐渐应用于数字存储领域。1985 年Philips 和 Sony 公司共同推出了第一种数字光盘标准 CDCompact Disc从此光盘存储开始进入数字时代。之后随着技术的不断发展CD-ROM、DVD 和 Blu-ray 等新一代光盘存储技术相继问世,容量和读取速度也得到了显著提升。\n\n\n来源一文读懂光储存技术及原理-面包板社区;仅学术引用,著作权归作者所有。\n\n光盘存储的实现主要基于激光技术。在光盘上刻有一系列螺旋状的凹槽凹槽的长度和深度对应着数据的 1 和 0。当激光照射到光盘表面时通过检测反射光的强弱和光波的相位变化就可以判断凹槽的长度和深度从而读取数据。不同类型的光盘其光盘结构和读取方式也不同。\n**光盘存储适用于长期存储重要数据、分发软件、电影、音乐等媒体内容、随身携带备份个人数据或保存重要文档、兼容性广的数据存储需求。**虽然已经被硬盘和固态硬盘所取代,但在某些场合下仍然有其独特的应用优势。\n磁盘Disk\n传统的硬盘驱动器HDD使用旋转的磁性盘片来存储数据。优点是容量大成本低缺点是速度相对较慢。\n\n\n来源File:Laptop-hard-drive-exposed.jpg - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n机械硬盘Hard Disk DriveHDD是一种数据存储设备是计算机系统中最常用的存储媒介之一。它是一种使用磁盘片来存储数据的设备通过机械臂上的读写头在盘片上读写数据。\n发展历史\n机械硬盘存储的历史可以追溯到 20 世纪 50 年代,当时 IBM 公司研制出了第一个硬盘,容量为 5MB。随着计算机技术的不断进步机械硬盘存储的容量、速度、可靠性等方面都得到了不断提升和改善成为了计算机存储系统中不可或缺的一部分。\n\n\n1956 年IBM 305 RAMAC 是现代硬盘的雏形,容量仅为 5MB。\n\n\n1973 年IBM 3340 推出,拥有“温彻斯特”绰号,其存储单元恰好是当时“温彻斯特来福枪”的口径和填弹量。\n\n\n1980 年,希捷科技公司开发出 5.25 英寸的 5MB 硬盘 ST506这是面向台式机的首款硬盘产品。\n\n\n1991 年IBM 推出首款 3.5 英寸的 1GB 硬盘,应用了 MRMagneto Resistive 磁阻)技术,为硬盘容量的巨大提升奠定基础。\n\n\n1997 年IBM 应用 GMRGiant Magneto Resistive巨磁阻技术使磁头灵敏度进一步提升进而提高存储密度。\n\n\n2005 年日立环储和希捷都宣布将开始大量采用磁盘垂直写入技术perpendicular recording。\n\n\n2011 年,机械硬盘逐渐被固态硬盘所取代,希捷宣布收购三星旗下的硬盘业务。\n\n\n2020 年截至现存主要硬盘制造商包括西部数据、希捷、东芝、日立等。\n数据接口\n机械硬盘的接口是指将硬盘与计算机主板或控制卡连接的接口。早期的机械硬盘接口主要有 IDE (Integrated Drive Electronics) 和 SCSISmall Computer System Interface两种。目前常见的机械硬盘接口主要包括 SATASerial ATA和 SASSerial Attached SCSI两种。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n接口传输速率优点缺点适用场景IDEIntegrated Drive Electronics最高 133MB/s支持 PATA 和 SATA 接口兼容性好传输速率较慢线缆长度受限早期的个人电脑、低端工作站等SCSISmall Computer System Interface最高 640MB/s高速传输支持多设备连接可扩展性强价格较高设置和维护较为复杂高端服务器、存储阵列等SATASerial ATA最高 6Gbps价格低廉易于使用和安装传输速率较慢线缆长度受限个人电脑、工作站、NAS 等SASSerial Attached SCSI最高 12Gbps高速传输支持多设备连接价格较高服务器、存储阵列等高端应用FCFibre Channel最高 32Gbps高速传输支持多设备连接可扩展性强价格较高设置和维护较为复杂高端存储阵列、数据中心等\n硬盘尺寸\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n尺寸容量转速缓存平均寻道时间内部传输速度适用场景3.5 英寸机械硬盘160GB-16TB5400-15000 转/分8MB-256MB4-15ms最高 300MB/s台式电脑NAS服务器工作站等大型设备2.5 英寸机械硬盘40GB-5TB4200-15000 转/分8MB-128MB10-15ms最高 200MB/s笔记本电脑便携式硬盘智能电视游戏机等1.8 英寸机械硬盘30GB-320GB4200-5400 转/分2MB-16MB15-20ms最高 100MB/s平板电脑超极本便携式媒体播放器等\n实现原理\n机械硬盘存储的实现原理是基于磁性材料在磁场作用下的磁化性质。机械硬盘的磁性材料被划分为许多同心圆形的磁道每个磁道又被划分为多个扇区每个扇区存储着一定数量的数据。当计算机需要读取或写入数据时机械硬盘的读写头会在磁盘上移动将数据从磁盘读取或写入到存储器中。\n机械硬盘的物理结构包括盘片、读写头、马达、控制器等组件。盘片是机械硬盘最重要的组件之一用于存储数据。读写头则是机械硬盘的另一个重要组件用于读取和写入数据。马达则用于旋转盘片使得读写头能够顺利读取和写入数据。控制器则用于控制硬盘的读写和数据传输过程。\n设计结构\n\n来源File:Disk-structure2.svg - 维基百科,自由的百科全书;仅学术引用,著作权归作者所有。\n\n机械硬盘是一种基于磁记录技术的数据存储设备其物理结构主要包括磁头、盘片、马达、主轴、磁道、扇区、簇、块和分区表等部分。\n\n\n磁头机械硬盘中最为关键的部分之一其作用是读写盘片上的数据。通常情况下一块硬盘上会有多个磁头每个磁头分别负责读写一侧或多侧盘片上的数据。\n\n\n盘片机械硬盘中存储数据的主要介质它由铝合金或玻璃材料制成表面上涂覆有磁性材料用于记录数据。一块硬盘通常包含多个盘片每个盘片分别分成若干个磁道和扇区存储数据。\n\n\n马达和主轴是机械硬盘中的另外两个核心部件。马达用于带动盘片旋转主轴则承载盘片和保持其旋转稳定。马达和主轴的性能直接影响到机械硬盘的读写速度和稳定性。\n\n\n磁道盘片表面的一个环形区域类似于一条有向的螺旋线。每个磁道又被划分为多个扇区用于存储数据。随着硬盘存储密度的提高磁道数量也在不断增加。\n\n\n簇机械硬盘中的一个逻辑概念它是由多个扇区组成的一个数据单元。簇的大小通常为几个扇区取决于硬盘的格式化方式和操作系统的文件系统。\n\n\n块操作系统中对数据进行管理的最小单元每个块通常有固定的大小用于存储文件或其他数据。\n\n\n分区表硬盘中用于记录分区信息的一个特殊区域它记录了硬盘分区的数量、大小和位置等信息。操作系统需要依据分区表来读取和写入硬盘上的数据。\n\n\nMBR 和 GPT\n机械硬盘的逻辑结构主要包括两种格式MBRMaster Boot Record主引导记录和 GPTGUID Partition Table全局唯一标识分区表。\nMBR 是早期 PC 硬盘的标准分区方案,它将硬盘的分区信息保存在硬盘的第一个扇区中(即 0 号扇区),这个扇区的大小为 512 字节。MBR 可以分为两个部分:引导程序区和分区表。引导程序区存储了启动时需要加载的程序,分区表则记录了硬盘分区的信息,每个分区表项占用 16 字节其中包括分区类型、起始扇区和分区大小等信息。MBR 最多支持 4 个主分区或 3 个主分区和 1 个扩展分区。\nGPT 是新一代硬盘分区标准,它将硬盘的分区信息保存在硬盘的第一个和第二个 LBALogical Block Addressing逻辑块寻址扇区中每个 LBA 扇区的大小为 512 字节。GPT 采用了一个 128 位的唯一标识符GUID来标识分区表因此支持更多的分区。每个 GPT 分区表项占用 128 字节其中包括分区类型、GUID、起始扇区和分区大小等信息。GPT 最多支持 128 个分区。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性MBRGPT最大容量2 TB9.4 ZB分区数最多 4 个最多 128 个兼容性较好,可用于 BIOS 和 UEFI 系统较好,主要用于 UEFI 系统系统要求任何操作系统都支持Windows xp 64 位 +、Mac OS X 10.6.5 及更高版本、Linux 和 UNIX安全性差支持在分区表中存储磁盘分区信息的完整性校验和可检测分区表是否被修改\n固态驱动器SSD\n\n固态硬盘Solid State DriveSSD是一种非易失性的存储设备主要用于存储数据。与传统的机械硬盘Hard Disk DriveHDD相比它没有任何移动部件因此在速度、耐用性和能源消耗方面具有明显优势。\n发展历史\n固态硬盘的发展始于上世纪 50 年代那时候的存储设备主要基于半导体技术。随着半导体技术的发展SSD 逐渐成为计算机领域的一种主流存储设备。早期的 SSD 主要用于军事和航空领域因为它们对性能和稳定性有很高的要求。随着技术的进步和成本的降低SSD 已经成为消费者市场上的常见产品。\n\n\n1978 年Toshiba 的工程师 Fujio Masuoka 发明了闪存技术,这是固态硬盘的基础技术。\n\n\n1991 年SanDisk 推出首款基于 NAND 闪存的固态硬盘,容量为 20MB主要应用于工业和军事领域。\n\n\n1995 年IBM 发布了第一款 PCI 接口的固态硬盘,提高了数据传输速度。\n\n\n2007 年Intel 推出了其首款主流固态硬盘——Intel X25-M使用了 MLCMulti-Level CellNAND 闪存技术,容量为 80GB标志着固态硬盘开始进入消费者市场。\n\n\n2008 年OCZ 推出了第一款支持 SATA 接口的固态硬盘,使得 SSD 更容易与现有计算机系统兼容。\n\n\n2011 年,高通和三星等公司联合制定了 UFSUniversal Flash Storage标准为移动设备提供了更高速度的存储解决方案。\n\n\n2013 年NVMe 1.0 规范正式发布,为固态硬盘提供了更高性能的数据传输接口。\n\n\n2015 年,三星发布了其首款 NVMe 固态硬盘——Samsung 950 Pro采用 M.2 接口和 V-NAND 技术,具有更高的读写速度和更小的尺寸。\n\n\n2020 年主流的 SSD 厂商包括三星、英特尔、西部数据、东芝、海力士和金士顿等。\n数据接口\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n接口传输速度优点缺点适用场景PATAParallel ATA最高 133MB/s成本较低向后兼容性好速度较慢数据线较粗占用空间大早期台式机和笔记本电脑SATASerial ATA最高 6Gbps速度较快数据线较细易安装兼容性好速度相对于 NVMe 仍较慢台式机和笔记本电脑NVMeNon-Volatile Memory ExpressPCIe 3.0 x432 Gbit/s更高的传输速度低延迟可扩展性好成本较高需要主板支持高性能台式机、笔记本、服务器等PCIe 4.0 x464 Gbit/s\n硬盘尺寸\n固态硬盘有多种尺寸如 2.5 英寸、1.8 英寸和 mSATA。2.5 英寸是最常见的尺寸适用于笔记本电脑和台式机。1.8 英寸和 mSATA 主要用于超薄笔记本和移动设备。近年来M.22230、2242、2260、2280接口的 SSD 也越来越受欢迎,因为它们具有更小的尺寸和更高的性能。\n**M.2 尺寸中的四位数字表示长度和宽度。**例如M.2 2280 表示宽度为 22mm长度为 80mm。此外M.2 SSD 可能采用 SATA 或 NVMe 接口,需要根据设备的接口要求进行选择。\n实现原理\n固态硬盘SSD是一种非易失性的数据存储设备它使用闪存Flash Memory作为存储介质。闪存具有较高的存储密度、较快的读取速度和较低的功耗因此非常适合用于固态硬盘。与传统的机械硬盘HDD相比固态硬盘没有机械运动部件因此具有更高的读写速度、更低的延迟和更高的可靠性。\n固态硬盘的核心组件包括控制器和闪存。控制器负责管理数据的读写操作、通信接口如 SATA 或 NVMe、错误检测和校正ECC以及其他高级功能如垃圾回收和可穿戴平衡。闪存中的数据存储在称为存储单元的微小晶体管中数据通过改变存储单元的电子电压来表示不同的状态。\n为了提高写入性能和延长硬盘寿命固态硬盘采用了可穿戴平衡策略并通过映射表将操作系统看到的逻辑地址映射到闪存中的物理地址。此外固态硬盘还使用垃圾回收算法优化存储空间使用以及接收操作系统的 TRIM 命令来提高写入性能。\n设计结构\n\n\n来源深入浅出SSD - 注册以后还能改吧 - 博客园;仅学术引用,著作权归作者所有。\n\n\n闪存芯片Flash Memory Chips闪存是固态硬盘的核心存储介质通常采用 NAND 型闪存。闪存具有较高的存储密度、较快的读取速度和较低的功耗。根据存储单元所存储的比特数,闪存可以分为 SLC单级单元、MLC多级单元、TLC三级单元和 QLC四级单元等类型。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型存储比特数写入速度寿命容量密度成本适用场景SLC1 比特/单元最快最高(约 10 万次低高企业级存储、高性能应用、工业级存储等要求高可靠性和耐用性的场景MLC2 比特/单元中等高(约 3 万次中中等主流消费级和企业级应用平衡了性能、耐用性和成本TLC3 比特/单元较慢中等(约 1 万次高较低主流消费级存储适用于大容量、低成本的应用场景QLC4 比特/单元最慢最低(约 1 千次)最高最低面向大容量存储需求,以成本为主要考虑因素的应用场景\n\n\n控制器Controller控制器是固态硬盘的大脑负责管理数据的读写操作、通信接口如 SATA 或 NVMe、错误检测和校正ECC以及其他高级功能如垃圾回收、可穿戴平衡和 AES 加密。控制器的性能对固态硬盘的整体性能有很大影响。\n\n\n缓存Cache部分固态硬盘配置有 DRAM 或 SRAM 作为缓存用于临时存储数据以提高数据传输速度。缓存还可以用于存储映射表Mapping Table用于记录逻辑地址和物理地址之间的映射关系。\n\n\n电源电路Power Circuitry固态硬盘的电源电路负责将来自主板的电源转换为适用于控制器和闪存芯片的电压。\n\n\n接口Interface固态硬盘需要一个接口与主板相连以便于数据传输和电源供应。常见的接口类型包括 SATA、mSATA、M.2(支持 SATA 和 NVMe 协议)以及 U.2 等。\n\n\n固件Firmware固态硬盘的固件包含一组存储在控制器上的指令用于控制和管理硬盘的各种功能。固件可以通过制造商发布的更新来优化性能和修复已知问题。\n\n\n散热Thermal Management高性能的固态硬盘在运行过程中可能会产生较高的热量因此需要采取一定的散热措施。散热解决方案包括散热片、热导管以及与主板的热接触等。\n\n\n总之固态硬盘的设计结构由闪存芯片、控制器、缓存、电源电路、接口、固件以及散热系统等组件组成。这些组件共同协作实现了高速、低功耗、高可靠性和抗震性等优点。相较于传统的机械硬盘固态硬盘在许多应用场景中具有明显优势特别是在高性能需求、移动设备和企业级应用等方面。随着闪存技术的不断发展固态硬盘的容量和性价比也在逐渐提高使得固态硬盘成为越来越多用户的首选存储设备。\nRAID独立磁盘冗余阵列技术\nRAID 0条带化\n\nRAID 0条带化是一种数据分发方式数据被分成大小相等的块并分别存储在多个硬盘上以提高读写性能。它没有冗余机制一旦任意一块硬盘出现故障整个阵列的数据都会丢失。\nRAID 1镜像\n\nRAID 1镜像是通过在多个硬盘上保存完全相同的数据来提高数据可靠性。每个硬盘上的数据都是相同的如果一个硬盘出现故障数据仍然可以从其他硬盘中恢复。\nRAID 5分布式奇偶校验\n\nRAID 5分布式奇偶校验将数据块和校验块分别存储在多个硬盘上。校验块被计算为所有数据块的异或值以提供数据冗余和容错能力。RAID 5 可以通过使用奇偶校验的方式在一个硬盘故障时恢复数据,但是如果两个硬盘故障,则可能会导致数据无法恢复。\nRAID 6双奇偶校验\n\nRAID 6双奇偶校验与 RAID 5 类似,但是它使用两个校验块来提供更高的数据冗余和容错能力,可以在两个硬盘故障的情况下恢复数据。\nRAID 10/01镜像 + 条带化)\n\n\nRAID 10/01镜像 + 条带化)都是将 RAID 0 和 RAID 1 组合而成的 RAID 级别,其中 RAID 10 是镜像 + 条带化RAID 01 是条带化 + 镜像。它们的区别在于数据的条带化和镜像是先进行哪一个操作。\n\nRAID 10镜像 + 条带化 RAID 10 首先将多个磁盘分成两组,每一组中的磁盘都是相互镜像的,然后将这两组磁盘进行条带化。\nRAID 01条带化 + 镜像 RAID 01 首先将多个磁盘进行条带化,然后将这些条带进行镜像备份。\n\n**RAID 10 和 RAID 01 虽然都是将 RAID 0 和 RAID 1 进行组合,但它们的性能和可靠性并不相同。**RAID 10 通常被认为比 RAID 01 更为可靠因为它允许多个磁盘同时出现故障而不会导致数据丢失。另外RAID 10 的写入性能也比 RAID 01 更好,因为 RAID 10 能够同时使用多个磁盘进行并行写入。\nRAID 级别对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nRAID 级别优点缺点硬盘数量允许损坏适用场景RAID 0高性能读写速度快性价比高容错性差一块硬盘出问题会导致全部数据丢失n≥20需要高性能的应用场景如视频编辑、大型数据库等RAID 1数据冗余可靠性高单盘故障不会影响数据容量利用率低需要成倍增加硬盘数量n≥2n-1对数据可靠性要求较高的应用场景如企业数据中心等RAID 5较高的读写性能具有数据冗余单盘故障仍能正常运行写性能较差阵列重建需要消耗大量时间n≥31对读写性能和数据可靠性要求较高的应用场景如小型企业数据库等RAID 6可以容忍任意两块硬盘故障可靠性更高读写性能较差阵列重建需要更长时间n≥42对数据可靠性要求非常高的应用场景如金融、医疗等RAID 10读写性能优秀可靠性高同时具备数据冗余和高性能的优点成本较高容量利用率低n=4,n%2=0n/2对读写性能和数据可靠性要求都很高的应用场景如大型企业数据库等\n**RAID 级别的选择应该根据实际的业务需求和场景来确定。**例如对于一个需要高性能和可靠性的应用场景RAID 10 可能是更好的选择但如果成本和容量利用率是更重要的考虑因素RAID 5 可能是更好的选择。\n长江存储\n长江存储Yangtze Memory Technologies Co., Ltd.YMTC是一家中国领先的半导体存储产品制造商总部位于武汉市东湖新技术开发区。长江存储成立于 2016 年,由中国国家集成电路产业投资基金、武汉市政府、合肥市政府和清华紫光集团共同投资成立。\n\n\n2016 年,长江存储正式成立。\n\n\n2017 年,长江存储研发成功 32 层堆叠 3D NAND 闪存。\n\n\n2018 年,公司成功研发 64 层堆叠 3D NAND 闪存,实现量产。\n\n\n2019 年,长江存储发布 128 层 3D NAND 闪存。\n\n\n2020 年,长江存储正式宣布 128 层 3D NAND 闪存量产。\n\n\n2021 年,长江存储的 128 层闪存开始广泛应用于客户端 SSD 产品。\n\n\n长江存储的主要发展方向是提高闪存产品的性能和容量降低生产成本不断扩大市场份额。公司将继续专注于 3D NAND 闪存技术的研发和量产,努力实现更高层次的堆叠技术,以满足客户在各种应用场景的需求。此外,长江存储也将积极拓展国际市场,与全球半导体产业链深度合作,提高国产存储器在全球市场的竞争力。\n长江存储是中国领先的半导体存储制造商自成立以来公司在 3D NAND 闪存技术领域取得了显著成果。通过不断提高产品性能、降低成本以及拓展国际市场,长江存储正努力在全球存储产业中树立中国品牌的地位,推动国产半导体产业的发展。\n国产之光冲冲冲"},"Technology/ComputerStorage/3.-存储架构":{"title":"3. 存储架构","links":[],"tags":["技术/计算机存储","计算机存储/基础"],"content":"存储架构\n存储架构是企业 IT 基础设施的核心部分决定了数据的存储、管理和访问方式。本文将详细介绍存储架构的不同类型及其发展历史、实现原理、技术架构和未来展望包括直接附加存储DAS、网络附加存储NAS和存储区域网络SAN。\n直接附加存储DAS\n\n直接附加存储Direct Attached StorageDAS是最早的存储架构形式之一广泛应用于早期的计算机系统中。DAS 系统通过直接连接存储设备到服务器的方式实现数据存储和访问。与网络附加存储NAS和存储区域网络SAN相比DAS 架构更加简单,性能也较高。\n发展历史\nDAS 系统的发展始于计算机早期阶段,随着技术的进步,不断演变和改进。\n\n1970 年代DAS 系统初期使用并行 ATAPATA接口这种接口在台式机和服务器中非常常见但受限于传输速度和数据线的限制。\n2000 年代初:随着技术进步,串行 ATASATA接口逐渐取代了 PATA 接口。SATA 接口不仅传输速度更快,而且数据线更细、更便于管理。\n2000 年代中期:串行连接 SCSISAS接口出现进一步提升了 DAS 系统的性能和可靠性。SAS 接口支持更高的数据传输速率,并且具有较好的兼容性和扩展性。\n2010 年代非易失性存储器快速接口NVMe开始被广泛应用使得 DAS 系统的传输速度达到新的高度。NVMe 接口利用 PCIe 总线,实现了更低的延迟和更高的 IOPS 性能。\n\n实现原理\nDAS 系统通过专用接口将存储设备(如硬盘驱动器或固态硬盘)直接连接到服务器的主板上。每个存储设备都有其独立的数据通道,与主机直接通信,不经过任何中间网络设备。这种直接连接的方式确保了数据传输的高效性和稳定性。\n技术架构\nDAS 系统的主要组件包括:\n\n存储设备硬盘驱动器HDD或固态硬盘SSD用于存储数据。SSD 由于其高性能和低延迟,逐渐成为主流选择。\n接口实现数据传输的接口包括 SATA、SAS 和 NVMe。不同接口类型提供不同的传输速度和功能。\n控制器管理数据读写操作的硬件或固件。控制器负责协调存储设备与服务器之间的数据传输确保数据的完整性和可靠性。\n\n优缺点\n优点:\n\n高性能由于存储设备直接连接到服务器数据传输路径短延迟低性能高。\n低成本相较于 NAS 和 SANDAS 系统的架构简单,不需要额外的网络设备,成本较低。\n易于部署DAS 系统的安装和配置相对简单,适合小型企业和个人用户。\n\n缺点:\n\n扩展性差DAS 系统的存储容量受限于服务器的接口数量和可支持的存储设备数量,扩展性较差。\n共享性低DAS 系统通常仅限于单个服务器使用,不能方便地在多个服务器之间共享存储资源。\n管理复杂随着存储设备数量的增加管理和维护多个独立的 DAS 系统变得复杂。\n\n适用场景\nDAS 系统适用于以下场景:\n\n小型企业由于成本低、易于部署小型企业常采用 DAS 系统满足其存储需求。\n高性能应用需要高数据传输速度和低延迟的应用如视频编辑、科学计算等。\n特定任务某些专用任务如备份服务器、监控系统等由于不需要共享存储资源DAS 系统是一个理想选择。\n\n**直接附加存储DAS作为一种经典的存储架构具有高性能、低成本和易于部署的优点。**虽然在扩展性和共享性方面有所不足但在小型企业和特定应用场景中DAS 系统依然是一种高效且可靠的存储解决方案。随着技术的发展DAS 系统的接口类型和性能不断提升,为用户提供了更多的选择和更好的使用体验。\n网络附加存储NAS\n\n网络附加存储Network Attached StorageNAS是一种专为数据存储和文件共享设计的设备。通过连接到网络NAS 设备可以为多个客户端提供集中式存储服务解决了直接附加存储DAS在共享和扩展性方面的局限。\n发展历史\nNAS 系统的出现可以追溯到 20 世纪 90 年代,旨在克服 DAS 系统在数据共享和扩展性上的不足。以下是 NAS 系统发展中的几个关键节点:\n\n1992 年NetApp 公司推出了世界上第一台 NAS 设备,采用了文件系统和 TCP/IP 协议,使得存储设备能够通过网络进行文件共享。\n1995 年EMC 公司进入 NAS 市场,推出了高性能的 NAS 产品,进一步推动了 NAS 技术的发展和普及。\n2000 年代随着网络技术的发展NAS 设备逐渐支持千兆以太网Gigabit Ethernet提高了数据传输速度和效率。\n2010 年代:引入了 10GbE 和更高速的网络接口,使得 NAS 设备在性能上有了显著提升,并开始支持更多的企业级功能,如快照、复制和远程备份。\n\n实现原理\nNAS 系统通过网络接口通常是以太网连接到局域网LAN实现数据的集中存储和共享。客户端设备如计算机、服务器通过网络文件协议如 NFS、SMB/CIFS访问 NAS 设备上的数据。\n技术架构\nNAS 系统的主要组件包括:\n\n存储设备NAS 设备内部集成了多个硬盘驱动器HDD或固态硬盘SSD用于存储数据。\n网络接口常见的网络接口类型包括千兆以太网Gigabit Ethernet和 10GbE用于连接到局域网。\n操作系统NAS 设备运行专用的 NAS 操作系统,提供存储管理、网络服务和数据保护功能。常见的 NAS 操作系统有 FreeNAS、Synology DSM 和 QNAP QTS。\n协议支持NAS 设备通常支持多种网络文件协议如网络文件系统NFS、服务器消息块SMB/CIFS、苹果文件协议AFP确保跨平台的文件访问和共享。\n\n优缺点\n优点\n\n易于共享和管理NAS 设备通过网络连接,多个客户端可以同时访问和共享存储资源,简化了文件管理和协作。\n良好的扩展性NAS 系统可以通过增加硬盘或扩展柜轻松扩展存储容量,满足不断增长的数据需求。\n数据保护许多 NAS 设备提供高级数据保护功能,如 RAID、快照和备份确保数据的安全性和完整性。\n\n缺点\n\n性能受限于网络带宽NAS 设备的性能通常受限于网络带宽,尤其是在高并发访问或大文件传输时,可能会出现瓶颈。\n延迟较高相比 DAS 系统NAS 由于通过网络进行数据传输,延迟较高,可能不适用于对延迟敏感的应用。\n\n适用场景\nNAS 系统适用于以下场景:\n\n文件共享和协作在企业或团队中NAS 设备可以作为中心文件服务器,提供集中存储和文件共享,支持跨平台访问。\n数据备份和恢复NAS 设备常用于数据备份和恢复,提供自动备份、版本控制和数据恢复功能,保障数据安全。\n多媒体存储和流媒体家庭和小型企业可以使用 NAS 设备存储多媒体文件(如照片、视频、音乐),并通过 DLNA 等协议实现流媒体播放。\n\n**网络附加存储NAS作为一种高效、灵活的存储解决方案通过网络接口实现了数据的集中存储和共享。**尽管在性能上可能受限于网络带宽,但 NAS 系统在文件共享、数据备份和多媒体存储等应用场景中表现出色。随着网络技术和存储技术的不断进步NAS 设备的性能和功能将进一步提升,继续为中小型企业和家庭用户提供可靠的存储服务。\n存储区域网络SAN\n存储区域网络Storage Area NetworkSAN是一种高性能的存储架构通过专用的存储网络连接服务器和存储设备为企业和数据中心提供高效、可靠的存储解决方案。SAN 系统提供了块级存储访问,能够满足对高性能和高可用性存储需求的关键业务应用。\n发展历史\n存储区域网络的发展始于 20 世纪 90 年代末,旨在解决传统存储架构在性能和扩展性方面的不足。以下是 SAN 系统发展历程中的一些关键节点:\n\n1990 年代末SAN 系统开始普及最早采用的是光纤通道Fibre Channel技术提供高速、低延迟的存储连接。\n2000 年代初:随着互联网技术的发展,基于 IP 的 iSCSI 协议被引入,使得通过标准以太网实现 SAN 成为可能,降低了部署成本。\n2010 年代:引入了 Fibre Channel over EthernetFCoE技术结合了光纤通道的高性能和以太网的灵活性进一步提升了 SAN 系统的效率和可管理性。\n\n实现原理\nSAN 系统通过专用的存储网络(通常是光纤通道或以太网)将服务器和存储设备连接起来。服务器可以通过 SAN 网络直接访问存储设备上的块设备实现高效的数据读写操作。SAN 系统提供了集中化的存储管理,支持高级数据保护和备份功能。\n技术架构\nSAN 系统的主要组件包括:\n\n存储设备SAN 系统中的存储设备通常是高性能硬盘阵列或固态硬盘SSD用于存储大量数据并提供快速访问。\n网络交换机SAN 网络使用光纤通道交换机或以太网交换机连接存储设备和服务器。光纤通道交换机提供高速、低延迟的数据传输,以太网交换机则支持 iSCSI 协议,实现基于 IP 的存储连接。\n协议支持SAN 系统支持多种存储网络协议,包括 Fibre Channel、iSCSI 和 FCoE。这些协议确保数据在服务器和存储设备之间的高效传输。\n管理软件SAN 系统配备专用的管理软件,用于集中管理和配置存储资源。管理软件提供存储设备的监控、配置和优化功能,确保系统的高可用性和性能。\n\n优缺点\n优点:\n\n高性能SAN 系统通过高速存储网络实现了快速的数据传输,适用于高性能计算和数据库应用。\n高可用性SAN 系统通常具有冗余设计,支持多路径访问和故障切换,提高了系统的可靠性和可用性。\n良好的扩展性SAN 系统可以通过增加存储设备和网络交换机轻松扩展存储容量,满足不断增长的数据需求。\n集中管理SAN 系统提供集中化的存储管理,简化了存储资源的配置和管理,提高了运营效率。\n\n缺点:\n\n成本较高SAN 系统的初始部署和维护成本较高,包括高性能存储设备、光纤通道交换机和专业管理软件。\n复杂性高SAN 系统的架构和管理相对复杂,需要专业的技术人员进行维护和管理。\n\n适用场景\nSAN 系统适用于以下场景:\n\n大型企业和数据中心需要高性能、高可用性存储解决方案的企业和数据中心SAN 系统可以满足其关键业务应用的需求。\n高性能计算和数据库应用对于需要快速数据访问和高吞吐量的应用如科学计算、金融交易和大型数据库SAN 系统提供了理想的存储环境。\n虚拟化和云计算SAN 系统支持虚拟化和云计算环境中的集中存储和动态资源分配,提高了资源利用率和灵活性。\n\n存储区域网络SAN作为一种高性能的存储架构通过专用存储网络提供了块级存储访问具有高性能、高可用性和良好的扩展性。尽管成本和复杂性较高SAN 系统在大型企业和数据中心中得到了广泛应用满足了关键业务应用对存储性能和可靠性的严格要求。随着技术的不断进步SAN 系统将继续在高性能计算和虚拟化环境中发挥重要作用,为企业提供可靠的存储解决方案。\n存储架构的演变与发展\n随着技术的不断进步存储架构也在不断演变和发展以满足不同应用场景和业务需求。以下是存储架构发展中的几个重要趋势和技术。\n软件定义存储SDS\n软件定义存储Software-Defined StorageSDS通过抽象硬件资源使用软件实现存储功能为用户提供更高的灵活性和可扩展性。\nSDS 系统可以在标准硬件上运行,并支持多种存储协议和服务,具有以下特点:\n\n硬件抽象SDS 通过软件层将存储硬件抽象化,使存储资源的管理和配置更加灵活,不再依赖于特定的硬件设备。\n灵活扩展SDS 系统可以根据需求动态扩展存储容量和性能,无需更换整个存储架构。\n统一管理通过统一的软件平台管理存储资源实现对不同类型存储设备的集中管理和监控。\n\n主要优势:\n\n灵活性高SDS 可以在各种标准硬件上运行,用户可以根据需求选择硬件设备,避免厂商锁定。\n成本节约使用标准硬件和开源软件组件可以降低存储系统的总体拥有成本。\n易于扩展可以按需添加新的存储节点实现存储容量和性能的无缝扩展。\n\n超融合基础设施HCI\n**超融合基础设施Hyper-Converged InfrastructureHCI通过将计算、存储和网络资源整合到一个统一的平台上实现资源的统一管理和动态分配。**HCI 系统利用虚拟化技术,简化了 IT 基础设施的部署和管理,提高了资源利用率。其主要特点包括:\n\n统一平台计算、存储和网络资源集成在一个硬件设备中简化了物理设备的部署和管理。\n虚拟化技术通过虚拟化软件实现资源的池化和动态分配提高了资源的利用效率。\n扩展性强可以通过添加新的节点无缝扩展系统资源满足业务增长需求。\n\n主要优势:\n\n部署简便HCI 系统预先集成了计算、存储和网络资源,减少了部署和配置时间。\n管理简化通过统一的管理界面管理所有资源降低了运维复杂性。\n高效利用资源虚拟化技术实现资源池化和动态分配提高了资源利用率和系统灵活性。\n\n云存储\n**云存储Cloud Storage利用云计算技术提供按需扩展的存储服务。**企业可以通过云存储服务提供商获取高可用性和可扩展的存储资源,降低存储成本和管理复杂性。云存储具有以下特点:\n\n按需扩展根据实际需求动态调整存储容量避免过度采购和资源浪费。\n高可用性云存储服务提供商通常提供多重数据备份和灾难恢复措施确保数据的高可用性和可靠性。\n简化管理用户无需管理底层硬件只需关注数据和应用简化了存储系统的运维工作。\n\n主要优势\n\n成本节约按需付费模式降低了初始投资和运营成本。\n高可用性和可靠性云服务提供商提供的数据冗余和备份措施提高了数据的安全性和可靠性。\n灵活性和可扩展性可以随时调整存储容量满足业务需求的快速变化。\n\n存储网关和中继技术\n随着企业数据量的爆炸式增长和存储需求的多样化存储网关和中继技术在存储架构中扮演着越来越重要的角色。这些技术不仅提升了存储系统的灵活性和可扩展性还简化了数据管理和传输的复杂性。\n存储网关\n**存储网关Storage Gateway是一种连接本地存储和云存储的桥梁提供数据迁移、缓存和优化功能使企业能够无缝利用云存储资源。**存储网关通常支持多种存储协议,如 NFS、SMB/CIFS 和 iSCSI简化了数据的跨平台访问。其主要特点包括\n\n数据迁移支持将本地存储的数据迁移到云存储或从云存储迁移回本地实现数据的灵活调度和管理。\n缓存功能在本地存储和云存储之间提供缓存提高数据访问速度和效率减少延迟。\n数据优化通过数据压缩、重复数据删除和加密等技术优化数据传输和存储降低存储成本和提高安全性。\n\n主要优势\n\n灵活性存储网关使企业能够根据需要在本地和云存储之间灵活调度数据适应不同业务场景。\n成本节约通过缓存和数据优化技术减少了数据传输量和存储成本。\n简化管理支持多种存储协议简化了异构存储环境中的数据管理和访问。\n\n存储中继\n**存储中继Storage Relay通过中继设备或服务实现不同存储系统之间的数据传输和同步提高了数据的可访问性和一致性。**存储中继技术在异构存储环境和灾备方案中具有重要作用。其主要特点包括:\n\n数据传输实现不同存储系统之间的高速数据传输确保数据在不同位置和系统之间的一致性。\n数据同步通过定期或实时的数据同步确保数据在多个存储系统之间的一致性和可用性。\n异构环境支持支持不同类型和品牌的存储系统提供统一的数据传输和同步解决方案。\n\n主要优势\n\n数据一致性通过定期或实时同步确保不同存储系统之间的数据一致性减少数据不一致带来的风险。\n高可用性在灾备方案中存储中继技术可以确保数据在不同位置之间的可用性提高系统的容灾能力。\n跨平台支持支持异构存储环境实现不同存储系统之间的无缝数据传输和同步简化数据管理。\n\n适用场景\n存储网关和存储中继技术适用于以下场景\n\n混合云环境企业利用存储网关将本地存储与云存储无缝连接灵活利用云资源优化存储成本。\n灾备方案通过存储中继技术实现不同数据中心之间的数据同步和传输提高灾备能力和数据可用性。\n异构存储环境在多种存储系统共存的环境中存储中继技术提供统一的数据管理和传输解决方案简化数据管理。\n\n存储网关和中继技术在现代存储架构中发挥着关键作用提升了数据管理的灵活性和效率。存储网关通过连接本地存储和云存储提供数据迁移、缓存和优化功能帮助企业更好地利用云存储资源。\n存储中继通过实现不同存储系统之间的数据传输和同步提高了数据的一致性和可访问性特别是在异构存储环境和灾备方案中具有重要作用。随着技术的不断发展这些技术将继续在数据管理和存储优化中发挥重要作用为企业提供更加灵活和高效的存储解决方案。\n结论\n存储架构是企业 IT 基础设施的关键组成部分,不同的存储架构类型适用于不同的业务需求和场景。存储架构从传统的 DAS、NAS 和 SAN 系统,逐步发展到 SDS、HCI 和云存储,每种架构都有其独特的优缺点,更体现了技术进步和需求变化的驱动力。\n随着技术的不断发展存储架构将继续创新和进化为企业的数字化转型提供坚实的基础。在未来随着大数据、人工智能和物联网等技术的进一步发展存储架构将面临新的挑战和机遇为企业提供更加灵活、高效和可靠的存储服务。"},"Technology/ComputerStorage/4.-文件系统":{"title":"4. 文件系统","links":[],"tags":["标签"],"content":"文件系统\nLinux 文件系统\nLinux 文件系统始于 1987 年,当时 Linus Torvalds 在创建 Linux 内核时,选择了 Minix 文件系统。Minix 文件系统由 Andrew S. Tanenbaum 为 Minix 操作系统设计,具有简单且可靠的特点。然而,由于其最大文件和文件系统大小仅为 64MB以及文件名长度限制为 14 字符,无法满足更复杂的需求。\n1992 年Rémy Card 开发了第一个专为 Linux 设计的文件系统 Extended File System (EXT),以解决 Minix 文件系统的限制问题。EXT 的最大文件和文件系统大小分别为 2GB文件名长度扩展到 255 字符。然而EXT 仍然缺乏日志功能和对更大规模的支持。\n1993 年Rémy Card 发布了 EXT2 文件系统,这成为 Linux 内核 2.0 版的默认文件系统。EXT2 支持的最大文件大小为 2TB最大文件系统大小为 4TB尽管没有日志功能但它提供了更大的文件和文件系统支持并改进了性能。\n1994 年Silicon GraphicsSGI开发了 XFS 文件系统,最初用于其 IRIX 操作系统。XFS 以其高性能和可扩展性在科学计算和数据密集型应用中广泛使用,支持的最大文件和文件系统大小分别为 18EB具有高效的日志记录机制。\n2001 年Stephen Tweedie 发布了 EXT3 文件系统,这是 EXT2 的升级版本增加了日志功能以提高数据可靠性和系统恢复速度。EXT3 保持了 EXT2 的文件和文件系统大小限制,并且向后兼容 EXT2。同年Hans Reiser 开发了 ReiserFS这是第一个默认支持日志功能的文件系统支持的最大文件和文件系统大小分别为 8TB 和 16TB。ReiserFS 以高效的小文件存储和快速目录查找而闻名,但后续发展受限,逐渐被其他文件系统取代。\n2004 年Sun Microsystems 开发并发布了 ZFS 文件系统,最初用于 Solaris 操作系统现在已移植到多个平台。ZFS 提供了极高的数据完整性和灵活性,支持的最大文件和文件系统大小为 256 兆亿亿字节,并集成了文件系统和逻辑卷管理、数据完整性校验、快照和复制、自动修复等新特性,适用于企业存储解决方案和云存储环境。\n2007 年Oracle 公司开发的 Btrfs 文件系统首次发布旨在提供高级管理功能和高可靠性。Btrfs 支持的最大文件和文件系统大小均为 16EB具有快照、内联数据压缩、子卷管理和在线文件系统检查等新特性适用于需要高级存储管理和数据保护的场景。\n2008 年,由 Theodore Tso 领导开发的 EXT4 文件系统发布,成为 EXT3 的继任者。EXT4 显著改进了性能和可靠性,支持的最大文件大小达到 1EB最大文件系统大小为 16TB并引入了延迟分配、多块分配、无日志模式和在线碎片整理等新特性。\nLinux 文件系统从 Minix 到 EXT再到更高级的 EXT4、Btrfs、XFS 和 ZFS 的发展过程中,每一次升级都带来了更大的存储支持、更高的性能和可靠性,以及更多的管理功能。\nEXT4\nEXT4Fourth Extended File System于 2008 年发布,由 Theodore Tso 领导开发,作为 EXT3 的继任者。EXT4 的发展旨在解决 EXT3 在大规模存储和性能上的限制并引入了许多新特性和性能改进。EXT4 成为现代 Linux 系统的主流文件系统,广泛应用于各种场景,从个人电脑到企业级服务器。它的设计兼顾了向后兼容和未来扩展的需求,使其在稳定性和性能上都有显著提升。\n\n特点\n\n最大文件大小1EBExabyte\n最大文件系统大小16TBTerabyte\n文件碎片整理引入了延迟分配Delayed Allocation技术这一特性通过推迟分配数据块的位置来减少文件碎片提高了文件系统性能。\n多块分配多块分配Multiblock Allocation允许一次性分配多个块减少文件碎片提高写入效率。\n日志模式支持多种日志模式Journal Mode包括数据模式、元数据模式和延迟模式以平衡性能和数据安全。\n文件系统检查引入了快速文件系统检查功能Fast Fsck通过存储已校验的文件系统部分减少了文件系统检查时间。\n无日志模式支持无日志模式No Journaling Mode适用于对性能要求极高而对数据安全要求不高的场景。\n在线碎片整理支持在线碎片整理功能允许在不卸载文件系统的情况下进行碎片整理提高了系统的可用性。\n\nBtrfs\nBtrfsB-Tree 文件系统)由 Oracle 公司于 2007 年首次发布旨在提供高级管理功能和高可靠性。Btrfs 的设计目标是应对大规模存储系统的需求并提供丰富的数据管理功能。Btrfs 在开发初期得到了广泛关注,被认为是未来 Linux 文件系统的发展方向之一。它的许多特性,如快照、压缩和自我修复,使其在数据密集型和高可靠性要求的应用场景中具有显著优势。\n\n特点\n\n最大文件大小16EBExabyte\n最大文件系统大小16EB\n快照支持快照Snapshot功能可以快速创建文件系统的时间点副本用于数据备份和恢复。\n内联数据压缩支持内联数据压缩Inline Compression有效减少存储空间需求。\n子卷管理支持子卷Subvolume管理允许在同一文件系统中创建多个逻辑卷提供更灵活的存储管理。\n在线文件系统检查支持在线文件系统检查和修复Online Scrubbing and Repair可以在系统运行时检测和修复数据损坏。\n自我修复内置数据校验和自我修复功能自动检测并修复数据损坏确保数据完整性。\n可扩展性高可扩展性支持大规模存储需求并允许在不中断服务的情况下进行文件系统扩展和缩减。\n\nXFS\nXFS 文件系统由 Silicon GraphicsSGI于 1994 年开发,最初用于其高性能计算和图形工作站的 IRIX 操作系统。XFS 以其高性能和可扩展性著称,特别适合处理大文件和高并发 I/O 操作。随着时间的推移XFS 被移植到 Linux 平台,并在数据密集型应用和科学计算领域得到了广泛应用。\n\n特点\n\n最大文件大小18EBExabyte\n最大文件系统大小18EB\n日志记录机制高效的日志记录机制Efficient Logging减少了系统崩溃后的恢复时间提高了数据可靠性。\n直接 I/O支持直接 I/ODirect I/O允许应用程序直接访问磁盘绕过文件系统缓存提高了 I/O 性能。\n可扩展性极高的可扩展性能够处理极大规模的存储需求适用于高性能计算和数据中心。\n动态扩展支持文件系统的动态扩展Dynamic Allocation在不卸载文件系统的情况下进行扩展。\n并发支持优秀的并发支持适用于高并发的 I/O 操作场景,如数据库和大规模数据处理。\n\nZFS\nZFSZettabyte File System由 Sun Microsystems 开发,最初用于 Solaris 操作系统现已移植到多个平台。ZFS 于 2004 年首次发布旨在提供极高的数据完整性和灵活性。ZFS 的设计理念是将文件系统和逻辑卷管理融合在一起,简化存储管理,同时提供强大的数据保护和管理功能。其创新的设计和丰富的特性使其在企业存储解决方案和云存储环境中得到了广泛应用。\n\n特点\n\n最大文件大小256 兆亿亿字节\n最大文件系统大小256 兆亿亿字节\n集成文件系统和逻辑卷管理ZFS 将文件系统和逻辑卷管理融合在一起,提供统一的存储管理界面,简化了管理操作。\n数据完整性校验内置数据校验Data Integrity Verification和自我修复功能确保数据在传输和存储过程中的完整性。\n快照和克隆支持快照Snapshot和克隆Clone功能可以快速创建数据副本用于备份和测试。\n自动修复当检测到数据损坏时ZFS 能自动从冗余数据中恢复,确保数据的高可靠性。\n高级存储管理支持数据压缩、去重Deduplication和动态磁盘池Dynamic Storage Pooling提高存储效率和灵活性。\n可扩展性高可扩展性支持大规模存储环境适用于企业级和云计算场景。\n\n对比表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件系统最大文件大小最大文件系统大小日志功能快照压缩数据校验自我修复应用场景EXT41EB16TB有无无无无现代 Linux 系统广泛应用于个人电脑和服务器Btrfs16EB16EB有有有有有高级存储管理和数据保护适用于服务器和企业级应用XFS18EB18EB有无无无无高并发 I/O 和大文件处理适用于高性能计算和数据密集型应用ZFS256 兆亿亿字节256 兆亿亿字节有有有有有企业存储解决方案和云存储环境,提供极高的数据完整性和灵活性\nWindows 文件系统\n1980 年代中期微软推出了最初的文件系统——FAT 文件系统File Allocation Table用于 MS-DOS 操作系统。FAT 文件系统简单且高效,适用于当时的硬盘存储需求。它最初有 FAT12 和 FAT16 两个版本分别用于小型和中型存储设备。FAT16 支持的最大分区大小为 2GB文件名长度为 8.3 格式(即最多 8 个字符的文件名加上 3 个字符的扩展名)。\n1993 年,随着 Windows NT 3.1 的发布微软引入了NTFS 文件系统New Technology File System。NTFS 提供了许多先进的功能如文件和文件系统的权限管理、日志记录、文件压缩和加密等。NTFS 支持的最大文件和文件系统大小大幅提升,文件名长度扩展到 255 字符。\n1996 年FAT32 文件系统随着 Windows 95 OSR2 的发布而推出,旨在克服 FAT16 的限制。FAT32 支持的最大分区大小为 2TB文件名长度仍为 8.3 格式,但增加了长文件名支持,允许最多 255 个字符。FAT32 广泛用于 U 盘和小型存储设备,因其跨平台兼容性而受到欢迎。\n2001 年,随着 Windows XP 的发布NTFS 文件系统成为默认文件系统。NTFS 的优势包括支持大文件和大分区、更好的数据安全性和可靠性以及改进的磁盘空间利用率。Windows XP 还继续支持 FAT32 文件系统,以保持对旧系统和设备的兼容性。\n2006 年Windows Vista 发布,引入了 NTFS 3.1 版本,增加了对事务性 NTFSTxF的支持以提高文件操作的可靠性和一致性。虽然 TxF 在后来版本中被弃用,但它显示了 NTFS 在功能和性能上的不断改进。\n2012 年,随着 Windows 8 的发布微软推出了ReFS 文件系统Resilient File System旨在提供更高的数据完整性和可扩展性。ReFS 具有自动修复、数据校验、数据损坏隔离等特性特别适用于大规模数据存储和虚拟化环境。ReFS 支持的最大文件大小和文件系统大小为 1YB1 百万 TB。\n2017 年,随着 Windows 10 的更新,微软引入了对 Linux 文件系统(如 Ext4 和 Btrfs的支持通过 Windows Subsystem for LinuxWSL使用户能够在 Windows 上使用 Linux 文件系统和工具。这标志着 Windows 文件系统生态的进一步扩展和兼容性提升。\nWindows 文件系统的发展历程从早期的 FAT 和 FAT16逐步发展到功能强大的 NTFS再到专为大规模数据存储设计的 ReFS每一次升级都带来了更高的性能、可靠性和功能。现代 Windows 操作系统还通过 WSL 支持 Linux 文件系统,展示了其在兼容性和多样性上的持续改进。\nNTFS\nNTFSNew Technology File System由 Microsoft 于 1993 年随 Windows NT 3.1 发布,作为 FAT 文件系统的继任者。NTFS 设计初衷是提供更高的安全性、可靠性和可扩展性,适应企业级应用的需求。它的发展伴随着 Windows NT 系列操作系统的进化,从最初的 NT 3.1 到后来的 Windows 2000、XP、Vista、7、8 和 10。NTFS 的引入标志着文件系统安全性和性能的显著提升,使其成为 Windows 系统的标准文件系统。\n特点\n\n文件和卷加密支持 EFSEncrypting File System加密技术提供文件和文件夹级别的加密保护。\n磁盘配额允许管理员设置磁盘配额限制用户或组的磁盘使用量。\n压缩支持文件和文件夹的压缩功能节省存储空间。\n日志功能具有日志功能记录文件系统元数据的变更确保数据完整性和快速恢复。\n单个文件和卷大小支持高达 256TB 的单个文件和卷大小,满足大规模存储需求。\n权限管理提供细粒度的文件和文件夹权限设置增强了数据安全性。\n索引服务支持文件内容索引加快文件搜索速度。\n\nFAT32\nFAT32File Allocation Table 32是 FAT 文件系统的改进版,于 1996 年随 Windows 95 OSR2 发布。FAT32 旨在解决 FAT16 的容量限制问题提供更大的卷和文件支持。由于其良好的兼容性FAT32 在便携设备和多平台数据交换中得到广泛应用。\n特点\n\n兼容性FAT32 可以在多种操作系统(如 Windows、MacOS、Linux之间无缝使用广泛用于便携式存储设备。\n卷和文件大小支持最高 4GB 的单个文件和 2TB 的卷大小。\n效率较小的簇大小提高了磁盘空间的利用率。\n简单性文件系统结构简单易于实现和维护。\n局限性不支持文件加密、磁盘配额和文件压缩等高级功能。\n\nexFAT\nexFATExtended File Allocation Table于 2006 年由 Microsoft 发布,旨在替代 FAT32专为闪存存储设备如 SD 卡和 USB 闪存驱动器优化。exFAT 解决了 FAT32 在文件大小和卷大小上的限制,同时保持了跨平台兼容性。\n特点\n\n文件和卷大小支持高达 128PB 的卷大小和无实际限制的文件大小,适用于大容量存储需求。\n优化性能针对闪存存储器优化提供更高的读写性能。\n跨平台兼容性广泛支持多种操作系统适合便携式存储设备。\n簇大小支持更大的簇大小适合处理大文件。\n简单性比 NTFS 结构简单,适合嵌入式系统和便携设备。\n\nReFS\nReFSResilient File System于 2012 年由 Microsoft 发布,作为 NTFS 的继任者,主要用于 Windows Server 环境。ReFS 设计初衷是提高数据可用性和弹性,特别适用于大规模数据存储和虚拟化环境。\n特点\n\n数据完整性采用校验和算法检测和修复数据损坏提高数据可靠性。\n自动修复支持自动修复功能通过冗余数据副本自动修复损坏的数据。\n弹性设计用于处理极大规模的数据卷和文件支持高达数百 PB 的存储容量。\n性能优化针对虚拟化和大规模存储场景进行了优化提高了性能和效率。\n兼容性虽然 ReFS 不完全兼容所有 NTFS 功能,但它与 Windows Server 和存储空间Storage Spaces高度集成。\n\n对比表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件系统最大文件大小最大卷大小日志功能文件和卷加密磁盘配额压缩跨平台兼容性应用场景NTFS256TB256TB有有有有部分兼容Windows 桌面和服务器企业级应用FAT324GB2TB无无无无广泛兼容便携式存储设备多平台数据交换exFAT无实际限制128PB无无无无广泛兼容闪存存储设备便携式大容量存储ReFS35PB35PB有无有无部分兼容大规模数据存储虚拟化环境Windows Server\nMacOS 主流文件系统\n1984 年Apple 推出了用于 Macintosh 计算机的初代文件系统——MFSMacintosh File System。MFS 是一个简单的文件系统,支持单级目录结构和 128KB 的块大小。虽然对于早期的 Macintosh 计算机来说足够但随着存储需求的增加MFS 的局限性逐渐显现。\n1985 年Apple 发布了**HFSHierarchical File System**以替代 MFS。HFS 引入了分层目录结构,支持更大容量的硬盘和文件系统,最大支持 2GB 的卷和 2GB 的文件大小。HFS 采用 512 字节的块大小,并增加了多级目录支持,极大地改善了文件管理。\n1998 年,随着 Mac OS 8.1 的发布Apple 推出了HFS+(也称为 Mac OS Extended这是对 HFS 的重大改进。HFS+ 引入了更小的块大小4KB大幅提高了磁盘空间利用率支持的最大卷和文件大小分别扩展到 8EBexabytes。HFS+ 还引入了 Unicode 支持,使文件名能够包含更多的字符。\n2002 年Mac OS X 10.2 Jaguar 发布HFS+ 成为默认文件系统。随着系统的不断更新HFS+ 增加了许多新功能,包括文件压缩、稀疏文件支持和更高效的文件存储。\n2014 年Apple 在 OS X Yosemite 中引入了 Core Storage这是一个逻辑卷管理器允许用户创建加密卷和使用 Fusion Drive 技术,将 SSD 和 HDD 组合成一个卷以提高性能和存储效率。\n2016 年Apple 发布了 macOS Sierra并引入了APFSApple File System。APFS 是对 HFS+ 的彻底重构设计目标是提高性能、安全性和可靠性。APFS 支持 64 位文件 ID最大支持的文件和卷大小为 8EB具有更快的目录操作、更高效的空间管理和更强的数据完整性保障。APFS 还支持快照、克隆、加密和原子操作,极大地提升了文件系统的功能性和用户体验。\n2017 年macOS High Sierra 发布APFS 成为默认文件系统。APFS 特别针对 SSD 优化,但也兼容 HDD 和外部存储设备。APFS 的推出标志着 macOS 文件系统迈向现代化和高效管理的新阶段。\nmacOS 文件系统从最初的 MFS 到 HFS再到 HFS+ 和现代的 APFS每一次升级都带来了显著的改进和新功能。随着存储需求和技术的发展Apple 不断提升文件系统的性能、可靠性和功能,确保 macOS 能够满足现代用户的需求。\nHFS+\nHFS+Hierarchical File System Plus也称为 Mac OS Extended是 Apple 于 1998 年推出的文件系统,用于替代早期的 HFS 文件系统。HFS+ 是为适应更大的存储需求和提高文件管理效率而设计的。它首次随 Mac OS 8.1 引入,并在之后的多个 Mac OS 版本中成为标准文件系统。HFS+ 通过增加文件大小和卷大小的支持,改进文件命名和目录结构,满足了当时不断增长的存储需求。\n特点\n\n最大文件大小8EBExabyte\n最大卷大小8EB\n硬链接和软链接支持硬链接和软链接提供更灵活的文件管理方式。\n文件压缩支持文件压缩减少存储空间的占用。\n分层目录结构改进的分层目录结构支持更大的文件和目录。\nUnicode 支持:改进的文件名编码,支持 Unicode 字符集,增强了跨平台兼容性。\n数据完整性支持日志功能记录文件系统的元数据更改提高数据完整性和恢复速度。\n\nAPFS\n文化和发展历史\nAPFSApple File System是 Apple 于 2017 年发布的新一代文件系统,设计初衷是替代 HFS+以满足现代存储需求。APFS 针对 SSD 和闪存存储器进行了优化显著提升了性能和数据安全性。APFS 随着 macOS High Sierra 的发布而引入,并逐渐成为 macOS、iOS、watchOS 和 tvOS 的标准文件系统。其设计注重高性能、高安全性和高效的存储管理,适应了当前和未来的数据存储需求。\n特点\n\n最大文件大小8EBExabyte\n最大卷大小8EB\n快照支持快照功能可以在不同时间点创建文件系统的副本方便数据恢复和备份。\n克隆支持克隆功能在不占用额外存储空间的情况下创建文件或目录的副本。\n加密内置强大的加密功能支持单文件和整个卷的加密增强了数据安全性。\n空间共享支持空间共享Space Sharing多个卷可以共享同一存储池有效利用存储空间。\n文件和目录压缩支持高效的文件和目录压缩节省存储空间。\n高效存储优化的元数据管理和文件系统布局提供更高的存储效率和性能。\n崩溃保护具备崩溃保护机制通过快速重启和数据恢复确保数据的高可用性。\n\n对比表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件系统发布年份最大文件大小最大卷大小日志功能硬链接软链接文件压缩快照克隆加密空间共享应用场景HFS+1998 年8EB8EB有有有有无无无无早期 Mac OS 系统个人计算和多媒体处理APFS2017 年8EB8EB有无有有有有有有现代 macOS、iOS、watchOS 和 tvOS 设备,提供高性能和数据安全性\n文件系统结构与管理\n文件系统结构\n层次\n文件系统层次结构指的是文件和目录的组织方式。大多数现代文件系统采用层次结构即目录和子目录构成树状结构。根目录Root Directory是树的起点其他所有文件和目录都可以从根目录访问。\n\n根目录文件系统的顶层目录通常表示为 /(在 Unix 和 Linux 系统中)或 C:\\(在 Windows 系统中)。\n目录和子目录目录是包含其他文件和目录的容器。子目录是父目录的一部分形成树状层次结构。\n文件存储数据的基本单位可以是文本文档、图像、可执行程序等。\n\n结构图\n\ngraph TD\n Superblock\n Inode1\n DataBlock1\n DataBlock2\n DataBlock3\n IndirectBlock1\n\n Superblock -->|Contains| FS_Size[File System Size]\n Superblock -->|Contains| Block_Size[Block Size]\n Superblock -->|Contains| Free_Block_Count[Free Block Count]\n Superblock -->|Contains| Free_Inode_Count[Free Inode Count]\n Superblock -->|Contains| FS_State[File System State]\n Superblock -->|Contains| FS_ID[File System ID]\n Superblock -->|Contains| Root_Inode[Root Inode]\n\n Inode1 -->|Points to| DirectBlock1[Direct Block 1]\n Inode1 -->|Points to| DirectBlock2[Direct Block 2]\n Inode1 -->|Points to| IndirectBlock1\n IndirectBlock1 -->|Points to| DataBlock1\n IndirectBlock1 -->|Points to| DataBlock2\n IndirectBlock1 -->|Points to| DataBlock3\n\n\n超级块Superblock包含文件系统的元数据例如文件系统大小、块大小、空闲块数量、空闲 Inode 数量、文件系统状态、文件系统 ID、根 Inode 等。\n索引节点Inode包含文件的元数据并指向文件的数据块。\n\n直接指针Direct Pointers直接指向数据块。\n一次间接指针Indirect Pointers指向一个包含数据块指针的块每个指针指向一个数据块。\n\n\n数据块Data Block实际存储文件数据的基本单元。\n\n超级块Superblock\n超级块是文件系统的核心元数据结构存储文件系统的整体信息。每个文件系统都有一个超级块用于描述文件系统的特性和状态。\n\n超级块就像是图书馆的管理员记录的总册它包含了图书馆的总体信息比如图书馆有多大每个书架的大小图书馆的状态是否开放有没有损坏等以及图书馆的标识符和根目录的位置。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n项目描述文件系统大小文件系统的总大小包括所有的数据块。块大小文件系统中每个数据块的大小通常为 1KB、2KB、4KB 或 8KB。空闲块数量当前可用的数据块数量表示文件系统中剩余的可用空间。空闲 Inode 数量当前可用的索引节点数量,表示文件系统中可用的文件/目录数。文件系统挂载状态文件系统是否已挂载,以及以何种模式挂载(只读或读写)。文件系统标识符唯一标识文件系统的 ID用于区分不同的文件系统实例。文件系统版本文件系统的版本号表示文件系统的格式版本。根目录 Inode指向根目录的索引节点号根目录是文件系统的入口。块组描述符位置存储块组描述符Block Group Descriptor的位置用于描述块组的结构。超级块备份位置存储超级块备份的位置通常在文件系统的多个位置保存超级块备份。文件系统状态文件系统当前的状态如是否干净卸载、是否需要检查等。文件系统创建时间文件系统创建的时间戳。文件系统修改时间最后一次修改文件系统元数据的时间戳。上次挂载时间文件系统上次被挂载的时间戳。上次卸载时间文件系统上次被卸载的时间戳。最大挂载次数在需要进行文件系统检查之前文件系统可以挂载的最大次数。文件系统检查间隔时间在需要进行文件系统检查之前文件系统可以运行的最长时间间隔。文件系统标志指示文件系统特性的标志如只读、已被卸载等。文件系统日志位置存储文件系统日志的起始位置用于恢复文件系统的一致性。默认权限掩码创建文件时使用的默认权限掩码。文件系统特性文件系统支持的特性标志如是否支持大文件、是否启用日志等。\n超级块是文件系统管理的核心一旦损坏整个文件系统将无法使用。超级块的损坏可能导致文件系统无法挂载或文件数据丢失。因此文件系统通常会在多个位置保存超级块的副本以提高容错性。\n\n主超级块文件系统中的主要超级块通常位于文件系统的第一个块。\n备份超级块为了防止单点故障文件系统会在多个位置保存超级块的副本。不同文件系统的备份策略不同例如EXT2/3/4 文件系统在每组块Block Group中保存备份超级块。\n\n索引节点Inode\nInode 是文件系统中的核心数据结构,用于存储文件元数据。每个文件和目录都有一个唯一的 Inode负责记录文件的相关信息。\n\nInode 就像每本书的标签,它记录了每本书的详细信息,比如书名、作者、出版日期、类别以及书在书架上的位置。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n项目描述文件类型指示文件的类型如普通文件、目录、符号链接等。文件大小文件的总字节数。文件权限文件的访问权限包括读r、写w和执行x权限。所有者信息文件的所有者用户 IDUID和所属组 IDGID。创建时间文件创建的时间戳。修改时间文件内容最后修改的时间戳。访问时间文件最后访问的时间戳。链接计数指向此 Inode 的硬链接数量。数据块指针指向存储文件内容的数据块的指针包括直接指针、一次间接指针、二次间接指针和三次间接指针。文件系统标志用于指示文件系统特性和状态的标志。文件生成号文件的唯一标识符通常用于网络文件系统NFS。文件大小高位文件大小的高位部分用于支持大文件。数据块数量文件使用的数据块总数。文件系统标识符标识文件系统类型或版本的标识符。数据块指针数量数据块指针的总数包括直接和间接指针。直接指针直接指向数据块的指针通常有 12 个直接指针。一次间接指针指向一个包含数据块指针的块,每个指针指向一个数据块。二次间接指针指向一个包含一次间接指针块的块,每个一次间接指针指向一个包含数据块指针的块。三次间接指针指向一个包含二次间接指针块的块,每个二次间接指针指向一个包含一次间接指针块的块。\nInode 负责管理文件的存储位置通过数据块指针指向文件的实际数据块。Inode 不存储文件名,文件名和 Inode 的关联关系存储在目录项中。\n\n直接指针直接指向数据块的指针通常一个 Inode 有 12 个直接指针。\n一次间接指针指向一个包含数据块指针的块每个指针指向一个数据块。\n二次间接指针指向一个包含一次间接指针块的块每个一次间接指针指向一个包含数据块指针的块。\n三次间接指针指向一个包含二次间接指针块的块每个二次间接指针指向一个包含一次间接指针块的块。\n\n这种指针结构使得 Inode 能够高效地管理小文件和大文件,同时提供良好的性能。\n数据块Data Block\n数据块是文件系统中存储文件实际内容的基本单元。文件的所有数据都存储在数据块中由 Inode 通过指针进行管理。数据块的大小通常为 4KB但可以根据文件系统的配置有所不同。常见的块大小有 1KB、2KB、4KB 和 8KB 等。\n\n数据块是文件系统中存储文件实际内容的基本单元就像图书馆的书架上的每一层存放书的地方。\n\n数据块用于存储文件的实际数据内容。Inode 通过直接和间接指针指向相应的数据块,以组织和管理文件数据。\n\n小文件存储对于小文件数据可以存储在少量数据块中甚至可能只使用一个数据块。Inode 的直接指针能够高效地管理这些数据块。\n大文件存储对于大文件可能需要多个直接指针、间接指针和多级间接指针来管理数据块。通过这种层次化指针结构文件系统能够有效地管理大文件同时保持性能。\n数据块分配文件系统在创建和扩展文件时会动态分配数据块。为了减少碎片化和提高性能文件系统通常会尽量连续分配数据块。\n数据块缓存为了提高文件读写性能操作系统会使用内存缓存如页缓存来缓存数据块的内容减少磁盘 I/O 操作。\n\n文件系统管理\n文件系统的创建与挂载\n\n\n创建文件系统\n在 Unix/Linux 系统中,可以使用 mkfs 命令创建文件系统。例如:\n# 创建一个 EXT4 文件系统。\nmkfs.ext4 /dev/sda1\n步骤\n\n选择并准备存储设备如磁盘分区。\n选择适当的文件系统类型。\n使用 mkfs 命令创建文件系统。\n\n\n\n挂载文件系统\n使用 mount 命令将文件系统挂载到目录。例如:\n# 将设备 `/dev/sda1` 挂载到 `/mnt` 目录。\nmount /dev/sda1 /mnt\n步骤\n\n创建挂载点目录如 /mnt。\n使用 mount 命令挂载文件系统。\n查看挂载状态可以使用 df -h 或 mount 命令。\n\n\n\n文件系统的格式化和修复\n\n\n格式化文件系统\n格式化文件系统可以使用 mkfs 命令。例如:\n# 格式化设备 `/dev/sda1` 为 EXT4 文件系统\nmkfs.ext4 /dev/sda1\n步骤\n\n确保设备未挂载。\n使用 mkfs 命令进行格式化。\n\n\n\n修复文件系统\n在 Unix/Linux 系统中,可以使用 fsck 命令检查和修复文件系统。例如:\n# 检查并修复设备 `/dev/sda1` 上的文件系统\nfsck /dev/sda1\n步骤\n\n确保文件系统未挂载对于根文件系统可以在单用户模式下进行。\n使用 fsck 命令检查文件系统的完整性。\n根据检查结果进行修复。\n\n\n\n文件权限与用户管理\n\n\n文件权限\n文件权限分为读r、写w和执行x三种。权限应用于文件所有者User、文件所属组Group和其他用户Others。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组别读rw执行xUser421Group421Others421\n使用 chmod 命令修改文件权限。例如:\n# 将文件 `filename` 的权限设置为 `rwxr-xr-x`\nchmod 755 filename\n\n\n用户和组管理\n用户管理使用 useradd 命令添加用户usermod 命令修改用户userdel 命令删除用户。例如:\n# 添加新用户 `username`\nuseradd username\n组管理使用 groupadd 命令添加组groupmod 命令修改组groupdel 命令删除组。例如:\n# 添加新组 `groupname`\ngroupadd groupname\n\n\n分布式文件系统\n分布式文件系统Distributed File SystemDFS是一种通过网络将文件存储在多个节点上的系统。它允许文件和数据跨越多台计算机进行存储和访问从而实现高可用性、高性能和高扩展性。以下内容将详细介绍几种常见的分布式文件系统包括 Hadoop Distributed File System (HDFS)、Google File System (GFS)、GlusterFS 和 CephFS。\nHadoop Distributed File System (HDFS)\n概述\nHadoop Distributed File System (HDFS) 是 Apache Hadoop 项目的一部分专为大数据处理设计。HDFS 能够处理大规模数据集支持高吞吐量的数据访问并具备良好的容错性。HDFS 最早由 Doug Cutting 和 Mike Cafarella 在 2005 年开发,灵感来源于 Google File System (GFS)。它主要用于存储和管理海量的数据,支持并行处理和分布式计算。\n历史发展\nHDFS 的历史发展与 Hadoop 项目的演进密切相关。2005 年Doug Cutting 和 Mike Cafarella 开始开发 Hadoop最初作为 Nutch 搜索引擎项目的一部分。2006 年Hadoop 被 Yahoo!采用并迅速成长为大数据处理的核心技术之一。2008 年Hadoop 成为 Apache 的顶级项目HDFS 作为其关键组件,随着大数据生态系统的扩展和完善,逐渐发展成现今广泛应用的分布式文件系统。\n架构与组件\ngraph TD;\n Client[Client] -->|Metadata Request| NN[NameNode];\n Client -->|Read/Write Data| DN1[DataNode 1];\n Client -->|Read/Write Data| DN2[DataNode 2];\n Client -->|Read/Write Data| DN3[DataNode 3];\n\n subgraph Metadata\n NN[NameNode] -->|Stores| BMR1[Block Metadata 1];\n NN -->|Stores| BMR2[Block Metadata 2];\n NN -->|Stores| BMR3[Block Metadata 3];\n end\n\n subgraph Storage\n DN1[DataNode 1] -->|Contains| B1[Block 1];\n DN1 -->|Contains| B2[Block 2];\n DN2[DataNode 2] -->|Contains| B3[Block 3];\n DN2 -->|Contains| B4[Block 4];\n DN3[DataNode 3] -->|Contains| B5[Block 5];\n DN3 -->|Contains| B6[Block 6];\n end\n\n B1 -.->|Metadata| BMR1;\n B2 -.->|Metadata| BMR2;\n B3 -.->|Metadata| BMR3;\n B4 -.->|Metadata| BMR1;\n B5 -.->|Metadata| BMR2;\n B6 -.->|Metadata| BMR3;\n\n classDef clientStyle fill:#f9f,stroke:#333,stroke-width:2px;\n classDef nnStyle fill:#9f9,stroke:#333,stroke-width:2px;\n classDef dnStyle fill:#99f,stroke:#333,stroke-width:2px;\n classDef blockStyle fill:#ff9,stroke:#333,stroke-width:2px;\n classDef metadataStyle fill:#f99,stroke:#333,stroke-width:2px;\n\n class Client clientStyle;\n class NN nnStyle;\n class DN1,DN2,DN3 dnStyle;\n class B1,B2,B3,B4,B5,B6 blockStyle;\n class BMR1,BMR2,BMR3 metadataStyle;\n\nHDFS 采用主从架构,由 NameNode 和多个 DataNode 组成:\n\nNameNode负责管理文件系统的命名空间和元数据。它记录文件和目录的树形结构并维护每个文件块的位置。NameNode 是 HDFS 的核心,所有的文件操作请求都需要通过 NameNode 来完成。\nDataNode负责存储实际的数据块并执行块的读写操作。每个 DataNode 定期向 NameNode 汇报其状态(心跳信号和块报告),以便 NameNode 能追踪数据块的分布和健康状态。\n\n此外还有一些辅助组件\n\nSecondary NameNode负责定期获取 NameNode 的元数据快照,辅助 NameNode 进行崩溃恢复,但不替代 NameNode 的功能。\nJournalNode在高可用 HDFS 配置中,用于保存 NameNode 的元数据日志,确保在主 NameNode 失败时可以无缝切换到备 NameNode。\n\n数据存储和复制机制\nHDFS 将文件划分为固定大小的数据块(默认 64MB 或 128MB并将每个数据块复制到多个 DataNode 上(默认 3 个副本),以提高数据的可靠性和容错性。数据块的多副本机制确保即使某个 DataNode 发生故障,数据仍然可以从其他副本中恢复。\nsequenceDiagram\n participant Client as Client\n participant NameNode as NameNode\n participant DataNode1 as DataNode 1\n participant DataNode2 as DataNode 2\n participant DataNode3 as DataNode 3\n\n Client->>NameNode: Request to Write File\n NameNode-->>Client: Respond with DataNodes and Block IDs\n note right of NameNode: NameNode allocates blocks and selects DataNodes for storage.\n\n Client->>DataNode1: Write Block 1 (part 1)\n DataNode1-->>Client: ACK Block 1 (part 1) Received\n Client->>DataNode2: Write Block 1 (part 2)\n DataNode2-->>Client: ACK Block 1 (part 2) Received\n Client->>DataNode3: Write Block 1 (part 3)\n DataNode3-->>Client: ACK Block 1 (part 3) Received\n\n Client->>NameNode: Notify Block 1 Written\n note right of NameNode: NameNode updates block metadata with DataNode locations.\n\n Client->>DataNode1: Write Block 2 (part 1)\n DataNode1-->>Client: ACK Block 2 (part 1) Received\n Client->>DataNode2: Write Block 2 (part 2)\n DataNode2-->>Client: ACK Block 2 (part 2) Received\n Client->>DataNode3: Write Block 2 (part 3)\n DataNode3-->>Client: ACK Block 2 (part 3) Received\n\n Client->>NameNode: Notify Block 2 Written\n note right of NameNode: NameNode updates block metadata with DataNode locations.\n\n Client->>DataNode1: Write Block 3 (part 1)\n DataNode1-->>Client: ACK Block 3 (part 1) Received\n Client->>DataNode2: Write Block 3 (part 2)\n DataNode2-->>Client: ACK Block 3 (part 2) Received\n Client->>DataNode3: Write Block 3 (part 3)\n DataNode3-->>Client: ACK Block 3 (part 3) Received\n\n Client->>NameNode: Notify Block 3 Written\n note right of NameNode: NameNode updates block metadata with DataNode locations.\n\n Client->>NameNode: Request to Read File\n NameNode-->>Client: Respond with DataNodes and Block IDs\n note right of NameNode: NameNode provides block locations for requested file.\n\n Client->>DataNode1: Read Block 1\n DataNode1-->>Client: Send Block 1 Data\n Client->>DataNode2: Read Block 2\n DataNode2-->>Client: Send Block 2 Data\n Client->>DataNode3: Read Block 3\n DataNode3-->>Client: Send Block 3 Data\n\n\n数据块划分大文件被拆分成多个数据块存储在不同的 DataNode 上,以实现并行处理。\n副本管理NameNode 决定每个数据块的副本数量和存放位置,确保副本均匀分布,以提高系统的可靠性和读取效率。\n副本放置策略为了提高数据的可靠性和可用性HDFS 通常将一个副本放在本地机架,第二个副本放在同一机架的不同节点上,第三个副本放在不同机架的节点上。\n\nHDFS 的优缺点及应用场景\n优点\n\n高容错性通过数据块的多副本机制保障数据安全。当一个或多个 DataNode 发生故障时,数据仍然可以从其他副本中恢复。\n高吞吐量适合大规模数据的批处理。HDFS 优化了数据的流式传输,支持大文件的高吞吐量数据访问。\n可扩展性易于扩展集群规模。通过添加新的 DataNodeHDFS 可以方便地扩展存储容量和处理能力。\n\n缺点\n\n不适合低延迟的数据访问HDFS 设计初衷是为批处理优化,而不是低延迟的随机读写操作。\n小文件存储效率低HDFS 更适合大文件存储,小文件会带来元数据管理的负担和存储效率问题。\n\n应用场景\n\n大数据分析与处理如 MapReduce 任务。HDFS 被广泛应用于大数据分析平台,支持海量数据的并行处理。\n数据仓库和日志处理HDFS 常用于数据仓库的底层存储,以及日志数据的存储和处理。\n\nGoogle File System (GFS)\n设计目标\nGoogle File System (GFS) 是 Google 设计的一种可扩展的分布式文件系统旨在支持大规模数据处理应用。GFS 的设计目标包括高容错性、高性能和高扩展性。GFS 的诞生背景是为了应对 Google 在互联网搜索和数据分析中面临的大量数据存储和处理需求。GFS 被设计为能够处理海量数据集,并且能够在廉价硬件上运行,同时具备良好的容错性和高性能。\n历史发展\nGFS 的开发始于 2000 年,最初由 Sanjay Ghemawat、Howard Gobioff 和 Shun-Tak Leung 领导的团队设计。GFS 在 2003 年正式发布,并在 Google 内部得到广泛应用,支持 Google 搜索、广告和其他大规模数据处理任务。GFS 的设计和实现奠定了现代分布式文件系统的基础,影响了后来的许多文件系统,如 HDFS。\n架构与组件\n\nGFS 采用主从架构,由一个 Master 和多个 ChunkServer 组成:\n\nMaster管理文件系统元数据如命名空间、访问控制信息和文件块chunk的位置信息。Master 还负责协调系统中的各种操作,如数据块的分配、复制和负载均衡。\nChunkServer存储实际的文件块并执行读写请求。每个 ChunkServer 都存储多个文件块,并通过心跳机制向 Master 汇报其状态和所持有的数据块信息。\n\nGFS 的架构还包括一个客户端库,提供给应用程序使用,使其能够与 GFS 进行交互。客户端直接与 ChunkServer 通信进行数据读写操作,从而减轻 Master 的负担。\n数据分片与复制策略\nGFS 将文件划分为固定大小的块64MB每个块有一个唯一的全局 ID并被复制到多个 ChunkServer 上(默认 3 个副本),以提高数据的可靠性。\n\n数据块划分每个文件被拆分成固定大小的数据块这些数据块被分布存储在不同的 ChunkServer 上。\n副本管理每个数据块默认有三个副本分布在不同的 ChunkServer 上,以确保高可用性和容错性。\n副本放置策略GFS 通过副本放置策略确保数据在不同物理位置和机架之间分布,以提高系统的容错性和数据可用性。\n\nMaster 负责监控数据块的副本情况,并在副本丢失或损坏时自动创建新的副本。\nGFS 的优缺点及应用场景\n优点\n\n高容错性通过多副本和定期的完整性检查保障数据安全。GFS 能够在硬件故障频繁发生的环境中保持高可用性。\n高性能适合大文件的高吞吐量数据访问。GFS 优化了数据的流式传输,支持大规模数据处理任务。\n可扩展性通过增加 ChunkServer 节点GFS 可以轻松扩展存储容量和计算能力。\n\n缺点\n\n主节点是单点故障尽管 GFS 设计了多种机制来提高 Master 的可靠性,但它仍然是单点故障。如果 Master 失败,系统的可用性会受到影响。\n不适合小文件和低延迟数据访问GFS 更适合大文件存储和批处理任务,对小文件和低延迟访问的支持较差。\n\n应用场景\n\n大规模数据处理应用如 Google 的搜索和数据分析任务。GFS 能够处理 PB 级数据,并支持高效的数据读写和分析。\n存储和处理大量日志数据GFS 非常适合存储和处理来自多个数据源的大量日志文件,支持大规模日志分析和数据挖掘。\n\nGlusterFS\n概述与历史\nGlusterFS 是一个开源的分布式文件系统,旨在处理海量数据存储。它最初由 Gluster 公司开发,并已被 Red Hat 收购。GlusterFS 以其高扩展性和灵活性而著称,能够在无需改变应用程序代码的情况下,通过聚合多台存储服务器,实现高性能和高可用性的数据存储解决方案。\nGlusterFS 的设计理念是通过对等架构peer-to-peer architecture消除单点故障增强系统的容错性和扩展性。自 2005 年首次发布以来GlusterFS 已经经历了多次重大更新和改进,成为企业级存储解决方案的首选之一。\n架构与工作原理\n\nGlusterFS 采用无中心节点的对等架构每个节点同时充当客户端和服务器。它通过将多个存储服务器聚合成一个大的并行文件系统来实现扩展。GlusterFS 的主要组件包括:\n\nGluster 节点Gluster Node每个节点既是客户端又是服务器负责存储和提供文件数据。\n砖Brick每个节点上的存储单元通常是一个挂载点或目录。多个砖组成一个卷volume。\n卷Volume由多个砖组成是 GlusterFS 的基本存储单元。卷通过聚合不同的砖提供存储服务。\n\nGlusterFS 的工作原理包括:\n\n卷管理通过卷管理器Volume Manager来创建和配置卷。卷可以是分布式卷、复制卷或条带化卷根据应用需求选择合适的卷类型。\n分布式哈希表DHT用于分布式卷的文件分配。DHT 根据文件名计算哈希值,并将文件分配到合适的砖上。\n自我修复GlusterFS 具有内置的自我修复机制,当检测到数据不一致时,会自动进行数据同步和修复。\n\n存储卷的管理与配置\nGlusterFS 通过卷Volume管理存储。卷由一个或多个砖Brick组成每个砖对应一个存储服务器上的目录。常见的卷类型包括\n\n分布式卷Distributed Volume将文件分布在所有砖上适合需要高吞吐量和大容量的应用场景。\n复制卷Replicated Volume在多个砖之间复制文件提高数据的冗余性和可用性适合高可用性需求的应用。\n条带化卷Striped Volume将文件分块存储在多个砖上适合大文件的高性能读写需求。\n分布式复制卷Distributed Replicated Volume结合分布和复制特性既保证数据的高可用性又能扩展存储容量。\n\n配置卷的步骤包括\n\n创建卷使用 gluster volume create 命令创建所需类型的卷。\n启动卷使用 gluster volume start 命令启动创建的卷。\n挂载卷使用客户端将卷挂载到本地文件系统通常使用 FUSEFilesystem in Userspace挂载。\n\nGlusterFS 的优缺点及应用场景\n优点\n\n高可扩展性可以通过添加节点无缝扩展存储容量适应数据增长需求。\n高可用性通过数据复制和分布式架构实现数据的高可用性避免单点故障。\n灵活性支持多种卷类型能够根据不同应用需求进行灵活配置。\n\n缺点\n\n性能在高负载下可能下降在高负载情况下性能可能会受到影响需要优化配置。\n配置和管理相对复杂需要一定的专业知识和经验进行配置和管理特别是在大规模部署时。\n\n应用场景\n\n大规模数据存储和备份适合企业级大规模数据存储和备份解决方案能够提供高可用性和数据安全性。\n多媒体内容存储和分发适用于多媒体文件的存储和分发如视频、音频和图像文件能够支持高吞吐量和大文件存储需求。\n虚拟化环境和云计算支持虚拟机和容器存储适用于云计算和虚拟化环境中的数据存储解决方案。\n\nCephFS\n概述\nCephFS 是 Ceph 分布式存储系统的一部分,提供 POSIX 兼容的文件系统接口。CephFS 利用 Ceph 强大的分布式存储架构实现高性能和高可靠性的文件存储服务。Ceph 的设计目标是创建一个统一的、可扩展的存储平台支持对象存储、块存储和文件系统。CephFS 通过元数据服务器MDS和对象存储设备OSD协同工作实现了文件系统的高效管理和数据存储。\n\n历史发展\nCeph 的开发始于 2004 年,由 Sage Weil 在加州大学圣克鲁兹分校作为博士研究项目启动。2010 年Ceph 项目被 Inktank 公司商业化,随后于 2014 年被 Red Hat 收购。Ceph 的设计灵感来源于需要高扩展性和高性能的分布式存储解决方案,其独特的 CRUSH 算法和无中心架构使其在众多分布式存储系统中脱颖而出。\nCeph 集群的架构与组件\nCeph 集群由以下几部分组成:\n\nMonitor (MON)负责维护集群状态、管理元数据和认证服务。Monitor 节点保持集群的一致性和健康状态,管理集群成员和元数据信息。\nObject Storage Device (OSD):负责存储数据并处理数据的读写请求。每个 OSD 节点负责管理一部分数据存储,执行数据复制、恢复和再平衡等操作。\nMetadata Server (MDS)管理文件系统的元数据支持快速文件系统操作。MDS 维护文件系统的目录结构和文件元数据,处理客户端的文件操作请求。\n\n元数据服务器MDS和对象存储设备OSD\nCephFS 通过 MDS 管理文件系统元数据OSD 存储实际的数据。MDS 和 OSD 协同工作,实现高效的数据存取和元数据管理。\n\nMetadata Server (MDS)MDS 负责处理文件系统的元数据操作如目录查询、文件创建和删除。MDS 分担了文件系统操作的负载提高了整体系统的性能和响应速度。CephFS 支持多个 MDS 节点,以实现负载均衡和高可用性。\nObject Storage Device (OSD)OSD 节点负责存储数据块,并执行数据读写操作。每个文件被分解为多个数据块,并通过 Ceph 的 CRUSH 算法分布在多个 OSD 节点上。OSD 节点之间通过网络进行数据同步和恢复,确保数据的一致性和可靠性。\n\nCephFS 的优缺点及应用场景\n优点\n\n高性能支持高吞吐量和低延迟的数据访问。CephFS 利用高效的元数据管理和数据分布策略,实现快速的数据读写操作。\n高可扩展性通过添加更多的 OSD 和 MDS 节点实现水平扩展。CephFS 可以根据存储需求的增长灵活扩展,无需中断服务。\n高可靠性通过多副本和纠删码保障数据安全。CephFS 具备强大的数据保护机制,确保数据在硬件故障或网络故障时的安全性。\n\n缺点\n\n部署和配置相对复杂CephFS 的部署和配置需要较高的技术知识和经验,特别是在大规模集群环境中。\n需要较高的硬件资源支持CephFS 的性能和可靠性依赖于高质量的硬件资源包括高速网络、SSD 存储和充足的内存。\n\n应用场景\n\n高性能计算HPC和科学研究数据存储CephFS 适用于需要高吞吐量和大规模数据存储的高性能计算和科学研究领域。\n企业级数据存储和备份解决方案CephFS 提供可靠的企业级存储解决方案,适用于存储和备份大量企业数据,确保数据的高可用性和安全性。\n云计算和虚拟化环境CephFS 支持云计算和虚拟化环境中的数据存储需求,提供灵活的存储扩展能力和高效的数据访问性能。\n"},"Technology/DatabaseSystem/PostgreSQL/基本概念":{"title":"基本概念","links":[],"tags":["数据库系统/PostgreSQL","技术/数据库"],"content":"引言\ngraph TD;\n A[大型图书馆系统] --> B1[历史分馆]\n A --> B2[科学分馆]\n A --> B3[文学分馆]\n \n B1 --> C1[古代历史区]\n B1 --> C2[现代历史区]\n \n B2 --> C3[物理学区]\n B2 --> C4[化学区]\n \n B3 --> C5[古典文学区]\n B3 --> C6[现代文学区]\n \n C1 --> D1[书籍1]\n C1 --> D2[书籍2]\n \n C2 --> D3[书籍3]\n C2 --> D4[书籍4]\n \n C3 --> D5[书籍5]\n C3 --> D6[书籍6]\n \n C4 --> D7[书籍7]\n C4 --> D8[书籍8]\n \n C5 --> D9[书籍9]\n C5 --> D10[书籍10]\n \n C6 --> D11[书籍11]\n C6 --> D12[书籍12]\n \n style A fill:#f9d,stroke:#333,stroke-width:2px;\n style B1 fill:#fc9,stroke:#333,stroke-width:2px;\n style B2 fill:#fc9,stroke:#333,stroke-width:2px;\n style B3 fill:#fc9,stroke:#333,stroke-width:2px;\n style C1 fill:#9cf,stroke:#333,stroke-width:2px;\n style C2 fill:#9cf,stroke:#333,stroke-width:2px;\n style C3 fill:#9cf,stroke:#333,stroke-width:2px;\n style C4 fill:#9cf,stroke:#333,stroke-width:2px;\n style C5 fill:#9cf,stroke:#333,stroke-width:2px;\n style C6 fill:#9cf,stroke:#333,stroke-width:2px;\n style D1 fill:#c9f,stroke:#333,stroke-width:2px;\n style D2 fill:#c9f,stroke:#333,stroke-width:2px;\n style D3 fill:#c9f,stroke:#333,stroke-width:2px;\n style D4 fill:#c9f,stroke:#333,stroke-width:2px;\n style D5 fill:#c9f,stroke:#333,stroke-width:2px;\n style D6 fill:#c9f,stroke:#333,stroke-width:2px;\n style D7 fill:#c9f,stroke:#333,stroke-width:2px;\n style D8 fill:#c9f,stroke:#333,stroke-width:2px;\n style D9 fill:#c9f,stroke:#333,stroke-width:2px;\n style D10 fill:#c9f,stroke:#333,stroke-width:2px;\n style D11 fill:#c9f,stroke:#333,stroke-width:2px;\n style D12 fill:#c9f,stroke:#333,stroke-width:2px;\n\n**PostgreSQL 数据库服务可以被想象成一个大型的图书馆系统,它拥有一套完整的工具和服务来管理和查询存储在其中的数据,就像图书馆中的书籍。**这个系统不仅保证了数据的安全和完整性,还提供了高效的数据访问方式,就如同图书馆的管理员能够妥善管理所有的书籍和资料。\n**在这个图书馆中,我们可以找到多个分馆,这就是所谓的数据库集簇。**每个数据库集簇就像一个分馆,拥有自己的一套书籍和资源,但都受到同一套图书馆系统的管理和维护。在 PostgreSQL 的架构中,一个数据库集簇是由多个数据库组成的,它们共享同一套 PostgreSQL 服务实例和系统资源,形成一个协调一致的系统。\n**每个分馆可以被视为一个单一的实例,它是一个独立运行的 PostgreSQL 服务,管理着一个数据库集簇。**这个实例就像一个独立的图书馆分馆,拥有自己的资源和管理系统,可以为用户提供多样化的服务和资源。\n**分馆中的各个专题区域,就是数据库。**在 PostgreSQL 中,一个数据库就像一个专门的区域,它聚焦于一个特定的主题或应用,存储着一系列相关的数据表和信息。就如同图书馆中有历史、科学或文学等不同的主题区域,每个区域都提供了丰富和多元的资源,满足不同用户的需求和探索。\n通过这样的架构和组织方式PostgreSQL 成为了一个高度灵活、安全和高效的数据库管理系统,能够满足现代数据管理的多样化需求。\n组成\n执行文件\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件名描述clusterdb用于重新集群数据库表的工具。createdb用于创建新数据库的工具。createuser用于创建新数据库用户的工具。dropdb用于删除数据库的工具。dropuser用于删除数据库用户的工具。initdb用于初始化新数据库群集的工具。oid2name用于将 OID对象标识符转换为名称的工具。pg_amcheck用于验证索引的完整性和一致性的工具。pg_archivecleanup用于清理归档日志文件的工具通常与归档日志一起使用。pg_basebackup用于创建 PostgreSQL 数据库的基本备份的工具。pgbench用于进行性能基准测试的工具。pg_checksums用于管理 PostgreSQL 数据目录中的页校验和设置。pg_config用于检索 PostgreSQL 安装的配置信息的工具。pg_controldata用于检索 PostgreSQL 数据目录中的控制信息的工具。pg_ctl用于启动、停止和管理 PostgreSQL 服务器的工具。pg_dump用于将 PostgreSQL 数据库导出为 SQL 脚本文件的工具。pg_dumpall用于导出所有 PostgreSQL 数据库的工具。pg_isready用于检查 PostgreSQL 服务器是否准备好接受连接的工具。pg_receivewal用于接收和保存流复制的 WALWrite-Ahead Logging数据的工具。pg_recvlogical用于接收和保存逻辑复制的数据的工具。pg_resetwal用于重置 PostgreSQL 的 WAL 日志文件的工具。pg_restore用于从 SQL 脚本文件或自定义归档中恢复 PostgreSQL 数据库的工具。pg_rewind用于将一个 PostgreSQL 数据库群集回滚到以前的状态的工具。pg_test_fsync用于测试文件同步性能的工具。pg_test_timing用于测试系统定时性能的工具。pg_upgrade用于升级 PostgreSQL 数据库群集的工具。pg_verifybackup用于验证 PostgreSQL 备份的完整性的工具。pg_waldump用于解析和显示 WALWrite-Ahead Logging文件内容的工具。postgresPostgreSQL 服务器主进程的可执行文件。postmaster符号链接指向 PostgreSQL 服务器主进程的可执行文件。psql用于与 PostgreSQL 数据库进行交互的命令行客户端工具。reindexdb用于重新创建索引的工具。vacuumdb用于执行 VACUUM 操作以清理和优化 PostgreSQL 数据库的工具。vacuumlo用于管理 PostgreSQL 大对象的工具。\n数据目录\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件/目录名称作用base存储用户创建的数据库和表的数据文件global存储系统范围的共享表格定义和数据pg_commit_ts用于跟踪提交的事务时间戳pg_dynshmem动态共享内存目录用于在运行时分配共享内存段pg_hba.conf客户端身份验证规则配置文件用于控制客户端连接的权限pg_ident.conf用于标识客户端连接的规则配置文件pg_logical用于逻辑复制的相关文件和状态信息pg_multixact存储多事务共享锁的信息pg_notify用于实现 NOTIFY 和 LISTEN 功能的通知目录pg_replslot存储逻辑复制插槽信息的目录pg_serial存储序列的数据文件pg_snapshots存储快照信息pg_stat包含统计信息的目录用于监视数据库性能pg_stat_tmp存储临时统计信息的目录pg_subtrans存储子事务信息pg_tblspc存储表空间符号链接的目录每个数据库都有一个符号链接pg_twophase存储两阶段提交事务信息的目录PG_VERSION数据库簇的版本信息文件pg_wal存储 Write-Ahead Logging (WAL) 文件用于事务恢复和复制pg_xact存储事务状态文件postgresql.auto.conf自动生成的配置文件包含了数据库的自动化配置信息postgresql.conf数据库的主要配置文件包含了许多配置选项[postmaster.opts]包含启动 PostgreSQL 时使用的最后一组选项。[postmaster.pid]包含运行的 PostgreSQL 主进程的 PID进程 ID和其他控制信息用于防止多个服务器实例在同一数据目录上同时运行。\n设计架构\n架构图\ngraph LR;\n A[PostgreSQL 数据库服务] --> B[数据库集簇];\n B --> C[单一实例];\n C --> D1[数据库 A];\n C --> D2[数据库 B];\n C --> D3[数据库 C];\n D1 --> E1[数据表1];\n D1 --> E2[数据表2];\n D1 --> F1[视图];\n D1 --> F2[函数];\n D1 --> F3[触发器];\n E1 --> G1[列];\n E1 --> G2[索引];\n E1 --> G3[主键];\n E1 --> G4[外键];\n E1 --> G9[约束];\n E2 --> G5[列];\n E2 --> G6[索引];\n E2 --> G7[主键];\n E2 --> G8[外键];\n E2 --> G10[约束];\n A --> H1[事务和并发控制];\n A --> H2[备份和恢复];\n A --> H3[安全性和权限管理];\n A --> H4[复制和高可用性];\n A --> H5[扩展性和插件];\n A --> H6[连接管理];\n A --> H7[监听和通知];\n \n A --> I[进程管理器];\n A --> J[SQL 解析器];\n A --> K[查询优化器];\n A --> L[查询执行器];\n \n I --> M[后台进程];\n I --> N[自动清理进程];\n I --> O[后台工作进程];\n \n L --> P[存储管理器];\n P --> Q[缓冲区管理];\n P --> R[磁盘空间管理];\n P --> S[事务管理];\n P --> X[日志管理];\n \n Q --> T[共享缓冲区];\n \n S --> V[事务日志];\n S --> W[多版本并发控制 MVCC];\n S --> U[WAL 预写日志];\n \n H1 --> Y[锁管理];\n H2 --> Z1[物理备份];\n H2 --> Z2[逻辑备份];\n H3 --> Z3[角色和权限管理];\n H3 --> Z4[加密和认证];\n H4 --> Z6[主从复制];\n H4 --> Z7[同步复制];\n H5 --> Z8[新数据类型];\n H5 --> Z9[新函数];\n H6 --> Z10[客户端连接];\n H7 --> Z11[LISTEN];\n H7 --> Z12[NOTIFY];\n \n K --> Z5[统计信息];\n \n L --> Z13[顺序扫描];\n L --> Z14[索引扫描];\n L --> Z15[哈希连接];\n\nstyle A fill:#f9d,stroke:#333,stroke-width:2px; \nstyle B fill:#fc9,stroke:#333,stroke-width:2px; \nstyle C fill:#9cf,stroke:#333,stroke-width:2px; \nstyle D1 fill:#9fc,stroke:#333,stroke-width:2px; \nstyle D2 fill:#9fc,stroke:#333,stroke-width:2px;\nstyle D3 fill:#9fc,stroke:#333,stroke-width:2px;\nstyle E1 fill:#c9f,stroke:#333,stroke-width:2px; \nstyle E2 fill:#c9f,stroke:#333,stroke-width:2px; \nstyle F1 fill:#ccf,stroke:#333,stroke-width:2px; \nstyle F2 fill:#ccf,stroke:#333,stroke-width:2px; \nstyle F3 fill:#ccf,stroke:#333,stroke-width:2px; \nstyle G1 fill:#fcc,stroke:#333,stroke-width:2px; \nstyle G2 fill:#fcc,stroke:#333,stroke-width:2px; \nstyle G3 fill:#fcc,stroke:#333,stroke-width:2px; \nstyle G4 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G5 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G6 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G7 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G8 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G9 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle G10 fill:#fcc,stroke:#333,stroke-width:2px;\nstyle H1 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H2 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H3 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H4 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H5 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H6 fill:#ccc,stroke:#333,stroke-width:2px;\nstyle H7 fill:#ccc,stroke:#333,stroke-width:2px;\n\n\n进程结构\ngraph LR\n\n A[客户端] --> B[后端进程/Backend Process]\n B --> C[共享缓冲区/Shared Buffers]\n B --> D[事务日志/WAL Writer]\n B --> E[查询执行器/Query Executor]\n B --> L[日志管理器/Log Manager]\n B --> M[缓冲管理器/Buffer Manager]\n B --> N[锁管理器/Lock Manager]\n B --> O[进程间通信/IPC]\n \n C --> D[事务日志/WAL Writer]\n E --> C[共享缓冲区/Shared Buffers]\n D --> J[归档进程/Archiver]\n \n F[后台进程/Background Processes] --> C\n F --> D\n F --> G[统计信息收集器/Stats Collector]\n F --> H[自动清理进程/Autovacuum Worker]\n F --> I[检查点进程/Checkpointer]\n F --> J\n F --> K[后台工作进程/Background Worker]\n F --> P[WAL Receiver]\n \n I --> C[共享缓冲区/Shared Buffers]\n\n style A fill:#f9d,stroke:#333,stroke-width:2px;\n style B fill:#fc9,stroke:#333,stroke-width:2px;\n style C fill:#9cf,stroke:#333,stroke-width:2px;\n style D fill:#9cf,stroke:#333,stroke-width:2px;\n style E fill:#9cf,stroke:#333,stroke-width:2px;\n style F fill:#9fc,stroke:#333,stroke-width:2px;\n style G fill:#c9f,stroke:#333,stroke-width:2px;\n style H fill:#c9f,stroke:#333,stroke-width:2px;\n style I fill:#c9f,stroke:#333,stroke-width:2px;\n style J fill:#c9f,stroke:#333,stroke-width:2px;\n style K fill:#c9f,stroke:#333,stroke-width:2px;\n style L fill:#c9f,stroke:#333,stroke-width:2px;\n style M fill:#c9f,stroke:#333,stroke-width:2px;\n style N fill:#c9f,stroke:#333,stroke-width:2px;\n style O fill:#c9f,stroke:#333,stroke-width:2px;\n style P fill:#c9f,stroke:#333,stroke-width:2px;\n\n\n客户端: 这是用户与 PostgreSQL 数据库交互的入口点。客户端可以是任何支持 PostgreSQL 的应用程序或工具,如 psql、PgAdmin 等。\n后端进程/Backend Process: 当客户端发起连接请求时PostgreSQL 会为每个连接创建一个后端进程。这个进程负责处理客户端的所有请求,包括查询执行、事务管理等。\n共享缓冲区/Shared Buffers: 这是 PostgreSQL 的内存缓存,用于存储表数据、索引、系统目录等。后端进程和后台进程都可以访问这个缓冲区。\n事务日志/WAL Writer: WAL (Write-Ahead Logging) 是 PostgreSQL 的一种持久化机制。在数据被写入磁盘之前,所有的修改都会先被记录在 WAL 中。这确保了在系统崩溃的情况下数据的完整性和持久性。\n查询执行器/Query Executor: 负责解析、优化和执行 SQL 查询。\n后台进程/Background Processes: 这是一组进程,负责各种后台任务,如清理、统计信息收集、日志归档等。\n统计信息收集器/Stats Collector: 收集数据库的使用统计信息,如查询执行次数、表的访问频率等。\n自动清理进程/Autovacuum Worker: 负责清理旧的数据和空间回收。\n检查点进程/Checkpointer: 定期将共享缓冲区中的数据写入磁盘,并创建检查点。\n归档进程/Archiver: 负责将 WAL 日志文件归档到一个指定的位置,以便于备份和恢复。\n后台工作进程/Background Worker: 可以执行各种自定义的后台任务。\n日志管理器/Log Manager , 缓冲管理器/Buffer Manager , 锁管理器/Lock Manager , 进程间通信/IPC: 这些都是 PostgreSQL 内部的核心组件,负责日志记录、缓冲管理、锁定资源和进程间的通信。\nWAL Receiver: 在复制环境中WAL Receiver 负责从主服务器接收 WAL 记录。\n\n内存结构\ngraph LR\n\n A[PostgreSQL 内存结构]\n A --> B[共享缓冲区/Shared Buffers]\n A --> C[工作内存/Work Mem]\n A --> D[维护工作内存/Maintenance Work Mem]\n A --> E[WAL缓冲区/WAL Buffers]\n A --> F[本地缓冲区/Local Buffers]\n A --> G[消息层/Message Layer]\n A --> H[CLOG缓冲区/CLOG Buffers]\n A --> I[TOAST缓冲区/TOAST Buffers]\n\n style A fill:#f9d,stroke:#333,stroke-width:2px;\n style B fill:#9cf,stroke:#333,stroke-width:2px;\n style C fill:#9cf,stroke:#333,stroke-width:2px;\n style D fill:#9cf,stroke:#333,stroke-width:2px;\n style E fill:#9cf,stroke:#333,stroke-width:2px;\n style F fill:#9cf,stroke:#333,stroke-width:2px;\n style G fill:#9cf,stroke:#333,stroke-width:2px;\n style H fill:#9cf,stroke:#333,stroke-width:2px;\n style I fill:#9cf,stroke:#333,stroke-width:2px;\n\n\nPostgreSQL 内存结构: 这是 PostgreSQL 数据库的总体内存结构,它包含了多个专门的缓冲区和内存区域,用于不同的任务和操作。\n共享缓冲区/Shared Buffers: 这是 PostgreSQL 的主要缓存区,用于存储表数据、索引和系统目录。它是所有后端进程和后台进程共享的,用于减少磁盘 I/O。\n工作内存/Work Mem: 用于存储排序和哈希操作的中间结果。每个后端进程都有自己的工作内存。\n维护工作内存/Maintenance Work Mem: 用于存储维护任务(如 VACUUM、CREATE INDEX的中间结果。这通常比普通的工作内存大。\nWAL 缓冲区/WAL Buffers: 用于存储即将写入 WALWrite-Ahead Logging的日志记录。这确保了在数据被写入磁盘之前所有的修改都会先被记录在 WAL 中。\n本地缓冲区/Local Buffers: 用于存储临时表的数据。与共享缓冲区不同,本地缓冲区是每个后端进程私有的。\n消息层/Message Layer: 负责处理后端进程之间的消息传递,如锁通知和进程间通信。\nCLOG 缓冲区/CLOG Buffers: CLOG (Commit Log) 用于存储事务的提交状态。每个事务都有一个对应的 CLOG 记录,指示它是已提交、未提交还是中止。\nTOAST 缓冲区/TOAST Buffers: TOAST (The Oversized-Attribute Storage Technique) 是 PostgreSQL 用于存储大型数据的机制。当一个数据项太大而不能直接存储在常规的数据页中时它会被“toast”到一个特殊的 TOAST 表中并在原表中保留一个指针。TOAST 缓冲区用于缓存这些大型数据项。\n\n逻辑存储结构\ngraph LR\n\n A[数据库集群/Cluster]\n A --> B[全局系统目录/pg_global]\n A --> C[数据库/Database 1]\n A --> D[数据库/Database 2]\n A --> E[...]\n A --> F[数据库/Database N]\n A --> S[表空间/Tablespace 1]\n A --> T[表空间/Tablespace 2]\n A --> U[...]\n A --> V[表空间/Tablespace N]\n\n B --> G[全局表/Global Tables]\n B --> H[全局系统目录/Global System Catalogs]\n\n C --> M[系统目录/System Catalogs]\n C --> N[用户表/User Tables]\n C --> O[索引/Indexes]\n C --> P[视图/Views]\n C --> Q[序列/Sequences]\n C --> R[其他对象/Other Objects]\n C --> W[扩展/Extensions]\n\n\n物理存储结构\ngraph TD\n A[数据库 Database]\n B1[表空间 Tablespace 1]\n B2[表空间 Tablespace 2]\n C1[关系文件 Relation File 1]\n C2[关系文件 Relation File 2]\n D[数据文件 Data File]\n E[索引文件 Index File]\n F[事务日志 WAL]\n G[统计信息 Statistics]\n H[配置文件 Config Files]\n I[备份文件 Backup Files]\n\n A --> B1\n A --> B2\n B1 --> C1\n B2 --> C2\n C1 --> D\n C1 --> E\n C2 --> D\n C2 --> E\n A --> F\n A --> G\n A --> H\n A --> I\n\n堆表文件内部结构\ngraph TD\n A[页面 Page]\n B[页面头部 Page Header]\n C[项目指针数组 Item Pointer Array]\n D[元组1 Tuple 1]\n E[元组2 Tuple 2]\n F[元组N Tuple N]\n G[空闲空间图 Free Space Map]\n H[可见性图 Visibility Map]\n I[多版本并发控制 MVCC]\n J[仅堆元组 HOT]\n\n A --> B\n A --> C\n C --> D\n C --> E\n C --> F\n A --> G\n A --> H\n D --> I\n E --> I\n F --> I\n D --> J\n E --> J\n F --> J\n\n服务模式\ngraph TD\n A[PostgreSQL 服务模式]\n B[单用户模式]\n C[多用户模式]\n D[主-从复制模式]\n E[集群模式]\n F[主数据库]\n G[从数据库1]\n H[从数据库2]\n I[服务实例1]\n J[服务实例2]\n K[服务实例3]\n\n A --> B\n A --> C\n A --> D\n A --> E\n\n D --> F\n F --> G[同步数据]\n F --> H[同步数据]\n\n E --> I\n E --> J\n E --> K\n \n style A fill:#f9d,stroke:#333,stroke-width:2px\n style B fill:#eef,stroke:#333,stroke-width:2px\n style C fill:#eef,stroke:#333,stroke-width:2px\n style D fill:#eef,stroke:#333,stroke-width:2px\n style E fill:#eef,stroke:#333,stroke-width:2px\n style F fill:#ddd,stroke:#333,stroke-width:2px\n style G fill:#ddd,stroke:#333,stroke-width:2px\n style H fill:#ddd,stroke:#333,stroke-width:2px\n style I fill:#ddd,stroke:#333,stroke-width:2px\n style J fill:#ddd,stroke:#333,stroke-width:2px\n style K fill:#ddd,stroke:#333,stroke-width:2px\n\n单用户模式\n在单用户模式下PostgreSQL 服务只允许一个用户(或一个应用)同时访问和操作数据库。这就像一个图书馆在特定时间只对一名读者开放,以便他/她可以独自浏览和使用图书馆的所有资源,而不会受到其他人的干扰。这种模式**通常用于数据库维护和故障排除。**在这种模式下,由于没有并发访问,管理员可以更容易地进行数据库的维护工作,如备份、恢复、重建索引等。\n多用户模式\n多用户模式是 PostgreSQL 的常规运行模式,它允许多个用户(或多个应用)同时访问和操作数据库。这就像一个图书馆在正常营业时间对所有读者开放,每个人都可以自由地浏览书籍和使用资源,同时图书馆的管理员会确保所有的操作都是有序和高效的。在这种模式下,数据库服务器必须处理并发访问,确保数据的完整性和一致性,并提供事务管理功能。\n主 - 从复制模式\n在主 - 从复制模式下,有一个主数据库(主图书馆)和一个或多个从数据库(分支图书馆)。**主数据库负责处理所有的写操作(如添加新书籍),而从数据库则是主数据库的只读副本,用于处理读操作(如查询书籍)。**从数据库会定期从主数据库同步数据,以保证数据的一致性。这样可以提高系统的读取性能和可用性。此外,这种模式还为数据备份和灾难恢复提供了额外的保障,因为从数据库可以作为备份数据源。\n集群模式\n**在集群模式下,多个 PostgreSQL 服务实例协同工作,共同提供数据库服务。**这就像一个图书馆网络,其中每个图书馆都可以提供完整的服务,并通过协同工作来提供更高效和更可靠的服务。这种模式可以提高系统的性能和可用性,同时也提供了更高的数据安全性。集群中的每个实例都可以处理读写请求,而数据的分布和复制是由集群管理软件自动处理的。这种模式通常用于大型、高并发的应用场景,需要高可用性和故障切换能力。"},"Technology/DatabaseSystem/PostgreSQL/安装配置":{"title":"安装配置","links":[],"tags":["数据库系统/PostgreSQL","技术/数据库"],"content":"序言\n对于初学者和有经验的开发者来说正确地安装和配置 PostgreSQL 是至关重要的。一个恰当的配置不仅可以确保数据库的稳定运行,还可以充分发挥其性能,满足复杂的业务需求。然而,由于 PostgreSQL 的功能丰富和配置项繁多,很多人在安装和配置过程中可能会遇到困惑和挑战。\nPostgreSQL 提供了多种安装方式,其中源码安装和编译安装是最为基础和原始的方法。这两种方法虽然相对复杂,但为用户提供了极大的灵活性,允许他们根据自己的需求进行定制和优化。\n依赖\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n依赖版本用途状态备注GNU make3.81 或更高构建 PostgreSQL✅必需; 其他版本或其他 make 程序不可用ISO/ANSI C compilerC99 兼容编译 PostgreSQL✅必需; 推荐使用 GCC 的最新版本tar无特定版本解压源代码分发包✅必需; 需要配合 gzip 或 bzip2 使用GNU Readline library无特定版本提高 PostgreSQL 命令行 SQL 解释器的用户体验✅必需; 可以选择不使用或使用 libedit 库作为替代zlib无特定版本支持 pg_dump 和 pg_restore 中的压缩存档功能✅必需; 可以选择不使用Perl5.8.3 或更高构建 PL/Perl 服务器编程语言🟢可选; 需要 libperl 共享库和头文件Python3.2 或更高构建 PL/Python 服务器编程语言🟢可选; 需要 libpython 共享库和头文件Tcl8.4 或更高构建 PL/Tcl 程序语言🟢可选; 需要 Tcl 安装OpenSSL1.0.1 或更高支持加密的客户端连接和随机数生成🟢可选; 用于支持加密的客户端连接和随机数生成Gettext API无特定版本实现 Native Language Support (NLS)🟢可选; 用于显示程序的非英语消息Kerberos无特定版本支持 Kerberos 认证🟢可选; 用于支持 Kerberos 认证OpenLDAP无特定版本支持 OpenLDAP 认证🟢可选; 用于支持 OpenLDAP 认证PAM无特定版本支持 PAM 认证🟢可选; 用于支持 PAM 认证LZ4无特定版本支持 LZ4 数据压缩🟢可选; 用于支持 LZ4 数据压缩Zstandard1.4.0 或更高支持 Zstandard 数据压缩🟢可选; 用于支持 Zstandard 数据压缩\n\n✅ 表示必需\n🟢 表示可选\n\n基本依赖\n# YUM 更新软件仓库 && 安装必需的依赖\nsudo yum update -y && sudo yum install -y make gcc tar gzip bzip2 readline readline-devel zlib zlib-devel\n \n# APT 更新软件仓库 && 安装必需的依赖\nsudo apt update && sudo apt install -y make gcc tar gzip bzip2 libreadline-dev zlib1g-dev\n拓展依赖\n# YUM 更新软件仓库 && 安装可选的依赖\nsudo yum update -y && sudo yum install -y perl perl-devel python3 python3-devel tcl tcl-devel openssl openssl-devel gettext krb5 krb5-devel openldap openldap-devel pam pam-devel lz4 lz4-devel zstd zstd-devel\n \n# APT 更新软件仓库 && 安装可选的依赖\nsudo apt update && sudo apt install -y perl libperl-dev python3 python3-dev tcl tcl-dev libssl-dev gettext krb5-user libkrb5-dev libldap2-dev libpam0g-dev liblz4-dev libzstd-dev\n依赖检查\n#!/bin/bash\n \n# 检查包管理器\n# 可自定义依赖检查项目\nif command -v yum &> /dev/null; then\n PACKAGE_MANAGER="yum"\n REQUIRED_DEPENDENCIES=("make" "gcc" "tar" "gzip" "bzip2" "readline" "readline-devel" "zlib" "zlib-devel")\n OPTIONAL_DEPENDENCIES=("perl" "perl-devel" "python3" "python3-devel" "tcl" "tcl-devel" "openssl" "openssl-devel" "gettext" "krb5" "krb5-devel" "openldap" "openldap-devel" "pam" "pam-devel" "lz4" "lz4-devel" "zstd" "zstd-devel")\nelif command -v apt-get &> /dev/null; then\n PACKAGE_MANAGER="apt-get"\n REQUIRED_DEPENDENCIES=("make" "gcc" "tar" "gzip" "bzip2" "libreadline-dev" "zlib1g-dev")\n OPTIONAL_DEPENDENCIES=("perl" "libperl-dev" "python3" "python3-dev" "tcl" "tcl-dev" "libssl-dev" "gettext" "krb5-user" "libkrb5-dev" "libldap2-dev" "libpam0g-dev" "liblz4-dev" "libzstd-dev")\nelse\n echo "❌ 不支持的包管理器。"\n exit 1\nfi\n \n# 定义一个函数来检查依赖是否安装,并显示版本信息\ncheck_dependency() {\n local package_name=$1\n \n if [ -z "$package_name" ]; then\n echo "错误:未提供依赖项名称。"\n exit 1\n fi\n \n if [ "$PACKAGE_MANAGER" == "yum" ]; then\n if rpm -q $package_name &> /dev/null; then\n version=$(rpm -q $package_name)\n printf " ✅ %-20s 版本: %s\\n" $package_name "$version"\n else\n printf " ❌ %-20s 未安装\\n" $package_name\n fi\n elif [ "$PACKAGE_MANAGER" == "apt-get" ]; then\n if dpkg -s $package_name &> /dev/null; then\n version=$(dpkg -s $package_name | grep Version | cut -d' ' -f2)\n if [ -z "$version" ]; then\n version="未知"\n fi\n printf " ✅ %-20s 版本: %s\\n" $package_name "$version"\n else\n printf " ❌ %-20s 未安装\\n" $package_name\n fi\n fi\n}\n \n# 定义一个函数来检查依赖项数组\ncheck_dependencies() {\n local dependencies=("$@")\n for dependency in "${dependencies[@]}"; do\n check_dependency "$dependency"\n done\n}\n \n# 检查必需的依赖\necho "Postgres 依赖检查"\necho "=> 必需的依赖:"\ncheck_dependencies "${REQUIRED_DEPENDENCIES[@]}"\n \n# 检查可选的依赖\necho ""\necho "=> 可选的依赖:"\ncheck_dependencies "${OPTIONAL_DEPENDENCIES[@]}"\n \n# 输出检查完成信息\necho ""\necho "=> 依赖检查完成!"\n安装\n源码安装\n1. 准备工作\n# 创建用户\nsudo adduser postgres\nsudo passwd postgres\n \n# 创建目录\nsudo mkdir -p /opt/postgresql/{data,archive,scripts,backup,pg16,source,logs,config,temp,extensions,upgrade_scripts}\n \n# 配置目录权限,后续默认以 postgres 用户操作\nsudo chown -R postgres:postgres /opt/postgresql\nsudo chmod -R 775 /opt/postgresql\npostgresql 目录下文件夹其对应的用途。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n目录用途/data存储 PostgreSQL 数据/archive存储归档日志文件/scripts存储 PostgreSQL 脚本/backup存储数据库备份/pgsql软连接到 /pg16/pg16PostgreSQL 16 版本/source存储源代码或配置文件/logs存储 PostgreSQL 日志/config存储 PostgreSQL 配置/temp存储临时文件/extensions存储 PostgreSQL 扩展/upgrade_scripts存储升级脚本\n2. 下载源码\nPostgreSQL 源码可以在官方提供的 FTP 渠道 下载。\n\n# 切换用户\nsu - postgres\n \n# 下载 PG16 \npostgres@debian:/opt/postgresql/source$ wget ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz\n \n# 解压 PG16\npostgres@debian:/opt/postgresql/source$ tar -zxvf postgresql-16.0.tar.gz\n3. 配置源码\n首先你需要配置源代码树以适应你的系统并选择你想要的选项。这是通过运行 configure 脚本完成的。你可以使用以下命令进行默认安装:\n# 安装 /opt/postgresql/pg16/ 路径\npostgres@debian:/opt/postgresql/source/postgresql-16.0$ ./configure --prefix=/opt/postgresql/pg16/\n# 默认安装\n./configure\n \n# 指定多个选项\n./configure --prefix=/usr/local/pgsql --bindir=/usr/local/pgsql/bin --datadir=/usr/local/pgsql/data --libdir=/usr/local/pgsql/lib\n \n# 禁用某些功能\n./configure --without-readline --without-zlib\n \n# 启用调试和指定编译器\n./configure --enable-debug --with-pgport=5432 CC=gcc CFLAGS='-O2 -g'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--prefix=<目录>指定安装目录的前缀,即 PostgreSQL 将被安装到的基本目录。--bindir=<目录>指定可执行文件的目录,例如 pg_ctl 和 psql。--sbindir=<目录>指定系统管理员可执行文件的目录,例如 pg_ctl 和 pg_config。--datadir=<目录>指定数据文件的根目录,例如数据表空间。--libdir=<目录>指定库文件的目录,例如共享库文件。--sysconfdir=<目录>指定配置文件的目录。--docdir=<目录>指定文档文件的目录。--includedir=<目录>指定包含头文件的目录,用于开发 PostgreSQL 扩展。--with-openssl启用 OpenSSL 支持,用于加密通信。--with-zlib启用 Zlib 支持,用于数据压缩。--with-libxml启用 Libxml2 支持,用于 XML 数据类型。--with-python启用 Python 支持,用于编写存储过程和触发器。--with-perl启用 Perl 支持,用于编写存储过程和触发器。--with-tcl启用 Tcl 支持,用于编写存储过程和触发器。--with-pam启用 PAM (Pluggable Authentication Modules) 支持。--with-ldap启用 LDAP 支持,用于身份验证和用户管理。--with-krb5启用 Kerberos 支持,用于身份验证。--with-system-tzdata使用操作系统提供的时区信息。--enable-debug启用调试支持构建时包括调试信息。--disable-ipv6禁用 IPv6 支持。\n4. 构建二进制\n可以输入以下任一命令开始构建可以使用 -j 选项指定线程数加快速度。\nmake\n \n# 多线程构建\nmake -j 8 \n如果你想构建所有可以构建的内容包括文档HTML 和 man 页面和附加模块contrib则可以输入\nmake world\n或者如果你想构建所有可以构建的内容包括附加模块contrib但不包括文档可以输入\nmake world-bin\n5. 测试软件\n如果你想在安装之前测试新构建的服务器你可以在此时运行回归测试。这是一个测试套件用于验证 PostgreSQL 是否按照开发人员预期的方式在你的机器上运行。可以使用以下命令进行测试:\nmake check\n6. 安装\n要安装 PostgreSQL可以输入\nmake install\n此步骤将把文件安装到第一步中指定的目录中。**确保你有适当的权限写入该区域。**或者,你可以提前创建目标目录并安排授予适当的权限。\n如果你构建了上面的 world可以输入\nmake install-world\n这也会安装文档。如果你在上面构建了不包含文档的 world可以输入\nmake install-world-bin\n7. 配置软连\n设置 postgres 软链接,方便系统后续升级。\nln -s /opt/postgres/pg16 /opt/postgresql/pgsql\n8. 卸载和清理\n如果要撤销安装可以使用命令 make uninstall。但是这不会删除任何创建的目录。\n安装后你可以通过从源代码树中删除构建文件来释放磁盘空间命令是 make clean。这将保留 configure 程序创建的文件,以便你稍后可以使用 make 重新构建所有内容。要将源代码树重置为分发时的状态,请使用 make distclean。\n二进制安装\n1. 下载\n在开始二进制安装之前你需要首先下载适用于你的操作系统的 PostgreSQL 二进制包。你可以从 PostgreSQL 官方网站或者你的操作系统的软件库中获取它。\n# 通过 wget 命令下载\nwget download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm\n \n# 通过 curl 命令下载\ncurl -O download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm\n2. 安装\n安装二进制包通常比源码安装更快更简单。根据你的操作系统和包管理器这里介绍几种常用的安装方法\n# 在 Red Hat/CentOS 中安装\nsudo rpm -ivh pgdg-redhat-repo-latest.noarch.rpm\nsudo yum install postgresql-server\n \n# 在 Debian/Ubuntu 中安装\nsudo apt-get update\nsudo apt-get install postgresql\n \n# 在 Debian/Ubuntu 中使用自定义选项进行安装\nsudo apt install postgresql --prefix=/usr/local/pgsql --datadir=/usr/local/pgsql/data\n \n# 在 Red Hat/CentOS 中使用自定义选项进行安装\nsudo yum install postgresql-server --prefix=/usr/local/pgsql --datadir=/usr/local/pgsql/data\n安装过程中你可以使用以下选项来自定义安装\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--prefix=PREFIX定义安装的根目录所有文件和目录都将放在这个目录下--exec-prefix=EPREFIX定义架构相关文件的安装目录通常与 --prefix 相同--bindir=DIR定义用户可执行文件如 psql的安装目录--datadir=DIR定义只读架构独立数据的安装目录--libdir=DIR定义库文件的安装目录--sysconfdir=DIR定义系统级配置文件的安装目录--sharedstatedir=DIR定义可修改的单主机数据的安装目录--localstatedir=DIR定义可修改的多主机数据的安装目录--libexecdir=DIR定义可执行程序和其他程序运行的安装目录--includedir=DIR定义 C 头文件的安装目录--mandir=DIR定义 man 文档的安装目录--docdir=DIR定义文档的根目录\n3. 验证\n安装完成后验证 PostgreSQL 是否已成功安装和配置。可以通过以下命令来验证安装:\n# 检查 PostgreSQL 服务状态\nsudo systemctl status postgresql\n \n# 使用 psql 命令行工具连接到 PostgreSQL 服务器\npsql -U postgres\n \n# 显示 PostgreSQL 服务器的版本信息\npsql -U postgres -c 'SELECT version();'\n二进制安装成功后可以直接使用默认不需要后续的配置。\n设置\n1. 共享库设置 (Shared Libraries)\n在某些系统中你需要告诉系统如何找到新安装的共享库。这不包括 FreeBSD, HP-UX, Linux, NetBSD, OpenBSD 和 Solaris 等系统。设置共享库搜索路径的方法因平台而异,但最常用的方法是设置环境变量 LD_LIBRARY_PATH。以下是如何在 Bourne shell (如 sh, ksh, bash, zsh) 中设置:\nLD_LIBRARY_PATH=/usr/local/pgsql/lib\nexport LD_LIBRARY_PATH\n2. 环境变量设置 (Environment Variables)\n如果你将 PostgreSQL 安装到 /usr/local/pgsql 或其他默认情况下不搜索程序的位置,你应该将 /usr/local/pgsql/bin或你在第一步中设置的 --bindir 选项)添加到你的 PATH 中。这样可以使 PostgreSQL 的使用更加方便。以下是如何在 Bourne shell 中设置:\nPATH=/usr/local/pgsql/bin:$PATH\nexport PATH\n为了让你的系统找到 man 文档,你需要将以下行添加到一个 shell 启动文件中,除非你安装到了默认搜索的位置:\nMANPATH=/usr/local/pgsql/share/man:$MANPATH\nexport MANPATH\n环境变量 PGHOST 和 PGPORT 指定了数据库服务器的主机和端口,覆盖了编译时的默认设置。如果你打算远程运行客户端应用程序,那么每个计划使用数据库的用户都应设置 PGHOST。这不是必需的但可以通过大多数客户端程序的命令行选项来传递设置。\n3. 配置脚本示例\n#!/bin/bash\n \n# 将配置写入 ~/.bash_profile 文件\ncat >> ~/.bash_profile <<EOF\nexport PGDATA=/opt/postgres/data\nexport PGHOME=/opt/postgres/pgsql\nexport LD_LIBRARY_PATH=$pg_home/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH\nexport PATH=$pg_home/bin:$PATH:.\nexport MANPATH=$pg_home/share/man:$MANPATH\nexport PGHOST=$PGDATA\nexport PGUSER=postgres\nexport PGDATABASE=postgres\nEOF\n \n# 重新加载 ~/.bash_profile\nsource ~/.bash_profile\n使用\nPsql 命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n内置命令作用描述\\q退出 psql\\l 或 \\list列出所有数据库\\c [数据库名]连接到新数据库\\dt列出当前数据库中的所有表\\d [表名]显示表的结构(列、数据类型、权限等)\\du列出所有 PostgreSQL 用户角色\\e打开文本编辑器\\a切换输出格式对齐或非对齐\\x切换扩展显示模式\\timing显示 SQL 查询的执行时间\\i [文件名]执行文件中的 SQL 命令\\o [文件名]将查询结果输出到文件\\s显示命令历史\\?显示所有 psql 命令的帮助信息\\h [SQL命令]显示 SQL 命令的语法和选项\\set列出所有 psql 变量及其值\\unset删除一个或多个 psql 变量\\g 或 ;执行查询\\qecho [文本]在输出中显示文本(通常用于脚本中添加注释或空行)\\conninfo显示当前数据库连接的详细信息\n1. 初始化数据库目录\n首先需要使用 initdb 命令来初始化数据库目录。该命令会创建必要的目录结构和系统目录,以便 PostgreSQL 数据库能够运行。\n# -D 选项指定数据库目录的路径\ninitdb -D /path/to/data/directory\n2. 配置文件\npostgresql.conf\nPostgreSQL 的主配置文件,可以在这里设置各种参数,如内存使用、连接数等。下面是常用配置:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项作用示例配置连接设置listen_addresses定义服务器监听的地址listen_addresses = '*'port定义服务器监听的端口port = 5432max_connections最大并发连接数max_connections = 100superuser_reserved_connections为超级用户保留的连接数superuser_reserved_connections = 3unix_socket_directoriesUnix 域套接字的目录unix_socket_directories = '/var/run/postgresql'认证和安全ssl是否启用 SSLssl = onssl_cert_fileSSL 证书文件的位置ssl_cert_file = '/path/to/server.crt'ssl_key_fileSSL 私钥文件的位置ssl_key_file = '/path/to/server.key'password_encryption密码加密方式password_encryption = scram-sha-256hba_filepg_hba.conf 文件的位置hba_file = '/path/to/pg_hba.conf'内存使用shared_buffers用于缓存的内存大小shared_buffers = 128MBwork_mem查询操作可以使用的内存量work_mem = 4MBmaintenance_work_mem维护操作如 VACUUM可以使用的内存量maintenance_work_mem = 64MBeffective_cache_size估计的操作系统缓存大小effective_cache_size = 512MB查询调优seq_page_cost顺序磁盘页的成本seq_page_cost = 1.0random_page_cost随机磁盘页的成本random_page_cost = 4.0cpu_tuple_cost处理每个元组的 CPU 成本cpu_tuple_cost = 0.01cpu_index_tuple_cost处理每个索引元组的 CPU 成本cpu_index_tuple_cost = 0.005cpu_operator_cost执行操作符的 CPU 成本cpu_operator_cost = 0.0025日志记录logging_collector是否启用日志收集logging_collector = onlog_directory日志文件的存储目录log_directory = 'pg_log'log_filename日志文件的命名方式log_filename = 'postgresql.log'log_statement记录的 SQL 语句类型(例如所有语句或只有 DDLlog_statement = 'all'log_duration是否记录语句的执行时间log_duration = onlog_min_duration_statement记录执行时间超过指定毫秒数的语句log_min_duration_statement = 500运行时统计track_activities是否跟踪服务器进程的活动track_activities = ontrack_counts是否跟踪访问统计信息track_counts = ontrack_io_timing是否跟踪 I/O 计时信息track_io_timing = onstats_temp_directory临时统计数据的目录stats_temp_directory = 'pg_stat_tmp'锁定deadlock_timeout死锁检测的超时时间deadlock_timeout = 1smax_locks_per_transaction每个事务可以持有的最大锁数max_locks_per_transaction = 64自动 VACUUMautovacuum是否启用自动 VACUUMautovacuum = onautovacuum_vacuum_scale_factor触发自动 VACUUM 的脏数据比例autovacuum_vacuum_scale_factor = 0.2autovacuum_analyze_scale_factor触发自动 ANALYZE 的脏数据比例autovacuum_analyze_scale_factor = 0.1autovacuum_vacuum_cost_limit自动 VACUUM 操作的成本限制autovacuum_vacuum_cost_limit = 200客户端连接默认值DateStyle默认的日期格式DateStyle = 'ISO, MDY'TimeZone默认的时区TimeZone = 'UTC'lc_messages消息的本地化设置lc_messages = 'en_US.UTF-8'lc_monetary货币格式的本地化设置lc_monetary = 'en_US.UTF-8'lc_numeric数字格式的本地化设置lc_numeric = 'en_US.UTF-8'lc_time时间和日期格式的本地化设置lc_time = 'en_US.UTF-8'LOCALElc_collate字符串排序的本地化设置lc_collate = 'en_US.UTF-8'lc_ctype字符分类的本地化设置lc_ctype = 'en_US.UTF-8'\npg_hba.conf\npg_hba.conf 文件用于控制哪些客户端可以连接到数据库,以及它们可以使用的认证方法。以下是 pg_hba.conf 中的常见配置项、作用和示例配置:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型数据库用户地址认证方法说明localallalltrust本地所有用户对所有数据库的连接不需要密码hostallall127.0.0.1/32md5从本地通过 TCP/IP 连接的所有用户需要密码hostmydbmyuser192.168.1.0/24md5从指定网络连接到指定数据库的指定用户需要密码hostsslallall0.0.0.0/0md5从任何地址通过 SSL 连接的所有用户需要密码hostnosslallall0.0.0.0/0reject拒绝非 SSL 连接\n\n类型连接类型。常见的有 localUnix 域套接字、hostTCP/IP 套接字、hostssl仅限 SSL 的 TCP/IP 连接)和 hostnossl不使用 SSL 的 TCP/IP 连接)。\n数据库适用的数据库名。all 表示所有数据库。\n用户适用的用户名。all 表示所有用户。\n地址客户端的 IP 地址。对于 local 类型,这一列是空的。对于 host 类型,这是一个 CIDR 地址或一个 IP 地址和一个掩码。\n认证方法常见的有 trust不需要密码、reject拒绝连接、md5密码认证、password明文密码等。\n\npg_hba.conf 文件的每一行都是一个连接规则PostgreSQL 会按照文件中的顺序评估这些规则,直到找到一个匹配的规则为止。因此,顺序很重要,特别是当有多个规则可能匹配同一个连接时。\n3. 启动数据库\n一旦数据库目录被成功初始化可以使用 pg_ctl 命令来启动 PostgreSQL 数据库。\n# -D 选项指定了数据库目录的路径。\npg_ctl start -D /path/to/data/directory\n# 或者\npostgres -D /path/to/data/directory\n4. 验证数据库是否正在运行\n为了验证 PostgreSQL 数据库是否正在运行,可以使用 psql 命令连接到数据库并执行一个简单的查询,例如:\npsql -U postgres -c "SELECT version();"\n5. 配置 Systemctl 服务\n\n关闭 postgresql 数据库。\n创建一个 Systemd 服务文件,通常位于 /etc/systemd/system/postgresql.service。\n添加以下内容需要结合配置脚本示例。\n\n[Unit]\nDescription=PostgreSQL database server\nDocumentation=man:postgres(1)\nAfter=network.target\n \n[Service]\nType=forking\nUser=postgres\nGroup=postgres\nEnvironment=PGPORT=5432\nEnvironment=PGDATA=/opt/postgresql/data\nOOMScoreAdjust=-1000\nExecStart=/opt/postgresql/pgsql/bin/pg_ctl start -D ${PGDATA} -s -o "-p ${PGPORT}" -w -t 300\nExecStop=/opt/postgresql/pgsql/bin/pg_ctl stop -D ${PGDATA} -s -m fast\nExecReload=/opt/postgresql/pgsql//bin/pg_ctl reload -D ${PGDATA} -s\nKillMode=mixed\nKillSignal=SIGINT\nTimeoutSec=30\n \n[Install]\nWantedBy=multi-user.target\n\n重新加载 Systemd 配置sudo systemctl daemon-reload\n启动服务sudo systemctl start postgresql\n设置开机启动sudo systemctl enable postgresql\n\n6. 创建用户和数据库\n# 创建一个新用户\nsudo -u postgres createuser -P <username>\n \n# 创建一个新数据库\nsudo -u postgres createdb -O <username> <dbname>\n \n# 为用户分配特定权限\nsudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE <dbname> TO <username>;"\n7. 用户和角色管理\n# 创建角色\nsudo -u postgres createuser <role_name>\n \n# 为角色分配权限\nsudo -u postgres psql -c "GRANT <permission> ON <object> TO <role_name>;"\n \n# 删除角色\nsudo -u postgres dropuser <role_name>\n \n# 设置密码策略和验证\nsudo -u postgres psql -c "ALTER USER <username> WITH PASSWORD '<password>';"\n8. 备份和恢复\n备份和恢复是数据库管理的关键部分确保数据的安全和完整性。PostgreSQL 提供了 pg_dump 和 pg_restore 工具来帮助管理员进行这些操作。\npg_dump 备份\npg_dump 是用于备份 PostgreSQL 数据库的工具。它可以生成包含数据库内容的 SQL 脚本文件或其他格式,如 tar 和 custom。使用以下命令进行全量备份\npg_dump -U <username> -h <host> -p <port> -F c -b <dbname> > backup.dump\n额外的选项包括 --data-only 和 --schema-only这些选项可以让用户选择备份数据或者仅备份架构。\n使用 pg_restore 来验证备份文件的完整性。即使你不打算立即恢复,也应该定期验证备份。\npg_restore --list backup.dump\npg_restore 恢复\npg_restore 是用于恢复由 pg_dump 创建的备份的工具。使用以下命令进行恢复:\npg_restore -U <username> -h <host> -p <port> -d <dbname> backup.dump\n注意\n\n在恢复之前确保目标数据库是空的或你已经备份了任何重要的数据。\n如果备份是在不同版本的 PostgreSQL 上创建的,可能会遇到兼容性问题。在这种情况下,确保先测试恢复过程。\n如果你正在恢复到一个活动的数据库你可能需要在恢复前停止数据库服务。\n\n更新\n小版本升级Minor Version Upgrade\n**小版本升级通常涉及到安全修复和错误修复,而不会改变数据库的内部格式。**这些升级通常比较简单,并且可以通过替换二进制文件来完成。如下是 PostgreSQL 15.3 升级到 15.4 的小版本升级示例:\n步骤:\n\n\n备份数据:\n在进行任何升级之前始终确保备份您的数据库。\npg_dumpall > backup.sql\n\n\n停止 PostgreSQL 服务:\n使用 pg_ctl stop 或您的系统的服务管理工具停止 PostgreSQL 服务。\npg_ctl stop\n\n\n替换二进制文件:\n下载并安装 PostgreSQL 15.4 的二进制文件。\n\n\n重启 PostgreSQL 服务:\n使用 pg_ctl start 或您的系统的服务管理工具重新启动 PostgreSQL 服务。\npg_ctl start\n\n\n检查日志和运行测试:\n检查 /usr/local/pgsql/data/pg_log/ 中的日志文件以确保没有错误,并运行任何必要的测试以验证系统的功能。\n\n\n跨版本升级Major Version Upgrade\n跨版本升级涉及到从一个主版本升级到另一个主版本例如从 PostgreSQL 15 升级到 PostgreSQL 16。**这些升级通常会涉及到内部格式的变化,因此需要更多的注意和准备。**如下是 PostgreSQL 15.4 升级到 16.0 的大版本升级示例:\n步骤:\n\n\n备份数据:\n在进行任何升级之前始终确保备份您的数据库。\npg_dumpall > backup.sql\n\n\n检查兼容性:\n检查新版本的 PostgreSQL 文档以确保您的应用程序和数据库架构与新版本兼容。\n\n\n安装新版本的 PostgreSQL:\n在同一系统上安装新版本的 PostgreSQL但不要覆盖旧版本。\n\n\n使用 pg_upgrade 或逻辑备份和恢复:\n使用 pg_upgrade 工具快速升级。\npg_upgrade \\\n--old-datadir "/usr/local/pgsql/15.4/data" \\\n--new-datadir "/usr/local/pgsql/16.0/data" \\\n--old-bindir "/usr/local/pgsql/15.4/bin" \\\n--new-bindir "/usr/local/pgsql/16.0/bin"\n\n\n测试新集群:\n在新集群上运行测试以确保它按预期工作。\n\n\n切换到新集群:\n一旦满意可以切换到新集群并更新任何连接字符串和配置。\n\n\n监控性能和错误:\n在升级后监控系统性能和错误以确保一切正常。\n\n\n可选删除旧集群:\n确保新集群运行正常后可以选择删除旧集群以释放空间。\n\n"},"Technology/DatabaseSystem/PostgreSQL/简介":{"title":"简介","links":[],"tags":["数据库系统/PostgreSQL","技术/数据库"],"content":"序言\nPostgreSQL起源于加利福尼亚大学伯克利分校的 POSTGRES 项目,始于 1986 年。该项目由计算机科学教授 Michael Stonebraker 领导,他在数据库领域的贡献也促成了其他关系数据库系统的诞生。\nMichael Stonebraker 教授是 PostgreSQL 的创始人。他的愿景是设计一个既灵活又可扩展的数据库系统能够支持多种数据模型和查询语言。与其他关系型数据库相比PostgreSQL 的独特之处在于其开放和扩展性。它不仅支持许多标准 SQL 的特性,还允许用户自定义数据类型、操作符和函数。\n历史\nPostgreSQL 的发展历程反映了其对技术创新和社区驱动的承诺:\n\nPOSTGRES (1989):这是 PostgreSQL 的前身,其主要创新在于支持用户定义的数据类型和面向对象的特性。\nPostgreSQL 6.x (1996)此时POSTGRES 项目更名为 PostgreSQL标志着其对 SQL 标准的更深入支持。这个版本开始,它扩展到了多种操作系统平台,并建立了一个更加活跃的开发者社区。\nPostgreSQL 7.x (2000s):这个版本增强了对外部过程的支持,并引入了更加先进的查询优化器。\nPostgreSQL 8.x (2005):这是 PostgreSQL 首次支持 Windows 平台的版本。它还新增了点对点复制和表空间的功能。\nPostgreSQL 9.x (2010s):这个版本带来了众多创新,包括流复制、列式存储和对 JSON 数据类型的支持。\nPostgreSQL 10.x (2017)这个版本开始PostgreSQL 的版本号发生了变化,主要版本号只增加第一个数字。例如,从 9.6 直接跳到了 10。\nPostgreSQL 11.x (2018):此版本进一步增强了分区表的功能,并引入了并行执行的存储过程。\nPostgreSQL 12.x (2019):引入了对 SQL/JSON 路径语言的支持,提供了更好的索引和分区。\nPostgreSQL 13.x (2020):增加了并行化的增量排序和聚合功能,以及对 B 树索引的改进。\nPostgreSQL 14.x (2021):此版本带来了对长事务的性能改进,以及对复制和分区的增强。\nPostgreSQL 15.x (2022):发布于 2022 年 10 月 13 日,带来了一系列的新特性和改进。\nPostgreSQL 16.x (2023):计划于 2023 年 9 月 14 日发布,目前已经发布了 RC1 版本。\n\n与其他关系数据库相比PostgreSQL 一直强调其对开放性、扩展性和标准的遵循。与 MySQL、Oracle 和 SQL Server 等数据库相比,它被视为一个功能丰富但需要一定学习投入的选择。\n特点\n作为世界上最先进的开源关系数据库PostgreSQL 具有以下显著特点:\n\n数据类型支持标准及用户自定义数据类型增强应用灵活性。\n扩展性允许添加自定义函数、数据类型和聚合函数实现高度定制。\n事务性全面遵循 ACID 原则,确保数据完整性。\n并发控制利用 MVCC 技术,优化高并发下的读写性能。\n安全性集成 SSL、行级安全性和强大的访问控制。\n\n尽管 PostgreSQL 有许多优势,但它也面临一些挑战:\n优势\n\n开源 & 免费:功能丰富且完全免费。\n高度扩展性支持广泛的自定义功能。\n社区支持得益于活跃的全球社区。\n功能丰富支持如 JSON 存储、全文搜索等高级特性,并有众多插件。\n跨平台兼容 Linux、Windows 和 macOS。\n\n挑战\n\n性能比较在特定场景下可能不及 Oracle 或 SQL Server。\n大型应用适应性大型企业应用可能需要额外优化。\n学习曲线功能丰富可能导致新手上手难度增加。\n\nPostgreSQL 通常每年发布一次主要版本,并根据需要发布小的补丁更新。新版本的发布是基于特性完成度而不是预定的时间表,这确保了每个版本的高质量和稳定性。\ngraph LR\n style A fill:#f9d,stroke:#333,stroke-width:2px;\n style B fill:#9cf,stroke:#333,stroke-width:2px;\n style C fill:#9cf,stroke:#333,stroke-width:2px;\n style D fill:#ccf,stroke:#333,stroke-width:2px;\n style E fill:#ccf,stroke:#333,stroke-width:2px;\n style F fill:#ccf,stroke:#333,stroke-width:2px;\n style G fill:#ccf,stroke:#333,stroke-width:2px;\n \n A[PostgreSQL 发布规则]\n B[小版本发布]\n C[主要版本发布]\n D[小版本发布周期]\n E[主要版本发布日期]\n F[小版本发布目标日期]\n G[下一个主要版本]\n \n A --> B\n A --> C\n B --> D\n B --> F\n C --> E\n C --> G\n C --> H\n \n D[每个季度至少发布一次小版本]\n F[目标日期: 每年的 2 月, 5 月, 8 月和 11 月的第二个星期四]\n E[每年一次发布一次主要版本]\n G[计划在 2023 年第三季度发布 16 版本]\n H[主要版本提供 5 年技术支持]\n\n\n对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特点/数据库OracleMySQLSQL ServerPostgreSQL查询性能高优化了 OLTP 和 OLAP适中适合 Web 应用高,优化了 OLTP高特别是复杂查询并发性能高适中到高高高读写吞吐量高适中高高数据存储效率高支持多种压缩技术适中高支持列式存储高支持列式存储备份和恢复高有 RMAN适中有物理和逻辑备份高有完整的备份策略高支持 PITR扩展性高支持 RAC适中有集群解决方案高支持 AlwaysOn高支持分区和分片事务处理能力高支持多种隔离级别适中支持 MVCC高高支持 MVCC安全性高有完整的安全套件适中高有完整的安全策略高支持 RLS 和 TDE可用性高支持 Data Guard适中有复制高支持镜像和复制高支持流复制维护和管理适中有 Enterprise Manager适中有 Workbench适中有 SSMS适中有多种工具特性和功能高有多种高级功能适中支持 JSON高支持 BI、ML 等高,支持 JSON、GIS 等社区和支持适中,商业支持高,由 Oracle 支持适中,由 Microsoft 支持高活跃的社区成本效益高昂的许可费有开源版本有免费版本开源免费DB-Engines-Rank12401111902620\n使用场景\n\nPostgreSQL适用于需要高度可定制、高并发、复杂查询和高扩展性的应用如大型企业应用、GIS 系统、数据仓库等。\nOracle适用于大型企业和金融机构需要高可用性、高安全性和高性能的场景如 ERP、CRM、银行系统等。\nMySQL适用于 Web 应用、小到中型企业应用、开源项目等,需要快速部署和简单维护的场景。\nSQL Server适用于 Windows 环境、需要集成 Microsoft 生态系统的应用,如 .NET 应用、BI 解决方案等。\n\n文化\n**PostgreSQL 拥有一个非常活跃的全球社区,由数千名开发者、用户和志愿者组成。**这个社区不仅贡献代码,还提供技术支持、文档编写和培训。\n**社区坚守开放、共享和合作的原则,这些原则影响了其开发和决策过程,确保了项目的透明性和公正性。**每年,社区都会举办多次活动,如年度的 PostgreSQL 会议、地方性的聚会和线上研讨会。这些活动促进了社区成员之间的交流和合作,也为新成员提供了了解和参与社区的机会。\n所有的决策无论是关于新功能的开发、bug 修复还是其他项目管理事项都是在邮件列表、IRC 频道或其他公开论坛上进行的。这确保了所有的利益相关者都有机会参与和发表意见。\n**PostgreSQL 社区成功地平衡了开源精神与商业需求。**虽然 PostgreSQL 是一个开源项目,但它也与许多商业公司合作,提供商业支持和解决方案。社区也与其他数据库社区,如 MySQL 和 MariaDB有着友好的关系经常在技术和开发上互相学习和合作。\n尽管社区非常活跃和成功但它仍然面临一些挑战如技术挑战、社区管理挑战等。但社区始终坚信通过合作和创新它们可以克服这些挑战并继续发展。"},"Technology/DatabaseSystem/SQL-语言/基础语法":{"title":"基础语法","links":[],"tags":["数据库系统/SQL","技术/数据库"],"content":"概述\nSQLStructured Query Language是一种用于管理关系型数据库的强大语言。它的历史可以追溯到 1970 年,当时 IBM 的研究员 Edgar F. Codd 发表了论文 A Relational Model of Data for Large Shared Data Banks 中首次提出。最初SQL 被称为 SEQUELStructured English Query Language后来被简化为 SQL。\nSQL 语句根据其功能主要分为四类DDL、DML、DQL、DCL。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n分类全拼说明DDLData Definition Language数据定义语言用来定义数据库对象 (数据库,表,字段)。DMLData Manipulation Language数据操作语言用来对数据库表中的数据进行增删改。DQLData Query Language数据查询语言用来查询数据库中表的记录。DCLData Control Language数据控制语言用来创建数据库用户、控制数据库的访问权限。\n语法图\ngraph TD\nQUERY --> SELECT\nQUERY --> FROM\nQUERY --> WHERE\nQUERY --> GROUPBY\nQUERY --> ORDERBY\nSELECT --> Column1[Column1]\nSELECT --> Column2[Column2]\n...\nFROM --> Table1[Table1]\nFROM --> Table2[Table2]\nFROM --> JOIN\nJOIN --> Type[Type: INNER JOIN/LEFT JOIN/...]\nJOIN --> On[On: condition]\nWHERE --> Condition1[Condition1]\nWHERE --> Condition2[Condition2]\n...\nGROUPBY --> GroupColumn1[Column1]\n...\nORDERBY --> OrderColumn1[Column1 ASC/DESC]\n...\n\n\n数据库操作\n查询数据库列表\n-- 查询所有数据库\nSHOW DATABASES;\n创建和选择数据库\n要创建一个新的数据库使用 CREATE DATABASE 语句。如果数据库已经存在,可以使用 IF NOT EXISTS 来避免错误。\n-- 创建 my_database 数据库\nCREATE DATABASE IF NOT EXISTS my_database DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\n \n-- 选择使用 my_database 数据库\nUSE my_database;\n \n-- 查询当前数据库\nSELECT DATABASE(); -- 输出可能为 my_database\n删除数据库\n如果需要删除一个数据库可以使用 DROP DATABASE 语句。请谨慎使用,因为这将永久删除数据库及其数据。\n-- 删除 my_database 数据库\nDROP DATABASE IF EXISTS my_database;\n数据表操作\n数据类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据类型描述示例INT整数12345, -12345VARCHAR可变长度字符串"Hello", "SQL", "Database"CHAR固定长度字符串CHAR(5) 可以存储 "Hello"DATE日期"2023-09-06"DATETIME日期和时间"2023-09-06 14:45:00"FLOAT单精度浮点数3.14, 2.71DOUBLE双精度浮点数3.14159265359DECIMAL精确小数用于金融DECIMAL(5,2) 可存储范围为 -999.99 到 999.99 的数字BLOB二进制数据用于存储图像、音频等TEXT长文本数据用于存储较大的字符串BOOLEAN布尔值TRUE 或 FALSEENUM枚举预定义的值集合ENUM('small', 'medium', 'large')\n常见约束\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n约束描述PRIMARY KEY主键FOREIGN KEY外键UNIQUE唯一约束NOT NULL非空约束DEFAULT默认值约束CHECK条件检查约束\n-- 1.创建 Users 表\nCREATE TABLE Users (\n UserID INT PRIMARY KEY AUTO_INCREMENT,\n Username VARCHAR(50) COMMENT '用户名称',\n Email VARCHAR(100) COMMENT '电子邮件'\n) COMMENT '用户信息表';\n \n-- 2.查询 users 表创建语句\nSHOW CREATE TABLE Users;\n \n-- 3.查询表结构\nDESC Users;\n \n-- 4.查询当前数据库所有表\nSHOW TABLES; -- 输出可能包括 users\n \n-- 5.users 表添加 age 字段\nALTER TABLE Users ADD Age INT COMMENT '用户年龄';\n \n-- 6.users 表修改 age 字段数据类型\nALTER TABLE Users MODIFY Age SMALLINT; -- 将年龄字段类型改为 SMALLINT\n \n-- 7.users 表删除 Age 字段\nALTER TABLE Users DROP Age;\n \n-- 8.users 表修改表名 NewUsers\nALTER TABLE Users RENAME TO NewUsers;\n \n-- 9.清空表内容,保留结构\nTRUNCATE TABLE NewUsers;\n \n-- 10.删除 NewUsers 表\nDROP TABLE IF EXISTS NewUsers;\n查询表结构\n要查看表的结构列、数据类型、约束等可以使用 DESC 命令。\n-- 查询 Users 表结构\nDESC Users;\n查询当前数据库中的所有表\n使用 SHOW TABLES; 命令可以列出当前数据库中的所有表。\n-- 查询当前数据库中的所有表\nSHOW TABLES; -- 输出可能包括 Users 表\n修改表结构\n可以使用 ALTER TABLE 命令来修改表的结构,包括添加、修改和删除列等操作。\n-- 1. 添加列 Age 到 Users 表\nALTER TABLE Users ADD Age INT;\n \n-- 2. 修改列 Age 的数据类型为 SMALLINT\nALTER TABLE Users MODIFY Age SMALLINT;\n \n-- 3. 删除列 Age\nALTER TABLE Users DROP COLUMN Age;\n清空表内容\n-- 清空表内容,保留结构\nTRUNCATE TABLE Users;\n删除表\n要删除一个表及其数据可以使用 DROP TABLE 命令。\n-- 删除 Users 表\nDROP TABLE IF EXISTS Users;\n数据操纵语言DML\n数据操纵语言DML是用于操作数据库中的数据的一组 SQL 命令。与数据定义语言DDL不同DML 主要用于管理和控制数据库中的数据,涉及数据的插入、更新和删除操作。\n插入数据\n使用 INSERT INTO 命令来插入数据。\n-- 插入完整行数据\nINSERT INTO Users (UserID, Username, Email, Age) VALUES (1, 'John Doe', 'johndoe@example.com', 28);\n \n-- 插入部分列数据\nINSERT INTO Users (Username, Email) VALUES ('Jane Doe', 'janedoe@example.com');\n更新数据\n使用 UPDATE 命令来更新数据。\n-- 更新指定行数据\nUPDATE Users SET Age = 30 WHERE UserID = 1;\n \n-- 更新整表数据例如为所有用户年龄加1\nUPDATE Users SET Age = Age + 1;\n删除数据\n使用 DELETE 命令来删除数据。\n-- 删除指定行数据\nDELETE FROM Users WHERE UserID = 1;\n \n-- 删除整表数据(慎用!这将删除所有用户)\nDELETE FROM Users;\n数据查询语言DQL\n数据查询语言DQL是用于查询和检索数据库中存储的数据的一组 SQL 命令。DQL 使用户能够访问并操作数据,不会更改数据库中的任何内容,主要涉及数据的检索和显示。\n基本查询\n-- 1. SELECT - 选择列\nSELECT Username, Email FROM Users; -- 选择用户名和电子邮件列\n \n-- 2. FROM - 选择表\nSELECT * FROM Users; -- 选择 Users 表的所有列\n \n-- 3. WHERE - 条件过滤\nSELECT * FROM Users WHERE Age > 18; -- 选择年龄大于18的记录\n \n-- 4. ORDER BY - 排序结果集\nSELECT * FROM Users ORDER BY Age DESC; -- 按年龄降序排列\n \n-- 5. GROUP BY - 对结果集进行分组\nSELECT Age, COUNT(*) FROM Users GROUP BY Age; -- 按年龄分组,并统计每个年龄段的用户数\n \n-- 6. HAVING - 对分组后的结果进行过滤\nSELECT Age, COUNT(*) FROM Users GROUP BY Age HAVING COUNT(*) > 5; -- 选择用户数大于5的年龄段\n \n高级查询\n-- JOIN - 连接查询\nSELECT Users.Username, Orders.OrderID\nFROM Users\nJOIN Orders ON Users.UserID = Orders.UserID; -- 连接 Users 和 Orders 表,基于 UserID\n \n-- 子查询 - 嵌套 SELECT 语句\nSELECT Username FROM Users WHERE Age = (SELECT MAX(Age) FROM Users); -- 使用子查询来找到年龄最大的用户\n \n-- 聚合函数 - 如 COUNT, SUM, AVG 等\nSELECT AVG(Age) FROM Users; -- 计算所有用户的平均年龄\n \n-- 分页查询 - LIMIT, OFFSET\nSELECT * FROM Users LIMIT 10 OFFSET 5; -- 查询第6至第15条用户记录\n索引\n索引是数据库中的一种特殊的数据结构旨在加速查询操作。通过为表中的一列或多列建立索引查询操作可以更快地找到数据而无需逐行扫描整个表。\n优点:\n\n查询速度索引大大提高了查询速度减少了数据库的查询时间。\n数据检索效率有了索引数据的检索变得更加高效。\n加速表连接在进行 JOIN 操作时,如果涉及到的字段已经被索引,该操作会更加迅速。\n\n缺点:\n\n占用空间索引虽然可以提高查询速度但也占据了额外的磁盘空间。\n维护成本每当有数据插入、更新或删除时索引也需要进行相应的更新这可能导致这些操作的速度变慢。\n\n在实际操作中索引的使用主要是为了优化查询效率。当数据表中的数据量较大或需要频繁查询特定列数据时使用索引是明智的。那些经常需要排序的列或在 WHERE 子句中经常被查询的列,建议创建索引。\n然而对于数据量较小的表或数据在某列上有大量重复值的表以及对于经常进行大量的 INSERT、UPDATE 和 DELETE 操作的表,过多的索引可能并不合适,因为维护索引会带来额外的开销。\n创建索引\n-- 创建名为 idx_Username 的索引,用于 Users 表的 Username 列\nCREATE INDEX idx_Username ON Users(Username);\n删除索引\n-- 删除名为 idx_Username 的索引\nDROP INDEX idx_Username ON Users;\n索引种类\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n索引种类描述唯一索引 (UNIQUE INDEX)确保每行数据在索引列上的值是唯一的。主键索引 (PRIMARY INDEX)唯一索引的一种特殊类型,通常在主键上自动创建。全文索引 (FULLTEXT INDEX)用于在表中执行全文搜索。组合索引 (COMPOSITE INDEX)在两个或多个列上创建的索引。空间索引 (SPATIAL INDEX)在地理空间数据上创建的索引,例如:经纬度。\n视图\n视图是数据库中的一个虚拟表它的内容由查询定义。不同于普通的表视图不包含数据而只保存描述其内容或结构的 SQL 查询。当视图被引用时,其内部的查询被执行,从而产生结果集。视图的主要目的是提供一种机制,使用户可以查看数据的逻辑表示,而不必关心数据的物理存储和实现。\n优点:\n\n简化复杂查询: 对于经常被查询的数据,可以使用视图简化查询的复杂性。\n安全性: 通过视图可以限制对数据的访问,只显示某些部分,而不是完整的表。\n独立性: 对于应用程序,使用视图提供了数据的逻辑独立性。原始表的结构发生变化时,不会影响到使用视图的应用程序。\n\n缺点:\n\n性能: 一些视图可能会导致性能下降,特别是当视图基于多个表和复杂查询时。\n更新限制: 不是所有的视图都可以进行更新操作。\n\n创建视图\n使用 CREATE VIEW 命令来创建视图。\n-- 创建名为 TopUsers 的视图,显示 Users 表中年龄最大的用户\nCREATE VIEW TopUsers AS SELECT * FROM Users ORDER BY Age DESC LIMIT 5;\n修改视图\n要修改视图可以使用 ALTER VIEW 命令。\n-- 修改名为 TopUsers 的视图更改为显示前10个年龄最大的用户\nALTER VIEW TopUsers AS SELECT * FROM Users ORDER BY Age DESC LIMIT 10;\n删除视图\n如果不再需要视图可以使用 DROP VIEW 命令删除它。\n-- 删除名为 TopUsers 的视图\nDROP VIEW IF EXISTS TopUsers;\n事务\n事务是数据库管理系统中的一个单元操作由一个以上的相关操作组成。它可以确保被其包含的数据库操作要么全部成功要么全部失败确保数据库的完整性和一致性。\nACID\n\n原子性 (Atomicity): 事务被视为一个单独的单元,它要么完全地执行,要么完全地不执行。\n一致性 (Consistency): 事务确保数据库从一个一致性状态转换到另一个一致性状态。\n隔离性 (Isolation): 在并发环境中,事务的执行不应由其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,反之亦然。\n持久性 (Durability): 一旦事务被提交,它对数据库的改变就是永久的,接下来的其他操作或故障不应该对其有任何影响。\n\n事务在数据库管理中扮演了关键的角色特别是在处理复杂的业务逻辑时如涉及多个表的插入、更新或删除操作。这确保了所有相关操作要么全部成功执行要么全部不执行从而保障了数据的完整性。\n一个典型的例子是在银行应用中进行的转账操作其中从一个账户扣款和向另一个账户存款这两个动作都必须成功完成否则都应该被撤销以确保资金的准确性。此外在高并发的环境中如多用户同时访问数据库事务还能确保所有用户都能看到一致和准确的数据视图避免了因并发操作导致的数据不一致性。\n示例\n-- 开始事务\nBEGIN;\n......\n \n-- 提交事务\nCOMMIT;\n \n-- 回滚事务\nROLLBACK;\n-- 开始一个新的事务\nSTART TRANSACTION;\n \n-- 扣款操作从账户A减少100元\nUPDATE Accounts SET Balance = Balance - 100 WHERE AccountNumber = 'A';\n \n-- 存款操作向账户B增加100元\nUPDATE Accounts SET Balance = Balance + 100 WHERE AccountNumber = 'B';\n \n-- 如果上述两个操作都成功执行,提交事务\nCOMMIT;\n \n-- 如果发生错误或需要撤销操作,回滚事务\nROLLBACK;\n数据控制语言DCL\n数据控制语言DCLData Control Language是 SQL 的一个子集主要关注于访问权限和数据的安全性。DCL 提供了设置或撤回用户权限的工具,从而确保只有经授权的用户才能执行特定的活动。\n用户管理\n-- 1.查询用户\nuse mysql;\nselect * from user;\n \n-- 2.创建用户,主机名 % 通配符号\nCREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';\n \n-- 3.修改用户密码\nALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';\n \n-- 4.删除用户\nDROP USER '用户名'@'主机名';\n权限管理\n数据库权限的设置应该遵循最小权限原则即只赋予用户完成其任务所必需的最小权限。同时定期审查用户的权限并作必要的调整确保数据安全性。\n-- 查询权限:\nSHOW GRANTS FOR '用户名'@'主机名';\n \n-- 授予权限:\nGRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';\nGRANT SELECT, INSERT ON database_name.table_name TO 'username'@'hostname';\n \n-- 撤销权限:\nREVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';\nREVOKE SELECT, INSERT ON database_name.table_name FROM 'username'@'hostname';\n \n-- 注意:\n-- 多个权限用逗号分隔\n-- 授权时,数据库名和表名可以用 * 进行通配,代表所有\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n权限类型描述SELECT允许读取数据INSERT允许插入新数据UPDATE允许更新现有数据DELETE允许删除数据EXECUTE允许执行存储过程或函数ALTER允许修改数据库对象 (如表或索引)DROP允许删除数据库对象CREATE允许创建数据库对象GRANT OPTION允许用户授予权限给其他用户INDEX允许用户在表上创建索引REFERENCES允许用户在表上创建外键约束\nSQL 函数\nSQL 函数提供了处理数据的方便方法,允许我们在查询过程中对数据进行操作和转换。以下是一些常见的 SQL 函数分类及其示例。\n字符串函数\n-- 合并两个或多个字符串\nSELECT CONCAT('Hello', ' World!') AS Result; \n \n-- 从字符串中提取子字符串\nSELECT SUBSTRING('Hello World!', 1, 5) AS ExtractString;\n \n-- 去掉字符串开始或结束处的空白字符\nSELECT TRIM(' Hello World! ') AS TrimmedString;\n \n-- 转换字符串大小写\nSELECT UPPER('Hello'), LOWER('WORLD!') AS Result;\n数值函数\n-- 对数字进行四舍五入\nSELECT ROUND(123.4567, 2) AS RoundedNumber; \n \n-- 向下和向上取整\nSELECT FLOOR(123.4567) AS FloorValue, CEIL(123.4567) AS CeilValue;\n日期函数\n-- 格式化日期/时间值\nSELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS FormattedDate;\n \n-- 返回当前日期和时间\nSELECT CURDATE() AS TodayDate, CURTIME() AS CurrentTime;\n转换函数\n-- 将一个数据类型转换为另一个数据类型\nSELECT CAST('123' AS INT) AS IntegerType; \n \n-- 类似于CAST但提供了更多的格式选项\nSELECT CONVERT('123', INT) AS IntegerType;"},"Technology/DatabaseSystem/基础/关系型数据库":{"title":"关系型数据库","links":[],"tags":["数据库系统/关系型数据库","技术/数据库"],"content":"关系模型\n关系模型是一种理论模型它用于描述和组织数据库中的数据。这种模型通过使用一系列表格来表示不同实体之间的关系以及实体的属性。关系模型在数据库管理系统中广泛应用它提供了一种结构化的方式来存储、管理和查询数据。\n表的结构\n关系模型的核心组成部分是表或称为关系每个表都由一系列的行和列组成。\n\n行也称为记录或元组每一行代表数据库中的一个实体。\n列也称为属性每一列代表实体的一个属性。\n键一个或多个列被标识为主键用于唯一地标识每一行。\n\n主键保证每个实体在表中的唯一性。\n外键则用于与其他表的主键相连接建立表与表之间的关系。\n\n\n\n数据查询语言\n关系模型通常使用**结构化查询语言SQL**来执行查询和操作数据。SQL 是一种强大的语言,允许用户检索、插入、更新和删除数据。\n实例示例\n以下是一个示例的学生表格用于说明关系模型的结构\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n学号主键姓名年龄专业1001张三20计算机科学1002李四22数学1003王五21物理\n在这个表中\n\n每一行代表一个学生实体具有唯一的学号。\n每一列代表学生的属性如姓名、年龄和专业。\n\n通过这种结构数据库管理系统可以轻松地存储和检索数据。例如通过学号你可以快速地找到特定学生的信息。\nER 模型\n**ER 模型(实体 - 关系模型)用于描述现实世界的关系。**这个模型以图形的形式表示数据的结构,有助于理解和构建复杂的数据结构。让我们通过一个实例来详细了解 ER 模型的各个组成部分。\nerDiagram\n STUDENT ||--o{ ENROLLMENT : "enrolls"\n STUDENT ||--o{ TAKES : "takes"\n COURSE ||--o{ ENROLLMENT : "is enrolled in"\n COURSE ||--o{ TAKES : "is taken by"\n TEACHER ||--o{ TEACHES : "teaches"\n ENROLLMENT ||--o{ TAKES : "is taken in"\n TEACHER ||--o{ COURSE : "teaches"\n\n实体\n实体表示可以独立存在的事物。\n\n学生每个学生都有姓名、年龄等属性。\n课程每门课程都有课程名、学分等属性。\n教师每个教师都有姓名、专业等属性。\n\n关系\n关系模型中的关系有三种主要类型它们描述了实体之间的不同类型的连接和联系。这些关系类型包括\n一对一关系One-to-One Relationship\n例如考虑人和身份证之间的关系。每个人可能只有一个身份证号码而一个身份证号码也只能与一个人相关联。\n一对多关系One-to-Many Relationship\n例如一个学校的教师和课程之间的关系就是一对多关系。每个教师可以教授多门课程但每门课程只能由一个教师教授。\n多对多关系Many-to-Many Relationship\n例如学生和课程之间的关系就是多对多关系。一个学生可以选择多门课程同时每门课程也可以被多个学生选择。\n属性\n**属性描述实体或关系的特性,为数据提供更多的信息。**属性在数据库中对实体或关系的各个方面进行描述和标识,以便更好地管理和查询数据。\n\n学生姓名、年龄等。\n课程课程名、学分等。\n教师姓名、专业等。\n选课选课日期等。\n教授授课地点等。\n\n数据库规范化\n数据库规范化是一种组织数据的技术目的是减少冗余并避免不必要的复杂性。通过将数据分解成更小、更相关的部分可以确保数据库的一致性、完整性和性能优化。规范化通常遵循一系列范式每个范式都有特定的规则有助于确保数据库设计的质量和效率。\n第一范式1NF\n**第一范式确保每个列保持原子性,即列中的每个值都是不可分割的单一值。**这有助于消除重复的数据并减少数据冗余。要达到第一范式,确保每个表中的每个列都只包含原子值,而不是包含多个值的列表或数组。\n例如如果我们有一个存储学生和他们选修课程的表格\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n学生 ID姓名选修课程1001张三数学, 物理1002李四英语, 数学\n这就违反了第一范式因为选修课程列包含了多个值。要修正这种情况可以将每个选修课程拆分成单独的行\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n学生 ID姓名选修课程1001张三数学1001张三物理1002李四英语1002李四数学\n第二范式2NF\n**第二范式在满足第一范式的基础上,进一步移除部分依赖。**这意味着非主键列必须完全依赖于整个主键,而不仅仅是主键的一部分。为了达到第二范式,可以将表拆分成多个关联表,确保每个非主键属性只与一个候选键相关。\n例如考虑一个存储订单和订单项的表格\n订单表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n订单 ID (PK)顾客 ID订单日期00110012023-08-0100210022023-08-02\n订单项表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n订单 ID (PK, FK)产品 ID (PK)数量001101200110210021013\n在这里虽然订单表满足第一范式但订单项表中的数量列部分依赖于订单 ID而订单 ID 是主键的一部分。为了满足第二范式,我们可以将订单项表分为两个表格,一个是订单表,一个是订单项表。\n第三范式3NF\n**第三范式在满足第二范式的基础上,进一步移除所有传递依赖。**这意味着表中的每个非主键列都不能依赖于其他非主键列。为了达到第三范式,可以继续拆分表,确保每个非主键列都直接依赖于主键。\n例如考虑一个存储学生选课信息的表格\n学生课程表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n学生 ID (PK)课程 ID (PK)学分课程名称10011013数学10011024物理10021013数学\n在这里课程名称是根据课程 ID 直接得出的,因此存在传递依赖。为了满足第三范式,可以将课程名称拆分到一个独立的课程表中:\n课程表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n课程 ID (PK)课程名称101数学102物理\n学生课程表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n学生 ID (PK)课程 ID (PK)学分100110131001102410021013\n这样就消除了学生课程表中的传递依赖满足了第三范式的要求。\n数据完整性和安全性\n数据完整性\n**数据完整性是确保数据的准确性、一致性和有效性。**它是数据库设计和管理中的关键概念,以确保数据库中的数据始终保持正确的状态。以下是几个数据完整性的方面:\n\n实体完整性实体完整性要求每个表都应该有一个主键唯一标识符并且主键不允许为空或重复。这可以确保每个实体在数据库中都是唯一的从而避免数据重复和冗余。\n引用完整性引用完整性是确保外键关系的准确性和一致性。外键是一个表中的列它引用了另一个表的主键。引用完整性要求外键值必须对应于另一个表中的已存在的主键值防止数据之间的不一致性。\n领域完整性领域完整性是确保数据值在定义的范围内。例如一个存储年龄的字段不应该接受负值或过大的值。通过定义合适的数据范围可以避免无效的数据输入。\n\n数据安全性\n**数据安全性是保护数据库免受未经授权的访问、修改或泄露。**确保数据安全性对于保护用户隐私和敏感信息至关重要。以下是保障数据安全性的关键措施:\n\n用户认证用户认证是确认用户身份的过程。用户必须提供凭据如用户名和密码才能访问数据库。只有经过身份验证的用户才能执行操作。\n授权授权是定义用户对数据库的访问权限。不同用户可能需要不同级别的权限如读取、写入或管理员权限。授权可以避免未经授权的访问和潜在的数据泄露。\n加密数据加密是通过将数据转换为不可读的形式以保护数据的隐私。即使数据被盗加密的数据也无法被轻易解读。在传输和存储数据时使用加密可以防止中间人攻击和数据泄露。\n审计和监控定期审计数据库的活动和访问以便发现异常或未经授权的操作。监控数据库的性能和安全性有助于及早发现问题并采取适当的措施。\n\n通过数据完整性和安全性的综合措施数据库可以在保持数据的准确性和一致性的同时确保数据不受到未经授权的访问或恶意操作的影响。这有助于建立稳定、可靠且可信赖的数据库系统。"},"Technology/DatabaseSystem/基础/数据库概述":{"title":"数据库概述","links":[],"tags":["技术/数据库","数据库系统"],"content":"概述\n数据库是什么\n数据库是用于存储、检索和管理数据的组织化系统。在数据库中数据以结构化的方式组织可以通过使用查询语言来方便地访问和操作。数据库可以用于保存各种类型的信息例如客户信息、产品目录、交易记录等。\n为什么需要数据库\n\n信息组织数据库允许企业和个人以结构化的方式组织信息使数据检索和分析更加高效。\n数据完整性和准确性通过使用数据库可以确保数据的完整性和准确性防止数据冲突和错误。\n安全性和隐私数据库提供了访问控制和加密功能保护数据不被未授权访问。\n灵活性和扩展性数据库可以按需进行扩展适应不断增长的数据量和复杂的查询需求。\n\n历史发展\n1960 年代:计算机化数据库的开始\n在 1960 年代随着计算机价格的下降私人组织开始将数据存储和数据库转移到计算机上。CODASYL 网络模型和 IMS 层次模型成为流行的数据模型。IBM 的 SABRE 系统用于帮助美国航空管理预订数据,成为商业上的成功案例。\n1970 年代:关系型数据库的引入\nE.F. Codd 的关系数据库理论改变了人们对数据库的看法。他的模型将数据库的逻辑组织与物理信息存储分离成为数据库系统的标准原则。Ingres 和 System R 是这一时期的主要关系数据库系统原型。实体 - 关系ER模型也在 1976 年被提出,使设计人员能够专注于数据应用。\n1980 年代SQL 成为标准查询语言\n1986 年SQL 成为美国国家标准化协会选择的标准查询语言。关系数据库系统在商业上取得了成功,如 IBM 的 DB2 成为旗舰数据库产品。许多新的数据库公司成立,开发了如 PARADOX、RBASE 5000 等产品。\n1990 年代:数据库技术的多元化发展\n1990 年代,数据库和数据库软件取得了重要进展。新的客户端开发工具如 Oracle Developer、PowerBuilder、VB 等被发布。物联网的出现导致数据库行业的指数增长。到了 90 年代末,对互联网数据库连接器如 Front Page、Active Server Pages 等的需求增加。\n2000 年代NoSQL 数据库的开始和持续增长\n2000 年代初尽管互联网行业经历了衰退但数据库应用继续增长。NoSQL 术语首次在 1998 年由 Carlo Strozzi 提出,但直到 2009 年才重新进入行业词汇。新的交互式应用为 PDAs、销售点交易等开发。\n今天数据库无处不在\n现在数据库无处不在用于增强我们的日常生活。从个人云存储到预测天气许多我们今天使用的服务都得益于数据库。非关系数据库领域有许多新玩家提供特定解决方案如 Oracle、MySQL 和 DB2 等。\n数据库和数据库管理的未来\n未来的数据库和数据库管理将与处理和计算的整体发展紧密相连。**机器学习和人工智能将继续改进并成为数据库及其管理的组成部分。**更快、更高效的数据库管理工具将上市,行业标准将根据最新发展不断迭代。未来对于数据库行业来说看起来非常光明。\n数据库的种类\n数据库主要分为关系型数据库和非关系型数据库两大类。\n关系型数据库\n关系型数据库以表格形式存储数据并使用 SQL 进行查询。表中的每一行代表一个记录,每一列代表一个字段。\n常见的关系型数据库\n\nPostgres开源的对象 - 关系型数据库系统,提供了许多先进功能。\nMySQL流行的开源数据库适用于网站和在线应用。\nOracle企业级数据库提供了高性能、可靠性和安全性。\nSQL Server微软推出的数据库解决方案适合于 Windows 环境。\n\n非关系型数据库\n**非关系型数据库不完全依赖表格结构,更加灵活。**非关系型数据库主要分为以下几类:\n\n\n**文档型数据库:**存储数据的格式通常为 JSON 或 XML以文档为单位进行存储和查询适用于具有丰富结构的数据。\n\n\n**键值存储数据库:**以键值对形式存储数据,读写速度快,适用于需要快速读写操作的场景。\n\n\n**列族存储数据库:**适用于存储大量数据的场景,以列族形式存储,优化了列式查询的性能。\n\n\n**图数据库:**存储图形结构的数据,用于表示实体间的复杂关系。\n\n\n**时间序列数据库:**专门处理时间序列数据,适合存储连续产生的带时间戳的数据。\n\n\n**对象数据库:**将数据以对象的形式存储,可以直接与对象导向编程语言互操作。\n\n\n开源和商业数据库产品\n对比介绍\n数据库是现代组织的核心组成部分用于存储和管理大量数据。数据库解决方案可以分为两大类**开源数据库和商业数据库。**以下是关于这两种类型的对比介绍:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特点开源数据库商业数据库许可成本通常无前期许可成本可能有高级功能的付费版本明显的前期许可成本维护成本可能有订阅支持合同通常较低通常较高包括专业支持和维护服务许可模型开源许可可能因产品和供应商而异可能包括复杂和限制性的许可协议定价结构可能提供免费的基本功能和付费的高级功能根据功能和支持级别定价可定制性由于源代码可用可根据需求定制通常只能由授权用户查看或修改供应商支持可能有商业支持选项也可能依赖社区支持专业供应商提供全面支持包括补丁和升级优点成本效益、灵活性和定制性、社区支持功能丰富、专业支持和维护、合规性和安全性缺点可能缺乏专业支持、功能可能有限成本较高、可能缺乏灵活性适用背景初创公司和中小企业、开发和测试环境、社区驱动项目大型企业和政府机构、关键业务应用、合规性要求高的行业市场趋势成本效益和灵活性使其成为有吸引力的选择传统上提供更全面的功能和工具但成本较高\n市场趋势\n开源数据库在功能、管理工具和可用 DBA 技能方面的增长,结合商业数据库产品源代码的高成本和复杂的许可协议,使开源产品成为越来越有吸引力的替代方案。\n开源和商业数据库各有优势和劣势。开源解决方案提供了成本效益和灵活性而商业解决方案则提供了全面的功能和专业支持。组织在选择数据库解决方案时应考虑其特定需求、预算和战略目标。\n随着开源数据库的成熟和商业数据库的创新这两种类型的数据库将继续共同推动行业的发展。未来的趋势表明开源数据库的使用可能会在未来几年内增加这反映了其在成本、功能和灵活性方面的竞争优势。\n无论是开源还是商业数据库技术都在不断演进为组织提供了更多的选择和机会来满足其不断变化的业务需求。选择**合适的数据库解决方案需要综合考虑多个因素,包括成本、功能、支持和适用场景。**随着技术的不断发展,开源和商业数据库将继续为组织提供更多的机会和选择。"},"Technology/DatabaseSystem/基础/非关系型数据库":{"title":"非关系型数据库","links":[],"tags":["技术/数据库","数据库系统/非关系型数据库"],"content":"概述\n非关系型数据库NoSQL 数据库)是一种与传统的关系型数据库相对的数据存储和管理系统。**它不使用固定的表结构,没有统一的查询语言如 SQL更加灵活地处理数据的存储和检索。**特点包括:\n\n数据结构灵活 可以存储 JSON、XML 等多种格式的数据。\n查询语言多样 可以使用各种专用查询语言或 API。\n扩展性强 通常更容易水平扩展,适合大数据和高并发场景。\n一致性可调整 可以根据需要牺牲一些一致性,以换取更高的性能和可用性。\n性能优势 在读写密集和大数据场景下可能提供更高性能。\n特定用途 更适合特定用途,如大数据分析、实时应用、缓存等。\n\n与关系型数据库的对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性关系型数据库非关系型数据库数据结构固定的表结构每个表有预定义的列灵活的数据结构可以存储不同格式的数据查询语言使用 SQL 作为标准查询语言可使用各种专用查询语言或 API扩展性主要支持垂直扩展更容易水平扩展适合大数据和高并发场景一致性强一致性支持 ACID 事务可能牺牲一些一致性以换取更高的性能和可用性性能适合复杂查询和事务处理在读写密集和大数据场景下可能提供更高性能用途通用数据存储和管理特定用途如大数据分析、实时应用、缓存等典型数据库MySQL, PostgreSQL, Oracle 等MongoDB, Redis, Cassandra 等\n非关系型数据库广泛应用于大数据分析、实时应用、缓存、分布式系统等领域。由于其灵活的数据结构和高性能的读写能力非关系型数据库特别适合需要快速读写和灵活数据结构的场景如社交网络、电商、物联网等。\n键值存储数据库\n键值存储数据库是一种非常基础的数据库类型它以键值对的形式存储数据。每个键在数据库中都是唯一的对应一个特定的值。这种简单的数据模型使键值存储数据库非常快速和可扩展。\n特点\n\n高性能读写操作通常非常快因为它们是通过键进行的。\n可扩展性支持水平扩展可以轻松处理大量数据和高吞吐量。\n简单性基于键值对的结构使数据操作和管理非常直接和容易。\n灵活存储值可以是简单的字符串、数字或更复杂的数据结构。\n\n键值存储数据库非常适合那些需要快速读写访问的应用场景特别是其中数据结构相对简单的情况。\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景Redis高性能、支持多种数据结构、可用于缓存内存消耗较高、持久化配置较复杂实时分析、缓存、排行榜等Riak高可扩展性、容错能力强查询功能有限、配置复杂分布式应用、大数据处理Amazon DynamoDB完全托管、易于扩展、与 AWS 集成良好成本可能较高、灵活性可能较低云原生应用、移动应用、大规模实时分析\n适用场景\n\n缓存和会话存储快速的读写性能使其成为缓存和会话数据的理想选择。\n实时分析可以用于存储大量快速变化的数据如股票价格或网站点击量。\n物联网数据存储适合存储来自大量设备的简单数据。\n排行榜和计数器适合用于存储和检索按顺序排列的数据。\n\n键值存储数据库因其高性能、可扩展性和简单性而受到许多组织的欢迎。通过选择合适的键值存储数据库产品可以更有效地满足特定应用和业务需求的数据管理要求。\n文档型数据库\n文档型数据库以文档的形式存储数据通常使用 JSON 或 BSON 格式。每个文档都可以有不同的结构,包括嵌套的数组和对象。这种灵活性使文档型数据库非常适合存储半结构化数据。\n特点\n\n灵活性无需预定义的模式允许存储结构不同的文档。\n可扩展性通常支持水平扩展适合大规模数据处理。\n多样化查询支持复杂的查询操作包括全文搜索和地理空间查询。\n\n文档型数据库解决了传统关系型数据库在处理半结构化数据和快速迭代开发中的挑战。它们允许开发人员灵活地更改数据模型而无需迁移整个数据库。\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景MongoDB灵活的数据模型、高可扩展性、支持地理空间查询写入吞吐量可能受限、事务支持较弱大数据分析、实时应用、物联网数据存储CouchDB多版本并发控制MVCC、强大的 MapReduce 支持、高可用性查询性能可能较低、不支持复杂的事务分布式系统、移动应用数据同步RavenDB支持 ACID 事务、强大的索引和查询能力、易于使用和管理社区支持较弱、商业许可可能昂贵企业应用、金融服务、健康医疗数据管理\n适用场景\n\n大数据和实时分析灵活的数据结构和高可扩展性使文档型数据库适合大数据处理。\n内容管理和电子商务可以存储和检索各种格式的产品信息、用户评论等。\n移动应用和物联网适合存储来自不同设备和源的半结构化数据。\n敏捷开发和迭代灵活的模式设计支持快速迭代开发和变更。\n\n文档型数据库解决了传统关系型数据库在处理半结构化数据和快速迭代开发中的挑战。它们允许开发人员灵活地更改数据模型而无需迁移整个数据库。通过选择合适的文档型数据库产品组织可以更有效地满足特定应用和业务需求的数据管理要求。\n时间序列数据库\n时间序列数据库Time-Series DatabaseTSDB是一种专门用于处理时间序列数据的数据库即按照时间顺序排序的数据点序列。这些数据库特别适用于存储、检索和处理与时间戳关联的数据例如股票市场数据、传感器数据、网络监控数据等。\n特点\n\n时间优化针对时间序列数据的存储和查询进行了优化以支持高效的时间范围查询和聚合。\n高写入性能能够处理大量的写入操作适合记录连续产生的数据。\n可扩展性许多时间序列数据库支持水平扩展可用于大规模数据处理。\n数据压缩使用专门的算法进行数据压缩减少存储需求。\n自动数据管理自动执行数据过期和降采样等操作以管理数据的生命周期。\n\n时间序列数据库解决了传统数据库在处理时序数据方面的挑战适用于需要高效存储和分析时间序列数据的场景。\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景InfluxDB高写入吞吐量、强大的查询语言、易于使用高并发下性能可能受限监控、实时分析、物联网Prometheus高可用、与 Kubernetes 良好集成、丰富的可视化选项长时间存储能力较弱系统监控、应用性能监控TimescaleDB基于 PostgreSQL、SQL 兼容、可用现有工具和知识资源消耗可能较高金融分析、工业自动化、科学研究\n适用场景\n\n金融和市场分析存储和分析股票价格、交易量等金融市场数据。\n工业物联网收集和分析工厂设备的传感器数据用于监控和预测维护。\n系统和网络监控实时跟踪系统和网络性能指标。\n气象和环境监测存储和分析气象站或环境传感器收集的数据。\n\n时间序列数据库是处理时间敏感信息的理想选择通过对时间序列数据的高效存储和查询使组织能够实时洞察业务和运营情况。选择合适的时间序列数据库产品可以有效支持不同行业和应用场景的特定需求。\n图数据库\n图数据库是一种以图结构存储数据的数据库用于表示实体之间的复杂关系。在图数据库中实体表示为节点或顶点而实体之间的关系表示为边。图数据库非常适合用于分析和查询复杂的关系网络例如社交网络、组织结构、供应链等。\n特点\n\n强关系表示通过节点和边的结构可以直观有效地表示和查询复杂的关系。\n高性能查询针对复杂关系的查询进行了优化例如查找最短路径、连接度分析等。\n灵活性允许灵活地定义和更改实体和关系的属性。\n图遍历和分析支持高效的图遍历操作可用于诸如社交网络分析、推荐系统等。\n\n图数据库解决了传统关系型数据库在处理高度相互连接的数据方面的挑战。\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景Neo4j丰富的图查询语言、强大的社区支持、易于使用大规模分布式支持有限社交网络分析、推荐系统、欺诈检测OrientDB支持多模型图、文档、高性能、可扩展社区支持较弱多关系数据分析、实时应用Amazon Neptune完全托管、高可用、与 AWS 集成良好成本可能较高、自定义选项较少云原生应用、知识图谱、网络分析\n适用场景\n\n社交网络分析分析用户之间的连接和互动如朋友关系、共享兴趣等。\n推荐系统通过分析用户和商品之间的关系为用户提供个性化推荐。\n欺诈检测通过分析不正常的关系和行为模式检测欺诈活动。\n知识图谱构建表示和查询复杂的知识结构和语义关系。\n\n图数据库以其独特的图形结构优势在分析和处理复杂关系数据方面表现卓越。对于那些依赖于深入分析和理解复杂关系的应用场景图数据库提供了强大的支持和灵活性。选择合适的图数据库产品可以更有效地支持特定应用和业务需求的数据管理要求。\n对象数据库\n对象数据库Object-Oriented DatabaseOODB是一种数据库其存储结构以对象的形式来表示信息直接支持面向对象编程语言的各种特性如封装、继承和多态等。对象数据库试图使数据库的存储方式与应用程序的编程模型更加一致简化开发流程。\n特点\n\n对象模型数据以对象的形式存储每个对象都可以包含数据和方法完全符合面向对象的概念。\n支持继承和多态可以定义对象之间的继承关系和多态行为增加了数据模型的表现力和灵活性。\n直接持久化允许应用程序中的对象直接持久化到数据库中无需进行复杂的映射和转换。\n复杂结构支持非常适合存储具有复杂结构和关系的数据如几何模型、多媒体数据等。\n\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景ObjectDB高性能、易于使用、与 JPA 完全兼容社区支持有限企业应用、复杂数据模型管理Versant强大的并发控制、可扩展、长期稳定学习曲线可能较陡峭金融分析、电信网络管理db4o开源、轻量级、易于集成、适合移动和嵌入式设备没有商业支持、可能存在性能问题嵌入式系统、移动应用\n适用场景\n\n复杂数据模型管理例如 CAD/CAM 系统、科学研究、地理信息系统等需要处理复杂数据结构的应用。\n实时系统例如电信、工业自动化等需要快速响应和处理的场景。\n面向对象开发的企业应用对象数据库能够更自然地与面向对象的编程语言和开发模式集成。\n\n对象数据库通过与面向对象编程模型的紧密结合为开发者提供了一种自然、灵活的数据管理方式。它消除了传统关系数据库中对象和关系映射的复杂性特别适合需要处理复杂数据结构和关系的应用。虽然对象数据库在现代企业环境中使用不如关系数据库广泛但在特定场景下它仍然有着独特的优势和价值。\n列族存储数据库\n列族存储数据库是一种 NoSQL 数据库,其存储模型不是按行组织数据,而是按列组织。这种结构特别适合于具有大量列且读取模式相对固定的数据集,它可以提高数据读取的效率,并允许高效的数据压缩。\n特点\n\n列式存储数据按列组织和存储有助于特定列的查询和分析。\n可扩展性通常提供水平扩展的能力适合大规模数据集。\n高性能读取特别优化了列式数据的读取性能适合数据仓库和分析应用。\n灵活的数据模型通常不需要预定义的模式可以灵活地添加和删除列。\n\n常用产品\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据库优点缺点适用场景Apache HBase高可扩展、高可用、集成 Hadoop 生态写入性能较低、管理复杂大数据分析、实时分析、数据仓库Cassandra高可扩展、高性能读写、支持多数据中心学习曲线陡峭、一致性配置复杂互联网应用、实时大数据分析、分布式系统Google Bigtable企业级服务、高性能、完全托管成本可能较高、主要绑定 Google 云云原生应用、广告技术、物联网数据存储\n适用场景\n\n大数据分析针对大规模数据集的分析查询例如日志分析、趋势预测等。\n时间序列数据例如股票市场数据、气象数据等可以高效地按时间序列进行查询分析。\n实时应用例如金融交易、监控系统等需要高速读取和查询的应用。\n内容管理和个性化推荐存储用户行为和内容信息用于个性化推荐和广告定位。\n\n列族存储数据库通过其列式存储结构在大数据分析、实时查询等场景下表现出显著的性能优势。在需要处理大量列数据特别是读取模式相对固定的应用场景中列族存储数据库可以提供高效、灵活的解决方案。选择合适的列族存储数据库产品有助于满足特定业务和技术需求。"},"Technology/GettingStarted/命令行工具/PowerShell/PowerShell-入门":{"title":"PowerShell 入门","links":[],"tags":["技术/入门","PowerShell"],"content":"PowerShell\n概述\nPowerShell 是由微软开发的一种跨平台任务自动化和配置管理框架,由命令行 Shell 和脚本语言组成。它基于 .NET 框架,可以运行在 Windows、MacOS 和 Linux 系统上。PowerShell 的强大之处在于其能够访问和管理系统的所有资源,包括文件系统、注册表、网络等。它不仅适用于系统管理员进行日常管理任务的自动化,还适用于开发者进行复杂的脚本编写和配置管理。通过 PowerShell用户可以轻松地执行复杂的操作任务自动化日常管理工作简化运维流程并提高工作效率。\n**PowerShell 通过 cmdlet发音为 “command-let”来执行任务。**每个 cmdlet 通常由一个动词和一个名词组成,例如 Get-Process 用于获取进程信息。PowerShell 还支持面向对象的管道Pipeline允许 cmdlet 之间传递对象,而不仅仅是文本,这使得数据处理更加直观和强大。\n发展历史\n初期发展\n2006 年Windows PowerShell 1.0 PowerShell 最初在 2006 年作为 Windows PowerShell 1.0 发布。这一版本基于 .NET Framework旨在为系统管理员提供一种强大的命令行工具用于自动化日常管理任务。1.0 版本的发布标志着微软在命令行和脚本语言方面迈出了重要的一步。\n版本演进\n2008 年Windows PowerShell 2.0 2008 年,微软发布了 Windows PowerShell 2.0。此版本引入了许多新功能,包括 PowerShell ISE集成脚本环境、高级函数、远程处理Remoting和模块Modules等。这些功能显著增强了 PowerShell 的灵活性和扩展性,使其成为一个更加全面的管理工具。\n2012 年Windows PowerShell 3.0 Windows PowerShell 3.0 在 2012 年随 Windows Server 2012 和 Windows 8 一同发布。此版本进一步增强了脚本语言的功能引入了工作流Workflows和改进的 cmdlet增强了对任务自动化的支持。\n2013 年Windows PowerShell 4.0 2013 年发布的 Windows PowerShell 4.0 主要带来了 DSCDesired State Configuration功能使管理员能够声明性地配置和管理系统确保系统处于期望的状态。\n2016 年Windows PowerShell 5.0 Windows PowerShell 5.0 于 2016 年发布,进一步引入了许多新功能,如类和枚举、自定义模块仓库、改进的 PowerShell ISE 以及增强的 DSC 功能。\n开源与跨平台\n2016 年PowerShell Core 6.0 2016 年,微软宣布 PowerShell 开源,并发布了 PowerShell Core 6.0。这是一个基于 .NET Core 的跨平台版本,能够在 Windows、MacOS 和 Linux 上运行。PowerShell Core 的发布标志着 PowerShell 从 Windows 独有工具转变为一个真正的跨平台管理框架。\n统一版本\n2020 年PowerShell 7 2020 年,微软发布了 PowerShell 7。这一版本基于 .NET Core 3.1,进一步改进了跨平台兼容性,并统一了 Windows PowerShell 和 PowerShell Core 的功能和体验。PowerShell 7 的发布标志着 PowerShell 进入了一个新的时代,提供了更高效、更灵活的自动化和管理解决方案。\n未来发展\n持续更新与社区参与 PowerShell 的发展一直得到社区的积极参与和贡献。微软通过 GitHub 开放源码,接受社区的反馈和贡献,使 PowerShell 不断演进和改进。PowerShell 7 之后的版本将继续增强性能、扩展功能,并进一步提升跨平台支持。\nPowerShell 与其他 Shell 的对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n比较维度PowerShellCMDBashZsh平台支持跨平台Windows, Mac, LinuxWindowsUnix 系统Linux, MacUnix 系统Linux, Mac开发公司微软微软GNU开源社区对象模型面向对象操作 .NET 对象基于字符串处理基于字符串处理基于字符串处理管道机制支持对象管道不支持支持字符串管道支持字符串管道脚本扩展名.ps1.bat, .cmd.sh.zsh主要用途系统管理、自动化脚本简单任务自动化、批处理系统管理、自动化脚本、服务器管理系统管理、自动化脚本、服务器管理交互界面图形界面PowerShell ISE, VS Code无图形界面无图形界面无图形界面错误处理高级错误处理机制try/catch简单的错误处理if errorlevel基本错误处理基本错误处理模块系统丰富的模块和包管理系统PSGallery无模块系统基于文件和库基于文件和库脚本调试强大的调试工具断点、变量监视无直接调试工具基本调试工具set -x, trap基本调试工具set -x, trap命令别名支持丰富的命令别名支持少量命令别名支持命令别名支持强大的命令别名包括 Bash 支持的所有别名)扩展性高度扩展性,通过 .NET 库和第三方模块低扩展性中等扩展性,通过脚本和第三方工具高度扩展性,通过插件系统内置命令丰富的内置 cmdlet 和函数基本的内置命令丰富的内置命令丰富的内置命令学习曲线相对陡峭,需要了解 .NET 对象模型平缓,易于上手中等,需要了解 Unix 系统和命令中等,需要了解 Unix 系统和命令文档支持强大的内置帮助系统Get-Help基本的帮助命令help, /?)丰富的在线文档和社区支持丰富的在线文档和社区支持社区支持活跃的官方和社区支持基本的官方和社区支持广泛的社区支持广泛的社区支持\n安装与配置\n\n**下载:**从 PowerShell GitHub 页面 下载最新的 PowerShell 安装包。\n**安装:**使用包管理器或者双击安装包,并按照提示进行安装。\n**运行:**安装完成后Windows 可以通过 Start 菜单启动 PowerShell类 Unix 系统可以通过终端输入 pwsh 启动 PowerShell。\n**更新:**可以通过 Update-Help 命令更新帮助文件,以便获取最新的帮助文档。\n设置执行策略可选PowerShell 的执行策略决定了脚本能否在系统上运行。可以使用 Set-ExecutionPolicy RemoteSigned 允许本地脚本和从受信任来源下载的脚本运行。\n\n基础命令与语法\n命令基础\nPowerShell 中的命令被称为 cmdlet发音为 “command-let”。每个 cmdlet 通常由一个动词和一个名词组成,例如 Get-Process、Set-Location。cmdlet 具有一致的命名规范和结构,使得命令的学习和使用更加直观和简单。可以通过以下命令获取系统中的所有 cmdlet 列表:\nGet-Command\n此外Get-Command 还可以用于查找特定的命令或 cmdlet。例如要查找所有与 “process” 相关的命令,可以使用:\nGet-Command *process*\ncmdlet 结构(动词 - 名词)\n**PowerShell 的 cmdlet 以 “动词-名词” 形式命名,动词描述动作,名词描述操作对象。**例如:\nGet-Process # 获取当前运行的进程\nSet-Location # 设置当前工作目录\n常见动词\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n动词用途说明示例Get获取信息或对象Get-Process 获取当前运行的进程Set设置或配置对象Set-Location 设置当前工作目录New创建新的对象New-Item 创建新文件或目录Remove删除对象Remove-Item 删除文件或目录Start启动操作或进程Start-Process 启动一个进程Stop停止操作或进程Stop-Process 停止一个进程Restart重启操作或进程Restart-Service 重启服务Test测试或验证操作Test-Connection 测试网络连接Invoke执行操作Invoke-Command 执行命令Export导出数据或对象Export-Csv 导出到 CSV 文件Import导入数据或对象Import-Csv 从 CSV 文件导入数据Out输出数据到目标Out-File 输出到文件Write写入数据到目标Write-Output 写入输出流Read读取数据Read-Host 从用户输入读取数据Enable启用对象Enable-PSRemoting 启用远程处理Disable禁用对象Disable-PSRemoting 禁用远程处理Clear清除数据或对象Clear-Content 清除文件内容Select选择数据或对象Select-Object 选择对象的属性Measure计算或测量数据Measure-Object 计算对象的属性Compare比较数据或对象Compare-Object 比较对象Convert转换数据格式ConvertTo-Json 转换为 JSON 格式Sort排序数据Sort-Object 对对象进行排序Group分组数据Group-Object 对对象进行分组Join连接数据Join-Path 连接路径Split分割数据Split-Path 分割路径\n管道Pipeline和对象流\nPowerShell 的一个重要特性是管道Pipeline允许将一个 cmdlet 的输出直接传递给下一个 cmdlet 作为输入。管道在 PowerShell 中不仅传递文本,还可以传递对象,这使得数据处理更加直观和灵活。例如:\n# 上获取所有进程,并筛选出 CPU 使用率大于 100 的进程。\nGet-Process | Where-Object { $_.CPU -gt 100 }\n在这个示例中Get-Process cmdlet 的输出传递给 Where-Object cmdlet 进行过滤。$_ 是管道中的当前对象,$_ 后面可以跟对象的属性进行操作。\n管道的另一个常见用法是将多个 cmdlet 串联起来以完成复杂任务。例如:\n# 获取所有运行的服务,筛选出已停止的服务,并重新启动它们\nGet-Service | Where-Object { $_.Status -eq 'Stopped' } | Start-Service\n获取帮助和使用 Get-Help\nPowerShell 提供了强大的内置帮助系统,可以通过 Get-Help 命令获取详细的帮助信息。Get-Help 是学习和查找 cmdlet 详细信息的最佳方式。例如,要了解 Get-Process cmdlet可以使用\nGet-Help Get-Process\n使用 Update-Help 命令可以更新本地的帮助文件,以确保获取到最新的帮助信息:\nUpdate-Help\n核心概念\n变量\n在 PowerShell 中,变量以 $ 符号开头,并且是动态类型的。这意味着你可以在变量中存储任何类型的数据,而无需提前声明变量的类型。定义和使用变量的示例如下:\n# 定义变量\n$name = "John"\n$age = 30\n$fruits = @("Apple", "Banana", "Cherry")\n \n# 使用变量\nWrite-Output "Name: $name, Age: $age"\nWrite-Output "Fruits: $($fruits -join ', ')"\n数据类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据类型描述示例字符串String文本数据$string = "Hello, World!"整数Integer整数型数值$integer = 42浮点数Float浮点型数值$float = 3.14数组Array有序集合$array = @(1, 2, 3, 4, 5)哈希表Hashtable键值对集合$hashtable = @{ Name = "Alice"; Age = 25 }\n算术运算符\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述示例+加法$a + $b-减法$a - $b*乘法$a * $b/除法$a / $b%取模(余数)$a % $b\n比较运算符\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述示例-eq等于$a -eq $b-ne不等于$a -ne $b-gt大于$a -gt $b-ge大于或等于$a -ge $b-lt小于$a -lt $b-le小于或等于$a -le $b\n逻辑运算符\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述示例-and与$a -and $b-or或$a -or $b-not非-not $a\n特殊运算符\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述示例-match正则表达式匹配$string -match "Power"-like通配符匹配$string -like "Power*"-contains检查数组是否包含元素$array -contains 3\n流程控制\n条件语句\nif/else 语句\nif 语句用于根据条件执行不同的代码块。else 和 elseif 子句可以用于添加更多条件:\n$a = 10\n \nif ($a -gt 5) {\n Write-Output "a is greater than 5"\n} elseif ($a -eq 5) {\n Write-Output "a is equal to 5"\n} else {\n Write-Output "a is less than 5"\n}\nswitch 语句\nswitch 语句用于根据多个条件执行不同的代码块,可以替代多个 if/else 语句:\n$day = "Tuesday"\n \nswitch ($day) {\n "Monday" { Write-Output "Today is Monday" }\n "Tuesday" { Write-Output "Today is Tuesday" }\n "Wednesday" { Write-Output "Today is Wednesday" }\n default { Write-Output "Today is another day" }\n}\n循环语句\nfor 循环\nfor 循环用于执行一组语句一定次数,通常用于需要明确循环次数的情况:\nfor ($i = 0; $i -lt 5; $i++) {\n Write-Output "Iteration $i"\n}\nforeach 循环\nforeach 循环用于遍历数组或集合中的每个元素:\n$array = @(1, 2, 3, 4, 5)\n \nforeach ($item in $array) {\n Write-Output "Item: $item"\n}\nwhile 循环\nwhile 循环在指定条件为真时重复执行一组语句。适用于条件未知,需要动态检查的情况:\n$i = 0\n \nwhile ($i -lt 5) {\n Write-Output "Iteration $i"\n $i++\n}\ndo-while 循环\ndo-while 循环与 while 循环类似,但它至少会执行一次循环体,然后在循环体末尾检查条件:\n$i = 0\n \ndo {\n Write-Output "Iteration $i"\n $i++\n} while ($i -lt 5)\n脚本编写\nPowerShell 脚本文件的扩展名为 .ps1。可以使用任何文本编辑器编写脚本然后在 PowerShell 控制台中运行:\n# 示例脚本hello.ps1\n$name = "World"\nWrite-Output "Hello, $name!"\n在 PowerShell 控制台中执行脚本:\n.\\hello.ps1\n脚本参数和参数化脚本\n可以通过 param 关键字定义脚本参数,使脚本更灵活和可重用:\n# 示例脚本greet.ps1\nparam (\n [string]$name = "World"\n)\nWrite-Output "Hello, $name!"\n在 PowerShell 控制台中传递参数执行脚本:\n.\\greet.ps1 -name "Alice"\n注释和文档\n使用 # 符号添加单行注释,使用 <# ... #> 添加多行注释:\n# 这是单行注释\nWrite-Output "This is a single-line comment."\n \n<#\n这是多行注释\n可以跨越多行\n#>\nWrite-Output "This is a multi-line comment."\n良好的注释习惯可以提高脚本的可读性和维护性。例如\n# 定义变量\n$name = "PowerShell" # 变量存储名称\n \n# 输出问候信息\nWrite-Output "Hello, $name!" # 打印问候信息\n示例代码\n以下是一个示例代码展示了如何使用常见的数据类型和运算符并结合条件语句和循环语句获取并输出计算机的相关信息。代码包含详细的注释以帮助理解\n# 定义变量\n$computerName = "LocalHost" # 计算机名称\n$memoryThreshold = 4 # 内存阈值GB\n \n# 获取计算机的基本信息\n$os = Get-WmiObject -Class Win32_OperatingSystem\n$cpu = Get-WmiObject -Class Win32_Processor\n$memory = Get-WmiObject -Class Win32_PhysicalMemory\n \n# 输出计算机基本信息\nWrite-Output "Computer Name: $computerName"\nWrite-Output "Operating System: $($os.Caption)"\nWrite-Output "OS Version: $($os.Version)"\nWrite-Output "CPU: $($cpu.Name)"\nWrite-Output "Total Physical Memory: $([math]::round($os.TotalVisibleMemorySize / 1MB, 2)) GB"\n \n# 检查物理内存是否低于阈值\n$totalMemoryGB = [math]::round($os.TotalVisibleMemorySize / 1MB, 2)\n \nif ($totalMemoryGB -lt $memoryThreshold) {\n Write-Output "Warning: Physical memory is below the threshold of $memoryThreshold GB."\n} else {\n Write-Output "Physical memory is above the threshold."\n}\n \n# 使用 foreach 循环遍历和输出每条物理内存的信息\nWrite-Output "Detailed Physical Memory Info:"\nforeach ($mem in $memory) {\n $memCapacityGB = [math]::round($mem.Capacity / 1GB, 2)\n Write-Output "Memory Module: $($mem.DeviceLocator), Capacity: $memCapacityGB GB"\n}\n \n# 使用 for 循环计算并输出每个逻辑磁盘的总大小和可用空间\n$logicalDisks = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" # 仅获取本地磁盘\n \nfor ($i = 0; $i -lt $logicalDisks.Count; $i++) {\n $disk = $logicalDisks[$i]\n $totalSizeGB = [math]::round($disk.Size / 1GB, 2)\n $freeSpaceGB = [math]::round($disk.FreeSpace / 1GB, 2)\n Write-Output "Drive: $($disk.DeviceID), Total Size: $totalSizeGB GB, Free Space: $freeSpaceGB GB"\n}\n \n# 使用 while 循环等待特定进程启动示例notepad.exe\n$processName = "notepad.exe"\nWrite-Output "Waiting for $processName to start..."\nwhile (-not (Get-Process -Name "notepad" -ErrorAction SilentlyContinue)) {\n Start-Sleep -Seconds 2\n}\nWrite-Output "$processName has started."\n \n# 使用 switch 语句输出当前操作系统类型\nswitch ($os.Caption) {\n "Microsoft Windows 10 Pro" { Write-Output "You are running Windows 10 Pro." }\n "Microsoft Windows Server 2019" { Write-Output "You are running Windows Server 2019." }\n default { Write-Output "Operating system not recognized." }\n}\n \nWrite-Output "Script execution completed."\n "},"Technology/GettingStarted/命令行工具/PowerShell/PowerShell-进阶":{"title":"PowerShell 进阶","links":[],"tags":["技术/入门","PowerShell"],"content":"函数\n函数定义和调用\n在 PowerShell 中,函数是一段可以重复使用的代码块。定义函数使用 function 关键字:\nfunction Get-Greeting {\n Write-Output "Hello, World!"\n}\n \n# 调用函数\nGet-Greeting\n函数参数\n函数可以接受参数使其更通用和灵活。可以通过 param 关键字定义参数:\nfunction Get-Greeting {\n param (\n [string]$name = "World"\n )\n Write-Output "Hello, $name!"\n}\n \n# 调用函数并传递参数\nGet-Greeting -name "Alice"\n返回值\n函数可以返回值这使得它们可以用于复杂的计算和逻辑操作\nfunction Add-Numbers {\n param (\n [int]$a,\n [int]$b\n )\n return $a + $b\n}\n \n# 调用函数并获取返回值\n$result = Add-Numbers -a 5 -b 3\nWrite-Output "The sum is: $result"\n高级函数功能\n\n高级参数设置通过 Parameter 特性定义参数属性,例如 Mandatory 和 Position。\n支持管道输入使用 ValueFromPipeline 参数特性允许函数接收管道输入。\n\nfunction Get-Square {\n [CmdletBinding()]\n param (\n [Parameter(Mandatory, ValueFromPipeline)]\n [int]$number\n )\n process {\n return $number * $number\n }\n}\n \n# 使用管道输入\n1..5 | Get-Square\n模块\n模块是什么\n模块是 PowerShell 中的一种打包方式允许将相关的函数、cmdlet、变量和其他资源组织在一起以便重用和共享。模块可以帮助你管理和分发 PowerShell 代码。\n创建和使用模块\n创建一个模块只需将相关的函数和代码放在一个 .psm1 文件中。以下是一个简单模块的示例:\n\n创建一个名为 MyModule.psm1 的文件,并添加以下内容:\n\nfunction Get-Greeting {\n param (\n [string]$name = "World"\n )\n Write-Output "Hello, $name!"\n}\n\n将模块文件放在一个文件夹中并将文件夹命名为模块的名称例如 MyModule。\n使用模块\n\n# 确保模块文件夹路径包含在 $env:PSModulePath 中\nImport-Module -Name "MyModule"\n \n# 使用模块中的函数\nGet-Greeting -name "Alice"\nImport-Module 和 Export-Module\n\nImport-Module用于加载模块使其中定义的命令和功能可用。\n\nImport-Module -Name "MyModule"\n\nExport-ModuleMember用于指定哪些函数、变量或别名可以导出并供模块使用者使用。添加到 .psm1 文件中:\n\nfunction Get-Greeting {\n param (\n [string]$name = "World"\n )\n Write-Output "Hello, $name!"\n}\n \nExport-ModuleMember -Function Get-Greeting\n示例创建和使用模块\n以下是一个完整示例展示如何创建和使用模块\n\n创建模块文件夹 MyModule。\n在模块文件夹中创建 MyModule.psm1 文件,内容如下:\n\nfunction Get-Greeting {\n param (\n [string]$name = "World"\n )\n Write-Output "Hello, $name!"\n}\n \nExport-ModuleMember -Function Get-Greeting\n\n在 PowerShell 中导入并使用模块:\n\n# 设置模块路径(如果需要)\n$env:PSModulePath += ";C:\\Path\\To\\Your\\Module\\Directory"\n \n# 导入模块\nImport-Module -Name "MyModule"\n \n# 使用模块中的函数\nGet-Greeting -name "Alice"\n模块发布\n可以将模块发布到 PowerShell Gallery 或私有仓库,方便其他用户安装和使用。\n# 将模块发布到 PowerShell Gallery\nPublish-Module -Name "MyModule" -NuGetApiKey "YourApiKey"\n错误处理\n错误处理基础try/catch/finally\n在 PowerShell 中,可以使用 try, catch 和 finally 语句来处理脚本中的错误。\ntry {\n # 尝试执行的代码\n $result = Get-Process -Name "Notepad"\n Write-Output "Process found: $($result.Name)"\n} catch {\n # 捕获错误并处理\n Write-Output "An error occurred: $_"\n} finally {\n # 无论是否发生错误都会执行的代码\n Write-Output "Completed the error handling section."\n}\n捕获和处理异常\ncatch 块可以捕获不同类型的异常,并根据异常类型采取相应的处理措施。\ntry {\n # 尝试执行的代码\n $result = Get-Process -Name "Notepad"\n Write-Output "Process found: $($result.Name)"\n} catch [System.Management.Automation.CommandNotFoundException] {\n Write-Output "Command not found: $_"\n} catch [System.Exception] {\n Write-Output "General error: $_"\n}\n自定义错误处理\n可以自定义错误处理逻辑使脚本更具健壮性和用户友好性。\nfunction Get-ProcessInfo {\n param (\n [string]$processName\n )\n try {\n $process = Get-Process -Name $processName -ErrorAction Stop\n Write-Output "Process Name: $($process.Name)"\n Write-Output "CPU Usage: $($process.CPU)"\n } catch {\n Write-Output "Error: Process '$processName' not found."\n }\n}\n \nGet-ProcessInfo -processName "Notepad"\n调试\n使用断点调试脚本\n可以在脚本中设置断点以便逐步执行和调试代码。\n# 设置断点\nSet-PSBreakpoint -Script "C:\\Path\\To\\YourScript.ps1" -Line 5\n \n# 启动调试\nGet-Process\n \n# 移除断点\nRemove-PSBreakpoint -Id 0\n调试命令和技巧\nPowerShell 提供了一些用于调试脚本的命令和技巧:\n\nGet-PSBreakpoint查看当前设置的断点。\nEnable-PSBreakpoint 和 Disable-PSBreakpoint启用或禁用断点。\nStep-Into、Step-Over 和 Step-Out逐步执行代码。\nGet-PSCallStack查看当前调用堆栈。\n\n# 调试示例\nfunction Test-Debug {\n param ($a, $b)\n $sum = $a + $b\n Write-Output "Sum: $sum"\n}\n \n# 设置断点在函数的第一行\nSet-PSBreakpoint -Script "C:\\Path\\To\\YourScript.ps1" -Command "Test-Debug"\n \n# 调用函数,触发断点\nTest-Debug -a 5 -b 10\n调试日志\n使用 Write-Debug 和 Write-Verbose 命令输出调试信息和详细信息。\nfunction Test-Logging {\n [CmdletBinding()]\n param (\n [string]$message\n )\n Write-Debug "Debug: $message"\n Write-Verbose "Verbose: $message"\n}\n \n# 调用函数并启用调试和详细输出\nTest-Logging -message "Test message" -Debug -Verbose\n性能优化\n提升脚本性能的方法\n优化脚本性能可以显著提高执行效率。以下是一些提升性能的方法\n\n避免不必要的循环和递归。\n使用高效的 cmdlet 和操作,例如 Measure-Command 来衡量代码块的执行时间。\n尽量减少对外部资源的访问例如磁盘 I/O 操作。\n使用变量缓存重复计算的值。\n\n# 示例:使用 Measure-Command 测量执行时间\nMeasure-Command {\n $sum = 0\n for ($i = 0; $i -lt 1000000; $i++) {\n $sum += $i\n }\n}\n性能监控工具\nPowerShell 提供了一些工具来监控和分析脚本性能:\n\nMeasure-Command测量代码块的执行时间。\nMeasure-Object测量对象的属性例如长度、平均值、最大值、最小值。\nGet-EventLog 和 Get-WinEvent检查系统事件日志分析脚本对系统资源的影响。\n\n# 使用 Measure-Object 统计数据\n$data = 1..100\n$data | Measure-Object -Sum -Average -Maximum -Minimum\n内存管理\n在处理大量数据时优化内存使用也是提升性能的关键。可以通过以下方法进行内存管理\n\n使用 [System.Collections.Generic.List[<Type>]] 代替数组,以减少内存分配和复制。\n在处理大型文本文件时使用流式读取Get-Content -ReadCount来减少内存占用。\n\n# 示例:使用流式读取处理大型文本文件\nGet-Content -Path "largefile.txt" -ReadCount 1000 | ForEach-Object {\n # 处理每批次的行\n $_ | ForEach-Object { \n # 处理单行\n Write-Output $_ \n }\n}"},"Technology/GettingStarted/命令行工具/PowerShell/PowerShell-高级":{"title":"PowerShell 高级","links":[],"tags":["技术/入门","PowerShell"],"content":"文件系统管理\n管理文件和文件夹\nPowerShell 提供了丰富的命令来管理文件和文件夹,包括创建、删除、复制、移动和重命名文件和文件夹。\n创建文件和文件夹\n可以使用 New-Item 命令来创建文件和文件夹:\n# 创建文件夹\nNew-Item -Path "C:\\Example" -ItemType Directory\n \n# 创建文件\nNew-Item -Path "C:\\Example\\file.txt" -ItemType File\n删除文件和文件夹\n可以使用 Remove-Item 命令来删除文件和文件夹:\n# 删除文件\nRemove-Item -Path "C:\\Example\\file.txt"\n \n# 删除文件夹及其所有内容\nRemove-Item -Path "C:\\Example" -Recurse\n复制和移动文件\n可以使用 Copy-Item 和 Move-Item 命令来复制和移动文件:\n# 复制文件\nCopy-Item -Path "C:\\Example\\file.txt" -Destination "C:\\Example\\copy_of_file.txt"\n \n# 移动文件\nMove-Item -Path "C:\\Example\\file.txt" -Destination "C:\\Example\\moved_file.txt"\n重命名文件和文件夹\n可以使用 Rename-Item 命令来重命名文件和文件夹:\n# 重命名文件\nRename-Item -Path "C:\\Example\\moved_file.txt" -NewName "renamed_file.txt"\n文件内容的读取和写入\nPowerShell 提供了便捷的方法来读取和写入文件内容。\n读取文件内容\n可以使用 Get-Content 命令来读取文件内容:\n# 读取文件内容\nGet-Content -Path "C:\\Example\\file.txt"\n写入文件内容\n可以使用 Set-Content 和 Add-Content 命令来写入和追加文件内容:\n# 写入文件内容\nSet-Content -Path "C:\\Example\\file.txt" -Value "Hello, World!"\n \n# 追加文件内容\nAdd-Content -Path "C:\\Example\\file.txt" -Value "This is an appended line."\n搜索文件和文件夹\n可以使用 Get-ChildItem 命令来搜索文件和文件夹。支持通配符和递归搜索。\n# 搜索当前目录下的所有文件\nGet-ChildItem -Path "C:\\Example"\n \n# 搜索当前目录及其子目录下的所有文件\nGet-ChildItem -Path "C:\\Example" -Recurse\n \n# 使用通配符搜索特定类型的文件\nGet-ChildItem -Path "C:\\Example\\*.txt"\n文件属性和权限管理\n可以使用 Get-Item 和 Set-ItemProperty 命令来获取和设置文件属性,以及使用 Get-Acl 和 Set-Acl 命令来管理文件权限。\n获取和设置文件属性\n# 获取文件属性\n$file = Get-Item -Path "C:\\Example\\file.txt"\n$file.Attributes\n \n# 设置文件为只读\nSet-ItemProperty -Path "C:\\Example\\file.txt" -Name Attributes -Value ReadOnly\n管理文件权限\n# 获取文件权限\n$acl = Get-Acl -Path "C:\\Example\\file.txt"\n$acl\n \n# 设置文件权限\n$acl.SetAccessRuleProtection($true, $false) # 禁用继承\n$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "Read", "Allow")\n$acl.AddAccessRule($rule)\nSet-Acl -Path "C:\\Example\\file.txt" -AclObject $acl\n压缩和解压文件\n可以使用 Compress-Archive 和 Expand-Archive 命令来压缩和解压文件。\n压缩文件\n# 压缩文件到 zip\nCompress-Archive -Path "C:\\Example\\file.txt" -DestinationPath "C:\\Example\\archive.zip"\n解压文件\n# 解压 zip 文件\nExpand-Archive -Path "C:\\Example\\archive.zip" -DestinationPath "C:\\Example\\Unzipped"\n管理临时文件和文件夹\nPowerShell 提供了一些命令来管理临时文件和文件夹。\n创建临时文件和文件夹\n# 创建临时文件\n$tempFile = [System.IO.Path]::GetTempFileName()\nNew-Item -Path $tempFile -ItemType File\n \n# 创建临时文件夹\n$tempFolder = [System.IO.Path]::GetTempPath() + [System.Guid]::NewGuid().ToString()\nNew-Item -Path $tempFolder -ItemType Directory\n注册表管理\nPowerShell 可以读取和修改 Windows 注册表项,用于系统配置和管理。注册表操作涉及到读取、修改、新建和删除注册表项,以及管理注册表值和权限。\n注册表概述\nWindows 注册表是一个层次化数据库,存储了有关系统、硬件、用户配置和软件的信息。注册表包含多个根键,每个根键存储不同类型的信息:\n\nHKEY_LOCAL_MACHINE (HKLM):存储计算机的硬件、软件、操作系统和安全性等全局设置,对所有用户生效。\nHKEY_CURRENT_USER (HKCU):存储当前登录用户的配置信息和用户特定的设置。\nHKEY_CLASSES_ROOT (HKCR):存储文件类型关联和 OLE 对象的配置信息。\nHKEY_USERS (HKU):存储计算机上所有用户的配置信息,每个用户对应一个子键。\nHKEY_CURRENT_CONFIG (HKCC):存储当前硬件配置文件的信息。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n根键常见子键示例HKEY_LOCAL_MACHINE (HKLM)SYSTEM系统配置信息包括硬件设置、驱动程序和服务。SOFTWARE安装在计算机上的软件和应用程序的信息。SECURITY安全策略和权限设置。SAM安全帐户管理数据库的配置信息。HARDWARE硬件抽象层和即插即用管理的信息。HKEY_CURRENT_USER (HKCU)Software用户安装的软件和应用程序的配置信息。Control Panel用户的控制面板设置如桌面背景和显示设置。Environment用户环境变量。Network网络连接和配置的信息。Printers用户的打印机和打印设置。HKEY_CLASSES_ROOT (HKCR)*\\shell定义了所有文件类型的右键菜单命令。file特定文件类型的关联设置。CLSID类标识符的配置信息。Interface接口标识符的配置信息。HKEY_USERS (HKU)S-1-5-18LocalSystem 账户的设置。S-1-5-19LocalService 账户的设置。S-1-5-20NetworkService 账户的设置。S-1-5-21-<User-SID>特定用户的配置信息。HKEY_CURRENT_CONFIG (HKCC)System系统硬件配置文件。Software与当前硬件配置相关的软件设置。\n读取和修改注册表项\n读取注册表项\n可以使用 Get-ItemProperty 命令读取注册表项的值。\n# 读取注册表项值\nGet-ItemProperty -Path "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"\n修改注册表项\n可以使用 Set-ItemProperty 命令修改注册表项的值。\n# 修改注册表项值\nSet-ItemProperty -Path "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" -Name "Maximize" -Value 1\n新建和删除注册表项\n可以使用 New-Item 和 Remove-Item 命令来新建和删除注册表项。\n# 新建注册表项\nNew-Item -Path "HKCU:\\Software\\MyCompany"\n \n# 删除注册表项\nRemove-Item -Path "HKCU:\\Software\\MyCompany" -Recurse\n新建和删除注册表值\n可以使用 New-ItemProperty 和 Remove-ItemProperty 命令来新建和删除注册表值。\n# 新建注册表值\nNew-ItemProperty -Path "HKCU:\\Software\\MyCompany" -Name "MyValue" -Value "TestValue" -PropertyType String\n \n# 删除注册表值\nRemove-ItemProperty -Path "HKCU:\\Software\\MyCompany" -Name "MyValue"\n管理注册表权限\n可以使用 Get-Acl 和 Set-Acl 命令来获取和设置注册表项的权限。\n获取注册表项权限\n# 获取注册表项权限\n$acl = Get-Acl -Path "HKCU:\\Software\\MyCompany"\n$acl\n设置注册表项权限\n# 设置注册表项权限\n$acl = Get-Acl -Path "HKCU:\\Software\\MyCompany"\n$rule = New-Object System.Security.AccessControl.RegistryAccessRule("Everyone", "FullControl", "Allow")\n$acl.SetAccessRule($rule)\nSet-Acl -Path "HKCU:\\Software\\MyCompany" -AclObject $acl\n备份和还原注册表项\n可以使用 reg.exe 命令来备份和还原注册表项。\n备份注册表项\n# 备份注册表项到文件\nreg export "HKCU\\Software\\MyCompany" "C:\\Backup\\MyCompany.reg"\n还原注册表项\n# 从文件还原注册表项\nreg import "C:\\Backup\\MyCompany.reg"\n进程和服务管理\nPowerShell 提供了强大的功能来管理系统进程和 Windows 服务。\n管理系统进程\n获取进程信息\n可以使用 Get-Process 命令来获取系统中运行的所有进程的信息,或获取特定进程的信息。\n# 获取所有进程信息\nGet-Process\n \n# 获取特定进程信息\nGet-Process -Name "notepad"\n启动和停止进程\n可以使用 Start-Process 命令来启动进程,使用 Stop-Process 命令来停止进程。\n# 启动进程\nStart-Process -FilePath "notepad.exe"\n \n# 停止进程\nStop-Process -Name "notepad"\n获取和管理进程详细信息\n可以获取进程的详细信息如内存使用情况、CPU 使用率等,还可以暂停和恢复进程。\n# 获取进程的详细信息\nGet-Process -Name "notepad" | Select-Object -Property Name, Id, CPU, WS\n \n# 暂停进程\nSuspend-Process -Name "notepad"\n \n# 恢复进程\nResume-Process -Name "notepad"\n管理 Windows 服务\nPowerShell 提供了全面的命令来管理 Windows 服务,包括获取服务信息、启动和停止服务、设置服务启动类型等。\n获取服务信息\n可以使用 Get-Service 命令来获取系统中的所有服务的信息,或获取特定服务的信息。\n# 获取所有服务信息\nGet-Service\n \n# 获取特定服务信息\nGet-Service -Name "wuauserv"\n启动和停止服务\n可以使用 Start-Service 和 Stop-Service 命令来启动和停止服务。\n# 启动服务\nStart-Service -Name "wuauserv"\n \n# 停止服务\nStop-Service -Name "wuauserv"\n重启服务\n可以使用 Restart-Service 命令来重启服务。\n# 重启服务\nRestart-Service -Name "wuauserv"\n设置服务的启动类型\n可以使用 Set-Service 命令来设置服务的启动类型,例如设置为自动启动或手动启动。\n# 将服务设置为自动启动\nSet-Service -Name "wuauserv" -StartupType Automatic\n \n# 将服务设置为手动启动\nSet-Service -Name "wuauserv" -StartupType Manual\n管理服务依赖项\n可以使用 sc.exe 命令来设置服务的依赖项,使服务在启动时依赖于其他服务。\n# 设置服务依赖于其他服务\nsc.exe config "MyService" depend= "OtherService"\nWindows 服务管理\nWindows 服务是运行在 Windows 操作系统上的长期运行进程,通常在系统启动时自动启动,并在后台运行。使用 PowerShell 可以方便地创建、管理和配置 Windows 服务。\n创建 Windows 服务\n创建 Windows 服务通常需要以下步骤:\n\n编写服务应用程序通常使用 C# 或其他编程语言)。\n使用 PowerShell 注册服务。\n\n编写服务应用程序\n你需要编写一个可以作为服务运行的应用程序。以下是一个简单的 C# 服务示例:\ncsharp复制代码using System;\nusing System.ServiceProcess;\nusing System.IO;\n \npublic class MyService : ServiceBase\n{\n private FileSystemWatcher watcher;\n \n public MyService()\n {\n ServiceName = "MyService";\n }\n \n protected override void OnStart(string[] args)\n {\n watcher = new FileSystemWatcher();\n watcher.Path = "C:\\\\PathToWatch";\n watcher.Created += OnChanged;\n watcher.EnableRaisingEvents = true;\n File.AppendAllText("C:\\\\ServiceLog.txt", "Service started at " + DateTime.Now + Environment.NewLine);\n }\n \n private void OnChanged(object sender, FileSystemEventArgs e)\n {\n File.AppendAllText("C:\\\\ServiceLog.txt", $"File created: {e.FullPath} at {DateTime.Now}" + Environment.NewLine);\n }\n \n protected override void OnStop()\n {\n watcher.Dispose();\n File.AppendAllText("C:\\\\ServiceLog.txt", "Service stopped at " + DateTime.Now + Environment.NewLine);\n }\n \n public static void Main()\n {\n ServiceBase.Run(new MyService());\n }\n}\n编译此 C# 代码,生成一个可执行文件(如 MyService.exe。\n使用 PowerShell 注册服务\n编写完服务应用程序后可以使用 PowerShell 注册服务:\n# 定义服务名称和路径\n$serviceName = "MyService"\n$serviceExePath = "C:\\Path\\To\\MyService.exe"\n \n# 使用 sc.exe 创建服务\nsc.exe create $serviceName binPath= $serviceExePath\n \n# 启动服务\nStart-Service -Name $serviceName\n \n# 检查服务状态\nGet-Service -Name $serviceName\n配置和管理 Windows 服务\n使用 PowerShell可以方便地管理 Windows 服务,包括启动、停止、重启和删除服务,以及配置服务的启动类型和依赖项。\n启动和停止服务\n# 启动服务\nStart-Service -Name "MyService"\n \n# 停止服务\nStop-Service -Name "MyService"\n重启服务\n# 重启服务\nRestart-Service -Name "MyService"\n删除服务\n# 停止并删除服务\nStop-Service -Name "MyService"\nsc.exe delete "MyService"\n修改服务启动类型\n# 将服务设置为自动启动\nSet-Service -Name "MyService" -StartupType Automatic\n \n# 将服务设置为手动启动\nSet-Service -Name "MyService" -StartupType Manual\n设置服务依赖项\n# 设置服务依赖于其他服务\nsc.exe config "MyService" depend= "OtherService"\n示例脚本\n以下是一个完整的示例脚本用于创建、启动、检查、重启和删除服务\n# 服务名称和路径\n$serviceName = "MyService"\n$serviceExePath = "C:\\Path\\To\\MyService.exe"\n \n# 创建服务\nsc.exe create $serviceName binPath= $serviceExePath\nWrite-Output "Service $serviceName created."\n \n# 启动服务\nStart-Service -Name $serviceName\nWrite-Output "Service $serviceName started."\n \n# 检查服务状态\n$serviceStatus = Get-Service -Name $serviceName\nWrite-Output "Service $serviceName status: $($serviceStatus.Status)"\n \n# 重启服务\nRestart-Service -Name $serviceName\nWrite-Output "Service $serviceName restarted."\n \n# 删除服务\nStop-Service -Name $serviceName\nsc.exe delete $serviceName\nWrite-Output "Service $serviceName deleted."\n用户和权限管理\nPowerShell 提供了管理用户账户、组和权限的功能,帮助管理员高效地管理 Windows 系统的安全和用户权限。\n用户和组的管理\nPowerShell 提供了一系列命令来管理本地用户和组,包括创建、删除和修改用户和组的属性。\n创建和删除用户\n使用 New-LocalUser 命令可以创建新用户,使用 Remove-LocalUser 命令可以删除用户。\n# 创建新用户\nNew-LocalUser -Name "NewUser" -Password (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -FullName "New User" -Description "This is a new user."\n \n# 删除用户\nRemove-LocalUser -Name "NewUser"\n创建和删除组\n使用 New-LocalGroup 命令可以创建新组,使用 Remove-LocalGroup 命令可以删除组。\n# 创建新组\nNew-LocalGroup -Name "NewGroup" -Description "This is a new group."\n \n# 删除组\nRemove-LocalGroup -Name "NewGroup"\n将用户添加到组\n使用 Add-LocalGroupMember 命令可以将用户添加到组,使用 Remove-LocalGroupMember 命令可以将用户从组中移除。\n# 将用户添加到组\nAdd-LocalGroupMember -Group "Administrators" -Member "NewUser"\n \n# 将用户从组中移除\nRemove-LocalGroupMember -Group "Administrators" -Member "NewUser"\n查看用户和组信息\n使用 Get-LocalUser 命令可以查看用户信息,使用 Get-LocalGroup 命令可以查看组信息。\n# 查看所有本地用户\nGet-LocalUser\n \n# 查看特定用户信息\nGet-LocalUser -Name "NewUser"\n \n# 查看所有本地组\nGet-LocalGroup\n \n# 查看特定组信息\nGet-LocalGroup -Name "Administrators"\n权限设置\nPowerShell 提供了管理文件和文件夹权限的功能,可以查看和修改文件系统 ACL访问控制列表。\n查看文件和文件夹权限\n使用 Get-Acl 命令可以查看文件和文件夹的权限。\n# 查看文件权限\nGet-Acl -Path "C:\\Example\\file.txt"\n \n# 查看文件夹权限\nGet-Acl -Path "C:\\Example"\n修改文件和文件夹权限\n可以使用 Set-Acl 命令来修改文件和文件夹的权限。需要先获取现有的 ACL然后添加或修改权限规则最后应用新的 ACL。\n# 获取现有权限\n$acl = Get-Acl -Path "C:\\Example\\file.txt"\n \n# 定义新的权限规则\n$permission = "DOMAIN\\Username", "FullControl", "Allow"\n$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission\n \n# 添加权限规则\n$acl.SetAccessRule($accessRule)\n \n# 应用新的权限设置\nSet-Acl -Path "C:\\Example\\file.txt" -AclObject $acl\n删除文件和文件夹权限\n可以删除特定的权限规则。\n# 获取现有权限\n$acl = Get-Acl -Path "C:\\Example\\file.txt"\n \n# 定义要删除的权限规则\n$permission = "DOMAIN\\Username", "FullControl", "Allow"\n$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission\n \n# 删除权限规则\n$acl.RemoveAccessRule($accessRule)\n \n# 应用新的权限设置\nSet-Acl -Path "C:\\Example\\file.txt" -AclObject $acl\n递归修改文件夹权限\n可以递归修改文件夹及其子文件夹和文件的权限。\n# 获取文件夹及其子文件夹和文件\n$items = Get-ChildItem -Path "C:\\Example" -Recurse\n \n# 修改每个项目的权限\nforeach ($item in $items) {\n $acl = Get-Acl -Path $item.FullName\n $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ("DOMAIN\\Username", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")\n $acl.SetAccessRule($accessRule)\n Set-Acl -Path $item.FullName -AclObject $acl\n}\n远程用户和权限管理\nPowerShell 还提供了远程管理用户和权限的功能,通过 PowerShell Remoting 可以管理远程计算机上的用户和权限。\n启用 PowerShell Remoting\n# 启用 PowerShell Remoting\nEnable-PSRemoting -Force\n远程执行命令\n可以使用 Invoke-Command 命令在远程计算机上执行用户和权限管理命令。\n# 在远程计算机上创建用户\nInvoke-Command -ComputerName "RemoteComputer" -ScriptBlock {\n New-LocalUser -Name "RemoteUser" -Password (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -FullName "Remote User" -Description "This is a remote user."\n}\n \n# 在远程计算机上设置文件权限\nInvoke-Command -ComputerName "RemoteComputer" -ScriptBlock {\n $acl = Get-Acl -Path "C:\\RemoteExample\\file.txt"\n $permission = "DOMAIN\\Username", "FullControl", "Allow"\n $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission\n $acl.SetAccessRule($accessRule)\n Set-Acl -Path "C:\\RemoteExample\\file.txt" -AclObject $acl\n}\n网络管理\nPowerShell 提供了强大的工具来管理和配置网络包括查看和设置网络适配器、IP 地址、DNS 服务器以及测试网络连接。还可以通过 PowerShell 进行远程管理。\n网络配置\n获取和设置网络配置\nPowerShell 提供了丰富的 cmdlet 来获取和设置网络配置,包括查看网络适配器信息、配置 IP 地址等。\n获取网络适配器信息\n使用 Get-NetAdapter 命令可以查看所有网络适配器的信息,使用 Get-NetIPAddress 命令可以获取网络配置。\n# 获取所有网络适配器信息\nGet-NetAdapter\n \n# 获取特定网络适配器信息\nGet-NetAdapter -Name "Ethernet"\n获取网络配置\n# 获取所有网络适配器的 IP 配置\nGet-NetIPAddress\n \n# 获取特定网络适配器的 IP 配置\nGet-NetIPAddress -InterfaceAlias "Ethernet"\n设置网络配置\n使用 New-NetIPAddress 和 Set-DnsClientServerAddress 命令可以配置静态 IP 地址和 DNS 服务器。\n# 设置静态 IP 地址\nNew-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress "192.168.1.100" -PrefixLength 24 -DefaultGateway "192.168.1.1"\n \n# 设置 DNS 服务器\nSet-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses "8.8.8.8", "8.8.4.4"\n设置 DHCP\n使用 Remove-NetIPAddress 和 Set-DnsClientServerAddress 命令可以将网络配置改为 DHCP。\n# 移除静态 IP 地址以启用 DHCP\nRemove-NetIPAddress -InterfaceAlias "Ethernet" -Confirm:$false\n \n# 设置 DNS 服务器为自动获取\nSet-DnsClientServerAddress -InterfaceAlias "Ethernet" -ResetServerAddresses\n配置防火墙\nPowerShell 还可以用于配置防火墙规则。\n# 查看现有防火墙规则\nGet-NetFirewallRule\n \n# 新建入站规则允许 HTTP 流量\nNew-NetFirewallRule -DisplayName "Allow HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow\n \n# 新建出站规则阻止 FTP 流量\nNew-NetFirewallRule -DisplayName "Block FTP" -Direction Outbound -Protocol TCP -RemotePort 21 -Action Block\n测试网络连接\nPowerShell 提供了多种方法来测试网络连接,例如使用 Test-Connection 和 Test-NetConnection cmdlet。\n测试网络连通性\n使用 Test-Connection 命令可以测试网络连接,类似于 ping 命令。\n# 使用 Test-Connection 测试网络连接\nTest-Connection -ComputerName "www.google.com" -Count 4\n \n# 使用 Test-NetConnection 测试特定端口的网络连接\nTest-NetConnection -ComputerName "www.google.com" -Port 80\n远程管理\nPowerShell 提供了强大的远程管理功能,可以通过 WinRMWindows Remote Management和 SSH 进行远程管理。\n使用 PowerShell 进行远程管理WinRM, SSH\n启用 WinRM\n# 启用 WinRM 服务\nEnable-PSRemoting -Force\n配置 SSH\n# 安装 OpenSSH 客户端和服务器Windows 10 及以上版本)\nAdd-WindowsCapability -Online -Name OpenSSH.Client*\nAdd-WindowsCapability -Online -Name OpenSSH.Server*\n \n# 启动并配置 SSH 服务\nStart-Service sshd\nSet-Service -Name sshd -StartupType 'Automatic'\n \n# 配置防火墙规则允许 SSH 连接\nNew-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22\n使用 Invoke-Command 和 Enter-PSSession\n使用 Invoke-Command 在远程计算机上执行命令\n# 在远程计算机上执行命令\nInvoke-Command -ComputerName "RemoteComputerName" -ScriptBlock { Get-Process }\n \n# 使用凭证执行命令\n$cred = Get-Credential\nInvoke-Command -ComputerName "RemoteComputerName" -Credential $cred -ScriptBlock { Get-Process }\n使用 Enter-PSSession 进入远程会话\n# 进入远程计算机的 PowerShell 会话\nEnter-PSSession -ComputerName "RemoteComputerName"\n \n# 使用凭证进入远程会话\n$cred = Get-Credential\nEnter-PSSession -ComputerName "RemoteComputerName" -Credential $cred\n \n# 退出远程会话\nExit-PSSession\n高级网络配置\n配置网络流量控制QoS\n# 创建 QoS 策略\nNew-NetQosPolicy -Name "QoSPolicy1" -AppPathNameMatchCondition "C:\\Program Files\\ExampleApp\\Example.exe" -IPDstPortMatchCondition 80 -ThrottleRateActionBitsPerSecond 50000000\n \n# 查看现有 QoS 策略\nGet-NetQosPolicy\n \n# 删除 QoS 策略\nRemove-NetQosPolicy -Name "QoSPolicy1"\n配置路由\n# 查看路由表\nGet-NetRoute\n \n# 添加静态路由\nNew-NetRoute -DestinationPrefix "10.0.0.0/24" -NextHop "192.168.1.1" -InterfaceAlias "Ethernet"\n \n# 删除静态路由\nRemove-NetRoute -DestinationPrefix "10.0.0.0/24" -NextHop "192.168.1.1" -InterfaceAlias "Ethernet"\n通过以上内容和示例\n自动化\nPowerShell 是一个功能强大的自动化工具,可以帮助系统管理员和 IT 专业人员简化和自动化各种任务。本文将介绍如何使用 PowerShell 创建和管理计划任务,以及自动化日常管理任务的示例。\n任务计划\n使用 PowerShell 创建计划任务\nPowerShell 提供了 ScheduledTasks 模块,可以方便地创建和管理计划任务。以下是一些常见的计划任务操作示例:\n创建计划任务\n使用 New-ScheduledTaskAction、New-ScheduledTaskTrigger 和 Register-ScheduledTask 命令可以创建计划任务。\n# 定义任务动作\n$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-NoProfile -WindowStyle Hidden -File C:\\Scripts\\MyScript.ps1'\n \n# 定义触发器,每天上午 8 点执行\n$trigger = New-ScheduledTaskTrigger -Daily -At 8am\n \n# 定义任务设置\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries\n \n# 创建计划任务\nRegister-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -TaskName "MyDailyTask" -Description "My daily PowerShell script task"\n查看计划任务\n使用 Get-ScheduledTask 命令可以查看所有或特定的计划任务。\n# 获取所有计划任务\nGet-ScheduledTask\n \n# 获取特定计划任务\nGet-ScheduledTask -TaskName "MyDailyTask"\n修改计划任务\n使用 Set-ScheduledTask 命令可以修改现有计划任务的触发器、动作等。\n# 修改计划任务的触发器\n$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday,Wednesday,Friday -At 8am\nSet-ScheduledTask -TaskName "MyDailyTask" -Trigger $trigger\n删除计划任务\n使用 Unregister-ScheduledTask 命令可以删除计划任务。\n# 删除计划任务\nUnregister-ScheduledTask -TaskName "MyDailyTask" -Confirm:$false\n任务的调度和管理\n除了创建计划任务PowerShell 还可以管理任务的调度和执行情况。\n启动和停止计划任务\n# 启动计划任务\nStart-ScheduledTask -TaskName "MyDailyTask"\n \n# 停止计划任务\nStop-ScheduledTask -TaskName "MyDailyTask"\n获取计划任务运行历史\n使用 Get-ScheduledTaskInfo 命令可以获取计划任务的运行历史。\n# 获取任务的最近运行历史\nGet-ScheduledTaskInfo -TaskName "MyDailyTask"\n自动化常见任务\n自动化日常管理任务\nPowerShell 可以自动化许多日常管理任务,如备份文件、清理日志、监控系统等。\n自动备份文件\n以下脚本展示了如何使用 PowerShell 自动备份文件。\n# 自动备份文件脚本\n$sourcePath = "C:\\Data"\n$backupPath = "D:\\Backup"\n$timestamp = Get-Date -Format "yyyyMMddHHmmss"\n$backupDestination = "$backupPath\\DataBackup_$timestamp.zip"\n \n# 压缩并备份文件\nCompress-Archive -Path $sourcePath -DestinationPath $backupDestination\nWrite-Output "Backup completed: $backupDestination"\n自动清理日志\n以下脚本展示了如何使用 PowerShell 自动清理超过 30 天的日志文件。\n# 自动清理超过 30 天的日志文件\n$logPath = "C:\\Logs"\n$daysOld = 30\n \n# 获取并删除旧日志文件\nGet-ChildItem -Path $logPath -Filter *.log | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$daysOld) } | Remove-Item -Force\nWrite-Output "Old log files cleaned up."\n脚本的自动化执行\n通过计划任务或事件触发器可以自动执行 PowerShell 脚本,实现任务自动化。\n通过计划任务自动执行脚本\n使用计划任务可以定期执行脚本。\n# 创建计划任务以定期执行脚本\n$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-NoProfile -WindowStyle Hidden -File C:\\Scripts\\MyScript.ps1'\n$trigger = New-ScheduledTaskTrigger -Daily -At 6pm\nRegister-ScheduledTask -Action $action -Trigger $trigger -TaskName "EveningScriptTask"\n事件触发自动执行脚本\n使用事件触发器可以在特定事件发生时执行脚本例如系统启动时。\n# 创建事件触发器\n$trigger = New-ScheduledTaskTrigger -AtStartup\n \n# 创建计划任务在系统启动时执行脚本\n$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-NoProfile -WindowStyle Hidden -File C:\\Scripts\\StartupScript.ps1'\nRegister-ScheduledTask -Action $action -Trigger $trigger -TaskName "StartupScriptTask""},"Technology/GettingStarted/命令行工具/Shell/Shell-命令操作":{"title":"Linux 命令行操作","links":[":alpha:",":upper:",":lower:",":digit:",":alnum:",":punct:"],"tags":["Shell","Linux/基础","技术/入门"],"content":"一台完整的计算机是由运算器、控制器、存储器、输入/输出等多种硬件设备共同组成的而能让各种硬件设备各司其职且又能协同运行的东西就是系统内核。Linux 系统的内核负责完成对硬件资源的分配、调度等管理任务,对系统的正常运行起着十分重要的作用。\nShell 就是终端程序的统称,它充当了人与内核(硬件)之间的翻译官,用户把一些命令告诉终端程序,它就会调用相应的程序服务去完成某些工作。现在包括红帽系统在内的许多主流 Linux 系统默认使用的终端是 BashBourne-Again SHell解释器这个 Bash 解释器主要有以下 4 项优势:\n\n通过上下方向键来调取执行过的 Linux 命令;\n命令或参数仅需输入前几位就可以用 Tab 键补全;\n具有强大的批处理脚本\n具有实用的环境变量功能。\n\n执行命令\n命令 [命令参数] [命令对象]\n可选择的、可加或可不加的、非必需的参数使用中括号引起来而命令所要求的、必须有的参数或对象值则不带中括号。\n\n\n命令名称就是语法中的动词表达的是想要做的事情例如创建用户、查看文件、重启系统等操作。\n\n\n命令参数用于对命令进行调整让修改过的命令能更好地贴合工作需求达到事半功倍的效果。\n\n\nLinux 命令参数的长格式与短格式示例:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类别示例长格式man —help短格式man -h\n\n命令对象一般指要处理的文件、目录、用户等资源名称也就是命令执行后的承受方。例如创建一位叫小明的用户、查看一个叫工资表的文件、重启一个 IP 为 192.168.10.10 的系统等。\n\nLinux 系统中的命令、参数、对象都是严格区分大小写的。\n目录移动\nLinux 终端执行命令的很多情况下需要经常的更换目录cd 命令、pushd 命令、popd 命令可以快速移动目录。\n\ncd回到当前用户目录。\ncd ~:回到当前用户目录(方便切换到其他用户目录)。\ncd -:回到上次工作的目录。\npushd path存入 path 目录到目录栈。\npopd移动到目录栈弹出的目录。\n\n# 使用 `cd` 命令回到当前用户目录\n$ cd\n$ pwd\n/home/username\n \n# 使用 `cd ~` 命令也可以回到当前用户目录\n$ cd ~\n$ pwd\n/home/username\n \n# 使用 `cd -` 命令回到上次工作的目录\n$ cd /tmp\n$ cd -\n$ pwd\n/home/username\n \n# 使用 `pushd` 命令将目录存入目录栈\n$ pushd /var\n/var /home/username\n \n# 使用 `popd` 命令移动到目录栈弹出的目录\n$ popd\n/home/username\n快捷键\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷键功能描述Tab自动补全命令或文件名Ctrl+C终止当前命令Ctrl+Z将当前进程放到后台Ctrl+D退出当前终端Ctrl+L清屏Ctrl+U删除从光标位置到行首的字符Ctrl+K删除从光标位置到行尾的字符Ctrl+A移动光标到行首Ctrl+E移动光标到行尾Ctrl+R反向搜索命令历史Ctrl+W删除光标前的一个单词Ctrl+Y粘贴由 Ctrl+U、Ctrl+K 或 Ctrl+W 删除的文本Ctrl+T交换光标处字符与之前的字符Alt+B向后移动一个单词或 Ctrl+ 左箭头Alt+F向前移动一个单词或 Ctrl+ 右箭头Ctrl+Shift+C复制部分图形终端Ctrl+Shift+V粘贴部分图形终端\n特殊符号\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号功能描述!!引用上一条命令。例如,如果上一条命令是 ls -l那么输入 !! 将再次执行 ls -l。!$引用上一条命令的最后一个参数。例如,如果上一条命令是 cp /some/long/path /another/path那么输入 cd !$ 将执行 cd /another/path。!string引用最近一条以 string 开头的命令。例如,如果你之前执行过 ls -l那么输入 !ls 将再次执行 ls -l。^string1^string2^快速替换上一条命令中的字符串并执行。例如,如果上一条命令是 cat file1那么输入 ^file1^file2^ 将执行 cat file2。&&逻辑 AND。如果前一个命令成功执行退出状态为 0则执行后一个命令。例如command1 && command2 会在 command1 成功后执行 command2。;命令分隔符。允许在一行中执行多个命令。例如command1; command2 会依次执行 command1 和 command2不考虑前一个命令的成功与否。>输出重定向。将命令的输出写入到文件中而不是显示在屏幕上。例如ls -l > file.txt 将 ls -l 的输出保存到 file.txt。>>追加输出重定向。将命令的输出追加到现有文件的末尾。例如echo "hello" >> file.txt 将追加 “hello” 到 file.txt。<输入重定向。使用文件作为命令的输入。例如cat < file.txt 会显示 file.txt 的内容。“反引号。执行其中的命令并将输出作为另一个命令的参数。例如echo “Today is `date`” 会显示今天的日期。$( )命令替换。类似于反引号但更易读易用。例如echo "Today is $(date)" 会显示今天的日期。{ }大括号扩展。生成序列或列表。例如echo {1..5} 会输出 1 2 3 4 5。#注释符号。# 后面的内容将被视为注释,不会被执行。例如,# This is a comment。\n常用命令\n文件操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明lslist列出目录中的文件列表cdchange directory更改当前工作目录pwdprint working directory显示当前工作目录mkdirmake directory创建新目录rmdirremove directory删除空目录touchtouch创建新文件cpcopy复制文件或目录mvmove移动文件或目录rmremove删除文件或目录\n文件处理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明catconcatenate查看、合并文件内容headhead查看文件头部内容tailtail查看文件尾部内容grepglobal regular expression print在文件中查找指定文本sedstream editor流编辑器用于对文件进行基本文本处理awkawk文本和数据处理工具\n系统管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明psprocess status查看进程状态toptop实时查看系统进程状态killkill终止进程shutdownshutdown关闭系统rebootreboot重启系统unameuname显示系统信息dfdisk free显示磁盘使用情况dudisk usage显示目录空间使用情况freefree显示系统内存使用情况\n网络管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述ipinternet protocol显示和配置网络接口信息pingping测试主机之间的连通性nslookupname server lookup查询域名解析信息traceroutetrace route显示数据包到达目的地经过的路由信息routeroute显示和配置系统的路由表netstatnetwork statistics显示网络连接状态和统计信息tcpdumpTCP dump抓取网络数据包并进行分析\n权限管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述chmodchange mode修改文件或目录的访问权限chownchange owner修改文件或目录的所有者chgrpchange group修改文件或目录的所属组useradduser add添加用户账号usermoduser modify修改用户账号信息userdeluser delete删除用户账号groupaddgroup add添加用户组groupmodgroup modify修改用户组信息groupdelgroup delete删除用户组passwdpassword修改用户密码suswitch user切换用户身份sudosuperuser do以超级用户身份执行命令visudovisual sudo编辑 sudo 配置文件ididentity显示当前用户信息whoamiwho am i显示当前登录用户名\n软件管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明apt-getAdvanced Packaging ToolUbuntu 系统软件包管理工具yumYellowdog Updater ModifiedCentOS、Fedora 等系统软件包管理工具dpkgDebian PackageDebian、Ubuntu 等系统软件包管理工具rpmRed Hat Package ManagerCentOS、Fedora 等系统软件包管理工具\n磁盘管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼描述dfdisk filesystem显示磁盘空间使用情况dudisk usage显示文件和目录的磁盘使用情况fdiskfixed disk磁盘分区管理工具fsckfile system check检查和修复文件系统mkfsmake filesystem创建文件系统mountmount挂载文件系统到目录上umountunmount卸载文件系统\n进程管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述psprocess status显示当前进程状态toptask-oriented processor动态显示进程信息killkill终止一个进程killallkillall终止一个指定名称的进程nicenice改变进程优先级renicerenice改变正在运行进程的优先级jobsjobs显示当前 shell 的活动作业bgbackground将一个进程置于后台fgforeground将一个进程置于前台nohupno hang up在后台运行命令并不挂起pstreeprocess tree显示进程树\n任务\nLinux 系统中运行程序时,可以选择在前台或后台运行。在前台运行时,程序会占用终端并且输出信息直接显示在终端中。而在后台运行时,程序在后台默默地执行,不会占用终端并且不会直接显示输出信息。\n运行\n\n& 符号:在命令的末尾添加 & 符号例如command &。这将使命令在后台运行。\nnohup 命令nohup 命令可以使命令在后台运行并忽略挂断信号SIGHUP**这意味着即使你退出当前终端,程序仍会继续运行。**用法为nohup command &。\n\n# 在后台运行 sleep 命令(这个命令仅仅会让 shell 睡眠一段时间)\n$ sleep 300 &\n \n# 使用 nohup 命令在后台运行 sleep 命令,并且将输出信息存入 nohup.out 文件中\n$ nohup sleep 300 &\n \n# 使用 nohup 命令在后台运行 sleep 命令,并且将输出信息重定向到 output.txt 文件中\n$ nohup sleep 300 > output.txt &\n \n# 运行一个会产生错误的命令,并将错误信息重定向到 err.txt 文件中\n$ ls /nonexistent > /dev/null 2> err.txt\n \n# 使用 nohup 命令在后台运行一个会产生错误的命令,并将输出和错误信息重定向到相应的文件中\n$ nohup ls /nonexistent > out.txt 2> err.txt &\n \n# 使用 &> 符号将标准输出和错误输出都重定向到同一个文件中\n$ ls /nonexistent &> all.txt\n \n# 使用 |& 符号将错误输出重定向到另一个命令的标准输入\n$ ls /nonexistent |& less\n管理\nJobs\njobs 命令可以列出当前终端会话中正在运行的后台任务。每个任务都有一个唯一的编号,可以使用该编号来操作任务,例如将任务切换到前台或终止任务。\n# 列出当前终端会话中的后台任务\n$ jobs\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全拼描述-l—list列出每个作业的进程 ID 号-p—pid仅列出作业的进程 ID 号-n—new显示自上次通知以后已更改的作业-r—running仅列出运行中的作业-s—stopped仅列出停止的作业\nfg、bg\nfg 命令可以将一个后台任务切换到前台运行bg 命令可以将一个在后台暂停的任务切换到后台继续运行。\n# 将一个后台任务切换到前台运行,假设任务的编号是 1\n$ fg %1\n \n# 将一个后台任务切换到后台继续运行,假设任务的编号是 1\n$ bg %1\nPs\nps 命令可以显示系统中所有进程的状态,包括后台运行的进程。\n# 列出系统中所有进程的状态\n$ ps\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全拼描述-A—all显示所有进程在某些系统上此选项为 -e-f—full完整格式列出-u—user按用户列出-x—all-user-processes列出所有用户的进程-l—long长格式列出-j—jobs工作格式列出-r—running列出运行中的进程-a—all-with-tty列出拥有终端的所有进程-e—every列出所有进程在某些系统上此选项为 -A-p—pid列出指定进程号的进程\nKill\nkill 命令是用于发送特定的信号到操作系统中的进程。默认情况下如果不指定信号kill 命令会发送 TERM (终止) 信号,这会请求一个进程自我终止。\n# 终止一个后台任务,假设任务的编号是 1\n$ kill %1\n \n# 使用 ps 命令找到进程的 PID然后使用 kill 命令终止进程\n$ ps\n$ kill PID\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-l列出所有可用的信号-s signal指定发送的信号可以是信号名或信号号码-p不发送信号只打印进程 ID-9 或 -KILL发送 KILL 信号强制终止进程\n管道\n管道命令符把前一个命令原本要输出到屏幕的信息当作后一个命令的标准输入其执行格式为「命令 A | 命令 B」。按下键盘上的 Shift+ 反斜杠(\\)键即可输入管道符,\n# 输出禁止登录用户行数\ngrep /sbin/nologin /etc/passwd | wc -l\n \n# 搜索与 bash 有关的进程\nps aux | grep bash\n命令符可以无限组合例如命令 A | 命令 B | 命令 C |……\n\n曾经有位东北的同学做了一个特别贴切的类比把管道符当做流水线作业这跟吃顿烧烤是同一个道理即第一个人负责切肉第二个人负责串肉第三个人负责烧烤最后的处理结果交付给用户。\n\n重定向\n输入重定向是指把文件导入到命令中而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中。\n\n\n标准输入重定向STDIN文件描述符为 0默认从键盘输入也可从其他文件或命令中输入。\n\n\n标准输出重定向STDOUT文件描述符为 1默认输出到屏幕。\n\n\n错误输出重定向STDERR文件描述符为 2默认输出到屏幕。\n\n\n对于重定向中的标准输出模式可以省略文件描述符 1 不写,而错误输出模式的文件描述符 2 是必须要写的。\n# 输入重定向:将 file1.txt 作为 sort 命令的标准输入\n$ sort < file1.txt \n \n# 输入重定向并重定向输出:将 file1.txt 作为 sort 命令的输入,并将结果输出到 file2.txt 中\n$ sort < file1.txt > file2.txt \n \n# Here 文档(<<):将两行 "This is a line." 作为 cat 的输入\n$ cat << EOF\nThis is a line.\nThis is a line.\nEOF\n \n# 输出重定向:将 "Hello, World!" 输出到 output.txt 文件中(覆盖文件原有内容)\n$ echo "Hello, World!" > output.txt \n \n# 错误输出重定向:将错误信息输出到 error.txt 文件中\n$ ls /nonexistentdirectory 2> error.txt \n \n# 追加输出重定向:将 "Hello again!" 追加到 output.txt 文件中\n$ echo "Hello again!" >> output.txt \n \n# 追加错误输出重定向:将错误信息追加到 error.txt 文件中\n$ ls /anothernonexistentdirectory 2>> error.txt \n \n# 同时重定向标准输出和错误输出,追加到同一文件\n$ ls /nonexistentdirectory >> all_output.txt 2>&1 \n \n# 同时重定向标准输出和错误输出,追加到同一文件(简化写法)\n$ ls /nonexistentdirectory &>> all_output.txt \n \n输入重定向\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号作用命令 < 文件将文件作为命令的标准输入命令 << 分界符从标准输入中读入,直到遇见分界符才停止命令 < 文件 1 > 文件 2将文件 1 作为命令的标准输入并将标准输出到文件 2\n输出重定向\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号作用命令 > 文件将标准输出重定向到一个文件中(清空原有文件的数据)命令 2> 文件将错误输出重定向到一个文件中(清空原有文件的数据)命令 >> 文件将标准输出重定向到一个文件中(追加到原有内容的后面)命令 2>> 文件将错误输出重定向到一个文件中(追加到原有内容的后面)命令 >> 文件 2>&1、命令 &>> 文件将标准输出与错误输出共同写入到文件中(追加到原有内容的后面)\n通配符\n# 使用 * 通配符:列出所有 .txt 文件\n$ ls *.txt\n \n# 使用 ? 通配符:列出所有只有一个字符的 .txt 文件\n$ ls ?.txt\n \n# 使用 [] 通配符:列出所有以小写字母开始的 .txt 文件\n$ ls [a-z]*.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n通配符含义*任意字符?单个任意字符[a-z]单个小写字母[A-Z]单个大写字母[a-Z]单个字母[0-9]单个数字:alpha:任意字母:upper:任意大写字母:lower:任意小写字母:digit:所有数字:alnum:任意字母加数字:punct:标点符号\n转义字符\n# 使用反斜杠(\\)使反斜杠后面的一个变量变为单纯的字符。\n$ echo \\$HOME\n$HOME\n \n# 使用单引号(' ')转义其中所有的变量为单纯的字符串。\n$ echo '$HOME'\n$HOME\n \n# 使用双引号(" ")保留其中的变量属性,不进行转义处理。\n$ echo "$HOME"\n/home/username\n \n# 使用反引号(` `)把其中的命令执行后返回结果。\n$ echo `date`\nSun Sep 4 22:38:10 PDT 2023\n环境变量\n在 Linux 系统中,变量名称一般都是大写的,命令则都是小写的,这是一种约定俗成的规范。\nLinux 系统中最重要的 10 个环境变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量名称作用HOME用户的主目录即家目录SHELL用户在使用的 Shell 解释器名称HISTSIZE输出的历史命令记录条数HISTFILESIZE保存的历史命令记录条数MAIL邮件保存路径LANG系统语言、语系名称RANDOM生成一个随机数字PS1Bash 解释器的提示符PATH定义解释器搜索用户执行命令的路径EDITOR用户默认的文本编辑器\n帮助文档\nMan\n使用 man 命令查看到的帮助内容信息\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n按键作用空格键向下翻一页PaGe down向下翻一页PaGe up向上翻一页home直接前往首页end直接前往尾页/从上至下搜索某个关键词,如“/linux”?从下至上搜索某个关键词,如“?linux”n定位到下一个搜索到的关键词N定位到上一个搜索到的关键词q退出帮助文档\n示例\n# 查看 man 的帮助文件\nman man\n \n# 查看 ssh 的帮助文件\nman sh"},"Technology/GettingStarted/命令行工具/Shell/Shell-必备锦囊":{"title":"Shell 必备锦囊","links":[],"tags":["Shell","技术/入门"],"content":"Tab 补全\n在 Shell 中可以使用 tab 键盘实现快速补全,双击 tab 可以显示补全列表。\n@:~$ cd \n.ansible/ .config/ .wget-hsts index.html\n.bash_history .lesshst ChangeMirrors.sh index.html.1\n.bash_logout .profile DockerInstallation.sh \n.bashrc .ssh/ aaaa/ \n.cache/ .sudo_as_admin_successful demo/ \nHistory 历史\nhistory 命令可以显示执行过的命令历史。\n@:~$ history\n 1 pwd\n 2 ls -l\n 3 ip addr\n 4 apt-get update\n 5 sudo apt-get update\n^ 替换命令\n如果输错了命令特别是命令较长的情况下可以使用 ^ 替换错误的地方。\n@:~$ cat a。txt\ncat: a。txt: No such file or directory\n@:~$ ^。^.\ncat a.txt\nhelloworld!\n@:~$ \n! 快捷符号\n! 符号拥有很多便捷的实用方法,例如 !! 快速执行上条命令,特别适用于 sudo 权限的情况下。!foo 快速执行历史命令中 foo 开头的命令。!$ 命令引用上调命令中的最后一位参数。\n@:~$ !!\ncat a.txt\nhelloworld!\n@:~$ !ca\ncat a.txt\nhelloworld!\n@:~$ mkdir path-a\n@:~$ cd !$\ncd path-a\n@:~/path-a$ \n目录操作\nLinux 终端执行命令的很多情况下需要经常的更换目录cd 命令、pushd 命令、popd 命令可以快速移动目录。\n\ncd回到当前用户目录。\ncd ~:回到当前用户目录(方便切换到其他用户目录)。\ncd -:回到上次工作的目录。\npushd path存入 path 目录到目录栈。\npop移动到目录栈弹出的目录。\n\n@:~/demo/a$ cd ~\n@:~$ cd -\n/home/xxb/demo/a\n@:~/demo/a$ cd\n@:~$ cd -\n/home/xxb/demo/a\n@:~/demo/a$ pushd /home/xxb/demo/a\n~/demo/a ~/demo/a\n@:~/demo/a$ cd ~\n@:~$ popd\n~/demo/a\n@:~/demo/a$ \nAlias 别名\n一些常用的命令可以使用 alais 定义别名,方便快速操作。移除别名使用 unalias 命令。\n@:~/demo/a$ cat aa.txt \nhelloworld!\n@:~/demo/a$ alias abc='cat aa.txt'\n@:~/demo/a$ abc\nhelloworld!\n@:~/demo/a$ \n命令替换\nShell 内可以使用反引号和 $() 命令执行命令。\n@:~/demo/a$ pushd `pwd`\n~/demo/a ~/demo/a\n@:~/demo/a$ pushd $(pwd)\n~/demo/a ~/demo/a ~/demo/a\n@:~/demo/a$ "},"Technology/GettingStarted/命令行工具/Shell/Shell-是什么":{"title":"Shell 是什么","links":[],"tags":["Shell","技术/入门"],"content":"历史\n壳层shell这个说法起源于路易斯·普赞Louis Pouzin在 1964 年至 1965 年间首次提出,随后在 MulticsMULTiplexed Information and Computing System项目中首次被实现出来。Unix 上的第一个 Unix 壳层Unix shell是肯·汤普逊Ken Thompson以 Multics 上的 shell 为范本,所写出的 Thompson shell。\n微软的 Windows 操作系统也提供了命令行壳层的功能,它们是 Windows 95 / 98 下的 command.com、Windows NT 内核下的 cmd.exe 以及 PowerShell而图形界面壳层即为 explorer.exe。\n简介\nShell壳层在计算机科学中指为用户提供用户界面的软件通常指的是命令行界面的解析器。一般来说这个词是指操作系统中提供访问内核所提供之服务的程序。Shell 也用于泛指所有为用户提供操作界面的程序也就是程序和用户交互的层面。因此与之相对的是内核Kernel内核不提供和用户的交互功能。\n通常将 shell 分为两类命令行与图形界面。命令行壳层提供一个命令行界面CLI而图形壳层提供一个图形用户界面GUI。\n图形用户界面GUI\n\nDOS Shell\nMacintosh Finder\nMicrosoft Windows 环境Aston shell、BB4Win、Emerge Desktop、Geoshell、Litestep、程序管理器、Secure Desktop、SharpE、Windows Explorer、UserShell。\nX Window System 环境或 Wayland 环境(主要用于类 Unix 操作系统)\n\n独立的 X 窗口管理器,例如 Blackbox 与 Fluxbox。\n依靠窗口管理器的完整桌面环境例如CDE、GNOME、Unity以 GNOME 作内核、KDE、XFCE。\n\n\n\n命令行界面CLI\nUnix\nBourne Shell 兼容\n\n**Bourne shellsh**史蒂夫·伯恩在贝尔实验室时编写。1978 年随 Version 7 Unix 首次发布。\n\nAlmquist shellash由肯尼斯·艾昆斯特Kenneth Almquist在 SVR4 上建立了这个分支。\n**Bourne-Again shellbash**由布莱恩·福克斯在 1987 年为了 GNU 计划而编写。\nDebian Almquist shelldash由赫伯特·许Herbert Xu1997 年移植到 Linux 上后改名为 dash。\nKorn shellkshDavid Korn 在贝尔实验室时编写。\nZ shellzsh是 macOS2019 年起) 一款可用作交互式登录的 shell 及脚本编写的命令解释器。\n\n\n\nC Shell 兼容\n\nC shellcsh比尔·乔伊在加州大学伯克利分校时编写。1979 年随 BSD 首次发布。\n\nTENEX C shelltcsh 一个向下兼容 c shell 的 Unix shell目前作为 FreeBSD 和其延伸发行版的默认 shell。\n\n\n\n非 Unix\n\n4DOS, 4OS2, 4NT JP Software 公司可在在 DOS, OS/2及 Windows NT 下使用的壳层。Take Command 程序则是 GUI 方式的兼容程序。\nAmiga CLI/Amiga 壳层是称为 Workbench 的 AmigaOS 图形界面的另一选择。\nBASIC-PLUS RSTS/E\nBeemosBEEMos在 Windows XP 上执行的一个小型项目,提供设置、应用程序等功能,感觉起来像是在另一个操作系统下。\nCANDE MCS MCP 操作系统的指令行壳曾与文本编辑器\nCCP CP/M 操作系统的主控台指令处理器\ncmd.exe 基于 OS/2、Windows CE、Windows NT 系列操作系统的命令提示字符壳层\nCOMMAND.COM DOS 的壳层\nCommodore DOS Wedge Commodore 64 上 BASIC 2.0 的延伸功能,包括常用磁盘操作的简略指令\nDCL OpenVMS 的标准壳层派生自早期的迪吉多DEC操作系统\nDDT 迪吉多DECPDP-10 调试工具,麻省理工学院 Incompatible Timesharing System 的指令壳层\nDROS 智能手机上基于 Java ME 平台的类 DOS 壳层\nEFI-SHELL 可扩展固件界面Extensible Firmware InterfaceEFI指令壳层它是开放源代码的\nGoogle Shell –基于浏览器的 Google Search 前端界面\niSeries QSHELL IBM OS/400 上的 Unix 风格壳层\nMacintosh Programmers Workshop –古典 Mac OS 软件开发用的老式指令行环境\nMicrosoft BASIC –一些古老 8 位电脑上的主要作业环境\nRexx IBM 的脚本语言scripting language\nSingularity shell Singularity 的标准壳层\nWindows PowerShell –命令提示字符的新一代面向对象后继者(旧称 Monad 或 Microsoft Shell (MSH)\nWindows 修复主控台– Windows 2000、Windows XP、Windows 2003 操作系统的一项功能\nYouShell –用于 YouOS基于 JavaScript 的指令处理器\n"},"Technology/GettingStarted/命令行工具/Vim/1.Vim-入门":{"title":"Vim 快速入门","links":[],"tags":["Vim","技术/入门"],"content":"Vim 8.2 快速参考备忘单的有用集合,可帮助您更快地学习 vim 编辑器。\n入门\n运动图\n▼/▶ 光标 ▽/▷ 目标\n左右动作\n╭┈┈┈┈┈┈┈┈┈┈┈┈┈ | \n├┈┈┈┈┈┈┈┈┈┈┈┈┈ 0 $ ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╮\n┆ ╭┈┈┈┈┈┈┈┈┈┈ ^ fe ┈┈┈┈┈┈┈┈╮ ┆\n┆ ┆ ╭┈┈┈┈┈┈┈ Fo te ┈┈┈┈┈┈┈╮┆ ┆\n┆ ┆ ┆╭┈┈┈┈┈┈ To 30| ┈┈┈╮ ┆┆ ┆\n┆ ┆ ┆┆ ╭┈┈┈┈ ge w ┈┈┈╮ ┆ ┆┆ ┆\n┆ ┆ ┆┆ ┆ ╭┈┈ b e ┈╮ ┆ ┆ ┆┆ ┆\n┆ ┆ ┆┆ ┆ ┆ ╭h l╮ ┆ ┆ ┆ ┆┆ ┆\n▽ ▽ ▽▽ ▽ ▽ ▽▼ ▼▽ ▽ ▽ ▽ ▽▽ ▽\n echo "A cheatsheet from quickReference"\n上下动作\n - SCREEN 1 START\n ╭┈┬┈┈┈┈┈┈┈┈┈▷ #!/usr/bin/python\n ┆ ┆ ╭┈┈┈▷ \n ┆ ┆ ┆ print("Hello")\n ┆ ┆ { } ▶ print("Vim")\n ┆ ┆ ┆ print("!")\n ┆ ┆ └┈▷ \n ┆ ┆ ╭┈┈┈┬┈┈┈▷ print("Welcome")\nG gg H M L k j ▶ print("to")\n┆ ┆ └┈▷ print("Quick Reference")\n┆ ┆ print("/vim")\n┆ ┆ \n┆ ╰┈┈┈┈┈▷ \n┆ - SCREEN 1 END\n╰┈┈┈┈┈┈┈┈┈┈┈┈┈┈▷ print("SCREEN 2")\n动作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明hj<C-u> / <C-d>上/下半页<C-b> / <C-f>向上/向下翻页\n字 (词)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明b / w上一个/下一个单词ge / e上一个/下一个词尾\n行\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明0 (zero) / $行的开始/结束^行开头 (非空白)\n字符串\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明Fe / fe移动到上一个/下一个 eTo / to在上一个/下一个 o 之前/之后移动`*/*n\n文档\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明gg / G第一行/最后一行:nnG} / {下一个/上一个空行\n窗口\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明H / M / L上/中/下屏幕zt / zz / zb上/中/下这条线\n插入模式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明i / a在光标之前/之后插入I / A插入行的开始/结束o / O (letter)在下方/上方插入新行s / S删除字符/行并插入C / cc更改到/当前行的结尾gi在最后一个插入点插入Esc<C-[>\n保存和退出\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明:w保存:q关闭文件:wq:x:wqa保存并退出所有文件:q!ZQ:qa关闭所有文件:qa!强制退出所有文件:w new.txt写入 new.txt:sav new.txt保存并编辑 new.txt:w !sudo tee %写入只读文件\n正常模式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明r替换一个字符R进入替换模式u / 3u撤消更改 1/3 次U在一行上撤消更改J加入下一行<C-r> / 5 <C-r>重做更改 1/5 次\n剪切和粘贴\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明x删除字符 (剪切)p / P在之后/之前粘贴xp交换两个字符D删除到行尾 (剪切)dw删除单词 (剪切)dd删除线 (剪切)ddp交换两条线yy拉线 (复制)"*p"+p"*y"+y\n在可视化模式下\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明d ** xs替换选择yYank 选择 (复制)\n重复\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明.重复上一个命令;重复最新的 f、t、F 或 T,重复最新的 f、t、F 或 T 颠倒&重复最后一个 :s@:重复命令行命令\n可视化模式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明v进入可视化模式V进入视线模式<C-v>进入可视化阻挡模式ggVG选择所有文本> / <向右/向左移动文本\n宏\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--qi录制宏 iq停止录制宏@i运行宏 i7@i运行宏 i 7 次@@重复上一个宏\n您可以为任何字母保存宏而不仅仅是 i\nVim 运算符\n用法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明dw运算符动作\n将 可用运算符 与 动作 结合使用以使用它们\n可用运算符\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明d删除yYank (复制)c更改 (删除然后插入)p粘贴=格式代码g~切换案例gU大写gu小写>右缩进<左缩进!通过外部程序过滤\n例子\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组合说明dd删除当前行dj删除两行dw删除到下一个单词db删除到单词的开头dfa删除直到 a 字符d/hello删除直到 hellocc更改当前行与 S 同义yy复制当前行>j缩进 2 行ggdG删除完整的文档gg=G缩进一个完整的文档ggyG复制整个文档\n计数\n[数字] <运算符> <动作>\n<运算符> [数字] <动作>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组合说明2dd删除 2 行6yy复制 6 行d3w删除 3 字d5j向下删除 5 行>4k向上缩进 4 行\nVim 文本对象\n用法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明vi / aOperatorinner(内部) / around(周围)\n文本块内部或周围使用 operator 进行操作\n文本对象\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明p段落w单词WWORD (被空格包围)s句子[ ( { <[]、() 或 {} 块] ) } >[]、() 或 {} 块’ ” `带引号的字符串b一个块 [(B[{中的一个块t一个 HTML 标签块\n查看 :help text-objects\n删除\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明diw删除内词dis删除内句di”引号中删除da”删除引号 (包括引号)dip删除段落\n选择\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明vi”选择内引号“...{.underline}”va”选择引号 "..."{.underline}vi[选择内括号 [...{.underline}]va[选择括号 [...]{.underline}viw选择内词vip选择内部段落vipip选择更多段落\n杂项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明ciw换内字ci”更改内部引号cit更改内部标签 (HTML)cip更改内部段落yipYank 段落yapYank 段落 (包括换行符)\nVim 多个文件\nBuffers (缓冲器)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:e file在新缓冲区中编辑文件:bn转到下一个缓冲区:bp转到上一个缓冲区:bd从缓冲区列表中删除文件:b 5打开缓冲区 #5:b file按文件转到缓冲区:ls列出所有打开的缓冲区:sp file打开和拆分窗口:vs file打开和垂直拆分窗口:hid隐藏此缓冲区:wn写入文件并移至下一个:tab ba将所有缓冲区编辑为选项卡\n窗口\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--<C-w> s拆分窗口<C-w> v垂直拆分窗口<C-w> w切换窗口<C-w> q退出一个窗口<C-w> T拆分成一个新标签<C-w> x用下一个交换当前<C-w> - / +减少/增加高度<C-w> < / >减少/增加宽度<C-w> ``<C-w> =同样高和宽<C-w> h / l转到左/右窗口<C-w> j / k转到上/下窗口\n选项卡\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明:tabe [file]E 在新选项卡中编辑文件:tabf [file]如果在新选项卡中存在则打开:tabcC 失去当前选项卡:tabo关闭 o 其他选项卡:tabs列出所有标签:tabr转到第一个 r 标签:tabl转到 last 选项卡:tabm 0我转到位置 0:tabn转到 next 选项卡:tabp转到 p 上一个标签\n正常模式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明gt转到 next 选项卡gT转到 p 上一个标签2gt转到标签编号 2\nVim 搜索和替换\n搜索\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--/foo向前搜索/foo\\c向前搜索 (不区分大小写)?foo向后搜索/\\v\\d+使用 regex 搜索n下一个匹配的搜索模式N上一个匹配的搜索*向前搜索当前单词#向后搜索当前单词\n更换行\n:[range]s/{pattern}/{str}/[flags]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:s/old/new先更换:s/old/new/g全部替换:s/\\vold/new/g全部替换为 regex:s/old/new/gc全部替换 (确认):s/old/new/i先忽略大小写替换:2,6s/old/new/g在 2-6 行之间替换\n替换文件\n:%s/{pattern}/{str}/[flags]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:%s/old/new先更换:%s/old/new/g全部替换:%s/old/new/gc全部替换 (确认):%s/old/new/gi全部替换 (忽略大小写):%s/\\vold/new/g全部替换为 regex\n范围\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--%整个文件’<,>当前选择5第 5 行5,10第 5 行到第 10 行$最后一行2,$第 2 行到最后.当前行,3接下来的 3 行-3,转发 3 行\n全局命令\n:[range]g/{pattern}/[command]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:g/foo/d删除包含 foo 的行:g!/foo/d删除不包含 foo 的行:g/^\\s*$/d删除所有空行:g/foo/t$将包含 foo 的行复制到 EOF:g/foo/m$将包含 foo 的行移动到 EOF:g/^/m0反转文件:g/^/t.复制每一行\nInverse(逆) :g\n:[range]v/{pattern}/[command]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:v/foo/d删除不包含 foo 的行 (还有 :g!/foo/d)\nFlags(标志)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--g替换所有出现i忽略大小写I不要忽略大小写c确认每个替换\n替换表达式魔术\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--& ** \\0\\1…\\9替换为 0-9 组\\u大写下一个字母\\U后面的大写字符\\l小写下一个字母\\L后面的字符小写\\e\\u、\\U、\\l 和 \\L 的结尾\\E\\u、\\U、\\l 和 \\L 的结尾\n例子\n:s/a\\|b/xxx\\0xxx/g # 将 "a b" 修改为 "xxxaxxx xxxbxxx"\n:s/test/\\U& file/ # 将 "test" 修改为 "TEST FILE"\n:s/\\(test\\)/\\U\\1\\e file/ # 将 "test" 修改为 "TEST file"\n:s/\\v([abc])([efg])/\\2\\1/g # 将 "af fa bg" 修改为 "fa fa gb"\n:s/\\v\\w+/\\u\\0/g # 将 "bla bla" 修改为 "Bla Bla"\n:s/\\v([ab])|([cd])/\\1x/g # 将 "a b c d" 修改为 "ax bx x x"\n:%s/.*/\\L&/ # 将 "HTML" 修改为 "html"\n:s/\\v<(.)(\\w*)/\\u\\1\\L\\2/g # 将单词的每个首字母大写\n:%s/^\\(.*\\)\\n\\1/\\1/ # 删除重复行\n:%s/<\\/\\=\\(\\w\\+\\)\\>/\\U&/g # 将 HTML 标记转换为大写\n:g/^pattern/s/$/mytext # 查找文本并将其附加到末尾\n:g/pattern/norm! @i # 在匹配行上运行宏\n/^\\(.*\\)\\(\\r\\?\\n\\1\\)\\+$ # 查看重复行\n/\\v^(.*)(\\r?\\n\\1)+$ # 查看重复行(非常神奇)\n:v/./,/./-j # 将空行压缩成空行\n:g/<p1>/,/<p2>/d # 从 <p1> 到 <p2> 包含删除\nVimdiff\n用法\nvimdiff file1 file2 [file3]\nvim -d file1 file2 [file3]\n编辑\n:[range]diffget [bufspec]\n:[range]diffput [bufspec]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明do / :diffget获取get差异dp / :diffput放差价:dif重新扫描差异:diffo关闭差异模式:1,$+1diffget获取所有差异ZQ不做改动就退出\n请参阅范围\n折叠\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明zo / zO打开zc / zC关za / zA切换zv这条线的打开折叠zM关闭所有zR打开所有zm折叠更多 (折叠级别 += 1)zr少折叠 (折叠级别 -= 1)zx更新折叠\n跳跃\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明]c下一个区别[c以前的区别\n各种各样的\nCase\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明vU大写 字母vu小写 字符~切换案例 字符viw U大写 字viw u小写 字viw ~切换案例 字VU / gUU大写 行Vu / guu小写 行V~ / g~~切换案例 线gggUG大写 所有文本ggguG小写 所有文本ggg~G切换大小写 所有文本\n跳跃\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明<C-o>返回上一个<C-i>向前gf转到光标中的文件ga显示十六进制、ASCII 值\n其他命令行\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:h帮助打开帮助视图:edit!重新加载当前文件:2,8m0将行 2-8 移动到 0:noh清除搜索亮点:sort排序行:ter打开终端窗口:set paste启用插入粘贴子模式:set nopaste禁用插入粘贴子模式:cq退出并出现错误 (正在中止 Git)\n导航\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明%最近/匹配的 {[()]}[( ** [{]) ** ]{[m上一个方法开始[M上一个方法结束\n计数器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明<C-a>增加数量<C-x>减少数量\n选项卡\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明:tag Classname跳转到 Classname 的第一个定义<C-]>跳转到定义g]查看所有定义<C-t>回到最后一个标签<C-o> <C-i>后退前进:tselect Classname查找类名的定义:tjump Classname查找类名的定义 (自动选择第一个)\n格式化\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:ce 88 列之间的中心线:ri 4在 4 列右对齐行:le左对齐线\n查看 :help formatting\n标记\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明“^`插入模式下光标的最后位置“.`当前缓冲区的最后更改““`最后退出的当前缓冲区“0`在上次编辑的文件中''返回当前缓冲区中跳出的行````返回当前缓冲区中跳转的位置“[`到先前更改或拉出的文本的开头“]`到之前更改或拉出的文本的结尾“<`到最后一个可视化选择的开始“>`到最后一个可视化选择的结尾ma将此光标位置标记为a“a`跳转到光标位置 a'a跳转到位置为 a 的行首d'a从当前行删除到标记 a 的行da`从当前位置删除到标记 a 的位置c'a将文本从当前行更改为 a 行ya`将文本从当前位置拉到 a 的位置:marks列出所有当前标记:delm a删除标记 a:delm a-d删除标记 a、b、c、d:delm abc删除标记 a、b、c\n计算器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明<C-r> = 7*7显示结果<C-r> = 10/2显示结果\n在 INSERT 模式下执行此操作\nShell\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n:--:!<shell>解释 Shell 命令:r!<shell>读入 shell 的输出:r!date插入日期:!!date用日期替换当前行\n命令行\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷方式说明<C-r><C-w>将当前单词插入命令行<C-r>"从 注册 粘贴<C-x><C-f>在插入模式下自动完成路径\n技巧\n删除重复行\n:sort | %!uniq -u\n对文件中的行进行编号\n:%!cat -n\n将整个文档复制到剪贴板\n:%w !pbcopy # Mac OS X\n:%w !xclip -i -sel c # GNU/Linux\n:%w !xsel -i -b # GNU/Linux\n理解 Vim\n动词理解\nd # 表示删除delete\nr # 表示替换replace\nc # 表示修改change\ny # 表示复制yank\nv # 表示选取visual select\n动词代表了我们打算对文本进行什么样的操作\n名词理解\nw # 表示一个单词word\ns # 表示一个句子sentence\np # 表示一个段落paragraph\nt # 表示一个 HTML 标签tag\n名词代表了我们即将处理的文本。引号或者各种括号所包含的文本称作一个文本块。\n介词理解\ni # 表示在...之内 inside\na # 表示环绕... around\nt # 表示到...位置前 to\nf # 表示到...位置上 forward\n介词界定了待编辑文本的范围或者位置。\n数词理解\n数词指定了待编辑文本对象的数量从这个角度而言数词也可以看作是一种介词。引入数词之后文本编辑命令的语法就升级成了下面这样\n动词 介词/数词 名词\n下面是几个例子\nc3w # 修改三个单词change three words\nd2w # 删除两个单词delete two words\n另外数词也可以修饰动词表示将操作执行 n 次。于是,我们又有了下面的语法:\n数词 动词 名词\n示例\n2dw # 两次删除单词(等价于删除两个单词): twice delete word\n3x # 三次删除字符(等价于删除三个字符): three times delete character\n组词为句理解\n有了这些基本的语言元素我们就可以着手构造一些简单的命令了。文本编辑命令的基本语法如下\n动词 介词 名词\n下面是一些例子\ndip # 删除一个段落: delete inside paragraph\nvis # 选取一个句子: visual select inside sentence\nciw # 修改一个单词: change inside word\ncaw # 修改一个单词: change around word\ndtx # 删除文本直到字符“x”(不包括字符“x”): delete to x\ndfx # 删除文本直到字符“x”(包括字符“x”): delete forward x\n另见\n\n搞得像IDE一样的 Vim (github.io)\nVim 官方网站 (vim.org)\nDevhints (devhints.io)\nVim cheatsheet (vim.rotrr.com)\nVim documentation (vimdoc.sourceforge.net)\nInteractive Vim tutorial (openvim.com)\n\n\n来源Vim 备忘清单 & vim cheatsheet & Quick Reference仅学术引用著作权归作者所有。\n"},"Technology/GettingStarted/命令行工具/Vim/2.VIM-配置管理":{"title":"VIM 配置管理","links":[],"tags":["技术/入门","Vim"],"content":"vimrc 文件\n位置\nvimrc 文件是 Vim 的配置文件,用于存储用户的个人设置和定制。它的位置可能因操作系统而异:\n\nLinux/Unix通常在 ~/.vimrc 或 ~/.vim/vimrc\nMacOS类似于 Linux通常在 ~/.vimrc 或 ~/.vim/vimrc\nWindows在 C:\\Users\\<用户名>\\_vimrc 或 C:\\Users\\<用户名>\\vimfiles\\vimrc\n\n在 Vim 中,可以通过以下命令查看 vimrc 文件的位置:\n:echo $MYVIMRC\n基本结构\n一个典型的 vimrc 文件可能包含以下几部分:\n\n全局设置设置 Vim 的全局行为,例如编码、文件格式等。\n界面设置配置界面元素例如行号、颜色主题、状态栏等。\n编辑设置调整编辑行为例如自动缩进、搜索选项等。\n插件设置加载和配置 Vim 插件。\n快捷键映射自定义快捷键提升编辑效率。\n\n示例配置\n" 全局设置\nset nocompatible " 关闭与 Vi 的兼容模式\nfiletype off " 关闭文件类型检测\n \n" 界面设置\nset number " 显示行号\nsyntax on " 启用语法高亮\nset background=dark " 设置背景色为暗色系\ncolorscheme desert " 使用 desert 颜色主题\n \n" 编辑设置\nset tabstop=4 " 设置 Tab 宽度为 4 个空格\nset shiftwidth=4 " 设置自动缩进的宽度为 4 个空格\nset expandtab " 将 Tab 转换为空格\nset autoindent " 自动缩进新行\nset hlsearch " 高亮搜索结果\nset incsearch " 增量搜索\n \n" 插件设置\ncall plug#begin('~/.vim/plugged')\nPlug 'scrooloose/nerdtree' " 文件树插件\nPlug 'tpope/vim-fugitive' " Git 集成插件\ncall plug#end()\n \n" 快捷键映射\nnnoremap <C-n> :NERDTreeToggle<CR> " Ctrl+n 切换 NERDTree\n常用配置选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项说明示例set nocompatible关闭与 Vi 的兼容模式set nocompatibleset number显示行号set numberset relativenumber显示相对行号set relativenumberset tabstop设置 Tab 宽度以空格数表示set tabstop=4set shiftwidth设置自动缩进的宽度以空格数表示set shiftwidth=4set expandtab将 Tab 转换为空格set expandtabset autoindent自动缩进新行set autoindentset smartindent智能缩进set smartindentset hlsearch高亮搜索结果set hlsearchset incsearch增量搜索set incsearchset ignorecase搜索时忽略大小写set ignorecaseset smartcase智能大小写匹配set smartcasesyntax on启用语法高亮syntax onset background设置背景色dark 或 lightset background=darkcolorscheme设置颜色主题colorscheme desertset cursorline高亮当前行set cursorlineset wrap自动换行显示长行set wrapset nowrap禁止自动换行显示长行set nowrapset linebreak在单词边界处换行set linebreakset showcmd显示部分命令在底部命令行显示set showcmdset ruler显示光标位置行号和列号set rulerset wildmenu命令行补全增强set wildmenuset clipboard使用系统剪贴板set clipboard=unnamedplusset backspace设置退格键的行为set backspace=indent,eol,startset mouse启用鼠标操作a 为全部模式启用set mouse=aset splitbelow新窗口在当前窗口下方打开set splitbelowset splitright新窗口在当前窗口右侧打开set splitrightset foldmethod设置折叠方法syntax、indent 等set foldmethod=syntaxset foldlevel设置折叠级别set foldlevel=99set termguicolors启用真彩色支持需要终端支持set termguicolorsset guifont设置 GUI 字体(在 GUI Vim 中使用set guifont=Monaco:h12set encoding设置文件编码set encoding=utf-8filetype plugin indent on启用文件类型检测和插件filetype plugin indent onset spell启用拼写检查set spellset spelllang设置拼写检查语言set spelllang=en_usset list显示不可见字符set listset listchars设置不可见字符的显示方式set listchars=tab:>-,trail:~,eol:$set undofile启用撤销文件set undofileset undodir设置撤销文件的保存路径set undodir=~/.vim/undodirset backup启用备份文件set backupset backupdir设置备份文件的保存路径set backupdir=~/.vim/backupset updatetime设置交换文件的更新频率毫秒set updatetime=300\n快捷键映射\n自定义快捷键\nVim 提供了强大的快捷键映射功能,用户可以根据需要自定义快捷键。常用的映射命令有:\n\nmap通用映射\nnmap普通模式下的映射\nimap插入模式下的映射\nvmap可视模式下的映射\n\nnnoremap <C-s> :w<CR> " 在普通模式下Ctrl+s 保存文件\ninoremap <C-c> <Esc> " 在插入模式下Ctrl+c 切换到普通模式\nvnoremap <C-c> "+y " 在可视模式下Ctrl+c 复制到系统剪贴板\n常用快捷键示例\n以下是一些常用的快捷键示例这些快捷键可以提高日常编辑的效率\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷键配置模式说明示例nnoremap <C-s> :w<CR>普通模式Ctrl+s 保存文件nnoremap <C-s> :w<CR>inoremap <C-c> <Esc>插入模式Ctrl+c 退出插入模式inoremap <C-c> <Esc>vnoremap <C-c> "+y可视模式Ctrl+c 复制到系统剪贴板vnoremap <C-c> "+ynnoremap <C-x> :q<CR>普通模式Ctrl+x 退出 Vimnnoremap <C-x> :q<CR>nnoremap <C-t> :tabnew<CR>普通模式Ctrl+t 打开新标签nnoremap <C-t> :tabnew<CR>nnoremap <C-n> :NERDTreeToggle<CR>普通模式Ctrl+n 切换 NERDTree 文件树nnoremap <C-n> :NERDTreeToggle<CR>nnoremap <Leader>f :Files<CR>普通模式Leader+f 调用 FZF 查找文件nnoremap <Leader>f :Files<CR>nnoremap <Leader>g :Gstatus<CR>普通模式Leader+g 调用 Git 状态nnoremap <Leader>g :Gstatus<CR>nnoremap <Leader>w :w!<CR>普通模式Leader+w 强制保存文件nnoremap <Leader>w :w!<CR>nnoremap <Leader>q :q!<CR>普通模式Leader+q 强制退出 Vimnnoremap <Leader>q :q!<CR>nnoremap <Leader>r :source $MYVIMRC<CR>普通模式Leader+r 重新加载 vimrc 文件nnoremap <Leader>r :source $MYVIMRC<CR>vnoremap <Leader>y "+y可视模式Leader+y 复制选中文本到系统剪贴板vnoremap <Leader>y "+ynnoremap <Leader>p "+p普通模式Leader+p 从系统剪贴板粘贴nnoremap <Leader>p "+pnnoremap <Leader>t :terminal<CR>普通模式Leader+t 打开终端nnoremap <Leader>t :terminal<CR>nnoremap <C-j> :cnext<CR>普通模式Ctrl+j 跳到下一个 QuickFix 项nnoremap <C-j> :cnext<CR>nnoremap <C-k> :cprev<CR>普通模式Ctrl+k 跳到上一个 QuickFix 项nnoremap <C-k> :cprev<CR>nnoremap <Leader>n :nohlsearch<CR>普通模式Leader+n 取消搜索高亮nnoremap <Leader>n :nohlsearch<CR>nnoremap <Leader>e :e ~/.vimrc<CR>普通模式Leader+e 打开 vimrc 文件nnoremap <Leader>e :e ~/.vimrc<CR>nnoremap <Leader>d "_d普通模式Leader+d 删除但不复制到寄存器nnoremap <Leader>d "_d\nVim 插件管理\n插件管理工具\nVundle\nVundle 是一个流行的 Vim 插件管理工具,安装步骤如下:\n\n\n克隆 Vundle 仓库到 Vim 的插件目录:\n$ git clone github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim\n\n\n在 vimrc 文件中添加以下内容:\nset nocompatible " 关闭 Vi 兼容模式\nfiletype off " 关闭文件类型检测\n \n" 设置 Vundle\nset rtp+=~/.vim/bundle/Vundle.vim\ncall vundle#begin()\n" 在此处添加插件\nPlugin 'VundleVim/Vundle.vim'\ncall vundle#end() " 所有插件必须在这一行之前\n \nfiletype plugin indent on " 启用文件类型检测\n\n\n基本使用\n\n安装插件 在 vimrc 中添加插件后,启动 Vim 并运行 :PluginInstall。\n更新插件 启动 Vim 并运行 :PluginUpdate。\n删除插件 从 vimrc 中移除插件行,启动 Vim 并运行 :PluginClean。\n\nVim-plug\nvim-plug 是一个现代的 Vim 插件管理工具,安装步骤如下:\n\n\n下载 vim-plug 并放入 autoload 目录:\n$ curl -fLo ~/.vim/autoload/plug.vim --create-dirs raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim\n\n\n在 vimrc 文件中添加以下内容:\ncall plug#begin('~/.vim/plugged')\n" 在此处添加插件\nPlug 'junegunn/vim-plug'\ncall plug#end()\n\n\n基本使用\n\n安装插件 在 vimrc 中添加插件后,启动 Vim 并运行 :PlugInstall。\n更新插件 启动 Vim 并运行 :PlugUpdate。\n删除插件 从 vimrc 中移除插件行,启动 Vim 并运行 :PlugClean。\n\n常用插件\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n插件功能描述安装配置示例基于 vim-plug常用命令或快捷键NERDTree文件树管理Plug 'preservim/nerdtree':NERDTreeTogglefzf.vim模糊查找Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }:Files :Buffersctrlp.vim文件和缓冲区切换Plug 'ctrlpvim/ctrlp.vim':CtrlPYouCompleteMe代码补全Plug 'ycm-core/YouCompleteMe' (需要编译安装)自动代码补全Syntastic语法检查Plug 'vim-syntastic/syntastic':SyntasticCheckvim-airline状态栏美化Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline-themes'自动启用状态栏美化vim-fugitiveGit 集成Plug 'tpope/vim-fugitive':Gstatus :Gcommit :Gpush :Gpullvim-surround快速修改括号、引号等符号Plug 'tpope/vim-surround'ysiw] ds' cs"'vim-commentary快速注释代码Plug 'tpope/vim-commentary'gc + 动作vim-gitgutter显示 Git 更改信息Plug 'airblade/vim-gitgutter'自动显示更改标记\n配置示例\ncall plug#begin('~/.vim/plugged')\n \n" 文件树管理\nPlug 'preservim/nerdtree'\n \n" 模糊查找\nPlug 'junegunn/fzf', { 'do': { -> fzf#install() } }\nPlug 'junegunn/fzf.vim'\n \n" 文件和缓冲区切换\nPlug 'ctrlpvim/ctrlp.vim'\n \n" 状态栏美化\nPlug 'vim-airline/vim-airline'\nPlug 'vim-airline/vim-airline-themes'\n \n" Git 集成\nPlug 'tpope/vim-fugitive'\n \n" 快速修改括号、引号等符号\nPlug 'tpope/vim-surround'\n \n" 快速注释代码\nPlug 'tpope/vim-commentary'\n \n" 显示 Git 更改信息\nPlug 'airblade/vim-gitgutter'\n \ncall plug#end()\n \n" 基本设置\nset nocompatible\nset number\nset relativenumber\nset tabstop=4\nset shiftwidth=4\nset expandtab\nset autoindent\nset hlsearch\nset incsearch\nset ignorecase\nset smartcase\nsyntax on\nset background=dark\ncolorscheme desert\nset cursorline\nset wrap\nset showcmd\nset ruler\nset wildmenu\nset clipboard=unnamedplus\nset backspace=indent,eol,start\nset mouse=a\nset splitbelow\nset splitright\nset foldmethod=syntax\nset foldlevel=99\nset termguicolors\n \n" 快捷键映射\nnnoremap <C-n> :NERDTreeToggle<CR>\nnnoremap <C-p> :CtrlP<CR>\nnnoremap <Leader>f :Files<CR>\nnnoremap <Leader>g :Gstatus<CR>\nnnoremap <Leader>w :w!<CR>\nnnoremap <Leader>q :q!<CR>\nnnoremap <Leader>r :source $MYVIMRC<CR>\nvnoremap <Leader>y "+y\nnnoremap <Leader>p "+p\nnnoremap <Leader>t :terminal<CR>\nnnoremap <C-j> :cnext<CR>\nnnoremap <C-k> :cprev<CR>\nnnoremap <Leader>n :nohlsearch<CR>\nnnoremap <Leader>e :e ~/.vimrc<CR>\nnnoremap <Leader>d "_d\n \n" Airline 主题\nlet g:airline_theme='luna'\n \n" GitGutter 配置\nlet g:gitgutter_enabled = 1\n "},"Technology/GettingStarted/命令行工具/Vim/3.Vim-高级功能":{"title":"Vim 高级功能","links":[],"tags":["技术/入门","Vim"],"content":"高级技巧\n高级文本操作\n正则表达式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令或表达式说明向前搜索/pattern向前搜索匹配的模式向后搜索?pattern向后搜索匹配的模式全文替换:%s/pattern/replacement/g全文替换所有匹配的模式当前行替换:s/pattern/replacement/g替换当前行所有匹配的模式删除行首空白:%s/^\\s\\+//g删除每行开头的空白字符删除行尾空白:%s/\\s\\+$//g删除每行结尾的空白字符匹配任意字符.匹配任意字符匹配数字字符\\d匹配数字字符匹配非数字字符\\D匹配非数字字符匹配字母或数字字符\\w匹配字母或数字字符匹配非字母或数字字符\\W匹配非字母或数字字符匹配行首^匹配行首匹配行尾$匹配行尾\n多行编辑\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令说明行可视模式V进入行可视模式字符可视模式v进入字符可视模式块可视模式Ctrl+v进入块可视模式在每行开头添加:%s/^/#/使用正则表达式在每行开头添加 #在每行结尾添加:%s/$/;/使用正则表达式在每行结尾添加 ;\n宏录制与播放\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令说明录制宏qx ... q开始录制宏x 是寄存器名,执行一系列命令后停止录制播放宏@x播放寄存器 x 中的宏重复播放宏@@重复播放上一个宏多次播放宏10@x播放寄存器 x 中的宏 10 次\nVimScript\n基本语法\nVimScript 是 Vim 的脚本语言,用于扩展和定制 Vim 的功能。以下是一些基本语法:\n" 这是一个注释\n \n" 变量\nlet myvar = 42 " 整数变量\nlet mystr = "Hello" " 字符串变量\n \n" 条件语句\nif myvar > 0\n echo "Positive"\nelseif myvar == 0\n echo "Zero"\nelse\n echo "Negative"\nendif\n \n" 循环语句\nlet i = 0\nwhile i < 5\n echo i\n let i += 1\nendwhile\n \nfor item in [1, 2, 3, 4, 5]\n echo item\nendfor\n函数和变量\n" 定义函数\nfunction! MyFunction(arg)\n echo a:arg\nendfunction\n \n" 调用函数\ncall MyFunction("Hello")\n \n" 局部变量\nfunction! MyFunction()\n let l:localVar = "I am local"\n echo l:localVar\nendfunction\n \n" 全局变量\nlet g:globalVar = "I am global"\necho g:globalVar\n编写和调试简单的 VimScript 脚本\n编写脚本\n将 VimScript 代码写入 .vim 文件,例如 myplugin.vim\n" myplugin.vim\nfunction! SayHello()\n echo "Hello, Vim!"\nendfunction\ncommand! SayHello call SayHello()\n\n加载脚本\n将脚本放入 Vim 的 plugin 目录,启动 Vim 自动加载:\nmkdir -p ~/.vim/plugin\ncp myplugin.vim ~/.vim/plugin/\n\n调试脚本\n使用 echo 命令输出调试信息:\necho "Debug info: " . someVar\n\n使用 :messages 查看所有输出信息。\n自动化\n使用自动命令\n自动命令autocommand允许在特定事件发生时自动执行命令例如文件保存、打开等。\naugroup MyAutoCmd\n autocmd!\n autocmd BufWritePost *.txt :echo "Text file saved!"\naugroup END\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n事件说明权重BufReadPost文件读取后5BufWritePost文件写入后5BufNewFile新建文件4FileType文件类型检测5BufEnter缓冲区进入4BufLeave缓冲区离开4VimEnterVim 启动后5VimLeaveVim 退出前5WinEnter窗口进入3WinLeave窗口离开3\n配置文件模板\n在 ~/.vim/templates/ 目录中创建模板文件,例如 python_template.py\n#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n"""\nCreated on <++>\n \n@author: <++>\n"""\n \ndef main():\n pass\n \nif __name__ == "__main__":\n main()\n使用自动命令应用模板:\naugroup MyTemplates\n autocmd!\n autocmd BufNewFile *.py 0r ~/.vim/templates/python_template.py\naugroup END\n\n高效工作流\n版本控制集成\n使用 Vim-fugitive\n安装 vim-fugitive\n在 vimrc 文件中添加以下内容(以 vim-plug 为例):\ncall plug#begin('~/.vim/plugged')\nPlug 'tpope/vim-fugitive'\ncall plug#end()\n\n基本用法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令说明查看 Git 状态:Gstatus打开一个新窗口显示当前 Git 仓库的状态。可以在该窗口中导航和操作。Git 添加-在 :Gstatus 窗口中,将光标移动到文件名上,按 - 号将文件添加到索引。Git 提交:Gcommit打开一个新的缓冲区输入提交信息完成后保存并关闭缓冲区即可提交。Git 推送:Gpush将本地提交推送到远程仓库。Git 拉取:Gpull从远程仓库拉取最新的代码。Git 日志:Glog显示 Git 提交日志可以在日志中导航和查看每个提交的详细信息。Git 分支:Gbranch显示和管理 Git 分支。\n常用 Git 命令\n在 Vim 中,使用 vim-fugitive 可以执行常见的 Git 命令。同时你也可以在 Vim 外部使用 Git 命令行工具:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令说明克隆仓库git clone <repository_url>克隆一个远程仓库到本地。查看状态git status查看当前仓库的状态。添加文件git add <file>添加文件到索引。提交更改git commit -m "Commit message"提交已添加的更改。推送到远程仓库git push将本地提交推送到远程仓库。拉取最新代码git pull从远程仓库拉取最新的代码。创建新分支git checkout -b <new_branch>创建一个新的分支并切换到该分支。合并分支git merge <branch>将指定分支合并到当前分支。\n项目管理\nNERDTree\n在 vimrc 文件中添加以下内容(以 vim-plug 为例):\ncall plug#begin('~/.vim/plugged')\nPlug 'preservim/nerdtree'\ncall plug#end()\n\n打开/关闭 NERDTree\n:NERDTreeToggle\n\n或者添加快捷键映射\nnnoremap <C-n> :NERDTreeToggle<CR>\n\n在 NERDTree 中导航\n\n使用 j 和 k 键上下移动\n使用 o 键打开文件或目录\n使用 x 键关闭目录\n\n显示隐藏文件\n:NERDTreeShowHidden\n\n配置项目相关设置\n项目特定的 vimrc\n在项目根目录下创建一个 .vimrc 文件,包含项目特定的 Vim 配置。然后在主 vimrc 中添加以下内容:\nif filereadable("path/to/project/.vimrc")\n source path/to/project/.vimrc\nendif\n\n自动切换项目配置\n可以使用 vim-rooter 插件自动切换项目根目录并加载项目特定的配置。在 vimrc 中添加以下内容:\ncall plug#begin('~/.vim/plugged')\nPlug 'airblade/vim-rooter'\ncall plug#end()\nlet g:rooter_patterns = ['.git', '.hg', '.svn', 'Makefile']\n\n代码补全与调试\nYouCompleteMe 代码补全\nYouCompleteMe 是一个强大的代码补全插件,需要编译安装。具体步骤如下:\n\n\n安装依赖以 Ubuntu 为例):\nsudo apt install build-essential cmake python3-dev\n\n\n\n安装 YouCompleteMe\ngit clone github.com/ycm-core/YouCompleteMe.git ~/.vim/bundle/YouCompleteMe\ncd ~/.vim/bundle/YouCompleteMe\ngit submodule update --init --recursive\npython3 install.py --all\n\n\n\n在 vimrc 中添加以下内容:\ncall plug#begin('~/.vim/plugged')\nPlug 'ycm-core/YouCompleteMe'\ncall plug#end()\n\n\n\nDeoplete 代码补全\nDeoplete 是另一种流行的代码补全插件,基于 Neovim。\n\n\n安装依赖以 Neovim 为例):\npip install neovim\n\n\n\n在 vimrc 中添加以下内容:\ncall plug#begin('~/.vim/plugged')\nPlug 'Shougo/deoplete.nvim', {'do': ':UpdateRemotePlugins'}\nPlug 'Shougo/neosnippet.vim'\nPlug 'Shougo/neosnippet-snippets'\ncall plug#end()\n\nlet g:deoplete#enable_at_startup = 1\n\n\n\nVimspector 代码调试\n在 vimrc 文件中添加以下内容(以 vim-plug 为例):\ncall plug#begin('~/.vim/plugged')\nPlug 'puremourning/vimspector'\ncall plug#end()\n\n基本配置\n.vimspector.json 文件,定义调试配置,例如:\n{\n "configurations": {\n "Launch": {\n "adapter": "debugpy",\n "configuration": {\n "request": "launch",\n "program": "${workspaceFolder}/your_script.py",\n "console": "integratedTerminal"\n }\n }\n }\n}\n使用\n\n\n启动调试会话\n:VimspectorLaunch\n\n\n\n设置断点 将光标移动到需要设置断点的行,按 F9 键。\n\n\n继续执行、单步执行和停止调试 使用 F5、F10、F11 和 F12 键进行调试控制。\n\n\n性能优化\n启动优化\n延迟加载插件\n延迟加载插件可以显著提高 Vim 的启动速度,只在需要时加载插件。\n使用 vim-plug 进行延迟加载:\n\n\n在 vimrc 中配置延迟加载:\ncall plug#begin('~/.vim/plugged')\nPlug 'tpope/vim-fugitive', { 'on': 'Gstatus' }\nPlug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }\ncall plug#end()\n\n以上配置将 vim-fugitive 插件仅在执行 :Gstatus 命令时加载NERDTree 插件仅在执行 :NERDTreeToggle 命令时加载。\n\n\n使用 lazy.nvim 插件管理器:\nlazy.nvim 是一个专门用于延迟加载插件的插件管理器。\n\n\n安装 lazy.nvim\ngit clone github.com/folke/lazy.nvim.git ~/.vim/pack/lazy/start/lazy.nvim\n\n\n\n配置延迟加载\ncall lazy#load_plugin('nerdtree', { 'on': 'NERDTreeToggle' })\n\n\n\n精简配置文件\n移除不必要的配置\n定期检查 vimrc 文件,移除不再使用的配置和插件,以减少 Vim 的启动时间和运行负担。\n分离插件配置\n将插件的配置分离到独立的文件中以保持 vimrc 简洁。例如,将 NERDTree 的配置放在 ~/.vim/plugin/nerdtree.vim 中:\n" ~/.vim/plugin/nerdtree.vim\nnnoremap <C-n> :NERDTreeToggle<CR>\n\n使用本地配置\n根据项目需求在项目根目录下创建 .vimrc 或 .vim/ 目录,存放项目特定的配置文件,以避免在全局配置中添加过多内容。\n系统集成\n将 Vim 与 Tmux 结合使用\ntmux 是一个终端复用器,允许你在一个终端窗口中运行多个会话,与 Vim 结合使用可以大大提高工作效率。\n安装 tmux\n在 Linux 或 MacOS 中,可以使用包管理器安装 tmux\nsudo apt install tmux # Debian/Ubuntu\nbrew install tmux # macOS\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能命令说明启动 tmux 会话tmux启动一个新的 tmux 会话新建会话tmux new -s session_name创建一个名为 session_name 的新会话附加会话tmux attach -t session_name附加到一个名为 session_name 的会话列出会话tmux ls列出所有 tmux 会话杀死会话tmux kill-session -t session_name杀死一个名为 session_name 的会话分离会话Ctrl-b d分离当前会话新建窗口Ctrl-b c创建一个新窗口切换窗口Ctrl-b n切换到下一个窗口切换窗口Ctrl-b p切换到上一个窗口重命名窗口Ctrl-b ,重命名当前窗口分割窗格Ctrl-b %垂直分割当前窗格分割窗格Ctrl-b "水平分割当前窗格切换窗格Ctrl-b o切换到下一个窗格关闭窗格Ctrl-b x关闭当前窗格同步窗格Ctrl-b :setw synchronize-panes on在所有窗格中同步输入切换会话Ctrl-b s列出所有会话并切换\n与 Vim 集成:\n在 vimrc 中添加快捷键映射,方便与 tmux 交互:\nnnoremap <silent> <Leader>h :TmuxNavigateLeft<CR>\nnnoremap <silent> <Leader>j :TmuxNavigateDown<CR>\nnnoremap <silent> <Leader>k :TmuxNavigateUp<CR>\nnnoremap <silent> <Leader>l :TmuxNavigateRight<CR>\n\n需要安装 christoomey/vim-tmux-navigator 插件:\ncall plug#begin('~/.vim/plugged')\nPlug 'christoomey/vim-tmux-navigator'\ncall plug#end()\n\n在终端中使用 Vim\n在终端中使用 Vim 可以提高工作效率,特别是当你需要频繁切换编辑器和命令行时。\n配置终端\n选择一个支持丰富功能的终端例如 iTerm2macOS、Alacritty跨平台、GNOME TerminalLinux。\n终端快捷键配置\n根据需要配置终端快捷键方便打开 Vim。例如在 iTerm2 中,可以设置快捷键快速打开新的终端窗口或标签,并启动 Vim。\nShell 集成:\n在 ~/.bashrc 或 ~/.zshrc 中添加别名和函数,提高使用 Vim 的效率:\nalias vi="vim"\nalias svi="sudo vim"\nalias vrc="vim ~/.vimrc"\n \n# 快速打开项目目录中的 Vim\nfunction vproj() {\n cd ~/projects/$1 && vim\n}\n使用 FZF 进行文件搜索:\nFZF 是一个命令行模糊查找工具,可以与 Vim 集成,快速搜索和打开文件。\n\n\n安装 FZF\ngit clone --depth 1 github.com/junegunn/fzf.git ~/.fzf\n~/.fzf/install\n\n\n在 vimrc 中配置 FZF\ncall plug#begin('~/.vim/plugged')\nPlug 'junegunn/fzf'\nPlug 'junegunn/fzf.vim'\ncall plug#end()\n \n" 使用 FZF 查找文件\nnnoremap <Leader>f :Files<CR>\n\n"},"Technology/GettingStarted/命令行工具/Vim/4.Vim-实用技巧":{"title":"Vim 实用技巧","links":[],"tags":["技术/入门","Vim"],"content":"文件备份和编辑\n备份当前文件并打开进行编辑避免无法还原旧配置文件。\n:w hosts.back.240808 | e!\n\n快速查找并替换\n在所有文本文件中查找并替换某个模式。\n:args **/*.txt | argdo %s/pattern/replacement/g | update\n\n这个命令会在所有文本文件中查找并替换 pattern 为 replacement并保存所有修改。\n批量处理文件\n批量删除所有文件的行尾空白字符。\n:args **/* | argdo %s/\\s\\+$//e | update\n\n这个命令会在所有文件中删除行尾的空白字符并保存所有修改。\n快速拼接文件内容\n将多个文件的内容拼接到当前文件。\n:r !cat file1.txt file2.txt file3.txt\n\n这个命令将 file1.txt、file2.txt 和 file3.txt 的内容插入到当前文件光标所在位置。\n自动补全并打开文件\n自动补全路径并打开文件。\n:e <C-R>=expand("%:p:h") . "/" <C-R>=input("File: ")<CR>\n\n这个命令会打开一个提示输入文件名后会自动补全路径并打开文件。\n快速窗口管理\n垂直分割窗口打开文件关闭其他窗口\n:vsplit file.txt | only\n\n这个命令会垂直分割窗口并打开 file.txt然后关闭其他所有窗口。\n自动格式化代码\n格式化当前文件并保存\ngg=G`` | w\n\n这个命令会格式化整个文件并保持光标位置不变然后保存文件。\n批量执行宏\n在所有文本文件中执行宏。\n:args **/*.txt | argdo normal @q | update\n\n这个命令会在所有文本文件中执行寄存器 q 中的宏,并保存所有修改。\n快速编译并打开错误列表\n编译当前项目并打开 QuickFix 列表。\n:make | copen\n\n这个命令会编译当前项目并打开 QuickFix 窗口显示错误列表。\n运行代码并显示输出\n运行当前 Python 文件并显示输出\n:w | !python3 %\n\n这个命令会先保存当前文件然后运行它并显示输出。"},"Technology/GettingStarted/命令行工具/Vim/5.Vim-参考手册":{"title":"Vim 参考手册","links":[],"tags":["Vim","技术/入门"],"content":"Vim Cheat Sheet\n全局\n:h[elp] 关键字 - 打开关键字帮助\n:sav[eas] 文件名 - 另存为\n:clo[se] - 关闭当前窗口\n:ter[minal] - 打开一个shell窗口\nK - 打开光标所在单词的man页面\nTip 在终端中运行 vimtutor 以学习最基础的 Vim 命令。\n移动光标\nh - 左移光标\nj - 下移光标\nk - 上移光标\nl - 右移光标\ngj - 下移光标(折行文本)\ngk - 下移光标(折行文本)\nH - 移动到当前页面顶部\nM - 移动到当前页面中间\nL - 移动到当前页面底部\nw - 移动到下个单词开头\nW - 移动到下个单词开头(单词含标点)\ne - 移动到下个单词结尾\nE - 移动到下个单词结尾(单词含标点)\nb - 移动到上个单词开头\nB - 移动到上个单词开头(单词含标点)\nge - 移动到上个单词结尾\ngE - 移动到上个单词结尾(单词含标点)\n% - 跳转到配对的符号(默认支持的配对符号组:: '()', '{}', '[]' - \n 在vim中使用 :h matchpairs 获得更多信息)\n0 - 移动到行首\n^ - 移动到行首的非空白符\n$ - 移动到行尾\ng_ - 移动到行内最后一个非空白符\ngg - 移动到文件第一行\nG - 移动到文件最后一行\n5gg or 5G - 移动到第五行\ngd - 跳转到局部定义\ngD - 跳转到全局定义\nfx - 移动到字符 x 下次出现的位置\ntx - 移动到字符 x 下次出现的位置的前一个字符\nFx - 移动到字符 x 上次出现的位置\nTx - 移动到字符 x 上次出现的位置的后一个字符\n; - 重复之前的f、t、F、T操作\n, - 反向重复之前的f、t、F、T操作\n} - 移动到下一个段落 (当编辑代码时则为函数/代码块)\n{ - 移动到上一个段落 (当编辑代码时则为函数/代码块)\nzz - 移动屏幕使光标居中\nCtrl + e - 向下移动屏幕一行(保持光标不动)\nCtrl + y - 向上移动屏幕一行(保持光标不动)\nCtrl + b - 向上滚动一屏\nCtrl + f - 向下滚动一屏\nCtrl + d - 向下滚动半屏\nCtrl + u - 向上滚动半屏\n插入模式 - 插入/追加文本\ni - 从光标前开始插入字符\nI - 从行首开始插入字符\na - 从光标后开始插入字符\nA - 从行尾开始插入字符\no - 在当前行之下另起一行, 开始插入字符\nO - 在当前行之上另起一行, 开始插入字符\nea - 从当前单词末尾开始插入\nCtrl + h - 在插入模式下,删除光标前的字符\nCtrl + w - 在插入模式下,删除光标前的单词\nCtrl + j - 在插入模式下,另起一行\nCtrl + t - 在插入模式下,向右缩进,宽度由 shiftwidth 控制\nCtrl + d - 在插入模式下,向左缩进,宽度由 shiftwidth 控制\nCtrl + n - 在插入模式下,在光标之前插入自动补全的下一个匹配项\nCtrl + p - 在插入模式下,在光标之前插入自动补全的上一个匹配项\nCtrl + rx - 插入寄存器 x 的内容\nCtrl + ox - 暂时进入正常模式以发出一个正常模式命令 x。\nEsc - 退出插入模式\n编辑文本\nr - 替换当前字符\nR - 在 ESC 按下之前,替换多个字符\nJ - 将下一行合并到当前行, 并在两部分文本之间插入一个空格\ngJ - 将下一行合并到当前行, 两部分文本之间不含空格\ngwip - 重新调整段落\ng~ - 大小写转换操作修饰符\ngu - 小写操作修饰符\ngU - 大写操作修饰符\ncc - 将光标所在的行删除, 然后进入插入模式\nc$ or C - 将光标处到行尾删除, 然后进入插入模式\nciw - 将光标所在的单词删除, 然后进入插入模式\ncw or ce - 从光标位置开始, 修改单词\ns - 删除当前字符, 然后进入插入模式\nS - 清空当前行, 然后进入插入模式 (同cc)\nxp - 当前字符后移\nu - 撤销\nU - 撤销上一次的改动行的操作\nCtrl + r - 重做(取消撤销)\n. - 再次执行上个命令\n选择文本可视化模式\nv - 进入可视化模式, 移动光标高亮选择, 然后可以对选择的文本执行命令(比 y - 复制)\nV - 进入可视化模式(行粒度选择)\no - 切换光标到选择区开头/结尾\nCtrl + v - 进入可视化模式(矩阵选择)\nO - 切换光标到选择区的角\naw - 选择当前单词\nab - 选择被 () 包裹的区域(含括号)\naB - 选择被 {} 包裹的区域(含花括号)\nat - 选择被 <> 标签包裹的区域(含<>标签)\nib - 选择被 () 包裹的区域(不含括号)\niB - 选择被 {} 包裹的区域(不含花括号)\nit - 选择被 <> 标签包裹的区域(不含<>标签)\nEsc - 退出可视化模式\nTip 也可以使用 ( 和 { 分别代替 b 和 B\n可视化模式命令\n> - 向右缩进\n< - 向左缩进\ny - 复制\nd - 剪切\n~ - 大小写切换\nu - 将选中文本转换为小写\nU - 将选中文本转换为大写\n寄存器\n寄存器被存储在 ~/.viminfo 中, 在下次重启 vim 时仍会加载\n:reg[isters] - 显示寄存器内容\n"xy - 复制内容到寄存器 x\n"xp - 粘贴寄存器 x 中的内容\n"+y - 复制内容到系统剪贴板寄存器\n"+p - 粘贴系统剪贴板寄存器的内容\n特殊寄存器\n0 - 上次复制\n" - 未命名寄存器,上次复制或删除\n% - 当前文件名\n# - 轮换文件名\n* - 剪贴板内容 (X11 primary)\n+ - 剪贴板内容 (X11 clipboard)\n/ - 上次搜索的pattern\n: - 上次执行的命令\n. - 上次插入的文本\n- - 上次剪切的短于一行的文本\n= - 表达式寄存器\n_ - 黑洞寄存器\n标记\n:marks - 标记列表\nma - 设置当前位置为标记 a\n`a - 跳转到标记 a 的位置\ny`a - 复制当前位置到标记 a 的内容\n`0 - 跳转到上次 Vim 退出时的位置\n`" - 跳转到上次编辑该文件时的位置\n`. - 跳转到上次修改的位置\n`` - 跳转回上次跳转前的位置\n:ju[mps] - 列出跳转历史记录\nCtrl + i - 跳转至跳转历史中较晚的位置\nCtrl + o - 跳转回跳转历史中较早的位置\n:changes - 列出修改历史记录\ng, - 跳转至修改历史中较晚修改的位置\ng; - 跳转至修改历史中较早修改的位置\nCtrl + ] - 跳转到当前光标位置对应的 tag\nTip 可以使用反引号 (`) 或单引号 () 跳转至标记位置。使用单引号会跳转至该标记所在行行首 (首个非空白字符)。\n宏\nqa - 录制宏 a\nq - 停止录制宏\n@a - 执行宏 a\n@@ - 重新执行上次执行的宏\n剪切, 复制, 粘贴\nyy - 复制当前行\n2yy - 复制 2 行\nyw - 复制当前单词\nyiw - 复制光标处的单词\nyaw - 复制光标处的单词及其前后的空格\ny$ or Y - 复制, 从光标位置到行末\np - 在光标后粘贴\nP - 在光标前粘贴\ngp - 在光标后粘贴并把光标定位于粘贴的文本之后\ngP - 在光标前粘贴并把光标定位于粘贴的文本之后\ndd - 剪切当前行\n2dd - 剪切 2 行\ndw - 剪切当前单词\ndiw - 删除光标处的单词\ndaw - 删除光标处的单词及其前后的空格\nd$ or D - 剪切, 从光标位置到行末 (同 D )\nx - 剪切当前字符\n文字缩进\n>> - 将当前行向右缩进,宽度由 shiftwidth 控制\n<< - 将当前行向左缩进,宽度由 shiftwidth 控制\n>% - 向右缩进 () 或 {} 内的区域 (光标需置于括号上)\n>ib - 向右缩进 () 内的区域\n>at - 向右缩进 <> 标签内的区域\n3== - 自动缩进 3 行\n=% - 自动缩进 () 或 {} 内的区域 (光标需置于括号上)\n=iB - 自动缩进 {} 内的区域 (光标需置于括号上)\ngg=G - 自动缩进整个缓冲区\n]p - 粘贴并调整缩进至当前行\n退出\n:w - 保存\n:w !sudo tee % - 使用 sudo 保存当前文件\n:wq or :x or ZZ - 保存并退出\n:q - 退出(修改未保存时警告)\n:q! or ZQ - 不保存强制退出\n:wqa - 保存所有标签页并全部退出\n查找/替换\n/pattern - 查找 pattern\n?pattern - 向上查找 pattern\n\\vpattern - pattern 中的非字母数字字符被视为正则表达式特殊字符 (不需转义字符)\nn - 查找下一个\nN - 查找上一个\n:%s/old/new/g - 替换全部\n:%s/old/new/gc - (逐个)替换\n:noh[lsearch] - 移除搜索结果的高亮显示\n多文件搜索\n:vim[grep] /pattern/ {`{file}`} - 在多个文件中搜索 pattern\ne.g. :vim[grep] /foo/ **/*\n:cn[ext] - 移动至下一个\n:cp[revious] - 移动至上一个\n:cope[n] - 打开搜索结果列表\n:ccl[ose] - 关闭 quickfix 窗口\n标签\n:tabnew or :tabnew {page.words.file} - 在新标签中打开文件\nCtrl + wT - 将窗口变成标签\ngt or :tabn[ext] - 切换到下一个标签\ngT or :tabp[revious] - 切换到上一个标签\n#gt - 切换到第 # 个标签\n:tabm[ove] # - 移动标签到第 # 位(下标从 0 开始)\n:tabc[lose] - 关闭当前标签\n:tabo[nly] - 关闭其他标签\n:tabdo command - 在所有标签中执行命令 (例如 :tabdo q 关闭所有标签)\n多文件编辑\n:e[dit] 文件名 - 新建缓冲区打开 filename\n:bn[ext] - 切换到下个缓冲区\n:bp[revious] - 切换到上个缓冲区\n:bd[elete] - 关闭缓冲区\n:b[uffer]# - 切换到第 # 个缓冲区\n:b[uffer] file - 用文件名切换缓冲区\n:ls or :buffers - 列出所有打开的缓冲区\n:sp[lit] 文件名 - 新建缓冲区打开 filename 并水平分割窗口\n:vs[plit] 文件名 - 新缓冲区打开 filename 并垂直分割窗口\n:vert[ical] ba[ll] - 垂直分割窗口编辑所有缓冲区\n:tab ba[ll] - 标签页编辑所有缓冲区\nCtrl + ws - 水平分割窗口\nCtrl + wv - 垂直分割窗口\nCtrl + ww - 在窗口间切换\nCtrl + wq - 关闭窗口\nCtrl + wx - 当前窗口与下一个窗口交换位置\nCtrl + w= - 令所有窗口高 & 宽一致\nCtrl + wh - 切换到左侧窗口\nCtrl + wl - 切换到右侧窗口\nCtrl + wj - 切换到下侧窗口\nCtrl + wk - 切换到上侧窗口\nCtrl + wH - 使游标所在视窗全高并移至最左 (最左垂直视窗)\nCtrl + wL - 使游标所在视窗全高并移至最右 (最右垂直视窗)\nCtrl + wJ - 使游标所在视窗全宽并移至最下 (最下水平视窗)\nCtrl + wK - 使游标所在视窗全宽并移至最上 (最上水平视窗)\nDiff\nzf - 定义折叠修饰符\nzd - 删除光标位置的折叠\nza - 展开 & 关闭光标位置的折叠\nzo - 展开光标位置的折叠\nzc - 关闭光标位置的折叠\nzr - 展开同级的所有折叠\nzm - 关闭同级的所有折叠\nzi - 开启 & 关闭折叠功能\n]c - 光标移至下一处差异\n[c - 光标移至上一处差异\ndo or :diffg[et] - 将另一缓冲区中的差异合并至当前缓冲区\ndp or :diffpu[t] - 将当前缓冲区中的差异推送至另一缓冲区\n:diffthis - 令当前窗口成为 diff 模式的窗口之一\n:dif[fupdate] - 强制刷新 diff 的高亮与折叠\n:diffo[ff] - 令当前窗口退出 diff 模式\n折叠命令 (e.g. za) 只作用于当前级别。使用大写字母 (e.g. zA) 令命令作用于全部级别。\n可以直接在终端运行 vimdiff 查看文件间的不同。也可以将该程序设为 git difftool 的选项之一。"},"Technology/GettingStarted/命令行工具/Vim/6.Vim-帮助文档":{"title":"Vim 帮助文档","links":[],"tags":["Vim","技术/入门"],"content":"Vim 中文文档计划\n关于\nVim 是一个功能非常强大,且具有很强扩展性的编辑器。而且 Vim 本身带有一个完备的帮助系统。本项目的目的就是将 Vim 的这些文档翻译成中文,以 便更多的人认识及更好地使用这个非常强大的编辑器。文档分成用户手册和参考手册两部 分,你既可以象使用教程那样循序渐进,也可以快速地查阅来获取帮助。\n在线阅读\n可在线阅读帮助文档的 HTML 版。\nyianwillis.github.io/vimcdoc/\n为了最佳阅读效果请确保你的系统安装了 Noto Sans Mono CJK SC 或 NSimsun 字 体,否则可能有字体不能完全对齐的情况。\n下 载\ngithub.com/yianwillis/vimcdoc/releases 提供发布版本的下载。\n\nPDF 用户手册和参考手册\ntar.gz 包\nWin32 UTF8 版本的中文自动安装程序 (原有的 ANSI 版本不再提供)\n"},"Technology/GettingStarted/开源指南/如何向开源社区提问":{"title":"如何向开源社区提问","links":[],"tags":["社区/开源","技术/入门"],"content":"使用软件产品,或多或少都会遇到问题。对于商业产品,我们可以咨询客服寻求帮助。对于公司自己研发的产品,我们可以直接请教专家同事。但对于开源软件,在遇到问题时,如何才能及时有效地寻求帮助呢?\n本文以开源类库 SeaJS 为例,说说我心目中的最佳实践。\n提问前\n遇到问题时心里都很着急。在决定向开源社区提交问题前最好先做做以下功课\n尝试从官方文档中找到答案\n确保自己阅读过至少一次官方文档。这样在遇到问题时如果能回忆起只言片语就可以再去读一遍相关文档问题往往也就解决了。\nGoogle 是你的朋友\n对于成熟的开源项目你遇到的问题很可能别人也遇到过。这时通过 Google、StackOverflow 等网站的搜索服务,可以帮你快速定位并解决问题。永远记住,地球上的你并不孤单,包括你遇到的问题。\n挖掘 Bug 宝藏\n开源软件一般都会有自己的 Bug 管理方案,比如 WebKit、V8、jQuery、SeaJS 等等。从它们的官网上找到 Bug 管理地址,然后通过搜索看看有无你遇到的问题。对于活跃社区来说,这一招经常很管用。比如 jQuery 的 Bug Tracker通过右上角的 Search Tickets 可以找到非常多有用的信息。一个运作良好的 Bug 库经常是一座巨大的宝藏。SeaJS 是直接通过 GitHub Issues 来管理,你可以在 Issues 中找到很多信息。\n求助身边的朋友\n如果你使用的开源软件在朋友圈或同事圈里也有人使用那么抬起你的脚、或拿起你的电话真挚诚恳的探讨不会遭遇拒绝而会增进友谊。不要犹豫你的内心渴望面对面交流你的朋友也是。\n如果以上 4 步都无法解决你遇到的问题,也别犹豫,立马向开源社区提交问题就好。\n提问时\n提问有很多种比如你认识作者直接面对面请教就行。下面探讨的是如何通过互联网的方式来问问题。\n平和对等的心态\n很多开源软件都是免费的作者往往是业余时间出于兴趣在维护没有义务回答社区问题。提问时不要把自己摆在顾客的位置比如\n\n项目马上要上线了请务必帮忙解决\n这是我的邮箱请及时联系我\n\n另外也不要把自己摆在乞食者的位置比如\n\n冰天雪地跪求解答\n救命啊我的网站挂了\n\n在开源社区一切皆是朋友。无论对方是 Linux 内核的作者,还是某个 jQuery 插件的作者,你和作者都是对等的。你的提问是在帮助开源软件完善。平和对等的心态,可以让你的问题赢得更多人的阅读和思考。\n通过正确的途径提交\n如果遇到问题的开源软件有专门的 Bug 管理系统,请最好到这些指定系统中提交。比如,对于前端开发工程师来说,下面这些 Tracker 系统很重要。\n\njQuery Tickets\nWebKit Bugzilla\nMozilla Bugzilla\n\n还有各个开源类库的 Issues 库,比如 SeaJS 的是seajs/issues\n最不好的途径是\n\nQQ 、阿里旺旺、微信等群组。这些群组主要是用来工作或休闲的。对开源项目来说,在这些地方提问,作者一般不会关注,效率非常低。\n微博、Facebook 等社交网络。不少人在微博上通过 at 或私信询问 SeaJS 问题,这些我经常看不到。看到了,也不情愿回复。微博是扯淡、交流情感的地方,一般是写代码写累了,才去逛逛,很少会有在社交网络上回答技术问题的心情。\n\n通过正确的途径提交问题一般可以让你的问题得到及时准确的回复。\n使用明确、有意义的标题\n抱着平和对等的心态找到合适的途径后就得静下心来将遇到的问题写成文字。书写文字不是一件简单的事情我们可以从遵循一些简单的规则开始。\n首先是标题要简洁清晰要言之有物。比如\n\n我遇到了一个 Ajax 问题\nSeaJS 在我的浏览器上运行不了\n\n上面的标题很糟糕光看标题作者无法知道发生了什么事。当开源社区的问题很多时上面这类标题经常会让作者直接忽视或将优先级降到很低。更妥当的标题是\n\nAjax 请求未返回正确的 responseXML\nSeaJS 2.0 在 IE6 上运行时抛错\n\n明确、有意义的标题可以帮助作者确定问题具体是什么类型、预估需要多少时间解决、是否现在马上解决等。一个好的标题也有利于社区知识的沉淀和后期搜索。标题有如一个人的颜面衣着虽然不是关键但在嘈杂的信息社区中这很重要。\n遵循良好的模板\n如果社区提供了问题模板一定要仔细看下。比如 Google Code 社区,当你创建一个问题时,会自动提供以下模板:\nWhat steps will reproduce the problem? \n该问题的重现步骤是什么\n1. \n2. \n3. \n \nWhat is the expected output? What do you see instead? \n你期待的结果是什么实际看到的又是什么\n \n \nWhat version of the product are you using? On what operating system? \n你正在使用产品的哪个版本在什么操作系统上\n \n \nPlease provide any additional information below.\n如果有的话请在下面提供更多信息。\n遵循这个模板去描述问题经常能省很多事。作者一般也非常欢迎通过模板提交的问题。如果社区没有提供模板也可以自己遵循以上模板来提交。\n下面针对问题内容具体说说一些需要注意的点。\n语法正确、格式清晰\n虽然我们不是作家但正确的语法、清晰的格式可以让读者赏心悦目也就更有心情帮你一起思考解决问题。\n对于很多需要代码来描述的问题要尤其注意格式比如\nseajs.use('jquery',function($){$(document).ready(function() { /* ... */ })});\n可读性不如\nseajs.use('jquery', function($) {\n $(document).ready(function() {\n // ...\n });\n});\nGitHub 的 Markdown 语法可以很好地支持代码排版、语法高亮等建议书写代码时一定要先阅读下说明GitHub Flavored Markdown。这能让你的内容看起来很专业社区也就更有意愿会去帮助你否则糟糕的排版经常带来的是发帖之后的石沉大海。\n描述事实、而不是猜测\n事实是指依次进行了哪些操作、产生了怎样的结果。比如\n\n我在 Windows XP 下用 IE6 打开 seajs.org 后点击“5 分钟上手 SeaJS”这时浏览器弹出脚本错误提示例子显示不正确。\n\n上面是一段比较好的事实描述更好的是把错误提示也截图上来而不要像下面这样猜测\n\nSeaJS 在 IE6 下运行不正常,我怀疑是源码第 213 行有问题。\n\n上面的描述会让作者一头雾水、甚至很恼火。尽量避免猜测性描述除非你能先描述事实在事实描述清楚之后再给出合理的猜测是欢迎的。\n对于前端项目来说如果能提供可重现错误的在线可访问代码那是最好不过的。一旦你这么用心去做了作者往往也会很用心地立马帮你解决。\n描述目标、而不是过程\n经常会有这种情况提问者在脑袋里有个更高层次的目标他们在自以为能达到目标的特定道路上卡住了然后跑来问该怎么走。比如\n\nSeaJS 的 parseMap 方法在遇到 map 的多个配置项同时匹配同一个路径时,应该允许用户指定是全部生效还是仅第一个匹配的配置项生效。\n\n上面这个问题的背后提问者实际上想解决的是如何通过 SeaJS 来做版本管理。提问者选择了通过 map 的方式来实现,但这过程中遇到了问题,因此跑过来继续怎么走。然而,如果只是描述过程,往往会把作者也绕进去。\n实际情况却是提问者选择的路本身就是一条崎岖之路对于要解决的问题实际上有更好的方式。这种情况下描述清楚目标讲清楚要干什么非常重要。\n在描述自己是怎么做之前一定要先描述要做什么。提问题时What 往往比 How 更重要。\n要有具体场景\n无论在开源社区还是微博、知乎等平台上有一种非常常见的问题\n\n如何维护 JavaScript 代码?\n如何使用 SeaJS 进行模块化开发?\n\n这类问题还有很多每每遇到只能笑笑然后悄悄地忽略掉。因此这类问题很难回答就如下面这些问题一样\n\n如何才能让生命有意义\n如何打败淘宝\n\n这类提问者一般比较浮躁经常对问题本身也没有经过思考。踏实的提问者不会让问题浮在空中无法回答而会在具体场景中让问题落地\n\n我的项目有 20 多个 JS 文件,接下来还会急剧增加。目前遇到以下问题……(省略五百字)…… 请问如何维护?\n\n仔细检查、确保准确\n是人都会犯错误特别是在如此快节奏的互联网环境下。好不容易把问题描述清楚时不要急着立刻提交。在提交前至少保证从头到尾再仔细阅读一遍比如语法错误、错别字、标点符号、排版等等。做到这些不光是尊重别人也是尊重自己。\n提问后\n提交问题后建议通过邮件等方式订阅回复。互联网上最有效的沟通方式是异步沟通不要期待作者马上回复也不要心烦意乱着急地等待。出去看看天数数云朵你会逐步明白什么是风轻云淡。\n尽可能补充信息\n在接收到回复时仔细阅读。最经常的情况是社区回复的经常不是你想要的。比如\n\n根据你的描述问题无法重现。能否提供具体使用环境和重现步骤\n\n这时要淡定。仔细看看自己提交的问题描述是否足够清晰如果有可补充的信息尽量补充以帮助作者能尽快定位问题。比如\n\n很抱歉我前面有一步描述不正确实际情况是我是在 IETester 中运行的……\n\n谦和淡定的交流不光能帮助你解决问题还有助于你结交更多朋友。\n适当的总结\n当问题终于解决时建议对问题进行总结。可以编辑原帖也可以通过博客等方式总结。你的总结会让遇到同样问题的朋友们受益并且对自己的技能也是一种提高。前端业界无论国内还是国外有很多牛人之所以成为牛人很大程度上都是因为有总结思考的好习惯。\n不要忘记感谢\n最后记得感谢。很多开源软件的作者都是利用业余时间在创作代码。你的感谢汇集许许多多大家的感谢会让开源社区充满爱与力量。"},"Technology/GettingStarted/开源指南/如何有效报告-BUG":{"title":"如何有效报告 BUG","links":[],"tags":["社区/开源","技术/入门"],"content":"作者Simon Tatham 专业的自由软件程序员\n翻译Dasn\n[ English | Português | 简体中文 | Česky | Dansk | Deutsch | Español | Français | Magyar | Italiano | 日本語 | Nederlands | Polski | Русский | 繁體中文 ]\n引言\n为公众写过软件的人大概都收到过很拙劣的 bug计算机程序代码中的错误或程序运行时的瑕疵——译者注报告例如\n在报告中说“不好用”\n所报告内容毫无意义\n在报告中用户没有提供足够的信息\n在报告中提供了错误信息\n所报告的问题是由于用户的过失而产生的\n所报告的问题是由于其他程序的错误而产生的\n所报告的问题是由于网络错误而产生的\n这便是为什么“技术支持”被认为是一件可怕的工作因为有拙劣的 bug 报告需要处理。然而并不是所有的 bug 报告都令人生厌:我在业余时间维护自由软件,有时我会收到非常清晰、有帮助并且 “有内容” 的 bug 报告。\n在这里我会尽力阐明如何写一个好的 bug 报告。我非常希望每一个人在报告 bug 之前都读一下这篇短文,当然我也希望用户在给我报告 bug 之前已经读过这篇文章。\n简单地说报告 bug 的目的是为了让程序员看到程序的错误。您可以亲自示范,也可以给出能导致程序出错的、详尽的操作步骤。如果程序出错了,程序员会收集额外的信息直到找到错误的原因;如果程序没有出错,那么他们会请您继续关注这个问题,收集相关的信息。\n在 bug 报告里要设法搞清什么是事实例如“我在电脑旁”和“XX 出现了”)什么是推测(例如:“我想问题可能是出在……”)。如果愿意的话,您可以省去推测,但是千万别省略事实。\n当您报告 bug 的时候(既然您已经这么做了),一定是希望 bug 得到及时修正。所以此时针对程序员的任何过激或亵渎的言语(甚至谩骂)都是与事无补的——因为这可能是程序员的错误,也有可能是您的错误,也许您有权对他们发火,但是如果您能多提供一些有用的信息(而不是激愤之词)或许 bug 会被更快的修正。除此以外,请记住:如果是免费软件,作者提供给我们已经是出于好心,所以要是太多的人对他们无礼,他们可能就要“收起”这份好心了。\n“程序不好用”\n程序员不是弱智如果程序一点都不好用他们不可能不知道。他们不知道一定是因为程序在他们看来工作得很正常。所以或者是您作过一些与他们不同的操作或者是您的环境与他们不同。他们需要信息报告 bug 也是为了提供信息。信息总是越多越好。\n许多程序特别是自由软件会公布一个“已知 bug 列表”。如果您找到的 bug 在列表里已经有了,那就不必再报告了,但是如果您认为自己掌握的信息比列表中的丰富,那无论如何也要与程序员联系。您提供的信息可能会使他们更简单地修复 bug。\n本文中提到的都是一些指导方针没有哪一条是必须恪守的准则。不同的程序员会喜欢不同形式的 bug 报告。如果程序附带了一套报告 bug 的准则,一定要读。如果它与本文中提到的规则相抵触,那么请以它为准。\n如果您不是报告 bug而是寻求帮助您应该说明您曾经到哪里找过答案例如我看了第四章和第五章的第二节但我找不到解决的办法。这会使程序员了解用户喜欢到哪里去找答案从而使程序员把帮助文档做得更容易使用。\n“演示给我看”\n报告 bug 的最好的方法之一是“演示”给程序员看。让程序员站在电脑前,运行他们的程序,指出程序的错误。让他们看着您启动电脑、运行程序、如何进行操作以及程序对您的输入有何反应。\n他们对自己写的软件了如指掌他们知道哪些地方不会出问题而哪些地方最可能出问题。他们本能地知道应该注意什么。在程序真的出错之前他们可能已经注意到某些地方不对劲这些都会给他们一些线索。他们会观察程序测试中的每一个细节并且选出他们认为有用的信息。\n这些可能还不够。也许他们觉得还需要更多的信息会请您重复刚才的操作。他们可能在这期间需要与您交流一下以便在他们需要的时候让 bug 重新出现。他们可能会改变一些操作,看看这个错误的产生是个别问题还是相关的一类问题。如果您不走运,他们可能需要坐下来,拿出一堆开发工具,花上几个小时来好好地研究一下。但是最重要的是在程序出错的时候让程序员在电脑旁。一旦他们看到了问题,他们通常会找到原因并开始试着修改。\n“告诉我该怎么做”\n如今是网络时代是信息交流的时代。我可以点一下鼠标把自己的程序送到俄罗斯的某个朋友那里当然他也可以用同样简单的方法给我一些建议。但是如果我的程序出了什么问题我不可能在他旁边。“演示”是很好的办法但是常常做不到。\n如果您必须报告 bug而此时程序员又不在您身边那么您就要想办法让 bug重现在他们面前。当他们亲眼看到错误时就能够进行处理了。\n确切地告诉程序员您做了些什么。如果是一个图形界面程序告诉他们您按了哪个按钮依照什么顺序按的。如果是一个命令行程序精确的告诉他们您键入了什么命令。您应该尽可能详细地提供您所键入的命令和程序的反应。\n把您能想到的所有的输入方式都告诉程序员如果程序要读取一个文件您可能需要发一个文件的拷贝给他们。如果程序需要通过网络与另一台电脑通讯您或许不能把那台电脑复制过去但至少可以说一下电脑的类型和安装了哪些软件如果可以的话。\n“哪儿出错了在我看来一切正常哦”\n如果您给了程序员一长串输入和指令他们执行以后没有出现错误那是因为您没有给他们足够的信息可能错误不是在每台计算机上都出现您的系统可能和他们的在某些地方不一样。有时候程序的行为可能和您预想的不一样这也许是误会但是您会认为程序出错了程序员却认为这是对的。\n同样也要描述发生了什么。精确的描述您看到了什么。告诉他们为什么您觉得自己所看到的是错误的最好再告诉他们您认为自己应该看到什么。如果您只是说“程序出错了”那您很可能漏掉了非常重要的信息。\n如果您看到了错误消息一定要仔细、准确的告诉程序员这确实很重要。在这种情况下程序员只要修正错误而不用去找错误。他们需要知道是什么出问题了系统所报的错误消息正好帮助了他们。如果您没有更好的方法记住这些消息就把它们写下来。只报告“程序出了一个错”是毫无意义的除非您把错误消息一块报上来。\n特殊情况下如果有错误消息号一定要把这些号码告诉程序员。不要以为您看不出任何意义它就没有意义。错误消息号包含了能被程序员读懂的各种信息并且很有可能包含重要的线索。给错误消息编号是因为用语言描述计算机错误常常令人费解。用这种方式告诉您错误的所在是一个最好的办法。\n在这种情形下程序员的排错工作会十分高效。他们不知道发生了什么也不可能到现场去观察所以他们一直在搜寻有价值的线索。错误消息、错误消息号以及一些莫名其妙的延迟都是很重要的线索就像办案时的指纹一样重要保存好。\n如果您使用 UNIX 系统程序可能会产生一个内核输出coredump。内核输出是特别有用的线索来源别扔了它们。另一方面大多数程序员不喜欢收到含有大量内核输出文件的 EMAIL所以在发邮件之前最好先问一下。还有一点要注意内核输出文件记录了完整的程序状态也就是说任何秘密可能当时程序正在处理一些私人信息或秘密数据都可能包含在内核输出文件里。\n“出了问题之后我做了……”\n当一个错误或 bug 发生的时候,您可能会做许多事情。但是大多数人会使事情变的更糟。我的一个朋友在学校里误删了她所有的 Word 文件,在找人帮忙之前她重装了 Word又运行了一遍碎片整理程序这些操作对于恢复文件是毫无益处的因为这些操作搞乱了磁盘的文件区块。恐怕在这个世界上没有一种反删除软件能恢复她的文件了。如果她不做任何操作或许还有一线希望。\n这种用户仿佛一只被逼到墙角的鼬黄鼠狼、紫貂一类的动物——译者注背靠墙壁面对死亡的降临奋起反扑疯狂攻击。他们认为做点什么总比什么都不做强。然而这些在处理计算机软件问题时并不适用。\n不要做鼬做一只羚羊。当一只羚羊面对料想不到的情况或受到惊吓时它会一动不动是为了不吸引任何注意与此同时也在思考解决问题的最好办法如果羚羊有一条技术支持热线此时占线。。然后一旦它找到了最安全的行动方案它便去做。\n当程序出毛病的时候立刻停止正在做的任何操作。不要按任何健。仔细地看一下屏幕注意那些不正常的地方记住它或者写下来。然后慎重地点击“确定” 或“取消”,选择一个最安全的。学着养成一种条件反射——一旦电脑出了问题,先不要动。要想摆脱这个问题,关掉受影响的程序或者重新启动计算机都不好,一个解决问题的好办法是让问题再次产生。程序员们喜欢可以被重现的问题,快乐的程序员可以更快而且更有效率的修复 bug。\n“我想粒子的跃迁与错误的极化有关”\n并不只是非专业的用户才会写出拙劣的 bug 报告,我见过一些非常差的 bug 报告出自程序员之手,有些还是非常优秀的程序员。\n有一次我与另一个程序员一起工作他一直在找代码中的 bug他常常遇到一个 bug但是不会解决于是就叫我帮忙。“出什么毛病了”我问。而他的回答却总是一些关于 bug 的意见。如果他的观点正确,那的确是一件好事。这意味着他已经完成了工作的一半,并且我们可以一起完成另一半工作。这是有效率并有用的。\n但事实上他常常是错的。这就会使我们花上半个小时在原本正确的代码里来回寻找错误而实际上问题出在别的地方。我敢肯定他不会对医生这么做。“大夫我得了 Hydroyoyodyne真是怪病——译者给我开个方子”人们知道不该对一位医生说这些。您描述一下症状哪个地方不舒服哪里疼、起皮疹、发烧……让医生诊断您得了什么病应该怎样治疗。否则医生会把您当做疑心病或精神病患者打发了这似乎没什么不对。\n做程序员也是一样。即便您自己的“诊断”有时真的有帮助也要只说“症状”。“诊断”是可说可不说的但是“症状”一定要说。同样在 bug 报告里面附上一份针对 bug 而做出修改的源代码是有用处的,但它并不能替代 bug 报告本身。\n如果程序员向您询问额外的信息千万别应付。曾经有一个人向我报告 bug我让他试一个命令我知道这个命令不好用但我是要看看程序会返回一个什么错误这是很重要的线索。但是这位老兄根本就没试他在回复中说“那肯定不好用”于是我又花了好些时间才说服他试了一下那个命令。\n用户多动动脑筋对程序员的工作是有帮助的。即使您的推断是错误的程序员也应该感谢您至少您想去帮助他们使他们的工作变的更简单。不过千万别忘了报告“症状”否则只会使事情变得更糟。\n“真是奇怪刚才还不好用怎么现在又好了”\n“间歇性错误”着实让程序员发愁。相比之下进行一系列简单的操作便能导致错误发生的问题是简单的。程序员可以在一个便于观察的条件下重复那些操作观察每一个细节。太多的问题在这种情况下不能解决例如程序每星期出一次错或者偶然出一次错或者在程序员面前从不出错程序员一离开就出错。——译者。当然还有就是程序的截止日期到了那肯定要出错。\n大多数“间歇性错误”并不是真正的“间歇”。其中的大多数错误与某些地方是有联系的。有一些错误可能是内存泄漏产生的有一些可能是别的程序在不恰当的时候修改某个重要文件造成的还有一些可能发生在每一个小时的前半个小时中我确实遇到过这种事情。\n同样如果您能使 bug 重现,而程序员不能,那很有可能是他们的计算机和您的计算机在某些地方是不同的,这种不同引起了问题。我曾写过一个程序,它的窗口可以蜷缩成一个小球呆在屏幕的左上角,它在别的计算机上只能在 800x600 的解析度工作,但是在我的机器上却可以在 1024x768 下工作。\n程序员想要了解任何与您发现的问题相关的事情。有可能的话您到另一台机器上试试多试几次两次三次看看问题是不是经常发生。如果问题出现在您进行了一系列操作之后不是您想让它出现它就会出现这就有可能是长时间的运行或处理大文件所导致的错误。程序崩溃的时候您要尽可能的记住您都做了些什么并且如果您看到任何图形,也别忘了提一下。您提供的任何事情都是有帮助的。即使只是概括性的描述(例如:当后台有 EMACS 运行时,程序常常出错),这虽然不能提供导致问题的直接线索,但是可能帮助程序员重现问题。\n最重要的是程序员想要确定他们正在处理的是一个真正的“间歇性错误”呢还是一个在另一类特定的计算机上才出现的错误。他们想知道有关您计算机的许多细节以便了解您的机器与他们的有什么不同。有许多细节都依仗特定的程序但是有一件东西您一定要提供——版本号。程序的版本、操作系统的版本以及与问题有关的程序的版本。\n“我把磁盘装进了 Windows……”\n表意清楚在一份 bug 报告里是最基本的要求。如果程序员不知道您说的是什么意思,那您就跟没说一样。我收到的 bug 报告来自世界各地,有许多是来自非英语国家,他们通常为自己的英文不好而表示歉意。总的来说,这些用户发来的 bug 报告通常是清晰而且有用的。几乎所有不清晰的 bug 报告都是来自母语是英语的人,他们总是以为只要自己随便说说,程序员就能明白。\n\n精确。如果做相同的事情有两种方法请说明您用的是哪一种。例如“我选择了载入可能意味着“我用鼠标点击载入”或“我按下了ALT+L说清楚您用了哪种方法有时候这也有关系。\n详细。信息宁多毋少如果您说了很多程序员可以略去一部分可是如果您说的太少他们就不得不回过头再去问您一些问题。有一次我收到了一份 bug 报告只有一句话,每一次我问他更多事情时,他每次的回复都是一句话,于是我花了几个星期的时间才得到了有用的信息。\n慎用代词。诸如“它”“窗体”这些词当它们指代不清晰的时候不要用。来看看这句话“我运行了 FooApp它弹出一个警告窗口我试着关掉它它就崩溃了。”这种表述并不清晰用户究竟关掉了哪个窗口是警告窗口还是整个 FooApp 程序?您可以这样说,“我运行 FooApp 程序时弹出一个警告窗口我试着关闭警告窗口FooApp 崩溃了。”这样虽然罗嗦点,但是很清晰不容易产生误解。\n检查。重新读一遍您写的 bug 报告,您觉得它是否清晰?如果您列出了一系列能导致程序出错的操作,那么照着做一遍,看看您是不是漏写了一步。\n\n小结\n\nbug 报告的首要目的是让程序员亲眼看到错误。如果您不能亲自做给他们看,给他们能使程序出错的详细的操作步骤。\n如果首要目的不能达成程序员不能看到程序出错。这就需要 bug 报告的第二个目的来描述程序的什么地方出毛病了。详细的描述每一件事情:您看到了什么,您想看到什么,把错误消息记下来,尤其是“错误消息号”。\n当您的计算机做了什么您料想不到的事不要动在您平静下来之前什么都别做。不要做您认为不安全的事。\n尽量试着自己“诊断”程序出错的原因如果您认为自己可以的话。即使做出了“诊断”您仍然应该报告“症状”。\n如果程序员需要请准备好额外的信息。如果他们不需要就不会问您要。他们不会故意为难自己。您手头上一定要有程序的版本号它很可能是必需品。\n表述清楚确保您的意思不能被曲解。\n总的来说最重要的是要做到精确。程序员喜欢精确。\n\n\n\n声明* 我从没有真的看见过鼬和羚羊,我的比喻可能不恰当。\n\n版权所有 Simon Tatham 1999\n本文属于 OPLOpenContent License请在复制和使用本文时自觉遵守 OPL。\n对本文的任何意见和批评请发送至\n英文版anakin@pobox.com\n中文版dasn@users.sf.net"},"Technology/GettingStarted/开源指南/开源指北":{"title":"开源指北","links":[],"tags":["社区/开源","技术/入门"],"content":"一份给开源新手的保姆级开源百科,由 Gitee 开发维护。\n仓库地址开源指北\n在线阅读开源指北\n\n开源故事听一听「过来人」们的经验和故事\nGit 教程:一份简单易懂的 Git 入门指导教程\n"},"Technology/GettingStarted/开源指南/提问的智慧":{"title":"提问的智慧","links":[],"tags":["社区/开源","技术/入门"],"content":"How To Ask Questions The Smart Way\nCopyright © 2001,2006,2014 Eric S. Raymond, Rick Moen\n本指南英文版版权为 Eric S. Raymond, Rick Moen 所有。\n原文网址www.catb.org/~esr/faqs/smart-questions.html\nCopyleft 2001 by D.H.Grand(nOBODY/Ginux), 2010 by Gasolin, 2015 by Ryan Wu\n本中文指南是基于原文 3.10 版以及 2010 年由 Gasolin 所翻译版本的最新翻译;\n协助指出翻译问题请 发 issue或直接 发 pull request 给我。\n声明\n许多项目在他们的使用协助/说明网页中链接了本指南,这么做很好,我们也鼓励大家都这么做。但如果你是负责管理这个项目网页的人,请在超链接附近的显著位置上注明:\n本指南不提供此项目的实际支持服务\n我们已经深刻领教到少了上述声明所带来的痛苦。因为少了这点声明我们不停地被一些白痴纠缠。这些白痴认为既然我们发布了这本指南那么我们就有责任解决世上所有的技术问题。\n如果你因寻求某些帮助而阅读本指南并在离开时还觉得可以从本文作者这里得到直接帮助那你就是我们之前说的那些白痴之一。别问我们问题我们只会忽略你。我们在这本指南中想教你如何从那些真正懂得你所遇到的软件或硬件问题的人处取得协助而 99% 的情况下那不会是我们。除非你确定本指南的作者之一刚好是你所遇到的问题领域的专家,否则请不要打扰我们,这样大家都会开心一点。\n简介\n在 黑客 的世界里,当你拋出一个技术问题时,最终是否能得到有用的回答,往往取决于你所提问和追问的方式。本指南将教你如何正确的提问以获得你满意的答案。\n现在开源Open Source软件已经相当盛行您通常可以从其他更有经验的用户那里获得与黑客一样好的答案这是件好事和黑客相比用户们往往对那些新手常遇到的问题更宽容一些。尽管如此以我们在此推荐的方式对待这些有经验的用户通常也是从他们那里获得有用答案的最有效方式。\n首先你应该明白黑客们喜爱有挑战性的问题或者能激发他们思维的好问题。如果我们并非如此那我们也不会成为你想询问的对象。如果你给了我们一个值得反复咀嚼玩味的好问题我们自会对你感激不尽。好问题是激励是厚礼。好问题可以提高我们的理解力而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言“好问题”是诚挚的大力称赞。\n尽管如此黑客们有着蔑视或傲慢面对简单问题的坏名声这有时让我们看起来对新手、无知者似乎较有敌意但其实不是那样的。\n我们不讳言我们对那些不愿思考、或者在发问前不做他们该做的事的人的蔑视。那些人是时间杀手 —— 他们只想索取,从不付出,消耗我们可用在更有趣的问题或更值得回答的人身上的时间。我们称这样的人为 失败者(撸瑟) (由于历史原因,我们有时把它拼作 lusers。\n我们意识到许多人只是想使用我们写的软件他们对学习技术细节没有兴趣。对大多数人而言电脑只是种工具是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做。我们了解这点也从不指望每个人都对这些让我们着迷的技术问题感兴趣。尽管如此我们回答问题的风格是指向那些真正对此有兴趣并愿意主动参与解决问题的人这一点不会变也不该变。如果连这都变了我们就是在降低做自己最擅长的事情上的效率。\n我们在很大程度上是自愿的从繁忙的生活中抽出时间来解答疑惑而且时常被提问淹没。所以我们无情地滤掉一些话题特别是拋弃那些看起来像失败者的家伙以便更高效地利用时间来回答 赢家winner 的问题。\n如果你厌恶我们的态度高高在上或过于傲慢不妨也设身处地想想。我们并没有要求你向我们屈服 —— 事实上,我们大多数人非常乐意与你平等地交流,只要你付出小小努力来满足基本要求,我们就会欢迎你加入我们的文化。但让我们帮助那些不愿意帮助自己的人是没有效率的。无知没有关系,但装白痴就是不行。\n所以你不必在技术上很在行才能吸引我们的注意但你必须表现出能引导你变得在行的特质 —— 机敏、有想法、善于观察、乐于主动参与解决问题。如果你做不到这些使你与众不同的事情,我们建议你花点钱找家商业公司签个技术支持服务合同,而不是要求黑客个人无偿地帮助你。\n如果你决定向我们求助当然你也不希望被视为失败者更不愿成为失败者中的一员。能立刻得到快速并有效答案的最好方法就是像赢家那样提问 —— 聪明、自信、有解决问题的思路,只是偶尔在特定的问题上需要获得一点帮助。\n欢迎对本指南提出改进意见。你可以 email 你的建议至 esr@thyrsus.com 或 respond-auto@linuxmafia.com。然而请注意本文并非 网络礼节 的通用指南,而我们通常会拒绝无助于在技术论坛得到有用答案的建议)。\n在提问之前\n在你准备要通过电子邮件、新闻群组或者聊天室提出技术问题前请先做到以下事情\n\n尝试在你准备提问的论坛的旧文章中搜索答案。\n尝试上网搜索以找到答案。\n尝试阅读手册以找到答案。\n尝试阅读常见问题文件FAQ以找到答案。\n尝试自己检查或试验以找到答案。\n向你身边的强者朋友打听以找到答案。\n如果你是程序开发者请尝试阅读源代码以找到答案。\n\n当你提出问题的时候请先表明你已经做了上述的努力这将有助于树立你并不是一个不劳而获且浪费别人的时间的提问者。如果你能一并表达在做了上述努力的过程中所学到的东西会更好因为我们更乐于回答那些表现出能从答案中学习的人的问题。\n运用某些策略比如先用 Google 搜索你所遇到的各种错误信息(搜索 Google 论坛 和网页),这样很可能直接就找到了能解决问题的文件或邮件列表线索。即使没有结果,在邮件列表或新闻组寻求帮助时加上一句 我在 Google 中搜过下列句子但没有找到什么有用的东西 也是件好事,即使它只是表明了搜索引擎不能提供哪些帮助。这么做(加上搜索过的字串)也让遇到相似问题的其他人能被搜索引擎引导到你的提问来。\n别着急不要指望几秒钟的 Google 搜索就能解决一个复杂的问题。在向专家求助之前再阅读一下常见问题文件FAQ、放轻松、坐舒服一些再花点时间思考一下这个问题。相信我们他们能从你的提问看出你做了多少阅读与思考如果你是有备而来将更有可能得到解答。不要将所有问题一股脑拋出只因你的第一次搜索没有找到答案或者找到太多答案。\n准备好你的问题再将问题仔细的思考过一遍因为草率的发问只能得到草率的回答或者根本得不到任何答案。越是能表现出在寻求帮助前你为解决问题所付出的努力你越有可能得到实质性的帮助。\n小心别问错了问题。如果你的问题基于错误的假设某个普通黑客J. Random Hacker多半会一边在心里想着 蠢问题…,一边用无意义的字面解释来答复你,希望着你会从问题的回答(而非你想得到的答案)中汲取教训。\n绝不要自以为够格得到答案你没有你并没有。毕竟你没有为这种服务支付任何报酬。你将会是自己去挣到一个答案靠提出有内涵的、有趣的、有思维激励作用的问题 —— 一个有潜力能贡献社区经验的问题,而不仅仅是被动的从他人处索取知识。\n另一方面表明你愿意在找答案的过程中做点什么是一个非常好的开端。谁能给点提示、我的这个例子里缺了什么 以及 我应该检查什么地方 比 请把我需要的确切的过程贴出来 更容易得到答复。因为你表现出只要有人能指个正确方向,你就有完成它的能力和决心。\n当你提问时\n慎选提问的论坛\n小心选择你要提问的场合。如果你做了下述的事情你很可能被忽略掉或者被看作失败者\n\n在与主题不合的论坛上贴出你的问题。\n在探讨进阶技术问题的论坛张贴非常初级的问题反之亦然。\n在太多的不同新闻群组上重复转贴同样的问题cross-post。\n向既非熟人也没有义务解决你问题的人发送私人电邮。\n\n黑客会剔除掉那些搞错场合的问题以保护他们沟通的渠道不被无关的东西淹没。你不会想让这种事发生在自己身上的。\n因此第一步是找到对的论坛。再说一次Google 和其它搜索引擎还是你的朋友用它们来找到与你遭遇到困难的软硬件问题最相关的网站。通常那儿都有常见问题FAQ、邮件列表及相关说明文件的链接。如果你的努力包括阅读 FAQ都没有结果网站上也许还有报告 BugBug-reporting的流程或链接如果是这样链过去看看。\n向陌生的人或论坛发送邮件最可能是风险最大的事情。举例来说别假设一个提供丰富内容的网页的作者会想充当你的免费顾问。不要对你的问题是否会受到欢迎做太乐观的估计 —— 如果你不确定,那就向别处发送,或者压根别发。\n在选择论坛、新闻群组或邮件列表时别太相信名字先看看 FAQ 或者许可书以弄清楚你的问题是否切题。发文前先翻翻已有的话题,这样可以让你感受一下那里的文化。事实上,事先在新闻组或邮件列表的历史记录中搜索与你问题相关的关键词是个极好的主意,也许这样就找到答案了。即使没有,也能帮助你归纳出更好的问题。\n别像机关枪似的一次“扫射”所有的帮助渠道这就像大喊大叫一样会使人不快。要一个一个地来。\n搞清楚你的主题最典型的错误之一是在某种致力于跨平台可移植的语言、套件或工具的论坛中提关于 Unix 或 Windows 操作系统程序界面的问题。如果你不明白为什么这是大错,最好在搞清楚这之间差异之前什么也别问。\n一般来说在仔细挑选的公共论坛中提问会比在私有论坛中提同样的问题更容易得到有用的回答。有几个理由可以支持这点一是看潜在的回复者有多少二是看观众有多少。黑客较愿意回答那些能帮助到许多人的问题。\n可以理解的是老练的黑客和一些热门软件的作者正在接受过多的错发信息。就像那根最后压垮骆驼背的稻草一样你的加入也有可能使情况走向极端 —— 已经好几次了,一些热门软件的作者由于涌入其私人邮箱的大量不堪忍受的无用邮件而不再提供支持。\nStack Overflow\n搜索然后在 Stack Exchange 问。\n近年来Stack Exchange 社区已经成为回答技术及其他问题的主要渠道,尤其是那些开放源码的项目。\n因为 Google 索引是即时的,在看 Stack Exchange 之前先在 Google 搜索。有很高的几率某人已经问了一个类似的问题,而且 Stack Exchange 网站们往往会是搜索结果中最前面几个。如果你在 Google 上没有找到任何答案你再到特定相关主题的网站去找。用标签Tag搜索能让你更缩小你的搜索结果。\nStack Exchange 已经成长到 超过一百个网站,以下是最常用的几个站:\n\nSuper User 是问一些通用的电脑问题,如果你的问题跟代码或是写程序无关,只是一些网络连线之类的,请到这里。\nStack Overflow 是问写程序有关的问题。\nServer Fault 是问服务器和网管相关的问题。\n\n网站和 IRC 论坛\n本地的用户群组user group或者你所用的 Linux 发行版本也许正在宣传他们的网页论坛或 IRC 频道,并提供新手帮助(在一些非英语国家,新手论坛很可能还是邮件列表),这些都是开始提问的好地方,特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。有广告赞助的 IRC 频道是公开欢迎提问的地方,通常可以即时得到回应。\n事实上如果程序出的问题只发生在特定 Linux 发行版提供的版本(这很常见),最好先去该发行版的论坛或邮件列表中提问,再到程序本身的论坛或邮件列表提问。(否则)该项目的黑客可能仅仅回复“使用我们的版本”。\n在任何论坛发文以前先确认一下有没有搜索功能。如果有就试着搜索一下问题的几个关键词也许这会有帮助。如果在此之前你已做过通用的网页搜索你也该这样做还是再搜索一下论坛搜索引擎有可能没来得及索引此论坛的全部内容。\n通过论坛或 IRC 频道来提供用户支持服务有增长的趋势,电子邮件则大多为项目开发者间的交流而保留。所以最好先在论坛或 IRC 中寻求与该项目相关的协助。\n在使用 IRC 的时候,首先最好不要发布很长的问题描述,有些人称之为频道洪水。最好通过一句话的问题描述来开始聊天。\n第二步使用项目邮件列表\n当某个项目提供开发者邮件列表时要向列表而不是其中的个别成员提问即使你确信他能最好地回答你的问题。查一查项目的文件和首页找到项目的邮件列表并使用它。有几个很好的理由支持我们采用这种办法\n\n任何好到需要向个别开发者提出的问题也将对整个项目群组有益。反之如果你认为自己的问题对整个项目群组来说太愚蠢那这也不能成为骚扰个别开发者的理由。\n向列表提问可以分散开发者的负担个别开发者尤其是项目领导人也许太忙以至于没法回答你的问题。\n大多数邮件列表都会被存档那些被存档的内容将被搜索引擎索引。如果你向列表提问并得到解答将来其他人可以通过网页搜索找到你的问题和答案也就不用再次发问了。\n如果某些问题经常被问到开发者可以利用此信息来改进说明文件或软件本身以使其更清楚。如果只是私下提问就没有人能看到最常见问题的完整场景。\n\n如果一个项目既有“用户”也有“开发者”或“黑客”邮件列表或论坛而你又不会动到那些源代码那么就向“用户”列表或论坛提问。不要假设自己会在开发者列表中受到欢迎那些人多半会将你的提问视为干扰他们开发的噪音。\n然而如果你确信你的问题很特别而且在“用户”列表或论坛中几天都没有回复可以试试前往“开发者”列表或论坛发问。建议你在张贴前最好先暗地里观察几天以了解那里的行事方式事实上这是参与任何私有或半私有列表的好主意\n如果你找不到一个项目的邮件列表而只能查到项目维护者的电子邮件地址尽管向他发信。即使是在这种情况下也别假设项目邮件列表不存在。在你的电子邮件中请陈述你已经试过但没有找到合适的邮件列表也提及你不反对将自己的邮件转发给他人许多人认为即使没什么秘密私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人你给了相应人员处置你邮件的选择。\n使用有意义且描述明确的标题\n在邮件列表、新闻群组或论坛中大约 50 字以内的标题是抓住资深专家注意力的好机会。别用喋喋不休的 帮帮忙、跪求、急(更别说 救命啊!!!! 这样让人反感的话,用这种标题会被条件反射式地忽略)来浪费这个机会。不要妄想用你的痛苦程度来打动我们,而应该是在这点空间中使用极简单扼要的描述方式来提出问题。\n一个好标题范例是 目标 —— 差异 式的描述,许多技术支持组织就是这样做的。在 目标 部分指出是哪一个或哪一组东西有问题,在 差异 部分则描述与期望的行为不一致的地方。\n\n蠢问题救命啊我的笔记本电脑不能正常显示了\n聪明问题X.org 6.8.1 的鼠标光标会变形,某牌显卡 MV1005 芯片组。\n更聪明问题X.org 6.8.1 的鼠标光标,在某牌显卡 MV1005 芯片组环境下 - 会变形。\n\n编写 目标 —— 差异 式描述的过程有助于你组织对问题的细致思考。是什么被影响了? 仅仅是鼠标光标或者还有其它图形?只在 X.org 的 X 版中出现?或只是出现在 6.8.1 版中? 是针对某牌显卡芯片组?或者只是其中的 MV1005 型号? 一个黑客只需瞄一眼就能够立即明白你的环境和你遇到的问题。\n总而言之请想像一下你正在一个只显示标题的存档讨论串Thread索引中查寻。让你的标题更好地反映问题可使下一个搜索类似问题的人能够关注这个讨论串而不用再次提问相同的问题。\n如果你想在回复中提出问题记得要修改内容标题以表明你是在问一个问题 一个看起来像 Re: 测试 或者 Re: 新 bug 的标题很难引起足够重视。另外,在不影响连贯性之下,适当引用并删减前文的内容,能给新来的读者留下线索。\n对于讨论串不要直接点击回复来开始一个全新的讨论串这将限制你的观众。因为有些邮件阅读程序比如 mutt ,允许用户按讨论串排序并通过折叠讨论串来隐藏消息,这样做的人永远看不到你发的消息。\n仅仅改变标题还不够。mutt 和其它一些邮件阅读程序还会检查邮件标题以外的其它信息,以便为其指定讨论串。所以宁可发一个全新的邮件。\n在网页论坛上好的提问方式稍有不同因为讨论串与特定的信息紧密结合并且通常在讨论串外就看不到里面的内容故通过回复提问而非改变标题是可接受的。不是所有论坛都允许在回复中出现分离的标题而且这样做了基本上没有人会去看。不过通过回复提问这本身就是暧昧的做法因为它们只会被正在查看该标题的人读到。所以除非你只想在该讨论串当前活跃的人群中提问不然还是另起炉灶比较好。\n使问题容易回复\n以 请将你的回复发送到…… 来结束你的问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦,我们也觉得花几秒钟思考你的问题更麻烦。如果你的邮件程序不支持这样做,换个好点的;如果是操作系统不支持这种邮件程序,也换个好点的。\n在论坛要求通过电子邮件回复是非常无礼的除非你认为回复的信息可能比较敏感有人会为了某些未知的原因只让你而不是整个论坛知道答案。如果你只是想在有人回复讨论串时得到电子邮件提醒可以要求网页论坛发送给你。几乎所有论坛都支持诸如 追踪此讨论串、有回复时发送邮件提醒 等功能。\n使用清晰、正确、精准且合乎语法的语句\n我们从经验中发现粗心的提问者通常也会粗心地写程序与思考我敢打包票。回答粗心大意者的问题很不值得我们宁愿把时间耗在别处。\n正确的拼写、标点符号和大小写是很重要的。一般来说如果你觉得这样做很麻烦不想在乎这些那我们也觉得麻烦不想在乎你的提问。花点额外的精力斟酌一下字句用不着太僵硬与正式 —— 事实上,黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它必须很准确,而且有迹象表明你是在思考和关注问题。\n正确地拼写、使用标点和大小写不要将 its 混淆为 it'sloose 搞成 lose 或者将 discrete 弄成 discreet。不要全部用大写这会被视为无礼的大声嚷嚷全部小写也好不到哪去因为不易阅读。Alan Cox 也许可以这样做,但你不行)。\n更白话的说如果你写得像是个半文盲 [译注:小白],那多半得不到理睬。也不要使用即时通信中的简写或 火星文,如将 的 简化为 d 会使你看起来像一个为了少打几个键而省字的小白。更糟的是,如果像个小孩似地鬼画符那绝对是在找死,可以肯定没人会理你(或者最多是给你一大堆指责与挖苦)。\n如果在使用非母语的论坛提问你可以犯点拼写和语法上的小错但决不能在思考上马虎没错我们通常能弄清两者的分别。同时除非你知道回复者使用的语言否则请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂的语言写的消息。在网络上英语是通用语言用英语书写可以将你的问题在尚未被阅读就被直接删除的可能性降到最低。\n如果英文是你的外语Second language提示潜在回复者你有潜在的语言困难是很好的 [译注:以下附上原文以供使用]\n\nEnglish is not my native language; please excuse typing errors.\n\n\n英文不是我的母语请原谅我的错字或语法。\n\n\nIf you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.\n\n\n如果你说某语言请向我发电邮/私信;\n我需要有人协助我翻译我的问题。\n\n\nI am familiar with the technical terms, but some slang expressions and idioms are difficult for me.\n\n\n我对技术名词很熟悉但对于俗语或是特别用法不甚了解。\n\n\nIve posted my question in $LANGUAGE and English. Ill be glad to translate responses, if you only use one or the other.\n\n\n我把我的问题用某语言和英文写出来。\n如果你只用其中的一种语言回答我会乐意将回复翻译成为你使用的语言。\n\n使用易于读取且标准的文件格式发送问题\n如果你人为地将问题搞得难以阅读它多半会被忽略人们更愿读易懂的问题所以\n\n使用纯文字而不是 HTML (关闭 HTML 并不难)。\n使用 MIME 附件通常是可以的,前提是真正有内容(譬如附带的源代码或 patch而不仅仅是邮件程序生成的模板譬如只是信件内容的拷贝。\n不要发送一段文字只是一行句子但自动换行后会变成多行的邮件这使得回复部分内容非常困难。设想你的读者是在 80 个字符宽的终端机上阅读邮件,最好设置你的换行分割点小于 80 字。\n但是对一些特殊的文件不要设置固定宽度譬如日志文件拷贝或会话记录。数据应该原样包含让回复者有信心他们看到的是和你看到的一样的东西。\n在英语论坛中不要使用 Quoted-Printable MIME 编码发送消息。这种编码对于张贴非 ASCII 语言可能是必须的,但很多邮件程序并不支持这种编码。当它们处理换行时,那些文本中四处散布的 =20 符号既难看也分散注意力,甚至有可能破坏内容的语意。\n绝对永远不要指望黑客们阅读使用封闭格式编写的文档像微软公司的 Word 或 Excel 文件等。大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你家门口时你的反应一样。即便他们能够处理,他们也很厌恶这么做。\n如果你从使用 Windows 的电脑发送电子邮件,关闭微软愚蠢的 智能引号 功能 (从 [选项] > [校订] > [自动校正选项],勾选掉 智能引号 单选框),以免在你的邮件中到处散布垃圾字符。\n在论坛勿滥用 表情符号 和 HTML 功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。这通常不是个好主意,除非你只是对性而不是对答案感兴趣。\n\n如果你使用图形用户界面的邮件程序如微软公司的 Outlook 或者其它类似的),注意它们的默认设置不一定满足这些要求。大多数这类程序有基于选单的 查看源代码 命令,用它来检查发送文件夹中的邮件,以确保发送的是纯文本文件同时没有一些奇怪的字符。\n精确地描述问题并言之有物\n\n仔细、清楚地描述你的问题或 Bug 的症状。\n描述问题发生的环境机器配置、操作系统、应用程序、以及相关的信息提供经销商的发行版和版本号Fedora Core 4、Slackware 9.1 等)。\n描述在提问前你是怎样去研究和理解这个问题的。\n描述在提问前为确定问题而采取的诊断步骤。\n描述最近做过什么可能相关的硬件或软件变更。\n尽可能地提供一个可以 重现这个问题的可控环境 的方法。\n\n尽量去揣测一个黑客会怎样反问你在你提问之前预先将黑客们可能提出的问题回答一遍。\n以上几点中当你报告的是你认为可能在代码中的问题时给黑客一个可以重现你的问题的环境尤其重要。当你这么做时你得到有效的回答的机会和速度都会大大的提升。\nSimon Tatham 写过一篇名为《如何有效的报告 Bug》的出色文章。强力推荐你也读一读。\n话不在多而在精\n你需要提供精确有内容的信息。这并不是要求你简单的把成堆的出错代码或者资料完全转录到你的提问中。如果你有庞大而复杂的测试样例能重现程序挂掉的情境尽量将它剪裁得越小越好。\n这样做的用处至少有三点。 第一,表现出你为简化问题付出了努力,这可以使你得到回答的机会增加; 第二,简化问题使你更有可能得到有用的答案; 第三,在精炼你的 bug 报告的过程中,你很可能就自己找到了解决方法或权宜之计。\n别动辄声称找到 Bug\n当你在使用软件中遇到问题除非你非常、非常的有根据不要动辄声称找到了 Bug。提示除非你能提供解决问题的源代码补丁或者提供回归测试来表明前一版本中行为不正确否则你都多半不够完全确信。这同样适用在网页和文件如果你声称发现了文件的 Bug你应该能提供相应位置的修正或替代文件。\n请记得还有其他许多用户没遇到你发现的问题否则你在阅读文件或搜索网页时就应该发现了你在抱怨前 已经做了这些,是吧?)。这也意味着很有可能是你弄错了而不是软件本身有问题。\n编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了 Bug也就是在质疑他们的能力即使你是对的也有可能会冒犯到其中某部分人。当你在标题中嚷嚷着有 Bug 时,这尤其严重。\n提问时即使你私下非常确信已经发现一个真正的 Bug最好写得像是你做错了什么。如果真的有 Bug你会在回复中看到这点。这样做的话如果真有 Bug维护者就会向你道歉这总比你惹恼别人然后欠别人一个道歉要好一点。\n低声下气不能代替你的功课\n有些人明白他们不该粗鲁或傲慢的提问并要求得到答复但他们选择另一个极端 —— 低声下气:我知道我只是个可悲的新手,一个撸瑟,但...。这既使人困扰,也没有用,尤其是伴随着与实际问题含糊不清的描述时更令人反感。\n别用原始灵长类动物的把戏来浪费你我的时间。取而代之的是尽可能清楚地描述背景条件和你的问题情况。这比低声下气更好地定位了你的位置。\n有时网页论坛会设有专为新手提问的版面如果你真的认为遇到了初学者的问题到那去就是了但一样别那么低声下气。\n描述问题症状而非你的猜测\n告诉黑客们你认为问题是怎样造成的并没什么帮助。如果你的推断如此有效还用向别人求助吗因此要确信你原原本本告诉了他们问题的症状而不是你的解释和理论让黑客们来推测和诊断。如果你认为陈述自己的猜测很重要清楚地说明这只是你的猜测并描述为什么它们不起作用。\n\n蠢问题\n\n\n我在编译内核时接连遇到 SIG11 错误, 我怀疑某条飞线搭在主板的走线上了,这种情况应该怎样检查最好?\n\n\n聪明问题\n\n\n我的组装电脑是 FIC-PA2007 主机板搭载 AMD K6/233 CPU威盛 Apollo VP2 芯片组), 256MB Corsair PC133 SDRAM 内存,在编译内核时,从开机 20 分钟以后就频频产生 SIG11 错误, 但是在头 20 分钟内从没发生过相同的问题。重新启动也没有用,但是关机一晚上就又能工作 20 分钟。 所有内存都换过了,没有效果。相关部分的标准编译记录如下…。\n\n由于以上这点似乎让许多人觉得难以配合这里有句话可以提醒你所有的诊断专家都来自密苏里州。 美国国务院的官方座右铭则是:让我看看(出自国会议员 Willard D. Vandiver 在 1899 年时的讲话:我来自一个出产玉米,棉花,牛蒡和民主党人的国家,滔滔雄辩既不能说服我,也不会让我满意。我来自密苏里州,你必须让我看看。) 针对诊断者而言,这并不是一种怀疑,而只是一种真实而有用的需求,以便让他们看到的是与你看到的原始证据尽可能一致的东西,而不是你的猜测与归纳的结论。所以,大方的展示给我们看吧!\n按发生时间先后列出问题症状\n问题发生前的一系列操作往往就是对找出问题最有帮助的线索。因此你的说明里应该包含你的操作步骤以及机器和软件的反应直到问题发生。在命令行处理的情况下提供一段操作记录例如运行脚本工具所生成的并引用相关的若干行如 20 行)记录会非常有帮助。\n如果挂掉的程序有诊断选项如 -v 的详述开关),试着选择这些能在记录中增加调试信息的选项。记住,多 不等于 好。试着选取适当的调试级别以便提供有用的信息而不是让读者淹没在垃圾中。\n如果你的说明很长如超过四个段落在开头简述问题接下来再按时间顺序详述会有所帮助。这样黑客们在读你的记录时就知道该注意哪些内容了。\n描述目标而不是过程\n如果你想弄清楚如何做某事而不是报告一个 Bug在开头就描述你的目标然后才陈述重现你所卡住的特定步骤。\n经常寻求技术帮助的人在心中有个更高层次的目标而他们在自以为能达到目标的特定道路上被卡住了然后跑来问该怎么走但没有意识到这条路本身就有问题。结果要费很大的劲才能搞定。\n\n蠢问题\n\n\n我怎样才能从某绘图程序的颜色选择器中取得十六进制的 RGB 值?\n\n\n聪明问题\n\n\n我正试着用替换一幅图片的色码color table成自己选定的色码我现在知道的唯一方法是编辑每个色码区块table slot 但却无法从某绘图程序的颜色选择器取得十六进制的 RGB 值。\n\n第二种提问法比较聪明你可能得到像是 建议采用另一个更合适的工具 的回复。\n别要求使用私人电邮回复\n黑客们认为问题的解决过程应该公开、透明此过程中如果更有经验的人注意到不完整或者不当之处最初的回复才能够、也应该被纠正。同时作为提供帮助者可以得到一些奖励奖励就是他的能力和学识被其他同行看到。\n当你要求私下回复时这个过程和奖励都被中止。别这样做让回复者来决定是否私下回答 —— 如果他真这么做了,通常是因为他认为问题编写太差或者太肤浅,以至于不可能使其他人产生兴趣。\n这条规则存在一条有限的例外如果你确信提问可能会引来大量雷同的回复时那么这个神奇的提问句会是 向我发电邮,我将为论坛归纳这些回复。试着将邮件列表或新闻群组从洪水般的雷同回复中解救出来是非常有礼貌的 —— 但你必须信守诺言。\n清楚明确的表达你的问题以及需求\n漫无边际的提问是近乎无休无止的时间黑洞。最有可能给你有用答案的人通常也正是最忙的人他们忙是因为要亲自完成大部分工作。这样的人对无节制的时间黑洞相当厌恶所以他们也倾向于厌恶那些漫无边际的提问。\n如果你明确表述需要回答者做什么如提供指点、发送一段代码、检查你的补丁、或是其他等等就最有可能得到有用的答案。因为这会定出一个时间和精力的上限便于回答者能集中精力来帮你。这么做很棒。\n要理解专家们所处的世界请把专业技能想像为充裕的资源而回复的时间则是稀缺的资源。你要求他们奉献的时间越少你越有可能从真正专业而且很忙的专家那里得到解答。\n所以界定一下你的问题使专家花在辨识你的问题和回答所需要付出的时间减到最少这技巧对你有用答案相当有帮助 —— 但这技巧通常和简化问题有所区别。因此,问 我想更好地理解 X可否指点一下哪有好一点说明 通常比问 你能解释一下 X 吗? 更好。如果你的代码不能运作,通常请别人看看哪里有问题,比要求别人替你改正要明智得多。\n询问有关代码的问题时\n别要求他人帮你调试有问题的代码不提示一下应该从何入手。张贴几百行的代码然后说一声它不能工作 会让你完全被忽略。只贴几十行代码,然后说一句:在第七行以后,我期待它显示 <x>,但实际出现的是 <y> 比较有可能让你得到回应。\n最有效描述程序问题的方法是提供最精简的 Bug 展示测试用例bug-demonstrating test case。什么是最精简的测试用例那是问题的缩影一小个程序片段能刚好展示出程序的异常行为而不包含其他令人分散注意力的内容。怎么制作最精简的测试用例如果你知道哪一行或哪一段代码会造成异常的行为复制下来并加入足够重现这个状况的代码例如足以让这段代码能被编译/直译/被应用程序处理)。如果你无法将问题缩减到一个特定区块,就复制一份代码并移除不影响产生问题行为的部分。总之,测试用例越小越好(查看 话不在多而在精 一节)。\n一般而言要得到一段相当精简的测试用例并不太容易但永远先尝试这样做的是种好习惯。这种方式可以帮助你了解如何自行解决这个问题 —— 而且即使你的尝试不成功,黑客们也会看到你在尝试取得答案的过程中付出了努力,这可以让他们更愿意与你合作。\n如果你只是想让别人帮忙审查Review一下代码在信的开头就要说出来并且一定要提到你认为哪一部分特别需要关注以及为什么。\n别把自己家庭作业的问题贴上来\n黑客们很擅长分辨哪些问题是家庭作业式的问题因为我们中的大多数都曾自己解决这类问题。同样这些问题得由你来搞定你会从中学到东西。你可以要求给点提示但别要求得到完整的解决方案。\n如果你怀疑自己碰到了一个家庭作业式的问题但仍然无法解决试试在用户群组论坛或最后一招在项目的用户邮件列表或论坛中提问。尽管黑客们会看出来但一些有经验的用户也许仍会给你一些提示。\n去掉无意义的提问句\n避免用无意义的话结束提问例如 有人能帮我吗? 或者 这有答案吗?。\n首先如果你对问题的描述不是很好这样问更是画蛇添足。\n其次由于这样问是画蛇添足黑客们会很厌烦你 —— 而且通常会用逻辑上正确,但毫无意义的回答来表示他们的蔑视, 例如:没错,有人能帮你 或者 不,没答案。\n一般来说避免用 是或否、对或错、有或没有 类型的问句,除非你想得到 是或否类型的回答。\n即使你很急也不要在标题写 紧急\n这是你的问题不是我们的。宣称 紧急 极有可能事与愿违:大多数黑客会直接删除无礼和自私地企图即时引起关注的问题。更严重的是,紧急 这个字(或是其他企图引起关注的标题)通常会被垃圾信过滤器过滤掉 —— 你希望能看到你问题的人可能永远也看不到。\n有半个例外的情况是如果你是在一些很高调会使黑客们兴奋的地方也许值得这样去做。在这种情况下如果你有时间压力也很有礼貌地提到这点人们也许会有兴趣回答快一点。\n当然这风险很大因为黑客们兴奋的点多半与你的不同。譬如从 NASA 国际空间站International Space Station发这样的标题没有问题但用自我感觉良好的慈善行为或政治原因发肯定不行。事实上张贴诸如 紧急:帮我救救这个毛茸茸的小海豹! 肯定让你被黑客忽略或惹恼他们,即使他们认为毛茸茸的小海豹很重要。\n如果你觉得这点很不可思议最好再把这份指南剩下的内容多读几遍直到你弄懂了再发文。\n礼多人不怪而且有时还很有帮助\n彬彬有礼多用 请 和 谢谢您的关注,或 谢谢你的关照。让大家都知道你对他们花时间免费提供帮助心存感激。\n坦白说这一点并没有比使用清晰、正确、精准且合乎语法和避免使用专用格式重要也不能取而代之。黑客们一般宁可读有点唐突但技术上鲜明的 Bug 报告,而不是那种有礼但含糊的报告。(如果这点让你不解,记住我们是按问题能教给我们什么来评价问题的价值的)\n然而如果你有一串的问题待解决客气一点肯定会增加你得到有用回应的机会。\n我们注意到自从本指南发布后从资深黑客那里得到的唯一严重缺陷反馈就是对预先道谢这一条。一些黑客觉得 先谢了 意味着事后就不用再感谢任何人的暗示。我们的建议是要么先说 先谢了,然后事后再对回复者表示感谢,或者换种方式表达感激,譬如用 谢谢你的关注 或 谢谢你的关照。)\n问题解决后加个简短的补充说明\n问题解决后向所有帮助过你的人发个说明让他们知道问题是怎样解决的并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注应该在那里贴一个说明比较恰当。\n最理想的方式是向最初提问的话题回复此消息并在标题中包含 已修正,已解决 或其它同等含义的明显标记。在人来人往的邮件列表里,一个看见讨论串 问题 X 和 问题 X - 已解决 的潜在回复者就明白不用再浪费时间了(除非他个人觉得 问题 X 的有趣),因此可以利用此时间去解决其它问题。\n补充说明不必很长或是很深入简单的一句 你好,原来是网线出了问题!谢谢大家 Bill 比什么也不说要来的好。事实上,除非结论真的很有技术含量,否则简短可爱的小结比长篇大论更好。说明问题是怎样解决的,但大可不必将解决问题的过程复述一遍。\n对于有深度的问题张贴调试记录的摘要是有帮助的。描述问题的最终状态说明是什么解决了问题在此之后才指明可以避免的盲点。避免盲点的部分应放在正确的解决方案和其它总结材料之后而不要将此信息搞成侦探推理小说。列出那些帮助过你的名字会让你交到更多朋友。\n除了有礼貌和有内涵以外这种类型的补充也有助于他人在邮件列表/新闻群组/论坛中搜索到真正解决你问题的方案,让他们也从中受益。\n至少这种补充有助于让每位参与协助的人因问题的解决而从中得到满足感。如果你自己不是技术专家或者黑客那就相信我们这种感觉对于那些你向他们求助的大师或者专家而言是非常重要的。问题悬而未决会让人灰心黑客们渴望看到问题被解决。好人有好报满足他们的渴望你会在下次提问时尝到甜头。\n思考一下怎样才能避免他人将来也遇到类似的问题自问写一份文件或加个常见问题FAQ会不会有帮助。如果是的话就将它们发给维护者。\n在黑客中这种良好的后继行动实际上比传统的礼节更为重要也是你如何透过善待他人而赢得声誉的方式这是非常有价值的资产。\n如何解读答案\nRTFM 和 STFW如何知道你已完全搞砸了\n有一个古老而神圣的传统如果你收到 RTFMRead The Fucking Manual 的回应,回答者认为你应该去读他妈的手册。当然,基本上他是对的,你应该去读一读。\nRTFM 有一个年轻的亲戚。如果你收到 STFWSearch The Fucking Web 的回应,回答者认为你应该到他妈的网上搜索。那人多半也是对的,去搜索一下吧。(更温和一点的说法是 Google 是你的朋友!)\n在论坛你也可能被要求去爬爬论坛的旧文。事实上有人甚至可能热心地为你提供以前解决此问题的讨论串。但不要依赖这种关照提问前应该先搜索一下旧文。\n通常用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址而且他们打这些字的时候也正在读着。这些答复意味着回答者认为\n\n你需要的信息非常容易获得\n你自己去搜索这些信息比灌给你能让你学到更多。\n\n你不应该因此不爽依照黑客的标准他已经表示了对你一定程度的关注而没有对你的要求视而不见。你应该对他祖母般的慈祥表示感谢。\n如果还是搞不懂\n如果你看不懂回应别立刻要求对方解释。像你以前试着自己解决问题时那样利用手册FAQ网络身边的高手先试着去搞懂他的回应。如果你真的需要对方解释记得表现出你已经从中学到了点什么。\n比方说如果我回答你看来似乎是 zentry 卡住了你应该先清除它。然后这是一个很糟的后续问题回应zentry 是什么? 好的问法应该是这样:哦~~~我看过说明了但是只有 -z 和 -p 两个参数中提到了 zentries而且还都没有清楚的解释如何清除它。你是指这两个中的哪一个吗还是我看漏了什么\n处理无礼的回应\n很多黑客圈子中看似无礼的行为并不是存心冒犯。相反它是直截了当一针见血式的交流风格这种风格更注重解决问题而不是使人感觉舒服而却模模糊糊。\n如果你觉得被冒犯了试着平静地反应。如果有人真的做了出格的事邮件列表、新闻群组或论坛中的前辈多半会招呼他。如果这没有发生而你却发火了那么你发火对象的言语可能在黑客社区中看起来是正常的而你将被视为有错的一方这将伤害到你获取信息或帮助的机会。\n另一方面你偶尔真的会碰到无礼和无聊的言行。与上述相反对真正的冒犯者狠狠地打击用犀利的语言将其驳得体无完肤都是可以接受的。然而在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外人避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光这时最好不要把手放在键盘上以免冒险。\n有些人断言很多黑客都有轻度的自闭症或亚斯伯格综合症缺少用于润滑人类社会正常交往所需的神经。这既可能是真也可能是假的。如果你自己不是黑客兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了我们不在乎。我们喜欢我们现在这个样子并且通常对病患标记都有站得住脚的怀疑。\nJeff Bigler 的观察总结和这个相关也值得一读 (tact filters)。\n在下一节我们会谈到另一个问题当你行为不当时所会受到的 冒犯。\n如何避免扮演失败者\n在黑客社区的论坛中你以本指南所描述的或类似的方式可能会有那么几次搞砸了。而你会在公开场合中被告知你是如何搞砸的也许攻击的言语中还会带点夹七夹八的颜色。\n这种事发生以后你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被口头攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、不去关马桶盖等等。相反地你该这么做\n熬过去这很正常。事实上它是有益健康且合理的。\n社区的标准不会自行维持它们是通过参与者积极而公开地执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送它不是这样运作的。当有人评论你的一个说法有误或者提出不同看法时坚持声称受到个人攻击也毫无益处这些都是失败者的态度。\n也有其它的黑客论坛受过高礼节要求的误导禁止参与者张贴任何对别人帖子挑毛病的消息并声称 如果你不想帮助用户就闭嘴。 结果造成有想法的参与者纷纷离开,这么做只会使它们沦为毫无意义的唠叨与无用的技术论坛。\n夸张的讲法是你要的是“友善”以上述方式还是有用两个里面挑一个。\n记着当黑客说你搞砸了并且无论多么刺耳告诉你别再这样做时他正在为关心你和他的社区而行动。对他而言不理你并将你从他的生活中滤掉更简单。如果你无法做到感谢至少要表现得有点尊严别大声哀嚎也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者就指望别人像对待脆弱的洋娃娃那样对你。\n有时候即使你没有搞砸或者只是在他的想像中你搞砸了有些人也会无缘无故地攻击你本人。在这种情况下抱怨倒是真的会把问题搞砸。\n这些来找麻烦的人要么是毫无办法但自以为是专家的不中用家伙要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬要么用自己的方式对付他们。这些来找麻烦的人在给他们自己找麻烦这点你不用操心。\n也别让自己卷入口水战最好不要理睬大多数的口水战 —— 当然,这是在你检验它们只是口水战,并且未指出你有搞砸的地方,同时也没有巧妙地将问题真正的答案藏于其后(这也是有可能的)。\n不该问的问题\n以下是几个经典蠢问题以及黑客没回答时心中所想的\n问题我能在哪找到 X 程序或 X 资源?\n问题我怎样用 X 做 Y\n问题如何设定我的 shell 提示?\n问题我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文件转换为 TeX 格式吗?\n问题我的程序/设定/SQL 语句没有用\n问题我的 Windows 电脑有问题,你能帮我吗?\n问题我的程序不会动了我认为系统工具 X 有问题\n问题我在安装 Linux或者 X )时有问题,你能帮我吗?\n问题我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢?\n\n\n问题我能在哪找到 X 程序或 X 资源?\n\n回答就在我找到它的地方啊白痴 —— 搜索引擎的那一头。天哪!难道还有人不会用 Google 吗?\n\n问题我怎样用 X 做 Y\n\n回答如果你想解决的是 Y ,提问时别给出可能并不恰当的方法。这种问题说明提问者不但对 X 完全无知,也对 Y 要解决的问题糊涂,还被特定形势禁锢了思维。最好忽略这种人,等他们把问题搞清楚了再说。\n\n问题如何设定我的 shell 提示??\n\n回答如果你有足够的智慧提这个问题你也该有足够的智慧去 RTFM然后自己去找出来。\n\n问题我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文件转换为 TeX 格式吗?\n\n回答试试看就知道了。如果你试过你就知道了答案就不用浪费我的时间了。\n\n问题我的{程序/设定/SQL 语句}没有用\n\n回答这不算是问题吧我对要我问你二十个问题才找得出你真正问题的问题没兴趣 —— 我有更有意思的事要做呢。在看到这类问题的时候,我的反应通常不外如下三种\n\n你还有什么要补充的吗\n真糟糕希望你能搞定。\n这关我屁事\n\n\n问题我的 Windows 电脑有问题,你能帮我吗?\n\n回答能啊扔掉微软的垃圾换个像 Linux 或 BSD 的开源操作系统吧。\n注意如果程序有官方版 Windows 或者与 Windows 有互动(如 Samba你可以问与 Windows 相关的问题,只是别对问题是由 Windows 操作系统而不是程序本身造成的回复感到惊讶, 因为 Windows 一般来说实在太烂,这种说法通常都是对的。\n\n问题我的程序不会动了我认为系统工具 X 有问题\n\n回答你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与函数库文件有明显缺陷的人更有可能的是你完全没有根据。不同凡响的说法需要不同凡响的证据当你这样声称时你必须有清楚而详尽的缺陷说明文件作后盾。\n\n问题我在安装 Linux或者 X )时有问题,你能帮我吗?\n\n回答不能我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的 Linux 使用群组者寻求实际的指导吧(你能在 这儿 找到用户群组的清单)。\n注意如果安装问题与某 Linux 的发行版有关,在它的邮件列表、论坛或本地用户群组中提问也许是恰当的。此时,应描述问题的准确细节。在此之前,先用 Linux 和所有被怀疑的硬件作关键词仔细搜索。\n\n问题我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢?\n\n回答想要这样做说明了你是个卑鄙小人想找个黑客帮你说明你是个白痴\n好问题与蠢问题\n最后我将透过举一些例子来说明怎样聪明的提问同一个问题的两种问法被放在一起一种是愚蠢的另一种才是明智的。\n蠢问题\n\n我可以在哪儿找到关于 Foonly Flurbamatic 的资料?\n\n这种问法无非想得到 STFW 这样的回答。\n聪明问题\n\n我用 Google 搜索过 “Foonly Flurbamatic 2600”但是没找到有用的结果。谁知道上哪儿去找对这种设备编程的资料\n\n这个问题已经 STFW 过了,看起来他真的遇到了麻烦。\n蠢问题\n\n我从 foo 项目找来的源码没法编译。它怎么这么烂?\n\n他觉得都是别人的错这个傲慢自大的提问者。\n聪明问题\n\nfoo 项目代码在 Nulix 6.2 版下无法编译通过。我读过了 FAQ但里面没有提到跟 Nulix 有关的问题。这是我编译过程的记录,我有什么做的不对的地方吗?\n\n提问者已经指明了环境也读过了 FAQ还列出了错误并且他没有把问题的责任推到别人头上他的问题值得被关注。\n蠢问题\n\n我的主机板有问题了谁来帮我\n\n某黑客对这类问题的回答通常是好的还要帮你拍拍背和换尿布吗然后按下删除键。\n聪明问题\n\n我在 S2464 主机板上试过了 X 、 Y 和 Z ,但没什么作用,我又试了 A 、 B 和 C 。请注意当我尝试 C 时的奇怪现象。显然 florbish 正在 grommicking但结果出人意料。通常在 Athlon MP 主机板上引起 grommicking 的原因是什么?有谁知道接下来我该做些什么测试才能找出问题?\n\n这个家伙从另一个角度来看值得去回答他。他表现出了解决问题的能力而不是坐等天上掉答案。\n在最后一个问题中注意 告诉我答案 和 给我启示,指出我还应该做什么诊断工作 之间微妙而又重要的区别。\n事实上后一个问题源自于 2001 年 8 月在 Linux 内核邮件列表lkml上的一个真实的提问。我Eric就是那个提出问题的人。我在 Tyan S2464 主板上观察到了这种无法解释的锁定现象,列表成员们提供了解决这一问题的重要信息。\n通过我的提问方法我给了别人可以咀嚼玩味的东西我设法让人们很容易参与并且被吸引进来。我显示了自己具备和他们同等的能力并邀请他们与我共同探讨。通过告诉他们我所走过的弯路以避免他们再浪费时间我也表明了对他们宝贵时间的尊重。\n事后当我向每个人表示感谢并且赞赏这次良好的讨论经历的时候一个 Linux 内核邮件列表的成员表示,他觉得我的问题得到解决并非由于我是这个列表中的名人,而是因为我用了正确的方式来提问。\n黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙我相信他是对的如果我像个乞讨者那样提问不论我是谁一定会惹恼某些人或者被他们忽视。他建议我记下这件事这直接导致了本指南的出现。\n如果得不到回答\n如果仍得不到回答请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。没有回应不代表你被忽视虽然不可否认这种差别很难区分。\n总的来说简单的重复张贴问题是个很糟的点子。这将被视为无意义的喧闹。有点耐心知道你问题答案的人可能生活在不同的时区可能正在睡觉也有可能你的问题一开始就没有组织好。\n你可以通过其他渠道获得帮助这些渠道通常更适合初学者的需要。\n有许多网上的以及本地的用户群组由热情的软件爱好者即使他们可能从没亲自写过任何软件组成。通常人们组建这样的团体来互相帮助并帮助新手。\n另外你可以向很多商业公司寻求帮助不论公司大还是小。别为要付费才能获得帮助而感到沮丧毕竟假使你的汽车发动机汽缸密封圈爆掉了 —— 完全可能如此 —— 你还得把它送到修车铺,并且为维修付费。就算软件没花费你一分钱,你也不能强求技术支持总是免费的。\n对像是 Linux 这种大众化的软件,每个开发者至少会对应到上万名用户。根本不可能由一个人来处理来自上万名用户的求助电话。要知道,即使你要为这些协助付费,和你所购买的同类软件相比,你所付出的也是微不足道的(通常封闭源代码软件的技术支持费用比开源软件的要高得多,且内容也没那么丰富)。\n如何更好地回答问题\n态度和善一点。 问题带来的压力常使人显得无礼或愚蠢,其实并不是这样。\n对初犯者私下回复。 对那些坦诚犯错之人没有必要当众羞辱,一个真正的新手也许连怎么搜索或在哪找常见问题都不知道。\n如果你不确定一定要说出来 一个听起来权威的错误回复比没有还要糟,别因为听起来像个专家很好玩,就给别人乱指路。要谦虚和诚实,给提问者与同行都树个好榜样。\n如果帮不了忙也别妨碍他。 不要在实际步骤上开玩笑,那样也许会毁了提问者的设置 —— 有些可怜的呆瓜会把它当成真的指令。\n试探性的反问以引出更多的细节。 如果你做得好,提问者可以学到点东西 —— 你也可以。试试将蠢问题转变成好问题,别忘了我们都曾是新手。\n尽管对那些懒虫抱怨一声 RTFM 是正当的,但能给出文档的链接(即使只是建议个 Google 搜索关键词)会更好。\n如果你决定回答就请给出好的答案。 当别人正在用错误的工具或方法时别建议笨拙的权宜之计workaround应推荐更好的工具重新界定问题。\n正面地回答问题 如果这个提问者已经很深入的研究而且也表明已经试过 X 、 Y 、 Z 、 A 、 B 、 C 但没得到结果,回答 试试看 A 或是 B 或者 试试 X 、 Y 、 Z 、 A 、 B 、 C 并附上一个链接一点用都没有。\n帮助你的社区从问题中学习。 当回复一个好问题时,问问自己 如何修改相关文件或常见问题文件以免再次解答同样的问题?,接着再向文件维护者发一份补丁。\n如果你在研究一番后才作出了回答展现你的技巧而不是直接端出结果。毕竟 授人以鱼不如授人以渔。\n相关资源\n如果你需要个人电脑、Unix 系统和网络如何运作的基础知识,参阅 Unix 系统和网络基本原理。\n当你发布软件或补丁时试着按 软件发布实践 操作。\n鸣谢\nEvelyn Mitchel 贡献了一些愚蠢问题例子并启发了编写 如何更好地回答问题 这一节, Mikhail Ramendik 贡献了一些特别有价值的建议和改进。"},"Technology/GettingStarted/文本处理/正则表达式":{"title":"正则表达式","links":[],"tags":["技术/入门"],"content":"概述\n正则表达式Regular ExpressionRegex是用于匹配字符串中字符组合的模式。它由一系列字符和特殊符号组成可以高效地执行查找、替换、检查数据格式等多种文本处理任务。正则表达式的概念最初由数学家斯蒂芬·克莱尼在 20 世纪 50 年代提出,最早用于理论计算机科学和形式语言理论中。\n几乎所有现代编程语言都支持正则表达式包括 Python、JavaScript、Java、C#等。此外,许多文本编辑器和开发环境(如 VSCode、Sublime Text以及命令行工具如 grep也广泛应用正则表达式进行文本搜索和编辑。\n基本概念\n\n字面字符指在表达式中表示它们自身字面意义的字符例如 a、1、B。\n特殊字符在正则表达式中用来表示控制或通配符作用的字符如 *(匹配前一个字符 0 次或多次)。\n\n元字符\n元字符是构成正则表达式逻辑的基础具有特殊的匹配含义\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n元字符描述.句号匹配任意单个字符除了换行符。[ ]字符种类。匹配方括号内的任意字符。[^ ]否定的字符种类。匹配除了方括号里的任意字符*匹配 >=0 个重复的在 * 号之前的字符。+匹配 >=1 个重复的 + 号前的字符。?标记 ? 之前的字符为可选。{n,m}匹配 num 个大括号之前的字符或字符集 (n ⇐ num ⇐ m)。(xyz)字符集,匹配与 xyz 完全相等的字符串。``\\转义字符,用于匹配一些保留的字符 `[ ] ( ) { } . * + ? ^ $ \\^从开始行开始匹配。$从末端开始匹配。\n字符类\n字符类允许匹配指定集合中的字符常见的标准字符类和自定义字符类如下\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n简写描述.除换行符外的所有字符\\w匹配所有字母数字等同于 [a-zA-Z0-9_]\\W匹配所有非字母数字即符号等同于 [^\\w]\\d匹配数字 [0-9]\\D匹配非数字 [^\\d]\\s匹配所有空格字符等同于 [\\t\\n\\f\\r\\p{Z}]\\S匹配所有非空格字符 [^\\s]\\f匹配一个换页符\\n匹配一个换行符\\r匹配一个回车符\\t匹配一个制表符\\v匹配一个垂直制表符\\p匹配 CR/LF等同于 \\r\\n用来匹配 DOS 行终止符\n自定义字符类\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n示例描述[a-z]匹配任何小写字母[A-Z]匹配任何大写字母[0-9]匹配任何数字[aeiou]匹配所有小写元音字母[^0-9]匹配任何不是数字的字符(方括号内的 ^ 表示非)\n位置匹配\n位置匹配用于确定字符匹配的具体位置如行首或行尾等\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n锚点字符描述^不仅表示行的开始,也可在多行模式中匹配每一行的开始$表示行的结束或字符串的结束,同样在多行模式中可匹配每一行的结束\n量词和分组\n量词和分组是正则表达式中非常强大的功能它们让我们可以定义复杂的模式进行精确的文本匹配和操作。这部分内容也可以用表格形式进行更清晰的展示。\n量词\n量词用于指定一个元素出现的次数是正则表达式中控制匹配频度的关键工具。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n量词描述*匹配前一个元素 0 次或多次。+匹配前一个元素 1 次或多次。?匹配前一个元素 0 次或 1 次。{n}匹配前一个元素恰好 n 次。{n,}匹配前一个元素至少 n 次。{n,m}匹配前一个元素至少 n 次,但不超过 m 次。\n贪婪与非贪婪量词\n量词默认为贪婪模式尽可能多地匹配字符。通过添加 ? 后缀,量词变为非贪婪模式,尽可能少地匹配字符。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型示例描述贪婪匹配a.*b在 axxxbxxxb 中匹配从第一个 a 到最后一个 b 的整段文本。非贪婪匹配a.*?b在 axxxbxxxb 中匹配最短的,以 a 开始,以 b 结束的文本。\n分组和引用\n分组允许将正则表达式中的部分模式括起来作为一个整体进行操作这对于提取信息、构建复杂模式或进行条件匹配非常有用。\n捕获分组与非捕获分组\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型示例描述捕获分组(abc)匹配 abc并捕获匹配的文本以供后续引用。非捕获分组(?:abc)匹配 abc但不捕获匹配的文本仅用于匹配操作。\n后向引用\n后向引用让我们能够引用正则表达式中先前定义的捕获组这对于匹配重复的文本或验证两部分内容相同非常有用。\n\n\n\n\n\n\n\n\n\n\n\n\n\n示例描述(\\b\\w+)\\s+\\1匹配一个由单词、空格和相同单词构成的模式如 word word。\n高级匹配\n断言\n断言是正则表达式中的一个高级特性允许进行条件匹配即只有在满足特定条件的情况下才进行匹配。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号描述?=正先行断言 - 存在?!负先行断言 - 排除?<=正后发断言 - 存在?<!负后发断言 - 排除\n前向肯定断言 (?=)\n\n前向肯定断言允许你指定一个子模式必须出现在某个匹配之后但不会成为匹配结果的一部分。例如a(?=b) 会匹配前面有 a 且后面紧跟 b 的位置,但不会返回 b。\n\n前向否定断言 (?!)\n\n前向否定断言用来指定一个子模式必须不出现在某个匹配之后。例如a(?!b) 会匹配所有后面不跟 b 的 a。\n\n后向断言\n\n在支持的语言中如 JavaScript后向断言允许你指定一个子模式必须出现在某个匹配之前。如 (?<=b)a 表示 a 前面必须有 b。\n\n标志/模式修饰符\n标志或模式修饰符用于改变正则表达式的匹配行为。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n标志描述i忽略大小写。g全局搜索。m多行修饰符锚点元字符 ^ $ 工作范围在每行的起始。\n大小写不敏感 (i)\n\n使用此标志后匹配时将不区分大小写。例如正则表达式 /abc/i 将匹配 Abc、aBc、abc 等。\n\n多行模式 (m)\n\n在多行模式下^ 和 $ 不仅匹配输入字符串的开始和结束位置,也匹配行的开始和结束。\n\n点号包含换行 (s)\n\n通常. 不匹配换行符。使用此标志后,. 也将匹配换行符。\n\n参考实例\n\nregex101正则表达式测试工具\nREGEXP正则表达式测试工具\nRegulex正则表达式可视化工具\nany-rule正则表达式大全\nlearn-regex\n"},"Technology/GettingStarted/文本处理/结构化文件":{"title":"结构化文件","links":[],"tags":["技术/入门"],"content":"引言\n在现代软件开发和系统管理中结构化配置文件是不可或缺的工具。它们允许开发者和系统管理员以一种标准化和易于理解的方式组织配置数据这些数据控制着应用程序的行为和环境的特性。无论是简单的本地应用还是复杂的分布式系统合适的配置文件格式都可以大幅提高项目的可维护性、可扩展性和透明度。\n结构化配置文件的主要作用包括但不限于\n\n提高自动化水平自动部署和管理工具广泛依赖结构化数据来执行复杂的操作。\n促进团队协作统一的配置格式使得不同背景的开发者能够轻松理解和修改设置。\n增加应用的灵活性通过外部配置文件应用程序可以不需修改代码即可适应不同环境。\n支持环境隔离不同环境如开发、测试和生产可以使用不同的配置而不会互相干扰。\n\n选择对比 INI、YAML、XML、JSON、TOML、HCL 和 CSON 这些特定格式的原因基于它们在业界的广泛应用和独特优势。每种格式都有其特定的用途和优点,例如:\n\nINI 和 TOML 通常用于简单直观的配置需求。\nYAML 和 HCL 适合处理复杂的层次结构,广泛应用于现代 DevOps 工具。\nXML 因其扩展性和强大的自描述能力,常用于企业级应用。\nJSON 的轻量性和易于交互的特性使其成为 Web 应用的首选。\nCSON 提供了对 CoffeeScript 用户更友好的语法。\n\nINI\nINI 文件格式Initialization File起源于 Windows 操作系统用于存储程序的设置。它由节、键和值组成结构简单直观。INI 文件因其易于编辑和理解,以及良好的人类可读性,被广泛用于应用程序的配置。虽然在功能上比较基础,但 INI 文件依然在许多现代应用程序中发挥作用,特别是在需要简单配置而不涉及复杂层次结构的场合。\n基础语法和结构\nINI 文件的结构基于“节”sections和“键值对”key-value pairs。文本以方括号括起的标题开始表示一个节节下方跟随键值对键与值之间用等号=)连接。例如:\n[database]\nserver = 192.168.1.1\nport = 3306\nusername = admin\npassword = admin123\n在这个例子中database 是一个节,而 server、port、username 和 password 是键,右侧的内容则是对应的值。注释可以通过在行首添加分号(;)或井号(#)来实现。\n应用案例\n\n应用配置INI 文件经常用于存储应用程序的配置设置。例如,一个视频游戏可能使用 INI 文件来保存用户的视频设置和偏好控制配置。\n服务配置在许多传统服务器软件中INI 文件被用来配置服务器的基本属性,如数据库连接详情和网络设置。\n开发环境设置一些开发工具和环境如 PHP 的 php.ini使用 INI 文件来调整环境设置,影响语言的功能和性能。\n\nINI 文件的简洁性使其在不需要复杂数据结构的场景中非常适用,尤其是在快速开发和原型制作阶段。尽管现代开发趋向于使用更灵活的格式如 JSON 或 YAMLINI 文件仍保留了其实用性和便捷性。\nYAML\nYAMLYAML Aint Markup Language是一种以数据作为中心的序列化格式设计理念是易于阅读和书写同时具有一定的可扩展性。YAML 特别适用于配置文件、数据交换和复杂数据结构的存储,常被用于现代开发环境和应用,如容器编排和 DevOps 场景。\n基础语法和结构\nYAML 的数据结构由映射(键值对)、序列(列表)和标量(单个的、不可再分的值)组成。重要的特点包括:\n\n缩进用于表示层级关系缩进方式代表数据结构的嵌套。\n列表使用破折号-)开始新的列表项。\n字典键后面跟一个冒号和一个空格用以分隔键和值。\n\n示例\nusers:\n - name: John Doe\n age: 30\n - name: Jane Smith\n age: 25\n \nsettings:\n color: blue\n enabled: true\n应用案例\n\nKubernetesYAML 用于定义容器和服务的配置,如 Pods、Deployments 等。\nCI/CD 管道:如 GitLab CI 和 GitHub Actions 中定义作业和工作流。\n\nXML\nXMLeXtensible Markup Language是一种广泛使用的标记语言旨在存储和传输数据。它的设计允许用户定义自己的标记元素使得 XML 非常适合跨平台的数据交换和文档编制。\n基础语法和结构\nXML 的基础构造包括:\n\n标签定义开始 <tag> 和结束 </tag> 标签。\n属性在开始标签中定义用来存储有关元素的额外信息。\n嵌套元素可以包含其他元素形成复杂的树状结构。\n\n示例\n<person>\n <name>John Doe</name>\n <age>30</age>\n <address city="New York" />\n</person>\n应用案例\n\n企业级系统用于配置文件和数据交换。\nWeb 服务SOAP 协议中通常使用 XML 来编码消息。\n\nJSON\nJSON (JavaScript Object Notation) 是一种轻量级的数据交换格式易于人阅读和编写也易于机器解析和生成。JSON 的设计是为了简化服务器到页面的数据交换,现在被广泛使用于许多编程语言。\n基础语法和结构\nJSON 主要由两种结构组成:\n\n对象由花括号包围的一组无序的“键/值对”。\n数组由方括号包围的值的有序集合。\n\n示例\n{\n "users": [\n {"name": "John Doe", "age": 30},\n {"name": "Jane Smith", "age": 25}\n ],\n "settings": {\n "color": "blue",\n "enabled": true\n }\n}\n应用案例\n\nAPI 数据交换:广泛用于 Web API 中数据的发送和接收。\n\nTOML\nTOMLToms Obvious, Minimal Language是一种旨在简单和明确的数据序列化格式。它的设计哲学是易于阅读与编写且明确无误常用于配置文件。\n基础语法和结构\nTOML 支持表格、内联表、数组等结构,语法清晰直观:\n\n表表示为键值对的集合。\n内联表在同一行定义完整的表。\n数组一系列值可以包含表或基本数据类型。\n\n示例\n[database]\nserver = "192.168.1.1"\nports = [ 8001, 8001, 8002 ]\nconnection_max = 5000\nenabled = true\n \n[clients]\ndata = [ ["gamma", "delta"], [1, 2] ]\n \n# 内联表\nowner = { name = "Tom Preston-Werner", dob = 1979-05-27T07:32:00Z }\n应用案例\n\n软件项目配置如 Rust 项目中 Cargo 的 Cargo.toml 配置文件。\n\n格式对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特征 / 格式INIYAMLXMLJSONTOMLHCLCSON易于阅读⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐易于书写⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐数据结构⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐扩展性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐注释支持✅✅✅❌✅✅✅适用场景应用程序配置DevOps、复杂配置企业级数据交换Web 应用项目配置资源描述CoffeeScript 环境"},"Technology/GettingStarted/版本控制/Git/入门/分支":{"title":"分支","links":[],"tags":["Git/入门","技术/入门"],"content":"Git 的分支模型被称为它的**「必杀技特性」**,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。\n分支操作\n因为 Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。\n所以在进行提交操作时Git 会保存一个提交对象commit object。该提交对象会包含一个指向暂存内容快照的指针且还包含了作者的姓名和邮箱提交时输入的信息以及指向它的父对象的指针。 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象。\nGit 的分支,其实本质上仅仅是指向提交对象的可变指针。\n创建分支\n// 创建分支但不切换 \ngit branch <branch-name> \n \n// 创建并切换到新分支 \ngit checkout -b <branch-name> \n \n// 或者使用 \ngit branch -b <branch-name>\n切换分支\n// 切换到已存在的分支 \ngit checkout <branch-name> \n \n// 在 Git 2.23 版本之后,推荐使用 git switch \ngit switch <branch-name>\n查看分支\n// 列出所有分支 \ngit branch \n \n// 列出远程分支 \ngit branch -r \n \n// 列出本地和远程分支 \ngit branch -a\n合并分支\n// 将指定分支合并到当前分支 \ngit merge <branch-name> \n \n// 合并时,如果出现冲突,需要手动解决冲突后,使用以下命令完成合并 \ngit add <resolved-files> \ngit commit -m "解决合并冲突"\n重命名分支\n// 重命名本地分支 \ngit branch -m <old-branch-name> <new-branch-name> \n \n// 重命名远程分支 \ngit push origin --delete <old-branch-name> \ngit push origin <new-branch-name>\n删除分支\n// 删除本地分支 \ngit branch -d <branch-name> \n \n// 删除远程分支 \ngit push origin --delete <branch-name>\n强制更新分支到特定提交\n// 强制更新本地分支到特定提交 \ngit reset --hard <commit-hash> \n \n// 强制更新远程分支到特定提交 \ngit push origin <commit-hash>:<branch-name>\n推送分支到远程仓库\n// 推送当前分支到远程仓库 \ngit push \n \n// 推送特定分支到远程仓库 \ngit push origin <branch-name> \n \n// 推送分支并设置为默认分支 \ngit push -u origin <branch-name>\n从远程仓库拉取分支\n// 拉取远程分支到本地 \ngit fetch origin <branch-name> \n \n// 切换到远程分支,并创建一个本地追踪分支 \ngit checkout -b <branch-name> origin/<branch-name>\n分支冲突解决\n// 列出分支冲突 \ngit branch -vv \n \n// 合并分支时解决冲突 \ngit mergetool\n设置跟踪分支\n// 设置本地分支跟踪远程分支 \ngit branch --set-upstream-to=origin/<branch-name> <branch-name>\n \n分支实例\n你将经历如下步骤\n\n\n开发某个网站。\n\n\n为实现某个新的用户需求创建一个分支。\n\n\n在这个分支上开展工作。\n\n\n正在此时你突然接到一个电话说有个很严重的问题需要紧急修补。 你将按照如下方式来处理:\n\n切换到你的线上分支production branch。\n为这个紧急任务新建一个分支并在其中修复它。\n在测试通过之后切换回线上分支然后合并这个修补分支最后将改动推送到线上分支。\n切换回你最初工作的分支上继续工作。\n\n新建分支\n首先我们假设你正在你的项目上工作并且在 master 分支上已经有了一些提交。\n现在你为实现某个新的需求创建一个分支 iss53。\ngit checkout -b iss53\n当我们做了一些提交的时候iss53 分支在向前推进。\n现在你接到那个电话有个紧急问题等待你来解决现在要做的就是切换回主分支。\ngit switch master\n接下来你要修复这个紧急问题。新建一个 hotfix 分支,直至问题解决。\ngit checkout -b hotfix\n合并分支\n然后将 hotfix 分支合并回你的 master 分支来部署线上。\ngit switch master\ngit merge hotfix\n当你试图合并两个分支时 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进fast-forward”。\n此时hotfix 分支已经不需要了,可以将它删除。\ngit branch -d hotfix\n现在你切回你正在工作的分支继续你的工作并且拥有了新的提交。\n假设这时你已经完成了 iss53 的需求,需要将 iss53 分支合并入 master 分支。\ngit switch master\ngit merge iss53\n这和之前合并 hotfix 分支的时候看起来有点不一样。\n在这种情况下你的开发历史从一个更早的地方开始分叉开来diverged。 因为master 分支所在提交并不是 iss53 分支所在提交的直接祖先Git 不得不做一些额外的工作。 出现这种情况的时候Git 会使用两个分支的末端所指的快照以及这两个分支的公共祖先,做一个简单的三方合并。\n冲突时的分支合并\n有时候合并操作并不会如此顺利因为如果涉及到同一个文件的同一处就会在合并时产生冲突。此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。\n任何因包含合并冲突而有待解决的文件都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。\n出现冲突的文件会包含一些特殊区段像下面这个样子\n<<<<<<< HEAD:index.html\n<div id="footer">contact : email.support@github.com</div>\n=======\n<div id="footer">\n please contact us at support@github.com\n</div>\n>>>>>>> iss53:index.html\n这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分)。\n而 iss53 分支所指示的版本在 ===== 的下半部分。 为了解决冲突,你必须选择使用由 ===== 分割的两部分中的一个,或者你也可以自行合并这些内容。\n如你可以通过把这段内容换成下面的样子来解决冲突\n<div id="footer">\nplease contact us at email.support@github.com\n</div>\n上述的冲突解决方案仅保留了其中一个分支的修改并且 <<<<<<< , ======= , 和 >>>>>>> 这些行被完全删了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件Git 就会将它们标记为冲突已解决。\n远程分支\n远程引用是对远程仓库的引用指针包括分支、标签等等。请将它们看做书签 这样可以提醒你该分支在远程仓库中的位置就是你最后一次连接到它们的位置。\n推送分支\n当你想要公开分享一个分支时需要将其推送到有写入权限的远程仓库上。 本地的分支并不会自动与远程仓库同步——你必须显式地推送想要分享的分支。\n// 推送本地分支到正在跟踪远程分支\ngit push <remote> <branch>\n \n// 推送本地分支到远程分支(自定义远程分支命名)\ngit push <remote> <branch>:<origin-branch-name>\n跟踪分支\n从一个远程跟踪分支检出一个本地分支会自动创建所谓的“跟踪分支”它跟踪的分支叫做“上游分支”。跟踪分支是与远程分支有直接关系的本地分支。\n// 从远程分支新建本地跟踪分支\ngit checkout --track <remote>/<branch>\n \n// 从远程分支新建本地跟踪分支(自定义本地分支命名)\ngit checkout -b <branch> <remote>/<branch>\n \n// 修改跟踪的远程分支\ngit branch -u <remote>/<branch>\n \n// 查看设置的所有跟踪分支\ngit branch -vv\n拉取分支\n当从服务器上抓取本地没有的数据时可以运行 git fetch 或 git pull。推荐单独显式地使用 fetch 与 merge 命令。\n// 仅拉取默认远程分支数据,不进行自动合并。\ngit fetch <remote>\n \n// 拉取远程分支,并尝试自动合并。\ngit pull <remote>\n删除远程分支\ngit push <remote> --delete <branch>\n变基\n你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。在 Git 中,这种操作就叫做 变基rebase。\n// 重放式变基\ngit rebase <base-branch> <topic-branch>\n// 交互式变基\ngit rebase -i <base-branch> <topic-branch>\n它的原理是首先找到这两个分支假设当前分支 experiment、变基操作的目标基底分支 master 的最近共同祖先,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件, 然后将当前分支指向目标基底, 最后以此将之前另存为临时文件的修改依序应用。\n// 1.切换 experiment 分支。\ngit switch experiment\n \n// 2.变基至 master 分支。\ngit rebase master\n \n// 3.切换 master 分支。\ngit switch master\n \n// 4.合并 experiment 分支。\ngit merge experiment\n更有趣的变基例子\n在对两个分支进行变基时所生成的“重放”并不一定要在目标分支上应用你也可以指定另外的一个分支进行\n应用。\n你从 master 分支创建了一个 server 分支,添加功能并提交后。又基于提交后的 server 分支创建了 client 分支,同样添加功能并提交后。你回到了 server 分支,继续添加功能并提交。假设你希望将 client 中的修改合并到主分支并发布,但暂时并不想合并 server 中的修改,因为它们还需要经过更全面的测试。\n这时你就可以使用 git rebase 命令的 —onto 选项, 选中在 client 分支里但不在 server 分支里的修改,将它们在 master 分支上重放。\n// 1. 取出 client 分支,找出它从 server 分支分歧之后的补丁。然后把这些补丁在master 分支上重放一遍,让 client 看起来像直接基于 master 修改一样。\ngit rebase --onto master server client\n \n// 2. 切换 master 分支\ngit switch master\n \n// 3. 合并 client 分支\ngit merge client\n接下来你决定将 server 分支中的修改也整合进来。\n// 1.变基至 master分支\ngit rebase master server\n \n// 2.切换 master 分支\ngit switch master\n \n// 3.合并分支\ngit merge server\n \n// 4.删除分支\n变基的风险\n如果提交存在于你的仓库之外而别人可能基于这些提交进行开发那么不要执行变基。\n如果你遵循这条金科玉律就不会出差错。 否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾你。\n变基 Vs 合并\n至此你已在实战中学习了变基和合并的用法你一定会想问到底哪种方式更好。 在回答这个问题之前,让我们退后一步,想讨论一下提交历史到底意味着什么。\n有一种观点认为仓库的提交历史即是 记录实际发生过什么。 它是针对历史的文档,本身就有价值,不能乱改。 从这个角度看来,改变提交历史是一种亵渎,你使用 谎言 掩盖了实际发生过的事情。 如果由合并产生的提\n交历史是一团糟怎么办 既然事实就是如此,那么这些痕迹就应该被保留下来,让后人能够查阅。另一种观点则正好相反,他们认为提交历史是 项目过程中发生的事。 没人会出版一本书的第一版草稿,软件维护手册也是需要反复修订才能方便使用。 持这一观点的人会使用 rebase 及 filter-branch 等工具来编写故事,怎么方便后来的读者就怎么写。\n现在让我们回到之前的问题上来到底合并还是变基好希望你能明白这并没有一个简单的答案。 Git 是一个非常强大的工具,它允许你对提交历史做许多事情,但每个团队、每个项目对此的需求并不相同。 既然你已经分别学习了两者的用法,相信你能够根据实际情况作出明智的选择。\n总的原则是只对尚未推送或分享给别人的本地修改执行变基操作清理历史 从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。"},"Technology/GettingStarted/版本控制/Git/入门/协议":{"title":"协议","links":[],"tags":["Git/入门","技术/入门"],"content":"到目前为止,你应该已经有办法使用 Git 来完成日常工作。 然而,为了使用 Git 协作功能,你还需要有远程的 Git 仓库。 尽管在技术上你可以从个人仓库进行推送push和拉取pull来修改内容但不鼓励使用这种方法因为一不留心就很容易弄混其他人的进度。 此外,你希望你的合作者们即使在你的电脑未联机时亦能存取仓库 — 拥有一个更可靠的公用仓库十分有用。 因此,与他人合作的最佳方法即是建立一个你与合作者们都有权利访问,且可从那里推送和拉取资料的共用仓库。\n架设一台 Git 服务器并不难。如果你不介意托管你的代码在其他人的服务器,且不想经历设置与维护自己服务器的麻烦,可以试试第三方仓库托管服务。\n一个远程仓库通常只是一个裸仓库bare repository——即一个没有当前工作目录的仓库。 因为该仓库仅仅\n作为合作媒介不需要从磁盘检查快照存放的只有 Git 的资料。 简单的说,裸仓库就是你工程目录内的 .git\n子目录内容不包含其他资料。\nGit 协议\nGit 可以使用四种不同的协议来传输资料:\n\n本地协议Local\nHTTP 协议\nSSHSecure Shell协议\nGit 协议\n\n本地协议\n最基本的就是 本地协议Local protocol其中的远程版本库就是同一主机上的另一个目录。 这常见于团队每一个成员都对一个共享的文件系统(例如一个挂载的 NFS拥有访问权或者比较少见的多人共用同一台电脑的情况。 后者并不理想,因为你的所有代码版本库如果长存于同一台电脑,更可能发生灾难性的损失。\n\n优点\n\n基于文件系统的版本库的优点是简单并且直接使用了现有的文件权限和网络访问权限。 如果你的团队已经有共享文件系统,建立版本库会十分容易。 只需要像设置其他共享目录一样,把一个裸版本库的副本放到大家都可以访问的路径,并设置好读/写的权限,就可以了, 我们会在在服务器上搭建 Git 讨论如何导出一个裸版本库。这也是快速从别人的工作目录中拉取更新的方法。 如果你和别人一起合作一个项目,他想让你从版本库中拉取更新时,运行类似 git pull /home/john/project 的命令比推送到服务器再抓取回来简单多了。\n\n缺点\n\n这种方法的缺点是通常共享文件系统比较难配置并且比起基本的网络连接访问这不方便从多个位置访问。如果你想从家里推送内容必须先挂载一个远程磁盘相比网络连接的访问方式配置不方便速度也慢。值得一提的是如果你使用的是类似于共享挂载的文件系统时这个方法不一定是最快的。 访问本地版本库的速度与你访问数据的速度是一样的。 在同一个服务器上,如果允许 Git 访问本地硬盘,一般的通过 NFS 访问版本库要比通过 SSH 访问慢。最终,这个协议并不保护仓库避免意外的损坏。 每一个用户都有“远程”目录的完整 shell 权限,没有方法可以阻止他们修改或删除 Git 内部文件和损坏仓库。\nHTTP 协议\nGit 通过 HTTP 通信有两种模式:智能 HTTP 协议、哑Dumb HTTP 协议。\n智能 HTTP 协议\n智能 HTTP 的运行方式和 SSH 及 Git 协议类似,只是运行在标准的 HTTP/S 端口上并且可以使用各种 HTTP 验证机制, 这意味着使用起来会比 SSH 协议简单的多,比如可以使用 HTTP 协议的用户名/密码授权,免去设置 SSH 公钥。\n哑Dumb HTTP 协议\n如果服务器没有提供智能 HTTP 协议的服务Git 客户端会尝试使用更简单的“哑” HTTP 协议。 哑 HTTP 协议里 web 服务器仅把裸版本库当作普通文件来对待,提供文件服务。 哑 HTTP 协议的优美之处在于设置起来简单。\n\n优点\n\n我们将只关注智能 HTTP 协议的优点。不同的访问方式只需要一个 URL 以及服务器只在需要授权时提示输入授权信息,这两个简便性让终端用户使用 Git 变得非常简单。 相比 SSH 协议,可以使用用户名/密码授权是一个很大的优势,这样用户就不必须在使用 Git 之前先在本地生成 SSH 密钥对再把公钥上传到服务器。 对非资深的使用者,或者系统上缺少 SSH 相关程序的使用者HTTP 协议的可用性是主要的优势。 与 SSH 协议类似HTTP 协议也非常快和高效。你也可以在 HTTPS 协议上提供只读版本库的服务,如此你在传输数据的时候就可以加密数据;或者,你甚至可以让客户端使用指定的 SSL 证书。另一个好处是 HTTPS 协议被广泛使用,一般的企业防火墙都会允许这些端口的数据通过。\n\n缺点\n\n在一些服务器上架设 HTTPS 协议的服务端会比 SSH 协议的棘手一些。 除了这一点,用其他协议提供 Git 服务与智能 HTTP 协议相比就几乎没有优势了。如果你在 HTTP 上使用需授权的推送,管理凭证会比使用 SSH 密钥认证麻烦一些。 然而,你可以选择使用凭证存储工具,比如 macOS 的 Keychain 或者 Windows 的凭证管理器。 参考 凭证存储 如何安全地保存 HTTP 密码。\nSSH 协议\n架设 Git 服务器时常用 SSH 协议作为传输协议。 因为大多数环境下服务器已经支持通过 SSH 访问 —— 即使没有也很容易架设。 SSH 协议也是一个验证授权的网络协议;并且,因为其普遍性,架设和使用都很容易。\n\n优点\n\n用 SSH 协议的优势有很多。 首先SSH 架设相对简单 —— SSH 守护进程很常见,多数管理员都有使用经验,并\n且多数操作系统都包含了它及相关的管理工具。 其次,通过 SSH 访问是安全的 —— 所有传输数据都要经过授权和加密。 最后,与 HTTPS 协议、Git 协议及本地协议一样SSH 协议很高效,在传输前也会尽量压缩数据。\n\n缺点\nSSH 协议的缺点在于它不支持匿名访问 Git 仓库。 如果你使用 SSH那么即便只是读取数据使用者也 必须 通\n过 SSH 访问你的主机, 这使得 SSH 协议不利于开源的项目,毕竟人们可能只想把你的仓库克隆下来查看。 如果你只在公司网络使用SSH 协议可能是你唯一要用到的协议。 如果你要同时提供匿名只读访问和 SSH 协议,那么你除了为自己推送架设 SSH 服务以外, 还得架设一个可以让其他人访问的服务。\n\nGit 协议\n这是包含在 Git 里的一个特殊的守护进程它监听在一个特定的端口9418类似于 SSH 服务,但是访问无需任何授权。 要让版本库支持 Git 协议,需要先创建一个 git-daemon-export-ok 文件 —— 它是 Git 协议守护进程为这个版本库提供服务的必要条件 —— 但是除此之外没有任何安全措施。 要么谁都可以克隆这个版本库,要么谁也不能。 这意味着,通常不能通过 Git 协议推送。 由于没有授权机制,一旦你开放推送操作,意味着网络上知道这个项目 URL 的人都可以向项目推送数据。 不用说,极少会有人这么做。\n\n优点\n\n目前Git 协议是 Git 使用的网络传输协议里最快的。 如果你的项目有很大的访问量,或者你的项目很庞大并且不需要为写进行用户授权,架设 Git 守护进程来提供服务是不错的选择。 它使用与 SSH 相同的数据传输机制,但是省去了加密和授权的开销。\n\n缺点\n\nGit 协议缺点是缺乏授权机制。 把 Git 协议作为访问项目版本库的唯一手段是不可取的。 一般的做法里,会同时提供 SSH 或者 HTTPS 协议的访问服务,只让少数几个开发者有推送(写)权限,其他人通过 git:// 访问只有读权限。 Git 协议也许也是最难架设的。 它要求有自己的守护进程,这就要配置 xinetd、systemd 或者其他的程序,这些工作并不简单。 它还要求防火墙开放 9418 端口,但是企业防火墙一般不会开放这个非标准端口。而大型的企业防火墙通常会封锁这个端口。\n第三方托管\n现在已经拥有了很多更现代功能更全的 Git 服务器GitHub 便是其中最出名的一个,同时 GitLab、Gitee 都是很棒的开源社区。"},"Technology/GettingStarted/版本控制/Git/入门/基础":{"title":"基础","links":[],"tags":["Git/入门","技术/入门"],"content":"本章涵盖了你在使用 Git 完成各种工作时将会用到的各种基本命令。 在学习完本章之后你应该能够配置并初始化一个仓库repository、开始或停止跟踪track文件、暂存stage或提交commit更改。\n本章也将向你演示了如何配置 Git 来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操作、如何浏览你的项目的历史版本以及不同提交commits之间的差异、如何向你的远程仓库推送push以及如何从你的远程仓库拉取pull文件。\n获取 Git 仓库\n通常有两种获取 Git 项目仓库的方式:\n\n将尚未进行版本控制的本地目录转换为 Git 仓库。\n从其它服务器克隆一个已存在的 Git 仓库。\n\n在目录中初始化仓库\n// 当前目录下初始化仓库\ngit init\n该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。\n克隆现有的仓库\n如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone 命令。\n// 克隆远程仓库\ngit clone <url> \n如果你想在克隆远程仓库的时候自定义本地仓库的名字你可以通过额外的参数指定新的目录名\n// 指定仓库本地命名\ngit clone <url> <name>\n克隆现有的仓库实际上是多个命令的分解。首先初始化一个本地仓库接着添加远程仓库最后拉取远程仓库数据到本地。\n记录每次更新到仓库\n当我们成功拥有一个仓库后可以运行 git status 当仓库状态。在未进行开发的情况下,仓库都是干净的。当我们在工作目录对文件进行了变动,此时工作目录下的每一个文件都不外乎这两种状态:\n\n已跟踪指那些被纳入了版本控制的文件在上一次快照中有它们的记录在工作一段时间后 它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 Git 已经知道的文件。\n未跟踪工作目录中除已跟踪文件外的其它所有文件都属于未跟踪文件它们既不存在于上次快照的记录中也没有被放入暂存区。\n\n运行 git status 就会显示我们对那些文件进行了变动,那些是已跟踪,那些是未跟踪。接着我们可以使用 git add 将文件添加至暂存区。添加至暂存区后可以提交更新或继续工作;如果继续工作,同时对已暂存的文件进行了更改,可以使用 git diff 查看该文件工作区和暂存区之间的差异。\n如果提交新修改的文件至暂存区暂存区的文件会被新提交的覆盖。完成所有的工作开发并且提交至暂存区后就运行 git commit 提交更新至 git 目录,记录此次快照。\n进行多次开发之后想要回顾一下提交历史可以使用 git log 查看提交历史。\n忽略文件\n有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。\n在这种情况下我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式,不同目录下可以拥有不同的 .gitignore 。\n.gitignore 格式规范:\n\n所有空行或者以 # 开头的行都会被 Git 忽略。\n可以使用标准的 glob 模式匹配它会递归地应用在整个工作区中glob 模式是指 shell 所使用的简化了的正则表达式)。\n匹配模式可以以/)开头防止递归。\n匹配模式可以以/)结尾指定目录。\n要忽略指定模式以外的文件或目录可以在模式前加上叹号!)取反。\n\n\nGitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表, 你可以在 github.com/github/gitignore 找到它。\n\n检查当前仓库状态\n// 查看当前仓库状态总览\ngit status\n \n// 查看当前仓库状态简览\ngit status -s \ngit status --short \n \n// 当前文件和暂存区之间的具体差异\ngit diff \n \n// 暂存区和最后一次提交的具体差异\ngit diff --staged\ngit diff --cached\n踪新文件或暂存已修改的文件\n// 添加文件到暂存区\ngit add <file>\n \n// 添加路径到暂存区\ngit add <path>\n提交更新\n// 提交更新,同时会启动文本编辑器来输入提交说明。\ngit commit\n \n// 将提交信息与命令放在同一行\ngit commit -m <msg>\n \n// 跳过暂存,直接提交已跟踪文件。\ngit commit -a\n查看提交历史\nGit Log 的常用选项\n// 格式化输出一行显示提交历史\ngit log --oneline\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明-p按补丁格式显示每个提交引入的差异。—stat显示每次提交的文件修改统计信息。—shortstat只显示 —stat 中最后的行数修改添加移除统计。—name-only仅在提交信息后显示已修改的文件清单。—name-status显示新增、修改、删除的文件清单。—abbrev-commit仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。—relative-date使用较短的相对时间而不是完整格式显示日期比如“2 weeks ago”。—graph在日志旁以 ASCII 图形显示分支与合并历史。—pretty使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format用来定义自己的格式。—oneline—pretty=oneline —abbrev-commit 合用的简写。\nGit Log —pretty=format 常用的选项\n// format 可以定制记录的显示格式\ngit log --pretty=format:"%h - %an, %ar : %s"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明%H提交的完整哈希值%h提交的简写哈希值%T树的完整哈希值%t树的简写哈希值%P父提交的完整哈希值%p父提交的简写哈希值%an作者名字%ae作者的电子邮件地址%ad作者修订日期可以用 —date=选项 来定制格式)%ar作者修订日期按多久以前的方式显示%cn提交者的名字%ce提交者的电子邮件地址%cd提交日期%cr提交日期距今多长时间%s提交说明\nGit Log 限制输出的选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明-n仅显示最近的 n 条提交。—since, —after仅显示指定时间之后的提交。—until, —before仅显示指定时间之前的提交。—author仅显示作者匹配指定字符串的提交。—committer仅显示提交者匹配指定字符串的提交。—grep仅显示提交说明中包含指定字符串的提交。-S仅显示添加或删除内容匹配指定字符串的提交。\n撤消操作\n有时候我们提交完了才发现漏掉了几个文件没有添加或者提交信息写错了。 此时,可以运行带有 —amend 选\n项的提交命令来重新提交\n// 撤销上次提交\ngit commit --amend\n此命令会将当前暂存区的文件一并提交最终只会有一个提交——第二次提交将代替第一次提交的结果。\n撤销已暂存的文件\n// 取消暂存区文件\ngit reset HEAD <file>\ngit reset 确实是个危险的命令,如果加上了 —hard 选项则更是如此。 然而在上述场景中,工作目录中的文件尚未修改,因此相对安全一些。\n撤消对文件的修改\n// 撤销工作区的文件修改\ngit checkout -- <file>\n请务必记得 git checkout -- <file> 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。\n远程仓库\n为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库。远程仓库是指托管在因特网或其他网络中\n的你的项目的版本库。\n你可以有好几个远程仓库通常有些仓库对你只读有些则可以读写。 与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。 管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪等等。\n查看远程仓库\n运行 git remote 命令,查看你已经配置的远程仓库服务器。\n// 查看远程仓库\ngit remote\n也可以指定选项 -v会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL\n// 显示远程仓库简写及其 URL\ngit remote -v\n添加远程仓库\n你可以运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写:\n// 添加一个新的远程 Git 仓库\ngit remote add <remote-name> <url>\n从远程仓库中抓取与拉取\n当你添加远程仓库后可以从远程仓库拉取数据。\n// 从远程仓库拉取数据,不自动合并。\ngit fetch <remote-name>\n \n// 从远程仓库抓取数据,并尝试自动合并到当前分支。\ngit pull\n推送到远程仓库\n当你想分享你的项目时必须将其推送到上游。\n// 推送分支到远程仓库\ngit push <remote> <branch>\n查看、重命名与移除远程仓库\n你可以使用以下命令对远程仓库进行查看、重命名与移除操作。\n// 查看远程仓库\ngit remote show <remote>\n \n// 远程仓库的重命名\ngit remote rename <old> <new>\n \n// 远程仓库的移除\ngit remote remove <name>\n打标签\nGit 可以给仓库历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点( v1.0 、 v2.0 等等)\nGit 支持两种标签轻量标签lightweight与附注标签annotated。\n轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。\n而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard GPG签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。\n但是如果你只是想用一个临时的标签 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。\n创建标签\n// 创建轻量标签\ngit tag <tagname>\n \n// 创建附注标签\ngit tag -a <tagname>\n你也可以对过去的提交打标签。只需要输入提交的 SHA-1 数。\n// 后期打标签\ngit tag <tagname> <commit-id>\n查看标签\n// 列出已有的标签\ngit tag\n \n// 显示标签信息\ngit show <tagname>\n共享标签\n默认情况下git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。\n// 推送标签到远程仓库\ngit push origin <tagname>\n \n// 推送全部标签\ngit push origin --tags\n删除标签\n// 删除标签\ngit tag -d <tagname>\n \n// 删除远程仓库标签\ngit push origin --delete <tagname>\nGit 别名\nGit 并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过 git\nconfig 文件来轻松地为每一个命令设置一个别名。如下:\ngit config --global alias.co checkout\ngit config --global alias.br branch\ngit config --global alias.ci commit\ngit config --global alias.st status\n接下来我们就可以使用 git co 等价代替 git checkout其他同理。"},"Technology/GettingStarted/版本控制/Git/入门/起步":{"title":"起步","links":[],"tags":["Git/入门","技术/入门"],"content":"我们会先了解一些版本控制工具的历史背景,然后试着让 Git 在你的系统上跑起来,直到最后配置好,可以正常开始开发工作。读完本章,你就会明白为什么 Git 会如此流行,为什么你应该立即开始使用它。\n版本控制系统\n版本控制系统Version Control SystemsVCS是一种记录一个或若干文件内容变化以便将来查阅特定版本修订情况的系统。\n本地版本控制系统\n本地版本控制系统大多采用数据库来记录文件的历次更新差异。\n其中最流行的一种叫做 RCS现今许多计算机系统上都还看得到它的踪影。RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。\n\n集中化的版本控制系统\n为了解决本地版本控制系统无法协同工作的问题集中化的版本控制系统Centralized Version Control SystemsCVCS应允而生。其采用一个单一集中管理的服务器保存所有文件的修订版本协作者通过客户端连接服务器拉取最新文件或提交更新。\n\n优点相较于本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。\n缺点显而易见的缺点是中央服务器的单点故障。例如宕机一小时那么在这一小时内谁都无法提交更新也就无法协同工作如果中心数据库所在的磁盘发生损坏又没有做恰当备份毫无疑问你将丢失所有数据——包括项目的整个变更历史只剩下人们在各自机器上保留的单独快照。\n\n\n分布式版本控制系统\n为了解决集中化的版本控制系统的痛处分布式版本控制系统Distributed Version Control SystemDVCS面世了。分布式顾名思义每一个节点都基于公认中心节点服务器的镜像拷贝故每个节点都拥有代码仓库的完整信息。因此不存在中心节点故障无法工作、物理损坏无法恢复、日志历史不完整导致协作者无法相互协作。\n更进一步许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此你就可以在同一个项目中分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。\n\nGit 简史\n同生活中的许多伟大事物一样Git 诞生于一个极富纷争大举创新的年代。\nLinux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上19912002 年间)。到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。\n到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:\n\n速度\n简单的设计\n对非线性开发模式的强力支持允许成千上万个并行开发的分支\n完全分布式\n有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)\n\n自诞生于 2005 年以来Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。\nGit 特性\n那么简单地说Git 究竟是怎样的一个系统呢?它的主要特性是什么?\n直接记录快照而非差异比较\n\nGit 与其他版本控制系统主要差别在于对待数据的方法Git 直接记录快照而非差异比较。Git 中每一次提交更新或保存项目状态都是对全部文件创建一个快照并保存这个快照的索引如果文件没有修改Git 则不再重新存储该文件而是只保留一个链接指向之前存储的文件。Git 对待数据更像是一个快照流。\n近乎所有操作都是本地执行\n由于 Git 是分布式版本控制系统,在不对公认中心节点服务器操作的情况下,绝大多数操作都只需要访问本地文件资源。故 Git 大部分操作看起来瞬间完成,不存在网络延时。\n保证数据完整性\nGit 中所有的数据在存储前都用 SHA-1 散列hash哈希计算校验和并以哈希值来索引而不是文件名。这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。\n// SHA-1 哈希\n24b9da6552252987aa493b52f8696cd6d3b00373\n一般只添加数据\n因为 Git 一般只添加数据,所以你很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。\nGit 的三种状态\n\nGit 有三种状态,你的文件可能处于其中之一: 已修改modified 、已暂存staged和已提交committed。\n\n已修改修改了文件但还没保存到数据库中\n已暂存对一个已修改文件的当前版本做了标记使之包含在下次提交的快照中。\n已提交数据已经安全地保存在本地数据库中。\n\n这会让我们的 Git 项目拥有三个阶段工作区Working Directory、暂存区Staging Area 以及 Git 目录Repository。\n\n工作区工作区对项目的某个版本独立提取出来的内容放在磁盘上供你使用或修改。\n暂存区保存了下次将要提交的文件列表信息。\nGit 目录Git 用来保存项目的元数据和对象数据库的地方。\n\n所以 Git 的基本工作流程如下:\n\n在工作区中修改文件已修改。\n将你下次想要提交的更改选择性地暂存这样只会将更改的部分添加到暂存区已暂存。\n提交更新找到暂存区的文件将快照永久性存储到 Git 目录(已提交)。\n\nGit 首次运行\nGit 安装后首先要定制环境,仅需配置一次,升级时保留配置信息。\nGit 配置\n\n系统配置包含系统上每一个用户及其仓库的通用配置。\n全局配置只针对当前用户对系统上所有仓库生效。\n仓库配置仅对当前仓库生效为默认选项。\n\n配置文件作用域采用就近原则每一个级别会覆盖上一级别的配置。修改不同的配置文件需要在执行 git config 时传递不同参数。\ngit config --system\ngit config --global\ngit config --local\n用户信息\n务必设置用户名和邮件地址这一点至关重要因为每一个 Git 提交都会使用这些信息,并且写入到每一次提交中,不可更改。\ngit config --global user.name <user-name>\ngit config --global user.email <email@email.com>\n查看配置\n// 所有 Git 配置\ngit config --list\n \n// 检查 Git 的某一项配置\ngit config <key> \n获取帮助\n\nGit 官方手册\n开源指北\n\ngit help <verb>\ngit <verb> --help\nman git-<verb>\n \n// 简明的帮助文件\ngit <verb> -h"},"Technology/GettingStarted/版本控制/Git/进阶/Git-LFS":{"title":"Git-LFS","links":[],"tags":["Git/进阶","技术/入门"],"content":"在 Git 仓库中,对于非文本文件,如各种多媒体文件,软件制品文件,二进制文件等等,这些文件往往体积比较大,使用 Git 直接管理会导致仓库的体积迅速膨胀,进而导致 Git 的许多操作变慢,同时也影响仓库上传到远程端。\nGit LFSLarge File Storage 相当于 Git 的一种插件式增强工具,简单讲,它是在 Git 仓库使用这些文件的指针代替实际文件,而把实际文件存储在远程端 LFS 服务器,同时在本地仓库中实时追踪这些文件的变动。\n安装\nLinux\n$ curl -s packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash\n$ sudo apt-get install git-lfs\nMac\n$ /usr/bin/ruby -e "$(curl -fsSL raw.githubusercontent.com/Homebrew/install/master/install)"\n$ brew install git-lfs\nWindows\n\n下载安装 windows installer。\n运行 windows installer。\n\n使用\n配置 LFS\n$ git lfs install\n追踪文件\n# 追踪单个文件\n$ git lfs track "coding.png"\n# 追踪同一后缀的所有文件\n$ git lfs track "*.png"\n# 查看正在追踪的文件模式patterns\n$ git lfs track\n提交代码时需要将 .gitattributes 文件也提交到仓库,提交完成后,执行 git lfs ls-files 命令可以查看 LFS 跟踪的文件列表。\n推送仓库\ngit push origin main\n克隆 LFS 仓库\n$ git lfs clone e.coding.net/coding/coding-manual.git\nCloning into 'coding-manual'\nremote: Counting objects: 16,done.\nremote: Compressing objects: 100% (12/12),done.\nremote: Total 16 (delta 3), reused 9 (delta 1)\nReceiving objects: 100% (16/16),done.\nResolving deltas: 100% (3/3),done.\nChecking connectively...done.\nGit LFS: (4 of 4 files) 0 B / 100 B\n常用命令\n$ git lfs track\n# 将一个或者一类文件以 git lfs 的方式加入到版本控制中 (实质是修改 .gitattributes 文件)\n$ git lfs untrack\n# 将一个或者一类文件从 仓库中移除\n \n$ git lfs status\n# 类似于 git status , 显示 git lfs 方式的文件在 暂存区的状态\n \n$ git lfs lock\n# 锁定一个或者一些文件, 只允许当前的用户对这些文件进行修改, 防止在多人协作的场景下冲突(如果是仓库管理员可以带 --force 参数强制 unlock)\n$ git lfs unlock\n# 同上, 解锁一个或者一些文件\n \n$ git lfs migrate\n# 用来将当前已经被 git 储存库保存的文件以 git lfs 的保存 (将 git 对象转为 lfs 对象)\n# 例如如果将当前远程不存在的的所有 pdf 文件清除\n# git lfs migrate import --include="*.pdf"\n#\n# 如果是已经上传到中心服务器的内容, 则需要指定分支 (可能需要 push --force)\n# git lfs migrate import --include="*.mp4" --include-ref=refs/origin/master --include-ref=refs/origin/dev --include-ref=refs/origin/test\n#\n# 然后使用如下命令清理 .git 目录\n# git reflog expire --expire-unreachable=now --all && git gc --prune=now\n \n$ git lfs ls-files\n# 展示全部使用 git lfs 方式加入版本控制的文件\n \n$ git lfs prune\n# 删除全部旧的 Git LFS 文件\n \n$ git lfs fetch\n$ git lfs pull\n$ git lfs push\n$ git lfs checkout\n# 正常情况下会随着 git pull/push 一起执行\n# 如果在 git pull/push 的过程中断了, 导致二进制文件没有被拉取的时候, 可以使用这些命令(支持断点续传,速度不慢)"},"Technology/GettingStarted/版本控制/Git/进阶/参考手册":{"title":"参考手册","links":[],"tags":["Git/进阶","技术/入门"],"content":"创建与克隆项目\n有两种方式获取一个 Git 仓库,仓库是 Git 存放你要保存的快照的数据的地方。\n\n初始化一个新的 Git 仓库。\n克隆一个存在的项目。\n\nGit Init\n在命令行当前目录中执行 git init就可以将当前目录初始化为 Git 仓库。\n$ ls -l\ntotal 0\n$ git init\nInitialized empty Git repository in /root/gitStudy/.git/\n# 在 /root/gitStudy/.git/ 目录初始化空 Git 仓库完毕。\n$ ls -a\n. .. .git\nGit Clone\n如果需要克隆一个存在的项目。在命令行当前目录中执行 git clone [url]url 为项目地址然后就可以了。git clone 实际上是一个封装了其他几个命令的命令。\n\n它创建了一个新目录切换到新的目录。\n然后 git init 来初始化一个空的 Git 仓库, 然后为你指定的 URL 添加一个(默认名称为 origin 的)远程仓库。\n再针对远程仓库执行 git fetch最后通过 git checkout 将远程仓库的最新提交检出到本地的工作目录。\n\n$ git clone git://github.com/schacon/simplegit.git\nInitialized empty Git repository in /private/tmp/simplegit/.git/\nremote: Counting objects: 100, done.\nremote: Compressing objects: 100% (86/86), done.\nremote: Total 100 (delta 35), reused 0 (delta 0)\nReceiving objects: 100% (100/100), 9.51 KiB, done.\nResolving deltas: 100% (35/35), done.\n$ cd simplegit/\n$ ls\nREADME Rakefile lib\n快照基础\nGit 的工作就是创建和保存项目的快照,及与之后的快照进行对比。\n简而言之使用 git add 添加需要追踪的新文件和待提交的更改, 然后使用 git status 和 git diff 查看有何改动, 最后用 git commit 将你的快照记录。绝大部分时候的基本流程都是这样的。\nGit Add\n在 Git 中提交修改文件之前,需要将它们添加到缓存。\n# 添加 helloworld.cpp 至缓存区\n$ git add helloworld.cpp\n# 添加当前目录至缓存区\n$ git add .\nGit Status\n在 Git 中执行 git status 命令,查看代码在缓存与当前工作目录的状态。\n# 简短输出\n$ git status -s\n# 详细输出\n$ git status\nGit Diff\n在 Git 中使用 git diff 描述已临时提交的或者已修改但尚未提交的改动。\n# 尚未缓存的改动\n$ git diff\n# 查看已缓存的改动\n$ git diff --cached\n# 查看已缓存的与未缓存的所有改动\n$ git diff HEAD\n# 显示摘要而非整个 diff\n$ git diff --stat\nGit Commit\n在 Git 中使用 git add 将内容写入缓存,然后执行 git commit 就将它实际存储快照了。\n# 配置提交信息\n$ git config --global user.name 'Your Name'\n$ git config --global user.email you@somedomain.com\n# 添加至缓存\n$ git add hello.rb \n# 输出状态摘要\n$ git status -s\nM hello.rb\n# 提交快照\n$ git commit -m 'my hola mundo changes'\n[master 68aa034] my hola mundo changes\n 1 files changed, 2 insertions(+), 1 deletions(-)\n# 使用 -S 标志提交签名加密\n$ git commit -S -m 'my hola mundo changes'\n# 撤销上次提交\n$ git commit --amend\n如果执行 git commit 不适用 -m 选项Git 则会尝试打开一个编辑器以填写提交信息。如果认为使用 git add 提交的流程太过繁琐Git 允许使用 -a 选项跳过这一步。\n$ vim hello.rb\n$ git status -s\n M hello.rb\n$ git commit -m 'changes to hello file'\n# On branch master\n# Changed but not updated:\n# (use "git add <file>..." to update what will be committed)\n# (use "git checkout -- <file>..." to discard changes in working directory)\n#\n# modified: hello.rb\n#\nno changes added to commit (use "git add" and/or "git commit -a")\n$ git commit -am 'changes to hello file'\n[master 78b2670] changes to hello file\n 1 files changed, 2 insertions(+), 1 deletions(-)\nGit Reset HEAD\ngit reset 命令用于回退版本,可以指定退回某一次提交的版本。\n$git reset HEAD^\nGit Rm\n通过执行 git rm 来删除 Git 追踪的文件,它还会删除你的工作目录中的相应文件。\nGit Mv\ngit mv 命令是一个便利命令,用于移到一个文件并且在新文件上执行 git add 命令及在老文件上执行 git\nrm 命令。\nGit Clean\ngit clean 是一个用来从工作区中移除不想要的文件的命令。 可以是编译的临时文件或者合并冲突的文件。\n分支与合并\n几乎每一种版本控制系统都以某种形式支持分支一个分支代表一条独立的开发线。使用分支意味着你可以从开发主线上分离开来然后在不影响主线的同时继续工作。Git 的分支模型称为必杀技特性,而正是因为它,将 Git 从版本控制系统家族里区分出来。\nGit Branch\n在 Git 中列出、创建与管理工作上下文。\n# 列出可用的分支\n$ git branch\n# 创建新分支\n$ git branch (branchname)\n# 删除分支\n$ git branch -d (branchname)\nGit Switch\n在 Git 中切换至指定分支。\n$git switch master\nGit Checkout\n在 Git 中 git checkout 创建新分支,并立即切换到它\n$git checkout -b (branchname) \nGit Merge\n一旦某分支有了独立内容你终究会希望将它合并回到你的主分支。 你可以使用 git merge 命令将任何分支合并到当前分支中去。\n$ git branch\n* master\n removals\n$ ls\nREADME hello.rb more.txt test.txt\n$ git merge removals\nUpdating 8bd6d8b..8f7c949\nFast-forward\n more.txt | 1 -\n test.txt | 1 -\n 2 files changed, 0 insertions(+), 2 deletions(-)\n delete mode 100644 more.txt\n delete mode 100644 test.txt\n$ ls\nREADME hello.rb\nGit Stash\ngit stash 命令用来临时地保存一些还没有提交的工作,以便在分支上不需要提交未完成工作就可以清理工作\n目录。\nGit Log\n在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看。\n$ git log\ncommit 8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d\nMerge: 3cbb6aa 3ac015d\nAuthor: Scott Chacon <schacon@gmail.com>\nDate: Fri Jun 4 12:59:47 2010 +0200\n \n Merge branch 'fix_readme'\n \n Conflicts:\n README\n \ncommit 3cbb6aae5c0cbd711c098e113ae436801371c95e\nAuthor: Scott Chacon <schacon@gmail.com>\nDate: Fri Jun 4 12:58:53 2010 +0200\n \n fixed readme title differently\n \n...\nGit Tag\n如果你达到一个重要的阶段并希望永远记住那个特别的提交快照你可以使用 git tag 给它打上标签。\n$ git tag -a v1.0 \n# 指定提交打标签\n$ git tag -a v0.9 558151a\n# 指定标签信息命令\n$ git tag -a <tagname> -m "runoob.com标签"\n# PGP签名标签命令\n$ git tag -s <tagname> -m "runoob.com标签"\n项目分享与更新\nGit 并不像 Subversion 那样有个中心服务器。 目前为止所有的命令都是本地执行的,更新的知识本地的数据库。简而言之使用 git fetch 更新你的项目,使用 git push 分享你的改动。 你可以用 git remote 管理你的远程仓库。\nGit Remote\n在 Git 中 git remote 命令管理远端仓库列表。\n# 列出远端别名\n$ git remote\n# 为项目添加一个新的远端仓库\n$ git remote add <remote-name>\n# 删除现存的某个别名\n$ git remote rm <remote-name>\nGit Fetch\n在 Git 中 git fetch 从远端仓库下载新分支与数据。\n$git fetch <remote-name>\nGit Pull\n在 Git 中 **git pull 从远端仓库提取数据并尝试合并到当前分支。**该命令就是在 git fetch 之后紧接着 git merge 远端分支到你所在的任意分支。\n$git pull <remote-name>\nGit Push\n在 Git 中 git push remote-name branch-name 将本地改动推送到远端仓库。 如果可以的话,它会依据你的 branch 的样子,推送到远端的 branch 去。\n$git push github master\nGit Archive\ngit archive 命令用来创建项目一个指定快照的归档文件。\nGit Submodule\ngit submodule 命令用来管理一个仓库的其他外部仓库。\n检查与比较\nGit Show\ngit show 命令可以以一种简单的人类可读的方式来显示一个 Git 对象。 一般使用此命令来显示一个标签或一\n个提交的信息。\nGit Shortlog\ngit shortlog 是一个用来归纳 git log 的输出的命令。 它可以接受很多与 git log 相同的选项,但是此命\n令并不会列出所有的提交而是展示一个根据作者分组的提交记录的概括性信息\nGit Describe\ngit describe 命令用来接受任何可以解析成一个提交的东西,然后生成一个人类可读的字符串且不可变。\n调试\nGit Bisect\ngit bisect 工具是一个非常有用的调试工具,它通过自动进行一个二分查找来找到哪一个特定的提交是导致\nbug 或者问题的第一个提交。\nGit Blame\ngit blame 命令标注任何文件的行,指出文件的每一行的最后的变更的提交及谁是那一个提交的作者。 当你要\n找那个人去询问关于这块特殊代码的信息时这会很有用。\nGit Grep\ngit grep 命令可以帮助在源代码中,甚至是你项目的老版本中的任意文件中查找任何字符串或者正则表达式。\n补丁\nGit Cherry-pick\ngit cherry-pick 命令用来获得在单个提交中引入的变更,然后尝试将作为一个新的提交引入到你当前分支\n上。 从一个分支单独一个或者两个提交而不是合并整个分支的所有变更是非常有用的。\nGit Rebase\ngit rebase 命令基本是是一个自动化的 cherry-pick 命令。 它计算出一系列的提交,然后再以它们在其他\n地方以同样的顺序一个一个的 cherry-picks 出它们。\nGit Revert\ngit revert 命令本质上就是一个逆向的 git cherry-pick 操作。 它将你提交中的变更的以完全相反的方式\n的应用到一个新创建的提交中本质上就是撤销或者倒转。\n邮件\nGit Apply\ngit apply 命令应用一个通过 git diff 或者甚至使用 GNU diff 命令创建的补丁。 它跟补丁命令做了差不多\n的工作但还是有一些小小的差别。\nGit Am\ngit am 命令用来应用来自邮箱的补丁。特别是那些被 mbox 格式化过的。 这对于通过邮件接受补丁并将他们\n轻松地应用到你的项目中很有用。\nGit Format-patch\ngit format-patch 命令用来以 mbox 的格式来生成一系列的补丁以便你可以发送到一个邮件列表中。\nGit Imap-send\ngit imap-send 将一个由 git format-patch 生成的邮箱上传至 IMAP 草稿文件夹。\nGit Send-email\ngit send-mail 命令用来通过邮件发送那些使用 git format-patch 生成的补丁。\nGit Request-pull\ngit request-pull 命令只是简单的用来生成一个可通过邮件发送给某个人的示例信息体。 如果你在公共服务\n器上有一个分支并且想让别人知道如何集成这些变更而不用通过邮件发送补丁你就可以执行此命令的输出\n发送给这个你想拉取变更的人。\n外部系统\nGit Svn\ngit svn 可以使 Git 作为一个客户端来与 Subversion 版本控制系统通信。 这意味着你可以使用 Git 来检出内\n容或者提交到 Subversion 服务器。\nGit Fast-import\n对于其他版本控制系统或者从其他任何的格式导入你可以使用 git fast-import 快速地将其他格式映射到\nGit 可以轻松记录的格式。\n管理\nGit Gc\ngit gc 命令在你的仓库中执行 “garbage collection”删除数据库中不需要的文件和将其他文件打包成一种\n更有效的格式。\nGit Fsck\ngit fsck 命令用来检查内部数据库的问题或者不一致性。\nGit Reflog\ngit reflog 命令分析你所有分支的头指针的日志来查找出你在重写历史上可能丢失的提交。\nGit Filter-branch\ngit filter-branch 命令用来根据某些规则来重写大量的提交记录,例如从任何地方删除文件,或者通过过\n滤一个仓库中的一个单独的子目录以提取出一个项目。"},"Technology/GettingStarted/版本控制/Git/进阶/工作流":{"title":"工作流","links":[],"tags":["Git/进阶","技术/入门"],"content":"你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令。你现在可以学习如何利用 Git 提供的一些分布式工作流程了。\n分布式工作流程\n与传统的集中式版本控制系统CVCS相反Git 的分布式特性使得开发者间的协作变得更加灵活多样。 在集中式系统中,每个开发者就像是连接在集线器上的节点,彼此的工作方式大体相像。 而在 Git 中,每个开发者同时扮演着节点和集线器的角色——也就是说, 每个开发者既可以将自己的代码贡献到其他的仓库中,同时也能维护自己的公开仓库, 让其他人可以在其基础上工作并贡献代码。\n集中式工作流\n集中式系统中通常使用的是单点协作模型——集中式工作流。 一个中心集线器,或者说 仓库,可以接受代码,所有人将自己的工作与之同步。 若干个开发者则作为节点,即中心仓库的消费者与中心仓库同步。\n集成管理者工作流\nGit 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。 这种情形下通常会有个代表“官方”项目的权威的仓库。 要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。 接着你可以请求官方仓库的维护者拉取更新合并到主项目维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。这一流程的工作方式如下所示:\n\n项目维护者推送到主仓库。\n贡献者克隆此仓库做出修改。\n贡献者将数据推送到自己的公开仓库。\n贡献者给维护者发送邮件请求拉取自己的更新。\n维护者在自己本地的仓库中将贡献者的仓库加为远程仓库并合并修改。\n维护者将合并后的修改推送到主仓库。\n\n主管与副主管工作流\n这其实是多仓库工作流程的变种。 一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 被称为 副主管lieutenant 的各个集成管理者分别负责集成项目中的特定部分。 所有这些副主管头上还有一位称为 主管dictator 的总集成管理者负责统筹。 主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。 整个流程看起来是这样的:\n\n普通开发者在自己的主题分支上工作并根据 master 分支进行变基。 这里是主管推送的参考仓库的 master 分支。\n副主管将普通开发者的主题分支合并到自己的 master 分支中。\n主管将所有副主管的 master 分支并入自己的 master 分支中。\n最后主管将集成后的 master 分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基。\n\n向一个项目贡献\n描述如何向一个项目贡献的主要困难在于完成贡献有很多不同的方式。 因为 Git 非常灵活,人们可以通过不同的方式来一起工作,所以描述应该如何贡献并不是非常准确——每一个项目都有一点儿不同。 影响因素包括活跃贡献者的数量、选择的工作流程、提交权限与可能包含的外部贡献方法。\n第一个影响因素是活跃贡献者的数量——积极地向这个项目贡献代码的用户数量以及他们的贡献频率。 在许多情况下,你可能会有两三个开发者一天提交几次,对于不活跃的项目可能更少。 对于大一些的公司或项目,开发者的数量可能会是上千,每天都有成百上千次提交。这很重要,因为随着开发者越来越多,在确保你的代码能干净地应用或轻松地合并时会遇到更多问题。 提交的改动可能表现为过时的,也可能在你正在做改动或者等待改动被批准应用时被合并入的工作严重损坏。 如何保证代码始终是最新的,并且提交始终是有效的?\n下一个影响因素是项目使用的工作流程。 它是中心化的吗,即每一个开发者都对主线代码有相同的写入限?项目是否有一个检查所有补丁的维护者或整合者? 是否所有的补丁是同行评审后批准的? 你是否参与了那个过程? 是否存在副官系统,你必须先将你的工作提交到上面?\n下一个影响因素是提交权限。 是否有项目的写权限会使向项目贡献所需的流程有极大的不同。 如果没有写权限,项目会选择何种方式接受贡献的工作? 是否甚至有一个如何贡献的规范? 你一次贡献多少工作? 你多久贡献一次?\n提交准则\n首字母大写的摘要不多于 50 个字符)\n \n如果必要的话加入更详细的解释文字。在大概 72 个字符的时候换行。\n在某些情形下第一行被当作一封电子邮件的标题剩下的文本作为正文。\n分隔摘要与正文的空行是必须的除非你完全省略正文\n如果你将两者混在一起那么类似变基等工具无法正常工作。\n \n使用指令式的语气来编写提交信息使用“Fix bug”而非“Fixed bug”或“Fixes bug”。\n此约定与 git merge 和 git revert 命令生成提交说明相同。\n \n空行接着更进一步的段落。\n \n- 标号也是可以的。\n \n- 项目符号可以使用典型的连字符或星号,后跟一个空格,行之间用空行隔开,\n 但是可以依据不同的惯例有所不同。\n \n- 使用悬挂式缩进\n私有小型团队\n私有小型团队通常由两个以上开发者工作流程相对简单\n\n\n开发者 John克隆了仓库做了改动然后本地提交。\n\n\n开发者 Jessica做了同样的事情——克隆仓库并提交了一个改动\n\n\nJessica 把她的工作推送到服务器上,一切正常。\n\n\nJohn 稍候也做了些改动,将它们提交到了本地仓库中,然后试着将它们推送到同一个服务器。\n\n\n这时 John 会推送失败,因为之前 Jessica 已经推送了她的更改。\n\n\n因为 John 必须先抓取 Jessica 的上游改动并将它们合并到自己的本地仓库中,才能被允许推送。\n\n\n第一步John 抓取 Jessica 的工作。\n\n\n第二步John 合并工作。\n\n\n…………\n私有管理团队\n型私有团队中贡献者基于特性进行协作而这些团队的贡献将会由其他人整合。\n\nJohn 与 Jessica 在一个特性分支featureA上工作。\nJessica 同时与第三个开发者 Josie 在第二个特性分支featureB上工作。\n公司使用了一种整合 - 管理者工作流程,独立小组的工作只能被特定的工程师整合, 主仓库的 master 分支只能被那些工程师更新。\n在这种情况下所有的工作都是在基于团队的分支上完成的并且稍后会被整合者拉到一起。\n\n…………\n派生的公开项目\n第一个例子描述在支持简单派生的 Git 托管上使用派生来做贡献。 许多托管站点支持这个功能(包括 GitHub、BitBucket、repo.or.cz 等等),许多项目维护者期望这种风格的贡献。\n第二个例子会讨论偏好通过邮件接受贡献补丁的项目。\n通过 Fork 的公开项目\n首先你可能想要克隆主仓库为计划贡献的补丁或补丁序列创建一个主题分支然后在那儿做工作。\n// 克隆远程仓库\ngit clone <url>\n \n// 切换至项目目录\ncd project\n \n// 创建并切换至特性分支\ngit checkout -b featureA\n \n// ... 工作 ...\ngit commit\n \n// ... 工作 ...\ngit commit\n当你的分支工作完成后准备将其贡献回维护者去原始项目中然后点击 Fork 按钮,创建一份自己的可写的项目派生仓库。 然后需要在本地仓库中将该仓库添加为一个新的远程仓库,在本例中称作 myfork\n// 添加 fork 仓库\ngit remote add myfork <url>\n \n// 推送特性分支\ngit push -u myfork featureA\n当工作已经被推送到你的派生仓库后你需要通知原项目的维护者你有想要他们合并的工作。 这通常被称作一个 拉取请求Pull Request你通常可以通过网站生成它。也可以运行 git request-pull 命令然后将随后的输出通过电子邮件手动发送给项目维护者。\n在一个你不是维护者的项目上通常有一个总是跟踪 origin/master 的 master 分支会很方便,在主题分支上做工作是因为如果它们被拒绝时你可以轻松地丢弃。 如果同一时间主仓库移动了然后你的提交不再能干净地应用那么使工作主题独立于主题分支也会使你变基rebase工作时更容易。\n例如你想要提供第二个特性工作到项目不要继续在刚刚推送的主题分支上工作——从主仓库的 master 分支重新开始:\n通过邮件的公开项目\n首先你要克隆主仓库然后在那儿做工作。\n// 克隆远程仓库\ngit clone <url>\n \n// 切换至项目目录\ncd project\n \n// 创建并切换至特性分支\ngit checkout -b topicA\n \n// ... 工作 ...\ngit commit\n \n// ... 工作 ...\ngit commit\n现在有两个提交要发送到邮件列表。 使用 git format-patch 来生成可以邮寄到列表的 mbox 格式的文件——它将每一个提交转换为一封电子邮件,提交信息的第一行作为主题,剩余信息与提交引入的补丁作为正文。\ngit format-patch -M origin/master\n \n// 补丁文件\n<file-name>.patch\n<file-name>.patch\n为了将其邮寄到邮件列表你既可以将文件粘贴进电子邮件客户端也可以通过命令行程序发送它。\n// 本地邮件服务器设置正确的前提下,使用此命令。\ngit send-email <file-name>.patch\n维护项目\n除了如何有效地参与一个项目的贡献之外你可能也需要了解如何维护项目。 这包含接受并应用别人使用 format-patch 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行整合。 但无论是管理版本库,还是帮忙验证、审核收到的补丁,都需要同其他贡献者约定某种长期可持续的工作方式。\n在主题分支中工作\n如同本地新建一个特性分支一般。在添加贡献者的提交分支通过本地测试后就可以考虑是否将其合并到长期分支中了。\n应用来自邮件的补丁\n使用 Apply 命令应用补丁\n如果你收到了一个使用 git diff 或 Unix diff 命令的变体(不推荐使用这种方式,具体见下一小节) 创建的补丁,可以使用 git apply 命令来应用。 假设你将补丁保存在了 /tmp/patch-ruby-client.patch 中,可以这样应用补丁:\ngit apply /tmp/patch-ruby-client.patch\n使用 Am 命令应用补丁\n如果补丁的贡献者也是一个 Git 用户,并且其能熟练使用 format-patch 命令来生成补丁,这样的话你的工作会变得更加轻松,因为这种补丁中包含了作者信息和提交信息供你参考。\n要应用一个由 format-patch 命令生成的补丁,你应该使用 git am 命令。\ngit am <file-name>.patch\n检出远程分支\n如果你的贡献者建立了自己的版本库并且向其中推送了若干修改 之后将版本库的 URL 和包含更改的远程分支发送给你,那么你可以将其添加为一个远程分支,并且在本地进行合并。\n将贡献的工作整合进来\n合并工作流\n一种基本的工作流就是将所有的工作直接合并到 master 分支。 在这种情况下master 分支包含的代码是基本稳定的。 当你完成某个主题分支的工作,或审核通过了其他人所贡献的工作时,你会将其合并进入 master 分支,之后将主题分支删除,如此反复。\n大项目合并工作流\nGit 项目包含四个长期分支master、next用于新工作的 puproposed updates和用于维护性向后移植工作maintenance backports的 maint 分支。 贡献者的新工作会以类似之前所介绍的方式收入主题分支中(见 管理复杂的一系列接收贡献的平行主题分支。)。 之后对主题分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 安全的主题分支会被合并入 next 分支,之后该分支会被推送使得所有人都可以尝试整合到一起的特性。\n变基与拣选工作流\n为了保持线性的提交历史有些维护者更喜欢在 master 分支上对贡献过来的工作进行变基和拣选,而不是直接将其合并。 当你完成了某个主题分支中的工作,并且决定要将其整合的时候,你可以在该分支中运行变基命令, 在当前 master 分支(或者是 develop 等分支)的基础上重新构造修改。\n为发布打标签\n当你决定进行一次发布时你可能想要打一个标签这样在之后的任何一个提交点都可以重新创建该发布。\n生成一个构建号\nGit 中不存在随每次提交递增的 v123 之类的数字序列,如果你想要为提交附上一个可读的名称, 可以对其运行 git describe 命令。作为回应Git 将会生成一个字符串, 它由最近的标签名、自该标签之后的提交数目和你所描述的提交的部分 SHA-1 值(前缀的 g 表示 Git构成\ngit describe master\nv1.6.2-rc1-20-g8c5b85c\n准备一次发布\n现在你可以发布一个构建了。 其中一件事情就是为那些不使用 Git 的可怜包们创建一个最新的快照归档。 使用\ngit archive 命令完成此工作:\ngit archive master > archive.zip\n制作提交简报\n现在是时候通知邮件列表里那些好奇你的项目发生了什么的人了。 使用 git shortlog 命令可以快速生成一份包含从上次发布之后项目新增内容的修改日志changelog类文档。\n// 包括了自 v1.0.1 以来的所有提交\ngit shortlog --no-merges master --not v1.0.1"},"Technology/GettingStarted/版本控制/Git/进阶/常用命令":{"title":"常用命令","links":[],"tags":["Git/进阶","技术/入门"],"content":"创建版本库\n$ git clone <url> #克隆远程版本库\n$ git init #初始化本地版本库\n\n修改和提交\n$ git status #查看状态\n$ git diff #查看变更内容\n$ git add . #跟踪所有改动过的文件\n$ git add <file> #跟踪指定的文件\n$ git mv <old><new> #文件改名\n$ git rm<file> #删除文件\n$ git rm --cached<file> #停止跟踪文件但不删除\n$ git commit -m "commit messages" #提交所有更新过的文件\n$ git commit --amend #修改最后一次改动\n\n查看提交历史\n$ git log #查看提交历史\n$ git log -p <file> #查看指定文件的提交历史\n$ git blame <file> #以列表方式查看指定文件的提交历史\n\n撤销\n$ git reset --hard HEAD #撤销工作目录中所有未提交文件的修改内容\n$ git checkout HEAD <file> #撤销指定的未提交文件的修改内容\n$ git revert <commit> #撤销指定的提交\n$ git log --before="1 days" #退回到之前 1天的版本\n\n分支与标签\n$ git branch #显示所有本地分支\n$ git checkout <branch/tag> #切换到指定分支和标签\n$ git branch <new-branch> #创建新分支\n$ git branch -d <branch> #删除本地分支\n$ git tag #列出所有本地标签\n$ git tag <tagname> #基于最新提交创建标签\n$ git tag -d <tagname> #删除标签\n\n合并与衍合\n$ git merge <branch> #合并指定分支到当前分支\n$ git rebase <branch> #衍合指定分支到当前分支\n\n远程操作\n$ git remote -v #查看远程版本库信息\n$ git remote show <remote> #查看指定远程版本库信息\n$ git remote add <remote> <url> #添加远程版本库\n$ git fetch <remote> #从远程库获取代码\n$ git pull <remote> <branch> #下载代码及快速合并\n$ git push <remote> <branch> #上传代码及快速合并\n$ git push <remote\\> :<branch/tag-name\\> #删除远程分支或标签\n$ git push --tags #上传所有标签\n"},"Technology/GettingStarted/版本控制/Git/进阶/常用技巧":{"title":"常用技巧","links":[],"tags":["Git/进阶","技术/入门"],"content":"Config 配置\nGit 配置文件分为三级系统级—system、用户级—global和目录级—local三者的使用优先级以离目录repository最近为原则如果三者的配置不一样则生效优先级 目录级>用户级>系统级。\n\n系统级/etc/gitconfig使用 —system 来进行配置,该配置对系统上所有用户及他们所拥有的仓库都生效的配置值。\n\ngit config --system user.name "用户名"\ngit config --system user.email "邮箱地址"`\n\n用户级~/.gitconfig使用 —global 来进行配置,该配置对当前用户上所有的仓库有效。\n\ngit config --global user.name "用户名"\ngit config --global user.email "邮箱地址"\n\n目录级.git/config使用 —local 来进行配置,只对当前仓库生效。\n\ngit config --local user.name "用户名"\ngit config --local user.email "邮箱地址"\n设置默认分支\n可以根据需求设置为系统级—system、用户级—global和目录级—local。\ngit config --global init.defaultBranch <分支名称>\n# 设置默认分支 main\ngit config --global init.defaultBranch main\n多平台换行符问题 (LF or CRLF)\n**文本文件所使用的换行符,在不同的系统平台上是不一样的。**UNIX/Linux 使用的是 0x0ALF早期的 Mac OS 使用的是 0x0DCR后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用 0x0D0ACRLF 作为换行符。\n# 提交时转换为LF检出时转换为CRLF\ngit config --global core.autocrlf true\n# 提交时转换为LF检出时不转换\ngit config --global core.autocrlf input\n# 提交检出均不转换\ngit config --global core.autocrlf false\n# 拒绝提交包含混合换行符的文件\ngit config --global core.safecrlf true\n# 允许提交包含混合换行符的文件\ngit config --global core.safecrlf false\n# 提交包含混合换行符的文件时给出警告\ngit config --global core.safecrlf warn\n如果涉及到在多个系统平台上工作推荐将 git 做如下配置:\ngit config --global core.autocrlf input\ngit config --global core.safecrlf true\nAlias 重命名别名\ngit config --global alias.st status //status 缩写成 st\ngit config --global alias.co checkout //checkout 缩写成 co\ngit config --global alias.br branch //branch 缩写成 br\ngit config --global alias.ci commit //commit 缩写成 ci\nalias g='git'\nalias ga='git add'\nalias gco='git checkout'\nalias gcb='git checkout -b'\nalias gcm='git checkout master'\nalias gcd='git checkout develop'\nalias gd='git diff'\nalias gf='git fetch'\nalias gfo='git fetch origin'\nalias gl='git pull'\nalias gp='git push'\nGit 常用命令,可以根据实际需要创建缩写命令。\nGPG 签名提交\n创建新的GPG 密钥\n\n生成 GPG 密钥对\n\n// 1.1 创建 GPG 密钥\ngpg --full-gen-key\n \n// 1.2 列出 GPG 密钥\ngpg --list-secret-keys --keyid-format LONG "your_email@example.com"\n \n// 1.3 复制 GPG 密钥 ID以下示例复制 4AEA00A342C24CA3。\nsec ed25519/4AEA00A342C24CA3 2021-09-14 [SC]\n 6DE3507E82DEB6E8828FAAC34AEA00A342C24BD4\nuid [ 绝对 ] your_name "your_email@example.com"\nssb cv25519/812B586FD245B560 2021-09-14 [E]\n \n// 1.4 导出 GPG 公钥(以上述 ID 为例)\ngpg --armor --export 4AEA00A342C24CA3\n\n平台添加 GPG 公钥配置\n\n将 GPG 公钥添加到 git 托管平台,例如 Github、Gitlab、Gitee 等。\n\n本地 Git 仓库关联 GPG 密钥\n\n// 3.1 列出 GPG 密钥\ngpg --list-secret-keys --keyid-format LONG "your_email@example.com"\n \n// 3.2 复制 GPG 密钥 ID以下示例复制 4AEA00A342C24CA3。\nsec ed25519/4AEA00A342C24CA3 2021-09-14 [SC]\n 6DE3507E82DEB6E8828FAAC34AEA00A342C24BD4\nuid [ 绝对 ] your_name "your_email@example.com"\nssb cv25519/812B586FD245B560 2021-09-14 [E]\n \n// 3.3 本地 Git 仓库中配置该密钥,对 commit 提交进行签名。\ngit config --global user.signingkey 4AEA00A342C24CA3\n\n签名 Git commit\n\n运行 Git commit 命令时需要用到 -S 参数,如果不希望每次都要输入 -S 标志,可以配置默认签名。\n// 签名提交\ngit commit -S -m "your_commit_message"\n \n// 开启默认签名提交\ngit config --global commit.gpgsign true\n\n验证签名\n\n最后可以推送签名提交到 git 托管平台,验证是否签名成功!\n导入已有的 GPG 密钥\n如果你已经有现成的 GPG 密钥,可以导入并使用。\n\n\n导入 GPG 私钥:\ngpg --import your_private_key_file\n\n\n导入 GPG 公钥:\ngpg --import your_public_key_file\n\n\n信任导入的 GPG 密钥:\ngpg --edit-key your_key_id\ngpg> trust\ngpg> 5 (ultimate trust)\ngpg> quit\n\n\n重复创建新的GPG 密钥中的第三步。\n\n\n压缩提交记录\n如果在新分支进行了多次提交然后想合并到主分支。可以使用 —squash 选项,压缩合并提交。\n// 将目标分支的提交压缩为一个,然后合并分支\ngit merge --squash <branchName>\n忽略文件更改\n\n\n未提交添加忽略文件相对路径到 .gitignore 中即可。\n\n\n已提交git rm --cached file添加忽略文件相对路径到 .gitignore 中即可。\n\n\n配置 Git 的凭据存储\n当使用 Git 进行代码管理时,你可以配置 Git 的凭据存储,这样就不需要每次都输入用户名和密码。下面是详细的步骤:\n使用凭证缓存\n\n\n开启凭证缓存\ngit config --global credential.helper cache\n\n\n设置缓存超时时间默认为 15 分钟,以下示例设置为 1 小时):\ngit config --global credential.helper 'cache --timeout=3600'\n\n\n使用凭证管理器\nGit for Windows 以及较新的 Git 版本提供了凭证管理器Credential Manager可以在多平台下存储和管理凭证。\n\n\nWindows 用户:\ngit config --global credential.helper manager\n\n\nMacOS 用户:\ngit config --global credential.helper osxkeychain\n\n\nLinux 用户:\ngit config --global credential.helper cache\n\n\n使用凭证存储\n这种方法会将凭证以纯文本的方式存储在磁盘上安全性较低。\n\n\n开启凭证存储\ngit config --global credential.helper store\n\n\n第一次使用 Git 操作时输入用户名和密码后,凭证会被保存到磁盘。\n\n\n使用 cat 命令查看 .git-credentials 文件的内容:\ncat ~/.git-credentials\n\n\n请注意使用 store 凭据存储方式会将密码明文保存在磁盘上,所以请确保你的机器是安全的,并且不要在共享或公共设备上使用该功能。\n全局的 Git 日志美化\n可以使用 git config --global format.pretty 设置一个全局的 Git 日志格式化语句。\ngit config --global format.pretty "%C(red)%h%C(reset) - %C(yellow)%d%C(reset) %s %C(green)(%cr) %C(bold blue)<%an>%C(reset)"\n常用的配置选项及其描述\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项描述%H提交的完整哈希字符串%h提交的简短哈希字符串%T树的完整哈希字符串%t树的简短哈希字符串%P父节点的完整哈希字符串%p父节点的简短哈希字符串%an作者的名字%ae作者的电子邮件地址%ad作者修订日期可以用 —date=选项定制格式)%ar作者修订日期相对格式例如“2 weeks ago”%cn提交者的名字%ce提交者的电子邮件地址%cd提交日期%cr提交日期相对格式%s提交信息标题%b提交信息正文%Cred文字颜色为红色%Cgreen文字颜色为绿色%Cblue文字颜色为蓝色%Creset重置前面设置的颜色%C(yellow)文字颜色为黄色%d修饰比如分支名标签名%D修饰的完整列表"},"Technology/GettingStarted/版本控制/Git/进阶/思维导图":{"title":"思维导图","links":[],"tags":["Git/进阶","技术/入门"],"content":"\n\nXMind 文件\nPDF 文件\n"},"Technology/GettingStarted/版本控制/Git/进阶/钩子":{"title":"钩子","links":[],"tags":["Git/进阶","技术/入门"],"content":"钩子定义\n钩子是 Git 在特定的重要动作发生时触发自定义脚本,你可以随心所欲地运用这些钩子。主要分以下两种类型:\n\n客户端 客户端钩子由诸如提交和合并这样的操作所调用\n服务器端服务器端钩子作用于诸如接收被推送的提交这样的联网操作\n\n示例\n钩子默认存储在 Git 目录下的 hooks 子目录中。当你用 git init 初始化一个新版本库时Git 默认会在这个目录中放置一些示例脚本。 这些示例脚本的名字都是以 .sample 结尾,如果想启用它们,得先移除这个后缀。\n$ tree .git/hooks\n.git/hooks\n├── applypatch-msg.sample\n├── commit-msg.sample\n├── fsmonitor-watchman.sample\n├── post-update.sample\n├── pre-applypatch.sample\n├── pre-commit.sample\n├── pre-merge-commit.sample\n├── pre-push.sample\n├── pre-rebase.sample\n├── pre-receive.sample\n├── prepare-commit-msg.sample\n└── update.sample\n \n0 directories, 12 files\n这些脚本除了本身可以被调用外它们还透露了被触发时所传入的参数。 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python或任何你熟悉的语言编写它们。\n生命周期\n\n客户端钩子\n提交工作流钩子\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nhook触发点说明pre-commit提交信息前运行它用于检查即将提交的快照如果该钩子以非零值退出Git 将放弃此次提交,不过你可以用 git commit --no-verify 来绕过这个环节。prepare-commit-msg在启动提交信息编辑器之前默认信息被创建之后运行它允许你编辑提交者所看到的默认信息。 该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。 它对一般的提交来说并没有什么用;然而对那些会自动产生默认信息的提交,如提交信息模板、合并提交、压缩提交和修订提交等非常实用。 你可以结合提交模板来使用它动态地插入信息。commit-msg提交信息时运行钩子接收一个参数此参数即上文提到的存有当前提交信息的临时文件的路径。 如果该钩子脚本以非零值退出Git 将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。 在本章的最后一节我们将展示如何使用该钩子来核对提交信息是否遵循指定的模板。post-commit整个提交过程完成后运行它不接收任何参数但你可以很容易地通过运行 git log -1 HEAD 来获得最后一次的提交信息。 该钩子一般用于通知之类的事情。\n电子邮件工作流钩子\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nhook触发点说明applypatch-msg应用补丁前运行它接收单个参数包含请求合并信息的临时文件的名字。 如果脚本返回非零值Git 将放弃该补丁。 你可以用该脚本来确保提交信息符合格式或直接用脚本修正格式错误。pre-applypatch应用补丁后、产生提交之前运你可以用这个脚本运行测试或检查工作区。 如果有什么遗漏,或测试未能通过,脚本会以非零值退出,中断 git am 的运行这样补丁就不会被提交。post-applypatch提交产生后运行git am 运行期间最后被调用的钩子。 你可以用它把结果通知给一个小组或所拉取的补丁的作者。 但你没办法用它停止打补丁的过程。\n其他钩子\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nhook触发点说明pre-rebaserebase 前以非零值退出可以中止变基的过程。 你可以使用这个钩子来禁止对已经推送的提交变基。post-rewrite运行会替换提交记录的命令时调用比如git commit --amend 和 git rebase。它唯一的参数是触发重写的命令名同时从标准输入中接受一系列重写的提交记录。 这个钩子的用途很大程度上跟 post-checkout 和 post-merge 差不多。post-checkout在 git checkout 成功运行后你可以根据你的项目环境用它调整你的工作目录。 其中包括放入大的二进制文件、自动生成文档或进行其他类似这样的操作。post-merge在 git merge 成功运行后你可以用它恢复 Git 无法跟踪的工作区数据,比如权限数据。 这个钩子也可以用来验证某些在 Git 控制之外的文件是否存在这样你就能在工作区改变时把这些文件复制进来。pre-push在 git push 运行期间, 更新了远程引用但尚未传送对象时被调用它接受远程分支的名字和位置作为参数,同时从标准输入中读取一系列待更新的引用。 你可以在推送开始之前用它验证对引用的更新操作一个非零的退出码将终止推送过程。pre-auto-gc在垃圾回收git gc --auto开始之前被调用可以用它来提醒你现在要回收垃圾了或者依情形判断是否要中断回收。\n服务端钩子\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nhook触发点说明pre-receive来自客户端的推送操作时它从标准输入获取一系列被推送的引用。如果它以非零值退出所有的推送内容都不会被接受。 你可以用这个钩子阻止对引用进行非快进non-fast-forward的更新或者对该推送所修改的所有引用和文件进行访问控制。updateupdate 脚本和 pre-receive 脚本十分类似不同之处在于它会为每一个准备更新的分支各运行一次。假如推送者同时向多个分支推送内容pre-receive 只运行一次,相比之下 update 则会为每一个被推送的分支各运行一次。 它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的 SHA-1 值,以及用户准备推送的内容的 SHA-1 值。 如果 update 脚本以非零值退出只有相应的那一个引用会被拒绝其余的依然会被更新。post-receive整个接收过程完结以后运行可以用来更新其他系统服务或者通知用户。 它接受与 pre-receive 相同的标准输入数据。 它的用途包括给某个邮件列表发信通知持续集成continous integration的服务器 或者更新问题追踪系统ticket-tracking system —— 甚至可以通过分析提交信息来决定某个问题ticket是否应该被开启修改或者关闭。 该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态, 所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间"},"Technology/OperatingSystem/Automation/Ansible":{"title":"Ansible","links":[],"tags":["技术/操作系统","自动化/Linux","Linux/安装"],"content":"Ansible\nAnsible 是一个开源的自动化工具主要用于配置管理、应用部署、编排Orchestration等。由 Michael DeHaan 于 2012 年创建Ansible 的设计理念是简单易用、无代理Agentless和基于推送的模型。通过简单的 YAML 文件称为剧本Playbooks定义自动化任务Ansible 能帮助系统管理员和开发人员在大量服务器上快速、可靠地执行各种操作。\nAnsible 历史与发展\nAnsible 由 Michael DeHaan 创建,并在 2012 年发布首个版本。它迅速在 DevOps 社区中获得了广泛的关注和使用因其易用性和强大的功能。2015 年Ansible 被 Red Hat 收购这使其发展得更为迅速和稳定。如今Ansible 已成为业界领先的自动化工具之一,被广泛应用于各类企业和组织中。\n为什么选择 Ansible\n\n简单易用Ansible 采用 YAML 作为配置语言,简单明了,易于理解和编写。\n无代理架构Ansible 不需要在被管理的节点上安装任何代理软件,减少了维护成本和复杂性。\n强大的模块支持Ansible 提供了数百个模块,支持多种操作系统、云平台、网络设备等。\n声明式配置Ansible 允许用户通过声明式配置文件定义所需状态,确保系统的一致性。\n社区活跃Ansible 拥有一个活跃的开源社区,丰富的文档和资源,支持广泛。\n\nAnsible 架构概述\n\nAnsible 的架构设计非常简洁,主要包括以下几个组件:\n\n控制节点Control Node运行 Ansible 的机器,通常是管理员的工作站或管理服务器。所有的 Ansible 命令和 Playbook 都从控制节点执行。\n被管理节点Managed Nodes通过 SSH 或 WinRM 连接并由 Ansible 控制的机器,这些节点可以是物理服务器、虚拟机、容器,或网络设备等。\n剧本Playbooks使用 YAML 编写的配置文件,定义了一系列的任务和操作,用于配置、部署和编排多个被管理节点上的资源。\n模块ModulesAnsible 的基本执行单元每个模块都实现了特定的功能如安装软件包、管理文件、执行命令等。Ansible 提供了数百个内置模块,并允许用户编写自定义模块。\n插件Plugins扩展 Ansible 功能的小程序包括连接插件connection plugins、回调插件callback plugins、过滤插件filter plugins增强 Ansible 的灵活性和功能。\n清单Inventory定义被管理节点及其分组信息的文件可以是静态文件如 INI 或 YAML 格式)或动态生成的脚本,支持定义主机变量和组变量。\n角色Roles将剧本、任务、处理程序、变量、模板和文件等组织在一起的目录结构用于复用和共享配置实现配置管理的模块化和标准化。\n\nAnsible 主要特性\n无代理架构\nAnsible 采用无代理架构这意味着它不需要在被管理的节点上安装任何软件或代理。Ansible 通过 SSH 进行通信,简化了管理和维护工作,并提高了系统的安全性和可靠性。\n基于 YAML 的配置\nAnsible 使用 YAML 作为其配置语言。YAML 简洁直观,易于阅读和编写,特别适合用来编写配置文件。通过 YAML 文件,用户可以定义各种自动化任务,轻松实现复杂的操作。\n以声明式为中心\nAnsible 采用声明式配置模型用户只需定义期望的系统状态Ansible 会自动计算并执行所需的操作,确保系统达到期望状态。这种方式减少了配置错误,提高了系统的一致性和可维护性。\n广泛的模块支持\nAnsible 提供了丰富的内置模块涵盖了几乎所有常见的系统管理和应用部署任务。此外Ansible 还支持用户编写自定义模块,满足特殊需求。模块可以通过官方 Ansible Galaxy 平台共享和下载,进一步扩展了 Ansible 的功能和应用范围。\nAnsible 应用场景\n配置管理\nAnsible 可以用于配置管理自动化配置服务器和网络设备。通过剧本定义配置细节Ansible 能够确保大规模环境中所有设备的一致性,简化了系统维护和升级工作。\n应用部署\nAnsible 支持自动化应用部署从代码拉取、编译、安装到配置均可以通过剧本实现。无论是简单的单机应用还是复杂的多节点分布式系统Ansible 都能有效管理和部署。\n编排Orchestration\nAnsible 不仅可以执行单个任务还可以编排复杂的工作流程。通过定义依赖关系和执行顺序Ansible 能够协调多个服务和系统的协同工作,确保在多步骤操作中各个环节的正确执行。\nAnsible 安装与配置\n系统要求\nAnsible 设计为跨平台运行,支持多种操作系统,包括但不限于以下几种:\n\nLinux支持绝大多数发行版如 Ubuntu、CentOS、Debian、Red Hat Enterprise Linux (RHEL) 等。\nmacOS可以在 macOS 上安装并运行 Ansible用于开发和测试环境。\nWindows通过 WSLWindows Subsystem for Linux或在 Windows 上安装 Cygwin可以在 Windows 上运行 Ansible。\n\nAnsible 运行时需要以下基本依赖项:\n\nPythonAnsible 需要 Python 2.7 或 Python 3.5 及以上版本。\nSSHAnsible 通过 SSH 与被管理节点通信,需要在控制节点和被管理节点上配置 SSH。\n其他依赖根据具体模块需求可能需要额外安装一些依赖包例如用于云平台管理的 SDK。\n\nAnsible 安装步骤\n在不同操作系统上的安装\nUbuntu\n在 Ubuntu 上安装 Ansible 非常简单,可以通过官方的包管理器 APT 进行安装:\nsudo apt update\nsudo apt install ansible\nCentOS\n在 CentOS 上,可以通过 EPELExtra Packages for Enterprise Linux库安装 Ansible\nsudo yum install epel-release\nsudo yum install ansible\nmacOS\n在 macOS 上,可以使用 Homebrew 来安装 Ansible\nbrew install ansible\n通过 Python Pip 安装\n可以使用 Python 的包管理器 pip 来安装 Ansible这种方法适用于任何支持 Python 的操作系统:\npip install ansible\n从源代码安装\n从源代码安装适用于需要最新功能或定制 Ansible 的场景:\ngit clone github.com/ansible/ansible.git\ncd ansible\nsource ./hacking/env-setup\n这种方法需要额外的依赖包具体可以参考 Ansible 官方文档。\nAnsible 配置方法\nAnsible 配置文件结构ansible.cfg\nAnsible 的配置文件 ansible.cfg 允许用户自定义 Ansible 的运行参数。该文件通常位于以下位置之一:\n\n当前目录下的 ansible.cfg\n用户主目录下的 .ansible.cfg\n全局配置文件 /etc/ansible/ansible.cfg\n\n一个典型的 ansible.cfg 文件结构如下:\n[defaults]\ninventory = ./hosts\nremote_user = ansible\nprivate_key_file = ~/.ssh/id_rsa\nhost_key_checking = False\n \n[privilege_escalation]\nbecome = True\nbecome_method = sudo\nbecome_user = root\nbecome_ask_pass = False\n \n[ssh_connection]\nssh_args = -o ControlMaster=auto -o ControlPersist=60s\npipelining = True\nAnsible 配置文件优先级\nAnsible 允许在多个位置定义配置文件,并根据以下优先级顺序应用配置:\n\n命令行参数直接在命令行上指定的参数优先级最高。\n环境变量通过环境变量设置的配置次高优先级。\nansible.cfg 文件:\n\n当前目录下的 ansible.cfg\n用户主目录下的 .ansible.cfg\n全局配置文件 /etc/ansible/ansible.cfg\n\n\n模块参数模块内部的参数配置。\n默认值Ansible 内部的默认值。\n\n常用配置选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置选项说明inventory定义主机清单文件的位置。remote_user指定远程主机的默认用户。private_key_file定义用于 SSH 连接的私钥文件。host_key_checking是否检查 SSH 主机密钥默认启用。retry_files_enabled是否生成重试文件默认启用。log_path指定 Ansible 运行日志的存储路径。become是否启用权限提升如 sudo。become_method权限提升的方法如 sudo 或 su。become_user权限提升后的目标用户。become_ask_pass是否提示输入密码用于权限提升。ssh_args定制 SSH 连接参数。pipelining启用管道以提高性能。\nSSH 密钥和认证配置\nAnsible 通过 SSH 与被管理节点通信,配置 SSH 密钥认证可以提高安全性和自动化程度。\n\n生成 SSH 密钥对:\n\nssh-keygen -t rsa -b 4096 -C "your_email@example.com"\n生成的密钥文件通常存储在 ~/.ssh/ 目录下。\n\n将公钥添加到被管理节点\n\nssh-copy-id user@remote_host\n或者手动将公钥添加到被管理节点的 ~/.ssh/authorized_keys 文件中。\n\n配置 SSH 代理(可选): 使用 SSH 代理可以管理多个 SSH 密钥,提高连接效率:\n\neval "$(ssh-agent -s)"\nssh-add ~/.ssh/id_rsa\n通过上述步骤Ansible 可以无密码地通过 SSH 访问被管理节点,从而实现自动化操作。\nAnsible 自动化管理基础\nAnsible Playbooks\nPlaybook 的基本结构\nPlaybook 是 Ansible 的核心配置文件,用于定义一系列自动化任务。它使用 YAML 格式编写,主要由 Plays 和 Tasks 组成。一个典型的 Playbook 结构如下:\n- name: Describe the purpose of the playbook\n hosts: target_hosts_group\n become: yes\n vars:\n variable_name: value\n tasks:\n - name: Describe the task\n module_name:\n module_option: value\nPlaybook 的常用关键字\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n关键字说明name描述 Play 或 Task 的名称便于阅读和调试。hosts指定目标主机或主机组可以是一个或多个主机组名。become是否启用权限提升如 sudo默认值为 no。vars定义在 Play 级别的变量,适用于整个 Play。tasks任务列表每个任务调用一个模块执行特定操作。roles指定在 Play 中包含的角色角色是一个组织良好的任务集合。handlers定义事件触发的任务当其他任务通知这些处理程序时执行。environment指定任务或 Play 级别的环境变量。gather_facts是否在 Play 开始时收集远程主机的信息,默认值为 yes。notify通知一个或多个处理程序在任务完成时执行。when条件语句用于在特定条件下执行任务。with_items循环语句用于在任务中迭代一个列表。register捕获任务的输出结果并存储在变量中。tags为任务或 Play 打标签,便于选择性地运行特定任务或 Play。ignore_errors是否忽略任务执行中的错误继续执行后续任务。delegate_to将任务委派给指定的主机执行而不是在目标主机上执行。serial控制任务并行执行的主机数量或批次大小。max_fail_percentage允许的最大失败百分比超过此比例时停止 Play。\n编写和运行第一个 Playbook\n\n编写 Playbook 文件(如 first_playbook.yml\n\n- name: Install and start Apache web server\n hosts: webservers\n become: yes\n tasks:\n - name: Install Apache\n apt:\n name: apache2\n state: present\n - name: Start Apache service\n service:\n name: apache2\n state: started\n\n运行 Playbook\n\nansible-playbook first_playbook.yml\n在此示例中Playbook 定义了一个 Play包含两个任务一个用于安装 Apache Web 服务器,另一个用于启动 Apache 服务。hosts 指定了目标主机组为 webservers并通过 become: yes 启用权限提升(通常是 sudo。\n多 Play 和任务的组织\n一个 Playbook 可以包含多个 Play每个 Play 针对不同的主机组或执行不同的任务。这种结构有助于在一个 Playbook 中管理复杂的部署场景。\n- name: Setup web servers\n hosts: webservers\n become: yes\n tasks:\n - name: Install Apache\n apt:\n name: apache2\n state: present\n \n - name: Start Apache service\n service:\n name: apache2\n state: started\n \n- name: Setup database servers\n hosts: dbservers\n become: yes\n tasks:\n - name: Install MySQL\n apt:\n name: mysql-server\n state: present\n \n - name: Start MySQL service\n service:\n name: mysql\n state: started\n在此示例中Playbook 包含两个 Play第一个 Play 针对 webservers 主机组,安装并启动 Apache Web 服务器;第二个 Play 针对 dbservers 主机组,安装并启动 MySQL 数据库服务。\n通过组织多个 Play 和任务,可以在一个 Playbook 中处理多种部署需求,提高配置管理的灵活性和可维护性。\nAnsible 模块\n常用模块\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块名称用途示例file管理文件和目录yaml\\n- name: Create a directory\\n file:\\n path: /path/to/directory\\n state: directory\\nservice管理服务yaml\\n- name: Start a service\\n service:\\n name: nginx\\n state: started\\ncommand执行命令yaml\\n- name: Run a command\\n command: /usr/bin/uptime\\nshell执行 shell 命令yaml\\n- name: Run a shell command\\n shell: echo "Hello, world!" > /tmp/hello.txt\\ncopy复制文件到远程主机yaml\\n- name: Copy a file\\n copy:\\n src: /local/path/to/file\\n dest: /remote/path/to/file\\ntemplate使用 Jinja2 模板渲染并复制文件到远程主机yaml\\n- name: Deploy configuration file from template\\n template:\\n src: /path/to/template.j2\\n dest: /path/to/destination\\nyum使用 YUM 包管理器安装、卸载包(适用于 RHEL 系yaml\\n- name: Install a package using yum\\n yum:\\n name: httpd\\n state: present\\napt使用 APT 包管理器安装、卸载包(适用于 Debian 系yaml\\n- name: Install a package using apt\\n apt:\\n name: apache2\\n state: present\\nuser管理用户yaml\\n- name: Create a user\\n user:\\n name: username\\n state: present\\n password: password_hash\\ngroup管理用户组yaml\\n- name: Create a group\\n group:\\n name: groupname\\n state: present\\ncron管理 cron 作业yaml\\n- name: Add a cron job\\n cron:\\n name: "backup script"\\n minute: "0"\\n hour: "2"\\n job: "/path/to/backup.sh"\\ngit管理 Git 仓库yaml\\n- name: Clone a Git repository\\n git:\\n repo: "github.com/repo.git"\\n dest: "/path/to/destination"\\n\n每个模块都有特定的参数和选项可以在 Ansible 官方文档中查找详细信息。例如file 模块的常用参数包括 path、state、owner、group 等。\n自定义模块\n如果内置模块不能满足需求可以编写自定义模块。自定义模块可以使用 Python 编写,并放置在库路径中。\n示例自定义模块my_module.py\n#!/usr/bin/python\n \nfrom ansible.module_utils.basic import AnsibleModule\n \ndef run_module():\n module_args = dict(\n name=dict(type='str', required=True)\n )\n \n module = AnsibleModule(\n argument_spec=module_args,\n supports_check_mode=True\n )\n \n result = dict(\n changed=False,\n message=''\n )\n \n name = module.params['name']\n result['message'] = f'Hello, {name}!'\n \n if module.check_mode:\n module.exit_json(**result)\n \n module.exit_json(**result)\n \ndef main():\n run_module()\n \nif __name__ == '__main__':\n main()\n运行自定义模块\n- name: Use custom module\n hosts: localhost\n tasks:\n - name: Call custom module\n my_module:\n name: Ansible\nAnsible 变量和模板\n变量的定义与使用\n变量可以在多个地方定义如 Playbook、清单文件、角色等\n- name: Example with variables\n hosts: localhost\n vars:\n http_port: 80\n tasks:\n - name: Display variable\n debug:\n msg: "HTTP port is {{ http_port }}"\n变量优先级\nAnsible 变量的优先级从低到高依次为:\n\n角色默认变量role defaults\n组变量group vars\n主机变量host vars\n播放Play中的变量\n任务Task中的变量\n命令行定义的变量使用 -e 参数)\n\n这个优先级决定了当同一个变量在多个地方定义时哪个值会被使用。\nJinja2 模板语法\nAnsible 使用 Jinja2 作为模板引擎,支持复杂的模板生成。模板文件通常以 .j2 结尾,放置在 templates 目录下。\n示例模板文件config.j2\n## 变量替换\nHello, {{ name }}!\n \n## 条件语句\n{% if http_port == 80 %}\n server {\n listen 80;\n }\n{% else %}\n server {\n listen {{ http_port }};\n }\n{% endif %}\n \n## 循环语句\n{% for user in users %}\n user {{ user.name }} with id {{ user.id }}\n{% endfor %}\n使用模板生成配置文件\n可以使用 template 模块将 Jinja2 模板渲染为实际配置文件,并部署到目标主机上。\n示例 Playbookdeploy_config.yml\n- name: Deploy configuration file\n hosts: webservers\n become: yes\n vars:\n http_port: 80\n server_name: example.com\n proxy_url: 127.0.0.1:8080\n tasks:\n - name: Deploy nginx configuration\n template:\n src: templates/nginx.conf.j2\n dest: /etc/nginx/sites-available/default\n notify:\n - restart nginx\n \n handlers:\n - name: restart nginx\n service:\n name: nginx\n state: restarted\n示例模板文件nginx.conf.j2\nserver {\n listen {{ http_port }};\n server_name {{ server_name }};\n \n location / {\n proxy_pass http://{{ proxy_url }};\n }\n}\n在此 Playbook 中template 模块会将 templates/nginx.conf.j2 文件渲染为实际的配置文件,并部署到 /etc/nginx/sites-available/default。如果模板内容发生变化通知部分会触发 restart nginx 处理程序,重启 nginx 服务以应用新的配置。\n通过这种方式可以使用 Ansible 自动化生成和部署配置文件,大大简化了系统配置管理的工作,并确保配置的一致性和可重复性。\nAnsible 高级应用技巧\nAnsible 角色\n角色的结构与组成\n角色Roles是 Ansible 中的一种组织方式,用于将 Playbooks 和相关文件(如任务、处理程序、变量、模板等)结构化和模块化。角色的目录结构通常如下:\nroles/\n └── role_name/\n ├── tasks/\n │ └── main.yml\n ├── handlers/\n │ └── main.yml\n ├── templates/\n │ └── template_file.j2\n ├── files/\n │ └── file_name\n ├── vars/\n │ └── main.yml\n ├── defaults/\n │ └── main.yml\n ├── meta/\n │ └── main.yml\n └── README.md\n\ntasks存放主要任务列表main.yml 是入口文件)。\nhandlers存放处理程序main.yml 是入口文件)。\ntemplates存放 Jinja2 模板文件。\nfiles存放需要复制到远程主机的静态文件。\nvars存放角色专用变量。\ndefaults存放默认变量。\nmeta存放角色的元数据如依赖关系。\nREADME.md角色的说明文档描述角色的用途、用法等。\n\n创建和使用角色\n\n创建角色\n\nansible-galaxy init my_role\n这条命令会生成上述结构的角色目录。\n\n定义任务roles/my_role/tasks/main.yml\n\n- name: Install Apache\n apt:\n name: apache2\n state: present\n \n- name: Start Apache service\n service:\n name: apache2\n state: started\n在这个例子中定义了两个任务一个用于安装 Apache另一个用于启动 Apache 服务。\n\n在 Playbook 中使用角色:\n\n- name: Apply my role\n hosts: webservers\n roles:\n - my_role\n在 Playbook 中,通过 roles 关键字引用角色。\n角色的共享与重用Ansible Galaxy\nAnsible Galaxy 是 Ansible 官方的角色分享平台,用户可以在上面发布和下载角色,方便角色的共享与重用。\n\n安装角色\n\nansible-galaxy install username.role_name\n可以从 Galaxy 下载并安装角色。安装的角色通常会存放在 Ansible 的角色路径中(默认是 /etc/ansible/roles 或 ~/.ansible/roles。\n\n使用已安装的角色\n\n- name: Use a role from Ansible Galaxy\n hosts: webservers\n roles:\n - username.role_name\n在 Playbook 中通过 roles 关键字引用已经安装的角色。\n通过使用 Ansible 角色,可以将复杂的 Playbook 结构化、模块化,使得配置管理更为清晰、可维护。同时,通过 Ansible Galaxy 平台,可以方便地共享和重用角色,提升团队协作和生产效率。\nAnsible 动态 Inventory\n静态 Vs 动态 Inventory\n静态 Inventory 是一个简单的文本文件,列出所有被管理节点及其分组。动态 Inventory 则是通过脚本或插件生成的,适用于云环境或动态变化的基础设施。\n示例静态 Inventoryhosts\n[webservers]\nweb1.example.com\nweb2.example.com\n \n[dbservers]\ndb1.example.com\ndb2.example.com\n动态 Inventory 脚本编写\n动态 Inventory 脚本可以用任何语言编写,只要它能输出 JSON 格式的主机和组信息。例如,使用 Python 编写一个简单的动态 Inventory 脚本my_inventory.py\n#!/usr/bin/env python\n \nimport json\n \ninventory = {\n "webservers": {\n "hosts": ["web1.example.com", "web2.example.com"],\n },\n "dbservers": {\n "hosts": ["db1.example.com", "db2.example.com"],\n }\n}\n \nprint(json.dumps(inventory))\n运行 Playbook 时使用该脚本:\nansible-playbook -i my_inventory.py my_playbook.yml\n常用的动态 Inventory 插件(如 AWS、Azure\nAnsible 提供了多种动态 Inventory 插件,支持 AWS、Azure、GCP 等云平台。\n\nAWS 动态 Inventory 安装 boto3\n\npip install boto3\n创建 aws_ec2.yml 配置文件,使用 aws_ec2 插件:\nplugin: aws_ec2\nregions:\n - us-east-1\nfilters:\n instance-state-name: running\nkeyed_groups:\n - key: tags.Name\n prefix: tag\n - key: tags.Environment\n prefix: env\n使用该配置文件运行 Playbook\nansible-playbook -i aws_ec2.yml my_playbook.yml\n\nAzure 动态 Inventory 安装 azure-cli 和 azure-mgmt\n\npip install azure-cli azure-mgmt\n使用 azure_rm 插件:\nplugin: azure_rm\ninclude_vm_resource_groups:\n - myResourceGroup\nauth_source: auto\n使用该配置文件运行 Playbook\nansible-playbook -i azure_rm.yml my_playbook.yml\n\n\nGCP 动态 Inventory\n\n安装 google-auth 和 google-api-python-client 库:\npip install google-auth google-api-python-client\n创建 gcp_compute.yml 配置文件,使用 gcp_compute 插件:\nplugin: gcp_compute\nprojects:\n - my-gcp-project\nfilters:\n - status = RUNNING\nauth_kind: serviceaccount\nservice_account_file: /path/to/service-account.json\n使用该配置文件运行 Playbook\nansible-playbook -i gcp_compute.yml my_playbook.yml\n通过动态 Inventory可以自动发现和管理云环境中的资源提高自动化程度和灵活性。这在动态变化的基础设施中尤其有用确保 Ansible 的管理目标始终是最新的。\nAnsible Vault\n使用 Vault 加密敏感数据\nAnsible Vault 用于加密敏感数据,如密码、密钥等,确保这些信息在存储和传输过程中不会被泄露。以下是 Ansible Vault 的基本使用方法:\n# 1.加密文件\nansible-vault encrypt secret.yml\n \n# 2.解密文件\nansible-vault decrypt secret.yml\n \n# 3.编辑加密文件\nansible-vault edit secret.yml\n \n# 4.查看加密文件\nansible-vault view secret.yml\n \n# 5.重新加密文件(更改加密密码)\nansible-vault rekey secret.yml\nVault 的管理和使用\n为了更方便地管理 Vault可以在 ansible.cfg 中指定 Vault 密码文件,这样在运行 Playbook 时无需每次手动输入密码:\n[defaults]\nvault_password_file = /path/to/.vault_pass.txt\n/path/to/.vault_pass.txt 文件中应只包含 Vault 密码,且该文件应设置为仅有文件所有者可读写:\nchmod 600 /path/to/.vault_pass.txt\n如果不希望将密码写入文件也可以使用命令行参数 --ask-vault-pass\nansible-playbook --ask-vault-pass my_playbook.yml\n在 Playbooks 中集成 Vault\n在 Playbook 中使用 Vault 加密的变量文件时,可以通过 vars_files 引用这些文件:\n- name: Deploy with Vault\n hosts: webservers\n vars_files:\n - secret.yml\n tasks:\n - name: Use encrypted variable\n debug:\n msg: "The secret is {{ vault_secret }}"\n在这个示例中secret.yml 是一个加密的变量文件其中包含敏感数据。Ansible 会在运行 Playbook 时解密并加载这些变量。\nVault ID 和多 Vault 支持\nAnsible Vault 支持使用多个 Vault ID 来加密不同级别或类型的敏感数据。使用 --vault-id 选项可以指定不同的 Vault 密码文件或密码提示命令。\n例如加密文件时指定 Vault ID\nansible-vault encrypt --vault-id dev@prompt secret_dev.yml\nansible-vault encrypt --vault-id prod@/path/to/prod_vault_pass.txt secret_prod.yml\n在 Playbook 中引用不同 Vault ID 的变量文件:\n- name: Deploy with Vault IDs\n hosts: webservers\n vars_files:\n - vault_id: dev\n file: secret_dev.yml\n - vault_id: prod\n file: secret_prod.yml\n tasks:\n - name: Use dev encrypted variable\n debug:\n msg: "Dev secret is {{ dev_secret }}"\n - name: Use prod encrypted variable\n debug:\n msg: "Prod secret is {{ prod_secret }}"\n运行 Playbook 时,指定 Vault ID 和密码文件:\nansible-playbook --vault-id dev@prompt --vault-id prod@/path/to/prod_vault_pass.txt my_playbook.yml\n通过 Ansible Vault可以有效地保护敏感数据确保自动化流程的安全性同时保持操作的便捷性和高效性。\nAnsible 与其他自动化工具的比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度AnsiblePuppetChef架构无代理架构通过 SSH 或 WinRM 与被管理节点通信有代理架构,需要在被管理节点上安装 Puppet Agent有代理架构需要在被管理节点上安装 Chef Client通信模型基于推送模型由控制节点推送任务到被管理节点执行基于拉取模型被管理节点定期向 Puppet Master 拉取配置基于拉取模型,被管理节点定期向 Chef Server 拉取配置配置语言使用 YAML 编写 Playbook直观易读使用 Puppet 自定义的声明式语言编写清单Manifest使用 Ruby 编写食谱Cookbooks脚本式语言灵活性高学习曲线简单易用适合快速上手学习曲线较为陡峭学习曲线较陡需要掌握 Ruby适用场景临时和一次性任务、多平台支持、快速部署和小型团队大规模配置管理、复杂依赖管理、企业级功能复杂和大型环境管理、需要复杂逻辑和自定义的场景模块支持内置丰富的模块适用于多种场景提供丰富的模块和企业级工具提供灵活的配置和扩展能力依赖管理依赖管理能力相对较弱强大的资源依赖管理能力灵活的依赖管理和配置能力企业级功能提供一些企业级功能社区活跃资源丰富提供丰富的企业级功能和工具如报告、审计、合规管理等提供强大的企业级功能和支持性能由于采用 SSH 推送模型,在大规模环境中性能可能会受到限制性能较好,适合大规模环境性能较好,适合复杂和大型环境维护成本无代理架构,减少了管理和维护成本需要管理和维护 Puppet Master 和 Agent需要管理和维护 Chef Server 和 Client社区和支持拥有庞大且活跃的社区提供丰富的资源和支持社区活跃企业级支持完善社区活跃企业级支持完善\nAnsible 在云环境中的应用\nAWS 集成\n安装并配置 boto3 库,使用 ec2 模块管理 AWS 资源。\npip install boto3\n配置 Ansible Inventory 使用 AWS 动态库存插件 aws_ec2\nplugin: aws_ec2\nregions:\n - us-east-1\nfilters:\n instance-state-name: running\n示例 Playbook创建和管理 EC2 实例。\n- name: Launch EC2 instance\n hosts: localhost\n tasks:\n - name: Launch an instance\n ec2:\n key_name: my-key\n instance_type: t2.micro\n image: ami-0abcdef1234567890\n wait: yes\n region: us-east-1\n group: my-security-group\nAzure 集成\n安装并配置 azure-cli 和 azure-mgmt 库,使用 azure_rm 模块管理 Azure 资源。\npip install azure-cli azure-mgmt\n配置 Ansible Inventory 使用 Azure 动态库存插件 azure_rm\nplugin: azure_rm\ninclude_vm_resource_groups:\n - myResourceGroup\n示例 Playbook创建和管理 Azure VM 实例。\n- name: Launch Azure VM\n hosts: localhost\n tasks:\n - name: Create a VM\n azure_rm_virtualmachine:\n resource_group: myResourceGroup\n name: myVM\n vm_size: Standard_DS1_v2\n admin_username: azureuser\n admin_password: Password123!\n image:\n offer: UbuntuServer\n publisher: Canonical\n sku: 18.04-LTS\n version: latest\n云资源管理和部署\n动态库存管理\n使用动态库存插件自动发现和管理云资源无需手动更新 Inventory 文件。\n - name: List EC2 instances\n hosts: localhost\n tasks:\n - name: List instances\n ec2_instance_facts:\n region: us-east-1\n自动化部署\n使用 Ansible Playbook 实现云资源的自动化部署和配置,简化操作流程。\n- name: Deploy web application on AWS\n hosts: tag_Environment_web\n become: yes\n tasks:\n - name: Install Nginx\n yum:\n name: nginx\n state: present\n - name: Start Nginx\n service:\n name: nginx\n state: started\nAnsible 在容器化环境中的应用\nDocker 集成\n使用 community.docker 集成 Docker管理 Docker 容器和镜像。\n- name: Manage Docker\n hosts: all\n become: yes\n tasks:\n - name: Install Docker\n apt:\n name: docker.io\n state: present\n - name: Run a Docker container\n community.docker.docker_container:\n name: mycontainer\n image: nginx\n state: started\n ports:\n - "80:80"\nKubernetes 集成\n使用 kubernetes.core 集成 Kubernetes管理 Kubernetes 资源和集群。\n- name: Manage Kubernetes\n hosts: localhost\n tasks:\n - name: Create a namespace\n kubernetes.core.k8s:\n state: present\n definition:\n apiVersion: v1\n kind: Namespace\n metadata:\n name: mynamespace\n - name: Deploy a pod\n kubernetes.core.k8s:\n state: present\n definition:\n apiVersion: v1\n kind: Pod\n metadata:\n name: mypod\n namespace: mynamespace\n spec:\n containers:\n - name: nginx\n image: nginx\n容器部署\n使用 Ansible 部署和管理容器化应用,实现自动化运维。\n- name: Deploy Dockerized application\n hosts: all\n become: yes\n tasks:\n - name: Pull Docker image\n community.docker.docker_image:\n name: myapp\n tag: latest\n source: pull\n - name: Run Docker container\n community.docker.docker_container:\n name: myapp\n image: myapp:latest\n state: started\n ports:\n - "8080:8080"\nKubernetes 应用编排\n使用 Ansible 管理 Kubernetes 集群,实现应用编排和服务发现。\n- name: Deploy Kubernetes application\n hosts: localhost\n tasks:\n - name: Create deployment\n kubernetes.core.k8s:\n state: present\n definition:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: myapp\n namespace: default\n spec:\n replicas: 3\n selector:\n matchLabels:\n app: myapp\n template:\n metadata:\n labels:\n app: myapp\n spec:\n containers:\n - name: myapp\n image: myapp:latest\n ports:\n - containerPort: 8080\n - name: Expose service\n kubernetes.core.k8s:\n state: present\n definition:\n apiVersion: v1\n kind: Service\n metadata:\n name: myapp-service\n namespace: default\n spec:\n selector:\n app: myapp\n ports:\n - protocol: TCP\n port: 80\n targetPort: 8080\nAnsible 在传统 IT 环境中的应用\n数据中心管理\n服务器配置管理\n使用 Ansible 管理数据中心服务器的配置,确保一致性和自动化。\n- name: Configure data center servers\n hosts: datacenter\n become: yes\n tasks:\n - name: Update all packages\n apt:\n upgrade: dist\n - name: Ensure NTP is installed\n apt:\n name: ntp\n state: present\n - name: Configure NTP\n copy:\n src: templates/ntp.conf.j2\n dest: /etc/ntp.conf\n notify:\n - restart ntp\n \n handlers:\n - name: restart ntp\n service:\n name: ntp\n state: restarted\n硬件管理\n使用 Ansible 自动化硬件管理,如固件升级和 BIOS 配置。\n- name: Manage hardware\n hosts: datacenter\n become: yes\n tasks:\n - name: Upgrade firmware\n command: /usr/bin/upgrade_firmware.sh\n网络设备配置\n网络设备管理\n使用 Ansible 管理网络设备配置,自动化网络设备的部署和更新。\n- name: Configure network devices\n hosts: switches\n become: yes\n tasks:\n - name: Update switch firmware\n ios_command:\n commands:\n - copy tftp://192.0.2.1/new_firmware.bin flash:\n - reload\n网络拓扑管理\n使用 Ansible 自动化网络拓扑的配置和管理,确保网络配置的一致性。\n- name: Configure network topology\n hosts: routers\n become: yes\n tasks:\n - name: Configure OSPF\n ios_config:\n lines:\n - router ospf 1\n - network 10.0.0.0 0.255.255.255 area 0\n跨平台管理\n多操作系统管理\n使用 Ansible 管理多种操作系统,包括 Linux、Windows 和 macOS。\n- name: Manage multiple OS\n hosts: all\n become: yes\n tasks:\n - name: Install packages on Linux\n apt:\n name: nginx\n state: present\n when: ansible_os_family == "Debian"\n \n - name: Install packages on Windows\n win_feature:\n name: Web-Server\n state: present\n when: ansible_os_family == "Windows"\n \n - name: Install packages on macOS\n homebrew:\n name: nginx\n state: present\n when: ansible_os_family == "Darwin"\n跨平台应用部署\n使用 Ansible 实现跨平台应用的自动化部署,确保各平台的一致性。\n- name: Deploy application across platforms\n hosts: all\n become: yes\n tasks:\n - name: Deploy app on Linux\n command: /usr/local/bin/deploy_app.sh\n when: ansible_os_family == "Debian"\n \n - name: Deploy app on Windows\n win_command: C:\\Deploy\\deploy_app.bat\n when: ansible_os_family == "Windows"\n \n - name: Deploy app on macOS\n command: /usr/local/bin/deploy_app.sh\n when: ansible_os_family == "Darwin"\nAnsible 实践案例\n常见使用案例\n系统用户和组管理\n创建用户和组设置权限和密码。\n- name: Create a new user\n hosts: all\n become: yes\n tasks:\n - name: Add a user\n user:\n name: john\n state: present\n password: "{{ 'password' | password_hash('sha512') }}"\n软件安装和更新\n使用包管理器安装和更新软件包。\n- name: Install and update software packages\n hosts: all\n become: yes\n tasks:\n - name: Install nginx\n apt:\n name: nginx\n state: present\n - name: Update all packages\n apt:\n upgrade: dist\n服务管理\n启动、停止和重启服务。\n- name: Manage services\n hosts: all\n become: yes\n tasks:\n - name: Ensure nginx is running\n service:\n name: nginx\n state: started\n文件和目录管理\n创建、删除文件和目录设置权限和所有者。\n- name: Manage files and directories\n hosts: all\n become: yes\n tasks:\n - name: Create a directory\n file:\n path: /etc/myapp\n state: directory\n - name: Copy a configuration file\n copy:\n src: files/myapp.conf\n dest: /etc/myapp/myapp.conf\n owner: root\n group: root\n mode: '0644'\n网络配置\n配置网络接口和防火墙规则。\n- name: Configure network interfaces\n hosts: all\n become: yes\n tasks:\n - name: Configure eth0\n network:\n name: eth0\n state: up\n address: 192.168.1.100\n netmask: 255.255.255.0\n gateway: 192.168.1.1\n真实场景的 Playbook 编写\nLAMP 堆栈部署\n安装 Apache、MySQL 和 PHP配置虚拟主机和数据库。\n- name: Deploy LAMP stack\n hosts: webservers\n become: yes\n tasks:\n - name: Install Apache\n apt:\n name: apache2\n state: present\n \n - name: Install MySQL\n apt:\n name: mysql-server\n state: present\n \n - name: Install PHP\n apt:\n name: php\n state: present\n \n - name: Configure Apache virtual host\n template:\n src: templates/vhost.conf.j2\n dest: /etc/apache2/sites-available/000-default.conf\n notify:\n - restart apache\n \n handlers:\n - name: restart apache\n service:\n name: apache2\n state: restarted\nDocker 容器管理\n安装 Docker启动容器部署应用。\n- name: Manage Docker containers\n hosts: all\n become: yes\n tasks:\n - name: Install Docker\n apt:\n name: docker.io\n state: present\n \n - name: Ensure Docker is running\n service:\n name: docker\n state: started\n \n - name: Run a web application container\n docker_container:\n name: mywebapp\n image: nginx\n state: started\n ports:\n - "80:80"\n故障排除与调试技巧\n使用 -vvv 选项\n提供详细的输出信息帮助定位问题。\nansible-playbook -i inventory myplaybook.yml -vvv\n调试模块\n使用 debug 模块输出变量信息。\n- name: Debug variables\n hosts: all\n tasks:\n - name: Show variable value\n debug:\n var: my_variable\n条件执行\n使用 when 条件语句,避免在不满足条件时执行任务。\n- name: Conditional execution\n hosts: all\n tasks:\n - name: Only run when condition is met\n command: /usr/bin/somecommand\n when: ansible_os_family == "Debian"\n查看日志文件\n查看 Ansible 生成的日志文件,分析错误信息。\ntail -f /var/log/ansible.log\nAnsible 性能优化\n大规模部署的性能优化\n并行执行\n增加并行任务的数量默认值为 5可以通过 forks 参数调整。\nansible-playbook -i inventory myplaybook.yml -f 10\nSSH 连接复用\n启用 SSH 连接复用,提高效率。\n[ssh_connection]\nssh_args = -o ControlMaster=auto -o ControlPersist=60s\n使用缓存\n使用事实缓存减少收集远程主机信息的时间。\n[defaults]\nfact_caching = jsonfile\nfact_caching_connection = /tmp/ansible_cache\n高效编写 Playbooks 的技巧\n避免重复\n使用角色和 include 机制,避免重复代码。\n- name: Include common tasks\n import_tasks: common.yml\n变量和模板\n使用变量和模板简化配置文件。\n- name: Use variables in tasks\n hosts: all\n vars:\n my_var: "value"\n tasks:\n - name: Print variable\n debug:\n msg: "The value is {{ my_var }}"\n条件和循环\n使用条件和循环减少代码冗余。\n- name: Install multiple packages\n hosts: all\n become: yes\n tasks:\n - name: Install packages\n apt:\n name: "{{ item }}"\n state: present\n loop:\n - nginx\n - mysql-server\n - php\n常见性能问题及解决方案\nSSH 连接瓶颈\n使用 pipelining 提升 SSH 连接速度。\n[ssh_connection]\npipelining = True\n冗余任务执行\n\t使用 check_mode 检查任务是否需要执行,避免不必要的任务执行。\n- name: Check mode example\n hosts: all\n tasks:\n - name: Ensure nginx is installed\n apt:\n name: nginx\n state: present\n check_mode: yes\n过多事实收集\n禁用不必要的事实收集提高效率。\n- name: Disable fact gathering\n hosts: all\n gather_facts: no\n tasks:\n - name: Ensure nginx is installed\n apt:\n name: nginx\n state: present\nAnsible 集成\nJenkins\n\n\n安装 Jenkins 插件\n安装 Ansible 插件和 SSH 插件,以便 Jenkins 可以运行 Ansible 任务。\n\n\n配置 Jenkins 作业\n创建一个 Jenkins 作业,配置源代码管理、构建触发器等。\n\n\n在 Jenkins 中运行 Playbook\n在 Jenkins 作业中添加构建步骤,运行 Ansible Playbook。\n\n\n ansible-playbook -i inventory myplaybook.yml\nNagios\n使用 Ansible 安装和配置 Nagios部署监控插件。\n - name: Install Nagios\n hosts: all\n become: yes\n tasks:\n - name: Install Nagios packages\n apt:\n name: nagios3\n state: present\n - name: Configure Nagios\n template:\n src: templates/nagios.cfg.j2\n dest: /etc/nagios3/nagios.cfg\n notify:\n - restart nagios\n \n handlers:\n - name: restart nagios\n service:\n name: nagios3\n state: restarted\nPrometheus\n使用 Ansible 部署 Prometheus 和 Node Exporter收集和监控指标。\n - name: Install Prometheus\n hosts: all\n become: yes\n tasks:\n - name: Download Prometheus\n get_url:\n url: github.com/prometheus/prometheus/releases/download/v2.26.0/prometheus-2.26.0.linux-amd64.tar.gz\n dest: /tmp/prometheus.tar.gz\n \n - name: Extract Prometheus\n unarchive:\n src: /tmp/prometheus.tar.gz\n dest: /opt/\n remote_src: yes\n \n - name: Configure Prometheus\n template:\n src: templates/prometheus.yml.j2\n dest: /opt/prometheus-2.26.0.linux-amd64/prometheus.yml\n \n - name: Create systemd service\n template:\n src: templates/prometheus.service.j2\n dest: /etc/systemd/system/prometheus.service\n notify:\n - reload systemd\n - start prometheus\n \n handlers:\n - name: reload systemd\n command: systemctl daemon-reload\n - name: start prometheus\n service:\n name: prometheus\n state: started\n通过以上系统全面的内容您可以更好地理解和掌握 Ansible 的使用,从而实现自动化部署和管理,提高工作效率。"},"Technology/OperatingSystem/Automation/Cloud-init-快速部署":{"title":"Cloud-init","links":[],"tags":["技术/操作系统","自动化/Linux","Linux/安装"],"content":"Cloud-init\n概述\nCloud-init 是一个用于在云计算环境中自动化配置虚拟机实例的工具。它能够在实例启动时根据用户提供的配置脚本或元数据进行初始化和配置使得实例能够快速、统一地完成设置过程。Cloud-init 被广泛用于各种云平台,如 AWS、Azure、Google Cloud、OpenStack 等。\n历史与发展\nCloud-init 最早由 Canonical 公司开发,最初用于 Ubuntu 服务器的自动化配置。随着时间的推移Cloud-init 的功能不断扩展,逐渐支持更多的操作系统和云平台。现在,它已经成为云计算环境中不可或缺的配置工具,拥有一个活跃的开源社区,持续推动其发展和改进。\n为什么选择 Cloud-init\n\n自动化配置Cloud-init 可以自动执行实例初始化和配置,减少手动干预,提升效率。\n跨平台支持Cloud-init 支持多种云平台和操作系统,具有广泛的适用性。\n模块化设计通过模块化架构用户可以根据需求选择和定制功能。\n开源和社区支持Cloud-init 是开源软件,拥有活跃的社区和丰富的文档支持。\n\n主要特性\n\n**无代理设计:**Cloud-init 采用无代理设计,不需要在实例中运行长期驻留的代理进程。这种设计简化了系统架构,减少了资源占用和潜在的安全风险。\n**基于云元数据的初始化:**Cloud-init 利用云服务提供的元数据服务在实例启动时获取必要的配置信息。元数据通常包含实例的网络配置、用户数据脚本、公钥等Cloud-init 通过读取这些元数据进行相应的配置操作。\n**支持多种云平台:**Cloud-init 支持广泛的云平台包括但不限于Amazon Web Services (AWS)、Microsoft Azure、Google Cloud Platform (GCP)、OpenStack、Oracle Cloud Infrastructure (OCI)、DigitalOcean。\n\n主要优势\n\n无代理设计无需安装和维护长期驻留的代理进程减少系统资源占用和维护开销。\n快速初始化在实例启动时立即执行配置适用于快速部署环境。\n多平台支持支持多种云服务提供商和操作系统灵活适用。\n易于使用使用 YAML 格式配置文件,简洁易读,方便编写和维护。\n\n潜在劣势\n\n功能有限主要用于初始配置不适合复杂的持续配置管理和任务编排。\n单次执行通常在实例启动时执行一次不适合需要频繁更新配置的场景。\n依赖云平台依赖于云服务提供商提供的元数据服务在非云环境中使用受限。\n\n模块化架构\ngraph TD\n A[cloud-init]\n B1[Cloud Config]\n B2[Cloud Boot]\n B3[Cloud Init]\n B4[Cloud Final]\n C1[Data Sources]\n C2[Handlers]\n C3[Modules]\n C4[Cloud-Init Config]\n D1[Read Metadata]\n D2[Write Files]\n D3[Install Packages]\n D4[Run Commands]\n\n A --> B1\n A --> B2\n A --> B3\n A --> B4\n B1 --> C1\n B1 --> C2\n B1 --> C3\n B1 --> C4\n B2 --> D1\n B2 --> D2\n B3 --> D3\n B4 --> D4\n\nCloud-init 采用模块化架构,每个功能模块负责特定的配置任务。例如,网络配置模块、用户数据处理模块、包管理模块等。用户可以根据需求启用或禁用特定模块,并且可以编写自定义模块以满足特殊需求。\n应用场景\n云实例初始化\n**Cloud-init 最常见的应用场景是云实例的初始化。**在实例启动时Cloud-init 自动获取并应用配置完成系统设置、网络配置、用户账户创建、SSH 密钥安装等任务,使实例能够快速投入使用。\n配置管理\nCloud-init 可以用作配置管理工具执行复杂的系统配置任务。例如安装和配置软件包、设置系统参数、管理用户权限等。通过用户数据脚本用户可以定义详细的配置步骤Cloud-init 在实例启动时自动执行这些步骤。\n应用部署\nCloud-init 还可以用于自动化应用部署。用户可以在用户数据脚本中包含应用安装和配置指令Cloud-init 在实例启动时执行这些指令,完成应用的自动化部署。这种方式适用于 DevOps 流程,能够加速应用的交付和更新。\nCloud-init 安装与配置\n系统要求\nCloud-init 支持多种操作系统包括但不限于Ubuntu、CentOS、Fedora、Red Hat Enterprise Linux (RHEL)、Debian、SUSE Linux Enterprise Server (SLES)、Oracle Linux、FreeBSD。\n这些操作系统在不同的云平台上广泛使用使得 Cloud-init 能够在多种环境中提供一致的自动化配置功能。\n必要的依赖项\n在安装 Cloud-init 之前,确保系统满足以下基本依赖项:\n\n**Python**Cloud-init 主要用 Python 编写,因此需要系统中预装有 Python通常是 Python 3。\n**网络工具:**如 curl 或 wget用于从数据源获取元数据。\n**包管理工具:**如 apt、yum 或 zypper用于安装 Cloud-init 和相关依赖包。\n\n安装步骤\n通过包管理器安装\n在大多数 Linux 发行版中Cloud-init 都可以通过包管理器安装。根据具体的操作系统选择合适的包管理工具:\n\n\nDebian/Ubuntu 系列:\nsudo apt-get install cloud-init\n\n\nRHEL/CentOS 系列:\nsudo yum install cloud-init\n\n\nSUSE 系列:\nsudo zypper install cloud-init\n\n\n从源代码安装\n\n\n克隆 Cloud-init 源代码仓库:\ngit clone github.com/canonical/cloud-init.git\n\n\n切换到源码目录\ncd cloud-init\n\n\n安装必要的依赖\nsudo apt-get install python3 python3-pip\n\n\n安装 Cloud-init\nsudo python3 setup.py install\n\n\nCloud-init 自动化管理基础\nCloud-init 语法\nCloud-init 配置文件由多个配置段组成,每个配置段负责特定的初始化任务。常见的配置段包括用户定义、网络配置、包管理等。\n配置示例\n以下是一个 Cloud-init 配置文件的示例结构:\n#cloud-config\n \n# 1. 定义用户和其相关配置\n# 配置了一个名为 `ubuntu` 的用户,并设置了 SSH 公钥、sudo 权限和 shell。\nusers:\n - name: ubuntu\n sudo: ['ALL=(ALL) NOPASSWD:ALL']\n groups: sudo\n ssh-authorized-keys:\n - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAr... # 用户的 SSH 公钥\n shell: /bin/bash\n \n# 2. 配置网络设置\n# 启用了 DHCP 以自动获取 IP 地址。\nnetwork:\n version: 2\n ethernets:\n eth0:\n dhcp4: true\n \n# 3. 配置系统包更新和升级选项\n# 启用了系统包更新和升级。\npackage_update: true\npackage_upgrade: true\n \n# 4. 配置 apt 包管理器的相关选项\napt:\n sources:\n my_ppa:\n source: "ppa:my/ppa"\n preserve_sources_list: false\n \n# 5. 配置 snap 包管理器的相关选项\nsnappy:\n snaps:\n - name: core\n channel: stable\n - name: docker\n channel: stable\n \n# 6. 创建或修改两个文件\nwrite_files:\n - path: /etc/myconfig.conf\n content: |\n This is my config file\n - path: /etc/motd\n content: |\n Welcome to my custom server!\n \n# 7. 在实例引导过程中运行命令\nbootcmd:\n - echo 'Booting...'\n - mkdir -p /etc/mydir\n \n# 8. 在实例初始化过程中运行自定义命令\nruncmd:\n - echo 'Hello, world!'\n - [ cloud-init, status, --wait ]\n \n# 9. 配置系统的语言环境locale\nlocale: en_US.UTF-8\n \n# 10. 配置系统时区\ntimezone: America/New_York\n \n# 11. 配置 NTP网络时间协议服务\nntp:\n servers:\n - ntp.ubuntu.com\n - ntp.ubuntu.net\n \n# 12. 配置用户的 SSH 公钥,用于无密码登录\nssh_authorized_keys:\n - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAr...\n \n# 13. 配置根文件系统自动扩展\nresize_rootfs: true\n \n# 14. 配置在 Cloud-init 最终阶段运行的模块\ncloud_final_modules:\n - [scripts-user]\n - [phone-home, service]\n \n# 15. 配置实例初始化完成后发送通知\nphone_home:\n url: example.com/phone_home\n post:\n - instance_id\n - hostname\nCloud-init 模块\n常用模块\nCloud-init 通过模块化设计,将不同的初始化任务分配给不同的模块。以下是一些常用的 Cloud-init 模块:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模块描述运行阶段权重bootcmd在系统引导过程中运行命令早于其他 Cloud-init 配置执行。boot 阶段1growpart扩展分区大小。init 阶段2resize_rootfs配置根文件系统自动扩展。init 阶段3set_hostname设置实例的主机名。init 阶段4write_files创建或修改文件。init 阶段5users定义用户和其相关配置如用户名、SSH 密钥等。init 阶段6locale配置系统的语言环境locale。init 阶段7timezone配置系统时区。init 阶段8ntp配置 NTP网络时间协议服务。init 阶段9apt配置 apt 包管理器的相关选项。init 阶段10yum配置 yum 包管理器的相关选项。init 阶段11snappy配置 snap 包管理器的相关选项。init 阶段12ssh_authorized_keys配置用户的 SSH 公钥用于无密码登录。init 阶段13package_update配置系统包更新选项。init 阶段14package_upgrade配置系统包升级选项。init 阶段15apt-configure配置 apt 包管理器。init 阶段16ssh配置 SSH 相关设置,如主机密钥和 SSH 服务的相关配置。init 阶段17disable-ec2-metadata禁用 EC2 元数据服务。init 阶段18grub-dpkg配置 GRUB 引导加载程序。init 阶段19rsyslog配置 rsyslog 服务。init 阶段20snap配置 Snap 包管理器。init 阶段21mounts配置文件系统的挂载点。init 阶段22runcmd在实例初始化过程中运行自定义命令。final 阶段23phone_home配置实例初始化完成后发送通知。final 阶段24cloud_final_modules配置在 Cloud-init 最终阶段运行的模块。final 阶段25\n分阶段执行\n当 Cloud-init 运行时,它会在三个主要阶段中按顺序执行配置文件中的模块:\n\n网络阶段 (cloud_init_modules)\n\n处理网络相关的配置。\n设置主机名、获取用户数据和元数据。\n\n\n配置阶段 (cloud_config_modules)\n\n配置用户账户和权限。\n安装和配置软件包。\n处理 SSH 密钥和认证设置。\n\n\n最终阶段 (cloud_final_modules)\n\n执行用户定义的脚本和命令。\n触发配置管理插件。\n记录配置状态和信息。\n\n\n\n模块执行频率\nCloud-init 的模块可以配置不同的执行频率:\n\nPer instance模块在实例的首次引导时运行。例如克隆一个实例或从保存的镜像创建新实例时指定为 per instance 的模块会再次运行。\nPer once模块只运行一次。例如如果克隆实例或从保存的镜像创建新实例指定为 per once 的模块不会在这些实例上再次运行。\nPer always模块在每次引导时都运行。\n\n自定义模块开发\n用户可以根据需求编写自定义模块以扩展 Cloud-init 的功能。自定义模块需遵循 Cloud-init 的模块开发规范,并放置在合适的目录中(如 /etc/cloud/cloud.cfg.d/)。以下是一个简单的自定义模块示例:\n# custom_module.py\nimport os\nfrom cloudinit import util\n \ndef handle(name, cfg, cloud, log, args):\n log.info("Running custom module")\n util.write_file('/var/log/custom_module.log', 'Custom module executed')\n将自定义模块集成到 Cloud-init 配置中:\ncloud_final_modules:\n - custom_module\nCloud-init 数据源\nCloud-init 通过数据源获取实例的元数据和用户数据。一般 Cloud-init 使用用户数据、元数据和厂商数据来完成实例初始化:\n\n用户数据用户在 cloud.cfg 文件和 cloud.cfg.d 目录中指定的指令,如要运行的脚本、要安装的软件包等。\n元数据与特定数据源关联的数据如服务器名称和实例 ID。不同的云平台决定实例从哪里查找元数据和用户数据。\n厂商数据由云提供商提供包含用于自定义镜像的信息。\n\n**Cloud-init 的主要配置文件是 /etc/cloud/cloud.cfg。**该文件定义了 Cloud-init 在实例启动时执行的全局配置和行为。拓展数据源的文件通常位于 /etc/cloud/cloud.cfg.d/ 目录下。\n数据源类型\n数据源类型决定了 Cloud-init 如何获取和处理这些数据。常见的数据源类型包括:\n\nNoCloud用于本地测试和开发数据存储在 ISO 镜像或本地文件中。\nEC2用于 Amazon Web Services (AWS)。\nAzure用于 Microsoft Azure。\nGCE用于 Google Cloud Platform。\nOpenStack用于 OpenStack 环境。\n\n常用数据源\n以下是一些常用的数据源配置示例\nNoCloud\ndatasource_list: [ NoCloud ]\ndatasource:\n NoCloud:\n seedfrom: /path/to/nocloud/seed/\nEC2\ndatasource_list: [ Ec2 ]\ndatasource:\n Ec2:\n metadata_urls: [ 'http://169.254.169.254' ]\nGCE\ndatasource_list: [ GCE ]\ndatasource:\n GCE:\n metadata_server: 'metadata.google.internal'\nAzure\ndatasource_list: [ Azure ]\ndatasource:\n Azure:\n retries: 10\n timeout: 5\n数据源优先级和故障处理\nCloud-init 可以配置多个数据源并按照优先级顺序依次尝试。当一个数据源不可用时Cloud-init 会自动尝试下一个数据源。优先级顺序通过 datasource_list 配置项定义:\ndatasource_list: [ NoCloud, Ec2, GCE, Azure ]\n可以通过配置故障处理选项控制 Cloud-init 在数据源不可用时的行为:\ndatasource:\n Ec2:\n max_wait: 120 # 最大等待时间(秒)\n timeout: 5 # 每次请求的超时时间(秒)\n retries: 10 # 重试次数\nCloud-init 的生命周期\nCloud-init 的生命周期分为多个阶段,每个阶段负责特定的初始化和配置任务。理解这些阶段有助于更好地使用和调试 Cloud-init。下面是 Cloud-init 的详细生命周期描述:\nsequenceDiagram\n participant Systemd\n participant CloudInitGenerator\n participant CloudInitLocal\n participant CloudInitNetwork\n participant CloudInitConfig\n participant CloudInitFinal\n\n Systemd ->> CloudInitGenerator: 运行 Cloud-init 生成器\n CloudInitGenerator ->> CloudInitGenerator: 检查配置文件和内核参数\n CloudInitGenerator ->> CloudInitGenerator: 确定数据源\n CloudInitGenerator ->> Systemd: 生成相应的 systemd 单元文件\n\n Systemd ->> CloudInitLocal: 启动 Cloud-init 本地阶段\n CloudInitLocal ->> CloudInitLocal: 识别本地数据源并应用初始网络配置\n CloudInitLocal ->> CloudInitLocal: 读取并处理本地存储的元数据\n CloudInitLocal ->> CloudInitLocal: 设置主机名和其他基础配置\n\n Systemd ->> CloudInitNetwork: 启动 Cloud-init 网络阶段\n CloudInitNetwork ->> CloudInitNetwork: 获取完整的用户数据和元数据\n CloudInitNetwork ->> CloudInitNetwork: 运行 cloud_init_modules 列出的模块\n CloudInitNetwork ->> CloudInitNetwork: 处理和执行用户提供的配置脚本\n\n Systemd ->> CloudInitConfig: 启动 Cloud-init 配置阶段\n CloudInitConfig ->> CloudInitConfig: 运行 cloud_config_modules 列出的模块\n CloudInitConfig ->> CloudInitConfig: 配置用户账户、安装和配置软件包\n\n Systemd ->> CloudInitFinal: 启动 Cloud-init 最后阶段\n CloudInitFinal ->> CloudInitFinal: 运行 cloud_final_modules 列出的模块\n CloudInitFinal ->> CloudInitFinal: 执行用户定义的脚本和命令\n CloudInitFinal ->> CloudInitFinal: 记录最终的配置状态和信息\n\n1. 生成器阶段 (Generator Stage)\n在系统引导过程中systemd 会运行 Cloud-init 生成器generator。生成器的主要任务是确定是否在当前引导中启用 Cloud-init 以及选择适当的数据源。生成器阶段包括以下任务:\n\n检查配置文件和内核参数决定是否启用 Cloud-init。\n确定使用哪个数据源例如 EC2、Azure、NoCloud 等)。\n生成相应的 systemd 单元文件,以便在后续阶段运行 Cloud-init 服务。\n\n2. 本地阶段 (Local Stage)\n本地阶段是 Cloud-init 的第一个主要执行阶段发生在实例启动的早期阶段。在本地阶段Cloud-init 会执行以下操作:\n\n识别本地数据源并应用初始网络配置。\n读取并处理本地存储的元数据。\n处理基本的网络配置如静态 IP 设置或 DHCP 回退机制。\n设置实例的主机名和其他基础配置。\n\n本地阶段的主要目的是确保实例在能够访问外部网络之前完成基本的配置。\n3. 网络阶段 (Network Stage)\n网络阶段是 Cloud-init 的第二个主要执行阶段依赖于实例已经有了基础网络连接。在这一阶段Cloud-init 会执行以下任务:\n\n通过网络访问数据源获取完整的用户数据和元数据。\n运行 /etc/cloud/cloud.cfg 文件中 cloud_init_modules 部分列出的模块。\n处理和执行用户提供的配置脚本和指令。\n\n这一阶段确保实例能够通过网络访问必要的资源并完成初步的配置任务。\n4. 配置阶段 (Config Stage)\n配置阶段是 Cloud-init 的第三个主要执行阶段负责更详细的系统配置。在这一阶段Cloud-init 会执行以下操作:\n\n运行 /etc/cloud/cloud.cfg 文件中 cloud_config_modules 部分列出的模块。\n配置用户账户和权限、安装和配置软件包、设置系统参数等。\n\n配置阶段处理实例的核心配置任务确保系统按预期进行初始化和设置。\n5. 最后阶段 (Final Stage)\n最后阶段是 Cloud-init 的最后一个主要执行阶段负责执行所有剩余的配置任务和用户定义的脚本。在这一阶段Cloud-init 会执行以下操作:\n\n运行 /etc/cloud/cloud.cfg 文件中 cloud_final_modules 部分列出的模块。\n执行用户定义的脚本和命令如软件包安装、服务启动等。\n记录最终的配置状态和信息。\n\n最后阶段确保所有配置任务完成并记录实例的最终状态。\nCloud-init 高级应用技巧\nCloud-init 用户数据\n用户数据格式和用法\nCloud-init 用户数据用于在实例启动时传递自定义的配置和脚本。用户数据支持多种格式:\n\nCloud ConfigYAML 格式):使用 #cloud-config 作为头标识。\nShell 脚本:使用 #! 或 #cloud-boothook 作为头标识。\nMIME 多部分消息:支持混合多种类型的数据。\n\n示例\n#cloud-config\nusers:\n - name: example-user\n ssh-authorized-keys:\n - ssh-rsa AAAAB3Nza...\n \n \n#!/bin/bash\necho "Hello, World!" > /var/log/hello.log\n \nContent-Type: multipart/mixed; boundary="===============BOUNDARY=="\n \nMIME-Version: 1.0\n \n--===============BOUNDARY==\nContent-Type: text/cloud-config\n \n \n#cloud-config\nusers:\n - name: example-user\n ssh-authorized-keys:\n - ssh-rsa AAAAB3Nza...\n \n--===============BOUNDARY==\nContent-Type: text/x-shellscript\n \n \n#!/bin/bash\necho "Hello, World!" > /var/log/hello.log\n \n--===============BOUNDARY==--\n脚本和配置的集成\n用户数据可以包含多个脚本和配置指令Cloud-init 会按照定义的顺序依次执行。例如,可以先配置用户,然后运行一个脚本来安装软件:\n#cloud-config\nusers:\n - name: example-user\n ssh-authorized-keys:\n - ssh-rsa AAAAB3Nza...\n \nruncmd:\n - apt-get update\n - apt-get install -y nginx\n用户数据的传递和解析\n用户数据可以通过多种方式传递到实例中\n\nCloud Provider 控制台:通过云服务提供商的控制台界面输入用户数据。\nAPI 调用:使用云服务提供商的 API 传递用户数据。\n配置文件在本地环境中通过配置文件传递用户数据。\n\nCloud-init 会在实例启动时解析这些数据,并根据配置执行相应的任务。\n调试和日志\nCloud-init 在实例启动时会生成日志,记录执行的每个步骤。这些日志通常保存在 /var/log/cloud-init.log 和 /var/log/cloud-init-output.log 文件中。通过检查这些日志,可以调试和验证用户数据是否正确执行。\nCloud-init 与其他工具的比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度Cloud-initAnsiblePuppet架构无代理实例初始化无代理远程执行代理 - 服务器,持续管理设计理念云实例启动时配置配置管理和应用部署声明式,持续配置使用场景云实例首次配置持续配置管理,多节点大规模持续管理主要优势轻量,快速配置,多平台支持强大编排,灵活管理自动纠正,模块丰富主要劣势功能有限,单次执行,依赖云平台需维护控制节点,执行慢需安装代理,学习曲线陡适用场景初始配置,快速部署,统一环境动态配置,多节点管理持续监控,大规模部署不适用场景复杂多节点,持续监控快速初始配置轻量初始配置\nCloud-init 在实际环境中的应用\nCloud-init 在云环境中的应用\n在 AWS 中的使用\n在 AWS 中Cloud-init 通过 EC2 实例元数据服务获取用户数据和元数据进行初始化配置。以下是一个示例:\n\n\n创建一个 EC2 实例时,在“高级详细信息”部分提供用户数据。\n\n\n例如用户数据可以是一个简单的 Shell 脚本或 Cloud-config 配置:\n#!/bin/bash\necho "Hello from EC2" > /var/log/cloud-init.log\n或者\n#cloud-config\npackages:\n - nginx\nruncmd:\n - service nginx start\n\n\n启动实例后Cloud-init 会在首次启动时自动执行这些配置。\n\n\n在 Azure 中的使用\n在 Azure 中Cloud-init 支持通过 Azure 元数据服务进行初始化配置。\n\n\n创建虚拟机时选择“云初始化”选项来提供用户数据。\n\n\n例如一个简单的 Cloud-config 文件:\n#cloud-config\nusers:\n - default\npackages:\n - apache2\nruncmd:\n - systemctl start apache2\n\n\n启动虚拟机后Cloud-init 将读取用户数据并执行相应配置。\n\n\n在 Google Cloud 中的使用\n在 Google Cloud 中Cloud-init 支持通过 GCE 元数据服务进行实例初始化配置。\n\n\n创建 VM 实例时,在“管理、安全性、磁盘、网络、单租户”部分提供启动脚本。\n\n\n例如一个简单的启动脚本\n#!/bin/bash\necho "Hello from GCE" > /var/log/cloud-init.log\n或者\n#cloud-config\npackages:\n - mysql-server\nruncmd:\n - systemctl start mysql\n\n\n启动实例后Cloud-init 会读取用户数据并执行配置。\n\n\nCloud-init 在容器化环境中的应用\n容器实例初始化\nCloud-init 主要用于虚拟机实例的初始化,而在容器化环境中,初始化和配置任务通常由容器编排工具(如 Kubernetes和容器镜像自身完成。不过在一些场景下Cloud-init 也可以用于初始化容器主机环境。\n与 Docker 的集成\n虽然 Cloud-init 本身不直接用于 Docker 容器的管理,但它可以用于配置运行 Docker 容器的主机。例如,配置主机环境并安装 Docker\n#cloud-config\npackages:\n - docker.io\nruncmd:\n - systemctl start docker\n - docker run hello-world\n与 Kubernetes 的集成\nCloud-init 可以用于配置 Kubernetes 集群的节点,在节点启动时自动完成必要的配置和初始化步骤:\n\n\n安装 Kubernetes 必要的软件包:\n#cloud-config\npackages:\n - kubeadm\n - kubelet\n - kubectl\nruncmd:\n - kubeadm join --token <token> <master-ip>:<port>\n\n\n启动节点后Cloud-init 会自动加入节点到 Kubernetes 集群。\n\n\nCloud-init 在传统 IT 环境中的应用\n虚拟机初始化\n在传统的虚拟化环境中如 VMware、KVMCloud-init 也可以用于虚拟机的初始化和配置。通过本地数据源NoCloud来提供用户数据和元数据\n#cloud-config\nusers:\n - name: admin\n ssh-authorized-keys:\n - ssh-rsa AAAAB3Nza...\n本地部署配置\n在本地数据中心环境中Cloud-init 可以用于统一配置管理和自动化部署。例如,通过本地镜像或 ISO 文件传递配置数据,实现自动化初始化:\n#cloud-config\npackages:\n - nginx\nruncmd:\n - systemctl start nginx\n跨平台管理\nCloud-init 的跨平台支持使得它可以用于多种操作系统和环境中的一致性管理。在不同的平台上使用相同的 Cloud-config 文件,实现统一的配置和管理:\n#cloud-config\nusers:\n - name: user\n ssh-authorized-keys:\n - ssh-rsa AAAAB3Nza...\npackages:\n - git\nruncmd:\n - git clone github.com/example/repo.git /opt/repo"},"Technology/OperatingSystem/Automation/PXE--系统部署":{"title":"PXE 自动化部署","links":[],"tags":["Linux/安装","技术/操作系统","自动化/Linux"],"content":"PXE 技术概述\nPXEPreboot Execution Environment是一种网络引导技术允许计算机在启动 BIOS/UEFI 后通过网络接口从远程服务器下载操作系统或其他软件进行启动。这项技术主要应用于无人值守的自动化部署场景包括系统部署、更新、维护和灾难恢复。与传统的物理介质启动相比PXE 提供了更大的灵活性和可管理性,特别适合需要快速部署和更新大量系统的企业和机构。\n主要应用场景\n\n系统自动化部署实现无人值守的操作系统和应用程序批量部署。\n故障恢复通过网络快速恢复故障系统。\n远程维护支持远程诊断和修复问题。\n固件更新批量更新设备固件。\n\nPXE 工作原理\n启动流程详解\nsequenceDiagram\n participant Client as PXE客户端\n participant DHCPServer as DHCP服务器\n participant TFTPServer as TFTP服务器\n participant BootServer as 引导服务器\n\n Client->>DHCPServer: 请求IP地址和引导服务器信息\n DHCPServer->>Client: 分配IP地址和引导服务器地址\n Client->>TFTPServer: 请求引导镜像文件\n TFTPServer->>Client: 传输引导镜像文件\n Client->>BootServer: 加载引导菜单并请求启动操作系统\n BootServer-->>Client: 根据选择传输操作系统启动文件\n Client->>BootServer: 启动操作系统或应用程序\n\nPXE 启动流程可以分为以下几个阶段:\n\nPOST 自检: 计算机启动时会进行开机自检POST。\n获取 DHCP 信息: 自检完成后PXE 客户机会向 DHCP 服务器发送请求,获取 IP 地址、引导服务器地址等信息。\n下载引导镜像: 客户机从 TFTP 服务器下载引导镜像,如 pxelinux.0。\n加载引导菜单: 引导镜像加载后,会显示引导菜单,允许用户选择要启动的操作系统或应用程序。\n启动操作系统: 根据用户选择,启动相应的操作系统或应用程序。\n\n涉及的关键网络协议\nPXE 工作过程中涉及以下几个关键网络协议:\n\nDHCP: 动态主机配置协议,用于为 PXE 客户机分配 IP 地址和引导服务器地址。\nTFTP: Trivial File Transfer Protocol用于传输引导镜像和其他文件。\nHTTP/HTTPS在 UEFI 模式下,相比 TFTP 提供更快的文件传输速度和加密支持。\nBPD: Boot Protocol Discovery用于引导服务器发现 PXE 客户机。\n\nPXE 技术的关键组件\nPXE 部署涉及的核心组件包括 DHCP 服务器、TFTP/HTTP 服务器和 PXE 引导程序。这些组件协同工作,实现了从网络启动计算机并自动加载操作系统的功能。\nDHCP 服务器\nDHCP 服务器负责在网络启动过程中为客户端分配 IP 地址,并提供引导服务器(如 TFTP 或 HTTP 服务器)的位置和启动文件名。这是实现 PXE 环境的基础。\nTFTP/HTTP 服务器\n\nTFTP 服务器用于存储和传输引导文件(如 pxelinux.0 或 grubx64.efi和操作系统映像。尽管 TFTP 是传统选择,但它的传输速度相对较慢。\nHTTP/HTTPS 服务器提供了一种更快、更安全的替代方案,尤其是在 UEFI 启动模式下。HTTPS 还可以加密数据传输,保护部署过程中的数据安全。\n\nPXE 引导程序\nPXE 引导程序如 SYSLINUX 或 GRUB负责显示启动菜单允许用户选择不同的操作系统或工具进行加载。它们支持从 TFTP 或 HTTP 服务器加载操作系统映像。\n无人值守安装\n无人值守安装允许自动执行操作系统安装无需人工干预。这通过使用预先定义的安装脚本或应答文件来实现可以大幅提升大规模部署的效率和一致性。\n实现步骤\n\n准备操作系统映像将操作系统安装文件存放于 TFTP 或 HTTP 服务器。\n创建应答文件例如 Kickstart用于 Red Hat/CentOS或 Preseed用于 Debian/Ubuntu定义安装过程中的所有选择如分区、网络配置、用户账号和安装的软件包。\n配置 PXE 引导程序:设置启动菜单以引导到特定的安装环境,并指定应答文件。\n\n自动化脚本和工具\n使用如 Ansible、Puppet 的自动化运维工具进一步自动化和优化部署流程,可以在无人值守安装基础上实现后续的配置管理和应用部署。\nPXE 环境搭建\n搭建 PXE 环境需要配置服务器端(包括 DHCP、TFTP/HTTP 服务器和引导文件和客户端BIOS/UEFI 设置)。\n服务器端要求\n\n操作系统Linux 发行版,如 CentOS 或 Ubuntu。\n软件组件\n\nDHCP 服务器(如 ISC DHCP Server\nTFTP 服务器(如 tftp-hpa或 HTTP 服务器(如 Apache 或 Nginx\nPXE 引导程序(如 SYSLINUX 或 GRUB\n\n\n网络配置静态 IP 地址,确保服务器与客户端在同一网络段。\n\n客户端配置要求\n\nBIOS/UEFI 设置:启用网络启动选项,设置网络引导为首选启动设备。\n\nUEFI 支持\n\nUEFI 启动:配置 UEFI 启动模式下的特定引导文件(如 grubx64.efi和 DHCP 选项,以支持更现代的硬件。\n\n网络环境配置与优化\n\n通信检查确保服务器和客户端间网络畅通。\n使用 VLAN 隔离:将 PXE 部署网络与生产网络隔离,增强安全性。\n性能优化在支持的环境下使用 HTTP/HTTPS 替代 TFTP 以提升文件传输速度和安全性。\n\n安全性\n虽然 PXE 提供了极大的便利,但也引入了新的安全风险。以下措施可以帮助提升 PXE 环境的安全性:\n网络隔离和访问控制\n通过 VLAN 或物理隔离手段将 PXE 部署网络与生产网络分离,限制对 PXE 服务器的访问,确保只有授权客户端可以启动和访问部署服务。\n数据加密\n使用 HTTPS 代替 TFTP为数据传输过程提供加密保护敏感信息不被窃取。\n定期更新和补丁应用\n定期更新 PXE 服务器上的软件和操作系统,应用安全补丁,减少安全漏洞。\n强化服务器安全\n为 PXE 服务器配置强密码,实施最小权限原则,使用防火墙和入侵检测系统等安全工具,增加额外的安全层。\nPXE 技术的优势与局限性\nPXEPreboot Execution Environment技术在系统部署和维护方面带来了显著的优势但同时也存在一些局限性。理解这些优点和缺点对于有效地利用 PXE 技术至关重要。\n优势\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n优势描述自动化部署通过无人值守安装极大提高批量部署计算机的效率尤其适合数据中心、测试实验室等需要频繁部署大量系统的环境。集中管理启动镜像和安装脚本可以集中存储在网络服务器上使得更新和管理更加集中和方便。可扩展性支持通过网络启动任意数量的客户端轻松扩展以满足增长的需求无需对每个客户端进行手动配置。安全性提升通过网络安全策略和技术保护部署过程如网络隔离、数据加密减少物理介质丢失或被盗的风险。\n局限性\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n局限性描述网络依赖性完全依赖于网络环境。网络配置错误、服务器不可用或网络故障都可能导致部署失败大规模部署时对网络带宽的需求也相应增加。安全风险错误配置的 PXE 环境可能成为安全漏洞,未经授权的设备可能尝试接入网络,攻击者可能利用环境中的漏洞发起攻击。技术复杂性设置和管理 PXE 环境比传统物理介质安装更复杂,需要专业知识配置和维护 DHCP、TFTP/HTTP 服务器以及安全措施。兼容性问题在不同硬件和操作系统之间可能会遇到兼容性问题,特别是 UEFI 启动模式下可能需要额外的配置支持。\nPXE 技术的应用\n基于 RHEL/Fedora 系的详细配置指南\n1. 安装必要的软件包\nsudo yum install dhcp-server tftp-server syslinux\n2.配置 DHCP 服务器\n\n编辑配置文件 /etc/dhcp/dhcpd.conf添加以下内容\n\nsubnet 192.168.1.0 netmask 255.255.255.0 {\n range 192.168.1.100 192.168.1.200;\n option routers 192.168.1.1;\n option domain-name-servers 8.8.8.8, 8.8.4.4;\n next-server 192.168.1.2;\n filename "pxelinux.0";\n}\n\n启动并启用 DHCP 服务:\n\nsudo systemctl start dhcpd\nsudo systemctl enable dhcpd\n3. 配置 TFTP 服务器\n\n创建 TFTP 根目录:\n\nsudo mkdir -p /var/lib/tftpboot\nsudo chmod -R 777 /var/lib/tftpboot\n\n复制 PXE 引导文件到 TFTP 根目录:\n\nsudo cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot/\n4. 配置 PXE 引导程序\n\n将操作系统安装镜像和相关文件复制到 TFTP 服务器的目录中:\n\nsudo cp /path/to/your/os/* /var/lib/tftpboot/\n\n编辑 /etc/sysconfig/iptables允许 DHCP 和 TFTP 流量:\n\n-A INPUT -p udp --dport 67:68 -j ACCEPT\n-A INPUT -p udp --dport 4011:4012 -j ACCEPT\n\n重启 iptables 服务:\n\nsudo systemctl restart iptables\n5.客户端配置\n\n进入 BIOS 设置,启用网络启动,并设置为第一启动选项。\n\n基于 Debian/Ubuntu 系的详细配置指南"},"Technology/OperatingSystem/Docker/基础/基础概念":{"title":"基础概念","links":[],"tags":["Docker/基础","技术/操作系统"],"content":"Docker 是一个开源的容器化平台,它允许开发者打包应用及其依赖到一个可移植的容器中,然后在任何支持 Docker 的系统上运行这个容器。容器化技术使得应用从环境配置中解脱出来,增强了应用的可移植性、效率和安全性。\nDocker 核心概念\n\n容器Containers容器是 Docker 的核心,可以被理解为一个轻量级、可执行的软件包,包含了运行某个应用所需的全部内容——代码、运行时环境、库、环境变量和配置文件等。你可以把容器想象成一个独立的小型计算机,它在一个隔离的环境中运行应用。\n镜像Images镜像是创建 Docker 容器的模板。镜像是静态的包含了运行应用所需的代码、库、环境变量和配置文件。可以把镜像想象成容器的“蓝图”。创建容器时Docker 会从镜像中读取这些信息。\n仓库Repositories仓库是集中存放镜像的地方。Docker Hub 是最著名的公共仓库,但用户也可以创建私有仓库来存储和管理自己的镜像。\nDockerfileDockerfile 是一个文本文件,包含了一系列的指令和参数,用于自动化构建 Docker 镜像的过程。通过编写 Dockerfile开发者可以定义如何构建镜像包括添加文件、运行命令和配置环境等。\nDocker ComposeDocker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件,你可以配置应用服务所需的所有容器,然后使用一个命令同时创建和启动所有这些容器。\n\nDocker 工作原理\nDocker 使用容器来运行应用,容器运行在 Docker 引擎之上。Docker 引擎负责管理容器的生命周期,包括容器的创建、启动、停止、移动和删除。容器与虚拟机相比,占用的资源更少,启动更快,因为容器共享宿主机的内核,而不需要模拟整个操作系统。\nDocker 设计架构\nDocker 的架构主要基于客户端 - 服务器Client-Server模型涉及几个关键组件Docker 客户端、Docker 服务器也称为守护进程、Docker 镜像、容器、仓库等。\n\nDocker 客户端ClientDocker 客户端是用户与 Docker 交互的主要方式。用户通过运行 Docker 客户端命令来告诉 Docker 守护进程需要做什么。例如,构建镜像、运行容器、停止容器等操作都是通过客户端发起的。\nDocker 服务器守护进程DaemonDocker 守护进程运行在宿主机上,处理客户端发来的请求,如创建、运行、监控容器,构建和存储镜像等。守护进程与其他 Docker 守护进程通信,管理 Docker 服务。\n\nDocker 客户端和守护进程可以在同一系统上运行,也可以将 Docker 客户端连接到远程 Docker 守护进程。 Docker 客户端和守护进程使用 REST API 通过 UNIX 套接字或网络接口进行通信。\n"},"Technology/OperatingSystem/Docker/基础/安装配置":{"title":"安装配置","links":[],"tags":["Docker/基础","技术/操作系统"],"content":"官方手册\n\nGet Dockerdocs.docker.com/get-docker/\n\n安装脚本\n正式版本\ncurl -fsSL get.docker.com -o get-docker.sh\nsh get-docker.sh\n测试版本\ncurl -fsSL test.docker.com -o test-docker.sh\nsh test-docker.sh\n启动测试\n# 默认启动\nsudo systemctl enable docker\nsudo systemctl start docker\n \n# 验证是否正确安装\ndocker run --rm hello-world\n镜像加速\n国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。国内各大云服务商(腾讯云、阿里云、百度云)均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。\n请首先执行以下命令查看是否在 docker.service 文件中配置过镜像地址。\n$ systemctl cat docker | grep '\\-\\-registry\\-mirror'\n\n如果该命令有输出那么请执行 $ systemctl cat docker 查看 ExecStart= 出现的位置,修改对应的文件内容去掉 --registry-mirror 参数及其值,并按接下来的步骤进行配置。\n如果以上命令没有任何输出那么就可以在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):\n{\n "registry-mirrors": [\n "hub-mirror.c.163.com",\n "mirror.baidubce.com"\n ]\n}\n\n注意一定要保证该文件符合 json 规范,否则 Docker 将不能启动。\n\n最后重新启动服务。\nsudo systemctl daemon-reload\n \nsudo systemctl restart docker"},"Technology/OperatingSystem/Docker/基础/简介":{"title":"简介","links":[],"tags":["Docker/基础","技术/操作系统"],"content":"概述\nDocker 是一种开源的容器化技术,它允许开发者将应用及其运行环境打包在一个轻量级、可移植的容器中。这个容器可以在任何支持 Docker 的系统上运行,确保了应用在不同环境之间的一致性。可以把 Docker 容器看作是一个简化版的虚拟机,但与传统的虚拟机相比,它更为轻量和高效,因为容器直接运行在宿主机的操作系统内核上,而不需要额外的操作系统层。\n想象一下如果你是一位厨师Docker 就像是你的食材和调料被一起打包在一个便携式的盒子里。无论你去到哪个厨房(服务器),只要那里有 Docker相当于一个标准的炉子你就能够使用那个盒子里的东西应用和环境来准备你的菜肴运行你的应用。\n我们还可以把 Docker 想象成一种创新的快递服务。它不仅提供了一个标准化的包裹盒(容器),而且还确保了无论包裹被送到哪里(无论是开发、测试还是生产环境),里面的物品(应用和环境)都能够完好无损地到达。\n历史\n\n2013 年Docker 的诞生\nDocker 最初是由 Solomon Hykes 在 dotCloud 公司(后来改名为 Docker Inc.)开发的一个内部项目,旨在简化应用的部署过程。它基于 Linux 容器LXC技术并在 2013 年 3 月以开源项目的形式发布。\n2014 年Docker 1.0 发布\nDocker 迅速获得开发者社区的关注和支持。2014 年 6 月Docker 1.0 正式发布,标志着 Docker 成为生产环境准备就绪的技术。\n2015 年Docker Compose 和 Docker Swarm 的推出\n随着 Docker 的普及用户开始寻求更好的工具来管理多个容器。Docker Compose 作为定义和运行多容器 Docker 应用的工具在 2015 年初推出。同年Docker Swarm 也被引入作为 Docker 的原生集群管理工具。\n2016 年Docker 成为 Moby 项目\n2016 年Docker Inc.宣布将 Docker 核心分割为多个独立的组件,核心 Docker 平台被重命名为 Moby Project。这一变化旨在促进社区贡献并提高项目的模块化。\n2017 年Docker 宣布支持 Kubernetes\n随着 Kubernetes 成为容器编排领域的领导者Docker Inc.在 2017 年宣布原生支持 Kubernetes允许用户在 Docker 平台上直接使用 Kubernetes 进行容器编排。\n2019 年Docker 企业业务被 Mirantis 收购\n2019 年 11 月Docker Inc.宣布将其企业业务出售给云计算公司 Mirantis同时 Docker Inc.将专注于发展 Docker Desktop 和 Docker Hub。\n2020 年及以后Docker 的持续发展\n即使在企业业务被出售后Docker 仍然是开发和运行容器化应用最流行的平台之一。Docker 继续推出新版本,增加新特性,并优化用户体验。同时,社区和生态系统也在不断壮大,为 Docker 的未来发展提供了坚实的基础。\nDocker 的发展历史体现了容器技术在软件开发和部署中的革命性变化。从一个小型内部项目到成为全球广泛采用的开源平台Docker 不仅改变了我们构建和部署应用的方式,也促进了 DevOps 文化和微服务架构的发展。\n优势\nDocker 提供了许多优势,包括但不限于:\n\n一致性和可移植性无论开发者的本地机器使用什么操作系统Docker 容器都能确保应用可以在任何支持 Docker 的环境中以相同的方式运行。\n快速部署由于容器不需要启动一个完整的操作系统它们可以在几秒钟内启动和停止这大大加快了部署和扩展应用的速度。\n资源高效容器共享宿主机的核心不需要额外的操作系统负担这使得它们比虚拟机更加资源高效。\n隔离每个容器都在自己的环境中运行与其他容器隔离。这提高了安全性因为它防止了应用之间的干扰。\n\n应用场景\nDocker 可以用于多种场景,包括:\n\n开发环境的一致性确保开发、测试和生产环境完全一致减少了“在我这里运行得好好的”问题。\n微服务架构每个微服务运行在自己的容器中便于管理和扩展。\n持续集成/持续部署CI/CDDocker 容器可以用于自动化测试和生产部署,提高软件交付的速度和质量。\n应用的快速部署和扩展在云平台和虚拟化环境中快速部署和扩展应用。\n\n同类产品对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性/产品DockerKubernetesPodman定义开源容器化平台允许开发者打包、分发和运行应用。开源的容器编排平台用于自动化容器的部署、扩展和管理。开源容器化工具允许开发者构建、运行和管理容器和容器镜像。设计目标简化应用的打包和部署流程。在集群中自动化部署、扩展和操作容器化的应用程序。提供一个与 Docker 兼容的命令行界面,但不依赖于守护进程,更加注重安全性。运行环境单机或 Swarm 模式下的多机环境。集群环境,可以跨多个主机运行容器。单机,支持通过 Podman 或 Kubernetes 进行编排。安全性通过 Docker 守护进程运行需要考虑守护进程的安全性。设计用于多租户场景提供严格的安全策略。不需要守护进程每个容器都是在用户空间中作为独立进程运行提供更高的安全性。使用场景开发、测试和生产环境中的应用容器化和微服务架构。大规模容器管理和自动化部署、管理和扩展容器化应用。适用于希望避免使用守护进程或寻求更高安全性的开发者和系统管理员。社区和生态庞大的社区支持和丰富的容器镜像库。强大的社区支持是云原生计算基金会CNCF的一部分拥有广泛的生态系统。正在快速增长的社区与 Docker 镜像和容器生态系统兼容。主要优势用户友好的界面和命令行工具,广泛的采用和支持。强大的容器编排和管理能力,适合大规模部署。更适合安全敏感的环境,无需守护进程,支持 rootless 运行。"},"Technology/OperatingSystem/Docker/进阶/Docker-Compose":{"title":"Docker Compose","links":[],"tags":["Docker/进阶","技术/操作系统"],"content":"概述\nDocker Compose 是一种工具,用于定义和运行多容器 Docker 应用程序。通过使用 Compose你可以使用 YAML 文件来配置你的应用服务。然后,只需一个简单的命令,就能创建并启动你配置中的所有服务。\nDocker Compose 允许你使用 YAML 文件来定义多个容器的应用服务,包括网络、卷等其他资源。这种方法可以让你将整个应用的配置集中管理,极大地简化了容器管理过程。\n\n简化配置使用 YAML 文件定义服务,使得配置过程更加简单明了。\n一键部署多容器应用可以通过一个命令同时启动无需分别操作每个容器。\n易于维护和扩展服务的更新和扩展可以通过修改配置文件实现易于管理。\n\n安装\nDocker Compose 的安装过程取决于你的操作系统。在大多数情况下,它可以作为 Docker Desktop 的一部分自动安装,或者可以单独安装。\n在 Linux 上安装\ncurl -L "github.com/docker/compose/releases/download/v2.24.6/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose\nsudo chmod +x /usr/local/bin/docker-compose\n基本命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述docker-compose up构建、重新创建、启动和连接到服务的容器。使用 -d 参数以后台模式运行。docker-compose down停止并移除容器、网络、卷和镜像。docker-compose build构建或重新构建服务中定义的镜像。docker-compose logs查看服务的日志输出。docker-compose pull拉取服务依赖的镜像。docker-compose push将服务镜像推送到 Docker Hub 或其他镜像仓库。docker-compose restart重启服务。docker-compose start启动已经存在的服务容器。docker-compose stop停止运行中的容器不移除它们。docker-compose pause暂停服务中的容器。docker-compose unpause恢复服务中已暂停的容器。docker-compose rm删除所有停止状态的服务容器。docker-compose run在一个服务上运行一次性命令。docker-compose exec在服务的容器中执行命令。docker-compose scale设置服务的容器数量。在 3.x 版本中已被 docker-compose up --scale 代替docker-compose config验证并查看 Compose 文件的配置。docker-compose top显示运行中的容器的进程。docker-compose port打印绑定的公开端口。docker-compose ps列出项目中目前的所有容器。docker-compose version显示 Docker Compose 的版本信息。\n如果你想操作特定的一个 Docker Compose 编排,你应该在该编排文件所在的目录下执行相应的 docker-compose 命令,并使用 -f 参数指定你的编排文件(如果不是使用默认的 docker-compose.yml 文件名)。\n管理应用\n让我们通过一个简单的示例来展示如何使用 Docker Compose 管理多容器应用。\n示例应用\n下面创建一个 docker-compose.yml 文件,定义一个简单的 web 应用服务。\napp.py\nfrom flask import Flask\nfrom redis import Redis\n \napp = Flask(__name__)\nredis = Redis(host='redis', port=6379)\n \n@app.route('/')\ndef hello():\n count = redis.incr('hits')\n return 'Hello World! 该页面已被访问 {} 次。\\n'.format(count)\n \nif __name__ == "__main__":\n app.run(host="0.0.0.0", debug=True)\nDockerfile\nFROM python:3.6-alpine\nADD . /code\nWORKDIR /code\nRUN pip install redis flask\nCMD ["python", "app.py"]\ndocker-compose.yml\nversion: '3'\nservices:\n \n web:\n build: .\n ports:\n - "5000:5000"\n \n redis:\n image: "redis:alpine"\n启动应用\n使用 docker-compose up 命令来启动应用Docker Compose 会自动启动定义的所有服务。\ndocker-compose up -d\n停止应用\n当你完成工作后可以使用 docker-compose down 命令来停止并清理应用服务。\ndocker-compose down\nCompose 文件\nDocker Compose 文件是 Docker Compose 的核心,它使用 YAML 文件格式定义了多容器 Docker 应用的所有服务、网络和卷。\n文件结构\n一个基本的 docker-compose.yml 文件包含三个主要部分services服务、networks网络和 volumes。\n下面是一个简单的示例展示了这些组件如何被定义和关联\nversion: '3'\nservices:\n web:\n image: nginx\n ports:\n - "80:80"\n depends_on:\n - db\n networks:\n - backend\n db:\n image: postgres\n environment:\n POSTGRES_PASSWORD: mysecretpassword\n volumes:\n - db-data:/var/lib/postgresql/data\n networks:\n - backend\n \nnetworks:\n backend:\n \nvolumes:\n db-data:\n服务Services\n在 services 部分你定义了应用中的各个服务每个服务可以是一个容器在上面的例子中有两个服务web 和 db。\n\nimage: 指定服务使用的镜像。\nports: 映射端口到宿主机。\ndepends_on: 表示服务之间的依赖关系。\nnetworks: 指定服务连接的网络。\nenvironment: 设置环境变量。\n\n网络Networks\n在 networks 部分,你可以定义一个或多个网络,服务可以连接到这些网络。在上例中,定义了一个名为 backend 的网络web 和 db 服务都连接到了这个网络,使得它们可以相互通信。\n卷Volumes\n在 volumes 部分你定义了数据卷用于数据持久化。在上例中db-data 卷被挂载到了 db 服务的容器中,用于存储数据库数据。\n语法\ngraph LR\n A[Docker Compose] --> B[Services]\n A --> C[Volumes]\n A --> D[Networks]\n A --> E[Configs]\n A --> F[Secrets]\n\n B --> G[Service 1]\n B --> H[Service 2]\n B --> I[Service N]\n \n G --> J[Image/Build]\n G --> K[Environment]\n G --> L[Ports]\n G --> M[Depends On]\n G --> N[Volumes]\n G --> O[Networks]\n\n C --> P[Volume 1]\n C --> Q[Volume 2]\n C --> R[Volume N]\n\n D --> S[Network 1]\n D --> T[Network 2]\n D --> U[Network N]\n\n E --> V[Config 1]\n E --> W[Config 2]\n\n F --> X[Secret 1]\n F --> Y[Secret 2]\n\n J --> J1[Type: Image or Build Path]\n K --> K1[Variables]\n L --> L1[Container:Host]\n M --> M1[Service Dependencies]\n N --> N1[Service:Volume Mapping]\n O --> O1[Service Networks]\n\n P --> P1[Driver]\n Q --> Q1[Driver Options]\n\n S --> S1[Driver]\n T --> T1[Driver Options]\n\n V --> V1[File or External]\n W --> W1[File or External]\n\n X --> X1[File or External]\n Y --> Y1[File or External]\n\n关键字\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置项描述build定义了构建服务的配置可以是一个构建上下文的路径或者一个包含 context、dockerfile 和 args 的对象。cap_add, cap_drop添加或删除容器的能力。cgroup_parent指定容器的父 cgroup。command覆盖容器的默认命令。configs为服务提供对配置的访问。container_name指定自定义容器名称。credential_spec配置管理服务帐户的凭据规范。depends_on表达服务之间的依赖关系。deploy指定与服务部署和运行相关的配置。devices设备映射列表。dns, dns_search自定义 DNS 服务器和搜索域。entrypoint覆盖容器的默认入口点。env_file从文件中加载环境变量。environment设置环境变量。expose暴露端口而不发布到宿主机。external_links链接到 Docker Compose 外部的容器。extra_hosts添加主机名映射。healthcheck配置容器的健康检查。image指定服务使用的镜像。init使用 Docker 的 init 进程。labels添加标签到容器。links链接到其他服务的容器。logging配置日志记录。network_mode网络模式。networks配置网络。pidPID 模式。ports发布端口。secrets配置访问秘密。security_opt安全选项。stop_grace_period设置停止前的等待时间。stop_signal设置停止容器的信号。sysctls内核参数设置。tmpfs挂载临时文件系统。ulimits用户限制。user指定运行用户。userns_mode用户命名空间模式。volumes, volume_driver配置卷。volumes_from从其他服务或容器挂载卷。working_dir工作目录。\n服务配置详解\n构建选项\n如果你不是使用现有的镜像而是需要构建自定义镜像可以使用 build 选项:\nversion: '3'\nservices:\n webapp:\n build: ./dir\n环境变量\n你可以直接在 docker-compose.yml 文件中为服务设置环境变量,或者使用 .env 文件来管理:\nversion: '3'\nservices:\n web:\n image: nginx\n environment:\n - NGINX_PORT=80\n依赖关系\n使用 depends_on 选项可以定义服务启动的先后顺序:\nversion: '3'\nservices:\n web:\n image: nginx\n depends_on:\n - db\n db:\n image: postgres\n端口映射\n通过 ports 选项,可以将容器内的端口映射到宿主机的端口:\nversion: '3'\nservices:\n web:\n image: nginx\n ports:\n - "80:80"\n环境变量与 .env 文件的使用\n管理配置和敏感信息时推荐使用 .env 文件来外部定义环境变量,然后在 docker-compose.yml 文件中引用这些变量:\n.env 文件:\nDB_PASSWORD=mysecretpassword\ndocker-compose.yml 文件:\nversion: '3'\nservices:\n db:\n image: postgres\n environment:\n POSTGRES_PASSWORD: ${DB_PASSWORD}\n通过这种方式你可以避免将敏感信息直接硬编码在 docker-compose.yml 文件中,而是将其存储在外部的 .env 文件中,这有助于保持你的配置的安全性和灵活性。\n多容器应用管理\n在 Docker Compose 的使用中,管理多容器应用是核心任务之一。这包括了如何定义和运行多容器应用、如何管理容器间的网络连接以及如何实现数据的持久化和共享。\n定义与运行多容器应用\n利用 docker-compose.yml 文件,开发者可以定义涵盖多个服务(容器)的完整应用架构,实现一键部署和管理。\n考虑到一个典型的三层应用架构包含前端、后端及数据库层\nversion: '3.8'\nservices:\n frontend:\n image: nginx:latest\n ports:\n - "80:80"\n depends_on:\n - backend\n networks:\n - app-network\n \n backend:\n image: node:14\n environment:\n DB_HOST: db\n ports:\n - "3000:3000"\n depends_on:\n - db\n networks:\n - app-network\n \n db:\n image: postgres:13\n environment:\n POSTGRES_USER: user\n POSTGRES_PASSWORD: password\n volumes:\n - db-data:/var/lib/postgresql/data\n networks:\n - app-network\n \nvolumes:\n db-data:\n \nnetworks:\n app-network:\n在这个例子中我们指定了使用的镜像、环境变量、端口映射、依赖关系、网络和数据卷。通过这样的配置可以确保应用的各个部分能够正确连接和交互同时数据也得到了持久化。\n网络管理\nDocker Compose 默认创建一个网络,使得同一 docker-compose.yml 文件中定义的所有服务都能够在这个网络中相互通信。然而,复杂应用可能需要更精细的网络配置来满足不同的安全和隔离需求。\n自定义网络配置允许服务根据实际需求分配到不同的网络中实现更细致的网络隔离和通信策略。\nnetworks:\n app-network:\n driver: bridge\n internal-network:\n driver: bridge\n internal: true\n在上述配置中app-network 用于暴露外部可访问的服务(如前端),而 internal-network 则用于内部服务间的通信,不对外部暴露,增强了安全性。\n数据卷与持久化\n数据持久化对于任何生产级应用都至关重要Docker Compose 通过卷volumes提供了数据持久化的能力。\nvolumes:\n db-data:\n driver: local\n这里定义了一个名为 db-data 的卷,用于 PostgreSQL 数据库的数据持久化存储。通过指定卷,即使容器重新创建,数据也不会丢失。\nDocker Compose 也支持定义卷来实现服务之间的数据共享:\nservices:\n service1:\n volumes:\n - shared-data:/path/to/data\n service2:\n volumes:\n - shared-data:/path/to/data\n \nvolumes:\n shared-data:\n在此配置中service1 和 service2 共享了同一个卷 shared-data允许它们访问和修改相同的数据集这在需要数据共享的应用场景中非常有用。\n高级功能\nDocker Compose 不仅仅是一个多容器部署工具,它还提供了一系列高级功能和最佳实践,帮助开发者和运维人员优化应用配置和管理。本章节将深入探讨服务的健康检查、如何使用 extends 特性以及如何通过覆盖文件分离环境配置。\n服务的健康检查\n健康检查是监控服务状态和健康状况的重要手段。通过配置健康检查Docker 可以自动检测服务是否正常运行。\n在 docker-compose.yml 文件中,可以为服务配置 healthcheck 指令:\nservices:\n web:\n image: my-web-app\n healthcheck:\n test: ["CMD", "curl", "-f", "http://localhost"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n这个配置定义了一个健康检查每 30 秒执行一次 curl -f http://localhost 命令来检查 web 服务的健康状态,如果命令在 10 秒内没有成功执行(即返回状态码非 0则认为是一次失败。如果连续 3 次检查失败,则服务被认为是不健康的。\n扩展与重写服务\nextends 特性允许在一个服务中重用另一个服务的配置。这对于不同环境下的配置共享非常有用。\n假设有一个基础服务配置 base-service.yml\nversion: '3.8'\nservices:\n app_base:\n image: my-app\n environment:\n - DEBUG=false\n可以在 docker-compose.yml 中扩展这个服务:\nversion: '3.8'\nservices:\n app:\n extends:\n file: base-service.yml\n service: app_base\n ports:\n - "80:80"\n通过这种方式app 服务继承了 app_base 的所有配置,并添加了端口映射。\n使用覆盖文件来分离环境配置\nDocker Compose 允许使用多个文件来定义项目配置,这使得可以针对不同环境(如开发、测试、生产)使用不同的配置。\n基础 docker-compose.yml 文件定义了所有环境共有的配置:\nversion: '3.8'\nservices:\n web:\n image: my-web-app\n environment:\n - LOG_LEVEL=info\n针对开发环境的 docker-compose.override.yml\nversion: '3.8'\nservices:\n web:\n environment:\n - DEBUG=true\n volumes:\n - .:/code\n在生产环境的 docker-compose.prod.yml\nversion: '3.8'\nservices:\n web:\n ports:\n - "80:80"\n environment:\n - LOG_LEVEL=warning\n通过指定 -f 参数来使用不同的配置文件:\ndocker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n这种方法使得基础配置与环境特定配置分离便于管理和维护。\n实战项目\n本实战项目将引导你构建一个简单的 Web 应用,该应用包含三个主要组件:前端(使用 Nginx 静态文件服务),后端(一个简单的 Node.js API以及数据库PostgreSQL。此外我们还将探讨如何调试这些服务并进行基本的性能优化。\nWeb 实战项目\n项目概述\n\n前端使用 Nginx 服务静态文件。\n后端Node.js 应用提供 RESTful API。\n数据库PostgreSQL 存储数据。\n\ndocker-compose.yml\nversion: '3.8'\nservices:\n frontend:\n image: nginx:alpine\n volumes:\n - ./frontend:/usr/share/nginx/html\n ports:\n - "80:80"\n depends_on:\n - backend\n networks:\n - app-network\n \n backend:\n build:\n context: ./backend\n dockerfile: Dockerfile\n environment:\n DATABASE_URL: postgres://user:password@db:5432/mydb\n ports:\n - "3000:3000"\n depends_on:\n - db\n networks:\n - app-network\n \n db:\n image: postgres:13\n environment:\n POSTGRES_USER: user\n POSTGRES_PASSWORD: password\n POSTGRES_DB: mydb\n volumes:\n - db-data:/var/lib/postgresql/data\n networks:\n - app-network\n \nvolumes:\n db-data:\n \nnetworks:\n app-network:\n前端\n前端使用 Nginx 静态文件服务。你需要在 ./frontend 目录下放置你的静态文件HTML、CSS、JavaScript 文件等)。\n后端\n后端是一个简单的 Node.js 应用,提供 RESTful API。你需要在 ./backend 目录下创建一个 Dockerfile 和你的 Node.js 应用代码。\n./backend/Dockerfile\nFROM node:14-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install\nCOPY . .\nEXPOSE 3000\nCMD ["node", "server.js"]\nNode.js 服务器\n// server.js\nconst express = require('express');\nconst app = express();\nconst PORT = process.env.PORT || 3000;\n \napp.get('/api', (req, res) => {\n res.json({ message: "Hello from the backend!" });\n});\n \napp.listen(PORT, () => {\n console.log(`Server is running on port ${PORT}`);\n});\n数据库\n使用 PostgreSQL 作为数据库服务。docker-compose.yml 文件中已经配置了必要的环境变量。\n调试与优化\n容器日志查看\n使用 Docker Compose 查看服务日志的命令:\ndocker-compose logs -f backend\n这将跟踪并显示后端服务的实时日志输出。\n资源监控与性能优化\nDocker Desktop 和其他第三方工具如 Portainer 或 cAdvisor 可用于监控容器的资源使用情况。基于监控数据,你可以对服务进行必要的调整,比如调整容器的 CPU 和内存限制:\nservices:\n backend:\n build: ./backend\n mem_limit: 500m\n cpus: '0.5'\n在 docker-compose.yml 文件中,为后端服务设置了内存限制为 500MBCPU 使用限制为 50%。"},"Technology/OperatingSystem/Docker/进阶/Docker-Dockerfile":{"title":"Docker Dockerfile","links":[],"tags":["Docker/进阶","技术/操作系统"],"content":"概述\nDockerfile 是一个文本文件,包含了一系列指令和参数,用于自动化构建 Docker 镜像。每条指令都会在镜像中创建一个新的层,涵盖了从基础镜像开始、复制文件、运行命令、设置环境变量等多种操作。通过 Dockerfile可以确保镜像的构建过程是可重复且无差异的这对于持续集成和持续部署CI/CD的实施至关重要。\nDockerfile\nDockerfile 的开发是一个循环的过程,涉及编写、构建、测试、优化和维护,旨在创建高效、可维护且可重复使用的 Dockerfile以生成高质量的 Docker 镜像。\n以下是 Dockerfile 开发的常规工作流程:\ngraph TD\n A[需求分析] --> B[编写 Dockerfile]\n B --> C[构建镜像]\n C --> D[测试镜像]\n D --> E{满足需求?}\n E -->|是| F[优化和迭代]\n E -->|否| G[维护和更新]\n F --> H[分享和部署]\n G --> B\n H --> I[结束]\n\n关键步骤\n\n定义基础镜像从一个已有的镜像开始这是所有后续操作的基础。\n执行构建命令安装软件包、修改配置文件等。\n添加文件和目录将所需文件和目录添加到镜像中。\n设置工作目录为 Dockerfile 中的指令指定工作目录。\n配置环境变量设定必要的环境变量。\n暴露端口声明容器监听的端口。\n配置启动命令设置容器启动时执行的命令。\n\n指令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n指令描述示例FROM指定基础镜像是构建新镜像的起点。FROM ubuntu:18.04RUN在镜像构建过程中运行命令。RUN apt-get update && apt-get install -y nginxCMD提供容器启动时的默认执行命令。CMD ["nginx", "-g", "daemon off;"]ENTRYPOINT配置容器启动时运行的命令可以与 CMD 指令配合使用。ENTRYPOINT ["./app"]COPY将文件从构建上下文复制到镜像中。COPY . /appADD将文件从构建上下文或 URL 复制到镜像中可自动解压压缩包。ADD example.com/big.tar.xz /usr/src/things/ENV设置环境变量。ENV MY_VAR=valueEXPOSE声明容器运行时监听的端口。EXPOSE 80VOLUME创建一个挂载点来持久化数据。VOLUME /dataWORKDIR为 Dockerfile 中的指令设置工作目录。WORKDIR /appARG定义构建时的变量可以在构建命令中用 --build-arg 来覆盖。ARG VERSION=latestUSER指定运行容器时的用户名或 UID以及可选的用户组或 GID。USER www-dataLABEL为镜像添加元数据。LABEL version="1.0"ONBUILD为镜像指定触发器指令当镜像作为基础镜像时触发器将在派生镜像中执行。ONBUILD RUN echo 'Doing something...'HEALTHCHECK指定一个命令用于检查容器是否健康运行。`HEALTHCHECK CMD curl —fail http://localhost:80/SHELL用于覆盖默认的 shell 命令。SHELL ["/bin/bash", "-c"]STOPSIGNAL设置停止容器时发送的系统调用信号。STOPSIGNAL SIGTERM\n示例\n# 指定基础镜像\nFROM python:3.8\n \n# 设置工作目录\nWORKDIR /app\n \n# 复制依赖文件到容器中\nCOPY requirements.txt ./\n \n# 安装依赖\nRUN pip install --no-cache-dir -r requirements.txt\n \n# 将当前目录下的所有文件复制到容器的工作目录中\nCOPY . .\n \n# 暴露端口\nEXPOSE 5000\n \n# 定义容器启动时执行的命令\nCMD ["flask", "run", "--host=0.0.0.0"]\n镜像构建\n镜像构建是 Docker 使用中的核心概念,它允许用户从一个基础镜像开始,通过一系列步骤添加自定义的层次,最终创建出一个新的镜像。深入了解镜像构建,包括二次构建(多阶段构建)等高级特性,可以帮助你更高效地使用 Docker优化你的开发和部署流程。\n\nDockerfileDockerfile 是构建 Docker 镜像的蓝图,它包含了一系列的指令,每个指令都会在镜像中创建一个新的层。\n镜像层Docker 镜像是由多个只读层组成的。当你更改镜像并提交这些更改时,你实际上是在基础镜像上添加了一个新层。\n构建上下文构建上下文是指向 Docker 守护进程的一组文件和目录,这些文件和目录用于构建 Docker 镜像。构建上下文的路径可以在 docker build 命令中指定。\n\n基本构建\n使用 docker build 命令和 Dockerfile 来构建镜像。在构建过程中Docker 逐条处理 Dockerfile 中的指令,每条指令都会创建镜像的一个新层。构建完成后,你将获得一个可用于创建容器的镜像。\ndocker build -t my_image_name:my_tag .\n这个命令将使用当前目录中的 Dockerfile 来构建镜像,并将其标记为 my_image_name:my_tag。\n多阶段构建\n多阶段构建是 Docker 17.05 版本引入的一个特性,它允许在一个 Dockerfile 中定义多个构建阶段,每个阶段都可以使用不同的基础镜像。多阶段构建的主要优点是减小最终镜像的大小,提高构建效率,避免在最终镜像中包含不必要的文件。\n\n定义多个阶段可以通过在 Dockerfile 中多次使用 FROM 指令来定义多个构建阶段。\n复制阶段间的文件使用 COPY --from=<stage> 指令可以从一个阶段复制文件到另一个阶段。\n\n# 第一阶段:构建阶段\n# 使用官方 Python 镜像作为构建镜像的基础\nFROM python:3.8-slim as builder\n \n# 设置工作目录\nWORKDIR /app\n \n# 将应用依赖复制到容器中\nCOPY requirements.txt .\n \n# 安装应用依赖\nRUN pip install --user -r requirements.txt\n \n# 复制应用代码到容器中\nCOPY . .\n \n# 第二阶段:运行阶段\n# 再次从一个干净的 Python 镜像开始\nFROM python:3.8-slim\n \n# 创建一个非 root 用户\nRUN useradd -m myuser\nUSER myuser\n \n# 从构建阶段复制已安装的依赖\nCOPY --from=builder /root/.local /home/myuser/.local\nCOPY --from=builder /app /app\n \n# 设置工作目录\nWORKDIR /app\n \n# 设置环境变量\nENV PATH=/home/myuser/.local/bin:$PATH\n \n# 暴露应用端口\nEXPOSE 5000\n \n# 设置容器启动时执行的命令\nCMD ["python", "app.py"]\n优化构建\n\n减少层的数量合并多个 RUN 指令可以减少镜像层的数量,减小镜像大小。\n使用 .dockerignore 文件:通过定义 .dockerignore 文件排除不必要的文件和目录,减少构建上下文的大小,加快构建速度。\n利用构建缓存Docker 会缓存每一层的结果,如果 Dockerfile 中的某一层没有变化,则在构建时会重用这一层的缓存。合理利用构建缓存可以显著提高构建效率。\n\n镜像管理\nDocker 提供了多种命令来管理本地存储的镜像:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例docker images 或 docker image ls列出本地所有镜像docker imagesdocker rmi <image>删除指定的镜像docker rmi nginx:latestdocker inspect <image>显示镜像的详细信息docker inspect ubuntu:18.04docker pull <image>从远程仓库拉取指定的镜像docker pull python:3.8-slimdocker push <image>将本地镜像推送到远程仓库docker push myusername/myimage:tagdocker build -t <tag> .根据当前目录的 Dockerfile 构建镜像docker build -t myapp:v1 .docker history <image>查看镜像的构建历史docker history nginx:latestdocker tag <image> <tag>为镜像添加一个新标签docker tag myimage:latest myimage:v2docker save -o <path> <image>将镜像保存为 tar 归档文件docker save -o myimage.tar myimage:latestdocker load -i <path>从 tar 归档文件中加载镜像docker load -i myimage.tardocker image prune删除未被任何容器使用的悬挂镜像docker image prunedocker image rm <image>删除一个或多个镜像docker image rm myimage1 myimage2\n镜像仓库\nDocker 镜像仓库扮演着在 Docker 生态系统中极为关键的角色,它们不仅存储和分发容器镜像,还促进了开发和运维工作的协同。这些仓库可以是公开的,也可以是私有的,以满足不同的安全和隐私需求。\nDocker Hub 是最广为人知的 Docker 镜像仓库,提供了大量的公共镜像供下载和使用。它支持个人和组织管理镜像,并能与自动化构建和测试流程无缝集成。\n对于需要控制镜像访问权限的场景私有 Docker 仓库是理想的选择。私有仓库可以部署在内部网络中确保敏感镜像的安全。Docker Registry 是官方提供的开源仓库解决方案,支持本地部署和管理私有镜像。\n使用 Docker Hub 拉取镜像\n从 Docker Hub 或私有仓库拉取镜像是常见操作。使用 docker pull 命令可以轻松完成这一任务:\ndocker pull my_username/my_image_name:my_tag\n推送镜像到 Docker Hub\n1. 创建 Docker Hub 账号\n如果你还没有 Docker Hub 的账号,你需要先在 Docker Hub 上注册一个。\n2. 登录到 Docker Hub\n在终端或命令行界面使用 docker login 命令登录到你的 Docker Hub 账号。输入你的用户名和密码进行认证。\ndocker login\n\n成功登录后你的认证信息将被保存以便后续操作无需重复登录。\n3. 标记你的镜像\n在推送镜像之前你需要为你的镜像设置一个标签Tag这个标签应该包含你的 Docker Hub 用户名、镜像的名字,以及(可选的)标签。\ndocker tag local-image-name:tag your-dockerhub-username/repository-name:tag\n\n\nlocal-image-name:tag 是你本地镜像的名称和标签。\nyour-dockerhub-username 是你在 Docker Hub 上的用户名。\nrepository-name 是你希望在 Docker Hub 上创建的仓库名。\ntag 是你给镜像指定的标签,如果不指定,默认为 latest。\n\n例如如果你的 Docker Hub 用户名是 johndoe并且你想要推送一个名为 myapp 的镜像,标签为 v1.0,你可以执行:\ndocker tag myapp:latest johndoe/myapp:v1.0\n\n4. 推送镜像到 Docker Hub\n使用 docker push 命令将镜像推送到你的 Docker Hub 仓库:\ndocker push your-dockerhub-username/repository-name:tag\n\n继续之前的例子\ndocker push johndoe/myapp:v1.0\n\n这个命令会将 myapp 镜像的 v1.0 标签版本推送到 Docker Hub 上的 johndoe/myapp 仓库中。\n5. 验证\n推送完成后你可以在 Docker Hub 的网站上登录你的账号,查看你的仓库列表,确认新推送的镜像已经出现在列表中。\n推送镜像到私人仓库\n推送镜像到私人仓库的过程与推送到 Docker Hub 类似,但需要确保你有权限访问该私人仓库,并且可能需要配置额外的认证信息。以下是推送镜像到私人仓库的一般步骤:\n1. 登录私人仓库\n私有仓库通常需要认证以保证仓库的安全性。使用 docker login 命令进行登录,确保你拥有足够的权限来推送镜像。\ndocker login myregistry.example.com\n2.标记你的镜像\n在推送镜像之前需要将其标记为私人仓库的地址。这是通过 docker tag 命令完成的,标记格式通常为 仓库地址/用户名/镜像名称:标签。\ndocker tag my_image_name:my_tag myregistry.example.com/my_username/my_image_name:my_tag\n这里\n\nmy_image_name:my_tag 是你本地镜像的名称和标签。\nmyregistry.example.com 是你的私人仓库地址。\nmy_username 是你在该仓库的用户名或命名空间。\n\n3. 推送镜像\n完成镜像标记后使用 docker push 命令将其推送到私人仓库。\n标记完成后使用 docker push 命令将镜像推送到私人仓库:\ndocker push myregistry.example.com/my_username/my_image_name:my_tag\n4. 管理私人仓库中的镜像\n私人仓库可能提供了一个用户界面或者 API供你管理仓库中的镜像包括查看、删除和设置访问权限等。\n5. 使用私人仓库中的镜像\n从私人仓库拉取镜像时同样需要先进行认证。一旦认证通过你可以使用 docker pull 命令拉取所需的镜像。\ndocker pull myregistry.example.com/my_username/my_image_name:my_tag"},"Technology/OperatingSystem/Docker/进阶/Docker-使用":{"title":"Docker 使用","links":[],"tags":["Docker/进阶","技术/操作系统"],"content":"Docker 是一个开源平台用于自动化开发、部署和运行应用程序的过程通过使用容器化技术Docker 允许开发者将应用及其依赖打包成一个轻量级、可移植的容器,然后这个容器可以在任何地方运行。这样,它解决了“在我的机器上可以运行”的问题,提高了软件交付的效率和可靠性。\n容器\n容器化是一种虚拟化技术它允许你在隔离的环境中运行和部署应用。每个容器独立运行一个或多个应用程序包括它们所需的所有依赖。这就像将你的应用及其所有依赖打包在一个集装箱中无论在什么环境下运输运行都能确保其内容不受影响。\n生命周期\n容器的生命周期管理是 Docker 使用的核心概念之一,涉及容器从创建到销毁的全过程。容器的生命周期可以通过一系列的 Docker 命令来管理,这些命令包括创建、启动、停止、重启、删除等操作。\n\n创建容器\n创建容器是容器生命周期的第一步这一过程依赖于 Docker 镜像。Docker 镜像是一个包含了应用及其依赖的轻量级、可执行的软件包,确保了应用在任何环境下的一致性和可移植性。\ndocker run hello-world\n容器管理\n容器一旦创建就可以通过各种命令进行管理。这些命令允许用户控制容器的生命周期包括启动、停止、重启和删除等操作。\n\n启动容器docker start my_container此命令用于启动一个或多个已经创建但停止运行的容器。\n停止容器docker stop my_container该命令用于停止一个或多个正在运行的容器。停止容器会向容器内的主进程发送 SIGTERM 信号,之后发送 SIGKILL 信号,以确保容器停止运行。\n查看运行中的容器docker ps此命令展示了所有当前正在运行的容器。使用 -a 选项可以查看包括停止的在内的所有容器。\n进入运行中的容器docker exec -it my_container /bin/bash该命令允许用户进入一个正在运行的容器内部并以交互模式启动一个新的终端会话。这对于调试应用或管理容器内的服务非常有用。\n删除容器docker rm my_container使用这个命令可以删除一个或多个已停止的容器。如果要删除运行中的容器需要加上 -f 或 --force 参数来强制删除。\n\n高级容器管理\n除了基本的生命周期管理命令Docker 还提供了一系列高级功能,以支持更复杂的容器操作和管理需求。\n\n查看容器日志docker logs my_container这个命令允许用户检查和跟踪容器内的标准输出和错误输出。对于调试应用和监控容器运行状态非常有用。\n查看容器内部进程docker top my_container此命令显示运行在容器内部的进程列表有助于了解容器内部的活动。\n暂停容器docker pause my_container该命令用于暂停运行中的容器所有进程都会被挂起。这可以用于资源管理或在特定时刻“冻结”容器的状态。\n恢复容器docker unpause my_container与 docker pause 相对,此命令用于恢复被暂停的容器的执行。\n容器资源限制在创建或运行容器时可以通过 --memory、--cpu-shares 等参数来限制容器可以使用的资源,从而避免单个容器占用过多的系统资源。\n\n数据卷\n数据卷是 Docker 实现数据持久化和共享的关键机制之一。通过使用数据卷,用户可以在不同容器之间共享数据,同时保证数据的持久化存储,即使容器被删除,卷中的数据也不会丢失。\n\n数据持久化数据卷提供了一种机制可以将数据存储在容器之外确保重要数据不会因容器的删除而丢失。\n数据共享与重用数据卷可以被多个容器挂载和访问实现数据的共享。\n容器解耦通过数据卷应用程序的运行状态可以与数据保持独立便于应用的迁移和备份。\n\n使用数据卷\n创建和使用数据卷的基本命令如下\n# 创建一个新的数据卷\ndocker volume create my_volume\n \n# 将数据卷挂载到容器\ndocker run -d -v my_volume:/path/in/container --name my_container my_image\n此命令会启动一个新的容器将之前创建的数据卷 my_volume 挂载到容器的指定路径 /path/in/container 下。容器内应用对该路径的任何写操作都会直接反映到数据卷上,同样,对数据卷的任何更改也会立即在挂载它的所有容器中可见。\n数据卷容器\n数据卷容器是一种使用数据卷共享数据的模式。通过创建一个专门的容器来持有数据卷其他容器可以通过 —volumes-from 标志来挂载这个容器中的数据卷。\n# 创建一个带数据卷的容器\ndocker run -d --name data_container -v my_volume:/path/in/container my_image\n \n# 使用 --volumes-from 从其他容器挂载数据卷\ndocker run -d --name app_container --volumes-from data_container my_app_image\n这种方法使得数据的管理和共享变得更加集中和高效。\nDocker 网络\nDocker 网络功能允许容器相互通信并与外部世界交互。Docker 提供了多种网络模式,以支持不同的使用场景。\n网络模式\n\nbridge默认网络模式。当容器运行在桥接网络中时Docker 会自动使用私有子网内的 IP 地址来分配给每个容器,并通过 NAT 实现与外部网络的通信。\nhost在这种模式下容器共享宿主机的网络命名空间不进行网络隔离。容器的网络性能更好但是安全性降低。\nnone在这种模式下容器具有自己的网络命名空间但不配置任何网络接口通常用于需要手动管理网络的高级场景。\n\n自定义网络\n创建自定义网络可以提供更灵活的网络配置使得容器间的通信更加方便和安全。\n# 创建自定义桥接网络\ndocker network create --driver bridge my_custom_bridge\n \n# 运行容器时指定网络\ndocker run -d --name my_container --network my_custom_bridge my_image\n在自定义网络中容器可以通过容器名相互访问而不需要使用 IP 地址,简化了容器间通信的配置。\n网络连接和断开\nDocker 允许在运行时将容器连接到网络或从网络断开。\n# 将运行中的容器连接到网络\ndocker network connect my_custom_bridge my_container\n \n# 将容器从网络断开\ndocker network disconnect my_custom_bridge my_container\n这提供了动态管理容器网络连接的灵活性允许根据需要调整容器的网络配置。"},"Technology/OperatingSystem/Docker/高级/Docker-命令手册":{"title":"Docker 命令手册","links":[],"tags":["Docker/高级","技术/操作系统"],"content":"以下是根据你提供的内容,补充完善后的 Docker 命令手册:\n容器生命周期管理\n\n\ndocker run [OPTIONS] IMAGE [COMMAND] [ARG...]:创建一个新容器并运行一个命令。\n\n\ndocker start CONTAINER启动一个或多个已经停止的容器。\n\n\ndocker stop CONTAINER停止一个或多个正在运行的容器。\n\n\ndocker restart CONTAINER重启一个或多个容器。\n\n\ndocker kill CONTAINER强制停止一个或多个正在运行的容器。\n\n\ndocker rm CONTAINER删除一个或多个容器。\n\n\ndocker pause CONTAINER暂停一个或多个容器的所有进程。\n\n\ndocker unpause CONTAINER恢复一个或多个容器的所有进程。\n\n\ndocker create [OPTIONS] IMAGE [COMMAND] [ARG...]:创建一个新的容器但不启动它。\n\n\ndocker exec [OPTIONS] CONTAINER COMMAND [ARG...]:在运行的容器中执行一个命令。\n\n\n容器操作\n\n\ndocker ps [OPTIONS]:列出容器。\n\n\ndocker inspect [OPTIONS] TARGET返回 Docker 对象的底层信息。\n\n\ndocker top CONTAINER [ps OPTIONS]:显示容器的运行进程。\n\n\ndocker attach CONTAINER连接到正在运行的容器。\n\n\ndocker events [OPTIONS]:从服务器获取实时事件。\n\n\ndocker logs [OPTIONS] CONTAINER获取容器的日志。\n\n\ndocker wait CONTAINER阻塞到容器停止然后打印退出代码。\n\n\ndocker export CONTAINER将文件系统作为一个 tar 归档文件导出到 STDOUT。\n\n\ndocker port CONTAINER [PRIVATE_PORT[/PROTO]]:列出容器的端口映射,或打印指定端口的映射。\n\n\ndocker stats [OPTIONS] [CONTAINER...]:实时显示容器的资源使用统计信息。\n\n\n容器 Rootfs 命令\n\n\ndocker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]:从容器创建一个新的镜像。\n\n\ndocker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-:在本地文件系统和容器之间复制文件/文件夹。\n\n\ndocker diff CONTAINER检查在容器文件系统上所做的更改。\n\n\n镜像仓库\n\n\ndocker login [OPTIONS] [SERVER]:登录 Docker 的镜像仓库。\n\n\ndocker pull [OPTIONS] NAME[:TAG|@DIGEST]:从镜像仓库中拉取镜像。\n\n\ndocker push [OPTIONS] NAME[:TAG]:将镜像或仓库推送到镜像仓库。\n\n\ndocker search [OPTIONS] TERM在 Docker Hub 中搜索镜像。\n\n\n本地镜像管理\n\n\ndocker images [OPTIONS] [REPOSITORY[:TAG]]:列出镜像。\n\n\ndocker rmi [OPTIONS] IMAGE [IMAGE...]:删除一个或多个镜像。\n\n\ndocker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]:为源镜像创建一个新的别名标签。\n\n\ndocker build [OPTIONS] PATH | URL | -:从 Dockerfile 构建一个新的镜像。\n\n\ndocker history [OPTIONS] IMAGE显示镜像的历史。\n\n\ndocker save [OPTIONS] IMAGE [IMAGE...]:将一个或多个镜像保存为 tar 归档文件。\n\n\ndocker load [OPTIONS]:从 tar 归档文件加载一个或多个镜像。\n\n\ndocker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]:从 tarball 导入内容以创建一个文件系统镜像。\n\n\n系统信息\n\n\ndocker info [OPTIONS]:显示系统级信息。\n\n\ndocker version [OPTIONS]:显示 Docker 版本信息。\n\n"},"Technology/OperatingSystem/Docker/高级/Docker-存储":{"title":"Docker 存储","links":[],"tags":["Docker/高级","技术/操作系统"],"content":"Docker 提供了三种主要的数据存储机制:数据卷、目录绑定和临时数据。这些机制可以根据不同的需求和场景来实现数据的持久化存储和共享。\n数据卷\n数据卷是一种用于持久化存储容器数据的机制。它可以将主机上的目录或文件挂载到容器中从而实现数据在容器和主机之间的共享和持久化。数据卷的主要优势是容器与数据的解耦使得容器可以在不同的主机上迁移和共享数据。\n数据卷的主要特点包括\n\n数据卷是独立于容器的实体。即使容器被删除数据卷仍然存在。\n数据卷可以被多个容器共享。这意味着多个容器可以访问和修改同一个数据卷中的数据。\n数据卷可以在容器之间进行传递。例如可以将一个数据卷从一个容器挂载到另一个容器中从而实现数据的共享和传递。\n数据卷可以在容器运行时进行挂载和卸载。这意味着可以在容器运行时动态地修改数据卷的挂载点。\n\n使用数据卷的步骤如下\n\n\n创建一个数据卷\ndocker volume create my-volume\n这将创建一个名为 my-volume 的数据卷。\n\n\n将数据卷挂载到容器中\ndocker run -v my-volume:/path/in/container my-image\n这将把名为 my-volume 的数据卷挂载到容器中的 /path/in/container 目录。\n\n\n可以在多个容器中使用相同的数据卷\ndocker run -v my-volume:/path/in/container another-image\n这将把同一个名为 my-volume 的数据卷挂载到另一个容器中。\n\n\n数据卷的生命周期管理包括创建、使用和删除。可以使用以下命令和操作来管理数据卷\n\n\n创建一个数据卷\ndocker volume create my-volume\n这将创建一个名为 my-volume 的数据卷。\n\n\n将数据卷挂载到容器中\ndocker run -v my-volume:/path/in/container my-image\n这将把名为 my-volume 的数据卷挂载到容器中的 /path/in/container 目录。\n\n\n查看数据卷的详细信息\ndocker volume inspect my-volume\n这将显示关于数据卷的详细信息包括挂载点、创建时间等。\n\n\n删除一个数据卷\ndocker volume rm my-volume\n这将删除名为 my-volume 的数据卷。请注意,只有在没有容器使用该数据卷时才能删除。\n\n\n数据卷的备份和还原可以使用以下方法\n\n\n备份数据卷\ndocker run --rm -v my-volume:/data -v $(pwd):/backup busybox tar cvf /backup/my-volume.tar /data\n这将创建一个名为 my-volume.tar 的备份文件,其中包含了 my-volume 数据卷中的所有数据。\n\n\n还原数据卷\ndocker run --rm -v my-volume:/data -v $(pwd):/backup busybox tar xvf /backup/my-volume.tar -C /\n这将从备份文件 my-volume.tar 中还原数据到 my-volume 数据卷中。\n\n\n目录绑定\n目录绑定是将主机上的目录直接映射到容器中的一种机制。通过目录绑定容器可以直接访问和修改主机上的文件和目录。\n目录绑定的主要特点包括\n\n目录绑定是容器和主机之间的直接映射关系。容器中的操作会直接影响主机上的文件和目录。\n目录绑定是一种静态的映射关系。一旦映射建立容器运行期间无法修改映射关系。\n目录绑定是一对一的关系。每个容器只能与一个主机目录进行映射。\n目录绑定可以在容器创建时进行设置也可以在容器运行时进行修改。但无论何时修改映射关系都需要重新启动容器。\n\n使用目录绑定的步骤如下\n\n\n将主机上的目录映射到容器中\ndocker run -v /path/on/host:/path/in/container my-image\n这将把主机上的 /path/on/host 目录映射到容器中的 /path/in/container 目录。\n\n\n容器中对映射的目录进行操作将直接影响主机上的目录。\n\n\n临时数据\n在某些情况下容器可能需要临时性的数据存储这些数据不需要持久化保存。Docker 提供了几种方式来实现临时数据存储。\n临时数据的存储方式包括\n\n\n临时文件系统tmpfs可以将一个临时文件系统挂载到容器中的某个目录用于存储临时数据。这些数据在容器停止时会被删除。\ndocker run --rm -it --mount type=tmpfs,destination=/data my-image\n\n\n临时性数据卷可以创建一个临时性的数据卷用于存储临时数据。这些数据卷在容器停止时会被删除。\ndocker run --rm -it -v /data my-image\n\n\n临时数据的清理与管理方法包括\n\n定期清理任务可以编写一个定期运行的清理任务删除不再需要的临时数据。\n使用临时性数据卷如果使用临时性数据卷存储临时数据可以在容器停止时自动删除数据卷。\n\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述docker volume create <volume_name>创建一个数据卷docker volume ls列出所有数据卷docker volume inspect <volume_name>查看数据卷的详细信息docker volume rm <volume_name>删除一个数据卷docker run -v <volume_name>:<container_path> <image>将数据卷挂载到容器中docker run -v <host_path>:<container_path> <image>将主机上的目录映射到容器中docker run --mount type=tmpfs,destination=<container_path> <image>创建一个临时文件系统挂载到容器中docker cp <container_id>:<container_path> <host_path>将容器中的文件或目录复制到主机上docker run --rm -v <volume_name>:/data -v $(pwd):/backup busybox tar cvf /backup/<backup_name>.tar /data备份数据卷中的数据到主机上的备份文件中docker run --rm -v <volume_name>:/data -v $(pwd):/backup busybox tar xvf /backup/<backup_name>.tar -C /从备份文件中还原数据到数据卷中docker run --rm -it --mount type=tmpfs,destination=<container_path> <image>创建一个临时文件系统挂载到容器中用于存储临时数据docker run --rm -it -v /data <image>创建一个临时性数据卷,用于存储临时数据\n请注意上述命令中的 <volume_name>、<container_path>、<host_path>、<backup_name> 等参数需要根据实际情况进行替换。\n数据卷插件\n除了默认的本地数据卷驱动程序Docker 还支持使用数据卷插件进行数据存储。数据卷插件可以提供更高级的存储功能,例如远程存储、分布式存储等。\n数据卷插件分为存储驱动程序插件和第三方数据卷插件。\n存储驱动程序插件\n存储驱动程序插件是 Docker 的一种官方插件类型,用于扩展 Docker 引擎的存储功能。存储驱动程序插件可以实现不同的存储后端,例如 Amazon EBS、GlusterFS、Ceph 等。\n使用存储驱动程序插件时需要先安装插件并将其配置为 Docker 引擎的默认存储驱动程序。然后,可以使用标准的 Docker 命令和操作来创建和管理存储卷。\n第三方数据卷插件\n除了官方的存储驱动程序插件还有很多第三方数据卷插件可供选择。这些插件提供了各种不同的存储后端和功能可以根据具体需求选择合适的插件。\n使用第三方数据卷插件时需要先安装插件并配置其相关参数。然后可以使用插件特定的命令和操作来创建和管理存储卷。\n数据备份与迁移\n在 Docker 中,数据备份和迁移是常见的需求。下面介绍一些备份和迁移容器中数据的方法。\n备份容器中的数据\n备份容器中的数据可以使用以下方法\n\n\n使用 docker cp 命令将容器中的数据复制到主机上:\ndocker cp <container_id>:/path/in/container /path/on/host\n这将把容器中的 /path/in/container 目录或文件复制到主机上的 /path/on/host 目录。\n\n\n使用数据卷进行备份如果容器使用了数据卷可以直接备份数据卷或者将数据卷挂载到另一个容器中进行备份。\n\n\n迁移容器中的数据到其他环境\n迁移容器中的数据到其他环境可以使用以下方法\n\n\n使用数据卷进行迁移如果容器使用了数据卷可以将数据卷挂载到另一个容器中然后在新环境中运行该容器从而迁移数据。\n\n\n使用容器快照进行迁移Docker 提供了容器快照功能,可以将容器的状态和数据保存为一个快照文件,然后在其他环境中加载该快照文件,从而迁移数据。\n\n\n以上是关于 Docker 数据存储的详细介绍和示例。根据不同的需求和场景,可以选择合适的数据存储机制来管理容器中的数据。"},"Technology/OperatingSystem/Docker/高级/Docker-网络":{"title":"Docker 网络","links":[],"tags":["Docker/高级","技术/操作系统"],"content":"Docker 网络\nDocker 网络是容器间通信的基础,它提供了不同容器之间的网络连接和通信能力。**Docker 默认的网络是 bridge 网络,它是一种虚拟的以太网桥,用于连接未指定网络配置的容器。**除了 bridge 网络之外Docker 还提供了其他网络驱动类型,如 host、ipvlan、macvlan 和 overlay 等,用于满足不同的网络需求。\n特点\n\n自动连接当启动容器时如果没有明确指定网络容器会自动加入到 bridge 网络。这种默认行为简化了容器间通信的设置。\n隔离与通信bridge 网络允许容器之间相互通信,但默认情况下对外部网络是不可见的。要从外部访问容器内的应用,需要设置端口映射。\n内部 DNS 解析Docker 为 bridge 网络提供了内部 DNS 解析,容器可以使用其他容器的名字进行相互通信,而不是依赖于 IP 地址,提高了配置的灵活性和容器间互联的便利性。\n\n命令\n以下是一些常用的 Docker 网络命令:\n\ndocker network ls列出所有当前的 Docker 网络。\ndocker network create [OPTIONS] NETWORK创建一个新的 Docker 网络。可以使用 --driver bridge 来指定网络驱动。\ndocker network rm NETWORK删除一个或多个 Docker 网络。\ndocker network inspect NETWORK显示一个或多个 Docker 网络的详细信息。\ndocker network connect NETWORK CONTAINER将一个容器连接到一个网络。对于已经运行的容器添加网络连接特别有用。\ndocker network disconnect NETWORK CONTAINER将一个容器从一个网络断开。\ndocker run --network NETWORK在创建容器时指定容器连接的网络。如果不指定容器将连接到默认的 bridge 网络。\ndocker run -p HOST_PORT:CONTAINER_PORT在运行容器时创建端口映射将宿主机的端口映射到容器的端口允许从外部访问容器的服务。\n\n管理\nDocker 网络的管理涉及以下几个方面:\n步骤 1: 创建自定义网络\n首先我们可以创建一个自定义的网络以实现更好的网络隔离和通信管理。\ndocker network create --driver bridge my-custom-network\n这个命令创建了一个名为 my-custom-network 的新网络,使用的是 bridge 驱动。\n步骤 2: 在自定义网络中启动容器\n现在我们可以在这个新创建的网络中启动容器了。例如我们可以运行一个简单的 web 应用容器:\ndocker run -d --name my-web-app --network my-custom-network -p 8080:80 nginx\n这个命令做了几件事情\n\n-d以 detached 模式运行容器,即在后台运行。\n--name my-web-app给容器指定一个名称这里是 my-web-app。\n--network my-custom-network指定容器加入 my-custom-network 网络。\n-p 8080:80将容器内部使用的端口 80 映射到宿主机的端口 8080 上。这意味着,你可以通过访问宿主机的 8080 端口来访问容器内部运行的 Nginx 服务。\n\n步骤 3: 验证网络和端口映射\n在容器启动后你可以使用以下命令来检查网络设置和端口映射是否按预期工作\ndocker container inspect my-web-app\n这个命令会输出很多信息包括容器的网络配置。你可以查找到 Networks 部分,确保容器已经加入到 my-custom-network 网络。同时,查看 Ports 部分,确认端口映射设置正确。\n步骤 4: 访问你的 Web 应用\n既然我们已经将容器的 80 端口映射到了宿主机的 8080 端口,你可以通过浏览器访问 http://<宿主机IP>:8080 来查看 Nginx 的欢迎页面。这表明你的容器已经成功运行,并且端口映射工作正常。\n网络类型\nDocker 提供了多种网络类型,可以根据需求选择合适的网络驱动和配置。下面是一个关于 Docker 网络驱动的表格整理:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n网络驱动介绍优点缺点配置方式适用场景Bridge默认网络驱动创建桥接网络简单易用容器之间可以互相通信容器与宿主机之间的网络性能有一定损耗docker network create --driver bridge my-bridge-network多个容器需要在同一网络中进行通信Host容器直接使用宿主机网络栈最大化网络性能容器与宿主机共享网络资源容器与宿主机之间的网络隔离性较弱在运行容器时使用 --network host 参数需要容器与宿主机共享网络资源的场景IPvlan容器直接使用宿主机物理网络接口容器与外部网络直接通信性能较好需要满足宿主机网络接口的限制配置较为复杂docker network create --driver ipvlan my-ipvlan-network需要容器具有独立的 IP 地址的场景Macvlan容器直接使用宿主机物理网络接口容器与外部网络直接通信性能较好需要满足宿主机网络接口的限制配置较为复杂docker network create --driver macvlan my-macvlan-network需要容器具有独立的 MAC 和 IP 地址的场景Overlay多主机网络用于跨主机容器通信容器可以在多个主机之间进行通信支持跨主机容器编排和服务发现需要配置额外的网络管理工具和服务使用 Docker Swarm 模式创建 Overlay 网络多主机环境下需要容器之间进行通信的场景None容器不连接到任何网络提供完全的网络隔离适用于一些特殊的使用场景容器无法与其他容器或外部网络进行通信在运行容器时使用 --network none 参数需要在容器中运行一些网络隔离的工具或测试环境\n桥接网络Bridge Network\n桥接网络是 Docker 默认网络的一种模式它允许容器通过一个虚拟网桥接口连接到宿主机的物理网络。这种网络模式下Docker 会为每个容器分配一个唯一的 IP 地址,并使用 NAT网络地址转换技术将容器内部的 IP 地址映射到宿主机的 IP 地址上,从而实现容器与外部网络的通信。\n要创建一个桥接网络可以使用以下命令\ndocker network create my-bridge-network\n主机网络Host Network\n主机网络模式允许容器直接使用宿主机的网络栈与宿主机共享网络命名空间。这意味着容器将使用宿主机的 IP 地址和端口,与宿主机一样具有与外部网络通信的能力。这种模式适用于需要容器与宿主机共享网络资源的场景,但也带来了安全性和隔离性的考虑。\n要在容器中使用主机网络模式可以在运行容器时使用 --network host 参数:\ndocker run --network host my-container\n当涉及到 Docker 网络连接时,除了桥接网络、主机网络和 None 网络之外还有两种重要的网络连接方式ipvlan 和 macvlan。这两种连接方式可以提供更高级的网络功能和更好的性能。下面我们将深入了解这两种网络连接方式的概念、用法和适用场景。\nIPvlan Network\nIPvlan 是一种网络连接方式,允许容器直接使用宿主机的网络接口,并为每个容器分配独立的 MAC 和 IP 地址。与桥接网络不同IPvlan 不需要进行 NAT 转换,从而提供了更好的性能和更低的延迟。\n在 IPvlan 中,有两种模式可供选择:\n\nL2 模式Layer 2 mode容器可以直接使用宿主机的网络接口每个容器分配一个独立的 MAC 地址。这种模式适用于需要容器与外部网络直接通信的场景,如虚拟机迁移和容器之间的高性能通信。\nL3 模式Layer 3 mode容器使用宿主机的网络接口并为每个容器分配一个独立的 IP 地址。这种模式适用于需要容器与外部网络进行通信,但不需要直接与其他容器通信的场景。\n\n使用 IPvlan 连接容器\n要在 Docker 中使用 IPvlan 连接容器,需要满足以下要求:\n\n宿主机的内核版本必须支持 IPvlan。\n宿主机的网络接口必须支持多播multicast。\n\n以下是使用 IPvlan 连接容器的示例命令:\ndocker network create -d ipvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=eth0 my-ipvlan-network\n \ndocker run --network=my-ipvlan-network --ip=192.168.0.2 my-container\n在上面的示例中我们创建了一个名为 my-ipvlan-network 的 IPvlan 网络,并将容器连接到该网络。容器被分配了一个 IP 地址192.168.0.2),并使用了宿主机的 eth0 接口。\nMacvlan Network\nMacvlan 是另一种网络连接方式,允许容器直接使用宿主机的网络接口,并为每个容器分配独立的 MAC 地址。与 IPvlan 类似Macvlan 也提供了更好的性能和更低的延迟。\n在 Macvlan 中,有三种模式可供选择:\n\n桥接模式Bridge mode容器使用宿主机的网络接口并分配一个独立的 MAC 地址。这种模式适用于需要容器与外部网络直接通信的场景。\nVEPA 模式Virtual Ethernet Port Aggregator mode容器使用宿主机的网络接口并分配一个独立的 MAC 地址。这种模式适用于需要容器与外部网络通信,并且需要在物理网络上进行流量分析的场景。\nPrivate 模式:容器使用宿主机的网络接口,并分配一个独立的 MAC 地址。这种模式适用于需要容器与外部网络通信,但不需要与其他容器直接通信的场景。\n\n使用 Macvlan 连接容器\n要在 Docker 中使用 Macvlan 连接容器,需要满足以下要求:\n\n宿主机的内核版本必须支持 Macvlan。\n宿主机的网络接口必须支持 promiscuous 模式。\n\n以下是使用 Macvlan 连接容器的示例命令:\ndocker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=eth0 my-macvlan-network\n \ndocker run --network=my-macvlan-network --ip=192.168.0.2 my-container\n在上面的示例中我们创建了一个名为 my-macvlan-network 的 Macvlan 网络,并将容器连接到该网络。容器被分配了一个 IP 地址192.168.0.2),并使用了宿主机的 eth0 接口。\nNone 网络\nNone 网络模式是一种特殊的网络模式,它表示容器不连接到任何网络。在这种模式下,容器只能与它自己隔离,并且无法与其他容器或外部网络进行通信。这种模式适用于一些特殊的使用场景,例如需要在容器中运行一些网络隔离的工具或测试环境。\n要在容器中使用 None 网络模式,可以在运行容器时使用 --network none 参数:\ndocker run --network none my-container\n自定义网络\nDocker 允许用户创建自定义网络,以满足特定的网络需求。自定义网络可以提供更好的隔离性、灵活性和可管理性。\n1. 创建自定义网络\n首先确定你需要的网络类型。Docker 支持多种网络类型例如bridge、overlay、macvlan但对于大多数单宿主场景bridge 类型是最常用的。\n可以使用以下命令创建具有自定义子网和网关的 bridge 类型网络:\ndocker network create --driver bridge --subnet=192.168.1.0/24 --gateway=192.168.1.1 my-custom-network\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--driver指定网络的驱动类型。常用的驱动有 bridge、overlay、macvlan 等。--subnet定义网络的 IP 地址范围。例如,--subnet=192.168.1.0/24 指定了一个包含 256 个可能 IP 地址的网络。--ip-range指定允许分配给容器的 IP 地址范围。它必须在 --subnet 指定的范围内。--gateway定义网络的网关地址。容器将使用这个地址作为出口网关。--aux-address为网络上的特定用途保留 IP 地址。例如,可以为网络服务保留地址。--ipam-driver指定 IP 地址管理IPAM驱动默认是 default。--ipam-opt传递给 IPAM 驱动的选项。--opt 或 -o设置驱动特定的选项和参数。例如-o com.docker.network.bridge.name=docker1 可以设置桥接网络的名称。--label为网络添加元数据标签。\n2. 指定容器的网络设置\n在你的自定义网络中启动容器时可以使用 --ip 选项为容器指定一个固定的 IP 地址:\ndocker run -d --name my-container --network my-custom-network --ip=192.168.1.5 nginx\n确保指定的 IP 地址在 --subnet 指定的范围内。\n如果需要可以在启动容器时通过 --dns 选项指定一个或多个 DNS 服务器:\ndocker run -d --name my-container --network my-custom-network --dns=8.8.8.8 nginx\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--dns设置容器使用的 DNS 服务器的 IP 地址。--dns-search设置容器 DNS 搜索域名用于解析未完全限定的域名FQDN。--dns-option设置容器 DNS 解析器的内部选项。\n3. 管理和验证网络配置\n创建网络和容器后可以使用以下命令查看网络的详细信息验证配置是否正确\ndocker network inspect my-custom-network\n这将显示网络的配置详情包括分配给网络中容器的 IP 地址。\n为了测试容器间的网络通信可以在两个或更多容器之间进行 ping 测试,确保它们能够相互通信。\nDocker Swarm 模式下的网络\nDocker Swarm 是 Docker 的集群管理和编排工具,用于在多个 Docker 守护进程上运行和管理容器。在 Docker Swarm 模式下,网络的管理和配置与单个 Docker 守护进程的方式有所不同。Docker Swarm 提供了一种名为 Overlay 网络的特殊网络类型,用于实现跨主机容器的通信。\nOverlay 网络\nOverlay 网络是一种多主机网络,它允许在 Docker Swarm 集群中的多个节点上创建和管理网络。Overlay 网络使用 VXLANVirtual Extensible LAN技术来实现容器之间的通信提供了跨主机的网络隔离和连接。\n要创建一个 Overlay 网络,需要先初始化一个 Docker Swarm 集群,然后使用以下命令创建网络:\ndocker network create --driver overlay my-overlay-network\n这将创建一个名为 my-overlay-network 的 Overlay 网络。\n在 Overlay 网络中启动服务\n在 Overlay 网络中启动服务与在普通网络中启动服务类似,只需将服务加入到 Overlay 网络即可。以下是一个示例命令:\ndocker service create --name my-service --network my-overlay-network nginx\n这将在 Swarm 集群中启动一个名为 my-service 的服务,并将其加入到 my-overlay-network 网络中。服务将在 Swarm 集群中的多个节点上运行,并通过 Overlay 网络进行通信。\n跨主机通信\n在 Overlay 网络中容器可以跨主机进行通信无需显式配置。Docker Swarm 使用内置的路由和负载均衡机制来处理跨主机通信。\n例如如果在 Swarm 集群中有两个节点,分别是 Node1 和 Swarm 节点上的网络管理有一些特殊考虑。\nOverlay 网络\nOverlay 网络是 Docker Swarm 模式下的一种网络类型,它允许在多个 Swarm 节点之间创建跨主机的容器网络。Overlay 网络提供了容器之间的透明通信,并支持容器的动态伸缩和服务发现。\n要创建一个 Overlay 网络,可以使用以下命令:\ndocker network create --driver overlay my-overlay-network\n在创建 Overlay 网络时Docker 会自动配置网络的路由和负载均衡,使得容器可以在不同的 Swarm 节点上进行通信。\n跨主机通信\n在 Docker Swarm 模式下,容器可以在不同的 Swarm 节点上运行。为了实现跨主机的容器通信,需要使用 Overlay 网络。\n以下是在 Swarm 模式下实现跨主机通信的一般步骤:\n\n\n创建一个 Overlay 网络:\ndocker network create --driver overlay my-overlay-network\n\n\n在 Swarm 中创建服务:\ndocker service create --name my-service --network my-overlay-network my-image\n这将在 Swarm 中创建一个名为 my-service 的服务,并将其连接到 my-overlay-network 网络。\n\n\n根据需要进行扩展\ndocker service scale my-service=3\n这将将 my-service 服务的副本数扩展到 3 个。\n\n\n验证容器间的通信\ndocker exec -it <container_id> ping <container_name>\n使用上述命令在一个容器中执行 ping 命令,以验证与另一个容器的通信。\n\n\n负载均衡\n在 Docker Swarm 模式下Overlay 网络提供了内置的负载均衡功能。当多个副本的服务容器运行在不同的 Swarm 节点上时Docker 会自动将流量分发到这些容器上,实现负载均衡。\n负载均衡是通过 Swarm 内部的 DNS 解析和代理实现的。当一个服务容器被创建时Docker 会自动为该容器分配一个虚拟 IP 地址,并将其注册到内部 DNS 服务中。当其他容器或外部客户端访问该服务时DNS 解析会将请求路由到可用的服务副本上。\n操作示例\n下面是一个在 Docker Swarm 模式下创建 Overlay 网络和服务的操作示例:\n\n\n创建一个 Overlay 网络:\ndocker network create --driver overlay my-overlay-network\n\n\n构建一个包含 Web 应用的镜像:\ndocker build -t my-web-app .\n\n\n将镜像推送到 Docker 镜像仓库:\ndocker push my-web-app:latest\n\n\n在 Swarm 中创建一个服务:\ndocker service create --name my-service --network my-overlay-network -p 8080:80 my-web-app\n这将在 Swarm 中创建一个名为 my-service 的服务,并将其连接到 my-overlay-network 网络。同时,将容器内部的 80 端口映射到宿主机的 8080 端口上,以便从外部访问该服务。\n\n\n验证服务是否正常运行\ncurl http://localhost:8080\n如果一切正常你应该能够看到 Web 应用返回的内容。\n\n"},"Technology/OperatingSystem/Linux/1.文化/GNU-and-Linux-历史与发展":{"title":"GNU&Linux 历史与发展","links":[],"tags":["Linux/文化","技术/操作系统"],"content":"概述\nGNU/Linux 是一个开源操作系统和 IT 基础架构平台。Linux 内核由 Linus Torvalds 于 1991 年构思设计而成最初这只是他的一项兴趣爱好。如今GNU/Linux 不仅是公共互联网服务器上最常用的操作系统,还是速度排名前 500 的超级电脑上使用的唯一一款操作系统同时GNU/Linux 也广泛地运用在智能移动设备和嵌入式终端上。\nGNU/Linux 也是自由软件和开放源代码软件发展中最著名的例子。只要遵循 GNU 通用公共许可证GPL任何个人和机构都可以自由地使用 GNU/Linux 的所有底层源代码,也可以自由地修改和再发布。大多数 GNU/Linux 系统还包括像提供 GUI 的 X Window 之类的程序。\n如果提及 GNU/Linux 就不得不了解 UNIX 与 GUN 计划,以及它们之间是如何相爱相杀、互相成就的。\nUnix 的诞生和演变\nUNIX非复用信息和计算机服务Uniplexed Information and Computing ServiceUnICS操作系统是一个强大的多用户、多任务操作系统支持多种处理器架构按照操作系统的分类属于分时操作系统最早由肯·汤普逊、丹尼斯·里奇和道格拉斯·麦克罗伊于 1969 年在 AT&T 的贝尔实验室开发。\n目前它的商标权由国际开放标准组织所拥有只有符合单一 UNIX 规范的 UNIX 系统才能使用 UNIX 这个名称,否则只能称为类 UNIXUNIX-like。\n1965 年贝尔实验室计划要创建一套多用户、多任务、多层次multiuser、multiprocessor、multilevel的 MULTICS 操作系统。贝尔实验室参与了这个操作系统的研发但因为开发速度太慢1969 年贝尔实验室决定退出这个计划。贝尔实验室的工程师,肯·汤普逊和丹尼斯·里奇,在此时自行开发了 Unix。\n1974 年,汤普逊和里奇合作在 ACM 通信上发表了一篇关于 UNIX 的文章,这是 UNIX 第一次出现在贝尔实验室以外。此后 UNIX 被政府机关,研究机构,企业和大学注意到,并逐渐流行开来。\n在此后的 10 年Unix 在学术机构和大型企业中得到了广泛的应用,当时的 UNIX 拥有者 AT&T 公司以低廉甚至免费的许可将 Unix 源码授权给学术机构做研究或教学之用许多机构在此源码基础上加以扩展和改进形成了所谓的“Unix 变种”,这些变种反过来也促进了 Unix 的发展其中最著名的变种之一是由加州大学柏克莱分校开发的伯克利软件套件BSD产品。\n后来 AT&T 意识到了 Unix 的商业价值,于 1983 年发布 Unix 第一个商业版本 System V。便不再将 Unix 源码授权给学术机构,并对之前的 Unix 及其变种声明了著作权权利。故开始了一场持久的著作权官司,直至 AT&T 将自己的 Unix 系统实验室卖掉。\n新接手的 Novell 采取了一种比较开明的做法,允许柏克莱分校自由发布自己的 Unix 变种,但是前提是必须将来自于 AT&T 的代码完全删除,于是诞生了 4.4 BSD Lite 版,由于这个版本不存在法律问题,**4.4 BSD Lite 成为了现代柏克莱软件包的基础版本。**所以从这个角度上4.4 BSD 又是所有自由版本 Unix 的基础,\n后续 BSD 在发展中也逐渐派生出 3 个主要的分支FreeBSD、OpenBSD 和 NetBSD。\n外部链接UNIX的完整历史\n\nGNU 项目的历史和目标\n1983 年AT&T 发布了 Unix 最新版 system V这是一个商业化版本付费才能使用并且不得传播源码。正是因为看到了 Unix 被商业化,所以 1983 年 9 月 27 日由理查德·斯托曼在麻省理工学院公开发起 GNU 计划。\nGNU 计划 的基本目标和一贯目标是提供一个和 Unix 兼容的 100% 自由软件的操作系统。不是 95%、也不是 99.5%、而是 100% 自由。这个系统的名字叫 GNU是 GNUs Not Unix 的首字母递归缩写——这是对 Unix 的技术思想致敬的一种方法,同时表达 GNU 有所不同。从技术上说GNU 很像 Unix。但是它不同于 UnixGNU 给予其用户自由。\n1985 年,理查德·斯托曼创立了自由软件基金会来为 GNU 计划提供技术、法律以及财政支持。到了 1990 年GNU 计划已经开发出的软件包括了一个功能强大的文字编辑器 Emacs、C 语言编译器 GCC 以及大部分 UNIX 系统的程序库和工具。唯一依然没有完成的重要组件,就是操作系统的内核(称为 HURD。\n**1991 年Linus Torvalds 编写出了与 UNIX 兼容的 Linux 操作系统内核并在 GPL 下发布。**GNU/Linux 之后在网上广泛流传。1992 年Linux 与其他 GNU 软件结合,完全自由的操作系统正式诞生。许多程序员参与了 Linux 的开发与修改,也经常将 Linux 当成开发 GNU 计划软件的平台。该操作系统往往被称为“GNU/Linux”或简称 Linux。\n但 Linux 本身不属于 GNU 计划的一部分GNU 计划自己的内核 Hurd 依然在开发中,目前已经发布 Beta 版本。\nLinux 的诞生和发展\n1991 年Linus Torvalds 在赫尔辛基大学上学时,对操作系统很好奇。他对 MINIX 只允许在教育上使用很不满(在当时 MINIX 不允许被用作任何商业使用),于是他便开始写他自己的操作系统,这就是后来的 Linux 内核。\n\nLinus Torvalds 曾笑言:我要是知道有 BSD那我就不开发 Linux 了。\n\nLinux 的标志和吉祥物是一只名字叫做 Tux 的企鹅,标志的由来有一说是因为 Linus 在澳洲时曾被一座动物园里的企鹅咬了一口,便选择企鹅作为 Linux 的标志,但更容易被接受的说法是:企鹅代表南极,而南极又是全世界所共有的一块陆地。这也就代表 Linux 是所有人的 Linux。\n1994 年 3 月Linux1.0 版正式发布Marc Ewing 成立 Red Hat 软件公司,成为最著名的 Linux 经销商之一。\n今天由 Linus Torvalds 带领下,众多开发人员共同参与开发和维护 Linux 内核。理查德·斯托曼领导的自由软件基金会,继续提供大量支持 Linux 内核的 GNU 组件。一些个人和企业开发的第三方的非 GNU 组件也提供对 Linux 内核的支持,这些第三方组件包括大量的作品,有内核模块和用户应用程序和库等内容。\nLinux 发行版指的就是通常所说的 Linux 操作系统,它一般是由一些组织、团体、公司或者个人制作并发行的。\nLinux 内核主要作为 Linux 发行版的一部分而使用。通常来讲,一个 Linux 发行版包括 Linux 内核,以及将整个软件安装到电脑上的一套安装工具,还有各种 GNU 软件,和其他的一些自由软件,在一些 Linux 发行版中可能会包含一些专有软件。\n发行版为许多不同的目的而制作包括对不同电脑硬件结构的支持对普通用户或开发者使用方式的调整针对实时应用或嵌入式系统的开发等等。目前超过三百个发行版被积极的开发最普遍被使用的发行版有大约十多个。较为知名的有 Debian、Ubuntu、Fedora、CentOS、Arch Linux 和 openSUSE 等。\n\nGNU/Linux 的特点和优势\n跨平台的硬件支持\n由于 Linux 的内核大部分是用 C 语言编写的,并采用了可移植的 Unix 标准应用程序接口,所以它支持如 i386、Alpha、AMD 和 Sparc 等系统平台,以及从个人电脑到大型主机,甚至包括智能移动设备和嵌入式设备在内的各种硬件。\n外部链接开源操作系统比较\n支持的平台\n\n支持的硬件\n\n支持的网络\n\n网络技术\n\n支持的文件系统\n\n支持的文件系统特性\n\n安全特性\n\n低资源占用下良好的稳定性\nLinux 内核的源代码是以标准规范位数的计算机来做的最佳化设计,既可确保其系统的稳定性,也能使在系统上运行的要求比 Windows 或 macOS 低。有些发行版适用于可追溯到 Pentium 系列的 CPU另一些发行版则仅需要 1 GB 以下的 RAM。正因为 Linux 的低资源占用和稳定,才使得一些安装 Linux 的主机像 Unix 机一样常年不关而不曾宕机。\n高效的文件系统\nLinux 秉持了「一切皆文件」的 Unix 哲学,几乎兼容了所有市面上主流的文件系统;它们不但可以对文件设置权限,实施完全的保护,而且可以达到「越用越整齐」,「越用碎片越少」;使用 Linux 完全不需要什么「管家」或者「大师」。\n可靠的安全性\nLinux 系统的核心代码是开源的,对用户完全透明,这意味着你的 Linux 系统漏洞更少。同时,由于 Linux 有着各种各样的不同版本,这也提高了被攻击的难度。你可以在选择更新时通过签名检查进行严格的细粒度控制,大多数的发行版在系统更新时都默认强制安全检查。\n此外它采取了很多包括读写权限控制、带保护的子系统、审计跟踪、核心授权的安全措施这为网络环境中的用户提供了安全保障。当一个病毒在 Linux 下被恶意发布,几个小时后所有的发行版都已经接种了疫苗。你可能很难找到那些每天都提供更新的单一主流操作系统,但是这样的 Linux 发行版却有很多。\n完善纯净的软件包管理机制\n大部分 Linux 发行版都具有特定的软件包管理工具(类似于无需注册帐号的 App Store具有易于安装更新和卸载的特性并起到了保护配置文件的作用不需要处理依赖关系也不容易对系统造成污染。同时由于其开源的特点相较 Windows 和 macOS 里你那些平时用不到却会在每次大版本升级后「卷土重来」的预置应用,在 Linux 里你可以卸载一切不想安装在系统里的预置应用。\n随心所欲定制 UI\n在 Linux 系统中,你可以对系统功能进行任意更改。 Linux 生态系统中的核心项目之一就是桌面环境——它是一些由基础的用户程序和可视化元素组成的一个集合,比如状态栏和启动器,这些元素构成了用户与计算机的一个交互界面。在 Linux 系统中,用户都可以随意更换他们喜欢的桌面环境。\n社区的支持\nLinux 系统拥有一个团结且友好型的社区。由于 Linux 在桌面系统是一个相对小众的桌面操作系统,仅占有 3% 左右的市场份额因此Linux 社区更希望有更多的潜在用户加入进来。Linux 系统有很多的用户论坛,尤其是对新手比较友好的论坛,它包括非常丰富且全面的知识来帮助用户解决一些基本的系统问题。很多高级用户更倾向于定制 Linux 系统,因此那些 Linux 发行版都拥有非常非常详尽维基文档,以指导用户完成高级的系统应用项目。\n开源\n因为开源的特性多数 Linux 发行版都会去中心化在全球部署镜像,平时在 Windows 和 macOS 的更新下载不稳定?在 Linux 设置中更换为本地的镜像源便无须担心。"},"Technology/OperatingSystem/Linux/1.文化/GNU-and-Linux-社区与文化":{"title":"GNU&Linux 社区与文化","links":[],"tags":["Linux/文化","技术/操作系统"],"content":"官方社区\n官方讨论社区\nLinux.org 是一个广泛的 Linux 讨论和学习社区,提供了丰富的信息资源,包括新闻、教程、论坛讨论和详尽的 Linux 发行版目录。无论你是 Linux 新手还是经验丰富的用户,都可以在这个社区找到有用的信息和交流的机会。\n内核归档社区\nKernel.org 是 Linux 内核的主要分发点,你可以在这个网站上找到最新的 Linux 内核源代码,以及与内核相关的各种信息,包括发布日志、维护者信息、补丁提交指南等。这是一个面向内核开发者和高级用户的社区。\nGNU 项目社区\nGNU.org 是 GNU 项目的官方网站,你可以在这里找到关于 GNU 操作系统、GNU 许可证和自由软件哲学的所有信息。这个网站还包括了一个开放的社区其中包括各种邮件列表、IRC 频道和论坛,供 GNU 用户和开发者进行交流。\n自由软件基金会\nFree Software Foundation (FSF) 是一个致力于自由软件事业的非营利性组织其官方网站提供了丰富的关于自由软件的信息和资源包括新闻、活动、项目、法律资源和教育资源等。作为自由软件运动的中心FSF 社区也为用户、开发者和支持者提供了一个交流和协作的平台。www.fsf.org/)\nLinux 基金会\nLinux 基金会 旨在推动 Linux 和开源生态系统的增长。它主办各种技术峰会,发布研究报告,同时也主导了多个重要的开源项目,比如 CNCF云原生计算基金会LF AILinux 基金会人工智能Hyperledger 等。\n开源社区\nDebian 社区\n\n\nDebian 是一个由普罗大众组成的社区!\n\n概述\n在 1993 年 8 月Ian Murdock 开始着手创建一个遵循 Linux 和 GNU 理念的、开放的操作系统。他向其他软件开发人员发出了一份公开邀请,希望他们能为一个基于 Linux 内核的新发行版作出贡献,当时的 Linux 内核仅仅还在起步阶段。\nDebian 项目最初是一个由自由软件爱好者组成的和谐小团体后来逐渐发展成为一个由开发者、贡献者和用户组成的庞大且组织良好的社区。Debian 的设计目标是创建一个各组件能够紧密协作、并得到精心维护和支持的系统,同时积极接纳来自自由软件社区的开放设计、贡献和支持。\n特色\n**Debian 以其坚守 Unix 和自由软件的理念,以及给用户提供的丰富选择而闻名。**至今Debian 提供了超过 25,000 个软件,超过 50,000 个软件包,并正式支持 10 个计算机系统架构。众多知名的 Linux 发行版,例如 Ubuntu、Knoppix 和 Deepin也都基于 Debian GNU/Linux 构建。\nDebian 社区下设有多个采用不同操作系统内核的子项目:\n\n主要项目是采用 Linux 内核的 Debian GNU/Linux。\n采用 GNU Hurd 内核的 Debian GNU/Hurd。\n采用 FreeBSD 内核的 Debian GNU/kFreeBSD。\n\nDebian 主要有三个版本稳定版stable、测试版testing、不稳定版unstable。\nDebian 稳定版通常每两年发布一次,每个版本从发布之日起会得到大约三年的正式支持。期间,系统会不定期得到小版本更新以及持续的安全更新以修复已知的重要问题。\n自 Debian 6 开始Debian 也推出了长期支持LTS计划为每个稳定版在三年支持期结束后提供额外两年的安全更新支持但不再提供小版本更新。这意味着每个稳定版的用户可以享受总计五年的安全更新支持。\n\n社区评价\nDebian Project 是一个独立运作的项目,不受任何商业性质的影响,并且不依赖任何商业公司或者机构,这使得 Debian 能够坚持自由软件的理念和独特风格。因为 Debian 不受任何商业公司或者机构控制,所以它不会为了迎合商业利益而牺牲用户权益,也不会因为公司运营不善或者商业模式转换等因素影响开发进度。这些特性使得 Debian 在众多的 GNU/Linux 发行版中独树一帜。\n一些用户批评 Debian 的发布周期过长,这可能导致稳定版中的软件包版本较旧。由于 Debian 的设计理念主要考虑稳定性,因此它的发行版通常更适合“静态”环境(例如服务器或开发环境),在这些环境中,用户通常只需要安全更新,而不需要最新的软件版本。\n另外因为 Debian 对于自由软件的严格标准,有些软件和文件并未出现在 Debian 的官方包库中。例如mplayer 曾经就未被收录为 Debian 的官方包。同样地,也有人批评 Debian 将一些专有软件放到“非自由”包库中而没有完全排除这些软件。过去Debian 在其“主要”main包库中同时包含自由和非自由的软件包但现在已将非自由的软件例如专有的驱动程序移至不同的包库中。\nArch 社区\n\n\nArch 之道Keep It Simple, Stupid\n\n概述\n由加拿大程序设计师兼吉他手 Judd Vinet 从 2001 年早期开始开发 Arch Linux并在 2002 年 3 月 11 日正式发行 0.1 版。2007 下半年Vinet 退出了 Arch Linux 的开发,项目由 Aaron Griffin 接手并继续推进。\n特色\n\n简洁Arch Linux 主张避免任何不必要的添加、修改和复杂性增加,致力于提供一个最小化、高度可定制的平台。\n现代Arch 采用滚动升级策略,始终保持软件处于最新的稳定版本。只要系统软件包不出现破损,都会使用最新版本。安装一次,随时升级,享受最新的软件和特性。\n实用Arch 注重实用性,避免无谓的意识形态争辩。最终的设计决策都是由开发者基于事实的技术分析和讨论来决定的,不受流行观点和政治因素的影响。\n以用户为中心Arch Linux 一直坚持以用户为中心,更关注满足贡献者的需求,而非只是吸引尽可能多的用户。\n\n这四点可以概括为 Arch 之道由简洁、现代、实用、以用户为中心构成,或许最好的结词是 Keep It Simple, Stupid。\n社区评价\nArch Linux 是一款具有极度定制化特性的操作系统,允许用户根据个人需求和偏好配置,显著区别于像 Ubuntu 和 Fedora 这类预装大量软件的发行版。同时通过采取滚动升级模型Arch Linux 确保了社区成员能始终使用到最新的软件包,只要他们定期进行系统更新。\n社区为 Arch Linux 打造了丰富的 Wiki 和用户资源库不仅提供了全面的操作系统安装和维护信息还有一个大型的社区驱动的软件仓库为用户提供了极其丰富的资源。然而也必须注意到Arch Linux 作为一款面向中高级用户的系统,其入门门槛可能相对较高,对于 Linux 新手可能会有一定挑战。\nopenSUSE 社区\n\n\n桌面用户、开发者以及系统管理员的匠之所选。\n\nopenSUSE 是一款基于 Linux 的开源操作系统对稳定性和易用性有着深远的追求。它是一款多用途的发行版能够满足各种类型的用户需求。openSUSE 项目由国际 IT 企业 SUSE 赞助并支持,该公司也为 openSUSE 提供了商业版本,即 SUSE Linux Enterprise Server (SLES)。\nopenSUSE 以其出色的硬件兼容性、清晰的配置工具和卓越的用户文档而受到广泛赞誉。项目发布两种版本的 openSUSE分别为 openSUSE Leap稳定版本和 openSUSE Tumbleweed滚动更新版本。\n特色\nYaST\nopenSUSE 包含一个称为 YaSTYet another Setup Tool的系统配置工具它是一个功能全面的配置工具允许用户以图形界面或命令行界面对系统进行设置和修改。YaST 是 openSUSE 的一大亮点,极大地方便了系统的管理和配置。\n稳定性和易用性\nopenSUSE 的设计注重稳定性和易用性,使其成为 Linux 初学者的理想选择。开发者社区提供大量的教程和文档,帮助新用户解决问题。\n发布版本\nopenSUSE 提供两种版本的发行版,分别为 openSUSE Leap 和 openSUSE Tumbleweed。Leap 是定期发布的稳定版本强调稳定性和兼容性。Tumbleweed 是滚动更新版本,为了追求最新的软件和功能,采用了持续更新的模式。\n社区评价\nopenSUSE 是世界上最受欢迎的 Linux 发行版之一,它以其易用性、稳定性和全面的特性受到了用户的高度赞誉。开发者社区活跃,而且对新手友好,提供了大量的教程和文档来帮助新用户解决问题。\n虽然 openSUSE 是一个强大且易于使用的系统但是有些用户反映openSUSE 的软件包可能不如一些其他的发行版更新得那么及时,这可能会让一些追求最新软件的用户感到失望。此外,一些用户也反映 YaST 有时候对于高级用户来说过于复杂。\n\n商业社区\nRedHat 社区\n\n\n世界领先的企业级开源解决方案供应商。\n\n概述\n红帽Red Hat是美国一家以开发、贩售 Linux 发行版本并提供技术服务为业务内容的企业,其著名的产品为 Red Hat Enterprise Linux。\n1990 年代末期Linux 以自由软件和开放源代码的理念挑战商业且闭源的 Windows 在操作系统市场的霸主地位。适时地Red Hat 推出了 Linux 系统与软件集成包——Red Hat Linux满足了市场的需求从而奠定了 Red Hat 在 Linux 业界的领导地位。\n截至 2008 年Red Hat 在提供 Linux 集成服务的同类企业中规模最大。Red Hat 于 1999 年 8 月 11 日在纳斯达克上市2005 年 12 月 19 日纳入纳斯达克 100 指数2006 年 12 月 12 日转到纽约证券交易所挂牌。2018 年 10 月 28 日IBM 以每股 190 美元的现金收购 Red Hat 所有已发行股份,总价值约为 340 亿美元。目前红帽的产品涉及五大技术领域:云计算、存储、虚拟化、中间件、操作系统。\nFedora\n\nFedora Linux第七版以前为 Fedora Core是较具知名度的 Linux 发行包之一,由 Fedora 项目社群开发红帽公司赞助。其目标是创建一个新颖、多功能且自由开放源代码的操作系统。Fedora 是商业化的 Red Hat Enterprise Linux 发行版的上游源码。\n最早Fedora Linux 社群的目标是为 Red Hat Linux 制作并发布第三方的软件包。然而,当免费的 Red Hat Linux 停止发行后Fedora 社群整合到了 Red Hat 赞助的 Fedora 项目。新的目标是开发一个由社群支持的操作系统。Red Hat Enterprise Linux 则取代了 Red Hat Linux成为官方支持的系统版本。\n\nRed Hat Enterprise Linux\n\nRed Hat Enterprise LinuxRHEL是一个由 **Red Hat 开发的面向商业市场的 Linux 发行版。**红帽公司从 Red Hat Enterprise Linux 5 开始,为每个版本的企业版 Linux 提供 10 年的支持。RHEL 是常用的非官方简称。Red Hat Enterprise Linux 约每 3 年发布一个新版本。起初Red Hat Enterprise Linux 基于 Red Hat Linux但使用较为保守的发布周期。后来的版本都是基于 Fedora。\n\nCentOS\n\nCentOSCommunity Enterprise Operating System是 Linux 发行版之一,它是基于 Red Hat Enterprise LinuxRHEL依照开放源代码规定发布的源代码所编译而成。因为源于相同的源代码因此许多需要高度稳定性的服务器选择 CentOS 替代商业版的 Red Hat Enterprise Linux。CentOS 和 RHEL 的主要区别在于CentOS 并不包含封闭源代码软件,它的主要修改是为了移除不能自由使用的商标。\nCentOS 开发团队于 2020 年 12 月 8 日宣布,传统的 CentOS 8 将仅维护至 2021 年底,之后仅维护 CentOS Stream使其变为滚动发行的散布版。\nRHEL、CentOS 和 Fedora 的关系\n**RHEL、CentOS 和 Fedora 的相似之处都是基于 2004 年停产的 Red Hat Linux。**RHEL、CentOS 和 Fedora 的区别在于CentOS 是社区开发的 RHELFedora 是面向社区、快节奏的 RHEL 上游贡献者RHEL 则是基于 Fedora 的企业稳定版。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n免费下载免费使用技术支持 (商业)RHEL否否付费提供CentOS是是不提供Fedora是是不提供\nUbuntu 社区\n\n\n我的存在是因为大家的存在。\n\n概述\n**Ubuntu 是一个基于 Debian 的 Linux 发行版,以桌面应用为主。**Ubuntu 主要有三个版本:桌面版、服务器版和专为物联网设备及机器人设计的 Core 版。\nUbuntu 由英国的 Canonical 公司发布并提供商业支持。Canonical 公司由南非企业家 Mark Shuttleworth 创立,该公司通过销售 Ubuntu 相关的技术支持和其他服务来产生收益。Ubuntu 项目坚守开源软件开发原则,鼓励使用、研究、改进和分发自由软件。\nUbuntu 是目前用户数最多的 Linux 发行版之一。Ubuntu 每六个月发布一个新版本每两年发布一次长期支持LTS版本。非 LTS 版本的支持期为 9 个月,而 LTS 版本的支持期为 5 年。\n特色\n系统管理\nUbuntu 的一个独特之处在于所有系统相关任务都需要使用 sudo 指令,这比传统的以系统管理员账户进行管理的方式更安全。这是 Linux 和 Unix 系统的基本设计理念之一。Windows 在其新版本中也引入了类似的 UAC用户账户控制机制。\n开发理念\nUbuntu 强调易用性和国际化使其能够被更多的人使用。Ubuntu 在 5.04 版本发布时,就已将 UnicodeUTF-8设为系统默认编码以应对全球各地不同的语言和文字符号努力为用户提供一个无乱码的交流平台。在语言支持方面Ubuntu 是 Linux 发行版中的佼佼者。\n发布周期\nUbuntu 每 6 个月发布一个新版本每个版本都有自己的代号和版本号。长期支持版本LTS每两年发布一次它的更新和维护时间相对较长。\n\n社区评价\n在 2005 年伦敦举行的 Linux 世界论坛及会议LinuxWorld Conference and ExpoUbuntu 被读者选为最佳 Linux 发行版。\nUbuntu 虽源自 Debian但 Debian 的创始人 Ian Murdock 对 Ubuntu 提出了批评。他认为 Ubuntu 虽然是一款优秀的 Linux 发行版,推动了 Debian 的全球化,**但 Ubuntu 开发的软件包并未直接改进 Debian 的现有软件包,因此产生了与 Debian 不兼容的问题。**他希望 Ubuntu 能与 Debian 进行更为紧密的合作,使其改进也可以被 Debian 所采用。\n2010 年欧洲 GUADEC 会议上公布的“GNOME 开发者分布”表明Ubuntu 的母公司 Canonical 对 GNOME 项目的贡献很小。此事引发了一些人的不满,他们认为 Canonical 应该做出更大的贡献。前 Red Hat 开发者 Greg DeKoenigsberg 就批评 Canonical 是一家伪装成技术企业的营销公司虽然他后来为此道歉但仍然坚持Canonical 应该为 Linux 社区做出更大的贡献。\n由于 Ubuntu 基于 Debian 的不稳定分支sid所以在使用过程中用户可能会遇到一些内部错误。\n由于 Canonical 帮助微软开发了 Windows 下的 Linux 兼容层Windows Subsystem for LinuxWSL部分用户认为这是背叛了 Linux 社区。\n特色社区\nKali Linux 社区\n\n\nThe most advanced Penetration Testing Distribution\n\n概述\nKali Linux 是一款源自 Debian 的开源操作系统,专门为数字取证和渗透测试设计。此操作系统由 Offensive Security 维护和资助。Kali Linux 包含了数百种安全相关的工具,满足专业安全和网络测试人员的需求。\nKali Linux 系统被设计成满足所有的渗透测试需求,包含了静态二进制分析到后门的嵌入等多种工具。\n特色\n安全工具\nKali Linux 操作系统包括了一套广泛的安全和取证工具,它们在系统安装时即被预先安装,以便用户随时使用。这些工具包括 Aircrack-ng、Nmap、Wireshark、John the Ripper、Burp suite 和 OWASP ZAP 等等。\n系统设计\nKali Linux 系统专为安全专家设计,主要在网络安全和信息安全审计领域应用。这使得 Kali Linux 成为那些需要进行系统渗透测试、网络防御、计算机取证、安全研究等工作的人员的理想选择。\n定制性\nKali Linux 具有很高的定制性,允许用户定制自己的 Kali Linux 发行版,包括选择安装的工具,修改 Kali Linux ISO 图像等。\n社区评价\nKali Linux 作为一个专注于网络安全的操作系统,在网络安全领域的用户之间赢得了极高的赞誉。它为安全专业人员和热衷于安全的爱好者提供了一个集成了所有主要的安全工具的平台。\n尽管 Kali Linux 的功能强大但它并不适合所有的用户。由于其主要针对的是安全专家因此对于初学者和非专业人士来说Kali Linux 可能会感到复杂和难以管理。此外,使用 Kali Linux 所包含的一些工具可能需要合法的授权,否则可能会违反某些地方的法律规定。因此,使用 Kali Linux 需要对安全和法律问题有充分的认识。\nTails 社区\n\n\nTails is a portable operating system that protects against surveillance and censorship.\n\n概述\nTailsThe Amnesic Incognito Live System是一个基于 Debian 的操作系统,专注于提供个人隐私保护和匿名性,并封锁所有非匿名通信。所有的外部通信都会被强制通过 Tor 网络进行传输为了最大程度地确保用户的隐私安全。Tails 是一个可以通过 Live DVD 或 Live USB 启动的系统其设计原则是在非显式用户操作下不留下任何数据痕迹。Tails 项目得到了 Tor Project 的经济支持。\n特色\n隐私和匿名性\nTails 的核心理念是提供一个全匿名的操作环境,并通过使用 Tor 网络,使用户在浏览互联网时可以难以被追踪。它包含了众多预安装的隐私工具,如匿名浏览器 Tor Browser加密邮件客户端 Thunderbird文件加密和隐藏工具等。\n” 遗忘性 ” 系统\nTails 是一个 ” 遗忘性 ” 的系统。这意味着,除非显式地保存,否则系统在关机后不会保留任何用户数据。这对于需要在不留下任何痕迹的情况下使用计算机的用户来说,是非常有用的。\n轻型系统\nTails 是一个轻量级的操作系统,可以在 Live DVD 或 Live USB 上运行。这使得用户可以在任何支持引导的计算机上,使用包含完整操作环境的 Tails。\n社区评价\nTails 社区以其对隐私保护的坚定承诺而受到高度赞誉。**它是对抗互联网审查,特别是在网络审查严格的国家和地区的重要工具。**然而,由于 Tails 的这些特性,它也可能被用于非法活动,这引发了一些关于如何平衡隐私权和社会责任的讨论。\n由于 Tails 的使用有一定的技术门槛,使得不熟悉技术的用户可能难以上手。尽管 Tails 社区提供了详细的使用指南,但是由于 Tails 的安全特性,一些常见的用户体验可能会受到影响。此外,由于所有的网络流量都通过 Tor 网络,所以网络连接速度可能会较慢。\n中国社区\nDeepin 社区\n\n\n漂亮的设计、贴心的人机交互、安全友好的社区环境让您感觉宾至如归。\n\n概述\nDeepin深度操作系统是一个来自中国的基于 Debian 的开源操作系统主要以美观和易用性为特点。Deepin 系统由武汉深之度科技有限公司维护和发布。\nDeepin 提供了一个用户友好的、美观的桌面环境,被称为 DDEDeepin Desktop Environment。此外Deepin 还提供了一套自家开发的应用程序,包括深度商店、深度音乐、深度影院等。\n在 2023 年Deepin 发布了 V23 的预览版,包括了三个主要的新特性:全新的仓库,原子更新,和自研的软件包格式 Linglong。\n特色\n\n\n美观的用户界面Deepin 仍然是众多 Linux 发行版中最美观的一个,它的桌面环境和系统应用都经过精心设计,目的是为用户提供一种清新、美观、用户友好的界面。\n\n\n易用性Deepin 注重用户体验,提供了丰富的系统设置和定制选项,使用户能够按照自己的需要和喜好来定制系统。\n\n\n本地化支持Deepin 是最先提供全面中文支持的 Linux 发行版之一,而且也提供了多种语言环境,以满足全球用户的需求。\n\n\nDeepin V23 预览版引入了一些新的特性:\n\n全新的仓库依赖于核心包和一些可选组件预览阶段构建了一个全新的 V23 仓库。deepin 将继续从上游分发(如 Debian 和 Arch Linux中学习。\nLinglong 包格式:这是由 deepin 开发的新包格式,旨在解决 Linux 下传统包格式因复杂依赖关系引起的各种兼容性问题以及通过分散控制权限引起的安全风险。Linglong 可用于任何 Linux 发行版,支持应用程序的增量更新,管理,分发,以及沙盒化应用,这不仅提高了易用性,而且大大保护了用户隐私。\n原子更新这是一种新的系统更新概念可以在系统更新失败时将系统还原到之前的版本从而有效地避免了一些依赖关系安装了但系统没有完全升级的问题。原子更新不依赖于系统安装方法和特定分区并支持升级后的系统回滚。\n\n社区评价\nDeepin 因其美观的用户界面和易用性在用户中享有高度声誉特别是在中国用户中极受欢迎。Deepin 被认为是一款适合新手的 Linux 发行版,因为它极大地降低了 Linux 的学习曲线。\n然而Deepin 也有一些争议,尤其是关于其隐私政策。由于 Deepin 的维护公司位于中国,一些用户担心 Deepin 可能被用于收集用户数据。然而Deepin 是开源的,任何人都可以审计其代码,这就大大减轻了这种担忧。\nOpenEuler 社区\n\n概述\nopenEuler 是基于 Linux Kernel 的开放的企业级 Linux 操作系统软件,具备高安全性、高可扩展性、高性能等技术特性,能够满足客户 IT 基础设施和云计算服务等多业务场景需求。openEuler 拥有三级智能调度,可以将多进程并发时延缩短 60%,而且还可以智能自动有规划,可将 Web 服务器性能提升 137%。\n2021 年 9 月 25 日,面向数字基础设施的开源操作系统 EulerOS「欧拉」全新发布。它以 Linux 稳定系统内核为基础,支持鲲鹏处理器和容器虚拟化技术,是一个面向企业级的通用服务器架构平台。其可广泛部署于服务器、云计算、边缘计算、嵌入式等各种形态设备,应用场景覆盖 IT、CT 和 OT实现统一操作系统支持多设备应用一次开发覆盖全场景。目前欧拉和鸿蒙已经实现了内核技术共享未来在鸿蒙和欧拉之间会共享底层技术使安装两个操作系统的设备可以连接起来打通两个操作系统。\n\n华为服务器操作系统 EulerOS 开源后命名为 openEuler。\n\n特色\nOpenEuler 基于 Linux Kernel 5.10 内核构建,并且在进程调度、内存管理等方面带来了 10 余处创新。\n\n多架构支持如主流的处理器架构和硬件 100% 覆盖,例如 ARM、x86、RISC-V 等。\n全场景覆盖如云原生、大数据、CDN、工业控制等主流应用场景 100% 支持。\n优化性能OpenEuler 通过一系列技术手段优化了系统的运行效率,包括改进内存管理,提升大块内存的处理速度,以及优化内核的抢占模式等。\n新型文件系统OpenEuler 引入了一种名为 Eulerfs 的新型文件系统,它通过创新的技术降低了元数据同步的开销,使得文件系统的性能得到了提升。\n内存分级扩展OpenEuler 可以支持多种内存和存储设备,使得系统的内存容量可以得到扩展,同时降低了内存使用成本。\n云原生调度增强OpenEuler 优化了在云环境中的任务调度,可以保证在线任务能够快速抢占 CPU 资源,同时在内存不足时,优先回收低优先级的进程组的内存,保障在线业务的正常运行。\nKubeOSOpenEuler 实现了一种名为 KubeOS 的容器化操作系统,可以统一管理云原生集群 OS使得操作系统可以轻量化快速升级和替换。\n轻量安全容器增强OpenEuler 采用了一种轻量级的虚拟化技术,使得容器的运行负载降低,同时提高了虚拟机的安全性。\n\n社区评价\nOpenEuler 社区活跃且开放,得到了来自全球开发者的广泛关注和参与。它因其在多硬件架构支持和系统优化方面的努力,以及对开源精神的坚持而受到广泛的赞誉。截至在 Linux Kernel 5.10 版本中,华为提交的补丁数量为 1434 个,占比 8.9%,内核代码贡献排名第一,代码修改 41049 行,占比 5.3%。\n尽管 OpenEuler 具有许多优点,但作为一个较新的开源项目,在稳定性和兼容性上可能面临一些挑战。然而,社区正在积极努力,通过开放的合作和持续的技术创新,来解决这些问题。\n\nOpenAnolis 社区\n\n\n多架构的开源 Linux 操作系统发行版\n\n概述\nOpenAnolis 是一个致力于提供高效、稳定、可扩展操作系统平台的开源社区,**核心技术基于 Linux Kernel 和 K8s对接云原生生态。**OpenAnolis 由阿里云发起并持续维护,旨在通过社区合作,推动 Linux 和云原生技术的创新和发展。\nOpenAnolis 提供了一个包含了云原生组件、工具链、硬件和服务的完整技术栈,以帮助用户构建云原生应用。\n特色\n\n\n云原生支持OpenAnolis 针对云原生应用进行了设计,提供了一套完整的云原生技术栈,包括操作系统、容器运行时、服务网格等,以帮助用户快速构建和部署云原生应用。\n\n\n系统优化OpenAnolis 基于 Linux Kernel针对云原生环境进行了深度优化以提供高效、稳定、可扩展的运行环境。\n\n\n社区驱动OpenAnolis 由社区驱动,汇集了众多企业和开发者的力量,共同推动云原生技术的创新和发展。\n\n\n社区评价\nOpenAnolis 由于其针对云原生的专注和优化,在云原生领域得到了广泛的认可和使用。其社区活跃,技术发展快速,被认为是云原生技术的重要推动者。\n尽管 OpenAnolis 在云原生领域表现出色,但由于其相对年轻和专注的特性,在通用性和成熟度上可能略显不足。社区正在努力通过持续的技术创新和社区合作,来解决这些问题。"},"Technology/OperatingSystem/Linux/1.文化/开源软件的概念与重要性":{"title":"开源软件的概念与重要性","links":[],"tags":["Linux/文化","技术/操作系统"],"content":"开源软件的发展始于上世纪 80 年代,起初是由一些计算机爱好者和学术研究人员开发的。随着互联网的发展,越来越多的人开始加入到开源软件开发的行列中。\n开源软件是指能够公开查看、使用、复制、修改和分发源代码的软件。源代码开放的软件并不一定是开源软件开源软件有着严格统一的的定义封闭软件Closed Software、自由软件Free software和开源软件Open source software有着显著地区别。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n区别自由软件开源软件商业软件私有化反对保护支持知识产权反对有条件保护支持使用条件无限制开放源代码有条件商业模式可能不支持支持支持\n自由软件与商业软件是两种截然不同的软件开发思想前者反对脑力劳动成果私有化、反知识产权强调软件的使用和传播应该是自由的所有人都有权使用和修改软件。而商业软件则支持脑力劳动成果私有化主张软件的使用应该受到一定的控制和限制开发者有权对软件进行专利保护和商业化运营。\n开源软件则是介于两者之间的一种软件开发思想它保护脑力劳动成果私有化和支持知识产权但同时强调开放源代码和使用条件的公开和透明允许其他人使用、修改和分发软件同时也允许商业化运营但在使用和分发上有一些条件限制。\n在商业模式方面自由软件和开源软件可能不支持商业模式或者支持不同类型的商业模式例如服务、咨询和技术支持等。而商业软件则通常支持商业模式并通过销售软件许可证等方式获取商业利益。\n开源软件的定义\n开源软件促进协会 OSI 对开源软件有明确的定义OSI 对开源软件的定义一共有十个条款:\n1. 自由再发布Free Redistribution\n2. 源代码Source Code\n3. 派生作品Derived Works\n4. 作者源代码的完整性Integrity of The Author's Source Code\n5. 不能歧视任何个人和团体No Discrimination Against Persons or Groups\n6. 不能歧视任何领域No Discrimination Against Fields of Endeavor\n7. 许可证的发布Distribution of License\n8. 许可证不能针对某个产品License Must Not Be Specific to a Product\n9. 许可证不能约束其他软件License Must Not Restrict Other Software\n10. 许可证必须技术中立License Must Be Technology-Neutral\n通过开源软件定义的十个条款可以清楚的看到 OSI 所坚持的原则:\n\n坚持开放鼓励最大化地参与和协作\n尊重作者权利同时保证程序的完整性\n尊重独立和中立避免任何可能影响这种独立性的事物\n\n有了这样一个清晰而又完整的定义在法律层面保证了开源软件的开放性独立性和继承性。\n开源软件的优点\n如今开源软件已经成为了计算机行业的重要组成部分。在云计算、大数据、人工智能、区块链等领域开源软件已经成为了主流。开源软件具有以下优点\n\n降低成本使用开源软件可以降低企业和个人的软件开发和使用成本促进信息技术的普及和发展。\n提高软件质量由于开源软件可以被众多开发者修改和维护因此往往拥有更高的质量和稳定性。\n促进创新开源软件允许任何人自由修改和定制因此可以促进创新和技术进步。\n社区贡献开源软件的发展离不开庞大的社区支持和贡献。开源社区的力量可以帮助开源软件更快地发展和成长。\n\n开源社区的贡献和影响\n开源社区是指一群志同道合的开发者和用户他们自愿地为开源软件的发展做出贡献。开源社区的贡献和影响包括\n\n代码贡献开源社区的开发者可以为开源软件贡献代码和新功能为软件的发展和改进做出贡献。\n社区支持开源社区的用户可以为其他用户提供支持和帮助帮助他们解决问题和改进软件。\n文档贡献开源社区的用户可以为开源软件编写文档和教程帮助其他用户更好地了解和使用软件。\n测试贡献开源社区的用户可以为开源软件测试和反馈问题帮助开发者发现和修复软件中的漏洞和问题。\n社区文化开源社区的文化包括开放、透明、协作和互助这种文化对软件开发和技术创新产生了重要影响。\n\n开源社区的贡献和影响不仅限于软件本身还可以促进技术创新和知识共享。例如一些开源社区的成员通过协作和分享知识共同解决了一些重大技术难题为社会的进步做出了贡献。同时开源社区的文化也对软件行业和互联网文化产生了重要影响激发了人们对于开放、自由和协作的追求。\n著名的开源社区\n\nLinux 开源社区Linux 是一个开源操作系统由一群志愿者开发和维护Linux 开源社区是 Linux 开发和用户社区的总称,包括 Linux 内核开发者、Linux 发行版开发者和 Linux 用户等。\nApache Software FoundationApache Software Foundation 是一个非营利组织,致力于支持开源软件项目的开发和维护,旗下拥有众多著名的开源软件项目,如 Apache HTTP Server、Hadoop、Tomcat 等。\nGitHub 开源社区GitHub 是一个代码托管和开源社区平台,用户可以在 GitHub 上创建和维护开源项目,并与其他开发者协作开发和维护项目。\nEclipse 开源社区Eclipse 开源社区是一个致力于开发和维护 Eclipse 开源软件的社区Eclipse 是一个跨平台的集成开发环境IDE被广泛用于 Java 开发和其他编程语言的开发。\nMozilla 开源社区Mozilla 开源社区是一个致力于推广开放网络和开源软件的组织,旗下拥有著名的开源软件项目,如 Firefox 浏览器、Thunderbird 邮件客户端等。\n\n这些开源社区不仅在技术上做出了巨大贡献还形成了独特的开源文化和价值观成为了全球开源社区的重要组成部分。\n开源软件的风险\n开源软件主要风险在于 管理维护 和 技术支持 以及 许可证法律纠纷,由于开源软件采用的协作方式,你可能无法追究某一处代码的作者(部分协议要求作者著名)。以及如果出现问题,你可能无法寻找官方的技术支持,更多的支持可能来自于社区,可这种支持不是每次都有好人跳出来帮忙。还有如果你不了解许可证可能会带来的法律风险(部分国家法律不同,如果源代码无许可证,默认著作权属于作者)。\n开源许可证简介\n开源许可证并不只是保护作者的权利更多是赋予用户各项权利许可证规定了使用主体方式用途。明确说明了用户可以是个人或者公司等怎么修改和运行以及是否可以用来进行其他合法用途。\n在使用开源软件要做的第一步就是找出开源软件中所涉及的所有许可证。每个开源软件的不同版本可能会使用不同的许可证同时还有注意许可证的版本以及有些开源软件会采用双重或多重许可dual-license的模式。\n在 OSI 的网站上列出的 流行并广泛使用且拥有广泛社区的许可证,分别是:\n\nApache 许可证 2.0\nBSD 许可证 3-Clause\nBSD 许可证 2-Clause\nGNU 通用公共许可证(简称 GPL\nGNU 宽通用公共许可证(简称 LGPL\nMIT 许可证\nMozilla 公共许可证 2.0(简称 MPL\n通用开发和发布许可证 1.0(简称 CDDL\nEclipse 公共许可证 2.0(简称 EPL\n\n开源软件许可证规定了软件代码的使用、修改和分发等方面的条款和条件不同的许可证可能有不同的限制和要求。在使用开源软件时需要仔细阅读和理解相应的许可证确保自己的使用行为符合许可证的要求。\n许可证的兼容性\n目前经过 ISO 认证的许可证多达 70 多种,被自由软件基金会认可的自由软件许可证也有数十种,而它们的条款又各不相同,有些甚至互相矛盾。这种兼容性问题被称为 许可证增值问题License proliferation。\n怎么样才算兼容呢如果使用许可证 A 的代码和使用许可证 B 的代码能在一个广域作品中结合在一起,那么 A 和 B 就是兼容的,否则就是不兼容的。更近一步,如果结合后的广义作品可以用许可证 A 发布,那么许可证 B 就是许可证 A 兼容的A-compatible。反之亦然但需要注意的是兼容性并不可逆。\n如何选择许可证\n\n\n开源许可证选择工具\n\n如今开源软件早已经成为了软件领域不可或缺的重要组成部分要以辨证的观点看待开源软件。它自由平等协作的精神实践了信息和知识共享的理念并且实现了知识产权保护和分享之间的微妙平衡。同时开源带来的自由免费有可能也是最贵的。\n\n参考\n《开源软件之道》\n开源社——开源许可证选择器\nOpen Source Initiative\n阮一峰《如何选择开源许可证》\n"},"Technology/OperatingSystem/Linux/2.安装/GRUB-引导程序":{"title":"GRUB 引导程序","links":[],"tags":["技术/操作系统","Linux/安装"],"content":"引导加载器\n引导加载器是什么\n\n引导加载器是计算机启动过程中一个至关重要的组件。 它的主要功能是在硬件自检POST完成后从存储设备中加载并启动操作系统的内核。引导加载器充当了硬件和操作系统之间的桥梁确保操作系统能够顺利运行。具体来说引导加载器的职责包括以下几个方面\n\n识别和加载内核引导加载器从预定义的启动分区或磁盘位置找到操作系统内核并将其加载到内存中。\n传递启动参数引导加载器可以将启动参数传递给内核以决定操作系统的启动行为。\n多操作系统引导管理在多操作系统环境中引导加载器允许用户在多个操作系统之间进行选择。\n错误处理和恢复当出现启动错误时引导加载器通常提供恢复选项以修复引导过程中的问题。\n\n引导加载器的发展历史可以追溯到早期的计算机系统。在早期硬件本身提供了简单的启动机制通常只支持启动单一操作系统。随着计算机技术的发展引导加载器逐渐演变出更复杂的功能以支持多操作系统和复杂的启动配置。\n\n早期阶段最初的引导加载器非常简单主要是在特定存储设备上找到一个可执行的程序来启动操作系统。这种简单的引导方法适用于单操作系统环境但在现代复杂的多操作系统环境中不再适用。\nLILOLinux LoaderLILO 是 Linux 早期使用的引导加载器,支持在多操作系统之间进行简单切换。它的配置相对复杂,且不支持动态更新。\nGRUB 的出现:为了克服 LILO 的限制GRUBGrand Unified Bootloader作为更强大的引导加载器被开发出来支持动态更新和更复杂的启动配置。\n\nGRUB 历史发展\nGRUBGRand Unified Bootloader作为一种广泛使用的引导加载器其历史发展体现了计算机引导技术的演变。从最初的 GRUB Legacy 到现代的 GRUB 2.x它的功能和特性经历了显著的变化和提升。\nGRUB 0.x 和 GRUB LegacyGRUB 1.x\nGRUB 的发展始于 1999 年,最早的稳定版本 GRUB 0.97 发布。它被设计为 LILOLInux Loader的替代品主要目标是提供一种灵活的引导方式支持多操作系统和多内核引导。GRUB Legacy或 GRUB 1.x使用 menu.lst 作为其主要配置文件。用户需要手动编辑这个文件来定义启动项和内核参数。虽然配置相对简单,但其缺乏自动化和灵活性,配置更新需手动完成。\nGRUB 2.x\n随着技术的发展2010 年 GRUB 2.00 发布,引入了许多新的特性和改进,逐步取代了 GRUB Legacy。GRUB 2.x 的核心改进之一是其配置文件 grub.cfg这是一个自动生成的文件用户不再需要直接编辑。配置管理转移到 /etc/default/grub 和 /etc/grub.d/ 目录中的脚本,通过 update-grub 命令自动生成 grub.cfg从而减少了手动错误并增强了配置的灵活性。\n另一个显著的改进是 GRUB 2.x 引入了模块化设计。它支持动态加载模块,根据启动需求加载或卸载不同的功能模块,如文件系统支持、网络引导、图形界面等。这一设计不仅提高了灵活性,还减少了内存占用,因为只有必要的模块会被加载。\nGRUB 2.x 还引入了自动检测操作系统的功能。通过 os-prober 工具GRUB 能够扫描磁盘上的所有操作系统并自动更新启动菜单,这使得多操作系统环境的管理变得更加简便。\n与 UEFI 的集成\n**随着计算机硬件逐步转向 UEFIUnified Extensible Firmware InterfaceGRUB 也适应了这一变化。**在 2012 年以后GRUB 开始支持 UEFI 模式,使其能够在现代计算机上运行,并与传统 BIOS 模式兼容。**GRUB 在 UEFI 环境中支持 Secure Boot 功能,这是防止未经授权的操作系统加载的安全机制。**为了满足这一要求GRUB 必须经过签名以确保其能够在 Secure Boot 环境中运行。\n未来展望\n展望未来GRUB 可能会继续演进以支持新兴的引导技术和标准。未来的 GRUB 版本可能会进一步增强安全功能,如更全面的加密支持和更严格的 Secure Boot 集成以应对不断演变的安全威胁。同时GRUB 可能会与新兴操作系统和虚拟化技术深度集成,提升对各种操作系统和平台的支持能力。\nGRUB 基础概念\n基本结构\n\nGRUB Legacy 的分层结构\n\nGRUB Legacy 的结构设计为分阶段加载,以克服早期计算机系统的限制并实现多操作系统引导。\n\nStage 1GRUB 的 Stage 1 通常位于硬盘的主引导记录MBR中。由于 MBR 只有 512 字节的大小限制Stage 1 的代码非常简短,主要任务是定位并加载 Stage 1.5 或 Stage 2。Stage 1 的目标是让计算机找到并启动 Stage 1.5 或直接启动 Stage 2。\nStage 1.5Stage 1.5 是 GRUB 特有的一个中间层,通常存储在硬盘的第一个分区之前的空闲区域中。它的主要作用是提供对文件系统的支持,使得 GRUB 能够从特定的文件系统中加载 Stage 2。这一阶段的引入是为了弥补 Stage 1 无法直接处理复杂文件系统的不足。\nStage 2Stage 2 是 GRUB Legacy 的主要加载器部分负责呈现启动菜单、加载操作系统内核并执行用户命令。Stage 2 通常存储在硬盘的文件系统中,并且支持多操作系统的引导选择。用户可以通过 Stage 2 的菜单界面选择启动不同的操作系统或进入命令行模式进行手动操作。\n\nGRUB 2 的模块化结构和主要组件\n\n与 GRUB Legacy 相比GRUB 2.x 采用了更加现代化的模块化结构旨在提高灵活性、可扩展性和易用性。GRUB 2.x 的结构主要包括以下组件:\n\n核心映像Core Image\n核心映像是 GRUB 2.x 的基本加载器部分,相当于 GRUB Legacy 的 Stage 1 和 Stage 1.5。它通常包括最低限度的模块化代码,用于加载其他模块和配置文件。\n模块Modules\nGRUB 2.x 使用模块来扩展其功能。不同于 GRUB Legacy 的固定功能GRUB 2.x 的模块可以按需加载。这些模块提供文件系统支持、设备驱动、网络引导支持等功能,使 GRUB 2.x 可以适应更复杂的启动需求。\n配置文件Configuration File\nGRUB 2.x 的配置文件是 grub.cfg由系统自动生成包含启动菜单的配置、内核选项和模块加载指令。与 GRUB Legacy 的 menu.lst 不同grub.cfg 不应手动编辑,而是通过 /etc/default/grub 和脚本生成。\n图形用户界面Graphical User Interface\nGRUB 2.x 支持图形用户界面,通过加载特定模块,可以显示带有背景图片和自定义主题的启动菜单,使用户体验更加友好。\n\n核心功能\n引导操作系统内核\nGRUB 的核心功能之一是加载并引导操作系统内核。具体过程包括:\n\n内核定位与加载当计算机启动时GRUB 负责从指定的分区或设备上找到操作系统的内核映像,并将其加载到内存中。这一过程包括读取内核文件(通常是一个压缩的内核映像)并将其拷贝到内存中,为内核执行做准备。\n传递启动参数GRUB 在加载内核之前,可以通过配置文件或启动菜单传递参数给内核。这些参数可以控制内核的行为,如指定根文件系统位置、启用或禁用调试模式、设置单用户模式等。参数传递允许用户在启动时对系统进行定制化配置。\n支持多种内核格式GRUB 支持多种内核格式和引导机制,包括传统的 Linux 内核、内核映像和初始 RAM 磁盘initrd。对于不同的操作系统和内核类型GRUB 提供了相应的支持。\n\n提供多操作系统引导菜单\nGRUB 允许用户在多操作系统环境中选择要引导的操作系统,具体功能包括:\n\n启动菜单的生成与显示GRUB 在系统启动时提供一个引导菜单,用户可以通过此菜单选择要启动的操作系统或内核版本。菜单可以是文本模式的,也可以是图形化的,具体取决于 GRUB 的配置和主题设置。\n自动检测操作系统GRUB 2.x 的自动检测功能通过 os-prober 工具扫描硬盘上的所有分区,识别已安装的操作系统,并自动生成相应的启动条目。这样,用户无需手动编辑配置文件,就能在新操作系统安装后自动更新启动菜单。\n自定义启动项用户可以通过编辑 /etc/default/grub 配置文件和 /etc/grub.d/ 目录中的脚本来定义和管理启动项。用户可以指定启动顺序、设置超时时间、定义默认启动项等。GRUB 2.x 的配置方式使得多操作系统环境的管理变得更加灵活和方便。\n支持多种操作系统GRUB 支持多种操作系统的引导,包括 Linux、Windows、BSD 等。每个操作系统的引导条目可以根据需要进行配置和调整,支持各种引导需求。\n\n提供命令行工具进行手动操作\nGRUB 提供了一个强大的命令行工具,支持在引导阶段进行手动操作和故障排除,功能包括:\n\n命令行模式的进入在 GRUB 启动时,用户可以通过按下 c 键进入命令行模式。在这个模式下,用户可以手动输入命令,执行内核加载、根文件系统设置、模块加载等操作。这对于系统管理员和高级用户在遇到引导问题时进行诊断和修复非常有用。\n常用命令\n\nset设置或显示 GRUB 环境变量。例如,设置内核启动参数或根文件系统。\ninsmod加载 GRUB 模块。这允许用户动态添加支持某些文件系统或功能的模块。\nlinux指定要启动的内核通常与内核文件路径一起使用。\ninitrd指定内核的初始 RAM 磁盘映像,用于提供启动时所需的驱动程序和工具。\nboot启动加载并执行内核开始操作系统的引导过程。\nls列出指定设备或分区的内容帮助用户查找内核和其他引导文件。\n\n\n命令行调试通过命令行模式用户可以灵活地调试和恢复系统例如在 GRUB 配置文件损坏或系统引导失败时,用户可以手动加载内核和初始化 RAM 磁盘,逐步解决问题。\n\n这些核心功能使 GRUB 成为一个强大而灵活的引导加载器,能够处理多种操作系统的引导需求,提供详细的故障排除能力,并允许用户在复杂环境中进行精细控制。\n1.x 和 2.x 的主要区别\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性GRUB 1.x (Legacy)GRUB 2.x配置文件menu.lstgrub.cfg自动生成不建议直接编辑配置方式手动编辑 menu.lst通过 /etc/default/grub 和 /etc/grub.d/ 脚本管理,通过 update-grub 自动生成模块化支持固定功能需重新编译模块化设计动态加载模块按需加载或卸载功能模块功能扩展受限增加功能需重新编译支持图形引导界面、脚本支持、LVM、RAID、加密文件系统、PXE 网络引导等高级功能引导方式仅支持传统的 BIOS 引导支持 BIOS 和 UEFI 引导,兼容性更广错误处理错误提示信息较少,问题排查困难提供详细的错误信息和调试模式,支持 grub-rescue 和 grub> 命令行模式多语言支持限制,主要支持英文支持多语言,包括对图形界面的本地化支持支持的文件系统支持的文件系统较少,通常为 ext2/ext3/ext4支持多种文件系统包括 ext2/3/4、Btrfs、XFS、FAT、NTFS 等动态发现和配置静态配置,需要手动添加新操作系统通过 os-prober 自动发现并添加操作系统,支持动态配置高级配置配置复杂且功能有限支持更复杂的配置和脚本,例如条件引导、动态菜单生成等引导菜单界面基本文本模式支持图形界面,自定义主题和菜单布局,提供更友好的用户体验性能优化性能优化有限支持优化和调整,如减少启动超时,按需加载模块以提高启动速度\nGRUB 安装\n在不同操作系统上安装 GRUB\nLinux 发行版\n在大多数 Linux 发行版中GRUB 通常作为默认的引导加载器自动安装,但在某些情况下可能需要手动安装或修复。以下是在常见 Linux 发行版上安装 GRUB 的基本步骤:\n\n\nUbuntuUbuntu 在安装过程中会自动安装 GRUB。若需要手动安装可以使用以下命令\nsudo grub2-install /dev/sda\nsudo update-grub\n其中/dev/sda 表示要安装 GRUB 的硬盘。如果需要修复 GRUB例如由于分区表变动导致 GRUB 无法启动),可以使用 Ubuntu Live CD 或 USB 启动系统,然后在 Live 环境下安装和更新 GRUB。\n\n\nCentOSCentOS 也在安装过程中自动安装 GRUB。手动安装的步骤与 Ubuntu 类似,使用以下命令:\nsudo grub2-install /dev/sda\nsudo grub2-mkconfig -o /boot/grub2/grub.cfg\n需要注意的是在 CentOS 7 及以后GRUB 2 是默认的引导加载器,配置文件位置和命令与 GRUB Legacy 略有不同。\n\n\n双系统Windows + Linux\n在双系统Windows + Linux环境中GRUB 通常被用来管理启动顺序,使用户可以在系统启动时选择进入 Windows 或 Linux。在这种环境下安装 GRUB需要考虑以下步骤\n\n\n安装顺序通常**建议先安装 Windows再安装 Linux。**这是因为 Windows 的引导加载器会覆盖 MBR而 Linux 在安装时可以自动检测 Windows 并配置 GRUB 以引导 Windows。\n\n\n安装 GRUB在安装 Linux 时,选择安装 GRUB 到主硬盘的 MBR通常是 /dev/sda这将使 GRUB 成为默认的引导加载器。在安装完成后GRUB 将会自动检测 Windows 并在启动菜单中列出。\n\n\n**修复 GRUB**如果 Windows 更新或修复过程中覆盖了 GRUB可以使用 Linux Live CD 启动系统,然后使用以下命令重新安装和配置 GRUB\n\n\nsudo grub2-install /dev/sda\nsudo update-grub\n在 UEFI 和 Legacy BIOS 模式下安装 GRUB 的区别\n在不同启动模式下安装 GRUB 需要考虑不同的配置和操作方法。\n\n\nLegacy BIOS 模式\n在 Legacy BIOS 模式下GRUB 通常安装在 MBR 中(即硬盘的第一个扇区)。在安装 GRUB 时,需要确保目标磁盘使用 MBR 分区表格式,并在 MBR 中安装 GRUB 的 Stage 1 部分。安装命令一般为:\nsudo grub2-install /dev/sda\n此外还需要生成或更新 grub.cfg 文件,以确保 GRUB 能够正确加载操作系统。\n\n\nUEFI 模式:\n在 UEFI 模式下GRUB 通常安装在 EFI 系统分区ESP并且要求硬盘使用 GPT 分区表格式。UEFI 模式不使用 MBR因此 GRUB 需要安装到 ESP 中,并以 .efi 文件的形式存在。安装 GRUB 时,通常指定 --target=x86_64-efi 参数:\nsudo grub2-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB\n这会在 ESP 中创建一个 GRUB 目录,并将 GRUB 的 EFI 文件放入其中。\n\n\ngrub2-install 命令\ngrub2-install 是用于安装 GRUB 引导加载器的命令。它的基本语法为:\nsudo grub2-install [选项] <目标设备>\n常见参数包括\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数描述适用情况--target指定目标平台定义 GRUB 将要安装的架构或平台。常见的值包括 i386-pcLegacy BIOS和 x86_64-efiUEFI。用于选择 GRUB 安装的架构或平台。--efi-directory指定 EFI 系统分区的挂载点。在 UEFI 模式下使用GRUB 必须安装在此分区的 /EFI 子目录下。仅在 UEFI 模式下使用。--boot-directory指定 GRUB 安装目录,通常是 /boot。GRUB 的核心文件将被安装在此目录。用于定义 GRUB 安装的路径。--recheck重新检测目标设备。如果在初次安装时设备信息发生变化使用此选项可确保 GRUB 正确识别设备。用于修正设备检测问题。--force强制安装 GRUB即使检测到可能的冲突或警告。适用于在安装过程中遇到错误时进行尝试。用于在可能冲突的情况下强制安装。\n在不同的分区方案MBR 和 GPT下使用 grub-install\n在使用 grub-install 命令时分区方案MBR 或 GPT决定了 GRUB 的安装位置和方式。\nMBRMaster Boot Record\n对于 MBR 分区表grub-install 通常将 GRUB 的 Stage 1 部分安装到 MBR即硬盘的第一个扇区。这是 Legacy BIOS 模式下的常见方法:\nsudo grub2-install /dev/sda\n安装完成后GRUB 会将控制权转移给 Stage 1.5 或 Stage 2 部分,并加载操作系统内核。\nGPTGUID Partition Table\n在 GPT 分区表下,如果使用 Legacy BIOS 模式引导GRUB 仍然可以安装在一个特殊的 BIOS 引导分区中。对于 UEFI 模式GRUB 则安装在 EFI 系统分区ESP\nsudo grub2-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB\n在这种情况下GRUB 不会占用 MBR而是通过 EFI 固件直接启动。\n将 GRUB 安装到特定磁盘或分区\n有时需要将 GRUB 安装到特定的磁盘或分区,例如在多硬盘系统中选择某个硬盘作为主引导盘。可以使用 grub-install 命令指定目标设备:\n安装到特定磁盘\n如果要将 GRUB 安装到特定的硬盘,例如 /dev/sdb可以使用\nsudo grub2-install /dev/sdb\n这会将 GRUB 的引导加载器部分安装到 /dev/sdb 的 MBR 或 EFI 系统分区中。\n安装到特定分区\n在某些情况下可能需要将 GRUB 安装到特定分区(例如双引导设置中)。这种情况下,需要特别小心,因为在分区中安装 GRUB 可能会带来一些引导问题,通常不推荐这种做法,但可以通过指定目标分区来实现:\nsudo grub2-install /dev/sda1\n这会将 GRUB 的 Stage 1 部分安装到指定的分区中,但通常这种方式仅用于链式引导等特殊情况。\nGRUB 配置文件\ngrub.cfg 文件\ngrub.cfg 是 GRUB 2.x 的主要配置文件,通常位于 /boot/grub/ 或 /boot/grub2/ 目录下。这个文件由 grub-mkconfig 工具自动生成,包含了 GRUB 启动菜单的所有配置项。grub.cfg 的结构包括以下几个主要部分:\n\nGlobal Settings全局设置定义 GRUB 的全局设置,如默认启动项、超时时间、终端输出等。通常位于文件的开头部分。\nMenu Entries菜单项定义每个操作系统或内核的启动项。每个启动项通常以 menuentry 关键字开头,后面跟随启动项的名称和启动配置。\nModules and Additional Settings模块和其他设置包含 GRUB 加载的模块以及其他特定设置,例如图形界面、密码保护等。\n\nGrub 基本语法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n语法元素说明示例注释使用 # 符号添加注释。注释内容不会被 GRUB 解析,用于在配置文件中添加说明或备注。# 这是一个注释变量使用 set 关键字定义和设置变量。变量可用于存储配置选项如默认启动项、根文件系统路径等。set default=0 set root=(hd0,1)命令和选项GRUB 使用类似脚本的语法定义启动选项。常用命令包括set用于定义和设置环境变量如设置启动项、根目录等。set default=0 set timeout=10linux加载内核并指定内核参数。通常用于定义启动的内核文件及其参数。linux /vmlinuz root=/dev/sda1initrd指定初始 RAM 磁盘映像initramfs为内核启动提供必要的驱动程序和工具。initrd /initrd.imgboot启动内核和初始 RAM 磁盘开始操作系统的引导过程。bootmenuentry定义启动菜单中的条目每个条目表示一个可启动的操作系统或内核版本。menuentry "Ubuntu" { ... }insmod加载 GRUB 模块用于添加支持特定功能的模块如文件系统、网络等。insmod ext2search搜索指定的设备或分区通常用于查找启动文件或内核。search --no-floppy --fs-uuid --set=rootconfigfile引用另一个配置文件。用于将配置文件分成多个部分以简化管理。configfile /boot/grub/custom.cfgif 和 else条件判断允许根据不同条件执行不同的配置或命令。if [ "$grub_platform" = "efi" ]; then ...\n虽然 grub.cfg 是可以手动编辑的,但不建议直接修改这个文件,原因如下:\n\n自动生成grub.cfg 通常由 grub-mkconfig 自动生成,手动编辑的修改在下次更新时可能会被覆盖。\n复杂性grub.cfg 文件可能包含复杂的逻辑和脚本,手动修改容易引入错误,导致系统无法启动。\n安全性错误的配置可能导致系统无法启动或引发安全漏洞因此建议通过修改 /etc/default/grub 和相关脚本来间接配置 GRUB然后生成新的 grub.cfg 文件。\n\nGRUB 菜单项的定义和配置\n在 grub.cfg 文件中,菜单项是由 menuentry 关键字定义的,每个菜单项通常包括以下内容:\n\n菜单项名称menuentry 'Ubuntu' 定义了显示在启动菜单中的名称。\n内核加载使用 linux 命令加载指定的内核映像,例如 linux /vmlinuz-5.4.0-42-generic root=/dev/sda1。\n初始内存盘使用 initrd 命令加载内核的初始内存盘initrd例如 initrd /initrd.img-5.4.0-42-generic。\n额外参数可以为内核传递额外的启动参数例如 quiet splash这些参数通常通过 GRUB_CMDLINE_LINUX_DEFAULT 变量定义。\n\n/etc/default/grub 配置文件\n/etc/default/grub 是 GRUB 的主配置文件之一,用户可以通过修改该文件来影响 GRUB 的行为。常见的配置选项包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n配置项说明作用示例GRUB_DEFAULT设置 GRUB 的默认启动项。可以是菜单项的索引(从 0 开始计数)或 saved表示上次启动的菜单项。确定系统启动时默认选择的启动项。GRUB_DEFAULT=0 GRUB_DEFAULT=savedGRUB_TIMEOUT设置 GRUB 启动菜单显示的超时时间单位为秒。超时后GRUB 将自动启动默认项。如果设置为 -1则菜单将无限期显示。控制 GRUB 菜单显示的时间长度。GRUB_TIMEOUT=5 GRUB_TIMEOUT=-1GRUB_DISTRIBUTOR指定 GRUB 菜单中显示的操作系统名称。通常由发行版自动设置不建议手动修改。设置菜单中显示的操作系统名称。GRUB_DISTRIBUTOR="Ubuntu"GRUB_CMDLINE_LINUX为所有 Linux 内核启动项传递通用的内核参数。这些参数将在所有启动项中生效。定义内核启动时使用的通用参数影响所有内核启动项。GRUB_CMDLINE_LINUX="nomodeset"GRUB_CMDLINE_LINUX_DEFAULT为默认启动项传递的内核参数通常用于设置用户友好的启动体验如减少启动时的屏幕输出。仅在默认启动项中生效。配置默认启动项时的特定内核参数。GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"GRUB_BACKGROUND设置 GRUB 启动菜单的背景图片。可以指定图片的路径。更改 GRUB 启动菜单的视觉效果。GRUB_BACKGROUND="/boot/grub/background.png"GRUB_HIDDEN_TIMEOUT设置隐藏 GRUB 菜单的超时时间(单位为秒)。如果设置为 0菜单将被隐藏并直接启动默认项。控制 GRUB 菜单是否在启动时显示。GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT=2GRUB_HIDDEN_TIMEOUT_QUIET如果启用将在 GRUB 菜单隐藏时不显示任何提示。控制菜单隐藏时是否显示提示。GRUB_HIDDEN_TIMEOUT_QUIET=trueGRUB_GFXMODE设置 GRUB 菜单的分辨率模式。可以设置为具体的分辨率(如 1024x768。配置 GRUB 菜单的显示分辨率。GRUB_GFXMODE=1024x768GRUB_TERMINAL设置 GRUB 的终端类型。可以设置为 console 或 gfxterm。决定 GRUB 使用文本模式还是图形模式。GRUB_TERMINAL=console GRUB_TERMINAL=gfxtermGRUB_TERMINAL_OUTPUT设置 GRUB 的终端输出方式,可以选择 console文本模式或 gfxterm图形模式。配置 GRUB 的输出显示方式。GRUB_TERMINAL_OUTPUT=console GRUB_TERMINAL_OUTPUT=gfxtermGRUB_SAVEDEFAULT如果启用GRUB 将记住上一次启动的菜单项,并在下次启动时默认选择该项。使 GRUB 记住并自动选择上次启动的菜单项。GRUB_SAVEDEFAULT=trueGRUB_DISABLE_RECOVERY如果启用将禁用 GRUB 菜单中的恢复模式。控制是否在 GRUB 菜单中显示恢复模式选项。GRUB_DISABLE_RECOVERY=true\n使用 grub-mkconfig 生成 GRUB 配置文件\ngrub-mkconfig 是生成 grub.cfg 文件的工具,它会自动扫描系统中的操作系统和内核,并生成相应的启动项。基本用法为:\nsudo grub2-mkconfig -o /boot/grub/grub.cfg\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明作用示例-o, --output指定生成的 GRUB 配置文件的路径。用于指定生成的 grub.cfg 文件的位置。-o /boot/grub/grub.cfg--config-file指定一个替代的 GRUB 配置文件路径。允许使用指定的配置文件而不是默认的 grub.cfg 文件。--config-file /etc/grub.custom.cfg--directory指定 GRUB 安装目录,其中包含 GRUB 模块和其他文件。用于设置 GRUB 模块的位置。--directory /boot/grub--default设置默认启动项。配置默认启动项的编号。--default 1--output-format设置输出格式可以是 grub 或 plaintext。控制生成的配置文件格式。--output-format grub--no-nice禁用生成配置文件时的优雅显示。使 grub-mkconfig 不显示任何额外的信息。--no-nice--no-legacy禁用旧版 GRUB 配置文件的生成。防止生成兼容旧版 GRUB 的配置。--no-legacy--help显示帮助信息。提供 grub-mkconfig 命令的使用帮助。--help--version显示 grub-mkconfig 的版本信息。显示当前安装的 grub-mkconfig 版本。--version--verbose显示详细输出。输出详细的处理信息。--verbose--quiet减少输出信息。减少生成配置时的屏幕输出。--quiet--chroot在指定的 chroot 环境中运行。在指定的 chroot 环境中生成 GRUB 配置。--chroot /mnt/root--force强制生成配置文件即使在检测到潜在问题时。忽略警告和错误强制生成配置文件。--force\nGRUB 高级配置\nGRUB 配置文件的结构和语法\n在 GRUB 配置文件 grub.cfg 中,配置的基本单位是 menuentry它定义了启动菜单中的每一个选项。此外GRUB 还支持子菜单submenu结构用于组织复杂的引导选项。\nmenuentry 块\nmenuentry 是定义单个启动项的基本结构。每个启动项通常包括操作系统名称、内核路径、初始化内存盘路径、以及内核参数。例如:\nmenuentry 'Ubuntu, with Linux 5.4.0-42-generic' {\n set root='hd0,msdos1'\n linux /vmlinuz-5.4.0-42-generic root=/dev/sda1 ro quiet splash\n initrd /initrd.img-5.4.0-42-generic\n}\n\nset root='hd0,msdos1':设置引导分区。\nlinux指定内核路径和启动参数。\ninitrd指定初始化内存盘的路径。\n\nsubmenu 块\nsubmenu 用于创建包含多个启动项的子菜单,便于在复杂的多操作系统或多内核环境中管理启动选项。例如:\nsubmenu 'Advanced options for Ubuntu' {\n menuentry 'Ubuntu, with Linux 5.4.0-42-generic' {\n linux /vmlinuz-5.4.0-42-generic root=/dev/sda1 ro quiet splash\n initrd /initrd.img-5.4.0-42-generic\n }\n menuentry 'Ubuntu, with Linux 5.4.0-40-generic' {\n linux /vmlinuz-5.4.0-40-generic root=/dev/sda1 ro quiet splash\n initrd /initrd.img-5.4.0-40-generic\n }\n}\n在启动菜单中用户可以选择进入子菜单然后选择特定的启动项。\n使用 insmod 加载模块的配置方法\nGRUB 的模块化设计允许通过 insmod 命令按需加载功能模块例如文件系统支持、图形界面支持等。insmod 通常在 grub.cfg 文件的顶部或 menuentry 块中使用。例如:\ninsmod part_gpt\ninsmod ext2\n\n\npart_gpt加载 GPT 分区表支持模块。\next2加载 ext2/3/4 文件系统支持模块。\n\n加载模块的顺序很重要因为某些模块可能依赖其他模块。insmod 命令可以在启动时手动使用,也可以在配置文件中自动执行。\n通过 set 指令配置 GRUB 的环境变量\nGRUB 允许使用 set 指令配置环境变量,这些变量可以用于控制引导流程的各个方面。例如:\nset timeout=5\nset default=0\n\n\ntimeout设置引导菜单的超时时间。\ndefault设置默认的启动项。\n\n这些变量在启动时会影响 GRUB 的行为。此外,还可以定义自定义变量,用于复杂的引导逻辑控制。例如:\nset fallback_entry=2\n\n自定义变量可以在条件语句中使用以实现更复杂的启动方案。\n使用环境变量和内核参数自定义引导菜单\n使用 GRUB 环境变量控制引导流程\nGRUB 环境变量用于动态控制引导菜单的行为。这些变量可以通过 set 指令定义,并在 grub.cfg 中使用。例如,使用 GRUB_DEFAULT=saved 可以保存上次的启动选择,并在下次启动时自动选择相同的启动项。\n\n\n保存上次的选择\nset default=saved\nsave_env default\n这将允许 GRUB 在每次启动后保存默认启动项,并在下次启动时自动选择。\n\n\n使用条件语句 可以根据环境变量的值决定不同的启动流程。例如:\nif [ "${timeout}" -eq "0" ]; then\n set timeout_style=hidden\nfi\n这段代码在超时时间为 0 时隐藏启动菜单。\n\n\n在引导时传递内核参数以影响操作系统的启动行为\n内核参数可以在引导时通过 GRUB 传递,以改变操作系统的启动行为。例如,在 menuentry 块中添加内核参数:\nmenuentry 'Ubuntu, with Linux 5.4.0-42-generic' {\n linux /vmlinuz-5.4.0-42-generic root=/dev/sda1 ro quiet splash\n initrd /initrd.img-5.4.0-42-generic\n}\n\nro使根文件系统以只读模式挂载。\nquiet splash减少启动信息并显示启动动画。\n\n通过这些内核参数用户可以控制内核的启动模式、日志输出、硬件配置等。高级用户可以利用这些参数解决特定硬件问题或调试启动过程。\n多重引导配置\n配置 Windows 和 Linux 的双重引导\n在同一台计算机上同时运行 Windows 和 Linux 操作系统是许多用户的常见需求GRUB 可以轻松管理这种双重引导配置。\n\n\n安装顺序\n**一般建议先安装 Windows然后安装 Linux。**这是因为 Windows 安装程序通常会覆盖 MBR 或 EFI 系统分区中的引导加载器,而 Linux 安装程序会检测到已有的 Windows 安装并配置 GRUB 以包含 Windows 的启动选项。\n\n\nLinux 安装时的引导配置:\n在 Linux 安装过程中,选择将 GRUB 安装到主硬盘的 MBR 或 EFI 系统分区中。Linux 安装程序通常会自动检测到 Windows 并生成相应的启动菜单项。例如Ubuntu 的安装程序会自动运行 os-prober 来检测 Windows并添加启动项到 GRUB 配置文件中。\n\n\n修复引导问题\n如果 Windows 更新或重新安装后覆盖了 GRUB可以使用 Linux Live CD/USB 启动并修复 GRUB。具体步骤如下\n\n\n启动 Linux Live 环境并打开终端。\n\n\n挂载根分区和 EFI 系统分区(如果适用):\nsudo mount /dev/sda1 /mnt\nsudo mount /dev/sda2 /mnt/boot/efi\n\n\n\n安装 GRUB 并更新配置:\nsudo grub2-install --boot-directory=/mnt/boot /dev/sda\nsudo chroot /mnt\nsudo grub2-mkconfig -o /boot/grub/grub.cfg\n\n\n\n配置多个 Linux 发行版的引导\n在同一台计算机上安装多个 Linux 发行版时GRUB 可以管理这些系统的引导顺序和配置。\n\n\n选择主引导加载器\n通常选择一个主要的 Linux 发行版作为主引导加载器管理系统,其他发行版的 GRUB 可以安装到其根分区,而不是 MBR 或 EFI 系统分区。例如,使用 Ubuntu 的 GRUB 作为主引导加载器,其它发行版的 GRUB 安装到各自的根分区。\n\n\n更新主引导配置\n在主引导管理系统中使用 sudo grub2-mkconfig -o /boot/grub/grub.cfg 命令更新 GRUB 配置文件。os-prober 将自动检测到其他 Linux 发行版,并添加相应的启动项。如果检测不到,可以手动添加启动项。例如:\n\n\nmenuentry 'Fedora' {\n set root='hd0,msdos2'\n linux /vmlinuz-linux root=/dev/sda2 ro quiet\n initrd /initramfs-linux.img\n}\n\n解决冲突和兼容性问题\n在多个 Linux 系统共存的情况下,内核参数或引导设置可能会冲突。例如,某些发行版可能需要特定的内核参数才能正确启动。可以通过调整 grub.cfg 或 /etc/default/grub 中的参数来解决这些问题。\n\n在多操作系统环境中可能会出现以下兼容性问题\n\n文件系统兼容性Windows 通常使用 NTFS 文件系统,而 Linux 使用 ext4、btrfs 等文件系统。GRUB 需要通过加载相应的模块(如 insmod ntfs来访问这些文件系统。\nSecure Boot在启用 Secure Boot 的 UEFI 系统中GRUB 和 Linux 内核需要签名才能引导。如果安装的 Linux 发行版没有合适的签名文件,可能需要禁用 Secure Boot 或手动签名 GRUB 和内核。\nUEFI 与 Legacy BIOS 模式的混用:混用 UEFI 和 Legacy BIOS 模式可能导致引导问题,特别是在多操作系统环境中。如果系统采用 UEFI 模式安装,确保所有操作系统都使用相同的模式安装。\n\n设置和管理不同操作系统的引导顺序\n调整引导顺序的技巧\n在多系统引导环境中用户可能需要调整操作系统的引导顺序。GRUB 提供了多种方法来实现这一点:\n\n\n编辑 /etc/default/grub 文件:\n修改 GRUB_DEFAULT 变量来设置默认启动项。例如,将默认启动项设置为 Windows\nGRUB_DEFAULT="Windows 10"\n\n然后运行 update-grub 更新配置文件。\n\n\n使用 grub-set-default 命令:\n该命令可以在引导菜单项之间切换默认启动项。查看当前的菜单项列表\nsudo awk -F\\' '/menuentry / {print $2}' /boot/grub/grub.cfg\n\n设置新的默认启动项\nsudo grub2-set-default "Windows 10"\n\n\n临时改变引导顺序\n在 GRUB 启动菜单出现时,可以手动选择一个非默认启动项。按下 e 键可以编辑引导命令,修改后按 F10 键启动。这不会永久更改引导顺序。\n\n\n解决 GRUB 更新后引导顺序变化的问题\nGRUB 更新后,默认启动项可能会意外改变,通常是因为新的内核或操作系统被检测到并设置为默认。\n\n\n持久化设置\n使用 saved 选项来保存用户的最后一次选择。确保在 /etc/default/grub 中配置如下:\nGRUB_DEFAULT=saved\nGRUB_SAVEDEFAULT=true\n\n\n\n锁定默认项\n如果不希望 GRUB 更新后改变默认启动项,可以在 /etc/default/grub 中设置具体的启动项名称:\nGRUB_DEFAULT="Ubuntu, with Linux 5.4.0-42-generic"\n\n\n\n修复 /etc/grub.d/ 脚本:\n检查 /etc/grub.d/ 目录中的脚本,确保没有不必要的脚本导致意外的引导顺序变化。可以通过禁用或删除无用的脚本来控制菜单的生成。\n\n\n使用 GRUB 的 os-prober 自动检测并添加其他操作系统\nos-prober 是 GRUB 中的一个实用工具,用于自动检测系统中的其他操作系统,并将其添加到 GRUB 的启动菜单中。os-prober 通常与 update-grub 一起使用。\n\n\n启用 os-prober\n默认情况下os-prober 应该是启用的,可以通过检查 /etc/default/grub 中的设置来确认:\nGRUB_DISABLE_OS_PROBER=false\n\n然后运行以下命令更新 GRUB 配置:\nsudo grub2-mkconfig -o /boot/grub/grub.cfg\n\n\n\n手动运行 os-prober\n如果系统未自动检测到其他操作系统可以手动运行 os-prober 来检查:\nsudo os-prober\n\n运行完毕后重新生成 GRUB 配置:\nsudo grub2-mkconfig -o /boot/grub/grub.cfg\n\n\n\n排查 os-prober 问题:\n如果 os-prober 未能检测到某些操作系统,可能是因为文件系统未挂载或缺少文件系统支持模块。确保所有相关分区已挂载,并通过 insmod 加载必要的模块(如 ntfs、ext2 等)。\n\n\nGRUB 命令行模式\n如何进入 GRUB 命令行模式\nGRUB 命令行模式是一种强大的工具,**允许用户在引导阶段直接输入命令来引导操作系统或进行系统调试。**进入 GRUB 命令行模式有几种方法:\n\n从 GRUB 启动菜单进入:\n在系统启动时如果看到 GRUB 启动菜单,可以按下 c 键直接进入 GRUB 命令行模式。这种方法适用于系统正常引导但需要手动控制启动过程的情况。\n在引导失败时自动进入\n如果系统引导失败例如无法找到内核或引导配置文件损坏GRUB 可能会自动进入命令行模式。这是一个提示,表明需要手动引导或修复引导配置。\n从子菜单进入命令行\n如果在 GRUB 启动菜单的高级选项或子菜单中,用户也可以通过按下 c 键进入命令行模式。这样可以在选择特定启动项之前先检查或修改启动参数。\n\nGRUB 命令行的基本操作\n进入 GRUB 命令行模式后,用户会看到一个类似于 shell 的界面,可以直接输入命令。以下是 GRUB 命令行的基本操作特点:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明用途示例set设置和显示 GRUB 环境变量用于设置或显示 GRUB 的环境变量,如根分区、启动参数等。显示环境变量: set 设置根分区: set root=(hd0,msdos1) 设置启动参数: set default=0insmod加载 GRUB 模块动态加载模块以支持特定功能,如文件系统或图形模式。加载文件系统模块: insmod ext2 加载视频模块: insmod vbe 加载 LVM 模块: insmod lvmlinux指定要启动的内核及其启动参数设置要引导的内核和传递给内核的启动参数。指定内核和启动参数 linux /vmlinuz-5.4.0-42-generic root=/dev/sda1 ro quiet splashinitrd指定内核的初始 RAM 磁盘映像设置内核启动时使用的初始 RAM 磁盘映像。指定 initrd 映像: initrd /initrd.img-5.4.0-42-genericboot启动操作系统启动由 linux 和 initrd 命令加载的内核。启动内核: bootls列出设备和分区列出可用的磁盘、分区以及指定分区中的文件和目录。列出磁盘和分区 ls 查看分区内容: ls (hd0,msdos1)/search搜索文件或设备查找指定的文件或设备根据给定的条件。搜索内核文件 search --file --no-floppy /vmlinuz-5.4.0-42-genericroot设置根分区设置启动时的根分区。设置根分区 root=(hd0,msdos1)configfile加载配置文件从指定路径加载 GRUB 配置文件。加载配置文件: configfile /boot/grub/grub.cfgreboot重启系统重新启动计算机。重启系统 reboothalt关闭系统关闭计算机。关闭系统 halt\nGRUB 命令行手动引导操作系统\n当自动引导失败或需要临时更改引导参数时可以手动加载内核并启动操作系统。以下是手动引导 Linux 系统的步骤:\n# 1. 设置根分区\nset root=(hd0,msdos1)\n \n# 2. 加载内核\nlinux /vmlinuz-5.4.0-42-generic root=/dev/sda1 ro quiet splash\n \n# 3. 加载 initrd\ninitrd /initrd.img-5.4.0-42-generic\n \n# 4. 启动系统\nboot\n常见问题的诊断和修复方法\n引导失败可能发生在 GRUB 安装或更新后,导致系统无法启动。以下是一些常见的原因和解决方法:\n错误的引导加载器安装\n重新安装 GRUB 可以解决大多数引导失败问题。首先,使用 Live CD/USB 启动系统,挂载系统分区,然后重新安装 GRUB。\n# 1. 启动到 Live CD/USB\n \n# 2. 挂载根文件系统\nsudo mount /dev/sda1 /mnt\n# (假设 /dev/sda1 是根分区,实际分区可能有所不同)\n \n# 3. 如果使用 UEFI还需要挂载 EFI 分区\nsudo mount /dev/sda2 /mnt/boot/efi\n# (假设 /dev/sda2 是 EFI 分区)\n \n# 4. 安装 GRUB\nsudo grub-install --root-directory=/mnt /dev/sda\n \n# 5. 更新 GRUB 配置\nsudo chroot /mnt\nsudo update-grub\nexit\n引导分区丢失或损坏\n如果引导分区丢失或损坏可以尝试以下步骤来恢复或重新创建引导分区\n\n\n检查分区表和分区类型 确保分区表MBR 或 GPT与当前系统配置一致。使用工具如 fdisk 或 parted 检查分区表和分区类型:\nsudo fdisk -l\nsudo parted -l\n\n\n恢复引导分区\n\n\n创建新的引导分区 使用分区工具(如 gparted 或 fdisk创建新的引导分区。请确保选择正确的文件系统如 ext4 或 FAT32取决于你的系统配置。\n\n\n重新安装 GRUB 挂载引导分区和根分区,并重新安装 GRUB。请参考以下步骤\nsudo mount /dev/sda1 /mnt # 假设 /dev/sda1 是根分区\nsudo mount --bind /dev /mnt/dev\nsudo mount --bind /proc /mnt/proc\nsudo mount --bind /sys /mnt/sys\nsudo mount /dev/sda2 /mnt/boot/efi # 如果使用 UEFI假设 /dev/sda2 是 EFI 分区\nsudo chroot /mnt\ngrub-install /dev/sda\nupdate-grub\nexit\n\n\n\n\n验证分区和 GRUB 配置: 确保分区和 GRUB 配置文件正确无误。检查 /etc/fstab 文件中的分区设置是否正确,以确保系统能够正确挂载分区。\n\n\n解决 GRUB 菜单不显示或错误加载的问题\n如果 GRUB 菜单不显示或加载错误,可以尝试以下方法解决问题:\n\n\n检查 GRUB 配置文件: 确保 /etc/default/grub 文件中的配置正确,并且 GRUB 配置文件 /boot/grub/grub.cfg 已正确生成。可以运行以下命令来重新生成配置文件:\nsudo update-grub\n\n\n重新安装 GRUB 如果菜单项不显示或 GRUB 引导程序损坏,可以重新安装 GRUB。以下步骤适用于 BIOS 和 UEFI 系统:\n\n\nBIOS 系统:\nsudo grub-install /dev/sda\nsudo update-grub\n\n\nUEFI 系统:\nsudo mount /dev/sda1 /mnt # 假设 /dev/sda1 是根分区\nsudo mount --bind /dev /mnt/dev\nsudo mount --bind /proc /mnt/proc\nsudo mount --bind /sys /mnt/sys\nsudo mount /dev/sda2 /mnt/boot/efi # 假设 /dev/sda2 是 EFI 分区\nsudo chroot /mnt\ngrub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub\nupdate-grub\nexit\n\n\n\n\n检查文件系统的完整性 使用 fsck 工具检查并修复文件系统错误。如果 GRUB 菜单项无法加载,可能是由于文件系统损坏:\nsudo fsck /dev/sda1\n\n\n使用 Live CD 或 Live USB 修复损坏的 GRUB 安装\nLive CD/USB 可以提供一个临时的操作环境,用于修复系统问题,包括 GRUB 安装问题。以下是进入救援模式的步骤:\n# 1. 启动 Live CD/USB 并进入 Live 环境\n \n# 2. 挂载系统分区\nsudo mount /dev/sda1 /mnt\n \n# 如果使用 UEFI还需挂载 EFI 分区\nsudo mount /dev/sda2 /mnt/boot/efi\n \n# 3. 进入 chroot 环境\nsudo chroot /mnt\n \n# 4. 重新安装 GRUB\ngrub-install /dev/sda\n \n# 5. 更新 GRUB 配置\nupdate-grub\n \n# 6. 退出 chroot 环境并卸载分区\nexit\nsudo umount /mnt/boot/efi\nsudo umount /mnt\nGRUB 安全配置\n设置 GRUB 密码保护\nGRUB 密码保护是一种有效的措施,用于防止未经授权的用户修改 GRUB 菜单项或启动参数,从而提高系统安全性。以下是配置 GRUB 密码保护的步骤:\n# 1. 生成加密密码\nsudo grub-mkpasswd-pbkdf2\n \n# 按提示输入密码后,命令会输出类似于以下的加密字符串\n# PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.<hash>\n \n# 2. 编辑 GRUB 配置文件\n# 打开配置文件并添加密码保护设置\n# 通常是 /etc/grub.d/40_custom\necho 'set superusers="root"' | sudo tee -a /etc/grub.d/40_custom\necho 'password_pbkdf2 root grub.pbkdf2.sha512.10000.<hash>' | sudo tee -a /etc/grub.d/40_custom\n \n# 3. 更新 GRUB 配置\nsudo update-grub\n设置 GRUB 用户和密码涉及以下步骤:\n# 1. 定义用户\n# 打开 /etc/grub.d/40_custom 文件,添加设置用户的指令\n# 使用 echo 命令追加到文件中\necho 'set superusers="admin"' | sudo tee -a /etc/grub.d/40_custom\n \n# 2. 设置密码\n# 使用 grub-mkpasswd-pbkdf2 生成加密密码,然后将其添加到配置文件中\n# 例如:使用以下命令生成加密密码\n# sudo grub-mkpasswd-pbkdf2\n# 输出类似于PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.<hash>\n# 将生成的 <hash> 替换到下面命令中\necho 'password_pbkdf2 admin grub.pbkdf2.sha512.10000.<hash>' | sudo tee -a /etc/grub.d/40_custom\n \n# 3. 更新 GRUB 配置\n# 保存更改并更新 GRUB 配置\nsudo update-grub\n配置用户认证和访问控制\nGRUB 本身不支持细粒度的权限控制,但可以通过不同的配置文件和密码保护机制来实现基础的用户认证和访问控制。\n\n单一用户模式\n如果需要一个简单的保护机制可以设置一个用户和一个密码如上所述。这可以防止未授权的用户访问或修改引导菜单。\n多用户配置\n虽然 GRUB 不原生支持多用户权限级别,但可以通过多重密码保护和分开管理不同的菜单项来模拟这种控制。例如,可以创建不同的菜单项,每个菜单项都有不同的密码保护。\n\n通过使用密码保护配置可以控制哪些用户能够访问特定的菜单项\n在 /etc/grub.d/40_custom 文件中,可以为每个菜单项设置不同的密码。例如\nshell```shell\nmenuentry “Restricted OS” {\nset superusers="admin"\n\npassword_pbkdf2 admin grub.pbkdf2.sha512.10000.<hash>\n\nlinux /boot/vmlinuz-linux root=/dev/sda1\n\n}\n\n只有提供正确密码的用户才能访问 `"Restricted OS"` 菜单项。在需要高度安全性的环境中,可以考虑以下策略:\n\n- **使用加密和保护配置文件**\n 确保 `/boot/grub/grub.cfg` 和 `/etc/grub.d/` 目录中的文件受到保护,防止未授权访问和修改。\n- **定期更新密码**\n 定期更换 GRUB 密码,并更新配置文件和 GRUB 设置。\n- **监控和审计**\n 监控系统的引导日志和配置文件的变更,以检测潜在的安全风险。\n\n### 配置 GRUB 以支持系统的磁盘加密\n\nGRUB 能够引导加密的操作系统,但需要额外的配置来处理加密磁盘。以下是配置 GRUB 以支持加密操作系统的步骤:\n\n- **配置 GRUB 以支持 LUKS 加密磁盘**LUKSLinux Unified Key Setup是常用的加密解决方案。在 GRUB 配置文件中,需要确保 GRUB 能够识别和解密加密的磁盘分区。\n\n- **编辑 GRUB 配置文件**:确保 GRUB 能够加载加密磁盘的模块。在 `/etc/grub.d/` 目录下的相关配置文件中,可以添加以下内容来加载加密支持:\n\n ```shell\n insmod cryptodisk\n insmod luks\n\n\n\n配置加密磁盘配置加密磁盘的详细信息。例如如果加密分区是 /dev/sda1可以在 /etc/grub.d/40_custom 中添加:\nmenuentry "Encrypted Linux" {\n insmod cryptodisk\n insmod luks\n set root='cryptomount'\n cryptomount -u UUID\n linux /vmlinuz-5.4.0-42-generic root=/dev/mapper/root ro quiet splash\n initrd /initrd.img-5.4.0-42-generic\n}\n\n\n配置 LUKS 加密磁盘与 GRUB 的兼容性\nLUKS 加密磁盘需要 GRUB 能够正确解密。以下是配置步骤:\n\n\n创建加密分区使用 LUKS 工具创建加密分区。例如:\ncryptsetup luksFormat /dev/sda1\n\n\n打开加密分区使用 LUKS 密钥解密分区,并创建映射:\ncryptsetup luksOpen /dev/sda1 cryptroot\n\n\n配置 initramfs确保 initramfs 能够处理 LUKS 加密磁盘。更新 initramfs 以包含 LUKS 支持:\nsudo update-initramfs -u\n\n\n实现基于密码的加密磁盘解锁\n加密磁盘解锁通常在引导时需要用户输入密码。以下是配置步骤\n\n\n配置 GRUB 提示解锁:在 GRUB 配置文件中,设置加密分区的 UUID并确保在引导时提示用户输入密码。\n\n\n配置加密解锁步骤在 GRUB 配置中添加用于解锁加密磁盘的设置cryptdevice=UUID=<UUID>:cryptroot 在 /etc/default/grub 中设置:\nGRUB_CMDLINE_LINUX="cryptdevice=UUID=<UUID>:cryptroot"\n\n\n\n更新 GRUB 和 initramfs重新生成 GRUB 配置和 initramfs\nsudo update-grub\nsudo update-initramfs -u\n\n\n\nGRUB 自定义与优化\n自定义 GRUB 菜单主题\n自定义 GRUB 菜单的外观可以提升用户体验和系统的视觉美感。以下是自定义 GRUB 菜单主题的步骤:\n\n\n准备自定义图片和资源\n\n准备适合的背景图片通常为 PNG 格式。\n确保图片尺寸符合屏幕分辨率以避免拉伸或失真。\n\n\n\n安装 GRUB 主题包\n可以通过下载现成的主题包或创建自己的主题包。常见的主题可以在网上找到也可以通过系统的包管理器安装。例如在 Ubuntu 中,可以安装 grub2-themes 包:\n\n\nsudo apt-get install grub2-themes\n\n\n配置自定义主题\n编辑 GRUB 配置文件以应用自定义主题。首先,将主题文件放置在 /boot/grub/themes/ 目录下,并确保主题文件夹包含 theme.txt 和相关资源文件。\n\n设置背景图片在 theme.txt 中,设置背景图片路径:\n\n # Background image\n background_image /boot/grub/themes/mytheme/background.png\n\n\n自定义字体和颜色在 theme.txt 中,设置字体和颜色:\n# Font\nfont /boot/grub/themes/mytheme/dejavu-sans.ttf\n \n# Colors\nmenu_color_normal = black/white\nmenu_color_highlight = white/black\n\n\n\n\n应用自定义主题\n在 /etc/default/grub 文件中,设置 GRUB_THEME 指令以启用自定义主题:\nGRUB_THEME=/boot/grub/themes/mytheme/theme.txt\n\n\n更新 GRUB 配置\n保存更改后更新 GRUB 配置以应用主题:\nsudo update-grub\n\n\n安装和配置自定义 GRUB 主题包\n\n下载并解压主题包将下载的主题包解压到 /boot/grub/themes/ 目录下,例如:\n\nsudo tar -xvf custom-theme.tar.gz -C /boot/grub/themes/\n\n配置 GRUB 使用新主题:编辑 /etc/default/grub 文件,设置 GRUB_THEME 指令:\n\nGRUB_THEME=/boot/grub/themes/custom-theme/theme.txt\n\n更新 GRUB 配置:运行更新命令以应用新主题:\n\nsudo update-grub\n调整菜单布局以提高可用性\n\n修改菜单项的布局在 theme.txt 文件中,可以调整菜单项的位置和对齐方式。例如:\n\nmenu_color_normal = cyan/blue\nmenu_color_highlight = red/black\n\n增加可用性选项可以根据需要调整菜单项的字体大小、颜色和选中效果以提升可用性。\n\n优化 GRUB 的启动速度和菜单配置\n通过减少超时和优化配置文件加快引导速度\nGRUB 的启动速度可以通过减少超时和优化配置来提高。\n\n\n减少超时\n编辑 /etc/default/grub 文件,减少 GRUB_TIMEOUT 的值来缩短引导菜单的显示时间。\n\n\n禁用不必要的菜单项\n删除不常用的菜单项以减少引导菜单的加载时间。可以编辑 /etc/grub.d/ 目录下的相关文件,删除不需要的菜单项。\n\n\n优化 GRUB 配置文件\n通过删除无用的模块和配置减少 GRUB 配置文件的复杂性,提高引导速度。\n\n"},"Technology/OperatingSystem/Linux/2.安装/Linux-下-0-1-手动安装-Arch-Linux":{"title":"Linux 下 0-1 手动安装 Arch Linux","links":[],"tags":["技术/操作系统","Linux/安装"],"content":"从 0 到 1 手动安装一个 Linux 发行版本确实是一个非常有价值的学习实践。以下是一个详细的方案和步骤,通过手动方式从分区开始安装 Linux。\n这里以 Arch Linux 为例,因为它是一个极简主义的发行版,允许你从头开始定制系统。可以根据实际情况选择参考 Arch Linux 官方的安装手册,也可以选择阅读下面的文章。\n0.前期准备\n\n\n获取 Arch Linux ISO 文件:从 Arch Linux 官方网站下载 最新的 ISO 文件。\n\n\n创建可引导的 USB 安装盘:使用 dd 或 Rufus 创建一个可引导的 USB 安装盘。\nsudo dd if=/path/to/archlinux.iso of=/dev/sdX bs=4M status=progress && sync\n这里 /dev/sdX 是你的 USB 设备。\n\n\n1.启动并进入 Arch Linux 环境\n1.1 从 USB 启动\n电脑开机选择从 USB 启动,进入 Arch Linux 的 Live 环境。\n1.2 网络连接\n首先确保网络接口已启动。通常在最小系统中不会有图形化的网络管理工具因此我们需要通过命令行手动管理网络接口。可以使用 ip 管理网络接口,不过重启后会重置)。\n# 查看网络接口\n# 这将列出所有网络接口以及它们的状态(`UP` 或 `DOWN`)。\nip link\n \n# 如果接口状态为 DOWN使用以下命令启动它。\n# 注意将 enp0s3 替换为你实际的网络接口名称。\nip link set enp0s3 up\n \n# 手动为某个网络接口配置静态 IP 地址。\n# 192.168.1.100/24 是你要设置的 IP 地址和子网掩码。\n# enp0s3 是你要配置的网络接口。\nip addr add 192.168.1.100/24 dev enp0s3\n \n# 配置默认网关,确保网络接口能够访问外部网络\n# 192.168.1.1 是默认网关的 IP 地址(通常是路由器的 IP 地址)。\nip route add default via 192.168.1.1\n \n# 查看网络配置\nip addr show enp0s3\n \n# 测试网络连接\nping -c 4 baidu.com\n1.3 配置 DNS可选\n如果 ping 域名失败,但 ping IP 地址成功,则可能是 DNS 配置有问题。\n编辑或创建 /etc/resolv.conf 文件,并添加公共 DNS 服务器,如 Google 的 DNS\necho "nameserver 223.5.5.5" > /etc/resolv.conf\necho "nameserver 8.8.8.8" >> /etc/resolv.conf\n1.4 同步时间\ntimedatectl set-ntp true\n2.磁盘分区\n2.1 查看磁盘\n在开始分区之前首先需要了解系统中的磁盘情况。使用以下命令查看磁盘设备和它们的现有分区\nfdisk -l\n这个命令会列出所有的磁盘及其分区。假设你的目标磁盘是 /dev/sda你可能将看到类似如下的输出\nDisk /dev/sda: 50 GiB, 53687091200 bytes, 104857600 sectors\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 4096 bytes\nI/O size (minimum/optimal): 4096 bytes / 4096 bytes\nDisklabel type: gpt\nDisk identifier: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n \nDevice Start End Sectors Size Type\n/dev/sda1 2048 1050623 1048576 512M EFI System\n/dev/sda2 1050624 42008575 40957952 20G Linux filesystem\n/dev/sda3 42008576 104857566 62848991 30G Linux filesystem\n在这个示例中磁盘 /dev/sda 上有三个分区,其中 /dev/sda1 是 EFI 系统分区,/dev/sda2 是根分区,/dev/sda3 是 Home 分区。\n2.2 分区磁盘\n接下来我们将使用 fdisk 来创建新的分区。以下是使用 fdisk 工具创建分区的详细步骤。\n2.2.1 启动 fdisk\n使用以下命令启动 fdisk 工具并开始分区:\nfdisk /dev/sda\n进入 fdisk 后,命令行会切换到交互模式,你将看到一个提示符类似 Command (m for help):。\n2.2.2 创建 EFI 系统分区\n\n\n输入 n 创建一个新分区。\nCommand (m for help): n\n\n\n选择分区类型通常默认是 primary直接按 Enter。\n\n\n选择分区号一般是 1按 Enter。\n\n\n选择起始扇区默认从 2048 开始,按 Enter。\n\n\n输入分区大小。例如为 EFI 系统分区分配 512MB+512M\nLast sector, +sectors or +size{K,M,G,T,P} (2048-104857599, default 104857599): +512M\n\n\n设置分区类型为 EFI 系统分区(类型代码为 1输入 t 修改类型:\nCommand (m for help): t\nSelected partition 1\nHex code (type L to list all codes): 1\n\n\n2.2.3 创建 root 根分区\n\n\n同样输入 n 创建新的根分区:\nCommand (m for help): n\n\n\n选择分区类型和分区号2然后按 Enter。\n\n\n选择起始扇区默认即可按 Enter。\n\n\n输入分区大小例如分配 20GB 给根分区(+20G\nLast sector, +sectors or +size{K,M,G,T,P} (1050624-104857599, default 104857599): +20G\n\n\n2.2.4 创建 Home 分区\n\n\n输入 n 创建 Home 分区:\nCommand (m for help): n\n\n\n选择分区类型和分区号3然后按 Enter。\n\n\n选择起始扇区默认即可按 Enter。\n\n\n直接按 Enter 使用剩余的所有空间:\nLast sector, +sectors or +size{K,M,G,T,P} (42008576-104857599, default 104857599): <Press Enter>\n\n\n2.2.5 保存分区表并退出\n\n\n输入 w 写入分区表并退出 fdisk\nCommand (m for help): w\n\n\n此时新分区已经创建并保存到磁盘中。\n2.3 格式化分区\n现在使用 mkfs 命令格式化新创建的分区:\n2.3.1 格式化 EFI 分区\nmkfs.fat -F32 /dev/sda1\n2.3.2 格式化根分区\nmkfs.ext4 /dev/sda2\n2.3.3 格式化 Home 分区\nmkfs.ext4 /dev/sda3\n2.4 交换分区(可选)\n如果需要交换分区你可以在磁盘上创建一个交换分区或选择使用交换文件。\n2.4.1 创建交换分区\n\n\n在分区时创建一个适合你系统需求大小的交换分区。例如创建一个 2GB 的交换分区。\n\n\n格式化交换分区\nmkswap /dev/sda4\n\n\n启用交换分区\nswapon /dev/sda4\n\n\n2.4.2 创建交换文件(可选)\n如果你不想使用交换分区可以使用以下步骤创建交换文件\n\n\n创建一个 2GB 的交换文件:\ndd if=/dev/zero of=/mnt/swapfile bs=1M count=2048\n\n\n将其格式化为交换文件格式\nmkswap /mnt/swapfile\n\n\n启用交换文件\nswapon /mnt/swapfile\n\n\n为了确保在系统重启后交换文件仍然有效你需要将其添加到 /etc/fstab 中:\necho '/mnt/swapfile none swap sw 0 0' | tee -a /etc/fstab\n\n\n至此你已经成功地完成了磁盘分区并格式化了各个分区。接下来你可以继续安装操作系统的其他部分。\n3.挂载分区\n3.1 挂载根分区\n# 挂载 root 根分区\nmount /dev/sda2 /mnt\n3.2 创建必要的目录并挂载\n# 创建 boot 目录,并挂载\nmkdir /mnt/boot\nmount /dev/sda1 /mnt/boot\n \n# 创建 home 目录,并挂载\nmkdir /mnt/home\nmount /dev/sda3 /mnt/home\n4.安装基础系统\n4.1 选择最快的镜像\n可以手动编辑 /etc/pacman.d/mirrorlist将最快的镜像放在顶部。\n4.2 安装基本包\n使用 pacstrap 命令安装基本系统。\npacstrap /mnt base linux linux-firmware\n4.3 生成 Fstab\n手动生成文件系统表并将其写入 fstab 文件。\ngenfstab -U /mnt >> /mnt/etc/fstab\n5.系统配置\n5.1 进入 Chroot 环境\narch-chroot /mnt\n5.2 设置系统时区\nln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\nhwclock --systohc\n5.3 设置系统语言\n手动编辑 /etc/locale.gen取消你需要的语言注释然后生成本地化设置。\nlocale-gen\necho "LANG=en_US.UTF-8" > /etc/locale.conf\n5.4 设置系统主机名\necho "your_hostname" > /etc/hostname\n5.5 设置 Hosts 文件\necho "127.0.0.1 localhost" > /etc/hosts\necho "::1 localhost" >> /etc/hosts\necho "127.0.1.1 your_hostname.localdomain your_hostname" >> /etc/hosts\n5.6 设置 Root 密码\npasswd\n6.引导加载程序\n根据你的系统BIOS 或 UEFI安装 GRUB 或 systemd-boot。\n6.1 对于 UEFI 系统\npacman -S grub efibootmgr\ngrub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB\ngrub-mkconfig -o /boot/grub/grub.cfg\n6.2 对于 BIOS 系统\npacman -S grub\ngrub-install --target=i386-pc /dev/sda\ngrub-mkconfig -o /boot/grub/grub.cfg\n7.完成和重启\n# 退出 chroot 并卸载\nexit\numount -R /mnt\nreboot\n如果一切正常你现在应该能够从硬盘启动进入新安装的 Arch Linux 系统。\n7.1 确认网络连接正常\n如果网络未连接请先重复 1.2 和 1.3 步骤。\n7.2 安装 NetworkManager 管理网络\n通过安装 NetworkManager你可以快速在最小化系统中配置网络确保系统能连接到互联网并正常工作。\npacman -S networkmanager\nsystemctl enable NetworkManager\nsystemctl start NetworkManager\n7.3 重启更新系统\n首先重启 Linux 确定 NetworkManager 工作正常,然后确保你的系统是最新的:\nreboot\nsudo pacman -Syu\n8.基本的桌面环境\n在 Arch Linux 上安装一个基本的桌面环境 (Desktop Environment, DE) 需要经过几个步骤,包括安装 X Window 系统、显卡驱动程序以及实际的桌面环境。以下是详细的步骤说明。\n8.1 安装 X Window 系统\nX Window 系统是 Linux 上大多数桌面环境的基础。你需要安装 xorg 相关的包:\nsudo pacman -S xorg-server xorg-apps xorg-xinit xterm\n\nxorg-server 是 X 服务器。\nxorg-apps 是一些有用的 X 应用程序。\nxorg-xinit 是 X 启动器。\nxterm 是一个基本的终端仿真器,供测试 X 环境使用。\n\n8.2 安装显卡驱动程序(可选)\n根据你的显卡类型安装相应的驱动程序。\n8.2.1 对于 Intel 显卡\nsudo pacman -S xf86-video-intel\n8.2.2 对于 NVIDIA 显卡:\n# 开源驱动\nsudo pacman -S nvidia nvidia-utils nvidia-settings\n \n# 闭源驱动\nsudo pacman -S xf86-video-nouveau\n8.2.3 对于 AMD 显卡\nsudo pacman -S xf86-video-amdgpu\n8.3 安装桌面环境\n你可以选择多种桌面环境根据你的需求选择一个。这里我将介绍如何安装几个常见的桌面环境。\n8.3.1 安装 GNOME 桌面环境\nGNOME 是一个功能齐全的桌面环境,适合需要稳定和易用性的用户。\nsudo pacman -S gnome gnome-extra\n安装完成后启用 gdmGNOME Display Manager\nsudo systemctl enable gdm\nsudo systemctl start gdm\n8.3.2 安装 KDE Plasma 桌面环境\nKDE Plasma 是一个高度可定制的桌面环境,适合喜欢自定义的用户。\nsudo pacman -S plasma kde-applications\n安装完成后启用 sddmSimple Desktop Display Manager\nsudo systemctl enable sddm\nsudo systemctl start sddm\n8.3.3 安装 XFCE 桌面环境\nXFCE 是一个轻量级且资源占用较低的桌面环境,适合性能较弱的机器。\nsudo pacman -S xfce4 xfce4-goodies\n你可以选择安装 lightdm 作为显示管理器:\nsudo pacman -S lightdm lightdm-gtk-greeter\nsudo systemctl enable lightdm\nsudo systemctl start lightdm\n8.4 使用 startx 启动\n如果你不使用显示管理器而是手动使用 startx 启动桌面环境,需要编辑 .xinitrc 文件。\nnano ~/.xinitrc\n在文件末尾添加你选择的桌面环境启动命令\n# GNOME\nexec gnome-session\n# KDE Plasma\nexec startplasma-x11\n# XFCE\nexec startxfce4\n保存并退出然后通过 startx 启动桌面环境:\nstartx\n8.5 重启系统并登录\n重启系统后你应该会被引导至图形登录界面。如果使用了显示管理器如 GDM、SDDM 或 LightDM你可以选择相应的桌面环境并登录。\nsudo reboot\n通过这些步骤你将成功安装并配置一个基本的桌面环境并能够在 Arch Linux 上运行图形化应用程序。如果有任何问题或需要进一步的帮助,请随时提问。\n9.完整的工作环境\n如果要将 Arch Linux 从一个最小的基础系统升级为一个功能齐全的工作环境,你需要安装和配置一些常用的工具和软件包。以下是一个全面的步骤指南,帮助你将 Arch Linux 系统完善到适合日常使用的状态。\n9.1 更新系统\n确保你的系统和包管理器处于最新状态\nsudo pacman -Syu\n9.2 安装基础开发工具\n这些工具对于编译软件或开发环境非常重要\nsudo pacman -S base-devel\nbase-devel 包括 gcc、make、binutils 等常用的开发工具。\n9.3 安装网络工具\n一些常用的网络工具如 wget、curl 和 net-tools在日常使用中非常有用\nsudo pacman -S wget curl net-tools openssh\n9.4 安装文件系统和磁盘管理工具\n这些工具有助于管理磁盘、文件系统和分区\nsudo pacman -S dosfstools exfat-utils ntfs-3g gparted\n\ndosfstools 和 exfat-utils支持 FAT 和 exFAT 文件系统。\nntfs-3g支持 NTFS 文件系统。\ngparted一个图形化的分区管理工具。\n\n9.5 安装常用编辑器\n根据你的喜好安装文本编辑器\nsudo pacman -S vim nano\n\nvim功能强大的文本编辑器。\nnano简单易用的文本编辑器。\n\n9.6 安装常用终端工具\n一些增强终端体验的工具\nsudo pacman -S htop tmux screen neofetch\n\nhtop互动的进程查看器。\ntmux 和 screen终端复用器允许在单个终端中运行多个会话。\nneofetch显示系统信息的工具。\n\n9.7 安装常用压缩工具\n安装一些常用的归档和解压工具\nsudo pacman -S unzip p7zip tar gzip\n9.8 安装常用字体\n安装一些常用字体以改善图形界面和文档的显示\nsudo pacman -S ttf-dejavu ttf-liberation noto-fonts\n9.9 安装浏览器\n选择并安装一个适合你的浏览器\nsudo pacman -S firefox\n你也可以选择 chromium或者在 AUR 中安装 google-chrome。\n9.10 安装常用的多媒体工具\n多媒体播放和管理工具\nsudo pacman -S vlc mpv\n\nvlc功能强大的媒体播放器。\nmpv轻量级的媒体播放器。\n\n9.11 安装办公软件\n如果需要办公软件可以安装 LibreOffice\nsudo pacman -S libreoffice-fresh\n9.12 安装 AUR 助手\nArch User Repository (AUR) 包含了大量社区维护的软件包,安装一个 AUR 助手会方便很多。yay 是一个常用的 AUR 助手。\n首先确保你安装了 git\nsudo pacman -S git\n然后克隆 yay 的仓库并安装它:\ncd /opt\nsudo git clone aur.archlinux.org/yay.git\nsudo chown -R $USER:$USER yay\ncd yay\nmakepkg -si\n安装完成后你可以通过 yay -S <package_name> 安装 AUR 软件包。\n9.13 安装实用工具\n安装一些实用工具提高使用体验\nsudo pacman -S ranger fzf fd ripgrep\n\nranger终端文件管理器。\nfzf模糊查找工具。\nfd 和 ripgrep快速文件和内容查找工具。\n\n9.14 安装打印和扫描支持\n如果你有打印和扫描需求可以安装以下软件包\nsudo pacman -S cups hplip simple-scan\n\ncups打印服务管理器。\nhplipHP 打印机驱动(适用于 HP 打印机用户)。\nsimple-scan简单易用的扫描工具。\n\n9.15 安装虚拟机支持\n如果你打算在 Arch Linux 上运行虚拟机,安装 VirtualBox 及其扩展包:\nsudo pacman -S virtualbox virtualbox-host-modules-arch\n9.16 启用常用服务\n确保一些关键服务开机自启例如\nsudo systemctl enable sshd\nsudo systemctl enable cups\nsudo systemctl enable NetworkManager\n9.17 安装额外的文件系统支持\n支持额外的文件系统例如 btrfs 或 zfs\nsudo pacman -S btrfs-progs\n如果需要 ZFS 支持,可以从 AUR 安装 zfs-linux。\n9.18 清理不需要的包\n清理系统中不再需要的孤立包\nsudo pacman -Rns $(pacman -Qdtq)"},"Technology/OperatingSystem/Linux/2.安装/Linux-下源代码编译与安装实战":{"title":"Linux 下源代码编译与安装实战","links":[],"tags":["Linux/高级","技术/操作系统"],"content":"概述\n编译和安装源代码是 Unix 和 Unix-like 系统中一个非常重要且基本的技能。通过这种方法你不仅可以获得软件的最新版本而且还可以根据自己的需求和偏好定制软件。在本指南中我们将通过一个具体实例Nginx 软件包)来详细讲解源代码编译和安装的全过程。\ngraph LR;\n A[开始] --> B[获取源代码];\n B --> C[安装编译依赖];\n C --> D[解压源代码];\n D --> E[配置];\n E --> F[编译];\n F --> G[安装];\n G --> H[测试];\n H --> I[运行和管理];\n I --> J[清理];\n J --> K[配置 Systemd 服务];\n K --> L[结束];\n\n\n第一步准备工作\n1. 获取源代码\n在开始编译和安装过程之前首先需要获取软件的源代码。这可以通过多种途径实现例如直接从官方网站下载源代码压缩包或使用版本控制系统如 git来克隆源代码仓库。\n# 使用 wget 命令下载源代码压缩包\nwget example.com/software-x.y.z.tar.gz\n \n# 或使用 git 克隆源代码仓库\ngit clone github.com/example/software.git\n2. 安装编译依赖\n在编译源代码之前通常需要安装一些依赖库和工具。这些依赖包括编译器如 gcc和其他必要的库。\nsudo apt update\nsudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev\n第二步配置与编译\n1. 解压源代码\n如果源代码是压缩包形式你需要解压它以访问源代码文件。\n# 使用 tar 命令解压源代码压缩包\ntar xvf software-x.y.z.tar.gz\n \n# 进入源代码目录\ncd software-x.y.z\n2. Configure 配置\n配置是准备编译的重要步骤通常通过运行 configure 脚本来完成。这个脚本会检测你的系统环境和参数,并准备好编译过程。\n# 运行 configure 脚本来配置软件包\n./configure --prefix=/usr/local\n常用的 configure 选项及其描述:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--prefix=PREFIX指定安装路径例如 /usr/local--enable-FEATURE启用某个特性--disable-FEATURE禁用某个特性--with-PACKAGE包含某个包的支持--without-PACKAGE不包含某个包的支持--help显示所有可用的 configure 选项--version显示程序版本和 configure 脚本信息--quiet, --silent禁止显示多余的输出--libdir=DIR指定库文件的安装目录--includedir=DIR指定头文件的安装目录--mandir=DIR指定 man 手册页面的安装目录--sysconfdir=DIR指定系统配置文件的安装目录--localstatedir=DIR指定本地状态数据如日志文件的安装目录--enable-shared启用或禁用共享库的构建--enable-static启用或禁用静态库的构建--enable-debug启用调试模式--enable-optimizations启用代码优化--host=HOST指定主机类型用于交叉编译--build=BUILD指定构建系统类型\n3. Make 编译\n配置完成后我们可以开始编译源代码了。这一步通常通过 make 命令来完成,它根据 Makefile 文件中的指令进行源代码编译。\n# 使用 make 命令来编译源代码\nmake\n常用目标\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n目标描述all编译所有的目标文件和链接成一个可执行程序默认目标install将编译好的程序和相关文件安装到指定的目录clean清理编译过程中产生的临时文件和目标文件distclean除了执行 clean 目标的操作外还会清理配置文件test 或 check运行程序的测试套件uninstall从指定目录中移除之前通过 make install 安装的文件\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-j [N]允许同时执行 N 个作业(如果未指定 N则自动选择基于可用 CPU 核心的数量)-k 或 --keep-going即使有错误发生也继续尽可能多的编译--silent 或 -s禁止显示执行的命令--always-make 或 -B无论目标文件是否最新都重新构建所有目标-f FILE 或 --file=FILE指定一个非标准名称的 Makefile 文件来使用--debug为调试 make 而显示调试信息-n 或 --just-print显示但不执行命令-q 或 --question无输出模式用来检查指定目标是否已经是最新的-C DIRECTORY在执行 make 命令前,先切换到指定的目录\n第三步安装与测试\n1. 安装\n编译完成后下一步是将软件包安装到系统中。这也是通过运行 make 命令完成的,但常配合 install 目标来将文件安装到正确的位置。\n# 使用 make 命令来安装软件包\nsudo make install\n2. 测试\n某些软件包提供了测试步骤允许你在安装之前测试以确保一切正常。\n# 使用 make 命令来测试软件包\nmake test\n第四步后续管理和清理\n1. 运行和管理\n安装完成后你可以使用相应的命令来启动、停止或重载服务。例如在 Nginx 的情况下,你可以使用以下命令:\n# 启动 Nginx 服务\nsudo /usr/local/nginx/sbin/nginx\n \n# 停止 Nginx 服务\nsudo /usr/local/nginx/sbin/nginx -s stop\n \n# 重新加载 Nginx 配置\nsudo /usr/local/nginx/sbin/nginx -s reload\n2. 清理\n最后为了保持系统整洁你可以选择清理编译时生成的临时文件。\n# 使用 make 命令来清理编译生成的文件\nmake clean\n第五步配置 Systemd 服务\n如果你希望你的新安装的服务例如 Nginx更好地集成到系统中可以考虑为它创建一个 Systemd 服务单元文件。这样,你就可以用 Systemd 来管理这个服务了。\n1. 创建 Systemd 服务单元文件\n首先我们需要创建一个新的 Systemd 服务单元文件。打开一个文本编辑器并创建一个新文件,通常位于 /etc/systemd/system/ 目录,并以 .service 扩展名结尾。\nsudo nano /etc/systemd/system/nginx.service\n2. 编辑服务单元文件\n在这个文件中我们将定义服务的各种属性包括如何启动和停止服务。以下是一个简单的 Nginx Systemd 服务单元文件示例:\n[Unit]\nDescription=The NGINX HTTP and reverse proxy server\nAfter=network.target\n \n[Service]\nType=forking\nPIDFile=/usr/local/nginx/logs/nginx.pid\nExecStartPre=/usr/local/nginx/sbin/nginx -t\nExecStart=/usr/local/nginx/sbin/nginx\nExecReload=/usr/local/nginx/sbin/nginx -s reload\nExecStop=/usr/local/nginx/sbin/nginx -s stop\nPrivateTmp=true\n \n[Install]\nWantedBy=multi-user.target\n3. 重新加载 Systemd\n创建或修改任何 Systemd 服务单元文件后,你需要运行以下命令来重新加载 Systemd使其识别新的或更改的服务单元文件\nsudo systemctl daemon-reload\n4. 启动和启用服务\n现在你可以使用 systemctl 命令来启动 Nginx 服务,并将其设置为在系统启动时自动启动:\nsudo systemctl start nginx\nsudo systemctl enable nginx\n5. 状态和日志\n你可以使用以下命令来检查服务的状态和日志\n# 检查服务状态\nsudo systemctl status nginx\n \n# 查看服务日志\nsudo journalctl -u nginx"},"Technology/OperatingSystem/Linux/2.安装/Linux-发行版镜像":{"title":"Linux 发行版镜像","links":[],"tags":["技术/操作系统","Linux/安装"],"content":"操作系统镜像\n操作系统镜像Operating System Image是操作系统及其配置、软件包和文件系统结构的一个完整副本可以用于在计算设备上安装和部署操作系统。镜像通常以文件的形式存在可以被烧录到光盘、U 盘或硬盘中,也可以直接用于虚拟化和云环境的部署。\n作用和用途\n\n快速部署镜像可以用来快速部署操作系统不需要从头安装和配置每个软件包节省时间和精力。\n一致性使用相同的镜像可以确保不同设备上的操作系统环境一致有助于维护和管理。\n备份和恢复镜像可以用作系统备份确保在系统故障时能够快速恢复到正常状态。\n定制化可以创建定制的镜像包含特定的应用程序和配置满足特定需求。\n分发和分发操作系统镜像可以用来分发操作系统使得用户能够方便地安装和使用。\n\n镜像的历史和发展\n\n早期阶段在计算机的早期阶段操作系统的安装通常依赖于软盘和磁带。操作系统镜像的概念尚未广泛应用用户需要手动安装和配置操作系统。\n光盘时代随着 CD 和 DVD 的普及,操作系统开始以光盘镜像的形式发布。用户可以通过引导光盘安装操作系统,这简化了安装过程。\n虚拟化和云计算的兴起随着虚拟化技术的发展操作系统镜像开始被用于虚拟机的创建和管理。云计算的兴起进一步推动了镜像技术的发展云服务提供商开始提供优化的操作系统镜像便于用户在云环境中快速部署和扩展。\n\n各类镜像的演变\n\n基本镜像最早期的镜像类型通常用于本地和虚拟机安装。包含最小化的操作系统组件和核心工具。\n现场救援镜像Live Image可以从可移动介质启动不需要安装即可运行操作系统。用于系统故障修复和数据恢复。\n云服务镜像专为云环境优化和定制的镜像预装了云提供商的特定工具和驱动提升了在云环境中的性能和兼容性。\n容器镜像用于容器化技术的轻量级操作系统镜像包含运行应用所需的最低限度的操作系统组件支持跨不同环境的一致运行。\n定制镜像根据特定需求或应用场景定制的镜像包含特定应用、配置和优化适用于特定业务需求。\n物理服务器镜像专为物理服务器优化的镜像包含特定的驱动和固件优化系统性能和可靠性。\n虚拟化镜像专为虚拟化平台优化的镜像包含虚拟化平台的驱动和工具提升虚拟机的运行效率和管理便捷性。\n\n基本镜像\n基本镜像Base Image是操作系统及其最小必要组件的完整副本通常用于本地安装、虚拟机创建或作为其他镜像的基础。它包含操作系统的核心功能、基本工具和库但不包括特定的应用软件和服务。\n典型特点\n\n最小化只包含操作系统的核心组件和基础工具提供一个精简的环境。\n通用性适用于多种硬件和虚拟化平台不针对特定的硬件或云环境进行优化。\n稳定性通常选择稳定版本经过充分测试确保在各种环境下运行稳定。\n可扩展性用户可以根据需要添加额外的软件包和配置进行定制和扩展。\n\n容器镜像\n**容器镜像Container Image是一个包含应用程序及其所有依赖环境的只读模板用于创建容器。**镜像由多个层组成,每一层代表镜像的一个版本。\n典型特点\n\n不可变性镜像一旦创建就不会改变确保了应用环境的一致性。\n分层存储镜像由多个层组成每一层可以复用减少存储空间和提高构建效率。\n便携性镜像可以在任何支持容器的平台上运行实现真正的“构建一次运行到处”。\n快速部署镜像可以快速启动极大地缩短应用的部署时间。\n\n定制镜像\n**定制镜像Custom Image是根据特定需求或应用场景创建的操作系统镜像。**与标准镜像相比,定制镜像包含了特定的软件包、配置和优化,旨在满足特定业务或应用的需求。\n应用场景\n\n企业部署企业可以创建包含预先配置的应用和服务的定制镜像以快速部署一致的工作环境。\n开发和测试开发团队可以创建包含所有开发工具和依赖的定制镜像确保开发环境和生产环境的一致性。\n自动化部署在 CI/CD 流水线中使用定制镜像,确保每次部署都基于相同的环境,提高部署的可靠性和速度。\n安全和合规创建包含安全补丁和配置的定制镜像确保部署的系统符合安全和合规要求。\n\n虚拟化镜像\n**虚拟化镜像Virtual Machine Image是用于创建和运行虚拟机的操作系统镜像**包含操作系统及其配置、驱动程序和预安装的应用程序。虚拟化镜像可在虚拟化平台上运行,为虚拟机提供基础环境。\n典型特点\n\n硬件抽象虚拟化镜像与底层硬件解耦可以在不同的物理硬件上运行。\n快照和克隆支持快照和克隆功能可以快速创建和恢复虚拟机状态。\n资源管理可以灵活分配和调整 CPU、内存、存储和网络资源提高资源利用率。\n高可用性支持高可用性和灾难恢复功能确保虚拟机的持续运行。\n\n云服务镜像\n**云服务镜像Cloud Service Image是专为云计算环境设计和优化的操作系统镜像。**它们通常由云服务提供商(如 AWS、Google Cloud、Azure 等)预配置和发布,包含操作系统、必要的驱动程序和云服务的特定工具,以便在云环境中高效运行。\n典型特点\n\n预配置工具内置云服务提供商的管理工具和驱动程序如 AWS CLI、GCP SDK 等),方便用户与云服务的集成和管理。\n优化针对云平台的硬件和网络环境进行优化提高性能和兼容性。\n自动扩展支持云环境中的自动扩展和缩减功能适应动态负载需求。\n安全性内置安全优化和补丁管理确保镜像在云环境中的安全性。\n高可用性设计为在分布式和冗余的云架构中高效运行提供高可用性和故障恢复能力。\n\n物理服务器镜像\n**物理服务器镜像Physical Server Image是专为部署在物理服务器上的操作系统镜像。**它包含了操作系统及其配置、必要的驱动程序和预安装的应用程序,通常用于在企业数据中心或高性能计算环境中部署和管理物理服务器。\n典型特点\n\n硬件优化包含针对特定硬件平台如特定的 CPU、存储设备、网络接口等优化的驱动程序和配置。\n高性能通过优化 I/O 性能、内存管理和网络配置,最大化物理服务器的性能。\n高可用性设计为在高可靠性和高可用性要求的环境中运行包含冗余配置和故障恢复机制。\n可定制性可以根据特定需求预装应用程序和服务满足业务需求。\n\n不同类型镜像的对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性基本镜像容器镜像定制镜像虚拟化镜像云服务镜像物理服务器镜像定义最小化操作系统镜像容器化应用镜像根据特定需求创建的操作系统镜像创建和运行虚拟机的操作系统镜像云环境优化操作系统镜像部署在物理服务器上的镜像特点最小化、通用性、可扩展性轻量化、不可变性、分层存储、便携性高度定制化、优化、维护硬件抽象、快照和克隆、资源管理、高可用性预配置工具、优化、自动扩展、安全性硬件优化、高性能、高可用性使用场景本地安装、虚拟机环境容器化应用、微服务架构企业部署、开发和测试、自动化部署虚拟化平台、资源管理云计算环境、自动扩展企业数据中心、高性能计算环境维护通常由社区或发行商维护用户自行维护和更新需要自行维护和更新虚拟化平台提供支持和管理由云服务提供商和用户共同维护企业内部维护性能适中轻量级高性能优化后的高性能适中优化后的性能高性能安全性需要自行配置和管理需要自行管理和扫描定制的安全配置和优化依赖虚拟化平台的安全功能内置安全优化和补丁管理高安全性配置可移植性高高中高云平台内可移植低\n使用场景评分参照表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n场景/需求基本镜像容器镜像定制镜像虚拟化镜像云服务镜像物理服务器镜像开发环境⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐测试环境⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐生产环境⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐微服务架构⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐CI/CD 流水线⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐混合云部署⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐高性能计算⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐企业数据中心⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐自动化部署⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐灾难恢复⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐资源管理⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐安全性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐\n"},"Technology/OperatingSystem/Linux/2.安装/Linux-安装和配置":{"title":"Linux 安装和配置","links":[],"tags":["Linux/安装","技术/操作系统"],"content":"GNU/Linux 发行版的选择和下载\nGNU/Linux 有许多不同的发行版可供选择,如 Debian、CentOS/RHEL、 Ubuntu 等,它们都有自己的特点和适用场景。下表列出了几种常见的 GNU/Linux 发行版及其特点和适用场景。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n发行版特点适用场景官方网站中国国内官方镜像站点Ubuntu易用、更新快、软件库丰富个人、办公、教育等领域ubuntu.com/https://mirrors.ustc.edu.cn/Debian稳定、安全、软件包多服务器、开发等领域www.debian.org/https://mirrors.ustc.edu.cn/CentOS稳定、安全、兼容性好、商业支持企业级应用、服务器等领域www.centos.org/https://mirrors.ustc.edu.cn/Red Hat Enterprise Linux (RHEL)稳定、安全、商业支持、适用于企业级应用企业级应用、服务器等领域www.redhat.com/zh/technologies/linux-platforms/enterprise-linuxFedora最新的开源软件、社区驱动开发、实验、桌面等领域getfedora.org/https://mirrors.ustc.edu.cn/Arch Linux简单、灵活、滚动更新开发、实验、高级用户等领域www.archlinux.org/https://mirrors.ustc.edu.cn/\n以下是一些常用的中国国内 GNU/Linux 官方镜像站点:\n\n清华大学开源软件镜像站mirrors.tuna.tsinghua.edu.cn/\n阿里云开源镜像站mirrors.aliyun.com/\n网易开源镜像站mirrors.163.com/\n中科大开源镜像站mirrors.ustc.edu.cn/\n华中科技大学开源镜像站mirrors.hust.edu.cn/\n上海交通大学开源软件镜像站ftp.sjtu.edu.cn/\n北京交通大学开源软件镜像站mirror.bjtu.edu.cn/\n北京理工大学开源镜像站mirror.bit.edu.cn/\n\n可以根据自己的需求来选择最适合自己的 GNU/Linux 发行版。例如,如果您需要一个易于使用、更新快、软件库丰富的发行版,那么 Ubuntu 是一个不错的选择;如果您需要一个稳定、安全、软件包多的发行版,那么 Debian 可能更适合您的需求。\nGNU/Linux 的安装和配置\n在选择好自己的发行版后我们需要将其安装到计算机上并进行配置。下面是 GNU/Linux 安装的一些基本步骤:\n\n下载并刻录光盘或制作 U 盘启动盘。\n进入 BIOS 设置,设置计算机从光盘或 U 盘启动。\n启动后进入安装程序进行分区、格式化、挂载硬盘等操作。\n安装操作系统并进行基本设置如选择时区、语言、设置用户等。\n\n安装完成后我们需要对 GNU/Linux 进行基本配置,以确保系统的正常运行。下面是一些基本的配置步骤:\n\n配置基本系统设置如修改主机名、设置 IP 地址等。\n设置时区、语言、字符集等。\n配置网络连接如设置网卡、DHCP 等。\n安装和配置必要的软件包如 SSH、防火墙等。\n\n建议在虚拟机环境下进行安装、配置、学习同时学会利用虚拟机快照功能可以事半功倍。可以合理使用 LinuxMirrors 一键更换国内软件源。\nLinuxMirrors\nGNU/Linux 一键更换国内软件源脚本\nLinuxMirrors 旨在为从事计算机相关行业的朋友们提供便利\nbash <(curl -sSL gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)\nGNU/Linux 的基本设置和管理\n在完成基本的配置后我们需要对 GNU/Linux 进行一些基本的设置和管理。下面是一些常见的设置和管理操作:\n\n配置用户和权限如添加用户、设置用户组、分配权限等。\n管理软件包如更新、安装、删除软件包等。\n配置服务如启动、停止、重启服务等。\n监控系统性能如查看系统负载、内存使用情况等。\n备份和恢复系统如定期备份数据、恢复系统等。\n\nCockpit\n\nThe easy-to-use, integrated, glanceable, and open web-based interface for your servers\n\nCockpit 是一款基于 Web 的 GNU/Linux 服务器管理工具,它提供了图形化的用户界面,使得管理和监控服务器变得更加简单和易于操作。\n\n安装手册\n官方文档\n"},"Technology/OperatingSystem/Linux/2.安装/Linux-无法启动排查指南":{"title":"Linux 无法启动排查指南","links":[],"tags":["技术/操作系统","Linux/安装"],"content":"摘要\n本文档系统性地介绍了 Linux 操作系统在无法正常启动时的排查与解决方法。本文档旨在为系统管理员和高级用户提供一套全面的方法论,以有效识别、诊断和解决操作系统启动过程中可能遇到的问题。该手册涵盖了从引导加载器到用户环境的各个层面,并提供了详细的操作步骤和解决方案。\n1. 引言\nLinux 系统广泛应用于服务器、工作站和嵌入式设备中。尽管 Linux 被誉为稳定和可靠的操作系统,但启动失败的问题仍然可能由于多种原因而发生。排查 Linux 系统启动问题是一个复杂且具有挑战性的过程,涉及多种系统组件的协同工作。为了帮助用户更有效地解决此类问题,本文档将详细探讨从 BIOS/UEFI 设置到用户空间环境的各个阶段,并提供系统化的排查与修复指南。\n2. 引导加载阶段的排查\n2.1 BIOS/UEFI 设置问题\n2.1.1 问题描述\nBIOS基本输入输出系统或 UEFI统一可扩展固件接口是启动过程中最先被执行的固件程序。错误的设置可能导致系统无法正确加载 Linux 操作系统。\n2.1.2 解决方案\n\n检查启动顺序\n\n进入 BIOS/UEFI 设置界面(通常通过按下 Del, F2, Esc 或 F10 键)。\n确保硬盘或 SSD 被设置为第一启动设备。\n如果使用 UEFI请确保选择了正确的引导模式UEFI 或 Legacy。\n\n\nUEFI/Legacy 模式:\n\n确保与系统安装时的启动模式一致。如果系统是以 UEFI 模式安装的,则需要在 UEFI 模式下启动;反之亦然。\n\n\n\n2.2 GRUB 引导加载器问题\n2.2.1 问题描述\nGRUBGrand Unified Bootloader是常用的引导加载器它负责加载 Linux 内核。如果 GRUB 配置文件损坏或丢失,可能导致无法进入操作系统。\n2.2.2 解决方案\n\n\nGRUB 命令行修复:如果系统停留在 GRUB 命令行界面,可以手动引导:\nset root=(hd0,1) # 设置根分区,可能需要调整分区编号\nlinux /vmlinuz-xxx root=/dev/sda1 ro\ninitrd /initrd.img-xxx\nboot\n若手动引导成功需在进入系统后重新安装和配置 GRUB\nsudo grub-install /dev/sda # 安装到主硬盘\nsudo update-grub # 更新 GRUB 配置\n\n\n使用 Live CD/USB 修复 GRUB从 Live CD/USB 启动系统,打开终端:\nsudo mount /dev/sda1 /mnt # 假设 /dev/sda1 是根分区\nsudo grub-install --root-directory=/mnt /dev/sda\nsudo chroot /mnt\nupdate-grub\n重启系统检查问题是否解决。\n\n\n2.3 MBR 和 GPT 分区表问题\n2.3.1 问题描述\nMBRMaster Boot Record和 GPTGUID Partition Table是两种主要的分区表格式。系统启动失败有时可能与损坏的分区表或不兼容的分区表格式有关。如果分区表损坏或引导记录丢失系统将无法正确引导。\n2.3.2 解决方案\n\n\n检查分区表类型与兼容性\n\n在 BIOS/UEFI 中确认是否与系统的分区表格式MBR 或 GPT兼容。如果使用 UEFI 模式,则应使用 GPT 分区表;而 Legacy 模式通常需要 MBR 分区表。\n使用 fdisk -l 或 gdisk -l 检查当前硬盘的分区表格式。\n\n\n\n修复 MBR如果使用的是 MBR 分区表并且怀疑其损坏,可以使用以下命令修复 MBR\nsudo dd if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sda\n或者通过 Windows 的 bootrec 工具修复:\nbootrec /fixmbr\n\n\n修复 GPT对于 GPT 分区表,如果有损坏,可以使用 gdisk 工具修复:\nsudo gdisk /dev/sda\n在 gdisk 提示符下输入 v 检查 GPT 的一致性,输入 w 写入并退出。\n\n\n重建分区表如果分区表严重损坏且无法修复可能需要从头创建新的分区表。这将导致数据丢失因此建议先备份数据然后使用 parted 或 gparted 重建分区表。\n\n\n2.4 EFI 引导文件问题\n2.4.1 问题描述\n在 UEFI 系统中EFI 引导文件(通常存储在 EFI 系统分区内)负责引导操作系统。如果 EFI 引导文件丢失或损坏,系统将无法启动。\n2.4.2 解决方案\n\n\n确认 EFI 系统分区的挂载:使用以下命令检查 EFI 系统分区是否正确挂载:\nls /boot/efi\n如果 EFI 分区未挂载,手动挂载它:\nsudo mount /dev/sda1 /boot/efi # 假设 /dev/sda1 是 EFI 分区\n\n\n重建 EFI 引导文件:使用 efibootmgr 工具重建 EFI 引导条目:\nsudo efibootmgr --create --disk /dev/sda --part 1 --label "Linux" --loader \\\\EFI\\\\debian\\\\grubx64.efi\n在某些情况下可能需要手动复制 GRUB EFI 文件到 EFI 分区:\nsudo cp /boot/grub/x86_64-efi/grub.efi /boot/efi/EFI/ubuntu/grubx64.efi\n\n\n修复 EFI 引导条目:如果 BIOS/UEFI 无法检测到正确的 EFI 引导条目,使用 Live CD/USB 重新安装 GRUB 到 EFI 分区:\nsudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB\nsudo update-grub\n\n\n2.5 引导配置文件(如 grub.cfg损坏\n2.5.1 问题描述\nGRUB 的引导配置文件 grub.cfg 可能因配置错误或损坏而导致系统无法正常启动。\n2.5.2 解决方案\n\n\n重建 grub.cfg进入恢复模式或使用 Live CD/USB 启动,重新生成 grub.cfg 文件:\nsudo grub-mkconfig -o /boot/grub/grub.cfg\n\n\n检查和修复 grub.cfg手动检查 grub.cfg 文件中的启动条目,确保路径和分区设置正确,特别是内核和 initrd 的路径。\n\n\n2.6 其他引导加载器问题(如 LILO, Syslinux\n2.6.1 问题描述\n虽然 GRUB 是最常见的引导加载器,但在某些系统中可能使用 LILO 或 Syslinux。如果这些引导加载器配置错误也会导致无法正常启动。\n2.6.2 解决方案\n\n\nLILO 修复:如果使用 LILO 作为引导加载器,可以通过 Live CD/USB 启动系统,并使用以下命令修复 LILO 配置:\nsudo lilo -M /dev/sda mbr\nsudo lilo\n\n\nSyslinux 修复:对于使用 Syslinux 的系统,可以使用 syslinux-install_update 工具重新安装引导加载器:\nsudo syslinux-install_update -i -a -m\n\n\n3. 内核加载阶段的排查\n3.1 内核崩溃Kernel Panic\n3.1.1 问题描述\nKernel Panic 是 Linux 内核在遇到无法恢复的错误时发生的现象。可能是由于不兼容的硬件驱动或损坏的内核模块引起。\n3.1.2 解决方案\n\n进入安全模式在 GRUB 菜单中选择高级选项,然后选择一个带有 (recovery mode) 的内核版本。\n禁用 quiet 和 splash 参数:编辑 GRUB 启动参数(在 GRUB 菜单中按 e删除 quiet 和 splash 选项,以便详细查看启动日志。\n使用旧版本内核选择旧版本的内核启动系统。如果旧内核可以正常启动说明问题可能出在新内核或新模块上。可以通过移除或重新编译问题模块来解决。\n\n3.2 内核模块加载失败\n3.2.1 问题描述\n内核模块加载失败通常与硬件不兼容或模块配置错误有关。\n3.2.2 解决方案\n\n\n检查内核日志使用 dmesg 或 cat /var/log/kern.log 查看内核日志,查找模块加载失败的相关错误信息。\n\n\n禁用或重新编译模块如果确定是某个特定模块导致问题可以尝试禁用该模块。例如编辑 /etc/modprobe.d/blacklist.conf 文件,将模块加入黑名单:\n\n\n blacklist 模块名\n或者重新编译内核并调整模块配置以确保模块的兼容性。\n3.3 内核参数错误\n3.3.1 问题描述\n内核启动参数是影响内核行为的关键因素。配置错误或不兼容的内核参数可能导致系统无法正常启动。\n3.3.2 解决方案\n\n检查并修改内核启动参数\n\n在 GRUB 菜单中,按 e 编辑启动条目,检查 linux 行中的启动参数。\n确保没有冲突的参数如过度调优的内存参数或与硬件不兼容的选项。常见的参数包括 nomodeset禁用内核模式设置、acpi=off禁用 ACPI等。\n如果怀疑参数有问题尝试移除或调整特定参数并启动系统。\n\n\n恢复默认启动参数如果内核启动参数被修改导致系统无法启动可以通过 GRUB 菜单恢复到默认启动参数。例如,通过选择不带特殊参数的内核版本或恢复模式启动。\n\n3.4 内核升级或降级问题\n3.4.1 问题描述\n在内核升级或降级过程中可能会引入不兼容的问题导致系统在加载新的或旧的内核时失败。\n3.4.2 解决方案\n\n\n切换到不同版本的内核在 GRUB 菜单中选择高级选项,然后选择不同版本的内核进行启动。确认问题是否与特定内核版本相关。\n\n\n回退到上一个工作内核如果新内核导致问题使用以下命令卸载问题内核并安装上一个稳定的内核\nsudo apt-get remove linux-image-版本号\nsudo apt-get install linux-image-旧版本号\n更新 GRUB 并重启系统:\nsudo update-grub\nsudo reboot\n\n\n检查内核依赖内核升级或降级过程中可能需要更新或回退与内核相关的驱动程序或模块。使用 dkms 工具管理这些模块,并确保它们与当前内核版本兼容:\nsudo dkms status\nsudo dkms install 模块名/版本号\n\n\n3.5 内核和初始内存盘initramfs问题\n3.5.1 问题描述\ninitramfs 是一个临时文件系统,负责在根文件系统挂载之前提供必要的驱动和工具。如果 initramfs 文件损坏或配置错误,系统可能无法启动。\n3.5.2 解决方案\n\n\n重建 initramfs使用 Live CD/USB 启动系统或进入恢复模式,重建 initramfs\nsudo update-initramfs -u -k all\n确保所有必要的驱动程序和模块被正确包含在 initramfs 中。\n\n\n检查 initramfs 配置:确保 /etc/initramfs-tools/conf.d/ 中的配置文件没有错误,特别是 MODULES 和 BOOT 参数是否设置正确。\n\n\n检查 initramfs 损坏情况:检查 /boot 目录下的 initrd.img 文件是否存在并正确。可以通过重新生成或从备份中恢复损坏的文件:\n\n\n sudo mkinitramfs -o /boot/initrd.img-$(uname -r)\n3.6 硬件兼容性与内核驱动问题\n3.6.1 问题描述\n某些硬件设备可能与当前内核不兼容或者需要特定的驱动程序支持。如果缺少必要的驱动内核可能无法正常加载或初始化设备导致启动失败。\n3.6.2 解决方案\n\n\n检查硬件兼容性使用 lspci、lsusb、dmidecode 等工具查看系统硬件信息,并确认是否与内核兼容。特别注意新安装的硬件设备是否需要额外的驱动支持。\n\n\n安装或更新硬件驱动如果硬件设备无法正常工作尝试安装或更新驱动程序。例如对于图形设备\nsudo apt-get install nvidia-driver-版本号 # 对于 NVIDIA 显卡\n对于其他硬件设备可能需要从厂商获取并编译驱动程序。\n\n\n内核调试与测试\n\n启用内核调试选项如 debug 参数),捕获详细的内核日志,并分析硬件初始化过程中可能存在的问题。\n使用 modprobe 命令手动加载或卸载驱动模块,测试硬件设备与内核的兼容性。\n\n\n\n4. 文件系统的排查与修复\n4.1 文件系统完整性检查\n4.1.1 问题描述\n文件系统损坏会导致系统启动失败通常表现为无法挂载根分区或其他关键分区。\n4.1.2 解决方案\n\n\n使用 fsck 修复文件系统:进入恢复模式或使用 Live CD/USB 启动,并运行以下命令:\nsudo fsck /dev/sda1 # 假设 /dev/sda1 是根分区\n如果提示修复错误按照提示进行操作。\n\n\n4.2 分区挂载问题\n4.2.1 问题描述\n系统无法正确挂载分区可能导致启动失败通常由 /etc/fstab 配置错误引起。\n4.2.2 解决方案\n\n\n检查并修复 /etc/fstab\n\n\n使用 Live CD/USB 启动系统并编辑 /etc/fstab确保挂载点和分区设置正确。\n\n\n手动尝试挂载分区验证是否存在问题\n\n\n\n\nsudo mount /dev/sda1 /mnt # 假设 /mnt 是临时挂载点\n\n如果挂载失败检查分区是否存在物理损坏。\n\n4.3 文件系统类型不兼容\n4.3.1 问题描述\n在某些情况下系统可能尝试挂载一个不支持的文件系统类型或者文件系统类型在内核中未被正确加载。这通常会导致系统启动失败或某些分区无法挂载。\n4.3.2 解决方案\n\n\n确认文件系统类型使用 lsblk -f 或 blkid 命令检查分区的文件系统类型,确认分区是否使用了 Linux 支持的文件系统(如 ext4, xfs, btrfs 等)。\n检查内核模块是否支持该文件系统类型。例如 btrfs 文件系统需要 btrfs 模块:\nsudo modprobe btrfs\n\n\n转换文件系统类型如果文件系统类型不兼容或需要更换可以使用工具将文件系统转换为兼容的格式但在操作前务必备份数据。例如从 ext2 转换到 ext4\nsudo tune2fs -O extents,uninit_bg,dir_index /dev/sda1\nsudo e2fsck -f /dev/sda1\n\n\n重新格式化分区如果文件系统已损坏且不可修复可以考虑重新格式化分区这将清空数据\nsudo mkfs.ext4 /dev/sda1\n之后编辑 /etc/fstab确保系统能够正确挂载该分区。\n\n\n4.4 LVM 逻辑卷管理问题\n4.4.1 问题描述\nLVM逻辑卷管理使得磁盘分区的管理更加灵活但如果逻辑卷或物理卷出现问题可能导致系统无法启动或某些分区无法挂载。\n4.4.2 解决方案\n\n\n检查 LVM 状态:使用以下命令检查 LVM 卷组和逻辑卷的状态:\nsudo vgscan\nsudo lvscan\nsudo pvscan\n确保所有的卷组和逻辑卷都处于“active”状态。\n\n\n激活逻辑卷如果某个逻辑卷未激活可以手动激活它\nsudo vgchange -ay\n\n\n修复损坏的 LVM使用 lvrepair 和 vgrepair 修复损坏的逻辑卷或卷组。如果 LVM 元数据损坏,可以尝试恢复备份:\nsudo vgcfgrestore -f /etc/lvm/archive/your_volume_group_name\n\n\n4.5 RAID 阵列问题\n4.5.1 问题描述\n如果系统使用软件 RAID 阵列(如 mdadm在启动时某个 RAID 阵列无法正确加载或同步,可能导致系统启动失败或数据不可访问。\n4.5.2 解决方案\n\n\n检查 RAID 阵列状态:使用 cat /proc/mdstat 查看 RAID 阵列状态,确认所有阵列都在运行。使用 mdadm 命令详细检查 RAID 阵列:\nsudo mdadm --detail /dev/md0\n\n\n修复 RAID 阵列:如果 RAID 阵列出现降级degraded或设备丢失可以尝试重新添加丢失的设备\nsudo mdadm --manage /dev/md0 --add /dev/sdX\n如果 RAID 阵列同步失败,可能需要重新同步:\nsudo mdadm --grow /dev/md0 --raid-devices=2\n\n\n重建 RAID 阵列:如果 RAID 阵列损坏严重,需要重新构建。备份数据后,可以重新创建 RAID 阵列并恢复数据:\nsudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1\n\n\n4.6 其他文件系统工具\n4.6.1 问题描述\n不同的文件系统类型有各自专用的检查和修复工具。未使用正确的工具可能导致检查或修复失败。\n4.6.2 解决方案\n\n\n使用文件系统专用工具对于 xfs 文件系统,使用 xfs_repair 而不是 fsck\nsudo xfs_repair /dev/sda1\n对于 btrfs 文件系统,使用 btrfs check 或 btrfs scrub\nsudo btrfs check /dev/sda1\nsudo btrfs scrub start /mnt\n对于 reiserfs 文件系统,使用 reiserfsck\nsudo reiserfsck --check /dev/sda1\n\n\n检查文件系统空间使用情况如果文件系统使用率达到 100%,可能导致系统异常。使用 df -h 检查各分区的使用情况,并清理不必要的文件。\n\n\n5. 启动服务的排查与修复\n5.1 Systemd 服务故障\n5.1.1 问题描述\nsystemd 是现代 Linux 系统的初始化系统,负责管理系统启动时的服务。如果某些关键服务启动失败,可能导致系统卡住或无法正常启动。\n5.1.2 解决方案\n\n\n进入恢复模式\n\n在 GRUB 菜单中选择恢复模式,进入单用户模式或维护模式。\n\n\n\n检查失败的服务使用 systemctl 查看启动失败的服务:\nsystemctl list-units --failed\n对于识别的失败服务可以尝试禁用或重新启动\nsudo systemctl disable 服务名\nsudo systemctl restart 服务名\n检查相关日志文件 /var/log/syslog 或 journalctl进一步分析失败原因。\n\n\n5.2 非 Systemd 系统中的服务管理问题\n5.2.1 问题描述\n并非所有的 Linux 发行版都使用 systemd 作为其初始化系统。一些较旧或轻量级的发行版可能仍然使用 SysVinit、Upstart 或 OpenRC 等初始化系统。如果这些初始化系统配置错误或服务脚本损坏,可能导致系统启动服务失败。\n5.2.2 解决方案\n\n\nSysVinit 系统:使用 service 命令查看和管理服务的状态:\n sudo service 服务名 status\n sudo service 服务名 start\n sudo service 服务名 stop\n如果某个服务无法启动检查对应的 /etc/init.d/ 脚本是否正确,以及相关配置文件是否存在问题。\n\n\nUpstart 系统:使用 initctl 命令管理 Upstart 服务:\nsudo initctl list\nsudo initctl status 服务名\nsudo initctl start 服务名\nsudo initctl stop 服务名\n检查 /etc/init/ 中的服务配置文件,确保格式和内容正确。\n\n\nOpenRC 系统:使用 rc-service 命令管理 OpenRC 服务:\nsudo rc-service 服务名 start\nsudo rc-service 服务名 stop\nsudo rc-service 服务名 restart\n确保 /etc/conf.d/ 中的配置文件正确配置,并检查 /etc/init.d/ 中的服务脚本是否损坏。\n\n\n5.3 服务依赖问题\n5.3.1 问题描述\n服务之间的依赖关系是系统启动顺序中的一个重要部分。如果某些关键服务未按顺序启动或启动失败可能会导致其他服务无法正常工作。\n5.3.2 解决方案\n\n\n检查服务依赖关系在 systemd 系统中,可以使用以下命令查看服务的依赖关系:\nsystemctl list-dependencies 服务名\n确保所有依赖服务都已正确启动且未报告错误。\n\n\n调整服务启动顺序\n如果发现某些服务启动顺序不正确可以通过修改其配置文件或 systemd 的 After 和 Requires 选项来调整服务的启动顺序。例如,在 /etc/systemd/system/服务名.service 中添加:\n\n\n[Unit]\nAfter=network.target\nRequires=network.target\n\n在非 systemd 系统中管理依赖:对于使用 SysVinit 的系统,可以编辑 /etc/init.d/ 中的服务脚本,确保所需的依赖服务已在脚本中指定(通常通过 Required-Start 和 Required-Stop 标注)。\n\n5.4 服务配置文件损坏或缺失\n5.4.1 问题描述\n服务的配置文件可能会因为错误修改、升级不兼容或其他原因而损坏或丢失。这会导致服务无法正确启动或工作。\n5.4.2 解决方案\n\n\n检查并恢复配置文件使用 systemctl status 服务名 检查服务状态,查看是否有配置文件错误提示。\n通过包管理器重新安装相关服务以恢复默认配置文件。例如\nsudo apt-get install --reinstall 服务包名\n如果系统支持也可以从 /etc/ 的备份中恢复配置文件。\n\n\n手动修复配置文件根据服务文档或在线资源手动检查并修复配置文件。确保语法正确并符合服务所需的配置要求。\n\n\n验证配置文件对于一些服务可以使用自带的验证工具来检查配置文件的正确性。例如Nginx 提供以下命令来验证配置:\nsudo nginx -t\n\n\n5.5 日志分析与错误排查\n5.5.1 问题描述\n启动服务失败时日志文件是排查问题的重要资源。通过分析系统日志和服务专用日志可以获取服务失败的详细原因。\n5.5.2 解决方案\n\n\n使用 journalctl 查看日志:对于 systemd 系统,使用 journalctl 查看系统和服务日志:\nsudo journalctl -u 服务名\nsudo journalctl -xe # 查看最近的错误日志\n分析日志信息查找具体错误原因。\n\n\n检查 /var/log/ 目录中的日志文件:某些服务会记录日志到 /var/log/ 目录下的专用日志文件中,如 /var/log/nginx/error.log 或 /var/log/mysql/error.log。检查这些日志文件以获取详细错误信息。\n\n\n启用详细日志记录对于复杂的问题可以通过修改服务配置文件启用详细日志记录。例如在 Nginx 中设置更高的日志记录级别:\n\n\nerror_log /var/log/nginx/error.log info;\n重新启动服务后检查日志以获取更多调试信息。\n5.6 服务权限与用户问题\n5.6.1 问题描述\n服务通常以特定用户身份运行。如果服务没有足够的权限访问所需的资源或配置文件可能导致启动失败或功能异常。\n5.6.2 解决方案\n\n\n检查服务的运行用户在 systemd 系统中,可以检查服务文件中的 User 和 Group 设置,确认服务以正确的用户身份运行:\n[Service]\nUser=服务用户\nGroup=服务组\n如果运行用户不正确可以通过修改服务文件或重新分配文件和目录的权限来解决问题。\n\n\n修复权限问题使用 chown 和 chmod 命令修复文件和目录的权限。例如:\nsudo chown -R 服务用户:服务组 /var/lib/服务名\nsudo chmod 755 /etc/服务名\n\n\n检查 SELinux 或 AppArmor 配置:如果系统启用了 SELinux 或 AppArmor需要确认这些安全模块没有阻止服务的运行。使用以下命令检查 SELinux 日志:\n\n\nsudo ausearch -m avc -ts recent\n根据提示调整 SELinux 或 AppArmor 配置,或者暂时将服务设置为 permissive 模式进行排查。\n6. 用户环境的排查与修复\n6.1 登录问题\n6.1.1 问题描述\n如果系统进入多用户模式后无法登录可能是由于用户权限问题、认证模块如 PAM配置错误、用户配置文件损坏或其他与登录管理器、Shell 环境配置相关的问题。\n6.1.2 解决方案\n\n\n进入恢复模式使用恢复模式或 Live CD/USB 进入系统,修改 /etc/passwd、/etc/shadow 或 /etc/sudoers 文件,确保用户具有正确的权限。\n检查用户是否被锁定或密码是否过期可以使用以下命令解锁用户并重置密码\nsudo passwd 用户名 # 重置密码\nsudo usermod -U 用户名 # 解锁用户\n\n\n修复认证模块PAM\n\n检查 PAM 配置文件 /etc/pam.d/,确保没有错误配置导致认证失败。可以将配置文件恢复为默认状态,或参考其他工作系统的配置文件进行修复。\n如果是 SSH 登录问题,检查 /etc/ssh/sshd_config 配置文件,确保未禁用合法用户的登录权限。\n\n\n\n修复登录管理器如果问题与登录管理器如 GDM, LightDM, SDDM有关尝试重启登录管理器服务\nsudo systemctl restart gdm # 以 GDM 为例\n检查登录管理器的配置文件确保没有错误配置影响用户登录。如果登录管理器无法启动可以尝试切换到另一个管理器确认问题是否与特定软件相关\nsudo apt-get install lightdm\nsudo dpkg-reconfigure lightdm\n\n\n重置用户配置文件如果是特定用户的配置文件损坏可以重命名用户的主目录下的配置文件夹如 .config然后重新登录系统\n\n\nmv /home/username/.config /home/username/.config.bak\n检查 .bashrc、.profile 等 Shell 配置文件,确保没有错误配置导致 Shell 环境无法正常加载。\n\n检查 Shell 环境配置:确保用户的默认 Shell 正常工作,检查 /etc/passwd 中的 Shell 设置。如果 Shell 程序损坏或配置错误,可以将用户的 Shell 设置为 /bin/bash\n\nsudo usermod -s /bin/bash 用户名\n6.2 图形界面问题\n6.2.1 问题描述\n如果 Linux 系统进入图形界面时出现问题(如黑屏、闪屏或 Xorg 崩溃通常与显示管理器、图形驱动、桌面环境配置、Xorg 或 Wayland 配置相关。\n6.2.2 解决方案\n\n\n检查 Xorg 日志:使用恢复模式或 TTY 终端Ctrl + Alt + F1-F6查看 /var/log/Xorg.0.log查找与显示器或图形驱动相关的错误信息。检查 Xorg 配置文件 /etc/X11/xorg.conf确保配置正确。如果配置文件丢失或损坏可以尝试自动生成新的配置文件\nsudo X -configure\nsudo mv xorg.conf.new /etc/X11/xorg.conf\n\n\n重置图形驱动尝试重新安装或更新图形驱动程序。例如使用 apt 重新安装 NVIDIA 驱动:\nsudo apt-get install --reinstall nvidia-driver\n对于 AMD 或 Intel 显卡,可以安装适当的开源驱动程序(如 xserver-xorg-video-amdgpu 或 xserver-xorg-video-intel。\n\n\n切换图形服务器Xorg/Wayland如果系统默认使用 Wayland但存在兼容性问题可以切换到 Xorg 进行测试。在 GDM 登录屏幕上选择齿轮图标,切换到 “Xorg” 会话。\n\n\n恢复默认桌面环境配置如果问题与特定桌面环境配置有关可以恢复默认配置或删除用户配置文件\nrm -rf ~/.config/xfce4 # 以 XFCE 为例\n如果桌面环境崩溃尝试使用一个不同的桌面环境如从 GNOME 切换到 KDE确认问题是否与特定桌面环境有关。\n\n\n修复 Display Manager显示管理器重启显示管理器服务或者切换到一个不同的显示管理器以排除问题\nsudo systemctl restart gdm # 以 GDM 为例\nsudo dpkg-reconfigure lightdm # 切换到 LightDM\n\n\n6.3 用户数据与配置恢复\n6.3.1 问题描述\n用户配置文件或数据丢失、损坏可能导致应用程序无法启动或工作不正常甚至影响用户登录和桌面环境的加载。\n6.3.2 解决方案\n\n\n备份与恢复用户数据使用 rsync 或 cp 命令备份用户主目录中的重要数据:\nrsync -av /home/username /backup/location/\n如果用户配置文件损坏可以从备份中恢复相关文件或目录。\n\n\n修复用户权限\n确保用户主目录及其下文件的权限正确使用 chown 和 chmod 修复权限问题:\nsudo chown -R username:username /home/username\nsudo chmod -R 755 /home/username\n\n\n清理缓存与临时文件删除用户目录下的缓存和临时文件防止损坏的缓存影响系统启动\nrm -rf ~/.cache/*\nrm -rf /tmp/*\n\n\n检查并修复应用程序配置如果某个应用程序无法启动检查其配置文件是否损坏或丢失。可以删除相关配置文件夹让应用程序重新生成默认配置\nrm -rf ~/.config/应用程序名\n\n\n7. 硬件兼容性检查\n7.1 硬件驱动问题\n7.1.1 问题描述\n虽然假设硬件没有问题但某些硬件可能与当前的 Linux 内核或驱动版本不完全兼容,导致系统无法正常启动。\n7.1.2 解决方案\n\n\n检查硬件驱动兼容性在恢复模式或 Live CD/USB 中,使用 lspci、lsusb 等工具查看硬件信息,并检查与硬件相关的内核模块是否加载正常。\n\n\n更新内核或驱动程序如果发现某个硬件不兼容当前内核尝试更新内核或特定驱动程序\nsudo apt-get update && sudo apt-get upgrade\nsudo apt-get install linux-generic\n\n\n7.2 新硬件与旧内核的兼容性问题\n7.2.1 问题描述\n当在较老的 Linux 内核版本上使用新硬件时,可能会出现兼容性问题,因为较老的内核可能未包含新硬件的驱动程序或支持。这种情况通常会导致系统无法识别或初始化新硬件,从而引发启动失败或系统不稳定的问题。\n7.2.2 解决方案\n\n\n检查内核版本与硬件支持使用 uname -r 查看当前内核版本,确认是否支持新硬件。如果发现内核版本较旧,可以考虑升级内核。查阅硬件制造商的文档或社区支持页面,确认推荐使用的内核版本。\n\n\n升级到最新内核版本使用以下命令安装最新稳定版内核\nsudo apt-get install linux-generic-hwe-$(lsb_release -rs)\n或者直接从源代码编译最新的主线内核适用于高级用户\nwget cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.x.tar.xz\ntar -xvf linux-6.x.tar.xz\ncd linux-6.x\nmake menuconfig # 配置内核\nmake -j$(nproc) && sudo make modules_install && sudo make install\nsudo update-grub\n\n\n使用 Linux 发行版的硬件支持扩展包:某些 Linux 发行版提供硬件支持扩展包这些包通常包含额外的驱动和内核模块以支持新硬件。例如Ubuntu 提供硬件启用堆栈HWE可通过以下命令安装\nsudo apt-get install --install-recommends linux-generic-hwe-$(lsb_release -rs)\n\n\n7.3 外部设备兼容性问题\n7.3.1 问题描述\n外部设备如 USB 驱动器、打印机、蓝牙设备等)有时可能无法在 Linux 系统上正常工作,尤其是在未正确加载相应驱动或固件的情况下。这会导致设备无法被识别或无法正常使用。\n7.3.2 解决方案\n\n\n检查设备连接与识别使用 dmesg 命令检查系统日志,确认外部设备是否被正确识别和连接。例如,插入 USB 设备后,查看 dmesg 输出:\ndmesg | grep usb\n使用 lsusb 或 lspci 查看设备列表,确认系统是否识别了外部设备。\n\n\n安装或更新设备驱动对于常见设备使用包管理器安装相应的驱动程序或固件。例如\nsudo apt-get install printer-driver-gutenprint # 打印机驱动\nsudo apt-get install bluez # 蓝牙驱动\n对于特殊设备如某些厂商特定的硬件可能需要从厂商网站下载驱动并手动安装。\n\n\n检查并加载固件某些外部设备需要特定的固件才能正常工作。使用 dmesg 检查是否有固件加载失败的错误信息,并根据提示安装缺少的固件包。例如:\nsudo apt-get install firmware-linux-nonfree\n\n\n调整设备的电源管理设置外部设备可能由于电源管理设置而无法正常工作尤其是在便携式计算机上。禁用自动挂起或调整电源管理策略\nsudo powertop --auto-tune\n\n\n7.4 BIOS/UEFI 固件相关问题\n7.4.1 问题描述\nBIOS/UEFI 固件版本过旧或配置不当可能导致硬件兼容性问题,特别是在处理器、内存、存储设备和显卡等关键硬件的初始化过程中。\n7.4.2 解决方案\n\n\n更新 BIOS/UEFI 固件:\n\n访问硬件制造商的网站检查是否有更新的 BIOS/UEFI 固件版本可用。下载并按照制造商的指示进行升级。\n注意更新 BIOS/UEFI 固件存在风险,可能会导致系统无法启动,因此务必备份重要数据并严格按照指导操作。\n\n\n\n调整 BIOS/UEFI 设置:进入 BIOS/UEFI 设置界面(通常通过按 Del、F2、Esc 或 F10 键),确认以下设置:\n\nSecure Boot对于一些 Linux 发行版,建议禁用 Secure Boot 以避免驱动签名问题。\nLegacy/UEFI Boot Mode确保启动模式与操作系统安装时的配置一致。\nSATA 模式:对于硬盘控制器,尝试切换 SATA 模式AHCI/IDE确保与系统兼容。\n内存设置检查内存频率和时序确认是否与硬件配置匹配。\n\n\n\n7.5 硬件故障排查\n7.5.1 问题描述\n虽然假设硬件没有问题但在某些情况下硬件故障仍然可能导致启动失败或系统不稳定。内存错误、硬盘损坏或过热问题都可能在启动过程中表现为系统问题。\n7.5.2 解决方案\n\n\n内存检测使用 memtest86+ 工具检查内存模块是否存在错误。大多数 Linux 发行版的启动菜单中包含此工具,可以选择运行以检测内存问题。如果检测到内存错误,考虑更换内存模块。\n\n\n硬盘健康检查使用 smartctl 工具检查硬盘的 S.M.A.R.T 状态,以评估硬盘的健康状况:\nsudo smartctl -a /dev/sda\n如果发现硬盘存在错误或即将故障备份数据并考虑更换硬盘。\n\n\n系统温度与散热检查使用 sensors 工具检查 CPU 和 GPU 温度,确保系统在正常温度范围内工作:\nsudo apt-get install lm-sensors\nsensors\n如果温度过高检查散热器和风扇是否正常工作并清理机箱内部的灰尘。\n\n\n其他硬件检测对于怀疑可能出现问题的其他硬件如显卡、主板可以尝试使用替代硬件进行测试\n\n\n8. 恢复与重装系统\n8.1 数据备份\n在执行任何可能导致数据丢失或系统变更的操作之前备份数据是确保系统恢复能力的关键步骤。通过系统备份可以防止在系统修复或重装过程中丢失重要数据。\n8.1.1 备份策略\n\n\n选择适当的备份方案\n\n根据数据的重要性和系统环境选择全备份、增量备份或差异备份方案。\n对于关键数据如用户的家庭目录、数据库文件等建议采用全备份的方式而对于不经常变化的大量数据可以采用增量备份以节省空间。\n\n\n\n确定备份存储位置\n\n使用外部存储设备如 USB 硬盘、NAS、云存储等作为备份目标以确保备份数据在原始系统故障时的安全性。\n使用 RAID 阵列或磁盘镜像技术提高本地存储的可靠性。\n\n\n\n使用适当的工具进行备份使用 rsync\n工具进行增量备份确保仅复制变更的数据节省时间和空间\nrsync -av --delete /home/username /mnt/backup/\n使用 tar 工具创建完整的归档备份,便于之后的恢复:\ntar -cvpzf /mnt/backup/username-backup.tar.gz /home/username\n对于企业级备份可以使用 Bacula、Amanda 或 Duplicity 等备份软件,以实现自动化和远程备份。\n\n\n验证备份有效性定期测试备份文件的完整性和可恢复性确保备份在需要时能够成功恢复\ntar -tvf /mnt/backup/username-backup.tar.gz\n\n\n8.2 重装系统\n当系统无法修复或需要重新部署时重装操作系统是一种有效的解决方案。重装过程需要谨慎进行以避免不必要的数据丢失和系统配置的复杂性。\n8.2.1 重装准备\n\n\n准备安装介质\n\n下载并创建最新版本的 Linux 发行版的启动介质(如 USB 启动盘或 DVD。\n确保安装介质与目标系统的硬件和架构如 x86_64兼容。\n\n\n\n检查硬件兼容性\n\n在安装之前确保系统的硬件已获得新的操作系统版本的支持。检查硬件制造商的文档或社区支持论坛。\n如果使用 UEFI 引导,确保 BIOS/UEFI 设置正确,并禁用或配置 Secure Boot。\n\n\n\n备份当前系统配置使用 dpkg --get-selections 或 rpm -qa 命令导出当前系统已安装的软件包列表,以便在重装后快速恢复环境:\ndpkg --get-selections > package-list.txt\n导出重要配置文件如 /etc/fstab、网络配置、GRUB 配置等),以便重装后参考和恢复。\n\n\n8.2.2 重装过程\n\n启动安装介质\n\n插入安装介质并启动系统通常通过按下 F12、Esc 或 Del 键进入启动菜单,从安装介质启动系统。\n\n\n选择安装类型\n\n在安装向导中选择安装类型全新安装、替换现有系统或手动分区。\n对于保留数据的重装可以选择不格式化数据分区但建议全新安装以确保系统的稳定性。\n\n\n配置系统分区\n\n根据需要手动分区或使用自动分区选项。确保根分区 /、交换分区 swap、以及 /home 分区配置合理。\n如果使用 LVM 或 RAID确保在安装过程中正确配置这些选项。\n\n\n完成安装并初步配置\n\n按照安装向导完成系统安装设置主机名、用户账号和密码等基本信息。\n安装完成后重启系统并移除安装介质。\n\n\n\n8.2.3 恢复备份和环境\n\n\n恢复数据备份在新系统中挂载外部存储设备并使用 rsync 或 tar 恢复用户数据:\nrsync -av /mnt/backup/username /home/username/\n确保恢复的数据权限正确使用 chown 和 chmod 命令调整权限。\n\n\n恢复软件和配置使用导出的包列表重新安装软件\nsudo dpkg --set-selections < package-list.txt\nsudo apt-get dselect-upgrade\n手动恢复配置文件或参考备份的配置文件确保系统服务和网络配置等恢复到之前的状态。\n\n\n更新和优化系统完成安装和恢复后运行系统更新以确保所有软件包处于最新状态\nsudo apt-get update && sudo apt-get upgrade\n根据需要安装额外的驱动程序和工具优化系统性能。\n\n\n测试系统功能\n测试所有关键功能包括网络连接、外部设备、图形界面和应用程序以确保系统恢复正常运行。\n\n"},"Technology/OperatingSystem/Linux/3.基础操作/Linux-包管理器":{"title":"Linux 包管理器","links":[],"tags":["Linux/基础","技术/操作系统"],"content":"包管理器\nLinux 系统的强大功能之一在于其庞大、多样化的软件生态。不同于 Windows 或 macOSLinux 使用包管理器来自动化软件的安装、更新、配置和删除,极大简化了软件管理的复杂性。包管理器不仅确保软件和其依赖关系正确安装,还能保持系统的整洁和更新。\n定义和作用\n包管理器是 Linux 和 Unix-like 系统中用于自动化处理软件包任务的工具。它允许用户搜索、安装、更新、配置和删除软件包,而无需手动下载和解压缩。更重要的是,包管理器处理软件包之间的依赖关系,确保系统稳定运行,避免 ” 依赖地狱 “。\n软件包格式\nLinux 软件包有多种格式,最常见的是 Debian 系的 .deb 和 Red Hat 系的 .rpm。\n\n.debDebian、Ubuntu 及其衍生版使用的软件包格式,通过 dpkg 和 APT 等工具进行管理。\n.rpmRed Hat、Fedora、CentOS 等发行版采用的格式,由 RPM 包管理器以及 YUM 或 DNF 等高级工具处理。\n\n这些格式基本上定义了如何打包软件、元数据如版本、依赖关系以及安装后如何布局文件。\n软件仓库和软件源\n软件仓库是托管软件包及其元数据的服务器。每个 Linux 发行版通常都会有一个或多个官方软件仓库同时也支持添加第三方仓库。软件源Repository Sources是软件仓库的地址用户可以在包管理器中配置这些地址以便下载和安装软件包。\n\n官方仓库提供由发行版维护团队精选和测试的软件包确保软件的稳定性和安全性。\n第三方仓库提供额外的软件包可能包括最新的软件版本或官方仓库中未包含的软件。\n\n用户可以根据需要添加、删除或更改软件源以优化软件安装和更新过程。\n常用包管理器\nLinux 的包管理器是系统管理的核心组件,它简化了软件的安装、更新、配置和移除过程。下面是针对主流 Linux 发行版包管理器的详细介绍。\nDebian/Ubuntu 系\nDpkg\ndpkg 是 APT 底层的工具,负责处理 .deb 文件Debian 软件包格式。dpkg 直接与软件包交互,执行如安装、移除和提供软件包信息等任务。虽然 dpkg 可以独立使用,但通常与 APT 一起使用以自动处理软件依赖。\ndpkg 最早于 1993 年由 Debian 项目的创始人 Ian Murdock 开发。自此dpkg 成为了 Debian 项目的核心组件之一,逐步发展壮大。后来,随着 Ubuntu 等基于 Debian 的发行版的出现dpkg 的使用范围进一步扩大。\ndpkg 的主要设计理念是简单、稳定、可扩展。它旨在为 Debian 及衍生系统提供一个可靠、易于使用的软件包管理基础设施。此外dpkg 还遵循 Unix 哲学,即“做好一件事”,专注于软件包的底层管理,而将依赖关系处理等高级功能交给上层工具。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令安装软件包dpkg -i <package_file.deb>删除软件包dpkg -r <package_name>显示已安装软件包信息dpkg -s <package_name>列出所有已安装软件包dpkg -l查询文件所属的软件包dpkg -S <file_name>\nAPT\nAPT (Advanced Package Tool) 是 Debian 及其衍生版(如 Ubuntu最常用的包管理工具。APT 是一个高级接口它能够自动下载、配置、安装和删除软件包。APT 的主要特点包括对依赖关系的自动处理、易于使用的命令行界面、软件包的稳定升级以及对多种下载协议的支持。\nAPT 最早在 1998 年由 Debian 开发者 Ian Murdock 和其他开发者创建。当时Debian 社区意识到需要一个更高级的软件包管理工具来简化系统维护,因此 APT 应运而生。随着时间的推移APT 得到了持续的改进和扩展,逐渐成为 Debian 及其衍生系统的重要组成部分。\nAPT 的实现主要基于 C++ 编程语言,后端库则依赖于 dpkg。APT 与 dpkg 紧密协作dpkg 负责底层的软件包安装、卸载和管理,而 APT 则负责处理软件仓库、依赖关系和软件包更新。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令更新软件包列表apt update安装软件包apt install <package_name>升级软件包apt upgrade升级所有软件包apt full-upgrade搜索软件包apt search <package_name>显示软件包信息apt show <package_name>删除软件包apt remove <package_name>删除软件包及配置apt purge <package_name>清理未使用的软件包apt autoremove清理下载的软件包文件apt clean\nRed Hat/CentOS 系\nRPM\nRPM (RPM Package Manager) 是一个包管理系统,用于安装、升级、查询、验证、卸载 RPM 软件包。RPM 是 Fedora、RHEL 及其衍生版的底层包管理工具YUM 和 DNF 都是在 RPM 之上构建的高级工具,提供了更完整的软件包管理功能。\nRPM 的发展始于 1997 年,当时由 Red Hat 的开发人员创建,用于替代当时较为简单的 Linux 软件包管理工具。随着 Linux 的发展RPM 得到了广泛的应用,成为了许多基于 Red Hat 的发行版的标准软件包管理工具。现在RPM 在 Fedora、RHEL、CentOS 等发行版中仍被广泛使用。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令安装 RPM 软件包rpm -ivh <package_name.rpm>升级 RPM 软件包rpm -Uvh <package_name.rpm>移除卸载软件包rpm -e <package_name>查询所有已安装的软件包rpm -qa查询特定软件包是否已安装rpm -q <package_name>查询已安装软件包的信息rpm -qi <package_name>列出软件包中的文件rpm -ql <package_name>查询某个文件属于哪个软件包rpm -qf <file_name>显示软件包的依赖关系rpm -qR <package_name>验证软件包rpm -V <package_name>查询软件包信息未安装的rpm -qpi <package_name.rpm>查询未安装软件包中的文件rpm -qpl <package_name.rpm>查询未安装软件包的依赖关系rpm -qpR <package_name.rpm>导入 RPM GPG keyrpm --import /path/to/key检查软件包签名rpm -K <package_name.rpm>\nYUM\nYUM (Yellowdog Updater, Modified) 是基于 RPM 包管理的命令行工具,主要用于 Fedora、RHEL 及其衍生系统(如 CentOS。YUM 使得管理 RPM 软件包变得更简单,自动处理依赖关系,提供易于使用的接口来管理软件仓库。\nYum 最初由 Seth Vidal 编写2003 年首次在 Fedora Core 1 中引入。Yum 的设计理念是为了改进 Red Hat Linux 中的软件包管理器使其更快、更易用和更灵活。目前Yum 已成为 Red Hat Enterprise LinuxRHEL和 CentOS 等 Linux 发行版中的标准软件包管理器。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令更新软件包列表yum makecache安装软件包yum install <package_name>更新软件包yum update <package_name>更新所有软件包yum update删除软件包yum remove <package_name>搜索软件包yum search <package_name>列出所有可用软件包yum list available\nDNF\nDNF (Dandified YUM) 是 YUM 的下一代版本旨在提供更好的性能和改进的依赖关系解决算法。DNF 采用了新的解决方案架构,改进了用户界面,并支持模块化和容器化应用。\nDNF 最初是由 Fedora 项目推出的 YUM 的替代品目的是提供更好的性能、更好的内存管理和更好的依赖关系解决方案。随着时间的推移DNF 在 Red Hat 及其衍生产品中逐渐取代了 YUM。\nDNF 的实现基于 Python使用 RPM 库进行底层软件包管理。DNF 的核心设计思想是提供更好的性能、内存管理和依赖关系解决方案,同时支持多个软件包仓库、插件和模块化架构。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令更新软件包列表dnf makecache安装软件包dnf install <package_name>更新软件包dnf upgrade <package_name>更新所有软件包dnf upgrade删除软件包dnf remove <package_name>搜索软件包dnf search <package_name>清理缓存dnf clean all\nArch Linux\nPacman 是 Arch Linux 的官方包管理工具它结合了一个简单的二进制包格式和一个易于使用的构建系统。Pacman 的特点包括易于理解的命令语法、对依赖关系的自动处理以及对滚动更新的原生支持。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令更新软件包数据库pacman -Sy安装软件包pacman -S <package_name>更新所有软件包pacman -Syu删除软件包pacman -R <package_name>搜索软件包pacman -Ss <search_term>列出已安装软件包pacman -Q清理未使用的包pacman -Rns $(pacman -Qdtq)\nSUSE/openSUSE 系\nZypper 是 SUSE Linux 发行版的命令行包管理工具。它提供了对 RPM 软件包的全面管理包括安装、更新、搜索和卸载软件包。Zypper 的特点是对软件仓库的高级管理能力和对依赖关系处理的强大支持。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令更新软件包列表zypper refresh安装软件包zypper install <package_name>更新软件包zypper update <package_name>更新所有软件包zypper update删除软件包zypper remove <package_name>搜索软件包zypper search <package_name>列出所有软件仓库zypper repos\nGentoo\nPortage 是 Gentoo Linux 的包管理系统它是基于源代码的包管理系统的一个例子。Portage 包括一个命令行界面工具emerge用户可以通过它安装、搜索、查询和维护软件包。Portage 的特点是高度可配置性,允许用户以最适合其需求的方式编译软件。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令操作emerge --sync同步软件包数据库emerge <package_name>安装软件包emerge —update —deep —newuse @world更新系统emerge —deselect <package_name>删除软件包emerge —search <package_name>搜索软件包qlist -I列出所有安装的软件包emerge —update <package_name>更新软件包emerge —depclean检查依赖性并重新构建equery list <package_name>查看软件包信息\n实践操作\n更新和升级\ngraph LR\n A[开始] --> B{检查更新}\n B -->|有更新| C[下载更新]\n B -->|无更新| F[结束,系统已是最新]\n C --> D[安装更新]\n D --> E{需要清理旧软件包吗?}\n E -->|是| G[清理旧版本软件包]\n E -->|否| F\n G --> F\n\n\n\n更新软件包列表\n在安装新软件或升级现有软件之前应该更新本地软件包列表以确保获取到最新版本的软件包信息。可以通过以下命令来更新软件包列表\nsudo apt update\n\n\n升级所有可升级的软件包\n更新了软件包列表后可以通过以下命令来升级所有已安装的软件包至最新版本\nsudo apt upgrade\n此命令会根据依赖关系自动升级软件包但它不会升级那些会引起依赖问题的软件包。\n\n\n全面升级系统\n要执行一个更彻底的系统升级可能包括删除一些旧软件包可以使用以下命令\nsudo apt full-upgrade\n这个命令会更积极地处理依赖关系可能会安装新软件包或删除无法升级的软件包以满足其他软件包的依赖需求。\n\n\n清理不再需要的软件包\n在软件升级过程中一些旧版本的软件包或不再需要的依赖可能会保留在系统上。可以通过以下命令清理这些不再需要的软件包\nsudo apt autoremove\n\n\n管理仓库源\n仓库源是指软件包管理器所用的软件仓库用于提供软件包的下载和更新。常见的 Linux 发行版都有官方仓库源,也有一些社区提供的非官方仓库源,以及一些专门为国内用户提供的镜像源。\n官方仓库源是由 Linux 发行版官方维护的软件仓库,提供的软件包通常经过严格的测试和验证,保证了软件的稳定性和安全性。用户可以通过软件包管理器直接访问官方仓库源,以获取最新的软件包和更新。\n\n\nDebian 官方源deb.debian.org/\n\n\nDebian 安全源security.debian.org/\n\n\nUbuntu 官方源archive.ubuntu.com\n\n\nCentOS 官方源mirror.centos.org/\n\n\n由于国内网络环境的特殊性使用国外官方仓库源可能会遇到较慢的下载速度或无法连接的问题。因此一些开源社区提供了针对国内用户的镜像仓库源用于加速软件包下载和更新。\n\n阿里云开源镜像站mirrors.aliyun.com/\n中科大开源软件镜像站mirrors.ustc.edu.cn/\n教育网联合镜像站help.mirrors.cernet.edu.cn/\n\n一键脚本\nLinuxMirrors 是一个由 SuperManito 维护的 Linux 镜像站点列表。该项目旨在为 Linux 用户提供可靠、高速的镜像站点列表,用户可以通过该列表轻松找到离自己最近的镜像站点,以加速软件包的下载和更新。\nLinuxMirrors github.com/SuperManito/LinuxMirrors\nbash <(curl -sSL linuxmirrors.cn/main.sh)\n问题解决\n在 Linux 系统的维护过程中,备份、安全性验证以及故障排除是保障系统稳定运行的重要措施。以下是这些方面的详细介绍和指导。\n备份和恢复\n备份软件包列表可以帮助你在系统重装或迁移时快速恢复之前的软件环境。\n1. 备份软件包列表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n发行版备份命令Debian/Ubuntudpkg --get-selections > packages_list.txtFedora/CentOS (DNF)dnf list installed > packages_list.txtArch Linuxpacman -Qqe > packages_list.txt\n2. 恢复软件包\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n发行版恢复命令Debian/Ubuntu1. dpkg --set-selections < packages_list.txt2. apt-get dselect-upgradeFedora/CentOS (DNF)dnf install $(cat packages_list.txt)Arch Linuxpacman -S --needed $(< packages_list.txt)\n安全性和验证\n确保软件包的完整性和安全性对于维护 Linux 系统的安全至关重要。下面详细介绍如何操作 GPG 签名验证和校验和检查:\nGPG 签名验证\nGPGGNU Privacy Guard签名验证是一种确认软件包未被篡改并且确实来自发布者的方法。\nDebian/Ubuntu使用 APT\n\n导入 GPG 密钥:如果你尝试安装一个第三方软件包,首先需要导入其 GPG 密钥,使用命令 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys <KEY_ID>。\n验证软件包APT 在下载和安装软件包时自动验证 GPG 签名。如果验证失败APT 将停止安装过程并显示错误。\n\nFedora/CentOS使用 RPM\n\n导入 GPG 密钥:首先,导入软件包签名用的 GPG 密钥,使用命令 sudo rpm --import /path/to/key。\n检查软件包签名在安装 RPM 包之前,可以使用 rpm --checksig -v <package.rpm> 命令检查软件包的签名。\n\n校验和检查\n校验和是文件的小型数字摘要用于检测文件是否在传输过程中被篡改。使用校验和进行文件完整性检查是一个好习惯。\n使用 sha256sum 检查:\n\n首先你需要获取软件包的 SHA256 校验和,通常在软件下载页面或通过安全信道由软件发布者提供。\n下载完软件包后在终端中使用命令 sha256sum <downloaded_file> 生成文件的 SHA256 校验和。\n比较计算出的校验和与发布者提供的校验和。如果两者相同说明文件未被篡改可以安全安装。\n\n常见问题和故障排除\n在软件包的安装和更新过程中可能会遇到各种问题如依赖关系错误、软件源不可达、包损坏等。\n解决依赖问题\n软件包依赖问题通常发生在软件包需要但未安装的其他包或者是需要特定版本的包而系统上安装的是不兼容版本。大多数现代的包管理器都能自动处理依赖问题但有时候可能需要手动干预。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作Debian/UbuntuFedora/CentOS (DNF)自动修复依赖sudo apt-get -f installsudo dnf check搜索软件包apt search <package_name>dnf search <package_name>\n更新软件源\n软件源或仓库是网络上或本地的软件包集合。系统通过软件源获取和安装软件包。如果软件源列表过时或软件源服务器不可达可能会导致无法安装或更新软件包。更新软件源列表或更换到更快的镜像服务器可以解决这个问题。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作Debian/UbuntuFedora/CentOS (DNF)编辑软件源列表编辑 /etc/apt/sources.list 文件编辑 /etc/yum.repos.d/ 目录下的文件清理缓存sudo apt cleansudo dnf clean all\n修复损坏的包\n损坏的软件包可能会阻止软件正常安装或运行。这可能是由于下载过程中的错误、磁盘错误或其他问题导致的文件损坏。重新安装软件包通常可以解决这个问题。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作Debian/UbuntuFedora/CentOS (DNF)重新安装软件包sudo apt-get install --reinstall <package_name>sudo dnf reinstall <package_name>清理缓存sudo apt cleansudo dnf clean all\n通用包管理器\n在 Linux 生态系统中,通用包管理器如 Flatpak 和 AppImage 提供了跨发行版的软件分发方案,使得应用程序的安装和运行变得更加容易和安全。这些工具各有特点,适用于不同的场景和需求。\nFlatpak\n基础知识 Flatpak 通过提供一个沙盒环境,允许应用程序在其自己的隔离空间中运行,与系统的其他部分相互独立。这种方法不仅提高了系统的安全性,还解决了传统的依赖问题,因为每个 Flatpak 应用都包含了其运行所需的所有依赖。\n首先确保你的系统已安装 Flatpak。在大多数发行版中可以通过包管理器来安装 Flatpak\n# Debian/Ubuntu\nsudo apt install flatpak\n \n# Fedora\nsudo dnf install flatpak\n \n# Arch Linux\nsudo pacman -S flatpak\n\n添加 Flathub 仓库: Flathub 是最流行的 Flatpak 应用仓库之一。通过以下命令添加 Flathub 仓库:\n\nflatpak remote-add --if-not-exists flathub flathub.org/repo/flathub.flatpakrepo\n\n安装 Flatpak 应用: 安装应用非常简单,只需知道应用的 ID。例如安装 Spotify\n\nflatpak install flathub com.spotify.Client\n\n运行 Flatpak 应用: 安装后,可以通过以下命令运行应用:\n\nflatpak run com.spotify.Client\nAppImage\nAppImage 提供了一种便携式软件分发方法,应用程序及其依赖被打包在单一的 AppImage 文件中。用户只需下载这个文件,无需安装,就可以运行应用程序。\n使用 AppImage 使用 AppImage 极其简单,只需几个步骤:\n\n\n下载 AppImage 文件:首先,从应用程序的官方网站或 GitHub 发布页面下载 AppImage 文件。\n\n\n赋予执行权限下载后需要为 AppImage 文件赋予执行权限。在文件所在的目录中打开终端,执行以下命令:\nchmod +x <AppImage_File>\n替换 <AppImage_File> 为你的 AppImage 文件名。\n\n\n运行 AppImage赋予执行权限后直接点击文件或在终端中执行文件即可启动应用程序\n./<AppImage_File>\n\n"},"Technology/OperatingSystem/Linux/3.基础操作/Linux-文件管理":{"title":"Linux 文件管理","links":[],"tags":["Linux/基础","技术/操作系统"],"content":"概述\nLinux 文件系统是指在 Linux 操作系统上对磁盘空间进行组织、管理和访问的一种机制。Linux 文件系统使用了树形结构的文件目录结构,每个文件都被组织在文件夹中,并按照一定的权限进行管理。\n常见的 Linux 文件系统包括 ext2、ext3、ext4、XFS、Btrfs 等。其中ext 系列是最常用的 Linux 文件系统它使用索引节点inode来管理文件支持文件系统日志journal能够更好地防止数据丢失和损坏。\n在 Linux 中,文件和目录被组织在一个单一的目录树中,以根目录“/”为起点。用户可以通过终端命令或者图形化界面访问和管理文件和目录。Linux 文件系统支持权限和访问控制,可以对文件和目录设置用户和组的权限,以控制对文件的访问和操作。\nLinux 文件系统还支持链接,包括硬链接和符号链接。硬链接是指将一个文件名指向另一个文件的实际内容,从而实现文件名的共享和链接;符号链接则是指将一个文件名指向另一个文件名,从而实现文件名的共享和链接。\nLinux 文件系统还支持磁盘配额可以对用户或者组的磁盘空间使用量进行限制。此外Linux 文件系统还支持快照和备份等高级特性,以便在文件丢失或损坏时进行数据恢复。\nLinux 文件系统是 Linux 操作系统中重要的组成部分,它提供了一种方便、安全和高效的数据存储和管理机制。\n管理维护\n目录操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令描述示例查看ls列出目录内容ls -l /homepwd显示当前工作目录pwdtree以树形结构显示目录和文件tree /home/user创建mkdir创建新目录mkdir /home/new_directory复制cp复制目录或文件cp -R /source /destination移动cd更改当前工作目录cd /home/userpushd将当前目录压入栈并切换到新目录pushd /home/new_directorypopd从栈中弹出目录并切换回去popd删除rmdir删除空目录rmdir /home/empty_directory\n文件操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令描述示例查看file确定文件类型file file.txtcat显示文件内容cat file.txtmore分页显示文件内容more file.txtless可以向前和向后翻页显示文件内容less file.txthead显示文件的开头部分head -n 5 file.txttail显示文件的末尾部分tail -n 5 file.txt查找whereis查找可执行文件、源码和手册页whereis python3which显示可执行文件的位置which python3find搜索文件和目录find /home -name "file.txt"创建touch创建空文件或更新文件时间戳touch new_file.txtln创建硬链接和符号链接ln -s source_file.txt link.txt复制cp复制文件cp source_file.txt destination.txt移动mv移动文件或目录mv source_file.txt destination.txt删除rm删除文件或目录rm file.txt\n文件处理\n基础\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例grep在文件中搜索字符串或正则表达式grep "pattern" file.txtsed流编辑器用于对文本文件进行基于行的编辑sed 's/foo/bar/g' input.txt > output.txtdiff比较文件差异diff file1.txt file2.txtdiff3比较三个文件差异diff3 file1.txt file2.txt file3.txtmd5sum计算文件的 MD5 校验和md5sum file.txtawk文本处理工具用于对文本进行模式扫描和处理awk '{ print $1 }' file.txtsort对文件中的行进行排序sort file.txtuniq去除文件中的重复行uniq file.txttr翻译或删除字符tr 'a-z' 'A-Z' < input.txt > output.txtwc计算字节数、字符数、行数wc file.txtcut从文件中移除一部分cut -f 1,3 -d ',' file.txtpaste横向连接文件paste file1.txt file2.txt\nNano\nNano 是一款基于命令行的文本编辑器,它是 Linux 中最常用的编辑器之一。以下是 Nano 的常用命令:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能Ctrl + G显示帮助文档Ctrl + O保存文件Ctrl + X退出 NanoCtrl + K剪切当前行Ctrl + U粘贴剪切的行Ctrl + W查找文本Ctrl + \\替换文本Ctrl + ↑移动到文本的上一屏Ctrl + ↓移动到文本的下一屏Ctrl + →移动到文本的下一单词Ctrl + ←移动到文本的上一单词\n下面是一些 Nano 编辑器的使用示例:\n\n\n打开文件\nCopy code\nnano filename.txt\n这将打开一个名为 “filename.txt” 的文件,并将其用 Nano 编辑器打开。\n\n\n查找文本\n您可以使用 Ctrl + W 来查找文本。输入您想要查找的文本,然后按 Enter 键。Nano 将跳转到文本中找到的第一个匹配项。\n\n\n替换文本\n您可以使用 Ctrl + \\ 来替换文本。输入您想要替换的文本和替换文本,然后按 Enter 键。Nano 将替换文本中找到的第一个匹配项。\n\n\n剪切和粘贴行\n使用 Ctrl + K 剪切当前行,使用 Ctrl + U 粘贴剪切的行。\n\n\n移动光标\n使用 Ctrl + ↑ 和 Ctrl + ↓ 移动到文本的上一屏或下一屏;使用 Ctrl + → 和 Ctrl + ← 移动到文本的下一单词或上一单词。\n\n\n保存和退出\n使用 Ctrl + O 保存文件,使用 Ctrl + X 退出 Nano 编辑器。\n\n\nVim\nVim 是一款文本编辑器,也是 Linux 中最常用的编辑器之一。Vim 支持多种编辑模式,包括命令模式、插入模式和可视模式。以下是 Vim 的常用命令:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能:w保存文件:q退出 Vim:wq保存文件并退出 Vimi进入插入模式Esc退出插入模式并返回命令模式v进入可视模式V进入行选择模式y复制选中文本p粘贴文本/查找文本:进入命令模式\n下面是一些 Vim 编辑器的使用示例:\n\n\n打开文件\nCopy code\nvim filename.txt\n这将打开一个名为 “filename.txt” 的文件,并将其用 Vim 编辑器打开。\n\n\n保存文件\n在命令模式下输入 :w然后按 Enter 键即可保存文件。\n\n\n退出 Vim\n在命令模式下输入 :q然后按 Enter 键即可退出 Vim。\n\n\n保存文件并退出 Vim\n在命令模式下输入 :wq然后按 Enter 键即可保存文件并退出 Vim。\n\n\n插入文本\n在命令模式下按下 i 进入插入模式,然后开始编辑文本。\n\n\n复制和粘贴文本\n进入可视模式按下 v选择要复制的文本然后按下 y 复制选中文本。返回命令模式后,将光标移动到要粘贴文本的位置,按下 p 粘贴文本。\n\n\n查找文本\n在命令模式下输入 /,然后输入要查找的文本并按下 Enter 键。Vim 将跳转到文本中找到的第一个匹配项。\n\n\n文件解压缩\nTar\nTar磁带归档器Tape Archive是一种用于文件打包归档的 UNIX 和 Linux 系统上的实用程序。它能将多个文件和目录合并成一个单独的归档文件便于文件的传输、备份和存储。需要注意的是Tar 本身并不具备压缩功能,但它可以与其他压缩工具(如 Gzip、Bzip2 等)结合使用,以实现文件归档与压缩的需求。\n优点\n\n跨平台兼容性Tar 是 UNIX 和 Linux 系统的标准工具,但在其他操作系统(如 Windows、macOS 等)上也有实现,因此具有较强的跨平台兼容性。\n保留文件属性Tar 可以在归档过程中保留文件和目录的原始属性(如权限、时间戳等),便于在解包时恢复文件的状态。\n可与压缩工具结合尽管 Tar 本身不具备压缩功能,但可以与 Gzip、Bzip2 等压缩工具结合使用,提供压缩功能。\n适用于大型文件集合Tar 能有效地处理大量文件和目录,将它们打包成一个单独的归档文件,便于管理和传输。\n\n缺点\n\n不具备原生压缩功能Tar 本身不具有压缩功能,需要与其他压缩工具结合使用。\n压缩效率较低与一体化的压缩工具相比使用 Tar 结合其他压缩工具的方式在压缩效率上可能略有不足。\n\n适用场景\n\n文件备份Tar 可以将多个文件和目录打包成一个归档文件,便于进行文件备份和存储。\n文件传输将多个文件和目录打包成一个归档文件可以方便地进行文件传输尤其是在网络传输中减少传输次数和网络开销。\n软件发布开发者经常使用 Tar 打包源代码或二进制文件,方便用户下载和安装。\n数据压缩与压缩工具如 Gzip、Bzip2 等)结合使用,可以实现文件的归档与压缩。\n\n总的来说**Tar 是一种非常灵活的文件打包和压缩工具,具有多种压缩格式支持、易于传输和备份、支持文件和目录和支持存档格式等优点。**但是,它的压缩比较低,不支持加密,因此在选择使用 Tar 时,需要根据具体的场景和需求来综合考虑其优缺点。\n常见命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述tar -cvf archive.tar file1 file2 directory1创建归档文件tar -xvf archive.tar解压缩归档文件tar -tvf archive.tar查看归档文件的内容tar -zcvf archive.tar.gz file1 file2 directory1压缩归档文件为.gz 格式tar -zxvf archive.tar.gz解压缩.gz 格式的归档文件tar -jcvf archive.tar.bz2 file1 file2 directory1压缩归档文件为.bz2 格式tar -jxvf archive.tar.bz2解压缩.bz2 格式的归档文件tar -P保留绝对路径tar --exclude='*.log' directory1排除指定文件或目录\n常见选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项全拼功能-c--create创建归档文件-x--extract解压归档文件-t--list查看归档文件中的文件列表-f--file指定归档文件的名称-z--gzip使用 gzip 压缩算法压缩归档文件-j--bzip2使用 bzip2 压缩算法压缩归档文件-v--verbose在执行操作时显示详细信息-P--absolute-names保留文件和目录的绝对路径--exclude--exclude=PATTERN排除匹配指定模式的文件或目录\nZip\nZIPZone Information Protocol是一种广泛使用的文件压缩和归档格式工具它可以将多个文件或目录打包成一个单独的文件以便于传输、备份和存档。这种格式最初是由 Phil Katz 在 1989 年开发的,现在已成为一种通用的归档和压缩标准。\n优点\n\n跨平台兼容性Zip 是一种通用的文件压缩和归档格式,几乎所有的操作系统(如 Windows、macOS、Linux 等)都支持 Zip 格式,具有很强的跨平台兼容性。\n集成压缩和归档功能Zip 同时具备文件压缩和归档功能,可以将多个文件和目录压缩成一个文件,便于传输和存储。\n压缩率适中Zip 格式的压缩率适中,能有效减少文件大小,从而节省存储空间和加快文件传输速度。\n随机访问Zip 支持随机访问,可以在不解压整个压缩包的情况下提取单个文件。\n密码保护Zip 格式支持为压缩文件设置密码,以提高文件的安全性。\n\n缺点\n\n压缩效率与一些专门的压缩算法如 7z、Bzip2 等相比Zip 的压缩效率较低,可能无法获得最佳的压缩效果。\n加密安全性Zip 的标准加密算法较弱,容易受到密码破解工具的攻击。虽然现代的 Zip 实现支持更强大的加密算法,但并非所有的压缩工具都支持这些算法。\n\n适用场景\n\n文件传输Zip 可以将多个文件和目录压缩成一个文件,减小文件大小,方便在不同设备和平台之间进行传输。\n文件存储将文件和目录压缩成 Zip 格式,可以节省存储空间,便于备份和管理。\n软件分发开发者经常使用 Zip 格式打包软件和资源,便于用户下载和安装。\n文档压缩将文档、图片等资料压缩成 Zip 格式,方便存储和分享。\n\n总的来说Zip 是一种广泛使用的文件压缩和归档格式具有很强的跨平台兼容性。它可以将多个文件和目录压缩成一个文件便于传输和存储。Zip 的压缩率适中,支持随机访问和密码保护。然而,与一些专门的压缩算法(如 7z、Bzip2 等相比Zip 的压缩效率较低,可能无法获得最佳的压缩效果。\n此外虽然 Zip64 扩展已经解决了传统 Zip 格式中的 4GB 文件大小限制,但并非所有的压缩解压缩工具都支持 Zip64因此在处理大文件时需要注意选择合适的工具。\n常见命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述zip archive.zip file1 file2 directory1创建 Zip 归档文件unzip archive.zip解压缩 Zip 归档文件zip -r archive.zip directory1压缩目录为 Zip 归档文件unzip -l archive.zip列出 Zip 归档文件中的文件列表zip -e archive.zip file1 file2使用加密算法压缩文件为 Zip 归档文件\n常见选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项全拼功能-r--recurse-paths递归压缩目录及其所有子目录-e--encrypt使用加密算法压缩文件-d--delete从 Zip 归档文件中删除文件-u--update更新 Zip 归档文件中的文件-l--list列出 Zip 归档文件中的文件列表-v--verbose在执行操作时显示详细信息-q--quiet在执行操作时禁止输出-f--file指定归档文件的名称-z--gzip使用 gzip 压缩算法压缩归档文件-j--bzip2使用 bzip2 压缩算法压缩归档文件\nGzip\nGzipGNU zip是一种广泛使用的文件压缩和解压缩工具。它基于 DEFLATE 算法,该算法结合了 LZ77Lempel-Ziv 77和 Huffman 编码技术能够有效地压缩文件。Gzip 主要用于压缩单个文件,而不是整个目录结构。在 Linux 和 Unix 系统中Gzip 常与 Tar磁带归档器结合使用以实现文件归档和压缩的双重功能。\n优点\n\n高压缩率Gzip 通常能提供较高的压缩率,从而降低文件大小,节省存储空间和带宽。\n快速压缩和解压缩速度Gzip 在保证较高压缩率的同时,压缩和解压缩速度相对较快。\n跨平台兼容性Gzip 在 Linux、Unix、macOS 和 Windows 等操作系统上都有实现,具有良好的跨平台兼容性。\n开源和免费Gzip 是 GNU 项目的一部分,遵循开源协议,免费提供给用户使用。\n\n缺点\n\n仅支持单文件压缩Gzip 本身只能压缩单个文件,无法直接压缩目录。通常需要与 Tar 等归档工具结合使用。\n压缩效率高虽然 Gzip 的压缩效率较高,但与一些专门的压缩算法(如 7z、Bzip2 等)相比,可能无法获得最佳的压缩效果。\n\n适用场景\n\n文件传输Gzip 可以将文件压缩成更小的体积,有助于减少传输时间和网络开销。\n网页优化服务器可以使用 Gzip 压缩网页内容,提高传输速度,降低带宽消耗,提高用户体验。\n数据存储Gzip 可以用于压缩文档、日志文件等,节省存储空间。\n软件分发开发者可以将源代码或二进制文件压缩为 Gzip 格式,便于用户下载和安装。\n\n总之Gzip 是一种广泛使用的文件压缩工具,基于 DEFLATE 算法,提供较高的压缩率和较快的压缩速度。尽管 Gzip 仅支持单文件压缩,但可以与 Tar 等归档工具结合使用,实现目录的压缩。具有良好的跨平台兼容性和开源性质,适用于文件传输、网页优化、数据存储和软件分发等场景。在压缩效率方面,虽然 Gzip 表现出色,但可能无法与一些专门的压缩算法(如 7z、Bzip2 等)相媲美。\n常见命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述gzip file.txt压缩文件“file.txt”gzip -r directory1递归压缩目录“directory1”及其所有子目录和文件gzip -d file.txt.gz解压缩 Gzip 压缩的文件“file.txt.gz”gzip -l file.txt.gz查看 Gzip 压缩文件“file.txt.gz”的详细信息gzip -v file.txt压缩文件“file.txt”并显示压缩进度\n常见选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全称功能-d--decompress解压缩文件-r--recursive递归压缩目录及其所有子目录-l--list列出 Gzip 压缩文件的详细信息-v--verbose显示操作的详细信息-q--quiet禁止输出操作信息-f--force强制执行操作即使会覆盖文件-t--test测试 Gzip 压缩文件的完整性-k--keep保留原始文件不删除压缩文件\nBzip2\nBzip2 是一款开源的文件压缩工具,使用 Burrows-Wheeler 算法BWT以及哈夫曼编码进行文件压缩。Bzip2 专注于提供高压缩率,通常能够比 Gzip 提供更高的压缩效果,但相应的压缩和解压缩速度较慢。与 Gzip 类似Bzip2 主要用于压缩单个文件,而不是整个目录结构。在 Linux 和 Unix 系统中Bzip2 也常与 Tar 归档工具结合使用。\n优点\n\n高压缩率Bzip2 通常能提供比 Gzip 更高的压缩率,从而进一步减小文件大小,节省存储空间和带宽。\n开源和免费Bzip2 是一个开源项目,可以免费使用。\n跨平台兼容性Bzip2 在 Linux、Unix、macOS 和 Windows 等操作系统上都有实现,具有良好的跨平台兼容性。\n\n缺点\n\n速度较慢由于 Bzip2 的高压缩率,压缩和解压缩速度相对较慢,特别是与 Gzip 相比。\n仅支持单文件压缩Bzip2 本身只能压缩单个文件,无法直接压缩目录。通常需要与 Tar 等归档工具结合使用。\n\n适用场景\n\n文件存储当存储空间有限且需要高压缩率时Bzip2 可用于压缩文档、日志文件等。\n文件传输Bzip2 可以将文件压缩成更小的体积,有助于减少传输时间和网络开销,尤其在对压缩率要求较高的场景中。\n软件分发开发者可以将源代码或二进制文件压缩为 Bzip2 格式,以获得更小的文件体积,便于用户下载和安装。\n\n简单总结Bzip2 是一款开源的文件压缩工具,使用 Burrows-Wheeler 算法和哈夫曼编码提供较高的压缩率但压缩和解压缩速度较慢。Bzip2 主要用于压缩单个文件,可以与 Tar 等归档工具结合使用,具有良好的跨平台兼容性。适用于文件存储、传输和软件分发等场景,特别是在对压缩率要求较高的情况下。\n常见命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述bzip2 file.txt压缩文件“file.txt”bzip2 -k file.txt压缩文件“file.txt”并保留原始文件bzip2 -d file.txt.bz2解压缩 Bzip2 压缩的文件“file.txt.bz2”bzip2 -l file.txt.bz2查看 Bzip2 压缩文件“file.txt.bz2”的详细信息bzip2 -v file.txt压缩文件“file.txt”并显示压缩进度\n常见选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全称功能-c—stdout将输出写入标准输出而不是写入压缩文件。-d—decompress解压缩 Bzip2 压缩文件,生成原始文件。-f—force强制覆盖现有的压缩文件而不提示。-k—keep保留原始文件不删除生成的压缩文件。-q—quiet不显示任何压缩和解压缩过程的信息。-t—test测试 Bzip2 压缩文件的完整性。-v—verbose显示详细的压缩和解压缩过程的信息。-z—compress使用 Bzip2 进行压缩,生成 Bzip2 压缩文件(默认选项)。-1—fast使用 1 级别的压缩,生成速度快,压缩比低的压缩文件。-2—best使用 2 级别的压缩,生成速度慢,压缩比高的压缩文件(默认级别)。-3—small使用 3 级别的压缩,生成速度较慢,压缩比更高的压缩文件。-4使用 4 级别的压缩,生成速度更慢,压缩比更高的压缩文件。-5使用 5 级别的压缩,生成速度更慢,压缩比更高的压缩文件。-6使用 6 级别的压缩,生成速度更慢,压缩比更高的压缩文件。-7使用 7 级别的压缩,生成速度更慢,压缩比更高的压缩文件。-8使用 8 级别的压缩,生成速度更慢,压缩比更高的压缩文件。-9—best-quality使用 9 级别的压缩,生成速度最慢,压缩比最高的压缩文件。\n7z\n7z7-Zip是一款开源的文件压缩和解压缩工具主要使用 LZMALempel-Ziv-Markov 链算法)和 LZMA2 算法进行压缩。7z 格式以高压缩率和高压缩速度而著称,通常能够提供比 Gzip 和 Bzip2 更高的压缩效果。除了 7z 格式7-Zip 还支持其他压缩格式,如 ZIP、Gzip、Bzip2、Tar 等。\n优点\n\n高压缩率7z 格式通常能提供非常高的压缩率,从而进一步减小文件大小,节省存储空间和带宽。\n压缩速度7z 在保证高压缩率的同时,压缩速度相对较快。\n多文件支持7z 支持压缩多个文件和目录结构,无需额外的归档工具。\n密码保护7z 支持使用 AES-256 加密算法对压缩文件进行密码保护。\n开源和免费7-Zip 是一个开源项目,可以免费使用。\n跨平台兼容性7-Zip 在 Windows、Linux 和 macOS 等操作系统上都有实现,具有良好的跨平台兼容性。\n\n缺点\n\n广泛支持度尽管 7z 格式具有许多优点,但与 ZIP 和 Gzip 相比,它的支持和普及程度相对较低。\n可能需要额外软件在某些操作系统如 macOS 和 Linux可能需要额外安装 7-Zip 或类似工具,以支持 7z 格式。\n\n适用场景\n\n文件存储当存储空间有限或需要高压缩率时7z 可用于压缩文档、日志文件等。\n文件传输7z 可以将文件压缩成更小的体积,有助于减少传输时间和网络开销。\n软件分发开发者可以将源代码或二进制文件压缩为 7z 格式,以获得更小的文件体积,便于用户下载和安装。\n数据备份7z 支持压缩大量文件和目录结构,适用于对数据进行备份和归档。\n\n简单总结7z 是一款开源的文件压缩工具,使用 LZMA 和 LZMA2 算法提供高压缩率和较快的压缩速度。7z 支持压缩多个文件和目录结构,支持密码保护,具有良好的跨平台\n常见命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述7z a archive.7z file1 file2将 file1 和 file2 添加到名为 archive.7z 的压缩文件中7z a -r archive.7z folder将 folder 目录及其子目录递归添加到名为 archive.7z 的压缩文件中7z e archive.7z从 archive.7z 提取文件不保留目录结构7z x archive.7z从 archive.7z 提取文件保留目录结构7z l archive.7z显示名为 archive.7z 的压缩文件中的文件列表7z t archive.7z测试名为 archive.7z 的压缩文件的完整性7z a -pPASSWORD archive.7z file将 file 添加到名为 archive.7z 的压缩文件中,并使用密码 PASSWORD 保护7z a -sfx archive.exe file创建名为 archive.exe 的自解压缩可执行文件,其中包含 file7z a -tzip archive.zip file将 file 添加到名为 archive.zip 的 ZIP 格式压缩文件中7z a archive.7z -v100m file将 file 添加到名为 archive.7z 的压缩文件中,并创建 100MB 的分卷文件\n常见选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项全拼功能aAdd添加文件到压缩文件eExtract提取压缩文件不保留目录结构lList显示压缩文件中的文件列表tTest测试压缩文件的完整性xeXtract with full paths提取压缩文件保留目录结构-pPassword设置压缩文件的密码-rRecurse递归处理子文件夹-sfxCreate SFX archive创建自解压缩可执行文件-tType指定压缩文件的类型如 7z、zip、gzip 等)-vCreate volumes创建多卷压缩文件"},"Technology/OperatingSystem/Linux/3.基础操作/Linux-环境变量":{"title":"Linux 环境变量","links":[],"tags":["技术/操作系统","Linux/基础"],"content":"基础概念\n环境变量\n环境变量Environment Variables是在操作系统层面为程序和用户提供的动态值。 这些变量可以影响程序的行为、系统的配置以及用户环境的设定。在 Linux 系统中,环境变量以键值对的形式存在,键是变量的名称,值则是变量的具体内容。这些变量在系统启动时由 shell如 Bash、Zsh 等)加载,贯穿整个用户会话的生命周期。\n环境变量在 Linux 系统中的作用举足轻重,它们不仅影响着系统的运行方式,还决定了程序的执行路径、用户的语言和区域设置、命令行工具的默认行为等。通过设置和管理环境变量,用户可以在不同的系统和应用程序间无缝切换,优化工作流程。\n环境变量的用途\n环境变量的用途广泛且多样主要体现在以下几个方面\n\n控制系统行为环境变量可以直接影响系统的某些行为。例如通过设置 PATH 变量,可以定义系统在运行命令时搜索可执行文件的目录顺序。\n传递配置信息程序在启动时可以读取环境变量中的信息以决定如何进行初始化和配置。例如Java 程序可以通过 JAVA_HOME 变量找到 JDK 的安装路径。\n个性化用户环境用户可以通过环境变量定制他们的工作环境。例如设置 EDITOR 变量可以指定默认的文本编辑器,设置 LANG 和 LC_* 变量可以确定语言和区域设置。\n跨程序的共享信息环境变量可以在不同的程序间传递信息尤其是在脚本编写和自动化任务中非常有用。脚本可以使用环境变量与其他脚本或进程进行通信。\n简化命令行操作通过设置环境变量用户可以减少命令行输入的长度和复杂度。例如定义 PAGER 变量可以设置默认的分页程序,使用更短的命令来查看长文件。\n\n系统环境变量 Vs 用户环境变量\n在 Linux 系统中,环境变量可以按照其作用范围和生效范围分为系统环境变量和用户环境变量:\n\n系统环境变量这些变量在整个系统范围内有效通常由系统管理员在系统启动时配置影响到所有用户的会话。系统环境变量的配置文件通常位于 /etc/ 目录下,包括 /etc/environment、/etc/profile 等文件。系统环境变量的设置影响所有用户,通常用于定义系统级别的配置,如全局的 PATH 变量。\n用户环境变量这些变量仅对特定用户的会话有效。用户可以在自己的 home 目录中通过编辑 ~/.bashrc、~/.bash_profile 或 ~/.profile 文件来配置和持久化这些变量。用户环境变量主要用于个性化用户的工作环境,不会影响到其他用户。\n\n系统环境变量通常在系统启动时由 /etc/profile 或其他系统脚本设置,而用户环境变量则是在用户登录时由 ~/.bash_profile、~/.bashrc 等用户级配置文件加载。在需要覆盖系统默认配置时,用户可以通过设置用户环境变量来实现。\n常见的环境变量\n环境变量的种类繁多但其中一些是最为常用的用户在日常使用和配置中会经常接触。以下是一些常见的环境变量及其作用\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量描述用途典型示例值PATH定义 shell 搜索可执行文件的路径列表当用户在命令行输入一个命令时,系统会根据 PATH 中定义的目录顺序逐一搜索可执行文件/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOME当前用户的主目录用于存放用户的个人文件和配置文件。在脚本中使用 HOME 变量,可以避免硬编码路径/home/usernameSHELL指定用户当前使用的 shell 程序影响用户的命令行环境和脚本的执行环境/bin/bash, /bin/zsh, /bin/fishUSER当前登录的用户名在脚本或程序中识别当前操作者通常用于权限检查或个性化设置usernameLOGNAME通常与 USER 一致用于登录和身份验证相关的操作usernameLANG系统默认的语言设置控制系统的语言和字符编码影响命令行工具和应用程序的显示语言en_US.UTF-8, zh_CN.UTF-8LC_ALL覆盖所有其他本地化设置强制设置系统的语言和区域优先级高于其他 LC_* 变量en_US.UTF-8EDITOR系统默认的文本编辑器在需要用户输入文本的程序中如 git commit调用此编辑器vim, nano, geditPAGER用于分页显示长文件内容的程序当输出内容较长时自动分页显示常用于 man 等命令less, moreTERM终端类型定义了终端的类型和功能如支持的颜色和格式。影响终端的显示效果xterm-256color, vt100PS1主提示符字符串定义 shell 提示符的外观,通常包含用户名、主机名和当前目录\\u@\\h:\\w\\$MAIL当前用户的邮件存储路径定义系统中邮件程序的默认邮件存储位置/var/spool/mail/usernamePWD当前工作目录记录当前 shell 会话中的工作目录,通常通过 cd 命令更新/home/username/projectsOLDPWD上一个工作目录保存上一次 cd 操作之前的工作目录,方便快速返回/home/usernameDISPLAYX11 显示服务器的位置用于图形界面程序,定义显示服务器的位置,通常用于远程显示:0, localhost:10.0HOSTNAME当前主机的名称标识系统的网络主机名通常用于个性化提示符或网络相关操作mycomputer.localSSH_CLIENTSSH 连接的客户端信息包含 SSH 客户端的 IP 地址、端口等信息通常用于记录和安全检查192.168.1.100 12345 22SSH_TTY当前 SSH 会话的终端设备指定当前 SSH 会话使用的伪终端设备/dev/pts/1HISTFILE保存 shell 历史记录的文件路径定义 shell 历史记录的保存位置,默认为 ~/.bash_history~/.bash_historyHISTSIZEshell 历史记录的最大条目数控制 shell 保存的历史记录条数1000HISTCONTROL控制历史记录的行为用于定义 shell 如何保存历史记录例如忽略重复命令ignoredups\n查看和操作环境变量\n了解如何查看和操作环境变量是掌握环境变量管理的基础技能。以下是一些常用的命令和方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述用法示例用途printenv显示当前环境变量的值。可以查看特定变量或所有环境变量。printenv PATH printenv用于快速检查环境变量的值特别是在调试配置或验证设置时。env类似于 printenv显示当前环境变量。还能在临时修改环境变量的情况下执行命令而不影响当前 shell 环境。env env PATH=/new/path command用于查看所有环境变量或在不改变当前环境的情况下临时设置变量并执行命令。set查看当前 shell 中的所有变量包括环境变量、局部变量、shell 函数和导出变量。set详细检查当前 shell 的变量状态适用于调试和故障排查。echo $VARIABLE_NAME输出特定环境变量的值。通过在变量名前加上 $ 符号来引用变量。echo $HOME echo $PATH用于快速查看单个变量的值尤其是在脚本或命令行中使用变量时。export将 shell 中的变量导出为环境变量,使其在当前 shell 及其子进程中可用。export VAR_NAME="value"用于设置新的环境变量或修改现有变量使其在子进程中生效。unset移除指定的环境变量或 shell 变量。unset VAR_NAME用于删除不再需要的环境变量或清理环境。declare -x显示当前 shell 中已导出的环境变量。declare -x类似于 export 的查看功能专门用于检查已导出的变量适合确认哪些变量被导出为环境变量。env -i启动一个不带任何环境变量的新 shell 环境用于排除现有环境变量对命令或程序的影响。env -i bash --noprofile --norc用于在不受当前环境变量影响的情况下测试命令或程序帮助识别环境变量引发的问题。source在当前 shell 会话中执行指定脚本文件并将其导出的环境变量加载到当前环境中。source ~/.bashrc用于重新加载环境配置文件如 .bashrc无需重启 shell。typeset查看或设置 shell 变量和函数的属性。可以与 -x 选项结合使用,类似 declare -x。typeset -x另一种检查和管理 shell 变量和环境变量的方法,适合在不同 shell 中使用(如 ksh。alias定义或显示别名别名本质上是命令的环境变量。alias ll='ls -la'用于为常用命令创建快捷方式提高工作效率。别名本质上也是环境变量的一部分。envsubst替换文本中的环境变量常用于处理模板文件。envsubst < template.txt > output.txt用于将包含环境变量的模板文件转换为实际值的文件适合自动化任务中的配置文件生成。printenv -0类似于 printenv但以 NUL 字符分隔输出适合处理包含特殊字符的变量值。printenv -0处理复杂环境变量值时使用确保输出不会被空格或换行符误解析。\n环境变量的配置与持久化\n临时设置环境变量\n使用 export VARIABLE_NAME=value 命令设置变量\n在 Linux 系统中export 命令用于设置和导出环境变量,使得这些变量在当前 shell 会话中可用,并能够被所有从该 shell 派生的子进程继承。export 命令的语法非常简单,通常以 export VARIABLE_NAME=value 的形式使用。以下是其基本用法的示例:\nexport MY_VAR="Hello, World!"\n在这个例子中我们定义了一个名为 MY_VAR 的环境变量,并将其值设置为 "Hello, World!"。此后MY_VAR 将在当前 shell 会话中有效,且在该会话中启动的任何程序都可以访问 MY_VAR。\n需要注意的是**通过 export 设置的环境变量仅在当前 shell 会话中有效。**如果关闭该 shell 或启动一个新的 shell 会话,之前设置的环境变量将失效。此特性使得 export 非常适合临时调整环境变量,而不对系统整体配置造成影响。\n在当前 Shell 会话中设置变量的作用范围\n**当你使用 export 设置一个环境变量时,它只在当前 shell 会话及其子进程中有效。**这意味着如果你打开了一个新的终端窗口,或者启动了一个新的 shell会话中的环境变量将不会自动继承到新的会话中。这种行为可以通过以下两个例子说明\n\n\n当前 shell 会话中有效:\nexport MY_VAR="Hello, World!"\necho $MY_VAR # 输出Hello, World!\n\n\n新 shell 会话中无效:\nbash # 启动一个新的 shell 会话\necho $MY_VAR # 输出为空,因为 MY_VAR 在新会话中不存在\n\n\n要让环境变量在所有会话中都有效必须将其持久化到用户或系统的配置文件中。\nexport 与 set 的区别\nexport 和 set 都可以用来定义 shell 中的变量,但有一些关键区别:\n\nset设置 shell 局部变量,变量只在当前 shell 环境中有效,不会自动传递给子进程。\nexport将变量导出使其在当前 shell 以及所有子进程中都有效。通过 export 设置的变量是环境变量,而通过 set 设置的只是普通的 shell 变量。\n\n持久化环境变量\n**持久化环境变量指的是将环境变量配置保存到特定的配置文件中,这样每次登录或启动 shell 时,这些环境变量都能自动加载。**根据环境变量的作用范围,持久化配置可以分为全局和用户两种。\ngraph TD;\n A[1. System Boot] --> B["2. /etc/environment"]\n A --> C["3. /etc/profile"]\n C --> D["4. /etc/profile.d/*"]\n A --> E["5. ~/.bash_profile or ~/.profile"]\n E --> F["6. ~/.bashrc"]\n F --> G["7. Manual Load (source ~/.bashrc)"]\n \n subgraph Global Settings\n B\n C\n D\n end\n \n subgraph User Settings\n E\n F\n end\n \n style A fill:#ffcccc,stroke:#333,stroke-width:2px\n style B fill:#ffcc99,stroke:#333,stroke-width:2px\n style C fill:#ffcc99,stroke:#333,stroke-width:2px\n style D fill:#ffcc99,stroke:#333,stroke-width:2px\n style E fill:#ccffcc,stroke:#333,stroke-width:2px\n style F fill:#ccffcc,stroke:#333,stroke-width:2px\n style G fill:#ccccff,stroke:#333,stroke-width:2px\n\n\n全局环境变量配置\n全局环境变量是对整个系统所有用户都有效的变量配置通常由系统管理员设置且保存在 /etc/ 目录下的全局配置文件中。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件作用格式特点适用范围/etc/environment定义全局环境变量适用于所有用户在系统启动时加载。KEY=value不支持 shell 语法(如变量引用或命令替换),只能用简单的键值对形式定义变量。适用于所有用户,自动在系统启动时加载。/etc/profile全局 shell 配置文件,适用于所有用户的登录 shell在用户登录时运行。支持 在 Docker 中使用环境变量 shell 脚本语法通常包含全局的环境变量设置、路径配置、别名等,支持 shell 脚本语法(如条件语句、循环等)。所有用户登录 shell 时自动执行。/etc/profile.d/*.sh扩展 /etc/profile 的功能,允许为特定应用或功能模块单独设置环境变量和配置。各 .sh 文件独立,支持 shell 脚本语法提供更细粒度的控制,允许系统管理员为不同的应用程序或模块编写特定的环境变量配置脚本。所有用户的登录 shell自动加载所有 .sh 文件。\n用户环境变量配置\n用户环境变量仅对特定用户的会话有效通常由用户自己配置并保存在用户 home 目录下的配置文件中。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件作用加载时机典型用法特点~/.bashrc用户级非登录 shell 的配置文件,定义环境变量、别名和 shell 功能。适用于每次打开新终端时加载。非登录 shell 启动时如打开新终端窗口export PATH="$HOME/bin:$PATH" alias ll='ls -la'用户个性化 shell 环境的主要工具,常用于设置别名、函数及环境变量。适用于所有非登录 shell 会话。~/.bash_profile用户级登录 shell 的配置文件,主要用于定义登录时的环境变量。通常调用 ~/.bashrc 来加载非登录 shell 配置。登录 shell 启动时if [ -f ~/.bashrc ]; then . ~/.bashrc; fi专用于登录 shell如通过 SSH 或控制台登录时加载。通常只加载一次,并可以调用 ~/.bashrc。~/.profile用户级通用 shell 配置文件,如果 ~/.bash_profile 不存在,则 Bash 会加载 ~/.profile。适用于其他 shell。登录 shell 启动时export JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64" export PATH="$JAVA_HOME/bin:$PATH"通用配置文件,适用于 Bash 和其他 shell。在 ~/.bash_profile 不存在时作为后备配置。~/.bash_logout用户退出登录 shell 时执行的脚本,用于清理环境或记录会话信息。退出登录 shell 时echo "Logout at $(date)" >> ~/.logout_log在用户退出登录 shell 时自动执行,用于清理任务或保存退出日志。适合用于清理会话的任务或执行退出时的命令。\n非 Bash Shell 的配置\n除了 Bash其他 shell如 Zsh 和 Fish也有各自的配置文件和方法用于设置和持久化环境变量。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件作用加载时机典型用法特点~/.zshrc非登录 shell 的配置文件,用于设置 Zsh 环境变量、别名和函数。类似于 Bash 的 ~/.bashrc。非登录 shell 启动时如打开新终端窗口export PATH="$HOME/bin:$PATH" alias ll='ls -la'用户自定义 Zsh 环境的主要文件,适用于非登录 shell会话中自动加载。~/.zprofile登录 shell 的配置文件,初始化环境,类似于 Bash 的 ~/.bash_profile。可调用 ~/.zshrc。登录 shell 启动时if [ -f ~/.zshrc ]; then source ~/.zshrc; fi专用于登录 shell 的配置文件,用于设置初始环境,并调用非登录 shell 的配置。~/.config/fish/config.fishFish shell 的用户配置文件,设置环境变量、别名等。使用 Fish 特有的语法,不支持 POSIX 语法。启动 Fish shell 时set -x PATH $HOME/bin $PATH alias ll="ls -la"Fish shell 的主要配置文件,语法不同于其他 shell使用简单、直观的命令语法。适用于所有 Fish 会话。\n环境变量的加载顺序和优先级\n了解不同环境变量配置文件的加载顺序和优先级对于正确配置系统至关重要。\ngraph TD;\n A[1. System Boot] --> B["2. /etc/environment"]\n B --> C["3. /etc/profile"]\n C --> D["4. /etc/profile.d/*.sh"]\n C --> E["5. ~/.bash_profile or ~/.profile"]\n E --> F["6. ~/.bashrc"]\n F --> G["7. Non-login Shell (Terminal Window)"]\n G --> H["8. Logout"]\n H --> I["9. ~/.bash_logout"]\n \n subgraph User Level\n E\n F\n I\n end\n\n\n subgraph System Level\n B\n C\n D\n end\n \n style B fill:#ffcccc,stroke:#333,stroke-width:2px\n style C fill:#ffcc99,stroke:#333,stroke-width:2px\n style D fill:#ffcc99,stroke:#333,stroke-width:2px\n style E fill:#ccffcc,stroke:#333,stroke-width:2px\n style F fill:#ccffcc,stroke:#333,stroke-width:2px\n style G fill:#ccccff,stroke:#333,stroke-width:2px\n style H fill:#ccccff,stroke:#333,stroke-width:2px\n style I fill:#ffccff,stroke:#333,stroke-width:2px\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n阶段加载文件描述加载时机同名变量优先级数值1. 系统启动/etc/environment定义系统范围的静态环境变量适用于所有用户。此文件不支持 shell 语法仅支持简单的键值对形式。系统启动时加载影响所有用户的全局环境。102. 用户登录 (Login Shell)/etc/profile全局的登录 shell 配置文件,适用于所有用户。通常用于设置全局路径、别名和系统范围的 shell 配置。用户通过登录 shell如 SSH、TTY 登录时加载。20/etc/profile.d/*.sh系统管理员可通过该目录中的脚本为特定应用程序或模块设置额外的环境变量。作为 /etc/profile 的扩展按顺序加载每个脚本。303. 用户登录 (Login Shell)~/.bash_profile 或 ~/.profile用户级的登录 shell 配置文件,通常包含用户特定的环境变量。~/.bash_profile 针对 Bash~/.profile 更通用。登录 shell 启动时加载(如 SSH 登录、控制台登录。40~/.bashrc通常由 ~/.bash_profile 调用,定义非登录 shell 的配置,如别名、函数和用户特定的变量。非登录 shell 启动时如打开终端窗口时加载。504. 非登录 Shell 启动~/.bashrc非登录 shell 的配置文件,通常由 ~/.bash_profile 调用,设置别名、环境变量、函数等。每次启动新的终端窗口(非登录 shell时加载。505. 用户退出 (Logout Shell)~/.bash_logout用户退出登录 shell 时执行的脚本。用于清理临时文件、保存退出日志等操作。用户退出登录 shell如退出 SSH、TTY时执行。不适用\n**在同一个会话中,如果同一个变量在多个文件中被定义,后加载的文件会覆盖之前的设置。**例如上表中优先级数值越高,覆盖优先级越高。即数值高的文件中的同名变量会覆盖数值低的文件中的同名变量。例如,~/.bashrc (优先级 50) 会覆盖 /etc/profile (优先级 20) 中定义的同名变量。\n根据终端类型不同环境变量的加载行为也不同\n\n登录 shell当用户首次登录系统如通过 SSH、TTY系统会加载 /etc/profile、~/.bash_profile 或 ~/.profile然后根据这些文件设置登录 shell 的环境。\n非登录 shell当用户打开一个新的终端窗口或执行一个 shell 脚本时,系统会加载 ~/.bashrc 或 ~/.zshrc设置非登录 shell 的环境。这些环境变量仅在当前非登录 shell 中有效。\n\n总结来说登录 shell 更适合进行用户登录时的全局环境配置,而非登录 shell 则适合用于更为频繁的日常任务和命令行操作。\n环境变量的高级使用\n环境变量的引用与扩展\n使用 $ 引用变量\n在 Linux 中,通过在变量名前加 $ 符号来引用环境变量。例如:\nexport MY_VAR="Hello, World!"\necho $MY_VAR \n# 输出: Hello, World!\n这是最常见的引用方式适合在命令行和脚本中使用能够动态传递和使用变量的值。\n使用 ${} 进行引用和扩展\n${} 是一种更灵活的引用方式,适合处理变量与其他字符紧密相连的情况,确保变量正确解析。例如:\nFILENAME="file"\necho "${FILENAME}_backup.txt" \n# 输出: file_backup.txt\n变量替换\nBash 提供了替换机制,当变量未定义或为空时,可以返回默认值:\n\n\n默认值替换${VARIABLE_NAME:-default_value} 当变量未设置时,返回 default_value但不修改变量本身\necho ${MY_VAR:-"Default Value"} # 输出: Default Value\n\n\n空值替换并赋值${VARIABLE_NAME:=default_value} 如果变量未设置,返回 default_value并同时将其赋值给变量\necho ${MY_VAR:="Default Value"} # 输出: Default Value\necho $MY_VAR # 输出: Default Value\n\n\n管理复杂的 PATH 变量\n添加路径到 PATH 的正确方式\nPATH 变量决定了 shell 在执行命令时查找可执行文件的目录列表。正确的做法是将新的路径追加到现有的 PATH 变量中,而不是覆盖它:\nexport PATH=$PATH:/new/path\n这行命令将 /new/path 添加到 PATH 的末尾。如果希望优先使用新路径,可以将它放在最前面:\nexport PATH=/new/path:$PATH\n路径顺序的重要性\nPATH 中的路径顺序决定了 shell 查找命令的优先级。当同一个命令在多个路径中存在时shell 会执行第一个找到的版本。因此,路径的安排很重要:\n\n\n系统路径优先确保 /usr/bin 和 /bin 等系统路径优先,避免误覆盖系统命令。\n\n\n用户路径优先在需要覆盖系统命令时可以将用户路径放在前面\nexport PATH=~/custom/bin:$PATH\n\n\n避免冗余和无效路径管理好路径避免路径重复或无效路径。\n\n\n临时修改 PATH 变量\n如果需要临时修改 PATH可以在执行命令时临时更改而不会影响全局环境\nPATH=/new/temp/path:$PATH command_to_run\n这种方法适合在特定环境下执行命令或测试不同的工具版本命令执行完毕后 PATH 会自动恢复。\n环境变量的调试\nenv -i 命令启动无环境变量的 Shell\n为了排除环境变量的影响你可以使用 env -i 启动一个不带任何环境变量的 shell\nenv -i bash --noprofile --norc\n这会启动一个全新的 shell不加载任何环境变量。此方法常用于调试环境问题确保命令不受现有环境变量的影响。\ndeclare -x 查看已导出的环境变量\ndeclare -x 命令仅显示当前 shell 中已导出的环境变量,不包含普通变量或函数:\ndeclare -x\n这是一个方便的命令用于检查当前 shell 中导出的环境变量状态。\n使用 strace 查看进程使用的环境变量\nstrace 是一个强大的工具,能够跟踪进程使用的系统调用和环境变量。以下命令可以帮助你查看某个进程读取了哪些环境变量:\nstrace -e trace=execve -s 1000 -o output.log env\nstrace 将跟踪 env 命令的执行,并将所有与环境变量相关的操作记录到 output.log 文件中,帮助分析复杂的环境问题。\n环境变量的安全性与优化\n环境变量的安全性\n环境变量有时会用于存储敏感信息如密码、API 密钥等。然而,这种做法存在一定的安全风险,因为环境变量在系统中相对容易被泄露或访问。\n风险分析\n\n进程环境可访问在某些情况下系统中的其他用户可能通过查看进程环境例如通过 /proc 文件系统)访问环境变量,从而获取敏感信息。\n日志记录风险如果环境变量值被意外写入日志文件如错误日志敏感信息可能会暴露给不相关的用户。\n环境传递风险当启动子进程时父进程的环境变量通常会传递给子进程这可能导致敏感信息被传播到不安全的环境中。\n\n使用 .env 文件和 dotenv 工具安全管理环境变量\n为了解决环境变量的安全性问题可以使用 .env 文件和相关的工具(如 dotenv来更安全地管理这些变量。.env 文件通常用于在开发或部署环境中存储配置,而不会将其公开到全局环境中。\n\n\n创建 .env 文件:在项目的根目录下创建 .env 文件,并将敏感信息存储在其中。例如:\nDB_PASSWORD=SuperSecretPassword\nAPI_KEY=YourApiKeyValue\n\n\n使用 dotenv 加载变量:在使用这些变量的脚本或应用中,可以通过 dotenv 库(适用于 Python、Node.js 等)加载 .env 文件中的变量,而不必将其暴露在全局环境中。\n\n\n保护 .env 文件:确保 .env 文件的权限设置正确,并在版本控制系统中将其排除(如使用 .gitignore以防止敏感信息泄露。\n\n\n避免环境变量泄露减少使用 export 公布敏感变量\n为了减少环境变量泄露的风险建议谨慎使用 export 命令来公开敏感信息。相反,可以考虑以下方法:\n\n\n使用局部变量在脚本或命令中尽可能使用局部变量而不是环境变量这样可以限制变量的作用范围。\n\n\n临时变量设置在需要时临时设置环境变量只在当前命令或脚本执行期间有效\nDB_PASSWORD=SuperSecretPassword command_to_run\n\n\n加密存储对于非常敏感的信息考虑使用加密工具或安全存储服务如 AWS Secrets Manager进行保护而不是简单地存储在环境变量中。\n\n\n环境变量配置的优化\n避免冗余的环境变量配置\n环境变量的冗余配置不仅会增加系统的复杂性还可能导致不必要的冲突和资源浪费。以下是一些优化策略\n\n定期清理环境变量定期检查和清理不再使用或重复的环境变量保持配置的简洁性。\n合并相似变量如果多个变量具有相似的功能或目的考虑将它们合并为一个更通用的变量。例如将多个路径变量合并为一个综合的 PATH 变量。\n文档化环境变量记录所有使用的环境变量及其用途以便日后维护和优化。\n\n使用 direnv 自动加载特定目录的环境变量\ndirenv 是一个有用的工具,可以根据用户当前所在的目录自动加载和卸载环境变量。它允许用户为不同的项目配置独立的环境,而不必手动切换。\n\n\n安装 direnv首先需要在系统中安装 direnv 工具,通常可以通过包管理器完成:\nsudo apt install direnv\n\n\n配置项目环境在项目目录下创建 .envrc 文件,并将所需的环境变量定义在其中:\nexport PATH=$HOME/project/bin:$PATH\nexport DB_PASSWORD=SuperSecretPassword\n\n\n自动加载环境每次进入该目录时direnv 会自动加载 .envrc 中的环境变量。当用户离开该目录时,这些变量将被卸载。\n\n\ndirenv 提供了一种优雅的方式来管理多个项目的环境配置,避免了环境变量的全局污染。\n基于场景的环境变量管理策略如开发环境 Vs 生产环境)\n在不同的环境如开发、测试、生产通常需要使用不同的环境变量配置。基于场景的环境变量管理策略可以帮助开发者和运维人员更好地控制和调试系统。\n\n分离配置文件为不同的环境如开发、测试、生产创建独立的环境变量配置文件如 .env.dev、.env.prod并根据需要进行加载。\n自动切换环境使用脚本或工具如 direnv 或 dotenv根据当前环境自动切换和加载相应的环境变量配置。\n敏感信息保护在生产环境中尤其要注意环境变量的安全性确保敏感信息不被暴露。可以使用加密存储或安全凭证管理服务来进一步保护这些信息。\n\n环境变量在脚本中的使用\n在 Bash 脚本中使用环境变量\n使用 $VARIABLE_NAME 传递参数\n在脚本中可以直接使用 $VARIABLE_NAME 来引用和使用环境变量。例如:\n#!/bin/bash\n \n# 定义一个环境变量\nGREETING="Hello"\n \n# 使用环境变量\necho "$GREETING, $USER!"\n在这个简单的脚本中GREETING 和 USER 是两个环境变量。USER 是系统提供的,表示当前用户,而 GREETING 是自定义的变量。脚本输出一个欢迎消息,包含用户的用户名。\n通过命令行传递环境变量\nBash 脚本可以接收从命令行传递的环境变量,这在自动化脚本中尤为有用。例如:\n#!/bin/bash\n \n# 使用传递进来的环境变量\necho "The project directory is: $PROJECT_DIR"\n你可以在运行脚本时传递 PROJECT_DIR 变量:\nPROJECT_DIR="/home/user/project" ./myscript.sh\n这种方法使得脚本的行为可以通过外部参数进行调整而不需要修改脚本本身。\n设置和导出环境变量\n在脚本中使用 export 命令可以将一个变量导出为环境变量,使其在脚本的所有子进程中都可见。例如:\n#!/bin/bash\n \n# 设置并导出一个环境变量\nexport DATABASE_URL="mysql://user:password@localhost/dbname"\n \n# 执行某个程序,该程序可以访问 DATABASE_URL\npython myapp.py\n在这个例子中DATABASE_URL 被导出myapp.py 可以访问到这个环境变量,用于数据库连接配置。\n修改现有环境变量\n脚本还可以修改现有的环境变量。例如扩展 PATH 变量以包括自定义的二进制路径:\n#!/bin/bash\n \n# 将自定义路径添加到 PATH 中\nexport PATH="/opt/myapp/bin:$PATH"\n \n# 验证新的 PATH\necho $PATH\n这样做确保了脚本执行时系统首先查找 /opt/myapp/bin 中的可执行文件,然后才查找其他路径。\n条件逻辑基于环境变量\n脚本可以根据环境变量的值执行不同的操作。例如\n#!/bin/bash\n \n# 基于 DEBUG 环境变量控制脚本行为\nif [ "$DEBUG" == "true" ]; then\n echo "Debug mode is ON"\n set -x # 开启命令回显\nelse\n echo "Debug mode is OFF"\n set +x # 关闭命令回显\nfi\n在这个例子中脚本通过检查 DEBUG 环境变量来决定是否开启调试模式。在调试模式下,脚本将回显每一条命令,这对于排查问题非常有帮助。\n环境变量在 CI/CD 中的应用\n在持续集成/持续部署CI/CD管道中环境变量用于传递配置信息和敏感数据如 API 密钥),以便在不同的构建和部署阶段使用。这种做法不仅提高了安全性,还简化了配置管理。\n在 CI/CD 系统中定义环境变量\n大多数 CI/CD 工具(如 Jenkins、GitLab CI、Travis CI都允许在项目设置或管道文件中定义环境变量。例如在 GitLab CI 中,可以在 .gitlab-ci.yml 文件中定义全局或作业级别的环境变量:\nvariables:\n DATABASE_URL: "mysql://user:password@localhost/dbname"\n \nbuild:\n script:\n - echo $DATABASE_URL\n这些变量在管道的所有步骤中都可用确保构建和部署过程的一致性。\n使用环境变量存储敏感信息\n在 CI/CD 中,敏感信息(如密钥和密码)不应硬编码在脚本或配置文件中。相反,应将它们存储为环境变量,并通过安全机制(如加密或隐藏变量)进行管理。例如,在 Jenkins 中,可以使用 Credentials Binding Plugin 来安全地注入敏感信息:\npipeline {\n environment {\n AWS_ACCESS_KEY_ID = credentials('aws-access-key-id')\n AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key')\n }\n stages {\n stage('Deploy') {\n steps {\n sh 'aws s3 sync . s3://mybucket'\n }\n }\n }\n}\n基于环境的动态配置\n可以根据环境变量的值动态选择配置。例如在 Node.js 应用中,可以使用 NODE_ENV 环境变量来选择不同的配置文件:\nconst config = require(`./config.${process.env.NODE_ENV}.json`);\n在 CI/CD 管道中,可以通过设置 NODE_ENV 来自动选择适当的配置:\ndeploy:\n stage: deploy\n script:\n - export NODE_ENV=production\n - npm run deploy\n这种方法确保了同一份代码能够灵活地部署到不同的环境中。\n在 Docker 中使用环境变量\nDocker 支持在容器启动时传递环境变量。这些变量可以通过 docker run 命令的 -e 选项或 --env-file 选项传递。例如:\ndocker run -e DATABASE_URL="mysql://user:password@localhost/dbname" myapp\n或者使用 .env 文件:\ndocker run --env-file .env myapp\n通过这种方式应用程序可以根据传入的环境变量配置其行为而无需在镜像中硬编码这些信息。\n在 Kubernetes 中管理环境变量\nKubernetes 提供了多种管理环境变量的方法,包括通过 ConfigMaps 和 Secrets 将配置信息和敏感数据传递给容器。\n\n\n通过 ConfigMap 设置环境变量:\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: app-config\ndata:\n DATABASE_URL: "mysql://user:password@localhost/dbname"\n在 Pod 配置中引用 ConfigMap\napiVersion: v1\nkind: Pod\nmetadata:\n name: myapp\nspec:\n containers:\n - name: myapp-container\n image: myapp:latest\n envFrom:\n - configMapRef:\n name: app-config\n\n\n通过 Secret 管理敏感环境变量:\nKubernetes 的 Secret 机制用于安全管理敏感数据,例如 API 密钥。与 ConfigMap 类似Secret 可以在 Pod 中引用,并以环境变量的形式提供给容器:\napiVersion: v1\nkind: Secret\nmetadata:\n name: db-secret\ntype: Opaque\ndata:\n DB_PASSWORD: c3VwZXJzZWNyZXRwYXNzd29yZA==\n在 Pod 中引用 Secret\napiVersion: v1\nkind: Pod\nmetadata:\n name: myapp\nspec:\n containers:\n - name: myapp-container\n image: myapp:latest\n env:\n - name: DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: db-secret\n key: DB_PASSWORD\n\n\n这种方法确保了容器中的环境变量安全且易于管理适用于大规模的集群环境。"},"Technology/OperatingSystem/Linux/3.基础操作/Linux-用户和权限":{"title":"Linux 用户和权限","links":[],"tags":["Linux/基础","技术/操作系统"],"content":"概述\nLinux 多用户系统的历史可以追溯到 1960 年代的 Unix 系统Unix 是一种多用户、多任务的操作系统,被广泛应用于大型计算机和服务器上。随着 Linux 的发展,它也成为了一种强大的多用户操作系统,并被广泛应用于服务器、个人电脑和移动设备等领域。\n设计原则\nLinux 多用户系统的设计基于以下原则:\n\n唯一用户标识符UID每个用户都有一个唯一的标识符用于标识其身份。\n用户组标识符GID每个用户可以分配到一个或多个用户组用户组也有一个唯一的标识符。\n所有者和用户组每个文件和目录都有一个所有者和一个所属用户组用于控制访问权限。\n主目录Home Directory每个用户都有一个主目录用于存储其个人文件和设置。\n系统管理员权限系统管理员可以创建、删除和管理用户和用户组以及控制用户的权限和访问权限。\n\n实现机制\nLinux 多用户系统的实现基于以下机制:\n\n配置文件用户和用户组的信息存储在特定的配置文件中如 /etc/passwd、/etc/shadow、/etc/group 和 /etc/gshadow。\n身份验证用户登录时需要进行身份验证通常使用用户名和密码进行认证。\n管理工具系统管理员可以使用命令行工具或图形界面来创建、删除和管理用户和用户组以及配置用户的权限和访问权限。\n安全机制Linux 系统提供了许多安全机制如访问控制列表ACL、文件系统权限和 SELinux用于保护系统和用户的数据安全。\n\n权限管理\n在 Linux 系统中文件和目录的权限由三个组件组成所有者权限、所属组权限和其他用户权限。每个组件可以设置为读取r、写入w和执行x权限这些权限可以用数字表示r=4, w=2, x=1。\n用户和权限的配置文件\n以下是存储用户和权限信息的主要配置文件\n\n/etc/passwd存储用户账户信息。\n/etc/shadow存储用户密码信息包含加密的密码和其他安全信息。\n/etc/group存储用户组信息。\n/etc/gshadow存储用户组密码信息。\n/etc/login.defs定义系统登录的默认配置。\n/etc/adduser.conf定义添加用户时的默认配置。\n\n安全性建议\n在使用 root 用户时,应注意系统的安全性,尽量使用 sudo 或 su 命令以普通用户身份执行命令,以减少误操作对系统的影响。\n用户\n创建\nUseradd\nuseradd 命令是 Linux 系统中的一个命令行工具,用于创建新用户帐户。通过 useradd 命令,可以指定新用户的用户名、用户 IDUID、主目录、默认 shell 和密码等信息。\n在大多数 Linux 系统中,只有管理员用户(如 root 用户)可以创建新用户。通常情况下,管理员用户需要使用 sudo 命令或以 root 用户身份登录系统,才能使用 useradd 命令创建新用户。\n# 创建一个新用户\nsudo useradd john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-c, --comment COMMENT指定用户的注释字段。sudo useradd -c "John Smith" john-d, --home-dir HOME_DIR指定用户的家目录。sudo useradd -d /home/john john-e, --expiredate EXPIRE_DATE指定用户的账户过期日期。sudo useradd -e 2023-06-30 john-f, --inactive INACTIVE设置密码过期后的不活动期限为 INACTIVE以禁用账户。sudo useradd -f 30 john-g, --gid GROUP指定用户的主用户组。sudo useradd -g staff john-G, --groups GROUPS指定用户所属的其他用户组。sudo useradd -G staff,developer john-m, --create-home创建用户的家目录。sudo useradd -m john-p, --password PASSWORD指定用户的加密密码。sudo useradd -p password_hash john-s, --shell SHELL指定用户的默认 shell。sudo useradd -s /bin/bash john-u, --uid UID指定用户的 UID。sudo useradd -u 1001 john\nAdduser\nadduser 命令是 Linux 系统中的一个高层次的用户添加工具,它提供了比 useradd 更加用户友好的界面和交互过程。adduser 通常作为一个 Perl 脚本,封装了 useradd 命令,并在用户创建过程中进行一些附加的配置工作,如创建主目录、复制模板文件、设置密码等。\n\n配置文件adduser 命令的默认配置文件为 /etc/adduser.conf可以在此文件中修改默认设置如主目录、用户组等。\n密码设置adduser 默认会在用户创建过程中提示输入密码。如果使用 --disabled-password 选项,则不会设置密码,需要在用户创建后使用 passwd 命令单独设置。\n与 useradd 的兼容性:虽然 adduser 提供了更友好的用户创建界面,但它并不是所有发行版都默认包含的命令。某些轻量级发行版可能只提供 useradd。\n\n# 创建一个新用户\nsudo adduser john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例--home HOME_DIR指定用户的家目录。sudo adduser --home /home/john john--shell SHELL指定用户的默认 shell。sudo adduser --shell /bin/bash john--uid UID指定用户的 UID。sudo adduser --uid 1001 john--gid GID指定用户的 GID。sudo adduser --gid 100 john--disabled-password创建用户但不设置密码。sudo adduser --disabled-password john--disabled-login创建用户但禁止登录。sudo adduser --disabled-login john--gecos GECOS提供用户的 GECOS 信息。sudo adduser --gecos "John Smith,,," john--no-create-home不创建用户的家目录。sudo adduser --no-create-home john--ingroup GROUP将用户添加到指定的主用户组。sudo adduser --ingroup staff john--extra-groups GROUPS将用户添加到附加用户组。sudo adduser --extra-groups staff,developer john\nadduser 与 useradd 的区别:\n\n交互式adduser 提供了交互式的用户创建过程向导会提示输入用户名、密码、GECOS 信息(如全名、电话等)。\n默认设置adduser 使用系统默认配置文件(如 /etc/adduser.conf来设定新用户的默认值例如主目录位置、用户组等。\n附加任务adduser 会自动完成一些附加任务,如创建用户主目录、复制 /etc/skel 目录中的模板文件到新用户主目录等。\n\n管理\nChfn\nchfn change finger information命令用于更改用户的 GECOS 信息。GECOS 字段包含用户的全名、办公地址、办公电话和家庭电话等信息。通常,这些信息存储在 /etc/passwd 文件中\n# 更改当前用户信息\ndebian@SevenWate-PC:$ chfn\nPassword:\nChanging the user information for debian\nEnter the new value, or press ENTER for the default\n Full Name:\n Room Number []:\n Work Phone []:\n Home Phone []:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-f, --full-name NAME更改用户的全名。chfn -f "John Smith"-r, --room ROOM更改用户的办公地址。chfn -r "Room 123"-w, --work-phone PHONE更改用户的办公电话。chfn -w "555-1234"-h, --home-phone PHONE更改用户的家庭电话。chfn -h "555-5678"-o, --other OTHER更改用户的其他信息。chfn -o "Other Info"-u, --username USER指定要更改 GECOS 信息的用户名(仅 root 用户可以使用该选项。sudo chfn -f "John Smith" john-q, --quiet安静模式不输出任何信息。chfn -q-v, --verbose显示详细信息。chfn -v\nChsh\nchsh change shell命令用于更改用户的默认登录 shell。通过 chsh 命令,用户可以选择不同的 shell 来作为他们的登录环境。在 Linux 系统中,常见的 shell 有 bash、zsh、ksh、csh 等。\n# 查看当前系统 shell\ncat /etc/shells\n \n# 更改当前用户的默认 shell\nchsh -s /bin/bash\n \n# 更改其他用户的默认 shell\nchsh -s /bin/bash john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-s, --shell SHELL指定新的登录 shell。chsh -s /bin/zsh-l, --list-shells列出系统中可用的 shell。chsh -l-u, --username USER指定要更改 shell 的用户。仅 root 用户可以使用该选项。sudo chsh -s /bin/zsh john-h, --help显示帮助信息。chsh -h\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nShell描述主要特性适用场景shBourne Shell最早的 UNIX Shell。基本命令解释器轻量标准 UNIX Shell传统 UNIX 系统基础脚本编写bashBourne Again Shell最常用的 Shell向后兼容 sh。强大的脚本功能命令行编辑历史记录命令补全日常使用脚本编写系统管理员使用cshC Shell语法类似 C 语言。C 语言风格语法,别名,历史记录喜欢 C 语言语法的用户脚本编写tcshcsh 的改进版本,增加了一些用户友好功能。增强的命令行编辑,命令补全,语法高亮改进的 C Shell 用户交互式使用kshKorn Shell结合了 sh 和 csh 的优点。丰富的编程特性数组处理命令行编辑高级脚本编写系统管理员使用zshZ Shell功能强大且灵活支持许多高级特性。强大的命令补全插件系统主题支持多行命令编辑高级用户脚本编写开发人员fishFriendly Interactive Shell用户友好的 Shell。人性化提示智能命令补全颜色高亮简易配置新手用户日常使用用户友好环境dashDebian Almquist Shell轻量级的 sh 实现。轻量快速标准兼容资源占用低系统启动脚本嵌入式系统资源受限环境ashAlmquist Shell另一个轻量级的 sh 实现。轻量快速标准兼容资源占用低嵌入式系统资源受限环境轻量级需求rbashRestricted Bash限制版的 bash。限制用户执行某些命令增强安全性受限用户环境安全要求高的场景scponly限制用户只能使用 scp 命令。限制用户只进行 SCP 操作增强安全性安全文件传输环境受限用户访问nologin禁止用户登录 Shell但允许 FTP 等非交互式服务。禁止交互登录显示消息安全性控制禁止交互登录的用户提供非交互服务git-shell专为 Git 用户设计的 Shell限制用户只能执行 Git 命令。限制用户只能使用 Git 命令增强代码管理安全性Git 服务器环境,限制用户操作,代码管理服务器\nChage\nchage change age命令用于更改用户密码的有效期和过期信息。系统管理员可以通过 chage 命令来设置用户密码的到期时间、警告时间和账户失效时间等,从而增强系统的安全性。\n# 查看用户密码信息\nsudo chage -l john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-d, --lastday LAST_DAY设置用户密码最后一次更改的日期。日期格式为 YYYY-MM-DD。sudo chage -d 2024-08-05 john-E, --expiredate EXPIRE_DATE设置账户过期日期。日期格式为 YYYY-MM-DD。sudo chage -E 2024-12-31 john-I, --inactive INACTIVE设置密码过期后多少天账户变为不活跃状态。sudo chage -I 30 john-m, --mindays MIN_DAYS设置密码的最短使用期限两次修改密码之间最少要间隔的天数。sudo chage -m 7 john-M, --maxdays MAX_DAYS设置密码的最长使用期限密码过期前的最大天数。sudo chage -M 90 john-W, --warndays WARN_DAYS设置密码过期前警告用户的天数。sudo chage -W 7 john-l, --list显示用户密码和账户的过期信息。sudo chage -l john-h, --help显示帮助信息。chage -h\n日期格式应为 YYYY-MM-DD如果不指定具体日期可以使用 -1 表示永不过期。\nPasswd\npasswd password命令是 Linux 系统中的一个命令行工具,用于更改用户的密码或口令。默认情况下,每个 Linux 用户都有一个口令或密码来保护其账户的安全性。passwd 命令可用于更改密码或口令。\n# 更改当前用户的\npasswd \n \n# 更改其他用户的密码\npasswd john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-d, --delete删除用户的密码使账户不需要密码即可登录。sudo passwd -d john-e, --expire使用户密码立即过期强制用户在下次登录时更改密码。sudo passwd -e john-i, --inactive INACTIVE设置密码过期后账户被禁用前的天数。sudo passwd -i 30 john-k, --keep-tokens仅更新有效期信息而不更改密码。sudo passwd -k john-l, --lock锁定用户密码禁用账户。sudo passwd -l john-S, --status显示账户的密码状态信息。sudo passwd -S john-u, --unlock解锁用户密码启用账户。sudo passwd -u john-x, --maxdays MAX_DAYS设置密码的最大使用期限。sudo passwd -x 90 john-n, --mindays MIN_DAYS设置密码的最小使用期限。sudo passwd -n 7 john-w, --warndays WARN_DAYS设置密码过期前的警告天数。sudo passwd -w 7 john-q, --quiet安静模式不输出任何信息。passwd -q\nUsermod\nusermoduser modify命令是 Linux 系统中的一个命令行工具用于修改用户的属性或配置。usermod 命令允许您更改现有用户的用户名、UID、主目录、默认 shell 等信息,还可以将用户添加到其他用户组中。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-c, --comment COMMENT修改用户的注释字段。sudo usermod -c "John Smith" john-d, --home HOME_DIR修改用户的主目录并将目录内容移至新位置使用 -m 选项。sudo usermod -d /home/newjohn -m john-e, --expiredate EXPIRE_DATE设置用户帐户的过期日期。sudo usermod -e 2024-12-31 john-f, --inactive INACTIVE设置密码过期后多少天账户变为不活跃状态。sudo usermod -f 30 john-g, --gid GROUP修改用户的主用户组。sudo usermod -g staff john-G, --groups GROUPS修改用户所属的附加组。sudo usermod -G staff,developer john-a, --append将用户添加到附加组与 -G 选项一起使用。sudo usermod -a -G sudo john-l, --login NEW_LOGIN修改用户的登录名。sudo usermod -l newjohn john-L, --lock锁定用户密码禁用账户。sudo usermod -L john-U, --unlock解锁用户密码启用账户。sudo usermod -U john-s, --shell SHELL修改用户的登录 shell。sudo usermod -s /bin/zsh john-u, --uid UID修改用户的用户 IDUID。sudo usermod -u 1001 john-p, --password PASSWORD修改用户的加密密码。sudo usermod -p password_hash john-m, --move-home将用户的主目录内容移动到新位置与 -d 选项一起使用。sudo usermod -d /home/newjohn -m john-o, --non-unique允许分配重复的 UID与 -u 选项一起使用。sudo usermod -o -u 1001 john\n删除\nUserdel\nuserdelUser Delete命令是 Linux 系统中的一个命令行工具用于删除现有用户帐户。默认情况下userdel 命令仅删除用户的帐户,而不删除用户的主目录和邮件箱。如果需要删除用户的主目录和邮件箱,可以使用 -r 选项。\n\n删除用户前的检查在删除用户之前应检查用户是否拥有任何正在运行的进程并终止这些进程。可以使用 ps -u username 命令查看用户的进程。\n备份重要数据在删除用户及其主目录之前建议备份用户的重要数据以防止数据丢失。\nSELinux 用户映射:如果系统启用了 SELinux并且为用户分配了 SELinux 用户映射,可以使用 -Z 选项删除该映射。\n删除用户后删除用户后应检查并清理与该用户相关的任何残留文件或配置以确保系统的一致性和安全性。\n\n# 删除一个用户\nsudo userdel john\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-f, --force强制删除用户账户即使用户当前正在登录。sudo userdel -f john-r, --remove删除用户的主目录及其邮件池。sudo userdel -r john-Z, --selinux-user删除用户的 SELinux 用户映射。sudo userdel -Z john\n用户组\n创建\nGroupadd\ngroupadd 命令是 Linux 系统中的一个命令行工具,用于创建新的用户组。管理员用户(如 root 用户)可以使用 groupadd 命令创建新组。\n# 创建一个新组\nsudo groupadd newgroup\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-f, --force强制操作如果组已存在则不报错。如果组不存在则创建新组。sudo groupadd -f developers-g, --gid GID指定新组的组 ID。sudo groupadd -g 1001 developers-K, --key KEY=VALUE覆盖 /etc/login.defs 文件中的设置。sudo groupadd -K GID_MIN=1000 developers-o, --non-unique允许创建具有重复 GID 的组。sudo groupadd -o -g 1001 developers-r, --system创建一个系统组。sudo groupadd -r sysgroup\n管理\nGroups\ngroups 命令是 Linux 系统中的一个命令行工具,用于显示当前用户所属的用户组。如果没有指定用户名,则 groups 命令将显示当前用户所属的用户组。\n# 显示当前用户所属的用户组\ngroups\n \n# 显示指定用户所属的用户组\ngroups john\nGpasswd\ngpasswd group password命令是 Linux 系统中的一个命令行工具,用于管理用户组的密码和成员列表。管理员用户(如 root 用户)可以使用 gpasswd 命令来添加或删除用户组的成员,或者设置或删除用户组的密码。\n# 设置组密码\nsudo gpasswd newgroup\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-a, --add user将用户添加到组中。sudo gpasswd -a john developers-d, --delete user从组中删除用户。sudo gpasswd -d john developers-r, --remove删除组密码。sudo gpasswd -r developers-R, --restrict禁用组密码只有组管理员可以使用 newgrp 命令。sudo gpasswd -R developers-A, --administrators user,...设置组管理员。sudo gpasswd -A admin1,admin2 developers-M, --members user,...设置组成员覆盖现有成员。sudo gpasswd -M john,doe developers\nGroupmod\ngroupmod group modify命令是 Linux 系统中的一个命令行工具,用于修改已有用户组的属性,例如组 ID、组名称和组密码等。管理员用户如 root 用户)可以使用 groupmod 命令来更改用户组的属性。\n# 修改组名\nsudo groupmod -n newname oldname\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-g, --gid GID将组的 GID 设置为指定的值。sudo groupmod -g 1001 newgroup-n, --new-name NEW_GROUP将组的名称更改为指定的名称。sudo groupmod -n newgroup2 newgroup-o, --non-unique允许使用非唯一 GID 创建组。sudo groupmod -o newgroup-p, --password PASSWORD将组密码设置为指定的密码。sudo groupmod -p mypassword newgroup\n删除\nGroupdel\ngroupdel group delete是 Linux 系统中的一个命令行工具,用于删除一个用户组。删除用户组时,系统会自动将该组的所有成员从该组中删除,并将文件和目录中的组 ID 更改为其他组。\n# 删除一个用户组\nsudo groupdel newgroup\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-f, --force强制删除用户组即使该组仍有成员。sudo groupdel -f newgroup-h, --help显示命令帮助信息。groupdel -h-R, --root CHROOT_DIR在指定的 chroot 环境中运行命令。sudo groupdel --root /mnt/newroot newgroup-v, --verbose显示命令详细输出。sudo groupdel -v newgroup\nRoot 超级用户\n在 Linux 系统中root 是超级用户具有完全的系统管理权限。root 用户可以执行任何命令并访问系统中的所有文件和资源。在默认情况下root 用户的密码是空的,因此在安全性方面需要额外注意。\nSu\nsuswitch user命令是 Linux 系统中的一个命令行工具它允许您在不注销当前用户的情况下切换到其他用户帐户。默认情况下su 命令切换到超级用户帐户root。\n\n使用 sudo 代替 su在许多现代系统中推荐使用 sudo 命令来代替 su以提供更细粒度的权限控制和审计功能。\n登录环境使用 -l 或 - 选项时su 命令会模拟用户完整的登录过程,包括加载用户的 shell 配置文件(如 .bash_profile、.profile 等)。\n环境变量默认情况下su 命令会重置环境变量,以匹配目标用户的环境。使用 -m 或 -p 选项可以保留当前的环境变量。\n权限要求切换到其他用户身份通常需要输入目标用户的密码。切换到 root 用户身份需要输入 root 用户的密码。\n安全性尽量使用 su 命令时指定 - 选项,以确保切换到目标用户的完整环境,减少潜在的权限问题。\n\n# 默认切换 root\nsu\n \n# 切换到 debian\nsu debian\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-切换到目标用户的登录环境,相当于 -l 选项。su --l, --login切换到目标用户的登录环境。su -l john-c, --command COMMAND执行指定的命令然后退出。su -c 'ls /root'-s, --shell SHELL使用指定的 shell 而不是目标用户的默认 shell。su -s /bin/bash john-m, --preserve-environment保留当前环境变量而不是重置它们。su -m john-p保留当前环境变量等同于 -m 选项。su -p john-h, --help显示帮助信息。su -h-v, --version显示版本信息。su -v\nSudo\n在 Unix 和类 Unix 系统中sudo 是一个强大的工具允许普通用户以超级用户root的权限来执行特定的命令或访问受限资源。sudo 命令的行为由一个配置文件定义,这个文件通常称为 sudoers 文件。\nsudoers 文件位于 /etc/sudoers 或 /etc/sudoers.d 目录中只有超级用户root有权限进行编辑。\n\n谨慎编辑 sudoers 文件:对 sudoers 文件的修改应当谨慎进行,并且建议使用 visudo 命令来编辑,以确保语法正确并避免意外的访问限制。\n安全性在使用 sudo 命令时,应确保只有可信任的用户和命令被授权,以防止潜在的安全漏洞。\n审计和记录sudo 命令的使用会被记录在 /var/log/auth.log 文件中,管理员可以通过该日志进行审计和监控。\n\n# Sudoers 文件示例\n \n# 允许 `sudo` 组的成员以任何用户身份ALL:ALL执行任何命令ALL。\n%sudo ALL=(ALL:ALL) ALL\n \n# 允许 `admin` 组的成员以任何用户身份ALL:ALL执行任何命令ALL。\n%admin ALL=(ALL:ALL) ALL\n \n# 允许 `root` 用户以任何用户身份ALL:ALL执行任何命令ALL。\nroot ALL=(ALL:ALL) ALL\n \n# 允许 `sudo` 组的成员以任何用户身份ALL:ALL执行任何命令ALL并且无需输入密码NOPASSWD。\n%sudo ALL=(ALL:ALL) NOPASSWD: ALL\n语法格式\nuser/group hosts=(users:groups) commands\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n项目描述user/group指定用户或用户组可以使用用户名或组名。hosts指定可以使用 sudo 命令的主机列表可以是主机名、IP 地址或特殊的通配符。users:groups指定要执行命令的用户和组以冒号分隔。commands指定允许执行的命令。ALL表示匹配所有主机、用户或命令。NOPASSWD表示无需输入密码。\n使用 sudo 命令创建 sudo 用户\n# 1. 创建用户\nsudo adduser username\n \n# 2. 将用户添加到 sudo 组\nsudo usermod -aG sudo username\n \n# 3. 检查用户是否已成功添加到 sudo 组\ngroups username\n \n# 4. 确认用户可以使用 sudo 命令\nsudo -l -U username\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-u, --user USER指定要切换到的用户。sudo -u user1 ls -l-g, --group GROUP指定要切换到的组。sudo -g group1 ls -l-k, --reset-timestamp重置 sudo 命令的时间戳。sudo -k-v, --validate验证 sudo 命令的权限但不执行任何命令。sudo -v-l, --list [COMMAND]显示 sudo 命令当前用户的授权信息或显示指定命令的授权信息。sudo -l 或 sudo -l /usr/bin/apt-get-h, --help显示 sudo 命令的帮助信息。sudo -h-V, --version显示 sudo 命令的版本信息。sudo -V\nNewusers\nnewusers 是一个 Linux 系统命令,用于批量创建新的用户账号。该命令可以从指定的文件中读取一组用户信息,并自动创建这些用户账号,设置相应的密码、主目录和 shell。\n语法格式\nnewusers 命令从指定的文件中读取用户信息,每行包括以下字段,字段间用冒号分隔:\n用户名:密码:用户ID:主组ID:注释字段:主目录:默认shell\n\n用户名新用户的登录名。\n密码用户的密码通常以加密格式存储。\n用户 IDUID新用户的用户标识符。\n主组 IDGID新用户的主组标识符。\n注释字段用户的全名或其他描述信息。\n主目录用户的主目录路径。\n默认 shell用户登录时的默认 shell。\n\n使用 Newusers 批量创建\n-------------------- user.txt --------------------\nuser1:x:1001:1001:User One:/home/user1:/bin/bash\nuser2:x:1002:1002:User Two:/home/user2:/bin/bash\nuser3:x:1003:1003:User Three:/home/user3:/bin/bash\n--------------------------------------------------\n \n# 读取 user.txt 批量创建用户\nnewusers user.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-u, --uid指定起始用户 IDnewusers -u 1000 users.txt-g, --gid指定起始组 IDnewusers -g 1000 users.txt-c, --comment指定用户的注释信息newusers -c "User One" users.txt, newusers --comment "User One" users.txt-s, --shell指定新用户的默认 shellnewusers -s /bin/bash users.txt, newusers --shell /bin/bash users.txt-H, --no-create-home禁止创建用户主目录newusers -H users.txt, newusers --no-create-home users.txt-N, --no-user-group禁止创建与用户名同名的主组newusers -N users.txt, newusers --no-user-group users.txt\nChpasswd\nchpasswd 命令用于批量修改用户的密码,可以一次性修改多个用户的密码,而不需要逐个输入密码。它可以从标准输入、文件或命令行参数中读取用户密码信息,并将其应用于指定的用户账户。\n\n文件安全文件中包含敏感信息用户密码应妥善保管并确保其权限设置正确以防止未经授权的访问。\n加密格式如果密码已加密确保使用 -e 选项。否则,密码将被视为明文并重新加密。\n权限要求chpasswd 命令需要管理员权限,通常通过 sudo 命令运行。\n密码复杂性在更新密码时建议使用复杂密码包括大小写字母、数字和特殊字符以提高账户的安全性。\n\n语法格式\nuser1:password1\nuser2:password2\n使用 Chpasswd 批量更改\n-------------------- users.txt --------------------\nuser1:password1\nuser2:password2\n--------------------------------------------------\n \n# 将 user1 的密码修改为 password1\necho 'user1:password1' | chpasswd\n \n# 批量更新,使用 md5 加密方式\nsudo chpasswd -m < users.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-e, --encrypted指定密码已加密chpasswd -e < users.txt-h, --help显示帮助信息并退出chpasswd --help-m, --md5指定密码以 MD5 格式加密chpasswd -m < users.txt-c, --crypt-method指定密码加密方法chpasswd --crypt-method SHA512 < users.txt-R, --root以 root 权限运行命令sudo chpasswd --root-u, --update仅更新现有用户的密码chpasswd -u < users.txt-I, --inactive指定密码失效时间单位为天chpasswd --inactive 7 < users.txt\npwck、grpck\npwckPassword Check和 grpckGroup Check命令是 Linux 系统中用于检查 /etc/passwd、/etc/shadow 和 /etc/group 等文件的格式和完整性的工具。这些命令可以帮助系统管理员查找和修复这些文件中的错误,以确保系统的安全性和稳定性。\n在执行 pwck 或 grpck 之前,建议备份 /etc/passwd、/etc/shadow、/etc/group 和 /etc/gshadow 文件,以防止误操作导致数据丢失。\n用户配置文件\n\n用户配置文件/etc/passwd 文件是 Linux 系统中存储用户信息的文件之一,包含每个用户的用户名、用户 ID、主目录、登录 shell 等信息。\n用户密码配置文件/etc/shadow 文件是 Linux 系统中存储用户密码信息的文件之一,包含每个用户的密码哈希值、最后一次更改密码的日期等信息。\n用户组配置文件/etc/group 文件是 Linux 系统中存储用户组信息的文件之一,包含每个用户组的名称、组 ID 和组成员列表等信息。\n用户组密码配置文件/etc/gshadow 文件是 Linux 系统中存储用户组密码信息的文件之一,包含每个用户组的密码哈希值、管理员列表和成员列表等信息。\n默认配置文件/etc/login.defs 文件是 Linux 系统中存储默认登录选项的文件之一,包含默认的密码长度、最大尝试登录次数等信息。\n配置文件/etc/adduser.conf 文件是 Linux 系统中存储新用户默认配置选项的文件之一,包含新用户的默认主目录、默认 shell 等信息。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例-r, --root DIR指定要检查的根目录pwck/grpck -r /mnt-s, --silent安静模式只输出错误信息pwck/grpck -s /etc/passwd /etc/shadow-q, --quiet安静模式不输出信息pwck/grpck -q /etc/passwd /etc/group-n, --nocheck不检查用户主目录和组文件pwck/grpck -n /etc/passwd /etc/shadow\npwconv、pwunconv、grpconv、grpunconv\npwconvPassword Conversion、pwunconvPassword unConversion、grpconvGroup Conversion和 grpunconvGroup unConversion 命令是 Linux 系统中的工具,用于转换密码文件和组文件的格式。它们帮助系统管理员将 /etc/passwd、/etc/shadow 和 /etc/group 等文件的格式进行转换或恢复,从而提高系统的安全性和管理效率。\n作用和用途\n\npwconv 命令:将 /etc/passwd 和 /etc/shadow 文件的格式从标准格式(包括用户名、密码和 UID 等信息)转换为 shadow 格式(将密码单独存储在 /etc/shadow 文件中)。\npwunconv 命令:将 /etc/passwd 和 /etc/shadow 文件的格式从 shadow 格式转换为标准格式。\ngrpconv 命令:将 /etc/group 文件的格式从标准格式(包括组名、组密码和 GID 等信息)转换为 gshadow 格式(将组密码单独存储在 /etc/gshadow 文件中)。\ngrpunconv 命令:将 /etc/group 文件的格式从 gshadow 格式转换为标准格式。\n\n这些工具的用途包括但不限于\n\n提高系统安全性使用 shadow 格式将用户密码单独存储在 /etc/shadow 文件中,可以防止未经授权的用户访问密码信息,提高系统安全性。\n管理用户和组的身份验证通过转换和恢复密码和组文件格式可以更轻松地管理用户和组的身份验证信息例如更改密码、添加或删除用户和组等操作。\n\n其他\nW\nw 命令在 Unix 和 Unix 类操作系统中用于显示有关系统活动的信息。这个命令可以显示当前系统中登录的用户、他们所做的事情、从哪里登录、他们登录的时间以及系统负载等。\nroot@LinuxTest:~# w\n 14:16:51 up 22:16, 2 users, load average: 0.00, 0.00, 0.00\nUSER TTY 来自 LOGIN@ IDLE JCPU PCPU WHAT\nsevenwat tty1 - 二16 22:15m 0.16s 0.05s -bash\nsevenwat pts/0 172.17.0.100 13:55 0.00s 0.51s 0.13s sshd: sevenwate [priv]\nId\nid 命令用于显示用户和用户组的标识信息。它可以用于查看当前用户或指定用户的 UID用户标识符、GID组标识符和所属用户组的名称。\nsevenwate@LinuxTest:~$ id\n用户id=1000(sevenwate) 组id=1000(sevenwate) 组=1000(sevenwate),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev),1001(grpdemo)\nWhoami\nwhoami 命令用于显示当前登录用户的用户名。它是一个非常简单的命令,通常用于 shell 脚本和命令行中,以便在需要当前用户的用户名时快速获取它。\nsevenwate@LinuxTest:~$ whoami\nsevenwate\nLast\nlast 命令在 Linux 中用于显示系统的登录记录。这个命令列出了系统登录和启动的详细信息,如登录用户、登录的 IP 地址、登录时间以及登录持续的时间。\nroot@LinuxTest:~# last\nsevenwat pts/0 172.17.0.100 Wed May 31 13:55 still logged in\nsevenwat pts/1 172.17.0.100 Wed May 31 11:07 - 11:21 (00:14)\nsevenwat pts/0 172.17.0.100 Wed May 31 11:07 - 13:00 (01:53)\nsevenwat pts/0 172.17.0.100 Wed May 31 10:55 - 11:04 (00:09)\nsevenwat pts/0 172.17.0.100 Wed May 31 10:49 - 10:51 (00:02)\nsevenwat pts/0 172.17.0.100 Tue May 30 17:03 - 17:35 (00:32)\nsevenwat pts/0 172.17.0.100 Tue May 30 16:03 - 16:53 (00:50)\nsevenwat pts/2 172.17.0.100 Tue May 30 16:02 - 16:02 (00:00)\nsevenwat pts/1 172.17.0.100 Tue May 30 16:02 - 16:02 (00:00)\nsevenwat pts/0 172.17.0.100 Tue May 30 16:02 - 16:02 (00:00)\nsevenwat tty1 Tue May 30 16:01 still logged in\nreboot system boot 5.10.0-23-amd64 Tue May 30 16:00 still running\n \nwtmp begins Tue May 30 16:00:47 2023\nLastlog\nlastlog 命令用于查看所有用户最后一次登录的时间和登录的终端。这个命令检查 /var/log/lastlog 文件以确定每个用户的最后一次登录信息。此命令的输出包含用户名、最后登录的端口和最后登录的时间。\nroot@LinuxTest:~# lastlog\n用户名 端口 来自 最后登录时间\nroot **从未登录过**\n……\nsevenwate pts/0 172.17.0.100 三 5月 31 13:55:15 +0800 2023\nnewuser **从未登录过**\n创建用户示例\ngraph LR\n SwitchToRoot[切换到 root 用户]\n SwitchToRoot --> CreateUser[创建新用户]\n CreateUser --> SetPassword[设置新用户的密码]\n SetPassword --> ChangeUserInfo{更新新用户信息?}\n ChangeUserInfo -- Yes --> RunChfn[chfn]\n ChangeUserInfo -- No --> AssignHomeDir{指定用户目录?}\n RunChfn --> AssignHomeDir\n AssignHomeDir -- Yes --> RunUseraddWithD[useradd -d]\n AssignHomeDir -- No --> SetLoginShell{指定登录 shell?}\n RunUseraddWithD --> SetLoginShell\n SetLoginShell -- Yes --> RunUseraddWithS[useradd -s]\n SetLoginShell -- No --> AddToExtraGroups{添加到额外的组?}\n RunUseraddWithS --> AddToExtraGroups\n AddToExtraGroups -- Yes --> RunUsermod[usermod -aG]\n AddToExtraGroups -- No --> End(结束)\n RunUsermod --> End\n\n\n\n打开终端快捷键 Ctrl+Alt+T 打开终端。\n\n\n切换到 root 用户:使用 su - 命令切换到 root 用户。\n\n\n使用 useradd 命令创建新用户:使用 useradd 命令和新用户的用户名来创建新用户。例如创建一个名为 newuser 的新用户:\nroot@LinuxTest:~# useradd newuser\n\n\n设置新用户的密码使用 passwd 命令和新用户的用户名来设置密码。\nroot@LinuxTest:~# passwd newuser\n新的 密码:\n重新输入新的 密码:\npasswd已成功更新密码\n\n\n更改新用户的信息可选可以使用 chfn 命令更改新用户的全名、房间号、工作电话和家庭电话。\nroot@LinuxTest:~# chfn newuser\n正在改变 newuser 的用户信息\n请输入新值或直接敲回车键以使用默认值\n 全名 []: newuser\n 房间号码 []: 888\n 工作电话 []: 18688888888\n 家庭电话 []: 0371\n 其它 []: \n\n\n给新用户分配家目录可选默认情况下 useradd 命令会为新用户创建一个在 /home 下的家目录。usermod 可以使用 -d 选项为新用户指定一个不同的家目录。例如,指定 newuser 的家目录是 /opt/newuser\nroot@LinuxTest:~# usermod -d /opt/newuser -m newuser\n\n\n指定不同的登录 shell可选usermod 可以使用 -s 选项指定一个不同的登录 shell。例如为 newuser 指定 /bin/sbin/noligin 作为登录 shell你可以运行\n# 使用 usermod 命令\nroot@LinuxTest:~# usermod -s /usr/bin/nologin newuser\n# 使用 chsh 命令\nroot@LinuxTest:~# chsh -s /bin/bash newuser\n\n\n将新用户添加到一个或多个额外的组可选可以使用 usermod 命令的 -G 选项将新用户添加到一个或多个额外的组。例如将 newuser 添加到 sudo 和 users 组,你可以运行:\nroot@LinuxTest:~# usermod -aG sudo,users newuser\nroot@LinuxTest:~# id newuser\n用户id=1003(newuser) 组id=1003(newuser) 组=1003(newuser),27(sudo),100(users)\n# 用户最终信息\nroot@LinuxTest:~# cat /etc/passwd | grep newuser\nnewuser:x:1003:1003:newuser,888-1,18688888888,0371-88888888:/opt/newuser2:/usr/bin/nologin\n\n"},"Technology/OperatingSystem/Linux/3.基础操作/Shell-命令行操作":{"title":"Linux 命令行操作","links":[":alpha:",":upper:",":lower:",":digit:",":alnum:",":punct:"],"tags":["Linux/基础","技术/操作系统"],"content":"一台完整的计算机是由运算器、控制器、存储器、输入/输出等多种硬件设备共同组成的而能让各种硬件设备各司其职且又能协同运行的东西就是系统内核。Linux 系统的内核负责完成对硬件资源的分配、调度等管理任务,对系统的正常运行起着十分重要的作用。\nShell 就是终端程序的统称,它充当了人与内核(硬件)之间的翻译官,用户把一些命令告诉终端程序,它就会调用相应的程序服务去完成某些工作。现在包括红帽系统在内的许多主流 Linux 系统默认使用的终端是 BashBourne-Again SHell解释器这个 Bash 解释器主要有以下 4 项优势:\n\n通过上下方向键来调取执行过的 Linux 命令;\n命令或参数仅需输入前几位就可以用 Tab 键补全;\n具有强大的批处理脚本\n具有实用的环境变量功能。\n\n执行命令\n命令 [命令参数] [命令对象]\n可选择的、可加或可不加的、非必需的参数使用中括号引起来而命令所要求的、必须有的参数或对象值则不带中括号。\n\n\n命令名称就是语法中的动词表达的是想要做的事情例如创建用户、查看文件、重启系统等操作。\n\n\n命令参数用于对命令进行调整让修改过的命令能更好地贴合工作需求达到事半功倍的效果。\n\n\nLinux 命令参数的长格式与短格式示例:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类别示例长格式man —help短格式man -h\n\n命令对象一般指要处理的文件、目录、用户等资源名称也就是命令执行后的承受方。例如创建一位叫小明的用户、查看一个叫工资表的文件、重启一个 IP 为 192.168.10.10 的系统等。\n\nLinux 系统中的命令、参数、对象都是严格区分大小写的。\n目录移动\nLinux 终端执行命令的很多情况下需要经常的更换目录cd 命令、pushd 命令、popd 命令可以快速移动目录。\n\ncd回到当前用户目录。\ncd ~:回到当前用户目录(方便切换到其他用户目录)。\ncd -:回到上次工作的目录。\npushd path存入 path 目录到目录栈。\npopd移动到目录栈弹出的目录。\n\n# 使用 `cd` 命令回到当前用户目录\n$ cd\n$ pwd\n/home/username\n \n# 使用 `cd ~` 命令也可以回到当前用户目录\n$ cd ~\n$ pwd\n/home/username\n \n# 使用 `cd -` 命令回到上次工作的目录\n$ cd /tmp\n$ cd -\n$ pwd\n/home/username\n \n# 使用 `pushd` 命令将目录存入目录栈\n$ pushd /var\n/var /home/username\n \n# 使用 `popd` 命令移动到目录栈弹出的目录\n$ popd\n/home/username\n快捷键\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n快捷键功能描述Tab自动补全命令或文件名Ctrl+C终止当前命令Ctrl+Z将当前进程放到后台Ctrl+D退出当前终端Ctrl+L清屏Ctrl+U删除从光标位置到行首的字符Ctrl+K删除从光标位置到行尾的字符Ctrl+A移动光标到行首Ctrl+E移动光标到行尾Ctrl+R反向搜索命令历史Ctrl+W删除光标前的一个单词Ctrl+Y粘贴由 Ctrl+U、Ctrl+K 或 Ctrl+W 删除的文本Ctrl+T交换光标处字符与之前的字符Alt+B向后移动一个单词或 Ctrl+ 左箭头Alt+F向前移动一个单词或 Ctrl+ 右箭头Ctrl+Shift+C复制部分图形终端Ctrl+Shift+V粘贴部分图形终端\n特殊符号\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号功能描述!!引用上一条命令。例如,如果上一条命令是 ls -l那么输入 !! 将再次执行 ls -l。!$引用上一条命令的最后一个参数。例如,如果上一条命令是 cp /some/long/path /another/path那么输入 cd !$ 将执行 cd /another/path。!string引用最近一条以 string 开头的命令。例如,如果你之前执行过 ls -l那么输入 !ls 将再次执行 ls -l。^string1^string2^快速替换上一条命令中的字符串并执行。例如,如果上一条命令是 cat file1那么输入 ^file1^file2^ 将执行 cat file2。&&逻辑 AND。如果前一个命令成功执行退出状态为 0则执行后一个命令。例如command1 && command2 会在 command1 成功后执行 command2。;命令分隔符。允许在一行中执行多个命令。例如command1; command2 会依次执行 command1 和 command2不考虑前一个命令的成功与否。>输出重定向。将命令的输出写入到文件中而不是显示在屏幕上。例如ls -l > file.txt 将 ls -l 的输出保存到 file.txt。>>追加输出重定向。将命令的输出追加到现有文件的末尾。例如echo "hello" >> file.txt 将追加 “hello” 到 file.txt。<输入重定向。使用文件作为命令的输入。例如cat < file.txt 会显示 file.txt 的内容。“反引号。执行其中的命令并将输出作为另一个命令的参数。例如echo “Today is `date`” 会显示今天的日期。$( )命令替换。类似于反引号但更易读易用。例如echo "Today is $(date)" 会显示今天的日期。{ }大括号扩展。生成序列或列表。例如echo {1..5} 会输出 1 2 3 4 5。#注释符号。# 后面的内容将被视为注释,不会被执行。例如,# This is a comment。\n常用命令\n文件操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明lslist列出目录中的文件列表cdchange directory更改当前工作目录pwdprint working directory显示当前工作目录mkdirmake directory创建新目录rmdirremove directory删除空目录touchtouch创建新文件cpcopy复制文件或目录mvmove移动文件或目录rmremove删除文件或目录\n文件处理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明catconcatenate查看、合并文件内容headhead查看文件头部内容tailtail查看文件尾部内容grepglobal regular expression print在文件中查找指定文本sedstream editor流编辑器用于对文件进行基本文本处理awkawk文本和数据处理工具\n系统管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明psprocess status查看进程状态toptop实时查看系统进程状态killkill终止进程shutdownshutdown关闭系统rebootreboot重启系统unameuname显示系统信息dfdisk free显示磁盘使用情况dudisk usage显示目录空间使用情况freefree显示系统内存使用情况\n网络管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述ipinternet protocol显示和配置网络接口信息pingping测试主机之间的连通性nslookupname server lookup查询域名解析信息traceroutetrace route显示数据包到达目的地经过的路由信息routeroute显示和配置系统的路由表netstatnetwork statistics显示网络连接状态和统计信息tcpdumpTCP dump抓取网络数据包并进行分析\n权限管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述chmodchange mode修改文件或目录的访问权限chownchange owner修改文件或目录的所有者chgrpchange group修改文件或目录的所属组useradduser add添加用户账号usermoduser modify修改用户账号信息userdeluser delete删除用户账号groupaddgroup add添加用户组groupmodgroup modify修改用户组信息groupdelgroup delete删除用户组passwdpassword修改用户密码suswitch user切换用户身份sudosuperuser do以超级用户身份执行命令visudovisual sudo编辑 sudo 配置文件ididentity显示当前用户信息whoamiwho am i显示当前登录用户名\n软件管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼说明apt-getAdvanced Packaging ToolUbuntu 系统软件包管理工具yumYellowdog Updater ModifiedCentOS、Fedora 等系统软件包管理工具dpkgDebian PackageDebian、Ubuntu 等系统软件包管理工具rpmRed Hat Package ManagerCentOS、Fedora 等系统软件包管理工具\n磁盘管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令全拼描述dfdisk filesystem显示磁盘空间使用情况dudisk usage显示文件和目录的磁盘使用情况fdiskfixed disk磁盘分区管理工具fsckfile system check检查和修复文件系统mkfsmake filesystem创建文件系统mountmount挂载文件系统到目录上umountunmount卸载文件系统\n进程管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令命令全拼描述psprocess status显示当前进程状态toptask-oriented processor动态显示进程信息killkill终止一个进程killallkillall终止一个指定名称的进程nicenice改变进程优先级renicerenice改变正在运行进程的优先级jobsjobs显示当前 shell 的活动作业bgbackground将一个进程置于后台fgforeground将一个进程置于前台nohupno hang up在后台运行命令并不挂起pstreeprocess tree显示进程树\n任务\nLinux 系统中运行程序时,可以选择在前台或后台运行。在前台运行时,程序会占用终端并且输出信息直接显示在终端中。而在后台运行时,程序在后台默默地执行,不会占用终端并且不会直接显示输出信息。\n运行\n\n& 符号:在命令的末尾添加 & 符号例如command &。这将使命令在后台运行。\nnohup 命令nohup 命令可以使命令在后台运行并忽略挂断信号SIGHUP**这意味着即使你退出当前终端,程序仍会继续运行。**用法为nohup command &。\n\n# 在后台运行 sleep 命令(这个命令仅仅会让 shell 睡眠一段时间)\n$ sleep 300 &\n \n# 使用 nohup 命令在后台运行 sleep 命令,并且将输出信息存入 nohup.out 文件中\n$ nohup sleep 300 &\n \n# 使用 nohup 命令在后台运行 sleep 命令,并且将输出信息重定向到 output.txt 文件中\n$ nohup sleep 300 > output.txt &\n \n# 运行一个会产生错误的命令,并将错误信息重定向到 err.txt 文件中\n$ ls /nonexistent > /dev/null 2> err.txt\n \n# 使用 nohup 命令在后台运行一个会产生错误的命令,并将输出和错误信息重定向到相应的文件中\n$ nohup ls /nonexistent > out.txt 2> err.txt &\n \n# 使用 &> 符号将标准输出和错误输出都重定向到同一个文件中\n$ ls /nonexistent &> all.txt\n \n# 使用 |& 符号将错误输出重定向到另一个命令的标准输入\n$ ls /nonexistent |& less\n管理\nJobs\njobs 命令可以列出当前终端会话中正在运行的后台任务。每个任务都有一个唯一的编号,可以使用该编号来操作任务,例如将任务切换到前台或终止任务。\n# 列出当前终端会话中的后台任务\n$ jobs\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全拼描述-l—list列出每个作业的进程 ID 号-p—pid仅列出作业的进程 ID 号-n—new显示自上次通知以后已更改的作业-r—running仅列出运行中的作业-s—stopped仅列出停止的作业\nfg、bg\nfg 命令可以将一个后台任务切换到前台运行bg 命令可以将一个在后台暂停的任务切换到后台继续运行。\n# 将一个后台任务切换到前台运行,假设任务的编号是 1\n$ fg %1\n \n# 将一个后台任务切换到后台继续运行,假设任务的编号是 1\n$ bg %1\nPs\nps 命令可以显示系统中所有进程的状态,包括后台运行的进程。\n# 列出系统中所有进程的状态\n$ ps\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项选项全拼描述-A—all显示所有进程在某些系统上此选项为 -e-f—full完整格式列出-u—user按用户列出-x—all-user-processes列出所有用户的进程-l—long长格式列出-j—jobs工作格式列出-r—running列出运行中的进程-a—all-with-tty列出拥有终端的所有进程-e—every列出所有进程在某些系统上此选项为 -A-p—pid列出指定进程号的进程\nKill\nkill 命令是用于发送特定的信号到操作系统中的进程。默认情况下如果不指定信号kill 命令会发送 TERM (终止) 信号,这会请求一个进程自我终止。\n# 终止一个后台任务,假设任务的编号是 1\n$ kill %1\n \n# 使用 ps 命令找到进程的 PID然后使用 kill 命令终止进程\n$ ps\n$ kill PID\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述-l列出所有可用的信号-s signal指定发送的信号可以是信号名或信号号码-p不发送信号只打印进程 ID-9 或 -KILL发送 KILL 信号强制终止进程\n管道\n管道命令符把前一个命令原本要输出到屏幕的信息当作后一个命令的标准输入其执行格式为「命令 A | 命令 B」。按下键盘上的 Shift+ 反斜杠(\\)键即可输入管道符,\n# 输出禁止登录用户行数\ngrep /sbin/nologin /etc/passwd | wc -l\n \n# 搜索与 bash 有关的进程\nps aux | grep bash\n命令符可以无限组合例如命令 A | 命令 B | 命令 C |……\n\n曾经有位东北的同学做了一个特别贴切的类比把管道符当做流水线作业这跟吃顿烧烤是同一个道理即第一个人负责切肉第二个人负责串肉第三个人负责烧烤最后的处理结果交付给用户。\n\n重定向\n输入重定向是指把文件导入到命令中而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中。\n\n\n标准输入重定向STDIN文件描述符为 0默认从键盘输入也可从其他文件或命令中输入。\n\n\n标准输出重定向STDOUT文件描述符为 1默认输出到屏幕。\n\n\n错误输出重定向STDERR文件描述符为 2默认输出到屏幕。\n\n\n对于重定向中的标准输出模式可以省略文件描述符 1 不写,而错误输出模式的文件描述符 2 是必须要写的。\n# 输入重定向:将 file1.txt 作为 sort 命令的标准输入\n$ sort < file1.txt \n \n# 输入重定向并重定向输出:将 file1.txt 作为 sort 命令的输入,并将结果输出到 file2.txt 中\n$ sort < file1.txt > file2.txt \n \n# Here 文档(<<):将两行 "This is a line." 作为 cat 的输入\n$ cat << EOF\nThis is a line.\nThis is a line.\nEOF\n \n# 输出重定向:将 "Hello, World!" 输出到 output.txt 文件中(覆盖文件原有内容)\n$ echo "Hello, World!" > output.txt \n \n# 错误输出重定向:将错误信息输出到 error.txt 文件中\n$ ls /nonexistentdirectory 2> error.txt \n \n# 追加输出重定向:将 "Hello again!" 追加到 output.txt 文件中\n$ echo "Hello again!" >> output.txt \n \n# 追加错误输出重定向:将错误信息追加到 error.txt 文件中\n$ ls /anothernonexistentdirectory 2>> error.txt \n \n# 同时重定向标准输出和错误输出,追加到同一文件\n$ ls /nonexistentdirectory >> all_output.txt 2>&1 \n \n# 同时重定向标准输出和错误输出,追加到同一文件(简化写法)\n$ ls /nonexistentdirectory &>> all_output.txt \n \n输入重定向\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号作用命令 < 文件将文件作为命令的标准输入命令 << 分界符从标准输入中读入,直到遇见分界符才停止命令 < 文件 1 > 文件 2将文件 1 作为命令的标准输入并将标准输出到文件 2\n输出重定向\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n符号作用命令 > 文件将标准输出重定向到一个文件中(清空原有文件的数据)命令 2> 文件将错误输出重定向到一个文件中(清空原有文件的数据)命令 >> 文件将标准输出重定向到一个文件中(追加到原有内容的后面)命令 2>> 文件将错误输出重定向到一个文件中(追加到原有内容的后面)命令 >> 文件 2>&1、命令 &>> 文件将标准输出与错误输出共同写入到文件中(追加到原有内容的后面)\n通配符\n# 使用 * 通配符:列出所有 .txt 文件\n$ ls *.txt\n \n# 使用 ? 通配符:列出所有只有一个字符的 .txt 文件\n$ ls ?.txt\n \n# 使用 [] 通配符:列出所有以小写字母开始的 .txt 文件\n$ ls [a-z]*.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n通配符含义*任意字符?单个任意字符[a-z]单个小写字母[A-Z]单个大写字母[a-Z]单个字母[0-9]单个数字:alpha:任意字母:upper:任意大写字母:lower:任意小写字母:digit:所有数字:alnum:任意字母加数字:punct:标点符号\n转义字符\n# 使用反斜杠(\\)使反斜杠后面的一个变量变为单纯的字符。\n$ echo \\$HOME\n$HOME\n \n# 使用单引号(' ')转义其中所有的变量为单纯的字符串。\n$ echo '$HOME'\n$HOME\n \n# 使用双引号(" ")保留其中的变量属性,不进行转义处理。\n$ echo "$HOME"\n/home/username\n \n# 使用反引号(` `)把其中的命令执行后返回结果。\n$ echo `date`\nSun Sep 4 22:38:10 PDT 2023\n环境变量\n在 Linux 系统中,变量名称一般都是大写的,命令则都是小写的,这是一种约定俗成的规范。\nLinux 系统中最重要的 10 个环境变量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n变量名称作用HOME用户的主目录即家目录SHELL用户在使用的 Shell 解释器名称HISTSIZE输出的历史命令记录条数HISTFILESIZE保存的历史命令记录条数MAIL邮件保存路径LANG系统语言、语系名称RANDOM生成一个随机数字PS1Bash 解释器的提示符PATH定义解释器搜索用户执行命令的路径EDITOR用户默认的文本编辑器\n帮助文档\nMan\n使用 man 命令查看到的帮助内容信息\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n按键作用空格键向下翻一页PaGe down向下翻一页PaGe up向上翻一页home直接前往首页end直接前往尾页/从上至下搜索某个关键词,如“/linux”?从下至上搜索某个关键词,如“?linux”n定位到下一个搜索到的关键词N定位到上一个搜索到的关键词q退出帮助文档\n示例\n# 查看 man 的帮助文件\nman man\n \n# 查看 ssh 的帮助文件\nman sh"},"Technology/OperatingSystem/Linux/4.系统管理/Linux-内核管理":{"title":"Linux 内核管理","links":[],"tags":["Linux/系统管理","技术/操作系统"],"content":"概述\nLinux 内核\nLinux 内核是一个操作系统OS内核由林纳斯·托瓦兹Linus Torvalds在 1991 年首次发布。作为操作系统最核心的部分Linux 内核负责处理计算机硬件与软件资源的管理、提供系统服务的接口。它是一个中介,位于用户应用程序与计算机硬件之间,使应用程序在不直接操作硬件的情况下运行,同时保证了系统的稳定性和安全性。\nLinux 内核发展历史\nLinux 内核的发展是开源社区合作精神的典范。自 1991 年林纳斯·托瓦兹在赫尔辛基大学开始其开发项目以来经过三十多年的迅速发展Linux 内核已经成长为最为广泛使用的操作系统之一。它的发展历程标志着许多技术的创新与突破,比如对多处理器的支持、对不同硬件架构的兼容性以及对虚拟化的原生支持等。\nLinux 内核版本管理\nLinux 内核的版本管理体现了其开发过程的开放性和社区驱动的特点。内核版本号遵循“主版本号.次版本号.修订号.额外信息”的格式。其中偶数的次版本号代表稳定版本奇数的次版本号则用于开发中的版本。Linux 内核项目采用 Git 作为版本控制系统林纳斯·托瓦兹本人负责主线mainline内核的发布。\nLinux 内核架构\nLinux 内核的架构设计兼顾了灵活性与高效性,支持广泛的硬件平台。它主要包括以下几个部分:**进程管理、内存管理、文件系统、网络系统、设备驱动程序以及安全模块。**内核架构将这些功能模块化,不仅促进了开发和维护的便捷,也使得内核能够在不牺牲性能的情况下,提供丰富的功能和强大的扩展性。\nLinux 内核编译与安装\n准备工作\n\n明确目标首先你需要确定为什么要编译 Linux 内核。可能是为了获取新功能、支持新硬件、提高系统安全性或是出于学习目的。明确目标将帮助你选择合适的内核版本。\n选择合适的环境推荐在一个不是日常使用的系统上进行编译比如虚拟机这样可以避免潜在的风险对你的主系统产生影响。\n下载源码访问 The Linux Kernel Archives根据你的需求下载对应版本的内核源码。同时下载源码的 PGP 签名文件,以便进行安全验证。\n安装依赖编译内核需要 GCC 编译器、make 工具等。你可以通过 Linux 发行版的包管理器来安装这些工具及其他依赖。\n\n# Debian 以及其衍生版本\nsudo apt install bc binutils bison dwarves flex gcc git gnupg2 gzip libelf-dev libncurses5-dev libssl-dev make openssl pahole perl-base rsync tar xz-utils\n \n# Fedora 以及其衍生版本\nsudo dnf install binutils ncurses-devel \\\n /usr/include/{libelf.h,openssl/pkcs7.h} \\\n/usr/bin/{bc,bison,flex,gcc,git,gpg2,gzip,make,openssl,pahole,perl,rsync,tar,xz,zstd}\n选择内核版本\n\n理解版本内核版本有稳定版、长期支持LTS版和开发版等。选择适合你目标的版本。稳定版和 LTS 版更适合需要稳定性的环境,而开发版则包含最新的功能和修复。\n下载并验证下载所选版本的内核源码和 PGP 签名,使用 GPG 验证下载文件的真实性和完整性,确保源码未被篡改。\n\n# 安装 Linus Torvalds 和 Greg KH 使用的 GPG 公开密钥\ngpg2 --locate-keys torvalds@kernel.org gregkh@kernel.org\n \n# 验证 Tar 的完整性\ngpg2 --verify linux-*.tar.sign\n解压和配置内核\n\n解压源码使用 tar 命令解压内核源码包到一个工作目录中。\n配置内核\n\n基础配置可以使用发行版的配置作为起点。复制系统的当前内核配置文件通常位于 /boot/config-$(uname -r))到源码目录,并重命名为 .config。\n更新配置运行 make olddefconfig 自动更新配置,使之适应新版本内核。\n定制配置通过 make menuconfig 启动基于文本的配置界面,此处可以启用或禁用特定的内核功能。这一步需要基于你的具体需求来进行选择。\n\n\n\n编译内核\n\n\n编译命令在源码目录下执行 make -j$(nproc) 来编译内核。这里的 -j$(nproc) 参数让编译过程并行进行,加快编译速度。\nmake -j$(nproc) 2>&1 | tee log\n\n\n标签添加如果需要可以在编译时通过 LOCALVERSION 选项添加自定义标签,以区分这个内核版本。\n./scripts/config --file .config --set-str LOCALVERSION "-7wate"\n\n\n安装内核\n\n\n安装模块编译完成后使用 sudo make modules_install 命令安装内核模块。\nsudo make modules_install -j$(nproc)\n\n\n安装内核执行 sudo make install 命令,这将自动将内核安装到 /boot 目录,并更新引导加载器,比如 GRUB。\nsudo make install\n\n\n更新引导加载器\n\nGRUB 更新:大多数 Linux 发行版会在执行 sudo make install 时自动更新 GRUB 配置。如果没有,你可能需要手动运行 sudo update-grub 或相应的命令来更新启动菜单。\n\n重启并验证\n\n重启电脑完成安装后重启电脑。\n选择内核在引导菜单中选择新编译的内核启动。\n验证安装系统启动后使用 uname -r 命令验证当前运行的内核版本,确认是否与你安装的版本相匹配。\n\nLinux 内核模块管理\n内核模块概述\nLinux 内核模块LKM使得内核具备了极高的灵活性和可扩展性。模块允许在不重启系统的情况下添加或删除功能这对于需要动态管理硬件驱动和系统服务的情况非常有用。这些模块通常用于添加设备驱动、文件系统支持或其他内核级功能。内核模块的使用不仅减少了内核的静态大小还提高了系统的灵活性和模块的可重用性。\n模块的加载和卸载\nLinux 提供了 insmod、modprobe、rmmod 等工具来管理内核模块的加载和卸载。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述依赖处理insmod将模块插入内核不解决依赖问题modprobe加载模块并自动处理依赖自动处理依赖rmmod从内核中移除模块不解决依赖问题modprobe -r移除模块并解决依赖问题自动处理依赖\n模块参数管理\n操作系统的模块化设计不仅提高了系统的可扩展性和灵活性而且通过参数管理允许用户或管理员定制化模块的行为。在 Linux 系统中当加载内核模块kernel modules管理员可以通过命令行向模块传递参数这些参数能够影响模块的运行配置和提供的功能。\n例如网络设备驱动模块可能允许用户通过参数设置 IP 地址、子网掩码或是开启/关闭特定的功能等。通过这种方式,即使是相同的模块,在不同的参数配置下也能够提供不同的功能或表现出不同的性能。\n使用 modinfo 命令,用户可以查询特定模块可接受的参数及其说明。这个命令显示的信息对于理解如何正确配置模块至关重要。例如,运行 modinfo your_module_name 将展示该模块的所有可配置参数及简要描述,帮助用户做出合适的配置决策。\n模块依赖解决\n在复杂的系统中模块之间往往存在依赖关系。一个模块的正常运作可能依赖于一个或多个其他模块的功能。Linux 系统中的 depmod 命令会分析并生成所有模块之间的依赖关系列表。这个列表被存储在系统的特定目录下,供其他工具如 modprobe 使用。\nmodprobe 命令在加载一个模块时会自动查询这个依赖关系列表并且自动加载该模块所依赖的其他模块。这种自动解决依赖的机制极大地简化了模块管理的复杂度。例如如果一个网络协议栈模块依赖于特定的硬件驱动模块当管理员请求加载该网络协议栈模块时modprobe 会首先确保所有必要的硬件驱动模块也被加载。\n这一机制不仅保证了模块之间的兼容性和稳定性也让系统管理员能够更加方便地管理系统因为它减少了手动解决模块依赖所需的工作量。通过这种方式系统的维护者可以更加专注于系统的配置和优化而不是被复杂的依赖关系所困扰。\nLinux 内核调试技术\n内核调试工具介绍\nLinux 提供了一系列强大的内核调试工具,这些工具为开发者和系统管理员在诊断问题、分析性能瓶颈时提供了极大的便利。\n\nGDBGNU DebuggerGDB 是最广泛使用的调试工具之一它不仅可以用于用户空间程序的调试也可以用来调试内核本身及其模块。GDB 的强大之处在于它支持单步执行、断点设置、变量检查和内存状态分析等功能,极大地方便了内核开发和调试过程。\nKdump 和 Crash在遇到内核崩溃的情况下Kdump 和 Crash 的组合使用尤为重要。Kdump 利用 kexec 技术,在系统崩溃时迅速启动一个新内核并抓取崩溃时的内存转储,而 Crash 工具则用于分析这些转储文件,帮助开发者快速定位问题原因。\nperfperf 是 Linux 下的性能分析工具,它能够提供丰富的性能数据,包括 CPU 使用率、缓存命中情况、上下文切换次数等,对于性能优化具有重要意义。\nFtraceFtrace 是一个功能强大的内核跟踪工具,通过在内核中插入跟踪点来监视和记录函数调用过程和时序信息,对于理解内核行为和性能分析非常有用。\n\n内核调试方法\n根据不同的需求和调试环境开发者和系统管理员可以选择最合适的内核调试方法。\n\n日志分析通过分析内核日志例如 dmesg 命令的输出),可以获得系统错误、警告信息和其他关键诊断信息,这是最基本也是最直接的调试方法。\n动态调试工具如 perf 和 Ftrace 允许在系统运行时进行动态调试和性能分析,这对于定位运行时问题和性能瓶颈特别有效。\n静态分析在代码运行之前通过阅读源码和使用静态代码分析工具如 Sparse来检测潜在错误这可以在早期阶段发现并修复问题。\n\n常见内核调试问题\n在 Linux 内核调试过程中,可能会遇到各种复杂的问题,如死锁、内存泄漏和性能瓶颈等。\n\n对于内存泄漏问题可以使用 Valgrind 等工具进行分析和定位。\n针对死锁问题可以通过分析锁依赖图来识别死锁的根源。\n而对于性能瓶颈则可以通过 perf 等性能分析工具来定位问题,例如 CPU 使用率过高、I/O 延迟等。\n\n内核性能调优\n为了优化系统的整体性能内核性能调优是一个不可或缺的步骤。这包括但不限于调整内核参数、优化调度策略、调整文件系统和网络配置等。\n\n使用 sysctl 工具可以动态地调整内核参数,无需重启系统。\ntuned 工具提供了一套预定义的性能调优方案,适用于不同的使用场景。\n对于 NUMA非一致性内存访问系统numactl 工具可以帮助优化内存使用,提高系统性能。\n\nLinux 内核错误处理与日志分析\n内核错误类型\nLinux 内核在运行时可能会遭遇多种类型的错误,这些错误可能由不同的因素引起,具体包括:\n\n硬件错误这类错误通常由硬件故障引起如内存条损坏、硬盘故障或其他 I/O 设备问题。硬件错误往往需要通过更换损坏的硬件部件来解决。\n软件错误涵盖了程序逻辑错误、内存泄露、竞态条件等软件缺陷。这些错误通常需要通过分析日志、使用调试工具或静态代码分析来定位和修复。\n配置错误错误的系统配置或参数设置可能导致服务不可用或系统行为异常。解决这类问题通常需要检查和调整配置文件或系统设置。\n安全相关错误这类错误可能由安全漏洞引起或是系统遭受恶意攻击的结果。处理方法包括应用安全补丁、增强系统安全设置等。\n\n内核错误处理方法\n针对不同类型的内核错误可以采用以下方法进行处理\n\n系统日志分析系统日志文件是诊断问题的宝贵资源。分析日志文件如 /var/log/messages 和 /var/log/syslog可以帮助定位错误原因。\n使用内核崩溃转储工具kdump 等工具在系统崩溃时捕获内核的内存映像,这对后续的问题分析非常有用。\n利用调试器对于软件开发者来说GDB 等调试器是查找软件错误的有力工具,能够逐步跟踪程序执行过程,定位问题代码。\n更新和修补定期更新系统和应用程序及时应用安全补丁是预防软件缺陷和安全漏洞的有效方法。\n\nLinux 内核日志系统\nLinux 拥有一个全面的日志系统,能够记录系统的运行状况和各种事件,对于错误诊断和性能分析至关重要。\n\n主要的日志文件存放在 /var/log/ 目录下,如 /var/log/messages 用于记录系统消息,/var/log/syslog 记录广泛的系统信息。\ndmesg 命令显示内核环形缓冲区的消息,特别适用于分析启动问题和设备驱动错误。\n\n日志分析工具介绍\n有效的日志管理和分析对于快速定位和解决问题非常重要。以下工具可以帮助简化这一过程\n\nlogwatch它自动解析 /var/log/ 目录下的日志文件,并生成易于阅读的摘要报告,帮助快速识别常见问题。\nrsyslog这是一个高性能的日志处理系统支持日志的收集、过滤、解析和转发。它可以配置为处理大量日志数据非常适合大型系统环境。\njournalctl作为 systemd 的一部分journalctl 允许用户查询和显示 systemd 日志消息。它提供了灵活的查询选项,如按时间、服务或优先级过滤日志。\n\nLinux 内核更新与升级\nLinux 内核更新方式\nLinux 内核的更新可以通过多种方式进行,每种方式各有利弊,适用于不同的场景和需求。\n\n包管理器这是最常见且推荐的更新方式因为它简单易行且能够自动处理依赖关系和配置。不同的 Linux 发行版使用不同的包管理器,如 Debian 及其衍生版使用 aptRed Hat 及其衍生版使用 yum 或 dnf。\n手动编译安装对于需要特殊配置或想要使用最新内核的用户手动编译安装是一种可行的选择。这种方式允许用户自定义配置优化内核以适应特定的需求或硬件。然而这也要求用户具备一定的技术知识。\n发行版升级当新的 Linux 发行版发布时,它通常会包含更新的内核版本。通过升级到最新的发行版,用户不仅能够更新内核,还能享受到最新的系统功能和应用更新。\n\n内核更新的风险和注意事项\n更新 Linux 内核时,需要注意以下几个方面,以避免可能出现的问题:\n\n兼容性问题新版本的内核可能会引入与现有硬件或软件配置不兼容的变更因此在更新前应该仔细检查兼容性。\n配置更新新内核可能需要更新或调整配置文件特别是当添加新功能或废弃旧功能时。\n备份更新前应该备份重要数据和系统配置以便在更新失败或出现问题时能够快速恢复。\n\nLinux 内核版本迁移\n内核版本迁移是一个复杂但必要的过程尤其当新版本提供了重要的性能改进、安全补丁或新功能时。迁移过程需要细致的规划和执行以确保系统的平稳过渡。\n\n评估和计划首先需要评估新内核版本的特性、改进点及其对现有系统的潜在影响。这包括兼容性测试、性能预期以及新功能的适用性评估。基于这些信息制定详细的迁移计划包括回滚策略以应对可能的故障。\n测试在更新生产系统之前应在测试环境中进行充分的测试。这包括安装新内核、运行系统和应用程序的基准测试、验证硬件兼容性以及测试新功能。测试应尽可能覆盖所有使用场景确保新内核不会引入新的问题。\n实施在测试确保新内核稳定运行后可以开始在生产环境中实施升级。建议在系统负载较低的时段进行升级并确保有充分的时间监控系统运行状态以便及时发现并解决可能出现的问题。\n监控内核升级后需要密切监控系统的性能和稳定性包括但不限于系统日志、性能指标和用户反馈。任何异常都应立即分析和处理。此外也应该评估新内核带来的改进是否符合预期以及是否有必要进行进一步的优化。\n\n内核升级实例解析\n以下是一个假设场景展示了在一台运行老版本 Linux 内核的服务器上进行内核升级的过程:\n\n准备阶段确保已经对系统进行了全面备份包括重要数据和配置文件。检查新内核版本的发布说明了解新特性和已知问题评估这些变更对现有系统的影响。\n下载新内核可以通过官方网站下载最新的内核源代码或者通过系统的包管理器查找可用的内核更新包。\n安装新内核\n\n通过包管理器使用命令如 apt-get install linux-image-x.x.x安装新的内核包这通常是最简单且风险最低的方法。\n手动编译安装如果从源代码安装需要解压下载的内核源码然后使用 make menuconfig 配置内核选项,接着编译和安装内核。\n\n\n更新引导加载器安装完新内核后需要确保引导加载器如 GRUB已更新以包含新内核的启动项。这通常在安装过程中自动完成但有时可能需要手动配置。\n重启并测试重启服务器并在启动时选择新内核。系统启动后进行详尽的测试验证系统和应用的稳定性与性能。测试应包括常规操作和压力测试以确保新内核的可靠性。\n监控和调整在接下来的日子里继续监控系统日志和性能指标。根据需要调整系统配置优化性能。如果遇到任何问题根据事先制定的回滚计划进行处理必要时恢复到旧版本的内核。\n\n对于基于 Debian 的系统(如 Ubuntu\nDebian 及其衍生系统使用 APT 作为包管理器。你可以按照以下步骤来检索和安装指定的内核版本:\n\n\n更新包索引\nsudo apt update\n\n\n搜索可用的内核版本\napt search linux-image\n这将列出所有可用的 Linux 内核包。你可以通过更精确的关键词例如linux-image-5来缩小搜索范围。\n\n\n安装指定的内核版本 找到你想要安装的内核版本后,使用以下命令进行安装:\nsudo apt install linux-image-your-version-here\n请将 linux-image-your-version-here 替换为你选择的内核版本,例如 linux-image-5.4.0-42-generic。\n\n\n对于基于 RPM 的系统(如 Fedora、CentOS\nFedora、CentOS 及其衍生系统通常使用 yumCentOS 7 及之前版本)或 dnfFedora 和 CentOS 8 及之后版本)作为包管理器。\n\n\n更新包索引对于使用 dnf 的系统):\nsudo dnf check-update\n\n\n搜索可用的内核版本以 dnf 为例):\ndnf search kernel\n这将列出所有可用的内核包。类似地你可以使用更具体的搜索词来过滤结果。\n\n\n安装指定的内核版本 找到想要安装的内核版本后,使用以下命令进行安装(以 dnf 为例):\nsudo dnf install kernel-your-version-here\n将 kernel-your-version-here 替换为你的目标内核版本,例如 kernel-5.8.15-301.fc33。\n\n\n注意事项\n\n依赖性安装新内核时包管理器会自动处理所有必要的依赖性。\n引导加载器安装新内核后大多数 Linux 发行版会自动更新引导加载器(如 GRUB。重启系统后你可能需要在启动菜单中选择新安装的内核版本。\n备份在进行任何重要系统更改之前包括内核更新强烈建议备份重要数据和系统配置。\n\nLinux 内核安全管理\n内核漏洞概述\n内核漏洞通常是由于内核开发和维护过程中的错误或疏忽造成的。这些漏洞可能存在于内核的任何组件中包括网络堆栈、文件系统、设备驱动程序等。一旦被发现和利用它们就可能成为系统安全的致命弱点。\n内核安全补丁管理\n有效的安全补丁管理策略对于防御已知的内核漏洞至关重要\n\n订阅安全通知关注和订阅 Linux 内核和所使用发行版的安全通知服务,是及时了解和响应新发现漏洞的前提。\n定期更新内核利用包管理器定期更新内核以确保所有已知的安全漏洞都被及时修补。大多数 Linux 发行版都提供了方便的更新机制,自动化这一过程。\n自定义补丁在一些特殊场景下可能需要根据具体的需求和环境开发自定义的安全补丁。这通常需要较高的专业知识和充分的安全评估。\n\n内核安全加固方式\n加固 Linux 内核是通过一系列措施提高系统抵御未知攻击的能力。这些措施包括但不限于:\n\n配置安全模块启用并配置 SELinux、AppArmor 等安全模块以实现强制访问控制MAC限制应用程序和服务的权限从而减少潜在的攻击面。\n最小化内核通过移除不必要的内核模块和服务可以显著减少系统的攻击面。这要求管理员根据系统的实际用途进行精细化配置。\n使用命名空间和 cgroups利用 Linux 的命名空间和控制组cgroups功能可以有效隔离不同进程的资源和视图增强系统的安全隔离性。\n\n内核安全监控技术\n持续的安全监控是及时发现并应对安全威胁的关键\n\n审计日志配置 Linux 审计框架auditd监控关键文件、系统调用等敏感活动。审计日志是事后分析和取证的重要资料。\n实时监控工具如 Sysdig 和 Falco 能够提供实时的系统监控能力,检测异常行为和潜在的安全威胁。这些工具通过分析系统调用和网络活动来实现。\n漏洞扫描和评估定期使用漏洞扫描工具如 OpenVAS、Nessus 等,对系统进行安全评估。这有助于识别系统中仍未修补的漏洞,并促进及时的漏洞修复。\n\nLinux 内核性能优化\n性能优化概述\n性能优化的主要目标是减少系统的响应时间提高处理速度和吞吐量并确保资源被高效利用。这意味着需要在多个层面进行考虑和调整包括但不限于 CPU 利用率的优化、内存管理的改进、文件系统性能的提升以及网络传输效率的增加。\n内核性能分析工具\n要有效地进行性能优化首先需要准确地诊断和分析当前的性能状况。这里介绍的工具是这一过程中的关键\n\nperf提供了丰富的性能分析功能包括 CPU 使用情况、系统调用追踪等,是 Linux 性能分析的主力工具。\nvmstat、iostat、mpstat这些工具可以提供实时的系统性能数据帮助识别内存、I/O 和 CPU 性能瓶颈。\nsysctl通过动态调整内核参数管理员可以根据实际的性能分析结果对系统进行实时优化。\nhtop相比于传统的 top 工具htop 提供了更为直观的界面和更多的信息,帮助快速定位性能问题。\n\n内核性能调优方法\n根据性能分析的结果可以采取以下一些常见的调优方法来提升系统性能\n\n调整内核参数修改 /etc/sysctl.conf 文件中的参数,如网络堆栈的大小、文件系统的缓冲区大小等,以满足特定应用的需求。\n优化调度策略根据系统的负载特性选择合适的 CPU 调度策略,比如对于 I/O 密集型的应用,选择 Deadline 调度器可能更合适。\n内存管理优化通过优化内存分配策略和回收机制减少内存的碎片和泄漏提高内存使用效率。\n文件系统选择和调整根据应用特性选择最合适的文件系统并通过调整挂载选项来优化性能。\n\nLinux 内核性能优化实例\n假设我们要优化一个高负载的 Web 服务器,首先使用 perf 和 iostat 工具来分析 CPU 和 I/O 性能瓶颈。根据分析结果,发现 I/O 等待时间较长,可能是磁盘操作造成的性能瓶颈。\n为了解决这个问题我们可以\n\n使用 perf 和 iostat 分析性能:首先识别出性能瓶颈,比如 CPU 使用率过高或磁盘 I/O 等待时间过长。\n调整 I/O 调度器:如果发现磁盘 I/O 是性能瓶颈,可以考虑将 I/O 调度器从默认的 CFQ完全公平队列更改为 Deadline 或 Noop。这两种调度器可以减少请求的延迟特别适用于 SSD 或高性能存储系统。\n增加内存缓存对于频繁访问的数据增加内存缓存可以减少对物理磁盘的访问次数从而降低 I/O 等待时间。可以通过调整 vm.dirty_ratio 和 vm.dirty_background_ratio 这类 sysctl 参数来优化内存中的写缓存行为。\n优化数据库查询在高负载的 Web 服务器中,数据库查询往往是性能瓶颈之一。优化查询语句,减少不必要的数据访问,使用索引来加快查询速度,都是提升数据库性能的有效方法。\n采用 SSD如果预算允许使用 SSD 替换传统的机械硬盘是提高 I/O 性能的直接方法。SSD 提供了更低的读写延迟和更高的吞吐量,尤其对于 I/O 密集型的应用来说,性能提升显著。\n网络性能调优对于 Web 服务器而言,网络带宽和延迟同样关键。可以通过调整 TCP 堆栈的相关参数(如增大 TCP 窗口大小、启用 TCP 快速打开等)来优化网络传输效率。\n监控和迭代优化是一个持续的过程通过监控工具如 Nagios、Prometheus 等)持续跟踪系统的性能指标,根据实时数据进一步调整和优化。\n"},"Technology/OperatingSystem/Linux/4.系统管理/Linux-基本配置":{"title":"Linux 基本配置","links":[],"tags":["Linux/系统管理","技术/操作系统"],"content":"1. 网络配置\n网络配置是 Linux 系统管理中的一个基础且关键的环节,它确保系统能够正确地连接到网络并进行通信。以下是网络配置的一些基本步骤和建议实践:\n1.1 配置网络接口\n确保正确配置网络接口以便系统能够连接到互联网或内部网络。这通常涉及到设置静态 IP 地址或配置 DHCP 客户端。\n\n静态 IP 地址配置:编辑网络配置文件,如 /etc/network/interfaces对于基于 Debian 的系统)或 /etc/sysconfig/network-scripts/ifcfg-<interface>(对于基于 RedHat 的系统),来设置静态 IP 地址、子网掩码、默认网关和 DNS 服务器。\nDHCP 客户端设置:大多数现代 Linux 发行版使用 NetworkManager 或 NetworkConfig 工具来管理 DHCP。可以通过图形界面或相应的命令行工具来启用 DHCP 并配置网络接口。\n\n1.2 配置 DNS\nDNS 配置对于确保域名能够正确解析至关重要。以下是配置 DNS 的一些建议实践:\n\n使用 NetworkManager 管理 DNSNetworkManager 可以自动配置 DNS 设置,包括使用网络接口的 DHCP 配置或手动设置 DNS 服务器。\n手动配置 DNS如果需要手动配置 DNS可以编辑 /etc/resolv.conf 文件来添加 DNS 服务器。此外,/etc/hosts 文件也可以用来添加静态主机名到 IP 地址的映射,这对于本地网络中的名称解析非常有用。\n\n2. 主机配置\n主机配置涉及到设置系统的基本信息如主机名、语言和键盘布局、时区等。以下是主机配置的一些基本步骤和建议实践\n2.1 配置主机名称\n主机名称是系统在网络上的身份标识正确配置主机名称对于网络管理和故障排查非常重要。\n\n使用 hostnamectl 配置主机名hostnamectl 是一个强大的工具,可以用来查看和修改系统的主机名。使用 sudo hostnamectl set-hostname <新主机名> 命令可以直接设置新的主机名。\n手动编辑配置文件也可以直接编辑 /etc/hostname 文件来更改主机名,并更新 /etc/hosts 文件以确保内部名称解析的一致性。\n\n2.2 配置语言和键盘布局\n正确的语言和键盘布局设置可以提高用户工作效率并确保系统输出的一致性。\n\n使用 localectl 配置语言和键盘布局localectl 命令可以用来设置系统语言和键盘布局。例如,使用 sudo localectl set-locale LANG=en_US.UTF-8 设置系统语言为英语(美国),使用 sudo localectl set-keymap us 设置键盘布局为美国标准布局。\n手动编辑配置文件语言和键盘布局的配置通常存储在 /etc/locale.conf 和 /etc/vconsole.conf 文件中。可以直接编辑这些文件来设置系统语言和键盘布局。\n\n2.3 配置时区\n正确的时区设置对于系统日志、定时任务和用户活动的记录非常重要。\n\n使用 timedatectl 配置时区timedatectl 是一个用于管理日期和时间设置的工具。使用 sudo timedatectl set-timezone <时区> 命令可以设置系统时区,例如 sudo timedatectl set-timezone Asia/Shanghai 将时区设置为上海。\n手动链接时区文件时区信息可以通过链接 /etc/localtime 文件到 /usr/share/zoneinfo/ 目录下的相应时区文件来设置。timedatectl 命令会自动处理这个链接的更新。\n\n2.4 配置 NTP\n网络时间协议NTP用于同步系统时钟与互联网时间服务器确保系统时间的准确性。\n\n安装并启动 NTP 服务:安装 chronyd 或 ntpd 服务,并启动它们。对于 chronyd使用 sudo systemctl start chronyd 和 sudo systemctl enable chronyd 命令;对于 ntpd使用 sudo systemctl start ntpd 和 sudo systemctl enable ntpd 命令。\n配置 NTP 服务器:在 NTP 配置文件中指定要使用的 NTP 服务器。对于 chronyd编辑 /etc/chrony.conf 文件;对于 ntpd编辑 /etc/ntp.conf 文件。添加 server 指令来指定 NTP 服务器地址。\n\n2.5 配置时间同步\n确保系统时间自动与选定的 NTP 服务器保持同步,这通常通过 NTP 服务的配置来自动完成。\n\n检查和手动触发同步对于 chronyd使用 chronyc sources 命令查看时间源状态,使用 chronyc makestep 命令手动触发立即同步。对于 ntpd使用 ntpq -p 命令查看时间源状态。\n\n3. 更新系统\n为了确保系统的安全性和稳定性定期更新操作系统和应用程序是非常重要的。这不仅可以修复已知的安全漏洞还可以带来新功能和性能改进。\n\n软件源管理首先需要确保软件源repositories是最新和最可靠的\n\n对于基于 Debian 的系统,编辑 /etc/apt/sources.list 文件。\n对于基于 RedHat 的系统,编辑 /etc/yum.repos.d/ 目录下的文件。\n\n\n更新软件包列表使用包管理器更新本地软件包数据库。\n\n对于 APT可以使用 sudo apt-get update 命令;\n对于 YUM可以使用 sudo yum makecache 或者 sudo dnf makecache如果你的系统使用 DNF 作为包管理器)。\n\n\n更新升级系统在更新了软件包列表之后可以进行系统更新。\n\n对于 APT使用 sudo apt-get upgrade 命令;\n对于 YUM 或 DNF使用 sudo yum update 或 sudo dnf upgrade。这些命令会下载并安装所有可用的更新。\n\n\n\n4. 安装基本软件和工具\n\n安装文本编辑器选择适合的文本编辑器如 vim、nano以便于配置文件编辑。\n安装网络工具安装基础网络诊断工具如 curl、wget、net-tools、traceroute。\n\n5. 安全设置\n安全性是系统管理中的一个关键方面。以下是一些基本的安全设置步骤。\n\n设置防火墙ufw 和 firewalld 是两个流行的防火墙管理工具。它们可以轻松配置入站和出站规则,限制未授权访问。例如,使用 sudo ufw allow 22 来允许 SSH 连接。\n安装和配置安全增强工具SELinux 和 AppArmor 提供了强制访问控制,可以增强系统安全。安装后,需要根据需要配置相应的策略。\n定期扫描漏洞使用安全扫描工具定期检查系统漏洞。ClamAV 是一个开源的杀毒工具可以扫描恶意软件。Lynis 是一个安全审计工具,可以帮助检查系统配置和潜在的安全风险。\n\n6. OpenSSH 通讯\nOpenSSH 是 Linux 系统中用于远程管理的标准工具。以下是一些重要的 SSH 配置和安全措施。\n\n配置 SSH安装 OpenSSH 服务后,编辑 /etc/ssh/sshd_config 文件进行配置。可以更改默认端口,配置密钥认证,禁用 root 登录等。\n定期更新密码定期更新用户和 root 账户的密码,遵循强密码策略,以增加账户安全性。\n配置 SSH 密钥认证:密钥认证比密码认证更安全。生成密钥对,并将其添加到服务器的 ~/.ssh/authorized_keys 文件中。\n禁用 SSH 空密码登录:确保 SSH 配置文件中的 PermitEmptyPasswords 选项设置为 no以防止空密码账户通过 SSH 登录。\n\n7. 用户账户角色管理\n用户账户管理是系统安全的关键部分。合理的用户和权限管理可以防止未授权的访问和潜在的安全风险。\n\n添加用户使用 sudo adduser 或 sudo useradd 命令创建新用户。为每个任务创建专用的用户账户,避免使用 root 账户进行日常工作。\n用户组管理合理地使用用户组来分配权限和管理用户权限。使用 sudo groupadd 创建新组,使用 sudo usermod -aG 将用户添加到组中。\nroot 用户管理:限制 root 账户的远程访问,只通过 sudo 提升权限。确保 root 账户有一个强密码,并定期更新。\n用户权限管理通过配置 /etc/sudoers 文件或使用 visudo 命令,为特定用户分配 sudo 权限。确保遵循最小权限原则,只授予必要的权限。\n重置 root 密码:如果忘记 root 密码,可以使用系统救援模式或 Live CD/USB 来重置密码。这通常涉及到挂载系统分区并修改 /etc/shadow 文件。\n\n8. 配置服务和程序\n服务和程序的配置对于系统的稳定运行和性能至关重要。\n\n管理 systemd 系统服务:使用 systemctl 命令管理服务。了解不同 systemd 单元文件的存放位置和优先级,以便正确管理服务。\n服务自启动管理使用 systemctl enable 或 disable 命令来管理服务是否在系统启动时自动运行。这有助于控制系统启动时的资源消耗。\n不必要服务的移除定期审查系统服务卸载或禁用不必要的服务和程序以减少系统的潜在攻击面和提高系统性能。\n引导至救援模式了解如何使用系统引导菜单或添加启动参数进入救援模式。这对于系统修复和故障排除非常有用。\n\n9. 日志管理和监控\n日志管理和监控对于维护系统安全和稳定运行至关重要。\n\n配置系统日志使用 rsyslog 或 syslog-ng 配置日志记录规则。确保重要信息,如安全警告和系统错误,被妥善记录。\n安装监控工具安装 htop 和 iftop 等工具来监控系统资源使用情况。还可以考虑安装 nmon、glances 等综合系统监控工具,以获得更全面的系统状态视图。\n日志分析工具安装日志分析工具如 Logwatch 或 GoAccess这些工具可以帮助更容易地分析和理解日志文件及时发现潜在的安全威胁或系统问题。\n\n10. 备份和恢复计划\n备份和恢复计划是防止数据丢失和系统故障的关键。\n\n配置定期备份使用 rsync、tar 或定制脚本实现重要数据和配置的定期备份。考虑使用定时任务cron jobs来自动执行备份。\n远程备份使用远程备份解决方案如 rsync 配合 SSH 将备份数据同步到远程服务器,提高数据安全性。\n灾难恢复计划制定并测试灾难恢复计划确保在数据丢失或系统崩溃时能够迅速恢复。这可能包括系统镜像备份、关键数据的恢复流程等。\n\n11. 自定义用户环境\n为了提高用户的工作效率和满意度可以对用户环境进行一些自定义设置。\n\n磁盘配额使用 quota 工具为用户和用户组设置磁盘配额,防止单个用户占用过多磁盘空间。\n使用 ulimit 设置资源限制:使用 ulimit 命令为用户和进程设置资源使用限制,如打开文件的数量,以避免单个进程耗尽系统资源。\nShell 环境定制:根据个人偏好定制 Shell 环境,配置别名、环境变量和命令提示符。这可以通过编辑用户的 .bashrc、.bash_profile 或 .zshrc 文件来实现。\n安装和配置图形界面可选如果系统需要图形界面安装桌面环境如 GNOME、KDE并进行相应配置。确保图形界面的安全性例如通过配置 .xinitrc 文件来启动图形会话。\n\n12. 系统性能优化\n系统性能优化可以提高系统响应速度和处理能力特别是在资源受限的环境中。\n\n内核参数调整根据系统用途调整 /etc/sysctl.conf 中的内核参数。例如,可以增加 net.core.somaxconn 来提高网络性能,或者调整 fs.file-max 来增加文件系统的最大句柄数。\n\n13. 故障转移\n故障转移和灾难恢复策略对于确保业务连续性至关重要。\n\n故障转移和灾难恢复策略制定并实施故障转移和灾难恢复策略。这可能包括设置冗余服务器、配置数据同步、以及制定在发生故障时切换到备份系统的流程。\n\n14. 文档和记录\n良好的文档和记录习惯对于系统管理和故障排除非常重要。\n\n系统配置文档化详细记录系统配置和定制过程。这包括网络配置、安全设置、服务管理等以便于故障排除和系统迁移。\n变更管理记录所有系统变更包括软件安装、配置修改等。这有助于追踪可能的问题来源并在必要时回滚更改。\n"},"Technology/OperatingSystem/Linux/4.系统管理/Linux-日志管理":{"title":"Linux 日志管理","links":[],"tags":["Linux/系统管理","技术/操作系统"],"content":"引言\n在复杂的信息技术世界中Linux 系统因其高效、稳定、开源的特性而广泛应用于服务器、云计算以及各类嵌入式系统中。有效的系统管理不仅要求对 Linux 系统有深入的理解,还需要掌握各种工具和技术以保证系统的可靠运行和高效故障排查。特别是日志管理,作为系统管理的核心部分,对于监控系统健康状况、分析系统问题具有不可或缺的作用。\nLinux 日志系统\nLinux 日志文件是记录系统运行状态、软件错误信息、用户操作以及各种系统事件的文件。它们对于系统安全审计、故障诊断和性能分析等任务至关重要。\n常见日志文件\nLinux 系统中的日志文件通常存储在 /var/log 目录下。这个目录中有许多文件和子目录,用于记录各种不同类型的日志。以下是其中一些重要的日志文件:\n\n/var/log/syslog 或 /var/log/messages这两个文件通常包含系统和应用程序的所有非安全日志消息。哪个文件被使用取决于你的发行版和配置。\n/var/log/auth.log 或 /var/log/secure这些文件记录所有的安全授权信息包括用户认证、sudo 操作等。\n/var/log/kern.log该文件记录所有的内核相关消息。\n/var/log/dmesg保存由 dmesg 命令显示的内核环形缓冲区的消息。\n/var/log/boot.log记录系统启动过程中的信息。\n/var/log/faillog这个文件记录所有的登录失败尝试。它可以帮助管理员跟踪并阻止潜在的非法活动。\n/var/log/maillog 或 /var/log/mail.log这两个文件记录与电子邮件系统相关的所有日志信息。包括邮件传送、接收以及任何可能发生的错误。\n/var/log/journal/:此目录包含了 systemd 日志服务journald的二进制日志文件。它们包含了系统启动以来的所有日志消息。\n/var/log/lastlog此文件记录了系统上每个账户的最后登录时间。管理员可以使用这个日志来跟踪用户活动。\n/var/log/wtmp 和 /var/log/btmp这两个文件分别记录了成功和失败的登录尝试。通过检查这些文件管理员可以发现潜在的安全问题。\n/var/log/Xorg.0.log此文件记录了 X Window 系统的日志,主要用于调试 X 服务器的问题。\n\n理解这些日志文件的内容和它们所在的位置对于日常的系统维护、问题诊断和安全审计都非常重要。在实际使用中还需要结合具体的发行版和配置以及具体的应用程序和服务的需求来进行灵活的操作和管理。\n日志管理工具\njournalctl 日志管理\nSystemd 是一个系统和服务管理器它提供了对服务的并行启动、日志记录和系统初始化的能力。Systemd 使用 journald一个日志收集守护进程来收集和管理日志信息。与传统的基于文本文件的日志系统如通过 syslog 或直接写入 /var/log 的方式相比journald 提供了一些优势:\n\n集中管理journald 收集系统启动、应用程序和内核的日志信息,提供了一个统一的日志入口。\n性能和可靠性journald 可以在系统崩溃后保留日志信息,提高了日志的可靠性。同时,它还支持日志的按需加载,改善了大量日志处理的性能问题。\n高级查询通过 journalctl 工具,用户可以执行基于时间、服务、优先级等多维度的复杂日志查询,这在传统文本文件日志系统中难以实现。\n\n日志文件的变化\n由于 journald 的引入,很多原本分散在 /var/log 中的日志文件,如 auth.log用于记录认证日志、daemon.log用于记录系统守护进程的日志现在可以通过 journalctl 命令统一查询。例如,原先查看 auth.log 的命令可能被替换为 journalctl -u ssh.service查看 SSH 服务的日志)或者 journalctl _SYSTEMD_UNIT=sshd.service同样的查询但是使用不同的过滤方式。\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能描述命令示例查看所有日志journalctl反向查看日志最新的先显示journalctl -r查看特定服务的日志journalctl -u 服务名.service按时间查看日志journalctl --since "YYYY-MM-DD HH:MM:SS"journalctl --until "YYYY-MM-DD HH:MM:SS"实时跟踪日志输出journalctl -f查看此次启动的日志journalctl -b查看上一次启动的日志journalctl -b -1根据优先级过滤日志journalctl -p err (err, crit, warn, info 等)显示日志的尾部 N 条记录journalctl -n 数量过滤特定时间段的日志journalctl --since "昨天" --until "今天"过滤特定进程的日志journalctl _PID=进程号查看特定用户的日志journalctl _UID=用户ID合并多个日志文件显示journalctl -m查看内核消息journalctl -k过滤特定系统单元及其优先级的日志journalctl -u 服务名.service -p err显示日志的详细输出journalctl -o verbose使用导出格式查看日志journalctl -o json指定日志标识符SYSLOG_IDENTIFIER过滤journalctl SYSLOG_IDENTIFIER=标识符\nLogwatch 日志分析工具\nLogwatch 是一个高度可定制和灵活的日志分析工具,广泛用于 Linux 和 Unix 系统。它自动分析和报告系统日志文件中的重要信息使系统管理员能够轻松识别常见问题和潜在安全威胁。Logwatch 能够处理各种服务的日志,如 Apache、SSH、FTP 以及系统安全日志等。\n主要特性\n\n自动化日志分析自动分析系统中的各种日志文件并生成易于理解的摘要报告。\n高度可定制用户可以定制报告的内容、格式、详细程度以及报告周期以满足不同的监控需求。\n邮件报告可以将日志分析报告通过电子邮件发送给系统管理员便于及时审查。\n支持多种服务和应用Logwatch 具有广泛的服务和应用支持,包括但不限于系统安全、网络服务和邮件系统等。\n\n配置选项\nLogwatch 的配置文件位于 /usr/share/logwatch/default.conf/logwatch.conf也可以拷贝至 /etc/logwatch/conf 目录下,编写个人化配置文件。以下是一些可复用的 Logwatch 配置模板,你可以根据需求进行调整,并保存在 /etc/logwatch/conf/ 目录下,以 .conf 结尾。例如custom.conf。\n# 设置详细等级\nDetail = Low # 可选值Low, Med, High\n# 设置输出方式\nOutput = stdout # 可选值stdout, mail\n# 设置报告范围\nRange = yesterday\n# 指定接收报告的邮件地址\nMailTo = admin@example.com\n# 指定发件人邮件地址\nMailFrom = logwatch@example.com\n\n常见的命令选项包括\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--detail设置报告的详细级别Low, Med, High 或具体数字)。--output指定输出类型stdout, mail, file。--format指定报告格式html, text--mailto当输出类型为 mail 时,指定接收报告的电子邮件地址。--mailfrom指定发送报告的电子邮件地址仅当 --output mail 时有效)。--range指定报告的时间范围today, yesterday, All, 或自定义范围如 between -7 days and today。--service指定要包含在报告中的服务。多个服务可以通过重复此选项来指定。--logfile指定要分析的特定日志文件。多个日志文件可以通过重复此选项来指定。--hostname指定在报告中使用的主机名。--config指定一个自定义的配置文件路径如前所述这个选项实际上并不存在配置应通过修改或添加 /etc/logwatch/conf/ 目录下的文件来实现)。--numeric显示数字 IP 地址而不是主机名(对于某些服务日志)。--archives在分析日志时包括旧的日志档案。--debug打印调试信息有助于故障排除。\nLogwatch 日志命令\nlogrotate 日志轮转\n日志文件可以在短时间内变得非常大尤其是当系统或应用程序产生大量日志信息时。一个大的日志文件不仅会占用大量的磁盘空间也会使日志分析变得复杂和耗时。这就是为什么日志旋转变得非常重要。\n日志旋转是一种解决方法它会定期将旧的日志条目移动到新的文件中同时管理和删除过旧的日志文件。在 Linux 系统中,这通常由 logrotate 实现。\nlogrotate 是一个用于管理日志文件的工具,它可以自动轮转、压缩、删除和邮件发送日志文件。在 Linux 系统中许多程序都会生成日志文件这些文件会随着时间的推移不断增长logrotate 可以帮助系统管理员管理这些日志文件,防止它们占用过多的磁盘空间。\nlogrotate 的主要特性和功能:\n\n\n日志轮转logrotate 可以按照日、周、月或者文件大小来轮转日志文件。这意味着当一个新的轮转周期开始时,当前的日志文件将被重命名,然后创建一个新的日志文件。例如,你可以配置 logrotate 每天轮转一次 /var/log/messages 文件,那么每天开始时,/var/log/messages 文件会被重命名为 /var/log/messages.1,然后创建一个新的 /var/log/messages 文件用于记录新的日志。\n\n\n日志压缩logrotate 可以自动压缩旧的日志文件以节省磁盘空间。默认情况下,它使用 gzip 进行压缩,但也可以配置使用其他压缩工具。\n\n\n删除旧的日志文件你可以配置 logrotate 自动删除超过一定时间的旧日志文件。例如,你可以配置 logrotate 只保留最近 30 天的日志文件。\n\n\n邮件发送日志文件如果你希望保存被删除的日志文件可以配置 logrotate 在删除之前将日志文件发送到一个指定的电子邮件地址。\n\n\nlogrotate 的配置文件通常位于 /etc/logrotate.conf 和 /etc/logrotate.d/ 目录下。/etc/logrotate.conf 是主配置文件,定义了全局的配置选项。/etc/logrotate.d/ 目录下的文件通常是各个程序的配置文件,例如 Apache、rsyslog、nginx 等。\n下面是一个 logrotate 配置文件的示例myapp 的日志文件每天轮替,保留 5 份旧的日志文件。如果日志文件丢失或者为空,那么会忽略这个错误。轮替的日志文件会被压缩。新的日志文件将会以 0644 的权限创建,所有者为 root组为 adm。每次日志轮替后会重新加载 myapp 的配置。\n/var/log/myapp/*.log {\n daily\n rotate 5\n missingok\n notifempty\n compress\n create 0644 root adm\n sharedscripts\n postrotate\n /etc/init.d/myapp reload > /dev/null\n endscript\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述示例rotate指定你希望保存的旧日志文件的数量。rotate 5daily/weekly/monthly/yearly定义了日志轮转的频率。dailycompress让 logrotate 使用 gzip 压缩旧的日志文件。compressdelaycompress让 logrotate 延迟压缩直到下一次轮转周期。delaycompressmissingok如果日志文件丢失logrotate 会忽略错误。missingoknotifempty如果日志文件为空logrotate 会忽略它。notifemptycreate mode owner group让 logrotate 创建新的日志文件并设置指定的权限、所有者和组。create 0644 root admpostrotate/endscript在 postrotate 和 endscript 之间的命令会在每次日志轮转之后执行。postrotate /etc/init.d/apache2 reload endscriptsharedscripts会使得 logrotate 对每个日志只运行一次 postrotate 脚本。sharedscripts\n日志分析技巧\nGrep 文本搜索工具\ngrep 是 Unix 和类 Unix 系统中的一个强大的文本搜索工具,用于搜索匹配特定模式的行。在日志文件中,你可以使用 grep 来搜索出包含特定关键字的日志条目。\n常见的 grep 命令示例:\nshellCopy code# 在文件中搜索特定文本\ngrep 'text' /path/to/file\n \n# 在文件中搜索,忽略大小写\ngrep -i 'text' /path/to/file\n \n# 递归搜索目录中的所有文件\ngrep -r 'text' /path/to/dir\n \n# 显示匹配文本的行数\ngrep -c 'text' /path/to/file\n \n# 显示匹配和不匹配的行\ngrep -v 'text' /path/to/file\nAwk 文本分析工具\nawk 是一个功能强大的文本分析工具,主要用于生成报告和处理数据文件。它拥有强大的编程语言特性,可以处理复杂的任务。\n常见的 awk 命令示例:\nshellCopy code# 打印文件的第一列\nawk '{print $1}' /path/to/file\n \n# 计算文件的第一列的和\nawk '{sum += $1} END {print sum}' /path/to/file\n \n# 在文件中查找特定的文本\nawk '/text/ {print $0}' /path/to/file\n \n# 打印文件中的行数\nawk 'END {print NR}' /path/to/file\nSed 文本处理工具\nsed流编辑器是 Unix 和类 Unix 系统中的一个非常强大的文本处理工具。主要用于文本替换,删除,插入和其他文本转换任务。\n常见的 sed 命令示例:\nshellCopy code# 在文件中替换文本\nsed 's/text/newtext/g' /path/to/file\n \n# 在文件中删除行\nsed '5d' /path/to/file # 删除第 5 行\nsed '/text/d' /path/to/file # 删除包含 "text" 的行\n \n# 插入文本\nsed '5i\\text' /path/to/file # 在第 5 行之前插入 "text"\nsed '5a\\text' /path/to/file # 在第 5 行之后插入 "text"\nHead 查看文件头部内容\nhead 命令在 Unix-like 系统中用于输出文件的头部内容。它主要用于快速查看文件的开始部分,对于检查日志文件、文本文件等的开头信息非常有用。\n常用的 head 命令示例:\n# 默认查看文件的前 10 行\nhead /path/to/file\n \n# 查看文件的前 20 行\nhead -n 20 /path/to/file\nTail 查看文件尾部内容\ntail 命令在 Unix-like 系统中用于输出文件的尾部内容。它主要用于实时查看和监控日志文件的变化。\n常用的 tail 命令示例:\n# 默认查看文件的最后 10 行\ntail /path/to/log\n \n# 查看文件的最后 20 行\ntail -n 20 /path/to/log\n \n# 实时查看文件的变化\ntail -f /path/to/log\nLess 查看文件内容\nless 是一个在 Unix-like 系统中用于查看文件内容的命令。相比于其他查看器,如 moreless 提供了更多的功能和灵活性。\nLess 命令的一个重要特性是它允许用户向前和向后滚动查看文件。在 less 中,你可以使用 Page Up 和 Page Down 键来滚动查看文件,使用 / 来搜索文本,使用 n 和 N 来查找下一个和上一个匹配的文本。\n在 less 中,你可以使用 Shift + F 来实时查看文件的变化,按 Ctrl + C 停止实时查看。\n以下是一些常用的 less 命令示例:\n# 查看文件\nless /path/to/log\n \n# 在文件中搜索文本\nless /path/to/log\n/keyword\n \n# 实时查看文件的变化\nless +F /path/to/log\n高级日志处理\n日志处理是 Linux 系统管理的重要部分,用于监控系统行为,诊断问题,以及安全审计。高级日志处理涉及到日志服务器的配置使用,以及日志分析框架的应用。\n日志服务器\nrsyslog 和 syslog-ng 是两种广泛使用的日志服务器,这两种服务器都可以接收、处理和转发日志信息。\nRsyslog\nrsyslog 是一个多线程的日志处理系统提供了高性能、安全性、模块化和可配置性。rsyslog 的配置文件通常位于 /etc/rsyslog.conf你可以在这个文件中定义日志的收集方式、存储位置以及转发规则等。\n例如如果你想配置 rsyslog 来接收远程日志,你需要在 /etc/rsyslog.conf 文件中添加以下行:\nmodule(load="imudp")\ninput(type="imudp" port="514")\n\n这将配置 rsyslog 来监听 UDP 端口 514并接收该端口上的日志消息。\nSyslog-ng\nsyslog-ng 是另一个强大的日志管理解决方案它提供了更多的灵活性和功能包括内容过滤、丰富的日志转换能力以及对各种日志格式的支持。syslog-ng 的配置文件通常位于 /etc/syslog-ng/syslog-ng.conf。\n例如你可以在 syslog-ng 的配置文件中添加以下行,以接收远程日志:\nsource s_net { udp(ip(0.0.0.0) port(514)); };\nlog { source(s_net); destination(d_local); };\n\n这将配置 syslog-ng 来监听 UDP 端口 514并将接收到的日志消息转发到本地的日志目的地 d_local。\n集中日志管理的实践\n集中日志管理是指通过网络将所有服务器的日志集中到一个地方进行存储和分析。这样可以提高日志分析的效率也可以提高数据安全性因为日志信息不再分散在各个服务器上。\n在 rsyslog 或 syslog-ng 中,你可以配置日志转发规则,将日志信息发送到日志服务器上。例如,在 rsyslog 中,你可以在 /etc/rsyslog.conf 文件中添加以下行,以将所有日志消息转发到远程服务器:\n*.* @remote-host:514\n\n在这个例子中*.* 表示所有的设施和优先级,@ 表示使用 UDP 协议remote-host 是远程服务器的主机名或 IP 地址514 是远程服务器上 rsyslog 服务的端口号。\n在日志服务器上你需要配置相应的服务以接收和存储这些日志信息。此外你还需要配置日志轮转以防止日志文件占用过多的磁盘空间。你可以使用 logrotate 工具来配置日志轮转,例如,你可以在 /etc/logrotate.conf 文件中添加以下配置:\n/var/log/syslog\n{\n rotate 7\n daily\n compress\n postrotate\n /usr/bin/killall -HUP syslogd\n endscript\n}\n\n这个配置将每天轮转 /var/log/syslog 文件,保留 7 天的日志,将旧的日志文件压缩,轮转后发送 HUP 信号给 syslogd 进程,让它重新打开日志文件。\n日志分析框架\n日志分析框架是用于处理和分析大量日志数据的工具其中最常用的是 ELK 栈。\nELK 栈Elasticsearch, Logstash, Kibana的安装和配置\nELK 栈是 Elasticsearch、Logstash 和 Kibana 的组合,它们一起提供了一个强大的日志分析框架。\n\nElasticsearch 是一个基于 Lucene 的搜索和分析引擎,用于存储、搜索和分析大量的日志数据。\nLogstash 是一个强大的日志收集、处理和转发工具,它可以将日志数据从各种来源收集过来,然后进行处理,并将其发送到 Elasticsearch 或其他存储系统中。\nKibana 是一个用于可视化 Elasticsearch 数据的 Web 界面,你可以通过 Kibana 创建各种图表和仪表板,以直观地展示和分析日志数据。\n\n安装和配置 ELK 栈需要多个步骤,包括安装 Java 环境,下载和安装 Elasticsearch、Logstash 和 Kibana以及配置它们的通信和安全性等。\n使用案例和最佳实践\n使用 ELK 栈进行日志分析的案例有很多,例如,你可以使用它来分析 Web 服务器的访问日志,从而了解网站的访问量、访问者的地理位置、访问的高峰时段等信息。\n或者你也可以使用 ELK 栈来分析系统日志,以监控系统的运行状态,识别和预防可能的问题。\n在使用 ELK 栈时,有一些最佳实践可以参考,例如:\n\n使用 Logstash 的过滤插件来清洗和转换日志数据,以提高 Elasticsearch 的搜索和分析效率。\n使用 Kibana 的仪表板功能来创建实时的系统监控界面。\n为 Elasticsearch 配置适当的索引策略,以提高搜索效率并降低存储成本。\n定期备份 Elasticsearch 的数据,以防止数据丢失。\n\n故障排除实践\n日志排错流程和方法\n故障排除的第一步是查看相关日志因为日志通常包含有关故障的关键信息。以下是一般的日志排错流程和方法\n\n\n确定故障现象首先要明确故障的具体表现和现象例如服务无法启动、网络连接失败等。\n\n\n查看系统日志检查系统的核心日志文件如 /var/log/syslog、/var/log/messages以及应用程序的日志文件。查找与故障相关的错误消息、警告或异常。\n\n\n分析日志内容仔细阅读日志文件查找关键字、错误代码或异常信息。注意日志文件中的时间戳以确定故障发生的时间点。\n\n\n比对正常日志如果可能的话对比故障发生之前的正常日志和故障发生时的异常日志以找出变化和异常之处。\n\n\n查找解决方案根据日志中的错误消息或异常信息使用搜索引擎、官方文档或社区论坛等资源查找可能的解决方案。\n\n\n尝试修复故障根据找到的解决方案尝试修复故障。在进行任何更改之前确保备份相关文件和配置。\n\n\n验证修复效果修复故障后验证系统是否恢复正常。检查相关服务的状态、功能和性能。\n\n\n记录故障和解决方案将故障和解决方案记录下来以便将来参考。这对于建立故障知识库和提高故障排除效率非常有帮助。\n\n\n常见故障案例\n服务启动失败\n故障现象某个服务无法启动无法提供正常的功能和服务。\n排除方法\n\n检查服务的日志文件查找与启动失败相关的错误消息或异常信息。\n确保服务的依赖项已安装并正确配置。\n检查服务的配置文件确保没有语法错误或配置问题。\n检查服务的权限设置确保对必要的文件和目录具有适当的权限。\n尝试手动启动服务并观察是否有错误消息或异常输出。\n\n解决方案\n\n根据日志文件中的错误消息或异常信息查找解决方案。\n检查系统和服务的文档、社区论坛或官方支持渠道寻求帮助和建议。\n如果问题仍然存在尝试重新安装服务或使用备份恢复系统。\n\n网络问题\n故障现象服务器无法与其他设备或互联网建立连接网络服务不可用。\n排除方法\n\n检查网络接口的状态和配置确保网络接口已启用并正确配置。\n使用 ping 命令检查与其他设备的连通性。\n检查网络设备如路由器、交换机的状态和配置确保网络设备正常工作。\n检查防火墙规则和安全组配置确保允许必要的网络流量通过。\n\n解决方案\n\n根据网络设备的日志和错误消息查找解决方案。\n检查网络设备的文档、社区论坛或官方支持渠道寻求帮助和建议。\n如果问题仍然存在尝试重新配置网络设备或与网络管理员协商解决。\n\n安全和权限问题\n故障现象访问被拒绝无法执行某些操作权限不足等安全或权限相关的问题。\n排除方法\n\n检查访问被拒绝的错误消息和日志查找与权限相关的信息。\n确保使用正确的身份验证凭据进行访问检查用户名和密码是否正确。\n检查文件和目录的权限设置确保有足够的权限执行所需的操作。\n检查安全策略和访问控制列表ACL确保允许所需的访问权限。\n\n解决方案\n\n根据错误消息和日志中的信息查找解决方案。\n检查系统和应用程序的文档、安全指南或官方支持渠道寻求帮助和建议。\n如果问题涉及到安全漏洞及时更新系统、应用程序或补丁以修复漏洞。\n\n安全和审计日志\n安全和审计日志对于保护系统安全和识别潜在的安全威胁非常重要。\n安全日志监控是指对系统和应用程序的安全事件进行实时监控和记录以便及时发现和应对潜在的安全威胁。以下是安全日志监控的重要性\n\n\n威胁检测和响应通过监控安全日志可以及时检测到潜在的安全威胁例如入侵尝试、异常登录、恶意代码等。及早发现威胁并采取相应的响应措施可以减少损失和风险。\n\n\n事件调查和取证安全日志记录了系统和应用程序的关键事件可以用于后续的事件调查和取证。当发生安全事件时可以通过分析安全日志来了解事件的起因、影响和相关的活动。\n\n\n合规性和法规要求许多行业和组织需要遵守特定的合规性和法规要求其中包括对安全日志的监控和记录。通过对安全日志进行监控可以满足合规性要求并提供给审核人员进行审计。\n\n\n使用 auditd 进行系统审计\nauditd 是 Linux 系统中的一个审计框架,可以用于记录系统和应用程序的安全事件。它提供了强大的审计功能,可以配置和记录各种事件,如文件访问、用户登录、进程创建等。\n审计日志的配置和分析\n要使用 auditd 进行系统审计,需要进行以下配置和分析步骤:\n\n\n安装和启动 auditd首先需要安装 auditd 软件包,并启动 auditd 服务。具体的安装和启动方法取决于所使用的 Linux 发行版。\n\n\n配置审计规则通过编辑 auditd 的配置文件,可以定义需要审计的事件和规则。配置文件通常位于 /etc/audit/auditd.conf 或 /etc/audit/rules.d/ 目录下。\n\n\n启用审计规则使用 auditctl 命令加载和启用审计规则。例如,可以使用以下命令启用一个规则来监控文件的访问:\nauditctl -w /path/to/file -p rwxa\n\n这将监控指定文件的读取、写入、执行和属性更改。\n\n\n审计日志的分析审计日志通常存储在 /var/log/audit/audit.log 文件中。可以使用工具如 ausearch 和 aureport 来分析和查询审计日志。下面将详细介绍这两个工具。\n\n\nausearch 和 aureport 工具的使用\nausearch 和 aureport 是 auditd 提供的两个用于审计日志分析的工具。\n\n\nausearchausearch 工具用于在审计日志中进行高级搜索和过滤。它可以根据时间、进程、文件、用户等条件来查询特定的审计事件。以下是一些常用的 ausearch 命令示例:\n\n\n搜索特定时间范围内的事件\nausearch -ts <start_time> -te <end_time>\n\n\n\n搜索特定用户的事件\nausearch -m USER_LOGIN -k <username>\n\n\n\n搜索特定文件的事件\nausearch -f /path/to/file\n\n\n\n\n\naureportaureport 工具用于生成审计日志的报告和摘要信息。它可以提供关于审计事件的统计数据、趋势分析和可视化图表。以下是一些常用的 aureport 命令示例:\n\n\n生成文件访问统计报告\naureport -f\n\n\n\n生成用户登录统计报告\naureport -l\n\n\n\n生成系统调用统计报告\naureport -s\n\n\n\n\n\n通过使用 ausearch 和 aureport 工具,可以对审计日志进行深入的分析和查询,以便了解系统中发生的安全事件和活动。"},"Technology/OperatingSystem/Linux/4.系统管理/Linux-服务管理":{"title":"Linux 服务管理","links":[],"tags":["Linux/系统管理","技术/操作系统"],"content":"Linux 服务概述\n在现代 Linux 发行版中,系统和服务管理器是核心组件之一,负责初始化系统、管理系统进程和服务。这些管理器确保系统服务按正确的顺序启动、监控它们的运行状态,并在服务出现故障时进行恢复。传统上,这一角色由 SysV init 系统承担,但在过去几年中,更多现代化的解决方案如 systemd 和 Upstart 开始主导。\nSystemd 的设计目标和特点\nsystemd 是为了克服旧式 init 系统的缺陷而设计的其主要设计目标包括提高系统启动速度和处理复杂的依赖关系。systemd 使用 socket 和 D-Bus 进行服务间通信支持按需启动守护进程具有更强的并发能力。此外systemd 提供了诸如日志系统 journal 的集成,这是一个统一的日志管理解决方案,能够收集和管理来自内核、初始化系统以及用户空间应用的日志。\n特点归纳如下\n\n单元Unitssystemd 将服务、挂载点、设备等管理对象抽象为单元,通过单元文件进行配置。\n依赖性管理可以配置单元间的依赖关系确保服务以合适的顺序启动。\n并行启动支持服务的并行启动显著提高系统的启动速度。\n状态监控实时监控服务状态提供重新启动失败服务的机制。\n\nSystemd 的历史和影响\nsystemd 最初由 Lennart Poettering 和 Kay Sievers 在 2010 年开发,作为一个更加强大和灵活的替代传统的 Unix-style init 系统的方案。自引入以来systemd 已被广泛接受并成为多个主流 Linux 发行版的标准部分,包括 Fedora、Debian、Ubuntu 和 CentOS。这种广泛的采用引发了广泛的讨论和争议尤其是关于它的复杂性和与 Unix 哲学的一致性。尽管有争议systemd 的设计允许了更快的系统启动时间和更好的服务管理,对 Linux 系统管理产生了深远的影响。\n与其他服务管理器的比较\n与 SysV init 系统相比systemd 提供了更加现代化和强大的功能集。例如SysV init 使用脚本逐个启动服务无法进行有效的依赖管理和并行处理。Upstart 是另一种较早的替代 init 系统它介绍了基于事件的启动机制尽管如此Upstart 仍未提供像 systemd 这样的综合日志管理和系统状态监控。\nsystemd 的优势在于其架构的整合性和管理能力,这使其成为了大多数主流 Linux 发行版的默认服务管理系统。\nSystemd 架构\nsystemd 的架构是高度模块化的主要由各种类型的单元Units构成这些单元通过配置文件定义并由 systemd 管理器控制。单元是管理系统资源的基本方法,每种单元类型都有其特定的用途和应用场景。\n架构图\n\n单元Units\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述实际应用场景服务Services代表一个后台运行的进程可以是一次性的、持续的或间歇性的。用于管理各种后台服务如网络服务、数据库服务等。插槽Sockets允许 systemd 按需启动服务通过监听特定的端口来激活服务。用于提高资源利用效率例如仅在有请求时启动数据库服务。设备Devices表示系统中的物理或虚拟设备由 systemd 动态管理。用于设备的动态挂载和管理,如自动管理 USB 设备。挂载Mounts控制文件系统的挂载点。用于管理文件系统的挂载确保在需要时可用。自动挂载Automounts在访问时自动挂载文件系统。用于访问网络存储或其他延迟加载的资源时提高性能。路径Paths监视文件系统路径的更改并在更改时激活相应的 Units。用于触发任务如在文件下载完毕后自动启动处理脚本。定时器Timers类似于 cron 作业,按计划时间执行任务。定时执行如备份、日志清理等任务。\n目标Targets\nTargets 是特殊类型的 Unit用于将系统带到特定的状态。例如graphical.target 设置图形用户界面multi-user.target 设置多用户网络服务。Targets 帮助组织和优化启动过程,通过控制哪些服务和 Units 需要启动来达到所需的操作状态。\n启动流程图\nflowchart TB\n start([Start]) --> basic.target{{basic.target}}\n basic.target --> sysinit.target{{sysinit.target}}\n sysinit.target --> sockets.target{{sockets.target}}\n sysinit.target --> paths.target{{paths.target}}\n sysinit.target --> slices.target{{slices.target}}\n sysinit.target --> timers.target{{timers.target}}\n sockets.target --> network.target{{network.target}}\n paths.target --> multi-user.target{{multi-user.target}}\n network.target --> network-online.target{{network-online.target}}\n multi-user.target --> graphical.target{{graphical.target}}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n目标名称描述basic.target启动系统基础服务。sysinit.target系统初始化包括设备和文件系统的挂载。sockets.target确保所有需要的套接字服务已启动准备好通信接口。paths.target监控文件系统路径变更触发相应服务。slices.target管理系统资源分配。timers.target启动所有计时器单元处理定时任务。network.target表示网络功能基本就绪为后续服务提供网络支持。network-online.target确保网络完全可用用于需要网络连接的服务。multi-user.target启动多用户环境下所需的服务准备好除图形界面外的网络服务。graphical.target启动图形界面相关的服务达到图形用户界面状态。\n生命周期和状态转换\nsystemd 的生命周期管理涉及启动、停止、重启和重新加载服务及其他 Units。状态转换通过 systemd 的命令行工具 systemctl 实现,该工具使管理员能够控制和查询 systemd 的状态。\nflowchart LR\n start(Start) -->|Load| loaded(Loaded)\n loaded -->|Start| running(Running)\n running -->|Stop| stopped(Stopped)\n running -->|Restart| running\n stopped -->|Start| running\n loaded -->|Reload| running\n running -->|Fail| failed(Failed)\n failed -->|Restart| running\n failed -->|Stop| stopped\n\n生命周期管理还包括处理依赖关系确保服务按正确的顺序启动和停止。systemd 优化了这些过程,使系统管理更加高效和可预测。\nSystemd 单元文件\n结构和语法\nsystemd 的单元文件是纯文本文件,用于定义如何管理和启动系统资源,如服务、进程、设备等。每个单元文件分为几个部分,主要包括:\n\n[Unit]:提供描述、依赖关系和启动顺序的信息。\n[Service]:特定于服务的配置,如服务类型、启动命令和重启策略。\n[Install]:定义如何安装(启用/禁用)这个单元,涉及默认的启动目标。\n\n单元文件通常位于 /etc/systemd/system 或 /usr/lib/systemd/system 目录下,根据是否是系统级或用户定义的单元而有所不同。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n目录描述/etc/systemd/system/使用 systemctl enable 命令创建的 systemd 单元文件,以及为扩展服务添加的单元文件。这个目录优先于带有运行时单元文件的目录。/usr/lib/systemd/system/与安装的软件包一起分发的 systemd 单元文件。/run/systemd/system/在运行时创建的 systemd 单元文件。该目录优先于安装了的服务单元文件的目录。\n自定义单元文件\n创建自定义单元文件允许用户定义特定的服务或应用程序的启动和管理方式。例如编写一个简单的服务单元文件来管理一个自定义的脚本服务可能看起来如下\n[Unit]\nDescription=My Custom Service\nAfter=network.target\n \n[Service]\nType=simple\nExecStart=/usr/bin/mycustomscript\nRestart=on-failure\n \n[Install]\nWantedBy=multi-user.target\n这个单元文件指定了服务依赖于网络服务后启动使用 /usr/bin/mycustomscript 作为启动命令,如果失败则自动重启。\n启用和禁用单元文件\n通过 systemctl 命令管理单元文件的启用状态是标准做法。启用单元文件使得在启动时自动运行服务:\nsudo systemctl enable myservice.service\n相反如果不希望服务在启动时运行可以禁用该单元文件\nsudo systemctl disable myservice.service\n启用单元只影响系统启动行为并不启动或停止当前运行的服务。\n条件性单元和模板单元\n\n条件性单元systemd 允许在单元文件中设置条件,例如 ConditionPathExists=/path/to/check只有当指定路径存在时单元才会启动。\n模板单元模板单元允许通过实例化来重用配置。例如可以创建一个名为 myservice@.service 的模板,然后通过指定不同的实例名称启动不同配置的服务。\n\n例如如果有多个相似的服务需要运行可以使用模板单元文件\n[Unit]\nDescription=My Service Instance %i\n \n[Service]\nExecStart=/usr/bin/myservice --instance %i\n然后可以通过 systemctl start myservice@1.service 来启动服务的一个实例。\nSystemd 命令行工具\nsystemctl 是 systemd 的主要命令行工具,用于检查和控制系统和服务管理器的状态。它提供了一套全面的功能来启动、停止、重启、重新加载服务,以及查看状态和管理系统。\nSystemctl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明启动服务sudo systemctl start apache2.service启动指定的服务如 Apache2。停止服务sudo systemctl stop apache2.service停止正在运行的服务。重启服务sudo systemctl restart apache2.service重新启动服务常用于应用更新后的配置重新载入。查看服务状态sudo systemctl status apache2.service显示服务的当前运行状态包括是否活跃、启动时间等信息。启用服务自启sudo systemctl enable apache2.service配置服务在系统启动时自动启动。禁用服务自启sudo systemctl disable apache2.service取消服务的自启动设置不在系统启动时自动启动。重新加载服务sudo systemctl reload apache2.service重新加载服务的配置文件不中断当前运行的服务。强制重启服务sudo systemctl force-reload apache2.service当普通重载无效时使用此命令强制重启服务。显示服务列表systemctl list-units --type=service列出系统上所有服务的状态。检查服务是否启动失败sudo systemctl is-failed apache2.service检查服务是否启动失败并返回状态。\nSystemd-analyze\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明分析启动时间systemd-analyze显示启动耗时的总览。显示启动过程详细信息systemd-analyze blame列出每个服务的启动耗时帮助识别启动过程中的瓶颈。生成启动时间图systemd-analyze plot > file.svg生成系统启动过程中各服务启动时间的图表。检查安全性systemd-analyze security评估系统上服务的安全性。查看单位依赖`systemd-analyze dotdot -Tsvg > systemd.svg`\nHostnamectl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明显示当前主机名hostnamectl显示关于当前系统主机的详细信息。设置主机名sudo hostnamectl set-hostname new-hostname设置或更改系统的主机名。\nLocalectl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明显示当前区域设置localectl显示当前的语言和区域设置。设置系统语言sudo localectl set-locale LANG=en_US.UTF-8设置系统的语言环境。设置键盘布局sudo localectl set-keymap us设置系统的键盘布局。\nTimedatectl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明显示当前时间和日期timedatectl显示当前的时间、日期和时区。设置时区sudo timedatectl set-timezone America/New_York设置系统的时区。设置系统时间sudo timedatectl set-time '2021-01-01 12:34:56'手动设置系统的时间。\nLoginctl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例命令说明列出登录会话loginctl list-sessions显示当前所有活跃的登录会话。显示会话详细信息loginctl show-session session-id显示指定会话的详细信息。结束会话sudo loginctl terminate-session session-id强制结束指定的会话。\nJournalctl 命令\n查看系统状态和服务的日志对于系统管理至关重要。systemctl status 命令可以显示单个服务或整个系统的状态。此外journalctl 是 systemd 的日志管理工具,用于查询和显示系统日志:\n\n查看所有系统日志sudo journalctl\n按服务过滤日志sudo journalctl -u apache2.service\n显示实时日志sudo journalctl -f\n\n管理服务和挂载点\nsystemctl 允许管理员管理不仅是服务,还包括挂载点、计时器等其他资源。例如,启动或停止挂载点的命令与服务类似,如 sudo systemctl start home.mount 或 sudo systemctl stop home.mount。\n系统启动和关机\n控制系统的启动和关机是 systemctl 命令的基本功能:\n\n重新启动系统sudo systemctl reboot\n关闭系统sudo systemctl poweroff\n暂停系统sudo systemctl suspend\n休眠系统sudo systemctl hibernate\n\n这些命令提供了对系统状态的直接控制使管理员能够从命令行安全地管理系统的启动和关闭过程。\nSystemd 服务管理\n服务的依赖关系和并发控制\n在 systemd 中,服务之间的依赖关系是通过单元文件中的 After, Before, Requires, 和 Wants 指令定义的。这些指令确保服务以合适的顺序启动和停止,以及在必要的服务不可用时进行正确的处理。\n\nAfter 和 Before确保服务按正确的顺序启动。例如如果服务 B 在服务 A 后启动,服务 B 的单元文件将包含 After=a.service。\nRequires 和 WantsRequires 会在依赖的单元失败时终止当前单元,而 Wants 则较为宽松,不会因依赖单元的失败而停止当前单元。\n\n并发控制通过 Type 指令管理这决定了服务是并行启动还是串行。例如Type=oneshot 通常用于需要顺序执行的脚本,而 Type=simple 或 Type=forking 用于常规后台服务。\n服务的重启策略和超时设置\nsystemd 允许通过单元文件中的 Restart 指令定义服务的重启策略,如何响应服务的意外终止:\n\nRestart=no不自动重启。\nRestart=on-failure仅在服务非正常退出时重启。\nRestart=always无论退出状态如何都重启。\n\n超时设置通过 TimeoutStartSec, TimeoutStopSec, 和 TimeoutSec 控制,这些设置定义了启动和停止服务之前的等待时间,有助于管理服务在启动或关闭时挂起的情况。\n服务的环境变量和执行参数\n通过单元文件中的 Environment 指令可以设置服务的环境变量。这对于需要特定环境配置的服务来说非常有用:\n[Service]\nEnvironment="VAR1=value1" "VAR2=value2"\n执行参数通过 ExecStart, ExecStop, 和 ExecReload 指令定义,这些指令指定了启动、停止和重新加载服务时执行的命令。\n服务的状态和输出处理\n状态监控是通过 systemctl status 命令实现的,它提供了关于服务运行状态的详细信息,包括是否活跃、运行时长和最近的日志条目。\n输出处理通常通过 systemd 的日志系统 journald 管理,它收集和管理来自系统和服务的日志。通过 journalctl 命令,管理员可以查询和查看服务日志:\njournalctl -u myservice.service\n这使得跟踪和调试服务问题变得更加容易。\nSystemd 目标和资源管理\n理解 Systemd 目标\n在 systemd 中目标Targets相当于传统 init 系统中的运行级别,但提供了更多的灵活性和配置选项。目标用于组织和管理系统服务的集合,以达到特定的系统状态。常见的目标包括 graphical.target图形界面、multi-user.target多用户环境和 network.target网络服务就绪。通过使用 systemctl 命令设置目标,管理员可以控制哪些服务组在系统启动或运行时被激活:\nsudo systemctl set-default graphical.target\n\n资源分配和限制\nsystemd 提供了丰富的资源管理功能,允许系统管理员对服务进行资源限制,确保系统的稳定性和响应能力。这些设置在单元文件的 [Service] 部分配置,主要包括:\n\nCPU 时间CPUQuota= 可以限制服务使用的 CPU 百分比。\n内存限制MemoryLimit= 设置服务可以使用的最大内存。\n磁盘 I/OIOWeight= 控制服务的磁盘 I/O 优先级。\n\n例如为一个服务设置内存和 CPU 使用限制:\n[Service]\nMemoryLimit=500M\nCPUQuota=30%\n\n这些限制帮助防止单个服务消耗过多资源从而影响系统上其他服务的性能。\n电源管理和节能设置\nsystemd 集成了电源管理功能,通过 logind 和 systemd-sleep 服务提供对系统休眠、待机和唤醒的控制。这些功能特别适用于希望优化能源消耗的移动和嵌入式设备。电源管理设置通常在 /etc/systemd/logind.conf 文件中配置,包括:\n\nHandleSuspendKey控制当挂起键被按下时的行为。\nHandleLidSwitch笔记本电脑盖关闭时的系统反应。\nPowerKeyBehavior电源键被按下时的行为。\n\n此外systemd 提供了 systemctl suspend、systemctl hibernate 和 systemctl hybrid-sleep 命令,允许从命令行管理系统的电源状态。这些命令提供了对系统电源行为的即时控制,使管理员能够根据需要调整系统节能设置和电源策略。\nsudo systemctl suspend\nSystemd 网络配置\n网络接口和插槽的管理\nsystemd 提供了一个叫做 systemd-networkd 的守护进程用于管理网络配置使其成为处理网络接口和插槽的强大工具。systemd-networkd 管理静态和动态网络配置,包括地址分配、路由表配置和网络接口状态管理。此服务对于服务器和容器环境特别有用,其中可能需要在系统启动时自动配置网络。\n网络配置文件的结构和语法\n网络配置文件通常位于 /etc/systemd/network 目录中,文件扩展名为 .network。这些配置文件使用 INI 格式,分为几个部分,主要包括 [Match] 和 [Network]\n\n[Match] 部分确定配置文件适用于哪些网络接口。可以按接口名称、MAC 地址等属性匹配。\n[Network] 部分定义了接口的网络设置,如 IP 地址、网关、DNS 等。\n\n例如为特定接口配置静态 IP 地址的 .network 文件可能看起来如下:\n[Match]\nName=eth0\n\n[Network]\nAddress=192.168.1.100/24\nGateway=192.168.1.1\nDNS=192.168.1.1\n\n动态主机配置协议DHCP和静态网络配置\nsystemd-networkd 支持通过 DHCP 自动配置网络接口。启用 DHCP 的配置非常简单:\n[Match]\nName=eth0\n\n[Network]\nDHCP=yes\n\n这将为指定接口启用 DHCP自动获取 IP 地址、网关、DNS 服务器等。对于静态配置,如上所示,管理员需要手动指定这些值。\n同时systemd 还提供了高级网络特性,如桥接、绑定和虚拟局域网 (VLAN) 配置,这些都可以通过类似的 .netdev 和 .network 配置文件进行管理。\nSystemd 日志管理\n日志记录和存储\nsystemd 的日志管理是通过 systemd-journald 服务实现的这是一个日志守护程序负责收集和存储日志数据包括内核消息、系统服务消息以及其他日志源的数据。journald 收集的日志存储在二进制文件中,通常位于 /var/log/journal/ 目录。这种存储方式优化了日志的读取和写入速度,并支持包括元数据在内的丰富日志信息。\n使用 Journalctl 命令查看和分析日志\njournalctl 是用于查询和显示从 systemd-journald 收集的日志的工具。这个命令提供了强大的过滤和排序功能,使得查找特定日志事件变得简单。常用的 journalctl 命令包括:\n\n查看所有日志journalctl\n按时间倒序查看日志journalctl -r\n按单位查看日志journalctl -u nginx.service\n查看指定时间段的日志journalctl --since "2021-01-01" --until "2021-01-02"\n实时跟踪最新日志journalctl -f\n\n这些命令提供了灵活性以适应不同的日志查询需求。\n日志的归档和清理\n随着时间的推移日志文件可能会变得很大占用大量磁盘空间。systemd-journald 提供了自动归档和清理旧日志的功能,以保持系统的整洁和效率。管理员可以通过编辑 /etc/systemd/journald.conf 文件来配置日志保留策略,例如:\n\nSystemMaxUse设置日志占用的最大磁盘空间。\nSystemKeepFree设置系统应保持空闲的最小磁盘空间。\nMaxRetentionSec设置日志的最大保留时间。\nVacuumSize当日志大小达到指定值时自动清理旧日志。\n\n通过这样的配置系统可以自动管理日志文件的大小避免磁盘空间被过度使用。\nsudo journalctl --vacuum-size=1G\n上面的命令将删除旧日志直到日志文件的总大小减少到 1GB。\nSystemd 定时任务\n定时器和计时器单元\n在 systemd 中定时器Timers是用来替代传统的 cron 作业的功能,提供了时间基的任务调度。定时器通过两部分配置实现:一个是 .timer 文件,另一个是与之关联的 .service 文件。\n\n.timer 单元:定义了定时器的触发时间和条件。这包括周期性触发和单次触发的配置。\n.service 单元:指定了定时器触发时要执行的任务或服务。\n\n编写和配置定时任务\n创建一个新的定时器涉及到编写 .timer 和 .service 文件。例如,假设我们要每天定时备份一次数据:\n\n\n创建 service 文件backup.service\n[Unit]\nDescription=Daily Backup Job\n\n[Service]\nExecStart=/usr/bin/backup-script\n\n\n\n创建 timer 文件backup.timer\n[Unit]\nDescription=Runs backup every day\n\n[Timer]\nOnCalendar=daily\nPersistent=true\n\n[Install]\nWantedBy=timers.target\n\n\n\n在这个例子中OnCalendar=daily 触发规则设定了每天运行备份任务。Persistent=true 确保即使在某些情况下错过了定时时间,下次启动时也会尝试执行。\n定时任务的依赖和执行顺序\n在 systemd 中配置定时任务时,可以通过依赖关系和顺序指令来控制任务的执行顺序和条件。例如,如果一个任务需要在网络服务完全启动后执行,可以在 .service 文件中使用 After=network.target 指令。\n此外使用 Requires= 和 After= 指令确保在特定服务或任务失败时,相关的定时任务不会执行,这为任务调度提供了更高的可控性和稳定性。\n示例依赖网络的定时任务\n\n\n修改 service 文件:增加依赖关系\niniCopy code[Unit]\nDescription=Perform network-dependent task\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nExecStart=/usr/bin/network-dependent-script\n\n\n\n配置 timer 文件:如之前所示,定时设置保持不变。\n\n\n通过这样的配置systemd 确保只有在网络完全可用的情况下才执行该任务。这种方法提高了任务执行的可靠性,避免了因依赖条件未满足而导致的失败。\n高级 Systemd 特性\n容器和 Systemd\nsystemd 提供了对容器的广泛支持,特别是通过 systemd-nspawn 工具它允许用户在隔离的环境中启动容器或虚拟机。systemd-nspawn 被用作轻量级的容器管理工具,适合于开发和测试环境。\n\n\n使用 systemd-nspawn该命令可以启动一个基于特定文件系统目录的容器例如\nsudo systemd-nspawn -D /path/to/container/root\n这条命令启动一个容器使用指定目录作为其根文件系统。\n\n\n集成与管理systemd 的机制还允许通过 .service 单元文件管理容器,使得容器的启动和停止可以像管理常规服务一样进行。\n\n\n系统升级和回滚\nsystemd 提供了机制来帮助管理系统升级和回滚,确保系统更新可以安全地应用并在需要时回滚到旧版本。通过使用 systemd 的快照和原子更新特性,管理员可以在应用更新前创建系统状态的快照,并在更新不成功时恢复到这个快照。\n\n\n创建和恢复快照可以通过 systemctl 命令管理快照:\nbashCopy code\nsudo systemctl snapshot my_snapshot.service\n\n如有需要可以通过类似的命令恢复到此快照状态。\n\n\n原子更新systemd 支持在不中断当前运行服务的情况下更新软件和服务,减少系统升级带来的不便和风险。\n\n\n远程管理和控制\nsystemd 也扩展了其功能到远程管理领域,通过 systemd-machined 和 systemd-journal-remote 等守护程序支持远程机器和日志的管理。这允许管理员从中央位置监控和控制多台机器的状态和日志。\n\n\n设置远程日志收集systemd-journal-remote 可以配置为接收其他机器发送的日志数据,从而集中日志管理:\nsudo systemctl start systemd-journal-remote\n\n\n\n远程机器管理使用 systemctl 命令远程控制系统服务,需配置适当的网络和权限设置。\n\n\n故障排查和性能优化\n常见的 Systemd 问题和解决方案\n在使用 systemd 管理系统时,可能会遇到一些常见问题。这里列举几个典型问题及其解决方案:\n\n服务无法启动检查服务的单元文件中的 ExecStart 指令指定的路径和权限。使用 journalctl -u service-name.service 查看服务日志以获得错误详细信息。\n服务启动超时调整单元文件中的 TimeoutStartSec 设置,以提供更长的启动时间。\n依赖问题确保所有必需的服务都已配置为在当前服务之前启动通过 After 和 Requires 指令控制启动顺序。\n\n性能监控和优化技巧\nsystemd 提供了多种工具和方法来监控和优化系统性能:\n\n使用 systemd-analyze 命令这个工具可以帮助你分析系统启动时间并确定哪些服务影响了启动性能。例如systemd-analyze blame 显示启动过程中各服务的启动时间。\n优化服务启动顺序和资源使用通过调整服务的启动顺序使用 After 和 Before和资源限制如 MemoryLimit 和 CPUShares可以显著提高系统的响应性和效率。\n\n安全性和隐私考虑\n安全性和隐私是系统管理中的重要组成部分systemd 提供了多种机制来增强系统的安全性:\n\n使用 ProtectSystem、ProtectHome这些设置可以限制服务对系统文件和用户主目录的访问从而减少恶意软件可能利用的攻击面。\n日志安全性通过配置 systemd-journald 的日志存储策略(如加密存储日志),增强日志数据的安全性和隐私保护。\n\n通过定期审查安全配置和采用最佳实践可以有效防止潜在的安全威胁确保系统运行的安全性和稳定性。\n实践案例和最佳实践\n真实世界中的 Systemd 应用案例\nsystemd 的应用遍布现代 Linux 系统,从桌面到服务器,再到容器和云基础设施。以下是几个具体的应用案例:\n\n大规模云服务管理许多云服务提供商使用 systemd 来管理和维护成千上万的服务实例,利用其并发控制和服务依赖管理功能来优化资源使用和响应时间。\nIoT 设备在物联网设备上systemd 用于管理设备的启动流程和服务,提高设备的启动速度和可靠性。\n容器编排在容器化环境中如使用 Podman 和 Kubernetessystemd 常用于管理容器的生命周期,配合 systemd-nspawn 提供额外的隔离和管理能力。\n\n遵循的最佳实践和设计模式\n为了最大化 systemd 的效益,建议遵循以下最佳实践:\n\n彻底利用单元文件的依赖管理通过正确配置 After、Before、Wants 和 Requires 等指令,确保服务按正确的顺序启动和停止。\n使用资源限制提高系统稳定性在单元文件中配置 MemoryLimit、CPUQuota 等,以避免单个服务占用过多资源。\n积极使用日志管理功能通过 systemd-journald 提供的日志管理,进行有效的故障诊断和性能监控。\n\n社区资源和支持\nsystemd 的广泛采用也意味着有一个活跃的社区和丰富的资源可供获取支持和学习:\n\n官方文档和手册systemd 的官方文档提供了详尽的指导和参考。\n论坛和社区如 Reddit 的 Linux 社区、Stack Exchange 网站等,这些平台有大量的讨论和解决方案。\n开发者博客和教程许多系统管理员和开发者在其博客上分享具体的案例和高级技巧。\n\n通过利用这些资源用户可以更深入地理解 systemd 的功能,解决实际问题,同时也能跟上该技术的最新发展。"},"Technology/OperatingSystem/Linux/4.系统管理/Linux-系统启动详解":{"title":"Linux 服务管理","links":[],"tags":["Linux/系统管理","技术/操作系统"],"content":"引言\nLinux一种自由和开源的操作系统因其强大的定制性和稳定性在全球各地的服务器、桌面、移动设备等领域得到了广泛应用。无论是云计算的基础设施还是物联网设备的操作系统Linux 都是核心的选择。然而,为了充分利用 Linux 的潜力,了解其如何启动和运行,以及如何管理运行级别,是必不可少的。\n系统启动\nLinux 系统的启动过程是多阶段的,涉及硬件、引导加载器、内核和系统初始化等多个阶段。\n\n启动流程\n\n开机自检POST当电源开启后BIOS 或 UEFI 固件从非易失性存储器中加载,执行一系列检查来验证系统基本硬件功能,如内存、处理器和输入/输出系统是否正常工作。\n设备检测在开机自检之后BIOS/UEFI 将识别并配置系统中连接的所有硬件设备,包括处理器、内存、硬盘、光驱以及其他外围设备,如键盘和鼠标。\n选择启动设备BIOS/UEFI 检查其设置或启动顺序配置决定从哪个设备启动操作系统。这可能包括硬盘、USB 设备、网络服务器或光驱。\n运行引导加载器从选定的启动设备加载引导加载器例如 GRUB 或 Windows Boot Manager。引导加载器提供一个界面用户可以选择加载特定的操作系统或内核版本。\n内核加载引导加载器从启动设备中加载选定的操作系统内核到 RAM 中,并开始系统的初始化过程。此过程包括加载必要的驱动程序以及进行初步的系统设置。\n系统服务启动操作系统内核初始化完成后systemd 或其他初始化系统作为第一个用户空间进程运行,负责启动其他系统服务和进程。这个阶段可能包括硬件探测、文件系统挂载和网络配置。\n执行启动脚本在系统服务启动之后操作系统执行多个启动脚本这些脚本进一步配置环境变量、网络设置、用户权限和系统服务确保系统按预期方式运行。\n显示登录界面所有系统服务和启动脚本执行完毕后操作系统将显示登录界面。用户现在可以输入用户名和密码进行登录系统则为用户会话准备环境和资源。\n\n1.BIOS 阶段\n当电脑开机时会进行一种叫做电源自检Power-On Self TestPOST的过程。这个过程是由电脑的基本输入/输出系统Basic Input/Output SystemBIOS或统一可扩展固件接口Unified Extensible Firmware InterfaceUEFI来管理的。POST 是电脑启动过程中的第一个步骤,是为了确定系统的基本硬件设备是否能够正常运行。\n基本的 POST 过程的步骤:\ngraph LR\n A[系统电源打开] --> B[CPU 复位]\n B --> C[BIOS/UEFI 初始化]\n C --> D[硬件检查]\n D --> E[错误检查和报告]\n E --> F[启动引导设备]\n\n\n\n系统电源打开当你按下电源开关后电源供应器开始为整个系统供电。\n\n\nCPU 复位电源打开后中央处理器CPU会被复位到预定义的状态。复位过程包括清空 CPU 的寄存器和缓存,设置程序计数器为预定义的地址(在许多系统中,这通常是固定的 ROM 地址)。\n\n\nBIOS/UEFI 初始化CPU 开始执行在预定义地址上的代码,这通常是 BIOS/UEFI 的代码。BIOS/UEFI 在启动时,会进行一些基本的系统初始化,如设置中断描述符表、初始化内存控制器等。\n\n\n硬件检查BIOS/UEFI 开始进行 POST检查系统的基本硬件设备。这通常包括内存、硬盘驱动器、键盘、鼠标等设备。这个过程可能包括设备自我检测如果设备支持的话也可能包括读写测试如对内存的读写测试。\n\n\n错误检查和报告如果在 POST 过程中检测到错误BIOS/UEFI 会报告这个错误。这可能是通过屏幕上的错误消息,或者通过蜂鸣器的蜂鸣声(通常被称为 “beep codes”。\n\n\n启动引导设备如果 POST 成功完成BIOS/UEFI 会开始从引导设备如硬盘、USB 设备等)加载操作系统。\n\n\n在这个阶段有一些系统可能使用 UEFI统一的可扩展固件接口而不是传统的 BIOS。UEFI 是一个规范定义了软件与操作系统和平台固件之间的软件接口。UEFI 启动过程的细节和 BIOS 有所不同,但基本思路是类似的:它负责初始化硬件,然后加载并运行启动加载器。\n2.引导加载器阶段\n**启动加载程序Bootloader是在计算机启动过程中BIOS 或 UEFI 完成硬件检测后,用于加载操作系统内核的一个小程序。**常见的 Linux 启动加载程序有 GRUBGNU GRand Unified Bootloader、LILOLinux Loader、SYSLINUX 等。\n启动加载程序的基本步骤\ngraph LR\n A[读取配置文件] --> B[展示操作系统选择菜单]\n B --> C[加载操作系统内核]\n C --> D[传递控制权]\n\n\n\n\n读取配置文件启动加载程序首先会读取其配置文件了解哪些操作系统可供选择每个操作系统的内核文件存放在何处是否有特定的启动参数等信息。在 GRUB 中,这个配置文件通常是 /boot/grub/grub.cfg。\n\n\n展示操作系统选择菜单根据配置文件启动加载程序会在屏幕上展示一个菜单列出所有可用的操作系统如果有多个的话并等待用户选择。用户可以在这个时候选择要启动的操作系统或者修改启动参数。\n\n\n加载操作系统内核用户选择了要启动的操作系统后启动加载程序会找到相应的内核文件加载到内存中。这个过程可能涉及到文件系统的操作因为内核文件通常存放在硬盘的某个文件系统中。所以启动加载程序需要包含一些简单的文件系统驱动程序。\n\n\n传递控制权内核文件被加载到内存后启动加载程序会将 CPU 的控制权传递给内核,然后操作系统开始运行。\n\n\n引导加载器不仅可以加载 Linux也可以加载许多其他类型的操作系统。例如GRUB 支持加载 Linux、Windows、FreeBSD 等等。这是通过多启动multi-boot规范实现的它定义了一个标准的方法让引导加载器与操作系统内核交互。\n3.内核阶段\n**一旦启动加载程序(例如 GRUB将操作系统内核加载到内存并将控制权移交给它Linux 内核就开始初始化。**在内核初始化过程中,它实际上是在设定一个基本的运行环境,这样用户空间的程序才能在这个环境中运行。在这个环境中,内核提供了许多基本的服务,例如设备驱动、文件系统、网络服务、进程调度等。所有这些服务在用户空间的程序看来就像是操作系统的一部分,但它们实际上都是由内核提供的。\n以下是内核阶段的一些主要步骤\ngraph LR\n A[初始化 CPU 和内存管理] --> B[启动其他 CPU 核心]\n B --> C[设备和驱动初始化]\n C --> D[设置中断和系统调用处理]\n D --> E[初始化虚拟文件系统 VFS]\n E --> F[挂载根文件系统]\n F --> G[启动 init 进程]\n\n\n\n初始化 CPU 和内存管理:首先,内核需要设置和初始化处理器和内存管理系统。它会设置页表来管理虚拟内存,检测和初始化 CPU 和其他硬件设备,以及初始化内核数据结构。\n\n\n启动其他 CPU 核心:在多核处理器系统中,内核需要唤醒和初始化其他的 CPU 核心。\n\n\n设备和驱动初始化内核会开始探测并初始化系统中的各种硬件设备。这包括识别硬件设备加载和初始化设备驱动以及设置设备的相关参数。\n\n\n设置中断和系统调用处理内核会设置中断处理程序这是处理硬件中断例如键盘输入、网络数据包到达等的机制。同时内核也会设置系统调用处理程序这是用户空间程序与内核进行交互的主要方式。\n\n\n初始化虚拟文件系统VFSLinux 内核会初始化虚拟文件系统VFS这是管理所有文件和目录的核心组件。\n\n\n挂载根文件系统内核会挂载根文件系统通常是 ”/”)。这通常涉及到读取硬盘上的数据,并可能需要启动额外的驱动程序来识别文件系统(如 ext4、btrfs 等)。\n\n\n启动 init 进程:最后,内核会启动一个特殊的用户空间程序,称为 init 进程。这个进程的进程 IDPID是 1它负责启动所有其他的用户空间程序和服务。\n\n\n4.系统初始化阶段\n**在 Linux 内核完成初始化并挂载了根文件系统后,它将启动第一个用户空间程序,这个进程通常被称为 init 进程。init 进程的进程 IDPID是 1它是所有其他用户空间进程的父进程。**init 进程在系统中有特殊的地位,它负责启动其他所有的系统服务和用户空间进程。\n常见的 init 系统包括 Systemd、Upstart、SysV init 等,它们各自的启动流程可能会有所不同。以下是使用 Systemd 作为 init 系统的一般流程:\ngraph LR\n A[启动] --> B[读取和解析配置文件]\n B --> C[启动系统服务]\n C --> D[启动用户登录服务]\n\n\n\n启动内核首先启动 Systemd 进程,通常是通过执行 /sbin/init 程序。这个程序通常是指向 Systemd 的一个符号链接。\n\n\n读取和解析配置文件Systemd 首先读取和解析其配置文件,了解要启动哪些系统服务。这些配置文件通常位于 /etc/systemd/system 或 /lib/systemd/system 目录中,每个文件描述了一个服务的启动信息,如启动命令、依赖关系等。\n\n\n启动系统服务Systemd 开始按照配置文件启动系统服务。Systemd 会处理服务之间的依赖关系,确保服务按照正确的顺序启动。这些服务通常包括网络服务、日志服务、定时任务等。\n\n\n启动用户登录服务Systemd 会启动一个特殊的服务,用于处理用户登录。这个服务可以是一个命令行登录程序(如 getty 或 mingetty也可以是一个图形登录界面如 GDM 或 LightDM。\n\n\n在系统初始化阶段init 系统会根据预设的运行级别启动一系列的系统服务和守护进程。这些运行级别是一个用来定义系统应该运行哪些服务的机制。例如,在某个运行级别,系统可能只启动最必要的服务,以便快速启动或进行故障排查。而在另一个运行级别,系统可能会启动全部的服务,包括图形界面、网络服务等。\n运行级别的概念\n运行级别是 Linux 系统中用于定义系统需要运行哪些服务和进程的方式。每个运行级别都有特定的服务和进程集合可以根据系统的需求进行切换。Linux 系统中包含以下七个运行级别:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运行级别描述0系统停机通常用于正常关闭系统。1单用户模式通常用于系统维护。2多用户模式不包括网络服务。3完全的多用户模式包括网络服务。这通常是 Linux 系统默认的运行级别。4通常不使用用户可以自定义。5图形用户模式启动 X Window 图形界面。6系统重启。\n管理运行级别\nLinux 系统提供了一些工具和命令,使用户能够查看和更改当前的运行级别。\n\n使用 runlevel 命令可以查看当前的运行级别。该命令会输出两个数字,前一个代表前一个运行级别,后一个代表当前运行级别。\n使用 init 命令加上运行级别的数字,可以更改当前的运行级别。例如,执行 init 3 会将系统转换到多用户文本模式。\n另外用户还可以通过编辑 /etc/inittab 文件来更改系统的默认运行级别。例如id:3:initdefault: 就设置了系统的默认运行级别为 3。\n\n通过理解 Linux 系统的启动流程和运行级别,可以更好地理解和管理 Linux 系统的行为和状态。这些知识对于系统管理员来说尤其重要,因为它们直接影响到系统的性能和稳定性。\n进程管理\n在操作系统中理解并掌握进程及其管理是至关重要的尤其是在类 Unix 的操作系统如 Linux 中,它们是系统正常运行的基础。\n进程的概念\n进程是一个运行的程序的实例。每个运行中的程序都会生成至少一个进程。每个进程都有一个唯一的进程 ID也称为 PID是由系统自动分配的。同时每个进程都有其父进程。父进程是创建其他进程的进程。在 Linux 系统中init 进程PID 为 1是所有进程的祖先进程神父进程。\n进程的状态\nLinux 进程有五种状态运行Running等待Interruptible Sleep非中断等待Uninterruptible Sleep停止Stopped僵尸Zombie。\nstateDiagram-v2\n [*] --> Running: 创建进程\n Running --> InterruptibleSleep: 等待事件\n InterruptibleSleep --> Running: 事件完成\n Running --> Stopped: 收到停止信号\n Stopped --> Running: 收到继续信号\n Running --> Zombie: 进程结束\n Zombie --> [*]: 父进程读取状态\n\n\n运行状态Running: 进程正在 CPU 上运行或者在运行队列中等待运行。运行状态的进程可能正在使用 CPU ,也可能正在等待 CPU 时间片。\n等待状态Interruptible Sleep: 进程正在等待某个条件(如用户输入或者磁盘 I/O完成。当满足其等待的条件它就会转移到运行状态。\n非中断等待状态Uninterruptible Sleep: 与等待状态类似,进程在等待某个条件完成。但这种状态的进程不能被其他进程或者事件唤醒和打断,只有等待的条件被满足,它才会被唤醒。\n停止状态Stopped: 进程被暂停执行可以由一个信号signal触发进入该状态。即使有可用的 CPU 时间,被停止的进程也不会执行。\n僵尸状态Zombie: 这是进程结束(或被其他进程杀死)后的一种状态。尽管进程的主体已经终止,但它在进程表中的条目仍然存在,直到父进程读取了子进程的退出状态信息后,才会消失。\n\n进程的优先级\n在 Linux 系统中,处理器必须在多个并发运行的进程之间分享其时间。**为了公平和有效地管理这些进程Linux 使用一种称为优先级的机制来确定哪个进程应该优先获取 CPU 时间。**优先级是一种衡量进程重要性和优先级的方法,优先级较高的进程将获得更多的 CPU 时间。\nLinux 系统使用所谓的 Nice 值来表示进程的优先级。Nice 值的范围从 -20最高优先级到 19最低优先级。默认的 Nice 值是 0。Nice 值越低,进程的优先级就越高,也就是说,它会获得更多的 CPU 时间。反之Nice 值越高,进程的优先级就越低,获得的 CPU 时间也就越少。\n在 Linux 系统中,你可以使用 nice 和 renice 命令来设置和修改进程的优先级。以下是它们的使用方法:\n# PID 是想要修改的进程的进程 ID可以使用 ps 或 top 命令来查看进程的 PID\n# 使用 nice 命令启动一个新进程,设置其 Nice 值为 10\nnice -n 10 command\n \n# 使用 nice 命令启动一个新进程,设置其 Nice 值为 -5\nnice -n -5 command\n \n# 将 PID 为 1234 的进程的 Nice 值设为 10\nrenice 10 -p 1234\n \n# 将 PID 为 5678 的进程的 Nice 值设为 -5\nrenice -5 -p 5678\n进程管理命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述ps显示当前进程的快照。top动态显示进程状态可以实时查看系统中各个进程的资源占用情况。htop与 top 类似但提供了一个更美观、更友好的界面以及额外的功能如垂直和水平滚动。pgrep根据条件查找进程并列出匹配条件的进程 ID。pkill发送信号到匹配条件的进程常用于终止进程。kill发送信号到特定的进程最常用于终止进程。killall根据进程的名称来终止一组进程。nice启动一个进程并设置其优先级。优先级较低的进程运行得较慢从而减少对系统资源的占用。renice修改已经运行的进程的优先级。nohup运行命令使其可以在用户注销后继续运行。jobs显示当前会话中的所有作业及其状态。bg将一个在后台暂停的作业恢复执行。fg将一个在后台运行的作业调到前台继续运行。&在命令后添加 & 可以让命令在后台运行。disown将作业从当前会话的作业列表中移除使得该作业不会在会话结束时被终止。\n服务管理\n服务的概念\n在 Linux 环境中服务也被称为守护进程是一个关键概念指的是一种在后台运行的程序或一组程序这些程序在用户的视觉范围之外不断地提供某些特定的功能或服务。例如web 服务器(如 Apache数据库服务器如 MySQL邮件服务器SSHFTP 等都属于典型的服务。这些服务是操作系统正常运行的重要组成部分,负责处理各种系统任务和应用请求。\n服务管理则是操作系统中的一项重要任务其主要目标是保证服务能够稳定、高效地运行同时也能够便捷地进行服务的配置和维护。为了达到这个目标人们设计了许多不同的服务管理系统例如 SysV initUpstart以及现在广泛使用的 Systemd。\n服务管理\nSystemd\nsystemd 是当前大多数 Linux 发行版中默认的初始化系统和服务管理器,由 Lennart Poettering 和 Kay Sievers 在 Freedesktop.org 项目中创建。它的主要任务是负责系统的引导流程,以及在系统运行期间管理和维护各种服务。\n与传统的 SysV init 和 Upstart 等系统相比systemd 提供了许多高级特性。其中一个主要特点就是并行化处理能同时启动多个服务大大提高了系统启动的速度。此外systemd 还支持按需启动服务,即只有在服务被需要时才启动。这些特性加上实时系统状态查看,服务依赖管理,系统资源控制等,使得 systemd 能为用户提供现代化的、高效的、全面的解决方案。\n**systemd 还提供了一种新的系统配置方法,即使用 systemd 单元unit文件。**这些单元文件用于定义服务、设备、挂载点、套接字等对象的属性和行为。单元文件是纯文本文件,易于编辑,支持灵活的配置选项。\n除了基本的初始化服务**systemd 还提供了进程监控、日志管理、设备管理、网络配置、用户会话管理等多项功能。**特别是通过日志管理工具 journald实现了全面的日志管理功能。journald 可以收集各种类型的日志信息,包括内核日志、系统服务日志、用户程序日志等,然后将它们统一存储在一个中央日志库中,便于用户查阅和管理。\n尽管 systemd 具有诸多优点,但由于其庞大和复杂,也引来了不少批评。一些人认为 systemd 违反了 Unix 哲学——” 做一件事,并把它做好 “,它的功能太过全面,违反了模块化设计的原则。然而,也有很多人认为,对于现代 Linux 系统来说 systemd 是必不可少的。\n以下是一些 systemd 中常用的 systemctl 命令示例:\n# 启动一个服务\nsystemctl start [service_name]\n \n# 停止一个服务\nsystemctl stop [service_name]\n \n# 重启一个服务\nsystemctl restart [service_name]\n \n# 查看一个服务的状态\nsystemctl status [service_name]\n \n# 设置一个服务在系统启动时自动启动\nsystemctl enable [service_name]\n \n# 禁止一个服务在系统启动时自动启动\nsystemctl disable [service_name]\n常用的选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明--user对用户级别的服务进行操作而不是系统级别的服务--global对所有用户的用户级别的服务进行操作--system对系统级别的服务进行操作这是默认的操作级别--all显示所有的服务包括未启动的和不活跃的服务--failed显示启动失败的服务-H [user@]hostname对远程主机上的服务进行操作--no-pager不使用分页显示输出结果\n总的来说systemd 是一种强大的初始化系统和服务管理器,它改变了 Linux 系统的启动方式和服务管理方式,带来了许多新的可能性和便利性。如果你正在使用的是一个现代的 Linux 发行版,那么你很可能已经在使用 systemd 了。\nUpstart\nUpstart 是一种为 Linux 系统设计的事件驱动的初始化系统和服务管理器,由 Canonical 公司的 Scott James Remnant 开发,最初用于 Ubuntu 发行版。它的设计初衷是用于取代传统的 SysV init 系统,并且解决其在处理现代化计算环境中的并发性和动态性时的局限性。\nUpstart 的主要特点是事件驱动Event-Driven它可以根据系统事件比如硬件添加或者删除服务状态变化等来动态地启动或停止服务。这种设计使得 Upstart 能够灵活地适应不同的系统状态,并确保相关的服务在适当的时机和顺序下启动。\n此外Upstart 还支持并行启动服务,这大大提高了系统启动的速度。它还具有服务状态跟踪功能,可以在服务异常退出时自动重启服务,从而提高系统的可靠性。\nUpstart 使用的服务配置文件称为 Job 文件这些文件定义了一个服务的启动条件、停止条件、脚本等信息。Job 文件是纯文本文件,位于 /etc/init 目录下,易于编辑和管理。\n以下是一些 Upstart 中常用的 initctl 命令示例:\n# 启动一个服务\ninitctl start [job_name]\n \n# 停止一个服务\ninitctl stop [job_name]\n \n# 重启一个服务\ninitctl restart [job_name]\n \n# 查看一个服务的状态\ninitctl status [job_name]\n常用的选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明list列出所有已知的任务和服务show-config显示指定任务或服务的所有配置信息emit发出一个事件可以触发相关的任务和服务reload-configuration重新加载所有的任务和服务的配置文件\n尽管 Upstart 在其出现时提供了一种新颖和强大的初始化和服务管理方式,但由于其开发和维护的复杂性,以及后来 systemd 的出现Upstart 在许多 Linux 发行版中被 systemd 替代。然而,了解 Upstart 仍然是有益的,因为有些旧的系统或特定的场景可能仍然在使用它。\nSysV Init\nSysV init 是 Unix System V 中的初始化系统,长期以来在各种 Unix-like 系统中使用,包括早期的 Linux 发行版。它主要负责在系统启动时启动各种服务,以及在系统运行期间管理和维护各种服务。\nSysV init 的主要特点是顺序启动服务。它依赖于在 /etc/inittab 文件中定义的运行级别runlevels并在每个运行级别中按照预定义的顺序启动或停止服务。这种设计简单可靠但在处理现代化计算环境中的并发性和动态性时表现出一定的局限性。\n在 SysV init 系统中,服务的启动脚本通常位于 /etc/init.d/ 目录下,而各个运行级别的服务链接则位于 /etc/rc.d/ 或 /etc/rc[runlevel].d/ 目录下。这种设计使得服务配置分散在多个文件和目录中,管理相对较复杂。\n以下是一些 SysV init 中常用的命令示例:\n# 启动一个服务\n/etc/init.d/[service_name] start\n \n# 停止一个服务\n/etc/init.d/[service_name] stop\n \n# 重启一个服务\n/etc/init.d/[service_name] restart\n \n# 查看一个服务的状态\n/etc/init.d/[service_name] status\n \n# 切换运行级别\ninit [runlevel]\n常用的运行级别\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运行级别说明0关机1单用户模式2多用户模式没有网络服务3多用户模式有网络服务4未定义可以由用户自定义5多用户模式有网络服务和图形用户界面6重启\n尽管 SysV init 系统在设计上有一些局限性,但其简单和可靠的特点使得它在许多年里得到了广泛的使用。然而,随着现代 Linux 系统的发展,更多的发行版开始选择如 Upstart 或 systemd 这样的现代化的初始化系统和服务管理器。\n未来发展\n随着云计算、容器技术、微服务等新技术的发展服务管理面临着新的挑战和机遇。在这样的环境下服务管理不仅要考虑如何管理单个系统上的服务还需要考虑如何在分布式环境中协调和管理多个服务。这可能需要新的管理策略和工具或者是现有工具的深度集成和优化。\n例如随着 Kubernetes 这样的容器编排工具的普及,服务的生命周期管理和调度已经可以通过这些工具来完成。在这种情况下,传统的服务管理器可能需要与 Kubernetes 等工具进行深度整合,以便更好地在微服务环境中管理服务。\n另一方面新的服务管理工具和框架也正在不断出现比如用 Go 语言编写的 supervisord或者是由 Uber 开发的 Peloton。这些工具都试图在特定环境下提供更好的服务管理能力。\n总的来说服务管理是一个重要且不断发展的领域。随着新技术的发展我们期待看到更多的创新和进步以帮助我们更好地管理和维护系统服务。"},"Technology/OperatingSystem/Linux/5.安全配置/Linux-系统安全与防护":{"title":"Linux 系统安全与防护","links":[],"tags":["Linux/进阶","技术/操作系统"],"content":"基本概念和原则\n系统安全的基本目标是保护信息系统的可用性确保数据的机密性和完整性同时预防、检测和应对各种形式的威胁。这涵盖了多个层次包括物理安全、网络安全、操作系统安全、应用安全以及人为因素等。其核心的目标是防止未经授权的访问、使用、披露、破坏、修改、检查或干扰。\n理解系统安全的关键原则是掌握其核心理念并将其应用于实际安全策略和操作中。以下是一些基本原则\n\n最小权限原则只给用户或程序足够的权限让他们完成任务无需多余的权限。这样如果有人或某程序想要滥用权限他们的破坏范围也会被限制在最小。\n防御深度原则在系统的每一层都设置防御措施从物理设备到网络再到软件。这样如果有人攻击他们需要一层一层地突破防线增加了攻击的难度。\n故障隔离原则如果系统的一部分出现问题其他部分不会受到影响。这样可以防止问题扩大化保护整个系统的稳定。\n开放性设计原则不通过隐藏信息来保证系统安全而是通过优秀的设计和实现来保护系统。哪怕攻击者知道系统的全部信息也找不到破绽。\n安全生命周期管理原则从设计到废弃整个过程都要考虑安全性。每一步都不能忽视否则可能会留下安全隐患。\n复杂性是敌人原则系统越复杂安全隐患就越多也越难管理。所以应该尽量使系统简单避免不必要的复杂性。\n默认拒绝原则除非明确允许否则一律拒绝。这样可以避免未知的威胁增强系统的安全性。\n\n常见的威胁和攻击\n在我们的日常生活中信息系统可能会面临各种形式的威胁和攻击。以下是对常见的威胁和攻击类型进行的详细解释\n\n恶意软件Malware这是一个广泛的类别包括许多类型的恶意软件。其中包括\n\n病毒这是一种自我复制的恶意代码它可以附着在其他程序上并在这些程序运行时执行。病毒可能会删除或修改文件或者对系统造成其他形式的破坏。\n蠕虫蠕虫与病毒类似都是自我复制的恶意代码。然而与病毒不同的是蠕虫可以自我复制并在网络中传播无需附着在其他程序上。\n特洛伊木马这是一种伪装成合法程序的恶意软件它可以提供一个后门让攻击者远程控制受感染的计算机。\n勒索软件这种类型的恶意软件会对用户的文件或系统进行加密并要求用户支付赎金以获取解密密钥。近年来勒索软件的使用日益普遍并已对许多个人和组织造成了重大影响。\n\n\n网络攻击这个类别包括各种利用网络进行的攻击\n\n分布式拒绝服务DDoS这种攻击涉及使用大量的计算机通常是通过恶意软件感染的计算机组成的僵尸网络向目标发送大量的网络流量从而使目标的网络服务变得不可用。\n嗅探这种攻击涉及监听网络通信以窃取敏感信息如密码或信用卡号。\n欺骗这种攻击涉及伪装成另一个系统或用户以获取敏感信息或进行其他形式的欺诈行为。\n会话劫持这种攻击涉及接管用户的网络会话以便在没有用户知情的情况下代替用户进行操作。\n\n\n身份欺诈和权限提升这个类别的攻击涉及尝试以某种方式绕过系统的认证机制\n\n身份欺诈这种攻击涉及伪装成另一个用户以获得其在系统中的权限。这通常涉及某种形式的密码破解或欺骗。\n权限提升这种攻击涉及利用系统的漏洞或配置错误以提升攻击者在系统中的权限。这通常涉及利用系统或应用程序的漏洞。\n\n\n社会工程攻击这个类别的攻击涉及利用人类的信任和习惯进行欺骗\n\n钓鱼攻击这种攻击涉及发送伪装成来自合法组织如银行或邮件服务商的电子邮件以诱使用户提供他们的用户名和密码。\n预言攻击这种攻击涉及利用用户的可预测性如使用弱密码或在多个网站使用同一密码来猜测他们的密码。\n垃圾邮件这种攻击涉及发送大量的垃圾邮件以诱使用户点击恶意链接或提供他们的个人信息。\n\n\n\nLinux 安全性设置和机制\nSELinux\nSELinuxSecurity-Enhanced Linux是一个强大的 Linux 内核安全模块用于实现访问控制安全策略。它通过强制访问控制MAC限制用户和进程对系统资源的访问从而提高系统安全性。\nSELinux 的起源可以追溯到 1998 年当时美国国家安全局NSA与安全系统研究小组SFR共同开发了一个名为 Flask 的安全架构。该架构的目标是为操作系统提供一种强大且灵活的访问控制机制。在 2000 年NSA 将 Flask 架构集成到 Linux 内核中,从而诞生了 SELinux。\nSELinux 的开发过程受到了开源社区的广泛支持。Red Hat 在 2003 年发布的 Red Hat Enterprise Linux 4RHEL 4中首次将 SELinux 作为默认安全模块。此后,许多其他 Linux 发行版,如 CentOS、Fedora 和 Gentoo也开始支持 SELinux。\nSELinux 的实现是通过 Linux 内核安全模块LSM框架这使得内核能够支持额外的安全策略。在 SELinux 中,安全策略和安全上下文标签用于对进程和对象进行访问控制。这种访问控制不仅基于传统的 UNIX 文件权限也考虑了诸如进程类型、文件类型等其他因素从而提供更强大的安全保护。同时SELinux 的安全策略规则集定义了允许的操作、角色和类型。这些规则集能够提供详尽的权限设置,进一步强化了系统的安全性。\nSELinux 目前的发展方向主要集中在以下几个方面:\n\n**提高安全性:**SELinux 将继续优化安全策略提高系统安全性。例如通过引入更多安全策略类型如基于属性的访问控制ABAC以满足不断变化的安全需求。\n**简化配置和管理:**尽管 SELinux 的学习曲线较陡,但它将继续努力简化安全策略的配置和管理,以便降低使用门槛。\n**性能优化:**SELinux 将持续改进性能,以减轻其对系统性能的影响,同时确保高度安全性。\n**社区合作与支持:**SELinux 将继续与开源社区合作,共同推动 Linux 安全模块的发展和完善。此外,它将继续提供支持和培训,帮助用户更好地理解和应用 SELinux。\n\n运行模式\n**SELinux 的运行模式主要有两种Targeted 和 Strict。**在 Targeted 模式中,只有被标记为需要保护的进程会受到 SELinux 的管控,其余的进程则运行在传统的 Linux 访问控制下。而在 Strict 模式下,所有的进程都会受到 SELinux 的管控。这两种模式提供了灵活性,使得用户可以根据他们的具体需求选择适合的模式。\n优缺点\n\n提供详细的安全策略和访问控制支持多种安全策略如基于角色的访问控制RBAC和类型强制访问控制TE等。\n通过强制访问控制MAC限制用户和进程对系统资源的访问从而提高系统安全性。\n被广泛应用于许多 Linux 发行版,如 Red Hat Enterprise Linux (RHEL)、CentOS 和 Fedora 等。\n完全集成在内核中提供强大的安全保护。\n\nSELinux 的缺点包括配置和学习复杂,性能开销较大。因此,**它更适用于高度安全要求的环境,如政府、金融和敏感数据处理等场景。**在这些场合SELinux 能够提供强大且灵活的安全策略,以满足不同的安全需求。\n常用命令\n\nEnforcing在此模式下**SELinux 会执行所有安全策略并强制访问控制。**如果发现违反了安全策略SELinux 将阻止访问并在审计日志中记录相关信息。这是 SELinux 的默认模式,旨在提供最高级别的系统安全保护。\nPermissive在此模式下**SELinux 不会阻止任何违反安全策略的操作,但仍会在审计日志中记录违规行为。**这种模式通常用于调试和排错,因为它允许管理员了解哪些操作可能被阻止,同时不会对系统造成实际影响。\nDisabled在此模式下**SELinux 完全禁用,不会执行任何安全策略。**所有操作都将按照传统的 Linux 访问控制(如文件权限和所有者)进行,而不受 SELinux 的影响。这种模式可能会降低系统安全性,因此不推荐在生产环境中使用。\n\n# 显示当前 SELinux 状态和概述\nsudo sestatus\n \n# 显示当前 SELinux 模式enforcing, permissive, disabled\nsudo getenforce\n \n# 设置 SELinux 模式0 = permissive, 1 = enforcing\nsudo setenforce 1\n \n# 更改文件或目录的 SELinux 上下文\nsudo chcon -t httpd_sys_content_t /var/www/html\n \n# 恢复文件或目录的默认 SELinux 上下文\nsudo restorecon -Rv /var/www/html\n \n# 管理 SELinux 的配置、布尔值、上下文等\nsudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"\n \n# 搜索和分析 SELinux 的审计日志\nsudo ausearch -m AVC\n \n# 从审计日志生成 SELinux 策略模块\nsudo audit2allow -a -M my_new_module\n \n# 管理 SELinux 策略模块\nsudo semodule -i my_new_module.pp\nAppArmor\nAppArmorApplication Armor是一种 Linux 安全模块目标是保护应用程序免受潜在威胁。AppArmor 通过强制访问控制MAC限制应用程序对系统资源的访问以此增强系统的安全性。AppArmor 的安全策略配置相对简单,易于理解和配置,这主要得益于它基于路径的访问控制方式。\nAppArmor 于 1998 年诞生,最初由 Immunix 公司开发,旨在为 Linux 系统提供一个易于管理且高效的安全解决方案。2005 年Novell 收购了 Immunix 公司,并在同年将 AppArmor 开源。从那时起AppArmor 成为了一个独立的开源项目,吸引了众多开发者和维护者的加入。\n2007 年AppArmor 成为 Ubuntu 7.10Gutsy Gibbon的默认安全模块。之后其他 Linux 发行版,如 openSUSE 和 Debian也开始支持 AppArmor。作为一种与 SELinux 并行的 Linux 安全模块AppArmor 在易用性和性能上表现出了明显的优势,这使得它在个人电脑和服务器领域得到了广泛应用。\nAppArmor 的实现是通过 Linux 内核安全模块LSM框架这使得内核能够支持额外的安全策略。在 AppArmor 中基于路径的访问控制策略被用来控制应用程序的访问权限。此外通过简单的文本策略文件AppArmor 可以定义允许的操作、文件访问权限等,进一步简化了策略配置和管理。\nAppArmor 目前的发展方向主要集中在以下几个方面:\n\n**简化策略配置和管理:**AppArmor 将继续简化安全策略的配置和管理,使其更易于使用和部署。\n**提升性能:**AppArmor 会持续优化其性能,以满足日益增长的系统安全需求,并尽量减少性能开销。\n**扩展功能和支持:**AppArmor 将继续扩展其功能,支持更多的 Linux 发行版和应用场景。同时,也可能引入新的安全机制,以增强其安全性能。\n社区合作AppArmor 将继续与开源社区紧密合作,共同推动 Linux 安全模块的发展和完善。\n\n优缺点\n\n**策略配置相对简单:**AppArmor 的访问控制策略基于路径,这使得策略配置易于理解和配置。\n增强系统安全性通过限制应用程序对文件系统和其他资源的访问AppArmor 能够有效增强系统的安全性。\n广泛应用于各种 Linux 发行版AppArmor 已被多种 Linux 发行版如 Ubuntu、openSUSE 和 Debian 所支持和使用。\n策略隔离良好AppArmor 可以针对单个应用程序进行策略配置,从而实现策略的隔离。\n低性能开销相较于其它一些安全模块AppArmor 的性能开销较低。\n\n虽然 AppArmor 在许多方面表现出色但它也存在一些缺点。例如其安全策略相对简单可能无法满足某些高度安全要求的场景。另外AppArmor 不支持基于角色的访问控制。因此,**AppArmor 更适合于安全要求一般的环境,例如个人电脑和服务器等场景。**在这些场景中AppArmor 可以提供简单而实用的安全策略,帮助用户有效地保护系统资源和数据。\n常用命令\n# 显示当前 AppArmor 状态和概述\nsudo apparmor_status\n \n# 设置指定配置文件为强制模式enforce\nsudo aa-enforce /etc/apparmor.d/usr.bin.firefox\n \n# 设置指定配置文件为投诉模式complain\nsudo aa-complain /etc/apparmor.d/usr.bin.firefox\n \n# 禁用指定配置文件\nsudo aa-disable /etc/apparmor.d/usr.bin.firefox\n \n# 生成指定程序的 AppArmor 配置文件\nsudo aa-genprof /usr/bin/firefox\n \n# 分析日志,根据需求更新 AppArmor 配置文件\nsudo aa-logprof\n \n# 自动生成 AppArmor 配置文件的依赖项\nsudo aa-autodep /usr/bin/firefox\n \n# 清理无用的配置文件\nsudo aa-cleanprof\n \n# 列出未受 AppArmor 限制的进程\nsudo aa-unconfined\nSELinux 与 AppArmor 对比\nSELinuxSecurity-Enhanced Linux和 AppArmorApplication Armor都是为 Linux 系统设计的安全模块用于实现访问控制安全策略以增强系统安全性。尽管它们都提供了用于增强系统安全性的强制访问控制MAC机制但每个框架都有其自己的优点和缺点使其适用于不同的场景。\n以下是 SELinux 和 AppArmor 的一些主要对比点:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性 / 安全模块SELinuxAppArmor优点详细的安全策略和访问控制支持多种安全策略策略配置简单基于路径的访问控制较低的性能开销缺点配置和学习复杂性能开销较大安全策略相对简单不支持基于角色的访问控制适用场景高度安全要求的环境例如军事或政府机构一般安全要求的环境例如个人电脑和服务器等发行版本RHEL、CentOS、Fedora 等Ubuntu、openSUSE、Debian 等学习曲线陡峭,需要深入理解 SELinux 的安全策略平缓,基于路径的策略使得配置更为简单性能影响可能较大,尤其是在处理大量文件访问时通常较小,对性能的影响比 SELinux 小策略灵活性高,支持多种类型的安全策略,包括 RBAC 和 MLS较低主要支持基于路径的访问控制支持的访问控制支持类型强制、角色基础访问控制和多级安全主要是基于路径的访问控制安全策略管理涉及许多配置文件策略更复杂使用简单的文本策略文件更易于管理和配置\n总的来说选择 SELinux 还是 AppArmor 取决于特定的需求和环境。如果需要一个强大而精细的安全策略,那么 SELinux 可能是更好的选择。然而,如果优先考虑易用性和性能,那么 AppArmor 可能更适合。\nTCP Wrappers\nTCP WrappersTCP 包装器是一个开源的网络服务请求过滤系统用于实现主机基础的网络访问控制列表ACL。它通过使用访问控制文件来限制客户端对服务器资源的访问进而增强服务器的安全性。\nTCP Wrappers 最初由 Wietse Venema 开发,目的是提供一种简单的保护方式,能防止未经授权的访问者对服务器的潜在威胁。这个系统在网络管理员中非常受欢迎,因为它提供了一种简单有效的方式,用于监控和限制对网络服务的访问。\nTCP Wrappers 的核心功能包括访问控制和日志记录:\n\n访问控制TCP Wrappers 可以定义哪些主机或主机组能够访问服务器的某个特定服务。例如,你可以设置一个规则,仅允许来自特定 IP 地址的用户访问你的 SSH 服务。这种访问控制功能通过两个配置文件实现:/etc/hosts.allow 和 /etc/hosts.deny。当一个来自远程主机的请求尝试连接服务器的服务时TCP Wrappers 会首先查看这两个文件,以确定是否允许或拒绝该连接。\n日志记录除了访问控制TCP Wrappers 也可以记录有关远程主机尝试连接服务器的信息。这些日志对于审计、问题诊断和网络管理都非常有用。如果发现有可疑的活动,网络管理员可以快速查看日志,以确定发生了什么,并采取相应的行动。\n\n优缺点\n\n提供简单而有效的访问控制和日志记录功能。\n容易安装和配置。\n可以与其他网络服务如 xinetd 和 inetd配合使用以增强服务器的安全性。\n\n虽然 TCP Wrappers 能够提供一定的网络服务保护,但是,这种保护并不是全方位的。具体来说,只有那些在编译时链接了 libwrap 库的服务才能受到 TCP Wrappers 的保护。此外当面临一些复杂的网络攻击时比如分布式拒绝服务攻击DDoSTCP Wrappers 可能无法提供充分的防护。\n常用命令\n# 编辑 /etc/hosts.allow 文件以允许某个主机或主机组访问一个服务\necho "sshd : 192.168.1.0/255.255.255.0 : allow" >> /etc/hosts.allow\n \n# 编辑 /etc/hosts.deny 文件以拒绝某个主机或主机组访问一个服务\necho "sshd : 192.168.1.0/255.255.255.0 : deny" >> /etc/hosts.deny\n \n# 使用 tcpdchk 命令检查 hosts.allow 和 hosts.deny 文件的语法和逻辑错误\ntcpdchk\n \n# 使用 tcpdmatch 命令模拟来自特定主机的连接请求,看它是否会被允许或拒绝\ntcpdmatch sshd 192.168.1.100\n通过正确地配置和使用 TCP Wrappers你可以大大提高你的服务器的安全性并有能力追踪和控制对你的网络服务的访问。\nAuditd\nAuditd 是 Linux 审计框架的核心组件,用于收集来自内核中的审计记录。它允许系统管理员跟踪在系统上发生的活动,以便在系统安全出现问题时追溯和分析。\nAuditd 的起源可以追溯到 Linux 内核版本 2.6 的早期当时引入了新的审计框架。该框架由内核部分生成审计事件记录和用户空间部分接收和处理这些记录组成。Auditd 就是用户空间部分的主要组件。\n主要功能包括系统调用追踪、文件和目录访问监控、系统启动和关闭日志等。其主要用于帮助管理员诊断问题、满足合规性要求、并提高系统的安全性。\nAuditd 的运行可以通过 service 或 systemctl 命令进行管理如启动service auditd start、停止service auditd stop、查看状态service auditd status等。\nAuditd 可以通过 audit.rules 文件配置审计规则,这些规则定义了应生成哪些类型的审计记录。例如,可以跟踪所有对特定文件的操作,或者监视所有的用户和组管理活动。审计规则的配置需要具有很高的灵活性和精确性,以便系统管理员可以精确地获取他们需要的信息。\n然而auditd 的使用和配置可能会相当复杂,需要一定的专业知识才能有效地使用。\n运行模式\nauditd 的运行模式主要是启动和停止,启动 auditd 后,它将开始收集审计事件并将其记录到日志文件中,通常是 /var/log/audit/audit.log。停止 auditd 后,系统将停止记录审计事件。\n优缺点\n\n提供了详尽的系统活动日志记录可以帮助系统管理员诊断问题、满足合规性要求并提高系统的安全性。\n审计规则的配置具有很高的灵活性和精确性。\n广泛用于许多 Linux 发行版,如 Red Hat Enterprise Linux (RHEL)、CentOS 和 Fedora 等。\n\nauditd 的主要缺点是配置和使用相对复杂,对于新手可能有些困难。\n常用命令\n# 启动 auditd 服务\nsystemctl start auditd\n \n# 停止 auditd 服务\nsystemctl stop auditd\n \n# 显示 auditd 服务状态\nsystemctl status auditd\n \n# 显示当前的审计规则\nauditctl -l\n \n# 监控对 /etc/passwd 文件的写访问和更改属性操作\nauditctl -w /etc/passwd -p wa\n \n# 创建一个审计规则,用于记录所有因权限不足而失败的文件打开尝试\nauditctl -a always,exit -F arch=b64 -S open -F exit=-EACCES -k access_denied\n \n# 搜索今天的所有 SELinux AVC 事件\nausearch -m avc -ts today\n \n# 生成一个包含所有被执行程序的摘要报告\naureport -x --summary\n加密和认证技术\n加密和认证技术对于确保系统安全至关重要。以下是一些常见的加密和认证技术\n\nSSL 和 TLSSSLSecure Sockets Layer和 TLSTransport Layer Security是用于在网络通信中提供安全层的协议。它们用于保护数据的隐私和完整性。TLS 是 SSL 的后续版本,目前更为常用。\nSSHSSHSecure Shell是一种网络协议用于安全地远程连接到服务器。SSH 提供了强大的认证和安全通信功能,包括加密远程会话和传输文件。\nPGPPretty Good PrivacyPGP 是一种数据加密和解密程序,提供加密、解密和数字签名的服务。它常用于保护电子邮件的隐私和完整性,同时也可用于加密文件和存储设备。\n公钥基础设施PKI和证书颁发机构CAPKI 是一套基于公钥密码学的加密体系结构,用于生成、管理和分发数字证书。证书颁发机构是负责验证用户身份并颁发数字证书的可信实体。\n一次性密码OTP和多因素认证MFAOTP 是一种仅限单次使用的密码用于增强身份验证的安全性。MFA 要求用户提供两个或多个不同类型的身份验证因素,例如密码、指纹识别、硬件令牌或手机验证码。\nIPSecInternet Protocol SecurityIPSec 是一组协议和算法用于在网络层提供数据的机密性、完整性和身份验证。它常用于虚拟私有网络VPN和远程访问连接的安全保护。\n数字证书数字证书是由证书颁发机构颁发的电子文件用于验证用户、服务器或组织的身份。数字证书使用公钥密码学来验证身份并可用于安全通信和电子交易。\n访问控制列表ACLACL 是一种用于控制网络设备上的流量的机制。它基于源 IP 地址、目标 IP 地址、协议和端口号等条件来决定数据包的接受或拒绝。\n防火墙防火墙是一种网络安全设备用于监控和控制进出网络的流量。它可以根据预定义的安全策略过滤流量以阻止未经授权的访问和网络攻击。\n单点登录SSOSSO 是一种身份验证机制,允许用户使用单一的凭据(如用户名和密码)访问多个相关系统。这减少了用户需要记住多个凭据的负担,并提供了更方便的身份验证体验。\n加密硬件设备加密硬件设备如硬件安全模块提供了物理级别的安全性用于存储和处理敏感数据、生成和管理密钥并执行加密操作。这些设备通常具有更高的安全性和防护能力。\n双因素认证2FA双因素认证要求用户在登录过程中提供两个或多个不同类型的身份验证凭据如密码、硬件令牌、指纹识别或短信验证码。这提供了更强的身份验证保护即使密码被泄露也能降低风险。\n安全套接层虚拟专用网SSL VPNSSL VPN 是一种通过 SSL/TLS 协议提供远程访问安全性的技术。它允许用户通过加密通道连接到内部网络,并通过认证和授权机制进行访问控制。\n\n综上所述系统安全涉及许多复杂的方面。了解和应用这些基本概念、原则以及正确使用相关工具和技术对于有效保护信息系统免受威胁和攻击至关重要。"},"Technology/OperatingSystem/Linux/6.网络管理/Linux-网络管理":{"title":"Linux 网络管理","links":[],"tags":["Linux/进阶","技术/操作系统"],"content":"网络配置\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n发行版常用网络管理工具网络配置文件路径UbuntuNetworkManager, systemd-networkd/etc/netplan/DebianNetworkManager, systemd-networkd, ifupdown/etc/network/interfacesCentOS/RHELNetworkManager, systemd-networkd, ifcfg/etc/sysconfig/network-scripts/ifcfg-*FedoraNetworkManager, systemd-networkd, ifcfg/etc/sysconfig/network-scripts/ifcfg-*Arch Linuxnetctl/etc/netctl/openSUSENetworkManager, ifup/etc/sysconfig/network/ifcfg-*\n网络概念\n\n**动态主机配置协议DHCP**DHCP 用于自动分配 IP 地址、子网掩码、默认网关等网络参数。\n**静态地址Static IP**静态 IP 是预先分配给设备的固定 IP 地址。\n地址IP网络设备的唯一标识符用于在网络中进行通信。IPv4 地址格式为 xxx.xxx.xxx.xxx例如 192.168.1.10。\n子网掩码NetMask用于划分 IP 地址的网络和主机部分。常见的子网掩码有 255.255.255.0,表示一个 C 类子网。\n网关Gateway连接不同网络的设备通常是路由器。默认网关用于转发网络请求到其他网络段。\n域名系统DNS将域名解析为 IP 地址的服务。常见的 DNS 服务器有 Google 的 8.8.8.8 和 8.8.4.4。\n\nIp\nip 命令是 Linux 系统中用于管理网络设备、地址、路由等网络设置的一个强大工具。它是 iproute2 软件包的一部分,由 Alexey N. Kuznetsov 开发,首次发布于 1999 年。ip 命令的设计目的是替代原有的 ifconfig、route 等传统网络配置工具,提供更灵活、功能强大的解决方案。\n**ip 命令通过 Netlink 套接字与 Linux 内核通信,实现对网络设备、地址、路由等资源的管理。**Netlink 是一种用于在内核和用户空间之间传递信息的通信机制。通过 Netlinkip 命令能够执行各种复杂的网络配置任务。\nip 命令的配置是临时的,仅在当前会话中有效。重启系统或网络服务后,这些配置将会丢失。\n生命周期\nflowchart LR\n A[1. 开始] --> B[2. 显示网络接口信息]\n B --> C[ip addr show]\n B --> D[ip link show]\n B --> E[ip route show]\n \n A --> F[3. 添加 IP 地址]\n F --> G[ip addr add <IP>/<PREFIX> dev <DEVICE>]\n \n A --> H[4. 删除 IP 地址]\n H --> I[ip addr del <IP>/<PREFIX> dev <DEVICE>]\n \n A --> J[5. 修改网络接口状态]\n J --> K[5.1 启用接口]\n K --> L[ip link set dev <DEVICE> up]\n J --> M[5.2 禁用接口]\n M --> N[ip link set dev <DEVICE> down]\n \n A --> O[6. 添加路由]\n O --> P[ip route add <ROUTE> via <GATEWAY>]\n \n A --> Q[7. 删除路由]\n Q --> R[ip route del <ROUTE>]\n \n A --> S[8. 管理邻居条目]\n S --> T[8.1 显示邻居表]\n T --> U[ip neigh show]\n S --> V[8.2 添加邻居条目]\n V --> W[ip neigh add <IP> lladdr <MAC> dev <DEVICE>]\n S --> X[8.3 删除邻居条目]\n X --> Y[ip neigh del <IP> dev <DEVICE>]\n \n A --> Z[9. 刷新 IP 地址]\n Z --> AA[ip addr flush dev <DEVICE>]\n \n A --> AB[10. 监控网络事件]\n AB --> AC[ip monitor all]\n \n A --> AD[11. 显示网络设备统计信息]\n AD --> AE[ip -s link]\n \n A --> AF[12. 查看或设置 MTU 值]\n AF --> AG[12.1 查看 MTU]\n AG --> AH[ip link show dev <DEVICE>]\n AF --> AI[12.2 设置 MTU]\n AI --> AJ[ip link set dev <DEVICE> mtu <MTU>]\n \n A --> AK[13. 显示和修改路由规则]\n AK --> AL[13.1 显示路由规则]\n AL --> AM[ip rule show]\n AK --> AN[13.2 添加路由规则]\n AN --> AO[ip rule add from <SOURCE> table <TABLE>]\n AK --> AP[13.3 删除路由规则]\n AP --> AQ[ip rule del from <SOURCE> table <TABLE>]\n \n A --> AR[14. 创建和管理虚拟接口]\n AR --> AS[14.1 创建虚拟接口]\n AS --> AT[ip link add link <PARENT> name <NAME> type vlan id <ID>]\n AR --> AU[14.2 删除虚拟接口]\n AU --> AV[ip link del <NAME>]\n\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明ip addr show显示网络接口的地址信息ip addr add为网络接口添加 IP 地址ip addr del删除网络接口的 IP 地址ip link show显示网络接口状态ip link set修改网络接口属性ip route show显示路由表ip route add添加路由ip route del删除路由ip neigh show显示邻居表ARP 缓存ip neigh add添加邻居条目ip neigh del删除邻居条目\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明show显示指定类型的网络对象如地址、链接、路由等add添加指定类型的网络对象del删除指定类型的网络对象set修改指定类型的网络对象的属性list列出指定类型的网络对象flush清除指定类型的网络对象monitor监控网络事件-4仅处理 IPv4 地址和路由-6仅处理 IPv6 地址和路由-s输出简化版信息-brief以简洁的格式输出信息-json以 JSON 格式输出信息-details输出详细信息-family指定地址族如 inet、inet6、link 等)-dynamic设置动态属性如动态路由等-permanent设置永久属性如永久地址等\n操作示例\n\n\n查看当前网络接口信息\n$ ip route show\n192.168.101.0/24 dev ens32 proto kernel scope link src 192.168.101.177\n \n$ ip link show\n1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000\n link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000\n link/ether 00:0c:29:99:2f:75 brd ff:ff:ff:ff:ff:ff\n altname enp2s0\n \n$ ip addr show\n1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n inet 127.0.0.1/8 scope host lo\n valid_lft forever preferred_lft forever\n inet6 ::1/128 scope host\n valid_lft forever preferred_lft forever\n2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n link/ether 00:0c:29:99:2f:75 brd ff:ff:ff:ff:ff:ff\n altname enp2s0\n inet 192.168.101.177/24 scope global ens32\n valid_lft forever preferred_lft forever\n\n\n关闭指定网络接口\n$ ip link set dev ens32 down\n注意如果通过 SSH 连接,执行此操作会导致连接断开。\n\n\n配置静态 IP 地址\n$ ip addr add 192.168.101.222/24 dev ens32\n$ ip addr show\n1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n inet 127.0.0.1/8 scope host lo\n valid_lft forever preferred_lft forever\n inet6 ::1/128 scope host\n valid_lft forever preferred_lft forever\n2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n link/ether 00:0c:29:99:2f:75 brd ff:ff:ff:ff:ff:ff\n altname enp2s0\n inet 192.168.101.177/24 scope global ens32\n valid_lft forever preferred_lft forever\n inet 192.168.101.222/24 scope global secondary ens32\n valid_lft forever preferred_lft forever\n\n\n配置网关地址\n$ ip route add default via 192.168.101.1\n\n\n配置 DNS 服务器地址\n$ echo "nameserver 8.8.8.8" > /etc/resolv.conf\n$ echo "nameserver 8.8.4.4" >> /etc/resolv.conf\n\n\n启用网络接口\n$ ip link set dev ens32 up\n\n\nNetworkManager\n**NetworkManager 是由 Red Hat 公司开发的一款用于管理 Linux 操作系统上网络连接的软件。**自 2004 年首次发布以来,它迅速成为 Linux 操作系统中最流行的网络管理工具之一。在 NetworkManager 诞生之前Linux 中的网络管理通常需要通过手动配置网络文件完成,这一过程不仅繁琐且易出错,但随着 NetworkManager 的出现,这一切都变得简单和直观。\nNetworkManager 展现了其在管理网络连接和网络接口方面的核心能力,提供了**一整套综合工具,大大简化了网络设置的复杂性。**用户得以轻松添加、修改、启用或禁用各类网络连接包括有线和无线网络乃至虚拟私人网络VPN。其核心由负责监控和管理网络的后台守护进程、提供直观操作的图形界面以及功能强大的命令行界面组成还包括管理设备驱动和处理连接请求的高效后端服务。\n在用户进行网络设置调整时NetworkManager 自动更新相关配置文件,确保网络设置的一致性和准确性得到坚实保障。借助灵活的插件体系和高效的 D-Bus 通信机制NetworkManager 能够轻松处理多种类型的网络连接,将配置和管理过程自动化,从而提供了一个无缝、直观且高度可靠的网络管理解决方案。\nNmcli\nnmcli 是 NetworkManager 的命令行界面,提供了全面的功能来管理网络。用户可以通过它快速创建、修改和监控网络连接。无论是列出网络设备状态,管理网络连接,设置静态 IP还是管理 VPN 和其他特殊连接nmcli 都能提供强大支持。\nNmtui\n对于那些偏好图形界面或在终端中工作的用户nmtui 提供了一个简单直观的解决方案。这个交互式的文本界面应用使得配置 NetworkManager 控制的网络设置变得轻松。它的直观操作和无需鼠标的特性,使得 nmtui 成为 SSH 会话和终端窗口中理想的网络管理工具。\n生命周期\nflowchart LR\n A[1. 开始] --> B[2. 添加新设备]\n B --> C[3. NetworkManager 识别设备]\n C --> D[4. 查看设备状态]\n D --> E[nmcli device show]\n \n C --> F[5. 配置网络连接]\n F --> G[5.1 配置 DHCP]\n G --> H[nmcli connection modify <connection-name> ipv4.method auto]\n F --> I[5.2 配置静态 IP]\n I --> J[nmcli connection modify <connection-name> ipv4.addresses <ip-address>/<subnet-mask> ipv4.gateway <gateway-address> ipv4.dns <dns-address> ipv4.method manual]\n \n F --> K[5.3 配置 Wi-Fi]\n K --> L[5.3.1 扫描 Wi-Fi 网络]\n L --> M[nmcli device wifi rescan]\n K --> N[5.3.2 显示 Wi-Fi 网络]\n N --> O[nmcli device wifi list]\n K --> P[5.3.3 连接 Wi-Fi 网络]\n P --> Q[nmcli device wifi connect <SSID> password <password>]\n \n C --> R[6. 激活网络连接]\n R --> S[nmcli connection up <connection-name>]\n \n C --> T[7. 管理现有连接]\n T --> U[7.1 查看现有连接]\n U --> V[nmcli connection show]\n T --> W[7.2 修改现有连接]\n W --> X[nmcli connection modify <connection-name> ...]\n T --> Y[7.3 删除现有连接]\n Y --> Z[nmcli connection delete <connection-name>]\n \n C --> AA[8. 监控和调试]\n AA --> AB[8.1 监控网络状态]\n AB --> AC[nmcli general status]\n AA --> AD[8.2 监控连接状态]\n AD --> AE[nmcli connection show --active]\n \n C --> AF[9. 禁用设备]\n AF --> AG[nmcli device disconnect <device-name>]\n \n AG --> AH[10. 设备生命周期结束]\n\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明nmcli dev show显示所有网络设备的信息nmcli conn show显示所有网络连接的信息nmcli conn up启用指定的网络连接nmcli conn down禁用指定的网络连接nmcli conn add添加一个新的网络连接nmcli conn modify修改一个已有的网络连接nmcli conn delete删除一个已有的网络连接nmcli connection edit编辑一个已有的网络连接nmcli device wifi显示所有 Wi-Fi 网络及其相关信息nmcli device wifi rescan重新扫描 Wi-Fi 网络列表nmcli device wifi connect连接指定的 Wi-Fi 网络\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项说明-f—format指定输出格式例如 csv、json、tabular 等)-t—terse指定分隔符-m—mode指定最大输出宽度用于长文本的换行-p—set-property指定要修改的属性-a—add添加新的属性-r—remove删除一个属性-e—enable激活一个属性-d—disable禁用一个属性-v—verbose输出详细信息-i—ignore-case忽略大小写\n操作实例\n\n\n查看当前网络接口信息\n# 显示所有网络设备的信息\nnmcli device show\n\n\n配置静态 IP 地址\n注意如果当前已经有一个 DHCP 分配的 IP 地址,则需要首先释放该地址。\n# 释放 DHCP 分配的 IP 地址\nnmcli connection modify ens160 ipv4.method auto\n \n# 为指定网络接口配置静态 IP 地址\nnmcli connection modify ens160 ipv4.addresses 192.168.101.123/24 ipv4.gateway 192.168.101.1 ipv4.dns 114.114.114.114 ipv4.method manual\n\n\n激活新的网络配置\n# 激活新的网络配置\nnmcli connection up ens160\n\n\n连接到 Wi-Fi 网络\n# 重新扫描 Wi-Fi 网络列表\nnmcli device wifi rescan\n \n# 显示所有 Wi-Fi 网络及其相关信息\nnmcli device wifi list\n \n# 连接指定的 Wi-Fi 网络\nnmcli device wifi connect <SSID> password <password>\n\n\n添加新的网络连接\n# 添加一个新的以太网连接\nnmcli connection add type ethernet ifname eth0 con-name static-eth0 autoconnect yes ip4 192.168.1.100/24 gw4 192.168.1.1 ipv4.dns 8.8.8.8\n\n\n删除网络连接\n# 删除一个已有的网络连接\nnmcli connection delete static-eth0\n\n\n查看和管理 VPN 连接\n# 显示活动的 VPN 连接\nnmcli connection show --active\n \n# 添加一个新的 OpenVPN 连接\nnmcli connection import type openvpn file <path-to-ovpn-file>\n \n# 激活 VPN 连接\nnmcli connection up <vpn-connection-name>\n \n# 禁用 VPN 连接\nnmcli connection down <vpn-connection-name>\n\n\n网络管理\nIptables\niptables 是 Linux 系统中的一个命令行防火墙工具它允许系统管理员配置内核防火墙netfilter规则。它主要用于数据包过滤、网络地址转换NAT和数据包修改。由于 iptables 在内核空间运行,能够为内核提供强大的防火墙和网络处理功能。\niptables 由 Rusty Russell 在 1998 年创建,最初作为 ipchains 的替代品发布。它是 netfilter 项目的一部分,该项目的目标是提供一套丰富且可靠的防火墙和路由工具。\n架构图\n在 iptables 的规则体系中,存在一个重要的概念叫做四表五链。这些表和链提供了 iptables 进行包过滤和处理的基础架构。\ngraph TB\n subgraph 四表\n A[filter]\n B[nat]\n C[mangle]\n D[raw]\n end\n\n subgraph 五链\n E[INPUT]\n F[OUTPUT]\n G[FORWARD]\n H[PREROUTING]\n I[POSTROUTING]\n end\n\n A --> E\n A --> F\n A --> G\n\n B --> H\n B --> F\n B --> I\n\n C --> H\n C --> E\n C --> G\n C --> F\n C --> I\n\n D --> H\n D --> F\n\n四表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n表名用途关联的链filter数据包过滤INPUT、FORWARD、OUTPUTnat网络地址转换NATPREROUTING、OUTPUT、POSTROUTINGmangle数据包修改PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTINGraw配置连接追踪豁免PREROUTING、OUTPUT\n五链\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n链名用途INPUT处理进入本机的数据包OUTPUT处理本机产生的数据包FORWARD处理经过本机转发的数据包PREROUTING在路由决策之前处理进入系统的数据包POSTROUTING在路由决策之后处理离开系统的数据包\n尽管 iptables 强大且灵活但也有一些缺点。例如iptables 的配置较为复杂,需要花费较多的时间学习和理解。\n此外iptables 的性能与网络流量和规则数量成正比,大量的规则和网络流量可能会导致性能下降。然而,通过深入理解和恰当配置,管理员可以充分利用 iptables 来建立强大且灵活的网络防火墙。\n随着时间的推移iptables 已经不再是 Linux 系统中唯一的防火墙解决方案。在最近的 Linux 发行版中nftables 开始替代 iptables 成为默认的防火墙工具。nftables 提供了与 iptables 类似的功能,但具有更优的性能和更简洁的语法。\n尽管如此iptables 仍然广泛用于很多系统中,并且由于其强大和灵活的特性,仍然是许多系统管理员的首选工具。\n常用命令\n# 列出所有防火墙规则\nsudo iptables -L\n \n# 添加一条新的规则\nsudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT\n \n# 删除一条规则\nsudo iptables -D INPUT 1\n \n# 清空所有规则\nsudo iptables -F\n \n# 设置默认策略\nsudo iptables -P INPUT DROP\n \n# 创建新的链\nsudo iptables -N LOGGING\n \n# 删除一个空链\nsudo iptables -X LOGGING\n \n# 在链中插入一条规则\nsudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT\n \n# 替换链中的一条规则\nsudo iptables -R INPUT 1 -p tcp --dport 80 -j ACCEPT\n \n# 列出所有规则的详细信息\nsudo iptables -S\n \n# 列出规则,不解析服务名称\nsudo iptables -n -L\n \n# 保存 iptables 规则\nsudo iptables-save > /etc/iptables/rules.v4\n \n# 恢复 iptables 规则\nsudo iptables-restore < /etc/iptables/rules.v4\nNftables\nnftables (Netfilter tables) 是一种 Linux 内核的包过滤框架,它是 iptables、ip6tables、arptables、ebtables 等工具的替代品旨在提供单一、统一的解决方案以简化包过滤和防火墙的配置。nftables 提供了一个新的、更高级的语法,用于更简洁、更直观地定义和管理规则。\nnftables 于 2014 年作为 Linux 内核 3.13 的一部分首次发布。它由同样也是 iptables 创建者的 Netfilter 项目团队开发,主要目的是解决 iptables 在易用性和性能上的一些问题。新的框架是为了改善和扩展现有的过滤系统,提供更强大的网络数据包处理能力。\n架构图\ngraph TD\n A[Netfilter框架] --> B[nftables核心]\n B --> C[用户空间工具nft]\n B --> D[Netlink接口]\n B --> E[内核模块nftables]\n C --> F[命令行接口]\n C --> G[规则定义文件]\n D --> H[配置和管理]\n E --> I[数据包处理]\n I --> J[规则匹配]\n I --> K[动作执行]\n J --> L[过滤]\n J --> M[网络地址转换NAT]\n J --> N[数据包修改]\n K --> O[接受]\n K --> P[丢弃]\n K --> Q[重定向]\n\n subgraph "用户空间"\n F\n G\n end\n\n subgraph "内核空间"\n H\n I\n L\n M\n N\n O\n P\n Q\n end\n\nnftables 提供了一种新的、基于 Netlink 的接口,用于配置网络过滤规则。它还提供了一种新的语法,用于定义过滤规则。这种语法更加简洁、直观,比 iptables 的语法更易于学习和使用。与 iptables 相比nftables 还有一些其他的优点。例如,它能更高效地处理大量的规则,支持更多的数据类型和操作符,提供更强大的过滤和分类功能,支持动态更新规则等等。\n核心特性\n\n更简洁、更直观的语法nftables 的语法比 iptables 的语法更简洁、更直观,更易于学习和使用。\n更高的性能nftables 能更高效地处理大量的规则,对性能的影响较小。\n更强大的功能nftables 支持更多的数据类型和操作符,提供更强大的过滤和分类功能,支持动态更新规则。\n替代多种工具nftables 可以替代 iptables、ip6tables、arptables、ebtables 等工具,提供一个统一的解决方案。\n使用新技术作为一种新的包过滤框架nftables 使用了许多新的技术和接口,这可能需要一些学习和适应。\n\n尽管 nftables 在许多方面都优于 iptables但它也存在一些问题。例如它的语法和接口与 iptables 不兼容,这可能导致一些旧的脚本和工具无法正常工作。此外,由于 nftables 是相对较新的技术,可能还存在一些 bug 或不稳定的问题。\n总的来说nftables 是一种强大而灵活的网络过滤框架,它提供了许多 iptables 所不具备的特性和优点。它的目标是简化网络过滤和防火墙的配置,提供更高的性能,支持更多的功能,使得网络管理员能够更有效地管理他们的网络。\n常用的命令\n# 显示当前已定义的所有表\nnft list tables\n \n# 添加一个新表,表名为 "mytable",表类型为 "ip"\nnft add table ip mytable\n \n# 列出在表 "mytable" 下的 "mychain" 中定义的所有链\nnft list chain ip mytable mychain\n \n# 在表 "mytable" 下添加一个新链 "mychain",并设置链的类型为 "filter"hook 为 "input",优先级为 0\nnft add chain ip mytable mychain { type filter hook input priority 0 \\; }\n \n# 在 "mychain" 中添加一个新规则,如果源 IP 地址是 192.0.2.1,则丢弃该包\nnft add rule ip mytable mychain ip saddr 192.0.2.1 drop\n \n# 列出所有已定义的规则集\nnft list ruleset\n \n# 删除在 "mychain" 中的 handle 是 1 的规则\nnft delete rule ip mytable mychain handle 1\n \n# 清空指定链 "mychain" 中的所有规则\nnft flush chain ip mytable mychain\n \n# 删除指定链 "mytable" 中的 "mychain"\nnft delete chain ip mytable mychain\n \n# 删除指定表 "mytable"\nnft delete table ip mytable\nUfw\nufwUncomplicated Firewall是一种简洁的防火墙配置工具专门为 Linux 设计。 该工具的主要目标是简化 iptables 防火墙配置的复杂性并提供一个用户友好的界面以便于用户进行操作和管理。UFW 是由 Ubuntu 开发的,但它也能在其他的 Linux 发行版上使用。\nUFW 的功能主要是通过控制网络流量来提供安全防护。用户可以设置防火墙规则,来允许或拒绝某个 IP 地址、端口或服务的入站或出站流量。同时UFW 也支持 IPv6这样可以满足现代网络环境的需求。\n架构图\ngraph TD\n subgraph ufw\n A[UFW Command Line Interface]\n B[UFW Configuration]\n C[Backend]\n C --> D[iptables/nftables]\n E[Logging]\n F[Applications]\n end\n A --> B\n A --> C\n A --> E\n A --> F\n\n\nUFW Command Line InterfaceUFW 提供了一个简单的命令行界面,通过该界面用户可以方便地管理防火墙规则。\nUFW Configuration配置文件存储了 UFW 的规则和策略,用户可以编辑这些文件以自定义防火墙行为。\nBackend后端UFW 支持两种主要的后端iptables 和 nftables。后端负责实际执行防火墙规则。\nLogging日志UFW 支持日志记录功能,用户可以配置日志级别以监控网络活动。\nApplications应用UFW 支持预配置的应用规则,使用户能够方便地管理常见应用的防火墙规则。\n\n工作流程\nflowchart TD\n A[启动 UFW] --> B[加载配置文件]\n B --> C[设置初始防火墙规则]\n C --> D{用户交互}\n D -->|添加规则| E[更新配置文件]\n D -->|删除规则| F[更新配置文件]\n D -->|修改规则| G[更新配置文件]\n E --> H[应用新规则]\n F --> H[应用新规则]\n G --> H[应用新规则]\n H --> I[日志记录]\n I --> J[监控网络活动]\n\n\n启动当 UFW 启用时,它会加载配置文件,并根据这些配置文件设置初始的防火墙规则。\n规则管理用户可以通过 CLI命令行界面与 UFW 进行交互,添加、删除或修改防火墙规则。\n应用规则UFW 支持预配置的应用规则,用户可以通过简单的命令添加或删除这些规则。\n日志记录用户可以配置 UFW 的日志记录级别,以便监控和调试网络活动。\n持久性配置UFW 的配置文件存储在系统中,可以在重启后自动加载。\n\n常用命令\n# 启用 UFW\nsudo ufw enable\n \n# 禁用 UFW\nsudo ufw disable\n \n# 显示 UFW 状态和规则\nsudo ufw status\n \n# 允许特定端口或服务的流量\nsudo ufw allow 22\n \n# 拒绝特定端口或服务的流量\nsudo ufw deny 22\n \n# 删除特定规则\nsudo ufw delete allow 22\n \n# 设置默认的入站或出站策略\nsudo ufw default deny incoming\n \n# 显示预配置的应用规则\nsudo ufw app list\n \n# 显示特定应用的规则信息\nsudo ufw app info 'Apache'\n \n# 设置日志记录级别\nsudo ufw logging medium\n \n# 重新加载 UFW 规则,无需重启防火墙服务\nsudo ufw reload\n \n# 重置 UFW 配置为默认状态\nsudo ufw reset\nFirewalld\nfirewalld 是一个用于管理 Linux 发行版的防火墙的动态守护程序。主要用于 IPv4、IPv6 防火墙规则以及以太网桥的管理,**firewalld 基于 nftables 或 iptables 实现网络包过滤。**相较于传统的防火墙管理方式firewalld 采用动态管理,能够让你在无需重启防火墙的情况下实时更新策略和规则。\n**firewalld 使用区域zones来定义不同网络接口或连接的安全级别和防火墙规则。**每个区域都有一组默认规则,可以允许或拒绝特定类型的流量。区域的设计目的是根据网络信任度对网络流量进行分区管理。这使你能够为信任的网络接口、设备和服务定义区域,实现更加灵活的防火墙管理。\n架构图\ngraph TD\n subgraph firewalld\n A[firewalld Daemon]\n B[D-Bus Interface]\n C[Backend]\n C --> D[iptables/nftables]\n E[Zones]\n E --> drop[Drop]\n E --> block[Block]\n E --> public[Public]\n E --> external[External]\n E --> dmz[DMZ]\n E --> work[Work]\n E --> home[Home]\n E --> internal[Internal]\n F[Services]\n end\n A -->|Communicates via| B\n A --> C\n A --> E\n A --> F\n\n\nfirewalld Daemonfirewalld 是一个常驻内存的守护进程,负责管理防火墙规则。它通过 D-Bus 接口提供与外部交互的能力,可以动态加载和卸载规则,而不需要重启防火墙服务。\nD-Bus InterfaceD-Bus 是一个消息总线系统firewalld 通过它与其他系统组件和应用程序进行通信。用户和管理工具可以通过 D-Bus 与 firewalld 交互,查询状态、修改规则等。\nBackend后端firewalld 支持两种主要的后端iptables 和 nftables。后端是实际执行防火墙规则的地方firewalld 负责将用户定义的规则翻译成适当的后端命令并执行。\nZones区域区域是 firewalld 管理规则的一种方式。每个网络接口或连接可以分配到一个区域,区域定义了特定的信任级别和规则集。常见的区域包括 public、home、work 和 internal 等。\nServices服务服务定义了一组预定义的规则这些规则允许或拒绝特定的网络流量。例如HTTP 服务允许 TCP 端口 80 的流量。通过添加或删除服务,用户可以方便地管理复杂的防火墙规则。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n区域描述默认行为适用场景drop丢弃所有传入的网络包不回应任何请求。丢弃所有传入流量高度安全需求伪装系统离线block拒绝所有传入的连接返回拒绝信息。拒绝所有传入流量完全信任的网络连接public对外部网络的默认配置允许有限的传入连接。允许有限的传入流量公共网络连接最低信任级别external用于外部网关启用网络地址转换NAT保护内部网络。启用 NAT限制传入流量外部网络网关保护内部网络dmz非军事区DMZ允许对公众开放的服务同时保护内部网络。允许特定服务的传入流量公共服务的隔离区保护内部网络work适用于工作环境信任网络较高允许更多的传入连接。允许更多的传入流量工作环境较高信任级别home适用于家庭网络信任网络较高允许更多的传入连接。允许更多的传入流量家庭网络高信任级别internal适用于完全信任的内部网络允许所有传入的连接。允许所有传入流量完全信任的内部网络\n工作流程\nflowchart TD\n A[启动 firewalld] --> B[加载默认配置文件]\n B --> C[设置初始防火墙规则]\n C --> D{用户交互}\n D -->|添加规则| E[更新规则]\n D -->|删除规则| F[更新规则]\n D -->|修改规则| G[更新规则]\n E --> H[应用新规则]\n F --> H[应用新规则]\n G --> H[应用新规则]\n H --> I[日志记录]\n I --> J[监控网络活动]\n H --> K{持久性配置}\n K -->|临时规则| L[临时规则加载,重启后丢失]\n K -->|永久规则| M[永久规则保存到配置文件]\n\n\n启动 firewalld当 firewalld 守护进程启动时,开始加载默认配置文件。\n加载默认配置文件从系统中读取默认的防火墙配置文件。\n设置初始防火墙规则根据配置文件设置初始的防火墙规则。\n用户交互用户通过 CLI命令行界面或 GUI图形用户界面与 firewalld 进行交互,执行添加、删除或修改规则的操作。这些命令通过 D-Bus 接口传递给 firewalld 守护进程。\n更新规则根据用户的操作更新防火墙规则。\n应用新规则根据更新后的配置文件立即应用新的防火墙规则而不需要重启服务。\n日志记录firewalld 支持日志记录功能,记录防火墙的操作和网络活动。\n监控网络活动通过日志用户可以监控和分析网络活动及安全事件。\n**持久性配置:**firewalld 提供两种规则管理模式:\n\n临时规则这些规则在系统重启后会丢失。\n永久规则这些规则会保存到配置文件中在系统重启后自动加载。\n\n\n\n常用命令\n# 启动 firewalld\nsystemctl start firewalld\n \n# 停止 firewalld\nsystemctl stop firewalld\n \n# 在启动时启用 firewalld\nsystemctl enable firewalld\n \n# 查看 firewalld 状态\nfirewall-cmd --state\n \n# 列出所有区域\nfirewall-cmd --get-zones\n \n# 查看某个区域的详细信息\nfirewall-cmd --zone=public --list-all\n \n# 更改默认区域\nfirewall-cmd --set-default-zone=home\n \n# 将接口分配到特定区域\nfirewall-cmd --zone=home --change-interface=eth0\n \n# 永久分配接口到特定区域\nfirewall-cmd --permanent --zone=home --add-interface=eth0\n \n# 添加源地址到区域\nfirewall-cmd --zone=public --add-source=192.168.1.0/24\n \n# 永久添加源地址到区域\nfirewall-cmd --permanent --zone=public --add-source=192.168.1.0/24\n \n# 列出所有默认防火墙规则\nfirewall-cmd --list-all\n \n# 添加服务到防火墙\nfirewall-cmd --permanent --add-service=http\n \n# 删除服务\nfirewall-cmd --permanent --remove-service=http\n \n# 开放端口\nfirewall-cmd --permanent --add-port=8080/tcp\n \n# 移除端口\nfirewall-cmd --permanent --remove-port=8080/tcp\n \n# 重新载入防火墙规则\nfirewall-cmd --reload\n \n# 列出所有区域\nfirewall-cmd --get-zones\n \n# 查看某个区域的详细信息\nfirewall-cmd --zone=public --list-all\n \n# 更改默认区域\nfirewall-cmd --set-default-zone=home\n \n# 将接口分配到特定区域\nfirewall-cmd --zone=home --change-interface=eth0\n \n# 永久分配接口到特定区域\nfirewall-cmd --permanent --zone=home --add-interface=eth0\n \n# 添加源地址到区域\nfirewall-cmd --zone=public --add-source=192.168.1.0/24\n \n# 永久添加源地址到区域\nfirewall-cmd --permanent --zone=public --add-source=192.168.1.0/24\niptables、nftables、UFW、firewalld 对比\n在 Linux 环境下iptablesnftablesufw 和 firewalld 都是常用的防火墙工具,每种工具都有其独特的优点和使用场景:\n在 Linux 环境下iptablesnftablesufw 和 firewalld 都是常用的防火墙工具,每种工具都有其独特的优点和使用场景:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性iptablesnftablesufwfirewalld发布日期1998201420082011操作复杂度高中低中基于netfilternetfilteriptablesiptables/nftables内建于内核是是否否GUI否否否是基于区域的过滤否否否是直接规则是是否是规则集合否是否是协议支持IPv4/IPv6IPv4/IPv6IPv4/IPv6IPv4/IPv6适用于服务器、桌面服务器、桌面桌面、新手服务器、桌面跨平台是是是是语法复杂度高低低中动态规则修改否是否是日志记录是是是是应用配置支持否否是是持久性配置是是是是\n\n初学者和基本防火墙需求ufw 是最好的选择,因其简易性和用户友好性。\n高级用户和复杂配置iptables 提供了最细致的控制,适合需要高度自定义和复杂配置的环境。\n现代化和简化管理nftables 提供了更简洁的语法和规则集合功能,是 iptables 的现代替代品。\n动态和区域管理firewalld 结合了强大功能和易用性,适合需要动态管理和基于区域的过滤需求的环境。\n\n**总的来说,应该根据特定需求和技能水平选择最适合的防火墙工具。**对于初学者和只需要基本防火墙功能的用户来说ufw 可能是最好的选择。对于需要进行精细控制和高级配置的用户iptables 和 nftables 可能更合适。如果您需要一种同时提供强大功能和易用性的防火墙工具,那么 firewalld 可能是最好的选择。\n网络优化\n网络带宽管理\n网络带宽管理是一种在 Linux 系统上优化网络性能和响应时间的方法。它允许管理员控制和分配网络带宽,从而为不同的应用程序和服务提供最佳性能。\n\ntc (Traffic Control)Linux 内核的一部分,用于实现复杂的带宽管理和流量控制策略。\nHTB (Hierarchical Token Bucket):一个基于 tc 的流量整形工具,允许管理员创建多层次的带宽限制和优先级分配策略。\n\n网络质量管理QoS\n网络质量管理Quality of ServiceQoS是一种用于分配网络带宽的技术确保网络资源的公平使用和最佳利用。通过 QoS管理员可以根据应用程序的需求和优先级分配网络带宽从而优化网络性能。\n\ntc (Traffic Control):用于实现复杂的 QoS 策略和流量控制。\nWondershaper一个基于 tc 的简单 QoS 工具,允许管理员轻松设置带宽限制和优先级策略。\n\n负载均衡\n负载均衡是在多个服务器之间分配负载的技术以提高应用程序的性能和可靠性。在 Linux 系统上,可以使用软件负载均衡器和硬件负载均衡器来实现负载均衡。\n\nHAProxy一个高性能、高可用性的软件负载均衡器支持 TCP 和 HTTP 协议。\nNginx一个功能强大的 Web 服务器,也可以作为负载均衡器和反向代理服务器。\nLVS (Linux Virtual Server):一个基于 Linux 内核的负载均衡解决方案,支持多种负载均衡算法。\n\n数据压缩\n数据压缩技术可以减少网络传输的数据量从而提高网络带宽利用率和传输效率。Linux 系统提供了多种压缩工具和库,支持不同的压缩算法。\n\ngzip一种广泛使用的文件压缩工具基于 DEFLATE 压缩算法。\nbzip2一个基于 Burrows-Wheeler 算法的文件压缩工具,提供较高的压缩率。\nlz4一种快速的无损压缩算法适用于实时场景和大数据处理。\n\n缓存服务\n缓存服务用于在网络上存储和提供数据以提高访问速度和响应时间。Linux 系统上有多种缓存服务可用,包括 Web 缓存、DNS 缓存和内容分发网络CDN。\n\nSquid一个成熟的 Web 缓存代理服务器,可以用来缓存网站内容和优化网络访问速度。\nUnbound一个轻量级的 DNS 缓存服务器,用于加速 DNS 解析请求和提高域名解析性能。\nVarnish一个高性能的 HTTP 加速器和缓存服务器,广泛用于 Web 应用程序的性能优化。\n\nTCP/IP 优化\nTCP/IP 优化包括调整 TCP 拥塞控制算法、修改最大传输单元MTU、调整 Nagle 算法等以提高网络性能和传输速度。Linux 系统提供了多种工具和设置来优化 TCP/IP 性能。\n\n修改内核参数通过调整 /proc/sys/net/ipv4/ 目录下的内核参数,如 tcp_wmem、tcp_rmem 和 tcp_congestion_control以优化 TCP 性能。\n调整 MTU修改网卡的 MTU 设置,以适应网络环境和提高传输效率。\n禁用 Nagle 算法:通过设置 TCP_NODELAY 选项,关闭 Nagle 算法以减小传输延迟。\n\nCDN内容分发网络\n内容分发网络CDN是一种用于分发静态内容的技术通过在全球范围内部署多个数据中心将内容缓存到离用户最近的节点从而提高访问速度和减轻源服务器负担。CDN 广泛应用于 Web 应用程序和大型网站,以提供优质的用户体验。\n\nAkamai全球最大的 CDN 服务商,提供广泛的网络加速和安全解决方案。\nCloudflare一家提供 CDN 和网络安全服务的公司,帮助网站加速和保护其内容。\nAmazon CloudFront亚马逊提供的全球内容分发服务与其他 AWS 服务紧密集成。\n\n网络安全\n网络故障排查与诊断\nLinux 系统提供了一系列工具来帮助用户进行网络故障排查与诊断,包括 ping、traceroute、mtr、nslookup、dig 和 whois 等。\n\nping用于检测网络连接和延迟通过发送 ICMP 数据包来检测目标主机是否可达。\ntraceroute用于显示数据包从源主机到目标主机经过的路由路径。\nmtr结合了 ping 和 traceroute 功能的网络诊断工具,提供实时路由分析。\nnslookup用于查询 DNS 服务器以获取域名解析信息。\ndig功能强大的 DNS 查询工具,可以获取详细的 DNS 记录信息。\nwhois用于查询域名注册信息和 IP 地址分配信息。\n\n安全隔离\n安全隔离是网络安全的重要概念可以防止潜在的网络攻击和数据泄露。主要实现技术包括 VLAN、DMZ 和容器网络隔离。\n\nVLAN (Virtual Local Area Network):通过在网络交换机上配置 VLAN可以将物理网络划分为多个逻辑子网实现网络资源的安全隔离。\nDMZ (Demilitarized Zone):一种网络安全策略,通过在内部网络和外部网络之间建立一个隔离区域,保护内部网络资源免受外部攻击。\n容器网络隔离通过使用容器技术如 Docker、Kubernetes和虚拟网络如 Calico、Flannel来实现应用程序的安全隔离。\n\nSSH 安全配置\nSSH 是远程登录和管理 Linux 系统的常用协议。正确配置 SSH 可以提高系统的安全性。\n\n密钥认证使用公钥/私钥对进行身份验证,替代密码认证,提高安全性。\n端口改变将 SSH 服务端口从默认的 22 更改为其他端口,降低被扫描和攻击的风险。\n禁止 root 登录:禁止直接通过 SSH 以 root 身份登录,减少被攻击者利用的可能性。\n防止暴力破解通过限制登录尝试次数、使用防火墙规则或安装防暴力破解软件如 Fail2Ban来防止暴力破解攻击。\n\n虚拟化网络\n虚拟化网络是在物理网络基础上创建虚拟网络资源的技术包括虚拟网卡、虚拟交换机、网桥和 SDN软件定义网络等。\n\n虚拟网卡在虚拟机和容器中模拟的网络接口与物理网卡类似可用于建立虚拟网络连接。\n虚拟交换机在虚拟环境中实现网络连接和数据包转发的虚拟设备。\n网桥用于连接虚拟网络和物理网络实现虚拟机与外部网络通信。\nSDN一种将网络控制平面与数据平面分离的技术允许通过软件实现网络资源的动态配置和管理。\n\n网络监测和分析\n网络监测和分析工具可以帮助管理员实时监控网络状况、发现异常行为和安全威胁。常用工具包括 tcpdump、Wireshark、netstat、nmap、sniffing、IDS 和 NMS 等。\n\ntcpdump用于捕获和分析网络数据包的命令行工具。\nWireshark一个图形界面的网络协议分析器。\nnetstat用于显示网络连接状态和监听端口的命令行工具。\nnmap一款强大的网络扫描和安全审计工具。\n\n网络入侵检测系统IDS\n网络入侵检测系统Intrusion Detection SystemIDS可以检测网络中的恶意行为和攻击活动。常见的 IDS 工具包括 Snort、Suricata、OSSEC 和 Bro/Zeek。\n\nSnort一款开源的网络入侵检测和防御系统基于规则匹配和异常检测来识别恶意流量。\nSuricata一个高性能的开源 IDS/IPS/NSM网络安全监控引擎支持实时流量分析和威胁防御。\nOSSEC一个开源的主机入侵检测系统用于监控文件系统、日志文件和网络活动。\nBro/Zeek一款强大的网络安全监控平台支持实时流量分析、协议解析和异常检测。\n\n网络安全监控系统NMS\n网络安全监控系统Network Monitoring SystemNMS用于实时监控网络设备和服务的运行状况发现性能问题和安全威胁。常见的 NMS 工具包括 Nagios、Zabbix、Cacti、Prometheus 和 Grafana。\n\nNagios一款功能强大的开源网络监控系统支持多种插件和扩展用于监控网络设备、服务和应用程序。\nZabbix一种企业级的开源监控解决方案提供分布式监控、报警和报表功能。\nCacti一个基于 RRDtool 的网络图形监控工具,用于绘制网络设备性能图表。\nPrometheus一个开源的监控和告警系统广泛用于监控微服务和容器化应用程序。\nGrafana一个流行的开源监控数据可视化工具支持多种数据源如 Prometheus、InfluxDB 和 Elasticsearch 等。\n\n网络安全审计系统\n网络安全审计系统用于评估网络设备和应用程序的安全性发现潜在的漏洞和配置问题。常见的安全审计工具包括 OSSEC、Tripwire、AIDE、OpenSCAP 和 Lynis。\n\nOSSEC一个开源的主机入侵检测系统也可以用于安全审计和配置检查。\nTripwire一款用于文件完整性检查和安全审计的工具可以检测文件的变更和潜在的安全问题。\nAIDE (Advanced Intrusion Detection Environment):一个用于文件完整性检查和入侵检测的开源工具。\nOpenSCAP (Open Security Content Automation Protocol):一个开源的安全配置和漏洞管理框架,基于 SCAP 标准实现。\nLynis一个开源的安全审计和硬化工具用于检查 Linux 系统的配置和安全性。\n\n网络加密技术\n网络加密技术用于保护数据在传输过程中的隐私和完整性。主要的网络加密技术包括 SSL/TLS、IPSec、SSH 等。\n\nSSL/TLS安全套接层Secure Sockets LayerSSL和传输层安全Transport Layer SecurityTLS是应用于网络传输层的加密技术用于保护 Web 浏览、电子邮件和其他应用程序的数据安全。\nIPSecInternet 协议安全IP SecurityIPSec是一个用于保护 IP 数据包传输安全的协议套件提供加密、认证和完整性保护功能。IPSec 广泛应用于 VPN 技术中。\nSSH安全外壳Secure ShellSSH是一种加密网络协议用于在不安全的网络环境中实现安全的远程登录、文件传输和其他网络服务。\n\n安全认证和授权\n安全认证和授权技术用于验证用户身份和控制用户访问权限。主要技术包括 RADIUS、TACACS+、LDAP、Kerberos 等。\n\nRADIUS远程认证拨号用户服务Remote Authentication Dial-In User ServiceRADIUS是一个用于 AAA认证、授权和计费的网络协议广泛应用于网络接入和 VPN 服务中。\nTACACS+:终端访问控制器访问控制系统 +Terminal Access Controller Access-Control System+TACACS+)是一种用于网络设备管理的 AAA 协议,主要应用于路由器、交换机等网络设备的远程管理。\nLDAP轻型目录访问协议Lightweight Directory Access ProtocolLDAP是一种用于访问和维护分布式目录信息服务的协议常用于企业网络的用户认证和组织结构管理。\nKerberos一种基于票据的网络认证协议用于实现单点登录Single Sign-OnSSO和安全的跨域认证。\n\n网络安全策略和最佳实践\n为了提高网络安全企业和组织需要制定和实施合适的网络安全策略并遵循最佳实践。\n\n制定并执行网络安全政策明确网络资源的访问控制、数据保护和应急响应等方面的要求。\n定期进行安全审计和漏洞扫描检查网络设备和应用程序的安全配置发现并修复潜在的安全漏洞。\n提高员工安全意识通过培训和教育提高员工对网络安全的认识防止误操作和内部威胁。\n"},"Technology/OperatingSystem/Linux/7.存储管理/Linux-文件系统":{"title":"Linux 文件系统","links":[],"tags":["技术/操作系统","Linux/存储管理"],"content":"概念\n文件系统是一种用于存储和组织计算机数据的机制它使用文件和树形目录的抽象逻辑概念来代替硬盘和光盘等物理设备使用数据块的概念。文件系统的设计使得对数据的访问和查找变得容易用户不必关心数据实际保存在硬盘或光盘的哪个地址只需要记住文件所属的目录和文件名。文件系统自动完成硬盘上的存储空间管理分配和释放用户只需要记住数据被写入到哪个文件中。\n常见的文件系统列表如下\n\n文件配置表File Allocation TableFAT系列FAT12、FAT16、FAT32、exFAT\n新技术文件系统New Technology File SystemNTFS\n分层文件系统Hierarchical File SystemHFS和 HFS Plus\n延伸文件系统Extended File Systemext系列ext1、ext2、ext3、ext4\n旧式数据系统Old Data SystemODS\nBtrfsB-tree 文件系统)\nXFSSGI 的高性能日志文件系统)\nUFSUnix 文件系统)\nZFSZettabyte 文件系统)\n\n在文件系统中文件名是用于定位存储位置。大多数的文件系统对文件名的长度有限制。文件名可以是大小写不敏感的也可以是大小写敏感的。现今的文件系统允许文件名包含非常多的 Unicode 字符集的字符,但某些特殊字符在文件名中受限。方便起见,一般不建议在文件名中包含特殊字符。\n文件系统还维护元数据Metadata包括文件长度、最后修改时间、文件设备类型、文件所有者和访问权限等信息。有些文件系统还保存文件的创建时间、最后访问时间及属性修改时间。元数据还可以包括文件设备类型、字符集、套接口、子目录等信息。\n文件系统可以通过访问控制列表或 capabilities 实现安全访问,但访问控制列表难以保证安全,因此研发中的文件系统倾向于使用 capabilities。然而目前多数商业性的文件系统仍然使用访问控制列表。\n文件系统可以使用硬盘、光盘等物理设备存储数据也可以通过网络协议提供数据甚至可能根本没有对应的文件。严格来说文件系统是一种实现数据的存储、分级组织、访问和获取等操作的抽象数据类型。\nLinux 文件系统\n在 Linux 系统中支持多种文件系统Ext2、Ext3、Ext4、XFS、Btrfs、NTFS、FAT32、ISO 9660、NFS 等。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n系统全拼功能优点用途Ext2Second Extended File System提供基本的文件存储功能简单速度较快可靠性高适用于小型存储设备如闪存卡Ext3Third Extended File System在 Ext2 基础上增加了日志功能文件系统可靠性更高,具有较好的容错能力适用于大多数 Linux 发行版以及需要可靠数据存储的服务器环境Ext4Fourth Extended File System在 Ext3 基础上增加了更多的特性如更大的文件系统和更高的性能支持大容量文件和高性能文件系统访问适用于大型服务器和高性能计算机XFSXFS File System高性能文件系统支持大容量文件和高吞吐量应用速度快可靠性高适合高性能计算和大型存储设备适用于需要大容量和高性能访问的服务器环境BtrfsB-tree File System先进的文件系统支持快照、数据压缩和多个设备的联合文件系统等功能可靠性高能够在多个设备之间提供容错性适用于需要高效数据管理和可靠存储的服务器和桌面环境NTFSNew Technology File SystemWindows 操作系统上的文件系统,支持文件和目录的权限控制和加密等功能可以处理很大的文件系统,能够在 Windows 和 Linux 之间进行数据传输适用于需要与 Windows 系统交互的 Linux 系统FAT32File Allocation Table 32-bit一种老旧的文件系统支持大容量的存储设备可以在不同的操作系统之间进行数据传输通常用于移动设备和便携式存储介质上适用于小型存储设备如 USB 闪存盘和 SD 卡ISO 9660International Standard Organization 9660用于光盘文件系统支持只读访问可以在不同的操作系统之间进行数据传输适用于在 CD 和 DVD 上发布数据的场景NFSNetwork File System一种网络文件系统可以让不同的机器上的用户共享文件系统能够在不同的计算机之间共享文件和目录提供高度的数据访问性能适用于需要在多个计算机之间共享文件的网络环\nFHS 层次结构\n\n\n来源Linux 文件系统结构 - Strong在线文档库仅学术引用著作权归作者所有。\n\n在 Linux 系统中文件系统采用了一种层次结构来组织文件和目录这种层次结构称为文件系统层次结构Filesystem Hierarchy StandardFHS。FHS 是一种标准化的文件系统层次结构,规定了在不同的 Linux 系统中应该如何组织文件和目录,以保证文件系统的一致性和兼容性。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n目录名全拼功能用途/Root根目录包含所有其他目录和文件的根目录/binBinary存放系统二进制可执行文件包含最基本的系统命令/bootBoot存放启动加载程序和内核包含启动 Linux 系统所必需的文件/devDevice存放设备文件包含 Linux 系统中所有的设备文件,如硬盘、键盘、鼠标等/etcEtcetera存放系统配置文件包含 Linux 系统中所有的系统配置文件,如网络配置文件、用户账号配置文件等/homeHome存放用户家目录包含所有用户的家目录/libLibrary存放系统共享库文件包含系统运行时所需要的一些库函数/mediaMedia存放可移动介质挂载点包含可移动介质的挂载点如 U 盘、光盘等/mntMount存放挂载点包含文件系统挂载点用于临时挂载其他文件系统/optOptional存放第三方应用程序包含安装在系统中的第三方应用程序/procProcess存放进程相关信息包含 Linux 系统中所有进程的相关信息/rootRootroot 用户家目录仅限 root 用户访问的家目录/runRun存放运行时信息包含运行时所需要的各种信息如进程号等/sbinSystem Binary存放系统管理二进制可执行文件包含系统管理员使用的基本命令和系统管理工具/srvService存放服务相关数据包含服务相关的数据如 Web 服务的网站文件/sysSystem存放系统设备文件包含系统中所有设备的相关信息/tmpTemporary存放临时文件包含系统中各种临时文件/usrUnix Shared Resources存放 Unix 共享资源包含系统中大多数应用程序、库文件和文档等/varVariable存放经常变化的文件包含系统中经常变化的文件如日志文件、数据库文件等\nInode 文件元数据\n**在 Linux 系统中,每个文件都有其对应的元信息,也称为元数据 (metadata)。**元数据包含了文件的基本属性,如文件的创建时间、访问时间、修改时间,文件大小,文件所有者和所属组,文件的权限等等。\n以下是一些常见的文件元数据\n\n文件名文件的名字用于标识文件。\n文件类型表示文件的类型如普通文件、目录、链接文件、字符设备、块设备等等。\n文件大小表示文件的大小以字节为单位。\n时间戳记录了文件的创建时间、访问时间、修改时间等信息。\n文件权限文件所有者、所属组、其他用户对文件的读、写、执行权限。\n文件所有者和所属组表示文件的所有者和所属组。\n文件状态如 inode 号码、硬链接数等。\n\n在 Unix 和类 Unix 操作系统中 文件系统中,每个文件或目录都有一个 inode 号码,它是唯一的,由文件系统分配,文件名只是 inode 的别名而已。当我们打开一个文件时,实际上是根据该文件名找到对应的 inode然后通过 inode 读取文件的数据。\nindex node (inode) 是 Unix 和类 Unix 操作系统中的一个重要概念,它是文件系统中用来存储文件或目录的元数据信息的一种数据结构,每个文件或目录都对应一个唯一的 inode。下面是一个示例 inode 表格:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件类型inode 号大小拥有者权限访问时间修改时间创建时间普通文件123451KBroot6442022/3/12022/3/22022/3/1\nDev 物理设备文件\n在 Linux 系统中,一切都是文件,包括硬件设备也不例外。这是因为在 Linux 中硬件设备被抽象成了一种特殊的文件类型称为设备文件Device file。设备文件用于对硬件设备进行读写操作类似于普通文件的读写操作。设备文件分为两种类型\n\n块设备文件对应的硬件设备是以块为单位进行读写的设备例如硬盘、U 盘等;\n字符设备文件对应的硬件设备是以字符为单位进行读写的设备例如键盘、鼠标、打印机等。\n\n**在 Linux 系统中,每个设备文件都有一个对应的设备文件名,该文件名通常位于 /dev 目录下,不同的硬件设备会有不同的设备文件名。**通过访问设备文件,用户可以对硬件设备进行操作。例如,如果想要读取硬盘的数据,用户可以通过访问对应的设备文件(如 /dev/sda来读取数据而不需要关心具体的物理硬盘是什么型号、连接方式等等。这种抽象的方式让用户更方便地使用硬件设备并且使得操作系统能够更好地管理硬件设备。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n硬件设备命名规则IDE 接口硬盘/dev/hd[a-d]SCSI、SATA、U 盘/dev/sd[a-z]KVM/QEMU 虚拟设备/dev/vd[a-z]软盘/dev/fd[0-1]打印机/dev/lp[0-15]CD/DVD 光盘驱动器/dev/cdrom鼠标设备/dev/mouseSCSI 接口磁带机或 IDE 接口/dev/st0 或 /dev/ht0\n新磁盘挂载\n\n\n插入新硬盘\n\n将新硬盘插入计算机的硬盘插槽中并连接好数据线和电源线。\n\n查看新硬盘设备信息\n\n确认新硬盘的设备名称可以使用 fdisk -l 命令或者 lsblk 命令来列出系统中的所有硬盘设备,找到新硬盘的设备名称。\n$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS\nnvme0n1 259:0 0 64G 0 disk\n├─nvme0n1p1 259:1 0 1G 0 part /boot\n└─nvme0n1p2 259:2 0 63G 0 part\n ├─rhel-root 253:0 0 39.7G 0 lvm /\n ├─rhel-swap 253:1 0 3.9G 0 lvm [SWAP]\n └─rhel-home 253:2 0 19.4G 0 lvm /home\nnvme0n2 259:3 0 8G 0 disk 👈\n$ fdisk -l /dev/nvme0n2\nDisk /dev/nvme0n28 GiB8589934592 字节16777216 个扇区\n磁盘型号VMware Virtual NVMe Disk\n单元扇区 / 1 * 512 = 512 字节\n扇区大小(逻辑/物理)512 字节 / 512 字节\nI/O 大小(最小/最佳)512 字节 / 512 字节\n3.创建硬盘分区\n如果新硬盘未被分区则需要先创建分区。可以使用 fdisk 命令来创建分区,然后按照提示创建分区。\n$ fdisk /dev/nvme0n2\n \n欢迎使用 fdisk (util-linux 2.37.4)。\n更改将停留在内存中直到您决定将更改写入磁盘。\n使用写入命令前请三思。\n \n设备不包含可识别的分区表。\n创建了一个磁盘标识符为 0x70f8d313 的新 DOS 磁盘标签。\n \n命令(输入 m 获取帮助)n 👈\n分区类型\n p 主分区 (0 primary, 0 extended, 4 free)\n e 扩展分区 (逻辑分区容器)\n选择 (默认 p)p 👈\n分区号 (1-4, 默认 1): 1 👈\n第一个扇区 (2048-16777215, 默认 2048):2048 👈\n最后一个扇区+/-sectors 或 +size{K,M,G,T,P} (2048-16777215, 默认 16777215): +1g 👈\n \n创建了一个新分区 1类型为“Linux”大小为 1 GiB。\n \n命令(输入 m 获取帮助)w 👈\n分区表已调整。\n将调用 ioctl() 来重新读分区表。\n正在同步磁盘。\n\n格式化新分区文件系统\n\n**分区创建完成后,需要将分区格式化为文件系统才能挂载。**可以使用 mkfs 命令来格式化分区,比如可以使用 mkfs.ext4 /dev/nvme0n2p1 命令将 /dev/nvme0n2p1 分区格式化为 ext4 文件系统。\n$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS\nnvme0n1 259:0 0 64G 0 disk\n├─nvme0n1p1 259:1 0 1G 0 part /boot\n└─nvme0n1p2 259:2 0 63G 0 part\n ├─rhel-root 253:0 0 39.7G 0 lvm /\n ├─rhel-swap 253:1 0 3.9G 0 lvm [SWAP]\n └─rhel-home 253:2 0 19.4G 0 lvm /home\nnvme0n2 259:3 0 8G 0 disk\n└─nvme0n2p1 259:5 0 1G 0 part 👈\n$ mkfs.ext4 /dev/nvme0n2p1\nmke2fs 1.46.5 (30-Dec-2021)\n创建含有 262144 个块(每块 4k和 65536 个inode的文件系统\n文件系统UUID28337fe9-2ec1-4d39-9001-27595dd569bf\n超级块的备份存储于下列块\n 32768, 98304, 163840, 229376\n \n正在分配组表 完成\n正在写入inode表 完成\n创建日志8192 个块)完成\n写入超级块和文件系统账户统计信息 已完成\n\n创建硬盘新分区目录挂载点\n\n在 Linux 中,需要先创建一个目录,作为挂载点,使用 mount 命令将分区挂载到该目录下。\n$ mkdir /mnt/newdisk-1gb\n$ mount /dev/nvme0n2p1 /mnt/newdisk-1gb/\n$ df -h\n文件系统 容量 已用 可用 已用% 挂载点\ndevtmpfs 4.0M 0 4.0M 0% /dev\ntmpfs 1.8G 0 1.8G 0% /dev/shm\ntmpfs 726M 9.1M 717M 2% /run\n/dev/mapper/rhel-root 40G 2.2G 38G 6% /\n/dev/mapper/rhel-home 20G 171M 20G 1% /home\n/dev/nvme0n1p1 1014M 244M 771M 24% /boot\ntmpfs 363M 0 363M 0% /run/user/0\n/dev/nvme0n2p1 974M 24K 907M 1% /mnt/newdisk-1gb 👈\n\n配置硬盘新分区开机自动挂载目录\n\n$ df -h\n文件系统 容量 已用 可用 已用% 挂载点\ndevtmpfs 4.0M 0 4.0M 0% /dev\ntmpfs 1.8G 0 1.8G 0% /dev/shm\ntmpfs 726M 9.1M 717M 2% /run\n/dev/mapper/rhel-root 40G 2.2G 38G 6% /\n/dev/mapper/rhel-home 20G 171M 20G 1% /home\n/dev/nvme0n1p1 1014M 244M 771M 24% /boot\ntmpfs 363M 0 363M 0% /run/user/0\n/dev/nvme0n2p1 974M 24K 907M 1% /mnt/newdisk-1gb\n$ blkid | grep 0n2\n/dev/nvme0n2p1: UUID="28337fe9-2ec1-4d39-9001-27595dd569bf" TYPE="ext4" PARTUUID="70f8d313-01"\n$ echo "UUID=28337fe9-2ec1-4d39-9001-27595dd569bf /mnt/newdisk-1gb ext4 defaults 0 0" >> /etc/fstab\n$ tail -n 1 /etc/fstab\nUUID=28337fe9-2ec1-4d39-9001-27595dd569bf /mnt/newdisk-1gb ext4 defaults 0 0\n$ mount -a\n$ reboot\n======================== 重启后 ========================\n$ df -h\n文件系统 容量 已用 可用 已用% 挂载点\ndevtmpfs 4.0M 0 4.0M 0% /dev\ntmpfs 1.8G 0 1.8G 0% /dev/shm\ntmpfs 726M 9.1M 717M 2% /run\n/dev/mapper/rhel-root 40G 2.2G 38G 6% /\n/dev/mapper/rhel-home 20G 171M 20G 1% /home\n/dev/nvme0n2p1 974M 24K 907M 1% /mnt/newdisk-1gb 👈\n/dev/nvme0n1p1 1014M 244M 771M 24% /boot\ntmpfs 363M 0 363M 0% /run/user/0\n日常巡检\n\n查询磁盘空间使用情况\n使用 df 命令来查询文件系统的空间使用情况。\n$ df -h\n文件系统 容量 已用 可用 已用% 挂载点\ndevtmpfs 4.0M 0 4.0M 0% /dev\ntmpfs 1.8G 0 1.8G 0% /dev/shm\ntmpfs 726M 9.1M 717M 2% /run\n/dev/mapper/rhel-root 40G 2.3G 38G 6% /\n/dev/mapper/rhel-home 20G 171M 20G 1% /home\n/dev/nvme0n2p1 974M 24K 907M 1% /mnt/newdisk-1gb\n/dev/nvme0n1p1 1014M 244M 771M 24% /boot\ntmpfs 363M 0 363M 0% /run/user/0\n查询目录空间使用情况\n使用 du 命令来查询指定目录的空间使用情况。\n$ du -h /var | head -n 10\n488K /var/lib/dnf\n54M /var/lib/rpm\n0 /var/lib/games\n0 /var/lib/misc\n0 /var/lib/rpm-state/kernel\n0 /var/lib/rpm-state\n48K /var/lib/alternatives\n0 /var/lib/selinux/tmp\n36K /var/lib/selinux/targeted/active/modules/100/abrt\n20K /var/lib/selinux/targeted/active/modules/100/accountsd\n磁盘性能监测\nsysstatSystem Statistics是一个系统性能监控工具它包含了一系列的工具和报告可以用来监测系统负载、CPU 使用率、内存使用率、网络活动等系统性能指标。sysstat 提供了一些常用的命令行工具,包括 sar、iostat、mpstat、pidstat 等,这些工具可以周期性地获取系统的性能指标数据,并将数据保存在文件中。用户可以使用这些数据来分析系统的负载情况、瓶颈所在等,进一步优化系统性能。\nsysstat 的主要功能包括:\n\n提供了 sar 工具,可以对系统进行多方面的监控,如 CPU 使用率、内存使用率、IO 使用率等。\n提供了 iostat 工具,可以监控磁盘 I/O 活动情况。\n提供了 mpstat 工具,可以监控 CPU 的性能指标,如使用率、上下文切换、中断数等。\n提供了 pidstat 工具,可以监控进程的性能指标,如 CPU 使用率、内存使用率、IO 活动情况等。\n提供了 sadf 工具,可以将 sar 工具的输出转换成其他格式,如 CSV、XML、JSON 等。\n支持将性能监控数据保存到文件中并提供了一些工具如 sadc、sa1、sa2 等,来周期性地收集性能数据。\n支持使用系统日志守护程序来管理和处理系统日志如 syslogd、rsyslogd 等。\n\n总之sysstat 提供了一系列强大的性能监控工具和报告,可以帮助用户深入了解系统的性能状况,并及时识别并解决性能瓶颈,从而提高系统的稳定性和可靠性。\n权限和安全\nLinux 文件系统的权限和安全主要可以分为四个部分:常用权限控制、特殊权限控制、隐藏权限控制和 SELinux 权限控制。\n常用权限\nLinux 系统中有三种基本的权限rread、写wwrite和执行xexecute。也可以使用数字来表示文件或目录的权限。每个权限用一个数字表示分别为 4、2 和 1分别代表读、写和执行权限。通过将这些数字相加可以得到一个三位数的数字用于表示用户、组和其他用户的权限。这些权限分别适用于文件和目录。权限可以分为三组分别为用户uuserggroup和其他oothers。\n\n文件权限设置为 -rw-r—r—chmod 644 file.txt、chmod u=rw,g=r,o=r file.txt\n文件所有者设置执行权限chmod u+x file.txt\n文件所有组去除写入和执行权限chmod g-wx file.txt\n文件其他用户设置只读权限chmod o=r file.txt\n\n注意chmod + 表示添加权限,- 表示删除权限,= 表示设置权限。\ndrwxr-xr-x 1 root root 4096 Dec 10 03:15 boot\n \n这是一个目录d开头权限为rwxr-xr-x所有者为root所属组也为root大小为4096字节创建时间为12月10日 03:15。\n \n所有者root具有读、写和执行权限rwx\n所属组root和其他用户具有读和执行权限r-x\n总的来说这个目录的权限是755rwxr-xr-x所有者有最高的权限可以对目录进行任何操作而组和其他用户只有读和执行权限。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n权限数字文件权限目录权限读r4允许用户读取文件内容允许用户查看目录内容写w2允许用户修改文件内容允许用户在目录中创建、删除和重命名文件执行 (x)1允许用户执行文件如程序或脚本允许用户进入目录\n特殊权限\nLinux 系统中,特殊权限是指那些不同于常规文件和目录权限(读、写、执行)的权限。这些特殊权限有助于控制用户或进程在访问或操作文件时所拥有的权限。\n\n文件设置粘滞位chmod o+t\n文件取消粘滞位chmod o-t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特殊权限示例描述Setuid (suid)chmod u+s当文件具有 setuid 权限时任何用户在执行该文件时都将获得文件所有者的权限。Setgid (sgid)chmod g+s当文件具有 setgid 权限时,用户可以以文件所属组的权限执行文件。对于目录,具有 setgid 权限的目录下创建的文件和子目录自动继承该目录的组。粘滞位 (Sticky Bit)chmod o+t当为目录设置粘滞位时只有文件所有者和 root 用户可以删除或重命名该目录中的文件。\n隐藏权限\nLinux 系统中,隐藏权限通常指那些不容易被用户发现的权限。这些权限可以通过 chattr 命令设置,并使用 lsattr 命令查看。隐藏权限有助于保护文件免受意外删除或修改,从而增强 Linux 系统的安全性。\n\n文件设置不可修改i权限chattr +i example.txt\n文件取消不可修改i权限chattr -i example.txt\n查看文件的隐藏权限lsattr example.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n隐藏权限chattr 参数作用Immutablei无法修改文件目录中子文件内容可修改不能新建或删除文件Append onlya仅允许追加内容无法覆盖/删除内容SyncS文件内容变更后立即同步到硬盘Secure deletions彻底删除不可恢复用 0 填充原文件所在硬盘区域No update of atimeA不再修改文件或目录的最后访问时间No update of btimeb不再修改文件或目录的存取时间Error checkingD检查压缩文件中的错误No dumpd使用 dump 命令备份时忽略本文件/目录Compressionc默认将文件或目录进行压缩Undeletionu删除后保留在硬盘中的数据方便恢复Tail-mergingt让文件系统支持尾部合并Direct accessx可以直接访问压缩文件中的内容\n系统分区\n**系统分区system partition是指计算机中用于存放操作系统和操作系统所需的系统文件和程序的分区也称为根分区root partition。**在计算机中,系统分区是最基本的分区之一,是计算机系统正常运行的核心部分。\n**在 PC 机上,系统分区通常使用 MBRMaster Boot Record或 GPTGUID Partition Table格式的分区表来管理磁盘分区。**MBR 是一种旧的分区表格式,它支持最多 4 个主分区或 3 个主分区和 1 个扩展分区,每个分区表项占用 16 个字节。GPT 是一种新的分区表格式,支持最多 128 个分区,每个分区表项占用 128 个字节,可以支持超过 2TB 的硬盘容量。\n在 Linux 系统中,系统分区通常包括 /boot、/、/usr、/var、/tmp、/home 等分区。其中,/boot 分区包含了操作系统的内核和引导程序;/ 分区包含了操作系统及其所有文件和程序;/usr 分区包含了系统的共享程序和文件;/var 分区包含了系统运行时生成的变量数据;/tmp 分区是临时文件存储分区;/home 分区则是存放用户数据和个人文件的分区。\n在进行磁盘分区时应该根据计算机的实际情况来选择合适的分区表格式和分区方案并为每个分区分配正确的类型和大小。在安装操作系统时应该按照系统要求来分配磁盘空间和设置系统分区以确保计算机系统的正常运行和数据安全。\n分区表\n**分区表Partition Table Type是计算机中用于管理硬盘分区的数据结构记录硬盘上分区的信息和布局方式。**操作系统通过读取分区表来获取硬盘分区的信息,并根据这些信息进行分区、格式化、挂载等操作。分区表通常存储在硬盘的特定位置,例如 MBRMaster Boot Record分区表通常存储在硬盘的第一个扇区而 GPTGUID Partition Table分区表则存储在硬盘的最后一个扇区。\n分区表的历史可以追溯到早期的操作系统例如 MS-DOS 和 Windows 95 等。早期的操作系统并不支持硬盘分区的概念,所有数据都存储在同一个分区中,这带来了数据管理和备份的不便,也限制了硬盘容量的利用。\n为了克服这些限制早期的操作系统开始使用分区表来管理硬盘分区。**最早被广泛使用的分区表格式之一是 MBR 分区表,出现于 1983 年,可以管理最多 4 个主分区或 3 个主分区和 1 个扩展分区。**另一种早期的分区表格式是 APMApple Partition Map由苹果公司开发用于管理 Macintosh 计算机上的硬盘分区。\n随着计算机硬件的不断升级MBR 分区表无法满足大容量硬盘的管理需求。于是,新的分区表格式 GPTGUID Partition Table应运而生。GPT 使用全球唯一的 GUID 标识硬盘上的分区信息,支持的最大硬盘容量达 EBexabyte级别最多可以管理 128 个分区。GPT 分区表还支持热插拔、校验和、备份分区表等特性,由于使用了 GUID 标识分区信息GPT 比 MBR 更加安全可靠。\n**MBR 分区方案以其广泛的兼容性和简单易用性著称,几乎所有现有的操作系统和硬件都支持 MBR且其分区表结构简单便于操作和维护。**然而MBR 也存在明显的缺点。首先,它只能支持最大 2TB 的硬盘容量在现代计算机应用中可能不够用。此外MBR 最多支持四个主分区或三个主分区加一个扩展分区这在某些情况下显得不足。最重要的是MBR 没有备份分区表的机制,一旦损坏,可能导致数据丢失。\n尽管 MBR 的兼容性较好但随着计算机技术的发展MBR 的局限性逐渐显现。未来MBR 可能会在特定场景下继续使用例如在旧式硬件或操作系统上。然而随着硬盘容量的增长和技术的进步MBR 正逐渐被 GPT 分区方案所取代。GPT 分区方案具有更大的磁盘容量支持、更多的分区数量和更高的数据安全性,已经成为现代操作系统和硬件的首选分区方案。\nMBR 分区\n**MBRMaster Boot Record是一种分区表结构位于硬盘的第一个扇区通常为磁盘的第一个物理扇区即 LBA 0。**MBR 包含了操作系统启动引导代码Bootloader和分区表信息。MBR 的主要作用是在计算机启动时加载操作系统。\nMBR 分区方案的历史可以追溯到 1983 年,当时 IBM PC/AT 发布。当时的 PC/AT 使用 16 位 Intel 80286 处理器,最大寻址空间为 16 MB。随着硬盘容量的增长MBR 分区方案逐渐显现出容量限制。因此GPTGUID Partition Table分区方案应运而生取代了 MBR。\n标准 MBR 结构\nMBR 分区表结构包括以下部分:\n\nBootloader446 字节):存放引导加载程序,负责将操作系统从磁盘加载到内存。\n分区表64 字节记录了硬盘上分区的信息如分区类型、分区大小、分区位置等。MBR 支持最多四个主分区或三个主分区加一个扩展分区。扩展分区可进一步划分为多个逻辑分区。\n签名2 字节一个固定的值0x55AA表示这是一个有效的 MBR 分区表。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字节偏移 (Hex)字节偏移 (Oct)字节偏移 (Dec)长度 (Byte)描述0x00000000446Bootloader引导加载程序0x1BE067644616主分区 1分区表条目 10x1CE070646216主分区 2分区表条目 20x1DE073647816主分区 3分区表条目 30x1EE076649416主分区 4分区表条目 40x1FE07765102签名0x55AA表示有效的 MBR 分区表)\n分区表条目结构\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字节偏移 (Hex)字节偏移 (Oct)字节偏移 (Dec)长度 (Byte)描述0x0000001引导标识符80h 为活动分区0x0100113起始磁头柱面、磁头、扇区0x0400441分区类型0x0500553结束磁头柱面、磁头、扇区0x0801084起始 LBA 地址0x0C014124分区扇区数\nGPT 分区\n**GPTGUID Partition Table是一种分区表结构适用于新型磁盘和操作系统。**GPT 是 UEFI统一可扩展固件接口规范的一部分用于替代传统的 MBRMaster Boot Record分区表。\n**随着计算机技术的发展以及硬盘容量的增长MBR 分区方案逐渐暴露出容量和分区数量的限制。**为解决这些问题Intel 在 1999 年引入了 GPT 分区方案。GPT 随后被纳入 UEFI 规范,成为现代计算机系统的主流分区方案。\n**GPT 分区方案具有显著的优势,包括支持超过 2TB 的磁盘容量,解决了 MBR 分区方案的容量限制。**此外GPT 允许创建多达 128 个分区,比 MBR 的分区数量更为灵活。数据安全性方面GPT 提供了备份分区表的机制有助于防止数据丢失。然而GPT 也存在兼容性问题。虽然大多数现代操作系统和硬件都支持 GPT但在较旧的系统中可能会遇到兼容性障碍。\nGPT 目前主要适用于大容量硬盘(容量大于 2TB、需要创建超过 4 个分区的情况,以及支持 UEFI 的现代操作系统和硬件。随着计算机技术的进步和硬盘容量的增加GPT 分区方案逐渐成为主流凭借其在磁盘容量支持、分区数量和数据安全性等方面的优势已成为现代操作系统和硬件的首选分区方案。随着旧式硬件和操作系统的逐渐淘汰GPT 的普及程度将进一步提高。\n展望未来GPT 分区方案可能会继续演进以适应新的技术发展和需求。比如随着硬盘容量的进一步扩大GPT 可能需要支持更大的磁盘容量和更多的分区数量。此外为了提高数据安全性GPT 可能会引入新的数据保护和恢复机制。同时,随着新型存储技术(如固态硬盘和非易失性内存)的发展,可能会出现新的分区方案,以满足这些存储设备的特性和性能需求。\n标准 GPT 结构\nGPT 分区表结构包括以下部分:\n\n保护性 MBRLBA 0在 GPT 磁盘的第一个扇区,包含一个伪 MBR以兼容旧式磁盘管理工具。\nGPT HeaderLBA 1包含 GPT 分区表的元数据,如分区表大小、分区表位置等。\nPartition Entry ArrayLBA 233存储分区条目信息。每个分区条目占用 128 字节,典型的 GPT 分区表支持最多 128 个分区。\n备份分区表GPT 在磁盘的末尾备份了 Header 和 Partition Entry Array以提高数据安全性。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n区域起始 LBA (Hex)起始 LBA (Oct)起始 LBA (Dec)长度(扇区)描述保护性 MBR (Protective MBR)0x00000001保护性主引导记录用于兼容旧式磁盘管理工具GPT Header0x10000111包含 GPT 分区表的元数据Partition Entry Array0x200002232存储分区条目信息每个分区条目占用 128 字节主数据区 (Primary Data)0x220004234可变磁盘的主要数据存储区域备份 Partition Entry Array-0x21-00041-3332磁盘末尾的备份分区条目数组备份 GPT Header-0x1-00001-11磁盘末尾的备份 GPT Header\n分区条目结构\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字节偏移 (Hex)字节偏移 (Oct)字节偏移 (Dec)长度 (Byte)描述0x00000016分区类型 GUID0x100201616唯一分区 GUID0x20040328起始 LBA 地址0x28050408结束 LBA 地址0x30060488分区属性如只读、隐藏等0x380705672分区名称UTF-16LE 编码)\n分区容量\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n分区建议大小说明/ (根分区)> 32GB存放操作系统及程序文件包括系统配置文件、应用程序及库文件等swap> 2GB虚拟内存用于内存交换在物理内存不足时起辅助作用/home剩余磁盘空间存放用户数据和配置文件根据个人需求分配磁盘空间/boot< 1GB存放引导程序和内核文件通常只需较小的磁盘空间/var> 16GB存放系统日志、缓存和其他可变数据/tmp< 32GB存放临时文件\n综合考虑以上各分区的建议大小总共空间建议至少应 ≥ 128GB这里的建议数值适用于大多数场景但请根据具体需求和磁盘空间进行调整。\n分区工具\nParted\nPartedGNU Parted是一个用于磁盘分区和管理的命令行工具全称为“GNU Partition Editor”。由 GNU 项目开发的自由软件Parted 主要用于创建、修改和删除磁盘分区,在 Linux 系统中广泛应用。它支持多种文件系统和磁盘标签,包括 ext2/ext3/ext4、FAT16/FAT32、NTFS、HFS+、XFS、JFS 等。\n历史背景\nParted 项目始于 1999 年,由 Andrew Clausen 和 Lennert Buytenhek 开发。其目标是提供一个类似于商业分区工具如 Partition Magic 的功能但在许可协议方面更自由同时支持更多的文件系统。随着时间的推移Parted 不断发展,添加了对更多文件系统和分区表的支持,并在许多 Linux 发行版中成为默认的磁盘分区工具。\n功能特性\nParted 使用库 libparted 进行磁盘分区操作。libparted 是一个用 C 语言编写的库提供底层分区表和文件系统的操作接口。Parted 的命令行界面调用 libparted 的接口,以实现对磁盘分区的管理。这种设计使得其他项目(如图形界面的 GParted也能利用 libparted 提供的功能。\nParted 具备以下优点:\n\n开源且免费遵循 GNU GPL 许可协议。\n多文件系统支持支持多种文件系统和磁盘标签。\n大容量硬盘支持支持大容量硬盘和 GPT 分区表。\n动态分区调整可以在不损坏数据的情况下调整分区大小。\n脚本自动化命令行界面易于编写脚本进行自动化操作。\n\n然而Parted 也存在一些缺点:\n\n命令行复杂性对新手来说命令行界面可能不如图形界面直观。\n文件系统支持限制对某些文件系统的支持可能不如专门针对这些文件系统的工具完善。\n\n使用方法\n启动 Parted 并指定目标磁盘(例如 /dev/sda\nsudo parted /dev/sda\n进入 Parted 交互界面后,可以使用以下常用命令:\n\nprint显示当前分区表。\nmklabel创建新的磁盘标签如 gpt 或 msdos。\nmkpart创建新分区。\nrm删除现有分区。\nresizepart调整分区大小。\nquit退出 Parted。\n\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作命令示例说明查看磁盘信息parted /dev/sda print显示 /dev/sda 的磁盘信息选择磁盘parted /dev/sda操作 /dev/sda 磁盘创建分区表parted /dev/sda mklabel gpt在 /dev/sda 上创建 GPT 分区表创建主分区parted /dev/sda mkpart primary ext4 1MiB 2GiB创建一个从 1MiB 到 2GiB 的 ext4 主分区创建扩展分区parted /dev/sda mkpart extended 2GiB 4GiB创建一个从 2GiB 到 4GiB 的扩展分区创建逻辑分区parted /dev/sda mkpart logical ext4 2GiB 4GiB创建一个从 2GiB 到 4GiB 的 ext4 逻辑分区删除分区parted /dev/sda rm 1删除编号为 1 的分区改变分区文件系统类型parted /dev/sda set 1 ext4 on将编号为 1 的分区的文件系统类型设置为 ext4设置引导标志parted /dev/sda set 1 boot on将编号为 1 的分区设置为引导分区移动分区parted /dev/sda move 1 2GiB 4GiB将编号为 1 的分区从当前位置移到 2GiB 到 4GiB 之间扩展分区parted /dev/sda resizepart 1 4GiB将编号为 1 的分区大小扩展到 4GiB缩小分区parted /dev/sda resizepart 1 2GiB将编号为 1 的分区大小缩小到 2GiB激活分区parted /dev/sda set 1 lvm on激活编号为 1 的分区以用于 LVM取消激活分区parted /dev/sda set 1 lvm off取消激活编号为 1 的分区以用于 LVM\nParted 提供了一种免费且开源的磁盘分区管理方案,它解决了在 Linux 系统下对磁盘进行分区操作的需求。此外,它还支持许多文件系统和磁盘标签,从而可以满足不同用户的需求。\nParted 适用于在 Linux 系统下进行磁盘分区管理的场景,包括创建、删除、调整分区大小等操作。它特别适合那些需要进行批量操作或自动化任务的场景,因为其命令行界面易于编写脚本。\nParted 将继续保持对新文件系统和磁盘技术的支持以适应不断发展的硬件和软件环境。此外开发者可能会继续改进其性能和稳定性以满足用户在各种场景下的需求。随着技术的发展Parted 也可能会支持新的存储介质如固态硬盘、NVMe 等。同时对于一些现有问题如对特定文件系统支持的不完善未来可能会有所改进。另外随着图形界面工具的普及Parted 可能会与这些工具更紧密地集成,以提供更友好的用户体验。\nGdisk\ngdiskGUID Partition Table Disk是一个用于操作 GPT 分区表的命令行工具。它的功能与传统的 fdisk 工具类似,但专门针对 GPT 分区表进行了优化。gdisk 是由 Rod Smith 开发的,旨在满足大容量硬盘和 UEFI统一可扩展固件接口环境下的分区需求。\n历史背景\ngdisk 的开发始于 2009 年,那时 MBR 分区表已经无法满足对大容量硬盘的需求。随着时间的推移gdisk 不断演进,支持了越来越多的功能,成为了处理 GPT 分区表的重要工具。GPT 分区表相对于 MBR 分区表,具有更大的灵活性和扩展性,能够支持更大容量的硬盘和更多的分区数量。\n功能特性\ngdisk 基于 libparted 库,通过调用底层库函数来读取、修改、写入 GPT 分区表信息。这使得 gdisk 能够在不同的平台上运行。其主要功能包括:\n\n查看分区表列出磁盘上的所有 GPT 分区及其详细信息。\n创建新分区在未使用的磁盘空间上创建新的 GPT 分区。\n删除分区移除现有的 GPT 分区,使其空间重新变为未使用状态。\n修改分区调整 GPT 分区的大小或属性。\n转换分区表将 MBR 分区表转换为 GPT 分区表。\n修复分区表检查并修复损坏的 GPT 分区表。\n\n使用方法\n启动 gdisk 并指定目标磁盘(例如 /dev/sda\nsudo gdisk /dev/sd\n进入 gdisk 交互界面后,可以使用以下常用命令:\n\np显示当前分区表。\nn创建新分区。\nd删除现有分区。\nt更改分区类型。\nw写入分区表并退出。\nq退出而不保存更改。\nr进入恢复和转换菜单执行高级操作。\n\nGPT 与 UEFI\nGPT 分区表解决了 MBR 分区表的许多限制,例如最大仅支持 2TB 的磁盘容量和最多 4 个主分区的限制。GPT 分区表可以支持更大的磁盘(最大 18EB和几乎无限数量的分区。此外GPT 分区表与 UEFI 引导方式兼容,提供了更强的灵活性和更好的系统引导性能。\nFdisk\nfdisk 是一个用于 Linux 系统的磁盘分区管理工具。它提供创建、删除和修改分区表以及设置分区启动标志等功能。fdisk 支持 MBR主引导记录分区表是适用于 BIOS 分区表管理的经典工具。\n历史背景\nfdisk 最早出现在 Unix 系统中,随着时间的推移,它被移植到了 Linux 平台。由于其简单易用和功能强大的特点fdisk 成为 Linux 系统中非常受欢迎的分区管理工具。然而,随着 GPT 分区表的出现和逐渐普及fdisk 的功能局限逐渐显现出来,于是 gdisk 等工具应运而生,以支持更加现代的 GPT 分区表格式。\n功能特性\nfdisk 通过读取磁盘的主引导记录MBR来获取分区信息。MBR 位于磁盘的第一个扇区,包含了分区表和启动程序。使用 fdisk 可以执行以下操作:\n\n查看分区表列出磁盘上的所有分区及其详细信息。\n创建新分区在未使用的磁盘空间上创建新的分区。\n删除分区移除现有的分区使其空间重新变为未使用状态。\n修改分区调整分区的大小或属性。\n设置分区启动标志标记某个分区为可引导分区。\n\n使用方法\n启动 fdisk 并指定目标磁盘(例如 /dev/sda\nsudo fdisk /dev/sda\n\n进入 fdisk 交互界面后,可以使用以下常用命令:\n\np显示当前分区表。\nn创建新分区。\nd删除现有分区。\nt更改分区类型。\na切换启动标志。\nw写入分区表并退出。\nq退出而不保存更改。\n\nMBR 与 GPT\nfdisk 主要用于管理 MBR 分区表。MBR 分区表具有以下限制:\n\n支持的最大磁盘容量为 2TB。\n最多只能有 4 个主分区,或者 3 个主分区和 1 个扩展分区(可以包含多个逻辑分区)。\n\n随着硬盘容量的增加和新技术的发展GPTGUID 分区表)逐渐取代了 MBR。GPT 支持更大的磁盘和更多的分区,并与 UEFI 引导方式兼容。对于需要管理 GPT 分区表的系统,可以使用 gdisk 或 parted 等工具。\n磁盘管理\n磁盘格式化\n磁盘格式化是将磁盘分区初始化为特定的文件系统以便操作系统能够读写数据。格式化是磁盘准备使用的关键步骤涉及创建文件系统、设置必要的结构和数据以确保存储和检索信息的高效性和安全性。\n\nmkfs通用的文件系统格式化工具支持多种文件系统类型。\nmke2fs专门用于创建 ext2、ext3、ext4 文件系统的工具。\n\n以下是一些常用的磁盘格式化命令及其说明\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明mkfs -t ext4 /dev/sda1将/dev/sda1 分区格式化为 ext4 文件系统mke2fs -j /dev/sda1将/dev/sda1 分区格式化为 ext3 文件系统带日志功能mke2fs -b 4096 /dev/sda1将/dev/sda1 分区格式化为 ext2 文件系统,并设置块大小为 4096 字节\n磁盘检查与修复\n磁盘检查与修复主要是检查文件系统的完整性、查找并修复磁盘错误。\n常用的磁盘检查与修复工具有\n\n文件系统检查fsck、e2fsck针对 ext2、ext3、ext4\n坏扇区检测badblocks\n数据恢复testdisk、photorec\n文件系统修复xfs_repair针对 xfs、btrfs-check针对 btrfs\n\n常用命令及选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明fsck /dev/sda1检查并尝试修复/dev/sda1 分区的文件系统e2fsck -f /dev/sda1强制检查并尝试修复/dev/sda1 分区的 ext2/ext3/ext4 文件系统badblocks -v /dev/sda1以详细模式检查/dev/sda1 分区的坏扇区testdisk /dev/sda检查并尝试恢复/dev/sda 磁盘上的分区表、引导扇区等photorec /dev/sda1从/dev/sda1 分区中恢复丢失的文件xfs_repair /dev/sda1检查并修复/dev/sda1 分区的 xfs 文件系统btrfs-check —repair /dev/sda1检查并修复/dev/sda1 分区的 btrfs 文件系统\n磁盘清理与优化\n磁盘清理与优化主要是清除无用的临时文件、整理碎片、压缩磁盘空间以及加密磁盘等操作以提高磁盘的使用效率和安全性。\n常用的磁盘清理与优化工具有\n\n清理临时文件tmpwatch、systemd-tmpfiles\n碎片整理e2fsck针对 ext 系列、xfs_fsr针对 xfs\n磁盘压缩btrfs filesystem defragment针对 btrfs\n磁盘加密dm-crypt、LUKS、eCryptfs、VeraCrypt 等\n\n常用命令及选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明tmpwatch —mtime 7 /tmp删除/tmp 目录中超过 7 天未修改的临时文件systemd-tmpfiles —clean按照/tmpfiles.d/目录中的配置文件清理过期的临时文件e2fsck -D /dev/sda1对/dev/sda1 分区的 ext2/ext3/ext4 文件系统进行碎片整理xfs_fsr /dev/sda1对/dev/sda1 分区的 xfs 文件系统进行碎片整理btrfs filesystem defragment /mnt/btrfs对挂载在/mnt/btrfs 的 btrfs 文件系统进行压缩整理cryptsetup luksFormat /dev/sda1使用 LUKS 对/dev/sda1 分区进行加密veracrypt —create /dev/sda1使用 VeraCrypt 对/dev/sda1 分区进行加密\n磁盘监控与诊断\n磁盘清理与优化主要是清除无用的临时文件、整理碎片、压缩磁盘空间以及加密磁盘等操作以提高磁盘的使用效率和安全性。\n常用的磁盘清理与优化工具有\n\n清理临时文件tmpwatch、systemd-tmpfiles\n碎片整理e2fsck针对 ext 系列、xfs_fsr针对 xfs\n磁盘压缩btrfs filesystem defragment针对 btrfs\n磁盘加密dm-crypt、LUKS、eCryptfs、VeraCrypt 等\n\n常用命令及选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明tmpwatch —mtime 7 /tmp删除/tmp 目录中超过 7 天未修改的临时文件systemd-tmpfiles —clean按照/tmpfiles.d/目录中的配置文件清理过期的临时文件e2fsck -D /dev/sda1对/dev/sda1 分区的 ext2/ext3/ext4 文件系统进行碎片整理xfs_fsr /dev/sda1对/dev/sda1 分区的 xfs 文件系统进行碎片整理btrfs filesystem defragment /mnt/btrfs对挂载在/mnt/btrfs 的 btrfs 文件系统进行压缩整理cryptsetup luksFormat /dev/sda1使用 LUKS 对/dev/sda1 分区进行加密veracrypt —create /dev/sda1使用 VeraCrypt 对/dev/sda1 分区进行加密fio —name=test —rw=read —bs=4k —numjobs=4 —size=1G —runtime=60s —ioengine=libaio —iodepth=32 —time_based测试磁盘的 I/O 性能,以 4K 块大小、深度为 32 的顺序读取方式运行 60 秒的测试iozone -a -s 1G使用 iozone 工具对 1GB 文件进行自动性能测试df -h以人类可读的格式显示磁盘空间使用情况du -sh /home显示/home 目录的磁盘空间占用情况ncdu /home以图形界面显示/home 目录的磁盘空间占用情况iostat -xz 5每隔 5 秒输出一次磁盘 I/O 统计信息iotop -o实时显示当前磁盘 I/O 活动的进程,只显示有 I/O 操作的进程\nLVM\n**逻辑卷管理Logical Volume ManagementLVM是一种在 Linux 系统中管理硬盘空间的技术。**它允许将多个硬盘分区或物理硬盘组合成一个逻辑卷从而更加灵活地管理存储空间。LVM 允许管理员在不重启系统的情况下调整磁盘空间分配提供了一些高级的存储管理功能如快照、镜像和跨磁盘分区等。LVM 通常被用于服务器环境中,因为它可以有效地处理大容量存储设备。\n历史背景\nLVM 最初是由 Sistina Software 公司于 1998 年开发的,旨在提供一种动态分区管理技术,以替代传统的静态分区方式。在 2001 年Red Hat 收购了 Sistina Software 公司,将 LVM 整合到 Red Hat Enterprise Linux 中,并在 2002 年的 Linux 内核 2.4.0 版本中首次亮相。此后LVM 逐渐成为了 Linux 系统中的标准组件之一,并且得到了广泛的应用。\n实现原理\nLVM 的实现原理是将物理存储设备如磁盘、分区分为若干个物理卷PV并将多个物理卷组成一个卷组VG。然后在卷组上创建一个或多个逻辑卷LV并将逻辑卷格式化为文件系统。当需要增加存储空间时可以将一个或多个物理卷添加到卷组中并将空间分配给逻辑卷。当需要缩小存储空间时可以将逻辑卷缩小并将空闲空间返回给卷组。\n\nLVM 由以下三个主要组件组成:\n\n物理卷Physical VolumePV物理卷是指磁盘或分区等物理存储设备。在使用 LVM 之前,需要将物理存储设备划分为物理卷,并且将它们标记为 LVM 可用的卷。\n卷组Volume GroupVG卷组是由一个或多个物理卷组成的逻辑容器。卷组可以包含多个物理卷这些物理卷可以来自不同的磁盘也可以是同一磁盘上的不同分区。在 LVM 中,卷组是用来为逻辑卷提供空间的。\n逻辑卷Logical VolumeLV逻辑卷是在卷组上创建的逻辑分区。逻辑卷可以动态地分配和释放存储空间并且可以根据需要调整大小。逻辑卷可以被格式化为文件系统并像常规分区一样使用。\n\n主要特性\n逻辑卷管理器LVMLogical Volume Manager是 Linux 系统中管理磁盘存储的灵活且强大的工具。它允许系统管理员在不重新分区的情况下调整文件系统的大小从而更高效地利用存储资源。LVM 的主要特性包括:\n\n动态卷管理提供灵活性允许在系统运行时动态调整存储配置无需重新启动系统或中断服务。创建、删除和调整逻辑卷和物理卷的大小都变得更加方便。\n存储虚拟化将物理存储设备抽象成卷组Volume Group, VG和逻辑卷Logical Volume, LV实现更高层次的存储控制。这种虚拟化使得数据可以在物理设备之间移动而不影响上层应用。\n卷组与逻辑卷卷组将多个物理卷Physical Volume, PV聚合提供统一的存储资源池。逻辑卷可以根据需要调整大小甚至在多个物理设备之间扩展或缩小提供极大的灵活性。\n条带化与镜像支持条带化striping和镜像mirroring功能。条带化通过将数据分散存储在多个物理卷上提高磁盘 I/O 性能;镜像则提供数据冗余,增强存储系统的可靠性。\n快照功能允许创建卷的时间点副本用于数据备份、系统恢复和测试确保数据的一致性和完整性。\nRAID 支持:能够与软件 RAID 结合使用,提供额外的数据保护和性能增强。结合 LVM 和 RAID 技术,可以实现更高的灵活性和可靠性。\n在线调整允许在系统运行过程中进行卷的扩展、缩减和迁移无需停机。这对于高可用性要求高的企业环境尤为重要。\n简化管理提供一系列命令行工具如 lvcreate、lvremove、lvextend和图形化界面工具如 system-config-lvm使存储管理任务变得简便降低了管理复杂度。\n集成与兼容性与各种文件系统如 ext4、XFS、Btrfs和 Linux 发行版高度集成,提供广泛的兼容性和无缝协作。\n\n常用命令\n物理卷 (PV)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述语法格式示例命令pvchange更改物理卷属性pvchange [选项] 物理卷pvchange -x n /dev/sda1pvck检查物理卷的一致性pvck 物理卷pvck /dev/sda1pvcreate创建一个新的物理卷pvcreate 设备pvcreate /dev/sda1pvdisplay显示物理卷的属性pvdisplay [选项] [物理卷]pvdisplay /dev/sda1pvmove移动物理卷上的数据pvmove [选项] 源物理卷 [目标物理卷]pvmove /dev/sda1 /dev/sdb1pvremove从卷组中移除物理卷pvremove 物理卷pvremove /dev/sda1pvresize调整物理卷的大小pvresize [选项] 物理卷pvresize --setphysicalvolumesize 500G /dev/sda1pvs显示物理卷的概要信息pvs [选项] [物理卷]pvspvscan扫描系统中的物理卷pvscan [选项]pvscan\n卷组 (VG)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述语法格式示例命令vgcfgbackup备份卷组配置vgcfgbackup [选项] 卷组vgcfgbackup vg01vgcfgrestore恢复卷组配置vgcfgrestore [选项] 卷组vgcfgrestore vg01vgchange更改卷组属性vgchange [选项] 卷组vgchange -a y vg01vgck检查卷组的一致性vgck [选项] 卷组vgck vg01vgcreate创建一个新的卷组vgcreate 卷组 物理卷...vgcreate vg01 /dev/sda1vgconvert转换卷组元数据格式vgconvert [选项] 卷组vgconvert --metadataformat lvm2 vg01vgdisplay显示卷组的属性vgdisplay [选项] [卷组]vgdisplay vg01vgexport导出卷组vgexport [选项] 卷组vgexport vg01vgextend向卷组中添加物理卷vgextend 卷组 物理卷vgextend vg01 /dev/sdb1vgimport导入卷组vgimport [选项] 卷组vgimport vg01vgimportclone导入克隆卷组vgimportclone [选项] 卷组vgimportclone vg01vgimportdevices导入设备的卷组vgimportdevices [选项] 卷组vgimportdevices vg01vgmerge合并两个卷组vgmerge 卷组1 卷组2vgmerge vg01 vg02vgmknodes重建设备节点vgmknodes [选项]vgmknodesvgreduce从卷组中移除物理卷vgreduce 卷组 物理卷vgreduce vg01 /dev/sda1vgremove删除卷组vgremove 卷组vgremove vg01vgrename重命名卷组vgrename 卷组 新名称vgrename vg01 vg02vgs显示卷组的概要信息vgs [选项] [卷组]vgsvgscan扫描系统中的卷组vgscan [选项]vgscanvgsplit分割卷组vgsplit [选项] 卷组1 卷组2 物理卷vgsplit vg01 vg02 /dev/sda1\n逻辑卷 (LV)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述语法格式示例命令lvcreate创建一个新的逻辑卷lvcreate [选项] 卷组lvcreate -L 10G -n lv01 vg01lvchange更改逻辑卷属性lvchange [选项] 逻辑卷lvchange -ay /dev/vg01/lv01lvconvert转换逻辑卷类型lvconvert [选项] 逻辑卷lvconvert --type raid1 /dev/vg01/lv01lvdisplay显示逻辑卷的属性lvdisplay [选项] [逻辑卷]lvdisplay /dev/vg01/lv01lvextend扩展逻辑卷的大小lvextend [选项] 逻辑卷lvextend -L +5G /dev/vg01/lv01lvreduce缩减逻辑卷的大小lvreduce [选项] 逻辑卷lvreduce -L 5G /dev/vg01/lv01lvremove删除逻辑卷lvremove 逻辑卷lvremove /dev/vg01/lv01lvrename重命名逻辑卷lvrename 逻辑卷 新名称lvrename /dev/vg01/lv01 lv02lvresize调整逻辑卷的大小lvresize [选项] 逻辑卷lvresize -L 15G /dev/vg01/lv01lvs显示逻辑卷的概要信息lvs [选项] [逻辑卷]lvslvscan扫描系统中的逻辑卷lvscan [选项]lvscan\n其他命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述语法格式示例命令lvmLVM 命令的主入口lvm [命令]lvmlvm.confLVM 配置文件n/an/alvmconfig显示和更新 LVM 配置lvmconfig [选项]lvmconfig --type fulllvmdevices管理 LVM 设备lvmdevices [选项]lvmdevices --adddev /dev/sda1lvm-fullreport显示 LVM 完整报告lvm-fullreport [选项]lvm-fullreportlvm-lvpoll轮询 LVM 逻辑卷lvm-lvpoll [选项]lvm-lvpollblkdeactivate停用块设备blkdeactivate [选项]blkdeactivate alllvmdump创建 LVM 状态转储文件lvmdump [选项]lvmdump --dumpconfigdmeventd设备映射事件守护进程dmeventd [选项]dmeventd -dlvmpolldLVM 轮询守护进程lvmpolld [选项]lvmpolld -dlvmlockdLVM 锁定守护进程lvmlockd [选项]lvmlockd -dlvmlockctl控制 LVM 锁定lvmlockctl [选项]lvmlockctl --glcmirrord集群镜像守护进程cmirrord [选项]cmirrord -dlvmdbusdLVM D-Bus 守护进程lvmdbusd [选项]lvmdbusd -dfsadm文件系统调整fsadm [选项] 操作fsadm resize /dev/vg01/lv01lvmsystemid显示 LVM 系统 IDlvmsystemid [选项]lvmsystemidlvmreport生成 LVM 报告lvmreport [选项]lvmreport --alllvmcache管理 LVM 缓存lvmcache [选项]lvmcache --configlvmraid管理 LVM RAIDlvmraid [选项]lvmraid --statuslvmthin管理 LVM 精简卷lvmthin [选项]lvmthin --usagelvmvdo管理 LVM VDOlvmvdo [选项]lvmvdo --statuslvmautoactivation自动激活 LVM 逻辑卷lvmautoactivation [选项]lvmautoactivation --statusdmsetup设备映射器的命令行接口dmsetup [命令]dmsetup statusdmstats设备映射器统计信息dmstats [命令]dmstats listreadline命令行编辑库n/an/a\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项/全拼释义-v, --verbose显示详细的信息-f, --force强制执行操作-L, --size指定逻辑卷的大小-n, --name指定逻辑卷的名称-i, --stripes指定逻辑卷的条带数-r, --resizefs在逻辑卷大小改变后自动调整文件系统-a, --activate激活或停用卷-y, --yes自动回答“是”以确认操作-P, --partial允许部分操作完成--addtag向卷、卷组或物理卷添加标签--deltag从卷、卷组或物理卷删除标签--config使用特定配置文件--metadatacopies n设置元数据区域的备份级别为 n--setphysicalvolumesize调整物理卷的大小-l, --extents指定逻辑卷的大小以 PE物理扩展的数量-s, --snapshot创建逻辑卷的快照-t, --test运行测试模式不实际执行命令-v, --verbose显示详细输出\nLVM 示例\ngraph LR;\n A[创建物理卷 PV] --> B[创建卷组 VG ];\n B --> C[创建逻辑卷 LV ];\n C --> D[格式化文件系统];\n D --> E[挂载文件系统];\n E --> F[使用文件系统];\n \n\n\n创建物理卷 (PV)\n\n在实际操作中我们需要首先查看系统中有哪些可用的物理卷使用命令 lsblk 可以列出所有的物理磁盘及其分区信息。然后使用 pvcreate 命令将指定的物理卷初始化为 LVM 物理卷,例如:\n$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS\nnvme0n1 259:0 0 64G 0 disk\n├─nvme0n1p1 259:1 0 1G 0 part /boot\n└─nvme0n1p2 259:2 0 63G 0 part\n ├─rhel-root 253:0 0 39.7G 0 lvm /\n ├─rhel-swap 253:1 0 3.9G 0 lvm [SWAP]\n └─rhel-home 253:2 0 19.4G 0 lvm /home\nnvme0n2 259:3 0 8G 0 disk\nnvme0n3 259:4 0 8G 0 disk\n$ pvcreate /dev/nvme0n2 \n Physical volume "/dev/nvme0n2" successfully created.\n$ pvcreate /dev/nvme0n3\n Physical volume "/dev/nvme0n3" successfully created.\n\n创建卷组 (VG)\n\n在物理卷初始化之后我们需要将其添加到一个卷组中。使用 vgcreate 命令可以创建一个新的卷组,并将一个或多个物理卷添加到其中,例如:\n$ vgcreate data_nvme_vg /dev/nvme0n2 /dev/nvme0n3\n Volume group "data_nvme_vg" successfully created\n$ vgdisplay data_nvme_vg\n --- Volume group ---\n VG Name data_nvme_vg\n System ID\n Format lvm2\n Metadata Areas 2\n Metadata Sequence No 1\n VG Access read/write\n VG Status resizable\n MAX LV 0\n Cur LV 0\n Open LV 0\n Max PV 0\n Cur PV 2\n Act PV 2\n VG Size 15.99 GiB\n PE Size 4.00 MiB\n Total PE 4094\n Alloc PE / Size 0 / 0\n Free PE / Size 4094 / 15.99 GiB\n VG UUID MbZpcX-1H5P-RKBU-aEAM-9AE3-ums0-nQ2zVc\n\n创建逻辑卷 (LV)\n\n在卷组创建之后我们可以使用 lvcreate 命令创建一个或多个逻辑卷,并指定它们的大小、名称、副本数等信息,例如:\n$ lvcreate -L 8G -n data_nvme_lv1 data_nvme_vg\n Logical volume "data_nvme_lv1" created.\n$ lvdisplay /dev/data_nvme_vg/data_nvme_lv1\n --- Logical volume ---\n LV Path /dev/data_nvme_vg/data_nvme_lv1\n LV Name data_nvme_lv1\n VG Name data_nvme_vg\n LV UUID YFSoPg-xCQu-EFLB-lqUC-o7u5-5bhS-N6LJRT\n LV Write Access read/write\n LV Creation host, time rhel, 2023-04-24 10:23:20 +0800\n LV Status available\n # open 0\n LV Size 8.00 GiB\n Current LE 2048\n Segments 2\n Allocation inherit\n Read ahead sectors auto\n - currently set to 8192\n Block device 253:3\n\n格式化文件系统\n\n在逻辑卷创建之后我们需要格式化其文件系统以便进行挂载和使用。使用 mkfs 命令可以对逻辑卷上的文件系统进行格式化,例如:\n$ mkfs.ext4 /dev/data_nvme_vg/data_nvme_lv1\nmke2fs 1.46.5 (30-Dec-2021)\n创建含有 2097152 个块(每块 4k和 524288 个inode的文件系统\n文件系统UUID68dd2677-4f0e-421f-bf14-9216eb34b3e5\n超级块的备份存储于下列块\n 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632\n \n正在分配组表 完成\n正在写入inode表 完成\n创建日志16384 个块)完成\n写入超级块和文件系统账户统计信息 已完成\n\n挂载文件系统\n\n在格式化文件系统之后我们需要将其挂载到系统中的一个目录中以便进行使用。使用 mount 命令可以将格式化后的文件系统挂载到指定的目录中,例如:\n$ mkdir /mnt/data_nvme_lv1\n$ mount /dev/data_nvme_vg/data_nvme_lv1 /mnt/data_nvme_lv1/\n\n使用文件系统\n\n最后我们可以在挂载的文件系统上进行文件的读写和访问等操作例如\n$ cd /mnt/data_nvme_lv1/\n$ ll\n总用量 16\ndrwx------. 2 root root 16384 4月 24 10:25 lost+found\n[root@rhel data_nvme_lv1]# echo "hello world!" >> demo.txt\n[root@rhel data_nvme_lv1]# cat demo.txt\nhello world!\n\n调整逻辑卷容量大小\n\n如果想调整 lv 逻辑卷的容量大小可以使用 lvextend、resize2fs例如为 /dev/data_nvme_vg/data_nvme_lv1 增加 2GB 容量。\n$ lvextend -L +2G /dev/data_nvme_vg/data_nvme_lv1\n Size of logical volume data_nvme_vg/data_nvme_lv1 changed from 8.00 GiB (2048 extents) to 10.00 GiB (2560 extents).\n Logical volume data_nvme_vg/data_nvme_lv1 successfully resized.\n$ resize2fs /dev/data_nvme_vg/data_nvme_lv1\nresize2fs 1.46.5 (30-Dec-2021)\n/dev/data_nvme_vg/data_nvme_lv1 上的文件系统已被挂载于 /mnt/data_nvme_lv1需要进行在线调整大小\n \nold_desc_blocks = 1, new_desc_blocks = 2\n/dev/data_nvme_vg/data_nvme_lv1 上的文件系统现在为 2621440 个块(每块 4k。\n \n$ df -h /dev/data_nvme_vg/data_nvme_lv1\n文件系统 容量 已用 可用 已用% 挂载点\n/dev/mapper/data_nvme_vg-data_nvme_lv1 9.8G 28K 9.3G 1% /mnt/data_nvme_lv1\n其他文件系统\n网络文件系统\n网络文件系统如 NFS、Samba允许不同操作系统的计算机在网络上共享文件和目录。这使得跨平台文件共享变得简单提高了团队协作效率。NFS 主要用于 UNIX/Linux 系统间的文件共享,而 Samba 则提供了在 Windows 和 UNIX/Linux 系统间共享文件的能力。\niSCSI\niSCSIInternet Small Computer System Interface是一种网络存储技术允许将存储设备如磁盘阵列共享给其他计算机。通过 iSCSI计算机可以通过网络访问共享的存储设备就像直接连接到本地硬盘一样。这大大简化了存储管理并提高了存储资源的利用率。\nRAID 透传\nRAID 透传是一种将物理 RAID 卡的功能直接传递给虚拟机的技术。通过 PCIe 直通,虚拟机可以直接访问 RAID 卡,从而获得更好的存储性能和可靠性。这种方法允许虚拟机完全利用 RAID 卡的性能和冗余功能,提高数据保护和虚拟机性能。\n存储池\n存储池是一种将多个物理磁盘组合成一个逻辑存储单元的技术。一些现代文件系统如 ZFS、Btrfs支持存储池功能允许管理员轻松地添加、删除或替换磁盘以满足存储需求。存储池提供了数据冗余、快照、自动修复等高级功能确保数据的可靠性和完整性。\n分布式存储\n分布式存储系统如 Ceph、GlusterFS是一种将数据分散在多个存储节点上的技术实现高可用、高扩展性的存储方案。分布式存储系统通常采用数据副本、纠删码等技术保证数据的可靠性当部分存储节点发生故障时系统仍然可以继续提供服务。此外分布式存储系统具有良好的横向扩展性可以通过添加更多节点来扩展存储容量和性能。\n备份恢复\n备份恢复是计算机系统管理的重要部分涉及到数据的备份、存储和恢复等操作。通过合理的备份策略和方式可以确保系统的稳定性和数据的安全。\n备份策略\n备份策略是指备份数据的范围和周期。常见的备份策略\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n备份策略优点缺点适用场景完整备份可以完整地备份所有数据恢复时速度快备份时间长备份数据量大占用存储空间大数据量较小、备份频率较低、对数据完整性要求较高的场景增量备份备份时间短占用存储空间小可以快速备份所有修改的数据恢复速度慢需要还原完整的备份链备份链中任意一次备份失败后续备份将无法进行大量数据需要备份数据变化较频繁的场景差异备份备份数据量小备份速度快恢复速度快恢复速度慢需要还原完整的备份链备份链中任意一次备份失败后续备份将无法进行备份频率较高数据变化较频繁但备份数据量不宜过大的场景定期备份定期备份可以保证备份数据的实时性和完整性需要人工干预备份可能会漏备数据量较大、需要保证数据实时性和完整性的场景混合备份策略可以充分利用完整备份、增量备份和差异备份各自的优点灵活备份实现较为复杂管理备份链需要一定的技术水平备份数据量大数据量较大、备份频率较高、需要保证备份数据完整性和实时性的场景\n**备份策略的选择应该根据实际的业务需求和场景来确定。**例如,对于一个数据量较小、备份频率较低、对数据完整性要求较高的场景,完整备份可能是更好的选择,但如果数据变化较频繁,备份数据量较大,增量备份或差异备份可能是更好的选择。在实际应用中,也可以根据不同的数据类型和备份需求,结合多种备份策略进行混合备份,以达到更好的备份效果。\n备份方式\n备份方式是指备份的数据类型和范围。常见的备份方式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n备份类型概念优点缺点适用场景系统备份对整个操作系统进行备份备份恢复速度快可快速恢复整个系统需要重启系统才能恢复需要专业技术人员进行操作升级系统、修复系统、系统迁移、系统备份恢复数据备份对重要数据进行备份备份恢复速度快只恢复需要的数据节省存储空间无法恢复系统设置不适用于系统级别的恢复备份重要数据、恢复文件和数据分区备份对磁盘分区进行备份可以备份恢复单独的分区无法恢复其他分区的数据恢复速度慢对某个分区进行备份、对分区进行数据恢复磁盘备份对整个硬盘进行备份包括系统和数据备份恢复速度快可快速恢复整个系统需要专业技术人员进行操作恢复速度慢备份数据量大硬盘更换、系统崩溃、病毒攻击、数据丢失等紧急情况的备份恢复\n**不同类型的备份应该根据实际的业务需求和场景来选择。**例如,对于需要备份整个系统的情况,系统备份可能是最好的选择;对于只需要备份重要数据的情况,数据备份可能是更好的选择;对于需要备份整个硬盘的情况,磁盘备份可能是最好的选择。在实际应用中,也可以结合多种备份方式进行备份,以达到更好的备份效果。\n备份工具\n备份工具是用于执行备份任务的软件。常见的备份工具有\n\n文件级别备份rsync、tar、cpio、duplicity 等\n块级别备份dd、partclone、Clonezilla 等\n数据库备份mysqldump、pg_dump、oracle-exp 等\n\n常用命令及选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明rsync -avz /src/ /dst/使用 rsync 工具将/src/目录下的文件同步到/dst/目录下tar czf backup.tar.gz /src/使用 tar 工具将/src/目录下的文件打包成 backup.tar.gz 文件cpio -o > backup.cpio < filelist.txt使用 cpio 工具将 filelist.txt 中的文件打包成 backup.cpio 文件duplicity /src/ file:///dst/使用 duplicity 工具将/src/目录下的文件加密并备份到/dst/目录下dd if=/dev/sda1 of=backup.img使用 dd 工具备份/dev/sda1 分区到 backup.img 文件partclone.ext4 -c -s /dev/sda1 -o backup.img使用 partclone 工具备份 ext4 格式的/dev/sda1 分区到 backup.img 文件mysqldump -u user -p dbname > backup.sql使用 mysqldump 工具备份 MySQL 数据库到 backup.sql 文件pg_dump -U user dbname > backup.sql使用 pg_dump 工具备份 PostgreSQL 数据库到 backup.sql 文件\n恢复操作\n恢复操作是指根据备份数据恢复系统或数据的过程。常见的恢复操作有\n\n系统还原使用系统备份恢复操作系统、配置文件、应用程序等\n数据恢复从数据备份中恢复用户数据、数据库等\n磁盘恢复使用磁盘备份恢复整个磁盘及其上的所有分区\n备份恢复策略根据备份策略选择合适的恢复方法和顺序\n\n常用命令及选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令说明rsync -avz /src/ /dst/使用 rsync 工具从/src/目录下恢复文件到/dst/目录下tar xzf backup.tar.gz -C /dst/使用 tar 工具从 backup.tar.gz 文件恢复文件到/dst/目录下cpio -i < backup.cpio使用 cpio 工具从 backup.cpio 文件恢复文件duplicity restore file:///src/ /dst/使用 duplicity 工具从/src/目录下的加密备份恢复文件到/dst/目录下dd if=backup.img of=/dev/sda1使用 dd 工具从 backup.img 文件恢复/dev/sda1 分区partclone.ext4 -r -s backup.img -o /dev/sda1使用 partclone 工具从 backup.img 文件恢复 ext4 格式的/dev/sda1 分区mysql -u user -p dbname < backup.sql使用 mysql 命令恢复 MySQL 数据库从 backup.sql 文件psql -U user dbname < backup.sql使用 psql 命令恢复 PostgreSQL 数据库从 backup.sql 文件"},"Technology/OperatingSystem/Linux/7.存储管理/fio-存储性能测试":{"title":"fio 存储性能测试","links":[],"tags":["技术/操作系统","Linux/存储管理"],"content":"Fio 概述\nFio 是什么\nfioFlexible I/O Tester是一款用于生成磁盘 I/O 测试负载的工具广泛用于存储设备的性能测试和分析。fio 支持多种 I/O 模式、并发任务以及灵活的配置选项,可以模拟实际工作负载下的磁盘 I/O 行为,因此在存储系统的基准测试、故障排查、存储设备选型等场景中被广泛应用。\n\n\n存储设备性能测试fio 可以通过模拟不同的 I/O 模式如顺序读写、随机读写等来评估存储设备在各种工作负载下的性能表现。它支持在固态硬盘SSD、机械硬盘HDD、NVMe 等存储介质上进行测试,从而帮助用户了解这些设备在不同 I/O 压力下的吞吐量、延迟和 IOPS每秒输入输出操作数。\n\n\n模拟实际工作负载在生产环境中存储设备通常面对复杂的混合读写请求fio 可以通过配置多线程、多任务以及读写比例来模拟真实的工作负载。例如,数据库服务器的 I/O 通常以随机读为主而备份系统则更多地依赖顺序写。fio 能够灵活配置任务,以精确模拟不同应用场景下的 I/O 行为。\n\n\n测试不同 I/O 模型的性能fio 支持多种 I/O 引擎(如 sync、libaio、io_uring 等),用户可以通过调整不同的 I/O 模型来测试系统的最大 I/O 能力。同步 I/O 更适合简单的 I/O 操作场景,而异步 I/O 则能在多任务或高并发负载下提供更高的性能。\n\n\n支持并发、多任务处理fio 提供了非常强大的并发处理能力,可以通过设置 numjobs 参数来控制并发的任务数量,从而模拟不同的并发场景。此外,通过调整 iodepth 参数,可以控制异步 I/O 请求的深度,进一步增强并发能力。\n\n\n丰富的可配置选项fio 提供了大量灵活的配置参数用户可以通过自定义配置文件或命令行参数来控制测试的具体行为。可以指定块大小bs、I/O 深度iodepth、读写比例rwmixread等详细参数。此外fio 还支持多种输出格式,如 JSON、CSV以便于集成到监控系统中进行结果分析。\n\n\n\nfio was written by Jens Axboe axboe@kernel.dk to enable flexible testing of the Linux I/O subsystem and schedulers. He got tired of writing specific test applications to simulate a given workload, and found that the existing I/O benchmark/test tools out there werent flexible enough to do what he wanted.\nJens Axboe axboe@kernel.dk 20060905\n\nFio 安装方法\nfio 支持多种操作系统,包括主流的 Linux、macOS 和 Windows 平台。在不同的操作系统上安装 fio 具有一些小的差异,用户可以选择合适的安装方式。目前 fio 已经集成在各大 Linux 发行版中,可以自行安装或参考 官方手册。\n支持的平台\n\nLinuxLinux 是 fio 最常用的平台,在各大 Linux 发行版(如 Ubuntu、CentOS、Debian 等fio 都有对应的预编译包。\nmacOSfio 也支持在 macOS 上安装,可以通过 Homebrew 等包管理工具安装。\nWindows在 Windows 环境下fio 支持原生的 Windows 文件系统,并可以通过 Cygwin 或 Windows Subsystem for Linux (WSL) 运行。\n\nFio 基本原理\nfio 是一个高度灵活的工具,它的核心原理是通过模拟不同的 I/O 模式来生成实际负载,从而测试存储设备的性能。了解 fio 的 I/O 模型和工作负载模拟原理,能够帮助用户更好地配置测试场景。\nI/O 模型\n在 fio 中I/O 模型分为两类:同步 I/O 和异步 I/O。\n\n\n同步 I/O 同步 I/O 模型是指每个 I/O 操作在完成之前,发起 I/O 请求的线程会被阻塞,直到 I/O 操作完成后才会继续进行后续操作。这种模型通常用于低并发场景或 I/O 请求较少的工作负载。例如,在单线程的顺序读写测试中,使用同步 I/O 可以更直接地反映存储设备的顺序访问性能。\n\n\n异步 I/O 异步 I/O 模型允许多个 I/O 请求同时进行。发起 I/O 请求后,线程不需要等待当前 I/O 操作完成,而是可以继续发起其他请求,这大大提高了并发能力。异步 I/O 更适合高并发、大量随机访问的场景,比如服务器上并发处理多个数据库查询请求时,异步 I/O 能显著提升处理效率。常用的异步 I/O 引擎包括 libaio 和 io_uring。\n\n\nfio 支持多种 I/O 引擎,它们决定了 I/O 操作的执行方式,不同的 I/O 引擎在性能和应用场景上有很大区别。选择合适的 I/O 引擎可以帮助用户更精准地模拟特定的负载场景。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nI/O 引擎特点sync同步 I/O 引擎,所有 I/O 操作在返回前都会被阻塞适合简单的顺序读写操作。适合对吞吐量敏感的场景。libaioLinux 异步 I/O 引擎,允许多个 I/O 请求并行执行不需等待前一个操作完成。适合高并发、高性能存储设备。mmap通过内存映射实现的 I/O 操作适合对文件的大块连续读写场景。io_uringLinux 新引入的高性能异步 I/O 模型,提供了更低的系统开销和更高的 I/O 性能。特别适用于 NVMe 等高性能存储设备。\nFio 如何模拟工作负载\nfio 通过创建多个线程或进程来模拟多任务并发的 I/O 请求。 每个任务可以独立配置它的 I/O 模型、读写模式、块大小等,从而能够精确地模拟出不同应用程序的 I/O 行为。例如,可以同时配置一个任务进行顺序写操作,另一个任务进行随机读操作,达到模拟数据库写操作和备份操作并行执行的效果。\nFio Job 的基本组成\n一个 fio 的 job任务是测试的核心它通常由以下几个部分组成\n\n任务配置每个任务可以独立配置 I/O 模型、读写模式等。例如,可以配置多个 job 并发运行以模拟真实环境中的多线程负载。\n文件配置文件配置指的是 fio 要对哪个文件或设备进行读写操作。可以是具体的文件路径,也可以是块设备,如 /dev/sda。\n进程/线程控制fio 可以通过 numjobs 参数创建多个并发任务,并通过 thread 参数决定任务是以线程还是进程的形式运行。\n\nFio 基本操作\nFio 基础命令\nfio 支持两种方式运行:命令行模式和配置文件模式。 这两种方式提供了不同的灵活性和适用场景:\n\n\n命令行模式在命令行中直接指定测试参数和选项。这种方式更适合简单、快速的测试场景。命令行模式提供的参数直接跟随 fio 命令。例如:\nfio --name=test --rw=randread --size=1G --bs=4k --ioengine=libaio --numjobs=4 --iodepth=64\n\n\n配置文件模式将所有的测试选项写入一个配置文件然后通过 fio 执行该配置文件。这种模式适合复杂的多任务、多文件的测试场景,尤其在需要复现特定的工作负载时非常有用。例如,用户可以在配置文件中定义多个任务,指定不同的读写模式、块大小和 I/O 引擎等。使用方式如下:\nfio mytest.fio\n配置文件的内容可以非常复杂允许用户指定多个任务和设备。\n\n\n基本语法和参数介绍\n在命令行模式中fio 的基本命令结构如下:\nfio [全局参数] --name=任务名 [任务参数]\n全局参数影响所有任务的运行行为如日志输出格式。\n任务参数每个任务可以独立配置如 I/O 模式、块大小等。常用参数包括 rw、bs、size、numjobs 等。\n简单 I/O 测试实例\n通过简单的 fio 命令,可以执行读写操作并测试设备性能。以下是一些常见的测试场景:\n# 在默认路径生成一个 1GB 的文件,并进行顺序写操作,块大小为 1MB。\nfio --name=seqwrite --rw=write --size=1G --bs=1M --ioengine=sync\n \n# 随机读操作,块大小为 4KB使用异步 I/O 引擎并设置 I/O 深度为 64。\nfio --name=randread --rw=randread --size=1G --bs=4k --ioengine=libaio --iodepth=64\n使用 --output 参数保存输出结果\nfio 支持将测试结果保存到指定的文件中,这对于长时间或复杂的测试尤为重要。可以通过 --output 参数将输出保存到文件:\nfio --name=test --rw=randwrite --size=1G --bs=4k --output=result.txt\nFio 常用参数\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数描述常用选项示例命令rw定义 I/O 操作类型,包括顺序读 (read)、顺序写 (write)、随机读 (randread)、随机写 (randwrite)、混合读写 (randrw)。read, write, randread, randwrite, randrwfio --name=test --rw=randread --size=1G --bs=4kbs块大小指定每次 I/O 操作的块大小,影响 IOPS 和带宽。小块大小适合 IOPS大块适合带宽测试。4k, 8k, 1Mfio --name=test --rw=write --bs=1M --size=1Gsize测试文件的大小定义测试过程中传输的数据总量。1G, 2G, 10Gfio --name=test --rw=write --size=2Gioengine选择不同的 I/O 引擎,如同步 (sync)、异步 (libaio)、io_uring。sync, libaio, io_uringfio --name=test --rw=randread --ioengine=libaio --iodepth=64numjobs设置并发任务数增加并发负载模拟多线程或多进程环境下的 I/O。1, 4, 8, 16fio --name=test --rw=randwrite --numjobs=4iodepth控制异步 I/O 请求的队列深度,适用于 libaio 和 io_uring 等异步 I/O 模型。32, 64, 128fio --name=test --rw=randread --ioengine=libaio --iodepth=64thread控制任务以线程模式执行适合轻量级并发场景。thread, processfio --name=test --rw=randread --numjobs=4 --threadrwmixread在混合读写测试中控制读写比例如 70% 读30% 写。50, 70, 80fio --name=test --rw=randrw --rwmixread=70 --size=1G --bs=4krate限制每秒的传输字节数适用于带宽受限的场景。10m, 100m, 1gfio --name=test --rw=randwrite --size=1G --rate=10mrate_iops限制每秒的 I/O 操作次数IOPS。100, 500, 1000fio --name=test --rw=randwrite --rate_iops=100verify数据一致性校验确保写入数据能正确读回常用模式如 md5、crc32。md5, crc32fio --name=test --rw=randwrite --verify=md5 --size=1G\nFio 文件配置\nfio 文件配置为管理复杂的 I/O 测试场景提供了极大的灵活性。 通过配置文件,用户可以定义多个并发任务,指定不同的 I/O 模式、块大小、I/O 引擎以及存储目标。每个测试任务的参数可以独立配置,适合多任务并发运行或复杂负载的测试需求。\n**fio 配置文件使用 .fio 后缀,文件结构类似于 ini 格式,每个任务用 [jobname] 进行定义,后面跟随具体的参数配置。**配置文件可以包含全局设置以及单独任务的定义,适合测试复杂的场景,如多任务、多设备的并发 I/O 测试。\n配置文件结构示例\n[global]\nioengine=libaio\nsize=1G\nbs=4k\n \n[readtest]\nrw=randread\niodepth=32\n \n[writetest]\nrw=randwrite\niodepth=64\n\n[global]:全局配置部分,适用于所有任务,例如 ioengine=libaio 设置 I/O 引擎为异步模式size=1G 设置测试文件大小为 1GBbs=4k 设置块大小为 4KB。\n[readtest]定义了一个随机读测试任务iodepth=32 表示该任务的 I/O 队列深度为 32。\n[writetest]定义了一个随机写测试任务iodepth=64 表示该任务的 I/O 队列深度为 64。\n\n使用 filename 参数定义测试文件\nfilename 参数用于指定测试使用的文件或块设备。可以是具体的文件路径,也可以是裸设备(如 /dev/sda。这使得 fio 不仅可以在文件系统层面测试,还可以直接测试块设备的 I/O 性能。\nfio --name=test --rw=write --size=1G --filename=/dev/sda\n\n临时文件在文件系统上创建的文件用于测试适合测试文件系统的性能。\n裸设备直接在块设备上运行测试适合测试硬盘或存储设备的底层性能避免文件系统的缓存影响。\n\n多文件和目录的 I/O 测试\nfio 支持在多个文件或目录上并发运行测试任务。可以使用通配符或明确指定多个文件进行测试。\nfio --name=test --rw=randread --filename=/mnt/data/testfile[1-4]\n使用 fio 配置文件,可以管理复杂的测试场景。配置文件结构清晰,能够定义多个并发任务、不同的 I/O 模式以及特定的存储目标。\nfio 配置文件使用 .fio 作为后缀,文件内部的结构类似于 ini 格式。每个任务通过 [jobname] 定义,任务的详细参数在后续逐行配置。例如:\n[global]\nioengine=libaio\nsize=1G\nbs=4k\n \n[readtest]\nrw=randread\niodepth=32\n \n[writetest]\nrw=randwrite\niodepth=64\n该配置文件定义了两个任务 readtest 和 writetest分别进行随机读和随机写操作。\nFio 日志报告\nfio 提供了方便的输出报告功能,可以将测试结果保存到日志文件中,便于后续分析、共享和归档。通过 --output 参数指定输出文件,可以轻松生成测试报告:\nfio --name=test --rw=randread --size=1G --output=result.txt\n标准输出解析\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n术语描述适用场景单位IOPS每秒输入输出操作数用于衡量设备在单位时间内处理的 I/O 请求数量。特别适合小块随机 I/O 的性能评估。高并发场景,如数据库、虚拟化系统中小块 I/O 性能的评估。IOPS每秒请求数带宽Bandwidth表示单位时间内的数据传输量评估大块顺序 I/O 性能。适合大文件传输、顺序读写的场景如流媒体、备份等需要大量连续数据传输的场景。MB/s 或 GB/s延迟Latency每个 I/O 操作从发出到响应完成的时间。延迟越低系统响应越快适合高并发和实时性要求高的应用。高性能存储需求场景如数据库、交易系统、实时应用。微秒µs或毫秒ms完成时间Completion Time表示单个测试任务完成所需的总时间。这可以用于评估整体性能表现。测试持续时间较长的 I/O 操作如备份和归档。秒sCPU 使用率CPU Utilization指测试期间系统的 CPU 占用情况,反映 I/O 操作对 CPU 资源的消耗。用于衡量存储设备和系统的 CPU 整体利用效率,特别是在高并发或高负载场景中有助于确定 CPU 资源是否成为瓶颈。百分比(%队列深度Queue Depth反映测试期间并发处理的 I/O 请求数量,尤其是异步 I/O 操作中。队列深度较大时,系统可以更高效地并行处理 I/O 请求。适合异步 I/O 负载测试场景,如 SSD 和 NVMe 设备的性能优化帮助评估设备的并行处理能力。无单位错误率Error Rate反映测试过程中发生的错误数量和类型如 I/O 失败或数据验证失败。确保测试过程中的数据完整性和可靠性。数据可靠性测试和故障排查场景如验证存储设备的故障检测能力。错误次数磁盘利用率Disk Utilization指存储设备的忙碌程度反映设备在 I/O 操作中的占用率,通常结合 CPU 利用率来评估系统资源的综合使用情况。用于评估系统和存储设备在高负载下的工作状态,判断系统瓶颈点。百分比(%\n日志输出格式\n为了方便数据分析和集成监控系统fio 支持将测试结果输出为标准文本、JSON 或 CSV 格式。用户可以选择最适合的格式来处理和分析测试结果。\nJSON 格式\n结构化数据输出适合与自动化工具和监控系统集成。JSON 输出便于导入诸如 Grafana、Prometheus 等监控工具进行可视化和性能趋势分析。\nfio --name=test --rw=randread --size=1G --output-format=json --output=result.json\nCSV 格式\nCSV 格式适合导入 Excel 或数据分析工具(如 R、Python便于用户手动分析和生成图表。\nfio --name=test --rw=write --size=1G --output-format=csv --output=result.csv\n日志间隔与精确数据记录\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数描述示例命令适用场景--log_avg_msec设置时间间隔记录平均性能数据适用于长时间压力测试帮助用户观察性能趋势和波动。fio --name=test --rw=randread --size=1G --log_avg_msec=1000 --output=result.txt长时间压力测试性能趋势观察--log_hist_msec记录更加精确的 I/O 性能数据,适用于捕捉短时间内的 I/O 波动帮助分析微观层面上的性能变化。fio --name=test --rw=randwrite --size=1G --log_hist_msec=100 --output=result.txt高精度性能监控短时间性能分析--write_iops_log将 IOPS 性能数据记录到日志文件中,用于观察和分析 IOPS 的变化情况支持长期记录和监控。fio --name=test --rw=randread --size=1G --write_iops_log=iops_log.txtIOPS 监控,长期性能观察--write_bw_log将带宽Bandwidth性能数据记录到日志文件中适合大文件传输、顺序读写的带宽监控与分析。fio --name=test --rw=write --size=1G --write_bw_log=bw_log.txt带宽性能监控顺序读写分析--write_lat_log将延迟Latency数据记录到日志文件中帮助分析 I/O 操作的响应时间变化特别适用于高实时性要求的场景如数据库和虚拟机。fio --name=test --rw=randwrite --size=1G --write_lat_log=lat_log.txt延迟监控高实时性应用分析--write_log同时记录 IOPS、带宽和延迟数据生成综合日志文件适合对存储设备的整体性能进行全面监控和记录。fio --name=test --rw=randrw --size=1G --write_log=performance_log.txt综合性能监控全面性能评估--log_max_value设置日志记录的最大值适用于限制日志文件中记录的最大性能数据点防止异常值导致日志分析数据失真。fio --name=test --rw=write --size=1G --log_max_value=10000限制日志数据范围去除异常数据--log_offset为日志文件中的数据设置偏移值用于对记录数据进行时间上的调整适合对多次测试进行对比分析时使用。fio --name=test --rw=randread --size=1G --log_offset=1000 --output=result.txt数据对比分析多次测试分析--log_unix_epoch记录日志时以 Unix 时间戳秒级或毫秒级为基础适用于将数据集成到其他系统中进行时序分析或对接监控工具。fio --name=test --rw=randwrite --size=1G --log_unix_epoch=1 --output=result.txt时间序列分析监控系统集成--write_log_units设置日志文件中记录的数据单位如 IOPS 的单位可以是 iops带宽可以是 mbps延迟可以是 ms。fio --name=test --rw=randread --size=1G --write_log_units=iops,mbps,ms --write_log=unit_log.txt自定义单位日志记录--log_avg_msec设置记录平均性能数据的时间间隔用于长时间性能监控。fio --name=test --rw=randwrite --size=1G --log_avg_msec=2000 --output=result.txt长时间压力测试平均性能分析--log_hist_coarseness设置记录直方图数据的粒度适用于需要捕捉细微性能变化的场景。fio --name=test --rw=randread --size=1G --log_hist_coarseness=10 --output=hist_log.txt性能微观分析细粒度数据监控\nFio 实际应用案例\nfio 是一个高度灵活的存储性能测试工具,广泛应用于不同场景下的 I/O 性能测试。无论是在评估 SSD 和 HDD 性能、分布式存储和网络 I/O 测试还是模拟数据库负载fio 都能够提供精准的 I/O 负载模拟和详细的性能指标。此外fio 在企业级存储基准测试和大规模存储性能测试中也是必不可少的工具。\n在 SSD/HDD 上的测试\nSSD 和 HDD 是两类性能差异较大的存储介质。SSD 具有更高的随机读写性能和更低的延迟,而 HDD 则更适合大规模顺序读写操作。 通过 fio可以精确测试这两种设备在不同工作负载下的表现并对其性能差异进行对比。\nSSD 的读写性能测试\nSSD 通常在随机读写操作中表现突出,尤其是 NVMe SSD 通过支持高并发和低延迟的 I/O 操作,能显著提升系统性能。使用 fio 测试 SSD 的随机读写性能,可以评估其在高负载场景下的表现。\n# 测试 NVMe SSD 的随机读写性能,其中 70% 是随机读30% 是随机写,块大小为 4KBI/O 深度为 64。\nfio --name=ssd-test --rw=randrw --rwmixread=70 --bs=4k --size=10G --iodepth=64 --numjobs=4 --filename=/dev/nvme0n1\n\n机械硬盘的顺序读写和随机读写性能测试\n机械硬盘HDD在顺序读写操作中表现较好但在随机读写下性能表现较差。fio 可以帮助分析 HDD 的顺序和随机 I/O 性能,评估其适用于哪些应用场景。\n# 测试顺序写性能,块大小为 1MB适合测试 HDD 的带宽和吞吐量。\nfio --name=hdd-test --rw=write --bs=1M --size=10G --iodepth=32 --filename=/dev/sda\n \n# 测试 HDD 的随机读性能,适合评估 HDD 在随机访问应用场景中的表现。\nfio --name=hdd-test --rw=randread --bs=4k --size=10G --iodepth=32 --filename=/dev/sda\n分布式存储和网络 I/O 测试\n在现代数据中心分布式存储和网络文件系统被广泛使用如 Ceph、GlusterFS、NFS 等。fio 支持 client/server 模式,可以用于分布式 I/O 测试,评估系统在网络存储环境中的性能表现。\n使用 client/server 模式进行分布式 I/O 测试\nfio 的 client/server 模式允许在不同的主机之间进行 I/O 测试,这使得其非常适合分布式存储环境的性能评估。通过在不同节点之间传输数据,可以测试网络延迟、带宽以及多节点间的 I/O 协作能力。\n# 1.服务器端启动并等待客户端连接。\nfio --server\n \n# 2.客户端启动测试,客户端连接到远程 `fio` 服务器进行随机写测试。\nfio --client=server_ip --name=test --rw=randwrite --size=10G --bs=4k\n网络文件系统NFS、分布式存储Ceph的测试\n对于分布式文件系统如 NFS 或 Ceph可以使用 fio 测试其性能,模拟多个客户端同时访问共享存储的场景。\n# 在挂载的 NFS 目录中执行随机写测试,用于评估 NFS 在并发访问下的性能表现。\nfio --name=nfs-test --rw=randwrite --size=10G --bs=4k --directory=/mnt/nfs\n \n# 在 Ceph 文件系统中执行多任务随机读测试,评估其在高并发情况下的读写能力。\nfio --name=ceph-test --rw=randread --size=10G --bs=4k --numjobs=8 --filename=/mnt/ceph\n模拟数据库负载\n数据库应用的 I/O 负载通常表现为高并发、小块的随机读写操作。通过 fio可以模拟数据库的典型 I/O 模型,测试存储设备在类似数据库工作负载下的性能。\n数据库负载往往以 4KB 的小块随机读写为主fio 可以通过设置 bs=4k 和高并发来精确模拟这种工作负载。\n# 模拟 70% 随机读和 30% 随机写的混合操作,块大小为 4KB16 个并发任务和较高的 I/O 深度,能够逼真地模拟数据库环境中的高负载。\nfio --name=db-test --rw=randrw --rwmixread=70 --bs=4k --size=10G --numjobs=16 --iodepth=64\n为了进一步优化数据库工作负载的性能通常需要对块大小和 I/O 深度进行调整:\n\n块大小数据库通常使用较小的块大小如 4KB以优化随机读写性能。较大的块大小适合顺序操作或批量数据处理但对数据库负载可能不利。\nI/O 深度:增加 I/O 深度iodepth可以提高系统的并发处理能力尤其是对于 NVMe SSD 等高性能存储设备,合适的 iodepth 可以极大提升系统 IOPS。\n\n企业级应用场景\n在企业环境中fio 被广泛用于存储设备的基准测试、压力测试和性能验证。通过 fio 的灵活配置,用户可以评估存储系统在不同负载下的表现,并预测系统在实际生产环境中的稳定性和响应能力。\n使用 Fio 进行存储设备的基准测试和验证\n基准测试是存储设备选型和性能优化的重要手段。fio 能够模拟各种典型的应用场景,帮助企业对比不同存储设备的性能表现。\n# 对设备进行顺序读基准测试,块大小为 1MB适合评估设备的最大带宽。\nfio --name=baseline --rw=read --bs=1M --size=10G --iodepth=32 --filename=/dev/sda\n大规模存储设备的 I/O 性能测试与压力测试\n在大规模存储系统如 SAN、NAS压力测试用于评估系统在长时间高负载条件下的性能稳定性。通过增加并发任务和 I/O 负载fio 能够模拟生产环境中极端的使用场景,帮助企业发现存储系统的性能瓶颈。\n# 在 24 小时内对存储设备进行随机读写压力测试64 个并发任务和较高的 I/O 深度能够逼真模拟企业生产环境下的高负载工作场景。\nfio --name=stress --rw=randrw --bs=4k --size=100G --numjobs=64 --iodepth=128 --runtime=24h --time_based\nFio 性能优化与故障排查\n性能调优技巧\n使用 numjobs 增加并发性\nnumjobs 参数是 fio 中控制并发性的重要工具。它用于定义并行执行的任务数量,适合模拟多线程或多任务环境下的 I/O 负载。例如,在测试数据库或虚拟化环境中,可以通过增加并发任务数量来模拟实际应用中高负载下的存储访问行为。\n\n\n调优场景\n\n如果存储设备支持并发 I/O那么通过增加 numjobs 可以有效提升设备的吞吐量和 IOPS尤其是在 NVMe SSD 等高性能存储设备上。\n\n\n\n示例\nfio --name=test --rw=randread --size=1G --bs=4k --numjobs=8\n在该命令中numjobs=8 表示将启动 8 个并发任务进行随机读操作。较高的并发性适合测试系统在高负载条件下的 I/O 性能。\n\n\n调整 iodepth 优化异步性能\niodepth 参数定义了在异步 I/O 模式下(如 libaio 或 io_uring队列中允许同时存在的最大 I/O 请求数。更高的 iodepth 值可以提升并发能力,但如果系统资源有限,过高的 iodepth 可能会导致队列过长,增加延迟。通过合理调整 iodepth可以找到设备的最佳异步性能点。\n\n\n调优场景\n\n在高性能 SSD 或 NVMe 设备上,较大的 iodepth 可以提高设备的 IOPS 和吞吐量。\n对于 HDD 或 SATA SSD过高的 iodepth 可能会因为硬件瓶颈导致性能下降或延迟增加。\n\n\n\n示例\nfio --name=test --rw=randwrite --size=1G --ioengine=libaio --iodepth=64\n该命令中iodepth=64 表示同时进行 64 个异步 I/O 操作,适合高并发场景。\n\n\n针对 IOPS、带宽、延迟等不同目标进行针对性优化\n根据不同的测试目标fio 可以通过以下参数进行针对性优化:\n\n\n优化 IOPS为小块随机读写的场景调优。通过增加并发任务数numjobs和适度提高 iodepth可以有效提高 IOPS。合适的块大小bs对 IOPS 影响极大,通常 4KB 是优化 IOPS 的标准选择。\nfio --name=io_test --rw=randread --bs=4k --size=10G --numjobs=16 --iodepth=32\n\n\n优化带宽适用于大块顺序读写操作。通过增大块大小bs=1M 或更大),可以提高数据传输速率,最大化设备的带宽性能。\nfio --name=bw_test --rw=write --bs=1M --size=10G\n\n\n优化延迟适用于实时性要求较高的场景。需要控制 iodepth 和 numjobs避免过多的并发和过深的队列保证 I/O 请求尽快被处理。\nfio --name=latency_test --rw=randread --bs=4k --size=1G --iodepth=4\n\n\nFio 常见问题与排错\n在使用 fio 进行测试时,可能会遇到一些错误和性能问题。了解 fio 输出日志中的错误信息,并通过正确的调试工具和方法进行排错,是测试工作顺利进行的保障。\n如何分析和解决 Fio 报错\n\n常见报错\n\n文件系统/块设备权限问题:执行测试时,确保 fio 对测试文件或设备有写入权限。可以通过 chmod 或 chown 修改文件权限。\n参数配置冲突有些参数不能同时使用如指定 rw=randread 时不应再设定 verify 参数。解决方案是根据报错提示,调整相应的参数配置。\n\n\n分析报错日志 当 fio 报错时,日志中会包含详细的错误信息。通过阅读 fio 输出的错误消息,可以准确定位到导致错误的参数或系统配置。例如,如果在测试期间设备无法响应,报错信息可能会显示 “I/O error”。\n解决方法\n\n检查并确保所有的设备路径正确。\n检查设备的挂载状态和可写权限。\n根据错误日志调整 fio 的配置或系统资源分配。\n\n\n\n系统资源CPU、内存、磁盘的使用情况监控\nfio 运行时对系统资源的占用情况(如 CPU 和内存)可能会影响测试结果,因此监控系统资源使用至关重要。可以使用以下工具来监控测试过程中系统的资源使用情况:\n\n\ntop 或 htop实时监控 CPU 和内存使用情况,识别系统瓶颈。\ntop\n\n\niostat监控磁盘 I/O 性能,分析磁盘读写速率、设备利用率等。\niostat -x 1\n\n\nvmstat监控系统的虚拟内存使用情况帮助识别内存瓶颈。\nvmstat 1\n\n\n通过实时监控系统资源使用可以识别由于 CPU 或内存不足导致的 I/O 性能瓶颈,并进行相应的优化调整。\n使用 --debug 参数进行深度调试\nfio 提供了 --debug 参数,用于调试运行过程中的细节。可以通过该参数输出更多调试信息,从而深入了解 fio 的内部运行机制,帮助排查一些难以发现的系统问题。\nfio --name=test --rw=randread --size=1G --debug=all\n此命令会生成详尽的调试信息涵盖从 I/O 操作到系统调用的详细日志。\n性能瓶颈分析与解决方案\nfio 测试过程中,存储设备的性能可能受到多种硬件和软件因素的影响。分析 I/O 性能瓶颈,并结合其他系统工具进行深入排查,可以帮助用户识别并解决影响系统性能的根本问题。\n分析不同硬件和软件配置下的 I/O 性能瓶颈\n存储设备的 I/O 性能瓶颈可以来源于硬件或软件层:\n\n硬件瓶颈\n\n磁盘 I/O 性能不足:传统 HDD 在处理高并发随机 I/O 时会遇到 IOPS 限制。更换为 SSD 或 NVMe 设备通常能显著提高 IOPS 性能。\n网络带宽受限在分布式存储系统中网络带宽可能成为瓶颈。通过增加网络带宽或使用更高性能的网络接口卡如 10GbE、25GbE可以缓解这种瓶颈。\n\n\n软件瓶颈\n\nI/O 队列设置不当:在高并发负载下,如果 I/O 队列深度设置过小,可能会导致设备性能无法充分发挥;如果设置过大,可能会增加延迟,导致系统响应速度变慢。\n文件系统的选择不同文件系统如 ext4、XFS的性能差异可能影响测试结果。针对特定应用场景选择合适的文件系统对提高 I/O 性能至关重要。\n\n\n\n使用 Fio 结合其他系统工具(如 iostat、sar进行性能分析\nfio 可以与其他性能监控工具结合使用,帮助全面分析系统的 I/O 性能瓶颈:\n\n\niostatiostat 提供了磁盘 I/O 的详细信息,包括每个设备的读写速率、平均等待时间、设备利用率等。通过与 fio 结合使用,可以监控不同测试条件下磁盘的性能表现。\niostat -x 1\n\n\nsarsar 是一款强大的系统性能分析工具,可以监控系统的 CPU、内存、I/O 性能等多种资源。通过收集长时间的系统数据,用户可以分析系统在不同时间段的性能变化情况。\nsar -d 1\n\n\n通过这些工具用户可以更好地了解 fio 测试时系统的资源使用情况,从而识别和解决性能瓶颈。"},"Technology/OperatingSystem/Virtualization/1.虚拟化概述/虚拟化平台简介":{"title":"虚拟化平台简介","links":[],"tags":["技术/操作系统","虚拟化/概述"],"content":"主流虚拟化平台\nVMware vSphere\nVMware vSphere 是 VMware 公司推出的企业级虚拟化平台被广泛认为是市场上最成熟、功能最强大的虚拟化解决方案之一。vSphere 集成了虚拟化、管理和自动化功能,帮助企业构建灵活、高效的 IT 基础设施。\n架构图\n\n历史发展\n\n2001 年VMware 发布了其首个虚拟化产品 VMware GSX Server 和 VMware ESX Server。\n2009 年:发布 vSphere 4标志着 VMware 全面进入虚拟化管理市场。\n2020 年:发布 vSphere 7进一步集成 Kubernetes增强了容器和微服务的支持。\n\n主要特点\n\n高性能和可扩展性支持大规模虚拟机部署和高性能计算满足企业不断增长的需求。\n丰富的管理工具提供 vCenter Server 进行集中管理和监控,使 IT 管理更加高效。\n集成安全功能内置多层次的安全机制保护虚拟化环境确保数据安全。\n自动化和编排通过 vRealize Suite 实现自动化管理和编排,提高 IT 运维效率。\n支持多云环境与 AWS、Azure 等云平台无缝集成,支持混合云和多云架构,提升灵活性。\n\n优势\n\n市场领先作为虚拟化领域的先驱VMware 拥有成熟的技术和广泛的用户基础,市场占有率高。\n高可靠性支持 vSphere HA高可用性和 vSphere FT容错确保关键业务的连续性。\n强大的生态系统与众多硬件和软件供应商合作提供广泛的兼容性和集成解决方案满足多样化需求。\n全面的支持和服务提供全球范围的技术支持和培训服务确保企业顺利部署和维护虚拟化环境。\n\n适用场景\n\n大型企业和数据中心适用于需要高性能、高可靠性和高可扩展性的企业级虚拟化部署。\n云计算和混合云环境适用于构建私有云、混合云和多云架构的场景。\n业务连续性和灾难恢复适用于需要高可用性和快速恢复能力的关键业务应用。\n\n部署与管理\n\nvCenter Server提供集中管理和监控通过单一控制台管理整个虚拟化环境。\nvSphere Client基于 Web 的管理界面,支持跨平台访问和操作。\n虚拟网络和存储支持虚拟交换机vSwitch、分布式虚拟交换机DVS以及多种存储选项如 iSCSI、NFS 和 FC。\n\n性能优化与监控\n\nvRealize Operations提供性能监控、容量规划和故障排除功能确保虚拟化环境高效运行。\nDistributed Resource Scheduler (DRS):自动负载均衡,优化资源利用率,提升系统性能。\nStorage DRS自动管理存储资源优化存储性能避免资源瓶颈。\n\n安全与合规\n\nvSphere Trust Authority增强虚拟化环境的安全性确保数据和工作负载的保护。\n虚拟机加密提供虚拟机和 vMotion 流量的加密,确保数据在传输过程中的安全。\n合规管理支持多种合规标准如 GDPR、HIPAA帮助企业满足法律法规要求。\n\nVMware vSphere 是一款功能强大的企业级虚拟化平台,具有高性能、高可靠性、丰富的管理工具和强大的安全功能。它广泛适用于各种企业级应用场景,包括大型企业、数据中心、云计算和混合云环境。通过 vSphere企业可以构建灵活、高效的 IT 基础设施实现业务的连续性和高效管理。无论是性能优化、安全合规还是自动化管理vSphere 都提供了全面的解决方案,帮助企业应对现代 IT 环境中的各种挑战。\nMicrosoft Hyper-V\nMicrosoft Hyper-V 是微软推出的虚拟化平台,广泛集成在 Windows Server 操作系统中提供企业级虚拟化解决方案。Hyper-V 支持虚拟化 Windows 和 Linux 操作系统,是微软生态系统的重要组成部分。\n架构图\n\n历史发展\n\n2008 年:微软发布了 Hyper-V 的第一个版本,作为 Windows Server 2008 的一个功能组件,标志着微软正式进入虚拟化市场。\n2012 年:发布 Windows Server 2012增强了 Hyper-V 的功能和性能,包括虚拟交换机、存储虚拟化等新特性。\n2021 年:发布 Windows Server 2022进一步提升 Hyper-V 的安全性和性能,增加了对新硬件和技术的支持。\n\n主要特点\n\n内置于 Windows Server无需额外购买直接集成在 Windows Server 中,便于企业采用。\n深度集成 Microsoft 生态系统:与 Active Directory、System Center 等微软产品紧密集成,提供统一的管理和操作体验。\n高可用性和灾难恢复支持集群和高可用性配置以及 Hyper-V Replica 功能,实现灾难恢复,确保业务连续性。\n虚拟网络和存储提供虚拟交换机和存储虚拟化功能支持多种存储选项如 SMB、iSCSI 和 FC灵活配置网络和存储资源。\n强大的虚拟机管理支持热迁移、快照和虚拟机克隆等功能简化虚拟机的管理和维护。\n\n优势\n\n成本效益高作为 Windows Server 的一部分,企业无需额外支付虚拟化许可费用,降低 IT 成本。\n易于管理通过熟悉的 Windows 管理工具(如 Hyper-V Manager 和 PowerShell进行管理降低学习成本和管理复杂度。\n强大的社区支持广泛的用户社区和技术支持资源帮助企业快速解决问题确保虚拟化环境的稳定运行。\n跨平台支持不仅支持 Windows还支持多种 Linux 发行版,满足多样化的应用需求。\n\n适用场景\n\n中小型企业适用于需要高性价比虚拟化解决方案的中小型企业特别是那些已有 Windows Server 环境的企业。\n微软技术栈企业 IT 环境主要使用微软技术和产品的场景Hyper-V 能够与现有系统无缝集成,提供一致的用户体验。\n开发和测试环境为开发和测试提供灵活的虚拟化平台支持快速部署和回滚。\n业务连续性和灾难恢复企业需要高可用性和灾难恢复能力的关键业务应用可以通过 Hyper-V Replica 和集群配置实现。\n\n部署与管理\n\nHyper-V Manager提供图形用户界面便于创建和管理虚拟机。\nPowerShell通过命令行工具进行自动化管理和脚本编写提高管理效率。\nSystem Center Virtual Machine Manager (SCVMM):提供集中管理,适用于大规模虚拟化环境的管理和维护。\n\n性能优化与监控\n\n实时监控通过 Hyper-V 管理器和 Performance Monitor 实时监控虚拟机性能。\n动态内存支持动态内存调整优化虚拟机的内存使用。\n资源分配支持 CPU 和存储资源的动态分配,确保关键业务的资源需求。\n\n安全与合规\n\nShielded VM保护虚拟机免受未经授权的访问确保数据安全。\n虚拟机隔离通过虚拟机隔离技术防止恶意软件在虚拟机之间传播。\n合规管理支持多种合规标准帮助企业满足法律法规要求。\n\nMicrosoft Hyper-V 是一款功能强大且成本效益高的企业级虚拟化平台,广泛适用于各种应用场景。其深度集成于 Windows Server与 Microsoft 生态系统紧密结合提供高效的虚拟化解决方案。无论是中小型企业还是大型企业Hyper-V 都能提供灵活、可靠的虚拟化平台,帮助企业构建高效、安全的 IT 基础设施。通过 Hyper-V企业可以实现高可用性、灾难恢复和性能优化确保关键业务的连续性和稳定运行。\nKVM 与 QEMU\nKVM (Kernel-based Virtual Machine) 是一个集成在 Linux 内核中的开源虚拟化解决方案,由开源社区开发和维护,后被 Red Hat 收购提供商业版本 Red Hat Virtualization。QEMUQuick EMUlator则是一款广泛用于仿真和虚拟化的开源平台支持多种硬件架构和操作系统。\nQEMU 可以独立运行,也可以与 KVM 结合使用,以提供接近原生的性能。\n架构图\n\n历史发展\n\n2003 年QEMU 项目由 Fabrice Bellard 启动,最初作为一种用户模式仿真器发布。\n2005 年:引入 KVM 支持,使 QEMU 能够利用硬件虚拟化技术,提高性能。\n2006 年KVM 项目由 Qumranet 公司启动,并于同年被合并到 Linux 内核中。\n2008 年Red Hat 收购 Qumranet并将 KVM 集成到 RHEL 中,进一步推动其发展。\n2010 年Red Hat 发布 RHEV (Red Hat Enterprise Virtualization),基于 KVM 的企业级虚拟化平台,提供更强大的管理功能和性能优化。\n\n主要特点\n\nQEMU 多架构支持QEMU 支持多种硬件架构,包括 x86、ARM、PowerPC、MIPS 和 SPARC适用于各种平台和应用。\nKVM 硬件虚拟化KVM 利用硬件虚拟化技术(如 Intel VT-x 和 AMD-V提供高性能虚拟化直接运行在 Linux 内核中。\n操作系统兼容性QEMU 和 KVM 共同支持多种操作系统,包括 Linux、Windows、BSD 和 macOS。\n虚拟化和仿真结合QEMU 可以作为仿真器独立运行,也可以与 KVM 结合,提供高性能虚拟化解决方案。\n安全性和隔离性KVM 利用 Linux 内核的安全特性(如 SELinux 和 cgroups提供高水平的虚拟机隔离和安全性。\n\n优势\n\n开源和社区驱动QEMU 和 KVM 都由开源社区开发和维护,代码透明且可定制,用户可以根据需求进行修改和优化。\n高度可扩展QEMU 的多架构支持和 KVM 的硬件虚拟化能力使其适用于从小型实验室到大型数据中心的各种虚拟化部署。\n性能优越结合 KVM 使用时QEMU 提供接近裸机的性能,适用于高性能计算和生产环境。\n灵活性和可定制性企业可以根据需求定制和优化虚拟化环境充分利用开源社区的创新和资源。\n强大的支持服务Red Hat 提供全面的技术支持和培训服务,确保企业顺利部署和维护 KVM 和 QEMU减少运维成本。\n成本节约作为开源软件KVM 和 QEMU 无需支付高昂的许可费用,降低了企业的虚拟化成本。\n\n适用场景\n\n开发和测试环境适用于开发人员和测试人员进行跨平台的应用程序开发和测试支持多种操作系统和硬件架构。\n仿真和教学适用于教学和研究领域提供硬件和操作系统的仿真环境。\n生产环境结合 KVM 使用,适用于高性能计算、服务器虚拟化和云计算等生产环境。\n嵌入式开发支持多种嵌入式硬件架构适用于嵌入式系统的开发和测试。\n混合云和多云架构KVM 可以与 OpenStack 等开源云平台无缝集成,支持企业构建混合云和多云环境。\n\n部署与管理\n\nRHEV (Red Hat Enterprise Virtualization):提供基于 KVM 的企业级虚拟化管理平台,具备图形化管理界面和丰富的管理功能。\noVirt开源的虚拟化管理平台基于 KVM 和 RHEV提供强大的管理和自动化功能。\nLibvirt通用的虚拟化管理 API支持 KVM 和其他虚拟化技术,提供统一的管理接口。\n命令行工具QEMU 提供强大的命令行工具,支持详细的配置和管理,适合高级用户和自动化脚本使用。\n图形界面通过第三方图形界面如 virt-manager 和 GNOME Boxes用户可以方便地创建和管理虚拟机。\n\n性能优化与监控\n\n硬件加速支持硬件虚拟化技术提高虚拟化性能。\n资源分配灵活配置虚拟机的 CPU、内存和存储资源优化性能。\n性能监控通过工具如 oVirt 和 RHEV进行实时性能监控和分析确保虚拟化环境的高效运行。\n自动化管理利用 Ansible 和 Puppet 等配置管理工具,实现虚拟化环境的自动化部署和管理,提升运维效率。\n\n安全与合规\n\n虚拟机隔离通过虚拟机隔离技术确保不同虚拟机之间的安全性和独立性。\n虚拟机加密支持虚拟机和存储加密保护数据在传输和存储过程中的安全。\n合规管理支持多种合规标准如 GDPR 和 HIPAA帮助企业满足法律法规要求。\n\n**QEMU 和 KVM 是现代虚拟化技术的核心组件二者结合使用可以提供高效、灵活的虚拟化解决方案。QEMU 提供了全面的仿真和设备虚拟化支持,而 KVM 利用硬件虚拟化特性实现高性能的虚拟机执行。**通过这种组合,用户可以在一个平台上高效地运行多个操作系统和应用程序,满足开发、测试和生产环境的多样化需求。\n**Red Hat 的支持进一步确保了企业在部署和维护虚拟化环境时的顺利进行和高效管理。**无论是小型实验室环境、大型数据中心还是混合云和多云架构QEMU 与 KVM 的结合都能提供满足企业需求的高效虚拟化平台。\nCitrix XenServer\n**Citrix XenServer 是基于 Xen hypervisor 的开源虚拟化平台,提供企业级的虚拟化解决方案。**XenServer 以其高性能和高可用性著称,并且能够与 Citrix 的桌面虚拟化和应用虚拟化解决方案无缝集成。\n架构图\n\n历史发展\n\n2003 年Xen 项目由剑桥大学发起,并迅速成为开源社区的热门项目。\n2007 年Citrix 收购 XenSource并将其虚拟化产品命名为 Citrix XenServer进一步推动其商业化和普及。\n2013 年Citrix 将 XenServer 开源,提供社区版和商业版,促进了其在开源社区中的发展和应用。\n\n主要特点\n\n高性能和高可用性支持高性能计算和大规模虚拟机部署提供高可用性功能如 XenMotion 和自动化恢复),确保业务连续性。\n集成 Citrix 生态系统:与 Citrix 的桌面虚拟化和应用虚拟化解决方案(如 Citrix Virtual Apps and Desktops无缝集成提供一体化的虚拟化解决方案。\n易于管理提供简便的管理工具如 XenCenter和自动化功能降低管理复杂性提高运维效率。\n灵活的存储选项支持多种存储类型如 NFS、iSCSI、Fibre Channel提供灵活的存储解决方案。\n广泛的操作系统支持支持多种操作系统包括 Windows、Linux 和其他 UNIX 系统,满足多样化的应用需求。\n\n优势\n\n开源和成本效益作为开源项目企业可以免费使用 XenServer 的基本功能,同时享受开源社区的支持和贡献,降低 IT 成本。\n广泛的硬件支持兼容多种硬件平台提供广泛的驱动支持确保在各种硬件环境下的稳定运行。\n安全性内置多层次的安全功能包括虚拟机隔离、网络隔离和安全补丁管理确保虚拟化环境的安全性。\n扩展性和可定制性支持 API 和脚本编写,企业可以根据自身需求进行扩展和定制。\n\n适用场景\n\n桌面虚拟化适用于需要大规模部署桌面虚拟化解决方案的企业通过与 Citrix Virtual Apps and Desktops 的集成,提供高效的桌面虚拟化服务。\n开源技术偏好适用于偏好开源解决方案的企业和组织充分利用开源社区的资源和支持。\n混合云和多云环境支持在多种云环境下的部署适合构建混合云和多云架构的企业。\n高性能计算和数据中心适用于需要高性能计算和大规模虚拟机部署的数据中心和企业提供高效的计算资源管理和调度。\n\n部署与管理\n\nXenCenter提供图形用户界面便于创建和管理虚拟机支持实时监控和性能分析。\nCLI 和 API通过命令行界面和 API 进行自动化管理和脚本编写,提高管理效率。\n存储管理支持多种存储类型和灵活的存储配置提供集中管理和优化。\n\n性能优化与监控\n\n实时性能监控通过 XenCenter 和其他监控工具进行实时性能监控,确保虚拟机和物理主机的高效运行。\n资源调度和负载均衡支持智能资源调度和负载均衡优化计算资源利用率提高系统性能。\n性能调优提供多种性能调优选项帮助企业根据实际需求优化虚拟化环境的性能。\n\n安全与合规\n\n虚拟机隔离通过虚拟机隔离技术防止恶意软件在虚拟机之间传播确保数据安全。\n网络隔离支持虚拟网络和 VLAN提供安全的网络隔离和流量控制。\n安全补丁管理提供及时的安全补丁和更新确保虚拟化环境的安全性和合规性。\n\nCitrix XenServer 是一款高性能、高可用性和易于管理的开源虚拟化平台,广泛适用于各种企业级应用场景。其与 Citrix 生态系统的深度集成,为企业提供了一体化的虚拟化解决方案。通过 XenServer企业可以实现高效的资源利用、灵活的存储配置和强大的安全保障。无论是桌面虚拟化、大规模数据中心部署还是构建混合云和多云架构Citrix XenServer 都能提供稳定、高效的虚拟化服务,满足企业的多样化需求。\n其他虚拟化平台\nOpenStack\n**OpenStack 是一个开源的云计算平台,支持构建公有云和私有云环境。**它由多个互相依赖的组件组成提供计算、存储和网络的虚拟化服务。OpenStack 提供了高度可扩展和灵活的云基础设施,适用于各种规模的企业和组织。\n架构图\n\n历史发展\n\n2010 年OpenStack 项目由 NASA 和 Rackspace 合作发起,旨在提供开源的云计算解决方案,为用户提供自由和灵活的云环境选择。\n2012 年OpenStack 基金会成立,负责项目的管理和推广,确保 OpenStack 的健康发展和持续创新。\n至今OpenStack 已发展成为一个广泛应用的云计算平台,拥有庞大的社区和众多的企业用户,广泛应用于各个行业的云计算部署。\n\n主要特点\n\n模块化设计OpenStack 由多个可独立部署的组件组成,如 Nova计算、Cinder存储、Neutron网络、Keystone身份认证、Glance镜像服务和 Swift对象存储每个组件各司其职互相配合。\n高度可扩展支持从小规模部署到大规模数据中心的云计算环境适应企业不断增长的需求。\n广泛的硬件和软件兼容性支持多种硬件平台和虚拟化技术包括 KVM、Xen、VMware 和 Hyper-V提供灵活的部署选择。\n丰富的生态系统拥有广泛的第三方支持包括硬件供应商、软件开发商和服务提供商提供全面的解决方案和技术支持。\n\n优势\n\n开源和社区支持强大的开源社区持续不断的改进和创新快速响应用户需求和市场变化。\n灵活性和可定制性企业可以根据需要定制和扩展 OpenStack 环境,满足不同的业务需求。\n经济高效避免厂商锁定降低总体拥有成本提供具有竞争力的云计算解决方案。\n多租户隔离支持多租户环境提供强大的安全隔离和资源管理功能。\n\n适用场景\n\n大规模云计算环境适用于需要高度可扩展和灵活性的云计算部署如互联网公司和大型企业的数据中心。\n企业私有云和公有云企业构建私有云或公有云解决方案的理想选择满足内部部署和公共服务的需求。\n混合云架构支持混合云环境与其他云平台如 AWS、Azure 和 Google Cloud无缝集成提供灵活的跨云部署和管理。\n\n部署与管理\n\nDashboardHorizon提供用户友好的图形管理界面便于管理员和用户管理和监控云资源。\n命令行工具CLI提供丰富的命令行工具支持自动化脚本和批量操作提高管理效率。\nHeatOpenStack 的编排服务,通过模板定义和管理云资源,实现自动化部署和管理。\n\n性能优化与监控\n\nCeilometerOpenStack 的计量和监控服务,提供详细的资源使用数据和性能监控,帮助管理员优化资源分配。\nAodh报警服务支持设置和管理报警规则及时发现和处理系统问题。\nMonasca开源的监控即服务Monitoring-as-a-Service支持大规模的实时监控和报警。\n\n安全与合规\n\nKeystone身份认证服务提供强大的身份管理和访问控制功能确保云环境的安全性。\nBarbican密钥管理服务提供安全的密钥存储和管理保护敏感数据和应用。\n合规支持支持多种合规标准如 GDPR 和 HIPAA帮助企业满足法律法规要求确保数据安全和隐私保护。\n\n**OpenStack 是一款功能强大且灵活的开源云计算平台,广泛适用于各种规模的企业和组织。**其模块化设计和高度可扩展性,使其能够满足多样化的云计算需求。通过 OpenStack企业可以构建经济高效、高度可定制的云计算环境实现计算、存储和网络资源的虚拟化管理。无论是公有云、私有云还是混合云架构OpenStack 都提供了全面的解决方案,帮助企业实现数字化转型和业务创新。\nProxmox VE\nProxmox VE (Virtual Environment) 是一个开源的虚拟化管理平台,支持 KVMKernel-based Virtual Machine和 LXCLinux Containers容器。它提供了集成的虚拟化和容器化管理功能是中小企业和实验室环境的理想选择。\n架构图\n\n历史发展\n\n2008 年Proxmox VE 发布第一个版本,提供开源的 KVM 管理平台,为企业和开发者提供了一个免费的虚拟化解决方案。\n2012 年:引入 LXC 容器支持,增强了平台的功能,使用户能够同时管理虚拟机和容器。\n至今Proxmox VE 持续发展,凭借其开源性质和强大的功能,成为开源虚拟化管理平台的佼佼者,广泛应用于各种场景。\n\n主要特点\n\n集成虚拟化和容器化管理同时支持 KVM 虚拟机和 LXC 容器的管理,提供灵活的虚拟化和容器化解决方案。\n易于部署和管理提供简便的 Web 界面和命令行工具,便于配置和管理虚拟化环境。\n高可用性和备份功能内置集群和备份功能确保虚拟化环境的高可用性和数据安全。\n存储集成支持多种存储类型包括本地存储、NFS、iSCSI、Ceph 和 ZFS提供灵活的存储解决方案。\n网络虚拟化支持 VLAN、Linux Bridge 和 Open vSwitch提供强大的网络虚拟化能力。\n\n优势\n\n开源和成本效益免费开源企业无需支付高昂的许可费用降低虚拟化部署成本。\n灵活性和易用性易于安装和管理适合各种规模的企业使用从小型实验室到大型生产环境均可适用。\n强大的社区支持活跃的社区提供技术支持和资源用户可以获得及时的帮助和更新。\n集成备份和恢复内置的备份和恢复功能使数据保护和灾难恢复变得简单和高效。\n\n适用场景\n\n中小型企业和实验室环境适用于需要成本效益和易用性的虚拟化解决方案满足中小企业和实验室的需求。\n多虚拟化技术集成适用于同时需要管理 KVM 虚拟机和 LXC 容器的场景,提供灵活的混合虚拟化环境。\n开发和测试环境为开发和测试提供灵活的虚拟化和容器化平台支持快速部署和迭代。\n\n部署与管理\n\nWeb 界面Proxmox VE Web GUI提供直观的图形用户界面简化虚拟机和容器的管理。\n命令行工具CLI提供丰富的命令行工具支持自动化脚本和批量操作提高管理效率。\nProxmox VE API支持 REST API方便与第三方工具和系统集成实现自动化管理。\n\n性能优化与监控\n\n实时性能监控通过 Web 界面和 CLI 提供实时性能监控,帮助管理员优化资源分配。\n资源调度和负载均衡支持集群中的资源调度和负载均衡优化系统性能和资源利用率。\nZFS 存储:提供先进的存储功能,包括快照、压缩和重复数据删除,提升存储性能和效率。\n\n安全与合规\n\n虚拟机和容器隔离通过虚拟机和容器隔离技术确保不同工作负载之间的安全性。\n集成防火墙提供内置防火墙保护虚拟化环境免受网络攻击。\n数据加密和备份支持数据加密和备份确保数据在传输和存储过程中的安全性。\n合规支持支持多种合规标准帮助企业满足法律法规要求确保数据和操作的合规性。\n\n**Proxmox VE 是一款功能强大且灵活的开源虚拟化管理平台,广泛适用于中小型企业和实验室环境。**其集成的虚拟化和容器化管理功能,使其能够满足各种复杂的应用需求。通过 Proxmox VE企业可以实现高效的资源管理、数据保护和系统高可用性。无论是开发测试环境还是生产环境Proxmox VE 都提供了全面的解决方案,帮助企业实现高效、可靠的虚拟化部署和管理。\nParallels Desktop\n**Parallels Desktop 是一款专为 macOS 设计的虚拟化软件,允许用户在 Mac 电脑上运行 Windows、Linux 和其他操作系统。**它广泛应用于个人用户和企业,提供无缝的跨平台体验和强大的性能。\n历史发展\n\n2006 年Parallels Desktop 第一个版本发布,成为第一款允许在 Intel Mac 上运行 Windows 的虚拟化软件。\n2009 年:发布 Parallels Desktop 5显著提升性能和用户体验。\n至今Parallels Desktop 持续更新,不断增强性能和兼容性,成为 macOS 用户最受欢迎的虚拟化解决方案之一。\n\n主要特点\n\n无缝集成支持与 macOS 无缝集成,用户可以在 macOS 和 Windows 应用之间自由切换。\n高性能优化性能提供接近原生的应用体验支持 DirectX 和 OpenGL提高图形和游戏性能。\n跨平台兼容支持多种操作系统包括 Windows、Linux、Android 和 macOS。\n简便易用提供用户友好的图形界面简化虚拟机的创建和管理过程。\n共享文件夹和剪贴板支持跨操作系统的文件和剪贴板共享提高工作效率。\n\n优势\n\n专为 Mac 设计:深度优化 macOS 平台,提供最佳的用户体验和性能。\n高效的跨平台工作流允许用户在 Mac 上运行 Windows 应用,提供跨平台的工作流和兼容性。\n易于设置和管理用户可以轻松安装和管理虚拟机快速上手并高效工作。\n持续更新和支持Parallels 不断更新软件,提供新功能和性能改进,同时提供技术支持。\n\n适用场景\n\n跨平台应用使用适用于需要在 Mac 上运行 Windows 或其他操作系统的用户,提供无缝的跨平台体验。\n开发和测试环境开发人员和测试人员可以在 Mac 上创建和管理多种操作系统的虚拟机,进行跨平台的应用开发和测试。\n企业环境企业可以为员工提供在 Mac 上运行 Windows 应用的能力,提升工作效率和灵活性。\n\n部署与管理\n\n简单安装用户可以通过 Parallels Desktop 简便地安装和设置虚拟机,支持从 ISO 映像、USB 设备和网络安装。\n集中管理企业版提供集中管理功能允许管理员管理多个虚拟机和用户简化企业级部署和管理。\n自动更新支持自动更新功能确保用户始终使用最新版本和功能。\n\n性能优化与监控\n\n资源分配用户可以灵活配置虚拟机的 CPU、内存和存储资源优化性能。\n性能监控通过图形界面和命令行工具实时监控虚拟机性能帮助用户优化资源利用。\n图形加速支持 DirectX 和 OpenGL 图形加速,提高图形应用和游戏的性能。\n\n安全与合规\n\n虚拟机隔离通过虚拟机隔离技术确保不同虚拟机之间的安全性和独立性。\n数据加密支持虚拟机磁盘加密保护数据安全。\n安全设置提供多种安全设置确保虚拟化环境的安全性。\n\nParallels Desktop 是一款**专为 macOS 设计的高性能虚拟化软件,广泛适用于个人用户和企业。**其无缝的跨平台兼容性和高效的性能,使其成为 Mac 用户运行 Windows 和其他操作系统的首选解决方案。通过 Parallels Desktop用户可以在 macOS 环境中创建和管理多种虚拟机进行跨平台的应用开发和测试提升工作效率和灵活性。无论是个人用户还是企业Parallels Desktop 都提供了强大、易用的虚拟化功能,满足各种复杂的虚拟化需求。\nOracle VM VirtualBox\nOracle VM VirtualBox 是一个开源的桌面虚拟化软件支持多种操作系统。它广泛应用于开发和测试环境提供跨平台的兼容性。VirtualBox 是开发人员和测试人员常用的工具,因其易用性和灵活性而深受欢迎。\n历史发展\n\n2007 年InnoTek 公司发布 VirtualBox作为一个免费开源的虚拟化软件迅速受到欢迎。\n2008 年Sun Microsystems 收购 InnoTekVirtualBox 成为 Sun 的虚拟化产品。\n2010 年Oracle 收购 Sun Microsystems将 VirtualBox 更名为 Oracle VM VirtualBox并继续其开发和维护。\n至今VirtualBox 持续发展,凭借其丰富的功能和稳定性,成为最受欢迎的桌面虚拟化软件之一。\n\n主要特点\n\n易于使用提供简便的图形用户界面和命令行工具便于安装和配置虚拟机适合初学者和高级用户。\n跨平台支持支持 Windows、Linux、macOS 和 Solaris 操作系统,用户可以在不同的平台上运行 VirtualBox。\n广泛的操作系统支持兼容多种客操作系统包括 Windows、Linux、BSD 和其他 Unix 系统,满足多样化的测试和开发需求。\n快照功能支持虚拟机快照用户可以保存虚拟机的状态并随时恢复便于测试和故障排除。\n可扩展性支持多种扩展包和插件增强虚拟化功能如 USB 设备支持、远程桌面协议RDP和共享文件夹等。\n\n优势\n\n免费开源无需许可费用降低开发和测试环境的成本开源社区提供持续支持和更新。\n灵活性和兼容性支持多种主机和客操作系统提供良好的兼容性适用于各种开发和测试场景。\n便于开发和测试适用于开发人员和测试人员进行跨平台的应用程序开发和测试支持快速部署和迭代。\n轻量级和高效VirtualBox 轻量级且高效,能够在桌面环境中运行多个虚拟机而不影响主机性能。\n\n适用场景\n\n开发和测试环境适用于需要跨平台兼容性和灵活性的开发和测试环境帮助开发人员在不同操作系统上测试应用程序。\n跨平台兼容性测试需要在多个操作系统上测试应用程序的场景确保应用程序在不同平台上的一致性和稳定性。\n教育和培训适用于教育和培训环境为学生和培训人员提供虚拟化实验平台便于学习和实践。\n个人用户和技术爱好者个人用户和技术爱好者可以使用 VirtualBox 创建和管理虚拟机,探索不同的操作系统和软件。\n\n部署与管理\n\n图形用户界面GUI提供直观的图形用户界面用户可以轻松创建、配置和管理虚拟机。\n命令行工具VBoxManage支持丰富的命令行工具用户可以通过脚本进行自动化管理和批量操作。\n扩展包和插件支持多种扩展包和插件增强虚拟化功能如 VirtualBox Extension Pack 提供的 USB 2.0/3.0 支持、远程桌面协议RDP和 PXE 引导等。\n\n性能优化与监控\n\n资源分配用户可以灵活配置虚拟机的 CPU、内存和存储资源优化虚拟机性能。\n性能监控通过图形用户界面和命令行工具实时监控虚拟机性能帮助用户优化资源利用。\n集成工具Guest Additions提供集成工具Guest Additions增强虚拟机性能和用户体验如共享剪贴板、拖放文件和自动分辨率调整等。\n\n安全与合规\n\n虚拟机隔离通过虚拟机隔离技术确保不同虚拟机之间的安全性和独立性。\n加密和安全设置支持虚拟机磁盘加密和多种安全设置保护虚拟机数据和应用程序的安全。\n合规支持帮助企业满足多种合规标准确保虚拟化环境的合规性和数据保护。\n\nOracle VM VirtualBox 是**一款功能强大且灵活的开源桌面虚拟化软件,广泛适用于开发和测试环境。**其易用性、跨平台支持和广泛的操作系统兼容性使其成为开发人员和测试人员的首选工具。无论是个人用户、教育机构还是企业VirtualBox 都能提供高效、经济的虚拟化解决方案,帮助用户实现多样化的虚拟化需求。通过 VirtualBox用户可以创建和管理虚拟机进行跨平台的应用程序开发和测试探索不同的操作系统和软件提升工作效率和学习体验。\n虚拟化平台对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度VMware vSphereMicrosoft Hyper-VKVM 与 QEMUCitrix XenServerOpenStackProxmox VE技术全虚拟化裸机型 Hypervisor支持 vMotion、DRS、HA 等。全虚拟化,裸机型 Hypervisor支持 Hyper-V Replica。全虚拟化内核模块支持高性能计算和虚拟网络。全虚拟化裸机型 Hypervisor支持高性能计算和大规模部署。全虚拟化模块化组件设计支持计算、存储和网络虚拟化。全虚拟化支持 KVM 虚拟机和 LXC 容器,集群和备份功能。分类硬件虚拟化,操作系统虚拟化。硬件虚拟化,操作系统虚拟化。硬件虚拟化,操作系统虚拟化。硬件虚拟化,操作系统虚拟化。硬件虚拟化,操作系统虚拟化,网络虚拟化,存储虚拟化。硬件虚拟化,操作系统虚拟化,容器虚拟化。特点高性能和高可靠性,先进的管理功能,广泛兼容性,强大安全性。内置于 Windows Server深度集成 Microsoft 生态系统,高可用性和灾难恢复。开源和社区驱动,高度可扩展,性能优越。高性能和高可用性,集成 Citrix 生态系统,易于管理。模块化设计,高度可扩展,广泛的硬件和软件兼容性。集成虚拟化和容器化管理,易于部署和管理,高可用性和备份功能。优势成熟稳定,丰富的生态系统,强大技术支持。成本效益高,易于管理,强大的社区支持。灵活性和可定制性,强大支持服务,成本节约。开源和成本效益,广泛硬件支持,安全性强。开源和社区支持,灵活性和可定制性,经济高效。开源和成本效益,灵活性和易用性,强大的社区支持。缺点价格较高,学习曲线较陡。性能可能不如专门的虚拟化平台,功能可能不如 vSphere 强大。需要较高的 Linux 知识,商业支持需付费。社区支持较弱,功能可能不如 vSphere 和 Hyper-V。部署和管理复杂需高技术水平。不如商业平台功能强大企业级支持较少。适用场景大型企业数据中心私有云和混合云。中小型企业微软技术栈。开源技术偏好企业多样化 IT 环境。桌面虚拟化开源技术偏好企业。大规模云计算环境企业私有云和公有云。中小型企业和实验室环境多虚拟化技术集成。虚拟化软件VMware vSphere、ESXi、vCenter Server。Windows Server、Hyper-V Manager、System Center。Red Hat Enterprise Linux、RHEV、oVirt。Citrix XenServer、XenCenter。OpenStack Compute (Nova)、Cinder、Neutron。Proxmox VE、PVE 管理界面。Hypervisor 类型Type 1 裸机型。Type 1 裸机型。Type 1+2 型KVM 集成在 Linux 内核中。Type 1 裸机型。Type 1 裸机型模块化架构。Type 1 裸机型。容器支持通过 vSphere Integrated Containers 支持。通过 Windows Server 容器支持。通过 Docker 和 Podman 支持。支持 LXC 容器。通过 Magnum 支持容器编排。通过 LXC 支持容器。存储虚拟化vSAN、VAAI。Storage Spaces Direct。GlusterFS、Ceph。XenMotion、XenServer StorageLink。Cinder、Swift、Ceph。ZFS、Ceph。网络虚拟化NSX、vSwitch。Hyper-V Virtual Switch、SDN。Open vSwitch、Linux Bridge。Open vSwitch、SR-IOV。Neutron、Open vSwitch。Open vSwitch、Linux Bridge。安全功能NSX、vShield。Shielded VM、Security Center。SELinux、AppArmor。Xen Security Modules (XSM)。Keystone、Barbican。AppArmor、Firewall。性能优化DRS、vMotion。动态内存调整、资源调控。调度器优化、NUMA 支持。高性能计算支持、NUMA 支持。调度器优化、高性能计算支持。性能调优工具、高可用性支持。高可用性和灾难恢复HA、FT、vMotion。Hyper-V Replica、Live Migration。高可用性集群、Live Migration。HA、XenMotion。高可用性集群、热迁移。高可用性集群、备份恢复工具。管理工具vCenter Server、vSphere Client。Hyper-V Manager、System Center Virtual Machine Manager。oVirt、RHEV-M。XenCenter、Xen Orchestra。Horizon、Dashboard。PVE 管理界面、命令行工具。\n选择合适的虚拟化平台取决于企业的具体需求、预算和现有 IT 环境。**VMware vSphere 和 Microsoft Hyper-V 适用于大多数企业级部署Red Hat KVM 和 Citrix XenServer 则更适合偏好开源解决方案的企业。而 OpenStack、Proxmox VE 则提供了灵活的选择,满足不同规模和类型的虚拟化需求。**了解每个平台的特点和优势,能够帮助企业做出更明智的决策,实现 IT 基础设施的现代化和优化。"},"Technology/OperatingSystem/Virtualization/1.虚拟化概述/虚拟化概述":{"title":"虚拟化概述","links":[],"tags":["技术/操作系统","虚拟化/概述"],"content":"虚拟化概述\n虚拟化的概念\n虚拟化是指利用软件技术将计算机的物理资源如 CPU、内存、存储、网络等进行抽象和转换并将其呈现为多个逻辑虚拟资源。 虚拟化技术通过创建多个虚拟资源,打破了物理硬件的限制,使得资源可以更加灵活、高效地使用。\n虚拟化的本质在于将物理资源与软件应用解耦实现资源的弹性化和高效利用。这不仅提高了资源利用率还简化了 IT 管理,并为企业带来了更高的灵活性和可扩展性。\n虚拟化的起源\n虚拟化技术并不是一个新概念其历史可以追溯到 20 世纪 60 年代。当时IBM 首次提出了虚拟机的概念,用于大型机资源共享。 通过虚拟化技术,多个用户可以共享一台大型计算机的资源,而互不干扰。\n到了 20 世纪 70 年代IBM 发布了 VM/370 虚拟机操作系统,这一操作系统大大推动了虚拟化技术的发展。进入 20 世纪 90 年代随着个人电脑的普及虚拟化技术逐渐应用于个人电脑领域VMware 和 VirtualBox 等虚拟化软件相继出现。\n进入 21 世纪,虚拟化技术在云计算、大数据等领域得到了广泛应用,近年来随着容器化技术(如 Docker 和 Kubernetes的兴起虚拟化技术再次得到了快速发展。\n虚拟化的优势\n虚拟化技术带来了诸多显著的优势使其在现代 IT 基础设施中占据重要地位。以下是虚拟化技术的主要优势:\n\n\n提高资源利用率虚拟化可以打破物理硬件的限制使资源利用更加高效。在一台物理机上运行多个虚拟机不仅提高了资源利用率还减少了资源浪费从而降低了 IT 成本。\n\n\n降低成本虚拟化减少了对物理硬件的投资需求并简化了 IT 管理。通过虚拟化技术,企业可以降低服务器采购和维护成本,提高资源利用率,减少资源浪费,从而降低运营成本。\n\n\n提高灵活性虚拟化技术使 IT 基础设施的部署和管理更加灵活。可以快速创建和部署新的虚拟机,满足不断变化的业务需求。虚拟机可以轻松迁移,提高了业务的敏捷性。\n\n\n增强安全性虚拟化技术增强了 IT 基础设施的安全性。通过隔离不同的虚拟机,可以有效防止病毒和恶意软件的传播。此外,虚拟化还可以实现更安全的备份和恢复。\n\n\n虚拟化技术\n虚拟化技术主要依赖于以下几个基本技术\n1. 虚拟机\n虚拟机Virtual MachineVM是一种模拟物理机的软件环境可以运行操作系统和应用软件。每个虚拟机都有自己的虚拟硬件和独立的操作系统使得多个虚拟机可以在同一台物理机上独立运行。\n\n虚拟硬件包括虚拟 CPU、虚拟内存、虚拟存储和虚拟网络接口等。\n虚拟机的优点提高资源利用率、隔离性好、支持多种操作系统。\n虚拟机的缺点开销较大性能可能略低于直接运行在物理机上的操作系统。\n\n2. Hypervisor虚拟机监控器\nHypervisor 是虚拟机的管理程序负责资源分配、调度和隔离。Hypervisor 在物理硬件和虚拟机之间进行协调,确保资源的高效利用和虚拟机的安全隔离。\n\n\nType 1 Hypervisor裸机型直接运行在物理硬件上无需宿主操作系统。例如 VMware ESXi、Microsoft Hyper-V 和 Citrix XenServer。\nType 2 Hypervisor托管型运行在宿主操作系统之上。例如 VMware Workstation、Oracle VirtualBox。\n\n3. 虚拟化软件\n虚拟化软件是实现虚拟化功能的核心工具提供了创建和管理虚拟机的接口和工具。常见的虚拟化软件包括\n\nVMware vSphere企业级虚拟化解决方案提供高级功能如 vMotion、DRS 和 HA。\nMicrosoft Hyper-V集成在 Windows Server 中的虚拟化平台,广泛用于 Windows 环境。\nRed Hat KVM基于 Linux 内核的开源虚拟化技术,适用于各种 Linux 发行版。\nOracle VirtualBox跨平台的开源虚拟化软件适用于个人用户和开发测试环境。\n\n4. 容器\n容器是一种轻量级的虚拟化方式通过提供隔离的用户空间环境实现应用的快速部署和运行。容器技术共享宿主操作系统内核但每个容器有自己的文件系统、进程空间和网络接口。\n\n\nDocker最流行的容器技术提供简单易用的工具来创建、管理和分发容器化应用。\nKubernetes容器编排平台用于自动化部署、扩展和管理容器化应用。\nLXCLinux Containers基于 Linux 的轻量级容器技术。\n\n5. 软件定义网络SDN\nSDN 通过软件控制网络硬件实现网络资源的虚拟化和集中管理。SDN 使网络管理员能够灵活配置和管理网络资源,提升网络效率和灵活性。\n\nOpenFlow一种开放标准协议允许 SDN 控制器与网络设备进行通信,实现网络资源的虚拟化。\nSDN 控制器:管理和控制网络设备的软件平台,常见的控制器包括 OpenDaylight、ONOS 和 Cisco APIC。\n虚拟网络设备如虚拟交换机vSwitch、虚拟路由器vRouter用于实现网络资源的虚拟化和管理。\n\n6. 存储虚拟化\n存储虚拟化通过将物理存储资源抽象为逻辑存储资源实现存储资源的集中管理和优化利用。\n\nSANStorage Area Network虚拟化将多个存储设备连接成一个高性能存储网络提供统一管理和高可用性。\nNASNetwork Attached Storage虚拟化通过网络提供文件级存储服务实现灵活的文件共享和存储管理。\n分布式存储将数据分布存储在多个物理设备上实现高可用性和扩展性代表技术包括 Ceph、GlusterFS 和 Hadoop HDFS。\n\n虚拟化分类\n虚拟化技术根据其应用层次和实现方式可以分为多个类别。以下是对虚拟化分类的全面介绍\n1. 物理硬件\n硬件虚拟化通过将物理硬件资源如 CPU、内存、存储虚拟化为多个逻辑硬件资源使得多个虚拟机可以共享同一套物理硬件资源。硬件虚拟化提供了高效的资源利用率和良好的隔离性。\n\n全虚拟化虚拟机直接使用物理硬件资源无需对操作系统进行任何修改。代表技术包括 VMware ESXi 和 Microsoft Hyper-V。\n半虚拟化虚拟机需要部分修改硬件驱动程序以提高性能和兼容性。典型实现有 Xen。\n准虚拟化虚拟机需要修改操作系统内核以实现更高的性能和兼容性常用于特定高性能需求场景。\n\n2. 操作系统\n操作系统虚拟化在一个物理机上运行多个虚拟操作系统每个虚拟操作系统都有自己独立的运行环境能够有效隔离不同的操作系统和应用程序。\n\n基于 Hypervisor 的虚拟化Hypervisor 直接管理物理硬件资源,为每个虚拟操作系统分配资源。分为 Type 1裸机型 和 Type 2托管型。常见技术包括 KVM 和 Xen。\n容器化虚拟化容器共享物理硬件资源但拥有独立的操作系统环境和应用程序。容器通过共享宿主机内核实现轻量级虚拟化代表技术包括 Docker 和 LXC。\n\n3. 应用程序\n应用虚拟化将应用程序与操作系统解耦使其可以在不同的操作系统环境中运行。应用虚拟化使得应用程序可以跨平台运行简化了部署和管理。\n\n字节码虚拟化应用程序代码被编译成字节码可以在支持相应虚拟机的平台上运行。典型例子是 Java 虚拟机JVM。\n沙盒虚拟化应用程序运行在一个独立的沙盒环境中与其他应用程序隔离保证了更高的安全性和稳定性。示例包括 Google Chrome 的沙盒技术。\n\n4. 网络\n网络虚拟化通过将物理网络资源虚拟化为逻辑网络资源实现灵活的网络配置和管理。网络虚拟化提高了网络资源的利用效率和管理灵活性。\n\n软件定义网络SDN通过软件控制网络硬件实现网络资源的虚拟化和集中管理。代表技术包括 VMware NSX 和 Cisco ACI。\n虚拟局域网VLAN通过逻辑分区实现网络隔离和资源优化配置。\n\n5. 存储\n存储虚拟化通过将物理存储资源虚拟化为逻辑存储资源实现存储资源的集中管理和优化利用。存储虚拟化提供了更高的存储利用率和灵活性。\n\n块级存储虚拟化将物理存储设备虚拟化为逻辑存储块代表技术包括 EMC VPLEX 和 IBM SVC。\n文件级存储虚拟化将物理文件系统资源虚拟化为逻辑文件系统资源代表技术包括 VMware vSAN 和 NetApp ONTAP。\n\n虚拟化的应用与前景\n虚拟化在企业中的应用\n虚拟化技术在企业中有广泛的应用主要体现在以下几个方面\n\n桌面虚拟化将桌面操作系统虚拟化提供云桌面服务。桌面虚拟化可以实现统一管理、降低成本、提高安全性。用户可以通过任何设备访问虚拟桌面提高了工作灵活性和效率。\n服务器虚拟化在物理服务器上运行多个虚拟机提高资源利用率、降低成本、简化管理。服务器虚拟化可以有效整合服务器资源减少硬件需求优化数据中心的运行效率。\n云计算虚拟化技术是云计算的基础实现资源的弹性化和扩展性。通过虚拟化云服务提供商可以灵活管理计算资源提供按需服务满足客户的各种需求。\n大数据虚拟化技术支持大数据的快速部署和扩展。通过虚拟化可以高效管理和调度大数据处理任务提高数据处理效率和灵活性。\n移动应用虚拟化技术支持移动应用的开发和部署。通过应用虚拟化可以确保移动应用在不同操作系统环境中的兼容性简化开发和测试流程提高应用的可靠性和安全性。\n\n虚拟化的未来发展趋势\n随着技术的不断发展虚拟化技术也在不断演进未来的发展趋势主要包括以下几个方面\n\n云计算的普及虚拟化技术是云计算的基础随着云计算的普及虚拟化技术将得到更广泛的应用。\n容器化技术的发展容器化技术是虚拟化技术的延伸具有更高的灵活性和效率未来将得到更多应用。\n边缘计算的兴起虚拟化技术可以应用于边缘计算提供更灵活的计算资源配置和管理。\n安全性增强随着虚拟化技术的普及虚拟化安全性将成为关注的重点未来将会有更多的安全技术和方案应用于虚拟化环境。\n\n通过虚拟化技术的不断发展和应用未来的 IT 基础设施将更加高效、灵活和安全,为企业的数字化转型提供有力支持。"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/1.-KVM-概述":{"title":"1. KVM 概述","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"引言\n什么是虚拟化\n**虚拟化是一种通过抽象底层硬件资源来创建多个独立运行的虚拟环境的技术。**它允许一台物理服务器运行多个操作系统实例,从而极大地提高了资源利用率和灵活性。\n虚拟化可以分为以下几类\n\n全虚拟化虚拟机完全模拟底层硬件操作系统无需修改即可运行。代表技术有 VMware ESXi 和 Microsoft Hyper-V。\n半虚拟化需要对操作系统进行修改以适应虚拟化环境从而提高性能。代表技术有 Xen。\n硬件辅助虚拟化通过 CPU 提供的虚拟化指令集(如 Intel VT-x 和 AMD-V来提高虚拟化性能。现代的虚拟化技术通常结合了全虚拟化和硬件辅助虚拟化。\n\n虚拟化的历史和发展\n虚拟化技术的起源可以追溯到 20 世纪 60 年代。当时 IBM 开发了 CP/CMS 操作系统,为大型机提供了虚拟化功能,以便同时运行多个操作系统实例。\n在 1960 年代IBM 的 CP-40 和 CP-67 系统首次引入了虚拟化的概念允许多个虚拟机在同一个物理机上运行。这些虚拟机提供了彼此隔离的操作环境极大地提高了大型机的利用率和灵活性。CP/CMS 操作系统是虚拟化技术的早期实现之一,为后来发展的虚拟化技术奠定了基础。\n进入 21 世纪随着硬件性能的提升和虚拟化需求的增加虚拟化技术得到了迅速发展。VMware 在 1999 年发布了首款商业虚拟化产品标志着现代虚拟化技术的兴起。随着开源社区的崛起KVMKernel-based Virtual Machine于 2006 年被合并到 Linux 内核中成为开源虚拟化领域的重要组成部分。KVM 通过将 Linux 内核转变为一个 Hypervisor为用户提供了高效且灵活的虚拟化解决方案。\nKVM 的定位和重要性\nKVMKernel-based Virtual Machine是 Linux 内核的一部分,它将 Linux 内核转变为一个 Hypervisor允许用户在 Linux 操作系统上运行多个隔离的虚拟机。作为一种开源虚拟化技术KVM 在虚拟化领域占据了重要地位。\nKVM 是一个模块化的虚拟化解决方案,与 Linux 内核紧密集成,利用 Linux 的调度和内存管理功能来实现高效的虚拟化。它支持全虚拟化和硬件辅助虚拟化,能够运行多种操作系统,包括 Linux、Windows 和 BSD。作为开源社区的一部分KVM 受到了广泛的支持和发展。它不仅被许多企业和研究机构采用,还成为了许多云计算平台(如 OpenStack的核心虚拟化技术。\nKVM 的应用领域非常广泛。在数据中心KVM 被广泛应用以提高服务器的利用率和灵活性。通过 KVM可以在同一台物理服务器上运行多个虚拟机从而实现资源的动态分配和高效利用。在云计算环境中KVM 得到了广泛应用,许多公有云和私有云平台都采用 KVM 作为底层虚拟化技术,为云计算提供了灵活的资源管理和隔离机制。开发人员和测试人员也利用 KVM 提供的灵活虚拟化环境快速创建和销毁虚拟机以便进行软件开发和测试。KVM 还可以用于桌面虚拟化,将用户的桌面环境虚拟化,实现集中管理和远程访问。\nKVM 的灵活性、高性能和开源特性使其成为现代虚拟化技术的重要组成部分,广泛应用于各个领域,推动了虚拟化技术的发展和普及。\nKVM 简介\n什么是 KVM\nKVMKernel-based Virtual Machine是一个开源虚拟化技术它将 Linux 内核转变为一个 Hypervisor使得用户可以在 Linux 操作系统上运行多个隔离的虚拟机。KVM 通过加载内核模块来提供虚拟化功能,并且依赖硬件辅助虚拟化技术(如 Intel VT-x 和 AMD-V来提高虚拟化性能。\nKVM 的定义\nKVM 是一个虚拟化基础架构,它将 Linux 内核转换为一个 Hypervisor从而使主机能够运行多个虚拟机。每个虚拟机拥有其独立的虚拟硬件包括 CPU、内存、磁盘和网络接口。\nKVM 的特点\n\n高性能KVM 利用硬件辅助虚拟化技术,实现了高效的虚拟化性能。\n模块化设计KVM 是一个内核模块,可以动态加载和卸载,不影响主机系统的其他功能。\n开源KVM 是开源项目,源代码公开,广泛应用于开源社区和企业环境。\n与 Linux 紧密集成KVM 作为 Linux 内核的一部分,能够充分利用 Linux 的调度、内存管理和设备驱动等功能。\n支持多种操作系统KVM 支持运行多种操作系统,包括 Linux、Windows、BSD 等。\n\nKVM 的发展历史和背景\nKVM 的发展历程可以追溯到 2006 年,由以色列企业 Qumranet 的 Avi Kivity 开发,并于同年被合并到 Linux 内核主线。随着时间的推移KVM 逐渐发展成为一个成熟的虚拟化解决方案。\nKVM 的起源和演变\nKVM 由 Avi Kivity 开发,并在 2006 年被合并到 Linux 内核版本 2.6.20。KVM 最初的目标是提供一个简单、高效的虚拟化解决方案,与现有的虚拟化技术(如 Xen形成竞争。\n关键版本和里程碑\n\n2006 年KVM 被合并到 Linux 内核 2.6.20,标志着 KVM 的诞生。\n2008 年Red Hat 收购 Qumranet进一步推动 KVM 的开发和商业化应用。\n2011 年KVM 成为 OpenStack 项目的核心组件之一,大大提升了其在云计算领域的应用。\n2014 年KVM 成为 Linux 基金会的一个顶级项目,进一步加强了其在开源社区的影响力。\n\nKVM 在虚拟化技术中的地位\nKVM 在虚拟化技术领域占据了重要地位,与其他虚拟化技术(如 VMware vSphere、Microsoft Hyper-V 和 Xen相比KVM 具有独特的优势。\nKVM 与其他虚拟化技术的比较\n\nVMware vSphereVMware vSphere 是一种成熟的商业虚拟化解决方案具有强大的管理工具和企业支持。相比之下KVM 虽然是开源项目,但在灵活性和成本效益方面具有优势。\nMicrosoft Hyper-VHyper-V 是微软的虚拟化解决方案,与 Windows Server 紧密集成。KVM 则与 Linux 紧密集成,适合在 Linux 环境中使用。\nXenXen 是另一种开源虚拟化技术早期采用半虚拟化技术后来也支持全虚拟化。KVM 相较于 Xen更容易与 Linux 系统集成,并且逐渐在开源社区中获得更广泛的支持。\n\nKVM 在开源社区的影响力\nKVM 作为一个开源项目,受到了广泛的支持和贡献。它不仅是许多 Linux 发行版的默认虚拟化技术,还在许多开源项目(如 OpenStack、oVirt 和 Proxmox中发挥着关键作用。KVM 的成功得益于其高效的性能、灵活的架构以及与 Linux 内核的紧密集成。作为开源社区的重要组成部分KVM 推动了虚拟化技术的发展和普及,为各类应用场景提供了强大的支持。\nKVM 的基本概念\n\nKVM 的工作原理\nKVMKernel-based Virtual Machine将 Linux 内核转变为一个 Hypervisor使其能够运行多个隔离的虚拟机。KVM 依赖于硬件辅助虚拟化技术,如 Intel VT-x 和 AMD-V以实现高效的虚拟化性能。\nKVM 与 Linux 内核的集成\nKVM 作为一个内核模块加载到 Linux 内核中利用内核的现有功能如调度和内存管理从而实现虚拟化。KVM 模块加载后Linux 内核变成一个功能强大的 Hypervisor能够创建和管理虚拟机。\nKVM 的运行机制\nKVM 通过/dev/kvm 设备接口与用户空间交互。用户空间的虚拟机管理工具(如 QEMU通过这个接口创建和管理虚拟机。每个虚拟机都有一个对应的 QEMU 进程,该进程负责模拟虚拟机的硬件设备,而 KVM 模块则处理虚拟机的 CPU 和内存管理。\n全虚拟化与半虚拟化\n\n虚拟化可以分为全虚拟化和半虚拟化两者在实现和性能上有所不同。\n全虚拟化的定义与实现\n全虚拟化是指虚拟机完全模拟底层硬件使操作系统无需修改即可运行。KVM 实现全虚拟化依赖于硬件辅助虚拟化技术通过这些技术KVM 可以拦截并处理虚拟机的特权指令,从而实现对底层硬件的完全模拟。\n半虚拟化的定义与实现\n半虚拟化是指需要对操作系统进行修改以适应虚拟化环境从而提高性能。半虚拟化通过让操作系统直接调用 Hypervisor 提供的接口来执行特权操作减少了特权指令的模拟开销。KVM 支持通过 virtio 接口提供半虚拟化设备,如 virtio-net 和 virtio-blk从而提高虚拟机的 I/O 性能。\n硬件辅助虚拟化\n硬件辅助虚拟化通过在 CPU 中添加专门的指令集来支持虚拟化,从而提高虚拟化性能并简化 Hypervisor 的实现。Intel 和 AMD 分别提供了 VT-x 和 AMD-V 技术来支持硬件辅助虚拟化。\nIntel VT-x 技术\nIntel VT-x 技术通过在 CPU 中添加虚拟化指令集支持全虚拟化。VT-x 技术包括虚拟机扩展VMX允许 KVM 拦截并处理虚拟机的特权指令以及扩展页表EPT提供高效的内存管理。\nAMD-V 技术\nAMD-V 技术类似于 Intel VT-x通过在 CPU 中添加虚拟化指令集来支持全虚拟化。AMD-V 技术包括安全虚拟机模式SVM允许 KVM 拦截并处理虚拟机的特权指令以及快速虚拟化索引RVI提供高效的内存管理。\n硬件辅助虚拟化的优势\n硬件辅助虚拟化的主要优势包括\n\n性能提升通过专门的指令集和硬件支持减少了虚拟机的特权指令模拟开销提高了虚拟化性能。\n简化实现硬件辅助虚拟化简化了 Hypervisor 的实现,使其能够更高效地管理虚拟机。\n提高安全性通过硬件隔离提高了虚拟机之间的隔离性增强了虚拟化环境的安全性。\n\nKVM 利用硬件辅助虚拟化技术,实现了高效、灵活和安全的虚拟化解决方案,广泛应用于数据中心、云计算、开发和测试等领域。\nKVM 的架构\n\nKVM 模块\nKVM 通过内核模块加载到 Linux 内核中,将其转变为一个功能强大的 Hypervisor。主要包括以下模块\nkvm.ko 模块\nkvm.ko 是 KVM 的核心模块,它提供了基本的虚拟化功能。该模块负责虚拟机的创建、配置和管理,并与硬件辅助虚拟化技术(如 Intel VT-x 和 AMD-V进行交互。\nkvm-intel.ko 和 kvm-amd.ko 模块\nkvm-intel.ko 和 kvm-amd.ko 是 KVM 的硬件特定模块。kvm-intel.ko 用于支持 Intel 的 VT-x 技术,而 kvm-amd.ko 则用于支持 AMD 的 AMD-V 技术。这些模块处理与特定 CPU 虚拟化指令集的交互,提供高效的虚拟化性能。\nQEMU 用户空间工具\nQEMU 是一个开源的用户空间虚拟化工具,与 KVM 协作以提供完整的虚拟化解决方案。\nQEMU 的作用和功能\n**QEMU 负责模拟虚拟机的硬件设备,如 CPU、内存、磁盘和网络接口。**它支持多种架构和设备提供灵活的虚拟机配置选项。QEMU 还负责虚拟机的启动、暂停和停止等操作。\nQEMU 与 KVM 的协作\nQEMU 与 KVM 协作,通过 /dev/kvm 设备接口与 KVM 模块进行通信。QEMU 处理虚拟机的用户态操作,如设备模拟和 I/O 操作,而 KVM 则负责虚拟机的内核态操作,如 CPU 和内存的管理。通过这种协作QEMU 和 KVM 提供了一个高效且灵活的虚拟化平台。\nKVM 和 QEMU 的关系\nKVM 和 QEMU 之间通过明确的分工来实现高效的虚拟化解决方案。\n用户态和内核态的分工\nKVM 负责内核态的虚拟化操作,主要包括 CPU 和内存的管理。QEMU 负责用户态的虚拟机管理和设备模拟。通过这种分工KVM 可以利用硬件虚拟化特性提供高性能的虚拟化支持,而 QEMU 则提供灵活的设备模拟和管理功能。\n资源管理和调度\nKVM 通过内核模块管理物理资源,如 CPU、内存和 I/O 设备。QEMU 通过用户态进程管理虚拟机的生命周期,并与 KVM 协同调度资源。KVM 利用 Linux 内核的调度机制,实现对虚拟机资源的高效管理。\n虚拟机监控器Hypervisor与宿主操作系统的关系\nKVM 作为一个内核模块,与宿主操作系统(通常是 Linux紧密集成共享和管理宿主机的资源。\n宿主机资源的管理\nKVM 使用 Linux 内核的调度和内存管理功能实现对虚拟机的资源分配和管理。宿主操作系统负责提供底层硬件的访问接口KVM 则通过这些接口管理虚拟机的运行。\n客户机与宿主机的交互\n客户机虚拟机通过虚拟硬件设备与宿主机进行交互。这些虚拟硬件设备由 QEMU 模拟,并通过 KVM 实现与实际硬件的映射。例如,客户机的网络流量通过虚拟网卡传输到宿主机,再由宿主机的物理网卡发送出去。\nKVM 的架构通过模块化设计,实现了高效的虚拟化性能和灵活的资源管理。与 QEMU 的紧密协作,使得 KVM 成为一个功能强大且广泛应用的虚拟化解决方案。\nKVM 的功能特性\n支持的操作系统\nKVM 作为一个强大的虚拟化平台,具有广泛的客户操作系统兼容性,能够运行多种操作系统,使其在各种应用场景中得以广泛应用。\n客户操作系统的兼容性\nKVM 支持多种客户操作系统,包括但不限于 Linux、Windows 和 BSD 系列操作系统。其兼容性源自 KVM 对硬件辅助虚拟化技术的支持,以及 QEMU 提供的广泛硬件设备模拟。\n常见支持的操作系统\n\nLinux几乎所有主流的 Linux 发行版都可以在 KVM 上运行,如 Ubuntu、CentOS、Debian、Fedora 等。\nWindowsKVM 支持多种版本的 Windows 操作系统,包括 Windows Server 和 Windows Desktop 版本。\nBSD 系列FreeBSD、OpenBSD 和 NetBSD 等 BSD 系列操作系统也能在 KVM 上良好运行。\n\n高性能和高可用性\nKVM 设计为高性能和高可用性环境,提供了多种性能优化机制和高可用性特性。\n性能优化机制\nKVM 通过硬件辅助虚拟化技术(如 Intel VT-x 和 AMD-V实现高效的虚拟化性能。此外KVM 利用 Linux 内核的调度和内存管理功能,以及高级的 I/O 虚拟化技术(如 Virtio来优化性能。\n\n硬件辅助虚拟化使用 CPU 的虚拟化指令集来降低虚拟化开销,提高性能。\nVirtio 驱动:提供高效的虚拟化 I/O 设备,提高网络和存储性能。\n大页支持利用大页内存减少内存管理开销提高内存访问性能。\n\n高可用性特性\nKVM 支持多种高可用性特性,确保虚拟机的持续可用性。\n\n实时迁移Live Migration允许虚拟机在不停机的情况下从一个物理主机迁移到另一个物理主机。\n故障转移在硬件故障时自动将虚拟机转移到备用主机确保服务不中断。\n快照和备份支持虚拟机的快照和备份机制提供恢复手段确保数据安全。\n\n内存管理和硬件支持\nKVM 提供了先进的内存管理机制和广泛的硬件支持,确保虚拟机的高效运行。\n内存分配和管理\nKVM 利用 Linux 内核的内存管理功能,实现高效的内存分配和管理。\n\n内存过量使用Overcommitment允许分配的虚拟内存总量超过物理内存总量提高资源利用率。\n透明大页Transparent Huge Pages自动将小页转换为大页减少内存管理开销提高性能。\n内存共享Memory Ballooning动态调整虚拟机的内存分配根据实际需求优化内存使用。\n\n硬件兼容性和支持\nKVM 兼容大多数现代 x86 和 x86_64 架构的硬件平台,支持 Intel 和 AMD 的硬件虚拟化技术。KVM 还支持多种硬件设备和外围设备,通过 PCI 直通PCI Passthrough技术可以将物理设备直接分配给虚拟机提高性能。\n网络和存储的虚拟化支持\nKVM 提供了强大的网络和存储虚拟化支持,确保虚拟机的灵活性和高效性。\n虚拟网络的实现\nKVM 通过虚拟网络设备和软件定义网络SDN技术实现灵活的网络虚拟化。\n\n虚拟网桥vBridge通过 Linux Bridge 或 Open vSwitch 实现虚拟机之间的网络连接。\n虚拟网络接口vNIC通过 Virtio 网络驱动提供高效的网络性能。\nSDN 集成:支持与 OpenStack Neutron 等 SDN 解决方案集成,实现高级网络功能。\n\n存储虚拟化的实现\nKVM 提供多种存储虚拟化机制,确保数据存储的高效和灵活。\n\n虚拟磁盘支持多种虚拟磁盘格式如 QCOW2、RAW、VMDK 等。\n存储池和卷通过 Libvirt 管理存储池和存储卷,提供灵活的存储分配。\nI/O 虚拟化:通过 Virtio 块设备驱动提供高效的存储性能。\n\n快照和备份\nKVM 提供了全面的快照和备份功能,确保虚拟机数据的安全和可恢复性。\n快照的创建与管理\nKVM 支持虚拟机的快照功能,可以在任何时间点创建虚拟机的状态快照,用于备份和恢复。\n\n创建快照通过 QEMU 或 Libvirt 接口创建虚拟机快照,保存当前状态。\n管理快照支持多级快照管理可以回滚到任意快照点实现灵活的状态恢复。\n\n备份和恢复机制\nKVM 提供了强大的备份和恢复机制,确保数据安全。\n\n实时备份支持虚拟机运行时的实时备份确保数据不丢失。\n增量备份通过 QCOW2 格式支持增量备份,减少备份数据量,提高效率。\n恢复机制提供便捷的恢复工具可以快速恢复虚拟机到任意备份点。\n\nKVM 的功能特性使其成为一个灵活、高效且可靠的虚拟化解决方案,广泛应用于数据中心、云计算、开发和测试等领域。\nKVM 的优缺点\nKVM 的优势\n开源免费\nKVM 是一个完全开源的虚拟化解决方案,任何人都可以免费使用、修改和分发。作为 Linux 内核的一部分KVM 继承了开源社区的优势,具有透明的开发流程和广泛的社区支持。此外,开源的特性使得用户可以根据需要定制虚拟化环境,而无需支付昂贵的许可费用。\n与 Linux 内核紧密集成\nKVM 直接集成在 Linux 内核中,利用 Linux 内核的强大功能如调度、内存管理和安全机制。这种紧密集成不仅提高了虚拟化性能还简化了虚拟化环境的管理。Linux 内核的稳定性和广泛的硬件支持也为 KVM 提供了坚实的基础。\n高性能和扩展性\nKVM 利用硬件辅助虚拟化技术(如 Intel VT-x 和 AMD-V提供了高效的虚拟化性能。通过 Virtio 驱动KVM 进一步优化了网络和存储 I/O 性能。此外KVM 支持实时迁移Live Migration、快照和大页内存等高级功能提供了高扩展性和灵活性满足各种复杂应用场景的需求。\nKVM 的限制和不足\n对硬件要求较高\nKVM 依赖硬件辅助虚拟化技术,因此对硬件的要求较高。需要支持 VT-x 或 AMD-V 的处理器才能发挥 KVM 的全部功能。这在某些旧硬件或嵌入式系统中可能会成为一个限制。\n学习曲线\n虽然 KVM 提供了强大的功能,但其配置和管理相对复杂,尤其对于初学者来说,学习曲线较陡。用户需要掌握 Linux 系统管理、QEMU、Libvirt 等相关知识,才能高效地使用和管理 KVM 环境。\n社区支持与企业支持的差异\nKVM 主要依靠开源社区的支持,虽然社区活跃且资源丰富,但与一些商业虚拟化解决方案相比,企业级的技术支持可能不够全面和及时。对于需要高可靠性和快速响应支持的企业用户,可能需要依赖第三方服务提供商,如 Red Hat 提供的企业级 KVM 支持。\nKVM 的应用场景\n服务器虚拟化\n数据中心的服务器整合\nKVM 在数据中心的服务器整合中发挥了重要作用。通过 KVM可以在一台物理服务器上运行多个虚拟机从而将多个服务器的工作负载集中到少量高性能服务器上。这种整合不仅降低了硬件成本还减少了物理空间的占用和电力消耗。此外KVM 的高效资源管理功能使得数据中心能够灵活分配和调整计算资源,提高整体运营效率。\n提高资源利用率\nKVM 通过虚拟化技术提高了物理服务器的资源利用率。传统物理服务器在不同应用负载下常常会有大量资源闲置,而 KVM 允许在同一物理服务器上运行多个虚拟机,每个虚拟机可以运行不同的应用程序,从而充分利用服务器的计算能力、内存和存储资源。这种资源共享和动态分配的能力,使得企业能够更高效地管理其 IT 基础设施。\n桌面虚拟化\n桌面即服务DaaS\nKVM 在桌面即服务DaaS中被广泛应用提供虚拟桌面基础设施VDI解决方案。通过 KVM用户可以在数据中心托管虚拟桌面并通过网络远程访问。这种方式不仅提高了数据安全性和管理的便捷性还降低了终端设备的成本和维护复杂性。用户可以通过各种设备如 PC、平板电脑和智能手机访问其虚拟桌面实现无缝办公体验。\n远程办公的支持\n随着远程办公需求的增加KVM 提供了可靠的虚拟化解决方案,支持员工在任何地点、任何设备上访问其工作环境。通过 KVM 实现的远程桌面虚拟化,可以确保数据安全和应用程序的一致性,同时提供高性能和低延迟的用户体验。这对于需要频繁远程访问公司资源的企业尤为重要。\n云计算环境中的应用\n公有云与私有云中的 KVM\nKVM 在公有云和私有云环境中都得到了广泛应用。许多公有云提供商,如 Google Cloud 和 OpenStack都使用 KVM 作为其底层虚拟化技术。KVM 的开源特性和高性能使其成为构建私有云的理想选择。企业可以使用 KVM 创建和管理虚拟机,提供灵活的计算资源,并根据需求动态扩展或缩减云环境。\nKVM 在 IaaS 中的作用\nKVM 在基础设施即服务IaaS中起着关键作用。通过 KVMIaaS 提供商能够为用户提供按需计算资源包括虚拟机、存储和网络。这种灵活的资源分配和管理方式使得用户可以根据其业务需求快速部署和调整计算资源同时仅为实际使用的资源付费。KVM 的高性能和可靠性确保了 IaaS 平台的稳定运行。\n开发和测试环境\n快速部署和回滚\n在开发和测试环境中KVM 提供了快速部署和回滚的能力。开发人员可以迅速创建虚拟机进行应用程序测试,模拟不同的操作系统和配置环境。通过快照功能,开发人员可以在测试前创建虚拟机快照,出现问题时快速回滚到之前的状态。这种灵活性大大提高了开发和测试的效率,缩短了软件开发周期。\n多平台兼容性测试\nKVM 支持多种操作系统,使其成为多平台兼容性测试的理想选择。开发团队可以在同一台物理服务器上运行多个虚拟机,测试应用程序在不同操作系统和版本上的表现。这种多平台测试能力,确保了软件在各种环境中的兼容性和稳定性,减少了发布后的问题和维护成本。\nKVM 的广泛应用场景展示了其作为一种高效、灵活的虚拟化解决方案的巨大潜力。从服务器虚拟化、桌面虚拟化到云计算和开发测试环境KVM 为各种业务需求提供了强有力的支持,助力企业实现数字化转型和高效运作。\nKVM 的未来发展\nKVM 社区的现状和发展方向\n当前社区的活跃度\nKVM 社区非常活跃,汇集了大量开发者、企业和开源爱好者的贡献。社区定期发布更新,改进功能和性能,并积极修复漏洞。大型企业如 Red Hat、Intel 和 IBM 等都在积极支持和推动 KVM 的发展,确保其在虚拟化领域的领先地位。\n社区的重要项目和贡献\nKVM 社区中有多个重要项目和贡献,这些项目推动了 KVM 的技术进步和广泛应用:\n\nQEMU作为 KVM 的用户空间工具QEMU 的开发和改进直接影响 KVM 的功能和性能。社区对 QEMU 的持续优化使得 KVM 在硬件模拟和设备支持方面不断增强。\nLibvirt这是一个开源 API 和管理工具集,用于管理 KVM 虚拟机。Libvirt 的开发提高了 KVM 虚拟机的管理和自动化能力,使其更易于集成和使用。\nVirtioVirtio 项目致力于优化虚拟机的 I/O 性能,通过提供高效的虚拟化驱动程序,使得 KVM 在网络和存储性能方面表现优异。\n\n新技术和趋势\nKVM 与容器技术的结合\n随着容器技术的普及KVM 与容器技术的结合成为一种趋势。KVM 提供了虚拟化的隔离性和安全性而容器技术则提供了轻量级和高效的应用部署方式。两者的结合可以实现更高效和安全的云计算环境。例如KubeVirt 项目就是一个将 KVM 和 Kubernetes 结合的开源项目,允许用户在 Kubernetes 集群中运行虚拟机,从而实现虚拟机和容器的混合编排。\nKVM 在边缘计算中的应用\n边缘计算的兴起为 KVM 提供了新的应用场景。在边缘计算环境中计算资源靠近数据源从而减少延迟和带宽消耗。KVM 可以在边缘节点上运行提供虚拟化服务使得边缘设备能够高效地运行各种应用程序。KVM 的灵活性和高性能使其成为边缘计算的理想选择,特别是在需要多租户隔离和资源动态分配的场景中。\nKVM 的性能优化和新特性\nKVM 的未来发展方向之一是持续的性能优化和新特性的引入。以下是一些值得关注的方向:\n\n内存优化通过改进内存管理机制如大页支持和内存共享技术提高虚拟机的内存使用效率。\nI/O 性能提升:通过优化 Virtio 驱动和引入新的 I/O 虚拟化技术,进一步提升虚拟机的网络和存储性能。\n安全性增强引入更多的安全机制如 SEV安全加密虚拟化和 SGX软件保护扩展提高虚拟机的隔离性和数据保护能力。\n多架构支持扩展对更多硬件架构的支持如 ARM 和 RISC-V以适应多样化的应用需求。\n\nKVM 作为一个成熟且不断发展的虚拟化解决方案其未来充满潜力。在社区的推动和新技术的引入下KVM 将继续优化和扩展其功能为用户提供更高效、安全和灵活的虚拟化服务。无论是在云计算、边缘计算还是在混合编排环境中KVM 都将发挥重要作用。"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/2.-KVM-安装配置":{"title":"2. KVM 安装配置","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"环境准备\n硬件要求\n检查 CPU 是否支持虚拟化技术Intel VT-x 或 AMD-V\n在部署 KVM 前,需要确保系统的 CPU 支持硬件虚拟化技术。这些技术包括 Intel 的 VT-x 和 AMD 的 AMD-V。以下是检查方法\n\nIntel CPU使用命令 grep -E "vmx" /proc/cpuinfo 检查 CPU 是否支持 VT-x。\nAMD CPU使用命令 grep -E "svm" /proc/cpuinfo 检查 CPU 是否支持 AMD-V。\n\n如果命令输出中包含 vmx 或 svm则表示 CPU 支持相应的虚拟化技术。\n启用 BIOS/UEFI 中的虚拟化支持\n**即使 CPU 支持虚拟化技术,也需要在 BIOS/UEFI 中启用相应的功能。**以下是通用的启用步骤,具体步骤可能因主板制造商不同而有所差异:\n\n启动计算机并进入 BIOS/UEFI 设置界面(通常按 Delete、F2、F10 或 Esc 键)。\n在 BIOS/UEFI 设置中,找到“高级”或“处理器”选项。\n启用 “Intel Virtualization Technology” 或 “AMD-V” 选项。\n保存更改并退出 BIOS/UEFI 设置。\n\n操作系统要求\nKVM 作为 Linux 内核的一部分,主要在 Linux 操作系统上运行。以下是一些常用的、支持 KVM 的 Linux 发行版:\n\nCentOS企业级发行版基于 Red Hat Enterprise Linux (RHEL) 的源代码构建,适合服务器环境。\nRHELRed Hat Enterprise Linux提供商业支持和长期维护广泛应用于企业环境。\nUbuntu广泛使用的发行版提供了良好的社区支持和文档。\n\n安装 KVM 和 QEMU\n在 Ubuntu 上安装\n\n\n更新软件包列表\nsudo apt update\n\n\n安装 KVM、QEMU 和相关工具:\napt -y install qemu-kvm libvirt-daemon-system libvirt-daemon virtinst libosinfo-bin\n\n\n启用并启动 libvirtd 服务:\nsudo systemctl enable --now libvirtd\n\n\n在 CentOS/RHEL 上安装\n\n\n更新系统\nsudo dnf update\n\n\n安装 KVM、QEMU 和相关工具:\nsudo dnf install qemu-kvm libvirt virt-install\n\n\n启用并启动 libvirtd 服务:\nsudo systemctl enable --now libvirtd\n\n\n在其他 Linux 发行版上安装\n以下是一些其他常见 Linux 发行版的安装方法:\n\n\nDebian:\nsudo apt update\nsudo apt install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils\nsudo systemctl enable --now libvirtd\n\n\nFedora:\nsudo dnf update\nsudo dnf install @virtualization\nsudo systemctl enable --now libvirtd\n\n\n安装虚拟机管理工具\n安装 libvirt\nlibvirt 是一个开源 API用于管理平台虚拟化。前面已经在安装 KVM 和 QEMU 时安装了 libvirt。确保其已启用并正在运行\nsudo systemctl enable --now libvirtd\n安装 virt-manager\nvirt-manager 是一个基于 GUI 的虚拟机管理工具,适用于桌面用户。\n\n\n在 Ubuntu 上安装:\nsudo apt install virt-manager\n\n\n在 CentOS/RHEL 上安装:\nsudo dnf install virt-manager\n\n\n在其他 Linux 发行版上安装:\n\n\nDebian:\nsudo apt install virt-manager\n\n\nFedora:\nsudo dnf install virt-manager\n\n\n\n\n验证安装\n检查 KVM 模块是否已加载\n\n\n检查 KVM 模块是否已加载:\nlsmod | grep kvm\n应该看到类似以下的输出\nkvm_intel 204800 0\nkvm 655360 1 kvm_intel\n\n\n如果使用 AMD 处理器,检查 kvm-amd 模块:\nlsmod | grep kvm\n应该看到类似以下的输出\nkvm_amd 204800 0\nkvm 655360 1 kvm_amd\n\n\n确认虚拟化功能可用\n\n\n在 Ubuntu 和 Debian 上使用 kvm-ok 工具检查虚拟化功能:\nsudo apt install cpu-checker\nsudo kvm-ok\n输出应显示\nINFO: /dev/kvm exists\nKVM acceleration can be used\n\n\n在 CentOS/RHEL 和其他发行版上,使用 virt-host-validate 工具检查:\nsudo virt-host-validate\n输出应显示\nQEMU: Checking for hardware virtualization: PASS\nQEMU: Checking for device /dev/kvm: PASS\nQEMU: Checking for device /dev/vhost-net: PASS\nQEMU: Checking for device /dev/net/tun: PASS\n……\n\n\n通过以上步骤可以确保 KVM 及其相关工具已正确安装并配置好。接下来可以开始创建和管理虚拟机,充分利用 KVM 提供的虚拟化功能。\n基本配置\n配置网络桥接\n网络桥接允许虚拟机直接与主机网络进行通信使其像物理机一样访问网络。以下是使用 nmcli 创建和配置虚拟网络桥接的详细步骤:\n创建虚拟网络桥接桥接模式\n\n\n安装必要的软件包\n\n\n在 Ubuntu 上:\nsudo apt update\nsudo apt install network-manager\n\n\n在 CentOS/RHEL 上:\nsudo dnf install NetworkManager\n\n\n\n\n配置网络桥接\n\n\n创建一个新的网桥接口\nsudo nmcli connection add type bridge ifname br0\n\n\n将物理接口连接到网桥上例如假设你正在使用 eth0 接口:\nsudo nmcli connection add type bridge-slave ifname eth0 master br0\n\n\n建议禁用网桥接口 IPv4 和 IPv6网桥接口仅作为二层设备使用\nsudo nmcli connection modify br0 ipv4.method disable\nsudo nmcli connection modify br0 ipv6.method disable\n\n\n激活网桥和物理接口\nsudo nmcli connection up br0\nsudo nmcli connection up eth0\n\n\n\n\n验证桥接配置\n\n\n检查网桥接口状态\nnmcli connection show\nnmcli device status\n应该看到类似以下的输出表示网桥 br0 和物理接口 eth0 已经配置并启用:\nNAME UUID TYPE DEVICE\nbr0 12345678-1234-1234-1234-123456789abc bridge br0\neth0 87654321-4321-4321-4321-abcdefabcdef ethernet eth0\n\n\n配置 Libvirt 使用桥接网络\n\n\n编辑或创建网络配置文件例如 /etc/libvirt/qemu/networks/bridged.xml\n<network>\n <name>bridged</name>\n <forward mode='bridge'/>\n <bridge name='br0'/>\n</network>\n\n\n定义并启动该网络\nsudo virsh net-define /etc/libvirt/qemu/networks/bridged.xml\nsudo virsh net-start bridged\nsudo virsh net-autostart bridged\n\n\n通过这些步骤您可以在 Ubuntu 和 CentOS 系列系统中使用 nmcli 来统一配置和管理网络桥接。这确保了配置的一致性,并简化了网络管理。\n配置存储池和存储卷\n存储池和存储卷管理是 KVM 中虚拟机存储管理的重要组成部分。存储池可以是目录、LVM 或 NFS 等类型,存储卷则是具体的磁盘映像文件。\n创建存储池\n\n\n目录类型存储池\n\n\n创建目录\nsudo mkdir -p /var/lib/libvirt/images\n\n\n定义存储池\nsudo virsh pool-define-as --name default --type dir --target /var/lib/libvirt/images\n\n\n启动并自动启动存储池\nsudo virsh pool-start default\nsudo virsh pool-autostart default\n\n\n\n\nLVM 类型存储池:\n\n\n创建物理卷和卷组\nsudo pvcreate /dev/sdX\nsudo vgcreate vg_kvm /dev/sdX\n\n\n定义存储池\nsudo virsh pool-define-as --name lvm-pool --type logical --source-name vg_kvm\n\n\n启动并自动启动存储池\nsudo virsh pool-start lvm-pool\nsudo virsh pool-autostart lvm-pool\n\n\n\n\nNFS 类型存储池:\n\n\n安装 NFS 客户端:\n\n\n在 Ubuntu 上:\nsudo apt install nfs-common\n\n\n在 CentOS/RHEL 上:\nsudo dnf install nfs-utils\n\n\n\n\n定义存储池\nsudo virsh pool-define-as nfs-pool netfs --source-host nfs-server --source-path /path/to/nfs/export --target /mnt/nfs\n\n\n启动并自动启动存储池\nsudo virsh pool-start nfs-pool\nsudo virsh pool-autostart nfs-pool\n\n\n\n\n管理存储卷\n\n\n创建存储卷\n\n\n在默认存储池中创建一个新的存储卷\nsudo virsh vol-create-as default new-volume 10G\n\n\n在 LVM 存储池中创建一个新的逻辑卷:\nsudo virsh vol-create-as lvm-pool lv_new-volume 10G\n\n\n\n\n查看存储卷\nsudo virsh vol-list default\nsudo virsh vol-list lvm-pool\n\n\n删除存储卷\nsudo virsh vol-delete new-volume --pool default\n\n\n通过以上配置步骤可以成功配置 KVM 的网络桥接、存储池和存储卷,确保虚拟机具备网络连接和存储资源。\n创建和管理虚拟机\n使用命令行工具创建虚拟机\n使用 virt-install 创建虚拟机\nvirt-install 是一个命令行工具,用于创建虚拟机。它支持多种参数,可以灵活配置虚拟机的各种选项。\n\n\n创建基本虚拟机\nsudo virt-install \\\n --name myvm \\\n --ram 2048 \\\n --disk path=/var/lib/libvirt/images/myvm.qcow2,size=20 \\\n --vcpus 2 \\\n --os-type linux \\\n --os-variant ubuntu20.04 \\\n --network bridge=br0 \\\n --graphics vnc \\\n --cdrom /path/to/ubuntu-20.04.iso\n以上命令创建了一个名为 myvm 的虚拟机,分配 2 GB 内存、20 GB 磁盘空间和 2 个虚拟 CPU使用桥接网络并通过 VNC 访问图形界面。\n\n\n其他常用选项\n在使用 virt-install 创建和安装虚拟机时,以下是一些常用的选项及其功能,列在一个表格中以便参考:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项功能--name虚拟机的名称--memory分配给虚拟机的内存大小单位MB--vcpus分配给虚拟机的虚拟 CPU 数量--disk定义虚拟机的磁盘配置--cdrom使用 CD-ROM 镜像文件作为安装源--location网络安装源的位置URL 或本地路径)--os-type指定操作系统类型如 linux、windows--os-variant指定操作系统版本--graphics配置图形显示方式--network配置虚拟机的网络接口--extra-args向内核传递额外的启动参数--boot配置引导设备和引导顺序--console配置控制台类型--import从现有磁盘映像文件导入虚拟机--autostart安装后自动启动虚拟机--cpu配置 CPU 相关选项--check启用或禁用安装前的配置检查--virt-type指定虚拟化类型如 kvm、xen--initrd-inject指定需要注入到 initrd 的文件--metadata定义虚拟机的元数据--noautoconsole安装后不自动连接到控制台--wait等待安装完成的时间单位分钟\n\n\n使用 virsh 管理虚拟机\nvirsh 是一个强大的命令行工具,用于管理和控制虚拟机。以下是一些常用的命令及其功能,列在一个表格中以便参考:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能virsh list列出当前运行的虚拟机virsh list --all列出所有虚拟机包括停止的virsh start <vm_name>启动指定的虚拟机virsh shutdown <vm_name>关闭指定的虚拟机virsh reboot <vm_name>重启指定的虚拟机virsh destroy <vm_name>强制关闭指定的虚拟机virsh suspend <vm_name>暂停指定的虚拟机virsh resume <vm_name>恢复暂停的虚拟机virsh create <xml_file>从 XML 配置文件创建并启动虚拟机virsh define <xml_file>定义但不启动虚拟机virsh undefine <vm_name>删除虚拟机定义但不删除磁盘文件virsh edit <vm_name>编辑虚拟机的 XML 配置virsh dumpxml <vm_name>输出指定虚拟机的 XML 配置virsh attach-disk <vm_name> <disk_path> <target_dev>附加磁盘到虚拟机virsh detach-disk <vm_name> <target_dev>从虚拟机分离磁盘virsh attach-interface <vm_name> <type> <source>附加网络接口到虚拟机virsh detach-interface <vm_name> <type> <mac>从虚拟机分离网络接口virsh snapshot-create-as <vm_name> <snapshot_name>创建虚拟机快照virsh snapshot-list <vm_name>列出虚拟机的所有快照virsh snapshot-revert <vm_name> <snapshot_name>恢复到指定快照virsh migrate <vm_name> <dest_uri>迁移虚拟机到另一个主机virsh console <vm_name>连接到虚拟机的控制台virsh dominfo <vm_name>显示虚拟机的详细信息virsh domstats <vm_name>显示虚拟机的统计信息\n使用图形化工具创建虚拟机\n安装和使用 virt-manager\nvirt-manager 是一个基于图形界面的虚拟机管理工具,适合那些更喜欢图形界面操作的用户。\n\n\n安装 virt-manager\n\n\n在 Ubuntu 上:\nsudo apt install virt-manager\n\n\n在 CentOS/RHEL 上:\nsudo dnf install virt-manager\n\n\n\n\n启动 virt-manager\nvirt-manager\n\n\n通过 virt-manager 创建和配置虚拟机\n\n创建新虚拟机\n\n打开 virt-manager点击左上角的“创建新虚拟机”按钮。\n选择安装来源例如ISO 映像或 PXE 网络引导),然后点击“转到下一步”。\n设置虚拟机名称、内存和 CPU 配置,然后点击“转到下一步”。\n配置虚拟机硬盘例如创建新磁盘映像或导入现有磁盘然后点击“转到下一步”。\n选择网络配置例如使用桥接网络然后点击“转到下一步”。\n检查配置并点击“完成”以创建虚拟机。\n\n\n配置虚拟机\n\n右键点击已创建的虚拟机选择“打开”以启动虚拟机。\n在虚拟机启动后可以通过 VNC 或 SPICE 连接访问虚拟机的图形界面。\n可以通过“虚拟机”菜单下的“编辑”选项修改虚拟机配置如增加内存、添加硬盘或修改网络设置。\n\n\n\n通过上述方法可以使用命令行工具和图形化工具创建和管理 KVM 虚拟机。无论是命令行操作还是图形界面,都提供了丰富的选项和灵活的配置,使得 KVM 虚拟机的管理变得简单高效。"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/3.-KVM-管理工具":{"title":"3. KVM 管理工具","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"KVM 管理工具\nKVM 管理工具是用于管理和控制 KVMKernel-based Virtual Machine虚拟化环境的工具。这些工具提供了创建、配置、监控和维护虚拟机的功能简化了 KVM 虚拟化环境的管理。KVM 管理工具可以是命令行工具、图形化用户界面GUI工具或基于 Web 的管理平台。\n\nKVM 管理工具在虚拟化环境中的作用和重要性主要体现在以下几个方面:\n\n简化虚拟机管理通过图形化界面或命令行工具管理员可以方便地创建、配置和管理虚拟机减少了手动配置的复杂性。\n提高效率管理工具提供自动化功能如批量创建虚拟机、自动配置网络和存储从而提高管理效率。\n增强监控和维护通过监控工具可以实时监控虚拟机的性能和资源使用情况及时发现和解决问题确保系统稳定运行。\n安全性和隔离管理工具提供访问控制和权限管理功能确保虚拟机和宿主机之间的安全隔离保护数据和系统安全。\n灵活性和可扩展性支持多种虚拟机配置和管理需求适应不同规模和复杂度的虚拟化环境。\n\nLibvirt\nLibvirt 概述\n**Libvirt 是一个开源的 API、守护进程和管理工具集用于管理平台虚拟化。**其主要功能和特点包括:\n\n多种虚拟化后端支持Libvirt 支持多种虚拟化技术,如 KVM、QEMU、Xen、VMware ESXi、Microsoft Hyper-V 等。\n抽象化和统一管理接口Libvirt 提供统一的 API 和管理工具,简化了不同虚拟化技术的管理。\n丰富的管理功能支持虚拟机的生命周期管理、存储管理、网络管理、快照、迁移等。\n广泛的语言绑定支持多种编程语言的 API 绑定,如 C、Python、Perl、Java、Go 等,方便开发者集成和扩展。\n\n**Libvirt 支持多种虚拟化后端,**主要包括:\n\nKVM/QEMU主流的开源虚拟化解决方案广泛应用于 Linux 服务器和桌面环境。\nXen高性能的开源虚拟化技术特别适用于服务器虚拟化和云计算。\nVMware ESXi商业虚拟化解决方案广泛应用于企业数据中心。\nMicrosoft Hyper-VWindows Server 内置的虚拟化技术,适用于 Windows 环境。\n其他还支持 LXCLinux 容器、OpenVZ 等轻量级虚拟化技术。\n\nLibvirt 安装与配置\n在不同的 Linux 发行版上安装 Libvirt步骤如下\n\n在 Ubuntu 上:\n\n sudo apt update\n sudo apt install libvirt-daemon-system libvirt-clients\n sudo systemctl enable --now libvirtd\n\n在 CentOS/RHEL 上:\n\n sudo yum update\n sudo yum install libvirt libvirt-python\n sudo systemctl enable --now libvirtd\n\n\n配置文件位置\n\n主配置文件/etc/libvirt/libvirtd.conf\n网络配置文件/etc/libvirt/qemu/networks/\n\n\n\n常用配置项\n\n\n# 启用 TCP 连接 \n listen_tls = 0\n listen_tcp = 1\n auth_tcp = "none"\n# 设置日志级别\n log_filters="3:remote 4:event"\n log_outputs="1:file:/var/log/libvirt/libvirtd.log"\n\n重启 Libvirt 服务:\n\nsudo systemctl restart libvirtd\nVirsh 管理命令\nVirsh 是一个强大的命令行工具,用于管理基于 libvirt 的虚拟化环境。其功能和特点包括:\n\n管理虚拟机生命周期创建、删除、启动、停止、重启虚拟机。\n配置和调整虚拟机资源修改虚拟机的 CPU、内存、网络和存储配置。\n快照管理创建、恢复和删除虚拟机快照。\n实时迁移在主机之间迁移虚拟机。\n网络和存储管理创建和管理虚拟网络、存储池和存储卷。\n脚本化和自动化支持脚本化操作方便批量管理和自动化运维。\n\nVirt-install\nvirsh-install 命令是用于在 KVM 环境中创建虚拟机的一个非常常用的命令。它提供了一系列选项来配置和启动虚拟机。\n# 创建虚拟机\nsudo virt-install \\\n --name myvm \\\n --ram 2048 \\\n --disk path=/var/lib/libvirt/images/myvm.qcow2,size=20 \\\n --vcpus 2 \\\n --os-type linux \\\n --os-variant ubuntu20.04 \\\n --network bridge=br0 \\\n --graphics vnc \\\n --cdrom /path/to/ubuntu-20.04.iso\n常用选项\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选项描述--name设置虚拟机的名称--memory指定虚拟机的内存大小MB--vcpus指定虚拟机的 CPU 数量--disk指定虚拟机的磁盘配置如路径、大小、格式等--cdrom指定安装介质如 ISO 文件路径)--network指定虚拟机的网络配置--os-variant指定虚拟机操作系统的类型--graphics设置图形界面配置如 VNC、Spice 等)--extra-args指定附加的引导参数--location指定安装介质的位置如网络安装源--import导入已有磁盘来创建虚拟机--boot指定引导选项如引导顺序、引导设备等--initrd-inject将文件注入到虚拟机的 initrd--console指定控制台配置\n通用\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh help显示所有可用命令的帮助信息virsh quit / exit退出 virsh 交互模式virsh connect qemu:///system连接到本地 QEMU/KVM 管理器virsh uri显示当前连接的 URIvirsh version显示 libvirt 版本信息virsh hostname显示主机名virsh sysinfo显示系统信息virsh nodeinfo显示节点硬件信息virsh list --all列出所有虚拟机包括运行中和停止的virsh start <vm_name>启动指定虚拟机virsh nodecpustats显示节点 CPU 统计信息virsh nodememstats显示节点内存统计信息\n主机\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh start <vm_name>启动指定虚拟机virsh shutdown <vm_name>关闭指定虚拟机virsh reboot <vm_name>重启指定虚拟机virsh suspend <vm_name>挂起指定虚拟机virsh resume <vm_name>恢复挂起的虚拟机virsh destroy <vm_name>强制关闭指定虚拟机virsh autostart <vm_name>设置指定虚拟机开机自启virsh undefine <vm_name>取消定义指定虚拟机virsh dominfo <vm_name>显示虚拟机的基本信息virsh domstate <vm_name>显示虚拟机的当前状态virsh domiflist <vm_name>列出虚拟机的网络接口virsh domblklist <vm_name>列出虚拟机的块设备virsh domstats <vm_name>显示虚拟机的统计信息virsh dumpxml <vm_name>显示虚拟机的 XML 配置virsh edit <vm_name>编辑虚拟机的 XML 配置virsh console <vm_name>连接到虚拟机的控制台virsh setmem <vm_name> <size>设置虚拟机的内存大小virsh setvcpus <vm_name> <count>设置虚拟机的 CPU 数量\n设备\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh attach-device <vm_name> <device.xml>连接设备virsh detach-device <vm_name> <device.xml>分离设备virsh attach-disk <vm_name> <source> <target>附加磁盘virsh detach-disk <vm_name> <target>分离磁盘virsh attach-interface <vm_name> <type> <source>连接接口virsh detach-interface <vm_name> <type> <mac>分离接口virsh update-device <vm_name> <device.xml>更新设备virsh change-media <vm_name> <path> --eject --insert改变媒体\n节点\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh nodedev-list列出所有节点设备virsh nodedev-info <device>显示节点设备的信息virsh nodedev-dumpxml <device>显示节点设备的 XML 配置virsh nodedev-reattach <device>重新附加节点设备virsh nodedev-detach <device>分离节点设备virsh nodedev-reset <device>重置节点设备virsh nodedev-autostart <device>设置节点设备开机自启\n网络\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh net-list --all列出所有虚拟网络virsh net-info <network>显示虚拟网络的信息virsh net-dumpxml <network>显示虚拟网络的 XML 配置virsh net-create <network.xml>创建虚拟网络virsh net-destroy <network>销毁虚拟网络virsh net-start <network>启动虚拟网络virsh net-autostart <network>设置虚拟网络开机自启virsh net-undefine <network>取消定义虚拟网络virsh net-edit <network>编辑虚拟网络的 XML 配置virsh net-update <network> <command> <section> <xml>更新虚拟网络virsh net-dhcp-leases <network>列出网络的 DHCP 租约\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh net-port-list <network>列出指定虚拟网络的所有端口virsh net-port-create <port.xml>创建网络端口virsh net-port-dumpxml <port>显示网络端口的 XML 配置virsh net-port-delete <port>删除网络端口\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh iface-list --all列出所有网络接口virsh iface-info <interface>显示网络接口的信息virsh iface-dumpxml <interface>显示网络接口的 XML 配置virsh iface-define <interface.xml>定义新网络接口virsh iface-undefine <interface>取消定义网络接口virsh iface-start <interface>启动网络接口virsh iface-destroy <interface>销毁网络接口virsh iface-edit <interface>编辑网络接口的 XML 配置virsh iface-bridge <interface> <bridge>将接口桥接到指定桥virsh iface-unbridge <bridge>取消接口的桥接virsh iface-commit <interface>提交接口的更改virsh iface-rollback <interface>回滚接口的更改\n存储\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh pool-list --all列出所有存储池virsh pool-info <pool>显示存储池的信息virsh pool-dumpxml <pool>显示存储池的 XML 配置virsh pool-create <pool.xml>从 XML 文件创建存储池virsh pool-create-as <name> <type> <source>创建指定类型的存储池virsh pool-define <pool.xml>从 XML 文件定义存储池virsh pool-define-as <name> <type> <source>定义指定类型的存储池virsh pool-start <pool>启动存储池virsh pool-build <pool>构建存储池virsh pool-refresh <pool>刷新存储池virsh pool-autostart <pool>设置存储池开机自启virsh pool-destroy <pool>销毁存储池virsh pool-delete <pool>删除存储池virsh pool-undefine <pool>取消定义存储池virsh find-storage-pool-sources --type <type>查找存储池源\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh vol-list <pool>列出指定存储池的所有卷virsh vol-info <volume>显示卷的信息virsh vol-dumpxml <volume>显示卷的 XML 配置virsh vol-create <pool> <volume.xml>从 XML 文件创建卷virsh vol-create-as <pool> <name> <capacity>创建指定大小的卷virsh vol-create-from <pool> <name> <source-volume>从现有卷创建新卷virsh vol-clone <source-volume> <new-volume>克隆卷virsh vol-delete <volume>删除卷virsh vol-upload <volume> <source>上传数据到卷virsh vol-download <volume> <dest>从卷下载数据virsh vol-resize <volume> <capacity>调整卷大小virsh vol-wipe <volume>擦除卷virsh vol-path <volume>显示卷的路径virsh vol-name <volume>显示卷的名称virsh vol-key <volume>显示卷的唯一标识符\n快照\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh snapshot-list <vm_name>列出指定虚拟机的所有快照virsh snapshot-info <snapshot>显示快照的信息virsh snapshot-dumpxml <snapshot>显示快照的 XML 配置virsh snapshot-create <vm_name>创建快照virsh snapshot-create-as <vm_name> <snapshot_name>创建命名快照virsh snapshot-current <vm_name>显示当前快照virsh snapshot-edit <snapshot>编辑快照的 XML 配置virsh snapshot-revert <vm_name> <snapshot>恢复到指定快照virsh snapshot-delete <vm_name> <snapshot>删除指定快照virsh snapshot-parent <snapshot>显示快照的父级快照\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh checkpoint-list <vm_name>列出指定虚拟机的所有检查点virsh checkpoint-info <checkpoint>显示检查点的信息virsh checkpoint-dumpxml <checkpoint>显示检查点的 XML 配置virsh checkpoint-create <vm_name>创建检查点virsh checkpoint-create-as <vm_name> <checkpoint_name>创建命名检查点virsh checkpoint-edit <checkpoint>编辑检查点的 XML 配置virsh checkpoint-delete <vm_name> <checkpoint>删除指定检查点virsh checkpoint-parent <checkpoint>显示检查点的父级检查点\nLibvirt API 开发\n使用 Libvirt API\nLibvirt 提供丰富的 API用于开发和集成虚拟化管理工具。以下是使用 Python Libvirt API 的示例:\n\n\n安装 Python Libvirt 库:\nsudo apt install python3-libvirt\n\n\nPython 示例代码:\nimport libvirt\n \nconn = libvirt.open('qemu:///system')\nif conn is None:\n print('Failed to open connection to qemu:///system')\n exit(1)\n \ndomains = conn.listAllDomains()\nfor domain in domains:\n print('Domain: ' + domain.name())\nconn.close()\n\n\nLibvirt 与其他工具的集成\nLibvirt 与许多其他工具集成,提供全面的虚拟化管理功能:\n\nOpenStack作为 IaaS 平台OpenStack 使用 Libvirt 作为其底层虚拟化管理工具之一。\noVirt基于 Libvirt 的虚拟化管理平台,提供企业级虚拟化解决方案。\nAnsible使用 ansible-libvirt 模块,可以通过 Ansible 自动化管理 Libvirt 虚拟机和资源。\n\nVirt-manager\nVirt-manager 概述\nVirt-manager 是一个基于 GUI 的虚拟机管理工具,用于管理 KVM、QEMU 和其他支持的虚拟化平台。其主要功能和特点包括:\n\n虚拟机创建和配置通过图形化界面轻松创建和配置虚拟机包括设置 CPU、内存、存储和网络等资源。\n虚拟机监控实时监控虚拟机的性能和资源使用情况提供详细的统计信息。\n存储和网络管理管理虚拟机的存储池、存储卷和网络配置支持多种存储和网络类型。\n快照和迁移支持虚拟机快照创建和恢复以及实时迁移虚拟机到其他主机。\n易用性提供直观的图形化界面简化了虚拟机管理任务。\n\nVirt-manager 的图形化界面包括以下主要部分:\n\n主窗口显示所有已定义的虚拟机及其状态提供虚拟机的基本管理操作。\n详细信息面板展示选定虚拟机的详细信息包括硬件配置、性能监控和控制台访问。\n菜单和工具栏提供常用的管理功能和配置选项如创建新虚拟机、启动/停止虚拟机、查看日志等。\n\nVirt-manager 安装与配置\n在不同的 Linux 发行版上安装 Virt-manager 的步骤如下:\n# 在 Debian/Ubuntu 上\nsudo apt update\nsudo apt install virt-manager\n \n# 在 CentOS/RHEL 上\nsudo dnf install virt-manager\n\n\n启动 libvirtd 服务(如果尚未启动):\nsudo systemctl enable --now libvirtd\n\n\n配置用户权限 确保用户属于 libvirt 组,以便能够管理虚拟机:\nsudo usermod -aG libvirt $USER\n\n\n重启系统或重新登录以应用权限更改。\n\n\n使用 Virt-manager 管理虚拟机\n创建和配置虚拟机\n\n\n启动 Virt-manager 打开终端并运行 virt-manager 命令,或通过桌面环境的应用菜单启动 Virt-manager。\n\n\n\n创建新虚拟机\n\n\n在 Virt-manager 主界面,点击左上角的创建新虚拟机按钮。\n\n\n\n选择安装来源例如 ISO 映像或网络安装),点击转到下一步。\n\n\n\n设置虚拟机名称、内存和 CPU 配置,点击转到下一步。\n\n\n\n配置虚拟机硬盘例如创建新磁盘映像或使用现有磁盘点击转到下一步。\n\n\n\n选择网络配置例如桥接网络或默认 NAT 网络),点击转到下一步。\n\n\n\n检查配置并点击完成以创建虚拟机。\n\n\n\n\n配置虚拟机\n\n右键点击已创建的虚拟机选择打开以启动虚拟机。\n在虚拟机启动后可以通过 VNC 或 SPICE 连接访问虚拟机的图形界面。\n在虚拟机设置中可以调整虚拟机的硬件配置如增加内存、添加硬盘或修改网络设置。\n\n\n\n监控和管理虚拟机\n\n监控虚拟机性能\n\n在 Virt-manager 主界面,双击虚拟机名称进入详细信息面板。\n查看 CPU、内存、网络和存储的实时使用情况。\n\n\n管理虚拟机状态\n\n在主界面中右键点击虚拟机名称可以选择启动、暂停、恢复、关闭等操作。\n查看和管理虚拟机的快照执行备份和恢复操作。\n\n\n\n使用 Virt-manager 进行快照和迁移\n\n创建快照\n\n在 Virt-manager 中,选择虚拟机,右键点击并选择快照。\n点击创建快照按钮输入快照名称和描述然后点击创建。\n\n\n恢复快照\n\n在 Virt-manager 中,选择虚拟机,右键点击并选择快照。\n选择要恢复的快照点击恢复按钮。\n\n\n实时迁移虚拟机\n\n在 Virt-manager 中,选择要迁移的虚拟机,右键点击并选择迁移。\n输入目标主机的连接信息选择迁移选项如实时迁移然后点击开始迁移。\n\n\n\n通过上述方法用户可以使用 Virt-manager 轻松创建、配置和管理 KVM 虚拟机同时进行性能监控、快照管理和虚拟机迁移等操作。Virt-manager 的图形化界面使得虚拟机管理任务更加直观和便捷。\nCockpit\nCockpit 概述\nCockpit 是一个开源的服务器管理工具,提供了一个基于 Web 的图形用户界面,用于管理 Linux 服务器。其主要功能和特点包括:\n\n实时监控和管理提供实时系统性能监控、日志查看、服务管理等功能。\n用户友好简单直观的 Web 界面,易于使用和配置。\n扩展性通过插件机制扩展功能可以管理存储、虚拟化、网络等。\n多服务器管理可以集中管理多个服务器支持跨主机操作。\n集成虚拟化管理内置对 KVM 虚拟机的支持,可以创建和管理虚拟机。\n\nCockpit 的架构包括以下主要组件:\n\nWeb 前端:基于 HTML5 和 JavaScript 构建的用户界面,通过 Web 浏览器访问。\nCockpit 服务:运行在服务器上的后台服务,处理用户请求并与系统进行交互。\n系统接口Cockpit 使用 D-Bus 与 Linux 系统和服务进行通信,执行管理任务。\n\nCockpit 安装与配置\nCockpit 可以在多种 Linux 发行版上安装。以下是一些常见的安装步骤:\n# 在 Ubuntu 上\nsudo apt update\nsudo apt install cockpit\nsudo systemctl enable --now cockpit.socket\n# 打开防火墙端口\nsudo ufw allow 9090/tcp\n \n# 在 CentOS/RHEL 上\nsudo yum install cockpit\nsudo systemctl enable --now cockpit.socket\n# 打开防火墙端口\nsudo firewall-cmd --add-port=9090/tcp --permanent\nsudo firewall-cmd --reload\n在浏览器中访问 https://<server-ip>:9090使用服务器上的用户凭证登录。\n使用 Cockpit 管理虚拟机\n创建和管理虚拟机\n\n\n启用虚拟化插件\n安装 Cockpit 的虚拟化插件(如果尚未安装)。\n\n\n# 在 Ubuntu 上:\nsudo apt install cockpit-machines\n \n# 在 CentOS/RHEL 上:\nsudo yum install cockpit-machines\n\n创建虚拟机\n\n\n在 Cockpit Web 界面中,导航到虚拟机页面。\n点击创建新虚拟机按钮按照向导输入虚拟机名称、操作系统类型、内存、CPU 和磁盘配置。\n选择安装来源ISO 镜像或网络安装),点击创建完成虚拟机的创建。\n\n\n管理虚拟机\n\n\n在虚拟机页面查看已创建的虚拟机列表。\n选择虚拟机可以执行启动、停止、重启、暂停等操作。\n点击虚拟机名称可以查看详细信息并修改配置。\n\n配置网络和存储\n\n配置网络\n\n在虚拟机页面选择虚拟机并进入详细信息页面。\n在网络选项卡中添加或修改网络接口选择桥接或 NAT 网络类型。\n\n\n配置存储\n\n在虚拟机页面选择虚拟机并进入详细信息页面。\n在存储选项卡中添加或修改存储设备选择磁盘镜像文件或 LVM 卷。\n\n\n\n使用 Cockpit 进行监控和管理\n\n监控系统性能\n\n在 Cockpit 主界面中,查看系统概览,包括 CPU、内存、磁盘和网络使用情况。\n导航到日志页面查看系统日志和服务日志帮助诊断问题。\n\n\n管理服务\n\n在 Cockpit 主界面中,导航到服务页面,查看和管理系统服务。\n可以启动、停止、重启服务并查看服务状态和日志。\n\n\n多服务器管理\n\n在 Cockpit 主界面中,导航到仪表板页面,添加其他服务器进行集中管理。\n输入其他服务器的 IP 地址和凭证,添加成功后,可以跨主机进行操作和监控。\n\n\n\n通过以上步骤用户可以使用 Cockpit 创建和管理虚拟机配置网络和存储并进行系统监控和管理。Cockpit 提供了一个直观且功能强大的 Web 界面,使得 Linux 服务器管理变得更加简便和高效。\nProxmox VE\nProxmox VE 概述\nProxmox Virtual Environment (Proxmox VE) 是一个开源的服务器虚拟化管理平台,集成了 KVM 和 LXCLinux 容器),提供企业级的虚拟化解决方案。其主要功能和特点包括:\n\n虚拟化集成支持 KVM 虚拟机和 LXC 容器,提供灵活的虚拟化选择。\n集中管理通过基于 Web 的用户界面,集中管理所有虚拟机和容器。\n高可用性内置高可用性HA集群管理确保服务持续运行。\n存储支持支持多种存储类型包括本地存储、NFS、iSCSI 和 Ceph 分布式存储。\n备份和恢复提供全面的备份和恢复功能确保数据安全。\n集成防火墙内置防火墙功能提高虚拟机和容器的安全性。\n集成 Web 界面:易于使用的 Web 界面,简化管理任务。\n\nProxmox VE 的架构主要包括以下组件:\n\nProxmox VE 主机:运行 KVM 和 LXC 的物理服务器,托管虚拟机和容器。\nProxmox VE 集群:多个 Proxmox VE 主机组成的集群,提供高可用性和负载均衡。\nProxmox VE Web 界面:基于 Web 的管理界面,用于管理集群、虚拟机和容器。\nProxmox VE API提供 RESTful API用于集成和自动化管理任务。\n\nProxmox VE 安装与配置\n\n下载 Proxmox VE 安装 ISO\n\n访问 Proxmox VE 官网 下载最新的安装 ISO。\n\n\n创建安装介质\n\n使用 Rufus、Etcher 等工具,将 ISO 写入 U 盘或刻录到光盘。\n\n\n启动安装\n\n将安装介质插入服务器重启并从安装介质启动。\n按照安装向导完成安装包括选择目标磁盘、配置网络和设置管理账户。\n\n\n完成安装后访问 Web 界面:\n\n在浏览器中访问 https://<server-ip>:8006使用安装时设置的管理账户登录。\n\n\n\n使用 Proxmox VE 管理虚拟机\n创建和管理虚拟机\n\n创建虚拟机\n\n在 Web 界面中,导航到节点 →虚拟机。\n点击创建虚拟机按照向导输入虚拟机名称、操作系统类型、硬盘大小和网络配置。\n点击完成创建虚拟机。\n\n\n管理虚拟机\n\n在虚拟机列表中选择虚拟机使用启动、停止、重启等操作管理虚拟机。\n编辑虚拟机配置调整 CPU、内存、存储和网络设置。\n\n\n\n配置网络和存储\n\n配置虚拟网络\n\n在节点 →网络中添加或编辑桥接网络、VLAN 和绑定接口。\n在虚拟机网络设置中选择相应的网络接口。\n\n\n配置存储卷\n\n在数据中心 →存储中,添加或管理存储池。\n为虚拟机分配存储卷调整存储大小和类型。\n\n\n\n高可用性和备份\n\n配置高可用性\n\n在数据中心 →高可用性中,添加虚拟机到高可用性组。\n配置高可用性参数确保虚拟机在节点故障时自动迁移。\n\n\n配置备份\n\n在数据中心 →备份中,创建备份计划,选择备份存储、频率和保留策略。\n配置备份任务确保定期备份虚拟机数据。\n\n\n\nKVM 管理工具的选择\n根据需求选择合适的工具\n选择合适的 KVM 管理工具应根据具体需求进行考虑,例如企业环境的高可用性、桌面环境的简单虚拟机管理等。\n\n\n**libvirt**libvirt 是一个开源 API、守护进程和管理工具用于管理平台虚拟化技术包括 KVM、QEMU、Xen、VMware ESXi 等。\n\n\n**virt-manager**virt-manager 是一个基于桌面的图形化工具,用于管理 KVM 虚拟机,主要依赖于 libvirt。\n\n\n**Cockpit**Cockpit 是一个轻量级的 web 界面,支持系统管理和 KVM 虚拟机管理,通过插件扩展功能。\n\n\n**Proxmox VE**Proxmox VE 是一个开源的企业级虚拟化管理平台,支持 KVM 和 LXC 容器,提供高可用性、备份和集群管理功能。\n\n\n各工具的优缺点比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具优点缺点适用场景易用性扩展性性能优化高可用性支持平台界面libvirt灵活、支持多种虚拟化平台、API 支持广泛、命令行工具强大初学者学习曲线较陡需要较多配置和命令行操作高度定制化需求一般高高无KVM, QEMU, Xen, VMware ESXiCLIvirt-manager图形化界面简单易用、适合桌面环境、依赖 libvirt功能相对较少不支持高级特性如高可用性和集群管理小规模桌面环境高一般一般无KVMGUICockpit轻量级、扩展性强、支持插件、直观的 web 界面虚拟机管理功能有限需要额外配置中小型服务器管理高高一般无KVMWebProxmox VE集成度高、支持高可用性和备份、图形化界面友好、支持集群管理和 LXC 容器初始配置复杂、对硬件要求较高企业级虚拟化和容器管理一般高高高KVM, LXCWeb\n未来发展趋势\nKVM 管理工具的发展方向\n\n自动化和编排随着虚拟化和云计算的发展自动化和编排工具将变得更加重要。\n容器集成越来越多的 KVM 管理工具开始支持容器,提供虚拟机和容器的混合管理。\n增强安全性安全性将继续成为虚拟化管理的重要考虑因素更多的安全功能和机制将被集成。\n\n新兴技术和工具\n\n云原生技术Kubernetes 和 OpenShift 等云原生平台正在集成虚拟化功能,提供统一的容器和虚拟机管理。\n边缘计算随着边缘计算的兴起新的虚拟化管理工具将出现支持分布式和低延迟环境。\n人工智能和机器学习AI 和 ML 技术将被用于优化虚拟化管理,提供智能调度和预测性维护。\n"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/4.-KVM-网络配置":{"title":"4. KVM 网络配置","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"KVM 网络基础\nKVMKernel-based Virtual Machine网络是指在 KVM 虚拟化环境中,为虚拟机提供的网络连接和通信机制。通过 KVM 网络,虚拟机可以与其他虚拟机、宿主机以及外部网络进行通信。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n网络类型描述优点缺点适用场景NAT 网络虚拟机通过宿主机的网络接口与外部通信IP 地址被隐藏。配置简单,适合需要外部通信的虚拟机。虚拟机间通信需额外配置,网络性能可能受限。适合不需外部访问但需访问外网的虚拟机。桥接网络虚拟机直接连接物理网络接口,拥有独立 IP 地址,可直接与其他设备通信。与物理网络无缝集成,适合需外部访问的虚拟机。配置较复杂,需适当配置物理网络接口。适合需要直接对外提供服务的虚拟机。内部网络仅允许虚拟机之间的通信,不与宿主机或外部网络通信。提供隔离网络,适合测试和开发。虚拟机无法与外部网络通信。适合需要隔离的测试和开发环境。仅主机网络允许虚拟机与宿主机通信,但不与外部网络通信。简单隔离,适合虚拟机与宿主机通信。虚拟机无法与外部网络通信。适合虚拟机与宿主机需要频繁交互的场景。\nKVM 网络安装与准备\n你可以选择使用任意一款网络管理工具这里**推荐使用NetworkManager**来管理网络桥接。\n安装 NetworkManager\n非 Fedora/RHEL 系列,需要手动安装 NetworkManager并配置 NetworkManager 接管网络。\n# Debian/Ubuntu 系列\nsudo apt-get update\nsudo apt-get install -y network-manager\n配置系统网络支持\n\n\n启用 NetworkManager\n# 启动并启用 NetworkManager 服务\nsudo systemctl start NetworkManager\nsudo systemctl enable NetworkManager\n\n\n创建并配置网络桥接\n使用nmcli工具创建一个新的桥接接口。例如创建名为br0的桥接接口并将现有的以太网接口假设为eth0添加到桥接中。\nsudo nmcli connection add type bridge autoconnect yes con-name br0 ifname br0\nsudo nmcli connection add type bridge-slave autoconnect yes con-name br0-slave ifname eth0 master br0\nsudo nmcli connection modify br0 ipv4.method auto\nsudo nmcli connection up br0\n\n\n确认桥接网络配置\n使用以下命令确认桥接网络是否正确配置。\nnmcli connection show\nip a\n\n\n确认内核模块加载情况\n确保KVM相关的内核模块已加载\nlsmod | grep kvm\n\n\n示例配置文件\n对于NetworkManager的配置文件一般位于/etc/NetworkManager/system-connections/目录下你可以手动编辑这些文件进行更复杂的配置。例如编辑br0的配置文件\n[connection]\nid=br0\ntype=bridge\ninterface-name=br0\nautoconnect=true\n \n[ipv4]\nmethod=auto\n \n[ipv6]\nmethod=auto\n其他注意事项\n\n防火墙配置确保你的防火墙规则允许桥接网络的流量。\n验证桥接网络创建一个虚拟机并将其连接到br0桥接网络验证网络连接是否正常。\n\nNAT 网络\n**KVM 默认会创建一个名为 default 的 NAT 网络。**这个网络通常在安装 libvirt 时自动创建和启用。\n\n\n检查并启用默认网络\n检查 default 网络是否已经存在并启用:\nsudo virsh net-list --all\n如果默认网络未启用可以通过以下命令启用\nsudo virsh net-start default\nsudo virsh net-autostart default\n\n\n查看默认网络配置\n查看默认网络的详细配置\nsudo virsh net-dumpxml default\n\n典型的默认网络配置如下\n<network>\n <name>default</name>\n <uuid>……</uuid>\n <forward mode='nat'>\n <nat>\n <port start='1024' end='65535'/>\n </nat>\n </forward>\n <bridge name='virbr0' stp='on' delay='0'/>\n <mac address='52:54:00:d3:9b:fb'/>\n <ip address='192.168.122.1' netmask='255.255.255.0'>\n <dhcp>\n <range start='192.168.122.2' end='192.168.122.254'/>\n </dhcp>\n </ip>\n</network>\n\n\n创建虚拟机\n创建一台连接到 default 网络的虚拟机。可以使用 virt-install 命令来完成:\nsudo virt-install \\\n --name myvm \\\n --ram 4096 \\\n --disk path=/var/lib/libvirt/images/myvm_storage.qcow2,size=32 \\\n --vcpus 2 \\\n --os-type linux \\\n --os-variant ubuntu20.04 \\\n --network network=default \\\n --graphics none \\\n --console pty,target_type=serial \\\n --location 'mirrors.tuna.tsinghua.edu.cn/ubuntu/dists/focal/main/installer-amd64/' \\\n --extra-args 'console=ttyS0,115200n8 serial'\n\n\n验证虚拟机网络连接\n登录到虚拟机并验证其网络连接\nping -c 4 8.8.8.8\n检查虚拟机是否能够获得 IP 地址:\nip a\n\n\nvirsh 创建自定义 NAT 网络\n通过 virsh 命令创建自定义 NAT 网络,并配置 DHCP 和 IP 地址范围。\n\n\n创建网络配置文件\n创建一个自定义网络配置文件如 custom-net.xml\n<network>\n <name>custom-net</name>\n <forward mode='nat'/>\n <bridge name='virbr1' stp='on' delay='0'/>\n <mac address='52:54:00:12:34:56'/>\n <ip address='192.168.100.1' netmask='255.255.255.0'>\n <dhcp>\n <range start='192.168.100.2' end='192.168.100.254'/>\n </dhcp>\n </ip>\n</network>\n\n\n定义并启动网络\n使用 virsh 命令定义并启动该网络:\nsudo virsh net-define custom-net.xml\nsudo virsh net-start custom-net\nsudo virsh net-autostart custom-net\n\n\n查看自定义网络状态\n确认网络已启用\nsudo virsh net-list --all\n\n\n在上面的 custom-net.xml 文件中,已经定义了 DHCP 范围:\n<ip address='192.168.100.1' netmask='255.255.255.0'>\n <dhcp>\n <range start='192.168.100.2' end='192.168.100.254'/>\n </dhcp>\n</ip>\n此配置表示\n\n网关地址192.168.100.1\nDHCP 范围192.168.100.2 到 192.168.100.254\n\nNetworkManager 创建自定义 NAT 网络\n\n\n确保 NetworkManager 已启用:\nsudo systemctl enable --now NetworkManager\n\n\n创建 NetworkManager 桥接连接:\n编辑 NetworkManager 配置文件,创建一个桥接网络(例如 /etc/NetworkManager/system-connections/bridge-br1.nmconnection\n[connection]\nid=bridge-br1\ntype=bridge\nautoconnect=true\n \n[bridge]\nstp=true\n \n[ipv4]\nmethod=manual\naddress1=192.168.100.1/24\n \n[ipv6]\nmethod=ignore\n\n\n重启 NetworkManager 服务:\nsudo systemctl restart NetworkManager\n\n\n验证桥接网络\n确认新的桥接网络已创建并启用\nnmcli connection show\n\n\n桥接网络\n使用 NetworkManager 的 nmcli 命令来创建和配置桥接网络接口,并将物理接口绑定到网桥。\n\n\n创建桥接接口\n使用 nmcli 命令创建一个新的桥接接口:\nsudo nmcli connection add type bridge ifname br0\n\n\n配置桥接接口的 IP 地址:\n为桥接接口配置 IP 地址:\nsudo nmcli connection modify br0 ipv4.addresses 192.168.1.100/24 ipv4.method manual\nsudo nmcli connection modify br0 ipv4.gateway 192.168.1.1\nsudo nmcli connection modify br0 ipv4.dns "8.8.8.8,8.8.4.4"\nsudo nmcli connection modify br0 connection.autoconnect yes\n\n\n将物理接口绑定到桥接接口\n假设物理接口为 eth0使用 nmcli 将其绑定到 br0\nsudo nmcli connection add type ethernet ifname eth0 master br0\n\n\n启用桥接接口\n启用桥接接口 br0 和物理接口 eth0\nsudo nmcli connection up br0\nsudo nmcli connection up eth0\n\n\n编辑虚拟机的 XML 配置文件:\n假设虚拟机名称为 testvm使用以下命令编辑其 XML 配置文件:\nsudo virsh edit testvm\n\n\n添加桥接网络接口配置\n在 <devices> 部分中添加以下内容,将 br0 作为桥接接口:\n<interface type='bridge'>\n <mac address='52:54:00:12:34:56'/>\n <source bridge='br0'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n\n\n保存并退出\n保存配置文件并退出编辑器。\n\n\n重启虚拟机\n重启虚拟机使新的网络配置生效\nsudo virsh shutdown testvm\nsudo virsh start testvm\n\n\n内部网络\n内部网络允许虚拟机之间进行通信而无需通过外部网络。这种网络模式适用于需要隔离的测试环境或需要内部通信的应用。\n\n\n创建内部网络 XML 配置文件\n首先创建一个 XML 文件(如 internal-net.xml定义内部网络的配置\n<network>\n <name>internal-net</name>\n <forward mode='none'/>\n <bridge name='virbr1' stp='on' delay='0'/>\n <ip address='192.168.200.1' netmask='255.255.255.0'>\n <dhcp>\n <range start='192.168.200.2' end='192.168.200.254'/>\n </dhcp>\n </ip>\n</network>\n\n\n在上面的 XML 文件中,已定义网络名称为 internal-netIP 地址范围为 192.168.200.2 到 192.168.200.254。\n\n\n定义并启动网络\n使用 virsh 命令定义并启动内部网络:\nsudo virsh net-define internal-net.xml\nsudo virsh net-start internal-net\nsudo virsh net-autostart internal-net\n\n\n编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n\n在 <devices>部分中添加以下内容,将 internal-net作为网络接口\n<interface type='network'>\n <mac address='52:54:00:12:34:56'/>\n <source network='internal-net'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n\n\n保存并退出编辑器。\n\n\n重启虚拟机使新的网络配置生效\nsudo virsh shutdown <vm_name>\nsudo virsh start <vm_name>\n\n\n仅主机网络\n仅主机网络Host-only Network允许虚拟机与宿主机通信但不允许虚拟机与外部网络通信。这种网络模式适用于需要虚拟机与宿主机进行隔离通信的场景。\n\n\n创建仅主机网络 XML 配置文件\n创建一个 XML 文件(如 host-only-net.xml定义仅主机网络的配置\n<network>\n <name>host-only-net</name>\n <forward mode='none'/>\n <bridge name='virbr2' stp='on' delay='0'/>\n <ip address='192.168.150.1' netmask='255.255.255.0'>\n <dhcp>\n <range start='192.168.150.2' end='192.168.150.254'/>\n </dhcp>\n </ip>\n</network>\n在上面的 XML 文件中,已定义网络名称为 host-only-netIP 地址范围为 192.168.150.2 到 192.168.150.254。\n\n\n定义并启动网络\n使用 virsh 命令定义并启动仅主机网络:\nsudo virsh net-define host-only-net.xml\nsudo virsh net-start host-only-net\nsudo virsh net-autostart host-only-net\n\n\n编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n在 <devices>部分中添加以下内容,将 host-only-net 作为网络接口:\n<interface type='network'>\n <mac address='52:54:00:12:34:56'/>\n <source network='host-only-net'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n\n\n保存并退出编辑器。\n\n\n重启虚拟机使新的网络配置生效\nsudo virsh shutdown <vm_name>\nsudo virsh start <vm_name>\n\n\n高级网络功能\nVLAN 配置\n使用 NetworkManager 和 nmcli 命令创建 VLAN 网络。\n\n\n创建 VLAN 接口:\n假设物理接口为 eth0VLAN ID 为 100VLAN 接口命名为 eth0.100\nsudo nmcli connection add type vlan con-name vlan100 dev eth0 id 100\n\n\n配置 VLAN 接口 IP 地址:\n为 VLAN 接口配置 IP 地址:\nsudo nmcli connection modify vlan100 ipv4.addresses 192.168.100.1/24 ipv4.method manual\nsudo nmcli connection modify vlan100 ipv4.gateway 192.168.100.254\nsudo nmcli connection modify vlan100 ipv4.dns "8.8.8.8,8.8.4.4"\nsudo nmcli connection up vlan100\n\n\n使用 virsh 配置 VLAN 网络\n\n编辑虚拟机的 XML 配置文件:\n\nsudo virsh edit <vm_name>\n\n在 <devices>部分中添加以下内容,将 vlan100作为网络接口\n\n<interface type='network'>\n<mac address='52:54:00:12:34:56'/>\n<source network='vlan100'/>\n<model type='virtio'/>\n<vlan>\n <tag id='100'/>\n</vlan>\n<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n\n\n保存并退出编辑器。\n\n\n重启虚拟机使新的网络配置生效\n\n\nsudo virsh shutdown <vm_name>\nsudo virsh start <vm_name>\n\n\n配置虚拟机的多网卡\n\n编辑虚拟机的 XML 配置文件:\n\nsudo virsh edit <vm_name>\n\n在 <devices>部分中添加多个 <interface>元素,每个代表一个网络接口:\n\n<interface type='network'>\n <mac address='52:54:00:12:34:56'/>\n <source network='default'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n<interface type='network'>\n <mac address='52:54:00:12:34:57'/>\n <source network='vlan100'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>\n</interface>\n\n\n保存并退出编辑器。\n\n\n重启虚拟机使新的网络配置生效\n\n\nsudo virsh shutdown <vm_name>\nsudo virsh start <vm_name>\n配置网络带宽限制\n\n编辑虚拟机的 XML 配置文件:\n\nsudo virsh edit <vm_name>\n\n在 <interface> 元素中添加 <bandwidth> 元素,设置带宽限制参数,例如:\n\n<interface type='network'>\n <mac address='52:54:00:12:34:56'/>\n <source network='default'/>\n <model type='virtio'/>\n <bandwidth>\n <inbound average='1000' peak='2000' burst='512'/>\n <outbound average='1000' peak='2000' burst='512'/>\n </bandwidth>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n以上配置将网络带宽限制为入站和出站各 1000 Kbps 平均速率2000 Kbps 峰值速率512 KB 突发流量。\n\n\n保存并退出编辑器。\n\n\n重启虚拟机使新的网络配置生效\n\n\nsudo virsh shutdown <vm_name>\nsudo virsh start <vm_name>\n\n\n在宿主机和虚拟机上安装 iperf\nsudo apt install iperf3 # Ubuntu\nsudo yum install iperf3 # CentOS/RHEL\n\n\n在虚拟机上启动 iperf 服务端:\niperf3 -s\n\n\n在宿主机上运行 iperf 客户端进行带宽测试:\niperf3 -c <vm_ip_address>\n\n\n检查测试结果验证带宽限制是否生效。\n\n\n通过以上步骤使用 NetworkManager 和 nmcli 命令配置 VLAN 网络、为虚拟机添加多个网卡,并使用 virsh 配置网络带宽限制。同时,可以通过 iperf 工具验证网络带宽限制的效果。\n管理和监控虚拟网络\nvirsh 命令管理网络\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述virsh net-list --all列出所有虚拟网络virsh net-info <network>显示虚拟网络的信息virsh net-dumpxml <network>显示虚拟网络的 XML 配置virsh net-create <network.xml>创建虚拟网络virsh net-destroy <network>销毁虚拟网络virsh net-start <network>启动虚拟网络virsh net-autostart <network>设置虚拟网络开机自启virsh net-undefine <network>取消定义虚拟网络virsh net-edit <network>编辑虚拟网络的 XML 配置virsh net-update <network> <command> <section> <xml>更新虚拟网络virsh net-dhcp-leases <network>列出网络的 DHCP 租约\n监控网络性能\n使用 iftop 和 vnstat 等工具\n\n\n安装 iftop 和 vnstat\n # 在 Ubuntu 上\nsudo apt install iftop vnstat\n \n# 在 CentOS/RHEL 上\nsudo yum install iftop vnstat\n\n\n使用 iftop 监控实时网络流量:\n sudo iftop -i <network_interface>\niftop 会显示实时的网络流量,包括发送和接收数据的主机 IP 和带宽使用情况。\n\n\n使用 vnstat 监控网络流量:\n初始化 vnstat数据库\nsudo vnstat -u -i <network_interface>\n\n\n查看实时流量\nsudo vnstat -l\n\n\n查看流量统计\nsudo vnstat\n\n\n查看详细流量统计\nsudo vnstat -d # 查看每日流量统计\nsudo vnstat -m # 查看每月流量统计\nsudo vnstat -t # 查看每小时流量统计\n\n\n\n\n分析网络流量和性能\n\n分析流量数据\n\n使用 iftop 和 vnstat 收集的流量数据,可以帮助识别网络瓶颈和高流量的主机。\n\n\n优化网络配置\n\n根据监控数据优化虚拟网络的配置例如调整网络带宽限制、优化网络拓扑结构等。\n\n\n监控网络接口的性能\n\n定期检查和分析网络接口的性能确保虚拟网络的稳定性和高效运行。\n\n\n\n安全配置\n配置防火墙规则\n使用 iptables 配置防火墙\n\n\n安装 iptables\n# 在 CentOS/RHEL 上\nsudo yum install iptables-services\nsudo systemctl enable --now iptables\n \n# 在 Ubuntu 上\nsudo apt install iptables\n\n\n配置基本规则\n允许虚拟机网络通信\nsudo iptables -A FORWARD -i virbr0 -o eth0 -j ACCEPT\nsudo iptables -A FORWARD -i eth0 -o virbr0 -j ACCEPT\n\n\n保存规则\n# 在 CentOS/RHEL 上\nsudo service iptables save\n \n# 在 Ubuntu 上\nsudo iptables-save | sudo tee /etc/iptables/rules.v4\n\n\n配置 firewalld 管理规则\n\n\n安装 firewalld\n# 在 CentOS/RHEL 上\nsudo yum install firewalld\nsudo systemctl enable --now firewalld\n \n# 在 Ubuntu 上\nsudo apt install firewalld\nsudo systemctl enable --now firewalld\n\n\n配置基本规则\n允许虚拟机网络通信\nsudo firewall-cmd --zone=public --add-interface=virbr0 --permanent\nsudo firewall-cmd --zone=public --add-masquerade --permanent\nsudo firewall-cmd --reload\n\n\n网络隔离与访问控制\n使用 VLAN 实现网络隔离\n\n\n创建 VLAN 接口:\n使用 nmcli创建 VLAN 接口:\nsudo nmcli connection add type vlan con-name vlan100 dev eth0 id 100\nsudo nmcli connection modify vlan100 ipv4.addresses 192.168.100.1/24 ipv4.method manual\n\n\nsudo nmcli connection up vlan100\n\n2. **配置虚拟机使用 VLAN**\n\n使用 `virt-manager` 或 `virsh` 配置虚拟机连接到 VLAN 网络。\n\n#### 配置虚拟机访问控制列表ACL\n\n1. **使用 `virsh` 配置 ACL**\n\n为虚拟机创建网络 ACL 规则:\n\n```shell\nsudo virsh nwfilter-define /etc/libvirt/nwfilter/myfilter.xml\n\n配置 myfilter.xml文件示例\n<filter name='myfilter' chain='ipv4'>\n <uuid>...</uuid>\n <rule action='accept' direction='in' priority='500'>\n <mac address='52:54:00:12:34:56'/>\n </rule>\n <rule action='drop' direction='in' priority='1000'/>\n</filter>\n\n\n应用 ACL 到虚拟机:\n编辑虚拟机的 XML 配置文件,应用网络过滤器:\n<interface type='network'>\n <mac address='52:54:00:12:34:56'/>\n <source network='default'/>\n <model type='virtio'/>\n <filterref filter='myfilter'/>\n</interface>\n重启虚拟机使 ACL 生效。\n\n\n故障排查\n常见网络问题及解决方法\n虚拟机无法连接网络\n\n检查虚拟机的网络配置\n\n确认虚拟机的网络接口配置正确。\n使用 virsh dumpxml <vm_name> 命令查看虚拟机的 XML 配置,确保 <interface> 部分配置正确。\n\n\n检查虚拟网络状态\n\n使用 virsh net-list --all 命令查看虚拟网络是否启动。\n如果虚拟网络未启动使用 virsh net-start <network_name> 启动虚拟网络。\n\n\n检查宿主机的网络配置\n\n确认宿主机的网络接口和桥接配置正确。\n使用 nmcli connection show 命令查看 NetworkManager 的连接状态,确保相关接口已连接。\n\n\n检查虚拟机的 IP 地址:\n\n登录到虚拟机使用 ip a 命令查看虚拟机的 IP 地址是否正确分配。\n如果未分配 IP 地址,检查 DHCP 配置是否正确。\n\n\n\n网络性能问题\n\n检查网络带宽限制\n\n确认是否为虚拟机配置了带宽限制。\n使用 virsh edit <vm_name> 命令检查 <bandwidth> 配置。\n\n\n检查网络流量\n\n使用 iftop 和 vnstat 等工具监控网络流量,识别高流量主机和瓶颈。\n\n\n优化网络配置\n\n调整虚拟机的网络接口配置例如使用 Virtio 网络驱动以提高性能。\n使用桥接网络模式确保虚拟机与物理网络的高效通信。\n\n\n\n日志查看与分析\n查看 libvirt 网络日志\n\nlibvirt 日志路径:\n\n在 CentOS/RHEL 上libvirt 日志通常位于 /var/log/libvirt/ 目录下。\n在 Ubuntu 上libvirt 日志通常位于 /var/log/libvirt/ 目录下。\n\n\n查看网络日志\n\n使用 tail -f /var/log/libvirt/libvirtd.log 命令查看实时日志。\n使用 grep 命令筛选关键字以查找特定问题,例如 grep "network" /var/log/libvirt/libvirtd.log。\n\n\n\n使用系统日志进行排查\n\n查看系统日志\n\n使用 journalctl 命令查看系统日志,例如 journalctl -u libvirtd 查看 libvirtd 服务的日志。\n\n\n检查网络相关日志\n\n使用 dmesg 命令查看内核日志,查找与网络相关的错误信息。\n\n\n"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/5.-KVM-存储管理":{"title":"5. KVM 存储管理","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"KVM 存储\n存储概念\nKVMKernel-based Virtual Machine存储是指在 KVM 虚拟化环境中为虚拟机提供的存储资源。KVM 支持多种存储类型包括磁盘映像文件、逻辑卷管理LVM和网络存储。虚拟机的存储设备可以像物理机的硬盘一样使用并且可以通过不同的存储格式和协议进行管理和访问。\n虚拟机存储类型\n磁盘映像文件qcow2, raw\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型特点使用场景qcow2 (QEMU Copy On Write version 2)支持动态分配、快照、压缩和加密。磁盘空间在实际使用时才分配可以节省存储空间。适合需要多快照和动态存储分配的环境。raw不支持快照、压缩和加密直接映射磁盘数据。性能更高适合需要最大化性能的场景。适合高性能需求和简单存储管理的环境。\n其他常见磁盘映像文件类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型特点使用场景qcow (QEMU Copy On Write)qcow2 的前身,支持动态分配和快照,但性能和功能不及 qcow2。已有 qcow 格式的旧环境。vmdk (Virtual Machine Disk)主要用于 VMware 虚拟机,可以兼容 KVM。支持多种虚拟磁盘格式和快照。需要在 KVM 和 VMware 之间进行迁移的环境。vdi (Virtual Disk Image)主要用于 Oracle VirtualBox 虚拟机,可以兼容 KVM。支持动态分配和快照。需要在 KVM 和 VirtualBox 之间进行迁移的环境。vhd/vhdx (Virtual Hard Disk)主要用于 Microsoft Hyper-V 虚拟机,可以兼容 KVM。vhdx 是 vhd 的改进版本,支持更大容量和更高性能。需要在 KVM 和 Hyper-V 之间进行迁移的环境。\n逻辑卷管理LVM\n逻辑卷管理LVM提供灵活的存储管理可以动态调整逻辑卷大小、快照和卷组管理。性能较高适合企业级应用和需要高性能、灵活存储管理的环境。\n\n\n创建物理卷和卷组\nsudo pvcreate /dev/sdX\nsudo vgcreate vg_kvm /dev/sdX\n\n\n创建逻辑卷\nsudo lvcreate -n lv_myvm -L 20G vg_kvm\n\n\n网络存储NFS, iSCSI\nNFSNetwork File System通过网络共享文件系统适合共享存储和集中存储管理以及多台虚拟机需要共享同一存储资源的环境。\n挂载 NFS 存储:\nsudo mount -t nfs server:/path/to/nfs /mnt/nfs\niSCSIInternet Small Computer Systems Interface\n通过网络提供块级存储适合高性能需求的存储应用以及需要集中管理和高性能存储访问的环境。\n\n安装 iSCSI 客户端:\n\nsudo apt install open-iscsi # Ubuntu\nsudo yum install iscsi-initiator-utils # CentOS/RHEL\n\n发现和登录 iSCSI 目标:\n\nsudo iscsiadm -m discovery -t sendtargets -p <iSCSI_server_IP>\nsudo iscsiadm -m node --login\n配置系统存储支持\n确认存储驱动加载情况\n\n\n检查存储驱动\n使用 lsmod 命令检查存储驱动是否加载:\nlsmod | grep -E 'virtio_blk|virtio_scsi'\n\n\n加载存储驱动\n如果存储驱动未加载可以手动加载\nsudo modprobe virtio_blk\nsudo modprobe virtio_scsi\n\n\n准备存储设备和挂载点\n\n\n准备本地存储设备\n分区和格式化存储设备\nsudo fdisk /dev/sdX\nsudo mkfs.ext4 /dev/sdX1\n创建挂载点并挂载\nsudo mkdir -p /mnt/kvm_storage\nsudo mount /dev/sdX1 /mnt/kvm_storage\n\n\n准备网络存储设备NFS 例子):\n安装 NFS 客户端:\nsudo apt install nfs-common # Ubuntu\nsudo yum install nfs-utils # CentOS/RHEL\n挂载 NFS 共享:\nsudo mkdir -p /mnt/nfs_storage\nsudo mount -t nfs server:/path/to/nfs /mnt/nfs_storage\n\n\n配置自动挂载\n编辑 /etc/fstab 文件,添加以下内容确保重启后自动挂载:\n/dev/sdX1 /mnt/kvm_storage ext4 defaults 0 2\nserver:/path/to/nfs /mnt/nfs_storage nfs defaults 0 0\n\n\n通过以上步骤可以为 KVM 环境配置各种存储支持包括磁盘映像文件、LVM 和网络存储。确保存储驱动已加载,并准备好存储设备和挂载点,为虚拟机提供可靠的存储资源。\n配置存储池\n存储池是什么\n存储池的概念\n存储池Storage Pool是 KVM 虚拟化环境中的一种抽象概念用于管理和组织底层存储资源。存储池可以包含多个存储卷Storage Volume每个存储卷对应虚拟机的一个磁盘映像文件、逻辑卷或网络存储块。通过存储池管理员可以更方便地管理和分配存储资源。\n存储池的类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型特点使用场景目录存储池 (Directory Storage Pool)使用本地或挂载的目录作为存储池。简单易用,适合中小型部署。适合中小型部署。逻辑卷存储池 (LVM Storage Pool)基于 LVMLogical Volume Manager创建和管理逻辑卷。提供灵活的卷管理和快照功能。适合企业级部署。网络存储池 (Network Storage Pool)使用网络存储协议(如 NFS、iSCSI创建存储池。适合分布式存储和集中存储管理。适合分布式存储和集中存储管理。\n创建和管理目录存储池\n使用 virsh 创建目录存储池\n\n\n创建目录存储池\n创建一个目录存储池的 XML 配置文件,例如 dir-pool.xml\n<pool type='dir'>\n <name>dir-pool</name>\n <target>\n <path>/mnt/kvm_storage</path>\n </target>\n</pool>\n\n\n定义并启动存储池\n使用 virsh 命令定义并启动目录存储池:\nsudo virsh pool-define dir-pool.xml\nsudo virsh pool-start dir-pool\nsudo virsh pool-autostart dir-pool\n\n\n配置目录存储池\n\n\n查看存储池信息\nsudo virsh pool-info dir-pool\n\n\n查看存储池中的存储卷\nsudo virsh vol-list dir-pool\n\n\n创建存储卷\nsudo virsh vol-create-as dir-pool volume1 10G\n\n\n创建和管理逻辑卷存储池\n使用 virsh 创建 LVM 存储池\n\n\n创建 LVM 存储池:\n创建一个 LVM 存储池的 XML 配置文件,例如 lvm-pool.xml\n<pool type='logical'>\n <name>lvm-pool</name>\n <source>\n <device path='/dev/vg_kvm'/>\n <name>vg_kvm</name>\n <format type='lvm2'/>\n </source>\n <target>\n <path>/dev/vg_kvm</path>\n </target>\n</pool>\n\n\n定义并启动存储池\n使用 virsh 命令定义并启动 LVM 存储池:\nsudo virsh pool-define lvm-pool.xml\nsudo virsh pool-start lvm-pool\nsudo virsh pool-autostart lvm-pool\n\n\n配置 LVM 存储池\n\n\n查看存储池信息\nsudo virsh pool-info lvm-pool\n\n\n查看存储池中的存储卷\nsudo virsh vol-list lvm-pool\n\n\n创建存储卷\nsudo virsh vol-create-as lvm-pool lv_volume1 20G\n\n\n创建和管理网络存储池\n使用 virsh 创建 NFS 存储池\n\n\n创建 NFS 存储池:\n创建一个 NFS 存储池的 XML 配置文件,例如 nfs-pool.xml\n<pool type='netfs'>\n <name>nfs-pool</name>\n <source>\n <host name='nfs-server'/>\n <dir path='/path/to/nfs'/>\n </source>\n <target>\n <path>/mnt/nfs_storage</path>\n </target>\n</pool>\n\n\n定义并启动存储池\n使用 virsh 命令定义并启动 NFS 存储池:\nsudo virsh pool-define nfs-pool.xml\nsudo virsh pool-start nfs-pool\nsudo virsh pool-autostart nfs-pool\n\n\n使用 virsh 创建 iSCSI 存储池\n\n\n创建 iSCSI 存储池:\n创建一个 iSCSI 存储池的 XML 配置文件,例如 iscsi-pool.xml\n<pool type='iscsi'>\n <name>iscsi-pool</name>\n <source>\n <host name='iscsi-server'/>\n <device path='/dev/sdX'/>\n </source>\n <target>\n <path>/dev/disk/by-path/</path>\n </target>\n</pool>\n\n\n定义并启动存储池\n使用 virsh 命令定义并启动 iSCSI 存储池:\nsudo virsh pool-define iscsi-pool.xml\nsudo virsh pool-start iscsi-pool\nsudo virsh pool-autostart iscsi-pool\n\n\n配置网络存储池\n\n\n查看存储池信息\nsudo virsh pool-info nfs-pool\nsudo virsh pool-info iscsi-pool\n\n\n查看存储池中的存储卷\nsudo virsh vol-list nfs-pool\nsudo virsh vol-list iscsi-pool\n\n\n创建存储卷\nsudo virsh vol-create-as nfs-pool volume1 10G\nsudo virsh vol-create-as iscsi-pool volume2 20G\n\n\n配置存储卷\n存储卷的概念\n**存储卷Storage Volume是存储池Storage Pool中的一个逻辑单元类似于传统文件系统中的文件。**存储卷为虚拟机提供存储空间,用于存储操作系统、应用程序和数据。每个存储卷可以对应一个磁盘映像文件、逻辑卷或网络存储块。通过存储卷,管理员可以灵活管理和分配存储资源。\n创建和管理磁盘映像文件\n使用 virsh 创建磁盘映像文件\n\n\n创建磁盘映像文件\n使用 virsh 创建一个磁盘映像文件:\nsudo virsh vol-create-as dir-pool mydisk.qcow2 20G --format qcow2\n以上命令将在 dir-pool 存储池中创建一个名为 mydisk.qcow2 的磁盘映像文件,大小为 20GB格式为 qcow2。\n\n\n查看磁盘映像文件信息\n查看创建的磁盘映像文件信息\nsudo virsh vol-info mydisk.qcow2 --pool dir-pool\n\n\n配置磁盘映像文件的大小和格式\n\n\n调整磁盘映像文件大小\n可以使用 qemu-img 工具调整磁盘映像文件的大小:\nqemu-img resize /path/to/mydisk.qcow2 +10G\n以上命令将 mydisk.qcow2 的大小增加 10GB。\n\n\n转换磁盘映像文件格式\n可以使用 qemu-img 工具转换磁盘映像文件的格式:\nqemu-img convert -f qcow2 -O raw /path/to/mydisk.qcow2 /path/to/mydisk.raw\n以上命令将 mydisk.qcow2 转换为 mydisk.raw格式从 qcow2 转换为 raw。\n\n\n创建和管理逻辑卷\n使用 virsh 创建逻辑卷\n\n\n创建逻辑卷\n使用 virsh 创建一个逻辑卷:\nsudo virsh vol-create-as lvm-pool lv_mydisk 20G\n以上命令将在 lvm-pool 存储池中创建一个名为 lv_mydisk 的逻辑卷,大小为 20GB。\n\n\n查看逻辑卷信息\n查看创建的逻辑卷信息\nsudo virsh vol-info lv_mydisk --pool lvm-pool\n\n\n配置逻辑卷的大小和格式\n\n\n调整逻辑卷大小\n可以使用 lvresize 工具调整逻辑卷的大小:\nsudo lvresize -L +10G /dev/vg_kvm/lv_mydisk\n以上命令将 lv_mydisk 的大小增加 10GB。\n\n\n格式化逻辑卷\n在使用逻辑卷之前需要对其进行格式化\nsudo mkfs.ext4 /dev/vg_kvm/lv_mydisk\n\n\n通过以上步骤可以使用 virsh 创建和管理磁盘映像文件和逻辑卷,并灵活配置其大小和格式。这些存储卷为虚拟机提供了可靠和高效的存储解决方案。\n虚拟机的存储配置\n使用 virsh 添加和删除虚拟机磁盘\n添加虚拟机磁盘\n\n\n创建一个新的磁盘映像文件如果需要\nsudo qemu-img create -f qcow2 /var/lib/libvirt/images/mydisk.qcow2 20G\n\n\n使用 virsh 命令编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n在 <devices> 部分中添加以下内容,指定新的磁盘设备:\n<disk type='file' device='disk'>\n <driver name='qemu' type='qcow2'/>\n <source file='/var/lib/libvirt/images/mydisk.qcow2'/>\n <target dev='vdb' bus='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>\n</disk>\n\n\n保存并退出编辑器启动或重启虚拟机以使新磁盘生效\nsudo virsh start <vm_name>\n\n\n删除虚拟机磁盘\n\n\n使用 virsh 命令编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n找到需要删除的 <disk> 节点,并将其删除:\n<disk type='file' device='disk'>\n <driver name='qemu' type='qcow2'/>\n <source file='/var/lib/libvirt/images/mydisk.qcow2'/>\n <target dev='vdb' bus='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>\n</disk>\n\n\n保存并退出编辑器启动或重启虚拟机以应用更改\nsudo virsh start <vm_name>\n\n\nvirsh 配置虚拟机的启动磁盘\n\n\n使用 virsh 命令编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n在 <os> 部分中,找到 <boot dev='...'> 节点并调整顺序。例如,将磁盘设备设为首选启动设备:\n<os>\n <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>\n <boot dev='hd'/>\n <boot dev='cdrom'/>\n</os>\n\n\n保存并退出编辑器启动或重启虚拟机以应用更改\nsudo virsh start <vm_name>\n\n\n配置虚拟机 BIOS 设置\n\n\n使用 virsh 命令编辑虚拟机的 XML 配置文件:\nsudo virsh edit <vm_name>\n\n\n在 <os> 部分中,添加或修改 <bios> 节点。例如,启用 BIOS 引导菜单:\n<os>\n <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>\n <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>\n <nvram>/var/lib/libvirt/qemu/nvram/<vm_name>.fd</nvram>\n <bootmenu enable='yes'/>\n</os>\n\n\n保存并退出编辑器启动或重启虚拟机以应用更改\nsudo virsh start <vm_name>\n\n\n高级存储管理\n快照管理\n创建和管理磁盘快照\n快照是虚拟机在某一时刻的状态包括虚拟机的磁盘和内存状态。通过快照您可以在需要时恢复虚拟机到之前的状态。\n创建磁盘快照\n使用 virsh 创建磁盘快照:\nsudo virsh snapshot-create-as <vm_name> <snapshot_name> --disk-only --atomic\n以上命令创建一个仅包含磁盘状态的快照。\n管理磁盘快照\n使用 virsh 列出所有快照:\nsudo virsh snapshot-list <vm_name>\n恢复快照\n使用 virsh 恢复快照:\nsudo virsh snapshot-revert <vm_name> <snapshot_name>\n扩展存储池容量\n扩展目录存储池\n确保文件系统有足够的空间然后直接添加更多存储卷到目录存储池即可。\n扩展 LVM 存储池\n\n\n添加新的物理卷到卷组\nsudo pvcreate /dev/sdX\nsudo vgextend vg_kvm /dev/sdX\n\n\n更新存储池配置\nsudo virsh pool-refresh lvm-pool\n\n\n扩展网络存储池\n对于 NFS 和 iSCSI直接在网络存储服务器上扩展存储容量然后刷新存储池即可。\n缩减存储池容量\n缩减 LVM 存储池\n\n\n移动逻辑卷中的数据到其他物理卷\nsudo pvmove /dev/sdX\n\n\n移除物理卷并减少卷组大小\nsudo vgreduce vg_kvm /dev/sdX\nsudo pvremove /dev/sdX\n\n\n缩减目录存储池和网络存储池\n一般不直接缩减这些存储池建议清理不需要的存储卷以释放空间。\n磁盘镜像和克隆\n创建磁盘镜像\n创建磁盘镜像\n使用 qemu-img 创建磁盘镜像:\nqemu-img create -f qcow2 /var/lib/libvirt/images/mydisk.qcow2 20G\n转换磁盘镜像格式\n使用 qemu-img 转换磁盘镜像格式:\nqemu-img convert -f qcow2 -O raw /path/to/mydisk.qcow2 /path/to/mydisk.raw\n克隆虚拟机磁盘\n\n\n使用 qemu-img 克隆磁盘映像:\nqemu-img create -f qcow2 -b /var/lib/libvirt/images/source-disk.qcow2 /var/lib/libvirt/images/clone-disk.qcow2\n\n\n使用 virsh 定义新的虚拟机,并指定克隆的磁盘映像:\n创建虚拟机 XML 文件:\n<domain type='kvm'>\n <name>clone-vm</name>\n <memory unit='KiB'>1048576</memory>\n <vcpu placement='static'>1</vcpu>\n <os>\n <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>\n </os>\n <devices>\n <disk type='file' device='disk'>\n <driver name='qemu' type='qcow2'/>\n <source file='/var/lib/libvirt/images/clone-disk.qcow2'/>\n <target dev='vda' bus='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>\n </disk>\n </devices>\n</domain>\n\n\n使用 virsh 定义并启动新的虚拟机:\nsudo virsh define /path/to/clone-vm.xml\nsudo virsh start clone-vm\n\n"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/6.-KVM-性能优化":{"title":"6. KVM 性能优化","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"性能优化概述\n为什么需要性能优化\n性能优化在虚拟化环境中至关重要原因如下\n\n\n提高资源利用率 通过性能优化可以更有效地利用计算资源CPU、内存、存储和网络从而支持更多的虚拟机运行在同一硬件上。\n\n\n增强用户体验 优化虚拟机性能可以降低延迟、提高响应速度,为最终用户提供更好的体验。\n\n\n降低运营成本 更高的资源利用率意味着可以在相同的硬件投资上运行更多的虚拟机,从而降低数据中心的运营成本。\n\n\n延长硬件寿命 通过优化,避免资源的过度使用和硬件的过度磨损,从而延长硬件的使用寿命。\n\n\n提高系统稳定性和可靠性 优化虚拟化环境中的性能可以减少瓶颈和故障,从而提高系统的稳定性和可靠性。\n\n\n性能优化的基本原则\n\n监控和分析持续监控虚拟机和宿主机的性能指标分析性能瓶颈。使用工具如 top、htop、vmstat、iostat 和 sar。\n资源隔离和分配合理配置虚拟机的资源分配使用 CPU 和内存配额、限制和保留来避免资源争用。\n调整虚拟机配置根据负载情况调整虚拟机的 CPU、内存、存储和网络配置确保满足应用需求。\n优化存储性能使用合适的存储格式如 qcow2 和 raw、启用缓存和 I/O 调度策略,优化磁盘 I/O 性能。\n优化网络性能使用 Virtio 网络驱动、启用多队列支持、调整网络缓冲区大小和使用网络分段来提高网络性能。\n保持系统和软件更新定期更新操作系统和虚拟化软件获取最新的性能优化和安全补丁。\n\n性能优化的常见挑战\n\n资源争用当多个虚拟机共享相同的物理资源时可能会导致资源争用影响整体性能。需要合理配置资源隔离和分配策略。\nI/O 瓶颈:磁盘 I/O 和网络 I/O 是虚拟化环境中常见的瓶颈。需要优化存储和网络配置以提高 I/O 性能。\nCPU 和内存过载:虚拟机可能会导致宿主机的 CPU 和内存过载,从而影响系统性能。需要监控和调整虚拟机的 CPU 和内存使用。\n网络延迟和吞吐量虚拟化环境中的网络性能可能受到延迟和吞吐量的限制需要优化网络配置和使用高效的网络驱动。\n存储性能下降存储设备性能下降可能会影响虚拟机的响应时间。需要选择合适的存储设备和优化存储配置。\n软件和硬件兼容性某些软件和硬件可能无法充分利用虚拟化环境中的优化功能需要确保兼容性和最佳实践。\n\nCPU 性能优化\n在 KVMKernel-based Virtual Machine虚拟化环境中CPU 性能优化对于提升虚拟机VM的运行效率和整体系统性能至关重要。本文将深入探讨 CPU 性能优化的几个关键方面,包括 CPU 分配和超线程、CPU 亲和性设置、以及优化 CPU 调度策略。\nCPU 分配和超线程\n分配虚拟 CPU (vCPU)\n虚拟机的 CPU 分配直接影响其性能。为虚拟机分配适当数量的 vCPU 可以确保其在执行任务时拥有足够的计算资源。以下是几个关键点:\n\n评估工作负载根据虚拟机所需运行的应用程序或服务的特定需求来分配 vCPU 数量。一般来说,轻量级应用程序需要较少的 vCPU而计算密集型应用程序则需要更多的 vCPU。\n避免过度分配避免为虚拟机分配过多的 vCPU这样可能会导致宿主机资源紧张影响整体性能。\n动态调整利用 KVM 的热插拔功能,可以在虚拟机运行时动态调整 vCPU 数量,以适应变化的工作负载。\n\n启用和配置超线程\n超线程技术Hyper-Threading允许每个物理 CPU 核心同时处理多个线程,从而提高 CPU 的并行处理能力。启用和配置超线程可以显著提升虚拟机的性能:\n\n启用超线程在 BIOS 或 UEFI 中启用超线程功能,以便操作系统和 KVM 可以利用这一技术。\n合理配置在分配 vCPU 时,考虑超线程的影响。例如,如果物理 CPU 核心启用了超线程,理论上每个核心可以运行两个 vCPU。根据实际性能测试结果调整 vCPU 分配策略。\n\nCPU 亲和性设置\n配置 CPU 亲和性\nCPU 亲和性CPU Affinity指将特定的 vCPU 绑定到物理 CPU 核心上,从而减少 CPU 切换带来的性能开销,提高缓存命中率。配置 CPU 亲和性的方法包括:\n\n手动配置在创建虚拟机时通过指定 vCPU 与物理 CPU 核心的绑定关系来配置 CPU 亲和性。\n自动化工具使用自动化工具如 libvirt进行配置简化管理过程。\n\n使用 virsh 设置 vCPU 亲和性\nvirsh 是一个用于管理 KVM 虚拟机的命令行工具,通过它可以方便地设置和调整 vCPU 亲和性:\n\n查看当前配置使用 virsh vcpuinfo <VM名> 查看虚拟机当前的 vCPU 配置和绑定关系。\n设置亲和性使用 virsh vcpupin <VM名> <vCPU编号> <物理CPU编号> 命令,将指定的 vCPU 绑定到物理 CPU 核心。例如virsh vcpupin myvm 0 2 将虚拟机 myvm 的第一个 vCPU 绑定到物理 CPU 的第二个核心。\n保存配置确保更改的配置在虚拟机重启后仍然有效可以将配置写入虚拟机的 XML 配置文件中。\n\n优化 CPU 调度策略\n使用 Cgroups 控制 CPU 使用\n控制组cgroups是一种 Linux 内核功能,允许用户对进程进行资源限制和监控。利用 cgroups 可以更精细地控制虚拟机的 CPU 资源使用:\n\n创建 cgroup使用 cgcreate 命令创建一个新的 cgroup。例如cgcreate -g cpu:/mygroup 创建一个名为 mygroup 的 cgroup。\n设置 CPU 限额:使用 cgset 命令设置 cgroup 的 CPU 使用限制。例如cgset -r cpu.shares=512 mygroup 将 mygroup 的 CPU 使用份额设置为 512。\n将虚拟机进程加入 cgroup通过 cgclassify 或 echo <PID> > /sys/fs/cgroup/cpu/mygroup/tasks 命令将虚拟机进程加入 cgroup 中,以应用资源限制。\n\n调整调度策略\nKVM 虚拟化环境中,合理的 CPU 调度策略可以显著提升虚拟机的性能和响应速度。常见的调度策略包括:\n\n完全公平调度器CFSLinux 默认的调度策略,适用于大多数场景。通过调整 CFS 参数,可以优化虚拟机的 CPU 性能。\n实时调度器RT适用于对延迟敏感的应用如音视频处理或实时计算任务。可以通过设置实时优先级和资源预留来优化性能。\n自动化调度工具使用如 libvirt 的调度策略配置功能,自动优化虚拟机的调度策略。\n\n通过以上方法和工具可以系统地优化 KVM 环境下虚拟机的 CPU 性能,从而提高整体系统的效率和稳定性。在实际应用中,应根据具体需求和工作负载特征,选择合适的优化策略和参数设置,以达到最佳性能表现。\n内存性能优化\n内存性能是虚拟化环境中影响虚拟机VM运行效率的关键因素之一。KVMKernel-based Virtual Machine提供了多种内存优化技术本文将详细探讨内存分配和大页支持、内存过量使用和气球驱动、以及 NUMA 配置优化等方面的内容。\n内存分配和大页支持\n分配合适的内存大小\n为虚拟机分配合适的内存大小是确保其性能的基本步骤\n\n评估工作负载需求根据虚拟机上运行的应用程序和服务的需求确定所需的内存大小。轻量级应用程序需要较少的内存而数据密集型或计算密集型应用程序则需要更多的内存。\n避免过度分配过度分配内存会导致宿主机的内存资源紧张影响整体系统性能。因此需要合理分配内存确保宿主机和所有虚拟机的内存需求都能得到满足。\n动态调整内存利用 KVM 的热插拔内存功能,可以在虚拟机运行时动态调整内存大小,以应对变化的工作负载需求。\n\n启用和配置大页HugePages\n大页HugePages是指较大的内存页用于减少内存分页和 TLBTranslation Lookaside Buffer失效的开销从而提高内存访问效率。启用和配置大页可以显著提升虚拟机的性能\n\n启用大页支持在宿主机上启用大页支持可以通过修改内核参数或使用命令来实现。例如可以在 /etc/sysctl.conf 文件中添加 vm.nr_hugepages=512然后运行 sysctl -p 应用配置。\n配置大页使用在创建或配置虚拟机时指定其使用大页内存。例如通过 libvirt 的 XML 配置文件,可以在 <memoryBacking> 节点中添加 <hugepages/> 元素。\n监控大页使用使用 cat /proc/meminfo | grep HugePages 查看当前系统的大页使用情况,确保配置的生效和合理性。\n\n内存过量使用和气球驱动\n启用内存过量使用\n内存过量使用Memory Overcommitment允许为虚拟机分配的内存总量超过宿主机的物理内存量从而提高资源利用率\n\n评估风险内存过量使用虽然可以提高资源利用率但也带来了一定的风险如宿主机内存不足导致的性能下降或崩溃。因此需要谨慎评估和控制过量使用的程度。\n启用内存过量使用在 KVM 环境中,可以通过调整宿主机的内存管理策略和参数来实现内存过量使用。例如,调整 vm.overcommit_memory 参数为 1表示允许过量分配内存。\n\n使用气球驱动动态调整内存\n气球驱动Ballooning是一种动态调整虚拟机内存分配的技术通过调整虚通过以上常见性能问题及其解决方法的介绍以及日志分析方法的讲解可以帮助管理员有效地排查和解决 KVM 虚拟化环境中的性能问题,确保虚拟机的稳定运行和高效性能。在实际应用中,应结合具体问题和环境特点,灵活应用这些故障排查方法。拟机的内存使用,优化宿主机的内存资源分配:\n\n安装气球驱动确保虚拟机中安装了气球驱动通常 KVM 虚拟机中默认包含该驱动。如果没有,可以通过安装相应的虚拟化工具包来获取。\n启用气球驱动在虚拟机的配置文件中启用气球驱动例如在 libvirt 的 XML 配置文件中,添加 <memballoon model='virtio'/> 元素。\n动态调整内存使用 virsh 命令行工具,通过 virsh setmem <VM名> <内存大小> 命令动态调整虚拟机的内存大小。例如virsh setmem myvm 2G 将虚拟机 myvm 的内存调整为 2GB。\n\nNUMA 配置优化\n什么是 NUMA\n非一致性内存访问NUMANon-Uniform Memory Access是一种内存架构在多处理器系统中每个处理器拥有自己的本地内存访问本地内存的速度比访问其他处理器的内存更快。合理配置 NUMA 可以显著提升多处理器系统中虚拟机的性能。\n配置虚拟机的 NUMA 节点\n在 KVM 虚拟化环境中,可以配置虚拟机的 NUMA 节点,以优化内存访问性能:\n\n\n查看宿主机的 NUMA 配置:使用 numactl --hardware 或 lscpu 命令查看宿主机的 NUMA 节点和 CPU、内存分布情况。\n\n\n配置虚拟机的 NUMA 节点:在 libvirt 的 XML 配置文件中,指定虚拟机的 NUMA 节点。例如:\n \n \n \n \n \n \n \n \n\n\n\n \n \n \n \n \n \n \n 0-1\n \n ```\n以上配置将虚拟机的内存和 vCPU 绑定到宿主机的 0 和 1 号 NUMA 节点,确保虚拟机内存访问的性能。\n\n测试和调整在实际应用中通过性能测试和监控工具评估 NUMA 配置的效果,根据需要进行调整和优化。\n\n存储性能优化\n在 KVMKernel-based Virtual Machine虚拟化环境中磁盘 I/O 性能是影响虚拟机VM整体性能的关键因素之一。本文将详细探讨使用 Virtio 驱动提升性能、优化磁盘 I/O 调度策略、以及使用缓存策略等方面的内容。\n使用 Virtio 驱动提升性能\nVirtio 驱动的优势\nVirtio 是 KVM 环境中用于提高虚拟机 I/O 性能的一组标准驱动程序。Virtio 驱动通过简化虚拟化 I/O 路径和减少开销,提供了显著的性能提升:\n\n高效的 I/O 处理Virtio 驱动直接与 KVM hypervisor 通信,减少了传统设备模拟带来的开销,提高了 I/O 操作的效率。\n更低的延迟通过简化 I/O 路径和优化数据传输Virtio 驱动显著降低了 I/O 操作的延迟,提升了虚拟机的响应速度。\n广泛的兼容性Virtio 驱动被广泛支持,适用于大多数 Linux 发行版和现代 Windows 操作系统,确保了虚拟机的兼容性和稳定性。\n\n安装和配置 Virtio 驱动\n安装和配置 Virtio 驱动以充分利用其性能优势:\n\n\nLinux 虚拟机:在大多数现代 Linux 发行版中Virtio 驱动通常已经内置。如果需要手动安装,可以使用包管理器安装相应的 Virtio 驱动包。\n配置虚拟机使用 Virtio 驱动,在 libvirt 的 XML 配置文件中,将磁盘设备类型设置为 virtio\n<disk type='file' device='disk'>\n <driver name='qemu' type='qcow2'/>\n <source file='/var/lib/libvirt/images/myvm.qcow2'/>\n <target dev='vda' bus='virtio'/>\n</disk>\n\n\nWindows 虚拟机:\n\n下载并安装 Virtio 驱动程序,通常可以从 Red Hat 提供的 Virtio 驱动包中获取。\n在虚拟机创建过程中通过虚拟光驱加载 Virtio 驱动 ISO 文件,并在 Windows 安装过程中手动加载驱动程序。\n配置完成后在设备管理器中确认 Virtio 驱动已正确安装并应用于相应的设备。\n\n\n\n磁盘 I/O 调度策略\n选择合适的 I/O 调度器\nI/O 调度器负责管理磁盘 I/O 请求的调度,选择合适的 I/O 调度器可以显著提升磁盘 I/O 性能。常见的 I/O 调度器包括:\n\nCFQCompletely Fair Queuing适用于大多数通用场景通过公平分配 I/O 带宽,提供较好的性能和响应时间。\nDeadline适用于对延迟敏感的应用通过设置请求的截止时间确保 I/O 请求在规定时间内完成,减少延迟。\nNOOP适用于 SSD 等固态存储设备,采用简单的 FIFO 队列,减少 I/O 调度开销。\n\n在宿主机上可以通过修改 /sys/block/<设备名>/queue/scheduler 文件来设置 I/O 调度器,例如:\necho deadline > /sys/block/sda/queue/scheduler\n使用 ionice 控制 I/O 优先级\nionice 命令可以设置进程的 I/O 优先级,从而控制其 I/O 操作的优先级顺序:\n\n\n命令语法\nionice -c <class> -n <priority> <command>\n\n<class>I/O 优先级类别0实时、1最佳努力、2空闲。\n<priority>:优先级级别,范围为 0 到 7数值越小优先级越高。\n\n\n\n示例\nionice -c 1 -n 3 dd if=/dev/zero of=/var/lib/libvirt/images/test.img bs=1M count=1024\n以上命令将 dd 命令的 I/O 优先级设置为最佳努力类别,优先级为 3。\n\n\n使用缓存策略\n配置缓存模式\nKVM 虚拟机的磁盘设备支持多种缓存模式,不同缓存模式对性能有不同影响:\n\nnone直接 I/O 模式,虚拟机的 I/O 请求直接传递到宿主机,不经过宿主机的页缓存。适用于需要确保数据一致性的场景,如数据库应用。\nwriteback写回缓存模式I/O 请求先写入缓存,再异步写入磁盘。提供较好的写入性能,但在宿主机崩溃时可能导致数据丢失。\nwritethrough直写缓存模式写请求直接写入磁盘同时更新缓存。确保数据的一致性但写入性能相对较低。\n\n在 libvirt 的 XML 配置文件中,可以通过 <driver> 元素配置缓存模式,例如:\n<disk type='file' device='disk'>\n <driver name='qemu' type='qcow2' cache='none'/>\n <source file='/var/lib/libvirt/images/myvm.qcow2'/>\n <target dev='vda' bus='virtio'/>\n</disk>\n使用 Directsync 和 None 模式\ndirectsync 和 none 模式在确保数据一致性的同时提供不同的性能优势:\n\ndirectsync同步 I/O 模式I/O 请求直接传递到宿主机,并在请求完成后返回,确保数据一致性。适用于需要严格数据一致性的应用。\nnone直接 I/O 模式,无缓存。适用于需要高性能的读写操作,且能够容忍一定程度数据丢失的场景。\n\n通过合理选择和配置缓存模式可以在性能和数据一致性之间取得平衡优化虚拟机的磁盘 I/O 性能。\n综上所述通过使用 Virtio 驱动、优化 I/O 调度策略和缓存策略,可以显著提升 KVM 虚拟化环境中虚拟机的磁盘 I/O 性能。在实际应用中,应根据具体需求和工作负载特征,选择合适的优化策略和参数设置,以达到最佳性能表现。\n网络性能优化\n使用 Virtio 网卡\nVirtio 网卡的优势\nVirtio 网卡是 KVM 虚拟化环境中用于提高网络性能的一种标准化虚拟网络接口。使用 Virtio 网卡具有以下优势:\n\n高效的 I/O 处理Virtio 网卡通过简化 I/O 路径,减少传统网络设备模拟带来的开销,提高网络吞吐量和数据传输效率。\n低延迟Virtio 网卡通过优化数据传输路径,显著降低了网络延迟,提高了虚拟机的网络响应速度。\n广泛的兼容性Virtio 网卡被广泛支持,适用于大多数 Linux 发行版和现代 Windows 操作系统,确保虚拟机的兼容性和稳定性。\n\n配置 Virtio 网卡\n配置 Virtio 网卡以充分利用其性能优势:\n\n\n在 Linux 虚拟机中配置 Virtio 网卡:\n确保虚拟机的网络接口类型设置为 virtio在 libvirt 的 XML 配置文件中,可以这样配置:\n<interface type='network'>\n <mac address='52:54:00:6b:3c:58'/>\n <source network='default'/>\n <model type='virtio'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n</interface>\n在虚拟机操作系统中确认 Virtio 驱动已正确加载,通常在现代 Linux 发行版中默认支持。\n\n\n在 Windows 虚拟机中配置 Virtio 网卡:\n\n下载并安装 Virtio 网络驱动程序,通常可以从 Red Hat 提供的 Virtio 驱动包中获取。\n在虚拟机创建过程中通过虚拟光驱加载 Virtio 驱动 ISO 文件,并在 Windows 设备管理器中手动安装驱动程序。\n确认 Virtio 网卡在设备管理器中正确识别并工作。\n\n\n\n网络带宽限制和优先级\n配置网络带宽限制\n通过配置网络带宽限制可以有效管理虚拟机的网络流量防止个别虚拟机占用过多带宽从而影响其他虚拟机的网络性能\n使用 libvirt 的 XML 配置文件,可以为虚拟机的网络接口设置带宽限制。例如:\n<interface type='network'>\n <mac address='52:54:00:6b:3c:58'/>\n <source network='default'/>\n <model type='virtio'/>\n <bandwidth>\n <inbound average='1000' peak='1200' burst='256'/>\n <outbound average='1000' peak='1200' burst='256'/>\n </bandwidth>\n</interface>\n以上配置将虚拟机的入站和出站流量限制为平均 1000kbps峰值 1200kbps突发流量 256kb。\n使用 tc 命令设置优先级\ntcTraffic Control命令是 Linux 中用于网络流量控制的强大工具,可以设置流量优先级,确保关键应用的网络性能:\n\n\n安装 tc 工具:大多数 Linux 发行版默认包含 tc 工具,如果没有安装,可以通过包管理器安装(如 apt-get install iproute2。\n\n\n配置流量优先级\n\n\n创建根队列\n \n\n\n\n\ntc qdisc add dev eth0 root handle 1: htb default 12\n ```\n\n \n\n\n\n创建类并分配带宽\n \n\n\ntc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit\n tc class add dev eth0 parent 1:1 classid 1:11 htb rate 30mbit\n\ntc class add dev eth0 parent 1:1 classid 1:12 htb rate 70mbit\n ```\n\n\n\n配置流量过滤规则\n \n\n\ntc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 192.168.1.100/32 flowid 1:11\n tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.1.100/32 flowid 1:11\n\n\n### 调整网络缓冲区和队列\n\n#### 优化网络缓冲区大小\n\n优化网络缓冲区大小可以提高网络吞吐量减少丢包率从而提升网络性能\n\n1. **调整接收RX和发送TX缓冲区**:使用 `ethtool`命令查看和设置网卡的缓冲区大小。例如:\n\n ```shell\n ethtool -g eth0\n ethtool -G eth0 rx 4096 tx 4096\n\n以上命令将 eth0 网卡的接收和发送缓冲区大小设置为 4096。\n\n\n调整内核参数修改 /etc/sysctl.conf 文件,增加以下参数:\nnet.core.rmem_max = 16777216\nnet.core.wmem_max = 16777216\nnet.core.rmem_default = 8388608\nnet.core.wmem_default = 8388608\n应用配置\nsysctl -p\n\n\n配置多队列支持\n启用和配置多队列Multiqueue支持可以提高网络 I/O 并行处理能力,提升网络性能:\n\n\n启用多队列\n在 libvirt 的 XML 配置文件中,为 Virtio 网卡启用多队列支持:\n<interface type='network'>\n <mac address='52:54:00:6b:3c:58'/>\n <source network='default'/>\n <model type='virtio'/>\n <driver name='vhost' queues='4'/>\n</interface>\n以上配置将 Virtio 网卡的队列数设置为 4。\n\n\n调整虚拟机内核参数\n修改虚拟机操作系统内核参数以支持多队列。例如在 Linux 虚拟机中,可以使用\nethtool\n命令启用多队列\nethtool -L eth0 combined 4\n以上命令将 eth0 网卡的队列数设置为 4。\n\n\n虚拟机快照和备份的性能优化\n在 KVMKernel-based Virtual Machine虚拟化环境中快照和备份功能是保障数据安全和系统可靠性的重要手段。然而这些操作也会对系统性能产生影响。本文将详细探讨快照性能影响及其优化策略、以及优化备份策略以减少对系统性能的影响。\n快照性能影响\n快照的创建和管理\n快照是虚拟机在某一时刻的状态包括内存、磁盘和设备状态的完整备份。快照可以用于快速恢复到某一特定状态但频繁的快照操作会影响系统性能\n\n\n快照的创建\n快照创建过程中KVM 会冻结虚拟机的运行状态并复制当前的内存和磁盘数据。这会占用大量 I/O 资源,导致虚拟机短暂的性能下降。使用 virsh 命令创建快照,例如:\nvirsh snapshot-create-as --domain <VM名> --name <快照名> --description "<描述>" --disk-only --atomic\n\n\n快照的管理\n定期检查并管理快照删除不再需要的快照以释放存储空间减少性能影响。使用 virsh 命令查看和删除快照,例如:\nvirsh snapshot-list <VM名>\nvirsh snapshot-delete <VM名> <快照名>\n\n\n减少快照对性能的影响\n为了减少快照对虚拟机性能的影响可以采取以下优化策略\n\n\n优化快照存储位置\n将快照存储在性能较高的存储设备上例如 SSD减少 I/O 瓶颈对虚拟机性能的影响。\n\n\n限制快照数量\n避免同时创建过多的快照定期清理不需要的快照保持系统存储的简洁性和高效性。\n\n\n使用外部快照\n使用外部快照External Snapshot将快照数据与原始磁盘数据分开存储减少对原始磁盘 I/O 的影响。例如:\nvirsh snapshot-create-as --domain <VM名> --name <快照名> --diskspec <disk>,snapshot=external --disk-only\n\n\n备份策略\n使用增量备份减少影响\n增量备份是指仅备份自上次备份以来发生变化的数据相较于全量备份增量备份占用的存储空间更少备份速度更快性能影响更低\n\n\n配置增量备份\n使用增量备份工具如 rsync、Bacula、Duplicity配置增量备份任务定期备份虚拟机的数据。例如使用 rsync 进行增量备份:\nrsync -av --progress --delete /path/to/source /path/to/destination\n\n\n利用 KVM 内置增量备份功能:\n利用 KVM 和 QEMU 的增量备份功能,使用 QEMU 提供的块设备接口(如 qemu-img进行增量备份。例如\nqemu-img create -f qcow2 -b <base-image> <incremental-image>\n\n\n配置备份窗口和策略\n配置合理的备份窗口和策略减少备份操作对系统性能的影响\n\n\n选择备份窗口\n选择系统负载较低的时间段进行备份操作例如夜间或周末避免影响业务高峰期的性能。\n使用任务调度工具如 cron配置备份任务的执行时间。例如配置每日凌晨 3 点进行备份:\n0 3 * * * /path/to/backup-script.sh\n\n\n配置备份策略\n制定合理的备份策略包括全量备份和增量备份的频率、保留周期等。例如每周进行一次全量备份每日进行增量备份保留最近一个月的备份数据。\n使用备份管理工具如 Bacula、Amanda配置和管理备份策略实现自动化和集中管理。\n\n\n性能问题的故障排查\n在 KVMKernel-based Virtual Machine虚拟化环境中性能问题的故障排查是保障虚拟机VM稳定运行的重要工作。本文将详细探讨常见性能问题及其解决方法以及如何通过日志分析进行性能排查。\n常见性能问题及解决方法\n虚拟机运行缓慢\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n问题原因解决方法CPU 资源不足虚拟机分配的 vCPU 数量不足,或者宿主机的 CPU 资源紧张增加虚拟机的 vCPU 数量。检查宿主机的 CPU 负载,优化其他虚拟机的 CPU 使用,必要时迁移部分虚拟机到其他宿主机。内存资源不足虚拟机分配的内存不足,或者宿主机的内存资源紧张增加虚拟机的内存。检查宿主机的内存使用情况,优化其他虚拟机的内存使用,必要时使用内存气球驱动动态调整内存分配。磁盘 I/O 瓶颈虚拟机磁盘 I/O 负载过高,导致 I/O 操作延迟优化虚拟机的磁盘 I/O 调度策略,使用合适的 I/O 调度器。将虚拟机的磁盘文件迁移到性能更好的存储设备(如 SSD。启用并配置 Virtio 磁盘驱动,提高 I/O 性能。网络 I/O 瓶颈虚拟机网络负载过高,导致网络延迟和吞吐量下降配置 Virtio 网卡,提高网络 I/O 性能。优化网络带宽限制和优先级配置,确保关键应用的网络带宽。检查宿主机和虚拟机的网络配置,确保网络连接正常。\n网络性能不佳\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n问题原因解决方法网络配置问题虚拟机或宿主机的网络配置错误或不优化检查虚拟机和宿主机的网络配置确保网络接口和路由配置正确。优化虚拟机的网络缓冲区和队列配置提高网络 I/O 性能。网络带宽瓶颈虚拟机网络流量过大,占用过多带宽配置网络带宽限制,确保网络资源合理分配。使用 tc 命令配置网络流量优先级,确保关键应用的网络性能。网络延迟问题虚拟机或宿主机的网络延迟过高优化虚拟机的网络路由配置,减少中间跳数和延迟。检查宿主机的网络硬件,确保网卡和交换机性能正常。\n性能日志分析\n日志分析是故障排查的重要手段通过查看和分析 KVM 和系统日志,可以快速定位和解决性能问题。\n查看和分析 KVM 日志\nKVM 和 libvirt 生成的日志文件可以提供虚拟机运行的详细信息,帮助排查性能问题:\n\n\n查看 libvirt 日志libvirt 日志通常位于 /var/log/libvirt 目录下,可以通过 virsh 命令查看特定虚拟机的日志:\nvirsh log <VM名>\n直接查看日志文件\ntail -f /var/log/libvirt/qemu/<VM名>.log\n\n\n分析日志内容\n\n检查日志中是否有错误信息、警告信息或性能相关的提示。\n根据日志中的时间戳和事件定位性能问题发生的时间段和可能的原因。\n\n\n\n使用系统日志进行排查\n系统日志如 syslog、dmesg记录了宿主机的各种事件包括硬件信息、系统错误和性能警告通过分析系统日志可以排查性能问题\n\n\n查看系统日志使用 dmesg 命令查看内核日志:\ndmesg | less\n查看 syslog 日志,通常位于 /var/log 目录下:\ntail -f /var/log/syslog\n\n\n分析日志内容\n\n检查是否有与虚拟机或宿主机相关的错误信息或警告信息。\n根据日志信息确定是否有硬件故障、资源瓶颈或其他性能问题。\n\n\n"},"Technology/OperatingSystem/Virtualization/2.KVM虚拟化/7.-KVM-系统监控":{"title":"7. KVM 系统监控","links":[],"tags":["技术/操作系统","虚拟化/KVM"],"content":"监控概述\n在 KVMKernel-based Virtual Machine虚拟化环境中监控是确保系统稳定性、性能优化和故障排查的重要手段。本文将探讨监控的必要性、基本原则以及常用的监控工具。\n为什么需要监控\n\n确保系统稳定性\n\n通过监控系统资源使用情况和性能指标可以及时发现潜在的问题防止系统崩溃或服务中断。\n实时监控有助于预防性维护提前识别并解决硬件或软件故障。\n\n\n优化性能\n\n监控数据提供了关于资源使用的详细信息帮助管理员优化虚拟机配置和资源分配以提高整体系统性能。\n通过性能趋势分析可以发现并消除系统瓶颈提升用户体验。\n\n\n故障排查\n\n监控日志和性能指标记录了系统运行的详细信息帮助管理员快速定位和解决故障。\n实时报警功能可以在问题发生时立即通知管理员减少故障排除时间和系统停机时间。\n\n\n容量规划\n\n监控资源使用趋势和增长情况有助于进行合理的容量规划确保系统在未来增长中仍能稳定运行。\n提前规划资源扩展避免资源不足导致的性能下降。\n\n\n\n监控的基本原则\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n原则详细内容全面覆盖监控系统应覆盖所有关键组件包括 CPU、内存、磁盘、网络等资源以及虚拟机和宿主机的状态。 监控范围还应包括应用层面的性能指标,以全面掌握系统运行状况。实时性监控系统应提供实时的数据采集和报警功能,确保在问题发生时能够立即响应。 实时监控有助于快速发现和解决突发问题,减少对业务的影响。历史记录监控系统应保存历史数据,便于进行趋势分析和性能基线建立。 历史记录有助于识别长期趋势和周期性问题,进行有效的容量规划和性能优化。报警机制监控系统应具备灵活的报警机制,根据预定义的阈值触发报警,通知管理员采取措施。 报警应支持多种通知方式(如邮件、短信、即时通讯工具),确保及时传达信息。可视化展示监控数据应通过可视化的方式展示,便于管理员直观了解系统状态和性能指标。 可视化工具(如仪表盘、图表)有助于快速识别问题和进行数据分析。\n常用的监控工具\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具概述特点PrometheusPrometheus 是一款开源的系统监控和报警工具特别适用于云原生和容器化环境。高效的数据采集和存储强大的查询语言PromQL灵活的报警机制丰富的可视化支持如 Grafana。GrafanaGrafana 是一款开源的可视化和分析平台,用于展示和监控系统数据。支持多种数据源(如 Prometheus、InfluxDB、Elasticsearch强大的仪表盘和图表功能灵活的报警和通知机制。ZabbixZabbix 是一款开源的企业级监控解决方案适用于大规模分布式系统的监控。全面的监控功能灵活的报警机制强大的数据可视化和报告生成能力广泛的社区支持。NagiosNagios 是一款经典的开源监控工具,广泛应用于 IT 基础设施的监控。灵活的插件机制支持多种监控对象可靠的报警和通知功能丰富的社区插件。CollectdCollectd 是一款轻量级的系统统计收集工具,用于收集和传输系统性能数据。高效的数据采集,多种插件支持,灵活的数据输出选项(如写入 InfluxDB、Graphite。TelegrafTelegraf 是一个开源的服务器代理,用于收集和发送指标数据,作为 TICKTelegraf, InfluxDB, Chronograf, Kapacitor堆栈的一部分。插件驱动的架构支持多种输入和输出插件易于集成和扩展。\n使用内置工具监控\nKVMKernel-based Virtual Machine环境中内置的监控工具如 virsh 和 virt-top 提供了便捷的虚拟机监控方法,帮助管理员实时了解虚拟机的运行状态和资源使用情况。本文将详细介绍如何使用 virsh 和 virt-top 进行监控。\n使用 virsh 进行监控\nvirsh 是 libvirt 提供的命令行工具,用于管理和监控 KVM 虚拟机。通过 virsh 命令,可以查看虚拟机的信息和资源使用情况。\n查看虚拟机信息\n使用 virsh 命令可以查看虚拟机的基本信息,包括状态、配置和资源分配情况:\n\n\n列出所有虚拟机\nvirsh list --all\n输出示例\n Id Name State\n----------------------------------------------------\n 1 myvm running\n - testvm shut off\n\n\n\n查看虚拟机详细信息\nvirsh dominfo <VM名>\n输出示例\nId: 1\nName: myvm\nUUID: 2d4c3b1c-467d-4b88-8f0d-5b63a3c6e29d\nOS Type: hvm\nState: running\nCPU(s): 4\nMax memory: 2097152 KiB\nUsed memory: 2097152 KiB\nPersistent: yes\nAutostart: disable\nManaged save: no\n\n\n监控资源使用情况\n通过 virsh 命令,可以监控虚拟机的实时资源使用情况,包括 CPU 和内存使用情况:\n\n\n查看虚拟机 CPU 和内存使用情况:\nvirsh domstats <VM名>\n输出示例\nDomain: 'myvm'\n state.state=1\n state.reason=1\n cpu.time=1234567890\n cpu.user=234567890\n cpu.system=34567890\n balloon.current=2097152\n balloon.maximum=2097152\n balloon.swap_in=0\n balloon.swap_out=0\n balloon.major_fault=0\n balloon.minor_fault=12345\n balloon.usable=1987654\n ...\n\n\n查看所有虚拟机的资源使用情况\nvirsh list --all --name | xargs -I{} virsh domstats {}\n该命令将列出所有虚拟机的资源使用统计信息便于管理员进行整体监控。\n\n\n使用 virt-top 监控\nvirt-top 是一个类似于 top 的命令行工具,用于实时监控 KVM 虚拟机的性能和资源使用情况。通过 virt-top管理员可以直观地查看每个虚拟机的 CPU、内存、磁盘和网络使用情况。\n安装和配置 virt-top\n\n安装 virt-top\n\n ## 在基于 Debian 的系统(如 Ubuntu上\n sudo apt-get install virt-top\n \n ## 在基于 RHEL 的系统(如 CentOS上\n sudo yum install virt-top\n\n\n配置 virt-top\n安装完成后运行 virt-top 命令启动监控:\nsudo virt-top\n\n\n使用 virt-top 查看虚拟机性能\nvirt-top 提供了一个交互式界面,显示每个虚拟机的详细性能数据:\n\n\n启动 virt-top\nsudo virt-top\n输出示例\nvirt-top 0.5.12 x86_64 libvirt 6.0.0\n2 domains, 1 active, 1 running, 0 sleeping, 0 paused, 0 inactive D:0 O:0 X:0\nCPU: 2.0% Mem: 2097152 kB (64.0%) RSS: 512 MB\nDomains: 2 ID S RDRQ RDRS WRRQ WRRS RXBY TXBY %CPU %MEM\n 1 myvm 1 R 0 0 0 0 0 0 2.0 64.0\n\n\n查看具体虚拟机的详细信息\n\n在 virt-top 界面中,使用箭头键选择具体的虚拟机,然后按回车键查看详细信息。\n可以查看的性能指标包括CPU 使用率、内存使用率、磁盘读写、网络接收和发送等。\n\n\n\n自定义视图和排序\n\n按 f 键选择要显示的字段,可以选择 CPU、内存、磁盘、网络等不同的监控指标。\n按 s 键选择排序方式,可以按 CPU 使用率、内存使用率、磁盘 I/O 等进行排序,方便定位高负载的虚拟机。\n\n\n\n通过使用 virsh 和 virt-top 工具,管理员可以方便地监控 KVM 虚拟化环境中虚拟机的运行状态和资源使用情况。这些工具提供了丰富的命令和参数,可以满足大部分日常监控和性能分析的需求。在实际应用中,应根据具体需求和环境特点,选择合适的监控工具和方法,以确保虚拟机和宿主机的稳定运行和高效性能。\n使用系统监控工具\n除了专门的虚拟化监控工具系统自带的监控工具如 top、htop、iotop 和 iftop 也可以用来监控 KVM 虚拟化环境中的性能。本文将详细介绍这些工具的使用方法,包括查看系统整体性能、监控虚拟机的资源占用、监控磁盘 I/O 性能以及监控网络流量。\n使用 top 和 htop\n查看系统整体性能\ntop 和 htop 是常用的系统性能监控工具,提供了关于系统资源使用的实时信息:\n\n\n使用 top 查看系统性能:启动 top\ntop\n输出示例\ntop - 14:55:30 up 10 days, 2:48, 3 users, load average: 0.00, 0.01, 0.05\nTasks: 125 total, 1 running, 124 sleeping, 0 stopped, 0 zombie\n%Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st\nKiB Mem : 2048.0 total, 104.0 free, 512.0 used, 1432.0 buff/cache\nKiB Swap: 1024.0 total, 1024.0 free, 0.0 used. 1480.0 avail Mem \n \n PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND\n 1234 root 20 0 162180 7644 4388 S 0.3 0.4 0:00.03 qemu-kvm\n ...\n该命令显示系统的 CPU、内存使用情况以及每个进程的资源占用。\n\n\n使用 htop 查看系统性能:启动 htop如果未安装可以通过 sudo apt-get install htop 或 sudo yum install htop 安装):\nhtop\nhtop 提供了比 top 更友好的界面,支持鼠标操作和自定义视图。可以使用上下箭头键浏览进程,使用 F2 键进入设置界面。\n\n\n监控虚拟机的资源占用\n在 top 和 htop 中,可以通过筛选 KVM 相关进程来监控虚拟机的资源占用情况:\n\n\n使用 top 监控虚拟机资源占用:\n启动 top 后,按 u 键,然后输入虚拟机所属用户(通常是 qemu 或 libvirt按回车键\ntop -u qemu\n该命令将只显示属于该用户的进程包括 KVM 虚拟机进程。\n\n\n使用 htop 监控虚拟机资源占用:启动 htop 后,按 F4 键进入过滤模式,然后输入 qemu 或虚拟机进程名:\nhtop\n\n\n使用 iotop\niotop 是一个用于监控磁盘 I/O 性能的工具,可以帮助找出性能瓶颈。需要 root 权限运行。\n监控磁盘 I/O 性能\n\n\n安装 iotop\n# 在基于Debian的系统上\nsudo apt-get install iotop\n \n# 在基于RHEL的系统上\nsudo yum install iotop\n\n\n启动 iotop\nsudo iotop\n输出示例\nless复制代码Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s\nActual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s\n TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND\n1234 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kworker/0:1]\n...\niotop 显示每个进程的实时磁盘读写速度,帮助管理员识别高 I/O 负载进程。\n\n\n找出性能瓶颈\n\n通过排序和过滤找出 I/O 瓶颈:\n\n在 iotop 界面中,按 O 键只显示正在进行 I/O 操作的进程。\n按 P 键根据 I/O 优先级排序,或按 T 键根据线程排序,快速定位高 I/O 负载进程。\n\n\n查看具体进程的 I/O 使用情况:\n\n使用上下箭头键选择具体进程查看详细的 I/O 读写情况。可以通过进程 IDPID进一步分析相关进程的具体操作和配置。\n\n\n\n使用 iftop\niftop 是一个实时网络流量监控工具,可以帮助分析网络性能问题。\n监控网络流量\n\n\n安装 iftop\n## 在基于 Debian 的系统上\nsudo apt-get install iftop\n \n## 在基于 RHEL 的系统上\nsudo yum install iftop\n\n\n启动 iftop\nsudo iftop\n输出示例\ninterface: eth0\nIP address is: 192.168.1.10\nMAC address is: 00:1a:4b:16:01:59\nListening on port 0000\n---------------------------------------------------\n192.168.1.10 => 192.168.1.1 123KB 456KB 789KB\n <= 23KB 56KB 89KB\n...\niftop 显示网络接口的实时流量情况,包括发送和接收数据的速率。\n\n\n分析网络性能问题\n\n通过排序和过滤分析流量\n\n在 iftop 界面中,按 P 键切换端口显示模式,按 N 键切换主机名显示模式,按 S 键切换源地址和目的地址显示顺序。\n使用 l 键限制显示特定网络接口的流量,帮助聚焦分析特定接口的网络性能。\n\n\n查看具体连接的流量使用情况\n\n使用上下箭头键选择具体连接查看详细的流量使用情况。可以进一步分析哪些主机或服务占用了过多的网络带宽。\n\n\n\n通过使用系统监控工具如 top、htop、iotop 和 iftop管理员可以实时了解 KVM 虚拟化环境中系统资源的使用情况,快速识别并解决性能问题,确保虚拟机和宿主机的稳定运行和高效性能。在实际应用中,应结合具体需求和环境特点,灵活使用这些工具进行系统监控和性能优化。"},"Technology/OperatingSystem/Windows/文化/微软及其Windows系统的历史发展":{"title":"微软及其Windows系统的历史发展","links":[],"tags":["Windows/文化","技术/操作系统"],"content":"概述\n1975 年 4 月 4 日,比尔·盖茨和保罗·艾伦在新墨西哥州阿尔伯克基共同创立了微软公司。起初,微软专注于开发和销售 BASIC 解释器。1974 年底,艾伦在哈佛广场发现了介绍 Altair 8800 微型计算机的《流行电子学》杂志,激发了他与高中好友盖茨合作为这款计算机开发 BASIC 的灵感。这一合作的成功促成了微软的成立,盖茨为此离开了哈佛大学。\n微软的早期产品主要是为当时流行的家用计算机系统如 Apple II 和 Commodore 64开发的 Microsoft BASIC 的不同版本。他们的第一个硬件产品是 Z-80 SoftCard使 Apple II 能运行业界标准的 CP/M 操作系统。1980 年,微软发布了其首个公开的操作系统 Xenix一种基于 Unix 的系统。\n1980 年,微软开始与 IBM 合作,为 IBM 计算机提供操作系统。这一合作标志着微软在操作系统市场的重要转折点。在 IBM 与 Digital Research 的谈判失败后IBM 选择了微软作为其 IBM PC 操作系统的提供者。微软购买了 86-DOS 系统,重命名为 IBM PC DOS这成为了 IBM PC 的标准操作系统,并为后来广泛使用的 MS-DOS 奠定了基础。\nWindows 操作系统\n自 1985 年首次推出以来Windows 操作系统已成为全球最受欢迎的个人电脑操作系统之一。Windows 1.0 的发布标志着图形用户界面时代的到来,为用户提供了一个直观、易用的界面,相较于传统的命令行界面。\n进入 1990 年代,微软发布了 Windows 3.0 和 3.1,这些版本的成功标志着 Windows 的普及。随后Windows 95、98、2000、XP 等版本陆续推出,每个版本都在功能、稳定性和用户界面上进行了创新。尤其是 Windows XP它集成了早期版本的优势成为微软历史上最成功的操作系统之一。\n21 世纪以来Windows Vista、7、8 和 10 的发布展示了微软在操作系统领域的持续进步特别是在跨平台和云计算方面。Windows 10 的推出特别体现了微软对未来技术趋势的适应性。最新的 Windows 11 进一步展现了微软在用户界面设计和多任务处理方面的创新。\nWindows 操作系统的持续发展不仅反映了技术的革新,也展示了微软在市场策略和用户需求适应上的灵活性。面对苹果的 Mac OS 和各种 Linux 发行版的竞争Windows 继续保持其在个人电脑操作系统市场的主导地位,对全球用户的计算体验产生了深远的影响。\n发展历史\n\n\n1985 年:发布 Windows 1.0,引入图形用户界面。\n\n\n1990 年Windows 3.0 的推出,带来图形界面和性能的改进。\n\n\n1995 年Windows 95 发布,引入开始菜单,实现市场突破。\n\n\n2001 年:推出 Windows XP融合前代优势获得巨大成功。\n\n\n2007 年Windows Vista 问世,带来 Aero 图形界面,但因兼容性和性能问题遭遇批评。\n\n\n2009 年:发布 Windows 7修复了 Vista 的问题,赢得市场和用户好评。\n\n\n2012 年Windows 8 发布,引入触摸屏优化的界面。\n\n\n2015 年:推出 Windows 10标志着微软在跨平台和云计算方面的重大进步。\n\n\n2021 年Windows 11 发布,带来全新的用户界面和对最新硬件的强化支持。\n\n\n产品和服务多样化\n微软不仅专注于 Windows 操作系统,还大力发展了其他产品和服务,表现出高度的多样性和创新:\n\nOffice 套件:包括 Word、Excel、PowerPoint 等,成为全球标准办公软件。\nXbox 游戏平台:推出 Xbox 系列游戏机和 Xbox Live 在线服务,成为游戏行业的关键参与者。\nSurface 设备:推出一系列创新的个人电脑和平板设备,如 Surface Pro 和 Surface Laptop。\nAzure 云服务:提供云计算、存储及多种企业级服务,成为微软转型的核心。\nLinkedIn 和 Skype收购这些公司后微软在社交网络和通信领域的影响力得到扩展。\n\n微软的这一发展历程不仅体现了其在技术创新方面的领先地位也展示了其对市场变化的快速响应和适应能力。从一个小型软件公司成长为全球科技巨头微软不断扩展其影响力覆盖了操作系统、办公软件、游戏娱乐、云计算等多个领域。微软的成功在于其不断追求创新以及对用户需求和市场趋势的深刻理解。随着技术的不断进步微软继续引领着全球计算技术的未来方向为全世界的用户提供更加强大、便捷的技术解决方案。"},"Technology/ProgrammingLanguage/Python/入门/函数方法":{"title":"函数方法","links":[],"tags":["Python/入门","技术/程序语言"],"content":"函数\n\n函数是通过白盒/黑盒封装多行代码的实现方式,通常具有输入和输出,目的是为了简化代码、重复调用和模块化编程。\n在 Python 中def 关键字用于定义函数,每个函数都具有一个唯一的名称,其命名规则与变量命名规则相同。函数体的第一条语句可以是一个字符串,该字符串被称为文档字符串或 docstring用于提供关于函数的简要描述。\n# 语法\ndef 函数名(参数列表):\n 函数体\n \n# 实例\ndef fib(n): \n """输出限定数值内的斐波那契数列函数"""\n a, b = 0, 1\n while a < n:\n print(a, end=' ')\n a, b = b, a+b\n print()\n参数传递\npython 中类型属于对象,变量是没有类型的。**python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。**而不可变对象和可变对象的区别在于:不可变对象的值不可以改变,而可变对象的值可以改变。\n可更改与不可更改对象\n在 python 中 strings,、tuples 和 numbers 是不可更改的对象,而 list、dict 等则是可以修改的对象。\n\n**不可变类型:**变量赋值 a=5 后再赋值 a=10这里实际是新生成一个 int 值对象 10再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。\n**可变类型:**变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身 la 没有动,只是其内部的一部分值被修改了。\n\n参数传递\n\n**不可变类型:**类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。\n**可变类型:**类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响\n\n默认值参数\n在 Python 中,函数的参数可以有默认值,也支持使用可变参数,所以 Python 并不需要像其他语言一样支持函数的重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式。\ndef add(a=0, b=0, c=0):\n """三个数相加"""\n return a + b + c\nadd(1,2,3)\n# 6\n键值参数\nkwarg=value 形式的 关键字参数 也可以用于调用函数。函数示例如下:\n该函数接受一个必选参数voltage和三个可选参数state, action 和 type。\ndef parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):\n print("-- This parrot wouldn't", action, end=' ')\n print("if you put", voltage, "volts through it.")\n print("-- Lovely plumage, the", type)\n print("-- It's", state, "!")\n \nparrot("halo",type="test")\n \n# -- This parrot wouldn't voom if you put halo volts through it.\n# -- Lovely plumage, the test\n# -- It's a stiff !\n特殊参数\n可变参数 *\n在参数名前面的 * 表示 args 是一个可变参数,可以输入多个参数。\ndef add2(*args):\n total = 0\n for val in args:\n total += val\n print(total)\n \nadd2(1,2,3)\n# 6\n键值参数 **\n在参数名前面的 ** 表示 args 是一个可变参数,可以输入键值对。\ndef add2(**arg):\n print(arg)\n \nadd2(name="halo")\n# {'name': 'halo'}\n限位置参数 /\n/ 必须放在形参后面表示限制位置参数,实参必须按照形参位置输入。\ndef pos_only_arg(arg, /):\n print(arg)\n限关键字参数 *\n* 必须放在形参前面表示限关键字参数,实参必须按键值参数输入。\ndef kwd_only_arg(*, arg):\n print(arg)\n特殊参数组合\ndef combined_example(pos_only, /, standard, *, kwd_only):\n print(pos_only, standard, kwd_only)\n \n"""\n运行示例\n"""\n>>> combined_example(1, 2, 3)\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\nTypeError: combined_example() takes 2 positional arguments but 3 were given\n \n>>> combined_example(1, 2, kwd_only=3)\n1 2 3\n \n>>> combined_example(1, standard=2, kwd_only=3)\n1 2 3\n \n>>> combined_example(pos_only=1, standard=2, kwd_only=3)\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\nTypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'\nReturn\nreturn [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。\ndef sum( arg1, arg2 ):\n # 返回2个参数的和."\n total = arg1 + arg2\n print ("函数内 : ", total)\n return total\n \n# 调用sum函数\ntotal = sum( 10, 20 )\nprint ("函数外 : ", total)\n全局、局部变量\n在 Python 中,变量的作用范围可分为全局变量和局部变量。\n\n**全局变量:**在函数体外部声明的变量被称为全局变量。全局变量在程序的整个生命周期内都是可访问的。\n**局部变量:**在函数体内部声明的变量被称为局部变量。它们只能在声明它们的函数内部被访问。\n\nx = 10 # 这是一个全局变量\n \ndef func():\n y = 5 # 这是一个局部变量\n print(y) # 输出5\n \nfunc()\nprint(x) # 输出10\nprint(y) # 将会引发一个错误,因为 y 在这个作用域内不存在\nglobal、nonlocal\n当需要在函数或其他作用域内部改变全局变量或嵌套作用域中的变量时我们需要使用 global 或 nonlocal 关键字。\n\nglobal 关键字: 允许你在函数或其他局部作用域内部修改全局变量。\nnonlocal 关键字: 允许你在嵌套的函数(即闭包)中修改上一层非全局作用域的变量。\n\n# 使用 global 关键字:\nx = 10\n \ndef func():\n global x\n x = 20 # 修改全局变量 x\n \nfunc()\nprint(x) # 输出20\n \n# 使用 nonlocal 关键字:\ndef outer():\n x = 10\n def inner():\n nonlocal x\n x = 20 # 修改上一层函数中的 x\n \n inner()\n print(x) # 输出20\n \nouter()\nYield\nyield 是 Python 中用于创建生成器generator的关键字。一个包含 yield 表达式的函数被称为一个生成器函数。这种函数在被调用时不会立即执行,而是返回一个迭代器,这个迭代器可以在其元素需要被处理时生成它们。这种延迟生成元素的方式使得生成器在处理大数据集或无限序列时非常有用,因为它们不需要一次性生成所有元素,从而节省内存。\n生成器函数在执行到 yield 表达式时会暂停并保存当前所有的状态信息(包括局部变量等),在下次从该函数获取下一个元素(即进行下一次迭代)时,它会从保存的状态和位置继续执行。\n# yield a 语句会暂停函数的执行并返回当前的 a 值作为序列的下一个元素。\n# 在下次迭代时,函数会从 yield a 语句后的语句继续执行,计算出序列的下一个值。\ndef fibonacci():\n a, b = 0, 1\n while True:\n yield a\n a, b = b, a + b\n \n# zip(range(10), fibonacci()) 部分会生成一个迭代器\n# 这个迭代器在每次迭代时都会返回斐波那契数列的下一个数字,直到生成了前 10 个数字为止。\nfor _, val in zip(range(10), fibonacci()):\n print(val)\nLambda\nlambda 关键字用于创建小巧的匿名函数。Lambda 函数可用于任何需要函数对象的地方。在语法上匿名函数只能是单个表达式。在语义上它只是常规函数定义的语法糖。与嵌套函数定义一样lambda 函数可以引用包含作用域中的变量:\n\nlambda 只是一个表达式,函数体比 def 简单很多。\nlambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。\nlambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。\n虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。\n\n# 语法\nlambda arguments: expression\n \n# lambda 实例\ndouble = lambda x: x * 2\n \n# 常规函数\ndef double(x):\n return x * 2\n \nprint(double(5)) # 输出10"},"Technology/ProgrammingLanguage/Python/入门/基础语法":{"title":"基础语法","links":[],"tags":["Python/入门","技术/程序语言"],"content":"简介\nPython 是一门易于学习、功能强大的编程语言。同时是一种解释型语言不需要编译和链接可以节省大量开发时间。Python 入门相对其它程序设计语言简单,但是熟练掌握需要一定学习时间,尤其是丰富的魔术方法。\nPython 程序简洁、易读,通常比实现同种功能的 C、C++、Java 代码短很多,原因如下:\n\n高级数据类型允许在单一语句中表述复杂操作\n使用缩进而不是括号实现代码块分组\n无需预声明变量或参数。\n\nPython 解释器易于扩展,使用 C 或 C++(或其他 C 能调用的语言)即可为 Python 扩展新功能和数据类型。Python 也可用作定制软件中的扩展程序语言。\nPython 官网上免费提供了 Python 解释器和扩展的标准库,包括源码和适用于各操作系统的机器码形式,并可自由地分发。\nPython 官网还包含许多免费丰富的第三方 Python 模块、程序和工具发布包及文档链接。\n使用\n安装\nPython 官网www.python.org/,可以在 官方文档 帮助下选择合适版本安装。\n运行\nPython 安装后在 Shell 中输入 Python 既可运行交互解释器,在解释器内编写 Python 脚本既可以运行。如果需要退出,输入 quit()。\n编码\nPython 源码文件的默认编码是 UTF-8如果不使用默认编码则要声明文件的编码文件的第一行要写成特殊注释。句法如下\n# -*- coding: encoding -*-\n注释\n\n\n单行注释以 # 和空格开头的部分\n\n\n多行注释三个引号开头三个引号结尾\n\n\n"""\n第一个 Python 程序 - hello, world!\n向伟大的 Dennis M. Ritchie 先生致敬\n"""\n# hello world\nprint('hello, world!')\nprint("你好, 世界!")\n缩进\nPython 最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} 。缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。如果语句缩进数的空格数不一致,会导致运行错误。\n# 正确缩进\nif True:\n print ("True")\nelse:\n print ("False")\n \n# 错误缩进\nif True:\n print ("Answer")\n print ("True")\nelse:\n print ("Answer")\n print ("False") # 缩进不一致,会导致运行错误\n行语句\n如果语句很长我们可以使用反斜杠 \\ 来实现多行语句;如果在同一行中使用多条语句,语句之间使用分号 ; 分割。在 [], {}, 或 () 中的多行语句,不需要使用反斜杠 \\。 字符串之间不换行则会自动拼接。\n# 反斜杠 \\ 用法\ntotal = item_one + \\\n item_two + \\\n item_three\n \n# 分号 ; 用法\nimport sys; x = 'runoob'; sys.stdout.write(x + '\\n')\n \n# 特殊多行语句\ntotal = ['item_one', 'item_two', 'item_three',\n 'item_four', 'item_five']\n \n# 字符串\nstr = "hello" "world" "!"\n复合语句\nPython 像 if、while、def 和 class 这样的复合语句,首行以关键字开始,以冒号 ( : ) 结束,该行之后的一行或多行代码构成代码组。首行及后面的代码组称为一个子句 (clause)。\nif expression : \n suite\nelif expression : \n suite \nelse : \n suite\n此外Python 还支持一些更高级的特性,如函数式编程、面向对象编程和元编程等。随着学习的深入,你会发现 Python 的世界越来越广阔。\n关键字\nPython 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字:\n$ import keyword\n$ print(keyword.kwlist)\n \n['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']\n声明\n硬性规则\n\n变量名由字母广义的 Unicode 字符,不包括特殊字符)、数字和下划线构成,数字不能开头。\n大小写敏感大写的 a 和小写的 A 是两个不同的变量)。\n不要跟关键字有特殊含义的单词和系统保留字如函数、模块等的名字冲突。\n\nPEP 8 要求:\n\n用小写字母拼写多个单词用下划线连接。\n受保护的实例属性用单个下划线开头。\n私有的实例属性用两个下划线开头。\n"},"Technology/ProgrammingLanguage/Python/入门/控制语句":{"title":"控制语句","links":[],"tags":["Python/入门","技术/程序语言"],"content":"Python 中的控制语句有条件语句,循环语句,异常处理,以及其他一些特殊的控制语句。\n条件语句\nPython 中的条件语句是通过一条或多条语句的执行结果(即 True 或 False来决定执行的代码块。\n判断的值可以分为\n\n假值 None、空列表、空集合、空字典空元组、空字符串、0、False 等。\n真值 :非空列表、非空集合、非空字典,非空元组、非空字符串、非 0 数值、True 等。\n\nIf\n在 Python 中,要构造分支结构可以使用 if、elif 和 else 关键字。elif 和 else 都是可选的,可以根据需要进行使用。\n# 示例\n>>> x = int(input("Please enter an integer: "))\nPlease enter an integer: 42\n>>> if x < 0:\n x = 0\n print('Negative changed to zero')\n elif x == 0:\n print('Zero')\n elif x == 1:\n print('Single')\n else:\n print('More')\n当然如果要构造出更多的分支可以使用 if...elif...else... 结构或者嵌套的 if...else... 结构。\nMatch\nPython 3.10 引入了新的 match 语句它是模式匹配的一种形式。match 语句接受一个表达式并将它的值与一系列的模式进行比较。 每个模式都关联到一个代码块,当模式与表达式的值匹配时,该代码块将被执行。这在某种程度上类似于其他语言中的 switch 语句。\ndef http_error(status):\n match status:\n case 400:\n return "Bad request"\n case 404:\n return "Not found"\n case 418:\n return "I'm a teapot"\n #"变量名" `_` 被作为 通配符 并必定会匹配成功\n case _: \n return "Something's wrong with the internet"\n你可以使用 | (“ or ”)在一个模式中组合几个字面值:\ncase 401 | 403 | 404:\n return "Not allowed"\n注意match 语句和模式匹配的概念是 Python 3.10 中新增的特性,可能在更早版本的 Python 中无法使用。\n循环语句\nFor\nPython 的 for 语句用于遍历任何序列的项目,如列表或字符串。\nPython 的 for 语句与 C 或 Pascal 中的不同。Python 的 for 语句不迭代算术递增数值(如 Pascal或是给予用户定义迭代步骤和暂停条件的能力如 C而是迭代列表或字符串等任意序列元素的迭代顺序与在序列中出现的顺序一致。\n"""\n用for循环实现1~100求和\n"""\n \nsum = 0\nfor x in range(101):\n sum += x\nprint(sum)\n内置函数 range() 表示不可变的数字序列,通常用于在 for 循环中循环指定的次数。\n在 Python 中range() 是一个内置函数,用于生成一个不可变的数字序列。通常,这个函数在 for 循环中使用用于指定循环的次数。range(101) 可以用来生成一个包含 0 到 100不包含 101的整数序列。\n你也可以根据需要更改 range() 函数的参数,例如:\n\nrange(1, 101):生成一个包含 1 到 100不包含 101的整数序列。\nrange(1, 101, 2):生成一个包含 1 到 100 的奇数序列,其中 2 是步长。\nrange(100, 0, -2):生成一个包含 100 到 1 的偶数序列,其中 -2 是步长。\n\nWhile\nwhile 循环语句用于在条件满足的情况下重复执行一个代码块。条件表达式的结果为 True 时,继续循环;结果为 False 时,结束循环。\n"""\n猜数字游戏\n"""\nimport random\n \nanswer = random.randint(1, 100)\ncounter = 0\nwhile True:\n counter += 1\n number = int(input('请输入: '))\n if number < answer:\n print('大一点')\n elif number > answer:\n print('小一点')\n else:\n print('恭喜你猜对了!')\n break\nprint('你总共猜了%d次' % counter)\nif counter > 7:\n print('你的智商余额明显不足')\nBreak\nbreak 语句可以提前退出循环。具体来说break 用于完全结束一个循环,并跳出该循环体。\nContinue\ncontinue 语句用于跳过当前循环的剩余语句,然后继续进行下一轮循环。\nElse\n在 Python 中else 子句可以与 for 循环和 while 循环一起使用。当循环正常完成(即没有碰到 break 语句else 块的内容会被执行。这个特性在很多其他语言中都没有,因此对于初学者来说可能会感到有些不熟悉。\n# 使用 else 的 for 循环的示例\nfor i in range(5):\n if i == 10:\n break\nelse:\n print("循环正常完成")\n在这个示例中循环会正常完成因为没有任何一个元素使得 i == 10 为 True所以 break 语句不会被执行else 块的内容会被打印出来。\n如果我们修改 if 语句的条件使得 break 语句被执行,那么 else 块的内容就不会被打印出来:\nfor i in range(5):\n if i == 3:\n break\nelse:\n print("循环正常完成")\n在这个示例中当 i 等于 3 时break 语句就会被执行所以循环没有正常完成else 块的内容不会被打印出来。\n同样的else 也可以与 while 循环一起使用,当 while 循环的条件变为 False 时else 块的内容会被执行。\ni = 0\nwhile i < 5:\n if i == 3:\n break\n i += 1\nelse:\n print("循环正常完成")\n在这个示例中当 i 等于 3 时break 语句就会被执行所以循环没有正常完成else 块的内容不会被打印出来。\n异常语句\ntry、except、finally\ngraph TD\n A(开始)\n B[try 块]\n C[except 块1]\n D[except 块2]\n E[else 块]\n F[finally 块]\n G(结束)\n A --> B\n B -- 异常1 --> C\n B -- 异常2 --> D\n B -- 无异常 --> E\n C --> F\n D --> F\n E --> F\n F --> G\n\n\n\n确定需要的异常处理结构在开始编写异常处理结构时首先确定你需要 try, except, else 和/或 finally 语句块。要记住的是except 和 finally 块至少需要一个,否则 try 将失去其意义。\n编写 try 语句块:将可能抛出异常的代码放入 try 块。如果在 try 块中发生异常Python 将停止执行 try 块的其余部分,并转到 except 块。\n编写 except 语句块:为每种可能抛出的异常类型编写一个 except 块。Python 会按照它们在代码中出现的顺序来检查这些 except 块。如果匹配到异常Python 将执行相应的 except 块并停止查找。\n处理多个异常你可以将多个异常类型放入一个元组中然后使用一个 except 块来处理它们。例如except (TypeError, ValueError):。\n处理所有异常如果 except 块后面没有指定异常类型,那么这个 except 块将处理所有异常。你可以通过 logging 或 sys 模块获取异常的详细信息。\n重新抛出异常如果你在 except 块中捕获了一个异常,然后想要再次抛出它,你可以使用 raise 语句而不需要附加任何参数或信息。\n编写 else 语句块else 块中的代码只有在 try 块没有发生任何异常时才会被执行。\n编写 finally 语句块无论是否发生异常finally 块中的代码总是会被执行。这对于清理(例如关闭文件或网络连接)非常有用。\n重构代码考虑使用 with 语句或 getattr() 方法等内置的异常处理语句,而不是 try/except。此外如果可能尽量避免在同一个 except 块中捕获和抛出相同的异常。最后,除非你确定需要处理所有可能的异常,否则不应该捕获所有异常,因为这可能会隐藏严重的问题。\n\n# 示例\ntry:\n # 这里可能会抛出异常的代码\n do_something()\nexcept SomeException as e:\n # 当捕获到SomeException时的处理代码\n handle_exception(e)\n \n# 实例\ndef div(a, b):\n try:\n print(a / b)\n except ZeroDivisionError:\n print("错误b 不应为 0 !!")\n except Exception as e:\n print("意外错误:{}".format(e))\n else:\n print('只有当一切正常时,才会运行 else')\n finally:\n print('始终运行 finally 块。')\n \n# 测试\ndiv(2, 0)\ndiv(2, '错误的类型')\ndiv(1, 2)\n \n \n# 在一行中捕获多个异常\ntry:\n print(a / b)\nexcept (ZeroDivisionError, TypeError) as e:\n print(e)\n \n \n# 当存在 finally 时except 是可选的\ntry:\n open(database)\nfinally:\n close(database)\n \n# 捕获所有错误并记录下来\ntry:\n do_work()\nexcept: \n # 从 logging 模块获取详细信息\n logging.exception('捕获到异常!')\n \n # 从 sys.exc_info() 方法获取详细信息\n error_type, error_value, trace_back = sys.exc_info()\n print(error_value)\n raise\nWith\nPython 的 with 语句支持通过上下文管理器所定义的运行时上下文这一概念。\nwith 语句是一种处理上下文管理器的语句,上下文管理器通常包含 __enter__ 和 __exit__ 这两个方法。在 with 语句的代码块被执行前,会首先执行 __enter__ 方法,在执行完毕后,会调用 __exit__ 方法。这在你需要管理资源,如文件,网络连接或锁定等情况非常有用,因为它可以保证在任何情况下都会执行必要的清理操作。\n# 在这里,文件已经被关闭,无需再次手动关闭\nwith open("file.txt", "r") as file:\n for line in file:\n print(line)\n# 基本思想是 with 所求值的对象必须有一个 enter() 方法,一个 exit() 方法。\n# 紧跟 with 后面的语句被求值后,返回对象的 enter() 方法被调用,并将返回值赋值给 as 后面的变量。\n# 当 with 的代码块全部被执行完之后,将调用前面返回对象的 exit() 方法。\n \nclass ManagedFile:\n def __init__(self, filename):\n self.filename = filename\n \n def __enter__(self):\n self.file = open(self.filename, 'r')\n return self.file\n \n def __exit__(self, exc_type, exc_val, exc_tb):\n if self.file:\n self.file.close()\n \n# 使用自定义的上下文管理器\nwith ManagedFile("file.txt") as file:\n print(file.read())\nRaise\nraise 语句用于引发特定的异常。你可以定义异常类型并附加一个错误消息:\nraise ValueError("这是一个无效的值!")\n如果你在 except 块中使用 raise 语句,而不提供任何参数,它将默认重新引发最近的异常。\ntry:\n print(5/0)\nexcept ZeroDivisionError as e:\n print("发生了一个错误!")\n raise # 重新引发最近的异常\n其他语句\nAssert\nassert 语句用于断言某个条件为真,如果条件为假,则会抛出 AssertionError 异常。它常常用于调试代码,确认代码的某些方面满足预期,例如:\nx = 1\nassert x == 1 # 条件为真,没有问题\n \n# 条件为假,抛出 AssertionError并附带错误信息\nassert x == 2, "x should be 2 but is actually " + str(x) \n注意assert 语句在优化模式下(使用 -O 参数启动 Python 时)会被全局禁用。\nPass\npass 语句是 Python 中的空语句,用于在需要语句的地方保持语法的完整性,但是实际上不做任何事情。通常,我们使用它作为未完成代码的占位符:\ndef my_function():\n pass # TODO: implement this function\n \nclass MyEmptyClass:\n pass\nReturn\nreturn 语句用于从函数返回一个值。所有函数都会返回一个值:如果函数执行到结尾而没有遇到 return 语句,它将返回特殊值 None\ndef add(a, b):\n return a + b\n \nprint(add(1, 2)) # 输出3"},"Technology/ProgrammingLanguage/Python/入门/数据类型":{"title":"数据类型","links":[],"tags":["Python/入门","技术/程序语言"],"content":"在编程领域理解和掌握各种数据类型是任何编程语言的基础Python 也不例外。Python 3 提供了多种内置数据类型,包括但不限于数字(整型、浮点型、复数)、布尔型、列表、元组、字符串、集合、字典等,还有函数、模块等高级类型。每种数据类型都有其特定的特性和适用场景。\n\n在 Python 中变量可以被理解为一个标签tag或者标记它是附着在特定对象上的名字。你可以将这个理念理解为在超市里的商品标签标签告诉你这是什么商品而商品是具体的物品。同样的Python 的变量名就像是一个标签,它告诉我们这个变量指向的是什么对象,而对象是存储在内存中的具体数据。\n\n对象与类型\n**在 Python 中,几乎所有的数据都可以被视为对象,每一个对象都有其相应的类型。**例如:\nprint(type(123)) # <class 'int'>\nprint(type(3.14)) # <class 'float'>\nprint(type('hello')) # <class 'str'>\n**Python 是动态类型语言,我们不需要预先声明变量的类型。**在程序运行过程中,变量的类型可以根据赋值而改变。例如:\nx = 123 # x 是一个整数\nprint(type(x)) # <class 'int'>\n \nx = 'hello' # x 变成了一个字符串\nprint(type(x)) # <class 'str'>\nPython 中有两个内置函数 id 和 type。\n\nid(obj) 函数:返回对象 obj 的唯一标识符,其实质上是该对象在内存中的地址。\ntype(obj) 函数:返回对象 obj 的类型。\n\n引用计数和垃圾收集\nPython 不依赖存储期(即对象在内存中存在的时间)来管理变量和对象,而是使用引用计数。每个对象都会计算有多少个变量引用了它,当引用计数为 0 时,对象就会被垃圾收集器删除。可以使用内置的 id 函数获取对象的标识(这实际上是该对象的内存地址),使用 type 函数获取对象的类型。\n# 引用计数和垃圾收集的例子:\n# 在代码中,`sys.getrefcount(a)`可以获得对象`a`的引用计数。\n# 当我们创建一个新的引用`b`时,`a`的引用计数增加1。\n# 当我们删除`b`时,`a`的引用计数减少1。\n \nimport sys\n \na = [] # 创建一个空列表\n \nprint(sys.getrefcount(a)) # 输出2一个引用来自 a一个来自 getrefcount 的参数\n \nb = a # 增加一个引用\n \nprint(sys.getrefcount(a)) # 输出3新增一个引用来自 b\n \nb = None # 删除一个引用\n \nprint(sys.getrefcount(a)) # 输出2b 不再引用\n可变类型、不可变类型\nPython 中的数据类型可以分为两大类:可变类型与不可变类型。\n\n可变类型值可以更改如列表、字典和集合。\n不可变类型值不可更改如数字、字符串、元组等。\n\n不可变类型的变量如果改变值实际上是生成了一个新的对象并使变量引用新的对象。Python 的赋值语句复制的是对象的引用而不是对象的值。因此Python 中的“变量”与其他编程语言中的“变量”不完全相同,将其翻译为“引用”可能更加合适。\n# 在代码中,`list1`是一个列表,是可变类型。\n# 我们可以通过`append`方法修改`list1`,但是`list1`的`id`并未改变,说明`list1`还是同一个对象。\n# `x`是一个整数,是不可变类型。当我们改变`x`的值时,`x`的`id`改变了,说明`x`现在是一个新的对象。\n \n# 可变类型:列表\nlist1 = [1, 2, 3]\nprint(id(list1)) # 输出 list1 的 id\nlist1.append(4) # 修改 list1\nprint(id(list1)) # id 没有改变\n \n# 不可变类型:整数\nx = 1\nprint(id(x)) # 输出 x 的 id\nx = x + 1 # 修改 x\nprint(id(x)) # id 改变了\nPython3 内置类型\nPython 3 内置了多种数据类型,同时还内建了许多其他类型,如上下文管理器类型、模块、方法、代码对象、类型对象、内部对象等。\n数字类型\n数字类型主要用于存储和处理数值。这包括整数、浮点数、复数和布尔类型。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性int整数无论大小都可以是正数或负数。123, -456, 0不可变float浮点数包含小数部分的数字。3.14, -0.01, 9.0不可变complex复数包含实部和虚部的数字。1+2j, 3-4j不可变\n布尔类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性bool布尔表示真或假的值。True, False不可变\n序列类型\n序列类型是一种有序的元素集合包括字符串、列表和元组。每个元素都有一个相应的索引可以通过索引来访问。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性str字符串由零个或多个字符组成的文本。'hello', "world", ''不可变list列表由一系列按特定顺序排列的元素组成。[1, 'two', 3.0]可变tuple元组类似于列表但元素不可更改。(1, 'two', 3.0)不可变\n集合类型\n集合类型是一个无序的元素集合其中的元素都是唯一的。这包括集合和冻结集合。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性set集合一组无序的、不重复的元素。{1, 'two', 3.0}可变frozenset不可变集合类似于集合但元素不可更改。frozenset({1, 'two', 3.0})不可变\n映射类型\n映射类型是一个存储键值对的元素集合其中的键是唯一的。字典就是一个映射类型。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性dict字典包含键值对的数据结构。{'name': 'John', 'age': 25}可变\n特殊类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性NoneType表示 None 的特殊类型。None不可变EllipsisType表示省略的特殊类型主要在切片和 NumPy 库中使用。Ellipsis 或 ...不可变NotImplementedType表示未实现方法的特殊类型主要在自定义比较方法中使用。NotImplemented不可变\n二进制类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性bytes字节包含零个或多个范围为 0⇐x<256 的整数的不可变序列。b'hello', b'\\x01\\x02'不可变bytearray字节数组包含零个或多个范围为 0⇐x<256 的整数的可变序列。bytearray(b'hello')可变memoryview内存查看用于访问其他二进制序列、打包的数组和缓冲区的内部数据。memoryview(b'hello')依据所查看对象\n类、实例和异常\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性object对象所有类的基类。obj = object()依据具体类exception异常程序运行时的错误。raise Exception('Error!')不可变\n其他内置类型\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型描述示例可变性function函数包含一系列指令的代码块。def greet(): print('Hello!')不可变type类型表示对象的类型。type(123)不可变generator生成器一种可迭代的对象由函数定义并使用 yield 产生值。(x**2 for x in range(10))不可变\n类型转换\nPython 提供了多种函数,用于在不同类型之间进行转换:\nx = "123" # 这是一个字符串\nprint(type(x)) # <class 'str'>\n \nx = int(x) # 将字符串转为整数\nprint(type(x)) # <class 'int'>\n \nx = float(x) # 将整数转为浮点数\nprint(type(x)) # <class 'float'>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述int(x [,base])将 x 转换为一个整数float(x)将 x 转换到一个浮点数complex(real [,imag])创建一个复数str(x)将对象 x 转换为字符串repr(x)将对象 x 转换为表达式字符串eval(str)用来计算在字符串中的有效 Python 表达式,并返回一个对象tuple(s)将序列 s 转换为一个元组list(s)将序列 s 转换为一个列表set(s)转换为可变集合dict(d)创建一个字典。d 必须是一个 (key, value) 元组序列frozenset(s)转换为不可变集合chr(x)将一个整数转换为一个字符ord(x)将一个字符转换为它的整数值hex(x)将一个整数转换为一个十六进制字符串oct(x)将一个整数转换为一个八进制字符串\n运算符\n在实际开发中如果搞不清楚运算符的优先级可以使用括号来确保运算的执行顺序。\n# 运算符\na = 10\nb = 20\n \nprint(a + b) # 加法,输出: 30\nprint(a - b) # 减法,输出: -10\nprint(a * b) # 乘法,输出: 200\nprint(a / b) # 除法,输出: 0.5\nprint(a ** 2) # 幂运算,输出: 100\nprint(a % 3) # 取模,输出: 1\n \n# 逻辑运算符\nprint(a > b) # 大于,输出: False\nprint(a < b) # 小于,输出: True\nprint(a == b) # 等于,输出: False\nprint(a != b) # 不等于,输出: True\n \n# 成员运算符\ns = 'Hello World'\nprint('World' in s) # 输出: True\nprint('Python' not in s) # 输出: True\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述[] [:]下标,切片**指数~ + -按位取反, 正负号* / % //乘,除,模,整除+ -加,减>> <<右移,左移&按位与^ ``<= < > >=小于等于,小于,大于,大于等于== !=等于不等于is is not身份运算符in not in成员运算符not or and逻辑运算符= += -= *= /= %= //= **= &= `=^=>>=“<⇐`"},"Technology/ProgrammingLanguage/Python/入门/数据结构":{"title":"数据结构","links":[],"tags":["Python/入门","技术/程序语言"],"content":"数值\nPython 的数值数据类型是用来存储数值的。一旦创建数值对象的身份和类型是不可改变的。如果你改变了数值对象的值Python 将创建一个新的数值对象。Python 支持三种不同的数值类型:\n\n整型 (int):被用来表示整数,包括正整数和负整数,不带小数点。在 Python 3 中,整数的长度是无限的,可以视为 Python 2 中的 Long 类型。此外布尔类型bool实际上是整型的一种特殊形式其中 True 和 False 分别被表示为 1 和 0。\n浮点型 (float)用来表示实数由整数部分和小数部分组成。浮点型还可以使用科学计数法表示。例如2.5e2 表示的是 2.5 乘以 10 的平方,等于 250。\n复数 (complex):复数由实部和虚部构成,表示形式可以是 a + bj或者 complex(a,b)。在这里,实部 a 和虚部 b 都是浮点型。\n\nnum1 = -100 # 整数\nnum2 = 200.01 # 浮点数\nnum3 = 0xA0F # 十六进制\nnum4 = 0o37 # 八进制\n \n# 引入库\nimport math\nimport random\n \n# 数学常量 PI 和 e\npi = math.pi\ne = math.e\n \n# 绝对值\nabs_val = abs(num1)\n \n# 向上取整\nceil_val = math.ceil(num2)\n \n# 返回最大数\nmax_val = max(num1, num2)\n \n# x**y 运算后的值\npow_val = pow(num1, num2)\n \n# 随机数\nrandom_val = random.random()\n \n# x弧度的正弦值。\nsin_val = math.sin(pi/2)\n字符串\n字符串在计算机科学和编程中非常重要。在 Python 程序中,如果我们把单个或多个字符用单引号或者双引号包围起来,我们就创建了一个字符串。\n定义\n# 在 Python 中,可以使用单引号(')和双引号(")来定义字符串,它们的使用方式完全相同。\ns1 = 'hello, world!'\ns2 = "hello, world!"\n \n# 使用三个单引号(''')或者三个双引号(""")可以创建一个多行字符串。\ns3 = """\nhello, \nworld!\n"""\n \n# 反斜杠(\\)可以用来在字符串中插入特殊字符,这被称为转义字符。\ns4 = '\\n\\t\\141\\u9a86\\u660a'\n \n# 在字符串前加上字符 r 可以阻止反斜杠的转义效果。\ns5 = r'\\n\\\\hello, world!\\\\\\n' \n \n# 通过将字符串级联来创建新的字符串。\ns6 = "this " "is " "string"\n \n# 字符串是不可变的,这意味着你不能改变一个字符串的内容。\ns6[2] = "c" # 这将引发一个错误\n \n# 字符串可以通过索引进行访问,其中 0 是第一个字符的索引,-1 是最后一个字符的索引。\ns1 = 'hello, world!'\nprint(s1[0]) # 输出h\nprint(s1[-1]) # 输出:!\n \n# Python也支持字符串的切片操作你可以使用这种方式来获取字符串的一部分。\ns1 = 'hello, world!'\nprint(s1[0:5]) # 输出hello\n \n# ===== 字符串切片示意图 =====\n| L | e | t | t | e | r | s |\n|---|---|---|---|---|---|---|\n| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n|-7 |-6 |-5 |-4 |-3 |-2 |-1 |\n转义\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n转义字符描述示例\\\\反斜杠符号print("\\\\") 输出:\\\\'单引号print('\\'') 输出:'\\"双引号print("\\"") 输出:"\\n换行print("\\n") 输出一个新行\\r回车print("Hello\\rWorld!") 输出World!\\t横向制表符Tabprint("Hello\\tWorld!") 输出Hello World!\\b退格 (Backspace)print("Hello \\bWorld!") 输出Hello World!\\f换页print("Hello \\fWorld!") 输出Hello World!\\a响铃print("\\a") 执行后电脑有响声\\000空print("\\000") 输出:“\\v纵向制表符print("Hello \\vWorld!") 输出Hello World!\\other其他的字符以普通格式输出\\xhh二进制数代表一个 ASCII 字符print("\\x48\\x65\\x6c\\x6c\\x6f") 输出Hello\\ooo八进制数代表一个 ASCII 字符print("\\141\\142\\143") 输出abc\\uhhhh16 进制数,代表一个 Unicode 字符print("\\u6211\\u4eec") 输出:我们\n运算\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符描述示例+连接字符串"Hello " + "World!" 输出Hello World!*重复字符串"Hello " * 3 输出Hello Hello Hello[]索引字符串"Hello"[1] 输出e[:]切片字符串"Hello"[1:4] 输出ellin成员运算符 - 如果字符串中包含给定的字符返回 True'H' in 'Hello' 输出Truenot in成员运算符 - 如果字符串中不包含给定的字符返回 True'H' not in 'Hello' 输出False%格式化字符串"Hello, %s" % 'World!' 输出Hello, World!f-string格式化字符串的新方式Python 3.6+f"Hello, {'World!'} 输出Hello, World!\nf-strings\n在 Python 3.6 及以后的版本中,格式化字符串引入了更为简洁的方式,即使用 f 字符作为字符串的前缀创建所谓的格式化字符串字面值f-string。通过 f-string可以在字符串中直接插入变量值或表达式并可以通过冒号和数字来指定输出宽度等格式化选项。\n# {a:10} 表示将变量 a 插入到字符串中,并占用 10 个字符的宽度。不足 10 个字符,将使用空格进行填充。\n \na, b = 5, 10\nprint(f'{a:10} * {b:10} = {a * b}')\nPEP 701 的更新\n在 Python 3.11 版本中f-strings 还存在一些限制导致在某些情况下使用起来不够灵活。PEP 701 对 f-strings 进行了一些更新,解除了一些限制,使得 f-strings 可以更灵活地使用,包括以下方面的更新:\n在 Python 3.12 版本中,对 f-strings 进行了更新,解除了之前的一些限制,使得 f-strings 更加灵活和强大。更新主要包括以下方面:\n引号重用\n在 Python 3.11 中f-string 的表达式组件使用与包含 f-string 相同的引号会导致 SyntaxError。而在 Python 3.12 中,可以重用引号,不再限制引号的使用。\nsongs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']\nresult1 = f"This is the playlist: {', '.join(songs)}"\nprint(result1)\n# 输出:'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'\n多行表达式和注释\n在 Python 3.11 中f-string 的表达式必须在一行内定义,即使外部表达式可以跨多行,这会使得代码可读性变差。而在 Python 3.12 中,可以定义跨多行的表达式,并且可以包含注释,提高了代码的可读性。\nresult2 = f"This is the playlist: {', '.join([\n 'Take me back to Eden', # My, my, those eyes like fire\n 'Alkaline', # Not acid nor alkaline\n 'Ascensionism' # Take to the broken skies at last\n])}"\nprint(result2)\n# 输出:'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'\n反斜杠和 Unicode 字符\n在 Python 3.11 中f-string 的表达式不能包含任何反斜杠字符,也不能包含 Unicode 转义序列。而在 Python 3.12 中,可以包含反斜杠和 Unicode 字符,使得表达式更加灵活。\nsongs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']\n \nresult3 = f"This is the playlist: {'\\n'.join(songs)}"\nprint(result3)\n# 输出:\n# This is the playlist: Take me back to Eden\n# Alkaline\n# Ascensionism\n \nresult4 = f"This is the playlist: {'\\N{BLACK HEART SUIT}'.join(songs)}"\nprint(result4)\n# 输出:'This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism'\n以上代码展示了 Python 3.12 中 f-strings 的更新。可以看到,我们可以在 f-string 中使用引号重用,多行表达式和注释,以及包含反斜杠和 Unicode 字符的表达式,这些更新使得 f-strings 更加灵活和强大,更方便地进行字符串格式化。同时,通过使用 PEG 解析器实现的更新,使得错误消息更加准确,有助于代码调试。\n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述示例len(str)返回字符串长度len('hello, world!') 输出结果13str.capitalize()返回首字母大写的字符串'hello, world!'.capitalize() 输出结果Hello, world!str.title()返回每个单词首字母大写的字符串'hello, world!'.title() 输出结果Hello, World!str.upper()返回字符串变大写后的拷贝'hello, world!'.upper() 输出结果HELLO, WORLD!str.find(sub)查找子串在字符串中的起始位置,未找到返回 -1'hello, world!'.find('or') 输出结果8str.startswith(prefix)检查字符串是否以指定的前缀开头'hello, world!'.startswith('He') 输出结果Falsestr.endswith(suffix)检查字符串是否以指定的后缀结尾'hello, world!'.endswith('!') 输出结果Truestr.center(width, fillchar)将字符串以指定宽度居中并在两侧填充指定字符'hello'.center(10, '*') 输出结果hellostr.rjust(width, fillchar)将字符串以指定宽度靠右并在左侧填充指定字符'hello'.rjust(10, '*') 输出结果:*****hellostr.isdigit()检查字符串是否由数字构成'abc123456'.isdigit() 输出结果Falsestr.isalpha()检查字符串是否由字母构成'abc123456'.isalpha() 输出结果Falsestr.isalnum()检查字符串是否由字母和数字构成'abc123456'.isalnum() 输出结果Truestr.strip()返回修剪左右两侧空格之后的字符串' jackfrued@126.com '.strip() 输出结果jackfrued@126.com\n列表\n列表list是一种结构化的、非标量类型它是值的有序序列每个值都可以通过索引进行标识定义列表可以将列表的元素放在 [] 中,多个元素用 , 进行分隔,可以使用 for 循环对列表元素进行遍历,也可以使用 [] 或 [:] 运算符取出列表中的一个或多个元素。\n定义\n# 列表定义\nlist1 = [ 'abcd', 786, 2.23, 'runoob', 70.2 ]\ntinylist = [123, 'runoob']\n \n# 输出完整列表\nprint(list1) # 输出结果:['abcd', 786, 2.23, 'runoob', 70.2]\n \n# 输出列表第一个元素\nprint(list1[0]) # 输出结果:'abcd'\n \n# 从第二个开始输出到第三个元素\nprint(list1[1:3]) # 输出结果:[786, 2.23]\n \n# 输出从第三个元素开始的所有元素\nprint(list1[2:]) # 输出结果:[2.23, 'runoob', 70.2]\n \n# 输出两次列表\nprint(tinylist * 2) # 输出结果:[123, 'runoob', 123, 'runoob']\n \n# 连接列表\nprint(list1 + tinylist) # 输出结果:['abcd', 786, 2.23, 'runoob', 70.2, 123, 'runoob']\n \n# 通过循环用下标遍历列表元素\nfor index in range(len(list1)):\n print(list1[index])\n \n# 通过for 循环遍历列表元素\nfor elem in list1:\n print(elem)\n \n# 通过 enumerate 函数处理列表之后再遍历可以同时获得元素索引和值\nfor index, elem in enumerate(list1):\n print(index, elem)\n运算\n# 创建列表\nlist1 = [1, 2, 3]\nlist2 = [4, 5, 6]\n \n# 连接列表,返回一个新的列表\nlist3 = list1 + list2\nprint(list3) # 输出:[1, 2, 3, 4, 5, 6]\n \n# 复制列表,返回一个新的列表\nlist4 = list1 * 3\nprint(list4) # 输出:[1, 2, 3, 1, 2, 3, 1, 2, 3]\n \n# 计算元素个数\nlength = len(list1)\nprint(length) # 输出3\n \n# 判断元素是否在列表中\nresult = 4 in list1\nprint(result) # 输出False\n \nresult = 2 in list1\nprint(result) # 输出True\n \n# 访问元素可以使用索引索引从0开始\nelem = list1[0]\nprint(elem) # 输出1\n \n# 切片操作\nlist5 = list1[1:3]\nprint(list5) # 输出:[2, 3]\n \n# 切片时可以指定步长\nlist6 = list1[0:3:2]\nprint(list6) # 输出:[1, 3]\n \n# 切片时可以省略开始或结束索引\nlist7 = list1[:2]\nlist8 = list1[1:]\nprint(list7) # 输出:[1, 2]\nprint(list8) # 输出:[2, 3]\n \n# 反向切片\nlist9 = list1[::-1]\nprint(list9) # 输出:[3, 2, 1]\n \n# 修改元素值\nlist1[0] = 100\nprint(list1) # 输出:[100, 2, 3]\n \n# 列表末尾添加元素\nlist1.append(4)\nprint(list1) # 输出:[100, 2, 3, 4]\n \n# 列表末尾删除元素\nlist1.pop()\nprint(list1) # 输出:[100, 2, 3]\n \n# 指定位置插入元素\nlist1.insert(1, 200)\nprint(list1) # 输出:[100, 200, 2, 3]\n \n# 删除指定位置的元素\ndel list1[2]\nprint(list1) # 输出:[100, 200, 3]\n \n# 清空列表\nlist1.clear()\nprint(list1) # 输出:[]\n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述len(list)返回列表元素的个数。list.append(x)在列表末尾添加元素 x。list.insert(i, x)在指定位置 i 前插入元素 x。list.extend(iterable)将可迭代对象中的元素逐个添加到列表。list.remove(x)删除列表中第一个值为 x 的元素。list.pop([i])移除并返回列表中指定位置 i 处的元素。如果未指定索引默认删除并返回最后一个元素。list.clear()清空列表中的所有元素。list.index(x[, start[, end]])返回列表中第一个值为 x 的元素的索引。如果未找到该元素,会引发 ValueError 异常。list.count(x)返回元素 x 在列表中出现的次数。list.sort(key=None, reverse=False)对列表进行排序,如果指定参数 key 则按照 key 进行排序,如果指定参数 reverse 则为降序。list.reverse()将列表中的元素倒序排列。list.copy()返回列表的浅拷贝,即创建一个新列表并复制原列表中的元素。\n元组\nPython 中的元组是一种容器数据类型,使用小括号 () 定义,类似于列表,但元组的元素不能修改,是不可变的。元组用于存储多个数据,可以包含不同类型的元素。与列表不同,元组在定义时可以省略括号,但在实际使用中建议加上括号,以增强代码的可读性。\n\n定义\n# 定义元组\nt = ('骆昊', 38, True, '四川成都')\n \n# 定义空元组\nt1 = ()\n \n# 元组中只包含一个元素时,需要在元素后面添加逗号 `,`,否则括号会被当作运算符使用。\ntup1 = (50) # 不加逗号,类型为整型\ntup1 = (50,) # 加上逗号,类型为元组\n \n# 遍历元组中的值\nfor member in t:\n print(member)\n \n# 重新给元组赋值\n# t[0] = '王大锤' # TypeError元组不可修改\n# 变量t重新引用了新的元组原来的元组将被垃圾回收\nt = ('王大锤', 20, True, '云南昆明')\n \n# 将元组转换成列表\nperson = list(t)\n \n# 将列表转换成元组\nfruits_list = ['apple', 'banana', 'orange']\nfruits_tuple = tuple(fruits_list)\n \n# 创建一个新的元组\ntup1 = (12, 34.56)\ntup2 = ('abc', 'xyz')\ntup3 = tup1 + tup2\n \n# 删除元组\ntup = ('Google', 'Runoob', 1997, 2000)\ndel tup\n运算\n# 创建元组\ntup1 = (1, 2, 3)\ntup2 = (4, 5, 6)\n \n# 连接元组,返回一个新的元组\ntup3 = tup1 + tup2\nprint(tup3) # 输出:(1, 2, 3, 4, 5, 6)\n \n# 复制元组,返回一个新的元组\ntup4 = tup1 * 3\nprint(tup4) # 输出:(1, 2, 3, 1, 2, 3, 1, 2, 3)\n \n# 计算元素个数\nlength = len(tup1)\nprint(length) # 输出3\n \n# 判断元素是否在元组中\nresult = 4 in tup1\nprint(result) # 输出False\n \nresult = 2 in tup1\nprint(result) # 输出True\n \n# 访问元素可以使用索引索引从0开始\nelem = tup1[0]\nprint(elem) # 输出1\n \n# 切片操作\ntup5 = tup1[1:3]\nprint(tup5) # 输出:(2, 3)\n \n# 切片时可以指定步长\ntup6 = tup1[0:3:2]\nprint(tup6) # 输出:(1, 3)\n \n# 切片时可以省略开始或结束索引\ntup7 = tup1[:2]\ntup8 = tup1[1:]\nprint(tup7) # 输出:(1, 2)\nprint(tup8) # 输出:(2, 3)\n \n# 反向切片\ntup9 = tup1[::-1]\nprint(tup9) # 输出:(3, 2, 1)\n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述len(tuple)返回元组中元素的个数。tuple.count(x)返回元组中元素 x 出现的次数。tuple.index(x[, start[, end]])返回元组中第一个值为 x 的元素的索引。如果未找到该元素,会引发 ValueError 异常。tuple + tuple将两个元组连接成一个新的元组。tuple * n将元组重复 n 次。x in tuple判断元素 x 是否在元组中,如果在返回 True否则返回 False。x not in tuple判断元素 x 是否不在元组中,如果不在返回 True否则返回 False。\n集合\n集合set是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。\n定义\n集合可以通过花括号 {} 或 set() 函数创建。注意,创建空集合只能用 set(),不能用 {},因为 {} 创建的是空字典。\n# 创建集合\nset1 = {1, 2, 3, 4, 5}\nset2 = {3, 4, 5, 6, 7}\nset3 = {5, 6, 7, 8, 9}\n \n# 判断元素是否在集合内\n3 in set1 # True\n10 in set1 # False\n \n# 添加元素\nset1.add(6) # {1, 2, 3, 4, 5, 6}\nset1.add(7) # {1, 2, 3, 4, 5, 6, 7}\nset1.add(3) # {1, 2, 3, 4, 5, 6, 7},重复的元素不会被添加\n \n# 删除元素\nset1.remove(4) # {1, 2, 3, 5, 6, 7}\nset1.discard(6) # {1, 2, 3, 5, 7}\nset1.discard(8) # {1, 2, 3, 5, 7}如果元素不存在discard 方法不会引发异常\n \n# 元素个数\nlen(set1) # 5\n \n# 清空集合\nset1.clear() # set()\n运算\nset1 = {1, 2, 3, 4, 5}\nset2 = {3, 4, 5, 6, 7}\nset3 = {5, 6, 7, 8, 9}\n \n# 交集\nset1 & set2 # {3, 4, 5}\n \n# 并集\nset1 | set2 # {1, 2, 3, 4, 5, 6, 7}\n \n# 差集\nset1 - set2 # {1, 2}\n \n# 对称差运算(在 set1 或 set2 中,但不会同时出现在二者中)\nset1 ^ set2 # {1, 2, 6, 7}\n \n# 判断子集和超集\nset2 <= set1 # Falseset2 是 set1 的子集吗?\nset3 <= set1 # Falseset3 是 set1 的子集吗?\nset1 >= set2 # Falseset1 是 set2 的超集吗?\nset1 >= set3 # Falseset1 是 set3 的超集吗?\n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述set.add(x)将元素 x 添加到集合中set.remove(x)删除集合中的元素 x如果 x 不在集合中会引发 KeyErrorset.discard(x)删除集合中的元素 x如果 x 不在集合中不会引发异常set.pop()随机删除集合中的一个元素并返回删除的元素set.clear()清空集合中的所有元素len(set)返回集合中元素的个数x in set判断元素 x 是否在集合中,如果在返回 True否则返回 Falseset1.isdisjoint(set2)判断两个集合是否没有共同的元素,如果没有返回 True否则返回 Falseset1.issubset(set2)判断集合 set1 是否是集合 set2 的子集,如果是返回 True否则返回 Falseset1.issuperset(set2)判断集合 set1 是否是集合 set2 的超集,如果是返回 True否则返回 Falseset1.union(set2)返回集合 set1 和 set2 的并集set1.intersection(set2)返回集合 set1 和 set2 的交集set1.difference(set2)返回集合 set1 和 set2 的差集,即在 set1 中但不在 set2 中的元素set1.symmetric_difference(set2)返回集合 set1 和 set2 的对称差集,即在 set1 或 set2 中但不会同时出现在二者中的元素set1.update(set2)将集合 set2 中的元素添加到 set1 中set1.intersection_update(set2)将集合 set1 中不在 set2 中的元素删除set1.difference_update(set2)将集合 set1 和 set2 的差集中的元素从 set1 中删除set1.symmetric_difference_update(set2)将集合 set1 和 set2 的对称差集中的元素添加到 set1 中set.copy()返回集合的浅拷贝set.pop()随机删除并返回集合中的一个元素\n字典\n\n字典是另一种可变容器模型且可存储任意类型对象。字典与列表、集合不同的是它是一种键 - 值key-value对应的数据结构。每个元素都是由一个键和一个值组成的键值对键和值通过冒号分开。键必须是唯一的但值则不必。\n\n定义\n# 使用大括号创建字典\nperson = {'name': 'John', 'age': 30, 'city': 'New York'}\n \n# 使用 dict() 创建字典\nempty_dict = dict()\n \n# 访问字典中的元素\nprint(person['name']) # 输出John\nprint(person['age']) # 输出30\nprint(person['city']) # 输出New York\n运算\n# 修改字典中的元素\nperson['age'] = 31\nprint(person) # 输出:{'name': 'John', 'age': 31, 'city': 'New York'}\n \n# 添加新的键值对\nperson['job'] = 'Engineer'\nprint(person) # 输出:{'name': 'John', 'age': 31, 'city': 'New York', 'job': 'Engineer'}\n \n# 删除字典中的元素\ndel person['city']\nprint(person) # 输出:{'name': 'John', 'age': 31, 'job': 'Engineer'}\n \n# 清空字典\nperson.clear()\nprint(person) # 输出:{}\n \n# 遍历字典的键\nfor key in person:\n print(key)\n \n# 遍历字典的值\nfor value in person.values():\n print(value)\n \n# 遍历字典的键值对\nfor key, value in person.items():\n print(key, value)\n \n# 判断键是否存在\nif 'name' in person:\n print("Name exists.")\n \n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述keys()返回字典所有键的列表values()返回字典所有值的列表items()返回字典所有键值对的元组列表get(key, default=None)返回指定键的值如果键不存在返回默认值pop(key)删除指定键的值并返回该键对应的值popitem()随机删除一个键值对并返回该键值对clear()删除字典中的所有键值对update(other_dict)将其他字典的键值对更新到当前字典copy()返回字典的浅拷贝(复制字典中的键值对)\n推导式\n推导式是一种强大的 Python 特性,可以快速、简洁地创建新的数据序列。它可以从一个数据序列构建另一个新的数据序列的结构体。\n列表\n列表推导式是最常用的推导式它通过在一个可迭代对象上应用表达式来创建一个新的列表。\n# 语法\nnew_list = [out_exp_res for out_exp in input_list]\nnew_list = [out_exp_res for out_exp in input_list if condition]\n \n# 示例\nmultiples = [i for i in range(30) if i % 3 == 0]\nprint(multiples) # 输出:[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]\n字典\n# 语法\nnew_dict = {key_expr: value_expr for value in collection}\nnew_dict = {key_expr: value_expr for value in collection if condition}\n \n# 示例\ndic = {x: x**2 for x in (2, 4, 6)}\nprint(dic) # 输出:{2: 4, 4: 16, 6: 36}\n集合\n# 语法\nnew_set = {expression for item in sequence}\nnew_set = {expression for item in sequence if conditional}\n \n# 示例\na = {x for x in 'abracadabra' if x not in 'abc'}\nprint(a) # 输出:{'d', 'r'}\n元组\n# 语法\nnew_tuple = (expression for item in sequence)\nnew_tuple = (expression for item in sequence if conditional)\n \n# 示例\na = (x for x in range(1, 10))\nprint(a) # 输出:<generator object <genexpr> at 0x7f900dfdd200>\nprint(tuple(a)) # 输出:(1, 2, 3, 4, 5, 6, 7, 8, 9)\n其他\nf = [x for x in range(1, 10)]\nprint(f)\n \nf = [x + y for x in 'ABCDE' for y in '1234567']\nprint(f)\n \nf = [x ** 2 for x in range(1, 1000)]\nprint(sys.getsizeof(f)) # 查看对象占用内存的字节数\nprint(f)\n \n# 生成器表达式,不占用额外内存\nf = (x ** 2 for x in range(1, 1000))\nprint(sys.getsizeof(f)) # 相比列表生成式,生成器不占用存储数据的空间\nprint(f)\nfor val in f:\n print(val)\n \n迭代器\n可迭代对象是 Python 中的一种数据结构,例如列表、元组、字典、字符串等都是可迭代对象。迭代器是一种特殊的可迭代对象,它可以通过调用 iter() 函数获取,然后使用 next() 函数逐个访问元素。迭代器在其生命周期中会有四个状态GEN_CREATED、GEN_RUNNING、GEN_SUSPENDED 和 GEN_CLOSED。\ngraph LR\n A[生成器已创建] --> B[解释器执行中]\n B --> C[在 yield 表达式处暂停]\n C --> D[解释器执行中]\n D --> C\n D --> E[生成器执行结束]\n\n\niter():创建迭代器。\nnext():输出迭代器的下一个元素。\n\ns = 'abc'\nit = iter(s)\n \nprint(it) # 输出:<str_iterator object at 0x10c90e650>\nprint(next(it)) # 输出:'a'\nprint(next(it)) # 输出:'b'\nprint(next(it)) # 输出:'c'\n \n# 抛出异常\n# 迭代器用尽后会引发 StopIteration 异常\ntry:\n print(next(it))\nexcept StopIteration:\n print("迭代器用尽了。")\n \n生成器\n生成器是一种特殊的迭代器它是一个可以像迭代器一样使用 for 循环来获取元素的函数。生成器函数使用 yield 关键字将一个普通函数改造成生成器函数yield 相当于 return 但有所不同yield 虽然返回了值但函数并没有结束,而是暂停在 yield 处,下次调用 next() 或循环迭代时会从 yield 处继续执行。生成器在其生命周期中会有四个状态GEN_CREATED、GEN_RUNNING、GEN_SUSPENDED 和 GEN_CLOSED。\ngraph LR\n A[生成器函数被调用] --> B[生成器已创建]\n B --> C[解释器执行中]\n C --> D[在 yield 表达式处暂停]\n D --> C\n C --> E[生成器执行结束]\n\n F[生成器已创建] --> G[GEN_CREATED]\n G --> H[生成器正在执行]\n H --> I[GEN_RUNNING]\n I --> J[在 yield 表达式处暂停]\n J --> H\n I --> K[生成器执行结束]\n K --> L[GEN_CLOSED]\n\n生成器在其生命周期中会有如下四个状态\n\nGEN_CREATED生成器已创建还未被激活。\nGEN_RUNNING解释器正在执行只有在多线程应用中才能看到这个状态。\nGEN_SUSPENDED在 yield 表达式处暂停。\nGEN_CLOSED生成器执行结束。\n\ndef fibonacci(n):\n a, b, counter = 0, 1, 0\n while True:\n if counter > n:\n return\n yield a\n a, b = b, a + b\n counter += 1\n \nfor i in fibonacci(10):\n print(i, end=" ") # 输出0 1 1 2 3 5 8 13 21 34 55"},"Technology/ProgrammingLanguage/Python/入门/模块和包":{"title":"模块和包","links":[],"tags":["Python/入门","技术/程序语言"],"content":"在编程语言中,我们常常会看到各种不同级别的封装,如代码块、函数、类、模块,甚至包,每个级别都会进行逐级调用。在 Python 中,一个 .py 文件就被看作是一个模块。这实际上是比类级别更高的封装。在其他的编程语言中,被导入的模块通常被称为库。\n模块\n在 Python 中,模块可以分为自定义模块、内置模块(标准模块)和第三方模块。使用模块主要有以下几个好处:\n\n提高了代码的可维护性。通过将代码拆分为多个模块可以降低每个模块的复杂性更容易进行理解和维护。\n重用代码。当一个模块编写完毕就可以被其他的模块引用。这避免了“重复造轮子”允许开发者更加专注于新的任务。\n避免命名冲突。同名的类、函数和变量可以分别存在于不同的模块中防止名称冲突。但也要注意尽量避免与内置函数名类名冲突。\n\n自定义模块\n自定义模块是开发者根据实际需求编写的代码封装为模块方便在多个地方使用。当创建一个新的 Python 文件时,比如 mymodule.py我们就创建了一个名为 mymodule 的模块,可以通过 import mymodule 来导入和使用。\n# mymodule.py\ndef hello():\n print("Hello, World!")\n# main.py\nimport mymodule\n \nmymodule.hello() # 输出 "Hello, World!"\n标准模块\nPython 拥有一个强大的标准库。Python 语言的核心只包含数值、字符串、列表、字典、文件等常见类型和函数,而由 Python 标准库提供了系统管理、网络通信、文本处理、数据库接口、图形系统、XML 处理等额外的功能。如文本处理、文件系统操作、操作系统功能、网络通信、W3C 格式支持等。\nPython 标准库中的模块可以直接通过 import 语句来导入。比如,我们可以导入 math 模块,使用其中的 sqrt 函数来求平方根:\nimport math\n \nprint(math.sqrt(16)) # 输出 4.0\n第三方模块\nPython 拥有大量的第三方模块,这也是其核心优点之一。这些模块通常在 Python 包管理系统 PyPI 中注册,你可以通过 pip 工具来安装。\n比如我们可以通过 pip install requests 来安装 requests 模块,然后在代码中使用它发送 HTTP 请求:\nimport requests\n \nresponse = requests.get('www.python.org')\nprint(response.status_code) # 输出 200\n包\nPython 为了避免模块名冲突又引入了按目录来组织模块的方法称为包Package。包是模块的集合比模块又高一级的封装。包是一个分层次的文件目录结构它定义了一个由模块及子包和子包下的子包等组成的 Python 的应用环境。一般来说,包名通常为全部小写,避免使用下划线。\n标准包\n标准包就是文件夹下必须存在 __init__.py 文件该文件的内容可以为空。如果没有该文件Python 无法识别出标准包。Python 中导入包后会初始化并执行 __init__.py 进行初始化;在 __init__.py 中,如果将 __all__ 定义为列表,其中包含对象名称的字符串,程序就可以通过 * 的方式导入。\n例如我们有以下的目录结构\ntest.py\npackage_runoob\n|-- __init__.py\n|-- runoob1.py\n|-- runoob2.py\n它们的代码如下\n# package_runoob/runoob1.py\ndef runoob1():\n print("I'm in runoob1")\n \n# package_runoob/runoob2.py\ndef runoob2():\n print("I'm in runoob2")\n \n# package_runoob/__init__.py\nif __name__ == '__main__':\n print('作为主程序运行')\nelse:\n print('package_runoob 初始化')\n \n# test.py\nfrom package_runoob.runoob1 import runoob1\nfrom package_runoob.runoob2 import runoob2\n \nrunoob1()\nrunoob2()\n \n# 输出\n# package_runoob 初始化\n# I'm in runoob1\n# I'm in runoob2\n模块和包的导入\nPython 模块是一个包含 Python 定义和语句的文件,模块可以定义函数,类和变量。模块也可以包含可执行的代码。包是一种管理 Python 模块命名空间的形式,采用 ” 点模块名称 “。\n导入方式\n在 Python 中,可以通过以下四种方式导入模块或包:\nimport xx.xx\n这种方式将整个模块导入。如果模块中有函数、类或变量我们需要以 module.xxx 的方式调用。\n# Module_a.py\n \ndef func():\n print("This is module A!") \n \n# Main.py\n \nimport module_a\nmodule_a.func() # 调用函数\nfrom xx.xx import xx\n这种方式从某个模块中导入某个指定的部分到当前命名空间不会将整个模块导入。这种方式可以节省代码量但需要注意避免名字冲突。\n# Main.py\n \nfrom module_a import func\nfunc() # 直接调用 func\nfrom xx.xx import xx as rename\n为了避免命名冲突我们可以在导入时重命名模块。\n# Main.py\n \nfrom module_a import func as f\nf() # 使用新名称 f 来调用函数\nfrom xx.xx import \\*\n这种方式将模块中的所有内容全部导入非常容易发生命名冲突因此需要谨慎使用。\n# Main.py\n \nfrom module_a import *\n \ndef func():\n print("This is the main module!")\n \nfunc() # func 从 module_a 导入被 main 中的 func 覆盖\n绝对导入\n绝对导入使用模块的完整路径来导入。这个路径是从项目的根目录开始的也就是说从 Python 解释器开始搜索模块的路径。让我们通过一个示例来理解绝对导入。\n假设我们有以下项目结构\nmyproject/\n│\n├── main.py\n│\n└── mypackage/\n ├── __init__.py\n ├── module_a.py\n └── subpackage/\n ├── __init__.py\n └── module_b.py\n在这个项目中我们有一个主程序 main.py 和一个包 mypackage包含了模块 module_a.py 和一个子包 subpackage包含了模块 module_b.py。\n在 main.py 中,我们可以使用绝对导入来导入 module_a.py\n# main.py\nimport mypackage.module_a\n在这里mypackage 是项目的根目录,所以我们使用完整的路径来导入 module_a。\n同样在 module_b.py 中,我们可以使用绝对导入来导入 module_a.py\n# mypackage/subpackage/module_b.py\nimport mypackage.module_a\n适用场景\n绝对导入的适用场景包括\n\n明确绝对导入提供了清晰的模块路径使得其他开发人员更容易理解模块之间的关系。\n项目结构不变当项目结构发生变化时绝对导入不需要更新导入路径。\n可移植性如果一个包被设计成可以独立安装并作为第三方库使用绝对导入是更好的选择。\n\n相对导入\n相对导入是基于当前模块文件的目录结构的。使用 . 表示当前目录,.. 表示父目录,以此类推。相对导入通常用在包内部,当模块之间互相导入时。让我们通过示例来理解相对导入。\n在 module_b.py 中,我们可以使用相对导入来导入同一包下的 module_a.py\n# mypackage/subpackage/module_b.py\nfrom .. import module_a\n在这里.. 表示上一级目录,即 mypackage然后我们导入了 module_a。\n注意事项\n相对导入需要一些额外的注意事项\n\n相对导入只能用于包内部模块之间的导入不能用于顶级模块或脚本。\n如果直接运行一个包含相对导入的模块可能会导致 ImportError。\n\n适用场景\n相对导入通常更适合以下情况\n\n包内部导入当你在包内部工作时相对导入可以更好地保持模块的封装性和可移植性。\n封装和模块重构相对导入在包内部重构时特别有用因为它减少了需要更改的导入语句的数量。\n\n模块路径搜索顺序\n当我们尝试导入一个模块时Python 解释器对模块位置的搜索顺序是:\n\nPython 项目的当前目录\n在环境变量 PYTHONPATH 中列出的所有目录\nPython 的安装目录和其他默认目录\n\n模块搜索路径存储在 sys 模块的 sys.path 变量中。\nimport sys\nprint(sys.path)\n命名空间和作用域\n在 Python 中命名空间Namespace是从名称到对象的映射主要用于避免命名冲突。命名空间的生命周期取决于对象的作用域如果对象执行完成则该命名空间的生命周期就结束。\n命名空间类型\nPython 有三种命名空间:\n\n内置名称built-in namesPython 语言内置的名称,如函数名 abs、char 和异常名称 BaseException、Exception 等。\n全局名称global names模块中定义的名称包括模块的函数、类、导入的模块、模块级别的变量和常量。\n局部名称local names函数中定义的名称包括函数的参数和局部定义的变量。\n\n\n作用域\n作用域定义了命名空间可以直接访问的代码段决定了在哪一部分程序可以访问特定的变量名。Python 的作用域一共有 4 种,分别是:\n\n\nLLocal最内层包含局部变量比如一个函数/方法内部。\nEEnclosing包含了非局部non-local也非全局non-global的变量。比如两个嵌套函数一个函数或类A 里面又包含了一个函数 B那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。\nGGlobal当前脚本的最外层比如当前模块的全局变量。\nBBuilt-in 包含了内建的变量/关键字等,最后被搜索。\n\n变量的查找顺序是L ⇒ E ⇒ G ⇒ B。\n代码示例\n# 全局变量\nx = 10\nz = 40\n \n# 定义函数 foo\ndef foo():\n # 局部变量\n x = 20\n z = 50\n \n def bar():\n nonlocal z\n print("局部变量 z =", z) # 输出 "局部变量 z = 50"\n \n def baz():\n global z\n print("全局变量 z =", z) # 输出 "全局变量 z = 40"\n \n print("局部变量 x =", x) # 输出 "局部变量 x = 20"\n bar()\n baz()\n \n# 定义函数 outer\ndef outer():\n y = 30 # 封闭作用域变量\n \n def inner():\n nonlocal y\n print("封闭作用域 y =", y) # 输出 "封闭作用域 y = 30"\n \n inner()\n \n# 执行函数\nfoo()\nprint("全局变量 x =", x) # 输出 "全局变量 x = 10"\nouter()\n \n# 调用内置函数\nprint(abs(-5)) # 输出 5\n这个例子展示了 Python 中的作用域和命名空间的概念。在函数 foo 中,变量 x 和 z 是局部变量,只在 foo 函数内部可见。函数 bar 和 baz 改变了 z 的作用域bar 定义 z 为封闭作用域foo 函数的作用域),而 baz 定义 z 为全局作用域。函数 outer 和 inner 展示了封闭作用域变量的使用outer 函数内的 y 变量在 inner 函数中也可见。\n最后我们调用了内置函数 abs这是一个内置命名空间的例子。所有的内置函数和关键字都在 Python 的内置命名空间中,无需导入就可以直接使用。"},"Technology/ProgrammingLanguage/Python/入门/面对对象":{"title":"面对对象","links":[],"tags":["Python/入门","技术/程序语言"],"content":"面向对象编程Object-Oriented ProgrammingOOP是一种编程范式或模型以「对象」作为核心来设计和实现软件。这种方法主要的目标是将数据和处理数据的函数结合在一起封装成独立的软件模块我们称之为「对象」。面向对象编程被广泛应用于多种编程语言中包括 Python。\n基本概念\n理念和用途\n**面向对象编程是在更高的抽象层次上思考问题的一种方式。**面向对象编程的主要理念是,将现实世界中的对象抽象化,将对象的属性(也叫状态)和行为(也叫方法)封装在一起。面向对象编程的思考方式,更贴近我们对现实世界的认知。\n面向对象编程的主要优点包括\n\n代码复用性类的定义一旦完成就可以在任何地方创建其对象复用类的属性和方法而无需重复编写代码。通过类之间的继承关系子类可以继承父类的代码从而实现代码的复用。\n代码的可维护性和可扩展性面向对象编程的封装特性保护了对象内部的数据使得代码更安全更易于维护。通过类的继承和多态可以轻松实现对现有代码的扩展。\n\n特点\n面向对象编程有三个主要的特点封装、继承、和多态。\n\n封装封装是指将对象的状态数据和行为方法包装在一起隐藏对象的内部实现细节仅对外提供必要的接口。这样可以保护对象的内部状态提高代码的安全性也提高了代码的可维护性。\n继承继承是指子类可以继承父类的属性和方法。继承让我们可以在父类的基础上进行扩展实现代码的复用提高代码的可扩展性。\n多态多态是指不同类的对象对同一消息会做出不同的响应。多态提供了统一的接口使得我们可以使用一致的方式处理不同类的对象提高了代码的灵活性。\n\nPython 中的类和对象\n在 Python 中,我们使用 class 关键字来定义类。类是一种数据类型,它定义了一种新的对象,这种对象具有自己的属性和方法。\n类和对象的概念\n\n类 (Class) 类是对象的蓝图或原型。你可以想象成是创建对象的模板,它定义了特定类型的对象的属性和方法。\n\n# 一个简单的 Python 类的例子\nclass Dog:\n pass\n\n对象 (Object):对象是类的实例。具体来说,当我们根据类的定义创建了一个实例后,这个实例就是一个对象。每个对象都具有类定义的属性和方法。\n\n# 创建Dog类的一个实例\nmy_dog = Dog()\n我们可以通过创建类的实例也就是对象来使用类的属性和方法。\n类的属性和方法\n类的属性和方法是类的主要组成部分。属性用于描述类和其实例的状态方法用于描述类和其实例可以进行的操作。\n在 Python 中,我们可以在类中定义两种类型的属性和方法:\n\n实例属性和方法实例属性和方法属于类的实例。每个实例都有自己的实例属性这些属性与其他实例的属性互不影响。实例方法可以通过实例来调用它可以访问和修改实例的属性。\n\n# 在Python类中定义实例属性和方法的例子\nclass Dog:\n def __init__(self, name):\n self.name = name # 实例属性\n \n def bark(self): # 实例方法\n return f"{self.name} says woof!"\n \n\n类属性和方法类属性和方法是属于类本身的所有的实例都会共享同一个类属性。类方法可以通过类名直接调用也可以通过实例调用但是它不能访问和修改实例属性。\n\n# 在Python类中定义类属性和方法的例子\nclass Dog:\n species = "Canis familiaris" # 类属性\n \n @classmethod\n def description(cls): # 类方法\n return "This class represents a dog."\n \n__init__\n在 Python 中使用 __init__ 方法来初始化类的实例。这个方法会在创建实例时自动调用,我们可以在这个方法中设置实例的初始状态,也就是定义实例的属性。\n__init__ 方法的第一个参数始终是 self代表了实例本身。在 __init__ 方法中,我们使用 self.属性名 来定义实例属性。\nclass Dog:\n def __init__(self, name, age):\n self.name = name\n self.age = age\n封装\n概念和用途\n封装这是面向对象编程OOP中的基本概念之一其目标是通过将数据对象的状态和对象的行为组合在一起来隐藏或封装对象内部的详细信息。简单地说封装就是把客户端代码对象的使用者从对象的内部细节中解耦出来。\n封装的主要优势包括\n\n提高了代码的安全性封装可以防止对象状态的无意义或不合适的修改。只有通过定义好的方法有时被称为 getter 和 setter )才能修改状态,这些方法可以控制对对象状态的更改,从而保证其正确和一致。\n提高了代码的可维护性由于客户端代码从对象的内部实现中解耦出来我们可以自由地改变对象的内部实现而不会影响到使用该对象的代码。\n\nPython 中实现封装\n数据封装\n在 Python 中,我们可以通过使用私有属性(私有变量)实现数据封装。**Python 中的私有属性名字前面带有两个下划线(例如 __name。**这些属性只能在类的内部被访问,不能在类的外部直接访问,从而实现了数据的封装。\nclass Dog:\n def __init__(self, name, age):\n # __name和__age是私有属性我们不能在类的外部直接访问\n self.__name = name\n self.__age = age\n方法封装\nPython 同样可以通过私有方法实现方法的封装。私有方法的名字也以两个下划线开始,它们只能在类的内部被调用,不能在类的外部直接调用。\nclass Dog:\n def __init__(self, name, age):\n self.__name = name\n self.__age = age\n \n # __bark 是一个私有方法,我们不能在类的外部直接调用\n def __bark(self):\n return f"{self.__name} says woof!"\n尽管私有属性和方法不能在类的外部直接访问但是我们可以提供公共的 getter 和 setter 方法,让外部代码能够以受控的方式读写这些私有属性。这样我们就可以保证封装的安全性,同时也提供了一定的灵活性。\nclass Dog:\n def __init__(self, name, age):\n self.__name = name\n self.__age = age\n \n # getter for __name\n def get_name(self):\n return self.__name\n \n # setter for __name\n def set_name(self, name):\n self.__name = name\n \n # getter for __age\n def get_age(self):\n return self.__age\n \n # setter for __age\n def set_age(self, age):\n self.__age = age\n \n # __bark 是一个私有方法,我们不能在类的外部直接调用\n def __bark(self):\n return f"{self.__name} says woof!"\n \n # 公共方法可以调用私有方法\n def public_bark(self):\n return self.__bark()\n继承\n继承的概念和用途\n继承是面向对象编程中的核心概念之一。继承允许我们定义一个新的类子类或派生类来继承现有类父类或基类的属性变量和方法函数。这样我们就可以在新类中复用父类的代码避免了代码的重复同时也可以在新类中添加新的方法或对父类的方法进行重写override。\n继承的主要优点包括\n\n代码复用子类继承了父类的所有属性和方法所以我们可以通过创建子类来复用和扩展父类的代码减少了代码的重复。\n易于维护和修改由于子类可以重写父类的方法这就意味着我们可以在不改变父类的情况下改变子类的行为。这使得代码更容易维护和修改。\n\nPython 中实现继承\n单继承\n在 Python 中,我们可以通过在类定义时的括号中写入父类的名字来创建子类。新定义的类将会继承父类的所有属性和方法。\nclass Animal:\n def __init__(self, name):\n self.name = name\n \n# Dog 是 Animal 的子类,它继承了 Animal 的所有属性和方法。\nclass Dog(Animal):\n pass\n多继承\nPython 支持多继承,意味着一个类可以继承多个父类。但这可能会导致一些复杂性,如“菱形问题”。\nclass Swimming:\n def swim(self):\n return "Swims!"\n \nclass Flying:\n def fly(self):\n return "Flies!"\n \nclass Duck(Swimming, Flying):\n pass\n \nduck = Duck()\nprint(duck.swim()) # Outputs: Swims!\nprint(duck.fly()) # Outputs: Flies!\nsuper 函数\n在 Python 中super 函数是一个内置函数,它可以用来调用父类的方法。这在你需要在子类中扩展父类的方法时特别有用。\nclass Animal:\n def __init__(self, name):\n self.name = name\n \n# Dog 的 __init__ 方法中使用了 super().__init__(name) 来调用 Animal 的 __init__ 方法。\nclass Dog(Animal):\n def __init__(self, name, breed):\n super().__init__(name) # 调用父类的构造方法\n self.breed = breed # 新增的属性\n多态\n多态的概念和用途\n在面向对象编程OOP多态性是一种允许一个实体采取多种形态的能力。更具体地说多态是指通过同一个接口使用不同的实例可以产生不同的结果。这使得我们可以在运行时确定我们正在使用的对象类型然后执行相应的操作。\n多态的优势主要有两点\n\n提高代码的灵活性多态能够让我们以更一般的方式编写代码处理更广泛的数据类型而不仅仅是特定的单一数据类型。这使得我们的代码更加灵活和可维护。\n提高代码的可扩展性如果我们想要添加新的数据类型我们只需要确保它们遵循现有的接口规定。这使得我们的代码更易于扩展和改进而无需修改大量现有代码。\n促进了类之间的解耦多态允许系统在不修改现有代码的情况下添加新的对象类型。\n\nPython 中实现多态\nPython 是一种动态类型语言,意味着我们不需要明确地声明对象的类型。这就让我们在 Python 中能够非常容易地实现多态。以下是 Python 中实现多态的一些方法:\n方法重写\n在 Python 中,子类可以重写父类的方法。这就意味着,当我们在子类中调用一个父类的方法时,将会执行子类中定义的版本,而非父类中的原始版本。这使得我们可以改变子类中方法的行为,以符合我们的需求。\nclass Animal:\n def sound(self):\n return "Generic animal sound"\n \n# Dog类重写了Animal类的sound方法所以当我们调用Dog实例的sound方法时会返回"Woof!",而不是"Generic animal sound"。\nclass Dog(Animal):\n def sound(self):\n return "Woof!"\nDuck Typing\nPython 支持一种编程概念叫做 duck typing这也是实现多态的一种方法。Duck typing 的核心思想是:如果一个对象能够像鸭子一样走路,像鸭子一样叫,那么我们就可以认为它是鸭子。对于 Python 来说,如果一个对象有我们需要的方法,我们就可以使用它,而不管它是什么类型的对象(运行时类型确定)。\ndef animal_sound(animal):\n # 这个函数只关心对象是否有sound方法而不关心对象的具体类型\n return animal.sound()\n \nprint(animal_sound(Dog())) # 输出"Woof!"\nprint(animal_sound(Animal())) # 输出"Generic animal sound"\n抽象类和接口\n抽象类和接口的概念\n抽象类是一种特殊的类它不能被实例化只能被继承。抽象类中可以定义抽象方法这些方法在抽象类中没有实现在子类中必须实现。\n接口是一种特殊的抽象类它只定义了一组方法的签名没有提供任何实现。接口定义了一组行为任何实现了这些行为的类都可以说是实现了这个接口。\nPython 的 Abc 模块\n在 Python 中,我们使用 abc 模块来创建抽象类和接口。abc 模块提供了 ABC 基类和 abstractmethod 装饰器,我们可以使用它们来定义抽象类和抽象方法。\nPython 中使用抽象类和接口\n创建抽象类\n我们可以使用 ABC 基类和 abstractmethod 装饰器来创建抽象类。\nfrom abc import ABC, abstractmethod\n \n# AbstractAnimal 是一个抽象类,它有一个抽象方法 sound。\nclass AbstractAnimal(ABC):\n @abstractmethod\n def sound(self):\n pass\n创建接口\n在 Python 中,接口的概念可以通过完全由抽象方法构成的抽象类来实现。与抽象类类似,我们使用 ABC 基类和 abstractmethod 装饰器来定义接口。\nfrom abc import ABC, abstractmethod\n \n# AnimalBehaviour 是一个接口它定义了两个抽象方法eat 和 sleep。\nclass AnimalBehaviour(ABC):\n @abstractmethod\n def eat(self):\n pass\n \n @abstractmethod\n def sleep(self):\n pass\n \n实现接口\n我们可以通过继承抽象类并实现其所有的抽象方法来实现接口。\nclass Dog(AbstractAnimal, AnimalBehaviour):\n def sound(self):\n return "Woof!"\n \n def eat(self):\n return "The dog is eating."\n \n def sleep(self):\n return "The dog is sleeping.""},"Technology/ProgrammingLanguage/Python/文化/发展历史":{"title":"发展历史","links":[],"tags":["Python/文化","技术/程序语言"],"content":"\nPython 之父吉多·范罗苏姆(荷兰人 Guido van Rossum于 1982 年从阿姆斯特丹大学取得了数学和计算机硕士学位。后来他在多个研究机构工作,包括在荷兰阿姆斯特丹的国家数学和计算机科学研究学会,在马里兰州 Gaithersburg 的国家标准暨技术研究院,和维珍尼亚州 Reston 的国家创新研究公司。\n20 世纪 80 年代中期Python 之父 Guido van Rossum 还在 CWI数学和理论计算机科学领域的研究中心位于阿姆斯特丹为 ABC 语言贡献代码。ABC 语言是一个为编程初学者打造的研究项目。ABC 语言给了 Python 之父 Guido 很大影响,**Python 从 ABC 语言中继承了很多东西:比如字符串、列表和字节数列都支持索引、切片排序和拼接操作。**在 CWI 工作了一段时间后Guido 构思了一门致力于解决问题的编程语言,他觉得现有的编程语言对非计算机专业的人十分不友好。\n于是 1989 年 12 月份为了打发无聊的圣诞节假期Guido 开始写 Python 的第一个版本。值得一提的是 Python 这个名字的由来,**Python 有蟒蛇的意思,但 Guido 起这个名字完全和蟒蛇没有关系。**当 Guido 在实现 Python 的时候,他还阅读了 Monty Pythons Flying Circus 的剧本,这是来自一部来自 20 世纪 70 年代的 BBC 喜剧。Guido 认为他需要一个简短、独特且略显神秘的名字,因此他决定将该语言称为 Python。\n在 1991 年 2 月,范罗苏姆在 alt.sources 上发布了最初代码(标记为版本 0.9.0),这时就已经存在了带继承的类、异常处理、函数和核心数据类型 list、dict、str 等。在这个最初发行中就有了从 Modula-3 引进的模块系统,它的异常模型也类似于 Modula-3。\n在 1994 年 1 月 Python 达到了版本 1.0。这个发行版主要新特征是包括了由 Amrit Prem 提供的函数式编程工具 lambda、map、filter 和 reduce。Python 1.4 增加了受 Modula-3 启发的关键字参数,和对复数的内建支持,还包含了采取名字修饰的一种基本形式的数据隐藏。\nPython 2.0 于 2000 年 10 月 16 日发布,介入了列表推导式,这是从函数式编程语言 SETL 和 Haskell 中引入的。它还向垃圾收集系统增加了环检测算法,并且支持 Unicode。Python 2.1 支持了嵌套作用域就像其他静态作用域语言一样。Python 2.2 的重大革新是将 Python 的类型(用 C 写成)和类(用 Python 写成)统一入一个层级,使得 Python 的对象模型成为纯粹和一致的面向对象的模型;还增加了迭代器,受 CLU 和 Icon 启发的生成器和描述器协议。Python 2.4 加入了集合数据类型和函数修饰器。Python 2.5 加入了 with 语句。\n**Python 3.0 于 2008 年 12 月 3 日发布,它对语言做了较大修订而不能完全后向兼容。**Python 3 发行包括了 2 to 3 实用工具,它(至少部分的)自动将 Python 2 代码转换成 Python 3 代码。Python 3 的很多新特性后来也被移植到旧的 Python 2.6/2.7 版本中。\n罗苏姆作为 Python 的主要开发者,独自担负这个项目的发展决策者职责,直到 2018 年 7 月 12 日他宣布从终身仁慈独裁者BDFL的职权上“永久休假”。他在 2019 年 1 月至 11 月参与了第一届五人掌控委员会继续领导项目发展。在 2021 年 12 月,活跃的 Python 核心开发者选举 Pablo Galindo Salgado、Petr Viktorin、Thomas Wouters、Gregory P. Smith 和 Brett Cannon 为 2022 年度《掌控委员会》的五位成员来领导这个项目。\n\n来源Python - 维基百科,自由的百科全书;非商业引用,著作权归作者所有。\n"},"Technology/ProgrammingLanguage/Python/文化/生命周期":{"title":"生命周期","links":[],"tags":["Python/文化","技术/程序语言"],"content":"版本列表\n以下为官方目前支持的版本2022 年 10 月)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n版本最新微版本发布日期完全支持结束安全修复结束3.73.7.122018-06-272020-06-272023-06-273.83.8.122019-10-142021-05-032024-103.93.9.102020-10-052022-052025-103.103.10.22021-10-042023-052026-103.113.11.0a22022-10-032024-052027-103.12需要更新2023-102025-052028-10\n支持周期\n"},"Technology/ProgrammingLanguage/Python/文化/社区文化":{"title":"社区文化","links":[],"tags":["Python/文化","技术/程序语言"],"content":"Python 增强提案PEP 文档)\nPEP 是什么?\nPEPPython Enhancement ProposalPython 增强提案),它是 Python 记录 Python 变化的书面文档。PEP 文档对 Python 的作用非常重要根据讨论的主题PEP 主要有以下 3 种用途:\n\n通知汇总 Python 核心开发者需要的信息,并通知 Python 发布日程。\n标准化提供代码风格、文档或其他指导意见。\n设计对提交的功能进行说明。\n\n阅读 Python 源代码可以帮助你了解 Python 的当前的处理逻辑,读 PEP 文档可以帮助你了解 Python 设计的来龙去脉,帮助你解答如下问题:\n\nA 功能为什么要以这样的方式运行?\nPython 为什么没有 B 功能?\n\n大多数情况下关于该功能的某个 PEP 文档已经该出了上述问题的详细答案。很多提交关于 Python 语言功能的 PEP 文档并没有通过。这些文档可以作为历史资料来参考。\nPEP 0\n所有提交过的 PEP 都被汇总在一个文档中,就是 PEP 0 — Index of Python Enhancement Proposals (PEPs)。同时 PEP 0 叙述了如何共享 PEP如何提交 PEP 以及 PEP 目标。\nPEP 贡献流程\n\nA Accepted (Standards Track only) or Active proposal 已接受(仅限标准跟踪)或有效提案\nD Deferred proposal 延期提案\nF Final proposal 最终提案\nP Provisional proposal 暂定提案\nR Rejected proposal 拒绝提案\nS Superseded proposal 被取代的提案\nW Withdrawn proposal 撤回提案\n重要的 PEP\n\nPEP 8 — Style Guide for Python CodePython编码规范\nPEP 20 — The Zen of Python\n\n\n来源PEP 0 Index of Python Enhancement Proposals (PEPs) | peps.python.org非商业引用著作权归作者所有。\n\n\n来源Python改进提案PEP文档 标点符;非商业引用,著作权归作者所有。\n"},"Technology/ProgrammingLanguage/Python/文化/设计哲学":{"title":"设计哲学","links":[],"tags":["Python/文化","技术/程序语言"],"content":"# 运行此语句\n# 控制台输出显示 Python 之禅\nimport this\nThe Zen of Python, by Tim Peters\nPython 之禅,蒂姆·彼得斯 (Tim Peters)\nBeautiful is better than ugly.\n优美优于丑陋\nExplicit is better than implicit.\n明了优于隐晦\nSimple is better than complex.\n简单优于复杂\nComplex is better than complicated.\n复杂优于繁杂\nFlat is better than nested.\n扁平优于嵌套\nSparse is better than dense.\n稀疏优于稠密\nReadability counts.\n可读性很重要\nSpecial cases arent special enough to break the rules. Although practicality beats purity.\n特例亦不可违背原则即使实用比纯粹更优。\nErrors should never pass silently. Unless explicitly silenced.\n错误绝不能悄悄忽略除非它明确需要如此。\nIn the face of ambiguity, refuse the temptation to guess.\n面对不确定性拒绝妄加猜测。\nThere should be one— and preferably only one —obvious way to do it.\n任何问题应有一种且最好只有一种显而易见的解决方法。\nAlthough that way may not be obvious at first unless youre Dutch.\n尽管这方法一开始并非如此直观除非你是荷兰人。\nNow is better than never. Although never is often better than right now.\n做优于不做然而不假思索还不如不做。\nIf the implementation is hard to explain, its a bad idea.\n很难解释的必然是坏方法。\nIf the implementation is easy to explain, it may be a good idea.\n很好解释的可能是好方法。\nNamespaces are one honking great idea — lets do more of those!\n命名空间是个绝妙的主意我们应好好利用它。"},"Technology/ProgrammingLanguage/Python/文化/语言特性":{"title":"语言特性","links":[],"tags":["Python/文化","技术/程序语言"],"content":"Python 是一门跨平台的脚本语言Python 规定了一个 Python 语法规则,根据该规则可编写 Python 解释器。\nPython 属于动态语言,将 Python 程序编译成中间形式的字节码,并接着在它的虚拟机上执行,相较于 C/C++ 等编译成机器码的编译语言而言运行速度较慢。\nPython 是多范型编程语言。它完全支持结构化编程和面向对象编程,还有很多特征支持函数式编程和元编程比如元对象协议(元类和魔术方法)。通过扩展还可以支持很多范型,包括面向切面编程、契约式设计和逻辑编程。\nPython 使用动态类型,在内存管理上采用引用计数和环检测相结合的垃圾收集器。它的特征还有动态名字解析(后期绑定),即在程序执行期间绑定方法和变量的名字。\nPython 对遵循 LISP 传统的函数式编程提供了有限的支持,它提供了 map、filter 和 reduce 函数;列表推导式、字典、集合和生成器表达式。标准库中的模块 functools 和 itertools实现了从 Haskell 和 Standard ML 借鉴来的函数式工具。\nPython 的设计理念是“优雅”、“明确”、“简单”它的一些重要准被合称为“Python 之禅”。\nPython 开发者的方法论是“用一种方法,最好是只有一种方法来做一件事”,显著不同于以 Perl 语言为代表的“不止一种方法去做一件事”风格。Python 开发者在设计语言时,如果面临多种选择,一般会拒绝花俏的语法,而选择明确没有或者很少有歧义的语法。\nPyPIPython Package IndexPyPI是 Python 的正式第三方( official third-party软件套件的软件存储库。pip 是事实标准和官网推荐的用 Python 书写的软件包管理系统,它通常连接到叫做 Python 包索引的一个公开软件包在线仓库。\nPython venv 是标准库中的虚拟环境管理工具同时支持多种不同的虚拟环境管理如Virtualenv、Pipenv 等。"},"Technology/ProgrammingLanguage/Python/模块/WEB开发/Jinja-模板引擎":{"title":"Jinja 模板引擎","links":[],"tags":["Python/PyPI","技术/程序语言"],"content":"Jinja2 是一款为 Python 设计的模板引擎,版本目前最新为 3.12。它能够生成 HTML、XML、CSV、邮件等多种文本格式的文档。\nJinja2 的设计理念源自 Django 模板引擎,但在易用性、扩展性和性能上做出了大幅提升。\n安装\npip install jinja2\nJinja2 没有复杂的依赖 ,安装后可以直接导入和使用。\n核心功能\n创建模板环境\n使用 Jinja2 时 ,第一步是创建一个模板环境。模板环境包含了模板的各种配置选项 ,如全局函数、过滤器、测试等。通常一个应用只需要创建一个环境。\nfrom jinja2 import Environment PackageLoader select_autoescape\n \nenv = Environment(\n loader=PackageLoader('yourapplication' 'templates') \n autoescape=select_autoescape(['html' 'xml'])\n)\n这里我们使用 PackageLoader 加载 app/templates 目录下的模板 ,并开启了自动转义 HTML 和 XML 的功能 ,以防范 XSS 攻击。trim_blocks 选项可以去除模板代码前后的空行。\n定义模板\nJinja2 使用类 HTML 语法的模板文件 ,其中嵌入了一些特殊的语法来完成变量替换、逻辑控制等功能。例如:\n<!DOCTYPE html>\n<html>\n<head>\n <title>{{ title }}</title>\n</head>\n<body>\n <ul>\n {% for item in items %}\n <li>{{ loop.index }}: {{ item }}</li>\n {% endfor %}\n </ul>\n</body>\n</html>\n这个模板实现了一个简单的动态列表渲染 使用了变量、for 循环等模板语法。\n渲染模板\n加载一个模板并渲染只需要简单的两步\ntemplate = env.get_template('index.html')\ncontent = template.render(title='Home' items=['A' 'B' 'C'])\n这样就可以通过一个字典对象传入变量 ,生成最后的文本结果。\nJinja2 也支持模板继承 ,一个基础模板可以被多个页面模板扩展:\n{# base.html #}\n \n<!DOCTYPE html>\n<html>\n<body>\n {% block content %}\n {% endblock %} \n</body>\n</html>\n \n \n{# index.html #}\n \n{% extends "base.html" %}\n \n{% block content %}\n<p>This is Index Page.</p> \n{% endblock %}\n实践使用\n帖子应用\n以下是一个使用 FlaskPython Web 框架)和 Jinja 的简单帖子列表应用,这个应用将允许用户查看帖子列表,并点击一个帖子以查看其详细内容。\n前端部分将使用 Jinja 来生成 HTML后端部分将使用 Flask 来处理 HTTP 请求。\n首先让我们从后端开始。我们将定义一个 Flask 应用和两个路由:一个用于显示帖子列表,另一个用于显示单个帖子的详细信息。\nfrom flask import Flask render_template\n \napp = Flask(__name__)\n \nposts = [\n {'id': 1 'title': 'First Post' 'content': 'This is the first post.'} \n {'id': 2 'title': 'Second Post' 'content': 'This is the second post.'} \n # Add more posts as needed\n]\n \n@app.route('/')\ndef post_list():\n return render_template('post_list.html' posts=posts)\n \n@app.route('/post/<int:post_id>')\ndef post_detail(post_id):\n post = next((post for post in posts if post['id'] == post_id) None)\n if post is None:\n return 'Post not found' 404\n return render_template('post_detail.html' post=post)\n \nif __name__ == '__main__':\n app.run(debug=True)\n在这个后端代码中posts 是一个包含多个帖子的列表,每个帖子都是一个字典,包含一个 ID、一个标题和内容。post_list 和 post_detail 函数是两个路由处理器,分别用于显示帖子列表和单个帖子的详细信息。\n接下来让我们看看前端部分。我们将需要两个 Jinja 模板:一个用于显示帖子列表,另一个用于显示单个帖子的详细信息。\npost_list.html\n<!doctype html>\n<html>\n <head>\n <title>Post List</title>\n </head>\n <body>\n <h1>Post List</h1>\n <ul>\n {% for post in posts %}\n <li>\n <a href="{{ url_for('post_detail' post_id=post.id) }}">{{ post.title }}</a>\n </li>\n {% endfor %}\n </ul>\n </body>\n</html>\npost_detail.html\n<!doctype html>\n<html>\n <head>\n <title>{{ post.title }}</title>\n </head>\n <body>\n <h1>{{ post.title }}</h1>\n <p>{{ post.content }}</p>\n <a href="{{ url_for('post_list') }}">Back to Post List</a>\n </body>\n</html>\n在这些模板中我们使用了 Jinja 的变量、循环和函数。例如,{% for post in posts %} 循环遍历所有的帖子,{{ post.title }} 显示帖子的标题,{{ url_for('post_detail' post_id=post.id) }} 生成帖子详细信息页面的 URL。\n这就是一个简单的使用 Flask 和 Jinja 的帖子列表应用示例。你可以根据需要添加更多的功能,例如添加新的帖子、编辑现有的帖子等。\n注意**在 Flask 中Jinja 是默认的模板引擎,**所以你不需要显式创建 Jinja 的环境。如果你的模板不在默认的 templates 文件夹中,你需要在创建 Flask 应用时指定模板文件夹的路径,如下:\napp = Flask(__name__ template_folder='/path/to/your/templates')\n博客应用\n以下是一个简单的博客应用示例。首先我们定义 Flask 应用和路由app.py\nfrom flask import Flask render_template\n \napp = Flask(__name__)\n \n# 假设我们有以下博客文章\nposts = [\n {"id": 1 "title": "First Post" "content": "This is the first post."} \n {"id": 2 "title": "Second Post" "content": "This is the second post."} \n]\n \n@app.route("/")\ndef home():\n return render_template("home.html" posts=posts)\n \n@app.route("/post/<int:post_id>")\ndef post_detail(post_id):\n post = next((post for post in posts if post["id"] == post_id) None)\n if post is None:\n return "Post not found" 404\n return render_template("post_detail.html" post=post)\n \nif __name__ == "__main__":\n app.run(debug=True)\n接着我们创建一个基础模板base.html\n<!DOCTYPE html>\n<html>\n<head>\n <title>{% block title %}{% endblock %}</title>\n</head>\n<body>\n {% block content %}{% endblock %}\n</body>\n</html>\n然后定义主页模板home.html\n{% extends "base.html" %}\n \n{% block title %}\n Home\n{% endblock %}\n \n{% block content %}\n <h1>My Blog</h1>\n <ul>\n {% for post in posts %}\n <li>\n <a href="{{ url_for('post_detail' post_id=post.id) }}">\n {{ post.title }}\n </a>\n </li>\n {% endfor %}\n </ul>\n{% endblock %}\n最后定义文章详情页模板post_detail.html\n{% extends "base.html" %}\n \n{% block title %}\n {{ post.title }}\n{% endblock %}\n \n{% block content %}\n <h1>{{ post.title }}</h1>\n <p>{{ post.content }}</p>\n <a href="{{ url_for('home') }}">Back to Home</a>\n{% endblock %}\n在这个 Flask 应用示例中,它显示了一个博客文章列表,你可以点击每个文章的标题来查看文章的详细内容。所有的模板都继承自 base.html并覆盖了 title 和 content 区块。home.html 使用了一个 for 循环来显示所有的文章post_detail.html 显示了单个文章的标题和内容。\n最佳规范\n编写模板时 ,有一些最佳实践可以提高可维护性:\n\n命名规范如 index.html base.html macros.html\n模板结构HTML、逻辑、配置等区块划分清楚\n功能模块化使用宏、包含等复用代码\n注释标识如命名空间、宏参数等\n\n高级功能\n代码优化\n在 Jinja 中,一些优化技术可以帮助你提高模板的性能和可读性。例如:\n\n使用宏Macros宏类似于 Python 中的函数,可以帮助你避免重复的代码。\n\n{% macro input(name value='' type='text') %}\n <input type= {{ type }} name= {{ name }} value= {{ value }} >\n{% endmacro %}\n\n使用 include 和 extends include 和 extends 可以帮助你复用和组织模板。\n\n{% extends base.html %}\n \n{% block content %}\n <h1>{{ title }}</h1>\n <p>{{ content }}</p>\n{% endblock %}\n错误处理\n在 Jinja 中错误处理是通过抛出异常实现的。Jinja 定义了一些自己的异常,如 TemplateNotFound、TemplateSyntaxError 等。主要异常类型有:\n\nTemplateNotFound模板文件不存在\nTemplateSyntaxError模板语法错误\nUndefinedError变量未定义\nSecurityError安全错误 (如禁用标签)\n\n你可以通过捕捉这些异常来处理错误。\nfrom jinja2 import TemplateNotFound\n \ntry:\n template = env.get_template('mytemplate.html')\nexcept TemplateNotFound:\n print('Template not found')\n测试和调试\nJinja 提供了一个强大的模板调试器,可以帮助你查找和修复模板中的错误。你可以通过设置 Environment 的 debug 选项来启用调试器。\nenv = Environment(loader=... debug=True)\n当 debug 选项设置为 True 时Jinja 会在渲染模板时检查错误,并在发现错误时抛出异常。\n集成其他库\nJinja 可以与许多其他 Python 库和框架一起使用。例如Jinja 是 Flask 和 Django 这两个流行的 Web 框架的默认模板引擎。此外Jinja 也可以与诸如 Bootstrap 之类的前端框架一起使用,以创建更丰富和动态的网页。\n社区动态\nJinja 是一个活跃的开源项目,有一个活跃的开发者和用户社区。你可以在 Github 上关注 Jinja 的最新更新和发布。此外,你还可以参与 Gitter上的Jinja社区在那里你可以找到其他 Jinja 用户的帮助,分享你的经验,或者只是去看看其他人都在做什么。\n总的来说Jinja 是一个强大而灵活的模板引擎,适合用于多种应用。通过深入学习和实践,你可以充分利用 Jinja 的功能,提高你的 Web 开发效率和质量。"},"Technology/ProgrammingLanguage/Python/模块/数据处理/configparser-配置文件解析器":{"title":"configparser 配置文件解析器","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"configparser 是 Python 的标准库之一,主要用于处理配置文件,格式通常为 .ini 文件。\n配置文件\n首先要理解 .ini 文件的基本构成。.ini 文件是一种配置文件格式,它由多个 section 组成,每个 section 下面有多个 option每个 option 对应一个 value。例如\n[DEFAULT]\nServerAliveInterval = 45\nCompression = yes\nCompressionLevel = 9\nForwardX11 = yes\n \n[bitbucket.org]\nUser = hg\n \n[topsecret.server.com]\nPort = 50022\nForwardX11 = no\n读取配置文件\n要使用 configparser 读取配置文件,首先需要创建一个 ConfigParser 对象,然后使用 read() 方法读取配置文件。在读取了配置文件之后,我们可以像操作字典一样操作配置文件中的数据。如下例:\nimport configparser\n \n# 创建一个新的配置解析器\nconfig = configparser.ConfigParser()\n \n# 读取配置文件\nconfig.read('example.ini')\n \n# 获取配置文件中的信息\nsection = config['DEFAULT']\nprint(section['ServerAliveInterval']) # 输出45\n创建和编辑配置文件\nconfigparser 也可以用来创建和编辑配置文件。如果我们想添加一个新的 section可以使用 add_section() 方法。如果我们想在特定的 section 下添加或修改 option 和 value可以使用 set() 方法。最后,我们可以使用 write() 方法将更改保存到文件。如下例:\nimport configparser\n \nconfig = configparser.ConfigParser()\n \n# 添加新的 section\nconfig.add_section('new_section')\n \n# 在新的 section 下添加 option 和 value\nconfig.set('new_section', 'new_option', 'new_value')\n \n# 写入文件\nwith open('example.ini', 'w') as configfile:\n config.write(configfile)\n深入理解 Configparser\nconfigparser 还有一些更高级的用法。例如,每个 ConfigParser 对象都有一个默认的 section名为 DEFAULT。DEFAULT section 中的值会作为其他 section 的默认值。这意味着,如果其他 section 中没有定义某个 option那么 configparser 就会在 DEFAULT section 中寻找这个 option。\n此外configparser 还提供了 options() 和 items() 方法,可以用来获取一个 section 中所有的 options 和 items。has_section() 和 has_option() 方法可以用来检查特定的 section 或 option 是否存在。\nimport configparser\n \nconfig = configparser.ConfigParser()\nconfig.read('example.ini')\n \n# 检查 section 或 option 是否存在\nprint(config.has_section('new_section')) # True\nprint(config.has_option('new_section', 'new_option')) # True\n \n# 获取所有的 options 和 items\nprint(config.options('new_section')) # ['new_option']\nprint(config.items('new_section')) # [('new_option', 'new_value')]\n错误处理\n在使用 configparser 时,可能会遇到各种错误和异常。例如,如果尝试获取不存在的 section 或 optionconfigparser 就会抛出 NoSectionError 或 NoOptionError。为了使程序更加健壮我们需要学会处理这些错误和异常。\nimport configparser\n \nconfig = configparser.ConfigParser()\ntry:\n config.read('example.ini')\n print(config['nonexistent_section'])\nexcept configparser.NoSectionError:\n print('Section does not exist.')\n高级特性\nconfigparser 还支持值插值。这意味着你可以在配置文件的一个值中引用另一个值。例如:\n[Paths]\nhome_dir: //Users\nmy_dir: %(home_dir)s/lumberjack\nmy_pictures: %(my_dir)s/Pictures\n在这个例子中my_dir 的值是 /Users/lumberjackmy_pictures 的值是 /Users/lumberjack/Pictures。\n要使用插值你需要在 get() 方法中传入 raw=False。默认情况下raw 参数为 False。\nimport configparser\n \nconfig = configparser.ConfigParser()\nconfig.read('example.ini')\n \n# 使用插值\nprint(config.get('Paths', 'my_pictures', raw=False)) # 输出:/Users/lumberjack/Pictures"},"Technology/ProgrammingLanguage/Python/模块/数据处理/csv-文件读写":{"title":"csv 文件读写","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"CSV\nCSV 文件是什么\nCSVComma Separated Values字符分隔值是一种简单的文件格式用来存储表格数据如电子表格或数据库。CSV 文件由任意数量的记录组成,记录间以某种换行符分隔。每条记录由字段组成,字段间的分隔符是其他字符或字符串,最常见的是逗号或制表符。\n用途和优点\nCSV 文件常用于数据的导入导出,可以被大多数类型的软件包括文本编辑器和电子表格程序读取。其优点包括简单、易于阅读、跨平台和语言兼容。\n基本结构\nCSV 文件由行和列组成。每一行代表一个数据记录,而列则代表该记录的字段。字段的值由逗号分隔,不同的行则由换行符分隔。\nname,age,job\nJohn,25,Engineer\nAlice,30,Doctor\nPython Csv 模块\nPython 的 csv 模块提供了一种方便的方式来操作 CSV 文件。它包括了用于读取和写入 CSV 数据的函数,以及用于处理 CSV 数据的类。\n在 Python 中导入 csv 模块只需要简单的 import 语句:\nimport csv\n主要函数和类\ncsv 模块的主要函数和类有:\n\ncsv.reader():生成一个读取器对象,用于迭代读取 CSV 文件的每一行。\ncsv.writer():生成一个写入器对象,用于将数据写入 CSV 文件。\ncsv.DictReader():生成一个读取器对象,用于以字典形式读取 CSV 文件的每一行。\ncsv.DictWriter():生成一个写入器对象,用于将字典数据写入 CSV 文件。\n\n读取 CSV 文件\n使用 csv.reader() 函数读取 CSV 文件\n使用 csv.reader() 函数读取 CSV 文件的步骤如下:\n\n打开你想要读取的 CSV 文件。\n创建一个 csv.reader 对象,传入该文件对象作为参数。\n迭代 csv.reader 对象,读取文件的每一行。\n\nimport csv\n \nwith open('example.csv', 'r') as file:\n reader = csv.reader(file)\n for row in reader:\n print(row)\n**读取 CSV 文件时可能遇到的问题包括编码问题、字段格式问题等。**常见解决方法包括指定文件的编码方式、使用 try-except 块处理可能出现的错误等。\nCSV 文件的读取实例\n假设我们有一个名为 employees.csv 的 CSV 文件,内容如下:\nname,age,department\nJohn Doe,30,Engineering\nJane Smith,40,Marketing\n我们可以使用以下代码来读取这个文件\nimport csv\n \nwith open('employees.csv', 'r') as file:\n reader = csv.reader(file)\n for row in reader:\n print(f'Name: {row[0]}, Age: {row[1]}, Department: {row[2]}')\n写入 CSV 文件\n使用 csv.writer() 函数写入 CSV 文件\n使用 csv.writer() 函数写入 CSV 文件的步骤如下:\n\n打开你想要写入的 CSV 文件。\n创建一个 csv.writer 对象,传入该文件对象作为参数。\n使用 writerow() 或 writerows() 方法,将数据写入文件。\n\nimport csv\n \nwith open('example.csv', 'w', newline='') as file:\n writer = csv.writer(file)\n writer.writerow(['name', 'age', 'job'])\n writer.writerow(['John', '25', 'Engineer'])\n writer.writerow(['Alice', '30', 'Doctor'])\n**写入 CSV 文件可能遇到的问题包括权限问题、磁盘空间问题等。**常见解决方法包括检查文件写入权限、确保磁盘有足够空间等。\nCSV 文件的写入实例\n假设我们需要将以下数据写入一个名为 employees.csv 的 CSV 文件:\nemployees = [\n ['name', 'age', 'department'],\n ['John Doe', '30', 'Engineering'],\n ['Jane Smith', '40', 'Marketing']\n]\n我们可以使用以下代码来写入这个文件\nimport csv\n \nwith open('employees.csv', 'w', newline='') as file:\n writer = csv.writer(file)\n writer.writerows(employees)\nCSV 数据使用字典处理\n使用 csv.DictReader() 函数读取 CSV 文件并返回字典\ncsv.DictReader() 函数可以将 CSV 文件的每行读取为一个字典,其中列名为键,列值为值。\nimport csv\n \nwith open('example.csv', 'r') as file:\n reader = csv.DictReader(file)\n for row in reader:\n print(row)\n使用 csv.DictWriter() 函数将字典写入 CSV 文件\ncsv.DictWriter() 函数可以将字典数据写入 CSV 文件。需要先指定列名,然后调用 writeheader() 方法写入列名,最后调用 writerow() 或 writerows() 方法写入字典数据。\nimport csv\n \nwith open('example.csv', 'w', newline='') as file:\n fieldnames = ['name', 'age', 'job']\n writer = csv.DictWriter(file, fieldnames=fieldnames)\n \n writer.writeheader()\n writer.writerow({'name': 'John', 'age': '25', 'job': 'Engineer'})\n writer.writerow({'name': 'Alice', 'age': '30', 'job': 'Doctor'})\n字典和 CSV 数据的交互\n假设我们有一个名为 employees.csv 的 CSV 文件,内容如下:\nname,age,department\nJohn Doe,30,Engineering\nJane Smith,40,Marketing\n我们可以使用以下代码来读取这个文件并打印出每个员工的名字和部门\nimport csv\n \nwith open('employees.csv', 'r') as file:\n reader = csv.DictReader(file)\n for row in reader:\n print(f"Name: {row['name']}, Department: {row['department']}")\nCSV 文件中的错误和异常\n读取和写入 CSV 文件时可能遇到的错误和异常包括文件不存在、文件不可读写、磁盘空间不足等。可以使用 try-except 结构来捕获和处理这些异常。\nimport csv\n \ntry:\n with open('example.csv', 'r') as file:\n reader = csv.reader(file)\n for row in reader:\n print(row)\nexcept FileNotFoundError:\n print('File not found.')\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n错误类型错误描述解决方案FileNotFoundError找不到指定的文件。确保文件的路径和名称正确且文件确实存在。PermissionError没有足够的权限打开文件。确保你有足够的权限访问和修改文件。IsADirectoryError尝试打开的是一个目录而不是文件。确保指定的路径是文件而非目录。IOError文件读写出错例如磁盘空间不足。确保磁盘有足够的空间文件没有被其他程序锁定。csv.ErrorCSV 文件格式错误。确保 CSV 文件的格式正确例如字段是否正确分隔。UnicodeDecodeError文件编码问题。确保文件的编码和你在 Python 中指定的编码一致。"},"Technology/ProgrammingLanguage/Python/模块/数据处理/json-编码和解码器":{"title":"json 编码和解码器","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"JSON 是什么\nJSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,它基于 JavaScript 的一个子集。数据格式简洁和明了,具有易于读写的特性,常用于数据的存储和网络数据的交换。\n基本数据类型\nJSON 支持以下数据类型:\n\n数字整数或浮点数\n字符串在双引号中\n布尔值true 或 false\n数组在方括号中\n对象在大括号中\nnull\n\n一个简单的 JSON 对象示例:\n{\n "name": "John",\n "age": 30,\n "is_student": false,\n "cars": ["Ford", "BMW", "Fiat"],\n "pets": null\n}\nJSON 使用场景\nJSON 的主要用途是在服务器和 web 应用之间传输数据。由于其简洁明了的特性JSON 也被广泛用于配置文件、数据存储等场景。\nJSON 与 XML 的比较\nJSON 和 XML 都是数据存储和传输的格式。与 XML 相比JSON 更小、更快、更易解析。JSON 是语言无关的,它支持的数据结构在所有现代编程语言中都有对应的类型。而 XML 则更多地被用于文档的存储和传输。\nPython 对 JSON 的支持\nPython 标准库中的 json 模块提供了 JSON 数据的编码和解码功能。它可以将 Python 对象转换为 JSON 字符串,也可以将 JSON 字符串解码为 Python 对象。\nJson 模块的主要函数和对象\njson 模块的主要函数包括:\n\njson.dumps():将 Python 对象编码成 JSON 字符串。\njson.loads():将 JSON 字符串解码为 Python 对象。\njson.dump():将 Python 对象编码成 JSON 字符串并写入文件。\njson.load():读取文件中的 JSON 字符串并解码为 Python 对象。\n\njson 模块的主要对象包括:\n\njson.JSONEncoder用于自定义编码。\njson.JSONDecoder用于自定义解码。\n\nJSON 编码\n将 Python 对象转换为 JSON 格式。\njson.dumps() 函数\n将 Python 对象编码成 JSON 字符串。\njson.dumps() 函数接受一个 Python 对象,并返回一个 JSON 格式的字符串。例如:\nimport json\n \nperson = {\n "name": "John",\n "age": 30,\n "is_student": False,\n "cars": ["Ford", "BMW", "Fiat"],\n "pets": None\n}\n \nperson_json = json.dumps(person)\nprint(person_json)\njson.dump() 函数\n将 Python 对象编码成 JSON 字符串并写入文件。\njson.dump() 函数与 json.dumps() 功能相同,但它不返回结果,而是直接将 JSON 字符串写入一个文件对象。例如:\nimport json\n \nperson = {\n "name": "John",\n "age": 30,\n "is_student": False,\n "cars": ["Ford", "BMW", "Fiat"],\n "pets": None\n}\n \nwith open('person.json', 'w') as f:\n json.dump(person, f)\nJSON 解码\n将 JSON 格式转换为 Python 对象。\njson.loads() 函数\n将 JSON 字符串解码为 Python 对象。\njson.loads() 函数接受一个 JSON 格式的字符串,并返回一个 Python 对象。例如:\nimport json\n \nperson_json = '{"name": "John", "age": 30, "is_student": false, "cars": ["Ford", "BMW", "Fiat"], "pets": null}'\n \nperson = json.loads(person_json)\nprint(person)\njson.load() 函数\n读取文件中的 JSON 字符串并解码为 Python 对象。\njson.load() 函数与 json.loads() 功能相同,但它读取一个文件对象中的 JSON 字符串,而不是直接解码字符串。例如:\nimport json\n \nwith open('person.json', 'r') as f:\n person = json.load(f)\nprint(person)\n自定义 JSON 编码和解码\njson.JSONEncoder 类进行自定义编码\n如果你想对默认行为进行更多的控制例如改变日期时间的格式你可以自定义 json.JSONEncoder 类。例如:\nimport json\nfrom datetime import datetime\n \nclass DateTimeEncoder(json.JSONEncoder):\n def default(self, o):\n if isinstance(o, datetime):\n return o.isoformat()\n \n return super().default(o)\n \nnow = datetime.now()\njson.dumps(now, cls=DateTimeEncoder)\njson.JSONDecoder 类进行自定义解码\n同样你可以自定义 json.JSONDecoder 类来对 JSON 字符串进行特殊的解码。例如,你可以解析特定的日期时间格式:\nimport json\nfrom datetime import datetime\n \nclass DateTimeDecoder(json.JSONDecoder):\n def object_hook(self, dict_):\n for key, value in dict_.items():\n try:\n dict_[key] = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")\n except (TypeError, ValueError):\n pass\n return dict_\n \njson_string = '{"name": "John", "birthday": "2000-01-01T00:00:00"}'\njson.loads(json_string, cls=DateTimeDecoder)\n处理复杂的 JSON 数据\n使用嵌套的数据结构处理复杂的 JSON 数据\nJSON 可以表示复杂的嵌套数据结构,包括嵌套的对象和数组。你可以使用 Python 的字典、列表、元组等数据结构来处理这些复杂的 JSON 数据。\n如何处理 JSON 数据中的日期和时间\nJSON 格式本身并不支持日期和时间类型,一般以字符串形式表示。你可以在编码和解码时使用自定义的 json.JSONEncoder 和 json.JSONDecoder 类来处理日期和时间。\n如何处理 JSON 数据中的自定义对象\n你可以重写 json.JSONEncoder 的 default() 方法和 json.JSONDecoder 的 object_hook() 方法来处理自定义对象。\n错误和异常处理\n在使用 json 模块时,你可能会遇到以下几种错误和异常:\n\njson.JSONDecodeError在解码 JSON 数据时发生的错误。\nTypeError当你试图将不可序列化的对象如函数编码为 JSON 时json.dumps() 和 json.dump() 会抛出这个错误。\n\n处理错误和异常\n你可以使用 Python 的异常处理机制来处理这些错误和异常,例如:\nimport json\n \ntry:\n person_json = '{"name": "John", "age": 30, "is_student": false, "cars": ["Ford", "BMW", "Fiat"], "pets": null,'\n person = json.loads(person_json)\nexcept json.JSONDecodeError as e:\n print(f"Invalid JSON: {e}")\nexcept TypeError as e:\n print(f"Type Error: {e}")"},"Technology/ProgrammingLanguage/Python/模块/文本处理/re-----正则表达式操作":{"title":"re --- 正则表达式操作","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"Python 的 re 库是一个非常强大的工具,用于执行正则表达式操作。这意味着它可以帮助你在文本中执行复杂的模式匹配、搜索、替换和解析任务。\n正则表达式\n正则表达式是一种特殊的文本字符串用于描述搜索或匹配文本的一个模式。例如你可以用它来查找所有的电子邮件地址、电话号码或特定单词的出现。\n编写正则表达式需要学习其特殊的语法其中一些常用的元素包括\n\n字面字符大多数字符在正则表达式中表示它们自己。\n元字符如 .(匹配任何单个字符)、^(匹配字符串的开始)、$(匹配字符串的结尾)。\n字符类用方括号定义如 [a-z] 匹配任何小写字母。\n特殊序列如 \\d 匹配任何数字,\\s 匹配任何空白字符。\n\nPython 中的 re 模块\n在 Python 中re 模块提供了一系列函数和语法用于在字符串中应用正则表达式。首先,你需要导入模块:\nimport re\n基本函数\nre 模块提供了几个基本函数来处理正则表达式:\n\nre.search(pattern, string):在字符串中搜索第一个与模式匹配的部分。如果找到匹配,它返回一个匹配对象;否则返回 None。\nre.match(pattern, string):如果字符串的开始处匹配模式,返回一个匹配对象。\nre.findall(pattern, string):返回字符串中所有与模式匹配的部分的列表。\nre.sub(pattern, repl, string):替换字符串中的模式匹配项。\n\n分组捕获\n使用圆括号可以在正则表达式中创建“组”。组可以帮助你提取正则表达式匹配的部分。例如\npattern = r'(\\b\\w+)@(\\w+\\.\\w+)'\nmatch = re.search(pattern, "username@example.com")\nif match:\n print(match.group()) # 整个匹配\n print(match.group(1)) # 第一个括号内的匹配\n print(match.group(2)) # 第二个括号内的匹配"},"Technology/ProgrammingLanguage/Python/模块/系统交互/dotenv-环境变量管理":{"title":"dotenv 环境变量管理","links":[],"tags":["Python/PyPI","技术/程序语言"],"content":"在现代软件开发中,理解和正确使用环境变量是提高项目灵活性和安全性的关键。本文将全面介绍如何在 Python 项目中利用 dotenv 库高效管理环境变量,内容将由浅入深,适合各层次开发者阅读。\n环境变量\n环境变量是操作系统中用来指定操作系统运行环境的一些参数。在 Python 项目中环境变量常用于存储配置信息如数据库连接字符串、API 密钥等。这样做的好处是可以将配置与代码分离,使得应用更安全,同时也便于在不同环境(开发、测试、生产)中切换配置。\nDotenv\nPython 的 dotenv 库允许我们从一个文件中加载环境变量,而不是将它们硬编码在代码中。这使得管理私密和环境特定的数据更加安全和方便。\n安装\n开始之前需要确保 Python 环境已经搭建好。安装 dotenv 只需一条简单的命令:\npip install python-dotenv\n创建 .env\n.env 文件是一个文本文件,其中包含了键值对形式的环境变量。例如:\nDB_HOST=localhost\nDB_USER=root\nDB_PASS=s1mpl3\n\n这个文件应该放在项目的根目录下同时记得将 .env 添加到 .gitignore 文件中,避免敏感信息泄露到公共代码库。\n方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述示例代码load_dotenv()加载 .env 文件中的环境变量。默认情况下,加载当前目录下的 .env 文件。load_dotenv()dotenv_values()读取 .env 文件并返回一个包含所有环境变量的字典。config = dotenv_values(".env")find_dotenv()在文件系统中查找 .env 文件。默认从当前目录开始递归搜索直到找到为止。dotenv_path = find_dotenv()set_key()将一个新的键值对添加到 .env 文件中。set_key(".env", "KEY", "value")unset_key()从 .env 文件中删除一个键值对。unset_key(".env", "KEY")get_key()从 .env 文件中读取指定的键的值。value = get_key(".env", "KEY")\n使用\n一旦 .env 文件准备好,就可以在 Python 代码中使用 dotenv 来加载这些变量了。以下是一个简单的示例:\nfrom dotenv import load_dotenv\nimport os\n\n# 加载.env文件\nload_dotenv()\n\n# 使用环境变量\ndb_host = os.getenv("DB_HOST")\ndb_user = os.getenv("DB_USER")\ndb_pass = os.getenv("DB_PASS")\n\nprint(f"Database host: {db_host}")\n\n在这个示例中load_dotenv() 会查找并加载 .env 文件,然后可以通过 os.getenv 来访问这些变量。\n优先级\ndotenv 库在处理环境变量时,遵循一定的优先级规则,首先考虑的是系统环境变量,它们在操作系统中已设定,拥有最高优先级,并且不会被 .env 文件中的设置覆盖。接着是 .env 文件中定义的变量,仅在系统环境变量未定义相同变量时生效。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n优先级来源描述1系统环境变量在操作系统中已经设置的环境变量具有最高优先级。2.env 文件dotenv 读取的项目根目录下的 .env 文件中定义的环境变量。3其他 dotenv 配置文件如 .env.development、.env.test 等根据项目配置或命令行参数加载。4程序内部设置在程序运行时直接设置的环境变量例如使用 os.environ。这些设置只在当前程序运行期间有效。\n最佳实践和安全性\n使用环境变量的一个主要目的是提高应用程序的安全性。遵循以下最佳实践可以帮助您达到这一目的\n\n不要将 .env 文件提交到版本控制系统:确保 .env 文件在 .gitignore 中,以防止敏感信息泄露。\n在不同环境中使用不同的 .env 文件:例如,您可能会有 .env.development、.env.test 和 .env.production 文件,根据环境加载不同的配置。\n\n与框架集成\ndotenv 可以轻松地与各种 Python 框架(如 Flask 或 Django集成。例如在 Flask 应用中,可以在应用启动时加载 .env 文件:\nfrom flask import Flask\nfrom dotenv import load_dotenv\n\nload_dotenv() # 加载.env文件\napp = Flask(__name__)\n\n# 应用配置\napp.config['SECRET_KEY'] = os.getenv('SECRET_KEY')\n\n在这个例子中Flask 应用将从 .env 文件加载秘钥等配置。\n高级功能\ndotenv 库也支持一些高级功能,如类型转换和默认值。例如,您可以这样设置默认值:\nfrom dotenv import load_dotenv\nimport os\n\nload_dotenv()\n\n# 获取环境变量,如果不存在则返回默认值\ndebug_mode = os.getenv('DEBUG', 'False').lower() == 'true'\n\n在这个例子中如果 DEBUG 环境变量不存在debug_mode 将默认为 False。\n错误处理和调试\n当环境变量不存在或出现其他问题时合理的错误处理和调试非常重要。例如您可以检查变量是否被正确加载\ndb_user = os.getenv("DB_USER")\nif db_user is None:\n raise ValueError("未找到DB_USER环境变量。")\n\n这段代码将验证 DB_USER 是否被正确设置,如果没有,将抛出一个异常。"},"Technology/ProgrammingLanguage/Python/模块/系统交互/logging-日志记录工具":{"title":"logging 日志记录工具","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"简介\n**logging 模块是 Python 标准库里提供的日志功能组件,它是在开发过程中实现日志记录的推荐方式。**logging 模块主要包含四个组件Logger、Handler、Filter 和 Formatter。通过它们的协作可以快速实现对日志的控制和处理。\n组件\nLogger\n**Logger 是日志模块中最基本的组件,它负责生成和分类日志。**在应用代码中,我们可以通过 getLogger 方法获取 Logger 对象,主要有两种获取方式:\nimport logging\n \n# 1. 不指定 Logger 名称,返回 root Logger \nlogger1 = logging.getLogger()\n \n# 2. 指定名称获取 Logger \nlogger2 = logging.getLogger('test')\nHandler\nHandler 用于指定 Logger 生成的日志消息应发送到哪个目标输出,常用的 Handler 有两种:\n\nStreamHandler输出到流如 sys.stdout、sys.stderr\nFileHandler输出到文件\n\n我们可以通过 Logger 对象的 addHandler 方法将 Handler 与 Logger 关联起来:\nlogger = logging.getLogger('test')\n \n# 创建一个 Handler用于写入日志文件\nfh = logging.FileHandler('test.log')\n \n# 给 logger 添加 Handler\nlogger.addHandler(fh)\nFilter\n**Filter 用于提供复杂的日志过滤功能,可以用来过滤 INFO、DEBUG 等不同级别的日志。**根据需求,我们可以通过 logger.addFilter 将过滤器加到 logger 或者 handler 里。\n# 只记录 ERROR 及以上级别的日志\nclass ErrorFilter(logging.Filter):\n def filter(self, record):\n return record.levelno >= logging.ERROR\n \nlogger.addFilter(ErrorFilter())\nFormatter\n**Formatter 用于控制日志信息的最终输出格式。**我们可以指定日志不同部分的显示格式,如时间、代码位置、日志消息等。\n# 指定日志格式\nformatter = logging.Formatter('[%(levelname)s] %(asctime)s - %(message)s') \nhandler.setFormatter(formatter)\n基础配置\n我们可以通过字典或文件的方式配置 logging 模块。\ndictConfig 配置\nimport logging.config\n \nconfig_dict = {\n 'version': 1,\n 'formatters': {\n 'simple': {\n 'format': '[%(levelname)s] %(asctime)s - %(message)s'\n }\n },\n 'handlers': {\n 'console': {\n 'class': 'logging.StreamHandler',\n 'level': 'DEBUG',\n 'formatter': 'simple'\n },\n 'file': {\n 'class': 'logging.FileHandler',\n 'filename': 'test.log',\n 'formatter': 'simple'\n }\n },\n 'root': {\n 'level': 'DEBUG',\n 'handlers': ['console', 'file']\n }\n}\n \nlogging.config.dictConfig(config_dict)\nfileConfig 配置\n将配置字典写入 json 或 yaml 文件,通过 fileConfig 函数加载:\nimport logging.config\n \nlogging.config.fileConfig('config.yaml')\n配置参数\nlogging 模块的配置参数较多,主要包括以下方面:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数说明version配置字典的版本目前为 1disable_existing_loggers是否禁用已存在的其他日志器默认 Falseformatters定义日志信息的格式化样式filters定义过滤日志信息的过滤器handlers定义日志的处理方法以及目标位置loggers定义具体的日志器并绑定处理器和过滤器root根日志器配置其配置会应用到所有日志器上\nloggers 配置参数:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数说明level日志器接收的日志级别handlers绑定的日志处理器filters绑定的日志过滤器propagate是否传递给父日志器默认 True\nhandlers 常用参数:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数说明class指定处理器类如 FileHandler、StreamHandler 等level处理器的日志级别formatter用于格式化日志的 Formatterargs处理器初始化参数如文件名等\nformatters 参数:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数说明format指定日志输出格式的模板datefmt格式化时间的格式字符串style输出样式{$ 等\n模块用法\ngraph TB\n START(开始)-->Choose_Logger[选择Logger]\n Choose_Logger-->|内置Logger|Use_Builtin[使用Python内置Logger]\n Choose_Logger-->|自定义Logger|Define_Logger[定义自定义Logger]\n \n Define_Logger-->Set_Level[设置日志级别<br>如DEBUG,INFO等]\n Define_Logger-->Create_Handler[创建Handler<br>如FileHandler,<br>StreamHandler等] \n Set_Level-->Create_Handler\n \n Create_Handler-->Set_Format[设置日志格式]\n Set_Format-->Add_Handler[添加Handler到Logger]\n \n Use_Builtin-->Set_Level\n Use_Builtin-->Create_Handler\n \n Add_Handler--> USE[使用Logger记录日志]\n USE-->END(结束)\n\n日志级别\nlogging 模块总共定义了 6 个级别的日志,按照严重程度从低到高排列如下:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n级别数值说明DEBUG10最详细的调试信息INFO20确认一切运行正常WARNING30表示出现异常但尚未影响程序运行ERROR40由于更严重的问题程序的某些功能已经不能正常运行了CRITICAL50严重错误程序可能无法继续运行\n在代码中记录日志时我们可以根据需要的日志级别选择合适的函数比如\nimport logging\n \nlogging.debug('detailed debug info')\nlogging.info('program running info') \nlogging.warning('warning occurred')\nlogging.error('error occurred')\nlogging.critical('critical error')\n日志级别可用于控制日志的输出粒度通过设置级别参数可以只输出大于或等于该级别的日志。\n日志输出\nlogging 模块支持通过多种 Handler 将日志输出到不同的位置,常见的有两种:\n输出到控制台\nimport logging\n \n# create logger\nlogger = logging.getLogger('simple_example')\nlogger.setLevel(logging.DEBUG)\n \n# create console handler and set level to debug\nch = logging.StreamHandler()\nch.setLevel(logging.DEBUG)\n \n# create formatter\nformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n \n# add formatter to ch\nch.setFormatter(formatter)\n \n# add ch to logger\nlogger.addHandler(ch)\n \n# 'application' code\nlogger.debug('debug message')\nlogger.info('info message')\nlogger.warning('warn message')\nlogger.error('error message')\nlogger.critical('critical message')\n输出到文件\nimport logging\n \n# 创建 logger\nlogger = logging.getLogger('simple_example')\nlogger.setLevel(logging.DEBUG)\n \n# 创建一个向文件输出的 handler\nfh = logging.FileHandler('test.log')\nfh.setLevel(logging.DEBUG)\n \n# 创建 formatter\nformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n \n# 添加 formatter 到 fh\nfh.setFormatter(formatter) \n \n# 添加 fh 到 logger\nlogger.addHandler(fh)\n \n# 日志输出\nlogger.debug('debug message') \nlogger.info('info message')\nlogger.warning('warn message')\nlogger.error('error message')\nlogger.critical('critical message')\n此外还可以通过 SocketHandler 进行网络日志,通过 MemoryHandler 将日志输出到内存等。\n日志格式化\nlogging 模块允许自定义日志的输出格式,方便阅读和分析。主要通过 Formatter 实现。\n# 自定义格式\n# 2023-02-28 155007431 - myapp.utils - INFO - User signed in successfully [in /path/to/utils.py456] \nformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s [in %(pathname)s%(lineno)d]')\n \nhandler.setFormatter(formatter)\nFormatter 使用的格式字符串类似于 C 语言的 printf 格式,可以包含以下字段:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字段说明asctime日志事件发生时间如 2023-02-28 154923895levelname日志级别的文本表示如 INFO、ERROR 等levelno日志级别的数值如 20、40 等message日志消息文本pathname调用日志输出函数的源代码文件路径filenamepathname 的文件名部分module文件名的模块名部分funcName调用日志输出函数的函数名lineno调用日志输出函数的源代码行号thread线程 IDprocess进程 ID\n日志高级功能\n日志回滚\n通过 RotatingFileHandler 可以实现日志文件回滚,即当日志文件达到一定大小时自动生成新文件。\nhandler = RotatingFileHandler('test.log', maxBytes=1024, backupCount=5)\n日志分割\n它可以设置最大字节数和备份文件的数量超过这些限制之后就会生成新的日志文件。通过 TimedRotatingFileHandler 可以实现日志文件按时间分割。\nhandler = TimedRotatingFileHandler('test.log', when='D', interval=1) \n通过 when 参数可以设置按日、周、月等时间间隔进行切割interval 参数设置时间间隔大小。\n最佳实践\n根据应用场景配置 Logging 模块\n不同的 Python 应用场景需要不同的日志方案:\n\n小型命令行程序直接输出到 stdout\n大型项目输出到日志文件同时进行错误提醒、日志分割等\n分布式系统实现集中式日志结合 ELK 等日志分析系统\n\n选择合适的 logging 功能组合。\n与项目架构相结合\nlogging 模块要与项目的架构设计相结合,比如:\n\n对 Django 项目进行专门的 Logging 设置\n对 Flask 项目使用 dictsConfig 进行配置\n对于大型项目创建一个 log.py 统一处理日志\n\n可选的日志收集工具\n可以结合日志收集系统实现可视化分析如 ELK(ElasticSearch + Logstash + Kibana) 组合。\n日志的性能优化\n\n通过配置只记录必要的日志级别不记录无用日志\n将调试日志单独记录到一个文件\n避免频繁字符串拼接使用参数化格式\n控制日志文件大小和滚动频率\n\n实战练习\n标准日志模块的配置示范\n# log_config.py\n \nimport logging\nimport logging.config\n \n# 日志配置字典\nconfig_dict = {\n \n # 版本配置\n 'version': 1,\n \n # 配置日志格式化器\n 'formatters': {\n \n # 简单日志格式\n 'simple': {\n 'format': '[%(asctime)s] [%(levelname)s] %(message)s'\n },\n \n # 复杂日志格式 \n 'complex': {\n 'format': '[%(asctime)s] [%(levelname)s] [%(name)s] [%(filename)s %(funcName)s %(lineno)d] %(message)s'\n }\n },\n \n # 配置日志处理器\n 'handlers': {\n \n # 控制台日志\n 'console': {\n 'class': 'logging.StreamHandler',\n 'level': 'DEBUG',\n 'formatter': 'simple'\n },\n \n # 文件日志\n 'file': {\n 'class': 'logging.FileHandler',\n 'filename': 'app.log',\n 'mode': 'a',\n 'formatter': 'complex'\n }\n },\n \n # 配置日志器\n 'loggers': {\n \n # 应用日志器\n 'app': {\n 'handlers': ['console', 'file'],\n 'level': 'DEBUG', \n }\n }\n}\n \nif __name__ == '__main__':\n \n # 加载配置字典\n logging.config.dictConfig(config_dict)\n \n # 获取日志器并输出日志\n logger = logging.getLogger('app')\n logger.debug('This is a debug message')\n以上实现了一个标准的日志配置输出到控制台和文件并使用不同的格式器包含日志实践中的常见操作。\n小型项目中添加日志\n以一个小型的 Web 项目为例:\nimport logging\n \n# 创建日志器 \nlogger = logging.getLogger('myweb')\n \n# 创建控制台处理器并设置级别\nch = logging.StreamHandler()\nch.setLevel(logging.INFO)\n \n# 添加格式器 \nformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\nch.setFormatter(formatter)\n \n# 将处理器添加到日志器\nlogger.addHandler(ch)\n \n# 记录一条日志\nlogger.info('Starting myweb server...') \n代码中创建日志器、添加处理器、设置格式后就可以在项目代码任何地方使用 logger.info、logger.debug 等记录日志,从而方便地添加日志功能。\n尝试优化项目日志的性能\n优化日志性能的常见做法\n\n通过配置文件配置日志不要在代码里反复配置\n设置生产环境只记录必要的日志级别如 WARNING 以上\nERROR 日志单独记录到文件,便于定位问题\nDEBUG 日志可以使用内存 Handler避免 IO 消耗\n使用异步日志避免影响程序性能\n合理设置日志滚动策略避免文件过大\n\n扩展学习\n其他日志框架的比较 (Loguru、log4j 等)\nlogging 模块作为标准库,用法简单,但需要自行处理诸如异步、日志分割等额外功能。一些第三方日志库如 loguru、log4j 等提供了更多实用功能的封装,可以根据需求选择。\n分布式系统日志收集方案\n在分布式系统中可以通过将日志发送到消息队列如 Kafka然后由 Logstash 收集存储到 ElasticSearch 中,最后结合 Kibana 进行日志分析和可视化。也可以直接使用 ELK 提供的 Filebeat 代替 Logstash 从日志文件中收集日志。"},"Technology/ProgrammingLanguage/Python/模块/系统交互/loguru-日志库":{"title":"loguru 日志库","links":[],"tags":["Python/PyPI","技术/程序语言"],"content":"简单而强大的 Python 日志库\nLoguru 是一个非常简单但功能强大的 Python 日志库,它可以让你用极少的代码就实现强大的日志功能。\n安装\npip install loguru\n基本用法\n创建 Logger 对象\nfrom loguru import logger\n \nlogger.info("Hello World!")\n设置日志级别\n使用 logger 的 level() 方法可以设置日志级别级别从低到高为TRACE、DEBUG、INFO、SUCCESS、WARNING、ERROR、CRITICAL。值得注意的是Loguru 还提供了一个额外的 SUCCESS 级别。\nlogger.level("INFO") # 设置日志级别为INFO\n默认级别为 DEBUG低于设置级别的日志不会被显示。\n输出到控制台\n默认 Loguru 会将日志输出到 sys.stderr你可以通过 add() 指定其他输出方式:\nlogger.add(sys.stdout) # 日志输出到stdout\n输出到文件\n输出日志到文件只需要提供文件名Loguru 会自动处理后续的文件创建及回滚等操作:\nlogger.add("file.log") # 日志输出到file.log文件\nLoguru 还提供了“热重载”功能,如果日志文件被删除或移动,将自动创建新的日志文件。\n格式化日志\nLoguru 支持非常丰富的参数格式设置,可以完全自定义日志内容和格式。一些常用的参数包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n格式化对象格式化语法示例时间{time} {time:格式}{time}, {time:YYYY-MM-DD HH:mm:ss}级别{level}{level}消息{message}{message}模块{module}{module}函数{function}{function}行号{line}{line}进程{process}{process}线程{thread}{thread}文件名{file}{file}Logger 名{name}{name}异常{exception}{exception}嵌套{time:{hour}}{time:{hour}}条件表达式{level:样式 if 条件}{level:红色 if level=="ERROR"}设置宽度{参数:<宽度}{level:<8}设置精度{参数:.精度}{level:.2f}设置颜色{参数:<颜色>}{level:<red>}设置样式{参数:<样式>}{message:<bold>}\n例如\nlogger.info("{time:<12} - {level:<8} - {message}", "Hello World!")\n \n# 输出\n# 2022-07-14 201432.199 - INFO - Hello World!\n日志文件管理\nLoguru 可以方便地对日志文件进行管理。\n设置日志文件大小\n通过 rotation 参数可以设置每个日志文件的最大大小:\nlogger.add("file.log", rotation="500 MB") # 设置日志文件最大500MB\n设置回滚日志文件个数\n通过 retention 参数可以设置保留的历史日志文件个数:\nlogger.add("file.log", rotation="500 MB", retention="10") # 保留最近10个日志文件\n滚动日志文件\n日志文件到达最大大小后会自动滚动新的日志写入到新的文件。可以通过 rotate() 主动触发滚动。\nlogger.rotate("file.log") # 手动滚动日志文件\n异常捕获\nLoguru 可以非常方便地记录异常信息。\n记录异常信息\n在 try except 中使用 logger.exception() 可以记录异常堆栈:\ntry:\n 1/0\nexcept:\n logger.exception("Catch an exception.")\n它会打印出完整的异常信息像正常的 traceback 模块。\n格式化异常显示\n可以使用 format_exc 参数来格式化显示异常:\ntry:\n 1/0 \nexcept Exception as e:\n logger.error("Error {e}", e=logger.format_exc())\n过滤日志\n可以通过添加或删除过滤器来过滤日志。\n添加过滤器\n例如只记录 warning 及以上级别的日志:\nlogger.add(lambda msg: msg.level > 20)\n删除过滤器\nlogger.remove() # 移除所有过滤器\n异步日志\nLoguru 原生支持异步日志,可以通过 queue_size 参数开启。\nlogger.add("file.log", enqueue=True) # 异步队列大小为1万\n这可以大大提升日志写入速度。\n结构化日志\n可以在日志中插入字典、JSON 等结构化数据:\nlogger.info({"timestamp": 1234, "values": [1,2,3]})\n非常方便后续日志分析。\n最佳实践\n在项目中我建议以下最佳实践\n\n\n创建一个全局的 Loguru 对象 logger作为日志的入口。\n\n\n根据应用设置合理的日志级别如 info 或 warning。\n\n\n主要输出日志到文件同时输出重要的日志到 console。\n\n\n使用日志文件回滚保证不会增大无限。\n\n\n格式化日志包含关键信息如时间、函数、行数等。\n\n\n在必要时开启异步日志。\n\n\n在 exception 中使用 logger.exception() 打印堆栈。\n\n\n根据需要添加日志过滤器。\n\n\n直接使用 Loguru不需要标准 logging 模块。\n\n\nfrom loguru import logger\nimport sys\n \n# 设置日志级别\nlogger.level("INFO")\n \n# 输出日志到文件,并设置文件回滚策略\nlogger.add("file_{time}.log", rotation="1 day") # 每天回滚\n \n# 同时输出重要的日志到 console\nlogger.add(sys.stderr, level="WARNING")\n \n# 格式化日志,包含关键信息\nfmt = "<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>"\nlogger.remove()\nlogger.add(sys.stderr, format=fmt)\n \n# 在必要时开启异步日志\nlogger.add("async_{time}.log", rotation="1 day", enqueue=True) # 每天回滚,启用异步日志\n \ntry:\n # 做一些可能会抛出异常的操作\n 1 / 0\nexcept Exception as e:\n # 在 exception 中使用 logger.exception() 打印堆栈\n logger.exception("An error occurred: {}", e)\n \n# 根据需要添加日志过滤器\ndef debug_or_higher(record):\n return record["level"].no >= logger.level("DEBUG").no\n \nlogger.add("debug_or_higher.log", filter=debug_or_higher)\n \n# 使用 logger\nlogger.info("This is a normal message.")\nlogger.warning("This is a warning message.")\nlogger.error("This is an error message.")"},"Technology/ProgrammingLanguage/Python/模块/系统交互/os-多种操作系统接口":{"title":"os 多种操作系统接口","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"概述\n**os 模块的主要目的之一就是提供一个跨平台的接口来与操作系统进行交互。**通过这个抽象层,开发者可以编写在多种操作系统上都能运行的代码,而无需关心底层操作系统的具体实现细节。\n这样做有几个主要优点\n\n可移植性代码可以在不同的操作系统上运行无需进行大量的修改。\n维护性由于操作系统特定的实现细节被抽象出来维护代码变得更容易。\n可读性和可理解性提供了一组统一的 API使得代码更容易阅读和理解。\n开发效率开发者可以更快地开发应用程序因为他们不需要了解所有操作系统的内部工作机制。\n\n然而也有一些局限性和挑战\n\n性能抽象层可能会引入一些额外的性能开销。\n功能限制为了保持跨平台性os 模块可能不会提供某个特定操作系统上可用的高级功能。\n平台特定的代码虽然 os 模块尽量提供跨平台的方法,但有时还是需要编写一些平台特定的代码。\n\n总体来说os 模块确实旨在消除操作系统之间的不一致性,并提供一个更加统一和高级的编程接口。\n导入\nimport os\n进程管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.fork()创建一个子进程UNIX/Linuxos.exec*()在当前进程中执行新程序所有(但在 Windows 上有限制os.spawn*()创建新进程运行程序所有(但在 UNIX/Linux 上不常用os.wait()等待子进程完成UNIX/Linuxos.waitpid(pid, options)等待特定的子进程完成UNIX/Linuxos.kill(pid, signal)向进程发送信号UNIX/Linuxos.terminate()终止当前进程Windowsos.startfile(filepath)使用关联的应用程序打开文件Windows\n文件管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.open(file, flags[, mode])打开文件并返回文件描述符所有os.close(fd)关闭文件描述符所有os.read(fd, n)从文件描述符 fd 读取最多 n 个字节所有os.write(fd, str)写入字符串到文件描述符 fd所有os.remove(path)删除指定的文件所有os.rename(src, dst)重命名文件或目录所有os.stat(path)获取文件或目录的状态信息所有os.chmod(path, mode)改变文件或目录的权限所有os.chown(path, uid, gid)改变文件或目录的所有者和所属组UNIX/Linuxos.utime(path, times)更新文件时间戳所有os.path.getsize(path)获取文件的大小所有os.path.getmtime(path)获取文件的最后修改时间所有os.path.getctime(path)获取文件的创建时间所有os.path.isfile(path)检查指定路径是否是文件所有os.path.isdir(path)检查指定路径是否是目录所有os.path.exists(path)检查指定路径是否存在所有os.path.split(path)将路径分割为目录和文件名所有os.path.splitext(path)将文件路径分割为文件名和扩展名所有os.path.join(a, b)将多个路径组合成一个路径所有\n目录操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.getcwd()获取当前工作目录所有os.chdir(path)改变当前工作目录所有os.mkdir(path)创建新目录所有os.makedirs(path)创建新目录如果父目录不存在也会被创建所有os.rmdir(path)删除目录所有os.removedirs(path)删除目录如果目录内有文件也会被删除所有os.listdir(path)列出指定目录下的所有文件和目录所有os.scandir(path)返回一个迭代器,包含目录中的 DirEntry 对象所有os.rename(old, new)重命名目录所有os.stat(path)获取目录的状态信息所有os.chmod(path, mode)改变目录的权限所有os.chown(path, uid, gid)改变目录的所有者和所属组UNIX/Linuxos.path.isdir(path)检查指定路径是否是目录所有os.path.exists(path)检查指定路径是否存在所有os.path.split(path)将路径分割为目录和文件名所有os.path.join(a, b)将多个路径组合成一个路径所有\n系统信息\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.name获取操作系统名字如 'posix', 'nt'所有os.uname()获取详细的系统信息(仅 UNIX/LinuxUNIX/Linuxos.environ获取环境变量所有os.getenv(key)获取特定环境变量的值所有os.putenv(key, value)设置环境变量的值所有os.system(command)运行外部命令所有os.cpu_count()获取 CPU 核心数量所有os.getpid()获取当前进程 ID所有os.getppid()获取父进程 ID所有os.getuid()获取当前用户 ID仅 UNIX/LinuxUNIX/Linuxos.getgid()获取当前组 ID仅 UNIX/LinuxUNIX/Linuxos.getlogin()获取当前用户登录名UNIX/Linux, Windowsos.urandom(n)生成 n 个字节的强随机数所有\n文件描述符操作\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.dup(fd)复制文件描述符所有os.dup2(fd, fd2)复制文件描述符到另一个文件描述符所有os.fdopen(fd[, mode[, bufsize]])通过文件描述符打开文件对象所有\n信号处理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.kill(pid, sig)向进程发送信号UNIX/Linuxos.signal(signalnum, handler)设置信号处理程序UNIX/Linux\n终端管理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.isatty(fd)检查文件描述符是否连接到终端所有os.ttyname(fd)获取与文件描述符关联的终端名称UNIX/Linux\n其他\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述平台适用性os.popen(command[, mode[, bufsize]])打开与一个进程的管道所有os.pipe()创建一个管道所有os.tempnam([dir[, prefix]])生成一个唯一的临时文件名(不推荐,使用 tempfile 模块代替所有os.tmpfile()创建并打开w+b一个新的临时文件不推荐使用 tempfile 模块代替UNIX/Linux"},"Technology/ProgrammingLanguage/Python/模块/系统交互/subprocess-子进程管理":{"title":"subprocess 子进程管理","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"概念\nsubprocess 是 Python 中的一个重要模块,自 Python 2.4 版本开始引入,用于管理和与外部进程进行交互。一个“进程”是一个运行中的程序实例,它有自己的内存空间和系统资源。我们需要管理进程以便在 Python 脚本中执行外部命令,或者与其他进程交互。\nsubprocess 提供了一个强大而灵活的接口,允许你启动新的进程、连接到它们的输入、输出和错误管道,并获取它们的返回代码。它旨在替代一些旧的进程管理方法,如 os.system 和 os.spawn*,并为进程管理提供了一个现代化的解决方案。\n基础操作\nsubprocess 是 Python 的标准库,所以不需要单独安装。\n基本功能\n使用 run() 函数可以运行外部命令。例如:\nimport subprocess\n \n# 运行命令并捕获输出\nresult = subprocess.run(["ls", "-l"], capture_output=True, text=True)\nprint(result.stdout)\n常用示例\n# 运行命令并捕获输出\nresult = subprocess.run(["ls", "-l"], capture_output=True, text=True)\nprint(result.stdout)\n \n# 运行命令并检查返回代码\ntry:\n subprocess.run(["false"], check=True)\nexcept subprocess.CalledProcessError:\n print("命令执行失败!")\n \n# 使用 shell 执行命令\nsubprocess.run("echo Hello, World!", shell=True)\n深入探索\nRun 函数\nrun 函数是 subprocess 模块中的核心函数,它提供了丰富的参数来控制子进程的行为。以下是一些示例和参数的详细描述:\nimport subprocess\n \n# 示例 1: 运行基本的外部命令,捕获输出\nresult = subprocess.run(["ls", "-l"], capture_output=True, text=True)\nprint("示例 1 输出:")\nprint(result.stdout)\n \n# 示例 2: 运行命令并检查返回代码\ntry:\n subprocess.run(["false"], check=True)\nexcept subprocess.CalledProcessError:\n print("示例 2: 命令执行失败!")\n \n# 示例 3: 使用 shell 执行命令\nsubprocess.run("echo Hello, World!", shell=True)\n \n# 示例 4: 指定工作目录和自定义环境变量\ncustom_env = {"MY_VARIABLE": "some_value"}\nresult = subprocess.run(["echo", "$MY_VARIABLE"], env=custom_env, shell=True, text=True)\nprint("示例 4 输出:")\nprint(result.stdout)\n \n# 示例 5: 设置超时\ntry:\n subprocess.run(["sleep", "10"], timeout=5)\nexcept subprocess.TimeoutExpired:\n print("示例 5: 命令超时!")\n \n# 示例 6: 重定向错误输出\nresult = subprocess.run(["ls", "nonexistent"], stderr=subprocess.PIPE, text=True)\nprint("示例 6 输出:")\nprint(result.stderr)\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n参数描述args要运行的命令以及命令的参数通常作为一个字符串列表传递。stdin用于指定子进程的标准输入流。可以是文件对象、subprocess.PIPE、subprocess.DEVNULL、或一个打开的文件描述符。stdout用于指定子进程的标准输出流。可以是文件对象、subprocess.PIPE、subprocess.DEVNULL、或一个打开的文件描述符。stderr用于指定子进程的标准错误流。可以是文件对象、subprocess.PIPE、subprocess.DEVNULL、或一个打开的文件描述符。shell如果为 True则将命令传递给系统的 shell 执行,可以使用 shell 语法。默认为 False。cwd子进程的工作目录用于指定命令在哪个目录下执行。env一个字典包含自定义的环境变量。子进程将在这个环境中执行。universal_newlines如果为 True则标准输入和输出以文本模式打开可以使用字符串而不是字节进行通信。默认为 False。encoding指定编码用于将标准输出和标准错误流解码为文本。通常与 universal_newlines=True 配合使用。默认为 None。errors用于指定编码错误处理策略通常与 encoding 参数一起使用。默认为 None。text与 universal_newlines 相同,如果为 True则将标准输入和输出以文本模式打开。已在 Python 3.7 中引入。默认为 False。capture_output如果为 True则会捕获子进程的标准输出和标准错误流并将其包含在返回的 CompletedProcess 对象中。已在 Python 3.5 中引入。timeout设置命令的超时时间如果命令在指定的时间内未完成将引发 TimeoutExpired 异常。check如果为 True则会检查命令的返回代码如果不为零则引发 CalledProcessError 异常。默认为 False。\nPopen\nsubprocess.Popen 是 subprocess 模块中的一个类,用于创建和管理子进程,允许更高级和灵活的进程交互。通过 Popen你可以控制子进程的输入、输出和错误流以及其他进程相关的属性。\nimport subprocess\n \n# 使用 Popen 接口\nwith subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, text=True) as proc:\n output = proc.stdout.read()\n print(output)\n方法和属性\n\ncommunicate(): 与子进程交互,发送输入数据和读取输出数据。\npoll(): 检查子进程是否已结束。\nwait(): 等待子进程结束。\nreturncode: 子进程的返回代码。\n"},"Technology/ProgrammingLanguage/Python/模块/系统交互/sys-系统相关的形参和函数":{"title":"sys 系统相关的形参和函数","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"概述\nsys 模块是 Python 标准库中的一部分,它提供了与 Python 解释器及其环境交互的功能。这包括对命令行参数、标准输入/输出、异常处理、解释器配置等的访问。\nsys 模块是 Python 的标准库之一,自 Python 诞生以来一直存在,并随着 Python 的发展不断更新和改进。\nsys 模块用于各种用例,包括:\n\n访问和操作命令行参数。\n控制 Python 解释器的运行时行为。\n处理异常和退出程序。\n访问与 Python 解释器相关的信息。\n执行与系统交互的任务。\n\n优点\n\n内置模块无需安装。\n提供了许多与 Python 解释器及其环境交互的功能。\n可以用于处理系统级任务。\n\n缺点\n\n有些功能可能是平台相关的不一定在所有系统上表现一致。\n高级功能需要一定的 Python 知识。\n\n基础操作\nsys 是 Python 的标准库之一,无需额外安装。\n基本功能\nimport sys\n \n# 获取 Python 解释器版本\nprint("Python版本:", sys.version)\n \n# 获取命令行参数\nprint("命令行参数:", sys.argv)\n \n# 获取系统平台信息\nprint("系统平台:", sys.platform)\n常用示例代码\n以下是一些 sys 模块的常用示例代码:\nimport sys\n \n# 假设脚本名为 script.py运行时传递参数python script.py arg1 arg2\nscript_name = sys.argv[0]\narguments = sys.argv[1:]\n \nprint("脚本名称:", script_name)\nprint("命令行参数:", arguments)\n \n \n# 设置 Python 解释器的输出编码为UTF-8\nsys.stdout.encoding = 'utf-8'\n \n# 退出程序可选参数为退出状态码通常0表示成功非0表示错误\nsys.exit(0)\n深入探索\nsys.path 包含用于查找模块的目录列表\nimport sys\n \n# 获取当前模块搜索路径\nmodule_search_paths = sys.path\nprint("模块搜索路径:", module_search_paths)\n \n# 添加自定义路径到模块搜索路径\ncustom_path = "/path/to/custom/modules"\nsys.path.append(custom_path)\n \n# 输出自定义路径\nprint(sys.path)\nsys.stdin、sys.stdout 和 sys.stderr 用于标准输入、标准输出和标准错误流的对象\nimport sys\n \n# 重定向标准输出到文件\nwith open('output.txt', 'w') as f:\n sys.stdout = f\n print("这个文本将被写入output.txt")\n sys.stdout = sys.__stdout__ # 恢复标准输出\nsys.exc_info() 用于获取当前异常信息的元组\nimport sys\nimport traceback\n \ntry:\n # 产生一个异常\n 1 / 0\nexcept:\n # 获取当前异常信息\n exc_type, exc_value, exc_traceback = sys.exc_info()\n print("异常类型:", exc_type)\n print("异常值:", exc_value)\n print("异常跟踪信息:")\n traceback.print_tb(exc_traceback)"},"Technology/ProgrammingLanguage/Python/模块/网络处理/requests-HTTP-库":{"title":"requests HTTP 库","links":["Tech/programming-language/Python/进阶/异常处理"],"tags":["Python/PyPI","技术/程序语言"],"content":"Requests 是 Python 的一个非常流行和强大的 HTTP 库,使用 Requests 可以极其方便地发送 HTTP/HTTPS 请求,然后获取并解析响应。它的语法简洁而又优雅,出色地符合 Python 风格,相比起 Python 自带的 urllib 来说Requests 无疑更加人性化和易用。\n概述\n**Requests 库的目标就是让 HTTP 请求变得简单而又 Pythonic。**它可以显著减少程序员发送 HTTP 请求的工作量。使用 Requests你不必手动添加查询字符串到 URL 中,或 encode post 数据了。一切都自动完成。\nRequests Vs Urllib\nPython 内置的 urllib 模块也可以发送网络请求,但其 API 不够优雅简洁。与 urllib 相比Requests 更加 Pythonic而且更简单易用。\n# 使用 urllib 获取一个网页的代码\nimport urllib.request\nresponse = urllib.request.urlopen('https//www.python.org')\nhtml = response.read()\n \n# 使用 Requests 获取同一个页面的代码\nimport requests\nresponse = requests.get('https//www.python.org') \nhtml = response.text\n \n \n# Requests 允许使用 params 关键字传递参数,数据自动编码\npayload = {'key1' 'value1' 'key2' 'value2'} \nr = requests.get('https//httpbin.org/get' params=payload)\n \n# 而通过 urllib 则要手动编码\nimport urllib.parse\nimport urllib.request\nurl = 'https//httpbin.org/get' + '?' + urllib.parse.urlencode(payload)\nresp = urllib.request.urlopen(url)\n总之Requests 相对于 urllib 更加简洁易用。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比项requestsurllib发送请求方法简洁的 requests.get()/post()较复杂的 urllib.request.urlopen()参数传递自动编码,直接传 dict需要手动 urlencode请求头直接传 dict 作为 headers通过 Request 类设置响应内容多属性访问 text/content/json/raw 等仅 response.read()编码支持自动编码需要手动编码连接池支持连接池和会话不支持异常处理提供多种请求相关异常仅 urllib.error 异常证书验证通过 verify 参数验证 SSL 证书通过 context 参数验证代理设置支持通过 proxies 参数较复杂的 ProxyHandlerCookies提供 cookie 参数通过 cookielib 模块管理重定向自动处理,可通过 max_redirects 配置需要手动处理基本认证通过 auth 参数通过 HTTPSHandler流请求内置支持需要自定义异步请求支持异步模式不支持异步\nRequests 的关键特性\n\n继承了 urllib 的所有特性\n支持 HTTP 连接保持和连接池,提高效率\n支持使用 cookie 跟踪会话\n支持文件上传\n支持自动解码内容\n支持国际化的 URL 和 POST 数据自动编码\n更加 Pythonic 的 API\n连接超时设置\n支持 HTTPS 请求SSL 证书验证\n自动解压\n流下载\n支持基本/摘要式的身份认证\n\n基础用法\n构造请求\nimport requests\n \n# requests.get 用于获取页面信息,\nresponse = requests.get('https//www.example.com') \n \n# requests.post 用于提交 POST 请求。\nresponse = requests.post('https//httpbin.org/post' data = {'key''value'})\n获取响应\n \n# 获取响应的内容使用 text 属性\nhtml = response.text\n \n# 获取二进制响应内容使用 content 属性\npng_data = response.content\n \n# 获取 JSON 响应使用 json() 方法\njson_data = response.json()\n获取响应状态码\n获取响应状态码可以检查 response.status_code\nprint(response.status_code)\n \n200\nRequests 还提供了一个内置的状态码查询对象 requests.codes。例如\nprint(requests.codes.ok) \n \n200\n请求参数\n向请求中传入参数有以下几种方法\n\n通过 params 参数传入键值对\n\npayload = {'key1' 'value1' 'key2' 'value2'}\nr = requests.get('https//httpbin.org/get' params=payload) \n\n通过字典直接作为 params 参数传入\n\nparams = {'key1' 'value1' 'key2' 'value2'}\nr = requests.get('https//httpbin.org/get' params)\n\n通过 url 中的查询字符串传递参数\n\nurl = 'https//httpbin.org/get#039;\nr = requests.get(url)\n设置请求头\n可以通过 headers 参数设置 HTTP 请求头,例如:\nurl = 'https//httpbin.org/get'\nheaders = {'user-agent' 'my-app/0.0.1'}\n \nr = requests.get(url headers=headers)\n响应内容\n对于响应内容有多种属性供访问\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性说明r.text字符串形式的响应体会自动解码r.content字节形式的响应体可迭代r.json()将 JSON 响应转换为字典r.raw原始响应体需要自行解码r.encoding响应体编码方式r.status_codeHTTP 响应状态码r.headers响应头部的字典r.request请求的 Request 对象r.url请求的 URLr.history请求的重定向信息\n例如\nr = requests.get('https//api.github.com')\n \nprint(r.text) # 字符串形式的响应体\nprint(r.content) # 字节形式的响应体,可迭代 \nprint(r.json()) # JSON格式转换为字典 \nprint(r.raw) # 返回原始响应体\n高级用法\nRequests 还提供了很多高级功能,极大地丰富了这一模块的使用场景。\n会话维持\nRequests 提供了 session 对象,用于实现会话维持:\ns = requests.Session()\ns.get('http//httpbin.org/cookies/set/sessioncookie/123456789')\nr = s.get("http//httpbin.org/cookies")\n \nprint(r.text)\n# '{"cookies" {"sessioncookie" "123456789"}}'\n默认的 requests 函数并不会在同一个 session 中保持 cookie所以它不会在跨请求保持状态。要保持会话就需要使用 session 对象。\nSSL 证书验证\nRequests 可以验证 SSL 证书,你可以指定一个本地证书用作客户端证书,以完成客户端验证:\nimport requests\n \nresp = requests.get('https//example.com' verify='path/to/certfile')\n或者你也可以指定一个本地证书作为 CA 证书 BUNDLE来验证请求的 TLS 服务端证书:\nimport requests\n \nresp = requests.get('https//example.com' verify='path/to/cacert.pem')\n代理设置\n使用代理也很简单\nimport requests\n \nproxies = {\n "http" "http//10.10.1.103128"\n "https" "http//10.10.1.101080"\n}\n \nrequests.get("http//example.org" proxies=proxies)\n你也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 配置代理。\n超时设置\n通过 timeout 参数,可以告诉 requests 等待服务器响应的超时时间,以秒为单位:\nrequests.get('https//github.com' timeout=0.001)\n分别为连接超时 connect timeou t 和读取超时 read timeout\nrequests.get('https//github.com' timeout=(3.05 10))\n好的文章继续\n异常处理\nRequests 的异常类型主要分为以下几类:\n\n连接异常包括 RequestsConnectionError 和 ConnectTimeout表示与远程服务器的连接发生错误。\n超时异常RequestsTimeout 表示请求超时。可以分为连接超时和读取超时。\nTooManyRedirects表示重定向次数超过了最大限制默认为 30 次)。\nHTTP 错误HTTPError 表示 HTTP 错误响应,例如 404 或者 500 等。Requests 会自动为其封装异常。\n请求异常RequestException 是 Requests 库自身的异常基类。\nSSL 错误SSLError 表示 SSL 证书验证错误。\n代理错误ProxyError 表示代理连接失败。\n数据解析错误JSONDecodeError 和 DecodeError 表示响应数据解析错误。\n其他ConnectionError、InvalidURL 等其他异常。\n\n可以通过 try except 语句捕获这些 异常:\nimport requests\n \ntry\n response = requests.get('https//httpbin.org/delay/10' timeout=2)\nexcept requests.ConnectTimeout\n print('Connection timed out') \nexcept requests.ConnectionError\n print('Connection error')\n如果不捕获异常程序会中断并抛出异常。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n异常类型说明RequestsConnectionError网络连接错误ConnectTimeout连接超时错误RequestsTimeout请求超时错误TooManyRedirects重定向次数超限HTTPErrorHTTP 错误响应RequestException请求异常基类SSLErrorSSL 证书验证错误ProxyError代理连接错误JSONDecodeErrorJSON 解析错误ConnectionError连接错误\n流式下载\n对于大文件下载可以使用流模式节省内存\nwith requests.get('http//httpbin.org/stream/100' stream=True) as r\n for chunk in r.iter_content(chunk_size=1024) \n print(chunk)\n该模式仅当你在迭代时才会持续下载响应体部分如果你要多次读取响应必须使用 r.content 访问内容。\n连接重试\n可以通过设置 retries 参数,让请求在遇到连接错误时自动重试指定次数:\nfrom requests.adapters import HTTPAdapter\n \ns = requests.Session()\nretries = Retry(total=5 backoff_factor=1 status_forcelist=[502 503 504])\ns.mount('http//' HTTPAdapter(max_retries=retries)) \n如果响应状态码是 502/503/504该请求会重试最多 5 次。\n实践技巧\n文件上传\nRequests 使得文件上传变得极其简单:\nurl = 'https//httpbin.org/post'\nfiles = {'file' open('report.pdf' 'rb')}\n \nr = requests.post(url files=files)\n我们只需要在传递的字典中设置好文件名和文件对象即可Requests 会帮你正确编码并发送。\n获取图片\n由于图片也是一种二进制数据所以获取图片可以这么写\nurl = 'https//images.pexels.com/photos/1562477/pexels-photo-1562477.jpeg'\nr = requests.get(url)\n \nwith open('image.jpeg' 'wb') as f\n f.write(r.content)\n图片内容保存在 r.content 中,我们可以直接 write 到文件。\nPrepared Request\n如果要一次构造同一个请求发送多次可以使用 Prepared Request\nurl = 'https//httpbin.org/post'\ndata = {'key''value'}\nheaders = {'User-Agent' 'my-app'}\n \nrequest = requests.Request('POST' url data=data headers=headers)\nprepared_request = request.prepare()\n \ns = requests.Session()\nresponse = s.send(prepared_request)\n异步 Requests\n基于 Gevent 的异步\nimport requests\nimport gevent\nfrom gevent import monkey\n \nmonkey.patch_all()\n \nurls = [\n 'https//www.python.org'\n 'https//www.mi.com'\n 'https//www.baidu.com'\n]\n \njobs = [gevent.spawn(requests.get url) for url in urls]\ngevent.joinall(jobs)\nprint([job.value.text for job in jobs])\n基于 Asyncio 的异步\nimport asyncio\nimport requests\n \nasync def download_site(url session)\n async with session.get(url) as response\n print(f"Read {len(response.content)} from {url}")\n \nasync def download_all_sites(sites)\n async with requests.Session() as session\n tasks = []\n for url in sites\n task = asyncio.ensure_future(download_site(url session))\n tasks.append(task)\n await asyncio.gather(*tasks)\n \nif __name__ == "__main__"\n sites = [\n "https//www.jython.org"\n "http//olympus.realpython.org/dice"\n ] * 80\n asyncio.run(download_all_sites(sites))"},"Technology/ProgrammingLanguage/Python/模块/网络处理/socket-底层网络接口":{"title":"socket 底层网络接口","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"概述\nSocket 是计算机网络中用于实现进程间通信的一种技术。简而言之,它是一个端点,用于发送或接收数据。这些数据可以在同一台计算机上的进程之间,或者在不同计算机上的进程之间进行传输。\nsocket 是 Python 中的一个标准库,它提供了低级的网络通信功能。基于该库,开发者可以实现 TCP、UDP 以及其他类型的网络协议的客户端和服务端程序。\nsocket 库的历史可以追溯到 Unix 操作系统的早期。在 Unix 中socket 被用作进程间通信 (IPC) 的一种方式。随着互联网的发展socket 逐渐被应用于网络通信。Python 的 socket 库提供了对这一功能的高级封装,使得开发网络应用变得更为简单。\n工作原理\nsocket 网络通信最常见的模型是客户端 - 服务器模型。客户端是请求服务的实体而服务器是提供服务的实体。Socket 允许这两个实体进行通信。\n\n客户端: 创建 Socket → 连接到服务器 → 交换数据 → 关闭 Socket\n服务器: 创建 Socket → 绑定到特定地址和端口 → 监听连接 → 接受客户端连接 → 交换数据 → 关闭 Socket\n\nsocket 主要被用于:\n\n创建网络服务器和客户端。\n实现多种网络协议如 TCP 和 UDP。\n进行低级的网络通信如发送原始套接字数据。\n\n它解决了开发者在进行网络通信时的底层细节问题如地址转换、数据传输等。\n协议类型\n\n流式 Socket (SOCK_STREAM): 提供了一个可靠的、面向连接的字节流。这是最常用的 Socket 类型TCP 协议就是基于这种 Socket。\n数据报 Socket (SOCK_DGRAM): 提供了一种无连接的、不可靠的数据传输方式。UDP 协议就是基于这种 Socket。\n原始 Socket (SOCK_RAW): 允许直接访问底层协议,通常用于开发新的通信协议。\n\n地址家族\n\nAF_INET (IPv4): 最常用的地址家族,用于 Internet 通信。\nAF_INET6 (IPv6): 下一代 Internet 地址家族。\nAF_UNIX: 用于同一台机器上的进程间通信。\n\n生命周期\ngraph LR;\n A[创建 Socket] --> B[绑定 Socket到地址和端口];\n B --> C[开始监听传入的连接];\n C --> D[接受连接请求];\n D --> E[进行数据传输];\n E --> F[关闭 Socket];\n\n\n创建: 使用 socket.socket() 创建一个新的 Socket 对象。\n绑定: 使用 bind() 方法将 Socket 绑定到特定的地址和端口。\n监听: 使用 listen() 方法开始监听传入的连接。\n接受连接: 使用 accept() 方法接受一个连接。\n数据传输: 使用 send() 和 recv() 方法进行数据传输。\n关闭: 使用 close() 方法关闭 Socket。\n\n基础操作\n由于 socket 是 Python 的标准库,无需额外安装。\n支持协议\nsocket 库支持多种协议,用于不同的网络通信场景。\n# 服务器\nimport socket\n \nserver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nserver_socket.bind(('localhost', 8080))\nserver_socket.listen(5)\n \nprint("服务器正在监听...")\nclient_socket, addr = server_socket.accept()\nprint(f"连接来自 {addr}")\n \ndata = client_socket.recv(1024)\nprint(f"接收到的数据: {data.decode('utf-8')}")\nclient_socket.send("谢谢你!".encode('utf-8'))\n \nclient_socket.close()\nserver_socket.close()\n# 客户端\nimport socket\n \nclient_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nclient_socket.connect(('localhost', 8080))\n \nclient_socket.send("你好,服务器!".encode('utf-8'))\ndata = client_socket.recv(1024)\nprint(f"接收到的数据: {data.decode('utf-8')}")\n \nclient_socket.close()\nTCP 示例\ngraph LR\n\nsubgraph TCP服务器\n A[创建Socket] --> B[绑定到地址和端口]\n B --> C[监听连接请求]\n C --> D[接受连接]\n D --> E[接收数据]\n E --> F[处理数据]\n F --> G[发送响应]\n G --> E\n E --> H[关闭连接]\n H --> D\nend\n\nsubgraph TCP客户端\n I[创建Socket] --> J[连接到服务器]\n J --> K[发送数据]\n K --> L[接收响应]\n L --> M[处理响应]\n M --> K\n K --> N[关闭连接]\nend\n\nA --> I\n\n\n服务器\nimport socket\n \n# 步骤1创建 TCP Socket\nserver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n \n# 步骤2绑定 Socket 到一个特定的 IP 地址和端口\nserver_address = ('localhost', 12345)\nserver_socket.bind(server_address)\n \n# 步骤3监听传入的连接请求\nserver_socket.listen(5)\n \nprint("TCP 服务器启动,等待连接...")\n \nwhile True:\n # 步骤4接受客户端的连接请求\n client_socket, client_address = server_socket.accept()\n print(f"接受来自 {client_address} 的连接")\n \n # 步骤5与客户端建立通信\n while True:\n data = client_socket.recv(1024)\n if not data:\n break\n \n # 步骤6接收和发送数据\n data = data.decode('utf-8')\n print(f"接收到来自客户端的数据: {data}")\n response = f"你好,\n客户端\nimport socket\n \n# 步骤1创建 TCP Socket\nclient_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n \n# 步骤2连接到服务器的 IP 地址和端口\nserver_address = ('localhost', 12345)\nclient_socket.connect(server_address)\n \nwhile True:\n # 步骤3发送数据给服务器\n message = input("请输入要发送的消息 (输入 'exit' 退出): ")\n \n if message == 'exit':\n break\n \n client_socket.send(message.encode('utf-8'))\n \n # 步骤4接收来自服务器的响应数据\n data = client_socket.recv(1024)\n \n # 步骤5处理服务器的响应数据\n data = data.decode('utf-8')\n print(f"接收到服务器的响应: {data}")\n \n# 步骤6关闭与服务器的连接\nclient_socket.close()\nUDP 示例\ngraph LR\n\nsubgraph UDP服务器\n A[创建Socket] --> B[绑定到地址和端口]\n B --> C[接收数据]\n C --> D[处理数据]\n D --> E[发送响应]\n E --> C\nend\n\nsubgraph UDP客户端\n F[创建Socket] --> G[发送数据]\n G --> H[接收响应]\n H --> I[处理响应]\n I --> G\nend\n\nA --> F\n\n\n服务端\nimport socket\n \n# 步骤1创建 UDP Socket\nserver_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n \n# 步骤2绑定 Socket 到一个特定的 IP 地址和端口\nserver_address = ('localhost', 12345)\nserver_socket.bind(server_address)\n \nprint("UDP 服务器启动,等待数据...")\n \nwhile True:\n # 步骤3接收客户端发送的数据\n data, client_address = server_socket.recvfrom(1024)\n \n # 步骤4处理客户端数据\n data = data.decode('utf-8')\n print(f"接收到来自 {client_address} 的数据: {data}")\n \n # 步骤5为客户端发送响应如果需要\n response = f"你好,客户端!你发送了:{data}"\n server_socket.sendto(response.encode('utf-8'), client_address)\n \n# 步骤6关闭 Socket这里永远不会执行到\nserver_socket.close()\n客户端\nimport socket\n \n# 步骤1创建 UDP Socket\nclient_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n \n# 服务器地址和端口\nserver_address = ('localhost', 12345)\n \nwhile True:\n # 步骤2发送数据给服务器\n message = input("请输入要发送的消息 (输入 'exit' 退出): ")\n \n if message == 'exit':\n break\n \n client_socket.sendto(message.encode('utf-8'), server_address)\n \n # 步骤3接收来自服务器的响应数据\n data, server_address = client_socket.recvfrom(1024)\n \n # 步骤4处理服务器的响应数据\n data = data.decode('utf-8')\n print(f"接收到服务器的响应: {data}")\n \n# 步骤5关闭 Socket\nclient_socket.close()\n常用方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述socket()创建一个新的 socketbind()绑定到一个地址和端口listen()开始监听连接accept()接受一个新的连接connect()连接到一个服务器send()发送数据recv()接收数据close()关闭 socket\n深入探索\n高级功能\n非阻塞 Sockets\nimport socket\n \ns = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\ns.setblocking(False)\n套接字选项\ns.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n超时\ns.settimeout(5.0)"},"Technology/ProgrammingLanguage/Python/模块/网络处理/urllib-URL-处理模块":{"title":"urllib URL 处理模块","links":[],"tags":["Python/标准库","技术/程序语言"],"content":"概述\nurllib 是 Python 标准库中用于处理 URL统一资源定位符相关操作的模块它提供了多个子模块用于执行网络请求、解析 URL、处理错误以及解析 robots.txt 文件等。以下是 urllib 的子模块:\n子模块\n\nurllib.request提供打开和读取 URL 的功能。支持多种网络协议,如 HTTP、FTP 等。\nurllib.error包含与网络请求相关的异常类用于处理错误和异常情况。\nurllib.parse用于解析和构建 URL提供各种操作如分割、组合、编码和解码。\nurllib.robotparser用于解析网站的 robots.txt 文件,确定哪些页面可以被爬取。\n\n优点\n\n内置模块作为 Python 标准库的一部分,无需单独安装。\n全面功能支持多种网络协议和操作适用于多种网络操作需求。\n高度可定制用于处理 URL 的多个方面,如打开、读取、解析等。\n\n缺点\n\n较低层次的 API与一些第三方库相比如 requestsurllib 的 API 较为底层,可能需要编写更多的代码。\n繁琐的错误处理错误处理需要额外的代码相比使用像 requests 这样的库可能更复杂。\n\n同类产品对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n产品优点缺点适用背景社区支持urllib标准库全面API 较底层网络请求URL 操作Python 社区requestsAPI 简单需要单独安装HTTP 请求Python 社区httplib2功能丰富使用复杂HTTP 请求Python 社区\nurllib.request\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法功能描述示例urlopen()打开并读取一个 URL 的内容urllib.request.urlopen(url)urlretrieve()将 URL 指向的文件下载到本地urllib.request.urlretrieve(url, filename)build_opener()构建一个可自定义的 Opener 对象opener = urllib.request.build_opener()install_opener()安装全局的 Openerurllib.request.install_opener(opener)HTTPBasicAuthHandler()HTTP 基础认证处理程序handler = urllib.request.HTTPBasicAuthHandler()HTTPCookieProcessor()用于处理 HTTP cookieshandler = urllib.request.HTTPCookieProcessor()ProxyHandler()设置代理proxy = urllib.request.ProxyHandler({'http': 'www.example.com:8080'})Request()创建一个请求对象,用于定制 HTTP 头等req = urllib.request.Request(url, headers={...})\nurlopen() 打开 URL\nimport urllib.request\n \n# 打开一个网页\nresponse = urllib.request.urlopen('www.example.com')\n \n# 读取网页内容\ndata = response.read()\n \n# 输出网页内容\nprint(data)\nurlretrieve() 下载文件\nimport urllib.request\n \n# 从指定 URL 下载文件,并保存到本地\nurllib.request.urlretrieve('www.example.com/file.txt', 'local_file.txt')\nbuild_opener() 和 install_opener()\nbuild_opener() 传递一系列处理程序handlers这些处理程序用于定义如何处理各种 HTTP 功能比如重定向、基础认证、cookies 等。一旦你使用 build_opener() 创建了一个 Opener 对象,你可以使用 install_opener() 来设置它作为默认的 Opener。\nimport urllib.request\n \n# 创建基础认证处理程序\nauth_handler = urllib.request.HTTPBasicAuthHandler()\nauth_handler.add_password('realm', 'host', 'username', 'password')\n \n# 创建代理处理程序\nproxy_handler = urllib.request.ProxyHandler({'http': 'www.proxy.com:8080'})\n \n# 创建 Opener\nopener = urllib.request.build_opener(auth_handler, proxy_handler)\n \n# 安装 Opener\nurllib.request.install_opener(opener)\n \n# 使用 urlopen() 方法,这样会应用我们之前设置的所有处理程序\nresponse = urllib.request.urlopen('www.example.com')\nHTTP 基础认证 (HTTPBasicAuthHandler)\nimport urllib.request\n \n# 创建一个 HTTPBasicAuthHandler 对象\nauth_handler = urllib.request.HTTPBasicAuthHandler()\n \n# 添加认证信息\nauth_handler.add_password('realm', 'host', 'username', 'password')\n \n# 创建并安装 opener\nopener = urllib.request.build_opener(auth_handler)\nurllib.request.install_opener(opener)\nHTTPCookieProcessor 处理 Cookies\nimport urllib.request\nimport http.cookiejar\n \n# 创建一个 CookieJar 对象\ncookie_jar = http.cookiejar.CookieJar()\n \n# 创建一个 HTTPCookieProcessor 对象\ncookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)\n \n# 构建和安装 opener\nopener = urllib.request.build_opener(cookie_handler)\nProxyHandler 设置代理\nimport urllib.request\n \n# 创建一个 ProxyHandler 对象\nproxy_handler = urllib.request.ProxyHandler({'http': 'www.proxy.com:8080'})\n \n# 构建并安装 opener\nopener = urllib.request.build_opener(proxy_handler)\nRequest() 自定义请求\nimport urllib.request\n \n# 创建一个 Request 对象\nreq = urllib.request.Request(url='www.example.com', headers={'User-Agent': 'MyApp/1.0'})\n \n# 使用 urlopen 打开自定义的请求\nresponse = urllib.request.urlopen(req)\nurllib.error\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法功能描述URLError所有 urllib 产生的异常的基类HTTPError处理 HTTP 错误状态,继承自 URLErrorContentTooShortError在下载过程中数据不足时抛出的异常\nURLError\n当使用 urllib.request 打开一个 URL 失败时,通常会抛出 URLError 异常。\nimport urllib.request\nimport urllib.error\n \ntry:\n response = urllib.request.urlopen('www.nonexistentwebsite.com')\nexcept urllib.error.URLError as e:\n print(e.reason)\nHTTPError\n当服务器返回 HTTP 错误状态码(如 404、500 等)时,会抛出 HTTPError。\nimport urllib.request\nimport urllib.error\n \ntry:\n response = urllib.request.urlopen('www.example.com/404')\nexcept urllib.error.HTTPError as e:\n print(f'HTTP Error Code: {e.code}')\n print(f'Reason: {e.reason}')\nContentTooShortError\n如果使用 urlretrieve() 函数,但获取的数据长度与 Content-Length 头中声明的长度不匹配时,会抛出 ContentTooShortError。\nimport urllib.request\nimport urllib.error\n \ntry:\n urllib.request.urlretrieve('www.example.com/file', 'local_file.txt')\nexcept urllib.error.ContentTooShortError as e:\n print('The downloaded data is less than expected.')\nurllib.parse\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法功能描述示例urlparse()解析 URL返回一个 ParseResult 对象urllib.parse.urlparse(url)urlunparse()将 ParseResult 对象转回 URLurllib.parse.urlunparse(parse_result)urlsplit()类似于 urlparse(),但不分割 paramsurllib.parse.urlsplit(url)urlunsplit()将由 urlsplit() 返回的对象转回 URLurllib.parse.urlunsplit(split_result)urljoin()合并两个 URLurllib.parse.urljoin(base, url)urlencode()将字典或序列转换为 URL 查询字符串urllib.parse.urlencode(query_dict)quote()将字符串进行 URL 编码urllib.parse.quote(string)unquote()对 URL 编码的字符串进行解码urllib.parse.unquote(encoded_string)\n解析和构建 URL\nfrom urllib.parse import urlparse, urlunparse, urlsplit, urlunsplit, urljoin\n \n# 解析URL并返回ParseResult对象\nparsed_url = urlparse('www.example.com/path#039;)\n \n# 将ParseResult对象转换回URL\nnew_url = urlunparse(parsed_url)\n \n# 类似于urlparse()但不分割params\nsplit_result = urlsplit('www.example.com/path#039;)\n \n# 将由urlsplit()返回的对象转换回URL\noriginal_url = urlunsplit(split_result)\n \n# 合并两个URL\nnew_url = urljoin('www.example.com/path/', '/anotherpath.html')\n \n转换查询字符串\nfrom urllib.parse import urlencode\n \n# 将字典或序列转换为URL查询字符串\nquery_dict = {'key1': 'value1', 'key2': 'value2'}\nquery_string = urlencode(query_dict)\n \nURL 编码和解码\nfrom urllib.parse import quote, unquote\n \n# 将字符串进行URL编码\nencoded = quote('a string with / and ?')\n \n# 对URL编码的字符串进行解码\ndecoded = unquote(encoded)\nurllib.robotparser\n通过使用 urllib.robotparser你可以确保你的网络爬虫尊重网站的抓取策略这是一种负责任的爬虫行为。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法功能描述示例RobotFileParser()创建一个 RobotFileParser 对象rp = urllib.robotparser.RobotFileParser()set_url()设置 robots.txt 文件的 URLrp.set_url('www.example.com/robots.txt')read()从设置的 URL 读取 robots.txt 文件rp.read()parse()用于手动解析 robots.txt 文件的行rp.parse(robots_txt_body.split("\\n"))can_fetch()检查指定的 User-Agent 是否可以访问某个路径rp.can_fetch('*', 'www.example.com/page')mtime()获取最后一次获取 robots.txt 文件的时间Unix 时间戳rp.mtime()modified()设置最后一次获取 robots.txt 文件的时间rp.modified()\n创建和设置 RobotFileParser\n首先你需要创建一个 RobotFileParser 对象,并设置要解析的 robots.txt 文件的 URL。\nimport urllib.robotparser\n \n# 创建 RobotFileParser 对象\nrp = urllib.robotparser.RobotFileParser()\n \n# 设置 robots.txt 文件的 URL\nrp.set_url('www.example.com/robots.txt')\n \n# 从 URL 读取 robots.txt 文件\nrp.read()\n检查爬虫是否可以访问特定页面\n使用 can_fetch() 方法,您可以检查指定的 User-Agent 是否被允许抓取特定的网页路径。\n# 检查 '*'(所有 User-Agents是否允许访问 '/page'\nallowed = rp.can_fetch('*', 'www.example.com/page')\n \nif allowed:\n print("I can crawl this page.")\nelse:\n print("I cannot crawl this page.")\n手动解析 robots.txt\n如果你需要手动解析 robots.txt 文件的内容,可以使用 parse() 方法。\n# 假设 robots_txt_body 包含了 robots.txt 的文本内容\nrobots_txt_body = '''\nUser-agent: *\nDisallow: /private/\n'''\n \n# 手动解析这些规则\nrp.parse(robots_txt_body.split("\\n"))"},"Technology/ProgrammingLanguage/Python/进阶/函数式编程":{"title":"函数式编程","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"函数式编程\n函数式编程是什么\n函数式编程Functional Programming, FP是一种编程范式**主张用数学上的函数方式构建结构和元素之间的关系,而不是改变状态和数据。**在函数式编程中,函数是第一公民,这意味着函数可以被传递、返回和操作,就像其他的数据类型一样。函数在这里是「纯」的,意味着相同的输入始终产生相同的输出,并且没有副作用。\n# 函数作为参数传递给另一个函数\ndef apply(func, value):\n return func(value)\n \nresult = apply(lambda x: x*2, 5) # 输出10\n函数式编程与其他编程范式的区别\n函数式编程与命令式编程的区别在于命令式编程关注如何完成任务强调程序状态和改变状态的语句而**函数式编程注重数据的映射和组合。**面向对象编程重视对象及其之间的交互,而函数式编程重视函数和数据处理。\n函数式编程的优势和局限性\n优势\n\n简洁性函数式编程往往更简洁可以用更少的代码做更多的事情。\n可维护性由于函数式编程的代码没有副作用它通常更容易维护和调试。\n可重用性函数是高度模块化的可以在多个地方重用。\n\n局限性\n\n内存使用由于函数式编程倾向于复制数据而不是改变它它可能使用更多的内存。\n难度对于不熟悉该范式的开发者来说函数式编程可能较难学习。\n\nPython 中的基础函数式工具\nPython 提供了一些内置的函数式工具,如 lambdamap()filter() 和 reduce(),它们可以帮助你以函数式的方式处理数据。\nlambda\nlambda 允许我们定义简短的匿名函数。\ndouble = lambda x: x * 2\nprint(double(5)) # 输出10\nmap()\nmap() 函数将指定函数应用于序列的每一个元素。\nnums = [1, 2, 3, 4]\nsquared = list(map(lambda x: x**2, nums)) # 输出[1, 4, 9, 16]\nfilter()\nfilter() 函数根据指定函数的判断结果来过滤序列。\nnums = [1, 2, 3, 4, 5]\nevens = list(filter(lambda x: x % 2 == 0, nums)) # 输出[2, 4]\nreduce()\nreduce() 函数对序列中的元素进行连续、累计地应用指定函数。\nfrom functools import reduce\n \nnums = [1, 2, 3, 4]\nproduct = reduce(lambda x, y: x*y, nums) # 输出24\nfunctools 模块\nfunctools 模块提供了一些用于函数式编程的实用工具,如偏函数等。\nfrom functools import partial\n \ndef multiply(x, y):\n return x * y\n \ndouble = partial(multiply, 2)\nprint(double(4)) # 输出8\n高阶函数\n高阶函是数什么\n高阶函数接受一个或多个函数作为参数或者返回一个函数。\ndef greet(type_):\n if type_ == 'hello':\n return lambda name: "Hello, " + name\n else:\n return lambda name: "Hi, " + name\n \ngreeting = greet('hello')\nprint(greeting('Alice')) # 输出'Hello, Alice'\n在 Python 中创建和使用高阶函数\n除了 Python 内置的如 map、filter 和 reduce 这样的高阶函数外,我们也可以创建自己的高阶函数。\ndef apply(func, data):\n return [func(item) for item in data]\n \nnums = [1, 2, 3, 4]\nresult = apply(lambda x: x*2, nums) # 输出[2, 4, 6, 8]\n纯函数和不变性\n纯函数是什么\n纯函数是函数式编程的核心概念之一。一个函数被认为是纯的当它满足以下条件时\n\n给定相同的输入总是返回相同的输出。\n没有任何副作用例如修改全局状态、修改传入的参数、进行 I/O 操作等)。\n\n这些特性使纯函数变得可预测且容易测试。\n# 纯函数示例\ndef add(x, y):\n return x + y\n \n# 不纯的函数示例,因为它改变了外部状态\ncounter = 0\ndef increment():\n global counter\n counter += 1\n return counter\n数据的不变性\n在函数式编程中数据是不可变的。这意味着一旦一个数据结构被创建就不能再改变它。而是每次需要修改数据时都会返回一个新的数据副本。\n这一特性增加了代码的可读性和可预测性因为你不必担心数据在不知情的情况下被修改。\n# 使用列表作为示例\nlst = [1, 2, 3]\n \n# 错误的做法:修改原始列表\nlst.append(4)\n \n# 正确的做法:创建新的列表\nnew_lst = lst + [4]\n装饰器\nPython 中的装饰器\n装饰器是 Python 中的一个强大工具,它允许开发者**在不修改原始函数代码的情况下,给函数增加新的功能。**它们通常用于日志、权限检查、统计或其他跨越多个函数或方法的通用任务。\ndef my_decorator(func):\n def wrapper():\n print("Something is happening before the function is called.")\n func()\n print("Something is happening after the function is called.")\n return wrapper\n \n@my_decorator\ndef say_hello():\n print("Hello!")\n \nsay_hello()\n如何利用装饰器优化代码\n如上所示装饰器是一个返回另一个函数的函数。要使用装饰器只需在你想要装饰的函数上方加上 @decorator_name。\ndef repeat(num):\n def decorator_repeat(func):\n def wrapper(*args, **kwargs):\n for _ in range(num):\n result = func(*args, **kwargs)\n return result\n return wrapper\n return decorator_repeat\n \n@repeat(num=4)\ndef greet(name):\n print(f"Hello, {name}")\n \ngreet("Alice") # 输出四次 "Hello, Alice"\n闭包和自由变量\n闭包是一种特殊的函数它可以记住在其所在作用域中声明的自由变量的值即使它们在函数外部是不可用的。在更简单的语言中闭包允许函数携带与之相关的数据。\n在 Python 中,当内部函数引用了外部函数中的变量,内部函数就被认为是闭包。\ndef outer_function(x):\n def inner_function(y):\n return x + y\n return inner_function\n \nclosure = outer_function(10)\nprint(closure(5)) # 输出15\n递归\n递归是一种编程技巧其中函数调用自身以解决较小的问题实例。递归通常与某种终止条件结合使用以防止无限的自我调用。递归函数的经典例子是计算阶乘\n# 此函数会不断调用自己直到n为1。\ndef factorial(n):\n if n == 1:\n return 1\n return n * factorial(n - 1)\n \nprint(factorial(5)) # 输出120\n递归、迭代对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比点递归迭代直观性通常更直观和更容易实现通常需要使用循环结构可能不如递归直观自然选择对于某些问题如树的遍历递归是自然的选择对于基本的数据结构如数组和链表迭代是自然选择函数调用可能会导致大量的函数调用从而可能达到调用堆栈的限制由于是循环结构不会导致函数调用的堆栈溢出效率对于大量的递归可能不如迭代高效对于简单的循环迭代可能更加高效内存使用每次调用自己都需要额外的内存来存储变量和信息可能会导致调用堆栈溢出通常更为内存高效因为它不需要为每次循环存储额外的信息实现方式函数调用自己直到满足某个条件使用循环结构如 for 和 while"},"Technology/ProgrammingLanguage/Python/进阶/垃圾回收":{"title":"垃圾回收","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"引用和引用计数\nPython 中的引用概念\n**在 Python 中,所有的数据都是以对象的形式存在。**当我们创建一个变量并赋值时,实际上 Python 会为我们创建一个对象,然后变量会引用这个对象。这种关系,我们称之为引用。\n例如\na = 1\n这里数字 1 是一个 int 类型的对象,变量 a 是对这个对象的引用。\n引用计数的基本原理\n**Python 使用一种叫做引用计数的方式来管理内存。**每一个对象都有一个引用计数,用来记录有多少个引用指向这个对象。当这个计数值变为 0 时, Python 就知道没有任何引用指向这个对象,这个对象就可以被安全地销毁了,它占用的内存就会被释放。\n例如\na = 1 # 引用计数为1\nb = a # 引用计数为2\na = None # 引用计数为1\nb = None # 引用计数为0对象被销毁\n引用计数的增减和对象的创建与销毁过程\ngraph LR\n A[Python 对象] --> |创建| B(引用计数增加)\n B --> C{引用计数是否为0?}\n C -->|是| D[对象被立即回收]\n C -->|否| E[对象继续存在]\n E --> F{是否存在循环引用?}\n F --> |是| G[标记-清除处理]\n G --> H[分代回收处理]\n F --> |否| I[对象持续存在]\n H --> J{是否到达阈值?}\n J -->|是| K[触发垃圾回收]\n J -->|否| I\n K --> L[回收结束,对象被销毁]\n\n每当我们创建一个新的引用赋值操作对象的引用计数就会增加 1。当我们删除一个引用例如赋值为 None 或者使用 del 命令),对象的引用计数就会减少 1。当引用计数变为 0 时Python 的垃圾回收器就会销毁这个对象并回收它所占用的内存。\n循环引用和引用计数的限制\n循环引用的概念和问题\n**循环引用是指两个或更多的对象互相引用,形成一种闭环。**在这种情况下,即使没有其他引用指向这些对象,它们的引用计数也永远不会变为 0所以它们不会被 Python 的垃圾回收器销毁,导致内存泄漏。\n例如\nclass Node:\n def __init__(self):\n self.other = None\n \na = Node()\nb = Node()\na.other = b # a 引用了 b\nb.other = a # b 引用了 a形成了循环引用\n引用计数无法解决的循环引用问题\n这正是引用计数法的一个主要弱点。尽管它简单易懂但它不能处理循环引用的问题。在上面的例子中即使我们删除了对 a 和 b 的引用,它们也不会被销毁,因为它们互相引用,它们的引用计数永远不会变为 0。\ndel a\ndel b\n# 现在a 和 b 形成的循环引用对象仍然存在,但我们无法访问它们\n引用计数的弱点和限制\n引用计数法的另一个弱点是它的开销相对较大。每次创建或删除引用时Python 都需要更新引用计数。这可能在大量对象创建和销毁的情况下成为性能瓶颈。\n垃圾回收算法\n垃圾回收算法的概述\n为了解决引用计数法不能处理循环引用的问题Python 引入了两种垃圾回收算法:标记 - 清除算法和分代回收算法。这两种算法都是为了检测和回收循环引用的对象。\n标记 - 清除算法的原理和流程\n标记 - 清除算法是一种基础的垃圾回收算法。它的**基本原理是通过标记和清除两个步骤来回收垃圾对象。**在标记步骤中,从某些根对象(例如全局变量)出发,遍历所有可达的对象,将这些对象标记为活动。剩下的未被标记的对象(即不可达的对象)就被认为是垃圾。然后在“清除”步骤中,清除所有标记为“垃圾”的对象。\n在 Python 中,标记 - 清除算法主要用于检测和清除循环引用对象。它的工作流程是这样的:\n\n从所有的容器对象例如列表、字典和类实例等出发找出所有可能形成循环引用的对象。\n对这些对象应用标记 - 清除算法,找出并清除真正的循环引用对象。\n\n分代回收算法的原理和优化\n分代回收是 Python 用来优化垃圾回收性能的一种方式。它的**基本思想是将所有的对象分为几代,每一代的对象有自己的生命周期和回收策略。**新创建的对象被放入第一代,当这一代的对象经历了一定次数的垃圾回收后仍然存活,就被移到下一代。每一代的垃圾回收频率都不同,通常,越年轻的代的垃圾回收频率越高。\nPython 的分代回收有三代。新创建的对象被放入第一代generation 0当它经历了一次垃圾回收后仍然存活就被移到第二代generation 1。同样第二代的对象在经历了一次垃圾回收后仍然存活就被移到第三代generation 2。第三代的对象在经历了一次垃圾回收后仍然存活就留在第三代。每一代的垃圾回收频率都不同第一代的频率最高第三代的频率最低。\n分代回收算法的优点是它可以减少垃圾回收的开销因为经常产生垃圾的通常是生命周期短的对象例如临时变量而生命周期长的对象例如全局变量很少产生垃圾。这种方式可以让 Python 更加聚焦于可能产生垃圾的地方,从而提高垃圾回收的效率。\nPython 中的垃圾回收算法实现\nsequenceDiagram\n participant O as Python对象\n participant RC as 引用计数\n participant GM as 垃圾回收机制\n participant GC as gc模块\n O->>RC: 创建对象,引用计数+1\n RC-->>O: 维持对象\n RC->>GM: 检查引用计数是否为0\n GM-->>RC: 不为0继续维持\n RC->>GM: 引用计数变为0\n GM-->>O: 对象被立即回收\n GM->>GC: 检查是否存在循环引用\n GC-->>GM: 存在循环引用\n GM->>GC: 触发标记-清除\n GC-->>GM: 清除循环引用\n GM->>GC: 触发分代回收\n GC-->>GM: 分代回收完成\n GM->>GC: 检查是否达到阈值\n GC-->>GM: 达到阈值\n GM->>O: 触发垃圾回收,对象被销毁\n GM->>GC: 检查是否达到阈值\n GC-->>GM: 没有达到阈值\n GM-->>GC: 继续监视\n\nPython 的垃圾回收机制是基于引用计数的,当对象的引用计数降到 0 时该对象就会被立即回收。但是对于循环引用的问题Python 使用标记 - 清除和分代回收两种算法来解决。\n首先Python 使用标记 - 清除算法来检测和清除循环引用的对象。然后为了优化垃圾回收的性能Python 会根据对象的存活时间将它们分成三代并分别进行回收。这样Python 就能有效地管理内存,同时尽可能地降低垃圾回收的开销。\nGc 模块\nPython 通过 gc 模块提供了对垃圾回收机制的直接控制。gc 模块提供了一些函数,让我们可以手动触发垃圾回收,查询垃圾回收的状态,或者调整垃圾回收的参数。\n基础功能\n下面是一些常用的 gc 函数:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n函数描述gc.enable()启用自动垃圾回收。gc.disable()禁用自动垃圾回收。gc.isenabled()查看自动垃圾回收是否被启用。gc.collect(generation=2)立即进行一次垃圾回收。可以通过 generation 参数指定要收集的代的编号0 代表最年轻的一代2 代表所有代。gc.set_threshold(threshold0, threshold1=None, threshold2=None)设置垃圾回收的阈值。当某一代的垃圾数量超过对应的阈值时就会触发垃圾回收。gc.get_threshold()获取当前的垃圾回收阈值。gc.get_count()获取当前每一代的垃圾数量。gc.get_objects()返回一个列表包含所有当前被监视的对象。gc.get_stats()返回一个字典包含垃圾回收的统计信息。gc.set_debug(flags)设置垃圾回收的调试标志。gc.get_debug()获取当前的垃圾回收调试标志。gc.get_referents(*objs)返回一个列表包含所有给定对象的直接引用对象。gc.get_referrers(*objs)返回一个列表,包含所有直接引用给定对象的对象。\n下面是一个简单的例子演示了如何使用 gc 模块:\nimport gc\n \n# 手动触发垃圾回收\ngc.collect()\n \n# 获取当前的计数器值\nprint(gc.get_count())\n \n# 获取当前的阈值\nprint(gc.get_threshold())\n \n# 设置新的阈值\ngc.set_threshold(500)\n \n# 获取所有存在的对象\nprint(len(gc.get_objects()))\n \n# 获取统计信息\nprint(gc.get_stats())\n高级用法\n除了上述的基本功能gc 模块还提供了一些高级功能,例如你可以注册自己的回调函数,当垃圾回收发生时,这些回调函数就会被调用。这可以用来监控垃圾回收的过程,或者调试内存泄漏的问题。\n下面是一个例子演示了如何注册回调函数\nimport gc\n \ndef callback(phase, info):\n print(f"{phase}: {info}")\n \n# 注册回调函数\ngc.callbacks.append(callback)\n \n# 触发垃圾回收\ngc.collect()\n在这个例子中每次垃圾回收发生时callback 函数都会被调用,它会打印出垃圾回收的阶段和一些信息。\n总结\nPython 的垃圾回收机制是基于引用计数的它简单高效但无法处理循环引用的问题。为了解决这个问题Python 引入了标记 - 清除和分代回收两种垃圾回收算法。这两种算法可以有效地检测和清除循环引用的对象,同时优化垃圾回收的性能。\nPython 通过 gc 模块提供了对垃圾回收机制的直接控制。通过 gc 模块,我们可以手动触发垃圾回收,查询垃圾回收的状态,或者调整垃圾回收的参数。我们甚至可以注册自己的回调函数,以便在垃圾回收发生时获取通知。"},"Technology/ProgrammingLanguage/Python/进阶/并行和并发":{"title":"并行和并发","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"基础概念\n并发与并行\ngraph TD\n concurrency[并发]\n task1[任务1] --> run1[运行...]\n task2[任务2] --> run2[运行...]\n task3[任务3] --> run3[运行...]\n \n concurrency --> task1\n concurrency --> task2\n concurrency --> task3\n\n并发Concurrency指的是多个任务在近似同一时间内启动和运行的能力。不同于并行这些任务不一定在同一时间点真正地执行但它们可能看起来似乎是同时进行的。这经常是通过任务切换或调度来实现的使得每个任务都可以得到处理器的时间片并轮流执行。\n\n例子一个银行柜台只有一位出纳员但有多位客户在排队等待服务。出纳员可能会处理第一个客户的部分业务然后转向第二个客户处理其业务之后再返回第一个客户以此类推。\n尽管在任何特定时刻只有一个客户正在得到服务但因为切换得足够快所有的客户可能都觉得自己几乎是在同一时间得到服务的。这就是并发。\n\n\ngraph TD\n parallelism[并行]\n cpu1[处理单元1] --> run1[运行任务1]\n cpu2[处理单元2] --> run2[运行任务2]\n cpu3[处理单元3] --> run3[运行任务3]\n \n parallelism --> cpu1\n parallelism --> cpu2\n parallelism --> cpu3\n\n**并行Parallelism指的是多个任务或多个处理单元在同一时刻真正地同时执行。**与并发不同,它不仅仅是任务准备同时运行或看似同时运行,而是真正地在同一时刻执行。这通常在具有多个处理器或多个核心的计算机系统中发生。\n\n例子一个快餐店里面有三个员工。当三位顾客同时走进店内并分别点餐时如果每位员工分别为每位顾客制作餐点而且三位员工都在同一时刻开始并同时完成任务那么这就是并行。\n每位员工和他们分别服务的顾客可以看作是一个处理单元和一个任务。\n\n同步与异步\ngraph TD\n synchronous[同步]\n op1[操作1] --> op2[操作2]\n op2 --> op3[操作3]\n \n synchronous --> op1\n\n**同步Synchronous描述的是一个操作或任务需要等待另一个操作或任务完成之后才能开始或继续执行。**它通常涉及一种线性或顺序的流程,其中一个操作完全依赖于另一个操作的完成。\n\n例子在超市结账时如果只有一个收银员那么顾客需要按照顺序来结账。第一个顾客必须完成结账并离开第二个顾客才能开始结账以此类推。\n这里的每个结账过程都是同步的因为每个顾客的结账必须在前一个顾客完成后才能开始。\n\ngraph LR\n asynchronous[异步]\n op1[操作1] --> callback1[回调1]\n op2[操作2]\n op3[操作3]\n \n asynchronous --> op1\n asynchronous --> op2\n asynchronous --> op3\n\n**异步Asynchronous描述的是一个操作开始后并不需要等待其完成可以继续执行其他操作。**一旦异步操作完成,通常通过回调、事件、通知或其他机制来获取结果或进一步处理。\n\n例子你在一家咖啡店点了一杯咖啡。而不是站在柜台等待咖啡制作完成你可以找个座位坐下甚至看书或工作。当咖啡制作好店员会叫你的名字或号码此时你前去取杯。\n在这个期间你并没有闲置而是进行了其他活动。\n\n阻塞与非阻塞\ngraph TD\n blocking[阻塞]\n op1[操作1] --> wait[等待资源...]\n \n blocking --> op1\n\n阻塞Blocking描述的是当一个操作或任务等待某个条件通常是某种资源满足时它会进入一个暂停或等待状态。在该条件被满足之前操作或任务不会继续执行。\n\n例子你在电话上等待客服代表。在你等待的时候你不能使用电话进行其他通话也不能结束当前的通话直到客服代表接听你的电话。\n在这段时间里你的电话线路被阻塞。\n\ngraph LR\n nonBlocking[非阻塞]\n op1[操作1] --> return[立即返回]\n continueOp[继续其他操作] \n \n nonBlocking --> op1\n op1 --> continueOp\n\n**非阻塞Non-blocking描述的是当一个操作或任务遇到必须等待的条件如等待某种资源它不会进入暂停或等待状态而是立即返回让程序可以继续执行其他操作。**当原始操作可以继续进行时,它会在适当的时间继续。\n\n例子一个自助餐厅。即使前面的人在选择食物并花费很长时间你也可以选择跳过他们去取你想要的食物而不必等待。\n这种情况下你的选择流程是非阻塞的\n\n特性对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性适用背景优点缺点注意事项并发多任务需在相近的时间内执行但不一定同时 - 单核或多核系统资源高效利用、提高响应性任务管理和调度可能复杂需要避免任务间的资源争用并行同时执行多任务、多核或多处理器系统性能大幅提升、任务真正同时执行需要硬件支持、并行化设计可能复杂要注意数据共享和并行任务之间的同步同步当一个任务需要另一个任务的结果时、线性流程简单易理解、流程清晰可能导致资源浪费和延迟避免长时间的同步操作异步当任务之间无直接依赖关系、同时处理多个操作时提高效率、无需等待需要处理任务完成的回调或通知要确保正确处理回调和错误阻塞当任务需要等待某资源或条件满足时简单的编程模型、确保条件满足导致程序或线程停滞、资源可能被浪费尽量避免长时间的阻塞操作非阻塞当任务在等待某条件时仍需进行其他操作响应迅速、资源高效利用程序逻辑可能变得复杂需要检查操作是否真的完成或资源是否真的可用\n进程和线程\n进程\n进程是什么\n进程是计算机中的程序关于某数据集的一次运行活动。它是系统资源分配的基本单位并拥有独立的内存空间。进程具有自己的代码段、数据段和系统资源。\n为什么需要进程\n\n进程使操作系统可以多任务处理同时执行多个程序。每个进程在其独立的地址空间中运行互不干扰。\n进程提供了应用程序执行的隔离环境确保一个进程的故障不会影响到其他进程。\n进程间的隔离也增强了系统的安全性。\n\n进程间通信IPC队列管道\n\nIPCInter-Process Communication允许进程间相互通信和同步的技术。它包括信号、消息、共享内存等方法。\n队列是一个先进先出FIFO的数据结构可以用于进程间发送消息。\n管道是一个双向通信的方法允许一个进程的输出成为另一个进程的输入。管道通常用于父子进程间的通信。\n\n线程\n线程是什么\n线程是进程内部的执行单位它是 CPU 调度和分派的基本单位。同一进程内的线程共享进程的资源,如内存、文件句柄等。但每个线程有其自己的运行栈和程序计数器。\nthreading 模块\nPython 的 threading 模块提供了低级线程 API使我们可以轻松创建和管理线程。以下是如何使用 threading.Thread 创建新线程的示例:\nimport threading\n \ndef print_numbers():\n for i in range(10):\n print(i)\n \nthread = threading.Thread(target=print_numbers)\nthread.start()\nthread.join()\n全局解释器锁GIL\nGIL 是什么\nGIL 是 Python 解释器中的一个锁,它使得任何时候只有一个线程在执行。此锁仅存在于 CPython 解释器中。\n\nPython 官方社区计划在 3.12 以后版本逐步移除 GIL 锁。\n\nGIL 的存在原因\n\nGIL 的主要目的是简化 CPythonPython 的标准解释器的实现。由于多线程并发访问数据可能会导致数据损坏或不一致的情况GIL 可以防止这种情况的发生。\nCPython 的内存管理不是线程安全的GIL 可以保证同时只有一个线程执行 Python 字节码,从而避免并发访问的问题。\n\nGIL 对多线程程序的影响\n\n由于 GIL 的存在,多线程的 Python 程序不能充分利用多核心 CPU 的优势因为任何时候都只有一个线程在执行。这意味着在计算密集型任务上Python 的多线程并不总是有效的。\n对于 I/O 密集型任务,多线程仍然是有效的,因为线程在等待 I/O 操作完成时可以释放 GIL这允许其他线程执行。\n要真正充分利用多核心Python 开发者通常会使用进程级的并发(如 multiprocessing 模块)或使用其他没有 GIL 限制的 Python 实现,例如 Jython 或 IronPython。\n\nPython 并发库\n并发是一种技术可以使多个任务似乎在同一时间执行。Python 提供了多种方式来实现并发,以下是其中的一些主要方式。\nmultiprocessing多进程\nPython 由于 GIL全局解释器锁的存在在多线程时并不能充分利用多核 CPU。为了避免 GIL 的限制,可以使用 multiprocessing 模块创建多个进程。\n\n\n优点可以充分利用多核 CPU、进程间内存是隔离的增加了安全性。\n\n\n**缺点:**进程启动和通信相对较慢。\n\n\nfrom multiprocessing import Process\n \ndef print_hello(name):\n print(f"Hello, {name}!") # 输出Hello, world!\n \np = Process(target=print_hello, args=('world',))\np.start()\np.join()\nconcurrent.futures线程池与进程池\nconcurrent.futures 提供了高层次的异步执行接口,支持线程池和进程池。\n线程池\n线程比进程轻量创建和切换成本较低但受到 GIL 的限制。\nfrom concurrent.futures import ThreadPoolExecutor\n \n# 使用线程池\nwith ThreadPoolExecutor(max_workers=4) as executor:\n results = list(executor.map(print_hello, ['world', 'python', 'asyncio']))\n # 输出(注意:线程执行的顺序可能是不确定的,以下只是一个可能的输出):\n # Hello, world!\n # Hello, python!\n # Hello, asyncio!\n进程池\nfrom concurrent.futures import ProcessPoolExecutor\n \n# 使用进程池\nwith ProcessPoolExecutor(max_workers=4) as executor:\n results = list(executor.map(print_hello, ['world', 'python', 'asyncio']))\n # 输出(进程的执行顺序可能是不确定的,以下只是一个可能的输出):\n # Hello, world!\n # Hello, python!\n # Hello, asyncio!\nasyncio异步协程\nasyncio 是 Python 的异步编程框架,它使用事件循环驱动的协程来实现并发。\n事件循环\n事件循环是异步编程的核心用于调度和执行任务确保异步任务的非阻塞执行。通过使用 asyncio.get_event_loop() 获取当前事件循环。\n协程\n协程是 asyncio 的核心部分。使用 async def 定义协程,使用 await 在协程中等待另一个协程完成。\nimport asyncio\n \nasync def main():\n print('Hello') # 输出Hello\n await asyncio.sleep(1)\n print('World') # 输出World\n \nasyncio.run(main())\n高级异步特性\n异步生成器\n可以在一个异步函数中产生多个值。\nimport asyncio\n \nasync def async_gen():\n for i in range(3):\n await asyncio.sleep(1)\n yield i\n \nasync def main_gen():\n async for value in async_gen():\n print(value) # 输出0 1 2\n \nasyncio.run(main())\n \n异步上下文管理器\n允许使用 async with 语句进行异步资源管理。\nclass AsyncContextManager:\n async def __aenter__(self):\n print("Entered the async context.") # 输出Entered the async context.\n return self\n \n async def __aexit__(self, exc_type, exc, tb):\n print("Exited the async context.") # 输出Exited the async context.\n \nasync def main_context():\n async with AsyncContextManager() as acm:\n print("Inside the async context.") # 输出Inside the async context.\n \nasyncio.run(main_context())\nPython 的并发库为开发者提供了多种选择,选择哪种方式取决于具体的应用需求和场景。不管选择哪种方式,重要的是理解其背后的工作原理和限制,这样可以更好地实现并发,并提高应用的性能。\n其他异步框架和库\nTornado\nTornado 是一个 Python Web 服务器软件的开放源码版本。由于其非阻塞 I/O 设计它能够处理大量的长连接非常适用于长轮询、WebSockets 等网络协议。与传统的多线程和多进程服务器相比Tornado 使用单线程事件循环,可以高效地管理数千甚至数百万的并发连接。\nTwisted\nTwisted 是一个事件驱动的网络引擎,用于构建各种网络应用。除了支持常见的网络协议如 HTTP、SMTP、POP3、FTP 等Twisted 还提供了其它功能如身份验证、SSL 和其他安全特性。Twisted 的设计理念是为开发者提供最大的灵活性,允许他们使用自己喜欢的工具和库。\nQuart\nQuart 是一个基于 Python 的 ASGI Web 微框架。尽管它的 API 与 Flask 极为相似,但由于集成了 asyncio 的异步功能Quart 可以提供更高的响应速度。使用 Quart开发者可以无缝地将 Flask 代码迁移到一个异步环境中,从而充分利用现代硬件的并发性。\n锁、信号量和同步原语\n互斥锁 (Mutex)\n**互斥锁确保特定资源或代码段在同一时间只能被一个线程访问。**例如,如果两个线程尝试同时更新一个共享的数据结构,没有适当的同步可能会导致数据损坏。互斥锁就是这样一个保护机制,确保资源的一致性和完整性。\nimport threading\n \n# 创建一个互斥锁\nmutex = threading.Lock()\n \ndef update_data():\n # 获取锁\n mutex.acquire()\n \n try:\n # TODO: 更新共享资源\n pass\n finally:\n # 释放锁\n mutex.release()\n \n# 启动多个线程来调用update_data\n读写锁\n读写锁是一种特殊的锁针对读者 - 作者问题而设计。当资源经常被读取但很少被修改时,读写锁是很有用的。在这种情况下,多个读线程可以并发访问资源,但写线程会阻塞所有其他线程,确保在写操作期间资源的完整性。\nfrom rwlock import RWLock\n \nrwlock = RWLock()\n \ndef read_data():\n with rwlock.r_lock():\n # TODO: 读取数据\n pass\n \ndef write_data():\n with rwlock.w_lock():\n # TODO: 修改数据\n pass\n信号量 (Semaphore)\n与互斥锁不同信号量允许多个线程并发访问资源但是数量是有限的。例如如果你有一个包含 5 个数据库连接的连接池,你可以使用一个计数为 5 的信号量来确保任何时候最多只有 5 个线程使用这些连接。\nimport threading\n \n# 创建一个信号量最多允许5个线程同时访问\nsemaphore = threading.Semaphore(5)\n \ndef access_resource():\n # 获取信号量\n semaphore.acquire()\n \n try:\n # TODO: 访问资源\n pass\n finally:\n # 释放信号量\n semaphore.release()\n条件变量\n条件变量是用于线程之间的同步特别是当线程需要等待特定条件成立时。例如一个线程可能会等待一个队列非空才开始处理。使用条件变量这个线程可以在队列为空时进入休眠并在其他线程向队列添加项时被唤醒。\nimport threading\n \ncondition = threading.Condition()\nqueue = []\n \ndef produce_item():\n with condition:\n # TODO: 生产一个项目并添加到队列\n queue.append("item")\n # 唤醒等待队列非空的线程\n condition.notify()\n \ndef consume_item():\n with condition:\n while not queue:\n # 如果队列为空,则等待\n condition.wait()\n # TODO: 从队列中消费一个项目\n item = queue.pop()\n设计模式与最佳实践\n生产者 - 消费者模式\n生产者 - 消费者模式是一个并发模式,其中一个或多个生产者线程创建项目,而一个或多个消费者线程处理这些项目。这种模式可以有效地分离数据生产和数据处理,通常使用队列来传输数据。\nimport threading\nimport queue\n \nq = queue.Queue()\n \ndef producer():\n while True:\n item = produce_item()\n q.put(item)\n \ndef consumer():\n while True:\n item = q.get()\n process_item(item)\n \ndef produce_item():\n # TODO: 生产数据\n return "item"\n \ndef process_item(item):\n # TODO: 处理数据\n pass\n发布者 - 订阅者模式\n发布者 - 订阅者模式是一种通知模式,其中发布者发送通知,而订阅者(可以有多个)接收通知。这种模式适用于需要广播信息的场景。\nclass Publisher:\n def __init__(self):\n self.subscribers = set()\n \n def register(self, who):\n self.subscribers.add(who)\n \n def unregister(self, who):\n self.subscribers.discard(who)\n \n def dispatch(self, message):\n for subscriber in self.subscribers:\n subscriber.update(message)\n \nclass Subscriber:\n def update(self, message):\n # TODO: 处理消息\n print(message)\n避免死锁、资源竞争、线程安全的设计\n\n避免死锁确保线程按照一致的顺序请求资源使用锁的超时功能或使用死锁检测工具。\n资源竞争使用锁、信号量等同步原语确保对共享资源的有序访问。\n线程安全的设计避免修改共享数据或确保使用适当的同步机制来保护数据。考虑使用不可变数据结构和线程局部存储。\n\n实际应用与性能分析\n选择适当的并发或并行工具\n\n任务性质I/O 密集型任务可以从多线程中受益,而 CPU 密集型任务可能更适合多进程或异步编程。\n共享数据如果需要大量共享数据则线程可能是一个好选择否则多进程可能更简单。\n\n性能分析工具\ncProfile\ncProfile 是 Python 的一个内置性能分析工具。它测量函数调用的频率和执行时间,对于查找瓶颈和代码优化尤为有用。\nimport cProfile\n \ndef my_function():\n # TODO: 一些代码\n pass\n \ncProfile.run('my_function()')\nmemory_profiler\nmemory_profiler 是一个用于监控 Python 程序内存使用的工具,它可以为你提供关于对象的内存消耗等信息。\nfrom memory_profiler import profile\n \n@profile\ndef memory_test_func():\n a = [i for i in range(100000)]\n return a\n \nmemory_test_func()\ntimeit\ntimeit 是一个专门用于测量小代码片段执行时间的工具。它的优势在于,它会多次运行指定的代码,以获取更精确的平均运行时间。\nimport timeit\n \ndef code_to_test():\n return sum(range(10000))\n \n# 该方法会运行 `code_to_test` 函数 1000 次,并返回总运行时间\nelapsed_time = timeit.timeit(code_to_test, number=1000)\nprint(elapsed_time)\n \ntime.process_time\n这个函数返回当前进程运行的 CPU 时间,而不是实际经过的时间,它可以帮助我们忽略其他进程或线程对测量结果的影响。\nimport time\n \nstart = time.process_time()\n \n# 要测量的代码\nresult = sum(range(1000000))\n \nend = time.process_time()\nprint(f"Time taken: {end - start} seconds")\ntime.perf_counter\ntime.perf_counter 是一个高分辨率的计时器,适合对代码段进行基准测试,并且还会计算系统的休眠时间。\nimport time\n \nstart = time.perf_counter()\n \n# 要测量的代码\nresult = sum(range(1000000))\n \nend = time.perf_counter()\nprint(f"Time taken: {end - start} seconds")\n优化策略\n\n减少锁的使用频繁使用锁可能导致线程等待降低整体性能。尝试减少锁的持有时间或使用更细粒度的锁以减少资源争用。\n使用线程池和连接池通过预先创建和复用线程或数据库连接可以避免频繁地创建和销毁资源这可以显著提高性能。\n优化数据结构和算法选择正确的数据结构和算法可以极大地提高代码的运行效率。定期审查代码确保它是最优的。\n利用缓存将常用的计算结果或查询结果缓存起来可以避免重复的、消耗性能的操作。\n延迟加载只有在真正需要时再加载数据这样可以避免不必要的计算和资源使用。\n"},"Technology/ProgrammingLanguage/Python/进阶/异常处理":{"title":"异常处理","links":["Tech/programming-language/Python/模块/网络处理/requests-HTTP-库"],"tags":["Python/进阶","技术/程序语言"],"content":"异常的概念\n**在 Python 中,异常是程序运行时发生的错误,它中断了正常的程序流程。**Python 使用异常对象来表示错误。当程序中发生错误时Python 会创建一个相应的异常对象。若未处理,程序将终止并显示错误信息。\n异常处理是一种编程结构用于捕获和响应程序中的异常。正确处理异常可以提高程序的健壮性和可靠性预防中断或崩溃。\n异常是一种特殊对象包含错误的详细信息如类型和发生时的状态。Python 内置了许多标准异常类型,例如 ValueError、TypeError、IndexError每种类型对应特定错误。\n我们**可以通过异常处理机制捕获异常。**处理异常允许我们决定出错时的响应方式,而非直接让程序崩溃。这对构建健壮和稳定的程序至关重要。\n异常层次结构\ngraph LR\n BaseException --> SystemExit\n BaseException --> KeyboardInterrupt\n BaseException --> GeneratorExit\n BaseException --> Exception\n Exception --> StopIteration\n Exception --> ArithmeticError\n ArithmeticError --> FloatingPointError\n ArithmeticError --> OverflowError\n ArithmeticError --> ZeroDivisionError\n Exception --> AssertionError\n Exception --> AttributeError\n Exception --> EOFError\n Exception --> ImportError\n Exception --> ModuleNotFoundError\n Exception --> LookupError\n LookupError --> IndexError\n LookupError --> KeyError\n Exception --> NameError\n NameError --> UnboundLocalError\n Exception --> OSError\n OSError --> IOError\n Exception --> RuntimeError\n RuntimeError --> NotImplementedError\n RuntimeError --> RecursionError\n Exception --> SyntaxError\n Exception --> SystemError\n Exception --> TypeError\n Exception --> ValueError\n Exception --> UnicodeError\n\n**Python 的异常遵循一定的层次结构。**在这个层次结构的顶端是 BaseException 类,它是所有异常的基类。接着是其他一些内置异常,如 SystemExit、KeyboardInterrupt 等,这些通常用于系统退出和用户中断。\n紧随其后的是 Exception 类,它是大多数内置可被应用程序捕获的错误的基类。从 Exception 类派生出更具体的异常类,如 StopIteration、ArithmeticError、LookupError 等,这些类又有自己的子类,分别对应特定的错误情况。\n基本异常处理try, except, else, finally\nPython 中处理异常的关键字有四个try、except、finally、else。\n\ntry: 将可能引发异常的代码放在 try 块中。\nexcept: 当 try 块中的代码引发异常时,执行 except 块中的代码。可指定要捕获的异常类型。一个 try 块可以跟随多个 except 块,以捕获不同类型的异常。\nfinally: 不论 try 块是否引发异常,都会执行 finally 块。常用于清理操作,如关闭文件。\nelse: 若 try 块中无异常发生,则执行 else 块。else 是可选的。\n\ntry:\n # 可能抛出异常的代码\n result = 10 / 0\nexcept ZeroDivisionError:\n # 处理ZeroDivisionError异常的代码\n print("Cannot divide by zero!")\nelse:\n # try代码块成功执行后的代码\n print("Operation successful.")\nfinally:\n # 无论是否发生异常都会执行的代码\n print("This is the finally block.")\nPython 内置标准异常\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n异常名描述BaseException所有异常的基类SystemExit解释器请求退出KeyboardInterrupt用户中断执行 (通常是输入^C)Exception常规错误的基类StopIteration迭代器没有更多的值GeneratorExit生成器 (generator) 发生异常来通知退出SystemError解释器发现内部错误SyntaxErrorPython 语法错误IndentationError缩进错误TabErrorTab 和空格混用NameError未声明/初始化对象 (没有属性)UnboundLocalError访问未初始化的本地变量AttributeError对象没有这个属性TypeError对类型无效的操作AssertionError断言语句失败ImportError导入模块/对象失败ModuleNotFoundError找不到模块LookupError无效数据查询的基类IndexError序列中没有此索引 (index)KeyError映射中没有这个键ValueError传入无效的参数UnicodeErrorUnicode 相关的错误ArithmeticError数学运算基类FloatingPointError浮点计算错误OverflowError数值运算超出最大限制ZeroDivisionError除 (或取模) 零 (所有数据类型)EnvironmentError操作系统错误的基类IOError输入/输出操作失败OSError操作系统错误EOFError没有内建输入,到达 EOF 标记RuntimeError一般的运行时错误NotImplementedError尚未实现的方法RecursionError超过最大递归深度\n自定义异常的创建和抛出\n**自定义异常通过继承 Exception 类来定义。**在自定义类中,可以定义所需的任何方法,但通常自定义异常很简单,只提供基本信息。\n要抛出自定义异常使用 raise 关键字。在 raise 语句后,指定异常类型和可选的错误消息。\nclass CustomError(Exception):\n """自定义的异常类型"""\n \n def __init__(self, message):\n self.message = message\n \ntry:\n raise CustomError("This is a custom error.")\nexcept CustomError as e:\n print("Caught an exception:", e.message)\n异常链raise from和异常上下文\nPython 3 引入异常链允许在处理异常时引发另一个异常,保留原始异常的上下文。使用 raise from 实现。\ntry:\n int('a')\nexcept ValueError as e:\n raise RuntimeError('转换错误') from e\n警告warnings 模块)的实用场景\n警告不中断程序但提供有关潜在问题的信息。warnings 模块发出警告并处理。使用警告来通知即将废弃的功能,或提醒用户注意非关键问题。\nimport warnings\n \ndef my_function():\n warnings.warn("这个功能即将废弃", DeprecationWarning)\n \nmy_function()\n异常处理最佳实践\n合适的异常处理策略\n\n确切地知道你在捕获什么仅捕获能正确处理的异常。\n避免捕获太广泛的异常避免使用空 except: 子句,以免捕获所有异常。\n在正确的层级处理异常在适当的抽象级别处理异常避免在函数内部处理应由调用者处理的异常。\n\n避免常见错误\n\n过度使用异常处理不要使用异常处理来控制正常程序流程。\n在异常处理中隐藏错误捕获异常时应记录或报告错误信息。\n错误地屏蔽异常避免在 except 块中引发新异常,覆盖原始异常。\n\n异常处理示例网络应用程序\n在网络应用程序中需要从远程服务器获取数据。这可能因多种原因失败如网络问题或服务器错误。使用异常处理优雅地处理这些问题并提供回退机制或错误信息。\nimport requests\n \ntry:\n response = requests.get('example.com/data')\n response.raise_for_status()\nexcept requests.exceptions.HTTPError as he:\n print(f'HTTP错误: {he}')\nexcept requests.exceptions.ConnectionError as ce:\n print(f'连接错误: {ce}')\nexcept requests.exceptions.Timeout as te:\n print(f'请求超时: {te}')\nelse:\n # 处理成功的响应\n process_data(response)\n在这个例子中使用 requests HTTP 库 分别处理了 HTTP 错误、连接错误和超时错误,每种类型的错误都有专门的异常类。这使得错误处理更加具体和有用。"},"Technology/ProgrammingLanguage/Python/进阶/数据库操作":{"title":"数据库操作","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"Python DB-API 2.0 规范概述\n**Python DB-API 2.0 规范是一个重要的标准,它为 Python 程序与数据库间的交互提供了一致的接口。**这个规范的目标是简化数据库编程,同时保持足够的灵活性来支持不同的数据库系统。\nDB-API 2.0 规范定义在 Python 标准库的 PEP 249 文档中。它规定了数据库驱动(或数据库模块)应遵循的接口标准,以便程序员可以使用一致的编程风格来访问不同的数据库系统。\n核心组件\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n组件描述关键方法或属性连接对象Connection代表数据库的连接。- connect(): 连接数据库。- commit(): 提交当前事务。- rollback(): 回滚当前事务。- close(): 关闭连接。游标对象Cursor用于执行查询和获取结果。- execute(sql, [parameters]): 执行 SQL 语句。- executemany(sql, seq_of_parameters): 执行相同的 SQL 语句多次。- fetchone(): 获取结果集的下一行。- fetchmany(size): 获取结果集的下几行。- fetchall(): 获取结果集中的所有行。- close(): 关闭游标对象。\n标准方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法类型方法名描述连接方法connect()连接到数据库。commit()提交当前的事务。rollback()回滚当前的事务。close()关闭数据库连接。游标方法execute(sql, [parameters])执行一个 SQL 语句。executemany(sql, seq_of_parameters)执行相同的 SQL 语句多次。fetchone()从结果集中获取下一行。fetchmany(size)从结果集中获取多行。fetchall()获取结果集中的所有行。close()关闭游标对象。\n标准异常\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n异常类别描述Warning警告类的基类用于非致命性问题的提示。Error与数据库相关错误的基类。如果未指定具体的异常则抛出这个错误。InterfaceError与数据库接口而非数据库本身相关的错误。DatabaseError数据库操作过程中发生的错误的基类。DataError数据异常比如数值溢出、数据类型不匹配等。OperationalError数据库操作中的内部错误如连接问题、内存分配问题等。IntegrityError数据完整性相关的错误如外键违反等。InternalError数据库内部错误如游标无效、事务同步失效等。ProgrammingError程序错误如表找不到、SQL 语句语法错误等。NotSupportedError当尝试使用数据库不支持的功能或 API 时抛出的错误。\nPython 数据库操作\n首先需要安装对应数据库的 Python 库,例如,如果是使用 MySQL可以安装 mysql-connector-python。然后可以使用如下代码连接到数据库并执行简单的 SQL 语句:\nimport sqlite3\n \ntry:\n # 连接到 SQLite 数据库\n # 如果文件不存在,会自动创建\n conn = sqlite3.connect('example.db')\n \n # 创建一个游标对象,用于执行 SQL 命令\n cursor = conn.cursor()\n \n # 创建一个新表\n # IF NOT EXISTS 用于避免在表已存在时产生错误\n cursor.execute('''\n CREATE TABLE IF NOT EXISTS stocks\n (date text, trans text, symbol text, qty real, price real)\n ''')\n \n # 插入一条记录\n cursor.execute("INSERT INTO stocks VALUES ('2023-11-17','BUY','AAPL',100,35.14)")\n \n # 提交当前事务\n conn.commit()\n \n # 查询数据\n cursor.execute("SELECT * FROM stocks WHERE symbol = 'AAPL'")\n print(cursor.fetchall())\n \n# 捕获任何可能发生的异常\nexcept sqlite3.Error as e:\n print(f"数据库错误: {e}")\nexcept Exception as e:\n print(f"非数据库错误: {e}")\nfinally:\n # 关闭游标\n if cursor:\n cursor.close()\n # 关闭数据库连接\n if conn:\n conn.close()\n \n连接Connection\n连接对象代表了 Python 应用程序和数据库之间的连接。通过这个连接,程序能够执行 SQL 命令、处理事务。\n创建连接\n\n连接是通过调用特定数据库模块的 connect() 函数创建的。\n这个函数通常需要数据库特定的参数如主机名、数据库名、用户名和密码。\n\nimport sqlite3\n \n# 创建连接到 SQLite 数据库文件 'example.db'\nconn = sqlite3.connect('example.db')\n关键特性和方法\n\n事务处理\n\ncommit(): 提交当前事务。在执行如 INSERT、UPDATE、DELETE 等操作后,需要调用此方法以确保更改被保存。\nrollback(): 回滚当前事务。在遇到错误或需要撤销更改时使用。\n\n\n连接管理\n\nclose(): 关闭连接。关闭后,连接对象和其下所有的游标将不可用。\n\n\n错误处理\n\n连接操作可能会抛出 DB-API 定义的异常,如 InterfaceError 或 DatabaseError。\n\n\n\ntry:\n # 执行数据库操作\n conn.commit() # 提交事务\nexcept Exception as e:\n conn.rollback() # 回滚事务\n raise e\nfinally:\n conn.close() # 关闭连接\nPython 进行数据库操作务必管理好数据库连接的生命周期。使用完毕后应及时关闭,避免资源泄露。建议使用 Python 的上下文管理器with 语句)可以自动管理连接的开启和关闭。\n游标Cursor\n游标是通过连接对象创建的用于执行 SQL 命令和处理查询结果。\n创建游标\n\n通过连接对象的 cursor() 方法创建。\n可以创建多个游标用于执行不同的数据库操作。\n\ncursor = conn.cursor() # 创建游标\n关键特性和方法\n\n执行 SQL 命令:\n\nexecute(sql, [parameters]): 执行单个 SQL 命令。\nexecutemany(sql, seq_of_parameters): 执行相同 SQL 命令多次,但使用不同的参数。\n\n\n结果处理\n\nfetchone(): 返回结果集的下一行。\nfetchmany(size): 返回结果集的下几行。\nfetchall(): 返回结果集中的所有行。\n\n\n元数据获取\n\n游标对象提供了诸如 description 属性,可以用来获取查询结果的列信息。\n\n\n游标管理\n\nclose(): 关闭游标。关闭后,游标将不可用。\n\n\n\n# 执行 SQL 查询\ncursor.execute('SELECT * FROM some_table')\n \n# 获取查询结果\nrows = cursor.fetchall() # 获取所有行\nfor row in rows:\n print(row)\n \n# 关闭游标\ncursor.close()\n为避免资源占用执行完毕后应及时关闭游标。使用参数化查询而不是字符串拼接以防止 SQL 注入攻击。\n执行 SQL 语句execute\n在 Python 中,使用游标对象执行 SQL 语句并处理结果。\n\n使用游标对象的 execute() 方法执行 SQL 语句。\n对于查询操作如 SELECT结果可以通过游标提供的方法获取。\n对于非查询操作如 INSERT、UPDATE、DELETE结果通常是影响的行数。\n\n# 执行一个查询\ncursor.execute('SELECT * FROM some_table')\n \n# 或者执行一个更新\ncursor.execute('UPDATE some_table SET column = value WHERE condition')\n处理结果\n\n使用 fetchone()、fetchmany(size) 或 fetchall() 方法获取查询结果。\nfetchone() 返回单行fetchmany(size) 返回指定数量的行fetchall() 返回所有行。\n\n# 执行查询\ncursor.execute('SELECT * FROM some_table')\n \n# 获取单行\nrow = cursor.fetchone()\nprint(row)\n \n# 获取多行\nrows = cursor.fetchmany(5)\nfor row in rows:\n print(row)\n \n# 获取所有行\nall_rows = cursor.fetchall()\nfor row in all_rows:\n print(row)\n错误处理\n在 Python 数据库编程中错误处理是必不可少的部分。常见的数据库错误包括连接错误、SQL 语法错误、数据类型不匹配等。合理的错误处理可以提高程序的健壮性和用户体验。\n\n使用 try-except 块捕获并处理数据库异常。\n利用 Python 的 DB-API 定义的异常类(如 DatabaseErrorIntegrityError 等)来识别和响应特定的错误情况。\n\ntry:\n conn.execute('SELECT * FROM non_existent_table')\nexcept sqlite3.DatabaseError as e:\n print("Database error occurred:", e)\n调试数据库应用\n\n使用日志记录重要的操作和异常信息。\n在开发阶段打印或记录 SQL 语句和其参数,以便检查和调整。\n使用交互式 Python 环境(如 IPython 或 Jupyter Notebook进行逐步执行和测试。\n\n参数化查询\n参数化查询是一种编写 SQL 查询的方法,可以提高安全性和灵活性。\n编写安全的 SQL 查询以避免 SQL 注入\n通过使用占位符而非直接拼接字符串来构建 SQL 语句,可以有效防止 SQL 注入攻击。\n# 错误的做法:直接字符串拼接\nunsafe_sql = "SELECT * FROM users WHERE name = '" + user_input + "'"\n \n# 正确的做法:使用参数化查询\ncursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))\n使用参数而非字符串拼接\n在构建 SQL 语句时,应优先考虑使用参数化查询。\nuser_id = 5\ncursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))\n事务管理\n基本概念ACID 特性)\n事务是数据库操作的基本单位它应满足 ACID 特性即原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability。\n\n原子性确保所有操作要么全部完成要么全部不执行。\n一致性事务完成时数据必须处于一致状态。\n隔离性多个事务同时进行时一个事务的操作不应影响其他事务。\n持久性一旦事务提交其结果就永久保存在数据库中。\n\n在 Python 中进行事务控制\n在 Python 中事务控制通常由连接对象Connection来管理。使用 commit() 和 rollback() 方法来控制事务的提交和回滚。\nconn = sqlite3.connect('example.db')\ntry:\n # 开始一个事务\n conn.execute('INSERT INTO table_name VALUES (...)')\n \n # 更多数据库操作...\n \n # 提交事务\n conn.commit()\nexcept Exception as e:\n # 出现错误,回滚事务\n conn.rollback()\n raise e\nfinally:\n # 关闭连接\n conn.close()\n数据库连接池\n理解数据库连接池的概念\n数据库连接池是一种创建和管理数据库连接的技术用于减少建立和关闭连接的开销。在高并发情况下连接池可以显著提高性能。\n使用连接池提高性能\n在 Python 中,可以使用第三方库(如 sqlalchemy.pool来实现数据库连接池。连接池管理着一组连接当需要时分配给请求者使用完毕后返回池中。\nfrom sqlalchemy.pool import QueuePool\nfrom sqlalchemy import create_engine\n \n# 创建一个带连接池的引擎\nengine = create_engine('postgresql://username:password@localhost/dbname', poolclass=QueuePool)\n \n# 使用连接\nwith engine.connect() as connection:\n result = connection.execute("SELECT * FROM table_name")\n for row in result:\n print(row)\nORM 工具\n在 Python 中对象关系映射Object-Relational Mapping, ORM是一种流行的技术它允许开发者以对象的形式操作数据库而无需编写 SQL 语句。ORMObject-Relational Mapping是一种将数据库表转换为程序中对象的技术使开发者能够以面向对象的方式处理数据库。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nORM 库简介特点适用场景Django ORMDjango 框架的一部分无需编写 SQL支持多数据库丰富的查询构造器Django 框架的 web 应用SQLAlchemy流行的独立 ORM 工具灵活模型定义强大查询支持多数据库适用于各种规模应用特别是复杂数据库应用Peewee小巧但功能完整的 ORM 库简单易用,学习曲线低小型项目或简单 ORM 需求Tortoise ORM异步 ORM 库支持异步操作,适合异步编程环境需要高并发处理的现代 web 应用Pony ORM提供直观查询语言的 ORM 库独特的查询语法,易于理解寻求直观查询方式的开发者\n基本的 ORM 操作\n使用 ORM 工具时,开发者定义模型(即类),这些模型映射到数据库的表。在 Python 中,常见的 ORM 工具包括 SQLAlchemy 和 Django ORM。\nfrom sqlalchemy import create_engine, Column, Integer, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\n \nBase = declarative_base()\nengine = create_engine('sqlite:///example.db')\nSession = sessionmaker(bind=engine)\n \nclass User(Base):\n __tablename__ = 'users'\n \n id = Column(Integer, primary_key=True)\n name = Column(String)\n \n# 创建表\nBase.metadata.create_all(engine)\n \n# 使用会话进行数据库操作\nsession = Session()\nnew_user = User(name='Alice')\nsession.add(new_user)\nsession.commit()\nsession.close()\n项目实战\n为了将所学知识应用于实际可以从开发一个简单的数据库应用开始。例如创建一个图书管理系统包括图书的添加、查询、更新和删除功能。\nimport sqlite3\nfrom sqlite3 import Error\n \ndef create_connection(db_file):\n """ 创建一个数据库连接到 SQLite 数据库 """\n conn = None\n try:\n conn = sqlite3.connect(db_file)\n return conn\n except Error as e:\n print(e)\n \n return conn\n \ndef create_table(conn, create_table_sql):\n """ 创建表 """\n try:\n c = conn.cursor()\n c.execute(create_table_sql)\n except Error as e:\n print(e)\n \ndef main():\n database = r"pythonsqlite.db"\n \n sql_create_projects_table = """ CREATE TABLE IF NOT EXISTS projects (\n id integer PRIMARY KEY,\n name text NOT NULL,\n begin_date text,\n end_date text\n ); """\n \n sql_create_tasks_table = """CREATE TABLE IF NOT EXISTS tasks (\n id integer PRIMARY KEY,\n name text NOT NULL,\n priority integer,\n status_id integer NOT NULL,\n project_id integer NOT NULL,\n begin_date text NOT NULL,\n end_date text NOT NULL,\n FOREIGN KEY (project_id) REFERENCES projects (id)\n );"""\n \n # 创建一个数据库连接\n conn = create_connection(database)\n \n # 创建表\n if conn is not None:\n create_table(conn, sql_create_projects_table)\n create_table(conn, sql_create_tasks_table)\n else:\n print("无法创建数据库连接。")\n \n # 插入数据\n project = ('Cool App with SQLite & Python', '2023-01-01', '2023-12-31')\n project_id = insert_project(conn, project)\n \n task_1 = ('Analyze the requirements of the app', 1, 1, project_id, '2023-01-01', '2023-01-02')\n task_2 = ('Confirm with user about the top priorities', 1, 1, project_id, '2023-01-03', '2023-01-05')\n \n # 插入任务\n insert_task(conn, task_1)\n insert_task(conn, task_2)\n \n # 查询数据\n print("1. 查询项目:")\n select_all_projects(conn)\n \n print("2. 查询任务:")\n select_all_tasks(conn)\n \n # 更新数据\n update_task(conn, (2, '2023-01-04', 2))\n \n # 删除数据\n delete_task(conn, 2)\n \n # 关闭连接\n conn.close()\n \ndef insert_project(conn, project):\n """\n 创建一个新的项目\n :param conn:\n :param project:\n :return: project id\n """\n sql = ''' INSERT INTO projects(name,begin_date,end_date)\n VALUES(?,?,?) '''\n cur = conn.cursor()\n cur.execute(sql, project)\n conn.commit()\n return cur.lastrowid\n \ndef insert_task(conn, task):\n """\n 创建一个新的任务\n :param conn:\n :param task:\n :return:\n """\n sql = ''' INSERT INTO tasks(name,priority,status_id,project_id,begin_date,end_date)\n VALUES(?,?,?,?,?,?) '''\n cur = conn.cursor()\n cur.execute(sql, task)\n conn.commit()\n return cur.lastrowid\n \ndef select_all_projects(conn):\n """\n 查询所有项目\n :param conn: the Connection object\n :return:\n """\n cur = conn.cursor()\n cur.execute("SELECT * FROM projects")\n \n rows = cur.fetchall()\n \n for row in rows:\n print(row)\n \ndef select_all_tasks(conn):\n """\n 查询所有任务\n :param conn: the Connection object\n :return:\n """\n cur = conn.cursor()\n cur.execute("SELECT * FROM tasks")\n \n rows = cur.fetchall()\n \n for row in rows:\n print(row)\n \ndef update_task(conn, task):\n """\n 更新任务\n :param conn:\n :param task:\n :return: project id\n """\n sql = ''' UPDATE tasks\n SET priority = ? ,\n end_date = ?\n WHERE id = ?'''\n cur = conn.cursor()\n cur.execute(sql, task)\n conn.commit()\n \ndef delete_task(conn, id):\n """\n 删除一个任务通过任务 id\n :param conn: Connection to the SQLite database\n :param id: id of the task\n :return:\n """\n sql = 'DELETE FROM tasks WHERE id=?'\n cur = conn.cursor()\n cur.execute(sql, (id,))\n conn.commit()\n \nif __name__ == '__main__':\n main()"},"Technology/ProgrammingLanguage/Python/进阶/文件和IO操作":{"title":"文件和IO操作","links":["Tech/programming-language/Python/进阶/资源管理","Tech/programming-language/Python/模块/数据处理/csv-文件读写","Tech/programming-language/Python/模块/数据处理/json-编码和解码器","Tech/programming-language/Python/进阶/异常处理"],"tags":["Python/进阶","技术/程序语言"],"content":"Python 文件操作基础\n文件和 IO 的基本概念\n在编程领域文件和输入/输出IO操作是基本的组成部分。文件是存储在磁盘上的数据集合可以包含文本、图片、音频等多种格式的数据。IO 操作则涉及到数据的读取(输入)和写入(输出)。在 Python 中,对文件的操作简单而强大,涵盖了从文本文件到复杂数据格式的处理。\n理解文件的操作对于数据处理、日志记录、配置文件的读写等都至关重要。Python 提供了丰富的库来处理各种类型的文件,使得文件读写变得既简单又安全。\n文件打开与关闭\n文件在使用前必须先打开并在操作完成后关闭。Python 通过内置的 open() 函数来打开文件,这个函数返回一个文件对象,然后可以对其进行读取或写入操作。文件操作完成后,应该使用 close() 方法关闭文件以释放系统资源。但更推荐的做法是使用 with 语句(上下文管理器),它会在代码块执行完毕后自动关闭文件,即使在代码块中发生了异常。\n文件读写操作\n读取和写入是文件操作中最基础的部分。Python 提供了多种方法来读取文件(如 read()readline()readlines())和写入文件(如 write()writelines())。这些方法可以灵活应用于不同的场景,如逐字符、逐行读取或写入整个文件。\n文件模式\n在打开文件时可以指定不同的模式\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n模式描述'r'只读模式。如果文件不存在,抛出异常。'w'写入模式。如果文件存在,覆盖原有内容;如果文件不存在,创建新文件。'a'附加模式。如果文件存在,将数据添加到文件末尾;如果文件不存在,创建新文件。'r+'读写模式。可以读取和写入文件,如果文件不存在,抛出异常。'w+'写读模式。打开文件进行读写,覆盖原有内容;如果文件不存在,则创建新文件。'a+'附加和读取模式。可以读取和在文件末尾附加内容;如果文件不存在,则创建新文件。'rb'以二进制格式打开文件进行只读。'wb'以二进制格式打开文件进行写入,覆盖原有内容;如果文件不存在,则创建新文件。'ab'以二进制格式打开文件进行附加,如果文件不存在,则创建新文件。'rb+'以二进制格式打开文件进行读写。'wb+'以二进制格式打开文件进行写读,覆盖原有内容;如果文件不存在,则创建新文件。'ab+'以二进制格式打开文件进行附加和读取。\n文件类型和数据格式处理\n处理文本文件\n文本文件存储的是可读字符如 .txt 文件。Python 中处理文本文件非常直接,可以使用字符串方法对内容进行操作。\n# 读取文本文件\nwith open('example.txt', 'r') as file:\n content = file.read()\n print(content)\n处理二进制文件\n二进制文件存储的是字节数据如图片、音频等。在 Python 中,通过在 open() 函数中使用 'rb' 或 'wb' 模式来读取或写入二进制文件。\n# 读取二进制文件\nwith open('image.png', 'rb') as file:\n content = file.read()\nCSV 文件处理\nCSV逗号分隔值是一种常见的数据交换格式。Python 的 csv 模块 提供了读取和写入 CSV 文件的功能。\nimport csv\n \n# 读取 CSV 文件\nwith open('data.csv', 'r') as file:\n csv_reader = csv.reader(file)\n for row in csv_reader:\n print(row)\n \n# 写入 CSV 文件\nwith open('output.csv', 'w', newline='') as file:\n csv_writer = csv.writer(file)\n csv_writer.writerow(['name', 'age'])\n csv_writer.writerow(['Alice', 30])\nJSON 文件处理\nJSONJavaScript Object Notation是一种轻量级的数据交换格式。Python 的 json 模块 可以轻松处理 JSON 数据。\nimport json\n \n# 读取 JSON 文件\nwith open('data.json', 'r') as file:\n data = json.load(file)\n print(data)\n \n# 写入 JSON 文件\nwith open('output.json', 'w') as file:\n json.dump({'name': 'Alice', 'age': 30}, file, indent=4)\n \n文件系统操作\n文件和目录的基本操作\nPython 的 os 和 shutil 模块提供了丰富的文件和目录管理功能,包括创建、删除、移动、复制等。\nimport os\nimport shutil\n \n# 创建目录\nos.mkdir('new_directory')\n \n# 移动文件\nshutil.move('example.txt', 'new_directory/example.txt')\n \n# 复制文件\nshutil.copy('new_directory/example.txt', 'example_copy.txt')\n \n# 删除文件\nos.remove('example_copy.txt')\n \n路径操作\nPython 提供了 os.path 和 pathlib 模块来处理文件路径的各种需求。\nfrom pathlib import Path\n \n# 创建 Path 对象\npath = Path('example.txt')\n \n# 检查文件是否存在\nprint(path.exists())\n \n# 获取文件扩展名\nprint(path.suffix)\n \n使用临时文件\ntempfile 模块用于创建临时文件和目录,这在需要临时存储数据时非常有用。\nimport tempfile\n \n# 创建临时文件\ntemp_file = tempfile.TemporaryFile()\n \n# 写入临时文件\ntemp_file.write(b'Temporary data')\ntemp_file.seek(0)\n \n# 读取临时文件\nprint(temp_file.read())\n \n# 关闭临时文件\ntemp_file.close()\n高级文件操作技巧\n文件迭代与遍历\n文件内容可以逐行或按特定条件迭代这对于处理大型文件尤为重要。\n# 逐行读取文件\nwith open('large_file.txt', 'r') as file:\n for line in file:\n process(line) # 自定义的处理函数\n \n内存映射文件操作\n使用 mmap 模块可以将文件内容映射到内存,这样可以提高读写大文件的效率。\nimport mmap\n \n# 内存映射一个大文件\nwith open('large_file.txt', 'r+b') as f:\n mm = mmap.mmap(f.fileno(), 0)\n print(mm.readline()) # 读取一行内容\n mm.close()\n \n异步 IO 操作\nPython 的 asyncio 库允许进行异步 IO 操作,这对于提高 IO 密集型应用的性能很有帮助。\nimport asyncio\n \nasync def read_file_async(file_name):\n with open(file_name, 'r') as file:\n return await file.read()\n \n# 在异步函数中调用\nasync def main():\n content = await read_file_async('example.txt')\n print(content)\n \nasyncio.run(main())\n \n编码和错误处理\n字符编码\n理解字符编码如 UTF-8, ASCII对于正确处理文本文件至关重要特别是在处理国际化内容时。\n# 指定文件的编码\nwith open('example.txt', 'r', encoding='utf-8') as file:\n content = file.read()\n \n文件操作中的错误处理\n文件操作可能会引发各种 异常,例如 FileNotFoundError 或 PermissionError。正确处理这些异常是编写健壮代码的关键。\ntry:\n with open('nonexistent_file.txt', 'r') as file:\n content = file.read()\nexcept FileNotFoundError:\n print("文件不存在")\n性能优化和最佳实践\n处理文件和 IO 操作时,性能优化和资源管理是两个关键的方面。正确处理这些问题不仅可以提高程序的效率,还能避免常见的资源泄露和同步问题。\n性能优化\n在处理大型文件时性能成为一个重要的考虑因素。以下是一些优化文件操作性能的策略\n逐行处理而非一次性读取整个文件\n对于非常大的文件一次性读取整个文件到内存中可能会导致内存溢出。逐行读取文件是一个更好的选择。\nwith open('large_file.txt', 'r') as file:\n for line in file:\n process(line) # 对每行进行处理\n使用生成器进行延迟计算\n如果处理文件的过程涉及到复杂的数据处理可以使用生成器来进行延迟计算这样可以避免不必要的内存使用。\ndef read_large_file(file_obj):\n """逐行读取大文件的生成器"""\n for line in file_obj:\n yield line.strip()\n \nwith open('large_file.txt', 'r') as file:\n for line in read_large_file(file):\n process(line)\n内存映射文件\n对于非常大的文件使用内存映射的方式可以提高读写效率。这种方法适用于二进制文件可以让你像访问数组一样访问文件内容。\nimport mmap\n \nwith open('large_file.bin', 'r+b') as f:\n mm = mmap.mmap(f.fileno(), 0)\n # 访问文件内容\n mm.close()\n资源管理最佳实践\n在文件和 IO 操作中,正确的资源管理至关重要。以下是一些资源管理的最佳实践:资源管理。"},"Technology/ProgrammingLanguage/Python/进阶/测试和调试":{"title":"测试和调试","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"调试基础\n理解调试\n调试是软件开发过程中不可或缺的一部分。它涉及到识别和修复代码中的错误或缺陷以确保程序按预期运行。有效的调试策略可以大幅减少开发时间并提高代码质量。\n基本调试技巧\n最基础的调试方法是使用 print 语句输出变量的值或程序的执行状态。虽然简单,但这种方法在初步诊断问题时非常有效。\ndef add(a, b):\n print(f"a: {a}, b: {b}") # 输出参数值\n return a + b\n \nresult = add(5, '3')\nprint(f"结果: {result}")\n在这个例子中print 语句帮助我们理解错误发生的原因:尝试将整数和字符串相加。\nPython 调试器pdb\nPython 的内置调试器 pdb 是一个非常强大的交互式调试工具,它允许开发者逐行执行代码,检查当前的变量状态,评估表达式,甚至在运行时修改代码。\n基本使用\n使用 pdb 的最简单方式是在代码中插入断点。可以通过在代码中添加 import pdb; pdb.set_trace() 来实现这一点。当程序执行到这一行时,它将暂停执行并进入交互式调试模式。\nimport pdb\n \ndef my_function(arg1, arg2):\n # 设置断点\n pdb.set_trace()\n # breakpoint() \n return arg1 + arg2\n \nresult = my_function(2, 3)\n当程序运行到 pdb.set_trace() 时程序将暂停并出现一个交互式的调试环境。Python 3.8 版本以后可以使用 breakpoint() 替代 import pdb;pdb.set_trace()\n调试命令\n在 pdb 的调试环境中,有多种命令可用于调试程序:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述l (list)显示当前位置周围的代码。n (next)执行程序的下一行代码。如果当前行调用了一个函数不会进入该函数内部。c (continue)从当前位置继续执行程序直到遇到下一个断点。b (break)在指定的行号处设置断点。例如 b 120 在第 120 行设置断点。s (step)执行下一行代码如果当前行调用了一个函数则进入该函数内部。p (print)打印一个表达式的值。例如 p my_var 打印变量 my_var 的值。q (quit)退出调试器。r (return)继续执行直到当前函数返回。a (args)打印当前函数的参数列表。j (jump)将当前执行位置跳转到指定的行。例如 j 50 跳转到第 50 行。h (help)显示命令列表或查找特定命令的帮助信息。!执行任意 Python 代码。例如 !x = 5 会设置变量 x 的值为 5。\n调试流程\n在 pdb 中,通常的调试流程包括设置断点、运行程序、在断点处暂停、检查变量值或程序状态、逐步执行代码,并根据需要重复这个过程。\nsequenceDiagram\n participant P as 程序员\n participant I as IDE/调试器\n participant C as 代码\n\n P->>+I: 启动调试\n I->>+C: 运行到断点\n C-->>-I: 暂停执行,显示当前状态\n loop 检查和调整\n P->>+I: 检查变量和堆栈\n I->>+C: 获取信息\n C-->>-I: 返回信息\n P->>I: 修改代码或断点\n end\n P->>+I: 继续执行/单步执行\n I->>+C: 执行下一步\n C-->>-I: 更新状态\n P->>I: 停止调试/修复代码\n I-->>-P: 结束调试会话\n\n\n高级使用\npdb 还提供了一些高级功能,比如:\n\n\n条件断点您可以设置一个条件断点只有在特定条件满足时才会停止。\npdb.set_trace()\n# 在命令行中使用\n# b 54, x > 100\n# b 命令 54 行设置 x 大于 100 停止\n\n\n后期调试如果程序崩溃可以使用 pdb.pm() 来进行后期调试。\n\n\n命令行调试\n您也可以直接从命令行启动 pdb。这在调试脚本时非常有用。\npython -m pdb my_script.py\n在这种模式下pdb 将在脚本开始执行之前启动,允许您提前设置断点。\nPython 单元测试unittest\nunittest 是 Python 内置的测试框架,灵感来源于 JUnit。它支持自动化测试共享测试设置setup和关闭代码teardown聚集多个测试用例以及与测试框架的集成等功能。\n基本概念\n\n测试用例TestCase测试用例是 unittest 中的基本单元。每一个测试用例是 unittest.TestCase 的子类,通常包含多个以 test 开头的方法,这些方法是实际的测试脚本。\n测试套件TestSuite测试套件是一系列的测试用例或测试套件。它用于聚合需要一起执行的测试用例。\n测试运行器TestRunner测试运行器是用于执行和控制测试的组件。默认的运行器会将测试结果输出到标准输出。\n测试装置TestFixture测试装置指的是执行一系列测试所需的准备工作及相关的清理操作。这通常包括 setUp() 和 tearDown() 方法。\n\n基本的测试用例\n使用 unittest 编写测试用例通常涉及创建一个继承自 unittest.TestCase 的类,并在其中定义一系列的测试方法。\nimport unittest\n \nclass MyTest(unittest.TestCase):\n def setUp(self):\n # 测试前的准备工作\n pass\n\t\n # 类内部 test 开头的方法视为一个测试用例\n def test_something(self):\n # 实际的测试内容\n self.assertEqual(1 + 1, 2)\n \n def tearDown(self):\n # 测试后的清理工作\n pass\n \nif __name__ == '__main__':\n unittest.main()\n在这个例子中MyTest 类包含了一个简单的测试方法 test_something它测试了 1 + 1 是否等于 2。\n断言方法\nunittest 提供了一系列的断言方法来检查期望和实际结果。常用的断言方法包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述assertEqual(a, b)检查 a 是否等于 bassertNotEqual(a, b)检查 a 是否不等于 bassertTrue(x)检查 x 是否为 TrueassertFalse(x)检查 x 是否为 FalseassertIs(a, b)检查 a 是否是 b a is bassertIsNot(a, b)检查 a 是否不是 bassertIsNone(x)检查 x 是否为 NoneassertIsNotNone(x)检查 x 是否不是 NoneassertIn(a, b)检查 a 是否在 b 中assertNotIn(a, b)检查 a 是否不在 b 中assertIsInstance(a, b)检查 a 是否是 b 类型的实例assertNotIsInstance(a, b)检查 a 是否不是 b 类型的实例assertRaises(Error, func, *args, **kwargs)检查调用 func 时是否抛出了 Error 异常\n设置和清理\n通过定义 setUp 和 tearDown 方法,可以在每个测试方法执行前后进行设置和清理工作。\nclass MyTest(unittest.TestCase):\n def setUp(self):\n # 测试前的设置\n self.resource = allocate_resource()\n \n def tearDown(self):\n # 测试后的清理\n self.resource.release()\n运行测试\n通常有两种方式运行测试\n\n直接运行测试文件如果 unittest.main() 被调用,当 Python 文件被直接运行时,测试将被执行。\n使用命令行可以使用 Python 的 -m unittest 命令来发现和运行测试。\n\npython -m unittest discover\n测试驱动开发TDD\nTDD 概念\n测试驱动开发TDD是一种软件开发方法它要求开发人员先编写测试用例然后编写能够通过这些测试的代码。这种方法强调先有测试后有实现有助于创建更可靠、更易维护的代码。\n实践 TDD\n在 TDD 实践中,开发过程分为三个主要步骤:编写失败的测试、编写通过测试的代码、重构代码。\n# 假设我们有一个待实现的函数 add\n# 首先编写测试用例\nclass TestAddFunction(unittest.TestCase):\n def test_add_numbers(self):\n self.assertEqual(add(1, 2), 3)\n \n# 接着实现函数\ndef add(a, b):\n return a + b\n \n# 最后运行测试,确认通过\n通过重复这个循环逐步构建并完善整个程序。\n高级测试技巧\n集成测试和系统测试\n集成测试是指在单元测试的基础上测试多个模块或组件协同工作的情况。系统测试则是测试整个应用程序的行为。\nMocking 和 Patching\n在测试过程中我们经常需要模拟Mock某些对象或函数的行为以便于在测试环境中替换掉它们。Python 的 unittest.mock 模块提供了强大的工具来进行 Mocking 和 Patching。\nfrom unittest.mock import MagicMock\n \n# 假设我们要测试以下函数\ndef fetch_data(api_client):\n return api_client.get_data()\n \n# 我们可以这样模拟 API 客户端\nclass TestFetchData(unittest.TestCase):\n def test_fetch_data(self):\n mock_client = MagicMock()\n mock_client.get_data.return_value = 'mock data'\n self.assertEqual(fetch_data(mock_client), 'mock data')\n在这个例子中我们使用 MagicMock 来模拟 API 客户端的行为。\n测试框架和工具\n探索其他测试框架\n除了 unittestPython 还有其他流行的测试框架,如 pytest 和 nose。它们提供了更简洁的语法和更丰富的功能。\n代码覆盖率工具\n代码覆盖率是衡量测试完整性的重要指标。Python 的 coverage.py 工具可以帮助测量代码覆盖率,确保测试覆盖了所有重要的代码路径。\n持续集成 (CI)\n持续集成简介\n持续集成CI是一种软件开发实践开发者经常将代码集成到共享仓库中。每次集成都通过自动化构建来验证以尽早发现集成错误。\n使用 CI 工具\nCI 工具如 Jenkins、Travis CI 和 GitHub Actions 可以帮助自动化测试流程,确保代码更改不会破坏现有功能。\n# 示例GitHub Actions 配置文件\nname: Python CI\n \non: [push]\n \njobs:\n build:\n \n runs-on: ubuntu-latest\n \n steps:\n - uses: actions/checkout@v2\n - name: Set up Python\n uses: actions/setup-python@v2\n with:\n python-version: 3.8\n - name: Install dependencies\n run: |\n pip install -r requirements.txt\n - name: Run tests\n run: |\n python -m unittest"},"Technology/ProgrammingLanguage/Python/进阶/资源管理":{"title":"资源管理","links":["Tech/programming-language/Python/进阶/并行和并发"],"tags":["Python/进阶","技术/程序语言"],"content":"资源管理是编程中的一个关键概念特别是在处理文件、网络连接和数据库等资源时。Python 的 with 语句提供了一种高效且简便的方式来处理这些资源管理任务,确保即使在出现错误的情况下,资源也能被正确管理和释放。\nwith 语句和上下文管理器的原理\nPython 中的 with 语句是围绕上下文管理器概念设计的。它主要用于场景,如文件操作,以确保文件即使在出现错误的情况下也会被正确关闭。\n上下文管理器是实现了特定协议的对象该协议包含两个魔术方法__enter__() 和 __exit__()。__enter__() 方法在进入 with 语句块前执行,而 __exit__() 方法则在退出 with 语句块时执行,即使是通过异常退出。\nwith open('example.txt', 'w') as file:\n file.write('Hello, World!')\n# 文件在这里已自动关闭\n在此示例中open 函数返回的文件对象是一个上下文管理器,它保证了文件在离开 with 块后会自动关闭。\n自定义资源管理\n自定义上下文管理器的实现\n创建自定义上下文管理器需要定义一个类并实现 __enter__ 和 __exit__ 方法。这样的类可以用来管理自定义资源,比如数据库连接。\nclass MyDatabase:\n def __enter__(self):\n # 初始化数据库连接\n return self\n \n def __exit__(self, exc_type, exc_value, traceback):\n # 清理资源,如关闭连接\n pass\n \nwith MyDatabase() as db:\n # 使用数据库连接\n pass\ncontextlib 模块的应用\ncontextlib 模块提供了更简洁的方法来创建上下文管理器,尤其是对于函数装饰器。使用 contextlib.contextmanager 装饰器,可以通过一个生成器定义上下文管理逻辑。\nimport time\nfrom contextlib import contextmanager\n \n@contextmanager\ndef timer():\n start = time.time()\n yield\n end = time.time()\n print(f"运行时间: {end - start} 秒")\n \nwith timer():\n for _ in range(1000000):\n pass\n高级应用\n在并发环境中的资源管理\n在 多线程和多进程 环境中,资源管理变得更加重要。使用线程/进程安全的上下文管理器可以确保资源在并发环境下安全地使用和释放。\nfrom threading import Thread, Lock\n \n# 共享资源\ncounter = 0\n# 创建一个锁对象\nlock = Lock()\n \ndef increment_counter():\n global counter\n with lock:\n # 在这个区块内counter 变量被锁保护\n for _ in range(100000):\n counter += 1\n \n# 创建线程列表\nthreads = []\n \n# 创建并启动5个线程\nfor _ in range(5):\n thread = Thread(target=increment_counter)\n thread.start()\n threads.append(thread)\n \n# 等待所有线程完成\nfor thread in threads:\n thread.join()\n \n# 输出最终的计数器值\nprint(f"最终计数器值: {counter}")\n管理网络\n确保网络和数据库连接在使用后正确关闭是非常重要的以避免资源泄漏。\nimport requests\n \nwith requests.Session() as session:\n response = session.get('example.com')\n \n if response.status_code == 200:\n print("成功获取网页内容!")\n print(response.text)\n else:\n print("请求失败,状态码:", response.status_code)\n \n数据库连接\n假设我们使用的是 Python 的 sqlite3 库来管理 SQLite 数据库连接。这个示例将展示如何创建一个上下文管理器来处理数据库连接和事务。\n首先导入所需的库并设置数据库连接\nimport sqlite3\nfrom contextlib import contextmanager\n \n# 定义数据库连接函数\n@contextmanager\ndef get_db_connection(database):\n try:\n # 创建数据库连接\n conn = sqlite3.connect(database)\n print("数据库连接成功")\n yield conn\n except sqlite3.Error as e:\n print(f"数据库连接错误: {e}")\n finally:\n # 关闭数据库连接\n conn.close()\n print("数据库连接关闭")\n \nif __name__ == "__main__":\n # 使用上下文管理器执行数据库操作\n\twith get_db_connection('my_database.db') as conn:\n cursor = conn.cursor()\n # 执行一些数据库操作\n cursor.execute('''CREATE TABLE IF NOT EXISTS my_table \n (id INTEGER PRIMARY KEY, name TEXT)''')\n cursor.execute('''INSERT INTO my_table (name) VALUES ('Alice')''')\n # 提交事务\n conn.commit()\n在这个示例中我们首先创建了一个名为 my_table 的新表(如果它还不存在的话),然后向表中插入了一条记录。所有的这些操作都在安全的上下文中执行,无论操作成功还是遇到异常,数据库连接最终都会被正确关闭。\n资源管理的最佳实践\n\n及时释放资源使用 with 语句确保文件或网络连接被及时释放。\n异常安全确保在资源管理器的 __exit__ 方法中正确处理异常。\n有效共享资源在多线程/多进程环境中使用安全机制共享资源。\n"},"Technology/ProgrammingLanguage/Python/进阶/面向对象进阶":{"title":"面向对象","links":[],"tags":["Python/进阶","技术/程序语言"],"content":"生命周期\ngraph TD\nA[类定义阶段: class MyClass] --> B[类对象创建]\nB --> C1[类属性访问: MyClass.class_attr]\nB --> C[实例化阶段: __new__ method]\nC --> D[初始化阶段: __init__ method]\nD --> E1[属性的设置与获取: __setattr__, __getattr__]\nD --> E2[对象的表示: __str__, __repr__]\nD --> E3[方法调用]\nD --> E4[上下文管理: __enter__, __exit__]\nD --> E5[对象比较: __eq__, __lt__]\nD --> E6[对象的计算: __add__, __mul__]\nE1 --> F\nE2 --> F\nE3 --> F\nE4 --> F\nE5 --> F\nE6 --> F\nF[对象销毁: del obj or GC] --> G[__del__ method]\nG --> H[垃圾回收: Cleanup by Python GC]\n\n\n类定义阶段在这个阶段定义类的方法和属性。\n类对象创建当 Python 读取到类定义时,它会创建一个类对象。\n类属性访问在实例化之前可以访问类的静态和类属性。\n实例化阶段使用类名创建对象时首先调用 __new__ 方法来分配内存。\n初始化阶段紧随其后__init__ 方法会被调用,对新对象进行初始化。\n属性的设置与获取在对象的生命周期中你可以使用 __getattr__, __setattr__, __getattribute__ 等特殊方法来控制属性的访问。\n对象的表示当尝试显示对象时例如通过 print__str__ 和 __repr__ 方法可以被调用。\n方法调用可以调用对象的方法。\n上下文管理使用 with 语句时,对象的 __enter__ 和 __exit__ 方法会被调用。\n对象比较使用比较操作符时如==或>__eq__, __lt__, __le__ 等特殊方法会被调用。\n对象的计算如加法或乘法等运算符会调用 __add__, __mul__ 等特殊方法。\n对象销毁当对象的引用计数减少到零或者被明确销毁使用 del 语句__del__ 方法会被调用。\n垃圾回收Python 的垃圾回收器会识别循环引用,并在适当的时候销毁相关对象。\n\n特殊方法\nPython 中的类包含了许多特殊方法它们经常被称为魔术方法magic methods或者双下方法dunder methods因为它们的名字都是以双下划线开始和结束的。这些特殊方法为 Python 的对象提供了许多内置的功能,如算术运算、迭代和字符串表示。\n魔术方法是 Python 类的特殊方法,它们定义了许多 Python 中基本的操作。例如,当你为一个对象定义了 __add__ 方法时,这个对象就可以使用 + 运算符。这些方法的名称都是以两个下划线开始和结束,这也是为什么它们被称为双下方法的原因。\n基础方法\n__init__\n__init__ 方法是类的构造函数当我们创建类的实例时__init__ 方法会被自动调用。我们可以在 __init__ 方法中初始化实例的属性。\nclass MyClass:\n def __init__(self, value):\n self.value = value # 初始化实例属性\n \n# 创建实例\nmc = MyClass(10)\nprint(mc.value) # 输出10\n__del__\n__del__ 方法是类的析构函数当一个实例被销毁时例如被垃圾回收器回收时__del__ 方法会被自动调用。注意,我们通常不需要在 __del__ 方法中做清理工作Python 的垃圾回收器会自动清理对象的资源。\nclass MyClass:\n def __del__(self):\n print("Instance is being destroyed.")\n \nmc = MyClass() # 创建实例\ndel mc # 销毁实例\n__str__\n__str__ 方法返回一个表示该对象的字符串,这个字符串通常用于给用户看。当我们调用 str() 或 print() 时,会使用 __str__ 的返回值。\nclass MyClass:\n def __str__(self):\n return "This is a MyClass instance."\n \nmc = MyClass() # 创建实例\nprint(mc) # 输出This is a MyClass instance.\n注意__repr__ 和 __str__ 的区别在于__repr__ 更侧重于开发,而 __str__ 更侧重于用户。\n__repr__\n__repr__ 方法返回一个表示该对象的官方字符串,这个字符串通常可以被 eval() 执行来重新得到这个对象。如果我们没有定义 __str__ 方法,那么在调用 str() 或 print() 时也会使用 __repr__ 的返回值。\nclass MyClass:\n def __repr__(self):\n return "MyClass()"\n \nmc = MyClass() # 创建实例\nprint(mc) # 输出MyClass()\n__format__\n__format__ 方法定义了当我们调用 format() 或使用格式化字符串f-string时的行为。format_spec 是一个格式说明符,它是在格式化字符串中 : 后面的部分。\nclass MyClass:\n def __format__(self, format_spec):\n if format_spec == 'fancy':\n return 'This is a fancy MyClass instance.'\n return 'This is a MyClass instance.'\n \nmc = MyClass() # 创建实例\nprint(f"{mc:fancy}") # 输出This is a fancy MyClass instance.\n数学运算\n比较运算的魔术方法允许类的实例之间进行比较。例如__eq__ 定义了对象的等于操作。这些方法的使用可以使您的类实例支持标准的比较操作符,如 ==, !=, +, -, %, 和 @。类似地,可以为其他数学运算符定义其他魔术方法。\nclass Book:\n def __init__(self, title, author):\n self.title = title\n self.author = author\n \n def __eq__(self, other):\n if isinstance(other, Book):\n return self.title == other.title and self.author == other.author\n return False\n \n# 比较两本书是否具有相同的标题和作者\nbook1 = Book('1984', 'George Orwell')\nbook2 = Book('1984', 'George Orwell')\nbook3 = Book('Brave New World', 'Aldous Huxley')\n \nprint(book1 == book2) # 输出True\nprint(book1 == book3) # 输出False\nclass Vector:\n def __init__(self, x, y):\n self.x = x\n self.y = y\n \n def __add__(self, other):\n if isinstance(other, Vector):\n return Vector(self.x + other.x, self.y + other.y)\n return NotImplemented\n \n# 使用 + 操作符组合两个向量\nv1 = Vector(1, 2)\nv2 = Vector(2, 3)\nv3 = v1 + v2\n \nprint(v3.x, v3.y) # 输出3 5\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符对应的魔术方法描述==__eq__等于!=__ne__不等于<__lt__小于<=__le__小于或等于>__gt__大于>=__ge__大于或等于+__add__加法-__sub__减法*__mul__乘法/__truediv__真除//__floordiv__整除%__mod__取模**__pow__乘方@__matmul__Python 3.5+ 矩阵乘法\n容器方法\n__len__\n__len__ 方法定义了 len() 的返回值。它应该返回一个整数,表示对象包含的元素的个数。\nclass MyClass:\n def __init__(self):\n self.data = [1, 2, 3]\n \n def __len__(self):\n return len(self.data)\n \nmc = MyClass() # 创建实例\nprint(len(mc)) # 输出3\n__getitem__\n__getitem__ 方法定义了使用索引访问元素的行为。key 是索引。\nclass MyClass:\n def __getitem__(self, key):\n return f"You are trying to access key {key}."\n \nmc = MyClass() # 创建实例\nprint(mc[10]) # 输出You are trying to access key 10.\n__setitem__\n__setitem__ 方法定义了使用索引设置元素的行为。key 是索引value 是我们试图设置的值。\nclass MyClass:\n def __setitem__(self, key, value):\n print(f"Set key {key} to {value}.")\n \nmc = MyClass() # 创建实例\nmc[10] = "value" # 输出Set key 10 to value.\n__delitem__\n__delitem__ 方法定义了使用索引删除元素的行为。key 是索引。\nclass MyClass:\n def __delitem__(self, key):\n print(f"Deleted key {key}.")\n \nmc = MyClass() # 创建实例\ndel mc[10] # 输出Deleted key 10.\n__iter__、__next__\n迭代器协议的魔术方法允许对象支持迭代这意味着您可以在对象上使用 for 循环。为了使一个对象可迭代,您需要定义 __iter__ 和 __next__ 两个魔术方法。\n\n\n__iter__ 返回对象本身,它应该返回一个实现了 __next__ 的迭代器对象。\n\n\n__next__ 方法返回序列中的下一个值。如果所有项都返回了,那么它应该引发一个 StopIteration 异常来通知迭代的完成。\n\n\nclass Counter:\n def __init__(self, start, end):\n self.current = start\n self.end = end\n \n def __iter__(self):\n return self\n \n def __next__(self):\n if self.current < self.end:\n value = self.current\n self.current += 1\n return value\n else:\n raise StopIteration\n \n# 使用Counter迭代器\ncounter = Counter(1, 4)\n \nfor number in counter:\n print(number)\n# 输出:\n# 1\n# 2\n# 3\n在上述 Counter 类中,我们定义了一个简单的迭代器,它从 start 开始,每次迭代增加 1直到 end 为止。for 循环通过调用 __iter__ 来获取迭代器对象,并在每次迭代中调用 __next__直到捕获 StopIteration 异常为止。\n属性访问\n__dir__\n__dir__ 方法返回类中定义的属性、方法等的列表。它对内置的 dir() 函数的行为进行重载。\nclass MyClass:\n def __dir__(self):\n return ["custom_attr1", "custom_attr2"]\n \nmc = MyClass()\nprint(dir(mc)) # 输出:['custom_attr1', 'custom_attr2']\n__getattr__\n当尝试访问一个不存在的属性时__getattr__ 方法会被调用。name 是试图访问的属性名称。\nclass MyClass:\n def __getattr__(self, name):\n return f"{name} does not exist."\n \nmc = MyClass() # 创建实例\nprint(mc.unknown_attr) # 输出unknown_attr does not exist.\n值得注意的是__getattr__ 只有在所请求的属性不存在时才会被调用。\n__setattr__\n每当尝试设置一个属性值时__setattr__ 都会被调用不论该属性是否存在。name 是试图设置的属性的名称,而 value 是试图赋给该属性的值。\nclass MyClass:\n def __setattr__(self, name, value):\n self.__dict__[name] = value # 防止无限递归, 需要在__dict__中设置属性\n print(f"Set {name} to {value}.")\n \nmc = MyClass() # 创建实例\nmc.attr = 10 # 输出Set attr to 10.\n__delattr__\n当试图删除一个属性时__delattr__ 方法会被调用。name 是试图删除的属性的名称。\nclass MyClass:\n attr = 10\n \n def __delattr__(self, name):\n del self.__dict__[name] # 防止无限递归, 需要在__dict__中删除属性\n print(f"Deleted {name}.")\n \nmc = MyClass() # 创建实例\ndel mc.attr # 输出Deleted attr.\n__getattribute__\n每次尝试访问一个属性时__getattribute__ 方法都会被调用,无论该属性是否存在。\nclass MyClass:\n def __getattribute__(self, name):\n return f"You are trying to access {name}."\n \nmc = MyClass() # 创建实例\nprint(mc.attr) # 输出You are trying to access attr.\n重要的是如果 __getattribute__ 被定义,那么 __getattr__ 不会被调用,因为 __getattribute__ 的优先级更高。*\n上下文管理\n__enter__、__exit__\n当使用 with 语句进入上下文管理时__enter__ 方法会被调用。它应该返回上下文管理器对象本身或其他与上下文相关的对象。\n当 with 语句块结束时__exit__ 方法会被调用。它接收三个参数exc_type、exc_val 和 exc_tb分别代表异常类型、异常值和异常回溯。如果 with 语句块中没有发生异常,这三个参数的值都为 None。\nclass ContextManager:\n def __enter__(self):\n print("Entering the context")\n return self\n \n def __exit__(self, exc_type, exc_val, exc_tb):\n if exc_type is None:\n print("Exiting the context without any exception.")\n else:\n print(f"Exiting the context with exception: {exc_val}")\n \n def say_hello(self):\n print("Hello from inside the context!")\n \nwith ContextManager() as cm:\n cm.say_hello()\n \n# 输出:\n# Entering the context\n# Hello from inside the context!\n# Exiting the context without any exception.\n如果在 with 语句块中引发了异常__exit__ 方法可以选择处理这个异常(例如记录日志)并返回 True 来阻止异常向外传播,或者返回 False或 None让异常继续向外传播。\n上下文管理器是一种非常强大的工具特别是当涉及到需要设置和清理资源的任务时例如文件 I/O、网络连接或数据库连接。\n描述符\n描述符是实现了描述符协议的对象。描述符协议由 __get__、__set__ 和 __delete__ 方法组成。描述符用于创建那些需要特殊行为的对象属性,例如类型检查或只读属性。\n__get__\n__get__ 方法定义了在获取属性时应执行的行为。当试图获取属性值时,这个方法会被调用。\nclass Descriptor:\n def __get__(self, instance, owner):\n print(f"Getting value from {instance.__class__.__name__}")\n \nclass MyClass:\n attr = Descriptor()\n \nmc = MyClass()\nmc.attr\n# 输出:\n# Getting value from MyClass\n__set__\n__set__ 方法定义了在设置属性值时应执行的行为。当试图给属性赋值时,这个方法会被调用。\nclass Descriptor:\n def __set__(self, instance, value):\n print(f"Setting value {value} to {instance.__class__.__name__}")\n \nclass MyClass:\n attr = Descriptor()\n \nmc = MyClass()\nmc.attr = 10\n# 输出:\n# Setting value 10 to MyClass\n__delete__\n__delete__ 方法定义了当删除属性时应执行的行为。当试图删除属性时,这个方法会被调用。\nclass Descriptor:\n def __delete__(self, instance):\n print(f"Deleting value from {instance.__class__.__name__}")\n \nclass MyClass:\n attr = Descriptor()\n \ndel mc.attr\n# 输出:\n# Deleting value from MyClass\n使对象可调用\n**在 Python 中,函数是一类对象,可以调用它们。**但是,您知道您也可以使自己的对象表现得像函数一样吗?通过定义 __call__ 魔术方法,您可以使类的实例表现得像函数,从而允许对它们进行调用。\n__call__\n当实例作为函数被“调用”时__call__ 方法就会被执行。这提供了一种优雅的方式来使用对象,同时保持其对象性质。通过这种方式,您的对象不仅可以表示数据,还可以表现得像函数,这增加了编码的灵活性和创造性。\nclass Greeter:\n def __init__(self, greeting="Hello"):\n self.greeting = greeting\n \n def __call__(self, name):\n return f"{self.greeting}, {name}!"\n \n# 创建一个Greeter实例\nhello_greeter = Greeter("Hello")\nprint(hello_greeter("John")) # 输出Hello, John!\n \nbonjour_greeter = Greeter("Bonjour")\nprint(bonjour_greeter("Pierre")) # 输出Bonjour, Pierre!\n值比较\n__hash__\n__hash__ 方法返回对象的哈希值。哈希值通常用于字典的键值和其他需要快速查找的数据结构中。如果一个对象是可变的,通常最好不要实现此方法。如果对象定义了 __eq__ 方法并且是不可变的,则通常也应定义此方法。\nclass MyClass:\n def __init__(self, value):\n self.value = value\n \n def __eq__(self, other):\n if isinstance(other, MyClass):\n return self.value == other.value\n return NotImplemented\n \n def __hash__(self):\n return hash(self.value)\n \nobj1 = MyClass(5)\nobj2 = MyClass(5)\nmy_dict = {obj1: "a"}\nprint(my_dict[obj2]) # 输出a\n__bool__\n__bool__ 方法用于实现 bool() 内置函数的调用。当我们调用 bool() 函数或使用对象在条件语句(例如 if obj:)中作为条件时,会调用此方法。如果 __bool__ 没有被定义__len__ 会被调用(如果已定义)。如果两者都未定义,所有实例都默认为 True。\nclass MyClass:\n def __init__(self, value):\n self.value = value\n \n def __bool__(self):\n return bool(self.value)\n \nobj1 = MyClass(0)\nobj2 = MyClass(5)\nprint(bool(obj1)) # 输出False\nprint(bool(obj2)) # 输出True\n类型转换\n__int__\n__int__ 方法允许将一个对象转换为整数。当使用 int() 内置函数时,如果对象实现了此方法,会被调用。\nclass MyClass:\n def __int__(self):\n return 42\n \nobj = MyClass()\nprint(int(obj)) # 输出42\n__float__\n__float__ 方法允许将一个对象转换为浮点数。当使用 float() 内置函数时,如果对象实现了此方法,会被调用。\nclass MyClass:\n def __float__(self):\n return 42.0\n \nobj = MyClass()\nprint(float(obj)) # 输出42.0\n__complex__\n__complex__ 方法允许将一个对象转换为复数。当使用 complex() 内置函数时,如果对象实现了此方法,会被调用。\nclass MyClass:\n def __complex__(self):\n return 3 + 4j\n \nobj = MyClass()\nprint(complex(obj)) # 输出:(3+4j)\n__bytes__\n__bytes__ 方法定义了当我们调用 bytes() 时的行为。它应该返回一个字节串。\nclass MyClass:\n def __bytes__(self):\n return b'MyClass instance'\n \nmc = MyClass() # 创建实例\nprint(bytes(mc)) # 输出b'MyClass instance'\n类和静态方法\n在 Python 中,类是一个创建对象的蓝图。对象则是基于类定义的实例。默认情况下,在类内部定义的方法是实例方法。\n实例方法\n实例方法的第一个参数是 self代表类的实例对象。它可以访问和修改与实例相关的属性和方法。实例方法只能由其实例对象调用。\nclass Example:\n def instance_method(self):\n return "This is an instance method", self\n \ne = Example()\nprint(e.instance_method()) \n# 输出 ('This is an instance method', <__main__.Example object at 0x7f49af98f610>)\n类方法\n类方法使用 @classmethod 装饰器定义。其第一个参数是 cls代表类本身。类方法既可以由类直接调用也可以被其实例调用。\nclass Example:\n class_var = "Class Variable"\n \n @classmethod\n def class_method(cls):\n return "This is a class method accessing:", cls.class_var\n \nprint(Example.class_method()) \n# 输出 ('This is a class method accessing:', 'Class Variable')\n静态方法\n静态方法使用 @staticmethod 装饰器定义。它不需要传递 self 或 cls 参数。静态方法不能访问或修改类或实例的属性和方法。它仅仅与它所在的类相关,但不需要访问类的特性。\nclass Example:\n @staticmethod\n def static_method():\n return "This is a static method"\n \nprint(Example.static_method())\n# 输出 This is a static method\n类方法 Vs 静态方法\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型用途优点缺点类方法访问/修改类属性,方法继承于子类可访问/修改类属性,适用于继承不能访问实例特有的属性静态方法不需访问实例/类数据的操作,与类相关但不需访问类或实例无需实例化,代码组织清晰不能访问类和实例的属性或方法\n在面向对象编程中合理地使用实例方法、类方法和静态方法可以使代码更有组织性更易于维护。\n属性\n@property 装饰器\n在 Python 中,@property 装饰器使我们能够将类中的方法用作属性,从而实现对属性的控制。它可以用于确保属性的读取和设置遵循某种特定的逻辑。\nclass Example:\n def __init__(self, number):\n self._number = number\n \n @property\n def number(self):\n return self._number\n \ne = Example(5)\nprint(e.number)\n# 输出 5\n使用 Setter 和 Getter 方法\nSetter 和 Getter 在 Python 中用于控制属性的访问和赋值。\n@<property_name>.setter\n在定义了属性的 getter 方法后,我们可以使用 @<property_name>.setter 装饰器定义相应的 setter 方法,以控制该属性的赋值逻辑。\nclass Example:\n def __init__(self, number):\n self._number = number\n \n @property\n def number(self):\n return self._number\n \n @number.setter\n def number(self, value):\n self._number = value\n \ne = Example(5)\ne.number = 10\nprint(e.number)\n# 输出 10\n@<property_name>.deleter\n除了设置和获取属性我们还可以定义如何删除属性。\nclass Example:\n def __init__(self, number):\n self._number = number\n \n @property\n def number(self):\n return self._number\n \n @number.deleter\n def number(self):\n print("Deleting number")\n del self._number\n \ne = Example(5)\ndel e.number\n属性保护\n在 Python 中,我们通常使用下划线来表示属性应该是私有的或受保护的。\n\n受保护的属性: 通常使用单下划线前缀 _ 来定义,例如 _name。这只是一个约定表示这个属性是为类内部使用的但外部仍然可以访问。\n私有属性: 使用双下划线前缀 __ 来定义,例如 __name。Python 会对其进行名称修饰,使得在类的外部更难直接访问。\n\nclass Example:\n def __init__(self):\n self.__private_attr = "I am private"\n self._protected_attr = "I am protected"\n \n def reveal(self):\n print(self.__private_attr)\n \ne = Example()\nprint(e._protected_attr)\n# print(e.__private_attr) # 将会抛出错误异常\ne.reveal() # 正常工作\n__slots__ 限制动态属性的添加\n为了提高性能和内存效率Python 允许在类定义中使用 __slots__ 来限制可以添加到对象的属性。这通常在需要创建大量对象时很有用。\nclass Example:\n __slots__ = ['name', 'age']\n \ne = Example()\ne.name = "ChatGPT"\n# e.salary = 10000 # 将会抛出错误异常"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/pip":{"title":"pip","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"pip 是 Python 的包管理工具,用于安装和管理 Python 软件包。它从 Python 包索引PyPI获取包并安装。通过 pip我们可以方便地使用已经编写好的 Python 库和框架,避免重复造轮子,提升开发效率。\n安装和升级\n现在在安装 Python 时已经包含了 pip因此一般不需要单独安装。但是我们需要定期更新 pip 以保持其版本的新旧。升级 pip 的命令如下:\npip3 install --upgrade pip\n使用 Pip 安装包\n使用 pip 安装包非常简单,基本命令如下:\npip install package_name\n比如我们想要安装著名的数据处理库 Pandas只需输入\npip install pandas\n有时我们需要安装特定版本的包可以在包名后面添加 == 和版本号,如安装版本为 1.2.3 的 Pandas\npip install pandas==1.2.3\n升级和卸载包\n我们可以用 pip 来升级已经安装的包,命令如下:\npip install --upgrade package_name\n如果我们不再需要某个包可以用 pip 来卸载它,命令如下:\npip uninstall package_name\nrequirements.txt\n在 Python 项目中,我们通常会有很多依赖,这些依赖会被写在一个名为 requirements.txt 的文件中。这个文件是一个文本文件,列出了项目所需的所有 Python 包及其对应的版本号。比如,一个 requirements.txt 可能是这样的:\nnumpy==1.18.5\npandas==1.2.3\nscikit-learn==0.23.2\n我们可以通过以下命令来安装 requirements.txt 中的所有包:\npip install -r requirements.txt\npip 并不是 Python 的唯一包管理工具。比如conda 是一个同时处理 Python 和非 Python 包的工具适合于科学计算和数据分析pipenv 和 poetry 则集成了包管理和虚拟环境管理,适合于开发 Python 应用。\nVenv 虚拟环境\nvenv 是 Python3 中自带的虚拟环境工具。它可以在单独的目录中创建独立的 Python 运行环境,使得项目所需的包和版本与其他项目隔离开来,避免版本冲突。\n使用 venv 创建虚拟环境的方法如下:\n\n在终端中运行下面的命令创建虚拟环境\n\npython3 -m venv /path/to/new/virtual/env_name\n\n激活虚拟环境\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nShell用于激活虚拟环境的命令bash/zsh$ source <venv>/bin/activatefish$ source <venv>/bin/activate.fishcsh/tcsh$ source <venv>/bin/activate.cshPowerShell$ <venv>/bin/Activate.ps1cmd.exeC:\\> <venv>\\Scripts\\activate.batPowerShellPS C:\\> <venv>\\Scripts\\Activate.ps1\n在激活虚拟环境后可以使用 pip 安装包。可以使用 deactivate 命令关闭虚拟环境。"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/pipenv":{"title":"pipenv","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"简介\nPipenv 是 Python 官方推荐的包管理和虚拟环境工具。它结合了 pip 和 virtualenv 的功能,提供了一种简单且高效的方式来管理项目的依赖和环境。\nPipenv 主要旨在为应用程序的用户和开发人员提供一种简单的方法来实现一致的工作项目环境。\n特性\n\n自动管理虚拟环境Pipenv 自动创建和管理虚拟环境,简化了环境配置过程。\n声明式依赖文件Pipfile 易于阅读和编辑,更加人性化。\n依赖锁定Pipfile.lock 确保了在不同环境中依赖版本的一致性。\n安全性检查集成了安全性检查功能可以检测依赖中的安全漏洞。\n环境变量隔离通过支持 .env 文件Pipenv 提供了一种简单的环境变量管理方法。\n\n安装\nPipenv 可以通过 pip 安装在不同的操作系统上,推荐使用最新版的 pip 和 Python 以确保兼容性。安装命令如下:\n# 在 macOS 上\n$ brew install pipenv\n \n# 在 Windows 上\n$ pip install --user pipenv\n \n# 在 Linux 上\n$ pip3 install --user pipenv\n注意在 Windows 系统上,可能需要将用户二进制目录添加到环境变量。在 Linux 系统上,建议使用 pip3 以确保 Python 3 的兼容性。\n基本概念\nPipfile\n\nPipfile声明项目所需依赖的文件类似于 requirements.txt但更易于阅读和维护。\n\nPipfile.lock\n\nPipfile.lock锁定依赖版本确保所有环境中的依赖一致性防止版本冲突。\n\n常用流程\ngraph LR\n A[开始] --> B[克隆/创建项目]\n B --> C[安装依赖]\n C --> D[添加包]\n D --> E[更新全部依赖]\n E --> F[更新特定包]\n F --> G[检查过时包]\n G --> H[确定虚拟环境路径]\n H --> I[激活 Pipenv shell]\n\n# 1.克隆或创建项目仓库\ncd your_project_directory\n \n# 2.安装依赖使用 pipenv sync 安装 Pipfile.lock 中的依赖\npipenv sync\n \n# 3.添加包并更新依赖\npipenv install <package>\n \n# 4.更新所有包\npipenv update\n \n# 更新特定包\npipenv update <package>\n \n# 检查过时的包\npipenv update --outdated\n \n# 获取虚拟环境的路径\npipenv --venv\n \n# 激活 Pipenv shell 虚拟环境\npipenv shell\n基本操作\n创建虚拟环境\n创建一个新的项目时Pipenv 会自动为你创建一个虚拟环境。运行以下命令来创建一个新的项目:\nmkdir myproject\ncd myproject\npipenv install\n这会创建一个 Pipfile 和一个空的虚拟环境。\n安装和同步依赖\n\n安装依赖pipenv install [package]\n\n# 例如,安装 requests\npipenv install requests\n\n这会自动将 requests 添加到 Pipfile 并更新 Pipfile.lock。\n\n同步环境pipenv sync\n\n使用 pipenv sync 可以快速同步项目环境,例如:\n# 根据 Pipfile.lock 安装依赖\npipenv sync\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令用途pipenv install安装项目所需的包pipenv install —python [version]安装项目指定的 python 版本(使用 pyenvpipenv install [package]安装特定的包pipenv install —dev [package]安装用于开发环境的包pipenv uninstall [package]卸载特定的包pipenv lock生成锁定文件确保项目在不同环境中的包版本一致性pipenv sync根据 Pipfile.lock 安装所有依赖确保与锁文件一致pipenv update更新项目中的所有包pipenv update [package]更新特定的包pipenv install —ignore-pipfile忽略 Pipfile根据 Pipfile.lock 安装依赖pipenv install —selective-upgrade升级指定的依赖并更新 Pipfile.lock 文件pipenv check检查项目中的包是否有安全漏洞pipenv verify校验 Pipfile.lock 中的哈希是否最新pipenv graph展示项目依赖关系图pipenv clean删除虚拟环境中无用的包pipenv shell启动虚拟环境的 shellpipenv run [command]在虚拟环境中运行命令pipenv —venv显示虚拟环境的位置pipenv —py显示虚拟环境中 Python 解释器的位置pipenv —where显示项目文件的位置pipenv —rm删除虚拟环境\n高级操作\n自动安装 Python\nPipenv 可以与 pyenv 结合使用,自动安装所需的 Python 版本。这在你的系统中没有安装特定版本的 Python 时非常有用。\n示例代码\n# 假设你的 Pipfile 需要 Python 3.6,但系统中没有安装\n# 当运行 pipenv install 时,它会提示是否使用 pyenv 安装 Python 3.6\npipenv install\n自动加载 .env 文件\nPipenv 会自动从 .env 文件加载环境变量。这对于管理配置和密钥非常有用,尤其是在生产环境中。\n# 假设你有一个 .env 文件包含如下内容\nHELLO=WORLD\n \n# 当运行 pipenv shell 或 pipenv run 时,它会加载这些环境变量\npipenv run python main.py\n自定义虚拟环境位置\n通过设置 WORKON_HOME 环境变量,你可以自定义 Pipenv 创建虚拟环境的位置。\n# 将虚拟环境存储在特定位置\nexport WORKON_HOME=~/.venvs\n使用 Pipenv 进行测试\nPipenv 与 Travis CI 和 tox 等测试框架结合使用,可以维护一致的测试环境。\n示例 Travis CI 配置:\nlanguage: python\npython:\n - "3.6"\ninstall:\n - pip install pipenv\n - pipenv install --dev\nscript:\n - pipenv run pytest\nPipfile Vs setup.py\n理解 Pipfile 和 setup.py 之间的区别。Pipfile 用于应用程序,而 setup.py 用于库。\n示例 Pipfile\n[[source]]\nurl = "pypi.python.org/simple"\nverify_ssl = true\n \n[packages]\nrequests = "*"\n示例 setup.py\nfrom setuptools import setup\n\nsetup(\n name='your_package',\n version='0.1',\n install_requires=[\n 'requests',\n ]\n)\n"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/poetry":{"title":"poetry","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"简介\nPoetry 是一个面向未来的 Python 依赖管理和打包工具,它支持了 Python 社区的 PEP 518 提案里的 pyproject.toml 新标准文件,用以管理我们与 Python 项目有关的内容。它的目的是简化 Python 包管理的过程,使其变得更容易和更可靠。\nPoetry 主要由两部分组成:\n\n一个命令行工具用于管理依赖关系和发布包。\n一个配置文件pyproject.toml用于描述项目的元数据和依赖关系。\n\nPoetry 的一个重要特点是它支持自动生成和维护项目的锁定文件Pipfile.lock锁定文件用于跟踪项目依赖关系的版本号。这样可以保证项目在不同环境中使用相同的依赖关系版本。\nPoetry 也支持创建和发布 Python 包,使用 poetry build 命令可以生成可发布的包,使用 poetry publish 命令可以将包发布到 PyPI 上。\n总之 poetry 是一个功能强大,简单易用,支持创建和发布包的工具,适合于开发和维护 Python 项目的开发人员使用。它提供了一组简单易用的命令来管理项目的依赖关系,并且支持自动生成和维护项目的锁定文件,保证项目在不同环境中使用相同的依赖关系版本。并且它还支持创建和发布 Python 包,使得开发者可以更加方便地管理项目和发布自己的包。\n使用\n1. 安装\nPoetry 为了避免版本控制混乱,不推荐使用 pip 安装 poetry。\nLinux, macOS, Windows (WSL)\ncurl -sSL install.python-poetry.org | python3 -\nWindows (Powershell)\n如果是通过 Microsoft Store 安装的 Python请将命令中的 py 替换为 python。\n(Invoke-WebRequest -Uri install.python-poetry.org -UseBasicParsing).Content | py -\n2. 设置\nPoetry 会基于平台安装在特定的目录,如果此目录不在 Path 中需要手动添加路径:\n\nMacOS~/Library/Application Support/pypoetry/venv/bin/poetry\nLinux/Unix~/.local/share/pypoetry/venv/bin/poetry\nWindows%APPDATA%\\pypoetry\\venv\\Scripts\\poetry\n\n设置完成后可以使用 poetry --version 命令验证版本。\n3. 使用\n3.1 项目管理\n新建项目\n# 新建 poetry-demo 项目\npoetry new poetry-demo\n \n# 项目目录\npoetry-demo\n├── pyproject.toml\n├── README.md\n├── poetry_demo\n│ └── __init__.py\n└── tests\n └── __init__.py\n \n# pyproject.toml\n[tool.poetry]\nname = "poetry-demo"\nversion = "0.1.0"\ndescription = ""\nauthors = ["Sébastien Eustace <sebastien@eustace.io>"]\nreadme = "README.md"\npackages = [{include = "poetry_demo"}]\n \n[tool.poetry.dependencies]\npython = "^3.7"\n \n \n[build-system]\nrequires = ["poetry-core"]\nbuild-backend = "poetry.core.masonry.api"\n \n初始化项目\n# 初始化\ncd pre-existing-project\npoetry init\n \n# 引导创建项目配置\n······\n3.2 虚拟环境\n# 激活虚拟环境\npoetry shell\n \n# 关闭虚拟环境\nexit\ndeactivate\n \n# 设置 Python 版本\npoetry env use /full/path/to/python\npoetry env use python3.7\npoetry env use 3.7\n \n# 环境信息\npoetry env info\npoetry env list\n \n# 删除环境\npoetry env remove /full/path/to/python\npoetry env remove python3.7\npoetry env remove 3.7\n \n# 删除所有虚拟环境\npoetry env remove --all\n3.3 安装依赖\n# 安装依赖\npoetry install\n \n# 添加依赖包\npoetry add django\n \n# 安装依赖指定版本\npoetry add django@^4.0.0\npoetry add django@latest\n \n# 移除依赖\npoetry remove django\n \n# 更新依赖\npoetry update\n3.4 依赖组别\nPoetry 提供了一种按组织依赖项的方法。例如,您可能拥有仅用于测试项目或构建文档所需的依赖项。\n# -D 选项添加到开发组依赖\npoetry add -D black flake8 mypy\n \n# -D 选项移除开发组依赖\npoetry remove -D black flake8 mypy\n \n# --group 选项添加到指定组\npoetry add pytest --group test\n3.5 打包发布\n# 打包\npoetry build\n \n# 发布 PyPI\npoetry publish\n \n# 设置包源\npoetry config repositories.foo pypi.example.org/legacy/\n \n# 发布指定包源\npoetry publish --build --repository foo-pub\n \n# 导出 requirements.txt\npoetry export -o requirements.txt\n \n# 不导出 Hash 值\npoetry export --without-hashes\n \n# 导出开发依赖\npoetry export --without-hashes --dev\n3.6 依赖包源\n# --default 选项配置默认包源\npoetry source add --default foo foo.bar/simple/\n \n# --secondary 选项配置辅助包源\npoetry source add --secondary foo pypi.example.org/simple/\n \n# 配置辅助包源凭证\npoetry config http-basic.foo <username> <password>\n \n# 指定包源添加依赖\npoetry add --source foo private-package\n4. 命令\npoetry 的 常用命令,完整的命令可以在终端执行 poetry —help 查看。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令作用new创建新项目install安装项目依赖add添加项目依赖remove删除项目依赖update更新项目依赖lock生成锁定文件build构建项目包publish发布项目包env管理虚拟环境run运行项目shell进入项目环境config查看或修改配置info显示项目信息check检查项目状态\n5. 更新\n# 自动更新\npoetry self update\n# 安装预发布版本\npoetry self update --preview\n# 安装特定版本\npoetry self update 1.3.0\n6. 卸载\nPoetry 可以通过使用 --uninstall 选项再次运行安装程序,或 POETRY_UNINSTALL 在执行安装程序之前设置环境变量来将它从系统中完全删除。\ncurl -sSL install.python-poetry.org | python3 - --uninstall\ncurl -sSL install.python-poetry.org | POETRY_UNINSTALL=1 python3 -"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/pyenv":{"title":"pyenv","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"概述\nPython 是一种广泛使用的高级编程语言,以其易读性和强大的库支持而闻名。然而,随着项目数量和复杂性的增加,管理不同项目所需的不同 Python 版本和依赖成为了一个挑战。pyenv 和 pipenv 是两个解决这些问题的强大工具,能够帮助开发者有效地管理多个 Python 版本和项目环境。\npyenv 是一个流行的 Python 版本管理工具,它允许你在同一系统上安装和使用多个 Python 版本。它提供了一个干净的方式来切换全局 Python 版本,也可以在项目级别设置特定的 Python 版本。\n实现\npyenv 实现多版本 Python 管理的核心是通过拦截 Python 命令,选择并使用特定的 Python 版本。这是通过几个关键步骤和机制实现的:\n1. 改变 PATH 环境变量\npyenv 在你的 PATH 环境变量前面插入一个 shims 目录。当你运行 python 或 Python 包的任何命令时,实际上你首先运行的是一个 shim。\n2. 使用 Shims\nShims是一种轻量级的转发脚本它们决定实际调用哪个 Python 版本。当你运行 python 时shim 会查询 pyenv 以确定使用哪个版本的 Python。\n3. 版本选择\npyenv 根据多个因素确定使用哪个 Python 版本,包括:\n\n全局版本你通过 pyenv global 设置的系统范围的默认版本。\n项目级别版本通过 pyenv local 在特定项目目录下设置的版本。\nShell 临时版本:通过 pyenv shell 为当前会话设置的版本。\n版本继承如果你在一个没有本地版本设置的目录中pyenv 会向上查找父目录直到找到一个版本或达到全局版本。\n\n4. 构建和安装 Python\n当你要求安装新的 Python 版本时pyenv 会下载源代码,然后根据你的系统配置编译它。完成后,该特定版本的 Python 将被安装在 ~/.pyenv/versions 目录下。\n5. 灵活性和可扩展性\n\npyenv 可以通过插件来扩展,如 pyenv-virtualenv提供对虚拟环境的支持。\n它不会覆盖系统 Python 版本,而是允许你在系统 Python 和任意数量的不同版本之间切换。\n\n使用\n1. 安装 Python 版本\n确定项目需要哪个 Python 版本。使用 pyenv install <version> 来安装该版本(如 3.8.5)。\n2. 创建项目目录\n为你的项目创建一个新目录或者导航到现有项目的目录。\n3. 设置项目的 Python 版本\n在项目目录中使用 pyenv local <version> 设置项目使用的 Python 版本。这将在当前目录创建一个 .python-version 文件,指定该目录下所有命令应使用的 Python 版本。\n4. 验证 Python 版本\n在项目目录中运行 python --version 确保正确的 Python 版本被激活。\n5. (可选)集成虚拟环境\n虽然 pyenv 本身不直接处理虚拟环境,但它与 pipenv、virtualenv 等工具兼容。如果需要,可以现在设置虚拟环境:\n\n使用 pipenv运行 pipenv install 来创建虚拟环境并生成 Pipfile。\n使用 virtualenv首先安装 pyenv-virtualenv 插件,然后使用 pyenv virtualenv <version> <env-name> 创建一个新的虚拟环境。\n\n6. 激活虚拟环境(如果使用)\n如果你使用了虚拟环境工具\n\n对于 pipenv使用 pipenv shell 来激活虚拟环境。\n对于 pyenv-virtualenv虚拟环境将根据 .python-version 或 pyenv local <env-name> 自动激活。\n\n7. 安装依赖\n在激活的虚拟环境中使用 pip 或 pipenv 安装项目所需的所有依赖。\n8. 开发和测试\n进行你的正常开发工作。只要你在项目目录中pyenv 和虚拟环境都会确保使用正确的 Python 版本和依赖。\n9. 提交和共享\n在项目的版本控制系统如 Git中提交 .python-version 文件(不要提交虚拟环境)。这样,其他开发者可以了解并使用相同的 Python 版本。\n命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令描述示例/注释pyenv install <version>安装指定的 Python 版本pyenv install 3.8.5 安装 Python 3.8.5pyenv uninstall <version>卸载指定的 Python 版本pyenv uninstall 3.8.5 卸载 Python 3.8.5pyenv versions列出所有已安装的 Python 版本列出系统中所有可用的 Python 版本pyenv version显示当前激活的 Python 版本显示当前会话或全局设置的 Python 版本pyenv global <version>设置全局默认的 Python 版本pyenv global 3.8.5 设置全局版本为 3.8.5pyenv local <version>设置当前目录的 Python 版本pyenv local 3.7.7 设置当前目录的 Python 版本pyenv shell <version>设置当前会话的 Python 版本pyenv shell 3.6.9 临时更改会话的 Python 版本pyenv rehash重新计算并安装 shim在安装新版本或卸载后更新 shimpyenv which <command>显示特定命令的路径pyenv which pip 显示 pip 命令的路径pyenv exec <command>在选定的 Python 环境中执行命令pyenv exec pip list 在当前环境中运行 pip listpyenv init用于配置 shell 环境通常添加到 .bashrc 或 .zshrcpyenv virtualenvs列出所有已创建的虚拟环境列出系统中所有已创建的虚拟环境pyenv virtualenv <version> <env-name>创建一个新的虚拟环境pyenv virtualenv 3.8.5 myenv 创建名为 myenv 的虚拟环境pyenv virtualenv-delete <env-name>删除指定虚拟环境pyenv virtualenv-delete myenv 删除名为 myenv 的虚拟环境pyenv local --unset取消项目级别的 Python 版本设置pyenv local --unset 取消项目目录下的 Python 版本设置pyenv shell --unset取消会话级别的 Python 版本设置pyenv shell --unset 取消会话中的 Python 版本设置pyenv local --unset-all取消所有项目级别的 Python 版本设置pyenv local --unset-all 取消所有项目目录下的 Python 版本设置pyenv version-file查找当前目录下的 .python-version 文件pyenv version-file 查找并显示当前目录下的 .python-version 文件路径"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/virtualenv":{"title":"Virtualenv","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"简介\nVirtualenv 是 Python 社区一款老牌、成熟的虚拟环境管理工具,经过多个版本迭代也具备丰富的功能。并且自从 Python 3.3 版本开始,它的部分功能已也被集成到了 venv 标准库中,足见其对于 Python 虚拟环境管理工作贡献的份量如何。\n从某些程度上来说Virtualenv 和 venv 的功能十分类似,但 Virtualenv 在其官方文档中也指出了 venv 的不足之处:\n\nis slower创建速度慢\nis not as extendable可扩展性差\ncannot create virtual environments for arbitrarily installed python versions无法创建任意 Python 版本的虚拟环境)\nis not upgrade-able via pip无法通过 pip 进行升级)\ndoes not have as rich programmatic API没有丰富的 API 编程方法扩展)\n\n而这些不足之处在 Virtualenv 里都有了比较完善的解决方案。\n使用\nvirtualenv 是一个用于创建虚拟环境的库。它可以在其中安装 Python 包并运行 Python 程序。使用 virtualenv 创建虚拟环境的方法如下:\n\n安装 virtualenv\n\npip install virtualenv\n\n创建虚拟环境\n\nvirtualenv env_name\n\n激活虚拟环境\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nShell用于激活虚拟环境的命令bash/zsh$ source <venv>/bin/activatefish$ source <venv>/bin/activate.fishcsh/tcsh$ source <venv>/bin/activate.cshPowerShell$ <venv>/bin/Activate.ps1cmd.exeC:\\> <venv>\\Scripts\\activate.batPowerShellPS C:\\> <venv>\\Scripts\\Activate.ps1\n在激活虚拟环境后可以使用 pip 安装包。可以使用 deactivate 命令关闭虚拟环境。"},"Technology/ProgrammingLanguage/Python/项目/虚拟环境/概述":{"title":"概述","links":[],"tags":["Python/虚拟环境","技术/程序语言"],"content":"虚拟环境是一种在单独的目录中为 Python 项目创建独立的 Python 运行环境的方式。这样可以确保项目所需的包和版本与其他项目隔离开来,避免版本冲突。\n在 Python 中,有很多工具可以用来创建和管理虚拟环境,如下:\n\nvenvPython3 中自带的轻量级虚拟环境管理工具。\nvirtualenv一款老牌、成熟的虚拟环境管理工具。\nPoetry一个面向未来的 Python 依赖管理和打包工具。\npipenv一个较新的结合 pip 和 virtualenv 的虚拟环境管理工具。\nConda一个跨平台的包或库和虚拟环境管理系统。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具优点缺点不同点venvPython3 内置工具无需安装额外的包简单易用的虚拟环境管理。比其他工具poetry、pipenv功能较弱。venv 是 Python3 内置工具无需安装额外的包venv 更简单易用功能不如其他工具强大。virtualenv广泛使用且文档齐全兼容 Python2 和 Python3。比其他工具poetry、pipenv功能较弱。virtualenv 是第三方包需要预先安装virtualenv 更简单易用功能不如其他工具强大。poetry强大的依赖管理功能支持创建和发布包与其他工具集成良好。不如 pip 和 virtualenv 广泛使用相对较新文档较少。poetry 比 venv 和 virtualenv 更强大的依赖管理功能poetry 适合创建和发布包,不如 venv 和 virtualenv 简单。pipenv强大的包和环境管理功能简单易用能与其他工具良好的集成。不如 pip 和 virtualenv 广泛使用, 相对较新文档较少。pipenv 比 venv 和 virtualenv 更强大的依赖管理功能pipenv 简易好用,不如 venv 和 virtualenv 简单易用。conda强大的包和环境管理功能适合科学计算和数据科学跨平台支持。不如 pip 和 virtualenv 广泛使用相对较新文档较少。conda 比 venv 和 virtualenv 更强大的依赖管理功能conda 适用于科学计算和数据科学,不如 venv 和 virtualenv 简单易用。"},"Technology/ProgrammingLanguage/Python/项目/风格指南/风格指南":{"title":"Python 风格指南","links":[],"tags":["Python/项目","技术/程序语言"],"content":"PEP 8 官方风格\nPEP 8 Style Guide for Python Code\nPEP 8 — Python 代码风格指南(中文版)\nGoogle 风格指南\nGoogle Python Style Guide\n谷歌 Python 风格指南 - 语言规范(中文版)"},"Technology/ProgrammingLanguage/home":{"title":"程序设计语言","links":[],"tags":[],"content":"TIOBE 榜单\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nOct 2022Oct 2021ChangeProgramming LanguageRatingsChange11Python17.08%+5.81%22C15.21%+4.05%33Java12.84%+2.38%44C++9.92%+2.42%55C#4.42%-0.84%66Visual Basic3.95%-1.29%77JavaScript2.74%+0.55%810Assembly language2.39%+0.33%99PHP2.04%-0.06%108SQL1.78%-0.39%\n\n来源TIOBE Index - TIOBE非商业引用著作权归作者所有。\n\n程序设计语言历史\n1940 之前\n第一个编程语言比现代的电脑还早诞生。首先这种语言是种代码。\n于 1804 年发明的雅卡尔织布机,运用打孔卡上的坑洞来代表缝纫织布机的手臂动作,以便自动化产生装饰的图案。\n1940 年代\n最早被确认的现代化、电力启动electrically powered的电脑约在 1940 年代被创造出来。程序员在有限的速度及存储器容量限制之下撰写人工调整hand tuned过的汇编语言程序。\n1950 与 1960 年代\n有三个现代编程语言于 1950 年代被设计出来,这三者所派生的语言直到今日仍旧广泛地被采用:\n\nFORTRAN (1955),名称取自 “FORmula TRANslator”(公式翻译器),由约翰·巴科斯等人所发明;\nLISP名称取自 “LISt Processor”(枚举处理器),由约翰·麦卡锡等人所发明;\nCOBOL名称取自 “COmmon Business Oriented Language”(通用商业导向语言),由被葛丽丝·霍普深刻影响的 Short Range Committee 所发明。\n\n1960 年代晚期 - 1970 年代晚期:确立了基础范型\n1960 年代晚期至 1970 年代晚期的期间中,编程语言的发展也有了重大的成果。大多数现在所使用的主要语言范型都是在这段期间中发明的:\n\nSimula于 1960 年代晚期由奈加特与达尔以 Algol 60 超集合的方式发展,同时也是第一个设计支持面向对象进行开发的编程语言。\nC于 1969 至 1973 年间由贝尔实验室的研究人员丹尼斯·里奇与肯·汤普逊所开发,是一种早期的系统程序设计语言。\nSmalltalk于 1970 年代中期所开发是一个完全从零开始ground-up设计的面向对象编程语言。\nProlog于 1972 年由 Colmerauer、Roussel 以及 Kowalski 所设计,是第一个逻辑程序语言。\nML于 1973 年由罗宾·米尔纳所发明,是一个基于 Lisp 所建构的多态polymorphic类型系统同时也是静态类型函数编程语言的先驱。\n\n1980 年代:增强、模块、性能\n1980 年代的编程语言与之前相较显得更为强大。C++ 合并了面向对象以及系统程序设计。美国政府标准化一种名为 Ada 的系统编程语言并提供给国防承包商使用。日本以及其他地方运用了大量的资金对采用逻辑编程语言结构的第五代编程语言进行研究。函数编程语言社群则把焦点转移到标准化 ML 及 Lisp 身上。这些活动都不是在开发新的范型,而是在将上个世代发明的构想进一步发扬光大。\n在这段期间被开发出来的重要语言包括有\n\n1980 - Ada\n1983 - C++(就像有类别的 C\n1984 - Common Lisp\n1985 - Eiffel\n1986 - Erlang\n1987 - Perl\n1988 - Tcl\n1989 - FLBackus\n\n1990 年代:互联网时代\n1990 年代未见到有什么重大的创新,大多都是以前构想的重组或变化。这段期间主要在推动的哲学是提升程序员的生产力。许多 ” 快速应用程序开发 ” RAD语言也应运而生这些语言大多都有相应的集成开发环境、垃圾回收等机制且大多是先前语言的派生语言。这类型的语言也大多是面向对象的编程语言包含有 Object Pascal、Visual Basic以及 C#。Java 则是更加保守的语言,也具备垃圾回收机制。与其他类似语言相比,也受到更多的观注。新的脚本语言则比 RAD 语言更新更好。这种语言并非直接从其他语言派生而且新的语法更加开放地liberal与功能契合。虽然脚本语言比 RAD 语言来的更有生产力,但大多会有因为小程序较为简单,但是大型程序则难以使用脚本语言撰写并维护的顾虑。尽管如此,脚本语言还是网络层面的应用上大放异彩。\n在这段期间被开发出来的重要语言包括有\n\n1990 - Haskell\n1991 - Python\n1991 - Visual Basic\n1993 - Ruby\n1993 - Lua\n1994 - Close (part of ANSI Common Lisp)\n1995 - Java\n1995 - Delphi (Object Pascal)\n1995 - JavaScript\n1995 - PHP\n1997 - REBOL\n1999 - D\n\n现今的趋势\n编程语言持续在学术及企业两个层面中发展进化目前的一些趋势包含有\n\n\n在语言中增加安全性与可靠性验证机制额外的堆栈检查、信息流 (information flow) 控制,以及静态线程安全。\n\n\n提供模块化的替代机制混入委托以及剖面导向。\n\n\n组件导向 (component-oriented) 软件开发。\n\n\n元编程、反射或是访问抽象语法树。\n\n\n更重视分布式及移动式的应用。\n\n\n与数据库的集成包含 XML 及关系数据库。\n\n\n支持使用 Unicode 编写程序,所以原始码不会受到 ASCII 字符集的限制,而可以使用像是非拉丁语系的脚本\n\n\n延伸标点符号。\n\n\n图形用户界面所使用的 XML(XUL、XAML)。\n\n\n在这段期间被开发出来的重要语言包括有\n\n2001 - C#\n2001 - Visual Basic .NET\n2002 - F#\n2003 - Scala\n2003 - Factor\n2006 - Windows PowerShell\n2007 - Clojure\n2009 - Go\n2014 - Swift (编程语言)\n\n编程语言发展史上的杰出人物\n\n约翰·巴科斯发明了 Fortran。\n阿兰·库珀开发了 Visual Basic。\n艾兹格·迪杰斯特拉开创了正确运用编程语言proper programming的框架。\n詹姆斯·高斯林开发了 Oak该语言为 Java 的先驱。\n安德斯·海尔斯伯格开发了 Turbo Pascal、Delphi以及 C#。\n葛丽丝·霍普开发了 Flow-Matic该语言对 COBOL 造成了影响。\n肯尼斯·艾佛森开发了 APL并与 许国华 合作开发了 J。\n比尔·乔伊发明了 viBSD Unix 的前期作者,以及 SunOS 的发起人,该操作系统后来改名为 Solaris。\n艾伦·凯开创了 面向对象编程语言,以及 Smalltalk 的发起人。\n布莱恩·柯林汉与 丹尼斯·里奇 合著第一本 C 程序设计语言的书籍,同时也是 AWK 与 AMPL 程序设计语言的共同作者。\n约翰·麦卡锡发明了 LISP。\n约翰·冯·诺伊曼操作系统 概念的发起者。\n丹尼斯·里奇发明了 C。\n比雅尼·斯特劳斯特鲁普开发了 C++。\n肯·汤普逊发明了 Unix。\n尼克劳斯·维尔特发明了 Pascal、Modula 与 Oberon。\n拉里·沃尔创造了 Perl 与 Raku。\n吉多·范罗苏姆创造了 Python。\n\n\n来源编程语言历史 - 维基百科,自由的百科全书;非商业引用,著作权归作者所有。\n\n程序设计语言图谱\n\n\nSVG 格式图片,新窗口打开可以无失真缩放查看。\n来源Computer Languages History非商业引用著作权归作者所有。\n\n程序设计语言生命周期\n不仅可以在每个程序设计语言的官方可以了解其生命周期还可以在如下网址查询\n\nendoflife.date\n"},"Technology/SoftwareEngineering/协作规范/1.关于Readme":{"title":"关于Readme","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"README 文件的命名应以项目的受众群体为依据。命名 README.md、README_EN.md、README_ZH.md。\n中文模板\n# 项目名称\n \n## 徽章\n \n[![Badge](img.shields.io/badge/Badge-Text-blue)](链接)\n \n## 简介\n \n在这部分提供对你的项目的简短描述包括其功能目标和主要特性。\n \n## 演示\n \n如果可能的话提供一个项目演示的链接或者是屏幕录像。这可以让用户直观地了解项目的功能和使用方式。\n \n## 原理图 / 流程图\n \n如果项目的工作原理复杂或者涉及到一些特定的流程可以在这里提供一个原理图或者流程图来帮助理解。\n \n# 用法\n \n## 安装\n \n提供详细的安装指南包括所有必要的步骤和要求。\n \n## 文档\n \n提供关于如何使用项目的详细信息或者链接到详细的文档。\n \n## FAQ\n \n列出一些常见的问题和答案以帮助用户解决可能遇到的问题。\n \n# 路线\n \n## 开发路线\n \n描述项目的未来发展计划包括新功能和改进。\n \n## 更新历史\n \n提供一个项目的更新历史包括版本号、更新日期以及主要的修改。\n \n# 贡献\n \n说明如何为项目做出贡献包括代码、文档或者报告问题。\n \n# 致谢\n \n向为项目提供帮助的人或者组织表示感谢。\n \n# 协议\n \n列出项目的许可协议或者提供一个链接到全文。\n英文模板\n# Project Name\n \n## Badges\n \n[![Badge](img.shields.io/badge/Badge-Text-blue)](Link)\n \n## Introduction\n \nIn this section, provide a brief description of your project, including its functions, goals, and main features.\n \n## Demo\n \nIf possible, provide a link to a project demo or a screencast. This can give users a direct understanding of the project's functionality and usage.\n \n## Schematic / Flowchart\n \nIf the working principle of the project is complex or involves specific processes, provide a schematic or flowchart to aid understanding here.\n \n# Usage\n \n## Install\n \nProvide detailed installation guides, including all necessary steps and requirements.\n \n## Documentation\n \nProvide detailed information on how to use the project, or link to detailed documentation.\n \n## FAQ\n \nList some common questions and answers to help users solve possible problems.\n \n# Map\n \n## Development map\n \nDescribe the future development plan of the project, including new features and improvements.\n \n## Update history\n \nProvide a history of project updates, including version numbers, update dates, and major modifications.\n \n# Contribute\n \nExplain how to contribute to the project, including code, documentation, or reporting issues.\n \n# Thanks\n \nExpress gratitude to individuals or organizations that have provided help for the project.\n \n# License\n \nList the project's license, or provide a link to the full text.\n "},"Technology/SoftwareEngineering/协作规范/2.开源协议License":{"title":"开源协议License","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"文件命名LICENSE\n许可证向导kaiyuanshe.cn/license-tool/\n"},"Technology/SoftwareEngineering/协作规范/3.贡献者协议Contributing":{"title":"贡献者协议Contributing","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"开源项目的成功在很大程度上取决于社区的参与和贡献。然而这种参与经常涉及到一些复杂的法律问题尤其是与知识产权有关的问题。为了解决这些问题开源社区引入了两种主要的贡献者协议CLA (Contributor License Agreement) 和 DCO (Developer Certificate of Origin)。这两种协议在法律义务和责任方面有着显著的不同。\nCLA\nCLA (Contributor License Agreement) 是开源协议的补充它明确了贡献者和项目所有者之间的法律关系。CLA 协议包括公司级别和个人级别的 CLA公司级别的 CLA 允许一个公司代表其所有员工签署,而个人级别的 CLA 则只针对个人贡献者。\nCLA 协议主要涵盖以下几点:\n\n签署该 CLA 的主体和贡献的定义;\n授予著作权给拥有该软件知识产权的公司或组织\n专利许可的授予\n签署者保证依法有权授予上述许可\n签署者确保所有的贡献内容均为原创作品\n签署者为贡献内容支持的免责描述\n说明贡献者提交非原创作品应该采用的方式\n保证在获悉任何方面不准确的事实或情况之时通知签约方。\n\n对于在中国的企业他们还会在 CLA 协议中加入一些本地化的内容,比如阿里巴巴的 Alibaba Open Source Individual CLA。\nDCO\nDCO (Developer Certificate of Origin) 是由 Linux Foundation 制定的,它并不是一个法律协议,而是一种证明。开源贡献者只需要在提交时签署邮件地址,就相当于确认了他们对提交的贡献拥有相应的权利,并同意该贡献在该项目或涉及的开源许可下公开发布。\nDCO 包含以下四点保证:\n\n贡献全部或部分由我创建我有权根据文件中指明的开源许可提交\n贡献是基于以前的工作这些工作属于适当的开源许可无论这些工作全部还是部分由我完成我有权根据相同的开源许可证除非我被允许根据不同的许可证提交提交修改后的工作\n贡献由 1、2、或 3 证明的其他人直接提供给我,而我没有对其进行修改。\n我理解并同意该项目和贡献是公开的并且该贡献的记录包括我随之提交的所有个人信息包括我的签字将无限期保留并且可以与本项目或涉及的开源许可证保持一致或者重新分配。\n\nCLA 与 DCO 的比较\n下表对比了 CLA 和 DCO 的特性,可以看出两者在法律责任、社区属性、签署方式等方面都有不同。这就需要根据项目的特点和需求来选择合适的贡献协议。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性CLADCO社区属性弱强签署方式一次性每次提交时在 commit 信息里追加 Signed-off-by: email 信息法律责任明确法律义务无声明,用来限制提交者遵守开源 license是否可自定义公司或组织可自行定义否使用案例Google、Pivotal、CNCF、阿里巴巴、Apache SkyWalkingGitLab、Chef、Harbor、TiKV公司属性强可以签署公司级别的 CLA弱\n在选择合适的贡献协议时不仅要考虑法律问题也要考虑社区的文化和参与者的需求。例如对于大型跨公司开源项目来说CLA 可能更适合因为它可以让项目更加正规并且更符合长期发展的需求。而对于那些更依赖社区的项目来说DCO 由于其简洁和易于理解的优点,可能会是更好的选择。\n贡献者协议\n文件通常被命名为 CONTRIBUTING.md这个文件通常位于项目的根目录中。有一些项目可能会使用不同的文件名例如 CONTRIBUTORS.txt 或 CONTRIBUTE.md但是 CONTRIBUTING.md 是最常见的约定。\n中文模板\n贡献者许可协议\n \n本贡献者许可协议以下简称“协议”由签署下列的一方以下简称“贡献者”同意并向[项目名称]授予对由[项目名称]管理的软件项目的某些许可权。本协议自下列最新的签名日期起生效。\n \n1. 定义:\n “代码”指的是在此协议下由贡献者交付给[项目名称]的计算机软件代码,无论是以人类可读形式还是机器可执行形式。\n \n2. 版权授予:在此协议的条款和条件下,贡献者特此向[项目名称]和[项目名称]分发的软件的接收者授予永久的,全球性的,非独占的,免费的,免版税的,不可撤销的版权许可,用于复制,准备衍生作品,公开展示,公开表演,再许可,和分发代码及其衍生作品。\n \n贡献者声明贡献者有法律权利授予上述许可。\n \n贡献者名称__________\n签名__________\n日期__________\n \n英文模板\nContributor License Agreement\n \nThis Contributor License Agreement ("Agreement") is agreed to by the party signing below ("Contributor"), and conveys certain license rights to [Project Name] for software projects managed by [Project Name]. This Agreement is effective as of the latest signature date below.\n \n1. Definitions:\n "Code" means the computer software code, whether in human-readable or machine-executable form, that is delivered by Contributor to [Project Name] under this Agreement.\n \n2. Copyright Grant: Subject to the terms and conditions of this Agreement, Contributor hereby grants to [Project Name] and to recipients of software distributed by [Project Name], a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Code and such derivative works.\n \nContributor represents that Contributor is legally entitled to grant the above license.\n \nContributor Name: __________\nSignature: __________\nDate: __________\n "},"Technology/SoftwareEngineering/协作规范/4.分支Branch":{"title":"分支Branch","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n分支类型命名规则备注主分支main开发分支develop功能分支除 master、main、develop、release-*、hotfix-* 以外的任何名字避免使用 master、main、develop、release-*、hotfix-*预发布分支release-*名称中的 * 表示版本号或其他标识热修复分支hotfix-*名称中的 * 表示版本号或其他标识\n为了防止产生歧义我们建议避免使用简拼命名。\n主要分支\n中央仓库中存在两个生命期无限长的主要分支\n\nMain主分支\nDevelop开发分支\n\n主分支 origin/main 的 HEAD 指向的源码总是处于可发布的状态。另一方面,开发分支 origin/develop 的 HEAD 指向的源码应包含为下次版本发布准备的最近的一次提交。\n当 develop 分支上的代码达到一个稳定点,并且准备进行发版时,所有在该分支上的修改都应该合并回 main 分支并且打一个版本号标签tag。\n辅助分支\n为了协助平行开发简化功能追踪协助产品发布和快速修复线上版本的 bug我们采用了功能分支、预发布分支和热修复分支。\n\nFeature branches (功能分支)\nRelease branches (预发布分支)\nHotfix branches (热修复分支)\n\n功能分支\n功能分支是从 develop 创建,必须合并回 develop。这些分支主要存在于开发者的本地仓库不在远程仓库 origin 中。\n预发布分支\n预发布分支从 develop 创建,必须合并回 develop 和 main。这些分支用于准备新版本的发布包括进行小的 bug 修复和准备发布数据。发布后,预发布分支可以删除。\n热修复分支\n热修复分支从 main 创建,必须合并回 develop 和 main。这些分支用于修复线上版本的严重 bug。修复完成后热修复分支可以删除。如果当前存在预发布分支热修复分支应该合并到预发布分支而不是开发分支。"},"Technology/SoftwareEngineering/协作规范/5.日志Commit":{"title":"日志Commit","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"对于项目,日志内容应使用 ASCII 字符、中文或 emoji以实现最大化的兼容性方便进行兼容处理。\ncommit 包含三个部分Header、Body、Footer。\n<type>([scope]): <subject>\n \n[body]\n \n[footer]\n示例\nfeature(auth): increase length of new API key\n \nthe length is increased from 24 to 32 for new API keys\n \nclose #12\n头部Header\n头部只有一行包含三个字段类型、范围和主题。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n全拼简拼描述featurefeat新增特性fixfix修复 bugdocumentsdocs文档变动stylestyle代码格式不影响功能例如空格、分号等格式修正refactorrefactor代码重构performanceperf改善性能testtest测试buildbuild影响构建系统或外部依赖的更改例如gulp、npm、webpackcontinuous integrationci更改了 CI 配置文件和脚本chorechore对构建过程或辅助工具和库的更改不影响源文件、测试用例revertrevert撤销上一次的 commit\n\n对于破坏兼容性的更改即会影响到依赖本项目的其他系统的更改请在类型后面加上半角感叹号「!」。\n主题务必不超过 72 个字符,且必须简洁明了。如果无法限制在 72 个字符内,请拆分提交。\n主题部分应以小写字母开头专有名词首字母大写缩略语大写并且结尾不用句号。\n\n主体Body\n主题与正文之间应有一个空行。\n如果内容简单可以按照主题格式撰写。如果超过一行应按照常规的段落格式。\n首字母应大写正确使用标点。可以有多行或多段但每行不超过 72 个字符,行尾不出现空格,段落之间应用空行隔开。\nfeature!(api): limit array length to 256 elements\n \nBREAKING: Array length limit is added to further limit request size. A\nsmall number of existing apps may receive HTTP 413 "Payload too Large"\nerror.\n脚注Footer\n正文与脚注之间应有一个空行。\n脚注主要用于记录不兼容的更改和关闭问题的操作。对于不兼容的更改需要在脚注中进行描述同时还需要在主体部分进行详细描述。如果关闭的问题是在追踪系统如 GitHub中的问题需要在脚注中使用 Close #issue 格式进行描述。"},"Technology/SoftwareEngineering/协作规范/6.版本Tag":{"title":"版本Tag","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"\n首发版本以 0.1.0 开始,版本格式:主版本号.次版本号.修订号,递增规则如下:\n\n主版本号当你做了不兼容的 API 修改,\n次版本号当你做了向下兼容的功能性新增\n修订号当你做了向下兼容的问题修正。\n\n参考 语义化版本 2.0.0。"},"Technology/SoftwareEngineering/协作规范/7.注释Comments":{"title":"注释Comments","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"代码应视为最好的注释,因此应尽量使用英文注释,并坚决避免滥用注释。不必在代码中标明作者、时间、或改动记录,这些信息应放在 Git 的提交日志中!\n行注释\n行注释应放在相应代码行之前而不是代码行之后。\n// 注释文字\n代码\n示例\n// 启用便携式支持\nconst portable = bootstrapNode.configurePortable(product);\n关键字注释\n在注释块的尾部关键字前添加 @ 符号。\n/* \n * 注释\n * @type{变量} 注释\n * @param{变量} 注释\n * @returns{变量} 注释\n */\n示例\n/*\n * @param {string} dir\n * @returns {Promise<string>}\n */\nfunction mkdirp(dir) {\n return new Promise((resolve, reject) => {\n fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? reject(err) : resolve(dir));\n });\n}\n版权注释\n版权注释应位于代码文件首行。\n/*----------------\n * 版权归 XX 所有\n * 遵循 XX 开源协议\n *----------------*/\n \n代码···\n上下分割线的长度应为描述文字长度的 1.1 倍。/* */ 不应与注释内容放在同一行,且描述文字前应保持 1 个空格。\n示例\n/*---------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *---------------------------------------------------------------------------------------*/\n \nconst perf = require('./vs/base/common/performance');\nperf.mark('code/didStartMain');"},"Technology/SoftwareEngineering/协作规范/8.交流反馈Issue":{"title":"交流反馈Issue","links":[],"tags":["软件工程/Git协作","技术/软件工程"],"content":"文件命名ISSUE.md。\n新需求Pull Request\n规范使用 Pr<scope>:title 来命名。<scope> 表示需求涉及的模块或功能title 则表示具体需求的主题。\n示例Pr(auth):role-based authorization\n提交新需求时请遵循以下格式\n规范Pr<scope>:title\n示例Pr(auth):role-based authorization\n## 背景\n \n- 描述你希望解决的问题\n- 如果相关的 issue 或社区帖子已存在,请附上链接\n \n## 思路\n \n描述解决思路可以包含 API 设计和伪代码等。\n \n## 实现\n \n附上对应的 Pull Request 地址。如果还未实现,可以描述你打算如何实现此需求。\n \n反馈缺陷Bug\n在提交 Bug 前,请务必先阅读提问的智慧!\n规范使用 Bug<scope>:title 来命名。<scope> 表示 Bug 涉及的模块或功能title 则表示 Bug 的主要问题。\n示例Bug(login):Admin password cannot be reset\n提交 Bug 反馈时,请遵循以下格式:\n## 运行环境\n \n- 系统Linux、Mac、Windows\n- 环境(运行版本、配套软件版本)\n \n## 该问题是怎么引起的?\n \n- 简述可能引起的原因和操作步骤\n \n## 重现步骤\n \n- 陈述可以复现 Bug 的详细步骤\n \n## 报错信息\n \n- 附上具体的报错信息、日志等。如果可能,截图也会非常有用。\n \n答疑交流Usage\n一般来说我们更推荐使用社区自助交流方式。\n规范使用 Usage<scope>:title 来命名。<scope> 表示问题涉及的模块或功能title 则表示问题的主要内容。\n示例Usage(update):1.2.3 version update failed\n提交问题或请求帮助时请遵循以下格式\n## 运行环境\n \n- 系统Linux、Mac、Windows\n- 环境(运行版本、配套软件版本)\n \n## 报错信息\n \n- 提供详细的报错信息、日志等。截图,如果可能,也是非常有用的。\n "},"Technology/SoftwareEngineering/文档规范/1.简介":{"title":"简介","links":["Tech/software-engineering/技术文档/1.简介","Tech/software-engineering/技术文档/2.标点符号","Tech/software-engineering/技术文档/3.命名约定","Tech/software-engineering/技术文档/4.语言风格","Tech/software-engineering/技术文档/5.文档内容","Tech/software-engineering/技术文档/6.文档结构","Tech/software-engineering/技术文档/7.附录资料"],"tags":["技术/软件工程","软件工程/文档规范"],"content":"引言\n本指南规范了一种中文写作风格主要用于技术文档的编写。素材来源于互联网为各家中文文案风格指南的综合旨在对中文技术文档的语言风格、结构样式、内容元素、标点符号、格式排版等方面给出参考规范。我希望本指南的出现能为日后业界标准的建立贡献一点力量。\n目的\n\n提高中文文案的可读性。\n统一文档风格保证组织对外输出形象一致。\n避免不同的文档作者对同一问题反复作出决策降低与文档相关的沟通成本。\n\n适用范围\n\n为编写中文文档的作者如产品研发人员、技术写作人员等提供规范或建议。\n审校文档过程中争议问题的裁决。\n也可供软件界面、帮助文档等资料开发人员参考。\n\n目录大纲\n简介\n\n技术文档的重要性\n技术文档的类型\n\n标点符号\n\n标点符号的基本规则\n常见的错误用法\n\n命名约定\n\n命名约定的重要性\n常见的命名规则\n\n语言风格\n\n语言风格的定义\n一致性和简洁性的重要性\n\n文档内容\n\n文档内容的构成\n如何编写高质量的文档内容\n\n文档结构\n\n文档的基本结构\n不同类型文档的结构差异\n\n附录资料\n\n附录的定义\n附录的使用场景\n\n使用原则\n本指南是一本查询手册建议初次阅读本指南时先大致浏览目录章节结构了解本指南涵盖的内容范围之后就编写文档时碰到的实际问题再回头查找相应规范。\n修订和审查\n\n定期修订定期修订文档以保持其准确性和时效性。\n多人审查邀请其他人审查文档他们可能会发现你可能忽视的错误或者遗漏。\n\n本指南主要针对中文技术文档的编写给出了一系列的规范和建议包括语言风格、结构样式、内容元素、标点符号、格式排版等方面。我希望本指南能帮助你提高中文文档的编写质量提高其可读性同时也能减少与文档相关的沟通成本。"},"Technology/SoftwareEngineering/文档规范/2.标点符号":{"title":"标点符号","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"常用中文标点符号\n句号「。」\n句号用于标示一句话的结束。在 Markdown 中,句号的使用和平常无异。\n\n这是一个句子。\n\n逗号「」\n逗号用于在句子中创建停顿分隔句子的不同部分。\n\n我需要苹果香蕉和橙子。\n\n顿号「、」\n顿号用于列举或枚举同类事物。\n\n我需要苹果、香蕉、和橙子。\n\n分号「」\n分号用于连接两个相关的句子。\n\n我喜欢苹果我也喜欢香蕉。\n\n冒号「」\n冒号用于引出说明或解释或引出直接引语。\n\n注这是一句解释性的话。\n\n引号「“ ”,‘ ’」\n引号用于引用别人的言论。\n\n他说“我喜欢你。”\n\n括号「」\n括号用于添加解释注释或者附加的信息。\n\n我喜欢吃水果如苹果香蕉橙子。\n\n书名号「《》」\n书名号用于标注书籍报纸电影等作品的标题。\n\n我最近在读《哈利·波特》。\n\n连接号「-」\n连接号用于连接两个有直接关联的词语。\n\n中美 - 贸易\n\n破折号「——」\n破折号表示转折解释或者暂停。\n\n我喜欢吃水果——尤其是苹果。\n\n省略号「……」\n省略号表示语句的不连续。\n\n等待……\n\n感叹号「」\n感叹号用于标识感叹或者强烈的情绪。\n\n太好了\n\n斜杠「/」\n在 Markdown 中,斜杠被用作转义字符,表示接下来的字符应被解析为文字,而非 Markdown 语法。\n\n我* 喜欢* 你。\n输出为我喜欢你。\n\n反斜杠「\\」\n在 Markdown 中,反斜杠主要用作转义字符。\n\n\\\\ 在 Markdown 中会输出一个斜杠:\\。\n\n反引号「`」\n在 Markdown 中,反引号用于创建 inline 代码块。\n\n`print(Hello, World!)` 在 Markdown 中会输出一个 inline 代码块print('Hello, World!')。\n\n中文标点使用\n使用中文标点符号时推荐遵循以下规则。\n\n\n在中文语境下标点符号应使用全角形式即中文输入法下的标点符号不能使用半角形式即英文输入法下的标点符号。\n\n\n中文全角标点符号两侧不应该有半角空格。\n\n\n\n如果 CPU 设有限额□(从 K8S 指定的上限)□,则需要手动调整。❌\n如果 CPU 设有限额(从 K8S 指定的上限),则需要手动调整。\n\n\n句号、问号、叹号、逗号、顿号、分号、冒号、结束引号、结束括号等标点不应出现在一行的开头。\n\n\n排版时注意某些\n符号不能在行首\n别弄错了。❌\n排版时注意某些\n符号不能在行首\n别弄错了。\n\n\n开始引号、开始括号、开始双书名号等标点不应出现在一行的末尾。\n\n\n她对我们说“\n这书太赞了。”❌\nCopy code 她对我们说:\n“这书太赞了。”\n\n中英文混用时的标点符号用法\n在中文技术文档中可能会出现英文此时可能会使用全角形式的中文标点和半角形式的英文标点。在中英文混用时需特别注意标点符号的使用。\n这部分介绍在中英文交接处使用标点符号的规则。\n根本原则\n中文技术文档主要针对中文文本应以中文标点符号为主英文标点符号为辅。\n基本规范\n\n在中文句子中使用英文单词或词组时\n\n使用的英文单词或词组不需要用中文引号包围。\n如果使用的英文单词或词组本身有英文标点保留其英文标点。\n中文句子的末尾应使用中文标点符号。\n\n\n在中文句子中使用英文句子时\n\n应用中文引号包围英文句子。\n如果英文句子本身有英文标点保留其英文标点。\n中文句子的末尾应使用中文标点符号。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n标点符号中文句子内夹用英文单词或词组时中文句子内夹用英文句子时句号change 和 transform 意义不同。I like you.我喜欢你。逗号这个数据库的官方描述是“open-source, distributed SQL database”。他们的官方文档上写着“Try it out, and you will get a 10% discount.”。问号distributed SQL 在这里是什么意思他伸出手说“Need a hand?”这句话的含义是“你需要帮助吗叹号不要总是对女孩说“Pretty!”他站在那感叹了句“What a beautiful scene!”。顿号be 动词包括 is、are、were、was 等。“He is man.”、“He is a man.”和“He is the man。”三者的含义有何区别分号如果想表示更礼貌的语气用 might反之用 may。官方文档上说“To deploy the database, use the TiUP tool; to migrate data, use the DM tool.”。冒号官网有个首页按钮失效了Newsletter。文档站的右上角写着Try it now。引号将来时态通常由“will + 动词原形”组成。这篇文章里有句话比较难理解“The saint said, Follow your fear.”。破折号这个符号表示禁止——stop。“Well—emm, I dont know how to say—but I hope you can understand my position.”他纠结地说。省略号使用 so…that… 句型表示结果意思是“如此……以至于……”。“I dont know how to say this…”的含义是“我不知道该怎么说了……”。\n中英文括号的使用\n\n括号里全为英文时建议使用半角括号并在括号前后各空一个半角空格括号和括号内的英文之间不需要空格。\n\n\n数据定义语言DDL是一种……使用了全角括号❌\n数据定义语言 (DDL) 是一种……(半角括号前后未空格)❌\n数据定义语言□(□DDL□)□是一种……(半角括号和半角括号内的英文之间空了一格)❌\n正确示例数据定义语言□(DDL)□是一种……\n\n\n括号里既有中文又有英文即只要括号内包含任何中文时建议使用全角括号括号前后不空格。\n\n\n斜杠 (slash 或 forward slash) 和反斜杠 (backslash) 是两种符号。❌\n斜杠slash 或 forward slash和反斜杠 (backslash) 是两种符号。\n\n英文书籍、报刊、标题的引用方法\n\n\n中文句子中夹用英文书籍或报刊名时不能使用中文书名号《》而应使用斜体字表示如果无法使用斜体字建议使用中文引号包裹引用。\n\n\n英文文章的标题用中文引号包裹引用。\n\n\n\nNew York Times 发布了一篇新文章标题是“Cloud is Eating the World”。\n"},"Technology/SoftwareEngineering/文档规范/3.命名约定":{"title":"命名约定","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"文件命名\n在以 Markdown 语言编写的技术文档中,源文件的命名应遵循以下规范:\n\n文件名应简明地概述文档内容。\n文件名长度应适中避免过长。\n当文件名由多个英文单词组成时用短划线「-」连接。\n在文件名中避免使用下划线「_」它在 URL 中可能影响搜索引擎优化,并可能被某些 Markdown 实现当作修饰字符。\n多个单词组成的文件名全小写或全大写均可但避免大小写混用如 faq.md 或 FAQ.md。\n文件扩展名应为小写。\nMarkdown 文件应使用「.md」后缀虽然「.markdown」也可以接受但应保证整体文件风格的统一。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n文件名内容描述introduction-to-python.md此文件可能包含有关 Python 语言的基础知识database-connection-guide.md这是一个指南说明如何连接到数据库faq.md这是一个常见问题解答文件README.md这是一个项目介绍文件\n产品命名\n企业为其产品或工具命名时应确保遵循一致的风格和规范以避免可能的法律风险如重名问题和品牌形象受损。推荐组织设立统一的产品命名流程并维护一个组织内部产品名称列表。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n英文产品名称中文产品名称Microsoft Office微软办公软件Photoshop阿多比 Photoshop\n名称使用\n在中文技术文档中应遵守以下专用名称使用规范\n国外组织、品牌或产品名称使用规范\n\n当中文读者熟知其中文官方译名时使用中文官方译名。\n当中文读者不熟悉、但有中文官方译名时使用「中文官方译名 (英文官方名称)」格式。\n对于没有中文官方译名的名称直接用英文指称务必保持正确的大小写形式。\n\n注意判断是否「中文读者熟知」具有主观性如有疑虑建议优先使用「中文官方译名 (英文官方名称)」格式。在首次提到该名称时,使用完整格式,之后的提及可只使用中文官方译名。\n组织、品牌或产品名称列表\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n中文读者熟知中文官方译名中文读者不熟悉、但有中文官方译名无中文官方译名微软 (Microsoft)威睿 (VMware)GitHub苹果 (Apple)塔多思 (Trados)SDL甲骨文 (Oracle)雪佛龙 (Chevron)MySQL沃尔玛 (Walmart)埃克森美孚 (Exxon Mobil)Alphabet亚马逊 (Amazon)大众 (Volkswagen)MongoDB惠普 (HP)戴姆勒 (Daimler)Azure宝马 (BMW)西门子 (Siemens)Jira波音 (Boeing)软银 (SoftBank)Slack雀巢 (Nestle)东芝 (Toshiba)Docker宝洁 (Procter & Gamble)思科 (Cisco)Kubernetes强生 (Johnson & Johnson)瑞声 (Resound)Ansible索尼 (Sony)罗克韦尔 (Rockwell Automation)GitLab百事 (Pepsi)三洋 (Sanyo)TensorFlow可口可乐 (Coca-Cola)格雷普 (Crepe)Elasticsearch高盛 (Goldman Sachs)微步 (Microstep)PyTorch佳能 (Canon)三菱 (Mitsubishi)Apache Kafka推特 (Twitter)亚都 (Audu)Redis脸书 (Facebook)逸碧 (Epyc)Apache Spark领英 (LinkedIn)萨博 (Saab)Terraform"},"Technology/SoftwareEngineering/文档规范/4.语言风格":{"title":"语言风格","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"在技术文档的写作中,风格和语气的掌握是至关重要的。下面是一些关于技术文档写作的基本准则。\n对话式语气\n技术文档的语言风格应该采用平易近人、直截了当的语气比如使用「你可以…」这样的表达方式避免过于正式或冗长的句子。\n\n请使用下面的按钮来完成操作。❌\n你可以使用下面的按钮来完成操作。\n\n客观礼貌的语气\n技术文档的语气应客观并保持礼貌不进行产品推销主要目的是传达技术信息。应该使用友好而有礼貌的措辞避免强硬或粗鲁的语气。在指导性文档中尽量保持语气冷静、客观且简洁。\n\n你一定要按照这样做否则会失败。❌\n按照以下步骤操作可以成功完成。\n\n简洁清晰地表达\n简洁明了是技术文档的重要原则。建议作者在完成初稿后通读整篇文档删去没有明显作用的字、词、句将文档长度缩短但同时确保信息传递效果不受影响。避免使用冗长的句子和逻辑混乱的段落尽量使用主动语态明确阐述主语和宾语。\n\n如果在配置过程中出现问题那么需要查看日志文件然后分析日志文件中的错误信息最后采取适当的措施来解决问题。❌\n配置过程中出现问题时查看日志文件分析错误信息并采取适当措施解决问题。\n\n通俗易懂的语词\n**使用通俗易懂的词语是技术文档的基本要求。**避免使用行话、俚语或网络流行语,或故意使用谐音错别字。应使用标准的技术术语,避免过度使用缩略语或专业术语,尽量用简单明了的表达方式。\n\n这个软件有魔改功能能让你的计算机跑得飞快❌\n这个软件有优化功能可以提升计算机的运行速度。\n\n以用户为导向\n**技术文档应以用户为导向,从用户的角度思考问题,提供有用的信息。**在撰写文档时,考虑文档的目标读者可能的技术水平和实际操作中可能遇到的问题,尽可能全面且清晰地解释技术信息,并提供更多的详细信息和解决方案。建议进行文档可用性测试,让无技术背景的测试人员参照文档进行操作,以确保文档的易用性。\n\n在设置菜单中选择适当的选项以进行配置。❌\n在设置菜单中选择相关选项以便进行配置。\n\n用词恰当和统一\n**在技术文档中,使用正确和一致的词汇非常重要。**你应避免使用可能引发冲突的词汇,并在同一篇或同一系列的技术文档中,保持一致的用词,避免造成混淆或阅读困难。\n\n我们强烈推荐使用最新版本的软件。❌\n建议使用最新版本的软件。\n\n正确使用“的”、“地”、“得”\n\n调度系统会将数据迁移到其他的存储节点上。形容词名词\n数据库可以显式地使用事务。副词动词\n这个值不宜调得过大。动词副词\n\n明确代词指代\n你应确保代词的指代对象明确避免造成读者的困惑。\n\n如果希望从本地已编译好的二进制文件构建 PD、TiKV 或 TiDB 的镜像,需要将其 image 字段留空。❌\n如果希望从本地已编译好的二进制文件构建 PD、TiKV 或 TiDB 的镜像,需要将相应镜像的 image 字段留空。\n"},"Technology/SoftwareEngineering/文档规范/5.文档内容":{"title":"文档内容","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"空白符号\n空白符号包括空格、空行等其中空格分为半角空格和全角空格。\n空格\n\n使用半角空格不使用全角空格英文字符和阿拉伯数字用半角空格包围\n\n\n这是一段□□□文本。❌\n这是一段文本。\n这是一段文本包含中文、English□words□和□12345。\n\n\n\n除缩进、列表级别、代码块和 Markdown 表格外,禁止连续使用半角空格。\n\n\n禁止使用 Tab 替换空格。\n\n\n空行\n\n不同段落间用一个空行隔开不同排版格式之间如标题和正文正文和代码块正文和表格等也使用一个空行隔开。\n\n# 这是一个标题\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n这是第一段。\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n这是第二段。\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n\n禁止连续出现两个及以上的空行。\n\n这是一段文本。\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n这是另一段错误的文本。❌\n其他\n\n\n行宽在 80、120 字符中自由选择,原则上不超过 160 字符宽。\n\n\n推荐使用空格进行缩进或对齐禁止使用 Tab 键。\n\n\n- 列表项1\n - 子列表项1\n - 子列表项2\n- 列表项2\n列表\n\n使用纵向列表表示多项信息。\n\n以下是我们需要考虑的事项\n- 项目预算\n- 团队规模\n- 项目时间线\n- 预期成果\n\n列表项的顺序重要时使用有序列表。\n\n请按照以下步骤进行操作\n1. 打开电脑。\n2. 打开浏览器。\n3. 输入网址。\n\n并列列表项中使用相似的句子结构并保持标点符号一致。\n\n我们的团队成员包括\n- 李雷,负责产品设计。\n- 韩梅梅,负责项目管理。\n- Jim负责软件开发。\n\n使用清晰的、描述性的句子或短语来引出表。\n\n以下是我们团队的主要职责\n- 设计和开发新产品。\n- 维护现有产品。\n- 提供客户支持。\n\n使用有序列表描述操作任务的步骤。\n\n使用该软件的步骤如下\n1. 下载并安装软件。\n2. 运行软件并点击 "新建项目"。\n3. 输入项目详情并保存。\n4. 开始使用软件进行项目管理。\n\n嵌套使用列表最多不超过 3 级。\n\n本产品主要包括以下部分\n- 外壳\n - 上盖\n - 下盖\n- 内部组件\n - CPU\n - 内存\n - 硬盘\n表格\n\n所有内容保持左对齐内容尽量简练避免长篇大段的说明不出现空白的单元格单元格内容避免重复。\n\n| 表头1 | 表头2 | 表头3 |\n|:-------|:-------|:-------|\n| 内容1 | 内容2 | 内容3 |\n| 内容4 | 内容5 | 内容6 |\n\n表格需要有表头描述同一文档中相同类型表格的表头描述需要保持一致。\n\n| 姓名 | 年龄 | 职业 |\n|:-------|:-----|:-----|\n| 张三 | 25 | 程序员 |\n| 李四 | 30 | 设计师 |\n\n每个表格下都要空一行空行的样式为正文。\n\n| 姓名 | 年龄 | 职业 |\n|:-------|:-----|:-----|\n| 张三 | 25 | 程序员 |\n| 李四 | 30 | 设计师 |\n□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n这是正文部分\n图形和图片\n\n必须使用清晰可辨的图形图片。\n中文文档里图形图片上的文字建议都用中文如果原图文字是其他语言应该先做好图片本地化工作。\n文字建议使用免费开源可商用字体以免引入法律风险。同一文档内图形图片上的中文应该统一字体如思源黑体英文和数字也要统一字体如 Times New Roman。\n图形图片中避免出现大段文字描述性语言建议放到图外用编号替代。\n图形图片中包含缩略语时需要在图说明中对缩略语进行解释。\n图说明和图尽量保证在同一页中显示。\n图片的命名建议使用描述性的文字。\n插入图片时建议添加替代文本从而改进文档的可访问性。\n\n![描述图片内容](/path/to/image.jpg "图片标题,可选填")\n \n- **说明**图1. 这是一幅示例图片。其中的文字全部使用了中文并且字体统一为思源黑体。对于图中的缩略语我们在这里进行解释XYZ代表的是...\n代码块和代码注释\n\n如果代码块语言被支持那么应该明确声明语言类型。\n\n ```python\n # 这是一个 Python 示例\n print("Hello, World!")\n ```\n\n代码块中出现的长命令应当按逻辑进行换行并且注明需要换行的地方。\n\n ```bash\n # 在这个长命令中,我们使用 \\ 来进行换行\n command --option1 --option2 \\\n --option3 --option4 --option5\n ```\n\n代码块中的命令如需参数替换应该清晰标注。\n\n ```bash\n # 在这个命令中,<username> 需要被你的用户名替换\n ssh <username>@example.com\n ```\n\n代码块中不应当出现警告或者错误信息除非它们是文章需要表达的内容。\n\n ```python\n # 这个 Python 示例没有任何错误或警告\n def greet(name):\n print(f"Hello, {name}!")\n greet("World")\n ```\n\n代码注释需要使用英文并且注释要简洁明了且必须准确。\n\n ```python\n # Correct and concise comment: Print greeting\n print("Hello, World!") \n ```\n\n如果代码块中的注释和文章内容重复那么优先使用代码块中的注释同时去掉文章中的内容。\n\n ```python\n # This comment explains the following code block\n print("Hello, World!") # This line prints a greeting\n ```\n链接和引用\n\n链接和引用必须给出精确的位置信息。例如如果你正在引用一个具体的 GitHub 代码行:\n\n看一下 [这个具体的代码行](github.com/user/repository/blob/master/file.py#L42) 来理解如何实现这个功能。\n\n如果链接和引用的位置有更新必须及时更新链接。\n\n由于最新的更新参考 [新的代码实现](github.com/user/repository/blob/master/new_file.py#L50)。\n\n链接和引用中出现的代码必须使用代码块包围。\n\n参考以下代码实现\n \n ```python\n def greet(name):\n ```\n\n必须标注链接的类型如文章、工具、命令等。\n\n阅读这篇 [文章](example.com/article) 来更深入地了解这个主题。\n使用这个 [工具](example.com/tool) 来帮助你的开发工作。\n运行以下 [命令](example.com/command) 来配置你的环境。\n\n每个文件的引用必须声明来源使用全称不要使用相对路径或者绝对路径。\n\n引用自 [Python官方文档](docs.python.org/3/tutorial/index.html),不是 `../tutorial/index.html` 或者 `/home/user/docs/tutorial/index.html`。\n\n不能使用会失效的链接。\n\n请使用 [永久链接](example.com/permanent-link),而不是 [会失效的链接](example.com/temporary-link)。\n\n链接的文字应描述其链接的内容而不应为「这里」、「此处」等模糊词汇。\n\n阅读 [Python教程](docs.python.org/3/tutorial/index.html),而不是点击 [这里](docs.python.org/3/tutorial/index.html)。\n缩略语\n在编写中文技术文档时我们常会用到两类缩略语汉语缩略语和英语缩略语。\n汉语缩略语\n汉语缩略语是通过缩短和省略较长的中文词语来形成的新词。例如「人大」是「人民大会堂」的缩略而「重启」则是「重启动」的缩略。\n**使用汉语缩略语时,我们要确保这些词在上下文中的含义清晰、准确,以避免产生歧义。**如果某个汉语缩略语并非大众常用或容易理解,我们在初次使用时应提供全称和相应的解释。例如,如果我们在文档中使用「绑核」作为「核心绑定」的缩略,我们需要在初次使用时指出:「本文将使用 绑核 作为 核心绑定 的缩略」。\n英语缩略语\n相较于汉语缩略语英语缩略语种类繁多数量众多。一般来说它们分为三类首字母缩略词、字母词和缩写词。\n\n\n首字母缩略词这类缩略词是由每个单词的首字母组合而成且作为一个单词发音。如「NATO」North Atlantic Treaty Organization我们读作 /neɪtoʊ/,而非逐字母发音。\n\n\n字母词与首字母缩略词类似也是由每个词的首字母组成但是按字母逐一发音。例如「FBI」Federal Bureau of Investigation我们会读作 /efbi:aɪ/,而非作为一个单词发音。\n\n\n缩写词直接将较长的词语进行缩短形成新词。例如「App」是「Application」的缩写词「demo」则是「demonstration」的缩写词。我们读作 /æp/,而非逐字母发音。\n\n\n在使用英语缩略语时我们需要注意以下几点\n\n\n在标题中避免对英文缩略语进行解释以免使标题过长影响阅读。\n\n\n在正文中首次出现的英文缩略语需要提供其完整形式和对应的解释。例如如果我们首次使用「AI」我们需要指出「AIArtificial Intelligence人工智能」。\n\n\n当使用缩略语代指某词时必须在该词首次出现时告知读者下文将以缩略语的形式称呼该词。\n\n\n不要使用非标准的或可能引起混淆的缩略语例如「16c32g」不能用来表示「16 核、32GB」「10w」也不能用来表示「10 万」。\n\n\n数字\n在中文语境中数字有两种形式第一种是汉字数字如「二」、「十」等第二种是阿拉伯数字如「2」、「10」等。\n汉字数字\n汉字数字主要用于表示概数、干支纪年、含有汉字数字的词语以及突出庄重典雅的效果。\n\n概数表达数字连用表示概数时不用顿号隔开。例如 三四十。\n年份简写年份简写后的数字不应简写为两位数字。例如 二〇二三 而不是 二三。\n月日的专名含有月日的专名中使用间隔号「·」将数字分开并在前后加引号避免歧义。例如 "六·二六"。\n法律文书和财务票据大写汉字数字用于法律文书和财务票据。例如 肆仟贰佰叁拾肆元整。\n计量和编号「零」用于计量」用于编号。例如 十零个苹果, 编号〇一〇二。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n适用场景示例数字连用表示的概数、含「几」的概数等三四个月、一二十个、十五六岁、五六万套、五六十年前、几千、二十几、一百几十、几十万分之一干支纪年、农历月日、历史朝代纪年及其他传统上采用汉字形式的非公历纪年腊月二十三、正月初五、八月十五中秋、秦文公四十四年、太平天国庚申十年九月二十三号、日本庆应三年、丙寅年十月十五日汉语中长期使用且已稳定下来的包含汉字数字形式的词语星期五、四氧化三铁、一方面、不二法门、二八年华、二百五、八国联军、五四运动、万一、一旦、四书五经、七上八下、不管三七二十一、半斤八两、「一·二八」事变、「一·二九」运动希望突出庄重典雅的表达效果时六方会谈不写为「6 方会谈」、十一届全国人大一次会议不写为「11 届全国人大 1 次会议」)\n阿拉伯数字\n阿拉伯数字主要用于计量、编号、现代社会生活中的事物和现象以及突出简洁醒目的效果。\n\n\n形式书写使用半角形式书写避免使用全角形式。例如 2023 而不是 2023。\n\n\n分节符使用半角逗号作为分节符。例如 1,000,000 而不是 1000000。\n\n\n表达范围表示数值范围时使用浪纹式连接号「」或一字线连接号「—」。例如 1020 或 10—20。\n\n\n日期和时间年月日和时分秒的表达顺序按照口语中的自然顺序。例如 2023年6月26日 或 15:30:00。\n\n\n月日的专名含有月日的专名中使用间隔号「·」将数字分开并在前后加引号避免歧义。例如 "6·26"。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n适用场景示例用于计量即用于加、减、乘、除等数学运算的数字如正负整数、小数、百分比、比例、分数等。-126、34.05%、63%67%、1:500、87/90当数值伴随有计量单位如长度、容积、面积、体积、质量、温度、经纬度、音量、频率等特别是当计量单位以字母表达时524.5 km524.5 千米、53 MB53 兆字节、12 h12 小时)用于编号的数字- 电话号码98888 - 邮政编码100083 - 电子邮件地址xxx@163.com - 网页地址http://127.0.0.1 - 章节编号4.1.2 - 产品型号PH-3000 型计算机 - 产品序列号C84XB-JYVFD-P7HC4-6XKRJ-7M6XH - 汽车号牌:京 A00001 - 公交车号: 302 路公交车 - 道路编号101 国道 - 公文编号:国办发 [1987]9 号 - 图书编号ISBN 978-7-80184-224-4 - 刊物编号CN11-1389 - 单位注册号02050214 - 行政许可登记编号0684D10004-828现代社会生活中出现的事物、现象、事件其名称的书写形式中包含阿拉伯数字已经广泛使用而稳定下来4G 手机、MP4 播放器、维生素 B12、「5·27」事件希望突出简洁醒目的表达效果时北京时间 2020 年 10 月 1 日 12 点整\n单位符号\n\n\n汉字名称建议用汉字名称代替单位符号。例如 三米 而不是 3m。\n\n\n间隔空格数值和单位之间通常需要空一个半角空格但有例外情况。例如 3□kg。\n\n\n角度、摄氏度和百分号角度、摄氏度和百分号的单位与数值之间不空格。例如 45°、 20°C 或 50%。\n\n\n英尺符号和英寸符号英尺符号和英寸符号与数值之间不空格。例如 6'2"。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n单位形式示例汉字名称三米间隔空格3□kg角度、摄氏度和百分号45°、20°C、50%英尺符号和英寸符号62”\n拼写\n中文技术文档既包含中文内容也可能包含英文内容。因此我们必须避免以下几种拼写错误。\n\n禁止简体中文和繁体中文的混用。\n\n\n这款软件的颜色设计很独特它的界面顏色是由用户自己选择的。❌\n正确示例这款软件的颜色设计很独特它的界面颜色是由用户自己选择的。\n\n\n禁止出现中英文错别字。错别字包括错字和别字。\n\n\n这款软件使用 MySOL 数据库存储数据。❌\n这款软件使用 MySQL 数据库存储数据。\n\n英文的大小写形式\n\n英文大小写形式不能写错。\n\n\n用户可以在 mysql 数据库中创建新的表。❌\n用户可以在 MySQL 数据库中创建新的表。\n\n\n当中文句子中夹有英文单词或词组时无论该英文单词或词组位于中文句子的开头、中间还是末尾普通单词、词组必须小写专有名词等在英文中必须大写的单词或词组保留其大写形式。\n\n\n在 SQL 语句中,你可以使用 “SELECT” 语句获取数据。❌\n在 SQL 语句中,你可以使用 “select” 语句获取数据。\n\n\n当中文句子中夹有完整的英文句子时无论该英文句子位于中文句子的开头、中间还是末尾其首字母均保留大写形式。\n\n\n如需更多信息请参阅 “in this chapter, we will learn how to create tables.”❌\n如需更多信息请参阅 “In this chapter, we will learn how to create tables.”\n\n语法\n成分残缺\n在编写技术文档时务必确保语句的成分完整。每个句子都应该有一个明确的主语和谓语以及必要的宾语和定语。\n\n会话保持在应用程序没有提供会话保持的功能下HAProxy 可以提供该项功能。❌\n会话保持在应用程序没有提供会话保持功能的情况下HAProxy 可以提供该项功能。\n\n搭配不当\n确保你的句子中使用的词汇是搭配恰当的。不正确的词汇搭配可能会让读者混淆影响他们对你的文档的理解。\n\nHAProxy 是由 Linux 内核的核心贡献者 Willy Tarreau 于 2000 年编写,并仍然负责该项目的维护,该在开源社区提供免费和版本迭代。❌\nHAProxy 是由 Linux 内核的核心贡献者 Willy Tarreau 于 2000 年编写,他现在仍然负责该项目的维护,并在开源社区免费提供版本迭代。\n\n倍数表达\n技术文档中表达倍数建议遵循以下规范。\n\n数值的增加必须明确使用「增加了」或「增加到」不能只使用「增加」。「了」表增量「到」表定量。\n数值的减少必须明确使用「降低了」或「降低到」不能只使用「降低」。「了」表增量「到」表定量。\n不能用「降低 N 倍」或「减少 N 倍」的表示法,要用「降低百分之几」或「减少百分之几」。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n表述方式示例校验增加了处理速度增加了两倍。✔只用增加处理速度增加两倍。❌增加到处理速度增加到两倍。✔只用增加处理速度增加两倍。❌降低了处理速度降低了五十百分点。✔降低 N 倍处理速度降低两倍。❌\n成分多余\n避免在句子中使用不必要的词汇或短语这可能会使句子变得冗长和复杂影响其清晰度和可读性。\n\n根据官方建议目前稳定版本的 HAProxy 为稳定版 2.0 特性。❌\n官方目前建议使用 HAProxy 稳定版本 2.0。\n\n句式杂糅\n避免在一个句子中混合使用多种句式。尽量保持句子简洁明了如果需要表达的信息较多可以考虑分解为多个句子。\n\n当部署多个 DM-master 节点时,所有 DM-master 节点将使用内部嵌入的 etcd 组成集群并用于存储集群节点信息、任务配置等元数据,同时通过 etcd 选举出 leader 节点用于提供集群管理、数据迁移任务管理相关的各类服务。因此,若 DM-master 可用节点数超过部署节点的半数,即可正常提供服务。❌\n当部署多个 DM-master 节点时,所有 DM-master 节点将使用内部嵌入的 etcd 组成集群。该 DM-master 集群用于存储集群节点信息、任务配置等元数据,同时通过 etcd 选举出 leader 节点。该 leader 节点用于提供集群管理、数据迁移任务管理相关的各类服务。因此,若可用的 DM-master 节点数超过部署节点的半数,即可正常提供服务。\n"},"Technology/SoftwareEngineering/文档规范/6.文档结构":{"title":"文档结构","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"标题\n文档结构是技术文档的重要组成部分一个良好的文档结构能有效帮助读者理解和掌握文档的逻辑和主题。以下是一些关于文档结构的关键要点。\n层级\n在技术文档中我们通常使用的**标题层级最多不超过三级。**标题应该按照层级递增,禁止跳级使用。为了保持文档的整洁和一致,除非有特殊需要,否则不建议使用四级标题,可以选择使用列表代替四级标题。\n# 文章主标题\n## 主要章节的标题\n### 子章节的标题\n#### 四级标题使用列表代替\n描述\n标题的描述应简洁明确可以采用名词词组、主题词 + 动词、动词 + 主题词、定语 + 主题词、介词 + 定语 + 主题词等形式。它们应能概括反映本章节的中心内容。为了保持标题的一致性,同级别的标题应尽量使用相同的结构。\n\n名词词组 例如「数据结构」、「网络安全」等。\n主题词 + 动词: 这种形式更加动态,例如「电池充电」、「程序执行」等。\n动词 + 主题词: 这种形式可以清晰地指示一个操作或行动,例如「安装软件」、「编写代码」等。\n定语 + 主题词: 这种形式可以给出更多的描述性信息,例如「高效的算法」、「重要的更新」等。\n介词 + 定语 + 主题词: 这种形式更加详细,例如「对数据结构的理解」、「在网络安全中的防御」等。\n\n注意事项\n\n**避免重复:**例如,如果一级标题是「数据结构」,那么二级标题应避免再次使用「数据结构」,而应该是更具体的主题,如「数组」、「链表」等。\n避免使用标点 例如,不应该写成「数据结构:数组。」,而应该是「数据结构:数组」。\n避免解释缩略语 例如不应该写成「APIApplication Programming Interface而应该在正文中解释这个缩略语。\n添加引导性句子 例如,在标题「数据结构」和「数组」之间,可以添加一句话:「接下来,我们将详细讨论数据结构中的一种重要类型——数组。」\n避免孤立编号的标题 正文不要有孤立的三级和四级标题,每个标题都应该在上一级标题的基础上展开。例如,如果一个部分只有一个三级标题,那么它应该被升级为二级标题。\n项目列表作为最小编号单位 不应在项目列表中嵌套任何级别的标题。例如,列表中的每一项都应该是一个完整的思想或概念,而不是一个需要进一步分解的主题。\n\n段落\n段落是正文部分的基本构成单元由多个句子组成。**每个段落应只有一个主题或中心句子,并且中心句子建议放在段落的开头,对全段内容进行概述。段落长度建议在 50~250 字之间,避免超过 300 字。**为提高可读性,段落之间应设置适当的间距。同时,技术描述类主题应考虑先图表、后句子的原则,避免仅依赖段落陈述。\n另外**句子应避免过长,建议不超过 100 字。**使用简单句和并列句,避免复杂的复合句,可以适当地断句,防止句子过长。\n示例\n1. 数据结构简介\n \n数据结构是计算机科学中的一个核心概念中心句子。它是数据值、数据之间的关系、以及对数据进行操作的函数的组织和存储方式。数据结构可以直接或间接地影响程序的效率。在计算机编程中选择最合适的数据结构对于编写高效的代码至关重要此段落的长度约为50字。\n \n2. 数组和链表\n \n数组和链表是两种常见的数据结构中心句子。如图1所示数组是一种线性数据结构它包含一个或多个元素每个元素都有一个与之相关联的索引。与此不同链表由一系列节点组成每个节点包含一个值和一个指向下一个节点的指针此段落的长度约为60字图表在句子之前便于读者理解。\n数据结构是计算机科学中的一个核心概念。简单句\n \n数据结构可以直接或间接地影响程序的效率因此在编程中选择最合适的数据结构至关重要。并列句不超过100字\n \n数组是一种线性数据结构包含一个或多个元素每个元素都有一个与之相关联的索引链表则由一系列节点组成每个节点包含一个值和一个指向下一个节点的指针。并列句分句处理避免过长\n目录\n文档目录是帮助读者快速浏览和定位章节的重要工具。通过各级标题我们可以自动生成文档目录。例如技术手册必须提供总目录包含所有章节和附录。在网页端发布的技术手册通常会有全手册导航栏和页内导航栏相当于总目录和单篇文档目录。这需要根据使用的文档框架自定义文档的标题层级以确保导航栏能正确显示。\n"},"Technology/SoftwareEngineering/文档规范/7.附录资料":{"title":"附录资料","links":[],"tags":["技术/软件工程","软件工程/文档规范"],"content":"针对编写的一系列技术文档,应提供相应的术语表和缩略语表作为附录资料,方便读者查阅。\n同时根据技术文档发布平台的不同应在阅读文档的醒目处提示读者有关文档的侵权说明、商标说明等信息。\n参考资料\nGoogle Developer Documentation Style Guide\nPingCAP Markdown 编码规范\nMicrosoft Docs 参与者指南概述\n产品手册中文写作规范\n中文技术文档的写作规范\n豌豆荚文案风格指南\nLeanCloud 文案风格指南\nLengoo 简体中文规范指南\n知乎专栏 - 写给大家看的中文排版指南\nMarkdown 书写风格指南\n中文文案排版指北\nRequirements for Chinese Text Layout 中文排版需求\n余光中怎样改进英式中文- 论中文的常态与变态\n正确使用 Tab 和空格:\n\n缩进与对齐——正确地使用Tab和空格\n使用tab, 还是空格, 小小编程习惯却有巨大的差别\n写代码时缩进使用tab 还是空格? - 知乎\n\n数字\n\n《出版物上数字用法》GB/T 15835—2011\n《出版物上数字用法的规定》GB/T 15835—1995\n\n标点符号\n\n《标点符号用法》GB/T 15834—2011\n《夹用英文的中文文本的标点符号用法草案》\n易混标点符号一字线、短横线-)、浪纹线(~)\n\n列表\n\n写给初学者的 Markdown 教程\n英语技术文档中如何正确使用无序列表和有序列表\n使用无序列表的 7 项注意\n\n引号\n为什么在知乎上表引用时用直角引号「」而不是弯引号“”\n顿号\n\n8 例顿号误用解析 - 中国编辑校对网\n顿号标点符号- 百度百科\n\n语言文字\n《常见语言文字错误防范手册》. 周奇主编. 北京: 中国标准出版社, 2010."},"Technology/SoftwareEngineering/架构设计/REST":{"title":"REST","links":[],"tags":["技术/软件工程","软件工程/架构设计"],"content":"HTTP 协议\nHTTPHyperText Transfer Protocol是互联网应用中最基础的通信协议之一主要用于在客户端通常是浏览器和服务器之间传输超文本。 随着互联网的发展HTTP 协议经历了多个版本的演变,每次升级都引入了更高效、更安全的特性,特别是对现代 Web 和 API 开发有着重要的影响。\nHTTP 的发展历史\nHTTP 协议自从 1990 年代初被发明以来,已经经历了多个版本的升级,目的是为了应对不断增长的 Web 流量需求,提升数据传输效率和安全性。\n\nHTTP/0.9: 这是最早期的 HTTP 版本,仅支持 GET 请求和简单的 HTML 文档传输完全没有状态码、Headers 的概念。它只能请求单一资源,没有元数据传递。\nHTTP/1.0: 引入了多种请求方法(如 POST 和 HEAD、状态码如 404、Headers 机制(如 Content-Type支持传输更多数据类型。这是第一代较为成熟的 HTTP 协议。\nHTTP/1.1: 在 1997 年发布,成为 Web 应用的主流协议。该版本引入了持久连接Persistent Connections、管道化Pipelining减少了每次请求都需要重新建立连接的开销并且进一步扩展了 HTTP 方法、增加了缓存控制等重要特性。这一版本至今仍广泛使用。\nHTTP/2: 该版本于 2015 年发布,旨在大幅提升 Web 性能。HTTP/2 通过多路复用Multiplexing支持在同一个 TCP 连接上并发多个请求,减少了延迟,还引入了 Header 压缩、服务器推送Server Push等优化。\nHTTP/3: 基于 QUIC 协议UDP 的一种扩展HTTP/3 主要解决了 HTTP/2 中的队头阻塞问题,提供了更快、更可靠的数据传输,尤其适用于移动设备和高延迟网络环境。\n\n版本对 API 设计的影响: 随着 HTTP 版本的升级API 开发者在设计时必须考虑到版本的特性。例如HTTP/2 允许并行处理多个请求,因此在 RESTful API 设计中可以优化性能减少请求数量。此外HTTP/2 和 HTTP/3 的 Header 压缩也能提高传输效率。\n请求/响应模型详解\nHTTP 是基于请求 - 响应模型的,这意味着每当客户端需要访问资源时,都会向服务器发送请求,并接收到服务器的响应。这种通信模式是无状态的,即每个请求都独立进行,服务器不会记住之前的请求。\n请求的组成部分\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n请求组成部分描述请求行包含 HTTP 方法(如 GET、POST、目标资源的 URI 和协议版本定义了请求的类型和目标资源。Headers提供关于请求的元信息如内容类型、用户代理、认证信息等帮助服务器处理请求。Body包含请求发送的实际数据通常用于 POST、PUT 等方法,可包含 JSON、XML、表单数据等格式。方法Method指定请求的操作类型常见方法包括 GET获取资源、POST创建资源、PUT更新资源、DELETE删除资源。Query ParametersURL 中可选的参数用于筛选或过滤请求的数据。Cookies客户端存储的信息用于会话管理随请求自动发送至服务器。Path VariablesURL 路径中的动态参数,标识特定资源或操作。\n响应的组成部分\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n响应组成部分描述状态行包含协议版本、状态码及其文本描述指示服务器对请求的处理结果。Headers提供响应的元信息如内容类型、内容长度、缓存控制等帮助客户端理解和处理响应。Body响应体包含实际返回的数据格式可能为 JSON、HTML、XML 等取决于请求类型和响应内容。状态码三位数代码表明请求结果主要分为成功2xx、客户端错误4xx、服务器错误5xx等。协议版本指定 HTTP 协议的版本,如 HTTP/1.1 或 HTTP/2决定了通信方式的特性和性能。Cookies服务器通过响应设置客户端的 Cookies用于会话管理或跟踪用户状态。缓存控制通过响应头控制客户端或代理服务器的缓存策略优化性能减少重复请求。重定向通过 3xx 状态码和 Location 头实现,将客户端引导至新的资源 URI。\nHTTP 方法的语义与应用场景GET、POST、PUT、PATCH、DELETE 等)\n每个 HTTP 方法都具有特定的语义,并且适用于不同的操作场景。在设计 RESTful API 时,选择合适的 HTTP 方法可以确保语义的清晰性,并减少不必要的复杂性。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述应用场景GET获取资源不会修改服务器上的数据。数据检索、读取操作如获取用户列表或单个用户信息。POST创建资源在服务器上生成新数据。创建新资源如提交表单、创建新用户或订单。PUT更新资源完全替换目标资源。更新完整的资源如更新用户的所有信息。PATCH部分更新资源修改资源的部分属性。局部更新资源如修改用户的部分信息如电子邮件地址。DELETE删除资源从服务器上移除指定资源。删除操作如删除用户或订单。HEAD与 GET 类似但不返回响应体仅返回响应头。用于检查资源是否存在或获取元数据信息。OPTIONS返回目标资源支持的 HTTP 方法。检查服务器支持的请求方法,常用于跨域请求预检。\n在设计 RESTful API 时,务必为资源的不同操作选择最合适的 HTTP 方法,确保 API 具有良好的语义一致性。错误使用方法(如用 GET 修改资源)会导致不易维护和安全性问题。\nHTTP 状态码的分类与标准化使用2xx、3xx、4xx、5xx\nHTTP 状态码用于表示服务器对客户端请求的处理结果。状态码被分为五个主要类别,每个类别的状态码都有特定的含义和应用场景:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n状态码描述应用场景200 OK请求成功服务器返回请求的数据。数据获取成功如返回用户信息或资源列表。201 Created请求成功服务器创建了新的资源。资源创建成功如新用户或新订单创建成功。204 No Content请求成功但无返回内容。更新或删除操作成功但无需返回数据如删除用户操作。301 Moved Permanently请求的资源已被永久移动到新的 URI。用于永久重定向到新地址如页面永久搬迁。302 Found请求的资源临时移动到新的 URI客户端应使用新的 URI 进行访问。临时重定向例如用户登录后重定向到首页。304 Not Modified资源未被修改客户端可以使用缓存的版本。用于缓存验证减少重复数据传输。307 Temporary Redirect请求资源临时重定向到新的 URI但应继续使用原请求方法。临时重定向且要求客户端保持请求方法不变如 POST 仍保持为 POST。400 Bad Request请求无效服务器无法处理。请求格式错误或缺少必需参数。401 Unauthorized请求未授权缺少或错误的身份验证凭据。用户未登录或提供了无效的 Token。403 Forbidden请求被拒绝用户没有权限访问资源。用户尝试访问未授权的资源或功能。404 Not Found请求的资源不存在。请求的 URL 无效或资源已删除。405 Method Not Allowed请求方法不被允许。使用了不支持的 HTTP 方法如对资源使用错误的请求方式。500 Internal Server Error服务器内部错误无法处理请求。服务器发生意外错误或无法完成请求。503 Service Unavailable服务器当前无法处理请求可能暂时过载或维护。服务器过载或正在维护客户端需要稍后再试。\n**在设计 API 时,务必使用合适的状态码来准确反映请求的处理结果。**例如,避免使用 200 OK 返回错误信息,应使用 4xx 或 5xx 类状态码以便客户端能正确处理异常情况。\nHTTP Headers 的使用(如 Content-Type、Authorization、Accept 等)\nHTTP Headers 是 HTTP 请求和响应的重要组成部分,它们用于传递有关资源的元数据以及控制请求和响应的行为。以下是一些常见的 Headers 及其在 API 设计中的作用:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHeader描述应用场景Content-Type指定请求或响应体的媒体类型如 application/json、text/html。用于指定数据格式如传递 JSON 数据时使用 application/json。Authorization用于传递认证信息如 Bearer Token 或 Basic Auth。用户认证和授权场景如 API 调用时传递 JWT。Accept指定客户端可接受的媒体类型如 application/json、text/html。客户端希望接收到的响应格式如请求 JSON 数据时使用 application/json。User-Agent指定发起请求的客户端信息浏览器、设备、操作系统等。用于服务器识别客户端类型如识别是桌面端还是移动端。Cache-Control控制缓存行为常见值包括 no-cache不使用缓存、max-age缓存有效时间。优化缓存策略减少不必要的请求提升性能。Cookie客户端发送给服务器的 Cookie用于维持会话状态。用户会话管理传递用户登录状态或偏好设置。Set-Cookie服务器返回给客户端的 Cookie用于存储会话信息。用于创建或更新客户端的 Cookie如登录后设置用户会话 Cookie。Content-Length指定请求或响应体的字节长度。服务器在响应中告知客户端数据长度便于优化传输。Host指定请求的目标主机及端口号。用于虚拟主机场景帮助服务器确定请求的目标网站。Accept-Encoding指定客户端可接受的内容编码格式如 gzip、deflate。用于压缩响应数据减少带宽占用。Content-Encoding指定响应的编码方式如 gzip、deflate。服务器在响应中使用压缩编码提高传输效率。Referer指定请求来源的页面 URL通常用于追踪链接点击来源。用于分析用户从何处访问当前页面支持流量追踪和安全控制。Location指定重定向的目标 URL。当使用 3xx 状态码时告知客户端资源的重定向地址。Connection控制连接行为如 keep-alive 保持长连接或 close 关闭连接。控制 HTTP 连接的生命周期优化连接性能或资源释放。Accept-Language指定客户端可接受的语言列表如 en-US、zh-CN。用于内容本地化服务器根据此信息返回合适语言的内容。If-Modified-Since告知服务器自某个时间点以来资源是否被修改过。客户端缓存验证减少重复下载未修改的资源提升效率。\n在 API 设计中,合理使用 HTTP Headers 不仅能够优化性能(如缓存控制),还可以提升安全性(如使用 Authorization Header 进行身份验证),同时帮助客户端与服务器之间的通信更为高效。\nCookies、Session 与 Token 的区别与应用\n在 Web 应用中,状态管理是一个重要的环节,尤其是当 HTTP 协议本身是无状态的情况下。为了在多个请求之间保持用户的身份和会话,常用的技术包括 Cookies、Session 和 Token。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度CookiesSessionToken如 JWT存储位置存储在客户端浏览器中并在每次请求时自动发送给服务器。存储在服务器端客户端只保存 Session ID通常通过 Cookie。存储在客户端通常通过 Authorization 头部或 Cookie 发送。数据存储可存储少量数据如会话标识符、用户偏好等。会话数据存储在服务器端客户端仅传递会话标识符。Token 本身携带用户身份信息,可自包含认证信息。安全性易受 XSS、CSRF 攻击,如果不加密或设置不当,可能泄露敏感数据。会话标识符通常通过 Cookies 传递避免敏感数据直接暴露但可能被劫持。JWT 可以通过签名防止篡改,但易受 XSS 攻击,且无法主动失效。服务器开销几乎无服务器开销,所有数据存储在客户端。会话数据存储在服务器,服务器需要维护大量会话,导致高并发时内存开销较大。无服务器存储开销,服务器不需要保存 Token 状态,适合分布式架构。扩展性易于实现,适合简单的 Web 应用。扩展性有限服务器需要保存每个用户的会话信息增加负担。高扩展性Token 可以跨服务器节点使用,适合分布式和无状态系统。状态管理方式通过在客户端存储会话标识符来维持状态。通过服务器保存会话数据,客户端通过会话 ID 与服务器会话关联。无状态管理Token 本身携带用户身份信息,服务器不保存状态。使用场景适用于存储简单信息,如用户偏好、会话标识符等。适合传统的 Web 应用和小规模的用户会话管理。适用于现代 Web 应用和 API 认证尤其是分布式系统中的无状态认证。有效期控制可以设置过期时间但一旦生成客户端完全控制其生命周期。服务器可以主动失效会话但需要持续维护会话状态。Token 有有效期,通过 exp 设置,但过期后客户端必须重新登录。认证方式通常用于存储会话标识符,不能直接实现认证。基于服务器端会话存储,通过 Session ID 识别用户。自包含认证Token 本身包含用户身份信息,服务器通过验证 Token 认证。管理与维护客户端管理,较易实现,但不易追踪与主动失效。服务器管理,较为安全,但增加服务器开销。客户端自管理,服务器不存储状态,适合大规模分布式系统。\n在设计 API 时,通常推荐使用 Token尤其是 JWT因为它不依赖服务器会话并且可以轻松扩展至多个服务器节点。 Cookies 和 Session 更适合于传统的 Web 应用,但在现代的 RESTful API 中Token 逐渐成为主流。\nREST\nRESTRepresentational State Transfer是一种架构风格它通过一系列原则和约束定义了如何在 Web 环境中高效、简单地进行分布式系统通信。 REST 的核心思想是通过 Web 的资源和 HTTP 协议实现系统间的通信,使得 Web 服务具有高度的可扩展性和可维护性。理解 REST 架构风格的背景、六大约束以及与其他架构的对比,是设计优秀的 RESTful API 的基础。\nREST 的起源\nREST 这一架构风格最早由 Roy Fielding 在 2000 年的博士论文中提出。 Fielding 是 HTTP 协议的共同设计者之一,他在设计和发展 HTTP 的过程中,总结出了一系列的架构约束,旨在提高 Web 系统的可扩展性、性能和简单性。\nREST 的背景可以追溯到 1990 年代,当时互联网正迅速发展,传统的分布式计算模型(如 CORBA、RPC 等)在 Web 环境下表现得不够灵活。因此Fielding 提出了 REST作为一种通过统一接口来简化客户端和服务器之间交互的架构风格。\nREST 强调的是利用现有的 Web 标准(如 HTTP 协议、URL、MIME 类型等来设计系统使得客户端和服务器能够通过统一的、标准化的接口进行通信。REST 的设计理念在于构建面向资源的架构,通过操作资源状态的转移实现功能。\nREST 设计理念的核心\n\n资源导向一切对象都可以看作资源且通过 URI 进行唯一标识。\n状态转移客户端通过 HTTP 方法(如 GET、POST、PUT、DELETE与资源交互资源的状态在请求中被转移。\n表现层独立客户端不需要知道服务器的实现细节而是通过资源的表现层进行交互。\n\nREST 的六大约束\nFielding 在他的论文中提出了 REST 架构风格的六大核心约束,这些约束共同定义了 REST 系统的行为和特性。在设计 RESTful API 时,这些约束为开发者提供了清晰的指导。\n1. 客户端 - 服务器架构\n客户端和服务器角色在 REST 架构中是分离的。 客户端负责用户界面,服务器负责处理数据存储和逻辑。通过这种解耦,系统的开发和演进更加灵活。客户端和服务器可以独立开发、更新,而不需要彼此依赖。\n\n服务器只需要暴露数据接口而不必关心如何展示数据客户端只需要调用 API而不必关心底层数据如何存储和处理。\n这种分离使得前后端分离开发成为可能也是现代 Web 应用中非常普遍的实践。\n\n2. 无状态性\n每个客户端的请求都应当是独立的、无状态的。 服务器不应保存客户端的会话信息,每次请求都必须包含所有必要的信息来完成请求。这样做简化了服务器设计,提高了可扩展性。\n\n每次请求中都要携带认证信息如 Token以确保服务器能够识别并处理请求。\n无状态性使得扩展服务器集群变得容易因为请求的处理不依赖于任何特定的服务器。\n\n3. 统一接口\nREST 的一个重要特性是通过统一的接口与资源进行交互。 所有的资源都通过标准化的 URI 进行标识,客户端通过通用的 HTTP 方法(如 GET、POST、PUT、DELETE对资源进行操作。资源与其操作行为是独立的这种统一接口使得系统设计更为简洁、规范。\n\n统一接口保证了客户端和服务器之间的一致性客户端可以预测如何与资源进行交互。\n标准的 HTTP 方法与状态码约定了行为的语义性,简化了开发和文档的维护。\n\n4. 可缓存性\n为了提高性能服务器可以通过 HTTP Headers 控制资源的缓存行为。 客户端可以缓存静态资源,避免频繁请求同一资源,这在提升性能和降低服务器负载方面非常重要。\n\n通过适当的缓存策略如 Cache-Control、ETag可以显著提升 API 的响应速度和系统的可扩展性。\n缓存使得静态内容的重复传输最小化从而提高了资源利用率。\n\n5. 分层系统\nREST 允许通过多层架构的方式组织系统。 中间层可以用于负载均衡、缓存、安全、代理等功能,而客户端不需要知道这些中间层的存在。分层系统的好处是提高了系统的安全性和扩展性。\n\nAPI 的设计可以通过代理或网关等中间件进行处理,如认证、负载均衡、限流等操作。\n分层架构为系统提供了灵活性和可扩展性可以根据需要引入不同的服务层。\n\n6. 按需代码(可选)\nREST 的这一约束是可选的,指服务器可以临时向客户端传递代码(如 JavaScript使得客户端在本地执行某些功能。 这个约束在实际 API 设计中较少使用,但对于增强客户端功能是有帮助的。\n\n按需代码通常用于需要动态加载脚本的场景如在单页应用SPA中为客户端提供额外的功能。\n\nREST 与其他架构风格的对比SOAP、GraphQL、gRPC\nREST 并不是唯一的 Web 服务架构风格,其他常见的架构包括 SOAP、GraphQL 和 gRPC。每种架构都有其独特的优势和适用场景了解它们的异同对于选择合适的架构至关重要。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比维度RESTSOAPGraphQLgRPC架构风格基于资源的无状态架构基于 XML 的消息传递协议基于查询语言的灵活数据请求基于 HTTP/2 的高性能 RPC 框架协议HTTP/HTTPSHTTP/HTTPS、SMTP 等HTTP/HTTPSHTTP/2数据格式通常为 JSON也支持 XMLXMLJSONProtocol Buffers (二进制格式)使用场景Web 应用、移动应用、轻量级服务企业级应用、银行、支付系统、事务性应用复杂数据查询、前端优化、移动和 Web 应用微服务间通信、分布式系统、高性能低延迟通信消息传输通过 URI 定位资源,使用标准 HTTP 方法GET、POST、PUT、DELETE基于 XML 的消息体,严格标准化的协议单一端点,基于查询语言,客户端可自定义请求结构双向流式通信,支持一元和流式 RPC 请求性能轻量级,较高的性能较重,性能相对较低,开销较大数据传输灵活,性能良好,减少多余数据传输高效的二进制传输,性能和吞吐量非常高扩展性易扩展,轻量,适合快速开发和高并发扩展性较低,严格依赖规范,事务处理复杂高度扩展,适合复杂的数据模型和大规模查询高扩展性,特别适合微服务和分布式架构安全性依赖于传输层(如 HTTPS、OAuth 等支持 WS-Security具有内置的安全和事务性支持依赖 HTTPS 等传输层安全支持认证、加密,需自定义安全机制实时通信支持 WebSocket 等方式实现实时通信不支持内置实时通信机制支持实时更新,通过 Subscription 实现支持双向流式通信,天然支持实时数据传输优缺点- 简单易用,灵活性高,工具链成熟 - 无状态、易于缓存- 标准化程度高,安全性强,适合复杂业务场景 - 性能较低,复杂度高- 数据请求灵活,避免数据过量和不足 - 需要客户端精确控制查询逻辑- 高性能,支持流式通信 - 学习曲线较陡调试复杂典型应用Web 服务、移动 API、微服务银行、支付、企业内部复杂系统复杂前端应用如单页应用 SPA、优化数据请求微服务间通信、高性能系统、物联网、实时应用\nREST 是一种通用性强、实现简单的架构风格,适合大多数 Web 应用,尤其是资源导向的系统。如果系统对请求的复杂度要求不高、需要高扩展性、并且使用标准化 HTTP 协议,那么 REST 是最佳选择。\nRESTful API\n**RESTful API 是一种基于 RESTRepresentational State Transfer架构风格设计的 Web 服务接口。**RESTful API 的目的是通过标准的 Web 协议(通常是 HTTP以资源为中心的方式进行系统间的通信确保服务具备高可扩展性、简洁性和易维护性。其核心思想是利用 HTTP 的方法来操作 Web 上的资源,并通过统一的接口进行数据交互。\n基本定义\nRESTful API 是遵循 REST 架构风格设计的 API。 REST 架构的核心思想是把 Web 中的所有对象视为资源,通过 URI统一资源标识符来标识资源并使用标准的 HTTP 方法(如 GET、POST、PUT、DELETE来操作这些资源。RESTful API 的特性决定了它在 Web 服务中的广泛应用。\n基本特性\n\n资源导向在 REST 中,所有的实体(如用户、订单、商品)都被视为资源。每个资源通过唯一的 URI 进行标识,这使得资源的查找和操作变得直观。\n无状态性每个请求都是独立的服务器不会保存客户端的状态。这种无状态的设计减少了服务器的负担并使得系统更具扩展性。\n统一接口RESTful API 强调通过统一的接口来操作资源。HTTP 方法(如 GET、POST、PUT、DELETE为资源操作提供了明确的语义并且通过状态码返回操作结果。\n表现层独立客户端和服务器之间的通信通过资源的表现层如 JSON 或 XML进行传递客户端并不需要了解服务器端资源的内部实现。这种分离使得客户端和服务器可以独立演进。\n可缓存性通过 HTTP 的缓存机制,客户端可以缓存一些静态资源或不经常更新的数据,减少不必要的请求,提升系统性能。\n分层系统RESTful API 支持分层架构设计,系统可以引入负载均衡、代理服务器等中间层,客户端不需要知道服务器背后的架构细节。\n\nRESTful API 拥有诸多优势,首先在于其高灵活性,客户端可以通过标准的 HTTP 方法(如 GET、POST、PUT、DELETE灵活地选择操作方式执行各种操作。其次RESTful API 简洁明了,基于资源的 URI 和 HTTP 方法的组合提供了一种直观的交互方式降低了开发者理解和使用的复杂性。最后RESTful API 的无状态性和分层架构为其提供了强大的扩展性,特别适合应对高并发和大规模的分布式系统。\n资源与 URI 的设计\n**RESTful API 的核心是资源,资源是任何可以被存储或操作的数据实体,例如用户、订单或文件。**在 REST 中,资源通过 URI 进行唯一标识,因此设计一个合理的 URI 是构建良好 RESTful API 的关键。\nURI 设计的基本原则\n在设计 RESTful API 时,良好的 URI 设计不仅能提高可读性,还能使 API 更加直观、易于维护和扩展。以下是一些关键的 URI 设计原则及其示例。\n使用名词而非动词\nURI 应表示资源本身,而不是对资源的操作。具体的操作通过 HTTP 方法(如 GET、POST、PUT、DELETE来决定而不应该在 URI 中体现。\n# 错误示例\n/getUserInfo\n \n# 正确示例\n/users/{id}\n在这里/users/{id} 表示用户资源,通过 HTTP 方法来区分不同的操作。例如GET 表示获取用户信息PUT 表示更新用户信息。\n保持层次结构\n当资源之间有上下级关系时URI 应该体现这种层次关系。例如订单属于某个用户URI 可以设计为 /users/{id}/orders通过这种方式直观展示资源之间的依赖关系。\n/users/{id}/orders/{orderId}\n该示例表示用户 id 下的特定订单 orderId清晰表达了用户和订单之间的关联。\n使用复数表示资源集合\n当 URI 表示资源的集合时,应该使用复数形式。这样可以保证一致性,也能明确区分资源集合与单个资源。例如,/users 表示用户集合,/orders 表示订单集合。\n/users\n/orders\n避免使用过多的查询参数\nURI 应保持简洁明了,查询参数用于筛选、分页或排序,而不应该用于资源的主干定位。比如,查询参数适合处理分页和筛选需求,而不适合直接用来定位资源。\n/users?page=1&limit=10\n/orders?sort=date&status=shipped\n遵循标准的 HTTP 方法\nURI 仅用于标识资源,具体的操作应通过标准的 HTTP 方法实现。常见的 HTTP 方法及其在 URI 设计中的应用如下:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHTTP 方法URI操作描述GET/users/{id}获取用户信息获取指定 ID 的用户信息POST/users创建新用户创建一个新的用户PUT/users/{id}更新用户信息更新指定 ID 的用户信息DELETE/users/{id}删除用户删除指定 ID 的用户\n通过这些设计原则API 的 URI 能够更具可读性和一致性,使客户端能够更加方便、快速地理解和使用 API。这样的设计也有助于 API 的可维护性和扩展性,便于应对系统增长和新功能的添加。\n幂等性与安全性\n幂等性是 RESTful API 中的一个重要概念。 幂等性指的是无论客户端多次重复执行同样的操作,结果总是相同。换句话说,幂等操作不会因为多次执行而对系统产生不同的影响。\n安全性指请求是否只用于读取数据而不会修改服务器上的资源。 GET 是安全的,因为它不会对服务器数据产生副作用,而 DELETE、PUT、POST 会对数据进行更改,因此被认为是不安全的。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHTTP 方法幂等性安全性描述GET幂等安全用于读取资源多次请求返回相同的资源不会影响服务器的数据。DELETE幂等不安全用于删除资源无论执行多少次结果都是相同的即资源被删除或确认其不存在。PUT幂等不安全用于更新资源多次请求将资源更新到相同状态不会重复创建资源。POST非幂等不安全用于创建新资源多次请求可能创建多个相同的资源实例。\n如何保证 API 的幂等性与安全性?\n\n对于幂等操作应设计好 HTTP 方法,避免不必要的副作用。\n对于非幂等的 POST 操作,考虑使用客户端生成的唯一 ID 来避免重复创建资源。\n实现良好的错误处理机制确保在网络中断或错误重试时系统能够正确处理。\n\n资源表示\n在 RESTful API 中,资源的表示是指资源在被传递时的表现形式。不同的表现形式可以满足不同的需求,而在选择资源的表示格式时,常见的选项包括 JSON、XML 和 YAML。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比维度JSONXMLYAML数据结构复杂度适合简单到中等复杂的数据结构表现为键值对。支持复杂的嵌套结构和命名空间适合高度结构化的数据。适合简单和轻量级的数据依赖缩进表示层次关系。可读性可读性较好结构简洁开发者易于理解和使用。结构较为冗长可读性差尤其是在大规模数据时。可读性高格式简洁直观易于人工编辑和维护。数据体积较轻量数据体积小适合在带宽有限的环境下传输。数据较为冗长体积大传输效率低。体积较小适合用于配置和轻量级数据传输。解析难度与效率解析速度快几乎所有语言和框架都支持 JSON 解析库。解析速度相对较慢,且需要处理复杂的 XML 结构和命名空间。解析较简单但在处理大规模数据时易出错。注释支持不支持注释常用来传输纯数据。支持注释和元数据适合带有文档和描述信息的场景。支持注释适合用于配置文件和开发者文档。数据类型支持支持常见数据类型字符串、数值、数组、对象等但不支持二进制数据。支持丰富的数据类型包括二进制、复杂对象、命名空间。支持基础数据类型适合简单的配置和传输。常见应用场景Web 应用、移动应用、轻量级 API 传输。企业级系统、复杂数据交换、跨平台数据传输。配置文件、轻量级数据传输、开发文档和配置管理。兼容性与 JavaScript 原生兼容,适用于大多数现代开发环境。多语言、多平台支持,广泛用于企业应用和遗留系统。适合配置管理和轻量数据交换,现代开发中较少用于 API。扩展性可扩展性有限不适合非常复杂的场景。高度可扩展支持复杂的数据结构和验证机制。可扩展性较弱主要用于简单的数据结构和配置。\n\nJSON 作为默认选择:对于大多数 RESTful APIJSON 是首选的数据格式,尤其是在现代 Web 和移动应用中JSON 因其轻量和兼容性广泛使用。\nXML 在企业级系统中的应用如果系统需要支持复杂的数据结构或与遗留的企业系统进行交互XML 可能是更合适的选择。\nYAML 适用于配置和轻量级数据传输YAML 更适合配置文件,但较少用于数据交换格式。\n\n在设计 API 时,确保 API 支持多种格式(如 JSON 和 XML并通过 Content-Type 和 Accept 头来协商客户端和服务器之间的资源表示格式,可以提高 API 的兼容性和灵活性。\n资源建模\n资源建模是 RESTful API 设计的核心工作之一。在 REST 架构中,资源是 Web 上的基本实体每个资源都有独立的标识符URI客户端通过 HTTP 方法对这些资源进行操作。良好的资源建模有助于系统具备清晰的逻辑结构、易于理解和扩展的 API并减少客户端和服务器之间的耦合度。\n资源建模的基本概念\n**在 RESTful API 中,资源 是可以通过 URI 进行标识的实体。**它可以是任何可访问的对象,如用户、订单、产品、文件等。资源的本质是服务器存储的一段数据,资源建模的目标是以自然、直观的方式将这些数据结构化。\n资源建模的基本原则\n资源建模是设计 RESTful API 的核心步骤,它直接影响 API 的可读性、可扩展性和可维护性。以下是资源建模时应遵循的基本原则,帮助开发者构建稳定、高效的 API。\n明确资源的边界\n资源应该对应实际的业务对象而不是技术操作。例如用户 和 订单 是两个独立的业务概念,分别建模为独立的资源 /users 和 /orders。资源应该反映业务逻辑而非操作行为。\n/users/{id} # 表示单个用户\n/orders/{orderId} # 表示单个订单\n避免过度建模\n不应为每一个操作或功能都设计独立的资源应该保持资源的抽象级别合理。过度细化的资源设计会增加系统复杂性导致 API 维护困难。确保每个资源都足够通用,能够反映业务的核心数据。\n/createUser # 不推荐使用动词操作\n/updateOrderStatus # 不推荐将操作作为资源\n资源是稳定的\n资源建模应基于稳定的数据结构。资源的设计应尽量减少变动即使业务需求发生变化也不应轻易更改资源的定义。这有助于保证 API 的长期稳定性和向后兼容性。\n/products # 产品资源不应频繁改变,结构稳定\n/categories # 类别资源保持一致\n资源的演进\n通过 API 版本控制来应对不可避免的变化,而不是直接修改现有资源结构。可以通过 URI 或请求头进行版本管理,确保旧版本的客户端依然能够正常使用。\n/v1/products # 旧版本的产品资源\n/v2/products # 新版本的产品资源,带有扩展功能\n遵循 REST 的无状态性\n资源建模应遵循 REST 的无状态原则。每个请求必须包含足够的信息,使服务器可以独立处理该请求。不要让服务器依赖客户端的历史操作或状态信息。\nGET /orders/{orderId} # 请求包含必要的订单 ID无需额外上下文\n自包含请求\n每个请求都应自包含所有必需的数据例如身份认证信息、查询参数等。避免设计依赖于会话或前置请求的 API 调用。\nGET /orders?status=shipped # 查询所有已发货订单,无需依赖服务器保存状态\n如何识别资源\n资源建模的关键是识别业务实体并基于这些实体构建资源。在识别资源时可以遵循以下规则\n唯一标识\n资源应具备唯一标识。例如用户通过 /users/{id} 进行唯一标识,订单通过 /orders/{orderId} 唯一标识。通过这种方式,客户端和服务器之间可以清晰地定位并操作具体资源。\n/users/{id} # 用户资源id 唯一标识每个用户\n/orders/{orderId} # 订单资源orderId 唯一标识每个订单\n资源集合与单个资源\n不仅仅是单个对象资源集合也是资源。可以通过集合 URI 访问资源集合,例如 /users 表示所有用户的数据集合,而 /users/{id} 访问具体用户。\nGET /users # 获取所有用户\nGET /users/{id} # 获取单个用户\n\n复合资源\n当资源与另一个资源密切相关时可以通过嵌套 URI 表示层次结构。例如,订单属于用户,可以通过 /users/{id}/orders 访问该用户的所有订单。这样的层次结构能够清晰展示资源间的关系。\n/users/{id}/orders # 获取用户的所有订单\n/users/{id}/orders/{orderId} # 获取用户的具体订单\n\n资源层次结构及其设计\n资源层次结构是资源建模中的一个关键部分它帮助定义资源之间的关系并通过 URL 路径表达这种层次关系。层次结构清晰的资源模型能够使 API 更加直观、易于理解。\n资源之间的父子关系\n如果资源之间存在自然的父子关系可以将子资源嵌套在父资源的路径中。 例如,用户和订单是典型的父子关系,每个订单都属于某个特定用户。因此可以设计为 /users/{id}/orders表示该用户的订单列表或者 /users/{id}/orders/{orderId} 表示某个用户的具体订单。\n层次化的路径设计不仅直观而且可以清晰地表现资源间的关联性帮助客户端理解资源结构。\n避免过度嵌套\n虽然嵌套可以表达资源关系但过深的嵌套会导致 URI 冗长且不易使用。**一般情况下,嵌套层次不宜超过两层。**例如,/users/{id}/orders/{orderId}/items 可能过于复杂,通常可以简化为 /orders/{orderId}/items。\n对于更深层次的关系可以通过查询参数来替代过度嵌套。 例如,订单的某些明细可以通过 /orders/{orderId}?include=details 来实现,而不是通过路径嵌套。\n处理多对多的关系\n当资源之间存在多对多关系时应避免嵌套 URI。可以通过独立的资源或查询参数来表示。 例如,用户和产品之间存在购买关系,而不应通过嵌套 URI如 /users/{userId}/products/{productId})来表示,最好通过单独的资源来表示购买行为,如 /purchases/{purchaseId} 或通过查询参数来筛选资源 /products?buyer={userId}。\n层次结构设计的优势\n通过层次化设计资源之间的关系在 URL 中得到了清晰地表达,使得 API 更加语义化、直观化,同时也更容易维护。同时清晰的层次结构能够帮助前端开发者更好地理解资源之间的关系,减少文档查阅的时间。\nREST 中的 URL 设计策略\n在 RESTful API 中URL统一资源定位符用于唯一标识资源。设计一个良好的 URL 是确保 API 清晰易用的重要步骤。一个合理的 URL 设计可以让用户通过直观的路径轻松理解资源的位置和操作方式。\n简洁性与一致性\nURL 应保持简洁,避免使用复杂的结构和不必要的参数。简洁的 URL 不仅易于记忆和理解,也更符合 REST 的设计精神。\nURL 设计应保持一致。 例如,资源集合使用复数形式 /users而具体资源使用单数形式 /users/{id}。保持一致的命名规则有助于减少客户端的困惑。\n遵循 HTTP 方法的语义\nURL 只负责表示资源,不应包含操作信息。资源的操作应通过 HTTP 方法来决定。 例如,创建用户应通过 POST /users 而不是 /users/create删除用户应通过 DELETE /users/{id} 而不是 /deleteUser?id={id}。这样可以保持 URL 的纯粹性,使其只负责资源的标识,而不涉及操作。\n使用查询参数进行过滤和分页\n当需要对资源进行过滤、排序或分页时应使用查询参数。 例如,可以使用 /products?category=electronics 过滤出电子产品,或使用 /products?page=1&limit=10 进行分页。查询参数的使用使得 API 更加灵活,并避免通过路径过度嵌套带来的复杂性。\n避免使用文件扩展名\n现代 RESTful API 中通常避免在 URL 中使用文件扩展名(如 .json 或 .xml。客户端应通过 Accept 头来指定所期望的返回格式, 而不是通过扩展名。这可以使 URL 更加整洁和统一。\nURL 设计示例\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n操作描述HTTP 方法URL 示例说明获取用户列表GET/users返回所有用户的列表获取某个用户信息GET/users/{id}根据用户 ID 获取指定用户的信息创建新用户POST/users创建新的用户更新用户信息PUT/users/{id}更新指定 ID 用户的信息删除用户DELETE/users/{id}删除指定 ID 的用户获取用户订单列表GET/users/{id}/orders获取指定用户的所有订单获取某个订单详情GET/users/{id}/orders/{orderId}获取指定用户的某个订单详情创建新订单POST/users/{id}/orders为指定用户创建一个新的订单更新订单信息PUT/users/{id}/orders/{orderId}更新指定用户的某个订单信息删除订单DELETE/users/{id}/orders/{orderId}删除指定用户的某个订单获取所有产品列表GET/products获取所有产品的列表获取某个产品信息GET/products/{productId}获取指定产品的详细信息创建新产品POST/products创建新的产品更新产品信息PUT/products/{productId}更新指定产品的信息删除产品DELETE/products/{productId}删除指定产品获取订单的发货信息GET/orders/{orderId}/shipping获取指定订单的发货信息更新订单的发货信息PUT/orders/{orderId}/shipping更新指定订单的发货信息获取用户的购物车GET/users/{id}/cart获取指定用户的购物车信息将商品加入用户的购物车POST/users/{id}/cart/items将商品添加到指定用户的购物车从购物车中移除某个商品DELETE/users/{id}/cart/items/{itemId}从指定用户的购物车中移除某个商品获取购物车中的所有商品GET/users/{id}/cart/items获取指定用户购物车中的所有商品清空用户的购物车DELETE/users/{id}/cart清空指定用户的购物车检查用户的购物车状态GET/users/{id}/cart/status获取指定用户的购物车状态处理支付POST/users/{id}/orders/{orderId}/payment为指定订单进行支付操作\nRESTful API 的版本控制策略\n**随着 API 的演进,版本控制是不可避免的。**当业务需求不断变化时,为了避免对现有客户端造成破坏,需要对 API 进行版本管理。版本控制能够确保旧版本的客户端仍能正常使用,而新功能可以在新版本中得到实现。\n\nURI 版本控制:适合早期的 API 版本管理,路径清晰,适用于版本较少的系统。\n请求头版本控制在保持 URI 稳定的情况下支持复杂 API 版本管理,适合需要平滑升级的系统。\n参数版本控制适合小型 API 或简单场景版本控制通过参数完成URI 结构保持稳定。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比维度URI 版本控制请求头版本控制参数版本控制示例/v1/usersAccept: application/vnd.myapi.v1+json/users?version=1版本显示位置显示在 URI 路径中显示在 HTTP 请求头中作为查询参数显示在 URL 中URI 结构每个版本有独立的 URIURI 保持不变版本由请求头控制URI 保持不变,版本通过查询参数控制客户端操作客户端需修改 URI 来访问不同版本客户端需通过 Accept 头指定版本客户端需通过查询参数指定版本服务器处理服务器根据不同的 URI 处理不同版本服务器需解析 Accept 头确定版本服务器解析查询参数以确定版本请求清晰度版本清晰,显式显示在 URI 中版本隐藏在请求头中,较为隐式版本信息位于查询参数,清晰度中等扩展性新版本需要新的 URI旧版本可继续使用新版本可在不修改 URI 的情况下引入新版本通过查询参数引入,无需修改 URI向后兼容性保留旧 URI易于维护多版本可通过头信息管理多版本向后兼容性较强版本信息通过参数控制易维护向后兼容性API 文档维护文档需为不同版本分别编写文档需解释如何设置 Accept 头请求版本文档需解释如何在查询参数中指定版本适用场景适合简单场景和版本较少的系统适合复杂系统,需要平滑引入新版本适合小型 API 和简单系统\nHTTP 方法设计\n**在 RESTful API 中HTTP 方法是操作资源的关键工具。**每种方法具有特定的语义,并用于处理不同的操作(如创建、读取、更新、删除等)。选择合适的 HTTP 方法,可以确保 API 语义的清晰性和一致性,从而提升系统的易用性和可维护性。\n如何为资源操作选择合适的 HTTP 方法\nRESTful API 强调使用标准的 HTTP 方法来操作资源。 通过合理使用这些方法API 可以保持清晰的语义简化客户端的使用。HTTP 提供了多种方法,但在 RESTful API 中最常用的几种是GET、POST、PUT、PATCH 和 DELETE。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHTTP 方法操作类型安全性幂等性典型应用场景示例GET读取资源安全幂等获取资源列表、获取某个具体资源GET /users GET /users/{id}POST创建新资源不安全非幂等创建新用户、发送表单数据POST /users POST /formsPUT完全替换资源不安全幂等更新某个用户的所有信息、如果资源不存在可能创建新资源PUT /users/{id}PATCH部分更新资源不安全幂等更新资源的部分属性如修改用户的部分信息PATCH /users/{id}DELETE删除资源不安全幂等删除指定资源如删除某个用户DELETE /users/{id}\n选择合适方法的关键在于理解操作的语义对于读取操作使用 GET创建使用 POST完全更新使用 PUT部分更新使用 PATCH删除使用 DELETE。这不仅使得 API 符合 REST 的设计理念,还让客户端对 API 的行为有明确的预期。\nREST 设计中的 HTTP PATCH 实践\nPATCH 方法是 HTTP/1.1 引入的,用于对资源进行部分更新。 与 PUT 不同的是PATCH 不会替换整个资源,而是只更新请求中包含的部分字段。\nPATCH 的应用场景\n\n\n部分更新PATCH 非常适合资源的部分更新场景。例如,更新用户的某些字段时,使用 PATCH 可以仅发送要修改的字段,而不是将整个用户对象发送回服务器。例如:\nPATCH /users/{id}\n{\n "email": "newemail@example.com"\n}\n\n\n避免冗余数据传输由于 PATCH 只传递变化的数据,它比 PUT 更高效尤其当资源对象非常大时。例如如果用户的资料中包含大量数据但你只想更新其中的邮箱地址PATCH 允许你只发送与邮箱相关的字段,而 PUT 则需要传递整个用户对象。\n\n\n复杂更新逻辑PATCH 也可以用于需要复杂逻辑的更新,例如某些资源字段是依赖其他字段的变化,使用 PATCH 可以更加灵活地处理部分更新操作。\n\n\n如何正确实现 PATCH\n\n在服务端需要对 PATCH 请求进行部分更新的解析和处理。这意味着,服务器需要验证传入的数据并仅更新指定的字段。处理 PATCH 时,必须保证不对未包含在请求中的字段进行不必要的更改。\n幂等性尽管 PATCH 被设计为幂等操作,但其实现可能会因资源的设计复杂性而引入非幂等的行为。为确保 PATCH 的幂等性,服务端应在接收到相同的 PATCH 请求时多次执行不会产生不同的结果。\n\n通过合理使用 PATCH 方法RESTful API 可以在更新资源时减少数据传输量,提高性能,并增强灵活性。\n请求与响应设计\n在 RESTful API 中,请求和响应是客户端与服务器之间交互的基础。请求体和响应体的设计应当遵循一致性、简洁性和易读性的原则,以便提升开发效率和用户体验。此外,合理使用状态码与错误处理机制对于 API 的健壮性和可维护性至关重要。特别是在处理大数据集时,分页、排序和过滤策略的设计有助于优化性能。\nAPI 的请求体Request Body和响应体Response Body包含了客户端与服务器之间传递的主要数据。如何为这些数据选择合适的格式和设计结构直接影响 API 的易用性和可扩展性。\n请求体设计\n\n\n创建请求 (POST): 当客户端需要向服务器创建新资源时POST 请求体应当包含资源的完整数据。通常以 JSON 格式传递新资源的属性。例如,创建新用户:\n{\n "name": "John Doe",\n "email": "john.doe@example.com",\n "age": 30\n}\n\n\n更新请求 (PUT/PATCH): PUT 请求需要包含完整的资源数据(即便是更新部分字段),而 PATCH 请求则只需传递需要更新的部分字段。例如,更新用户电子邮件地址:\n{\n "email": "newemail@example.com"\n}\n\n\n响应体设计\n\n\n成功响应: 成功的响应通常包括资源的当前状态。以 JSON 格式为例,服务器返回用户的详细信息:\n{\n "id": 123,\n "name": "John Doe",\n "email": "john.doe@example.com",\n "age": 30\n}\n\n\n资源创建响应 (201 Created): 创建新资源的响应应返回新资源的 URI 和相关数据。服务器可以返回响应头 Location 来指示新资源的位置,响应体则包含资源的详细信息:\n{\n "id": 123,\n "name": "John Doe",\n "email": "john.doe@example.com"\n}\n\n\n状态码的合理使用与错误处理\n**HTTP 状态码是 RESTful API 的重要组成部分,它能够明确告知客户端操作的结果。**在 API 设计中,合理使用状态码有助于提升系统的可理解性和可维护性。\n常见状态码的合理使用\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n状态码描述2xx 成功状态码200 OK请求成功服务器返回请求的数据常用于 GET、PUT、PATCH 请求。201 Created资源已成功创建常用于 POST 请求,响应中应包含新资源的 URI。202 Accepted请求已被接受但尚未处理通常用于异步操作。204 No Content请求成功但没有返回任何内容常用于 DELETE 或 PUT 请求。3xx 重定向状态码301 Moved Permanently资源已被永久移动到新的 URI客户端应使用新的 URI 进行访问。302 Found临时重定向客户端应使用新的 URI但未来请求仍使用原 URI。304 Not Modified缓存未过期客户端可以继续使用缓存的资源无需重新获取。4xx 客户端错误状态码400 Bad Request客户端请求有误通常是请求格式错误或缺少必要的参数。401 Unauthorized请求未授权客户端需要提供认证信息。403 Forbidden服务器理解请求但拒绝执行通常是权限不足。404 Not Found请求的资源不存在服务器无法找到相应的资源。405 Method Not Allowed请求方法不允许对资源执行。409 Conflict请求冲突通常是资源状态与当前操作不一致。410 Gone请求的资源已永久删除不再可用。422 Unprocessable Entity请求格式正确但无法处理通常是验证错误。429 Too Many Requests客户端发送了过多的请求服务器限制请求频率。5xx 服务器错误状态码500 Internal Server Error服务器内部错误通常是代码问题或服务器故障。502 Bad Gateway服务器作为网关或代理从上游服务器收到无效响应。503 Service Unavailable服务器暂时无法处理请求可能正在维护或过载。504 Gateway Timeout服务器作为网关或代理未能及时从上游服务器获取响应。\n错误处理策略\n错误响应应当提供足够的错误描述信息帮助客户端开发者理解问题并进行修复。例如验证错误时返回字段错误信息\n{\n "error": "Validation Failed",\n "details": [\n {\n "field": "email",\n "message": "Email is invalid"\n }\n ]\n}\n设计统一的错误响应结构包括错误码、错误描述、调试信息等。这样可以确保不同类型的错误都能通过相同的方式处理。\n错误响应的标准化设计\n在 RESTful API 中,标准化的错误响应有助于简化客户端处理错误的逻辑,并帮助调试。良好的错误响应不仅包括错误码,还应提供有用的描述信息和建议的解决方案。\n错误响应的基本结构\n错误响应应该包含以下几个关键字段\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n字段名称描述错误码 (error_code)应用级别的唯一错误码用于标识具体的错误类型。例如4001 代表验证错误4031 代表权限错误。客户端可以根据该错误码采取对应的行动。错误消息 (message)简洁明了的错误描述帮助用户或开发者快速了解问题所在。例如“Invalid input” 或 “Unauthorized access”。详细信息 (details)对错误的详细描述,特别适用于复杂错误的调试。例如,表明哪个字段的验证失败、哪个参数缺失等,帮助开发者进行更深层次的错误分析。时间戳 (timestamp)记录错误发生的时间,通常以 ISO 8601 格式提供。例如2023-10-09T14:48:00Z。便于日志管理和问题追踪。请求 ID (request_id)可选字段,用于唯一标识该请求,方便在服务器日志中查找对应请求的相关信息。路径 (path)可选字段,记录发生错误的 API 路径,便于明确是在哪个端点出错。建议 (suggestion)可选字段,提供给客户端的一些可能的解决方案或进一步的操作建议。例如:“请检查输入数据格式” 或 “请联系管理员”。\n示例\n{\n "error_code": "4001",\n "message": "Invalid input",\n "details": "The 'email' field is required",\n "timestamp": "2024-10-09T14:48:00Z",\n "request_id": "abc123xyz",\n "path": "/users",\n "suggestion": "Please provide a valid email address"\n}\n这种一致性可以让开发者快速识别错误并处理避免不同错误类型返回不同结构的响应增加客户端处理的复杂度。\n分页、排序、过滤的设计策略\n当数据量较大时分页、排序和过滤机制是提高 API 性能和用户体验的必要手段。通过分页,客户端可以逐步加载数据,而不是一次性获取全部数据。排序和过滤功能可以帮助客户端更高效地找到所需的数据。\n分页设计\n\n\n常见分页模式 采用查询参数控制分页。通常的做法是通过 page 参数控制当前页数limit 参数控制每页的记录数。\n# 返回第 2 页,每页 20 条数据。\n/users?page=2&limit=20\n\n\n返回分页信息 响应中应返回分页的相关元数据,如总页数、当前页、总记录数等,帮助客户端知道下一步如何处理。\n{\n "data": [\n { "id": 1, "name": "John Doe" },\n { "id": 2, "name": "Jane Doe" }\n ],\n "pagination": {\n "current_page": 2,\n "total_pages": 5,\n "total_items": 100,\n "limit": 20\n }\n}\n\n\n排序设计\n排序通常通过 sort 参数实现。可以通过 asc 或 desc 指定升序或降序。例如:\n# 根据创建时间降序排序用户列表。\nGET /users?sort=created_at&order=desc\n过滤设计\n过滤通过查询参数实现。通常可以通过字段名作为查询参数来筛选数据。例如 GET /users?role=admin 返回角色为管理员的用户。\n复杂的过滤可以通过多个查询参数组合。例如 GET /users?role=admin&status=active 返回活跃状态的管理员用户。\nHATEOAS\nHATEOASHypermedia as the Engine of Application State是 REST 架构的核心特性之一,它确保客户端能够通过 API 提供的链接自发现和操作资源,从而实现 API 的自描述性。HATEOAS 提供了一种动态的方式,允许客户端通过导航链接了解当前资源状态,并执行后续操作。\nHATEOAS 的概念、原理与意义\nHATEOAS 是 REST 架构的约束之一,它指的是在 API 响应中嵌入超媒体Hypermedia链接使得客户端不仅能够获取资源的当前状态还能根据提供的链接执行进一步的操作。换句话说客户端不需要事先知道 API 的详细操作路径,而是通过 API 响应中的链接进行下一步操作。\nHATEOAS 的作用:\n\n可发现性通过超媒体链接客户端可以发现资源的所有可能操作而无需提前编写操作逻辑。客户端根据返回的链接执行后续操作。\n自描述性API 响应中嵌入的链接描述了客户端接下来可以做什么,使得 API 自带文档性质,减少了额外文档的需求。\n解耦性客户端不必依赖于服务器的具体实现而是依赖于超媒体指引。即使 API 版本更新或内部逻辑发生变化,只要链接保持一致,客户端仍然可以正常工作。\n\nHATEOAS 强化了 REST 的核心特性之一即通过统一接口来操作资源。它使得客户端能够灵活地与服务器交互尤其在资源复杂、操作链较长的场景中HATEOAS 通过链接引导客户端进行进一步操作,减少了客户端与服务器的耦合性。\n在没有 HATEOAS 的传统 API 设计中,客户端通常需要事先知道每个操作的具体路径和方法。而 HATEOAS 允许客户端根据响应中的超媒体链接动态决定接下来的请求,减少了对 API 事先了解的依赖。\n如何在 API 中实现 HATEOAS\n实现 HATEOAS 的核心思想是,在资源的响应中嵌入相关的超媒体链接。这些链接描述了资源的当前状态以及可能的后续操作。\n实现步骤\n\n定义资源的链接在 API 响应中,除了返回资源的具体数据,还应包含相关的链接。这些链接通常嵌入到 links 或 _links 字段中,指向与该资源相关的其他操作。例如,返回一个用户资源时,可能会提供指向该用户订单的链接、更新用户信息的链接等。\n链接的类型\n\nself表示当前资源的 URL客户端可以通过此链接重新获取资源。\nrelated指向与当前资源相关的其他资源。例如用户的订单列表、用户的地址信息等。\nactions表示客户端可以对该资源执行的操作例如编辑、删除等。\n\n\n返回响应中包含链接 在 RESTful API 的响应体中,返回的资源除了数据本身,还可以包含指向相关资源的超链接。通过这些链接,客户端可以动态发现可以执行的操作,而无需事先了解所有 API 细节。例如,在获取用户资源时,响应体不仅返回用户的基本信息,还应包含一些超媒体链接,指向用户的其他关联资源或可执行的操作。\n\n示例响应\n{\n "id": 123,\n "name": "John Doe",\n "email": "john.doe@example.com",\n "_links": {\n "self": {\n "href": "/users/123"\n },\n "orders": {\n "href": "/users/123/orders"\n },\n "edit": {\n "href": "/users/123/edit",\n "method": "PUT"\n },\n "delete": {\n "href": "/users/123",\n "method": "DELETE"\n }\n }\n}\n在这个示例中响应体不仅包含了用户的基本信息还包含了一系列可执行的操作链接\n\nself 链接指向当前用户资源的详细信息。\norders 链接指向用户的订单列表。\nedit 链接指向用户信息的更新操作。\ndelete 链接指向删除用户的操作。\n\n客户端可以基于这些链接执行相应的操作而不需要事先知道每个路径或方法。\n实现中的注意点\n\n链接的描述除了提供链接的 URL最好还指明该链接对应的 HTTP 方法,例如 GET、PUT、DELETE 等。这让客户端更加明确该链接是用于获取、修改还是删除资源。\n动态链接生成服务器端应根据资源的当前状态动态生成合适的链接。例如当某个资源处于只读状态时不应返回更新或删除的链接。\n\nHATEOAS 实例\n下面我们通过一个完整的实例来展示如何在 RESTful API 中使用 HATEOAS。假设我们有一个电商系统客户端请求获取某个商品的信息同时希望知道可以对该商品进行的操作。\n请求\n客户端发出请求获取商品的详细信息GET /products/456\n响应\n服务器返回商品的信息并提供相关操作的链接\n{\n "id": 456,\n "name": "Laptop",\n "price": 1200,\n "availability": "in_stock",\n "_links": {\n "self": {\n "href": "/products/456"\n },\n "add_to_cart": {\n "href": "/cart",\n "method": "POST",\n "body": {\n "product_id": 456,\n "quantity": 1\n }\n },\n "reviews": {\n "href": "/products/456/reviews"\n },\n "related_products": {\n "href": "/products/456/related"\n }\n }\n}\n\nself 链接指向当前商品的详细信息,允许客户端重新获取或刷新商品信息。\nadd_to_cart 链接指向将该商品加入购物车的操作,并提供了 POST 请求的示例 body说明需要发送的具体数据。\nreviews 链接指向该商品的评论,客户端可以通过该链接获取相关评论。\nrelated_products 链接提供了推荐的相关产品。\n\n通过这种设计客户端无需提前知道如何将商品加入购物车或如何获取商品的评论只需要解析响应中的链接并进行相应操作即可。这种方式减少了客户端与服务器的耦合性并使得 API 更加灵活易用。\nHATEOAS 的优势\n\n动态性HATEOAS 使得客户端能够动态适应服务器端的变化。即使服务器端 API 的部分实现发生改变(如路径或操作方式),客户端仍然可以通过解析超链接来继续使用 API。\n减少客户端与服务器的依赖HATEOAS 将服务器的操作引导内嵌到 API 响应中,客户端只需依赖返回的超媒体链接进行操作,无需在代码中硬编码 API 路径。\n自描述性API 响应不仅提供数据,还提供了关于如何操作这些数据的详细说明,这使得 API 更具自描述性,减少了对文档的依赖。\n\n安全模型概述\n在 RESTful API 的开发过程中,安全性是一个至关重要的方面。由于 API 通常直接暴露在互联网上,成为恶意攻击的潜在目标,因此 API 的安全性设计需要特别重视。安全模型的设计不仅需要防止常见的攻击如 XSS、CSRF、SQL 注入,还需要确保 API 具备良好的身份验证、授权和数据保护机制。以下内容将讨论常见的 Web 安全威胁以及设计 API 安全模型的基本原则。\n常见 Web 安全威胁\nRESTful API 的安全威胁通常与 Web 应用面临的安全威胁类似。以下是几种常见的 Web 安全威胁及其在 API 中的防护措施:\n跨站脚本攻击 (XSS)\nXSS 攻击指的是恶意攻击者在 Web 页面中注入恶意脚本代码,通常是在没有充分验证和过滤用户输入的情况下发生。这些脚本代码会被浏览器执行,攻击者可以窃取用户的敏感信息,如身份验证 Cookie、会话 Token甚至修改页面内容。\n在 API 中的防护措施:\n\n输入验证与输出编码严格验证所有来自客户端的输入并对输出到客户端的数据进行编码防止 HTML 或 JavaScript 注入。确保任何用户提交的内容都不会被未经处理地传递给其他用户或系统。\n使用内容安全策略 (CSP)CSP 是一种浏览器的安全策略,可以防止跨站脚本和其他恶意代码执行。通过设定严格的 CSP可以降低 XSS 攻击的风险。\n避免反射性 XSS在 API 中尽量避免直接将用户输入的数据返回给客户端,尤其是未经处理的数据。\n\n跨站请求伪造 (CSRF)\nCSRF 攻击是指攻击者通过伪造用户的身份向 API 发起恶意请求。通常,攻击者会诱骗用户点击恶意链接或打开某些页面,利用用户已登录的身份在目标网站上执行未授权的操作,例如更改账户信息或提交表单。\n在 API 中的防护措施:\n\n使用 CSRF TokenAPI 应要求客户端发送唯一的 CSRF Token验证该 Token 是否与用户会话匹配。这样,即便攻击者尝试发起 CSRF 攻击,没有有效的 Token 就无法成功执行请求。\n同源策略确保 API 只允许来自受信任的源的请求。可以通过设置 Access-Control-Allow-Origin 来限制访问源。\n使用 SameSite Cookie 属性:确保会话 Cookie 设置了 SameSite 属性,这样可以防止 Cookie 被跨站请求利用。\n\nSQL 注入\nSQL 注入是指攻击者通过注入恶意 SQL 语句来操控数据库,通常是通过未经过滤的输入直接构造 SQL 查询发生的。这种攻击会导致数据泄露、数据篡改甚至系统的全面控制。\n在 API 中的防护措施:\n\n使用参数化查询或预处理语句永远不要直接将用户输入的数据拼接到 SQL 查询中,而是使用参数化查询或预处理语句来处理输入,这可以有效避免 SQL 注入。\n输入验证对所有的输入数据进行严格的验证与过滤确保其符合预期格式避免恶意数据进入系统。\n\n暴力破解攻击 (Brute Force Attack)\n攻击者通过大量尝试用户名和密码组合暴力破解账户。这种攻击通常利用 API 中的身份认证系统,以试图获取未经授权的访问权限。\n在 API 中的防护措施:\n\n限速和速率限制 (Rate Limiting):通过 API 速率限制,防止恶意用户在短时间内进行大量请求。可以采用 IP 限制或用户级别的请求速率限制。\n多因素身份验证 (MFA):启用多因素身份验证,可以有效减少单凭密码无法保护账户的风险。\n\n数据泄露和敏感信息暴露\n攻击者通过漏洞或不安全的传输方式获取系统中的敏感数据例如未加密的密码、个人信息等。\n在 API 中的防护措施:\n\n加密敏感数据确保在传输和存储过程中敏感信息如密码、身份验证 Token都经过加密处理。使用 HTTPS 协议来加密传输过程中的数据。\n敏感信息最小化避免在响应体或错误信息中暴露敏感信息例如详细的数据库错误或服务器结构信息。\n\nAPI 安全性设计的基本原则\n为了设计一个安全的 RESTful API开发者需要遵循一些核心的安全性原则。这些原则可以帮助 API 抵御常见的攻击,提高系统的健壮性。\n身份验证与授权\n身份验证验证客户端身份是确保 API 安全的第一步。API 可以使用多种身份验证机制来确保客户端请求的合法性:\n\nOAuth 2.0 和 OpenID Connect这是目前最常见的身份验证和授权机制。OAuth 2.0 通过授权服务器分发 Token客户端通过携带 Token 请求受保护的资源,服务器验证 Token 的有效性并授予访问权限。\nJWT (JSON Web Token)JWT 是一种轻量的 Token 格式常用于用户身份验证。API 可以使用 JWT 来验证用户身份JWT 包含了用户信息和数字签名,服务器通过解密签名来验证请求的真实性。\n\n授权在身份验证之后还需要验证用户是否有权限执行特定的操作。这可以通过细粒度的角色权限控制来实现。\n\n角色权限模型基于用户的角色例如管理员、普通用户控制其可以访问的资源和操作。\n资源级权限控制除了角色权限还可以基于具体资源的所有权来控制访问权限。例如一个用户只能修改自己创建的资源。\n\nHTTPS 加密传输\n所有 API 通信都应该使用 HTTPS 进行加密防止敏感数据在网络中传输时被窃听或篡改。TLS传输层安全协议可以确保数据在传输过程中的机密性、完整性和真实性。\n速率限制和 IP 黑名单\n速率限制 (Rate Limiting)限制单个客户端在单位时间内可以发送的请求数量可以有效防止暴力破解攻击、DDoS 攻击等。速率限制可以根据用户、IP 地址、API 端点等多种维度进行设置。例如限制用户在 1 分钟内只能发起 100 次请求,超过限制则返回 429 Too Many Requests。\nIP 黑名单和白名单:可以根据客户端的 IP 地址对请求进行控制,拒绝来自已知恶意 IP 的请求,或仅允许来自特定 IP 地址的访问。\n最小权限原则\nAPI 应该遵循最小权限原则,即每个用户或服务只能访问其执行操作所需的最小权限范围。这可以防止由于过多权限而导致的潜在滥用或攻击。\n\n限制 Token 权限:在使用 OAuth 2.0 或其他 Token 验证机制时,确保 Token 只具有访问必要资源的权限。Token 的生命周期应短,以减少攻击面。\n\n防止过度暴露信息\nAPI 响应中应避免泄露过多的敏感信息,尤其是在错误响应时。不要返回可能暴露系统内部实现的详细错误信息。对于客户端请求的错误,返回的错误信息应简洁明了,例如:\n\n避免返回详细的 SQL 错误。\n应当返回简单的 400 Bad Request 或 401 Unauthorized。\n\n日志记录与监控\nAPI 应该对所有敏感操作进行详细的日志记录,包括身份验证尝试、授权失败、数据修改操作等。日志有助于在发生攻击时快速追踪问题和响应。\n\n实时监控可以设置自动化监控系统在检测到可疑活动如大量 401 错误或速率限制触发)时及时报警。\n\nAPI 认证机制\nAPI 认证机制的目的是确保只有合法的用户或客户端能够访问受保护的资源。设计和实现安全、灵活的认证机制是 API 开发中的关键步骤。认证机制的选择应根据应用的具体需求,包括安全性、可扩展性和用户体验来做出决定。本节将详细介绍几种常见的 API 认证机制包括基本认证、摘要认证、OAuth 2.0、OpenID Connect 以及 JWTJSON Web Token。\n基本认证和摘要认证\n基本认证Basic Authentication 和摘要认证Digest Authentication 是两种较为简单的 HTTP 认证机制,它们通过 HTTP Headers 提供用户凭据来验证用户身份。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度基本认证摘要认证认证机制客户端将用户名和密码通过 Base64 编码后发送至服务器。请求头格式Authorization: Basic base64(username:password)客户端发送经过加密散列算法(如 MD5生成的摘要包含用户名、密码和随机数Nonce。服务器对摘要进行验证。密码传输方式用户名和密码以 Base64 编码形式发送,需依赖 HTTPS 来防止中间人攻击。用户名和密码不会直接传输,使用摘要验证,提供了一定程度的防护。服务器端验证服务器接收并解码 Base64 字符串然后匹配用户名和密码是否正确。服务器根据相同的加密算法和参数生成摘要并与客户端发送的摘要进行对比。请求头格式Authorization: Basic base64(username:password)Authorization: Digest username="user", realm="realm", nonce="random", response="hashed-data"安全性依赖高度依赖 HTTPS 加密来确保安全性,如果未加密,信息容易被拦截。提供比基本认证更好的安全性,因为密码不直接传输,但在未加密的通道上依然可能被攻击。状态保持无状态认证,每次请求都需要包含认证信息,服务器无需维护会话状态。也是无状态认证,每次请求都需包含认证摘要,但复杂度增加。实现复杂性实现简单,客户端和服务器都容易支持,尤其适用于快速开发场景。实现较复杂,客户端需要生成加密摘要,服务器需要根据多个参数验证摘要。常见应用场景内部系统、开发测试环境、简单 API 请求安全性要求稍高的场景、基本 Web 认证、使用加密通道但不需要复杂认证的系统浏览器支持原生支持,无需特殊处理。部分支持,需更多配置。性能影响对性能影响较小,因为只需要简单的 Base64 编码。对性能影响略大,因为需要进行多次加密和摘要计算。使用复杂度客户端和服务器均简单,适合低复杂度应用。客户端和服务器需进行额外的摘要计算,客户端的复杂度较高。\nOAuth 2.0\nOAuth 2.0 是目前最流行的认证和授权框架,广泛应用于各种 Web API 中。它提供了一种安全且灵活的方式,让用户能够通过第三方应用安全地授权 API 访问资源而无需分享其用户名和密码。OAuth 2.0 主要用于授权,而不是直接用于身份验证。\nOAuth 2.0 的工作原理\n\nOAuth 2.0 的核心思想是通过 授权服务器Authorization Server来颁发 访问令牌Access Token而不是用户直接向客户端提供凭据。整个过程分为以下步骤\n\n用户访问资源用户想要访问 Web 应用提供的某些受保护资源(通常存储在资源服务器上)。\n客户端请求授权Web 应用作为客户端,向授权服务器请求用户的授权。\n用户输入凭证用户在 Web 应用界面中输入其凭证(如用户名和密码),并同意授予 Web 应用访问其资源的权限。\n客户端传递凭证Web 应用将用户的凭证与 OAuth 相关的凭证(如客户端 ID、重定向 URI 等)发送给授权服务器,以换取访问令牌。\n授权服务器返回访问令牌授权服务器验证凭证并返回一个 访问令牌Access Token。这个令牌代表了 Web 应用的访问权限。\n客户端传递访问令牌Web 应用将获取的访问令牌传递给资源服务器。\n资源服务器授权访问资源服务器验证访问令牌并允许 Web 应用访问受保护的资源。\n用户可以访问应用用户最终可以通过 Web 应用访问到资源服务器上的受保护资源。\n\nOAuth 2.0 的授权模式\nOAuth 2.0 提供了几种不同的授权模式,适用于不同的场景:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度授权码模式 Authorization Code Grant隐式授权模式 Implicit Grant资源所有者密码凭证模式 Password Grant客户端凭证模式 Client Credentials Grant适用场景服务器端应用如 Web 应用、后台服务单页应用SPA、移动应用高度信任的应用如第一方应用、内部系统机器对机器M2M通信应用程序之间的服务调用认证流程1. 用户通过浏览器登录并授权。 2. 授权服务器返回授权码。 3. 后端服务器使用授权码交换访问令牌。1. 用户授权后,直接通过浏览器返回访问令牌。 2. 客户端可立即使用访问令牌访问资源。1. 用户直接提供用户名和密码给客户端。 2. 客户端使用凭证请求授权服务器获取令牌。1. 客户端使用自己的凭证直接向授权服务器请求访问令牌,无需用户参与。令牌存储位置令牌存储在服务器端,前端无法访问。令牌存储在浏览器或移动应用中,可能暴露在 URL 哈希或客户端存储。令牌存储在客户端,客户端必须保护用户名、密码和令牌安全。令牌存储在服务器端或应用程序中,应用需保护凭证和令牌的安全。安全性高:令牌通过后端服务器交换,不直接暴露在客户端中。低:令牌直接暴露在客户端的 URL 中,容易被截获,建议使用短期令牌。中等:凭证和令牌都直接提供给客户端,需要确保客户端的高度安全性。高:仅限于应用程序间的通信,不涉及用户凭证,因此安全性较高。实现复杂性高:需要后端服务器管理授权码和访问令牌的交换,流程相对复杂。低:流程简单,令牌直接返回给客户端,但安全性较差。中等:客户端需要管理用户凭证和访问令牌的安全,服务器端无需额外处理。低:应用直接使用凭证获取令牌,无需用户交互,流程较为简单。刷新令牌支持支持:可以使用刷新令牌获取新的访问令牌,适合长期授权使用。不支持:无法使用刷新令牌,需重新授权,适合短期访问场景。支持:可以通过刷新令牌获取新的访问令牌,但用户凭证仍然需要安全管理。支持:可以使用刷新令牌进行无缝授权续期。用户交互用户需要通过浏览器授权并登录,之后授权码通过后端交换,用户交互较少。用户直接在浏览器中完成授权和令牌获取,交互相对较多,但不涉及后端处理。用户直接提供用户名和密码给客户端,交互简单,但涉及高度信任的客户端。不涉及用户交互,应用程序自动完成凭证授权和令牌获取。常见应用场景- Web 应用程序 - 高安全性要求的应用,如金融服务- 单页应用SPA - 移动应用快速授权- 内部系统 - 高度信任的客户端,如公司内部的第一方应用- 后端服务之间的通信 - 微服务架构中应用程序之间的授权典型缺点实现复杂,需要维护服务器端的授权码和令牌交换机制。安全性较低,令牌易泄露,适合短期授权的场景,不适合长期会话。用户凭证直接暴露在客户端,适合信任关系高的场景,不适合开放性平台。只适用于服务端授权场景,不涉及用户,不能用于用户授权的情境。\nOpenID Connect\nOpenID Connect 是基于 OAuth 2.0 构建的身份认证协议,它将 OAuth 2.0 授权框架扩展为可以执行身份验证的协议。它不仅允许客户端获取用户的资源访问权限,还提供了用户身份的验证服务。\nOpenID Connect 工作原理\nOpenID Connect 在 OAuth 2.0 的基础上引入了 ID Token该 ID Token 是一种 JWTJSON Web Token包含了用户的身份信息如用户 ID、登录时间、签发者等。它不仅允许客户端获取访问令牌来访问用户资源还能够验证用户身份。\nsequenceDiagram\n participant User\n participant Client\n participant AuthorizationServer\n participant ResourceServer\n \n User ->> Client: 请求访问应用\n Client ->> AuthorizationServer: 请求授权 (Scope: openid)\n AuthorizationServer ->> User: 请求身份验证并授权\n User ->> AuthorizationServer: 验证通过并授权\n AuthorizationServer ->> Client: 返回 Access Token 和 ID Token\n Client ->> AuthorizationServer: 验证 ID Token (JWT)\n AuthorizationServer -->> Client: 返回验证结果\n Client ->> ResourceServer: 使用 Access Token 访问资源\n ResourceServer ->> Client: 返回受保护的资源\n Client ->> User: 展示资源或服务\n\n\n客户端请求授权客户端通过授权请求向授权服务器发起身份验证和授权请求在请求中包含 openid 范围,表明客户端希望获取用户的身份信息。\n用户认证并授权用户通过授权服务器的身份验证并同意授予客户端访问权限。\n授权服务器返回 ID Token 和 Access Token授权服务器在颁发访问令牌的同时还会返回一个 ID Token。ID Token 是一个 JWT其中包含了用户的身份信息。\n客户端验证 ID Token客户端解码并验证 JWTID Token确保其由授权服务器合法签发并且包含正确的用户身份信息。\n使用 Access Token 访问资源:客户端可以使用 OAuth 2.0 中获得的 Access Token向资源服务器请求访问受保护的资源。\n资源服务器验证 Access Token 并返回数据:资源服务器验证 Access Token 的合法性后,返回用户的资源数据。\n\nOpenID Connect 的优势\n\n统一身份验证与授权通过一个标准协议同时解决身份验证和授权问题。\n安全性强通过 JWT 进行身份验证,客户端可以验证 Token 的有效性、合法性。\n广泛支持OpenID Connect 得到许多主流身份提供者的支持,如 Google、Microsoft、Facebook 等。\n\n应用场景\n\n实现单点登录SSO允许用户使用第三方身份提供者登录。\n用户认证场景尤其是在需要用户信息的应用中OpenID Connect 提供了标准化的身份验证机制。\n\nJWT\nJSON Web Token (JWT) 是一种基于 JSON 的开放标准RFC 7519用于在客户端与服务器之间安全地传输信息。JWT 具有自包含性Token 中不仅包含了认证信息,还携带了一定的用户数据。它是 API 中广泛使用的认证和授权机制。\nJWT 的结构\nJWT 由三个部分组成,分别是:\n\n\nHeader描述了 Token 的类型和签名算法,例如:\n{\n "alg": "HS256",\n "typ": "JWT"\n}\n\n\nPayload包含了用户信息如用户 ID、角色和其他声明claims。例如\n{\n "sub": "1234567890",\n "name": "John Doe",\n "admin": true\n}\n\n\nSignature使用 Header 中声明的算法对 Header 和 Payload 进行签名,确保 Token 的完整性和可信度。\nHeader.Payload.Signature\n\n\nJWT 的工作原理\nsequenceDiagram\n participant User\n participant Client\n participant Server\n User ->> Client: 提交登录信息\n Client ->> Server: 发送登录请求\n Server ->> Server: 验证凭据\n Server ->> Client: 返回 JWT Token\n Client ->> Client: 存储 JWT (LocalStorage/Cookie)\n User ->> Client: 请求访问受保护资源\n Client ->> Server: 携带 JWT 的请求 (Authorization: Bearer <jwt_token>)\n Server ->> Server: 验证 JWT 签名\n Server ->> Client: 返回受保护的资源\n\n\n\n客户端发送登录请求当用户提交登录信息如用户名和密码服务器会验证这些凭据。如果验证通过服务器生成一个 JWT包含用户信息的 Token并将其返回给客户端。\n\n\n客户端存储并使用 JWT客户端接收到 JWT 后,会将其存储在安全的位置(如浏览器的 LocalStorage 或 Cookies。在后续的 API 请求中,客户端通过在 Authorization 头中携带 JWT向服务器证明身份\nAuthorization: Bearer <jwt_token>\n\n\n服务器验证 JWT当服务器接收到包含 JWT 的请求时,会对 JWT 的签名进行验证,确保它未被篡改。如果验证通过,并且 Token 仍然有效(没有过期),则服务器允许客户端访问受保护的资源。\n\n\nJWT 的安全性与实现模式\nJWT 的签名确保了它的完整性和可信度,但需要注意 JWT 本身不加密。敏感信息不应直接放在 JWT 的 Payload 中。可以结合 HTTPS 传输加密,确保数据的保密性。\nJWT 通常带有过期时间,确保 Token 的有效期有限。为了避免用户频繁登录,可以实现刷新 TokenRefresh Token机制允许客户端在 Token 过期时通过 Refresh Token 重新获取新的 JWT。\n示例\nGET /profile\nAuthorization: Bearer <jwt_token>\n\nJWT 的优势\n\n自包含性JWT 中自带了用户信息,服务器不需要存储 Token 状态,这使得 JWT 非常适合无状态的 RESTful API。\n扩展性强JWT 可以通过 Payload 携带任意声明,支持复杂的身份验证和授权逻辑。\n\n应用场景\n\n无状态的分布式应用认证。\n需要轻量化、低延迟的 Web 和移动应用认证。\n\nAPI Key\nAPI Key 是一种简单且常见的 API 认证机制,通常用于控制对 API 的访问权限。尽管它相比 OAuth 2.0 和 JWT 等复杂的认证机制较为基础但在某些场景中API Key 提供了足够的安全性和便利性。理解 API Key 的应用场景、优缺点,以及如何确保 API Key 的安全性,对 API 的开发和维护至关重要。\nAPI Key 的概念\nAPI Key 是一段唯一的字符串,用于标识和验证客户端请求。每个客户端在访问 API 时,都会将 API Key 附带在请求中API 服务器根据这个 Key 验证客户端的合法性从而允许或拒绝访问资源。API Key 通常通过 HTTP 头、查询参数或请求体传递。\n示例\nGET /api/v1/resources\nAuthorization: Api-Key {your-api-key}\n\nAPI Key 的应用场景\nAPI Key 通常用于以下场景:\n\n公共 API 访问控制API Key 广泛用于公共 API 来限制访问和监控流量。即使是开放的 API 也可能要求用户通过 API Key 来追踪和限制使用量。\n简单的身份验证在对复杂性要求不高的系统中API Key 提供了一种简单、直接的身份验证机制。许多内部系统和低安全性需求的应用会使用 API Key。\n服务到服务的通信在微服务架构或其他分布式系统中API Key 常用于服务之间的身份验证。相比于 OAuth 等机制API Key 在无需用户交互的机器间通信中更为简便。\n监控和速率限制通过 API Key可以轻松地对每个客户端进行速率限制和监控。API Key 可以帮助开发者统计每个客户端的请求数量、频率等指标。\n\nAPI Key 的优点\n\n简单易用API Key 易于生成、管理和集成。客户端只需在请求中附带 API Key 即可访问资源,服务器通过简单的验证机制即可控制访问权限。\n良好的可追溯性API Key 便于对客户端的使用情况进行监控和统计。例如,可以根据不同的 API Key 追踪请求来源、调用频率和使用量。\n广泛支持API Key 几乎所有的 Web 应用、移动应用和服务端应用都支持,并且与 HTTP 请求轻松集成。\n\nAPI Key 的缺点\n\n安全性较低API Key 通常是静态的容易暴露。API Key 仅凭一段字符串即可进行身份验证,无法提供足够强的安全保障,尤其是在恶意拦截攻击(如中间人攻击)下。\n缺乏授权控制API Key 只能用来认证客户端,但无法控制细粒度的资源授权。它无法像 OAuth 2.0 那样控制访问特定资源的权限,也无法处理用户身份验证。\n无状态性API Key 通常是无状态的,每次请求都需要携带 Key且服务器无法了解 Key 的上下文,难以提供复杂的认证和授权逻辑。\n\n与 OAuth 和 JWT 的对比分析\n为了帮助开发者选择合适的认证机制理解 API Key、OAuth 2.0 和 JWT 的不同点是很重要的。每种机制都有其独特的应用场景和优缺点。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比维度API KeyOAuth 2.0JWT身份验证与授权仅提供身份验证,不能细粒度控制权限提供身份验证和授权,支持细粒度权限控制,适合复杂授权场景可以携带用户信息,既可用于身份验证也可用于授权安全性静态密钥,容易被拦截和泄露,安全性较低动态 Access Token支持短生命周期 Token安全性较高通过签名防篡改安全性较高适合无状态认证复杂性实现简单客户端只需附带 API Key实现复杂需要授权服务器客户端需管理 Token 的获取与刷新需要签发和验证 JWT需管理 Token 生命周期复杂度较高使用成本开发成本低适合快速开发的项目开发成本高适合复杂的多方授权和高安全性需求的应用复杂度较高需处理签名和验证适合需要无状态认证的系统Token 生命周期无生命周期API Key 不会自动过期Token 有生命周期,过期后需要通过 Refresh Token 更新JWT 有固定的有效期过期后需重新获取Token 类型静态 Key动态 Access Token 和 Refresh TokenJWTJSON Web Token包含用户信息和签名传输安全性需要通过 HTTPS 保护密钥,防止泄露通过 Token 传输,支持加密传输,安全性较高通过签名和加密,防止数据篡改,传输安全性高典型应用场景适用于简单的公共 API 或低安全要求的内部应用第三方登录、社交应用、复杂授权(多角色、多权限)分布式系统、无状态认证、需要携带用户身份的场景实现的灵活性适合简单 API 调用,灵活度有限灵活,适用于多种应用场景,特别是复杂的授权场景灵活,支持无状态、分布式应用,适用于身份验证和授权适合的系统架构单体应用或简单的微服务架构复杂系统、多方授权的微服务架构分布式系统,跨服务的用户身份验证和授权\nAPI Key 安全实践\n尽管 API Key 的安全性较弱,但通过正确的安全措施,可以提高其安全性,防止常见的攻击和泄露。以下是一些在生成、存储和验证 API Key 时的最佳实践:\nAPI Key 的生成\n\n随机性与长度API Key 应具有足够的随机性和长度,避免简单的猜测和暴力破解。使用安全的伪随机算法生成 Key确保其不可预测性。推荐的 Key 长度至少为 32 个字符。\n唯一性确保每个客户端拥有唯一的 API Key防止 Key 的冲突和复用。\n\nAPI Key 的存储\n\n加密存储在服务器端存储 API Key 时,必须进行加密存储。不要将 API Key 以明文形式存储在数据库中。使用哈希算法(如 SHA-256加密 Key防止其在数据库泄露时被直接使用。\n传输时使用 HTTPS始终通过 HTTPS 传输 API Key确保 Key 在传输过程中不会被窃听。通过 TLS 加密通信可以有效防止中间人攻击。\n\nAPI Key 的验证\n\n限制 API Key 的使用范围:限制 API Key 只能在特定的 IP 地址、域名或平台上使用。这可以防止 API Key 被滥用。例如,限制 Key 只能从特定的 IP 地址发送请求。\n设置过期时间API Key 可以设置生命周期,确保 Key 在一段时间后失效,减少 Key 泄露带来的风险。如果应用长期使用,可以提供 Key 刷新机制,让用户周期性更换 Key。\n速率限制和流量监控对每个 API Key 进行速率限制,防止 API 被恶意滥用或攻击。通过速率限制,确保每个客户端在特定时间窗口内只能发送有限数量的请求(如每分钟 100 次请求)。\n\nAPI Key 的管理\n\n支持 API Key 的轮换与吊销:为用户提供 API Key 轮换和吊销的功能。当 Key 泄露或不再需要时,用户应能够吊销旧 Key 并生成新的 Key。通过这种机制可以减少 Key 泄露的影响。\n日志记录与监控记录每次使用 API Key 的请求,进行日志监控。定期检查是否存在异常使用行为,如频繁的失败请求、来自未知 IP 地址的访问等,以便及时发现和阻止潜在的攻击。\n\nAPI 性能监控与调优\nRESTful API 的性能对应用的整体用户体验和可扩展性至关重要。性能监控和调优是确保 API 在高并发和大流量情况下依然保持稳定、高效的关键环节。本节将介绍如何进行 API 性能监控、识别常见性能瓶颈,并通过负载测试和调优工具提高 API 的性能。\nAPI 性能监控的目的是实时捕获 API 的响应时间、吞吐量、错误率等关键指标,确保系统在正常工作负载和高负载下都能够正常运作。通过性能监控,开发者可以识别系统的瓶颈,并采取必要的调优措施。\n常用监控工具\nPrometheus\nPrometheus 是一个开源的监控系统专门用于时间序列数据的监控。它提供了强大的查询语言PromQL用于定义监控规则和创建告警还可以与其他监控工具如 Grafana结合使用。\nPrometheus 非常适合实时监控 API 的性能指标,包括响应时间、请求速率、错误率等。开发者可以设定阈值,当性能指标异常时自动触发告警。\nGrafana\nGrafana 是一个开源的数据可视化平台,通常与 Prometheus 一起使用,用于实时显示监控数据。开发者可以创建自定义仪表盘,展示 API 性能的各项关键指标。\n适合展示 API 性能趋势、监控 API 健康状态,以及通过丰富的可视化图表(如折线图、柱状图)监控多个 API 实例或微服务集群。\nElastic StackELK\nElastic StackElasticsearch、Logstash、Kibana可以帮助捕获和分析 API 的日志数据,并通过 Kibana 提供强大的日志可视化和搜索功能。API 的请求和错误日志可以通过 Logstash 收集并存储到 Elasticsearch 中,方便后续分析。\n适合通过分析日志数据监控 API 的运行状态,尤其是在需要深入分析请求失败、慢响应时。\n关键性能指标\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n性能指标描述监控方式作用与优化方向响应时间以毫秒ms为单位表示从客户端发出请求到收到服务器响应的时间。通常监控平均响应时间、P9595% 请求的响应时间)和 P9999% 请求的响应时间)来衡量 API 的性能。使用监控工具(如 Prometheus、Grafana跟踪每个 API 端点的响应时间,计算 P95、P99 等分位数指标。优化网络延迟、数据库查询、服务间调用等确保绝大多数请求的响应时间符合预期降低长尾延迟对用户体验的影响。吞吐量TPS/QPS每秒处理的事务或请求数量TPS每秒事务数或 QPS每秒查询数是衡量 API 并发处理能力的核心指标。高吞吐量表示 API 能够处理大量并发请求。使用性能测试工具(如 JMeter、Locust模拟高并发场景监控每秒处理的请求量TPS/QPS。优化 API 并发处理能力通过水平扩展如负载均衡、异步处理等技术提高吞吐量避免系统过载。错误率API 请求中的错误比例,通常通过 HTTP 状态码监控错误率。4xx 代表客户端错误5xx 代表服务器错误。高错误率可能反映出系统异常或过载,需要及时处理和优化。监控返回的 HTTP 状态码,使用工具(如 ELK Stack、Datadog分析 4xx 和 5xx 错误的频率。优化错误处理逻辑,减少服务端 5xx 错误,确保客户端调用参数正确减少 4xx 错误。通过速率限制和健康检查减少服务过载导致的错误。服务器资源使用率包括 CPU、内存、磁盘 I/O 的使用情况,帮助识别系统资源是否足够支撑 API 的负载。CPU 使用率过高可能导致响应延迟,内存不足可能引发服务崩溃,磁盘 I/O 过载则可能导致读写性能下降。使用监控工具(如 Prometheus、New Relic、Datadog跟踪服务器的 CPU、内存、磁盘 I/O 的使用率,分析资源瓶颈。通过优化算法、提高资源配置、负载均衡、水平扩展等手段来降低资源使用率,防止资源瓶颈影响系统稳定性和性能,确保在高负载下系统依然能够稳定运行。请求排队时间请求进入服务器队列后直到被处理的时间,较高的排队时间表示服务器处理能力达到瓶颈或请求过多。通过跟踪请求的进入和处理时间,监控排队时间,确保其保持在合理范围内。优化线程池配置、减少同步阻塞操作,提升服务器并发处理能力,降低请求排队时间,确保系统在高并发场景下仍能快速响应。连接超时率请求连接服务器时,由于网络延迟或服务器负载导致的超时请求的比例。监控连接的建立、处理和关闭时间,计算超时请求的比例。通过优化网络配置、使用 CDN 或边缘计算减少网络延迟,调整服务器负载,避免高并发或资源不足导致的连接超时。依赖服务性能如果 API 依赖其他服务(如数据库、缓存、外部 API这些依赖服务的性能也是关键指标包括数据库查询延迟、缓存命中率、外部服务响应时间等。监控与依赖服务的交互时间跟踪数据库查询、缓存读取、外部 API 调用的响应时间和成功率。通过优化数据库查询(如索引、缓存)、提高缓存命中率,减少外部 API 调用次数,确保依赖服务的高效性,降低 API 响应延迟。缓存命中率API 调用缓存的数据的成功率。高缓存命中率表示更多的请求可以从缓存中直接获取数据,减少对数据库等后端服务的依赖,提升响应速度。监控缓存请求的命中率和未命中率,分析缓存的使用情况。提高缓存的有效性和覆盖率,减少重复计算和数据库访问,确保常见请求能直接从缓存获取数据,从而提升 API 性能。\nAPI 性能瓶颈识别\n识别 API 性能瓶颈是提升性能的关键步骤。常见的性能瓶颈可以来自数据库、网络延迟、服务器负载等。通过监控和分析,可以快速识别问题所在,并采取相应的优化措施。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n性能瓶颈问题描述监控方法优化措施数据库瓶颈数据库查询复杂、缺乏索引或大量数据库连接会导致查询缓慢成为 API 性能的主要瓶颈。监控数据库查询时间、每秒查询数、慢查询日志,关注执行时间长的 SQL 语句。- 优化查询语句,减少复杂度 - 使用索引加快查询 - 引入缓存层(如 Redis减少数据库压力网络延迟网络不稳定或带宽限制尤其是跨地域调用可能导致请求延迟增加影响用户体验。监控网络延迟时间如 DNS 查询时间、TCP 建立时间、HTTP 请求 - 响应时间等)。- 使用 CDN 加速静态资源和部分动态响应 - 就近部署 API 服务节点,减少传输距离 - 使用 HTTP/2 或 HTTP/3 减少延迟服务器负载高并发请求、CPU/内存资源不足或磁盘 I/O 过高,可能导致服务器性能下降,甚至服务中断。通过监控工具跟踪 CPU 使用率、内存占用率、磁盘 I/O 等服务器资源使用情况。- 通过负载均衡增加服务器节点 - 垂直扩展(增加 CPU 核心数、内存容量) - 优化代码,减少 CPU 密集型操作和内存占用API 自身设计API 设计不合理,如一次请求查询多个资源、返回大量冗余数据,增加了请求复杂性和响应时间。分析 API 的设计和调用次数,监控单个请求的响应时间和数据返回量,避免不必要的查询和数据传输。- 优化 API 路由和返回数据 - 使用 Gzip 压缩响应体 - 设计批量接口,一次请求返回多个结果,减少请求次数磁盘 I/O 瓶颈磁盘读写速度过慢或 I/O 操作频繁会导致服务器性能下降,尤其是在处理大量数据写入或查询时。监控磁盘 I/O 性能,查看 I/O 等待时间和读写操作的频率,特别关注高 I/O 负载下的性能。- 优化数据存储结构,减少不必要的磁盘读写 - 使用 SSD 等高速存储设备 - 引入缓存机制减少对磁盘的直接访问缓存命中率低API 调用未充分利用缓存,导致大量请求直接命中数据库或后端服务,增加了延迟和服务器负载。监控缓存命中率和缓存使用情况,跟踪未命中缓存的请求,分析数据库和后端服务的压力。- 提高缓存命中率,确保常用数据可以从缓存中读取 - 减少重复查询和数据库调用 - 定期更新缓存,保持数据的新鲜度依赖外部服务延迟如果 API 依赖外部服务(如第三方 API 或内部微服务),外部服务的性能不佳可能导致整体延迟增加。监控与外部服务的交互时间,跟踪外部 API 的调用延迟、失败率和重试次数。- 缓存外部服务的返回数据,减少频繁调用 - 使用异步调用和重试机制,减少外部服务延迟对 API 的影响请求排队时间长请求进入服务器队列后等待处理的时间过长,可能由于服务器处理能力不足或请求过多。监控请求的排队时间,分析请求进入队列和被处理的时间差,检测是否存在过多请求积压。- 优化并发处理能力,增加处理线程数 - 减少同步阻塞操作,提升服务器的并发性能 - 增加服务器节点,分担负载压力\n负载测试与调优工具\n负载测试是衡量 API 在高并发情况下性能表现的重要手段,通过负载测试可以模拟不同的用户行为和并发场景,从而找到系统的极限和潜在瓶颈。负载测试还可以帮助评估系统在不同条件下的扩展性和稳定性。\n常用的负载测试工具\nLocust\nLocust 是一个基于 Python 的开源负载测试工具。它允许开发者编写自定义的测试场景,通过模拟大量用户对 API 发起并发请求。可以编写复杂的测试脚本,灵活控制用户行为。支持分布式测试,适合大规模负载测试。\n适合模拟真实用户行为和场景生成多种并发场景的数据便于识别 API 的性能瓶颈。\nJMeter\nApache JMeter 是一个开源的负载测试工具,广泛用于测试 Web 应用、RESTful API 的性能。支持 HTTP、HTTPS 等多种协议,界面友好,便于设置复杂的测试方案。可以模拟高并发场景,监测服务器响应时间、吞吐量等性能指标。\n适合各种协议下的 API 性能测试,尤其是对于大规模并发用户的模拟。\nGatling\nGatling 是一个基于 Scala 的高性能负载测试工具,专为测试高并发场景而设计。它的优势在于生成详细的测试报告和图表,帮助开发者深入分析性能问题。高性能、可扩展性强。支持复杂的场景测试,并能够实时生成详细的可视化测试报告。\n适合用于大规模、高并发的负载测试尤其是需要实时监控和详细分析性能的场景。\n性能调优技巧\n\n并发控制在高并发环境下通过对 API 进行并发控制(如使用互斥锁、队列)来防止过多的并发请求超出服务器承受能力。\n缓存使用缓存技术如 Redis、Memcached来缓存频繁访问的资源减少数据库的查询压力。针对静态资源可以在客户端和服务器端进行缓存控制。\n数据库优化在数据库层面进行优化例如使用查询缓存、优化 SQL 查询和索引策略,减少对数据库的多次查询。对于 NoSQL 数据库,考虑调整数据分片策略。\nAPI 网关和负载均衡:使用 API 网关处理流量,提供限流、熔断等功能,同时通过负载均衡分发流量,提升 API 的整体性能和可靠性。\n\n缓存设计\n缓存是提升 API 性能的关键手段之一。通过合理的缓存设计,能够减少不必要的资源请求,降低服务器负载,并提高响应速度。缓存可以发生在多个层面,例如客户端、服务器端、以及使用 CDN 进行缓存。合理运用 HTTP 缓存机制和缓存策略可以大幅提升 API 的性能。\nHTTP 缓存机制\nHTTP 缓存机制允许浏览器和中间代理(如 CDN缓存响应以减少对服务器的重复请求提高页面加载速度。了解 HTTP 缓存机制的工作原理可以帮助设计更高效的 API。\n1. Cache-Control\nCache-Control 是 HTTP/1.1 引入的用于控制缓存的主要机制通过该头部字段服务器可以告诉客户端和中间代理如何缓存响应。Cache-Control 具有以下常见指令:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n指令描述应用场景示例max-age指定响应可以被缓存的最大时间以秒为单位。客户端在该时间内不需要重新请求资源直接使用缓存内容。适用于可频繁访问、内容变化不频繁的资源如静态文件图片、CSS、JavaScript。Cache-Control: max-age=3600no-cache指示客户端每次都必须向服务器重新验证缓存内容是否有效不能直接使用缓存。适用于内容可能频繁变化需要服务器验证最新状态的资源如用户信息、动态数据等。Cache-Control: no-cacheno-store禁止缓存。客户端和代理服务器不能存储请求或响应的任何部分。适用于敏感数据或隐私信息的场景如登录页面、银行账户详情等。Cache-Control: no-storepublic允许响应被任何缓存包括客户端、代理服务器、中间 CDN 服务器)进行缓存。适用于所有用户都可以访问且不涉及隐私的数据,如公开的文档、公共 API 响应、静态资源等。Cache-Control: publicprivate只允许客户端缓存中间代理或 CDN 服务器不能缓存该响应保护私有数据。适用于包含个人信息或与用户相关的资源如用户个人资料、私有账户信息等防止代理服务器缓存敏感数据。Cache-Control: privatemust-revalidate指示客户端必须重新验证缓存的有效性并且只有在服务器验证后才能使用缓存内容。适用于确保缓存的内容始终是最新的防止客户端使用过期缓存的场景如实时数据或交易信息。Cache-Control: must-revalidateproxy-revalidate要求中间代理如 CDN必须在过期后重新验证缓存的有效性类似于 must-revalidate但仅作用于代理服务器。适用于希望确保中间代理服务器缓存内容始终与源服务器同步的场景防止代理服务器使用过期缓存。Cache-Control: proxy-revalidates-maxage适用于共享缓存如代理服务器、CDN的最大存储时间。覆盖 max-age 指令,用于中间缓存而不是客户端。适用于代理服务器或 CDN 的缓存控制,例如为静态资源在 CDN 上设置不同于客户端缓存的生命周期。Cache-Control: s-maxage=7200stale-while-revalidate允许客户端在后台重新验证缓存的同时使用过期缓存提高响应速度。适用于需要快速响应但内容变化较少的场景如缓存静态资源同时异步更新缓存。Cache-Control: stale-while-revalidate=300stale-if-error允许客户端在服务器无法提供有效响应时使用已过期的缓存作为备用内容。适用于当源服务器出现问题时可以临时使用过期缓存提供服务减少服务中断对用户的影响。Cache-Control: stale-if-error=86400\n2. ETag\nETag实体标签Entity Tag 是一种基于响应内容生成的唯一标识符。每次请求资源时,服务器会返回一个 ETag客户端可以在后续请求中使用 If-None-Match 头携带这个 ETag 值。如果服务器发现资源没有变化,返回 304 Not Modified 响应,而不发送资源的实际内容。\nETag 工作流程:\n\n\n服务器返回响应时携带 ETag 头。\nETag: "686897696a7c876b7e"\n\n\n\n客户端后续请求同一资源时携带 If-None-Match 头进行验证。\nIf-None-Match: "686897696a7c876b7e"\n\n\n\n如果资源未修改服务器返回 304 Not Modified。\nHTTP/1.1 304 Not Modified\n\n\n\nETag 可以精确比较资源的变化,因此比 Last-Modified 更可靠,尤其是资源频繁更新的场景。\n3. Last-Modified\nLast-Modified 是另一种验证资源是否更新的机制。它记录了资源上次修改的时间戳,客户端可以在请求中使用 If-Modified-Since 头来询问服务器自该时间之后资源是否已修改。\nLast-Modified 工作流程:\n\n\n服务器返回响应时包含 Last-Modified 头:\nLast-Modified: Wed, 21 Oct 2023 07:28:00 GMT\n\n\n\n客户端后续请求时携带 If-Modified-Since 头进行验证:\nIf-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT\n\n\n\n如果资源未修改服务器返回 304 Not Modified。\n\n\n虽然 Last-Modified 易于实现,但它的时间精度有限(通常精确到秒),并且无法检测到资源在同一秒内多次修改的情况。\n4. Expires\nExpires 头用于指定资源的到期时间点,表示在这个时间点之前,客户端和代理可以使用缓存,而无需请求服务器。它被 Cache-Control: max-age 所取代,但仍旧被一些旧系统使用。\nExpires: Wed, 21 Oct 2023 07:28:00 GMT\n\n如何提升 API 性能\n通过结合使用 Cache-Control、ETag 和 Last-Modified 等机制API 可以在提供最新数据的同时减少冗余请求和响应负载。例如,针对不经常更新的数据资源(如静态文件、配置数据等),可以通过设置较长的 max-age 来显著减少请求流量。而对于可能随时变更的动态数据,使用 ETag 进行内容校验是一种有效的优化方式。\n客户端与服务器端缓存策略\n缓存策略的设计需要根据应用的具体场景来决定既要最大化性能又要保证数据的时效性和准确性。缓存可以发生在客户端、服务器端以及代理服务器上不同层级的缓存策略组合能显著提升 API 的性能。\n1. 客户端缓存策略\n客户端缓存是浏览器和移动设备等客户端应用存储数据的一种方式。浏览器缓存通过 Cache-Control、Expires、ETag 等 HTTP 头来决定是否直接从缓存中读取资源。\n\n静态资源长期缓存对于 CSS、JavaScript、图像等静态资源可以使用 Cache-Control: max-age=31536000 设置长时间缓存,并通过文件名哈希管理版本。当资源更新时,通过更改 URL 来强制客户端重新获取。\n动态资源短期缓存对于动态资源或频繁变化的资源可以通过 Cache-Control: no-cache 或短时间的 max-age如 300 秒)确保客户端频繁向服务器验证资源是否更新。\n\n2. 服务器端缓存策略\n服务器端缓存是 API 服务器通过中间件或缓存系统(如 Redis、Memcached缓存数据的方式。缓存可以显著减少对数据库和外部服务的请求提升 API 响应速度。\n\n数据库查询结果缓存将耗时长的查询结果缓存到内存数据库中减少数据库压力。例如将用户的配置信息缓存到 Redis 中,在短时间内不需要频繁查询数据库。\n页面级缓存对于不常变化的页面或资源可以缓存完整的响应结果。例如新闻网站的首页可以通过服务器缓存几分钟的时间减少对后台服务的压力。\nAPI 响应缓存:通过缓存整个 API 响应数据,加速对常见请求的处理。例如,使用 Redis 来缓存最近的热门商品列表。\n\n3. 代理服务器缓存策略\n在服务器和客户端之间还可以设置代理服务器来缓存 API 响应。这类缓存通常是透明的,对客户端和服务器都不可见。例如,反向代理服务器(如 NGINX可以作为 API 的缓存层。\n\n缓存可公开资源可以对公共 API 响应进行缓存,如公开的商品列表或新闻资讯。\n分层缓存通过多级缓存策略如 CDN、反向代理、数据库缓存确保数据尽可能来自离用户最近的缓存层。\n\nCDN 与缓存的结合\n内容分发网络 (CDN) 是缓存机制的重要组成部分特别是在全球范围内分发静态资源和减少服务器负载方面具有显著优势。CDN 是由分布在各地的节点组成的网络,能够在地理上靠近用户的节点缓存静态资源或 API 响应,从而减少延迟并提高性能。\n\n减少延迟通过将资源缓存到离用户最近的节点CDN 能够显著减少 API 请求的网络延迟,提升用户体验。\n分散负载CDN 能够将流量分散到多个节点,减轻源服务器的负载压力,特别是高并发请求时表现尤为出色。\n提高可用性即使源服务器发生故障CDN 仍可以提供缓存的内容,提高服务的可用性。通过 CDN 的分布式架构,即使某些节点发生故障,其他节点仍然可以响应用户请求,保证服务的高可用性。\n\nCDN 缓存与 API 缓存的结合\n\n静态资源缓存CDN 特别适合用于缓存静态资源如图片、CSS、JavaScript 文件)。这些资源的 URL 通常可以通过版本号或文件名哈希进行区分,确保更新时客户端获取最新版本的资源。\nAPI 响应缓存:对于某些响应时间长或查询较频繁的 API如公共数据接口CDN 可以缓存 API 的响应内容,避免每次请求都触发服务器查询。\n动态内容加速尽管 CDN 更擅长静态资源缓存但它也能加速动态内容的分发。通过边缘缓存Edge CachingCDN 可以缓存部分动态内容的响应,如用户认证后的页面,减少源服务器的压力。\n缓存失效控制在缓存内容需要及时更新或失效时合理控制缓存的生命周期至关重要。例如当数据更新时CDN 上的缓存必须失效,避免用户获取过期数据。\n\nCDN 配合缓存策略的设计\nCDN 与缓存策略的结合可以大幅提升 API 的性能。一个合理的缓存策略可能包括以下几点:\n\n短时间动态数据缓存对于变化频繁但可以短时间缓存的动态数据如新闻文章、商品列表使用 CDN 缓存几分钟或几秒钟的时间来减轻源服务器压力。\n静态资源长期缓存将静态资源通过 CDN 进行长期缓存,减少源服务器的请求压力和流量。\n分区缓存针对不同区域的用户利用 CDN 的区域缓存功能,使不同地区的用户可以更快地获取数据。\n\n限流与速率限制\n限流与速率限制是确保 API 能够在高并发情况下稳定运行的关键手段之一。通过限制客户端的请求速率,可以有效防止服务滥用、保护服务器资源,并确保在高负载时仍能保持可用性。限流机制可以通过多种策略和算法来实现,以确保 API 服务在不同场景下的性能与安全。\nAPI 限流机制的设计\nAPI 限流机制通过设置一个客户端在给定时间段内能够发出的最大请求数,来防止服务资源过度消耗并保护服务稳定性。限流不仅用于防止恶意请求,还用于确保服务质量并防止系统过载。\n常见限流策略\n固定窗口限流Fixed Window Limiting\n在一个固定时间窗口内如 1 分钟),允许客户端发出一定数量的请求。例如,允许每个客户端在 1 分钟内发出最多 100 个请求。\n简单易实现适合处理定时任务或请求负载相对稳定的场景。在时间窗口接近结束时可能会出现“突发”请求现象如在窗口结束前大量请求接着在下一个窗口开始时又发生大量请求。\n滑动窗口限流Sliding Window Limiting\n与固定窗口限流类似但将时间窗口划分为更小的时间段进行滑动更新实时跟踪请求速率。滑动窗口技术可以减少固定窗口的突发流量问题。\n可以更平滑地控制请求速率减少时间窗口边界的突发流量。实现相对复杂需要更多的内存和计算资源。\n令牌桶限流Token Bucket\n系统定期生成一定数量的“令牌”每个请求消耗一个令牌。当令牌耗尽时后续请求将被限制或延迟直到系统再次生成令牌。\n令牌桶允许一定程度的突发请求适合处理偶尔的高峰流量。如果令牌桶设计不当可能无法有效平衡突发流量与正常流量。\n漏桶限流Leaky Bucket\n将请求放入“漏桶”中桶中的请求以固定速率排出。如果请求流量超过排出的速度桶将溢出超出部分请求将被丢弃。\n确保以固定速率处理请求适合需要严格控制请求速率的场景。突发流量可能导致部分请求被丢弃。\n限流机制设计与实现\n\n基于用户/IP 的限流:限流可以根据用户的身份或客户端的 IP 地址来进行控制。比如,对于每个用户或 IP 地址,每分钟最多允许 100 个请求。如果超过这个限制API 将返回 429 Too Many Requests 错误。\n基于 API 端点的限流:对于一些资源密集型的 API如文件上传、数据处理等可以为特定的 API 端点设计更严格的限流策略。例如,文件上传 API 每个用户每分钟只能调用 10 次,而普通数据查询 API 可以放宽限流。\n动态限流动态限流机制根据系统负载和流量情况动态调整限流阈值。例如在系统压力较大时减少可接受的请求数而在负载较小时增加允许的请求数。\n\n防止服务滥用与滥发请求的策略\nAPI 限流不仅能保护服务器资源,还能有效防止恶意攻击和服务滥用。以下是一些常见的防止滥发请求的策略。\n1. 速率限制\n通过设定时间窗口内允许的最大请求数确保每个客户端只能在合理的速率内访问 API。\n\n应用对每个用户、IP 或客户端进行速率限制,控制每秒、每分钟、每小时的请求数量。如果超过阈值,返回 429 Too Many Requests 错误。\n最佳实践动态调整限流阈值根据系统的实时负载情况进行适当的调节。\n\n2. 黑白名单机制\n通过维护 IP 地址的黑名单和白名单,控制哪些客户端可以访问 API。\n\n白名单只允许白名单中的客户端访问 API。例如内部系统或受信任的合作伙伴可以通过白名单控制。\n黑名单对恶意请求的 IP 地址进行屏蔽,防止这些客户端持续向 API 发起恶意请求。\n\n3. 验证码与人机验证\n对一些频繁调用的接口如登录、注册等引入验证码防止恶意机器人自动发起请求。\n\n应用场景当检测到客户端发起大量相同请求时可以通过图形验证码或人机验证如 Google reCAPTCHA防止进一步的请求滥用。\n\n4. 动态 IP 速率限制\n对于一些恶意的 IP 地址,可以通过动态调节限流阈值的方式对其进行限制。对于短时间内发起大量请求的 IP 地址,可以临时增加请求延迟或降低请求速率。\n\n应用场景防止恶意 IP 短时间内对 API 发起大量请求攻击。\n\n5. JWT 与 API Key 的结合\n通过结合 API Key 和 JWT确保每个客户端都有唯一标识符并根据其身份和权限进行请求限制和监控。特别是在 API 网关中,可以根据不同的客户端或用户角色设置不同的速率限制策略。\nAPI 网关\n在微服务架构中API 网关是一个核心组件,它作为客户端和后端服务之间的中介,处理请求的路由、验证、安全、负载均衡等操作。通过 API 网关,可以集中管理多个微服务的访问,简化系统架构并增强安全性和扩展性。本节将介绍 API 网关的概念、功能及常见工具。\nAPI 网关是什么\nAPI 网关 是一种位于客户端和后端服务之间的反向代理服务,客户端所有的请求都会首先经过 API 网关,再由网关将请求路由到合适的后端服务。它作为微服务架构的入口点,提供统一的请求处理机制,包括路由转发、身份验证、速率限制、负载均衡等功能。\n在传统的单体架构中客户端通常直接与服务器进行交互。然而在微服务架构中不同的服务可能具有独立的 API 接口。API 网关通过将这些分散的接口聚合到一个统一的入口,简化了客户端与后端微服务之间的交互。\nAPI 网关的作用\n\n统一入口API 网关为所有微服务提供一个统一的入口,客户端不需要知道后端服务的具体地址,只需通过网关访问。\n隔离复杂性通过 API 网关,后端服务的实现细节(如服务地址、通信协议等)对客户端透明,减少了客户端与微服务之间的耦合。\n增强安全性API 网关通常集成了身份验证和授权机制,确保只有合法的请求可以访问后端服务。\n流量管理API 网关可以进行流量监控、负载均衡和限流,确保服务的高可用性和性能。\n\nAPI 网关的功能\nAPI 网关具有多种功能主要包括请求路由、负载均衡、身份验证、速率限制、缓存、监控和日志记录等。通过这些功能API 网关不仅简化了客户端的请求管理,还提供了服务的安全性和可扩展性。\n1. 请求路由\nAPI 网关的核心功能之一是请求路由。它根据客户端的请求路径或其他请求信息(如 HTTP 头、请求参数等将请求转发给对应的后端微服务。通过灵活的路由规则API 网关可以实现动态请求转发。\n\n\n功能将客户端的请求分发到合适的后端服务根据请求 URL 路径、HTTP 方法、查询参数等条件路由请求。\n\n\n示例\n\n请求 /users 路由到用户服务。\n请求 /orders 路由到订单服务。\n\n\n\n2. 负载均衡\nAPI 网关可以在多个后端服务实例之间分发请求,确保服务负载均衡。负载均衡可以通过轮询、最小连接数、响应时间等策略实现。\n\n\n功能将流量均匀地分配到不同的服务实例避免某一实例过载。\n\n\n常用负载均衡策略\n\n\n轮询法依次将请求分配给不同的服务实例。\n\n最小连接法将请求发送给当前连接数最少的服务实例。\n\n\n\n响应时间法将请求发送给响应最快的服务实例。\n\n\n3. 身份验证与授权\nAPI 网关可以负责用户的身份验证与授权,例如集成 OAuth 2.0 或 JWTJSON Web Token认证机制。在请求到达后端服务之前网关可以先验证请求的合法性确保只有授权用户才能访问特定资源。\n\n功能通过集成认证机制如 OAuth 2.0、JWT、API Key 等),对请求进行身份验证和授权。\n应用场景如确保只有已登录用户才能访问用户信息 API或限制某些用户组的访问权限。\n\n4. 速率限制与限流\n为了防止服务滥用和过载API 网关可以根据客户端的身份或 IP 进行速率限制。它限制客户端在指定时间窗口内发送的请求数量,从而保护后端服务免受恶意攻击或流量突增的影响。\n\n功能对每个客户端进行速率限制限制每秒、每分钟的请求数量。如果超过限额返回 429 Too Many Requests。\n应用场景如每个用户每分钟最多发起 100 次请求,超过后需要等待下一分钟才能继续请求。\n\n5. 缓存\nAPI 网关可以对静态响应或不常变化的数据进行缓存,从而减少对后端服务的请求次数,提高系统性能。通过缓存策略,网关可以根据请求的 Cache-Control、ETag 等头信息来决定是否使用缓存。\n\n功能缓存常用的响应数据减少后端服务的负载提升 API 响应速度。\n应用场景如对静态数据如配置文件、用户偏好进行缓存避免重复请求。\n\n6. 监控与日志记录\nAPI 网关可以记录每个请求的详细日志包括请求路径、响应时间、HTTP 状态码等。通过这些日志数据,开发者可以监控 API 的使用情况,及时发现性能问题或安全漏洞。\n\n功能记录和监控每个请求的详细信息生成 API 的性能和使用报告。\n应用场景如追踪 API 调用的频率,监控某个服务的异常情况或高延迟。\n\n常见的 API 网关工具\n目前市面上有多种 API 网关工具,它们提供了不同的功能和特性,适合各种规模的微服务架构。以下是几款常见的 API 网关工具及其特点:\n1. Kong\nKong 是一个基于 NGINX 的开源 API 网关,具有高性能、易扩展的特点。它提供了丰富的插件系统,支持身份验证、日志记录、限流、缓存等功能。\n\n强大的插件系统Kong 提供了大量内置插件,开发者可以根据需要添加认证、速率限制、负载均衡等功能。\n高性能Kong 基于 NGINX能够处理高并发的请求适合高流量场景。\n易于集成Kong 通过数据库或无数据库模式运行,适合多种应用场景。\n\n2. Apigee\nApigee 是 Google 提供的企业级 API 网关平台,支持 API 的全生命周期管理。它提供了 API 设计、开发、监控、分析、流量管理等功能,主要面向企业级用户。\n\n强大的分析功能Apigee 提供了详细的 API 分析和监控报告,可以帮助企业全面了解 API 的使用情况和性能。\n集成安全功能Apigee 提供内置的安全功能,包括身份验证、授权、加密等,确保 API 的安全性。\n支持 API 生命周期管理从设计、开发到发布、管理Apigee 提供了全套工具来管理 API。\n\n3. NGINX\n简介NGINX 是一个轻量级的高性能 HTTP 服务器和反向代理服务器,广泛应用于 Web 服务器、负载均衡器等场景。NGINX 还可以通过配置成为一个简单的 API 网关,处理路由、负载均衡、速率限制等功能。\n\n高性能NGINX 以其极高的并发处理能力著称,适合高流量场景。\n灵活的配置NGINX 的配置灵活,开发者可以根据需求自定义路由规则、限流策略等。\n广泛应用NGINX 是一个成熟的解决方案,拥有大量的社区支持和文档资源。\n\n工具比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能KongApigeeNGINX开源/商业开源商业开源扩展性插件系统丰富企业级集成灵活配置性能高性能(基于 NGINX企业级性能高性能分析工具基本分析高级分析无内置分析适用场景大规模微服务企业级 API 管理轻量级网关\nAPI 测试策略\nAPI 测试是确保 API 功能、性能、安全性和稳定性的重要环节。通过不同类型的测试,可以覆盖从基础功能到系统集成再到整体性能的不同层面,确保 API 在不同条件下表现良好。本节将讨论 API 的单元测试、集成测试和端到端测试,并介绍常用的自动化测试工具及其使用方法,同时探讨性能测试与安全性测试的必要性及其实施方法。\n单元测试、集成测试与端到端测试的区别与实现\nAPI 测试可以根据不同的测试层级划分为单元测试、集成测试和端到端测试。每种测试类型都针对不同的系统层次,发挥不同的作用。\n单元测试Unit Testing\n单元测试是针对 API 中最小的功能单元(如函数、方法)的测试,确保每个单元模块能够按预期执行。它通常是最底层的测试,覆盖代码的具体实现。\n\n\n作用验证 API 内部逻辑的正确性,发现低层次的逻辑错误和边缘情况。\n\n\n工具使用编程语言的内置测试框架如 JavaScript 中的 Mocha、Python 的 unittest 或 pytest、Java 的 JUnit 等。\n\n\n示例\n\n测试单个 API 端点中的数据处理函数,确保输入输出符合预期。\n检查错误处理逻辑是否在边缘情况下能正确返回错误响应。\n\n\n\n实现方法\n# Python 中的单元测试示例\nimport unittest\nfrom my_api import calculate_total\n \nclass TestMyAPI(unittest.TestCase):\n def test_calculate_total(self):\n result = calculate_total(100, 0.1)\n self.assertEqual(result, 110)\n集成测试Integration Testing\n集成测试是在不同模块或服务之间进行的测试验证它们的交互是否正常工作。在微服务架构中集成测试尤为重要因为 API 通常依赖外部服务,如数据库、缓存系统、第三方 API。\n\n\n作用验证 API 各个组件之间的交互,如数据库连接、第三方服务调用、微服务之间的通信等。\n\n\n工具集成测试可以使用 API 测试工具(如 Postman、Insomnia或编程语言的测试框架。\n\n\n示例\n\n测试 API 端点是否能成功写入数据库并返回正确响应。\n验证服务间调用是否在正常情况下返回预期结果。\n\n\n\n实现方法\n// 使用 Mocha 进行集成测试\nconst request = require('supertest');\nconst app = require('../app');\n \ndescribe('API Integration Test', () => {\n it('should create a new user in the database', async () => {\n const res = await request(app)\n .post('/users')\n .send({name: 'John', email: 'john@example.com'});\n expect(res.statusCode).toEqual(201);\n expect(res.body).toHaveProperty('id');\n });\n});\n端到端测试End-to-End Testing, E2E\n端到端测试是对整个应用系统进行的完整性测试确保从客户端到后端的整个流程都能按预期工作。它模拟真实用户行为覆盖系统的各个方面通常包括前端、后端、数据库和外部依赖。\n\n\n作用确保用户能够通过 API 完成从请求到响应的完整操作流程,捕捉系统级别的错误。\n\n\n工具常用工具包括 Cypress、Selenium用于测试 API 和 UI 的交互Postman 也可以用于端到端 API 测试。\n\n\n**示例:**模拟用户登录并获取个人信息,通过 API 端点从数据库中提取数据并返回给用户。\n\n\n实现方法\n// 使用 Cypress 进行端到端测试\ndescribe('User Login Flow', () => {\n it('should log in a user and fetch profile data', () => {\n cy.request('POST', '/login', {username: 'user1', password: 'password'})\n .then((response) => {\n expect(response.status).to.eq(200);\n const token = response.body.token;\n \n cy.request({\n method: 'GET',\n url: '/profile',\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n }).then((profileResponse) => {\n expect(profileResponse.status).to.eq(200);\n expect(profileResponse.body).to.have.property('username', 'user1');\n });\n });\n });\n});\n自动化 API 测试工具\n自动化测试工具使得开发者可以快速高效地对 API 进行功能测试、集成测试和端到端测试。以下是一些常用的 API 自动化测试工具及其特点:\nPostman\nPostman 是一个广泛使用的 API 开发和测试工具,支持 API 端点的自动化测试。Postman 提供了用户友好的界面,允许开发者定义请求、测试响应并自动化测试流程。\n\n支持 REST、GraphQL 和 SOAP API 测试。\n提供 API 测试套件和测试脚本,可以将测试用例组装成完整的测试流程。\n支持环境变量、集合和测试结果报告。\n\nPostman 测试脚本示例:\n# Postman 发送 POST 请求到登录接口,并验证响应状态码和 Token 是否正确返回。\npm.test("Status code is 200", function () {\n pm.response.to.have.status(200);\n});\n \npm.test("Response has token", function () {\n var jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property('token');\n});\nSwagger/OpenAPI\nSwagger 是一个 API 文档生成和测试工具,基于 OpenAPI 规范。通过 Swagger UI可以自动生成交互式 API 文档,并直接通过页面测试 API。\n\n提供交互式 API 文档,可以通过文档界面直接测试 API 请求。\n支持自动生成 OpenAPI 文档,便于 API 文档与测试的同步。\n开发者可以通过 Swagger UI 测试 API 的功能和返回结果。\n\nInsomnia\nInsomnia 是一个开源的 API 客户端工具,支持 REST、GraphQL 和 WebSocket 的测试。与 Postman 类似,它可以帮助开发者对 API 进行自动化测试和调试。\n\n简单直观的界面适合快速测试 API。\n支持编写测试脚本测试请求响应的正确性。\n支持 GraphQL API 测试。\n\n性能测试与安全性测试\n性能测试\n性能测试旨在评估 API 在不同负载下的响应时间、吞吐量和稳定性,确保 API 在高并发和大流量情况下表现良好。\n常用工具\n\nJMeter用于模拟大量并发请求测试 API 的性能表现。它可以监测响应时间、错误率等性能指标。\nLocust基于 Python 的负载测试工具,可以模拟大量用户对 API 的并发访问。\nk6轻量级的性能测试工具支持 HTTP 协议测试,特别适用于微服务架构。\n\n实施方法\n\n定义测试场景明确 API 的性能要求,设定并发用户数、请求速率等测试条件。\n执行压力测试使用工具模拟不同的负载场景观察 API 在高并发下的响应时间和错误率。\n分析结果通过工具生成的性能报告分析系统瓶颈并优化数据库查询、缓存策略或 API 设计。\n\n安全性测试\n安全性测试的目的是发现 API 的潜在漏洞,确保 API 不受常见攻击(如 SQL 注入、XSS、CSRF 等)的影响,并对敏感数据提供保护。\n常用工具\n\nOWASP ZAP开源的 Web 应用安全测试工具,支持对 API 进行自动化安全扫描。\nBurp Suite专业的 Web 安全测试工具,能发现 API 中的潜在安全漏洞。\n\n实施方法\n\n模拟攻击使用工具进行自动化漏洞扫描尝试模拟常见攻击手段如 SQL 注入、XSS 攻击、身份验证绕过等。\n验证安全策略检查 API 的身份验证、授权机制,确保敏感数据传输时使用了加密协议(如 HTTPS。\n分析并修复漏洞分析安全测试报告修复 API 中的潜在安全漏洞。\n\nAPI Mocking 与 Stub\n在 API 的开发和测试过程中Mocking 和 Stub 是常用的技术,能够**帮助开发者模拟 API 的行为,从而实现独立开发与测试。**这些技术不仅加快了开发进度,还能避免对实际服务的依赖,尤其是在后端服务尚未完成或难以访问时。通过 API Mocking 和 Stub开发者可以在没有完整后端的情况下进行前端开发或集成测试。\nMockServer 和 WireMock 是两种常用的 API Mocking 工具,能够通过模拟 API 的行为,为开发和测试提供虚拟服务。这些工具允许开发者定义 API 的响应,提供模拟的 HTTP 请求和响应,帮助独立开发者在没有完整后端的情况下进行测试。\nMockServer\nMockServer 是一个功能强大的工具,支持模拟 HTTP 和 HTTPS API。开发者可以使用 MockServer 来模拟 RESTful API并且它能够动态生成模拟响应、验证请求还支持集成测试的场景。\n主要功能\n\n模拟 HTTP/HTTPS 响应:可以根据不同的请求条件,动态返回预定义的响应数据,模拟各种 API 场景。\n请求验证可以记录和验证传入的 HTTP 请求,以确保客户端发送了正确的请求。\n集成测试支持MockServer 可以与不同的测试框架集成,如 JUnit、Testing 等,方便进行自动化集成测试。\n\n# 在 MockServer 中模拟一个用户 API 的响应:\nnew MockServerClient("localhost", 1080)\n .when(\n request()\n .withMethod("GET")\n .withPath("/users/123")\n )\n .respond(\n response()\n .withStatusCode(200)\n .withBody("{ \\"id\\": 123, \\"name\\": \\"John Doe\\" }")\n );\n当客户端发送 GET 请求到 /users/123 时MockServer 将返回包含用户信息的模拟 JSON 响应。\nWireMock\nWireMock 是一个强大且简单易用的 API Mocking 工具,广泛应用于前端开发和自动化测试中。它可以模拟 API 的各种行为,允许开发者定义不同的请求和响应,并提供灵活的配置选项。\n主要功能\n\n模拟静态和动态响应可以为特定的 URL 和 HTTP 方法设置固定的响应,或者根据请求参数生成动态响应。\n请求记录与重放可以记录实际请求并重放帮助测试复杂的场景。\n集成测试WireMock 可以嵌入到测试中,作为独立的 Mock Server帮助实现 API 的自动化测试。\n\n# 使用 WireMock 模拟一个 POST 请求响应:\nstubFor(post(urlEqualTo("/login"))\n .willReturn(aResponse()\n .withStatus(200)\n .withHeader("Content-Type", "application/json")\n .withBody("{ \\"token\\": \\"abc123\\" }")));\n当客户端发送 POST 请求到 /login 时WireMock 将返回包含 token 的模拟 JSON 响应。\nMockServer 与 WireMock 的对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度MockServerWireMock灵活性高支持复杂的动态响应、请求验证、基于条件的行为及复杂的响应逻辑简单易用适合常见的模拟场景支持基本的请求匹配和响应集成性与多种测试框架JUnit、Testing、Maven、Gradle集成支持多语言Java、JavaScript、C# 等)集成与 Java 生态系统集成紧密,支持 Spring Boot 和 JUnit主要专注于 Java 应用程序应用场景适用于复杂的集成测试、动态模拟场景、微服务和 API 网关的测试适合前端开发、简单 API 测试和 RESTful 服务模拟性能性能高效,支持大规模、高并发测试场景性能较优,适合常规的开发和测试,适用中小规模的场景动态响应支持复杂的动态响应,可以通过脚本、回调等生成自定义的响应数据支持静态响应,动态响应的支持较有限,需要通过扩展或插件实现请求验证高度灵活的请求验证机制,支持多种条件(如查询参数、头部、内容)支持基本的请求验证,适合一般的 RESTful API 请求的验证可扩展性高度可扩展,可以通过自定义代码和插件轻松扩展功能可扩展性较好,支持通过插件实现部分扩展功能,但复杂度较高协议支持支持 HTTP、HTTPS、WebSocket、TCP 等多种协议主要支持 HTTP 和 HTTPS其他协议支持较少文档与社区支持文档较全社区支持良好适合高级用户使用文档详尽社区活跃适合初学者和中级开发人员使用模拟请求速率支持控制请求的处理速率适合模拟复杂的网络条件速率控制能力有限主要用于简单场景的网络模拟错误处理与容错提供高级错误处理和容错机制支持模拟服务降级和异常场景提供基本的错误模拟但复杂的错误场景需要额外定制化部署与配置可以独立运行也可以通过 Docker、Kubernetes 集成到 CI/CD 流程中可独立运行或集成到 Java 项目中,支持 Docker但不如 MockServer 灵活日志与调试提供丰富的日志与调试工具,支持详细的请求/响应记录支持基础的日志记录和调试功能,适合简单的调试需求学习曲线学习曲线较陡,适合高级用户和复杂测试场景学习曲线平缓,适合初学者和中小规模测试项目\nRESTful API 测试的最佳实践\nRESTful API 测试是确保 API 功能健全、稳定性强和应对各种边界情况的重要环节。通过编写高效的测试用例、模拟真实场景以及提高测试覆盖率,开发者可以确保 API 的正确性、性能和安全性。本节将介绍编写有效 API 测试用例的最佳实践,如何模拟复杂的真实世界 API 交互场景,以及评估测试覆盖率与代码质量的方法。\n编写有效的 API 测试用例\n编写有效的 API 测试用例需要确保全面覆盖 API 的不同功能和场景,包括关键路径、边界条件和异常情况。以下是编写高质量 API 测试用例的最佳实践:\n1. 确保完整的用例覆盖\n\n功能测试针对 API 的每个端点编写功能测试,确保它们按照预期返回正确的响应。例如,对于一个用户登录的端点,测试其输入正确的用户名和密码时是否返回正确的身份验证 Token。\n边界条件测试确保测试包括边界条件如空输入、极端数值、超长字符串等。例如测试用户输入过长的用户名是否能够正确处理并返回合理的错误响应。\n异常处理测试模拟可能的错误情况测试 API 如何处理各种异常,例如无效的参数、丢失的参数、无权限访问、服务器错误等。\nHTTP 方法测试:针对每个 API 端点的不同 HTTP 方法(如 GET、POST、PUT、DELETE编写测试用例确保每种方法的响应行为符合 RESTful 标准。\n\n2. 使用数据驱动测试\n\n参数化测试通过使用多组测试数据驱动测试用例以确保 API 能够处理各种输入和场景。例如,使用不同的用户角色和权限来测试访问控制逻辑。\n测试边缘情况包括最大最小值、空数据、特殊字符等极端情况。\n\n3. 验证响应的准确性\n\nHTTP 状态码:测试 API 是否返回了正确的状态码,如 200 OK、201 Created、400 Bad Request、404 Not Found 等。正确的状态码是 RESTful API 的重要特性。\n响应体结构验证 API 返回的 JSON 或 XML 响应体的结构是否正确,是否包含所需的字段,并确保字段类型和格式符合预期。\n\n4. 测试幂等性\n\nPUT/DELETE 请求的幂等性:对于需要多次调用的请求(如 PUT 或 DELETE测试其幂等性确保多次执行相同请求不会产生副作用。例如多次 DELETE 请求应该返回相同的响应,而不会导致重复删除。\n\n如何模拟真实世界场景中的 API 交互\n在测试 API 时,模拟真实的使用场景非常重要。真实世界的 API 交互往往更加复杂,需要处理多服务之间的调用、用户角色和权限管理、并发请求等多种情况。\n1. 场景测试与事务流\n\n多步骤操作测试模拟实际应用中的多步骤操作如用户注册、登录、修改配置、查看数据等场景。每一步的测试不仅要验证结果还要确保前后步骤间的状态保持一致。\n事务流测试模拟典型的事务流例如在电商网站中测试用户浏览商品、添加购物车、结账和支付的全过程。\n\n2. 并发测试\n\n模拟并发请求在真实的生产环境中API 往往要处理多个用户的并发请求。编写测试用例,模拟多个客户端同时请求同一个 API确保 API 在并发场景下的稳定性和正确性。例如,测试库存系统在高并发情况下的响应时间和准确性。\n测试数据一致性并发操作可能会引发数据一致性问题尤其是在涉及数据库写操作时。测试用例应检查并发写入是否导致数据冲突或丢失。\n\n3. 权限和角色测试\n\n模拟不同用户角色的请求测试 API 如何根据不同的用户角色控制资源的访问权限。例如,管理员可以查看和修改所有用户数据,而普通用户只能查看和修改自己的数据。通过角色模拟测试,确保 API 的访问控制逻辑严格遵循设计。\n\n4. 依赖服务的模拟\n\n使用 Mock 和 Stub 模拟依赖服务:在 API 测试中,很多服务可能依赖第三方 API、数据库或外部微服务。通过 Mock 和 Stub模拟这些依赖的行为确保测试的独立性且不会因为依赖服务的不可用性影响测试。\n延迟和错误注入模拟网络延迟、外部服务失败等场景确保 API 能够优雅地处理超时和错误情况。\n\n测试覆盖率与代码质量的衡量\n测试覆盖率和代码质量是衡量 API 测试有效性的关键指标。高测试覆盖率能够确保系统的各个部分都得到了测试,但不仅要关注测试覆盖率的数量,更要关注测试的深度和有效性。\n1. 测试覆盖率的评估方法\n\n代码覆盖率Code Coverage通过统计代码被测试的百分比了解测试是否覆盖了代码中的所有分支、逻辑路径。通常使用工具如 IstanbulJavaScript、Coverage.pyPython等生成代码覆盖率报告。\n分支覆盖率Branch Coverage确保代码中所有条件分支如 if-else 语句)都被测试,避免遗漏某些逻辑路径。\n功能覆盖率Functional Coverage确保 API 的所有功能都得到了充分测试,涵盖了常规操作、异常处理、边界条件等。\n\n2. 确保 API 的高质量\n\n结合单元测试、集成测试与端到端测试通过多层次的测试来覆盖不同级别的 API 逻辑,从单个函数的正确性到整个系统的功能。\n定期执行回归测试在 API 迭代更新时,确保新增的功能没有破坏已有功能。自动化的回归测试可以快速验证所有核心功能是否正常工作。\n测试敏捷性确保测试用例的运行效率尤其是在 CI/CD 流程中,测试时间越短,反馈越快,有助于提高开发效率。\n\n3. 代码质量的衡量\n\n错误检测与调试高质量的测试应该能够捕获 API 中的各类异常,包括边界条件、错误输入等,并给出详细的错误信息,帮助调试和修复。\n自动化测试集成将测试自动化集成到 CI/CD 流程中,确保每次代码提交后都自动运行测试,并生成覆盖率报告和质量评估。\n静态代码分析工具通过静态代码分析工具如 ESLint、SonarQube确保代码的可读性、可维护性并检测潜在的错误。\n\n容器化与微服务架构\n容器化技术和微服务架构已经成为现代软件开发的主流方式。通过将 RESTful API 容器化并采用微服务架构开发团队能够实现高扩展性、易维护性和强大的部署灵活性。Kubernetes 作为容器编排工具,进一步提升了管理和部署微服务的能力。\nDocker\nDocker 是一个开源的容器化平台,允许开发者将应用及其依赖打包成容器。容器具有轻量级、可移植性和隔离性等特点,非常适合现代分布式和云端环境。\n\n可移植性Docker 容器可以在不同的操作系统和平台上运行,确保 API 在开发、测试和生产环境中行为一致。\n一致性通过 Docker 容器API 及其所有依赖(如操作系统库、应用依赖)都可以打包在一起,避免了“开发环境和生产环境不一致”的问题。\n轻量化和资源效率与虚拟机相比Docker 容器更加轻量,占用更少的系统资源,因此非常适合大规模微服务部署。\n\n容器化 RESTful API 的具体步骤\n容器化一个 RESTful API 主要包括编写 Dockerfile、构建容器镜像并运行容器。这些步骤可以确保 API 在任何支持 Docker 的环境中运行。\n\n\n编写 Dockerfile Dockerfile 是定义容器镜像构建过程的脚本,包含基础镜像、安装依赖、配置环境等步骤。\n# 选择基础镜像\nFROM node:14\n \n# 设置工作目录\nWORKDIR /usr/src/app\n \n# 复制 package.json 并安装依赖\nCOPY package*.json ./\nRUN npm install\n \n# 复制项目源代码\nCOPY . .\n \n# 暴露端口\nEXPOSE 3000\n \n# 启动应用\nCMD ["npm", "start"]\n\n\n构建容器镜像 通过 Docker 构建命令创建镜像。\ndocker build -t my-restful-api .\n\n\n运行容器 使用 docker run 命令启动容器并运行 RESTful API。\ndocker run -p 3000:3000 my-restful-api\n\n\nKubernetes\nKubernetesK8s 是一个开源的容器编排平台负责自动化部署、扩展和管理容器化应用。Kubernetes 提供了强大的容器调度和管理能力,能够处理大规模的容器集群。\n\nPodKubernetes 中最小的部署单元,一个 Pod 可以包含一个或多个容器,通常运行同一个应用程序。\nNodeKubernetes 集群中的工作节点,每个节点上运行一个或多个 Pod。\nCluster由多个节点组成的 Kubernetes 集群,负责运行容器化的应用程序。\nService用于定义 Pod 的访问策略,支持负载均衡和服务发现。\nDeployment用于声明和管理应用程序的期望状态如运行多少个副本如何进行滚动更新等。\n\n在 Kubernetes 中部署 RESTful API\n在 Kubernetes 中,微服务 API 可以通过 YAML 文件定义并部署到集群中。通常涉及以下步骤:\n\n\n编写 Deployment 文件: Deployment 文件定义了 API 应用的期望状态,比如容器镜像、资源配置和副本数量。\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: api-deployment\nspec:\n replicas: 3\n selector:\n matchLabels:\n app: api\n template:\n metadata:\n labels:\n app: api\n spec:\n containers:\n - name: api-container\n image: my-restful-api:latest\n ports:\n - containerPort: 3000\n\n\n创建 Service 文件Service 文件用于暴露 Pod让外部客户端能够访问 API。\napiVersion: v1\nkind: Service\nmetadata:\n name: api-service\nspec:\n selector:\n app: api\n ports:\n - protocol: TCP\n port: 80\n targetPort: 3000\n type: LoadBalancer\n\n\n部署到 Kubernetes 集群:使用 kubectl 命令将 API 部署到 Kubernetes 集群中:\nkubectl apply -f deployment.yaml\nkubectl apply -f service.yaml\n\n\nKubernetes 的应用场景\n\n自动扩展Kubernetes 可以根据负载自动扩展或缩减 API 副本,确保服务稳定性和资源高效利用。\n滚动更新与回滚通过 Kubernetes可以平滑地进行 API 版本更新,并在出现问题时快速回滚到之前的版本。\n高可用性Kubernetes 通过多副本部署和服务自动恢复机制,确保 API 的高可用性。\n\n微服务与 API 网关\nAPI 网关的作用\n在微服务架构中API 网关是系统的入口点,负责将客户端请求转发到不同的微服务。它提供了负载均衡、身份验证、限流等功能,同时简化了客户端与后端服务的交互。\n\n统一入口API 网关为所有微服务提供了一个统一的访问入口,简化了客户端与多个微服务的通信。\n服务发现与负载均衡API 网关可以根据微服务的状态动态地发现服务,并为每个请求分配最佳的服务实例。\n安全与身份验证通过 API 网关可以统一处理所有的身份验证和授权逻辑,减少每个微服务的安全负担。\n\n常见 API 网关工具与 Kubernetes 集成\n\nKongKong 是一个开源的 API 网关,支持与 Kubernetes 集成,能够动态发现并管理 Kubernetes 中的微服务。\nNGINX作为反向代理服务器NGINX 也常用于微服务架构中,支持负载均衡、缓存和限流功能。\nIstioIstio 是 Kubernetes 上的服务网格,提供 API 网关功能,负责服务间的流量管理、监控、认证和加密。\n\n集成示例\n假设一个微服务架构中有多个 API 服务API 网关通过路径路由将请求转发到不同的微服务。例如 /users 请求转发到用户服务,/orders 请求转发到订单服务。\nKong 配置示例:\napiVersion: configuration.konghq.com/v1\nkind: KongIngress\nmetadata:\n name: api-gateway\nproxy:\n path: /users\n service: user-service\n---\napiVersion: configuration.konghq.com/v1\nkind: KongIngress\nmetadata:\n name: order-gateway\nproxy:\n path: /orders\n service: order-service\nAPI 网关的好处\n\n解耦客户端与微服务API 网关屏蔽了客户端与多个微服务直接交互的复杂性,客户端只需与 API 网关进行通信。\n增强安全性通过 API 网关集中管理身份验证、限流、SSL 终结等安全功能,减少每个微服务的负担。\n性能优化API 网关可以实现缓存、速率限制和负载均衡,优化系统性能并确保服务稳定。\n\n无服务器架构与 RESTful API\n无服务器架构Serverless是近年来兴起的一种新型计算模式它允许开发者在无需管理服务器基础设施的情况下直接编写代码并部署功能。Serverless 架构特别适用于 RESTful API 的开发,因为它提供了按需自动扩展、事件驱动的高效计算方式。本节将介绍无服务器架构的基本概念、如何使用 AWS Lambda 等工具部署 API以及其局限性和适用场景。\n无服务器架构Serverless\nServerless 架构的基本概念\nServerless 架构 是一种云计算执行模型,开发者不再需要管理服务器和基础设施,而是将应用代码作为“函数”上传到云平台,由平台自动负责资源分配、扩展和管理。尽管称为“无服务器”,实际上底层仍然有服务器,只是服务器的管理完全被云服务提供商抽象化和自动化。\n\n事件驱动Serverless 函数基于事件触发执行,例如 HTTP 请求、数据库更新或文件上传。\n自动扩展Serverless 服务按需自动扩展资源,在流量高峰时能够无缝扩展,而在流量较小时自动缩减资源使用。\n按使用付费用户只为函数的实际执行时间付费而不必为闲置的服务器资源支付费用。\n\n无服务器架构在 API 开发中的应用\n在 API 开发中,无服务器架构非常适合构建高并发、事件驱动的 RESTful API。每个 API 端点可以被设计为一个独立的函数,按需触发并执行。例如,通过 HTTP 请求触发 AWS Lambda 函数,从而实现快速、高效的 API 响应。\n\n动态内容生成Serverless 函数可以处理 HTTP 请求,生成动态内容返回给用户。\n事件响应API 端点可以响应不同的事件触发(如用户创建、订单处理、文件上传)。\n微服务支持Serverless 支持将 API 设计为一系列独立的服务,便于扩展和管理。\n\n无服务器架构的局限性与应用场景\n局限性\n\n冷启动延迟当无服务器函数长时间未被调用时下次调用可能需要几百毫秒的冷启动时间可能会影响对响应速度要求较高的应用。\n无状态性Serverless 函数是无状态的,这意味着如果应用需要维持用户会话或长时间的任务处理,可能需要额外的状态管理服务(如 Redis、DynamoDB 等)。\n调试困难与传统架构相比调试和监控 Serverless 函数更加复杂,尤其是在复杂的微服务系统中。\n复杂性上升随着系统规模扩大管理多个函数、事件流和服务之间的通信可能变得更加复杂。\n\n应用场景分析\n无服务器架构非常适合以下场景\n\n按需计算当 API 流量波动较大时Serverless 能够自动扩展和缩减资源,非常适合这种按需计算的应用。\n事件驱动系统无服务器架构擅长处理事件驱动的系统例如文件上传、实时数据处理、日志分析等场景。\n快速开发和原型由于 Serverless 无需管理底层基础设施,开发者可以专注于业务逻辑,快速开发并发布原型。\nAPI 微服务架构对于设计为多个独立功能模块的微服务架构Serverless 可以轻松实现各模块的独立部署和管理。\n\n不适合的场景\n\n低延迟、高并发的实时系统对于需要持续高性能、低延迟的系统Serverless 的冷启动延迟可能会影响性能。\n长时间任务处理Serverless 函数通常有执行时间限制(如 AWS Lambda 最高 15 分钟),不适合长时间任务处理。\n\n常见安全漏洞与防护\n在现代 API 开发中,安全性是一个至关重要的问题。无论是 RESTful API 还是其他形式的 API都容易受到各种网络攻击的威胁。开发者必须意识到常见的安全漏洞并采取合适的防护措施。OWASP 提供了 Web 安全的十大常见漏洞清单,帮助开发者识别和修复这些潜在风险。\nOWASP Top 10 介绍\n**OWASP Top 10 是一个由开源安全社区 OWASP 定期发布的常见 Web 应用安全风险排行榜。**它帮助开发者和安全团队识别常见漏洞,并提供相应的防护措施。以下是 OWASP Top 10 中的常见漏洞及其在 API 开发中的防护方法:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n名称概述防护措施A01:2021 失效的访问控制未正确实施访问控制,导致攻击者可以访问未授权数据或功能。确保每个 API 端点的访问权限基于用户角色正确配置,使用强大的身份验证和授权机制如 OAuth 2.0、JWT在 API 网关层进行访问控制。A02:2021 加密失败缺乏或不正确的加密措施,导致敏感数据在传输或存储时泄露。使用 HTTPS 保障数据传输安全敏感数据加密存储采用适当的密钥管理策略确保密钥和证书的安全性。A03:2021 注入攻击包括 SQL 注入、命令注入等,通过未验证输入操纵数据库或系统命令。使用参数化查询和 ORM 防止 SQL 注入对所有输入进行严格的验证和过滤。A04:2021 不安全的设计应用设计缺陷导致系统在设计层面存在漏洞。采用安全设计模式在设计阶段进行威胁建模评估潜在的安全风险。A05:2021 安全配置错误错误配置、未更新的系统、不安全的 HTTP 头设置。定期审查和更新系统配置,禁用生产环境下不必要的服务或功能,使用安全的 HTTP 头,如 Content-Security-Policy 和 Strict-Transport-Security。A06:2021 失效的身份验证身份验证不安全导致攻击者冒充其他用户或获取未授权访问权限。使用强密码策略实施双因素身份验证2FA使用 OAuth 2.0 和 OpenID Connect 等安全身份验证机制。A07:2021 软件和数据完整性失败缺乏对代码、应用更新或第三方组件的验证导致恶意代码注入。使用签名验证机制确保软件包和数据完整性定期更新和修复第三方组件的漏洞。A08:2021 安全日志记录与监控失败缺乏日志记录或监控导致攻击活动难以检测和响应。确保记录关键操作如登录、数据访问建立实时监控和告警机制及时响应潜在攻击。A09:2021 安全代码注入包括 XML 注入、代码注入等允许执行未授权代码或操作。对输入进行严格校验和过滤避免动态执行用户提供的数据。A10:2021 服务器端请求伪造SSRF攻击者通过伪造请求访问服务器内部资源。限制外部请求的 IP 地址和端口使用防火墙和访问控制列表ACL保护内部网络资源。\n防止 SQL 注入、XSS、CSRF 的最佳实践\n在 Web API 中SQL 注入、跨站脚本攻击XSS和跨站请求伪造CSRF是常见的攻击手段开发者必须采取措施防止这些漏洞。\n防止 SQL 注入\nSQL 注入 是一种常见的攻击,攻击者通过恶意的 SQL 语句操纵数据库查询,导致数据泄露、篡改或删除。\n\n\n参数化查询使用参数化查询或预编译语句将用户输入作为参数传递给 SQL 查询,而不是直接拼接在查询字符串中。\n示例Python + SQLAlchemy\nuser = db.session.query(User).filter(User.username == username).first()\n\n\n\nORM对象关系映射使用 ORM 工具(如 Hibernate、Entity Framework、SQLAlchemy来避免直接编写 SQL 查询。\n\n\n输入验证与清理对所有用户输入进行验证和清理确保其格式符合预期不包含恶意 SQL 片段。\n\n\n防止 XSS跨站脚本攻击\nXSSCross-Site Scripting 是攻击者通过注入恶意脚本,使得这些脚本在其他用户的浏览器中执行,窃取数据或进行恶意操作。\n\n\n输出编码在返回给客户端的 HTML 中,对用户输入的内容进行输出编码,避免恶意脚本被直接解析执行。例如,使用 HTML.escape() 将特殊字符(如 < 和 `> 转换为 HTML 实体。\n<span>{{ user_input | escape }}</span>\n\n\n\n内容安全策略CSP配置 Content-Security-Policy 头,限制浏览器加载的资源来源,防止恶意脚本的执行。\n\n\n避免直接输出用户输入避免在 API 响应中直接输出未经处理的用户输入。\n\n\n防止 CSRF跨站请求伪造\nCSRFCross-Site Request Forgery 是攻击者通过伪造用户请求,强迫用户在已认证的情况下执行未授权的操作。\n\n\n使用 CSRF Token在表单或 HTTP 请求中引入唯一的 CSRF Token服务器在验证请求时检查该 Token 是否有效,防止伪造请求。\n示例\n<input type="hidden" name="csrf_token" value="{{ csrf_token }}">\n\n\n\n使用 SameSite Cookie通过设置 Cookie 的 SameSite 属性,限制浏览器在跨站请求时发送 Cookie减少 CSRF 攻击的机会。\n示例\nSet-Cookie: sessionId=abc123; SameSite=Strict\n\n\n\n双重提交 Cookie在表单提交时将 CSRF Token 作为表单字段和 Cookie 同时提交,服务器可以验证两个值是否匹配。\n\n\n使用 HTTPS 确保 API 安全\nHTTPS超文本传输协议安全 是通过 SSL/TLS 加密层在客户端与服务器之间建立安全连接,确保数据在传输过程中不会被窃听或篡改。对于 API 来说,使用 HTTPS 是确保通信安全的基础措施。\nHTTPS 的重要性\n\n加密传输通过 HTTPS 加密数据,防止传输中的数据被第三方窃听或篡改。这对于传输敏感数据(如用户登录信息、支付信息)尤为重要。\n防止中间人攻击HTTPS 通过 SSL/TLS 证书验证服务器身份,确保客户端与真实服务器通信,防止中间人攻击。\n增强信任现代浏览器和 API 客户端对没有使用 HTTPS 的请求都会发出安全警告,使用 HTTPS 有助于增强用户信任。\n\n如何在 API 中强制使用 HTTPS\n确保 API 服务器配置 SSL/TLS 证书,并强制通过 HTTPS 进行通信。可以使用 Lets Encrypt 提供的免费 SSL 证书或者从认证机构CA获取付费证书。\nserver {\n listen 443 ssl;\n server_name api.example.com;\n \n ssl_certificate /etc/nginx/ssl/example.com.crt;\n ssl_certificate_key /etc/nginx/ssl/example.com.key;\n \n location / {\n proxy_pass http://localhost:3000;\n }\n}\n如果客户端通过 HTTP 访问 API服务器应自动重定向到 HTTPS确保所有通信加密传输。\nserver {\n listen 80;\n server_name api.example.com;\n return 301 https://$host$request_uri;\n}\n配置 HTTP 严格传输安全HSTS确保浏览器始终通过 HTTPS 访问 API。\nStrict-Transport-Security: max-age=31536000; includeSubDomains; preload\n数据隐私与法规遵从\n随着隐私问题日益受到关注全球多个国家和地区出台了严格的法律法规规范数据的收集、处理和存储。在 API 开发中,确保符合数据隐私法规不仅能够保护用户数据安全,还能帮助企业避免法律风险。本节将重点介绍 GDPR 和 HIPAA 等关键法规的要求,讨论如何确保 API 数据处理、存储和日志记录的合规性。\nGDPR通用数据保护条例\nGDPR 概述\nGDPRGeneral Data Protection Regulation通用数据保护条例 是欧盟制定的关于数据隐私的法规,于 2018 年 5 月 25 日生效。它是目前最严格的隐私和安全法规之一适用于处理欧盟公民数据的公司或组织。GDPR 主要目标是保护个人数据,并赋予欧盟居民对自己数据更大的控制权。\nGDPR 对 API 数据处理和存储的影响\n在 API 开发和数据处理过程中GDPR 要求开发者和组织必须遵循严格的数据隐私和安全要求,确保用户数据得到充分保护。以下是 GDPR 的一些核心要求及其在 API 开发中的影响:\n\n\n数据最小化原则API 只应收集和处理最低限度的个人数据,避免收集与业务无关的额外信息。例如,一个用户注册 API 应该只收集用户名和邮箱地址,而不应请求与身份验证无关的敏感数据。\n\n\n合法性、透明度和公平性API 在处理用户数据时必须确保合法性,并且要对用户透明,告知他们数据将如何被使用。例如,在 API 中收集用户信息时,必须获得用户的明确同意(如通过条款同意书)。\n\n\n用户数据访问和删除权GDPR 赋予了用户访问和删除其个人数据的权利。在 API 设计中,需要提供相关功能,让用户可以请求其数据副本或要求删除其数据(“被遗忘权”)。\n实现示例创建 API 端点 /user/delete用户可以通过此端点请求删除其账户和数据。\n\n\n数据加密在传输和存储过程中API 必须确保数据的安全性,通常使用加密技术来保护数据。例如,使用 HTTPS 加密 API 通信,确保用户数据在传输过程中不会被窃听或篡改。\n\n\n数据泄露通知如果发生数据泄露组织必须在 72 小时内通知监管机构并告知受影响的用户。API 系统应具备日志和审计功能,及时发现潜在的数据泄露事件。\n\n\n实践建议\n\n数据匿名化和伪匿名化对于存储的数据可以使用数据匿名化或伪匿名化技术降低敏感数据泄露的风险。\n访问控制和权限管理确保只有授权用户和系统能够访问个人数据使用基于角色的访问控制RBAC机制。\n\nHIPAA健康保险可携性与责任法案\nHIPAA 概述\nHIPAAHealth Insurance Portability and Accountability Act健康保险可携性与责任法案 是美国联邦法律旨在保护患者的敏感健康信息。HIPAA 对存储、处理和传输医疗数据的组织如医疗提供商、保险公司等提出了严格的合规要求。任何处理或存储受保护健康信息PHIProtected Health Information的 API 都必须符合 HIPAA 规定。\nHIPAA 对 API 合规性的要求\n在处理医疗数据时HIPAA 要求 API 开发者采取一系列的技术和管理措施,确保医疗数据的安全和隐私。以下是 HIPAA 的关键合规要求及其对 API 开发的影响:\n\n\nPHI 保护API 必须确保所有涉及患者健康数据的请求和响应安全。例如,传输患者健康记录时,使用加密技术保护数据不被泄露。\n\n\n数据加密API 处理涉及医疗数据时,必须确保数据的加密,特别是在传输和存储过程中。采用 SSL/TLS 协议加密传输数据,并对数据库中的 PHI 使用 AES 或其他强加密算法。\n\n\n访问控制只有经过授权的个人和实体才能访问 PHI 数据。API 系统必须实现严格的身份验证和授权机制如基于角色的访问控制RBAC以确保不同用户只能访问符合其权限的数据。\n示例医生通过 API 查询病人数据时API 应确保只有具备访问权限的医生才能查看相关数据。\n\n\n审计与监控API 必须具备日志记录功能,记录所有与 PHI 相关的访问和更改操作。HIPAA 要求有能力追踪谁在何时访问了哪些数据。\n实现示例在 API 中记录每次数据访问和修改操作,存储操作时间、用户 ID 以及访问的资源信息。\n\n\n数据备份和恢复确保定期备份医疗数据并提供灾难恢复方案以防止数据丢失。\n\n\n业务伙伴协议BAA如果 API 提供方是一个第三方服务,则必须与其客户签署业务伙伴协议,明确双方在 PHI 处理中的责任和义务。\n\n\n实践建议\n\n强身份验证使用双因素身份验证2FA来保护对敏感医疗数据的访问。\n日志管理与审计确保所有与 PHI 相关的 API 请求都被审计,并且这些日志能够保存足够长的时间以供监管部门审查。\n\nAPI 日志记录与数据保护的合规实践\n在开发和运行 API 时,日志记录对于监控系统状态、调试问题和保障合规性至关重要。但在处理敏感数据时,必须确保日志记录符合隐私法规,防止泄露用户信息。\n日志记录的原则\n\n\n最小化数据记录在 API 日志中,避免记录过多的敏感信息。例如,不应将用户密码、完整的信用卡信息或敏感的个人健康信息记录在日志中。可以选择记录经过部分脱敏的敏感数据(如仅显示信用卡号的最后四位)。\n示例API 日志应记录用户 ID而不是记录敏感的个人数据。\n\n\n加密日志数据对于涉及敏感数据的日志建议对日志文件进行加密确保即使日志被泄露数据仍然不可读。\n\n\n访问控制限制对日志的访问权限确保只有经过授权的管理员或审核人员才能查看日志数据。\n\n\n日志存储期限根据法规要求合理设置日志的保存期限。例如GDPR 规定用户有权要求删除其个人数据,因此在处理欧洲用户的数据时,应避免长期保存敏感日志数据。\n\n\n日志记录的合规要求\n\n\nGDPR 合规日志:在欧洲数据保护框架下,日志中必须避免记录未授权的个人数据。如果日志中不可避免地包含了个人数据,必须确保这些数据经过匿名化或伪匿名化处理。\n示例对 API 请求中包含的用户身份标识进行伪匿名化处理,确保日志数据无法直接识别具体用户。\n\n\nHIPAA 合规日志:对于处理 PHI 的系统,所有访问医疗数据的操作都必须被记录,并且日志必须具备审计功能,能够追踪所有涉及 PHI 数据的活动。确保日志记录可以追踪到具体用户的操作。\n\n\n日志合规实践总结\n\n去标识化如果需要记录用户相关的操作确保日志中的个人数据经过去标识化处理避免直接暴露敏感信息。\n分级日志记录针对不同类型的数据设置不同的日志记录级别。对于高敏感度的数据可以通过日志掩码masking或加密的方式进行处理。\n自动化审计与告警使用自动化审计工具定期检查日志记录的合规性并在发生异常活动时自动告警。\n\nGraphQL、gRPC 与 REST\n随着现代 API 技术的不断发展REST、GraphQL 和 gRPC 成为三种最常用的 API 设计方案。它们各自具有独特的优势和劣势,适用于不同的应用场景。理解这些 API 设计模式的异同及其使用场景有助于开发者根据业务需求选择最佳的解决方案。\nGraphQL\nGraphQL 是由 Facebook 开发的一种查询语言,用于通过单个 API 端点提供灵活的数据查询。与 REST 不同GraphQL 允许客户端精确指定所需的字段和数据结构,从而避免了过多或不足的数据返回问题。\n\n单个端点所有请求通过同一个端点处理客户端可以根据需要指定数据字段。\n数据查询灵活客户端能够查询、嵌套和组合数据请求减少了不必要的 API 请求。\n实时更新支持支持通过 Subscription 进行实时数据推送。\n\ngRPC\ngRPC 是由 Google 开发的高性能远程过程调用RPC框架它使用 ProtobufProtocol Buffers作为接口定义语言和数据序列化格式。gRPC 支持多种通信模式,如一元 RPC、双向流式 RPC 等,适合需要高效、低延迟的应用场景。\n\n高效的二进制协议使用 Protobuf 进行数据序列化,相较于 REST 的 JSONgRPC 的数据传输更快且数据量更小。\n多语言支持gRPC 支持多种编程语言,如 C++、Java、Go、Python 等,便于跨语言通信。\n全双工流式通信支持双向流式通信客户端和服务器可以同时发送和接收消息适合实时和高频通信场景。\n\n三者对比\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n维度RESTGraphQLgRPC请求端点多个端点每个资源对应一个 URI单一端点通过查询参数灵活获取数据单一端点通过定义的服务接口进行通信数据获取客户端获取固定数据可能会出现过量或不足获取问题客户端可以精确获取所需的数据避免过量获取基于 Protobuf 序列化的高效二进制数据传输,数据精确获取实时通信需要借助其他协议(如 WebSocket实现实时通信支持通过 Subscription 进行实时数据推送支持全双工流式通信,适合高频率、低延迟的数据交换协议基于 HTTP/1.1 或 HTTP/2使用文本格式传输JSON、XML基于 HTTP/1.1,通常使用 JSON 格式传输基于 HTTP/2使用 Protobuf 二进制传输,效率更高缓存支持通过 URL 很容易实现 HTTP 缓存,缓存机制友好较难实现缓存机制,因为查询通常通过 POST 请求不支持 HTTP 缓存,需要通过外部机制实现性能优化基于 HTTP 协议,容易优化,适合轻量级场景查询复杂,灵活性高但可能带来性能问题,服务器端优化难度大高效的二进制协议,适合需要高吞吐、低延迟的场景学习曲线易于理解和实现,广泛使用,工具链成熟灵活性高,适合复杂查询,但增加了服务器的复杂性学习曲线陡峭,特别是 Protobuf 和流式通信语言支持与 HTTP 协议兼容,几乎所有语言都可以支持基于 HTTP 和 JSON几乎所有语言都能支持支持多种语言如 Java、C++、Python、Go非常适合跨语言系统工具链工具和库非常成熟易于调试和开发工具链逐渐成熟支持调试但调试复杂度较高工具支持有限二进制传输使调试较为复杂需要专用工具安全性通过基于 URL 的访问控制,支持 OAuth 和基于角色的控制必须为每个字段单独配置访问控制,安全性配置较复杂通过服务定义的访问控制,支持强类型和身份验证机制授权与访问控制基于 HTTP 方法和 URL 进行访问控制,授权机制成熟由于字段灵活性,必须实现细粒度的字段访问控制可以通过 Protobuf 服务定义进行精确的访问控制适用场景适用于静态内容、公共 API、简单的 CRUD 操作适合复杂数据查询、前端灵活请求数据的场景适合高性能、高并发的服务间通信,尤其是微服务架构缺点存在过量获取和不足获取问题,可能需要多个 API 调用查询复杂,服务器端需要处理复杂的请求优化,缓存难以实现浏览器支持有限,调试复杂,学习曲线较高\nRESTful API 与边缘计算\n边缘计算是近年来迅速发展的计算模式它将数据处理从集中式的数据中心转移到网络边缘靠近数据源的地方从而减少延迟、节省带宽并提高实时数据处理能力。RESTful API 在物联网和边缘计算中的应用日益广泛,因为它们提供了一种标准化的方式来实现设备之间的通信和分布式计算任务的协调。\n边缘计算\n边缘计算的基本概念\n边缘计算 是一种分布式计算模型,它将计算和数据存储资源从中央数据中心移至更接近数据源的网络边缘设备,如智能传感器、路由器、网关等。边缘计算的目标是通过在数据源附近处理数据,减少延迟、节省网络带宽,并提高实时响应能力。\n\n本地数据处理边缘设备可以直接处理收集到的数据而不必将所有数据都传输到远程数据中心。这种模式有助于减少数据传输量和带宽消耗。\n分布式架构边缘计算通常作为一种分布式架构的一部分计算任务在多个边缘设备上分布进行形成一个协同的计算网络。\n实时响应由于数据处理发生在接近数据源的地方边缘计算能够显著减少数据处理和响应的延迟特别适用于需要低延迟的应用场景如自动驾驶、工业控制和实时监控。\n\n边缘计算的应用领域\n\n物联网IoT在物联网环境中数百万个智能设备收集数据并与云端或数据中心通信。通过在边缘进行处理可以减少云端的负载并提高数据处理的实时性。\n智慧城市智能交通、公共安全和环境监控等应用需要快速响应的本地计算能力边缘计算能支持这些系统在本地分析数据并做出决策。\n5G 和自动驾驶:边缘计算与 5G 技术结合,支持低延迟的通信与决策,尤其适合自动驾驶汽车等需要实时数据处理和响应的场景。\n\nRESTful API 在物联网与边缘计算中的应用\nRESTful API 与边缘计算的结合\nRESTful API 是基于 HTTP 协议的一种轻量级、无状态的通信方式广泛应用于不同系统之间的交互。由于其通用性和跨平台支持RESTful API 成为物联网和边缘计算环境中设备、网关和云端之间通信的标准接口之一。\n\n轻量化通信物联网设备通常计算和存储资源有限RESTful API 的轻量化特点使其非常适合用于边缘设备之间的通信。\n标准化接口RESTful API 为不同厂商的设备和平台提供了统一的接口标准,使得跨设备和跨平台的数据交换更加简单和高效。\n无状态性由于 RESTful API 是无状态的,它非常适合在分布式环境中进行调用,每个请求都独立处理,减少了对持久连接的需求。\n\n典型应用场景\n\n物联网设备数据管理在物联网架构中成千上万个设备产生的数据可以通过 RESTful API 发送到边缘服务器进行预处理。例如,智能家居设备可以通过 REST API 将数据发送到本地的家庭网关进行处理,只有关键数据才会上传到云端。\n边缘计算节点的分布式协作在边缘计算环境中多个边缘节点可以通过 RESTful API 相互通信和协调,分担计算任务。例如,在智慧城市的监控系统中,边缘节点之间可以使用 RESTful API 共享监控数据,分布式处理视频流以减少单个节点的计算负荷。\n设备管理和监控RESTful API 可以用于远程设备管理和监控,物联网设备可以定期向边缘服务器发送健康状态报告,并通过 API 接收配置更新和指令。\n\n边缘计算对 RESTful API 设计的挑战与优化策略\n边缘计算对 API 设计的挑战\n边缘计算环境具有分散性、异构性和资源受限的特点这些特性对 RESTful API 的设计和性能提出了一系列挑战:\n\n延迟与网络不稳定由于边缘设备通常位于网络边缘网络连接可能不稳定导致 API 请求的延迟增加甚至出现请求失败的情况。API 必须具备应对高延迟和网络故障的能力。\n设备资源受限边缘设备的计算能力、存储空间和带宽有限API 必须设计得足够轻量,避免过大的数据传输和复杂的计算任务。\n安全性边缘设备分布广泛暴露在开放网络中容易成为攻击目标。API 的安全设计必须非常谨慎,尤其是在涉及敏感数据的物联网场景中。\n高并发与扩展性边缘计算系统通常需要处理大量的设备和数据请求API 必须能够支持高并发和快速扩展,以应对数据量的增长和请求的激增。\n\n优化 RESTful API 以适应边缘计算环境的策略\n为了适应边缘计算环境的挑战可以采用以下优化策略来提高 RESTful API 的性能和可靠性:\n\n\n减少数据传输量通过压缩传输数据或者通过使用更加紧凑的数据格式如 Protobuf 代替 JSON可以减少带宽消耗提升 API 响应速度。\n优化示例 使用 Protobuf 代替 JSON 作为数据格式,通过更高效的二进制编码减少传输量。\n\n\n使用本地缓存与重试机制为了应对网络不稳定API 客户端可以实现本地缓存和请求重试机制。边缘设备可以在网络不稳定时先缓存数据,待网络恢复后再批量发送到服务器。\n优化示例 边缘设备可以将传感器数据缓存本地,在网络恢复时批量发送到边缘服务器,避免丢失数据。\n\n\n异步通信与事件驱动架构在边缘环境中使用异步通信机制如 WebSocket 或基于事件驱动的架构)可以提高系统的实时性和响应能力,减少 RESTful API 传统的请求 - 响应模式下的延迟。\n优化示例 使用 MQTT 或 WebSocket 进行事件驱动通信,减少 HTTP 请求的开销。\n\n\n安全性增强措施在边缘计算环境中API 需要采取更严格的安全措施,如使用 HTTPS 加密通信、OAuth2.0 进行认证以及基于角色的访问控制RBAC以防止恶意攻击和数据泄露。\n优化示例 对每个 API 调用进行强身份验证,并使用 HTTPS 进行加密,确保通信安全。\n\n\n微服务架构与服务拆分边缘计算可以采用微服务架构将不同的功能模块拆分为小的服务单元通过 RESTful API 进行通信和协调,减少单一服务的负载,并提高系统的扩展性和可维护性。\n优化示例 将设备监控、数据收集、故障处理等功能拆分为不同的服务单元,通过 API 进行相互协作。\n\n\n案例分析边缘计算与 RESTful API 的结合\n\n智能交通系统在智能交通系统中交通灯、摄像头和车辆传感器都可以作为边缘设备通过 RESTful API 与本地的边缘服务器进行通信。本地服务器可以实时处理交通数据,优化交通信号控制。通过本地缓存和异步通信机制,这种系统可以在网络不稳定的情况下仍然保持高效运行。\n工业物联网IIoT在智能制造环境中边缘计算可以通过 RESTful API 连接各种工业设备和传感器,实现实时数据采集和处理。边缘服务器可以直接分析传感器数据并做出响应,而不必等待云端的处理结果,从而减少延迟,提高工厂的自动化水平。\n\nRESTful API 的未来趋势\n随着现代软件架构的不断演进RESTful API 作为系统通信的核心部分也在不断发展。未来的 API 技术趋势表明API 不仅将继续在事件驱动架构和无服务器计算等领域发挥重要作用,还会与自动化和 AI 技术深度融合,以提升开发效率和系统性能。\n事件驱动 APIEvent-Driven API\n事件驱动 API 的概念\n事件驱动 APIEvent-Driven API 是一种基于事件的通信方式,当某个系统内发生特定事件时,会自动触发通知或执行相应的操作,而不是通过客户端主动请求来获取数据。这种模式常用于实时响应场景中,能够提供更高效和动态的通信机制。\n与传统的 REST API 模式不同,事件驱动 API 不需要客户端轮询或频繁发出请求,而是通过订阅事件并在事件发生时接收通知。这种架构非常适合处理实时更新的场景,如物联网设备通信、股票交易系统或聊天应用。\n事件驱动 API 的优势\n\n低延迟事件驱动架构允许客户端在事件发生时立即接收更新无需轮询减少了延迟并提高了响应速度。\n减少不必要的请求客户端不再需要频繁地发送请求去检查数据状态的变化这降低了服务器负载并提高了通信效率。\n实时性增强事件驱动 API 非常适合需要实时响应的应用场景,如金融交易、监控系统和实时消息传递。\n\n事件驱动 API 与 REST API 的区别\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n对比维度REST API事件驱动 API通信模式请求 - 响应模式,客户端主动发出请求并等待响应事件驱动模式,服务端根据事件触发,主动向客户端推送数据数据传输方式每次请求都会返回完整的响应数据,无论数据是否发生变化仅在事件发生时传递增量或变化数据,减少数据传输量实时性通过轮询或长轮询实现伪实时性,客户端需不断发起请求内置实时事件通知,客户端在事件发生时立即收到推送数据触发机制客户端主动发起请求,拉取数据服务端在事件触发时主动推送数据,客户端被动接收性能消耗客户端需频繁发送请求,可能导致带宽和服务器资源浪费减少频繁请求和带宽占用,仅在必要时发送事件复杂性实现较为简单,基于标准 HTTP 方法,适合传统应用场景事件流管理较复杂,涉及消息中间件(如 Kafka、RabbitMQ或 WebSocket 连接维护适用场景适合静态资源、单次查询、CRUD 操作等场景适合实时更新、数据推送和异步处理场景,如物联网、消息通知系统状态管理基于无状态请求,每次请求独立基于状态和事件流,服务端和客户端间可能保持连接状态数据一致性需要客户端定期发起请求才能获取最新数据,可能存在数据滞后数据一致性高,服务端推送最新数据,保持实时同步协议支持基于 HTTP/1.1 或 HTTP/2使用标准化的 HTTP 方法和状态码基于 WebSocket、Server-Sent Events (SSE),或使用消息队列扩展性随着客户端请求数量增加,服务器负载可能增加高扩展性,适合处理大量事件的异步、分布式系统可靠性高度依赖客户端的请求,客户端不请求则无法获取更新数据事件丢失可能导致数据不同步,但可以通过消息队列的持久化机制来保证可靠性带宽使用客户端需要不断请求,即使没有数据更新仅在事件发生时推送数据,带宽使用更高效调试与开发工具工具链成熟,调试简单,广泛支持(如 Postman、Insomnia工具较为有限调试复杂需要支持事件流的调试工具典型应用场景适用于 CRUD 操作、资源管理、数据检索等标准 Web 服务适用于实时数据推送、物联网系统、实时通知、社交媒体更新等场景\n事件驱动 API 的应用场景\n\n物联网IoT传感器或设备发生状态变化时触发事件边缘设备或云端系统可通过事件驱动 API 及时处理。\n金融服务如股票价格的实时更新或用户的交易通知系统可以基于事件驱动模式触发操作。\n聊天和社交应用用户消息发送和接收的实时通知。\n\nAPI-as-a-Product\nAPI 产品化的概念\nAPI-as-a-Product 是指将 API 视为企业的核心产品之一进行开发和管理而不仅仅是系统内部的技术实现。API 产品化的理念要求开发者从用户体验、商业模式和开发生命周期的角度来设计和维护 API。这意味着API 不仅要满足技术需求,还要通过良好的文档、开发者体验和性能优化等方面提高用户的使用效果。\nAPI 产品化的关键要素\n\n开发者体验DXAPI 用户不仅是系统内的开发者,也包括外部开发者,因此必须提供清晰、易用的文档、示例和 SDK确保开发者能够快速上手并集成 API。\n版本控制产品化的 API 需要长期维护和迭代,必须考虑 API 的版本管理和向后兼容性,避免因为版本变更影响现有用户。\n监控与分析API 产品化需要建立完善的监控系统,分析 API 的使用情况、性能指标、错误率等,帮助开发团队不断优化 API 性能和稳定性。\n定价与商业模式API 产品通常涉及商业化,企业需要为 API 提供合理的定价策略,如按请求计费、订阅收费等方式。\n\nAPI-as-a-Product 的优势\n\n增强业务价值通过开放 API企业可以扩大生态系统与第三方合作伙伴共同开发产品从而增强业务价值。\n提高竞争力提供高质量、易用的 API 可以吸引更多开发者和合作伙伴,帮助企业在市场中占据优势地位。\n开发者社区的构建API 产品化有助于建立开发者社区,开发者的参与和反馈可以促进产品迭代和改进。\n\n无服务器 API 的未来发展方向\nServerless API 概述\n无服务器ServerlessAPI 是指基于无服务器架构的 API 设计模式开发者只需关注代码逻辑而不需要管理底层的服务器和基础设施。API 的请求由云提供商自动扩展和分配资源,并按实际使用量收费。\n无服务器 API 的发展趋势\n\n无缝集成与扩展无服务器架构可以自动扩展随着云服务的不断成熟Serverless API 的扩展性和稳定性将进一步提升,能够应对更大规模的流量和更复杂的应用场景。\n与事件驱动架构结合未来无服务器 API 将更多地与事件驱动架构结合,开发者可以基于事件触发 API 请求,从而实现更高效的数据处理和系统通信。\n多云环境的无服务器 API随着多云战略的普及开发者可以在不同的云平台之间无缝运行和扩展 API提供更灵活的部署选择。\n\n无服务器 API 的应用场景\n\n短周期任务如图片处理、数据转换等可以通过无服务器 API 轻松处理,按需扩展并减少资源浪费。\n物联网与边缘计算无服务器架构可以与边缘设备和物联网系统结合处理来自分布式设备的数据并通过 API 进行实时分析和响应。\n事件驱动任务通过 Serverless 架构API 可以根据不同的事件(如数据库变更、文件上传等)进行触发执行,灵活高效。\n\nAPI 自动化与 AI 的结合\nAI 与 API 自动化的结合\n随着人工智能AI技术的进步AI 与 API 开发的结合可以显著提升 API 的设计、测试和优化效率。API 自动化与 AI 技术的结合意味着开发者可以通过机器学习和智能化工具自动化生成 API 代码、编写测试用例,甚至自动化优化 API 性能。\n自动化 API 生成\n\n智能代码生成器基于 AI 模型的代码生成工具可以根据描述文档(如 OpenAPI 规范)自动生成 API 的代码和接口,减少开发者手动编写代码的工作量。\n自适应 APIAI 可以分析 API 的历史请求和使用模式,并根据负载情况自动调整 API 配置和资源分配,确保系统在不同流量场景下保持高效。\n\n自动化测试与优化\n\nAI 驱动的测试生成AI 可以根据 API 的文档和行为自动生成测试用例和场景覆盖率从而大幅提高测试效率。AI 还能自动识别常见的安全漏洞和性能瓶颈。\n预测性维护与优化通过机器学习算法分析 API 的性能数据和使用趋势AI 可以提前发现潜在的性能问题并提出优化建议,避免系统崩溃或服务中断。\n\nAPI 安全与 AI\n\n自动化安全检测AI 技术可以在开发和测试阶段自动化检测 API 的安全漏洞(如 SQL 注入、跨站脚本攻击等),并提供修复建议。\n动态威胁检测AI 还可以在 API 运行时监控异常流量和攻击行为,动态检测潜在的安全威胁并自动采取防护措施。\n"},"Technology/SoftwareEngineering/自动化流程/工具使用/GitHub-Actions":{"title":"GitHub Actions","links":[],"tags":["技术/软件工程","软件工程/自动化流程"],"content":"GitHub Actions\nGitHub Actions 是一个持续集成和持续交付CI/CD平台它允许开发者在 GitHub 仓库中自动化构建、测试和部署软件项目。通过定义工作流文件workflow开发者可以在特定事件如代码提交或发布标签触发时执行一系列任务。\nGitHub Actions 的主要特性:\n\n事件驱动工作流可以基于 GitHub 上的各种事件(如 push、pull request、issue触发。\n基于 YAML 文件:使用易于编写和阅读的 YAML 文件定义工作流。\n跨平台支持支持在 Linux、macOS 和 Windows 环境下运行作业。\n安全性通过 GitHub Secrets 管理敏感信息,确保工作流的安全性。\n\nGitHub Actions 的主要用途:\n\n持续集成CI在代码每次变更时自动运行构建和测试流程确保代码的正确性和稳定性。\n持续交付CD将代码自动部署到开发、测试或生产环境确保软件可以快速、安全地发布。\n自动化任务执行其他重复性任务如代码格式化、依赖管理、安全扫描等。\n\nGitHub Actions 基本概念\n工作流Workflow\n工作流Workflow是 GitHub Actions 的核心单元,通过 YAML 文件定义,位于 .github/workflows/ 目录下。工作流文件描述了自动化流程的具体操作步骤包括何时触发on、在何种环境中运行runs-on、以及执行的任务jobs 和 steps。\ngraph TD\n A[Workflow]\n A --> B1[name]\n A --> B2[on]\n B2 --> C1[push]\n B2 --> C2[pull_request]\n B2 --> C3[schedule]\n B2 --> C4[workflow_dispatch]\n A --> B3[jobs]\n B3 --> D1[Job 1]\n B3 --> D2[Job 2]\n D1 --> E1[runs-on]\n D1 --> E2[needs]\n D1 --> E3[env]\n D1 --> E4[steps]\n E4 --> F1[Step 1]\n E4 --> F2[Step 2]\n F1 --> G1[uses]\n F1 --> G2[run]\n F1 --> G3[env]\n F1 --> G4[with]\n F2 --> G5[uses]\n F2 --> G6[run]\n F2 --> G7[env]\n F2 --> G8[with]\n D2 --> H1[runs-on]\n D2 --> H2[needs]\n D2 --> H3[env]\n D2 --> H4[steps]\n H4 --> I1[Step 1]\n H4 --> I2[Step 2]\n I1 --> J1[uses]\n I1 --> J2[run]\n I1 --> J3[env]\n I1 --> J4[with]\n I2 --> J5[uses]\n I2 --> J6[run]\n I2 --> J7[env]\n I2 --> J8[with]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n关键字描述示例name工作流的名称可选name: CI/CD Pipelineon定义触发工作流的事件on: [push, pull_request, schedule, workflow_dispatch]push代码推送事件push: { branches: [main] }pull_request拉取请求事件pull_request: { branches: [main] }schedule定时器触发schedule: [{ cron: '0 0 * * *' }]workflow_dispatch手动触发工作流workflow_dispatch:jobs包含一个或多个作业jobs: { build: { ... }, test: { ... }, deploy: { ... } }runs-on指定作业运行的虚拟环境runs-on: ubuntu-latestneeds指定作业的依赖关系needs: buildenv设置环境变量作业级或步骤级env: { NODE_ENV: production }steps作业中的具体操作步骤steps: [ { name: Checkout code, uses: actions/checkout@v2 }, ... ]name (Step)步骤的名称name: Checkout codeuses调用预定义的 actionuses: actions/checkout@v2run运行命令行命令run: npm installwith传递给 action 的参数with: { node-version: '14' }\n作业Job\n**作业Job是工作流中独立运行的一组步骤。**作业可以在不同的虚拟环境中运行,并且可以并行或按顺序执行;作业之间可以是独立的,也可以相互依赖。\ngraph TD\n A[jobs]\n A --> B1[Job 1]\n A --> B2[Job 2]\n \n B1 --> C1[runs-on]\n B1 --> C2[steps]\n B1 --> C3[needs] --> D1[依赖的Job]\n B1 --> C4[env] --> D2[环境变量]\n \n C2 --> D3[Step 1]\n C2 --> D4[Step 2]\n \n D3 --> E1[uses]\n D3 --> E2[run]\n D3 --> E3[name]\n D3 --> E4[with] --> F1[参数]\n D3 --> E5[env] --> F2[环境变量]\n D3 --> E6[if] --> F3[条件]\n \n D4 --> G1[uses]\n D4 --> G2[run]\n D4 --> G3[name]\n D4 --> G4[with] --> H1[参数]\n D4 --> G5[env] --> H2[环境变量]\n D4 --> G6[if] --> H3[条件]\n\n B2 --> I1[runs-on]\n B2 --> I2[steps]\n B2 --> I3[needs] --> J1[依赖的Job]\n B2 --> I4[env] --> J2[环境变量]\n \n I2 --> K1[Step 1]\n I2 --> K2[Step 2]\n \n K1 --> L1[uses]\n K1 --> L2[run]\n K1 --> L3[name]\n K1 --> L4[with] --> M1[参数]\n K1 --> L5[env] --> M2[环境变量]\n K1 --> L6[if] --> M3[条件]\n \n K2 --> N1[uses]\n K2 --> N2[run]\n K2 --> N3[name]\n K2 --> N4[with] --> O1[参数]\n K2 --> N5[env] --> O2[环境变量]\n K2 --> N6[if] --> O3[条件]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n关键字描述jobs顶级节点包含所有作业的定义。Job每个作业的定义包含运行环境、步骤、依赖关系和环境变量。runs-on指定作业运行的虚拟环境如 ubuntu-latest、windows-latest、macos-latest。steps包含作业中所有步骤的列表。Step每个步骤的定义可以包含 uses、run、name、with、env 和 if 等子字段。uses调用预定义的 Action例如 actions/checkout@v2。run运行命令行命令如 npm install。name步骤名称用于描述步骤的功能。with传递给 Action 的参数,如 node-version: '14'。env环境变量可以在作业级别或步骤级别定义。if条件表达式控制步骤或作业的执行例如 if: github.ref == 'refs/heads/main'。needs定义作业的依赖关系确保按顺序执行例如 needs: [build]。matrix定义矩阵策略用于在多个环境组合上并行运行作业。timeout-minutes设置作业超时时间以分钟为单位防止作业无限制地运行。continue-on-error如果设置为 true即使作业失败也会继续执行后续作业。container在指定的 Docker 容器中运行作业。services为作业提供依赖服务如数据库服务。\n步骤Step\n**步骤Step是作业中的单个任务。**步骤可以是运行命令行命令run或调用预定义的 actionuses。步骤在同一个作业中按顺序执行且共享相同的上下文包括工作目录、环境变量等。\ngraph TD\n A[steps]\n A --> B1[Step 1]\n A --> B2[Step 2]\n \n B1 --> C1[name]\n B1 --> C2[uses]\n B1 --> C3[run]\n B1 --> C4[with] --> D1[参数]\n B1 --> C5[env] --> D2[环境变量]\n B1 --> C6[if] --> D3[条件]\n B1 --> C7[continue-on-error] --> D4[错误继续]\n B1 --> C8[timeout-minutes] --> D5[超时时间]\n\n B2 --> E1[name]\n B2 --> E2[uses]\n B2 --> E3[run]\n B2 --> E4[with] --> F1[参数]\n B2 --> E5[env] --> F2[环境变量]\n B2 --> E6[if] --> F3[条件]\n B2 --> E7[continue-on-error] --> F4[错误继续]\n B2 --> E8[timeout-minutes] --> F5[超时时间]\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n关键字描述steps包含作业中所有步骤的列表。name步骤名称用于描述步骤的功能。uses调用预定义的 Action例如 actions/checkout@v2。run运行命令行命令如 npm install。with传递给 Action 的参数,如 node-version: '14'。env环境变量可以在步骤级别定义。if条件表达式控制步骤的执行例如 if: github.ref == 'refs/heads/main'。continue-on-error如果设置为 true即使步骤失败也会继续执行后续步骤。timeout-minutes设置步骤超时时间以分钟为单位防止步骤无限制地运行。\nRunner 和执行器Runner\nRunner 是运行 GitHub Actions 作业的计算资源。GitHub 提供了托管 Runner也可以使用自托管 Runner。\n\n托管 Runner由 GitHub 提供和维护,目前支持 Linux、macOS 和 Windows。\n自托管 Runner由用户提供和维护适用于需要特殊软件或硬件环境的场景。\n\nGitHub Actions 中 YAML 的具体示例\n在 GitHub Actions 中YAML 文件用于定义工作流的结构和行为。主要包括工作流名称、触发事件、作业和步骤等。\nname: CI/CD Pipeline\n \n# 定义触发事件:推送到 main 分支、拉取请求到 main 分支、定时触发、手动触发\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n schedule:\n - cron: '0 0 * * *'\n workflow_dispatch:\n \njobs:\n build:\n # 使用 GitHub 托管的 Ubuntu 环境\n runs-on: ubuntu-latest\n \n # 矩阵策略:在多个 Node.js 版本上运行作业\n strategy:\n matrix:\n node-version: [12, 14, 16]\n \n # 作业级别环境变量\n env:\n BUILD_ENV: production\n \n steps:\n - name: Checkout code\n # 使用 actions/checkout@v2 Action 检出代码\n uses: actions/checkout@v2\n \n - name: Set up Node.js\n # 使用 actions/setup-node@v2 Action 设置 Node.js 环境\n uses: actions/setup-node@v2\n with:\n node-version: ${{ matrix.node-version }}\n \n - name: Install dependencies\n # 运行命令安装依赖\n run: npm install\n \n - name: Build project\n # 运行命令构建项目\n run: npm run build\n \n - name: Upload build artifacts\n # 上传构建产物\n uses: actions/upload-artifact@v2\n with:\n name: build-artifacts\n path: build/\n \n test:\n # 需要等待 build 作业完成后再执行\n needs: build\n runs-on: ubuntu-latest\n \n # 矩阵策略:在多个 Node.js 版本上运行作业\n strategy:\n matrix:\n node-version: [12, 14, 16]\n \n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n \n - name: Set up Node.js\n uses: actions/setup-node@v2\n with:\n node-version: ${{ matrix.node-version }}\n \n - name: Install dependencies\n run: npm install\n \n - name: Run tests\n # 运行命令执行测试\n run: npm test\n # 设置步骤级别的环境变量\n env:\n CI: true\n \n deploy:\n # 需要等待 test 作业完成后再执行\n needs: test\n runs-on: ubuntu-latest\n \n # 仅在推送到 main 分支时执行部署\n if: github.ref == 'refs/heads/main'\n \n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n \n - name: Set up Node.js\n uses: actions/setup-node@v2\n with:\n node-version: 14\n \n - name: Install dependencies\n run: npm install\n \n - name: Build project\n run: npm run build\n \n - name: Deploy to server\n # 使用 GitHub Secrets 管理敏感信息\n env:\n SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}\n REMOTE_USER: ${{ secrets.REMOTE_USER }}\n REMOTE_HOST: ${{ secrets.REMOTE_HOST }}\n run: |\n echo "$SSH_PRIVATE_KEY" | tr -d '\\r' | ssh-add - > /dev/null\n ssh -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_HOST "mkdir -p ~/myapp"\n rsync -avz -e "ssh -o StrictHostKeyChecking=no" ./build/ $REMOTE_USER@$REMOTE_HOST:~/myapp/\n ssh -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_HOST "pm2 restart myapp"\nGitHub Actions 基础实践\n创建第一个 GitHub Actions 工作流\n使用模板创建工作流是快速上手 GitHub Actions 的一种方法。GitHub 提供了一些预定义的模板,帮助用户快速生成工作流配置文件,适用于常见的 CI/CD 场景,如构建、测试和部署。\n使用模板\ngraph LR\n A[访问仓库的 Actions 页面] --> B[选择模板]\n B --> C[修改模板]\n C --> D[保存工作流文件]\n\n\n访问仓库的 Actions 页面: 在 GitHub 仓库页面上,点击顶部菜单中的 “Actions” 标签,进入 Actions 页面。\n选择模板 GitHub 会根据仓库中的项目类型推荐一些工作流模板。例如,对于 Node.js 项目,会推荐 Node.js CI 模板。用户可以选择一个合适的模板进行创建。\n修改模板 选择模板后GitHub 会展示模板的 YAML 配置文件。用户可以根据需要修改该文件,例如调整触发条件、添加或删除步骤。\n保存工作流文件 修改完成后,点击 “Start commit” 按钮,将工作流文件保存到仓库的 .github/workflows/ 目录下。\n\n手动创建\n手动编写工作流文件提供了更高的灵活性和控制力适用于复杂或特定需求的自动化流程。用户可以根据具体需求自定义工作流的触发条件、作业和步骤。\ngraph LR\n A[创建工作流文件] --> B[编写 YAML 文件]\n B --> C[定义工作流名称和触发条件]\n C --> D[定义作业和步骤]\n\n\n创建工作流文件 在仓库的根目录下创建 .github/workflows/ 目录。如果该目录不存在,需要手动创建。\n编写 YAML 文件: 在 .github/workflows/ 目录下创建一个新的 YAML 文件,例如 ci.yml。在该文件中定义工作流的名称、触发条件、作业和步骤。\n定义工作流名称和触发条件 使用 name 字段定义工作流的名称,使用 on 字段定义工作流的触发条件,如 push、pull_request。\n定义作业和步骤 使用 jobs 字段定义一个或多个作业,每个作业包含多个步骤。步骤可以是运行命令或调用预定义的 action。\n\n使用预定义的 Actions\nGitHub Actions 生态系统中包含大量的预定义 Actions分为官方 Actions 和社区 Actions。官方 Actions 由 GitHub 维护和提供,质量和可靠性有保障;社区 Actions 由开源社区开发和维护,种类丰富,覆盖了各种功能需求。可以在 GitHub Marketplace 查找和使用各种 Actions查看其文档和示例。\n官方 Actions 库\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAction功能说明示例actions/checkout检查出仓库代码uses: actions/checkout@v2actions/setup-node设置 Node.js 环境uses: actions/setup-node@v2actions/upload-artifact上传构建工件uses: actions/upload-artifact@v2actions/download-artifact下载构建工件uses: actions/download-artifact@v2actions/setup-python设置 Python 环境uses: actions/setup-python@v2actions/setup-java设置 Java 环境uses: actions/setup-java@v2actions/setup-go设置 Go 环境uses: actions/setup-go@v3actions/cache缓存依赖和构建结果uses: actions/cache@v2actions/github-script在 GitHub 上运行任意脚本uses: actions/github-script@v5actions/labeler根据文件更改自动打标签uses: actions/labeler@v2actions/stale自动标记和关闭过期的 issues 和 PRsuses: actions/stale@v5\n社区 Actions 库\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAction功能说明示例stefanzweifel/git-auto-commit-action自动提交代码更改uses: stefanzweifel/git-auto-commit-action@v4docker/build-push-action构建并推送 Docker 镜像uses: docker/build-push-action@v2slackapi/slack-github-action发送通知到 Slack 频道uses: slackapi/slack-github-action@v1github/codeql-action代码安全分析和质量检查uses: github/codeql-action/analyze@v2peter-evans/create-issue-from-file从文件创建 issueuses: peter-evans/create-issue-from-file@v2softprops/action-gh-release发布 GitHub Releaseuses: softprops/action-gh-release@v1peaceiris/actions-gh-pages部署静态网站到 GitHub Pagesuses: peaceiris/actions-gh-pages@v3JamesIves/github-pages-deploy-action自动部署到 GitHub Pagesuses: JamesIves/github-pages-deploy-action@4.1.4coverallsapp/github-action测试覆盖率报告uses: coverallsapp/github-action@v1actions-rs/toolchain设置 Rust 工具链uses: actions-rs/toolchain@v1microsoft/playwright-github-action运行 Playwright 测试uses: microsoft/playwright-github-action@v1\n使用预定义的 Actions 可以简化工作流配置,快速实现复杂功能。流行的预定义 Actions 通常经过广泛测试和使用,具有较高的可靠性和易用性。\n步骤\n\n\n选择 Action 在 GitHub Marketplace 或官方文档中查找需要的 Action阅读其使用说明和示例。\n\n\n添加到工作流 在工作流文件的 steps 部分,使用 uses 关键字引用选定的 Action并根据需求传递参数。\n\n\n具体示例 使用 actions/checkout 和 actions/setup-node Actions 的工作流示例:\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2 # 该 Action 用于将仓库代码检出到 Runner 的工作目录。此步骤通常是工作流的第一步,用于获取最新代码。\n - name: Set up Node.js\n uses: actions/setup-node@v2\n with:\n node-version: '14'\n - name: Install dependencies\n run: npm install\n - name: Run tests\n run: npm test\n示例解析\n\nactions/checkout\nactions/setup-node该 Action 用于设置 Node.js 环境。通过传递 node-version 参数,指定要使用的 Node.js 版本。\nrun使用 run 关键字直接运行命令行命令,如安装依赖和运行测试。\n\n\n\n运行基本的 CI 流程\n构建\n构建工具用于自动化编译、打包和依赖管理是 CI 流程的重要组成部分。Maven 和 Gradle 是常见的 Java 项目构建工具,其他语言也有类似的工具,如 Node.js 的 npm 和 Python 的 pip。\n步骤\n\n设置构建环境 在工作流文件中,配置运行环境和必要的依赖工具。例如,在 Java 项目中,通常需要设置 JDK 环境。\n添加构建步骤 在 steps 部分,使用 run 关键字执行构建工具的命令,如 mvn install 或 gradle build。\n\n示例 集成 Maven 的工作流文件示例:\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up JDK\n uses: actions/setup-java@v2\n with:\n java-version: '11'\n - name: Build with Maven\n run: mvn install\n集成 Gradle 的工作流文件示例:\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up JDK\n uses: actions/setup-java@v2\n with:\n java-version: '11'\n - name: Build with Gradle\n run: gradle build\n测试\n单元测试和集成测试是保证代码质量和功能正确性的关键步骤。通过在工作流中集成测试步骤可以在每次代码变更时自动运行测试及时发现和修复问题。\n步骤\n\n配置测试环境 确保工作流中包含必要的依赖工具和环境设置,以便能够运行测试。例如,在 Node.js 项目中,需要安装依赖包。\n添加测试步骤 在 steps 部分,使用 run 关键字执行测试命令,如 npm test、mvn test 或 gradle test。\n\n示例 添加单元测试和集成测试的工作流文件示例Node.js 项目):\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up Node.js\n uses: actions/setup-node@v2\n with:\n node-version: '14'\n - name: Install dependencies\n run: npm install\n - name: Run unit tests\n run: npm test\n - name: Run integration tests\n run: npm run integration-test\n添加单元测试和集成测试的工作流文件示例Java 项目):\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up JDK\n uses: actions/setup-java@v2\n with:\n java-version: '11'\n - name: Build with Maven\n run: mvn install\n - name: Run unit tests\n run: mvn test\n - name: Run integration tests\n run: mvn verify\nGitHub Actions 进阶操作\n自定义 Actions\n创建和发布 JavaScript Actions\nJavaScript Actions 是基于 Node.js 环境执行的自定义 Actions适用于编写需要复杂逻辑或与 Node.js 生态系统集成的任务。它们可以复用现有的 npm 包,并且易于调试和测试。\n\n\n初始化项目 使用 npm init 初始化一个新的 Node.js 项目,并安装必要的依赖。\n$ mkdir my-action\n$ cd my-action\n$ npm init -y\n$ npm install @actions/core @actions/github\n\n\n编写代码 创建 index.js 文件,编写 Action 的核心逻辑。\nconst core = require('@actions/core');\nconst github = require('@actions/github');\n \ntry {\n const nameToGreet = core.getInput('who-to-greet');\n console.log(`Hello ${nameToGreet}!`);\n const time = new Date().toTimeString();\n core.setOutput("time", time);\n} catch (error) {\n core.setFailed(error.message);\n}\n\n\n创建 Action 元数据文件: 在项目根目录下创建 action.yml 文件,定义 Action 的元数据。\nname: 'Hello World'\ndescription: 'Greet someone and print the current time'\ninputs:\n who-to-greet:\n description: 'The name of the person to greet'\n required: true\n default: 'World'\nruns:\n using: 'node12'\n main: 'index.js'\n\n\n发布 Action 将代码提交到 GitHub 仓库,并打标签发布。\n$ git add .\n$ git commit -m "Initial commit"\n$ git tag -a -m "Initial release" v1\n$ git push --follow-tags\n\n\n**示例使用:**在工作流中使用自定义的 JavaScript Action\njobs:\n greet:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Greet\n uses: my-org/my-action@v1\n with:\n who-to-greet: 'John Doe'\n\n\n创建和发布 Docker Actions\nDocker Actions 运行在 Docker 容器中,适用于需要特定环境或依赖的任务。通过 Docker可以确保 Action 在各种环境中具有一致的运行行为。\n\n\n创建 Dockerfile 在项目根目录下创建 Dockerfile定义容器的构建过程。\nFROM node:12-alpine\nCOPY . /my-action\nWORKDIR /my-action\nRUN npm install\nENTRYPOINT ["node", "/my-action/index.js"]\n\n\n编写代码 创建 index.js 文件,编写 Action 的核心逻辑。\nconst core = require('@actions/core');\nconst github = require('@actions/github');\n \ntry {\n const nameToGreet = core.getInput('who-to-greet');\n console.log(`Hello ${nameToGreet}!`);\n const time = new Date().toTimeString();\n core.setOutput("time", time);\n} catch (error) {\n core.setFailed(error.message);\n}\n\n\n创建 Action 元数据文件: 在项目根目录下创建 action.yml 文件,定义 Action 的元数据。\nname: 'Hello World'\ndescription: 'Greet someone and print the current time'\ninputs:\n who-to-greet:\n description: 'The name of the person to greet'\n required: true\n default: 'World'\nruns:\n using: 'docker'\n image: 'Dockerfile'\n\n\n发布 Action 将代码提交到 GitHub 仓库,并打标签发布。\n$ git add .\n$ git commit -m "Initial commit"\n$ git tag -a -m "Initial release" v1\n$ git push --follow-tags\n\n\n示例使用 在工作流中使用自定义的 Docker Action\njobs:\n greet:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Greet\n uses: my-org/my-action@v1\n with:\n who-to-greet: 'Jane Doe'\n\n\n使用 Composite Actions 复用步骤\nComposite Actions 允许将多个步骤组合成一个 Action以便在多个工作流中复用。适用于需要多个步骤的复杂任务。\n步骤\n\n\n创建 Composite Action 文件: 在项目根目录下创建 action.yml 文件,定义 Composite Action。\nname: 'Greet and Time'\ndescription: 'Greet someone and print the current time'\ninputs:\n who-to-greet:\n description: 'The name of the person to greet'\n required: true\n default: 'World'\nruns:\n using: 'composite'\n steps:\n - run: echo "Hello ${{ inputs.who-to-greet }}!"\n - run: echo "The current time is ${{ steps.time.outputs.time }}"\n id: time\n shell: bash\n\n\n发布 Composite Action 将代码提交到 GitHub 仓库,并打标签发布。\n$ git add .\n$ git commit -m "Initial commit"\n$ git tag -a -m "Initial release" v1\n$ git push --follow-tags\n\n\n示例使用 在工中使用自定义的 Composite Action\n\n\njobs:\n greet_and_time:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Greet and Time\n uses: my-org/greet-and-time@v1\n with:\n who-to-greet: 'Alice'\n使用 GitHub Secrets 进行安全管理\n添加和管理 Secrets\nSecrets 是 GitHub 提供的一种安全管理敏感信息的方法,用于存储诸如 API 密钥、凭据和其他机密数据。Secrets 可以在工作流中安全地引用,而不暴露实际值。\n步骤\n\n添加 Secrets 在 GitHub 仓库页面,进入 “Settings” → “Secrets” → “Actions”点击 “New repository secret” 添加新的 Secret。\n\nName为 Secret 取一个名称,例如 MY_SECRET.\nValue输入 Secret 的值,例如 super-secret-value.\n\n\n管理 Secrets Secrets 可以通过 GitHub 界面进行添加、编辑和删除。注意Secret 值一旦保存,不能直接查看,只能通过工作流引用。\n\n在工作流中安全地使用 Secrets\n在工作流中可以通过 ${{ secrets.SECRET_NAME }} 的语法安全地引用 Secrets。GitHub Actions 会在运行时将该表达式替换为实际的 Secret 值。\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Use Secret\n run: echo "The secret is ${{ secrets.MY_SECRET }}"\n示例解析\n\nsecrets.MY_SECRET引用名称为 MY_SECRET 的 Secret。GitHub Actions 会在运行时自动替换为 Secret 的实际值。\n\n设置条件化执行和并行作业\n使用 if 表达式设置条件化执行\nif 表达式允许根据条件控制工作流的执行。例如,可以在特定分支上执行特定步骤,或在测试失败时停止后续步骤。\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Run tests\n run: npm test\n - name: Deploy\n if: github.ref == 'refs/heads/main' && success()\n run: ./deploy.sh\n示例解析\n\nif: github.ref == 'refs/heads/main' && success():仅在当前分支为 main 且前一步骤成功时执行 deploy 步骤。\n\n配置并行作业和依赖关系\n默认情况下GitHub Actions 中的作业是并行运行的。通过配置 needs 关键字,可以定义作业之间的依赖关系,确保某些作业按顺序执行。\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Build project\n run: npm build\n \n test:\n runs-on: ubuntu-latest\n needs: build\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Run tests\n run: npm test\n \n deploy:\n runs-on: ubuntu-latest\n needs: [build, test]\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Deploy project\n run: ./deploy.sh\n示例解析\n\nneeds: build表示 test 作业依赖 build 作业test 作业将在 build 作业完成后执行。\nneeds: [build, test]:表示 deploy 作业依赖 build 和 test 作业deploy 作业将在 build 和 test 作业完成后执行。\n\n集成第三方服务如 Slack、AWS、Azure\n使用 Webhooks 和自定义 Notifications\nWebhooks 允许工作流在特定事件发生时向外部服务发送 HTTP 请求,实现与外部服务的集成和通知。自定义 Notifications 可用于在工作流执行过程中发送通知,例如 Slack 通知。\n示例 向 Slack 发送通知:\n\n\n创建 Slack Webhook URL 在 Slack 工作区中,创建一个新的 Webhook URL。\n\n\n添加 Slack Webhook URL 到 Secrets 在 GitHub 仓库中添加一个新的 Secret例如 SLACK_WEBHOOK_URL保存 Webhook URL。\n\n\n在工作流中使用 Webhook URL\njobs:\n notify:\n runs-on: ubuntu-latest\n steps:\n - name: Send notification to Slack\n run: |\n curl -X POST -H 'Content-type: application/json' \\\n --data '{"text":"Build completed successfully!"}' \\\n ${{ secrets.SLACK_WEBHOOK_URL }}\n\n\n示例解析\n\nsecrets.SLACK_WEBHOOK_URL引用名称为 SLACK_WEBHOOK_URL 的 Secret用于发送 HTTP 请求到 Slack Webhook URL。\n\n部署到 AWS、Azure、GCP 等云服务\nGitHub Actions 可以与各大云服务平台(如 AWS、Azure、GCP集成实现自动化部署。通过使用官方或社区提供的 Actions可以简化部署流程。\n部署到 AWS S3\n\n\n添加 AWS 凭证到 Secrets 在 GitHub 仓库中添加 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY Secrets。\n\n\n在工作流中配置部署步骤\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Upload to S3\n uses: aws-actions/configure-aws-credentials@v1\n with:\n aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}\n aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n aws-region: us-west-2\n - name: Sync S3 bucket\n run: |\n aws s3 sync . s3://my-bucket --exclude ".git/*"\n\n\n示例解析\n\naws-actions/configure-aws-credentials@v1配置 AWS 凭证和区域。\naws s3 sync使用 AWS CLI 将代码同步到 S3 存储桶。\n\n通知集成如 Slack、Microsoft Teams\n除了 WebhooksGitHub Actions 还可以通过官方和社区 Actions 发送通知到各种消息平台,如 Slack 和 Microsoft Teams。这些通知可以用于报告工作流状态、构建结果等。\n发送通知到 Microsoft Teams\n\n\n创建 Microsoft Teams Webhook URL 在 Microsoft Teams 中,创建一个新的 Webhook URL。\n\n\n添加 Webhook URL 到 Secrets 在 GitHub 仓库中添加一个新的 Secret例如 TEAMS_WEBHOOK_URL保存 Webhook URL。\n\n\n在工作流中使用 Webhook URL\njobs:\n notify:\n runs-on: ubuntu-latest\n steps:\n - name: Send notification to Microsoft Teams\n run: |\n curl -H 'Content-Type: application/json' \\\n -d '{"title": "Build Notification", "text": "The build has completed successfully!"}' \\\n ${{ secrets.TEAMS_WEBHOOK_URL }}\n\n\n示例解析\n\nsecrets.TEAMS_WEBHOOK_URL引用名称为 TEAMS_WEBHOOK_URL 的 Secret用于发送 HTTP 请求到 Microsoft Teams Webhook URL。\n\nGitHub Actions 高级实践\n持续交付CD流程\n配置持续交付流水线\n持续交付CD是软件工程中的一项实践旨在通过自动化部署过程使软件能够随时发布到任何环境。GitHub Actions 提供了强大的工具支持配置和管理 CD 流水线。\n步骤\n\n\n创建工作流文件 在 .github/workflows/ 目录下创建一个新的工作流文件,例如 cd.yml。\n\n\n定义触发条件 配置工作流在合适的事件发生时触发,如代码推送到主分支或发布标签创建。\non:\n push:\n branches:\n - main\n release:\n types: [created]\n\n\n配置作业 定义 CD 流水线的各个作业,包括构建、测试和部署。\n\n\nname: CD Pipeline\n \non:\n push:\n branches:\n - main\n release:\n types: [created]\n \njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Build project\n run: npm build\n \n test:\n runs-on: ubuntu-latest\n needs: build\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Run tests\n run: npm test\n \n deploy:\n runs-on: ubuntu-latest\n needs: [build, test]\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Deploy to production\n run: ./deploy.sh\n自动化版本发布和部署\n自动化版本发布和部署确保软件能够快速、安全地交付给用户减少人为操作和错误。GitHub Actions 可以自动执行版本号管理、构建工件发布和部署到目标环境。\n步骤\n\n版本号管理 在构建完成后,使用脚本自动更新版本号。\n发布构建工件 使用 actions/upload-artifact 将构建工件上传到 GitHub或使用 actions/create-release 创建 GitHub Release。\n自动部署 配置部署步骤,将构建工件部署到目标环境。\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up Node.js\n uses: actions/setup-node@v2\n with:\n node-version: '14'\n - name: Build project\n run: npm build\n - name: Upload build artifacts\n uses: actions/upload-artifact@v2\n with:\n name: build-artifacts\n path: build/\n \n release:\n runs-on: ubuntu-latest\n needs: build\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Create GitHub Release\n uses: actions/create-release@v1\n env:\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n with:\n tag_name: v1.0.0\n release_name: Release v1.0.0\n draft: false\n prerelease: false\n - name: Upload release assets\n uses: actions/upload-release-asset@v1\n with:\n upload_url: ${{ steps.create_release.outputs.upload_url }}\n asset_path: ./build/\n asset_name: build-artifacts.zip\n asset_content_type: application/zip\n \n deploy:\n runs-on: ubuntu-latest\n needs: release\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Deploy to production\n run: ./deploy.sh\n使用矩阵构建不同环境和配置\n定义矩阵策略\n矩阵策略允许在多个环境和配置下并行运行作业确保代码在不同平台、依赖版本和配置下的兼容性和稳定性。\n步骤\n\n定义矩阵 在工作流文件中使用 matrix 关键字定义多个变量组合。\n配置作业 配置作业使用矩阵变量运行。\n\njobs:\n build:\n runs-on: ubuntu-latest\n strategy:\n matrix:\n node-version: [12, 14, 16]\n os: [ubuntu-latest, windows-latest, macos-latest]\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Setup Node.js\n uses: actions/setup-node@v2\n with:\n node-version: ${{ matrix.node-version }}\n - name: Install dependencies\n run: npm install\n - name: Run tests\n run: npm test\n针对不同操作系统和依赖版本运行作业\n使用矩阵策略可以针对不同操作系统和依赖版本并行运行作业验证代码在多种环境下的行为。\n示例 在多个操作系统和 Node.js 版本上运行测试:\njobs:\n test:\n runs-on: ${{ matrix.os }}\n strategy:\n matrix:\n node-version: [12, 14, 16]\n os: [ubuntu-latest, windows-latest, macos-latest]\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Setup Node.js\n uses: actions/setup-node@v2\n with:\n node-version: ${{ matrix.node-version }}\n - name: Install dependencies\n run: npm install\n - name: Run tests\n run: npm test\n部署到 Kubernetes\n使用 kubectl 和 kustomize 进行 Kubernetes 部署\nkubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群。kustomize 允许在 Kubernetes 原生清单上进行声明式配置管理。使用它们可以实现自动化 Kubernetes 部署。\n步骤\n\n配置 Kubernetes 凭证: 在 GitHub Secrets 中添加 Kubernetes 配置,例如 KUBE_CONFIG.\n编写部署步骤 在工作流中使用 kubectl 和 kustomize 部署应用。\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up kubectl\n uses: azure/setup-kubectl@v1\n with:\n version: 'v1.18.0'\n - name: Deploy to Kubernetes\n env:\n KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}\n run: |\n kubectl apply -k ./kustomize\n集成 Helm Charts\nHelm 是 Kubernetes 的包管理工具,使用 Charts 定义、安装和管理 Kubernetes 应用。通过 Helm 可以简化 Kubernetes 应用的部署和管理。\n步骤\n\n添加 Helm 凭证: 在 GitHub Secrets 中添加 Helm 凭证,例如 HELM_REPO_URL 和 HELM_REPO_AUTH.\n编写部署步骤 在工作流中使用 Helm 部署应用。\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up Helm\n uses: azure/setup-helm@v1\n - name: Deploy with Helm\n env:\n HELM_REPO_URL: ${{ secrets.HELM_REPO_URL }}\n HELM_REPO_AUTH: ${{ secrets.HELM_REPO_AUTH }}\n run: |\n helm repo add my-repo $HELM_REPO_URL --username $HELM_REPO_AUTH\n helm upgrade --install my-release my-repo/my-chart\n4.3.3 配置自动扩展和滚动更新\n自动扩展和滚动更新是 Kubernetes 提供的功能,用于动态调整应用实例数量和无停机时间更新应用。配置这些功能可以提高应用的弹性和可靠性。\n步骤\n\n编写 Kubernetes 配置文件: 使用 HPAHorizontal Pod Autoscaler和 Rolling Update 策略配置文件。\n在工作流中应用配置 使用 kubectl 命令应用这些配置。\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Set up kubectl\n uses: azure/setup-kubectl@v1\n with:\n version: 'v1.18.0'\n - name: Apply Kubernetes configuration\n env:\n KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}\n run: |\n kubectl apply -f k8s/deployment.yaml\n kubectl apply -f k8s/hpa.yaml\n性能优化和故障排查\n优化工作流运行时间\n优化工作流运行时间可以提高开发效率减少等待时间。通过并行执行任务、缓存依赖和减少不必要的步骤可以实现优化。\n步骤\n\n使用缓存 使用 actions/cache 缓存依赖,减少重复下载和安装时间。\n并行执行任务 将独立的任务配置为并行执行,减少总运行时间。\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Cache npm dependencies\n uses: actions/cache@v2\n with:\n path: ~/.npm\n key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}\n restore-keys: |\n ${{ runner.os }}-node-\n - name: Install dependencies\n run: npm install\n - name: Build project\n run: npm build\n日志和调试\n通过分析日志可以排查工作流中的问题。GitHub Actions 提供详细的日志记录,可以在执行过程中查看每个步骤的输出。\n步骤\n\n启用调试日志 在工作流文件中设置 ACTIONS_STEP_DEBUG 环境变量为 true。\n查看运行日志 在 GitHub Actions 界面查看每个作业和步骤的详细日志。\n\njobs:\n build:\n runs-on: ubuntu-latest\n env:\n ACTIONS_STEP_DEBUG: true\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n - name: Run tests\n run: npm test\n监控和告警设置\n通过监控和告警可以及时发现和处理问题确保工作流的稳定运行。可以使用外部服务如 Prometheus 和 Grafana或集成通知如 Slack实现监控和告警。\n步骤\n\n集成监控工具 在工作流中集成 Prometheus、Grafana 等监控工具,收集和可视化指标数据。\n设置告警通知 在工作流中配置告警通知,通过 Slack 或 Email 接收告警信息。\n\n示例 通过 Slack 发送告警通知:\njobs:\n notify:\n runs-on: ubuntu-latest\n steps:\n - name: Send notification to Slack\n run: |\n curl -X POST -H 'Content-type: application/json' \\\n --data '{"text":"Build failed!"}' \\\n ${{ secrets.SLACK_WEBHOOK_URL }}\nGitHub Actions 与其他 CI/CD 工具的对比\nCI/CD 工具用于自动化软件构建、测试和部署过程,确保快速和可靠的发布周期。不同的工具有各自的优势和特点,适合不同规模和需求的项目。\nJenkins\nJenkins 是一个开源的自动化服务器广泛用于构建、部署和自动化任何项目。由于其强大的插件生态系统和可扩展性Jenkins 成为许多企业的首选 CI/CD 工具。\n优点\n\n开源和可扩展性庞大的插件库可以满足几乎所有的 CI/CD 需求。\n广泛的社区支持活跃的社区和丰富的资源文档、教程、插件。\n可自托管完全控制构建环境和安全性适用于企业内部部署。\n\n缺点\n\n复杂性设置和维护可能需要大量时间和经验。\n用户界面传统界面可能不够直观需要学习曲线。\n资源消耗自托管模式需要管理服务器资源。\n\n适用场景\n\n需要高度定制化和控制的企业级项目。\n复杂的构建和部署流水线。\n\n示例\npipeline {\n agent any\n stages {\n stage('Build') {\n steps {\n sh 'mvn clean install'\n }\n }\n stage('Test') {\n steps {\n sh 'mvn test'\n }\n }\n stage('Deploy') {\n steps {\n sh './deploy.sh'\n }\n }\n }\n}\nTravis CI\nTravis CI 是一个基于云的 CI 服务,特别适合开源项目。它提供简单的配置和与 GitHub 的深度集成。\n优点\n\n简单易用配置文件简洁明了适合快速上手。\n开源友好免费提供给开源项目。\nGitHub 集成:无缝集成 GitHub 仓库。\n\n缺点\n\n有限的自定义相比 JenkinsTravis CI 的自定义能力较弱。\n资源限制免费版有并发构建和资源使用限制。\n速度和稳定性在高峰期可能会出现构建排队和延迟。\n\n适用场景\n\n开源项目。\n需要快速上手和简便配置的小型项目。\n\n示例\nlanguage: java\njdk:\n - openjdk11\nscript:\n - mvn clean install\n - mvn test\ndeploy:\n provider: script\n script: ./deploy.sh\n on:\n branch: main\nCircleCI\nCircleCI 是一个基于云的 CI/CD 工具,提供灵活的配置和强大的并行执行能力,支持多种编程语言和框架。\n优点\n\n并行执行支持并行化构建和测试加快 CI/CD 流水线速度。\n灵活配置通过 YAML 文件配置流水线,支持多种语言和环境。\n集成和扩展与 GitHub、Bitbucket 和 Docker 集成良好。\n\n缺点\n\n成本高级功能和更多资源需要付费。\n复杂配置高级功能可能需要复杂的配置和调试。\n资源限制免费版有并发和资源使用限制。\n\n适用场景\n\n需要高并发和快速构建的大型项目。\n希望在云端管理 CI/CD 流水线的项目。\n\n示例\nversion: 2.1\njobs:\n build:\n docker:\n - image: circleci/openjdk:11\n steps:\n - checkout\n - run: mvn clean install\n - run: mvn test\nworkflows:\n version: 2\n build-and-test:\n jobs:\n - build\nGitLab CI\nGitLab CI 是 GitLab 集成的 CI/CD 工具,提供完整的 DevOps 生命周期管理,适合从代码托管到部署的全流程管理。\n优点\n\n集成性与 GitLab 无缝集成,支持整个 DevOps 生命周期。\n自托管提供自托管和云端版本满足不同企业需求。\n安全性内置的安全扫描和代码质量检查功能。\n\n缺点\n\n复杂性全面的功能可能需要较长的学习曲线。\n资源管理自托管版本需要额外的资源管理和维护。\n界面某些高级功能的界面和配置可能不够直观。\n\n适用场景\n\n需要一体化 DevOps 解决方案的企业。\n希望在同一平台上管理代码、CI/CD 和部署的项目。\n\n示例\nstages:\n - build\n - test\n - deploy\n \nbuild:\n stage: build\n script:\n - mvn clean install\n \ntest:\n stage: test\n script:\n - mvn test\n \ndeploy:\n stage: deploy\n script:\n - ./deploy.sh\n only:\n - main\n比较总结\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n特性JenkinsTravis CICircleCIGitLab CI开源/商业开源商业,开源项目免费商业,开源项目有限免费开源,商业版托管方式自托管云服务云服务,自托管云服务,自托管扩展性高中中高配置复杂度高低中中社区支持强强强强适用项目类型大型企业项目,复杂流水线开源项目,小型项目需要高并发和快速构建的项目希望全流程管理的企业项目\n不同的 CI/CD 工具各有优劣,选择合适的工具需要根据项目规模、复杂度和团队需求进行综合考虑。"},"Technology/SoftwareEngineering/自动化流程/工具使用/GitLab-Runner":{"title":"GitLab Runner","links":[],"tags":["技术/软件工程","软件工程/自动化流程"],"content":"GitLab CI/CD\n基本概念和工作原理\nGitLab CI/CD (Continuous Integration and Continuous Delivery/Deployment) 是一种自动化工具链用于软件开发过程中从代码提交到生产部署的全过程。它包括连续集成CI和连续交付/部署CD的实践。\n\n\nContinuous Integration (CI): CI 主要关注代码的频繁集成和测试。每当开发人员提交代码到版本控制系统时CI 系统会自动触发构建和测试流程,确保代码的正确性和质量。通过频繁集成和测试,能够快速发现和修复问题,减少集成风险。\nContinuous Delivery (CD): CD 的目标是确保软件在任何时候都可以安全地部署到生产环境。它通过自动化的方式将经过测试的代码推送到预生产或生产环境中。CD 包括自动化的部署、测试和发布过程。\nContinuous Deployment: 是 Continuous Delivery 的延伸,它将经过验证的代码自动部署到生产环境中,无需人工干预。这种实践要求更高的自动化和监控能力。\n\n\nGitLab CI/CD 通过 .gitlab-ci.yml 文件定义 CI/CD 流程,该文件包含了所有的构建、测试和部署步骤。 GitLab Runner 是 GitLab CI/CD 的执行者,它运行在不同的环境中,执行 .gitlab-ci.yml 文件中定义的任务。\nGitLab Runner\nGitLab Runner 是一个开源项目,用于运行由 GitLab CI/CD 定义的任务。它从 GitLab 服务器获取 .gitlab-ci.yml 文件中读取配置和作业并在不同的执行环境中执行这些作业。GitLab Runner 支持多种执行模式,并能与 GitLab 实例无缝集成。\n\n执行构建、测和部署任务\n支持并行作业和多平台执行\n提供日志记录和结果报告\n支持缓存和 artifacts优化构建过程\n\nGitLab Runner 的不同执行模式(如 Shell、Docker、Kubernetes\nGitLab Runner 支持多种执行模式,每种模式适用于不同的使用场景:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n执行模式描述优点缺点适用场景Shell使用主机的 Shell 环境执行作业。配置简单直接使用主机环境开销低。缺乏环境隔离可能影响主机系统安全性较低。适用于简单的构建和测试任务不需要复杂依赖或隔离环境的场景。Docker在 Docker 容器中执行作业,提供隔离的执行环境。提供环境隔离,易于管理依赖和一致性,支持多种语言和工具。需要配置 Docker容器启动有额外开销可能增加复杂性。需要特定依赖和环境配置的任务如使用特定版本的编译器、库或工具的构建和测试任务。Docker Machine动态创建和销毁 Docker 主机,支持弹性扩展。自动化资源管理,弹性扩展能力强,适合大规模分布式系统。配置和管理复杂,资源使用成本较高,创建和销毁主机耗时较长。需要弹性扩展、动态分配资源的场景,适合高并发或资源密集型的 CI/CD 管道。Kubernetes在 Kubernetes 集群中运行作业,提供容器编排和管理能力。强大的容器编排和管理功能,适合复杂的部署和扩展需求。需要熟悉 Kubernetes 的配置和管理,初始设置和维护较为复杂。适用于大规模分布式系统和云原生应用的 CI/CD 管道特别是在微服务架构下的持续集成和部署。Custom允许用户定义自定义执行器满足特定需求。灵活性极高能够满足特定的、非标准的需求。需要自行开发和维护自定义执行器配置复杂调试困难。需要特殊硬件或自定义环境的场景如 FPGA 编程、特殊设备测试,或使用非标准的执行环境。\nGitLab Runner 的安装步骤和配置方法\n安装 GitLab Runner 的过程因操作系统和执行模式不同而有所差异,建议参考官方文档手册。\n.gitlab-ci.yml\n.gitlab-ci.yml 是 GitLab 用于定义 CI/CD持续集成和持续部署管道的配置文件采用 YAML 语法编写。它位于 GitLab 项目的根目录中描述了项目的自动化构建、测试和部署流程。每次代码提交或合并时GitLab 会根据 .gitlab-ci.yml 文件中的配置自动触发相应的管道任务。基本结构包括以下部分:\ngraph LR\n A[.gitlab-ci.yml]\n \n A --> B[stages]\n A --> C[jobs]\n A --> D[scripts]\n A --> E[artifacts]\n A --> F[cache]\n A --> G[variables]\n A --> H[dependencies]\n A --> I[only/except]\n A --> J[include]\n \n B --> B1[build]\n B --> B2[test]\n B --> B3[deploy]\n\n C --> C1[build-job]\n C --> C2[test-job]\n C --> C3[deploy-job]\n \n D --> D1[build commands]\n D --> D2[test commands]\n D --> D3[deploy commands]\n\n E --> E1[build/]\n F --> F1[.m2/repository]\n \n G --> G1[DEPLOY_ENV: production]\n G --> G2[NODE_ENV: test]\n\n H --> H1[build-job]\n H --> H2[test-job]\n \n I --> I1[only: master]\n I --> I2[except: tags]\n\n J --> J1[template: Jobs/Build.gitlab-ci.yml]\n J --> J2[local: 'my-custom-config.yml']\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n元素描述stages定义 CI/CD 管道的不同阶段按顺序执行例如构建build、测试test和部署deploy。jobs定义在不同阶段中执行的具体任务每个任务必须属于某个阶段。scripts指定每个任务执行的命令和脚本通常包括构建、测试和部署的具体操作。artifacts定义构建产物的存储和使用通常用于保存构建结果以供后续作业使用或为后续步骤提供数据。cache配置缓存以优化构建速度减少重复下载或构建的时间尤其是在使用外部依赖时。variables定义环境变量配置不同任务的执行环境变量可以在脚本中引用以提供灵活的配置。dependencies指定当前作业依赖的前一阶段作业以确保当前作业可以访问前一作业的产物或输出。only/except定义作业的执行条件only 指定作业只在某些情况下执行except 指定作业在某些情况下不执行。include从外部文件或模板中引入配置便于配置的复用和管理常用于共享公共配置或集成现有配置文件。\n阶段stages\nStages 是 GitLab CI/CD 管道的核心组成部分,用于定义管道的执行顺序。每个 stage 代表一个阶段,按顺序执行。例如,常见的阶段包括 build构建、test测试和 deploy部署。所有在同一个 stage 中的作业会并行执行,整个 stage 成功后,管道会进入下一个阶段。\ngraph TD\n A[stages]\n A --> B[build]\n A --> C[test]\n A --> D[deploy]\n\n作业jobs\nJobs 是在 CI/CD 管道中实际执行的任务,每个 job 都属于一个特定的 stage。一个 job 通常包括编译代码、运行测试或部署应用的操作。每个 job 都会指定一个 stage并包含执行这些操作的具体命令和脚本。GitLab 会按照 stage 的顺序执行相应的 job。\ngraph TB\n A[jobs]\n A --> B[build-job]\n A --> C[test-job]\n A --> D[deploy-job]\n\n B --> B1[stage: build]\n C --> C1[stage: test]\n D --> D1[stage: deploy]\n\n脚本scripts\nScripts 是 job 中的核心部分,定义了在 CI/CD 管道中执行的具体命令或操作。这些脚本可以是简单的命令如打印消息、编译代码、运行测试或是调用外部工具。script 是实现构建、测试、部署等操作的关键,通过这些命令来自动化 CI/CD 流程。\ngraph TB\n A[scripts]\n A --> B[make]\n A --> C[make test]\n A --> D[make deploy]\n\n变量Variables\n变量用于在 .gitlab-ci.yml 文件中定义环境变量,帮助配置不同任务的执行环境。变量可以在脚本中引用,以实现动态配置。例如,环境变量 DEPLOY_ENV 可以用于指定部署的目标环境。\ngraph TB\n A[variables]\n A --> B[DEPLOY_ENV: production]\n A --> C[NODE_ENV: test]\n\n缓存Cache\n缓存用于保存构建过程中生成的中间文件或依赖项减少重复下载或构建的时间从而加快 CI/CD 管道的执行速度。例如,可以缓存 Maven 的依赖库。\ngraph TB\n A[cache]\n A --> B[.m2/repository]\n A --> C[node_modules/]\n\n构建产物Artifacts\nArtifacts 是作业运行后生成的文件或构建产物可以在后续作业中使用或下载。Artifacts 通常用于保存构建结果、测试报告等内容。\ngraph TB\n A[artifacts]\n A --> B[build/]\n A --> C[dist/]\n\n依赖Dependencies\n通过 dependencies 关键字,可以指定当前作业依赖于前一个阶段的某些作业。这样可以确保作业在正确的依赖产物生成后才会运行。例如,测试作业可以依赖于构建作业生成的构建产物。\ngraph TB\n A[dependencies]\n A --> B[build-job]\n A --> C[test-job]\n\n执行条件Conditions\n通过 only、except 和 when 等关键字可以指定作业的执行条件。only 和 except 用于限定作业在哪些分支或条件下执行,而 when 用于指定作业何时执行(例如:手动触发)。\ngraph TB\n A[执行条件]\n A --> B[only]\n B --> B1[master]\n \n A --> C[except]\n C --> C1[tags]\n\n包含Includes\nGitLab 提供了一些预定义的 CI/CD 模板,可以通过 include 关键字直接在 .gitlab-ci.yml 文件中引用。这些模板包含常见的构建、测试和部署任务,从而复用和共享配置。这对于大型项目或需要在多个项目间共享 CI/CD 配置时非常有用。\ngraph TB\n A[include]\n A --> B[template: Jobs/Build.gitlab-ci.yml]\n A --> C[local: 'my-custom-config.yml']\n\n示例配置\n# 定义不同的 CI/CD 阶段,按顺序执行\nstages:\n - build\n - test\n - deploy\n \n# 定义全局变量,可在所有作业中引用\nvariables:\n DEPLOY_ENV: production\n NODE_ENV: test\n \n# 使用缓存加速构建过程,避免重复下载依赖\ncache:\n paths:\n - .m2/repository\n - node_modules/\n \n# 构建作业,属于 build 阶段\nbuild-job:\n stage: build\n script:\n # 运行构建命令\n - echo "Building the project..."\n - make build\n artifacts:\n # 保存构建产物以供后续作业使用\n paths:\n - build/\n tags:\n # 使用带有 docker 标签的 Runner 运行作业\n - docker\n \n# 测试作业,属于 test 阶段\ntest-job:\n stage: test\n script:\n # 运行测试命令\n - echo "Running tests..."\n - make test\n dependencies:\n # 指定依赖的作业,确保使用 build-job 的构建产物\n - build-job\n only:\n # 仅在 master 分支上执行测试作业\n - master\n artifacts:\n # 保存测试结果\n paths:\n - test-reports/\n \n# 部署作业,属于 deploy 阶段\ndeploy-job:\n stage: deploy\n script:\n # 部署到生产环境\n - echo "Deploying to $DEPLOY_ENV environment..."\n - make deploy\n only:\n # 仅在 master 分支或带有生产标签的提交上执行部署\n - master\n except:\n # 排除带有 ci-skip 标签的提交\n - tags\n environment:\n # 定义部署的环境\n name: production\n url: production.example.com\n \n# 包含外部模板配置\ninclude:\n - template: Jobs/Build.gitlab-ci.yml\n基础实践\n创建第一个 GitLab CI/CD 管道Pipeline\n创建一个简单的 .gitlab-ci.yml 文件是开始使用 GitLab CI/CD 的第一步。该文件定义了管道中的作业和阶段。以下是一个简单的示例:\nstages:\n - build\n - test\n \nbuild-job:\n stage: build\n script:\n - echo "Compiling the code..."\n - make\n \ntest-job:\n stage: test\n script:\n - echo "Running tests..."\n - make test\n在 GitLab 中运行第一个管道\n\n将 .gitlab-ci.yml 文件提交到项目的根目录。\n登录 GitLab导航到项目页面。\n在左侧菜单中选择 “CI / CD” → “Pipelines”。\n查看新创建的管道点击查看详细信息。\n\nGitLab 会自动检测 .gitlab-ci.yml 文件并运行管道。你可以查看每个作业的日志,了解执行情况。\n监控和管理管道执行\n\n监控管道状态: 在 Pipelines 页面查看所有管道的状态(成功、失败、进行中)。\n查看作业日志: 点击具体作业查看详细日志,了解作业的执行情况和输出。\n重试失败的作业: 对于失败的作业,可以点击 Retry 按钮重新执行。\n取消进行中的管道: 如果需要终止进行中的管道,可以点击 Cancel 按钮。\n\n使用预定义的 GitLab CI 模板\nGitLab 提供了一些预定义的 CI 模板,帮助用户快速上手常见的 CI/CD 流程。这些模板涵盖了多种编程语言和框架,如 Java、Node.js、Python 等。\n\n\n常见模板:\n\nJobs/Build.gitlab-ci.yml\nJobs/Test.gitlab-ci.yml\nJobs/Deploy.gitlab-ci.yml\n\n\n\n如何在项目中引用和使用预定义模板\n你可以通过 include 关键字在 .gitlab-ci.yml 文件中引用预定义模板。例如下述示例中,引用了 GitLab 提供的构建模板,同时添加了一个自定义的测试作业。\ninclude:\n - template: Jobs/Build.gitlab-ci.yml\n \nstages:\n - build\n - test\n \ntest-job:\n stage: test\n script:\n - echo "Running custom tests..."\n - make test\n根据需求自定义和扩展模板\n使用预定义模板后你可以根据项目的具体需求进行自定义和扩展。例如通过自定义模板你可以在标准流程基础上添加特定的测试和部署逻辑。\ninclude:\n - template: Jobs/Build.gitlab-ci.yml\n \nstages:\n - build\n - test\n - deploy\n \ntest-job:\n stage: test\n script:\n - echo "Running custom tests..."\n - make test\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying to production..."\n - make deploy\n only:\n - master\n运行基本的 CI 流程(如构建、测试)\n在管道中定义和运行构建作业\n构建作业是 CI 流程的核心部分,通常包括编译代码和生成构建产物。以下是一个构建作业的示例:\nstages:\n - build\n \nbuild-job:\n stage: build\n # 定义构建过程中需要执行的命令。\n script:\n - echo "Compiling the code..."\n - make\n # 定义构建产物的路径,供后续作业使用。\n artifacts:\n paths:\n - build/\n集成单元测试和集成测试\n测试作业用于运行单元测试和集成测试确保代码的正确性。以下是一个测试作业的示例\nstages:\n - test\n \n# 运行单元测试\nunit-test-job:\n stage: test\n script:\n - echo "Running unit tests..."\n - make test-unit\n \n# 运行集成测试\nintegration-test-job:\n stage: test\n script:\n - echo "Running integration tests..."\n - make test-integration\n查看和分析测试结果\nGitLab CI/CD 提供了详细的测试结果报告,帮助开发人员分析和解决问题。\n\n查看测试日志: 在 Pipelines 页面点击具体作业,查看测试的详细日志和输出。\n分析测试结果: 使用 GitLab 提供的测试报告工具,如 JUnit 报告,查看测试通过率和失败的测试用例。\n\n使用 GitLab CI 的代码质量分析功能\nGitLab CI/CD 提供了代码质量分析功能,帮助识别代码中的潜在问题和改进点。以下是一个代码质量分析的示例:\nstages:\n - code_quality\n \ncode_quality:\n stage: code_quality\n script:\n - echo "Running code quality checks..."\n - eslint . # 使用 ESLint 等工具运行代码质量检查。\n # 生成代码质量报告并存储在 GitLab 中,供后续分析和查看。\n artifacts:\n reports:\n codequality: gl-code-quality-report.json\n进阶技能\n使用 GitLab Runner 执行自定义作业\n编写和配置自定义作业脚本\n自定义作业脚本使得 CI/CD 流程能够灵活适应不同的项目需求。通过在 .gitlab-ci.yml 文件中定义脚本,可以执行特定任务,例如编译、测试、部署等。以下是一个示例,在 script 部分中,可以编写任意 Bash 命令或调用外部脚本文件,以执行具体的任务。\nstages:\n - build\n - test\n - deploy\n \nbuild-job:\n stage: build\n script:\n - echo "Compiling the code..."\n - make\n \ntest-job:\n stage: test\n script:\n - echo "Running tests..."\n - make test\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying to production..."\n - make deploy\n在不同执行环境中运行自定义作业\nGitLab Runner 支持多种执行环境,使得 CI/CD 管道可以在不同的操作系统和容器中运行。以下是一些常见的执行环境配置示例:\nShell 执行环境\nbuild-job:\n stage: build\n script:\n - echo "Running in shell..."\n - make\n tags:\n - shell\nDocker 执行环境\nbuild-job:\n stage: build\n image: maven:3.6.3-jdk-8\n script:\n - echo "Running in Docker..."\n - mvn install\nKubernetes 执行环境\nbuild-job:\n stage: build\n script:\n - echo "Running in Kubernetes..."\n - kubectl apply -f deployment.yaml\n tags:\n - kubernetes\n利用并行作业和矩阵构建提高效率\n并行作业和矩阵构建使得多个作业可以同时运行从而加快 CI/CD 管道的执行速度。以下是并行作业和矩阵构建的示例:\n并行作业\nstages:\n - test\n \ntest-job-1:\n stage: test\n script:\n - echo "Running test job 1..."\n - make test-1\n \ntest-job-2:\n stage: test\n script:\n - echo "Running test job 2..."\n - make test-2\n矩阵构建\nstages:\n - test\n \ntest-job:\n stage: test\n script:\n - echo "Running tests..."\n - make test\n parallel:\n matrix:\n - TEST_ENV: ["python2.7", "python3.6"]\n - DB: ["mysql", "postgres"]\n使用 GitLab Secrets 进行安全管理\nGitLab CI/CD 中的秘密变量和环境变量管理\nGitLab 提供了管理秘密变量和环境变量的功能,以确保敏感信息(如 API 密钥、密码等)不会泄露。可以在 GitLab 项目或组的设置中定义这些变量。\n定义秘密变量:\n\n进入项目设置: Settings → CI/CD → Variables\n点击 “Add Variable”\n输入变量名称和值并选择保护选项如保护、掩码\n\n在 .gitlab-ci.yml 中安全使用秘密\n在 .gitlab-ci.yml 文件中,可以通过 ${VARIABLE_NAME} 的形式引用环境变量和秘密变量。通过这种方式,可以确保敏感信息不会暴露在代码库中。\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying to production..."\n - deploy --api-key=${API_KEY} --password=${PASSWORD}\n配置和管理 GitLab 项目和组的秘密\nGitLab 允许在项目和组级别管理秘密变量,便于多个项目共享相同的配置。\n项目级变量\n\n进入项目设置: Settings → CI/CD → Variables\n添加或编辑变量\n\n组级变量\n\n进入组设置: Group Settings → CI/CD → Variables\n添加或编辑变量\n\n多阶段管道和依赖管理\n定义多阶段multi-stage管道\n多阶段管道通过定义不同的阶段如 build、test、deploy来组织 CI/CD 流程。以下是一个多阶段管道的示例:\nstages:\n - build\n - test\n - deploy\n \nbuild-job:\n stage: build\n script:\n - echo "Building the project..."\n - make build\n \ntest-job:\n stage: test\n script:\n - echo "Testing the project..."\n - make test\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying the project..."\n - make deploy\n阶段之间的依赖管理和条件执行\n**通过定义阶段之间的依赖关系,可以控制作业的执行顺序和条件执行。**例如,可以使用 needs 关键字定义依赖关系:\nstages:\n - build\n - test\n - deploy\n \nbuild-job:\n stage: build\n script:\n - echo "Building the project..."\n - make build\n \ntest-job:\n stage: test\n script:\n - echo "Testing the project..."\n - make test\n needs: ["build-job"]\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying the project..."\n - make deploy\n only:\n - master\n使用 Needs 关键字优化管道执行顺序\n使用 needs 关键字可以显著优化管道的执行顺序,避免不必要的等待时间:\nstages:\n - build\n - test\n - deploy\n \nbuild-job:\n stage: build\n script:\n - echo "Building the project..."\n - make build\n \nunit-test-job:\n stage: test\n script:\n - echo "Running unit tests..."\n - make test-unit\n needs: ["build-job"]\n \nintegration-test-job:\n stage: test\n script:\n - echo "Running integration tests..."\n - make test-integration\n needs: ["build-job"]\n \ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying the project..."\n - make deploy\n needs: ["unit-test-job", "integration-test-job"]\n集成第三方服务如 Docker Registry、Kubernetes\n配置和使用 GitLab 内置的 Docker Registry\nGitLab 提供内置的 Docker Registry方便用户存储和管理 Docker 镜像。以下是配置和使用的步骤:\n\n\n启用 Docker Registry:\n\n进入项目设置: Settings → CI/CD → Container Registry\n确认 Docker Registry 已启用\n\n\n\n登录 Docker Registry:\n$ docker login registry.gitlab.com\n\n\n构建和推送 Docker 镜像:\nstages:\n - build\n - deploy\n \nbuild-job:\n stage: build\n image: docker:latest\n services:\n - docker:dind\n script:\n - docker build -t registry.gitlab.com/your-namespace/your-project:latest .\n - docker push registry.gitlab.com/your-namespace/your-project:latest\n\n\n在管道中构建和推送 Docker 镜像\n通过在管道中构建和推送 Docker 镜像,可以实现自动化的容器化部署:\nstages:\n - build\n - deploy\n \nbuild-job:\n stage: build\n image: docker:latest\n services:\n - docker:dind\n script:\n - docker build -t registry.gitlab.com/your-namespace/your-project:latest .\n - docker push registry.gitlab.com/your-namespace/your-project:latest\n \ndeploy-job:\n stage: deploy\n script:\n - docker pull registry.gitlab.com/your-namespace/your-project:latest\n - docker run -d registry.gitlab.com/your-namespace/your-project:latest\n only:\n - master\n集成 Kubernetes 进行持续部署\nGitLab CI/CD 可以与 Kubernetes 集成,实现自动化的持续部署:\n\n\n配置 Kubernetes 集群:\n\n在 GitLab 项目的 Kubernetes 集成页面添加集群信息\n\n\n\n在管道中使用 Kubernetes:\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n script:\n - kubectl apply -f deployment.yaml\n tags:\n - kubernetes\n\n\n使用 GitLab Kubernetes 集群管理工具\nGitLab 提供了 Kubernetes 集群管理工具,简化集群的配置和管理:\n\n添加 Kubernetes 集群:\n\n进入项目设置: Operations → Kubernetes\n添加集群信息API URL、CA 证书、Token 等)\n\n\n管理集群:\n\n使用 GitLab 提供的界面管理集群中的资源,如 Pods、Services 等\n配置自动化的 CI/CD 管道,实现持续部署\n\n\n\n高级实践\n持续交付CD流程\n定义和实现持续交付CD管道\n持续交付CD是指将代码在经过一系列自动化测试后自动部署到预生产或生产环境。以下是一个持续交付管道的示例\nstages:\n - build # 定义构建阶段\n - test # 定义测试阶段\n - deploy # 定义部署阶段\n \nbuild-job:\n stage: build # 指定作业所属的阶段\n script:\n - echo "Building the project..."\n - make build\n artifacts:\n paths:\n - build/ # 保存构建产物供后续使用\n \ntest-job:\n stage: test # 指定作业所属的阶段\n script:\n - echo "Running tests..."\n - make test\n dependencies:\n - build-job # 使用构建阶段的产物\n \ndeploy-job:\n stage: deploy # 指定作业所属的阶段\n script:\n - echo "Deploying to production..."\n - make deploy\n only:\n - master # 仅在 master 分支上执行部署\n environment:\n name: production # 部署环境名称\n url: production.example.com # 部署环境的 URL\n \n配置环境部署策略\nGitLab 提供了丰富的环境和部署策略配置选项,确保部署过程的安全性和稳定性。\n动态环境\n用于临时创建环境进行测试或演示。\nenvironment:\n name: review/$CI_COMMIT_REF_NAME\n url: https://$CI_COMMIT_REF_NAME.example.com\n on_stop: stop_review\n手动部署\n需要手动确认才能执行部署。\ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying to production..."\n - make deploy\n when: manual\n使用 GitLab 的环境和部署管理功能\nGitLab 提供环境和部署管理功能,帮助开发者和运维人员轻松管理不同的部署环境。\n\n查看环境状态: 在项目的 Environments 页面查看所有环境的状态和部署历史。\n手动触发部署: 在 Environments 页面手动触发部署任务。\n环境保护: 配置环境保护规则,限制谁可以部署到特定环境。\n\n回滚和部署策略优化\n部署过程中可能会遇到问题需要回滚到之前的版本。可以通过以下方式实现回滚和优化部署策略\n自动回滚: 在部署失败时自动回滚到上一个稳定版本。\ndeploy-job:\n stage: deploy\n script:\n - echo "Deploying to production..."\n - make deploy || make rollback\n\n\n蓝绿部署: 同时运行两个版本的应用,切换流量以实现无缝升级。\n\n\n金丝雀发布: 部分用户先访问新版本,观察其稳定性,然后逐步扩展。\n\n\n使用缓存和 Artifacts 提高构建效率\n配置和使用缓存加速构建过程\n缓存可以显著加快构建过程通过缓存依赖和构建中间结果减少重复工作。\n配置缓存\ncache:\n paths:\n - .m2/repository\n - node_modules/\n清理缓存\n在需要时清理缓存以确保使用最新的依赖。\ncache:\n key: "$CI_COMMIT_REF_SLUG"\n paths:\n - .m2/repository\n policy: push\n定义和管理 Artifacts\nArtifacts 是管道运行过程中生成的文件,通常用于后续阶段或作为构建产物存储。并在 GitLab 界面查看和下载 artifacts。\nartifacts:\n paths:\n - build/\n优化缓存和 Artifacts 的存储策略\n为了更好地利用缓存和 artifacts优化存储策略非常重要。\n按分支缓存\n不同分支使用不同的缓存避免相互影响。\ncache:\n key: "$CI_COMMIT_REF_NAME"\n paths:\n - .m2/repository\n长期存储\n重要的构建产物可以配置长期存储避免被清理。\nartifacts:\n paths:\n - build/\n expire_in: 1 month\n部署到 Kubernetes 和其他云平台\n使用 GitLab CI/CD 管道部署到 Kubernetes 集群\n将应用部署到 Kubernetes 集群,可以利用其强大的容器编排和管理能力。\n配置 Kubernetes 集群:\n\n在 GitLab 项目的 Kubernetes 集成页面添加集群信息。\n配置 kubeconfig 文件,用于访问 Kubernetes 集群。\n\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n script:\n - kubectl apply -f k8s/deployment.yaml\n - kubectl apply -f k8s/service.yaml\n tags:\n - kubernetes\n配置和使用 GitLab 的 Auto DevOps 功能\nAuto DevOps 是 GitLab 提供的自动化 CI/CD 流程,适用于常见的开发场景。启用 Auto DevOps 后GitLab 会自动检测并运行合适的 CI/CD 管道。\n\n启用 Auto DevOps:\n\n在项目设置页面启用 Auto DevOps。\n配置 Kubernetes 集群和相关的 CI/CD 设置。\n\n\n定制 Auto DevOps: 可以通过自定义 .gitlab-ci.yml 文件来扩展和定制 Auto DevOps 流程。\n\n集成其他云平台进行部署\n通过 GitLab CI/CD 管道,可以将应用部署到各种云平台。\n部署到 AWS\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n image: amazon/aws-cli\n script:\n - aws s3 cp build/ s3://my-bucket/ --recursive\n only:\n - master\n部署到 GCP\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n image: google/cloud-sdk\n script:\n - gcloud auth activate-service-account --key-file $GCP_KEY_FILE\n - gcloud app deploy\n only:\n - master\n部署到 Azure\nstages:\n - deploy\n \ndeploy-job:\n stage: deploy\n image: mcr.microsoft.com/azure-cli\n script:\n - az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID\n - az webapp up --name myapp --resource-group myResourceGroup --location "East US"\n only:\n - master\n性能优化和故障排查\n优化管道执行时间和资源使用\n通过以下方法可以优化 CI/CD 管道的执行时间和资源使用:\n\n并行执行: 将作业并行化,减少整体执行时间。\n缓存利用: 使用缓存减少重复工作。\n按需执行: 使用 only 和 except 关键字控制作业执行条件。\n\n监控和分析管道性能指标\nGitLab 提供了多种监控和分析工具,帮助优化管道性能:\n\nPipeline Analytics: 查看管道执行时间和成功率等指标。\nJob Artifacts: 分析作业的日志和生成的报告。\nGitLab CI/CD Monitoring: 使用外部监控工具(如 Prometheus、Grafana集成 GitLab 的 CI/CD 监控。\n\n常见错误和问题的排查方法\n常见错误包括作业失败、超时、依赖问题等。排查方法如下\n\n查看日志: 详细查看作业日志,分析错误信息。\n重试作业: 对于临时性问题,可以尝试重试作业。\n环境检查: 确认执行环境的配置和依赖是否正确。\n\n使用 GitLab CI/CD 的调试和日志功能\nGitLab CI/CD 提供了丰富的调试和日志功能,帮助定位和解决问题:\n\n\nDebug 作业: 在 .gitlab-ci.yml 中添加调试信息。\nscript:\n - echo "Debug info:"\n - env\n - make test\n\n\n\n查看作业日志: 在 GitLab 界面查看详细的作业执行日志。\n\n\n使用 SSH 访问 Runner: 在调试模式下使用 SSH 访问 Runner进行更深入的调试。\n\n"},"Technology/SoftwareEngineering/自动化流程/工具使用/Jenkins":{"title":"Jenkins","links":[],"tags":["技术/软件工程","软件工程/自动化流程"],"content":"Jenkins 概述\n\nJenkins 是什么\nJenkins 是一种广泛使用的开源自动化服务器旨在简化和自动化软件开发过程中的各种任务特别是在持续集成CI和持续交付CD方面。 持续集成是一种软件开发实践强调频繁地将代码集成到共享代码库中并自动进行构建和测试以尽早发现和解决集成问题。持续交付进一步扩展了这一概念通过自动化部署管道使得代码可以在任何时间点安全地部署到生产环境中。Jenkins 通过插件体系支持构建、测试和部署的自动化工作流,是 CI/CD 实践的重要工具。\nJenkins 的历史与发展\nJenkins 的前身是 Hudson由 Sun Microsystems 的开发者 Kohsuke Kawaguchi 于 2004 年创建。Hudson 在快速开发和社区支持下迅速流行,然而在 2011 年,由于与 OracleSun Microsystems 被 Oracle 收购在商标权和项目控制方面的分歧Hudson 社区分裂Kawaguchi 和大部分社区成员创建了一个新的项目 Jenkins。自此之后Jenkins 迅速成为 CI/CD 领域的主流工具,并在全球范围内得到了广泛应用和支持。\nJenkins 的发展伴随着软件开发方式的演变,从最初的自动化构建工具,逐渐扩展为一个可以支持复杂持续交付和 DevOps 实践的平台。随着社区贡献的插件数量不断增加Jenkins 的功能覆盖了从源码管理、编译、测试到部署的各个环节。近年来Jenkins 社区推出了 Jenkins X专注于云原生 CI/CD进一步推动了 Jenkins 在容器化和微服务架构中的应用。\nJenkins 的架构及工作原理\n\nJenkins 的核心架构由三部分组成主服务器Master、构建代理Agent/Slave 和 工作节点Node。主服务器负责管理 Jenkins 的核心功能包括调度构建作业、分配工作给构建代理、监控代理的执行情况以及提供用户接口。构建代理是实际执行构建、测试等任务的工作节点可以分布在不同的物理或虚拟机器上。通过分布式架构Jenkins 能够高效处理大规模并行任务。\n\nJenkins 的工作原理基于流水线Pipeline模型流水线定义了构建、测试、部署等一系列任务的执行步骤。用户可以通过 Jenkins UI 或 Jenkinsfile文本文件形式来定义流水线。Jenkins 通过与源码管理系统(如 Git、构建工具如 Maven、Gradle和部署工具如 Kubernetes、Ansible等的集成实现自动化的端到端软件交付流程。\nJenkins 与其他 CI/CD 工具的对比\nJenkins 作为 CI/CD 工具的代表,与其他流行的工具如 GitLab CI、Travis CI、CircleCI、Bamboo 等存在差异。Jenkins 的优势在于其高度的可扩展性和灵活性,通过数千种插件可以与各种工具和平台集成,适用于从小型团队到大型企业的各种规模的项目。然而,这种灵活性也带来了较高的配置和维护成本。\n相比之下GitLab CI 与 GitLab 紧密集成,适合使用 GitLab 进行源码管理的团队Travis CI 和 CircleCI 提供简便的配置和云端执行适合中小型团队的持续集成需求Bamboo 则与 Atlassian 生态系统深度集成,适合使用 Jira、Bitbucket 等 Atlassian 工具链的团队。\n选择哪种工具往往取决于团队的现有技术栈、规模、预算以及特定需求。\nJenkins 安装和配置\nJenkins 提供 多种安装方式,用户可以根据需求和环境选择适合的 安装方法。\n初始配置和界面概览\n\n在完成 Jenkins 的安装后,用户需要进行初始配置。第一次启动 Jenkins 时,会提示输入管理员密码,之后进入配置向导。配置向导会引导用户安装推荐的插件、创建管理员用户、配置邮件通知等基础设置。\nJenkins 的用户界面直观且功能强大。 主界面分为多个部分包括主菜单Dashboard、视图Views、构建队列Build Queue和系统管理Manage Jenkins。用户可以在主菜单中创建新的 Job、查看当前的构建状态和历史记录、配置 Jenkins 系统设置等。\n\n系统配置全局安全设置、系统信息、环境变量配置\n系统配置是 Jenkins 正常运行的核心,良好的系统配置有助于提升 Jenkins 的性能、安全性和易用性。\n\n全局安全设置Jenkins 提供多种安全控制机制包括用户身份验证、授权策略、SSL/TLS 加密、Agent 通信加密等。管理员可以配置基于角色的访问控制Role-Based Access ControlRBAC限制用户对不同项目和资源的访问权限。\n系统信息Jenkins 系统信息页面显示了有关 Jenkins 实例的详细信息,包括 JVM 参数、系统属性、环境变量、插件版本等。这些信息对于故障排查和性能优化非常重要。\n环境变量配置Jenkins 支持配置全局和 Job 级别的环境变量,这些变量可以在构建过程中使用。例如,可以配置 JAVA_HOME、MAVEN_HOME 等环境变量,确保构建脚本在执行时能够找到正确的工具和依赖项。\n\n\n用户管理创建用户和角色权限分配\n用户管理是 Jenkins 系统配置中的重要部分。**Jenkins 支持多种用户管理方式包括内置用户数据库、LDAP、Active Directory 等。**管理员可以创建用户账户,并通过角色策略分配权限,确保不同用户具有适当的操作权限。\n\n创建用户和角色管理员可以通过 Jenkins UI 创建新用户,并为用户分配特定的角色。角色可以是系统管理员、开发人员、测试人员等,根据角色的不同,用户在 Jenkins 中的操作权限也会有所不同。\n权限分配Jenkins 通过授权策略控制用户的操作权限。常见的授权策略包括基于项目的矩阵权限策略、基于角色的权限策略等。管理员可以灵活配置用户对不同 Job、视图、节点的访问和操作权限确保系统的安全性和管理的可控性。\n\nJenkins 插件系统\nJenkins 的强大功能和灵活性主要得益于其丰富的插件系统。插件为 Jenkins 提供了各种扩展能力,如源码管理、构建工具、测试框架、部署工具的集成,以及 UI 增强、安全性增强等。通过插件Jenkins 可以适应不同的开发流程、工具链和部署环境。\n\n插件的重要性Jenkins 的核心非常轻量级,而其大部分功能都是通过插件实现的。这种设计使得 Jenkins 能够根据项目需求进行定制化,避免了功能冗余和系统过度复杂化。插件生态的活跃程度也是 Jenkins 社区的重要标志,数以千计的插件为全球用户提供了广泛的选择。\n插件管理方法插件管理是 Jenkins 系统维护的重要内容。管理员可以通过 Jenkins UI 的插件管理界面安装、更新和卸载插件。安装插件时,推荐选择通过官方插件库进行,确保插件的安全性和稳定性。管理员还需要定期检查插件的更新,并测试更新前后的兼容性,以避免系统问题。\n\n\n常用插件介绍与配置\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n插件主要功能应用场景工作环节额外说明Git Plugin支持 Jenkins 与 Git 版本控制系统的集成。适用于使用 Git 作为版本控制系统的项目,实现代码的拉取、分支管理、触发基于 Git 事件的构建。源码管理与 GitHub、GitLab 等平台集成良好,支持 Webhook、Pull Request 构建触发。Pipeline Plugin允许用户使用代码Jenkinsfile定义构建、测试和部署流程。适用于需要复杂 CI/CD 流水线的项目,支持 Declarative 和 Scripted 两种 Pipeline 语法,提升自动化程度和流程可重复性。构建/流水线Pipeline 是 Jenkins 自动化的核心插件,几乎所有复杂的 Jenkins 实践都依赖它。Blue Ocean提供现代化的 Jenkins UI提升 Pipeline 可视化体验。适用于希望通过直观的图形界面管理和监控 Pipeline 的团队,特别是在大型团队和复杂项目中。用户界面/可视化提供更好的 Pipeline 可视化和执行状态展示便于调试和分析。Maven Integration Plugin提供对 Apache Maven 项目的集成支持。适用于使用 Maven 进行构建的 Java 项目,简化 Maven 生命周期管理和依赖处理。构建/编译支持自动化处理 Maven 构建、测试、打包、部署,集成代码质量分析工具(如 SonarQube。Docker Plugin支持在 Docker 容器中运行 Jenkins 构建任务。适用于希望在隔离环境中运行构建任务的项目,特别是需要一致性构建环境的场景,如构建微服务、容器化应用等。构建/环境管理通过容器化技术确保构建环境的一致性,支持 Docker 镜像的构建、推送和运行。Credentials Plugin提供安全管理和存储凭证如密码、SSH 密钥、API Tokens。适用于需要在构建过程中使用敏感信息的项目如推送代码到 Git 仓库、访问 API、登录服务器等。安全/凭证管理与其他插件集成良好,支持在 Pipeline 中安全使用凭证避免明文暴露敏感信息。GitHub Plugin提供与 GitHub 的深度集成支持,管理 Webhook、Pull Request 触发构建。适用于在 GitHub 上托管代码的项目,自动化处理 Pull Request 流程、代码变更触发构建等。源码管理/集成与 Git Plugin 搭配使用,提供对 GitHub 特定功能的支持如检查状态、自动合并等。Slack Notification Plugin支持将 Jenkins 构建状态通知发送到 Slack 频道。适用于需要即时通知构建状态的团队,特别是在 DevOps 实践中,通过 Slack 实时通知团队成员构建成功或失败。通知提供消息格式化、频道选择等配置选项支持根据构建结果触发不同的通知。JUnit Plugin解析并展示 JUnit 测试结果,生成测试报告。适用于需要集成单元测试的项目,通过自动化测试提升代码质量,生成并展示测试结果和趋势分析。测试/报告生成支持解析 JUnit 格式的 XML 报告,适用于 Java 项目和使用类似测试框架的其他项目。SonarQube Plugin与 SonarQube 集成,进行代码质量分析。适用于需要进行代码静态分析的项目,通过集成 SonarQube自动化分析代码质量生成报告。代码质量/分析适用于希望持续监控代码质量的团队特别是在大型项目和敏捷开发环境中。Parameterized Trigger Plugin允许触发其他 Jenkins Job 并传递参数。适用于需要跨 Job 触发构建任务的项目,特别是在复杂的 CI/CD 流程中,通过参数化触发实现灵活的构建配置。构建/触发器支持在 Pipeline 中调用和配置传递动态参数以适应不同的构建需求。Active Choices Plugin允许在参数化构建中动态生成参数选项。适用于需要用户在构建时根据特定条件选择不同参数的场景例如多分支部署、不同环境配置等。构建/参数化提供参数化选择的动态生成根据条件展示不同的选项提升参数化构建的灵活性。ThinBackup Plugin提供 Jenkins 配置和数据的备份与恢复功能。适用于需要定期备份 Jenkins 配置、Job 数据等的场景,确保在系统故障时可以快速恢复。备份/恢复支持增量备份、定时备份等功能,简化 Jenkins 的运维管理。Build Pipeline Plugin允许将多个 Job 组合成一个可视化的流水线。适用于需要通过多个 Job 组合实现复杂流水线的项目,提升流程的可视化和可管理性。流水线/可视化提供可视化的流水线展示和管理,适用于 DevOps 实践中多阶段自动化流程的实现。Job DSL Plugin通过代码定义 Jenkins Job支持批量创建和管理 Job。适用于需要自动化配置 Jenkins Job 的团队,特别是在大规模项目中,通过 DSL 脚本简化 Job 管理。构建/配置管理支持通过代码定义和管理 Job与版本控制系统集成提升可维护性和可移植性。Mailer Plugin发送构建结果通知邮件。适用于需要通过邮件通知构建结果的项目通过自动化邮件通知开发团队构建状态、测试结果等。通知提供简单的邮件配置选项支持根据构建结果发送不同的通知邮件。AnsiColor Plugin在 Jenkins 控制台输出中显示带颜色的日志。适用于希望在控制台中通过颜色区分不同类型日志信息的场景,如错误、警告、调试信息等。日志/可视化提供对多种终端颜色的支持提升控制台日志的可读性便于调试和分析。Kubernetes Plugin支持在 Kubernetes 集群中动态创建 Jenkins Agent运行构建任务。适用于在 Kubernetes 环境中运行 Jenkins 的团队,自动化创建和管理构建节点,确保构建环境的弹性和可扩展性。构建/环境管理通过 Kubernetes 动态管理 Jenkins Agent适用于大规模分布式构建环境。JIRA Plugin与 Atlassian JIRA 集成,自动化工单管理。适用于使用 JIRA 进行项目管理的团队,通过 Jenkins 自动创建、更新、关闭 JIRA 工单。项目管理/工单管理提供 JIRA 和 Jenkins 之间的双向集成提升项目管理自动化水平适用于敏捷开发团队。Artifactory Plugin集成 JFrog Artifactory用于管理和发布构件。适用于需要管理构件存储和发布的项目通过集成 Artifactory自动化管理构件的版本、依赖和分发。构件管理/发布支持与 Artifactory 的双向集成,自动化管理构件生命周期,适用于企业级 DevOps 实践。\n插件的更新和备份策略\n插件的更新和备份策略是 Jenkins 管理中的关键环节。为了保证系统的稳定性和安全性,管理员需要定期更新插件,并在更新前后做好备份。\n\n插件更新插件更新可以通过 Jenkins 的插件管理界面完成。更新前,管理员应先阅读插件的更新日志,了解新版本的改动和潜在影响。更新完成后,建议进行系统测试,确保新插件与现有配置和流水线兼容。\n备份策略定期备份 Jenkins 的配置和插件文件对于应对系统故障和数据丢失非常重要。备份内容包括 Jenkins 的配置文件、Job 定义、插件目录等。管理员可以使用 Jenkins 的备份插件(如 ThinBackup或脚本定期备份这些数据并将备份文件存储在安全的远程位置。\n\n插件冲突与兼容性问题的解决\n插件冲突和兼容性问题是 Jenkins 管理中常见的挑战。当多个插件同时作用于系统时,可能会出现功能冲突或性能问题。为了有效应对这些问题,管理员可以采取以下措施:\n\n隔离测试在更新或安装新插件之前建议先在测试环境中进行隔离测试。通过模拟生产环境的工作流管理员可以检测到潜在的插件冲突并在生产环境中更新前解决这些问题。\n日志分析Jenkins 提供了详细的日志功能,当系统出现问题时,管理员可以通过分析日志文件查找冲突的原因。常见的日志文件包括 Jenkins 主日志、Job 执行日志和插件日志等。\n社区支持Jenkins 社区是解决插件冲突和兼容性问题的重要资源。管理员可以通过 Jenkins 官方论坛、Stack Overflow 等平台寻求社区帮助,也可以直接联系插件的维护者报告问题或获取支持。\n\nJenkins Job\n自由风格项目Freestyle Project\n自由风格项目是 Jenkins 中最基本的 Job 类型也是使用最广泛的。它提供了高度的灵活性允许用户通过图形用户界面GUI配置和管理构建、测试、部署等任务。\n\n简单配置用户可以通过点击和选择的方式配置构建步骤而无需编写代码。\n多种构建步骤支持执行 shell 脚本、批处理命令、调用 Ant、Maven、Gradle 等构建工具,以及集成单元测试和代码质量检查工具。\n灵活的触发机制支持 SCM 轮询、定时构建、Webhook 触发等多种构建触发机制。\n插件支持自由风格项目可以通过安装和配置插件扩展其功能如集成 Git、Subversion 版本控制,使用 SonarQube 进行代码质量分析等。\n\n自由风格项目适用于需要快速搭建和配置的简单构建任务如小型项目的编译、测试和部署。它也是新手用户学习 Jenkins 基本操作的入门选择。\n流水线项目Pipeline Project\n流水线项目是 Jenkins 提供的另一种强大的 Job 类型,它以代码的形式(通常存储在 Jenkinsfile 中定义构建、测试、部署等整个流程。Pipeline 使用 Groovy 语言编写,提供了比自由风格项目更强大的功能和灵活性。\n\nPipeline as Code流水线定义存储在代码中Jenkinsfile并与项目的版本控制系统集成使构建流程的版本管理、审查和协作成为可能。\n复杂的流水线支持定义多阶段Stages的流水线可以串行、并行或条件性地执行不同任务。支持并行执行测试、自动化部署等高级功能。\n两种语法模式支持 Declarative 和 Scripted 两种语法模式。Declarative 语法更简洁适合大多数场景Scripted 语法则更灵活,适合高级用户编写复杂逻辑。\n共享库可以通过共享库Shared Library复用代码片段提升流水线的可维护性和重用性。\n\n流水线项目适合需要高度定制化和自动化的复杂 CI/CD 流程,尤其是在大型团队和企业级项目中。它在微服务、容器化应用和云原生开发中尤为常用。\n多分支流水线项目Multibranch Pipeline Project\n多分支流水线项目是对流水线项目的扩展自动化管理版本控制系统中的多个分支并为每个分支创建独立的 Pipeline Job。它自动检测新分支并根据 Jenkinsfile 定义的流程执行构建和测试。\n\n自动分支检测Jenkins 自动扫描版本控制系统中的所有分支,并为每个分支创建单独的 Job。这意味着新分支一旦创建Jenkins 就会自动为其触发构建。\n分支隔离每个分支都有独立的构建历史和流水线避免了不同分支间的冲突和干扰。\n支持多种版本控制系统支持 Git、Subversion 等版本控制系统,可以通过插件扩展更多 VCS 的支持。\nPull Request 构建:集成 GitHub、GitLab 等平台时,可以自动检测 Pull Request并在合并之前执行构建和测试确保代码质量。\n\n多分支流水线项目适合采用 Git Flow 或其他多分支开发模型的项目,特别是在需要频繁创建和合并分支的团队中。它在大规模、多团队协作的开发环境中表现出色。\nMaven 项目Maven Project\nMaven 项目是专为 Apache Maven 构建工具设计的 Jenkins Job 类型。它集成了 Maven 的构建生命周期,简化了 Maven 项目的配置和管理。\n\nMaven 集成:自动化处理 Maven 的构建生命周期包括编译、测试、打包、部署等步骤。Jenkins 能够直接解析和使用 pom.xml 文件中的配置信息。\n依赖管理通过 Maven 项目Jenkins 可以自动管理项目的依赖关系,并在构建时下载所需的库和插件。\n报告和分析支持生成和展示 Maven 的构建报告、测试报告和代码覆盖率报告(如使用 JaCoCo、Cobertura。\n多模块支持Maven 项目能够处理多模块的 Maven 项目,自动化管理每个模块的构建流程。\n\nMaven 项目专为使用 Maven 构建工具的 Java 项目设计,适合需要利用 Maven 的强大依赖管理和生命周期功能的开发团队。\n外部任务External Job\n外部任务是 Jenkins 提供的一种特殊 Job 类型,主要用于监控和集成在 Jenkins 外部执行的任务。它允许 Jenkins 记录这些任务的执行状态和结果。\n\n任务监控Jenkins 可以监控外部脚本或命令的执行状态,并记录它们的运行日志和结果。\n轻量集成外部任务不直接在 Jenkins 内部执行,但可以通过脚本或外部工具将任务状态反馈到 Jenkins。\n灵活性适合不希望或不能直接在 Jenkins 中执行的任务,如特定的系统任务、批处理作业或定制的自动化脚本。\n\n外部任务适合那些已经存在且不方便迁移到 Jenkins 内部的自动化任务,或需要与其他自动化工具集成的场景。\nPipeline as Code 项目Pipeline-as-Code Project\nPipeline as Code 项目是 Jenkins 鼓励的一种 CI/CD 实践,它将整个 Pipeline 定义通过代码的方式管理,通常与多分支流水线项目结合使用。虽然在技术上,它并不是一个单独的 Job 类型,但它代表了一种管理和执行 Pipeline 的方式。\n\n代码版本化Pipeline 定义与项目代码一起存储在版本控制系统中,所有变更都通过代码审查和版本控制管理。\n自动触发每次代码变更都会触发相应分支的 Pipeline 执行,确保代码在每次提交后都被自动测试和部署。\n集成最佳实践Pipeline as Code 项目通常集成了 DevOps 的最佳实践,如持续集成、持续交付、安全扫描、自动化测试等。\n\nPipeline as Code 项目适合推行 DevOps 文化的团队,尤其是那些希望将自动化流程与代码管理无缝集成的团队。\n组合项目Matrix Project\n组合项目也称为矩阵项目是 Jenkins 中的一种特殊 Job 类型允许用户在多个维度如操作系统、JDK 版本等)上并行运行多个构建配置。\n\n多维度构建允许定义多个轴如操作系统、编译器版本、依赖版本等并为每个组合运行独立的构建。\n并行执行可以在多台机器或多个 Agent 上并行执行构建任务,大大加快测试和构建速度。\n结果聚合组合项目可以汇总和展示所有维度的构建结果帮助用户全面了解构建的兼容性和性能。\n\n组合项目适合需要在不同环境中验证代码兼容性的大型项目如跨平台应用的构建和测试、不同 JDK 版本下的 Java 应用构建等。\n外部工作流External Workflow\n外部工作流是一种允许 Jenkins 与外部工作流引擎集成的 Job 类型。它类似于外部任务,但专注于与外部工作流系统的集成和监控。\n\n工作流集成可以与外部工作流系统如 Apache Airflow、Apache Oozie集成管理复杂的分布式任务。\n状态监控Jenkins 可以监控外部工作流的状态和进度,并在工作流完成时记录结果。\n灵活扩展支持通过脚本和插件与更多外部工作流工具集成。\n\n外部工作流适合需要与现有工作流系统集成的企业特别是那些依赖分布式计算和批处理作业的场景。\n构建流水线插件项目Build Pipeline Plugin Project\n构建流水线插件项目是 Jenkins 的一种扩展,通过 Build Pipeline Plugin用户可以将多个自由风格项目或其他 Job 类型组合成一个流水线,定义复杂的构建、测试和部署流程。\n\n可视化流水线提供图形化界面展示多个 Job 之间的依赖关系和执行顺序,便于管理和监控复杂的流水线流程。\n任务编排支持配置多个 Job 的触发条件和依赖关系,实现复杂任务的编排和自动化执行。\n手动审批支持在流水线的关键步骤中加入手动审批环节适合需要人为干预的发布流程。\n\n构建流水线插件项目适合需要将多个 Jenkins Job 组合成复杂流水线的项目,尤其在 DevOps 实践中,通过可视化管理和监控多个任务的执行,提升团队协作效率。\n配置源码管理Git、Subversion\nJenkins 通过源码管理插件支持多种版本控制系统,包括 Git、Subversion、Mercurial 等。在配置 Job 时,用户可以指定项目的源码管理系统,以便 Jenkins 能够自动拉取最新代码进行构建。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n源码管理系统概述主要特点使用场景Git分布式版本控制系统广泛用于开源和企业项目中。分布式架构支持离线操作、强大的分支管理功能、高效的合并与冲突解决、与 GitHub、GitLab 等平台无缝集成适用于几乎所有类型的软件项目,特别是需要复杂分支管理、多团队协作、开源项目和 DevOps 流程的开发环境。Subversion (SVN)集中式版本控制系统支持精细化权限控制广泛应用于企业。集中式架构便于集中管理、精细的访问控制和权限管理、支持目录级版本控制、提供日志和版本历史的详细记录适用于需要严格权限控制的企业级项目特别是那些需要维护大量历史版本记录和对特定目录进行精确管理的情况。Mercurial分布式版本控制系统类似于 Git但更注重性能和易用性。分布式架构支持离线操作、易于使用性能优异、良好的跨平台支持、简洁清晰的分支和合并模型适用于对性能和易用性有较高要求的开发团队尤其是中小型项目或者在 Git 之外需要额外的分布式版本控制方案时。Perforce (Helix Core)商业化集中式版本控制系统强大而复杂支持大规模项目的版本控制。强大的文件锁定和版本控制机制、集中式管理支持大规模项目、高效处理大型文件、支持代码和数字资产的版本管理适用于大型企业和游戏、影视制作等需要处理大型文件和复杂项目依赖的场景特别是那些需要精确控制和严格管理的开发流程。ClearCaseIBM 提供的集中式版本控制系统适合复杂企业环境。支持复杂的版本管理和配置管理、强大的访问控制、集成化管理开发和配置工具、支持多站点、多平台环境适用于有严格配置管理要求的企业级项目特别是在复杂企业环境中需要管理多种平台和分布式开发团队时。TFS (Azure DevOps Server)微软提供的版本控制系统,集成了项目管理和 CI/CD 工具。集成了版本控制、构建、发布、测试和项目管理、支持 Git 和 TFVC、与 Azure DevOps 深度集成,支持 CI/CD 流水线适用于使用微软技术栈的企业,特别是在使用 Azure 云服务的环境中,或者希望将版本控制与项目管理和 DevOps 工具无缝集成的团队。CVS (Concurrent Versions System)早期流行的集中式版本控制系统,现已逐渐被其他 VCS 取代。集中式管理、简单易用、基本的版本控制功能、早期开发工具集成支持适用于维护旧有的遗留系统或非常小型的项目对于那些历史悠久的代码库或不需要复杂功能的项目依然可能有所使用。BitbucketAtlassian 提供的 Git 版本控制系统,集成了项目管理工具和 CI/CD。Git 支持、与 Jira、Confluence 集成、支持 Pull Request 审查、内置 CI/CD 管道Bitbucket Pipelines适用于与 Atlassian 工具链(如 Jira、Confluence深度集成的团队特别是在使用 Bitbucket Cloud 或 Server 的开发环境中。GitHub全球最流行的 Git 托管平台广泛应用于开源项目和企业开发。Git 支持、强大的 Pull Request 和代码审查功能、支持 GitHub Actions 实现 CI/CD、大量社区插件和工具支持适用于开源项目和需要与全球开发者社区协作的项目以及希望使用 GitHub 提供的丰富 CI/CD 功能和集成能力的企业和个人开发者。\n构建触发器SCM 轮询、Webhook、定时任务\nJenkins 支持多种构建触发器,用户可以灵活配置 Job 的触发条件,确保构建流程在合适的时机自动启动。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n构建触发器概述主要特点使用场景SCM 轮询 (Poll SCM)定期检查源码管理系统SCM的变更当检测到代码变更时触发构建。使用 Cron 表达式配置轮询频率、自动检测源码变更并触发构建、简单易用配置灵活适用于需要定期检查代码变更的项目特别是小型团队或不频繁的代码更新场景。Webhook通过 Webhook 通知直接触发 Jenkins 构建任务。实时性强,无需轮询、减少服务器负载、与 GitHub、GitLab 等 VCS 平台无缝集成适用于希望实时响应代码变更的项目,特别是在大型团队中需要快速反馈或与 GitHub、GitLab 集成的场景。定时构建 (Scheduled Build)在预设的时间点或周期性地触发构建任务。使用 Cron 表达式配置构建时间、支持定时执行构建、可以用于生成每日构建、定期测试等任务适用于需要定期生成构建版本、执行定期任务(如回归测试)或确保构建环境稳定的项目。手动触发 (Manual Trigger)由用户手动启动的构建任务。灵活控制构建启动时间、支持用户通过 UI 或 API 手动触发、适用于测试和特殊场景适用于需要人为控制构建时间的场景,如代码发布前的最后检查、手动执行特定测试等。上游/下游项目触发 (Upstream/Downstream Trigger)当一个 Job 完成时,自动触发另一个相关的 Job。支持多 Job 之间的依赖关系、允许创建复杂的构建链、可以配置在上游任务成功、失败或完成时触发适用于多个构建任务之间存在依赖关系的场景,特别是需要串联多个构建任务或在构建完成后自动执行测试、部署等后续任务的项目。构建后操作触发 (Post-Build Actions)在构建完成后根据结果触发后续操作或构建任务。灵活配置不同结果的触发条件、支持在构建失败、成功、总是等不同情况下触发、适用于自动化发布、通知等后续操作适用于需要根据构建结果自动执行某些操作的场景,如在构建失败时发送通知、在成功时发布 Artefact 或触发下游构建任务。远程触发 (Remote Trigger)通过 HTTP 请求远程触发 Jenkins 构建。支持通过 URL 触发构建、可以配置触发器令牌进行安全控制、适用于系统集成和自动化脚本适用于需要从外部系统或脚本中触发 Jenkins 构建的场景,如通过自动化测试平台、持续集成工具或其他应用直接触发 Jenkins Job。节点标签触发 (Node Label Trigger)根据特定节点或标签触发构建任务。基于节点标签分配构建任务、支持在特定环境或机器上执行构建、提供更多构建调度的灵活性适用于需要在特定机器或环境中执行构建的场景,特别是当不同的构建任务需要不同的硬件资源或软件配置时。参数化触发 (Parameterized Trigger)允许用户在触发构建时传递参数,实现动态构建。用户可以在构建时输入参数、支持根据输入参数动态调整构建流程、适用于需要在不同环境中运行或根据用户输入动态配置的场景适用于需要根据用户输入或外部条件调整构建流程的场景,如在不同环境中部署、生成不同配置的构建 Artefact 或执行特定的测试组合等。Pipeline 触发器 (Pipeline Trigger)当一个 Pipeline 完成时,触发另一个 Pipeline 或 Job。支持流水线之间的依赖和触发、灵活配置触发条件、集成复杂的 CI/CD 流水线适用于多个 Pipeline 或 Job 之间存在依赖关系的复杂 CI/CD 流程,特别是在大规模自动化部署和测试环境中。\n构建步骤编译、测试、打包、部署\n构建步骤定义了 Job 的具体执行内容,是整个 Jenkins 自动化流程的核心部分。根据项目需求,构建步骤可以包括以下内容:\ngraph LR\n A[开始] --> B[编译]\n B --> C[测试]\n C --> D[打包]\n D --> E[部署]\n E --> F[结束]\n \n subgraph 编译阶段\n B1[选择编译工具]\n B2[指定编译路径和选项]\n B --> B1 --> B2\n end\n \n subgraph 测试阶段\n C1[单元测试]\n C2[集成测试]\n C3[端到端测试]\n C --> C1 --> C2 --> C3\n end\n \n subgraph 打包阶段\n D1[生成 JAR/WAR 文件]\n D2[生成前端压缩包]\n D --> D1 --> D2\n end\n \n subgraph 部署阶段\n E1[选择部署工具]\n E2[部署到测试或生产环境]\n E --> E1 --> E2\n end\n\n\n\n编译对于编程语言的编译项目如 Java、C++ 等构建步骤首先执行代码编译。Jenkins 支持多种编译工具,如 Maven、Gradle、Ant 等。配置编译步骤时,用户需要指定编译工具的路径、目标文件和编译选项。\n测试测试是 CI 流程中的关键环节Jenkins 支持集成多种测试框架,如 JUnit、Testing、Selenium 等。用户可以配置单元测试、集成测试和端到端测试的执行步骤,并在构建过程中自动生成测试报告。\n打包编译和测试通过后构建步骤通常包括打包操作。对于 Java 项目,打包步骤可能生成 JAR 或 WAR 文件;对于前端项目,可能生成压缩后的静态资源包。打包步骤可以集成版本控制,确保每个构建都生成唯一标识的可发布包。\n部署最后Jenkins 可以自动将打包好的应用部署到测试环境或生产环境。部署步骤可以使用各种工具,如 Ansible、Docker、Kubernetes 等,实现从构建到发布的全流程自动化。\n\nPipeline 脚本\nPipeline 是 Jenkins 用于定义和执行自动化流程的核心概念。通过 Pipeline用户可以以代码形式定义从构建、测试到部署的整个流程。Pipeline 的优势包括:\n\n可维护性由于 Pipeline 定义在代码中Jenkinsfile团队可以将其纳入版本控制与项目源码同步管理。任何对 Pipeline 的修改都能通过代码审查流程进行,确保变更的安全性和可追溯性。\n复用性Pipeline 支持将常用的步骤和逻辑封装成共享库,供多个项目复用。这不仅提高了开发效率,还减少了重复配置带来的维护成本。\n可视化Jenkins 提供了强大的 Pipeline 可视化工具(如 Blue Ocean帮助团队实时监控和管理 Pipeline 的执行状态,及时发现和解决问题。\n\nDeclarative Pipeline\nDeclarative Pipeline 是 Jenkins 中使用最广泛的 Pipeline 语法,旨在提供更简洁、易读的语法结构,适合大多数项目的自动化需求。\nDeclarative Pipeline 的基本结构如下:\ngraph LR\n A[pipeline] --> B[agent any]\n B --> C[environment]\n C --> D[stages]\n D --> E1[Stage Build]\n E1 --> E2[Steps: Execute Build Tasks]\n D --> F1[Stage Test]\n F1 --> F2[Steps: Execute Test Tasks]\n D --> G1[Stage Deploy]\n G1 --> G2[Steps: Execute Deploy Tasks]\n D --> H[post]\n H --> I1[Always: Cleanup]\n H --> I2[Success: Success Notification]\n H --> I3[Failure: Failure Notification]\n\n subgraph Declarative Pipeline Structure\n B -.-> C -.-> D -.-> H\n end\n\npipeline {\n agent any\n stages {\n stage('Build') {\n steps {\n sh 'make build'\n }\n }\n stage('Test') {\n steps {\n sh 'make test'\n }\n }\n stage('Deploy') {\n steps {\n sh 'make deploy'\n }\n }\n }\n post {\n always {\n echo 'Cleaning up...'\n deleteDir()\n }\n }\n}\n\npipeline定义 Pipeline 的顶级指令块,包含所有 Pipeline 相关的配置。\nagent定义 Pipeline 运行的执行环境。any 表示可以在任何可用的 Agent 上执行。也可以指定特定的 Agent 或容器。\nstages包含多个 stage 块,每个 stage 表示一个独立的构建阶段。\nsteps在 stage 内部定义具体的执行步骤。sh 是执行 Shell 命令的常用指令。\npost定义在 Pipeline 结束后执行的步骤,如清理工作、通知、报告生成等。\n\nDeclarative Pipeline 提供了丰富的条件控制(如 when、input、并行执行parallel以及环境变量管理environment适合定义结构化和易维护的流水线。\nScripted Pipeline\nScripted Pipeline 提供了更大的灵活性和控制力,但其语法相对复杂,通常用于需要高度定制的场景。\nScripted Pipeline 的基本结构如下:\ngraph LR\n A[node] --> B[try]\n B --> C[stage Build]\n C --> D[Steps: Execute Build Tasks]\n B --> E[stage Test]\n E --> F[Steps: Execute Test Tasks]\n B --> G[stage Deploy]\n G --> H[Steps: Execute Deploy Tasks]\n B --> I[catch Exception]\n I --> J[Steps: Handle Failure]\n B --> K[finally]\n K --> L[Steps: Cleanup]\n\n subgraph Scripted Pipeline Structure\n A -.-> B -.-> I -.-> K\n end\n\nnode {\n try {\n stage('Build') {\n sh 'make build'\n }\n stage('Test') {\n sh 'make test'\n }\n stage('Deploy') {\n sh 'make deploy'\n }\n } catch (Exception e) {\n currentBuild.result = 'FAILURE'\n throw e\n } finally {\n echo 'Cleaning up...'\n deleteDir()\n }\n}\n\nnode表示一个执行节点。所有的 Pipeline 步骤都在 node 块中定义。\nstage定义构建的不同阶段与 Declarative Pipeline 类似。\ntry-catch-finallyScripted Pipeline 中可以使用标准的 Groovy 语法进行异常处理和流程控制。\n\n由于 Scripted Pipeline 基于 Groovy 语言,用户可以在其中编写复杂的逻辑、调用自定义函数和类,适合高级用户和特殊需求。\nStages 步骤\nStages 是 Jenkins Pipeline 中的核心构建块,每个 stage 代表了 Pipeline 执行过程中的一个主要步骤或阶段。Stages 可以用于划分构建、测试、部署等不同的任务,帮助组织和管理复杂的构建流程。\n\n阶段划分Stages 将整个 Pipeline 分割为多个独立的部分,每个部分都代表一个逻辑步骤,如编译代码、运行测试、部署应用等。\n并行执行多个 Stages 可以在 parallel 指令下并行执行,减少总的执行时间。\n条件执行Stages 可以基于条件(如环境变量、分支名称等)选择性地执行,提升 Pipeline 的灵活性。\n可视化Jenkins 提供了直观的界面展示 Stages 的执行情况,便于监控和调试。\n\npipeline {\n agent any\n stages {\n stage('Build') {\n steps {\n sh 'make build'\n }\n }\n stage('Test') {\n steps {\n sh 'make test'\n }\n }\n stage('Deploy') {\n steps {\n sh 'make deploy'\n }\n }\n }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令关键字描述使用场景stage定义 Pipeline 的一个阶段,每个阶段包含特定的构建、测试或部署任务。用于将 Pipeline 划分为多个逻辑阶段如“构建”、“测试”、“部署”等便于组织和管理复杂的流程。steps在 stage 中定义具体执行的步骤或操作。用于在一个 stage 内执行一组具体的任务,如运行 Shell 命令、调用外部服务、存档文件等。parallel并行执行多个 stage提高 Pipeline 的执行效率。用于同时执行多个任务如并行运行测试、构建不同的模块或部署到多个环境。when基于条件执行某个 stage 或步骤。用于根据分支、环境变量、文件存在与否等条件控制某个阶段的执行如仅在特定分支上运行部署阶段。agent指定在哪个 Jenkins 节点或容器中运行该 stage。用于为特定阶段分配执行环境特别是在需要不同的构建环境或资源时如在特定的 Docker 容器中运行测试。post定义在 stage 完成后执行的操作。用于在阶段完成后触发清理、通知、存档等操作确保即使阶段失败也能执行必要的后续步骤。environment为特定 stage 定义环境变量。用于为某个阶段设置临时的环境变量,如 API 密钥、构建标志等确保变量仅在该阶段有效。input在 stage 开始前等待用户输入或确认。用于在高风险操作如生产环境部署前暂停并等待人工确认确保安全性。options为特定 stage 配置选项如超时时间、重试次数等。用于控制某个阶段的行为例如设置超时时间防止阶段长时间挂起或在阶段失败时自动重试。tools指定特定阶段使用的构建工具版本如 Maven、Gradle。用于确保某个阶段使用正确版本的构建工具特别是在不同阶段需要不同工具版本时如不同版本的 JDK 或 Maven。timeout为特定 stage 设置执行超时时间超时后自动终止。用于防止某个阶段长时间执行特别是在长时间运行的任务中确保流程的整体执行时间在可控范围内。retry在 stage 中步骤失败时重试指定次数。用于处理偶发的临时性错误例如网络请求失败、外部服务响应超时等确保任务的健壮性。failFast在并行执行的 stage 中,一旦某个 stage 失败,立即终止其他并行 stage。用于节省资源当某个关键阶段失败时立即停止所有并行任务避免不必要的资源消耗。input在 stage 开始前暂停执行等待用户输入或确认。用于在关键阶段如生产部署前需要人工确认时确保操作的安全性。lock在执行 stage 时获取锁,确保该阶段的操作是独占的。用于在多个 Pipeline 需要访问共享资源如数据库、环境配置避免并发冲突确保资源安全地被独占访问。stages定义嵌套的多个 stage用于创建分层的 Pipeline。用于组织更复杂的流程例如在一个大的 stage 内包含多个子 stage以实现多层次的执行结构。\nSteps 步骤\nSteps 是 Pipeline 中执行具体任务的最小单元,每个 step 代表一个独立的操作如执行命令、调用工具、发送通知等。Steps 是构建自动化流程的基础,可以根据需求灵活组合和配置。\n\n灵活组合Steps 可以按需组合,构建出适合特定项目需求的执行流程。\n参数化执行许多 Steps 支持传入参数,实现动态配置和执行。\n条件控制Steps 可以与条件语句结合,实现复杂的逻辑控制,如在特定情况下跳过某些步骤。\n\nsteps {\n sh 'npm install'\n sh 'npm test'\n archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令关键字描述使用场景sh在 Unix/Linux 系统上执行 Shell 命令。用于执行 Shell 脚本、命令行操作如编译代码、运行测试、部署应用等。bat在 Windows 系统上执行批处理命令。适用于在 Windows 环境下执行构建、测试、部署任务。checkout从版本控制系统如 Git、SVN检出代码。用于在 Pipeline 中拉取最新代码以确保构建和测试基于最新的源码。echo在控制台输出消息。用于在 Pipeline 中输出调试信息、状态消息或变量值便于跟踪和分析执行过程。sleep暂停 Pipeline 执行指定时间。用于在步骤之间插入延迟例如等待外部服务响应、控制构建节奏等。dir切换到指定的工作目录并在该目录中执行后续步骤。用于在特定目录下执行构建任务如切换到项目目录进行编译、测试等操作。withEnv设置环境变量并在定义的步骤范围内使用。用于临时改变环境变量例如配置 PATH、设置 API 密钥等确保这些变量仅在特定步骤中生效。archiveArtifacts存档构建生成的工件如 JAR 文件、日志、报告等。用于将构建生成的文件存档便于后续使用、分发或备份。junit解析 JUnit 测试结果并生成测试报告。用于在 Jenkins 中展示单元测试结果并生成测试趋势分析。mail发送电子邮件通知。用于在 Pipeline 执行过程中发送通知例如在构建失败时通知开发团队。input暂停 Pipeline 执行等待用户输入或确认。用于在关键步骤如生产环境部署前等待人工确认确保操作安全。timeout为步骤或阶段设置超时时间超时后自动终止。用于限制步骤或阶段的最长执行时间防止长时间挂起的任务阻塞 Pipeline。retry在失败时重试指定次数。用于处理可能出现暂时性错误的操作例如网络请求失败、依赖下载失败等。parallel并行执行多个步骤或阶段。用于提高 Pipeline 执行效率特别是在多任务并行的场景下如同时在多个环境中运行测试。build在 Pipeline 中触发其他 Jenkins Job。用于在一个 Pipeline 中调用其他 Job例如在构建完成后触发部署 Job 或运行测试 Job。tool在 Pipeline 中指定构建工具(如 Maven、Gradle。用于配置和使用特定版本的构建工具确保环境的一致性。withCredentials在 Pipeline 中使用存储的凭证进行操作。用于在需要认证的操作中安全地使用敏感信息,如推送代码到 Git 仓库、访问 API、登录服务器等。script在 Declarative Pipeline 中执行 Groovy 脚本。用于实现复杂的逻辑控制,或调用自定义的 Groovy 函数。stash保存文件以供后续使用。用于在不同的节点或步骤之间共享文件。unstash恢复之前保存的文件。用于在需要共享的步骤中使用之前保存的文件。catchError捕获错误并继续执行 Pipeline防止因非致命错误导致整个 Pipeline 中断。用于在 Pipeline 执行过程中捕获并处理可能的错误确保即使出现错误也能继续执行其他步骤。timestamps为 Pipeline 控制台输出添加时间戳。用于记录每个步骤的精确执行时间便于调试和性能分析。cleanWs清理工作区删除构建过程中生成的临时文件和目录。用于在 Pipeline 结束后清理 Jenkins 工作区释放磁盘空间确保环境整洁。ws在特定的工作空间目录中运行步骤。用于在指定的工作区中执行步骤特别是在多个 Pipeline 共享同一个节点时,避免工作区冲突。\nPost Actions 步骤\nPost Actions 是在 Pipeline 执行完毕后触发的操作用于处理构建结果、清理资源、发送通知等。post 块根据构建的不同结果(如 success、failure、always执行相应的操作确保在任何情况下都能正确处理构建流程的结束阶段。\n\n结果驱动Post Actions 根据构建结果自动触发相应的动作,确保在成功时发布、在失败时报警。\n资源清理Post Actions 可以用于释放资源、清理临时文件、关闭连接等,避免资源泄漏或积累。\n通知机制Post Actions 支持集成通知系统如邮件、Slack在构建完成后通知相关人员或系统。\n\npost {\n success {\n echo 'Build succeeded!'\n mail to: 'team@example.com',\n subject: "Build #${env.BUILD_NUMBER} succeeded",\n body: "Great news! The build succeeded."\n }\n failure {\n echo 'Build failed!'\n mail to: 'team@example.com',\n subject: "Build #${env.BUILD_NUMBER} failed",\n body: "Unfortunately, the build failed. Please check the logs."\n }\n always {\n cleanWs() // 清理工作区\n }\n}\nPipeline 实现动态参数化构建\n参数化 Pipeline 是 Jenkins 提供的一种灵活机制允许在执行构建时动态传入参数以实现更为灵活的构建流程。Jenkins 支持多种类型的参数,如字符串、布尔值、选择列表、密码等。这种动态化的构建方式特别适用于多分支开发或多环境部署的场景。\n使用参数\n在 Jenkinsfile 中,可以通过 parameters 块定义各种类型的参数。这些参数可以在构建时由用户输入,或者采用默认值。\npipeline {\n parameters {\n string(name: 'BRANCH', defaultValue: 'master', description: '分支名称')\n booleanParam(name: 'DEPLOY', defaultValue: true, description: '是否部署')\n }\n stages {\n stage('Build') {\n steps {\n echo "Building branch: ${params.BRANCH}"\n }\n }\n }\n}\n在 Pipeline 中,可以通过 params 对象访问传入的参数值。这些参数值可以用于控制构建流程中的各种逻辑,如条件判断、分支选择等。\n参数化 Pipeline 的主要优势在于其灵活性,能够适应不同环境需求或用户输入。这种方式特别适合多分支开发或针对不同部署环境的需求,使构建流程更加智能和可控。\n条件语句\n条件语句用于根据不同的输入参数或环境变量决定构建的执行路径。通过 when 指令,可以在 Declarative Pipeline 中实现条件执行,从而根据特定条件执行相应的构建步骤。\npipeline {\n stages {\n stage('Deploy') {\n when {\n branch 'master'\n }\n steps {\n echo 'Deploying to production...'\n }\n }\n }\n}\n循环结构\n循环结构在处理重复性任务时非常有用例如遍历文件列表或批量执行测试。在 Jenkins Pipeline 中,可以通过 for 循环实现这一功能,从而简化处理多个相似任务的代码复杂度。\npipeline {\n stages {\n stage('Batch Test') {\n steps {\n script {\n for (int i = 0; i < 5; i++) {\n echo "Running test ${i}"\n }\n }\n }\n }\n }\n}\n并行执行\n并行执行是 Jenkins Pipeline 的一大优势,允许多个步骤或阶段同时运行,从而加快构建过程。这一功能特别适用于并行测试和多平台构建,能够显著缩短总的构建时间。\npipeline {\n stages {\n stage('Parallel Test') {\n parallel {\n stage('Unit Tests') {\n steps {\n echo 'Running unit tests...'\n }\n }\n stage('Integration Tests') {\n steps {\n echo 'Running integration tests...'\n }\n }\n }\n }\n }\n}\n通过并行执行构建流程可以充分利用 Jenkins 的多核处理能力,提高整体效率,尤其是在大规模项目中,这种方式能够极大地提升构建速度并优化资源利用率。\nGroovy 语法\nJenkinsfile 采用 Groovy 作为脚本语言,其丰富的语法特性使 Jenkins Pipeline 具备高度的灵活性和表达能力。深入掌握 Groovy 语法在 Jenkinsfile 中的应用,是编写高效且复杂的 Pipeline 的基础。以下是 Groovy 语法在 Jenkinsfile 中的关键应用场景:\n变量和常量的定义\n在 Jenkinsfile 中,可以使用变量和常量来存储数据和配置项。变量使用 def 关键字定义,而常量则通过 final 关键字来定义,使其在代码执行过程中不可更改。\ndef myVar = 'value'\nfinal String CONSTANT = 'constantValue'\n条件语句的使用\n条件语句是控制流程的核心。通过 if-else 语句,可以根据不同的条件在 Pipeline 中执行不同的构建步骤。例如,可以根据分支名称来决定是否执行生产环境的部署。\nif (env.BRANCH_NAME == 'master') {\n // 执行生产环境的部署\n} else {\n // 执行测试环境的部署\n}\n循环结构的实现\nGroovy 支持多种循环结构,如 for、while 和 each在 Jenkinsfile 中可以用于自动化重复任务。循环的使用能够大大简化处理多个相似任务的代码复杂度。\nfor (int i = 0; i < 5; i++) {\n echo "Iteration ${i}"\n}\n函数和闭包的封装\n函数和闭包是 Groovy 的强大特性之一。它们允许将重复或复杂的逻辑封装成模块化的代码段,从而提升代码的复用性和可维护性。在 Jenkinsfile 中,这种封装对于结构化和清晰的 Pipeline 编写尤为重要。\ndef greet(name) {\n echo "Hello, ${name}!"\n}\ngreet('Jenkins')\n异常处理机制\n为了保证 Pipeline 的健壮性Groovy 提供了 try-catch-finally 结构来捕获和处理运行时可能发生的异常。通过异常处理机制可以确保即使在错误发生时Pipeline 也能进行适当的处理和资源清理,避免出现不可预料的问题。\ntry {\n // 可能抛出异常的代码\n} catch (Exception e) {\n echo "Caught exception: ${e.message}"\n} finally {\n echo "Cleanup actions"\n}\n使用 Credentials Plugin 进行安全管理\n**Credentials Plugin 是 Jenkins 用于安全存储和管理敏感信息如密码、密钥、Token 等)的关键插件。**它确保在 Pipeline 中使用的凭证不会以明文形式暴露,保护敏感数据的安全性。\n存储方式\n\nGlobal credentials可在 Jenkins 的全局范围内使用的凭证。\nDomain-specific credentials与特定域如 Git 仓库、Docker 注册表)关联的凭证,只能在特定域中使用。\n\n使用方式\n在 Jenkins 管理界面中管理员可以添加多种类型的凭证如用户名密码、SSH 密钥、Secret Text 等)。在 Pipeline 中,可以通过 withCredentials 指令调用并使用这些凭证。\npipeline {\n stages {\n stage('Checkout') {\n steps {\n withCredentials([usernamePassword(credentialsId: 'my-git-credentials', usernameVariable: 'USER', passwordVariable: 'PASS')]) {\n sh 'git clone https://${USER}:${PASS}@github.com/my-repo.git'\n }\n }\n }\n }\n}\n为了确保凭证的安全性在 Pipeline 中使用凭证时应避免以下情况:\n\n避免直接输出凭证确保凭证不会出现在日志或控制台输出中。\n使用安全的上下文通过 withCredentials 封闭使用凭证的代码段,避免凭证泄露。\n\npipeline {\n stages {\n stage('Deploy') {\n steps {\n withCredentials([string(credentialsId: 'SECRET_KEY', variable: 'SECRET')]) {\n sh 'deploy --key $SECRET'\n }\n }\n }\n }\n}\nJenkins 支持与多种第三方工具集成,通过 Credentials Plugin 进行凭证管理,如:\n\nGitHub使用 Personal Access Token 进行安全拉取和提交代码。\nDocker使用 Docker 凭证登录 Docker Registry执行镜像推送和拉取。\nAWS集成 AWS IAM 凭证,进行云端资源管理和部署。\n\n通过与第三方工具的凭证集成Jenkins 可以安全地执行各种自动化任务,避免敏感信息泄露。\n注意事项\n在与第三方工具集成时Jenkins 使用 Credentials Plugin 进行凭证管理,如 GitHub、Docker、AWS 等工具。这一功能极大地提升了自动化任务的安全性和效率,但在使用凭证管理时需注意以下安全事项:\n\n最小权限原则为 Jenkins 配置凭证时,应仅授予执行任务所需的最低权限,以减少敏感资源的暴露风险。\n定期更新凭证定期轮换 API Key、SSH 密钥等凭证,以降低凭证泄露的风险,并确保安全性。\n加密存储确保 Jenkins 运行在受信任的环境中,并将凭证存储在加密的文件系统上,以防止未经授权的访问。\n启用审计日志开启 Jenkins 的安全审计日志功能,记录凭证的使用情况,有助于及时检测和应对异常行为。\n\n这些措施有助于保护敏感信息确保与第三方工具的集成安全可靠。\n基本的 CI 流程\n使用 Pipeline 实现持续集成流程\n持续集成CI是现代软件开发中不可或缺的实践旨在通过频繁的代码集成和自动化测试快速发现和修复问题。Jenkins Pipeline 是实现持续集成的理想工具。\n典型的 CI 流程包括以下步骤:\ngraph TD\n A[代码提交] -->|开发者提交到版本控制系统| B[自动触发]\n B -->|通过 Webhook 或 SCM 轮询| C[拉取代码]\n C -->|从版本控制系统拉取最新代码| D[编译和测试]\n D -->|执行编译和单元测试| E[生成构建报告]\n E -->|生成测试报告和代码覆盖率报告,并发布构建结果| F[构建完成]\n\n\n代码提交开发者将代码提交到版本控制系统如 Git。\n自动触发通过 Webhook 或 SCM 轮询Jenkins 自动触发构建。\n拉取代码Jenkins 从版本控制系统中拉取最新代码。\n编译和测试Jenkins 执行编译和单元测试,确保代码质量。\n生成构建报告Jenkins 生成测试报告和代码覆盖率报告,并发布构建结果。\n\n通过持续集成流程开发团队可以快速响应代码变更确保代码库的稳定性。\n集成单元测试\n单元测试是 CI 流程中的重要组成部分Jenkins 提供了与多种测试框架的无缝集成。集成单元测试后Jenkins 会在构建页面展示测试结果,包括测试通过率、失败的测试用例等信息,帮助开发者快速定位问题。\nJUnit\nJenkins 支持 JUnit 测试框架,用户可以通过 junit 指令自动解析和展示测试结果。在 Pipeline 中,可以这样集成 JUnit 测试:\nstage('Test') {\n steps {\n sh 'mvn test'\n junit '**/target/surefire-reports/*.xml'\n }\n}\nTesting\nTesting 是另一种流行的 Java 测试框架,与 JUnit 类似,用户可以通过 publishTestNGResult 插件解析 Testing 生成的 XML 测试报告。\n构建失败后的错误处理与通知配置\n在 CI 流程中构建失败是不可避免的。Jenkins 提供了多种机制帮助开发者及时处理构建失败。\n错误处理\n在 Pipeline 中,用户可以使用 try-catch 块捕获构建中的异常,并执行相应的处理逻辑。例如,可以在构建失败后自动回滚到上一个稳定版本,或触发其他修复任务。\ntry {\n stage('Deploy') {\n sh 'make deploy'\n }\n} catch (Exception e) {\n currentBuild.result = 'FAILURE'\n // 处理失败逻辑\n echo "Deployment failed: ${e.message}"\n}\n通知配置\nJenkins 支持通过多种方式通知构建结果如电子邮件、Slack、Webhooks 等。在 Pipeline 中,可以通过 mail 指令发送通知:\npost {\n failure {\n mail to: 'team@example.com',\n subject: "Build failed: ${env.JOB_NAME}",\n body: "Build ${env.BUILD_NUMBER} failed. Please check the Jenkins logs."\n }\n}\n生成和发布构建报告\n构建报告是 Jenkins CI 流程的重要输出,帮助团队了解构建状态、测试结果和代码质量。\n\n\n测试报告Jenkins 可以自动生成和展示测试报告,如 JUnit、Testing 生成的测试结果。在 Pipeline 中,用户可以通过 junit、publishTestNGResult 等插件自动解析测试报告,并在构建页面展示详细的测试结果。\n\n\n代码覆盖率报告通过集成代码覆盖率工具如 JaCoCo、CoberturaJenkins 可以生成代码覆盖率报告,帮助团队了解测试覆盖情况。代码覆盖率报告可以与测试报告一起展示,提供全面的代码质量分析。\n\n\n构建工件存档在构建完成后Jenkins 可以自动存档构建生成的工件(如 JAR、WAR 文件),供后续发布或部署使用。通过 archiveArtifacts 指令,用户可以指定需要存档的文件或目录:\nstage('Package') {\n steps {\n sh 'mvn package'\n archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true\n }\n}\n\n\n生成和发布构建报告确保了构建过程的透明性和可追溯性帮助团队持续改进代码质量和构建流程。\n多分支管道和并行作业\n多分支 Pipeline 是 Jenkins 支持多分支开发模式的重要功能,能够自动检测并为每个代码分支创建单独的 Pipeline Job。\ngraph TD\n A[创建 Multibranch Pipeline] --> B[配置源码管理]\n B --> C[分支策略]\n C --> D[Jenkinsfile 位置]\n\n\n创建 Multibranch Pipeline在 Jenkins 中创建一个新的 Multibranch Pipeline 项目。\n配置源码管理指定 Git 或其他版本控制系统的仓库地址Jenkins 会自动扫描该仓库的所有分支。\n分支策略配置分支发现策略如只构建特定分支或忽略某些分支。\nJenkinsfile 位置:确保每个分支的根目录下有一个 JenkinsfileJenkins 将根据该文件定义 Pipeline。\n\n多分支 Pipeline 的优势在于它自动适应 Git Flow 等多分支开发策略,每个分支可以独立运行自己的 CI/CD 流水线,极大提高了开发效率。\nJenkins 对 Git 分支的支持与自动化构建\nJenkins 对 Git 的支持通过 Git 插件实现能够自动化处理代码的拉取、构建和测试。对于多分支项目Jenkins 可以在以下场景下自动触发构建:\n\n新分支创建当新分支推送到远程仓库时Jenkins 自动检测并触发构建。\n分支变更当现有分支发生变更如代码提交、MergeJenkins 自动拉取最新代码并重新构建。\n\n通过 Webhook 与 Jenkins 集成Git 仓库可以在代码变更时实时通知 Jenkins进一步优化构建响应时间。\n并行作业的配置与优化\n并行作业是在 Jenkins 中提升构建效率的关键技术,适合在 CI 流水线中并行执行不同的任务,如测试、代码分析、部署等。\n\n并行阶段在 Pipeline 中使用 parallel 指令定义并行阶段。\n资源管理合理配置并行作业的资源分配避免超载导致的系统性能下降。\n\npipeline {\n stages {\n stage('Test') {\n parallel {\n stage('Unit Tests') {\n steps {\n sh 'run-unit-tests.sh'\n }\n }\n stage('Integration Tests') {\n steps {\n sh 'run-integration-tests.sh'\n }\n }\n }\n }\n }\n}\n并行作业配置完成后Jenkins 会自动分配可用的 Agent 节点执行任务,极大缩短构建时间。\n实现高效的并行测试和部署\n通过并行执行Jenkins 可以同时运行多组测试或部署任务,最大化资源利用率。具体优化策略包括:\n\n细粒度分割测试将测试任务细分为多个小单元分别在不同的 Agent 上并行执行。\n自动化环境准备通过并行配置自动化准备不同测试环境减少环境切换时间。\n并行部署到多环境对于微服务架构的应用Jenkins 可以并行部署到多个环境,如开发、测试和生产环境。\n\n这些优化策略有助于显著提升 Jenkins Pipeline 的执行效率和系统性能。\n集成第三方服务\nGitHub\nJenkins 可以通过 Webhook 与 GitHub 集成,实现自动化的 CI/CD 流程。常见的集成方式包括:\n\nWebhookGitHub 中配置 Webhook当代码仓库发生事件如代码提交、Pull Request 创建)时,通知 Jenkins 自动触发相应的构建。\nPull Request 触发:使用 GitHub Pull Request Builder 插件,当有新的 Pull Request 创建或更新时Jenkins 自动拉取分支代码并触发 CI 流水线。\n\n通过这种集成Jenkins 能够在代码变更时快速响应,并在 Pull Request 合并前执行必要的测试和代码质量检查。\nDocker\nJenkins 可以与 Docker 深度集成,充分利用容器化技术提高 CI/CD 流程的灵活性和可移植性。\n构建 Docker 镜像\n通过 Docker Pipeline 插件Jenkins 可以在流水线中自动构建、标记和推送 Docker 镜像。\npipeline {\n agent {\n docker { image 'maven:3.6.3' }\n }\n stages {\n stage('Build') {\n steps {\n sh 'mvn clean package'\n }\n }\n stage('Build Docker Image') {\n steps {\n script {\n docker.build('myapp:latest').push('myrepo/myapp:latest')\n }\n }\n }\n }\n}\n使用 Docker 容器执行构建\nJenkins 可以通过 Docker Agent 在容器中执行构建任务,确保构建环境的一致性,并隔离不同构建任务的依赖。\npipeline {\n agent {\n docker { image 'node:14-alpine' }\n }\n stages {\n stage('Test') {\n steps {\n sh 'npm install'\n sh 'npm test'\n }\n }\n }\n}\n这种方法可以确保每次构建都在全新的、可控的环境中运行减少因环境差异导致的构建失败。\nKubernetes\nJenkins 与 Kubernetes 的集成使得 CI/CD 流水线可以轻松部署到云原生环境中特别是在微服务架构下Kubernetes 的动态调度和扩展能力与 Jenkins 的自动化能力结合,显著提升了软件交付效率。\nJenkins X\nJenkins X 是一个专为 Kubernetes 设计的 CI/CD 解决方案,简化了 Kubernetes 环境下的应用部署和管理。它基于 Jenkins但提供了更高层次的抽象和开箱即用的 DevOps 工具链。\n自动化部署到 Kubernetes\n通过 Kubernetes 插件Jenkins 可以直接与 Kubernetes API 交互,实现应用的自动化部署和管理。\npipeline {\n agent any\n stages {\n stage('Deploy to Kubernetes') {\n steps {\n script {\n kubernetesDeploy configs: 'k8s-deployment.yml', kubeconfigId: 'kube-config'\n }\n }\n }\n }\n}\n\nHelmJenkins 还可以集成 Helm通过 Helm Chart 管理 Kubernetes 应用的发布流程,进一步简化复杂应用的部署。\n\n其他服务集成\nJenkins 支持集成各种第三方服务,通过插件扩展其功能,如 Slack、JIRA 等。\nSlack 通知\n通过 Slack 插件Jenkins 可以在构建状态发生变化时自动发送通知到指定的 Slack 频道,及时通知开发团队。\npipeline {\n post {\n success {\n slackSend(channel: '#builds', message: "Build #${env.BUILD_NUMBER} succeeded")\n }\n failure {\n slackSend(channel: '#builds', message: "Build #${env.BUILD_NUMBER} failed")\n }\n }\n}\nJIRA 工单自动化\nJenkins 可以通过 JIRA 插件与 JIRA 项目管理工具集成,实现工单的自动创建、更新或关闭,配合 DevOps 流程。\npipeline {\n steps {\n jiraNewIssue site: 'JIRA_SITE', issue: [projectKey: 'PROJ', summary: 'Build failed', description: 'Build #${env.BUILD_NUMBER} failed']\n }\n}\n持续交付CD流程\n持续交付与持续部署的区别\n**持续交付Continuous Delivery, CD和持续部署Continuous Deployment**是现代 DevOps 实践中常见的自动化软件发布策略,虽然二者名称相似,但在实际实施中存在关键区别:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n持续交付Continuous Delivery, CD持续部署Continuous Deployment定义软件开发实践确保代码在通过所有自动化测试后随时可以部署到生产环境。持续交付的进一步扩展自动化流程不仅确保代码可以随时部署还会在测试通过后立即部署到生产环境。部署触发方式通常由人工操作触发需通过手动审批或按需执行部署。完全自动化无需人工干预测试通过后立即部署到生产环境。自动化程度自动化测试覆盖但部署步骤通常需要人工触发。全面自动化包括自动化测试和部署到生产环境。人工干预需要人工干预进行最终的部署决策。无需人工干预代码一旦通过测试就会直接部署。适用场景适用于业务敏感度较高的项目部署时间点需根据业务需求决定。适用于频繁发布、变化快的产品如 SaaS 应用。风险管理部署前有人工审核步骤较容易控制风险。需要非常严格的自动化测试和监控机制因每次提交都会直接影响生产环境。典型使用者传统企业软件、金融系统等对生产环境变更非常敏感的项目。快速迭代的互联网产品、SaaS 平台等。发布频率根据业务需求决定,可在经过人工审批后择机发布。发布频率高,通常在每次代码提交后,立即发布到生产环境。稳定性要求高度关注生产环境的稳定性,部署前可能进行额外的手动验证。依赖自动化测试和监控,生产环境的稳定性直接依赖于自动化机制的可靠性。\n在实践中持续交付适用于业务敏感度较高的项目而持续部署则适用于频繁发布、变化快的产品如 SaaS 应用。\n实现自动化部署的最佳实践\n自动化部署是持续交付的核心环节确保代码能快速、安全地发布到生产环境。以下是实现自动化部署的最佳实践\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n最佳实践描述工具或技术基础设施即代码IaC将基础设施配置代码化确保部署环境的一致性和可重复性。Terraform、Ansible、CloudFormation环境标准化使用容器化和虚拟化技术确保开发、测试、生产环境一致减少因环境差异导致的部署失败。Docker、Kubernetes、Vagrant无停机部署设计无停机的部署流程避免服务中断保持旧版本在新版本部署期间可用。蓝绿部署、金丝雀发布、滚动更新自动化回滚部署过程中设计回滚机制快速恢复到上一个稳定版本确保业务连续性。Jenkins、Spinnaker、ArgoCD安全集成在部署管道中集成安全扫描确保在每次部署前检测并修复安全漏洞和配置问题。Snyk、OWASP ZAP、Aqua Security监控与日志部署完成后自动更新监控和日志配置实时监控和分析新版本的健康状况。Prometheus、Grafana、ELK StackElasticsearch, Logstash, Kibana\n蓝绿部署、金丝雀发布等策略的实现\n蓝绿部署和金丝雀发布是两种常用的无停机部署策略适用于在不断变化的生产环境中安全地发布新版本。\n\n蓝绿部署蓝绿部署通过维护两套几乎相同的生产环境来实现无停机发布。当前版本在 蓝色 环境中运行,新版本在 绿色 环境中部署并验证,一旦验证通过,将流量切换到 绿色 环境。这样,即使新版本出现问题,也能快速切回“蓝色”环境。\n\n实现方式可以使用 DNS 切换、负载均衡器调整等手段实现流量的切换。\n\n\n金丝雀发布金丝雀发布是逐步将新版本部署给部分用户通常是生产环境的一小部分流量然后逐步增加新版本的用户比例。通过这种方式可以在生产环境中观察新版本的表现发现问题可以及时调整或回滚。\n\n实现方式可以使用负载均衡器或特定的路由策略如 Istio逐步引入新版本流量。\n\n\n\n通过 Jenkins 的 Pipeline 和 Kubernetes 的滚动更新策略,可以自动化实现上述部署策略。\n部署管道的监控与回滚机制\n部署管道不仅要确保软件顺利发布还要能够监控发布后的状态并在必要时快速回滚。有效的监控与回滚机制包括\n\n实时监控部署管道应集成应用性能监控工具如 Prometheus、Grafana和日志管理工具如 ELK Stack实时监控新版本的关键指标如响应时间、错误率、资源消耗等。\n健康检查在部署结束后自动触发健康检查脚本验证应用的核心功能和服务状态。如果检测到异常自动触发警报或启动回滚流程。\n自动化回滚在 Pipeline 中设计自动化回滚逻辑,一旦监控检测到严重问题,系统可以自动回滚到上一个稳定版本。例如,利用 Kubernetes 的回滚机制或通过 Jenkins 的 rollback 步骤触发回滚操作。\n部署日志与审计保持详细的部署日志和审计记录确保所有部署操作都可追踪。这样在出现问题时可以快速定位根本原因并采取修复措施。\n\n使用共享库提高管道重用性\n共享库Shared Library 是 Jenkins 中的一种机制,允许用户将常用的 Pipeline 代码封装在一个集中管理的库中,供多个 Jenkins Pipeline 复用。共享库通过将通用的构建、测试、部署逻辑抽象出来,使得各项目的 Pipeline 定义更加简洁,并易于维护和更新。\n\n代码复用将常用的 Pipeline 步骤、工具集成、通知机制等抽象为共享库函数,减少重复代码。\n标准化通过共享库定义企业级的标准化流水线组件确保所有项目遵循统一的流程和最佳实践。\n快速迭代当某个流程需要更新时只需更新共享库即可同时影响所有使用该库的 Pipeline减少了个别项目逐一修改的工作量。\n\n创建共享库\n创建共享库需要按照 Jenkins 的特定目录结构和代码规范进行,通常使用 Git 存储和版本控制。目录结构:共享库的代码需要存放在指定目录中,并按约定组织结构:\n\nvars/ 目录:存放全局可用的脚本(如 myStep.groovy可以直接在 Pipeline 中调用。\nsrc/ 目录:存放支持 Groovy 类的源码,便于复杂逻辑的封装。\nresources/ 目录:存放配置文件、模版等静态资源。\nJenkinsfile用于本地测试的 Jenkinsfile。\n\n// vars/myStep.groovy\ndef call(String name) {\n echo "Hello, ${name}!"\n}\n管理共享库\n\n版本控制共享库应存放在 Git 仓库中,便于版本管理和变更追踪。库的不同版本可以通过标签或分支管理。\n加载共享库在 Jenkinsfile 中,通过 @Library 注解加载共享库,并指定版本或分支。\n\n@Library('my-shared-library@main') _\npipeline {\n stages {\n stage('Greet') {\n steps {\n myStep('Jenkins')\n }\n }\n }\n}\n在 Pipeline 中使用共享库\n在 Jenkins Pipeline 中使用共享库的方式包括全局加载和按需加载:\n\n全局加载通过 Jenkins 管理界面配置共享库为全局库,所有 Pipeline 自动加载该库,无需在 Jenkinsfile 中显式声明。\n按需加载在 Pipeline 中通过 @Library 注解指定要加载的库,适用于不同项目使用不同版本或库的场景。\n\n@Library('my-shared-library@version-1.0') _\npipeline {\n stages {\n stage('Build') {\n steps {\n buildApp() // 调用共享库中的函数\n }\n }\n }\n}\n通过共享库团队可以将通用的流程和逻辑集中管理并在各个 Pipeline 中简化实现,提高代码的可维护性和一致性。\n版本控制与更新策略\n共享库的版本控制和更新策略对于确保稳定性和灵活性至关重要。\n为共享库设置版本标签或使用分支管理不同的版本确保不同项目可以基于稳定的版本进行开发和构建。主流策略包括使用 Git 标签管理稳定版本,使用分支(如 master、develop进行开发和测试。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n策略描述渐进式更新在更新共享库时避免直接修改主版本先在开发分支或新版本标签上进行迭代和测试。确认稳定后再将变更合并到主版本或在稳定分支中发布新版本减少构建失败风险。回滚机制确保更新共享库后所有依赖的 Pipeline 都能平稳过渡。如果新版本出现问题,可以快速回滚到旧版本,通过在 Pipeline 中指定旧版本或分支的方式实现回滚。文档与变更日志每次更新共享库时,附带详细的文档说明和变更日志,告知使用者新增功能、变更及可能的影响。良好的文档有助于团队更好地适应和采用新的库版本。向后兼容性更新共享库时,尽量保持向后兼容性。避免引入破坏性变更,或在引入破坏性变更时,提供过渡期和旧版支持,确保所有项目有足够的时间进行调整。\n部署到 Kubernetes 和其他云平台\nJenkins 可以与 Kubernetes 实现深度集成尤其是在自动化部署和容器化管理方面。Jenkins 的 Kubernetes 插件可以动态地在 Kubernetes 集群中启动 Jenkins Agent以执行构建任务。\n\nJenkins Agent 动态配置Jenkins 可以利用 Kubernetes 插件在需要时自动启动容器化的 Jenkins Agent并在任务完成后销毁这些容器。这种按需启动和销毁 Agent 的机制,提升了资源利用效率,特别适合处理高并发的构建任务。\nJenkins XJenkins X 是 Jenkins 的云原生扩展,专为 Kubernetes 环境设计。它简化了在 Kubernetes 上的 CI/CD 配置,自动管理应用的部署和环境,并提供开箱即用的 GitOps 流水线管理。\n集群管理和资源调度通过 Jenkins 与 Kubernetes 的集成Jenkins 可以直接与 Kubernetes API 交互,进行容器编排、服务部署、扩展和滚动更新,实现高效的自动化运维。\n\n使用 Helm 部署应用到 Kubernetes\nHelm 是 Kubernetes 的包管理工具,用于简化应用在 Kubernetes 上的部署和管理。通过 Helm用户可以定义、安装和升级 Kubernetes 应用。\n\n\n创建 Helm Chart一个 Helm Chart 是一个包含 Kubernetes 资源定义的模板包,描述了一个完整的应用及其依赖。开发者可以创建自定义的 Helm Chart 来管理应用的生命周期。\n\n\nHelm 与 Jenkins 集成:在 Jenkins Pipeline 中,用户可以通过 helm 命令自动化地管理 Helm Chart 的打包、发布和部署。例如,可以在 Pipeline 中执行以下步骤:\npipeline {\n agent any\n stages {\n stage('Helm Package') {\n steps {\n sh 'helm package myapp'\n }\n }\n stage('Helm Deploy') {\n steps {\n sh 'helm upgrade --install myapp ./myapp-chart'\n }\n }\n }\n}\n\n\n自动化发布和升级Helm 支持自动化的版本升级、回滚操作,配合 Jenkins 的 Pipeline可以实现持续交付的完整生命周期管理。\n\n\nJenkins 部署 AWS、Azure、GCP 等云平台\nJenkins 可以通过各种插件和脚本集成来实现对 AWS、Azure、GCP 等主流云平台的自动化部署和管理。\n\n\n使用 AWS CLI 和 SDKJenkins 可以在 Pipeline 中通过 AWS CLI 进行 S3 存储管理、EC2 实例启动、Lambda 函数部署等操作。\n\n\nCloudFormation 和 Terraform通过 Jenkins 自动化运行 CloudFormation 模板或 Terraform 脚本,管理 AWS 上的基础设施。\n\n\nAzure CLI 和 DevOps 集成Jenkins 支持使用 Azure CLI 管理 Azure 资源,还可以通过 Azure DevOps 插件,直接与 Azure DevOps 服务进行集成,自动化管理应用的发布、资源的创建和配置。\n\n\nGoogle Cloud SDKJenkins 可以利用 Google Cloud SDK 在 GCP 上进行容器管理、虚拟机管理以及云函数的部署。\n\n\nTerraform 集成:同样可以通过 Terraform 在 GCP 上定义和管理基础设施,配合 Jenkins 的自动化执行,实现 IaC。\n\n\n利用 Infrastructure as Code 实现自动化基础设施部署\nInfrastructure as CodeIaC 是通过代码定义和管理基础设施的实践。Jenkins 与 IaC 工具(如 Terraform、CloudFormation的集成可以实现从基础设施到应用的全自动化管理。\nTerraform\n使用 Terraform 脚本定义云资源,在 Jenkins Pipeline 中通过 terraform 命令执行资源创建、更新和销毁。\npipeline {\n agent any\n stages {\n stage('Terraform Apply') {\n steps {\n sh 'terraform init'\n sh 'terraform apply -auto-approve'\n }\n }\n }\n}\nTerraform 管理基础设施的状态,并支持自动化的回滚机制,在 Jenkins 中配置 terraform plan 和 terraform apply 步骤,实现安全的基础设施更新。\nCloudFormation\n使用 CloudFormation 模板定义 AWS 资源,并在 Jenkins 中通过 aws cloudformation 命令自动化执行栈的创建和更新。\npipeline {\n agent any\n stages {\n stage('Deploy Stack') {\n steps {\n sh 'aws cloudformation deploy --template-file stack.yml --stack-name my-stack'\n }\n }\n }\n}\n配置 CloudFormation 事件监控,通过 Jenkins Pipeline 自动化响应失败的栈操作,并触发回滚或重新部署。通过 IaC 的实践,开发和运维团队可以通过 Jenkins 实现基础设施的全生命周期管理,确保环境的一致性和自动化的高效性。\n性能优化和故障排查\nJenkins 性能瓶颈识别与优化策略\n随着项目规模的增长Jenkins 的性能优化变得至关重要。常见的性能瓶颈及优化策略包括:\n\nMaster 性能优化Jenkins Master 服务器的性能直接影响到整个系统的响应速度。优化 Master 性能的关键在于提升 CPU 和内存资源配置,使用高性能磁盘以加快 Job 的读取和日志存储。可以通过增加 Master 节点的资源或分离部分非核心任务到专用节点来缓解负载。\nAgent 管理优化:通过合理配置 Agent 的数量和资源,确保并发任务能够高效执行。可以使用 Kubernetes 动态扩展 Agent 的机制,根据需求自动调整 Agent 数量。\n数据库与存储优化Jenkins 的历史记录、构建日志、Artifact 存储等会消耗大量的存储资源。可以使用专用的数据库系统(如 MySQL管理 Jenkins 的元数据,定期清理旧的构建记录,压缩存储空间。\n插件管理尽量减少不必要的插件避免插件冲突或兼容性问题引发的性能问题。定期更新插件版本以利用最新的性能优化和功能改进。\n\n分布式构建Master-Slave 架构的优化\nJenkins 支持 Master-SlaveAgent架构通过分布式构建提升系统的并发能力和资源利用率。\n\n水平扩展通过增加 Slave 节点,可以水平扩展 Jenkins 的构建能力,将大量并发构建任务分散到多个 Slave 节点执行,减少 Master 的负载。\n专用 Slave为特定任务如测试、部署配置专用的 Slave 节点,以提高特定任务的执行效率。可以根据任务的资源需求选择不同类型的 Slave如高内存、GPU 支持的 Slave。\n负载均衡合理分配构建任务避免某些 Slave 节点负载过高。可以使用标签Label机制将不同类型的任务分配到适合的 Slave 上执行。\n网络优化确保 Master 和 Slave 之间的网络连接稳定可靠,使用高速网络和专用通道,减少构建数据传输的延迟。\n\nJenkins 日志分析\n日志是 Jenkins 故障排查的关键工具,通过分析 Jenkins 日志,团队可以快速定位问题并采取相应的解决措施。\n\n主日志Jenkins 的主日志包含了系统启动、插件加载、任务调度等核心信息。通过分析主日志,可以发现系统启动错误、插件兼容性问题、任务调度冲突等问题。\n构建日志每个 Jenkins Job 都有独立的构建日志,记录了从源码拉取、构建、测试到部署的详细过程。通过构建日志可以分析构建失败的原因,排查脚本错误、环境问题或外部依赖的故障。\n插件日志某些插件会生成独立的日志文件分析插件日志可以帮助解决插件相关的错误如身份验证失败、外部服务连接超时等。\n\nJenkins 故障排查\n\n重现问题通过复现问题可以确认问题的触发条件和影响范围。可以使用相同的输入和配置在测试环境中重现问题收集更多调试信息。\n日志级别调整在某些情况下可以通过提高日志级别如将默认的 INFO 级别提升为 DEBUG获取更详细的调试信息帮助分析复杂的问题。\n结合监控系统将 Jenkins 与系统监控工具(如 Prometheus、Grafana结合实时监控 Jenkins 的性能指标、资源消耗、错误率等,提前发现并预警潜在的问题。\n\n构建队列管理\n随着构建任务的增加构建队列的管理和资源优化变得至关重要。有效的队列管理可以避免任务积压提升系统整体效率。\n\n优先级队列通过 Jenkins 的优先级队列插件,可以为不同类型的任务设置优先级,确保高优先级任务优先执行,减少关键任务的等待时间。\n队列限流通过配置最大并发构建数限制资源消耗高的任务同时执行防止资源争用导致的系统性能下降。\n任务分配策略使用 Label 和 Node Affinity 机制,将特定任务分配到最合适的节点执行,提高执行效率并减少不必要的资源占用。\n\n资源优化\n\n缓存机制通过使用缓存如 Docker 镜像缓存、依赖包缓存),减少重复下载和构建时间,提升构建速度。\n构建资源池化将资源如数据库、外部服务池化处理避免频繁启动和销毁资源带来的开销。\n动态扩展使用自动化扩展工具根据实际负载动态调整 Jenkins 的资源配置,确保在高峰期自动扩展,在低负载时自动缩减,节省成本。\n"},"Technology/StructuresAlgorithms/数据结构":{"title":"数据结构","links":[],"tags":["数据结构","技术/数据结构算法"],"content":"概述\n数据结构是相互之间存在一种或多种特定关系的数据元素的集合。\n数据\n数据是描述客观事物的符号是计算机中可以操作的对象是能被计算机识别并输入给计算机处理的符号集合。\n数据项 > 数据元素 >> 数据对象:数据项构成了数据元素,数据元素组合成了数据对象。\n结构\n结构是不同数据元素之间不是独立的而是存在特定的关系。\n逻辑结构\n逻辑结构是指数据对象 中 数据元素之间的相互关系。\n\n集合集合结构中的数据元素除了属于一个集合外它们之间没有其他关系。\n线性线性结构中的数据元素之间是一对一的关系。\n树形树形结构中的数据元素之间存在一种多对多的层次关系。\n图形图形结构的数据元素是多对多的关系。\n\n物理结构\n物理结构是指数据的逻辑结构在计算机中的存储形式。\n顺序存储\n顺序存储结构是把数据元素放在地址连续的存储单元里其数据间的逻辑关系和物理关系是一致的。\n链式存储\n链式存储结构是把数据元素存放在任意的存储单元里这组存储单元可以是连续的也可以是不连续的。\n数据类型\n数据类型是指一组性质相同的值的集合以及定义在此集合上的一些操作的总称。\n定义\n\n相同数据对象集合例如整数 > 整数型,字符 > 字符型)。\n集合相关联的操作整数可以加减字符可以拼接。\n\n分类\n\n原子类型字节型、数值型、字符串型。\n结构类型原子类型的组合。\n\n抽象数据类型\n抽象数据类型Abstract Data TypeADT是指一个数学模型及其定义在该模型上的一组操作。\nADT 抽象数据类型名\nData\n\t数据元素之间逻辑关系的定义\nOperation\n\t操作1\n\t\t初始条件\n\t\t操作结果描述\n\t操作2\n\t\t…………\n\t操作n\n\t\t…………\nendADT"},"Technology/StructuresAlgorithms/算法":{"title":"算法","links":[],"tags":["数据结构","技术/数据结构算法"],"content":"概述\n算法是解决特定问题求解步骤的描述在计算机中表现为指令的有限步骤或序列。\n特性\n良好的算法须拥有如下五个特定输入、输出、有穷性、确定性、可行性。\n输入\n算法应具有零个或多个输入。\n输出\n算法至少有一个或多个输出。\n有穷性\n算法在执行有限的步骤后自动结束而不会出现无限循环并且每一个步骤都在可接受的时间内完成。\n确定性\n算法的每一步骤都具有确定性的含义不会出现二义性。\n可行性\n算法的每一步都必须是可行的也就是说每一步都能够通过执行有限次数完成。\n设计原则\n正确性\n算法的正确性是指算法至少应该具有输入、输出和加工处理无歧义性、能正确反应问题的需求、能够得到问题的正确答案。\n\n没有语法错误。\n合法的输入数据能够产生满足要求的输出结构。\n非法的输入数据能够得出满足规格说明的结构。\n刁难的测试数据都有满足要求的输出结果。\n\n可读性\n便于阅读、理解和交流。\n健壮性\n当输入数据不合法时算法也能做出相关处理而不是产生异常或莫名其妙的结果。\n时间效率和存储量低\n设计算法应该尽量满足时间效率高和存储量低的需求。\n度量方法\n评价算法的优良必须有相对应的准则目前从两方面出考量方法论、复杂度。\n方法论\n\n事后统计法\n事前分析估算法\n函数的渐近增长\n\n复杂度\n\n时间Time复杂度T(n) = O(f(n))\n空间Space复杂度S(n) = O(f(n))\n最坏情况与平均情况\n"},"Technology/WebDevelopment/0.Overview/概述":{"title":"概述","links":[],"tags":["技术/WebDev","WebDev/Overview"],"content":"简介\n前端开发是当今技术领域的重要组成部分它使我们能够以视觉上吸引人的、交互式的方式浏览网站和网络应用程序。\n前端开发的定义\n前端开发有时也被称为客户端开发是创建网络应用程序或网站用户交互界面的实践。它涉及到的技术包括 HTML、CSS 和 JavaScript以及各种现代框架和库如 React、Angular 和 Vue.js。前端开发者的目标是提供一个高度交互的、用户友好的界面它可以在各种设备和浏览器上无缝工作。\n前端与后端的区别\n在理解前端和后端的区别时最直接的比喻可能就是一家餐厅。在这个比喻中前端开发者就像是餐厅的服务员他们直接与顾客用户互动提供菜单接收订单并提供所需的食物数据。而后端开发者就像是厨师他们在幕后处理服务员传来的订单并准备好食物。\n在技术方面前端开发主要关注用户界面和用户体验而后端开发则是处理服务器、应用和数据库之间的交互。后端开发者使用如 Python、Ruby、Java、PHP 等服务器端语言,创建应用的业务逻辑,管理数据库,以及处理用户的请求和响应。\n前端开发的重要性\n前端开发的重要性在于它**直接影响到用户的体验。**一个易于使用、视觉吸引人的界面可以大大增加用户的满意度,提高用户的参与度,甚至影响到公司的品牌形象。此外,前端开发也涉及到网站的可访问性和响应式设计,这可以确保所有用户,无论他们使用的设备类型或者他们的身体能力如何,都可以方便的访问和使用网站。\n在当今的数字化世界中前端开发已经变得至关重要。无论是小型的静态网站还是大型的复杂网络应用都需要前端开发者的专业技能和经验来创建用户友好的界面。在未来随着技术的不断发展和新的用户需求的出现前端开发的重要性只会继续增加。\n历史发展\n前端开发已经经历了长达几十年的发展历程从最初的静态网页到现在的复杂的 Web 交互应用,前端开发的技术和工具都发生了巨大的变化。下面是前端开发的一些主要发展阶段:\n1990 年代:静态网页时代\n在 1990 年Tim Berners-Lee 发明了万维网,也就标志着网页的诞生。在这个阶段,网页主要由纯文本构成,使用 HTMLHyperText Markup Language进行标记。这些网页被称为静态网页因为它们的内容在服务器端生成用户端不能交互和修改。\n1995 年JavaScript 的诞生\n1995 年JavaScript 语言在 Netscape 浏览器上首次亮相,由 Brendan Eich 发明。最初JavaScript 被用作一种客户端的脚本语言,用于实现网页上的简单交互效果,如表单验证等。\n1996 年: CSS 的诞生\n1996 年W3C万维网联盟发布了 CSSCascading Style Sheets的第一版规范标志着样式表的诞生。CSS 的出现使得开发者可以更加方便地控制网页的样式和布局。\n2000 年代初:动态网页和 AJAX\n2000 年代初,随着 JavaScript 和服务端技术的发展网页开始从静态向动态转变。AJAXAsynchronous JavaScript and XML技术的出现使得网页可以在不刷新页面的情况下与服务器进行交互极大地提高了用户体验。\n2006 年jQuery 的出现\n2006 年jQuery 库发布,提供了一种简洁易用的 API 来操作 HTML 文档、处理事件、创建动画以及进行 AJAX 交互。jQuery 的出现极大地简化了前端开发,使得开发者可以用更少的代码完成更多的功能。\n2008 年Chrome 浏览器和 V8 引擎\n2008 年Google 发布了 Chrome 浏览器和 V8 JavaScript 引擎。V8 引擎的出现极大地提升了 JavaScript 的运行速度,使得 JavaScript 能够用于更复杂的应用。\n2010 年代:前端框架和工具的崛起\n2010 年代,前端开发进入了一个新的时代。一方面,出现了大量的前端框架和库,如 Angular、React 和 Vue.js使得开发者可以更容易地构建复杂的前端应用。另一方面前端开发工具和生态系统也得到了极大的发展如 Node.js、webpack、Babel、ESLint 等。\n2015 年至今:现代前端开发\n2015 年ECMAScript 6也称为 ES2015的发布为 JavaScript 带来了许多新的语言特性如类、模块、箭头函数、Promises、生成器等。同时随着 Web Components 和 Progressive Web AppsPWA的出现前端开发正在朝着更加模块化、组件化和原生应用化的方向发展。\n在过去的几十年里前端开发经历了从静态网页到复杂 Web 应用的巨大转变。尽管前端开发的技术和工具不断变化,但其核心目标一直未变,那就是创建出色的用户体验。\n现代化开发工具\n在前端开发过程中开发者需要利用一系列的工具和技术来提高工作效率、确保代码质量和进行项目管理。这些工具和技术构成了前端的开发工具链。以下是一些现代前端开发中常用的工具和技术:\n版本控制\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Git分布式版本控制系统用于项目文件的版本管理。分布式版本控制、支持分支管理、离线工作、社区庞大强大的分支管理、协作便利、开源且免费初学者理解复杂的操作和概念需要时间GitFlowGit 的工作流用于更有条理地管理项目的分支。特定的分支策略主分支、开发分支、功能分支、发布分支等结构化分支模型适用于大中型项目小型项目中可能显得冗余Pull Request用于代码审查和协作开发尤其在 GitHub 和 GitLab 上常见。代码审查、自动测试集成、评论机制易于团队协作、审查代码质量对于较小的团队可能不必要\n包管理器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点npmNode.js 的默认包管理器,用于安装和管理项目依赖。全球最大的 JavaScript 包仓库、广泛支持社区广泛支持、工具链成熟、默认支持 Node.js安装速度较慢、容易出现版本管理问题YarnFacebook 开发的包管理器,提供更快的安装速度。并行下载依赖、离线缓存、语义化版本锁定更快的包安装速度、更好的依赖缓存社区支持不如 npm 广泛pnpm高效的包管理器类似于 npm 和 Yarn使用软链接来提高效率。节省磁盘空间、安装速度快、依赖项去重高效的依赖管理、节省磁盘空间社区相对较小部分包的兼容性尚需验证\n代码编辑器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Visual Studio Code微软开发的开源代码编辑器支持多种语言和插件。语法高亮、代码补全、调试工具、Git 集成、丰富的插件生态免费、跨平台、插件系统强大、社区活跃某些复杂插件可能影响性能WebStormJetBrains 开发的专业 IDE专为前端和 JavaScript 开发者设计。集成调试、代码补全、测试工具、React/Vue/Angular 支持专业级功能、集成度高、支持多种框架付费软件、占用资源较多Sublime Text轻量级代码编辑器支持多种语言和插件。语法高亮、代码折叠、插件支持、极快的启动速度性能极佳、轻量快速、支持多种编程语言许多高级插件需要付费购买社区相对较小\n模块打包器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Webpack强大的 JavaScript 模块打包工具支持项目的依赖管理和打包。代码分割、Tree-shaking、动态导入、CSS 和 JS 处理、多种插件和扩展强大的生态系统、灵活性高、适合大型项目配置复杂、学习曲线较陡Vite轻量级开发服务器和构建工具专为现代前端开发优化。原生 ES 模块支持、开发服务器启动快、热模块替换HMR快速启动、极简配置、现代开发体验功能相对简洁高级功能可能需要配合 Webpack 等使用Parcel零配置的快速打包工具适合小型项目快速启动。零配置、自动依赖解析、支持 JS、CSS、HTML 等多种资源打包快速简单、易于上手、自动化程度高对于大型项目可能显得过于简洁配置不够灵活Rollup专注于打包 ES 模块的打包工具常用于库的打包。Tree-shaking、按需加载、模块化支持打包体积小、适合库开发配置相对复杂功能不如 Webpack 丰富Snowpack新兴打包工具支持即时开发和快速的模块打包。快速开发、基于 ES 模块、按需构建开发速度极快、支持热重载功能相对较少,适合轻量项目,不如 Webpack 灵活\n代码转译器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点BabelJavaScript 编译器,支持将现代 JS 转译为向后兼容的版本。ES6+ 支持、TypeScript 支持、React JSX 转译、插件扩展强大的语法转换功能、跨浏览器兼容性配置复杂,需要合适的 preset 和 pluginTypeScript CompilerTypeScript 官方的编译器,将 TS 代码编译为 JS。类型检查、语法转换、与现代 JS 兼容静态类型检查、提升代码可靠性对于纯 JS 项目引入 TS 可能显得复杂SWC新兴的快速 JavaScript/TypeScript 编译器,用 Rust 实现。高性能转译、支持多种语言JS、TS、React JSX编译速度极快、支持现代语法社区支持和插件生态尚不成熟Sucrase专注于速度的 JavaScript 编译器,支持 TypeScript、JSX 等。极快的编译速度、支持 JSX 和 TypeScript极度优化的性能功能相对有限缺少一些 Babel 的高级功能TraceurGoogle 开发的 ES6 转译器,允许 ES6 代码在旧浏览器中运行。ES6 支持、Polyfill 提供支持旧浏览器、轻量化生态和社区支持不如 Babel 和 SWC 等\n代码检查器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点ESLint开源 JavaScript 代码检查工具用于发现代码中的潜在问题。自定义规则、插件扩展、自动修复、与多种编辑器集成灵活的配置、强大的插件生态系统初次配置可能较复杂尤其在大项目中TSLint专为 TypeScript 开发的静态代码检查工具。专注于 TypeScript 检查、强大的类型检查功能专业针对 TS 项目,集成度高已被官方宣布停止维护,推荐迁移到 ESLint 与 TypeScript 插件Prettier代码格式化工具自动对 JS、CSS、HTML 等进行格式化。自动格式化、支持多种语言、与编辑器和 CI 集成保证代码风格一致性、易于集成无法进行语法错误检查,需与 ESLint 配合使用StylelintCSS 代码检查工具,支持 Sass、Less 等预处理器。自定义规则、自动修复、与编辑器集成提高 CSS 代码质量、可配置性高需与 ESLint 配合单独使用对大型项目管理不够全面SonarQube用于代码质量检测的工具支持多种语言的代码分析。多语言支持、静态代码分析、漏洞扫描代码质量分析全面、集成方便配置复杂适合大型项目和企业应用\n测试框架\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点JestFacebook 开发的 JavaScript 测试框架支持单元测试、集成测试。内置模拟和快照测试、异步测试支持、React 集成配置简单、性能优异、社区广泛对非 React 项目支持稍弱MochaJavaScript 测试框架,提供灵活的测试 API。灵活的测试框架、支持异步测试、与 Chai 和 Sinon 兼容灵活、可扩展、生态系统强大需要集成断言库(如 Chai和测试替身库如 SinonJasmine行为驱动开发BDD的测试框架专注于语义化断言和报告。语义化断言、开箱即用、支持异步测试API 简洁、集成容易功能相对 Mocha 简单,不如 Jest 集成度高KarmaJavaScript 测试运行器,专为浏览器测试而设计。多浏览器测试支持、与 CI 集成良好、与 Mocha、Jasmine 集成便于在多浏览器中进行测试单独使用功能有限通常与其他测试框架配合使用Cypress端到端测试框架允许模拟用户行为和测试整个应用。端到端测试、浏览器集成、模拟用户交互开发体验极佳、测试用例编写简单仅支持 Chrome 和 Electron跨浏览器支持较弱\n前端框架\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点ReactFacebook 开发的前端 UI 框架,采用组件化和声明式编程。组件化、虚拟 DOM、单向数据流、Hooks 支持、JSX 语法生态系统庞大、组件复用性高、灵活性强学习曲线较陡、需配合路由和状态管理库使用Vue.js轻量级前端框架支持渐进式开发适合小型和中型项目。双向绑定、虚拟 DOM、组件化、易于集成第三方库学习曲线平缓、灵活性强、文档详细在大型项目中生态系统不如 React 或 Angular 完善Angular全功能型前端框架支持企业级应用开发谷歌长期维护。双向绑定、依赖注入、模块化开发、强类型支持强大的生态系统、适合大型项目、企业支持强学习曲线陡峭、框架较为重量级Svelte新兴的前端框架编译时生成高度优化的代码。无虚拟 DOM、编译时优化、轻量级、快速渲染代码简洁、性能卓越、无框架运行时开销社区支持和生态系统相对较小适合小型项目Ember.js企业级 JavaScript 框架,支持约定优于配置。路由支持、模板引擎、组件化、双向数据绑定适合大型项目、内置许多最佳实践学习曲线较陡峭,社区不如 React 和 Vue 活跃\nCSS 预处理器\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Sass强大的 CSS 预处理器,允许使用变量、嵌套规则等功能。变量、嵌套、混合、继承、兼容标准 CSS提高可维护性和可读性、广泛支持编译过程复杂开发体验与标准 CSS 有差异LessCSS 预处理器,灵感来自 Sass允许使用变量和函数。变量、嵌套、函数支持、兼容标准 CSS简单易用、与现有 CSS 兼容性强社区活跃度和生态系统不如 Sass 丰富Stylus灵活的 CSS 预处理器,支持多种语法风格。自定义语法风格、灵活配置、支持变量和函数灵活性强、开发体验优秀使用相对复杂,社区支持不如 Sass 或 LessPostCSS用于转换 CSS 的工具,支持多种插件。插件扩展、现代 CSS 特性、与构建工具集成支持最新 CSS 特性、与其他工具兼容性好需根据具体项目配置插件初学者可能感到复杂CSS ModulesCSS 模块化方案,允许 CSS 在局部作用域中生效。局部作用域、自动生成类名、与 JavaScript 集成样式隔离性好、适合组件化开发需要与构建工具集成,使用稍有复杂\n服务器端渲染SSR和静态站点生成SSG\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Next.jsReact 的 SSR 和 SSG 框架支持服务器端渲染和静态站点生成。SSR、SSG、API 路由支持、自动路由、CSS 模块支持提升 SEO 和首屏加载速度、功能强大、社区支持广泛配置相对复杂,学习曲线比传统 React 项目陡峭Nuxt.jsVue.js 的 SSR 和 SSG 框架简化服务器端渲染过程。SSR、SSG、模块化、自动路由、SEO 优化与 Vue.js 无缝集成、提升性能和 SEO、开发体验好大型项目中的性能调优有时较为复杂GatsbyReact 的静态站点生成框架专注于构建快速的静态网站。SSG、GraphQL 数据层、插件丰富、PWA 支持静态网站生成快、开发体验好、生态系统成熟动态内容支持较弱对于大型动态站点不适用Hugo基于 Go 的静态站点生成器专注于构建快速静态网站。SSG、极快的构建速度、模板引擎、支持多语言极快的生成速度、模板灵活、文档优秀配置和模板引擎较复杂学习曲线较陡SapperSvelte 的 SSR 和 SSG 框架支持灵活的渲染模式。SSR、SSG、轻量快速、PWA 支持轻量化、高性能、Svelte 社区支持社区和生态系统较小,开发工具链不如 Next.js 和 Nuxt.js 成熟\n好的接下来我将补充一些其他类别的前端开发工具包括服务器端渲染SSR和静态站点生成SSG、端到端测试E2E、API Mocking 工具、设计工具和 UI 组件库、**持续集成/持续部署CI/CD**等。每个类目仍然会保持 3-5 个工具的介绍,继续以表格形式提供详细信息。\n\n服务器端渲染SSR和静态站点生成SSG\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Next.jsReact 的 SSR 和 SSG 框架支持服务器端渲染和静态站点生成。SSR、SSG、API 路由支持、自动路由、CSS 模块支持提升 SEO 和首屏加载速度、功能强大、社区支持广泛配置相对复杂,学习曲线比传统 React 项目陡峭Nuxt.jsVue.js 的 SSR 和 SSG 框架简化服务器端渲染过程。SSR、SSG、模块化、自动路由、SEO 优化与 Vue.js 无缝集成、提升性能和 SEO、开发体验好大型项目中的性能调优有时较为复杂GatsbyReact 的静态站点生成框架专注于构建快速的静态网站。SSG、GraphQL 数据层、插件丰富、PWA 支持静态网站生成快、开发体验好、生态系统成熟动态内容支持较弱对于大型动态站点不适用Hugo基于 Go 的静态站点生成器专注于构建快速静态网站。SSG、极快的构建速度、模板引擎、支持多语言极快的生成速度、模板灵活、文档优秀配置和模板引擎较复杂学习曲线较陡SapperSvelte 的 SSR 和 SSG 框架支持灵活的渲染模式。SSR、SSG、轻量快速、PWA 支持轻量化、高性能、Svelte 社区支持社区和生态系统较小,开发工具链不如 Next.js 和 Nuxt.js 成熟\n\n端到端测试E2E\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Cypress现代化端到端测试框架允许模拟用户行为并测试整个应用。端到端测试、自动等待、快照功能、内置测试服务器开发体验优秀、测试编写简单、调试方便跨浏览器支持有限仅支持 Chrome 和 ElectronPuppeteerGoogle 开发的用于控制 Chrome 浏览器的自动化库。浏览器自动化、无头浏览器支持、页面截图和生成 PDF、页面抓取强大的浏览器控制能力、支持无头浏览器仅限 Chrome 和 Chromium跨浏览器支持较差Playwright由 Microsoft 开发的跨浏览器自动化测试工具支持多种浏览器。支持多浏览器Chromium、Firefox、WebKit、并行执行测试、多语言 API 支持跨浏览器支持强大、性能好、API 简洁配置相对 Puppeteer 更复杂较新的项目社区资源相对较少TestCafe简单易用的端到端测试框架无需额外安装浏览器插件。无需浏览器插件、内置测试服务器、支持多浏览器易于上手、跨浏览器支持好相比 Cypress 等工具功能不够丰富Selenium历史悠久的自动化测试框架支持多种编程语言和浏览器。多语言支持、跨浏览器支持、与 CI 集成良好跨浏览器支持强、企业级应用多配置复杂、性能较慢,较新项目可能觉得过于重量级\nAPI Mocking 工具\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Mirage JS专注于前端的 API Mocking 库,允许模拟 REST 和 GraphQL API。API Mocking、模拟 REST 和 GraphQL、内置数据库、无需后端依赖开发体验优秀、与前端框架无缝集成如 React、Vue、Ember仅适用于前端后端项目使用较少json-server快速创建一个完整的 REST API用于前端开发和测试。快速生成 REST API、零配置、简单 JSON 文件即为数据库开发快速、无需配置、适合小型项目不适合复杂 API 或动态数据交互功能相对简单Mockoon桌面应用用于生成本地的 API Mock 服务器。本地 Mock 服务器、支持 REST 和 GraphQL、GUI 界面、导出导入 API 模型易于上手、跨平台、直观的 GUI对于复杂场景不够灵活功能不如 Mirage JS 灵活WireMockJava 实现的 API Mocking 工具适用于后端开发者。REST API Mock、支持复杂规则匹配、记录和重放请求强大的规则配置、适合企业级后端项目学习曲线较陡主要面向后端开发Mock Service Worker基于 Service Worker 的 Mock 工具,用于拦截和模拟 HTTP 请求。基于浏览器的 API Mocking、无需额外服务器、支持 REST 和 GraphQL轻量灵活、无需依赖外部服务器仅限于前端项目浏览器兼容性有限\n设计工具和 UI 组件库\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点Figma基于云的 UI 设计和协作工具支持团队实时协作。云端协作、原型设计、插件支持、设计系统管理多人实时协作、跨平台、免费版本功能丰富高级功能需付费Sketch知名的 UI 设计工具,专注于设计系统和原型设计。原型设计、设计系统、插件生态丰富、与开发工具集成良好专注于 UI 设计、插件丰富仅限 macOS 平台跨平台支持较差Adobe XDAdobe 推出的 UI 设计和原型设计工具,支持与 Adobe 生态系统集成。原型设计、设计共享、与 Adobe 生态系统集成与 Photoshop、Illustrator 等无缝集成插件生态不如 Figma 和 Sketch 丰富复杂功能需付费Ant Design蚂蚁金服推出的企业级 UI 组件库专注于数据驱动的企业应用。预定义组件丰富、设计语言统一、国际化支持、React 集成设计优秀、组件丰富、易于使用定制化相对困难适用于数据驱动的企业应用Material-UIGoogle 推出的 Material Design UI 组件库,适用于 React 项目。Material Design 风格、预定义组件丰富、React 集成Google 设计语言支持、组件丰富、文档详细过度依赖 Material Design 风格,定制难度较大\n持续集成/持续部署CI/CD\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点GitHub ActionsGitHub 提供的 CI/CD 工具,深度集成 GitHub 仓库。深度集成 GitHub、支持自动化工作流、支持多平台和多语言与 GitHub 无缝集成、社区支持好、配置灵活仅适用于 GitHub 项目复杂配置可能需要较长学习时间Jenkins开源的 CI/CD 自动化服务器广泛应用于企业级项目。支持多种构建工具和语言、插件丰富、与企业工具集成良好开源免费、支持多平台、多语言界面较为简陋、配置复杂学习曲线较陡CircleCI基于云的 CI/CD 平台专注于快速和高效的持续集成。云端构建、并行任务执行、Docker 支持、丰富的集成功能高效的并行构建、支持多种编程语言免费版限制较多复杂配置需付费版本Travis CI基于云的 CI 服务,支持多种语言的持续集成。与 GitHub 集成良好、支持多语言、简单配置、自动化测试和部署配置简单、免费版可满足大部分需求免费版并行任务有限制企业级用户需付费GitLab CIGitLab 提供的 CI/CD 工具,支持私有仓库的持续集成和部署。内置 CI/CD 支持、与 GitLab 仓库深度集成、Pipeline 可视化私有库免费、CI/CD 集成度高GitLab 生态外的项目集成不如 Jenkins 等工具灵活\n性能优化\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n工具名称工具简介特性优点缺点LighthouseGoogle 开发的网页性能分析工具评估页面的性能和最佳实践。性能评估、SEO 分析、可访问性检测、PWA 支持全面的性能评估、集成 DevTools、免费开源仅用于性能评估不直接提供优化解决方案Webpack Bundle AnalyzerWebpack 插件帮助开发者分析打包文件的大小和依赖关系。可视化依赖分析、Tree-shaking 分析、包体积优化建议帮助优化打包文件、可视化输出仅限 Webpack 项目使用其他打包工具支持较差PageSpeed InsightsGoogle 提供的网页性能评估工具支持移动和桌面页面分析。性能指标分析、SEO 评估、可访问性检测、可视化建议提供详细的优化建议、适合移动端和桌面端对于复杂场景优化建议不够细化WebPageTest开源网页性能测试工具支持全球多个测试位置和多种浏览器。支持多浏览器、多位置测试、详细的网络性能分析网络性能测试全面、报告详细相对 PageSpeed Insights 配置较为复杂Perfume.js前端性能监控库帮助开发者跟踪用户体验指标如 FCP、TTI。性能指标监控、轻量、支持多种 UX 性能指标FCP、TTI 等)开发者友好、易于集成、帮助优化页面加载时间需要手动集成到项目中,对于非技术用户使用难度较高\n未来发展趋势\n在未来前端开发预计将继续迅速发展和变化。以下是一些可能的发展趋势\n更丰富的交互体验\n随着技术的进步我们可以预期更加丰富和复杂的用户界面和交互体验。例如虚拟现实VR和增强现实AR技术可能会更加普及为前端开发带来全新的挑战和机遇。另外随着机器学习和人工智能的发展我们可能会看到更多的自适应和个性化的用户界面。\n新的和改进的工具\n前端开发工具在不断发展和改进。新的编程语言、库和框架正在不断出现以解决前端开发者面临的新的挑战。例如WebAssembly 可能会改变我们构建和运行前端应用的方式,而像 React Native 这样的框架可能会继续改变我们开发跨平台应用的方式。\n性能优化\n随着用户对于网页响应速度和流畅度的期望越来越高性能优化将继续是前端开发的重要主题。包括如何有效地使用缓存、如何优化代码以减少加载时间、如何更好地使用网络资源等方面。\nWeb 安全性\n随着网络攻击和数据泄露事件的增多Web 安全性将成为前端开发的重要考虑因素。前端开发者需要了解如何保护用户数据如何防止跨站脚本XSS攻击跨站请求伪造CSRF等。\n可访问性和包容性\n在未来可访问性和包容性可能会成为前端开发的更重要的考虑因素。这意味着创建的网站和应用需要对所有人开放无论他们的能力如何。这包括对于屏幕阅读器友好的设计对于不同的输入方法例如语音输入的支持以及对于不同文化和语言的考虑。"},"Technology/WebDevelopment/1.Browser/1.浏览器概述":{"title":"浏览器概述","links":[],"tags":["技术/WebDev","WebDev/Browser"],"content":"浏览器的基本概念\n\n**浏览器是现代互联网中不可或缺的核心工具,主要用于在人与网络世界之间建立交互桥梁。**它的核心功能是解析和渲染网页内容,将服务器端传送的代码(如 HTML、CSS、JavaScript 等)转化为用户能够直观理解和操作的图形界面。借助浏览器,用户可以轻松访问各类网站、查找信息、观看多媒体内容、进行在线购物以及处理电子邮件等。此外,现代浏览器还具备扩展功能,支持插件与增强安全特性,以提供更加个性化和安全的网络体验。\n随着互联网技术的不断发展浏览器不仅仅是简单的网页查看工具它还逐渐演变为集成各种网络服务的平台支持云计算、在线协作、实时通信等丰富的功能。因此浏览器已经成为人们日常工作、学习和娱乐不可或缺的工具之一。\n浏览器的核心功能\n浏览器的核心功能可以归结为三个主要方面页面渲染、用户交互与网络通信。 这些功能是用户与互联网内容交互的基础。\n1. 解析和渲染\n浏览器的首要职责是将开发者编写的 HTML、CSS 和 JavaScript 代码转换为可视化的网页内容。这一过程被称为渲染。具体而言,浏览器通过渲染引擎解析 HTML 生成 DOM 树、解析 CSS 生成 CSSOM 树,并将二者结合生成渲染树,最终通过布局计算和绘制,将结构化数据转化为图形并显示在用户屏幕上。\n渲染的流程大致可归纳为以下几个步骤\n\n解析将 HTML 和 CSS 转化为 DOM 树和 CSSOM 树。\n生成渲染树结合 DOM 和 CSSOM创建用于页面布局和显示的渲染树。\n布局Reflow根据视口大小和 CSS 样式规则计算每个元素的几何位置和大小。\n绘制Paint将渲染树中的每个节点绘制到屏幕上。\n\n这一系列步骤是浏览器性能优化的关键领域开发者通常通过减少**重排Reflow和重绘Repaint**操作,提升页面的渲染效率。\n2. 用户交互\n浏览器不仅负责页面渲染还必须处理来自用户的输入与操作。用户交互通过事件机制实现常见的交互方式包括\n\n鼠标事件如点击、双击、鼠标悬停等。\n键盘事件如按键输入、组合键操作。\n触摸事件如触摸屏上的滑动、缩放操作。\n\n浏览器通过事件监听器捕捉这些用户操作并根据定义的响应行为更新页面内容或执行特定的功能。这一机制是现代 Web 应用动态交互的基础。\n3. 网络请求与数据传输\n浏览器还需要与远程服务器进行通信以获取和发送数据。这一过程主要通过 HTTP 或 HTTPS 协议完成。浏览器发送请求时会附带相关的头部信息headers服务器返回的响应包括页面资源如 HTML、CSS、JavaScript 文件)和其他相关数据(如 JSON 数据、图像资源)。在这个过程中,浏览器负责处理以下任务:\n\nDNS 解析:将域名转换为服务器的 IP 地址。\nTLS/SSL 加密:确保 HTTPS 通信的安全性。\nHTTP 请求/响应处理:发送请求、接收响应并解析数据。\n\n现代浏览器还引入了多种优化手段如 HTTP/2、HTTP 缓存、服务端推送等,以减少页面加载时间并提高数据传输效率。\n现代浏览器的主要组件\n现代浏览器为了支持上述核心功能内部架构由多个组件组成。每个组件负责特定的任务并相互协作提供完整的浏览器功能。\n1. 用户界面UI\n用户界面是用户与浏览器交互的入口通常包括\n\n地址栏输入 URL 以导航至不同的网站。\n导航按钮前进、后退按钮用于页面间的跳转。\n标签页允许用户同时访问多个网站每个网站在不同的标签页中独立显示。\n菜单和书签供用户快捷访问浏览器功能和常用网站。\n\n这些元素都是浏览器的外部表现与用户的交互体验息息相关。\n2. 浏览器引擎\n浏览器引擎位于用户界面和渲染引擎之间负责管理两者之间的通信。它接收来自用户界面的指令如用户输入的 URL并控制渲染引擎加载和显示网页内容。此外浏览器引擎还负责管理其他功能模块如插件和扩展。\n3. 渲染引擎\n渲染引擎是浏览器的核心它决定了页面的渲染速度和精度。其主要任务是解析 HTML、CSS并将它们转化为用户可以看到的视觉内容。不同的浏览器使用不同的渲染引擎\n\nBlink由 Chrome、Edge 使用,是目前最广泛应用的渲染引擎。\nGecko由 Firefox 使用,具有高可扩展性和跨平台支持。\nWebKit由 Safari 使用,曾经是 Chrome 的前身渲染引擎。\n\n每个渲染引擎都有自己独特的实现方式和优化策略但其基本工作原理相似。\n4. 网络模块\n网络模块处理所有与服务器的通信任务确保浏览器可以正确获取远程资源。这些任务包括\n\n发送和接收 HTTP/HTTPS 请求。\n管理网络缓存避免重复加载相同资源。\n处理跨域资源共享CORS和安全策略。\n\n高效的网络模块设计可以显著提高页面加载速度尤其是在资源密集型的网页中。\n5. JavaScript 引擎\nJavaScript 引擎的主要任务是解析、编译并执行网页中的 JavaScript 代码。随着 Web 应用的复杂度不断提高JavaScript 引擎的性能显得尤为重要。主流的 JavaScript 引擎包括:\n\nV8由 Google 开发,使用在 Chrome 和 Edge 中。以其快速的编译速度和高效的垃圾回收机制著称。\nSpiderMonkey由 Mozilla 开发,使用在 Firefox 中。支持最新的 ECMAScript 标准,并具备高级优化功能。\nJavaScriptCore由 Apple 开发,使用在 Safari 中。为 WebKit 项目提供强大的 JavaScript 支持。\n\n这些引擎在执行 JavaScript 时通常采用即时编译Just-in-time Compilation, JIT技术将 JavaScript 代码编译为机器码以提高执行效率。\n6. 数据存储\n浏览器提供了多种数据存储机制以支持持久化和缓存用户数据。这些存储机制主要包括\n\nCookie最早的数据存储机制常用于会话管理、用户偏好存储等。它有较小的存储空间通常为 4KB并且会随请求发送至服务器。\nLocal Storage & Session StorageHTML5 引入的客户端存储方式Local Storage 用于持久存储Session Storage 则仅在浏览器会话期间有效。\nIndexedDB提供复杂的数据库查询能力适用于存储大量结构化数据。通常用于离线 Web 应用。\n\n这些数据存储机制帮助浏览器提升用户体验例如通过缓存数据实现快速加载或在用户离线时继续提供应用功能。\n浏览器的渲染机制\n浏览器的渲染机制是将用户请求的网页资源转化为可视化内容的过程。该过程涉及多个步骤包括解析页面内容、计算布局、绘制图形并最终呈现到屏幕上。了解这些步骤有助于开发者优化网页的性能提高用户体验。\n渲染流程概述\n从用户输入 URL 到页面完全呈现,浏览器会依次执行多个步骤。这些步骤确保浏览器能够从服务器获取网页资源,并将其转换为可供用户交互的可视化内容。以下是这一过程的概述:\n\n1. 客户端建立连接并发起 HTTP 请求\n当用户在浏览器地址栏输入 URL 并按下回车时,浏览器首先需要将域名转换为对应的服务器 IP 地址。这一过程称为DNS 解析,通常通过查询本地缓存或向 DNS 服务器发送请求完成。\n浏览器通过 IP 地址定位服务器并通过TCP协议建立连接。如果使用 HTTPS 协议则同时会通过TLS传输层安全协议加密数据传输以确保数据的安全性。\n连接建立后浏览器会发送HTTP 请求,请求的资源包括 HTML 文档、CSS 样式、JavaScript 文件、图像等。服务器响应浏览器的请求,并返回相应的资源文件。\n\n2. HTML 解析与 DOM 树生成\n浏览器接收到 HTML 文件后,进入解析阶段,将 HTML 标记解析为DOM 树Document Object Model。DOM 树是页面结构的抽象表示,每个 HTML 元素对应 DOM 树中的一个节点。浏览器依照 DOM 树的层次结构,组织页面的结构关系。\n\n3. CSS 解析与 CSSOM 树生成\n与此同时浏览器还会解析从服务器或本地缓存获取的 CSS 样式表生成CSSOM 树CSS Object Model。CSSOM 树是样式的结构化表示,描述了每个 DOM 元素的样式信息,如字体、颜色、尺寸等。\n\n4. JavaScript 执行\n在页面的解析过程中浏览器遇到 JavaScript 脚本时,会暂停 HTML 的解析并将脚本交由JavaScript 引擎执行。JavaScript 代码可能会修改 DOM 树或 CSSOM 树,因而会影响页面的渲染结果。常见的 JavaScript 引擎包括 Chrome 的V8引擎和 Firefox 的SpiderMonkey引擎。\n\n5. 布局绘制\n浏览器生成完 DOM 树和 CSSOM 树后,下一步是布局,即计算每个 DOM 元素的几何位置和大小。布局过程考虑了视口的大小、盒模型box model、浮动和定位规则等。布局信息用于指导元素的绘制顺序与空间占用。\n一旦布局完成浏览器进入绘制阶段。在这一阶段浏览器会根据渲染树中每个元素的几何位置信息将其样式如颜色、边框、阴影、背景图片等绘制到屏幕上。绘制的结果是由图形系统管理的一系列位图或图块tiles。\n\n6. 合成与渲染\n绘制后的内容会被分成多个图层这些图层独立存在并由合成器线程管理。合成器线程将这些图层合成为最终呈现的页面图像。为了提高性能某些元素如动画或变换元素会被放在独立图层中处理避免频繁的重排和重绘操作。这一过程在 GPU 加速下处理,以确保图像渲染流畅、及时。\n渲染树与渲染层\n浏览器通过渲染树来表示可见的页面元素该树由DOM 树和CSSOM 树相结合生成。渲染树仅包含那些对用户可见的元素,并排除了 display: none 等隐藏元素。渲染树是页面渲染的核心数据结构,它直接决定了页面的布局和绘制结果。\nDOM 树与 CSSOM 树的结合\n\nDOM 树表示网页的结构,如标记标签和节点的层级关系。\nCSSOM 树包含每个节点的样式信息。\n\n浏览器将 DOM 树和 CSSOM 树结合,生成一个只包含可见节点的渲染树。每个渲染树的节点包含布局计算和绘制所需的全部信息。\n\n布局与重绘\n渲染树生成后浏览器继续执行布局和绘制操作。页面的任何样式或结构变化都会触发这些操作。\n1. 布局Layout\n在布局阶段浏览器计算页面中每个元素的具体位置和尺寸。布局过程非常复杂涉及元素的盒模型、文档流、浮动、定位等多种因素。任何影响页面结构或尺寸的操作如添加新元素或调整元素大小都会触发布局操作。\n2. 重绘Repaint\n当元素的外观属性如颜色、阴影或背景图片发生变化而不会影响其位置或大小时浏览器会触发重绘操作。重绘仅更新元素的视觉外观不涉及重新计算其布局。虽然重绘比布局轻量但频繁的重绘也会影响页面性能。\n3. 重排Reflow\n当页面的结构、尺寸或位置发生变化时浏览器需要重新计算布局触发重排Reflow。重排是极为耗费性能的操作因为它需要重新计算多个元素的布局并且可能影响整个渲染树的结构。为提升性能开发者通常会尽量避免频繁触发重排操作例如减少 DOM 操作或批量更新 DOM 元素。\n浏览器的安全机制\n随着互联网的普及浏览器成为用户与网络互动的核心工具。因此浏览器不仅需要提供流畅的用户体验还必须确保用户的安全。为了防止潜在的攻击和数据泄露现代浏览器引入了多种安全机制包括同源策略、内容安全策略、沙盒机制等。以下是浏览器常见的安全机制及其实现原理。\n同源策略SOP\n\n同源策略的定义\n同源策略Same-Origin Policy, SOP是浏览器中最基础、最重要的安全机制之一旨在防止恶意网站访问其他站点的资源。根据同源策略只有同源的网页可以相互访问和操作资源所谓“同源”是指协议、域名和端口号必须完全一致。\n\n协议如 http:// 和 https:// 是不同的协议。\n域名如 example.com 和 sub.example.com 不是同源。\n端口号如 example.com:80 和 example.com:8080 不是同源。\n\n同源策略的主要目的是防止恶意脚本跨站点攻击如盗取用户凭据、篡改数据或进行恶意操作。\nCORS跨源资源共享\n尽管同源策略有效阻止了跨域访问但实际开发中跨域资源共享是很常见的需求。例如前端应用通常需要从不同的 API 或服务器获取数据。为了安全地实现跨源访问浏览器引入了跨源资源共享Cross-Origin Resource Sharing, CORS机制。\nCORS 允许服务器通过设置适当的 HTTP 头部显式地告诉浏览器哪些域名、HTTP 方法和请求头可以合法地访问服务器资源。常见的 CORS 头部包括:\n\nAccess-Control-Allow-Origin指定允许访问的域名或 * 表示允许所有域。\nAccess-Control-Allow-Methods列出允许的 HTTP 方法,如 GET、POST 等。\nAccess-Control-Allow-Headers列出允许的自定义请求头。\n\nCORS 机制不仅增强了灵活性,还确保了跨域访问的安全性。\n内容安全策略CSP\nCSP 的作用\n内容安全策略Content Security Policy, CSP是浏览器用于防范跨站脚本攻击Cross-Site Scripting, XSS的重要安全机制。XSS 攻击指的是攻击者在网页中注入恶意脚本从而盗取用户信息或执行恶意操作。CSP 通过定义一组安全策略,控制页面可以加载的资源类型和来源,有效阻止未经授权的脚本或资源执行。\nCSP 策略通过在 HTTP 响应头中添加 Content-Security-Policy 字段来实现。常见的 CSP 指令包括:\n\nscript-src限制可以加载的 JavaScript 脚本来源。\nstyle-src限制可以加载的样式表来源。\nimg-src限制可以加载的图片资源来源。\ndefault-src为所有类型的资源设置默认来源限制。\n\n例如以下 CSP 策略仅允许加载来自同源self和特定可信域名的脚本\nContent-Security-Policy: script-src 'self' trusted.cdn.com;\n通过严格的 CSP 配置,开发者可以有效减少网页受到 XSS、点击劫持Clickjacking等攻击的风险。\n沙盒机制与隔离\n进程隔离与沙盒机制\n沙盒机制是一种重要的浏览器安全防护手段旨在将浏览器内部的各个组件如标签页、插件、扩展程序等相互隔离防止恶意代码影响整个系统。现代浏览器如 Chrome、Firefox、Edge采用多进程架构即每个标签页、插件和扩展程序运行在独立的进程中这样即便某个进程被攻击或崩溃其他进程仍能继续安全运行。\n具体而言沙盒机制通过以下方式保障安全\n\n标签页隔离每个标签页运行在独立的进程中阻止跨站脚本在不同标签页之间传播。\n插件隔离插件和扩展程序运行在沙盒中无法直接访问操作系统资源或文件系统从而减少安全风险。\n权限管理插件和扩展的权限受到严格限制浏览器通过权限请求机制确保用户知晓并同意插件的操作范围。\n\n沙盒机制极大地提升了浏览器的安全性和稳定性防止恶意代码对系统或用户数据造成损害。\n混合内容检测\n现代浏览器还引入了混合内容检测功能确保 HTTPS 页面只加载安全的内容。所谓混合内容,是指 HTTPS 页面尝试加载不安全的 HTTP 资源(如脚本、图片或样式)。混合内容会导致页面的安全性降低,因为攻击者可能通过不安全的 HTTP 内容发起中间人攻击MITM。\n浏览器通常会根据混合内容的类型采取不同的措施\n\n主动混合内容如 HTTP 脚本):浏览器会阻止加载,并向用户发出警告。\n被动混合内容如 HTTP 图片):浏览器可能允许加载,但会显示“不完全安全”的提示。\n\n通过阻止不安全资源浏览器能够保证 HTTPS 页面的完整性,防止敏感数据泄露或遭受攻击。\n浏览器的前沿技术\n随着 Web 技术的快速发展,现代浏览器已不再局限于传统的静态网页浏览,而是逐步向更为复杂、功能丰富的应用平台演进。为了支持这一转变,浏览器引入了多项前沿技术,如渐进式 Web 应用PWA和WebAssemblyWASM这些技术赋予 Web 应用接近原生应用的体验和性能优势。\n渐进式 Web 应用PWA\n渐进式 Web 应用Progressive Web App, PWA是一种旨在结合 Web 与原生应用优势的新型 Web 应用模式。PWA 通过现代 Web API 提供类似于原生应用的体验,包括离线使用、推送通知、快速加载等特性,确保用户即使在不稳定的网络环境下,依然可以流畅使用 Web 应用。\nService Workers\nService Workers是 PWA 的核心技术,提供了一层独立于 Web 页面的后台脚本,负责管理网络请求、缓存资源、离线支持和后台任务。它们通过拦截网络请求,实现灵活的缓存策略,从而加速页面加载速度并提供离线访问功能。\n\n缓存管理Service Workers 可以根据预定义的规则缓存静态资源(如 HTML、CSS、JavaScript、图片等从而减少重复请求提升页面加载速度。\n离线支持在网络连接不稳定或断开时Service Workers 可以提供缓存的内容,使用户即使离线也能使用部分功能。\n后台同步Service Workers 还支持后台同步功能,即在网络恢复后,自动发送先前存储的请求,实现数据的自动同步。\n\nself.addEventListener('fetch', event => {\n event.respondWith(\n caches.match(event.request).then(response => {\n return response || fetch(event.request);\n })\n );\n});\nManifest 文件\nManifest 文件为 PWA 提供了原生应用般的安装体验。它是一个 JSON 文件,用于定义 Web 应用的外观和行为。通过配置 Manifest 文件,开发者可以控制 PWA 的启动方式、图标、主题颜色以及全屏显示等行为。用户可以通过浏览器将 PWA 安装到设备的主屏幕,并像本地应用一样打开它。\nManifest 文件的常见字段包括:\n\nname应用名称。\nicons定义应用图标的路径和不同分辨率。\nstart_url定义应用启动时的默认 URL。\ndisplay控制应用启动后的显示模式如 fullscreen、standalone。\nbackground_color 和 theme_color定义启动画面和主题颜色。\n\n{\n "name": "My PWA App",\n "icons": [\n {\n "src": "icon-192x192.png",\n "sizes": "192x192",\n "type": "image/png"\n }\n ],\n "start_url": "/index.html",\n "display": "standalone",\n "theme_color": "#3367D6",\n "background_color": "#ffffff"\n}\n通过 Service Workers 和 Manifest 文件PWA 应用可以离线运行、快速加载,并为用户提供接近原生应用的使用体验。\nWebAssemblyWASM\nWebAssemblyWASM是一种全新的二进制格式旨在让高性能的编程语言如 C、C++、Rust 等)编译后在浏览器中运行。与 JavaScript 相比WebAssembly 具有接近原生代码的执行效率特别适合执行复杂的计算任务如视频处理、3D 渲染、数据分析和游戏开发等。\nWebAssembly 简介\nWebAssembly 是一种低级别的字节码,浏览器通过高效的虚拟机直接执行它。不同于传统的 JavaScript 脚本WebAssembly 在设计上强调性能优化,尤其是它的可预测性和跨平台特性,使得它在不同设备上都能快速、安全地执行。\nWebAssembly 的主要优势包括:\n\n高性能WebAssembly 代码的执行接近原生速度,适合对性能要求极高的应用场景,如游戏引擎、图形处理和音视频编辑等。\n可移植性WebAssembly 与平台无关可以在各大主流浏览器Chrome、Firefox、Safari 等)上运行,保证了代码的跨平台兼容性。\n\n与 JavaScript 的互操作\nWebAssembly 并不是用来完全取代 JavaScript而是与其配合使用。Web 开发者可以利用 WebAssembly 执行性能敏感的任务,同时仍然依赖 JavaScript 处理页面交互、DOM 操作等业务逻辑。WebAssembly 模块可以被 JavaScript 直接调用,并与之交换数据。\n// 加载和实例化WASM模块\nfetch('example.wasm').then(response =>\n response.arrayBuffer()\n).then(bytes =>\n WebAssembly.instantiate(bytes)\n).then(results => {\n const instance = results.instance;\n console.log(instance.exports.add(1, 2)); // 调用WASM中的函数\n});\n在这个示例中WebAssembly 模块中定义的函数可以被 JavaScript 调用,并返回计算结果。这种互操作使开发者可以使用诸如 C、C++ 或 Rust 等语言编写复杂的算法或高性能代码,然后在浏览器中通过 JavaScript 无缝地调用这些模块。\n应用场景\nWebAssembly 的典型应用场景包括:\n\n游戏开发借助 WebAssembly 的高性能,开发者可以将现有的桌面游戏移植到 Web 平台,实现流畅的 3D 渲染和复杂的物理计算。\n多媒体处理WebAssembly 可以用于音频和视频编解码、图像处理等需要大量计算的任务,提供接近原生应用的性能。\n科学计算与数据分析WebAssembly 在大规模数据处理、机器学习推理等领域也有着广泛的应用前景。\n"},"Technology/WebDevelopment/1.Browser/2.Chrome":{"title":"Chrome","links":[],"tags":["技术/WebDev","WebDev/Browser"],"content":"Chrome\n概述与特点\n诞生背景\nGoogle Chrome 浏览器首次发布于 2008 年 9 月,是由 Google 开发的一款免费网络浏览器。其设计初衷是为了提供更快速、稳定和安全的浏览体验。Chrome 的开发基于开源项目Chromium这不仅保证了开发的透明度和社区的贡献还促使它成为现代浏览器的技术基石之一。自发布以来Chrome 迅速获得了全球用户的青睐,并成为当前市场上最广泛使用的浏览器之一。\n核心特性\n\n速度Chrome 因其优异的性能和快速的网页加载能力而广受好评。其性能优势主要来自于高效的V8 JavaScript 引擎和Blink 渲染引擎。V8 引擎能够快速编译和执行 JavaScript 代码,而 Blink 渲染引擎负责页面的布局、渲染和绘制,这二者协同作用使 Chrome 在页面加载速度和响应能力上表现出色。\n简洁的用户界面Chrome 以其极简主义的设计风格著称提供了简洁的用户界面使用户可以专注于内容本身。Chrome 的设计思路是去除多余的工具栏和按钮,最大化显示网页内容,提升用户的浏览体验。\n多进程架构Chrome 率先采用了多进程架构,即每个标签页、插件以及渲染进程都独立运行。这种设计极大地提升了浏览器的稳定性和安全性。即使一个标签页崩溃,其他标签页依然可以正常运行,避免了浏览器整体崩溃的情况。此外,独立进程为每个页面提供了隔离,增强了浏览器的安全性,防止恶意网站对系统产生威胁。\n扩展支持Chrome 拥有丰富的扩展生态系统。用户可以通过 Chrome Web Store 下载并安装各种扩展程序扩展程序能够大幅增强浏览器的功能例如广告拦截、开发者工具、自动填充表单等。Chrome 的扩展系统基于 JavaScript、HTML 和 CSS 等 Web 技术,便于开发者构建并发布。\n跨平台兼容Chrome 可以在多种操作系统上运行包括Windows、macOS、Linux、Android和iOS并且提供一致的用户体验。无论是在桌面还是移动端用户都可以享受同样流畅的浏览体验这得益于 Chrome 对跨平台兼容性的支持。\n同步功能Chrome 允许用户通过 Google 账号实现跨设备的数据同步。用户只需登录 Google 账号,便可以同步书签、浏览历史记录、扩展程序和设置等内容,从而无缝衔接桌面和移动设备上的浏览体验。这一功能特别方便频繁在不同设备间切换的用户,提供了极高的便利性。\n\n市场份额\n根据多项权威的市场分析报告Google Chrome 自发布以来迅速占据了全球浏览器市场的主导地位。 截至目前Chrome 在桌面和移动端的全球市场份额常年稳居第一,拥有超过 60% 的市场占有率。这一现象得益于 Chrome 持续的技术创新和用户体验的提升。Chrome 不仅在速度、稳定性和安全性方面表现出色,还在功能扩展和跨平台支持等领域提供了极大的便利,使其成为用户的首选浏览器。\nChrome 与 Chromium 的关系\nChromium 项目\nChromium 是 Google 主导的一个开源浏览器项目Chrome 的开发正是基于此项目。 Chromium 作为开源项目,提供了所有 Chrome 浏览器的核心技术和渲染引擎,但它不包含某些 Google 特有的服务和功能例如自动更新、内置的Flash 插件、某些视频编解码器的支持(如 AAC 和 H.264)以及 Chrome 专属的用户数据同步功能。由于 Chromium 是完全开源的,任何开发者都可以基于 Chromium 的代码进行修改和重新发布。\n其他基于 Chromium 的浏览器\n许多现代浏览器都基于 Chromium 项目进行开发,利用其强大的渲染引擎和底层技术。这些浏览器在保留了 Chromium 的性能和安全特性的同时,根据各自的需求对功能和界面进行了定制。其中较为知名的浏览器包括:\n\nMicrosoft Edge在转向 Chromium 内核后Edge 获得了更好的网页兼容性和性能表现,同时保留了 Microsoft 独特的服务集成(如与 Windows 系统的深度整合)。\nOperaOpera 基于 Chromium 开发但提供了其特有的功能如内置的广告拦截、VPN 服务和侧边栏快速访问功能。\nBraveBrave 主打隐私保护,基于 Chromium 构建并在默认情况下屏蔽广告和跟踪器同时引入了其独特的奖励系统BAT鼓励用户和内容创作者。\n\n这种基于 Chromium 的浏览器生态系统的繁荣,进一步验证了 Chromium 项目的开放性和强大的技术基础。尽管这些浏览器在用户体验和功能集成方面各有特色,但它们共享了 Chromium 的核心技术,确保了与现代网页标准的兼容性和良好的性能表现。\nChrome 历史发展\nChrome 的发布与早期发展2008-2010\n首次发布\nGoogle Chrome 于 2008 年 9 月推出了第一个测试版,首次发布仅支持 Windows 平台。Chrome 的推出引发了广泛关注,它标志着 Google 进军浏览器市场的开始。与当时主流的浏览器(如 Internet Explorer 和 Firefox相比Chrome 的设计哲学是提供更快、更稳定和更安全的浏览体验。Chrome 通过引入先进的V8 JavaScript 引擎和多进程架构,让其在速度和稳定性方面领先于竞争对手。\n开源项目 Chromium\n与 Chrome 发布同步Google 还推出了Chromium项目作为 Chrome 的开源基础。Chromium 为开发者和社区提供了浏览器的核心代码。Google 发布的 Chrome 在 Chromium 的基础上加入了一些专有组件如自动更新机制和Adobe Flash 插件支持,这些是开源版本所不具备的。\nChrome 的独特架构也为浏览器带来了显著的性能提升特别是独立标签页崩溃保护。通过多进程模型Chrome 确保每个标签页独立运行,这意味着即使一个标签页崩溃,其他标签页也不会受到影响,从而极大地提高了浏览器的稳定性。\n市场影响\n发布后不久Chrome 的市场占有率快速攀升。其简洁的界面设计、卓越的性能以及与 Google 生态系统的深度集成吸引了大量用户。短短几个月内Chrome 成功从一个新兴浏览器发展为一个强有力的竞争者,并在几年内迅速获得了数百万的用户。至 2010 年Chrome 已经成为全球第三大浏览器,仅次于 Internet Explorer 和 Firefox。\nChrome 的快速迭代与功能扩展2011-2015\n引入扩展支持\n2010 年Chrome 推出了扩展支持,允许用户通过安装扩展程序来自定义浏览器的功能。这项功能彻底改变了用户与浏览器的交互方式,开发者也可以基于 Chrome 的扩展框架开发功能丰富的工具。通过这些扩展,用户可以轻松实现广告拦截、自动化任务和页面定制等功能,极大地增强了浏览器的灵活性。\n跨平台支持\nChrome 的成功不仅局限于 Windows 平台。2010 年Google 发布了macOS和Linux版本进一步扩大了用户群体。2012 年Chrome 正式登陆Android平台并迅速成为移动设备上的主流浏览器之一。这标志着 Chrome 进入了移动互联网的新时代,并通过跨设备的数据同步功能,提供了一致且无缝的用户体验。\nChrome Web Store 的发布\n2011 年Google 推出了Chrome Web Store一个集中化的扩展市场用户可以在这里下载和安装扩展、主题以及应用程序。该平台不仅为用户提供了丰富的选择还推动了开发者社区的发展使得 Chrome 的功能生态系统得以快速扩展。\n浏览器性能的持续提升\n随着网络应用复杂性的不断提高Google 持续优化 Chrome 的性能。Chrome 团队在 2011 至 2015 年间对启动速度、内存占用以及JavaScript 引擎性能进行了一系列改进使其在各大基准测试中长期占据领先地位。尤其是V8 JavaScript 引擎的不断优化,使得 Chrome 成为了前端开发者首选的开发与测试平台。\nChrome 的现代化演变2016- 至今)\nMaterial Design 风格引入\n2016 年Chrome 的界面设计进行了重大更新,正式引入了 Google 的Material Design设计语言。这一改动带来了更简洁的视觉风格和更加一致的用户体验。Material Design 的引入不仅优化了 Chrome 的外观,还提升了用户的操作流畅性,使得浏览体验更加直观和友好。\n对 HTTP 的安全改进\nGoogle 一直致力于提高 Web 的安全性。自 2017 年起Chrome 开始对未使用 SSL 加密的 HTTP 网站标注为“不安全”。这一举措是推动 Web 安全转型的重要一步促使大量网站转向更安全的HTTPS 协议。Chrome 对安全性的不懈追求,加速了整个互联网向加密通信的转变,提升了用户的隐私保护和数据安全。\n逐步淘汰 Flash\nChrome 对Adobe Flash的支持逐步减少并最终于 2020 年完全停止支持。这一决定反映了 Web 技术的演变趋势Google 希望通过淘汰 Flash推动更现代化的 Web 标准如HTML5和WebAssembly的应用提升 Web 的开放性、安全性和性能。\nChrome DevTools 的扩展与强化\nChrome 不仅作为用户浏览器表现卓越作为开发工具也同样功能强大。Chrome DevTools随着时间的推移不断扩展增加了对前端开发者至关重要的功能如JavaScript 调试、网络请求分析、性能监控以及渐进式 Web 应用PWA 的调试支持。Chrome DevTools 的进步,使得开发者能够更高效地分析和优化网页性能,提升开发效率。\n移动端的持续扩展与优化\n随着移动互联网的兴起Chrome 在移动端的表现也愈发重要。Google 通过优化移动端浏览器的性能、改进触屏交互以及增强跨设备同步功能,使用户能够在不同设备间无缝切换,进一步提升了跨平台浏览体验的流畅度。\n持续的性能优化与创新\nChrome 通过不断引入新技术和优化现有功能保持了其在浏览器市场的技术领先地位。例如内存管理优化和标签页冻结功能减少了不活跃标签页的资源占用大幅提高了整体性能。V8 JavaScript 引擎的持续优化、对WebAssembly的支持等也为现代 Web 应用提供了强大的运行时性能,进一步推动了浏览器在复杂应用场景中的应用。\nChrome 的架构\n多进程架构的概述\nChrome 的多进程架构设计是其性能、稳定性和安全性的重要基石。 与传统的单进程浏览器模型不同Chrome 将不同的浏览器任务分配给多个独立的进程从而提升了浏览器的稳定性和安全性。具体来说Chrome 的多进程模型可以划分为以下几类进程:\n\n浏览器进程浏览器进程是整个浏览器的主进程负责管理用户界面UI、网络请求、文件存储以及控制浏览器窗口和标签页的操作。它还处理用户的输入如点击、键盘输入并负责协调其他子进程之间的通信。\n渲染进程每个标签页都会有一个独立的渲染进程负责渲染页面内容。渲染进程处理 HTML、CSS 解析、JavaScript 执行和页面布局等任务。为了保证安全,渲染进程通常在沙盒中运行,这意味着它被隔离在一个有限的权限环境中,无法直接访问操作系统的关键资源,防止恶意网页或代码对系统造成破坏。\nGPU 进程GPU 进程专门负责处理与图形相关的任务,包括页面的图层合成和硬件加速绘制。这使得页面内容能够以更高效的方式呈现,尤其是对于需要大量图形处理的页面(如 3D 图形或动画GPU 加速能显著提高渲染性能。\n插件进程Chrome 为每个插件分配独立的插件进程,确保即使插件崩溃,也不会影响其他标签页或整个浏览器的运行。这种隔离机制同样提高了浏览器的稳定性。\n扩展进程Chrome 的扩展运行在独立的扩展进程中,与页面内容隔离。这不仅提高了浏览器的安全性,还能保证扩展不会干扰页面的正常运行。\n\n多进程架构的优缺点\n优点\n\n稳定性Chrome 的多进程架构显著提升了浏览器的稳定性。每个标签页、插件和扩展都在各自的进程中运行,因此即使一个标签页崩溃,其他标签页和浏览器本身仍然可以正常工作。此外,独立的插件进程避免了插件崩溃导致整个浏览器崩溃的风险。\n安全性Chrome 通过进程隔离和沙盒技术提高了浏览器的安全性。每个渲染进程在沙盒中运行,这限制了进程对操作系统的访问权限,降低了恶意代码攻击系统的风险。即使某个标签页被恶意攻击,攻击者也难以利用其控制整个系统。\n并行处理多进程架构允许 Chrome 更好地利用现代多核 CPU。由于多个进程可以并发执行Chrome 能够更高效地处理多个标签页的加载、渲染和执行任务,提升浏览器的整体性能。\n\n缺点\n\n内存占用较高由于每个进程都有自己的独立内存空间多进程架构导致了内存使用的显著增加。尤其是在同时打开多个标签页时每个标签页分配一个独立的渲染进程会占用更多的内存资源。虽然多进程模型带来了稳定性和安全性但相对于单进程浏览器它对系统的内存消耗更大。\n\n沙盒安全模型\n沙盒模型是 Chrome 实现浏览器安全的重要机制之一。它通过将渲染进程置于受限环境中,减少了恶意网页对系统的潜在威胁。\n\n渲染进程沙盒Chrome 中的渲染进程运行在沙盒中,这意味着即使渲染进程处理恶意网页,也无法直接访问操作系统的敏感资源或文件。沙盒通过限制系统调用、文件访问等权限,保护用户系统免受来自网页的潜在攻击。沙盒机制确保了即使网页中的 JavaScript 或恶意代码试图执行危险操作,这些操作也会被阻止,保证用户系统的安全。\n进程间通信IPCChrome 的多进程架构依赖于IPC进程间通信 机制来实现各进程之间的数据交换。浏览器进程、渲染进程、GPU 进程等通过 IPC 协议进行通信。例如,当用户在浏览器地址栏输入网址时,浏览器进程会将请求传递给渲染进程,渲染进程完成页面加载和渲染后,再通过 IPC 将结果返回。IPC 的设计确保了即使进程之间彼此隔离,它们仍能高效合作。\n\nChrome 的渲染机制\n从输入 URL 到页面渲染的详细过程\n当用户在浏览器地址栏中输入 URL 并按下回车键时,浏览器将开始一系列复杂的过程,从网络请求到页面渲染完成。下面是详细的步骤说明:\n浏览器请求阶段\n\nDNS 解析:浏览器首先通过 DNS域名系统将用户输入的域名转换为服务器的 IP 地址。如果该域名对应的 IP 地址已被缓存,浏览器可以直接使用缓存中的结果。否则,浏览器会通过 DNS 服务器查询 IP 地址。\n建立连接获取 IP 地址后,浏览器与服务器建立 TCP 连接。如果是 HTTPS 请求还需进行TLS 握手来加密通信。通常TCP 连接会通过三次握手来建立。\n发送 HTTP 请求:连接建立后,浏览器会发起 HTTP 请求,请求的内容包括 HTML 文档及其引用的资源(如 CSS、JavaScript、图片等。\n接收响应服务器处理请求后返回 HTTP 响应,其中包含了请求的 HTML 文档和其他资源的 URL。浏览器根据这些资源的类型进一步请求它们以便完成页面渲染。\n\n渲染流程概述\n浏览器接收到 HTML 文档和其他资源后,开始进入渲染流程,即将网络传输的字节转换为屏幕上可见的内容。该过程包括以下几个阶段:\n\n解析 HTML 生成 DOM 树:浏览器解析 HTML 文档并逐步生成DOM 树Document Object Model。DOM 树是页面的内部表示,它以树结构描述页面的内容和元素关系,每个 HTML 标签对应 DOM 树中的一个节点。\n解析 CSS 生成 CSSOM 树:浏览器解析外部和内联的 CSS 样式生成CSSOM 树CSS Object Model。CSSOM 树代表页面中的所有样式规则,描述了每个 DOM 元素的样式属性。\n合成渲染树浏览器将DOM 树和CSSOM 树结合起来生成渲染树Render Tree。渲染树包含页面中的所有可见元素并应用其样式。与 DOM 树不同,渲染树只包含需要显示的内容,诸如 <head> 标签或带有 display: none 样式的元素不会被包括在内。\n布局Layout渲染树生成后浏览器开始进行布局计算也称为 ” 回流 “。在此步骤中,浏览器计算每个元素的具体大小和位置。布局过程基于 CSS 盒模型,通过对渲染树进行遍历来确定元素的几何属性,如宽度、高度、相对位置等。\n绘制Painting完成布局后浏览器将绘制页面的内容。绘制包括文本、颜色、背景、边框、阴影等各类视觉样式。此时渲染树中的元素被绘制成位图。\n合成与图层管理Compositing页面中可能有多个图层如浮动的元素、动画等这些图层需要由合成器线程进行合成处理。合成器将这些图层组合成最终的页面视图并通过 GPU 进行硬件加速渲染,从而提高渲染性能,尤其是复杂页面的绘制效率。\n\nChrome 的 Blink 渲染引擎\nBlink 引擎概述\nBlink是 Google Chrome 使用的渲染引擎,它是从 WebKit 渲染引擎的一个分支,专门用于处理 HTML、CSS、JavaScript 等 Web 内容并将其转化为屏幕上可见的页面。Blink 的高效性和现代化设计使得 Chrome 具备了快速的页面加载和渲染能力。\n渲染树的生成与作用\n\n渲染树生成Blink 通过解析 DOM 树和 CSSOM 树来生成渲染树。渲染树只包含可见的页面元素及其样式,因此相比 DOM 树,渲染树结构更加精简且高效。\n渲染树的作用渲染树是后续布局和绘制过程的基础。它提供了每个可见元素的样式和层次关系供浏览器在布局计算和最终绘制时使用。Blink 通过对渲染树的处理,将页面内容准确地呈现给用户。\n\n合成器线程Compositor Thread\n为了提高渲染性能Blink 引入了合成器线程。合成器线程专门处理图层的合成任务,避免主线程(负责执行 JavaScript 和处理页面逻辑)因繁重的渲染任务而被阻塞。合成器线程通过协调各个图层的绘制,确保页面即使在存在复杂动画或大量图层时,仍能流畅地进行渲染。\nV8 JavaScript 引擎\nV8是 Chrome 中的 JavaScript 引擎,负责将 JavaScript 代码转换为机器码并执行。作为一款高性能引擎V8 在 JavaScript 的执行效率、内存管理和性能优化上有许多先进的设计。\n即时编译JITJust-in-Time\nV8 采用了即时编译JIT技术通过将 JavaScript 代码在执行时即时编译为机器码避免了传统解释器逐行解释执行代码的低效问题。JIT 编译大大提升了 JavaScript 的执行速度,使得现代 Web 应用中的 JavaScript 代码能够在浏览器中快速运行。\n垃圾回收机制\nV8 通过分代式垃圾回收Generational Garbage Collection来管理内存。分代垃圾回收将内存中的对象分为“新生代”和“老生代”两个区域。新生代对象是刚刚创建的对象回收频率较高而老生代对象则是存活时间较长的对象。通过对新生代对象进行快速清理并采用更复杂的策略回收老生代对象V8 能够有效降低内存泄漏,并保证应用的平稳运行。\nChrome 的性能优化\n优化 Chrome 浏览器中的页面性能和网络性能是提升用户体验和提高应用响应速度的关键。在现代 Web 开发中,合理管理关键渲染路径、减少不必要的 DOM 操作、以及充分利用网络协议和缓存机制,能够显著提高 Web 应用的整体表现。\n页面性能优化\n页面性能优化的核心在于减少渲染的阻塞、减少 DOM 操作的开销,以及最大限度地优化资源加载和渲染流程。\n关键渲染路径优化\n关键渲染路径Critical Rendering Path是浏览器从获取 HTML 文件到将页面内容呈现在屏幕上的一系列步骤。为了加快页面渲染速度,开发者应尽量减少阻塞渲染的关键资源,并异步加载非必要的资源。\n\n减少阻塞资源CSS 和 JavaScript 文件会阻塞页面的渲染,尤其是位于页面头部的资源。为了优化关键渲染路径,可以使用 <link rel="preload"> 预加载关键资源,减少首次渲染时间。\n异步加载 JavaScript使用 async 或 defer 属性加载 JavaScript 文件。async 属性允许脚本并行下载并尽快执行,而 defer 则在 HTML 解析完成后才执行脚本,避免阻塞页面的渲染。\n\n<script src="script.js" async></script>\n<script src="deferred.js" defer></script>\n\nCSS 优化:将关键的 CSS 直接内联到 HTML 文件中,减少渲染的阻塞时间。对于非关键 CSS 文件,使用 media 属性延迟其加载。\n\n<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">\n减少重绘与回流\n\n重绘Repaint发生在元素的视觉外观发生改变时例如颜色、背景或阴影变化但不影响其布局。重绘虽然比回流开销小但仍然影响性能。\n回流Reflow回流是布局的重新计算发生在元素的大小、位置或结构发生改变时需要重新计算渲染树。回流比重绘开销大频繁的回流会显著影响性能。\n\n优化策略\n\n减少 DOM 操作:频繁修改 DOM 会引发回流。应尽量避免多次操作 DOM代之以批量操作。例如使用 DocumentFragment 来集中处理多次 DOM 修改,最后一次性插入页面。\n避免触发回流属性访问或修改像 offsetWidth、offsetHeight、scrollTop 等属性会强制触发浏览器的回流。将这些操作集中到一个步骤中,避免在同一循环中反复读取和修改布局属性。\nCSS 优化:将影响性能的动画限制在 transform 和 opacity 上,这样可以避免触发回流。\n\n网络性能优化\n网络优化是页面快速加载的另一个重要环节优化网络请求的数量和质量能够显著加快页面的初次渲染。\nHTTP/2 与 HTTP/3 的使用\n\nHTTP/2通过多路复用技术HTTP/2 允许多个请求同时通过一个 TCP 连接传输减少了连接的建立和关闭时间。同时HTTP/2 支持头部压缩,通过减少冗余的 HTTP 请求头部信息,进一步减少了网络传输的开销。\nHTTP/3基于 UDP 协议的 HTTP/3利用QUIC协议减少了 TCP 的握手延迟,并且可以在网络不稳定时更加高效地恢复数据传输,进一步提升了网站的加载速度。\n\nCDN 和缓存优化\n\nCDN内容分发网络通过使用 CDN将静态资源分布到多个地理位置的服务器上确保用户从最近的服务器获取资源减少传输延迟。CDN 还能有效减轻源服务器的负担,提高整体响应速度。\n缓存策略合理利用浏览器缓存能够极大提升页面加载性能。通过配置 Cache-Control 和 ETag 等 HTTP 头部,可以控制资源的缓存时间和验证机制,避免重复下载未更改的资源。\n\nCache-Control设置资源的缓存有效期例如使用 max-age 指定资源在多少秒内有效。\nETag利用 ETag 头部标识资源的版本,当资源没有变化时,服务器可以返回 304 状态码,告知浏览器使用本地缓存,减少网络带宽的消耗。\n\n\n\nCache-Control: max-age=31536000, public\nETag: "abc123"\nLazy Load 技术\n**懒加载Lazy Loading**是优化初次加载时的资源利用效率的重要技术,尤其适用于图片和视频等较大资源。懒加载技术会延迟加载那些在页面初始化时不需要立即显示的资源,直到用户滚动到这些资源的位置时才加载它们。\n\n图片懒加载在现代浏览器中可以通过为 <img> 标签添加 loading="lazy" 属性,轻松实现图片的懒加载。\n\n<img src="large-image.jpg" loading="lazy" alt="Lazy loaded image">\n\n视频懒加载类似的视频也可以使用懒加载技术只有当用户即将观看时才加载视频内容。\n\n通过这些技术页面的初始加载时间和数据传输量都能够显著减少从而提升页面的响应速度。\nChrome 浏览器的安全机制\nChrome 浏览器的安全机制旨在保护用户的数据和隐私防止恶意网站或代码对用户系统造成危害。它通过多种技术手段确保网页和扩展的安全性包括同源策略、沙盒机制和内容安全策略CSP。\n同源策略SOP, Same-Origin Policy\n同源策略的定义\n同源策略Same-Origin Policy, SOP是 Web 安全模型的核心之一它限制了不同来源origin之间的文档和脚本如何进行交互。浏览器将每个网页的资源视为具有特定的来源只有在同源的情况下页面之间的脚本才能进行互相访问。这种机制极大地减少了潜在的安全威胁例如跨站脚本XSS和跨站请求伪造CSRF。\n\n来源的定义同源意味着两个 URL 具有相同的协议、域名和端口。例如example.com:443 与 example.com 视为同源,但 example.com 与 example.com、sub.example.com 则被视为不同源。\n\n通过同源策略Chrome 可以有效防止恶意网站通过脚本读取、修改或操纵其他站点的敏感信息,从而提升用户数据的安全性。\n跨源资源共享CORS, Cross-Origin Resource Sharing\n尽管同源策略能够提高安全性但它也对合法的跨域资源访问造成了限制。为了解决这一问题跨源资源共享CORS机制应运而生。CORS 允许服务器通过 HTTP 头部信息明确声明哪些外部来源可以访问其资源,进而控制跨域请求的安全性。\nCORS 的工作机制包括:\n\n预检请求当浏览器发送跨域请求时首先会通过 OPTIONS 方法发出预检请求,询问服务器是否允许该跨域访问。服务器通过响应头中的 Access-Control-Allow-Origin、Access-Control-Allow-Methods 等字段来决定是否允许请求。\n跨域响应头服务器可以通过设置 Access-Control-Allow-Origin 头部,指定允许访问资源的来源。设置为 * 表示允许任何源访问该资源。\n\nAccess-Control-Allow-Origin: example.com\n通过 CORSChrome 浏览器能够灵活处理跨域资源请求,确保在安全框架下允许合法的跨域数据交互。\n沙盒机制与浏览器安全\n沙盒隔离\nChrome 的沙盒机制是其安全架构的核心之一。沙盒将每个标签页、插件或扩展的渲染进程与操作系统隔离开来,限制其对系统资源的访问。这意味着,即使某个网页包含恶意代码,该代码也无法直接访问或修改用户的文件、网络连接或其他敏感资源。\n\n沙盒隔离的优点\n\n限制访问权限沙盒通过减少进程的权限确保恶意网站或代码只能在受控的环境中运行无法对系统核心组件造成威胁。\n安全分区每个标签页的渲染进程都在沙盒中独立运行如果一个标签页崩溃或受到攻击其他标签页不会受到影响保障了浏览器的稳定性和安全性。\n\n\n\n这种基于沙盒的隔离策略不仅防止了浏览器内恶意脚本的横向移动还阻止了潜在攻击对操作系统和用户数据的直接访问。\n内容安全策略CSP, Content Security Policy\n内容安全策略Content Security Policy, CSP是 Chrome 中用于防止常见 Web 攻击(如 XSS的关键机制。CSP 通过定义允许网页加载的资源类型和来源,帮助开发者控制网页内容的来源,防止恶意脚本或未经授权的资源注入页面。\n\nCSP 的作用:\n\n防止 XSS 攻击:通过 CSP开发者可以禁止网页加载未经授权的脚本从而阻止恶意脚本通过漏洞注入到网页中执行。\n限制资源加载CSP 允许开发者指定页面能够加载的资源来源(如脚本、样式、图像等),从而限制外部资源对页面的影响。例如,开发者可以使用 CSP 规定只有从可信的域名加载 JavaScript 文件。\n\n\n\nCSP 示例:\nContent-Security-Policy: script-src 'self' trusted.cdn.com; object-src 'none';\n该策略仅允许从当前来源self和受信任的 CDNtrusted.cdn.com加载脚本并禁止页面加载任何插件或嵌入式对象object-src 'none'。通过这种方式CSP 可以极大地减少攻击面,防止常见的跨站脚本攻击。\nChrome 扩展开发\nChrome 扩展的核心概念\nChrome 扩展是用于增强浏览器功能的模块,允许用户根据需求自定义浏览体验。开发 Chrome 扩展需要遵循特定的结构和 API 规范。以下是 Chrome 扩展的核心概念和主要组成部分:\nmanifest.json 文件\n**manifest.json**是每个 Chrome 扩展的核心配置文件,负责定义扩展的基本信息、权限、功能以及相关资源。该文件的内容决定了扩展的行为方式以及可以访问的浏览器功能。主要字段包括:\n\nname扩展的名称。\nversion扩展的版本号。\nmanifest_versionChrome 扩展的规范版本(目前为 3。\npermissions扩展所需的权限如访问特定网站、读取浏览历史、操作标签页等。\nbackground定义扩展的背景脚本可以长期运行并处理后台任务。\ncontent_scripts定义内容脚本它们能够注入到网页中操纵 DOM 结构。\nicons扩展所使用的图标。\n\n示例\n{\n "name": "My Chrome Extension",\n "version": "1.0",\n "manifest_version": 3,\n "permissions": ["tabs", "storage"],\n "background": {\n "service_worker": "background.js"\n },\n "content_scripts": [\n {\n "matches": ["https://*.example.com/*"],\n "js": ["content.js"]\n }\n ],\n "icons": {\n "16": "icon16.png",\n "48": "icon48.png",\n "128": "icon128.png"\n }\n}\n背景脚本Background Scripts\n背景脚本负责管理扩展的长时间运行任务通常用于事件监听、消息传递和执行特定的操作。背景脚本在后台运行不会直接与网页交互它们可以通过chrome API与浏览器进行通信。例如它可以监听标签页的创建、关闭或消息传递。\n在 Manifest Version 3 中背景脚本被Service Workers取代进一步增强了扩展的性能和安全性确保扩展在不活动时不占用系统资源。\n示例\nchrome.runtime.onInstalled.addListener(() => {\n console.log("Extension installed");\n});\n \nchrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {\n if (changeInfo.status === "complete") {\n console.log("Tab updated:", tab.url);\n }\n});\n内容脚本Content Scripts\n内容脚本运行在特定网页的上下文中允许开发者直接操作网页的 DOM 结构。它们可以修改页面的内容、插入样式或脚本,但不能直接访问 Chrome 扩展的 API。为了与背景脚本或扩展其他部分通信内容脚本可以使用消息传递机制。\n内容脚本与页面的 JavaScript 环境是分离的,虽然它们能够操作 DOM但无法直接访问页面的全局变量或函数。\n示例\ndocument.body.style.backgroundColor = "yellow";\n扩展的安全模型\n为了防止恶意扩展滥用浏览器功能Chrome 扩展的安全模型设计了严格的权限和跨域请求限制。开发者必须声明扩展所需的所有权限,并且 Chrome 会在扩展安装或运行时提示用户。\n权限模型\n每个 Chrome 扩展必须在 manifest.json 中明确声明其所需的权限,如访问特定网站的权限、读取或修改浏览历史的权限、操作 Cookie 或标签页的权限等。Chrome 通过这种机制限制扩展的访问范围,以减少潜在的安全威胁。\n常见权限示例\n\n"tabs":允许扩展访问和操作浏览器的标签页。\n"cookies":访问和修改网站的 Cookie。\n"storage":使用 Chrome 的本地存储功能。\n"activeTab":允许扩展与当前活动的标签页交互。\n\n跨域请求\nChrome 扩展可以通过 chrome.extension API执行跨域请求而无需遵守浏览器通常的同源策略**Same-Origin Policy。然而为了保证安全开发者必须在 manifest.json 中声明明确的权限,允许扩展访问特定域名。这种设计确保扩展不会随意访问或篡改用户的数据。\n{\n "permissions": [\n "api.example.com/"\n ]\n}\n通过这种方式用户可以清楚地了解扩展的访问权限防止扩展未经许可访问敏感数据。\n开发与调试\nChrome 扩展的开发过程中Chrome 浏览器提供了丰富的调试工具,帮助开发者在不同的环境下进行测试和调试。\nChrome DevTools\nChrome DevTools 不仅可以用于调试网页,还支持对 Chrome 扩展进行调试。开发者可以通过以下功能调试扩展:\n\n调试内容脚本通过“Sources”选项卡调试注入到网页中的内容脚本设置断点、查看 DOM 结构或检查网络请求。\n调试背景脚本在“Background page”中开发者可以查看并调试背景脚本的运行状态监控事件、网络请求和消息传递行为。\n消息传递调试通过检查“Console”选项卡中的日志信息分析内容脚本与背景脚本之间的通信是否正常。\n\n发布到 Chrome Web Store\n扩展开发完成后开发者可以将其打包并发布到Chrome Web Store。发布步骤如下\n\n打包扩展在 Chrome 的扩展管理页面中,将开发完成的扩展打包为 .zip 文件。\n注册开发者账号开发者需拥有 Google 账号并注册成为 Chrome Web Store 的开发者。\n上传扩展通过 Chrome Web Store 管理后台上传打包的扩展文件。\n填写扩展信息包括扩展名称、描述、版本信息、权限说明、截图等。\n审核和发布Chrome Web Store 会对扩展进行安全审核,确保其符合安全规范和隐私政策。审核通过后,用户可以从 Chrome Web Store 下载安装扩展。\n\nChrome 的前沿技术\nChrome 浏览器始终处于推动 Web 技术发展的前沿,不断引入新的技术来增强 Web 应用的功能和性能。以下是两项重要的前沿技术:渐进式 Web 应用PWA*和*WebAssemblyWASM。\n渐进式 Web 应用PWA, Progressive Web App\n渐进式 Web 应用PWA是一种结合了 Web 和原生应用优势的新型 Web 应用模型。PWA 可以在网络不稳定的情况下正常运行,并且能够像原生应用一样被安装到用户设备上,提供离线功能、推送通知和快捷启动等特性。\nPWA 的核心技术\n\n\nService WorkersService Workers是 PWA 的核心技术,运行在浏览器的后台,独立于网页本身。它能够拦截网络请求,缓存静态资源,从而实现离线访问。通过 Service WorkersPWA 可以在没有网络连接时继续工作,提供类似原生应用的用户体验。\n另一个关键功能是推送通知。即使应用未被打开Service Workers 也可以通过服务器推送消息提供消息通知功能。此外Service Workers 还可以控制更新策略,确保应用始终保持最新版本。\n// 注册 Service Worker\nif ('serviceWorker' in navigator) {\n navigator.serviceWorker.register('/sw.js').then(registration => {\n console.log('Service Worker registered with scope:', registration.scope);\n }).catch(error => {\n console.log('Service Worker registration failed:', error);\n });\n}\n\n\nManifest 文件Web App Manifest是一个 JSON 文件,定义了 PWA 的启动行为、图标、显示模式(如全屏、固定窗口等),使 Web 应用在外观和使用上更接近原生应用。通过 Manifest 文件,用户可以将 PWA 应用安装到主屏幕,并通过自定义图标和启动界面提供一致的用户体验。\n示例 manifest.json 文件:\n{\n "name": "My PWA",\n "short_name": "PWA",\n "start_url": "/index.html",\n "icons": [\n {\n "src": "/images/icon-192.png",\n "sizes": "192x192",\n "type": "image/png"\n },\n {\n "src": "/images/icon-512.png",\n "sizes": "512x512",\n "type": "image/png"\n }\n ],\n "background_color": "#ffffff",\n "display": "standalone"\n}\n\n\nPWA 在 Chrome 中的支持与调试\nChrome 对 PWA 提供了全面的支持并且可以通过Chrome DevTools对 PWA 的功能进行调试:\n\n离线缓存调试在 Chrome DevTools 的 “Application” 面板中,开发者可以查看和管理 Service Workers 的缓存状态,查看哪些资源被缓存,以及何时清理缓存。\n推送通知调试DevTools 允许调试 PWA 的推送通知行为,查看消息是否成功推送,并在控制台模拟推送事件。\nManifest 文件调试:通过 DevTools 的 “Application” 面板,开发者可以检查 PWA 的 Manifest 文件配置,确保应用图标、启动 URL 等内容符合预期。\n\nWebAssemblyWASM\nWebAssemblyWASM是一种基于字节码的编程语言它允许开发者在浏览器中运行接近原生性能的代码。WASM 的出现使得高性能计算和复杂的应用场景(如游戏、图像处理、数据分析等)可以在浏览器中高效运行。\nWebAssembly 简介\nWebAssembly 是一种平台无关的二进制格式,通过编译其他高级语言(如 C、C++、Rust生成字节码在浏览器中执行这些代码时能够接近原生应用的性能。WASM 的设计目标是让 Web 应用能够高效地处理复杂计算任务,如 3D 图形、音频处理和加密等,这些通常是 JavaScript 难以胜任的场景。\nWebAssembly 的主要优点包括:\n\n高性能相比于 JavaScriptWASM 以二进制形式传输和执行,具有更快的解析速度和更高效的运行性能。\n跨平台WASM 是跨浏览器、跨平台的Chrome、Firefox、Edge、Safari 等主流浏览器都支持运行 WASM 模块。\n语言无关性WebAssembly 不依赖于某一种编程语言,开发者可以用多种高级语言编写代码并编译为 WASM。\n\n与 JavaScript 互操作\nWebAssembly 并非要完全取代 JavaScript而是与其互补。开发者可以在 JavaScript 中调用 WASM 模块,同时利用 JavaScript 的灵活性和 WASM 的高效计算能力,结合两者的优势构建复杂的 Web 应用。\n下面是一个基本的 WASM 和 JavaScript 互操作示例:\n\n\n编译 C 代码为 WASM 假设我们有一个 C 函数 add将其编译为 WASM 模块。\n// add.c\nint add(int a, int b) {\n return a + b;\n}\n使用 emscripten 工具链将 C 代码编译为 WebAssembly\nemcc add.c -s WASM=1 -o add.wasm\n\n\n在 JavaScript 中加载和调用 WASM 模块:\nconst importObject = {\n env: {\n // 可以定义一些供WASM使用的全局变量或函数\n }\n};\n \nWebAssembly.instantiateStreaming(fetch('add.wasm'), importObject)\n .then(obj => {\n const add = obj.instance.exports.add;\n console.log("Result of 3 + 4 =", add(3, 4)); // 输出Result of 3 + 4 = 7\n });\n\n\n在这个示例中WASM 模块定义了一个 add 函数,并通过 JavaScript 进行调用。WebAssembly 模块可以高效执行数值运算、处理复杂算法,从而显著提升应用的性能。"},"Technology/WebDevelopment/1.Browser/3.Firefox":{"title":"Firefox","links":[],"tags":["技术/WebDev","WebDev/Browser"],"content":"Firefox\nFirefox 的概述与特点\n诞生背景\nFirefox 是由 Mozilla 基金会发布的开源浏览器,其历史可以追溯到 2002 年以“Phoenix”项目为起点。 作为 Netscape 浏览器的继承者Firefox 的目标是提供一个开放源代码、隐私保护至上的浏览器推动开放互联网的发展。2004 年Firefox 正式推出 1.0 版本,并迅速成为主流浏览器,打破了当时 Internet Explorer 的垄断地位。\n核心特性\n\n速度Firefox 使用的Gecko 渲染引擎和SpiderMonkey JavaScript 引擎对页面加载和执行速度进行了持续优化。通过引入Quantum 项目Firefox 的性能在 2017 年得到了显著提升特别是在多核处理器上的并发执行效率方面。Quantum 通过改进 Gecko 引擎的架构,使得浏览器在处理复杂网页时的速度和响应能力大幅提高。\n隐私与安全Firefox 以其强大的隐私保护功能著称。浏览器内置了增强型追踪保护,可以阻止广告追踪器、第三方 Cookie 以及恶意脚本的运行。此外Firefox 还提供了隐私浏览模式自动清除会话结束后的所有历史记录和数据。Mozilla 还在持续开发工具如Firefox Monitor帮助用户检测数据泄露进一步保障用户隐私。\n扩展支持Firefox 支持广泛的扩展生态系统,并且与 Chrome 的扩展框架兼容采用了WebExtensions API。这意味着大多数为 Chrome 开发的扩展可以轻松移植到 Firefox用户可以访问大量扩展程序来定制浏览器功能。\n开源与透明作为一个开源项目Firefox 的源代码对公众开放任何开发者都可以查看、贡献或修改其代码。Mozilla 通过社区驱动的开发模式确保了浏览器的透明性和公正性。Firefox 的开放性不仅为开发者提供了自由,也使得用户能够信任该平台不会滥用数据或隐私。\n跨平台支持Firefox 支持多种操作系统包括Windows、macOS、Linux、Android和iOS。无论在哪个平台上Firefox 都提供一致的用户体验和功能集成,确保用户在不同设备上能够无缝切换浏览体验。\n同步功能Firefox 提供同步功能,允许用户通过创建 Firefox 账户,同步书签、浏览历史、扩展、密码和设置等信息。这一功能对于在多个设备上使用 Firefox 的用户而言,极大地提升了便利性和一致性。\n\n市场份额\n尽管 Firefox 的市场份额较谷歌 Chrome 有所减少,但它在隐私保护、开发者工具以及开源社区中的影响力依然显著。 尤其是在注重隐私和安全的用户群体以及开发者社区中Firefox 继续保持较高的忠诚度。开发者工具如Firefox DevTools提供了与 Chrome DevTools 类似的功能,吸引了大量开发者使用 Firefox 作为调试和开发环境。\nFirefox 与 Mozilla 的关系\nMozilla 基金会\nMozilla 基金会是非营利组织,成立于 2003 年,负责 Firefox 浏览器的开发与维护。Mozilla 的使命是促进开放、可访问、隐私保护的互联网发展。与一些商业浏览器不同Mozilla 的非营利性质确保了其不会依赖广告和数据追踪来获利,从而进一步保障了用户的隐私和数据安全。\nGecko 引擎\nGecko是 Mozilla 独立开发的渲染引擎,与 Chrome 的 Blink 引擎不同。Gecko 是开源的,旨在符合 W3C 的最新 Web 标准,并且经过了持续的优化,以提高性能、兼容性和安全性。它为 Firefox 提供了强大的 Web 渲染能力,并支持复杂的网页布局和动画处理。\nQuantum 项目\nQuantum 项目是 Mozilla 于 2017 年启动的重大性能提升计划,旨在彻底重构 Firefox 的引擎架构使其更快、更高效。Quantum 通过并行处理、多线程任务调度和内存管理的优化,使得 Firefox 在多核处理器上可以更好地利用硬件资源。这一项目极大提升了 Firefox 的加载速度、响应性和稳定性,并缩小了与其他主流浏览器的性能差距。\nQuantum 项目的推出标志着 Firefox 进入了一个新的性能时代,使其在与 Chrome 的竞争中具有了更强的技术基础。\nFirefox 历史发展\nFirefox 的早期发展2002-2010\nPhoenix 和 Firebird\nFirefox 的历史可以追溯到 2002 年,当时 Mozilla 社区开发了一个名为Phoenix的浏览器作为 Netscape Navigator 的继承者。Phoenix 以其轻量、快速和灵活的特性,试图与当时市场主导的 Internet Explorer 竞争。由于与另一个软件发生商标冲突Phoenix 被改名为Firebird。但很快Mozilla 决定将其最终命名为Firefox。\n2004 年Mozilla 发布了Firefox 1.0这是第一个正式版本。它以简洁的界面和卓越的性能迅速吸引了用户。当时Firefox 作为开源的替代选择提供了更强的安全性、隐私保护和浏览体验受到广大用户的欢迎。2004 年底Firefox 的下载量突破了 100 万次,标志着其作为主流浏览器的崛起。\nMozilla 的开放源代码理念\nFirefox 的诞生与发展深受Mozilla 开放源代码理念的影响。作为一个完全开源的浏览器Firefox 的代码对全球开发者开放,任何人都可以为其做出贡献。这种开发模式使得 Firefox 能够快速响应用户需求,进行持续的改进与创新。\n开源社区的支持不仅推动了 Firefox 技术的进步,还帮助其打造了一个高度活跃的开发者生态系统。这一生态系统为 Firefox 带来了新的功能和修复,也使得它能够快速跟进和实施最新的 Web 标准。\nFirefox 扩展生态的建立\nFirefox 在早期就意识到了扩展支持的重要性。它为用户提供了高度可定制的浏览体验,允许开发者创建扩展来增强浏览器的功能。通过 Firefox 扩展生态,用户可以安装广告拦截器、开发者工具、密码管理器等各种插件,满足不同的使用需求。\nFirefox 的扩展系统帮助它迅速积累了大批忠实用户和开发者。Firefox 成为了第一款主流浏览器中提供强大扩展支持的产品,这不仅增加了用户粘性,也推动了 Firefox 作为创新平台的形象。\nFirefox 的技术革新与竞争2011-2015\n多进程架构\nFirefox 最初采用单进程架构,即所有标签页、扩展和插件都在一个进程中运行。这导致了性能问题,尤其是当某个标签页崩溃时,会影响整个浏览器的稳定性。与采用多进程架构的 Chrome 相比Firefox 在性能和稳定性方面处于劣势。\n2011 年Mozilla 启动了Electrolysise10s项目逐步将 Firefox 转向多进程架构。通过这一架构,每个标签页、插件和扩展都在独立的进程中运行,从而提高浏览器的稳定性、安全性和性能。这一转变帮助 Firefox 缩小了与竞争对手 Chrome 在性能上的差距。\n扩展支持的改进\n为了提升扩展的兼容性Firefox 逐步过渡到WebExtensions API该 API 与 Google Chrome 的扩展框架兼容。这使得开发者可以更轻松地将 Chrome 扩展移植到 Firefox 上,丰富了 Firefox 的扩展生态。\n这一变化使得 Firefox 能够继续保持其高度可定制的特性,同时确保扩展的安全性和性能。与 Chrome 的兼容性也使得用户可以在两个平台之间无缝切换扩展,提升了用户体验。\nFirefox OS 项目\nMozilla 在此期间也探索了移动平台的可能性,推出了基于 Web 技术的移动操作系统Firefox OS。该系统主要面向低成本的智能手机市场旨在通过开放的 Web 技术推动移动互联网的普及。尽管 Firefox OS 未能在市场上取得预期的成功,并于 2016 年停止开发,但其在推动 Web 技术向移动端发展的过程中贡献显著。\nFirefox 的现代化演变2016- 至今)\nQuantum 项目的引入\n2017 年Mozilla 推出了Quantum 项目,这是 Firefox 现代化演变的标志性事件。Quantum 项目通过重构 Firefox 的浏览器引擎,带来了性能的质变提升。该项目引入了并行处理和多核优化,确保 Firefox 可以更高效地利用现代硬件资源。\nQuantum 项目显著提升了 Firefox 的速度和内存管理效率特别是在处理复杂网页和多任务操作时的表现。Quantum 还引入了基于 GPU 的图形渲染,进一步提升了网页的加载速度和流畅度,使得 Firefox 能够与 Chrome 等浏览器竞争。\n引入 Servo 技术\nFirefox 在 Quantum 项目中部分采用了由 Mozilla 开发的Servo 引擎技术。Servo 是一个基于 Rust 语言的新型浏览器引擎具备高并发处理和安全特性。Rust 语言的内存安全特性减少了传统 C/C++ 代码中的漏洞风险,这使得 Firefox 在性能与安全性上更具优势。\nServo 的引入使得 Firefox 能够更高效地进行并发任务处理,优化了渲染速度和内存使用,并为未来进一步提升性能提供了坚实基础。\n隐私保护的创新\n随着用户隐私日益受到关注Firefox 通过不断引入新的隐私保护功能进一步巩固了其在隐私领域的领先地位。2018 年Firefox 推出了增强型跟踪保护Enhanced Tracking Protection旨在阻止广告追踪器和第三方 Cookie从而保护用户隐私。\nMozilla 还推出了专注于隐私保护的浏览器Firefox Focus它默认启用广告拦截和隐私保护功能不保留浏览记录成为注重隐私用户的首选浏览器之一。\n逐步淘汰旧技术\n随着 Web 技术的发展Firefox 逐步淘汰了一些过时的技术如Adobe Flash。Mozilla 通过推动现代 Web 标准如HTML5、WebAssembly、WebRTC的采用促进了 Web 平台的进步。WebAssembly 的引入,使得开发者能够在浏览器中运行接近原生性能的代码,为高性能 Web 应用提供了强大的支持。\nFirefox 的架构\n多进程架构的概述\n多进程架构是现代浏览器中重要的设计模式通过将不同功能模块分离到独立的进程中提高浏览器的稳定性、安全性和性能。Electrolysise10s项目是 Mozilla 为 Firefox 引入多进程架构的关键项目,旨在解决传统单进程浏览器存在的崩溃、性能和安全性问题。通过 e10sFirefox 在架构上经历了重大革新,将用户界面、内容渲染和后台任务处理分布在多个独立的进程中,从而显著提升了用户体验。\nElectrolysise10s项目\nElectrolysis项目的推出是 Firefox 从单进程架构转向多进程架构的里程碑。单进程浏览器模式将所有页面、插件和 UI 渲染放在同一进程中导致一个标签页或插件的崩溃会引发整个浏览器的崩溃。Electrolysis 通过将浏览器的 UI 和页面内容分离到不同的进程中,解决了这一问题。\n核心目标\n\n稳定性通过进程隔离确保单个页面的崩溃不会影响其他标签页或浏览器主进程。\n性能分离进程后Firefox 能够更高效地分配资源,避免单个任务占用过多系统资源。\n安全性独立的内容进程运行在受限的权限范围内减少了恶意脚本对系统造成威胁的可能性。\n\n进程模型设计\nFirefox 的多进程架构将不同的功能模块分配到独立的进程中,优化了浏览器的资源管理和任务调度。\n\n主进程浏览器主进程Browser Process负责管理 Firefox 的 UI包括标签页、窗口、工具栏和菜单。同时它也负责处理网络请求、文件下载和各个进程之间的协调工作。主进程起到了控制中心的作用确保浏览器的核心功能顺畅运行。\n内容进程每个标签页在一个独立的内容进程中渲染和执行页面内容避免了页面之间的相互干扰。每个内容进程负责解析 HTML、CSS 和 JavaScript执行页面脚本并进行 DOM 操作。通过这种设计,内容进程的崩溃不会影响浏览器的主进程或其他标签页的运行,极大提升了浏览器的稳定性。\nGPU 进程GPU 进程Graphics Processing Unit Process是专门用于处理与图形相关的任务如页面渲染、动画和视频播放等。通过将这些资源密集型任务交给 GPU 处理Firefox 能够更高效地渲染复杂的网页内容,同时减少对 CPU 的依赖,提升整体性能。\n\n此外Firefox 的架构还包括一些辅助进程,例如:\n\n插件进程负责运行传统的浏览器插件如 Flash这些插件与页面内容隔离避免其崩溃影响浏览器稳定性。\n扩展进程负责执行 Firefox 扩展程序,使其与页面内容独立运行,增强浏览器的安全性和稳定性。\n\n多进程架构的优缺点\n优点\n\n稳定性提升多进程架构显著提升了 Firefox 的稳定性。每个标签页的内容进程独立运行,这意味着即使一个页面崩溃,其他标签页和浏览器本身仍能正常工作。主进程仅负责用户界面的管理和进程之间的通信,从而减少了浏览器整体崩溃的可能性。\n安全性增强多进程架构为安全性提供了更高的保障。内容进程运行在一个受限的环境沙盒不能直接访问用户的系统资源。这种隔离有效防止了恶意网站或脚本通过浏览器对用户的系统进行攻击。此外进程间的隔离机制进一步减少了跨站脚本攻击XSS和跨站请求伪造CSRF等网络攻击的风险。\n并行处理通过将渲染和脚本执行任务分配到多个进程中Firefox 能够更好地利用现代多核 CPU 的优势。各个进程可以并行执行,提升了整体的浏览性能和响应速度,特别是在多任务处理和高负载情况下。\n资源分配优化多进程模型使 Firefox 能够更细粒度地控制资源分配。每个进程独立管理内存和 CPU 资源,防止单个任务占用过多资源。这对于复杂的 Web 应用和动态页面特别重要,避免了单个页面造成浏览器性能下降的情况。\n\n缺点\n\n内存占用较高多进程架构的一个主要缺点是内存占用较高。每个独立进程都会占用一定的系统资源尤其是在同时打开多个标签页时每个内容进程独立运行导致内存需求增大。对于低内存设备或需要长时间打开大量标签页的用户这可能会影响系统的性能。\n启动速度影响多进程架构可能在某些情况下影响浏览器的启动速度特别是在需要为每个进程分配资源并初始化时可能会增加启动延迟。不过随着硬件性能的提升和 Firefox 的持续优化,这一问题已逐渐得到缓解。\n\nFirefox 的渲染机制\n从输入 URL 到页面渲染的详细过程\n当用户在浏览器中输入 URL 并按下回车键时浏览器开始从请求页面到呈现页面内容的整个渲染过程。Firefox 使用其独特的Gecko 渲染引擎来解析和渲染页面,具体过程如下:\n请求阶段\n\nDNS 解析与 HTTP 请求:\n\n首先Firefox 会通过DNS 解析将用户输入的域名(如 example.com转换为对应的 IP 地址。获取 IP 地址后浏览器通过TCP 连接与服务器建立通信。如果是 HTTPS 请求还会进行TLS 握手来确保通信的加密安全。\n随后浏览器向服务器发起HTTP/HTTPS 请求,请求获取页面的资源。这些资源包括 HTML 文档、CSS 文件、JavaScript 脚本、图片等。\n\n\n\n渲染流程\n在获取页面资源后Firefox 开始进入渲染阶段,将资源转化为用户可见的页面内容。\n\nHTML 解析与 DOM 树生成:浏览器首先解析 HTML 文档并构建DOM 树Document Object Model。DOM 树是页面内容的内部表示结构,每个 HTML 标签对应 DOM 树中的一个节点。这一步骤为页面的逻辑和结构提供基础。\nCSS 解析与 CSSOM 生成:同时,浏览器解析外部的 CSS 样式文件以及内联样式生成CSSOM 树CSS Object Model。CSSOM 树描述了页面中每个 DOM 元素的样式属性。DOM 树和 CSSOM 树结合,决定页面元素如何呈现。\n布局与绘制通过结合 DOM 树和 CSSOM 树,浏览器生成渲染树,表示页面中需要显示的可见元素。接着进入**布局Layout阶段浏览器计算每个元素的大小、位置确定它们在页面中的精确布局。完成布局后浏览器进入绘制Painting**阶段,将渲染树的内容绘制到屏幕上。这包括绘制元素的文本、颜色、边框、背景图片等视觉效果。\n合成与图层管理为了提升复杂页面的渲染效率Firefox 将页面内容分割成多个图层通过GPU 进程进行图层合成和渲染。页面中的动画、视频、图形处理都会通过GPU 加速,以提高渲染速度和流畅度。最后,浏览器将这些图层组合在一起,呈现在用户屏幕上。\n\nGecko 渲染引擎\nGecko 概述\nGecko是 Mozilla 专为 Firefox 开发的渲染引擎,用于解析和渲染 HTML、CSS、JavaScript 以及其他 Web 内容。作为一个完全支持现代 Web 标准的引擎Gecko 支持最新的 HTML5、CSS3、JavaScriptES6+)等技术,并且经过了多年的迭代优化。\nGecko 负责处理 Web 内容的呈现,从 HTML 解析、DOM 树构建到最终的页面绘制。它与 Firefox 的 JavaScript 引擎SpiderMonkey协同工作确保动态内容能够快速渲染。\nServo 项目的引入\nServo是由 Mozilla 开发的基于 Rust 语言的浏览器引擎旨在利用现代多核处理器的优势来并行处理页面渲染任务。Servo 具备较高的并发处理能力和内存安全性,能够避免许多传统引擎中的内存管理问题。\n在Quantum 项目中Firefox 逐步将Servo的技术引入到Gecko中。通过这种混合架构Firefox 的渲染速度大幅提升特别是在多核处理器上Servo 的并发处理特性让 Firefox 在渲染复杂页面时更加高效和流畅。\nQuantum 项目引入了 Servo 的部分技术,比如图层管理和并行化 CSS 处理,极大地改善了渲染性能和内存管理,使得 Firefox 在与 Chrome 等竞争对手的比较中不再处于劣势。\nSpiderMonkey JavaScript 引擎\nSpiderMonkey 概述\nSpiderMonkey是 Firefox 的 JavaScript 引擎,专门用于解析、编译和执行 JavaScript 代码。它支持现代 JavaScript 的所有功能,包括 ES6 及以后的标准。SpiderMonkey 在性能优化方面做了大量工作,以确保能够高效处理复杂的 Web 应用。\n\n即时编译JITJust-in-TimeSpiderMonkey 使用了即时编译技术,将 JavaScript 代码在运行时编译为机器码,这样可以显著提升执行速度,尤其是在处理复杂的动态脚本时。\nSpiderMonkey 通过优化代码执行和内存管理,确保页面脚本的快速执行。\n\n性能优化\nSpiderMonkey 在性能优化上进行了许多改进尤其是垃圾回收Garbage Collection机制。\n\n增量垃圾回收传统的垃圾回收策略会在回收时暂停应用的执行导致用户在运行时感受到明显的卡顿。为了解决这一问题SpiderMonkey 引入了增量垃圾回收机制,通过分阶段、逐步清理内存中的无效对象,减少垃圾回收过程对页面性能的影响。\n内存管理优化SpiderMonkey 通过精细的内存管理策略,优化了对对象的创建和销毁,提高了浏览器的整体性能和响应能力。尤其是在处理大规模 JavaScript 对象时,这种优化能够显著减少内存泄漏的风险,并保持页面的流畅运行。\n\nFirefox 的性能优化\n优化页面和网络性能是提升 Firefox 浏览器中 Web 应用响应速度和用户体验的关键步骤。通过合理的资源管理、延迟加载技术以及网络请求优化开发者可以大幅减少加载时间、提升页面交互流畅度。此外使用Firefox DevTools进行性能分析可以帮助开发者识别和解决性能瓶颈。\n页面性能优化\nLazy Loading 与资源延迟加载\nLazy Loading懒加载是一种优化页面加载性能的技术主要针对图片、视频等非关键资源。懒加载技术使得资源只在用户滚动到页面相应部分时才加载而不是在页面初次加载时就全部下载。这种方式有效减少了页面的初次渲染时间加速了页面的可用性。\n\n应用场景图片、视频、iframe 等资源。\n实现方式在 HTML 中使用 loading="lazy" 属性,或通过 JavaScript 动态加载资源。\n\n<img src="image.jpg" loading="lazy" alt="Lazy loaded image">\n通过这种延迟加载用户在没有浏览到相应内容时不会浪费带宽下载资源从而提高了页面的响应速度。\n减少回流与重绘\n\n\n回流Reflow回流发生在页面的布局发生变化时浏览器需要重新计算元素的大小、位置并重新绘制页面。这是一个性能开销较大的过程因此需要尽量减少不必要的回流。\n优化策略\n\n避免逐步操作 DOM尽量批量更新。可以使用 DocumentFragment 或批量操作 CSS 属性来减少 DOM 操作的次数。\n避免频繁读取导致回流的属性如 offsetHeight、scrollTop 等),应将它们的读取和写入操作分开。\n\n\n\n重绘Repaint重绘发生在元素的视觉样式发生变化如颜色、背景等但不影响布局时。虽然重绘的开销小于回流但频繁的重绘仍然会影响性能。\n优化策略\n\n将影响页面显示的操作尽量集中在一次操作中完成避免频繁更新样式。\n使用 transform 和 opacity 属性进行动画和视觉效果处理,因为这些属性不会触发回流或重绘。\n\n\n\n网络性能优化\nHTTP/2 与 HTTP/3 支持\nHTTP/2和HTTP/3是现代的网络协议它们通过多路复用、头部压缩等技术显著提高了网络性能。Firefox 支持这两种协议,开发者可以利用它们减少请求延迟、提高资源传输效率。\n\n多路复用HTTP/2 允许在单一的 TCP 连接上同时传输多个请求和响应,减少了建立多次连接的开销。\n头部压缩HTTP/2 通过对 HTTP 头部进行压缩,减少了数据传输量,提高了响应速度。\nHTTP/3基于 UDP 的 HTTP/3 协议通过QUIC协议进一步减少了连接建立的延迟并提高了在网络条件不佳时的传输稳定性。\n\n缓存优化\n有效利用浏览器的缓存机制可以显著减少不必要的网络请求提升页面加载速度。通过合理配置 Cache-Control 和 ETag 头部信息,开发者可以确保资源在合适的时间内被缓存,并避免重复加载。\n\nCache-Control指定资源的缓存策略如 max-age 来定义缓存的有效期。\n\n Cache-Control: max-age=3600, public\n\nETag用于标识资源的版本当资源未发生变化时服务器可以返回 304 状态码,指示浏览器使用本地缓存。\n\n ETag: "abc123"\n通过这些缓存优化浏览器能够减少向服务器请求的次数加快页面加载速度尤其是在用户频繁访问相同资源时。\nCDN 与预加载\n\n\nCDN内容分发网络使用 CDN 将静态资源分发到多个地理位置的服务器上,确保用户能够从离自己最近的服务器获取资源,减少了传输延迟。\n优化策略\n\n将静态资源如图片、CSS、JavaScript 文件)托管到 CDN。\n确保 CDN 能够根据用户的地理位置选择最优的资源节点进行分发。\n\n\n\n预加载技术通过预加载关键资源可以确保浏览器在用户需要时已经提前下载了这些资源从而减少等待时间。\n\n\n <link rel="preload" href="/style.css" as="style">\n预加载可以显著加快关键资源如 CSS 文件、字体、重要的 JavaScript 库)的加载速度,优化用户的首次访问体验。\nFirefox 的安全机制\nFirefox 通过多层次的安全机制来保障用户的隐私和系统安全防止恶意网站或代码对用户造成危害。这些安全机制包括同源策略SOP、沙盒隔离机制和内容安全策略CSP共同为用户提供全面的浏览器安全保障。\n同源策略SOP, Same-Origin Policy\n同源策略\n同源策略Same-Origin Policy, SOP是 Web 浏览器最基本的安全机制之一。它限制了来自不同来源的网页内容之间的交互,以防止恶意网站访问或篡改用户的敏感数据。同源策略通过控制文档、脚本和资源的交互权限,确保用户数据的隐私和安全。\n\n\n同源的定义同源指的是两个 URL 具有相同的协议(如 HTTP/HTTPS、域名和端口。如果这些信息中有任何一个不同则被认为是不同源。\n例如example.com:443 与 example.com、sub.example.com 都被视为不同源,这意味着它们之间不能直接共享数据。\n\n\n安全性作用同源策略通过限制不同来源的网站之间的脚本交互防止恶意网站读取用户会话、访问其他页面的 Cookie 或通过脚本窃取数据。它是防御跨站脚本XSS和跨站请求伪造CSRF等攻击的重要安全措施。\n\n\n1.2 CORS跨源资源共享\n尽管同源策略限制了不同来源的交互但某些情况下合法的跨域请求仍然是必要的。**CORS跨源资源共享**机制允许服务器明确控制哪些外部来源可以访问其资源。\n\nCORS 的工作机制:当浏览器发出跨域请求时,服务器可以在响应头中设置 Access-Control-Allow-Origin指定哪些来源可以访问资源。如果跨域请求被允许浏览器才会继续处理请求。\n\n Access-Control-Allow-Origin: example.com\n对于复杂请求浏览器会先发起预检请求OPTIONS 方法),询问服务器是否允许跨域请求。服务器通过返回适当的 CORS 响应头部来决定是否允许跨源访问。\n通过 CORS服务器能够精细控制跨域请求的权限确保合法请求被接受而非法请求则被拒绝从而进一步增强了跨域资源共享的安全性。\n沙盒隔离机制\n内容进程的沙盒化\n沙盒化是一种有效的安全技术通过将运行的程序与系统核心资源隔离开来限制其对操作系统的访问权限。Firefox 使用多进程架构,每个网页的内容渲染都在内容进程中进行,而内容进程被放置在一个受限的沙盒环境中运行。\n\n沙盒隔离的作用 内容进程只能访问特定的、受限的资源,它不能直接读取或写入用户的文件系统、摄像头、麦克风等关键系统资源。即便网页中包含恶意代码,由于沙盒的隔离作用,攻击者也难以突破浏览器的限制,损害用户的系统安全。\n减少恶意威胁 沙盒化机制有效阻止了通过浏览器攻击系统核心的企图,使得恶意网站、脚本无法获取到系统敏感资源。它还能够减少浏览器插件或第三方扩展中的潜在安全漏洞对系统的威胁。\n\n通过内容进程的沙盒化Firefox 在保护用户免受恶意网站攻击方面大大增强了安全性。\n内容安全策略CSP, Content Security Policy\n内容安全策略Content Security Policy, CSP是用于防止跨站脚本XSS和数据注入攻击的浏览器安全机制。CSP 允许 Web 开发者通过设置 HTTP 头部,明确指定哪些外部资源可以加载,哪些资源应被禁止。\n防止 XSS 攻击\n**跨站脚本攻击XSS**是最常见的网络攻击之一攻击者通过在网页中插入恶意脚本窃取用户数据或执行不受信任的操作。CSP 通过限制哪些外部脚本可以加载,帮助开发者防止这些攻击。\n\n\nCSP 的工作机制:开发者可以在响应头中指定允许加载的资源源,例如脚本、样式、图像等。只有符合 CSP 策略的资源才会被浏览器加载。\n示例 CSP 头部:\n\n\n Content-Security-Policy: script-src 'self' trusted.cdn.com\n在上面的示例中只有来自当前站点self和受信任的 CDNtrusted.cdn.com的脚本才能被加载其他来源的脚本将被阻止执行。\n\n防止恶意注入通过严格控制资源加载的来源CSP 可以有效阻止通过注入 HTML、JavaScript 或第三方插件带来的潜在安全威胁,尤其是那些试图窃取用户会话或操控页面行为的攻击。\n\nCSP 不仅是防御 XSS 攻击的关键工具,还能用于加强其他安全防护措施,防止未经授权的内容加载到网页中。\nFirefox 扩展开发\nFirefox 通过WebExtensions API提供了一个强大且灵活的扩展开发平台允许开发者创建**与 Chrome 等其他浏览器兼容的跨浏览器扩展。**开发者可以通过 Firefox 的工具和平台进行调试和发布扩展,确保其符合安全和性能标准。\nWebExtensions API\nWebExtensions API是 Firefox 的标准扩展开发框架,旨在简化扩展开发,并与其他主流浏览器(如 Chrome、Edge 和 Opera的扩展生态系统兼容。WebExtensions API 使得开发者能够编写一个扩展,在多个浏览器上运行,大大降低了开发和维护的复杂性。\n扩展兼容性\nFirefox 支持基于WebExtensions API的扩展与 Chrome 等浏览器的扩展系统高度兼容。开发者可以使用几乎相同的代码库在不同浏览器上发布扩展,这使得跨浏览器扩展的开发变得更加方便和高效。\nWebExtensions API 通过统一的接口,提供访问浏览器的核心功能(如标签管理、网络请求拦截、书签操作等)。这意味着开发者可以为多个浏览器创建同一个扩展,而无需为每个浏览器单独开发版本。\nmanifest.json 文件\n每个 Firefox 扩展都有一个manifest.json文件它是扩展的核心配置文件定义了扩展的权限、图标、背景脚本、内容脚本和其他关键信息。它的结构与 Chrome 扩展的 manifest 文件非常相似,使得开发者能够轻松适配其他浏览器。\n基本结构\n{\n "manifest_version": 2,\n "name": "My Firefox Extension",\n "version": "1.0",\n "description": "An example of a Firefox extension",\n "icons": {\n "48": "icons/icon-48.png",\n "96": "icons/icon-96.png"\n },\n "permissions": [\n "storage",\n "activeTab",\n "tabs"\n ],\n "background": {\n "scripts": ["background.js"]\n },\n "content_scripts": [\n {\n "matches": ["*://*.example.com/*"],\n "js": ["content.js"]\n }\n ]\n}\n关键字段\n\nname扩展的名称。\nversion扩展的版本号。\npermissions定义扩展所需的权限如访问标签页、存储数据、修改页面内容等。\nbackground指定运行在后台的脚本用于处理事件和状态。\ncontent_scripts注入到特定页面的脚本用于操作页面 DOM 或修改其行为。\n\n通过 manifest 文件,开发者可以定义扩展的行为和所需的浏览器权限,以确保功能的实现和资源的适当管理。\n开发与调试\nFirefox DevTools\nFirefox 提供了强大的DevTools帮助开发者调试扩展的运行状态。DevTools 可以调试扩展的内容脚本和后台脚本,分析其执行流程,查看网络请求,甚至调试扩展与浏览器之间的消息传递。\n\n\n调试内容脚本开发者可以通过 DevTools 的“Inspector”选项卡查看页面上注入的内容脚本是否正确执行以及是否对 DOM 进行了预期的修改。\n\n\n调试后台脚本通过 DevTools 中的“Debugger”工具开发者可以调试后台脚本设置断点、查看变量、跟踪事件响应等。后台脚本是扩展中的长期运行脚本常用于管理事件监听和状态维护。\n示例调试后台脚本\nchrome.runtime.onInstalled.addListener(function() {\n console.log("Extension installed");\n});\n \nchrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {\n if (changeInfo.status === "complete") {\n console.log("Tab updated:", tab.url);\n }\n});\n\n\n通过 DevTools开发者可以轻松排查扩展中的问题确保它们在不同浏览器上下文中正确运行。\n扩展开发流程\n\n安装扩展在 Firefox 的扩展管理界面,开发者可以将扩展以开发者模式加载到浏览器中,无需发布到 AMO。这可以方便开发和测试过程。\n调试与日志开发者可以在扩展中使用 console.log 进行调试,所有的日志输出都可以通过 DevTools 的“Console”面板查看。\n\n发布扩展\n发布到 AMO 平台\n**addons.mozilla.orgAMO**是 Mozilla 官方的扩展发布平台。开发者在完成扩展开发后,可以通过 AMO 将扩展发布给全球用户。与 Chrome Web Store 相比Firefox 对扩展的审查要求更为严格,重点关注隐私和安全性。\n\n审查流程\n\n扩展提交到 AMO 后,会经过自动和手动审查。审查主要检测扩展的代码是否包含恶意行为,是否有不必要的权限请求,以及是否符合 Mozilla 的隐私政策。\n权限审核Firefox 对扩展请求的权限有着严格的要求,开发者必须在 manifest 文件中明确声明所需权限,并确保这些权限的使用符合隐私保护要求。\n\n\n\n3.2 扩展的打包和上传\n\n打包扩展开发者需要将扩展打包为 .zip 或 .xpi 文件格式。在开发完成后,可以通过扩展管理页面或命令行工具进行打包。\n上传扩展进入 AMO 开发者页面后,开发者可以上传打包好的扩展。上传后,扩展将进入审查队列,审查通过后即可公开发布。\n开发者控制面板AMO 为开发者提供了详细的扩展管理控制面板,开发者可以管理扩展的版本更新、用户反馈和下载统计。\n\nFirefox 的前沿技术\nFirefox 始终致力于推动 Web 技术的前沿发展,并为开发者提供功能强大的平台,以构建高效、现代化的 Web 应用。**渐进式 Web 应用PWA和WebAssemblyWASM**是两项重要的前沿技术Firefox 通过持续优化对这些技术的支持,推动 Web 应用的性能、可用性和开发效率的提升。\n渐进式 Web 应用PWA, Progressive Web App\n渐进式 Web 应用PWA旨在提供类原生应用的 Web 体验,通过增加离线支持、推送通知和跨设备兼容等功能,使 Web 应用更加灵活、强大。Firefox 对 PWA 的支持为用户带来了高效、流畅的使用体验,增强了 Web 应用的功能性。\nService Workers 与缓存\nService Workers 是 PWA 的核心技术之一运行在浏览器后台独立于主页面提供了强大的功能如离线支持、缓存管理和通知推送。Firefox 对 Service Workers 的支持使得 PWA 能够在网络不稳定甚至无网络的情况下正常运行。\n\n\n离线支持通过 Service WorkersPWA 可以缓存关键资源,并在用户离线时使用这些缓存资源来渲染页面。缓存的资源可以包括 HTML、CSS、JavaScript 和图片等,确保用户能够在没有网络连接的情况下使用应用。\n示例Service Worker 的缓存机制:\nself.addEventListener('install', (event) => {\n event.waitUntil(\n caches.open('my-cache').then((cache) => {\n return cache.addAll([\n '/',\n '/index.html',\n '/styles.css',\n '/script.js'\n ]);\n })\n );\n});\n \nself.addEventListener('fetch', (event) => {\n event.respondWith(\n caches.match(event.request).then((response) => {\n return response || fetch(event.request);\n })\n );\n});\n\n\n通知推送Service Workers 还能接收推送通知,即使 PWA 未被打开时,用户也能收到消息。这使得 PWA 具备了与原生应用类似的互动功能,增强了用户参与度。\n\n\nManifest 文件与图标管理\nManifest 文件 是 PWA 的配置文件,用于定义应用的名称、图标、启动 URL、显示模式如全屏或固定窗口、主题颜色等。通过 Manifest 文件PWA 能够在用户设备上创建一个快捷方式,提供类似原生应用的启动体验。\n\n\n图标与启动配置Manifest 文件定义了 PWA 的图标、启动画面以及显示模式。通过这些配置PWA 不仅可以在桌面或移动设备上创建图标,还能够控制应用在不同设备上的呈现方式,如全屏模式运行或以固定窗口形式显示。\n示例manifest.json 文件:\n{\n "name": "My Progressive Web App",\n "short_name": "MyPWA",\n "start_url": "/index.html",\n "icons": [\n {\n "src": "/icons/icon-192.png",\n "sizes": "192x192",\n "type": "image/png"\n },\n {\n "src": "/icons/icon-512.png",\n "sizes": "512x512",\n "type": "image/png"\n }\n ],\n "background_color": "#ffffff",\n "theme_color": "#2196F3",\n "display": "standalone"\n}\n\n\nFirefox 对 PWA 的支持Firefox 允许用户将 PWA 应用安装到设备桌面,并通过 Manifest 文件管理图标和启动行为提供更接近原生应用的用户体验。此外Firefox 的**开发者工具DevTools**中还包含 PWA 调试功能,开发者可以检查缓存、查看 Service Worker 的状态等。\n\n\nWebAssemblyWASM\nWebAssemblyWASM 是一种二进制指令格式允许开发者在浏览器中运行接近原生性能的代码。Firefox 对 WebAssembly 的支持,极大提升了浏览器中运行复杂任务的效率,如 3D 渲染、加密运算和高性能游戏。\nWebAssembly 在 Firefox 中的支持\nWebAssembly 提供了运行高效代码的能力,使得浏览器不仅能够处理传统的 Web 任务,还能承担一些计算密集型的操作,如图像处理、机器学习模型训练、游戏渲染等。\n\n高性能计算WASM 通过将高级语言(如 C、C++、Rust编译成高效的字节码并在浏览器中运行从而实现接近原生性能的执行速度。它专为性能而设计能够在浏览器中快速运行复杂算法、3D 图形处理和实时视频编辑等任务。\n跨平台支持WASM 是一种跨浏览器、跨平台的技术Firefox 和其他主流浏览器(如 Chrome、Edge都支持 WebAssembly这使得开发者能够编写一次代码在多个平台上高效运行。\n\nJavaScript 与 WASM 的互操作\n虽然 WebAssembly 具有很高的性能,但它与 JavaScript 并不是竞争关系,而是互为补充。开发者可以在 JavaScript 代码中调用 WebAssembly 模块,并通过 API 在两者之间进行数据交换和函数调用。JavaScript 负责页面交互、UI 控制等任务,而 WebAssembly 处理高性能计算任务。\n\n\n调用 WASM 模块:开发者可以通过 JavaScript 加载 WASM 模块,并调用其中的函数。通过这种互操作机制,开发者可以结合两者的优势,构建高效的 Web 应用。\n示例JavaScript 调用 WASM 模块:\nfetch('module.wasm').then(response =>\n response.arrayBuffer()\n).then(bytes =>\n WebAssembly.instantiate(bytes)\n).then(results => {\n console.log(results.instance.exports.add(5, 10)); // 假设WASM模块中有add函数\n});\n\n\n数据交换与性能优化JavaScript 和 WebAssembly 之间的通信性能已经被大幅优化特别是在处理大数据集和复杂的计算时WASM 可以显著提升速度,而 JavaScript 则提供了灵活的控制和接口。\n\n"},"Technology/WebDevelopment/1.Browser/4.DevTools":{"title":"DevTools","links":[],"tags":["标签"],"content":"DevTools\n\nChrome DevTools 是 Google Chrome 浏览器内置的一套强大且灵活的前端开发和调试工具集。 它为前端开发人员提供了从页面结构分析到性能优化的全方位支持,能够大幅提升调试效率与开发体验。通过 DevTools开发者可以深入页面渲染过程实时修改资源查看并优化性能瓶颈确保应用程序的高效运行。\n\nChrome DevTools 官方文档\n\nDevTools 核心功能\nChrome DevTools 提供了一系列关键功能,涵盖了从调试到优化的多种开发需求。以下是其主要功能模块:\n调试和诊断\n\nJavaScript 调试: 提供断点调试功能,允许开发者在代码执行时设置断点,逐步执行代码,查看变量的实时值,从而定位和修复问题。\nDOM 事件追踪: 支持追踪和监控 DOM 元素的事件绑定情况,帮助开发者理解事件触发顺序及其背后的逻辑。\n网络请求分析 通过网络面板Network Tab开发者可以查看所有页面加载的 HTTP 请求,包括资源的加载时间、状态码、请求头和响应头等,帮助分析网络层面的性能瓶颈。\n\n性能分析\n\n页面加载时间分析 通过 Timeline 和 Performance 面板,开发者可以检测页面从加载到完成渲染的各个阶段的性能,帮助定位造成加载缓慢的原因。\n帧率监控 帧率FPS是衡量页面交互性能的重要指标DevTools 能够展示页面在用户交互过程中每一帧的渲染时间,便于分析动画和过渡效果的流畅性。\n内存占用分析 Memory 面板允许开发者分析页面的内存使用情况检测内存泄漏并优化内存管理特别是对单页应用SPA而言这一功能尤为重要。\n\n实时编辑\n\nDOM 和 CSS 的实时修改: Elements 面板允许开发者直接在浏览器中编辑 HTML 和 CSS实时查看修改效果支持快速调试页面样式和布局。\nJavaScript 实时执行: 在 Console 面板中,开发者可以直接输入 JavaScript 代码并立即执行,这种交互式的代码运行方式便于快速测试脚本功能。\n样式计算与渲染分析 DevTools 提供了渲染树的可视化工具,展示元素的样式计算和渲染情况,有助于理解页面样式的层叠与继承机制。\n\nDevTools 的跨平台支持\n作为 Chrome 浏览器的内置工具DevTools 在多个操作系统上具有一致的功能表现。 无论是在 Windows、macOS 还是 Linux 系统上开发者均可通过相同的界面与功能集进行调试。Chrome 的跨平台支持确保了开发者在不同开发环境中的无缝切换,从而提高开发效率。\nDevTools 的开放性与扩展性\n除了内置的功能外DevTools 还支持扩展和自定义功能。开发者可以利用 Chrome DevTools Protocol 与自身的调试流程进行集成并创建自定义工具以满足特定的调试需求。同时随着前端技术的演进DevTools 也不断更新,增加了如 Lighthouse 这样的工具模块,用于自动化页面性能和可访问性分析。\nDevTools 的核心面板\nElements 面板\n\nDOM 树与实时编辑\n\nDOM 树的可视化展示Elements 面板通过树状结构显示页面的 DOM文档对象模型帮助开发者了解页面的层次结构及其元素的相互关系。\n实时编辑功能开发者可以直接在 DOM 树中编辑 HTML 标签、属性和内容,修改的结果会立即反映在浏览器中。这使得前端开发和调试过程更高效,便于快速迭代和视觉验证。\nDOM 节点操作:除了编辑现有的 DOM 节点,开发者还可以通过上下文菜单添加、删除或重新排列元素,帮助更深入地理解页面结构。\n\nCSS 样式调试\n\n样式面板的动态编辑Elements 面板中的样式子面板允许开发者实时查看和编辑选中元素的 CSS 样式。通过修改现有规则、添加新规则或删除冗余样式,开发者可以快速调试布局和视觉问题。\n伪类状态模拟样式面板支持模拟特定的 CSS 伪类状态(如 :hover、:focus、:active 等),便于调试元素在不同交互状态下的样式。这在设计复杂交互时,尤其有用。\nCSS 样式层叠与优先级:样式面板还展示了所有适用的 CSS 规则,并按照优先级排序,开发者可以查看哪个规则覆盖了其他规则,并深入了解 CSS 样式的层叠和继承机制。\n\n布局与盒模型\n\n盒模型的可视化分析Elements 面板展示了所选元素的盒模型明确显示其宽度、高度、内边距padding、边框border、外边距margin等信息。开发者可以点击并修改每个部分的数值直观地调整布局。\nCSS Grid 和 Flexbox 调试工具:对使用 CSS Grid 和 Flexbox 布局的页面DevTools 提供了专门的可视化工具。开发者可以通过这些工具清楚地看到网格或弹性布局的结构和每个子元素的位置,方便调试和优化复杂布局。\n\nConsole 面板\n\n调试与输出\n\n实时日志输出Console 面板是调试 JavaScript 代码的主要工具之一,开发者可以使用 console.log()、console.warn()、console.error() 等方法输出不同类型的日志,以便查看变量值、函数执行结果或错误信息。\n交互式命令行Console 面板也充当了一个 JavaScript REPLRead-Eval-Print Loop允许开发者直接在其中输入并执行 JavaScript 代码,实时查看结果。这使得在无需刷新页面的情况下,快速验证代码片段或逻辑成为可能。\n自动补全与历史命令Console 提供智能代码补全和历史命令功能,帮助开发者更快地输入代码,并快速调用之前执行的命令,提高工作效率。\n\n错误和警告\n\n错误检测当页面中出现 JavaScript 错误、网络请求失败或其他问题时Console 面板会自动显示详细的错误信息。包括错误的具体行号、调用栈等,帮助开发者迅速定位并修复问题。\n日志过滤与级别分类开发者可以根据不同的日志级别如信息、警告、错误筛选输出内容以便在调试时聚焦于关键问题。通过日志过滤功能能够更好地管理大量输出信息。\n\nSources 面板\n\n文件调试\n\n文件浏览与加载Sources 面板显示页面中加载的所有 JavaScript 文件及其依赖项。开发者可以逐个浏览这些文件,并在需要的地方进行调试。\n代码断点设置通过在代码行上点击设置断点开发者可以在代码执行时暂停检查变量状态、调用栈和当前上下文从而更加精确地定位和修复问题。\n\n断点调试\n\n多种断点类型\n\n行断点在特定的行设置断点代码执行到此行时将暂停。\n条件断点开发者可以设置条件表达式代码仅在条件满足时才会暂停执行。\nXHR 断点:可以在发起特定的网络请求时自动暂停代码执行,方便调试 AJAX 请求等异步操作。\n\n\n调用栈分析当代码暂停时开发者可以查看当前的调用栈了解函数调用顺序及其参数和返回值帮助理解代码的执行流。\n\n实时编辑和本地覆盖\n\nJavaScript 实时编辑:开发者可以在 Sources 面板中直接修改 JavaScript 文件,并立即预览这些修改在页面上的效果。这为临时调试提供了便捷方式,无需修改源码后再重新部署。\nLocal Overrides通过 Local Overrides 功能,开发者可以将更改保存到本地,使页面在每次加载时都应用这些更改,从而模拟持久化修改,特别适用于调试第三方库或 CDN 加载的脚本。\n\nJavaScript 执行顺序与异步堆栈\n\n异步调试工具Sources 面板提供了异步任务的堆栈跟踪功能(如 setTimeout、Promise、async/await允许开发者查看异步操作的执行顺序及其影响。这个功能使得调试异步代码变得更加直观并帮助开发者理解 JavaScript 的事件循环和异步执行机制。\n\nDevTools 的性能优化功能\nPerformance 面板\n\nPerformance 面板提供了对页面加载、渲染和执行性能的全面分析。 开发者可以通过点击录制按钮开始捕获页面的性能数据,并生成一份详细的时间轴报告。这些数据展示了从页面开始加载到用户可交互之间的整个过程,帮助开发者全面了解性能瓶颈所在。\n在页面性能问题的定位过程中Performance 面板可以捕获特定的时间段,如页面的首次加载、用户滚动、元素交互等,开发者可以选择性地关注和分析这些关键时刻的表现。\n关键性能指标\n\n渲染路径分析Performance 面板通过详细的瀑布图展示页面的关键渲染路径,开发者可以识别导致性能瓶颈的因素,如长时间的 JavaScript 执行、阻塞式渲染、过多的重排和重绘等操作。通过这些信息,可以优化脚本加载顺序、减少不必要的 DOM 操作。\nFPS 分析帧率FPS是衡量动画和交互是否流畅的重要指标。Performance 面板实时监控页面的帧率,通过直观的图表展示页面在不同操作(如滚动、动画播放)下的帧率变化。帧率过低可能导致卡顿,特别是在复杂的视觉效果或页面滚动时,开发者可以通过优化动画性能或减少不必要的绘制操作提升用户体验。\n\n瀑布图与事件分析\n\n瀑布图的可视化分析Performance 面板生成的瀑布图通过展示页面加载、脚本执行、样式计算、渲染和绘制的每一步,帮助开发者掌握页面每个事件的执行顺序与耗时。这些信息对于识别性能瓶颈(如阻塞的 JavaScript、慢速网络请求等尤为关键。\nLayout Shift 与 CLS 分析性能优化过程中CLS累计布局偏移 是一个重要的用户体验指标。Performance 面板可以展示页面布局的变化和偏移,帮助开发者识别不必要的页面元素重排和重绘,减少影响用户体验的布局移动,从而优化关键性能指标如 CLS。\n\nLighthouse 面板\nLighthouse 是一个集成在 Chrome DevTools 中的开源性能分析工具,旨在自动化页面性能评估。它不仅能分析页面的性能,还覆盖了 SEO、可访问性、最佳实践和渐进式 Web 应用PWA支持等多个维度。通过 Lighthouse开发者可以生成一份涵盖全面优化建议的评分报告帮助提升 Web 应用的质量和用户体验。\nLighthouse 分析报告\n\n自动化评分报告生成Lighthouse 通过自动化测试生成一份页面性能报告,评分范围从 0 到 100涵盖页面性能的多个方面。每个维度都附带详细的改进建议例如减少未使用的 JavaScript、优化图片加载、提升初始渲染速度等。\n核心 Web 指标Core Web Vitals报告特别关注核心 Web 指标,这些是评估用户体验的关键性能指标,包括:\n\nLCP最大内容绘制衡量页面主内容的加载速度理想情况下应在 2.5 秒内完成。\nFID首次输入延迟反映页面的响应速度较长的延迟会导致用户输入操作的迟滞。\nCLS累计布局偏移衡量页面中不可预见的视觉布局移动得分越低越好以确保视觉稳定性。\n\n\n\nSEO 与可访问性\n\nSEO 评估Lighthouse 的 SEO 模块分析页面是否符合搜索引擎优化SEO最佳实践例如适当使用元标签、优化结构化数据、提升可抓取性等。优化页面的 SEO 有助于提高其在搜索引擎中的排名,从而吸引更多的访问者。\n可访问性分析Lighthouse 还评估页面的可访问性,确保网站对残障用户的友好程度。这包括检查页面元素的对比度、表单的可标记性、语义化 HTML 的使用等。提高页面的可访问性不仅符合道德规范和法律要求,还能提升所有用户的使用体验。\n\nDevTools 的网络分析功能\nNetwork 面板\n\nNetwork 面板是调试和优化网络性能的核心工具,展示页面加载过程中所有的网络请求,包含 HTML、CSS、JavaScript、图片、字体等资源。开发者可以清晰地看到每个请求的加载顺序、状态码、文件大小、请求方法如 GET、POST和响应时间等详细信息从而帮助分析和优化资源加载过程。\n资源加载时序图\n\n时序图的可视化分析Network 面板中的时序图Waterfall Chart通过可视化的方式展示各个资源的加载时序帮助开发者识别性能瓶颈。时序图按时间顺序排列资源请求明确区分了各个阶段如 DNS 解析、TCP 连接、请求发起与响应接收等)的时间消耗。借助这些信息,开发者可以发现阻塞渲染的资源,优化资源加载顺序,缩短关键渲染路径的时间。\n优化建议\n\n图像优化图片文件过大是常见的加载瓶颈之一开发者可以在 Network 面板中识别较大的图像资源,并通过使用更高效的图像格式(如 WebP或压缩技术来减少文件大小。\n脚本异步加载Network 面板能够帮助开发者识别阻塞渲染的 JavaScript 文件,通过引入 async 或 defer 属性,开发者可以优化脚本加载顺序,防止页面渲染被阻塞。\n\n\n\nHTTP 请求与响应\n\n请求与响应的详细信息通过 Network 面板,开发者可以查看每个 HTTP 请求的完整信息包括请求头Request Headers、响应头Response Headers、状态码如 200、404、500 等)以及响应内容(如 HTML、JSON、图片等。这有助于理解每个请求的交互过程以及网络层次上的问题。\n状态码与错误处理开发者可以轻松定位状态码为 4xx 或 5xx 的请求以此诊断客户端或服务器端的错误。针对特定的错误Network 面板还显示详细的调用信息,有助于快速定位问题的源头。\n缓存控制Network 面板可以展示每个资源的缓存命中情况,包括 Cache-Control 和 ETag 等缓存策略。通过分析这些缓存控制头信息,开发者可以判断资源是否被浏览器或 CDN 有效缓存,避免不必要的网络请求,提升页面加载速度。\n\n带宽与网络状况模拟\n\n网络条件模拟Network 面板支持模拟不同的网络环境,开发者可以通过内置的带宽模拟器(如 3G、4G、慢速网络等测试页面在各种网络条件下的表现。这有助于开发者验证页面在低带宽或高延迟环境中的响应速度从而进行相应的优化。\n离线模式测试开发者还可以启用离线模式模拟用户在没有网络连接时的页面表现特别是对渐进式 Web 应用PWA的开发和调试非常有用。\n\nApplication 面板\n\n存储与缓存\n\n本地存储管理Application 面板提供了对浏览器本地存储机制的全面访问,支持查看和管理以下几种存储类型:\n\nCookie显示页面使用的所有 Cookie开发者可以查看每个 Cookie 的详细信息(如名称、值、域名、到期时间、路径等),并直接编辑或删除它们以便调试用户会话和身份验证相关的问题。\nLocal Storage 和 Session Storage开发者可以使用 Application 面板查看和编辑 Local Storage本地存储与 Session Storage会话存储中的键值对数据。这些存储机制常用于保存轻量级的用户数据帮助页面实现状态持久化。\nIndexedDB 和 Web SQL对于更复杂的数据存储需求开发者可以通过 Application 面板查看 IndexedDB 和 Web SQL 数据库中的信息。IndexedDB 是一种结构化的存储机制,适合存储大量数据或执行离线操作。\n\n\n缓存与存储管理Application 面板允许开发者管理页面缓存包括浏览器缓存、Service Worker 缓存和离线缓存。开发者可以清除特定的缓存数据,或者检查缓存是否命中,以此调试页面的离线功能或缓存策略。\n\nService Workers 与 PWA 支持\nApplication 面板提供了对 Service Workers 的调试支持,开发者可以查看和管理页面注册的所有 Service Workers并控制其生命周期如启用、禁用或更新。Service Workers 是 PWA 实现离线功能的核心组件,通过它们可以缓存页面资源,从而支持离线访问和增强的用户体验。\n\n缓存策略优化开发者可以通过调试 Service Worker 的缓存策略确保资源在离线状态下的可用性同时避免过时的资源被长期缓存。Application 面板还允许模拟离线模式,从而验证 PWA 应用在无网络时的表现。\nPWA Manifest 调试Application 面板支持对 PWA Manifest 文件进行调试,确保页面具备符合 PWA 标准的元数据。Manifest 文件定义了 PWA 应用的名称、图标、启动 URL、主题颜色等调试过程中开发者可以检查这些属性是否正确配置以确保应用在不同平台上的表现一致。\n\nDevTools 的调试与调试增强功能\nJavaScript 调试与断点管理\n断点类型\n\n行断点最常见的断点类型允许开发者在特定的代码行暂停执行方便检查代码状态。通过在 Sources 面板中点击代码行数即可添加断点。\n条件断点适用于需要更精准调试的场景开发者可以为断点指定条件表达式只有当条件为真时才会暂停执行代码。此功能极大减少了不必要的中断提升调试效率。\nDOM 断点:开发者可以对特定 DOM 元素设置断点,在其属性或结构发生变化时自动暂停代码执行。这种类型的断点特别适合调试复杂的页面交互和动态 DOM 操作。\nXHR 断点:允许在发起或响应特定的网络请求时暂停 JavaScript 执行,便于调试 AJAX 请求、网络交互及其处理逻辑。\n断点调试设置断点后开发者可以逐步执行代码使用“步进Step Over”、“步入Step Into”和“步出Step Out”等操作控制代码的执行流程。调试过程中可以查看变量值、调用栈和上下文帮助分析和理解代码的执行逻辑。\n\nDOM 断点与事件监听\nDOM 断点\n\n监控 DOM 变化DOM 断点能够精确捕捉页面结构的变化。例如,开发者可以在某个节点上设置断点,当该节点的内容、属性或位置发生修改时,代码执行会自动暂停。这对于调试意外的 DOM 修改、追踪动态内容生成非常有用。\n追踪 DOM 操作:通过 DOM 断点,开发者可以调试那些可能由 JavaScript 动态修改的页面元素,定位哪一行代码引发了特定 DOM 节点的变化(如添加、删除、重排等)。\n\n事件监听\n\n事件流追踪DevTools 提供事件监听功能,允许开发者查看页面上发生的所有事件(如鼠标点击、键盘输入等),并以列表形式显示事件的执行顺序和关联的元素。这对于调试复杂交互或事件冲突非常有效。\n事件断点开发者可以为特定的事件类型如点击、提交等设置全局断点无论该事件在哪个元素上触发代码都会暂停。这个功能帮助开发者从更高层次追踪整个事件流从而掌握复杂的交互行为。\n\nDevTools 扩展与自定义\nDevTools 扩展与调试\n扩展 DevTools\nChrome 提供了丰富的 API允许开发者通过编写扩展Extension来增强 DevTools 的功能。开发者可以为特定的调试需求定制工具,比如开发特定框架的调试插件(如 React 或 Vue。\n借助 Chrome DevTools Protocol开发者可以构建自定义面板、工具条或其他 UI 组件,整合到 DevTools 中,满足复杂调试场景的个性化需求。自定义插件不仅可以扩展功能,还能改善调试体验,提高开发效率。\n远程调试\n\n远程调试移动设备DevTools 提供了远程调试功能,开发者可以通过 USB 或无线连接调试 Android 设备上的移动端页面。在移动端性能优化、响应式设计调试等场景中,远程调试功能非常实用,能帮助开发者在真实设备上进行调试和优化。\n跨平台调试支持不仅限于 AndroidDevTools 还支持远程调试其他平台上的 Web 应用,如在 Chrome 浏览器中远程调试不同操作系统的浏览器实例。\n\nDevTools 的前沿功能\n进阶的性能优化与分析\nWebAssembly 调试\n\n调试 WebAssembly 模块DevTools 提供对 WebAssemblyWASM的原生支持允许开发者调试 WASM 代码,查看二进制模块的执行过程。开发者可以使用断点调试 WebAssembly 与 JavaScript 的交互,确保二者的无缝配合和高效执行。\n性能分析由于 WebAssembly 通常用于计算密集型任务,通过 DevTools 调试可以检测模块的执行效率,确保其能充分发挥出高性能优势,并发现潜在的性能瓶颈。\n\nCPU 与内存分析\n\nCPU 剖析器DevTools 提供的 CPU 剖析器可以帮助开发者检测 JavaScript 代码的执行时间,分析函数调用的耗时及其频率。对于计算密集型或复杂交互型页面,剖析器能直观展示代码的性能表现,帮助开发者找到最耗费 CPU 资源的部分,进行性能优化。\n内存使用检测通过 Memory 面板,开发者可以跟踪页面的内存使用情况,监控对象的分配与释放。借助内存快照和内存泄漏检测工具,开发者能够发现和修复内存泄漏问题,从而优化应用的内存使用,提高应用稳定性和性能。\n"},"Technology/WebDevelopment/2.HTML/HTML":{"title":"HTML","links":[],"tags":["FullStack/基础"],"content":"语法和规则,将混沌的网络之地变为有序的信息之海。\nHTML\nHTML 是用来描述网页的一种语言它不是一种编程语言而是一种标记语言。它由一系列的元素或标签组成这些标签可以告诉浏览器如何呈现内容。HTML 构成了网页的骨架。\n<!DOCTYPE html>\n<html lang="zh">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>Document Title</title>\n <!-- CSS Stylesheet link -->\n <link rel="stylesheet" href="styles.css">\n</head>\n<body>\n <header>\n <!-- Navigation links, logo, etc. -->\n </header>\n <main>\n <!-- Main content goes here -->\n </main>\n <footer>\n <!-- Footer content goes here -->\n </footer>\n \n <!-- JavaScript file link -->\n <script src="script.js"></script>\n</body>\n</html>\n\n<!DOCTYPE html>: 声明 HTML5 文档。\n<html lang="zh">: HTML 的根元素,语言设为中文。\n<head>: 文档头部,包含元信息。\n<meta charset="UTF-8">: 设定 UTF-8 字符编码。\n<meta name="viewport" content="width=device-width, initial-scale=1.0">: 适应移动设备的视口设置。\n<title>Document Title</title>: 设置文档标题。\n<link rel="stylesheet" href="styles.css">: 链接外部 CSS 样式表。\n<body>: 文档主体,包含可见内容。\n<header>, <main>, <footer>: 分别为页眉、主内容、页脚的 HTML5 语义元素。\n<script src="script.js"></script>: 链接外部 JavaScript 文件。\n\n元信息\n**HTML 的元信息metadata是关于 HTML 文档的数据,它们不会显示给用户,而是提供给浏览器和搜索引擎。**元信息通常在 HTML 文档的 <head> 部分定义。\n<!DOCTYPE html>\n<html lang="zh">\n<head>\n <meta charset="UTF-8">\n <meta name="author" content="John Doe">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>网页的标题,这在浏览器的标签页中显示,并被搜索引擎用于索引页面。</title>\n <meta name="description" content="Page description. No longer than 155 characters.">\n <meta name="keywords" content="your, tags">\n <link rel="icon" href="favicon.ico" type="image/x-icon">\n <link rel="stylesheet" href="styles.css">\n <script src="script.js"></script>\n <meta http-equiv="refresh" content="30">\n <meta name="robots" content="noindex, nofollow">\n <link rel="canonical" href="example.com/"/>\n</head>\n<body>\n <!-- 主要内容在这里 -->\n</body>\n</html>\n\n<meta charset="UTF-8">: 这定义了文档的字符编码。常用的字符编码是 UTF-8因为它包含了大多数已知的字符和符号。\n<meta name="author" content="John Doe">: 这个 <meta> 标签定义了网页的作者。\n<title>: 网页的标题,这在浏览器的标签页中显示,并被搜索引擎用于索引页面。\n<meta name="viewport" content="width=device-width, initial-scale=1.0">: 这是移动端优化的元标签。它让网页的宽度等于设备的宽度,初始缩放比例为 1。\n<meta name="description" content="Page description. No longer than 155 characters.">: 这提供了页面的简洁描述,这在搜索引擎结果页 (SERP) 中显示可以提高页面的可点率CTR。\n<meta name="keywords" content="your, tags">: 这定义了网页的关键词。虽然现在搜索引擎很少使用这个元标签,但在 SEO 中还是有一些应用。\n<link rel="icon" href="favicon.ico" type="image/x-icon">: 这个 <link> 标签定义了网站的 favicon收藏夹图标。它在浏览器的标签页或地址栏中显示也可以在用户的书签中显示。\n<link rel="stylesheet" href="styles.css">: 这链接了一个外部的 CSS 文件。虽然 <link> 标签不是 <meta>,但它在 <head> 中定义,也提供了一些元信息。\n<script src="script.js"></script>: 这链接了一个外部的 JavaScript 文件。与 <link> 标签类似,<script> 标签也提供了一些元信息。\n<meta http-equiv="refresh" content="30">: 这可以让页面在特定的时间后自动刷新。在这个例子中,页面会在 30 秒后自动刷新。\n<meta name="robots" content="noindex, nofollow">: 这可以控制搜索引擎爬虫的行为。在这个例子中“noindex” 告诉爬虫不要索引这个页面“nofollow” 告诉爬虫不要追踪页面上的链接。\n<link rel="canonical" href="example.com/"/>: 这告诉搜索引擎此页面是其 URL 的最佳表现形式,用于防止重复内容问题。\n\n这些是 HTML 元信息的一些常见形式但还有更多的可能性。一般情况下你应该根据你的需要选择合适的元信息来优化网站的性能和搜索引擎优化SEO。\n基础标签\nHTML 文档的基础是由各种标签组成,这些标签定义了网页的不同部分。\n\n主要部分有\n\n开始标签Opening tag包含元素的名称本例为 p被左、右角括号所包围。开头标签标志着元素开始或开始生效的地方。在这个示例中它在段落文本的开始之前。\n内容Content元素的内容本例中就是段落的文本。\n结束标签Closing tag与开始标签相似只是其在元素名之前包含了一个斜杠。这标志着该元素的结束。没有包含关闭标签是一个常见的初学者错误它可能会产生奇特的结果。\n\n以下是一些最常见和重要的 HTML 标签:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n标签描述<html>定义 HTML 文档<head>包含元数据/头部数据<title>定义文档的标题<body>定义文档的主体<h1> 到 <h6>定义标题<p>定义段落<br>插入换行符<hr>定义主题之间的切换(水平线)<!--...-->定义注释<a>定义超链接<img>定义图像<table>定义表格<tr>定义表格行<th>定义表格标题<td>定义表格单元格<caption>定义表格标题<thead>定义表格头部分组<tbody>定义表格主体分组<tfoot>定义表格脚部分组<div>定义文档中的节<span>定义文档中的行内元素\n属性\nHTML 属性是 HTML 元素提供的附加信息。它们定义了元素的一些特性或行为,或者包含了元素的可用数据。\n\n属性总是在 HTML 元素的开始标签中指定,通常是以 name="value" 的形式出现。这里的 class 是属性名editor-note 是属性值。\n属性必须包含\n\n空格它在属性和元素名称之间。如果一个元素具有多个属性则每个属性之间必须由空格分隔。\n名称后面跟着一个等于号。\n属性值由一对引号"")引起来。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述常用在的标签class定义元素的一种或多种类名所有标签id为元素定义唯一的 ID所有标签style为元素定义内联 CSS 样式所有标签src定义引用的资源 URL<img>, <script>, <iframe>, <source>, <audio>, <video>alt定义图像的替代文本<img>width 和 height定义元素的宽度和高度<img>, <canvas>, <iframe>, <video>, <object>href定义链接的 URL<a>, <link>, <base>, <area>target定义链接打开的位置<a>, <base>, <form>disabled定义元素为禁用状态<button>, <fieldset>, <input>, <optgroup>, <option>, <select>, <textarea>placeholder定义输入字段的占位符文本<input>, <textarea>value定义元素的值<button>, <option>, <input>, <li>, <meter>, <progress>, <param>checked定义单选按钮或复选框是否被选中<input>selected定义选项是否被选中<option>readonly定义输入元素为只读<input>, <textarea>maxlength定义输入元素的最大长度<input>, <textarea>rel定义当前文档与链接文档的关系<a>, <link>, <area>, <form>type定义元素的类型<button>, <input>, <command>, <embed>, <object>, <script>, <source>, <style>, <menu>\n表单与输入\n在 HTML 中,表单是一个包含表单元素的区域。表单元素是允许用户在表单中输入内容,如文本字段,选择框,单选框,复选框等。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n标签描述<form>定义 HTML 表单<input>定义输入控制。HTML5 引入了一些新的输入类型,如 color, date, datetime-local, email, month, number, range, search, tel, time, url, week<textarea>定义多行文本输入控制<button>定义点击按钮<select>定义下拉列表<optgroup>定义下拉列表中的选项组<option>定义下拉列表中的选项<label>定义 input, meter, progress, select, textarea 元素的标签<fieldset>定义表单中的一组相关元素<legend>定义 fieldset 元素的标题<datalist>定义 input 元素的预定义选项列表<output>定义计算结果<progress>定义进度(进度条)<meter>定义度量衡。仅用于已知最大和最小值的度量,如磁盘使用、查询结果的相关性等\nHTML5 新特性\nHTML5 是 HTML 的最新演进,它引入了一系列新的元素和属性,以反映现代网站设计和开发的实践。\n语义元素\nHTML5 引入了一系列新的语义元素,以更准确地描述内容。例如,<article><section><nav><header><footer><aside><figure><figcaption> 等。\n<article>\n <header>\n <h2>Article Title</h2>\n <p>Posted on <time datetime="2023-10-13">October 13, 2023</time></p>\n </header>\n <p>This is the article content.</p>\n <footer>\n <p>Author: John Doe</p>\n </footer>\n</article>\n图形和多媒体元素\nHTML5 引入了新的元素来支持图形和多媒体,包括 <canvas> 用于绘制图形,<svg> 用于定义可缩放向量图形,以及 <video> 和 <audio> 用于在网页上播放视频和音频。\n<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">\n</canvas>\n \n<video width="320" height="240" controls>\n <source src="movie.mp4" type="video/mp4">\n <source src="movie.ogg" type="video/ogg">\n Your browser does not support the video tag.\n</video>\n表单控件\nHTML5 为表单输入引入了新的元素类型,如 colordateemailnumberrangesearchteltime 等。还引入了新的表单元素,如 <datalist> 和 <output>。\n<input type="number" name="quantity" min="1" max="10">\n \n<input list="browsers" name="browser">\n<datalist id="browsers">\n <option value="Internet Explorer">\n <option value="Firefox">\n <option value="Chrome">\n <option value="Opera">\n <option value="Safari">\n</datalist>\nWeb APIs\nHTML5 引入了一系列新的 JavaScript APIs如 Geolocation APIDrag and Drop APILocal Storage API等等。这些 API 使网页可以与用户设备进行更深层次的交互。\n// Geolocation API\nnavigator.geolocation.getCurrentPosition(function(position) {\n console.log("Latitude: " + position.coords.latitude + ", Longitude: " + position.coords.longitude);\n});\n \n// Local Storage API\nlocalStorage.setItem("name", "John Doe");\nconsole.log(localStorage.getItem("name"));\nWeb Socket\nWeb Socket 是一种协议,它提供了全双工通信的能力,使得服务器能够实时地向客户端推送数据。\nvar socket = new WebSocket("ws://localhost:8080");\n \nsocket.onopen = function(event) {\n socket.send("Hello Server");\n};\n \nsocket.onmessage = function(event) {\n console.log("Message from server: ", event.data);\n};\nWeb Workers\nWeb Workers 允许开发者在后台,独立于主执行线程运行脚本。这样可以在不影响用户界面的情况下执行复杂的计算任务。\nvar worker = new Worker("worker.js");\n \nworker.onmessage = function(event) {\n console.log("Received: " + event.data);\n};\n \nworker.postMessage("Hello Worker");\n离线存储\nHTML5 引入了应用程序缓存AppCache和本地存储localStorage 和 sessionStorage使得网页可以在离线状态下工作以及保存用户数据在本地。\n// Check if a new cache is available on page load.\nwindow.addEventListener('load', function(e) {\n window.applicationCache.addEventListener('updateready', function(e) {\n if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {\n // Browser downloaded a new app cache.\n if (confirm('A new version of this site is available. Load it?')) {\n window.location.reload();\n }\n } else {\n // Manifest didn't change. Nothing new to server.\n }\n }, false);\n}, false);\n文档架构\n基本组成\nHTML超文本标记语言是用于构建网页的标准标记语言它使用一系列的标签或元素来描述和组织内容。\nHTML 文档的基本结构通常包含以下几个主要部分:\n\n页眉Header通常位于整个页面的顶部包含网站的主要标题和/或标志。它是网站的核心信息,通常在所有页面上都存在。\n导航栏Navigation Bar导航栏包含指向网站各个主要区域的超链接。它通常以菜单按钮、链接或标签页的形式呈现。导航栏在设计上通常要保持一致出现在所有页面上以帮助用户导航网站。有些人将导航栏视为页眉的一部分而另一些人认为导航栏是一个独立的组件。\n主内容区域Main Content主内容区域是页面的中心部分包含当前页面的大部分独有内容如文章、视频、地图、新闻等。主内容区域是网站的核心部分不同页面的主内容会有所不同。\n侧边栏Sidebar侧边栏通常位于主内容区域旁边包含一些附加信息、链接、引用、广告等。侧边栏通常与主内容相关例如在新闻页面上侧边栏可能包含作者信息或相关文章链接。侧边栏还可以包含其他重复元素如辅助导航系统。\n页脚Footer页脚位于页面底部通常是一个横跨页面的窄条区域。类似于页眉页脚包含一些公共信息如版权声明或联系方式。通常使用较小的字体内容相对次要。页脚还可以提供快速访问链接以改善网站的搜索引擎优化SEO。\n\n一个典型的网站可能会这样布局\n\n布局细节\n在进行网页布局时有一些关键的细节需要考虑。以下是一些常见的布局细节可以帮助你创建具有良好用户体验和吸引力的网页布局。\n\n\n**响应式设计:**确保你的网页能够适应不同屏幕尺寸和设备类型。使用 CSS 媒体查询和弹性布局来实现响应式设计,以便在桌面电脑、平板电脑和移动设备上都能提供良好的用户体验。\n\n\n**网格布局:**使用网格系统来创建整齐的网页布局。将页面划分为网格列和行,以便在不同屏幕尺寸上灵活地排列和对齐内容。\n\n\n**盒子模型:**了解 CSS 盒子模型的概念,包括内容区域、填充、边框和外边距。正确地设置和管理盒子模型属性可以影响元素的大小、间距和布局。\n\n\n**流动布局:**使用流动布局使元素按照自然流动方式排列。避免使用固定宽度和高度,而是使用百分比或自适应单位来设置元素的尺寸。\n\n\n**定位:**使用 CSS 定位属性(如相对定位、绝对定位和固定定位)来精确控制元素在页面中的位置。这可以用于创建重叠效果、浮动元素或固定位置的元素。\n\n\n**色彩和对比度:**选择适合你网站主题和品牌的配色方案。确保文本和背景之间有足够的对比度,以确保可读性和可访问性。\n\n\n**导航设计:**设计易于使用的导航菜单,使用户能够轻松浏览网站的不同部分。考虑使用清晰的标签、下拉菜单或面包屑导航等。\n\n\n**空白和间距:**合理利用空白和间距来提高页面的可读性和视觉吸引力。避免内容过于拥挤,给元素之间留出适当的空间。\n\n\n**图片和媒体布局:**对于包含图片、视频或其他媒体的网页,考虑使用适当的布局和对齐方式来展示这些媒体内容。\n\n\n多媒体嵌入\n视频\n<video> 元素用于在网页上嵌入视频内容。以下是一个简单的例子:\n<video width="320" height="240" controls>\n <source src="movie.mp4" type="video/mp4">\n <source src="movie.ogg" type="video/ogg">\n 您的浏览器不支持 Video 标签。\n</video>\n在上面的例子中<video> 标签内部的 <source> 标签用于指定视频源文件。支持多个 <source> 标签,这样如果浏览器不支持第一个视频格式,它将尝试下一个。您的浏览器不支持 Video 标签将在所有指定的源都不被支持的情况下显示。\n<video> 标签的常用属性包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例controls为视频提供播放、暂停和音量控制按钮<video src="movie.mp4" controls>autoplay视频就绪后立即开始播放。注意因为用户体验的问题一些浏览器可能会忽略这个属性<video src="movie.mp4" autoplay>loop视频播放结束后从头开始<video src="movie.mp4" loop>muted将视频的声音默认设置为静音<video src="movie.mp4" muted>poster在视频下载期间或用户在点击播放按钮之前显示一个图像。图像的 URL 在 poster 属性中指定<video src="movie.mp4" poster="poster.jpg">preload规定页面加载后立即加载视频。可以设置为 “auto”、“metadata” 或 “none”<video src="movie.mp4" preload="auto">width 和 height定义视频播放器的高度和宽度<video src="movie.mp4" width="320" height="240">src规定媒介源的 URL<video src="movie.mp4">\n音频\n<audio> 元素用于在网页上嵌入音频内容。语法和 <video> 类似:\n<audio controls>\n <source src="audio.mp3" type="audio/mpeg">\n <source src="audio.ogg" type="audio/ogg">\n 您的浏览器不支持Audio标签。\n</audio>\n<audio> 标签的常用属性也包括 controls、autoplay、loop 和 muted 等。\nIframe\n<iframe> 是一个 HTML 标签,它允许我们在当前的 HTML 文档中嵌入另一个 HTML 文档。<iframe> 标签通常被用于嵌入来自不同源的内容,例如嵌入 Google 地图YouTube 视频,或者其他网站的页面。\n例如通过 <iframe> 标签嵌入 YouTube 视频:\n<iframe width="560" height="315" src="www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>\n<iframe> 标签支持多种属性,包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性名描述示例src规定在 <iframe> 中显示的文档的 URL<iframe src="www.example.com">height 和 width规定 <iframe> 的高度和宽度单位可以是像素px或百分比%<iframe src="demo.html" height="200" width="300">frameborder规定是否显示 <iframe> 的边框。在 HTML5 中,这个属性已经废弃,应使用 CSS 来控制边框<iframe src="demo.html" frameborder="0">sandbox允许对于 <iframe> 中内容的一些限制,如阻止脚本执行,限制表单提交等<iframe src="demo.html" sandbox>allowfullscreen允许 <iframe> 的内容全屏显示,这对于嵌入视频特别有用<iframe src="video.html" allowfullscreen>\n兼容性\n要注意的是不是所有浏览器都支持所有视频或音频格式。例如MP4 主要由 IESafari 和 Chrome 支持,而 Firefox 和 Opera 主要支持 Ogg 和 WebM 。因此,为了获得最佳的跨浏览器兼容性,通常需要提供多种格式的源文件。\n总的来说<video>、<audio> 和 <iframe> 标签在现代浏览器中都有良好的兼容性。但是,考虑到一些用户可能仍然使用老版本的浏览器,我们需要在使用这些标签的时候提供合适的备选方案。\nHTML 表格\nHTML 数据表格用于在网页上显示二维数据。它由 <table>、<tr>、<td> 和 <th> 等标签组成。以下是一个基本的 HTML 表格结构:\n<table>\n <tr>\n <th>标题1</th>\n <th>标题2</th>\n </tr>\n <tr>\n <td>数据1</td>\n <td>数据2</td>\n </tr>\n</table>\n在上述代码中\n\n<table> 标签定义了一个表格。\n<tr> 标签定义了一个表格行。\n<th> 标签定义了一个表头单元格,通常用于显示列的标题。<th> 中的内容默认会被加粗并居中显示。\n<td> 标签定义了一个表格数据单元格,用于显示数据。\n\nHTML 表格还支持一些更高级的特性,例如:\n\n<thead>、<tbody> 和 <tfoot>:用于对表格内容进行分组,有助于提高可访问性,并可以用于应用特定的样式。\ncolspan 和 rowspan 属性:用于定义单元格可以横跨的列数和行数。\n<caption>:为表格提供标题或摘要。\n\n以下是一个使用了这些高级特性的表格示例\n<table>\n <caption>2019 年销售数据</caption>\n <thead>\n <tr>\n <th>季度</th>\n <th>销售额</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>第一季度</td>\n <td>$200,000</td>\n </tr>\n <tr>\n <td>第二季度</td>\n <td>$250,000</td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td colspan="2">总计:$450,000</td>\n </tr>\n </tfoot>\n</table>\n在这个例子中<caption> 提供了表格的标题,<thead>、<tbody> 和 <tfoot> 将表格内容进行了分组colspan 属性使得总计行可以横跨两列。\n需要注意的是**虽然 HTML 表格非常适合用于显示二维数据,但是不应该用于页面布局。**使用 CSS 布局技术(如 Flexbox 或 Grid可以更好地控制页面布局同时也能提高页面的可访问性和响应式设计的能力。"},"Technology/WebDevelopment/3.CSS/CSS":{"title":"CSS","links":[],"tags":["FullStack/基础"],"content":"世界的色彩与形状来自于你的手中。\nCSS\nCSS全称为层叠样式表Cascading Style Sheets是**一种用于描述 HTML 或 XML 文档样式的标记语言。**由于其简洁的语法和强大的功能CSS 已成为前端开发的核心技术之一。\n选择器\n**CSS 的选择器是绑定样式到 HTML 元素的关键。**CSS 选择器大致可以分为以下几类:\n\n简单选择器包括元素选择器、类选择器、ID 选择器。\n属性选择器根据元素的属性选择元素。例如[attr=value] 选择具有特定值的特定属性的元素,[attr^=value] 选择属性值以特定值开始的元素,[attr$=value] 选择属性值以特定值结束的元素,[attr*=value] 选择属性值中包含特定值的元素。\n伪类和伪元素选择器伪类选择器是基于元素的特定状态选择元素例如 :hover、:focus、:checked 等。伪元素选择器是用于选择元素的特定部分,例如 ::before、::after、::first-line 等。\n组合选择器包括子元素选择器、后代选择器、相邻兄弟选择器和一般兄弟选择器。这些选择器可以与简单选择器组合使用以选择符合特定关系的元素。\n分组选择器用逗号分隔的列表可以同时选择多个元素。\n\n常用的 CSS 选择器作用和使用示例:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选择器类型作用示例元素选择器根据元素名称选择元素p { color: red; }类选择器根据元素的 class 属性选择元素.intro { font-size: 20px; }ID 选择器根据元素的 id 属性选择元素#first-paragraph { text-align: center; }属性选择器根据元素的属性选择元素a[target="_blank"] { color: red; }伪类选择器根据元素的特定状态选择元素a:hover { color: red; }伪元素选择器选择元素的特定部分p::first-line { color: blue; }子元素选择器选择特定父元素的直接子元素div > p { margin-left: 20px; }后代选择器选择特定元素的所有后代元素div p { margin-left: 20px; }相邻兄弟选择器选择紧接在另一元素后的元素且二者有相同父元素h1 + p { margin-top: 50px; }一般兄弟选择器选择所有在另一元素之后的兄弟元素且二者有相同父元素h1 ~ p { color: green; }分组选择器同时选择多个元素h1, h2, p { color: purple; }\n权重计算\nCSS 选择器的权重是由选择器的各个部分组成的,又称为选择器的特异性。**特异性的计算是在冲突解决中用来决定哪个样式规则优先应用的一种方式。**计算特异性的基本规则如下:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n选择器类型示例特异性内联样式<div style="...">1,0,0,0ID 选择器#example0,1,0,0类选择器、属性选择器、伪类.example, [type="radio"], :hover0,0,1,0元素选择器、伪元素div, ::before0,0,0,1\n**特异性的计算方式是逐级相加。**例如,对于选择器 #id .class div:hover其特异性是 0100 (id选择器) + 0010 (class选择器) + 0001 (元素选择器) + 0010 (伪类) = 0121。\n需要注意的是**!important 规则可以覆盖其他任何特异性计算。**只有比较两个同时使用 !important 的规则时,才会比较特异性。此外,当样式规则的特异性相同时,后出现的规则将覆盖先出现的规则。\n以下是一个示例\n<div id="id1" class="class1">\n Hello World\n</div>\n \n<style>\n div { color: blue; } /* 特异性 0001 */\n .class1 { color: green; } /* 特异性 0010 */\n #id1 { color: red; } /* 特异性 0100 */\n</style>\n在这个例子中文本 Hello World 的颜色将会是红色,因为 #id1 的特异性最高。\n层叠基层\n**CSS 的全名是 Cascading Style Sheets其中 Cascading层叠指的是如何解决样式冲突的过程。**当多个样式规则应用于同一个元素时,浏览器会根据一系列规则来决定使用哪个样式。这个过程主要依赖于以下三个因素:\n\n\n特异性如前面所述不同的选择器具有不同的特异性。具有更高特异性的规则会覆盖具有较低特异性的规则。例如ID 选择器(特异性为 0,1,0,0会覆盖类选择器特异性为 0,0,1,0。\n\n\n来源样式规则的来源也会影响其优先级。例如用户代理浏览器的默认样式具有最低优先级作者的样式规则优先级较高而用户自定义的样式规则优先级最高。\n\n\n顺序在具有相同特异性的规则中后出现的规则会覆盖先出现的规则。\n\n\n另一方面CSS 的 继承 是指某些 CSS 属性的值可以从其父元素传递给其子元素。例如,如果你为一个 <div> 元素设置了 color: blue;,那么 <div> 元素的所有子元素(除非它们有自己的 color 规则)都将默认使用蓝色字体。\n**需要注意的是,并非所有 CSS 属性都是可继承的。**一些影响布局和盒模型的属性,如 width, height, padding, margin 和 border是不可继承的。而一些与文字样式和颜色相关的属性如 color, font, letter-spacing 和 line-height是可以继承的。如果你想强制一个属性继承其父元素的值可以使用 inherit 关键字,如 width: inherit;。\n盒子模型\n**在 CSS 中,所有的 HTML 元素都可以看作是盒子。**当你在设计一个网页时,你实际上是在操作这些盒子。这种观念被称为 盒子模型Box Model。\n+---------------------------------------------------+\n| Margin |\n| +---------------------------------------------+ |\n| | Border | |\n| | +---------------------------------------+ | |\n| | | Padding | | |\n| | | +---------------------------------+ | | |\n| | | | Content | | | |\n| | | +---------------------------------+ | | |\n| | | Padding | | |\n| | +---------------------------------------+ | |\n| | Border | |\n| +---------------------------------------------+ |\n| Margin |\n+---------------------------------------------------+\nCSS 的盒子模型主要由四个部分组成:\n\nContent内容这是 HTML 元素的实际内容,如文字、图片等。\nPadding内边距包围在内容周围的空间。内边距是透明的。\nBorder边框包围在内边距和内容周围的边框。边框是可见的你可以定义其样式、宽度和颜色。\nMargin外边距包围在边框和其他元素之间的空间。外边距是透明的。\n\n这些部分一起决定了元素的总尺寸。**元素的 width 和 height 属性默认只包含内容的尺寸,不包括内边距、边框和外边距,这是因为 box-sizing 默认值为 content-box。**但是,你可以通过设置 box-sizing: border-box; 来改变这种行为,使 width 和 height 也包括内边距和边框。\n这里是一个样例代码\ndiv {\n width: 300px;\n padding: 10px;\n border: 5px solid black;\n margin: 20px;\n}\n在这个例子中div 元素的实际宽度是 350px300px 的内容宽度 + 2 10px 的内边距 + 2 5px 的边框宽度 = 350px外边距额外增加了 20px 的空间,但不会增加 div 元素本身的宽度。\n边框\n边框主要由 border 属性控制,这也是一个复合属性,包括以下几个子属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例值border-width设置边框的宽度1px, medium, thickborder-style设置边框的样式solid, dashed, dotted, noneborder-color设置边框的颜色black, #000000, rgb(0,0,0)border-radius设置边框的圆角半径10px, 50%\n.example-border {\n /* 设置边框宽度为 5px */\n border-width: 5px;\n \n /* 设置边框样式为实线 */\n border-style: solid;\n \n /* 设置边框颜色为蓝色 */\n border-color: blue;\n \n /* 设置边框的圆角半径为 10px使得边框具有圆角效果 */\n border-radius: 10px;\n}\n背景\n背景主要由 background 属性控制,这是一个复合属性,包括以下几个子属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例值background-color设置元素的背景颜色red, #FF0000, rgb(255,0,0)background-image设置一个或多个背景图像url("image.jpg")background-repeat设置背景图像是否以及如何重复no-repeat, repeat-x, repeat-y, repeatbackground-position设置背景图像的起始位置center, top right, 50% 50%background-size设置背景图像的大小cover, contain, 50% 50%\n.example-background {\n /* 设置背景颜色为浅灰色 */\n background-color: #f8f8f8;\n \n /* 设置背景图像,这里使用了一个在线的图片 URL */\n background-image: url('example.com/image.jpg');\n \n /* 设置背景图像不重复 */\n background-repeat: no-repeat;\n \n /* 设置背景图像的位置在元素的中央 */\n background-position: center;\n \n /* 设置背景图像的大小以完全覆盖元素 */\n background-size: cover;\n}\n文本处理\n在 CSS 中,你可以使用各种属性来处理和控制文本的样式。以下是一个 CSS 文本处理示例:\n.example-text {\n /* 设置文本颜色为红色 */\n color: red;\n \n /* 设置字体为 Arial */\n font-family: Arial;\n \n /* 设置字体大小为 14px */\n font-size: 14px;\n \n /* 设置字体粗细为粗体 */\n font-weight: bold;\n \n /* 设置字体样式为斜体 */\n font-style: italic;\n \n /* 设置文本居中对齐 */\n text-align: center;\n \n /* 设置下划线装饰线 */\n text-decoration: underline;\n \n /* 设置文本全部转换为大写 */\n text-transform: uppercase;\n \n /* 设置行高为 20px */\n line-height: 20px;\n \n /* 设置字符间距为 2px */\n letter-spacing: 2px;\n \n /* 设置单词间距为 5px */\n word-spacing: 5px;\n \n /* 设置首行文本缩进为 20px */\n text-indent: 20px;\n \n /* 设置不换行 */\n white-space: nowrap;\n \n /* 设置文本阴影,水平偏移 1px垂直偏移 1px阴影模糊半径 2px阴影颜色为黑色 */\n text-shadow: 1px 1px 2px black;\n}\n以下是一些常用的 CSS 文本属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例值color设置文本颜色red, #FF0000, rgb(255,0,0)font-family设置字体Arial, "Times New Roman", sans-seriffont-size设置字体大小12px, 1em, 80%font-weight设置字体的粗细normal, bold, 600font-style设置字体样式如斜体normal, italic, obliquetext-align设置文本对齐方式left, right, center, justifytext-decoration设置文本装饰线如下划线none, underline, overline, line-throughtext-transform设置文本转换如大写none, uppercase, lowercase, capitalizeline-height设置行高normal, 1.5, 20pxletter-spacing设置字符间距normal, 3px, 0.5emword-spacing设置单词间距normal, 10px, 2emtext-indent设置首行文本缩进0, 20px, 5%white-space设置如何处理元素内的空白normal, nowrap, pre, pre-wrap, pre-linetext-shadow设置文本阴影1px 1px 2px black\n溢出内容\n在 CSS 中overflow 属性用于控制当元素的内容超过其指定的宽度和高度时发生的情况。这种情况通常称为溢出。overflow 属性有以下几个值:\n\nvisible这是默认值表示内容会溢出元素的边界框。\nhidden如果内容溢出元素的边界框则该内容会被剪裁并且其他内容是不可见的。\nscroll如果内容溢出元素的边界框浏览器会添加滚动条以便查看剩余的内容。\nauto如果内容溢出元素的边界框浏览器会根据需要添加滚动条。\n\n另外还有 overflow-x 和 overflow-y 属性这两个属性分别用于设置元素的水平和垂直溢出。这些属性有相同的值visible、hidden、scroll 和 auto。\n以下是一些示例\n/* 如果其内容溢出,该内容将被剪裁 */\n.example {\n overflow: hidden;\n}\n \n/* 如果其内容在垂直方向上溢出,浏览器将添加滚动条 */\n.example {\n overflow-y: scroll;\n}\n \n/* 如果其内容溢出,浏览器将根据需要添加滚动条 */\n.example {\n overflow: auto;\n}\n需要注意的是overflow 属性只有在元素的宽度和高度已经明确指定(例如,通过 CSS 或内联样式),并且内容实际上溢出这些指定的尺寸时,才会起作用。\n单位和值\n在 CSS 中,我们经常需要为各种属性提供值,这些值可能需要单位。下面是一些常见的 CSS 单位和值:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型单位说明相对长度em相对于父元素的字体大小相对长度rem相对于根元素通常是 <html>)的字体大小相对长度%相对于父元素的大小绝对长度px屏幕上的一个点绝对长度cm, mm, in在屏幕上的大小可能会因设备而异但在打印中很有用其他单位vw相对于视口的宽度“1vw” 等于视口宽度的 1%其他单位vh相对于视口的高度“1vh” 等于视口高度的 1%其他单位vmin 和 vmax分别是视口宽度和高度中较小和较大的值的百分比颜色值Hexadecimal十六进制如 “#FF0000” 代表红色颜色值RGB如 “rgb(255, 0, 0)” 代表红色颜色值RGBA增加了一个 alpha (透明度) 值,如 “rgba(255, 0, 0, 0.5)” 代表半透明的红色颜色值HSL使用色相hue、饱和度saturation和亮度lightness来指定颜色如 “hsl(0, 100%, 50%)” 代表红色颜色值HSLA与 HSL 类似,但增加了 alpha (透明度) 值,如 “hsla(0, 100%, 50%, 0.5)” 代表半透明的红色关键字值display可以接受 “block”, “inline”, “inline-block”, “none” 等值关键字值position可以接受 “static”, “relative”, “absolute”, “fixed” 等值\n布局技巧\n在 CSS 的世界里,布局是最重要的技巧之一。**Flexbox弹性盒子和 Grid网格布局是两种现代且强大的布局方法。**Flexbox 主要用于在一维空间(行或列)内对元素进行布局,非常适合用于组件和小型布局。而 Grid 则主要用于在二维空间(行和列)内对元素进行布局,非常适合用于大型布局项目,如整个页面布局。\nDisplay\nCSS 中 display 属性用于控制元素的显示类型。以下是一些常见的 display 属性值:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性值描述示例元素block元素作为块级元素显示前后会有换行符。<div>, <p>, <h1>-<h6> 等inline元素作为内联元素显示元素前后不会产生换行。<span>, <a>, <img> 等inline-block元素作为内联块级元素显示可以和其他元素在同一行显示但内部可以像块级元素一样设置宽度和高度。-none元素不会被显示。-flex元素作为弹性盒子模型显示用于在一维空间上布局项目能够管理和分配空间和对齐内容。-grid元素作为网格容器显示用于在二维空间上进行布局。-\n以下是一些使用 display 属性的示例:\n/* 元素设置为块级元素 */\n.example {\n display: block;\n}\n \n/* 元素设置为内联元素 */\n.example {\n display: inline;\n}\n \n/* 元素设置为内联块级元素 */\n.example {\n display: inline-block;\n}\n \n/* 元素设置为不显示 */\n.example {\n display: none;\n}\n \n/* 元素设置为弹性盒子模型 */\n.example {\n display: flex;\n}\n \n/* 元素设置为网格模型 */\n.example {\n display: grid;\n}\nFlexbox\n**Flexbox 是一种一维布局模型,主要用于在一个维度(行或列)上对元素进行排列。**只需要简单的设置 display: flex;,一个元素就可以变为弹性容器,其子元素会成为弹性项目。这种布局是响应式的,这意味着项目的大小和位置可以根据父容器的大小动态改变。\n假设我们有一个包含三个子项的容器\n<style>\n .flex-container {\n display: flex;\n }\n</style>\n \n<div class="flex-container">\n <div>1</div>\n <div>2</div>\n <div>3</div>\n</div>\n默认情况下这会让这三个子项并排显示并填充整个容器宽度。\n| Flex Container |\n| 1 | 2 | 3 |\nFlexbox 布局中的一些常用属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性作用示例display定义一个弹性容器.container { display: flex; }flex-direction定义项目的排列方向.container { flex-direction: row; }justify-content定义项目在主轴上的对齐方式.container { justify-content: space-between; }align-items定义项目在交叉轴上的对齐方式.container { align-items: center; }flex-wrap定义项目是否换行.container { flex-wrap: wrap; }flex定义项目的增长、缩小和基本大小.item { flex: 1 1 auto; }\nGrid\n相较于 Flexbox 的一维布局,**Grid 布局则是一个二维布局模型,可以同时在行和列两个维度上对元素进行排列。**通过设置 display: grid;一个元素就可以变为网格容器其子元素会成为网格项目。Grid 布局非常适合用于构建符合网格的复杂界面。\n假设我们有一个包含九个子项的容器\n<style>\n .grid-container {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: repeat(3, 1fr);\n }\n</style>\n \n<div class="grid-container">\n <div>1</div>\n <div>2</div>\n <div>3</div>\n <div>4</div>\n <div>5</div>\n <div>6</div>\n <div>7</div>\n <div>8</div>\n <div>9</div>\n</div>\n这会将子项布局为一个 3x3 的网格,如下所示:\n| Grid Container |\n| 1 | 2 | 3 |\n| 4 | 5 | 6 |\n| 7 | 8 | 9 |\nGrid 布局中的一些常用属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性作用示例display定义一个网格容器.container { display: grid; }grid-template-columns / grid-template-rows定义列宽/行高.container { grid-template-columns: 1fr 1fr; }grid-column / grid-row定义项目的列/行位置.item { grid-column: 1 / 2; }grid-gap定义列间隔/行间隔.container { grid-gap: 10px; }justify-items / align-items定义项目在单元格中的对齐方式.container { justify-items: center; }grid-auto-flow定义项目的排列方式.container { grid-auto-flow: dense; }\nPosition\nCSS 定位Position非常强大它可以用于创建各种复杂的布局。**但是,请注意,过度使用 absolute 或 fixed 定位可能会导致布局难以管理,尤其是在响应式设计中。**在可能的情况下,使用 Flexbox 或 Grid 通常是更好的选择。\nStatic\n**static 是元素的默认定位方式。**这种定位方式下元素会按照正常的文档流进行布局。static 定位的元素不会受到 top、bottom、left 或 right 属性的影响。\ndiv {\n position: static;\n}\nRelative\n**relative 定位的元素会相对于它在正常文档流中的位置进行定位。**例如,设置 left: 20px 会使元素向右移动 20px。\ndiv {\n position: relative;\n left: 20px;\n}\nAbsolute\n**absolute 定位的元素会相对于最近的非 static 定位的祖先元素(如果存在的话)进行定位。**如果没有这样的祖先元素,那么它会相对于 initial containing block 进行定位。absolute 定位的元素会从正常的文档流中移除,并不会影响到其他元素的布局。\ndiv {\n position: absolute;\n top: 20px;\n right: 0;\n}\nFixed\nfixed 定位的元素会相对于浏览器窗口进行定位即使页面滚动它也始终保持在同一位置。fixed 定位的元素会从正常的文档流中移除,并不会影响到其他元素的布局。\ndiv {\n position: fixed;\n bottom: 0;\n right: 0;\n}\nSticky\n**sticky 定位是相对定位和固定定位的混合类型。**元素在滚动到某个位置前为相对定位,之后为固定定位。\ndiv {\n position: sticky;\n top: 0;\n}\n过渡与动画\n在 CSS 中,动画和过渡都是创建动态效果的重要工具,它们可以在提升用户体验和增强网页视觉效果方面发挥重要作用。\nTransition\n过渡是当元素从一个样式逐渐改变为另一个样式时产生的效果。\ntransition 属性是一个复合属性,用于设置四个过渡效果的属性,包括 transition-propertytransition-durationtransition-timing-function 和 transition-delay。这些属性可以单独使用也可以组合在一起使用。\n例如你可以创建一个当鼠标悬停时颜色逐渐改变的按钮\nbutton {\n background-color: blue;\n transition: background-color 2s;\n}\n \nbutton:hover {\n background-color: red;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例值transition-property指定应用过渡效果的 CSS 属性。可以是任何 CSS 属性,如 background-colorheightall 等。background-colortransition-duration指定过渡效果花费的时间以秒s或毫秒ms为单位。2stransition-timing-function规定过渡效果的速度曲线。可选值有 lineareaseease-inease-outease-in-outcubic-bezier(n,n,n,n)。ease-intransition-delay指定过渡效果何时开始。时间以秒s或毫秒ms为单位。1s\nAnimation\n动画是元素从一系列样式中逐渐改变的过程可以使用 @keyframes 规则和 animation 属性来创建动画。@keyframes 本身并没有属性,但是你可以在 **@keyframes 规则中定义动画的各个阶段(关键帧)**和它们的样式。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n关键词描述示例值@keyframes用于创建新的动画规则。它的值是一个动画名称和一个包含关键帧的块。@keyframes myAnimation {...}0% 或 from表示动画的开始阶段。你可以在这里定义元素的初始样式。0% { opacity: 0; }100% 或 to表示动画的结束阶段。你可以在这里定义元素的最终样式。100% { opacity: 1; }n%表示动画的中间阶段。n 是一个介于 0 和 100 之间的百分数。你可以在这里定义元素在动画中间的样式。50% { opacity: 0.5; }\n**而 animation 属性则用于将动画绑定到特定元素。**例如,你可以创建一个循环移动的方块:\n@keyframes move {\n 0% { left: 0; }\n 50% { left: 200px; }\n 100% { left: 0; }\n}\n \ndiv {\n position: absolute;\n width: 100px;\n height: 100px;\n background: red;\n animation: move 2s infinite;\n}\n在这个例子中方块将在 2 秒内从左移动到右,然后再移动回左边,这个过程将无限循环。\n响应式设计与媒体查询\n**响应式设计是一种使网站能够适应各种屏幕尺寸和设备的设计和开发方法。**在响应式设计中,布局、图片、文字和其他元素都会根据浏览器窗口的大小自动调整。\n响应式设计的主要原则包括\n\n流式布局元素的宽度以百分比表示以便能够随着浏览器窗口的大小变化而变化。\n灵活的图片和媒体这些元素的大小也是以百分比表示以保持其在页面中的比例不变。\n媒体查询根据设备的特性如宽度、高度和方向等应用不同的样式规则。\n\n媒体查询是实现响应式设计的主要工具。媒体查询允许我们根据设备的特性如宽度、高度和方向等应用不同的样式规则。在创建响应式布局时我们也可以使用视口单位vw、vh、vmin、vmax。这些单位是相对于视口即浏览器窗口的大小根据视口的大小动态变化非常适合用于创建响应式设计。\n媒体查询的基本语法如下\n@media media-type and (media-feature) {\n /* CSS rules go here */\n}\n\nmedia-type 是可选的,表示媒体类型,如 screen、print 等。\nmedia-feature 表示要查询的设备特性,如 width、height 等。\n\n例如我们可以写一个媒体查询当浏览器窗口的宽度小于 600 像素时,让主要内容的字体大小增大,以便于在小屏幕设备上阅读。\n@media screen and (max-width: 600px) {\n .main-content {\n font-size: 18px;\n }\n}\n在这个例子中.main-content { font-size: 18px; } 这条样式规则只会在媒体类型为 screen 并且浏览器窗口的最大宽度为 600px 时应用。以下是一些常见的媒体查询的例子:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n媒体特性描述示例max-width屏幕宽度的最大值@media (max-width: 600px) {...}min-width屏幕宽度的最小值@media (min-width: 768px) {...}max-height屏幕高度的最大值@media (max-height: 400px) {...}min-height屏幕高度的最小值@media (min-height: 500px) {...}orientation设备屏幕的方向横向或纵向@media (orientation: landscape) {...}aspect-ratio视窗的宽高比@media (aspect-ratio: 16/9) {...}resolution设备的像素密度@media (min-resolution: 300dpi) {...}color设备的颜色位数@media (color: 8) {...}monochrome黑白设备的像素位数@media (monochrome: 2) {...}\nCSS 预处理器\n**CSS 预处理器是一种脚本语言,它扩展了 CSS 的功能,增加了变量、嵌套、混合和函数等特性,使得 CSS 更加强大和易于维护。**预处理器将扩展的 CSS 语法转换为普通的 CSS以便浏览器可以解析。\nSASS 和 LESS 都是流行的 CSS 预处理器它们提供了许多强大的特性如变量、嵌套、混合和函数等。SASS 支持两种语法:旧版的缩进语法和新版的 SCSS 语法,而 LESS 的语法更接近于原生 CSS。此外SASS 提供了更多高级的特性,比如条件语句、循环等。在选择哪种预处理器时,你可以根据你的需求和喜好来决定。\nSASS\nSASSSyntactically Awesome StyleSheets是一种 CSS 预处理器它提供了许多有用的特性如变量、嵌套、混合和函数等。SASS 支持两种语法旧版的缩进语法Indented Syntax和新版的 SCSS。旧版的语法更简洁但新版的 SCSS 语法更接近于原生 CSS。\n以下是一个使用 SASS 特性的例子:\n$font-stack: Helvetica, sans-serif;\n$primary-color: #333;\n \nbody {\n font: 100% $font-stack;\n color: $primary-color;\n}\n \n.container {\n width: 100%;\n \n .sidebar {\n width: 30%;\n }\n \n .content {\n width: 70%;\n }\n}\nLESS\nLESS 是另一种流行的 CSS 预处理器,它的语法和 CSS 非常相似所以学习曲线相对较平缓。LESS 提供了变量、嵌套、混合、函数和运算等特性。\n以下是一个使用 LESS 特性的例子:\n@base-color: #f938ab;\n \n.box-shadow(@style, @c) when (iscolor(@c)) {\n -webkit-box-shadow: @style @c;\n box-shadow: @style @c;\n}\n.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {\n .box-shadow(@style, rgba(0, 0, 0, @alpha));\n}\n.box {\n color: saturate(@base-color, 5%);\n border-color: lighten(@base-color, 30%);\n div { .box-shadow(0 0 5px, 30%) }\n}\n总的来说CSS 预处理器如 SASS 和 LESS 可以让你的 CSS 更加强大和易于维护,它们是现代前端开发工具链的重要组成部分。"},"Technology/WebDevelopment/4.JavaScript/JavaScript":{"title":"JavaScript","links":[],"tags":["FullStack/基础"],"content":"网页的心跳,使静态的网页获得了动态的脉搏。\nJavaScript\nJavaScript 是一种动态的、解释的编程语言,广泛应用于 Web 开发中。JavaScript 通过 BOM浏览器对象模型和 DOM文档对象模型与浏览器进行交互。\nBOM 提供了访问和操作浏览器窗口的能力包括窗口大小、导航、定时器、对话框等。DOM 则是对网页内容的抽象,它将网页文档结构化为一个节点树,允许开发者查询和操作页面内容。\n简单来说JavaScript 是语言DOM 是这个语言可以操作的对象之一网页内容BOM 也是这个语言可以操作的对象之一(浏览器窗口及其相关属性和方法)。\ngraph TB\n A[JavaScript] -- Interacts with --> B[BOM]\n A -- Interacts with --> C[DOM]\n B -- Manages --> D[Browser Window]\n C -- Manages --> E[Web Page Content]\n\n这个图展示了 JavaScript、BOM、DOM 之间的关系。其中JavaScript 与 BOM 和 DOM 进行交互BOM 管理浏览器窗口DOM 管理网页内容。\n基础语法\nJavaScript 的基础语法相对简单,主要包含变量、数据类型、运算符、语句与注释等。\n变量\nJavaScript 通过 var、let 和 const 关键词来声明变量,它们之间存在明显的区别:\n\nvar 是函数作用域的变量,也就是说,如果你在一个函数内部声明了一个 var 变量,那么它只能在这个函数内部被访问。\nlet 和 const 都是块级作用域的变量,它们只能在声明它们的代码块或者更小的作用域内被访问。\n\nvar 存在变量提升的特性,即在声明之前使用变量不会报错,但是值为 undefined。而 let 和 const 不存在变量提升,它们具有所谓的暂时性死区特性。\n// var 声明的变量可以重复声明,会发生变量提升\nvar name = 'John';\nvar name = 'Peter'; \n \n// let 声明的变量不可以重复声明,有块级作用域\nlet age = 25; \nlet age = 30; // 报错\n \n// const 声明的是常量,初始化后值不可修改\nconst pi = 3.14;\npi = 3; // 报错\n数据类型\nJavaScript 中有七种数据类型:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n数据类型说明示例Number包括整数和浮点数123, 3.14String字符串,使用单引号或双引号包裹hello, “world”Booleantrue 和 falsetrue, falseNull表示无值nullUndefined表示值未定义undefinedSymbol表示独一无二的值Symbol(id)BigInt可表示任意大的整数9007199254740991n\nJavaScript 中还有一种复杂数据类型 Object表示由多个键值对组成的对象。可以使用 typeof 来判断一个变量的类型:\nlet n = 123; \nlet s = 'Hello';\nlet b = true;\n \ntypeof n; // 'number'\ntypeof s; // 'string' \ntypeof b; // 'boolean'\n运算符\nJavaScript 支持多种运算符,包括:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n运算符类型运算符说明示例算术运算符+ - * / % ++ —用于执行算术运算x + y赋值运算符= += -= *= /= %= **=用于给变量赋值x += 1比较运算符 = != !== > < >= ⇐用于比较两个值x == y逻辑运算符&& || !用于组合条件x > 0 && y < 0条件运算符? :根据条件选择值condition ? val1 : val2位运算符& | ^ ~ << >> >>>用于位运算x & y\nlet a = 1 + 2; // 3\nlet b = 'Hello' + ' ' + 'World!'; // 'Hello World!'\n \nconsole.log(a == b); // false\nconsole.log(a != b); // true\n \nconsole.log(a > 0 && b.includes('Hello')); // true\n语句\nJavaScript 提供了多种控制结构,包括条件语句、循环语句、分支语句和跳转语句。\n条件语句\n使用 if/else 语句进行条件判断:\nif (condition) {\n // 条件为真时执行\n} else {\n // 条件为假时执行 \n}\nif/else 语句可以进行多重条件判断:\nif (n > 0) {\n // n 大于 0\n} else if (n < 0) {\n // n 小于 0\n} else {\n // n 等于 0\n}\n循环语句\n使用 for 循环和 while 循环进行迭代操作:\n// for 循环\nfor (let i = 0; i < 5; i++) {\n console.log(i); \n}\n \n// while 循环\nlet j = 0;\nwhile (j < 5) {\n console.log(j);\n j++;\n}\n分支语句\n使用 switch 语句进行多分支判断:\nswitch(fruit) {\n case 'apple': \n console.log('苹果');\n break;\n case 'banana':\n console.log('香蕉');\n break;\n default:\n console.log('其他水果');\n}\n跳转语句\nbreak 用于退出循环continue 用于跳过当前循环:\nfor (let i = 0; i < 10; i++) {\n if (i % 2 === 0) { \n continue; // 跳过偶数\n }\n console.log(i);\n \n if (i > 5) {\n break; // 当 i 大于 5 时退出循环\n } \n}\n另外JavaScript 支持使用注释来增加代码的可读性:\n// 这是单行注释\n \n/*\n这是多行注释可以注释一段代码\n*/\n函数\n函数是 JavaScript 中组织代码的基本单元,可以封装一段可以重复执行的代码块:\n// 函数声明\nfunction add(x, y) {\n return x + y; \n}\n \n// 函数表达式\nconst subtract = function(x, y) {\n return x - y;\n};\n \n// 箭头函数ES6 新增)\nconst multiply = (x, y) => {\n return x * y;\n};\n函数可以有参数也可以有返回值。在 JavaScript 中,函数也是一种对象,可以被赋值给变量,也可以作为其他函数的参数或返回值。\n数组\n数组是一种特殊的对象用于存储一系列的值\nlet nums = [1, 2, 3];\nlet fruits = ['Apple', 'Banana', 'Orange'];\n \nnums.push(4); // 添加元素\nnums.pop(); // 删除最后一个元素\nnums.includes(2); // 检查是否包含某个元素\n在 JavaScript 中,数组是动态的,可以随时添加或删除元素。数组的长度可以通过其 length 属性获取。\n对象\n对象是 JavaScript 的核心概念,它是由一组键值对构成的数据集合:\nlet person = {\n name: 'John',\n age: 20,\n sayHi: function() {\n console.log('Hi!'); \n }\n};\n \nconsole.log(person.name); // 访问属性\nperson.sayHi(); // 调用方法\n**在 JavaScript 中,几乎所有的东西都是对象。**函数、数组、日期和正则表达式等都是特殊的对象。对象的属性和方法可以被动态创建和删除,非常灵活。\n其他特性\nJavaScript 还有许多其他高级特性,例如原型和继承、闭包、异步处理和模块等。\n原型和继承\nJavaScript 是基于原型的语言每个对象都有一个指向它的原型prototype的链接。当试图访问一个对象的属性时JavaScript 会首先在对象本身的属性中搜索,如果找不到,就会在它的原型对象中搜索。\nfunction Person(name) {\n this.name = name;\n}\n \nPerson.prototype.sayName = function() {\n console.log(this.name); \n};\n \nlet person1 = new Person('John');\nperson1.sayName(); // 'John'\nJavaScript 的继承机制是基于原型的。我们可以通过设置一个类型的原型为另一个类型的实例,来实现继承。\nfunction Student(name, grade) {\n Person.call(this, name); // 继承属性\n this.grade = grade;\n}\n \nStudent.prototype = Object.create(Person.prototype); // 继承方法\nStudent.prototype.constructor = Student;\n \nlet student1 = new Student('Tom', 5);\nconsole.log(student1.name); // Tom\nconsole.log(student1.grade); // 5\nstudent1.sayName(); // Tom\n闭包\n闭包closure是 JavaScript 中一个重要的概念。在 JavaScript 中,函数可以形成闭包。闭包是指有权访问另一个函数作用域中的变量的函数。\nfunction createCounter() {\n let count = 0;\n return function() {\n return ++count;\n };\n}\n \nlet counter = createCounter();\nconsole.log(counter()); // 1\nconsole.log(counter()); // 2\n闭包的一个常见应用是使函数有私有变量。在上面的例子中变量 count 就像 createCounter 函数的私有变量,外部无法访问,只能通过闭包来操作。\n异步处理\nJavaScript 是单线程的,但是它可以通过事件和回调函数来处理异步操作。例如,我们可以使用 setTimeout 函数来延迟执行一段代码:\nconsole.log('Hello');\nsetTimeout(function() {\n console.log('World');\n}, 1000);\nconsole.log('!');\n这段代码会首先输出 Hello!’,然后等待一秒钟后,再输出 World。虽然 setTimeout 函数在 ! 之前调用,但是它不会阻塞代码的执行。\n在 ES6 中JavaScript 引入了 Promise 和 async/await使得异步编程更加方便和强大。\n模块\n在现代的 JavaScript 开发中我们通常会把代码分成多个模块module每个模块负责一部分功能。模块可以导入import其他模块也可以导出export自己的接口给其他模块使用。\n// math.js\nexport function add(x, y) {\n return x + y;\n}\n \n// main.js\nimport { add } from './math.js';\nconsole.log(add(1, 2)); // 3\n模块可以使我们的代码更加结构化和可维护。\nBOM 模型\n**浏览器对象模型Browser Object ModelBOM是用于与浏览器交互的模型。**它提供了一种方式,使开发者能够通过 JavaScript 访问和操作浏览器的窗口。\nBOM 主要由一系列的对象组成,这些对象提供了许多方法和属性,使得开发者能够处理浏览器窗口和文档的加载、大小、位置等各种情况,以及进行网络通信等操作。\nBOM 的核心对象是 window它代表了浏览器的窗口也是 JavaScript 的全局对象。除此之外BOM 还包括了其他一些对象,例如:\n\nlocation 对象:提供了当前窗口中加载的文档的 URL 信息,以及用于导航的方法。\nnavigator 对象:提供了当前浏览器的信息,比如版本、名称等。\nhistory 对象:提供了浏览器历史的信息,以及用于导航的方法。\ndocument 对象:提供了当前加载在窗口中的 HTML 文档的访问和操作的方式。\n\nclassDiagram\n Window --|> Document: "document"\n Window --|> Navigator: "navigator"\n Window --|> History: "history"\n Window --|> Location: "location"\n Window --|> Screen: "screen"\n Window --|> Frames: "frames"\n Window --|> Performance: "performance"\n Window --|> localStorage: "localStorage"\n Window --|> sessionStorage: "sessionStorage"\n Window --|> console: "console"\n class Window {\n +open()\n +close()\n +getComputedStyle()\n +setTimeout()\n +setInterval()\n +clearTimeout()\n +clearInterval()\n +fetch()\n }\n class Document {\n +getElementById(id)\n +getElementsByClassName(name)\n +getElementsByTagName(name)\n +querySelector(selector)\n +querySelectorAll(selector)\n +createElement(tagName)\n +createTextNode(data)\n }\n class Navigator {\n +appName\n +appVersion\n +userAgent\n +platform\n +language\n +onLine\n +geolocation\n +cookieEnabled\n +javaEnabled()\n }\n class History {\n +back()\n +forward()\n +go(n)\n +pushState()\n +replaceState()\n }\n class Location {\n +href\n +protocol\n +host\n +hostname\n +port\n +pathname\n +search\n +hash\n +reload()\n +assign(URL)\n +replace(URL)\n }\n class Screen {\n +availWidth\n +availHeight\n +width\n +height\n +colorDepth\n +pixelDepth\n }\n class Frames\n class Performance\n class localStorage {\n +setItem()\n +getItem()\n +removeItem()\n +clear()\n }\n class sessionStorage {\n +setItem()\n +getItem()\n +removeItem()\n +clear()\n }\n class console {\n +log()\n +info()\n +warn()\n +error()\n }\n\n需要注意的是**BOM 并没有一个标准的定义,不同的浏览器可能实现了不同的 BOM。**但是,现代的浏览器已经在很大程度上实现了 BOM 的兼容性。\n窗口对象\n窗口对象Window Object是 BOM 的核心对象,它代表了浏览器的窗口。所有的全局变量,函数都是它的方法和属性。例如,我们可以获取窗口的尺寸:\nlet width = window.innerWidth;\nlet height = window.innerHeight;\n我们也可以使用 setTimeout 和 setInterval 方法来执行定时操作:\n// 打印 "Hello, world!" 然后 2 秒后关闭窗口\nwindow.setTimeout(function() {\n console.log("Hello, world!");\n window.close();\n}, 2000);\n以下是 window 对象的一些常用属性和方法的表格形式:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述属性window.innerWidth浏览器窗口的视口viewport的宽度包括滚动条属性window.innerHeight浏览器窗口的视口viewport的高度包括滚动条属性window.outerWidth浏览器窗口的外部宽度属性window.outerHeight浏览器窗口的外部高度属性window.location当前窗口的 Location 对象,包含了当前页面的 URL 信息属性window.document当前窗口加载的 Document 对象,即 DOM文档对象模型属性window.history当前窗口的 History 对象提供了浏览历史的访问和操作属性window.screen当前屏幕的 Screen 对象提供了屏幕的信息方法window.alert()显示一个警告对话框方法window.prompt()显示一个提示对话框并请求用户输入方法window.confirm()显示一个确认对话框并请求用户确认方法window.open()打开一个新的浏览器窗口或标签页方法window.close()关闭当前的浏览器窗口或标签页方法window.setTimeout()设置一个定时器在指定的毫秒数后执行一个函数或代码方法window.setInterval()设置一个定时器每隔指定的毫秒数重复执行一个函数或代码方法window.clearTimeout()清除由 setTimeout 设置的定时器方法window.clearInterval()清除由 setInterval 设置的定时器\n文档对象\n文档对象Document Object是 HTML 文档的根节点用于访问和操作网页内容。document 对象允许你访问和操作页面的内容,包括元素节点、属性节点和文本节点。\n以下是 document 对象的一些常见属性和方法:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述属性document.documentElement返回文档的根元素在 HTML 中,通常是 <html> 元素属性document.body返回文档的 <body> 元素属性document.head返回文档的 <head> 元素属性document.title获取或设置文档的标题方法document.getElementById(id)返回具有指定 ID 的元素方法document.getElementsByClassName(name)返回所有具有指定类名的元素的集合方法document.getElementsByTagName(name)返回所有具有指定标签名的元素的集合方法document.querySelector(selector)返回匹配指定 CSS 选择器的第一个元素方法document.querySelectorAll(selector)返回匹配指定 CSS 选择器的所有元素的集合方法document.createElement(tagName)创建一个新的元素节点方法document.createTextNode(data)创建一个新的文本节点\n这些只是 document 对象的基本属性和方法。实际上DOM 提供了非常多的 API 来查询和操作文档,包括添加、删除和修改元素,添加事件监听器,修改 CSS 样式等等。\n例如我们可以使用 document.getElementById() 来获取具有特定 ID 的元素,或者使用 document.createElement() 来创建新的元素:\n// 获取 ID 为 "myElement" 的元素\nlet myElement = document.getElementById("myElement");\n \n// 创建一个新的 <p> 元素\nlet newElement = document.createElement("p");\nnewElement.textContent = "This is a new paragraph.";\ndocument.body.appendChild(newElement);\n导航对象\n导航对象Navigator Object提供了关于浏览器的信息。下面是一些常见的 navigator 对象的属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述属性navigator.appName返回浏览器的名称属性navigator.appVersion返回浏览器的版本信息属性navigator.userAgent返回用户代理头的字符串表示包含浏览器名称、版本、操作系统等信息属性navigator.platform返回运行浏览器的操作系统平台属性navigator.language返回浏览器的默认语言属性navigator.onLine返回浏览器的在线状态如果浏览器在线则返回 true否则返回 false\n另外navigator 对象还包含一些用于特定功能的方法和对象,例如:\n\nnavigator.geolocation用于获取用户的地理位置信息。\nnavigator.cookieEnabled返回一个布尔值表示是否启用了 cookie。\nnavigator.javaEnabled():返回一个布尔值,表示是否启用了 Java。\n\n请注意navigator 对象的一些属性和方法可能会因浏览器的不同而有所差异。而且,由于隐私和安全的考虑,某些信息可能需要用户的许可才能访问。\nconsole.log(navigator.userAgent);\n历史对象\n历史对象History Object提供了浏览器历史记录的操作方法。然而由于隐私原因您不能获取到用户的浏览历史具体细节但可以用 history 对象来操作当前窗口的浏览历史。\n以下是 history 对象的一些常见方法:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述方法history.back()和点击浏览器后退按钮一样,加载历史列表中的前一个 URL方法history.forward()和点击浏览器前进按钮一样,加载历史列表中的下一个 URL方法history.go(n)加载历史列表中的某个具体页面,通过参数 n 指定。n 为正数时前进n 为负数时后退n 为 0 时刷新当前页面方法history.pushState()在历史记录中添加一个状态但不触发页面刷新方法history.replaceState()在历史记录中替换当前状态,但不触发页面刷新\n注意pushState() 和 replaceState() 方法可以改变 URL 并添加历史记录,但并不会重新加载页面。这对于创建 AJAX 驱动的动态页面非常有用。\n还有一个 history.length 属性,它返回当前窗口历史堆栈中的 URL 数量。由于安全和隐私原因,您无法访问堆栈中的实际 URL。\n例如我们可以使用 history.back() 和 history.forward() 方法来模拟用户点击浏览器的后退和前进按钮:\n// 后退到上一个页面\nhistory.back();\n \n// 前进到下一个页面\nhistory.forward();\n位置对象\n位置对象Location Object提供了当前窗口或标签的 URL 信息,以及一些方法来操作 URL。\n以下是 location 对象的一些常见属性和方法:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述属性location.href获取或设置整个 URL属性location.protocol返回 URL 的协议部分“http:” 或 “https:“属性location.host返回 URL 的主机名和端口如果有的话属性location.hostname返回 URL 的主机名属性location.port返回 URL 的端口号属性location.pathname返回 URL 的路径名属性location.search返回 URL 的查询字符串(包括 ”?“属性location.hash返回 URL 的片段标识符(包括 ”#“方法location.reload()重新加载当前页面方法location.assign(URL)加载新的页面方法location.replace(URL)替换当前页面\n这些属性和方法使我们可以从 JavaScript 中读取和操作 URL 的各个部分。例如,我们可以使用 location.href 来获取当前页面的 URL或者使用 location.assign() 来加载一个新的页面。还要注意的是,使用 location.replace() 方法不会在历史记录中留下记录,所以用户不能使用 ” 后退 ” 按钮返回。\n例如我们可以使用 location.href 来获取或设置当前页面的 URL或者使用 location.reload() 来重载当前页面:\n// 打印当前页面的 URL\nconsole.log(location.href);\n \n// 重载当前页面\nlocation.reload();\n屏幕对象\n屏幕对象Screen Object提供了关于用户的屏幕信息。这些信息包括屏幕的宽度、高度、颜色深度和像素深度等。以下是 screen 对象的一些常见属性:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n类型名称描述属性screen.availWidth返回屏幕的可用宽度以像素为单位减去界面特性如 Windows 任务栏属性screen.availHeight返回屏幕的可用高度以像素为单位减去界面特性如 Windows 任务栏属性screen.width返回屏幕的总宽度以像素为单位属性screen.height返回屏幕的总高度以像素为单位属性screen.colorDepth返回目标设备或缓冲器上的颜色深度以位为单位属性screen.pixelDepth返回屏幕的像素深度\n这些属性可以帮助你了解用户的屏幕信息并据此调整网页的布局或设计。例如你可以根据 screen.width 和 screen.height 来调整网页的大小,以最佳地适应用户的屏幕。\n注意screen 对象的属性是只读的,你不能修改它们的值。我们可以使用 screen.width 和 screen.height 来获取屏幕的宽度和高度:\nconsole.log("Screen width: " + screen.width);\nconsole.log("Screen height: " + screen.height);\nDOM 模型\n**文档对象模型Document Object ModelDOM是一种编程接口它允许程序和脚本动态地访问和更新文档的内容、结构和样式。**DOM 将文档解析为一个由节点和对象(包括属性和方法)构成的结构集合,这样就可以使用脚本语言(如 JavaScript来操作这些节点和对象。\n在 Web 中,最常见的文档类型是 HTML 或 XML 文档。对于这种类型的文档DOM 表示它们为一个树状结构其中每个节点都是一个对象代表了文档的一部分。例如HTML 文档中的每个元素、属性和文本都会被表示为一个 DOM 节点。\n一个简单的 HTML DOM 结构可能会像下面这样:\n<!DOCTYPE html>\n<html>\n <head>\n <title>My Page</title>\n </head>\n <body>\n <h1>Welcome to My Page</h1>\n <p>Content here</p>\n </body>\n</html>\n在这个 HTML 文档中,<html>、<head>、<title>、<body>、<h1> 和 <p> 元素都是 DOM 节点。My Page 和 Welcome to My Page 以及 Content here 这些文本也是 DOM 节点,它们是元素节点的子节点。\nclassDiagram\n Document --|> HTMLElement: "elements"\n HTMLElement --|> HTMLDivElement\n HTMLElement --|> HTMLSpanElement\n HTMLElement --|> HTMLAnchorElement\n HTMLElement --|> HTMLImageElement\n HTMLElement --|> HTMLParagraphElement\n HTMLElement --|> HTMLInputElement\n HTMLElement --|> HTMLButtonElement\n HTMLElement --|> HTMLCanvasElement\n HTMLElement --|> HTMLTableElement\n class Document {\n +getElementById(id)\n +getElementsByClassName(name)\n +getElementsByTagName(name)\n +querySelector(selector)\n +querySelectorAll(selector)\n +createElement(tagName)\n +createTextNode(data)\n }\n class HTMLElement {\n +innerHTML\n +outerHTML\n +textContent\n +id\n +className\n +setAttribute(name, value)\n +getAttribute(name)\n +removeAttribute(name)\n +addEventListener(type, listener)\n +removeEventListener(type, listener)\n }\n class HTMLDivElement\n class HTMLSpanElement\n class HTMLAnchorElement {\n +href\n }\n class HTMLImageElement {\n +src\n +alt\n }\n class HTMLParagraphElement\n class HTMLInputElement {\n +value\n +checked\n }\n class HTMLButtonElement {\n +disabled\n }\n class HTMLCanvasElement\n class HTMLTableElement\n\n开发者可以使用 DOM API 来获取、创建、修改或删除这些节点,从而实现对网页内容和结构的动态控制。这是现代网页交互性的基础。\n获取元素\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述示例document.getElementById(id)通过元素 ID 获取元素。此方法返回一个对象,表示带有指定 ID 的元素。document.getElementById('myId')document.getElementsByClassName(name)通过类名获取元素。此方法返回一个 HTMLCollection 对象包含了文档中所有具有指定类名的元素。document.getElementsByClassName('myClass')document.getElementsByTagName(name)通过标签名获取元素。此方法返回一个 HTMLCollection 对象包含了文档中所有具有指定标签名的元素。document.getElementsByTagName('div')document.querySelector(selector)返回文档中匹配指定 CSS 选择器的第一个元素。document.querySelector('.myClass')document.querySelectorAll(selector)返回文档中匹配指定 CSS 选择器的所有元素。此方法返回一个 NodeList 对象。document.querySelectorAll('.myClass')document.getElementsByName(name)通过元素的 Name 属性获取元素。此方法返回一个 NodeList 对象,包含了文档中所有具有指定 Name 属性的元素。document.getElementsByName('myName')Element.querySelector(selector)返回元素内部匹配指定 CSS 选择器的第一个元素。document.getElementById('myId').querySelector('.myClass')Element.querySelectorAll(selector)返回元素内部匹配指定 CSS 选择器的所有元素。此方法返回一个 NodeList 对象。document.getElementById('myId').querySelectorAll('.myClass')\n请注意Element.querySelector 和 Element.querySelectorAll 与 document.querySelector 和 document.querySelectorAll 类似,但它们只在指定元素的后代中查找,而不是在整个文档中查找。\n例如:\n// 获取 id 为 title 的元素\nconst title = document.getElementById('title'); \n \n// 获取所有 <p> 元素\nconst ps = document.getElementsByTagName('p');\n \n// 获取所有 class 为 content 的元素 \nconst contents = document.getElementsByClassName('content');\n \n// 获取第一个 class 为 content 的元素\nconst content = document.querySelector('.content'); \n改变元素\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述示例element.setAttribute(name, value)设置元素的属性。此方法会设置或更新元素的属性。element.setAttribute('class', 'myClass')element.getAttribute(name)获取元素的属性值。此方法返回指定属性的值,如果该属性不存在,则返回 null。element.getAttribute('class')element.removeAttribute(name)删除元素的属性。此方法会完全移除元素的指定属性。element.removeAttribute('class')element.classList.add(class1, class2, ...)向元素添加一个或多个类。此方法会向元素的类列表添加一个或多个类名。如果指定的类名已存在则不会添加。element.classList.add('myClass')element.classList.remove(class1, class2, ...)从元素中删除一个或多个类。此方法会从元素的类列表中删除一个或多个类名。element.classList.remove('myClass')element.classList.toggle(class, true/false)切换元素的类。如果类名存在则删除它如果类名不存在则添加它。element.classList.toggle('myClass')element.style.cssText设置或返回元素的样式属性。此属性返回一个 CSSStyleDeclaration 对象,代表元素的 style 属性。element.style.cssText = 'color: red; background: blue;'element.style.property设置或返回元素的指定样式属性。此属性会设置或返回元素的指定样式属性。element.style.color = 'red'element.innerHTML设置或返回元素的 HTML 内容。此属性会设置或返回元素的内部 HTML。element.innerHTML = '<b>Hello</b>'element.outerHTML设置或返回元素的外部 HTML。此属性会设置或返回元素的开头和结尾标签包括元素的所有后代。console.log(element.outerHTML)element.textContent设置或返回元素的文本内容。此属性会设置或返回元素的所有文本内容包括它的所有后代。element.textContent = 'Hello'\n请注意每个属性和方法可能有其适用性和局限性。在使用它们的时候需要考虑到你的需求和它们的特性。\n// 改变内容\ntitle.innerHTML = 'New title'; \n \n// 改变样式\ntitle.style.color = 'red';\n \n// 显示/隐藏\ncontent.style.display = 'none';\n \n// 添加类\ncontent.classList.add('hidden'); \n \n// 删除类\ncontent.classList.remove('hidden');\n创建元素\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述示例document.createElement(tagName)创建一个新元素。此方法创建一个具有指定标签名的新元素。let div = document.createElement('div')document.createTextNode(data)创建一个新的文本节点。此方法创建一个包含指定文本的新 Text 节点。let text = document.createTextNode('Hello')Node.appendChild(child)向元素添加一个新的子节点。此方法将指定的节点添加到指定节点的子节点列表的末尾。div.appendChild(text)Node.insertBefore(newNode, referenceNode)在参考节点之前插入一个新节点。此方法将指定的节点插入到参考节点之前。如果参考节点为 null则新节点将被添加到子节点的末尾。document.body.insertBefore(div, document.body.firstChild)Element.insertAdjacentHTML(position, text)解析指定的文本作为 HTML 或 XML并将生成的节点插入到 DOM 树的指定位置。此方法不会重新解析它正在使用的元素因此它不会破坏元素内的现有元素。div.insertAdjacentHTML('beforeend', '<span>Hello</span>')Element.insertAdjacentText(position, text)将指定的文本插入到 DOM 树的指定位置。此方法不会重新解析它正在使用的元素因此它不会破坏元素内的现有元素。div.insertAdjacentText('beforeend', 'Hello')Element.insertAdjacentElement(position, element)将指定的元素插入到 DOM 树的指定位置。此方法不会重新解析它正在使用的元素因此它不会破坏元素内的现有元素。let span = document.createElement('span'); div.insertAdjacentElement('beforeend', span)Node.cloneNode(deep)创建指定节点的副本。此方法创建一个新的节点,这个节点是调用此方法的节点的副本。如果 deep 参数为 true则复制包括整个子 DOM 树否则只复制节点本身。let divClone = div.cloneNode(true)Node.replaceChild(newChild, oldChild)替换一个子节点。此方法将 oldChild 替换为 newChild。div.replaceChild(newSpan, oldSpan)\n这些方法为您提供了创建和操纵 DOM 元素的强大工具。在实际开发中,您可能会经常使用它们来动态地更新页面内容。\n// 创建新元素\nconst div = document.createElement('div');\n \n// 设置属性\ndiv.innerHTML = 'Hello World'; \ndiv.style.color = 'blue';\n \n// 插入到文档中\ndocument.body.appendChild(div);\n事件处理\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n方法描述示例element.addEventListener(event, function, useCapture)为元素添加事件监听器。此方法在指定元素上添加一个事件处理程序。element.addEventListener('click', myFunction)element.removeEventListener(event, function, useCapture)从元素中移除事件监听器。此方法从指定元素中移除事件处理程序。element.removeEventListener('click', myFunction)element.onclick为元素设置 click 事件处理程序。此属性返回当前元素的 onclick 事件处理程序代码,或设置一个新的 onclick 事件处理程序代码。element.onclick = myFunctionevent.preventDefault()取消事件的默认动作。此方法阻止事件的默认动作。例如,点击链接的默认动作是跳转到链接的 URL当调用此方法后点击链接不会跳转。event.preventDefault()event.stopPropagation()阻止事件冒泡。此方法阻止事件向上冒泡到 DOM 树。event.stopPropagation()event.stopImmediatePropagation()阻止剩余的事件处理程序被执行并阻止事件冒泡到 DOM 树。event.stopImmediatePropagation()event.target返回触发事件的元素。此属性返回触发事件的元素。let targetElement = event.targetevent.type返回事件的名称。此属性返回表示事件名称的字符串。let eventType = event.typeevent.clientX and event.clientY返回鼠标事件发生时鼠标指针的位置。这两个属性返回鼠标指针相对于浏览器窗口的水平和垂直坐标。let x = event.clientX; let y = event.clientY\n这些都是最常用的事件处理方法和属性。实际上还有更多的事件类型和与事件相关的方法和属性它们可以用来处理键盘事件、触摸事件、拖放事件等等。请查阅相关文档以获取更多信息。\n// 点击事件\nbtn.addEventListener('click', () => {\n // 点击时运行的代码\n});\n \n// 加载事件\nwindow.addEventListener('load', () => {\n // 页面加载完成后运行的代码\n});\n事件处理\nJavaScript 可以对各种事件做出响应。\n鼠标事件\n常见的鼠标事件:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n事件类型描述示例click鼠标点击一个元素时触发。element.addEventListener('click', myFunction)dblclick鼠标双击一个元素时触发。element.addEventListener('dblclick', myFunction)mousedown鼠标按钮被按下时触发。element.addEventListener('mousedown', myFunction)mouseup鼠标按钮被松开时触发。element.addEventListener('mouseup', myFunction)mousemove鼠标被移动时触发。element.addEventListener('mousemove', myFunction)mouseover鼠标指针移动到元素上时触发。element.addEventListener('mouseover', myFunction)mouseout鼠标指针移动出元素时触发。element.addEventListener('mouseout', myFunction)mouseenter鼠标指针移动到元素上时触发不冒泡。element.addEventListener('mouseenter', myFunction)mouseleave鼠标指针移动出元素时触发不冒泡。element.addEventListener('mouseleave', myFunction)contextmenu当尝试在元素上打开上下文菜单时通常通过右键点击触发。element.addEventListener('contextmenu', myFunction)mousewheel / wheel当鼠标滚轮被滚动时触发。element.addEventListener('wheel', myFunction)\n在这些事件处理程序中你可以使用 event 对象来访问事件的相关信息,比如触发事件的元素 (event.target),鼠标的位置 (event.clientX 和 event.clientY),以及鼠标按钮的状态 (event.button) 等等。\n例如:\n// 点击事件\nbtn.addEventListener('click', () => {\n console.log('Button clicked');\n})\n \n// 移动事件\nwindow.addEventListener('mousemove', (event) => {\n console.log('鼠标坐标:' + event.clientX + ', ' + event.clientY); \n})\n键盘事件\n常见的键盘事件:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n事件类型描述示例keydown当用户按下键盘按键时触发。window.addEventListener('keydown', myFunction)keyup当用户释放键盘按键时触发。window.addEventListener('keyup', myFunction)keypress当用户按下并释放键盘按键时触发。window.addEventListener('keypress', myFunction)\n在这些事件处理程序中你可以使用 event 对象来访问事件的相关信息,例如:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n属性描述示例event.key返回被按下的键的字符。let key = event.keyevent.code返回被按下的物理键的代码。let code = event.codeevent.altKey如果 Alt 键被按下时返回 true否则返回 false。let altKeyPressed = event.altKeyevent.ctrlKey如果 Ctrl 键被按下时返回 true否则返回 false。let ctrlKeyPressed = event.ctrlKeyevent.shiftKey如果 Shift 键被按下时返回 true否则返回 false。let shiftKeyPressed = event.shiftKeyevent.metaKey如果 Meta 键(在 Windows 键盘上通常是 Windows 键,在 Apple 键盘上通常是 Command 键)被按下时返回 true否则返回 false。let metaKeyPressed = event.metaKey\n请注意键盘事件通常在 window 对象上监听,而不是特定的元素上,因为键盘输入通常是全局的。例如:\n// 按下任意键时打印\ndocument.addEventListener('keydown', (event) => {\n console.log('Pressed key: ' + event.key);\n});\n其他事件\n还有一些其他常用的事件:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n事件类型描述示例load当页面完全加载后包括所有图像、脚本文件、CSS 文件等触发。window.addEventListener('load', myFunction)unload当页面即将被卸载或关闭时触发。window.addEventListener('unload', myFunction)beforeunload当窗口即将卸载新的页面时触发。这个事件可以用来提示用户是否真的要离开当前页面例如如果有未保存的更改。window.addEventListener('beforeunload', myFunction)resize当浏览器窗口被调整大小时触发。window.addEventListener('resize', myFunction)scroll当用户滚动指定的元素或页面时触发。window.addEventListener('scroll', myFunction)focus当元素获得焦点时触发。element.addEventListener('focus', myFunction)blur当元素失去焦点时触发。element.addEventListener('blur', myFunction)input当 <input>、<select> 或 <textarea> 元素的值改变时触发。element.addEventListener('input', myFunction)change当用户改变 <input>、<select> 或 <textarea> 元素的值并且失去焦点时触发。element.addEventListener('change', myFunction)submit当表单提交时触发。element.addEventListener('submit', myFunction)touchstart当用户触摸屏幕时触发。element.addEventListener('touchstart', myFunction)touchmove当用户在屏幕上移动触摸点时触发。element.addEventListener('touchmove', myFunction)touchend当用户停止触摸屏幕时触发。element.addEventListener('touchend', myFunction)\n这只是可能发生的事件类型的一部分。实际上HTML DOM API 定义了很多不同的事件类型,可以用来处理各种各样的用户交互和页面生命周期事件。\nES6+ 新特性\nES6 开始 JavaScript 引入了许多新特性,极大地丰富了语言本身。\nLet 和 Const\n\nlet 声明的变量有块级作用域,这意味着 let 声明的变量只在其声明的块或子块中可用,而在外部不可访问。这与 var 不同var 声明的变量是函数作用域或全局作用域。\nconst 声明的是不可修改的常量一旦声明其值就不能改变。这并不意味着它指向的对象不可改变例如const 声明的对象,我们仍然可以修改其属性。\n\n箭头函数\n箭头函数提供了一种更简洁的函数定义方式它有几个特点\n\n更简洁的语法\n不绑定自己的 this它会捕获其所在的上下文的 this 值作为自己的 this 值\n没有 arguments 对象,如果你需要类似的功能,可以使用 rest 参数代替\n不能作为构造函数也就是说不能使用 new 命令\n\n// 传统函数\nfunction add(a, b) {\n return a + b;\n}\n \n// 箭头函数\nconst add = (a, b) => a + b; \n模板字符串\n模板字符串使用反引号 (“),可以内嵌变量和表达式,也支持多行字符串。\nconst name = 'John';\nconsole.log(`Hello ${name}!`) // Hello John!\n对象解构\n对象解构允许我们从对象中提取属性作为变量这使得从对象中获取数据变得非常方便。解构也可以用于数组可以让我们更快速地获取数组中的元素。\nconst person = {\n name: 'John',\n age: 20\n};\n \n// 解构\nconst { name, age } = person; \n模块化\nES6 引入了模块化的概念,可以使用 import 和 export 实现模块的导入和导出。这个特性使得 JavaScript 代码更加模块化,便于组织和管理。\n// foo.js\nexport const name = 'John';\n \n// main.js\nimport { name } from './foo.js';\n等等众多特性,极大地推动了 JavaScript 的发展。\n异步编程\nJavaScript 的异步编程主要基于 Promise 和 async/await。\nPromise\nPromise 是 JavaScript 中处理异步操作的一种方式是一种代表未来将要发生事件的对象。Promise 有三种状态pending进行中、fulfilled已成功和 rejected已失败。Promise 的状态一旦改变,就不会再变。\nPromise 可以链式调用,这意味着我们可以在一个 Promise 完成后,返回一个新的 Promise这使得我们可以以同步的方式编写异步代码。\nfunction fetchData() {\n return new Promise((resolve, reject) => {\n // 异步操作\n setTimeout(() => {\n const data = 'Hello World';\n resolve(data); \n }, 3000);\n });\n}\n \nfetchData().then(data => {\n // 成功时调用\n console.log(data);\n});\nasync/await\nasync/await 是基于 Promise 实现的,它是一种更人性化的处理异步的方式。它让异步代码看起来更像同步代码,大大提高了代码的可读性和可维护性。\n// 用 async 声明一个异步函数\nasync function fetchData() {\n // 使用 await 获取 Promise 的结果\n const data = await new Promise((resolve) => {\n setTimeout(() => {\n resolve('Hello World');\n }, 3000);\n });\n \n return data;\n}\n \n// 调用异步函数\nfetchData().then(data => {\n console.log(data); \n});\n使用 async 关键字声明的函数称为异步函数,它会隐式返回一个 Promise。await 关键字可以用于等待一个 Promise 完成并获取其结果。注意await 关键字只能在 async 函数内部使用。\nasync/await 与 Promise 一样,有很好的错误处理机制。我们可以使用 try…catch 语句来捕获和处理 Promise 中发生的错误。"},"Technology/WebDevelopment/7.Tools/PM2-工具":{"title":"PM2 工具","links":[],"tags":["FullStack/工具"],"content":"简介\nPM2 是一个卓越的 Node.js 进程管理工具,它可以帮助我们简化 Node.js 应用程序的管理和部署。通过 PM2我们可以实现自动重启、负载均衡、性能监控以及日志管理等功能大大提高应用程序的稳定性和可靠性。\n安装\n安装 PM2 非常简单,只需执行以下命令即可:\nnpm install -g pm2\n这将全局安装 PM2使其可以在命令行中直接使用。\n管理\n目录结构\n安装 PM2 后,它会自动创建一些目录,这些目录对于管理和运行应用程序非常重要。以下是这些目录的简要介绍:\n\n$HOME/.pm2包含所有与 PM2 相关的文件。\n$HOME/.pm2/logs包含所有应用程序的日志文件。\n$HOME/.pm2/pids包含所有应用程序的进程 ID 文件。\n$HOME/.pm2/pm2.logPM2 的日志文件。\n$HOME/.pm2/pm2.pidPM2 的进程 ID 文件。\n$HOME/.pm2/rpc.sock用于远程命令的 Socket 文件。\n$HOME/.pm2/pub.sock用于发布事件的 Socket 文件。\n$HOME/.pm2/conf.jsPM2 的配置文件。\n\n常用命令\nPM2 提供了许多常用的命令,用于管理和操作应用程序。以下是一些常用的命令及其说明:\n\npm2 start app.js启动一个应用程序。\npm2 restart app.js重启一个应用程序。\npm2 stop app.js停止一个应用程序。\npm2 delete app.js删除一个应用程序。\npm2 list/l/ls查看所有运行中的应用程序的状态和详细信息。\npm2 describe app.js查看特定应用程序的详细信息。\npm2 logs显示所有应用程序的日志。\npm2 monit启动一个终端仪表板显示每个应用程序的 CPU 和内存使用情况。\n\n使用\n监听文件\n使用 PM2您可以轻松地监听应用程序目录中的文件变化并在文件发生更改时自动重启应用程序。只需在启动应用程序时添加 —watch 参数即可,例如:\npm2 start app.js --watch\n这将使 PM2 监视 app.js 文件的变化,并在文件发生更改时自动重启应用程序。\n负载均衡\nPM2 还支持负载均衡功能,可以根据需要启动多个应用程序实例。您可以使用以下命令启动多个实例:\npm2 start app.js -i <instances>\n将 instances 替换为您要启动的实例数。如果将 instances 设置为 0 或 max则 PM2 将根据系统的 CPU 核心数自动确定实例数。\n配置文件\nPM2 还支持使用配置文件来管理应用程序。您可以创建一个 JSON 或 YAML 格式的配置文件,并在启动应用程序时指定该配置文件。配置文件可以包含应用程序的名称、启动脚本、环境变量等信息。以下是一个示例配置文件的结构:\n{\n "name": "my-app",\n "script": "app.js",\n "env": {\n "NODE_ENV": "production"\n }\n}\n您可以使用以下命令启动应用程序并指定配置文件\npm2 start my-config.json\n将 my-config.json 替换为您的配置文件路径。\nPM2 是一个功能强大的 Node.js 进程管理工具,它可以帮助您简化应用程序的管理和部署。\n日志管理\nPM2 默认会捕获并记录应用程序的 STDOUT 和 STDERR 输出,并将其存储在 $HOME/.pm2/logs 目录下。你可以使用 pm2 logs 命令来查看这些日志。\n此外PM2 还提供了一些高级功能,如日志切割,你可以使用 pm2 install pm2-logrotate 命令来安装日志切割模块,这对于日志管理非常有用。\n性能监控\nPM2 还提供了一个内置的模块系统,可以安装各种模块来增强 PM2 的功能。其中,一个非常有用的模块是 pm2-monitoring它可以提供应用程序的性能监控功能。只需执行 pm2 install pm2-monitoring 命令,就可以启用该功能。\n此外PM2 还有一个叫做 Keymetrics 的云端平台它提供了一整套的应用程序性能管理APM功能包括实时监控、CPU/内存使用情况、HTTP 交易等。\n结论\nPM2 是一个功能强大的 Node.js 进程管理工具它可以帮助你简化应用程序的管理和部署提高应用程序的稳定性和可靠性。不论是在开发环境还是在生产环境PM2 都是管理 Node.js 应用程序的理想选择。"},"Technology/WebDevelopment/7.Tools/Webpack":{"title":"Webpack","links":[],"tags":["FullStack/工具"],"content":"Webpack 是一个开源的 JavaScript 模块打包器。它是构建现代 JavaScript 应用程序的一个重要工具,用于将项目的不同部分(包括 JS、HTML、CSS、图片等资源打包成一个或多个优化后的文件供浏览器加载和执行。\n历史\nWebpack 是一个强大的静态模块打包器,它在 2012 年末由 Tobias Koppers 发布。在 Webpack 出现之前,开发者使用 Browserify、RequireJS 等工具来解决 JavaScript 代码模块化的问题。\nWebpack 1.0 在 2014 年发布提供了诸如“loaders”和“plugins”的新特性。2016 年Webpack 2.0 发布,其主要更新包括对 ES6 模块的支持、Tree shaking 和动态导入。\n2018 年Webpack 4.0 发布,带来了更快的编译速度和更小的 bundle 大小同时提供了“零配置”选项。2020 年Webpack 5.0 发布,引入了许多新特性,包括对持久缓存的改进,模块联邦,以及对 Webassembly 的更好支持。\n背景\n在 Webpack 出现之前开发者通常需要手动管理项目中的所有文件和依赖。随着项目的复杂性增加这种方式变得越来越困难。Webpack 通过自动处理和打包项目中的各种资源和依赖极大地简化了开发的复杂性。此外Webpack 还提供了许多优化机制,如代码分割和懒加载,以改进应用的性能。\n特性\n\n代码分割Code SplittingWebpack 可以将代码分割成多个 bundle从而实现按需加载和并行加载。\n懒加载Lazy LoadingWebpack 支持懒加载,即按需加载某个模块,可以有效地减少应用的初始加载时间。\n模块热替换Hot Module ReplacementHMRWebpack 支持 HMR可以在运行时替换、添加或删除模块而无需进行完全刷新。\nLoadersWebpack 使用 loaders 来处理非 JavaScript 类型的文件,如 CSS、HTML、图片等。\nPluginsWebpack 使用 plugins 来添加额外的功能,如优化 bundle、管理输出和环境变量等。\n\n优点\n\nWebpack 提供了高度的灵活性和可配置性,可以满足各种项目的需求。\nWebpack 支持多种类型的模块和资源,包括 ES6 模块、CommonJS 模块、CSS、图片、字体等。\nWebpack 提供了许多优化机制,如代码分割、懒加载、持久缓存等,可以改进应用的性能。\n\n缺点\n\nWebpack 的配置相对复杂,需要一些学习和实践。\nWebpack 的构建速度可能在大型项目中变得较慢。\nWebpack 目前只支持 JavaScript 和 JSON对其他语言的支持需要通过 loaders 和 plugins 实现。\n\n实用示例\n官网指南\n与其他工具的对比\nWebpack 的主要竞争者包括 Parcel、Rollup 和 Browserify。\n\nParcel 提供了零配置的体验对于小型项目和入门级项目来说Parcel 可能是一个更好的选择。但是对于需要高度自定义的大型项目Webpack 的灵活性和可配置性可能更胜一筹。\nRollup 主要专注于 JavaScript 库和框架的打包,它提供了更好的 tree shaking 和 ES6 模块的处理。但是对于一般的应用项目Webpack 提供的特性更多,如代码分割和懒加载。\nBrowserify 是最早的模块打包器之一,它允许开发者在浏览器中使用 CommonJS 模块。然而Browserify 的功能相对有限,且没有得到很好的维护和更新。\n\n未来发展方向\nWebpack 的未来发展方向可能包括以下几点:\n\n更好的性能Webpack 会继续优化其构建速度和生成的代码质量,以提供更好的性能。\n更好的兼容性Webpack 会支持更多的模块类型和语言,以提供更好的兼容性。\n更好的可用性Webpack 会改进其文档和错误消息,以提供更好的可用性。\n更好的插件生态Webpack 会继续扩大其插件生态,以提供更多的功能和选择。\n\n总的来说Webpack 是前端开发工具链中的一个重要组成部分。尽管有一些竞争者试图挑战其地位但是由于其强大的功能、灵活的配置和丰富的插件Webpack 仍然是目前最受欢迎和最广泛使用的模块打包器之一。"},"Technology/WebDevelopment/7.Tools/包管理工具":{"title":"包管理器","links":[],"tags":["FullStack/工具"],"content":"Npm\nnpm 是 JavaScript 编写的软件包管理工具,同时也是 node.js 的默认包管理工具。\n早期版本\n因为早期 npm 版本采用嵌套结构,所以存在依赖地狱和存储空间占用过大问题;同时 Windows 环境下路径限制 256 字符,可能会导致运行出错。\n\nV3 版本\nV3 版本采用扁平结构来避免过深的依赖树和包冗余,子依赖会尽量平铺在主依赖所在的目录中(同一包但版本号不同还是会放至子目录中)。\nnode_modules\n├── A@1.0.0\n├── B@1.0.0\n└── C@1.0.0\n └── node_modules\n └── B@2.0.0\n虽然解决了依赖地狱的问题但是又形成了新的问题。\n幽灵依赖\n幽灵依赖是指在 package.json 中未定义的依赖,但项目中依然可以正确地被引用到。\n{\n "dependencies": {\n "A": "^1.0.0",\n "C": "^1.0.0"\n }\n}\n例如我们只安装了 A 和 C虽然 A 引用了 B但是因为平铺在同一目录所以在项目中引用 B 还是可以正常工作的。将来如果某个版本的 A 依赖不再依赖 B 或者 B 的版本发生了变化,那么就会造成依赖缺失或兼容性问题。\n不确定性\nnode_modules\n├── A@1.0.0\n├── B@1.0.0\n└── C@1.0.0\n └── node_modules\n └── B@2.0.0\nnode_modules\n├── A@1.0.0\n│ └── node_modules\n│ └── B@1.0.0\n├── B@2.0.0\n└── C@1.0.0\n不确定性是指同样的 package.json 文件install 依赖后可能不会得到同样的 node_modules 目录结构。如果 A 依赖 B@1.0C 依赖 B@2.0;依赖安装后究竟该提升 B 为 1.0 还是 2.0 取决于用户的安装顺序。\n依赖分身\n假设继续再安装依赖 B@1.0 的 D 模块和依赖 @B2.0 的 E 模块此时A 和 D 依赖 B@1.0C 和 E 依赖 B@2.0。\nnode_modules\n├── A@1.0.0\n├── B@1.0.0\n├── D@1.0.0\n├── C@1.0.0\n│ └── node_modules\n│ └── B@2.0.0\n└── E@1.0.0\n └── node_modules\n └── B@2.0.0\n可以看到 B@2.0 会被安装两次,实际上无论提升 B@1.0 还是 B@2.0,都会存在重复版本的 B 被安装,这两个重复安装的 B 就叫依赖分身。\n安装方式\n可以通过 node.js 官网 下载安装,或者直接使用如下脚本。\ncurl -qL www.npmjs.com/install.sh | sh\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能npm help帮助文档npm -vnpm 版本npm config list -lnpm 配置npm init初始化引导创建 package.json 文件npm set <变量名> <值>设置环境变量npm search <关键词> [-g]检索模块npm list局部查看模块npm list -g —depth 0全局安装的模块目录深度为 0。npm install读取 package.json 安装模块npm uninstall <模块> [-g]卸载局部模块或全局模块npm update <模块> [-g]升级局部模块或全局的指定模块npm run <脚本>运行 package.json 脚本\nYarn\nyarn 同样采用扁平结构,它的出现是为了解决 npm V3 依赖安装速度慢和不确定性。\n提升安装速度\nyarn 采用并行模式替代 npm 串行模式安装包,并且利用全局缓存可以提升较大安装速度。\nLockfile 解决不确定性\n安装依赖时根据 package.josn 生成一份 yarn.lock 文件。因为 lockfile 里记录了依赖,以及依赖的子依赖、依赖的版本、获取地址、验证模块完整性的 hash所以即使是不同的安装顺序相同的依赖关系在任何的环境和容器中都能得到统一的 node_modules 目录结构,保证了依赖安装的确定性。\nnpm v5 才发布 package-lock.json。\n存在的问题\n因为 yarn 和 npm 一样是扁平结构的 node_modules ,所以并没有解决幽灵依赖和依赖分身问题。\n安装方式\nnpm install --global yarn\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能yarn help帮助文档yarn init初始化项目yarn install安装所有依赖项yarn add [package]安装指定依赖项yarn add [package]@[version | tag]安装指定版本依赖yarn up [package]升级指定依赖yarn up [package]@[version | tag]升级指定版本依赖yarn remove [package]删除指定依赖\nPnpm\n\npnpm 不同于 npm 和 yarn 使用的扁平结构而是采用了内容寻址存储。pnpm 通过设置全局 store然后在项目中通过使用硬链接与符号链接引用依赖。为了实现此功能node_modules 目录下会多出 .pnpm 目录,而且是非扁平结构。\n\n硬链接 Hard link硬链接可以理解为源文件的副本。\n符号链接 Symbolic link符号链接软连接可以理解为快捷方式。\n\n<store>/xxx 开头的路径是硬链接,指向全局 store 中安装的依赖。其余的是符号链接,指向依赖的快捷方式。\n \nnode_modules\n├── .pnpm\n│ ├── A@1.0.0\n│ │ └── node_modules\n│ │ ├── A => <store>/A@1.0.0\n│ │ └── B => ../../B@1.0.0\n│ ├── B@1.0.0\n│ │ └── node_modules\n│ │ └── B => <store>/B@1.0.0\n│ ├── B@2.0.0\n│ │ └── node_modules\n│ │ └── B => <store>/B@2.0.0\n│ └── C@1.0.0\n│ └── node_modules\n│ ├── C => <store>/C@1.0.0\n│ └── B => ../../B@2.0.0\n│\n├── A => .pnpm/A@1.0.0/node_modules/A\n└── C => .pnpm/C@1.0.0/node_modules/C\n未来可期\npnpm 这套全新的机制设计地十分巧妙,不仅兼容 node 的依赖解析,同时也解决了如下问题:\n\n\n幽灵依赖只有直接依赖会平铺在 node_modules 下,子依赖不会被提升,不会产生幽灵依赖。\n\n\n依赖分身相同的依赖只会在全局 store 中安装一次。项目中的都是源文件的副本,几乎不占用任何空间,没有了依赖分身。\n\n\n同时由于链接的优势pnpm 的安装速度在大多数场景比 npm 和 yarn 快 2 倍,同时也节省更多的磁盘空间。但也存在一些弊端:\n\n\n因为 pnpm 创建的 node_modules 依赖软链接,所以在不支持软链接的环境中无法使用 pnpm比如 Electron 应用。\n\n\n因为依赖源文件是安装在 store 中,调试依赖或 patch-package 给依赖打补丁也不太方便,可能会影响其他项目。\n\n\n安装方式\nNpm\nnpm install -g pnpm\nCurl\ncurl -fsSL get.pnpm.io/install.sh | sh -\n常用命令\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n命令功能pnpm install安装 package.json 文件中的所有依赖项pnpm add <pkg>安装指定的依赖项pnpm update更新所有的依赖项pnpm uninstall移除指定的依赖项pnpm list列出已安装的所有依赖项pnpm run运行在 package.json 文件中定义的脚本pnpm test运行测试pnpm link创建或者删除一个软链接到全局安装的依赖项pnpm prune移除无用的依赖项pnpm publish将你的包发布到 npm 注册表pnpm root打印全局安装的依赖项的位置pnpm store控制共享的包存储pnpm outdated检查哪些依赖项有新版本可以更新pnpm rebuild重新编译包pnpm import从 npm 转换一个项目pnpm fetch预下载所有从注册表下载的依赖项到本地的存储库pnpm audit检查项目依赖项中的已知的漏洞\nnpmyarnpnpm 功能比较\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n功能pnpmYarnnpm工作空间支持monorepo隔离的 node_modules✔ - 默认✔️❌提升的 node_modules✔ - 默认自动安装 peers✔ - 通过 auto-install-peers=true❌✔PlugnPlay✔ - 默认❌零安装❌✔️❌修补依赖项✔️✔️❌管理 Node.js 版本✔️❌❌有锁文件✔️ - pnpm-lock.yaml✔ - yarn.lock✔ - package-lock.json支持覆盖✔ - 通过 resolutions✔内容可寻址存储✔❌❌动态包执行✔ - 通过 pnpm dlx✔ - 通过 yarn dlx✔ - 通过 npxSide-effects cache✔❌❌"},"index":{"title":"数字花园","links":[],"tags":[],"content":"\nAlways For Freedom.\n\n一个喜欢异想天开的家伙 💨\n在这里记录知识希望对你也有帮助。\n目录\nWiki\n├── Life\n├── NaturalSciences\n├── Obsidian\n│   ├── Canvas\n│   ├── Static\n│   └── Templates\n├── Personal\n│   ├── Blog\n│   ├── Book\n│   ├── Journal\n│   └── Writing\n├── Photography\n├── Professional\n│   ├── Company\n│   └── Work\n├── SocialSciences\n│   ├── English\n│   └── Government\n└── Technology\n ├── CloudService\n ├── ComputerNetwork\n ├── ComputerSecurity\n ├── ComputerStorage\n ├── DatabaseSystem\n ├── GettingStarted\n ├── OperatingSystem\n ├── ProgrammingLanguage\n ├── SoftwareEngineering\n └── StructuresAlgorithms\n分支\nMain 主分支\n└─ dev 日常分支\n贡献\n欢迎各位提供指导纠错。\n协议\n\n\n所有原创代码采用 GPL-3.0 协议,原创非代码内容采用 署名-相同方式共享 4.0 国际。\n\n\n所有引用第三方内容仅为学术使用。其所属著作权、版权均归原作者所有如有冒犯侵权请 邮件联系 删除。\n\n\n致谢\n感谢第三方原创作者的无私贡献"}}