diff --git a/published/20170118 10 reasons to use Cinnamon as your Linux desktop environment.md b/published/20170118 10 reasons to use Cinnamon as your Linux desktop environment.md new file mode 100644 index 0000000000..330ef3aab7 --- /dev/null +++ b/published/20170118 10 reasons to use Cinnamon as your Linux desktop environment.md @@ -0,0 +1,70 @@ +10 个使用 Cinnamon 作为 Linux 桌面环境的理由 +============================================================ + +> Cinnamon 是一个让人怀旧 GNOME 2 的 Linux 桌面环境,它灵活、快速,并提供了种种的功能。 + +![10 reasons to use Cinnamon as your Linux desktop environment](https://opensource.com/sites/default/files/styles/image-full-size/public/cinnamon.jpg?itok=rPZvjqGr "10 reasons to use Cinnamon as your Linux desktop environment") + +最近我安装了 Fedora 25,我觉得当前的 [KDE][3] Plasma 版本并不稳定。在我决定尝试其它的桌面之前一天崩溃了好几次。在我安装了几个其它的桌面,并每个尝试了几个小时后,我最终决定在 Plasma 打上补丁并且稳定之前就使用 Cinnamon 了。以下是我所发现的。 + +### Cinnamon 简介 + +在 2011,带有新的 GNOME Shell 的 GNOME 3 发布了,新的界面马上引来了或正或反的反馈。许多用户以及开发者非常喜欢原先的 GNOME 界面,因此有多个组织复刻了它,其中一个结果就是 Cinnamon。 + +开发 GNOME 3 的 GNOME shell 背后的原因之一是许多原先的 GNOME 用户界面组件不再活跃开发了。这同样也是 Cinnamon 以及其他 GNOME 复刻项目的问题。 Linux Mint 项目是 Cinnamon 的一个首要推动者,因为 GNOME 是 Mint 的官方桌面环境。Mint 开发者已经将 Cinnamon 推进到了不需要 GNOME 本身的地步,Cinnamon 已经是一个完全独立的桌面环境,它保留了许多用户喜欢的 GNOME 界面的功能。 + +![cinnamon-desktop-environment.jpg](https://opensource.com/sites/default/files/images/life-uploads/cinnamon-desktop-environment.jpg) + +*图 1:打开系统设置工具的默认 Cinnamon 桌面。* + +Cinnamon 3.2 是当前发布版本。除了 Mint,Cinnamon 还在许多发行版中可用,包括 Fedora、Arch、Gentoo、Debian 和 OpenSUSE 等。 + +### 使用 Cinnamon 的理由 + +这是我的使用 Cinnamon 的 10 个重要理由: + +1. **集成。** 桌面的选择并不取决于在较长时间内是否有为它写的应用。我使用过的所有应用程序,不管它是在哪个桌面下写的,它都可以在任何其它桌面上运行正常,Cinnamon 也不例外。要运行那些为 KDE、GNOME 或其他桌面编写的程序所需要的库都有,可以在 Cinnamon 上面顺滑地使用这些程序。 +2. **外观。** 让我们面对它,外观是很重要的。Cinnamon 有一个明快的、干净的外观,它使用了易于阅读的字体以及颜色的组合。桌面没有不必要的阻碍,你可以使用“系统设置” => “桌面” 菜单配置显示在桌面上的的图标。这个菜单还允许你指定是否在主监视器、次监视器或者所有监视器上显示桌面图标。 +3. **桌面组件。** 桌面组件是一些小型的、可以添加到桌面的单一用途的程序。只有一些是可用的,但是你可以从 CPU 或者磁盘监视器、天气应用、便利贴、桌面相簿、时间和日期等之中选择。我喜欢时间和日期桌面组件,因为它比 Cinnamon 面板中的小程序易于阅读。 +4. **速度。** Cinnamon 快速又敏捷。程序加载和显示很快。桌面自身在登录时加载也很快,虽然这只是我的主观体验,并没有基于时间测试。 +5. **配置。 ** Cinnamon 不如 KDE Plasma 那样可配置,但是也要比我第一次尝试它的时候有更多的配置。Cinnamon 控制中心提供了许多桌面配置选项的集中访问。它有一个主窗口,可以从它启动特定功能的配置窗口。可以很容易地在 “系统设置” 的 “主题” 的可用外观中选择新的外观。你可以选择窗口边框、图标、控件、鼠标指针和桌面基本方案。其它选择还包括字体和背景。我发现这些配置工具中有许多是我遇到的最好的。它有适量的桌面主题,从而能够显著改变桌面的外观,而不会像 KDE 那样面临选择困难。 +6. **Cinnamon 面板。** Cinnamon 面板,即工具栏,最初的配置非常简单。它包含用于启动程序的菜单、基本的系统托盘和应用程序选择器。这个面板易于配置,并且添加新的程序启动器只需要定位你想要添加到主菜单的程序,右键单击程序图标,然后选择“添加到面板”。你还可以将启动器图标添加到桌面本身,以及 Cinnamon 的 “收藏” 的启动栏中。你还可以进入面板的**编辑**模式并重新排列图标。 +7. **灵活性。** 有时可能很难找到最小化或者隐藏的正在运行的程序,如果有许多正在运行的应用程序,则在工具栏的程序选择器上查找它可能会有挑战性。 在某种程度上,这是因为程序并不总是有序地排在选择器中使其易于查找,所以我最喜欢的功能之一就是可以拖动正在运行的程序的按钮并将其重新排列在选择器上。这可以使查找和显示属于程序的窗口更容易,因为现在它们现在在我放的位置上。 + + Cinnamon 桌面还有一个非常好的弹出菜单,你可以右键单击访问。此菜单有一些常用任务,例如访问桌面设置、添加桌面组件以及其他与桌面相关的任务。 + + 其它菜单项之一是 “创建新文档”,它使用位于 `~/Templates` 目录中的文档模板,并列出它们中的每一个。只需点击要使用的模板,使用这个模板的文档就会使用默认的 Office 程序创建。在我的情况下,那就是 LibreOffice。 +8. **多工作空间。** Cinnamon 像其他桌面环境一样提供了多个桌面。Cinnamon 称它为“工作区”。工作区选择器位于 Cinnamon 面板中并展示每个工作区的窗口概览。窗口可以在工作区之间移动或指定到所有工作区。我确实发现工作区选择器有时候会比窗口位置的显示慢一些,所以我将工作区选择器切换为显示工作区编号,而不是在工作区中显示窗口概览。 +9. **Nemo。** 大部分桌面因种种目而使用它们自己偏好的默认程序,Cinnamon 也不例外。我偏好的桌面文件管理器是 Krusader,但是 Cinnamon 默认使用 Nemo,因此在测试中我就用它了。我发现我很喜欢 Nemo。它有一个美丽干净的界面,我喜欢大部分功能并经常使用。它易于使用,同时对我的需求也足够灵活。虽然 Nemo 是 Nautilus 的复刻,但是我发现 Nemo 更好地被集成进了 Cinnamon 环境。Nautilus 界面看上去没有与 Cinnamon 很好集成,与 Cinnamon 不太和谐。 +10. **稳定性。**  Cinnamon 非常稳定且可用。 + +### 总结 + +Cinnamon 是 GNOME 3 桌面的复刻,它看上去像一个前所未有的 GNOME 桌面。它的发展看起来是符合逻辑的改进, Cinnamon 开发者认为需要在提升和扩展 GNOME 的同时保留它的独特性以及被大家非常喜欢的特性。它不再是 GNOME 3 - 它是不同的并且是更好的。Cinnamon 看上去很棒,并且对我而言也工作得很好,并且从 KDE 这个我仍旧非常喜欢的环境切换过来也很顺畅。我花费了几天时间学习 Cinnamon 的差异如何使我的桌面体验更好,并且我非常高兴了解这个很棒的桌面。 + +虽然我喜欢 Cinnamon,但我仍然喜欢体验其它的环境,我目前正切换到 LXDE 桌面,并已经用了几个星期。在我使用一段时间时候,我会分享我的 LXDE 体验。 + +(题图: [Sam Mugraby][1],Photos8.com. [CC BY 2.0][2]) + +-------------------------------------------------------------------------------- + +作者简介: + +![](https://opensource.com/sites/default/files/styles/profile_pictures/public/david-crop.jpg?itok=oePpOpyV) + +David Both 是一个 Linux 和开源倡导者,他居住在北卡罗莱纳州的 Raleigh。他在 IT 行业已经超过 40 年,在他工作的 IBM 公司教授 OS/2 超过 20 年,他在 1981 年为最早的 IBM PC 写了第一个培训课程。他教过 Red Hat 的 RHCE 课程,在 MCI Worldcom、 Cisco 和北卡罗莱纳州 工作过。他一直在使用 Linux 和开源软件近 20 年。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/17/1/cinnamon-desktop-environment + +作者:[David Both][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/users/dboth +[1]:https://commons.wikimedia.org/wiki/File:Cinnamon-other.jpg +[2]:https://creativecommons.org/licenses/by/2.0/deed.en +[3]:https://opensource.com/life/15/4/9-reasons-to-use-kde diff --git a/published/20170308 Many SQL Performance Problems Stem from Unnecessary, Mandatory Work.md b/published/20170308 Many SQL Performance Problems Stem from Unnecessary, Mandatory Work.md new file mode 100644 index 0000000000..70148a5af7 --- /dev/null +++ b/published/20170308 Many SQL Performance Problems Stem from Unnecessary, Mandatory Work.md @@ -0,0 +1,401 @@ +许多 SQL 性能问题来自于“不必要的强制性工作” +===================================== + +在编写高效 SQL 时,你可能遇到的最有影响的事情就是[索引][1]。但是,一个很重要的事实就是很多 SQL 客户端要求数据库做很多**“不必要的强制性工作”**。 + +跟我再重复一遍: + +> 不必要的强制性工作 + +什么是**“不必要的强制性工作”**?这个意思包括两个方面: + +### 不必要的 + +假设你的客户端应用程序需要这些信息: + +[ + ![](https://lukaseder.files.wordpress.com/2017/03/title-rating.png?w=662) +][2] + +这没什么特别的。我们运行着一个电影数据库([例如 Sakila 数据库][3]),我们想要给用户显示每部电影的名称和评分。 + +这是能产生上面结果的查询: + +``` +SELECT title, rating +FROM film +``` + +然而,我们的应用程序(或者我们的 ORM(LCTT 译注:Object-Relational Mapping,对象关系映射))运行的查询却是: + +``` +SELECT * +FROM film +``` + +我们得到什么?猜一下。我们得到很多无用的信息: + +[ + ![](https://lukaseder.files.wordpress.com/2017/03/useless-information.png?w=662&h=131) +][4] + +甚至一些复杂的 JSON 数据全程在下列环节中加载: + +* 从磁盘 +* 加载到缓存 +* 通过总线 +* 进入客户端内存 +* 然后被丢弃 + +是的,我们丢弃了其中大部分的信息。检索它所做的工作完全就是不必要的。对吧?没错。 + +### 强制性 + +这是最糟糕的部分。现今随着优化器变得越来越聪明,这些工作对于数据库来说都是强制执行的。数据库没有办法_知道_客户端应用程序实际上不需要其中 95% 的数据。这只是一个简单的例子。想象一下如果我们连接更多的表... + +你想想那会怎样呢?数据库还快吗?让我们来看看一些之前你可能没有想到的地方: + +### 内存消耗 + +当然,单次执行时间不会变化很大。可能是慢 1.5 倍,但我们可以忍受,是吧?为方便起见,有时候确实如此。但是如果你_每次_都为了方便而牺牲性能,这事情就大了。我们不说性能问题(单个查询的速度),而是关注在吞吐量上时(系统响应时间),事情就变得困难而难以解决。你就会受阻于规模的扩大。 + +让我们来看看执行计划,这是 Oracle 的: + +``` +-------------------------------------------------- +| Id | Operation | Name | Rows | Bytes | +-------------------------------------------------- +| 0 | SELECT STATEMENT | | 1000 | 166K| +| 1 | TABLE ACCESS FULL| FILM | 1000 | 166K| +-------------------------------------------------- +``` + +对比一下: + +``` +-------------------------------------------------- +| Id | Operation | Name | Rows | Bytes | +-------------------------------------------------- +| 0 | SELECT STATEMENT | | 1000 | 20000 | +| 1 | TABLE ACCESS FULL| FILM | 1000 | 20000 | +-------------------------------------------------- +``` + +当执行 `SELECT *` 而不是 `SELECT film, rating` 的时候,我们在数据库中使用了 8 倍之多的内存。这并不奇怪,对吧?我们早就知道了。在很多我们并不需要其中全部数据的查询中我们都是这样做的。我们为数据库产生了**不必要的强制性工作**,其后果累加了起来,就是我们使用了多达 8 倍的内存(当然,数值可能有些不同)。 + +而现在,所有其它的步骤(比如,磁盘 I/O、总线传输、客户端内存消耗)也受到相同的影响,我这里就跳过了。另外,我还想看看... + +### 索引使用 + +如今大部分数据库都有[涵盖索引][5](LCTT 译注:covering index,包括了你查询所需列、甚至更多列的索引,可以直接从索引中获取所有需要的数据,而无需访问物理表)的概念。涵盖索引并不是特殊的索引。但对于一个特定的查询,它可以“意外地”或人为地转变为一个“特殊索引”。 + +看看这个查询: + +``` +SELECT * +FROM actor +WHERE last_name LIKE 'A%' +``` + +执行计划中没有什么特别之处。它只是个简单的查询。索引范围扫描、表访问,就结束了: + +``` +------------------------------------------------------------------- +| Id | Operation | Name | Rows | +------------------------------------------------------------------- +| 0 | SELECT STATEMENT | | 8 | +| 1 | TABLE ACCESS BY INDEX ROWID| ACTOR | 8 | +|* 2 | INDEX RANGE SCAN | IDX_ACTOR_LAST_NAME | 8 | +------------------------------------------------------------------- +``` + +这是个好计划吗?如果我们只是想要这些,那么它就不是: + +[ + ![](https://lukaseder.files.wordpress.com/2017/03/first-name-last-name.png?w=662) +][6] + +当然,我们浪费了内存之类的。再来看看这个查询: + +``` +SELECT first_name, last_name +FROM actor +WHERE last_name LIKE 'A%' +``` + +它的计划是: + +``` +---------------------------------------------------- +| Id | Operation | Name | Rows | +---------------------------------------------------- +| 0 | SELECT STATEMENT | | 8 | +|* 1 | INDEX RANGE SCAN| IDX_ACTOR_NAMES | 8 | +---------------------------------------------------- +``` + +现在我们可以完全消除表访问,因为有一个索引涵盖了我们查询需要的所有东西……一个涵盖索引。这很重要吗?当然!这种方法可以将你的某些查询加速一个数量级(如果在某个更改后你的索引不再涵盖,可能会降低一个数量级)。 + +你不能总是从涵盖索引中获利。索引也有它们自己的成本,你不应该添加太多索引,例如像这种情况就是不明智的。让我们来做个测试: + +``` +SET SERVEROUTPUT ON +DECLARE + v_ts TIMESTAMP; + v_repeat CONSTANT NUMBER := 100000; +BEGIN + v_ts := SYSTIMESTAMP; + + FOR i IN 1..v_repeat LOOP + FOR rec IN ( + -- Worst query: Memory overhead AND table access + SELECT * + FROM actor + WHERE last_name LIKE 'A%' + ) LOOP + NULL; + END LOOP; + END LOOP; + + dbms_output.put_line('Statement 1 : ' || (SYSTIMESTAMP - v_ts)); + v_ts := SYSTIMESTAMP; + + FOR i IN 1..v_repeat LOOP + FOR rec IN ( + -- Better query: Still table access + SELECT /*+INDEX(actor(last_name))*/ + first_name, last_name + FROM actor + WHERE last_name LIKE 'A%' + ) LOOP + NULL; + END LOOP; + END LOOP; + + dbms_output.put_line('Statement 2 : ' || (SYSTIMESTAMP - v_ts)); + v_ts := SYSTIMESTAMP; + + FOR i IN 1..v_repeat LOOP + FOR rec IN ( + -- Best query: Covering index + SELECT /*+INDEX(actor(last_name, first_name))*/ + first_name, last_name + FROM actor + WHERE last_name LIKE 'A%' + ) LOOP + NULL; + END LOOP; + END LOOP; + + dbms_output.put_line('Statement 3 : ' || (SYSTIMESTAMP - v_ts)); +END; +/ +``` + + +结果是: + +``` +Statement 1 : +000000000 00:00:02.479000000 +Statement 2 : +000000000 00:00:02.261000000 +Statement 3 : +000000000 00:00:01.857000000 +``` + +注意,表 actor 只有 4 列,因此语句 1 和 2 的差别并不是太令人印象深刻,但仍然很重要。还要注意我使用了 Oracle 的提示来强制优化器为查询选择一个或其它索引。在这种情况下语句 3 明显胜利。这是一个好_很多_的查询,也是一个十分简单的查询。 + +当我们写 `SELECT *` 语句时,我们为数据库带来了**不必要的强制性工作**,这是无法优化的。它不会使用涵盖索引,因为比起它所使用的 `LAST_NAME` 索引,涵盖索引开销更多一点,不管怎样,它都要访问表以获取无用的 `LAST_UPDATE` 列。 + +使用 `SELECT *` 会变得更糟。考虑一下…… + +### SQL 转换 + +优化器工作的很好,因为它们转换了你的 SQL 查询([看我最近在 Voxxed Days Zurich 关于这方面的演讲][7])。例如,其中有一个称为“表连接消除”的转换,它真的很强大。看看这个辅助视图,我们写了这个视图是因为我们非常讨厌总是连接所有这些表: + +``` +CREATE VIEW v_customer AS +SELECT + c.first_name, c.last_name, + a.address, ci.city, co.country +FROM customer c +JOIN address a USING (address_id) +JOIN city ci USING (city_id) +JOIN country co USING (country_id) +``` + +这个视图仅仅是把 `CUSTOMER` 和他们不同的 `ADDRESS` 部分所有“对一”关系连接起来。谢天谢地,它很工整。 + +现在,使用这个视图一段时间之后,想象我们非常习惯这个视图,我们都忘了所有它底层的表。然后,我们运行了这个查询: + +``` +SELECT * +FROM v_customer +``` + +我们得到了一个相当令人印象深刻的计划: + +``` +---------------------------------------------------------------- +| Id | Operation | Name | Rows | Bytes | Cost | +---------------------------------------------------------------- +| 0 | SELECT STATEMENT | | 599 | 47920 | 14 | +|* 1 | HASH JOIN | | 599 | 47920 | 14 | +| 2 | TABLE ACCESS FULL | COUNTRY | 109 | 1526 | 2 | +|* 3 | HASH JOIN | | 599 | 39534 | 11 | +| 4 | TABLE ACCESS FULL | CITY | 600 | 10800 | 3 | +|* 5 | HASH JOIN | | 599 | 28752 | 8 | +| 6 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 | +| 7 | TABLE ACCESS FULL| ADDRESS | 603 | 17487 | 3 | +---------------------------------------------------------------- +``` + +当然是这样。我们运行了所有这些表连接以及全表扫描,因为这就是我们让数据库去做的:获取所有的数据。 + +现在,再一次想一下,对于一个特定场景,我们真正想要的是: + +[ + ![](https://lukaseder.files.wordpress.com/2017/03/first-name-last-name-customers.png?w=662) +][8] + +是啊,对吧?现在你应该知道我的意图了。但想像一下,我们确实从前面的错误中学到了东西,现在我们实际上运行下面一个比较好的查询: + +``` +SELECT first_name, last_name +FROM v_customer +``` + +再来看看结果! + +``` +------------------------------------------------------------------ +| Id | Operation | Name | Rows | Bytes | Cost | +------------------------------------------------------------------ +| 0 | SELECT STATEMENT | | 599 | 16173 | 4 | +| 1 | NESTED LOOPS | | 599 | 16173 | 4 | +| 2 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 | +|* 3 | INDEX UNIQUE SCAN| SYS_C007120 | 1 | 8 | 0 | +------------------------------------------------------------------ +``` + +这是执行计划一个_极大的_进步。我们的表连接被消除了,因为优化器可以证明它们是**不必要的**,因此一旦它可以证明这点(而且你不会因使用 `select *` 而使其成为**强制性**工作),它就可以移除这些工作并不执行它。为什么会发生这种情况? + +每个 `CUSTOMER.ADDRESS_ID` 外键保证了_有且只有一个_ `ADDRESS.ADDRESS_ID` 主键值,因此可以保证 `JOIN` 操作是对一连接,它不会产生或者删除行。如果我们甚至不选择行或查询行,当然我们就不需要真正地去加载行。可以证实地移除 `JOIN` 并不会改变查询的结果。 + +数据库总是会做这些事情。你可以在大部分数据库上尝试它: + +``` +-- Oracle +SELECT CASE WHEN EXISTS ( + SELECT 1 / 0 FROM dual +) THEN 1 ELSE 0 END +FROM dual + +-- 更合理的 SQL 语句,例如 PostgreSQL +SELECT EXISTS (SELECT 1 / 0) +``` + +在这种情况下,当你运行这个查询时你可能预料到会抛出算术异常: + +``` +SELECT 1 / 0 FROM dual +``` + +产生了: + +``` +ORA-01476: divisor is equal to zero +``` + +但它并没有发生。优化器(甚至解析器)可以证明 `EXISTS (SELECT ..)` 谓词内的任何 `SELECT` 列表达式不会改变查询的结果,因此也就没有必要计算它的值。呵! + +### 同时…… + +大部分 ORM 最不幸问题就是事实上他们很随意就写出了 `SELECT *` 查询。事实上,例如 HQL / JPQL,就设置默认使用它。你甚至可以完全抛弃 `SELECT` 从句,因为毕竟你想要获取所有实体,正如声明的那样,对吧? + +例如: + +`FROM` `v_customer` + +例如 [Vlad Mihalcea][9](一个 Hibernate 专家和 Hibernate 开发倡导者)建议你每次确定不想要在获取后进行任何更改时再使用查询。ORM 使解决对象图持久化问题变得简单。注意:持久化。真正修改对象图并持久化修改的想法是固有的。 + +但如果你不想那样做,为什么要抓取实体呢?为什么不写一个查询?让我们清楚一点:从性能角度,针对你正在解决的用例写一个查询_总是_会胜过其它选项。你可以不会在意,因为你的数据集很小,没关系。可以。但最终,你需要扩展并重新设计你的应用程序以便在强制实体图遍历之上支持查询语言,就会变得很困难。你也需要做其它事情。 + +### 计算出现次数 + +资源浪费最严重的情况是在只是想要检验存在性时运行 `COUNT(*)` 查询。例如: + +> 这个用户有没有订单? + +我们会运行: + +``` +SELECT count(*) +FROM orders +WHERE user_id = :user_id +``` + +很简单。如果 `COUNT = 0`:没有订单。否则:是的,有订单。 + +性能可能不会很差,因为我们可能有一个 `ORDERS.USER_ID` 列上的索引。但是和下面的这个相比你认为上面的性能是怎样呢: + +``` +-- Oracle +SELECT CASE WHEN EXISTS ( + SELECT * + FROM orders + WHERE user_id = :user_id +) THEN 1 ELSE 0 END +FROM dual + +-- 更合理的 SQL 语句,例如 PostgreSQL +SELECT EXISTS ( + SELECT * + FROM orders + WHERE user_id = :user_id +) +``` + +它不需要火箭科学家来确定,一旦它找到一个,实际存在谓词就可以马上停止寻找额外的行。因此,如果答案是“没有订单”,速度将会是差不多。但如果结果是“是的,有订单”,那么结果在我们不计算具体次数的情况下就会_大幅_加快。 + +因为我们_不在乎_具体的次数。我们告诉数据库去计算它(**不必要的**),而数据库也不知道我们会丢弃所有大于 1 的结果(**强制性**)。 + +当然,如果你在 JPA 支持的集合上调用 `list.size()` 做同样的事情,情况会变得更糟! + +[近期我有关于该情况的博客以及在不同数据库上的测试。去看看吧。][10] + +### 总结 + +这篇文章的立场很“明显”。别让数据库做**不必要的强制性工作**。 + +它**不必要**,因为对于你给定的需求,你_知道_一些特定的工作不需要完成。但是,你告诉数据库去做。 + +它**强制性**,因为数据库无法证明它是**不必要的**。这些信息只包含在客户端中,对于服务器来说无法访问。因此,数据库需要去做。 + +这篇文章大部分在介绍 `SELECT *`,因为这是一个很简单的目标。但是这并不仅限于数据库。这关系到客户端要求服务器完成**不必要的强制性工作**的任何分布式算法。你的 AngularJS 应用程序平均有多少个 N+1 问题,UI 在服务结果 A 上循环,多次调用服务 B,而不是把所有对 B 的调用打包为一个调用?这是一个复发的模式。 + +解决方法总是相同。你给执行你命令的实体越多信息,(理论上)它能更快执行这样的命令。每次都写一个好的查询。你的整个系统都会为此感谢你的。 + +### 如果你喜欢这篇文章... + +再看看近期我在 Voxxed Days Zurich 的演讲,其中我展示了一些在数据处理算法上为什么 SQL 总是会胜过 Java 的双曲线例子 + +-------------------------------------------------------------------------------- + +via: https://blog.jooq.org/2017/03/08/many-sql-performance-problems-stem-from-unnecessary-mandatory-work + +作者:[jooq][a] +译者:[ictlyh](https://github.com/ictlyh) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://blog.jooq.org/ +[1]:http://use-the-index-luke.com/ +[2]:https://lukaseder.files.wordpress.com/2017/03/title-rating.png +[3]:https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/Sakila +[4]:https://lukaseder.files.wordpress.com/2017/03/useless-information.png +[5]:https://blog.jooq.org/2015/04/28/do-not-think-that-one-second-is-fast-for-query-execution/ +[6]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name.png +[7]:https://www.youtube.com/watch?v=wTPGW1PNy_Y +[8]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name-customers.png +[9]:https://vladmihalcea.com/2016/09/13/the-best-way-to-handle-the-lazyinitializationexception/ +[10]:https://blog.jooq.org/2016/09/14/avoid-using-count-in-sql-when-you-could-use-exists/ diff --git a/published/20170316 An introduction to GRUB2 configuration for your Linux machine.md b/published/20170316 An introduction to GRUB2 configuration for your Linux machine.md new file mode 100644 index 0000000000..1556849b7a --- /dev/null +++ b/published/20170316 An introduction to GRUB2 configuration for your Linux machine.md @@ -0,0 +1,141 @@ +Linux GRUB2 配置简介 +============================================================ + +> 学习 GRUB 引导加载程序是如何预备你的系统并启动操作系统内核的。 + + +![Linux GRUB2 配置简介](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/car-penguin-drive-linux-yellow.png?itok=ueZE5mph "Linux GRUB2 配置简介") + + +自从上个月为我的文章《[Linux 引导和启动过程简介][2]》做研究开始,我对更深入了解 GRUB2 产生了兴趣。这篇文章提供了配置 GRUB2 的简要介绍。为了简便起见,我大多数情况下会使用 GRUB 指代 GRUB2。 + +### GRUB + +GRUB 来自 GRand Unified Bootloader 的缩写。它的功能是在启动时从 BIOS 接管掌控、加载自身、加载 Linux 内核到内存,然后再把执行权交给内核。一旦内核开始掌控,GRUB 就完成了它的任务,也就不再需要了。 + +GRUB 支持多种 Linux 内核,并允许用户在启动时通过菜单在其中选择。我发现这是一种非常有用的工具,因为我有很多次遇到一个应用程序或者系统服务在特定内核版本下失败的问题。有好几次,引导到一个较旧的内核时就可以避免类似的问题。默认情况下,使用 `yum` 或 `dnf` 进行更新时会保存三个内核 - 最新的以及两个比较旧的。在被包管理器删除之前所保留的内核数目可以在 `/etc/dnf/dnf.conf` 或 `/etc/yum.conf` 文件中配置。我通常把 `installonly_limit` 的值修改为 9 以便保留 9 个内核。当我不得不恢复到低几个版本的内核时这非常有用。 + +### GRUB 菜单 + +GRUB 菜单的功能是当默认的内核不是想要的时,允许用户从已经安装的内核中选择一个进行引导。通过上下箭头键允许你选中想要的内核,敲击回车键会使用选中的内核继续引导进程。 + +GRUB 菜单也提供了超时机制,因此如果用户没有做任何选择,GRUB 就会在没有用户干预的情况下使用默认内核继续引导。敲击键盘上除了回车键之外的任何键会停止终端上显示的倒数计时器。立即敲击回车键会使用默认内核或者选中的内核继续引导进程。 + +GRUB 菜单提供了一个 “救援rescue” 内核,用于故障排除或者由于某些原因导致的常规内核不能完成启动过程。不幸的是,这个救援内核不会引导到救援模式。文章后面会更详细介绍这方面的东西。 + +### grub.cfg 文件 + +`grub.cfg` 文件是 GRUB 配置文件。它由 `grub2-mkconfig` 程序根据用户的配置使用一组主配置文件以及 grub 默认文件而生成。`/boot/grub2/grub.cfg` 文件在 Linux 安装时会初次生成,安装新内核时又会重新生成。 + +`grub.cfg` 文件包括了类似 Bash 脚本的代码以及一个按照安装顺序排序的已安装内核列表。例如,如果你有 4 个已安装内核,最新的内核索引是 0,前一个内核索引是 1,最旧的内核索引是 3。如果你能访问 `grub.cfg` 文件,你应该去看看感受一下它看起来是什么样。`grub.cfg` 太大也就没有包含在这篇文章中。 + +### GRUB 配置文件 + +`grub.cfg` 的主要配置文件都在 `/etc/grub.d` 目录。该目录中的每个文件都包含了最终会整合到 `grub.cfg` 文件中的 GRUB 代码。这些配置文件的命名模式以排序方式设计,这使得最终的 `grub.cfg` 文件可以按正确的顺序整合而成。每个文件都有注释表明该部分的开始和结束,这些注释也是最终的 `grub.cfg` 文件的一部分,从而可以看出每个部分是由哪个文件生成。分隔注释看起来像这样: + +``` +### BEGIN /etc/grub.d/10_linux ### + +### END /etc/grub.d/10_linux ### +``` + +不要修改这些文件,除非你是一个 GRUB 专家并明白更改会发生什么。无论如何,修改 `grub.cfg` 文件时你也总应该保留一个原始文件的备份。 `40_custom` 和 `41_custom` 这两个特别的文件用于生成用户对 GRUB 配置的修改。你仍然要注意对这些文件的更改的后果,并保存一份原始 `grub.cfg` 文件的备份。 + +你也可以把你自己的文件添加到 `/etc/grub.d` 目录。这样做的一个可能的原因是为非 Linux 操作系统添加菜单行。要注意遵循命名规则,确保配置文件中额外的菜单选项刚好在 `10_linux` 条目之前或之后。 + +### GRUB 默认文件 + +老版本 GRUB 的配置非常简单而明了,我只需要修改 `/boot/grub/grub.conf` 就可以了。对于新版本的 GRUB2,我虽然还可以通过更改 `/boot/grub2/grub.cfg` 来修改,但和老版本的 GRUB 相比,新版本相对更加复杂。另外,安装一个新内核时 `grub.cfg` 可能会被重写,因此任何修改都可能消失。当然,GNU.org 的 GRUB 手册确实有过直接创建和修改 `/boot/grub2/grub.cfg` 的讨论。 + +一旦你明白了如何做,更改 GRUB2 配置就会变得非常简单。我为之前的文章研究 GRUB2 的时候才明白这个。秘方就在 `/etc/default` 目录里面,一个自然而然称为 `grub` 的文件,它可以通过简单的终端命令操作。`/etc/default` 目录包括了一些类似 Google Chrome、 useradd、 和 grub 程序的配置文件。 + +`/etc/default/grub` 文件非常简单。这个 `grub` 默认文件已经列出了一些有效的键值对。你可以简单地更改现有键值或者添加其它文件中还没有的键。下面的列表 1 显示了一个没有更改过的 `/etc/default/grub` 文件。 + +``` +GRUB_TIMEOUT=5 +GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' + /etc/system-release)" +GRUB_DEFAULT=saved +GRUB_DISABLE_SUBMENU=true +GRUB_TERMINAL_OUTPUT="console" +GRUB_CMDLINE_LINUX="rd.lvm.lv=fedora_fedora25vm/root + rd.lvm.lv=fedora_fedora25vm/swap + rd.lvm.lv=fedora_fedora25vm/usr rhgb quiet" +GRUB_DISABLE_RECOVERY="true" +``` + +_列表 1:Fedora 25 一个原始 grub 默认文件。_ + +[GRUB 手册 5.1 章节][7]包括了所有可以添加到该 `grub` 文件的键的信息。我只需要修改 `grub` 默认文件已经有的一些键值就够了。让我们看看这些键值以及一些在 grub 默认文件中没有出现的每个键的意义。 + +* `GRUB_TIMEOUT` 这个键的值决定了显示 GRUB 选择菜单的时间长度。GRUB 提供了同时保存多个安装内核并在启动时使用 GRUB 菜单在其中选择的功能。这个键的默认值是 5 秒,但我通常修改为 10 秒使得有更多时间查看选项并作出选择。 +* `GRUB_DISTRIBUTOR` 这个键定义了一个从 `/etc/system-release` 文件中提取发行版本的 [sed][3] 表达式。这个信息用于生成出现在 GRUB 菜单中的每个内核发布版的文本名称,例如 “Fedora” 等。由于不同发行版之间 `system-release` 文件结构的差异,在你的系统中这个 sed 表达式可能有些不同。 +* `GRUB_DEFAULT` 决定默认引导哪个内核。如果是 `saved`,这代表最新内核。这里的其它选项如果是数字则代表了 `grub.cfg` 中列表的索引。使用索引号 3,就会总是加载列表中的第四个内核,即使安装了一个新内核之后也是。因此使用索引数字的话,在安装一个新内核后会加载不同的内核。要确保引导特定内核版本的唯一方法是设置 `GRUB_DEFAULT` 的值为想要内核的名称,例如 `4.8.13-300.fc25.x86_64`。 +* `GRUB_SAVEDEFAULT` 通常,grub 默认文件中不会指定这个选项。当选择不同内核进行引导时,正常操作下该内核只会启动一次。默认内核不会改变。当其设置为 `true` 并和 `GRUB_DEFAULT=saved` 一起使用时,这个选项会保存一个不同内核作为默认值。当选择不同内核进行引导时会发生这种情况。 +* `GRUB_DISABLE_SUBMENU` 一些人可能会希望为 GRUB 菜单创建一个内核的层级菜单结构。这个键和 `grub.cfg` 中一些额外内核配置允许创建这样的层级结构。例如,主菜单中可能有 `production` 和 `test` 子菜单,每个子菜单中包括了一些合适的内核。设置它为 `false` 可以启用子菜单。 +* `GRUB_TERMINAL_OUTPUT` 一些环境下可能需要或者必要将输出重定向到一个不同的显示控制台或者终端。默认情况下是把输出发送到默认终端,通常 `console` 等价于 Intel 系列个人电脑的标准输出。另一个有用的选择是在使用串行终端或者 Integrated Lights Out (ILO) 终端连接的数据中心或者实验室环境中指定 `serial`。 +* `GRUB_TERMINAL_INPUT` 和 `GRUB_TERMINAL_OUTPUT` 类似,可能需要或者必要重定向输入为串行终端或者 ILO 设备、而不是标准键盘输入。 +* `GRUB_CMDLINE_LINUX` 这个键包括了在启动时会传递给内核的命令行参数。注意这些参数会被添加到 `grub.cfg` 所有已安装内核的内核行。这意味着所有已安装的内核在启动时都会有相同的参数。我通常删除 `rhgb` 和 `quiet` 参数以便我可以看到引导和启动时内核和 systemd 输出的所有内核信息消息。 +* `GRUB_DISABLE_RECOVERY` 当这个键的值被设置为 `false`,GRUB 菜单中就会为每个已安装的内核创建一个恢复条目。当设置为 `true` 时就不会创建任何恢复条目。但不管这个设置怎样,最后的内核条目总是一个 `rescue` 选项。不过在 rescue 选项中我遇到了一个问题,下面我会详细介绍。 + +还有一些你可能觉得有用但我没有在这里介绍的键。它们的描述可以在 [GRUB 手册 2][8] 的 5.1 章节找到。 + +### 生成 grub.cfg + +完成所需的配置之后,就需要生成 `/boot/grub2/grub.cfg` 文件。这通过下面的命令完成。 + +``` +grub2-mkconfig > /boot/grub2/grub.cfg +``` + +这个命令按照顺序使用位于 `/etc/grub.d` 的配置文件构建 `grub.cfg` 文件,然后使用 grub 默认文件的内容修改输出以便获得最终所需的配置。`grub2-mkconfig` 命令会尝试定位所有已安装的内核并在 `grub.cfg` 文件的 `10_Linux` 部分新建条目。它还创建一个 `rescue` 条目提供一个用于从 Linux 不能启动的严重问题中恢复的方法。 + +强烈建议你不要手动编辑 `grub.cfg` 文件,因为任何对该文件的直接修改都会在下一次安装新内核或者手动运行 `grub2-mkconfig` 时被重写。 + +### 问题 + +我遇到一个如果没有意识到就可能导致严重后果的 GRUB2 问题。这个救援内核没有启动,反而启动了另外一个内核。我发现那是列表中索引为 1 的内核,也就是列表中的第二个内核。额外的测试发现不管使用原始的还是我生成的 `grub.cfg` 配置文件都会发生这个问题。我在虚拟机和真实硬件上都尝试过而且都发生了这个问题。我只测试了 Fedora 25,因此其它 Fedora 发行版本可能没有这个问题。 + +注意,从救援内核生成的 “recovery” 内核条目不能引导到维护模式。 + +我推荐将 grub 默认文件中 `GRUB_DISABLE_RECOVERY` 的值更改为 “false”,然后生成你自己的 `grub.cfg`。这会在 GRUB 菜单中为每个已安装的内核生成可用的恢复条目。这些恢复配置能像期望那样工作,从而从那些需要输入密码登录的内核条目中引导到运行级别 1,也就是进入(不需要密码的)单用户维护模式。你也可以按 `Ctrl-D` 继续正常的引导进入默认运行级别。 + +### 总结 + +GRUB 是引导 Linux 计算机到可用状态过程的一系列事件中,发生在 BIOS 之后的第一步。理解如何配置 GRUB 对于恢复或者处理多种类型的问题非常重要。 + +这么多年来我多次不得不引导到恢复或者救援模式以便解决多种类型的问题。其中的一些问题确实是类似 `/etc/fstab` 或其它配置文件中不恰当条目导致的引导问题,也有一些是由于应用程序或者系统软件和最新的内核不兼容的问题。硬件兼容性问题也可能妨碍特定的内核启动。 + +我希望这些信息能对你开启 GRUB 配置之旅有所帮助。 + +( 题图 : Internet Archive [Book][5] [Images][6]. Opensource.com 修改。 CC BY-SA 4.0) + +-------------------------------------------------------------------------------- + +作者简介: + +David Both - David Both 是一个居住在 Raleigh,北卡罗来纳州的 Linux 和开源倡导者。他在 IT 界已经有超过 40 年,并在他工作的 IBM 执教 OS/2 20 多年。在 IBM 的时候,他在 1981 年开设了第一个最初 IBM 个人电脑的培训课程。他在红帽教授过 RHCE 课程并在 MCI Worldcom、 Cisco、 和北卡罗来纳州工作过。他已经在 Linux 和开源软件方面工作将近 20 年。 + + +---------------- + +via: https://opensource.com/article/17/3/introduction-grub2-configuration-linux + +作者:[David Both][a] +译者:[ictlyh](https://github.com/ictlyh) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/users/dboth +[1]:https://opensource.com/article/17/2/linux-boot-and-startup +[2]:https://opensource.com/article/17/2/linux-boot-and-startup +[3]:https://en.wikipedia.org/wiki/Sed +[4]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux?rate=QrIzRpQ3YhewYlBD0AFp0JiF133SvhyAq783LOxjr4c +[5]:https://www.flickr.com/photos/internetarchivebookimages/14746482994/in/photolist-ot6zCN-odgbDq-orm48o-otifuv-otdyWa-ouDjnZ-otGT2L-odYVqY-otmff7-otGamG-otnmSg-rxnhoq-orTmKf-otUn6k-otBg1e-Gm6FEf-x4Fh64-otUcGR-wcXsxg-tLTN9R-otrWYV-otnyUE-iaaBKz-ovcPPi-ovokCg-ov4pwM-x8Tdf1-hT5mYr-otb75b-8Zk6XR-vtefQ7-vtehjQ-xhhN9r-vdXhWm-xFBgtQ-vdXdJU-vvTH6R-uyG5rH-vuZChC-xhhGii-vvU5Uv-vvTNpB-vvxqsV-xyN2Ai-vdXcFw-vdXuNC-wBMhes-xxYmxu-vdXxwS-vvU8Zt +[6]:https://www.flickr.com/photos/internetarchivebookimages/14774719031/in/photolist-ovAie2-otPK99-xtDX7p-tmxqWf-ow3i43-odd68o-xUPaxW-yHCtWi-wZVsrD-DExW5g-BrzB7b-CmMpC9-oy4hyF-x3UDWA-ow1m4A-x1ij7w-tBdz9a-tQMoRm-wn3tdw-oegTJz-owgrs2-rtpeX1-vNN6g9-owemNT-x3o3pX-wiJyEs-CGCC4W-owg22q-oeT71w-w6PRMn-Ds8gyR-x2Aodm-owoJQm-owtGp9-qVxppC-xM3Gw7-owgV5J-ou9WEs-wihHtF-CRmosE-uk9vB3-wiKdW6-oeGKq3-oeFS4f-x5AZtd-w6PNuv-xgkofr-wZx1gJ-EaYPED-oxCbFP +[7]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration +[8]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration +[9]:https://opensource.com/user/14106/feed +[10]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux#comments +[11]:https://opensource.com/users/dboth diff --git a/published/20170317 How to control GPIO pins and operate relays with the Raspberry Pi.md b/published/20170317 How to control GPIO pins and operate relays with the Raspberry Pi.md new file mode 100644 index 0000000000..a7928f5f68 --- /dev/null +++ b/published/20170317 How to control GPIO pins and operate relays with the Raspberry Pi.md @@ -0,0 +1,454 @@ +如何用树莓派控制 GOIO 引脚并操作继电器 +========================================== + +> 学习如何用 PHP 和温度传感器实现树莓派控制 GPIO 并操作继电器 + + ![How to control GPIO pins and operate relays with the Raspberry Pi](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/raspberry_pi_day_lead_0.jpeg?itok=lCxmviRD "How to control GPIO pins and operate relays with the Raspberry Pi") + +你是否曾经想知道怎样使用手机或者电脑在任何地方控制你的风扇和灯等一些家用电器? + +我现在想控制我的圣诞彩灯,是使用手机呢,还是使用平板电脑呢,或者是使用笔记本电脑呢?都不是,而是仅仅使用一个树莓派。让我来告诉你如何使用 PHP 和温度传感器实现树莓派控制 GPIO 引脚并操作继电器。我使用 AJAX 把它们整合在了一起。 + +### 硬件要求: + +* 树莓派 +* 安装有 Raspbian 系统的 SD 卡(任何一张 SD 卡都可以,但是我更偏向使用大小为 32GB 等级为 class 10 的 SD 卡) +* 电源适配器 +* 跳线(母对母跳线和公转母跳线) +* 继电器板(我使用一个用于 12V 继电器的继电器板) +* DS18B20 温度传感器 +* 树莓派的 Wi-Fi 适配器 +* 路由器(为了访问互联网,你需要有一个拥有端口转发的路由器) +* 10KΩ 的电阻 + +### 软件要求: + +* 下载并安装 Raspbian 系统到你的 SD 卡 +* 有效的互联网连接 +* Apache web 服务器 +* PHP +* WiringPi +* 基于 Mac 或者 Windows 的 SSH 客户端 + +### 一般的配置和设置 + +1、 插入 SD 卡到树莓派,然后使用以太网网线将它连接到路由器; + +2、 连接 WiFi 适配器; + +3、 使用 SSH 方式登录到树莓派,然后使用下面的命令编辑 `interfaces` 文件: + +``` +sudo nano /etc/network/interfaces +``` + +这个命令会用一个叫做 `nano` 的编辑器打开这个文件。它是一个非常简单又易于使用的文本编辑器。如果你不熟悉基 Linux 的操作系统,可以使用键盘上的方向键来操作。 + +用 `nano` 打开这个文件后,你会看到这样一个界面: + +![File editor nano](https://opensource.com/sites/default/files/putty_0.png "File editor nano") + +4、要配置你的无线网络,按照下面所示修改这个文件: + +``` +iface lo inet loopback +iface eth0 inet dhcp +allow-hotplug wlan0 +auto wlan0 +iface wlan0 inet dhcp + wpa-ssid "Your Network SSID" + wpa-psk "Your Password" +``` + +5、 按 `CTRL+O` 保存,然后按 `CTRL+X` 退出编辑器。 + +到目前为止,一切都已经配置完成,接下来你需要做的就是使用命令重新加载网络: + +``` +sudo service networking reload +``` + +(警告:如果你是使用远程连接的方式连接的树莓派,连接将会中断。) + +### 软件配置 + +#### 安装 Apache web 服务器 + +Apache 是一个受欢迎的服务器应用,你可以在树莓派安装这个程序让它提供网页服务。Apache 原本就可以通过 HTTP 方式提供 HTML 文件服务,添加其他模块后,Apache 还可以使用像 PHP 这样的脚本语言来提供动态网页的服务。 + +可以在命令行输入下面命令安装 Apache: + +``` +sudo apt-get install apache2 -y +``` + +安装完成后,可以在浏览器地址栏输入树莓派的 IP 地址来测试 web 服务器。如果你可以获得下面图片的内容,说明你已经成功地安装并设置好了你的服务器。 + +![Successful server setup](https://opensource.com/sites/default/files/itworks.png "Successful server setup") + +要改变这个默认的页面和添加你自己的 html 文件,进入 `var/www/html` 目录: + +``` +cd /var/www/html +``` + +添加一些文件来测试是否成功。 + +#### 安装 PHP + +PHP 是一个预处理器,这意味着它是当服务器收到网页请求时才会运行的一段代码。它开始运行,处理网页上需要被显示的内容,然后把网页发送给浏览器。不像静态的 HTML,PHP 在不同的环境下可以显示不同的内容。其他的语言也可以做到这一点,但是由于 WordPress 是用 PHP 编写的,有些时候你需要使用它。PHP 是 web 上一种非常受欢迎的语言,像 Facebok 和 Wikipeadia 这样的大型项目都是用 PHP 编写的。 + +使用下面的命令安装 PHP 和 Apache 软件包: + +``` +sudo apt-get install php5 libapache2-mod-php5 -y +``` + +#### 测试 PHP + +创建文件 `index.php`: + +``` +sudo nano index.php +``` + +在里面写入一些 PHP 内容: + +``` + +``` + +保存文件,接下来删除 `index.html`,因为它比 `index.php` 的优先级更高: + +``` +sudo rm index.html +``` + +刷新你的浏览器,你会看到 “hello world”。这并不是动态的,但是它仍然由 PHP 提供服务。如果你在上面看到提原始的 PHP 文件而不是“hello world”,重新加载和重启 Apahce(LCTT 译注,重启即可): + +``` +sudo /etc/init.d/apache2 reload +sudo /etc/init.d/apache2 restart +``` + +#### 安装 WiringPi + +为了可以对代码的更改进行跟踪,WiringPi 的维护采用 git。但假如你因为某些原因而没法使用 git,还有一种可以替代的方案。(通常你的防火墙会把你隔离开来,所以请先检查一下你的防火墙的设置情况!) + +如果你还没有安装 git,那么在 Debian 及其衍生版本中(比如 Raspbian),你可以这样安装它: + +``` +sudo apt-get install git-core +``` + +若是你遇到了一些错误,请确保你的树莓派是最新版本的 Raspbian 系统: + +``` +sudo apt-get update sudo apt-get upgrade +``` + +使用 git 获取最 WiringPi: + +``` +sudo git clone git://git.drogon.net/wiringPi +``` + +如果你之前已经使用过 clone 操作,那么可以使用下面命令: + +``` +cd wiringPi && git pull origin +``` + +这个命令会将会获取更新的版本,你然后可以重新运行下面的构建脚本。 + +有一个新的简化的脚本来构建和安装: + +``` +cd wiringPi && ./build +``` + +这个新的构建脚本将会为你完成编译和安装 WiringPi。它曾一度需要使用 `sudo` 命令,所以在运行这它之前你可能需要检查一下这个脚本。 + +#### 测试 WiringPi + +运行 `gpio` 命令来检查安装成功与否: + +``` +gpio -v gpio readall +``` + +这将给你一些信心,软件运行良好。 + +#### 连接 DS18B20 传感器到树莓派 + +* 传感器上的黑线用于 GND。 +* 红线用于 VCC。 +* 黄线是 GPIO 线。 + +![GPIO image](https://opensource.com/sites/default/files/gpio_0.png "GPIO image") + +连线: + + * VCC 连接 3V 的 1 号引脚。 + * GPIO 线连接 7 号引脚(GPIO4)。 + * 地线连接 GND 的 9 号引脚。 + +#### 软件配置 + +为了用 PHP 使用 DS18B20 温度传感器模块,你需要执行下面的命令来激活用于树莓派上 GPIO 引脚和 DS18B20 的内核模块: + +``` +sudo modprobe w1-gpio +sudo modprobe w1-therm +``` + +你不想每次 Raspberry 重启后都手动执行上述命令,所以你想每次开机能自动启动这些模块。可以在文件 `/etc/modules` 中添加下面的命令行来做到: + +``` +sudo nano /etc/modules/ +``` + +添加下面的命令行到它里面: + +``` +w1-gpio +w1-therm +``` + +为了测试,输入: + +``` +cd /sys/bus/w1/devices/ +``` + +现在输入 `ls`。 + +你会看到你的设备信息。在设备驱动程序中,你的 DS18B20 传感器应该作为一串字母和数字被列出。在本例中,设备被记录为 `28-000005e2fdc3`。然后你需要使用 `cd` 命令来访问传感器,用你自己的序列号替代我的: `cd 28-000005e2fdc3`。 + +DS18B20 会周期性的将数据写入文件 `w1_slave`,所以你只需要使用命令 `cat`来读出数据: `cat w1_slave`。 + +这会生成下面的两行文本,输出中 `t=` 表示摄氏单位的温度。在前两位数后面加上一个小数点(例如,我收到的温度读数是 30.125 摄氏度)。 + +### 连接继电器 + +1、 取两根跳线,把其中一根连接到树莓派上的 GPIO24(18 号引脚),另一根连接 GND 引脚。你可以参考下面这张图。 + +2、 现在将跳线的另一端连接到继电器板。GND 连接到继电器上的 GND,GPIO 输出线连接到继电器的通道引脚号,这取决于你正使用的继电器型号。记住,将树莓派上的 GND 与继电器上的 GND 连接连接起来,树莓派上的 GPIO 输出连接继电器上的输入引脚。 + +![Headers](https://opensource.com/sites/default/files/headers.png "Headers") + +注意!将继电器连接树莓派的时候小心一些,因为它可能会导致电流回流,这会造成短路。 + +3、 现在将电源连接继电器,可以使用 12V 的电源适配器,也可以将 VCC 引脚连接到什么破上的 3.3V 或 5.5V 引脚。 + +### 使用 PHP 控制继电器 + +让我们先写一个借助于 WiringPi 软件用来控制 Paspberry Pi 上 GPIO 引脚的 PHP 脚本。 + +1、在 Apache 服务器的网站根目录下创建一个文件,使用下面命令切换到该目录: + +``` +cd /var/www/html +``` + +2、 新建一个叫 `Home` 的文件夹: + +``` +sudo mkdir Home +``` + +3、 新建一个叫 `on.php`的脚本 + +``` +sudo nano on.php +``` + +4、 在脚本中加入下面的代码: + +``` + +``` + +5、 使用 `CTRL+O` 保存文件,`CTRL+X` 退出。 + +上面的代码中,你在第一行使用命令将 24 号 GPIO引脚设置为 output 模式: + +``` +system("gpio-g mode 24 out") ; +``` + +在第二行,你使用 `1` 将 24 号引脚 GPIO 打开,在二进制中"1"表示打开,"0"表示关闭。 + +6、 为了关闭继电器,可以创建另外一个 `off.php` 文件,并用 `0` 替换 `1`。 + +``` + +``` + +7、 如果你已经将继电器连接了树莓派,可以在浏览器中输入你的树莓派的 IP 地址,并在后面加上目录名和文件名来进行访问: + +``` +http://{IPADDRESS}/home/on.php +``` + +这将会打开继电器。 + +8、 要关闭它,可以访问叫 `off.php` 的文件: + +``` +http://{IPADDRESS}/home/off.php +``` + +现在你需要能够在一个单独的页面来控制这两样事情,而不用单独的刷新或者访问这两个页面。你可以使用 AJAX 来完成。 + +9、 新建一个 HTML 文件,并在其中加入下面代码: + +``` +[html + php + ajax codeblock] + + + + + + + + - - -``` - -10\. 保存文件,进入你的web 浏览器目录,然后打开那个网页。你会看到两个按钮,它们可以打开和关闭灯泡。基于同样的想法,你还可以使用bootstrap和CSS来创建一个更加漂亮的web界面。 - -### 在这个网页上观察温度 - -1\. 新建一个temperature.php的文件: - -``` -sudo nano temperature.php -``` - -2\. 在文件中加入下面的代码,用你自己的设备ID替换10-000802292522: - -``` - -``` - -3\. 打开你刚刚创建的HTML文件,并创建一个新的带有 **id** “screen”的 `
`标签 -``` -
-``` - -4\. 在这个标签后或者这个文档的尾部下面的代码: - -``` - -``` - -其中,`#screen`是标签`
`的`id`,你想在它里面显示温度。它会每隔1000毫秒加载一次`temperature.php`文件。 - -我使用了bootstrap框架来制作一个漂亮的面板来显示温度,你还可以加入多个icons和 glyphicons让网页更有吸引力。 - -这只是一个控制继电器板并显示温度的基础的系统,你可以通过创建基于定时和从恒温器读数等基于事件触发来进一步地对系统进行开发。 - --------------------------------------------------------------------------------- - - -作者简介: - -Abdul Hannan Mustajab: 我17岁,生活在印度。我正在追求科学,数学和计算机科学方面的教育。我在spunkytechnology.com上发表关于我的项目的博客。我一直在对使用不同的微控制器和电路板的基于物联网的AI进行研究。 - - -via: https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi - -作者:[ Abdul Hannan Mustajab][a] -译者:[译者ID](https://github.com/zhousiyu325) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]:https://opensource.com/users/mustajabhannan -[1]:http://www.php.net/system -[2]:http://www.php.net/system -[3]:http://www.php.net/system -[4]:http://www.php.net/system -[5]:http://www.php.net/system -[6]:http://www.php.net/file -[7]:http://www.php.net/explode -[8]:http://www.php.net/number_format -[9]:https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi?rate=RX8QqLzmUb_wEeLw0Ee0UYdp1ehVokKZ-JbbJK_Cn5M -[10]:https://opensource.com/user/123336/feed -[11]:https://opensource.com/users/mustajabhannan - - diff --git a/sources/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md b/translated/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md similarity index 51% rename from sources/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md rename to translated/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md index 7bc19ba829..937ac5113e 100644 --- a/sources/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md +++ b/translated/tech/20170506 Writing a Linux Debugger Part 6 Source-level stepping.md @@ -1,40 +1,40 @@ -ictlyh Translating -Writing a Linux Debugger Part 6: Source-level stepping +开发 Linux 调试器第六部分:源码级逐步执行 ============================================================ -A couple of posts ago we learned about DWARF information and how it lets us relate the machine code to the high-level source. This time we’ll be putting this knowledge into practice by adding source-level stepping to our debugger. +在前几篇博文中我们学习了 DWARF 信息以及它如何使我们将机器码和上层源码联系起来。这一次我们通过为我们的调试器添加源码级逐步调试将该知识应用于实际。 * * * -### Series index +### 系列文章索引 -These links will go live as the rest of the posts are released. +随着后面文章的发布,这些链接会逐渐生效。 -1. [Setup][1] +1. [启动][1] -2. [Breakpoints][2] +2. [断点][2] -3. [Registers and memory][3] +3. [寄存器和内存][3] -4. [Elves and dwarves][4] +4. [Elves 和 dwarves][4] -5. [Source and signals][5] +5. [源码和信号][5] -6. [Source-level stepping][6] +6. [源码级逐步执行][6] -7. Source-level breakpoints +7. 源码级断点 -8. Stack unwinding +8. 调用栈展开 -9. Reading variables +9. 读取变量 -10. Next steps +10. 下一步 +译者注:ELF([Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format "Executable and Linkable Format") 可执行文件格式),DWARF(一种广泛使用的调试数据格式,参考 [WIKI](https://en.wikipedia.org/wiki/DWARF "DWARF WIKI")) * * * -### Exposing instruction-level stepping +### 暴露指令级逐步执行 -But we’re getting ahead of ourselves. First let’s expose instruction-level single stepping through the user interface. I decided to split it between a `single_step_instruction` which can be used by other parts of the code, and a `single_step_instruction_with_breakpoint_check` which ensures that any breakpoints are disabled and re-enabled. +我们已经超越了自己。首先让我们通过用户接口暴露指令级单步执行。我决定将它切分为能被其它部分代码利用的 `single_step_instruction` 和确保是否启用了某个断点的 `single_step_instruction_with_breakpoint_check`。 ``` void debugger::single_step_instruction() { @@ -43,7 +43,7 @@ void debugger::single_step_instruction() { } void debugger::single_step_instruction_with_breakpoint_check() { - //first, check to see if we need to disable and enable a breakpoint + //首先,检查我们是否需要停用或者启用某个断点 if (m_breakpoints.count(get_pc())) { step_over_breakpoint(); } @@ -53,7 +53,7 @@ void debugger::single_step_instruction_with_breakpoint_check() { } ``` -As usual, another command gets lumped into our `handle_command` function: +正如以往,另一个命令被集成到我们的 `handle_command` 函数: ``` else if(is_prefix(command, "stepi")) { @@ -63,15 +63,15 @@ else if(is_prefix(command, "stepi")) { } ``` -With these functions added we can begin to implement our source-level stepping functions. +利用新增的这些函数我们可以开始实现我们的源码级逐步执行函数。 * * * -### Implementing the steps +### 实现逐步执行 -We’re going to write very simple versions of these functions, but real debuggers tend to have the concept of a  _thread plan_  which encapsulates all of the stepping information. For example, a debugger might have some complex logic to determine breakpoint sites, then have some callback which determines whether or not the step operation has completed. This is a lot of infrastructure to get in place, so we’ll just take a naive approach. We might end up accidentally stepping over breakpoints, but you can spend some time getting all the details right if you like. +我们打算编写这些函数非常简单的版本,但真正的调试器有 _thread plan_ 的概念,它封装了所有的单步信息。例如,调试器可能有一些复杂的逻辑去决定断点的位置,然后有一些回调函数用于判断单步操作是否完成。这其中有非常多的基础设施,我们只采用一种朴素的方法。我们可能会意外地跳过断点,但如果你愿意的话,你可以花一些时间把所有的细节都处理好。 -For `step_out`, we’ll just set a breakpoint at the return address of the function and continue. I don’t want to get into the details of stack unwinding yet – that’ll come in a later part – but it suffices to say for now that the return address is stored 8 bytes after the start of a stack frame. So we’ll just read the frame pointer and read a word of memory at the relevant address: +对于跳出`step_out`,我们只是在函数的返回地址处设一个断点然后继续执行。我暂时还不想考虑调用栈展开的细节 - 这些都会在后面的部分介绍 - 但可以说返回地址就保存在栈帧开始的后 8 个字节中。因此我们会读取栈指针然后在内存相对应的地址读取值: ``` void debugger::step_out() { @@ -92,7 +92,7 @@ void debugger::step_out() { } ``` -`remove_breakpoint` is a little helper function: +`remove_breakpoint` 是一个小的帮助函数: ``` void debugger::remove_breakpoint(std::intptr_t addr) { @@ -103,7 +103,7 @@ void debugger::remove_breakpoint(std::intptr_t addr) { } ``` -Next is `step_in`. A simple algorithm is to just keep on stepping over instructions until we get to a new line. +接下来是跳入`step_in`。一个简单的算法是继续逐步执行指令直到新的一行。 ``` void debugger::step_in() { @@ -118,7 +118,7 @@ void debugger::step_in() { } ``` -`step_over` is the most difficult of the three for us. Conceptually, the solution is to just set a breakpoint at the next source line, but what is the next source line? It might not be the one directly succeeding the current line, as we could be in a loop, or some conditional construct. Real debuggers will often examine what instruction is being executed and work out all of the possible branch targets, then set breakpoints on all of them. I’d rather not implement or integrate an x86 instruction emulator for such a small project, so we’ll need to come up with a simpler solution. A couple of horrible options are to just keep stepping until we’re at a new line in the current function, or to just set a breakpoint at every line in the current function. The former would be ridiculously inefficient if we’re stepping over a function call, as we’d need to single step through every single instruction in that call graph, so I’ll go for the second solution. +跳过`step_over` 对于我们来说是三个中最难的。理论上,解决方法就是在下一行源码中设置一个断点,但下一行源码是什么呢?它可能不是当前行后续的那一行,因为我们可能处于一个循环、或者某种条件结构之中。真正的调试器一般会检查当前正在执行什么指令然后计算出所有可能的分支目标,然后在所有分支目标中设置断点。对于一个小的项目,我不打算实现或者集成一个 x86 指令模拟器,因此我们要想一个更简单的解决办法。有几个可怕的选项,一个是一直逐步执行直到当前函数新的一行,或者在当前函数的每一行都设置一个断点。如果我们是要跳过一个函数调用,前者将会相当的低效,因为我们需要逐步执行那个调用图中的每个指令,因此我会采用第二种方法。 ``` void debugger::step_over() { @@ -154,7 +154,7 @@ void debugger::step_over() { } ``` -This function is a bit more complex, so I’ll break it down a bit. +这个函数有一点复杂,我们将它拆开来看。 ``` auto func = get_function_from_pc(get_pc()); @@ -162,7 +162,7 @@ This function is a bit more complex, so I’ll break it down a bit. auto func_end = at_high_pc(func); ``` -`at_low_pc` and `at_high_pc` are functions from `libelfin` which will get us the low and high PC values for the given function DIE. +`at_low_pc` 和 `at_high_pc` 是 `libelfin` 中的函数,它们能给我们指定函数 DWARF 信息条目的最小和最大程序计数器值。 ``` auto line = get_line_entry_from_pc(func_entry); @@ -179,7 +179,7 @@ This function is a bit more complex, so I’ll break it down a bit. } ``` -We’ll need to remove any breakpoints we set so that they don’t leak out of our step function, so we keep track of them in a `std::vector`. To set all the breakpoints, we loop over the line table entries until we hit one which is outside the range of our function. For each one, we make sure that it’s not the line we are currently on, and that there’s not already a breakpoint set at that location. +我们需要移除我们设置的所有断点,以便不会泄露我们的逐步执行函数,为此我们把它们保存到一个 `std::vector` 中。为了设置所有断点,我们循环遍历行表条目直到找到一个不在我们函数范围内的。对于每一个,我们都要确保它不是我们当前所在的行,而且在这个位置还没有设置任何断点。 ``` auto frame_pointer = get_register_value(m_pid, reg::rbp); @@ -190,7 +190,7 @@ We’ll need to remove any breakpoints we set so that they don’t leak out of o } ``` -Here we are setting a breakpoint on the return address of the function, just like in `step_out`. +这里我们在函数的返回地址处设置一个断点,正如跳出 `step_out`。 ``` continue_execution(); @@ -200,11 +200,11 @@ Here we are setting a breakpoint on the return address of the function, just lik } ``` -Finally, we continue until one of those breakpoints has been hit, then remove all the temporary breakpoints we set. +最后,我们继续执行直到命中它们中的其中一个断点,然后移除所有我们设置的临时断点。 -It ain’t pretty, but it’ll do for now. +它并不美观,但暂时先这样吧。 -Of course, we also need to add this new functionality to our UI: +当然,我们还需要将这个新功能添加到用户界面: ``` else if(is_prefix(command, "step")) { @@ -220,9 +220,9 @@ Of course, we also need to add this new functionality to our UI: * * * -### Testing it out +### 测试 -I tested out my implementation with a simple program which calls a bunch of different functions: +我通过实现一个调用一系列不同函数的简单函数来进行测试: ``` void a() { @@ -259,16 +259,16 @@ int main() { } ``` -You should be able to set a breakpoint on the address of `main` and then in, over, and out all over the program. Expect things to break if you try to step out of `main` or into some dynamically linked library. +你应该可以在 `main` 地址处设置一个断点,然后在整个程序中跳入、跳过、跳出函数。如果你尝试跳出 `main` 函数或者跳入任何动态链接库,就会出现意料之外的事情。 -You can find the code for this post [here][7]. Next time we’ll use our newfound DWARF expertise to implement source-level breakpoints.   +你可以在[这里][7]找到这篇博文的相关代码。下次我们会利用我们新的 DWARF 技巧来实现源码级断点。 -------------------------------------------------------------------------------- via: https://blog.tartanllama.xyz/c++/2017/05/06/writing-a-linux-debugger-dwarf-step/ 作者:[TartanLlama ][a] -译者:[译者ID](https://github.com/译者ID) +译者:[ictlyh](https://github.com/ictlyh) 校对:[校对者ID](https://github.com/校对者ID) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/translated/tech/20170508 8 ways to get started with open source hardware.md b/translated/tech/20170508 8 ways to get started with open source hardware.md new file mode 100644 index 0000000000..235f1a8a61 --- /dev/null +++ b/translated/tech/20170508 8 ways to get started with open source hardware.md @@ -0,0 +1,99 @@ +8 种方式开始使用开源硬件 +============================================================ + +### 制造自己的硬件比以往任何时候都更容易,更便宜。以下是你需要设计,构建和测试你的第一块电路板。 + + +![8 ways to get started with open source hardware](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/hardware_hammer_sign.jpg?itok=vh76LBib "8 ways to get started with open source hardware") +>图片提供: Thomas Hawk on [Flickr][11]. [CC BY-NC 2.0][12]. 由 Opensource.com 修改 + +著名的计算机科学家 Alan Kay 曾经说过:“认真对待软件的人应该制造它们自己的硬件。” 我认为今天就如 1982 年他所说的一样真实。然而,现在和那时之间的变化是硬件变得越来越快,越来越小,最重要的是:更便宜。 现在可以用 5 美元购买一台完整的电脑。 + +随着大公司降低自己产品的价格,它发展了一个能够生产生产级硬件的制造业生态系统,它的成本足够便宜,并且达到了普通人都可以接受的程度。这种可用性以及可负担性正在帮助推动诸如众筹和制造商运动之类的事情,但他们也让更多的个人能够通过开源硬件参与开源。 + +探索开放硬件 + +* [什么是开放硬件?][1] + +* [什么是树莓派?][2] + +* [什么是 Arduino?][3] + +* [我们最新的开放硬件文章][4] + +什么是或者不是开源硬件有很多区别,但是开源硬件联盟(OSHWA)定义了一个大多数人同意的定义,如果你熟悉开源软件,这不会听上去太奇怪: + + +> “开源硬件(OSHW)是有形人工机器、设备或者其他物理东西的术语-其设计像公众发布,任何人可以制造、修改、分发并使用那些。” + +周围已经有很多开源硬件了。你可能没有注意到你在使用的主板可能实际上是开放的硬件。从[低调]但通用的[Arduino][13],一直到像 [BeagleBone][14] family 和 [C.H.I.P.][15] 计算机这样的完整功能的电脑,这有很多开放硬件的例子,还有更多的在设计中。 + +硬件可能很复杂,对初学者而言为什么设计需要这些有时不太明显。但开源硬件使你不仅可以看到工作示例,还可以更改这些设计,或者在你自己的设计中复制所需的部分,就如复制和粘贴一样简单。 + +### 我该如何开始? + +我们先要指出硬件很难,它很复杂,有时是深奥的,你可能用到的工具并不总是最人性化的。任何一个玩微处理器的时间足够长的人都可以证明有一种可能:你会烧坏一些东西,看到神奇的烟雾在某个时刻冒出来。没关系,我们都做过,有些人还会反复做,因为我们在做一件事情的前 100 次时都不会得到教训,但不让让这阻碍你:当做错事情时,你会学到教训,而且你将来还会有有趣的故事告诉别人。 + +### 建模 + +首先要做的是开始使用现有的电路板,跳线、面包板以及你要连接的任何设备来建模你想要做的事情。在许多情况下,最简单的事情就是在板上添加更多的 LED,并以新颖的方式让它们闪烁。这是一个很好的出原型的方式,也是一个很常见的事情。它看上去不漂亮,你可能会发现你的线接错了,但这些都是原型 - 你只是想证明硬件可以工作。当硬件不工作时,一定要仔细检查一切,不要害怕寻求帮助 - 有时第二双眼睛会发现你奇怪的接地短路。 + +### 设计 + +当你弄清楚你想要构建的硬件,现在是时候把你的想法从跳线和面包板变成实际的设计了。这时事情会变得让人气馁,但是从小的开始,事情上,可以从熟悉加工和流程这样非常小的开始,所以为什么不制作一块带有 LED 和电池的印刷电路板?认真地说,这可能听起来过于简单,但在这里有很多新的基础要了解。 + +1. **找到一个电子设计自动化(EDA)工具来使用。** 这有很多好的开源软件可以选择,但是它们并不总是用户友好的。[Fritzing][5]、[gEDA][6] 还有 [KiCad ][7] 都是开源的,并以可用性升序排序。如果你想要尝试更多的商业软件,那么还有一些其他的选择。Eagle 有受限的免费版本使用,有许多的开源硬件是用它设计的。 + +2. **在 EDA 工具中设计你的电路板。** 依据你选择的工具,这可能会非常快,或者可能是学习如何设计的很好的练习。这是我建议从小的硬件开始的原因之一。一个带 LDED 的电路可以如一块电池、一个电阻、一个 LED 一样简单。电路图非常简单,并且布局也会非常小、非常简单。 + +3. **为制造导出设计。** 这与列表中的下一件事情紧密相连,但如果你以前没有这样做,这也可能是一个令人困惑的过程。当你在导出时,你会有很多细节需要调整,并且需要以某种方式导出以便电路板工厂能确切知道你要做的。 + +4. **找到一个电路板工厂。** 有许多电路板工厂可以制作你的设计,并且一些比其他更加友好及有帮助。一个特别棒的地方是 [OSH Park][8],这些人非常友好并支持开源硬件。他们也有一个非常扎实的流程来确认你发送给它的就是会被制造的,所以他们值得一试。还有很多其他选择; 看看 [PCB Shopper][9],它可以让你比较不同实体 PCB 商家的价格、周转时间等等。 + +5. **等待。** 这或许是在制造你自己的电路板中最难的一部分了,因为它会花费时间将数字部分变成物理产品。计划好两周时间来拿到你的电路板。这是你继续下个项目的绝好时间,确保或获取你当前制造的所有部分,或者通常上尝试不要担心。你的第一块电路板是艰难的 - 你现在非常想要,但是保持耐心。 + +6. **修补并提升。** 一旦拿到你的板子,是时候上电测试了。如果你是以 LED 电路开始,那么它很容易调试,并且你会得到一些可以工作的东西。如果你有更复杂的电路,那么需要有条理并且有耐心。有时候电路不会工作,并且你需要用你的调试技能来追踪问题。 + +7. **最后,如果你做的是开源硬件,那就发布它。*** 我们谈论的是开源硬件,因此确保包含了一个许可,但是发布它、共享它,把它放在人们可以看见你所做的地方。你或许会想写一篇博客并提交到如 Hackaday 上面。 + +8. **最重要的是,玩得开心。** 坦白说,如果你在说一些事但是你不开心,你应该停止这样做。开源硬件可以很有趣,虽然有时是困难而且复杂的。但是不是一切都会正常。见鬼,我已经设计了一半的电路不工作,或者我(意外地)在电源和接地之间造成了 12 次短路。这些电路板是双层板:是的。我在这个过程中学到了一些东西:非常多,并且我不会再犯同样的错误。我会做出新的板子,但不是这些。(我会支持并盯着这些板子和它们的错误,悲伤的是,它们不会在我盯着它们时感到难受)。 + +build the hardware that they want—not the hardware they can get. +现在有许多的开源硬件,以及从中可以查看、复制、衍生,并且有很多信息使制造硬件变得简单。这就是开源硬件:一个社区的人们制造它们,共享它们,这样每个人可以制作他们自己的东西并构建他们想要的硬件 - 而不是他们可以得到的硬件。 + +-------------------------------------------------------------------------------- + + + +作者简介: + +John 'Warthog9' Hawley - John 在 VMWare 的开源项目办公室为上游开源项目工作。在以前的生活中,他曾在 MinnowBoard 开源硬件项目上工作,领导了 kernel.org 上的系统管理团队,并在桌面集群变得很酷之前构建了它们。为了乐趣,他构建了多个明星项目,一个受欢迎的英国电视节目 K-9 的复制品,在无人机的飞行计算机视觉处理中完成,设计并制作了一堆自己的硬件。 + +------------------------------------- + +via: https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware + +作者:[John 'Warthog9' Hawley ][a] +译者:[geekpi](https://github.com/geekpi) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware +[1]:https://opensource.com/resources/what-open-hardware?src=open_hardware_resources_menu +[2]:https://opensource.com/resources/what-raspberry-pi?src=open_hardware_resources_menu +[3]:https://opensource.com/resources/what-arduino?src=open_hardware_resources_menu +[4]:https://opensource.com/tags/hardware?src=open_hardware_resources_menu +[5]:http://fritzing.org/home/ +[6]:http://www.geda-project.org/ +[7]:http://kicad-pcb.org/ +[8]:https://oshpark.com/ +[9]:http://pcbshopper.com/ +[10]:https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware?rate=jPBGDIa2vBXW6kb837X8JWdjI2V47hZ4KecI8-GJBjQ +[11]:https://www.flickr.com/photos/thomashawk/3048157616/in/photolist-5DmB4E-BzrZ4-5aUXCN-nvBWYa-qbkwAq-fEFeDm-fuZxgC-dufA8D-oi8Npd-b6FiBp-7ChGA3-aSn7xK-7NXMyh-a9bQQr-5NG9W7-agCY7E-4QD9zm-7HLTtj-4uCiHy-bYUUtG +[12]:https://creativecommons.org/licenses/by-nc/2.0/ +[13]:https://opensource.com/node/20751 +[14]:https://opensource.com/node/35211 +[15]:https://opensource.com/node/24891 +[16]:https://opensource.com/user/130046/feed +[17]:https://opensource.com/users/warthog9 diff --git a/translated/tech/20170516 What's the point of DevOps.md b/translated/tech/20170516 What's the point of DevOps.md index 09cf043dad..6cca11ead5 100644 --- a/translated/tech/20170516 What's the point of DevOps.md +++ b/translated/tech/20170516 What's the point of DevOps.md @@ -1,31 +1,20 @@ DevOps 的意义 ======================================== -### 真正的组织文化变革有助于你弥合你原先认为无法跨过的鸿沟 +> 真正的组织文化变革有助于你弥合你原先认为无法跨过的鸿沟 ![What's the point of DevOps?](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUSINESS_creativity.png?itok=x2HTRKVW "What's the point of DevOps?") ->图片来源 : opensource.com -回想你最近一次尝试改掉一个个人习惯,你可能遇到过这样的情形,你需要改变你思考的方式并且让不习惯成为你身体的一部分。这很艰难,你只是试着改变 _你自己的_ 思维方式。 -所以你可能会努力让自己处于新的环境。新的环境实际上可帮助我们养成 _新的_ 习惯,它反过又会促成新的思维方式。 +回想你最近一次尝试改掉一个个人习惯的事情,你可能遇到过这样的情形,你需要改变你思考的方式并且改掉之前的习惯。这很艰难,你只是试着改变 _你自己的_ 思维方式而已。 -那就是能否成功改变的所在:看起来是那么回事,实际上它就是那么回事 -。你需要知道 _为什么_ 你正在改变和你正准备去 _哪儿_ (而不是仅仅知道你要怎么做),因为改变本身往往是短暂和短视的。 +所以你可能会努力让自己处于新的环境。新的环境实际上可帮助我们养成 _新的_ 习惯,它反过来又会促成新的思维方式。 -现在思考你的 IT 组织需要做出的改变。也许你正在考虑采用像 DevOps 这样的东西。这个我们称之为 “DevOps” 的东西有三个组件:人、流程和工具。人和流程是 _任何_ 组织的基础。因此,采用 DevOps 需要对大多数组织的核心进行根本性的改变,而不仅仅是学习新的工具。 +那就是能否成功改变的所在:看起来是那么回事,实际上它就是那么回事 。你需要知道 _为什么_ 你正在改变以及你的目的 _所在_ (而不是仅仅你要怎么做),因为改变本身往往是短暂和短视的。 -开放式组织资源: +现在想想你的 IT 组织需要做出的改变。也许你正在考虑采用像 DevOps 这样的东西。这个我们称之为 “DevOps” 的东西有三个组件:人、流程和工具。人和流程是 _任何_ 团体组织的基础。因此,采用 DevOps 需要对大多数组织的核心进行根本性的改变,而不仅仅是学习新的工具。 -* [下载开放式组织领导手册][1] - -* [下载开放式组织现场指南][2] - -* [什么是开放式组织?][3] - -* [什么是开放式决策][4] - -和其他改变一样,它也是短视的。如果您将注意力集中在改变作为单点解决方案——例如,“获得更好的工具进行报警”——你可能想出一个狭隘的问题。这种思维方式或许可以提供一套拥有更多铃声和口哨并且可以有一种可以更好地处理随叫随到的方式的的工具,但是它不能解决这样的实际问题:警报不能到达正确的团队,或者故障得不到解决,因为实际上没有人知道如何修复服务。 +和其他改变一样,它也是短视的。如果您将注意力集中在改变作为单点解决方案——例如,“获得更好的工具进行报警”——你可能想出一个狭隘的问题。这种思维方式或许可以提供一套拥有更多铃声和口哨并且可以有一种可以更好地处理随叫随到的方式的工具,但是它不能解决这样的实际问题:警报不能到达正确的团队,或者故障得不到解决,因为实际上没有人知道如何修复服务。 新的工具(或者至少一个新工具的想法)创造了一个时刻来谈论困扰你的团队对监控的评价的潜在问题。新工具让你能够做出更大的改变——信仰和做法的改变——它们作为你组织的基础而显得更加重要。 @@ -33,13 +22,13 @@ DevOps 的意义 ### 清除栅栏 -> 就改革而言,它不同于腐化。有一条明显且简单的原则,这个原则可能被称为悖论。 在这种情况下,存在某种制度或法律; 让我们说,为了简单起见,在一条路上架设了一个栅栏或门。 现代化的改革者们来到这儿,并说:“我看不到它的用处,让我们把它清除掉。”聪明的改革者会很好地回答:“如果你看不到它的用处,我肯定不会让你清除它,回去想想,然后你可以回来 告诉我你看到它的用处,我会允许你摧毁它."—G.K Chesterton, 1929 +> 就改革而言,它不同于腐化。有一条明显且简单的原则,这个原则可能被称为悖论。在这种情况下,存在某种制度或法律;让我们说,为了简单起见,在一条路上架设了一个栅栏或门。现代化的改革者们来到这儿,并说:“我看不到它的用处,让我们把它清除掉。”聪明的改革者会很好地回答:“如果你看不到它的用处,我肯定不会让你清除它,回去想想,然后你可以回来告诉我你看到它的用处,我会允许你摧毁它。” — G.K Chesterton, 1929 为了了解对 DevOps 的需求——它试图将传统意义上分开的开发部门和运维部门进行重新组合——我们首先必须明白这个分开是如何产生的。一旦我们"知道了它的用处",然后我们就会知道将它们分开是为了什么,并且在必要的时候可以取消分开。 今天我们没有一个单一的管理理论,但是我们可以将大多数现代管理理论的起源追溯到弗雷德里克·温斯洛·泰勒。泰勒是一名机械工程师,他创建了一个衡量钢厂工人效率的系统。泰勒认为,他可以对工厂的劳动者应用科学分析,不仅为了改进个人任务,还为了证明有一个可以发现的用来执行 _任何_ 任务最佳方法。 -我们可以很容易地画一个以 Taylor 为起源的历史树。基于泰勒早在18世纪80年代后期的研究而出现的时间运动研究和其他质量改进计划跨越20世纪20年代一直到今天,我们可以从中看到六西格玛、精益,等等一些。自上而下、指导式管理,再加上研究过程的有条理的方法,今天主宰主流商业文化。它主要侧重于把效率作为工人成功的测量标准。 +我们可以很容易地画一个以 Taylor 为起源的历史树。基于泰勒早在 18 世纪 80 年代后期的研究而出现的时间运动研究和其他质量改进计划跨越 20 世纪 20 年代一直到今天,我们可以从中看到六西格玛、精益,等等一些。自上而下、指导式管理,再加上研究过程的有条理的方法,今天主宰主流商业文化。它主要侧重于把效率作为工人成功的测量标准。 > “开发”和“运维”的分开不是因为人的原因,不同的技能,或者放在新员工头上的一顶魔术帽,它是 Taylor 和 Sloan 的理论的副产品。 @@ -47,15 +36,15 @@ DevOps 的意义 1920 年,通用公司正经历一场管理危机,或者说是缺乏管理的危机。Sloan 向董事会写了一份为通用汽车的多个部门提出了一个新的结构《组织研究》。这一新结构的核心概念是“集中管理下放业务”。与雪佛兰,凯迪拉克和别克等品牌相关的各个部门将独立运作,同时为中央管理层提供推动战略和控制财务的手段。 -在 Sloan 的建议下(以及后来就任CEO的指导),通用汽车在美国汽车工业中占据了主导地位。Sloan 的计划把一个处于灾难边缘公司创造成了一个非常成功的公司。从中间来看,自治单位是黑盒子,激励和目标被设置在顶层,而团队在底层推动。 +在 Sloan 的建议下(以及后来就任 CEO 的指导),通用汽车在美国汽车工业中占据了主导地位。Sloan 的计划把一个处于灾难边缘公司创造成了一个非常成功的公司。从中间来看,自治单位是黑盒子,激励和目标被设置在顶层,而团队在底层推动。 -泰勒思想的“最佳实践” ——标准、可互换和可重复的行为——仍然在今天的管理理念中占有一席之地,与斯隆公司结构的层次模式相结合,主导了僵化的部门分裂和孤岛以实现最大的控制。 +泰勒思想的“最佳实践”——标准、可互换和可重复的行为——仍然在今天的管理理念中占有一席之地,与斯隆公司结构的层次模式相结合,主导了僵化的部门分裂和孤岛以实现最大的控制。 我们可以指出几份管理研究来证明这一点,但商业文化不是通过阅读书籍而创造和传播的。组织文化是 *真实的* 人在 *实际的* 情形下执行推动文化规范的 *具体的* 行为的产物。这就是为何类似 Taylor 和 Sloan 的主张这样的事情变得固化而不可动摇的原因。 -技术部门投资就是一个例子。以下是这个周期是如何循环的:投资者只投资于他们认为可以实现 *他们的* 特定成功观点的公司。这个成功的模式并不一定源于公司本身(和它的特定的目标);它来自董事会对一家成功的公司 *应该* 如何看待的想法。许多投资者来自在经营企业的尝试和苦难中幸存下来的公司,因此他们对什么会使一个公司成功有 *不同的* 蓝图。他们为那些能够被教导模仿他们的成功模式的公司提供资金所以希望获得资金的公司学会模仿。 这样,初创公司孵化器就是一种重现理想的结构和文化的直接的方式。 +技术部门投资就是一个例子。以下是这个周期是如何循环的:投资者只投资于他们认为可以实现 *他们的* 特定成功观点的公司。这个成功的模式并不一定源于公司本身(和它的特定的目标);它来自董事会对一家成功的公司 *应该* 如何看待的想法。许多投资者来自在经营企业的尝试和苦难中幸存下来的公司,因此他们对什么会使一个公司成功有 *不同的* 蓝图。他们为那些能够被教导模仿他们的成功模式的公司提供资金,所以希望获得资金的公司学会模仿。这样,初创公司孵化器就是一种重现理想的结构和文化的直接的方式。 -开发和运维的分开是不是因为人原因,不同的技能,或者放在新员工头上的一顶魔术帽;它是 Taylor 和 Sloan 的理论的副产品。责任与人员之间的透明和不可渗透的界线是一个管理功能,同时也注重员工的工作效率。管理上的分开可以很容易的落在产品或者项目界线上,而不是技能上,但是通过今天的业务管理理论的历史告诉我们,基于技能的分组是“最好”的高效方式。 +开发和运维的分开是不是因为人的原因,不同的技能,或者放在新员工头上的一顶魔术帽;它是 Taylor 和 Sloan 的理论的副产品。责任与人员之间的透明和不可渗透的界线是一个管理功能,同时也注重员工的工作效率。管理上的分开可以很容易的落在产品或者项目界线上,而不是技能上,但是通过今天的业务管理理论的历史告诉我们,基于技能的分组是“最好”的高效方式。 不幸的是,那些界线造成了紧张局势,这些紧张局势是由不同的管理链出于不同的目标设定的相反目标的直接结果。例如: @@ -65,27 +54,27 @@ DevOps 的意义 * 打败竞争对手 ⟷ 保护收入 * 修复出现的问题 ⟷ 在问题出现之前就进行预防 -今天,我们可以看到组织的高层领导人越来越认识到,现有的商业文化(并扩大了它所产生的紧张局势)是一个严重的问题。在2016年的 Gartner 报告中,57%的受访者表示,文化变革是2020年之前企业面临的主要挑战之一。像作为一种影响组织变革的的手段的敏捷和DevOps这样的新方法的兴起反映了这一认识。"[shadow IT][7]" 的出现是硬币的反面;最近的估计有将近30%的 IT 支出在IT组织的控制之外。 +今天,我们可以看到组织的高层领导人越来越认识到,现有的商业文化(并扩大了它所产生的紧张局势)是一个严重的问题。在 2016 年的 Gartner 报告中,57% 的受访者表示,文化变革是 2020 年之前企业面临的主要挑战之一。像作为一种影响组织变革的手段的敏捷和DevOps这样的新方法的兴起反映了这一认识。"[shadow IT][7]" 的出现是硬币的反面;最近的估计有将近 30% 的 IT 支出在 IT 组织的控制之外。 这些只是企业正在面临的一些“文化担忧”。改变的必要性是明确的,但前进的道路仍然受到昨天的决定的约束。 ### 抵抗并不是没用的 -> "Bert Lance 认为如果他能让政府采纳一条简单的格言“如果东西还没损坏,那就别去修理它”,他就可以为山姆拯救三十亿。他解释说:“这是政府的麻烦:'修复没有损坏的东西,而不是修复已经损坏了的东西。'” — Nation's Business, 1977.5 +> Bert Lance 认为如果他能让政府采纳一条简单的格言“如果东西还没损坏,那就别去修理它”,他就可以为山姆拯救三十亿。他解释说:“这是政府的麻烦:‘修复没有损坏的东西,而不是修复已经损坏了的东西。’” — Nation's Business, 1977.5 -通常,改革是组织针对所出现的错误所做的应对。 在这个意义上说,如果紧张局势(即使逆境)是变革的正常催化剂,那么 *抵抗* 变化就是成功的指标。但是过分强调成功的道路会使组织变得僵硬、衰竭和独断。 重视有效结果的政策导航是这种不断增长的僵局的症状。重视有效结果的政策导航是这种不断增长的僵局的症状。 +通常,改革是组织针对所出现的错误所做的应对。在这个意义上说,如果紧张局势(即使逆境)是变革的正常催化剂,那么 *抵抗* 变化就是成功的指标。但是过分强调成功的道路会使组织变得僵硬、衰竭和独断。重视有效结果的政策导航是这种不断增长的僵局的症状。 -传统IT部门的成功加剧了 IT 仓库的墙壁。其他部门现在变成了"顾客",而不是同事。试图将 IT 从成本中心转移出来创建一个新的操作模式,它可以将 IT 与其他业务目标断开。这反过来又会对敏捷性造成限制,增加摩擦,降低反应能力。合作被搁置而支持“专家方向”。结果是一个孤立主义的观点,IT 只能带来更多的伤害而不是好处。 +传统 IT 部门的成功加剧了 IT 仓库的墙壁。其他部门现在变成了“顾客”,而不是同事。试图将 IT 从成本中心转移出来创建一个新的操作模式,它可以将 IT 与其他业务目标断开。这反过来又会对敏捷性造成限制,增加摩擦,降低反应能力。合作被搁置而支持“专家方向”。结果是一个孤立主义的观点,IT 只能带来更多的伤害而不是好处。 -正如“软件吃掉世界”,IT 越来越成为组织整体成功的核心。具有前瞻性的IT组织认识到这一点,并且已经对其战略规划进行了有意义的改变,而不是将改变视为恐惧。 +正如“软件吃掉世界”,IT 越来越成为组织整体成功的核心。具有前瞻性的 IT 组织认识到这一点,并且已经对其战略规划进行了有意义的改变,而不是将改变视为恐惧。 ->改革不仅仅只是重构组织,它也是关于跨越历史上不可跨越的鸿沟的新途径。 +> 改革不仅仅只是重构组织,它也是关于跨越历史上不可跨越的鸿沟的新途径。 -例如,Facebook与人类学家罗宾·邓巴(Robin Dunbar)就社会团体的方法进行了磋商,而且意识到这一点对公司成长的内部团体(不仅仅是网站的外部用户)的影响。扎波斯的文化得到了很多的赞誉,该组织创立了一个部门,专注于培养他人对于核心价值观和企业文化的看法。当然,这本书是 _The Open Organization_ 的姊妹篇, 一本描述被应用于管理的开放原则——透明度、参与度和社区——可以如何为我们快节奏的有连系的时代重塑组织。 +例如,Facebook 与人类学家罗宾·邓巴(Robin Dunbar)就社会团体的方法进行了磋商,而且意识到这一点对公司成长的内部团体(不仅仅是网站的外部用户)的影响。扎波斯的文化得到了很多的赞誉,该组织创立了一个部门,专注于培养他人对于核心价值观和企业文化的看法。当然,这本书是 _The Open Organization_ 的姊妹篇, 一本描述被应用于管理的开放原则——透明度、参与度和社区——可以如何为我们快节奏的有联系的时代重塑组织。 ### 决心改变 -> "如果外界的变化率超过了内部的变化率,那末日就不远了."—Jack Welch, 2004 +> “如果外界的变化率超过了内部的变化率,那末日就不远了。” — Jack Welch, 2004 一位同事曾经告诉我他可以只用 [Information Technology Infrastructure Library][9] 框架里面的词汇向一位项目经理解释 DevOps。 @@ -95,14 +84,15 @@ DevOps 的意义 这些也不是“最佳实例”,它们只是一种检查你自己的栅栏的方式。每个组织都会有独特的由他们内部人员创造的栅栏。一旦你“知道了它的用途”,你就可以决定它是需要拆解还是掌握。 -** 本文是 Opensource.com 即将推出的关于开放组织和IT文化指南的一部分。[你可以在这注册以便当它发布时收到通知][5] +** 本文是 Opensource.com 即将推出的关于开放组织和 IT 文化指南的一部分。[你可以在这注册以便当它发布时收到通知][5] +(题图 : opensource.com) -------------------------------------------------------------------------------- 作者简介: -Matt Micene——Matt Micene 是 Red Hat 公司的 Linux 和容器传播者。他在信息技术方面拥有超过15年的经验,从架构和系统设计到数据中心设计。他对关键技术(如容器,云计算和虚拟化)有深入的了解。他目前的重点是宣传红帽企业版Linux,以及操作系统如何与计算环境的新时代相关。 +Matt Micene——Matt Micene 是 Red Hat 公司的 Linux 和容器传播者。他在信息技术方面拥有超过 15 年的经验,从架构和系统设计到数据中心设计。他对关键技术(如容器,云计算和虚拟化)有深入的了解。他目前的重点是宣传红帽企业版 Linux,以及操作系统如何与计算环境的新时代相关。 ------------------------------------------ @@ -110,7 +100,7 @@ via: https://opensource.com/open-organization/17/5/what-is-the-point-of-DevOps 作者:[Matt Micene ][a] 译者:[zhousiyu325](https://github.com/zhousiyu325) -校对:[校对者ID](https://github.com/校对者ID) +校对:[apemost](https://github.com/apemost) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出