Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu.Wang 2018-05-24 08:21:09 +08:00
commit fec1b8c276
11 changed files with 572 additions and 605 deletions

View File

@ -1,122 +1,116 @@
程序员的学习之路
============================================================
*2016 年 10 月,当我从微软离职时,我已经在微软工作了近 21 年,在业界也快 35 年了。我花了一些时间反思我这些年来学到的东西,这些文字是那篇帖子稍加修改后得到。请见谅,文章有一点长。*
*2016 年 10 月,当我从微软离职时,我已经在微软工作了近 21 年,在业界也快 35 年了。我花了一些时间反思我这些年来学到的东西,这些文字是那篇帖子稍加修改后得到。请见谅,文章有一点长。*
要成为一名专业的程序员,你需要知道的事情多得令人吃惊:语言的细节API算法数据结构系统和工具。这些东西一直在随着时间变化——新的语言和编程环境不断出现,似乎总有热门的新工具或新语言是“每个人”都在使用的。紧跟潮流,保持专业,这很重要。木匠需要知道如何为工作选择合适的锤子和钉子,并且要有能力笔直精准地钉入钉子。
要成为一名专业的程序员,你需要知道的事情多得令人吃惊:语言的细节、API、算法、数据结构、系统和工具。这些东西一直在随着时间变化——新的语言和编程环境不断出现,似乎总有一些“每个人”都在使用的热门的新工具或新语言。紧跟潮流,保持专业,这很重要。木匠需要知道如何为工作选择合适的锤子和钉子,并且要有能力笔直精准地钉入钉子。
与此同时,我也发现有一些理论和方法有着广泛的应用场景,它们能使用几十年。底层设备的性能和容量在这几十年来增长了几个数量级,但系统设计的思考方式还是互相有关联的,这些思考方式比具体的实现更根本。理解这些重复出现的主题对分析与设计我们所负责的系统大有帮助。
谦卑和自我
### 谦卑和自我
这不仅仅局限于编程,但在编程这个持续发展的领域,一个人需要在谦卑和自我中保持平衡。总有新的东西需要学习,并且总有人能帮助你学习——如果你愿意学习的话。一个人即需要保持谦卑,认识到自己不懂并承认它,也要保持自我,相信自己能掌握一个新的领域,并且能运用你已经掌握的知识。我见过的最大的挑战就是一些人在某个领域深入专研了很长时间,“忘记”了自己擅长学习新的东西。最好的学习来自放手去做,建造一些东西,即便只是一个原型或者 hack。我知道的最好的程序员对技术有广泛的认识但同时他们对某个技术深入研究成为了专家。而深入的学习来自努力解决真正困难的问题。
这不仅仅局限于编程,但在编程这个持续发展的领域,一个人需要在谦卑和自我中保持平衡。总有新的东西需要学习,并且总有人能帮助你学习——如果你愿意学习的话。一个人即需要保持谦卑,认识到自己不懂并承认它,也要保持自我,相信自己能掌握一个新的领域,并且能运用你已经掌握的知识。我见过的最大的挑战就是一些人在某个领域深入专研了很长时间,“忘记”了自己擅长学习新的东西。最好的学习来自放手去做,建造一些东西,即便只是一个原型或者 hack。我知道的最好的程序员对技术有广泛的认识但同时他们对某个技术深入研究成为了专家。而深入的学习来自努力解决真正困难的问题。
端到端观点
### 端到端观点
1981 年Jerry Saltzer, Dave Reed 和 Dave Clark 在做因特网和分布式系统的早期工作,他们提出了端到端观点,并作出了[经典的阐述][4]。网络上的文章有许多误传,所以更应该阅读论文本身。论文的作者很谦虚,没有声称这是他们自己的创造——从他们的角度看,这只是一个常见的工程策略,不只在通讯领域中,在其他领域中也有运用。他们只是将其写下来并收集了一些例子。下面是文章的一个小片段:
1981 年Jerry Saltzer Dave Reed 和 Dave Clark 在做因特网和分布式系统的早期工作,他们提出了<ruby>端到端<rt>end to end</rt></ruby>观点,并作出了[经典的阐述][4]。网络上的文章有许多误传,所以更应该阅读论文本身。论文的作者很谦虚,没有声称这是他们自己的创造——从他们的角度看,这只是一个常见的工程策略,不只在通讯领域中,在其他领域中也有运用。他们只是将其写下来并收集了一些例子。下面是文章的一个小片段:
> 当我们设计系统的一个功能时,仅依靠端点的知识和端点的参与,就能正确地完整地实现这个功能。在一些情况下,系统的内部模块局部实现这个功能,可能会对性能有重要的提升。
论文称这是一个“观点”,虽然在维基百科和其他地方它已经被上升成“原则”。实际上,还是把它看作一个观点比较好,正如作者们所说,系统设计者面临的最难的问题之一就是如何在系统组件之间划分责任,这会引发不断的讨论:怎样在划分功能时权衡利弊,怎样隔离复杂性,怎样设计一个灵活的高性能系统来满足不断变化的需求。没有简单的原则可以直接遵循。
论文称这是一个“观点”,虽然在维基百科和其他地方它已经被上升成“原则”。实际上,还是把它看作一个观点比较好,正如作者们所说,系统设计者面临的最难的问题之一就是如何在系统组件之间划分责任,这会引发不断的讨论:怎样在划分功能时权衡利弊,怎样隔离复杂性,怎样设计一个灵活的高性能系统来满足不断变化的需求。没有简单的原则可以直接遵循。
互联网上的大部分讨论集中在通信系统上,但端到端观点的适用范围其实更广泛。分布式系统中的“最终一致性”就是一个例子。一个满足“最终一致性”的系统,可以让系统中的元素暂时进入不一致的状态,从而简化系统,优化性能,因为有一个更大的端到端过程来解决不一致的状态。我喜欢横向拓展的订购系统的例子(例如亚马逊),它不要求每个请求都通过中央库存的控制点。缺少中央控制点可能允许两个终端出售相同的最后一本书,所以系统需要用某种方法来解决这个问题,如通知客户该书会延期交货。不论怎样设计,想购买的最后一本书在订单完成前都有可能被仓库中的叉车运出厍(译注:比如被其他人下单购买)。一旦你意识到你需要一个端到端的解决方案,并实现了这个方案,那系统内部的设计就可以被优化,并利用这个解决方案。
互联网上的大部分讨论集中在通信系统上,但端到端观点的适用范围其实更广泛。分布式系统中的“<ruby>最终一致性<rt>eventual consistency</rt></ruby>”就是一个例子。一个满足“最终一致性”的系统,可以让系统中的元素暂时进入不一致的状态,从而简化系统,优化性能,因为有一个更大的端到端过程来解决不一致的状态。我喜欢横向拓展的订购系统的例子(例如亚马逊),它不要求每个请求都通过中央库存的控制点。缺少中央控制点可能允许两个终端出售相同的最后一本书,所以系统需要用某种方法来解决这个问题,如通知客户该书会延期交货。不论怎样设计,想购买的最后一本书在订单完成前都有可能被仓库中的叉车运出厍(LCTT 译注:比如被其他人下单购买)。一旦你意识到你需要一个端到端的解决方案,并实现了这个方案,那系统内部的设计就可以被优化利用这个解决方案。
事实上,这种设计上的灵活性可以优化系统的性能,或者提供其他的系统功能,从而使得端到端的方法变得如此强大。端到端的思考往往允许内部进行灵活的操作,使整个系统更加健壮,并且能适应每个组件特性的变化。这些都让端到端的方法变得健壮,并能适应变化。
端到端方法意味着,添加会牺牲整体性能灵活性的抽象层和功能时要非常小心(也可能是其他的灵活性,但性能,特别是延迟,往往是特殊的)。如果你展示出底层的原始性能(performance, 也可能指操作),端到端的方法可以根据这个性能(操作)来优化,实现特定的需求。如果你破坏了底层性能(操作),即使你实现了重要的有附加价值的功能,你也牺牲了设计灵活性。
端到端方法意味着,添加会牺牲整体性能灵活性的抽象层和功能时要非常小心(也可能是其他的灵活性,但性能,特别是延迟,往往是特殊的)。如果你展示出底层的原始性能(LCTT 译注performance也可能指操作下同),端到端的方法可以根据这个性能(操作)来优化,实现特定的需求。如果你破坏了底层性能(操作),即使你实现了重要的有附加价值的功能,你也牺牲了设计灵活性。
如果系统足够庞大而且足够复杂,需要把整个开发团队分配给系统内部的组件,那么端到端观点可以和团队组织相结合。这些团队自然要扩展这些组件的功能,他们通常从牺牲设计上的灵活性开始,尝试在组件上实现端到端的功能。
应用端到端方法面临的挑战之一是确定端点在哪里。 俗话说,“大跳蚤上有小跳蚤,小跳蚤上有更少的跳蚤……等等”。
关注复杂性
### 关注复杂性
编程是一门精确的艺术,每一行代码都要确保程序的正确执行。但这是带有误导的。编程的复杂性不在于各个部分的整合,也不在于各个部分之间如何相互交互。最健壮的程序将复杂性隔离开,让最重要的部分变的简单直接,通过简单的方式与其他部分交互。虽然隐藏复杂性和信息隐藏、数据抽象等其他设计方法一样,但我仍然觉得,如果你真的要定位出系统的复杂所在,并将其隔离开,那你需要对设计特别敏锐。
编程是一门精确的艺术,每一行代码都要确保程序的正确执行。但这是带有误导的。编程的复杂性不在于各个部分的整合,也不在于各个部分之间如何相互交互。最健壮的程序将复杂性隔离开,让最重要的部分变的简单直接,通过简单的方式与其他部分交互。虽然隐藏复杂性和信息隐藏、数据抽象等其他设计方法一样,但我仍然觉得,如果你真的要定位出系统的复杂所在,并将其隔离开,那你需要对设计特别敏锐。
在我的[文章][5]中反复提到的例子是早期的终端编辑器 VI 和 Emacs 中使用的屏幕重绘算法。早期的视频终端实现了控制序列,来控制绘制字符核心操作,也实现了附加的显示功能,来优化重新绘制屏幕,如向上向下滚动当前行,或者插入新行,或在当前行中移动字符。这些命令都具有不同的开销,并且这些开销在不同制造商的设备中也是不同的。(参见[TERMCAP][6]以获取代码链接和更完整的历史记录。)像文本编辑器这样的全屏应用程序希望尽快更新屏幕,因此需要优化使用这些控制序列来转换屏幕从一个状态到另一个状态。
在我的[文章][5]中反复提到的例子是早期的终端编辑器 VI 和 Emacs 中使用的屏幕重绘算法。早期的视频终端实现了控制序列,来控制绘制字符核心操作,也实现了附加的显示功能,来优化重新绘制屏幕,如向上向下滚动当前行,或者插入新行,或在当前行中移动字符。这些命令都具有不同的开销,并且这些开销在不同制造商的设备中也是不同的。(参见[TERMCAP][6] 以获取代码和更完整的历史记录的链接。)像文本编辑器这样的全屏应用程序希望尽快更新屏幕,因此需要优化使用这些控制序列来从一个状态到另一个状态屏幕转换
这些程序在设计上隐藏了底层的复杂性。系统中修改文本缓冲区的部分(功能上大多数创新都在这里)完全忽略了这些改变如何被转换成屏幕更新命令。这是可以接受的,因为针对*任何*内容的改变计算最佳命令所消耗的性能代价,远不及被终端本身实际执行这些更新命令的性能代价。在确定如何隐藏复杂性,以及隐藏哪些复杂性时,性能分析扮演着重要的角色,这一点在系统设计中非常常见。屏幕的更新与底层文本缓冲区的更改是异步的,并且可以独立于缓冲区的实际历史变化顺序。缓冲区*怎样*改变的并不重要,重要的是改变了*什么*。异步耦合,在组件交互时消除组件对历史路径依赖的组合,以及用自然的交互方式以有效地将组件组合在一起是隐藏耦合复杂度的常见特征。
这些程序在设计上隐藏了底层的复杂性。系统中修改文本缓冲区的部分(功能上大多数创新都在这里)完全忽略了这些改变如何被转换成屏幕更新命令。这是可以接受的,因为针对*任何*内容的改变计算最佳命令所消耗的性能代价,远不及被终端本身实际执行这些更新命令的性能代价。在确定如何隐藏复杂性,以及隐藏哪些复杂性时,性能分析扮演着重要的角色,这一点在系统设计中非常常见。屏幕的更新与底层文本缓冲区的更改是异步的,并且可以独立于缓冲区的实际历史变化顺序。缓冲区*怎样*改变的并不重要,重要的是改变了*什么*。异步耦合,在组件交互时消除组件对历史路径依赖的组合,以及用自然的交互方式以有效地将组件组合在一起是隐藏耦合复杂度的常见特征。
隐藏复杂性的成功不是由隐藏复杂性的组件决定的,而是由使用该模块的使用者决定的。这就是为什么组件的提供者至少要为组件的某些端到端过程负责。他们需要清晰的知道系统的其他部分如何与组件相互作用,复杂性是如何泄漏出来的(以及是否泄漏出来)。这常常表现为“这个组件很难使用”这样的反馈——这通常意味着它不能有效地隐藏内部复杂性,或者没有选择一个隐藏复杂性的功能边界。
分层与组件化
### 分层与组件化
系统设计人员的一个基本工作是确定如何将系统分解成组件和层;决定自己要开发什么,以及从别的地方获取什么。开源项目在决定自己开发组件还是购买服务时,大多会选择自己开发,但组件之间交互的过程是一样的。在大规模工程中,理解这些决策将如何随着时间的推移而发挥作用是非常重要的。从根本上说,变化是程序员所做的一切的基础,所以这些设计决定不仅在当下评估,还要随着产品的不断发展而在未来几年得到评估。
系统设计人员的一个基本工作是确定如何将系统分解成组件和层;决定自己要开发什么,以及从别的地方获取什么。开源项目在决定自己开发组件还是购买服务时,大多会选择自己开发,但组件之间交互的过程是一样的。在大规模工程中,理解这些决策将如何随着时间的推移而发挥作用是非常重要的。从根本上说,变化是程序员所做的一切的基础,所以这些设计决定不仅在当下评估,还要随着产品的不断发展而在未来几年得到评估。
以下是关于系统分解的一些事情,它们最终会占用大量的时间,因此往往需要更长的时间来学习和欣赏。
* 层泄漏。层(或抽象)[基本上是泄漏的][1]。这些泄漏会立即产生后果,也会随着时间的推移而产生两方面的后果。其中一方面就是该抽象层的特性渗透到了系统的其他部分,渗透的程度比你意识到得更深入。这些渗透可能是关于具体的性能特征的假设,以及抽象层的文档中没有明确的指出的行为发生的顺序。这意味着假如内部组件的行为发生变化,你的系统会比想象中更加脆弱。第二方面是你比表面上看起来更依赖组件内部的行为,所以如果你考虑改变这个抽象层,后果和挑战可能超出你的想象。
* **层泄漏。**层(或抽象)[基本上是泄漏的][1]。这些泄漏会立即产生后果,也会随着时间的推移而产生两方面的后果。其中一方面就是该抽象层的特性渗透到了系统的其他部分,渗透的程度比你意识到得更深入。这些渗透可能是关于具体的性能特征的假设,以及抽象层的文档中没有明确的指出的行为发生的顺序。这意味着假如内部组件的行为发生变化,你的系统会比想象中更加脆弱。第二方面是你比表面上看起来更依赖组件内部的行为,所以如果你考虑改变这个抽象层,后果和挑战可能超出你的想象。
* **层具有太多功能。**您所采用的组件具有比实际需要更多的功能,这几乎是一个真理。在某些情况下,你决定采用这个组件是因为你想在将来使用那些尚未用到的功能。有时,你采用组件是想“上快车”,利用组件完成正在进行的工作。在功能强大的抽象层上开发会带来一些后果。
1. 组件往往会根据你并不需要的功能作出取舍。
2. 为了实现那些你并不没有用到的功能,组件引入了复杂性和约束,这些约束将阻碍该组件的未来的演变。
3. 层泄漏的范围更大。一些泄漏是由于真正的“抽象泄漏”另一些是由于明显的逐渐增加的对组件全部功能的依赖但这些依赖通常都没有处理好。Office 软件太大了,我们发现,对于我们建立的任何抽象层,我们最终都在系统的某个部分完全运用了它的功能。虽然这看起来是积极的(我们完全地利用了这个组件),但并不是所用的使用都有同样的价值。所以,我们最终要付出巨大的代价才能从一个抽象层往另一个抽象层迁移,这种“长尾”没什么价值,并且对使用场景认识不足。
4. 附加的功能会增加复杂性,并增加功能滥用的可能。如果将验证 XML 的 API 指定为 XML 树的一部分,那这个 API 可以选择动态下载 XML 的模式定义。这在我们的基本文件解析代码中被错误地执行,导致 w3c.org 服务器上的大量性能下降以及无意分布式拒绝服务攻击。这些被通俗地称为“地雷”API
* **抽象层被更换。**需求在进化,系统在进化,组件被放弃。您最终需要更换该抽象层或组件。不管是对外部组件的依赖还是对内部组件的依赖都是如此。这意味着上述问题将变得重要起来。
* **自己构建还是购买的决定将会改变。**这是上面几方面的必然结果。这并不意味着自己构建还是购买的决定在当时是错误的。一开始时往往没有合适的组件,一段时间之后才有合适的组件出现。或者,也可能你使用了一个组件,但最终发现它不符合您不断变化的要求,而且你的要求非常窄、很好理解,或者对你的价值体系来说是非常重要的,以至于拥有自己的模块是有意义的。这意味着你像关心自己构造的模块一样,关心购买的模块,关心它们是怎样泄漏并深入你的系统中的。
* **抽象层会变臃肿。**一旦你定义了一个抽象层,它就开始增加功能。层是对使用模式优化的自然分界点。臃肿的层的困难在于,它往往会降低您利用底层的不断创新的能力。从某种意义上说,这就是操作系统公司憎恨构建在其核心功能之上的臃肿的层的原因——采用创新的速度放缓了。避免这种情况的一种比较规矩的方法是禁止在适配器层中进行任何额外的状态存储。微软基础类在 Win32 上采用这个一般方法。在短期内,将功能集成到现有层(最终会导致上述所有问题)而不是重构和重新推导是不可避免的。理解这一点的系统设计人员寻找分解和简化组件的方法,而不是在其中增加越来越多的功能。
* 层具有太多功能了。您所采用的组件具有比实际需要更多的功能这几乎是一个真理。在某些情况下你决定采用这个组件是因为你想在将来使用那些尚未用到的功能。有时你采用组件是想“上快车”利用组件完成正在进行的工作。在功能强大的抽象层上开发会带来一些后果。1) 组件往往会根据你并不需要的功能作出取舍。 2) 为了实现那些你并不没有用到的功能组件引入了复杂性和约束这些约束将阻碍该组件的未来的演变。3) 层泄漏的范围更大。一些泄漏是由于真正的“抽象泄漏”另一些是由于明显的逐渐增加的对组件全部功能的依赖但这些依赖通常都没有处理好。Office 太大了我们发现对于我们建立的任何抽象层我们最终都在系统的某个部分完全运用了它的功能。虽然这看起来是积极的我们完全地利用了这个组件但并不是所用的使用都有同样的价值。所以我们最终要付出巨大的代价才能从一个抽象层往另一个抽象层迁移这种“长尾巴”没什么价值并且对使用场景认识不足。4) 附加的功能会增加复杂性,并增加功能滥用的可能。如果将验证 XML 的 API 指定为 XML 树的一部分,那这个 API 可以选择动态下载 XML 的模式定义。这在我们的基本文件解析代码中被错误地执行,导致 w3c.org 服务器上的大量性能下降以及无意分布式拒绝服务攻击。这些被通俗地称为“地雷”API
### 爱因斯坦宇宙
* 抽象层被更换。需求发展,系统发展,组件被放弃。您最终需要更换该抽象层或组件。不管是对外部组件的依赖还是对内部组件的依赖都是如此。这意味着上述问题将变得重要起来。
* 自己构建还是购买的决定将会改变。这是上面几方面的必然结果。这并不意味着自己构建还是购买的决定在当时是错误的。一开始时往往没有合适的组件,一段时间之后才有合适的组件出现。或者,也可能你使用了一个组件,但最终发现它不符合您不断变化的要求,而且你的要求非常窄,能被理解,或着对你的价值体系来说是非常重要的,以至于拥有自己的模块是有意义的。这意味着你像关心自己构造的模块一样,关心购买的模块,关心它们是怎样泄漏并深入你的系统中的。
* 抽象层会变臃肿。一旦你定义了一个抽象层,它就开始增加功能。层是对使用模式优化的自然分界点。臃肿的层的困难在于,它往往会降低您利用底层的不断创新的能力。从某种意义上说,这就是操作系统公司憎恨构建在其核心功能之上的臃肿的层的原因——采用创新的速度放缓了。避免这种情况的一种比较规矩的方法是禁止在适配器层中进行任何额外的状态存储。微软基础类在 Win32 上采用这个一般方法。在短期内,将功能集成到现有层(最终会导致上述所有问题)而不是重构和重新推导是不可避免的。理解这一点的系统设计人员寻找分解和简化组件的方法,而不是在其中增加越来越多的功能。
爱因斯坦宇宙
几十年来我一直在设计异步分布式系统但是在微软内部的一次演讲中SQL 架构师 Pat Helland 的一句话震惊了我。 “我们生活在爱因斯坦的宇宙中,没有同时性。”在构建分布式系统时(基本上我们构建的都是分布式系统),你无法隐藏系统的分布式特性。这是物理的。我一直感到远程过程调用在根本上错误的,这是一个原因,尤其是那些“透明的”远程过程调用,它们就是想隐藏分布式的交互本质。你需要拥抱系统的分布式特性,因为这些意义几乎总是需要通过系统设计和用户体验来完成。
几十年来我一直在设计异步分布式系统但是在微软内部的一次演讲中SQL 架构师 Pat Helland 的一句话震惊了我。 “我们生活在爱因斯坦的宇宙中,没有同时性这种东西。”在构建分布式系统时(基本上我们构建的都是分布式系统),你无法隐藏系统的分布式特性。这是物理的。我一直感到远程过程调用在根本上错误的,这是一个原因,尤其是那些“透明的”远程过程调用,它们就是想隐藏分布式的交互本质。你需要拥抱系统的分布式特性,因为这些意义几乎总是需要通过系统设计和用户体验来完成。
拥抱分布式系统的本质则要遵循以下几个方面:
* 一开始就要思考设计对用户体验的影响,而不是试图在处理错误,取消请求和报告状态上打补丁。
* 使用异步技术来耦合组件。同步耦合是*不可能*的。如果某些行为看起来是同步的,是因为某些内部层尝试隐藏异步,这样做会遮蔽(但绝对不隐藏)系统运行时的基本行为特征。
* 认识到并且明确设计了交互状态机,这些状态表示长期的可靠的内部系统状态(而不是由深度调用堆栈中的变量值编码的临时,短暂和不可发现的状态)。
* 认识到失败是在所难免的。要保证能检测出分布式系统中的失败,唯一的办法就是直接看你的等待时间是否“太长”。这自然意味着[取消的等级最高][2]。系统的某一层(可能直接通向用户)需要决定等待时间是否过长,并取消操作。取消只是为了重建局部状态,回收局部的资源——没有办法在系统内广泛使用取消机制。有时用一种低成本,不可靠的方法广泛使用取消机制对优化性能可能有用。
* 认识到取消不是回滚,因为它只是回收本地资源和状态。如果回滚是必要的,它必须实现成一个端到端的功能。
* 承认永远不会真正知道分布式组件的状态。只要你发现一个状态,它可能就已经改变了。当你发送一个操作时,请求可能在传输过程中丢失,也可能被处理了但是返回的响应丢失了,或者请求需要一定的时间来处理,这样远程状态最终会在未来的某个任意的时间转换。这需要像幂等操作这样的方法,并且要能够稳健有效地重新发现远程状态,而不是期望可靠地跟踪分布式组件的状态。“[最终一致性][3]”的概念简洁地捕捉了这其中大多数想法。
我喜欢说你应该“陶醉在异步”。与其试图隐藏异步,不如接受异步,为异步而设计。当你看到像幂等性或不变性这样的技术时,你就认识到它们是拥抱宇宙本质的方法,而不仅仅是工具箱中的一个设计工具。
性能
### 性能
我确信 Don Knuth 会对人们怎样误解他的名言“过早的优化是一切罪恶的根源”而感到震惊。事实上性能及性能持续超过60年的指数增长或超过10年取决于您是否愿意将晶体管真空管和机电继电器的发展算入其中为所有行业内的惊人创新和影响经济的“软件吃世界”的变化打下了基础。
我确信 Don Knuth 会对人们怎样误解他的名言“过早的优化是一切罪恶的根源”而感到震惊。事实上,性能,及性能持续超过 60 年的指数增长(或超过 10 年,取决于您是否愿意将晶体管,真空管和机电继电器的发展算入其中),为所有行业内的惊人创新和影响经济的“软件吃掉全世界”的变化打下了基础。
要认识到这种指数变化的一个关键是,虽然系统的所有组件正在经历指数变化,但这些指数是不同的。硬盘容量的增长速度与内存容量的增长速度不同,与 CPU 的增长速度不同,与内存 CPU 之间的延迟的性能改善速度也不用。即使性能发展的趋势是由相同的基础技术驱动的,增长的指数也会有分歧。[延迟的改进从根本上改善了带宽][7]。指数变化在近距离或者短期内看起来是线性的,但随着时间的推移可能是压倒性的。系统不同组件的性能的增长不同,会出现压倒性的变化,并迫使对设计决策定期进行重新评估。
要认识到这种指数变化的一个关键是,虽然系统的所有组件正在经历指数变化,但这些指数是不同的。硬盘容量的增长速度与内存容量的增长速度不同,与 CPU 的增长速度不同,与内存 CPU 之间的延迟的性能改善速度也不用。即使性能发展的趋势是由相同的基础技术驱动的,增长的指数也会有分歧。[延迟的改进从根本上改善了带宽][7]。指数变化在近距离或者短期内看起来是线性的,但随着时间的推移可能是压倒性的。系统不同组件的性能的增长不同,会出现压倒性的变化,并迫使对设计决策定期进行重新评估。
这样做的结果是,几年后,一度有意义的设计决就不再有意义了。或者在某些情况下,二十年前有意义的方法又开始变成一个好的决。现代内存映射的特点看起来更像是早期分时的进程切换,而不像分页那样。 (这样做有时会让我这样的老人说“这就是我们在 1975 年时用的方法”——忽略了这种方法在 40 年都没有意义,但现在又重新成为好的方法,因为两个组件之间的关系——可能是闪存和 NAND 而不是磁盘和核心内存——已经变得像以前一样了)。
这样做的结果是,几年后,一度有意义的设计决就不再有意义了。或者在某些情况下,二十年前有意义的方法又开始变成一个好的决。现代内存映射的特点看起来更像是早期分时的进程切换,而不像分页那样。 (这样做有时会让我这样的老人说“这就是我们在 1975 年时用的方法”——忽略了这种方法在 40 年都没有意义,但现在又重新成为好的方法,因为两个组件之间的关系——可能是闪存和 NAND 而不是磁盘和核心内存——已经变得像以前一样了)。
当这些指数超越人自身的限制时,重要的转变就发生了。你能从 2 的 16 次方个字符(一个人可以在几个小时打这么多字)过渡到 2 的 3 次方个字符(远超出了一个人打字的范围)。你可以捕捉比人眼能感知的分辨率更高的数字图像。或者你可以将整个音乐专辑存在小巧的磁盘上,放在口袋里。或者你可以将数字化视频录制存储在硬盘上。再通过实时流式传输的能力,可以在一个地方集中存储一次,不需要在数千个本地硬盘上重复记录。
当这些指数超越人自身的限制时,重要的转变就发生了。你能从 2 的 16 次方个字符(一个人可以在几个小时打这么多字)过渡到 2 的 32 次方个字符(远超出了一个人打字的范围)。你可以捕捉比人眼能感知的分辨率更高的数字图像。或者你可以将整个音乐专辑存在小巧的磁盘上,放在口袋里。或者你可以将数字化视频录制存储在硬盘上。再通过实时流式传输的能力,可以在一个地方集中存储一次,不需要在数千个本地硬盘上重复记录。
但有的东西仍然是根本的限制条件,那就是空间的三维和光速。我们又回到了爱因斯坦的宇宙。内存的分级结构将始终存在——它是物理定律的基础。稳定的存储和 IO,内存,计算和通信也都将一直存在。这些模块的相对容量延迟和带宽将会改变但是系统始终要考虑这些元素如何组合在一起以及它们之间的平衡和折衷。Jim Gary 是这方面的大师。
但有的东西仍然是根本的限制条件,那就是空间的三维和光速。我们又回到了爱因斯坦的宇宙。内存的分级结构将始终存在——它是物理定律的基础。稳定的存储和 IO、内存、计算和通信也都将一直存在。这些模块的相对容量延迟和带宽将会改变但是系统始终要考虑这些元素如何组合在一起以及它们之间的平衡和折衷。Jim Gary 是这方面的大师。
空间和光速的根本限制造成的另一个后果是,性能分析主要是关于三件事:局部化 (locality),局部化,局部化。无论是将数据打包在磁盘上,管理处理器缓存的层次结构,还是将数据合并到通信数据包中,数据如何打包在一起,如何在一段时间内从局部获取数据,数据如何在组件之间传输数据是性能的基础。把重点放在减少管理数据的代码上,增加空间和时间上的局部性,是消除噪声的好办法。
空间和光速的根本限制造成的另一个后果是,性能分析主要是关于三件事:<ruby>局部化<rt>locality</rt></ruby><ruby>局部化<rt>locality</rt></ruby><ruby>局部化<rt>locality</rt></ruby>。无论是将数据打包在磁盘上,管理处理器缓存的层次结构,还是将数据合并到通信数据包中,数据如何打包在一起,如何在一段时间内从局部获取数据,数据如何在组件之间传输数据是性能的基础。把重点放在减少管理数据的代码上,增加空间和时间上的局部性,是消除噪声的好办法。
Jon Devaan 曾经说过:“设计数据,而不是设计代码”。这也通常意味着当查看系统结构时,我不太关心代码如何交互——我想看看数据如何交互和流动。如果有人试图通过描述代码结构来解释一个系统,而不理解数据流的速率和数量,他们就不了解这个系统。
内存的层级结构也意味着缓存将会一直存在——即使某些系统层正在试图隐藏它。缓存是根本的,但也是危险的。缓存试图利用代码的运行时行为,来改变系统中不同组件之间的交互模式。它们需要对运行时行为进行建模,即使模型填充缓存并使缓存失效,并测试缓存命中。如果模型由于行为改变而变差或变得不佳,缓存将无法按预期运行。一个简单的指导方针是,缓存必须被检测——由于应用程序行为的改变,事物不断变化的性质和组件之间性能的平衡,缓存的行为将随着时间的推移而退化。每一个老程序员都有缓存变糟的经历。
内存的层级结构也意味着缓存将会一直存在——即使某些系统层正在试图隐藏它。缓存是根本的,但也是危险的。缓存试图利用代码的运行时行为,来改变系统中不同组件之间的交互模式。它们需要对运行时行为进行建模,即使模型填充缓存并使缓存失效,并测试缓存命中。如果模型由于行为改变而变差或变得不佳,缓存将无法按预期运行。一个简单的指导方针是,缓存必须被检测——由于应用程序行为的改变,事物不断变化的性质和组件之间性能的平衡,缓存的行为将随着时间的推移而退化。每一个老程序员都有缓存变糟的经历。
我很幸运,我的早期职业生涯是在互联网的发源地之一 BBN 度过的。 我们很自然地将将异步组件之间的通信视为系统连接的自然方式。流量控制和队列理论是通信系统的基础,更是任何异步系统运行的方式。流量控制本质上是资源管理(管理通道的容量),但资源管理是更根本的关注点。流量控制本质上也应该由端到端的应用负责,所以用端到端的方式思考异步系统是自然的。[缓冲区膨胀][8]的故事在这种情况下值得研究,因为它展示了当对端到端行为的动态性以及技术“改进”(路由器中更大的缓冲区)缺乏理解时,在整个网络基础设施中导致的长久的问题。
我发现“光速”的概念在分析任何系统时都非常有用。光速分析并不是从当前的性能开始分析,而是问“这个设计理论上能达到的最佳性能是多少?”真正传递的信息是什么,以什么样的速度变化?组件之间的底层延迟和带宽是多少?光速分析迫使设计师深入思考他们的方法能否达到性能目标,或者否需要重新考虑设计的基本方法。它也迫使人们更深入地了解性能在哪里损耗,以及损耗是由固有的,还是由于一些不当行为产生的。从构建的角度来看,它迫使系统设计人员了解其构建的模块的真实性能特征,而不是关注其他功能特性。
我发现“<ruby>光速<rt>light speed</rt></ruby>”的概念在分析任何系统时都非常有用。光速分析并不是从当前的性能开始分析,而是问“这个设计理论上能达到的最佳性能是多少?”真正传递的信息是什么,以什么样的速度变化?组件之间的底层延迟和带宽是多少?光速分析迫使设计师深入思考他们的方法能否达到性能目标,或者否需要重新考虑设计的基本方法。它也迫使人们更深入地了解性能在哪里损耗,以及损耗是由固有的,还是由于一些不当行为产生的。从构建的角度来看,它迫使系统设计人员了解其构建的模块的真实性能特征,而不是关注其他功能特性。
我的职业生涯大多花费在构建图形应用程序上。用户坐在系统的一端,定义关键的常量和约束。人类的视觉和神经系统没有经历过指数性的变化。它们固有地受到限制,这意味着系统设计者可以利用(必须利用)这些限制,例如,通过虚拟化(限制底层数据模型需要映射到视图数据结构中的数量),或者通过将屏幕更新的速率限制到人类视觉系统的感知限制。
复杂性的本质
### 复杂性的本质
我的整个职业生涯都在与复杂性做斗争。为什么系统和应用变得复杂呢?为什么在一个应用领域内进行开发并没有随着时间变得简单,而基础设施却没有变得更复杂,反而变得更强大了?事实上,管理复杂性的一个关键方法就是“走开”然后重新开始。通常新的工具或语言迫使我们从头开始,这意味着开发人员将工具的优点与从新开始的优点结合起来。从新开始是重要的。这并不是说新工具,新平台,或新语言可能不好,但我保证它们不能解决复杂性增长的问题。控制复杂性的最简单的方法就是用更少的程序员,建立一个更小的系统。
当然很多情况下“走开”并不是一个选择——Office 建立在有巨大的价值的复杂的资源上。通过 OneNote Office 从 Word 的复杂性上“走开”从而在另一个维度上进行创新。Sway 是另一个例子, Office 决定从限制中跳出来,利用关键的环境变化,抓住机会从底层上采取全新的设计方案。我们有 WordExcelPowerPoint 这些应用,它们的数据结构非常有价值,我们并不能完全放弃这些数据结构,它们成为了开发中持续的显著的限制条件。
当然很多情况下“走开”并不是一个选择——Office 软件建立在有巨大的价值的复杂的资源上。通过 OneNote Office 从 Word 的复杂性上“走开”从而在另一个维度上进行创新。Sway 是另一个例子, Office 决定从限制中跳出来,利用关键的环境变化,抓住机会从底层上采取全新的设计方案。我们有 Word、Excel、PowerPoint 这些应用,它们的数据结构非常有价值,我们并不能完全放弃这些数据结构,它们成为了开发中持续的显著的限制条件。
我受到 Fred Brook 讨论软件开发中的意外和本质的文章[《没有银弹》][9]的影响,他希望用两个趋势来尽可能地推动程序员的生产力:一是在选择自己开发还是购买时,更多地关注购买——这预示了开源社区和云架构的改变;二是从单纯的构建方法转型到更“有机”或者“生态”的增量开发方法。现代的读者可以认为是向敏捷开发和持续开发的转型。但那篇文章可是写于 1986 年!
我受到 Fred Brook 讨论软件开发中的意外和本质的文章[《没有银弹》][9]的影响,他希望用两个趋势来尽可能地推动程序员的生产力:一是在选择自己开发还是购买时,更多地关注购买——这预示了开源社区和云架构的改变;二是从单纯的构建方法转型到更“有机”或者“生态”的增量开发方法。现代的读者可以认为是向敏捷开发和持续开发的转型。但那篇文章可是写于 1986 年!
我很欣赏 Stuart Kauffman 的在复杂性的基本性上的研究工作。Kauffman 从一个简单的布尔网络模型(“[NK 模型][10]”)开始建立起来,然后探索这个基本的数学结构在相互作用的分子,基因网络,生态系统,经济系统,计算机系统(以有限的方式)等系统中的应用,来理解紧急有序行为的数学基础及其与混沌行为的关系。在一个高度连接的系统中,你固有地有一个相互冲突的约束系统,使得它(在数学上)很难向前发展(这被看作是在崎岖景观上的优化问题)。控制这种复杂性的基本方法是将系统分成独立元素并限制元素之间的相互连接(实质上减少 NK 模型中的“N”和“K”。当然对那些使用复杂隐藏信息隐藏和数据抽象并且使用松散异步耦合来限制组件之间的交互的技术的系统设计者来说这是很自然的。
我们一直面临的一个挑战是,我们想到的许多拓展系统的方法,都跨越了所有的方面。实时共同编辑是 Office 应用程序最近的一个非常具体的(也是最复杂的)例子。
我们的数据模型的复杂性往往等同于“能力”。设计用户体验的固有挑战是我们需要将有限的一组手势,映射到底层数据模型状态空间的转换。增加状态空间的维度不可避免地在用户手势中产生模糊性。这是“[纯数学][11]”,这意味着确保系统保持“易于使用”的最基本的方式常常是约束底层的数据模型。
管理
### 管理
我从高中开始着手一些领导角色(学生会主席!),对承担更多的责任感到理所当然。同时,我一直为自己在每个管理阶段都坚持担任全职程序员而感到自豪。但 Office 的开发副总裁最终还是让我从事管理,离开了日常的编程工作。当我在去年离开那份工作时,我很享受重返编程——这是一个出奇地充满创造力的充实的活动(当修完“最后”的 bug 时,也许也会有一点令人沮丧)。
我从高中开始担任一些领导角色(学生会主席!),对承担更多的责任感到理所当然。同时,我一直为自己在每个管理阶段都坚持担任全职程序员而感到自豪。但 Office 软件的开发副总裁最终还是让我从事管理,离开了日常的编程工作。当我在去年离开那份工作时,我很享受重返编程——这是一个出奇地充满创造力的充实的活动(当修完“最后”的 bug 时,也许也会有一点令人沮丧)。
尽管在我加入微软前已经做了十多年的“主管”,但是到了 1996 年我加入微软才真正了解到管理。微软强调“工程领导是技术领导”。这与我的观点一致,帮助我接受并承担更大的管理责任。
@ -124,21 +118,19 @@ Jon Devaan 曾经说过:“设计数据,而不是设计代码”。这也通
我过去说我的工作是设计反馈回路。独立工程师,经理,行政人员,每一个项目的参与者都能通过分析记录的项目数据,推进项目,产出结果,了解自己在整个项目中扮演的角色。最终,透明化最终成为增强能力的一个很好的工具——管理者可以将更多的局部控制权给予那些最接近问题的人,因为他们对所取得的进展有信心。这样的话,合作自然就会出现。
Key to this is that the goal has actually been properly framed (including key resource constraints like ship schedule). Decision-making that needs to constantly flow up and down the management chain usually reflects poor framing of goals and constraints by management.
关键需要确定目标框架(包括关键资源的约束,如发布的时间表)。如果决策需要在管理链上下不断流动,那说明管理层对目标和约束的框架不好。
当我在 Beyond Software 工作时,我真正理解了一个项目拥有一个唯一领导的重要性。原来的项目经理离职了(后来从 FrontPage 雇佣了我)。我们四个主管在是否接任这个岗位上都有所犹豫,这不仅仅由于我们都不知道要在这家公司坚持多久。我们都技术高超,并且相处融洽,所以我们决定以同级的身份一起来领导这个项目。然而这槽糕透了。有一个显而易见的问题,我们没有相应的战略用来在原有的组织之间分配资源——这应当是管理者的首要职责之一!当你知道你是唯一的负责人时,你会有很深的责任感,但在这个例子中,这种责任感缺失了。我们没有真正的领导来负责统一目标和界定约束。
当我在 Beyond Software 工作时,我真正理解了一个项目拥有一个唯一领导的重要性。原来的项目经理离职了(后来从 FrontPage 团队雇佣了我)。我们四个主管在是否接任这个岗位上都有所犹豫,这不仅仅由于我们都不知道要在这家公司坚持多久。我们都技术高超,并且相处融洽,所以我们决定以同级的身份一起来领导这个项目。然而这槽糕透了。有一个显而易见的问题,我们没有相应的战略用来在原有的组织之间分配资源——这应当是管理者的首要职责之一!当你知道你是唯一的负责人时,你会有很深的责任感,但在这个例子中,这种责任感缺失了。我们没有真正的领导来负责统一目标和界定约束。
我有清晰地记得,我第一次充分认识到*倾听*对一个领导者的重要性。那时我刚刚担任了 WordOneNotePublisher 和 Text Services 团队的开发经理。关于我们如何组织文本服务团队,我们有一个很大的争议,我走到了每个关键参与者身边,听他们想说的话,然后整合起来,写下了我所听到的一切。当我向其中一位主要参与者展示我写下的东西时,他的反应是“哇,你真的听了我想说的话”!作为一名管理人员,我所经历的所有最大的问题(例如,跨平台和转型持续工程)涉及到仔细倾听所有的参与者。倾听是一个积极的过程,它包括:尝试以别人的角度去理解,然后写出我学到的东西,并对其进行测试,以验证我的理解。当一个关键的艰难决定需要发生的时候,在最终决定前,每个人都知道他们的想法都已经被听到并理解(不论他们是否同意最后的决定)。
我有清晰地记得,我第一次充分认识到*倾听*对一个领导者的重要性。那时我刚刚担任了 Word、OneNote、Publisher 和 Text Services 团队的开发经理。关于我们如何组织文本服务团队,我们有一个很大的争议,我走到了每个关键参与者身边,听他们想说的话,然后整合起来,写下了我所听到的一切。当我向其中一位主要参与者展示我写下的东西时,他的反应是“哇,你真的听了我想说的话”!作为一名管理人员,我所经历的所有最大的问题(例如,跨平台和转型持续工程)涉及到仔细倾听所有的参与者。倾听是一个积极的过程,它包括:尝试以别人的角度去理解,然后写出我学到的东西,并对其进行测试,以验证我的理解。当一个关键的艰难决定需要发生的时候,在最终决定前,每个人都知道他们的想法都已经被听到并理解(不论他们是否同意最后的决定)。
在 FrontPage 担任开发经理的工作,让我理解了在只有部分信息的情况下做决定的“操作困境”。你等待的时间越长,你就会有更多的信息做出决定。但是等待的时间越长,实际执行的灵活性就越低。在某个时候,你仅需要做出决定。
在 FrontPage 团队担任开发经理的工作,让我理解了在只有部分信息的情况下做决定的“操作困境”。你等待的时间越长,你就会有更多的信息做出决定。但是等待的时间越长,实际执行的灵活性就越低。在某个时候,你仅需要做出决定。
设计一个组织涉及类似的两难情形。您希望增加资源领域以便可以在更大的一组资源上应用一致的优先级划分框架。但资源领域越大越难获得作出决定所需要的所有信息。组织设计就是要平衡这两个因素。软件复杂化因为软件的特点可以在任意维度切入设计。Office 已经使用[共享团队][12]来解决这两个问题(优先次序和资源),让跨领域的团队能与需要产品的团队分享工作(增加资源)。
设计一个组织涉及类似的两难情形。您希望增加资源领域以便可以在更大的一组资源上应用一致的优先级划分框架。但资源领域越大越难获得作出决定所需要的所有信息。组织设计就是要平衡这两个因素。软件复杂化因为软件的特点可以在任意维度切入设计。Office 软件部门已经使用[共享团队][12]来解决这两个问题(优先次序和资源),让跨领域的团队能与需要产品的团队分享工作(增加资源)。
随着管理阶梯的提升,你会懂一个小秘密:你和你的新同事不会因为你现在承担更多的责任,就突然变得更聪明。这强调了整个组织比顶层领导者更聪明。赋予每个级别在一致框架下拥有自己的决定是实现这一目标的关键方法。听取并使自己对组织负责,阐明和解释决策背后的原因是另一个关键策略。令人惊讶的是,害怕做出一个愚蠢的决定可能是一个有用的激励因素,以确保你清楚地阐明你的推理,并确保你听取所有的信息。
结语
### 结语
我离开大学寻找第一份工作时,面试官在最后一轮面试时问我对做“系统”和做“应用”哪一个更感兴趣。我当时并没有真正理解这个问题。在软件技术栈的每一个层面都会有趣的难题,我很高兴深入研究这些问题。保持学习。
@ -146,9 +138,9 @@ Key to this is that the goal has actually been properly framed (including key re
via: https://hackernoon.com/education-of-a-programmer-aaecf2d35312
作者:[ Terry Crowley][a]
作者:[Terry Crowley][a]
译者:[explosic4](https://github.com/explosic4)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,46 +1,54 @@
HeRMs - 一个命令行食谱管理器
HeRM's 一个命令行食谱管理器
======
![配图](https://www.ostechnix.com/wp-content/uploads/2017/12/herms-720x340.jpg)
烹饪让爱变得可见,不是吗?确实!烹饪也许是你的热情或爱好或职业,我相信你会维护一份烹饪日记。保持写烹饪日记是改善烹饪习惯的一种方法。有很多方法可以记录食谱。你可以维护一份小日记/笔记或将配方的笔记存储在智能手机中,或将它们保存在计算机中文档中。这有很多选择。今天,我介绍 **HeRM 's**,一个基于 Haskell 的命令行食谱管理器,能为你的美食食谱做笔记。使用 Herm's你可以添加、查看、编辑和删除食物配方甚至可以制作购物清单。这些全部来自你的终端它是免费的并使用 Haskell 语言编写的开源程序。源代码在 GitHub 中免费提供,因此你可以 fork 它,添加更多功能或改进它。
烹饪让爱变得可见,不是吗?确实!烹饪也许是你的热情或爱好或职业,我相信你会维护一份烹饪日记。保持写烹饪日记是改善烹饪习惯的一种方法。有很多方法可以记录食谱。你可以维护一份小日记/笔记或将配方的笔记存储在智能手机中,或将它们保存在计算机中文档中。这有很多选择。今天,我介绍 **HeRM's**这是一个基于 Haskell 的命令行食谱管理器,能为你的美食食谱做笔记。使用 Herm's你可以添加、查看、编辑和删除食物配方甚至可以制作购物清单。这些全部来自你的终端它是免费的是使用 Haskell 语言编写的开源程序。源代码在 GitHub 中免费提供,因此你可以复刻它,添加更多功能或改进它。
### HeRM's - 一个命令食谱管理器
#### **安装 HeRM 's**
#### 安装 HeRM's
由于它是使用 Haskell 编写的,因此我们需要首先安装 Cabal。 Cabal 是一个用于下载和编译用 Haskell 语言编写的软件的命令行程序。Cabal 存在于大多数 Linux 发行版的核心软件库中,因此你可以使用发行版的默认软件包管理器来安装它。
例如,你可以使用以下命令在 Arch Linux 及其变体(如 Antergos、Manjaro Linux中安装 cabal
```
sudo pacman -S cabal-install
```
在 Debian、Ubuntu 上:
```
sudo apt-get install cabal-install
```
安装 Cabal 后,确保你已经添加了 PATH。为此请编辑你的 **~/.bashrc**
安装 Cabal 后,确保你已经添加了 `PATH`。为此,请编辑你的 `~/.bashrc`
```
vi ~/.bashrc
```
添加下面这行:
```
PATH=$PATH:~/.cabal/bin
```
**:wq** 保存并退出文件。然后,运行以下命令更新所做的更改。
`:wq` 保存并退出文件。然后,运行以下命令更新所做的更改。
```
source ~/.bashrc
```
安装 cabal 后,运行以下命令安装 herms
安装 cabal 后,运行以下命令安装 `herms`
```
cabal install herms
```
喝一杯咖啡!这将需要一段时间。几分钟后,你会看到一个输出,如下所示。
```
[...]
Linking dist/build/herms/herms ...
@ -50,71 +58,77 @@ Installed herms-1.8.1.2
恭喜! Herms 已经安装完成。
#### **添加食谱**
#### 添加食谱
让我们添加一个食谱,例如 **Dosa**。对于那些想知道的Dosa 是一种受欢迎的南印度食物,配以 **sambar** 和**酸辣酱**。这是一种健康的,可以说是最美味的食物。它不含添加的糖或饱和脂肪。制作一个也很容易。有几种不同的 Dosas在我们家中最常见的是 Plain Dosa。
让我们添加一个食谱,例如 Dosa。对于那些想知道的Dosa 是一种受欢迎的南印度食物,配以 sambarLCTT 译注:扁豆和酸豆炖菜,像咖喱汤) 和**酸辣酱**。这是一种健康的,可以说是最美味的食物。它不含添加的糖或饱和脂肪。制作一个也很容易。有几种不同的 Dosas在我们家中最常见的是 Plain Dosa。
要添加食谱,请输入:
```
herms add
```
你会看到一个如下所示的屏幕。开始输入食谱的详细信息。
[![][1]][2]
![][2]
要变换字段,请使用以下键盘快捷键:
* **Tab / Shift+Tab** - 下一个/前一个字段
* **Ctrl + <箭头键>** - 导航字段
* **[Meta 或者 Alt] + <h-j-k-l>** - 导航字段
* **Esc** - 保存或取消。
* `Tab` / `Shift+Tab` - 下一个/前一个字段
* `Ctrl + <箭头键>` - 导航字段
* `[Meta 或者 Alt] + <h-j-k-l>` - 导航字段
* `Esc` - 保存或取消。
添加完配方的详细信息后,按下 ESC 键并点击 Y 保存。同样,你可以根据需要添加尽可能多的食谱。
添加完配方的详细信息后,按下 `ESC` 键并点击 `Y` 保存。同样,你可以根据需要添加尽可能多的食谱。
要列出添加的食谱,输入:
```
herms list
```
[![][1]][3]
![][3]
要查看上面列出的任何食谱的详细信息,请使用下面的相应编号。
```
herms view 1
```
[![][1]][4]
![][4]
要编辑任何食谱,使用:
```
herms edit 1
```
完成更改后,按下 ESC 键。系统会询问你是否要保存。你只需选择适当的选项。
完成更改后,按下 `ESC` 键。系统会询问你是否要保存。你只需选择适当的选项。
[![][1]][5]
![][5]
要删除食谱,命令是:
```
herms remove 1
```
要为指定食谱生成购物清单,运行:
```
herms shopping 1
```
[![][1]][6]
![][6]
要获得帮助,运行:
```
herms -h
```
当你下次听到你的同事、朋友或其他地方谈到好的食谱时,只需打开 Herms并快速记下并将它们分享给你的配偶。她会很高兴
当你下次听到你的同事、朋友或其他地方谈到好的食谱时,只需打开 Herm's并快速记下并将它们分享给你的配偶。她会很高兴
今天就是这些。还有更好的东西。敬请关注!
@ -126,16 +140,16 @@ herms -h
via: https://www.ostechnix.com/herms-commandline-food-recipes-manager/
作者:[][a]
作者:[SK][a]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.ostechnix.com
[1]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[2]:http://www.ostechnix.com/wp-content/uploads/2017/12/Make-Dosa-1.png ()
[3]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-1-1.png ()
[4]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-2.png ()
[5]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-3.png ()
[6]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-4.png ()
[2]:http://www.ostechnix.com/wp-content/uploads/2017/12/Make-Dosa-1.png
[3]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-1-1.png
[4]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-2.png
[5]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-3.png
[6]:http://www.ostechnix.com/wp-content/uploads/2017/12/herms-4.png

View File

@ -0,0 +1,134 @@
开始 Vagrant 之旅
=====
> 用管理虚拟机和容器的工具 Vagrant 清理你的开发环境和依赖。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/containers_scale_performance.jpg?itok=R7jyMeQf)
如果你和我一样,你可能在某一个地方有一个“沙盒”,你可以在那里进行你正在做的任何项目。随着时间的推移,沙盒会变得杂乱无章,充斥着各种想法、工具链元素、你不使用的代码模块,以及其他你不需要的东西。当你完成某件事情时,这会使你的部署变得复杂,因为你可能不确定项目的实际依赖关系 —— 随着时间推移你在沙盒中已经有了一些工具,但是你忘了必须安装它。你需要一个干净的环境,将所有的依赖关系放在一个地方,以便以后更方便。
或者你可能工作在 DevOps 中,你所服务的开发人员用模糊的依赖关系来编写代码,这使得测试变得更加困难。你需要一种方法来获得一个干净的盒子,将代码放入其中,并通过它运行代码,而且你希望这些环境是一次性的和可重复的。
那么选择 [Vagrant][1] 吧。由 HashiCorp 在 [MIT 许可证][2]下创建Vagrant 可充当 VirtualBox、Microsoft Hyper-V 或 Docker 容器的包装器和前端,并且可以通过[许多其他供应商][3]的插件进行扩展。你可以配置 Vagrant 以提供可重复的、干净的环境,并且已安装需要的基础架构。配置脚本是可移植的,因此,如果你的仓库和 Vagrant 配置脚本位于基于云存储上,那么你只需要很少的限制就可以启动并在多台机器机器上工作。让我们来看一看。
### 安装
对于本次安装,我的环境是 Linux Mint 桌面,版本是 18.3 Cinnamon 64 位,在其他大多数 Debian 派生系统上安装非常类似。在大多数发行版中,对于基于 RPM 的系统也有类似的安装程序。Vagrant 的[安装页面][4]为 Debian、 Windows、 CentOS、 MacOS 和 Arch Linux 都提供下载,但是我在我的软件包管理器中找到了它,所以我在那进行了安装。
最简单的安装使用了 VirtualBox 作为虚拟化提供者,所以我需要安装它:
```
sudo apt-get install virtualbox vagrant
```
安装程序将会获取依赖项 —— 主要是 Ruby 的一些东西,安装它们。
### 建立一个项目
在设置你的项目之前,你需要了解一些你想要运行它的环境。你可以在 [Vagrant Boxes 仓库][5]中找到为许多虚拟化供应商提供的大量预配置的<ruby>系统<rt>box</rt></ruby>。许多会预先配置一些你可能需要的核心基础设置,比如 PHP、 MySQL 和 Apache但是对于本次测试我将安装一个 Debian 8 64 位 “Jessie” 裸机沙盒并手动安装一些东西,这样你就可以看到具体过程了。
```
mkdir ~/myproject
cd ~/myproject
vagrant init debian/contrib-jessie64
vagrant up
```
最后一条命令将根据需要从仓库中获取或更新 VirtualBox 镜像,然后运行启动器,你的系统上会出现一个运行的系统!下次启动这个项目时,除非镜像已经在仓库中更新,否则不会花费太长时间。
要访问该沙盒,只需要输入 `vagrant ssh`,你将进入虚拟机的全功能 SSH 会话中,你将会是 `vagrant` 用户,但也是 `sudo` 组的成员,所以你可以切换到 root并在这里做你想做的任何事情。
你会在沙盒中看到一个名为 `/vagrant` 目录,对这个目录小心点,因为它与你主机上的 `~/myproject` 文件夹保持同步。在虚拟机 `/vagrant` 下建立一个文件它会立即复制到主机上,反之亦然。注意,有些沙盒并没有安装 VirtualBox 的附加功能,所以拷贝只能在启动时才起作用。有一些用于手动同步的命令行工具,这可能是测试环境中非常有用的特性。我倾向于坚持使用那些有附加功能的沙盒,所以这个目录可以正常工作,不必考虑它。
这个方案的好处很快显现出来了: 如果你在主机上有一个代码编辑工具链,并处于某种原因不希望它出现在虚拟机上,那么这不是问题 —— 在主机上进行编辑,虚拟机会立刻更改。快速更改虚拟机,它也将其同步到主机上的“官方”副本
让我们关闭这个系统,这样我们就可以在这个系统里提供一些我们需要的东西:
```
vagrant halt
```
### 在虚拟机上安装额外的软件
对于这个例子,我将使用 [Apache][6]、 [PostgreSQL][7] 和 Perl 的 [Dancer][8] web 框架进行项目开发。我将修改Vagrant 配置脚本,以便我需要的东西已经安装。 为了使之稍后更容易保持更新,我将在项目根目录下创建一个脚本`~/myproject/Vagrantfile`
```
$provision_script = <<SCRIPT
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install \
apache2 \
postgresql-client-9.4 \
postgresql-9.4 \
libdbd-pg-perl \
libapache2-mod-fastcgi \
libdata-validate-email-perl \
libexception-class-perl \
libexception-class-trycatch-perl \
libtemplate-perl \
libtemplate-plugin-json-escape-perl \
libdbix-class-perl \
libyaml-tiny-perl \
libcrypt-saltedhash-perl \
libdancer2-perl \
libtemplate-plugin-gravatar-perl \
libtext-csv-perl \
libstring-tokenizer-perl \
cpanminus
cpanm -f -n \
Dancer2::Session::Cookie \
Dancer2::Plugin::DBIC \
Dancer2::Plugin::Auth::Extensible::Provider::DBIC \
Dancer2::Plugin::Locale \
Dancer2::Plugin::Growler
sudo a2enmod rewrite fastcgi
sudo apache2ctl restart
SCRIPT
```
在 Vagrantfile 结尾附近,你会发现一行 `config.vm.provision` 变量,正如你在示例中看到的那样,你可以在此处以内联方式进行操作,只需通过取消注释以下行:
```
# config.vm.provision "shell", inline: <<-SHELL
# sudo apt-get update
# sudo apt-get install -y apache2
# SHELL
```
相反,将那四行替换为使用你在文件顶部定义为变量的配置脚本:
```
config.vm.provision "shell", inline: $provision_script
```
你可能还希望将转发的端口设置为从主机访问虚拟机上的 Apache。寻找包含 `forwarded_port` 的行并取消注释它。如果你愿意,也可以将端口从 8080 更改为其他内容。我通常使用端口 5000并在我的浏览器浏览 http://localhost:5000 就可以访问我虚拟机上的 Apache 服务器。
这里有一个设置提示:如果你的仓库位于云存储上,为了在多台机器上使用 Vagrant你可能希望将不同机器上的 `VAGRANT_HOME` 环境变量设置为不同的东西。以 VirtualBox 的工作方式,你需要分别为这些系统存储状态信息,确保你的版本控制系统忽略了用于此的目录 —— 我将 `.vagrant.d*` 添加到仓库的 `.gitignore` 文件中。不过,我确实让 Vagrantfile 成为仓库的一部分!
### 好了!
我输入 `vagrant up`,我准备开始写代码了。一旦你做了一两次,你可能会想到你可以循环利用很多的 Vagrantfile 模板文件(就像我刚刚那样),这就是 Vagrant 的优势之一。你可以更快地完成实际的编码工作,并将很少的时间花在基础设施上!
你可以使用 Vagrant 做更多事情。配置工具存在于许多工具链中,因此,无论你需要复制什么环境,它都是快速而简单的。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/4/getting-started-vagrant
作者:[Ruth Holloway][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/druthb
[1]:https://vagrantup.com
[2]:https://opensource.org/licenses/MIT
[3]:https://github.com/hashicorp/vagrant/wiki/Available-Vagrant-Plugins#providers
[4]:https://www.vagrantup.com/downloads.html
[5]:https://app.vagrantup.com/boxes/search
[6]:https://httpd.apache.org/
[7]:https://postgresql.org
[8]:https://perldancer.org

View File

@ -1,270 +0,0 @@
Translating by MjSeven
How to Install and Optimize Apache on Ubuntu
======
This is the beginning of our LAMP tutorial series: how to install the Apache web server on Ubuntu.
These instructions should work on any Ubuntu-based distro, including Ubuntu 14.04, Ubuntu 16.04, [Ubuntu 18.04][1], and even non-LTS Ubuntu releases like 17.10. They were tested and written for Ubuntu 16.04.
Apache (aka httpd) is the most popular and most widely used web server, so this should be useful for everyone.
### Before we begin installing Apache
Some requirements and notes before we begin:
* Apache may already be installed on your server, so check if it is first. You can do so with the "apachectl -V" command that outputs the Apache version you're using and some other information.
* You'll need an Ubuntu server. You can buy one from [Vultr][2], they're one of the [best and cheapest cloud hosting providers][3]. Their servers start from $2.5 per month.
* You'll need the root user or a user with sudo access. All commands below are executed by the root user so we didn't have to append 'sudo' to each command.
* You'll need [SSH enabled][4] if you use Ubuntu or an SSH client like [MobaXterm][5] if you use Windows.
That's most of it. Let's move onto the installation.
### Install Apache on Ubuntu
The first thing you always need to do is update Ubuntu before you do anything else. You can do so by running:
```
apt-get update && apt-get upgrade
```
Next, to install Apache, run the following command:
```
apt-get install apache2
```
If you want to, you can also install the Apache documentation and some Apache utilities. You'll need the Apache utilities for some of the modules we'll install later.
```
apt-get install apache2-doc apache2-utils
```
**And that 's it. You've successfully installed Apache.**
You'll still need to configure it.
### Configure and Optimize Apache on Ubuntu
There are various configs you can do on Apache, but the main and most common ones are explained below.
#### Check if Apache is running
By default, Apache is configured to start automatically on boot, so you don't have to enable it. You can check if it's running and other relevant information with the following command:
```
systemctl status apache2
```
[![check if apache is running][6]][6]
And you can check what version you're using with
```
apachectl -V
```
A simpler way of checking this is by visiting your server's IP address. If you get the default Apache page, then everything's working fine.
#### Update your firewall
If you use a firewall (which you should), you'll probably need to update your firewall rules and allow access to the default ports. The most common firewall used on Ubuntu is UFW, so the instructions below are for UFW.
To allow traffic through both the 80 (http) and 443 (https) ports, run the following command:
```
ufw allow 'Apache Full'
```
#### Install common Apache modules
Some modules are frequently recommended and you should install them. We'll include instructions for the most common ones:
##### Speed up your website with the PageSpeed module
The PageSpeed module will optimize and speed up your Apache server automatically.
First, go to the [PageSpeed download page][7] and choose the file you need. We're using a 64-bit Ubuntu server and we'll install the latest stable version. Download it using wget:
```
wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.deb
```
Then, install it with the following commands:
```
dpkg -i mod-pagespeed-stable_current_amd64.deb
apt-get -f install
```
Restart Apache for the changes to take effect:
```
systemctl restart apache2
```
##### Enable rewrites/redirects using the mod_rewrite module
This module is used for rewrites (redirects), as the name suggests. You'll need it if you use WordPress or any other CMS for that matter. To install it, just run:
```
a2enmod rewrite
```
And restart Apache again. You may need some extra configurations depending on what CMS you're using, if any. Google it for specific instructions for your setup.
##### Secure your Apache with the ModSecurity module
ModSecurity is a module used for security, again, as the name suggests. It basically acts as a firewall, and it monitors your traffic. To install it, run the following command:
```
apt-get install libapache2-modsecurity
```
And restart Apache again:
```
systemctl restart apache2
```
ModSecurity comes with a default setup that's enough by itself, but if you want to extend it, you can use the [OWASP rule set][8].
##### Block DDoS attacks using the mod_evasive module
You can use the mod_evasive module to block and prevent DDoS attacks on your server, though it's debatable how useful it is in preventing attacks. To install it, use the following command:
```
apt-get install libapache2-mod-evasive
```
By default, mod_evasive is disabled, to enable it, edit the following file:
```
nano /etc/apache2/mods-enabled/evasive.conf
```
And uncomment all the lines (remove #) and configure it per your requirements. You can leave everything as-is if you don't know what to edit.
[![mod_evasive][9]][9]
And create a log file:
```
mkdir /var/log/mod_evasive
chown -R www-data:www-data /var/log/mod_evasive
```
That's it. Now restart Apache for the changes to take effect:
```
systemctl restart apache2
```
There are [additional modules][10] you can install and configure, but it's all up to you and the software you're using. They're usually not required. Even the 4 modules we included are not required. If a module is required for a specific application, then they'll probably note that.
#### Optimize Apache with the Apache2Buddy script
Apache2Buddy is a script that will automatically fine-tune your Apache configuration. The only thing you need to do is run the following command and the script does the rest automatically:
```
curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl
```
You may need to install curl if you don't have it already installed. Use the following command to install curl:
```
apt-get install curl
```
#### Additional configurations
There's some extra stuff you can do with Apache, but we'll leave them for another tutorial. Stuff like enabling http/2 support, turning off (or on) KeepAlive, tuning your Apache even more. You don't have to do any of this, but you can find tutorials online and do it if you can't wait for our tutorials.
### Create your first website with Apache
Now that we're done with all the tuning, let's move onto creating an actual website. Follow our instructions to create a simple HTML page and a virtual host that's going to run on Apache.
The first thing you need to do is create a new directory for your website. Run the following command to do so:
```
mkdir -p /var/www/example.com/public_html
```
Of course, replace example.com with your desired domain. You can get a cheap domain name from [Namecheap][11].
Don't forget to replace example.com in all of the commands below.
Next, create a simple, static web page. Create the HTML file:
```
nano /var/www/example.com/public_html/index.html
```
And paste this:
```
<html>
     <head>
       <title>Simple Page</title>
     </head>
     <body>
       <p>If you're seeing this in your browser then everything works.</p>
     </body>
</html>
```
Save and close the file.
Configure the permissions of the directory:
```
chown -R www-data:www-data /var/www/example.com
chmod -R og-r /var/www/example.com
```
Create a new virtual host for your site:
```
nano /etc/apache2/sites-available/example.com.conf
```
And paste the following:
```
<VirtualHost *:80>
     ServerAdmin admin@example.com
     ServerName example.com
     ServerAlias www.example.com
   
     DocumentRoot /var/www/example.com/public_html
    
     ErrorLog ${APACHE_LOG_DIR}/error.log
     CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```
This is a basic virtual host. You may need a more advanced .conf file depending on your setup.
Save and close the file after updating everything accordingly.
Now, enable the virtual host with the following command:
```
a2ensite example.com.conf
```
And finally, restart Apache for the changes to take effect:
```
systemctl restart apache2
```
That's it. You're done. Now you can visit example.com and view your page.
--------------------------------------------------------------------------------
via: https://thishosting.rocks/how-to-install-optimize-apache-ubuntu/
作者:[ThisHosting][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://thishosting.rocks
[1]:https://thishosting.rocks/ubuntu-18-04-new-features-release-date/
[2]:https://thishosting.rocks/go/vultr/
[3]:https://thishosting.rocks/cheap-cloud-hosting-providers-comparison/
[4]:https://thishosting.rocks/how-to-enable-ssh-on-ubuntu/
[5]:https://mobaxterm.mobatek.net/
[6]:https://thishosting.rocks/wp-content/uploads/2018/01/apache-running.jpg
[7]:https://www.modpagespeed.com/doc/download
[8]:https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
[9]:https://thishosting.rocks/wp-content/uploads/2018/01/mod_evasive.jpg
[10]:https://httpd.apache.org/docs/2.4/mod/
[11]:https://thishosting.rocks/neamcheap-review-cheap-domains-cool-names
[12]:https://thishosting.rocks/wp-content/plugins/patron-button-and-widgets-by-codebard/images/become_a_patron_button.png
[13]:https://www.patreon.com/thishostingrocks

View File

@ -1,3 +1,5 @@
translated by hopefully2333
Using machine learning to color cartoons
======

View File

@ -1,3 +1,4 @@
KevinSJ Translating
A Beginners Guide To Cron Jobs
======

View File

@ -1,3 +1,5 @@
translating---geeekpi
Analyzing Ansible runs using ARA
======

View File

@ -1,86 +0,0 @@
translating---geekpi
3 useful things you can do with the IP tool in Linux
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/find-file-linux-code_magnifying_glass_zero.png?itok=E2HoPDg0)
It has been more than a decade since the `ifconfig` command has been deprecated on Linux in favor of the `iproute2` project, which contains the magical tool `ip`. Many online tutorial resources still refer to old command-line tools like `ifconfig`, `route`, and `netstat`. The goal of this tutorial is to share some of the simple networking-related things you can do easily using the `ip` tool instead.
### Find your IP address
```
[dneary@host]$ ip addr show
[snip]
44: wlp4s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 5c:e0:c5:c7:f0:f1 brd ff:ff:ff:ff:ff:ff
        inet 10.16.196.113/23 brd 10.16.197.255 scope global dynamic wlp4s0
        valid_lft 74830sec preferred_lft 74830sec
        inet6 fe80::5ee0:c5ff:fec7:f0f1/64 scope link
        valid_lft forever preferred_lft forever
```
`ip addr show` will show you a lot of information about all of your network link devices. In this case, my wireless Ethernet card (wlp4s0) is the IPv4 address (the `inet` field) `10.16.196.113/23`. The `/23` means that there are 23 bits of the 32 bits in the IP address, which will be shared by all of the IP addresses in this subnet. IP addresses in the subnet will range from `10.16.196.0 to 10.16.197.254`. The broadcast address for the subnet (the `brd` field after the IP address) `10.16.197.255` is reserved for broadcast traffic to all hosts on the subnet.
We can show only the information about a single device using `ip addr show dev wlp4s0`, for example.
### Display your routing table
```
[dneary@host]$ ip route list
default via 10.16.197.254 dev wlp4s0 proto static metric 600
10.16.196.0/23 dev wlp4s0 proto kernel scope link src 10.16.196.113 metric 601
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
```
The routing table is the local host's way of helping network traffic figure out where to go. It contains a set of signposts, sending traffic to a specific interface, and a specific next waypoint on its journey.
If you run any virtual machines or containers, these will get their own IP addresses and subnets, which can make these routing tables quite complicated, but in a single host, there are typically two instructions. For local traffic, send it out onto the local Ethernet, and the network switches will figure out (using a protocol called ARP) which host owns the destination IP address, and thus where the traffic should be sent. For traffic to the internet, send it to the local gateway node, which will have a better idea how to get to the destination.
In the situation above, the first line represents the external gateway for external traffic, the second line is for local traffic, and the third is reserved for a virtual bridge for VMs running on the host, but this link is not currently active.
### Monitor your network configuration
```
[dneary@host]$ ip monitor all
[dneary@host]$ ip -s link list wlp4s0
```
The `ip monitor` command can be used to monitor changes in routing tables, network addressing on network interfaces, or changes in ARP tables on the local host. This command can be particularly useful in debugging network issues related to containers and networking, when two VMs should be able to communicate with each other but cannot.
`all`, `ip monitor` will report all changes, prefixed with one of `[LINK]` (network interface changes), `[ROUTE]` (changes to a routing table), `[ADDR]` (IP address changes), or `[NEIGH]` (nothing to do with horses—changes related to ARP addresses of neighbors).
When used withwill report all changes, prefixed with one of(network interface changes),(changes to a routing table),(IP address changes), or(nothing to do with horses—changes related to ARP addresses of neighbors).
You can also monitor changes on specific objects (for example, a specific routing table or an IP address).
Another useful option that works with many commands is `ip -s`, which gives some statistics. Adding a second `-s` option adds even more statistics. `ip -s link list wlp4s0` above will give lots of information about packets received and transmitted, with the number of packets dropped, errors detected, and so on.
### Handy tip: Shorten your commands
In general, for the `ip` tool, you need to include only enough letters to uniquely identify what you want to do. Instead of `ip monitor`, you can use `ip mon`. Instead of `ip addr list`, you can use `ip a l`, and you can use `ip r` in place of `ip route`. `Ip link list` can be shorted to `ip l ls`. To read about the many options you can use to change the behavior of a command, visit the [ip manpage][1].
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/useful-things-you-can-do-with-IP-tool-Linux
作者:[Dave Neary][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/dneary
[1]:https://www.systutorials.com/docs/linux/man/8-ip-route/

View File

@ -0,0 +1,262 @@
如何在 Ubuntu 上安装和优化 Apache
=====
这是我们的 LAMP 系列教程的开始:如何在 Ubuntu 上安装 Apache web 服务器。
这些说明适用于任何基于 Ubuntu 的发行版,包括 Ubuntu 14.04, Ubuntu 16.04, [Ubuntu 18.04][1],甚至非 LTS 的 Ubuntu 发行版,例如 Ubuntu 17.10。这些说明经过测试并为 Ubuntu 16.04 编写。
Apache (又名 httpd) 是最受欢迎和使用最广泛的 web 服务器,所以这应该对每个人都有用。
### 开始安装 Apache 之前
在我们开始之前,这里有一些要求和说明:
* Apache 可能已经在你的服务器上安装了,所以开始之前首先检查一下。你可以使用 "apachectl -V" 命令来显示你正在使用的 Apache 的版本和一些其他信息。
* 你需要一个 Ubuntu 服务器。你可以从 [Vultr][2] 购买一个,它们是[最便宜的云托管服务商][3]之一。它们的服务器价格每月 2.5 美元起。
* 你需要有 root 用户或具有 sudo 访问权限的用户。下面的所有命令都由 root 用户自行,所以我们不必为每个命令都添加 'sudo'。
* 如果你使用 Ubuntu则需要[启用 SSH][4],如果你使用 Windows则应该使用类似 [MobaXterm][5] 的 SSH 客户端。
这就是全部要求和注释了,让我们进入安装过程。
### 在 Ubuntu 上安装 Apache
你需要做的第一件事就是更新 Ubuntu这是在你做任何事情之前都应该做的。你可以运行
```
apt-get update && apt-get upgrade
```
接下来,安装 Apache运行以下命令
```
apt-get install apache2
```
如果你愿意,你也可以安装 Apache 文档和一些 Apache 实用程序。对于我们稍后将要安装的一些模块,你将需要一些 Apache 实用程序。
```
apt-get install apache2-doc apache2-utils
```
**就是这样。你已经成功安装了 Apache **
你仍然需要配置它。
### 在 Ubuntu 上配置和优化 Apache
你可以在 Apache 上做各种各样的配置,但是主要的和最常见的配置将在下面做出解释。
#### 检查 Apache 是否正在运行
默认情况下Apache 设置为在机器启动时自动启动,因此你不必手动启用它。你可以使用以下命令检查它是否正在运行以及其他相关信息:
```
systemctl status apache2
```
[![check if apache is running][6]][6]
并且你可以检查你正在使用的版本:
```
apachectl -V
```
一种更简单的检查方法时访问服务器的 IP 地址,如果你得到默认的 Apache 页面,那么一切都正常。
#### 更新你的防火墙
如果你使用防火墙你应该使用它则可能需要更新防火墙规则并允许访问默认端口。Ubuntu 上最常用的防火墙是 UFW因此以下说明使用于 UFW。
要允许通过 80http和 443https端口的流量运行以下命令
```
ufw allow 'Apache Full'
```
#### 安装常见的 Apache 模块
一些模块经常被建议使用,所以你应该安装它们。我们将包含最常见模块的说明:
##### 使用 PageSpeed 加速你的网站
PageSpeed 模块将自动优化并加速你的 Apache 服务器。
首先,进入 [PageSpeed 下载页][7]并选择你需要的的文件。我们使用的是 64 位 Ubuntu 服务器,所以我们安装最新的稳定版本。使用 wget 下载它:
```
wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.deb
```
然后,使用以下命令安装它:
```
dpkg -i mod-pagespeed-stable_current_amd64.deb
apt-get -f install
```
重启 Apache 以使更改生效:
```
systemctl restart apache2
```
##### 使用 mod_rewrite 模块启动重写/重定向
顾名思义,该模块用于重写(重定向)。如果你使用 WordPress 或任何其他 CMS 来处理此问题,你就需要它。要安装它,只需运行:
```
a2enmod rewrite
```
然后再次重新启动 Apache。你可能需要一些额外的配置具体取决于你使用的 CMS如果有的话。为你的设置 Google 一下得到它的具体说明。
##### 使用 ModSecurity 模块保护你的 Apache
顾名思义ModSecurity 是一个用于安全性的模块,它基本上起着防火墙的作用,它可以监控你的流量。要安装它,运行以下命令:
```
apt-get install libapache2-modsecurity
```
再次重启 Apache
```
systemctl restart apache2
```
ModSecurity 自带了一个默认的设置,但如果你想扩展它,你可以使用 [OWASP 规则集][8]。
##### 使用 mod_evasive 模块抵御 DDoS 攻击
尽管 mod_evasive 在防止攻击方面有多大用处值得商榷,但是你可以使用它来阻止和防止服务器上的 DDoS 攻击。要安装它,使用以下命令:
```
apt-get install libapache2-mod-evasive
```
默认情况下mod_evasive 是禁用的,要启用它,编辑以下文件:
```
nano /etc/apache2/mods-enabled/evasive.conf
```
取消注释所有行(即删除 #),根据你的要求进行配置。如果你不知道要编辑什么,你可以保持原样。
[![mod_evasive][9]][9]
创建一个日志文件:
```
mkdir /var/log/mod_evasive
chown -R www-data:www-data /var/log/mod_evasive
```
就是这样。现在重启 Apache 以使更改生效。
```
systemctl restart apache2
```
你可以安装和配置[附加模块][10]但完全取决于你和你使用的软件。它们通常不是必需的。甚至我们上面包含的4个模块也不是必需的。如果特定应用需要模块那么它们可能会注意到这一点。
#### 用 Apache2Buddy 脚本优化 Apache
Apache2Buddy 是一个可以自动调整 Apache 配置的脚本。你唯一需要做的就是运行下面的命令,脚本会自动完成剩下的工作:
```
curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl
```
如果你没有安装 curl那么你可能需要安装它。使用以下命令来安装 curl
```
apt-get install curl
```
#### 额外配置
用 Apache 还可以做一些额外的东西,但我们会留下它们作为另一个教程。像启用 http/2 支持,关闭(或打开) KeepAlive调整你的 Apache 甚至更多。这些东西你现在不需要做,但是如果你在网上找到了教程,并且如果你等不及我们的教程,那就去做吧。
### 使用 Apache 创建你的第一个网站
现在我们已经完成了所有的调优工作,让我们开始创建一个实际的网站。按照我们的指示创建一个简单的 HTML 页面和一个在 Apache 上运行的虚拟主机。
你需要做的第一件事是为你的网站创建一个新的目录。运行以下命令来执行此操作:
```
mkdir -p /var/www/example.com/public_html
```
当然,将 example.com 替换为你所需的域名。你可以从 [Namecheap][11] 获得一个便宜的域名。
不要忘记在下面的所有命令中替换 example.com。
接下来,创建一个简单的静态网页。创建 HTML 文件:
```
nano /var/www/example.com/public_html/index.html
```
粘贴这些:
```
<html>
     <head>
       <title>Simple Page</title>
     </head>
     <body>
       <p>If you're seeing this in your browser then everything works.</p>
     </body>
</html>
```
保存并关闭文件。
配置目录的权限:
```
chown -R www-data:www-data /var/www/example.com
chmod -R og-r /var/www/example.com
```
为你的网站创建一个新的虚拟主机:
```
nano /etc/apache2/sites-available/example.com.conf
```
粘贴以下内容:
```
<VirtualHost *:80>
     ServerAdmin admin@example.com
     ServerName example.com
     ServerAlias www.example.com
   
     DocumentRoot /var/www/example.com/public_html
    
     ErrorLog ${APACHE_LOG_DIR}/error.log
     CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```
这是一个基础的虚拟主机。根据你的设置,你可能需要更高级的 .conf 文件。
在更新所有内容后保存并关闭文件。
现在,使用以下命令启用虚拟主机:
```
a2ensite example.com.conf
```
最后,重启 Apache 以使更改生效:
```
systemctl restart apache2
```
这就是全部了,你做完了。现在你可以访问 example.com 并查看你的页面。
--------------------------------------------------------------------------------
via: https://thishosting.rocks/how-to-install-optimize-apache-ubuntu/
作者:[ThisHosting][a]
译者:[MjSeven](https://github.com/MjSeven)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://thishosting.rocks
[1]:https://thishosting.rocks/ubuntu-18-04-new-features-release-date/
[2]:https://thishosting.rocks/go/vultr/
[3]:https://thishosting.rocks/cheap-cloud-hosting-providers-comparison/
[4]:https://thishosting.rocks/how-to-enable-ssh-on-ubuntu/
[5]:https://mobaxterm.mobatek.net/
[6]:https://thishosting.rocks/wp-content/uploads/2018/01/apache-running.jpg
[7]:https://www.modpagespeed.com/doc/download
[8]:https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
[9]:https://thishosting.rocks/wp-content/uploads/2018/01/mod_evasive.jpg
[10]:https://httpd.apache.org/docs/2.4/mod/
[11]:https://thishosting.rocks/neamcheap-review-cheap-domains-cool-names
[12]:https://thishosting.rocks/wp-content/plugins/patron-button-and-widgets-by-codebard/images/become_a_patron_button.png
[13]:https://www.patreon.com/thishostingrocks

View File

@ -1,166 +0,0 @@
开始 Vagrant 之旅
=====
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/containers_scale_performance.jpg?itok=R7jyMeQf)
如果你和我一样,你可能在某一个地方有一个“沙盒”,你可以在那里进行你正在做的任何项目。随着时间的推移,沙箱会变得杂乱无章,充斥着各种想法,工具链元素,你不使用的代码模块,以及其他你不需要的东西。当你完成某件事情时,这会使你的部署变得复杂,因为你可能不确定项目的实际依赖关系 - 随着时间推移你在沙盒中已经有了一些工具,但是你忘了必须安装它。你需要一个干净的环境,将所有的依赖关系放在一个地方,以便以后更方便。
或者你可能工作在 DevOps 中,你所服务的开发人员用模糊的依赖关系来编写代码,这使得测试变得更加困难。你需要一种方法来获得一个干净的盒子,将代码放入其中,并通过它运行代码,而且你希望这些环境是一次性的和可重复的。
那么选择 [Vagrant][1] 吧。由 HashiCorp 根据 [MIT License][2] 创建Vagrant 可充当 VirtualBox, Microsoft Hyper-V 或 Docker 容器的包装器和前端,并且可以通过[许多其他供应商][3]的插件进行扩展。你可以配置 Vagrant 以提供可重复干净的环境,并且已安装需要的基础架构。配置脚本是可移植的,因此,如果你的仓库和 Vagrant 配置脚本位于基于云存储上,那么你只需要很少的限制就可以启动并在多台机器机器上工作。让我们来看一看。
### 安装
对于本次安装,我的环境是 Linux Mint 桌面,版本是 18.3 Cinnamon 64 位,在其他大多数 Debian 派生系统上安装非常类似。在大多数发行版中,对于基于 RPM 的系统也有类似的安装程序。Vagrant 的[安装页面][4]为 Debian, Windows, CentOS, MacOS 和 Arch Linux 都提供下载,但是我在我的软件包管理器中找到了它,所以我在那进行了安装。
最简单的安装使用了 VirtualBox 作为虚拟化提供者,所以我需要安装它:
```
sudo apt-get install virtualbox vagrant
```
安装程序将会获取依赖项 - 主要是 Ruby 一些东西,安装它们。
### 建立一个项目
在设置你的项目之前,你需要了解一些你想要运行它的环境。你可以在 [Vagrant Boxes 仓库][5]中为许多虚拟化提供者找到大量预配置的盒子。许多会预先配置一些你可能需要的核心基础设置,比如 PHP, MySQL 和 Apache但是对于本次测试我将安装一个 Debian 8 64 位裸机 "Jessie" 沙盒并手动安装一些东西,这样你就可以看到具体过程了。
```
mkdir ~/myproject
cd ~/myproject
vagrant init debian/contrib-jessie64
vagrant up
```
最后一条命令将根据需要从仓库中获取或更新 VirtualBox 镜像,然后拉起启动器,你的系统上会出现一个运行框!下次启动这个项目时,除非镜像已经在仓库中更新,否则不会花费太长时间。
要访问沙盒,只需要输入 `vagrant ssh`,你将被放到虚拟机的全功能 SSH 会话中,你将会是 `vagrant` 用户,但你是 `sudo` 组的成员,所以你可以切换到 root并在这里做你想做的任何事情。
你会在沙盒中看到一个名为 `/vagrant` 目录,对这个目录小心点,因为它与你主机上的 `~/myproject` 文件夹保持同步。在虚拟机 `/vagrant` 下建立一个文件它会立即复制到主机上,反之亦然。注意,有些沙盒并没有安装 VirtualBox 的附加功能,所以拷贝只能在启动时才起作用。有一些用于手动同步的命令行工具,这可能是测试环境中非常有用的特性。我倾向于坚持使用那些有附加功能的沙盒,所以这个目录正常工作,不必考虑它。
这个方案的好处很快显现出来了: 如果你在主机上有一个代码编辑工具链,并处于某种原因不希望它出现在虚拟机上,那么这不是问题 - 在主机上进行编辑,虚拟机会立刻更改。快速更改虚拟机,它也将其同步到主机上的“官方”副本
让我们关闭这个盒子,这样我们就可以在这个盒子里提供一些我们需要的东西:`vagrant halt`。
### 在 Vm 上安装额外的软件
对于这个例子,我将使用 [Apache][6], [PostgreSQL][7] 和 [Dancer][8] web 框架为 Perl 的一个项目开发。我将修改Vagrant配置脚本以便我需要的东西已经安装。 为了使事情更容易保持稍后更新,我将在项目根目录下创建一个脚本`~/myproject/Vagrantfile`:
```
$provision_script = <<SCRIPT
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install \
  apache2 \
  postgresql-client-9.4 \
  postgresql-9.4 \
  libdbd-pg-perl \
  libapache2-mod-fastcgi \
  libdata-validate-email-perl  \
  libexception-class-perl \
  libexception-class-trycatch-perl \
  libtemplate-perl \
  libtemplate-plugin-json-escape-perl \
  libdbix-class-perl \
  libyaml-tiny-perl \
  libcrypt-saltedhash-perl \
  libdancer2-perl \
  libtemplate-plugin-gravatar-perl  \
  libtext-csv-perl \
  libstring-tokenizer-perl \
  cpanminus
cpanm -f -n \
  Dancer2::Session::Cookie \
  Dancer2::Plugin::DBIC \
  Dancer2::Plugin::Auth::Extensible::Provider::DBIC \
  Dancer2::Plugin::Locale \
  Dancer2::Plugin::Growler
sudo a2enmod rewrite fastcgi
sudo apache2ctl restart
SCRIPT
```
在 Vagrantfile 结尾附近,你会发现一行 `config.vm.provision` 变量,正如你在示例中看到的那样,你可以在此处以内联方式进行操作,只需通过取消注释以下行:
```
  # config.vm.provision "shell", inline: <<-SHELL
  #   sudo apt-get update
  #   sudo apt-get install -y apache2
  # SHELL
```
相反,将那四行替换为使用你在文件顶部定义为变量的配置脚本:
```
config.vm.provision "shell", inline: $provision_script
```
取消注释 `forwarded_port`。如果你愿意,你可以将端口从 8080 更改为其它端口。我通常使用 5000 端口,在浏览器中输入 `http://localhost:5000` 以访问虚拟机上的 Apache 服务器。
你可能还希望将转发的端口设置为从主机访问 VM 上的 Apache。寻找包含的行并取消注释它。如果你愿意也可以将端口从 8080 更改为其他内容。我通常使用端口 5000并在我的浏览器访问我虚拟机上的 Apache 服务器。
这里有一个设置提示:如果你的仓库位于云存储上,为了在多台机器上使用 Vagrant你可能希望将不同机器上的 `VAGRANT_HOME` 环境变量设置为不同的东西。通过 VirtualBox 的工作方式,你需要分别为这些系统存储状态信息,确保你的版本控制系统忽略了用于此的目录 - 我将 `.vagrant.d*` 添加到仓库的 `.gitignore` 文件中。不过,我确实让 Vagrantfile 成为仓库的一部分!
### 好了!
我进入 `vagrant up`,我准备开始写代码了。一旦你做了一两次,你可能会想出一些你会回收很多的 Vagrantfile 模板文件(就像我刚刚那样),这就是 Vagrant 的优势之一。你可以更快地完成实际的编码工作,并将很少的时间花在基础设施上!
你可以使用 Vagrant 做更多事情。配置工具存在于许多工具链中,因此,无论你需要复制什么环境,它都是快速而简单的。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/4/getting-started-vagrant
作者:[Ruth Holloway][a]
译者:[MjSeven](https://github.com/MjSeven)
校对:[校对者ID](https://github.com/校对者ID)
选题:[lujun9972](https://github.com/lujun9972)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/druthb
[1]:https://vagrantup.com
[2]:https://opensource.org/licenses/MIT
[3]:https://github.com/hashicorp/vagrant/wiki/Available-Vagrant-Plugins#providers
[4]:https://www.vagrantup.com/downloads.html
[5]:https://app.vagrantup.com/boxes/search
[6]:https://httpd.apache.org/
[7]:https://postgresql.org
[8]:https://perldancer.org

View File

@ -0,0 +1,82 @@
你可以用 Linux 中的 IP 工具做 3 件有用的事情
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/find-file-linux-code_magnifying_glass_zero.png?itok=E2HoPDg0)
`ifconfig` 命令在 Linux 上被弃用已有十多年的时间了,而 `iproute2` 项目包含了神奇的工具 `ip`。许多在线教程资源仍然采用旧的命令行工具,如 `ifconfig`、`route` 和 `netstat`。本教程的目标是分享一些可以使用 `ip` 工具轻松完成的网络相关的事情。
### 找出你的 IP 地址
```
[dneary@host]$ ip addr show
[snip]
44: wlp4s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 5c:e0:c5:c7:f0:f1 brd ff:ff:ff:ff:ff:ff
        inet 10.16.196.113/23 brd 10.16.197.255 scope global dynamic wlp4s0
        valid_lft 74830sec preferred_lft 74830sec
        inet6 fe80::5ee0:c5ff:fec7:f0f1/64 scope link
        valid_lft forever preferred_lft forever
```
`ip addr show` 会告诉你很多关于你的所有网络链接设备的信息。在这里我的无线以太网卡wlp4s0是 IPv4 地址(`inet` 字段)`10.16.196.113/23`。 `/23` 表示 32 位 IP 地址中的 23 位将被该子网中的所有 IP 地址共享。子网中的 IP 地址范围从 `10.16.196.0 到 10.16.197.254`。子网的广播地址IP 地址后面的 `brd` 字段)`10.16.197.255` 保留给子网上所有主机的广播流量。
例如,我们只能使用 `ip addr show dev wlp4s0` 来显示单个设备的信息。
### 显示你的路由表
```
[dneary@host]$ ip route list
default via 10.16.197.254 dev wlp4s0 proto static metric 600
10.16.196.0/23 dev wlp4s0 proto kernel scope link src 10.16.196.113 metric 601
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
```
路由表是本地主机帮助网络流量确定去哪里的方式。它包含一组路标,将流量发送到特定的接口,以及在旅途中的特定下一个地点。
如果你运行任何虚拟机或容器,它们将获得自己的 IP 地址和子网,这可能会使这些路由表非常复杂,但在单个主机中,通常有两条指令。对于本地流量,将其发送到本地以太网上,并且网络交换机将找出(使用称为 ARP 的协议)哪个主机拥有目标 IP 地址,并且要将流量发送到哪里。对于到互联网的流量,将其发送到本地网关节点,它将更好地了解如何到达目的地。
在上面的情况中,第一行代表外部流量的外部网关,第二行代表本地流量,第三行代表主机上运行的虚拟机的虚拟网桥,但该链接当前未激活。
### 监视你的网络配置
```
[dneary@host]$ ip monitor all
[dneary@host]$ ip -s link list wlp4s0
```
`ip monitor` 命令可用于监视路由表中的更改,网络接口上的网络寻址或本地主机上 ARP 表的更改。此命令在调试与容器和网络相关的网络问题时特别有用,如当两个虚拟机应该能彼此通信,但实际不能。
在使用 all 时ip monitor 会报告报告以 [LINK](网络接口更改),[ROUTE](更改路由表)、[ADDR]IP 地址更改)或 [NEIGH](与马无关 - 与邻居的 ARP 地址相关的变化)。
你还可以监视特定对象上的更改(例如,特定的路由表或 IP 地址)。
另一个适用于许多命令的有用选项是 `ip -s`,它提供了一些统计信息。添加第二个 `-s` 选项可以添加更多统计信息。上面的 `ip -s link list wlp4s0` 会给出很多关于接收和发送的数据包的信息、丢弃的数据包数量、检测到的错误等等。
### 提示:缩短你的命令
一般来说,对于 `ip` 工具,你只需要包含足够的字母来唯一标识你想要做的事情。你可以使用 `ip mon` 来代替 `ip monitor`。你可以使用 `ip a l`,,而不是 `ip addr list`,并且可以使用 `ip r`来代替 `ip route`。`ip link list` 可以缩写为 `ip l ls`。要了解可用于更改命令行为的许多选项,请浏览[ ip 手册页][1]。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/useful-things-you-can-do-with-IP-tool-Linux
作者:[Dave Neary][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/dneary
[1]:https://www.systutorials.com/docs/linux/man/8-ip-route/