1 line
4.2 MiB
1 line
4.2 MiB
{"Obsidian/Templates/博客模板":{"title":"标题","links":[],"tags":["标签"],"content":""},"Obsidian/Templates/文档模板":{"title":"标题","links":[],"tags":["标签"],"content":""},"Obsidian/Templates/日志---周记模板":{"title":"日志 - 周记模板","links":[],"tags":[],"content":"🗓️ Info §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon<% tp.date.now(“ddd HH:mm”) %><% tp.web.lunar_date() %><% tp.web.weather(“郑州”, “units=m&format=%l+%t+%c&lang=zh”) %><% tp.web.weather(“郑州”, “format=%m&lang=zh”) %>\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 recordsExercise logSleep logHydrationMental Relaxation\n✅ What Went Well §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTask/ActivityProgressDescription[项目名称/任务名称][进行中/已完成][描述]\n❌ What Didn’t 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\nTask/ActivityTime Allocation[项目名称/任务名称]⏲️\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📊 ThisWeek’s Overview §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nScore (1-10)Self EvaluationFeedback from Others"},"Obsidian/Templates/日志---季度模板":{"title":"日志 - 季度模板","links":[],"tags":[],"content":"📆 Info §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon<% tp.date.now(“ddd HH:mm”) %><% tp.web.lunar_date() %><% tp.web.weather(“郑州”, “units=m&format=%l+%t+%c&lang=zh”) %><% tp.web.weather(“郑州”, “format=%m&lang=zh”) %>\n🌟 Overview §\n🏠 Life §\n😊 Emotions §\n🍎 Health §\n👪 Family §\n🎨 Hobbies §\n🏡 Home §\n🌈 Social §\n🌍 Travel §\n📚 Learning §\n📖 Self-Reading §\n🎓 School Education §\n🎨 Creative Arts §\n🗣️ Public Speaking §\n🎲 Gaming §\n💼 Work §\n💻 Technical Research §\n📈 Business Development §\n🏦 Human Resources §\n📊 Data Analysis §\n📝 Document §\n📢 Public Relations §\n📩 Customer Service §\n💰 Big Finance §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n支出项描述金额\n🔥 Challenges §\n🌱 Personal Growth §\n💼 Work and Career §\n🎓 Learning and Academics §\n👪 Family and Intimate Relationships §\n💰 Finance and Economics §\n🍎 Health and Fitness §\n🌍 Society and Culture §\n🚀 Technology and Innovation §\n💡 Lessons Learned §\n👊 Next Steps §\n📈 Evaluation §\n📊 Appendix §"},"Obsidian/Templates/日志---日记模板":{"title":"日志 - 日记模板","links":[],"tags":[],"content":"📅 Info §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDateLunarWeatherMoon<% tp.date.now(“ddd HH:mm”) %><% tp.web.lunar_date() %><% tp.web.weather(“郑州”, “units=m&format=%l+%t+%c&lang=zh”) %><% tp.web.weather(“郑州”, “format=%m&lang=zh”) %>\n📖 Daily §\n<% tp.web.today_poetry() %>\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📝 Notes §"},"Obsidian/Templates/阅读模板":{"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\n\n\n\n\n\n\n评价豆瓣微信读书自我点评评分人数"},"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网址:http://ccaeo.com\n注册页面:http://ccaeo.com/free-hosting-signup.php\n技术支持:http://www.mizuiren.com\n技术教程:http://www.mizuiren.com/10.html\n原博主也有注册教程,大家多多支持!\n注册 §\n根据提示注册,务必想好域名前缀。因为注册后不可更改!注册信息,例如用户名,密码等等,在注册成功后会发送到邮箱一份!其他选项默认即可!\n\n注册成功后显示的页面,如果接收不到邮件可以点蓝色链接,重新发送一次。\n\n邮箱激活,点击链接激活。如果无法点击复制到浏览器地址栏访问。\n\n激活页面,不要关闭。等待激活成功!\n\n激活成功\n\n相关信息会发送到邮箱!\n\n到此,账户已经注册成功!域名已经可以访问初始页面!\n网址:http://zhou20181031.ccaeo.com\n部署网站 §\n了解过相关知识就知道,创建一个网站需要网站程序和数据库,类似于 Wordpress,Discuz,以及我使用的 Typecho 简称网站程序吧,一时间也想不起来术语了。这些都是开源的!这次我创建一个 Typecho 的博客,其他的也类似!首先下载博客主程序。\n网址:http://typecho.org/\n下载地址:http://typecho.org/downloads/1.1-17.10.30-release.tar.gz\n下载好文件,解压如下\n\n然后登陆网站后台,创建一个数据库。\n后台网址:http://cpanel.ccaeo.com\n账户以及密码信息,邮箱文件都有。语言选择简体中文。\n\n第一次出现这个页面,点击我同意即可!\n\n进入网站后台主页面\n\n第一次进入 phpMyAdmin 需要创建一个数据库。\n\n然后创建数据库,填写数据库名字。\n\n创建成功后会显示数据库信息。这里数据库信息是博客安装必须要用的!\n\n数据库到这一步已经创建成功!然后用 FTP 工具上传博客主程序。\nFTP 工具:https://www.smartftp.com/download\n\n登陆成功以后,按照图片操作。\n\n上传速度比较慢,耐心等待一下。等待上传完成!\n\n上传成功以后,打开自己的网站地址开始安装!\n\n\n博客网站管理员信息\n\n\n安装成功 §\n\n这一步网站就已经安装成功了!写的有点仓促,有什么笔误大家可以留言,关联微信了实时收到!多多留言支持!不介意给个赞助哈哈哈哈哈哈哈!\n网址:http://zhou20181031.ccaeo.com(2022.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":"饥荒(Don’t 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链接:[原文地址][https://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 知识。\nCPU:Intel 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配置清单:\nCPU:Intel 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 多,性能方面基本满足了我的需求。室友开黑,敲代码啊,没错全靠它了!这台电脑没有用的特别久,因为什么?你看看下面的标题就知道了!\nAMD,Yes §\n装机圈的朋友应该都知道「i3 默秒全」「一核有难、八核围观」这些埂,不懂得请自行百度哈哈,因为讲不完。\n2017 年 AMD Ryzen 横空出世,瞬间 AMD 真香,AMD Yes!我当时配第一台电脑得时候就很想配 AMD 的电脑,奈何荷包不足。只能 i3 8100 将就一下了,后来因特尔鬼才营销,将 i3 8100 推到 800 元以上。然后我就把 CPU 主板卖了,还小赚了一笔。\n锐龙一代存在一些小东小西的问题,以及二代的推出,导致后来价格迅速跌落至 900 元左右。是的,没错!八核十六线程主频 3.0 还可以超频,想啥呢?赶紧上车!\n配置清单:\nCPU:AMD 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][https://opensource.org/licenses/Apache-2.0 ]\n[BSD 许可证 3-Clause][https://opensource.org/licenses/BSD-3-Clause]\n[BSD 许可证 2-Clause][https://opensource.org/licenses/BSD-2-Clause]\n[GUN 通用公共许可证(简称 GPL)][https://opensource.org/licenses/gpl-license]\n[GUN 宽通用公共许可证(简称 LGPL)][https://opensource.org/licenses/lgpl-license]\n[MIT 许可证][https://opensource.org/licenses/MIT]\n[Mozilla 公共许可证 2.0(简称 MPL)][https://opensource.org/licenses/MPL-2.0]\n[通用开发和发布许可证 1.0(简称 CDDL)][https://opensource.org/licenses/CDDL-1.0]\n[Eclipse 公共许可证 2.0(简称 EPL)][https://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地址:https://www.jianshu.com/p/a79de84e949f\n图片《乌合麒麟作品集》\n作者:乌合麒麟\n地址:https://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 到 l,m 甚至有的衣服款式 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":"作为宇宙第二 IDE:Jetbrains,业内很多 ITer 肯定都了解一二。不过相对于宇宙第一 VS,Jetbrains 严格的正版授权和高昂的售价,让很多人望而却步。不过也肯定有不少细心的小伙伴发现了,如果你拥有一个开源项目便可以申请 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配置清单:\nCPU:AMD 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在线:7Wate’s blog\n\n\n主要功能 §\n\n专注阅读写作设计\n深 / 浅色自适应模式\n全尺寸布局媒体自适应\nMarkdown 样式设计\n社交链接展示\n支持独立页面\n\n安装方法 §\n\n远程拉取:https://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:"https://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 首发版 - 7Wate‘s blog;非商业引用,著作权归作者所有。\n"},"Personal/Blog/2022/Hello-Halo":{"title":"Hello Halo","links":[],"tags":["博客/原创"],"content":"Hello Halo §\n如果你看到了这一篇文章,那么证明你已经安装成功了,感谢使用 Halo 进行创作,希望能够使用愉快。\n相关链接 §\n\n官网:https://halo.run\n文档:https://docs.halo.run\n社区:https://bbs.halo.run\n主题仓库:https://halo.run/themes.html\n开源地址:https://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项目地址:https://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="https://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="https://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客观感觉确实有较大的吻合,感兴趣的也可以去测试一下 ~\nhttps://www.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当下个人知识的整理归纳已经及其重要了,废话不多说。可以先体验一下我的个人 wiki:https://wiki.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 "https://wiki.7wate.com/"\t\t\t\t\t# wiki 网址\n ],\n "sitemap_urls": [\n "https://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\n7:40 起床洗漱\n8:00 公司食堂早餐\n8:30 打卡\n8:30 - 10:00 阅读 RSS 订阅,浏览各大友博,看看 B 站的更新,欣赏一下别人的摄影作品。\n10:30 看完就会错点去打水,冲咖啡,泡茶喝\n10:30 - 12:30 昨天剩下的事情忙一下,同事聊聊天,随便逛逛,饿了会去小卖铺买吃的,当然带薪拉屎是一定的嘿嘿嘿,不过还是会做一个 todolist,明确一下下午要忙的事情。\n12:30 - 13:00 下班不积极,脑壳有问题 ~ 打卡吃饭!\n13:00 - 13:30 回宿舍刷抖音,睡觉前看一些搞笑抖音哈哈\n13:50 起床打卡上班\n14:00 - 17:00 主要以工作和学习为主,打工人嘛,累了该摸鱼摸鱼。\n17:00 - 18:00 讨论一下晚上吃啥,下班干啥(疫情哪都去不了)\n18:00 - 19:00 食堂的饭好吃不好吃,都会很认真的吃一顿。\n19:00 - 21:00 学习,刷课,撸代码,因为没人打扰,所以可以做一些需要专注的事情\n21:00 - 22:00 回宿舍撸铁,嗨歌,洗漱,冲澡\n22:00 - 23:30 刷韩剧,首先明确一下。我是一个很直很直的男生哈哈,但是韩剧真的好甜 😍\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 Machine,CVM) 提供安全可靠的弹性计算服务。 可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 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非必要需求,建议买国外。 云服务器相同配置情况下,境内境外服务器性能无明显差距,主要还是网络访问。境内云服务器访问一些网站,例如 github,dockerhub 等等太慢了,甚至是无法访问。并且可能会因为网络问题产生各种意外的错误。国外服务器还可以免备案域名绑定,同时带宽也相对较高,实际体验速度也不比国内慢太夸张。\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 Name,Domain),简称域名、网域,是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位。域名可以说是一个 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中国互联网域名体系:https://domain.miit.gov.cn/\n\n域名续费多久的好? §\n域名续费 8 年时间最好。 活动的时候会有折扣,然后就想着直接续费 10 年。在此忠告尽量不要续费 10 年,因为如果未来有转移域名的需求,你可能就要等一年或者两年才可以了。因为转移域名大部分情况必须在域名接收服务商再续费一年,所以域名续费 8 年时间最好。\n哪里购买域名有优惠? §\n谷歌域名购买选择土耳其地区付款。 我买了 8 年 org 域名,仅仅花费 200+,真的白捡似的。例如 .xyz 域名 10 年也才百十来块钱,所以冲啊!买垮谷歌域名!!!\n\n谷歌域名地址:https://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 并改名为 sonic;sonic 相对于 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 §\nRSS(RDF 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密码管理器这个范畴太大了,我平时用的最多的就是管理各个网站的密码,登录的时候一键填充密码服务。现在国外成立的 FIDO(Fast 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我相信版本控制的概念很多人都已经接触了,例如大名鼎鼎的 Git,SVN 等。社区托管服务中 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 System,DNS)是互联网的一项服务。它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。其实 DNS 的作用非常简单,就是根据域名找到对应的 IP 地址。你可以把它想象成一本巨大的电话本。\n基于天朝的国情,DNS 存在不同程度的污染情况以及法律法规的约束。例如前阵子 github 的 IP 地址被解析为天朝反诈骗中心、私自搭建公开 DNS 服务器更是违法行为。你想想,你带着老婆,坐着火车吃着火锅唱着歌。突然想给黄四郎打个电话,却被麻匪接到了。自建 DNS 就可以完美地解决这个问题。\nAdGuard Home §\nAdGuard Home 是一款用于拦截广告和跟踪的全网软件。设置完成后,它将覆盖您所有的家庭设备,您不需要为此安装任何客户端软件。随着物联网和连接设备的兴起,能够控制整个网络变得越来越重要。AdGuard Home 中提供了自定义 DNS 上游服务器以及 DNS 改写的功能,其他类似功能的软件可以达到同样的效果。\nAdGuard Home 以及其他类似功能的应用部署场景应该局限于家庭网络、局域网络,切记非必要勿公开。下面是推荐的上游 DNS 服务器:\n# 加密 DNS-over-TLS\nhttps://dns.alidns.com/dns-query\nhttps://doh.pub/dns-query\nhttps://dns.google/dns-query\nhttps://dns.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\nhttps://tagss.pro/(官网)\nhttps://tagss.pro#/register?invite=WB9TeKhc(推广链接)\n# WgetCloud\nwgetcloud.ltd(官网)\nhttps://invite.wgetcloud.ltd/auth/register?code=9GQH(推广链接)\n# Hutao\nhttps://hutao.cloud/(官网)\nhttps://hutao.cloud/auth/register?code=Z2J1(推广链接)\n# RelayCloud\nhttps://relaycloud.pro/(官网)\nhttps://relaycloud.pro/auth/register?code=310d(推广链接)\n# 一元机场\nhttps://一元机场.com/(官网)\nhttps://xn--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 https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)\n \n# Sudo 用户\nsudo bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)\n运行模式 §\n云服务器的操作系统安装完成后,规划合理的运行模式依旧很重要。因为我的目的是应用服务高内聚,低耦合,所以我使用的是容器模式;最常用的就是大名鼎鼎的 Docker。除了容器模式,还有裸机运行模式;同时低门槛上手,文档完善的管理面板就是 宝塔 了。可以结合实际情况来选择,但是我真的不建议用宝塔。🤐🤐🤐\n裸机 §\n裸机模式就是应用服务直接跑在操作系统上,性能利用率高、性能损耗少。但是环境管理难,容易出现莫名其妙的问题而且还不容易找到原因。而且你需要面对黑黑的命令行管理终端,面对新手朋友及其不友好。\n我就曾遇见一个网友学习使用 MySQL,当时他安装了两个版本的 MySQL,端口分别是 3306,3307。然后在数据库管理软件使用的 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当下个人知识的整理归纳已经及其重要了,废话不多说。可以先体验一下我的个人 wiki:https://wiki.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 "https://wiki.7wate.com/" # wiki 网址\n ],\n "sitemap_urls": [\n "https://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 的替代品 CanoKey,CanoKey 的目标是从零开始再造一个 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,是 “GNU’s 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 到 1,1 到 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 种语言的文本校对,包括中文。可以检测拼写、语法、标点符号等错误。 https://www.languagetool.org/\n爱校对:依托清华大学人机交互实验室的技术成果,致力于文字校对,公文校对,论文纠错,文档查错,错别字检查,敏感词检测,错别字筛查校稿。https://www.ijiaodui.com/\nJCJC 错别字在线检测:专注使用人工智能技术应用于文本纠错领域,拥有华为、浪潮、长沙晚报等知名客户。https://www.cuobiezi.net/\n写作猫:AI 写作,文章自动生成。https://xiezuocat.com/\n火龙果:AI 驱动的文字生产力工具。https://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预览地址:https://7wate.github.io/blog23/\nGitHub 地址:https://github.com/7Wate/EndOfYear\nGitee 地址:https://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: https://github.com/my_custom/other-action@v2\n或者通过修改 Gitea 的 app.ini 配置,将下载源指定为相应的仓库:\n[actions]\n# 1.19 可直接填写任意url如:https://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中国居民膳食指南(2022)pdf\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-wine:Debian/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。我也使用 Mac,Mac 的体验确实非常好,但高配置的 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关于我的情况详情见: https://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+ 人,最快 20:00+ 可以坐上缆车(当时早上 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 主页:https://space.bilibili.com/223211771\n丽江:https://www.bilibili.com/video/BV1ER4y1q7ij\n古城:https://www.bilibili.com/video/BV1Ay4y1f7Nf\n川西:https://www.bilibili.com/video/BV1584y1J78R\n日照金山:https://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 进行联动。俗话说,好记性不如烂笔头嘛。\nNews:NextCloud 的 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.com(Dream of night sky),却发现被一家书店注册了。后在于朋友聊天寻找新的域名时,一句无心的玩笑话——你脑子瓦特了吗?整天想这些干嘛,随便找一个不就行了?\n意外地给了我灵感——瓦特,好名字。\n我就立刻去查 wate.com 被注册了没,结果也被人注册了。这时,另一个朋友建议我:要不加个数字试试?于是我选择了 7wate.com,并为之赋予了一个新的概念:「wate」与「瓦特」谐音,那「七瓦特」的功率足以点亮一盏灯泡,其发出的光就可以照亮世界。\n\n实际上,无论是九瓦特,十瓦特,还是一百瓦特,都能点亮一盏灯泡。现在想想真是挺蠢蛋的哈哈。\n\n一开始从「7wate’s 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°30’00”N,113°06’39”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分类: 个人成长-认知思维\nISBN:9787508674421\n出版社:中信出版集团\n\n概述 §\n本书作者综合了近20年科学家与商业对于“习惯学”的研究,包括数百篇学术研究、300多位科学家与企业管理者的访谈,以及数十家企业的实践研究成果,分三个部分探讨了个人的习惯、成功组织的习惯以及社会群体的习惯,作者都希格认为,只要掌握“习惯回路”,学习观察生活中的暗示与奖赏,找到能获得成就感的正确的惯常行为,无论个人、企业,还是社会群体,都能改变根深蒂固的习惯。学会利用“习惯的力量”,就能让人生与事业焕然一新。\n划线 §\n\n她以爱和鼓励教会我如何以合适的语言服务于他人。\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/个人成长/以极简的方式去生活":{"title":"以极简的方式去生活","links":[],"tags":["阅读/个人成长-认知思维","阅读/笔记"],"content":"简介 §\n\n书名:《以极简的方式去生活》\n作者: 杨志华\n分类: 个人成长-认知思维\nISBN:9787518045853\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分类: 个人成长-情绪心灵\nISBN:9787555106425\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分类: 个人成长-认知思维\nISBN:9787111551287\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分类: 个人成长-人生哲学\nISBN:9787111639824\n出版社:机械工业出版社\n\n概述 §\n冥想是一种奇妙的技能,它有改变我们人生的潜力,但是怎样运用这种技能,则取决于你自己。随着媒体对冥想和正念的报道越来越多,许多人似乎急于确定冥想的用途。事实上,你只有确定了如何用它,你才能确定它的用途。在学骑自行车的时候,你所了解的是如何骑车,而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具,有些人用它跟朋友闲逛,还有极少数人可能以它为终身事业。对所有人来说,技能是一样的:安稳地坐在车座上,别掉下来。所以,虽然别人可以教你如何骑车,但骑车对你而言到底意味着什么,你要拿它做什么,以及它怎样才能最符合你的生活方式,这完全取决于你自己。冥想技能也是如此,你可以将它应用到生活中的任何方面,它的价值取决于你赋予它的价值。\n划线 §\n\n你上一次坐下来,安静不动,不分心,不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰,没有任何你需要思考和解决的事情,是什么时候?\n\n\n在正念环境中,冥想不是要去阻止想法、控制心灵。它是一个过程,在这个过程中,我们放弃控制,不插手,不介入,学会以被动的方式集中注意力,同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手,容许心灵以自己的节奏、自己的方式展开,你才能找到真正的头脑空间。\n\n\n你知道,如果你坐上飞机,从那些云的一端穿过,另一端就没有阴云,而只有蓝色的天空了。就算有大片阴沉沉的乌云,蓝色的天空也始终存在。\n\n\n我得到了这样一种理念:天空总是蓝的。云相当于我们的思想,当心灵忙于这些想法的时候,蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何,心灵的深层本质就像蓝色的天空一样,并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候,云会变得更加阴沉,更令人烦扰。也许整个天空中只有那么一个想法,然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走,而是:搬把椅子到花园里,坐看云卷云舒。有时候,蓝色的天空会穿过阴云展露出来,令人备感美好。如果我能耐心地坐在那里,不过分执着于那些阴云,那么蓝色的天空会显露得更多。\n\n\n。最重要的是,你可以想象心中有一片始终宁静、始终澄澈的区域,想象心中有一片你随时都可以依归的地方,想象无论生活中发生什么事,心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事,就指望它突然静静地在某个地方站定!因此,当你跟这匹野马,也就是你的心灵,一起坐下来的时候,你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上,相反,要给你的心灵一点时间,让它安定下来,放松一点。你急什么呢?”\n\n\n关注它的同时,试着温和地将它分享给他人。同样,如果你的注意力集中在令人不快的感受上,那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的,必将浮上来\n\n\n就情感而言,凡是被压制的,必会再浮上来。也许它会突出到表面来,就像情感本身一样,也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央,即一块开放田野的中央。现在,缰绳的一端系着这匹马,另一端在你手里。不过,缰绳是松弛的,这匹马有它所需要的一切空间,它并没有觉得被困住或者受到约束\n\n\n你有没有注意过,当你真正专注于某个事物的时候,你的心灵会变得多么平静?你有没有注意过,即便你的心灵之前还凌乱如麻,但是一旦专注于自己喜欢做的事情,并且全身心地沉浸在那项活动中时,心灵会开始安定下来,会感到非常宁静?\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分类: 个人成长-沟通表达\nISBN:9787308199025\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分类: 个人成长-人生哲学\nISBN:9787111552062\n出版社:机械工业出版社\n\n概述 §\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分类: 个人成长-人生哲学\nISBN:9787115510556\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行,加上留白的空间,一般控制在一屏显示3~4个段落比较合适。\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分类: 个人成长-人生哲学\nISBN:9787572603174\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分类: 个人成长-认知思维\nISBN:9787111691020\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因为前面0~5万元那部分已经全部给她,把她投入的时间和精力成本覆盖了。这时,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分类: 个人成长-励志成长\nISBN:9787508661766\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分类: 个人成长-励志成长\nISBN:9787520814669\n出版社:中国商业出版社\n\n概述 §\n作者用解剖学教科书的理念,分别在人生规划大方向,资源配置,时间管理,专业知识学习,以及职场实战落地的五个角度,针对同一个“人生规划”的问题,做了深入浅出的系统性交代,能帮助读者快速走出人生迷茫的盲区。全书主要阐述如何基于自身的情况,来快速定位自己的人生规划的不同阶段位置,制定接下来中长期的发展规划,然后逐步盘活自己的人生?\n划线 §\n\n10%的规划原则:当你想要去做十年规划的时候,我们建议用一年的时间去思考规划;当你想要去做一年规划的时候,我们建议你用365天中的36天去思考规划;\n\n\n真正原因是:你的后防线,你的系统能够支撑你有多少时间来成就自己,很多人富有才华,却因为后防线不稳定,没有修炼自己技能的机会,最后错过了时间,遗憾终身。\n\n\n学和习的比例:1:6~1: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因为岗位薪酬设计和工作价值的关系,你大概率可能会被锁死在某一个范围内。如果你想要破局的话,唯一的方式就是重新学习可以承载3~10倍及以上收入的知识体系,或者切换到更高收益的行业跑道或公司。\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第三步:收集。找到自认为觉得不错的10~50个人力资源的公众号,用Word文档复制粘贴一个公众号里面的最近50~100篇关于人力资源的公众号文章,重复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一天至少需要找到一个连续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比如,如何让自己每月多1000~3000元收入?如何让自己每天节约2小时时间?如何让自己的工作效率加快?如何管理5~10人的小团队?下个月的营业额如何达标?如何准备跳槽到收入高的公司?这些都是非常实际的问题。\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多个和自己收入差距在1~3倍的同行在哪里,他们在做什么样的工作,以及他们在哪里上班,同样每天8~12小时,他们都在用什么样的专业知识和技能来完成工作中,有了这些“我自己也能够得上的参考对标”,那么我只要找到这些专业知识,以及我自己能够承受得了的学习范围,剩下的就是时间磨炼和练习量的积累了。\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分类: 个人成长-人在职场\nISBN:9787115538253\n出版社:人民邮电出版社\n\n概述 §\n面试是人才招聘过程中的重要一环,面试官的水平直接影响到所招人员的素质高低。 那么,面试官该具备哪些基本素质和技能呢? 本书从面试环节出发,介绍了面试官定位、人才画像、面试准备、面试提问与追问、非语言信息观察、面试评分以及面试官的修养等与面试相关的内容。书中不仅穿插了大量的真实案例,便于读者快速理解和掌握知识点,而且在每一讲中都提供了对应的实操小工具,如人才画像分析表、面试提纲表和面试评语表等,帮助人力资源从业者快速掌握面试技巧,成为超级面试官。\n划线 §\n\n面试官定位、人才画像、面试准备、面试提问与追问、非语言信息观察、面试评分以及面试官的修养\n\n\n管理者最重要的事情就是招聘人才。\n\n\n招聘就像谈恋爱一样,要找到一个合适的人是很难的。找错对象会很痛苦,招错人才的代价也很大。\n\n\n如果招聘到不合适的人,公司就要付出相当于该员工15倍薪水的代价。\n\n\n(1)面试标准不清晰,不知道自己要招什么样的人;(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\n(2)岗位需要什么样的人?这是“硬”的条件,人力资源部门通过职位分析明确该岗位的任职者需要具备的学历、年龄、经验和技能等。\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分类: 医学健康-医学\nISBN:9787117306959\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建议发热超过38.5℃时才使用含有退热成分的抗感冒药,餐后吃,4~6小时后如果体温还超过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分类: 历史-历史文化\nISBN:9787115331809\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\n(1)信息贯穿了人类的发展史,今天的成果是过去一点点积累而来的;(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分类: 历史-中国史\nISBN:9787521731224\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分类: 哲学宗教-西方哲学\nISBN:9787115542649\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分类: 哲学宗教-思维科学\nISBN:9787514227697\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是计划(Plan),D是执行(Do),C是检查(Check),A是调整(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分类: 心理-心理学研究\nISBN:9787533941963\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分类: 心理-心理学应用\nISBN:9787111639824\n出版社:机械工业出版社\n\n概述 §\n冥想是一种奇妙的技能,它有改变我们人生的潜力,但是怎样运用这种技能,则取决于你自己。随着媒体对冥想和正念的报道越来越多,许多人似乎急于确定冥想的用途。事实上,你只有确定了如何用它,你才能确定它的用途。在学骑自行车的时候,你所了解的是如何骑车,而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具,有些人用它跟朋友闲逛,还有极少数人可能以它为终身事业。对所有人来说,技能是一样的:安稳地坐在车座上,别掉下来。所以,虽然别人可以教你如何骑车,但骑车对你而言到底意味着什么,你要拿它做什么,以及它怎样才能最符合你的生活方式,这完全取决于你自己。冥想技能也是如此,你可以将它应用到生活中的任何方面,它的价值取决于你赋予它的价值。\n划线 §\n\n你上一次坐下来,安静不动,不分心,不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰,没有任何你需要思考和解决的事情,是什么时候?\n\n\n在正念环境中,冥想不是要去阻止想法、控制心灵。它是一个过程,在这个过程中,我们放弃控制,不插手,不介入,学会以被动的方式集中注意力,同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手,容许心灵以自己的节奏、自己的方式展开,你才能找到真正的头脑空间。\n\n\n你知道,如果你坐上飞机,从那些云的一端穿过,另一端就没有阴云,而只有蓝色的天空了。就算有大片阴沉沉的乌云,蓝色的天空也始终存在。\n\n\n我得到了这样一种理念:天空总是蓝的。云相当于我们的思想,当心灵忙于这些想法的时候,蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何,心灵的深层本质就像蓝色的天空一样,并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候,云会变得更加阴沉,更令人烦扰。也许整个天空中只有那么一个想法,然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走,而是:搬把椅子到花园里,坐看云卷云舒。有时候,蓝色的天空会穿过阴云展露出来,令人备感美好。如果我能耐心地坐在那里,不过分执着于那些阴云,那么蓝色的天空会显露得更多。\n\n\n。最重要的是,你可以想象心中有一片始终宁静、始终澄澈的区域,想象心中有一片你随时都可以依归的地方,想象无论生活中发生什么事,心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事,就指望它突然静静地在某个地方站定!因此,当你跟这匹野马,也就是你的心灵,一起坐下来的时候,你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上,相反,要给你的心灵一点时间,让它安定下来,放松一点。你急什么呢?”\n\n\n关注它的同时,试着温和地将它分享给他人。同样,如果你的注意力集中在令人不快的感受上,那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的,必将浮上来\n\n\n就情感而言,凡是被压制的,必会再浮上来。也许它会突出到表面来,就像情感本身一样,也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央,即一块开放田野的中央。现在,缰绳的一端系着这匹马,另一端在你手里。不过,缰绳是松弛的,这匹马有它所需要的一切空间,它并没有觉得被困住或者受到约束\n\n\n你有没有注意过,当你真正专注于某个事物的时候,你的心灵会变得多么平静?你有没有注意过,即便你的心灵之前还凌乱如麻,但是一旦专注于自己喜欢做的事情,并且全身心地沉浸在那项活动中时,心灵会开始安定下来,会感到非常宁静?\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分类: 心理-认知与行为\nISBN:9787115543424\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分类: 心理-认知与行为\nISBN:9787115569455\n出版社:人民邮电出版社\n\n概述 §\n做成一件有价值的事,成为一个有价值的人; 成长的根本是做成事情、创造价值。 做到,是更高等级的成长。一个人的成长也是通过主动做成一件对他人很有用的事来实现的。但在现实生活中,很多人虽然内心强烈希望变好,行动也非常努力,却始终无法做成事情,这背后的原因通常是缺少价值意识、输出意识、创造意识、作品意识、利他意识…… 《认知驱动:做成一件对他人很有用的事》将通过“做成一件事”的心法和技法两部分内容,和大家一起探索如何通过创造个人价值获取人生的成功、幸福和意义。 从“习惯养成”到“技能培养”,从“对内输入”到“对外输出”,从成为“更好的人”到成为“更有价值的人”,这些刻意的转变会让我们走出焦虑的怪圈。 单纯依靠意志力的努力往往是盲目的,所以人们会反反复复地起念,又反反复复地失败。一个人只有了解做成一件事的来龙去脉、看清事情本质后,才能走出反复尝试却劳而无功的困境。 学会用认知来驱动自己,我们才能更好地到达成长的彼岸——做成一件对他人很有用的事,成为一个有价值的人。\n划线 §\n\n内向成长,即围绕自身展开的成长活动,比如早起、跑步、阅读等。\n\n\n外向成长,即围绕外界展开的成长活动,比如写作、画画、编程等。\n\n\n享受努力奋斗的状态,却少有产出作品的意识。\n\n\n重技能辅习惯,重输出辅输入。\n\n\n人生的差异往往源于人们看待生活的不同视角。当你掌握了“复制”和“转换”这两个底层概念时,或许会看到一个不同的世界。\n\n\n“转换”和“复制”的最大区别在于边际成本不同——“转换”的边际成本越来越高,“复制”的边际成本越来越低。\n\n\n并非所有的“复制”类活动都具有无限可能,因为“复制”只是一种渠道,获得无限可能的关键依旧在于价值。\n\n\n要想获得无限可能,“复制”和“价值”缺一不可,且价值越高,可能性越大。如果你对自己的人生有追求,那就应该激励自己去创造“可复制的价值”。\n\n\n更重要的是,每次提笔时我都要问自己这样一个问题:这篇文章在三年、五年甚至十年后再看还有价值吗?如果没有,那就没必要写了。仅这一问,就能消除一切浮躁的动机。\n\n\n产对别人有用的东西永远是写作的指南针,其他事情亦是如此,价值交换规律放在哪里都会起作用。\n\n\n永远走价值积累之路\n\n\n社会在巨变,但价值交换规律不变。\n\n\n而本节的意义就是想告诉你,无论你选择写作还是其他,“价值产出”之路永远适合每一个人,无论何时都有效。\n\n\n而一个人要是能放弃自己的小九九,能发自内心地为社会发展、为人民福祉去做事,他就会真的充满力量,完成难以达成的任务。\n\n\n我们是为了实现人类理想而努力奋斗。\n\n\n利他的途径是创造价值\n\n\n是误把牺牲和讨好当成利他,以致得到的反馈和体验极其不好。最典型的表现就是无原则地对他人好或是有目的地付出\n\n\n情侣在关爱对方的同时,也要不断提升自己,用自身的优秀去带动对方同步成长,这才是健康的爱。\n\n\n同样的话从你和牛人的嘴里说出来,效果就是不一样,这显然不取决于对或不对,而取决于说话的那个人是谁!\n\n\n更好的关系不是付出,而是吸引\n\n\n擅打组合牌的人往往会在条件允许的情况下,尽可能先把目光聚焦到自己身上,他们会维护自己的形象,增加自己的学识,提升自己的智慧,稳定自己的情绪,丰富自己的爱好,结交理想的朋友,追逐自己的梦想……这样就可以始终向别人传达自己的魅力和自信,让喜欢的人主动靠近。\n\n\n这背后的原因大同小异:从短期看,是对方的素质和修养不够高;从长期看,是自身的能力和表现还不够好。因为所有的社交都是一面镜子,外界如何给你反馈,根源在于自身长期的综合表现。\n\n\n在和别人结婚之前,不妨先和自己“结一次婚”。不管你是男是女、已婚未婚,都可以给自己做一次这样的假设:你愿意和自己这样的人共度一生吗?无论贫穷、疾病也不离不弃?(事实上,和自己结婚,也只能不离不弃。)你喜欢自己的外在表现吗?喜欢自己的言行举止吗?喜欢自己的能力和上进心吗?喜欢自己对未来的追求吗?如果你对自己尚不满意,就不要指望别人会尊敬和喜欢你了。\n\n\n想要更好,请停止追逐\n\n\n这就是所谓的“被动社交”——通过产出独一无二的、具有长久价值的作品或产品来与这个世界保持连接。\n\n\n内向者更有创造优势\n\n\n因为内向成长者的生理特点决定了他们更擅长与事物而非与人物打交道。\n\n\n内向者更倾向于使用理智脑与外界互动,而外向者更倾向于用本能脑和情绪脑与外界互动。\n\n\n越是在传播手段发达的社会里,越要坚守价值。因为这个世界已经不缺乏传播途径了,但价值依旧稀缺!\n\n\n所谓“自我意识”,就是从自己的身份定位开始思考问题,即“我是一个什么样的人,所以我应该去做什么样的事”。在这个视角之下,所有的选择、方法、努力都会主动围绕自我身份的建设而自动转换为合适的状态。这样的人,可以说是真正的觉醒者了。\n\n\n现在,我们可以脱离这一模型,记住“环境、努力、方法、选择、身份、意义”这几个词就行了\n\n\n对个体来说,最重要的事情莫过于找到人生目标和意义,想清楚自己应该成为什么样的人。\n\n\n身份:改变自己的终极力量\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分类: 心理-认知与行为\nISBN:9787521743241\n出版社:中信出版集团\n\n概述 §\n现代社会,女性的社会地位与自我认知都得到了很大提升,但在性的问题上,依然存在很多说不清道不明的羞耻感。性一直都属于禁忌话题,虽然不说或者很少说,但现实生活中,对性的理解与认知会在很大程度上影响女性的亲密关系幸福度,理解或认知不当甚至会造成悲剧。 《谈性说爱》一书作者甄宏丽深耕女性性心理治疗与科普领域,深谙中国女性的性困境,书中从揭开女性的身体奥秘开始,讲述了女性性生理和性心理唇齿相依的关系;强调了尊重性本能的重要意义;对性与爱的关系、性与亲密关系等敏感话题展开了详细分析,阐述了全新的观念:性与爱合久必分,分久必合。作者在书的最后指出,懂性、爱性是性福女人的基石,活出性感真我是女性魅力的核心。 对于中国的新女性来说,需要这么一本书来刷新自己在性问题上的认知,补上这堂迟来的性教育课。\n划线 §\n\n把处女膜献给我未来的丈夫。\n\n\n处女膜是长在我身上的,是属于我的,我想什么时候拿出来用就用,处女膜绝不是我留着献给男人的礼物”。\n\n\n女性太压抑自己的性欲望,不敢放开自己。\n\n\n“不要性骚扰,要性高潮!”\n\n\n性爱是两个平等、独立的主体间的双人舞。\n\n\n处女膜的概念属于性医学范畴;婚前性行为属于社会学范畴;体会性冲动的兴奋程度属于性生理学范畴;要不要发生婚前性行为属于性心理学和性教育学范畴;坚守处女情结,婚后因为怕疼无法完成性生活,属于性心理治疗学范畴。\n\n\n中国女性追求性福已经不再遮遮掩掩,但是她们的性生活满意度很低依然是个不争的事实。\n\n\n性道德、性权利、性价值观等核心问题上依然存在严重的男尊女卑观念。\n\n\n生理、心理、社会\n\n\n生殖器官正常存在,才能让我们拥有性别身份,即是男还是女。\n\n\n为什么会有处女膜这个名字?实际上这是男权社会用来管理女人的一种手段。\n\n\n“处女”这个词,已经不仅仅局限于没有发生过性行为的女性这个概念了。它衍生出的意义是,任何非常值得珍惜的第一次经历。这是非常美好的概念。\n\n\n第一,性道德观点压抑女性性能力。\n\n\n第二,女性对自己的定位存在偏差。\n\n\n第三,很多女性认为只有在爱的基础上才有权利享受性愉悦,也就是所谓的性和爱是不可分割的。\n\n\n第四,有的女性觉得自己性魅力不够。\n\n\n因此,女性在性爱中长期处于一种被检验的状态,无法自然放松下来,脑子里充满问号:他觉得我的胸够大吗?他觉得我的皮肤白皙吗?我的腿太粗了吧?我的臀部是下垂的,他发现了吧?等等。\n\n\n真正男女平等、彼此尊重的和谐社会,对于男性和女性应该是同样的标准,男女的性权利都值得尊重,男女的性行为都不可以乱来,都要有做人的行为底线,都有权利获得性愉悦,都有权利获得性的隐私保护,等等。\n\n\n客观地去感受,积极地去接纳。\n\n\n吃甜品不仅可以疏解消极情绪,还可以产生积极情绪。\n\n\n人类最大的性器官可能被我们忽视了,那就是皮肤。\n\n\n我们知道了皮肤是人类最大的性器官,当你想要被拥抱,或者想去触碰对方的时候,是有一种明显的性需求在里面的,不要去否定它。我们要抓住这种信号,让自己更加鲜活起来。\n\n\n性与爱是分久必合、合久必分的关系。\n\n\n我个人认为,分久必合、合久必分的观点,恰恰体现了性与爱之间的和谐,但性和爱又是完全不同的两个东西。\n\n\n青春期时对某个人的爱慕,就像一股清流,让人感到新奇而美妙,这种精神世界的美好已经让人很满足,不需要通过性交实现。\n\n\n男性从来都是把性能力放在第一位,这种性能力就是接受刺激就要勃起,对女性就得征服,不能输,要是阳痿那就完了。所以,在男性看来,性能力是高于性道德的。\n\n\n只要女性不再自己物化自己,就有可能真正地实现男女平等。\n\n\n女性面对自己喜欢的男性,容易活在自己的想象中,\n\n\n受中国几千年封建文化的影响,女性把自己物化,男性也把女性物化了。\n\n\n赤裸裸地坦诚相对,是恋人走进彼此内心世界的唯美途径,是其他任何关系都无法替代的。\n\n\n这里的熟女指的是懂得了人间情爱滋味的女人。这种在岁月中成长起来的魅力,实际上是源于懂男人。所谓懂男人,其实很大程度上是懂得男人的需求,懂得他们喜欢什么样的女性魅力。\n\n\n现实生活中我们也看到,如果女性有了婚外性行为,大多数丈夫都会选择离婚,而且很多女性也能接受离婚的现实,甚至有可能是女性主动提出离婚。很多人都问过我为什么会这样。其实这一点都不奇怪,跟我们传统性观念中性道德的男女双重标准有关。\n\n\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分类: 政治军事-政治\nISBN:7010011648\n出版社:人民出版社\n\n概述 §\n毛泽东的《实践论》,是为着用马克思主义的认识论观点去揭露党内的教条主义和经验主义——特别是教条主义这些主观主义的错误而写的。因为重点是揭露看轻实践的教条主义这种主观主义,故题为《实践论》。毛泽东曾以这篇论文的观点在延安的抗日军事政治大学作过讲演。\n划线 §\n\n马克思主义者认为,只有人们的社会实践,才是人们对于外界认识的真理性的标准。实际的情形是这样的,只有在社会实践过程中(物质生产过程中,阶级斗争过程中,科学实验过程中),人们达到了思想中所预想的结果时,人们的认识才被证实了。\n\n\n实践高于(理论的)认识,因为它不但有普遍性的品格,而且还有直接现实性的品格\n\n\n马克思主义的哲学辩证唯物论有两个最显著的特点:一个是它的阶级性,公然申明辩证唯物论是为无产阶级服务的;再一个是它的实践性,强调理论对于实践的依赖关系,理论的基础是实践,又转过来为实践服务。\n\n\n看到了各种文件,这些就是事物的现象,事物的各个片面以及这些事物的外部联系。这叫做认识的感性阶段,就是感觉和印象的阶段。\n\n\n这个概念、判断和推理的阶段,在人们对于一个事物的整个认识过程中是更重要的阶段,也就是理性认识的阶段。认识的真正任务在于经过感觉而到达于思维,到达于逐步了解客观事物的内部矛盾,了解它的规律性,了解这一过程和那一过程间的内部联系,即到达于论理的认识。\n\n\n感性的认识是属于事物之片面的、现象的、外部联系的东西,论理的认识则推进了一大步,到达了事物的全体的、本质的、内部联系的东西,到达了暴露周围世界的内在的矛盾,因而能在周围世界的总体上,在周围世界一切方面的内部联系上去把握周围世界的发展。\n\n\n认识过程中两个阶段的特性,在低级阶段,认识表现为感性的,在高级阶段,认识表现为论理的,但任何阶段,都是统一的认识过程中的阶段。\n\n\n我们的实践证明:感觉到了的东西,我们不能立刻理解它,只有理解了的东西才更深刻地感觉它。感觉只解决现象问题,理论才解决本质问题。\n\n\n马克思、恩格斯、列宁、斯大林之所以能够作出他们的理论,除了他们的天才条件之外,主要地是他们亲自参加了当时的阶级斗争和科学实验的实践,没有这后一个条件,任何天才也是不能成功的。\n\n\n为了明了基于变革现实的实践而产生的辩证唯物论的认识运动——认识的逐渐深化的运动,下面再举出几个具体的例子。\n\n\n战争的领导者,如果他们是一些没有战争经验的人,对于一个具体的战争(例如我们过去十年的土地革命战争)的深刻的指导规律,在开始阶段是不了解的。他们在开始阶段只是身历了许多作战的经验,而且败仗是打得很多的。然而由于这些经验(胜仗,特别是败仗的经验),使他们能够理解贯串整个战争的内部的东西,即那个具体战争的规律性,懂得了战略和战术,因而能够有把握地去指导战争。\n\n\n第一个,在前面已经说过的,这里再重复说一说,就是理性认识依赖于感性认识的问题。\n\n\n第二是认识有待于深化,认识的感性阶段有待于发展到理性阶段——这就是认识论的辩证法[插图]\n\n\n理性认识依赖于感性认识,感性认识有待于发展到理性认识,这就是辩证唯物论的认识论。\n\n\n抓着了世界的规律性的认识,必须把它再回到改造世界的实践中去,再用到生产的实践、革命的阶级斗争和民族斗争的实践以及科学实验的实践中去。\n\n\n理论的东西之是否符合于客观真理性这个问题,在前面说的由感性到理性之认识运动中是没有完全解决的,也不能完全解决的。要完全地解决这个问题,只有把理性的认识再回到社会实践中去,应用理论于实践,看它是否能够达到预想的目的。\n\n\n人们原定的思想、理论、计划、方案,毫无改变地实现出来的事,是很少的\n\n\n因为从事变革现实的人们,常常受着许多的限制,不但常常受着科学条件和技术条件的限制,而且也受着客观过程的发展及其表现程度的限制(客观过程的方面及本质尚未充分暴露)\n\n\n许多时候须反复失败过多次,才能纠正错误的认识\n\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:9787100106184\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\n(1)先看书名页,然后如果有序就先看序。\n\n\n(2)研究目录页,\n\n\n(3)如果书中附有索引,也要检阅一下\n\n\n(4)如果那是本包着书衣的新书,不妨读一下出版者的介绍。\n\n\n完成这四个步骤,你对一本书已经有足够的资讯,让你判断是想要更仔细地读这本书,还是根本不想读下去了。\n\n\n(5)从你对一本书的目录很概略,甚至有点模糊的印象当中,开始挑几个看来跟主题息息相关的篇章来看。\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(1)整体来说,这本书到底在谈些什么?\n\n\n作者细部说了什么,怎么说的?\n\n\n这本书说得有道理吗?是全部有道理,还是部分有道理?\n\n\n(4)这本书跟你有什么关系?如果这本书给了你一些资讯,你一定要问问这些资讯有什么意义。\n\n\n(1)画底线\n\n\n(2)在画底线处的栏外再加画一道线\n\n\n在空白处做星号或其他符号\n\n\n在空白处编号——作者的某个论点发展出一连串的重要陈述时,可以做顺序编号。\n\n\n(5)在空白处记下其他的页码\n\n\n将关键字或句子圈出来\n\n\n(7)在书页的空白处做笔记\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\n(5)诠释作者使用的关键字,与作者达成共识。(6)从最重要的句子中抓出作者的重要主旨。(7)找出作者的论述,重新架构这些论述的前因后果,以明白作者的主张。(8)确定作者已经解决了哪些问题,还有哪些是未解决的。在未解决的问题中,确定哪些是作者认为自己无法解决的问题。\n\n\n人是情绪与偏见的动物\n\n\n第一:要求读者先完整地了解一本书,不要急着开始批评。第二:恳请读者不要争强好辩或盲目反对。第三:将知识上的不同意见看作是大体上可以解决的问题。\n\n\n这个规则再进一步的话,就是要求读者要为自己不同的意见找到理论基础,这样这个议题才不只是被说出来,而且会解释清楚。只有这样,才有希望解决这个问题。\n\n\n(1)你的知识不足(uninformed)。(2)你的知识有错误(misinformed)。(3)你不合逻辑——你的推论无法令人信服。(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\n(1)这个作者想要证明什么?(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 teach),(3)有一群虔诚又顺服的成员,那么属于这类组织的成员在阅读的时候都会必恭必敬。他们不会——也不能——质疑这些对他们而言就是“经书”的书籍的权威与正确的阅读方法。信仰使得这些信徒根本不会发现“神圣的”经书中的错误,更别提要找出其中道理不通的地方。\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分类: 教育学习-外语\nISBN:9787213085802\n出版社:浙江人民出版社\n\n概述 §\n《赖世雄的英语学习法》是一本对英语学习者切实有效的方法指南。自学成才的赖世雄老师怀着帮助英语学习者少走弯路的初衷,在本书里详细讲解了自己在英语学习的每个阶段所采用的方法。从初学时如何通过反复模仿音标来塑造自己纯正的口音、如何通过自我对话的方式来增强讲英语的密度;到小有所成时如何通过大量阅读英文文章来大幅增加自己的词汇量,如何学习语法、划分句子结构从而为自己日后的写作打下坚实基础;再到英语学习的高级阶段中如何练习英汉互译,做口译练习的相关经验……凡此种种,赖世雄老师都结合自己的经验逐一进行了解释,并且细致地举出了在英语学习的各个阶段中学习者可能采用的错误方法。\n划线 §\n\n善用零星时间\n\n\nDon’t bite off more than you can chew.\n\n\n别咬下超过你能嚼得动的分量\n\n\n接下来我不是用背的方式去把这则会话背出来,而是一人扮演两个角色,把会话的内容自导自演,进行实际的演练,也就是一遍又一遍地把会话“演”出来。\n\n\n(1)善用零星时间(2)少就是多,慢就是快(3)持之以恒,永不放弃\n\n\n与“读”。我要说的是,看到英语文章就要开口念出声音来,而不是只默读,也不是马上查词典。我是一小段一小段地攻克新闻文章的,而不是一次把一整篇念完,这就是我所说的“少就是多”的原则。我再强调一次,我这里讲的阅读是“阅”与“读”。也就是说,当你的眼睛“看”到英语文章时,你的嘴巴就必须要同时把英文句子“念”\n\n\n我则是只要有零星时间就拿起《英文中国邮报》边看新闻文章(news stories)边念出声来。这么一来,我的嘴巴一天到晚讲的都是英语,我相信这会比在培训班里讲英语的机会多得多。Luther Burbank(卢瑟·伯班克)曾说过:“Time cannot be added to a person’s life,but it can be made more valuable by avoiding waste.”(时间不能加进一个人的生命里,但是珍惜光阴却可使生命变得更有价值。)\n\n\nTo err is human,to forgive divine.”翻译成中文是:“人非圣贤,孰能无过。\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/文学/凤凰项目:一个IT运维的传奇故事(修订版)":{"title":"凤凰项目:一个IT运维的传奇故事(修订版)","links":[],"tags":["阅读/文学-散文杂著","阅读/笔记"],"content":"简介 §\n\n书名:《凤凰项目:一个IT运维的传奇故事(修订版)》\n作者: 吉恩·金 凯文·贝尔 乔治·斯帕福德\n分类: 文学-散文杂著\nISBN:9787115516763\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分类: 文学-文学鉴赏\nISBN:9787550032262\n出版社:百花洲文艺出版社\n\n概述 §\n老舍是中国现代著名作家和语言大师,著有《骆驼祥子》《四世同堂》《茶馆》等颇具分量、雅俗共赏的经典作品,也留下了丰富的文学理论普及读物,如《和工人同志们谈写作》《老牛破车》《写与读》等。《老舍谈写作》精选其关于写作的论述,从写作的基本原则、写与读的关系,语言的运用、描写的技巧、结构的方法等方面,深入浅出地阐述“如何写作”这个主题。对于初学写作或希望在写作方面有所进益的读者来说,有很强的指导性和可操作性。\n划线 §\n\n我们从一篇作品里,可以看出作家怎样运用文字语言,怎样描写风景,刻画人物,怎样布置全局,怎样安排各处的情节。这些,都是我们应当细心体会的。\n\n\n练习基本功,对初学写作者来说,是很重要的事\n\n\n一个完完整整的人、一件完完整整的事做起。\n\n\n写小说的人,也不妨练习写写诗;写写诗,文字就可以更加精炼,因为诗的语言必须很精炼,一句要表达好几句的意思。\n\n\n字的本身没有好或坏,要看用在什么地方。用得恰当,就生动有力。\n\n\n简练就是话说得少,而意思包含得多\n\n\n我认为在学习过程中,出废品是很难免的。\n\n\n临时去观察一个人总不如随时注意一切的人更为重要。自己心里没有一个小的人海,创作起来就感到困难。\n\n\n只说这三点吧,我的那些缺点即暂不谈,留作另一篇小文的材料。\n\n\n凡是能写些文艺作品的人都是先在语文上用过功夫的。\n\n\n应当先去进修语文。把文字写明白了,就有了表现能力,会把心中的话写到纸上去。有了这种能力,再进一步学习剧本与小说的写作,就必定很顺利。反之,还没有把心里的话明明白白地写在纸上的本事,就想去写剧本或小说,必定劳而无功。\n\n\n他们的生活经验是这些作品的资料。\n\n\n不会写就是半个哑巴,只会用嘴说,而不会把话写在纸上。\n\n\n有思想,有生活,而表达不出来,问题也极为严重。\n\n\n语文是随时可以练习的。写日记、写信、纪录报告等等都是练习语文的机会,不可错过。\n\n\n读书而外,一个作家还须熟读社会人生。\n\n\n并没有看过另一本专写人力车夫的生活的书\n\n\n词汇较为丰富了,可是文笔反倒更显着平庸,因为说到什么都有个人云亦云的形容词,大雨必是滂沱的,火光必是熊熊的,溪流必是潺潺的……。这样穿戴着借来的衣帽的文章是很难得出色的。\n\n\n我们用文字表达我们的思想、感情;不以文字表达文字。字典里的文字最多,但字典不是文学作品。\n\n\n所谓不将就,即是不随便找个词汇敷衍一下。我们要想,想了再想,以便独出心裁地找到最恰当的字。假若找不到,就老老实实地用普通的字,不必勉强雕饰。\n\n\n写作技巧至少包括三方面:语言的运用,描写的能力,和作品的结构。\n\n\n只有自己也去生活,对人的了解才会深刻。因此,我们第一须和人民生活在一起,第二要在生活中表现得好,即使写不出好作品,仍不失为好人。\n\n\n文学修养必须包括思想。\n\n\n功到自然成,欲速则不达!\n\n\n第二,写东西时,用字,造句必须先要求清楚明白。\n\n\n要老老实实先把话写清楚了,然后再求生动\n\n\n就是要少用“然而”“所以”“但是”,不要老用这些字转来转去。\n\n\n第三,我们应向人民学习。人民的语言是那样简练、干脆。\n\n\n第四,我写文章,不仅要考虑每一个字的意义,还要考虑到每个字的声音。\n\n\n上句末一个字用了一个仄声字,如“他去了”,下句我就要用个平声字,如“你也去吗?”让\n\n\n第五,我们写话剧、写电影的同志,要注意这个问题:我们写的语言,往往是干巴巴地交代问题。\n\n\n第六,中国的语言,是最简练的语言。\n\n\n其实,文艺工作者的本事就是用浅显的话,说出很深的道理来。这就得想办法。必定把一个问题想得透彻了,然后才能用普通的、浅显的话说出很深的道理。\n\n\n人物要固定,事情要有范围\n\n\n我们记住语言,还须注意它的思想感情,注意说话人的性格、阶级、文化程度,和说话时的神情与音调等等。这就是说,必须注意一个人为什么说那句话,和他怎么说那句话的。通过一些话,我们可以看出他的生活与性格来。这就叫连人带话一齐来。\n\n\n“塞水不成河”是客观的观察,“月是故乡明”是主观的情感。\n\n\n这样,尽管我没写出过完美的相声段子,我可是得到一个写文章的好方法:句句要打埋伏。\n\n\n明白了作文要前呼后应,脉络相通,才不厌修改,不怕删减。狠心地修改、删减,正是为叫部分服从全体。\n\n\n语言练习不专仗着写剧本或某一种文体,而是需要全面学习。在写戏写小说之外,还须练基本功,诗词歌赋都拿得起来。\n\n\n高深的思想与精辟的语言应当是互为表里,相得益彰的。\n\n\n对话不能性格化,人物便变成剧作者的广播员。\n\n\n剧本的语言应是语言的精华,不是日常生活中你一言我一语的录音。\n\n\n喜剧语言必须馅儿多而皮薄,一咬即破,而味道无穷。\n\n\n第三,我的生活知识与艺术知识都太少,所以笔下枯涩。思想起来,好不伤心:音乐,不懂;绘画,不懂;芭蕾舞,不懂;对日常生活中不懂的事就更多了,没法在这儿报账。\n\n\n最容易看出来的是学生腔里爱转文,有意或无意地表示作者是秀才。\n\n\n生活是最伟大的一部活语汇。\n\n\n后来,稍稍学了一点拉丁及法文,我就更爱英文,也就翻回头来更爱华语了,因为以英文和拉丁或法文比较,才知道英文的简单正是语言的进步,而不是退化;那么以华语和英语比较,华语的惊人的简单,也正是它的极大的进步。\n\n\n文字的感动力是来自在某个场合中必然的说某种话——这个话是最普遍常用的,绝难借用外国文法的。一个哲学家,与一个工友,在他痛苦的时节,是同样的只会叫“妈”的。\n\n\n(一)写自己真知道的事,不写自己不十分知道的事。\n\n\n假若机智是感诉理智的,闹戏则仗着身体的摔打乱闹。喜剧批评生命,闹戏是故意招笑。\n\n\n今天贴了标语,明天中国就强起来——反语。君子国的标语:“之乎者也”——讽刺。标语是弱者的广告——机智。张三把“提倡国货”的标语贴在祖坟上——滑稽;再加上些贴标语时怎样摔跟头等等招笑的行动,就成了闹戏。张三把“打倒帝国主义走狗”贴成“走狗打倒帝国主义”——幽默;这个张三贴一天的标语也许才挣三毛小洋,贴错了当然要受罚;我们笑这种贴法,可是很可怜张三。\n\n\n叙述不是枝枝节节地随便说,而是把事物的本质说出来,使人得到确实的知识。\n\n\n叙述不怕细致,而怕不生动。在细致处,要显出才华。文笔如放风筝,要飞起来,不可爬伏在地上。要自己有想象,而且使读者的想象也活跃起来。\n\n\n内容决定形式。但形式亦足左右内容。\n\n\n描写人物要注意他的四围,把时间地点等跟人物合在一处。要有人,还有画面。\n\n\n我们必须去深刻地了解人。知道他的十件事,而只写一件事,容易成功。只知道一件,就写一件,很难写出人物来。\n\n\n写两千多字,不多写:这可只是大概的说,有时候三天连一个字也写不出!我不知道天下还有比这更难受的事没有。我看着纸,纸看着我,彼此不发生关系!\n\n\n不经过自己思索、创造出来的,就不会有风格。要出语惊人,就要表达出自己的感情,自己的想法,自己的笔调。这样的文章才会是独具风格的。\n\n\n初学者可以做个学习规划:可以从写日记开始,把自己看到的东西,能最简单地、如实地记下来,就是本领。日积月累,这就是宝贵材料。这样的练习就是记录生活,是创作的原材料。\n\n\n创造人物是小说家的第一项任务。\n\n\n一个小说家是人生经验的百货店,货越充实,生意才越兴旺。\n\n\n这不是政策,而是不得不如此。自己觉得很对不起文艺,可是钱与朋友也是不可得罪的。\n\n\n为艺术而牺牲是很好听的,可是饿死谁也是不应当的,为什么一定先叫作家饿死呢?我就不明白!\n\n\n一、散文是用加过工的语言组织成篇的。\n\n\n二、散文中的每个字都要用得适当。\n\n\n一句中不单重要的字要斟酌,就是次要的字也要费心想一想,甚至于用一个符号也要留神。写散文是件劳苦的事;信口开河必定失败。\n\n\n三、选择词与字是为造好了句子。\n\n\n一段中的句子要有变化,不许一边倒,老用一种结构。\n\n\n无论是写一部小说,还是一篇杂文,都须有组织。有组织的文字才能成为文艺作品。因此,无论是写一部小说,还是一篇短的杂文,我们都须事先详细计划一番,作出个提纲。写了一段,临时现去想下段,是很危险的。最好是一写头一段的时候,就已经计划好末一段说什么。\n\n\n我觉得通俗文艺有三难:不易通俗,不易有趣,与不易悦耳。\n\n\n大家也许就推举他主编。自傲心是最普遍的毛病,甲既受人推重,也许就难免傲然以文学家自居了。\n\n\n假若你不明白科学,你就连这样的小说或诗也读不懂,还说什么自己成为文艺家呢?!\n\n\n无论中外许多有名的文艺写家都并不是学文学的人;医生、律师……都有成为名写家的,而大学文学系毕业生反倒不一定能创作出什么来。\n\n\n学问、经验、修养、努力,加上文艺天才,方能产生一个作家。\n\n\n把事情看得太容易的人大概不易成功。\n\n\n在许多原因之中,恐怕大家把文艺看得太轻而易举也是个重要的原因。我不敢批评别人,只说我自己吧,我根本就不够格:以我的学问、经验、天才,公公道道的说,我只能作个相当好的小学校长或初中的国文教员,文艺写家差得太多,太多了!\n\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在你写东西的时候,要要求清楚,少用那些乱七八糟的修辞。你要是真看明白了一件事,你就能一针见血地把它写出来,写得简练有力!\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分类: 生活百科-体育\nISBN:9787115478528\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分类: 生活百科-体育\nISBN:9787115467782\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分类: 社会文化-社科\nISBN:9787549631780\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分类: 社会文化-法律\nISBN:9787515819556\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\n(1)寻找人证。找到能够证明骚扰发生的目击者,而且目击者最好愿意出庭作证,至少要能够提供书面的证言。(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\n(1)重婚或有配偶者与他人同居的;(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分类: 社会文化-文化\nISBN:9787549636358\n出版社:上海文汇出版社\n\n概述 §\n担心《论语》看不下去?那是因为不知道,孔子原来这么爱吐槽!通过手绘漫画和爆笑段子,陈磊(笔名:混子哥)领衔的半小时漫画团队,一边向我们展示孔子和弟子们的花式卖萌和吐槽,一边串讲《论语》里的经典章句,让我们在哈哈大笑中学到《论语》里的人生哲理。为什么颜回一生贫困潦倒,没做过什么大事,却获得了孔子“不迁怒,不贰过”的赞赏,并成为孔子最喜欢的学生?我们耳熟能详的“知之为知之,不知为不知,是知也”,其实是孔子对子路学习态度不端的吐槽?宰我到底做了什么,逼得孔子爆出了“朽木不可雕也,粪土之墙不可圬也”这样的粗口?翻开本书,看孔子和弟子们卖萌吐槽,人生哲理全学到!\n划线 §\n\n子曰:“有教无类。”——《论语·卫灵公》\n\n\n子曰:“默而识(zhì)之,学而不厌,诲人不倦,何有于我哉?”——《论语·述而》\n\n\n子曰:“人而不仁,如礼何?人而不仁,如乐何?”——《论语·八佾(yì)》\n\n\n称作孔门十哲。\n\n\n都说缘分天注定,相遇是命运\n\n\n所以,各位家长看见了吗?想要让自己的孩子赢在起跑线上,自己得先跑起来!\n\n\n但颜回总是表现得十分低调,从不显山露水,孔子甚至一度以为他是一个傻子……故事是这样的。\n\n\n但关键的一点是要看这个人能否做到:穷,也能穷得开心。\n\n\n安贫乐道。\n\n\n颜回就不这样。他能设身处地地理解别人,对他人的喜怒哀乐感同身受。\n\n\n子路会把陷入困境视作自己的问题,然后开始自我怀疑,这是不自信的表现。\n\n\n子曰:“三军可夺帅也,匹夫不可夺志也。”——《论语·子罕》\n\n\n不迁怒,不贰过。从来不迁怒于别人,犯过的错绝不再犯第二次。\n\n\n作为鲁国政坛上的过来人,孔子给冉雍支了三招:\n\n\n子曰:“夫人不言,言必有中。”——《论语·先进》孔子说:“这个人平日不大开口,一开口一定中肯。”[插图]成语言必有中就出自上文,意思是一个人说话总是能说到重点。\n\n\n所以,马德好才是骥能称为千里马的关键!把马换成人也是一样的道理,比起才华和颜值,德行才是最重要的。\n\n\n\n要解决问题,得先找到问题的根本\n\n\n\n\n为了解决问题,可以转移矛盾\n\n\n\n\n多次转移矛盾,彻底把水搅浑\n\n\n\n第一课:要充分了解对方的痛点,并给予不露声色的试探\n\n\n入,曰:“伯夷、叔齐何人也?”[插图]曰:“古之贤人也。”[插图]曰:“怨乎?”[插图]曰:“求仁而得仁,又何怨?”——\n\n\n如切如磋,如琢如磨。\n\n\n第二课:面对自己的无知,要虚心而积极地改正\n\n\n子贡问曰:“孔文子何以谓之‘文’也?”子曰:“敏而好学,不耻下问,是以谓之‘文’也。”[插图]——《论语·公冶长》\n\n\n第三课:对自己的老师,要给予家人般的温暖\n\n\n子曰:“莫我知也夫!”[插图]子贡曰:“何为其莫知子也?”[插图]子曰:“不怨天,不尤人,下学而上达。知我者其天乎!”——《论语·宪问》\n\n\n宰我:逼得孔子爆粗口的“杠精”学生\n\n\n子曰:“知者不惑,仁者不忧,勇者不惧。”——《论语·子罕》孔子说:“聪明的人不迷惑,仁德的人不忧虑,勇敢的人无所畏惧。”\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曰:“莫春者,春服既成,冠者五六人,童子六七人,浴乎沂(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\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分类: 社会文化-法律\nISBN:9787229156572\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分类: 社会文化-文化\nISBN:9787521701579\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分类: 科学技术-工业技术\nISBN:9787111655497\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分类: 经济理财-管理\nISBN:9787302392002\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\n(1)假设你所在的部门下设6个科,你是某科的科员,在你们科里,除了科长之外,大家公认你的业务能力最强。有一天,部门经理交给你一份刚收到的会议通知,让你去参加某个会议。请你谈谈,从你接到通知那一刻到参加会议前,你会做些什么?(2)如果你入选了,但你的岗位级别定得较低,而你的主管在学历、资历、能力等方面都不如你,你该怎么办?(3)请你说说与领导相处和与同事相处的不同点。(4)你和你的上司有过意见不一致的情况吗?如果有,且你觉得自己理由充分,你会据理力争吗?如果不会,为什么?你是否担心今后他给你“穿小鞋”?(5)企业管理人员的选择可以采用外部招聘和内部提升两种方式,你认为各有何优缺点?(6)面对客户除工作之外的要求,如暗示要财务旅游、招待,你如何对待?(7)你管理的员工及时处理了工作中发生的紧急情况,但违反了规章制度,事后,你会怎么办?(8)请你为我们这次面试做个小结或提个建议好吗?你对我们几个面试人员有什么看法和建议?(9)原单位的领导对你的离开会持什么态度?会不会挽留你?(10)请用三个词评价你自己(考虑半分钟)\n\n\n(1)请谈谈你现在的工作情况和工作业绩。或在你最近的工作中,最突出的业绩是什么?(2)你认为现在的工作对你的发展有何影响?你为什么想换工作?对于这个岗位你有哪些优势和不足?你打算怎样弥补不足?(3)你怎样理解你所应聘的岗位?你觉得如果我们录用你,你能为我们带来的最直接的效益是什么?(4)你需要多长时间来适应一个新工作岗位?最难处理的是什么事情?为什么?(5)你最富有创造性的工作成果是什么?(6)对你而言,“成功”有何含义?在你以前的工作经历中,什么事令你最有成就感?(7)最不喜欢怎样的工作?觉得自己最大的失败是什么?从中吸取了哪些教训?\n\n\n(1)你为什么应聘我们公司?你对我们公司有哪些了解?你最看好公司哪些方面?(2)你向往怎样的工作环境?欣赏怎样的领导风格?最反感怎样的领导风格?(3)你觉得至今为止,什么事情或什么人对你的影响最大?如何影响你?为什么?(4)你平时最喜欢什么休闲活动?最喜欢哪部文学作品或者哪个人物,为什么?(5)请结合自己的情况,谈谈你对公司晋升制度的建议?(6)你是如何看待事业和家庭之间的关系的?平时周末做什么?如经常需要周末加班,会有什么问题?为什么?(7)在你看来,当今最优秀的或最成功的企业是哪一家?为什么?(请考虑一分钟)(8)你选择工作时,薪酬的重要性排在第几位?排在第一位的是什么?为什么?\n\n\n第一章:总则。介绍部门职能说明书的使用、岗位职责说明书的使用、名称定义。第二章:公司组织结构图。第三章:部门职能说明书。包括13个部门。第四章:岗位结构。包括董事会机构岗位结构图、集团职能部门岗位结构图。第五章:岗位职责说明书。包括63个岗位。\n\n\n(1)A猎头公司的寻访流程,包括6个阶段:需求分析、企业了解、综合分析、寻访猎取、人才推荐、跟踪服务,具体见表17.1。表17.1 猎头寻访流程[插图]\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/经济理财/十分钟冥想":{"title":"十分钟冥想","links":[],"tags":["阅读/经济理财-理财","阅读/笔记"],"content":"\n简介 §\n\n书名:《十分钟冥想》\n作者: 安迪·普迪科姆\n分类: 经济理财-理财\nISBN:9787111639824\n出版社:机械工业出版社\n\n概述 §\n冥想是一种奇妙的技能,它有改变我们人生的潜力,但是怎样运用这种技能,则取决于你自己。随着媒体对冥想和正念的报道越来越多,许多人似乎急于确定冥想的用途。事实上,你只有确定了如何用它,你才能确定它的用途。在学骑自行车的时候,你所了解的是如何骑车,而不是你要如何去运用骑车的能力。有些人把自行车视为出行工具,有些人用它跟朋友闲逛,还有极少数人可能以它为终身事业。对所有人来说,技能是一样的:安稳地坐在车座上,别掉下来。所以,虽然别人可以教你如何骑车,但骑车对你而言到底意味着什么,你要拿它做什么,以及它怎样才能最符合你的生活方式,这完全取决于你自己。冥想技能也是如此,你可以将它应用到生活中的任何方面,它的价值取决于你赋予它的价值。\n划线 §\n\n你上一次坐下来,安静不动,不分心,不受电视、音乐、书籍、杂志、食物、电话、计算机、朋友、家人的打扰,没有任何你需要思考和解决的事情,是什么时候?\n\n\n在正念环境中,冥想不是要去阻止想法、控制心灵。它是一个过程,在这个过程中,我们放弃控制,不插手,不介入,学会以被动的方式集中注意力,同时将心灵安放在它自有的、自然的觉醒中。\n\n\n内心想法不介入不插手,容许心灵以自己的节奏、自己的方式展开,你才能找到真正的头脑空间。\n\n\n你知道,如果你坐上飞机,从那些云的一端穿过,另一端就没有阴云,而只有蓝色的天空了。就算有大片阴沉沉的乌云,蓝色的天空也始终存在。\n\n\n我得到了这样一种理念:天空总是蓝的。云相当于我们的思想,当心灵忙于这些想法的时候,蓝色的天空就暂时被遮蔽了。从我自\n\n\n无论我们感受如何,心灵的深层本质就像蓝色的天空一样,并没有发生变化。当我们因为某种原因心情不好或者感到痛苦的时候,云会变得更加阴沉,更令人烦扰。也许整个天空中只有那么一个想法,然而它似乎带走了我们全部的注意力。\n\n\n我一直都把头脑空间当成这种心境。冥想不是努力把阴云赶走,而是:搬把椅子到花园里,坐看云卷云舒。有时候,蓝色的天空会穿过阴云展露出来,令人备感美好。如果我能耐心地坐在那里,不过分执着于那些阴云,那么蓝色的天空会显露得更多。\n\n\n。最重要的是,你可以想象心中有一片始终宁静、始终澄澈的区域,想象心中有一片你随时都可以依归的地方,想象无论生活中发生什么事,心中都始终有一种安心感或安定感。\n\n\n你不可能因为你像一座雕像一样坐在那里做某种叫冥想的事,就指望它突然静静地在某个地方站定!因此,当你跟这匹野马,也就是你的心灵,一起坐下来的时候,你需要给它提供很大的空间。不要试图立刻将注意力集中在冥想对象上,相反,要给你的心灵一点时间,让它安定下来,放松一点。你急什么呢?”\n\n\n关注它的同时,试着温和地将它分享给他人。同样,如果你的注意力集中在令人不快的感受上,那么请你试着轻松地保持体验它或者替某个你关心的人照看它的心态。\n\n\n被压制的,必将浮上来\n\n\n就情感而言,凡是被压制的,必会再浮上来。也许它会突出到表面来,就像情感本身一样,也可能它会开始以别的方式影响我们的行为。\n\n\n要像训练野马那样去靠近你的心灵。要想象自己站在一个非常大的空间的中央,即一块开放田野的中央。现在,缰绳的一端系着这匹马,另一端在你手里。不过,缰绳是松弛的,这匹马有它所需要的一切空间,它并没有觉得被困住或者受到约束\n\n\n你有没有注意过,当你真正专注于某个事物的时候,你的心灵会变得多么平静?你有没有注意过,即便你的心灵之前还凌乱如麻,但是一旦专注于自己喜欢做的事情,并且全身心地沉浸在那项活动中时,心灵会开始安定下来,会感到非常宁静?\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分类: 经济理财-理财\nISBN:9787545552140\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分类: 经济理财-商业\nISBN:9787521745276\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分类: 经济理财-管理\nISBN:9787505748392\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分类: 艺术-民艺\nISBN:9787101138504\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分类: 计算机-编程设计\nISBN:9787115489456\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分类: 计算机-理论知识\nISBN:9787111597780\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分类: 计算机-编程设计\nISBN:9787115592514\n出版社:人民邮电出版社有限公司\n\n概述 §\n这是一本关于Linux命令行与shell脚本编程的系统性教程,主要包括四大部分 :Linux命令行、shell脚本编程基础、高级shell脚本编程,以及创建和管理实用的脚本。本书这一版针对Linux系统的新特性进行了更新,不仅涵盖了详尽的动手教程和现实世界中的实用信息,还提供了与所学内容相关的参考信息和背景资料。通过本书的学习,你能轻松写出自己的shell脚本。 本书适合Linux系统管理员及相关开发人员阅读。\n划线 §\n\nLinux系统可划分为以下4部分。·Linux内核·GNU工具·图形化桌面环境·应用软件\n\n\nLinux内核采用虚拟文件系统(virtual file system,VFS)作为和各种文件系统交互的接口\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/.bashprofile⋅HOME/.bashrc·HOME/.bashlogin⋅HOME/.profile\n\n\n/etc/profile文件是系统中默认的bash shell的主启动文件。系统中的每个用户登录时都会执行这个启动文件。\n\n\n大多数Linux发行版只用这4个启动文件中的一两个。·HOME/.bashprofile⋅HOME/.bashrc·HOME/.bashlogin⋅HOME/.profile\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/计算机/Linux是怎样工作的":{"title":"Linux是怎样工作的","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介 §\n\n书名:《Linux是怎样工作的》\n作者: 武内觉 著\n分类: 计算机-编程设计\nISBN:9787115581617\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分类: 计算机-编程设计\nISBN:9787115584045\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\n(1) 运行时校验:在执行阶段进行特定校验,当校验通不过时终止执行。· 适合原因:装饰器可以方便地在函数执行前介入,并且可以读取所有参数辅助校验。· 代表样例: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条设计原则。· S:single responsibility principle(单一职责原则,SRP)。· O:open-closed principle(开放–关闭原则,OCP)。· L:Liskov substitution principle(里式替换原则,LSP)。· I:interface segregation principle(接口隔离原则,ISP)。· D:dependency 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\nTDD(test-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分类: 计算机-编程设计\nISBN:9787115592422\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上述代码的执行演示过程见https://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分类: 计算机-编程设计\nISBN:9787115546081\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分类: 计算机-数据库\nISBN:9787115539168\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/计算机/SRE:Google运维解密":{"title":"SRE:Google运维解密","links":[],"tags":["阅读/计算机-计算机综合","阅读/笔记"],"content":"简介 §\n\n书名:《SRE:Google运维解密》\n作者: 贝特西·拜尔等\n分类: 计算机-计算机综合\nISBN:9787121297267\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 系统内部细节和1~3层网络知识是Google最看重的两类额外的技术能力。\n\n\n所有的SRE团队成员都必须非常愿意、也非常相信用软件工程方法可以解决复杂的运维问题。\n\n\n(a)对重复性、手工性的操作有天然的排斥感。(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分类: 计算机-计算机综合\nISBN:9787115557179\n出版社:人民邮电出版社\n\n概述 §\n自1969年在贝尔实验室的阁楼上诞生以来,Unix操作系统的发展远远超出其创造者们的想象。它带动了许多创新软件的开发,影响了无数程序员,改变了整个计算机技术的发展轨迹。本书不但书写Unix的历史,而且记录作者的回忆,一探Unix的起源,试图解释什么是Unix,Unix是如何产生的,以及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 Hopper,1906—1992),她在UNIVAC I大型机上开发出了一个名为A-0(Arithmetic 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)每个用户可选择不同的系统命令语言;(5)100多个子系统,包括十几种语言\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在之后的多年里,更多的功能被添加进来,Bash(Bourne 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💭 http://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分类: 计算机-计算机综合\nISBN:9787121417870\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分类: 计算机-编程设计\nISBN:9787121361128\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万行以下的代码量的汉子来说,设计模式=玄学;对于10~50万行代码量的汉子来说,设计模式=科学;对于50万行以上代码量的汉子来说,设计模式=文学。\n\n\n软件的设计是一个循序渐进、逐步优化的过程。\n\n\nRule of three 称为“三次法则”,指的是当某个功能第三次出现时,再进行抽象化,即事不过三,三则重构。\n\n\n(1)重复的代码太多,没有复用性,难以维护,需要修改时处处都得改。(2)代码的结构混乱,注释不清晰,没有人能清楚地理解这段代码的含义。(3)程序没有拓展性,遇到新的变化,不能灵活处理。(4)对象结构强耦合,业务逻辑太复杂,牵一发而动全身,维护时排查问题非常困难。(5)部分模块性能低,随着用户数量的增长,已无法满足响应速度的要求。\n\n\n一是对现有项目进行代码级别的重构;二是对现有的业务进行软件架构的升级和系统的升级。\n\n\n创建型模式、结构型模式和行为型模式\n\n\n创建型,即关注的是对象的创建和初始化过程;结构型,即关注的是对象的内部结构设计;行为型,即关注的是对象的特性和行为。\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/计算机/从0到1:HTML+CSS快速上手":{"title":"从0到1:HTML+CSS快速上手","links":[],"tags":["阅读/计算机-编程设计","阅读/笔记"],"content":"简介 §\n\n书名:《从0到1:HTML+CSS快速上手》\n作者: 莫振杰\n分类: 计算机-编程设计\nISBN:9787115510327\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到1:HTML5+CSS3修炼之道":{"title":"从0到1:HTML5+CSS3修炼之道","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介 §\n\n书名:《从0到1:HTML5+CSS3修炼之道》\n作者: 莫振杰\n分类: 计算机-编程设计\nISBN:9787115525055\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到1:JavaScript-快速上手":{"title":"从0到1:JavaScript 快速上手","links":[],"tags":["阅读/计算机-数据库","阅读/笔记"],"content":"简介 §\n\n书名:《从0到1:JavaScript 快速上手》\n作者: 莫振杰\n分类: 计算机-数据库\nISBN:9787115513007\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到1:jQuery快速上手":{"title":"从0到1:jQuery快速上手","links":[],"tags":["阅读/计算机","阅读/笔记"],"content":"简介 §\n\n书名:《从0到1:jQuery快速上手》\n作者: 莫振杰\n分类: 计算机-编程设计\nISBN:9787115526335\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分类: 计算机-编程设计\nISBN:9787115583765\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分类: 计算机-计算机综合\nISBN:9787302479703\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分为开源免费的CE(Community Edition)版本和收费的EE(Enterprise 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的取值为1~4094。\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分类: 计算机-编程设计\nISBN:9787115454157\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的每个元素都是真值,返回True;all([])返回True。any(iterable)只要iterable中有元素是真值,就返回True;any([])返回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分类: 计算机-计算机综合\nISBN:9787115516824\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分类: 计算机-编程设计\nISBN:9787115549365\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分类: 计算机-计算机综合\nISBN:9787115599438\n出版社:人民邮电出版社有限公司\n\n概述 §\n对于刚刚成为软件工程师的新手来说,知道如何编写代码只是成功了一半。你可能很快就会发现,学校并没有教授在现实世界中至关重要的技能和工作中必要的流程。本书恰恰填补了这一环节,它是作者十多年来在大型公司指导初级工程师工作的教程,涵盖软件工程的基础知识和best实践。 本书第1~2 章讲解当你在公司开启你的职业生涯时会发生什么;第3~11 章会扩展你的工作技能,教你如何使用现有代码库、解决和防止技术债、编写生产级软件、管理依赖关系、有效地测试、评审代码、交付软件、处理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 integration,CI)系统来绕过这个问题,这是一种糟糕的做法。\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 product,MVP)所不需要的产品特性——你需要那些可以获得用户反馈的最低限度的功能集。\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 code,CAC)的哲学认为,配置应该受到与代码同样严格的要求。配置错误可能是灾难性的,一个错误的整数或缺失的参数就可以毁掉一个应用程序。\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分类: 计算机-编程设计\nISBN:9787115526861\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分类: 计算机-理论知识\nISBN:9787115549976\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分类: 计算机-计算机综合\nISBN:9787121376627\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分类: 计算机-计算机综合\nISBN:9787115441249\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分类: 计算机-理论知识\nISBN:9787302429845\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分类: 计算机-编程设计\nISBN:9787111673248\n出版社:机械工业出版社\n\n概述 §\n《虚拟化工程师运维实战:VMware服务器虚拟化+Citrix桌面/应用虚拟化+Veeam备份+Zabbix监控》详细介绍了实际运维工作中虚拟化工程师应该熟练掌握的虚拟化技术。全书共7章,分别是虚拟化技术概述、虚拟化工程师应知必会的六件事、部署IT基础架构服务器、实现服务器虚拟化—基于VMwarevSphere、实现桌面/应用虚拟化—基于CitrixVirtualAppsandDesktops、虚拟化备份—基于VeeamBackup&Replication,实现对虚拟化环境的灵活监控。本书图文并茂,步骤详细,介绍了大量的实用知识,能够让读者清晰地理解虚拟化项目部署中的操作细节。本书适合于从事企业信息化运维工作的虚拟化工程师学习,也可以作为项目管理人员实施企业虚拟化项目的参考书,还可作为高等院校虚拟化技术相关课程的教材。\n划线 §\n\n虚拟化技术在企业中的应用主要涉及服务器虚拟化、桌面虚拟化和应用程序虚拟化三方面:\n\n\n云计算分成3个层次,分别是IaaS(Infrastucture as a Service,基础架构即服务)、PaaS(Platform as a Service,平台即服务)和SaaS(Software as a Service,软件即服务)\n\n\n根据云计算资源所在的位置,分成公有云、私有云和混合云3种。公有云,是指所有的资源都放在厂商建设的数据中心,用户通过互联网接入,获取到相应的云资源,使用便捷,按需付费。私有云,是指所有的资源都由用户方进行建设,放在自有的数据中心中。资源固定,安全性高。混合云,是私有云和公有云的结合。\n\n\n在各大招聘网站上搜索。从各个招聘渠道去搜索虚拟化工程师、系统工程师、IT工程师、IT技术支持等\n\n\n1)IT管理:管理技术团队、ITIL、PMP。2)IT基础架构:微软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等。对于虚拟化工程师来说,掌握1~2种常见的服务器虚拟化产品的部署、调试和维护是必不可少的技能。\n\n\n服务器提供了计算资源,网络设备将服务器之间连通,存储设备提供了数据存储的空间。\n\n\n常见的监控软件有IBM Tivoli、SolarWinds、Zabbix、Cacti、Nagios、Ganglia等。\n\n\n基础架构的范围比较广泛,广义上包含服务器等计算机设备、路由器、交换机等网络设备,存储阵列、防火墙等安全设备,机房制冷设备等,狭义上特指微软相关的基础架构服务器,例如域控制器、DNS(Domain Name System,域名系统)服务器、DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)服务器、WSUS(Windows Server Update Services,Windows Server更新服务)服务器等。\n\n\n这就好比是一个部门的员工,大家各自负责一方面的工作内容,有人负责服务器,有人负责网络,也有人负责安全。但随着员工数量的增多,老板没有更多的精力管理所有员工,于是指定了一个部门经理,专门管理其中一部分员工。这样一来部门经理来统一规定本部门员工的工作内容和指定规章制度等。针对大规模的计算机来说,也要实现统一的管理就需要借助AD来帮忙。域控制器担任了“部门经理”的角色,部门经理的存在就决定了整个部门的成立,而其他的计算机由域控制器进行统一管理。\n\n笔记 §\n书评 §\n点评 §"},"Personal/Book/计算机/计算机:一部历史":{"title":"计算机:一部历史","links":[],"tags":["阅读/计算机-理论知识","阅读/笔记"],"content":"简介 §\n\n书名:《计算机:一部历史》\n作者: 彼得·本特利\n分类: 计算机-理论知识\nISBN:9787121255113\n出版社:中信出版集团\n\n概述 §\n《计算机:一部历史》,给大众读者写的计算机科普读物,零门槛入门计算机科学。讲述计算机背后鲜为人知的故事,普及关于计算机和互联网,你不得不了解的知识。在过去数十年里,除非你一直与世隔绝,否则就不可能不受到信息革命的影响。我们身处技术演进史上的计算机时代,无论你是计算机和互联网的拥护者、反对者还是旁观者,无论你是否具备计算机专业背景,只要你使用计算机,这本书就是你的案头必备。\n\n划线 §\n\n显然,无论从事哪一个行业,要想赚取巨额财富,通晓计算机是必不可少的条件。\n\n\n计算机或许是我们无声的奴隶,盲目地执行每一项指令,但是我认为,我们可以从计算机上学到很多东西,通过它们了解这个世界乃至人类自身。\n\n\n计算机科学主要涉及到编程、工程学和数学\n\n\n德国的著名密码系统——“恩尼格玛”(9)(Enigma)\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预期的时间:实际的时间 = 1:1.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 和 JumpServer,Linux 因为身体原因和生活琐事导致进度较为缓慢,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.10,6.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.10,6.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\n(主)Linux 学习:进行中,进度 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 Didn’t 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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📊 ThisWeek’s 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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📊 ThisWeek’s 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📊 ThisWeek’s 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📊 ThisWeek’s 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/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 Didn’t 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📊 ThisWeek’s 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📊 ThisWeek’s 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 Didn’t 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📊 ThisWeek’s 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/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 服务按需求划分为不同的层级。主要的云服务模型包括IaaS(Infrastructure as a Service,基础设施即服务)、PaaS(Platform as a Service,平台即服务)*和*SaaS(Software as a Service,软件即服务)。这三种模型为企业提供了不同层次的服务,从基础的硬件资源到高级的软件应用,各层次都具备灵活性和可扩展性。\n\nIaaS:为企业提供虚拟化的计算资源,包括服务器、存储和网络等。它允许企业像管理物理资源一样管理云端的基础设施,但无需负责硬件的维护。\nPaaS:在 IaaS 之上,PaaS 为企业提供了开发和部署应用程序的平台,企业可以专注于应用程序的开发,而不需要管理底层基础设施。这极大地提高了应用开发的效率。\nSaaS:SaaS 进一步抽象化,直接向企业用户提供了完整的应用程序,如办公套件、客户关系管理(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域名的分层结构是企业内部网络资源组织和命名的重要基础。通常,企业内部的域名分层可分为一级域名、二级域名和三级域名,这些层次共同构成了完整的命名体系,用于区分和标识企业内的不同服务、应用和资源。\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\n示例:7wate.dev 作为顶级域名的分层结构 §\n以7wate.dev作为企业的顶级域名,结合云服务模型进行域名的分层划分,能够有效组织企业的网络资源。以下是一个示例说明:\n\n一级域名:7wate.dev——作为企业的核心顶级域名,所有内部网络服务以此为根。\n二级域名:根据不同的云服务模型进行划分:\n\nIaaS 层:compute.7wate.dev(用于计算资源管理)、network.7wate.dev(用于网络资源管理)、storage.7wate.dev(用于存储服务管理)\nPaaS 层:app.7wate.dev(用于应用开发与运行时环境)、database.7wate.dev(用于数据库管理)、container.7wate.dev(用于容器管理)\nSaaS 层:crm.7wate.dev(用于客户关系管理)、erp.7wate.dev(用于企业资源规划)、hrms.7wate.dev(用于人力资源管理系统)\n\n\n三级域名:细分具体服务和功能,例如:\n\nvpn.network.7wate.dev(用于 VPN 管理服务)\ntest.app.7wate.dev(用于应用的测试环境)\nnosql.database.7wate.dev(用于 NoSQL 数据库管理)\n\n\n\n通过这种域名分层结构,企业能够在不同服务层次上明确区分各类资源,并为管理和维护提供更高效的访问路径。\n2.2 IaaS、PaaS、SaaS 三层服务模型下的域名分配 §\n现代企业的 IT 服务通常采用 IaaS、PaaS 和 SaaS 三层服务模型,每一层都有其独特的功能和特性,因此在域名规划上需要根据各层的特点进行合理划分。下面我们将详细说明每一层的域名分配策略。\nIaaS 层域名规划 §\nIaaS(基础设施即服务)为企业提供虚拟化的计算资源、存储资源、网络管理和安全服务。在 IaaS 层中,资源往往以基础设施为中心,域名规划需要反映这一特性,确保对基础设施资源的精细化管理。\n\n计算资源(Compute):用于管理虚拟机、容器化服务、裸金属服务器等计算资源。例如,compute.7wate.dev 可以用来标识所有与计算相关的资源,进一步细化时,可以引入三级域名,如 vm.compute.7wate.dev(虚拟机管理) 或 container.compute.7wate.dev(容器管理)。\n存储资源(Storage):存储资源包括对象存储、文件存储、块存储等,典型的二级域名可以是 storage.7wate.dev。针对不同的存储服务,可以引入如 backup.storage.7wate.dev(用于数据备份)或 file.storage.7wate.dev(用于文件存储)的三级域名。\n网络管理(Networking):用于管理虚拟私有云(VPC)、负载均衡、内容分发网络(CDN)等网络资源。例如,network.7wate.dev 作为网络资源的总入口,可以通过三级域名进一步区分,如 vpn.network.7wate.dev(用于 VPN 管理)、cdn.network.7wate.dev(用于 CDN 管理)。\n安全管理(Security):在 IaaS 层,安全服务通常包括身份验证、访问控制、防火墙、加密等。安全管理的域名规划可以采用 security.7wate.dev,三级域名可用于标识具体安全服务,如 firewall.security.7wate.dev(用于防火墙管理)。\n\nPaaS 层域名规划 §\nPaaS(平台即服务)主要用于支持应用开发、测试和部署的技术平台。这一层的域名分配应考虑到开发环境、运行时环境、容器编排和中间件服务等需求。\n\n应用开发与运行时(Application Development and Runtime):应用开发与运行时环境可以使用 app.7wate.dev 作为二级域名,以此标识所有与应用开发相关的服务。进一步的三级域名可以用于区分测试环境、开发环境和生产环境,例如 test.app.7wate.dev(测试环境)和 prod.app.7wate.dev(生产环境)。\n容器管理(Container Management):容器化应用的管理通常涉及 Kubernetes 或 Docker 等技术,使用 container.7wate.dev 作为二级域名,通过三级域名进一步区分不同的集群或服务,如 k8s.container.7wate.dev(用于 Kubernetes 集群管理)。\n数据库管理(Database Management):PaaS 层下的数据库服务可以通过 database.7wate.dev 管理,三级域名可以区分不同类型的数据库服务,如 sql.database.7wate.dev(用于关系型数据库)和 nosql.database.7wate.dev(用于 NoSQL 数据库)。\n中间件与消息队列(Middleware and Messaging):中间件和消息队列服务可以通过 middleware.7wate.dev 进行统一管理,三级域名可以划分不同的中间件服务,如 kafka.middleware.7wate.dev(用于 Kafka 消息队列)或 mq.middleware.7wate.dev(用于消息队列服务)。\n\nSaaS 层域名规划 §\nSaaS(软件即服务)主要提供企业级的应用软件,帮助企业实现办公协作、客户关系管理、资源规划等功能。SaaS 层的域名规划应关注应用的最终用户,并确保每个应用有明确的域名标识。\n\n办公协作(Collaboration Tools):办公协作服务可以通过 collab.7wate.dev 进行标识,包括电子邮件、文档共享、视频会议等服务。三级域名可以区分不同的服务模块,如 email.collab.7wate.dev(电子邮件服务)和 drive.collab.7wate.dev(文档存储服务)。\n客户关系管理(CRM):CRM 系统可以通过 crm.7wate.dev 进行标识,用于管理销售、客户支持和营销服务。\n企业资源规划(ERP):ERP 系统是企业的核心管理软件,涵盖了财务、供应链、制造、采购等多个领域。通过 erp.7wate.dev 标识该系统,三级域名可以进一步细化为不同的 ERP 模块,例如 finance.erp.7wate.dev(财务模块)和 supply.erp.7wate.dev(供应链模块),确保各个业务模块有独立的域名进行管理。\n人力资源管理系统(HRMS):人力资源管理系统通过 hrms.7wate.dev 进行标识,用于管理员工档案、薪酬福利、招聘培训等人力资源流程。可以通过三级域名区分不同的人力资源管理模块,例如 payroll.hrms.7wate.dev(薪资管理模块)和 recruitment.hrms.7wate.dev(招聘管理模块)。\n财务与会计管理(Finance & Accounting):企业的财务与会计管理系统可以通过 finance.7wate.dev 进行标识,三级域名可以进一步细分,如 billing.finance.7wate.dev(账单管理)和 audit.finance.7wate.dev(审计服务),方便对财务流程的精细化管理。\n项目管理(Project Management):项目管理系统通常用于跟踪项目进度、分配任务和团队协作,project.7wate.dev 可以作为二级域名,三级域名可以用于区分不同的项目管理工具或模块,如 tracking.project.7wate.dev(项目进度追踪)和 tasks.project.7wate.dev(任务分配与管理)。\n电子商务管理(E-Commerce):电子商务平台管理包括产品目录、订单处理、支付系统等,通过 ecommerce.7wate.dev 进行标识。可以使用三级域名区分具体的服务模块,如 catalog.ecommerce.7wate.dev(产品目录管理)和 payment.ecommerce.7wate.dev(支付系统管理)。\n\n三级域名的引入:在复杂服务下细分子服务的命名规则 §\n随着企业 IT 基础设施的复杂化,仅靠一级域名和二级域名无法完全涵盖企业的多层次、多业务模块需求。因此,三级域名的引入成为细分和管理子服务的有效手段。通过在二级域名下进一步引入三级域名,企业可以对每个独立的子服务进行更精准的管理,同时保持命名的结构化和逻辑性。\n三级域名允许企业在现有的域名层次结构中细化管理,同时为未来的业务扩展留有足够的灵活性。以下是三级域名的几种常见使用场景:\n\n服务细分:当一个二级域名下的服务较为复杂时,三级域名可以用于对服务进行进一步细分。例如,vpn.network.7wate.dev 可以标识 VPN 服务,而 cdn.network.7wate.dev 则用于标识内容分发网络服务。通过这种方式,企业可以清晰地区分网络管理下的不同服务,方便维护和扩展。\n环境区分:对于应用开发和运行时环境,通常需要多个环境(如开发、测试、生产)并行运行。通过三级域名,可以将不同的环境区分开来。例如,在 app.7wate.dev 的基础上,可以引入 test.app.7wate.dev(测试环境)、dev.app.7wate.dev(开发环境)和 prod.app.7wate.dev(生产环境)。这种环境区分不仅有助于开发和运维团队的工作,还能有效防止不同环境之间的资源冲突。\n多业务模块支持:对于 ERP、CRM 等系统,通常会包含多个独立的业务模块。通过三级域名的引入,企业可以为每个业务模块分配独立的域名。例如,finance.erp.7wate.dev 可以用于管理财务模块,而 hr.erp.7wate.dev 则专注于人力资源管理模块。这种命名方式不仅简化了系统的运维管理,还提升了系统的可读性和组织性。\n地域或数据中心区分:对于分布式架构或多数据中心部署的企业,三级域名可以用于区分不同的地域或数据中心。比如,us-east.compute.7wate.dev 用于标识位于美国东部数据中心的计算资源,而 eu-west.compute.7wate.dev 用于标识欧洲西部的数据中心。通过这种方式,企业能够更加清晰地管理分布在全球各地的资源,提升业务的可扩展性和灵活性。\n\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 可以代表应用程序(Application),db 可以代表数据库(Database),net 可以代表网络服务(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专用二级域名:为无服务器架构设计独立的二级域名,可以确保这一架构下的资源与传统的 IaaS 或 PaaS 服务区分开来。例如,serverless.7wate.dev 可以作为无服务器应用的专用域名前缀,确保与传统服务的命名空间隔离开。此命名方式直观表达了该域名指向的是无服务器计算资源。\n事件驱动的子域名结构:在无服务器架构中,很多服务是事件驱动的。可以根据事件类型或功能创建不同的三级域名。例如:\n\nupload.serverless.7wate.dev:处理文件上传的无服务器函数。\nprocess.serverless.7wate.dev:处理数据处理事件的函数。\n\n\n\n通过这种方式,可以清晰划分不同的无服务器函数,便于管理和扩展。\n\n动态扩展与命名约定:Serverless 架构的另一个特点是服务自动扩展。因此,域名规划需要支持动态扩展的功能。例如,可以根据特定任务的不同版本或部署环境创建独立的域名,确保开发、测试、生产环境各自独立,如 v1.dev.serverless.7wate.dev 和 prod.serverless.7wate.dev。\n\n灵活性与扩展性:无服务器架构的优势在于其高度自动化和动态扩展的能力,因此,域名规划必须灵活适应这种动态性,确保每个服务调用都能快速、精准地对应到相应的资源。\n5.2 边缘计算(Edge Computing)域名规划 §\n边缘计算(Edge Computing)是在网络边缘处理数据的技术,特别适用于低延迟、高带宽需求的应用场景,如物联网(IoT)、实时数据处理和视频流传输。在边缘计算环境中,设备通常分布在地理上分散的多个位置,传统的集中式计算无法有效满足这些设备的需求。因此,域名规划必须考虑如何有效地管理分布在不同地理区域、数据中心和网络边缘节点的资源。\n域名规划策略:\n\n\n地理区分的二级域名\n:为边缘计算设备设计域名时,考虑到设备的地理分布,可以通过在域名中引入地理位置的标识来明确节点所在的区域。例如:\n\nus-west.edge.7wate.dev:表示美国西部的边缘计算节点。\neu-central.edge.7wate.dev:表示位于欧洲中部的数据中心或边缘节点。\n\n\n\n通过这种方式,可以快速识别不同地理位置的边缘节点,并进行针对性的管理和优化。\n\n\n设备类型的细分\n:边缘计算中的设备类型多样,可能包括传感器、网关、服务器等。可以通过三级域名对设备类型进行区分。例如:\n\nsensor1.us-west.edge.7wate.dev:用于标识位于美国西部的传感器设备。\ngateway.eu-central.edge.7wate.dev:用于标识位于欧洲中部的边缘网关设备。\n\n\n\n通过这种命名方式,不仅可以区分设备的物理位置,还可以标识其功能角色,便于运维人员对边缘设备的监控和维护。\n\nIoT 设备的域名分配:物联网设备通常数量庞大且部署分散,采用独立的命名规则可以避免冲突。例如,可以根据设备 ID 或功能为每个设备生成唯一的域名,如 device123.iot.edge.7wate.dev 或 camera1.edge.7wate.dev。这种方式确保每个设备有唯一的域名,便于快速定位和管理。\n\n可扩展性:由于边缘计算节点的部署是动态且分散的,域名规划应预留足够的空间以适应设备的大规模增长和地理分布的变化。\n5.3 多云策略下的域名管理 §\n随着企业逐渐采用多云策略,即同时使用多个云服务提供商的资源,域名管理面临新的挑战。不同云平台上的资源需要在命名上加以区分,同时又要保持一致的管理方式,以避免管理的混乱。通过设计合理的域名结构,企业能够有效地组织和管理多云环境中的资源,并提高不同云平台之间的互操作性。\n域名规划策略:\n\n\n云提供商区分的二级域名\n:为了清晰区分不同云提供商的资源,可以在域名中引入云提供商的标识。例如:\n\naws.compute.7wate.dev:用于标识 AWS 上的计算资源。\ngcp.compute.7wate.dev:用于标识 Google Cloud 上的计算资源。\n\n\n\n这种命名方式不仅帮助企业清晰地组织多云环境中的资源,还为运维人员提供了直观的识别手段,便于多云平台的管理和监控。\n\n跨云服务的命名一致性:虽然不同云平台之间的资源需要加以区分,但为了保持整体的管理一致性,应采用相似的命名规则。例如,AWS 和 Azure 的数据库服务分别使用 aws.database.7wate.dev 和 azure.database.7wate.dev,这种方式确保不同云平台的服务命名结构一致,便于跨平台的管理和监控。\n多云资源的自动化管理:企业可以通过自动化工具(如 Terraform、Ansible)为多个云平台配置统一的域名管理策略,确保不同平台上的 DNS 配置能够自动同步并保持一致。通过自动化配置,企业能够轻松管理跨云服务的域名解析,减少手动配置的复杂性和错误率。\n\n冗余与高可用性:在多云环境下,企业可以通过域名冗余实现高可用性。使用多个云服务提供商的域名配置,确保当一个云平台的资源不可用时,流量可以无缝转移到另一个平台。例如,通过配置 failover.aws.compute.7wate.dev 和 failover.azure.compute.7wate.dev,确保服务的高可用性。\n6. 域名管理的最佳实践 §\n为了确保企业在域名管理方面具备良好的组织性、可操作性和一致性,必须制定一套完善的最佳实践。这些实践不仅能够有效规范域名的命名、分配、生命周期管理,还能提升跨部门的协作和沟通效率。通过这些措施,企业可以确保域名资源的长期可用性、减少管理中的冲突和错误,并为未来的扩展做好准备。\n6.1 域名命名的标准化流程 §\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域名的生命周期管理是确保域名资源合理分配、有效使用和及时回收的重要措施。企业的域名从创建到废弃,经历多个阶段,每个阶段都需要清晰的管理流程和监控机制。\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在企业中,域名不仅是技术团队的关注点,也与业务部门、产品团队密切相关。为了确保域名规划的有效执行,跨部门的沟通与培训是关键的一环。\n跨部门沟通建议:\n\n建立跨部门的沟通机制:确保 IT 部门与业务部门之间的紧密协作。例如,业务部门在规划新服务时,应该提前通知 IT 部门,确保域名能够合理分配,并为即将上线的服务做准备。域名命名和分配需要业务部门的参与,以确保命名符合业务目标并具有实际意义。\n技术与业务的双向沟通:技术团队应向业务部门解释域名命名和分配的标准和规则,确保业务部门理解其重要性。同时,业务部门也应向技术团队反馈命名方案的合理性,确保域名命名符合产品需求和用户体验。\n透明化的审批流程:通过透明的域名申请与审批流程,业务团队能够清楚了解域名分配的状态和审批进度。技术团队应通过定期的沟通会或邮件通知,向业务部门汇报域名管理的状态与进展。\n\n培训计划:\n\n域名管理培训:所有相关团队(如开发、运维、产品和安全团队)应接受关于域名管理的基本培训。培训内容应包括域名命名规则、申请与审批流程、如何监控和维护域名,以及简拼缩写的使用规范。\n简拼缩写的使用规范:由于不同部门可能对简拼和全拼的理解存在差异,培训应明确简拼的使用场景和规则。提供统一的简拼对照表,并通过实例演示如何正确使用简拼和全拼。例如,app.7wate.dev 代表应用服务,而 db.7wate.dev 代表数据库服务,这些命名规则必须在培训中详细解释。\n持续性学习与更新:随着企业的业务变化和技术更新,域名管理的规范也会不断演进。因此,企业应定期组织培训,更新域名命名规则和管理流程,并确保所有团队都能掌握最新的域名管理标准。\n\n培训效果的评估:企业可以通过定期的反馈机制评估培训效果,确保所有团队对域名管理有足够的理解和应用能力。通过内部问卷或测试评估培训效果,及时调整培训内容,确保培训能够跟上技术和业务需求的变化。\n7. 实例分析 §\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,并根据不同业务模块、地域和服务类型划分二级和三级域名。\n\n\nIaaS 服务: 企业 A 的基础设施服务(IaaS)主要涵盖全球多个数据中心的计算、存储和网络资源。\n\n\n计算资源\n:\ncompute.enterpriseA.com\n\n\n北美数据中心:us.compute.enterpriseA.com\n亚太地区数据中心:ap.compute.enterpriseA.com\n\n\n\n存储资源\n:\nstorage.enterpriseA.com\n\n\n美国东部存储:us-east.storage.enterpriseA.com\n欧洲存储:eu.storage.enterpriseA.com\n\n\n\n网络资源\n:\nnetwork.enterpriseA.com\n\n\n主要网络节点:vpn.network.enterpriseA.com(VPN 服务)\nCDN 服务:cdn.network.enterpriseA.com\n\n\n\n\n\nPaaS 服务: 企业 A 为其开发团队提供了丰富的 PaaS 平台,支持应用开发、测试和运行。\n\n\n应用开发平台\n:\napp.enterpriseA.com\n\n\n开发环境:dev.app.enterpriseA.com\n生产环境:prod.app.enterpriseA.com\n\n\n\n数据库管理\n:\ndb.enterpriseA.com\n\n\n关系型数据库:sql.db.enterpriseA.com\nNoSQL 数据库:nosql.db.enterpriseA.com\n\n\n\n\n\nSaaS 服务: 企业 A 提供的 SaaS 服务涵盖电子商务、CRM 和其他企业应用服务。\n\n\n电子商务平台\n:\necommerce.enterpriseA.com\n\n\n北美电商平台:us.ecommerce.enterpriseA.com\n欧洲电商平台:eu.ecommerce.enterpriseA.com\n\n\n\nCRM 系统\n:\ncrm.enterpriseA.com\n\n\n营销自动化:marketing.crm.enterpriseA.com\n客户支持:support.crm.enterpriseA.com\n\n\n\n\n\n物联网(IoT)设备管理: 企业 A 拥有大量分布在全球的 IoT 设备,需对每个设备进行精细化管理和监控。\n\n\nIoT 设备管理平台\n:\niot.enterpriseA.com\n\n\n北美传感器:sensor.us.iot.enterpriseA.com\n亚太地区摄像头:camera.ap.iot.enterpriseA.com\n\n\n\n\n\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通过该简拼对照表,企业可以有效减少命名冲突,并在命名时保持简洁与一致。\n\nB. 域名规划工具与资源 §\n为了提高域名管理的效率和可靠性,企业可以借助多种工具来实现自动化的域名分配、管理和监控。以下是一些推荐的 DNS 管理和自动化部署工具:\n1. DNS 管理工具:\n\nBind:一种广泛使用的开源 DNS 服务器软件,提供灵活的域名解析功能,适用于中大型企业的本地 DNS 部署。它支持多种安全功能,如 DNSSEC 和防缓存中毒。\nPowerDNS:另一款高性能的开源 DNS 服务器,具备灵活的后端支持,包括数据库和 API 管理功能。适合需要高可用性和集成灵活性的企业。\nAmazon Route 53:AWS 提供的云 DNS 服务,支持全球范围的域名解析,具有自动化功能,并且与 AWS 生态系统深度集成,适合使用 AWS 云服务的企业。\nGoogle Cloud DNS:Google 提供的云 DNS 服务,支持地理负载均衡和自动化管理,适合使用 GCP 的企业。\n\n2. 自动化部署工具:\n\nAnsible:Ansible 是一款流行的自动化工具,支持基础设施即代码(IaC),能够快速实现批量的 DNS 记录管理和域名配置。其简洁的 YAML 语法使得复杂的任务易于编写和管理。\nTerraform:Terraform 提供了强大的多云管理功能,支持 AWS Route 53、Google Cloud DNS 等云 DNS 服务的自动化管理。它通过声明式配置文件来定义 DNS 记录,使得变更管理更加直观和可控。\nPuppet:Puppet 是另一种基础设施自动化工具,适用于复杂环境下的 DNS 管理。它支持模块化管理,能够通过编写配置文件来自动部署和更新 DNS 记录。\n\n3. 域名监控工具:\n\nNagios:Nagios 是一款开源的网络监控工具,能够帮助企业实时监控 DNS 服务器的状态和性能,并及时发现潜在问题。它支持通过自定义脚本监控域名解析的可用性。\nZabbix:Zabbix 同样是一款强大的监控工具,支持 DNS 解析监控,能够生成实时的性能报告并自动通知故障情况。\n\n4. 域名管理平台:\n\nCloudflare:Cloudflare 不仅是 DNS 服务提供商,还提供内容分发网络(CDN)、DDoS 防护等功能,适合对安全性要求较高的企业。其管理界面简洁,自动化集成方便。\nDNSimple:DNSimple 是一款简单易用的域名管理服务,适合中小企业进行 DNS 自动化管理和 API 集成。\n\n这些工具能够大大简化企业的域名管理任务,减少手动操作的复杂性,并且提高整体运维效率。\n\nC. 域名分配相关的标准和合规性要求 §\n在全球化运营背景下,企业的域名管理需要遵循相关法律法规和行业标准,确保合法合规的域名使用。以下是企业在域名管理中需要关注的主要标准和合规性要求:\n1. GDPR(General 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/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/full-stack/home":{"title":"前端工程师(Front-End Engineer)","links":[],"tags":[],"content":"前端工程师(Front-End Engineer) §\n前端工程师是负责构建和维护网页或 Web 应用用户界面的专业人员,他们将设计师的设计稿和后端开发者的 API 转换为可以在浏览器上运行的网页或应用。\n职责与工作内容:\n\n构建用户界面:使用 HTML、CSS 和 JavaScript 构建网页或应用的用户界面。\n实现交互效果:编写 JavaScript 代码来实现用户与网页或应用的交互。\n优化性能:优化前端代码和资源加载,提升网页的加载速度和运行性能。\n响应式设计:使网页或应用能够适应不同的设备和屏幕尺寸。\n与后端协作:与后端开发者协作,实现数据的前后端交互。\n测试与调试:使用各种工具对前端代码进行测试和调试,保证代码的质量和稳定性。\n\n必备技能与知识:\n\nHTML/CSS/JavaScript:这是前端开发的基础,HTML 用于描述网页内容,CSS 用于描述网页样式,JavaScript 用于实现网页交互。\n前端框架和库:如 React、Angular 或 Vue.js,这些框架能够帮助开发者更容易地构建复杂的前端应用。\n版本控制系统:如 Git,用于代码的版本管理和多人协作。\n构建和打包工具:如 Webpack、Babel,用于优化和转译前端代码。\n浏览器开发工具:理解并熟练使用浏览器的开发者工具,用于代码调试和性能分析。\n对用户体验的理解:理解并关注用户体验,包括交互设计、可访问性、性能优化等。\n\n总体来说,前端工程师的目标是构建和维护高性能、易用、美观的用户界面,他们通过技术手段,使得用户可以愉快、高效地使用网页或 Web 应用,满足用户的需求。他们的工作直接影响到用户的体验,对于提升产品的价值和满足客户需求至关重要。\nRoadMap §\n"},"Professional/Work/full-stack/基础/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 元素的实际宽度是 350px(300px 的内容宽度 + 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('https://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-property,transition-duration,transition-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-color,height,all 等。background-colortransition-duration指定过渡效果花费的时间,以秒(s)或毫秒(ms)为单位。2stransition-timing-function规定过渡效果的速度曲线。可选值有 linear,ease,ease-in,ease-out,ease-in-out,cubic-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 §\nSASS(Syntactically 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 更加强大和易于维护,它们是现代前端开发工具链的重要组成部分。"},"Professional/Work/full-stack/基础/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="http://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="http://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 为表单输入引入了新的元素类型,如 color,date,email,number,range,search,tel,time 等。还引入了新的表单元素,如 <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 API,Drag and Drop API,Local 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="https://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="https://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 主要由 IE,Safari 和 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)可以更好地控制页面布局,同时也能提高页面的可访问性和响应式设计的能力。"},"Professional/Work/full-stack/基础/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 Model,BOM)是用于与浏览器交互的模型。**它提供了一种方式,使开发者能够通过 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 Model,DOM)是一种编程接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。**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 中发生的错误。"},"Professional/Work/full-stack/工具/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.log:PM2 的日志文件。\n$HOME/.pm2/pm2.pid:PM2 的进程 ID 文件。\n$HOME/.pm2/rpc.sock:用于远程命令的 Socket 文件。\n$HOME/.pm2/pub.sock:用于发布事件的 Socket 文件。\n$HOME/.pm2/conf.js:PM2 的配置文件。\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 应用程序的理想选择。"},"Professional/Work/full-stack/工具/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 Splitting):Webpack 可以将代码分割成多个 bundle,从而实现按需加载和并行加载。\n懒加载(Lazy Loading):Webpack 支持懒加载,即按需加载某个模块,可以有效地减少应用的初始加载时间。\n模块热替换(Hot Module Replacement,HMR):Webpack 支持 HMR,可以在运行时替换、添加或删除模块,而无需进行完全刷新。\nLoaders:Webpack 使用 loaders 来处理非 JavaScript 类型的文件,如 CSS、HTML、图片等。\nPlugins:Webpack 使用 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 仍然是目前最受欢迎和最广泛使用的模块打包器之一。"},"Professional/Work/full-stack/工具/包管理工具":{"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.0,C 依赖 B@2.0;依赖安装后究竟该提升 B 为 1.0 还是 2.0 取决于用户的安装顺序。\n依赖分身 §\n假设继续再安装依赖 B@1.0 的 D 模块和依赖 @B2.0 的 E 模块,此时:A 和 D 依赖 B@1.0;C 和 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 https://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 https://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检查项目依赖项中的已知的漏洞\nnpm,yarn,pnpm 功能比较 §\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\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❌✔️Plug’n’Play✔️✔️ - 默认❌零安装❌✔️❌修补依赖项✔️✔️❌管理 Node.js 版本✔️❌❌有锁文件✔️ - pnpm-lock.yaml✔️ - yarn.lock✔️ - package-lock.json支持覆盖✔️✔️ - 通过 resolutions✔️内容可寻址存储✔️❌❌动态包执行✔️ - 通过 pnpm dlx✔️ - 通过 yarn dlx✔️ - 通过 npxSide-effects cache✔️❌❌"},"Professional/Work/full-stack/文化/历史发展":{"title":"历史发展","links":[],"tags":["fullstack/文化"],"content":"前端开发已经经历了长达几十年的发展历程,从最初的静态网页到现在的复杂的 Web 交互应用,前端开发的技术和工具都发生了巨大的变化。下面是前端开发的一些主要发展阶段:\n1990 年代:静态网页时代 §\n在 1990 年,Tim Berners-Lee 发明了万维网,也就标志着网页的诞生。在这个阶段,网页主要由纯文本构成,使用 HTML(HyperText Markup Language)进行标记。这些网页被称为静态网页,因为它们的内容在服务器端生成,用户端不能交互和修改。\n1995 年:JavaScript 的诞生 §\n1995 年,JavaScript 语言在 Netscape 浏览器上首次亮相,由 Brendan Eich 发明。最初,JavaScript 被用作一种客户端的脚本语言,用于实现网页上的简单交互效果,如表单验证等。\n1996 年: CSS 的诞生 §\n1996 年,W3C(万维网联盟)发布了 CSS(Cascading Style Sheets)的第一版规范,标志着样式表的诞生。CSS 的出现使得开发者可以更加方便地控制网页的样式和布局。\n2000 年代初:动态网页和 AJAX §\n2000 年代初,随着 JavaScript 和服务端技术的发展,网页开始从静态向动态转变。AJAX(Asynchronous 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 Apps(PWA)的出现,前端开发正在朝着更加模块化、组件化和原生应用化的方向发展。\n在过去的几十年里,前端开发经历了从静态网页到复杂 Web 应用的巨大转变。尽管前端开发的技术和工具不断变化,但其核心目标一直未变,那就是创建出色的用户体验。"},"Professional/Work/full-stack/文化/概述":{"title":"概述","links":[],"tags":["fullstack/文化"],"content":"简介 §\n前端开发是当今技术领域的重要组成部分,它使我们能够以视觉上吸引人的、交互式的方式浏览网站和网络应用程序。\n前端开发的定义 §\n前端开发,有时也被称为客户端开发,是创建网络应用程序或网站用户交互界面的实践。它涉及到的技术包括 HTML、CSS 和 JavaScript,以及各种现代框架和库,如 React、Angular 和 Vue.js。前端开发者的目标是提供一个高度交互的、用户友好的界面,它可以在各种设备和浏览器上无缝工作。\n前端与后端的区别 §\n在理解前端和后端的区别时,最直接的比喻可能就是一家餐厅。在这个比喻中,前端开发者就像是餐厅的服务员,他们直接与顾客(用户)互动,提供菜单,接收订单,并提供所需的食物(数据)。而后端开发者就像是厨师,他们在幕后处理服务员传来的订单,并准备好食物。\n在技术方面,前端开发主要关注用户界面和用户体验,而后端开发则是处理服务器、应用和数据库之间的交互。后端开发者使用如 Python、Ruby、Java、PHP 等服务器端语言,创建应用的业务逻辑,管理数据库,以及处理用户的请求和响应。\n前端开发的重要性 §\n前端开发的重要性在于它**直接影响到用户的体验。**一个易于使用、视觉吸引人的界面可以大大增加用户的满意度,提高用户的参与度,甚至影响到公司的品牌形象。此外,前端开发也涉及到网站的可访问性和响应式设计,这可以确保所有用户,无论他们使用的设备类型或者他们的身体能力如何,都可以方便的访问和使用网站。\n在当今的数字化世界中,前端开发已经变得至关重要。无论是小型的静态网站,还是大型的复杂网络应用,都需要前端开发者的专业技能和经验来创建用户友好的界面。在未来,随着技术的不断发展和新的用户需求的出现,前端开发的重要性只会继续增加。\n未来发展趋势 §\n在未来,前端开发预计将继续迅速发展和变化。以下是一些可能的发展趋势:\n更丰富的交互体验 §\n随着技术的进步,我们可以预期更加丰富和复杂的用户界面和交互体验。例如,虚拟现实(VR)和增强现实(AR)技术可能会更加普及,为前端开发带来全新的挑战和机遇。另外,随着机器学习和人工智能的发展,我们可能会看到更多的自适应和个性化的用户界面。\n新的和改进的工具 §\n前端开发工具在不断发展和改进。新的编程语言、库和框架正在不断出现,以解决前端开发者面临的新的挑战。例如,WebAssembly 可能会改变我们构建和运行前端应用的方式,而像 React Native 这样的框架可能会继续改变我们开发跨平台应用的方式。\n性能优化 §\n随着用户对于网页响应速度和流畅度的期望越来越高,性能优化将继续是前端开发的重要主题。包括如何有效地使用缓存、如何优化代码以减少加载时间、如何更好地使用网络资源等方面。\nWeb 安全性 §\n随着网络攻击和数据泄露事件的增多,Web 安全性将成为前端开发的重要考虑因素。前端开发者需要了解如何保护用户数据,如何防止跨站脚本(XSS)攻击,跨站请求伪造(CSRF)等。\n可访问性和包容性 §\n在未来,可访问性和包容性可能会成为前端开发的更重要的考虑因素。这意味着创建的网站和应用需要对所有人开放,无论他们的能力如何。这包括对于屏幕阅读器友好的设计,对于不同的输入方法(例如语音输入)的支持,以及对于不同文化和语言的考虑。"},"Professional/Work/full-stack/文化/现代化开发工具链":{"title":"现代化开发工具链","links":[],"tags":["fullstack/文化"],"content":"在前端开发过程中,开发者需要利用一系列的工具和技术来提高工作效率、确保代码质量和进行项目管理。这些工具和技术构成了前端的开发工具链。以下是一些现代前端开发中常用的工具和技术:\n版本控制:Git + GitFlow、Pull Request §\nGit 是一个开源的分布式版本控制系统,用于跟踪和记录项目文件的更改历史。GitHub 是一个基于 Git 的代码托管平台, 提供了代码审查、项目管理、版本控制等功能。使用 GitFlow 可以实现更规范的分支管理,Pull Request 允许代码审查,是团队协作的重要方式。\n包管理器:npm、yarn 和 Pnpm §\n包管理器用于自动处理项目的依赖关系。npm(Node Package Manager) 是 Node.js 的默认包管理器,yarn 由 Facebook 开发,提供更快速度。pnpm 结合了两者优点,也越来越受欢迎。\n代码编辑器:VS Code §\nVS Code(Visual Studio Code)是 Microsoft 开发的一个开源代码编辑器。VS Code 提供了语法高亮、智能代码补全、代码重构等功能,并支持大量的插件,如 ESLint、Prettier 等。\n模块打包器:Webpack 和 Vite §\nWebpack 是一个模块打包器,支持代码分割、懒加载等。Vite 通过原生 ES module 实现极速开发服务器启动,能够显著提升开发效率。\n代码转译器:Babel §\nBabel 是一个 JavaScript 编译器,可以将最新版的 JavaScript 代码转译成旧版的代码,以便在老版本的浏览器中运行。Babel 支持 ES6、React JSX 语法、TypeScript 等。\n代码检查器:ESLint 和 Prettier §\nESLint 是一个开源的 JavaScript 代码检查工具,可以检查代码中的错误和不符合规范的编码风格。Prettier 是一个代码格式化工具,可以自动格式化代码,确保代码的一致性。\n测试框架:Jest 和 Mocha §\nJest 是 Facebook 开发的一个 JavaScript 测试框架,支持模拟测试、快照测试等。Mocha 是另一种流行的 JavaScript 测试框架,可以搭配 Chai(断言库)和 Sinon(测试替身库)等工具使用。\n前端框架:React、Vue 和 Angular §\nReact、Vue 和 Angular 是目前最流行的前端框架,它们提供了组件化、声明式编程等高级特性,用于构建复杂的单页应用(SPA)。\nCSS 预处理器:Sass、CSS Modules §\nSass 是一种强大的 CSS 预处理器,允许使用变量、嵌套规则、混合等功能,以写出更干净、更易于维护的 CSS 代码。CSS Modules 是一种 CSS 模块化方案,可以实现 CSS 的局部作用域,避免样式冲突。\n结构化数据:GraphQL 和 REST API §\nGraphQL 是 Facebook 推出的一种数据查询和操作语言,可以让客户端精确地获取需要的数据,提高数据传输效率。REST API 是网络应用程序中最常用的 API 架构风格,它利用 HTTP 协议提供 CRUD(创建、读取、更新、删除)操作。\n状态管理:Redux、Vuex 和 MobX §\nRedux(用于 React)和 Vuex(用于 Vue)都是前端状态管理工具,用于管理和维护组件间共享的状态。MobX 是另一种流行的状态管理库,它使用响应式编程概念,让状态管理更加直观。\n静态类型检查器:TypeScript §\nTypeScript 是 JavaScript 的一个超集,它添加了静态类型检查和其他特性,可以提高代码的可维护性和可靠性。\n服务器端渲染(SSR)和静态站点生成(SSG):Next.js 和 Nuxt.js §\nNext.js(用于 React)和 Nuxt.js(用于 Vue)是用于构建服务器端渲染(SSR)和静态站点生成(SSG)的框架,可以提高首屏加载速度,优化 SEO。\n以上就是现代化前端开发工具链的概述,这些工具和技术可以提高开发效率,保证代码质量,使得前端开发更具生产力。\n端到端测试:Cypress 和 Puppeteer §\nCypress 和 Puppeteer 是用于进行端到端测试的工具,允许开发者模拟用户的行为,检查页面的响应,确保应用在真实使用场景中的表现。\n开发环境:Docker §\nDocker 是一种开源的容器平台,可以用于打包和运行应用,确保应用在不同环境中的一致性。使用 Docker 可以避免“在我机器上可以运行”的问题。\n持续集成/持续部署(CI/CD):GitHub Actions 和 Jenkins §\nGitHub Actions 和 Jenkins 是用于持续集成和持续部署的工具,可以自动化构建、测试和部署的过程,提高开发效率和代码质量。\n性能优化:Lighthouse 和 Webpack Bundle Analyzer §\nLighthouse 是一种开源工具,可以对网页进行性能、可访问性、最佳实践、SEO 等方面的评估。Webpack Bundle Analyzer 是一个插件,可以帮助开发者理解 webpack 打包的输出文件,找出优化的机会。\nAPI Mocking:Mirage JS 和 Json-server §\njson-server 和 Mirage JS 可以用于生成模拟的 RESTful API,帮助前端开发者在后端 API 还没准备好的情况下进行开发和测试。\n设计工具和 UI 组件库:Sketch、Figma、Ant Design 和 Material-UI §\nSketch 和 Figma 是用于设计 UI 的工具,可以创建和分享设计原型。Ant Design 和 Material-UI 是 UI 组件库,提供了一系列预定义的 UI 组件,可以快速构建美观的界面。\n调试工具:DevTools、VS Code 调试 §\nChrome DevTools 和 VS Code 的调试功能用于前端代码调试。"},"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补偿金 = 在职年限(N)x 工资基数\n赔偿金 = 2 x 在职年限(N)x 工资基数\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 的博客 」,原文:https://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本文转载自:「 少数派 」,原文:https://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 指南 :https://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文章地址:https://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 Indicators,KPI)又称主要绩效指标、重要绩效指标、绩效评核指标等,是指衡量一个管理工作成效最重要的指标,是一项数据化管理的工具,必须是客观、可衡量的绩效指标。\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 Results,OKR)是企业进行目标管理的一个简单有效的系统,能够将目标管理自上而下贯穿到基层。这套系统由英特尔公司制定,在谷歌成立不到一年的时间,被投资者约翰 · 都尔引入谷歌,并一直沿用至今。\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大部分翻译自:https://github.com/viraptor/reverse-interview ,亦有其他网友补充。\n译者总结的一份适合突击记忆的简洁版 LeetCode 题解和面试问题,也欢迎 Star。https://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 I’m 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(共享出行运营为例)“如果我们想提高日订单量,你觉得有哪些机会点?”\n(APP 投放为例)“如果我们想维持 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在线网址:https://en-letter.xiao84.com/\n\n音标 §\n\n\n在线网址:https://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 Services(AWS)及 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 会将请求转发到后端服务器(例如你的网站应用)。后端服务器处理请求后,将页面内容等资源返回给 Nginx,Nginx 再将这些内容发送给用户。在这个过程中,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, https://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: https://doh.pub/dns-query, https://1.12.12.12/dns-query, https://120.53.53.53/dns-query\nDoH (国密): https://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: https://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: https://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: https://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 (默认): https://dns.quad9.net/dns-query\nDoH (安全&支持 ECS): https://dns11.quad9.net/dns-query\n\n\n\nOpenDNS §\n\nOpenDNS: 208.67.222.222, 208.67.220.220\n\nDoH (默认): https://doh.opendns.com/dns-query\nDoH (家庭保护): https://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, https://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 (默认): https://dns.adguard.com/dns-query\nDoH (家庭保护): https://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: https://doh.dns.sb/dns-query, https://doh.sb/dns-query\nDoT: dot.sb\n\n\n\nHurricane Electric(HE) §\n\nHurricane Electric(HE): 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 (家庭保护): https://doh.cleanbrowsing.org/doh/family-filter/\nDoT: dns.cleanbrowsing.org\n\n\n\nPowerDNS §\n\nPowerDNS:\n\nDoH: https://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: https://public.dns.iij.jp/dns-query\n\n\n\nBlahdns 日本节点 §\n\nBlahdns 日本节点:\n\nDoH: https://doh-jp.blahdns.com/dns-query\n\n\n\nMullvad Public DNS §\n\nMullvad Public DNS: 194.242.2.2\n\nDoH: https://dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (去广告 + 跟踪器) §\n\nMullvad Public DNS (去广告 + 跟踪器): 194.242.2.3\n\nDoH: https://adblock.dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (去广告 + 跟踪器 + 恶意软件) §\n\nMullvad Public DNS (去广告 + 跟踪器 + 恶意软件): 194.242.2.4\n\nDoH: https://base.dns.mullvad.net/dns-query\n\n\n\nMullvad Public DNS (完全) §\n\nMullvad Public DNS (完全): 194.242.2.9\n\nDoH: https://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: https://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 (默认): https://dns.quad9.net/dns-query\nDoH (安全&支持 ECS): https://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镜像站地址: https://developer.aliyun.com/mirror\n\n腾讯云 §\n\n镜像站地址: https://mirrors.cloud.tencent.com\n\n网易 §\n\n镜像站地址: http://mirrors.163.com\n\n华为 §\n\n镜像站地址: https://mirrors.huaweicloud.com\n\n高校镜像 §\n中国校园网联合镜像 §\n\n镜像站地址:https://mirrors.cernet.edu.cn/\n\n中国科学技术大学 §\n\n镜像站地址: https://mirrors.ustc.edu.cn\n\n上海交通大学 §\n\n镜像站地址: https://mirrors.sjtug.sjtu.edu.cn\n\n清华大学 TUNA §\n\n镜像站地址: https:/mirrors.tuna.tsinghua.edu.cn\n镜像站地址: https://opentuna.cn\n\n北京大学 §\n\n镜像站地址: https://mirrors.pku.edu.cn/Mirrors\n\n哈尔滨工业大学 §\n\n镜像站地址: https://mirrors.hit.edu.cn\n\n浙江大学 §\n\n镜像站地址: http://mirrors.zju.edu.cn\n\n北京交通大学 §\n\n镜像站地址: https://mirror.bjtu.edu.cn\n\n北京外国语大学 §\n\n镜像站地址: https://mirrors.bfsu.edu.cn\n\n大连东软信息学院 §\n\n镜像站地址: http://mirrors.neusoft.edu.cn\n\n南京大学 §\n\n镜像站地址: http://mirrors.nju.edu.cn\n\n南京邮电大学 §\n\n镜像站地址: http://mirrors.njupt.edu.cn\n\n山东大学 §\n\n镜像站地址: http://mirrors.sdu.edu.cn\n\n华中科技大学 §\n\n镜像站地址: http://mirror.hust.edu.cn\n\n东北大学 §\n\n镜像站地址: http://mirror.neu.edu.cn\n\n大连理工大学 §\n\n镜像站地址: http://mirror.dlut.edu.cn\n\n南洋理工学院 §\n\n镜像站地址: https://mirror.nyist.edu.cn\n\n南方科技大学 §\n\n镜像站地址: https://mirrors.sustech.edu.cn\n\n重庆大学 §\n\n镜像站地址: http://mirrors.cqu.edu.cn\n\n山东女子学院 §\n\n镜像站地址: https://mirrors.sdwu.edu.cn\n\n西安交通大学 §\n\n镜像站地址: https://mirrors.xjtu.edu.cn\n镜像站地址: https://mirrors.xjtuana.com\n\n北京邮电大学 §\n\n镜像站地址: https://mirrors.bupt.edu.cn\n镜像站地址: https://mirrors.byrio.org\n\n西北农林科技大学 §\n\n镜像站地址: https://mirrors.nwsuaf.edu.cn\n镜像站地址: https://mirrors.nwafu.edu.cn\n\n同济大学 §\n\n镜像站地址: https://mirrors.tongji.edu.cn\n\n华南农业大学 §\n\n镜像站地址: https://mirrors.scau.edu.cn\n\n东莞理工学院 §\n\n镜像站地址: https://mirrors.dgut.edu.cn\n\n云南大学 §\n\n镜像站地址: https://mirrors.ynu.edu.cn/index\n\n中国科学院软件研究所 §\n\n镜像站地址: https://mirror.iscas.ac.cn\n\n武昌首义学院 §\n\n镜像站地址: https://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 Protocol,DHCP)是一个网络协议,它能够**动态地分配 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。对于 IPv4,DHCP 可以动态分配 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 System,DNS)是一个用于将域名(如 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\nDoH(DNS over HTTPS)和 DoT(DNS over TLS):这两种新技术可以实现 DNS 查询的加密传输,从而提高用户的隐私保护。DoH 和 DoT 都可以防止 DNS 查询被窃听或篡改,保护用户的互联网使用安全。\n国际化域名(IDNs):国际化域名是一种新的域名类型,允许使用非拉丁字符的域名,如中文、阿拉伯文等。这大大扩展了域名的使用范围,使得更多的人可以方便地使用互联网。\n基于 DNS 的服务发现(DNS-SD):DNS-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-Middle(MitM)攻击:攻击者插入到通信双方之间,秘密拦截或篡改数据。\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 连接的建立采用三次握手机制(SYN,SYN-ACK,ACK),确保双方都准备好进行数据传输。\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 同属于传输层协议,但相较于 TCP,UDP 的设计更为简单,提供更快的数据传输速度。\nUDP(用户数据报协议)是一种无连接的网络协议,由 David P. Reed 设计并于 1980 年在 RFC 768 中首次描述。它是互联网协议套件的一部分,与 TCP 同属于传输层协议,但相较于 TCP,UDP 的设计更为简单,提供更快的数据传输速度。\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协议:例如 IP(Internet Protocol)、ICMP(Internet Control Message Protocol)等。\n\n4. 传输层(Transport Layer) §\n\n功能:为端到端的通信提供服务。它负责数据的分割、传输、错误检测和恢复。\n协议:例如 TCP(Transmission Control Protocol)、UDP(User 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协议和服务:例如 HTTP(HyperText Transfer Protocol)、FTP(File 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 §\nRIP(Routing Information Protocol)是一种基于距离向量的内部网关协议(IGP),用于在小型网络中选择最佳路由。RIP 协议采用 Hop Count 作为路径计算标准,当路由表中某个目的地址的距离超过 15 个跳时,该地址将被认为是不可达的。\nOSPF §\nOSPF(Open Shortest Path First)是一种基于链路状态的内部网关协议(IGP),用于在大型网络中选择最佳路由。OSPF 协议将网络划分为多个区域,每个区域拥有自己的链路状态数据库(LSDB),可以实现快速收敛和路由分级。\nBGP §\nBGP(Border Gateway Protocol)是一种外部网关协议(EGP),用于在不同自治系统之间交换路由信息。BGP 协议可以实现路由的动态学习和选择,支持多路径和路由策略等功能。BGP 是互联网核心路由器之间的主要协议。\nIS-IS §\nIS-IS(Intermediate 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 Point,WAP) §\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 §\nApache(Apache HTTP Server)是一个开源的 Web 服务器软件。它由 Apache 软件基金会 维护,起源于 1995 年。Apache 支持多种操作系统,如 Linux、Unix、Windows 等。Apache 使用模块化的架构,可以通过安装和配置不同的模块来扩展其功能。\nApache 适用于各种规模的网站和应用;未来方向将继续优化性能,提高安全性,支持新的 Web 技术和标准。\nNginx §\nNginx 是一个轻量级的 Web 服务器、反向代理服务器和电子邮件代理服务器。起源于 2002 年,其设计目标是提供高性能、高并发和低内存占用。Nginx 在处理静态资源、负载均衡和反向代理等方面表现出色。\nNginx 适用于高并发、高流量的网站和应用,以及作为反向代理和负载均衡器。\nIIS §\nIIS(Internet Information Services)是微软推出的 Web 服务器软件,起源于 1995 年。IIS 只支持 Windows 操作系统。IIS 支持 ASP.NET、PHP 等多种语言,并且可以通过模块扩展其功能。\nIIS 适用于依赖于 Windows 平台和 Microsoft 技术的网站和应用。\nDHCP 服务 §\nISC DHCP §\nISC DHCP(Internet 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 §\nBIND(Berkeley 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 是一个开源的 NTP(Network Time Protocol)服务器和客户端软件,起源于 1997 年。它具有高度可配置的特点,可以在各种网络环境中提供精确的时间同步服务。\nChrony 适用于需要精确时间同步服务的企业、数据中心和科研机构。\nNTPd §\nNTPd(Network Time Protocol daemon)是一款开源的 NTP 服务器和客户端软件,起源于 1985 年。它广泛应用于各种规模的网络环境,支持各种操作系统。\nNTPd 适用于各种规模的网络环境,需要可靠的时间同步服务。\nVPN 服务 §\nOpenVPN §\nOpenVPN 是一个开源的 VPN(Virtual Private Network)软件,起源于 2001 年。它基于 SSL/TLS 协议,提供安全稳定的远程访问和站点间连接功能。\nOpenVPN 适用于需要安全远程访问和站点间连接的企业和个人用户。\nIPSec §\nIPSec(Internet Protocol Security)是一组用于保护 IP 数据包的协议,起源于 1990 年代。IPSec 提供了认证、完整性和加密功能,广泛应用于 VPN 场景。\nIPSec 适用于需要安全通信和网络互联的企业和数据中心。\nWireGuard §\nWireGuard 是一个简单、高性能的 VPN 软件,起源于 2016 年。它使用现代加密技术,具有易于配置和部署的特点。\nWireGuard 适用于需要简单易用、高性能 VPN 的企业和个人用户。\n负载均衡 §\nHAProxy §\nHAProxy(High Availability Proxy)是一个开源的、高性能的负载均衡软件,起源于 2000 年。它可以用于分发 TCP 和 HTTP 流量,广泛应用于大型网站和云计算环境。\nHAProxy 适用于需要高性能、高可用性负载均衡服务的大型网站和云计算环境。\nLVS §\nLVS(Linux Virtual Server)是一个开源的、基于 Linux 内核的负载均衡软件,起源于 1998 年。它支持 TCP 和 UDP 协议,可以用于分发各种网络服务。\nLVS 适用于需要高性能、高可用性负载均衡服务的大型网站和数据中心。\n文件共享服务 §\nSamba §\nSamba 是一个开源的文件共享服务软件,起源于 1992 年。它允许在不同操作系统(如 Linux、Windows 和 macOS)之间共享文件和打印机。\nSamba 适用于需要在不同操作系统之间共享文件和打印机的企业和家庭网络环境。\nNFS §\nNFS(Network File System)是一种分布式文件系统协议,起源于 1984 年。它允许在 UNIX/Linux 系统之间共享文件。\nNFS 适用于需要在 UNIX/Linux 系统之间共享文件的企业和数据中心。\nSFTP §\nSFTP(SSH 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":"简介 §\nGnuPG(GNU Privacy Guard,GPG)是一款开源软件,用于非对称加密。它是满足 GPL 协议的 PGP(Pretty 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 表示的是从世界标准时间(UTC,Coordinated 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 Encryption,PBE) ,在 PGP 里会用 PBE 加密私钥\n\n\n盐(Salt),在密码学中,是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。在大部分情况,盐是不需要保密的。盐可以是随机产生的字符串,其插入的位置可以也是随意而定。\n\n\n数字证书 = 用户信息(csr) + 用户公钥 + 公钥指纹 + 其它相关信息 + (颁发机构私钥 加密 前面提及的 相关数据的 数字摘要 所得到的数字签名)\n\n\nhttps 里的 ssl 证书就是数字证书\n\n\n这是数字证书的一般格式\n```\n 证书\n 版本号\n 序列号 由证书颁发者分配的本证书的唯一标识符。颁发者和证书序列号配合起来就能唯一地标识一张数字证书。\n 签名算法\n 颁发者\n 国家(C,Country)\n 州/省(S,State)\n 地域/城市(L,Location)\n 组织/单位(O,Organization)\n 通用名称(CN,Common Name)\n 证书有效期\n 此日期前无效\n 此日期后无效\n 主题\n 国家(C,Country)\n 州/省(S,State)\n 地域/城市(L,Location)\n 组织/单位(O,Organization)\n 通用名称(CN,Common 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 Certificate,PKC) ,就是数字证书\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 One,ASN.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 + TLS/SSL\n\n\nWSS = WebSocket + TLS/SSL\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 have):IC 卡、数字设备、数字签名、一次性密码 (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 List,ACL 是最早的、最基本的一种访问控制机制,是基于客体进行控制的模型,在其他模型中也有 ACL 的身影。为了解决相同权限的用户挨个配置的问题,后来也采用了用户组的方式。\n原理:每一个客体都有一个列表,列表中记录的是哪些主体可以对这个客体做哪些行为,非常简单。\n例如:当用户 A 要对一篇文章进行编辑时,ACL 会先检查一下文章编辑功能的控制列表中有没有用户 A,有就可以编辑,无则不能编辑。再例如:不同等级的会员在产品中可使用的功能范围不同。\n缺点:当主体的数量较多时,配置和维护工作就会成本大、易出错。\nDAC 模型:自主访问控制 §\nDiscretionary Access Control,DAC 是 ACL 的一种拓展。\n原理:在 ACL 模型的基础上,允许主体可以将自己拥有的权限自主地授予其他主体,所以权限可以任意传递。\n例如:常见于文件系统,LINUX,UNIX、WindowsNT 版本的操作系统都提供 DAC 的支持。\n缺点:对权限控制比较分散,例如无法简单地将一组文件设置统一的权限开放给指定的一群用户。主体的权限太大,无意间就可能泄露信息。\nMAC 模型:强制访问控制 §\nMandatory Access Control,MAC 模型中主要的是双向验证机制。常见于机密机构或者其他等级观念强烈的行业,如军用和市政安全领域的软件。\n原理:主体有一个权限标识,客体也有一个权限标识,而主体能否对该客体进行操作取决于双方的权限标识的关系。\n例如:将军分为上将 > 中将 > 少将,军事文件保密等级分为绝密 > 机密 > 秘密,规定不同军衔仅能访问不同保密等级的文件,如少将只能访问秘密文件;当某一账号访问某一文件时,系统会验证账号的军衔,也验证文件的保密等级,当军衔和保密等级相对应时才可以访问。\n缺点:控制太严格,实现工作量大,缺乏灵活性。\nABAC 模型:基于属性的访问控制 §\nAttribute-Based Access Control,能很好地解决 RBAC 的缺点,在新增资源时容易维护。\n原理:通过动态计算一个或一组属性是否满足某种机制来授权,是一种很灵活的权限模型,可以按需实现不同颗粒度的权限控制。\n属性通常有四类:\n\n主体属性,如用户年龄、性别等;\n客体属性,如一篇文章等;\n环境属性,即空间限制、时间限制、频度限制;\n操作属性,即行为类型,如读写、只读等。\n\n例如:早上 9:00,11:00 期间 A、B 两个部门一起以考生的身份考试,下午 14:00,17: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/用户安全/用户鉴权/JWT(JSON-Web-Token)鉴权":{"title":"JWT 鉴权","links":[],"tags":["计算机安全/用户安全","技术/计算机安全"],"content":"JWT(JSON 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\niss(issuer):签发人\nexp(expiration time):过期时间\nsub(subject):主题\naud(audience):受众\nnbf(Not Before):生效时间\niat(Issued At):签发时间\njti(JWT 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、微信授权服务)。\nhttps://qq.com/oauth/authorize?\n response_type=code&\n client_id=CLIENT_ID&\n redirect_uri=CALLBACK_URL&\n scope=read\n上面 URL 中,response_type 参数表示要求返回授权码(code),client_id 参数让 B 知道是谁在请求,redirect_uri 参数是 B 接受或拒绝请求后的跳转网址,scope 参数表示要求的授权范围(这里是只读)\n\n2. 授权服务器 §\n授权服务网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务网站就会跳回 redirect_uri 参数指定的网址。跳转时,会传回一个授权码,就像下面这样,code 参数就是授权码。\nhttps://a.com/callback?code=AUTHORIZATION_CODE\n\n3. 网站 A 服务器 §\n拿到授权码以后,就可以向 授权服务器 (qq.com) 请求令牌。\nhttps://qq.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 网站使用。\nhttps://qq.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 网站。\nhttps://a.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 就直接向授权服务器请求令牌。\nhttps://oauth.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客户端向授权服务器进行身份认证,并要求一个访问令牌。\nhttps://oauth.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那么就有了 CAS(Central Authentication Service)中央授权服务,那么我们先主要说下 CAS 的流程。\n单点登录下的 CAS 认证流程图 §\n\n单点登录下的 CAS 认证步骤详解 §\n\n客户端: 访问系统 A。\n系统 A: 发现用户未登录,重定向至 CAS 认证服务(sso.com),同时 URL 地址参数携带登录成功后回跳到系统 A 的页面链接 sso.com/login?redir…\nCAS 认证服务: 发现请求 Cookie 中没有携带登录的票据凭证(TGC),所以 CAS 认证服务判定用户处于未登录状态,重定向用户页面至 CAS 的登录界面,用户在 CAS 的登录页面上进行登录操作。\n客户端: 输入用户名密码进行 CAS 系统认证;\nCAS 认证服务: 校验用户信息,并且生成 TGC 放入自己的 Session 中,同时以 Set-Cookie 形式写入 Domain 为 sso.com 的域下 ;同时生成一个授权令牌 ST (Service Ticket),然后重定向至系统 A 的地址,重定向的地址中包含生成的 ST,重定向地址 www.taobao.com?token=ST-345678\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\nTGT(Ticket Grangting Ticket) :TGT 是 CAS 为用户签发的登录票据,拥有了 TGT,用户就可以证明自己在 CAS 成功登录过。\nTGC:Ticket Granting Cookie: CAS Server 生成 TGT 放入自己的 Session 中,而 TGC 就是这个 Session 的唯一标识(SessionId),以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。\nST(Service 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 Code,QR 全称 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":"引言 §\nSSH(Secure 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:一个用于远程登录到服务器的程序,它可以替代 telnet,rlogin 等非安全的远程 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哈希函数\nECC(Error 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\niSCSI(Internet Small Computer System Interface):\n\n定义:一种基于 IP 网络的存储协议,通过 TCP/IP 传输 SCSI 指令,使存储设备可以通过网络连接到主机。\n优势:低成本、易于配置和扩展,适用于中小型企业。\n应用场景:虚拟化环境、远程备份和恢复、灾难恢复等。\n\n\n\nFibre Channel(FC):\n\n定义:一种高速网络协议,专门用于存储区域网络(SAN),通过光纤或铜缆传输数据。\n优势:高带宽、低延迟、可靠性高,适用于大规模数据中心。\n应用场景:企业级存储网络、大型数据库和高性能计算等。\n\n\n\nNFS(Network File System):\n\n定义:一种网络文件系统协议,允许不同操作系统的计算机通过网络共享文件。\n优势:跨平台兼容、易于配置和管理,适用于文件共享和协作。\n应用场景:企业文件共享、网络附加存储(NAS)设备、虚拟化环境等。\n\n\n\nSMB(Server 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定义:NVMe(Non-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 NAND,3D NAND 能够在相同面积上提供更多的存储容量。\n高耐久性:改进的制造工艺和材料使用,延长了闪存的寿命。\n低成本:更高的存储密度和更低的单位存储成本。\n\n\n应用场景:消费级 SSD、企业级存储设备和移动设备等。\n\n7.3 储存级内存(SCM) §\n\n定义:储存级内存(Storage Class Memory,SCM)是一种介于 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\nGDPR(General Data Protection Regulation):\n\n定义:GDPR 是欧盟颁布的《通用数据保护条例》,旨在保护欧盟公民的个人数据隐私。\n主要要求:\n\n数据收集和处理需获得用户明确同意。\n用户有权访问、修改和删除其个人数据。\n企业需采取适当措施保护用户数据,并在数据泄露时及时通知用户。\n\n\n实施:企业需制定隐私政策,进行数据保护影响评估(DPIA),确保数据处理符合 GDPR 要求。\n\n\n\nHIPAA(Health 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 S3(Amazon 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\nHDFS(Hadoop 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 S3:AWS 提供的对象存储服务,具有高可用性和高耐久性。\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日志管理工具:如 ELK(Elasticsearch、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存储单元大小关系描述千字节(KB)1 KB = 1024 字节通常用于表示较小的文件大小兆字节(MB)1 MB = 1024 KB常用于表示文档、图片文件大小千兆字节(GB)1 GB = 1024 MB常用于表示视频文件或硬盘容量太字节(TB)1 TB = 1024 GB用于表示大容量硬盘或存储设备拍字节(PB)1 PB = 1024 TB用于大型数据中心存储艾字节(EB)1 EB = 1024 PB用于极大型数据中心或云存储\n数据表示 §\n字符编码用于将字符转换为计算机可以处理的二进制形式。常见的字符编码方式包括 ASCII、Unicode、UTF-8 等。\n文件系统 §\n文件系统是用于管理和组织存储设备上数据和文件的方法。文件系统负责文件的存储、命名、访问和保护。不同的文件系统在性能、可靠性、安全性和兼容性方面有所不同,常见的文件系统包括:\n\nFAT32(File Allocation Table 32):一种较老的文件系统,广泛用于 USB 闪存驱动器和小型存储设备,最大文件大小为 4 GB,分区最大为 8 TB。\nNTFS(New Technology File System):微软 Windows 操作系统的默认文件系统,支持大文件和大容量分区,具有文件和目录的权限管理、安全性高、支持加密和压缩等特点。\next4(Fourth Extended File System):Linux 操作系统常用的文件系统,支持大文件和大容量分区,具有高效的磁盘空间管理和良好的性能。\nAPFS(Apple File System):苹果公司用于 macOS 和 iOS 的文件系统,支持快照、克隆、加密、空间共享和崩溃保护等特性。\n\n存储性能指标 §\n存储性能指标是衡量存储设备效率和能力的关键参数。了解这些指标有助于评估存储系统的性能,并根据具体需求进行优化配置。以下是一些常见且重要的存储性能指标。\nIOPS §\n**IOPS(Input/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 公司共同推出了第一种数字光盘标准 CD(Compact 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 Drive,HDD)是一种数据存储设备,是计算机系统中最常用的存储媒介之一。它是一种使用磁盘片来存储数据的设备,通过机械臂上的读写头在盘片上读写数据。\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 硬盘,应用了 MR(Magneto Resistive 磁阻)技术,为硬盘容量的巨大提升奠定基础。\n\n\n1997 年,IBM 应用 GMR(Giant Magneto Resistive,巨磁阻)技术,使磁头灵敏度进一步提升,进而提高存储密度。\n\n\n2005 年,日立环储和希捷都宣布将开始大量采用磁盘垂直写入技术(perpendicular recording)。\n\n\n2011 年,机械硬盘逐渐被固态硬盘所取代,希捷宣布收购三星旗下的硬盘业务。\n\n\n2020 年截至现存主要硬盘制造商包括西部数据、希捷、东芝、日立等。\n数据接口 §\n机械硬盘的接口是指将硬盘与计算机主板或控制卡连接的接口。早期的机械硬盘接口主要有 IDE (Integrated Drive Electronics) 和 SCSI(Small Computer System Interface)两种。目前,常见的机械硬盘接口主要包括 SATA(Serial ATA)和 SAS(Serial 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接口传输速率优点缺点适用场景IDE(Integrated Drive Electronics)最高 133MB/s支持 PATA 和 SATA 接口,兼容性好传输速率较慢,线缆长度受限早期的个人电脑、低端工作站等SCSI(Small Computer System Interface)最高 640MB/s高速传输,支持多设备连接,可扩展性强价格较高,设置和维护较为复杂高端服务器、存储阵列等SATA(Serial ATA)最高 6Gbps价格低廉,易于使用和安装传输速率较慢,线缆长度受限个人电脑、工作站、NAS 等SAS(Serial Attached SCSI)最高 12Gbps高速传输,支持多设备连接价格较高服务器、存储阵列等高端应用FC(Fibre 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机械硬盘的逻辑结构主要包括两种格式:MBR(Master Boot Record,主引导记录)和 GPT(GUID Partition Table,全局唯一标识分区表)。\nMBR 是早期 PC 硬盘的标准分区方案,它将硬盘的分区信息保存在硬盘的第一个扇区中(即 0 号扇区),这个扇区的大小为 512 字节。MBR 可以分为两个部分:引导程序区和分区表。引导程序区存储了启动时需要加载的程序,分区表则记录了硬盘分区的信息,每个分区表项占用 16 字节,其中包括分区类型、起始扇区和分区大小等信息。MBR 最多支持 4 个主分区或 3 个主分区和 1 个扩展分区。\nGPT 是新一代硬盘分区标准,它将硬盘的分区信息保存在硬盘的第一个和第二个 LBA(Logical 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 Drive,SSD)是一种非易失性的存储设备,主要用于存储数据。与传统的机械硬盘(Hard Disk Drive,HDD)相比,它没有任何移动部件,因此在速度、耐用性和能源消耗方面具有明显优势。\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,使用了 MLC(Multi-Level Cell)NAND 闪存技术,容量为 80GB,标志着固态硬盘开始进入消费者市场。\n\n\n2008 年,OCZ 推出了第一款支持 SATA 接口的固态硬盘,使得 SSD 更容易与现有计算机系统兼容。\n\n\n2011 年,高通和三星等公司联合制定了 UFS(Universal 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接口传输速度优点缺点适用场景PATA(Parallel ATA)最高 133MB/s成本较低,向后兼容性好速度较慢,数据线较粗,占用空间大早期台式机和笔记本电脑SATA(Serial ATA)最高 6Gbps速度较快,数据线较细,易安装,兼容性好速度相对于 NVMe 仍较慢台式机和笔记本电脑NVMe(Non-Volatile Memory Express)PCIe 3.0 x4:32 Gbit/s更高的传输速度,低延迟,可扩展性好成本较高,需要主板支持高性能台式机、笔记本、服务器等PCIe 4.0 x4:64 Gbit/s\n硬盘尺寸 §\n固态硬盘有多种尺寸,如 2.5 英寸、1.8 英寸和 mSATA。2.5 英寸是最常见的尺寸,适用于笔记本电脑和台式机。1.8 英寸和 mSATA 主要用于超薄笔记本和移动设备。近年来,M.2(2230、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 Storage,DAS)是最早的存储架构形式之一,广泛应用于早期的计算机系统中。DAS 系统通过直接连接存储设备到服务器的方式,实现数据存储和访问。与网络附加存储(NAS)和存储区域网络(SAN)相比,DAS 架构更加简单,性能也较高。\n发展历史 §\nDAS 系统的发展始于计算机早期阶段,随着技术的进步,不断演变和改进。\n\n1970 年代:DAS 系统初期使用并行 ATA(PATA)接口,这种接口在台式机和服务器中非常常见,但受限于传输速度和数据线的限制。\n2000 年代初:随着技术进步,串行 ATA(SATA)接口逐渐取代了 PATA 接口。SATA 接口不仅传输速度更快,而且数据线更细、更便于管理。\n2000 年代中期:串行连接 SCSI(SAS)接口出现,进一步提升了 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 和 SAN,DAS 系统的架构简单,不需要额外的网络设备,成本较低。\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 Storage,NAS)是一种专为数据存储和文件共享设计的设备。通过连接到网络,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 Network,SAN)是一种高性能的存储架构,通过专用的存储网络连接服务器和存储设备,为企业和数据中心提供高效、可靠的存储解决方案。SAN 系统提供了块级存储访问,能够满足对高性能和高可用性存储需求的关键业务应用。\n发展历史 §\n存储区域网络的发展始于 20 世纪 90 年代末,旨在解决传统存储架构在性能和扩展性方面的不足。以下是 SAN 系统发展历程中的一些关键节点:\n\n1990 年代末:SAN 系统开始普及,最早采用的是光纤通道(Fibre Channel)技术,提供高速、低延迟的存储连接。\n2000 年代初:随着互联网技术的发展,基于 IP 的 iSCSI 协议被引入,使得通过标准以太网实现 SAN 成为可能,降低了部署成本。\n2010 年代:引入了 Fibre Channel over Ethernet(FCoE)技术,结合了光纤通道的高性能和以太网的灵活性,进一步提升了 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 Storage,SDS)通过抽象硬件资源,使用软件实现存储功能,为用户提供更高的灵活性和可扩展性。\nSDS 系统可以在标准硬件上运行,并支持多种存储协议和服务,具有以下特点:\n\n硬件抽象:SDS 通过软件层将存储硬件抽象化,使存储资源的管理和配置更加灵活,不再依赖于特定的硬件设备。\n灵活扩展:SDS 系统可以根据需求动态扩展存储容量和性能,无需更换整个存储架构。\n统一管理:通过统一的软件平台管理存储资源,实现对不同类型存储设备的集中管理和监控。\n\n主要优势:\n\n灵活性高:SDS 可以在各种标准硬件上运行,用户可以根据需求选择硬件设备,避免厂商锁定。\n成本节约:使用标准硬件和开源软件组件可以降低存储系统的总体拥有成本。\n易于扩展:可以按需添加新的存储节点,实现存储容量和性能的无缝扩展。\n\n超融合基础设施(HCI) §\n**超融合基础设施(Hyper-Converged Infrastructure,HCI)通过将计算、存储和网络资源整合到一个统一的平台上,实现资源的统一管理和动态分配。**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 Graphics(SGI)开发了 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 Ts’o 领导开发的 EXT4 文件系统发布,成为 EXT3 的继任者。EXT4 显著改进了性能和可靠性,支持的最大文件大小达到 1EB,最大文件系统大小为 16TB,并引入了延迟分配、多块分配、无日志模式和在线碎片整理等新特性。\nLinux 文件系统从 Minix 到 EXT,再到更高级的 EXT4、Btrfs、XFS 和 ZFS 的发展过程中,每一次升级都带来了更大的存储支持、更高的性能和可靠性,以及更多的管理功能。\nEXT4 §\nEXT4(Fourth Extended File System)于 2008 年发布,由 Theodore Ts’o 领导开发,作为 EXT3 的继任者。EXT4 的发展旨在解决 EXT3 在大规模存储和性能上的限制,并引入了许多新特性和性能改进。EXT4 成为现代 Linux 系统的主流文件系统,广泛应用于各种场景,从个人电脑到企业级服务器。它的设计兼顾了向后兼容和未来扩展的需求,使其在稳定性和性能上都有显著提升。\n\n特点\n\n最大文件大小:1EB(Exabyte)\n最大文件系统大小:16TB(Terabyte)\n文件碎片整理:引入了延迟分配(Delayed Allocation)技术,这一特性通过推迟分配数据块的位置来减少文件碎片,提高了文件系统性能。\n多块分配:多块分配(Multiblock Allocation)允许一次性分配多个块,减少文件碎片,提高写入效率。\n日志模式:支持多种日志模式(Journal Mode),包括数据模式、元数据模式和延迟模式,以平衡性能和数据安全。\n文件系统检查:引入了快速文件系统检查功能(Fast Fsck),通过存储已校验的文件系统部分,减少了文件系统检查时间。\n无日志模式:支持无日志模式(No Journaling Mode),适用于对性能要求极高而对数据安全要求不高的场景。\n在线碎片整理:支持在线碎片整理功能,允许在不卸载文件系统的情况下进行碎片整理,提高了系统的可用性。\n\nBtrfs §\nBtrfs(B-Tree 文件系统)由 Oracle 公司于 2007 年首次发布,旨在提供高级管理功能和高可靠性。Btrfs 的设计目标是应对大规模存储系统的需求,并提供丰富的数据管理功能。Btrfs 在开发初期得到了广泛关注,被认为是未来 Linux 文件系统的发展方向之一。它的许多特性,如快照、压缩和自我修复,使其在数据密集型和高可靠性要求的应用场景中具有显著优势。\n\n特点\n\n最大文件大小:16EB(Exabyte)\n最大文件系统大小:16EB\n快照:支持快照(Snapshot)功能,可以快速创建文件系统的时间点副本,用于数据备份和恢复。\n内联数据压缩:支持内联数据压缩(Inline Compression),有效减少存储空间需求。\n子卷管理:支持子卷(Subvolume)管理,允许在同一文件系统中创建多个逻辑卷,提供更灵活的存储管理。\n在线文件系统检查:支持在线文件系统检查和修复(Online Scrubbing and Repair),可以在系统运行时检测和修复数据损坏。\n自我修复:内置数据校验和自我修复功能,自动检测并修复数据损坏,确保数据完整性。\n可扩展性:高可扩展性,支持大规模存储需求,并允许在不中断服务的情况下进行文件系统扩展和缩减。\n\nXFS §\nXFS 文件系统由 Silicon Graphics(SGI)于 1994 年开发,最初用于其高性能计算和图形工作站的 IRIX 操作系统。XFS 以其高性能和可扩展性著称,特别适合处理大文件和高并发 I/O 操作。随着时间的推移,XFS 被移植到 Linux 平台,并在数据密集型应用和科学计算领域得到了广泛应用。\n\n特点\n\n最大文件大小:18EB(Exabyte)\n最大文件系统大小:18EB\n日志记录机制:高效的日志记录机制(Efficient Logging),减少了系统崩溃后的恢复时间,提高了数据可靠性。\n直接 I/O:支持直接 I/O(Direct I/O),允许应用程序直接访问磁盘,绕过文件系统缓存,提高了 I/O 性能。\n可扩展性:极高的可扩展性,能够处理极大规模的存储需求,适用于高性能计算和数据中心。\n动态扩展:支持文件系统的动态扩展(Dynamic Allocation),在不卸载文件系统的情况下进行扩展。\n并发支持:优秀的并发支持,适用于高并发的 I/O 操作场景,如数据库和大规模数据处理。\n\nZFS §\nZFS(Zettabyte 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 版本,增加了对事务性 NTFS(TxF)的支持,以提高文件操作的可靠性和一致性。虽然 TxF 在后来版本中被弃用,但它显示了 NTFS 在功能和性能上的不断改进。\n2012 年,随着 Windows 8 的发布,微软推出了ReFS 文件系统(Resilient File System),旨在提供更高的数据完整性和可扩展性。ReFS 具有自动修复、数据校验、数据损坏隔离等特性,特别适用于大规模数据存储和虚拟化环境。ReFS 支持的最大文件大小和文件系统大小为 1YB(1 百万 TB)。\n2017 年,随着 Windows 10 的更新,微软引入了对 Linux 文件系统(如 Ext4 和 Btrfs)的支持,通过 Windows Subsystem for Linux(WSL),使用户能够在 Windows 上使用 Linux 文件系统和工具。这标志着 Windows 文件系统生态的进一步扩展和兼容性提升。\nWindows 文件系统的发展历程从早期的 FAT 和 FAT16,逐步发展到功能强大的 NTFS,再到专为大规模数据存储设计的 ReFS,每一次升级都带来了更高的性能、可靠性和功能。现代 Windows 操作系统还通过 WSL 支持 Linux 文件系统,展示了其在兼容性和多样性上的持续改进。\nNTFS §\nNTFS(New 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文件和卷加密:支持 EFS(Encrypting File System)加密技术,提供文件和文件夹级别的加密保护。\n磁盘配额:允许管理员设置磁盘配额,限制用户或组的磁盘使用量。\n压缩:支持文件和文件夹的压缩功能,节省存储空间。\n日志功能:具有日志功能,记录文件系统元数据的变更,确保数据完整性和快速恢复。\n单个文件和卷大小:支持高达 256TB 的单个文件和卷大小,满足大规模存储需求。\n权限管理:提供细粒度的文件和文件夹权限设置,增强了数据安全性。\n索引服务:支持文件内容索引,加快文件搜索速度。\n\nFAT32 §\nFAT32(File 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 §\nexFAT(Extended File Allocation Table)于 2006 年由 Microsoft 发布,旨在替代 FAT32,专为闪存存储设备(如 SD 卡和 USB 闪存驱动器)优化。exFAT 解决了 FAT32 在文件大小和卷大小上的限制,同时保持了跨平台兼容性。\n特点\n\n文件和卷大小:支持高达 128PB 的卷大小和无实际限制的文件大小,适用于大容量存储需求。\n优化性能:针对闪存存储器优化,提供更高的读写性能。\n跨平台兼容性:广泛支持多种操作系统,适合便携式存储设备。\n簇大小:支持更大的簇大小,适合处理大文件。\n简单性:比 NTFS 结构简单,适合嵌入式系统和便携设备。\n\nReFS §\nReFS(Resilient 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 计算机的初代文件系统——MFS(Macintosh File System)。MFS 是一个简单的文件系统,支持单级目录结构和 128KB 的块大小。虽然对于早期的 Macintosh 计算机来说足够,但随着存储需求的增加,MFS 的局限性逐渐显现。\n1985 年,Apple 发布了**HFS(Hierarchical File System)**以替代 MFS。HFS 引入了分层目录结构,支持更大容量的硬盘和文件系统,最大支持 2GB 的卷和 2GB 的文件大小。HFS 采用 512 字节的块大小,并增加了多级目录支持,极大地改善了文件管理。\n1998 年,随着 Mac OS 8.1 的发布,Apple 推出了HFS+(也称为 Mac OS Extended),这是对 HFS 的重大改进。HFS+ 引入了更小的块大小(4KB),大幅提高了磁盘空间利用率,支持的最大卷和文件大小分别扩展到 8EB(exabytes)。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,并引入了APFS(Apple 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最大文件大小:8EB(Exabyte)\n最大卷大小:8EB\n硬链接和软链接:支持硬链接和软链接,提供更灵活的文件管理方式。\n文件压缩:支持文件压缩,减少存储空间的占用。\n分层目录结构:改进的分层目录结构,支持更大的文件和目录。\nUnicode 支持:改进的文件名编码,支持 Unicode 字符集,增强了跨平台兼容性。\n数据完整性:支持日志功能,记录文件系统的元数据更改,提高数据完整性和恢复速度。\n\nAPFS §\n文化和发展历史\nAPFS(Apple File System)是 Apple 于 2017 年发布的新一代文件系统,设计初衷是替代 HFS+,以满足现代存储需求。APFS 针对 SSD 和闪存存储器进行了优化,显著提升了性能和数据安全性。APFS 随着 macOS High Sierra 的发布而引入,并逐渐成为 macOS、iOS、watchOS 和 tvOS 的标准文件系统。其设计注重高性能、高安全性和高效的存储管理,适应了当前和未来的数据存储需求。\n特点\n\n最大文件大小:8EB(Exabyte)\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)权限。所有者信息文件的所有者用户 ID(UID)和所属组 ID(GID)。创建时间文件创建的时间戳。修改时间文件内容最后修改的时间戳。访问时间文件最后访问的时间戳。链接计数指向此 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组别读(r)写(w)执行(x)User421Group421Others421\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 System,DFS)是一种通过网络将文件存储在多个节点上的系统。它允许文件和数据跨越多台计算机进行存储和访问,从而实现高可用性、高性能和高扩展性。以下内容将详细介绍几种常见的分布式文件系统,包括 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可扩展性:易于扩展集群规模。通过添加新的 DataNode,HDFS 可以方便地扩展存储容量和处理能力。\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挂载卷:使用客户端将卷挂载到本地文件系统,通常使用 FUSE(Filesystem 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用于接收和保存流复制的 WAL(Write-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用于解析和显示 WAL(Write-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: 用于存储即将写入 WAL(Write-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 https://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 https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm\n \n# 通过 curl 命令下载\ncurl -O https://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 语句类型(例如所有语句或只有 DDL)log_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类型:连接类型。常见的有 local(Unix 域套接字)、host(TCP/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":"概述 §\nSQL(Structured Query Language)是一种用于管理关系型数据库的强大语言。它的历史可以追溯到 1970 年,当时 IBM 的研究员 Edgar F. Codd 发表了论文 A Relational Model of Data for Large Shared Data Banks 中首次提出。最初,SQL 被称为 SEQUEL(Structured 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数据控制语言(DCL,Data 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 Database,TSDB)是一种专门用于处理时间序列数据的数据库,即按照时间顺序排序的数据点序列。这些数据库特别适用于存储、检索和处理与时间戳关联的数据,例如股票市场数据、传感器数据、网络监控数据等。\n特点 §\n\n时间优化:针对时间序列数据的存储和查询进行了优化,以支持高效的时间范围查询和聚合。\n高写入性能:能够处理大量的写入操作,适合记录连续产生的数据。\n可扩展性:许多时间序列数据库支持水平扩展,可用于大规模数据处理。\n数据压缩:使用专门的算法进行数据压缩,减少存储需求。\n自动数据管理:自动执行数据过期和降采样等操作,以管理数据的生命周期。\n\n时间序列数据库解决了传统数据库在处理时序数据方面的挑战,适用于需要高效存储和分析时间序列数据的场景。\n常用产品 §\n\n\n\n\n\n\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 Database,OODB)是一种数据库,其存储结构以对象的形式来表示信息,直接支持面向对象编程语言的各种特性,如封装、继承和多态等。对象数据库试图使数据库的存储方式与应用程序的编程模型更加一致,简化开发流程。\n特点 §\n\n对象模型:数据以对象的形式存储,每个对象都可以包含数据和方法,完全符合面向对象的概念。\n支持继承和多态:可以定义对象之间的继承关系和多态行为,增加了数据模型的表现力和灵活性。\n直接持久化:允许应用程序中的对象直接持久化到数据库中,无需进行复杂的映射和转换。\n复杂结构支持:非常适合存储具有复杂结构和关系的数据,如几何模型、多媒体数据等。\n\n常用产品 §\n\n\n\n\n\n\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 主要带来了 DSC(Desired 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, Linux)WindowsUnix 系统(Linux, Mac)Unix 系统(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-18:LocalSystem 账户的设置。S-1-5-19:LocalService 账户的设置。S-1-5-20:NetworkService 账户的设置。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 提供了强大的远程管理功能,可以通过 WinRM(Windows 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 系统默认使用的终端是 Bash(Bourne-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 年间首次提出,随后在 Multics(MULTiplexed 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 shell(sh)**史蒂夫·伯恩在贝尔实验室时编写。1978 年随 Version 7 Unix 首次发布。\n\nAlmquist shell(ash)由肯尼斯·艾昆斯特(Kenneth Almquist)在 SVR4 上建立了这个分支。\n**Bourne-Again shell(bash)**由布莱恩·福克斯在 1987 年为了 GNU 计划而编写。\nDebian Almquist shell(dash)由赫伯特·许(Herbert Xu)1997 年移植到 Linux 上后改名为 dash。\nKorn shell(ksh)David Korn 在贝尔实验室时编写。\nZ shell(zsh)是 macOS(2019 年起) 一款可用作交互式登录的 shell 及脚本编写的命令解释器。\n\n\n\nC Shell 兼容 §\n\nC shell(csh)比尔·乔伊在加州大学伯克利分校时编写。1979 年随 BSD 首次发布。\n\nTENEX C shell(tcsh) 一个向下兼容 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\nBeemos(BEEMos)–在 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 – 迪吉多(DEC)PDP-10 调试工具,麻省理工学院 Incompatible Timesharing System 的指令壳层\nDROS – 智能手机上基于 Java ME 平台的类 DOS 壳层\nEFI-SHELL –可扩展固件界面(Extensible Firmware Interface,EFI)指令壳层,它是开放源代码的\nGoogle Shell –基于浏览器的 Google Search 前端界面\niSeries QSHELL – IBM OS/400 上的 Unix 风格壳层\nMacintosh Programmer’s 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 或 light)set 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 https://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 https://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 https://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 https://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选择一个支持丰富功能的终端,例如 iTerm2(macOS)、Alacritty(跨平台)、GNOME Terminal(Linux)。\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 https://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 版。\nhttps://yianwillis.github.io/vimcdoc/\n为了最佳阅读效果,请确保你的系统安装了 ‘Noto Sans Mono CJK SC’ 或 NSimsun 字 体,否则可能有字体不能完全对齐的情况。\n下 载 §\nhttps://github.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本文属于 OPL(OpenContent 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原文网址:http://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)都没有结果,网站上也许还有报告 Bug(Bug-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's,loose 搞成 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\nI’ve posted my question in $LANGUAGE and English. I’ll 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有一个古老而神圣的传统:如果你收到 RTFM(Read The Fucking Manual) 的回应,回答者认为你应该去读他妈的手册。当然,基本上他是对的,你应该去读一读。\nRTFM 有一个年轻的亲戚。如果你收到 STFW(Search 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 Expression,Regex)是用于匹配字符串中字符组合的模式。它由一系列字符和特殊符号组成,可以高效地执行查找、替换、检查数据格式等多种文本处理任务。正则表达式的概念最初由数学家斯蒂芬·克莱尼在 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 或 YAML,INI 文件仍保留了其实用性和便捷性。\nYAML §\nYAML(YAML Ain’t 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\nKubernetes:YAML 用于定义容器和服务的配置,如 Pods、Deployments 等。\nCI/CD 管道:如 GitLab CI 和 GitHub Actions 中定义作业和工作流。\n\nXML §\nXML(eXtensible 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 §\nTOML(Tom’s 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 协议\nSSH(Secure 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 文件列表, 你可以在 https://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 Systems,VCS)是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。\n本地版本控制系统 §\n本地版本控制系统大多采用数据库来记录文件的历次更新差异。\n其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。\n\n集中化的版本控制系统 §\n为了解决本地版本控制系统无法协同工作的问题,集中化的版本控制系统(Centralized Version Control Systems,CVCS)应允而生。其采用一个单一集中管理的服务器,保存所有文件的修订版本;协作者通过客户端连接服务器,拉取最新文件或提交更新。\n\n优点:相较于本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。\n缺点:显而易见的缺点是中央服务器的单点故障。例如宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作;如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。\n\n\n分布式版本控制系统 §\n为了解决集中化的版本控制系统的痛处,分布式版本控制系统(Distributed Version Control System,DVCS)面世了。分布式顾名思义,每一个节点都基于公认中心节点服务器的镜像拷贝,故每个节点都拥有代码仓库的完整信息。因此不存在中心节点故障无法工作、物理损坏无法恢复、日志历史不完整导致协作者无法相互协作。\n更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。\n\nGit 简史 §\n同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。\nLinux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002 年间)。到 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 LFS(Large File Storage) 相当于 Git 的一种插件式增强工具,简单讲,它是在 Git 仓库使用这些文件的指针代替实际文件,而把实际文件存储在远程端 LFS 服务器,同时在本地仓库中实时追踪这些文件的变动。\n安装 §\nLinux §\n$ curl -s https://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 https://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 https://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,用于新工作的 pu(proposed 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 使用的是 0x0A(LF),早期的 Mac OS 使用的是 0x0D(CR),后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用 0x0D0A(CRLF) 作为换行符。\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模块(Modules):Ansible 的基本执行单元,每个模块都实现了特定的功能,如安装软件包、管理文件、执行命令等。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:通过 WSL(Windows Subsystem for Linux)或在 Windows 上安装 Cygwin,可以在 Windows 上运行 Ansible。\n\nAnsible 运行时需要以下基本依赖项:\n\nPython:Ansible 需要 Python 2.7 或 Python 3.5 及以上版本。\nSSH:Ansible 通过 SSH 与被管理节点通信,需要在控制节点和被管理节点上配置 SSH。\n其他依赖:根据具体模块需求,可能需要额外安装一些依赖包,例如用于云平台管理的 SDK。\n\nAnsible 安装步骤 §\n在不同操作系统上的安装 §\nUbuntu §\n在 Ubuntu 上安装 Ansible 非常简单,可以通过官方的包管理器 APT 进行安装:\nsudo apt update\nsudo apt install ansible\nCentOS §\n在 CentOS 上,可以通过 EPEL(Extra 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 https://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: "https://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示例 Playbook(deploy_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示例静态 Inventory(hosts):\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: https://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 https://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: http://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: 'http://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 Config(YAML 格式):使用 #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、KVM),Cloud-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 https://github.com/example/repo.git /opt/repo"},"Technology/OperatingSystem/Automation/PXE--系统部署":{"title":"PXE 自动化部署","links":[],"tags":["linux/安装","技术/操作系统","自动化/linux"],"content":"PXE 技术概述 §\nPXE(Preboot 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 技术的优势与局限性 §\nPXE(Preboot 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 是最著名的公共仓库,但用户也可以创建私有仓库来存储和管理自己的镜像。\nDockerfile:Dockerfile 是一个文本文件,包含了一系列的指令和参数,用于自动化构建 Docker 镜像的过程。通过编写 Dockerfile,开发者可以定义如何构建镜像,包括添加文件、运行命令和配置环境等。\nDocker Compose:Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件,你可以配置应用服务所需的所有容器,然后使用一个命令同时创建和启动所有这些容器。\n\nDocker 工作原理 §\nDocker 使用容器来运行应用,容器运行在 Docker 引擎之上。Docker 引擎负责管理容器的生命周期,包括容器的创建、启动、停止、移动和删除。容器与虚拟机相比,占用的资源更少,启动更快,因为容器共享宿主机的内核,而不需要模拟整个操作系统。\nDocker 设计架构 §\nDocker 的架构主要基于客户端 - 服务器(Client-Server)模型,涉及几个关键组件:Docker 客户端、Docker 服务器(也称为守护进程)、Docker 镜像、容器、仓库等。\n\nDocker 客户端(Client):Docker 客户端是用户与 Docker 交互的主要方式。用户通过运行 Docker 客户端命令来告诉 Docker 守护进程需要做什么。例如,构建镜像、运行容器、停止容器等操作都是通过客户端发起的。\nDocker 服务器(守护进程,Daemon):Docker 守护进程运行在宿主机上,处理客户端发来的请求,如创建、运行、监控容器,构建和存储镜像等。守护进程与其他 Docker 守护进程通信,管理 Docker 服务。\n\nDocker 客户端和守护进程可以在同一系统上运行,也可以将 Docker 客户端连接到远程 Docker 守护进程。 Docker 客户端和守护进程使用 REST API 通过 UNIX 套接字或网络接口进行通信。\n"},"Technology/OperatingSystem/Docker/基础/安装配置":{"title":"安装配置","links":[],"tags":["docker/基础","技术/操作系统"],"content":"官方手册 §\n\nGet Docker:https://docs.docker.com/get-docker/\n\n安装脚本 §\n正式版本 §\ncurl -fsSL https://get.docker.com -o get-docker.sh\nsh get-docker.sh\n测试版本 §\ncurl -fsSL https://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 "https://hub-mirror.c.163.com",\n "https://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/CD):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特性/产品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 "https://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 文件中,为后端服务设置了内存限制为 500MB,CPU 使用限制为 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 http://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\nDockerfile:Dockerfile 是构建 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 网络使用 VXLAN(Virtual 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&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 Service,UnICS)操作系统,是一个强大的多用户、多任务操作系统,支持多种处理器架构,按照操作系统的分类,属于分时操作系统,最早由肯·汤普逊、丹尼斯·里奇和道格拉斯·麦克罗伊于 1969 年在 AT&T 的贝尔实验室开发。\n目前它的商标权由国际开放标准组织所拥有,只有符合单一 UNIX 规范的 UNIX 系统才能使用 UNIX 这个名称,否则只能称为类 UNIX(UNIX-like)。\n1965 年贝尔实验室计划要创建一套多用户、多任务、多层次(multi-user、multi-processor、multi-level)的 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,是 GNU’s Not Unix 的首字母递归缩写——这是对 Unix 的技术思想致敬的一种方法,同时表达 GNU 有所不同。从技术上说,GNU 很像 Unix。但是它不同于 Unix,GNU 给予其用户自由。\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&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 社区也为用户、开发者和支持者提供了一个交流和协作的平台。https://www.fsf.org/)\nLinux 基金会 §\nLinux 基金会 旨在推动 Linux 和开源生态系统的增长。它主办各种技术峰会,发布研究报告,同时也主导了多个重要的开源项目,比如 CNCF(云原生计算基金会),LF AI(Linux 基金会人工智能),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 包含一个称为 YaST(Yet 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 Linux(RHEL)是一个由 **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\nCentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是基于 Red Hat Enterprise Linux(RHEL)依照开放源代码规定发布的源代码所编译而成。因为源于相同的源代码,因此许多需要高度稳定性的服务器选择 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 是社区开发的 RHEL;Fedora 是面向社区、快节奏的 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 版本发布时,就已将 Unicode(UTF-8)设为系统默认编码,以应对全球各地不同的语言和文字符号,努力为用户提供一个无乱码的交流平台。在语言支持方面,Ubuntu 是 Linux 发行版中的佼佼者。\n发布周期 §\nUbuntu 每 6 个月发布一个新版本,每个版本都有自己的代号和版本号。长期支持版本(LTS)每两年发布一次,它的更新和维护时间相对较长。\n\n社区评价 §\n在 2005 年伦敦举行的 Linux 世界论坛及会议(LinuxWorld Conference and Expo)上,Ubuntu 被读者选为最佳 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 Linux,WSL),部分用户认为这是背叛了 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概述 §\nTails(The 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 提供了一个用户友好的、美观的桌面环境,被称为 DDE(Deepin 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 资源,同时在内存不足时,优先回收低优先级的进程组的内存,保障在线业务的正常运行。\nKubeOS:OpenEuler 实现了一种名为 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 Foundation:Apache 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早期阶段:最初的引导加载器非常简单,主要是在特定存储设备上找到一个可执行的程序来启动操作系统。这种简单的引导方法适用于单操作系统环境,但在现代复杂的多操作系统环境中不再适用。\nLILO(Linux Loader):LILO 是 Linux 早期使用的引导加载器,支持在多操作系统之间进行简单切换。它的配置相对复杂,且不支持动态更新。\nGRUB 的出现:为了克服 LILO 的限制,GRUB(Grand Unified Bootloader)作为更强大的引导加载器被开发出来,支持动态更新和更复杂的启动配置。\n\nGRUB 历史发展 §\nGRUB(GRand Unified Bootloader)作为一种广泛使用的引导加载器,其历史发展体现了计算机引导技术的演变。从最初的 GRUB Legacy 到现代的 GRUB 2.x,它的功能和特性经历了显著的变化和提升。\nGRUB 0.x 和 GRUB Legacy(GRUB 1.x) §\nGRUB 的发展始于 1999 年,最早的稳定版本 GRUB 0.97 发布。它被设计为 LILO(LInux 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**随着计算机硬件逐步转向 UEFI(Unified Extensible Firmware Interface),GRUB 也适应了这一变化。**在 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 1:GRUB 的 Stage 1 通常位于硬盘的主引导记录(MBR)中。由于 MBR 只有 512 字节的大小限制,Stage 1 的代码非常简短,主要任务是定位并加载 Stage 1.5 或 Stage 2。Stage 1 的目标是让计算机找到并启动 Stage 1.5 或直接启动 Stage 2。\nStage 1.5:Stage 1.5 是 GRUB 特有的一个中间层,通常存储在硬盘的第一个分区之前的空闲区域中。它的主要作用是提供对文件系统的支持,使得 GRUB 能够从特定的文件系统中加载 Stage 2。这一阶段的引入是为了弥补 Stage 1 无法直接处理复杂文件系统的不足。\nStage 2:Stage 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\nUbuntu:Ubuntu 在安装过程中会自动安装 GRUB。若需要手动安装,可以使用以下命令:\nsudo grub2-install /dev/sda\nsudo update-grub\n其中,/dev/sda 表示要安装 GRUB 的硬盘。如果需要修复 GRUB(例如由于分区表变动导致 GRUB 无法启动),可以使用 Ubuntu Live CD 或 USB 启动系统,然后在 Live 环境下安装和更新 GRUB。\n\n\nCentOS:CentOS 也在安装过程中自动安装 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-pc(Legacy BIOS)和 x86_64-efi(UEFI)。用于选择 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 的安装位置和方式。\nMBR(Master Boot Record) §\n对于 MBR 分区表,grub-install 通常将 GRUB 的 Stage 1 部分安装到 MBR(即硬盘的第一个扇区)。这是 Legacy BIOS 模式下的常见方法:\nsudo grub2-install /dev/sda\n安装完成后,GRUB 会将控制权转移给 Stage 1.5 或 Stage 2 部分,并加载操作系统内核。\nGPT(GUID 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 加密磁盘**:LUKS(Linux 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安装完成后,启用 gdm(GNOME Display Manager):\nsudo systemctl enable gdm\nsudo systemctl start gdm\n8.3.2 安装 KDE Plasma 桌面环境 §\nKDE Plasma 是一个高度可定制的桌面环境,适合喜欢自定义的用户。\nsudo pacman -S plasma kde-applications\n安装完成后,启用 sddm(Simple 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 https://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:打印服务管理器。\nhplip:HP 打印机驱动(适用于 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 http://example.com/software-x.y.z.tar.gz\n \n# 或使用 git 克隆源代码仓库\ngit clone https://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易用、更新快、软件库丰富个人、办公、教育等领域https://ubuntu.com/https://mirrors.ustc.edu.cn/Debian稳定、安全、软件包多服务器、开发等领域https://www.debian.org/https://mirrors.ustc.edu.cn/CentOS稳定、安全、兼容性好、商业支持企业级应用、服务器等领域https://www.centos.org/https://mirrors.ustc.edu.cn/Red Hat Enterprise Linux (RHEL)稳定、安全、商业支持、适用于企业级应用企业级应用、服务器等领域https://www.redhat.com/zh/technologies/linux-platforms/enterprise-linuxFedora最新的开源软件、社区驱动开发、实验、桌面等领域https://getfedora.org/https://mirrors.ustc.edu.cn/Arch Linux简单、灵活、滚动更新开发、实验、高级用户等领域https://www.archlinux.org/https://mirrors.ustc.edu.cn/\n以下是一些常用的中国国内 GNU/Linux 官方镜像站点:\n\n清华大学开源软件镜像站:https://mirrors.tuna.tsinghua.edu.cn/\n阿里云开源镜像站:https://mirrors.aliyun.com/\n网易开源镜像站:http://mirrors.163.com/\n中科大开源镜像站:https://mirrors.ustc.edu.cn/\n华中科技大学开源镜像站:https://mirrors.hust.edu.cn/\n上海交通大学开源软件镜像站:https://ftp.sjtu.edu.cn/\n北京交通大学开源软件镜像站:https://mirror.bjtu.edu.cn/\n北京理工大学开源镜像站:https://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 https://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 问题描述 §\nGRUB(Grand 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 问题描述 §\nMBR(Master Boot Record)和 GPT(GUID 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 https://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 或 macOS,Linux 使用包管理器来自动化软件的安装、更新、配置和删除,极大简化了软件管理的复杂性。包管理器不仅确保软件和其依赖关系正确安装,还能保持系统的整洁和更新。\n定义和作用 §\n包管理器是 Linux 和 Unix-like 系统中用于自动化处理软件包任务的工具。它允许用户搜索、安装、更新、配置和删除软件包,而无需手动下载和解压缩。更重要的是,包管理器处理软件包之间的依赖关系,确保系统稳定运行,避免 ” 依赖地狱 “。\n软件包格式 §\nLinux 软件包有多种格式,最常见的是 Debian 系的 .deb 和 Red Hat 系的 .rpm。\n\n.deb:Debian、Ubuntu 及其衍生版使用的软件包格式,通过 dpkg 和 APT 等工具进行管理。\n.rpm:Red 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 Linux(RHEL)和 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 官方源:http://deb.debian.org/\n\n\nDebian 安全源:https://security.debian.org/\n\n\nUbuntu 官方源:http://archive.ubuntu.com\n\n\nCentOS 官方源:http://mirror.centos.org/\n\n\n由于国内网络环境的特殊性,使用国外官方仓库源可能会遇到较慢的下载速度或无法连接的问题。因此,一些开源社区提供了针对国内用户的镜像仓库源,用于加速软件包下载和更新。\n\n阿里云开源镜像站:http://mirrors.aliyun.com/\n中科大开源软件镜像站:https://mirrors.ustc.edu.cn/\n教育网联合镜像站:https://help.mirrors.cernet.edu.cn/\n\n一键脚本 §\nLinuxMirrors 是一个由 SuperManito 维护的 Linux 镜像站点列表。该项目旨在为 Linux 用户提供可靠、高速的镜像站点列表,用户可以通过该列表轻松找到离自己最近的镜像站点,以加速软件包的下载和更新。\nLinuxMirrors: https://github.com/SuperManito/LinuxMirrors\nbash <(curl -sSL https://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 签名验证 §\nGPG(GNU 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 https://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 §\nZIP(Zone 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 §\nGzip(GNU zip)是一种广泛使用的文件压缩和解压缩工具。它基于 DEFLATE 算法,该算法结合了 LZ77(Lempel-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 §\n7z(7-Zip)是一款开源的文件压缩和解压缩工具,主要使用 LZMA(Lempel-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 命令,可以指定新用户的用户名、用户 ID(UID)、主目录、默认 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 §\nusermod(user 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修改用户的用户 ID(UID)。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 §\nuserdel(User 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 §\nsu(switch 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用户 ID(UID):新用户的用户标识符。\n主组 ID(GID):新用户的主组标识符。\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 §\npwck(Password Check)和 grpck(Group 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 §\npwconv(Password Conversion)、pwunconv(Password unConversion)、grpconv(Group Conversion)和 grpunconv(Group 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 系统默认使用的终端是 Bash(Bourne-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\nGDB(GNU Debugger):GDB 是最广泛使用的调试工具之一,它不仅可以用于用户空间程序的调试,也可以用来调试内核本身及其模块。GDB 的强大之处在于它支持单步执行、断点设置、变量检查和内存状态分析等功能,极大地方便了内核开发和调试过程。\nKdump 和 Crash:在遇到内核崩溃的情况下,Kdump 和 Crash 的组合使用尤为重要。Kdump 利用 kexec 技术,在系统崩溃时迅速启动一个新内核并抓取崩溃时的内存转储,而 Crash 工具则用于分析这些转储文件,帮助开发者快速定位问题原因。\nperf:perf 是 Linux 下的性能分析工具,它能够提供丰富的性能数据,包括 CPU 使用率、缓存命中情况、上下文切换次数等,对于性能优化具有重要意义。\nFtrace:Ftrace 是一个功能强大的内核跟踪工具,通过在内核中插入跟踪点来监视和记录函数调用过程和时序信息,对于理解内核行为和性能分析非常有用。\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 及其衍生版使用 apt,Red 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 及其衍生系统通常使用 yum(CentOS 7 及之前版本)或 dnf(Fedora 和 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 管理 DNS:NetworkManager 可以自动配置 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 系统中用于查看文件内容的命令。相比于其他查看器,如 more,less 提供了更多的功能和灵活性。\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\nausearch:ausearch 工具用于在审计日志中进行高级搜索和过滤。它可以根据时间、进程、文件、用户等条件来查询特定的审计事件。以下是一些常用的 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\naureport:aureport 工具用于生成审计日志的报告和摘要信息。它可以提供关于审计事件的统计数据、趋势分析和可视化图表。以下是一些常用的 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单元(Units):systemd 将服务、挂载点、设备等管理对象抽象为单元,通过单元文件进行配置。\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 和 Wants:Requires 会在依赖的单元失败时终止当前单元,而 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/O:IOWeight= 控制服务的磁盘 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 和 Kubernetes,systemd 常用于管理容器的生命周期,配合 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 Test,POST)的过程。这个过程是由电脑的基本输入/输出系统(Basic Input/Output System,BIOS)或统一可扩展固件接口(Unified Extensible Firmware Interface,UEFI)来管理的。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 启动加载程序有 GRUB(GNU GRand Unified Bootloader)、LILO(Linux 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初始化虚拟文件系统(VFS):Linux 内核会初始化虚拟文件系统(VFS),这是管理所有文件和目录的核心组件。\n\n\n挂载根文件系统:内核会挂载根文件系统(通常是 ”/”)。这通常涉及到读取硬盘上的数据,并可能需要启动额外的驱动程序来识别文件系统(如 ext4、btrfs 等)。\n\n\n启动 init 进程:最后,内核会启动一个特殊的用户空间程序,称为 init 进程。这个进程的进程 ID(PID)是 1,它负责启动所有其他的用户空间程序和服务。\n\n\n4.系统初始化阶段 §\n**在 Linux 内核完成初始化并挂载了根文件系统后,它将启动第一个用户空间程序,这个进程通常被称为 init 进程。init 进程的进程 ID(PID)是 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),邮件服务器,SSH,FTP 等都属于典型的服务。这些服务是操作系统正常运行的重要组成部分,负责处理各种系统任务和应用请求。\n服务管理则是操作系统中的一项重要任务,其主要目标是保证服务能够稳定、高效地运行,同时,也能够便捷地进行服务的配置和维护。为了达到这个目标,人们设计了许多不同的服务管理系统,例如 SysV init,Upstart,以及现在广泛使用的 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 §\nSELinux(Security-Enhanced Linux)是一个强大的 Linux 内核安全模块,用于实现访问控制安全策略。它通过强制访问控制(MAC)限制用户和进程对系统资源的访问,从而提高系统安全性。\nSELinux 的起源可以追溯到 1998 年,当时美国国家安全局(NSA)与安全系统研究小组(SFR)共同开发了一个名为 Flask 的安全架构。该架构的目标是为操作系统提供一种强大且灵活的访问控制机制。在 2000 年,NSA 将 Flask 架构集成到 Linux 内核中,从而诞生了 SELinux。\nSELinux 的开发过程受到了开源社区的广泛支持。Red Hat 在 2003 年发布的 Red Hat Enterprise Linux 4(RHEL 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 §\nAppArmor(Application Armor)是一种 Linux 安全模块,目标是保护应用程序免受潜在威胁。AppArmor 通过强制访问控制(MAC)限制应用程序对系统资源的访问,以此增强系统的安全性。AppArmor 的安全策略配置相对简单,易于理解和配置,这主要得益于它基于路径的访问控制方式。\nAppArmor 于 1998 年诞生,最初由 Immunix 公司开发,旨在为 Linux 系统提供一个易于管理且高效的安全解决方案。2005 年,Novell 收购了 Immunix 公司,并在同年将 AppArmor 开源。从那时起,AppArmor 成为了一个独立的开源项目,吸引了众多开发者和维护者的加入。\n2007 年,AppArmor 成为 Ubuntu 7.10(Gutsy 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 对比 §\nSELinux(Security-Enhanced Linux)和 AppArmor(Application 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 Wrappers(TCP 包装器)是一个开源的网络服务请求过滤系统,用于实现主机基础的网络访问控制列表(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 的保护。此外,当面临一些复杂的网络攻击时,比如分布式拒绝服务攻击(DDoS),TCP 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 和 TLS:SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)是用于在网络通信中提供安全层的协议。它们用于保护数据的隐私和完整性。TLS 是 SSL 的后续版本,目前更为常用。\nSSH:SSH(Secure Shell)是一种网络协议,用于安全地远程连接到服务器。SSH 提供了强大的认证和安全通信功能,包括加密远程会话和传输文件。\nPGP(Pretty Good Privacy):PGP 是一种数据加密和解密程序,提供加密、解密和数字签名的服务。它常用于保护电子邮件的隐私和完整性,同时也可用于加密文件和存储设备。\n公钥基础设施(PKI)和证书颁发机构(CA):PKI 是一套基于公钥密码学的加密体系结构,用于生成、管理和分发数字证书。证书颁发机构是负责验证用户身份并颁发数字证书的可信实体。\n一次性密码(OTP)和多因素认证(MFA):OTP 是一种仅限单次使用的密码,用于增强身份验证的安全性。MFA 要求用户提供两个或多个不同类型的身份验证因素,例如密码、指纹识别、硬件令牌或手机验证码。\nIPSec(Internet Protocol Security):IPSec 是一组协议和算法,用于在网络层提供数据的机密性、完整性和身份验证。它常用于虚拟私有网络(VPN)和远程访问连接的安全保护。\n数字证书:数字证书是由证书颁发机构颁发的电子文件,用于验证用户、服务器或组织的身份。数字证书使用公钥密码学来验证身份,并可用于安全通信和电子交易。\n访问控制列表(ACL):ACL 是一种用于控制网络设备上的流量的机制。它基于源 IP 地址、目标 IP 地址、协议和端口号等条件来决定数据包的接受或拒绝。\n防火墙:防火墙是一种网络安全设备,用于监控和控制进出网络的流量。它可以根据预定义的安全策略过滤流量,以阻止未经授权的访问和网络攻击。\n单点登录(SSO):SSO 是一种身份验证机制,允许用户使用单一的凭据(如用户名和密码)访问多个相关系统。这减少了用户需要记住多个凭据的负担,并提供了更方便的身份验证体验。\n加密硬件设备:加密硬件设备(如硬件安全模块)提供了物理级别的安全性,用于存储和处理敏感数据、生成和管理密钥,并执行加密操作。这些设备通常具有更高的安全性和防护能力。\n双因素认证(2FA):双因素认证要求用户在登录过程中提供两个或多个不同类型的身份验证凭据,如密码、硬件令牌、指纹识别或短信验证码。这提供了更强的身份验证保护,即使密码被泄露也能降低风险。\n安全套接层虚拟专用网(SSL VPN):SSL 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 是一种用于在内核和用户空间之间传递信息的通信机制。通过 Netlink,ip 命令能够执行各种复杂的网络配置任务。\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网络地址转换(NAT)PREROUTING、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 §\nufw(Uncomplicated 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 Interface:UFW 提供了一个简单的命令行界面,通过该界面用户可以方便地管理防火墙规则。\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 Daemon:firewalld 是一个常驻内存的守护进程,负责管理防火墙规则。它通过 D-Bus 接口提供与外部交互的能力,可以动态加载和卸载规则,而不需要重启防火墙服务。\nD-Bus Interface:D-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 环境下,iptables,nftables,ufw 和 firewalld 都是常用的防火墙工具,每种工具都有其独特的优点和使用场景:\n在 Linux 环境下,iptables,nftables,ufw 和 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 Service,QoS)是一种用于分配网络带宽的技术,确保网络资源的公平使用和最佳利用。通过 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 System,IDS)可以检测网络中的恶意行为和攻击活动。常见的 IDS 工具包括 Snort、Suricata、OSSEC 和 Bro/Zeek。\n\nSnort:一款开源的网络入侵检测和防御系统,基于规则匹配和异常检测来识别恶意流量。\nSuricata:一个高性能的开源 IDS/IPS/NSM(网络安全监控)引擎,支持实时流量分析和威胁防御。\nOSSEC:一个开源的主机入侵检测系统,用于监控文件系统、日志文件和网络活动。\nBro/Zeek:一款强大的网络安全监控平台,支持实时流量分析、协议解析和异常检测。\n\n网络安全监控系统(NMS) §\n网络安全监控系统(Network Monitoring System,NMS)用于实时监控网络设备和服务的运行状况,发现性能问题和安全威胁。常见的 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 Layer,SSL)和传输层安全(Transport Layer Security,TLS)是应用于网络传输层的加密技术,用于保护 Web 浏览、电子邮件和其他应用程序的数据安全。\nIPSec:Internet 协议安全(IP Security,IPSec)是一个用于保护 IP 数据包传输安全的协议套件,提供加密、认证和完整性保护功能。IPSec 广泛应用于 VPN 技术中。\nSSH:安全外壳(Secure Shell,SSH)是一种加密网络协议,用于在不安全的网络环境中实现安全的远程登录、文件传输和其他网络服务。\n\n安全认证和授权 §\n安全认证和授权技术用于验证用户身份和控制用户访问权限。主要技术包括 RADIUS、TACACS+、LDAP、Kerberos 等。\n\nRADIUS:远程认证拨号用户服务(Remote Authentication Dial-In User Service,RADIUS)是一个用于 AAA(认证、授权和计费)的网络协议,广泛应用于网络接入和 VPN 服务中。\nTACACS+:终端访问控制器访问控制系统 +(Terminal Access Controller Access-Control System+,TACACS+)是一种用于网络设备管理的 AAA 协议,主要应用于路由器、交换机等网络设备的远程管理。\nLDAP:轻型目录访问协议(Lightweight Directory Access Protocol,LDAP)是一种用于访问和维护分布式目录信息服务的协议,常用于企业网络的用户认证和组织结构管理。\nKerberos:一种基于票据的网络认证协议,用于实现单点登录(Single Sign-On,SSO)和安全的跨域认证。\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 Table,FAT)系列:FAT12、FAT16、FAT32、exFAT\n新技术文件系统(New Technology File System,NTFS)\n分层文件系统(Hierarchical File System,HFS)和 HFS Plus\n延伸文件系统(Extended File System,ext)系列:ext1、ext2、ext3、ext4\n旧式数据系统(Old Data System,ODS)\nBtrfs(B-tree 文件系统)\nXFS(SGI 的高性能日志文件系统)\nUFS(Unix 文件系统)\nZFS(Zettabyte 文件系统)\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 Standard,FHS)。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/nvme0n2:8 GiB,8589934592 字节,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文件系统UUID:28337fe9-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磁盘性能监测 §\nsysstat(System 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 系统中有三种基本的权限:读(r,read)、写(w,write)和执行(x,execute)。也可以使用数字来表示文件或目录的权限。每个权限用一个数字表示,分别为 4、2 和 1,分别代表读、写和执行权限。通过将这些数字相加,可以得到一个三位数的数字,用于表示用户、组和其他用户的权限。这些权限分别适用于文件和目录。权限可以分为三组,分别为:用户(u,user),组(g,group)和其他(o,others)。\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总的来说,这个目录的权限是755(rwxr-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权限数字文件权限目录权限读(r)4允许用户读取文件内容允许用户查看目录内容写(w)2允许用户修改文件内容允许用户在目录中创建、删除和重命名文件执行 (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 机上,系统分区通常使用 MBR(Master Boot Record)或 GPT(GUID 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)是计算机中用于管理硬盘分区的数据结构,记录硬盘上分区的信息和布局方式。**操作系统通过读取分区表来获取硬盘分区的信息,并根据这些信息进行分区、格式化、挂载等操作。分区表通常存储在硬盘的特定位置,例如 MBR(Master Boot Record)分区表通常存储在硬盘的第一个扇区,而 GPT(GUID Partition Table)分区表则存储在硬盘的最后一个扇区。\n分区表的历史可以追溯到早期的操作系统,例如 MS-DOS 和 Windows 95 等。早期的操作系统并不支持硬盘分区的概念,所有数据都存储在同一个分区中,这带来了数据管理和备份的不便,也限制了硬盘容量的利用。\n为了克服这些限制,早期的操作系统开始使用分区表来管理硬盘分区。**最早被广泛使用的分区表格式之一是 MBR 分区表,出现于 1983 年,可以管理最多 4 个主分区或 3 个主分区和 1 个扩展分区。**另一种早期的分区表格式是 APM(Apple Partition Map),由苹果公司开发用于管理 Macintosh 计算机上的硬盘分区。\n随着计算机硬件的不断升级,MBR 分区表无法满足大容量硬盘的管理需求。于是,新的分区表格式 GPT(GUID Partition Table)应运而生。GPT 使用全球唯一的 GUID 标识硬盘上的分区信息,支持的最大硬盘容量达 EB(exabyte)级别,最多可以管理 128 个分区。GPT 分区表还支持热插拔、校验和、备份分区表等特性,由于使用了 GUID 标识分区信息,GPT 比 MBR 更加安全可靠。\n**MBR 分区方案以其广泛的兼容性和简单易用性著称,几乎所有现有的操作系统和硬件都支持 MBR,且其分区表结构简单,便于操作和维护。**然而,MBR 也存在明显的缺点。首先,它只能支持最大 2TB 的硬盘容量,在现代计算机应用中可能不够用。此外,MBR 最多支持四个主分区或三个主分区加一个扩展分区,这在某些情况下显得不足。最重要的是,MBR 没有备份分区表的机制,一旦损坏,可能导致数据丢失。\n尽管 MBR 的兼容性较好,但随着计算机技术的发展,MBR 的局限性逐渐显现。未来,MBR 可能会在特定场景下继续使用,例如在旧式硬件或操作系统上。然而,随着硬盘容量的增长和技术的进步,MBR 正逐渐被 GPT 分区方案所取代。GPT 分区方案具有更大的磁盘容量支持、更多的分区数量和更高的数据安全性,已经成为现代操作系统和硬件的首选分区方案。\nMBR 分区 §\n**MBR(Master Boot Record)是一种分区表结构,位于硬盘的第一个扇区(通常为磁盘的第一个物理扇区,即 LBA 0)。**MBR 包含了操作系统启动引导代码(Bootloader)和分区表信息。MBR 的主要作用是在计算机启动时加载操作系统。\nMBR 分区方案的历史可以追溯到 1983 年,当时 IBM PC/AT 发布。当时的 PC/AT 使用 16 位 Intel 80286 处理器,最大寻址空间为 16 MB。随着硬盘容量的增长,MBR 分区方案逐渐显现出容量限制。因此,GPT(GUID Partition Table)分区方案应运而生,取代了 MBR。\n标准 MBR 结构 §\nMBR 分区表结构包括以下部分:\n\nBootloader(446 字节):存放引导加载程序,负责将操作系统从磁盘加载到内存。\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(分区表条目 1)0x1CE070646216主分区 2(分区表条目 2)0x1DE073647816主分区 3(分区表条目 3)0x1EE076649416主分区 4(分区表条目 4)0x1FE07765102签名(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**GPT(GUID Partition Table)是一种分区表结构,适用于新型磁盘和操作系统。**GPT 是 UEFI(统一可扩展固件接口)规范的一部分,用于替代传统的 MBR(Master 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保护性 MBR(LBA 0):在 GPT 磁盘的第一个扇区,包含一个伪 MBR,以兼容旧式磁盘管理工具。\nGPT Header(LBA 1):包含 GPT 分区表的元数据,如分区表大小、分区表位置等。\nPartition Entry Array(LBA 2~33):存储分区条目信息。每个分区条目占用 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 §\nParted(GNU 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 §\ngdisk(GUID 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随着硬盘容量的增加和新技术的发展,GPT(GUID 分区表)逐渐取代了 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 Management,LVM)是一种在 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 Volume,PV):物理卷是指磁盘或分区等物理存储设备。在使用 LVM 之前,需要将物理存储设备划分为物理卷,并且将它们标记为 LVM 可用的卷。\n卷组(Volume Group,VG):卷组是由一个或多个物理卷组成的逻辑容器。卷组可以包含多个物理卷,这些物理卷可以来自不同的磁盘,也可以是同一磁盘上的不同分区。在 LVM 中,卷组是用来为逻辑卷提供空间的。\n逻辑卷(Logical Volume,LV):逻辑卷是在卷组上创建的逻辑分区。逻辑卷可以动态地分配和释放存储空间,并且可以根据需要调整大小。逻辑卷可以被格式化为文件系统,并像常规分区一样使用。\n\n主要特性 §\n逻辑卷管理器(LVM,Logical 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文件系统UUID:68dd2677-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 §\niSCSI(Internet 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/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。QEMU(Quick 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\nDashboard(Horizon):提供用户友好的图形管理界面,便于管理员和用户管理和监控云资源。\n命令行工具(CLI):提供丰富的命令行工具,支持自动化脚本和批量操作,提高管理效率。\nHeat:OpenStack 的编排服务,通过模板定义和管理云资源,实现自动化部署和管理。\n\n性能优化与监控\n\nCeilometer:OpenStack 的计量和监控服务,提供详细的资源使用数据和性能监控,帮助管理员优化资源分配。\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) 是一个开源的虚拟化管理平台,支持 KVM(Kernel-based Virtual Machine)和 LXC(Linux 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 收购 InnoTek,VirtualBox 成为 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 Machine,VM)是一种模拟物理机的软件环境,可以运行操作系统和应用软件。每个虚拟机都有自己的虚拟硬件和独立的操作系统,使得多个虚拟机可以在同一台物理机上独立运行。\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:容器编排平台,用于自动化部署、扩展和管理容器化应用。\nLXC(Linux Containers):基于 Linux 的轻量级容器技术。\n\n5. 软件定义网络(SDN) §\nSDN 通过软件控制网络硬件,实现网络资源的虚拟化和集中管理。SDN 使网络管理员能够灵活配置和管理网络资源,提升网络效率和灵活性。\n\nOpenFlow:一种开放标准协议,允许 SDN 控制器与网络设备进行通信,实现网络资源的虚拟化。\nSDN 控制器:管理和控制网络设备的软件平台,常见的控制器包括 OpenDaylight、ONOS 和 Cisco APIC。\n虚拟网络设备:如虚拟交换机(vSwitch)、虚拟路由器(vRouter),用于实现网络资源的虚拟化和管理。\n\n6. 存储虚拟化 §\n存储虚拟化通过将物理存储资源抽象为逻辑存储资源,实现存储资源的集中管理和优化利用。\n\nSAN(Storage Area Network)虚拟化:将多个存储设备连接成一个高性能存储网络,提供统一管理和高可用性。\nNAS(Network 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 年发布了首款商业虚拟化产品,标志着现代虚拟化技术的兴起。随着开源社区的崛起,KVM(Kernel-based Virtual Machine)于 2006 年被合并到 Linux 内核中,成为开源虚拟化领域的重要组成部分。KVM 通过将 Linux 内核转变为一个 Hypervisor,为用户提供了高效且灵活的虚拟化解决方案。\nKVM 的定位和重要性 §\nKVM(Kernel-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? §\nKVM(Kernel-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 vSphere:VMware vSphere 是一种成熟的商业虚拟化解决方案,具有强大的管理工具和企业支持。相比之下,KVM 虽然是开源项目,但在灵活性和成本效益方面具有优势。\nMicrosoft Hyper-V:Hyper-V 是微软的虚拟化解决方案,与 Windows Server 紧密集成。KVM 则与 Linux 紧密集成,适合在 Linux 环境中使用。\nXen:Xen 是另一种开源虚拟化技术,早期采用半虚拟化技术,后来也支持全虚拟化。KVM 相较于 Xen,更容易与 Linux 系统集成,并且逐渐在开源社区中获得更广泛的支持。\n\nKVM 在开源社区的影响力 §\nKVM 作为一个开源项目,受到了广泛的支持和贡献。它不仅是许多 Linux 发行版的默认虚拟化技术,还在许多开源项目(如 OpenStack、oVirt 和 Proxmox)中发挥着关键作用。KVM 的成功得益于其高效的性能、灵活的架构以及与 Linux 内核的紧密集成。作为开源社区的重要组成部分,KVM 推动了虚拟化技术的发展和普及,为各类应用场景提供了强大的支持。\nKVM 的基本概念 §\n\nKVM 的工作原理 §\nKVM(Kernel-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 等。\nWindows:KVM 支持多种版本的 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)中起着关键作用。通过 KVM,IaaS 提供商能够为用户提供按需计算资源,包括虚拟机、存储和网络。这种灵活的资源分配和管理方式,使得用户可以根据其业务需求快速部署和调整计算资源,同时仅为实际使用的资源付费。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 虚拟机的管理和自动化能力,使其更易于集成和使用。\nVirtio:Virtio 项目致力于优化虚拟机的 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) 的源代码构建,适合服务器环境。\nRHEL:Red 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 管理工具是用于管理和控制 KVM(Kernel-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-V:Windows Server 内置的虚拟化技术,适用于 Windows 环境。\n其他:还支持 LXC(Linux 容器)、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 和 LXC(Linux 容器),提供企业级的虚拟化解决方案。其主要功能和特点包括:\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 网络基础 §\nKVM(Kernel-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 'https://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-net,IP 地址范围为 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-net,IP 地址范围为 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假设物理接口为 eth0,VLAN ID 为 100,VLAN 接口命名为 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存储概念 §\nKVM(Kernel-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) §\nNFS(Network File System)通过网络共享文件系统,适合共享存储和集中存储管理,以及多台虚拟机需要共享同一存储资源的环境。\n挂载 NFS 存储:\nsudo mount -t nfs server:/path/to/nfs /mnt/nfs\niSCSI(Internet 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)基于 LVM(Logical 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在 KVM(Kernel-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完全公平调度器(CFS):Linux 默认的调度策略,适用于大多数场景。通过调整 CFS 参数,可以优化虚拟机的 CPU 性能。\n实时调度器(RT):适用于对延迟敏感的应用,如音视频处理或实时计算任务。可以通过设置实时优先级和资源预留来优化性能。\n自动化调度工具:使用如 libvirt 的调度策略配置功能,自动优化虚拟机的调度策略。\n\n通过以上方法和工具,可以系统地优化 KVM 环境下虚拟机的 CPU 性能,从而提高整体系统的效率和稳定性。在实际应用中,应根据具体需求和工作负载特征,选择合适的优化策略和参数设置,以达到最佳性能表现。\n内存性能优化 §\n内存性能是虚拟化环境中影响虚拟机(VM)运行效率的关键因素之一。KVM(Kernel-based Virtual Machine)提供了多种内存优化技术,本文将详细探讨内存分配和大页支持、内存过量使用和气球驱动、以及 NUMA 配置优化等方面的内容。\n内存分配和大页支持 §\n分配合适的内存大小 §\n为虚拟机分配合适的内存大小是确保其性能的基本步骤:\n\n评估工作负载需求:根据虚拟机上运行的应用程序和服务的需求,确定所需的内存大小。轻量级应用程序需要较少的内存,而数据密集型或计算密集型应用程序则需要更多的内存。\n避免过度分配:过度分配内存会导致宿主机的内存资源紧张,影响整体系统性能。因此,需要合理分配内存,确保宿主机和所有虚拟机的内存需求都能得到满足。\n动态调整内存:利用 KVM 的热插拔内存功能,可以在虚拟机运行时动态调整内存大小,以应对变化的工作负载需求。\n\n启用和配置大页(HugePages) §\n大页(HugePages)是指较大的内存页,用于减少内存分页和 TLB(Translation 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非一致性内存访问(NUMA,Non-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在 KVM(Kernel-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\nCFQ(Completely 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 命令设置优先级 §\ntc(Traffic 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在 KVM(Kernel-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在 KVM(Kernel-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在 KVM(Kernel-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 是一个开源的服务器代理,用于收集和发送指标数据,作为 TICK(Telegraf, InfluxDB, Chronograf, Kapacitor)堆栈的一部分。插件驱动的架构,支持多种输入和输出插件,易于集成和扩展。\n使用内置工具监控 §\nKVM(Kernel-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 读写情况。可以通过进程 ID(PID)进一步分析相关进程的具体操作和配置。\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 官网:https://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)) # 输出:2,b 不再引用\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横向制表符(Tab)print("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 # False,set2 是 set1 的子集吗?\nset3 <= set1 # False,set3 是 set1 的子集吗?\nset1 >= set2 # False,set1 是 set2 的超集吗?\nset1 >= set3 # False,set1 是 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('https://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 names):Python 语言内置的名称,如函数名 abs、char 和异常名称 BaseException、Exception 等。\n全局名称(global names):模块中定义的名称,包括模块的函数、类、导入的模块、模块级别的变量和常量。\n局部名称(local names):函数中定义的名称,包括函数的参数和局部定义的变量。\n\n\n作用域 §\n作用域定义了命名空间可以直接访问的代码段,决定了在哪一部分程序可以访问特定的变量名。Python 的作用域一共有 4 种,分别是:\n\n\nL(Local):最内层,包含局部变量,比如一个函数/方法内部。\nE(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类)A 里面又包含了一个函数 B,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。\nG(Global):当前脚本的最外层,比如当前模块的全局变量。\nB(Built-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 Programming,OOP)是一种编程范式或模型,以「对象」作为核心来设计和实现软件。这种方法主要的目标是将数据和处理数据的函数结合在一起,封装成独立的软件模块,我们称之为「对象」。面向对象编程被广泛应用于多种编程语言中,包括 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 Python’s 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 是什么? §\nPEP(Python Enhancement Proposal,Python 增强提案),它是 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 Code,Python编码规范\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 aren’t 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 you’re Dutch.\n尽管这方法一开始并非如此直观,除非你是荷兰人。\nNow is better than never. Although never is often better than right now.\n做优于不做,然而不假思索还不如不做。\nIf the implementation is hard to explain, it’s a bad idea.\n很难解释的,必然是坏方法。\nIf the implementation is easy to explain, it may be a good idea.\n很好解释的,可能是好方法。\nNamespaces are one honking great idea — let’s 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 开发者在设计语言时,如果面临多种选择,一般会拒绝花俏的语法,而选择明确没有或者很少有歧义的语法。\nPyPI(Python Package Index,PyPI)是 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以下是一个使用 Flask(Python 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 或 option,configparser 就会抛出 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/lumberjack,my_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 文件是什么 §\nCSV(Comma 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 15:50:07,431 - myapp.utils - INFO - User signed in successfully [in /path/to/utils.py:456] \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 15:49:23,895levelname日志级别的文本表示,如 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 20:14:32.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/Linux)UNIX/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/Linux)UNIX/Linuxos.getgid()获取当前组 ID(仅 UNIX/Linux)UNIX/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?key1=val1&key2=val2'\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.10:3128",\n "https": "http://10.10.1.10:1080",\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:与一些第三方库相比(如 requests),urllib 的 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': 'http://www.example.com:8080'})Request()创建一个请求对象,用于定制 HTTP 头等req = urllib.request.Request(url, headers={...})\nurlopen() 打开 URL §\nimport urllib.request\n \n# 打开一个网页\nresponse = urllib.request.urlopen('http://www.example.com')\n \n# 读取网页内容\ndata = response.read()\n \n# 输出网页内容\nprint(data)\nurlretrieve() 下载文件 §\nimport urllib.request\n \n# 从指定 URL 下载文件,并保存到本地\nurllib.request.urlretrieve('http://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': '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('http://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': '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='http://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('http://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('http://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('http://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('http://www.example.com/path?query=arg')\n \n# 将ParseResult对象转换回URL\nnew_url = urlunparse(parsed_url)\n \n# 类似于urlparse(),但不分割params\nsplit_result = urlsplit('http://www.example.com/path?query=arg')\n \n# 将由urlsplit()返回的对象转换回URL\noriginal_url = urlunsplit(split_result)\n \n# 合并两个URL\nnew_url = urljoin('http://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('http://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('*', 'http://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('http://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('*', 'http://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 提供了一些内置的函数式工具,如 lambda,map(),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\nIPC(Inter-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 的主要目的是简化 CPython(Python 的标准解释器)的实现。由于多线程并发访问数据可能会导致数据损坏或不一致的情况,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('https://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 定义的异常类(如 DatabaseError,IntegrityError 等)来识别和响应特定的错误情况。\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 语句。ORM(Object-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 文件处理 §\nJSON(JavaScript 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 b)assertIsNot(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除了 unittest,Python 还有其他流行的测试框架,如 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('https://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 版本(使用 pyenv)pipenv 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 = "https://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 https://install.python-poetry.org | python3 -\nWindows (Powershell) §\n如果是通过 Microsoft Store 安装的 Python,请将命令中的 py 替换为 python。\n(Invoke-WebRequest -Uri https://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 https://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 https://foo.bar/simple/\n \n# --secondary 选项配置辅助包源\npoetry source add --secondary foo https://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 https://install.python-poetry.org | python3 - --uninstall\ncurl -sSL https://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\nvenv:Python3 中自带的轻量级虚拟环境管理工具。\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 - FL(Backus)\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比尔·乔伊,发明了 vi,BSD 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/CI&CD/GitHub-Actions":{"title":"GitHub Actions","links":[],"tags":["技术/软件工程","软件工程/cicd"],"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)或调用预定义的 action(uses)。步骤在同一个作业中按顺序执行,且共享相同的上下文,包括工作目录、环境变量等。\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除了 Webhooks,GitHub 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 配置文件: 使用 HPA(Horizontal 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有限的自定义:相比 Jenkins,Travis 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/CI&CD/GitLab-Runner":{"title":"GitLab Runner","links":[],"tags":["技术/软件工程","软件工程/cicd"],"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: https://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: https://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/CI&CD/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 年,由于与 Oracle(Sun 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 Control,RBAC),限制用户对不同项目和资源的访问权限。\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-finally:Scripted 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、Cobertura),Jenkins 可以生成代码覆盖率报告,帮助团队了解测试覆盖情况。代码覆盖率报告可以与测试报告一起展示,提供全面的代码质量分析。\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 位置:确保每个分支的根目录下有一个 Jenkinsfile,Jenkins 将根据该文件定义 Pipeline。\n\n多分支 Pipeline 的优势在于它自动适应 Git Flow 等多分支开发策略,每个分支可以独立运行自己的 CI/CD 流水线,极大提高了开发效率。\nJenkins 对 Git 分支的支持与自动化构建 §\nJenkins 对 Git 的支持通过 Git 插件实现,能够自动化处理代码的拉取、构建和测试。对于多分支项目,Jenkins 可以在以下场景下自动触发构建:\n\n新分支创建:当新分支推送到远程仓库时,Jenkins 自动检测并触发构建。\n分支变更:当现有分支发生变更(如代码提交、Merge),Jenkins 自动拉取最新代码并重新构建。\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\nWebhook:GitHub 中配置 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\nHelm:Jenkins 还可以集成 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 Stack(Elasticsearch, 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 X:Jenkins 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 和 SDK:Jenkins 可以在 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 SDK:Jenkins 可以利用 Google Cloud SDK 在 GCP 上进行容器管理、虚拟机管理以及云函数的部署。\n\n\nTerraform 集成:同样可以通过 Terraform 在 GCP 上定义和管理基础设施,配合 Jenkins 的自动化执行,实现 IaC。\n\n\n利用 Infrastructure as Code 实现自动化基础设施部署 §\nInfrastructure as Code(IaC) 是通过代码定义和管理基础设施的实践。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-Slave(Agent)架构,通过分布式构建提升系统的并发能力和资源利用率。\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/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](https://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](https://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许可证向导:https://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、webpack)continuous 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 don’t know how to say—but I hope you can understand my position.”他纠结地说。省略号使用 so…that… 句型表示结果,意思是“如此……以至于……”。“I don’t 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看一下 [这个具体的代码行](https://github.com/user/repository/blob/master/file.py#L42) 来理解如何实现这个功能。\n\n如果链接和引用的位置有更新,必须及时更新链接。\n\n由于最新的更新,参考 [新的代码实现](https://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阅读这篇 [文章](https://example.com/article) 来更深入地了解这个主题。\n使用这个 [工具](https://example.com/tool) 来帮助你的开发工作。\n运行以下 [命令](https://example.com/command) 来配置你的环境。\n\n每个文件的引用必须声明来源,使用全称,不要使用相对路径或者绝对路径。\n\n引用自 [Python官方文档](https://docs.python.org/3/tutorial/index.html),不是 `../tutorial/index.html` 或者 `/home/user/docs/tutorial/index.html`。\n\n不能使用会失效的链接。\n\n请使用 [永久链接](https://example.com/permanent-link),而不是 [会失效的链接](https://example.com/temporary-link)。\n\n链接的文字应描述其链接的内容,而不应为「这里」、「此处」等模糊词汇。\n\n阅读 [Python教程](https://docs.python.org/3/tutorial/index.html),而不是点击 [这里](https://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」,我们需要指出:「AI(Artificial 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表达范围:表示数值范围时使用浪纹式连接号「~」或一字线连接号「—」。例如: 10~20 或 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 km(524.5 千米)、53 MB(53 兆字节)、12 h(12 小时)用于编号的数字- 电话号码: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%英尺符号和英寸符号6’2”\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避免解释缩略语: 例如,不应该写成「API(Application 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/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 Type,ADT)是指一个数学模型及其定义在该模型上的一组操作。\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"}} |