From 0daf03512cae4e1c5995963cbdf4e11f523fe048 Mon Sep 17 00:00:00 2001 From: wxy Date: Mon, 5 Mar 2018 18:23:12 +0800 Subject: [PATCH 01/26] PRF:20171017 What Are the Hidden Files in my Linux Home Directory For.md @MjSeven --- ...en Files in my Linux Home Directory For.md | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md b/translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md index 681dfe94a8..c221094e63 100644 --- a/translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md +++ b/translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md @@ -1,51 +1,46 @@ -我的 Linux 主目录中的隐藏文件是干什么用的? +我的 Linux 主目录中的隐藏文件是干什么用的? ====== ![](https://www.maketecheasier.com/assets/uploads/2017/06/hidden-files-linux-hero.png) -在你的 Linux 系统中,你可能会在主目录中存储大量文件和文件夹。但在这些文件下面,你知道你的主目录还附带了很多隐藏的文件和文件夹吗?如果你在主目录中运行 `ls -a`,你会发现一堆带有点前缀的隐藏文件和目录。这些隐藏的文件到底做了什么? +在 Linux 系统中,你可能会在主目录中存储了大量文件和文件夹。但在这些文件之外,你知道你的主目录还附带了很多隐藏的文件和文件夹吗?如果你在主目录中运行 `ls -a`,你会发现一堆带有点前缀的隐藏文件和目录。这些隐藏的文件到底做了什么? ### 在主目录中隐藏的文件是干什么用的? ![hidden-files-liunux-2][1] -通常,主目录中的隐藏文件和目录包含该用户程序访问的设置或数据。它们不打算由用户编辑,只需要应用程序进行编辑。这就是为什么它们被隐藏在用户的正常视图中。 +通常,主目录中的隐藏文件和目录包含该用户程序访问的设置或数据。它们不打算让用户编辑,只需要应用程序进行编辑。这就是为什么它们被隐藏在用户的正常视图之外。 -通常,可以在不损坏操作系统的情况下删除和修改自己主目录中的文件。然而,依赖这些隐藏文件的应用程序可能不那么灵活。从主目录中删除隐藏文件时,通常会丢失与其关联的应用程序的设置。 +通常,删除和修改自己主目录中的文件不会损坏操作系统。然而,依赖这些隐藏文件的应用程序可能不那么灵活。从主目录中删除隐藏文件时,通常会丢失与其关联的应用程序的设置。 -依赖该隐藏文件的程序通常会重新创建它。 但是,你将从“开箱即用”设置开始,如全新用户。如果你在使用应用程序时遇到问题,那实际上可能是一个巨大的帮助。它可以让你删除可能造成麻烦的自定义设置。但如果你不这样做,这意味着你需要把所有的东西都设置成原来的样子。 +依赖该隐藏文件的程序通常会重新创建它。 但是,你将从“开箱即用”设置开始,如全新用户一般。如果你在使用应用程序时遇到问题,那实际上可能是一个巨大的帮助。它可以让你删除可能造成麻烦的自定义设置。但如果你不这样做,这意味着你需要把所有的东西都设置成原来的样子。 ### 主目录中某些隐藏文件的特定用途是什么? ![hidden-files-linux-3][2] -每个人在他们的主目录中都会有不同的隐藏文件。每个人都有一些。但是,无论父应用程序如何,这些文件都有类似的用途。 +每个人在他们的主目录中都会有不同的隐藏文件。每个人都有一些。但是,无论应用程序如何,这些文件都有类似的用途。 -### 系统设置 +#### 系统设置 系统设置包括桌面环境和 shell 的配置。 -* 你的 shell 和命令行程序的**配置文件:**根据你使用的特定 shell 和类似命令的应用程序,特定的文件名称会变化。你会看到 ".bashrc"、".vimrc" 和 ".zshrc"。这些文件包含你已经更改的有关 shell 的操作环境的任何设置,或者对 `vim` 等命令行实用工具的设置进行了调整。删除这些文件将使关联的应用程序返回到其默认状态。考虑到许多 Linux 用户多年来建立了一系列微妙的调整和设置,删除这个文件可能是一个非常头疼的问题。 +* shell 和命令行程序的**配置文件**:根据你使用的特定 shell 和类似命令的应用程序,特定的文件名称会变化。你会看到 `.bashrc`、`.vimrc` 和 `.zshrc`。这些文件包含你已经更改的有关 shell 的操作环境的任何设置,或者对 `vim` 等命令行实用工具的设置进行的调整。删除这些文件将使关联的应用程序返回到其默认状态。考虑到许多 Linux 用户多年来建立了一系列微妙的调整和设置,删除这个文件可能是一个非常头疼的问题。 +* **用户配置文件**:像上面的配置文件一样,这些文件(通常是 `.profile` 或 `.bash_profile`)保存 shell 的用户设置。该文件通常包含你的 `PATH` 环境变量。它还包含你设置的[别名][3]。用户也可以在 `.bashrc` 或其他位置放置别名。`PATH` 环境变量控制着 shell 寻找可执行命令的位置。通过添加或修改 `PATH`,可以更改 shell 的命令查找位置。别名更改了原有命令的名称。例如:一个别名可能将 `ls -l` 设置为 `ll`。这为经常使用的命令提供基于文本的快捷方式。如果删除 `.profile` 文件,通常可以在 `/etc/skel` 目录中找到默认版本。 +* **桌面环境设置**:这里保存你的桌面环境的任何定制。其中包括桌面背景、屏幕保护程序、快捷键、菜单栏和任务栏图标以及用户针对其桌面环境设置的其他任何内容。当你删除这个文件时,用户的环境会在下一次登录时恢复到新的用户环境。 -* **用户配置文件:**像上面的配置文件一样,这些文件(通常是 ".profile" 或 ".bash_profile")保存 shell 的用户设置。该文件通常包含你的 PATH。(译注: PATH 是环境变量)它还包含你设置的[别名][3]。用户也可以在 `.bashrc` 或其他位置放置别名。PATH 控制着 shell 寻找可执行命令的位置。通过添加或修改 PATH,可以更改 shell 的命令查找位置。别名更改了原有命令的名称。例如:一个别名可能将 `ls -l` 设置为 `ll`。这为经常使用的命令提供基于文本的快捷方式。如果删除 `.profile` 文件,通常可以在 "/etc/skel" 目录中找到默认版本。 +#### 应用配置文件 -* **桌面环境设置:**这里保存你的桌面环境的任何定制。其中包括桌面背景,屏幕保护程序,快捷键,菜单栏和任务栏图标以及用户针对其桌面环境设置的其他任何内容。当你删除这个文件时,用户的环境会在下一次登录时恢复到新的用户环境。 +你会在 Ubuntu 的 `.config` 文件夹中找到它们。 这些是针对特定应用程序的设置。 它们将包含喜好列表和设置等内容。 -### 应用配置文件 - -你会在 Ubuntu 的 ".config" 文件夹中找到它们。 这些是针对特定应用程序的设置。 它们将包含喜好列表和设置等内容。 - -* **应用程序的配置文件:**这包括应用程序首选项菜单中的设置,工作区配置等。 你在这里找到的具体取决于父应用程序。 - -* **Web浏览器数据:**这可能包括书签和浏览历史记录等内容。大部分文件构成缓存。这是 Web 浏览器临时存储下载文件(如图片)的地方。删除这些内容可能会降低你首次访问某些媒体网站的速度。 - -* **缓存:**如果用户应用程序缓存仅与该用户相关的数据(如 [Spotify 应用程序存储播放列表的缓存][4]),则主目录是存储该目录的默认地点。 这些缓存可能包含大量数据或仅包含几行代码:这取决于父应用程序需要什么。 如果你删除这些文件,则应用程序会根据需要重新创建它们。 - -* **日志:**一些用户应用程序也可能在这里存储日志。根据开发人员设置应用程序的方式,你可能会发现存储在你的主目录中的日志文件。然而,这不是一个常见的选择。 +* **应用程序的配置文件**:这包括应用程序首选项菜单中的设置、工作区配置等。 你在这里找到的具体取决于应用程序。 +* **Web 浏览器数据**:这可能包括书签和浏览历史记录等内容。这些文件大部分是缓存。这是 Web 浏览器临时存储下载文件(如图片)的地方。删除这些内容可能会降低你首次访问某些媒体网站的速度。 +* **缓存**:如果用户应用程序缓存仅与该用户相关的数据(如 [Spotify 应用程序存储播放列表的缓存][4]),则主目录是存储该目录的默认地点。 这些缓存可能包含大量数据或仅包含几行代码:这取决于应用程序需要什么。 如果你删除这些文件,则应用程序会根据需要重新创建它们。 +* **日志**:一些用户应用程序也可能在这里存储日志。根据开发人员设置应用程序的方式,你可能会发现存储在你的主目录中的日志文件。然而,这不是一个常见的选择。 ### 结论 -在大多数情况下,你的 Linux 主目录中的隐藏文件用于存储用户设置。 这包括命令行程序以及基于 GUI 的应用程序的设置。删除它们将删除用户设置。 通常情况下,它不会导致程序中断。 +在大多数情况下,你的 Linux 主目录中的隐藏文件用于存储用户设置。 这包括命令行程序以及基于 GUI 的应用程序的设置。删除它们将删除用户设置。 通常情况下,它不会导致程序被破坏。 -------------------------------------------------------------------------------- @@ -53,7 +48,7 @@ via: https://www.maketecheasier.com/hidden-files-linux-home-directory/ 作者:[Alexander Fox][a] 译者:[MjSeven](https://github.com/MjSeven) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 From b4e74c0f9e52e86ae7038b5fed1e8e3def025d40 Mon Sep 17 00:00:00 2001 From: wxy Date: Mon, 5 Mar 2018 18:24:51 +0800 Subject: [PATCH 02/26] PUB:20171017 What Are the Hidden Files in my Linux Home Directory For.md @MjSeven https://linux.cn/article-9409-1.html --- ...17 What Are the Hidden Files in my Linux Home Directory For.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {translated/tech => published}/20171017 What Are the Hidden Files in my Linux Home Directory For.md (100%) diff --git a/translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md b/published/20171017 What Are the Hidden Files in my Linux Home Directory For.md similarity index 100% rename from translated/tech/20171017 What Are the Hidden Files in my Linux Home Directory For.md rename to published/20171017 What Are the Hidden Files in my Linux Home Directory For.md From d464ae688fd7a1c438cb5746f8133b71cb53c3ef Mon Sep 17 00:00:00 2001 From: ranchong <37066859+ranchong@users.noreply.github.com> Date: Mon, 5 Mar 2018 10:28:11 +0000 Subject: [PATCH 03/26] Update 20180219 How Linux became my job.md --- sources/talk/20180219 How Linux became my job.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/talk/20180219 How Linux became my job.md b/sources/talk/20180219 How Linux became my job.md index 83bf420691..40bd9bb8b9 100644 --- a/sources/talk/20180219 How Linux became my job.md +++ b/sources/talk/20180219 How Linux became my job.md @@ -1,4 +1,4 @@ -How Linux became my job +How Linux became my job translation by ranchong ====== ![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_penguin_green.png?itok=ENdVzW22) From e79179d9e5c2dcc7ff15b0d5ffc29e777a4a3c3a Mon Sep 17 00:00:00 2001 From: yizhuyan Date: Mon, 5 Mar 2018 18:35:23 +0800 Subject: [PATCH 04/26] Delete 20171204 5 Tips to Improve Technical Writing for an International Audience.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 翻译完毕,删除原文 --- ...l Writing for an International Audience.md | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 sources/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md diff --git a/sources/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md b/sources/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md deleted file mode 100644 index f13a04cb49..0000000000 --- a/sources/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md +++ /dev/null @@ -1,83 +0,0 @@ -translating by yizhuoyan - -5 Tips to Improve Technical Writing for an International Audience -============================================================ - - -![documentation](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/typewriter-801921_1920.jpg?itok=faTXFNoE "documentation") -Writing in English for an international audience takes work; here are some handy tips to remember.[Creative Commons Zero][2] - -Writing in English for an international audience does not necessarily put native English speakers in a better position. On the contrary, they tend to forget that the document's language might not be the first language of the audience. Let's have a look at the following simple sentence as an example: “Encrypt the password using the 'foo bar' command.” - -Grammatically, the sentence is correct. Given that "-ing" forms (gerunds) are frequently used in the English language, most native speakers would probably not hesitate to phrase a sentence like this. However, on closer inspection, the sentence is ambiguous: The word “using” may refer either to the object (“the password”) or to the verb (“encrypt”). Thus, the sentence can be interpreted in two different ways: - -* Encrypt the password that uses the 'foo bar' command. - -* Encrypt the password by using the 'foo bar' command. - -As long as you have previous knowledge about the topic (password encryption or the 'foo bar' command), you can resolve this ambiguity and correctly decide that the second reading is the intended meaning of this sentence. But what if you lack in-depth knowledge of the topic? What if you are not an expert but a translator with only general knowledge of the subject? Or, what if you are a non-native speaker of English who is unfamiliar with advanced grammatical forms? - -### Know Your Audience - -Even native English speakers may need some training to write clear and straightforward technical documentation. Raising awareness of usability and potential problems is the first step. This article, based on my talk at[ Open Source Summit EU][5], offers several useful techniques. Most of them are useful not only for technical documentation but also for everyday written communication, such as writing email or reports. - -**1. Change perspective. **Step into your audience's shoes. Step one is to know your intended audience. If you are a developer writing for end users, view the product from their perspective. The [persona technique][6] can help to focus on the target audience and to provide the right level of detail for your readers. - -**2\. Follow the KISS principle. **Keep it short and simple. The principle can be applied to several levels, like grammar, sentences, or words. Here are some examples: - - _Words: _ Uncommon and long words slow down reading and might be obstacles for non-native speakers. Use simpler alternatives: - -“utilize” → “use” - -“indicate” → “show”, “tell”, “say” - -“prerequisite” → “requirement” - - _Grammar: _ Use the simplest tense that is appropriate. For example, use present tense when mentioning the result of an action: "Click  _OK_ . The  _Printer Options_  dialog appears.” - - _Sentences: _ As a rule of thumb, present one idea in one sentence. However, restricting sentence length to a certain amount of words is not useful in my opinion. Short sentences are not automatically easy to understand (especially if they are a cluster of nouns). Sometimes, trimming down sentences to a certain word count can introduce ambiquities, which can, in turn, make sentences even more difficult to understand. - -**3\. Beware of ambiguities. **As authors, we often do not notice ambiguity in a sentence. Having your texts reviewed by others can help identify such problems. If that's not an option, try to look at each sentence from different perspectives: Does the sentence also work for readers without in-depth knowledge of the topic? Does it work for readers with limited language skills? Is the grammatical relationship between all sentence parts clear? If the sentence does not meet these requirements, rephrase it to resolve the ambiguity. - -**4\. Be consistent. **This applies to choice of words, spelling, and punctuation as well as phrases and structure. For lists, use parallel grammatical construction. For example: - -Why white space is important: - -* It focuses attention. - -* It visually separates sections. - -* It splits content into chunks.  - -**5\. Remove redundant content.** Keep only information that is relevant for your target audience. On a sentence level, avoid fillers (basically, easily) and unnecessary modifications: - -"already existing" → "existing" - -"completely new" → "new" - -As you might have guessed by now, writing is rewriting. Good writing requires effort and practice. But even if you write only occasionally, you can significantly improve your texts by focusing on the target audience and by using basic writing techniques. The better the readability of a text, the easier it is to process, even for an audience with varying language skills. When it comes to localization especially, good quality of the source text is important: Garbage in, garbage out. If the original text has deficiencies, it will take longer to translate the text, resulting in higher costs. In the worst case, the flaws will be multiplied during translation and need to be corrected in various languages.  - - -![Tanja Roth](https://www.linux.com/sites/lcom/files/styles/floated_images/public/tanja-roth.jpg?itok=eta0fvZC "Tanja Roth") - -Tanja Roth, Technical Documentation Specialist at SUSE Linux GmbH[Used with permission][1] - - _Driven by an interest in both language and technology, Tanja has been working as a technical writer in mechanical engineering, medical technology, and IT for many years. She joined SUSE in 2005 and contributes to a wide range of product and project documentation, including High Availability and Cloud topics._ - --------------------------------------------------------------------------------- - -via: https://www.linux.com/blog/event/open-source-summit-eu/2017/12/technical-writing-international-audience?sf175396579=1 - -作者:[TANJA ROTH ][a] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]:https://www.linux.com/users/tanja-roth -[1]:https://www.linux.com/licenses/category/used-permission -[2]:https://www.linux.com/licenses/category/creative-commons-zero -[3]:https://www.linux.com/files/images/tanja-rothjpg -[4]:https://www.linux.com/files/images/typewriter-8019211920jpg -[5]:https://osseu17.sched.com/event/ByIW -[6]:https://en.wikipedia.org/wiki/Persona_(user_experience) From a48c07a8249020ca6daee599b83a791ba0f4b904 Mon Sep 17 00:00:00 2001 From: yizhuyan Date: Mon, 5 Mar 2018 18:37:33 +0800 Subject: [PATCH 05/26] Create 20171204 5 Tips to Improve Technical Writing for an International Audience.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 翻译完毕 --- ...l Writing for an International Audience.md | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 translated/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md diff --git a/translated/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md b/translated/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md new file mode 100644 index 0000000000..20e604f357 --- /dev/null +++ b/translated/tech/20171204 5 Tips to Improve Technical Writing for an International Audience.md @@ -0,0 +1,117 @@ + + +提升针对国际读者技术性写作的5个技巧 +============================================================ + + +![documentation](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/typewriter-801921_1920.jpg?itok=faTXFNoE "documentation") + + + +针对国际读者用英语写作很不容易,下面这些小窍门可以记下来。[知识共享许可][2] + + +针对国际读者用英语写文档不需要特别考虑英语母语的人。相反,更应该注意文档的语言可能不是读者的第一语言。我们看看下面这些简单的句子:“加密密码用‘xxx’命令(Encrypt the password using the 'foo bar' command.)” + +从语法上讲,这个句子是正确的。ing形式(动名词)经常在英语中使用,很多英语母语的人应该大概对这样造句没有疑惑。然而,仔细观察,这个句子有歧义:单词“using”可以针对“the password”,也可以针对动词“加密”。因此,这个句子能够有两种不同的理解方式。 + +* Encrypt the password that uses the 'foo bar' command( 加密这个使用xxx命令的密码). +* Encrypt the password by using the 'foo bar' command(使用xxx命令加密密码). + + +关于这个话题(密码加密或者xxx命令),只要你有这方面的知识,你就不会理解错误,而且正确的选择第二种方式才是句子要表达的含义。但是如果你对这个知识点没有概念呢?如果你仅仅是一个翻译者,只有关于文章主题的一般知识,而不是一个技术专家?或者英语不是你的母语而且你不熟悉英语的高级语法形式呢? + +甚至连英语母语的人都可能需要一些训练才能写出简洁明了的技术文档。所以提升对文章适用性和潜在问题的认识是第一步。 + + +这篇文章,基于我在[欧盟开放源码峰会][5]上的演讲,提供了几种有用的技巧。大多数技巧不仅仅针对技术文档,也可以用于日程信函的书写,如邮件或者报告之类的。 + + +**1. 转换视角** + +转换视角,从你的读者出发。首先要了解你潜在的读者。如果你是作为开发人员针对用户写,则从用户的视角来看待你的产品。用户画像(Persona)技术能够帮助你专注于目标受众,而且提供关于你的受众适当的细节信息。 + +**2. 遵守KISS(Keep it short and simple)原则** + +这个原则可以用于几个层次,如语法,句式或者单词。看下面的例子: + +_单词:_ + +罕见的和长的单词会降低阅读速度而且可能会是非母语读者的障碍。使用简单点的单词,如: +“utilize” → “use” +“indicate” → “show”, “tell”, “say” +“prerequisite” → “requirement” + + + + +_语法:_ + +最好使用最简单的时态。举个例子,当提到一个动作的结果时使用一般现在时。如“Click '_OK_' . The _Printer Options_ dialog appears(单击'_ok_'.就弹出_打印选项_对话框了)” + + +_句式:_ + +一般说来,一个句子就表达一个意思。然而在我看来,把句子的长度限制到一定数量的单词是没有用的。短句子不是想着那么容易理解的(特别是一组名词的时候)。有时候把句子剪短到一定单词数量会造成歧义,相应的还会使句子更加难以理解。 + + + + +**3. 当心歧义** + + +作为作者,我们通常没有注意到句子中的歧义。让别人审阅你的文章有助于发现这些问题。如果无法这么做,就尝试从这些不同的视角审视每个句子: +对于没有相关知识背景的读者也能看懂吗?对于语言能力有限的读者也可以吗?所有句子成分间的语法关系清晰吗?如果某个句子没有达到这些要求,重新措辞来解决歧义。 + +**4. 格式统一** + +这个适用于对单词,拼写和标点符号的选择,也是适用于短语和结构的选择。对于列表,使用平行的语法造句。如: + +Why white space is important(为什么空格很重要): + +* It focuses attention(让读者注意力集中). + +* It visually separates sections(让文章章节分割更直观). + +* It splits content into chunks(让文章内容分割为不同块). + +**5. 清除冗余** + +对目标读者仅保留明确的信息。在句子层面,避免填充(如basically, easily)和没必要的修饰。如: + +"already existing" → "existing" + +"completely new" → "new" + + +##总结 + +你现在应该猜到了,写作就是改。好的文章需要付出和练习。但是如果你仅是偶尔写写,则可以通过专注目标读者和运用基本写作技巧来显著地提升你的文章。 + +文章易读性越高,理解起来越容易,即使针对于不同语言级别的读者也是一样。尤其在本地化翻译方面,高质量的原文是非常重要的,因为“错进错出(原文:Garbage in, garbage out)"。如果原文有不足,翻译时间会更长,导致更高的成本。甚至,这种不足会在翻译过程中成倍的放大而且后面需要在多种语言版本中改正。 + + +![Tanja Roth](https://www.linux.com/sites/lcom/files/styles/floated_images/public/tanja-roth.jpg?itok=eta0fvZC "Tanja Roth") + +Tanja Roth, SUSE Linux公司-技术文档专家 [使用许可][1] + + +_在对语言和技术两方面兴趣的驱动下,Tanja作为一名技术文章的写作者,在机械工程,医学技术和IT领域工作了很多年。她在2005年加入SUSE组织并且贡献了各种各样产品和项目的文章,包括高可用性和云的相关话题。_ + +-------------------------------------------------------------------------------- + +via: https://www.linux.com/blog/event/open-source-summit-eu/2017/12/technical-writing-international-audience?sf175396579=1 + +作者:[TANJA ROTH ][a] +译者:[yizhuoyan](https://github.com/yizhuoyan) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.linux.com/users/tanja-roth +[1]:https://www.linux.com/licenses/category/used-permission +[2]:https://www.linux.com/licenses/category/creative-commons-zero +[3]:https://www.linux.com/files/images/tanja-rothjpg +[4]:https://www.linux.com/files/images/typewriter-8019211920jpg +[5]:https://osseu17.sched.com/event/ByIW +[6]:https://en.wikipedia.org/wiki/Persona_(user_experience) From 8b5f60e3d93f1aac0fb99b4336d2e032979808a3 Mon Sep 17 00:00:00 2001 From: yizhuyan Date: Mon, 5 Mar 2018 18:45:28 +0800 Subject: [PATCH 06/26] =?UTF-8?q?=E7=BF=BB=E8=AF=91=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ... File Permissions On Linux - Unix Web Server DocumentRoot.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/tech/20120424 How To Set Readonly File Permissions On Linux - Unix Web Server DocumentRoot.md b/sources/tech/20120424 How To Set Readonly File Permissions On Linux - Unix Web Server DocumentRoot.md index 6f46d154a1..d5b31e5120 100644 --- a/sources/tech/20120424 How To Set Readonly File Permissions On Linux - Unix Web Server DocumentRoot.md +++ b/sources/tech/20120424 How To Set Readonly File Permissions On Linux - Unix Web Server DocumentRoot.md @@ -1,3 +1,5 @@ +translating by yizhuoyan + How To Set Readonly File Permissions On Linux / Unix Web Server DocumentRoot ====== From c14fe6afbd0c3cf8b92014b4146f7da132645091 Mon Sep 17 00:00:00 2001 From: amwps290 Date: Mon, 5 Mar 2018 18:49:43 +0800 Subject: [PATCH 07/26] Translating by amwps290 --- ...0220 How to format academic papers on Linux with groff -me.md | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/tech/20180220 How to format academic papers on Linux with groff -me.md b/sources/tech/20180220 How to format academic papers on Linux with groff -me.md index 5131cad7f5..a7902856db 100644 --- a/sources/tech/20180220 How to format academic papers on Linux with groff -me.md +++ b/sources/tech/20180220 How to format academic papers on Linux with groff -me.md @@ -1,3 +1,4 @@ +translating by amwps290 How to format academic papers on Linux with groff -me ====== From 85ef69d1cd7eb83a656c768998b1fcd8bb69c3ce Mon Sep 17 00:00:00 2001 From: MjSeven <33125422+MjSeven@users.noreply.github.com> Date: Mon, 5 Mar 2018 19:13:54 +0800 Subject: [PATCH 08/26] Delete 20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md --- ...VM on CentOS 7 - RHEL 7 Headless Server.md | 344 ------------------ 1 file changed, 344 deletions(-) delete mode 100644 sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md diff --git a/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md deleted file mode 100644 index 560963281d..0000000000 --- a/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md +++ /dev/null @@ -1,344 +0,0 @@ -Translating by MjSeven - -How to install KVM on CentOS 7 / RHEL 7 Headless Server -====== - - -How do I install and configure KVM (Kernel-based Virtual Machine) on a CentOS 7 or RHEL (Red Hat Enterprise Linux) 7 server? How can I setup KMV on a CentOS 7 and use cloud images/cloud-init for installing guest VM? - - -Kernel-based Virtual Machine (KVM) is virtualization software for CentOS or RHEL 7. KVM turn your server into a hypervisor. This page shows how to setup and manage a virtualized environment with KVM in CentOS 7 or RHEL 7. It also described how to install and administer Virtual Machines (VMs) on a physical server using the CLI. Make sure that **Virtualization Technology (VT)** is enabled in your server 's BIOS. You can also run the following command [to test if CPU Support Intel VT and AMD-V Virtualization tech][1] -``` -$ lscpu | grep Virtualization -Virtualization: VT-x -``` - - - -### Follow installation steps of KVM on CentOS 7/RHEL 7 headless sever - -#### Step 1: Install kvm - -Type the following [yum command][2]: -`# yum install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install` -[![How to install KVM on CentOS 7 RHEL 7 Headless Server][3]][3] -Start the libvirtd service: -``` -# systemctl enable libvirtd -# systemctl start libvirtd -``` - -#### Step 2: Verify kvm installation - -Make sure KVM module loaded using lsmod command and [grep command][4]: -`# lsmod | grep -i kvm` - -#### Step 3: Configure bridged networking - -By default dhcpd based network bridge configured by libvirtd. You can verify that with the following commands: -``` -# brctl show -# virsh net-list -``` -[![KVM default networking][5]][5] -All VMs (guest machine) only have network access to other VMs on the same server. A private network 192.168.122.0/24 created for you. Verify it: -`# virsh net-dumpxml default` -If you want your VMs avilable to other servers on your LAN, setup a a network bridge on the server that connected to the your LAN. Update your nic config file such as ifcfg-enp3s0 or em1: -`# vi /etc/sysconfig/network-scripts/enp3s0 ` -Add line: -``` -BRIDGE=br0 -``` - -[Save and close the file in vi][6]. Edit /etc/sysconfig/network-scripts/ifcfg-br0 and add: -`# vi /etc/sysconfig/network-scripts/ifcfg-br0` -Append the following: -``` -DEVICE="br0" -# I am getting ip from DHCP server # -BOOTPROTO="dhcp" -IPV6INIT="yes" -IPV6_AUTOCONF="yes" -ONBOOT="yes" -TYPE="Bridge" -DELAY="0" -``` - -Restart the networking service (warning ssh command will disconnect, it is better to reboot the box): -`# systemctl restart NetworkManager` -Verify it with brctl command: -`# brctl show` - -#### Step 4: Create your first virtual machine - -I am going to create a CentOS 7.x VM. First, grab CentOS 7.x latest ISO image using the wget command: -``` -# cd /var/lib/libvirt/boot/ -# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/CentOS-7-x86_64-Minimal-1708.iso -``` -Verify ISO images: -``` -# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/sha256sum.txt -# sha256sum -c sha256sum.txt -``` - -##### Create CentOS 7.x VM - -In this example, I'm creating CentOS 7.x VM with 2GB RAM, 2 CPU core, 1 nics and 40GB disk space, enter: -``` -# virt-install \ ---virt-type=kvm \ ---name centos7 \ ---ram 2048 \ ---vcpus=1 \ ---os-variant=centos7.0 \ ---cdrom=/var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-1708.iso \ ---network=bridge=br0,model=virtio \ ---graphics vnc \ ---disk path=/var/lib/libvirt/images/centos7.qcow2,size=40,bus=virtio,format=qcow2 -``` -To configure vnc login from another terminal over ssh and type: -``` -# virsh dumpxml centos7 | grep vnc - -``` -Please note down the port value (i.e. 5901). You need to use an SSH client to setup tunnel and a VNC client to access the remote vnc server. Type the following SSH port forwarding command from your client/desktop/macbook pro system: -`$ ssh vivek@server1.cyberciti.biz -L 5901:127.0.0.1:5901` -Once you have ssh tunnel established, you can point your VNC client at your own 127.0.0.1 (localhost) address and port 5901 as follows: -[![][7]][7] -You should see CentOS Linux 7 guest installation screen as follows: -[![][8]][8] -Now just follow on screen instructions and install CentOS 7. Once installed, go ahead and click the reboot button. The remote server closed the connection to our VNC client. You can reconnect via KVM client to configure the rest of the server including SSH based session or firewall. - -#### Step 5: Using cloud images - -The above installation method is okay for learning purpose or a single VM. Do you need to deploy lots of VMs? Try cloud images. You can modify pre built cloud images as per your needs. For example, add users, ssh keys, setup time zone, and more using [Cloud-init][9] which is the defacto multi-distribution package that handles early initialization of a cloud instance. Let us see how to create CentOS 7 vm with 1024MB ram, 20GB disk space, and 1 vCPU. - -##### Grab CentOS 7 cloud image - -``` -# cd /var/lib/libvirt/boot -# wget http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 -``` - -##### Create required directories - -``` -# D=/var/lib/libvirt/images -# VM=centos7-vm1 ## vm name ## -# mkdir -vp $D/$VM -mkdir: created directory '/var/lib/libvirt/images/centos7-vm1' -``` - -##### Create meta-data file - -``` -# cd $D/$VM -# vi meta-data -``` -Append the following: -``` -instance-id: centos7-vm1 -local-hostname: centos7-vm1 -``` - -##### Crete user-data file - -I am going to login into VM using ssh keys. So make sure you have ssh-keys in place: -`# ssh-keygen -t ed25519 -C "VM Login ssh key"` -[![ssh-keygen command][10]][11] -See "[How To Setup SSH Keys on a Linux / Unix System][12]" for more info. Edit user-data as follows: -``` -# cd $D/$VM -# vi user-data -``` -Add as follows (replace hostname, users, ssh-authorized-keys as per your setup): -``` -#cloud-config - -# Hostname management -preserve_hostname: False -hostname: centos7-vm1 -fqdn: centos7-vm1.nixcraft.com - -# Users -users: - - default - - name: vivek - groups: ['wheel'] - shell: /bin/bash - sudo: ALL=(ALL) NOPASSWD:ALL - ssh-authorized-keys: - - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key - -# Configure where output will go -output: - all: ">> /var/log/cloud-init.log" - -# configure interaction with ssh server -ssh_genkeytypes: ['ed25519', 'rsa'] - -# Install my public ssh key to the first user-defined user configured -# in cloud.cfg in the template (which is centos for CentOS cloud images) -ssh_authorized_keys: - - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key - -# set timezone for VM -timezone: Asia/Kolkata - -# Remove cloud-init -runcmd: - - systemctl stop network && systemctl start network - - yum -y remove cloud-init -``` - -##### Copy cloud image - -``` -# cd $D/$VM -# cp /var/lib/libvirt/boot/CentOS-7-x86_64-GenericCloud.qcow2 $VM.qcow2 -``` - -##### Create 20GB disk image - -``` -# cd $D/$VM -# export LIBGUESTFS_BACKEND=direct -# qemu-img create -f qcow2 -o preallocation=metadata $VM.new.image 20G -# virt-resize --quiet --expand /dev/sda1 $VM.qcow2 $VM.new.image -``` -[![Set VM image disk size][13]][13] -Overwrite it resized image: -``` -# cd $D/$VM -# mv $VM.new.image $VM.qcow2 -``` - -##### Creating a cloud-init ISO - -`# mkisofs -o $VM-cidata.iso -V cidata -J -r user-data meta-data` -[![Creating a cloud-init ISO][14]][14] - -##### Creating a pool - -``` -# virsh pool-create-as --name $VM --type dir --target $D/$VM -Pool centos7-vm1 created -``` - -##### Installing a CentOS 7 VM - -``` -# cd $D/$VM -# virt-install --import --name $VM \ ---memory 1024 --vcpus 1 --cpu host \ ---disk $VM.qcow2,format=qcow2,bus=virtio \ ---disk $VM-cidata.iso,device=cdrom \ ---network bridge=virbr0,model=virtio \ ---os-type=linux \ ---os-variant=centos7.0 \ ---graphics spice \ ---noautoconsole -``` -Delete unwanted files: -``` -# cd $D/$VM -# virsh change-media $VM hda --eject --config -# rm meta-data user-data centos7-vm1-cidata.iso -``` - -##### Find out IP address of VM - -`# virsh net-dhcp-leases default` -[![CentOS7-VM1- Created][15]][15] - -##### Log in to your VM - -Use ssh command: -`# ssh vivek@192.168.122.85` -[![Sample VM session][16]][16] - -### Useful commands - -Let us see some useful commands for managing VMs. - -#### List all VMs - -`# virsh list --all` - -#### Get VM info - -``` -# virsh dominfo vmName -# virsh dominfo centos7-vm1 -``` - -#### Stop/shutdown a VM - -`# virsh shutdown centos7-vm1` - -#### Start VM - -`# virsh start centos7-vm1` - -#### Mark VM for autostart at boot time - -`# virsh autostart centos7-vm1` - -#### Reboot (soft & safe reboot) VM - -`# virsh reboot centos7-vm1` -Reset (hard reset/not safe) VM -`# virsh reset centos7-vm1` - -#### Delete VM - -``` -# virsh shutdown centos7-vm1 -# virsh undefine centos7-vm1 -# virsh pool-destroy centos7-vm1 -# D=/var/lib/libvirt/images -# VM=centos7-vm1 -# rm -ri $D/$VM -``` -To see a complete list of virsh command type -``` -# virsh help | less -# virsh help | grep reboot -``` - - -### About the author - -The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on [Twitter][17], [Facebook][18], [Google+][19]. - --------------------------------------------------------------------------------- - -via: https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/ - -作者:[Vivek Gite][a] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]:https://www.cyberciti.biz -[1]:https://www.cyberciti.biz/faq/linux-xen-vmware-kvm-intel-vt-amd-v-support/ -[2]:https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/ (See Linux/Unix yum command examples for more info) -[3]:https://www.cyberciti.biz/media/new/faq/2018/01/How-to-install-KVM-on-CentOS-7-RHEL-7-Headless-Server.jpg -[4]:https://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/ (See Linux/Unix grep command examples for more info) -[5]:https://www.cyberciti.biz/media/new/faq/2018/01/KVM-default-networking.jpg -[6]:https://www.cyberciti.biz/faq/linux-unix-vim-save-and-quit-command/ -[7]:https://www.cyberciti.biz/media/new/faq/2016/01/vnc-client.jpg -[8]:https://www.cyberciti.biz/media/new/faq/2016/01/centos7-guest-vnc.jpg -[9]:https://cloudinit.readthedocs.io/en/latest/index.html -[10]:https://www.cyberciti.biz/media/new/faq/2018/01/ssh-keygen-pub-key.jpg -[11]:https://www.cyberciti.biz/faq/linux-unix-generating-ssh-keys/ -[12]:https://www.cyberciti.biz/faq/how-to-set-up-ssh-keys-on-linux-unix/ -[13]:https://www.cyberciti.biz/media/new/faq/2018/01/Set-VM-image-disk-size.jpg -[14]:https://www.cyberciti.biz/media/new/faq/2018/01/Creating-a-cloud-init-ISO.jpg -[15]:https://www.cyberciti.biz/media/new/faq/2018/01/CentOS7-VM1-Created.jpg -[16]:https://www.cyberciti.biz/media/new/faq/2018/01/Sample-VM-session.jpg -[17]:https://twitter.com/nixcraft -[18]:https://facebook.com/nixcraft -[19]:https://plus.google.com/+CybercitiBiz From 8ede439b1998b445799bbc7e5277baee6b842d0e Mon Sep 17 00:00:00 2001 From: MjSeven <33125422+MjSeven@users.noreply.github.com> Date: Mon, 5 Mar 2018 19:14:38 +0800 Subject: [PATCH 09/26] Create 20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md --- ...VM on CentOS 7 - RHEL 7 Headless Server.md | 350 ++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md diff --git a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md new file mode 100644 index 0000000000..1aa429d651 --- /dev/null +++ b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md @@ -0,0 +1,350 @@ +如何在 CentOS 7 / RHEL 7 终端服务器上安装 KVM +====== + +如何在 CnetOS 7 或 RHEL 7( Red Hat 企业版 Linux) 服务器上安装和配置 KVM(基于内核的虚拟机)?如何在 CnetOS 7 上设置 KMV 并使用云镜像/ cloud-init 来安装客户虚拟机? + +基于内核的虚拟机(KVM)是 CentOS 或 RHEL 7 的虚拟化软件。KVM 将你的服务器变成虚拟机管理程序。本文介绍如何在 CentOS 7 或 RHEL 7 中使用 KVM 设置和管理虚拟化环境。还介绍了如何使用 CLI 在物理服务器上安装和管理虚拟机(VM)。确保在服务器的 BIOS 中启用了**虚拟化技术(vt)**。你也可以运行以下命令[测试 CPU 是否支持 Intel VT 和 AMD_V 虚拟化技术][1] +``` +$ lscpu | grep Virtualization +Virtualization: VT-x +``` + +### 按照 CentOS 7/RHEL 7 终端服务器上的 KVM 安装步骤进行操作 + +#### 步骤 1: 安装 kvm + +输入以下 [yum 命令][2]: +`# yum install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install` + +[![How to install KVM on CentOS 7 RHEL 7 Headless Server][3]][3] + +启动 libvirtd 服务: +``` +# systemctl enable libvirtd +# systemctl start libvirtd +``` + +#### 步骤 2: 确认 kvm 安装 + +确保使用 lsmod 命令和 [grep命令][4] 加载 KVM 模块: +`# lsmod | grep -i kvm` + +#### 步骤 3: 配置桥接网络 + +默认情况下,由 libvirtd 配置的基于 dhcpd 的网桥。你可以使用以下命令验证: +``` +# brctl show +# virsh net-list +``` +[![KVM default networking][5]][5] + +所有虚拟机(客户机器)只能在同一台服务器上对其他虚拟机进行网络访问。为你创建的私有网络是 192.168.122.0/24。验证: +`# virsh net-dumpxml default` + +如果你希望你的虚拟机可用于 LAN 上的其他服务器,请在连接到你的 LAN 的服务器上设置一个网桥。更新你的网卡配置文件,如 ifcfg-enp3s0 或 em1: +`# vi /etc/sysconfig/network-scripts/enp3s0 ` +添加一行: +``` +BRIDGE=br0 +``` + +[使用 vi 保存并关闭文件][6]。编辑 /etc/sysconfig/network-scripts/ifcfg-br0 : +`# vi /etc/sysconfig/network-scripts/ifcfg-br0` +添加以下东西: +``` +DEVICE="br0" +# I am getting ip from DHCP server # +BOOTPROTO="dhcp" +IPV6INIT="yes" +IPV6_AUTOCONF="yes" +ONBOOT="yes" +TYPE="Bridge" +DELAY="0" +``` + +重新启动网络服务(警告:ssh命令将断开连接,最好重新启动该设备): +`# systemctl restart NetworkManager` + +用 brctl 命令验证它: +`# brctl show` + +#### 步骤 4: 创建你的第一个虚拟机 + +我将会创建一个 CentOS 7.x 虚拟机。首先,使用 wget 命令获取 CentOS 7.x 最新的 ISO 镜像: +``` +# cd /var/lib/libvirt/boot/ +# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/CentOS-7-x86_64-Minimal-1708.iso +``` + +验证 ISO 镜像: +``` +# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/sha256sum.txt +# sha256sum -c sha256sum.txt +``` + +##### 创建 CentOS 7.x 虚拟机 + +在这个例子中,我创建了 2GB RAM,2 个 CPU 核心,1 个网卡和 40 GB 磁盘空间的 CentOS 7.x 虚拟机,输入: +``` +# virt-install \ +--virt-type=kvm \ +--name centos7 \ +--ram 2048 \ +--vcpus=1 \ +--os-variant=centos7.0 \ +--cdrom=/var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-1708.iso \ +--network=bridge=br0,model=virtio \ +--graphics vnc \ +--disk path=/var/lib/libvirt/images/centos7.qcow2,size=40,bus=virtio,format=qcow2 +``` + +从另一个终端通过 ssh 和 type 配置 vnc 登录: +``` +# virsh dumpxml centos7 | grep v nc + +``` + +请记录下端口值(即 5901)。你需要使用 SSH 客户端来建立隧道和 VNC 客户端才能访问远程 vnc 服务区。在客户端/桌面/ macbook pro 系统中输入以下 SSH 端口转化命令: +`$ ssh vivek@server1.cyberciti.biz -L 5901:127.0.0.1:5901` + +一旦你建立了 ssh 隧道,你可以将你的 VNC 客户端指向你自己的 127.0.0.1 (localhost) 地址和端口 5901,如下所示: +[![][7]][7] + +你应该看到 CentOS Linux 7 客户虚拟机安装屏幕如下: +[![][8]][8] + +现在只需按照屏幕说明进行操作并安装CentOS 7。一旦安装完成后,请继续并单击重启按钮。 远程服务器关闭了我们的 VNC 客户端的连接。 你可以通过 KVM 客户端重新连接,以配置服务器的其余部分,包括基于 SSH 的会话或防火墙。 + +#### 步骤 5: 使用云镜像 + +以上安装方法对于学习目的或单个虚拟机而言是可行的。你需要部署大量的虚拟机吗? 尝试云镜像。你可以根据需要修改预先构建的云图像。例如,使用 [Cloud-init][9] 添加用户,ssh 密钥,设置时区等等,这是处理云实例的早期初始化的事实上的多分发包。让我们看看如何创建带有 1024MB RAM,20GB 磁盘空间和 1 个 vCPU 的 CentOS 7 虚拟机。(译注: vCPU 即电脑中的虚拟处理器) + +##### 获取 CentOS 7 云镜像 + +``` +# cd /var/lib/libvirt/boot +# wget http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 +``` + +##### 创建所需的目录 + +``` +# D=/var/lib/libvirt/images +# VM=centos7-vm1 ## vm name ## +# mkdir -vp $D/$VM +mkdir: created directory '/var/lib/libvirt/images/centos7-vm1' +``` + +##### 创建元数据文件 + +``` +# cd $D/$VM +# vi meta-data +``` + +添加以下东西: +``` +instance-id: centos7-vm1 +local-hostname: centos7-vm1 +``` + +##### 创建用户数据文件 + +我将使用 ssh 密钥登录到虚拟机。所以确保你有 ssh-keys: +`# ssh-keygen -t ed25519 -C "VM Login ssh key"` +[![ssh-keygen command][10]][11] + +请参阅 "[如何在 Linux/Unix 系统上设置 SSH 密钥][12]" 来获取更多信息。编辑用户数据如下: +``` +# cd $D/$VM +# vi user-data +``` +添加如下(根据你的设置替换主机名,用户,ssh-authorized-keys): +``` +#cloud-config + +# Hostname management +preserve_hostname: False +hostname: centos7-vm1 +fqdn: centos7-vm1.nixcraft.com + +# Users +users: + - default + - name: vivek + groups: ['wheel'] + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + ssh-authorized-keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key + +# Configure where output will go +output: + all: ">> /var/log/cloud-init.log" + +# configure interaction with ssh server +ssh_genkeytypes: ['ed25519', 'rsa'] + +# Install my public ssh key to the first user-defined user configured +# in cloud.cfg in the template (which is centos for CentOS cloud images) +ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key + +# set timezone for VM +timezone: Asia/Kolkata + +# Remove cloud-init +runcmd: + - systemctl stop network && systemctl start network + - yum -y remove cloud-init +``` + +##### 复制云镜像 + +``` +# cd $D/$VM +# cp /var/lib/libvirt/boot/CentOS-7-x86_64-GenericCloud.qcow2 $VM.qcow2 +``` + +##### 创建 20GB 磁盘映像 + +``` +# cd $D/$VM +# export LIBGUESTFS_BACKEND=direct +# qemu-img create -f qcow2 -o preallocation=metadata $VM.new.image 20G +# virt-resize --quiet --expand /dev/sda1 $VM.qcow2 $VM.new.image +``` +[![Set VM image disk size][13]][13] +覆盖它的缩放图片: +``` +# cd $D/$VM +# mv $VM.new.image $VM.qcow2 +``` + +##### 创建一个 cloud-init ISO + +`# mkisofs -o $VM-cidata.iso -V cidata -J -r user-data meta-data` +[![Creating a cloud-init ISO][14]][14] + +##### 创建一个 pool + +``` +# virsh pool-create-as --name $VM --type dir --target $D/$VM +Pool centos7-vm1 created +``` + +##### 安装 CentOS 7 虚拟机 + +``` +# cd $D/$VM +# virt-install --import --name $VM \ +--memory 1024 --vcpus 1 --cpu host \ +--disk $VM.qcow2,format=qcow2,bus=virtio \ +--disk $VM-cidata.iso,device=cdrom \ +--network bridge=virbr0,model=virtio \ +--os-type=linux \ +--os-variant=centos7.0 \ +--graphics spice \ +--noautoconsole +``` +删除不需要的文件: +``` +# cd $D/$VM +# virsh change-media $VM hda --eject --config +# rm meta-data user-data centos7-vm1-cidata.iso +``` + +##### 查找虚拟机的 IP 地址 + +`# virsh net-dhcp-leases default` +[![CentOS7-VM1- Created][15]][15] + +##### 登录到你的虚拟机 + +使用 ssh 命令: +`# ssh vivek@192.168.122.85` +[![Sample VM session][16]][16] + +### 有用的命令 + +让我们看看管理虚拟机的一些有用的命令。 + +#### 列出所有虚拟机 + +`# virsh list --all` + +#### 获取虚拟机信息 + +``` +# virsh dominfo vmName +# virsh dominfo centos7-vm1 +``` + +#### 停止/关闭虚拟机 + +`# virsh shutdown centos7-vm1` + +#### 开启虚拟机 + +`# virsh start centos7-vm1` + +#### 将虚拟机标记为在引导时自动启动 + +`# virsh autostart centos7-vm1` + +#### 重新启动(软安全重启)虚拟机 + +`# virsh reboot centos7-vm1` +重置(硬重置/不安全)虚拟机 +`# virsh reset centos7-vm1` + +#### 删除虚拟机 + +``` +# virsh shutdown centos7-vm1 +# virsh undefine centos7-vm1 +# virsh pool-destroy centos7-vm1 +# D=/var/lib/libvirt/images +# VM=centos7-vm1 +# rm -ri $D/$VM +``` +查看 virsh 命令类型的完整列表 +``` +# virsh help | less +# virsh help | grep reboot +``` + +### 关于作者 + +作者是 nixCraft 的创建者,也是经验丰富的系统管理员和 Linux 操作系统/ Unix shell 脚本的培训师。 他曾与全球客户以及 IT,教育,国防和空间研究以及非营利部门等多个行业合作。 在 [Twitter][17],[Facebook][18],[Google +][19] 上关注他。 + +-------------------------------------------------------------------------------- + +via: [https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/][https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/] + +作者:[Vivek Gite][a] +译者:[MjSeven](https://github.com/MjSeven) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.cyberciti.biz +[1]:https://www.cyberciti.biz/faq/linux-xen-vmware-kvm-intel-vt-amd-v-support/ +[2]:https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/ (See Linux/Unix yum command examples for more info) +[3]:https://www.cyberciti.biz/media/new/faq/2018/01/How-to-install-KVM-on-CentOS-7-RHEL-7-Headless-Server.jpg +[4]:https://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/ (See Linux/Unix grep command examples for more info) +[5]:https://www.cyberciti.biz/media/new/faq/2018/01/KVM-default-networking.jpg +[6]:https://www.cyberciti.biz/faq/linux-unix-vim-save-and-quit-command/ +[7]:https://www.cyberciti.biz/media/new/faq/2016/01/vnc-client.jpg +[8]:https://www.cyberciti.biz/media/new/faq/2016/01/centos7-guest-vnc.jpg +[9]:https://cloudinit.readthedocs.io/en/latest/index.html +[10]:https://www.cyberciti.biz/media/new/faq/2018/01/ssh-keygen-pub-key.jpg +[11]:https://www.cyberciti.biz/faq/linux-unix-generating-ssh-keys/ +[12]:https://www.cyberciti.biz/faq/how-to-set-up-ssh-keys-on-linux-unix/ +[13]:https://www.cyberciti.biz/media/new/faq/2018/01/Set-VM-image-disk-size.jpg +[14]:https://www.cyberciti.biz/media/new/faq/2018/01/Creating-a-cloud-init-ISO.jpg +[15]:https://www.cyberciti.biz/media/new/faq/2018/01/CentOS7-VM1-Created.jpg +[16]:https://www.cyberciti.biz/media/new/faq/2018/01/Sample-VM-session.jpg +[17]:https://twitter.com/nixcraft +[18]:https://facebook.com/nixcraft +[19]:https://plus.google.com/+CybercitiBiz From 69b20e4aac51d1dae54d6f2b270b658aad73e736 Mon Sep 17 00:00:00 2001 From: MjSeven <33125422+MjSeven@users.noreply.github.com> Date: Mon, 5 Mar 2018 19:16:33 +0800 Subject: [PATCH 10/26] Update 20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md --- ...7 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md index 1aa429d651..994f0713a0 100644 --- a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md +++ b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md @@ -3,7 +3,7 @@ 如何在 CnetOS 7 或 RHEL 7( Red Hat 企业版 Linux) 服务器上安装和配置 KVM(基于内核的虚拟机)?如何在 CnetOS 7 上设置 KMV 并使用云镜像/ cloud-init 来安装客户虚拟机? -基于内核的虚拟机(KVM)是 CentOS 或 RHEL 7 的虚拟化软件。KVM 将你的服务器变成虚拟机管理程序。本文介绍如何在 CentOS 7 或 RHEL 7 中使用 KVM 设置和管理虚拟化环境。还介绍了如何使用 CLI 在物理服务器上安装和管理虚拟机(VM)。确保在服务器的 BIOS 中启用了**虚拟化技术(vt)**。你也可以运行以下命令[测试 CPU 是否支持 Intel VT 和 AMD_V 虚拟化技术][1] +基于内核的虚拟机(KVM)是 CentOS 或 RHEL 7 的虚拟化软件。KVM 将你的服务器变成虚拟机管理程序。本文介绍如何在 CentOS 7 或 RHEL 7 中使用 KVM 设置和管理虚拟化环境。还介绍了如何使用 CLI 在物理服务器上安装和管理虚拟机(VM)。确保在服务器的 BIOS 中启用了**虚拟化技术(vt)**。你也可以运行以下命令[测试 CPU 是否支持 Intel VT 和 AMD_V 虚拟化技术][1]。 ``` $ lscpu | grep Virtualization Virtualization: VT-x From 44cab90f4c7e4236e24fec7e3953307dc4d8e61b Mon Sep 17 00:00:00 2001 From: MjSeven <33125422+MjSeven@users.noreply.github.com> Date: Mon, 5 Mar 2018 19:18:27 +0800 Subject: [PATCH 11/26] Update 20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md --- ...27 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md | 1 + 1 file changed, 1 insertion(+) diff --git a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md index 994f0713a0..5fce199541 100644 --- a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md +++ b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md @@ -257,6 +257,7 @@ Pool centos7-vm1 created ##### 查找虚拟机的 IP 地址 `# virsh net-dhcp-leases default` + [![CentOS7-VM1- Created][15]][15] ##### 登录到你的虚拟机 From bb5ae07fef5c0dc4552ba4c3d68d93f70e7df859 Mon Sep 17 00:00:00 2001 From: MjSeven <33125422+MjSeven@users.noreply.github.com> Date: Mon, 5 Mar 2018 19:19:38 +0800 Subject: [PATCH 12/26] Update 20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md --- ...7 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md index 5fce199541..233daa72b2 100644 --- a/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md +++ b/translated/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md @@ -321,7 +321,7 @@ Pool centos7-vm1 created -------------------------------------------------------------------------------- -via: [https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/][https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/] +via: [https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/](https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/) 作者:[Vivek Gite][a] 译者:[MjSeven](https://github.com/MjSeven) From f198695ef0db95d07f9ac6b9add3495c481dcd8f Mon Sep 17 00:00:00 2001 From: Feng Lv Date: Mon, 5 Mar 2018 19:36:14 +0800 Subject: [PATCH 13/26] translated --- sources/tech/20160810 How does gdb work.md | 220 ------------------ translated/tech/20160810 How does gdb work.md | 219 +++++++++++++++++ 2 files changed, 219 insertions(+), 220 deletions(-) delete mode 100644 sources/tech/20160810 How does gdb work.md create mode 100644 translated/tech/20160810 How does gdb work.md diff --git a/sources/tech/20160810 How does gdb work.md b/sources/tech/20160810 How does gdb work.md deleted file mode 100644 index 56b0cfe7bf..0000000000 --- a/sources/tech/20160810 How does gdb work.md +++ /dev/null @@ -1,220 +0,0 @@ -translating by ucasFL - -How does gdb work? -============================================================ - -Hello! Today I was working a bit on my [ruby stacktrace project][1] and I realized that now I know a couple of things about how gdb works internally. - -Lately I’ve been using gdb to look at Ruby programs, so we’re going to be running gdb on a Ruby program. This really means the Ruby interpreter. First, we’re going to print out the address of a global variable: `ruby_current_thread`: - -### getting a global variable - -Here’s how to get the address of the global `ruby_current_thread`: - -``` -$ sudo gdb -p 2983 -(gdb) p & ruby_current_thread -$2 = (rb_thread_t **) 0x5598a9a8f7f0 - -``` - -There are a few places a variable can live: on the heap, the stack, or in your program’s text. Global variables are part of your program! You can think of them as being allocated at compile time, kind of. It turns out we can figure out the address of a global variable pretty easily! Let’s see how `gdb` came up with `0x5598a9a8f7f0`. - -We can find the approximate region this variable lives in by looking at a cool file in `/proc` called `/proc/$pid/maps`. - -``` -$ sudo cat /proc/2983/maps | grep bin/ruby -5598a9605000-5598a9886000 r-xp 00000000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby -5598a9a86000-5598a9a8b000 r--p 00281000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby -5598a9a8b000-5598a9a8d000 rw-p 00286000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby - -``` - -So! There’s this starting address `5598a9605000` That’s  _like_  `0x5598a9a8f7f0`, but different. How different? Well, here’s what I get when I subtract them: - -``` -(gdb) p/x 0x5598a9a8f7f0 - 0x5598a9605000 -$4 = 0x48a7f0 - -``` - -“What’s that number?”, you might ask? WELL. Let’s look at the **symbol table**for our program with `nm`. - -``` -sudo nm /proc/2983/exe | grep ruby_current_thread -000000000048a7f0 b ruby_current_thread - -``` - -What’s that we see? Could it be `0x48a7f0`? Yes it is! So!! If we want to find the address of a global variable in our program, all we need to do is look up the name of the variable in the symbol table, and then add that to the start of the range in `/proc/whatever/maps`, and we’re done! - -So now we know how gdb does that. But gdb does so much more!! Let’s skip ahead to… - -### dereferencing pointers - -``` -(gdb) p ruby_current_thread -$1 = (rb_thread_t *) 0x5598ab3235b0 - -``` - -The next thing we’re going to do is **dereference** that `ruby_current_thread`pointer. We want to see what’s in that address! To do that, gdb will run a bunch of system calls like this: - -``` -ptrace(PTRACE_PEEKTEXT, 2983, 0x5598a9a8f7f0, [0x5598ab3235b0]) = 0 - -``` - -You remember this address `0x5598a9a8f7f0`? gdb is asking “hey, what’s in that address exactly”? `2983` is the PID of the process we’re running gdb on. It’s using the `ptrace` system call which is how gdb does everything. - -Awesome! So we can dereference memory and figure out what bytes are at what memory addresses. Some useful gdb commands to know here are `x/40w variable` and `x/40b variable` which will display 40 words / bytes at a given address, respectively. - -### describing structs - -The memory at an address looks like this. A bunch of bytes! - -``` -(gdb) x/40b ruby_current_thread -0x5598ab3235b0: 16 -90 55 -85 -104 85 0 0 -0x5598ab3235b8: 32 47 50 -85 -104 85 0 0 -0x5598ab3235c0: 16 -64 -55 115 -97 127 0 0 -0x5598ab3235c8: 0 0 2 0 0 0 0 0 -0x5598ab3235d0: -96 -83 -39 115 -97 127 0 0 - -``` - -That’s useful, but not that useful! If you are a human like me and want to know what it MEANS, you need more. Like this: - -``` -(gdb) p *(ruby_current_thread) -$8 = {self = 94114195940880, vm = 0x5598ab322f20, stack = 0x7f9f73c9c010, - stack_size = 131072, cfp = 0x7f9f73d9ada0, safe_level = 0, raised_flag = 0, - last_status = 8, state = 0, waiting_fd = -1, passed_block = 0x0, - passed_bmethod_me = 0x0, passed_ci = 0x0, top_self = 94114195612680, - top_wrapper = 0, base_block = 0x0, root_lep = 0x0, root_svar = 8, thread_id = - 140322820187904, - -``` - -GOODNESS. That is a lot more useful. How does gdb know that there are all these cool fields like `stack_size`? Enter DWARF. DWARF is a way to store extra debugging data about your program, so that debuggers like gdb can do their job better! It’s generally stored as part of a binary. If I run `dwarfdump` on my Ruby binary, I get some output like this: - -(I’ve redacted it heavily to make it easier to understand) - -``` -DW_AT_name "rb_thread_struct" -DW_AT_byte_size 0x000003e8 -DW_TAG_member - DW_AT_name "self" - DW_AT_type <0x00000579> - DW_AT_data_member_location DW_OP_plus_uconst 0 -DW_TAG_member - DW_AT_name "vm" - DW_AT_type <0x0000270c> - DW_AT_data_member_location DW_OP_plus_uconst 8 -DW_TAG_member - DW_AT_name "stack" - DW_AT_type <0x000006b3> - DW_AT_data_member_location DW_OP_plus_uconst 16 -DW_TAG_member - DW_AT_name "stack_size" - DW_AT_type <0x00000031> - DW_AT_data_member_location DW_OP_plus_uconst 24 -DW_TAG_member - DW_AT_name "cfp" - DW_AT_type <0x00002712> - DW_AT_data_member_location DW_OP_plus_uconst 32 -DW_TAG_member - DW_AT_name "safe_level" - DW_AT_type <0x00000066> - -``` - -So. The name of the type of `ruby_current_thread` is `rb_thread_struct`. It has size `0x3e8` (or 1000 bytes), and it has a bunch of member items. `stack_size` is one of them, at an offset of 24, and it has type 31\. What’s 31? No worries! We can look that up in the DWARF info too! - -``` -< 1><0x00000031> DW_TAG_typedef - DW_AT_name "size_t" - DW_AT_type <0x0000003c> -< 1><0x0000003c> DW_TAG_base_type - DW_AT_byte_size 0x00000008 - DW_AT_encoding DW_ATE_unsigned - DW_AT_name "long unsigned int" - -``` - -So! `stack_size` has type `size_t`, which means `long unsigned int`, and is 8 bytes. That means that we can read the stack size! - -How that would break down, once we have the DWARF debugging data, is: - -1. Read the region of memory that `ruby_current_thread` is pointing to - -2. Add 24 bytes to get to `stack_size` - -3. Read 8 bytes (in little-endian format, since we’re on x86) - -4. Get the answer! - -Which in this case is 131072 or 128 kb. - -To me, this makes it a lot more obvious what debugging info is **for** – if we didn’t have all this extra metadata about what all these variables meant, we would have no idea what the bytes at address `0x5598ab3235b0` meant. - -This is also why you can install debug info for a program separately from your program – gdb doesn’t care where it gets the extra debug info from. - -### DWARF is confusing - -I’ve been reading a bunch of DWARF info recently. Right now I’m using libdwarf which hasn’t been the best experience – the API is confusing, you initialize everything in a weird way, and it’s really slow (it takes 0.3 seconds to read all the debugging data out of my Ruby program which seems ridiculous). I’ve been told that libdw from elfutils is better. - -Also, I casually remarked that you can look at `DW_AT_data_member_location` to get the offset of a struct member! But I looked up on Stack Overflow how to actually do that and I got [this answer][2]. Basically you start with a check like: - -``` -dwarf_whatform(attrs[i], &form, &error); - if (form == DW_FORM_data1 || form == DW_FORM_data2 - form == DW_FORM_data2 || form == DW_FORM_data4 - form == DW_FORM_data8 || form == DW_FORM_udata) { - -``` - -and then it keeps GOING. Why are there 8 million different `DW_FORM_data` things I need to check for? What is happening? I have no idea. - -Anyway my impression is that DWARF is a large and complicated standard (and possibly the libraries people use to generate DWARF are subtly incompatible?), but it’s what we have, so that’s what we work with! - -I think it’s really cool that I can write code that reads DWARF and my code actually mostly works. Except when it crashes. I’m working on that. - -### unwinding stacktraces - -In an earlier version of this post, I said that gdb unwinds stacktraces using libunwind. It turns out that this isn’t true at all! - -Someone who’s worked on gdb a lot emailed me to say that they actually spent a ton of time figuring out how to unwind stacktraces so that they can do a better job than libunwind does. This means that if you get stopped in the middle of a weird program with less debug info than you might hope for that’s done something strange with its stack, gdb will try to figure out where you are anyway. Thanks <3 - -### other things gdb does - -The few things I’ve described here (reading memory, understanding DWARF to show you structs) aren’t everything gdb does – just looking through Brendan Gregg’s [gdb example from yesterday][3], we see that gdb also knows how to - -* disassemble assembly - -* show you the contents of your registers - -and in terms of manipulating your program, it can - -* set breakpoints and step through a program - -* modify memory (!! danger !!) - -Knowing more about how gdb works makes me feel a lot more confident when using it! I used to get really confused because gdb kind of acts like a C REPL sometimes – you type `ruby_current_thread->cfp->iseq`, and it feels like writing C code! But you’re not really writing C at all, and it was easy for me to run into limitations in gdb and not understand why. - -Knowing that it’s using DWARF to figure out the contents of the structs gives me a better mental model and have more correct expectations! Awesome. - --------------------------------------------------------------------------------- - -via: https://jvns.ca/blog/2016/08/10/how-does-gdb-work/ - -作者:[ Julia Evans][a] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]:https://jvns.ca/ -[1]:http://jvns.ca/blog/2016/06/12/a-weird-system-call-process-vm-readv/ -[2]:https://stackoverflow.com/questions/25047329/how-to-get-struct-member-offset-from-dwarf-info -[3]:http://www.brendangregg.com/blog/2016-08-09/gdb-example-ncurses.html diff --git a/translated/tech/20160810 How does gdb work.md b/translated/tech/20160810 How does gdb work.md new file mode 100644 index 0000000000..e45b988d3d --- /dev/null +++ b/translated/tech/20160810 How does gdb work.md @@ -0,0 +1,219 @@ +gdb 如何工作? +============================================================ + +大家好!今天,我开始进行我的 [ruby 堆栈跟踪项目][1],我意识到,我现在了解了一些关于 gdb 内部如何工作的内容。 + +最近,我使用 gdb 来查看我的 Ruby 程序,所以,我们将对一个 Ruby 程序运行 gdb 。它实际上就是一个 Ruby 解释器。首先,我们需要打印出一个全局变量的地址:`ruby_current_thread`。 + +### 获取全局变量 + +下面展示了如何获取全局变量 `ruby_current_thread` 的地址: + +``` +$ sudo gdb -p 2983 +(gdb) p & ruby_current_thread +$2 = (rb_thread_t **) 0x5598a9a8f7f0 + +``` + +变量能够位于的地方有堆、栈或者程序的文本段。全局变量也是程序的一部分。某种程度上,你可以把它们想象成是在编译的时候分配的。因此,我们可以很容易的找出全局变量的地址。让我们来看看,gdb 是如何找出 `0x5598a9a87f0` 这个地址的。 + +我们可以通过查看位于 `/proc` 目录下一个叫做 `/proc/$pid/maps` 的文件,来找到这个变量所位于的大致区域。 + + +``` +$ sudo cat /proc/2983/maps | grep bin/ruby +5598a9605000-5598a9886000 r-xp 00000000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby +5598a9a86000-5598a9a8b000 r--p 00281000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby +5598a9a8b000-5598a9a8d000 rw-p 00286000 00:32 323508 /home/bork/.rbenv/versions/2.1.6/bin/ruby + +``` + +所以,我们看到,起始地址 `5598a9605000` 和 `0x5598a9a8f7f0` 很像,但并不一样。哪里不一样呢,我们把两个数相减,看看结果是多少: + +``` +(gdb) p/x 0x5598a9a8f7f0 - 0x5598a9605000 +$4 = 0x48a7f0 + +``` + +你可能会问,这个数是什么?让我们使用 `nm` 来查看一下程序的符号表。 + +``` +sudo nm /proc/2983/exe | grep ruby_current_thread +000000000048a7f0 b ruby_current_thread + +``` + +我们看到了什么?能够看到 `0x48a7f0` 吗?是的,没错。所以,如果我们想找到程序中一个全局变量的地址,那么只需在符号表中查找变量的名字,然后再加上在 `/proc/whatever/maps` 中的起始地址,就得到了。 + +所以现在,我们知道 gdb 做了什么。但是,gdb 实际做的事情更多,让我们跳过直接转到… + +### 解引用指针 + +``` +(gdb) p ruby_current_thread +$1 = (rb_thread_t *) 0x5598ab3235b0 + +``` + +我们要做的下一件事就是解引用 `ruby_current_thread` 这一指针。我们想看一下它所指向的地址。为了完成这件事,gdb 会运行大量系统调用比如: + +``` +ptrace(PTRACE_PEEKTEXT, 2983, 0x5598a9a8f7f0, [0x5598ab3235b0]) = 0 + +``` + +你是否还记得 `0x5598a9a8f7f0` 这个地址?gdb 会问:“嘿,在这个地址中的实际内容是什么?”。`2983` 是我们运行 gdb 这个进程的 ID。gdb 使用 `ptrace` 这一系统调用来完成这一件事。 + +好极了!因此,我们可以解引用内存并找出内存地址中存储的内容。一些有用的 gdb 命令能够分别知道 `x/40w` 和 `x/40b` 这两个变量哪一个会在给定地址展示 40 个字/字节。 + +### 描述结构 + +一个内存地址中的内容可能看起来像下面这样。大量的字节! + +``` +(gdb) x/40b ruby_current_thread +0x5598ab3235b0: 16 -90 55 -85 -104 85 0 0 +0x5598ab3235b8: 32 47 50 -85 -104 85 0 0 +0x5598ab3235c0: 16 -64 -55 115 -97 127 0 0 +0x5598ab3235c8: 0 0 2 0 0 0 0 0 +0x5598ab3235d0: -96 -83 -39 115 -97 127 0 0 + +``` + +这很有用,但也不是非常有用!如果你是一个像我一样的人类并且想知道它代表什么,那么你需要更多内容,比如像这样: + +``` +(gdb) p *(ruby_current_thread) +$8 = {self = 94114195940880, vm = 0x5598ab322f20, stack = 0x7f9f73c9c010, + stack_size = 131072, cfp = 0x7f9f73d9ada0, safe_level = 0, raised_flag = 0, + last_status = 8, state = 0, waiting_fd = -1, passed_block = 0x0, + passed_bmethod_me = 0x0, passed_ci = 0x0, top_self = 94114195612680, + top_wrapper = 0, base_block = 0x0, root_lep = 0x0, root_svar = 8, thread_id = + 140322820187904, + +``` + +太好了。现在就更加有用了。gdb 是如何知道这些所有域的,比如 `stack_size` ?输入 `DWARF`。`DWARF` 是存储额外程序调试数据的一种方式,从而调试器比如 gdb 能够更好的工作。它通常存储为一部分二进制。如果我对我的 Ruby 二进制文件运行 `dwarfdump` 命令,那么我将会得到下面的输出: + +(我已经重新编排使得它更容易理解) + +``` +DW_AT_name "rb_thread_struct" +DW_AT_byte_size 0x000003e8 +DW_TAG_member + DW_AT_name "self" + DW_AT_type <0x00000579> + DW_AT_data_member_location DW_OP_plus_uconst 0 +DW_TAG_member + DW_AT_name "vm" + DW_AT_type <0x0000270c> + DW_AT_data_member_location DW_OP_plus_uconst 8 +DW_TAG_member + DW_AT_name "stack" + DW_AT_type <0x000006b3> + DW_AT_data_member_location DW_OP_plus_uconst 16 +DW_TAG_member + DW_AT_name "stack_size" + DW_AT_type <0x00000031> + DW_AT_data_member_location DW_OP_plus_uconst 24 +DW_TAG_member + DW_AT_name "cfp" + DW_AT_type <0x00002712> + DW_AT_data_member_location DW_OP_plus_uconst 32 +DW_TAG_member + DW_AT_name "safe_level" + DW_AT_type <0x00000066> + +``` + +所以,`ruby_current_thread` 的类型名为 `rb_thread_struct`,它的大小为 0x3e8 (或 1000 字节),它有许多成员项,`stack_size` 是其中之一,在偏移为 24 的地方,它有类型 `31\` 。`31` 是什么?不用担心,我们也可以在 DWARF 信息中查看。 + +``` +< 1><0x00000031> DW_TAG_typedef + DW_AT_name "size_t" + DW_AT_type <0x0000003c> +< 1><0x0000003c> DW_TAG_base_type + DW_AT_byte_size 0x00000008 + DW_AT_encoding DW_ATE_unsigned + DW_AT_name "long unsigned int" + +``` + +所以,`stack_size` 具有类型 `size_t`,即 `long unsigned int`,它是 8 字节的。这意味着我们可以查看栈大小。 + +如果我们有了 DWARF 调试数据,该如何分解: + +1. 查看 `ruby_current_thread` 所指向的内存区域 + +2. 加上 24 字节来得到 `stack_size` + +3. 读 8 字节(以小端的格式,因为是在 x86 上) + +4. 得到答案! + +在上面这个例子中是 131072 或 128 kb 。 + +对我来说,这使得调试信息的用途更加明显。如果我们不知道这些所有变量所表示的额外元数据,那么我们无法知道在 `0x5598ab325b0` 这一地址的字节是什么。 + +这就是为什么你可以从你的程序中单独安装一个程序的调试信息,因为 gdb 并不关心从何处获取额外的调试信息。 + +### DWARF 很迷惑 + +我最近阅读了大量的 DWARF 信息。现在,我使用 libdwarf,使用体验不是很好,这个 API 很令人迷惑,你将以一种奇怪的方式初始化所有东西,它真的很慢(需要花费 0.3 s 的时间来读取我的 Ruby 程序的所有调试信息,这真是可笑)。有人告诉我,libdw 比 elfutils 要好一些。 + +同样,你可以查看 `DW_AT_data_member_location` 来查看结构成员的偏移。我在 Stack Overflow 上查找如何完成这件事,并且得到[这个答案][2]。基本上,以下面这样一个检查开始: + +``` +dwarf_whatform(attrs[i], &form, &error); + if (form == DW_FORM_data1 || form == DW_FORM_data2 + form == DW_FORM_data2 || form == DW_FORM_data4 + form == DW_FORM_data8 || form == DW_FORM_udata) { + +``` + +继续往前。为什么会有 800 万种不同的 `DW_FORM_data` 需要检查?发生了什么?我没有头绪。 + +不管怎么说,我的印象是,DWARF 是一个庞大而复杂的标准(可能是人们用来生成 DWARF 的库不匹配),但是这是我们所拥有的,所以我们只能用它来工作。 + +我能够编写代码并查看 DWARF 并且我的代码实际上大多数能够工作,这就很酷了,除了程序崩溃的时候。我就是这样工作的。 + +### 展开栈路径 + +在这篇文章的早期版本中,我说过,gdb 使用 libunwind 来展开栈路径,这样说并不总是对的。 + +有一位对 gdb 有深入研究的人发了大量邮件告诉我,他们花费了大量时间来尝试如何展开栈路径从而能够做得比 libunwind 更好。这意味着,如果你在程序的一个奇怪的中间位置停下来了,你所能够获取的调试信息又很少,那么你可以对栈做一些奇怪的事情,gdb 会尝试找出你位于何处。 + +### gdb 能做的其他事 + +我在这儿所描述的一些事请(查看内存,理解 DWARF 所展示的结构)并不是 gdb 能够做的全部事情。阅读 Brendan Gregg 的[昔日 gdb 例子][3],我们可以知道,gdb 也能够完成下面这些事情: + +* 反汇编 + +* 查看寄存器内容 + +在操作程序方面,它可以: + +* 设置断点,单步运行程序 + +* 修改内存(这是一个危险行为) + +了解 gdb 如何工作使得当我使用它的时候更加自信。我过去经常感到迷惑,因为 gdb 有点像 C,当你输入 `ruby_current_thread->cfp->iseq`,就好像是在写 C 代码。但是你并不是在写 C 代码。我很容易遇到 gdb 的限制,不知道为什么。 + +知道使用 DWARF 来找出结构内容给了我一个更好的心理模型和更加正确的期望!这真是极好的! + +-------------------------------------------------------------------------------- + +via: https://jvns.ca/blog/2016/08/10/how-does-gdb-work/ + +作者:[Julia Evans][a] +译者:[ucasFL](https://github.com/ucasFL) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://jvns.ca/ +[1]:http://jvns.ca/blog/2016/06/12/a-weird-system-call-process-vm-readv/ +[2]:https://stackoverflow.com/questions/25047329/how-to-get-struct-member-offset-from-dwarf-info +[3]:http://www.brendangregg.com/blog/2016-08-09/gdb-example-ncurses.html From d6f40c87c23a1f57e3243375ae79c77ebf8b2b53 Mon Sep 17 00:00:00 2001 From: wxy Date: Mon, 5 Mar 2018 22:57:12 +0800 Subject: [PATCH 14/26] PRF:20171214 6 open source home automation tools.md @qhwdw --- ...214 6 open source home automation tools.md | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/translated/tech/20171214 6 open source home automation tools.md b/translated/tech/20171214 6 open source home automation tools.md index 742ab453fe..017e0fd447 100644 --- a/translated/tech/20171214 6 open source home automation tools.md +++ b/translated/tech/20171214 6 open source home automation tools.md @@ -1,35 +1,37 @@ 6 个开源的家庭自动化工具 ====== +> 用这些开源软件解决方案构建一个更智能的家庭。 + ![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520x292_openlightbulbs.png?itok=nrv9hgnH) [物联网][13] 不仅是一个时髦词,在现实中,自 2016 年我们发布了一篇关于家庭自动化工具的评论文章以来,它也在迅速占领着我们的生活。在 2017,[26.5% 的美国家庭][14] 已经使用了一些智能家居技术;预计五年内,这一数字还将翻倍。 -使用数量持续增加的各种设备,可以帮助你实现对家庭的自动化管理、安保、和监视,在家庭自动化方面,从来没有像现在这样容易和更加吸引人过。不论你是要远程控制你的 HVAC 系统,集成一个家庭影院,保护你的家免受盗窃、火灾、或是其它威胁,还是节省能源或只是控制几盏灯,现在都有无数的设备可以帮到你。 +随着这些数量持续增加的各种设备的使用,可以帮助你实现对家庭的自动化管理、安保、和监视,在家庭自动化方面,从来没有像现在这样容易和更加吸引人过。不论你是要远程控制你的 HVAC 系统,集成一个家庭影院,保护你的家免受盗窃、火灾、或是其它威胁,还是节省能源或只是控制几盏灯,现在都有无数的设备可以帮到你。 -但同时,还有许多用户担心安装在他们家庭中的新设备带来的安全和隐私问题 —— 一个很现实也很 [严肃的问题][15]。他们想要去控制有谁可以接触到这个重要的系统,这个系统管理着他们的应用程序,记录了他们生活中的点点滴滴。这种想法是可以理解的:毕竟在一个连你的冰箱都是智能设备的今天,你不想要一个基本的保证吗?甚至是如果你授权了设备可以与外界通讯,它是否是仅被授权的人能够访问它呢? +但同时,还有许多用户担心安装在他们家庭中的新设备带来的安全和隐私问题 —— 这是一个很现实也很 [严肃的问题][15]。他们想要去控制有谁可以接触到这个重要的系统,这个系统管理着他们的应用程序,记录了他们生活中的点点滴滴。这种想法是可以理解的:毕竟在一个连你的冰箱都是智能设备的今天,你不想要一个基本的保证吗?甚至是如果你授权了设备可以与外界通讯,它是否是仅被授权的人访问它呢? [对安全的担心][16] 是为什么开源对我们将来使用的互联设备至关重要的众多理由之一。由于源代码运行在他们自己的设备上,完全可以去搞明白控制你的家庭的程序,也就是说你可以查看它的代码,如果必要的话甚至可以去修改它。 -虽然联网设备通常都包含他们专有的组件,但是将开源引入家庭自动化的第一步是确保你的设备和这些设备可以共同工作 —— 它们为你提供一个接口—— 并且是开源的。幸运的是,现在有许多解决方案可供选择,从 PC 到树莓派,你可以在它们上做任何事情。 +虽然联网设备通常都包含它们专有的组件,但是将开源引入家庭自动化的第一步是确保你的设备和这些设备可以共同工作 —— 它们为你提供一个接口 —— 并且是开源的。幸运的是,现在有许多解决方案可供选择,从 PC 到树莓派,你可以在它们上做任何事情。 这里有几个我比较喜欢的。 ### Calaos -[Calaos][17] 是一个设计为全栈家庭自动化的平台,包含一个服务器应用程序、触摸屏接口、Web 应用程序、支持 iOS 和 Android 的原生移动应用、以及一个运行在底层的预配置好的 Linux 操作系统。Calaos 项目出自一个法国公司,因此它的支持论坛以法语为主,不过大量的介绍资料和文档都已经翻译为英语了。 +[Calaos][17] 是一个设计为全栈的家庭自动化平台,包含一个服务器应用程序、触摸屏界面、Web 应用程序、支持 iOS 和 Android 的原生移动应用、以及一个运行在底层的预配置好的 Linux 操作系统。Calaos 项目出自一个法国公司,因此它的支持论坛以法语为主,不过大量的介绍资料和文档都已经翻译为英语了。 Calaos 使用的是 [GPL][18] v3 的许可证,你可以在 [GitHub][19] 上查看它的源代码。 ### Domoticz -[Domoticz][20] 是一个有大量设备库支持的家庭自动化系统,在它的项目网站上有大量的文档,从气象站到远程控制的烟雾探测器,以及大量的第三方 [集成][21] 。它使用一个 HTML5 前端,可以从桌面浏览器或者大多数现代的智能手机上访问它,它是一个轻量级的应用,可以运行在像树莓派这样的低功耗设备上。 +[Domoticz][20] 是一个有大量设备库支持的家庭自动化系统,在它的项目网站上有大量的文档,从气象站到远程控制的烟雾探测器,以及大量的第三方 [集成软件][21] 。它使用一个 HTML5 前端,可以从桌面浏览器或者大多数现代的智能手机上访问它,它是一个轻量级的应用,可以运行在像树莓派这样的低功耗设备上。 Domoticz 是用 C++ 写的,使用 [GPLv3][22] 许可证。它的 [源代码][23] 在 GitHub 上。 ### Home Assistant -[Home Assistant][24] 是一个开源的家庭自动化平台,它可以轻松部署在任何能运行 Python 3 的机器上,从树莓派到网络附加存储(NAS),甚至可以使用 Docker 容器轻松地部署到其它系统上。它集成了大量的开源的和商业的产品,允许你去连接它们,比如,IFTTT、天气信息、或者你的 Amazon Echo 设备,去控制从锁到灯的各种硬件。 +[Home Assistant][24] 是一个开源的家庭自动化平台,它可以轻松部署在任何能运行 Python 3 的机器上,从树莓派到网络存储(NAS),甚至可以使用 Docker 容器轻松地部署到其它系统上。它集成了大量的开源和商业的产品,允许你去连接它们,比如,IFTTT、天气信息、或者你的 Amazon Echo 设备,去控制从锁到灯的各种硬件。 Home Assistant 以 [MIT 许可证][25] 发布,它的源代码可以从 [GitHub][26] 上下载。 @@ -41,26 +43,26 @@ MisterHouse 使用 [GPLv2][28] 许可证,你可以在 [GitHub][29] 上查看 ### OpenHAB -[OpenHAB][30](开放家庭自动化总线的简称)是在开源爱好者中大家熟知的家庭自动化工具,它拥有大量用户的社区以及支持和集成了大量的设备。它是用 Java 写的,OpenHAB 非常轻便,可以跨大多数主流操作系统使用,它甚至在树莓派上也运行的很好。支持成百上千的设备,OpenHAB 被设计为与设备无关的,这使开发者在系统中添加他们的设备或者插件很容易。OpenHAB 也支持通过 iOS 和 Android 应用来控制设备以及设计工具,因此,你可以为你的家庭系统创建你自己的 UI。 +[OpenHAB][30](开放家庭自动化总线的简称)是在开源爱好者中所熟知的家庭自动化工具,它拥有大量用户的社区以及支持和集成了大量的设备。它是用 Java 写的,OpenHAB 非常轻便,可以跨大多数主流操作系统使用,它甚至在树莓派上也运行的很好。支持成百上千的设备,OpenHAB 被设计为与设备无关的,这使开发者在系统中添加他们的设备或者插件很容易。OpenHAB 也支持通过 iOS 和 Android 应用来控制设备以及设计工具,因此,你可以为你的家庭系统创建你自己的 UI。 你可以在 GitHub 上找到 OpenHAB 的 [源代码][31],它使用 [Eclipse 公共许可证][32]。 ### OpenMotics -[OpenMotics][33] 是一个开源的硬件和软件家庭自动化系统。它的设计目标是为控制设备提供一个综合的系统,而不是从不同的供应商处将各种设备拼接在一起。不像其它的系统主要是为了方便的改装而设计的,OpenMotics 专注于硬件解决方案。更多资料请查阅来自 OpenMotics 的后端开发者 Frederick Ryckbosch的 [完整文章][34] 。 +[OpenMotics][33] 是一个开源的硬件和软件家庭自动化系统。它的设计目标是为控制设备提供一个综合的系统,而不是从不同的供应商处将各种设备拼接在一起。不像其它的系统主要是为了方便改装而设计的,OpenMotics 专注于硬件解决方案。更多资料请查阅来自 OpenMotics 的后端开发者 Frederick Ryckbosch的 [完整文章][34] 。 OpenMotics 使用 [GPLv2][35] 许可证,它的源代码可以从 [GitHub][36] 上下载。 -当然了,我们的选择不仅有这些。许多家庭自动化爱好者使用不同的解决方案,甚至是它们自己动手做。其它用户选择使用单独的智能家庭设备而无需集成它们到一个单一的综合系统中。 +当然了,我们的选择不仅有这些。许多家庭自动化爱好者使用不同的解决方案,甚至是他们自己动手做。其它用户选择使用单独的智能家庭设备而无需集成它们到一个单一的综合系统中。 如果上面的解决方案并不能满足你的需求,下面还有一些潜在的替代者可以去考虑: * [EventGhost][1] 是一个开源的([GPL v2][2])家庭影院自动化工具,它只能运行在 Microsoft Windows PC 上。它允许用户去控制多媒体电脑和连接的硬件,它通过触发宏指令的插件或者定制的 Python 脚本来使用。 * [ioBroker][3] 是一个基于 JavaScript 的物联网平台,它能够控制灯、锁、空调、多媒体、网络摄像头等等。它可以运行在任何可以运行 Node.js 的硬件上,包括 Windows、Linux、以及 macOS,它使用 [MIT 许可证][4]。 -* [Jeedom][5] 是一个由开源软件([GPL v2][6])构成的家庭自动化平台,它可以控制灯、锁、多媒体等等。它包含一个移动应用程序(Android 和 iOS),并且可以运行在 Linux PC 上;该公司也销售 hubs,它为配置家庭自动化提供一个现成的解决方案。 +* [Jeedom][5] 是一个由开源软件([GPL v2][6])构成的家庭自动化平台,它可以控制灯、锁、多媒体等等。它包含一个移动应用程序(Android 和 iOS),并且可以运行在 Linux PC 上;该公司也销售 hub,它为配置家庭自动化提供一个现成的解决方案。 * [LinuxMCE][7] 标称它是你的多媒体与电子设备之间的“数字粘合剂”。它运行在 Linux(包括树莓派)上,它基于 Pluto 开源 [许可证][8] 发布,它可以用于家庭安全、电话(VoIP 和语音信箱)、A/V 设备、家庭自动化、以及玩视频游戏。 * [OpenNetHome][9],和这一类中的其它解决方案一样,是一个控制灯、报警、应用程序等等的一个开源软件。它基于 Java 和 Apache Maven,可以运行在 Windows、macOS、以及 Linux —— 包括树莓派,它以 [GPLv3][10] 许可证发布。 -* [Smarthomatic][11] 是一个专注于硬件设备和软件的开源家庭自动化框架,而不仅是用户接口。它基于 [GPLv3][12] 许可证,它可用于控制灯、电器、以及空调、检测温度、提醒给植物浇水。 +* [Smarthomatic][11] 是一个专注于硬件设备和软件的开源家庭自动化框架,而不仅是用户界面。它基于 [GPLv3][12] 许可证,它可用于控制灯、电器、以及空调、检测温度、提醒给植物浇水。 现在该轮到你了:你已经准备好家庭自动化系统了吗?或者正在研究去设计一个。你对家庭自动化的新手有什么建议,你会推荐什么样的系统? @@ -70,7 +72,7 @@ via: https://opensource.com/life/17/12/home-automation-tools 作者:[Jason Baker][a] 译者:[qhwdw](https://github.com/qhwdw) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 From 115a1b704b9deaa80a77536ff997ac982152a0c5 Mon Sep 17 00:00:00 2001 From: wxy Date: Mon, 5 Mar 2018 22:57:30 +0800 Subject: [PATCH 15/26] PUB:20171214 6 open source home automation tools.md @qhwdw --- .../20171214 6 open source home automation tools.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {translated/tech => published}/20171214 6 open source home automation tools.md (100%) diff --git a/translated/tech/20171214 6 open source home automation tools.md b/published/20171214 6 open source home automation tools.md similarity index 100% rename from translated/tech/20171214 6 open source home automation tools.md rename to published/20171214 6 open source home automation tools.md From 70f9cd171fdeadfb6e5a2df2c9effa7049209dfe Mon Sep 17 00:00:00 2001 From: Feng Lv Date: Mon, 5 Mar 2018 22:58:36 +0800 Subject: [PATCH 16/26] translated --- .../20180104 How does gdb call functions.md | 254 ------------------ .../20180104 How does gdb call functions.md | 254 ++++++++++++++++++ 2 files changed, 254 insertions(+), 254 deletions(-) delete mode 100644 sources/tech/20180104 How does gdb call functions.md create mode 100644 translated/tech/20180104 How does gdb call functions.md diff --git a/sources/tech/20180104 How does gdb call functions.md b/sources/tech/20180104 How does gdb call functions.md deleted file mode 100644 index c88fae999e..0000000000 --- a/sources/tech/20180104 How does gdb call functions.md +++ /dev/null @@ -1,254 +0,0 @@ -translating by ucasFL - -How does gdb call functions? -============================================================ - -(previous gdb posts: [how does gdb work? (2016)][4] and [three things you can do with gdb (2014)][5]) - -I discovered this week that you can call C functions from gdb! I thought this was cool because I’d previously thought of gdb as mostly a read-only debugging tool. - -I was really surprised by that (how does that WORK??). As I often do, I asked [on Twitter][6] how that even works, and I got a lot of really useful answers! My favorite answer was [Evan Klitzke’s example C code][7] showing a way to do it. Code that  _works_  is very exciting! - -I believe (through some stracing & experiments) that that example C code is different from how gdb actually calls functions, so I’ll talk about what I’ve figured out about what gdb does in this post and how I’ve figured it out. - -There is a lot I still don’t know about how gdb calls functions, and very likely some things in here are wrong. - -### What does it mean to call a C function from gdb? - -Before I get into how this works, let’s talk quickly about why I found it surprising / nonobvious. - -So, you have a running C program (the “target program”). You want to run a function from it. To do that, you need to basically: - -* pause the program (because it is already running code!) - -* find the address of the function you want to call (using the symbol table) - -* convince the program (the “target program”) to jump to that address - -* when the function returns, restore the instruction pointer and registers to what they were before - -Using the symbol table to figure out the address of the function you want to call is pretty straightforward – here’s some sketchy (but working!) Rust code that I’ve been using on Linux to do that. This code uses the [elf crate][8]. If I wanted to find the address of the `foo` function in PID 2345, I’d run `elf_symbol_value("/proc/2345/exe", "foo")`. - -``` -fn elf_symbol_value(file_name: &str, symbol_name: &str) -> Result> { - // open the ELF file - let file = elf::File::open_path(file_name).ok().ok_or("parse error")?; - // loop over all the sections & symbols until you find the right one! - let sections = &file.sections; - for s in sections { - for sym in file.get_symbols(&s).ok().ok_or("parse error")? { - if sym.name == symbol_name { - return Ok(sym.value); - } - } - } - None.ok_or("No symbol found")? -} - -``` - -This won’t totally work on its own, you also need to look at the memory maps of the file and add the symbol offset to the start of the place that file is mapped. But finding the memory maps isn’t so hard, they’re in `/proc/PID/maps`. - -Anyway, this is all to say that finding the address of the function to call seemed straightforward to me but that the rest of it (change the instruction pointer? restore the registers? what else?) didn’t seem so obvious! - -### You can’t just jump - -I kind of said this already but – you can’t just find the address of the function you want to run and then jump to that address. I tried that in gdb (`jump foo`) and the program segfaulted. Makes sense! - -### How you can call C functions from gdb - -First, let’s see that this is possible. I wrote a tiny C program that sleeps for 1000 seconds and called it `test.c`: - -``` -#include - -int foo() { - return 3; -} -int main() { - sleep(1000); -} - -``` - -Next, compile and run it: - -``` -$ gcc -o test test.c -$ ./test - -``` - -Finally, let’s attach to the `test` program with gdb: - -``` -$ sudo gdb -p $(pgrep -f test) -(gdb) p foo() -$1 = 3 -(gdb) quit - -``` - -So I ran `p foo()` and it ran the function! That’s fun. - -### Why is this useful? - -a few possible uses for this: - -* it lets you treat gdb a little bit like a C REPL, which is fun and I imagine could be useful for development - -* utility functions to display / navigate complex data structures quickly while debugging in gdb (thanks [@invalidop][1]) - -* [set an arbitrary process’s namespace while it’s running][2] (featuring a not-so-surprising appearance from my colleague [nelhage][3]!) - -* probably more that I don’t know about - -### How it works - -I got a variety of useful answers on Twitter when I asked how calling functions from gdb works! A lot of them were like “well you get the address of the function from the symbol table” but that is not the whole story!! - -One person pointed me to this nice 2 part series on how gdb works that they’d written: [Debugging with the natives, part 1][9] and [Debugging with the natives, part 2][10]. Part 1 explains approximately how calling functions works (or could work – figuring out what gdb **actually** does isn’t trivial, but I’ll try my best!). - -The steps outlined there are: - -1. Stop the process - -2. Create a new stack frame (far away from the actual stack) - -3. Save all the registers - -4. Set the registers to the arguments you want to call your function with - -5. Set the stack pointer to the new stack frame - -6. Put a trap instruction somewhere in memory - -7. Set the return address to that trap instruction - -8. Set the instruction pointer register to the address of the function you want to call - -9. Start the process again! - -I’m not going to go through how gdb does all of these (I don’t know!) but here are a few things I’ve learned about the various pieces this evening. - -**Create a stack frame** - -If you’re going to run a C function, most likely it needs a stack to store variables on! You definitely don’t want it to clobber your current stack. Concretely – before gdb calls your function (by setting the instruction pointer to it and letting it go), it needs to set the **stack pointer** to… something. - -There was some speculation on Twitter about how this works: - -> i think it constructs a new stack frame for the call right on top of the stack where you’re sitting! - -and: - -> Are you certain it does that? It could allocate a pseudo stack, then temporarily change sp value to that location. You could try, put a breakpoint there and look at the sp register address, see if it’s contiguous to your current program register? - -I did an experiment where (inside gdb) I ran:` - -``` -(gdb) p $rsp -$7 = (void *) 0x7ffea3d0bca8 -(gdb) break foo -Breakpoint 1 at 0x40052a -(gdb) p foo() -Breakpoint 1, 0x000000000040052a in foo () -(gdb) p $rsp -$8 = (void *) 0x7ffea3d0bc00 - -``` - -This seems in line with the “gdb constructs a new stack frame for the call right on top of the stack where you’re sitting” theory, since the stack pointer (`$rsp`) goes from being `...bca8` to `..bc00` – stack pointers grow downward, so a `bc00`stack pointer is **after** a `bca8` pointer. Interesting! - -So it seems like gdb just creates the new stack frames right where you are. That’s a bit surprising to me! - -**change the instruction pointer** - -Let’s see whether gdb changes the instruction pointer! - -``` -(gdb) p $rip -$1 = (void (*)()) 0x7fae7d29a2f0 <__nanosleep_nocancel+7> -(gdb) b foo -Breakpoint 1 at 0x40052a -(gdb) p foo() -Breakpoint 1, 0x000000000040052a in foo () -(gdb) p $rip -$3 = (void (*)()) 0x40052a - -``` - -It does! The instruction pointer changes from `0x7fae7d29a2f0` to `0x40052a` (the address of the `foo` function). - -I stared at the strace output and I still don’t understand **how** it changes, but that’s okay. - -**aside: how breakpoints are set!!** - -Above I wrote `break foo`. I straced gdb while running all of this and understood almost nothing but I found ONE THING that makes sense to me!! - -Here are some of the system calls that gdb uses to set a breakpoint. It’s really simple! It replaces one instruction with `cc` (which [https://defuse.ca/online-x86-assembler.htm][11] tells me means `int3` which means `send SIGTRAP`), and then once the program is interrupted, it puts the instruction back the way it was. - -I was putting a breakpoint on a function `foo` with the address `0x400528`. - -This `PTRACE_POKEDATA` is how gdb changes the code of running programs. - -``` -// change the 0x400528 instructions -25622 ptrace(PTRACE_PEEKTEXT, 25618, 0x400528, [0x5d00000003b8e589]) = 0 -25622 ptrace(PTRACE_POKEDATA, 25618, 0x400528, 0x5d00000003cce589) = 0 -// start the program running -25622 ptrace(PTRACE_CONT, 25618, 0x1, SIG_0) = 0 -// get a signal when it hits the breakpoint -25622 ptrace(PTRACE_GETSIGINFO, 25618, NULL, {si_signo=SIGTRAP, si_code=SI_KERNEL, si_value={int=-1447215360, ptr=0x7ffda9bd3f00}}) = 0 -// change the 0x400528 instructions back to what they were before -25622 ptrace(PTRACE_PEEKTEXT, 25618, 0x400528, [0x5d00000003cce589]) = 0 -25622 ptrace(PTRACE_POKEDATA, 25618, 0x400528, 0x5d00000003b8e589) = 0 - -``` - -**put a trap instruction somewhere** - -When gdb runs a function, it **also** puts trap instructions in a bunch of places! Here’s one of them (per strace). It’s basically replacing one instruction with `cc` (`int3`). - -``` -5908 ptrace(PTRACE_PEEKTEXT, 5810, 0x7f6fa7c0b260, [0x48f389fd89485355]) = 0 -5908 ptrace(PTRACE_PEEKTEXT, 5810, 0x7f6fa7c0b260, [0x48f389fd89485355]) = 0 -5908 ptrace(PTRACE_POKEDATA, 5810, 0x7f6fa7c0b260, 0x48f389fd894853cc) = 0 - -``` - -What’s `0x7f6fa7c0b260`? Well, I looked in the process’s memory maps, and it turns it’s somewhere in `/lib/x86_64-linux-gnu/libc-2.23.so`. That’s weird! Why is gdb putting trap instructions in libc? - -Well, let’s see what function that’s in. It turns out it’s `__libc_siglongjmp`. The other functions gdb is putting traps in are `__longjmp`, `____longjmp_chk`, `dl_main`, and `_dl_close_worker`. - -Why? I don’t know! Maybe for some reason when our function `foo()` returns, it’s calling `longjmp`, and that is how gdb gets control back? I’m not sure. - -### how gdb calls functions is complicated! - -I’m going to stop there (it’s 1am!), but now I know a little more! - -It seems like the answer to “how does gdb call a function?” is definitely not that simple. I found it interesting to try to figure a little bit of it out and hopefully you have too! - -I still have a lot of unanswered questions about how exactly gdb does all of these things, but that’s okay. I don’t really need to know the details of how this works and I’m happy to have a slightly improved understanding. - --------------------------------------------------------------------------------- - -via: https://jvns.ca/blog/2018/01/04/how-does-gdb-call-functions/ - -作者:[Julia Evans ][a] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]:https://jvns.ca/ -[1]:https://twitter.com/invalidop/status/949161146526781440 -[2]:https://github.com/baloo/setns/blob/master/setns.c -[3]:https://github.com/nelhage -[4]:https://jvns.ca/blog/2016/08/10/how-does-gdb-work/ -[5]:https://jvns.ca/blog/2014/02/10/three-steps-to-learning-gdb/ -[6]:https://twitter.com/b0rk/status/948060808243765248 -[7]:https://github.com/eklitzke/ptrace-call-userspace/blob/master/call_fprintf.c -[8]:https://cole14.github.io/rust-elf -[9]:https://www.cl.cam.ac.uk/~srk31/blog/2016/02/25/#native-debugging-part-1 -[10]:https://www.cl.cam.ac.uk/~srk31/blog/2017/01/30/#native-debugging-part-2 -[11]:https://defuse.ca/online-x86-assembler.htm diff --git a/translated/tech/20180104 How does gdb call functions.md b/translated/tech/20180104 How does gdb call functions.md new file mode 100644 index 0000000000..575563ad3d --- /dev/null +++ b/translated/tech/20180104 How does gdb call functions.md @@ -0,0 +1,254 @@ +gdb 如何调用函数? +============================================================ + +(之前的 gdb 系列文章:[gdb 如何工作(2016)][4] 和[通过 gdb 你能够做的三件事(2014)][5]) + +在这个周,我发现,我可以从 gdb 上调用 C 函数。这看起来很酷,因为在过去我认为 gdb 最多只是一个只读调试工具。 + +我对 gdb 能够调用函数感到很吃惊。正如往常所做的那样,我在 [Twitter][6] 上询问这是如何工作的。我得到了大量的有用答案。我最喜欢的答案是 [Evan Klitzke 的示例 C 代码][7],它展示了 gdb 如何调用函数。代码能够运行,这很令人激动! + +我相信(通过一些跟踪和实验)那个示例 C 代码和 gdb 实际上如何调用函数不同。因此,在这篇文章中,我将会阐述 gdb 是如何调用函数的,以及我是如何知道的。 + +关于 gdb 如何调用函数,还有许多我不知道的事情,并且,在这儿我写的内容有可能是错误的。 + +### 从 gdb 中调用 C 函数意味着什么? + +在开始讲解这是如何工作之前,我先快速的谈论一下我是如何发现这件令人惊讶的事情的。 + +所以,你已经在运行一个 C 程序(目标程序)。你可以运行程序中的一个函数,只需要像下面这样做: + +* 暂停程序(因为它已经在运行中) + +* 找到你想调用的函数的地址(使用符号表) + +* 使程序(目标程序)跳转到那个地址 + +* 当函数返回时,恢复之前的指令指针和寄存器 + +通过符号表来找到想要调用的函数的地址非常容易。下面是一段非常简单但能够工作的代码,我在 Linux 上使用这段代码作为例子来讲解如何找到地址。这段代码使用 [elf crate][8]。如果我想找到 PID 为 2345 的进程中的 foo 函数的地址,那么我可以运行 `elf_symbol_value("/proc/2345/exe", "foo")`。 + +``` +fn elf_symbol_value(file_name: &str, symbol_name: &str) -> Result> { + // 打开 ELF 文件 + let file = elf::File::open_path(file_name).ok().ok_or("parse error")?; + // 在所有的段 & 符号中循环,直到找到正确的那个 + let sections = &file.sections; + for s in sections { + for sym in file.get_symbols(&s).ok().ok_or("parse error")? { + if sym.name == symbol_name { + return Ok(sym.value); + } + } + } + None.ok_or("No symbol found")? +} + +``` + +这并不能够真的发挥作用,你还需要找到文件的内存映射,并将符号偏移量加到文件映射的起始位置。找到内存映射并不困难,它位于 `/proc/PID/maps` 中。 + +总之,找到想要调用的函数地址对我来说很直接,但是其余部分(改变指令指针,恢复寄存器等)看起来就不这么明显了。 + +### 你不能仅仅进行跳转 + +我已经说过,你不能够仅仅找到你想要运行的那个函数地址,然后跳转到那儿。我在 gdb 中尝试过那样做(`jump foo`),然后程序出现了段错误。毫无意义。 + +### 如何从 gdb 中调用 C 函数 + +首先,这是可能的。我写了一个非常简洁的 C 程序,它所做的事只有 sleep 1000 秒,把这个文件命名为 `test.c` : + +``` +#include + +int foo() { + return 3; +} +int main() { + sleep(1000); +} + +``` + +接下来,编译并运行它: + +``` +$ gcc -o test test.c +$ ./test + +``` + +最后,我们使用 gdb 来跟踪 `test` 这一程序: + +``` +$ sudo gdb -p $(pgrep -f test) +(gdb) p foo() +$1 = 3 +(gdb) quit + +``` + +我运行 `p foo()` 然后它运行了这个函数!这非常有趣。 + +### 为什么这是有用的? + +下面是一些可能的用途: + +* 它使得你可以把 gdb 当成一个 C 应答式程序,这很有趣,我想对开发也会有用 + +* 在 gdb 中进行调试的时候展示/浏览复杂数据结构的功能函数(感谢 [@invalidop][1]) + +* [在进程运行时设置一个任意的名字空间][2](我的同事 [nelhage][3] 对此非常惊讶) + +* 可能还有许多我所不知道的用途 + +### 它是如何工作的 + +当我在 Twitter 上询问从 gdb 中调用函数是如何工作的时,我得到了大量有用的回答。许多答案是”你从符号表中得到了函数的地址“,但这并不是完整的答案。 + +有个人告诉了我两篇关于 gdb 如何工作的系列文章:[和本地人一起调试-第一部分][9],[和本地人一起调试-第二部分][10]。第一部分讲述了 gdb 是如何调用函数的(指出了 gdb 实际上完成这件事并不简单,但是我将会尽力)。 + +步骤列举如下: + +1. 停止进程 + +2. 创建一个新的栈框(远离真实栈) + +3. 保存所有寄存器 + +4. 设置你想要调用的函数的寄存器参数 + +5. 设置栈指针指向新的栈框 + +6. 在内存中某个位置放置一条陷阱指令 + +7. 为陷阱指令设置返回地址 + +8. 设置指令寄存器的值为你想要调用的函数地址 + +9. 再次运行进程! + +(LCTT 译注:如果将这个调用的函数看成一个单独的线程,gdb 实际上所做的事情就是一个简单的线程上下文切换) + +我不知道 gdb 是如何完成这些所有事情的,但是今天晚上,我学到了这些所有事情中的其中几件。 + +**创建一个栈框** + +如果你想要运行一个 C 函数,那么你需要一个栈来存储变量。你肯定不想继续使用当前的栈。准确来说,在 gdb 调用函数之前(通过设置函数指针并跳转),它需要设置栈指针到某个地方。 + +这儿是 Twitter 上一些关于它如何工作的猜测: + +> 我认为它在当前栈的栈顶上构造了一个新的栈框来进行调用! + +以及 + +> 你确定是这样吗?它应该是分配一个伪栈,然后临时将 sp (栈指针寄存器)的值改为那个栈的地址。你可以试一试,你可以在那儿设置一个断点,然后看一看栈指针寄存器的值,它是否和当前程序寄存器的值相近? + +我通过 gdb 做了一个试验: + +``` +(gdb) p $rsp +$7 = (void *) 0x7ffea3d0bca8 +(gdb) break foo +Breakpoint 1 at 0x40052a +(gdb) p foo() +Breakpoint 1, 0x000000000040052a in foo () +(gdb) p $rsp +$8 = (void *) 0x7ffea3d0bc00 + +``` + +这看起来符合”gdb 在当前栈的栈顶构造了一个新的栈框“这一理论。因为栈指针(`$rsp`)从 `0x7ffea3d0bca8` 变成了 `0x7ffea3d0bc00` - 栈指针从高地址往低地址长。所以 `0x7ffea3d0bca8` 在 `0x7ffea3d0bc00` 的后面。真是有趣! + +所以,看起来 gdb 只是在当前栈所在位置创建了一个新的栈框。这令我很惊讶! + +**改变指令指针** + +让我们来看一看 gdb 是如何改变指令指针的! + +``` +(gdb) p $rip +$1 = (void (*)()) 0x7fae7d29a2f0 <__nanosleep_nocancel+7> +(gdb) b foo +Breakpoint 1 at 0x40052a +(gdb) p foo() +Breakpoint 1, 0x000000000040052a in foo () +(gdb) p $rip +$3 = (void (*)()) 0x40052a + +``` + +的确是!指令指针从 `0x7fae7d29a2f0` 变为了 `0x40052a`(`foo` 函数的地址)。 + +我盯着输出看了很久,但仍然不理解它是如何改变指令指针的,但这并不影响什么。 + +**如何设置断点** + +上面我写到 `break foo` 。我跟踪 gdb 运行程序的过程,但是没有任何发现。 + +下面是 gdb 用来设置断点的一些系统调用。它们非常简单。它把一条指令用 `cc` 代替了(这告诉我们 `int3` 意味着 `send SIGTRAP` [https://defuse.ca/online-x86-assembler.html][11]),并且一旦程序被打断了,它就把指令恢复为原先的样子。 + +我在函数 `foo` 那儿设置了一个断点,地址为 `0x400528` 。 + +`PTRACE_POKEDATA` 展示了 gdb 如何改变正在运行的程序。 + +``` +// 改变 0x400528 处的指令 +25622 ptrace(PTRACE_PEEKTEXT, 25618, 0x400528, [0x5d00000003b8e589]) = 0 +25622 ptrace(PTRACE_POKEDATA, 25618, 0x400528, 0x5d00000003cce589) = 0 +// 开始运行程序 +25622 ptrace(PTRACE_CONT, 25618, 0x1, SIG_0) = 0 +// 当到达断点时获取一个信号 +25622 ptrace(PTRACE_GETSIGINFO, 25618, NULL, {si_signo=SIGTRAP, si_code=SI_KERNEL, si_value={int=-1447215360, ptr=0x7ffda9bd3f00}}) = 0 +// 将 0x400528 处的指令更改为之前的样子 +25622 ptrace(PTRACE_PEEKTEXT, 25618, 0x400528, [0x5d00000003cce589]) = 0 +25622 ptrace(PTRACE_POKEDATA, 25618, 0x400528, 0x5d00000003b8e589) = 0 + +``` + +**在某处放置一条陷阱指令** + +当 gdb 运行一个函数的时候,它也会在某个地方放置一条陷阱指令。这是其中一条。它基本上是用 `cc` 来替换一条指令(`int3`)。 + +``` +5908 ptrace(PTRACE_PEEKTEXT, 5810, 0x7f6fa7c0b260, [0x48f389fd89485355]) = 0 +5908 ptrace(PTRACE_PEEKTEXT, 5810, 0x7f6fa7c0b260, [0x48f389fd89485355]) = 0 +5908 ptrace(PTRACE_POKEDATA, 5810, 0x7f6fa7c0b260, 0x48f389fd894853cc) = 0 + +``` + +`0x7f6fa7c0b260` 是什么?我查看了进程的内存映射,发现它位于 `/lib/x86_64-linux-gnu/libc-2.23.so` 中的某个位置。这很奇怪,为什么 gdb 将陷阱指令放在 libc 中? + +让我们看一看里面的函数是什么,它是 `__libc_siglongjmp` 。其他 gdb 放置陷阱指令的地方的函数是 `__longjmp` 、`___longjmp_chk` 、`dl_main` 和 `_dl_close_worker` 。 + +为什么?我不知道!也许出于某种原因,当函数 `foo()` 返回时,它调用 `longjmp` ,从而 gdb 能够进行返回控制。我不确定。 + +### gdb 如何调用函数是很复杂的! + +我将要在这儿停止了(现在已经凌晨 1 点),但是我知道的多一些了! + +看起来”gdb 如何调用函数“这一问题的答案并不简单。我发现这很有趣并且努力找出其中一些答案,希望你也能够找到。 + +我依旧有很多未回答的问题,关于 gdb 是如何完成这些所有事的,但是可以了。我不需要真的知道关于 gdb 是如何工作的所有细节,但是我很开心,我有了一些进一步的理解。 + +-------------------------------------------------------------------------------- + +via: https://jvns.ca/blog/2018/01/04/how-does-gdb-call-functions/ + +作者:[Julia Evans][a] +译者:[ucasFL](https://github.com/ucasFL) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://jvns.ca/ +[1]:https://twitter.com/invalidop/status/949161146526781440 +[2]:https://github.com/baloo/setns/blob/master/setns.c +[3]:https://github.com/nelhage +[4]:https://jvns.ca/blog/2016/08/10/how-does-gdb-work/ +[5]:https://jvns.ca/blog/2014/02/10/three-steps-to-learning-gdb/ +[6]:https://twitter.com/b0rk/status/948060808243765248 +[7]:https://github.com/eklitzke/ptrace-call-userspace/blob/master/call_fprintf.c +[8]:https://cole14.github.io/rust-elf +[9]:https://www.cl.cam.ac.uk/~srk31/blog/2016/02/25/#native-debugging-part-1 +[10]:https://www.cl.cam.ac.uk/~srk31/blog/2017/01/30/#native-debugging-part-2 +[11]:https://defuse.ca/online-x86-assembler.htm From c43a0c0b11bb374065ccd80322a26b2dc4c9814c Mon Sep 17 00:00:00 2001 From: geekpi Date: Tue, 6 Mar 2018 08:49:26 +0800 Subject: [PATCH 17/26] translated --- ...nd Share Terminal Session with Showterm.md | 76 ------------------- ...nd Share Terminal Session with Showterm.md | 73 ++++++++++++++++++ 2 files changed, 73 insertions(+), 76 deletions(-) delete mode 100644 sources/tech/20171116 Record and Share Terminal Session with Showterm.md create mode 100644 translated/tech/20171116 Record and Share Terminal Session with Showterm.md diff --git a/sources/tech/20171116 Record and Share Terminal Session with Showterm.md b/sources/tech/20171116 Record and Share Terminal Session with Showterm.md deleted file mode 100644 index 8d3ce451b5..0000000000 --- a/sources/tech/20171116 Record and Share Terminal Session with Showterm.md +++ /dev/null @@ -1,76 +0,0 @@ -translating---geekpi - -Record and Share Terminal Session with Showterm -====== - -![](https://www.maketecheasier.com/assets/uploads/2017/11/record-terminal-session.jpg) - -You can easily record your terminal sessions with virtually all screen recording programs. However, you are very likely to end up with an oversized video file. There are several terminal recorders available in Linux, each with its own strengths and weakness. Showterm is a tool that makes it pretty easy to record terminal sessions, upload them, share, and embed them in any web page. On the plus side, you don't end up with any huge file to deal with. - -Showterm is open source, and the project can be found on this [GitHub page][1]. - - **Related** : [2 Simple Applications That Record Your Terminal Session as Video [Linux]][2] - -### Installing Showterm for Linux - -Showterm requires that you have Ruby installed on your computer. Here's how to go about installing the program. -``` -gem install showterm -``` - -If you don't have Ruby installed on your Linux system: -``` -sudo curl showterm.io/showterm > ~/bin/showterm -sudo chmod +x ~/bin/showterm -``` - -If you just want to run the application without installation: -``` -bash <(curl record.showterm.io) -``` - -You can type `showterm --help` for the help screen. If a help page doesn't appear, showterm is probably not installed. Now that you have Showterm installed (or are running the standalone version), let us dive into using the tool to record. - - **Related** : [How to Record Terminal Session in Ubuntu][3] - -### Recording Terminal Session - -![showterm terminal][4] - -Recording a terminal session is pretty simple. From the command line run `showterm`. This should start the terminal recording in the background. All commands entered in the command line from hereon are recorded by Showterm. Once you are done recording, press Ctrl + D or type `exit` in the command line to stop your recording. - -Showterm should upload your video and output a link to the video that looks like http://showterm.io/. It is rather unfortunate that terminal sessions are uploaded right away without any prompting. Don't panic! You can delete any uploaded recording by entering `showterm --delete `. Before uploading your recordings, you'll have the chance to change the timing by adding the `-e` option to the showterm command. If by any chance a recording fails to upload, you can use `showterm --retry