@@ -172,15 +172,15 @@ export default function accessPage() {
}
```
-Because the router intercepts all the link clicks to do its navigation, we must prevent the event propagation for this link in particular.
+因为路由器会拦截所有链接点击来进行导航,所以我们必须特别阻止此链接的事件传播。
-Clicking on that link will redirect us to the backend, then to GitHub, then to the backend and then to the frontend again; to the callback page.
+单击该链接会将我们重定向到后端,然后重定向到 GitHub,再重定向到后端,然后再次重定向到前端; 到 `callback` 页面。
-### Callback Page
+### Callback 页面
-Create the file `static/pages/callback-page.js` with the following content:
+创建包括以下内容的 `static/pages/callback-page.js` 文件:
-```
+```javascript
import http from '../http.js'
import { navigate } from '../router.js'
@@ -211,13 +211,13 @@ function getAuthUser(token) {
}
```
-The callback page doesn’t render anything. It’s an async function that does a GET request to `/api/auth_user` using the token from the URL query string and saves all the data to localStorage. Then it redirects to `/`.
+`callback` 页面不呈现任何内容。这是一个异步函数,它使用 URL 查询字符串中的 token 向 `/api/auth_user` 发出 GET 请求,并将所有数据保存到 `localStorage`。 然后重定向到 `/`。
### HTTP
-There is an HTTP module. Create a `static/http.js` file with the following content:
+这里是一个 HTTP 模块。 创建一个包含以下内容的 `static/http.js` 文件:
-```
+```javascript
import { isAuthenticated } from './auth.js'
async function handleResponse(res) {
@@ -297,15 +297,15 @@ export default {
}
```
-This module is a wrapper around the [fetch][10] and [EventSource][11] APIs. The most important part is that it adds the JSON web token to the requests.
+这个模块是 [fetch][10] 和 [EventSource][11] API 的包装器。最重要的部分是它将 JSON web 令牌添加到请求中。
-### Home Page
+### Home 页面
![home page screenshot][12]
-So, when the user login, the home page will be shown. Create a `static/pages/home-page.js` file with the following content:
+因此,当用户登录时,将显示 `home` 页。 创建一个具有以下内容的 `static/pages/home-page.js` 文件:
-```
+```javascript
import { getAuthUser } from '../auth.js'
import { avatar } from '../shared.js'
@@ -334,15 +334,15 @@ function onLogoutClick() {
}
```
-For this post, this is the only content we render on the home page. We show the current authenticated user and a logout button.
+对于这篇文章,这是我们在 `home` 页上呈现的唯一内容。我们显示当前经过身份验证的用户和注销按钮。
-When the user clicks to logout, we clear all inside localStorage and do a reload of the page.
+当用户单击注销时,我们清除 `localStorage` 中的所有内容并重新加载页面。
### Avatar
-That `avatar()` function is to show the user’s avatar. Because it’s used in more than one place, I moved it to a `shared.js` file. Create the file `static/shared.js` with the following content:
+那个 `avatar()` 函数用于显示用户的头像。 由于已在多个地方使用,因此我将它移到 `shared.js` 文件中。 创建具有以下内容的文件 `static/shared.js`:
-```
+```javascript
export function avatar(user) {
return user.avatarUrl === null
? ``
@@ -350,23 +350,23 @@ export function avatar(user) {
}
```
-We use a small figure with the user’s initial in case the avatar URL is null.
+如果头像网址为 `null`,我们将使用用户的姓名首字母作为初始头像。
-You can show the initial with a little of CSS using the `attr()` function.
+你可以使用 `attr()` 函数显示带有少量 CSS 样式的首字母。
-```
+```css
.avatar[data-initial]::after {
content: attr(data-initial);
}
```
-### Development Login
+### 仅开发使用的登录
![access page with login form screenshot][13]
-In the previous post we coded a login for development. Lets add a form for that in the access page. Go to `static/pages/access-page.js` and modify it a little.
+在上一篇文章中,我们为编写了一个登录代码。让我们在 `access` 页面中为此添加一个表单。 进入 `static/ages/access-page.js`,稍微修改一下。
-```
+```javascript
import http from '../http.js'
const template = document.createElement('template')
@@ -420,15 +420,15 @@ function login(username) {
}
```
-I added a login form. When the user submits the form. It does a POST requets to `/api/login` with the username. Saves all the data to localStorage and reloads the page.
+我添加了一个登录表单。当用户提交表单时。它使用用户名对 `/api/login` 进行 POST 请求。将所有数据保存到 `localStorage` 并重新加载页面。
-Remember to remove this form once you are done with the frontend.
+记住在前端完成后删除此表单。
* * *
-That’s all for this post. In the next one, we’ll continue with the home page to add a form to start conversations and display a list with the latest ones.
+这就是这篇文章的全部内容。在下一篇文章中,我们将继续使用主页添加一个表单来开始对话,并显示包含最新对话的列表。
-[Souce Code][14]
+- [源代码][14]
--------------------------------------------------------------------------------
@@ -436,19 +436,19 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-access-page/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
+译者:[gxlct008](https://github.com/gxlct008)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
-[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
-[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
-[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
-[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
-[5]: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
-[6]: https://nicolasparada.netlify.com/posts/go-messenger-dev-login/
+[1]: https://linux.cn/article-11396-1.html
+[2]: https://linux.cn/article-11510-1.html
+[3]: https://linux.cn/article-12056-1.html
+[4]: https://linux.cn/article-12680-1.html
+[5]: https://linux.cn/article-12685-1.html
+[6]: https://linux.cn/article-12692-1.html
[7]: https://nicolasparada.netlify.com/posts/js-router/
[8]: https://unpkg.com/@nicolasparada/router
[9]: https://nicolasparada.netlify.com/img/go-messenger-access-page/access-page.png
diff --git a/sources/tech/20180719 Building a Messenger App- Home Page.md b/published/202010/20180719 Building a Messenger App- Home Page.md
similarity index 58%
rename from sources/tech/20180719 Building a Messenger App- Home Page.md
rename to published/202010/20180719 Building a Messenger App- Home Page.md
index ddec2c180f..741206a4a7 100644
--- a/sources/tech/20180719 Building a Messenger App- Home Page.md
+++ b/published/202010/20180719 Building a Messenger App- Home Page.md
@@ -1,50 +1,50 @@
[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
+[#]: translator: (gxlct008)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12722-1.html)
[#]: subject: (Building a Messenger App: Home Page)
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-home-page/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
-Building a Messenger App: Home Page
+构建一个即时消息应用(八):Home 页面
======
-This post is the 8th on a series:
+
- * [Part 1: Schema][1]
- * [Part 2: OAuth][2]
- * [Part 3: Conversations][3]
- * [Part 4: Messages][4]
- * [Part 5: Realtime Messages][5]
- * [Part 6: Development Login][6]
- * [Part 7: Access Page][7]
+本文是该系列的第八篇。
+ * [第一篇: 模式][1]
+ * [第二篇: OAuth][2]
+ * [第三篇: 对话][3]
+ * [第四篇: 消息][4]
+ * [第五篇: 实时消息][5]
+ * [第六篇: 仅用于开发的登录][6]
+ * [第七篇: Access 页面][7]
+继续前端部分,让我们在本文中完成 `home` 页面的开发。 我们将添加一个开始对话的表单和一个包含最新对话的列表。
-Continuing the frontend, let’s finish the home page in this post. We’ll add a form to start conversations and a list with the latest ones.
-
-### Conversation Form
+### 对话表单
![conversation form screenshot][8]
-In the `static/pages/home-page.js` file add some markup in the HTML view.
+转到 `static/ages/home-page.js` 文件,在 HTML 视图中添加一些标记。
-```
+```html
```
-Add that form just below the section in which we displayed the auth user and logout button.
+将该表单添加到我们显示 “auth user” 和 “logout” 按钮部分的下方。
-```
+```js
page.getElementById('conversation-form').onsubmit = onConversationSubmit
```
-Now we can listen to the “submit” event to create the conversation.
+现在我们可以监听 “submit” 事件来创建对话了。
-```
+```js
import http from '../http.js'
import { navigate } from '../router.js'
@@ -79,15 +79,15 @@ function createConversation(username) {
}
```
-On submit we do a POST request to `/api/conversations` with the username and redirect to the conversation page (for the next post).
+在提交时,我们使用用户名对 `/api/conversations` 进行 POST 请求,并重定向到 `conversation` 页面(用于下一篇文章)。
-### Conversation List
+### 对话列表
![conversation list screenshot][9]
-In the same file, we are going to make the `homePage()` function async to load the conversations first.
+还是在这个文件中,我们将创建 `homePage()` 函数用来先异步加载对话。
-```
+```js
export default async function homePage() {
const conversations = await getConversations().catch(err => {
console.error(err)
@@ -101,24 +101,24 @@ function getConversations() {
}
```
-Then, add a list in the markup to render conversations there.
+然后,在标记中添加一个列表来渲染对话。
-```
+```html
```
-Add it just below the current markup.
+将其添加到当前标记的正下方。
-```
+```js
const conversationsOList = page.getElementById('conversations')
for (const conversation of conversations) {
conversationsOList.appendChild(renderConversation(conversation))
}
```
-So we can append each conversation to the list.
+因此,我们可以将每个对话添加到这个列表中。
-```
+```js
import { avatar, escapeHTML } from '../shared.js'
function renderConversation(conversation) {
@@ -146,11 +146,11 @@ function renderConversation(conversation) {
}
```
-Each conversation item contains a link to the conversation page and displays the other participant info and a preview of the last message. Also, you can use `.hasUnreadMessages` to add a class to the item and do some styling with CSS. Maybe a bolder font or accent the color.
+每个对话条目都包含一个指向对话页面的链接,并显示其他参与者信息和最后一条消息的预览。另外,您可以使用 `.hasUnreadMessages` 向该条目添加一个类,并使用 CSS 进行一些样式设置。也许是粗体字体或强调颜色。
-Note that we’re escaping the message content. That function comes from `static/shared.js`:
+请注意,我们需要转义信息的内容。该函数来自于 `static/shared.js` 文件:
-```
+```js
export function escapeHTML(str) {
return str
.replace(/&/g, '&')
@@ -161,35 +161,34 @@ export function escapeHTML(str) {
}
```
-That prevents displaying as HTML the message the user wrote. If the user happens to write something like:
+这会阻止将用户编写的消息显示为 HTML。如果用户碰巧编写了类似以下内容的代码:
-```
+```js
```
-It would be very annoying because that script will be executed 😅
-So yeah, always remember to escape content from untrusted sources.
+这将非常烦人,因为该脚本将被执行😅。所以,永远记住要转义来自不可信来源的内容。
-### Messages Subscription
+### 消息订阅
-Last but not least, I want to subscribe to the message stream here.
+最后但并非最不重要的一点,我想在这里订阅消息流。
-```
+```js
const unsubscribe = subscribeToMessages(onMessageArrive)
page.addEventListener('disconnect', unsubscribe)
```
-Add that line in the `homePage()` function.
+在 `homePage()` 函数中添加这一行。
-```
+```js
function subscribeToMessages(cb) {
return http.subscribe('/api/messages', cb)
}
```
-The `subscribe()` function returns a function that once called it closes the underlying connection. That’s why I passed it to the “disconnect” event; so when the user leaves the page, the event stream will be closed.
+函数 `subscribe()` 返回一个函数,该函数一旦调用就会关闭底层连接。这就是为什么我把它传递给 “断开连接”事件的原因;因此,当用户离开页面时,事件流将被关闭。
-```
+```js
async function onMessageArrive(message) {
const conversationLI = document.querySelector(`li[data-id="${message.conversationID}"]`)
if (conversationLI !== null) {
@@ -221,14 +220,14 @@ function getConversation(id) {
}
```
-Every time a new message arrives, we go and query for the conversation item in the DOM. If found, we add the `has-unread-messages` class to the item, and update the view. If not found, it means the message is from a new conversation created just now. We go and do a GET request to `/api/conversations/{conversationID}` to get the conversation in which the message was created and prepend it to the conversation list.
+每次有新消息到达时,我们都会在 DOM 中查询会话条目。如果找到,我们会将 `has-unread-messages` 类添加到该条目中,并更新视图。如果未找到,则表示该消息来自刚刚创建的新对话。我们去做一个对 `/api/conversations/{conversationID}` 的 GET 请求,以获取在其中创建消息的对话,并将其放在对话列表的前面。
* * *
-That covers the home page 😊
-On the next post we’ll code the conversation page.
+以上这些涵盖了主页的所有内容 😊。
+在下一篇文章中,我们将对 conversation 页面进行编码。
-[Souce Code][10]
+- [源代码][10]
--------------------------------------------------------------------------------
@@ -236,20 +235,20 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-home-page/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
+译者:[gxlct008](https://github.com/gxlct008)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
-[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
-[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
-[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
-[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
-[5]: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
-[6]: https://nicolasparada.netlify.com/posts/go-messenger-dev-login/
-[7]: https://nicolasparada.netlify.com/posts/go-messenger-access-page/
+[1]: https://linux.cn/article-11396-1.html
+[2]: https://linux.cn/article-11510-1.html
+[3]: https://linux.cn/article-12056-1.html
+[4]: https://linux.cn/article-12680-1.html
+[5]: https://linux.cn/article-12685-1.html
+[6]: https://linux.cn/article-12692-1.html
+[7]: https://linux.cn/article-12704-1.html
[8]: https://nicolasparada.netlify.com/img/go-messenger-home-page/conversation-form.png
[9]: https://nicolasparada.netlify.com/img/go-messenger-home-page/conversation-list.png
[10]: https://github.com/nicolasparada/go-messenger-demo
diff --git a/sources/tech/20180720 Building a Messenger App- Conversation Page.md b/published/202010/20180720 Building a Messenger App- Conversation Page.md
similarity index 59%
rename from sources/tech/20180720 Building a Messenger App- Conversation Page.md
rename to published/202010/20180720 Building a Messenger App- Conversation Page.md
index c721b48161..95f91cabfa 100644
--- a/sources/tech/20180720 Building a Messenger App- Conversation Page.md
+++ b/published/202010/20180720 Building a Messenger App- Conversation Page.md
@@ -1,37 +1,37 @@
[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
+[#]: translator: (gxlct008)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12723-1.html)
[#]: subject: (Building a Messenger App: Conversation Page)
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-conversation-page/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
-Building a Messenger App: Conversation Page
+构建一个即时消息应用(九):Conversation 页面
======
-This post is the 9th and last in a series:
+
- * [Part 1: Schema][1]
- * [Part 2: OAuth][2]
- * [Part 3: Conversations][3]
- * [Part 4: Messages][4]
- * [Part 5: Realtime Messages][5]
- * [Part 6: Development Login][6]
- * [Part 7: Access Page][7]
- * [Part 8: Home Page][8]
+本文是该系列的第九篇,也是最后一篇。
+ * [第一篇: 模式][1]
+ * [第二篇: OAuth][2]
+ * [第三篇: 对话][3]
+ * [第四篇: 消息][4]
+ * [第五篇: 实时消息][5]
+ * [第六篇: 仅用于开发的登录][6]
+ * [第七篇: Access 页面][7]
+ * [第八篇: Home 页面][8]
+在这篇文章中,我们将对对话页面进行编码。此页面是两个用户之间的聊天室。在顶部我们将显示其他参与者的信息,下面接着的是最新消息列表,以及底部的消息表单。
-In this post we’ll code the conversation page. This page is the chat between the two users. At the top we’ll show info about the other participant, below, a list of the latest messages and a message form at the bottom.
-
-### Chat heading
+### 聊天标题
![chat heading screenshot][9]
-Let’s start by creating the file `static/pages/conversation-page.js` with the following content:
+让我们从创建 `static/pages/conversation-page.js` 文件开始,它包含以下内容:
-```
+```js
import http from '../http.js'
import { navigate } from '../router.js'
import { avatar, escapeHTML } from '../shared.js'
@@ -65,17 +65,17 @@ function getConversation(id) {
}
```
-This page receives the conversation ID the router extracted from the URL.
+此页面接收路由从 URL 中提取的会话 ID。
-First it does a GET request to `/api/conversations/{conversationID}` to get info about the conversation. In case of error, we show it and redirect back to `/`. Then we render info about the other participant.
+首先,它向 `/api/ conversations/{conversationID}` 发起一个 GET 请求,以获取有关对话的信息。 如果出现错误,我们会将其显示,并重定向回 `/`。然后我们呈现有关其他参与者的信息。
-### Conversation List
+### 对话列表
![chat heading screenshot][10]
-We’ll fetch the latest messages too to display them.
+我们也会获取最新的消息并显示它们。
-```
+```js
let conversation, messages
try {
[conversation, messages] = await Promise.all([
@@ -85,32 +85,32 @@ try {
}
```
-Update the `conversationPage()` function to fetch the messages too. We use `Promise.all()` to do both request at the same time.
+更新 `conversationPage()` 函数以获取消息。我们使用 `Promise.all()` 同时执行这两个请求。
-```
+```js
function getMessages(conversationID) {
return http.get(`/api/conversations/${conversationID}/messages`)
}
```
-A GET request to `/api/conversations/{conversationID}/messages` gets the latest messages of the conversation.
+发起对 `/api/conversations/{conversationID}/messages` 的 GET 请求可以获取对话中的最新消息。
-```
+```html
```
-Now, add that list to the markup.
+现在,将该列表添加到标记中。
-```
+```js
const messagesOList = page.getElementById('messages')
for (const message of messages.reverse()) {
messagesOList.appendChild(renderMessage(message))
}
```
-So we can append messages to the list. We show them in reverse order.
+这样我们就可以将消息附加到列表中了。我们以时间倒序来显示它们。
-```
+```js
function renderMessage(message) {
const messageContent = escapeHTML(message.content)
const messageDate = new Date(message.createdAt).toLocaleString()
@@ -127,28 +127,28 @@ function renderMessage(message) {
}
```
-Each message item displays the message content itself with its timestamp. Using `.mine` we can append a different class to the item so maybe you can show the message to the right.
+每个消息条目显示消息内容本身及其时间戳。使用 `.mine`,我们可以将不同的 css 类附加到条目,这样您就可以将消息显示在右侧。
-### Message Form
+### 消息表单
![chat heading screenshot][11]
-```
+```html
```
-Add that form to the current markup.
+将该表单添加到当前标记中。
-```
+```js
page.getElementById('message-form').onsubmit = messageSubmitter(conversationID)
```
-Attach an event listener to the “submit” event.
+将事件监听器附加到 “submit” 事件。
-```
+```js
function messageSubmitter(conversationID) {
return async ev => {
ev.preventDefault()
@@ -191,19 +191,20 @@ function createMessage(content, conversationID) {
}
```
-We make use of [partial application][12] to have the conversation ID in the “submit” event handler. It takes the message content from the input and does a POST request to `/api/conversations/{conversationID}/messages` with it. Then prepends the newly created message to the list.
-### Messages Subscription
+我们利用 [partial application][12] 在 “submit” 事件处理程序中获取对话 ID。它 从输入中获取消息内容,并用它对 `/api/conversations/{conversationID}/messages` 发出 POST 请求。 然后将新创建的消息添加到列表中。
-To make it realtime we’ll subscribe to the message stream in this page also.
+### 消息订阅
-```
+为了实现实时,我们还将订阅此页面中的消息流。
+
+```js
page.addEventListener('disconnect', subscribeToMessages(messageArriver(conversationID)))
```
-Add that line in the `conversationPage()` function.
+将该行添加到 `conversationPage()` 函数中。
-```
+```js
function subscribeToMessages(cb) {
return http.subscribe('/api/messages', cb)
}
@@ -229,16 +230,15 @@ function readMessages(conversationID) {
}
```
-We also make use of partial application to have the conversation ID here.
-When a new message arrives, first we check if it’s from this conversation. If it is, we go a prepend a message item to the list and do a POST request to `/api/conversations/{conversationID}/read_messages` to updated the last time the participant read messages.
+在这里我们仍然使用这个应用的部分来获取会话 ID。
+当新消息到达时,我们首先检查它是否来自此对话。如果是,我们会将消息条目预先添加到列表中,并向 `/api/conversations/{conversationID}/read_messages` 发起 POST 一个请求,以更新参与者上次阅读消息的时间。
* * *
-That concludes this series. The messenger app is now functional.
+本系列到此结束。 消息应用现在可以运行了。
-~~I’ll add pagination on the conversation and message list, also user searching before sharing the source code. I’ll updated once it’s ready along with a hosted demo 👨💻~~
-
-[Souce Code][13] • [Demo][14]
+- [源代码][13]
+- [演示][14]
--------------------------------------------------------------------------------
@@ -246,21 +246,21 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-conversation-page/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
+译者:[gxlct008](https://github.com/gxlct008)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
-[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
-[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
-[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
-[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
-[5]: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
-[6]: https://nicolasparada.netlify.com/posts/go-messenger-dev-login/
-[7]: https://nicolasparada.netlify.com/posts/go-messenger-access-page/
-[8]: https://nicolasparada.netlify.com/posts/go-messenger-home-page/
+[1]: https://linux.cn/article-11396-1.html
+[2]: https://linux.cn/article-11510-1.html
+[3]: https://linux.cn/article-12056-1.html
+[4]: https://linux.cn/article-12680-1.html
+[5]: https://linux.cn/article-12685-1.html
+[6]: https://linux.cn/article-12692-1.html
+[7]: https://linux.cn/article-12704-1.html
+[8]: https://linux.cn/article-12722-1.html
[9]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/heading.png
[10]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/list.png
[11]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/form.png
diff --git a/published/202010/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md b/published/202010/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md
new file mode 100644
index 0000000000..0222a78d37
--- /dev/null
+++ b/published/202010/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md
@@ -0,0 +1,273 @@
+[#]: collector: (lujun9972)
+[#]: translator: (gxlct008)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12737-1.html)
+[#]: subject: (Using Yarn on Ubuntu and Other Linux Distributions)
+[#]: via: (https://itsfoss.com/install-yarn-ubuntu)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+在 Ubuntu 和其他 Linux 发行版上使用 Yarn
+======
+
+> 本速成教程向你展示了在 Ubuntu 和 Debian Linux 上安装 Yarn 包管理器的官方方法。你还将学习到一些基本的 Yarn 命令以及彻底删除 Yarn 的步骤。
+
+[Yarn][1] 是 Facebook 开发的开源 JavaScript 包管理器。它是流行的 npm 包管理器的一个替代品,或者应该说是改进。 [Facebook 开发团队][2] 创建 Yarn 是为了克服 [npm][3] 的缺点。 Facebook 声称 Yarn 比 npm 更快、更可靠、更安全。
+
+与 npm 一样,Yarn 为你提供一种自动安装、更新、配置和删除从全局注册库中检索到的程序包的方法。
+
+Yarn 的优点是它更快,因为它可以缓存已下载的每个包,所以无需再次下载。它还将操作并行化,以最大化资源利用率。在执行每个已安装的包代码之前,Yarn 还使用 [校验和来验证完整性][4]。 Yarn 还保证可以在一个系统上运行的安装,在任何其他系统上都会以完全相同地方式工作。
+
+如果你正 [在 Ubuntu 上使用 node.js][5],那么你的系统上可能已经安装了 npm。在这种情况下,你可以使用 npm 通过以下方式全局安装 Yarn:
+
+```
+sudo npm install yarn -g
+```
+
+不过,我推荐使用官方方式在 Ubuntu/Debian 上安装 Yarn。
+
+### 在 Ubuntu 和 Debian 上安装 Yarn [官方方式]
+
+![Yarn JS][6]
+
+这里提到的说明应该适用于所有版本的 Ubuntu,例如 Ubuntu 18.04、16.04 等。同样的一组说明也适用于 Debian 和其他基于 Debian 的发行版。
+
+由于本教程使用 `curl` 来添加 Yarn 项目的 GPG 密钥,所以最好验证一下你是否已经安装了 `curl`。
+
+```
+sudo apt install curl
+```
+
+如果 `curl` 尚未安装,则上面的命令将安装它。既然有了 `curl`,你就可以使用它以如下方式添加 Yarn 项目的 GPG 密钥:
+
+```
+curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+```
+
+在此之后,将存储库添加到源列表中,以便将来可以轻松地升级 Yarn 包,并进行其余系统更新:
+
+```
+sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list'
+```
+
+你现在可以继续了。[更新 Ubuntu][7] 或 Debian 系统,以刷新可用软件包列表,然后安装 Yarn:
+
+```
+sudo apt update
+sudo apt install yarn
+```
+
+这将一起安装 Yarn 和 node.js。该过程完成后,请验证是否已成功安装 Yarn。 你可以通过检查 Yarn 版本来做到这一点。
+
+```
+yarn --version
+```
+
+对我来说,它显示了这样的输出:
+
+```
+yarn --version
+1.12.3
+```
+
+这意味着我的系统上安装了 Yarn 版本 1.12.3。
+
+### 使用 Yarn
+
+我假设你对 JavaScript 编程以及依赖项的工作原理有一些基本的了解。我在这里不做详细介绍。我将向你展示一些基本的 Yarn 命令,这些命令将帮助你入门。
+
+#### 使用 Yarn 创建一个新项目
+
+与 `npm` 一样,Yarn 也可以使用 `package.json` 文件。在这里添加依赖项。所有依赖包都缓存在项目根目录下的 `node_modules` 目录中。
+
+在项目的根目录中,运行以下命令以生成新的 `package.json` 文件:
+
+它会问你一些问题。你可以按回车键跳过或使用默认值。
+
+```
+yarn init
+yarn init v1.12.3
+question name (test_yarn): test_yarn_proect
+question version (1.0.0): 0.1
+question description: Test Yarn
+question entry point (index.js):
+question repository url:
+question author: abhishek
+question license (MIT):
+question private:
+success Saved package.json
+Done in 82.42s.
+```
+
+这样,你就得到了一个如下的 `package.json` 文件:
+
+```
+{
+ "name": "test_yarn_proect",
+ "version": "0.1",
+ "description": "Test Yarn",
+ "main": "index.js",
+ "author": "abhishek",
+ "license": "MIT"
+}
+```
+
+现在你有了 `package.json`,你可以手动编辑它以添加或删除包依赖项,也可以使用 Yarn 命令(首选)。
+
+#### 使用 Yarn 添加依赖项
+
+你可以通过以下方式添加对特定包的依赖关系:
+
+```
+yarn add <包名>
+```
+
+例如,如果你想在项目中使用 [Lodash][8],则可以使用 Yarn 添加它,如下所示:
+
+```
+yarn add lodash
+yarn add v1.12.3
+info No lockfile found.
+[1/4] Resolving packages…
+[2/4] Fetching packages…
+[3/4] Linking dependencies…
+[4/4] Building fresh packages…
+success Saved lockfile.
+success Saved 1 new dependency.
+info Direct dependencies
+└─ [email protected]
+info All dependencies
+└─ [email protected]
+Done in 2.67s.
+```
+
+你可以看到,此依赖项已自动添加到 `package.json` 文件中:
+
+```
+{
+ "name": "test_yarn_proect",
+ "version": "0.1",
+ "description": "Test Yarn",
+ "main": "index.js",
+ "author": "abhishek",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.11"
+ }
+}
+```
+
+默认情况下,Yarn 将在依赖项中添加最新版本的包。如果要使用特定版本,可以在添加时指定。
+
+```
+yarn add package@version-or-tag
+```
+
+像往常一样,你也可以手动更新 `package.json` 文件。
+
+#### 使用 Yarn 升级依赖项
+
+你可以使用以下命令将特定依赖项升级到其最新版本:
+
+```
+yarn upgrade <包名>
+```
+
+它将查看所涉及的包是否具有较新的版本,并且会相应地对其进行更新。
+
+你还可以通过以下方式更改已添加的依赖项的版本:
+
+```
+yarn upgrade package_name@version_or_tag
+```
+
+你还可以使用一个命令将项目的所有依赖项升级到它们的最新版本:
+
+```
+yarn upgrade
+```
+
+它将检查所有依赖项的版本,如果有任何较新的版本,则会更新它们。
+
+#### 使用 Yarn 删除依赖项
+
+你可以通过以下方式从项目的依赖项中删除包:
+
+```
+yarn remove <包名>
+```
+
+#### 安装所有项目依赖项
+
+如果对你 `project.json` 文件进行了任何更改,则应该运行:
+
+```
+yarn
+```
+
+或者,
+
+```
+yarn install
+```
+
+一次安装所有依赖项。
+
+### 如何从 Ubuntu 或 Debian 中删除 Yarn
+
+我将通过介绍从系统中删除 Yarn 的步骤来完成本教程,如果你使用上述步骤安装 Yarn 的话。如果你意识到不再需要 Yarn 了,则可以将它删除。
+
+使用以下命令删除 Yarn 及其依赖项。
+
+```
+sudo apt purge yarn
+```
+
+你也应该从源列表中把存储库信息一并删除掉:
+
+```
+sudo rm /etc/apt/sources.list.d/yarn.list
+```
+
+下一步删除已添加到受信任密钥的 GPG 密钥是可选的。但要做到这一点,你需要知道密钥。你可以使用 `apt-key` 命令获得它:
+
+```
+Warning: apt-key output should not be parsed (stdout is not a terminal) pub rsa4096 2016-10-05 [SC] 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310 uid [ unknown] Yarn Packaging yarn@dan.cx sub rsa4096 2016-10-05 [E] sub rsa4096 2019-01-02 [S] [expires: 2020-02-02]
+```
+
+这里的密钥是以 `pub` 开始的行中 GPG 密钥指纹的最后 8 个字符。
+
+因此,对于我来说,密钥是 `86E50310`,我将使用以下命令将其删除:
+
+```
+sudo apt-key del 86E50310
+```
+
+你会在输出中看到 `OK`,并且 Yarn 包的 GPG 密钥将从系统信任的 GPG 密钥列表中删除。
+
+我希望本教程可以帮助你在 Ubuntu、Debian、Linux Mint、 elementary OS 等操作系统上安装 Yarn。 我提供了一些基本的 Yarn 命令,以帮助你入门,并完成了从系统中删除 Yarn 的完整步骤。
+
+希望你喜欢本教程,如果有任何疑问或建议,请随时在下面留言。
+
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/install-yarn-ubuntu
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[gxlct008](https://github.com/gxlct008)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://yarnpkg.com/lang/en/
+[2]: https://code.fb.com/
+[3]: https://www.npmjs.com/
+[4]: https://itsfoss.com/checksum-tools-guide-linux/
+[5]: https://itsfoss.com/install-nodejs-ubuntu/
+[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/yarn-js-ubuntu-debian.jpeg?resize=800%2C450&ssl=1
+[7]: https://itsfoss.com/update-ubuntu/
+[8]: https://lodash.com/
diff --git a/published/202010/20190521 How to Disable IPv6 on Ubuntu Linux.md b/published/202010/20190521 How to Disable IPv6 on Ubuntu Linux.md
new file mode 100644
index 0000000000..a187054afd
--- /dev/null
+++ b/published/202010/20190521 How to Disable IPv6 on Ubuntu Linux.md
@@ -0,0 +1,221 @@
+[#]: collector: (lujun9972)
+[#]: translator: (rakino)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12689-1.html)
+[#]: subject: (How to Disable IPv6 on Ubuntu Linux)
+[#]: via: (https://itsfoss.com/disable-ipv6-ubuntu-linux/)
+[#]: author: (Sergiu https://itsfoss.com/author/sergiu/)
+
+如何在 Ubuntu Linux 上禁用 IPv6
+======
+
+想知道怎样在 Ubuntu 上**禁用 IPv6** 吗?我会在这篇文章中介绍一些方法,以及为什么你应该考虑这一选择;以防改变主意,我也会提到如何**启用,或者说重新启用 IPv6**。
+
+### 什么是 IPv6?为什么会想要禁用它?
+
+[互联网协议第 6 版][1](IPv6)是互联网协议(IP)的最新版本。互联网协议是一种通信协议,它为网络上的计算机提供识别和定位系统,并在互联网上进行通信路由。IPv6 于 1998 年设计,以取代 IPv4 协议。
+
+**IPv6** 意在提高安全性与性能的同时保证地址不被用尽;它可以在全球范围内为每台设备分配唯一的以 **128 位比特**存储的地址,而 IPv4 只使用了 32 位比特。
+
+![Disable IPv6 Ubuntu][2]
+
+尽管 IPv6 的目标是取代 IPv4,但目前还有很长的路要走;互联网上只有不到 **30%** 的网站支持 IPv6([这里][3] 是谷歌的统计),IPv6 有时也给 [一些应用带来问题][4]。
+
+由于 IPv6 使用全球(唯一分配的)路由地址,以及(仍然)有互联网服务供应商(ISP)不提供 IPv6 支持的事实,IPv6 这一功能在提供全球服务的**虚拟私人网络**(VPN)供应商的优先级列表中处于较低的位置,这样一来,他们就可以专注于对 VPN 用户最重要的事情:安全。
+
+不想让自己暴露在各种威胁之下可能是另一个让你想在系统上禁用 IPv6 的原因。虽然 IPv6 本身比 IPv4 更安全,但我所指的风险是另一种性质上的。如果你不实际使用 IPv6 及其功能,那么[启用 IPv6 后,你会很容易受到各种攻击][5],因而为黑客提供另一种可能的利用工具。
+
+同样,只配置基本的网络规则是不够的;你必须像对 IPv4 一样,对调整 IPv6 的配置给予同样的关注,这可能会是一件相当麻烦的事情(维护也是)。并且随着 IPv6 而来的将会是一套不同于 IPv4 的问题(鉴于这个协议的年龄,许多问题已经可以在网上找到了),这又会使你的系统多了一层复杂性。
+
+据观察,在某些情况下,禁用 IPv6 有助于提高 Ubuntu 的 WiFi 速度。
+
+### 在 Ubuntu 上禁用 IPv6 [高级用户]
+
+在本节中,我会详述如何在 Ubuntu 上禁用 IPv6 协议,请打开终端(默认快捷键:`CTRL+ALT+T`),让我们开始吧!
+
+**注意:** 接下来大部分输入终端的命令都需要 root 权限(`sudo`)。
+
+> 警告!
+>
+> 如果你是一个普通 Linux 桌面用户,并且偏好稳定的工作系统,请避开本教程,接下来的部分是为那些知道自己在做什么以及为什么要这么做的用户准备的。
+
+#### 1、使用 sysctl 禁用 IPv6
+
+首先,可以执行以下命令来**检查** IPv6 是否已经启用:
+
+```
+ip a
+```
+
+如果启用了,你应该会看到一个 IPv6 地址(网卡的名字可能会与图中有所不同)
+
+![IPv6 Address Ubuntu][7]
+
+在教程《[在 Ubuntu 中重启网络][8]》(LCTT 译注:其实这篇文章并没有提到使用 sysctl 的方法……)中,你已经见过 `sysctl` 命令了,在这里我们也同样会用到它。要**禁用 IPv6**,只需要输入三条命令:
+
+```
+sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
+sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
+sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
+```
+
+检查命令是否生效:
+
+```
+ip a
+```
+
+如果命令生效,你应该会发现 IPv6 的条目消失了:
+
+![IPv6 Disabled Ubuntu][9]
+
+然而这种方法只能**临时禁用 IPv6**,因此在下次系统启动的时候,IPv6 仍然会被启用。
+
+(LCTT 译注:这里的临时禁用是指这次所做的改变直到此次关机之前都有效,因为相关的参数是存储在内存中的,可以改变值,但是在内存断电后就会丢失;这种意义上来讲,下文所述的两种方法都是临时的,只不过改变参数值的时机是在系统启动的早期,并且每次系统启动时都有应用而已。那么如何完成这种意义上的永久改变?答案是在编译内核的时候禁用相关功能,然后要后悔就只能重新编译内核了(悲)。)
+
+一种让选项持续生效的方式是修改文件 `/etc/sysctl.conf`,在这里我用 `vim` 来编辑文件,不过你可以使用任何你想使用的编辑器,以及请确保你拥有**管理员权限**(用 `sudo`):
+
+![Sysctl Configuration][10]
+
+将下面这几行(和之前使用的参数相同)加入到文件中:
+
+```
+net.ipv6.conf.all.disable_ipv6=1
+net.ipv6.conf.default.disable_ipv6=1
+net.ipv6.conf.lo.disable_ipv6=1
+```
+
+执行以下命令应用设置:
+
+```
+sudo sysctl -p
+```
+
+如果在重启之后 IPv6 仍然被启用了,而你还想继续这种方法的话,那么你必须(使用 root 权限)创建文件 `/etc/rc.local` 并加入以下内容:
+
+```
+#!/bin/bash
+# /etc/rc.local
+
+/etc/sysctl.d
+/etc/init.d/procps restart
+
+exit 0
+```
+
+接着使用 [chmod 命令][11] 来更改文件权限,使其可执行:
+
+```
+sudo chmod 755 /etc/rc.local
+```
+
+这会让系统(在启动的时候)从之前编辑过的 sysctl 配置文件中读取内核参数。
+
+#### 2、使用 GRUB 禁用 IPv6
+
+另外一种方法是配置 **GRUB**,它会在系统启动时向内核传递参数。这样做需要编辑文件 `/etc/default/grub`(请确保拥有管理员权限)。
+
+![GRUB Configuration][13]
+
+现在需要修改文件中分别以 `GRUB_CMDLINE_LINUX_DEFAULT` 和 `GRUB_CMDLINE_LINUX` 开头的两行来在启动时禁用 IPv6:
+
+```
+GRUB_CMDLINE_LINUX_DEFAULT="quiet splash ipv6.disable=1"
+GRUB_CMDLINE_LINUX="ipv6.disable=1"
+```
+
+(LCTT 译注:这里是指在上述两行内增加参数 `ipv6.disable=1`,不同的系统中这两行的默认值可能有所不同。)
+
+保存文件,然后执行命令:
+
+```
+sudo update-grub
+```
+
+(LCTT 译注:该命令用以更新 GRUB 的配置文件,在没有 `update-grub` 命令的系统中需要使用 `sudo grub-mkconfig -o /boot/grub/grub.cfg` )
+
+设置会在重启后生效。
+
+### 在 Ubuntu 上重新启用 IPv6
+
+要想重新启用 IPv6,你需要撤销之前的所有修改。不过只是想临时启用 IPv6 的话,可以执行以下命令:
+
+```
+sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
+sudo sysctl -w net.ipv6.conf.default.disable_ipv6=0
+sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0
+```
+
+否则想要持续启用的话,看看是否修改过 `/etc/sysctl.conf`,可以删除掉之前增加的部分,也可以将它们改为以下值(两种方法等效):
+
+```
+net.ipv6.conf.all.disable_ipv6=0
+net.ipv6.conf.default.disable_ipv6=0
+net.ipv6.conf.lo.disable_ipv6=0
+```
+
+然后应用设置(可选):
+
+```
+sudo sysctl -p
+```
+
+(LCTT 译注:这里可选的意思可能是如果之前临时启用了 IPv6 就没必要再重新加载配置文件了)
+
+这样应该可以再次看到 IPv6 地址了:
+
+![IPv6 Reenabled in Ubuntu][14]
+
+另外,你也可以删除之前创建的文件 `/etc/rc.local`(可选):
+
+```
+sudo rm /etc/rc.local
+```
+
+如果修改了文件 `/etc/default/grub`,回去删掉你所增加的参数:
+
+```
+GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
+GRUB_CMDLINE_LINUX=""
+```
+
+然后更新 GRUB 配置文件:
+
+```
+sudo update-grub
+```
+
+### 尾声
+
+在这篇文章中,我介绍了在 Linux 上**禁用 IPv6** 的方法,并简述了什么是 IPv6 以及可能想要禁用掉它的原因。
+
+那么,这篇文章对你有用吗?你有禁用掉 IPv6 连接吗?让我们评论区见吧~
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/disable-ipv6-ubuntu-linux/
+
+作者:[Sergiu][a]
+选题:[lujun9972][b]
+译者:[rakino](https://github.com/rakino)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/sergiu/
+[b]: https://github.com/lujun9972
+[1]: https://en.wikipedia.org/wiki/IPv6
+[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/05/disable_ipv6_ubuntu.png?fit=800%2C450&ssl=1
+[3]: https://www.google.com/intl/en/ipv6/statistics.html
+[4]: https://whatismyipaddress.com/ipv6-issues
+[5]: https://www.internetsociety.org/blog/2015/01/ipv6-security-myth-1-im-not-running-ipv6-so-i-dont-have-to-worry/
+[6]: https://itsfoss.com/remove-drive-icons-from-unity-launcher-in-ubuntu/
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_address_ubuntu.png?fit=800%2C517&ssl=1
+[8]: https://linux.cn/article-10804-1.html
+[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_disabled_ubuntu.png?fit=800%2C442&ssl=1
+[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/05/sysctl_configuration.jpg?fit=800%2C554&ssl=1
+[11]: https://linuxhandbook.com/chmod-command/
+[12]: https://itsfoss.com/find-which-kernel-version-is-running-in-ubuntu/
+[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/05/grub_configuration-1.jpg?fit=800%2C565&ssl=1
+[14]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_address_ubuntu-1.png?fit=800%2C517&ssl=1
diff --git a/published/202010/20190822 Things You Didn-t Know About GNU Readline.md b/published/202010/20190822 Things You Didn-t Know About GNU Readline.md
new file mode 100644
index 0000000000..12dc0a568d
--- /dev/null
+++ b/published/202010/20190822 Things You Didn-t Know About GNU Readline.md
@@ -0,0 +1,132 @@
+[#]: collector: (lujun9972)
+[#]: translator: (rakino)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12706-1.html)
+[#]: subject: (Things You Didn't Know About GNU Readline)
+[#]: via: (https://twobithistory.org/2019/08/22/readline.html)
+[#]: author: (Two-Bit History https://twobithistory.org)
+
+你所不知的 GNU Readline
+======
+
+
+
+有时我会觉得自己的计算机是一栋非常大的房子,我每天都会访问这栋房子,也对一楼的大部分房间都了如指掌,但仍然还是有我没有去过的卧室,有我没有打开过的衣柜,有我没有探索过的犄角旮旯。我感到有必要更多地了解我的计算机了,就像任何人都会觉得有必要看看自己家里从未去过的房间一样。
+
+GNU Readline 是个不起眼的小软件库,我依赖了它多年却没有意识到它的存在,也许有成千上万的人每天都在不经意间使用它。如果你用 Bash shell 的话,每当你自动补全一个文件名,或者在输入的一行文本中移动光标,以及搜索之前命令的历史记录时,你都在使用 GNU Readline;当你在 Postgres(`psql`)或是 Ruby REPL(`irb`)的命令行界面中进行同样的操作时,你依然在使用 GNU Readline。很多软件都依赖 GNU Readline 库来实现用户所期望的功能,不过这些功能是如此的辅助与不显眼,以至于在我看来很少有人会停下来去想它是从哪里来的。
+
+GNU Readline 最初是自由软件基金会在 20 世纪 80 年代创建的,如今作为每个人的基础计算设施的重要的、甚至看不见的组成部分的它,由一位志愿者维护。
+
+### 充满特色
+
+GNU Readline 库的存在,主要是为了增强各种命令行界面,它提供了一组通用的按键,使你可以在一个单行输入中移动和编辑。例如,在 Bash 提示符中按下 `Ctrl-A`,你的光标会跳到行首,而按下 `Ctrl-E` 则会跳到行末;另一个有用的命令是 `Ctrl-U`,它会删除该行中光标之前的所有内容。
+
+有很长一段时间,我通过反复敲击方向键来在命令行上移动,如今看来这十分尴尬,也不知道为什么,当时的我从来没有想过可以有一种更快的方法。当然了,没有哪一个熟悉 Vim 或 Emacs 这种文本编辑器的程序员愿意长时间地击打方向键,所以像 Readline 这样的东西必然会被创造出来。在 Readline 上可以做的绝非仅仅跳来跳去,你可以像使用文本编辑器那样编辑单行文本——这里有删除单词、单词换位、大写单词、复制和粘贴字符等命令。Readline 的大部分按键/快捷键都是基于 Emacs 的,它基本上就是一个单行文本版的 Emacs 了,甚至还有录制和重放宏的功能。
+
+我从来没有用过 Emacs,所以很难记住所有不同的 Readline 命令。不过 Readline 有着很巧妙的一点,那就是能够切换到基于 Vim 的模式,在 Bash 中可以使用内置的 `set` 命令来这样做。下面会让 Readline 在当前的 shell 中使用 Vim 风格的命令:
+
+```
+$ set -o vi
+```
+
+该选项启用后,就可以使用 `dw` 等命令来删除单词了,此时相当于 Emacs 模式下的 `Ctrl-U` 的命令是 `d0`。
+
+我第一次知道有这个功能的时候很兴奋地想尝试一下,但它对我来说并不是那么好用。我很高兴知道有这种对 Vim 用户的让步,在使用这个功能上你可能会比我更幸运,尤其是你还没有使用 Readline 的默认按键的话;我的问题在于,我听说有基于 Vim 的界面时已经学会了几种默认按键,因此即使启用了 Vim 的选项,也一直在错误地用着默认的按键;另外因为没有某种指示器,所以 Vim 的模态设计在这里会很尴尬——你很容易就忘记了自己处于哪个模式,就因为这样,我卡在了一种虽然使用 Vim 作为文本编辑器,但却在 Readline 上用着 Emacs 风格的命令的情况里,我猜其他很多人也是这样的。
+
+如果你觉得 Vim 和 Emacs 的键盘命令系统诡异而神秘(这并不是没有道理的),你可以按照喜欢的方式自定义 Readline 的键绑定。Readline 在启动时会读取文件 `~/.inputrc`,它可以用来配置各种选项与键绑定,我做的一件事是重新配置了 `Ctrl-K`:通常情况下该命令会从光标处删除到行末,但我很少这样做,所以我在 `~/.inputrc` 中添加了以下内容,把它绑定为直接删除整行:
+
+```
+Control-k: kill-whole-line
+```
+
+每个 Readline 命令(文档中称它们为 “函数” )都有一个名称,你可以用这种方式将其与一个键序列联系起来。如果你在 Vim 中编辑 `~/.inputrc`,就会发现 Vim 知道这种文件类型,还会帮你高亮显示有效的函数名,而不高亮无效的函数名。
+
+`~/.inputrc` 可以做的另一件事是通过将键序列映射到输入字符串上来创建预制宏。[Readline 手册][1]给出了一个我认为特别有用的例子:我经常想把一个程序的输出保存到文件中,这意味着我得经常在 Bash 命令中追加类似 `> output.txt` 这样的东西,为了节省时间,可以把它做成一个 Readline 宏:
+
+```
+Control-o: "> output.txt"
+```
+
+这样每当你按下 `Ctrl-O` 时,你都会看到 `> output.txt` 被添加到了命令行光标的后面,这样很不错!
+
+不过你可以用宏做的可不仅仅是为文本串创建快捷方式;在 `~/.inputrc` 中使用以下条目意味着每次按下 `Ctrl-J` 时,行内已有的文本都会被 `$(` 和 `)` 包裹住。该宏先用 `Ctrl-A` 移动到行首,添加 `$(` ,然后再用 `Ctrl-E` 移动到行尾,添加 `)`:
+
+```
+Control-j: "\C-a$(\C-e)"
+```
+
+如果你经常需要像下面这样把一个命令的输出用于另一个命令的话,这个宏可能会对你有帮助:
+
+```
+$ cd $(brew --prefix)
+```
+
+`~/.inputrc` 文件也允许你为 Readline 手册中所谓的 “变量” 设置不同的值,这些变量会启用或禁用某些 Readline 行为,你也可以使用这些变量来改变 Readline 中像是自动补全或者历史搜索这些行为的工作方式。我建议开启的一个变量是 `revert-all-at-newline`,它是默认关闭的,当这个变量关闭时,如果你使用反向搜索功能从命令历史记录中提取一行并编辑,但随后又决定搜索另一行,那么你所做的编辑会被保存在历史记录中。我觉得这样会很混乱,因为这会导致你的 Bash 命令历史中出现从未运行过的行。所以在你的 `~/.inputrc` 中加入这个:
+
+```
+set revert-all-at-newline on
+```
+
+在你用 `~/.inputrc` 设置了选项或键绑定以后,它们会适用于任何使用 Readline 库的地方,显然 Bash 也包括在内,不过你也会在其它像是 `irb` 和 `psql` 这样的程序中受益。如果你经常使用关系型数据库的命令行界面,一个用于插入 `SELECT * FROM` 的 Readline 宏可能会很有用。
+
+### Chet Ramey
+
+GNU Readline 如今由凯斯西储大学的高级技术架构师 Chet Ramey 维护,Ramey 同时还负责维护 Bash shell;这两个项目都是由一位名叫 Brian Fox 的自由软件基金会员工在 1988 年开始编写的,但从 1994 年左右开始,Ramey 一直是它们唯一的维护者。
+
+Ramey 通过电子邮件告诉我,Readline 远非一个原创的想法,它是为了实现 POSIX 规范所规定的功能而被创建的,而 POSIX 规范又是在 20 世纪 80 年代末被制定的。许多早期的 shell,包括 Korn shell 和至少一个版本的 Unix System V shell,都包含行编辑功能。1988 年版的 Korn shell(`ksh88`)提供了 Emacs 风格和 Vi/Vim 风格的编辑模式。据我从[手册页][2]中得知,Korn shell 会通过查看 `VISUAL` 和 `EDITOR` 环境变量来决定你使用的模式,这一点非常巧妙。POSIX 中指定 shell 功能的部分近似于 `ksh88` 的实现,所以 GNU Bash 也要实现一个类似的灵活的行编辑系统来保持兼容,因此就有了 Readline。
+
+Ramey 第一次参与 Bash 开发时,Readline 还是 Bash 项目目录下的一个单一的源文件,它其实只是 Bash 的一部分;随着时间的推移,Readline 文件慢慢地成为了独立的项目,不过直到 1994 年(Readline 2.0 版本发布),Readline 才完全成为了一个独立的库。
+
+Readline 与 Bash 密切相关,Ramey 也通常把 Readline 与 Bash 的发布配对,但正如我上面提到的,Readline 是一个可以被任何有命令行界面的软件使用的库,而且它真的很容易使用。下面是一个例子,虽然简单,但这就是在 C 程序中使用 Readline 的方法。向 `readline()` 函数传递的字符串参数就是你希望 Readline 向用户显示的提示符:
+
+```
+#include
+#include
+#include "readline/readline.h"
+
+int main(int argc, char** argv)
+{
+ char* line = readline("my-rl-example> ");
+ printf("You entered: \"%s\"\n", line);
+
+ free(line);
+
+ return 0;
+}
+```
+
+你的程序会把控制权交给 Readline,它会负责从用户那里获得一行输入(以这样的方式让用户可以做所有花哨的行编辑工作),一旦用户真正提交了这一行,Readline 就会把它返回给你。在我的库搜索路径中有 Readline 库,所以我可以通过调用以下内容来链接 Readline 库,从而编译上面的内容:
+
+```
+$ gcc main.c -lreadline
+```
+
+当然,Readline 的 API 比起那个单一的函数要丰富得多,任何使用它的人都可以对库的行为进行各种调整,库的用户(开发者)甚至可以添加新的函数,来让最终用户可以通过 `~/.inputrc` 来配置它们,这意味着 Readline 非常容易扩展。但是据我所知,即使是 Bash ,虽然事先有很多配置,最终也会像上面的例子一样调用简单的 `readline()` 函数来获取输入。(参见 GNU Bash 源代码中的[这一行][3],Bash 似乎在这里将获取输入的责任交给了 Readline)。
+
+Ramey 现在已经在 Bash 和 Readline 上工作了二十多年,但他的工作却从来没有得到过报酬 —— 他一直都是一名志愿者。Bash 和 Readline 仍然在积极开发中,尽管 Ramey 说 Readline 的变化比 Bash 慢得多。我问 Ramey 作为这么多人使用的软件唯一的维护者是什么感觉,他说可能有几百万人在不知不觉中使用 Bash(因为每个苹果设备都运行 Bash),这让他担心一个破坏性的变化会造成多大的混乱,不过他已经慢慢习惯了所有这些人的想法。他还说他会继续在 Bash 和 Readline 上工作,因为在这一点上他已经深深地投入了,而且他也只是单纯地喜欢把有用的软件提供给世界。
+
+_你可以在 [Chet Ramey 的网站][4]上找到更多关于他的信息。_
+
+_喜欢这篇文章吗?我会每四周写出一篇像这样的文章。关注推特帐号 [@TwoBitHistory][5] 或者[订阅 RSS][6] 来获取更新吧!_
+
+--------------------------------------------------------------------------------
+
+via: https://twobithistory.org/2019/08/22/readline.html
+
+作者:[Two-Bit History][a]
+选题:[lujun9972][b]
+译者:[rakino](https://github.com/rakino)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://twobithistory.org
+[b]: https://github.com/lujun9972
+[1]: https://tiswww.case.edu/php/chet/readline/readline.html
+[2]: https://web.archive.org/web/20151105130220/http://www2.research.att.com/sw/download/man/man1/ksh88.html
+[3]: https://github.com/bminor/bash/blob/9f597fd10993313262cab400bf3c46ffb3f6fd1e/parse.y#L1487
+[4]: https://tiswww.case.edu/php/chet/
+[5]: https://twitter.com/TwoBitHistory
+[6]: https://twobithistory.org/feed.xml
+[7]: https://twitter.com/TwoBitHistory/status/1112492084383092738?ref_src=twsrc%5Etfw
diff --git a/published/202010/20191105 My first contribution to open source- Making a decision.md b/published/202010/20191105 My first contribution to open source- Making a decision.md
new file mode 100644
index 0000000000..a8863ea7ff
--- /dev/null
+++ b/published/202010/20191105 My first contribution to open source- Making a decision.md
@@ -0,0 +1,59 @@
+[#]: collector: (lujun9972)
+[#]: translator: (chenmu-kk)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12768-1.html)
+[#]: subject: (My first contribution to open source: Making a decision)
+[#]: via: (https://opensource.com/article/19/11/my-first-open-source-contribution-mistake-decisions)
+[#]: author: (Galen Corey https://opensource.com/users/galenemco)
+
+我的第一次开源贡献:做出决定
+======
+
+> 一位新的开源贡献者告诉你如何加入到开源项目中。
+
+
+
+先前,我把我的第一次开源贡献的拖延归咎于[冒牌综合症][2]。但还有一个我无法忽视的因素:我做出决定太艰难了。在[成千上百万][3]的开源项目中选择时,选择一个要做贡献的项目是难以抉择的。如此重负,以至于我常常不得不关掉我的笔记本去思考:“或许我改天再做吧”。
+
+错误之二是让我对做出决定的恐惧妨碍了我做出第一次贡献。在理想世界里,也许开始我的开源之旅时,心中就已经有了一个真正关心和想去做的具体项目,但我有的只是总得为开源项目做出贡献的模糊目标。对于那些处于同一处境的人来说,这儿有一些帮助我挑选出合适的项目(或者至少是一个好的项目)来做贡献的策略。
+
+### 经常使用的工具
+
+一开始,我不认为有必要将自己局限于已经熟悉的工具或项目。有一些项目我之前从未使用过,但由于它们的社区很活跃,或者它们解决的问题很有趣,因此看起来很有吸引力。
+
+但是,考虑我投入到这个项目中的时间有限,我决定继续投入到我了解的工具上去。要了解工具需求,你需要熟悉它的工作方式。如果你想为自己不熟悉的项目做贡献,则需要完成一个额外的步骤来了解代码的功能和目标。这个额外的工作量可能是有趣且值得的,但也会使你的工作时间加倍。因为我的目标主要是贡献,投入到我了解的工具上是缩小范围的很好方式。回馈一个你认为有用的项目也是有意义的。
+
+### 活跃而友好的社区
+
+在选择项目的时候,我希望在那里有人会审查我写的代码才会觉得有信心。当然,我也希望审核我代码的人是个和善的人。毕竟,把你的作品放在那里接受公众监督是很可怕的。虽然我对建设性的反馈持开放态度,但开发者社区中的一些有毒角落是我希望避免的。
+
+为了评估我将要加入的社区,我查看了我正在考虑加入的仓库的议题部分。我要查看核心团队中是否有人定期回复。更重要的是,我试着确保没有人在评论中互相诋毁(这在议题讨论中是很常见的)。我还留意了那些有行为准则的项目,概述了什么是适当的和不适当的在线互动行为。
+
+### 明确的贡献准则
+
+因为这是我第一次为开源项目做出贡献,在此过程中我有很多问题。一些项目社区在流程的文档记录方面做的很好,可以用来指导挑选其中的议题并发起拉取请求。 [Gatsby][4] 是这种做法的典范,尽管那时我没有选择它们,因为在此之前我从未使用过该产品。
+
+这种清晰的文档帮助我们缓解了一些不知如何去做的不安全感。它也给了我希望:项目对新的贡献者是开放的,并且会花时间来查看我的工作。除了贡献准则外,我还查看了议题部分,看看这个项目是否使用了“第一个好议题”标志。这是该项目对初学者开放的另一个迹象(并可以帮助你学会要做什么)。
+
+### 总结
+
+如果你还没有计划好选择一个项目,那么选择合适的领域进行你的第一个开源贡献更加可行。列出一系列标准可以帮助自己缩减选择范围,并为自己的第一个拉取请求找到一个好的项目。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/11/my-first-open-source-contribution-mistake-decisions
+
+作者:[Galen Corey][a]
+选题:[lujun9972][b]
+译者:[chenmu-kk](https://github.com/chenmu-kk)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/galenemco
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lightbulb-idea-think-yearbook-lead.png?itok=5ZpCm0Jh (Lightbulb)
+[2]: https://opensource.com/article/19/10/my-first-open-source-contribution-mistakes
+[3]: https://github.blog/2018-02-08-open-source-project-trends-for-2018/
+[4]: https://www.gatsbyjs.org/contributing/
diff --git a/published/202010/20200512 Scan your Linux security with Lynis.md b/published/202010/20200512 Scan your Linux security with Lynis.md
new file mode 100644
index 0000000000..e945d3b86d
--- /dev/null
+++ b/published/202010/20200512 Scan your Linux security with Lynis.md
@@ -0,0 +1,380 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12696-1.html)
+[#]: subject: (Scan your Linux security with Lynis)
+[#]: via: (https://opensource.com/article/20/5/linux-security-lynis)
+[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
+
+使用 Lynis 扫描 Linux 安全性
+======
+
+> 使用这个全面的开源安全审计工具检查你的 Linux 机器的安全性。
+
+
+
+你有没有想过你的 Linux 机器到底安全不安全?Linux 发行版众多,每个发行版都有自己的默认设置,你在上面运行着几十个版本各异的软件包,还有众多的服务在后台运行,而我们几乎不知道或不关心这些。
+
+要想确定安全态势(指你的 Linux 机器上运行的软件、网络和服务的整体安全状态),你可以运行几个命令,得到一些零碎的相关信息,但你需要解析的数据量是巨大的。
+
+如果能运行一个工具,生成一份关于机器安全状况的报告,那就好得多了。而幸运的是,有一个这样的软件:[Lynis][2]。它是一个非常流行的开源安全审计工具,可以帮助强化基于 Linux 和 Unix 的系统。根据该项目的介绍:
+
+> “它运行在系统本身,可以进行深入的安全扫描。主要目标是测试安全防御措施,并提供进一步强化系统的提示。它还将扫描一般系统信息、易受攻击的软件包和可能的配置问题。Lynis 常被系统管理员和审计人员用来评估其系统的安全防御。”
+
+### 安装 Lynis
+
+你的 Linux 软件仓库中可能有 Lynis。如果有的话,你可以用以下方法安装它:
+
+```
+dnf install lynis
+```
+
+或
+
+```
+apt install lynis
+```
+
+然而,如果你的仓库中的版本不是最新的,你最好从 GitHub 上安装它。(我使用的是 Red Hat Linux 系统,但你可以在任何 Linux 发行版上运行它)。就像所有的工具一样,先在虚拟机上试一试是有意义的。要从 GitHub 上安装它:
+
+```
+$ cat /etc/redhat-release
+Red Hat Enterprise Linux Server release 7.8 (Maipo)
+$
+$ uname -r
+3.10.0-1127.el7.x86_64
+$
+$ git clone https://github.com/CISOfy/lynis.git
+Cloning into 'lynis'...
+remote: Enumerating objects: 30, done.
+remote: Counting objects: 100% (30/30), done.
+remote: Compressing objects: 100% (30/30), done.
+remote: Total 12566 (delta 15), reused 8 (delta 0), pack-reused 12536
+Receiving objects: 100% (12566/12566), 6.36 MiB | 911.00 KiB/s, done.
+Resolving deltas: 100% (9264/9264), done.
+$
+```
+
+一旦你克隆了这个版本库,那么进入该目录,看看里面有什么可用的。主要的工具在一个叫 `lynis` 的文件里。它实际上是一个 shell 脚本,所以你可以打开它看看它在做什么。事实上,Lynis 主要是用 shell 脚本来实现的:
+
+```
+$ cd lynis/
+$ ls
+CHANGELOG.md CONTRIBUTING.md db developer.prf FAQ include LICENSE lynis.8 README SECURITY.md
+CODE_OF_CONDUCT.md CONTRIBUTORS.md default.prf extras HAPPY_USERS.md INSTALL lynis plugins README.md
+$
+$ file lynis
+lynis: POSIX shell script, ASCII text executable, with very long lines
+$
+```
+
+### 运行 Lynis
+
+通过给 Lynis 一个 `-h` 选项来查看帮助部分,以便有个大概了解:
+
+```
+$ ./lynis -h
+```
+
+你会看到一个简短的信息屏幕,然后是 Lynis 支持的所有子命令。
+
+接下来,尝试一些测试命令以大致熟悉一下。要查看你正在使用的 Lynis 版本,请运行:
+
+```
+$ ./lynis show version
+3.0.0
+$
+```
+
+要查看 Lynis 中所有可用的命令:
+
+```
+$ ./lynis show commands
+
+Commands:
+lynis audit
+lynis configure
+lynis generate
+lynis show
+lynis update
+lynis upload-only
+
+$
+```
+
+### 审计 Linux 系统
+
+要审计你的系统的安全态势,运行以下命令:
+
+```
+$ ./lynis audit system
+```
+
+这个命令运行得很快,并会返回一份详细的报告,输出结果可能一开始看起来很吓人,但我将在下面引导你来阅读它。这个命令的输出也会被保存到一个日志文件中,所以你可以随时回过头来检查任何可能感兴趣的东西。
+
+Lynis 将日志保存在这里:
+
+```
+ Files:
+ - Test and debug information : /var/log/lynis.log
+ - Report data : /var/log/lynis-report.dat
+```
+
+你可以验证是否创建了日志文件。它确实创建了:
+
+```
+$ ls -l /var/log/lynis.log
+-rw-r-----. 1 root root 341489 Apr 30 05:52 /var/log/lynis.log
+$
+$ ls -l /var/log/lynis-report.dat
+-rw-r-----. 1 root root 638 Apr 30 05:55 /var/log/lynis-report.dat
+$
+```
+
+### 探索报告
+
+Lynis 提供了相当全面的报告,所以我将介绍一些重要的部分。作为初始化的一部分,Lynis 做的第一件事就是找出机器上运行的操作系统的完整信息。之后是检查是否安装了什么系统工具和插件:
+
+```
+[+] Initializing program
+------------------------------------
+ - Detecting OS... [ DONE ]
+ - Checking profiles... [ DONE ]
+
+ ---------------------------------------------------
+ Program version: 3.0.0
+ Operating system: Linux
+ Operating system name: Red Hat Enterprise Linux Server 7.8 (Maipo)
+ Operating system version: 7.8
+ Kernel version: 3.10.0
+ Hardware platform: x86_64
+ Hostname: example
+ ---------------------------------------------------
+<<截断>>
+
+[+] System Tools
+------------------------------------
+ - Scanning available tools...
+ - Checking system binaries...
+
+[+] Plugins (phase 1)
+------------------------------------
+ Note: plugins have more extensive tests and may take several minutes to complete
+
+ - Plugin: pam
+ [..]
+ - Plugin: systemd
+ [................]
+```
+
+接下来,该报告被分为不同的部分,每个部分都以 `[+]` 符号开头。下面可以看到部分章节。(哇,要审核的地方有这么多,Lynis 是最合适的工具!)
+
+```
+[+] Boot and services
+[+] Kernel
+[+] Memory and Processes
+[+] Users, Groups and Authentication
+[+] Shells
+[+] File systems
+[+] USB Devices
+[+] Storage
+[+] NFS
+[+] Name services
+[+] Ports and packages
+[+] Networking
+[+] Printers and Spools
+[+] Software: e-mail and messaging
+[+] Software: firewalls
+[+] Software: webserver
+[+] SSH Support
+[+] SNMP Support
+[+] Databases
+[+] LDAP Services
+[+] PHP
+[+] Squid Support
+[+] Logging and files
+[+] Insecure services
+[+] Banners and identification
+[+] Scheduled tasks
+[+] Accounting
+[+] Time and Synchronization
+[+] Cryptography
+[+] Virtualization
+[+] Containers
+[+] Security frameworks
+[+] Software: file integrity
+[+] Software: System tooling
+[+] Software: Malware
+[+] File Permissions
+[+] Home directories
+[+] Kernel Hardening
+[+] Hardening
+[+] Custom tests
+```
+
+Lynis 使用颜色编码使报告更容易解读。
+
+ * 绿色。一切正常
+ * 黄色。跳过、未找到,可能有个建议
+ * 红色。你可能需要仔细看看这个
+
+在我的案例中,大部分的红色标记都是在 “Kernel Hardening” 部分找到的。内核有各种可调整的设置,它们定义了内核的功能,其中一些可调整的设置可能有其安全场景。发行版可能因为各种原因没有默认设置这些,但是你应该检查每一项,看看你是否需要根据你的安全态势来改变它的值:
+
+```
+[+] Kernel Hardening
+------------------------------------
+ - Comparing sysctl key pairs with scan profile
+ - fs.protected_hardlinks (exp: 1) [ OK ]
+ - fs.protected_symlinks (exp: 1) [ OK ]
+ - fs.suid_dumpable (exp: 0) [ OK ]
+ - kernel.core_uses_pid (exp: 1) [ OK ]
+ - kernel.ctrl-alt-del (exp: 0) [ OK ]
+ - kernel.dmesg_restrict (exp: 1) [ DIFFERENT ]
+ - kernel.kptr_restrict (exp: 2) [ DIFFERENT ]
+ - kernel.randomize_va_space (exp: 2) [ OK ]
+ - kernel.sysrq (exp: 0) [ DIFFERENT ]
+ - kernel.yama.ptrace_scope (exp: 1 2 3) [ DIFFERENT ]
+ - net.ipv4.conf.all.accept_redirects (exp: 0) [ DIFFERENT ]
+ - net.ipv4.conf.all.accept_source_route (exp: 0) [ OK ]
+ - net.ipv4.conf.all.bootp_relay (exp: 0) [ OK ]
+ - net.ipv4.conf.all.forwarding (exp: 0) [ OK ]
+ - net.ipv4.conf.all.log_martians (exp: 1) [ DIFFERENT ]
+ - net.ipv4.conf.all.mc_forwarding (exp: 0) [ OK ]
+ - net.ipv4.conf.all.proxy_arp (exp: 0) [ OK ]
+ - net.ipv4.conf.all.rp_filter (exp: 1) [ OK ]
+ - net.ipv4.conf.all.send_redirects (exp: 0) [ DIFFERENT ]
+ - net.ipv4.conf.default.accept_redirects (exp: 0) [ DIFFERENT ]
+ - net.ipv4.conf.default.accept_source_route (exp: 0) [ OK ]
+ - net.ipv4.conf.default.log_martians (exp: 1) [ DIFFERENT ]
+ - net.ipv4.icmp_echo_ignore_broadcasts (exp: 1) [ OK ]
+ - net.ipv4.icmp_ignore_bogus_error_responses (exp: 1) [ OK ]
+ - net.ipv4.tcp_syncookies (exp: 1) [ OK ]
+ - net.ipv4.tcp_timestamps (exp: 0 1) [ OK ]
+ - net.ipv6.conf.all.accept_redirects (exp: 0) [ DIFFERENT ]
+ - net.ipv6.conf.all.accept_source_route (exp: 0) [ OK ]
+ - net.ipv6.conf.default.accept_redirects (exp: 0) [ DIFFERENT ]
+ - net.ipv6.conf.default.accept_source_route (exp: 0) [ OK ]
+```
+
+看看 SSH 这个例子,因为它是一个需要保证安全的关键领域。这里没有什么红色的东西,但是 Lynis 对我的环境给出了很多强化 SSH 服务的建议:
+
+```
+[+] SSH Support
+------------------------------------
+ - Checking running SSH daemon [ FOUND ]
+ - Searching SSH configuration [ FOUND ]
+ - OpenSSH option: AllowTcpForwarding [ SUGGESTION ]
+ - OpenSSH option: ClientAliveCountMax [ SUGGESTION ]
+ - OpenSSH option: ClientAliveInterval [ OK ]
+ - OpenSSH option: Compression [ SUGGESTION ]
+ - OpenSSH option: FingerprintHash [ OK ]
+ - OpenSSH option: GatewayPorts [ OK ]
+ - OpenSSH option: IgnoreRhosts [ OK ]
+ - OpenSSH option: LoginGraceTime [ OK ]
+ - OpenSSH option: LogLevel [ SUGGESTION ]
+ - OpenSSH option: MaxAuthTries [ SUGGESTION ]
+ - OpenSSH option: MaxSessions [ SUGGESTION ]
+ - OpenSSH option: PermitRootLogin [ SUGGESTION ]
+ - OpenSSH option: PermitUserEnvironment [ OK ]
+ - OpenSSH option: PermitTunnel [ OK ]
+ - OpenSSH option: Port [ SUGGESTION ]
+ - OpenSSH option: PrintLastLog [ OK ]
+ - OpenSSH option: StrictModes [ OK ]
+ - OpenSSH option: TCPKeepAlive [ SUGGESTION ]
+ - OpenSSH option: UseDNS [ SUGGESTION ]
+ - OpenSSH option: X11Forwarding [ SUGGESTION ]
+ - OpenSSH option: AllowAgentForwarding [ SUGGESTION ]
+ - OpenSSH option: UsePrivilegeSeparation [ OK ]
+ - OpenSSH option: AllowUsers [ NOT FOUND ]
+ - OpenSSH option: AllowGroups [ NOT FOUND ]
+```
+
+我的系统上没有运行虚拟机或容器,所以这些显示的结果是空的:
+
+```
+[+] Virtualization
+------------------------------------
+
+[+] Containers
+------------------------------------
+```
+
+Lynis 会检查一些从安全角度看很重要的文件的文件权限:
+
+```
+[+] File Permissions
+------------------------------------
+ - Starting file permissions check
+ File: /boot/grub2/grub.cfg [ SUGGESTION ]
+ File: /etc/cron.deny [ OK ]
+ File: /etc/crontab [ SUGGESTION ]
+ File: /etc/group [ OK ]
+ File: /etc/group- [ OK ]
+ File: /etc/hosts.allow [ OK ]
+ File: /etc/hosts.deny [ OK ]
+ File: /etc/issue [ OK ]
+ File: /etc/issue.net [ OK ]
+ File: /etc/motd [ OK ]
+ File: /etc/passwd [ OK ]
+ File: /etc/passwd- [ OK ]
+ File: /etc/ssh/sshd_config [ OK ]
+ Directory: /root/.ssh [ SUGGESTION ]
+ Directory: /etc/cron.d [ SUGGESTION ]
+ Directory: /etc/cron.daily [ SUGGESTION ]
+ Directory: /etc/cron.hourly [ SUGGESTION ]
+ Directory: /etc/cron.weekly [ SUGGESTION ]
+ Directory: /etc/cron.monthly [ SUGGESTION ]
+```
+
+在报告的底部,Lynis 根据报告的发现提出了建议。每项建议后面都有一个 “TEST-ID”(为了下一部分方便,请将其保存起来)。
+
+```
+ Suggestions (47):
+ ----------------------------
+ * If not required, consider explicit disabling of core dump in /etc/security/limits.conf file [KRNL-5820]
+ https://cisofy.com/lynis/controls/KRNL-5820/
+
+ * Check PAM configuration, add rounds if applicable and expire passwords to encrypt with new values [AUTH-9229]
+ https://cisofy.com/lynis/controls/AUTH-9229/
+```
+
+Lynis 提供了一个选项来查找关于每个建议的更多信息,你可以使用 `show details` 命令和 TEST-ID 号来访问:
+
+```
+./lynis show details TEST-ID
+```
+
+这将显示该测试的其他信息。例如,我检查了 SSH-7408 的详细信息:
+
+```
+$ ./lynis show details SSH-7408
+2020-04-30 05:52:23 Performing test ID SSH-7408 (Check SSH specific defined options)
+2020-04-30 05:52:23 Test: Checking specific defined options in /tmp/lynis.k8JwazmKc6
+2020-04-30 05:52:23 Result: added additional options for OpenSSH < 7.5
+2020-04-30 05:52:23 Test: Checking AllowTcpForwarding in /tmp/lynis.k8JwazmKc6
+2020-04-30 05:52:23 Result: Option AllowTcpForwarding found
+2020-04-30 05:52:23 Result: Option AllowTcpForwarding value is YES
+2020-04-30 05:52:23 Result: OpenSSH option AllowTcpForwarding is in a weak configuration state and should be fixed
+2020-04-30 05:52:23 Suggestion: Consider hardening SSH configuration [test:SSH-7408] [details:AllowTcpForwarding (set YES to NO)] [solution:-]
+```
+
+### 试试吧
+
+如果你想更多地了解你的 Linux 机器的安全性,请试试 Lynis。如果你想了解 Lynis 是如何工作的,可以研究一下它的 shell 脚本,看看它是如何收集这些信息的。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/linux-security-lynis
+
+作者:[Gaurav Kamathe][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/gkamathe
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/yearbook-haff-rx-linux-file-lead_0.png?itok=-i0NNfDC (Hand putting a Linux file folder into a drawer)
+[2]: https://github.com/CISOfy/lynis
diff --git a/published/202010/20200521 Use the internet from the command line with curl.md b/published/202010/20200521 Use the internet from the command line with curl.md
new file mode 100644
index 0000000000..9880cead4e
--- /dev/null
+++ b/published/202010/20200521 Use the internet from the command line with curl.md
@@ -0,0 +1,171 @@
+[#]: collector: (lujun9972)
+[#]: translator: (MjSeven)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-12772-1.html)
+[#]: subject: (Use the internet from the command line with curl)
+[#]: via: (https://opensource.com/article/20/5/curl-cheat-sheet)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+使用 curl 从命令行访问互联网
+======
+
+> 下载我们整理的 curl 备忘录。要在不使用图形界面的情况下从互联网上获取所需的信息,curl 是一种快速有效的方法。
+
+
+
+`curl` 通常被视作一款非交互式 Web 浏览器,这意味着它能够从互联网上获取信息,并在你的终端中显示,或将其保存到文件中。从表面看,这是 Web 浏览器,类似 Firefox 或 Chromium 所做的工作,只是它们默认情况下会*渲染*信息,而 `curl` 会下载并显示原始信息。实际上,`curl` 命令可以做更多的事情,并且能够使用多种协议与服务器进行双向传输数据,这些协议包括 HTTP、FTP、SFTP、IMAP、POP3、LDAP、SMB、SMTP 等。对于普通终端用户来说,这是一个有用的工具;而对于系统管理员,这非常便捷;对于微服务和云开发人员来说,它是一个质量保证工具。
+
+`curl` 被设计为在没有用户交互的情况下工作,因此与 Firefox 不同,你必须从头到尾考虑与在线数据的交互。例如,如果想要在 Firefox 中查看网页,你需要启动 Firefox 窗口。打开 Firefox 后,在地址栏或搜索引擎中输入要访问的网站。然后,导航到网站,然后单击要查看的页面。
+
+对于 `curl` 来说也是如此,不同之处在于你需要一次执行所有操作:在启动 `curl` 的同时提供需要访问的互联网地址,并告诉它是否要将数据保存在终端或文件中。当你必须与需要身份验证的网站或 API 进行交互时,会变得有点复杂,但是一旦你学习了 `curl` 命令语法,它就会变得自然而然。为了帮助你掌握它,我们在一个方便的[备忘录][2]中收集了相关的语法信息。
+
+### 使用 curl 下载文件
+
+你可以通过提供指向特定 URL 的链接来使用 `curl` 命令下载文件。如果你提供的 URL 默认为 `index.html`,那么将下载此页面,并将下载的文件显示在终端屏幕上。你可以将数据通过管道传递到 `less`、`tail` 或任何其它命令:
+
+```
+$ curl "http://example.com" | tail -n 4
+
Example Domain
+
This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.
+ {{ range .List }}
+ {{ template "list_element" . }}
+ {{ end }}
+
+```
+
+You’re now rendering the `list_element` template with the list element from `.List`. But what if you want to also pass the current user `.User`? Unfortunately, you can only pass one argument from one template to another. If you have two arguments you want to pass to another template, with the standard library, you’re out of luck.
+
+The [whtmpl][65] package adds three helper functions to aid you here, `makepair`, `makemap`, and `makeslice` (more docs under the [whtmpl.Collection][66] type). `makepair` is the simplest. It takes two arguments and constructs a [whtmpl.Pair][67]. Fixing our example above would look like this now:
+
+```
+
+```
+
+The second thing [whtmpl][65] does is make defining lots of templates easy, by optionally automatically naming templates after the name of the file the template is defined in.
+
+For example, say you have three files.
+
+Here’s `pkg.go`:
+
+```
+package views
+
+import "gopkg.in/webhelp.v1/whtmpl"
+
+var Templates = whtmpl.NewCollection()
+```
+
+Here’s `landing.go`:
+
+```
+package views
+
+var _ = Templates.MustParse(`{{ template "header" . }}
+
+
Landing!
`)
+```
+
+And here’s `header.go`:
+
+```
+package views
+
+var _ = Templates.MustParse(`My website!`)
+```
+
+Now, you can import your new `views` package and render the `landing` template this easily:
+
+```
+func handler(w http.ResponseWriter, req *http.Request) {
+ views.Templates.Render(w, req, "landing", map[string]interface{}{})
+}
+```
+
+### User authentication
+
+I’ve written two Webhelp-style authentication libraries that I end up using frequently.
+
+The first is an OAuth2 library, [whoauth2][68]. I’ve written up [an example application that authenticates with Google, Facebook, and Github][69].
+
+The second, [whgoth][70], is a wrapper around [markbates/goth][71]. My portion isn’t quite complete yet (some fixes are still necessary for optional App Engine support), but will support more non-OAuth2 authentication sources (like Twitter) when it is done.
+
+### Route listing
+
+Surprise! If you’ve used [webhelp][27] based handlers and middleware for your whole app, you automatically get route listing for free, via the [whroute][72] package.
+
+My web serving code’s `main` method often has a form like this:
+
+```
+switch flag.Arg(0) {
+case "serve":
+ panic(whlog.ListenAndServe(*listenAddr, routes))
+case "routes":
+ whroute.PrintRoutes(os.Stdout, routes)
+default:
+ fmt.Printf("Usage: %s \n", os.Args[0])
+}
+```
+
+Here’s some example output:
+
+```
+GET /auth/_cb/
+GET /auth/login/
+GET /auth/logout/
+GET /
+GET /account/apikeys/
+POST /account/apikeys/
+GET /project//
+GET /project//control//
+POST /project//control//sample/
+GET /project//control/
+ Redirect: f(req)
+POST /project//control/
+POST /project//control_named//sample/
+GET /project//control_named/
+ Redirect: f(req)
+GET /project//sample//
+GET /project//sample//similar[/<*>]
+GET /project//sample/
+ Redirect: f(req)
+POST /project//search/
+GET /project/
+ Redirect: /
+POST /project/
+```
+
+### Other little things
+
+[webhelp][27] has a number of other subpackages:
+
+ * [whparse][73] assists in parsing optional request arguments.
+ * [whredir][74] provides some handlers and helper methods for doing redirects in various cases.
+ * [whcache][75] creates request-specific mutable storage for caching various computations and database loaded data. Mutability helps helper functions that aren’t used as middleware share data.
+ * [whfatal][76] uses panics to simplify early request handling termination. Probably avoid this package unless you want to anger other Go developers.
+
+
+
+### Summary
+
+Designing your web project as a collection of composable middlewares goes quite a long way to simplify your code design, eliminate cross-cutting concerns, and create a more flexible development environment. Use my [webhelp][27] package if it helps you.
+
+Or don’t! Whatever! It’s still a free country last I checked.
+
+#### Update
+
+Peter Kieltyka points me to his [Chi framework][77], which actually does seem to do the right things with respect to middleware, handlers, and contexts - certainly much more so than all the other frameworks I’ve seen. So, shoutout to Peter and the team at Pressly!
+
+--------------------------------------------------------------------------------
+
+via: https://www.jtolio.com/2017/01/writing-advanced-web-applications-with-go
+
+作者:[jtolio.com][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.jtolio.com/
+[b]: https://github.com/lujun9972
+[1]: https://www.ruby-lang.org/
+[2]: http://rubyonrails.org/
+[3]: http://www.sinatrarb.com/
+[4]: https://www.python.org/
+[5]: https://www.djangoproject.com/
+[6]: http://flask.pocoo.org/
+[7]: https://golang.org/
+[8]: https://groups.google.com/d/forum/golang-nuts
+[9]: https://www.reddit.com/r/golang/
+[10]: https://revel.github.io/
+[11]: https://gin-gonic.github.io/gin/
+[12]: http://iris-go.com/
+[13]: https://beego.me/
+[14]: https://go-macaron.com/
+[15]: https://github.com/go-martini/martini
+[16]: https://github.com/gocraft/web
+[17]: https://github.com/urfave/negroni
+[18]: https://godoc.org/goji.io
+[19]: https://echo.labstack.com/
+[20]: https://medium.com/code-zen/why-i-don-t-use-go-web-frameworks-1087e1facfa4
+[21]: https://groups.google.com/forum/#!topic/golang-nuts/R_lqsTTBh6I
+[22]: https://www.reddit.com/r/golang/comments/1yh6gm/new_to_go_trying_to_select_web_framework/
+[23]: https://golang.org/pkg/net/http/#Handler
+[24]: https://golang.org/pkg/net/http/#Request
+[25]: https://golang.org/pkg/net/http/#Request.Context
+[26]: https://golang.org/pkg/net/http/#Request.WithContext
+[27]: https://godoc.org/gopkg.in/webhelp.v1
+[28]: https://golang.org/doc/articles/wiki/
+[29]: https://expressjs.com/
+[30]: https://nodejs.org/en/
+[31]: https://en.wikipedia.org/wiki/Cross-cutting_concern
+[32]: https://github.com/gorilla/mux
+[33]: https://github.com/gorilla/
+[34]: https://golang.org/pkg/net/http/#ServeMux
+[35]: https://swtch.com/~rsc/
+[36]: https://github.com/rsc/tiddly
+[37]: https://github.com/rsc/tiddly/blob/8f9145ac183e374eb95d90a73be4d5f38534ec47/tiddly.go#L201
+[38]: https://godoc.org/gopkg.in/webhelp.v1/whmux#Dir
+[39]: https://godoc.org/gopkg.in/webhelp.v1/whmux
+[40]: https://godoc.org/gopkg.in/webhelp.v1/whmux#IntArg
+[41]: https://godoc.org/gopkg.in/webhelp.v1/whmux#StringArg
+[42]: https://golang.org/pkg/context/
+[43]: https://blog.golang.org/context
+[44]: https://godoc.org/golang.org/x/net/context
+[45]: https://godoc.org/gopkg.in/webhelp.v1#GenSym
+[46]: https://godoc.org/gopkg.in/webhelp.v1/whcompat
+[47]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#DoneNotify
+[48]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#CloseNotify
+[49]: https://godoc.org/gopkg.in/webhelp.v1/wherr
+[50]: https://godoc.org/gopkg.in/webhelp.v1/wherr#Handle
+[51]: https://godoc.org/gopkg.in/webhelp.v1/wherr#pkg-variables
+[52]: https://godoc.org/github.com/spacemonkeygo/errors
+[53]: https://godoc.org/github.com/spacemonkeygo/errors/errhttp
+[54]: https://github.com/zeebo/errs
+[55]: https://godoc.org/gopkg.in/webhelp.v1/whsess
+[56]: https://godoc.org/golang.org/x/crypto/nacl/secretbox
+[57]: https://godoc.org/gopkg.in/webhelp.v1/whlog
+[58]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogRequests
+[59]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogResponses
+[60]: https://godoc.org/gopkg.in/webhelp.v1/whlog#ListenAndServe
+[61]: https://godoc.org/gopkg.in/webhelp.v1/whmon
+[62]: https://godoc.org/gopkg.in/webhelp.v1/whgls
+[63]: https://godoc.org/github.com/jtolds/gls
+[64]: https://golang.org/pkg/html/template/
+[65]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl
+[66]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Collection
+[67]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Pair
+[68]: https://godoc.org/gopkg.in/go-webhelp/whoauth2.v1
+[69]: https://github.com/go-webhelp/whoauth2/blob/v1/examples/group/main.go
+[70]: https://godoc.org/gopkg.in/go-webhelp/whgoth.v1
+[71]: https://github.com/markbates/goth
+[72]: https://godoc.org/gopkg.in/webhelp.v1/whroute
+[73]: https://godoc.org/gopkg.in/webhelp.v1/whparse
+[74]: https://godoc.org/gopkg.in/webhelp.v1/whredir
+[75]: https://godoc.org/gopkg.in/webhelp.v1/whcache
+[76]: https://godoc.org/gopkg.in/webhelp.v1/whfatal
+[77]: https://github.com/pressly/chi
diff --git a/sources/tech/20180306 Exploring free and open web fonts.md b/sources/tech/20180306 Exploring free and open web fonts.md
deleted file mode 100644
index 533286ca2c..0000000000
--- a/sources/tech/20180306 Exploring free and open web fonts.md
+++ /dev/null
@@ -1,70 +0,0 @@
-Exploring free and open web fonts
-======
-
-
-
-There is no question that the face of the web has been transformed in recent years by open source fonts. Prior to 2010, the only typefaces you were likely to see in a web browser were the generic "web safe" [core fonts][1] from Microsoft. But that year saw the start of several revolutions: the introduction of the Web Open Font Format ([WOFF][2]), which offered an open standard for efficiently delivering font files over HTTP, and the launch of web-font services like [Google Fonts][3] and the [Open Font Library][4]—both of which offered web publishers access to a large collection of fonts, for free, available under open licenses.
-
-It is hard to overstate the positive impact of these events on web typography. But it can be all too easy to equate the successes of open web fonts with open source typography as a whole and conclude that the challenges are behind us, the puzzles solved. That is not the case, so if you care about type, the good news is there are a lot of opportunities to get involved in improvement.
-
-For starters, it's critical to understand that Google Fonts and Open Font Library offer a specialized service—delivering fonts in web pages—and they don't implement solutions for other use cases. That is not a shortcoming on the services' side; it simply means that we have to develop other solutions.
-
-There are a number of problems to solve. Probably the most obvious example is the awkwardness of installing fonts on a desktop Linux machine for use in other applications. You can download any of the web fonts offered by either service, but all you will get is a generic ZIP file with some TTF or OTF binaries inside and a plaintext license file. What happens next is up to you to guess.
-
-Most users learn quickly that the "right" step is to manually copy those font binaries into any one of a handful of special directories on their hard drive. But that just makes the files visible to the operating system; it doesn't offer much in the way of a user experience. Again, this is not a flaw with the web-font service; rather it's evidence of the point where the service stops and more work needs to be done on the other side.
-
-A big improvement from the user's perspective would be for the OS or the desktop environment to be smarter at this "just downloaded" stage. Not only would it install the font files to the right location but, more importantly, it could add important metadata that the user will want to access when selecting a font to use in a project.
-
-What this additional information consists of and how it is presented to the user is tied to another challenge: Managing a font collection on Linux is noticeably less pleasant than on other operating systems. Periodically, font manager applications appear (see [GTK+ Font Manager][5] for one of the most recent examples), but they rarely catch on. I've been thinking a lot about where I think they come up short; one core factor is they have limited themselves to displaying only the information embedded in the font binary: basic character-set coverage, weight/width/slope settings, embedded license and copyright statements, etc.
-
-But a lot of decisions go into the process of selecting a font for a job besides what's in this embedded data. Serious font users—like information designers, journal article authors, or book designers—make their font-selection decisions in the context of each document's requirements and needs. That includes license information, naturally, but it includes much more, like information about the designer and the foundry, stylistic trends, or details about how the font works in use.
-
-For example, if your document includes both English and Arabic text, you probably want a font where the Latin and Arabic glyphs were designed together by someone experienced with the two scripts. Otherwise, you'll waste a ton of time making tiny adjustments to the font sizes and line spacing trying to get the two languages to mix well. You may have learned from experience that certain designers or vendors are better at multi-script design than others. Or it might be relevant to your project that today's fashion magazines almost exclusively use "[Didone][6]"-style typefaces, a name that refers to super-high-contrast styles pioneered by [Firmin Didot][7] and [Giambattista Bodoni][8] around 200 years ago. It just happens to be the trend.
-
-But none of those terms (Didone, Didot, or Bodoni) are likely to show up in the binary's embedded data, nor is easy to tell whether the Latin and Arabic fit together or anything else about the typeface's back history. That information might appear in supplementary material like a type specimen or font documentation—if any exists.
-
-A specimen is a designed document (often a PDF) that shows the font in use and includes background information; it frequently serves a dual role as a marketing piece and a sample to look at when choosing a font. The considered design of a specimen showcases how the font functions in practice and in a manner that an automatically generated character table simply cannot. Documentation may include some other vital information, like how to activate the font's OpenType features, what mathematical or archaic forms it provides, or how it varies stylistically across supported languages. Making this sort of material available to the user in the font-management application would go a long way towards helping users find the fonts that fit their projects' needs.
-
-Of course, if we're going to consider a font manager that can handle documentation and specimens, we also have to take a hard look at what comes with the font packages provided by distributions. Linux users start with a few fonts automatically installed, and repository-provided packages are the only font source most users have besides downloading the generic ZIP archive. Those packages tend to be pretty bare-bones. Commercial fonts generally include specimens, documentation, and other support items, whereas open source fonts usually do not.
-
-There are some excellent examples of open fonts that do provide quality specimens and documentation (see [SIL Gentium][9] and [Bungee][10] for two distinctly different but valid approaches), but they rarely (if ever) make their way into the downstream packaging chain. We plainly can do better.
-
-There are some technical obstacles to offering a richer user experience for interacting with the fonts on your system. For one thing, the [AppStream][11] metadata standard defines a few [parameters][12] specific to font files, but so far includes nothing that would cover specimens, designer and foundry information, and other relevant details. For another, the [SPDX][13] (Software Package Data Exchange) format does not cover many of the software licenses (and license variants) used to distribute fonts.
-
-Finally, as any audiophile will tell you, a music player that does not let you edit and augment the ID3 tags in your MP3 collection is going to get frustrating quickly. You want to fix errors in the tags, you want to add things like notes and album art—essentially, you want to polish your library. You would want to do the same to keep your local font library in a pleasant-to-use state.
-
-But editing the embedded data in a font file has been taboo because fonts tend to get embedded and attached to other documents. If you monkey with the fields in a font binary, then redistribute it with your presentation slides, anyone who downloads those slides can end up with bad metadata through no fault of their own. So anyone making improvements to the font-management experience will have to figure out how to strategically wrangle repeated changes to the embedded and external font metadata.
-
-In addition to the technical angle, enriching the font-management experience is also a design challenge. As I said above, good specimens and well-written documentation exist for several open fonts. But there are many more packages missing both, and there are a lot of older font packages that are no longer being maintained. That probably means the only way that most open font packages are going to get specimens or documentation is for the community to create them.
-
-Perhaps that's a tall order. But the open source design community is bigger than it has ever been, and it is a highly motivated segment of the overall free and open source software movement. So who knows; maybe this time next year finding, downloading, and using fonts on a desktop Linux system will be an entirely different experience.
-
-One train of thought on the typography challenges of modern Linux users includes packaging, document design, and maybe even a few new software components for desktop environments. There are other trains to consider, too. The commonality is that where the web-font service ends, matters get more difficult.
-
-The best news, from my perspective, is that there are more people interested in this topic than ever before. For that, I think we have the higher profile that open fonts have received from big web-font services like Google Fonts and Open Font Library to thank.
-
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/3/webfonts
-
-作者:[Nathan Willis][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://opensource.com/users/n8willis
-[1]:https://en.wikipedia.org/wiki/Core_fonts_for_the_Web
-[2]:https://en.wikipedia.org/wiki/Web_Open_Font_Format
-[3]:https://fonts.google.com/
-[4]:https://fontlibrary.org/
-[5]:https://fontmanager.github.io/
-[6]:https://en.wikipedia.org/wiki/Didone_(typography)
-[7]:https://en.wikipedia.org/wiki/Firmin_Didot
-[8]:https://en.wikipedia.org/wiki/Giambattista_Bodoni
-[9]:https://software.sil.org/gentium/
-[10]:https://djr.com/bungee/
-[11]:https://www.freedesktop.org/wiki/Distributions/AppStream/
-[12]:https://www.freedesktop.org/software/appstream/docs/sect-Metadata-Fonts.html
-[13]:https://spdx.org/
diff --git a/sources/tech/20180414 Go on very small hardware Part 2.md b/sources/tech/20180414 Go on very small hardware Part 2.md
deleted file mode 100644
index 8ebfb263f1..0000000000
--- a/sources/tech/20180414 Go on very small hardware Part 2.md
+++ /dev/null
@@ -1,969 +0,0 @@
-Go on very small hardware (Part 2)
-============================================================
-
-
- [][1]
-
-At the end of the [first part][2] of this article I promised to write something about _interfaces_ . I don’t want to write here a complete or even brief lecture about the interfaces. Instead, I’ll show a simple example how to define and use an interface, and then, how to take advantage of ubiquitous _io.Writer_ interface. There will also be a few words about _reflection_ and _semihosting_ .
-
-Interfaces are a crucial part of Go language. If you want to learn more about them, I suggest to read [Effective Go][3] and [Russ Cox article][4].
-
-### Concurrent Blinky – revisited
-
-When you read the code of previous examples you probably noticed a counterintuitive way to turn the LED on or off. The _Set_ method was used to turn the LED off and the _Clear_ method was used to turn the LED on. This is due to driving the LEDs in open-drain configuration. What we can do to make the code less confusing? Let’s define the _LED_ type with _On_ and _Off_ methods:
-
-```
-type LED struct {
- pin gpio.Pin
-}
-
-func (led LED) On() {
- led.pin.Clear()
-}
-
-func (led LED) Off() {
- led.pin.Set()
-}
-
-```
-
-Now we can simply call `led.On()` and `led.Off()` which no longer raises any doubts.
-
-In all previous examples I tried to use the same open-drain configuration to don’t complicate the code. But in the last example, it would be easier for me to connect the third LED between GND and PA3 pins and configure PA3 in push-pull mode. The next example will use a LED connected this way.
-
-But our new _LED_ type doesn’t support the push-pull configuration. In fact, we should call it _OpenDrainLED_ and define another _PushPullLED_ type:
-
-```
-type PushPullLED struct {
- pin gpio.Pin
-}
-
-func (led PushPullLED) On() {
- led.pin.Set()
-}
-
-func (led PushPullLED) Off() {
- led.pin.Clear()
-}
-
-```
-
-Note, that both types have the same methods that work the same. It would be nice if the code that operates on LEDs could use both types, without paying attention to which one it uses at the moment. The _interface type_ comes to help:
-
-```
-package main
-
-import (
- "delay"
-
- "stm32/hal/gpio"
- "stm32/hal/system"
- "stm32/hal/system/timer/systick"
-)
-
-type LED interface {
- On()
- Off()
-}
-
-type PushPullLED struct{ pin gpio.Pin }
-
-func (led PushPullLED) On() {
- led.pin.Set()
-}
-
-func (led PushPullLED) Off() {
- led.pin.Clear()
-}
-
-func MakePushPullLED(pin gpio.Pin) PushPullLED {
- pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.PushPull})
- return PushPullLED{pin}
-}
-
-type OpenDrainLED struct{ pin gpio.Pin }
-
-func (led OpenDrainLED) On() {
- led.pin.Clear()
-}
-
-func (led OpenDrainLED) Off() {
- led.pin.Set()
-}
-
-func MakeOpenDrainLED(pin gpio.Pin) OpenDrainLED {
- pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain})
- return OpenDrainLED{pin}
-}
-
-var led1, led2 LED
-
-func init() {
- system.SetupPLL(8, 1, 48/8)
- systick.Setup(2e6)
-
- gpio.A.EnableClock(false)
- led1 = MakeOpenDrainLED(gpio.A.Pin(4))
- led2 = MakePushPullLED(gpio.A.Pin(3))
-}
-
-func blinky(led LED, period int) {
- for {
- led.On()
- delay.Millisec(100)
- led.Off()
- delay.Millisec(period - 100)
- }
-}
-
-func main() {
- go blinky(led1, 500)
- blinky(led2, 1000)
-}
-
-```
-
-We’ve defined _LED_ interface that has two methods: _On_ and _Off_ . The _PushPullLED_ and _OpenDrainLED_ types represent two ways of driving LEDs. We also defined two _Make_ _*LED_ functions which act as constructors. Both types implement the _LED_ interface, so the values of these types can be assigned to the variables of type _LED_ :
-
-```
-led1 = MakeOpenDrainLED(gpio.A.Pin(4))
-led2 = MakePushPullLED(gpio.A.Pin(3))
-
-```
-
-In this case the assignability is checked at compile time. After the assignment the _led1_ variable contains `OpenDrainLED{gpio.A.Pin(4)}` and a pointer to the method set of the _OpenDrainLED_ type. The `led1.On()` call roughly corresponds to the following C code:
-
-```
-led1.methods->On(led1.value)
-
-```
-
-As you can see, this is quite inexpensive abstraction if only consider the function call overhead.
-
-But any assigment to an interface causes to include a lot of information about the assigned type. There can be a lot information in case of complex type which consists of many other types:
-
-```
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 10356 196 212 10764 2a0c cortexm0.elf
-
-```
-
-If we don’t use [reflection][5] we can save some bytes by avoid to include the names of types and struct fields:
-
-```
-$ egc -nf -nt
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 10312 196 212 10720 29e0 cortexm0.elf
-
-```
-
-The resulted binary still contains some necessary information about types and full information about all exported methods (with names). This information is need for checking assignability at runtime, mainly when you assign one value stored in the interface variable to any other variable.
-
-We can also remove type and field names from imported packages by recompiling them all:
-
-```
-$ cd $HOME/emgo
-$ ./clean.sh
-$ cd $HOME/firstemgo
-$ egc -nf -nt
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 10272 196 212 10680 29b8 cortexm0.elf
-
-```
-
-Let’s load this program to see does it work as expected. This time we’ll use the [st-flash][6] command:
-
-```
-$ arm-none-eabi-objcopy -O binary cortexm0.elf cortexm0.bin
-$ st-flash write cortexm0.bin 0x8000000
-st-flash 1.4.0-33-gd76e3c7
-2018-04-10T22:04:34 INFO usb.c: -- exit_dfu_mode
-2018-04-10T22:04:34 INFO common.c: Loading device parameters....
-2018-04-10T22:04:34 INFO common.c: Device connected is: F0 small device, id 0x10006444
-2018-04-10T22:04:34 INFO common.c: SRAM size: 0x1000 bytes (4 KiB), Flash: 0x4000 bytes (16 KiB) in pages of 1024 bytes
-2018-04-10T22:04:34 INFO common.c: Attempting to write 10468 (0x28e4) bytes to stm32 address: 134217728 (0x8000000)
-Flash page at addr: 0x08002800 erased
-2018-04-10T22:04:34 INFO common.c: Finished erasing 11 pages of 1024 (0x400) bytes
-2018-04-10T22:04:34 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id
-2018-04-10T22:04:34 INFO flash_loader.c: Successfully loaded flash loader in sram
- 11/11 pages written
-2018-04-10T22:04:35 INFO common.c: Starting verification of write complete
-2018-04-10T22:04:35 INFO common.c: Flash written and verified! jolly good!
-
-```
-
-I didn’t connected the NRST signal to the programmer so the _—reset_ option can’t be used and the reset button have to be pressed to run the program.
-
-
-
-It seems that the _st-flash_ works a bit unreliably with this board (often requires reseting the ST-LINK dongle). Additionally, the current version doesn’t issue the reset command over SWD (uses only NRST signal). The software reset isn’t realiable however it usually works and lack of it introduces inconvenience. For this board-programmer pair the _OpenOCD_ works much better.
-
-### UART
-
-UART (Universal Aynchronous Receiver-Transmitter) is still one of the most important peripherals of today’s microcontrollers. Its advantage is unique combination of the following properties:
-
-* relatively high speed,
-
-* only two signal lines (even one in case of half-duplex communication),
-
-* symmetry of roles,
-
-* synchronous in-band signaling about new data (start bit),
-
-* accurate timing inside transmitted word.
-
-This causes that UART, originally intedned to transmit asynchronous messages consisting of 7-9 bit words, is also used to efficiently implement various other phisical protocols such as used by [WS28xx LEDs][7] or [1-wire][8] devices.
-
-However, we will use the UART in its usual role: to printing text messages from our program.
-
-```
-package main
-
-import (
- "io"
- "rtos"
-
- "stm32/hal/dma"
- "stm32/hal/gpio"
- "stm32/hal/irq"
- "stm32/hal/system"
- "stm32/hal/system/timer/systick"
- "stm32/hal/usart"
-)
-
-var tts *usart.Driver
-
-func init() {
- system.SetupPLL(8, 1, 48/8)
- systick.Setup(2e6)
-
- gpio.A.EnableClock(true)
- tx := gpio.A.Pin(9)
-
- tx.Setup(&gpio.Config{Mode: gpio.Alt})
- tx.SetAltFunc(gpio.USART1_AF1)
- d := dma.DMA1
- d.EnableClock(true)
- tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
- tts.Periph().EnableClock(true)
- tts.Periph().SetBaudRate(115200)
- tts.Periph().Enable()
- tts.EnableTx()
-
- rtos.IRQ(irq.USART1).Enable()
- rtos.IRQ(irq.DMA1_Channel2_3).Enable()
-}
-
-func main() {
- io.WriteString(tts, "Hello, World!\r\n")
-}
-
-func ttsISR() {
- tts.ISR()
-}
-
-func ttsDMAISR() {
- tts.TxDMAISR()
-}
-
-//c:__attribute__((section(".ISRs")))
-var ISRs = [...]func(){
- irq.USART1: ttsISR,
- irq.DMA1_Channel2_3: ttsDMAISR,
-}
-
-```
-
-You can find this code slightly complicated but for now there is no simpler UART driver in STM32 HAL (simple polling driver will be probably useful in some cases). The _usart.Driver_ is efficient driver that uses DMA and interrupts to ofload the CPU.
-
-STM32 USART peripheral provides traditional UART and its synchronous version. To use it as output we have to connect its Tx signal to the right GPIO pin:
-
-```
-tx.Setup(&gpio.Config{Mode: gpio.Alt})
-tx.SetAltFunc(gpio.USART1_AF1)
-
-```
-
-The _usart.Driver_ is configured in Tx-only mode (rxdma and rxbuf are set to nil):
-
-```
-tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
-
-```
-
-We use its _WriteString_ method to print the famous sentence. Let’s clean everything and compile this program:
-
-```
-$ cd $HOME/emgo
-$ ./clean.sh
-$ cd $HOME/firstemgo
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 12728 236 176 13140 3354 cortexm0.elf
-
-```
-
-To see something you need an UART peripheral in your PC.
-
-**Do not use RS232 port or USB to RS232 converter!**
-
-The STM32 family uses 3.3 V logic but RS232 can produce from -15 V to +15 V which will probably demage your MCU. You need USB to UART converter that uses 3.3 V logic. Popular converters are based on FT232 or CP2102 chips.
-
-
-
-You also need some terminal emulator program (I prefer [picocom][9]). Flash the new image, run the terminal emulator and press the reset button a few times:
-
-```
-$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit'
-Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
-Licensed under GNU GPL v2
-For bug reports, read
- http://openocd.org/doc/doxygen/bugs.html
-debug_level: 0
-adapter speed: 1000 kHz
-adapter_nsrst_delay: 100
-none separate
-adapter speed: 950 kHz
-target halted due to debug-request, current mode: Thread
-xPSR: 0xc1000000 pc: 0x080016f4 msp: 0x20000a20
-adapter speed: 4000 kHz
-** Programming Started **
-auto erase enabled
-target halted due to breakpoint, current mode: Thread
-xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000a20
-wrote 13312 bytes from file cortexm0.elf in 1.020185s (12.743 KiB/s)
-** Programming Finished **
-adapter speed: 950 kHz
-$
-$ picocom -b 115200 /dev/ttyUSB0
-picocom v3.1
-
-port is : /dev/ttyUSB0
-flowcontrol : none
-baudrate is : 115200
-parity is : none
-databits are : 8
-stopbits are : 1
-escape is : C-a
-local echo is : no
-noinit is : no
-noreset is : no
-hangup is : no
-nolock is : no
-send_cmd is : sz -vv
-receive_cmd is : rz -vv -E
-imap is :
-omap is :
-emap is : crcrlf,delbs,
-logfile is : none
-initstring : none
-exit_after is : not set
-exit is : no
-
-Type [C-a] [C-h] to see available commands
-Terminal ready
-Hello, World!
-Hello, World!
-Hello, World!
-
-```
-
-Every press of the reset button produces new “Hello, World!” line. Everything works as expected.
-
-To see bi-directional UART code for this MCU check out [this example][10].
-
-### io.Writer
-
-The _io.Writer_ interface is probably the second most commonly used interface type in Go, right after the _error_ interface. Its definition looks like this:
-
-```
-type Writer interface {
- Write(p []byte) (n int, err error)
-}
-
-```
-
- _usart.Driver_ implements _io.Writer_ so we can replace:
-
-```
-tts.WriteString("Hello, World!\r\n")
-
-```
-
-with
-
-```
-io.WriteString(tts, "Hello, World!\r\n")
-
-```
-
-Additionally you need to add the _io_ package to the _import_ section.
-
-The declaration of _io.WriteString_ function looks as follows:
-
-```
-func WriteString(w Writer, s string) (n int, err error)
-
-```
-
-As you can see, the _io.WriteString_ allows to write strings using any type that implements _io.Writer_ interface. Internally it check does the underlying type has _WriteString_ method and uses it instead of _Write_ if available.
-
-Let’s compile the modified program:
-
-```
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 15456 320 248 16024 3e98 cortexm0.elf
-
-```
-
-As you can see, _io.WriteString_ causes a significant increase in the size of the binary: 15776 - 12964 = 2812 bytes. There isn’t too much space left on the Flash. What caused such a drastic increase in size?
-
-Using the command:
-
-```
-arm-none-eabi-nm --print-size --size-sort --radix=d cortexm0.elf
-
-```
-
-we can print all symbols ordered by its size for both cases. By filtering and analyzing the obtained data (awk, diff) we can find about 80 new symbols. The ten largest are:
-
-```
-> 00000062 T stm32$hal$usart$Driver$DisableRx
-> 00000072 T stm32$hal$usart$Driver$RxDMAISR
-> 00000076 T internal$Type$Implements
-> 00000080 T stm32$hal$usart$Driver$EnableRx
-> 00000084 t errors$New
-> 00000096 R $8$stm32$hal$usart$Driver$$
-> 00000100 T stm32$hal$usart$Error$Error
-> 00000360 T io$WriteString
-> 00000660 T stm32$hal$usart$Driver$Read
-
-```
-
-So, even though we don’t use the _usart.Driver.Read_ method it was compiled in, same as _DisableRx_ , _RxDMAISR_ , _EnableRx_ and other not mentioned above. Unfortunately, if you assign something to the interface, its full method set is required (with all dependences). This isn’t a problem for a large programs that use most of the methods anyway. But for our simple one it’s a huge burden.
-
-We’re already close to the limits of our MCU but let’s try to print some numbers (you need to replace _io_ package with _strconv_ in _import_ section):
-
-```
-func main() {
- a := 12
- b := -123
-
- tts.WriteString("a = ")
- strconv.WriteInt(tts, a, 10, 0, 0)
- tts.WriteString("\r\n")
- tts.WriteString("b = ")
- strconv.WriteInt(tts, b, 10, 0, 0)
- tts.WriteString("\r\n")
-
- tts.WriteString("hex(a) = ")
- strconv.WriteInt(tts, a, 16, 0, 0)
- tts.WriteString("\r\n")
- tts.WriteString("hex(b) = ")
- strconv.WriteInt(tts, b, 16, 0, 0)
- tts.WriteString("\r\n")
-}
-
-```
-
-As in the case of _io.WriteString_ function, the first argument of the _strconv.WriteInt_ is of type _io.Writer_ .
-
-```
-$ egc
-/usr/local/arm/bin/arm-none-eabi-ld: /home/michal/firstemgo/cortexm0.elf section `.rodata' will not fit in region `Flash'
-/usr/local/arm/bin/arm-none-eabi-ld: region `Flash' overflowed by 692 bytes
-exit status 1
-
-```
-
-This time we’ve run out of space. Let’s try to slim down the information about types:
-
-```
-$ cd $HOME/emgo
-$ ./clean.sh
-$ cd $HOME/firstemgo
-$ egc -nf -nt
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 15876 316 320 16512 4080 cortexm0.elf
-
-```
-
-It was close, but we fit. Let’s load and run this code:
-
-```
-a = 12
-b = -123
-hex(a) = c
-hex(b) = -7b
-
-```
-
-The _strconv_ package in Emgo is quite different from its archetype in Go. It is intended for direct use to write formatted numbers and in many cases can replace heavy _fmt_ package. That’s why the function names start with _Write_ instead of _Format_ and have additional two parameters. Below is an example of their use:
-
-```
-func main() {
- b := -123
- strconv.WriteInt(tts, b, 10, 0, 0)
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, 6, ' ')
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, 6, '0')
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, 6, '.')
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, -6, ' ')
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, -6, '0')
- tts.WriteString("\r\n")
- strconv.WriteInt(tts, b, 10, -6, '.')
- tts.WriteString("\r\n")
-}
-
-```
-
-There is its output:
-
-```
--123
- -123
--00123
-..-123
--123
--123
--123..
-
-```
-
-### Unix streams and Morse code
-
-Thanks to the fact that most of the functions that write something use _io.Writer_ instead of concrete type (eg. _FILE_ in C) we get a functionality similar to _Unix streams_ . In Unix we can easily combine simple commands to perform larger tasks. For example, we can write text to the file this way:
-
-```
-echo "Hello, World!" > file.txt
-
-```
-
-The `>` operator writes the output stream of the preceding command to the file. There is also `|`operator that connects output and input streams of adjacent commands.
-
-Thanks to the streams we can easily convert/filter output of any command. For example, to convert all letters to uppercase we can filter the echo’s output through _tr_ command:
-
-```
-echo "Hello, World!" | tr a-z A-Z > file.txt
-
-```
-
-To show the analogy between _io.Writer_ and Unix streams let’s write our:
-
-```
-io.WriteString(tts, "Hello, World!\r\n")
-
-```
-
-in the following pseudo-unix form:
-
-```
-io.WriteString "Hello, World!" | usart.Driver usart.USART1
-
-```
-
-The next example will show how to do this:
-
-```
-io.WriteString "Hello, World!" | MorseWriter | usart.Driver usart.USART1
-
-```
-
-Let’s create a simple encoder that encodes the text written to it using Morse coding:
-
-```
-type MorseWriter struct {
- W io.Writer
-}
-
-func (w *MorseWriter) Write(s []byte) (int, error) {
- var buf [8]byte
- for n, c := range s {
- switch {
- case c == '\n':
- c = ' ' // Replace new lines with spaces.
- case 'a' <= c && c <= 'z':
- c -= 'a' - 'A' // Convert to upper case.
- }
- if c < ' ' || 'Z' < c {
- continue // c is outside ASCII [' ', 'Z']
- }
- var symbol morseSymbol
- if c == ' ' {
- symbol.length = 1
- buf[0] = ' '
- } else {
- symbol = morseSymbols[c-'!']
- for i := uint(0); i < uint(symbol.length); i++ {
- if (symbol.code>>i)&1 != 0 {
- buf[i] = '-'
- } else {
- buf[i] = '.'
- }
- }
- }
- buf[symbol.length] = ' '
- if _, err := w.W.Write(buf[:symbol.length+1]); err != nil {
- return n, err
- }
- }
- return len(s), nil
-}
-
-type morseSymbol struct {
- code, length byte
-}
-
-//emgo:const
-var morseSymbols = [...]morseSymbol{
- {1<<0 | 1<<1 | 1<<2, 4}, // ! ---.
- {1<<1 | 1<<4, 6}, // " .-..-.
- {}, // #
- {1<<3 | 1<<6, 7}, // $ ...-..-
-
- // Some code omitted...
-
- {1<<0 | 1<<3, 4}, // X -..-
- {1<<0 | 1<<2 | 1<<3, 4}, // Y -.--
- {1<<0 | 1<<1, 4}, // Z --..
-}
-
-```
-
-You can find the full _morseSymbols_ array [here][11]. The `//emgo:const` directive ensures that _morseSymbols_ array won’t be copied to the RAM.
-
-Now we can print our sentence in two ways:
-
-```
-func main() {
- s := "Hello, World!\r\n"
- mw := &MorseWriter{tts}
-
- io.WriteString(tts, s)
- io.WriteString(mw, s)
-}
-
-```
-
-We use the pointer to the _MorseWriter_ `&MorseWriter{tts}` instead os simple `MorseWriter{tts}` value beacuse the _MorseWriter_ is to big to fit into an interface variable.
-
-Emgo, unlike Go, doesn’t dynamically allocate memory for value stored in interface variable. The interface type has limited size, equal to the size of three pointers (to fit _slice_ ) or two _float64_ (to fit _complex128_ ), what is bigger. It can directly store values of all basic types and small structs/arrays but for bigger values you must use pointers.
-
-Let’s compile this code and see its output:
-
-```
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 15152 324 248 15724 3d6c cortexm0.elf
-
-```
-
-```
-Hello, World!
-.... . .-.. .-.. --- --..-- .-- --- .-. .-.. -.. ---.
-
-```
-
-### The Ultimate Blinky
-
-The _Blinky_ is hardware equivalent of _Hello, World!_ program. Once we have a Morse encoder we can easly combine both to obtain the _Ultimate Blinky_ program:
-
-```
-package main
-
-import (
- "delay"
- "io"
-
- "stm32/hal/gpio"
- "stm32/hal/system"
- "stm32/hal/system/timer/systick"
-)
-
-var led gpio.Pin
-
-func init() {
- system.SetupPLL(8, 1, 48/8)
- systick.Setup(2e6)
-
- gpio.A.EnableClock(false)
- led = gpio.A.Pin(4)
-
- cfg := gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain, Speed: gpio.Low}
- led.Setup(&cfg)
-}
-
-type Telegraph struct {
- Pin gpio.Pin
- Dotms int // Dot length [ms]
-}
-
-func (t Telegraph) Write(s []byte) (int, error) {
- for _, c := range s {
- switch c {
- case '.':
- t.Pin.Clear()
- delay.Millisec(t.Dotms)
- t.Pin.Set()
- delay.Millisec(t.Dotms)
- case '-':
- t.Pin.Clear()
- delay.Millisec(3 * t.Dotms)
- t.Pin.Set()
- delay.Millisec(t.Dotms)
- case ' ':
- delay.Millisec(3 * t.Dotms)
- }
- }
- return len(s), nil
-}
-
-func main() {
- telegraph := &MorseWriter{Telegraph{led, 100}}
- for {
- io.WriteString(telegraph, "Hello, World! ")
- }
-}
-
-// Some code omitted...
-
-```
-
-In the above example I omitted the definition of _MorseWriter_ type because it was shown earlier. The full version is available [here][12]. Let’s compile it and run:
-
-```
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 11772 244 244 12260 2fe4 cortexm0.elf
-
-```
-
-
-
-### Reflection
-
-Yes, Emgo supports [reflection][13]. The _reflect_ package isn’t complete yet but that what is done is enough to implement _fmt.Print_ family of functions. Let’s see what can we do on our small MCU.
-
-To reduce memory usage we will use [semihosting][14] as standard output. For convenience, we also write simple _println_ function which to some extent mimics _fmt.Println_ .
-
-```
-package main
-
-import (
- "debug/semihosting"
- "reflect"
- "strconv"
-
- "stm32/hal/system"
- "stm32/hal/system/timer/systick"
-)
-
-var stdout semihosting.File
-
-func init() {
- system.SetupPLL(8, 1, 48/8)
- systick.Setup(2e6)
-
- var err error
- stdout, err = semihosting.OpenFile(":tt", semihosting.W)
- for err != nil {
- }
-}
-
-type stringer interface {
- String() string
-}
-
-func println(args ...interface{}) {
- for i, a := range args {
- if i > 0 {
- stdout.WriteString(" ")
- }
- switch v := a.(type) {
- case string:
- stdout.WriteString(v)
- case int:
- strconv.WriteInt(stdout, v, 10, 0, 0)
- case bool:
- strconv.WriteBool(stdout, v, 't', 0, 0)
- case stringer:
- stdout.WriteString(v.String())
- default:
- stdout.WriteString("%unknown")
- }
- }
- stdout.WriteString("\r\n")
-}
-
-type S struct {
- A int
- B bool
-}
-
-func main() {
- p := &S{-123, true}
-
- v := reflect.ValueOf(p)
-
- println("kind(p) =", v.Kind())
- println("kind(*p) =", v.Elem().Kind())
- println("type(*p) =", v.Elem().Type())
-
- v = v.Elem()
-
- println("*p = {")
- for i := 0; i < v.NumField(); i++ {
- ft := v.Type().Field(i)
- fv := v.Field(i)
- println(" ", ft.Name(), ":", fv.Interface())
- }
- println("}")
-}
-
-```
-
-The _semihosting.OpenFile_ function allows to open/create file on the host side. The special path _:tt_ corresponds to host’s standard output.
-
-The _println_ function accepts arbitrary number of arguments, each of arbitrary type:
-
-```
-func println(args ...interface{})
-
-```
-
-It’s possible because any type implements the empty interface _interface{}_ . The _println_ uses [type switch][15] to print strings, integers and booleans:
-
-```
-switch v := a.(type) {
-case string:
- stdout.WriteString(v)
-case int:
- strconv.WriteInt(stdout, v, 10, 0, 0)
-case bool:
- strconv.WriteBool(stdout, v, 't', 0, 0)
-case stringer:
- stdout.WriteString(v.String())
-default:
- stdout.WriteString("%unknown")
-}
-
-```
-
-Additionally it supports any type that implements _stringer_ interface, that is, any type that has _String()_ method. In any _case_ clause the _v_ variable has the right type, same as listed after _case_ keyword.
-
-The `reflect.ValueOf(p)` returns _p_ in the form that allows to analyze its type and content programmatically. As you can see, we can even dereference pointers using `v.Elem()` and print all struct fields with their names.
-
-Let’s try to compile this code. For now let’s see what will come out if compiled without type and field names:
-
-```
-$ egc -nt -nf
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 16028 216 312 16556 40ac cortexm0.elf
-
-```
-
-Only 140 free bytes left on the Flash. Let’s load it using OpenOCD with semihosting enabled:
-
-```
-$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; arm semihosting enable; reset run'
-Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
-Licensed under GNU GPL v2
-For bug reports, read
- http://openocd.org/doc/doxygen/bugs.html
-debug_level: 0
-adapter speed: 1000 kHz
-adapter_nsrst_delay: 100
-none separate
-adapter speed: 950 kHz
-target halted due to debug-request, current mode: Thread
-xPSR: 0xc1000000 pc: 0x08002338 msp: 0x20000a20
-adapter speed: 4000 kHz
-** Programming Started **
-auto erase enabled
-target halted due to breakpoint, current mode: Thread
-xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000a20
-wrote 16384 bytes from file cortexm0.elf in 0.700133s (22.853 KiB/s)
-** Programming Finished **
-semihosting is enabled
-adapter speed: 950 kHz
-kind(p) = ptr
-kind(*p) = struct
-type(*p) =
-*p = {
- X. : -123
- X. : true
-}
-
-```
-
-If you’ve actually run this code, you noticed that semihosting is slow, especially if you write a byte after byte (buffering helps).
-
-As you can see, there is no type name for `*p` and all struct fields have the same _X._ name. Let’s compile this program again, this time without _-nt -nf_ options:
-
-```
-$ egc
-$ arm-none-eabi-size cortexm0.elf
- text data bss dec hex filename
- 16052 216 312 16580 40c4 cortexm0.elf
-
-```
-
-Now the type and field names have been included but only these defined in ~~_main.go_ file~~ _main_ package. The output of our program looks as follows:
-
-```
-kind(p) = ptr
-kind(*p) = struct
-type(*p) = S
-*p = {
- A : -123
- B : true
-}
-
-```
-
-Reflection is a crucial part of any easy to use serialization library and serialization ~~algorithms~~ like [JSON][16]gain in importance in the IOT era.
-
-This is where I finish the second part of this article. I think there is a chance for the third part, more entertaining, where we connect to this board various interesting devices. If this board won’t carry them, we replace it with something a little bigger.
-
---------------------------------------------------------------------------------
-
-via: https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html
-
-作者:[Michał Derkacz ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://ziutek.github.io/
-[1]:https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html
-[2]:https://ziutek.github.io/2018/03/30/go_on_very_small_hardware.html
-[3]:https://golang.org/doc/effective_go.html#interfaces
-[4]:https://research.swtch.com/interfaces
-[5]:https://blog.golang.org/laws-of-reflection
-[6]:https://github.com/texane/stlink
-[7]:http://www.world-semi.com/solution/list-4-1.html
-[8]:https://en.wikipedia.org/wiki/1-Wire
-[9]:https://github.com/npat-efault/picocom
-[10]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/usart/main.go
-[11]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/morseuart/main.go
-[12]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/morseled/main.go
-[13]:https://blog.golang.org/laws-of-reflection
-[14]:http://infocenter.arm.com/help/topic/com.arm.doc.dui0471g/Bgbjjgij.html
-[15]:https://golang.org/doc/effective_go.html#type_switch
-[16]:https://en.wikipedia.org/wiki/JSON
diff --git a/sources/tech/20180416 Cgo and Python.md b/sources/tech/20180416 Cgo and Python.md
index c78a820276..e5688d43c8 100644
--- a/sources/tech/20180416 Cgo and Python.md
+++ b/sources/tech/20180416 Cgo and Python.md
@@ -1,5 +1,4 @@
Cgo and Python
-[#] MonkeyDEcho translating
============================================================

diff --git a/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md b/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md
deleted file mode 100644
index aaa5a6ca00..0000000000
--- a/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md
+++ /dev/null
@@ -1,146 +0,0 @@
-An introduction to the GNU Core Utilities
-======
-
-
-
-Image credits :
-
-[Bella67][1] via Pixabay. [CC0][2].
-
-Two sets of utilities—the [GNU Core Utilities][3] and util-linux—comprise many of the Linux system administrator's most basic and regularly used tools. Their basic functions allow sysadmins to perform many of the tasks required to administer a Linux computer, including management and manipulation of text files, directories, data streams, storage media, process controls, filesystems, and much more.
-
-These tools are indispensable because, without them, it is impossible to accomplish any useful work on a Unix or Linux computer. Given their importance, let's examine them.
-
-### GNU coreutils
-
-The Linux Terminal
-
-* [Top 7 terminal emulators for Linux][4]
-* [10 command-line tools for data analysis in Linux][5]
-* [Download Now: SSH cheat sheet][6]
-* [Advanced Linux commands cheat sheet][7]
-
-To understand the origins of the GNU Core Utilities, we need to take a short trip in the Wayback machine to the early days of Unix at Bell Labs. [Unix was written][8] so Ken Thompson, Dennis Ritchie, Doug McIlroy, and Joe Ossanna could continue with something they had started while working on a large multi-tasking and multi-user computer project called [Multics][9]. That little something was a game called Space Travel. As remains true today, it always seems to be the gamers who drive forward the technology of computing. This new operating system was much more limited than Multics, as only two users could log in at a time, so it was called Unics. This name was later changed to Unix.
-
-Over time, Unix turned out to be such a success that Bell Labs began essentially giving it away it to universities and later to companies for the cost of the media and shipping. Back in those days, system-level software was shared between organizations and programmers as they worked to achieve common goals within the context of system administration.
-
-Eventually, the [PHBs][10] at AT&T decided they should make money on Unix and started using more restrictive—and expensive—licensing. This was taking place at a time when software was becoming more proprietary, restricted, and closed. It was becoming impossible to share software with other users and organizations.
-
-Some people did not like this and fought it with free software. Richard M. Stallman, aka RMS, led a group of rebels who were trying to write an open and freely available operating system they called the GNU Operating System. This group created the GNU Utilities but didn't produce a viable kernel.
-
-When Linus Torvalds first wrote and compiled the Linux kernel, he needed a set of very basic system utilities to even begin to perform marginally useful work. The kernel does not provide commands or any type of command shell such as Bash. It is useless by itself. So, Linus used the freely available GNU Core Utilities and recompiled them for Linux. This gave him a complete, if quite basic, operating system.
-
-You can learn about all the individual programs that comprise the GNU Utilities by entering the command info coreutils at a terminal command line. The following list of the core utilities is part of that info page. The utilities are grouped by function to make specific ones easier to find; in the terminal, highlight the group you want more information on and press the Enter key.
-
-```
-* Output of entire files:: cat tac nl od base32 base64
-* Formatting file contents:: fmt pr fold
-* Output of parts of files:: head tail split csplit
-* Summarizing files:: wc sum cksum b2sum md5sum sha1sum sha2
-* Operating on sorted files:: sort shuf uniq comm ptx tsort
-* Operating on fields:: cut paste join
-* Operating on characters:: tr expand unexpand
-* Directory listing:: ls dir vdir dircolors
-* Basic operations:: cp dd install mv rm shred
-* Special file types:: mkdir rmdir unlink mkfifo mknod ln link readlink
-* Changing file attributes:: chgrp chmod chown touch
-* Disk usage:: df du stat sync truncate
-* Printing text:: echo printf yes
-* Conditions:: false true test expr
-* Redirection:: tee
-* File name manipulation:: dirname basename pathchk mktemp realpath
-* Working context:: pwd stty printenv tty
-* User information:: id logname whoami groups users who
-* System context:: date arch nproc uname hostname hostid uptime
-* SELinux context:: chcon runcon
-* Modified command invocation:: chroot env nice nohup stdbuf timeout
-* Process control:: kill
-* Delaying:: sleep
-* Numeric operations:: factor numfmt seq
-```
-
-There are 102 utilities on this list. It covers many of the functions necessary to perform basic tasks on a Unix or Linux host. However, many basic utilities are missing. For example, the mount and umount commands are not in this list. Those and many of the other commands that are not in the GNU coreutils can be found in the util-linux collection.
-
-### util-linux
-
-The util-linix package of utilities contains many of the other common commands that sysadmins use. These utilities are distributed by the Linux Kernel Organization, and virtually every one of these 107 commands were originally three separate collections—fileutils, shellutils, and textutils—which were [combined into the single package][11] util-linux in 2003.
-
-```
-agetty fsck.minix mkfs.bfs setpriv
-blkdiscard fsfreeze mkfs.cramfs setsid
-blkid fstab mkfs.minix setterm
-blockdev fstrim mkswap sfdisk
-cal getopt more su
-cfdisk hexdump mount sulogin
-chcpu hwclock mountpoint swaplabel
-chfn ionice namei swapoff
-chrt ipcmk newgrp swapon
-chsh ipcrm nologin switch_root
-colcrt ipcs nsenter tailf
-col isosize partx taskset
-colrm kill pg tunelp
-column last pivot_root ul
-ctrlaltdel ldattach prlimit umount
-ddpart line raw unshare
-delpart logger readprofile utmpdump
-dmesg login rename uuidd
-eject look renice uuidgen
-fallocate losetup reset vipw
-fdformat lsblk resizepart wall
-fdisk lscpu rev wdctl
-findfs lslocks RTC Alarm whereis
-findmnt lslogins runuser wipefs
-flock mcookie script write
-fsck mesg scriptreplay zramctl
-fsck.cramfs mkfs setarch
-```
-
-Some of these utilities have been deprecated and will likely fall out of the collection at some point in the future. You should check [Wikipedia's util-linux page][12] for information on many of the utilities, and the man pages also provide details on the commands.
-
-### Summary
-
-These two collections of Linux utilities, the GNU Core Utilities and util-linux, together provide the basic utilities required to administer a Linux system. As I researched this article, I found several interesting utilities I never knew about. Many of these commands are seldom needed, but when you need them, they are indispensable.
-
-Between these two collections, there are over 200 Linux utilities. While Linux has many more commands, these are the ones needed to manage the basic functions of a typical Linux host.
-
-### About the author
-
-[][13]
-
-David Both \- David Both is a Linux and Open Source advocate who resides in Raleigh, North Carolina. He has been in the IT industry for over forty years and taught OS/2 for IBM where he worked for over 20 years. While at IBM, he wrote the first training course for the original IBM PC in 1981. He has taught RHCE classes for Red Hat and has worked at MCI Worldcom, Cisco, and the State of North Carolina. He has been working with Linux and Open Source Software for almost 20 years. David has written articles for... [more about David Both][14]
-
-[More about me][15]
-
-* [Learn how you can contribute][16]
-
----
-
-via: [https://opensource.com/article/18/4/gnu-core-utilities][17]
-
-作者: [David Both][18] 选题者: [@lujun9972][19] 译者: [译者ID][20] 校对: [校对者ID][21]
-
-本文由 [LCTT][22] 原创编译,[Linux中国][23] 荣誉推出
-
-[1]: https://pixabay.com/en/tiny-people-core-apple-apple-half-700921/
-[2]: https://creativecommons.org/publicdomain/zero/1.0/
-[3]: https://www.gnu.org/software/coreutils/coreutils.html
-[4]: https://opensource.com/life/17/10/top-terminal-emulators?intcmp=7016000000127cYAAQ
-[5]: https://opensource.com/article/17/2/command-line-tools-data-analysis-linux?intcmp=7016000000127cYAAQ
-[6]: https://opensource.com/downloads/advanced-ssh-cheat-sheet?intcmp=7016000000127cYAAQ
-[7]: https://developers.redhat.com/cheat-sheet/advanced-linux-commands-cheatsheet?intcmp=7016000000127cYAAQ
-[8]: https://en.wikipedia.org/wiki/History_of_Unix
-[9]: https://en.wikipedia.org/wiki/Multics
-[10]: https://en.wikipedia.org/wiki/Pointy-haired_Boss
-[11]: https://en.wikipedia.org/wiki/GNU_Core_Utilities
-[12]: https://en.wikipedia.org/wiki/Util-linux
-[13]: https://opensource.com/users/dboth
-[14]: https://opensource.com/users/dboth
-[15]: https://opensource.com/users/dboth
-[16]: https://opensource.com/participate
-[17]: https://opensource.com/article/18/4/gnu-core-utilities
-[18]: https://opensource.com/users/dboth
-[19]: https://github.com/lujun9972
-[20]: https://github.com/译者ID
-[21]: https://github.com/校对者ID
-[22]: https://github.com/LCTT/TranslateProject
-[23]: https://linux.cn/
diff --git a/sources/tech/20180522 Advanced use of the less text file viewer in Linux.md b/sources/tech/20180522 Advanced use of the less text file viewer in Linux.md
deleted file mode 100644
index 9d8ea93869..0000000000
--- a/sources/tech/20180522 Advanced use of the less text file viewer in Linux.md
+++ /dev/null
@@ -1,119 +0,0 @@
-Translating by MjSeven
-
-Advanced use of the less text file viewer in Linux
-======
-
-
-
-I recently read Scott Nesbitt's article "[Using less to view text files at the Linux command line][1]" and was inspired to share additional tips and tricks I use with `less`.
-
-### LESS env var
-
-If you have an environment variable `LESS` defined (e.g., in your `.bashrc`), `less` treats it as a list of options, as if passed on the command line.
-
-I use this:
-```
-LESS='-C -M -I -j 10 -# 4'
-
-```
-
-These mean:
-
- * `-C` – Make full-screen reprints faster by not scrolling from the bottom.
- * `-M` – Show more information from the last (status) line. You can customize the information shown with `-PM`, but I usually do not bother.
- * `-I` – Ignore letter case (upper/lower) in searches.
- * `-j 10` – Show search results in line 10 of the terminal, instead of the first line. This way you have 10 lines of context each time you press `n` (or `N`) to jump to the next (or previous) match.
- * `-# 4` – Jump four characters to the right or left when pressing the Right or Left arrow key. The default is to jump half of the screen, which I usually find to be too much. Generally speaking, `less` seems to be (at least partially) optimized to the environment it was initially developed in, with slow modems and low-bandwidth internet connections, when it made sense to jump half a screen.
-
-
-
-### PAGER env var
-
-Many programs show information using the command set in the `PAGER` environment variable (if it's set). So, you can set `PAGER=less` in your `.bashrc` and have your program run `less`. Check the man page environ(7) (`man 7 environ`) for other such variables.
-
-### -S
-
-`-S` tells `less` to chop long lines instead of wrapping them. I rarely find a need for this unless (and until) I've started viewing a file. Fortunately, you can type all command-line options inside `less` as if they were keyboard commands. So, if I want to chop long lines while I'm already in a file, I can simply type `-S`.
-
-The command-line optiontellsto chop long lines instead of wrapping them. I rarely find a need for this unless (and until) I've started viewing a file. Fortunately, you can type all command-line options insideas if they were keyboard commands. So, if I want to chop long lines while I'm already in a file, I can simply type
-
-Here's an example I use a lot:
-```
- su - postgres
-
- export PAGER=less # Because I didn't bother editing postgres' .bashrc on all the machines I use it on
-
- psql
-
-```
-
-Sometimes when I later view the output of a `SELECT` command with a very wide output, I type `-S` so it will be formatted nicely. If it jumps too far when I press the Right arrow to see more (because I didn't set `-#`), I can type `-#8`, then each Right arrow press will move eight characters to the right.
-
-Sometimes after typing `-S` too many times, I exit psql and run it again after entering:
-```
-export LESS=-S
-
-```
-
-### F
-
-The command `F` makes `less` work like `tail -f`—waiting until more data is added to the file before showing it. One advantage this has over `tail -f` is that highlighting search matches still works. So you can enter `less /var/log/logfile`, search for something—which will highlight all occurrences of it (unless you used `-g`)—and then press `F`. When more data is written to the log, `less` will show it and highlight the new matches.
-
-After you press `F`, you can press `Ctrl+C` to stop it from looking for new data (this will not kill it); go back into the file to see older stuff, search for other things, etc.; and then press `F` again to look at more new data.
-
-### Searching
-
-Searches use the system's regexp library, and this usually means you can use extended regular expressions. In particular, searching for `one|two|three` will find and highlight all occurrences of one, two, or three.
-
-Another pattern I use a lot, especially with wide log lines (e.g., ones that span more than one terminal line), is `.*something.*`, which highlights the entire line. This pattern makes it much easier to see where a line starts and finishes. I also combine these, such as: `.*one thing.*|.*another thing.*`, or `key: .*|.*marker.*` to see the contents of `key` (e.g., in a log file with a dump of some dictionary/hash) and highlight relevant marker lines (so I have a context), or even, if I know the value is surrounded by quotes:
-```
-key: '[^']*'|.*marker.*
-
-```
-
-`less` maintains a history of your search items and saves them to disk for future invocations. When you press `/` (or `?`), you can go through this history with the Up or Down arrow (as well as do basic line editing).
-
-I stumbled upon what seems to be a very useful feature when skimming through the `less` man page while writing this article: skipping uninteresting lines with `&!pattern`. For example, while looking for something in `/var/log/messages`, I used to iterate through this list of commands:
-```
- cat /var/log/messages | egrep -v 'systemd: Started Session' | less
-
- cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session' | less
-
- cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice' | less
-
- cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus' | less
-
- cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus|PackageKit Daemon' | less
-
-```
-
-But now I know how to do the same thing within `less`. For example, I can type `&!systemd: Started Session`, then decide I want to get rid of `systemd: Starting Session`, so I add it by typing `&!` and use the Up arrow to get the previous search from the history. Then I type `|systemd: Starting Session` and press `Enter`, continuing to add more items the same way until I filter out enough to see the more interesting stuff.
-
-### =
-
-The command `=` shows more information about the file and location, even more than `-M`. If the file is very long, and calculating `=` takes too long, you can press `Ctrl+C` and it will stop trying.
-
-If the content you're viewing is from a pipe rather than a file, `=` (and `-M`) will not show what it does not know, including the number of lines and bytes in the file. To see that data, if you know that `command` will finish quickly, you can jump to the end with `G`, and then `less` will start showing that information.
-
-If you press `G` and the command writing to the pipe takes longer than expected, you can press `Ctrl+C`, and the command will be killed. Pressing `Ctrl+C` will kill it even if you didn't press `G`, so be careful not to press `Ctrl+C` accidentally if you don't intend to kill it. For this reason, if the command does something (that is, it's not only showing information), it's usually safer to write its output to a file and view the file in a separate terminal, instead of using a pipe.
-
-### Why you need less
-
-`less` is a very powerful program, and contrary to newer contenders in this space, such as `most` and `moar`, you are likely to find it on almost all the systems you use, just like `vi`. So, even if you use GUI viewers or editors, it's worth investing some time going through the `less` man page, at least to get a feeling of what's available. This way, when you need to do something that might be covered by existing functionality, you'll know to search the manual page or the internet to find what you need.
-
-For more information, visit the [less home page][2]. The site has a nice FAQ with more tips and tricks.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/5/advanced-use-less-text-file-viewer
-
-作者:[Yedidyah Bar David][a]
-选题:[lujun9972](https://github.com/lujun9972)
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://opensource.com/users/didib
-[1]:http://opensource.com/article/18/4/using-less-view-text-files-command-line
-[2]:http://www.greenwoodsoftware.com/less/
diff --git a/sources/tech/20180612 Systemd Services- Reacting to Change.md b/sources/tech/20180612 Systemd Services- Reacting to Change.md
deleted file mode 100644
index a004f123c8..0000000000
--- a/sources/tech/20180612 Systemd Services- Reacting to Change.md
+++ /dev/null
@@ -1,275 +0,0 @@
-Systemd Services: Reacting to Change
-======
-
-
-
-[I have one of these Compute Sticks][1] (Figure 1) and use it as an all-purpose server. It is inconspicuous and silent and, as it is built around an x86 architecture, I don't have problems getting it to work with drivers for my printer, and that’s what it does most days: it interfaces with the shared printer and scanner in my living room.
-
-![ComputeStick][3]
-
-An Intel ComputeStick. Euro coin for size.
-
-[Used with permission][4]
-
-Most of the time it is idle, especially when we are out, so I thought it would be good idea to use it as a surveillance system. The device doesn't come with its own camera, and it wouldn't need to be spying all the time. I also didn't want to have to start the image capturing by hand because this would mean having to log into the Stick using SSH and fire up the process by writing commands in the shell before rushing out the door.
-
-So I thought that the thing to do would be to grab a USB webcam and have the surveillance system fire up automatically just by plugging it in. Bonus points if the surveillance system fired up also after the Stick rebooted, and it found that the camera was connected.
-
-In prior installments, we saw that [systemd services can be started or stopped by hand][5] or [when certain conditions are met][6]. Those conditions are not limited to when the OS reaches a certain state in the boot up or powerdown sequence but can also be when you plug in new hardware or when things change in the filesystem. You do that by combining a Udev rule with a systemd service.
-
-### Hotplugging with Udev
-
-Udev rules live in the _/etc/udev/rules_ directory and are usually a single line containing _conditions_ and _assignments_ that lead to an _action_.
-
-That was a bit cryptic. Let's try again:
-
-Typically, in a Udev rule, you tell systemd what to look for when a device is connected. For example, you may want to check if the make and model of a device you just plugged in correspond to the make and model of the device you are telling Udev to wait for. Those are the _conditions_ mentioned earlier.
-
-Then you may want to change some stuff so you can use the device easily later. An example of that would be to change the read and write permissions to a device: if you plug in a USB printer, you're going to want users to be able to read information from the printer (the user's printing app would want to know the model, make, and whether it is ready to receive print jobs or not) and write to it, that is, send stuff to print. Changing the read and write permissions for a device is done using one of the _assignments_ you read about earlier.
-
-Finally, you will probably want the system to do something when the conditions mentioned above are met, like start a backup application to copy important files when a certain external hard disk drive is plugged in. That is an example of an _action_ mentioned above.
-
-With that in mind, ponder this:
-
-```
-ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="e207",
-SYMLINK+="mywebcam", TAG+="systemd", MODE="0666", ENV{SYSTEMD_WANTS}="webcam.service"
-```
-
-The first part of the rule,
-
-```
-ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0",
-ATTRS{idProduct}=="e207" [etc... ]
-```
-
-shows the conditions that the device has to meet before doing any of the other stuff you want the system to do. The device has to be added (`ACTION=="add"`) to the machine, it has to be integrated into the `video4linux` subsystem. To make sure the rule is applied only when the correct device is plugged in, you have to make sure Udev correctly identifies the manufacturer (`ATTRS{idVendor}=="03f0"`) and a model (`ATTRS{idProduct}=="e207"`) of the device.
-
-In this case, we're talking about this device (Figure 2):
-
-![webcam][8]
-
-The HP webcam used in this experiment.
-
-[Used with permission][4]
-
-Notice how you use `==` to indicate that these are a logical operation. You would read the above snippet of the rule like this:
-
-```
-if the device is added and the device controlled by the video4linux subsystem
-and the manufacturer of the device is 03f0 and the model is e207, then...
-```
-
-But where do you get all this information? Where do you find the action that triggers the event, the manufacturer, model, and so on? You will probably have to use several sources. The `IdVendor` and `idProduct` you can get by plugging the webcam into your machine and running `lsusb`:
-
-```
-lsusb
-Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
-Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
-Bus 003 Device 003: ID 03f0:e207 Hewlett-Packard
-Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-Bus 001 Device 003: ID 04f2:b1bb Chicony Electronics Co., Ltd
-Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
-Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-```
-
-The webcam I’m using is made by HP, and you can only see one HP device in the list above. The `ID` gives you the manufacturer and the model numbers separated by a colon (`:`). If you have more than one device by the same manufacturer and not sure which is which, unplug the webcam, run `lsusb` again and check what's missing.
-
-OR...
-
-Unplug the webcam, wait a few seconds, run the command `udevadmin monitor --environment` and then plug the webcam back in again. When you do that with the HP webcam, you get:
-
-```
-udevadmin monitor --environment
-UDEV [35776.495221] add /devices/pci0000:00/0000:00:1c.3/0000:04:00.0
- /usb3/3-1/3-1:1.0/input/input21/event11 (input)
-.MM_USBIFNUM=00
-ACTION=add
-BACKSPACE=guess
-DEVLINKS=/dev/input/by-path/pci-0000:04:00.0-usb-0:1:1.0-event
- /dev/input/by-id/usb-Hewlett_Packard_HP_Webcam_HD_2300-event-if00
-DEVNAME=/dev/input/event11
-DEVPATH=/devices/pci0000:00/0000:00:1c.3/0000:04:00.0/
- usb3/3-1/3-1:1.0/input/input21/event11
-ID_BUS=usb
-ID_INPUT=1
-ID_INPUT_KEY=1
-ID_MODEL=HP_Webcam_HD_2300
-ID_MODEL_ENC=HP\x20Webcam\x20HD\x202300
-ID_MODEL_ID=e207
-ID_PATH=pci-0000:04:00.0-usb-0:1:1.0
-ID_PATH_TAG=pci-0000_04_00_0-usb-0_1_1_0
-ID_REVISION=1020
-ID_SERIAL=Hewlett_Packard_HP_Webcam_HD_2300
-ID_TYPE=video
-ID_USB_DRIVER=uvcvideo
-ID_USB_INTERFACES=:0e0100:0e0200:010100:010200:030000:
-ID_USB_INTERFACE_NUM=00
-ID_VENDOR=Hewlett_Packard
-ID_VENDOR_ENC=Hewlett\x20Packard
-ID_VENDOR_ID=03f0
-LIBINPUT_DEVICE_GROUP=3/3f0/e207:usb-0000:04:00.0-1/button
-MAJOR=13
-MINOR=75
-SEQNUM=3162
-SUBSYSTEM=input
-USEC_INITIALIZED=35776495065
-XKBLAYOUT=es
-XKBMODEL=pc105
-XKBOPTIONS=
-XKBVARIANT=
-```
-
-That may look like a lot to process, but, check this out: the `ACTION` field early in the list tells you what event just happened, i.e., that a device got added to the system. You can also see the name of the device spelled out on several of the lines, so you can be pretty sure that it is the device you are looking for. The output also shows the manufacturer's ID number (`ID_VENDOR_ID=03f0`) and the model number (`ID_VENDOR_ID=03f0`).
-
-This gives you three of the four values the condition part of the rule needs. You may be tempted to think that it a gives you the fourth, too, because there is also a line that says:
-
-```
-SUBSYSTEM=input
-```
-
-Be careful! Although it is true that a USB webcam is a device that provides input (as does a keyboard and a mouse), it is also belongs to the _usb_ subsystem, and several others. This means that your webcam gets added to several subsystems and looks like several devices. If you pick the wrong subsystem, your rule may not work as you want it to, or, indeed, at all.
-
-So, the third thing you have to check is all the subsystems the webcam has got added to and pick the correct one. To do that, unplug your webcam again and run:
-
-```
-ls /dev/video*
-```
-
-This will show you all the video devices connected to the machine. If you are using a laptop, most come with a built-in webcam and it will probably show up as `/dev/video0`. Plug your webcam back in and run `ls /dev/video*` again.
-
-Now you should see one more video device (probably `/dev/video1`).
-
-Now you can find out all the subsystems it belongs to by running `udevadm info -a /dev/video1`:
-
-```
-udevadm info -a /dev/video1
-
-Udevadm info starts with the device specified by the devpath and then
-walks up the chain of parent devices. It prints for every device
-found, all possible attributes in the udev rules key format.
-A rule to match, can be composed by the attributes of the device
-and the attributes from one single parent device.
-
- looking at device '/devices/pci0000:00/0000:00:1c.3/0000:04:00.0
- /usb3/3-1/3-1:1.0/video4linux/video1':
- KERNEL=="video1"
- SUBSYSTEM=="video4linux"
- DRIVER==""
- ATTR{dev_debug}=="0"
- ATTR{index}=="0"
- ATTR{name}=="HP Webcam HD 2300: HP Webcam HD"
-
-[etc...]
-```
-
-The output goes on for quite a while, but what you're interested is right at the beginning: `SUBSYSTEM=="video4linux"`. This is a line you can literally copy and paste right into your rule. The rest of the output (not shown for brevity) gives you a couple more nuggets, like the manufacturer and mode IDs, again in a format you can copy and paste into your rule.
-
-Now you have a way of identifying the device and what event should trigger the action univocally, it is time to tinker with the device.
-
-The next section in the rule, `SYMLINK+="mywebcam", TAG+="systemd", MODE="0666"` tells Udev to do three things: First, you want to create symbolic link from the device to (e.g. _/dev/video1_ ) to _/dev/mywebcam_. This is because you cannot predict what the system is going to call the device by default. When you have an in-built webcam and you hotplug a new one, the in-built webcam will usually be _/dev/video0_ while the external one will become _/dev/video1_. However, if you boot your computer with the external USB webcam plugged in, that could be reversed and the internal webcam can become _/dev/video1_ and the external one _/dev/video0_. What this is telling you is that, although your image-capturing script (which you will see later on) always needs to point to the external webcam device, you can't rely on it being _/dev/video0_ or _/dev/video1_. To solve this problem, you tell Udev to create a symbolic link which will never change in the moment the device is added to the _video4linux_ subsystem and you will make your script point to that.
-
-The second thing you do is add `"systemd"` to the list of Udev tags associated with this rule. This tells Udev that the action that the rule will trigger will be managed by systemd, that is, it will be some sort of systemd service.
-
-Notice how in both cases you use `+=` operator. This adds the value to a list, which means you can add more than one value to `SYMLINK` and `TAG`.
-
-The `MODE` values, on the other hand, can only contain one value (hence you use the simple `=` assignment operator). What `MODE` does is tell Udev who can read from or write to the device. If you are familiar with `chmod` (and, if you are reading this, you should be), you will also be familiar of [how you can express permissions using numbers][9]. That is what this is: `0666` means " _give read and write privileges to the device to everybody_ ".
-
-At last, `ENV{SYSTEMD_WANTS}="webcam.service"` tells Udev what systemd service to run.
-
-Save this rule into file called _90-webcam.rules_ (or something like that) in _/etc/udev/rules.d_ and you can load it either by rebooting your machine, or by running:
-
-```
-sudo udevadm control --reload-rules && udevadm trigger
-```
-
-## Service at Last
-
-The service the Udev rule triggers is ridiculously simple:
-
-```
-# webcam.service
-
-[Service]
-Type=simple
-ExecStart=/home/[user name]/bin/checkimage.sh
-```
-
-Basically, it just runs the _checkimage.sh_ script stored in your personal _bin/_ and pushes it the background. [This is something you saw how to do in prior installments][5]. It may seem something little, but just because it is called by a Udev rule, you have just created a special kind of systemd unit called a _device_ unit. Congratulations.
-
-As for the _checkimage.sh_ script _webcam.service_ calls, there are several ways of grabbing an image from a webcam and comparing it to a prior one to check for changes (which is what _checkimage.sh_ does), but this is how I did it:
-
-```
-#!/bin/bash
-# This is the checkimage.sh script
-
-mplayer -vo png -frames 1 tv:// -tv driver=v4l2:width=640:height=480:device=
- /dev/mywebcam &>/dev/null
-mv 00000001.png /home/[user name]/monitor/monitor.png
-
-while true
-do
- mplayer -vo png -frames 1 tv:// -tv driver=v4l2:width=640:height=480:device=/dev/mywebcam &>/dev/null
- mv 00000001.png /home/[user name]/monitor/temp.png
-
- imagediff=`compare -metric mae /home/[user name]/monitor/monitor.png /home/[user name]
- /monitor/temp.png /home/[user name]/monitor/diff.png 2>&1 > /dev/null | cut -f 1 -d " "`
- if [ `echo "$imagediff > 700.0" | bc` -eq 1 ]
- then
- mv /home/[user name]/monitor/temp.png /home/[user name]/monitor/monitor.png
- fi
-
- sleep 0.5
-done
-```
-
-Start by using [MPlayer][10] to grab a frame ( _00000001.png_ ) from the webcam. Notice how we point `mplayer` to the `mywebcam` symbolic link we created in our Udev rule, instead of to `video0` or `video1`. Then you transfer the image to the _monitor/_ directory in your home directory. Then run an infinite loop that does the same thing again and again, but also uses [Image Magick's _compare_ tool][11] to see if there any differences between the last image captured and the one that is already in the _monitor/_ directory.
-
-If the images are different, it means something has moved within the webcam's frame. The script overwrites the original image with the new image and continues comparing waiting for some more movement.
-
-### Plugged
-
-With all the bits and pieces in place, when you plug your webcam in, your Udev rule will be triggered and will start the _webcam.service_. The _webcam.service_ will execute _checkimage.sh_ in the background, and _checkimage.sh_ will start taking pictures every half a second. You will know because your webcam's LED will start flashing indicating every time it takes a snap.
-
-As always, if something goes wrong, run
-
-```
-systemctl status webcam.service
-```
-
-to check what your service and script are up to.
-
-### Coming up
-
-You may be wondering: Why overwrite the original image? Surely you would want to see what's going on if the system detects any movement, right? You would be right, but as you will see in the next installment, leaving things as they are and processing the images using yet another type of systemd unit makes things nice, clean and easy.
-
-Just wait and see.
-
-Learn more about Linux through the free ["Introduction to Linux" ][12]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/intro-to-linux/2018/6/systemd-services-reacting-change
-
-作者:[Paul Brown][a]
-选题:[lujun9972][b]
-译者:[译者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/bro66
-[b]: https://github.com/lujun9972
-[1]: https://www.intel.com/content/www/us/en/products/boards-kits/compute-stick/stk1a32sc.html
-[2]: https://www.linux.com/files/images/fig01png
-[3]: https://www.linux.com/sites/lcom/files/styles/floated_images/public/fig01.png?itok=cfEHN5f1 (ComputeStick)
-[4]: https://www.linux.com/licenses/category/used-permission
-[5]: https://www.linux.com/blog/learn/intro-to-linux/2018/5/writing-systemd-services-fun-and-profit
-[6]: https://www.linux.com/blog/learn/2018/5/systemd-services-beyond-starting-and-stopping
-[7]: https://www.linux.com/files/images/fig02png
-[8]: https://www.linux.com/sites/lcom/files/styles/floated_images/public/fig02.png?itok=esFv4BdM (webcam)
-[9]: https://chmod-calculator.com/
-[10]: https://mplayerhq.hu/design7/news.html
-[11]: https://www.imagemagick.org/script/compare.php
-[12]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180710 Building a Messenger App- Messages.md b/sources/tech/20180710 Building a Messenger App- Messages.md
deleted file mode 100644
index 55e596df64..0000000000
--- a/sources/tech/20180710 Building a Messenger App- Messages.md
+++ /dev/null
@@ -1,315 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Building a Messenger App: Messages)
-[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-messages/)
-[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
-
-Building a Messenger App: Messages
-======
-
-This post is the 4th on a series:
-
- * [Part 1: Schema][1]
- * [Part 2: OAuth][2]
- * [Part 3: Conversations][3]
-
-
-
-In this post we’ll code the endpoints to create a message and list them, also an endpoint to update the last time the participant read messages. Start by adding these routes in the `main()` function.
-
-```
-router.HandleFunc("POST", "/api/conversations/:conversationID/messages", requireJSON(guard(createMessage)))
-router.HandleFunc("GET", "/api/conversations/:conversationID/messages", guard(getMessages))
-router.HandleFunc("POST", "/api/conversations/:conversationID/read_messages", guard(readMessages))
-```
-
-Messages goes into conversations so the endpoint includes the conversation ID.
-
-### Create Message
-
-This endpoint handles POST requests to `/api/conversations/{conversationID}/messages` with a JSON body with just the message content and return the newly created message. It has two side affects: it updates the conversation `last_message_id` and updates the participant `messages_read_at`.
-
-```
-func createMessage(w http.ResponseWriter, r *http.Request) {
- var input struct {
- Content string `json:"content"`
- }
- defer r.Body.Close()
- if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
- http.Error(w, err.Error(), http.StatusBadRequest)
- return
- }
-
- errs := make(map[string]string)
- input.Content = removeSpaces(input.Content)
- if input.Content == "" {
- errs["content"] = "Message content required"
- } else if len([]rune(input.Content)) > 480 {
- errs["content"] = "Message too long. 480 max"
- }
- if len(errs) != 0 {
- respond(w, Errors{errs}, http.StatusUnprocessableEntity)
- return
- }
-
- ctx := r.Context()
- authUserID := ctx.Value(keyAuthUserID).(string)
- conversationID := way.Param(ctx, "conversationID")
-
- tx, err := db.BeginTx(ctx, nil)
- if err != nil {
- respondError(w, fmt.Errorf("could not begin tx: %v", err))
- return
- }
- defer tx.Rollback()
-
- isParticipant, err := queryParticipantExistance(ctx, tx, authUserID, conversationID)
- if err != nil {
- respondError(w, fmt.Errorf("could not query participant existance: %v", err))
- return
- }
-
- if !isParticipant {
- http.Error(w, "Conversation not found", http.StatusNotFound)
- return
- }
-
- var message Message
- if err := tx.QueryRowContext(ctx, `
- INSERT INTO messages (content, user_id, conversation_id) VALUES
- ($1, $2, $3)
- RETURNING id, created_at
- `, input.Content, authUserID, conversationID).Scan(
- &message.ID,
- &message.CreatedAt,
- ); err != nil {
- respondError(w, fmt.Errorf("could not insert message: %v", err))
- return
- }
-
- if _, err := tx.ExecContext(ctx, `
- UPDATE conversations SET last_message_id = $1
- WHERE id = $2
- `, message.ID, conversationID); err != nil {
- respondError(w, fmt.Errorf("could not update conversation last message ID: %v", err))
- return
- }
-
- if err = tx.Commit(); err != nil {
- respondError(w, fmt.Errorf("could not commit tx to create a message: %v", err))
- return
- }
-
- go func() {
- if err = updateMessagesReadAt(nil, authUserID, conversationID); err != nil {
- log.Printf("could not update messages read at: %v\n", err)
- }
- }()
-
- message.Content = input.Content
- message.UserID = authUserID
- message.ConversationID = conversationID
- // TODO: notify about new message.
- message.Mine = true
-
- respond(w, message, http.StatusCreated)
-}
-```
-
-First, it decodes the request body into an struct with the message content. Then, it validates the content is not empty and has less than 480 characters.
-
-```
-var rxSpaces = regexp.MustCompile("\\s+")
-
-func removeSpaces(s string) string {
- if s == "" {
- return s
- }
-
- lines := make([]string, 0)
- for _, line := range strings.Split(s, "\n") {
- line = rxSpaces.ReplaceAllLiteralString(line, " ")
- line = strings.TrimSpace(line)
- if line != "" {
- lines = append(lines, line)
- }
- }
- return strings.Join(lines, "\n")
-}
-```
-
-This is the function to remove spaces. It iterates over each line, remove more than two consecutives spaces and returns with the non empty lines.
-
-After the validation, it starts an SQL transaction. First, it queries for the participant existance in the conversation.
-
-```
-func queryParticipantExistance(ctx context.Context, tx *sql.Tx, userID, conversationID string) (bool, error) {
- if ctx == nil {
- ctx = context.Background()
- }
- var exists bool
- if err := tx.QueryRowContext(ctx, `SELECT EXISTS (
- SELECT 1 FROM participants
- WHERE user_id = $1 AND conversation_id = $2
- )`, userID, conversationID).Scan(&exists); err != nil {
- return false, err
- }
- return exists, nil
-}
-```
-
-I extracted it into a function because it’s reused later.
-
-If the user isn’t participant of the conversation, we return with a `404 Not Found` error.
-
-Then, it inserts the message and updates the conversation `last_message_id`. Since this point, `last_message_id` cannot by `NULL` because we don’t allow removing messages.
-
-Then it commits the transaction and we update the participant `messages_read_at` in a goroutine.
-
-```
-func updateMessagesReadAt(ctx context.Context, userID, conversationID string) error {
- if ctx == nil {
- ctx = context.Background()
- }
-
- if _, err := db.ExecContext(ctx, `
- UPDATE participants SET messages_read_at = now()
- WHERE user_id = $1 AND conversation_id = $2
- `, userID, conversationID); err != nil {
- return err
- }
- return nil
-}
-```
-
-Before responding with the new message, we must notify about it. This is for the realtime part we’ll code in the next post so I left a comment there.
-
-### Get Messages
-
-This endpoint handles GET requests to `/api/conversations/{conversationID}/messages`. It responds with a JSON array with all the messages in the conversation. It also has the same side affect of updating the participant `messages_read_at`.
-
-```
-func getMessages(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- authUserID := ctx.Value(keyAuthUserID).(string)
- conversationID := way.Param(ctx, "conversationID")
-
- tx, err := db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
- if err != nil {
- respondError(w, fmt.Errorf("could not begin tx: %v", err))
- return
- }
- defer tx.Rollback()
-
- isParticipant, err := queryParticipantExistance(ctx, tx, authUserID, conversationID)
- if err != nil {
- respondError(w, fmt.Errorf("could not query participant existance: %v", err))
- return
- }
-
- if !isParticipant {
- http.Error(w, "Conversation not found", http.StatusNotFound)
- return
- }
-
- rows, err := tx.QueryContext(ctx, `
- SELECT
- id,
- content,
- created_at,
- user_id = $1 AS mine
- FROM messages
- WHERE messages.conversation_id = $2
- ORDER BY messages.created_at DESC
- `, authUserID, conversationID)
- if err != nil {
- respondError(w, fmt.Errorf("could not query messages: %v", err))
- return
- }
- defer rows.Close()
-
- messages := make([]Message, 0)
- for rows.Next() {
- var message Message
- if err = rows.Scan(
- &message.ID,
- &message.Content,
- &message.CreatedAt,
- &message.Mine,
- ); err != nil {
- respondError(w, fmt.Errorf("could not scan message: %v", err))
- return
- }
-
- messages = append(messages, message)
- }
-
- if err = rows.Err(); err != nil {
- respondError(w, fmt.Errorf("could not iterate over messages: %v", err))
- return
- }
-
- if err = tx.Commit(); err != nil {
- respondError(w, fmt.Errorf("could not commit tx to get messages: %v", err))
- return
- }
-
- go func() {
- if err = updateMessagesReadAt(nil, authUserID, conversationID); err != nil {
- log.Printf("could not update messages read at: %v\n", err)
- }
- }()
-
- respond(w, messages, http.StatusOK)
-}
-```
-
-First, it begins an SQL transaction in readonly mode. Checks for the participant existance and queries all the messages. In each message, we use the current authenticated user ID to know whether the user owns the message (`mine`). Then it commits the transaction, updates the participant `messages_read_at` in a goroutine and respond with the messages.
-
-### Read Messages
-
-This endpoint handles POST requests to `/api/conversations/{conversationID}/read_messages`. Without any request or response body. In the frontend we’ll make this request each time a new message arrive in the realtime stream.
-
-```
-func readMessages(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- authUserID := ctx.Value(keyAuthUserID).(string)
- conversationID := way.Param(ctx, "conversationID")
-
- if err := updateMessagesReadAt(ctx, authUserID, conversationID); err != nil {
- respondError(w, fmt.Errorf("could not update messages read at: %v", err))
- return
- }
-
- w.WriteHeader(http.StatusNoContent)
-}
-```
-
-It uses the same function we’ve been using to update the participant `messages_read_at`.
-
-* * *
-
-That concludes it. Realtime messages is the only part left in the backend. Wait for it in the next post.
-
-[Souce Code][4]
-
---------------------------------------------------------------------------------
-
-via: https://nicolasparada.netlify.com/posts/go-messenger-messages/
-
-作者:[Nicolás Parada][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://nicolasparada.netlify.com/
-[b]: https://github.com/lujun9972
-[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
-[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
-[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
-[4]: https://github.com/nicolasparada/go-messenger-demo
diff --git a/sources/tech/20180710 Building a Messenger App- Realtime Messages.md b/sources/tech/20180710 Building a Messenger App- Realtime Messages.md
deleted file mode 100644
index 71479495b2..0000000000
--- a/sources/tech/20180710 Building a Messenger App- Realtime Messages.md
+++ /dev/null
@@ -1,175 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Building a Messenger App: Realtime Messages)
-[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/)
-[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
-
-Building a Messenger App: Realtime Messages
-======
-
-This post is the 5th on a series:
-
- * [Part 1: Schema][1]
- * [Part 2: OAuth][2]
- * [Part 3: Conversations][3]
- * [Part 4: Messages][4]
-
-
-
-For realtime messages we’ll use [Server-Sent Events][5]. This is an open connection in which we can stream data. We’ll have and endpoint in which the user subscribes to all the messages sended to him.
-
-### Message Clients
-
-Before the HTTP part, let’s code a map to have all the clients listening for messages. Initialize this globally like so:
-
-```
-type MessageClient struct {
- Messages chan Message
- UserID string
-}
-
-var messageClients sync.Map
-```
-
-### New Message Created
-
-Remember in the [last post][4] when we created the message, we left a “TODO” comment. There we’ll dispatch a goroutine with this function.
-
-```
-go messageCreated(message)
-```
-
-Insert that line just where we left the comment.
-
-```
-func messageCreated(message Message) error {
- if err := db.QueryRow(`
- SELECT user_id FROM participants
- WHERE user_id != $1 and conversation_id = $2
- `, message.UserID, message.ConversationID).
- Scan(&message.ReceiverID); err != nil {
- return err
- }
-
- go broadcastMessage(message)
-
- return nil
-}
-
-func broadcastMessage(message Message) {
- messageClients.Range(func(key, _ interface{}) bool {
- client := key.(*MessageClient)
- if client.UserID == message.ReceiverID {
- client.Messages <- message
- }
- return true
- })
-}
-```
-
-The function queries for the recipient ID (the other participant ID) and sends the message to all the clients.
-
-### Subscribe to Messages
-
-Lets go to the `main()` function and add this route:
-
-```
-router.HandleFunc("GET", "/api/messages", guard(subscribeToMessages))
-```
-
-This endpoint handles GET requests on `/api/messages`. The request should be an [EventSource][6] connection. It responds with an event stream in which the data is JSON formatted.
-
-```
-func subscribeToMessages(w http.ResponseWriter, r *http.Request) {
- if a := r.Header.Get("Accept"); !strings.Contains(a, "text/event-stream") {
- http.Error(w, "This endpoint requires an EventSource connection", http.StatusNotAcceptable)
- return
- }
-
- f, ok := w.(http.Flusher)
- if !ok {
- respondError(w, errors.New("streaming unsupported"))
- return
- }
-
- ctx := r.Context()
- authUserID := ctx.Value(keyAuthUserID).(string)
-
- h := w.Header()
- h.Set("Cache-Control", "no-cache")
- h.Set("Connection", "keep-alive")
- h.Set("Content-Type", "text/event-stream")
-
- messages := make(chan Message)
- defer close(messages)
-
- client := &MessageClient{Messages: messages, UserID: authUserID}
- messageClients.Store(client, nil)
- defer messageClients.Delete(client)
-
- for {
- select {
- case <-ctx.Done():
- return
- case message := <-messages:
- if b, err := json.Marshal(message); err != nil {
- log.Printf("could not marshall message: %v\n", err)
- fmt.Fprintf(w, "event: error\ndata: %v\n\n", err)
- } else {
- fmt.Fprintf(w, "data: %s\n\n", b)
- }
- f.Flush()
- }
- }
-}
-```
-
-First it checks for the correct request headers and checks the server supports streaming. We create a channel of messages to make a client and store it in the clients map. Each time a new message is created, it will go in this channel, so we can read from it with a `for-select` loop.
-
-Server-Sent Events uses this format to send data:
-
-```
-data: some data here\n\n
-```
-
-We are sending it in JSON format:
-
-```
-data: {"foo":"bar"}\n\n
-```
-
-We are using `fmt.Fprintf()` to write to the response writter in this format and flushing the data in each iteration of the loop.
-
-This will loop until the connection is closed using the request context. We defered the close of the channel and the delete of the client, so when the loop ends, the channel will be closed and the client won’t receive more messages.
-
-Note aside, the JavaScript API to work with Server-Sent Events (EventSource) doesn’t support setting custom headers 😒 So we cannot set `Authorization: Bearer `. And that’s the reason why the `guard()` middleware reads the token from the URL query string also.
-
-* * *
-
-That concludes the realtime messages. I’d like to say that’s everything in the backend, but to code the frontend I’ll add one more endpoint to login. A login that will be just for development.
-
-[Souce Code][7]
-
---------------------------------------------------------------------------------
-
-via: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
-
-作者:[Nicolás Parada][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://nicolasparada.netlify.com/
-[b]: https://github.com/lujun9972
-[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
-[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
-[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
-[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
-[5]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
-[6]: https://developer.mozilla.org/en-US/docs/Web/API/EventSource
-[7]: https://github.com/nicolasparada/go-messenger-demo
diff --git a/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md b/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md
deleted file mode 100644
index d305b716d6..0000000000
--- a/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md
+++ /dev/null
@@ -1,499 +0,0 @@
-50 Best Ubuntu Apps You Should Be Using Right Now
-======
-**Brief: A comprehensive list of best Ubuntu apps for all kind of users. These software will help you in getting a better experience with your Linux desktop.**
-
-I have written about [things to do after installing Ubuntu][1] several times in the past. Each time I suggest installing the essential applications in Ubuntu.
-
-But the question arises, what are the essential Ubuntu applications? There is no set answer here. It depends on your need and the kind of work you do on your Ubuntu desktop.
-
-Still, I have been asked to suggest some good Ubuntu apps by a number of readers. This is the reason I have created this comprehensive list of Ubuntu applications you can use regularly.
-
-The list has been divided into respective categories for ease of reading and ease of comprehension.
-
-### Best Ubuntu apps for a better Ubuntu experience
-
-![Best Ubuntu Apps][2]
-
-Of course, you don’t have to use all of these applications. Just go through this list of essential Ubuntu software, read the description and then install the ones you need or are inclined to use. Just keep this page bookmarked for future reference or simply search on Google with term ‘best ubuntu apps itsfoss’.
-
-The best Ubuntu application list is intended for average Ubuntu user. Therefore not all the applications here are open source. I have also marked the slightly complicated applications that might not be suitable for a beginner. The list should be valid for Ubuntu 16.04,18.04 and other versions.
-
-Unless exclusively mentioned, the software listed here are available in Ubuntu Software Center.
-
-If you don’t find any application in the software center or if it is missing installation instruction, let me know and I’ll add the installation procedure.
-
-Enough talk! Let’s see what are the best apps for Ubuntu.
-
-#### Web Browser
-
-Ubuntu comes with Firefox as the default web browser. Since the Quantum release, Firefox has improved drastically. Personally, I always use more than one web browser for the sake of distinguishing between different type of works.
-
-##### Google Chrome
-
-![Google Chrome Logo][3]
-
-Google Chrome is the most used web browser on the internet for a reason. With your Google account, it allows you seamless syncing across devices. Plenty of extensions and apps further enhance its capabilities. You can [download Chrome in Ubuntu from its website][4].
-
-##### Brave
-
-![brave browser][5]
-
-Google Chrome might be the most used web browser but it’s a privacy invader. An [alternative browser][6] is [Brave][7] that blocks ads and tracking scripts by default. This provides you with a faster and secure web browsing experience.
-
-#### Music applications
-
-![best music apps ubuntu][8]
-
-Ubuntu has Rhythmbox as the default music player which is not at all a bad choice for the default music player. However, you can definitely install a better music player.
-
-##### Sayonara
-
-[Sayonara][9] is a small, lightweight music player with a nice dark user interface. It comes with all the essential features you would expect in a standard music player. It integrates well with the Ubuntu desktop environment and doesn’t eat up your RAM.
-
-##### Audacity
-
-[Audacity][10] is more of an audio editor than an audio player. You can record and edit audio with this free and open source tool. It is available for Linux, Windows and macOS. You can install it from the Software Center.
-
-##### MusicBrainz Picard
-
-[Picard][11] is not a music player, it is a music tagger. If you have tons of local music files, Picard allows you to automatically update the music files with correct tracks, album, artist info and album cover art.
-
-#### Streaming Music Applications
-
-![Streaming Music app Ubuntu][12]
-
-In this age of the internet, music listening habit has surely changed. People these days rely more on streaming music players rather than storing hundreds of local music files. Let’s see some apps you can use for streaming music.
-
-##### Spotify
-
-[Spotify][13] is the king of streaming music. And the good thing is that it has a native Linux app. The [Spotify app on Ubuntu][14] integrates well with the media key and sound menu along with the desktop notification. Do note that Spotify may or may not be available in your country.
-
-##### Nuvola music player
-
-[Nuvola][15] is not a streaming music service like Spotify. It is a desktop music player that allows you to use several streaming music services in one application. You can use Spotify, Deezer, Google Play Music, Amazon Cloud Player and many more such services.
-
-#### Video Players
-
-![Video players for Linux][16]
-
-Ubuntu has the default GNOME video player (previously known as Totem) which is okay but it doesn’t support various media codecs. There are certainly other video players better than the GNOME video player.
-
-##### VLC
-
-The free and open source software [VLC][17] is the king of video players. It supports almost all possible media codecs. It also allows you to increase the volume up to 200%. It can also resume playing from the last known position. There are so many [VLC tricks][18] you can use to get the most of it.
-
-##### MPV
-
-[MPV][19] is a video player that deserves more attention. A sleek minimalist GUI and plenty of features, MPV has everything you would expect from a good video player. You can even use it in the command line. If you are not happy with VLC, you should surely give MPV a try.
-
-#### Cloud Storage Service
-
-Local backups are fine but cloud storage gives an additional degree of freedom. You don’t have to carry a USB key with you all the time or worry about a hard disk crash with cloud services.
-
-##### Dropbox
-
-![Dropbox logo][20]
-
-[Dropbox][21] is one of the most popular Cloud service providers. You get 2GB of free storage with the option to get more by referring others. Dropbox provides a native Linux client and you can download it from its website. It creates a local folder on your system that is synced with the cloud servers.
-
-##### pCloud
-
-![pCloud icon][22]
-
-[pCloud][23] is another good cloud storage service for Linux. It also has a native Linux client that you can download from its website. You get up to 20GB of free storage and if you need more, the pricing is better than Dropbox. pCloud is based in Switzerland, a country renowned for strict data privacy laws.
-
-#### Image Editors
-
-I am sure that you would need a photo editor at some point in time. Here are some of the best Ubuntu apps for editing images.
-
-##### GIMP
-
-![gimp icon][24]
-
-[GIMP][25] is a free and open source image editor available for Linux, Windows and macOS. It’s the best alternative for Adobe Photoshop in Linux. You can use it for all kind of image editing. There are plenty of resources available on the internet to help you with Gimp.
-
-##### Inkscape
-
-![inkscape icon][26]
-
-[Inkscape][27] is also a free and open source image editor specifically focusing on vector graphics. You can design vector arts and logo on it. You can compare it to Adobe Illustrator. Like Gimp, Inkscape too has plenty of tutorials available online.
-
-#### Paint applications
-
-Painting applications are not the same as image editors though their functionalities overlap at times. Here are some paint apps you can use in Ubuntu.
-![Painting apps for Ubuntu Linux][28]
-
-##### Krita
-
-[Krita][29] is a free and open source digital painting application. You can create digital art, comics and animation with it. It’s a professional grade software and is even used as the primary software in art schools.
-
-##### Pinta
-
-[Pinta][30] might not be as feature rich as Krita but that’s deliberate. You can think of Pinta as Microsoft Paint for Linux. You can draw, paint, add text and do other such small tasks you do in a paint application.
-
-#### Photography applications
-
-Amateur photographer or a professional? You have plenty of [photography tools][31] at your disposal. Here are some recommended applications.
-
-##### digiKam
-
-![digikam][32]
-
-With open source software [digiKam][33], you can handle your high-end camera images in a professional manner. digiKam provides all the tools required for viewing, managing, editing, enhancing, organizing, tagging and sharing photographs.
-
-##### Darktable
-
-![Darktable icon][34]
-
-[darktable][35] is an open source photography workflow application with a special focus on raw image development. This is the best alternative you can get for Adobe Lightroom. It is also available for Windows and macOS.
-
-#### Video editors
-
-![Video editors Ubuntu][36]
-
-There is no dearth of [video editors for Linux][37] but I won’t go in detail here. Take a look at some of the feature-rich yet relatively simple to use video editors for Ubuntu.
-
-##### Kdenlive
-
-[Kdenlive][38] is the best all-purpose video editor for Linux. It has enough features that compare it to iMovie or Movie Maker.
-
-##### Shotcut
-
-[Shotcut][39] is another good choice for a video editor. It is an open source software with all the features you can expect in a standard video editor.
-
-#### Image and video converter
-
-If you need to [convert the file format][40] of your images and videos, here are some of my recommendations.
-
-##### Xnconvert
-
-![xnconvert logo][41]
-
-[Xnconvert][42] is an excellent batch image conversion tool. You can bulk resize images, convert the file type and rename them.
-
-##### Handbrake
-
-![Handbrake Logo][43]
-
-[HandBrake][44] is an easy to use open source tool for converting videos from a number of formats to a few modern, popular formats.
-
-#### Screenshot and screen recording tools
-
-![Screenshot and recorders Ubuntu][45]
-
-Here are the best Ubuntu apps for taking screenshots and recording your screen.
-
-##### Shutter
-
-[Shutter][46] is my go-to tool for taking screenshots. You can also do some quick editing to those screenshots such as adding arrows, text or resizing the images. The screenshots you see on It’s FOSS have been edited with Shutter. Definitely one of the best apps for Ubuntu.
-
-##### Kazam
-
-[Kazam][47] is my favorite [screen recorder for Linux][48]. It’s a tiny tool that allows you to record the entire window, an application window or a selected area. You can also use shortcuts to pause or resume recording. The tutorials on [It’s FOSS YouTube channel][49] have been recorded with Kazam.
-
-#### Office suites
-
-I cannot imagine that you could use a computer without a document editor. And why restrict yourself to just one document editor? Go for a complete office suite.
-
-##### LibreOffice
-
-![LibreOffice logo][50]
-
-[LibreOffice][51] comes preinstalled on Ubuntu and it is undoubtedly the [best open source office software][52]. It’s a complete package comprising of a document editor, spreadsheet tool, presentation software, maths tool and a graphics tool. You can even edit some PDF files with LibreOffice.
-
-##### WPS Office
-
-![WPS Office logo][53]
-
-[WPS Office][54] has gained popularity for being a Microsoft Office clone. It has an interface identical to Microsoft Office and it claims to be more compatible with MS Office. If you are looking for something similar to the Microsoft Office, WPS Office is a good choice.
-
-#### Downloading tools
-
-![Downloading software Ubuntu][55]
-
-If you often download videos or other big files from the internet, these tools will help you.
-
-##### youtube-dl
-
-This is one of the rare Ubuntu application on the list that is command line based. If you want to download videos from YouTube, DailyMotion or other video websites, youtube-dl is an excellent choice. It provides plenty of [advanced option for video downloading][56].
-
-##### uGet
-
-[uGet][57] is a feature rich [download manager for Linux][58]. It allows you to pause and resume your downloads, schedule your downloads, monitor clipboard for downloadable content. A perfect tool if you have a slow, inconsistent internet or daily data limit.
-
-#### Code Editors
-
-![Coding apps for Ubuntu][59]
-
-If you are into programming, the default Gedit text editor might not be sufficient for your coding needs. Here are some of the better code editors for you.
-
-##### Atom
-
-[Atom][60] is a free and [open source code editor][61] from GitHub. Even before it was launched its first stable version, it became a hot favorite among coders for its UI, features and vast range of plugins.
-
-##### Visual Studio Code
-
-[VS Code][62] is an open source code editor from Microsoft. Don’t worry about Microsoft, VS Code is an awesome editor for web development. It also supports a number of other programming languages.
-
-#### PDF and eBooks related applications
-
-![eBook Management tools in Ubuntu][63]
-
-In this digital age, you cannot only rely on the real paper books especially when there are plenty of free eBooks available. Here are some Ubuntu apps for managing PDFs and eBooks.
-
-##### Calibre
-
-If you are a bibliophile and collect eBooks, you should use [Calibre][64]. It is an eBook manager with all the necessary software for [creating eBooks][65], converting eBook formats and managing an eBook library.
-
-##### Okular
-
-Okular is mostly a PDF viewer with options for editing PDF files. You can do some basic [PDF editing on Linux][66] with Okular such as adding pop-ups notes, inline notes, freehand line drawing, highlighter, stamp etc.
-
-#### Messaging applications
-
-![Messaging apps for Ubuntu][67]
-
-I believe you use at least one [messaging app on Linux][68]. Here are my recommendations.
-
-##### Skype
-
-[Skype][69] is the most popular video chatting application. It is also used by many companies and businesses for interviews and meetings. This makes Skype one of the must-have applications for Ubuntu.
-
-##### Rambox
-
-[Rambox][70] is not a messaging application on its own. But it allows you to use Skype, Viber, Facebook Messanger, WhatsApp, Slack and a number of other messaging applications from a single application window.
-
-#### Notes and To-do List applications
-
-Need a to-do list app or simple an app for taking notes? Have a look at these:
-
-##### Simplenote
-
-![Simplenote logo][71]
-
-[Simplenote][72] is a free and open source note taking application from WordPress creators [Automattic][73]. It is available for Windows, Linux, macOS, iOS and Android. Your notes are synced to a cloud server and you can access them on any device. You can download the DEB file from its website.
-
-##### Remember The Milk
-
-![Remember The Milk logo][74]
-
-[Remember The Milk][75] is a popular to-do list application. It is available for Windows, Linux, macOS, iOS and Android. Your to-do list is accessible on all the devices you own. You can also access it from a web browser. It also has an official native application for Linux that you can download from its website.
-
-#### Password protection and encryption
-
-![Encryption software Ubuntu][76]
-
-If there are other people regularly using your computer perhaps you would like to add an extra layer of security by password protecting files and folders.
-
-##### EncryptPad
-
-[EncryptPad][77] is an open source text editor that allows you to lock your files with a password. You can choose the type of encryption. There is also a command line version of this tool.
-
-##### Gnome Encfs Manager
-
-Gnome Encfs Manager allows you to [lock folders with a password in Linux][78]. You can keep whatever files you want in a secret folder and then lock it with a password.
-
-#### Gaming
-
-![Gaming on Ubuntu][79]
-
-[Gaming on Linux][80] is a lot better than what it used to be a few years ago. You can enjoy plenty of games on Linux without going back to Windows.
-
-##### Steam
-
-[Steam][81] is a digital distribution platform that allows you to purchase (if required) games. Steam has over 1500 [games for Linux][82]. You can download the Steam client from the Software Center.
-
-##### PlayOnLinux
-
-[PlayOnLinux][83] allows you to run Windows games on Linux over WINE compatibility layer. Don’t expect too much out of it because not every game will run flawlessly with PlayOnLinux.
-
-#### Package Managers [Intermediate to advanced users]
-
-![Package Management tools Ubuntu][84]
-
-Ubuntu Software Center is more than enough for an average Ubuntu user’s software needs but you can have more control on it using these applications.
-
-##### Gdebi
-
-Gedbi is a tiny packagae manager that you can use for installing DEB files. It is faster than the Software Center and it also handles dependency issues.
-
-##### Synaptic
-
-Synaptic was the default GUI package manager for most Linux distributions a decade ago. It still is in some Linux distributions. This powerful package manager is particularly helpful in [finding installed applications and removing them][85].
-
-#### Backup and Recovery tools
-
-![Backup and data recovery tools for Ubuntu][86]
-
-Backup and recovery tools are must-have software for any system. Let’s see what softwares you must have on Ubuntu.
-
-##### Timeshift
-
-Timeshift is a tool that allows you to [take a snapshot of your system][87]. This allows you to restore your system to a previous state in case of an unfortunate incident when your system configuration is messed up. Note that it’s not the best tool for your personal data backup though. For that, you can use Ubuntu’s default Deja Dup (also known as Backups) tool.
-
-##### TestDisk [Intermediate Users]
-
-This is another command line tool on this list of best Ubuntu application. [TestDisk][88] allows you to [recover data on Linux][89]. If you accidentally deleted files, there are still chances that you can get it back using TestDisk.
-
-#### System Tweaking and Management Tools
-
-![System Maintenance apps Ubuntu][90]
-
-##### GNOME/Unity Tweak Tool
-
-These Tweak tools are a must for every Ubuntu user. They allow you to access some advanced system settings. Best of all, you can [change themes in Ubuntu][91] using these tweak tools.
-
-##### UFW Firewall
-
-[UFW][92] stands for Uncomplicated Firewall and rightly so. UFW has predefined firewall settings for Home, Work and Public networks.
-
-##### Stacer
-
-If you want to free up space on Ubuntu, try Stacer. This graphical tool allows you to [optimize your Ubuntu system][93] by removing unnecessary files and completely uninstalling software. Download Stacer from [its website][94].
-
-#### Other Utilities
-
-![Utilities Ubuntu][95]
-
-In the end, I’ll list some of my other favorite Ubuntu apps that I could not put into a certain category.
-
-##### Neofetch
-
-One more command line tool! Neofetch displays your system information such as [Ubuntu version][96], desktop environment, theme, icons, RAM etc info along with [ASCII logo of the distribution][97]. Use this command for installing Neofetch.
-```
-sudo apt install neofetch
-
-```
-
-##### Etcher
-
-Ubuntu has a live USB creator tool installed already but Etcher is a better application for this task. It is also available for Windows and macOS. You can download it [from its website][98].
-
-##### gscan2pdf
-
-I use this tiny tool for the sole purpose of [converting images into PDF][99]. You can use it for combining multiple images into one PDF file as well.
-
-##### Audio Recorder
-
-Another tiny yet essential Ubuntu application for [recording audio on Ubuntu][100]. You can use it to record sound from system microphone, from music player or from any other source.
-
-### Your suggestions for essential Ubuntu applications?
-
-I would like to conclude my list of best Ubuntu apps here. I know that you might not need or use all of them but I am certain that you would like most of the software listed here.
-
-Did you find some useful applications that you didn’t know about before? If you would have to suggest your favorite Ubuntu application, which one would it be?
-
-In the end, if you find this article useful, please share it on social media, Reddit, Hacker News or other community or forums you visit regularly. This way you help us grow :)
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/best-ubuntu-apps/
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972](https://github.com/lujun9972)
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[1]:https://itsfoss.com/things-to-do-after-installing-ubuntu-18-04/
-[2]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/best-ubuntu-apps-featured.jpeg
-[3]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/google-chrome.jpeg
-[4]:https://www.google.com/chrome/
-[5]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/brave-browser-icon.jpeg
-[6]:https://itsfoss.com/open-source-browsers-linux/
-[7]:https://brave.com/
-[8]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/music-apps-ubuntu.jpeg
-[9]:https://itsfoss.com/sayonara-music-player/
-[10]:https://www.audacityteam.org/
-[11]:https://itsfoss.com/musicbrainz-picard/
-[12]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/streaming-music-apps-ubuntu.jpeg
-[13]:https://www.spotify.com//
-[14]:https://itsfoss.com/install-spotify-ubuntu-1404/
-[15]:https://tiliado.eu/nuvolaplayer/
-[16]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/Video-Players-linux.jpg
-[17]:https://www.videolan.org/index.html
-[18]:https://itsfoss.com/vlc-pro-tricks-linux/
-[19]:https://mpv.io/
-[20]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/dropbox-icon.jpeg
-[21]:https://www.dropbox.com/
-[22]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/pcloud-icon.jpeg
-[23]:https://itsfoss.com/recommends/pcloud/
-[24]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/gimp-icon.jpeg
-[25]:https://www.gimp.org/
-[26]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/inkscape-icon.jpeg
-[27]:https://inkscape.org/en/
-[28]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/paint-apps-ubuntu.jpeg
-[29]:https://krita.org/en/
-[30]:https://pinta-project.com/pintaproject/pinta/
-[31]:https://itsfoss.com/image-applications-ubuntu-linux/
-[32]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/digikam-icon.jpeg
-[33]:https://www.digikam.org/
-[34]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/darktable-icon.jpeg
-[35]:https://www.darktable.org/
-[36]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/video-editing-apps-ubuntu.jpeg
-[37]:https://itsfoss.com/best-video-editing-software-linux/
-[38]:https://kdenlive.org/en/
-[39]:https://shotcut.org/
-[40]:https://itsfoss.com/format-factory-alternative-linux/
-[41]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/xnconvert-logo.jpeg
-[42]:https://www.xnview.com/en/xnconvert/
-[43]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/handbrake-logo.jpeg
-[44]:https://handbrake.fr/
-[45]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/screen-recording-ubuntu-apps.jpeg
-[46]:http://shutter-project.org/
-[47]:https://launchpad.net/kazam
-[48]:https://itsfoss.com/best-linux-screen-recorders/
-[49]:https://www.youtube.com/c/itsfoss?sub_confirmation=1
-[50]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/libre-office-logo.jpeg
-[51]:https://www.libreoffice.org/download/download/
-[52]:https://itsfoss.com/best-free-open-source-alternatives-microsoft-office/
-[53]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/wps-office-logo.jpeg
-[54]:http://wps-community.org/
-[55]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/download-apps-ubuntu.jpeg
-[56]:https://itsfoss.com/download-youtube-linux/
-[57]:http://ugetdm.com/
-[58]:https://itsfoss.com/4-best-download-managers-for-linux/
-[59]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/coding-apps-ubuntu.jpeg
-[60]:https://atom.io/
-[61]:https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
-[62]:https://itsfoss.com/install-visual-studio-code-ubuntu/
-[63]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/pdf-management-apps-ubuntu.jpeg
-[64]:https://calibre-ebook.com/
-[65]:https://itsfoss.com/create-ebook-calibre-linux/
-[66]:https://itsfoss.com/pdf-editors-linux/
-[67]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/messaging-apps-ubuntu.jpeg
-[68]:https://itsfoss.com/best-messaging-apps-linux/
-[69]:https://www.skype.com/en/
-[70]:https://rambox.pro/
-[71]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/simplenote-logo.jpeg
-[72]:http://simplenote.com/
-[73]:https://automattic.com/
-[74]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/remember-the-milk-logo.jpeg
-[75]:https://itsfoss.com/remember-the-milk-linux/
-[76]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/encryption-apps-ubuntu.jpeg
-[77]:https://itsfoss.com/encryptpad-encrypted-text-editor-linux/
-[78]:https://itsfoss.com/password-protect-folder-linux/
-[79]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/gaming-ubuntu.jpeg
-[80]:https://itsfoss.com/linux-gaming-guide/
-[81]:https://store.steampowered.com/
-[82]:https://itsfoss.com/free-linux-games/
-[83]:https://www.playonlinux.com/en/
-[84]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/package-management-apps-ubuntu.jpeg
-[85]:https://itsfoss.com/how-to-add-remove-programs-in-ubuntu/
-[86]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/backup-recovery-tools-ubuntu.jpeg
-[87]:https://itsfoss.com/backup-restore-linux-timeshift/
-[88]:https://www.cgsecurity.org/wiki/TestDisk
-[89]:https://itsfoss.com/recover-deleted-files-linux/
-[90]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/system-maintenance-apps-ubuntu.jpeg
-[91]:https://itsfoss.com/install-themes-ubuntu/
-[92]:https://wiki.ubuntu.com/UncomplicatedFirewall
-[93]:https://itsfoss.com/optimize-ubuntu-stacer/
-[94]:https://github.com/oguzhaninan/Stacer
-[95]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/utilities-apps-ubuntu.jpeg
-[96]:https://itsfoss.com/how-to-know-ubuntu-unity-version/
-[97]:https://itsfoss.com/display-linux-logo-in-ascii/
-[98]:https://etcher.io/
-[99]:https://itsfoss.com/convert-multiple-images-pdf-ubuntu-1304/
-[100]:https://itsfoss.com/record-streaming-audio/
diff --git a/sources/tech/20181105 5 Minimal Web Browsers for Linux.md b/sources/tech/20181105 5 Minimal Web Browsers for Linux.md
deleted file mode 100644
index 34c0c1e18e..0000000000
--- a/sources/tech/20181105 5 Minimal Web Browsers for Linux.md
+++ /dev/null
@@ -1,171 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (MonkeyDEcho )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: subject: (5 Minimal Web Browsers for Linux)
-[#]: via: (https://www.linux.com/blog/intro-to-linux/2018/11/5-minimal-web-browsers-linux)
-[#]: author: (Jack Wallen https://www.linux.com/users/jlwallen)
-[#]: url: ( )
-
-5 Minimal Web Browsers for Linux
-======
-linux上的五种微型浏览器
-======
-
-
-
-There are so many reasons to enjoy the Linux desktop. One reason I often state up front is the almost unlimited number of choices to be found at almost every conceivable level. From how you interact with the operating system (via a desktop interface), to how daemons run, to what tools you use, you have a multitude of options.
-有太多理由去选择使用linux系统。很重要的一个理由是,我们可以按照我们自己的想法去选择想要的。从操作系统的交互方式(桌面系统)到守护系统的运行方式,在到使用的工具,你用更多的选择。
-
-The same thing goes for web browsers. You can use anything from open source favorites, such as [Firefox][1] and [Chromium][2], or closed sourced industry darlings like [Vivaldi][3] and [Chrome][4]. Those options are full-fledged browsers with every possible bell and whistle you’ll ever need. For some, these feature-rich browsers are perfect for everyday needs.
-web浏览器也是如此。你可以使用开源的[火狐][1],[Chromium][2];或者未开源的[Vivaldi][3],[Chrome][4]。这些功能强大的浏览器有你需要的各种功能。对于某些人,这些功能完备的浏览器是日常必需的。
-
-There are those, however, who prefer using a web browser without all the frills. In fact, there are many reasons why you might prefer a minimal browser over a standard browser. For some, it’s about browser security, while others look at a web browser as a single-function tool (as opposed to a one-stop shop application). Still others might be running low-powered machines that cannot handle the requirements of, say, Firefox or Chrome. Regardless of the reason, Linux has you covered.
-但是,有些人更喜欢没有冗余功能的纯粹的浏览器。实际上,有很多原因导致你会选择微型的浏览器而不选择上述功能完备的浏览器。对于某些人来说,与浏览器的安全有关;而有些人则将浏览器当作一种简单的工具(而不是一站式商店应用程序);还有一些可能运行在低功率的计算机上,这些计算机无法满足火狐,chrome浏览器的运行要求。无论出于何种原因,在linux系统上都可以满足你的要求。
-
-Let’s take a look at five of the minimal browsers that can be installed on Linux. I’ll be demonstrating these browsers on the Elementary OS platform, but each of these browsers are available to nearly every distribution in the known Linuxverse. Let’s dive in.
-让我们看一下可以在linux上安装运行的五种微型浏览器。我将在 Elementary 的操作系统平台上演示这些浏览器,在已知的linux发型版中几乎每个版本都可以使用这些浏览器。让我们一起来看一下吧!
-
-### GNOME Web
-
-GNOME Web (codename Epiphany, which means [“a usually sudden manifestation or perception of the essential nature or meaning of something”][5]) is the default web browser for Elementary OS, but it can be installed from the standard repositories. (Note, however, that the recommended installation of Epiphany is via Flatpak or Snap). If you choose to install via the standard package manager, issue a command such as sudo apt-get install epiphany-browser -y for successful installation.
-GNOME web (Epiphany 含义:[顿悟][5])是Elementary系统默认的web浏览器,也可以从标准存储库中安装。(注意,建议通过使用 Flatpak 或者 Snap 工具安装),如果你想选择标准软件包管理器进行安装,请执行 ```sudo apt-get install epiphany-browser -y``` 命令成功安装。
-
-Epiphany uses the WebKit rendering engine, which is the same engine used in Apple’s Safari browser. Couple that rendering engine with the fact that Epiphany has very little in terms of bloat to get in the way, you will enjoy very fast page-rendering speeds. Epiphany development follows strict adherence to the following guidelines:
-
- * Simplicity - Feature bloat and user interface clutter are considered evil.
-
- * Standards compliance - No non-standard features will ever be introduced to the codebase.
-
- * Software freedom - Epiphany will always be released under a license that respects freedom.
-
- * Human interface - Epiphany follows the [GNOME Human Interface Guidelines][6].
-
- * Minimal preferences - Preferences are only added when they make sense and after careful consideration.
-
- * Target audience - Non-technical users are the primary target audience (which helps to define the types of features that are included).
-
-
-
-
-GNOME Web is as clean and simple a web browser as you’ll find (Figure 1).
-
-![GNOME Web][8]
-
-Figure 1: The GNOME Web browser displaying a minimal amount of preferences for the user.
-
-[Used with permission][9]
-
-The GNOME Web manifesto reads:
-
-A web browser is more than an application: it is a way of thinking, a way of seeing the world. Epiphany's principles are simplicity, standards compliance, and software freedom.
-
-### Netsurf
-
-The [Netsurf][10] minimal web browser opens almost faster than you can release the mouse button. Netsurf uses its own layout and rendering engine (designed completely from scratch), which is rather hit and miss in its rendering (Figure 2).
-
-
-
-Although you might find Netsurf to suffer from rendering issues on certain sites, understand the Hubbub HTML parser is following the work-in-progress HTML5 specification, so there will be issues popup now and then. To ease those rendering headaches, Netsurf does include HTTPS support, web page thumbnailing, URL completion, scale view, bookmarks, full-screen mode, keyboard shorts, and no particular GUI toolkit requirements. That last bit is important, especially when you switch from one desktop to another.
-
-For those curious as to the requirements for Netsurf, the browser can run on a machine as slow as a 30Mhz ARM 6 computer with 16MB of RAM. That’s impressive, by today’s standard.
-
-### QupZilla
-
-If you’re looking for a minimal browser that uses the Qt Framework and the QtWebKit rendering engine, [QupZilla][11] might be exactly what you’re looking for. QupZilla does include all the standard features and functions you’d expect from a web browser, such as bookmarks, history, sidebar, tabs, RSS feeds, ad blocking, flash blocking, and CA Certificates management. Even with those features, QupZilla still manages to remain a very fast lightweight web browser. Other features include: Fast startup, speed dial homepage, built-in screenshot tool, browser themes, and more.
-One feature that should appeal to average users is that QupZilla has a more standard preferences tools than found in many lightweight browsers (Figure 3). So, if going too far outside the lines isn’t your style, but you still want something lighter weight, QupZilla is the browser for you.
-
-![QupZilla][13]
-
-Figure 3: The QupZilla preferences tool.
-
-[Used with permission][9]
-
-### Otter Browser
-
-Otter Browser is a free, open source attempt to recreate the closed-source offerings found in the Opera Browser. Otter Browser uses the WebKit rendering engine and has an interface that should be immediately familiar with any user. Although lightweight, Otter Browser does include full-blown features such as:
-
- * Passwords manager
-
- * Add-on manager
-
- * Content blocking
-
- * Spell checking
-
- * Customizable GUI
-
- * URL completion
-
- * Speed dial (Figure 4)
-
- * Bookmarks and various related features
-
- * Mouse gestures
-
- * User style sheets
-
- * Built-in Note tool
-
-
-![Otter][15]
-
-Figure 4: The Otter Browser Speed Dial tab.
-
-[Used with permission][9]
-
-Otter Browser can be run on nearly any Linux distribution from an [AppImage][16], so there’s no installation required. Just download the AppImage file, give the file executable permissions (with the command chmod u+x otter-browser-*.AppImage), and then launch the app with the command ./otter-browser*.AppImage.
-
-Otter Browser does an outstanding job of rendering websites and could function as your go-to minimal browser with ease.
-
-### Lynx
-
-Let’s get really minimal. When I first started using Linux, back in ‘97, one of the web browsers I often turned to was a text-only take on the app called [Lynx][17]. It should come as no surprise that Lynx is still around and available for installation from the standard repositories. As you might expect, Lynx works from the terminal window and doesn’t display pretty pictures or render much in the way of advanced features (Figure 5). In fact, Lynx is as bare-bones a browser as you will find available. Because of how bare-bones this web browser is, it’s not recommended for everyone. But if you happen to have a gui-less web server and you have a need to be able to read the occasional website, Lynx can be a real lifesaver.
-
-![Lynx][19]
-
-Figure 5: The Lynx browser rendering the Linux.com page.
-
-[Used with permission][9]
-
-I have also found Lynx an invaluable tool when troubleshooting certain aspects of a website (or if some feature on a website is preventing me from viewing the content in a regular browser). Another good reason to use Lynx is when you only want to view the content (and not the extraneous elements).
-
-### Plenty More Where This Came From
-
-There are plenty more minimal browsers than this. But the list presented here should get you started down the path of minimalism. One (or more) of these browsers are sure to fill that need, whether you’re running it on a low-powered machine or not.
-
-Learn more about Linux through the free ["Introduction to Linux" ][20]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/intro-to-linux/2018/11/5-minimal-web-browsers-linux
-
-作者:[Jack Wallen][a]
-选题:[lujun9972][b]
-译者:[译者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/jlwallen
-[b]: https://github.com/lujun9972
-[1]: https://www.mozilla.org/en-US/firefox/new/
-[2]: https://www.chromium.org/
-[3]: https://vivaldi.com/
-[4]: https://www.google.com/chrome/
-[5]: https://www.merriam-webster.com/dictionary/epiphany
-[6]: https://developer.gnome.org/hig/stable/
-[7]: /files/images/minimalbrowsers1jpg
-[8]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minimalbrowsers_1.jpg?itok=Q7wZLF8B (GNOME Web)
-[9]: /licenses/category/used-permission
-[10]: https://www.netsurf-browser.org/
-[11]: https://qupzilla.com/
-[12]: /files/images/minimalbrowsers3jpg
-[13]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minimalbrowsers_3.jpg?itok=O8iMALWO (QupZilla)
-[14]: /files/images/minimalbrowsers4jpg
-[15]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minimalbrowsers_4.jpg?itok=5bCa0z-e (Otter)
-[16]: https://sourceforge.net/projects/otter-browser/files/
-[17]: https://lynx.browser.org/
-[18]: /files/images/minimalbrowsers5jpg
-[19]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minimalbrowsers_5.jpg?itok=p_Lmiuxh (Lynx)
-[20]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md b/sources/tech/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md
deleted file mode 100644
index 71555454f5..0000000000
--- a/sources/tech/20190102 Using Yarn on Ubuntu and Other Linux Distributions.md
+++ /dev/null
@@ -1,265 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Using Yarn on Ubuntu and Other Linux Distributions)
-[#]: via: (https://itsfoss.com/install-yarn-ubuntu)
-[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
-
-Using Yarn on Ubuntu and Other Linux Distributions
-======
-
-**This quick tutorial shows you the official way of installing Yarn package manager on Ubuntu and Debian Linux. You’ll also learn some basic Yarn commands and the steps to remove Yarn completely.**
-
-[Yarn][1] is an open source JavaScript package manager developed by Facebook. It is an alternative or should I say improvement to the popular npm package manager. [Facebook developers’ team][2] created Yarn to overcome the shortcomings of [npm][3]. Facebook claims that Yarn is faster, reliable and more secure than npm.
-
-Like npm, Yarn provides you a way to automate the process of installing, updating, configuring, and removing packages retrieved from a global registry.
-
-The advantage of Yarn is that it is faster as it caches every package it downloads so it doesn’t need to download it again. It also parallelizes operations to maximize resource utilization. Yarn also uses [checksums to verify the integrity][4] of every installed package before its code is executed. Yarn also guarantees that an install that worked on one system will work exactly the same way on any other system.
-
-If you are [using nodejs on Ubuntu][5], probably you already have npm installed on your system. In that case, you can use npm to install Yarn globally in the following manner:
-
-```
-sudo npm install yarn -g
-```
-
-However, I would recommend using the official way to install Yarn on Ubuntu/Debian.
-
-### Installing Yarn on Ubuntu and Debian [The Official Way]
-
-![Yarn JS][6]
-
-The instructions mentioned here should be applicable to all versions of Ubuntu such as Ubuntu 18.04, 16.04 etc. The same set of instructions are also valid for Debian and other Debian based distributions.
-
-Since the tutorial uses Curl to add the GPG key of Yarn project, it would be a good idea to verify whether you have Curl installed already or not.
-
-```
-sudo apt install curl
-```
-
-The above command will install Curl if it wasn’t installed already. Now that you have curl, you can use it to add the GPG key of Yarn project in the following fashion:
-
-```
-curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-```
-
-After that, add the repository to your sources list so that you can easily upgrade the Yarn package in future with the rest of the system updates:
-
-```
-sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list'
-```
-
-You are set to go now. [Update Ubuntu][7] or Debian system to refresh the list of available packages and then install yarn:
-
-```
-sudo apt update
-sudo apt install yarn
-```
-
-This will install Yarn along with nodejs. Once the process completes, verify that Yarn has been installed successfully. You can do that by checking the Yarn version.
-
-```
-yarn --version
-```
-
-For me, it showed an output like this:
-
-```
-yarn --version
-1.12.3
-```
-
-This means that I have Yarn version 1.12.3 installed on my system.
-
-### Using Yarn
-
-I presume that you have some basic understandings of JavaScript programming and how dependencies work. I am not going to go in details here. I’ll show you some of the basic Yarn commands that will help you getting started with it.
-
-#### Creating a new project with Yarn
-
-Like npm, Yarn also works with a package.json file. This is where you add your dependencies. All the packages of the dependencies are cached in the node_modules directory in the root directory of your project.
-
-In the root directory of your project, run the following command to generate a fresh package.json file:
-
-It will ask you a number of questions. You can skip the questions r go with the defaults by pressing enter.
-
-```
-yarn init
-yarn init v1.12.3
-question name (test_yarn): test_yarn_proect
-question version (1.0.0): 0.1
-question description: Test Yarn
-question entry point (index.js):
-question repository url:
-question author: abhishek
-question license (MIT):
-question private:
-success Saved package.json
-Done in 82.42s.
-```
-
-With this, you get a package.json file of this sort:
-
-```
-{
- "name": "test_yarn_proect",
- "version": "0.1",
- "description": "Test Yarn",
- "main": "index.js",
- "author": "abhishek",
- "license": "MIT"
-}
-```
-
-Now that you have the package.json, you can either manually edit it to add or remove package dependencies or use Yarn commands (preferred).
-
-#### Adding dependencies with Yarn
-
-You can add a dependency on a certain package in the following fashion:
-
-```
-yarn add
-```
-
-For example, if you want to use [Lodash][8] in your project, you can add it using Yarn like this:
-
-```
-yarn add lodash
-yarn add v1.12.3
-info No lockfile found.
-[1/4] Resolving packages…
-[2/4] Fetching packages…
-[3/4] Linking dependencies…
-[4/4] Building fresh packages…
-success Saved lockfile.
-success Saved 1 new dependency.
-info Direct dependencies
-└─ [email protected]
-info All dependencies
-└─ [email protected]
-Done in 2.67s.
-```
-
-And you can see that this dependency has been added automatically in the package.json file:
-
-```
-{
- "name": "test_yarn_proect",
- "version": "0.1",
- "description": "Test Yarn",
- "main": "index.js",
- "author": "abhishek",
- "license": "MIT",
- "dependencies": {
- "lodash": "^4.17.11"
- }
-}
-```
-
-By default, Yarn will add the latest version of a package in the dependency. If you want to use a specific version, you may specify it while adding.
-
-As always, you can also update the package.json file manually.
-
-#### Upgrading dependencies with Yarn
-
-You can upgrade a particular dependency to its latest version with the following command:
-
-```
-yarn upgrade
-```
-
-It will see if the package in question has a newer version and will update it accordingly.
-
-You can also change the version of an already added dependency in the following manner:
-
-You can also upgrade all the dependencies of your project to their latest version with one single command:
-
-```
-yarn upgrade
-```
-
-It will check the versions of all the dependencies and will update them if there are any newer versions.
-
-#### Removing dependencies with Yarn
-
-You can remove a package from the dependencies of your project in this way:
-
-```
-yarn remove
-```
-
-#### Install all project dependencies
-
-If you made any changes to the project.json file, you should run either
-
-```
-yarn
-```
-
-or
-
-```
-yarn install
-```
-
-to install all the dependencies at once.
-
-### How to remove Yarn from Ubuntu or Debian
-
-I’ll complete this tutorial by mentioning the steps to remove Yarn from your system if you used the above steps to install it. If you ever realized that you don’t need Yarn anymore, you will be able to remove it.
-
-Use the following command to remove Yarn and its dependencies.
-
-```
-sudo apt purge yarn
-```
-
-You should also remove the Yarn repository from the repository list:
-
-```
-sudo rm /etc/apt/sources.list.d/yarn.list
-```
-
-The optional next step is to remove the GPG key you had added to the trusted keys. But for that, you need to know the key. You can get that using the apt-key command:
-
-Warning: apt-key output should not be parsed (stdout is not a terminal) pub rsa4096 2016-10-05 [SC] 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310 uid [ unknown] Yarn Packaging
-
-Warning: apt-key output should not be parsed (stdout is not a terminal) pub rsa4096 2016-10-05 [SC] 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310 uid [ unknown] Yarn Packaging yarn@dan.cx sub rsa4096 2016-10-05 [E] sub rsa4096 2019-01-02 [S] [expires: 2020-02-02]
-
-The key here is the last 8 characters of the GPG key’s fingerprint in the line starting with pub.
-
-So, in my case, the key is 86E50310 and I’ll remove it using this command:
-
-```
-sudo apt-key del 86E50310
-```
-
-You’ll see an OK in the output and the GPG key of Yarn package will be removed from the list of GPG keys your system trusts.
-
-I hope this tutorial helped you to install Yarn on Ubuntu, Debian, Linux Mint, elementary OS etc. I provided some basic Yarn commands to get you started along with complete steps to remove Yarn from your system.
-
-I hope you liked this tutorial and if you have any questions or suggestions, please feel free to leave a comment below.
-
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/install-yarn-ubuntu
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[b]: https://github.com/lujun9972
-[1]: https://yarnpkg.com/lang/en/
-[2]: https://code.fb.com/
-[3]: https://www.npmjs.com/
-[4]: https://itsfoss.com/checksum-tools-guide-linux/
-[5]: https://itsfoss.com/install-nodejs-ubuntu/
-[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/yarn-js-ubuntu-debian.jpeg?resize=800%2C450&ssl=1
-[7]: https://itsfoss.com/update-ubuntu/
-[8]: https://lodash.com/
diff --git a/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md b/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md
deleted file mode 100644
index 32a6a7dd3e..0000000000
--- a/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md
+++ /dev/null
@@ -1,232 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Different Ways To Update Linux Kernel For Ubuntu)
-[#]: via: (https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/)
-[#]: author: (SK https://www.ostechnix.com/author/sk/)
-
-Different Ways To Update Linux Kernel For Ubuntu
-======
-
-
-
-In this guide, we have given 7 different ways to update Linux kernel for Ubuntu. Among the 7 methods, five methods requires system reboot to apply the new Kernel and two methods don’t. Before updating Linux Kernel, it is **highly recommended to backup your important data!** All methods mentioned here are tested on Ubuntu OS only. We are not sure if they will work on other Ubuntu flavors (Eg. Xubuntu) and Ubuntu derivatives (Eg. Linux Mint).
-
-### Part A – Kernel Updates with reboot
-
-The following methods requires you to reboot your system to apply the new Linux Kernel. All of the following methods are recommended for personal or testing systems. Again, please backup your important data, configuration files and any other important stuff from your Ubuntu system.
-
-#### Method 1 – Update the Linux Kernel with dpkg (The manual way)
-
-This method helps you to manually download and install the latest available Linux kernel from **[kernel.ubuntu.com][1]** website. If you want to install most recent version (either stable or release candidate), this method will help. Download the Linux kernel version from the above link. As of writing this guide, the latest available version was **5.0-rc1** and latest stable version was **v4.20**.
-
-![][3]
-
-Click on the Linux Kernel version link of your choice and find the section for your architecture (‘Build for XXX’). In that section, download the two files with these patterns (where X.Y.Z is the highest version):
-
- 1. linux-image-*X.Y.Z*-generic-*.deb
- 2. linux-modules-X.Y.Z*-generic-*.deb
-
-
-
-In a terminal, change directory to where the files are and run this command to manually install the kernel:
-
-```
-$ sudo dpkg --install *.deb
-```
-
-Reboot to use the new kernel:
-
-```
-$ sudo reboot
-```
-
-Check the kernel is as expected:
-
-```
-$ uname -r
-```
-
-For step by step instructions, please check the section titled under “Install Linux Kernel 4.15 LTS On DEB based systems” in the following guide.
-
-+ [Install Linux Kernel 4.15 In RPM And DEB Based Systems](https://www.ostechnix.com/install-linux-kernel-4-15-rpm-deb-based-systems/)
-
-The above guide is specifically written for 4.15 version. However, all the steps are same for installing latest versions too.
-
-**Pros:** No internet needed (You can download the Linux Kernel from any system).
-
-**Cons:** Manual update. Reboot necessary.
-
-#### Method 2 – Update the Linux Kernel with apt-get (The recommended method)
-
-This is the recommended way to install latest Linux kernel on Ubuntu-like systems. Unlike the previous method, this method will download and install latest Kernel version from Ubuntu official repositories instead of **kernel.ubuntu.com** website..
-
-To update the whole system including the Kernel, just do:
-
-```
-$ sudo apt-get update
-
-$ sudo apt-get upgrade
-```
-
-If you want to update the Kernel only, run:
-
-```
-$ sudo apt-get upgrade linux-image-generic
-```
-
-**Pros:** Simple. Recommended method.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-Updating Kernel from official repositories will mostly work out of the box without any problems. If it is the production system, this is the recommended way to update the Kernel.
-
-Method 1 and 2 requires user intervention to update Linux Kernels. The following methods (3, 4 & 5) are mostly automated.
-
-#### Method 3 – Update the Linux Kernel with Ukuu
-
-**Ukuu** is a Gtk GUI and command line tool that downloads the latest main line Linux kernel from **kernel.ubuntu.com** , and install it automatically in your Ubuntu desktop and server editions. Ukku is not only simplifies the process of manually downloading and installing new Kernels, but also helps you to safely remove the old and unnecessary Kernels. For more details, refer the following guide.
-
-+ [Ukuu – An Easy Way To Install And Upgrade Linux Kernel In Ubuntu-based Systems](https://www.ostechnix.com/ukuu-an-easy-way-to-install-and-upgrade-linux-kernel-in-ubuntu-based-systems/)
-
-**Pros:** Easy to install and use. Automatically installs main line Kernel.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-#### Method 4 – Update the Linux Kernel with UKTools
-
-Just like Ukuu, the **UKTools** also fetches the latest stable Kernel from from **kernel.ubuntu.com** site and installs it automatically on Ubuntu and its derivatives like Linux Mint. More details about UKTools can be found in the link given below.
-
-+ [UKTools – Upgrade Latest Linux Kernel In Ubuntu And Derivatives](https://www.ostechnix.com/uktools-upgrade-latest-linux-kernel-in-ubuntu-and-derivatives/)
-
-**Pros:** Simple. Automated.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-#### Method 5 – Update the Linux Kernel with Linux Kernel Utilities
-
-**Linux Kernel Utilities** is yet another program that makes the process of updating Linux kernel easy in Ubuntu-like systems. It is actually a set of BASH shell scripts used to compile and/or update latest Linux kernels for Debian and derivatives. It consists of three utilities, one for manually compiling and installing Kernel from source from [**http://www.kernel.org**][4] website, another for downloading and installing pre-compiled Kernels from from **** website. and third script is for removing the old kernels. For more details, please have a look at the following link.
-
-+ [Linux Kernel Utilities – Scripts To Compile And Update Latest Linux Kernel For Debian And Derivatives](https://www.ostechnix.com/linux-kernel-utilities-scripts-compile-update-latest-linux-kernel-debian-derivatives/)
-
-**Pros:** Simple. Automated.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-
-### Part B – Kernel Updates without reboot
-
-As I already said, all of above methods need you to reboot the server before the new kernel is active. If they are personal systems or testing machines, you could simply reboot and start using the new Kernel. But, what if they are production systems that requires zero downtime? No problem. This is where **Livepatching** comes in handy!
-
-The **livepatching** (or hot patching) allows you to install Linux updates or patches without rebooting, keeping your server at the latest security level, without any downtime. This is attractive for ‘always-on’ servers, such as web hosts, gaming servers, in fact, any situation where the server needs to stay on all the time. Linux vendors maintain patches only for security fixes, so this approach is best when security is your main concern.
-
-The following two methods doesn’t require system reboot and useful for updating Linux Kernel on production and mission-critical Ubuntu servers.
-
-#### Method 6 – Update the Linux Kernel Canonical Livepatch Service
-
-![][5]
-
-[**Canonical Livepatch Service**][6] applies Kernel updates, patches and security hotfixes automatically without rebooting the Ubuntu systems. It reduces the Ubuntu systems downtime and keep them secure. Canonical Livepatch Service can be set up either during or after installation. If you are using desktop Ubuntu, the Software Updater will automatically check for kernel patches and notify you. In a console-based system, it is up to you to run apt-get update regularly. It will install kernel security patches only when you run the command “apt-get upgrade”, hence is semi-automatic.
-
-Livepatch is free for three systems. If you have more than three, you need to upgrade to enterprise support solution named **Ubuntu Advantage** suite. This suite includes **Kernel Livepatching** and other services such as,
-
- * Extended Security Maintenance – critical security updates after Ubuntu end-of-life.
- * Landscape – the systems management tool for using Ubuntu at scale.
- * Knowledge Base – A private collection of articles and tutorials written by Ubuntu experts.
- * Phone and web-based support.
-
-
-
-**Cost**
-
-Ubuntu Advantage includes three paid plans namely, Essential, Standard and Advanced. The basic plan (Essential plan) starts from **225 USD per year for one physical node** and **75 USD per year for one VPS**. It seems there is no monthly subscription for Ubuntu servers and desktops. You can view detailed information on all plans [**here**][7].
-
-**Pros:** Simple. Semi-automatic. No reboot necessary. Free for 3 systems.
-
-**Cons:** Expensive for 4 or more hosts. No patch rollback.
-
-**Enable Canonical Livepatch Service**
-
-If you want to setup Livepatch service after installation, just do the following steps.
-
-Get a key at [**https://auth.livepatch.canonical.com/**][8].
-
-```
-$ sudo snap install canonical-livepatch
-
-$ sudo canonical-livepatch enable your-key
-```
-
-#### Method 7 – Update the Linux Kernel with KernelCare
-
-![][9]
-
-[**KernelCare**][10] is the newest of all the live patching solutions. It is the product of [CloudLinux][11]. KernelCare runs on Ubuntu and other flavors of Linux. It checks for patch releases every 4 hours and will install them without confirmation. Patches can be rolled back if there are problems.
-
-**Cost**
-
-Fees, per server: **4 USD per month** , **45 USD per year**.
-
-Compared to Ubuntu Livepatch, kernelCare seems very cheap and affordable. Good thing is **monthly subscriptions are also available**. Another notable feature is it supports other Linux distributions, such as Red Hat, CentOS, Debian, Oracle Linux, Amazon Linux and virtualization platforms like OpenVZ, Proxmox etc.
-
-You can read all the features and benefits of KernelCare [**here**][12] and check all available plan details [**here**][13].
-
-**Pros:** Simple. Fully automated. Wide OS coverage. Patch rollback. No reboot necessary. Free license for non-profit organizations. Low cost.
-
-**Cons:** Not free (except for 30 day trial).
-
-**Enable KernelCare Service**
-
-Get a 30-day trial key at [**https://cloudlinux.com/kernelcare-free-trial5**][14].
-
-Run the following commands to enable KernelCare and register the key.
-
-```
-$ sudo wget -qq -O - https://repo.cloudlinux.com/kernelcare/kernelcare_install.sh | bash
-
-$ sudo /usr/bin/kcarectl --register KEY
-```
-
-If you’re looking for an affordable and reliable commercial service to keep the Linux Kernel updated on your Linux servers, KernelCare is good to go.
-
-*with inputs from **Paul A. Jacobs** , a Technical Evangelist and Content Writer from Cloud Linux.*
-
-**Suggested read:**
-
-And, that’s all for now. Hope this was useful. If you believe any other tools/methods should include in this list, feel free to let us know in the comment section below. I will check and update this guide accordingly.
-
-More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/
-
-作者:[SK][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.ostechnix.com/author/sk/
-[b]: https://github.com/lujun9972
-[1]: http://kernel.ubuntu.com/~kernel-ppa/mainline/
-[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[3]: http://www.ostechnix.com/wp-content/uploads/2019/01/Ubuntu-mainline-kernel.png
-[4]: http://www.kernel.org
-[5]: http://www.ostechnix.com/wp-content/uploads/2019/01/Livepatch.png
-[6]: https://www.ubuntu.com/livepatch
-[7]: https://www.ubuntu.com/support/plans-and-pricing
-[8]: https://auth.livepatch.canonical.com/
-[9]: http://www.ostechnix.com/wp-content/uploads/2019/01/KernelCare.png
-[10]: https://www.kernelcare.com/
-[11]: https://www.cloudlinux.com/
-[12]: https://www.kernelcare.com/update-kernel-linux/
-[13]: https://www.kernelcare.com/pricing/
-[14]: https://cloudlinux.com/kernelcare-free-trial5
diff --git a/sources/tech/20190113 Editing Subtitles in Linux.md b/sources/tech/20190113 Editing Subtitles in Linux.md
deleted file mode 100644
index 57db2754d4..0000000000
--- a/sources/tech/20190113 Editing Subtitles in Linux.md
+++ /dev/null
@@ -1,168 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (chenmu-kk )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Editing Subtitles in Linux)
-[#]: via: (https://itsfoss.com/editing-subtitles)
-[#]: author: (Shirish https://itsfoss.com/author/shirish/)
-
-Editing Subtitles in Linux
-======
-
-I have been a world movie and regional movies lover for decades. Subtitles are the essential tool that have enabled me to enjoy the best movies in various languages and from various countries.
-
-If you enjoy watching movies with subtitles, you might have noticed that sometimes the subtitles are not synced or not correct.
-
-Did you know that you can edit subtitles and make them better? Let me show you some basic subtitle editing in Linux.
-
-![Editing subtitles in Linux][1]
-
-### Extracting subtitles from closed captions data
-
-Around 2012, 2013 I came to know of a tool called [CCEextractor.][2] As time passed, it has become one of the vital tools for me, especially if I come across a media file which has the subtitle embedded in it.
-
-CCExtractor analyzes video files and produces independent subtitle files from the closed captions data.
-
-CCExtractor is a cross-platform, free and open source tool. The tool has matured quite a bit from its formative years and has been part of [GSOC][3] and Google Code-in now and [then.][4]
-
-The tool, to put it simply, is more or less a set of scripts which work one after another in a serialized order to give you an extracted subtitle.
-
-You can follow the installation instructions for CCExtractor on [this page][5].
-
-After installing when you want to extract subtitles from a media file, do the following:
-
-```
-ccextractor
-```
-
-The output of the command will be something like this:
-
-It basically scans the media file. In this case, it found that the media file is in malyalam and that the media container is an [.mkv][6] container. It extracted the subtitle file with the same name as the video file adding _eng to it.
-
-CCExtractor is a wonderful tool which can be used to enhance subtitles along with Subtitle Edit which I will share in the next section.
-
-```
-Interesting Read: There is an interesting synopsis of subtitles at [vicaps][7] which tells and shares why subtitles are important to us. It goes into quite a bit of detail of movie-making as well for those interested in such topics.
-```
-
-### Editing subtitles with SubtitleEditor Tool
-
-You probably are aware that most subtitles are in [.srt format][8] . The beautiful thing about this format is and was you could load it in your text editor and do little fixes in it.
-
-A srt file looks something like this when launched into a simple text-editor:
-
-The excerpt subtitle I have shared is from a pretty Old German Movie called [The Cabinet of Dr. Caligari (1920)][9]
-
-Subtitleeditor is a wonderful tool when it comes to editing subtitles. Subtitle Editor is and can be used to manipulate time duration, frame-rate of the subtitle file to be in sync with the media file, duration of breaks in-between and much more. I’ll share some of the basic subtitle editing here.
-
-![][10]
-
-First install subtitleeditor the same way you installed ccextractor, using your favorite installation method. In Debian, you can use this command:
-
-```
-sudo apt install subtitleeditor
-```
-
-When you have it installed, let’s see some of the common scenarios where you need to edit a subtitle.
-
-#### Manipulating Frame-rates to sync with Media file
-
-If you find that the subtitles are not synced with the video, one of the reasons could be the difference between the frame rates of the video file and the subtitle file.
-
-How do you know the frame rates of these files, then?
-
-To get the frame rate of a video file, you can use the mediainfo tool. You may need to install it first using your distribution’s package manager.
-
-Using mediainfo is simple:
-
-```
-$ mediainfo somefile.mkv | grep Frame
- Format settings : CABAC / 4 Ref Frames
- Format settings, ReFrames : 4 frames
- Frame rate mode : Constant
- Frame rate : 25.000 FPS
- Bits/(Pixel*Frame) : 0.082
- Frame rate : 46.875 FPS (1024 SPF)
-```
-
-Now you can see that framerate of the video file is 25.000 FPS. The other Frame-rate we see is for the audio. While I can share why particular fps are used in Video-encoding, Audio-encoding etc. it would be a different subject matter. There is a lot of history associated with it.
-
-Next is to find out the frame rate of the subtitle file and this is a slightly complicated.
-
-Usually, most subtitles are in a zipped format. Unzipping the .zip archive along with the subtitle file which ends in something.srt. Along with it, there is usually also a .info file with the same name which sometime may have the frame rate of the subtitle.
-
-If not, then it usually is a good idea to go some site and download the subtitle from a site which has that frame rate information. For this specific German file, I will be using [Opensubtitle.org][11]
-
-As you can see in the link, the frame rate of the subtitle is 23.976 FPS. Quite obviously, it won’t play well with my video file with frame rate 25.000 FPS.
-
-In such cases, you can change the frame rate of the subtitle file using the Subtitle Editor tool:
-
-Select all the contents from the subtitle file by doing CTRL+A. Go to Timings -> Change Framerate and change frame rates from 23.976 fps to 25.000 fps or whatever it is that is desired. Save the changed file.
-
-![synchronize frame rates of subtitles in Linux][12]
-
-#### Changing the Starting position of a subtitle file
-
-Sometimes the above method may be enough, sometimes though it will not be enough.
-
-You might find some cases when the start of the subtitle file is different from that in the movie or a media file while the frame rate is the same.
-
-In such cases, do the following:
-
-Select all the contents from the subtitle file by doing CTRL+A. Go to Timings -> Select Move Subtitle.
-
-![Move subtitles using Subtitle Editor on Linux][13]
-
-Change the new Starting position of the subtitle file. Save the changed file.
-
-![Move subtitles using Subtitle Editor in Linux][14]
-
-If you wanna be more accurate, then use [mpv][15] to see the movie or media file and click on the timing, if you click on the timing bar which shows how much the movie or the media file has elapsed, clicking on it will also reveal the microsecond.
-
-I usually like to be accurate so I try to be as precise as possible. It is very difficult in MPV as human reaction time is imprecise. If I wanna be super accurate then I use something like [Audacity][16] but then that is another ball-game altogether as you can do so much more with it. That may be something to explore in a future blog post as well.
-
-#### Manipulating Duration
-
-Sometimes even doing both is not enough and you even have to shrink or add the duration to make it sync with the media file. This is one of the more tedious works as you have to individually fix the duration of each sentence. This can happen especially if you have variable frame rates in the media file (nowadays rare but you still get such files).
-
-In such a scenario, you may have to edit the duration manually and automation is not possible. The best way is either to fix the video file (not possible without degrading the video quality) or getting video from another source at a higher quality and then [transcode][17] it with the settings you prefer. This again, while a major undertaking I could shed some light on in some future blog post.
-
-### Conclusion
-
-What I have shared in above is more or less on improving on existing subtitle files. If you were to start a scratch you need loads of time. I haven’t shared that at all because a movie or any video material of say an hour can easily take anywhere from 4-6 hours or even more depending upon skills of the subtitler, patience, context, jargon, accents, native English speaker, translator etc. all of which makes a difference to the quality of the subtitle.
-
-I hope you find this interesting and from now onward, you’ll handle your subtitles slightly better. If you have any suggestions to add, please leave a comment below.
-
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/editing-subtitles
-
-作者:[Shirish][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/shirish/
-[b]: https://github.com/lujun9972
-[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/editing-subtitles-in-linux.jpeg?resize=800%2C450&ssl=1
-[2]: https://www.ccextractor.org/
-[3]: https://itsfoss.com/best-open-source-internships/
-[4]: https://www.ccextractor.org/public:codein:google_code-in_2018
-[5]: https://github.com/CCExtractor/ccextractor/wiki/Installation
-[6]: https://en.wikipedia.org/wiki/Matroska
-[7]: https://www.vicaps.com/blog/history-of-silent-movies-and-subtitles/
-[8]: https://en.wikipedia.org/wiki/SubRip#SubRip_text_file_format
-[9]: https://www.imdb.com/title/tt0010323/
-[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/subtitleeditor.jpg?ssl=1
-[11]: https://www.opensubtitles.org/en/search/sublanguageid-eng/idmovie-4105
-[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/subtitleeditor-frame-rate-sync.jpg?resize=800%2C450&ssl=1
-[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/Move-subtitles-Caligiri.jpg?resize=800%2C450&ssl=1
-[14]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/move-subtitles.jpg?ssl=1
-[15]: https://itsfoss.com/mpv-video-player/
-[16]: https://www.audacityteam.org/
-[17]: https://en.wikipedia.org/wiki/Transcoding
-[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/editing-subtitles-in-linux.jpeg?fit=800%2C450&ssl=1
diff --git a/sources/tech/20190115 Linux Desktop Setup - HookRace Blog.md b/sources/tech/20190115 Linux Desktop Setup - HookRace Blog.md
deleted file mode 100644
index 29d5f63d2a..0000000000
--- a/sources/tech/20190115 Linux Desktop Setup - HookRace Blog.md
+++ /dev/null
@@ -1,514 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Linux Desktop Setup · HookRace Blog)
-[#]: via: (https://hookrace.net/blog/linux-desktop-setup/)
-[#]: author: (Dennis Felsing http://felsin9.de/nnis/)
-
-Linux Desktop Setup
-======
-
-
-My software setup has been surprisingly constant over the last decade, after a few years of experimentation since I initially switched to Linux in 2006. It might be interesting to look back in another 10 years and see what changed. A quick overview of what’s running as I’m writing this post:
-
-[![htop overview][1]][2]
-
-### Motivation
-
-My software priorities are, in no specific order:
-
- * Programs should run on my local system so that I’m in control of them, this excludes cloud solutions.
- * Programs should run in the terminal, so that they can be used consistently from anywhere, including weak computers or a phone.
- * Keyboard focused is nearly automatic by using terminal software. I prefer to use the mouse where it makes sense only, reaching for the mouse all the time during typing feels like a waste of time. Occasionally it took me an hour to notice that the mouse wasn’t even plugged in.
- * Ideally use fast and efficient software, I don’t like hearing the fan and feeling the room heat up. I can also keep running older hardware for much longer, my 10 year old Thinkpad x200s is still fine for all the software I use.
- * Be composable. I don’t want to do every step manually, instead automate more when it makes sense. This naturally favors the shell.
-
-
-
-### Operating Systems
-
-I had a hard start with Linux 12 years ago by removing Windows, armed with just the [Gentoo Linux][3] installation CD and a printed manual to get a functioning Linux system. It took me a few days of compiling and tinkering, but in the end I felt like I had learnt a lot.
-
-I haven’t looked back to Windows since then, but I switched to [Arch Linux][4] on my laptop after having the fan fail from the constant compilation stress. Later I also switched all my other computers and private servers to Arch Linux. As a rolling release distribution you get package upgrades all the time, but the most important breakages are nicely reported in the [Arch Linux News][5].
-
-One annoyance though is that Arch Linux removes the old kernel modules once you upgrade it. I usually notice that once I try plugging in a USB flash drive and the kernel fails to load the relevant module. Instead you’re supposed to reboot after each kernel upgrade. There are a few [hacks][6] around to get around the problem, but I haven’t been bothered enough to actually use them.
-
-Similar problems happen with other programs, commonly Firefox, cron or Samba requiring a restart after an upgrade, but annoyingly not warning you that that’s the case. [SUSE][7], which I use at work, nicely warns about such cases.
-
-For the [DDNet][8] production servers I prefer [Debian][9] over Arch Linux, so that I have a lower chance of breakage on each upgrade. For my firewall and router I used [OpenBSD][10] for its clean system, documentation and great [pf firewall][11], but right now I don’t have a need for a separate router anymore.
-
-### Window Manager
-
-Since I started out with Gentoo I quickly noticed the huge compile time of KDE, which made it a no-go for me. I looked around for more minimal solutions, and used [Openbox][12] and [Fluxbox][13] initially. At some point I jumped on the tiling window manager train in order to be more keyboard-focused and picked up [dwm][14] and [awesome][15] close to their initial releases.
-
-In the end I settled on [xmonad][16] thanks to its flexibility, extendability and being written and configured in pure [Haskell][17], a great functional programming language. One example of this is that at home I run a single 40” 4K screen, but often split it up into four virtual screens, each displaying a workspace on which my windows are automatically arranged. Of course xmonad has a [module][18] for that.
-
-[dzen][19] and [conky][20] function as a simple enough status bar for me. My entire conky config looks like this:
-
-```
-out_to_console yes
-update_interval 1
-total_run_times 0
-
-TEXT
-${downspeed eth0} ${upspeed eth0} | $cpu% ${loadavg 1} ${loadavg 2} ${loadavg 3} $mem/$memmax | ${time %F %T}
-```
-
-And gets piped straight into dzen2 with `conky | dzen2 -fn '-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-*' -bg '#000000' -fg '#ffffff' -p -e '' -x 1000 -w 920 -xs 1 -ta r`.
-
-One important feature for me is to make the terminal emit a beep sound once a job is done. This is done simply by adding a `\a` character to the `PR_TITLEBAR` variable in zsh, which is shown whenever a job is done. Of course I disable the actual beep sound by blacklisting the `pcspkr` kernel module with `echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf`. Instead the sound gets turned into an urgency by urxvt’s `URxvt.urgentOnBell: true` setting. Then xmonad has an urgency hook to capture this and I can automatically focus the currently urgent window with a key combination. In dzen I get the urgent windowspaces displayed with a nice and bright `#ff0000`.
-
-The final result in all its glory on my Laptop:
-
-[![Laptop screenshot][21]][22]
-
-I hear that [i3][23] has become quite popular in the last years, but it requires more manual window alignment instead of specifying automated methods to do it.
-
-I realize that there are also terminal multiplexers like [tmux][24], but I still require a few graphical applications, so in the end I never used them productively.
-
-### Terminal Persistency
-
-In order to keep terminals alive I use [dtach][25], which is just the detach feature of screen. In order to make every terminal on my computer detachable I wrote a [small wrapper script][26]. This means that even if I had to restart my X server I could keep all my terminals running just fine, both local and remote.
-
-### Shell & Programming
-
-Instead of [bash][27] I use [zsh][28] as my shell for its huge number of features.
-
-As a terminal emulator I found [urxvt][29] to be simple enough, support Unicode and 256 colors and has great performance. Another great feature is being able to run the urxvt client and daemon separately, so that even a large number of terminals barely takes up any memory (except for the scrollback buffer).
-
-There is only one font that looks absolutely clean and perfect to me: [Terminus][30]. Since i’s a bitmap font everything is pixel perfect and renders extremely fast and at low CPU usage. In order to switch fonts on-demand in each terminal with `CTRL-WIN-[1-7]` my ~/.Xdefaults contains:
-
-```
-URxvt.font: -xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*
-dzen2.font: -xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*
-
-URxvt.keysym.C-M-1: command:\033]50;-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-2: command:\033]50;-xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-3: command:\033]50;-xos4-terminus-medium-r-normal-*-18-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-4: command:\033]50;-xos4-terminus-medium-r-normal-*-22-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-5: command:\033]50;-xos4-terminus-medium-r-normal-*-24-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-6: command:\033]50;-xos4-terminus-medium-r-normal-*-28-*-*-*-*-*-*-*\007
-URxvt.keysym.C-M-7: command:\033]50;-xos4-terminus-medium-r-normal-*-32-*-*-*-*-*-*-*\007
-
-URxvt.keysym.C-M-n: command:\033]10;#ffffff\007\033]11;#000000\007\033]12;#ffffff\007\033]706;#00ffff\007\033]707;#ffff00\007
-URxvt.keysym.C-M-b: command:\033]10;#000000\007\033]11;#ffffff\007\033]12;#000000\007\033]706;#0000ff\007\033]707;#ff0000\007
-```
-
-For programming and writing I use [Vim][31] with syntax highlighting and [ctags][32] for indexing, as well as a few terminal windows with grep, sed and the other usual suspects for search and manipulation. This is probably not at the same level of comfort as an IDE, but allows me more automation.
-
-One problem with Vim is that you get so used to its key mappings that you’ll want to use them everywhere.
-
-[Python][33] and [Nim][34] do well as scripting languages where the shell is not powerful enough.
-
-### System Monitoring
-
-[htop][35] (look at the background of that site, it’s a live view of the server that’s hosting it) works great for getting a quick overview of what the software is currently doing. [lm_sensors][36] allows monitoring the hardware temperatures, fans and voltages. [powertop][37] is a great little tool by Intel to find power savings. [ncdu][38] lets you analyze disk usage interactively.
-
-[nmap][39], iptraf-ng, [tcpdump][40] and [Wireshark][41] are essential tools for analyzing network problems.
-
-There are of course many more great tools.
-
-### Mails & Synchronization
-
-On my home server I have a [fetchmail][42] daemon running for each email acccount that I have. Fetchmail just retrieves the incoming emails and invokes [procmail][43]:
-
-```
-#!/bin/sh
-for i in /home/deen/.fetchmail/*; do
- FETCHMAILHOME=$i /usr/bin/fetchmail -m 'procmail -d %T' -d 60
-done
-```
-
-The configuration is as simple as it could be and waits for the server to inform us of fresh emails:
-
-```
-poll imap.1und1.de protocol imap timeout 120 user "dennis@felsin9.de" password "XXX" folders INBOX keep ssl idle
-```
-
-My `.procmailrc` config contains a few rules to backup all mails and sort them into the correct directories, for example based on the mailing list id or from field in the mail header:
-
-```
-MAILDIR=/home/deen/shared/Maildir
-LOGFILE=$HOME/.procmaillog
-LOGABSTRACT=no
-VERBOSE=off
-FORMAIL=/usr/bin/formail
-NL="
-"
-
-:0wc
-* ! ? test -d /media/mailarchive/`date +%Y`
-| mkdir -p /media/mailarchive/`date +%Y`
-
-# Make backups of all mail received in format YYYY/YYYY-MM
-:0c
-/media/mailarchive/`date +%Y`/`date +%Y-%m`
-
-:0
-* ^From: .*(.*@.*.kit.edu|.*@.*.uka.de|.*@.*.uni-karlsruhe.de)
-$MAILDIR/.uni/
-
-:0
-* ^list-Id:.*lists.kit.edu
-$MAILDIR/.uni-ml/
-
-[...]
-```
-
-To send emails I use [msmtp][44], which is also great to configure:
-
-```
-account default
-host smtp.1und1.de
-tls on
-tls_trust_file /etc/ssl/certs/ca-certificates.crt
-auth on
-from dennis@felsin9.de
-user dennis@felsin9.de
-password XXX
-
-[...]
-```
-
-But so far the emails are still on the server. My documents are all stored in a directory that I synchronize between all computers using [Unison][45]. Think of Unison as a bidirectional interactive [rsync][46]. My emails are part of this documents directory and thus they end up on my desktop computers.
-
-This also means that while the emails reach my server immediately, I only fetch them on deman instead of getting instant notifications when an email comes in.
-
-From there I read the mails with [mutt][47], using the sidebar plugin to display my mail directories. The `/etc/mailcap` file is essential to display non-plaintext mails containing HTML, Word or PDF:
-
-```
-text/html;w3m -I %{charset} -T text/html; copiousoutput
-application/msword; antiword %s; copiousoutput
-application/pdf; pdftotext -layout /dev/stdin -; copiousoutput
-```
-
-### News & Communication
-
-[Newsboat][48] is a nice little RSS/Atom feed reader in the terminal. I have it running on the server in a `tach` session with about 150 feeds. Filtering feeds locally is also possible, for example:
-
-```
-ignore-article "https://forum.ddnet.tw/feed.php" "title =~ \"Map Testing •\" or title =~ \"Old maps •\" or title =~ \"Map Bugs •\" or title =~ \"Archive •\" or title =~ \"Waiting for mapper •\" or title =~ \"Other mods •\" or title =~ \"Fixes •\""
-```
-
-I use [Irssi][49] the same way for communication via IRC.
-
-### Calendar
-
-[remind][50] is a calendar that can be used from the command line. Setting new reminders is done by editing the `rem` files:
-
-```
-# One time events
-REM 2019-01-20 +90 Flight to China %b
-
-# Recurring Holidays
-REM 1 May +90 Holiday "Tag der Arbeit" %b
-REM [trigger(easterdate(year(today()))-2)] +90 Holiday "Karfreitag" %b
-
-# Time Change
-REM Nov Sunday 1 --7 +90 Time Change (03:00 -> 02:00) %b
-REM Apr Sunday 1 --7 +90 Time Change (02:00 -> 03:00) %b
-
-# Birthdays
-FSET birthday(x) "'s " + ord(year(trigdate())-x) + " birthday is %b"
-REM 16 Apr +90 MSG Andreas[birthday(1994)]
-
-# Sun
-SET $LatDeg 49
-SET $LatMin 19
-SET $LatSec 49
-SET $LongDeg -8
-SET $LongMin -40
-SET $LongSec -24
-
-MSG Sun from [sunrise(trigdate())] to [sunset(trigdate())]
-[...]
-```
-
-Unfortunately there is no Chinese Lunar calendar function in remind yet, so Chinese holidays can’t be calculated easily.
-
-I use two aliases for remind:
-
-```
-rem -m -b1 -q -g
-```
-
-to see a list of the next events in chronological order and
-
-```
-rem -m -b1 -q -cuc12 -w$(($(tput cols)+1)) | sed -e "s/\f//g" | less
-```
-
-to show a calendar fitting just the width of my terminal:
-
-![remcal][51]
-
-### Dictionary
-
-[rdictcc][52] is a little known dictionary tool that uses the excellent dictionary files from [dict.cc][53] and turns them into a local database:
-
-```
-$ rdictcc rasch
-====================[ A => B ]====================
-rasch:
- - apace
- - brisk [speedy]
- - cursory
- - in a timely manner
- - quick
- - quickly
- - rapid
- - rapidly
- - sharpish [Br.] [coll.]
- - speedily
- - speedy
- - swift
- - swiftly
-rasch [gehen]:
- - smartly [quickly]
-Rasch {n} [Zittergras-Segge]:
- - Alpine grass [Carex brizoides]
- - quaking grass sedge [Carex brizoides]
-Rasch {m} [regional] [Putzrasch]:
- - scouring pad
-====================[ B => A ]====================
-Rasch model:
- - Rasch-Modell {n}
-```
-
-### Writing and Reading
-
-I have a simple todo file containing my tasks, that is basically always sitting open in a Vim session. For work I also use the todo file as a “done” file so that I can later check what tasks I finished on each day.
-
-For writing documents, letters and presentations I use [LaTeX][54] for its superior typesetting. A simple letter in German format can be set like this for example:
-
-```
-\documentclass[paper = a4, fromalign = right]{scrlttr2}
-\usepackage{german}
-\usepackage{eurosym}
-\usepackage[utf8]{inputenc}
-\setlength{\parskip}{6pt}
-\setlength{\parindent}{0pt}
-
-\setkomavar{fromname}{Dennis Felsing}
-\setkomavar{fromaddress}{Meine Str. 1\\69181 Leimen}
-\setkomavar{subject}{Titel}
-
-\setkomavar*{enclseparator}{Anlagen}
-
-\makeatletter
-\@setplength{refvpos}{89mm}
-\makeatother
-
-\begin{document}
-\begin{letter} {Herr Soundso\\Deine Str. 2\\69121 Heidelberg}
-\opening{Sehr geehrter Herr Soundso,}
-
-Sie haben bei mir seit dem Bla Bla Bla.
-
-Ich fordere Sie hiermit zu Bla Bla Bla auf.
-
-\closing{Mit freundlichen Grüßen}
-
-\end{letter}
-\end{document}
-```
-
-Further example documents and presentations can be found over at [my private site][55].
-
-To read PDFs [Zathura][56] is fast, has Vim-like controls and even supports two different PDF backends: Poppler and MuPDF. [Evince][57] on the other hand is more full-featured for the cases where I encounter documents that Zathura doesn’t like.
-
-### Graphical Editing
-
-[GIMP][58] and [Inkscape][59] are easy choices for photo editing and interactive vector graphics respectively.
-
-In some cases [Imagemagick][60] is good enough though and can be used straight from the command line and thus automated to edit images. Similarly [Graphviz][61] and [TikZ][62] can be used to draw graphs and other diagrams.
-
-### Web Browsing
-
-As a web browser I’ve always used [Firefox][63] for its extensibility and low resource usage compared to Chrome.
-
-Unfortunately the [Pentadactyl][64] extension development stopped after Firefox switched to Chrome-style extensions entirely, so I don’t have satisfying Vim-like controls in my browser anymore.
-
-### Media Players
-
-[mpv][65] with hardware decoding allows watching videos at 5% CPU load using the `vo=gpu` and `hwdec=vaapi` config settings. `audio-channels=2` in mpv seems to give me clearer downmixing to my stereo speakers / headphones than what PulseAudio does by default. A great little feature is exiting with `Shift-Q` instead of just `Q` to save the playback location. When watching with someone with another native tongue you can use `--secondary-sid=` to show two subtitles at once, the primary at the bottom, the secondary at the top of the screen
-
-My wirelss mouse can easily be made into a remote control with mpv with a small `~/.config/mpv/input.conf`:
-
-```
-MOUSE_BTN5 run "mixer" "pcm" "-2"
-MOUSE_BTN6 run "mixer" "pcm" "+2"
-MOUSE_BTN1 cycle sub-visibility
-MOUSE_BTN7 add chapter -1
-MOUSE_BTN8 add chapter 1
-```
-
-[youtube-dl][66] works great for watching videos hosted online, best quality can be achieved with `-f bestvideo+bestaudio/best --all-subs --embed-subs`.
-
-As a music player [MOC][67] hasn’t been actively developed for a while, but it’s still a simple player that plays every format conceivable, including the strangest Chiptune formats. In the AUR there is a [patch][68] adding PulseAudio support as well. Even with the CPU clocked down to 800 MHz MOC barely uses 1-2% of a single CPU core.
-
-![moc][69]
-
-My music collection sits on my home server so that I can access it from anywhere. It is mounted using [SSHFS][70] and automount in the `/etc/fstab/`:
-
-```
-root@server:/media/media /mnt/media fuse.sshfs noauto,x-systemd.automount,idmap=user,IdentityFile=/root/.ssh/id_rsa,allow_other,reconnect 0 0
-```
-
-### Cross-Platform Building
-
-Linux is great to build packages for any major operating system except Linux itself! In the beginning I used [QEMU][71] to with an old Debian, Windows and Mac OS X VM to build for these platforms.
-
-Nowadays I switched to using chroot for the old Debian distribution (for maximum Linux compatibility), [MinGW][72] to cross-compile for Windows and [OSXCross][73] to cross-compile for Mac OS X.
-
-The script used to [build DDNet][74] as well as the [instructions for updating library builds][75] are based on this.
-
-### Backups
-
-As usual, we nearly forgot about backups. Even if this is the last chapter, it should not be an afterthought.
-
-I wrote [rrb][76] (reverse rsync backup) 10 years ago to wrap rsync so that I only need to give the backup server root SSH rights to the computers that it is backing up. Surprisingly rrb needed 0 changes in the last 10 years, even though I kept using it the entire time.
-
-The backups are stored straight on the filesystem. Incremental backups are implemented using hard links (`--link-dest`). A simple [config][77] defines how long backups are kept, which defaults to:
-
-```
-KEEP_RULES=( \
- 7 7 \ # One backup a day for the last 7 days
- 31 8 \ # 8 more backups for the last month
- 365 11 \ # 11 more backups for the last year
-1825 4 \ # 4 more backups for the last 5 years
-)
-```
-
-Since some of my computers don’t have a static IP / DNS entry and I still want to back them up using rrb I use a reverse SSH tunnel (as a systemd service) for them:
-
-```
-[Unit]
-Description=Reverse SSH Tunnel
-After=network.target
-
-[Service]
-ExecStart=/usr/bin/ssh -N -R 27276:localhost:22 -o "ExitOnForwardFailure yes" server
-KillMode=process
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-```
-
-Now the server can reach the client through `ssh -p 27276 localhost` while the tunnel is running to perform the backup, or in `.ssh/config` format:
-
-```
-Host cr-remote
- HostName localhost
- Port 27276
-```
-
-While talking about SSH hacks, sometimes a server is not easily reachable thanks to some bad routing. In that case you can route the SSH connection through another server to get better routing, in this case going through the USA to reach my Chinese server which had not been reliably reachable from Germany for a few weeks:
-
-```
-Host chn.ddnet.tw
- ProxyCommand ssh -q usa.ddnet.tw nc -q0 chn.ddnet.tw 22
- Port 22
-```
-
-### Final Remarks
-
-Thanks for reading my random collection of tools. I probably forgot many programs that I use so naturally every day that I don’t even think about them anymore. Let’s see how stable my software setup stays in the next years. If you have any questions, feel free to get in touch with me at [dennis@felsin9.de][78].
-
-Comments on [Hacker News][79].
-
---------------------------------------------------------------------------------
-
-via: https://hookrace.net/blog/linux-desktop-setup/
-
-作者:[Dennis Felsing][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: http://felsin9.de/nnis/
-[b]: https://github.com/lujun9972
-[1]: https://hookrace.net/public/linux-desktop/htop_small.png
-[2]: https://hookrace.net/public/linux-desktop/htop.png
-[3]: https://gentoo.org/
-[4]: https://www.archlinux.org/
-[5]: https://www.archlinux.org/news/
-[6]: https://www.reddit.com/r/archlinux/comments/4zrsc3/keep_your_system_fully_functional_after_a_kernel/
-[7]: https://www.suse.com/
-[8]: https://ddnet.tw/
-[9]: https://www.debian.org/
-[10]: https://www.openbsd.org/
-[11]: https://www.openbsd.org/faq/pf/
-[12]: http://openbox.org/wiki/Main_Page
-[13]: http://fluxbox.org/
-[14]: https://dwm.suckless.org/
-[15]: https://awesomewm.org/
-[16]: https://xmonad.org/
-[17]: https://www.haskell.org/
-[18]: http://hackage.haskell.org/package/xmonad-contrib-0.15/docs/XMonad-Layout-LayoutScreens.html
-[19]: http://robm.github.io/dzen/
-[20]: https://github.com/brndnmtthws/conky
-[21]: https://hookrace.net/public/linux-desktop/laptop_small.png
-[22]: https://hookrace.net/public/linux-desktop/laptop.png
-[23]: https://i3wm.org/
-[24]: https://github.com/tmux/tmux/wiki
-[25]: http://dtach.sourceforge.net/
-[26]: https://github.com/def-/tach/blob/master/tach
-[27]: https://www.gnu.org/software/bash/
-[28]: http://www.zsh.org/
-[29]: http://software.schmorp.de/pkg/rxvt-unicode.html
-[30]: http://terminus-font.sourceforge.net/
-[31]: https://www.vim.org/
-[32]: http://ctags.sourceforge.net/
-[33]: https://www.python.org/
-[34]: https://nim-lang.org/
-[35]: https://hisham.hm/htop/
-[36]: http://lm-sensors.org/
-[37]: https://01.org/powertop/
-[38]: https://dev.yorhel.nl/ncdu
-[39]: https://nmap.org/
-[40]: https://www.tcpdump.org/
-[41]: https://www.wireshark.org/
-[42]: http://www.fetchmail.info/
-[43]: http://www.procmail.org/
-[44]: https://marlam.de/msmtp/
-[45]: https://www.cis.upenn.edu/~bcpierce/unison/
-[46]: https://rsync.samba.org/
-[47]: http://www.mutt.org/
-[48]: https://newsboat.org/
-[49]: https://irssi.org/
-[50]: https://www.roaringpenguin.com/products/remind
-[51]: https://hookrace.net/public/linux-desktop/remcal.png
-[52]: https://github.com/tsdh/rdictcc
-[53]: https://www.dict.cc/
-[54]: https://www.latex-project.org/
-[55]: http://felsin9.de/nnis/research/
-[56]: https://pwmt.org/projects/zathura/
-[57]: https://wiki.gnome.org/Apps/Evince
-[58]: https://www.gimp.org/
-[59]: https://inkscape.org/
-[60]: https://imagemagick.org/Usage/
-[61]: https://www.graphviz.org/
-[62]: https://sourceforge.net/projects/pgf/
-[63]: https://www.mozilla.org/en-US/firefox/new/
-[64]: https://github.com/5digits/dactyl
-[65]: https://mpv.io/
-[66]: https://rg3.github.io/youtube-dl/
-[67]: http://moc.daper.net/
-[68]: https://aur.archlinux.org/packages/moc-pulse/
-[69]: https://hookrace.net/public/linux-desktop/moc.png
-[70]: https://github.com/libfuse/sshfs
-[71]: https://www.qemu.org/
-[72]: http://www.mingw.org/
-[73]: https://github.com/tpoechtrager/osxcross
-[74]: https://github.com/ddnet/ddnet-scripts/blob/master/ddnet-release.sh
-[75]: https://github.com/ddnet/ddnet-scripts/blob/master/ddnet-lib-update.sh
-[76]: https://github.com/def-/rrb/blob/master/rrb
-[77]: https://github.com/def-/rrb/blob/master/config.example
-[78]: mailto:dennis@felsin9.de
-[79]: https://news.ycombinator.com/item?id=18979731
diff --git a/sources/tech/20190116 Best Audio Editors For Linux.md b/sources/tech/20190116 Best Audio Editors For Linux.md
deleted file mode 100644
index d588c886e2..0000000000
--- a/sources/tech/20190116 Best Audio Editors For Linux.md
+++ /dev/null
@@ -1,156 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Best Audio Editors For Linux)
-[#]: via: (https://itsfoss.com/best-audio-editors-linux)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Best Audio Editors For Linux
-======
-
-You’ve got a lot of choices when it comes to audio editors for Linux. No matter whether you are a professional music producer or just learning to create awesome music, the audio editors will always come in handy.
-
-Well, for professional-grade usage, a [DAW][1] (Digital Audio Workstation) is always recommended. However, not everyone needs all the functionalities, so you should know about some of the most simple audio editors as well.
-
-In this article, we will talk about a couple of DAWs and basic audio editors which are available as **free and open source** solutions for Linux and (probably) for other operating systems.
-
-### Top Audio Editors for Linux
-
-![Best audio editors and DAW for Linux][2]
-
-We will not be focusing on all the functionalities that DAWs offer – but the basic audio editing capabilities. You may still consider this as the list of best DAW for Linux.
-
-**Installation instruction:** You will find all the mentioned audio editors or DAWs in your AppCenter or Software center. In case, you do not find them listed, please head to their official website for more information.
-
-#### 1\. Audacity
-
-![audacity audio editor][3]
-
-Audacity is one of the most basic yet a capable audio editor available for Linux. It is a free and open-source cross-platform tool. A lot of you must be already knowing about it.
-
-It has improved a lot when compared to the time when it started trending. I do recall that I utilized it to “try” making karaokes by removing the voice from an audio file. Well, you can still do it – but it depends.
-
-**Features:**
-
-It also supports plug-ins that include VST effects. Of course, you should not expect it to support VST Instruments.
-
- * Live audio recording through a microphone or a mixer
- * Export/Import capability supporting multiple formats and multiple files at the same time
- * Plugin support: LADSPA, LV2, Nyquist, VST and Audio Unit effect plug-ins
- * Easy editing with cut, paste, delete and copy functions.
- * Spectogram view mode for analyzing frequencies
-
-
-
-#### 2\. LMMS
-
-![][4]
-
-LMMS is a free and open source (cross-platform) digital audio workstation. It includes all the basic audio editing functionalities along with a lot of advanced features.
-
-You can mix sounds, arrange them, or create them using VST instruments. It does support them. Also, it comes baked in with some samples, presets, VST Instruments, and effects to get started. In addition, you also get a spectrum analyzer for some advanced audio editing.
-
-**Features:**
-
- * Note playback via MIDI
- * VST Instrument support
- * Native multi-sample support
- * Built-in compressor, limiter, delay, reverb, distortion and bass enhancer
-
-
-
-#### 3\. Ardour
-
-![Ardour audio editor][5]
-
-Ardour is yet another free and open source digital audio workstation. If you have an audio interface, Ardour will support it. Of course, you can add unlimited multichannel tracks. The multichannel tracks can also be routed to different mixer tapes for the ease of editing and recording.
-
-You can also import a video to it and edit the audio to export the whole thing. It comes with a lot of built-in plugins and supports VST plugins as well.
-
-**Features:**
-
- * Non-linear editing
- * Vertical window stacking for easy navigation
- * Strip silence, push-pull trimming, Rhythm Ferret for transient and note onset-based editing
-
-
-
-#### 4\. Cecilia
-
-![cecilia audio editor][6]
-
-Cecilia is not an ordinary audio editor application. It is meant to be used by sound designers or if you are just in the process of becoming one. It is technically an audio signal processing environment. It lets you create ear-bending sound out of them.
-
-You get in-build modules and plugins for sound effects and synthesis. It is tailored for a specific use – if that is what you were looking for – look no further!
-
-**Features:**
-
- * Modules to achieve more (UltimateGrainer – A state-of-the-art granulation processing, RandomAccumulator – Variable speed recording accumulator,
-UpDistoRes – Distortion with upsampling and resonant lowpass filter)
- * Automatic Saving of modulations
-
-
-
-#### 5\. Mixxx
-
-![Mixxx audio DJ ][7]
-
-If you want to mix and record something while being able to have a virtual DJ tool, [Mixxx][8] would be a perfect tool. You get to know the BPM, key, and utilize the master sync feature to match the tempo and beats of a song. Also, do not forget that it is yet another free and open source application for Linux!
-
-It supports custom DJ equipment as well. So, if you have one or a MIDI – you can record your live mixes using this tool.
-
-**Features**
-
- * Broadcast and record DJ Mixes of your song
- * Ability to connect your equipment and perform live
- * Key detection and BPM detection
-
-
-
-#### 6\. Rosegarden
-
-![rosegarden audio editor][9]
-
-Rosegarden is yet another impressive audio editor for Linux which is free and open source. It is neither a fully featured DAW nor a basic audio editing tool. It is a mixture of both with some scaled down functionalities.
-
-I wouldn’t recommend this for professionals but if you have a home studio or just want to experiment, this would be one of the best audio editors for Linux to have installed.
-
-**Features:**
-
- * Music notation editing
- * Recording, Mixing, and samples
-
-
-
-### Wrapping Up
-
-These are some of the best audio editors you could find out there for Linux. No matter whether you need a DAW, a cut-paste editing tool, or a basic mixing/recording audio editor, the above-mentioned tools should help you out.
-
-Did we miss any of your favorite? Let us know about it in the comments below.
-
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/best-audio-editors-linux
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://en.wikipedia.org/wiki/Digital_audio_workstation
-[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors-800x450.jpeg?resize=800%2C450&ssl=1
-[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/audacity-audio-editor.jpg?fit=800%2C591&ssl=1
-[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/lmms-daw.jpg?fit=800%2C472&ssl=1
-[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/ardour-audio-editor.jpg?fit=800%2C639&ssl=1
-[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/cecilia.jpg?fit=800%2C510&ssl=1
-[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/mixxx.jpg?fit=800%2C486&ssl=1
-[8]: https://itsfoss.com/dj-mixxx-2/
-[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/rosegarden.jpg?fit=800%2C391&ssl=1
-[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors.jpeg?fit=800%2C450&ssl=1
diff --git a/sources/tech/20190124 ffsend - Easily And Securely Share Files From Linux Command Line Using Firefox Send Client.md b/sources/tech/20190124 ffsend - Easily And Securely Share Files From Linux Command Line Using Firefox Send Client.md
deleted file mode 100644
index fcbdd3c5c7..0000000000
--- a/sources/tech/20190124 ffsend - Easily And Securely Share Files From Linux Command Line Using Firefox Send Client.md
+++ /dev/null
@@ -1,330 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (ffsend – Easily And Securely Share Files From Linux Command Line Using Firefox Send Client)
-[#]: via: (https://www.2daygeek.com/ffsend-securely-share-files-folders-from-linux-command-line-using-firefox-send-client/)
-[#]: author: (Vinoth Kumar https://www.2daygeek.com/author/vinoth/)
-
-ffsend – Easily And Securely Share Files From Linux Command Line Using Firefox Send Client
-======
-
-Linux users were preferred to go with scp or rsync for files or folders copy.
-
-However, so many new options are coming to Linux because it’s a opensource.
-
-Anyone can develop a secure software for Linux.
-
-We had written multiple articles in our site in the past about this topic.
-
-Even, today we are going to discuss the same kind of topic called ffsend.
-
-Those are **[OnionShare][1]** , **[Magic Wormhole][2]** , **[Transfer.sh][3]** and **[Dcp – Dat Copy][4]**.
-
-### What’s ffsend?
-
-[ffsend][5] is a command line Firefox Send client that allow users to transfer and receive files and folders through command line.
-
-It allow us to easily and securely share files and directories from the command line through a safe, private and encrypted link using a single simple command.
-
-Files are shared using the Send service and the allowed file size is up to 2GB.
-
-Others are able to download these files with this tool, or through their web browser.
-
-All files are always encrypted on the client, and secrets are never shared with the remote host.
-
-Additionally you can add a password for the file upload.
-
-The uploaded files will be removed after the download (default count is 1 up to 10) or after 24 hours. This will make sure that your files does not remain online forever.
-
-This tool is currently in the alpha phase. Use at your own risk. Also, only limited installation options are available right now.
-
-### ffsend Features:
-
- * Fully featured and friendly command line tool
- * Upload and download files and directories securely
- * Always encrypted on the client
- * Additional password protection, generation and configurable download limits
- * Built-in file and directory archiving and extraction
- * History tracking your files for easy management
- * Ability to use your own Send host
- * Inspect or delete shared files
- * Accurate error reporting
- * Low memory footprint, due to encryption and download/upload streaming
- * Intended to be used in scripts without interaction
-
-
-
-### How To Install ffsend in Linux?
-
-There is no package for each distributions except Debian and Arch Linux systems. However, we can easily get this utility by downloading the prebuilt appropriate binaries file based on the operating system and architecture.
-
-Run the below command to download the latest available version for your operating system.
-
-```
-$ wget https://github.com/timvisee/ffsend/releases/download/v0.1.2/ffsend-v0.1.2-linux-x64.tar.gz
-```
-
-Extract the tar archive using the following command.
-
-```
-$ tar -xvf ffsend-v0.1.2-linux-x64.tar.gz
-```
-
-Run the following command to identify your path variable.
-
-```
-$ echo $PATH
-/home/daygeek/.cargo/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
-```
-
-As i told previously, just move the executable file to your path directory.
-
-```
-$ sudo mv ffsend /usr/local/sbin
-```
-
-Run the `ffsend` command alone to get the basic usage information.
-
-```
-$ ffsend
-ffsend 0.1.2
-Usage: ffsend [FLAGS] ...
-
-Easily and securely share files from the command line.
-A fully featured Firefox Send client.
-
-Missing subcommand. Here are the most used:
- ffsend upload ...
- ffsend download ...
-
-To show all subcommands, features and other help:
- ffsend help [SUBCOMMAND]
-```
-
-For Arch Linux based users can easily install it with help of **[AUR Helper][6]** , as this package is available in AUR repository.
-
-```
-$ yay -S ffsend
-```
-
-For **`Debian/Ubuntu`** systems, use **[DPKG Command][7]** to install ffsend.
-
-```
-$ wget https://github.com/timvisee/ffsend/releases/download/v0.1.2/ffsend_0.1.2_amd64.deb
-$ sudo dpkg -i ffsend_0.1.2_amd64.deb
-```
-
-### How To Send A File Using ffsend?
-
-It’s not complicated. We can easily send a file using simple syntax.
-
-**Syntax:**
-
-```
-$ ffsend upload [/Path/to/the/file/name]
-```
-
-In the following example, we are going to upload a file called `passwd-up1.sh`. Once you upload the file then you will be getting the unique URL.
-
-```
-$ ffsend upload passwd-up1.sh --copy
-Upload complete
-Share link: https://send.firefox.com/download/a4062553f4/#yy2_VyPaUMG5HwXZzYRmpQ
-```
-
-![][9]
-
-Just download the above unique URL to get the file in any remote system.
-
-**Syntax:**
-
-```
-$ ffsend download [Generated URL]
-```
-
-Output for the above command.
-
-```
-$ ffsend download https://send.firefox.com/download/a4062553f4/#yy2_VyPaUMG5HwXZzYRmpQ
-Download complete
-```
-
-![][10]
-
-Use the following syntax format for directory upload.
-
-```
-$ ffsend upload [/Path/to/the/Directory] --copy
-```
-
-In this example, we are going to upload `2g` directory.
-
-```
-$ ffsend upload /home/daygeek/2g --copy
-You've selected a directory, only a single file may be uploaded.
-Archive the directory into a single file? [Y/n]: y
-Archiving...
-Upload complete
-Share link: https://send.firefox.com/download/90aa5cfe67/#hrwu6oXZRG2DNh8vOc3BGg
-```
-
-Just download the above generated the unique URL to get a folder in any remote system.
-
-```
-$ ffsend download https://send.firefox.com/download/90aa5cfe67/#hrwu6oXZRG2DNh8vOc3BGg
-You're downloading an archive, extract it into the selected directory? [Y/n]: y
-Extracting...
-Download complete
-```
-
-As this already send files through a safe, private, and encrypted link. However, if you would like to add a additional security at your level. Yes, you can add a password for a file.
-
-```
-$ ffsend upload file-copy-rsync.sh --copy --password
-Password:
-Upload complete
-Share link: https://send.firefox.com/download/0742d24515/#P7gcNiwZJ87vF8cumU71zA
-```
-
-It will prompt you to update a password when you are trying to download a file in the remote system.
-
-```
-$ ffsend download https://send.firefox.com/download/0742d24515/#P7gcNiwZJ87vF8cumU71zA
-This file is protected with a password.
-Password:
-Download complete
-```
-
-Alternatively you can limit a download speed by providing the download speed while uploading a file.
-
-```
-$ ffsend upload file-copy-scp.sh --copy --downloads 10
-Upload complete
-Share link: https://send.firefox.com/download/23cb923c4e/#LVg6K0CIb7Y9KfJRNZDQGw
-```
-
-Just download the above unique URL to get a file in any remote system.
-
-```
-ffsend download https://send.firefox.com/download/23cb923c4e/#LVg6K0CIb7Y9KfJRNZDQGw
-Download complete
-```
-
-If you want to see more details about the file, use the following format. It will shows you the file name, file size, Download counts and when it will going to expire.
-
-**Syntax:**
-
-```
-$ ffsend info [Generated URL]
-
-$ ffsend info https://send.firefox.com/download/23cb923c4e/#LVg6K0CIb7Y9KfJRNZDQGw
-ID: 23cb923c4e
-Name: file-copy-scp.sh
-Size: 115 B
-MIME: application/x-sh
-Downloads: 3 of 10
-Expiry: 23h58m (86280s)
-```
-
-You can view your transaction history using the following format.
-
-```
-$ ffsend history
-# LINK EXPIRY
-1 https://send.firefox.com/download/23cb923c4e/#LVg6K0CIb7Y9KfJRNZDQGw 23h57m
-2 https://send.firefox.com/download/0742d24515/#P7gcNiwZJ87vF8cumU71zA 23h55m
-3 https://send.firefox.com/download/90aa5cfe67/#hrwu6oXZRG2DNh8vOc3BGg 23h52m
-4 https://send.firefox.com/download/a4062553f4/#yy2_VyPaUMG5HwXZzYRmpQ 23h46m
-5 https://send.firefox.com/download/74ff30e43e/#NYfDOUp_Ai-RKg5g0fCZXw 23h44m
-6 https://send.firefox.com/download/69afaab1f9/#5z51_94jtxcUCJNNvf6RcA 23h43m
-```
-
-If you don’t want the link anymore then we can delete it.
-
-**Syntax:**
-
-```
-$ ffsend delete [Generated URL]
-
-$ ffsend delete https://send.firefox.com/download/69afaab1f9/#5z51_94jtxcUCJNNvf6RcA
-File deleted
-```
-
-Alternatively this can be done using firefox browser by opening the page .
-
-Just drag and drop a file to upload it.
-![][11]
-
-Once the file is downloaded, it will show you that 100% download completed.
-![][12]
-
-To check other possible options, navigate to man page or help page.
-
-```
-$ ffsend --help
-ffsend 0.1.2
-Tim Visee
-Easily and securely share files from the command line.
-A fully featured Firefox Send client.
-
-USAGE:
- ffsend [FLAGS] [OPTIONS] [SUBCOMMAND]
-
-FLAGS:
- -f, --force Force the action, ignore warnings
- -h, --help Prints help information
- -i, --incognito Don't update local history for actions
- -I, --no-interact Not interactive, do not prompt
- -q, --quiet Produce output suitable for logging and automation
- -V, --version Prints version information
- -v, --verbose Enable verbose information and logging
- -y, --yes Assume yes for prompts
-
-OPTIONS:
- -H, --history Use the specified history file [env: FFSEND_HISTORY]
- -t, --timeout Request timeout (0 to disable) [env: FFSEND_TIMEOUT]
- -T, --transfer-timeout Transfer timeout (0 to disable) [env: FFSEND_TRANSFER_TIMEOUT]
-
-SUBCOMMANDS:
- upload Upload files [aliases: u, up]
- download Download files [aliases: d, down]
- debug View debug information [aliases: dbg]
- delete Delete a shared file [aliases: del]
- exists Check whether a remote file exists [aliases: e]
- help Prints this message or the help of the given subcommand(s)
- history View file history [aliases: h]
- info Fetch info about a shared file [aliases: i]
- parameters Change parameters of a shared file [aliases: params]
- password Change the password of a shared file [aliases: pass, p]
-
-The public Send service that is used as default host is provided by Mozilla.
-This application is not affiliated with Mozilla, Firefox or Firefox Send.
-```
-
---------------------------------------------------------------------------------
-
-via: https://www.2daygeek.com/ffsend-securely-share-files-folders-from-linux-command-line-using-firefox-send-client/
-
-作者:[Vinoth Kumar][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.2daygeek.com/author/vinoth/
-[b]: https://github.com/lujun9972
-[1]: https://www.2daygeek.com/onionshare-secure-way-to-share-files-sharing-tool-linux/
-[2]: https://www.2daygeek.com/wormhole-securely-share-files-from-linux-command-line/
-[3]: https://www.2daygeek.com/transfer-sh-easy-fast-way-share-files-over-internet-from-command-line/
-[4]: https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/
-[5]: https://github.com/timvisee/ffsend
-[6]: https://www.2daygeek.com/category/aur-helper/
-[7]: https://www.2daygeek.com/dpkg-command-to-manage-packages-on-debian-ubuntu-linux-mint-systems/
-[8]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[9]: https://www.2daygeek.com/wp-content/uploads/2019/01/ffsend-easily-and-securely-share-files-from-linux-command-line-using-firefox-send-client-1.png
-[10]: https://www.2daygeek.com/wp-content/uploads/2019/01/ffsend-easily-and-securely-share-files-from-linux-command-line-using-firefox-send-client-2.png
-[11]: https://www.2daygeek.com/wp-content/uploads/2019/01/ffsend-easily-and-securely-share-files-from-linux-command-line-using-firefox-send-client-3.png
-[12]: https://www.2daygeek.com/wp-content/uploads/2019/01/ffsend-easily-and-securely-share-files-from-linux-command-line-using-firefox-send-client-4.png
diff --git a/sources/tech/20190204 Getting started with Git- Terminology 101.md b/sources/tech/20190204 Getting started with Git- Terminology 101.md
new file mode 100644
index 0000000000..0b76cd3a43
--- /dev/null
+++ b/sources/tech/20190204 Getting started with Git- Terminology 101.md
@@ -0,0 +1,157 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting started with Git: Terminology 101)
+[#]: via: (https://opensource.com/article/19/2/git-terminology)
+[#]: author: (Matthew Broberg https://opensource.com/users/mbbroberg)
+
+Getting started with Git: Terminology 101
+======
+Want to learn Git? Check out this quick summary of the most important
+terms and commands.
+![Digital hand surrounding by objects, bike, light bulb, graphs][1]
+
+Version control is an important tool for anyone looking to track their changes these days. It's especially helpful for programmers, sysadmins, and site reliability engineers (SREs) alike. The promise of recovering from mistakes to a known good state is a huge win and a touch friendlier than the previous strategy of adding **`.old`** to a copied file.
+
+But learning Git is often oversimplified by well-meaning peers telling everyone to "get into open source." Before you know it, someone asks for a _pull request_ or *merge request *where you _rebase_ from _upstream_ before they can merge from your _remote_—and be sure to remove _merge commits_. Whatever well-working contribution you want to give back to an open source project feels much further from being added when you look at all these words you don't know.
+
+![Git Cheat Sheet cover image][2]
+
+[Download][3] our
+Git cheat sheet.
+
+If you have a month or two and enough curiosity, [Git SCM][4] is the definitive source for all the terms you need to learn. If you're looking for a summary from the trenches, keep reading.
+
+### Reminder: What's a commit?
+
+The toughest part of Git for me to internalize was the simplest idea of Git: _a commit is a collection of content, a message about how you got there, and the commits that came before it_. There's no inherent code release strategy or even strong opinions built in. The content doesn't even have to be code—it is _anything_ you want to add to the repository. The commit message annotates that content.
+
+I like to think of a commit message as a gift to your future self: it may mention the files you edited, but more importantly it reminds you of your intention for changing those files. Adding more about why you have edited what you have helps anyone who uses your repository, even when that person is you.
+
+### There's no place like 'origin/master'
+
+Knowing where you are in a Git project starts with thinking of a tree. All Git projects have a root, similar to the idea of a filesystem's root directory. All commits branch off from that root. In this way, a branch is only a pointer to a commit. By convention, **master** is the default name for the default branch in your root directory.
+
+Since Git is a distributed version control system, where the same codebase is distributed to multiple locations, people often use the term "repository" as a way of talking about all copies of the same project. There is the _local repository_, where you edit your code (more on that in a minute), and the _remote repository_, the place where you want to send it after you're finished. Remotes can be anywhere, even on the same computer where your local repository is located, but they are often hosted on repository services like GitLab or GitHub.
+
+### What's the pwd of Git commands?
+
+While it's not an official selling point, being lost is part of the fun of a Git repository. You can find your way by running through this reliable set of commands:
+
+ * `git branch`—to find which branch you're on
+
+ * `git log`—to see what commit you're on
+
+ * `git status`—to see what edits you've made since the last commit
+
+ * `git remote`—to see what remote repository you're tracking
+
+
+
+
+Orienting yourself using these commands will give you a sense of direction when you're stuck.
+
+### Have I stashed or cached my commit?
+
+The code local to your computer is colloquially called your _workspace_. What is not immediately obvious is that you have two (yes, two!) other locations local to you when you are in a Git repository: _index_ and _stash_. When you write some content and then **add** it, you are adding it to the index, which is the cached content that is ready to commit. There are times when you have files in the index that you are not ready to commit, but you want to view another branch. That's where the stash comes in handy. You can store indexed-but-not-yet-committed files to the stash using `git stash`. When you're ready to retrieve the file, run `git stash pop` to bring changes back into the index.
+
+Here are some commands you'll need to use your stash and cache.
+
+ * `git diff ..origin/master`—to show the difference between the most recent local commit and the remote called "origin" and its branch called "master"
+
+ * `git diff --cached`—to show any differences between the most recent local commit and what has been added to the local index
+
+ * `git stash`—to place indexed (added but not committed) files in the stash stack
+
+ * `git stash list`—to show what changes are in the stash stack
+
+ * `git stash pop`—to take the most recent change off the stash stack
+
+
+
+
+### HEADless horseman
+
+Git is a collection of all kinds of metaphors. When I think of where the HEAD is, I think of train lines. If you end up in a _detached HEAD_ mode, it means you're off the metaphorical rails.
+
+HEAD is a pointer to your most recent commit in the currently checked-out branch. The default "checkout" is when you create a Git repository and land on the **master** branch. Every time you create or change to another branch, you are on that branch line. If you `git checkout ` somewhere in your current branch, HEAD will move to that commit. If there is no commit history connecting your current commit to the commit you checked out, then you'll be in a detached HEAD state. If you ever lose your head finding where HEAD is, you can always `git reset --hard origin/master` to delete changes and get back to a known state. _Warning: this will delete any changes you have made since you last pushed to master._
+
+### Are you upstream or downstream?
+
+The local copy of your project is considered your local repository. It may or may not have a remote repository—the place where you have a copy of your repository for collaboration or safekeeping. There may also be an _upstream_ repository where a third copy of the project is hosted and maintained by a different set of contributors.
+
+For instance, let's say I want to contribute to Kubernetes. I would first fork the **kubernetes/kubernetes** project to my account, **mbbroberg/kubernetes**. I would then clone my project to my local workspace. In this scenario, my local clone is my local repository, **mbbroberg/kubernetes** is my remote repository, and **kubernetes/kubernetes** is the upstream.
+
+### Merging the metaphors
+
+The visual of a root system merges with the train tracks image when you get deeper into Git branches. Branches are often used as ways of developing a new feature that you eventually want to _merge_ into the master branch. When doing this, Git keeps the common history of commits in order then appends the new commits for your branch to the history. There are a ton of nuances to this process—whether to rebase or not, whether to add a merge commit or not—which [Brent Laster][5] explores in greater detail in "[How to reset, revert, and return to previous states in Git][6]."
+
+### I think I Git it now
+
+There is a ton of terminology and a lot to explore to master the world of Git commands. I hope this first-person exploration of how I use the terms day-to-day helps you acclimate to it all. If you ever feel stuck or frustrated, feel free to reach out to me on Twitter [@mbbroberg][7].
+
+#### To review:
+
+ * **Commit**—stores the current contents of the index in a new commit along with a log message from the user describing the changes
+
+ * **Branch**—a pointer to a commit
+
+ * **Master**—the default name for the first branch
+
+ * **HEAD**—a pointer to the most recent commit on the current branch
+
+ * **Merge**—joining two or more commit histories
+
+ * **Workspace**—the colloquial name for your local copy of a Git repository
+
+ * **Working tree**—the current branch in your workspace; you see this in `git status` output all the time
+
+ * **Cache**—a space intended to temporarily store uncommitted changes
+
+ * **Index**—the cache where changes are stored before they are committed
+
+ * **Tracked and untracked files**—files either in the index cache or not yet added to it
+
+ * **Stash**—another cache, that acts as a stack, where changes can be stored without committing them
+
+ * **Origin**—the default name for a remote repository
+
+ * **Local repository**—another term for where you keep your copy of a Git repository on your workstation
+
+ * **Remote repository**—a secondary copy of a Git repository where you push changes for collaboration or backup
+
+ * **Upstream repository**—the colloquial term for a remote repository that you track
+
+ * **Pull request**—a GitHub-specific term to let others know about changes you've pushed to a branch in a repository
+
+ * **Merge request**—a GitLab-specific term to let others know about changes you've pushed to a branch in a repository
+
+ * **'origin/master'**—the default setting for a remote repository and its primary branch
+
+
+
+
+Postscript: Puns are one of the best parts of Git. Have fun with them.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/2/git-terminology
+
+作者:[Matthew Broberg][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mbbroberg
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
+[2]: https://opensource.com/sites/default/files/uploads/git_cheat_sheet_cover.jpg (Git Cheat Sheet cover image)
+[3]: https://opensource.com/downloads/cheat-sheet-git
+[4]: https://git-scm.com/about
+[5]: https://opensource.com/users/bclaster
+[6]: https://opensource.com/article/18/6/git-reset-revert-rebase-commands
+[7]: https://twitter.com/mbbroberg
diff --git a/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md b/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md
deleted file mode 100644
index e8722c63cc..0000000000
--- a/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md
+++ /dev/null
@@ -1,146 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Installing Kali Linux on VirtualBox: Quickest & Safest Way)
-[#]: via: (https://itsfoss.com/install-kali-linux-virtualbox/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Installing Kali Linux on VirtualBox: Quickest & Safest Way
-======
-
-_**This tutorial shows you how to install Kali Linux on Virtual Box in Windows and Linux in the quickest way possible.**_
-
-[Kali Linux][1] is one of the [best Linux distributions for hacking][2] and security enthusiasts.
-
-Since it deals with a sensitive topic like hacking, it’s like a double-edged sword. We have discussed it in the detailed Kali Linux review in the past so I am not going to bore you with the same stuff again.
-
-While you can install Kali Linux by replacing the existing operating system, using it via a virtual machine would be a better and safer option.
-
-With Virtual Box, you can use Kali Linux as a regular application in your Windows/Linux system. It’s almost the same as running VLC or a game in your system.
-
-Using Kali Linux in a virtual machine is also safe. Whatever you do inside Kali Linux will NOT impact your ‘host system’ (i.e. your original Windows or Linux operating system). Your actual operating system will be untouched and your data in the host system will be safe.
-
-![][3]
-
-### How to install Kali Linux on VirtualBox
-
-I’ll be using [VirtualBox][4] here. It is a wonderful open source virtualization solution for just about anyone (professional or personal use). It’s available free of cost.
-
-In this tutorial, we will talk about Kali Linux in particular but you can install almost any other OS whose ISO file exists or a pre-built virtual machine save file is available.
-
-**Note:** _The same steps apply for Windows/Linux running VirtualBox._
-
-As I already mentioned, you can have either Windows or Linux installed as your host. But, in this case, I have Windows 10 installed (don’t hate me!) where I try to install Kali Linux in VirtualBox step by step.
-
-And, the best part is – even if you happen to use a Linux distro as your primary OS, the same steps will be applicable!
-
-Wondering, how? Let’s see…
-
-[Subscribe to Our YouTube Channel for More Linux Videos][5]
-
-### Step by Step Guide to install Kali Linux on VirtualBox
-
-_We are going to use a custom Kali Linux image made for VirtualBox specifically. You can also download the ISO file for Kali Linux and create a new virtual machine – but why do that when you have an easy alternative?_
-
-#### 1\. Download and install VirtualBox
-
-The first thing you need to do is to download and install VirtualBox from Oracle’s official website.
-
-[Download VirtualBox][6]
-
-Once you download the installer, just double click on it to install VirtualBox. It’s the same for [installing VirtualBox on Ubuntu][7]/Fedora Linux as well.
-
-#### 2\. Download ready-to-use virtual image of Kali Linux
-
-After installing it successfully, head to [Offensive Security’s download page][8] to download the VM image for VirtualBox. If you change your mind to utilize [VMware][9], that is available too.
-
-![][10]
-
-As you can see the file size is well over 3 GB, you should either use the torrent option or download it using a [download manager][11].
-
-[Kali Linux Virtual Image][8]
-
-#### 3\. Install Kali Linux on Virtual Box
-
-Once you have installed VirtualBox and downloaded the Kali Linux image, you just need to import it to VirtualBox in order to make it work.
-
-Here’s how to import the VirtualBox image for Kali Linux:
-
-**Step 1** : Launch VirtualBox. You will notice an **Import** button – click on it
-
-![Click on Import button][12]
-
-**Step 2:** Next, browse the file you just downloaded and choose it to be imported (as you can see in the image below). The file name should start with ‘kali linux‘ and end with . **ova** extension.
-
-![Importing Kali Linux image][13]
-
-**S** Once selected, proceed by clicking on **Next**.
-
-**Step 3** : Now, you will be shown the settings for the virtual machine you are about to import. So, you can customize them or not – that is your choice. It is okay if you go with the default settings.
-
-You need to select a path where you have sufficient storage available. I would never recommend the **C:** drive on Windows.
-
-![Import hard drives as VDI][14]
-
-Here, the hard drives as VDI refer to virtually mount the hard drives by allocating the storage space set.
-
-After you are done with the settings, hit **Import** and wait for a while.
-
-**Step 4:** You will now see it listed. So, just hit **Start** to launch it.
-
-You might get an error at first for USB port 2.0 controller support, you can disable it to resolve it or just follow the on-screen instruction of installing an additional package to fix it. And, you are done!
-
-![Kali Linux running in VirtualBox][15]
-
-The default username in Kali Linux is root and the default password is toor. You should be able to login to the system with it.
-
-Do note that you should [update Kali Linux][16] before trying to install a new applications or trying to hack your neighbor’s WiFi.
-
-I hope this guide helps you easily install Kali Linux on Virtual Box. Of course, Kali Linux has a lot of useful tools in it for penetration testing – good luck with that!
-
-**Tip** : Both Kali Linux and Ubuntu are Debian-based. If you face any issues or error with Kali Linux, you may follow the tutorials intended for Ubuntu or Debian on the internet.
-
-### Bonus: Free Kali Linux Guide Book
-
-If you are just starting with Kali Linux, it will be a good idea to know how to use Kali Linux.
-
-Offensive Security, the company behind Kali Linux, has created a guide book that explains the basics of Linux, basics of Kali Linux, configuration, setups. It also has a few chapters on penetration testing and security tools.
-
-Basically, it has everything you need to get started with Kali Linux. And the best thing is that the book is available to download for free.
-
-[Download Kali Linux Revealed for FREE][17]
-
-Let us know in the comments below if you face an issue or simply share your experience with Kali Linux on VirtualBox.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/install-kali-linux-virtualbox/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://www.kali.org/
-[2]: https://itsfoss.com/linux-hacking-penetration-testing/
-[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box.png?resize=800%2C450&ssl=1
-[4]: https://www.virtualbox.org/
-[5]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
-[6]: https://www.virtualbox.org/wiki/Downloads
-[7]: https://itsfoss.com/install-virtualbox-ubuntu/
-[8]: https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/
-[9]: https://itsfoss.com/install-vmware-player-ubuntu-1310/
-[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box-image.jpg?resize=800%2C347&ssl=1
-[11]: https://itsfoss.com/4-best-download-managers-for-linux/
-[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-import-kali-linux.jpg?ssl=1
-[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-linux-next.jpg?ssl=1
-[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-kali-linux-settings.jpg?ssl=1
-[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-on-windows-virtualbox.jpg?resize=800%2C429&ssl=1
-[16]: https://linuxhandbook.com/update-kali-linux/
-[17]: https://kali.training/downloads/Kali-Linux-Revealed-1st-edition.pdf
diff --git a/sources/tech/20190212 Top 10 Best Linux Media Server Software.md b/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
index 8fcea6343a..79b9dcb3bc 100644
--- a/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
+++ b/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: ( )
+[#]: translator: (kodark)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
diff --git a/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md b/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md
deleted file mode 100644
index 615f7620ed..0000000000
--- a/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md
+++ /dev/null
@@ -1,135 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to build a WiFi picture frame with a Raspberry Pi)
-[#]: via: (https://opensource.com/article/19/2/wifi-picture-frame-raspberry-pi)
-[#]: author: (Manuel Dewald https://opensource.com/users/ntlx)
-
-How to build a WiFi picture frame with a Raspberry Pi
-======
-DIY a digital photo frame that streams photos from the cloud.
-
-
-
-Digital picture frames are really nice because they let you enjoy your photos without having to print them out. Plus, adding and removing digital files is a lot easier than opening a traditional frame and swapping the picture inside when you want to display a new photo. Even so, it's still a bit of overhead to remove your SD card, USB stick, or other storage from a digital picture frame, plug it into your computer, and copy new pictures onto it.
-
-An easier option is a digital picture frame that gets its pictures over WiFi, for example from a cloud service. Here's how to make one.
-
-### Gather your materials
-
- * Old [TFT][1] LCD screen
- * HDMI-to-DVI cable (as the TFT screen supports DVI)
- * Raspberry Pi 3
- * Micro SD card
- * Raspberry Pi power supply
- * Keyboard
- * Mouse (optional)
-
-
-
-Connect the Raspberry Pi to the display using the cable and attach the power supply.
-
-### Install Raspbian
-
-**sudo raspi-config**. There I change the hostname (e.g., to **picframe** ) in Network Options and enable SSH to work remotely on the Raspberry Pi in Interfacing Options. Connect to the Raspberry Pi using (for example) .
-
-### Build and install the cloud client
-
-Download and flash Raspbian to the Micro SD card by following these [directions][2] . Plug the Micro SD card into the Raspberry Pi, boot it up, and configure your WiFi. My first action after a new Raspbian installation is usually running. There I change the hostname (e.g., to) in Network Options and enable SSH to work remotely on the Raspberry Pi in Interfacing Options. Connect to the Raspberry Pi using (for example)
-
-I use [Nextcloud][3] to synchronize my pictures, but you could use NFS, [Dropbox][4], or whatever else fits your needs to upload pictures to the frame.
-
-If you use Nextcloud, get a client for Raspbian by following these [instructions][5]. This is handy for placing new pictures on your picture frame and will give you the client application you may be familiar with on a desktop PC. When connecting the client application to your Nextcloud server, make sure to select only the folder where you'll store the images you want to be displayed on the picture frame.
-
-### Set up the slideshow
-
-The easiest way I've found to set up the slideshow is with a [lightweight slideshow project][6] built for exactly this purpose. There are some alternatives, like configuring a screensaver, but this application appears to be the simplest to set up.
-
-On your Raspberry Pi, download the binaries from the latest release, unpack them, and move them to an executable folder:
-
-```
-wget https://github.com/NautiluX/slide/releases/download/v0.9.0/slide_pi_stretch_0.9.0.tar.gz
-tar xf slide_pi_stretch_0.9.0.tar.gz
-mv slide_0.9.0/slide /usr/local/bin/
-```
-
-Install the dependencies:
-
-```
-sudo apt install libexif12 qt5-default
-```
-
-Run the slideshow by executing the command below (don't forget to modify the path to your images). If you access your Raspberry Pi via SSH, set the **DISPLAY** variable to start the slideshow on the display attached to the Raspberry Pi.
-
-```
-DISPLAY=:0.0 slide -p /home/pi/nextcloud/picframe
-```
-
-### Autostart the slideshow
-
-To autostart the slideshow on Raspbian Stretch, create the following folder and add an **autostart** file to it:
-
-```
-mkdir -p /home/pi/.config/lxsession/LXDE/
-vi /home/pi/.config/lxsession/LXDE/autostart
-```
-
-Insert the following commands to autostart your slideshow. The **slide** command can be adjusted to your needs:
-
-```
-@xset s noblank
-@xset s off
-@xset -dpms
-@slide -p -t 60 -o 200 -p /home/pi/nextcloud/picframe
-```
-
-Disable screen blanking, which the Raspberry Pi normally does after 10 minutes, by editing the following file:
-
-```
-vi /etc/lightdm/lightdm.conf
-```
-
-and adding these two lines to the end:
-
-```
-[SeatDefaults]
-xserver-command=X -s 0 -dpms
-```
-
-### Configure a power-on schedule
-
-You can schedule your picture frame to turn on and off at specific times by using two simple cronjobs. For example, say you want it to turn on automatically at 7 am and turn off at 11 pm. Run **crontab -e** and insert the following two lines.
-
-```
-0 23 * * * /opt/vc/bin/tvservice -o
-
-0 7 * * * /opt/vc/bin/tvservice -p && sudo systemctl restart display-manager
-```
-
-Note that this won't turn the Raspberry Pi power's on and off; it will just turn off HDMI, which will turn the screen off. The first line will power off HDMI at 11 pm. The second line will bring the display back up and restart the display manager at 7 am.
-
-### Add a final touch
-
-By following these simple steps, you can create your own WiFi picture frame. If you want to give it a nicer look, build a wooden frame for the display.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/2/wifi-picture-frame-raspberry-pi
-
-作者:[Manuel Dewald][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ntlx
-[b]: https://github.com/lujun9972
-[1]: https://en.wikipedia.org/wiki/Thin-film-transistor_liquid-crystal_display
-[2]: https://www.raspberrypi.org/documentation/installation/installing-images/README.md
-[3]: https://nextcloud.com/
-[4]: http://dropbox.com/
-[5]: https://github.com/nextcloud/client_theming#building-on-debian
-[6]: https://github.com/NautiluX/slide/releases/tag/v0.9.0
diff --git a/sources/tech/20190218 Talk, then code.md b/sources/tech/20190218 Talk, then code.md
deleted file mode 100644
index 18ed81e43c..0000000000
--- a/sources/tech/20190218 Talk, then code.md
+++ /dev/null
@@ -1,64 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Talk, then code)
-[#]: via: (https://dave.cheney.net/2019/02/18/talk-then-code)
-[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
-
-Talk, then code
-======
-
-The open source projects that I contribute to follow a philosophy which I describe as _talk, then code_. I think this is generally a good way to develop software and I want to spend a little time talking about the benefits of this methodology.
-
-### Avoiding hurt feelings
-
-The most important reason for discussing the change you want to make is it avoids hurt feelings. Often I see a contributor work hard in isolation on a pull request only to find their work is rejected. This can be for a bunch of reasons; the PR is too large, the PR doesn’t follow the local style, the PR fixes an issue which wasn’t important to the project or was recently fixed indirectly, and many more.
-
-The underlying cause of all these issues is a lack of communication. The goal of the _talk, then code_ philosophy is not to impede or frustrate, but to ensure that a feature lands correctly the first time, without incurring significant maintenance debt, and neither the author of the change, or the reviewer, has to carry the emotional burden of dealing with hurt feelings when a change appears out of the blue with an implicit “well, I’ve done the work, all you have to do is merge it, right?”
-
-### What does discussion look like?
-
-Every new feature or bug fix should be discussed with the maintainer(s) of the project before work commences. It’s fine to experiment privately, but do not send a change without discussing it first.
-
-The definition of _talk_ for simple changes can be as little as a design sketch in a GitHub issue. If your PR fixes a bug, you should link to the bug it fixes. If there isn’t one, you should raise a bug and wait for the maintainers to acknowledge it before sending a PR. This might seem a little backward–who wouldn’t want a bug fixed–but consider the bug could be a misunderstanding in how the software works or it could be a symptom of a larger problem that needs further investigation.
-
-For more complicated changes, especially feature requests, I recommend that a design document be circulated and agreed upon before sending code. This doesn’t have to be a full blown document, a sketch in an issue may be sufficient, but the key is to reach agreement using words, before locking it in stone with code.
-
-In all cases you shouldn’t proceed to send code until there is a positive agreement from the maintainer that the approach is one they are happy with. A pull request is for life, not just for Christmas.
-
-### Code review, not design by committee
-
-A code review is not the place for arguments about design. This is for two reasons. First, most code review tools are not suitable for long comment threads, GitHub’s PR interface is very bad at this, Gerrit is better, but few have a team of admins to maintain a Gerrit instance. More importantly, disagreements at the code review stage suggests there wasn’t agreement on how the change should be implemented.
-
-* * *
-
-Talk about what you want to code, then code what you talked about. Please don’t do it the other way around.
-
-### Related posts:
-
- 1. [How to include C code in your Go package][1]
- 2. [Let’s talk about logging][2]
- 3. [The value of TDD][3]
- 4. [Suggestions for contributing to an Open Source project][4]
-
-
-
---------------------------------------------------------------------------------
-
-via: https://dave.cheney.net/2019/02/18/talk-then-code
-
-作者:[Dave Cheney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://dave.cheney.net/author/davecheney
-[b]: https://github.com/lujun9972
-[1]: https://dave.cheney.net/2013/09/07/how-to-include-c-code-in-your-go-package (How to include C code in your Go package)
-[2]: https://dave.cheney.net/2015/11/05/lets-talk-about-logging (Let’s talk about logging)
-[3]: https://dave.cheney.net/2016/04/11/the-value-of-tdd (The value of TDD)
-[4]: https://dave.cheney.net/2016/03/12/suggestions-for-contributing-to-an-open-source-project (Suggestions for contributing to an Open Source project)
diff --git a/sources/tech/20190402 When Wi-Fi is mission-critical, a mixed-channel architecture is the best option.md b/sources/tech/20190402 When Wi-Fi is mission-critical, a mixed-channel architecture is the best option.md
deleted file mode 100644
index 29a73998d7..0000000000
--- a/sources/tech/20190402 When Wi-Fi is mission-critical, a mixed-channel architecture is the best option.md
+++ /dev/null
@@ -1,90 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (When Wi-Fi is mission-critical, a mixed-channel architecture is the best option)
-[#]: via: (https://www.networkworld.com/article/3386376/when-wi-fi-is-mission-critical-a-mixed-channel-architecture-is-the-best-option.html#tk.rss_all)
-[#]: author: (Zeus Kerravala https://www.networkworld.com/author/Zeus-Kerravala/)
-
-When Wi-Fi is mission-critical, a mixed-channel architecture is the best option
-======
-
-### Multi-channel is the norm for Wi-Fi today, but it’s not always the best choice. Single-channel and hybrid APs offer compelling alternatives when reliable Wi-Fi is a must.
-
-![Getty Images][1]
-
-I’ve worked with a number of companies that have implemented digital projects only to see them fail. The ideation was correct, the implementation was sound, and the market opportunity was there. The weak link? The Wi-Fi network.
-
-For example, a large hospital wanted to improve clinician response times to patient alarms by having telemetry information sent to mobile devices. Without the system, the only way a nurse would know about a patient alarm is from an audible alert. And with all the background noise, it’s often tough to discern where noises are coming from. The problem was the Wi-Fi network in the hospital had not been upgraded in years and caused messages to be significantly delayed in their delivery, often taking four to five minutes to deliver. The long delivery times caused a lack of confidence in the system, so many clinicians stopped using it and went back to manual alerting. As a result, the project was considered a failure.
-
-I’ve seen similar examples in manufacturing, K-12 education, entertainment, and other industries. Businesses are competing on the basis of customer experience, and that’s driven from the ever-expanding, ubiquitous wireless edge. Great Wi-Fi doesn’t necessarily mean market leadership, but bad Wi-Fi will have a negative impact on customers and employees. And in today’s competitive climate, that’s a recipe for disaster.
-
-**[ Read also:[Wi-Fi site-survey tips: How to avoid interference, dead spots][2] ]**
-
-## Wi-Fi performance historically inconsistent
-
-The problem with Wi-Fi is that it’s inherently flaky. I’m sure everyone reading this has experienced the typical flaws with failed downloads, dropped connections, inconsistent performance, and lengthy wait times to connect to public hot spots.
-
-Picture sitting in a conference prior to a keynote address and being able to tweet, send email, browse the web, and do other things with no problem. Then the keynote speaker comes on stage and the entire audiences start snapping pics, uploading those pictures, and streaming things – and the Wi-Fi stops working. I find this to be the norm more than the exception, underscoring the need for [no-compromise Wi-Fi][3].
-
-The question for network professionals is how to get to a place where the Wi-Fi is rock solid 100% of the time. Some say that just beefing up the existing network will do that, and it might, but in some cases, the type of Wi-Fi might not be appropriate.
-
-The most commonly deployed type of Wi-Fi is multi-channel, also known as micro-cell, where each client connects to the access point (AP) using a radio channel. A high-quality experience is based on two things: good signal strength and minimal interference. Several things can cause interference, such as APs being too close, layout issues, or interference from other equipment. To minimize interference, businesses invest a significant amount of time and money in [site surveys to plan the optimal channel map][2], but even with that’s done well, Wi-Fi glitches can still happen.
-
-**[[Take this mobile device management course from PluralSight and learn how to secure devices in your company without degrading the user experience.][4] ]**
-
-## Multi-channel Wi-Fi not always the best choice
-
-For many carpeted offices, multi-channel Wi-Fi is likely to be solid, but there are some environments where external circumstances will impact performance. A good example of this is a multi-tenant building in which there are multiple Wi-Fi networks transmitting on the same channel and interfering with one another. Another example is a hospital where there are many campus workers moving between APs. The client will also try to connect to the best AP, causing the client to continually disconnect and reconnect resulting in dropped sessions. Then there are environments such as schools, airports, and conference facilities where there is a high number of transient devices and multi-channel can struggle to keep up.
-
-## Single channel Wi-Fi offers better reliability but with a performance hit
-
-What’s a network manager to do? Is inconsistent Wi-Fi just a fait accompli? Multi-channel is the norm, but it isn’t designed for dynamic physical environments or those where reliable connectivity is a must.
-
-Several years ago an alternative architecture was proposed that would solve these problems. As the name suggests, “single channel” Wi-Fi uses a single radio channel for all APs in the network. Think of this as being a single Wi-Fi fabric that operates on one channel. With this architecture, the placement of APs is irrelevant because they all utilize the same channel, so they won’t interfere with one another. This has an obvious simplicity advantage, such as if coverage is poor, there’s no reason to do another expensive site survey. Instead, just drop in APs where they are needed.
-
-One of the disadvantages of single-channel is that aggregate network throughput was lower than multi-channel because only one channel can be used. This might be fine in environments where reliability trumps performance, but many organizations want both.
-
-## Hybrid APs offer the best of both worlds
-
-There has been recent innovation from the manufacturers of single-channel systems that mix channel architectures, creating a “best of both worlds” deployment that offers the throughput of multi-channel with the reliability of single-channel. For example, Allied Telesis offers Hybrid APs that can operate in multi-channel and single-channel mode simultaneously. That means some web clients can be assigned to the multi-channel to have maximum throughput, while others can use single-channel for seamless roaming experience.
-
-A practical use-case of such a mix might be a logistics facility where the office staff uses multi-channel, but the fork-lift operators use single-channel for continuous connectivity as they move throughout the warehouse.
-
-Wi-Fi was once a network of convenience, but now it is perhaps the most mission-critical of all networks. A traditional multi-channel system might work, but due diligence should be done to see how it functions under a heavy load. IT leaders need to understand how important Wi-Fi is to digital transformation initiatives and do the proper testing to ensure it’s not the weak link in the infrastructure chain and choose the best technology for today’s environment.
-
-**Reviews: 4 free, open-source network monitoring tools:**
-
- * [Icinga: Enterprise-grade, open-source network-monitoring that scales][5]
- * [Nagios Core: Network-monitoring software with lots of plugins, steep learning curve][6]
- * [Observium open-source network monitoring tool: Won’t run on Windows but has a great user interface][7]
- * [Zabbix delivers effective no-frills network monitoring][8]
-
-
-
-Join the Network World communities on [Facebook][9] and [LinkedIn][10] to comment on topics that are top of mind.
-
---------------------------------------------------------------------------------
-
-via: https://www.networkworld.com/article/3386376/when-wi-fi-is-mission-critical-a-mixed-channel-architecture-is-the-best-option.html#tk.rss_all
-
-作者:[Zeus Kerravala][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.networkworld.com/author/Zeus-Kerravala/
-[b]: https://github.com/lujun9972
-[1]: https://images.idgesg.net/images/article/2018/09/tablet_graph_wifi_analytics-100771638-large.jpg
-[2]: https://www.networkworld.com/article/3315269/wi-fi-site-survey-tips-how-to-avoid-interference-dead-spots.html
-[3]: https://www.alliedtelesis.com/blog/no-compromise-wi-fi
-[4]: https://pluralsight.pxf.io/c/321564/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fmobile-device-management-big-picture
-[5]: https://www.networkworld.com/article/3273439/review-icinga-enterprise-grade-open-source-network-monitoring-that-scales.html?nsdr=true#nww-fsb
-[6]: https://www.networkworld.com/article/3304307/nagios-core-monitoring-software-lots-of-plugins-steep-learning-curve.html
-[7]: https://www.networkworld.com/article/3269279/review-observium-open-source-network-monitoring-won-t-run-on-windows-but-has-a-great-user-interface.html?nsdr=true#nww-fsb
-[8]: https://www.networkworld.com/article/3304253/zabbix-delivers-effective-no-frills-network-monitoring.html
-[9]: https://www.facebook.com/NetworkWorld/
-[10]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20190422 9 ways to save the planet.md b/sources/tech/20190422 9 ways to save the planet.md
deleted file mode 100644
index d3301006cc..0000000000
--- a/sources/tech/20190422 9 ways to save the planet.md
+++ /dev/null
@@ -1,96 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (9 ways to save the planet)
-[#]: via: (https://opensource.com/article/19/4/save-planet)
-[#]: author: (Jen Wike Huger https://opensource.com/users/jen-wike/users/alanfdoss/users/jmpearce)
-
-9 ways to save the planet
-======
-These ideas have an open source twist.
-![][1]
-
-What can be done to help save the planet? The question can seem depressing at a time when it feels like an individual's contribution isn't enough. But, who are we Earth dwellers if not for a collection of individuals? So, I asked our writer community to share ways that open source software or hardware can be used to make a difference. Here's what I heard back.
-
-### 9 ways to save the planet with an open source twist
-
-**1.** **Disable the blinking cursor in your terminal.**
-
-It might sound silly, but the trivial, blinking cursor can cause up to [2 watts per hour of extra power consumption][2]. To disable it, go to Terminal Settings: Edit > Preferences > Cursor > Cursor blinking > Disabled.
-
-_Recommended by Mars Toktonaliev_
-
-**2\. Reduce your consumption of animal products and processed foods.**
-
-One way to do this is to add these open source apps to your phone: Daily Dozen, OpenFoodFacts, OpenVegeMap, and Food Restrictions. These apps will help you eat a healthy, plant-based diet, find vegan- and vegetarian-friendly restaurants, and communicate your dietary needs to others, even if they do not speak the same language. To learn more about these apps read [_4 open source apps to support eating a plant-based diet_][3].
-
-_Recommendation by Joshua Allen Holm_
-
-**3\. Recycle old computers.**
-
-How? With Linux, of course. Pay it forward by giving creating a new computer for someone who can't one and keep a computer out of the landfill. Here's how we do it at [The Asian Penguins][4].
-
-_Recommendation by Stu Keroff_
-
-**4\. Turn off devices when you're not using them.**
-
-Use "smart power strips" that have a "master" outlet and several "controlled" outlets. Plug your PC into the master outlet, and when you turn on the computer, your monitor, printer, and anything else plugged into the controlled outlets turns on too. A simpler, low-tech solution is a power strip with a timer. That's what I use at home. You can use switches on the timer to set a handy schedule to turn the power on and off at specific times. Automatically turn off your network printer when no one is at home. Or for my six-year-old laptop, extend the life of the battery with a schedule to alternate when it's running from wall power (outlet is on) and when it's running from the battery (outlet is off).
-
-_Recommended by Jim Hall_
-
-**5\. Reduce the use of your HVAC system.**
-
-Sunlight shining through windows adds a lot of heat to your home during the summer. Use Home Assistant to [automatically adjust][5] window blinds and awnings [based on the time of day][6], or even based on the angle of the sun.
-
-_Recommended by Michael Hrivnak_
-
-**6\. Turn your thermostat off or to a lower setting while you're away.**
-
-If your home thermostat has an "Away" feature, activating it on your way out the door is easy to forget. With a touch of automation, any connected thermostat can begin automatically saving energy while you're not home. [Stataway][7] is one such project that uses your phone's GPS coordinates to determine when it should set your thermostat to "Home" or "Away".
-
-_Recommended by Michael Hrivnak_
-
-**7\. Save computing power for later.**
-
-I have an idea: Create a script that can read the power output from an alternative energy array (wind and solar) and begin turning on servers (taking them from a power-saving sleep mode to an active mode) in a computing cluster until the overload power is used (whatever excess is produced beyond what can be stored/buffered for later use). Then use the overload power during high-production times for compute-intensive projects like rendering. This process would be essentially free of cost because the power can't be buffered for other uses. I'm sure the monitoring, power management, and server array tools must exist to do this. Then, it's just an integration problem, making it all work together.
-
-_Recommended by Terry Hancock_
-
-**8\. Turn off exterior lights.**
-
-Light pollution affects more than 80% of the world's population, according to the [World Atlas of Artificial Night Sky Brightness][8], published (Creative Commons Attribution-NonCommercial 4.0) in 2016 in the open access journal _Science Advances_. Turning off exterior lights is a quick way to benefit wildlife, human health, our ability to enjoy the night sky, and of course energy consumption. Visit [darksky.org][9] for more ideas on how to reduce the impact of your exterior lighting.
-
-_Recommended by Michael Hrivnak_
-
-**9\. Reduce your CPU count.**
-
-For me, I remember I used to have a whole bunch of computers running in my basement as my IT playground/lab. I've become more conscious now of power consumption and so have really drastically reduced my CPU count. I like to take advantage of VMs, zones, containers... that type of technology a lot more these days. Also, I'm really glad that small form factor and SoC computers, such as the Raspberry Pi, exist because I can do a lot with one, such as run a DNS or Web server, without heating the room and running up my electricity bill.
-
-P.S. All of these computers are running Linux, FreeBSD, or Raspbian!
-
-_Recommended by Alan Formy-Duvall_
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/4/save-planet
-
-作者:[Jen Wike Huger ][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jen-wike/users/alanfdoss/users/jmpearce
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/pixelated-world.png?itok=fHjM6m53
-[2]: https://www.redhat.com/archives/fedora-devel-list/2009-January/msg02406.html
-[3]: https://opensource.com/article/19/4/apps-plant-based-diets
-[4]: https://opensource.com/article/19/2/asian-penguins-close-digital-divide
-[5]: https://www.home-assistant.io/docs/automation/trigger/#sun-trigger
-[6]: https://www.home-assistant.io/components/cover/
-[7]: https://github.com/mhrivnak/stataway
-[8]: http://advances.sciencemag.org/content/2/6/e1600377
-[9]: http://darksky.org/
diff --git a/sources/tech/20190501 Monitor and Manage Docker Containers with Portainer.io (GUI tool) - Part-1.md b/sources/tech/20190501 Monitor and Manage Docker Containers with Portainer.io (GUI tool) - Part-1.md
deleted file mode 100644
index 27bf04eb05..0000000000
--- a/sources/tech/20190501 Monitor and Manage Docker Containers with Portainer.io (GUI tool) - Part-1.md
+++ /dev/null
@@ -1,247 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-1)
-[#]: via: (https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-part1/)
-[#]: author: (Shashidhar Soppin https://www.linuxtechi.com/author/shashidhar/)
-
-Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-1
-======
-
-As **Docker** usage and adoption is growing faster and faster, monitoring **Docker container** images is becoming more challenging. As multiple Docker container images are getting created day-by-day, monitoring them is very important. There are already some in built tools and technologies, but configuring them is little complex. As micro-services based architecture is becoming the de-facto standard in coming days, learning such tool adds one more arsenal to your tool-set.
-
-Based on the above scenarios, there was in need of one light weight and robust tool requirement was growing. So Portainer.io addressed this. “ **Portainer.io** “,(Latest version is 1.20.2) the tool is very light weight(with 2-3 commands only one can configure it) and has become popular among Docker users.
-
-**This tool has advantages over other tools; some of these are as below** ,
-
- * Light weight (requires only 2-3 commands to be required to run to install this tool) {Also installation image is only around 26-30MB of size)
- * Robust and easy to use
- * Can be used for Docker monitor and Build
- * This tool provides us a detailed overview of your Docker environments
- * This tool allows us to manage your containers, images, networks and volumes.
- * Portainer is simple to deploy – this requires just one Docker command (can be run from anywhere.)
- * Complete Docker-container environment can be monitored easily
-
-
-
-**Portainer is also equipped with** ,
-
- * Community support
- * Enterprise support
- * Has professional services available(along with partner OEM services)
-
-
-
-**Functionality and features of Portainer tool are,**
-
- 1. It comes-up with nice Dashboard, easy to use and monitor.
- 2. Many in-built templates for ease of operation and creation
- 3. Support of services (OEM, Enterprise level)
- 4. Monitoring of Containers, Images, Networks, Volume and configuration at almost real-time.
- 5. Also includes Docker-Swarm monitoring
- 6. User management with many fancy capabilities
-
-
-
-**Read Also :[How to Install Docker CE on Ubuntu 16.04 / 18.04 LTS System][1]**
-
-### How to install and configure Portainer.io on Ubuntu Linux / RHEL / CentOS
-
-**Note:** This installation is done on Ubuntu 18.04 but the installation on RHEL & CentOS would be same. We are assuming Docker CE is already installed on your system.
-
-```
-root@linuxtechi:~$ lsb_release -a
-No LSB modules are available.
-Distributor ID: Ubuntu
-Description: Ubuntu 18.04 LTS
-Release: 18.04
-Codename: bionic
-root@linuxtechi:~$
-```
-
-Create the Volume for portainer
-
-```
-root@linuxtechi:~$ sudo docker volume create portainer_data
-portainer_data
-root@linuxtechi:~$
-```
-
-Launch and start Portainer Container using the beneath docker command,
-
-```
-root@linuxtechi:~$ sudo docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
-Unable to find image 'portainer/portainer:latest' locally
-latest: Pulling from portainer/portainer
-d1e017099d17: Pull complete
-0b1e707a06d2: Pull complete
-Digest: sha256:d6cc2c20c0af38d8d557ab994c419c799a10fe825e4aa57fea2e2e507a13747d
-Status: Downloaded newer image for portainer/portainer:latest
-35286de9f2e21d197309575bb52b5599fec24d4f373cc27210d98abc60244107
-root@linuxtechi:~$
-```
-
-Once the complete installation is done, use the ip of host or Docker using port 9000 of the Docker engine where portainer is running using your browser.
-
-**Note:** If OS firewall is enabled on your Docker host then make sure 9000 port is allowed else its GUI will not come up.
-
-In my case, IP address of my Docker Host / Engine is “192.168.1.16” so URL will be,
-
-
-
-[![Portainer-Login-User-Name-Password][2]][3]
-
-Please make sure that you enter 8-character passwords. Let the admin be the user as it is and then click “Create user”.
-
-Now the following screen appears, in this select “Local” rectangle box.
-
-[![Connect-Portainer-Local-Docker][4]][5]
-
-Click on “Connect”
-
-Nice GUI with admin as user home screen appears as below,
-
-[![Portainer-io-Docker-Monitor-Dashboard][6]][7]
-
-Now Portainer is ready to launch and manage your Docker containers and it can also be used for containers monitoring.
-
-### Bring-up container image on Portainer tool
-
-[![Portainer-Endpoints][8]][9]
-
-Now check the present status, there are two container images are already running, if you create one more that appears instantly.
-
-From your command line kick-start one or two containers as below,
-
-```
-root@linuxtechi:~$ sudo docker run --name test -it debian
-Unable to find image 'debian:latest' locally
-latest: Pulling from library/debian
-e79bb959ec00: Pull complete
-Digest: sha256:724b0fbbda7fda6372ffed586670573c59e07a48c86d606bab05db118abe0ef5
-Status: Downloaded newer image for debian:latest
-root@linuxtechi:/#
-```
-
-Now click Refresh button (Are you sure message appears, click “continue” on this) in Portainer GUI, you will now see 3 container images as highlighted below,
-
-[![Portainer-io-new-container-image][10]][11]
-
-Click on the “ **containers** ” (in which it is red circled above), next window appears with “ **Dashboard Endpoint summary** ”
-
-[![Portainer-io-Docker-Container-Dash][12]][13]
-
-In this page, click on “ **Containers** ” as highlighted in red color. Now you are ready to monitor your container image.
-
-### Simple Docker container image monitoring
-
-From the above step, it appears that a fancy and nice looking “Container List” page appears as below,
-
-[![Portainer-Container-List][14]][15]
-
-All the container images can be controlled from here (stop, start, etc)
-
-**1)** Now from this page, stop the earlier started {“test” container (this was the debian image that we started earlier)}
-
-To do this select the check box in front of this image and click stop button from above,
-
-[![Stop-Container-Portainer-io-dashboard][16]][17]
-
-From the command line option, you will see that this image has been stopped or exited now,
-
-```
-root@linuxtechi:~$ sudo docker container ls -a
-CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-d45902e717c0 debian "bash" 21 minutes ago Exited (0) 49 seconds ago test
-08b96eddbae9 centos:7 "/bin/bash" About an hour ago Exited (137) 9 minutes ago mycontainer2
-35286de9f2e2 portainer/portainer "/portainer" 2 hours ago Up About an hour 0.0.0.0:9000->9000/tcp compassionate_benz
-root@linuxtechi:~$
-```
-
-**2)** Now start the stopped containers (test & mycontainer2) from Portainer GUI,
-
-Select the check box in front of stopped containers, and the click on Start
-
-[![Start-Containers-Portainer-GUI][18]][19]
-
-You will get a quick window saying, “ **Container successfully started** ” and with running state
-
-[![Conatiner-Started-successfully-Portainer-GUI][20]][21]
-
-### Various other options and features are explored as below step-by-step
-
-**1)** Click on “ **Images** ” which is highlighted, you will get the below window,
-
-[![Docker-Container-Images-Portainer-GUI][22]][23]
-
-This is the list of container images that are available but some may not running. These images can be imported, exported or uploaded to various locations, below screen shot shows the same,
-
-[![Upload-Docker-Container-Image-Portainer-GUI][24]][25]
-
-**2)** Click on “ **volumes”** which is highlighted, you will get the below window,
-
-[![Volume-list-Portainer-io-gui][26]][27]
-
-**3)** Volumes can be added easily with following option, click on add volume button, below window appears,
-
-Provide the name as “ **myvol** ” in the name box and click on “ **create the volume** ” button.
-
-[![Volume-Creation-Portainer-io-gui][28]][29]
-
-The newly created volume appears as below, (with unused state)
-
-[![Volume-unused-Portainer-io-gui][30]][31]
-
-#### Conclusion:
-
-As from the above installation steps, configuration and playing around with various options you can see how easy and fancy looking is Portainer.io tool is. This provides multiple features and options to explore on building, monitoring docker container. As explained this is very light weight tool, so doesn’t add any overload to host system. Next set-of options will be explored in part-2 of this series.
-
-Read Also: **[Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-2][32]**
-
---------------------------------------------------------------------------------
-
-via: https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-part1/
-
-作者:[Shashidhar Soppin][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.linuxtechi.com/author/shashidhar/
-[b]: https://github.com/lujun9972
-[1]: https://www.linuxtechi.com/how-to-setup-docker-on-ubuntu-server-16-04/
-[2]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Login-User-Name-Password-1024x681.jpg
-[3]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Login-User-Name-Password.jpg
-[4]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Connect-Portainer-Local-Docker-1024x538.jpg
-[5]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Connect-Portainer-Local-Docker.jpg
-[6]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-Docker-Monitor-Dashboard-1024x544.jpg
-[7]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-Docker-Monitor-Dashboard.jpg
-[8]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Endpoints-1024x252.jpg
-[9]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Endpoints.jpg
-[10]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-new-container-image-1024x544.jpg
-[11]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-new-container-image.jpg
-[12]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-Docker-Container-Dash-1024x544.jpg
-[13]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-io-Docker-Container-Dash.jpg
-[14]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Container-List-1024x538.jpg
-[15]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Portainer-Container-List.jpg
-[16]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Stop-Container-Portainer-io-dashboard-1024x447.jpg
-[17]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Stop-Container-Portainer-io-dashboard.jpg
-[18]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Start-Containers-Portainer-GUI-1024x449.jpg
-[19]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Start-Containers-Portainer-GUI.jpg
-[20]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Conatiner-Started-successfully-Portainer-GUI-1024x538.jpg
-[21]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Conatiner-Started-successfully-Portainer-GUI.jpg
-[22]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Docker-Container-Images-Portainer-GUI-1024x544.jpg
-[23]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Docker-Container-Images-Portainer-GUI.jpg
-[24]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Upload-Docker-Container-Image-Portainer-GUI-1024x544.jpg
-[25]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Upload-Docker-Container-Image-Portainer-GUI.jpg
-[26]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-list-Portainer-io-gui-1024x544.jpg
-[27]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-list-Portainer-io-gui.jpg
-[28]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-Creation-Portainer-io-gui-1024x544.jpg
-[29]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-Creation-Portainer-io-gui.jpg
-[30]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-unused-Portainer-io-gui-1024x544.jpg
-[31]: https://www.linuxtechi.com/wp-content/uploads/2019/05/Volume-unused-Portainer-io-gui.jpg
-[32]: https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-io-part-2/
diff --git a/sources/tech/20190503 Mirror your System Drive using Software RAID.md b/sources/tech/20190503 Mirror your System Drive using Software RAID.md
index e72f3a5722..ba62a2f21a 100644
--- a/sources/tech/20190503 Mirror your System Drive using Software RAID.md
+++ b/sources/tech/20190503 Mirror your System Drive using Software RAID.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: (lixin555)
+[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
diff --git a/sources/tech/20190510 Learn to change history with git rebase.md b/sources/tech/20190510 Learn to change history with git rebase.md
deleted file mode 100644
index 4d46fef81f..0000000000
--- a/sources/tech/20190510 Learn to change history with git rebase.md
+++ /dev/null
@@ -1,597 +0,0 @@
-Translating by Scoutydren....
-
-
-[#]: collector: (lujun9972)
-[#]: translator: (Scoutydren)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Learn to change history with git rebase!)
-[#]: via: (https://git-rebase.io/)
-[#]: author: (git-rebase https://git-rebase.io/)
-
-Learn to change history with git rebase!
-======
-One of Git 's core value-adds is the ability to edit history. Unlike version control systems that treat the history as a sacred record, in git we can change history to suit our needs. This gives us a lot of powerful tools and allows us to curate a good commit history in the same way we use refactoring to uphold good software design practices. These tools can be a little bit intimidating to the novice or even intermediate git user, but this guide will help to demystify the powerful git-rebase .
-
-```
-A word of caution : changing the history of public, shared, or stable branches is generally advised against. Editing the history of feature branches and personal forks is fine, and editing commits that you haven't pushed yet is always okay. Use git push -f to force push your changes to a personal fork or feature branch after editing your commits.
-```
-
-Despite the scary warning, it's worth mentioning that everything mentioned in this guide is a non-destructive operation. It's actually pretty difficult to permanently lose data in git. Fixing things when you make mistakes is covered at the end of this guide.
-
-### Setting up a sandbox
-
-We don't want to mess up any of your actual repositories, so throughout this guide we'll be working with a sandbox repo. Run these commands to get started:
-
-```
-git init /tmp/rebase-sandbox
-cd /tmp/rebase-sandbox
-git commit --allow-empty -m"Initial commit"
-```
-
-If you run into trouble, just run rm -rf /tmp/rebase-sandbox and run these steps again to start over. Each step of this guide can be run on a fresh sandbox, so it's not necessary to re-do every task.
-
-
-### Amending your last commit
-
-Let's start with something simple: fixing your most recent commit. Let's add a file to our sandbox - and make a mistake:
-
-```
-echo "Hello wrold!" >greeting.txt
- git add greeting.txt
- git commit -m"Add greeting.txt"
-```
-
-Fixing this mistake is pretty easy. We can just edit the file and commit with `--amend`, like so:
-
-```
-echo "Hello world!" >greeting.txt
- git commit -a --amend
-```
-
-Specifying `-a` automatically stages (i.e. `git add`'s) all files that git already knows about, and `--amend` will squash the changes into the most recent commit. Save and quit your editor (you have a chance to change the commit message now if you'd like). You can see the fixed commit by running `git show`:
-
-```
-commit f5f19fbf6d35b2db37dcac3a55289ff9602e4d00 (HEAD -> master)
-Author: Drew DeVault
-Date: Sun Apr 28 11:09:47 2019 -0400
-
- Add greeting.txt
-
-diff --git a/greeting.txt b/greeting.txt
-new file mode 100644
-index 0000000..cd08755
---- /dev/null
-+++ b/greeting.txt
-@@ -0,0 +1 @@
-+Hello world!
-```
-
-### Fixing up older commits
-
-Amending only works for the most recent commit. What happens if you need to correct an older commit? Let's start by setting up our sandbox accordingly:
-
-```
-echo "Hello!" >greeting.txt
-git add greeting.txt
-git commit -m"Add greeting.txt"
-
-echo "Goodbye world!" >farewell.txt
-git add farewell.txt
-git commit -m"Add farewell.txt"
-```
-
-Looks like `greeting.txt` is missing "world". Let's write a commit normally which fixes that:
-
-```
-echo "Hello world!" >greeting.txt
-git commit -a -m"fixup greeting.txt"
-```
-
-So now the files look correct, but our history could be better - let's use the new commit to "fixup" the last one. For this, we need to introduce a new tool: the interactive rebase. We're going to edit the last three commits this way, so we'll run `git rebase -i HEAD~3` (`-i` for interactive). This'll open your text editor with something like this:
-
-```
-pick 8d3fc77 Add greeting.txt
-pick 2a73a77 Add farewell.txt
-pick 0b9d0bb fixup greeting.txt
-
-# Rebase f5f19fb..0b9d0bb onto f5f19fb (3 commands)
-#
-# Commands:
-# p, pick = use commit
-# f, fixup = like "squash", but discard this commit's log message
-```
-
-This is the rebase plan, and by editing this file you can instruct git on how to edit history. I've trimmed the summary to just the details relevant to this part of the rebase guide, but feel free to skim the full summary in your text editor.
-
-When we save and close our editor, git is going to remove all of these commits from its history, then execute each line one at a time. By default, it's going to pick each commit, summoning it from the heap and adding it to the branch. If we don't edit this file at all, we'll end up right back where we started, picking every commit as-is. We're going to use one of my favorite features now: fixup. Edit the third line to change the operation from "pick" to "fixup" and move it to immediately after the commit we want to "fix up":
-
-```
-pick 8d3fc77 Add greeting.txt
-fixup 0b9d0bb fixup greeting.txt
-pick 2a73a77 Add farewell.txt
-```
-
-**Tip** : We can also abbreviate this with just "f" to speed things up next time.
-
-Save and quit your editor - git will run these commands. We can check the log to verify the result:
-
-```
-$ git log -2 --oneline
-fcff6ae (HEAD -> master) Add farewell.txt
-a479e94 Add greeting.txt
-```
-
-### Squashing several commits into one
-
-As you work, you may find it useful to write lots of commits as you reach small milestones or fix bugs in previous commits. However, it may be useful to "squash" these commits together, to make a cleaner history before merging your work into master. For this, we'll use the "squash" operation. Let's start by writing a bunch of commits - just copy and paste this if you want to speed it up:
-
-```
-git checkout -b squash
-for c in H e l l o , ' ' w o r l d; do
- echo "$c" >>squash.txt
- git add squash.txt
- git commit -m"Add '$c' to squash.txt"
-done
-```
-
-That's a lot of commits to make a file that says "Hello, world"! Let's start another interactive rebase to squash them together. Note that we checked out a branch to try this on, first. Because of that, we can quickly rebase all of the commits since we branched by using `git rebase -i master`. The result:
-
-```
-pick 1e85199 Add 'H' to squash.txt
-pick fff6631 Add 'e' to squash.txt
-pick b354c74 Add 'l' to squash.txt
-pick 04aaf74 Add 'l' to squash.txt
-pick 9b0f720 Add 'o' to squash.txt
-pick 66b114d Add ',' to squash.txt
-pick dc158cd Add ' ' to squash.txt
-pick dfcf9d6 Add 'w' to squash.txt
-pick 7a85f34 Add 'o' to squash.txt
-pick c275c27 Add 'r' to squash.txt
-pick a513fd1 Add 'l' to squash.txt
-pick 6b608ae Add 'd' to squash.txt
-
-# Rebase 1af1b46..6b608ae onto 1af1b46 (12 commands)
-#
-# Commands:
-# p, pick = use commit
-# s, squash = use commit, but meld into previous commit
-```
-
-**Tip** : your local master branch evolves independently of the remote master branch, and git stores the remote branch as `origin/master`. Combined with this trick, `git rebase -i origin/master` is often a very convenient way to rebase all of the commits which haven't been merged upstream yet!
-
-We're going to squash all of these changes into the first commit. To do this, change every "pick" operation to "squash", except for the first line, like so:
-
-```
-pick 1e85199 Add 'H' to squash.txt
-squash fff6631 Add 'e' to squash.txt
-squash b354c74 Add 'l' to squash.txt
-squash 04aaf74 Add 'l' to squash.txt
-squash 9b0f720 Add 'o' to squash.txt
-squash 66b114d Add ',' to squash.txt
-squash dc158cd Add ' ' to squash.txt
-squash dfcf9d6 Add 'w' to squash.txt
-squash 7a85f34 Add 'o' to squash.txt
-squash c275c27 Add 'r' to squash.txt
-squash a513fd1 Add 'l' to squash.txt
-squash 6b608ae Add 'd' to squash.txt
-```
-
-When you save and close your editor, git will think about this for a moment, then open your editor again to revise the final commit message. You'll see something like this:
-
-```
-# This is a combination of 12 commits.
-# This is the 1st commit message:
-
-Add 'H' to squash.txt
-
-# This is the commit message #2:
-
-Add 'e' to squash.txt
-
-# This is the commit message #3:
-
-Add 'l' to squash.txt
-
-# This is the commit message #4:
-
-Add 'l' to squash.txt
-
-# This is the commit message #5:
-
-Add 'o' to squash.txt
-
-# This is the commit message #6:
-
-Add ',' to squash.txt
-
-# This is the commit message #7:
-
-Add ' ' to squash.txt
-
-# This is the commit message #8:
-
-Add 'w' to squash.txt
-
-# This is the commit message #9:
-
-Add 'o' to squash.txt
-
-# This is the commit message #10:
-
-Add 'r' to squash.txt
-
-# This is the commit message #11:
-
-Add 'l' to squash.txt
-
-# This is the commit message #12:
-
-Add 'd' to squash.txt
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# Date: Sun Apr 28 14:21:56 2019 -0400
-#
-# interactive rebase in progress; onto 1af1b46
-# Last commands done (12 commands done):
-# squash a513fd1 Add 'l' to squash.txt
-# squash 6b608ae Add 'd' to squash.txt
-# No commands remaining.
-# You are currently rebasing branch 'squash' on '1af1b46'.
-#
-# Changes to be committed:
-# new file: squash.txt
-#
-```
-
-This defaults to a combination of all of the commit messages which were squashed, but leaving it like this is almost always not what you want. The old commit messages may be useful for reference when writing the new one, though.
-
-**Tip** : the "fixup" command you learned about in the previous section can be used for this purpose, too - but it discards the messages of the squashed commits.
-
-Let's delete everything and replace it with a better commit message, like this:
-
-```
-Add squash.txt with contents "Hello, world"
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# Date: Sun Apr 28 14:21:56 2019 -0400
-#
-# interactive rebase in progress; onto 1af1b46
-# Last commands done (12 commands done):
-# squash a513fd1 Add 'l' to squash.txt
-# squash 6b608ae Add 'd' to squash.txt
-# No commands remaining.
-# You are currently rebasing branch 'squash' on '1af1b46'.
-#
-# Changes to be committed:
-# new file: squash.txt
-#
-```
-
-Save and quit your editor, then examine your git log - success!
-
-```
-commit c785f476c7dff76f21ce2cad7c51cf2af00a44b6 (HEAD -> squash)
-Author: Drew DeVault
-Date: Sun Apr 28 14:21:56 2019 -0400
-
- Add squash.txt with contents "Hello, world"
-```
-
-Before we move on, let's pull our changes into the master branch and get rid of this scratch one. We can use `git rebase` like we use `git merge`, but it avoids making a merge commit:
-
-```
-git checkout master
-git rebase squash
-git branch -D squash
-```
-
-We generally prefer to avoid using git merge unless we're actually merging unrelated histories. If you have two divergent branches, a git merge is useful to have a record of when they were... merged. In the course of your normal work, rebase is often more appropriate.
-
-### Splitting one commit into several
-
-Sometimes the opposite problem happens - one commit is just too big. Let's look into splitting it up. This time, let's write some actual code. Start with a simple C program2 (you can still copy+paste this snippet into your shell to do this quickly):
-
-```
-cat <main.c
-int main(int argc, char *argv[]) {
- return 0;
-}
-EOF
-```
-
-We'll commit this first.
-
-```
-git add main.c
-git commit -m"Add C program skeleton"
-```
-
-Next, let's extend the program a bit:
-
-```
-cat <main.c
-#include <stdio.h>
-
-const char *get_name() {
- static char buf[128];
- scanf("%s", buf);
- return buf;
-}
-
-int main(int argc, char *argv[]) {
- printf("What's your name? ");
- const char *name = get_name();
- printf("Hello, %s!\n", name);
- return 0;
-}
-EOF
-```
-
-After we commit this, we'll be ready to learn how to split it up.
-
-```
-git commit -a -m"Flesh out C program"
-```
-
-The first step is to start an interactive rebase. Let's rebase both commits with `git rebase -i HEAD~2`, giving us this rebase plan:
-
-```
-pick 237b246 Add C program skeleton
-pick b3f188b Flesh out C program
-
-# Rebase c785f47..b3f188b onto c785f47 (2 commands)
-#
-# Commands:
-# p, pick = use commit
-# e, edit = use commit, but stop for amending
-```
-
-Change the second commit's command from "pick" to "edit", then save and close your editor. Git will think about this for a second, then present you with this:
-
-```
-Stopped at b3f188b... Flesh out C program
-You can amend the commit now, with
-
- git commit --amend
-
-Once you are satisfied with your changes, run
-
- git rebase --continue
-```
-
-We could follow these instructions to add new changes to the commit, but instead let's do a "soft reset"3 by running `git reset HEAD^`. If you run `git status` after this, you'll see that it un-commits the latest commit and adds its changes to the working tree:
-
-```
-Last commands done (2 commands done):
- pick 237b246 Add C program skeleton
- edit b3f188b Flesh out C program
-No commands remaining.
-You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
- (Once your working directory is clean, run "git rebase --continue")
-
-Changes not staged for commit:
- (use "git add ..." to update what will be committed)
- (use "git checkout -- ..." to discard changes in working directory)
-
- modified: main.c
-
-no changes added to commit (use "git add" and/or "git commit -a")
-```
-
-To split this up, we're going to do an interactive commit. This allows us to selectively commit only specific changes from the working tree. Run `git commit -p` to start this process, and you'll be presented with the following prompt:
-
-```
-diff --git a/main.c b/main.c
-index b1d9c2c..3463610 100644
---- a/main.c
-+++ b/main.c
-@@ -1,3 +1,14 @@
-+#include <stdio.h>
-+
-+const char *get_name() {
-+ static char buf[128];
-+ scanf("%s", buf);
-+ return buf;
-+}
-+
- int main(int argc, char *argv[]) {
-+ printf("What's your name? ");
-+ const char *name = get_name();
-+ printf("Hello, %s!\n", name);
- return 0;
- }
-Stage this hunk [y,n,q,a,d,s,e,?]?
-```
-
-Git has presented you with just one "hunk" (i.e. a single change) to consider committing. This one is too big, though - let's use the "s" command to "split" up the hunk into smaller parts.
-
-```
-Split into 2 hunks.
-@@ -1 +1,9 @@
-+#include
-+
-+const char *get_name() {
-+ static char buf[128];
-+ scanf("%s", buf);
-+ return buf;
-+}
-+
- int main(int argc, char *argv[]) {
-Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?
-```
-
-**Tip** : If you're curious about the other options, press "?" to summarize them.
-
-This hunk looks better - a single, self-contained change. Let's hit "y" to answer the question (and stage that "hunk"), then "q" to "quit" the interactive session and proceed with the commit. Your editor will pop up to ask you to enter a suitable commit message.
-
-```
-Add get_name function to C program
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# interactive rebase in progress; onto c785f47
-# Last commands done (2 commands done):
-# pick 237b246 Add C program skeleton
-# edit b3f188b Flesh out C program
-# No commands remaining.
-# You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
-#
-# Changes to be committed:
-# modified: main.c
-#
-# Changes not staged for commit:
-# modified: main.c
-#
-```
-
-Save and close your editor, then we'll make the second commit. We could do another interactive commit, but since we just want to include the rest of the changes in this commit we'll just do this:
-
-```
-git commit -a -m"Prompt user for their name"
-git rebase --continue
-```
-
-That last command tells git that we're done editing this commit, and to continue to the next rebase command. That's it! Run `git log` to see the fruits of your labor:
-
-```
-$ git log -3 --oneline
-fe19cc3 (HEAD -> master) Prompt user for their name
-659a489 Add get_name function to C program
-237b246 Add C program skeleton
-```
-
-### Reordering commits
-
-This one is pretty easy. Let's start by setting up our sandbox:
-
-```
-echo "Goodbye now!" >farewell.txt
-git add farewell.txt
-git commit -m"Add farewell.txt"
-
-echo "Hello there!" >greeting.txt
-git add greeting.txt
-git commit -m"Add greeting.txt"
-
-echo "How're you doing?" >inquiry.txt
-git add inquiry.txt
-git commit -m"Add inquiry.txt"
-```
-
-The git log should now look like this:
-
-```
-f03baa5 (HEAD -> master) Add inquiry.txt
-a4cebf7 Add greeting.txt
-90bb015 Add farewell.txt
-```
-
-Clearly, this is all out of order. Let's do an interactive rebase of the past 3 commits to resolve this. Run `git rebase -i HEAD~3` and this rebase plan will appear:
-
-```
-pick 90bb015 Add farewell.txt
-pick a4cebf7 Add greeting.txt
-pick f03baa5 Add inquiry.txt
-
-# Rebase fe19cc3..f03baa5 onto fe19cc3 (3 commands)
-#
-# Commands:
-# p, pick = use commit
-#
-# These lines can be re-ordered; they are executed from top to bottom.
-```
-
-The fix is now straightforward: just reorder these lines in the order you wish for the commits to appear. Should look something like this:
-
-```
-pick a4cebf7 Add greeting.txt
-pick f03baa5 Add inquiry.txt
-pick 90bb015 Add farewell.txt
-```
-
-Save and close your editor and git will do the rest for you. Note that it's possible to end up with conflicts when you do this in practice - click here for help resolving conflicts.
-
-### git pull --rebase
-
-If you've been writing some commits on a branch which has been updated upstream, normally `git pull` will create a merge commit. In this respect, `git pull`'s behavior by default is equivalent to:
-
-```
-git fetch origin
-git merge origin/master
-```
-
-There's another option, which is often more useful and leads to a much cleaner history: `git pull --rebase`. Unlike the merge approach, this is equivalent to the following:
-
-```
-git fetch origin
-git rebase origin/master
-```
-
-The merge approach is simpler and easier to understand, but the rebase approach is almost always what you want to do if you understand how to use git rebase. If you like, you can set it as the default behavior like so:
-
-```
-git config --global pull.rebase true
-```
-
-When you do this, technically you're applying the procedure we discuss in the next section... so let's explain what it means to do that deliberately, too.
-
-### Using git rebase to... rebase
-
-Ironically, the feature of git rebase that I use the least is the one it's named for: rebasing branches. Say you have the following branches:
-
-```
-o--o--o--o--> master
- \--o--o--> feature-1
- \--o--> feature-2
-```
-
-It turns out feature-2 doesn't depend on any of the changes in feature-1, so you can just base it off of master. The fix is thus:
-
-```
-git checkout feature-2
-git rebase master
-```
-
-The non-interactive rebase does the default operation for all implicated commits ("pick")4, which simply rolls your history back to the last common anscestor and replays the commits from both branches. Your history now looks like this:
-
-```
-o--o--o--o--> master
- | \--o--> feature-2
- \--o--o--> feature-1
-```
-
-### Resolving conflicts
-
-The details on resolving merge conflicts are beyond the scope of this guide - keep your eye out for another guide for this in the future. Assuming you're familiar with resolving conflicts in general, here are the specifics that apply to rebasing.
-
-The details on resolving merge conflicts are beyond the scope of this guide - keep your eye out for another guide for this in the future. Assuming you're familiar with resolving conflicts in general, here are the specifics that apply to rebasing.
-
-Sometimes you'll get a merge conflict when doing a rebase, which you can handle just like any other merge conflict. Git will set up the conflict markers in the affected files, `git status` will show you what you need to resolve, and you can mark files as resolved with `git add` or `git rm`. However, in the context of a git rebase, there are two options you should be aware of.
-
-The first is how you complete the conflict resolution. Rather than `git commit` like you'll use when addressing conflicts that arise from `git merge`, the appropriate command for rebasing is `git rebase --continue`. However, there's another option available to you: `git rebase --skip`. This will skip the commit you're working on, and it won't be included in the rebase. This is most common when doing a non-interactive rebase, when git doesn't realize that a commit it's pulled from the "other" branch is an updated version of the commit that it conflicts with on "our" branch.
-
-### Help! I broke it!
-
-No doubt about it - rebasing can be hard sometimes. If you've made a mistake and in so doing lost commits which you needed, then `git reflog` is here to save the day. Running this command will show you every operation which changed a ref, or reference - that is, branches and tags. Each line shows you what the old reference pointed to, and you can `git cherry-pick`, `git checkout`, `git show`, or use any other operation on git commits once thought lost.
-
-
---------------------------------------------------------------------------------
-
-via: https://git-rebase.io/
-
-作者:[git-rebase][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://git-rebase.io/
-[b]: https://github.com/lujun9972
diff --git a/sources/tech/20190521 How to Disable IPv6 on Ubuntu Linux.md b/sources/tech/20190521 How to Disable IPv6 on Ubuntu Linux.md
deleted file mode 100644
index 4420b034e6..0000000000
--- a/sources/tech/20190521 How to Disable IPv6 on Ubuntu Linux.md
+++ /dev/null
@@ -1,219 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to Disable IPv6 on Ubuntu Linux)
-[#]: via: (https://itsfoss.com/disable-ipv6-ubuntu-linux/)
-[#]: author: (Sergiu https://itsfoss.com/author/sergiu/)
-
-How to Disable IPv6 on Ubuntu Linux
-======
-
-Are you looking for a way to **disable IPv6** connections on your Ubuntu machine? In this article, I’ll teach you exactly how to do it and why you would consider this option. I’ll also show you how to **enable or re-enable IPv6** in case you change your mind.
-
-### What is IPv6 and why would you want to disable IPv6 on Ubuntu?
-
-**[Internet Protocol version 6][1]** [(][1] **[IPv6][1]**[)][1] is the most recent version of the Internet Protocol (IP), the communications protocol that provides an identification and location system for computers on networks and routes traffic across the Internet. It was developed in 1998 to replace the **IPv4** protocol.
-
-**IPv6** aims to improve security and performance, while also making sure we don’t run out of addresses. It assigns unique addresses globally to every device, storing them in **128-bits** , compared to just 32-bits used by IPv4.
-
-![Disable IPv6 Ubuntu][2]
-
-Although the goal is for IPv4 to be replaced by IPv6, there is still a long way to go. Less than **30%** of the sites on the Internet makes IPv6 connectivity available to users (tracked by Google [here][3]). IPv6 can also cause [problems with some applications at time][4].
-
-Since **VPNs** provide global services, the fact that IPv6 uses globally routed addresses (uniquely assigned) and that there (still) are ISPs that don’t offer IPv6 support shifts this feature lower down their priority list. This way, they can focus on what matters the most for VPN users: security.
-
-Another possible reason you might want to disable IPv6 on your system is not wanting to expose yourself to various threats. Although IPv6 itself is safer than IPv4, the risks I am referring to are of another nature. If you aren’t actively using IPv6 and its features, [having IPv6 enabled leaves you vulnerable to various attacks][5], offering the hacker another possible exploitable tool.
-
-On the same note, configuring basic network rules is not enough. You have to pay the same level of attention to tweaking your IPv6 configuration as you do for IPv4. This can prove to be quite a hassle to do (and also to maintain). With IPv6 comes a suite of problems different to those of IPv4 (many of which can be referenced online, given the age of this protocol), giving your system another layer of complexity.
-
-[][6]
-
-Suggested read How To Remove Drive Icons From Unity Launcher In Ubuntu 14.04 [Beginner Tips]
-
-### Disabling IPv6 on Ubuntu [For Advanced Users Only]
-
-In this section, I’ll be covering how you can disable IPv6 protocol on your Ubuntu machine. Open up a terminal ( **default:** CTRL+ALT+T) and let’s get to it!
-
-**Note:** _For most of the commands you are going to input in the terminal_ _you are going to need root privileges ( **sudo** )._
-
-Warning!
-
-If you are a regular desktop Linux user and prefer a stable working system, please avoid this tutorial. This is for advanced users who know what they are doing and why they are doing so.
-
-#### 1\. Disable IPv6 using Sysctl
-
-First of all, you can **check** if you have IPv6 enabled with:
-
-```
-ip a
-```
-
-You should see an IPv6 address if it is enabled (the name of your internet card might be different):
-
-![IPv6 Address Ubuntu][7]
-
-You have see the sysctl command in the tutorial about [restarting network in Ubuntu][8]. We are going to use it here as well. To **disable IPv6** you only have to input 3 commands:
-
-```
-sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
-sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
-sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
-```
-
-You can check if it worked using:
-
-```
-ip a
-```
-
-You should see no IPv6 entry:
-
-![IPv6 Disabled Ubuntu][9]
-
-However, this only **temporarily disables IPv6**. The next time your system boots, IPv6 will be enabled again.
-
-One method to make this option persist is modifying **/etc/sysctl.conf**. I’ll be using vim to edit the file, but you can use any editor you like. Make sure you have **administrator rights** (use **sudo** ):
-
-![Sysctl Configuration][10]
-
-Add the following lines to the file:
-
-```
-net.ipv6.conf.all.disable_ipv6=1
-net.ipv6.conf.default.disable_ipv6=1
-net.ipv6.conf.lo.disable_ipv6=1
-```
-
-For the settings to take effect use:
-
-```
-sudo sysctl -p
-```
-
-If IPv6 is still enabled after rebooting, you must create (with root privileges) the file **/etc/rc.local** and fill it with:
-
-```
-#!/bin/bash
-# /etc/rc.local
-
-/etc/sysctl.d
-/etc/init.d/procps restart
-
-exit 0
-```
-
-Now use [chmod command][11] to make the file executable:
-
-```
-sudo chmod 755 /etc/rc.local
-```
-
-What this will do is manually read (during the boot time) the kernel parameters from your sysctl configuration file.
-
-[][12]
-
-Suggested read 3 Ways to Check Linux Kernel Version in Command Line
-
-#### 2\. Disable IPv6 using GRUB
-
-An alternative method is to configure **GRUB** to pass kernel parameters at boot time. You’ll have to edit **/etc/default/grub**. Once again, make sure you have administrator privileges:
-
-![GRUB Configuration][13]
-
-Now you need to modify **GRUB_CMDLINE_LINUX_DEFAULT** and **GRUB_CMDLINE_LINUX** to disable IPv6 on boot:
-
-```
-GRUB_CMDLINE_LINUX_DEFAULT="quiet splash ipv6.disable=1"
-GRUB_CMDLINE_LINUX="ipv6.disable=1"
-```
-
-Save the file and run:
-
-```
-sudo update-grub
-```
-
-The settings should now persist on reboot.
-
-### Re-enabling IPv6 on Ubuntu
-
-To re-enable IPv6, you’ll have to undo the changes you made. To enable IPv6 until reboot, enter:
-
-```
-sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
-sudo sysctl -w net.ipv6.conf.default.disable_ipv6=0
-sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0
-```
-
-Otherwise, if you modified **/etc/sysctl.conf** you can either remove the lines you added or change them to:
-
-```
-net.ipv6.conf.all.disable_ipv6=0
-net.ipv6.conf.default.disable_ipv6=0
-net.ipv6.conf.lo.disable_ipv6=0
-```
-
-You can optionally reload these values:
-
-```
-sudo sysctl -p
-```
-
-You should once again see a IPv6 address:
-
-![IPv6 Reenabled in Ubuntu][14]
-
-Optionally, you can remove **/etc/rc.local** :
-
-```
-sudo rm /etc/rc.local
-```
-
-If you modified the kernel parameters in **/etc/default/grub** , go ahead and delete the added options:
-
-```
-GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
-GRUB_CMDLINE_LINUX=""
-```
-
-Now do:
-
-```
-sudo update-grub
-```
-
-**Wrapping Up**
-
-In this guide I provided you ways in which you can **disable IPv6** on Linux, as well as giving you an idea about what IPv6 is and why you would want to disable it.
-
-Did you find this article useful? Do you disable IPv6 connectivity? Let us know in the comment section!
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/disable-ipv6-ubuntu-linux/
-
-作者:[Sergiu][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/sergiu/
-[b]: https://github.com/lujun9972
-[1]: https://en.wikipedia.org/wiki/IPv6
-[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/05/disable_ipv6_ubuntu.png?fit=800%2C450&ssl=1
-[3]: https://www.google.com/intl/en/ipv6/statistics.html
-[4]: https://whatismyipaddress.com/ipv6-issues
-[5]: https://www.internetsociety.org/blog/2015/01/ipv6-security-myth-1-im-not-running-ipv6-so-i-dont-have-to-worry/
-[6]: https://itsfoss.com/remove-drive-icons-from-unity-launcher-in-ubuntu/
-[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_address_ubuntu.png?fit=800%2C517&ssl=1
-[8]: https://itsfoss.com/restart-network-ubuntu/
-[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_disabled_ubuntu.png?fit=800%2C442&ssl=1
-[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/05/sysctl_configuration.jpg?fit=800%2C554&ssl=1
-[11]: https://linuxhandbook.com/chmod-command/
-[12]: https://itsfoss.com/find-which-kernel-version-is-running-in-ubuntu/
-[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/05/grub_configuration-1.jpg?fit=800%2C565&ssl=1
-[14]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/05/ipv6_address_ubuntu-1.png?fit=800%2C517&ssl=1
diff --git a/sources/tech/20190523 Run your blog on GitHub Pages with Python.md b/sources/tech/20190523 Run your blog on GitHub Pages with Python.md
deleted file mode 100644
index 1e3634a327..0000000000
--- a/sources/tech/20190523 Run your blog on GitHub Pages with Python.md
+++ /dev/null
@@ -1,235 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Run your blog on GitHub Pages with Python)
-[#]: via: (https://opensource.com/article/19/5/run-your-blog-github-pages-python)
-[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani)
-
-Run your blog on GitHub Pages with Python
-======
-Create a blog with Pelican, a Python-based blogging platform that works
-well with GitHub.
-![Raspberry Pi and Python][1]
-
-[GitHub][2] is a hugely popular web service for source code control that uses [Git][3] to synchronize local files with copies kept on GitHub's servers so you can easily share and back up your work.
-
-In addition to providing a user interface for code repositories, GitHub also enables users to [publish web pages][4] directly from a repository. The website generation package GitHub recommends is [Jekyll][5], written in Ruby. Since I'm a bigger fan of [Python][6], I prefer [Pelican][7], a Python-based blogging platform that works well with GitHub.
-
-Pelican and Jekyll both transform content written in [Markdown][8] or [reStructuredText][9] into HTML to generate static websites, and both generators support themes that allow unlimited customization.
-
-In this article, I'll describe how to install Pelican, set up your GitHub repository, run a quickstart helper, write some Markdown files, and publish your first page. I'll assume that you have a [GitHub account][10], are comfortable with [basic Git commands][11], and want to publish a blog using Pelican.
-
-### Install Pelican and create the repo
-
-First things first, Pelican (and **ghp-import** ) must be installed on your local machine. This is super easy with [pip][12], the Python package installation tool (you have pip right?):
-
-
-```
-`$ pip install pelican ghp-import`
-```
-
-Next, open a browser and create a new repository on GitHub for your sweet new blog. Name it as follows (substituting your GitHub username for here and throughout this tutorial):
-
-
-```
-`https://GitHub.com/username/username.github.io`
-```
-
-Leave it empty; we will fill it with compelling blog content in a moment.
-
-Using a command line (you command line right?), clone your empty Git repository to your local machine:
-
-
-```
-$ git clone blog
-$ cd blog
-```
-
-### That one weird trick…
-
-Here's a not-super-obvious trick about publishing web content on GitHub. For user pages (pages hosted in repos named _username.github.io_ ), the content is served from the **master** branch.
-
-I strongly prefer not to keep all the Pelican configuration files and raw Markdown files in **master** , rather just the web content. So I keep the Pelican configuration and the raw content in a separate branch I like to call **content**. (You can call it whatever you want, but the following instructions will call it **content**.) I like this structure since I can throw away all the files in **master** and re-populate it with the **content** branch.
-
-
-```
-$ git checkout -b content
-Switched to a new branch 'content'
-```
-
-### Configure Pelican
-
-Now it's time for content configuration. Pelican provides a great initialization tool called **pelican-quickstart** that will ask you a series of questions about your blog.
-
-
-```
-$ pelican-quickstart
-Welcome to pelican-quickstart v3.7.1.
-
-This script will help you create a new Pelican-based website.
-
-Please answer the following questions so this script can generate the files
-needed by Pelican.
-
-> Where do you want to create your new web site? [.]
-> What will be the title of this web site? Super blog
-> Who will be the author of this web site? username
-> What will be the default language of this web site? [en]
-> Do you want to specify a URL prefix? e.g., (Y/n) n
-> Do you want to enable article pagination? (Y/n)
-> How many articles per page do you want? [10]
-> What is your time zone? [Europe/Paris] US/Central
-> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) y
-> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) y
-> Do you want to upload your website using FTP? (y/N) n
-> Do you want to upload your website using SSH? (y/N) n
-> Do you want to upload your website using Dropbox? (y/N) n
-> Do you want to upload your website using S3? (y/N) n
-> Do you want to upload your website using Rackspace Cloud Files? (y/N) n
-> Do you want to upload your website using GitHub Pages? (y/N) y
-> Is this your personal page (username.github.io)? (y/N) y
-Done. Your new project is available at /Users/username/blog
-```
-
-You can take the defaults on every question except:
-
- * Website title, which should be unique and special
- * Website author, which can be a personal username or your full name
- * Time zone, which may not be in Paris
- * Upload to GitHub Pages, which is a "y" in our case
-
-
-
-After answering all the questions, Pelican leaves the following in the current directory:
-
-
-```
-$ ls
-Makefile content/ develop_server.sh*
-fabfile.py output/ pelicanconf.py
-publishconf.py
-```
-
-You can check out the [Pelican docs][13] to find out how to use those files, but we're all about getting things done _right now_. No, I haven't read the docs yet either.
-
-### Forge on
-
-Add all the Pelican-generated files to the **content** branch of the local Git repo, commit the changes, and push the local changes to the remote repo hosted on GitHub by entering:
-
-
-```
-$ git add .
-$ git commit -m 'initial pelican commit to content'
-$ git push origin content
-```
-
-This isn't super exciting, but it will be handy if we need to revert edits to one of these files.
-
-### Finally getting somewhere
-
-OK, now you can get bloggy! All of your blog posts, photos, images, PDFs, etc., will live in the **content** directory, which is initially empty. To begin creating a first post and an About page with a photo, enter:
-
-
-```
-$ cd content
-$ mkdir pages images
-$ cp /Users/username/SecretStash/HotPhotoOfMe.jpg images
-$ touch first-post.md
-$ touch pages/about.md
-```
-
-Next, open the empty file **first-post.md** in your favorite text editor and add the following:
-
-
-```
-title: First Post on My Sweet New Blog
-date:
-author: Your Name Here
-
-# I am On My Way To Internet Fame and Fortune!
-
-This is my first post on my new blog. While not super informative it
-should convey my sense of excitement and eagerness to engage with you,
-the reader!
-```
-
-The first three lines contain metadata that Pelican uses to organize things. There are lots of different metadata you can put there; again, the docs are your best bet for learning more about the options.
-
-Now, open the empty file **pages/about.md** and add this text:
-
-
-```
-title: About
-date:
-
-![So Schmexy][my_sweet_photo]
-
-Hi, I am and I wrote this epic collection of Interweb
-wisdom. In days of yore, much of this would have been deemed sorcery
-and I would probably have been burned at the stake.
-
-😆
-
-[my_sweet_photo]: {filename}/images/HotPhotoOfMe.jpg
-```
-
-You now have three new pieces of web content in your content directory. Of the content branch. That's a lot of content.
-
-### Publish
-
-Don't worry; the payoff is coming!
-
-All that's left to do is:
-
- * Run Pelican to generate the static HTML files in **output** : [code]`$ pelican content -o output -s publishconf.py`
-```
-* Use **ghp-import** to add the contents of the **output** directory to the **master** branch: [code]`$ ghp-import -m "Generate Pelican site" --no-jekyll -b master output`
-```
- * Push the local master branch to the remote repo: [code]`$ git push origin master`
-```
- * Commit and push the new content to the **content** branch: [code] $ git add content
-$ git commit -m 'added a first post, a photo and an about page'
-$ git push origin content
-```
-
-
-
-### OMG, I did it!
-
-Now the exciting part is here, when you get to view what you've published for everyone to see! Open your browser and enter:
-
-
-```
-`https://username.github.io`
-```
-
-Congratulations on your new blog, self-published on GitHub! You can follow this pattern whenever you want to add more pages or articles. Happy blogging.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/5/run-your-blog-github-pages-python
-
-作者:[Erik O'Shaughnessy][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/getting_started_with_python.png?itok=MFEKm3gl (Raspberry Pi and Python)
-[2]: https://github.com/
-[3]: https://git-scm.com
-[4]: https://help.github.com/en/categories/github-pages-basics
-[5]: https://jekyllrb.com
-[6]: https://python.org
-[7]: https://blog.getpelican.com
-[8]: https://guides.github.com/features/mastering-markdown
-[9]: http://docutils.sourceforge.net/docs/user/rst/quickref.html
-[10]: https://github.com/join?source=header-home
-[11]: https://git-scm.com/docs
-[12]: https://pip.pypa.io/en/stable/
-[13]: https://docs.getpelican.com
diff --git a/sources/tech/20190524 Dual booting Windows and Linux using UEFI.md b/sources/tech/20190524 Dual booting Windows and Linux using UEFI.md
deleted file mode 100644
index b281b6036b..0000000000
--- a/sources/tech/20190524 Dual booting Windows and Linux using UEFI.md
+++ /dev/null
@@ -1,104 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Dual booting Windows and Linux using UEFI)
-[#]: via: (https://opensource.com/article/19/5/dual-booting-windows-linux-uefi)
-[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss/users/ckrzen)
-
-Dual booting Windows and Linux using UEFI
-======
-A quick rundown of setting up Linux and Windows to dual boot on the same
-machine, using the Unified Extensible Firmware Interface (UEFI).
-![Linux keys on the keyboard for a desktop computer][1]
-
-Rather than doing a step-by-step how-to guide to configuring your system to dual boot, I’ll highlight the important points. As an example, I will refer to my new laptop that I purchased a few months ago. I first installed [Ubuntu Linux][2] onto the entire hard drive, which destroyed the pre-installed [Windows 10][3] installation. After a few months, I decided to install a different Linux distribution, and so also decided to re-install Windows 10 alongside [Fedora Linux][4] in a dual boot configuration. I’ll highlight some essential facts to get started.
-
-### Firmware
-
-Dual booting is not just a matter of software. Or, it is, but it involves changing your firmware, which among other things tells your machine how to begin the boot process. Here are some firmware-related issues to keep in mind.
-
-#### UEFI vs. BIOS
-
-Before attempting to install, make sure your firmware configuration is optimal. Most computers sold today have a new type of firmware known as [Unified Extensible Firmware Interface (UEFI)][5], which has pretty much replaced the other firmware known as [Basic Input Output System (BIOS)][6], which is often included through the mode many providers call Legacy Boot.
-
-I had no need for BIOS, so I chose UEFI mode.
-
-#### Secure Boot
-
-One other important setting is Secure Boot. This feature detects whether the boot path has been tampered with, and stops unapproved operating systems from booting. For now, I disabled this option to ensure that I could install Fedora Linux. According to the Fedora Project Wiki [Features/Secure Boot ][7] Fedora Linux will work with it enabled. This may be different for other Linux distributions —I plan to revisit this setting in the future.
-
-In short, if you find that you cannot install your Linux OS with this setting active, disable Secure Boot and try again.
-
-### Partitioning the boot drive
-
-If you choose to dual boot and have both operating systems on the same drive, you have to break it into partitions. Even if you dual boot using two different drives, most Linux installations are best broken into a few basic partitions for a variety of reasons. Here are some options to consider.
-
-#### GPT vs MBR
-
-If you decide to manually partition your boot drive in advance, I recommend using the [GUID Partition Table (GPT)][8] rather than the older [Master Boot Record (MBR)][9]. Among the reasons for this change, there are two specific limitations of MBR that GPT doesn’t have:
-
- * MBR can hold up to 15 partitions, while GPT can hold up to 128.
- * MBR only supports up to 2 terabytes, while GPT uses 64-bit addresses which allows it to support disks up to 8 million terabytes.
-
-
-
-If you have shopped for hard drives recently, then you know that many of today’s drives exceed the 2 terabyte limit.
-
-#### The EFI system partition
-
-If you are doing a fresh installation or using a new drive, there are probably no partitions to begin with. In this case, the OS installer will create the first one, which is the [EFI System Partition (ESP)][10]. If you choose to manually partition your drive using a tool such as [gdisk][11], you will need to create this partition with several parameters. Based on the existing ESP, I set the size to around 500MB and assigned it the ef00 (EFI System) partition type. The UEFI specification requires the format to be FAT32/msdos, most likely because it is supportable by a wide range of operating systems.
-
-![Partitions][12]
-
-### Operating System Installation
-
-Once you accomplish the first two tasks, you can install your operating systems. While I focus on Windows 10 and Fedora Linux here, the process is fairly similar when installing other combinations as well.
-
-#### Windows 10
-
-I started the Windows 10 installation and created a 20 Gigabyte Windows partition. Since I had previously installed Linux on my laptop, the drive had an ESP, which I chose to keep. I deleted all existing Linux and swap partitions to start fresh, and then started my Windows installation. The Windows installer automatically created another small partition—16 Megabytes—called the [Microsoft Reserved Partition (MSR)][13]. Roughly 400 Gigabytes of unallocated space remained on the 512GB boot drive once this was finished.
-
-I then proceeded with and completed the Windows 10 installation process. I then rebooted into Windows to make sure it was working, created my user account, set up wi-fi, and completed other tasks that need to be done on a first-time OS installation.
-
-#### Fedora Linux
-
-I next moved to install Linux. I started the process, and when it reached the disk configuration steps, I made sure not to change the Windows NTFS and MSR partitions. I also did not change the EPS, but I did set its mount point to **/boot/efi**. I then created the usual ext4 formatted partitions, **/** (root), **/boot** , and **/home**. The last partition I created was Linux **swap**.
-
-As with Windows, I continued and completed the Linux installation, and then rebooted. To my delight, at boot time the [GRand][14] [Unified Boot Loader (GRUB)][14] menu provided the choice to select either Windows or Linux, which meant I did not have to do any additional configuration. I selected Linux and completed the usual steps such as creating my user account.
-
-### Conclusion
-
-Overall, the process was painless. In past years, there has been some difficulty navigating the changes from UEFI to BIOS, plus the introduction of features such as Secure Boot. I believe that we have now made it past these hurdles and can reliably set up multi-boot systems.
-
-I don’t miss the [Linux LOader (LILO)][15] anymore!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/5/dual-booting-windows-linux-uefi
-
-作者:[Alan Formy-Duval][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/alanfdoss/users/ckrzen
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_keyboard_desktop.png?itok=I2nGw78_ (Linux keys on the keyboard for a desktop computer)
-[2]: https://www.ubuntu.com
-[3]: https://www.microsoft.com/en-us/windows
-[4]: https://getfedora.org
-[5]: https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface
-[6]: https://en.wikipedia.org/wiki/BIOS
-[7]: https://fedoraproject.org/wiki/Features/SecureBoot
-[8]: https://en.wikipedia.org/wiki/GUID_Partition_Table
-[9]: https://en.wikipedia.org/wiki/Master_boot_record
-[10]: https://en.wikipedia.org/wiki/EFI_system_partition
-[11]: https://sourceforge.net/projects/gptfdisk/
-[12]: /sites/default/files/u216961/gdisk_screenshot_s.png
-[13]: https://en.wikipedia.org/wiki/Microsoft_Reserved_Partition
-[14]: https://en.wikipedia.org/wiki/GNU_GRUB
-[15]: https://en.wikipedia.org/wiki/LILO_(boot_loader)
diff --git a/sources/tech/20190527 How To Enable Or Disable SSH Access For A Particular User Or Group In Linux.md b/sources/tech/20190527 How To Enable Or Disable SSH Access For A Particular User Or Group In Linux.md
deleted file mode 100644
index a717d05ed8..0000000000
--- a/sources/tech/20190527 How To Enable Or Disable SSH Access For A Particular User Or Group In Linux.md
+++ /dev/null
@@ -1,300 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How To Enable Or Disable SSH Access For A Particular User Or Group In Linux?)
-[#]: via: (https://www.2daygeek.com/allow-deny-enable-disable-ssh-access-user-group-in-linux/)
-[#]: author: (2daygeek http://www.2daygeek.com/author/2daygeek/)
-
-How To Enable Or Disable SSH Access For A Particular User Or Group In Linux?
-======
-
-As per your organization standard policy, you may need to allow only the list of users that are allowed to access the Linux system.
-
-Or you may need to allow only few groups, which are allowed to access the Linux system.
-
-How to achieve this? What is the best way? How to achieve this in a simple way?
-
-Yes, there are many ways are available to perform this.
-
-However, we need to go with simple and easy method.
-
-If so, it can be done by making the necessary changes in `/etc/ssh/sshd_config` file.
-
-In this article we will show you, how to perform this in details.
-
-Why are we doing this? due to security reason. Navigate to the following URL to know more about **[openSSH][1]** usage.
-
-### What Is SSH?
-
-openssh stands for OpenBSD Secure Shell. Secure Shell (ssh) is a free open source networking tool which allow us to access remote system over an unsecured network using Secure Shell (SSH) protocol.
-
-It’s a client-server architecture. It handles user authentication, encryption, transferring files between computers and tunneling.
-
-These can be accomplished via traditional tools such as telnet or rcp, these are insecure and use transfer password in cleartext format while performing any action.
-
-### How To Allow A User To Access SSH In Linux?
-
-We can allow/enable the ssh access for a particular user or list of the users using the following method.
-
-If you would like to allow more than one user then you have to add the users with space in the same line.
-
-To do so, just append the following value into `/etc/ssh/sshd_config` file. In this example, we are going to allow ssh access for `user3`.
-
-```
-# echo "AllowUsers user3" >> /etc/ssh/sshd_config
-```
-
-You can double check this by running the following command.
-
-```
-# cat /etc/ssh/sshd_config | grep -i allowusers
-AllowUsers user3
-```
-
-That’s it. Just bounce the ssh service and see the magic.
-
-```
-# systemctl restart sshd
-
-# service restart sshd
-```
-
-Simple open a new terminal or session and try to access the Linux system with different user. Yes, `user2` isn’t allowed for SSH login and will be getting an error message as shown below.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-Permission denied, please try again.
-```
-
-Output:
-
-```
-Mar 29 02:00:35 CentOS7 sshd[4900]: User user2 from 192.168.1.6 not allowed because not listed in AllowUsers
-Mar 29 02:00:35 CentOS7 sshd[4900]: input_userauth_request: invalid user user2 [preauth]
-Mar 29 02:00:40 CentOS7 unix_chkpwd[4902]: password check failed for user (user2)
-Mar 29 02:00:40 CentOS7 sshd[4900]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.6 user=user2
-Mar 29 02:00:43 CentOS7 sshd[4900]: Failed password for invalid user user2 from 192.168.1.6 port 42568 ssh2
-```
-
-At the same time `user3` is allowed to login into the system because it’s in allowed users list.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-[[email protected] ~]$
-```
-
-Output:
-
-```
-Mar 29 02:01:13 CentOS7 sshd[4939]: Accepted password for user3 from 192.168.1.6 port 42590 ssh2
-Mar 29 02:01:13 CentOS7 sshd[4939]: pam_unix(sshd:session): session opened for user user3 by (uid=0)
-```
-
-### How To Deny Users To Access SSH In Linux?
-
-We can deny/disable the ssh access for a particular user or list of the users using the following method.
-
-If you would like to disable more than one user then you have to add the users with space in the same line.
-
-To do so, just append the following value into `/etc/ssh/sshd_config` file. In this example, we are going to disable ssh access for `user1`.
-
-```
-# echo "DenyUsers user1" >> /etc/ssh/sshd_config
-```
-
-You can double check this by running the following command.
-
-```
-# cat /etc/ssh/sshd_config | grep -i denyusers
-DenyUsers user1
-```
-
-That’s it. Just bounce the ssh service and see the magic.
-
-```
-# systemctl restart sshd
-
-# service restart sshd
-```
-
-Simple open a new terminal or session and try to access the Linux system with Deny user. Yes, `user1` is in denyusers list. So, you will be getting an error message as shown below when you are try to login.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-Permission denied, please try again.
-```
-
-Output:
-
-```
-Mar 29 01:53:42 CentOS7 sshd[4753]: User user1 from 192.168.1.6 not allowed because listed in DenyUsers
-Mar 29 01:53:42 CentOS7 sshd[4753]: input_userauth_request: invalid user user1 [preauth]
-Mar 29 01:53:46 CentOS7 unix_chkpwd[4755]: password check failed for user (user1)
-Mar 29 01:53:46 CentOS7 sshd[4753]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.6 user=user1
-Mar 29 01:53:48 CentOS7 sshd[4753]: Failed password for invalid user user1 from 192.168.1.6 port 42522 ssh2
-```
-
-### How To Allow Groups To Access SSH In Linux?
-
-We can allow/enable the ssh access for a particular group or groups using the following method.
-
-If you would like to allow more than one group then you have to add the groups with space in the same line.
-
-To do so, just append the following value into `/etc/ssh/sshd_config` file. In this example, we are going to disable ssh access for `2g-admin` group.
-
-```
-# echo "AllowGroups 2g-admin" >> /etc/ssh/sshd_config
-```
-
-You can double check this by running the following command.
-
-```
-# cat /etc/ssh/sshd_config | grep -i allowgroups
-AllowGroups 2g-admin
-```
-
-Run the following command to know the list of the users are belongs to this group.
-
-```
-# getent group 2g-admin
-2g-admin:x:1005:user1,user2,user3
-```
-
-That’s it. Just bounce the ssh service and see the magic.
-
-```
-# systemctl restart sshd
-
-# service restart sshd
-```
-
-Yes, `user3` is allowed to login into the system because user3 is belongs to `2g-admin` group.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-[[email protected] ~]$
-```
-
-Output:
-
-```
-Mar 29 02:10:21 CentOS7 sshd[5165]: Accepted password for user1 from 192.168.1.6 port 42640 ssh2
-Mar 29 02:10:22 CentOS7 sshd[5165]: pam_unix(sshd:session): session opened for user user1 by (uid=0)
-```
-
-Yes, `user2` is allowed to login into the system because user2 is belongs to `2g-admin` group.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-[[email protected] ~]$
-```
-
-Output:
-
-```
-Mar 29 02:10:38 CentOS7 sshd[5225]: Accepted password for user2 from 192.168.1.6 port 42642 ssh2
-Mar 29 02:10:38 CentOS7 sshd[5225]: pam_unix(sshd:session): session opened for user user2 by (uid=0)
-```
-
-When you are try to login into the system with other users which are not part of this group then you will be getting an error message as shown below.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-Permission denied, please try again.
-```
-
-Output:
-
-```
-Mar 29 02:12:36 CentOS7 sshd[5306]: User ladmin from 192.168.1.6 not allowed because none of user's groups are listed in AllowGroups
-Mar 29 02:12:36 CentOS7 sshd[5306]: input_userauth_request: invalid user ladmin [preauth]
-Mar 29 02:12:56 CentOS7 unix_chkpwd[5310]: password check failed for user (ladmin)
-Mar 29 02:12:56 CentOS7 sshd[5306]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.6 user=ladmin
-Mar 29 02:12:58 CentOS7 sshd[5306]: Failed password for invalid user ladmin from 192.168.1.6 port 42674 ssh2
-```
-
-### How To Deny Group To Access SSH In Linux?
-
-We can deny/disable the ssh access for a particular group or groups using the following method.
-
-If you would like to disable more than one group then you need to add the group with space in the same line.
-
-To do so, just append the following value into `/etc/ssh/sshd_config` file.
-
-```
-# echo "DenyGroups 2g-admin" >> /etc/ssh/sshd_config
-```
-
-You can double check this by running the following command.
-
-```
-# # cat /etc/ssh/sshd_config | grep -i denygroups
-DenyGroups 2g-admin
-
-# getent group 2g-admin
-2g-admin:x:1005:user1,user2,user3
-```
-
-That’s it. Just bounce the ssh service and see the magic.
-
-```
-# systemctl restart sshd
-
-# service restart sshd
-```
-
-Yes `user3` isn’t allowed to login into the system because it’s not part of `2g-admin` group. It’s in Denygroups.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-Permission denied, please try again.
-```
-
-Output:
-
-```
-Mar 29 02:17:32 CentOS7 sshd[5400]: User user1 from 192.168.1.6 not allowed because a group is listed in DenyGroups
-Mar 29 02:17:32 CentOS7 sshd[5400]: input_userauth_request: invalid user user1 [preauth]
-Mar 29 02:17:38 CentOS7 unix_chkpwd[5402]: password check failed for user (user1)
-Mar 29 02:17:38 CentOS7 sshd[5400]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.6 user=user1
-Mar 29 02:17:41 CentOS7 sshd[5400]: Failed password for invalid user user1 from 192.168.1.6 port 42710 ssh2
-```
-
-Anyone can login into the system except `2g-admin` group. Hence, `ladmin` user is allowed to login into the system.
-
-```
-# ssh [email protected]
-[email protected]'s password:
-[[email protected] ~]$
-```
-
-Output:
-
-```
-Mar 29 02:19:13 CentOS7 sshd[5432]: Accepted password for ladmin from 192.168.1.6 port 42716 ssh2
-Mar 29 02:19:13 CentOS7 sshd[5432]: pam_unix(sshd:session): session opened for user ladmin by (uid=0)
-```
-
---------------------------------------------------------------------------------
-
-via: https://www.2daygeek.com/allow-deny-enable-disable-ssh-access-user-group-in-linux/
-
-作者:[2daygeek][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: http://www.2daygeek.com/author/2daygeek/
-[b]: https://github.com/lujun9972
-[1]: https://www.2daygeek.com/category/ssh-tutorials/
diff --git a/sources/tech/20190612 How to write a loop in Bash.md b/sources/tech/20190612 How to write a loop in Bash.md
deleted file mode 100644
index f63bff9cd3..0000000000
--- a/sources/tech/20190612 How to write a loop in Bash.md
+++ /dev/null
@@ -1,282 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to write a loop in Bash)
-[#]: via: (https://opensource.com/article/19/6/how-write-loop-bash)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth/users/goncasousa/users/howtopamm/users/howtopamm/users/seth/users/wavesailor/users/seth)
-
-How to write a loop in Bash
-======
-Automatically perform a set of actions on multiple files with for loops
-and find commands.
-![bash logo on green background][1]
-
-A common reason people want to learn the Unix shell is to unlock the power of batch processing. If you want to perform some set of actions on many files, one of the ways to do that is by constructing a command that iterates over those files. In programming terminology, this is called _execution control,_ and one of the most common examples of it is the **for** loop.
-
-A **for** loop is a recipe detailing what actions you want your computer to take _for_ each data object (such as a file) you specify.
-
-### The classic for loop
-
-An easy loop to try is one that analyzes a collection of files. This probably isn't a useful loop on its own, but it's a safe way to prove to yourself that you have the ability to handle each file in a directory individually. First, create a simple test environment by creating a directory and placing some copies of some files into it. Any file will do initially, but later examples require graphic files (such as JPEG, PNG, or similar). You can create the folder and copy files into it using a file manager or in the terminal:
-
-
-```
-$ mkdir example
-$ cp ~/Pictures/vacation/*.{png,jpg} example
-```
-
-Change directory to your new folder, then list the files in it to confirm that your test environment is what you expect:
-
-
-```
-$ cd example
-$ ls -1
-cat.jpg
-design_maori.png
-otago.jpg
-waterfall.png
-```
-
-The syntax to loop through each file individually in a loop is: create a variable ( **f** for file, for example). Then define the data set you want the variable to cycle through. In this case, cycle through all files in the current directory using the ***** wildcard character (the ***** wildcard matches _everything_ ). Then terminate this introductory clause with a semicolon ( **;** ).
-
-
-```
-`$ for f in * ;`
-```
-
-Depending on your preference, you can choose to press **Return** here. The shell won't try to execute the loop until it is syntactically complete.
-
-Next, define what you want to happen with each iteration of the loop. For simplicity, use the **file** command to get a little bit of data about each file, represented by the **f** variable (but prepended with a **$** to tell the shell to swap out the value of the variable for whatever the variable currently contains):
-
-
-```
-`do file $f ;`
-```
-
-Terminate the clause with another semi-colon and close the loop:
-
-
-```
-`done`
-```
-
-Press **Return** to start the shell cycling through _everything_ in the current directory. The **for** loop assigns each file, one by one, to the variable **f** and runs your command:
-
-
-```
-$ for f in * ; do
-> file $f ;
-> done
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-You can also write it this way:
-
-
-```
-$ for f in *; do file $f; done
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-Both the multi-line and single-line formats are the same to your shell and produce the exact same results.
-
-### A practical example
-
-Here's a practical example of how a loop can be useful for everyday computing. Assume you have a collection of vacation photos you want to send to friends. Your photo files are huge, making them too large to email and inconvenient to upload to your [photo-sharing service][2]. You want to create smaller web-versions of your photos, but you have 100 photos and don't want to spend the time reducing each photo, one by one.
-
-First, install the **ImageMagick** command using your package manager on Linux, BSD, or Mac. For instance, on Fedora and RHEL:
-
-
-```
-`$ sudo dnf install ImageMagick`
-```
-
-On Ubuntu or Debian:
-
-
-```
-`$ sudo apt install ImageMagick`
-```
-
-On BSD, use **ports** or [pkgsrc][3]. On Mac, use [Homebrew][4] or [MacPorts][5].
-
-Once you install ImageMagick, you have a set of new commands to operate on photos.
-
-Create a destination directory for the files you're about to create:
-
-
-```
-`$ mkdir tmp`
-```
-
-To reduce each photo to 33% of its original size, try this loop:
-
-
-```
-`$ for f in * ; do convert $f -scale 33% tmp/$f ; done`
-```
-
-Then look in the **tmp** folder to see your scaled photos.
-
-You can use any number of commands within a loop, so if you need to perform complex actions on a batch of files, you can place your whole workflow between the **do** and **done** statements of a **for** loop. For example, suppose you want to copy each processed photo straight to a shared photo directory on your web host and remove the photo file from your local system:
-
-
-```
-$ for f in * ; do
-convert $f -scale 33% tmp/$f
-scp -i seth_web tmp/$f [seth@example.com][6]:~/public_html
-trash tmp/$f ;
-done
-```
-
-For each file processed by the **for** loop, your computer automatically runs three commands. This means if you process just 10 photos this way, you save yourself 30 commands and probably at least as many minutes.
-
-### Limiting your loop
-
-A loop doesn't always have to look at every file. You might want to process only the JPEG files in your example directory:
-
-
-```
-$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done
-$ ls -m tmp
-cat.jpg, otago.jpg
-```
-
-Or, instead of processing files, you may need to repeat an action a specific number of times. A **for** loop's variable is defined by whatever data you provide it, so you can create a loop that iterates over numbers instead of files:
-
-
-```
-$ for n in {0..4}; do echo $n ; done
-0
-1
-2
-3
-4
-```
-
-### More looping
-
-You now know enough to create your own loops. Until you're comfortable with looping, use them on _copies_ of the files you want to process and, as often as possible, use commands with built-in safeguards to prevent you from clobbering your data and making irreparable mistakes, like accidentally renaming an entire directory of files to the same name, each overwriting the other.
-
-For advanced **for** loop topics, read on.
-
-### Not all shells are Bash
-
-The **for** keyword is built into the Bash shell. Many similar shells use the same keyword and syntax, but some shells, like [tcsh][7], use a different keyword, like **foreach** , instead.
-
-In tcsh, the syntax is similar in spirit but more strict than Bash. In the following code sample, do not type the string **foreach?** in lines 2 and 3. It is a secondary prompt alerting you that you are still in the process of building your loop.
-
-
-```
-$ foreach f (*)
-foreach? file $f
-foreach? end
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-In tcsh, both **foreach** and **end** must appear alone on separate lines, so you cannot create a **for** loop on one line as you can with Bash and similar shells.
-
-### For loops with the find command
-
-In theory, you could find a shell that doesn't provide a **for** loop function, or you may just prefer to use a different command with added features.
-
-The **find** command is another way to implement the functionality of a **for** loop, as it offers several ways to define the scope of which files to include in your loop as well as options for [Parallel][8] processing.
-
-The **find** command is meant to help you find files on your hard drives. Its syntax is simple: you provide the path of the location you want to search, and **find** finds all files and directories:
-
-
-```
-$ find .
-.
-./cat.jpg
-./design_maori.png
-./otago.jpg
-./waterfall.png
-```
-
-You can filter the search results by adding some portion of the name:
-
-
-```
-$ find . -name "*jpg"
-./cat.jpg
-./otago.jpg
-```
-
-The great thing about **find** is that each file it finds can be fed into a loop using the **-exec** flag. For instance, to scale down only the PNG photos in your example directory:
-
-
-```
-$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
-$ ls -m tmp
-design_maori.png, waterfall.png
-```
-
-In the **-exec** clause, the bracket characters **{}** stand in for whatever item **find** is processing (in other words, any file ending in PNG that has been located, one at a time). The **-exec** clause must be terminated with a semicolon, but Bash usually tries to use the semicolon for itself. You "escape" the semicolon with a backslash ( **\;** ) so that **find** knows to treat that semicolon as its terminating character.
-
-The **find** command is very good at what it does, and it can be too good sometimes. For instance, if you reuse it to find PNG files for another photo process, you will get a few errors:
-
-
-```
-$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;
-convert: unable to open image `tmp/./tmp/design_maori.png':
-No such file or directory @ error/blob.c/OpenBlob/2643.
-...
-```
-
-It seems that **find** has located all the PNG files—not only the ones in your current directory ( **.** ) but also those that you processed before and placed in your **tmp** subdirectory. In some cases, you may want **find** to search the current directory plus all other directories within it (and all directories in _those_ ). It can be a powerful recursive processing tool, especially in complex file structures (like directories of music artists containing directories of albums filled with music files), but you can limit this with the **-maxdepth** option.
-
-To find only PNG files in the current directory (excluding subdirectories):
-
-
-```
-`$ find . -maxdepth 1 -name "*png"`
-```
-
-To find and process files in the current directory plus an additional level of subdirectories, increment the maximum depth by 1:
-
-
-```
-`$ find . -maxdepth 2 -name "*png"`
-```
-
-Its default is to descend into all subdirectories.
-
-### Looping for fun and profit
-
-The more you use loops, the more time and effort you save, and the bigger the tasks you can tackle. You're just one user, but with a well-thought-out loop, you can make your computer do the hard work.
-
-You can and should treat looping like any other command, keeping it close at hand for when you need to repeat a single action or two on several files. However, it's also a legitimate gateway to serious programming, so if you have to accomplish a complex task on any number of files, take a moment out of your day to plan out your workflow. If you can achieve your goal on one file, then wrapping that repeatable process in a **for** loop is relatively simple, and the only "programming" required is an understanding of how variables work and enough organization to separate unprocessed from processed files. With a little practice, you can move from a Linux user to a Linux user who knows how to write a loop, so get out there and make your computer work for you!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/how-write-loop-bash
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth/users/goncasousa/users/howtopamm/users/howtopamm/users/seth/users/wavesailor/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
-[2]: http://nextcloud.com
-[3]: http://pkgsrc.org
-[4]: http://brew.sh
-[5]: https://www.macports.org
-[6]: mailto:seth@example.com
-[7]: https://en.wikipedia.org/wiki/Tcsh
-[8]: https://opensource.com/article/18/5/gnu-parallel
diff --git a/sources/tech/20190612 Why use GraphQL.md b/sources/tech/20190612 Why use GraphQL.md
deleted file mode 100644
index ad0d3a0056..0000000000
--- a/sources/tech/20190612 Why use GraphQL.md
+++ /dev/null
@@ -1,97 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Why use GraphQL?)
-[#]: via: (https://opensource.com/article/19/6/why-use-graphql)
-[#]: author: (Zach Lendon https://opensource.com/users/zachlendon/users/goncasousa/users/patrickhousley)
-
-Why use GraphQL?
-======
-Here's why GraphQL is gaining ground on standard REST API technology.
-![][1]
-
-[GraphQL][2], as I wrote [previously][3], is a next-generation API technology that is transforming both how client applications communicate with backend systems and how backend systems are designed.
-
-As a result of the support that began with the organization that founded it, Facebook, and continues with the backing of other technology giants such as Github, Twitter, and AirBnB, GraphQL's place as a linchpin technology for application systems seems secure; both now and long into the future.
-
-### GraphQL's ascent
-
-The rise in importance of mobile application performance and organizational agility has provided booster rockets for GraphQL's ascent to the top of modern enterprise architectures.
-
-Given that [REST][4] is a wildly popular architectural style that already allows mechanisms for data interaction, what advantages does this new technology provide over [REST][4]? The ‘QL’ in GraphQL stands for query language, and that is a great place to start.
-
-The ease at which different client applications within an organization can query only the data they need with GraphQL usurps alternative REST approaches and delivers real-world application performance boosts. With traditional [REST][4] API endpoints, client applications interrogate a server resource, and receive a response containing all the data that matches the request. If a successful response from a [REST][4] API endpoint returns 35 fields, the client application receives 35 fields
-
-### Fetching problems
-
-[REST][4] APIs traditionally provide no clean way for client applications to retrieve or update only the data they care about. This is often described as the “over-fetching” problem. With the prevalence of mobile applications in people’s day to day lives, the over-fetching problem has real world consequences. Every request a mobile application needs to make, every byte it has to send and receive, has an increasingly negative performance impact for end users. Users with slower data connections are particularly affected by suboptimal API design choices. Customers who experience poor performance using mobile applications are more likely to not purchase products and use services. Inefficient API designs cost companies money.
-
-“Over-fetching” isn’t alone - it has a partner in crime - “under-fetching”. Endpoints that, by default, return only a portion of the data a client actually needs require clients to make additional calls to satisfy their data needs - which requires additional HTTP requests. Because of the over and under fetching problems and their impact on client application performance, an API technology that facilitates efficient fetching has a chance to catch fire in the marketplace - and GraphQL has boldly jumped in and filled that void.
-
-### REST's response
-
-[REST][4] API designers, not willing to go down without a fight, have attempted to counter the mobile application performance problem through a mix of:
-
- * “include” and “exclude” query parameters, allowing client applications to specify which fields they want through a potentially long query format.
- * “Composite” services, which combine multiple endpoints in a way that allow client applications to be more efficient in the number of requests they make and the data they receive.
-
-
-
-While these patterns are a valiant attempt by the [REST][4] API community to address challenges mobile clients face, they fall short in a few key regards, namely:
-
- * Include and exclude query key/value pairs quickly get messy, in particular for deeper object graphs that require a nested dot notation syntax (or similar) to target data to include and exclude. Additionally, debugging issues with the query string in this model often requires manually breaking up a URL.
- * Server implementations for include and exclude queries are often custom, as there is no standard way for server-based applications to handle the use of include and exclude queries, just as there is no standard way for include and exclude queries to be defined.
- * The rise of composite services creates more tightly coupled back-end and front-end systems, requiring increasing coordination to deliver projects and turning once agile projects back to waterfall. This coordination and coupling has the painful side effect of slowing organizational agility. Additionally, composite services are by definition, not RESTful.
-
-
-
-### GraphQL's genesis
-
-For Facebook, GraphQL’s genesis was a response to pain felt and experiences learned from an HTML5-based version of their flagship mobile application back in 2011-2012. Understanding that improved performance was paramount, Facebook engineers realized that they needed a new API design to ensure peak performance. Likely taking the above [REST][4] limitations into consideration, and with needing to support different needs of a number of API clients, one can begin to understand the early seeds of what led co-creators Lee Byron and Dan Schaeffer, Facebook employees at the time, to create what has become known as GraphQL.
-
-With what is often a single GraphQL endpoint, through the GraphQL query language, client applications are able to reduce, often significantly, the number of network calls they need to make, and ensure that they only are retrieving the data they need. In many ways, this harkens back to earlier models of web programming, where client application code would directly query back-end systems - some might remember writing SQL queries with JSTL on JSPs 10-15 years ago for example!
-
-The biggest difference now is with GraphQL, we have a specification that is implemented across a variety of client and server languages and libraries. And with GraphQL being an API technology, we have decoupled the back-end and front-end application systems by introducing an intermediary GraphQL application layer that provides a mechanism to access organizational data in a manner that aligns with an organization’s business domain(s).
-
-Beyond solving technical challenges experienced by software engineering teams, GraphQL has also been a boost to organizational agility, in particular in the enterprise. GraphQL-enabled organizational agility increases are commonly attributable to the following:
-
- * Rather than creating new endpoints when 1 or more new fields are needed by clients, GraphQL API designers and developers are able to include those fields in existing graph implementations, exposing new capabilities in a fashion that requires less development effort and less change across application systems.
- * By encouraging API design teams to focus more on defining their object graph and be less focused on what client applications are delivering, the speed at which front-end and back-end software teams deliver solutions for customers has increasingly decoupled.
-
-
-
-### Considerations before adoption
-
-Despite GraphQL’s compelling benefits, GraphQL is not without its implementation challenges. A few examples include:
-
- * Caching mechanisms around [REST][4] APIs are much more mature.
- * The patterns used to build APIs using [REST][4] are much more well established.
- * While engineers may be more attracted to newer technologies like GraphQL, the talent pool in the marketplace is much broader for building [REST][4]-based solutions vs. GraphQL.
-
-
-
-### Conclusion
-
-By providing both a boost to performance and organizational agility, GraphQL's adoption by companies has skyrocketed in the past few years. It does, however, have some maturing to do in comparison to the RESTful ecosystem of API design.
-
-One of the great benefits of GraphQL is that it’s not designed as a wholesale replacement for alternative API solutions. Instead, GraphQL can be implemented to complement or enhance existing APIs. As a result, companies are encouraged to explore incrementally adopting GraphQL where it makes the most sense for them - where they find it has the greatest positive impact on application performance and organizational agility.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/why-use-graphql
-
-作者:[Zach Lendon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/zachlendon/users/goncasousa/users/patrickhousley
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_graph_stats_blue.png?itok=OKCc_60D
-[2]: https://graphql.org/
-[3]: https://opensource.com/article/19/6/what-is-graphql
-[4]: https://en.wikipedia.org/wiki/Representational_state_transfer
diff --git a/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md b/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md
deleted file mode 100644
index 724c97bc01..0000000000
--- a/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md
+++ /dev/null
@@ -1,337 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to use OpenSSL: Hashes, digital signatures, and more)
-[#]: via: (https://opensource.com/article/19/6/cryptography-basics-openssl-part-2)
-[#]: author: (Marty Kalin https://opensource.com/users/mkalindepauledu)
-
-How to use OpenSSL: Hashes, digital signatures, and more
-======
-Dig deeper into the details of cryptography with OpenSSL: Hashes,
-digital signatures, digital certificates, and more
-![A person working.][1]
-
-The [first article in this series][2] introduced hashes, encryption/decryption, digital signatures, and digital certificates through the OpenSSL libraries and command-line utilities. This second article drills down into the details. Let’s begin with hashes, which are ubiquitous in computing, and consider what makes a hash function _cryptographic_.
-
-### Cryptographic hashes
-
-The download page for the OpenSSL source code () contains a table with recent versions. Each version comes with two hash values: 160-bit SHA1 and 256-bit SHA256. These values can be used to verify that the downloaded file matches the original in the repository: The downloader recomputes the hash values locally on the downloaded file and then compares the results against the originals. Modern systems have utilities for computing such hashes. Linux, for instance, has **md5sum** and **sha256sum**. OpenSSL itself provides similar command-line utilities.
-
-Hashes are used in many areas of computing. For example, the Bitcoin blockchain uses SHA256 hash values as block identifiers. To mine a Bitcoin is to generate a SHA256 hash value that falls below a specified threshold, which means a hash value with at least N leading zeroes. (The value of N can go up or down depending on how productive the mining is at a particular time.) As a point of interest, today’s miners are hardware clusters designed for generating SHA256 hashes in parallel. During a peak time in 2018, Bitcoin miners worldwide generated about 75 million terahashes per second—yet another incomprehensible number.
-
-Network protocols use hash values as well—often under the name **checksum**—to support message integrity; that is, to assure that a received message is the same as the one sent. The message sender computes the message’s checksum and sends the results along with the message. The receiver recomputes the checksum when the message arrives. If the sent and the recomputed checksum do not match, then something happened to the message in transit, or to the sent checksum, or to both. In this case, the message and its checksum should be sent again, or at least an error condition should be raised. (Low-level network protocols such as UDP do not bother with checksums.)
-
-Other examples of hashes are familiar. Consider a website that requires users to authenticate with a password, which the user enters in their browser. Their password is then sent, encrypted, from the browser to the server via an HTTPS connection to the server. Once the password arrives at the server, it's decrypted for a database table lookup.
-
-What should be stored in this lookup table? Storing the passwords themselves is risky. It’s far less risky is to store a hash generated from a password, perhaps with some _salt_ (extra bits) added to taste before the hash value is computed. Your password may be sent to the web server, but the site can assure you that the password is not stored there.
-
-Hash values also occur in various areas of security. For example, hash-based message authentication code ([HMAC][3]) uses a hash value and a secret cryptographic key to authenticate a message sent over a network. HMAC codes, which are lightweight and easy to use in programs, are popular in web services. An X509 digital certificate includes a hash value known as the _fingerprint_, which can facilitate certificate verification. An in-memory truststore could be implemented as a lookup table keyed on such fingerprints—as a _hash map_, which supports constant-time lookups. The fingerprint from an incoming certificate can be compared against the truststore keys for a match.
-
-What special property should a _cryptographic hash function_ have? It should be _one-way_, which means very difficult to invert. A cryptographic hash function should be relatively straightforward to compute, but computing its inverse—the function that maps the hash value back to the input bitstring—should be computationally intractable. Here is a depiction, with **chf** as a cryptographic hash function and my password **foobar** as the sample input:
-
-
-```
- +---+
-foobar—>|chf|—>hash value ## straightforward
- +--–+
-```
-
-By contrast, the inverse operation is infeasible:
-
-
-```
- +-----------+
-hash value—>|chf inverse|—>foobar ## intractable
- +-----------+
-```
-
-Recall, for example, the SHA256 hash function. For an input bitstring of any length N > 0, this function generates a fixed-length hash value of 256 bits; hence, this hash value does not reveal even the input bitstring’s length N, let alone the value of each bit in the string. By the way, SHA256 is not susceptible to a [_length extension attack_][4]. The only effective way to reverse engineer a computed SHA256 hash value back to the input bitstring is through a brute-force search, which means trying every possible input bitstring until a match with the target hash value is found. Such a search is infeasible on a sound cryptographic hash function such as SHA256.
-
-Now, a final review point is in order. Cryptographic hash values are statistically rather than unconditionally unique, which means that it is unlikely but not impossible for two different input bitstrings to yield the same hash value—a _collision_. The [_birthday problem_][5] offers a nicely counter-intuitive example of collisions. There is extensive research on various hash algorithms’ _collision resistance_. For example, MD5 (128-bit hash values) has a breakdown in collision resistance after roughly 221 hashes. For SHA1 (160-bit hash values), the breakdown starts at about 261 hashes.
-
-A good estimate of the breakdown in collision resistance for SHA256 is not yet in hand. This fact is not surprising. SHA256 has a range of 2256 distinct hash values, a number whose decimal representation has a whopping 78 digits! So, can collisions occur with SHA256 hashing? Of course, but they are extremely unlikely.
-
-In the command-line examples that follow, two input files are used as bitstring sources: **hashIn1.txt** and **hashIn2.txt**. The first file contains **abc** and the second contains **1a2b3c**.
-
-These files contain text for readability, but binary files could be used instead.
-
-Using the Linux **sha256sum** utility on these two files at the command line—with the percent sign (**%**) as the prompt—produces the following hash values (in hex):
-
-
-```
-% sha256sum hashIn1.txt
-9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3 hashIn1.txt
-
-% sha256sum hashIn2.txt
-3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13 hashIn2.txt
-```
-
-The OpenSSL hashing counterparts yield the same results, as expected:
-
-
-```
-% openssl dgst -sha256 hashIn1.txt
-SHA256(hashIn1.txt)= 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3
-
-% openssl dgst -sha256 hashIn2.txt
-SHA256(hashIn2.txt)= 3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13
-```
-
-This examination of cryptographic hash functions sets up a closer look at digital signatures and their relationship to key pairs.
-
-### Digital signatures
-
-As the name suggests, a digital signature can be attached to a document or some other electronic artifact (e.g., a program) to vouch for its authenticity. Such a signature is thus analogous to a hand-written signature on a paper document. To verify the digital signature is to confirm two things. First, that the vouched-for artifact has not changed since the signature was attached because it is based, in part, on a cryptographic _hash_ of the document. Second, that the signature belongs to the person (e.g., Alice) who alone has access to the private key in a pair. By the way, digitally signing code (source or compiled) has become a common practice among programmers.
-
-Let’s walk through how a digital signature is created. As mentioned before, there is no digital signature without a public and private key pair. When using OpenSSL to create these keys, there are two separate commands: one to create a private key, and another to extract the matching public key from the private one. These key pairs are encoded in base64, and their sizes can be specified during this process.
-
-The private key consists of numeric values, two of which (a _modulus_ and an _exponent_) make up the public key. Although the private key file contains the public key, the extracted public key does _not_ reveal the value of the corresponding private key.
-
-The resulting file with the private key thus contains the full key pair. Extracting the public key into its own file is practical because the two keys have distinct uses, but this extraction also minimizes the danger that the private key might be publicized by accident.
-
-Next, the pair’s private key is used to process a hash value for the target artifact (e.g., an email), thereby creating the signature. On the other end, the receiver’s system uses the pair’s public key to verify the signature attached to the artifact.
-
-Now for an example. To begin, generate a 2048-bit RSA key pair with OpenSSL:
-
-**openssl genpkey -out privkey.pem -algorithm rsa 2048**
-
-We can drop the **-algorithm rsa** flag in this example because **genpkey** defaults to the type RSA. The file’s name (**privkey.pem**) is arbitrary, but the Privacy Enhanced Mail (PEM) extension **pem** is customary for the default PEM format. (OpenSSL has commands to convert among formats if needed.) If a larger key size (e.g., 4096) is in order, then the last argument of **2048** could be changed to **4096**. These sizes are always powers of two.
-
-Here’s a slice of the resulting **privkey.pem** file, which is in base64:
-
-
-```
-\-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANnlAh4jSKgcNj/Z
-JF4J4WdhkljP2R+TXVGuKVRtPkGAiLWE4BDbgsyKVLfs2EdjKL1U+/qtfhYsqhkK
-…
-\-----END PRIVATE KEY-----
-```
-
-The next command then extracts the pair’s public key from the private one:
-
-**openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem**
-
-The resulting **pubkey.pem** file is small enough to show here in full:
-
-
-```
-\-----BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ5QIeI0ioHDY/2SReCeFnYZJY
-z9kfk11RrilUbT5BgIi1hOAQ24LMilS37NhHYyi9VPv6rX4WLKoZCmkeYaWk/TR5
-4nbH1E/AkniwRoXpeh5VncwWMuMsL5qPWGY8fuuTE27GhwqBiKQGBOmU+MYlZonO
-O0xnAKpAvysMy7G7qQIDAQAB
-\-----END PUBLIC KEY-----
-```
-
-Now, with the key pair at hand, the digital signing is easy—in this case with the source file **client.c** as the artifact to be signed:
-
-**openssl dgst -sha256 -sign privkey.pem -out sign.sha256 client.c**
-
-The digest for the **client.c** source file is SHA256, and the private key resides in the **privkey.pem** file created earlier. The resulting binary signature file is **sign.sha256**, an arbitrary name. To get a readable (if base64) version of this file, the follow-up command is:
-
-**openssl enc -base64 -in sign.sha256 -out sign.sha256.base64**
-
-The file **sign.sha256.base64** now contains:
-
-
-```
-h+e+3UPx++KKSlWKIk34fQ1g91XKHOGFRmjc0ZHPEyyjP6/lJ05SfjpAJxAPm075
-VNfFwysvqRGmL0jkp/TTdwnDTwt756Ej4X3OwAVeYM7i5DCcjVsQf5+h7JycHKlM
-o/Jd3kUIWUkZ8+Lk0ZwzNzhKJu6LM5KWtL+MhJ2DpVc=
-```
-
-Or, the executable file **client** could be signed instead, and the resulting base64-encoded signature would differ as expected:
-
-
-```
-VMVImPgVLKHxVBapJ8DgLNJUKb98GbXgehRPD8o0ImADhLqlEKVy0HKRm/51m9IX
-xRAN7DoL4Q3uuVmWWi749Vampong/uT5qjgVNTnRt9jON112fzchgEoMb8CHNsCT
-XIMdyaPtnJZdLALw6rwMM55MoLamSc6M/MV1OrJnk/g=
-```
-
-The final step in this process is to verify the digital signature with the public key. The hash used to sign the artifact (in this case, the executable **client** program) should be recomputed as an essential step in the verification since the verification process should indicate whether the artifact has changed since being signed.
-
-There are two OpenSSL commands used for this purpose. The first decodes the base64 signature:
-
-**openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha256**
-
-The second verifies the signature:
-
-**openssl dgst -sha256 -verify pubkey.pem -signature sign.sha256 client**
-
-The output from this second command is, as it should be:
-
-
-```
-`Verified OK`
-```
-
-To understand what happens when verification fails, a short but useful exercise is to replace the executable **client** file in the last OpenSSL command with the source file **client.c** and then try to verify. Another exercise is to change the **client** program, however slightly, and try again.
-
-### Digital certificates
-
-A digital certificate brings together the pieces analyzed so far: hash values, key pairs, digital signatures, and encryption/decryption. The first step toward a production-grade certificate is to create a certificate signing request (CSR), which is then sent to a certificate authority (CA). To do this for the example with OpenSSL, run:
-
-**openssl req -out myserver.csr -new -newkey rsa:4096 -nodes -keyout myserverkey.pem**
-
-This example generates a CSR document and stores the document in the file **myserver.csr** (base64 text). The purpose here is this: the CSR document requests that the CA vouch for the identity associated with the specified domain name—the common name (CN) in CA-speak.
-
-A new key pair also is generated by this command, although an existing pair could be used. Note that the use of **server** in names such as **myserver.csr** and **myserverkey.pem** hints at the typical use of digital certificates: as vouchers for the identity of a web server associated with a domain such as [www.google.com][6].
-
-The same command, however, creates a CSR regardless of how the digital certificate might be used. It also starts an interactive question/answer session that prompts for relevant information about the domain name to link with the requester’s digital certificate. This interactive session can be short-circuited by providing the essentials as part of the command, with backslashes as continuations across line breaks. The **-subj** flag introduces the required information:
-
-
-```
-% openssl req -new
--newkey rsa:2048 -nodes -keyout privkeyDC.pem
--out myserver.csr
--subj "/C=US/ST=Illinois/L=Chicago/O=Faulty Consulting/OU=IT/CN=myserver.com"
-```
-
-The resulting CSR document can be inspected and verified before being sent to a CA. This process creates the digital certificate with the desired format (e.g., X509), signature, validity dates, and so on:
-
-**openssl req -text -in myserver.csr -noout -verify**
-
-Here’s a slice of the output:
-
-
-```
-verify OK
-Certificate Request:
-Data:
-Version: 0 (0x0)
-Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Subject Public Key Info:
-Public Key Algorithm: rsaEncryption
-Public-Key: (2048 bit)
-Modulus:
-00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e🇩🇪73:
-…
-Exponent: 65537 (0x10001)
-Attributes:
-a0:00
-Signature Algorithm: sha256WithRSAEncryption
-…
-```
-
-### A self-signed certificate
-
-During the development of an HTTPS web site, it is convenient to have a digital certificate on hand without going through the CA process. A self-signed certificate fills the bill during the HTTPS handshake’s authentication phase, although any modern browser warns that such a certificate is worthless. Continuing the example, the OpenSSL command for a self-signed certificate—valid for a year and with an RSA public key—is:
-
-**openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout myserver.pem -out myserver.crt**
-
-The OpenSSL command below presents a readable version of the generated certificate:
-
-**openssl x509 -in myserver.crt -text -noout**
-
-Here’s part of the output for the self-signed certificate:
-
-
-```
-Certificate:
-Data:
-Version: 3 (0x2)
-Serial Number: 13951598013130016090 (0xc19e087965a9055a)
-Signature Algorithm: sha256WithRSAEncryption
-Issuer: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Validity
-Not Before: Apr 11 17:22:18 2019 GMT
-Not After : Apr 10 17:22:18 2020 GMT
-Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Subject Public Key Info:
-Public Key Algorithm: rsaEncryption
-Public-Key: (4096 bit)
-Modulus:
-00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e🇩🇪73:
-…
-Exponent: 65537 (0x10001)
-X509v3 extensions:
-X509v3 Subject Key Identifier:
-3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
-X509v3 Authority Key Identifier:
-keyid:3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
-
- X509v3 Basic Constraints:
- CA:TRUE
-Signature Algorithm: sha256WithRSAEncryption
- 3a:eb:8d:09:53:3b:5c:2e:48:ed:14:ce:f9:20:01:4e:90:c9:
- ...
-```
-
-As mentioned earlier, an RSA private key contains values from which the public key is generated. However, a given public key does _not_ give away the matching private key. For an introduction to the underlying mathematics, see .
-
-There is an important correspondence between a digital certificate and the key pair used to generate the certificate, even if the certificate is only self-signed:
-
- * The digital certificate contains the _exponent_ and _modulus_ values that make up the public key. These values are part of the key pair in the originally-generated PEM file, in this case, the file **myserver.pem**.
- * The exponent is almost always 65,537 (as in this case) and so can be ignored.
- * The modulus from the key pair should match the modulus from the digital certificate.
-
-
-
-The modulus is a large value and, for readability, can be hashed. Here are two OpenSSL commands that check for the same modulus, thereby confirming that the digital certificate is based upon the key pair in the PEM file:
-
-
-```
-% openssl x509 -noout -modulus -in myserver.crt | openssl sha1 ## modulus from CRT
-(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
-
-% openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## modulus from PEM
-(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
-```
-
-The resulting hash values match, thereby confirming that the digital certificate is based upon the specified key pair.
-
-### Back to the key distribution problem
-
-Let’s return to an issue raised at the end of Part 1: the TLS handshake between the **client** program and the Google web server. There are various handshake protocols, and even the Diffie-Hellman version at work in the **client** example offers wiggle room. Nonetheless, the **client** example follows a common pattern.
-
-To start, during the TLS handshake, the **client** program and the web server agree on a cipher suite, which consists of the algorithms to use. In this case, the suite is **ECDHE-RSA-AES128-GCM-SHA256**.
-
-The two elements of interest now are the RSA key-pair algorithm and the AES128 block cipher used for encrypting and decrypting messages if the handshake succeeds. Regarding encryption/decryption, this process comes in two flavors: symmetric and asymmetric. In the symmetric flavor, the _same_ key is used to encrypt and decrypt, which raises the _key distribution problem_ in the first place: How is the key to be distributed securely to both parties? In the asymmetric flavor, one key is used to encrypt (in this case, the RSA public key) but a different key is used to decrypt (in this case, the RSA private key from the same pair).
-
-The **client** program has the Google web server’s public key from an authenticating certificate, and the web server has the private key from the same pair. Accordingly, the **client** program can send an encrypted message to the web server, which alone can readily decrypt this message.
-
-In the TLS situation, the symmetric approach has two significant advantages:
-
- * In the interaction between the **client** program and the Google web server, the authentication is one-way. The Google web server sends three certificates to the **client** program, but the **client** program does not send a certificate to the web server; hence, the web server has no public key from the client and can’t encrypt messages to the client.
- * Symmetric encryption/decryption with AES128 is nearly a _thousand times faster_ than the asymmetric alternative using RSA keys.
-
-
-
-The TLS handshake combines the two flavors of encryption/decryption in a clever way. During the handshake, the **client** program generates random bits known as the pre-master secret (PMS). Then the **client** program encrypts the PMS with the server’s public key and sends the encrypted PMS to the server, which in turn decrypts the PMS message with its private key from the RSA pair:
-
-
-```
- +-------------------+ encrypted PMS +--------------------+
-client PMS--->|server’s public key|--------------->|server’s private key|--->server PMS
- +-------------------+ +--------------------+
-```
-
-At the end of this process, the **client** program and the Google web server now have the same PMS bits. Each side uses these bits to generate a _master secret_ and, in short order, a symmetric encryption/decryption key known as the _session key_. There are now two distinct but identical session keys, one on each side of the connection. In the **client** example, the session key is of the AES128 variety. Once generated on both the **client** program’s and Google web server’s sides, the session key on each side keeps the conversation between the two sides confidential. A handshake protocol such as Diffie-Hellman allows the entire PMS process to be repeated if either side (e.g., the **client** program) or the other (in this case, the Google web server) calls for a restart of the handshake.
-
-### Wrapping up
-
-The OpenSSL operations illustrated at the command line are available, too, through the API for the underlying libraries. These two articles have emphasized the utilities to keep the examples short and to focus on the cryptographic topics. If you have an interest in security issues, OpenSSL is a fine place to start—and to stay.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-2
-
-作者:[Marty Kalin][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/mkalindepauledu
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_os_rh2x.png?itok=jbRfXinl (A person working.)
-[2]: https://opensource.com/article/19/6/cryptography-basics-openssl-part-1
-[3]: https://en.wikipedia.org/wiki/HMAC
-[4]: https://en.wikipedia.org/wiki/Length_extension_attack
-[5]: https://en.wikipedia.org/wiki/Birthday_problem
-[6]: http://www.google.com
diff --git a/sources/tech/20190624 Book Review- A Byte of Vim.md b/sources/tech/20190624 Book Review- A Byte of Vim.md
deleted file mode 100644
index e221a3bc6f..0000000000
--- a/sources/tech/20190624 Book Review- A Byte of Vim.md
+++ /dev/null
@@ -1,99 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Book Review: A Byte of Vim)
-[#]: via: (https://itsfoss.com/book-review-a-byte-of-vim/)
-[#]: author: (John Paul https://itsfoss.com/author/john/)
-
-Book Review: A Byte of Vim
-======
-
-[Vim][1] is a tool that is both simple and very powerful. Most new users will be intimidated by it because it doesn’t ‘work’ like regular graphical text editors. The ‘unusual’ keyboard shortcuts makes people wonder about [how to save and exit Vim][2]. But once you master Vim, there is nothing like it.
-
-There are numerous [Vim resources available online][3]. We have covered some Vim tricks on It’s FOSS as well. Apart from online resources, plenty of books have been dedicated to this editor as well. Today, we will look at one of such book that is designed to make Vim easy for most users to understand. The book we will be discussing is [A Byte of Vim][4] by [Swaroop C H][5].
-
-The author [Swaroop C H][6] has worked in computing for over a decade. He previously worked at Yahoo and Adobe. Out of college, he made money by selling Linux CDs. He started a number of businesses, including an iPod charger named ion. He is currently an engineering manager for the AI team at [Helpshift][7].
-
-### A Byte of Vim
-
-![][8]
-
-Like all good books, A Byte of Vim starts by talking about what Vim is: “a computer program used for writing any kind of text”. He does on to say, “What makes Vim special is that it is one of those few software which is both simple and powerful.”
-
-Before diving into telling how to use Vim, Swaroop tells the reader how to install Vim for Windows, Mac, Linux, and BSD. Once the installation is complete, he runs you through how to launch Vim and how to create your first file.
-
-Next, Swaroop discusses the different modes of Vim and how to navigate around your document using Vim’s keyboard shortcuts. This is followed by the basics of editing a document with Vim, including the Vim version of cut/copy/paste and undo/redo.
-
-Once the editing basics are covered, Swaroop talks about using Vim to edit multiple parts of a single document. You can also multiple tabs and windows to edit multiple documents at the same time.
-
-[][9]
-
-Suggested read Bring Your Old Computer Back to Life With 4MLinux
-
-The book also covers extending the functionality of Vim through scripting and installing plugins. There are two ways to using scripts in Vim, use Vim’s built-in scripting language or using a programming language like Python or Perl to access Vim’s internals. There are five types of Vim plugins that can be written or downloaded: vimrc, global plugin, filetype plugin, syntax highlighting plugin, and compiler plugin.
-
-In a separate section, Swaroop C H covers the features of Vim that make it good for programming. These features include syntax highlighting, smart indentation, support for shell commands, omnicompletion, and the ability to be used as an IDE.
-
-#### Getting the ‘A Byte of Vim’ book and contributing to it
-
-A Byte of Book is licensed under [Creative Commons 4.0][10]. You can read an online version of the book for free on [the author’s website][4]. You can also download a [PDF][11], [Epub][12], or [Mobi][13] for free.
-
-[Get A Byte of Vim for FREE][4]
-
-If you prefer reading a [hard copy][14], you have that option, as well.
-
-Please note that the _**original version of A Byte of Vim was written in 2008**_ and converted to PDf. Unfortunately, Swaroop C H lost the original source files and he is working to convert the book to [Markdown][15]. If you would like to help, please visit the [book’s GitHub page][16].
-
-Preview | Product | Price |
----|---|---|---
-![Mastering Vim Quickly: From WTF to OMG in no time][17] ![Mastering Vim Quickly: From WTF to OMG in no time][17] | [Mastering Vim Quickly: From WTF to OMG in no time][18] | $34.00[][19] | [Buy on Amazon][20]
-
-#### Conclusion
-
-When I first stared into the angry maw that is Vim, I did not have a clue what to do. I wish that I had known about A Byte of Vim then. This book is a good resource for anyone learning about Linux, especially if you are getting into the command line.
-
-Have you read [A Byte of Vim][4] by Swaroop C H? If yes, how do you find it? If not, what is your favorite book on an open source topic? Let us know in the comments below.
-
-[][21]
-
-Suggested read Iridium Browser: A Browser for the Privacy Conscious
-
-If you found this article interesting, please take a minute to share it on social media, Hacker News or [Reddit][22].
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/book-review-a-byte-of-vim/
-
-作者:[John Paul][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/john/
-[b]: https://github.com/lujun9972
-[1]: https://www.vim.org/
-[2]: https://itsfoss.com/how-to-exit-vim/
-[3]: https://linuxhandbook.com/basic-vim-commands/
-[4]: https://vim.swaroopch.com/
-[5]: https://swaroopch.com/
-[6]: https://swaroopch.com/about/
-[7]: https://www.helpshift.com/
-[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/06/Byte-of-vim-book.png?resize=800%2C450&ssl=1
-[9]: https://itsfoss.com/4mlinux-review/
-[10]: https://creativecommons.org/licenses/by/4.0/
-[11]: https://www.gitbook.com/download/pdf/book/swaroopch/byte-of-vim
-[12]: https://www.gitbook.com/download/epub/book/swaroopch/byte-of-vim
-[13]: https://www.gitbook.com/download/mobi/book/swaroopch/byte-of-vim
-[14]: https://swaroopch.com/buybook/
-[15]: https://itsfoss.com/best-markdown-editors-linux/
-[16]: https://github.com/swaroopch/byte-of-vim#status-incomplete
-[17]: https://i2.wp.com/images-na.ssl-images-amazon.com/images/I/41itW8furUL._SL160_.jpg?ssl=1
-[18]: https://www.amazon.com/Mastering-Vim-Quickly-WTF-time/dp/1983325740?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1983325740 (Mastering Vim Quickly: From WTF to OMG in no time)
-[19]: https://www.amazon.com/gp/prime/?tag=chmod7mediate-20 (Amazon Prime)
-[20]: https://www.amazon.com/Mastering-Vim-Quickly-WTF-time/dp/1983325740?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1983325740 (Buy on Amazon)
-[21]: https://itsfoss.com/iridium-browser-review/
-[22]: http://reddit.com/r/linuxusersgroup
diff --git a/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md b/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md
deleted file mode 100644
index 2a7fcb31de..0000000000
--- a/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md
+++ /dev/null
@@ -1,136 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (One CI/CD pipeline per product to rule them all)
-[#]: via: (https://opensource.com/article/19/7/cicd-pipeline-rule-them-all)
-[#]: author: (Willy-Peter Schaub https://opensource.com/users/wpschaub/users/bclaster/users/matt-micene/users/barkerd427)
-
-One CI/CD pipeline per product to rule them all
-======
-Is the idea of a unified continuous integration and delivery pipeline a
-pipe dream?
-![An intersection of pipes.][1]
-
-When I joined the cloud ops team, responsible for cloud operations and engineering process streamlining, at WorkSafeBC, I shared my dream for one instrumented pipeline, with one continuous integration build and continuous deliveries for every product.
-
-According to Lukas Klose, [flow][2] (within the context of software engineering) is "the state of when a system produces value at a steady and predictable rate." I think it is one of the greatest challenges and opportunities, especially in the complex domain of emergent solutions. Strive towards a continuous and incremental delivery model with consistent, efficient, and quality solutions, building the right things and delighting our users. Find ways to break down our systems into smaller pieces that are valuable on their own, enabling teams to deliver value incrementally. This requires a change of mindset for both business and engineering.
-
-### Continuous integration and delivery (CI/CD) pipeline
-
-The CI/CD pipeline is a DevOps practice for delivering code changes more often, consistently, and reliably. It enables agile teams to increase _deployment frequency_ and decrease _lead time for change_, _change-failure rate_, and _mean time to recovery_ key performance indicators (KPIs), thereby improving _quality_ and delivering _value_ faster. The only prerequisites are a solid development process, a mindset for quality and accountability for features from ideation to deprecation, and a comprehensive pipeline (as illustrated below).
-
-![Prerequisites for a solid development process][3]
-
-It streamlines the engineering process and products to stabilize infrastructure environments; optimize flow; and create consistent, repeatable, and automated tasks. This enables us to turn complex tasks into complicated tasks, as outlined by Dave Snowden's [Cynefin Sensemaking][4] model, reducing maintenance costs and increasing quality and reliability.
-
-Part of streamlining our flow is to minimize waste for the [wasteful practice types][5] Muri (overloaded), Mura (variation), and Muda (waste).
-
- * **Muri:** avoid over-engineering, features that do not link to business value, and excessive documentation
- * **Mura:** improve approval and validation processes (e.g., security signoffs); drive the [shift-left][6] initiative to push unit testing, security vulnerability scanning, and code quality inspection; and improve risk assessment
- * **Muda:** avoid waste such as technical debt, bugs, and upfront, detailed documentation
-
-
-
-It appears that 80% of the focus and intention is on products that provide an integrated and collaborative engineering system that can take an idea and plan, develop, test, and monitor your solutions. However, a successful transformation and engineering system is only 5% about products, 15% about process, and 80% about people.
-
-There are many products at our disposal. For example, Azure DevOps offers rich support for continuous integration (CI), continuous delivery (CD), extensibility, and integration with open source and commercial off-the-shelve (COTS) software as a service (SaaS) solutions such as Stryker, SonarQube, WhiteSource, Jenkins, and Octopus. For engineers, it is always a temptation to focus on products, but remember that they are only 5% of our journey.
-
-![5% about products, 15% about process, 80% about people][7]
-
-The biggest challenge is breaking down a process based on decades of rules, regulations, and frustrating areas of comfort: "_It is how we have always done it; why change?_"
-
-The friction between people in development and operation results in a variety of fragmented, duplicated, and incessant integration and delivery pipelines. Development wants access to everything, to iterate continuously, to enable users, and to release continuously and fast. Operations wants to lock down everything to protect the business and users and drive quality. This inadvertently and often entails processes and governance that are hard to automate, which results in slower-than-expected release cycles.
-
-Let us explore the pipeline with snippets from a recent whiteboard discussion.
-
-The variation of pipelines is difficult and costly to support; the inconsistency of versioning and traceability complicates live site incidents, and continuous streamlining of the development process and pipelines is a challenge.
-
-![Improving quality and visibility of pipelines][8]
-
-I advocate a few principles that enable one universal pipeline per product:
-
- * Automate everything automatable
- * Build once
- * Maintain continuous integration and delivery
- * Maintain continuous streamlining and improvement
- * Maintain one build definition
- * Maintain one release pipeline definition
- * Scan for vulnerabilities early and often, and _fail fast_
- * Test early and often, and _fail fast_
- * Maintain traceability and observability of releases
-
-
-
-If I poke the hornet's nest, however, the most important principle is to _keep it simple_. If you cannot explain the reason (_what_, _why_) and the process (_how_) of your pipelines, you do not understand your engineering process. Most of us are not looking for the best, ultramodern, and revolutionary pipeline—we need one that is functional, valuable, and an enabler for engineering. Tackle the 80%—the culture, people, and their mindset—first. Ask your CI/CD knights in shining armor, with their TLA (two/three-lettered acronym) symbols on their shield, to join the might of practical and empirical engineering.
-
-### Unified pipeline
-
-Let us walk through one of our design practice whiteboard sessions.
-
-![CI build/CD release pipeline][9]
-
-Define one CI/CD pipeline with one build definition per application that is used to trigger _pull-request pre-merge validation_ and _continuous integration_ builds. Generate a _release_ build with debug information and upload to the [Symbol Server][10]. ****This enables developers to debug locally and remotely in production without having to worry which build and symbols they need to load—the symbol server performs that magic for us.
-
-![Breaking down the CI build pipeline][11]
-
-Perform as many validations as possible in the build—_shift left_—allowing feature teams to fail fast, continuously raise the overall product quality, and include invaluable evidence for the reviewers with every pull request. Do you prefer a pull request with a gazillion commits? Or a pull request with a couple of commits and supporting evidence such as security vulnerabilities, test coverage, code quality, and [Stryker][12] mutant remnants? Personally, I vote for the latter.
-
-![Breaking down the CD release pipeline][13]
-
-Do not use build transformation to generate multiple, environment-specific builds. Create one build and perform release-time _transformation_, _tokenization_, and/or XML/JSON _value replacement_. In other words, _shift-right_ the environment-specific configuration.
-
-![Shift-right the environment-specific configuration][14]
-
-Securely store release configuration data and make it available to both Dev and Ops teams based on the level of _trust_ and _sensitivity_ of the data. Use the open source Key Manager, Azure Key Vault, AWS Key Management Service, or one of many other products—remember, there are many hammers in your toolkit!
-
-![Dev-QA-production pipeline][15]
-
-Use _groups_ instead of _users_ to move approver management from multiple stages across multiple pipelines to simple group membership.
-
-![Move approver management to simple group membership][16]
-
-Instead of duplicating pipelines to give teams access to their _areas of interest_, create one pipeline and grant access to _specific stages_ of the delivery environments.
-
-![Pipeline with access to specific delivery stages][17]
-
-Last, but not least, embrace pull requests to help raise insight and transparency into your codebase, improve the overall quality, collaborate, and release pre-validation builds into selected environments; e.g., the Dev environment.
-
-Here is a more formal view of the whole whiteboard sketch.
-
-![The full pipeline][18]
-
-So, what are your thoughts and learnings with CI/CD pipelines? Is my dream of _one pipeline to rule them all_ a pipe dream?
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/7/cicd-pipeline-rule-them-all
-
-作者:[Willy-Peter Schaub][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/wpschaub/users/bclaster/users/matt-micene/users/barkerd427
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LAW-Internet_construction_9401467_520x292_0512_dc.png?itok=RPkPPtDe (An intersection of pipes.)
-[2]: https://continuingstudies.sauder.ubc.ca/courses/agile-delivery-methods/ii861
-[3]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-2.png (Prerequisites for a solid development process)
-[4]: https://en.wikipedia.org/wiki/Cynefin_framework
-[5]: https://www.lean.org/lexicon/muda-mura-muri
-[6]: https://en.wikipedia.org/wiki/Shift_left_testing
-[7]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-3.png (5% about products, 15% about process, 80% about people)
-[8]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-4_0.png (Improving quality and visibility of pipelines)
-[9]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-5_0.png (CI build/CD release pipeline)
-[10]: https://en.wikipedia.org/wiki/Microsoft_Symbol_Server
-[11]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-6.png (Breaking down the CI build pipeline)
-[12]: https://stryker-mutator.io/
-[13]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-7.png (Breaking down the CD release pipeline)
-[14]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-8.png (Shift-right the environment-specific configuration)
-[15]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-9.png (Dev-QA-production pipeline)
-[16]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-10.png (Move approver management to simple group membership)
-[17]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-11.png (Pipeline with access to specific delivery stages)
-[18]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-12.png (The full pipeline)
diff --git a/sources/tech/20190712 What is Silverblue.md b/sources/tech/20190712 What is Silverblue.md
deleted file mode 100644
index c23a45b9f8..0000000000
--- a/sources/tech/20190712 What is Silverblue.md
+++ /dev/null
@@ -1,98 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (What is Silverblue?)
-[#]: via: (https://fedoramagazine.org/what-is-silverblue/)
-[#]: author: (Tomáš Popela https://fedoramagazine.org/author/tpopela/)
-
-What is Silverblue?
-======
-
-![][1]
-
-Fedora Silverblue is becoming more and more popular inside and outside the Fedora world. So based on feedback from the community, here are answers to some interesting questions about the project. If you do have any other Silverblue related questions, please leave it in the comments section and we will try to answer them in a future article.
-
-### What is Silverblue?
-
-Silverblue is a codename for the new generation of the desktop operating system, previously known as Atomic Workstation. The operating system is delivered in images that are created by utilizing the _[rpm-ostree][2]_ [project][2]. The main benefits of the system are speed, security, atomic updates and immutability.
-
-### What does “Silverblue” actually mean?
-
-“Team Silverblue” or “Silverblue” in short doesn’t have any hidden meaning. It was chosen after roughly two months when the project, previously known as Atomic Workstation was rebranded. There were over 150 words or word combinations reviewed in the process. In the end _Silverblue_ was chosen because it had an available domain as well as the social network accounts. One could think of it as a new take on Fedora’s blue branding, and could be used in phrases like “Go, Team Silverblue!” or “Want to join the team and improve Silverblue?”.
-
-### What is ostree?
-
-[OSTree or libostree is a project][3] that combines a “git-like” model for committing and downloading bootable filesystem trees, together with a layer to deploy them and manage the bootloader configuration. OSTree is used by rpm-ostree, a hybrid package/image based system that Silverblue uses. It atomically replicates a base OS and allows the user to “layer” the traditional RPM on top of the base OS if needed.
-
-### Why use Silverblue?
-
-Because it allows you to concentrate on your work and not on the operating system you’re running. It’s more robust as the updates of the system are atomic. The only thing you need to do is to restart into the new image. Also, if there’s anything wrong with the currently booted image, you can easily reboot/rollback to the previous working one, if available. If it isn’t, you can download and boot any other image that was generated in the past, using the _ostree_ command.
-
-Another advantage is the possibility of an easy switch between branches (or, in an old context, Fedora releases). You can easily try the _[Rawhide][4]_ or _[updates-testing][5]_ branch and then return back to the one that contains the current stable release. Also, you should consider Silverblue if you want to try something new and unusual.
-
-### What are the benefits of an immutable OS?
-
-One of the main benefits is security. The base operating system is mounted as read-only, and thus cannot be modified by malicious software. The only way to alter the system is through the _rpm-ostree_ utility.
-
-Another benefit is robustness. It’s nearly impossible for a regular user to get the OS to the state when it doesn’t boot or doesn’t work properly after accidentally or unintentionally removing some system library. Try to think about these kind of experiences from your past, and imagine how Silverblue could help you there.
-
-### How does one manage applications and packages in Silverblue?
-
-For graphical user interface applications, [Flatpak][6] is recommended, if the application is available as a flatpak. Users can choose between Flatpaks from either Fedora and built from Fedora packages and in Fedora-owned infrastructure, or Flathub that currently has a wider offering. Users can install them easily through GNOME Software, which already supports Fedora Silverblue.
-
-One of the first things users find out is there is no _dnf_ preinstalled in the OS. The main reason is that it wouldn’t work on Silverblue — and part of its functionality was replaced by the _rpm-ostree_ command. Users can overlay the traditional packages by using the _rpm-ostree install PACKAGE_. But it should only be used when there is no other way. This is because when the new system images are pulled from the repository, the system image must be rebuilt every time it is altered to accommodate the layered packages, or packages that were removed from the base OS or replaced with a different version.
-
-Fedora Silverblue comes with the default set of GUI applications that are part of the base OS. The team is working on porting them to Flatpaks so they can be distributed that way. As a benefit, the base OS will become smaller and easier to maintain and test, and users can modify their default installation more easily. If you want to look at how it’s done or help, take a look at the official [documentation][7].
-
-### What is Toolbox?
-
-[_Toolbox_][8] is a project to make containers easily consumable for regular users. It does that by using _podman_’s rootless containers. _Toolbox_ lets you easily and quickly create a container with a regular Fedora installation that you can play with or develop on, separated from your OS.
-
-### Is there any Silverblue roadmap?
-
-Formally there isn’t any, as we’re focusing on problems we discover during our testing and from community feedback. We’re currently using Fedora’s [Taiga][9] to do our planning.
-
-### What’s the release life cycle of the Silverblue?
-
-It’s the same as regular Fedora Workstation. A new release comes every 6 months and is supported for 13 months. The team plans to release updates for the OS bi-weekly (or longer) instead of daily as they currently do. That way the updates can be more thoroughly tested by QA and community volunteers before they are sent to the rest of the users.
-
-### What is the future of the immutable OS?
-
-From our point of view the future of the desktop involves the immutable OS. It’s safest for the user, and Android, ChromeOS, and the last macOS Catalina all use this method under the hood. For the Linux desktop there are still problems with some third party software that expects to write to the OS. HP printer drivers are a good example.
-
-Another issue is how parts of the system are distributed and installed. Fonts are a good example. Currently in Fedora they’re distributed in RPM packages. If you want to use them, you have to overlay them and then restart to the newly created image that contains them.
-
-### What is the future of standard Workstation?
-
-There is a possibility that the Silverblue will replace the regular Workstation. But there’s still a long way to go for Silverblue to provide the same functionality and user experience as the Workstation. In the meantime both desktop offerings will be delivered at the same time.
-
-### How does Atomic Workstation or Fedora CoreOS relate to any of this?
-
-Atomic Workstation was the name of the project before it was renamed to Fedora Silverblue.
-
-Fedora CoreOS is a different, but similar project. It shares some fundamental technologies with Silverblue, such as _rpm-ostree_, _toolbox_ and others. Nevertheless, CoreOS is a more minimal, container-focused and automatically updating OS.
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/what-is-silverblue/
-
-作者:[Tomáš Popela][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/tpopela/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2019/07/what-is-fedora-silverblue-816x345.jpg
-[2]: https://rpm-ostree.readthedocs.io/en/latest/
-[3]: https://ostree.readthedocs.io/en/latest/
-[4]: https://fedoraproject.org/wiki/Releases/Rawhide
-[5]: https://fedoraproject.org/wiki/QA:Updates_Testing
-[6]: https://flatpak.org/
-[7]: https://docs.fedoraproject.org/en-US/flatpak/tutorial/
-[8]: https://github.com/debarshiray/toolbox
-[9]: https://teams.fedoraproject.org/project/silverblue/
diff --git a/sources/tech/20190729 How to structure a multi-file C program- Part 1.md b/sources/tech/20190729 How to structure a multi-file C program- Part 1.md
deleted file mode 100644
index b9e026ca4b..0000000000
--- a/sources/tech/20190729 How to structure a multi-file C program- Part 1.md
+++ /dev/null
@@ -1,197 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (mengxinayan)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to structure a multi-file C program: Part 1)
-[#]: via: (https://opensource.com/article/19/7/structure-multi-file-c-part-1)
-[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjnyhttps://opensource.com/users/jnyjnyhttps://opensource.com/users/jim-salterhttps://opensource.com/users/cldxsolutions)
-
-How to structure a multi-file C program: Part 1
-======
-Grab your favorite beverage, editor, and compiler, crank up some tunes,
-and start structuring a C program composed of multiple files.
-![Programming keyboard.][1]
-
-It has often been said that the art of computer programming is part managing complexity and part naming things. I contend that this is largely true with the addition of "and sometimes it requires drawing boxes."
-
-In this article, I'll name some things and manage some complexity while writing a small C program that is loosely based on the program structure I discussed in "[How to write a good C main function][2]"—but different. This one will do something. Grab your favorite beverage, editor, and compiler, crank up some tunes, and let's write a mildly interesting C program together.
-
-### Philosophy of a good Unix program
-
-The first thing to know about this C program is that it's a [Unix][3] command-line tool. This means that it runs on (or can be ported to) operating systems that provide a Unix C runtime environment. When Unix was invented at Bell Labs, it was imbued from the beginning with a [design philosophy][4]. In my own words: _programs do one thing, do it well, and act on files_. While it makes sense to do one thing and do it well, the part about "acting on files" seems a little out of place.
-
-It turns out that the Unix abstraction of a "file" is very powerful. A Unix file is a stream of bytes that ends with an end-of-file (EOF) marker. That's it. Any other structure in a file is imposed by the application and not the operating system. The operating system provides system calls that allow a program to perform a set of standard operations on files: open, read, write, seek, and close (there are others, but those are the biggies). Standardizing access to files allows different programs to share a common abstraction and work together even when different people implement them in different programming languages.
-
-Having a shared file interface makes it possible to build programs that are _composable_. The output of one program can be the input of another program. The Unix family of operating systems provides three files by default whenever a program is executed: standard in (**stdin**), standard out (**stdout**), and standard error (**stderr**). Two of these files are opened in write-only mode: **stdout** and **stderr**, while **stdin** is opened read-only. We see this in action whenever we use file redirection in a command shell like Bash:
-
-
-```
-`$ ls | grep foo | sed -e 's/bar/baz/g' > ack`
-```
-
-This construction can be described briefly as: the output of **ls** is written to stdout, which is redirected to the stdin of **grep**, whose stdout is redirected to **sed**, whose stdout is redirected to write to a file called **ack** in the current directory.
-
-We want our program to play well in this ecosystem of equally flexible and awesome programs, so let's write a program that reads and writes files.
-
-### MeowMeow: A stream encoder/decoder concept
-
-When I was a dewy-eyed kid studying computer science in the <mumbles>s, there were a plethora of encoding schemes. Some of them were for compressing files, some were for packaging files together, and others had no purpose but to be excruciatingly silly. An example of the last is the [MooMoo encoding scheme][5].
-
-To give our program a purpose, I'll update this concept for the [2000s][6] and implement a concept called MeowMeow encoding (since the internet loves cats). The basic idea here is to take files and encode each nibble (half of a byte) with the text "meow." A lower-case letter indicates a zero, and an upper-case indicates a one. Yes, it will balloon the size of a file since we are trading 4 bits for 32 bits. Yes, it's pointless. But imagine the surprise on someone's face when this happens:
-
-
-```
-$ cat /home/your_sibling/.super_secret_journal_of_my_innermost_thoughts
-MeOWmeOWmeowMEoW...
-```
-
-This is going to be awesome.
-
-### Implementation, finally
-
-The full source for this can be found on [GitHub][7], but I'll talk through my thought process while writing it. The object is to illustrate how to structure a C program composed of multiple files.
-
-Having already established that I want to write a program that encodes and decodes files in MeowMeow format, I fired up a shell and issued the following commands:
-
-
-```
-$ mkdir meowmeow
-$ cd meowmeow
-$ git init
-$ touch Makefile # recipes for compiling the program
-$ touch main.c # handles command-line options
-$ touch main.h # "global" constants and definitions
-$ touch mmencode.c # implements encoding a MeowMeow file
-$ touch mmencode.h # describes the encoding API
-$ touch mmdecode.c # implements decoding a MeowMeow file
-$ touch mmdecode.h # describes the decoding API
-$ touch table.h # defines encoding lookup table values
-$ touch .gitignore # names in this file are ignored by git
-$ git add .
-$ git commit -m "initial commit of empty files"
-```
-
-In short, I created a directory full of empty files and committed them to git.
-
-Even though the files are empty, you can infer the purpose of each from its name. Just in case you can't, I annotated each **touch** with a brief description.
-
-Usually, a program starts as a single, simple **main.c** file, with only two or three functions that solve the problem. And then the programmer rashly shows that program to a friend or her boss, and suddenly the number of functions in the file balloons to support all the new "features" and "requirements" that pop up. The first rule of "Program Club" is don't talk about "Program Club." The second rule is to minimize the number of functions in one file.
-
-To be honest, the C compiler does not care one little bit if every function in your program is in one file. But we don't write programs for computers or compilers; we write them for other people (who are sometimes us). I know that is probably a surprise, but it's true. A program embodies a set of algorithms that solve a problem with a computer, and it's important that people understand it when the parameters of the problem change in unanticipated ways. People will have to modify the program, and they will curse your name if you have all 2,049 functions in one file.
-
-So we good and true programmers break functions out, grouping similar functions into separate files. Here I've got files **main.c**, **mmencode.c**, and **mmdecode.c**. For small programs like this, it may seem like overkill. But small programs rarely stay small, so planning for expansion is a "Good Idea."
-
-But what about those **.h** files? I'll explain them in general terms later, but in brief, those are called _header_ files, and they can contain C language type definitions and C preprocessor directives. Header files should _not_ have any functions in them. You can think of headers as a definition of the application programming interface (API) offered by the **.c** flavored file that is used by other **.c** files.
-
-### But what the heck is a Makefile?
-
-I know all you cool kids are using the "Ultra CodeShredder 3000" integrated development environment to write the next blockbuster app, and building your project consists of mashing on Ctrl-Meta-Shift-Alt-Super-B. But back in my day (and also today), lots of useful work got done by C programs built with Makefiles. A Makefile is a text file that contains recipes for working with files, and programmers use it to automate building their program binaries from source (and other stuff too!).
-
-Take, for instance, this little gem:
-
-
-```
-00 # Makefile
-01 TARGET= my_sweet_program
-02 $(TARGET): main.c
-03 cc -o my_sweet_program main.c
-```
-
-Text after an octothorpe/pound/hash is a comment, like in line 00.
-
-Line 01 is a variable assignment where the variable **TARGET** takes on the string value **my_sweet_program**. By convention, OK, my preference, all Makefile variables are capitalized and use underscores to separate words.
-
-Line 02 consists of the name of the file that the recipe creates and the files it depends on. In this case, the target is **my_sweet_program**, ****and the dependency is **main.c**.
-
-The final line, 03, is indented with a tab and not four spaces. This is the command that will be executed to create the target. In this case, we call **cc** the C compiler frontend to compile and link **my_sweet_program**.
-
-Using a Makefile is simple:
-
-
-```
-$ make
-cc -o my_sweet_program main.c
-$ ls
-Makefile main.c my_sweet_program
-```
-
-The [Makefile][8] that will build our MeowMeow encoder/decoder is considerably more sophisticated than this example, but the basic structure is the same. I'll break it down Barney-style in another article.
-
-### Form follows function
-
-My idea here is to write a program that reads a file, transforms it, and writes the transformed data to another file. The following fabricated command-line interaction is how I imagine using the program:
-
-
-```
- $ meow < clear.txt > clear.meow
- $ unmeow < clear.meow > meow.tx
- $ diff clear.txt meow.tx
- $
-```
-
-We need to write code to handle command-line parsing and managing the input and output streams. We need a function to encode a stream and write it to another stream. And finally, we need a function to decode a stream and write it to another stream. Wait a second, I've only been talking about writing one program, but in the example above, I invoke two commands: **meow** and **unmeow**? I know you are probably thinking that this is getting complex as heck.
-
-### Minor sidetrack: argv[0] and the ln command
-
-If you recall, the signature of a C main function is:
-
-
-```
-`int main(int argc, char *argv[])`
-```
-
-where **argc** is the number of command-line arguments, and **argv** is a list of character pointers (strings). The value of **argv[0]** is the path of the file containing the program being executed. Many Unix utility programs with complementary functions (e.g., compress and uncompress) look like two programs, but in fact, they are one program with two names in the filesystem. The two-name trick is accomplished by creating a filesystem "link" using the **ln** command.
-
-An example from **/usr/bin** on my laptop is:
-
-
-```
- $ ls -li /usr/bin/git*
-3376 -rwxr-xr-x. 113 root root 1.5M Aug 30 2018 /usr/bin/git
-3376 -rwxr-xr-x. 113 root root 1.5M Aug 30 2018 /usr/bin/git-receive-pack
-...
-```
-
-Here **git** and **git-receive-pack** are the same file with different names. We can tell it's the same file because they have the same inode number (the first column). An inode is a feature of the Unix filesystem and is super outside the scope of this article.
-
-Good and/or lazy programmers can use this feature of the Unix filesystem to write less code but double the number of programs they deliver. First, we write a program that changes its behavior based on the value of **argv[0]**, then we make sure to create links with the names that cause the behavior.
-
-In our Makefile, the **unmeow** link is created using this recipe:
-
-
-```
- # Makefile
- ...
- $(DECODER): $(ENCODER)
- $(LN) -f $< $@
- ...
-```
-
-I tend to parameterize everything in my Makefiles, rarely using a "bare" string. I group all the definitions at the top of the Makefile, which makes it easy to find and change them. This makes a big difference when you are trying to port software to a new platform and you need to change all your rules to use **xcc** instead of **cc**.
-
-The recipe should appear relatively straightforward except for the two built-in variables **$@** and **$<**. The first is a shortcut for the target of the recipe; in this case, **$(DECODER)**. (I remember this because the at-sign looks like a target to me.) The second, **$<** is the rule dependency; in this case, it resolves to **$(ENCODER)**.
-
-Things are getting complex for sure, but it's managed.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/7/structure-multi-file-c-part-1
-
-作者:[Erik O'Shaughnessy][a]
-选题:[lujun9972][b]
-译者:[萌新阿岩](https://github.com/mengxinayan)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jnyjnyhttps://opensource.com/users/jnyjnyhttps://opensource.com/users/jim-salterhttps://opensource.com/users/cldxsolutions
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming_keyboard_coding.png?itok=E0Vvam7A (Programming keyboard.)
-[2]: https://opensource.com/article/19/5/how-write-good-c-main-function
-[3]: https://en.wikipedia.org/wiki/Unix
-[4]: http://harmful.cat-v.org/cat-v/
-[5]: http://www.jabberwocky.com/software/moomooencode.html
-[6]: https://giphy.com/gifs/nyan-cat-sIIhZliB2McAo
-[7]: https://github.com/JnyJny/meowmeow
-[8]: https://github.com/JnyJny/meowmeow/blob/master/Makefile
diff --git a/sources/tech/20190730 Using Python to explore Google-s Natural Language API.md b/sources/tech/20190730 Using Python to explore Google-s Natural Language API.md
index 304fd79e0a..b5f8611a1c 100644
--- a/sources/tech/20190730 Using Python to explore Google-s Natural Language API.md
+++ b/sources/tech/20190730 Using Python to explore Google-s Natural Language API.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: (zhangxiangping)
+[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
@@ -264,7 +264,7 @@ via: https://opensource.com/article/19/7/python-google-natural-language-api
作者:[JR Oakes][a]
选题:[lujun9972][b]
-译者:[zhangxiangping](https://github.com/zhangxiangping)
+译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/sources/tech/20190731 How to structure a multi-file C program- Part 2.md b/sources/tech/20190731 How to structure a multi-file C program- Part 2.md
deleted file mode 100644
index 3f050b053b..0000000000
--- a/sources/tech/20190731 How to structure a multi-file C program- Part 2.md
+++ /dev/null
@@ -1,229 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (mengxinayan)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to structure a multi-file C program: Part 2)
-[#]: via: (https://opensource.com/article/19/7/structure-multi-file-c-part-2)
-[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjny)
-
-How to structure a multi-file C program: Part 2
-======
-Dive deeper into the structure of a C program composed of multiple files
-in the second part of this article.
-![4 manilla folders, yellow, green, purple, blue][1]
-
-In [Part 1][2], I laid out the structure for a multi-file C program called [MeowMeow][3] that implements a toy [codec][4]. I also talked about the Unix philosophy of program design, laying out a number of empty files to start with a good structure from the very beginning. Lastly, I touched on what a Makefile is and what it can do for you. This article picks up where the other one left off and now I'll get to the actual implementation of our silly (but instructional) MeowMeow codec.
-
-The structure of the **main.c** file for **meow**/**unmeow** should be familiar to anyone who's read my article "[How to write a good C main function][5]." It has the following general outline:
-
-
-```
-/* main.c - MeowMeow, a stream encoder/decoder */
-
-/* 00 system includes */
-/* 01 project includes */
-/* 02 externs */
-/* 03 defines */
-/* 04 typedefs */
-/* 05 globals (but don't)*/
-/* 06 ancillary function prototypes if any */
-
-int main(int argc, char *argv[])
-{
- /* 07 variable declarations */
- /* 08 check argv[0] to see how the program was invoked */
- /* 09 process the command line options from the user */
- /* 10 do the needful */
-}
-
-/* 11 ancillary functions if any */
-```
-
-### Including project header files
-
-The second section, **/* 01 project includes /***, reads like this from the source:
-
-
-```
-/* main.c - MeowMeow, a stream encoder/decoder */
-...
-/* 01 project includes */
-#include "main.h"
-#include "mmecode.h"
-#include "mmdecode.h"
-```
-
-The **#include** directive is a C preprocessor command that causes the contents of the named file to be "included" at this point in the file. If the programmer uses double-quotes around the name of the header file, the compiler will look for that file in the current directory. If the file is enclosed in <>, it will look for the file in a set of predefined directories.
-
-The file [**main.h**][6] contains the definitions and typedefs used in [**main.c**][7]. I like to collect these things here in case I want to use those definitions elsewhere in my program.
-
-The files [**mmencode.h**][8] and [**mmdecode.h**][9] are nearly identical, so I'll break down **mmencode.h**.
-
-
-```
- /* mmencode.h - MeowMeow, a stream encoder/decoder */
-
- #ifndef _MMENCODE_H
- #define _MMENCODE_H
-
- #include <stdio.h>
-
- int mm_encode(FILE *src, FILE *dst);
-
- #endif /* _MMENCODE_H */
-```
-
-The **#ifdef, #define, #endif** construction is collectively known as a "guard." This keeps the C compiler from including this file more than once per file. The compiler will complain if it finds multiple definitions/prototypes/declarations, so the guard is a _must-have_ for header files.
-
-Inside the guard, there are only two things: an **#include** directive and a function prototype declaration. I include **stdio.h** here to bring in the definition of **FILE** that is used in the function prototype. The function prototype can be included by other C files to establish that function in the file's namespace. You can think of each file as a separate _namespace_, which means variables and functions in one file are not usable by functions or variables in another file.
-
-Writing header files is complex, and it is tough to manage in larger projects. Use guards.
-
-### MeowMeow encoding, finally
-
-The meat and potatoes of this program—encoding and decoding bytes into/out of **MeowMeow** strings—is actually the easy part of this project. All of our activities until now have been putting the scaffolding in place to support calling this function: parsing the command line, determining which operation to use, and opening the files that we'll operate on. Here is the encoding loop:
-
-
-```
- /* mmencode.c - MeowMeow, a stream encoder/decoder */
- ...
- while (![feof][10](src)) {
-
- if (![fgets][11](buf, sizeof(buf), src))
- break;
-
- for(i=0; i<[strlen][12](buf); i++) {
- lo = (buf[i] & 0x000f);
- hi = (buf[i] & 0x00f0) >> 4;
- [fputs][13](tbl[hi], dst);
- [fputs][13](tbl[lo], dst);
- }
- }
-```
-
-In plain English, this loop reads in a chunk of the file while there are chunks left to read (**feof(3)** and **fgets(3)**). Then it splits each byte in the chunk into **hi** and **lo** nibbles. Remember, a nibble is half of a byte, or 4 bits. The real magic here is realizing that 4 bits can encode 16 values. I use **hi** and **lo** as indices into a 16-string lookup table, **tbl**, that contains the **MeowMeow** strings that encode each nibble. Those strings are written to the destination **FILE** stream using **fputs(3)**, then we move on to the next byte in the buffer.
-
-The table is initialized with a macro defined in [**table.h**][14] for no particular reason except to demonstrate including another project local header file, and I like initialization macros. We will go further into why a future article.
-
-### MeowMeow decoding
-
-Alright, I'll admit it took me a couple of runs at this before I got it working. The decode loop is similar: read a buffer full of **MeowMeow** strings and reverse the encoding from strings to bytes.
-
-
-```
- /* mmdecode.c - MeowMeow, a stream decoder/decoder */
- ...
- int mm_decode(FILE *src, FILE *dst)
- {
- if (!src || !dst) {
- errno = EINVAL;
- return -1;
- }
- return stupid_decode(src, dst);
- }
-```
-
-Not what you were expecting?
-
-Here, I'm exposing the function **stupid_decode()** via the externally visible **mm_decode()** function. When I say "externally," I mean outside this file. Since **stupid_decode()** isn't in the header file, it isn't available to be called in other files.
-
-Sometimes we do this when we want to publish a solid public interface, but we aren't quite done noodling around with functions to solve a problem. In my case, I've written an I/O-intensive function that reads 8 bytes at a time from the source stream to decode 1 byte to write to the destination stream. A better implementation would work on a buffer bigger than 8 bytes at a time. A _much_ better implementation would also buffer the output bytes to reduce the number of single-byte writes to the destination stream.
-
-
-```
- /* mmdecode.c - MeowMeow, a stream decoder/decoder */
- ...
- int stupid_decode(FILE *src, FILE *dst)
- {
- char buf[9];
- decoded_byte_t byte;
- int i;
-
- while (![feof][10](src)) {
- if (![fgets][11](buf, sizeof(buf), src))
- break;
- byte.field.f0 = [isupper][15](buf[0]);
- byte.field.f1 = [isupper][15](buf[1]);
- byte.field.f2 = [isupper][15](buf[2]);
- byte.field.f3 = [isupper][15](buf[3]);
- byte.field.f4 = [isupper][15](buf[4]);
- byte.field.f5 = [isupper][15](buf[5]);
- byte.field.f6 = [isupper][15](buf[6]);
- byte.field.f7 = [isupper][15](buf[7]);
-
- [fputc][16](byte.value, dst);
- }
- return 0;
- }
-```
-
-Instead of using the bit-shifting technique I used in the encoder, I elected to create a custom data structure called **decoded_byte_t**.
-
-
-```
- /* mmdecode.c - MeowMeow, a stream decoder/decoder */
- ...
-
- typedef struct {
- unsigned char f7:1;
- unsigned char f6:1;
- unsigned char f5:1;
- unsigned char f4:1;
- unsigned char f3:1;
- unsigned char f2:1;
- unsigned char f1:1;
- unsigned char f0:1;
- } fields_t;
-
- typedef union {
- fields_t field;
- unsigned char value;
- } decoded_byte_t;
-```
-
-It's a little complex when viewed all at once, but hang tight. The **decoded_byte_t** is defined as a **union** of a **fields_t** and an **unsigned char**. The named members of a union can be thought of as aliases for the same region of memory. In this case, **value** and **field** refer to the same 8-bit region of memory. Setting **field.f0** to 1 would also set the least significant bit in **value**.
-
-While **unsigned char** shouldn't be a mystery, the **typedef** for **fields_t** might look a little unfamiliar. Modern C compilers allow programmers to specify "bit fields" in a **struct**. The field type needs to be an unsigned integral type, and the member identifier is followed by a colon and an integer that specifies the length of the bit field.
-
-This data structure makes it simple to access each bit in the byte by field name and then access the assembled value via the **value** field of the union. We depend on the compiler to generate the correct bit-shifting instructions to access the fields, which can save you a lot of heartburn when you are debugging.
-
-Lastly, **stupid_decode()** is _stupid_ because it only reads 8 bytes at a time from the source **FILE** stream. Usually, we try to minimize the number of reads and writes to improve performance and reduce our cost of system calls. Remember that reading or writing a bigger chunk less often is much better than reading/writing a lot of smaller chunks more frequently.
-
-### The wrap-up
-
-Writing a multi-file program in C requires a little more planning on behalf of the programmer than just a single **main.c**. But just a little effort up front can save a lot of time and headache when you refactor as you add functionality.
-
-To recap, I like to have a lot of files with a few short functions in them. I like to expose a small subset of the functions in those files via header files. I like to keep my constants in header files, both numeric and string constants. I _love_ Makefiles and use them instead of Bash scripts to automate all sorts of things. I like my **main()** function to handle command-line argument parsing and act as a scaffold for the primary functionality of the program.
-
-I know I've only touched the surface of what's going on in this simple program, and I'm excited to learn what things were helpful to you and which topics need better explanations. Share your thoughts in the comments to let me know.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/7/structure-multi-file-c-part-2
-
-作者:[Erik O'Shaughnessy][a]
-选题:[lujun9972][b]
-译者:[萌新阿岩](https://github.com/mengxinayan)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jnyjny
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/file_system.jpg?itok=pzCrX1Kc (4 manilla folders, yellow, green, purple, blue)
-[2]: https://opensource.com/article/19/7/how-structure-multi-file-c-program-part-1
-[3]: https://github.com/jnyjny/MeowMeow.git
-[4]: https://en.wikipedia.org/wiki/Codec
-[5]: https://opensource.com/article/19/5/how-write-good-c-main-function
-[6]: https://github.com/JnyJny/meowmeow/blob/master/main.h
-[7]: https://github.com/JnyJny/meowmeow/blob/master/main.c
-[8]: https://github.com/JnyJny/meowmeow/blob/master/mmencode.h
-[9]: https://github.com/JnyJny/meowmeow/blob/master/mmdecode.h
-[10]: http://www.opengroup.org/onlinepubs/009695399/functions/feof.html
-[11]: http://www.opengroup.org/onlinepubs/009695399/functions/fgets.html
-[12]: http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html
-[13]: http://www.opengroup.org/onlinepubs/009695399/functions/fputs.html
-[14]: https://github.com/JnyJny/meowmeow/blob/master/table.h
-[15]: http://www.opengroup.org/onlinepubs/009695399/functions/isupper.html
-[16]: http://www.opengroup.org/onlinepubs/009695399/functions/fputc.html
diff --git a/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md b/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
index b4e1a2667b..b72de600e0 100644
--- a/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
+++ b/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
@@ -1,11 +1,11 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Learn how to Install LXD / LXC Containers in Ubuntu)
-[#]: via: (https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/)
-[#]: author: (Shashidhar Soppin https://www.linuxtechi.com/author/shashidhar/)
+[#]: collector: "lujun9972"
+[#]: translator: "runningwater "
+[#]: reviewer: " "
+[#]: publisher: " "
+[#]: url: " "
+[#]: subject: "Learn how to Install LXD / LXC Containers in Ubuntu"
+[#]: via: "https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/"
+[#]: author: "Shashidhar Soppin https://www.linuxtechi.com/author/shashidhar/"
Learn how to Install LXD / LXC Containers in Ubuntu
======
@@ -497,7 +497,7 @@ via: https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/
作者:[Shashidhar Soppin][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
+译者:[runningwater](https://github.com/runningwater)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/sources/tech/20190808 Sending custom emails with Python.md b/sources/tech/20190808 Sending custom emails with Python.md
deleted file mode 100644
index fb8e0d3938..0000000000
--- a/sources/tech/20190808 Sending custom emails with Python.md
+++ /dev/null
@@ -1,257 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Sending custom emails with Python)
-[#]: via: (https://opensource.com/article/19/8/sending-custom-emails-python)
-[#]: author: (Brian "bex" Exelbierd https://opensource.com/users/bexelbie)
-
-Sending custom emails with Python
-======
-Customize your group emails with Mailmerge, a command-line program that
-can handle simple and complex emails.
-![Chat via email][1]
-
-Email remains a fact of life. Despite all its warts, it's still the best way to send information to most people, especially in automated ways that allow messages to queue for recipients.
-
-One of the highlights of my work as the [Fedora Community Action and Impact Coordinator][2] is giving people good news about travel funding. I often send this information over email. Here, I'll show you how I send custom messages to groups of people using [Mailmerge][3], a command-line Python program that can handle simple and complex emails.
-
-### Install Mailmerge
-
-Mailmerge is packaged and available in Fedora, and you can install it from the command line with **sudo dnf install python3-mailmerge**. You can also install it from PyPI using **pip**, as the project's [README explains][4].
-
-### Configure your Mailmerge files
-
-Three files control how Mailmerge works. If you run **mailmerge --sample**, it will create template files for you. The files are:
-
- * **mailmerge_server.conf:** This contains the configuration details for your SMTP host to send emails. Your password is _not_ stored in this file.
- * **mailmerge_database.csv:** This holds the custom data for each email, including the recipients' email addresses.
- * **mailmerge_template.txt:** This is your email's text with placeholder fields that will be replaced using the data from **mailmerge_database.csv**.
-
-
-
-#### Server.conf
-
-The sample **mailmerge_server.conf** file includes several examples that should be familiar. If you've ever added email to your phone or set up a desktop email client, you've seen this data before. The big thing to remember is to update your username in the file, especially if you are using one of the example configurations.
-
-#### Database.csv
-
-The **mailmerge_database.csv** file is a bit more complicated. It must contain (at minimum) the recipients' email addresses and any other custom details necessary to replace the fields in your email. It is a good idea to write the **mailmerge_template.txt** file at the same time you create the fields list for this file. I find it helpful to use a spreadsheet to capture this data and export it as a CSV file when I am done. This sample file:
-
-
-```
-email,name,number
-[myself@mydomain.com][5],"Myself",17
-[bob@bobdomain.com][6],"Bob",42
-```
-
-allows you to send emails to two people, using their first name and telling them a number. This file, while not terribly interesting, illustrates an important habit: Always make yourself the first recipient in the file. This enables you to send yourself a test email to verify everything works as expected before you email the entire list.
-
-If any of your values contain commas, you _**must**_ enclose the entire value in double-quotes (**"**). If you need to include a double-quote in a double-quoted field, use two double-quotes in a row. Quoting rules are fun, so read about [CSVs in Python 3][7] for specifics.
-
-#### Template.txt
-
-As part of my work, I get to share news about travel-funding decisions for our Fedora contributor conference, [Flock][8]. A simple email tells people they've been selected for travel funding and their specific funding details. One user-specific detail is how much money we can allocate for their airfare. Here is an abbreviated version of my template file (I've snipped out a lot of the text for brevity):
-
-
-```
-$ cat mailmerge_template.txt
-TO: {{Email}}
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-
-Hi {{Name}},
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: {{Travel_Budget}}
-
-<<snip>>
-```
-
-The top of the template specifies the recipient, sender, and subject. After the blank line, there's the body of the email. This email needs the recipients' **Email**, **Name**, and **Travel_Budget** from the **database.csv** file. Notice that those fields are surrounded by double curly braces (**{{** and **}}**). The corresponding **mailmerge_database.csv** looks like this:
-
-
-```
-$ cat mailmerge_database.csv
-Name,Email,Travel_Budget
-Brian,[bexelbie@redhat.com][9],1000
-PersonA,[persona@fedoraproject.org][10],1500
-PèrsonB,[personb@fedoraproject.org][11],500
-```
-
-Notice that I listed myself first (for testing) and there are two other people in the file. The second person, PèrsonB, has an accented character in their name; Mailmerge will automatically encode it.
-
-That's the whole template concept: Write your email and put placeholders in double curly braces. Then create a database that provides those values. Now let's test the email.
-
-### Test and send simple email merges
-
-#### Do a dry-run
-
-Start by doing a dry-run that prints the emails, with the placeholder fields completed, to the screen. By default, if you run the command **mailmerge**, it will do a dry-run of the first email:
-
-
-```
-$ mailmerge
->>> encoding ascii
->>> message 0
-TO: [bexelbie@redhat.com][9]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: 7bit
-Date: Sat, 20 Jul 2019 18:17:15 -0000
-
-Hi Brian,
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: 1000
-
-<<snip>>
-
->>> sent message 0 DRY RUN
->>> No attachments were sent with the emails.
->>> Limit was 1 messages. To remove the limit, use the --no-limit option.
->>> This was a dry run. To send messages, use the --no-dry-run option.
-```
-
-Reviewing the first email (**message 0**, as counting starts from zero, like many things in computer science), you can see my name and travel budget are correct. If you want to review every email, enter **mailmerge --no-limit** to tell Mailmerge not to limit itself to the first email. Here's the dry-run of the third email, which shows the special character encoding:
-
-
-```
->>> message 2
-TO: [personb@fedoraproject.org][11]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Date: Sat, 20 Jul 2019 18:22:48 -0000
-
-Hi P=E8rsonB,
-```
-
-That's not an error; **P=E8rsonB** is the encoded form of **PèrsonB**.
-
-#### Send a test message
-
-Now, send a test email with the command **mailmerge --no-dry-run**, which tells Mailmerge to send a message to the first email on the list:
-
-
-```
-$ mailmerge --no-dry-run
->>> encoding ascii
->>> message 0
-TO: [bexelbie@redhat.com][9]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: 7bit
-Date: Sat, 20 Jul 2019 18:25:45 -0000
-
-Hi Brian,
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: 1000
-
-<<snip>>
-
->>> Read SMTP server configuration from mailmerge_server.conf
->>> host = smtp.gmail.com
->>> port = 587
->>> username = [bexelbie@redhat.com][9]
->>> security = STARTTLS
->>> password for [bexelbie@redhat.com][9] on smtp.gmail.com:
->>> sent message 0
->>> No attachments were sent with the emails.
->>> Limit was 1 messages. To remove the limit, use the --no-limit option.
-```
-
-On the fourth to last line, you can see it prompts you for your password. If you're using two-factor authentication or domain-managed logins, you will need to create an application password that bypasses these controls. If you're using Gmail and similar systems, you can do it directly from the interface; otherwise, contact your email system administrator. This will not compromise the security of your email system, but you should still keep the password complex and secret.
-
-When I checked my email account, I received a beautifully formatted test email. If your test email looks ready, send all the emails by entering **mailmerge --no-dry-run --no-limit**.
-
-### Send complex emails
-
-You can really see the power of Mailmerge when you take advantage of [Jinja2 templating][12]. I've found it useful for including conditional text and sending attachments. Here is a complex template and the corresponding database:
-
-
-```
-$ cat mailmerge_template.txt
-TO: {{Email}}
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-ATTACHMENT: attachments/{{File}}
-
-Hi {{Name}},
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: {{Travel_Budget}}
-{% if Hotel == "Yes" -%}
-Lodging: Lodging in the hotel Wednesday-Sunday (4 nights)
-{%- endif %}
-
-<<snip>>
-
-$ cat mailmerge_database.csv
-Name,Email,Travel_Budget,Hotel,File
-Brian,[bexelbie@redhat.com][9],1000,Yes,visa_bex.pdf
-PersonA,[persona@fedoraproject.org][10],1500,No,visa_person_a.pdf
-PèrsonB,[personb@fedoraproject.org][11],500,Yes,visa_person_b.pdf
-```
-
-There are two new things in this email. First, there's an attachment. I have to send visa invitation letters to international travelers to help them come to Flock, and the **ATTACHMENT** part of the header specifies which file to attach. To keep my directory clean, I put all of them in my Attachments subdirectory. Second, it includes conditional information about a hotel, because some people receive funding for their hotel stay, and I need to include those details for those who do. This is done with the **if** construction:
-
-
-```
-{% if Hotel == "Yes" -%}
-Lodging: Lodging in the hotel Wednesday-Sunday (4 nights)
-{%- endif %}
-```
-
-This works just like an **if** in most programming languages. Jinja2 is very expressive and can do multi-level conditions. Experiment with making your life easier by including database elements that control the contents of the email. Using whitespace is important for email readability. The minus (**-**) symbols in **if** and **endif** are part of how Jinja2 controls [whitespace][13]. There are lots of options, so experiment to see what looks best for you.
-
-Also note that I extended the database with two fields, **Hotel** and **File**. These are the values that control the inclusion of the hotel text and provide the name of the attachment. In my example, PèrsonB and I got hotel funding, while PersonA didn't.
-
-Doing a dry-run and sending the emails is the same whether you're using a simple or a complex template. Give it a try!
-
-You can also experiment with using conditionals (**if** … **endif**) in the header. You can, for example, have an attachment only if one is in the database, or maybe you need to change the sender's name for some emails but not others.
-
-### Mailmerge's advantages
-
-The Mailmerge program provides a powerful but simple method of sending lots of customized emails. Everyone gets only the information they need, and extraneous steps and details are omitted.
-
-Even for simple group emails, I have found this method much more effective than sending one email to a bunch of people using CC or BCC. A lot of people filter their email and delay reading anything not sent directly to them. Using Mailmerge ensures that every person gets their own email. Messages will filter properly for the recipient and no one can accidentally "reply all" to the entire group.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/sending-custom-emails-python
-
-作者:[Brian "bex" Exelbierd][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/bexelbie
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
-[2]: https://docs.fedoraproject.org/en-US/council/fcaic/
-[3]: https://github.com/awdeorio/mailmerge
-[4]: https://github.com/awdeorio/mailmerge#install
-[5]: mailto:myself@mydomain.com
-[6]: mailto:bob@bobdomain.com
-[7]: https://docs.python.org/3/library/csv.html
-[8]: https://flocktofedora.org/
-[9]: mailto:bexelbie@redhat.com
-[10]: mailto:persona@fedoraproject.org
-[11]: mailto:personb@fedoraproject.org
-[12]: http://jinja.pocoo.org/docs/latest/templates/
-[13]: http://jinja.pocoo.org/docs/2.10/templates/#whitespace-control
diff --git a/sources/tech/20190813 Building a non-breaking breakpoint for Python debugging.md b/sources/tech/20190813 Building a non-breaking breakpoint for Python debugging.md
deleted file mode 100644
index 1c33c05a68..0000000000
--- a/sources/tech/20190813 Building a non-breaking breakpoint for Python debugging.md
+++ /dev/null
@@ -1,238 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Building a non-breaking breakpoint for Python debugging)
-[#]: via: (https://opensource.com/article/19/8/debug-python)
-[#]: author: (Liran Haimovitch https://opensource.com/users/liranhaimovitch)
-
-Building a non-breaking breakpoint for Python debugging
-======
-Have you ever wondered how to speed up a debugger? Here are some lessons
-learned while building one for Python.
-![Real python in the graphic jungle][1]
-
-This is the story of how our team at [Rookout][2] built non-breaking breakpoints for Python and some of the lessons we learned along the way. I'll be presenting all about the nuts and bolts of debugging in Python at [PyBay 2019][3] in San Francisco this month. Let's dig in.
-
-### The heart of Python debugging: sys.set_trace
-
-There are many Python debuggers out there. Some of the more popular include:
-
- * **pdb**, part of the Python standard library
- * **PyDev**, the debugger behind the Eclipse and PyCharm IDEs
- * **ipdb**, the IPython debugger
-
-
-
-Despite the range of choices, almost every Python debugger is based on just one function: **sys.set_trace**. And let me tell you, **[sys.settrace][4]** might just be the most complex function in the Python standard library.
-
-![set_trace Python 2 docs page][5]
-
-In simpler terms, **settrace** registers a trace function for the interpreter, which may be called in any of the following cases:
-
- * Function call
- * Line execution
- * Function return
- * Exception raised
-
-
-
-A simple trace function might look like this:
-
-
-```
-def simple_tracer(frame, event, arg):
- co = frame.f_code
- func_name = co.co_name
- line_no = frame.f_lineno
- print("{e} {f} {l}".format(
-e=event, f=func_name, l=line_no))
- return simple_tracer
-```
-
-When looking at this function, the first things that come to mind are its arguments and return values. The trace function arguments are:
-
- * **frame** object, which is the full state of the interpreter at the point of the function's execution
- * **event** string, which can be **call**, **line**, **return**, or **exception**
- * **arg** object, which is optional and depends on the event type
-
-
-
-The trace function returns itself because the interpreter keeps track of two kinds of trace functions:
-
- * **Global trace function (per thread):** This trace function is set for the current thread by **sys.settrace** and is invoked whenever a new **frame** is created by the interpreter (essentially on every function call). While there's no documented way to set the trace function for a different thread, you can call **threading.settrace** to set the trace function for all newly created **threading** module threads.
- * **Local trace function (per frame):** This trace function is set by the interpreter to the value returned by the global trace function upon frame creation. There's no documented way to set the local trace function once the frame has been created.
-
-
-
-This mechanism is designed to allow the debugger to have more granular control over which frames are traced to reduce performance impact.
-
-### Building our debugger in three easy steps (or so we thought)
-
-With all that background, writing your own debugger using a custom trace function looks like a daunting task. Luckily, **pdb**, the standard Python debugger, is built on top of **Bdb**, a base class for building debuggers.
-
-A naive breakpoints debugger based on **Bdb** might look like this:
-
-
-```
-import bdb
-import inspect
-
-class Debugger(bdb.Bdb):
- def __init__(self):
- Bdb.__init__(self)
- self.breakpoints = dict()
- self.set_trace()
-
-def set_breakpoint(self, filename, lineno, method):
- self.set_break(filename, lineno)
- try :
- self.breakpoints[(filename, lineno)].add(method)
- except KeyError:
- self.breakpoints[(filename, lineno)] = [method]
-
-def user_line(self, frame):
- if not self.break_here(frame):
- return
-
- # Get filename and lineno from frame
- (filename, lineno, _, _, _) = inspect.getframeinfo(frame)
-
- methods = self.breakpoints[(filename, lineno)]
- for method in methods:
- method(frame)
-```
-
-All this does is:
-
- 1. Inherits from **Bdb** and write a simple constructor initializing the base class and tracing.
- 2. Adds a **set_breakpoint** method that uses **Bdb** to set the breakpoint and keeps track of our breakpoints.
- 3. Overrides the **user_line** method that is called by **Bdb** on certain user lines. The function makes sure it is being called for a breakpoint, gets the source location, and invokes the registered breakpoints
-
-
-
-### How well did the simple Bdb debugger work?
-
-Rookout is about bringing a debugger-like user experience to production-grade performance and use cases. So, how well did our naive breakpoint debugger perform?
-
-To test it and measure the global performance overhead, we wrote two simple test methods and executed each of them 16 million times under multiple scenarios. Keep in mind that no breakpoint was executed in any of the cases.
-
-
-```
-def empty_method():
- pass
-
-def simple_method():
- a = 1
- b = 2
- c = 3
- d = 4
- e = 5
- f = 6
- g = 7
- h = 8
- i = 9
- j = 10
-```
-
-Using the debugger takes a shocking amount of time to complete. The bad results make it clear that our naive **Bdb** debugger is not yet production-ready.
-
-![First Bdb debugger results][6]
-
-### Optimizing the debugger
-
-There are three main ways to reduce debugger overhead:
-
- 1. **Limit local tracing as much as possible:** Local tracing is very costly compared to global tracing due to the much larger number of events per line of code.
- 2. **Optimize "call" events and return control to the interpreter faster:** The main work in **call** events is deciding whether or not to trace.
- 3. **Optimize "line" events and return control to the interpreter faster:** The main work in **line** events is deciding whether or not we hit a breakpoint.
-
-
-
-So we forked **Bdb**, reduced the feature set, simplified the code, optimized for hot code paths, and got impressive results. However, we were still not satisfied. So, we took another stab at it, migrated and optimized our code to **.pyx**, and compiled it using [Cython][7]. The final results (as you can see below) were still not good enough. So, we ended up diving into CPython's source code and realizing we could not make tracing fast enough for production use.
-
-![Second Bdb debugger results][8]
-
-### Rejecting Bdb in favor of bytecode manipulation
-
-After our initial disappointment from the trial-and-error cycles of standard debugging methods, we decided to look into a less obvious option: bytecode manipulation.
-
-The Python interpreter works in two main stages:
-
- 1. **Compiling Python source code into Python bytecode:** This unreadable (for humans) format is optimized for efficient execution and is often cached in those **.pyc** files we have all come to love.
- 2. **Iterating through the bytecode in the _interpreter loop_:** This executes one instruction at a time.
-
-
-
-This is the pattern we chose: use **bytecode manipulation** to set **non-breaking breakpoints** with no global overhead. This is done by finding the bytecode in memory that represents the source line we are interested in and inserting a function call just before the relevant instruction. This way, the interpreter does not have to do any extra work to support our breakpoints.
-
-This approach is not magic. Here's a quick example.
-
-We start with a very simple function:
-
-
-```
-def multiply(a, b):
- result = a * b
- return result
-```
-
-In documentation hidden in the **[inspect][9]** module (which has several useful utilities), we learn we can get the function's bytecode by accessing **multiply.func_code.co_code**:
-
-
-```
-`'|\x00\x00|\x01\x00\x14}\x02\x00|\x02\x00S'`
-```
-
-This unreadable string can be improved using the **[dis][10]** module in the Python standard library. By calling **dis.dis(multiply.func_code.co_code)**, we get:
-
-
-```
- 4 0 LOAD_FAST 0 (a)
- 3 LOAD_FAST 1 (b)
- 6 BINARY_MULTIPLY
- 7 STORE_FAST 2 (result)
-
- 5 10 LOAD_FAST 2 (result)
- 13 RETURN_VALUE
-```
-
-This gets us closer to understanding what happens behind the scenes of debugging but not to a straightforward solution. Unfortunately, Python does not offer a method for changing a function's bytecode from within the interpreter. You can overwrite the function object, but that's not good enough for the majority of real-world debugging scenarios. You have to go about it in a roundabout way using a native extension.
-
-### Conclusion
-
-When building a new tool, you invariably end up learning a lot about how stuff works. It also makes you think out of the box and keep your mind open to unexpected solutions.
-
-Working on non-breaking breakpoints for Rookout has taught me a lot about compilers, debuggers, server frameworks, concurrency models, and much much more. If you are interested in learning more about bytecode manipulation, Google's open source **[cloud-debug-python][11]** has tools for editing bytecode.
-
-* * *
-
-_Liran Haimovitch will present "[Understanding Python’s Debugging Internals][12]" at [PyBay][3], which will be held August 17-18 in San Francisco. Use code [OpenSource35][13] for a discount when you purchase your ticket to let them know you found out about the event from our community._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/debug-python
-
-作者:[Liran Haimovitch][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/liranhaimovitch
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python_jungle_lead.jpeg?itok=pFKKEvT- (Real python in the graphic jungle)
-[2]: https://rookout.com/
-[3]: https://pybay.com/
-[4]: https://docs.python.org/3/library/sys.html#sys.settrace
-[5]: https://opensource.com/sites/default/files/uploads/python2docs.png (set_trace Python 2 docs page)
-[6]: https://opensource.com/sites/default/files/uploads/debuggerresults1.png (First Bdb debugger results)
-[7]: https://cython.org/
-[8]: https://opensource.com/sites/default/files/uploads/debuggerresults2.png (Second Bdb debugger results)
-[9]: https://docs.python.org/2/library/inspect.html
-[10]: https://docs.python.org/2/library/dis.html
-[11]: https://github.com/GoogleCloudPlatform/cloud-debug-python
-[12]: https://pybay.com/speaker/liran-haimovitch/
-[13]: https://ti.to/sf-python/pybay2019/discount/OpenSource35
diff --git a/sources/tech/20190814 9 open source cloud native projects to consider.md b/sources/tech/20190814 9 open source cloud native projects to consider.md
deleted file mode 100644
index 8f95262799..0000000000
--- a/sources/tech/20190814 9 open source cloud native projects to consider.md
+++ /dev/null
@@ -1,266 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (9 open source cloud native projects to consider)
-[#]: via: (https://opensource.com/article/19/8/cloud-native-projects)
-[#]: author: (Bryant Son https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo)
-
-9 open source cloud native projects to consider
-======
-Work with containers? Get familiar with these projects from the Cloud
-Native Computing Foundation
-![clouds in the sky with blue pattern][1]
-
-As the practice of developing applications with containers is getting more popular, [cloud-native applications][2] are also on the rise. By [definition][3]:
-
-> "Cloud-native technologies are used to develop applications built with services packaged in containers, deployed as microservices, and managed on elastic infrastructure through agile DevOps processes and continuous delivery workflows."
-
-This description includes four elements that are integral to cloud-native applications:
-
- 1. Container
- 2. Microservice
- 3. DevOps
- 4. Continuous integration and continuous delivery (CI/CD)
-
-
-
-Although these technologies have very distinct histories, they complement each other well and have led to surprisingly exponential growth of cloud-native applications and toolsets in a short time. This [Cloud Native Computing Foundation][4] (CNCF) infographic shows the size and breadth of the cloud-native application ecosystem today.
-
-![Cloud-Native Computing Foundation applications ecosystem][5]
-
-Cloud-Native Computing Foundation projects
-
-I mean, just look at that! And this is just a start. Just as NodeJS’s creation sparked the explosion of endless JavaScript tools, the popularity of container technology started the exponential growth of cloud-native applications.
-
-The good news is that there are several organizations that oversee and connect these dots together. One is the [**Open Containers Initiative (OCI)**][6], which is a lightweight, open governance structure (or project), "formed under the auspices of the Linux Foundation for the express purpose of creating open industry standards around container formats and runtime." The other is the **CNCF**, "an open source software foundation dedicated to making cloud native computing universal and sustainable."
-
-In addition to building a community around cloud-native applications generally, CNCF also helps projects set up structured governance around their cloud-native applications. CNCF created the concept of maturity levels—Sandbox, Incubating, or Graduated—which correspond to the Innovators, Early Adopters, and Early Majority tiers on the diagram below.
-
-![CNCF project maturity levels][7]
-
-CNCF project maturity levels
-
-The CNCF has detailed [criteria][8] for each maturity level (included below for readers’ convenience). A two-thirds supermajority of the Technical Oversight Committee (TOC) is required for a project to be Incubating or Graduated.
-
-### Sandbox stage
-
-> To be accepted in the sandbox, a project must have at least two TOC sponsors. See the CNCF Sandbox Guidelines v1.0 for the detailed process.
-
-### Incubating stage
-
-> Note: The incubation level is the point at which we expect to perform full due diligence on projects.
->
-> To be accepted to incubating stage, a project must meet the sandbox stage requirements plus:
->
-> * Document that it is being used successfully in production by at least three independent end users which, in the TOC’s judgement, are of adequate quality and scope.
-> * Have a healthy number of committers. A committer is defined as someone with the commit bit; i.e., someone who can accept contributions to some or all of the project.
-> * Demonstrate a substantial ongoing flow of commits and merged contributions.
-> * Since these metrics can vary significantly depending on the type, scope, and size of a project, the TOC has final judgement over the level of activity that is adequate to meet these criteria
->
-
-
-### Graduated stage
-
-> To graduate from sandbox or incubating status, or for a new project to join as a graduated project, a project must meet the incubating stage criteria plus:
->
-> * Have committers from at least two organizations.
-> * Have achieved and maintained a Core Infrastructure Initiative Best Practices Badge.
-> * Have completed an independent and third party security audit with results published of similar scope and quality as the following example (including critical vulnerabilities addressed): and all critical vulnerabilities need to be addressed before graduation.
-> * Adopt the CNCF Code of Conduct.
-> * Explicitly define a project governance and committer process. This preferably is laid out in a GOVERNANCE.md file and references an OWNERS.md file showing the current and emeritus committers.
-> * Have a public list of project adopters for at least the primary repo (e.g., ADOPTERS.md or logos on the project website).
-> * Receive a supermajority vote from the TOC to move to graduation stage. Projects can attempt to move directly from sandbox to graduation, if they can demonstrate sufficient maturity. Projects can remain in an incubating state indefinitely, but they are normally expected to graduate within two years.
->
-
-
-## 9 projects to consider
-
-While it’s impossible to cover all of the CNCF projects in this article, I’ll describe are nine of most interesting Graduated and Incubating open source projects.
-
-Name | License | What It Is
----|---|---
-[Kubernetes][9] | Apache 2.0 | Orchestration platform for containers
-[Prometheus][10] | Apache 2.0 | Systems and service monitoring tool
-[Envoy][11] | Apache 2.0 | Edge and service proxy
-[rkt][12] | Apache 2.0 | Pod-native container engine
-[Jaeger][13] | Apache 2.0 | Distributed tracing system
-[Linkerd][14] | Apache 2.0 | Transparent service mesh
-[Helm][15] | Apache 2.0 | Kubernetes package manager
-[Etcd][16] | Apache 2.0 | Distributed key-value store
-[CRI-O][17] | Apache 2.0 | Lightweight runtime for Kubernetes
-
-I also created this video tutorial to walk through these projects.
-
-## Graduated projects
-
-Graduated projects are considered mature—adopted by many organizations—and must adhere to the CNCF’s guidelines. Following are three of the most popular open source CNCF Graduated projects. (Note that some of these descriptions are adapted and reused from the projects' websites.)
-
-### Kubernetes
-
-Ah, Kubernetes. How can we talk about cloud-native applications without mentioning Kubernetes? Invented by Google, Kubernetes is undoubtedly the most famous container-orchestration platform for container-based applications, and it is also an open source tool.
-
-What is a container orchestration platform? Basically, a container engine on its own may be okay for managing a few containers. However, when you are talking about thousands of containers and hundreds of services, managing those containers becomes super complicated. This is where the container engine comes in. The container-orchestration engine helps scale containers by automating the deployment, management, networking, and availability of containers.
-
-Docker Swarm and Mesosphere Marathon are other container-orchestration engines, but it is safe to say that Kubernetes has won the race (at least for now). Kubernetes also gave birth to Container-as-a-Service (CaaS) platforms like [OKD][18], the Origin community distribution of Kubernetes that powers [Red Hat OpenShift][19].
-
-To get started, visit the [Kubernetes GitHub repository][9], and access its documentation and learning resources from the [Kubernetes documentation][20] page.
-
-### Prometheus
-
-Prometheus is an open source system monitoring and alerting toolkit built at SoundCloud in 2012. Since then, many companies and organizations have adopted Prometheus, and the project has a very active developer and user community. It is now a standalone open source project that is maintained independently of the company.
-
-![Prometheus’ architecture][21]
-
-Prometheus’ architecture
-
-The easiest way to think about Prometheus is to visualize a production system that needs to be up 24 hours a day and 365 days a year. No system is perfect, and there are techniques to reduce failures (called fault-tolerant systems). However, if an issue occurs, the most important thing is to identify it as soon as possible. That is where a monitoring tool like Prometheus comes in handy. Prometheus is more than a container-monitoring tool, but it is most popular among cloud-native application companies. In addition, other open source monitoring tools, including [Grafana][22], leverage Prometheus.
-
-The best way to get started with Prometheus is to check out its [GitHub repo][10]. Running Prometheus locally is easy, but you need to have a container engine installed. You can access detailed documentation on [Prometheus’ website][23].
-
-### Envoy
-
-Envoy (or Envoy Proxy) is an open source edge and service proxy designed for cloud-native applications. Created at Lyft, Envoy is a high-performance, C++, distributed proxy designed for single services and applications, as well as a communications bus and a universal data plane designed for large microservice service mesh architectures. Built on the learnings of solutions such as Nginx, HAProxy, hardware load balancers, and cloud load balancers, Envoy runs alongside every application and abstracts the network by providing common features in a platform-agnostic manner.
-
-When all service traffic in an infrastructure flows through an Envoy mesh, it becomes easy to visualize problem areas via consistent observability, tune overall performance, and add substrate features in a single place. Basically, Envoy Proxy is a service mesh tool that helps organizations build a fault-tolerant system for production environments.
-
-There are numerous alternatives for service mesh applications, such as Uber’s [Linkerd][24] (discussed below) and [Istio][25]. Istio extends Envoy Proxy by deploying as a [Sidecar][26] and leveraging the [Mixer][27] configuration model. Notable Envoy features are:
-
- * All the "table stakes" features (when paired with a control plane, like Istio) are included
- * Low, 99th percentile latencies at scale when running under load
- * Acts as an L3/L4 filter at its core with many L7 filters provided out of the box
- * Support for gRPC and HTTP/2 (upstream/downstream)
- * It’s API-driven and supports dynamic configuration and hot reloads
- * Has a strong focus on metric collection, tracing, and overall observability
-
-
-
-Understanding Envoy, proving its capabilities, and realizing its full benefits require extensive experience with running production-level environments. You can learn more in its [detailed documentation][28] and by accessing its [GitHub][11] repository.
-
-## Incubating projects
-
-Following are six of the most popular open source CNCF Incubating projects.
-
-### rkt
-
-rkt, pronounced "rocket," is a pod-native container engine. It has a command-line interface (CLI) for running containers on Linux. In a sense, it is similar to other containers, like [Podman][29], Docker, and CRI-O.
-
-rkt was originally developed by CoreOS (later acquired by Red Hat), and you can find detailed [documentation][30] on its website and access the source code on [GitHub][12].
-
-### Jaeger
-
-Jaeger is an open source, end-to-end distributed tracing system for cloud-native applications. In one way, it is a monitoring solution like Prometheus. Yet it is different because its use cases extend into:
-
- * Distributed transaction monitoring
- * Performance and latency optimization
- * Root-cause analysis
- * Service dependency analysis
- * Distributed context propagation
-
-
-
-Jaeger is an open source technology built by Uber. You can find [detailed documentation][31] on its website and its [source code][13] on GitHub.
-
-### Linkerd
-
-Like Lyft with Envoy Proxy, Uber developed Linkerd as an open source solution to maintain its service at the production level. In some ways, Linkerd is just like Envoy, as both are service mesh tools designed to give platform-wide observability, reliability, and security without requiring configuration or code changes.
-
-However, there are some subtle differences between the two. While Envoy and Linkerd function as proxies and can report over services that are connected, Envoy isn’t designed to be a Kubernetes Ingress controller, as Linkerd is. Notable features of Linkerd include:
-
- * Support for multiple platforms (Docker, Kubernetes, DC/OS, Amazon ECS, or any stand-alone machine)
- * Built-in service discovery abstractions to unite multiple systems
- * Support for gRPC, HTTP/2, and HTTP/1.x requests plus all TCP traffic
-
-
-
-You can read more about it on [Linkerd’s website][32] and access its source code on [GitHub][14].
-
-### Helm
-
-Helm is basically the package manager for Kubernetes. If you’ve used Apache Maven, Maven Nexus, or a similar service, you will understand Helm’s purpose. Helm helps you manage your Kubernetes application. It uses "Helm Charts" to define, install, and upgrade even the most complex Kubernetes applications. Helm isn’t the only method for this; another concept becoming popular is [Kubernetes Operators][33], which are used by Red Hat OpenShift 4.
-
-You can try Helm by following the [quickstart guide][34] in its documentation or its [GitHub guide][15].
-
-### Etcd
-
-Etcd is a distributed, reliable key-value store for the most critical data in a distributed system. Its key features are:
-
- * Well-defined, user-facing API (gRPC)
- * Automatic TLS with optional client certificate authentication
- * Speed (benchmarked at 10,000 writes per second)
- * Reliability (distributed using Raft)
-
-
-
-Etcd is used as a built-in default data storage for Kubernetes and many other technologies. That said, it is rarely run independently or as a separate service; instead, it utilizes the one integrated into Kubernetes, OKD/OpenShift, or another service. There is also an [etcd Operator][35] to manage its lifecycle and unlock its API management capabilities:
-
-You can learn more in [etcd’s documentation][36] and access its [source code][16] on GitHub.
-
-### CRI-O
-
-CRI-O is an Open Container Initiative (OCI)-compliant implementation of the Kubernetes runtime interface. CRI-O is used for various functions including:
-
- * Runtime using runc (or any OCI runtime-spec implementation) and OCI runtime tools
- * Image management using containers/image
- * Storage and management of image layers using containers/storage
- * Networking support through the Container Network Interface (CNI)
-
-
-
-CRI-O provides plenty of [documentation][37], including guides, tutorials, articles, and even podcasts, and you can also access its [GitHub page][17].
-
-* * *
-
-Did I miss an interesting open source cloud-native project? Please let me know in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/cloud-native-projects
-
-作者:[Bryant Son][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_cloud_cc.png?itok=XSV7yR9e (clouds in the sky with blue pattern)
-[2]: https://opensource.com/article/18/7/what-are-cloud-native-apps
-[3]: https://thenewstack.io/10-key-attributes-of-cloud-native-applications/
-[4]: https://www.cncf.io
-[5]: https://opensource.com/sites/default/files/uploads/cncf_1.jpg (Cloud-Native Computing Foundation applications ecosystem)
-[6]: https://www.opencontainers.org
-[7]: https://opensource.com/sites/default/files/uploads/cncf_2.jpg (CNCF project maturity levels)
-[8]: https://github.com/cncf/toc/blob/master/process/graduation_criteria.adoc
-[9]: https://github.com/kubernetes/kubernetes
-[10]: https://github.com/prometheus/prometheus
-[11]: https://github.com/envoyproxy/envoy
-[12]: https://github.com/rkt/rkt
-[13]: https://github.com/jaegertracing/jaeger
-[14]: https://github.com/linkerd/linkerd
-[15]: https://github.com/helm/helm
-[16]: https://github.com/etcd-io/etcd
-[17]: https://github.com/cri-o/cri-o
-[18]: https://www.okd.io/
-[19]: https://www.openshift.com
-[20]: https://kubernetes.io/docs/home
-[21]: https://opensource.com/sites/default/files/uploads/cncf_3.jpg (Prometheus’ architecture)
-[22]: https://grafana.com
-[23]: https://prometheus.io/docs/introduction/overview
-[24]: https://linkerd.io/
-[25]: https://istio.io/
-[26]: https://istio.io/docs/reference/config/networking/v1alpha3/sidecar
-[27]: https://istio.io/docs/reference/config/policy-and-telemetry
-[28]: https://www.envoyproxy.io/docs/envoy/latest
-[29]: https://podman.io
-[30]: https://coreos.com/rkt/docs/latest
-[31]: https://www.jaegertracing.io/docs/1.13
-[32]: https://linkerd.io/2/overview
-[33]: https://coreos.com/operators
-[34]: https://helm.sh/docs
-[35]: https://github.com/coreos/etcd-operator
-[36]: https://etcd.io/docs/v3.3.12
-[37]: https://github.com/cri-o/cri-o/blob/master/awesome.md
diff --git a/sources/tech/20190814 How to install Python on Windows.md b/sources/tech/20190814 How to install Python on Windows.md
deleted file mode 100644
index a3b7ea2454..0000000000
--- a/sources/tech/20190814 How to install Python on Windows.md
+++ /dev/null
@@ -1,203 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to install Python on Windows)
-[#]: via: (https://opensource.com/article/19/8/how-install-python-windows)
-[#]: author: (Seth Kenlon https://opensource.com/users/sethhttps://opensource.com/users/greg-p)
-
-How to install Python on Windows
-======
-Install Python, run an IDE, and start coding right from your Microsoft
-Windows desktop.
-![Hands programming][1]
-
-So you want to learn to program? One of the most common languages to start with is [Python][2], popular for its unique blend of [object-oriented][3] structure and simple syntax. Python is also an _interpreted_ _language_, meaning you don't need to learn how to compile code into machine language: Python does that for you, allowing you to test your programs sometimes instantly and, in a way, while you write your code.
-
-Just because Python is easy to learn doesn't mean you should underestimate its potential power. Python is used by [movie][4] [studios][5], financial institutions, IT houses, video game studios, makers, hobbyists, [artists][6], teachers, and many others.
-
-On the other hand, Python is also a serious programming language, and learning it takes dedication and practice. Then again, you don't have to commit to anything just yet. You can install and try Python on nearly any computing platform, so if you're on Windows, this article is for you.
-
-If you want to try Python on a completely open source operating system, you can [install Linux][7] and then [try Python][8].
-
-### Get Python
-
-Python is available from its website, [Python.org][9]. Once there, hover your mouse over the **Downloads** menu, then over the **Windows** option, and then click the button to download the latest release.
-
-![Downloading Python on Windows][10]
-
-Alternatively, you can click the **Downloads** menu button and select a specific version from the downloads page.
-
-### Install Python
-
-Once the package is downloaded, open it to start the installer.
-
-It is safe to accept the default install location, and it's vital to add Python to PATH. If you don't add Python to your PATH, then Python applications won't know where to find Python (which they require in order to run). This is _not_ selected by default, so activate it at the bottom of the install window before continuing!
-
-![Select "Add Python 3 to PATH"][11]
-
-Before Windows allows you to install an application from a publisher other than Microsoft, you must give your approval. Click the **Yes** button when prompted by the **User Account Control** system.
-
-![Windows UAC][12]
-
-Wait patiently for Windows to distribute the files from the Python package into the appropriate locations, and when it's finished, you're done installing Python.
-
-Time to play.
-
-### Install an IDE
-
-To write programs in Python, all you really need is a text editor, but it's convenient to have an integrated development environment (IDE). An IDE integrates a text editor with some friendly and helpful Python features. IDLE 3 and NINJA-IDE are two options to consider.
-
-#### IDLE 3
-
-Python comes with an IDE called IDLE. You can write code in any text editor, but using an IDE provides you with keyword highlighting to help detect typos, a **Run** button to test code quickly and easily, and other code-specific features that a plain text editor like [Notepad++][13] normally doesn't have.
-
-To start IDLE, click the **Start** (or **Window**) menu and type **python** for matches. You may find a few matches, since Python provides more than one interface, so make sure you launch IDLE.
-
-![IDLE 3 IDE][14]
-
-If you don't see Python in the Start menu, launch the Windows command prompt by typing **cmd** in the Start menu, then type:
-
-
-```
-`C:\Windows\py.exe`
-```
-
-If that doesn't work, try reinstalling Python. Be sure to select **Add Python to PATH** in the install wizard. Refer to the [Python docs][15] for detailed instructions.
-
-#### Ninja-IDE
-
-If you already have some coding experience and IDLE seems too simple for you, try [Ninja-IDE][16]. Ninja-IDE is an excellent Python IDE. It has keyword highlighting to help detect typos, quotation and parenthesis completion to avoid syntax errors, line numbers (helpful when debugging), indentation markers, and a **Run** button to test code quickly and easily.
-
-![Ninja-IDE][17]
-
-To install it, visit the Ninja-IDE website and [download the Windows installer][18]. The process is the same as with Python: start the installer, allow Windows to install a non-Microsoft application, and wait for the installer to finish.
-
-Once Ninja-IDE is installed, double-click the Ninja-IDE icon on your desktop or select it from the Start menu.
-
-### Tell Python what to do
-
-Keywords tell Python what you want it to do. In either IDLE or Ninja-IDE, go to the File menu and create a new file.
-
-Ninja users: Do not create a new project, just a new file.
-
-In your new, empty file, type this into IDLE or Ninja-IDE:
-
-
-```
-`print("Hello world.")`
-```
-
- * If you are using IDLE, go to the Run menu and select the Run Module option.
- * If you are using Ninja, click the Run File button in the left button bar.
-
-
-
-![Running code in Ninja-IDE][19]
-
-Any time you run code, your IDE prompts you to save the file you're working on. Do that before continuing.
-
-The keyword **print** tells Python to print out whatever text you give it in parentheses and quotes.
-
-That's not very exciting, though. At its core, Python has access to only basic keywords like **print** and **help**, basic math functions, and so on.
-
-Use the **import** keyword to load more keywords. Start a new file in IDLE or Ninja and name it **pen.py**.
-
-**Warning**: Do not call your file **turtle.py**, because **turtle.py** is the name of the file that contains the turtle program you are controlling. Naming your file **turtle.py** confuses Python because it thinks you want to import your own file.
-
-Type this code into your file and run it:
-
-
-```
-`import turtle`
-```
-
-[Turtle][20] is a fun module to use. Add this code to your file:
-
-
-```
-turtle.begin_fill()
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.end_fill()
-```
-
-See what shapes you can draw with the turtle module.
-
-To clear your turtle drawing area, use the **turtle.clear()** keyword. What do you think the keyword **turtle.color("blue")** does?
-
-Try more complex code:
-
-
-```
-import turtle as t
-import time
-
-t.color("blue")
-t.begin_fill()
-
-counter = 0
-
-while counter < 4:
- t.forward(100)
- t.left(90)
- counter = counter+1
-
-t.end_fill()
-time.sleep(2)
-```
-
-As a challenge, try changing your script to get this result:
-
-![Example Python turtle output][21]
-
-Once you complete that script, you're ready to move on to more exciting modules. A good place to start is this [introductory dice game][22].
-
-### Stay Pythonic
-
-Python is a fun language with modules for practically anything you can think to do with it. As you can see, it's easy to get started with Python, and as long as you're patient with yourself, you may find yourself understanding and writing Python code with the same fluidity as you write your native language. Work through some [Python articles][23] here on Opensource.com, try scripting some small tasks for yourself, and see where Python takes you. To really integrate Python with your daily workflow, you might even try Linux, which is natively scriptable in ways no other operating system is. You might find yourself, given enough time, using the applications you create!
-
-Good luck, and stay Pythonic.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/how-install-python-windows
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/sethhttps://opensource.com/users/greg-p
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
-[2]: https://www.python.org/
-[3]: https://opensource.com/article/19/7/get-modular-python-classes
-[4]: https://github.com/edniemeyer/weta_python_db
-[5]: https://www.python.org/about/success/ilm/
-[6]: https://opensource.com/article/19/7/rgb-cube-python-scribus
-[7]: https://opensource.com/article/19/7/ways-get-started-linux
-[8]: https://opensource.com/article/17/10/python-101
-[9]: https://www.python.org/downloads/
-[10]: https://opensource.com/sites/default/files/uploads/win-python-install.jpg (Downloading Python on Windows)
-[11]: https://opensource.com/sites/default/files/uploads/win-python-path.jpg (Select "Add Python 3 to PATH")
-[12]: https://opensource.com/sites/default/files/uploads/win-python-publisher.jpg (Windows UAC)
-[13]: https://notepad-plus-plus.org/
-[14]: https://opensource.com/sites/default/files/uploads/idle3.png (IDLE 3 IDE)
-[15]: http://docs.python.org/3/using/windows.html
-[16]: http://ninja-ide.org/
-[17]: https://opensource.com/sites/default/files/uploads/win-python-ninja.jpg (Ninja-IDE)
-[18]: http://ninja-ide.org/downloads/
-[19]: https://opensource.com/sites/default/files/uploads/ninja_run.png (Running code in Ninja-IDE)
-[20]: https://opensource.com/life/15/8/python-turtle-graphics
-[21]: https://opensource.com/sites/default/files/uploads/win-python-idle-turtle.jpg (Example Python turtle output)
-[22]: https://opensource.com/article/17/10/python-101#python-101-dice-game
-[23]: https://opensource.com/sitewide-search?search_api_views_fulltext=Python
diff --git a/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md b/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md
deleted file mode 100644
index 267a54e8d7..0000000000
--- a/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md
+++ /dev/null
@@ -1,169 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Cockpit and the evolution of the Web User Interface)
-[#]: via: (https://fedoramagazine.org/cockpit-and-the-evolution-of-the-web-user-interface/)
-[#]: author: (Shaun Assam https://fedoramagazine.org/author/sassam/)
-
-Cockpit and the evolution of the Web User Interface
-======
-
-![][1]
-
-Over 3 years ago the Fedora Magazine published an article entitled [Cockpit: an overview][2]. Since then, the interface has see some eye-catching changes. Today’s Cockpit is cleaner and the larger fonts makes better use of screen real-estate.
-
-This article will go over some of the changes made to the UI. It will also explore some of the general tools available in the web interface to simplify those monotonous sysadmin tasks.
-
-### Cockpit installation
-
-Cockpit can be installed using the **dnf install cockpit** command. This provides a minimal setup providing the basic tools required to use the interface.
-
-Another option is to install the Headless Management group. This will install additional packages used to extend the usability of Cockpit. It includes extensions for NetworkManager, software packages, disk, and SELinux management.
-
-Run the following commands to enable the web service on boot and open the firewall port:
-
-```
-$ sudo systemctl enable --now cockpit.socket
-Created symlink /etc/systemd/system/sockets.target.wants/cockpit.socket -> /usr/lib/systemd/system/cockpit.socket
-
-$ sudo firewall-cmd --permanent --add-service cockpit
-success
-$ sudo firewall-cmd --reload
-success
-```
-
-### Logging into the web interface
-
-To access the web interface, open your favourite browser and enter the server’s domain name or IP in the address bar followed by the service port (9090). Because Cockpit uses HTTPS, the installation will create a self-signed certificate to encrypt passwords and other sensitive data. You can safely accept this certificate, or request a CA certificate from your sysadmin or a trusted source.
-
-Once the certificate is accepted, the new and improved login screen will appear. Long-time users will notice the username and password fields have been moved to the top. In addition, the white background behind the credential fields immediately grabs the user’s attention.
-
-![][3]
-
-A feature added to the login screen since the previous article is logging in with **sudo** privileges — if your account is a member of the wheel group. Check the box beside _Reuse my password for privileged tasks_ to elevate your rights.
-
-Another edition to the login screen is the option to connect to remote servers also running the Cockpit web service. Click _Other Options_ and enter the host name or IP address of the remote machine to manage it from your local browser.
-
-### Home view
-
-Right off the bat we get a basic overview of common system information. This includes the make and model of the machine, the operating system, if the system is up-to-date, and more.
-
-![][4]
-
-Clicking the make/model of the system displays hardware information such as the BIOS/Firmware. It also includes details about the components as seen with **lspci**.
-
-![][5]
-
-Clicking on any of the options to the right will display the details of that device. For example, the _% of CPU cores_ option reveals details on how much is used by the user and the kernel. In addition, the _Memory & Swap_ graph displays how much of the system’s memory is used, how much is cached, and how much of the swap partition active. The _Disk I/O_ and _Network Traffic_ graphs are linked to the Storage and Networking sections of Cockpit. These topics will be revisited in an upcoming article that explores the system tools in detail.
-
-#### Secure Shell Keys and authentication
-
-Because security is a key factor for sysadmins, Cockpit now has the option to view the machine’s MD5 and SHA256 key fingerprints. Clicking the **Show fingerprints** options reveals the server’s ECDSA, ED25519, and RSA fingerprint keys.
-
-![][6]
-
-You can also add your own keys by clicking on your username in the top-right corner and selecting **Authentication**. Click on **Add keys** to validate the machine on other systems. You can also revoke your privileges in the Cockpit web service by clicking on the **X** button to the right.
-
-![][7]
-
-#### Changing the host name and joining a domain
-
-Changing the host name is a one-click solution from the home page. Click the host name currently displayed, and enter the new name in the _Change Host Name_ box. One of the latest features is the option to provide a _Pretty name_.
-
-Another feature added to Cockpit is the ability to connect to a directory server. Click _Join a domain_ and a pop-up will appear requesting the domain address or name, organization unit (optional), and the domain admin’s credentials. The Domain Membership group provides all the packages required to join an LDAP server including FreeIPA, and the popular Active Directory.
-
-To opt-out, click on the domain name followed by _Leave Domain_. A warning will appear explaining the changes that will occur once the system is no longer on the domain. To confirm click the red _Leave Domain_ button.
-
-![][8]
-
-#### Configuring NTP and system date and time
-
-Using the command-line and editing config files definitely takes the cake when it comes to maximum tweaking. However, there are times when something more straightforward would suffice. With Cockpit, you have the option to set the system’s date and time manually or automatically using NTP. Once synchronized, the information icon on the right turns from red to blue. The icon will disappear if you manually set the date and time.
-
-To change the timezone, type the continent and a list of cities will populate beneath.
-
-![][9]
-
-#### Shutting down and restarting
-
-You can easily shutdown and restart the server right from home screen in Cockpit. You can also delay the shutdown/reboot and send a message to warn users.
-
-![][10]
-
-#### Configuring the performance profile
-
-If the _tuned_ and _tuned-utils_ packages are installed, performance profiles can be changed from the main screen. By default it is set to a recommended profile. However, if the purpose of the server requires more performance, we can change the profile from Cockpit to suit those needs.
-
-![][11]
-
-### Terminal web console
-
-A Linux sysadmin’s toolbox would be useless without access to a terminal. This allows admins to fine-tune the server beyond what’s available in Cockpit. With the addition of themes, admins can quickly adjust the text and background colours to suit their preference.
-
-Also, if you type **exit** by mistake, click the _Reset_ button in the top-right corner*.* This will provide a fresh screen with a flashing cursor.
-
-![][12]
-
-### Adding a remote server and the Dashboard overlay
-
-The Headless Management group includes the Dashboard module (**cockpit-dashboard**). This provides an overview the of the CPU, memory, network, and disk performance in a real-time graph. Remote servers can also be added and managed through the same interface.
-
-For example, to add a remote computer in Dashboard, click the **+** button. Enter the name or IP address of the server and select the colour of your choice. This helps to differentiate the stats of the servers in the graph. To switch between servers, click on the host name (as seen in the screen-cast below). To remove a server from the list, click the check-mark icon, then click the red trash icon. The example below demonstrates how Cockpit manages a remote machine named _server02.local.lan_.
-
-![][13]
-
-### Documentation and finding help
-
-As always, the _man_ pages are a great place to find documentation. A simple search in the command-line results with pages pertaining to different aspects of using and configuring the web service.
-
-```
-$ man -k cockpit
-cockpit (1) - Cockpit
-cockpit-bridge (1) - Cockpit Host Bridge
-cockpit-desktop (1) - Cockpit Desktop integration
-cockpit-ws (8) - Cockpit web service
-cockpit.conf (5) - Cockpit configuration file
-```
-
-The Fedora repository also has a package called **cockpit-doc**. The package’s description explains it best:
-
-> The Cockpit Deployment and Developer Guide shows sysadmins how to deploy Cockpit on their machines as well as helps developers who want to embed or extend Cockpit.
-
-For more documentation visit
-
-### Conclusion
-
-This article only touches upon some of the main functions available in Cockpit. Managing storage devices, networking, user account, and software control will be covered in an upcoming article. In addition, optional extensions such as the 389 directory service, and the _cockpit-ostree_ module used to handle packages in Fedora Silverblue.
-
-The options continue to grow as more users adopt Cockpit. The interface is ideal for admins who want a light-weight interface to control their server(s).
-
-What do you think about Cockpit? Share your experience and ideas in the comments below.
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/cockpit-and-the-evolution-of-the-web-user-interface/
-
-作者:[Shaun Assam][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/sassam/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-816x345.jpg
-[2]: https://fedoramagazine.org/cockpit-overview/
-[3]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-login-screen.png
-[4]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-home-screen.png
-[5]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-system-info.gif
-[6]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-ssh-key-fingerprints.png
-[7]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-authentication.png
-[8]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-hostname-domain.gif
-[9]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-date-time.png
-[10]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-power-options.gif
-[11]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-tuned.gif
-[12]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-terminal.gif
-[13]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-add-remote-servers.gif
diff --git a/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md b/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md
deleted file mode 100644
index 877845b87a..0000000000
--- a/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md
+++ /dev/null
@@ -1,197 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to Configure SFTP Server with Chroot in Debian 10)
-[#]: via: (https://www.linuxtechi.com/configure-sftp-chroot-debian10/)
-[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
-
-How to Configure SFTP Server with Chroot in Debian 10
-======
-
-**SFTP** stands for Secure File Transfer Protocol / SSH File Transfer Protocol, it is one of the most common method which is used to transfer files securely over ssh from our local system to remote server and vice-versa. The main advantage of sftp is that we don’t need to install any additional package except ‘**openssh-server**’, in most of the Linux distributions ‘openssh-server’ package is the part of default installation. Other benefit of sftp is that we can allow user to use sftp only not ssh.
-
-[![Configure-sftp-debian10][1]][2]
-
-Recently Debian 10, Code name ‘Buster’ has been released, in this article we will demonstrate how to configure sftp with Chroot ‘Jail’ like environment in Debian 10 System. Here Chroot Jail like environment means that user’s cannot go beyond from their respective home directories or users cannot change directories from their home directories. Following are the lab details:
-
- * OS = Debian 10
- * IP Address = 192.168.56.151
-
-
-
-Let’s jump into SFTP Configuration Steps,
-
-### Step:1) Create a Group for sftp using groupadd command
-
-Open the terminal, create a group with a name “**sftp_users**” using below groupadd command,
-
-```
-root@linuxtechi:~# groupadd sftp_users
-```
-
-### Step:2) Add Users to Group ‘sftp_users’ and set permissions
-
-In case you want to create new user and want to add that user to ‘sftp_users’ group, then run the following command,
-
-**Syntax:** # useradd -m -G sftp_users <user_name>
-
-Let’s suppose user name is ’Jonathan’
-
-```
-root@linuxtechi:~# useradd -m -G sftp_users jonathan
-```
-
-set the password using following chpasswd command,
-
-```
-root@linuxtechi:~# echo "jonathan:" | chpasswd
-```
-
-In case you want to add existing users to ‘sftp_users’ group then run beneath usermod command, let’s suppose already existing user name is ‘chris’
-
-```
-root@linuxtechi:~# usermod -G sftp_users chris
-```
-
-Now set the required permissions on Users,
-
-```
-root@linuxtechi:~# chown root /home/jonathan /home/chris/
-```
-
-Create an upload folder in both the user’s home directory and set the correct ownership,
-
-```
-root@linuxtechi:~# mkdir /home/jonathan/upload
-root@linuxtechi:~# mkdir /home/chris/upload
-root@linuxtechi:~# chown jonathan /home/jonathan/upload
-root@linuxtechi:~# chown chris /home/chris/upload
-```
-
-**Note:** User like Jonathan and Chris can upload files and directories to upload folder from their local systems.
-
-### Step:3) Edit sftp configuration file (/etc/ssh/sshd_config)
-
-As we have already stated that sftp operations are done over the ssh, so it’s configuration file is “**/etc/ssh/sshd_config**“, Before making any changes I would suggest first take the backup and then edit this file and add the following content,
-
-```
-root@linuxtechi:~# cp /etc/ssh/sshd_config /etc/ssh/sshd_config-org
-root@linuxtechi:~# vim /etc/ssh/sshd_config
-………
-#Subsystem sftp /usr/lib/openssh/sftp-server
-Subsystem sftp internal-sftp
-
-Match Group sftp_users
- X11Forwarding no
- AllowTcpForwarding no
- ChrootDirectory %h
- ForceCommand internal-sftp
-…………
-```
-
-Save & exit the file.
-
-To make above changes into the affect, restart ssh service using following systemctl command
-
-```
-root@linuxtechi:~# systemctl restart sshd
-```
-
-In above ‘sshd_config’ file we have commented out the line which starts with “Subsystem” and added new entry “Subsystem sftp internal-sftp” and new lines like,
-
-“**Match Group sftp_users”** –> It means if a user is a part of ‘sftp_users’ group then apply rules which are mentioned below to this entry.
-
-“**ChrootDierctory %h**” –> It means users can only change directories within their respective home directories, they cannot go beyond their home directories, or in other words we can say users are not permitted to change directories, they will get jai like environment within their directories and can’t access any other user’s and system’s directories.
-
-“**ForceCommand internal-sftp**” –> It means users are limited to sftp command only.
-
-### Step:4) Test and Verify sftp
-
-Login to any other Linux system which is on the same network of your sftp server and then try to ssh sftp server via the users that we have mapped in ‘sftp_users’ group.
-
-```
-[root@linuxtechi ~]# ssh root@linuxtechi
-root@linuxtechi's password:
-Write failed: Broken pipe
-[root@linuxtechi ~]# ssh root@linuxtechi
-root@linuxtechi's password:
-Write failed: Broken pipe
-[root@linuxtechi ~]#
-```
-
-Above confirms that users are not allowed to SSH , now try sftp using following commands,
-
-```
-[root@linuxtechi ~]# sftp root@linuxtechi
-root@linuxtechi's password:
-Connected to 192.168.56.151.
-sftp> ls -l
-drwxr-xr-x 2 root 1001 4096 Sep 14 07:52 debian10-pkgs
--rw-r--r-- 1 root 1001 155 Sep 14 07:52 devops-actions.txt
-drwxr-xr-x 2 1001 1002 4096 Sep 14 08:29 upload
-```
-
-Let’s try to download a file using sftp ‘**get**‘ command
-
-```
-sftp> get devops-actions.txt
-Fetching /devops-actions.txt to devops-actions.txt
-/devops-actions.txt 100% 155 0.2KB/s 00:00
-sftp>
-sftp> cd /etc
-Couldn't stat remote file: No such file or directory
-sftp> cd /root
-Couldn't stat remote file: No such file or directory
-sftp>
-```
-
-Above output confirms that we are able to download file from our sftp server to local machine and apart from this we have also tested that users cannot change directories.
-
-Let’s try to upload a file under “**upload**” folder,
-
-```
-sftp> cd upload/
-sftp> put metricbeat-7.3.1-amd64.deb
-Uploading metricbeat-7.3.1-amd64.deb to /upload/metricbeat-7.3.1-amd64.deb
-metricbeat-7.3.1-amd64.deb 100% 38MB 38.4MB/s 00:01
-sftp> ls -l
--rw-r--r-- 1 1001 1002 40275654 Sep 14 09:18 metricbeat-7.3.1-amd64.deb
-sftp>
-```
-
-This confirms that we have successfully uploaded a file from our local system to sftp server.
-
-Now test the SFTP server with winscp tool, enter the sftp server ip address along user’s credentials,
-
-[![Winscp-sftp-debian10][1]][3]
-
-Click on Login and then try to download and upload files
-
-[![Download-file-winscp-debian10-sftp][1]][4]
-
-Now try to upload files in upload folder,
-
-[![Upload-File-using-winscp-Debian10-sftp][1]][5]
-
-Above window confirms that uploading is also working fine, that’s all from this article. If these steps help you to configure SFTP server with chroot environment in Debian 10 then please do share your feedback and comments.
-
---------------------------------------------------------------------------------
-
-via: https://www.linuxtechi.com/configure-sftp-chroot-debian10/
-
-作者:[Pradeep Kumar][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.linuxtechi.com/author/pradeep/
-[b]: https://github.com/lujun9972
-[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[2]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Configure-sftp-debian10.jpg
-[3]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Winscp-sftp-debian10.jpg
-[4]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Download-file-winscp-debian10-sftp.jpg
-[5]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Upload-File-using-winscp-Debian10-sftp.jpg
diff --git a/sources/tech/20190925 Debugging in Emacs- The Grand Unified Debugger.md b/sources/tech/20190925 Debugging in Emacs- The Grand Unified Debugger.md
deleted file mode 100644
index f1a7fe8060..0000000000
--- a/sources/tech/20190925 Debugging in Emacs- The Grand Unified Debugger.md
+++ /dev/null
@@ -1,97 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Debugging in Emacs: The Grand Unified Debugger)
-[#]: via: (https://opensourceforu.com/2019/09/debugging-in-emacs-the-grand-unified-debugger/)
-[#]: author: (Vineeth Kartha https://opensourceforu.com/author/vineeth-kartha/)
-
-Debugging in Emacs: The Grand Unified Debugger
-======
-
-[![][1]][2]
-
-_This article briefly explores the features of the Grand Unified Debugger, a debugging tool for Emacs._
-
-If you are a C/C++ developer, it is highly likely that you have crossed paths with GDB (the GNU debugger) which is, without doubt, one of the most powerful and unrivalled debuggers out there. Its only drawback is that it is command line based, and though that offers a lot of power, it is sometimes a bit restrictive as well. This is why smart people started coming up with IDEs to integrate editors and debuggers, and give them a GUI. There are still developers who believe that using the mouse reduces productivity and that mouse-click based GUIs are temptations by the devil.
-Since Emacs is one of the coolest text editors out there, I am going to show you how to write, compile and debug code without having to touch the mouse or move out of Emacs.
-
-![Figure 1: Compile command in Emacs’ mini buffer][3]
-
-![Figure 2: Compilation status][4]
-
-The Grand Unified Debugger, or GUD as it is commonly known, is an Emacs mode in which GDB can be run from within Emacs. This provides all the features of Emacs in GDB. The user does not have to move out of the editor to debug the code written.
-
-**Setting the stage for the Grand Unified Debugger**
-If you are using a Linux machine, then it is likely you will have GDB and gcc already installed. The next step is to ensure that Emacs is also installed. I am assuming that the readers are familiar with GDB and have used it at least for basic debugging. If not, please do check out some quick introductions to GDB that are widely available on the Internet.
-
-For people who are new to Emacs, let me introduce you to some basic terminology. Throughout this article, you will see shortcut commands such as C-c, M-x, etc. C means the Ctrl key and M means the Alt key. C-c means the Ctrl + c keys are pressed. If you see C-c c, it means Ctrl + c is pressed followed by c. Also, in Emacs, the main area where you edit the text is called the main buffer, and the area at the bottom of the Emacs window, where commands are entered, is called the mini buffer.
-Start Emacs and to create a new file, press _C-x C-f_. This will prompt you to enter a file name. Let us call our file ‘buggyFactorial.cpp’. Once the file is open, type in the code shown below:
-
-```
-#include
-#include
-int factorial(int num) {
-int product = 1;
-while(num--) {
-product *= num;
-}
-return product;
-}
-int main() {
-int result = factorial(5);
-assert(result == 120);
-}
-```
-
-Save the file with _C-x C-s_. Once the file is saved, it’s time to compile the code. Press _M-x_ and in the prompt that comes up, type in compile and hit Enter. Then, in the prompt, replace whatever is there with _g++ -g buggyFactorial.cpp_ and again hit _Enter_.
-
-This will open up another buffer in Emacs that will show the status of the compile and, hopefully, if the code typed in is correct, you will get a buffer like the one shown in Figure 2.
-
-To hide this compilation status buffer, make sure your cursor is in the compilation buffer (you can do this without the mouse using _C-x o_-this is used to move the cursor from one open buffer to the other), and then press _C-x 0_. The next step is to run the code and see if it works fine. Press M-! and in the mini buffer prompt, type _./a.out._
-
-See the mini buffer that says the assertion is failed. Clearly, something is wrong with the code, because the factorial (5) is 120. So let’s debug the code now.
-
-![Figure 3: Output of the code in the mini buffer][5]
-
-![Figure 4: The GDB buffer in Emacs][6]
-
-**Debugging the code using GUD**
-Now, since we have the code compiled, it’s time to see what is wrong with it. Press M-x and in the prompt, enter _gdb._ In the next prompt that appears, write _gdb -i=mi a.out_, which will start GDB in the Emacs buffer and if everything goes well, you should get the window that’s shown in Figure 4.
-At the gdb prompt, type break main and then r to run the program. This should start running the program and should break at the _main()_.
-
-As soon as GDB hits the break point at main, a new buffer will open up showing the code that you are debugging. Notice the red dot on the left side, which is where your breakpoint was set. There will be a small indicator that shows which line of the code you are on. Currently, this will be the same as the break point itself (Figure 5).
-
-![Figure 5: GDB and the code in split windows][7]
-
-![Figure 6: Show the local variables in a separate frame in Emacs][8]
-
-To debug the factorial function, we need to step into it. For this, you can either use the _gdb_ prompt and the gdb command step, or you can use the Emacs shortcut _C-c C-s_. There are other similar shortcuts, but I prefer using the GDB commands. So I will use them in the rest of this article.
-Let us keep an eye on the local variables while stepping through the factorial number. Check out Figure 6 for how to get an Emacs frame to show the local variables.
-
-Step through the code in the GDB prompt and watch the value of the local variable change. In the first iteration of the loop itself, we see a problem. The value of the product should have been 5 and not 4.
-
-This is where I leave you and now it’s up to the readers to explore and discover the magic land called GUD mode. Every gdb command works in the GUD mode as well. I leave the fix to this code as an exercise to readers. Explore and see how you can customise things to make your workflow simpler and become more productive while debugging.
-
---------------------------------------------------------------------------------
-
-via: https://opensourceforu.com/2019/09/debugging-in-emacs-the-grand-unified-debugger/
-
-作者:[Vineeth Kartha][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensourceforu.com/author/vineeth-kartha/
-[b]: https://github.com/lujun9972
-[1]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Screenshot-from-2019-09-25-15-39-46.png?resize=696%2C440&ssl=1 (Screenshot from 2019-09-25 15-39-46)
-[2]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Screenshot-from-2019-09-25-15-39-46.png?fit=800%2C506&ssl=1
-[3]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_1.png?resize=350%2C228&ssl=1
-[4]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_2.png?resize=350%2C228&ssl=1
-[5]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_3.png?resize=350%2C228&ssl=1
-[6]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_4.png?resize=350%2C227&ssl=1
-[7]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_5.png?resize=350%2C200&ssl=1
-[8]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/09/Figure_6.png?resize=350%2C286&ssl=1
diff --git a/sources/tech/20191003 4 open source eBook readers for Android.md b/sources/tech/20191003 4 open source eBook readers for Android.md
deleted file mode 100644
index f2c6638bc4..0000000000
--- a/sources/tech/20191003 4 open source eBook readers for Android.md
+++ /dev/null
@@ -1,174 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (4 open source eBook readers for Android)
-[#]: via: (https://opensource.com/article/19/10/open-source-ereaders-android)
-[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
-
-4 open source eBook readers for Android
-======
-Looking for a new eBook app? Check out these four solid, open source
-eBook readers for Android.
-![Computer browser with books on the screen][1]
-
-Who doesn't like a good read? Instead of frittering away your time on social media or a [messaging app][2], you can enjoy a book, magazine, or another document on your Android-powered phone or tablet.
-
-To do that, all you need is the right eBook reader app. So let's take a look at four solid, open source eBook readers for Android.
-
-### Book Reader
-
-Let's start off with my favorite open source Android eBook reader: [Book Reader][3]. It's based on the older, open source version of the now-proprietary FBReader app. Like earlier versions of its progenitor, Book Reader is simple and minimal, but it does a great job.
-
-**Pros of Book Reader:**
-
- * It's easy to use.
- * The app's interface follows Android's [Material Design guidelines][4], so it's very clean.
- * You can add bookmarks to an eBook and share text with other apps on your device.
- * There's growing support for languages other than English.
-
-
-
-**Cons of Book Reader:**
-
- * Book Reader has a limited number of configuration options.
- * There's no built-in dictionary or support for an external dictionary.
-
-
-
-**Supported eBook formats:**
-
-Book Reader supports EPUB, .mobi, PDF, [DjVu][5], HTML, plain text, Word documents, RTF, and [FictionBook][6].
-
-![Book Reader Android app][7]
-
-Book Reader's source code is licensed under the GNU General Public License version 3.0, and you can find it on [GitLab][8].
-
-### Cool Reader
-
-[Cool Reader][9] is a zippy and easy-to-use eBook app. While I think the app's icons are reminiscent of those found in Windows Vista, Cool Reader does have several useful features.
-
-**Pros of Cool Reader:**
-
- * It's highly configurable. You can change fonts, line and paragraph spacing, hyphenation, font sizes, margins, and background colors.
- * You can override the stylesheet in a book. I found this useful with two or three books that set all text in small capital letters.
- * It automatically scans your device for new books when you start it up. You can also access books on [Project Gutenberg][10] and the [Internet Archive][11].
-
-
-
-**Cons of Cool Reader:**
-
- * Cool Reader doesn't have the cleanest or most modern interface.
- * While it's usable out of the box, you really need to do a bit of configuration to make Cool Reader comfortable to use.
- * The app's default dictionary is proprietary, although you can swap it out for [an open one][12].
-
-
-
-**Supported eBook formats:**
-
-You can use Cool Reader to browse EPUB, FictionBook, plain text, RTF, HTML, [Compiled HTML Help][13] (.chm), and TCR (the eBook format for the Psion series of handheld computers) files.
-
-![Cool Reader Android app][14]
-
-Cool Reader's source code is licensed under the GNU General Public License version 2, and you can find it on [Sourceforge][15].
-
-### KOReader
-
-[KOReader][16] was originally created for [E Ink][17] eBook readers but found its way to Android. While testing it, I found KOReader to be both useful and frustrating in equal measures. It's definitely not a bad app, but it's not my first choice.
-
-**Pros of KOReader:**
-
- * It's highly configurable.
- * It supports multiple languages.
- * It allows you to look up words using a [dictionary][18] (if you have one installed) or Wikipedia (if you're connected to the internet).
-
-
-
-**Cons of KOReader:**
-
- * You need to change the settings for each book you read. KOReader doesn't remember settings when you open a new book.
- * The interface is reminiscent of a dedicated eBook reader. The app doesn't have that Android look and feel.
-
-
-
-**Supported eBook formats:**
-
-You can view PDF, DjVu, CBT, and [CBZ][5] eBooks. It also supports EPUB, FictionBook, .mobi, Word documents, text files, and [Compiled HTML Help][13] (.chm) files.
-
-![KOReader Android app][19]
-
-KOReader's source code is licensed under the GNU Affero General Public License version 3.0, and you can find it on [GitHub][20].
-
-### Booky McBookface
-
-Yes, that really is the name of [this eBook reader][21]. It's the most basic of the eBook readers in this article but don't let that (or the goofy name) put you off. Booky McBookface is easy to use and does the one thing it does quite well.
-
-**Pros of Booky McBookface:**
-
- * There are no frills. It's just you and your eBook.
- * The interface is simple and clean.
- * Long-tapping the app's icon in the Android Launcher pops up a menu from which you can open the last book you were reading, get a list of unread books, or find and open a book on your device.
-
-
-
-**Cons of Booky McBookface:**
-
- * The app has few configuration options—you can change the size of the font and the brightness, and that's about it.
- * You need to use the buttons at the bottom of the screen to navigate through an eBook. Tapping the edges of the screen doesn't work.
- * You can't add bookmarks to an eBook.
-
-
-
-**Supported eBook formats:**
-
-You can read eBooks in EPUB, HTML, or plain text formats with Booky McBookface.
-
-![Booky McBookface Android app][22]
-
-Booky McBookface's source code is available under the GNU General Public License version 3.0, and you can find it [on GitHub][23].
-
-Do you have a favorite open source eBook reader for Android? Share it with the community by leaving a comment.
-
-Have you ever downloaded an Android app only to find that it wants access to all your phone's...
-
-There is a rich and growing ecosystem of open source applications for mobile devices, just like the...
-
-With these seven open source apps, you can play chess against your phone or an online opponent,...
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/open-source-ereaders-android
-
-作者:[Scott Nesbitt][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/scottnesbitt
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_browser_program_books_read.jpg?itok=iNMWe8Bu (Computer browser with books on the screen)
-[2]: https://opensource.com/article/19/3/open-messenger-client
-[3]: https://f-droid.org/en/packages/com.github.axet.bookreader/
-[4]: https://material.io/design/
-[5]: https://opensource.com/article/19/3/comic-book-archive-djvu
-[6]: https://en.wikipedia.org/wiki/FictionBook
-[7]: https://opensource.com/sites/default/files/uploads/book_reader-book-list.png (Book Reader Android app)
-[8]: https://gitlab.com/axet/android-book-reader/tree/HEAD
-[9]: https://f-droid.org/en/packages/org.coolreader/
-[10]: https://www.gutenberg.org/
-[11]: https://archive.org
-[12]: http://aarddict.org/
-[13]: https://fileinfo.com/extension/chm
-[14]: https://opensource.com/sites/default/files/uploads/cool_reader-icons.png (Cool Reader Android app)
-[15]: https://sourceforge.net/projects/crengine/
-[16]: https://f-droid.org/en/packages/org.koreader.launcher/
-[17]: https://en.wikipedia.org/wiki/E_Ink
-[18]: https://github.com/koreader/koreader/wiki/Dictionary-support
-[19]: https://opensource.com/sites/default/files/uploads/koreader-lookup.png (KOReader Android app)
-[20]: https://github.com/koreader/koreader
-[21]: https://f-droid.org/en/packages/com.quaap.bookymcbookface/
-[22]: https://opensource.com/sites/default/files/uploads/booky_mcbookface-menu.png (Booky McBookface Android app)
-[23]: https://github.com/quaap/BookyMcBookface
diff --git a/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md b/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md
new file mode 100644
index 0000000000..da080e65ea
--- /dev/null
+++ b/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md
@@ -0,0 +1,307 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (20 Linux Command Tips and Tricks That Will Save You A Lot of Time)
+[#]: via: (https://itsfoss.com/linux-command-tricks/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+20 Linux Command Tips and Tricks That Will Save You A Lot of Time
+======
+
+_**Brief**: Here are some tiny but useful Linux commands, terminal tricks and shortcuts that will save you a lot of time while working with Linux command line._
+
+Have you ever encountered a moment when you see your colleague using some simple Linux commands for tasks that took you several keystrokes? And when you saw that you were like, “Wow! I didn’t know it could have been done that easily”.
+
+In this article, I’ll show you some pro Linux command tricks that will save you a lot of time and in some cases, from plenty of frustration. Not only your friends or colleagues will ‘wow’ at you, it will also help you increase your productivity as you will need fewer keystrokes and even fewer mouse clicks.
+
+It’s not that these are Linux tips for beginners only. Chances are that even experienced Linux users will find some hidden gems that they were not aware despite using Linux for all these years.
+
+In any case, you [learn Linux][1] by experience, be it your own or someone else’s :)
+
+### Cool Linux terminal tricks to save time and increase productivity
+
+![][2]
+
+You might already know a few of these Linux command tips or perhaps all of it. In either case, you are welcome to share your favorite tricks in the comment section.
+
+Some of these tips also depend on how the shell is configured. Let’s begin!
+
+#### 0\. Using tab for autocompletion
+
+I’ll start with something really obvious and yet really important: tab completion.
+
+When you are starting to type something in Linux terminal, you can hit the tab key and it will suggest all the possible options that start with string you have typed so far.
+
+For example, if you are trying to copy a file named my_best_file_1.txt, you can just type ‘cp m’ and hit tab to see the possible options.
+
+![Use tab for auto-completion][3]
+
+You can use tab in completing commands as well.
+
+[irp posts=”16244″ name=”Difference Between apt and apt-get Explained”]
+
+#### 1\. Switch back to the last working directory
+
+Suppose you end up in a long directory path and then you move to another directory in a totally different path. And then you realize that you have to go back to the previous directory you were in. In this case, all you need to do is to type this command:
+
+```
+cd -
+```
+
+This will put you back in the last working directory. You don’t need to type the long directory path or copy paste it anymore.
+
+![Easily switch between directories][4]
+
+#### 2\. Go back to home directory
+
+This is way too obvious. You can use the command below to move to your home directory from anywhere in Linux command-line:
+
+```
+cd ~
+```
+
+However, you can also use just cd to go back to home directory:
+
+```
+cd
+```
+
+Most modern Linux distributions have the shell pre-configured for this command. Saves you at least two keystrokes here.
+
+![Move to Home as quickly as possible][5]
+
+#### 3\. List the contents of a directory
+
+You must be guessing what’s the trick in the command for listing the contents of a directory. Everyone knows to use the ls -l for this purpose.
+
+And that’s the thing. Most people use ls -l to list the contents of the directory, whereas the same can be done with the following command:
+
+```
+ll
+```
+
+Again, this depends on the Linux distributions and shell configuration, but chances are that you’ll be able to use it in most Linux distributions.
+
+![Using ll instead of ls -l][6]
+
+#### 4\. Running multiple commands in one single command
+
+Suppose, you have to run several commands one after another. Do you wait for the first command to finish running and then execute the next one?
+
+You can use the ‘;’ separator for this purpose. This way, you can run a number of commands in one line. No need to wait for the previous commands to finish their business.
+
+```
+command_1; command_2; command_3
+```
+
+#### 5\. Running multiple commands in one single command only if the previous command was successful
+
+In the previous command, you saw how to run several commands in one single command to save time. But what if you have to make sure that commands don’t fail?
+
+Imagine a situation where you want to build a code and then if the build was successful, run the make?
+
+You can use && separator for this case. && makes sure that the next command will only run when the previous command was successful.
+
+```
+command_1 && command_2
+```
+
+A good example of this command is when you use sudo apt update && sudo apt upgrade to upgrade your system.
+
+#### 6\. Easily search and use the commands that you had used in the past
+
+Imagine a situation where you used a long command couple of minutes/hours ago and you have to use it again. Problem is that you cannot remember the exact command anymore.
+
+Reverse search is your savior here. You can search for the command in the history using a search term.
+
+Just use the keys ctrl+r to initiate reverse search and type some part of the command. It will look up into the history and will show you the commands that matches the search term.
+
+```
+ctrl+r search_term
+```
+
+By default, it will show just one result. To see more results matching your search term, you will have to use ctrl+r again and again. To quit reverse search, just use Ctrl+C.
+
+![Reverse search in command history][7]
+
+Note that in some Bash shells, you can also use Page Up and Down key with your search term and it will autocomplete the command.
+
+#### 7\. Unfreeze your Linux terminal from accidental Ctrl+S
+
+You probably are habitual of using Ctrl+S for saving. But if you use that in Linux terminal, you’ll have a frozen terminal.
+
+Don’t worry, you don’t have to close the terminal, not anymore. Just use Ctrl+Q and you can use the terminal again.
+
+```
+ctrl+Q
+```
+
+#### 8\. Move to beginning or end of line
+
+Suppose you are typing a long command and midway you realize that you had to change something at the beginning. You would use several left arrow keystrokes to move to the start of the line. And similarly for going to the end of the line.
+
+You can use Home and End keys here of course but alternatively, you can use Ctrl+A to go to the beginning of the line and Ctrl+E to go to the end.
+
+![Move to the beginning or end of the line][8]
+
+I find it more convenient than using the home and end keys, especially on my laptop.
+
+#### 9\. Reading a log file in real time
+
+In situations where you need to analyze the logs while the application is running, you can use the tail command with -f option.
+
+```
+tail -f path_to_Log
+```
+
+You can also use the regular grep options to display only those lines that are meaningful to you:
+
+```
+tail -f path_to_log | grep search_term
+```
+
+You can also use the option F here. This will keep the tail running even if the log file is deleted. So if the log file is created again, tail will continue logging.
+
+#### 10\. Reading compressed logs without extracting
+
+Server logs are usually gzip compressed to save disk space. It creates an issue for the developer or sysadmin analyzing the logs. You might have to [scp][9] it to your local and then extract it to access the files because, at times, you don’t have write permission to extract the logs.
+
+Thankfully, z commands save you in such situations. z commands provide alternatives of the regular commands that you use to deal with log files such as less, cat, grep etc.
+
+So you get zless, zcat, zgrep etc and you don’t even have to explicitly extract the compressed files. Please refer to my earlier article about [using z commands to real compressed logs][10] in detail.
+
+This was one of the secret finds that won me a coffee from my colleague.
+
+#### 11\. Use less to read files
+
+To see the contents of a file, cat is not the best option especially if it is a big file. cat command will display the entire file on your screen.
+
+You can use Vi, Vim or other terminal based text editors but if you just want to read a file, less command is a far better choice.
+
+```
+less path_to_file
+```
+
+You can search for terms inside less, move by page, display with line numbers etc.
+
+#### 12\. Reuse the last item from the previous command with !$
+
+Using the argument of the previous command comes handy in many situations.
+
+Say you have to create a directory and then go into the newly created directory. There you can use the !$ options.
+
+![Use !$ to use the argument of last command][11]
+
+A better way to do the same is to use alt+. . You can use . a number times to shuffle between the options of the last commands.
+
+#### 13\. Reuse the previous command in present command with !!
+
+You can call the entire previous command with !!. This comes particularly useful when you have to run a command and realize that it needs root privileges.
+
+A quick sudo !! saves plenty of keystrokes here.
+
+![Use !! to use last command as an argument][12]
+
+#### 14\. Using alias to fix typos
+
+You probably already know what is an alias command in Linux. What you can do is, to use them to fix typos.
+
+For example, you might often mistype grep as gerp. If you put an alias in your bashrc in this fashion:
+
+```
+alias gerp=grep
+```
+
+This way you won’t have to retype the command again.
+
+#### 15\. Copy Paste in Linux terminal
+
+This one is slightly ambiguous because it depends on Linux distributions and terminal applications. But in general, you should be able to copy paste commands with these shortcuts:
+
+ * Select the text for copying and right click for paste (works in Putty and other Windows SSH clients)
+ * Select the text for copying and middle click (scroll button on the mouse) for paste
+ * Ctrl+Shift+C for copy and Ctrl+Shift+V for paste
+
+
+
+#### 16\. Kill a running command/process
+
+This one is perhaps way too obvious. If there is a command running in the foreground and you want to exit it, you can press Ctrl+C to stop that running command.
+
+#### 17\. Using yes command for commands or scripts that need interactive response
+
+If there are some commands or scripts that need user interaction and you know that you have to enter Y each time it requires an input, you can use Yes command.
+
+Just use it in the below fashion:
+
+```
+yes | command_or_script
+```
+
+#### 18\. Empty a file without deleting it
+
+If you just want to empty the contents of a text file without deleting the file itself, you can use a command similar to this:
+
+```
+> filename
+```
+
+#### 19\. Find if there are files containing a particular text
+
+There are multiple ways to search and find in Linux command line. But in the case when you just want to see if there are files that contain a particular text, you can use this command:
+
+```
+grep -Pri Search_Term path_to_directory
+```
+
+I highly advise mastering find command though.
+
+#### 20\. Using help with any command
+
+I’ll conclude this article with one more obvious and yet very important ‘trick’, using help with a command or a command line tool.
+
+Almost all command and command line tool come with a help page that shows how to use the command. Often using help will tell you the basic usage of the tool/command.
+
+Just use it in this fashion:
+
+```
+command_tool --help
+```
+
+#### Your favorite Linux command line tricks?
+
+I have deliberately not included commands like [fuck][13] because those are not standard commands that you’ll find everywhere. The tricks discussed here should be usable almost in all Linux distributions and shell without the need of installing a new tool.
+
+I would also suggest [using alias command in Linux][14] to replace complicated commands with a simple. Saves a lot of time.
+
+I know that there are more Linux command tricks to save time in the terminal. Why not share some of your experiences with Linux and do share your best trick with rest of the community here? The comment section below is at your disposal.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/linux-command-tricks/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/learn-linux-for-free/
+[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-Tricks-Save-Time.jpeg?resize=800%2C450&ssl=1
+[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-8.png?ssl=1
+[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-1.png?ssl=1
+[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-2.png?ssl=1
+[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-3.png?ssl=1
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-4.png?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-5.png?ssl=1
+[9]: http://www.hypexr.org/linux_scp_help.php
+[10]: https://itsfoss.com/read-compressed-log-files-linux/
+[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-6.png?ssl=1
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-7.png?ssl=1
+[13]: https://github.com/nvbn/thefuck
+[14]: https://linuxhandbook.com/linux-alias-command/
diff --git a/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md b/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md
deleted file mode 100644
index 0f15fae6e6..0000000000
--- a/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md
+++ /dev/null
@@ -1,188 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to make a Halloween lantern with Inkscape)
-[#]: via: (https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape)
-[#]: author: (Jess Weichler https://opensource.com/users/cyanide-cupcake)
-
-How to make a Halloween lantern with Inkscape
-======
-Use open source tools to make a spooky and fun decoration for your
-favorite Halloween haunt.
-![Halloween - backlit bat flying][1]
-
-The spooky season is almost here! This year, decorate your haunt with a unique Halloween lantern made with open source!
-
-Typically, a portion of a lantern's structure is opaque to block the light from within. What makes a lantern a lantern are the parts that are missing: windows cut from the structure so that light can escape. While it's impractical for lighting, a lantern with windows in spooky shapes and lurking silhouettes can be atmospheric and a lot of fun to create.
-
-This article demonstrates how to create your own lantern using [Inkscape][2]. If you don't have Inkscape, you can install it from your software repository on Linux or download it from the [Inkscape website][3] on MacOS and Windows.
-
-### Supplies
-
- * Template ([A4][4] or [Letter][5] size)
- * Cardstock (black is traditional)
- * Tracing paper (optional)
- * Craft knife, ruler, and cutting mat (a craft cutting machine/laser cutter can be used instead)
- * Craft glue
- * LED tea-light "candle"
-_Safety note:_ Only use battery-operated candles for this project.
-
-
-
-### Understanding the template
-
-To begin, download the correct template for your region (A4 or Letter) from the links above and open it in Inkscape.
-
-* * *
-
-* * *
-
-* * *
-
-**![Lantern template screen][6]**
-
-The gray-and-white checkerboard background is see-through (in technical terms, it's an _alpha channel_.)
-
-The black base forms the lantern. Right now, there are no windows for light to shine through; the lantern is a solid black base. You will use the **Union** and **Difference** options in Inkscape to design the windows digitally.
-
-The dotted blue lines represent fold scorelines. The solid orange lines represent guides. Windows for light should not be placed outside the orange boxes.
-
-To the left of the template are a few pre-made objects you can use in your design.
-
-### To create a window or shape
-
- 1. Create an object that looks like the window style you want. Objects can be created using any of the shape tools in Inkscape's left toolbar. Alternately, you can download Creative Commons- or Public Domain-licensed clipart and import the PNG file into your project.
- 2. When you are happy with the shape of the object, turn it into a **Path** (rather than a **Shape**, which Inkscape sees as two different kinds of objects) by selecting **Object > Object to Path** in the top menu.
-
-
-
-![Object to path menu][7]
-
- 3. Place the object on top of the base shape.
- 4. Select both the object and the black base by clicking one, pressing and holding the Shift key, then selecting the other.
- 5. Select **Object > Difference** from the top menu to remove the shape of the object from the base. This creates what will become a window in your lantern.
-
-
-
-![Object > Difference menu][8]
-
-### To add an object to a window
-
-After making a window, you can add objects to it to create a scene.
-
-**Tips:**
-
- * All objects, including text, must be connected to the base of the lantern. If not, they will fall out after cutting and leave a blank space.
- * Avoid small, intricate details. These are difficult to cut, even when using a machine like a laser cutter or a craft plotter.
-
-
- 1. Create or import an object.
- 2. Place the object inside the window so that it is touching at least two sides of the base.
- 3. With the object selected, choose **Object > Object to Path** from the top menu.
-
-
-
-![Object to path menu][9]
-
- 4. Select the object and the black base by clicking on each one while holding the Shift key).
- 5. Select **Object > Union** to join the object and the base.
-
-
-
-### Add text
-
-Text can either be cut out from the base to create a window (as I did with the stars) or added to a window (which blocks the light from within the lantern). If you're creating a window, only follow steps 1 and 2 below, then use **Difference** to remove the text from the base layer.
-
- 1. Select the Text tool from the left sidebar to create text. Thick, bold fonts work best.
-
-![Text tool][10]
-
- 2. Select your text, then choose **Path > Object to Path** from the top menu. This converts the text object to a path. Note that this step means you can no longer edit the text, so perform this step _only after_ you're sure you have the word or words you want.
-
- 3. After you have converted the text, you can press **F2** on your keyboard to activate the **Node Editor** tool to clearly show the nodes of the text when it is selected with this tool.
-
-
-
-
-![Text selected with Node editor][11]
-
- 4. Ungroup the text.
- 5. Adjust each letter so that it slightly overlaps its neighboring letter or the base.
-
-
-
-![Overlapping the text][12]
-
- 6. To connect all of the letters to one another and to the base, re-select all the text and the base, then select **Path > Union**.
-
-![Connecting letters and base with Path > Union][13]
-
-
-
-
-### Prepare for printing
-
-The following instructions are for hand-cutting your lantern. If you're using a laser cutter or craft plotter, follow the techniques required by your hardware to prepare your files.
-
- 1. In the **Layer** panel, click the **Eye** icon beside the **Safety** layer to hide the safety lines. If you don't see the Layer panel, reveal it by selecting **Layer > Layers** from the top menu.
- 2. Select the black base. In the **Fill and Stroke** panel, set the fill to **X** (meaning _no fill_) and the **Stroke** to solid black (that's #000000ff to fans of hexes).
-
-
-
-![Setting fill and stroke][14]
-
- 3. Print your pattern with **File > Print**.
-
- 4. Using a craft knife and ruler, carefully cut around each black line. Lightly score the dotted blue lines, then fold.
-
-![Cutting out the lantern][15]
-
- 5. To finish off the windows, cut tracing paper to the size of each window and glue it to the inside of the lantern.
-
-![Adding tracing paper][16]
-
- 6. Glue the lantern together at the tabs.
-
- 7. Turn on a battery-powered LED candle and place it inside your lantern.
-
-
-
-
-![Completed lantern][17]
-
-Now your lantern is complete and ready to light up your haunt. Happy Halloween!
-
-How to make Halloween bottle labels with Inkscape, GIMP, and items around the house.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape
-
-作者:[Jess Weichler][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/cyanide-cupcake
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/halloween_bag_bat_diy.jpg?itok=24M0lX25 (Halloween - backlit bat flying)
-[2]: https://opensource.com/article/18/1/inkscape-absolute-beginners
-[3]: http://inkscape.org
-[4]: https://www.dropbox.com/s/75qzjilg5ak2oj1/papercraft_lantern_A4_template.svg?dl=0
-[5]: https://www.dropbox.com/s/8fswdge49jwx91n/papercraft_lantern_letter_template%20.svg?dl=0
-[6]: https://opensource.com/sites/default/files/uploads/lanterntemplate_screen.png (Lantern template screen)
-[7]: https://opensource.com/sites/default/files/uploads/lantern1.png (Object to path menu)
-[8]: https://opensource.com/sites/default/files/uploads/lantern2.png (Object > Difference menu)
-[9]: https://opensource.com/sites/default/files/uploads/lantern3.png (Object to path menu)
-[10]: https://opensource.com/sites/default/files/uploads/lantern4.png (Text tool)
-[11]: https://opensource.com/sites/default/files/uploads/lantern5.png (Text selected with Node editor)
-[12]: https://opensource.com/sites/default/files/uploads/lantern6.png (Overlapping the text)
-[13]: https://opensource.com/sites/default/files/uploads/lantern7.png (Connecting letters and base with Path > Union)
-[14]: https://opensource.com/sites/default/files/uploads/lantern8.png (Setting fill and stroke)
-[15]: https://opensource.com/sites/default/files/uploads/lantern9.jpg (Cutting out the lantern)
-[16]: https://opensource.com/sites/default/files/uploads/lantern10.jpg (Adding tracing paper)
-[17]: https://opensource.com/sites/default/files/uploads/lantern11.jpg (Completed lantern)
diff --git a/sources/tech/20191031 4 Python tools for getting started with astronomy.md b/sources/tech/20191031 4 Python tools for getting started with astronomy.md
deleted file mode 100644
index 79e64651b3..0000000000
--- a/sources/tech/20191031 4 Python tools for getting started with astronomy.md
+++ /dev/null
@@ -1,69 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (4 Python tools for getting started with astronomy)
-[#]: via: (https://opensource.com/article/19/10/python-astronomy-open-data)
-[#]: author: (Gina Helfrich, Ph.D. https://opensource.com/users/ginahelfrich)
-
-4 Python tools for getting started with astronomy
-======
-Explore the universe with NumPy, SciPy, Scikit-Image, and Astropy.
-![Person looking up at the stars][1]
-
-NumFOCUS is a nonprofit charity that supports amazing open source toolkits for scientific computing and data science. As part of the effort to connect Opensource.com readers with the NumFOCUS community, we are republishing some of the most popular articles from [our blog][2]. To learn more about our mission and programs, please visit [numfocus.org][3]. If you're interested in participating in the NumFOCUS community in person, check out a local [PyData event][4] happening near you.
-
-* * *
-
-### Astronomy with Python
-
-Python is a great language for science, and specifically for astronomy. The various packages such as [NumPy][5], [SciPy][6], [Scikit-Image][7] and [Astropy][8] (to name but a few) are all a great testament to the suitability of Python for astronomy, and there are plenty of use cases. [NumPy, Astropy, and SciPy are NumFOCUS fiscally sponsored projects; Scikit-Image is an affiliated project.] Since leaving the field of astronomical research behind more than 10 years ago to start a second career as software developer, I have always been interested in the evolution of these packages. Many of my former colleagues in astronomy used most if not all of these packages for their research work. I have since worked on implementing professional astronomy software packages for instruments for the Very Large Telescope (VLT) in Chile, for example.
-
-It struck me recently that the Python packages have evolved to such an extent that it is now fairly easy for anyone to build [data reduction][9] scripts that can provide high-quality data products. Astronomical data is ubiquitous, and what is more, it is almost all publicly available—you just need to look for it.
-
-For example, ESO, which runs the VLT, offers the data for download on their site. Head over to [www.eso.org/UserPortal][10] and create a user name for their portal. If you look for data from the instrument SPHERE you can download a full dataset for any of the nearby stars that have exoplanet or proto-stellar discs. It is a fantastic and exciting project for any Pythonista to reduce that data and make the planets or discs that are deeply hidden in the noise visible.
-
-I encourage you to download the ESO or any other astronomy imaging dataset and go on that adventure. Here are a few tips:
-
- 1. Start off with a good dataset. Have a look at papers about nearby stars with discs or exoplanets and then search, for example: . Notice that some data on this site is marked as red and some as green. The red data is not publicly available yet — it will say under “release date” when it will be available.
- 2. Read something about the instrument you are using the data from. Try and get a basic understanding of how the data is obtained and what the standard data reduction should look like. All telescopes and instruments have publicly available documents about this.
- 3. You will need to consider the standard problems with astronomical data and correct for them:
- 1. Data comes in FITS files. You will need **pyfits** or **astropy** (which contains pyfits) to read them into **NumPy** arrays. In some cases the data comes in a cube and you should to use **numpy.median **along the z-axis to turn them into 2-D arrays. For some SPHERE data you get two copies of the same piece of sky on the same image (each has a different filter) which you will need to extract using **indexing and slicing.**
- 2. The master dark and bad pixel map. All instruments will have specific images taken as “dark frames” that contain images with the shutter closed (no light at all). Use these to extract a mask of bad pixels using **NumPy masked arrays** for this. This mask of bad pixels will be very important — you need to keep track of it as you process the data to get a clean combined image in the end. In some cases it also helps to subtract this master dark from all scientific raw images.
- 3. Instruments will typically also have a master flat frame. This is an image or series of images taken with a flat uniform light source. You will need to divide all scientific raw images by this (again, using numpy masked array makes this an easy division operation).
- 4. For planet imaging, the fundamental technique to make planets visible against a bright star rely on using a coronagraph and a technique known as angular differential imaging. To that end, you need to identify the optical centre on the images. This is one of the most tricky steps and requires finding some artificial helper images embedded in the images using **skimage.feature.blob_dog**.
- 4. Be patient. It can take a while to understand the data format and how to handle it. Making some plots and histograms of the pixel data can help you to understand it. It is well worth it to be persistent! You will learn a lot about imaging data and processing.
-
-
-
-Using the tools offered by NumPy, SciPy, Astropy, scikit-image and more in combination, with some patience and persistence, it is possible to analyse the vast amount of available astronomical data to produce some stunning results. And who knows, maybe you will be the first one to find a planet that was previously overlooked! Good luck!
-
-_This article was originally published on the NumFOCUS blog and is republished with permission. It is based on [a talk][11] by [Ole Moeller-Nilsson][12], CTO at Pivigo. If you want to support NumFOCUS, you can donate [here][13] or find your local [PyData event][4] happening around the world._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/python-astronomy-open-data
-
-作者:[Gina Helfrich, Ph.D.][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ginahelfrich
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/space_stars_cosmos_person.jpg?itok=XUtz_LyY (Person looking up at the stars)
-[2]: https://numfocus.org/blog
-[3]: https://numfocus.org
-[4]: https://pydata.org/
-[5]: http://numpy.scipy.org/
-[6]: http://www.scipy.org/
-[7]: http://scikit-image.org/
-[8]: http://www.astropy.org/
-[9]: https://en.wikipedia.org/wiki/Data_reduction
-[10]: http://www.eso.org/UserPortal
-[11]: https://www.slideshare.net/OleMoellerNilsson/pydata-lonon-finding-planets-with-python
-[12]: https://twitter.com/olly_mn
-[13]: https://numfocus.org/donate
diff --git a/sources/tech/20191031 Advance your awk skills with two easy tutorials.md b/sources/tech/20191031 Advance your awk skills with two easy tutorials.md
deleted file mode 100644
index 76f7a54e5f..0000000000
--- a/sources/tech/20191031 Advance your awk skills with two easy tutorials.md
+++ /dev/null
@@ -1,287 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (nacyro)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Advance your awk skills with two easy tutorials)
-[#]: via: (https://opensource.com/article/19/10/advanced-awk)
-[#]: author: (Dave Neary https://opensource.com/users/dneary)
-
-Advance your awk skills with two easy tutorials
-======
-Go beyond one-line awk scripts with mail merge and word counting.
-![a checklist for a team][1]
-
-Awk is one of the oldest tools in the Unix and Linux user's toolbox. Created in the 1970s by Alfred Aho, Peter Weinberger, and Brian Kernighan (the A, W, and K of the tool's name), awk was created for complex processing of text streams. It is a companion tool to sed, the stream editor, which is designed for line-by-line processing of text files. Awk allows more complex structured programs and is a complete programming language.
-
-This article will explain how to use awk for more structured and complex tasks, including a simple mail merge application.
-
-### Awk program structure
-
-An awk script is made up of functional blocks surrounded by **{}** (curly brackets). There are two special function blocks, **BEGIN** and **END**, that execute before processing the first line of the input stream and after the last line is processed. In between, blocks have the format:
-
-
-```
-`pattern { action statements }`
-```
-
-Each block executes when the line in the input buffer matches the pattern. If no pattern is included, the function block executes on every line of the input stream.
-
-Also, the following syntax can be used to define functions in awk that can be called from any block:
-
-
-```
-`function name(parameter list) { statements }`
-```
-
-This combination of pattern-matching blocks and functions allows the developer to structure awk programs for reuse and readability.
-
-### How awk processes text streams
-
-Awk reads text from its input file or stream one line at a time and uses a field separator to parse it into a number of fields. In awk terminology, the current buffer is a _record_. There are a number of special variables that affect how awk reads and processes a file:
-
- * **FS** (field separator): By default, this is any whitespace (spaces or tabs)
- * **RS** (record separator): By default, a newline (**\n**)
- * **NF** (number of fields): When awk parses a line, this variable is set to the number of fields that have been parsed
- * **$0:** The current record
- * **$1, $2, $3, etc.:** The first, second, third, etc. field from the current record
- * **NR** (number of records): The number of records that have been parsed so far by the awk script
-
-
-
-There are many other variables that affect awk's behavior, but this is enough to start with.
-
-### Awk one-liners
-
-For a tool so powerful, it's interesting that most of awk's usage is basic one-liners. Perhaps the most common awk program prints selected fields from an input line from a CSV file, a log file, etc. For example, the following one-liner prints a list of usernames from **/etc/passwd**:
-
-
-```
-`awk -F":" '{print $1 }' /etc/passwd`
-```
-
-As mentioned above, **$1** is the first field in the current record. The **-F** option sets the FS variable to the character **:**.
-
-The field separator can also be set in a BEGIN function block:
-
-
-```
-`awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd`
-```
-
-In the following example, every user whose shell is not **/sbin/nologin** can be printed by preceding the block with a pattern match:
-
-
-```
-`awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd`
-```
-
-### Advanced awk: Mail merge
-
-Now that you have some of the basics, try delving deeper into awk with a more structured example: creating a mail merge.
-
-A mail merge uses two files, one (called in this example **email_template.txt**) containing a template for an email you want to send:
-
-
-```
-From: Program committee <[pc@event.org][2]>
-To: {firstname} {lastname} <{email}>
-Subject: Your presentation proposal
-
-Dear {firstname},
-
-Thank you for your presentation proposal:
- {title}
-
-We are pleased to inform you that your proposal has been successful! We
-will contact you shortly with further information about the event
-schedule.
-
-Thank you,
-The Program Committee
-```
-
-And the other is a CSV file (called **proposals.csv**) with the people you want to send the email to:
-
-
-```
-firstname,lastname,email,title
-Harry,Potter,[hpotter@hogwarts.edu][3],"Defeating your nemesis in 3 easy steps"
-Jack,Reacher,[reacher@covert.mil][4],"Hand-to-hand combat for beginners"
-Mickey,Mouse,[mmouse@disney.com][5],"Surviving public speaking with a squeaky voice"
-Santa,Claus,[sclaus@northpole.org][6],"Efficient list-making"
-```
-
-You want to read the CSV file, replace the relevant fields in the first file (skipping the first line), then write the result to a file called **acceptanceN.txt**, incrementing **N** for each line you parse.
-
-Write the awk program in a file called **mail_merge.awk**. Statements are separated by **;** in awk scripts. The first task is to set the field separator variable and a couple of other variables the script needs. You also need to read and discard the first line in the CSV, or a file will be created starting with _Dear firstname_. To do this, use the special function **getline** and reset the record counter to 0 after reading it.
-
-
-```
-BEGIN {
- FS=",";
- template="email_template.txt";
- output="acceptance";
- getline;
- NR=0;
-}
-```
-
-The main function is very straightforward: for each line processed, a variable is set for the various fields—**firstname**, **lastname**, **email**, and **title**. The template file is read line by line, and the function **sub** is used to substitute any occurrence of the special character sequences with the value of the relevant variable. Then the line, with any substitutions made, is output to the output file.
-
-Since you are dealing with the template file and a different output file for each line, you need to clean up and close the file handles for these files before processing the next record.
-
-
-```
-{
- # Read relevant fields from input file
- firstname=$1;
- lastname=$2;
- email=$3;
- title=$4;
-
- # Set output filename
- outfile=(output NR ".txt");
-
- # Read a line from template, replace special fields, and
- # print result to output file
- while ( (getline ln < template) > 0 )
- {
- sub(/{firstname}/,firstname,ln);
- sub(/{lastname}/,lastname,ln);
- sub(/{email}/,email,ln);
- sub(/{title}/,title,ln);
- print(ln) > outfile;
- }
-
- # Close template and output file in advance of next record
- close(outfile);
- close(template);
-}
-```
-
-You're done! Run the script on the command line with:
-
-
-```
-`awk -f mail_merge.awk proposals.csv`
-```
-
-or
-
-
-```
-`awk -f mail_merge.awk < proposals.csv`
-```
-
-and you will find text files generated in the current directory.
-
-### Advanced awk: Word frequency count
-
-One of the most powerful features in awk is the associative array. In most programming languages, array entries are typically indexed by a number, but in awk, arrays are referenced by a key string. You could store an entry from the file _proposals.txt_ from the previous section. For example, in a single associative array, like this:
-
-
-```
- proposer["firstname"]=$1;
- proposer["lastname"]=$2;
- proposer["email"]=$3;
- proposer["title"]=$4;
-```
-
-This makes text processing very easy. A simple program that uses this concept is the idea of a word frequency counter. You can parse a file, break out words (ignoring punctuation) in each line, increment the counter for each word in the line, then output the top 20 words that occur in the text.
-
-First, in a file called **wordcount.awk**, set the field separator to a regular expression that includes whitespace and punctuation:
-
-
-```
-BEGIN {
- # ignore 1 or more consecutive occurrences of the characters
- # in the character group below
- FS="[ .,:;()<>{}@!\"'\t]+";
-}
-```
-
-Next, the main loop function will iterate over each field, ignoring any empty fields (which happens if there is punctuation at the end of a line), and increment the word count for the words in the line.
-
-
-```
-{
- for (i = 1; i <= NF; i++) {
- if ($i != "") {
- words[$i]++;
- }
- }
-}
-```
-
-Finally, after the text is processed, use the END function to print the contents of the array, then use awk's capability of piping output into a shell command to do a numerical sort and print the 20 most frequently occurring words:
-
-
-```
-END {
- sort_head = "sort -k2 -nr | head -n 20";
- for (word in words) {
- printf "%s\t%d\n", word, words[word] | sort_head;
- }
- close (sort_head);
-}
-```
-
-Running this script on an earlier draft of this article produced this output:
-
-
-```
-[[dneary@dhcp-49-32.bos.redhat.com][7]]$ awk -f wordcount.awk < awk_article.txt
-the 79
-awk 41
-a 39
-and 33
-of 32
-in 27
-to 26
-is 25
-line 23
-for 23
-will 22
-file 21
-we 16
-We 15
-with 12
-which 12
-by 12
-this 11
-output 11
-function 11
-```
-
-### What's next?
-
-If you want to learn more about awk programming, I strongly recommend the book [_Sed and awk_][8] by Dale Dougherty and Arnold Robbins.
-
-One of the keys to progressing in awk programming is mastering "extended regular expressions." Awk offers several powerful additions to the sed [regular expression][9] syntax you may already be familiar with.
-
-Another great resource for learning awk is the [GNU awk user guide][10]. It has a full reference for awk's built-in function library, as well as lots of examples of simple and complex awk scripts.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/advanced-awk
-
-作者:[Dave Neary][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/dneary
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/checklist_hands_team_collaboration.png?itok=u82QepPk (a checklist for a team)
-[2]: mailto:pc@event.org
-[3]: mailto:hpotter@hogwarts.edu
-[4]: mailto:reacher@covert.mil
-[5]: mailto:mmouse@disney.com
-[6]: mailto:sclaus@northpole.org
-[7]: mailto:dneary@dhcp-49-32.bos.redhat.com
-[8]: https://www.amazon.com/sed-awk-Dale-Dougherty/dp/1565922255/book
-[9]: https://en.wikibooks.org/wiki/Regular_Expressions/POSIX-Extended_Regular_Expressions
-[10]: https://www.gnu.org/software/gawk/manual/gawk.html
diff --git a/sources/tech/20191111 A guide to intermediate awk scripting.md b/sources/tech/20191111 A guide to intermediate awk scripting.md
index 7e788b2adc..53e7126eb1 100644
--- a/sources/tech/20191111 A guide to intermediate awk scripting.md
+++ b/sources/tech/20191111 A guide to intermediate awk scripting.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: (lnrCoder)
+[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
diff --git a/sources/tech/20191118 Creating a Chat Bot with Recast.AI.md b/sources/tech/20191118 Creating a Chat Bot with Recast.AI.md
deleted file mode 100644
index 0b86e74c72..0000000000
--- a/sources/tech/20191118 Creating a Chat Bot with Recast.AI.md
+++ /dev/null
@@ -1,181 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Creating a Chat Bot with Recast.AI)
-[#]: via: (https://opensourceforu.com/2019/11/creating-a-chat-bot-with-recast-ai/)
-[#]: author: (Athira Lekshmi C.V https://opensourceforu.com/author/athira-lekshmi/)
-
-Creating a Chat Bot with Recast.AI
-======
-
-[![][1]][2]
-
-_According to a Gartner report from February 2018, “25 per cent of customer service and support operations will integrate virtual customer assistant (VCA) or chatbot technology across engagement channels by 2020, up from less than 2 per cent in 2017.” In the light of this, readers will find this tutorial on how the open source Recast. AI bot-creating platform works, helpful._
-
-Chat bots, both voice based and others, have been in use for quite a while now. From chatbots that engage the user in a murder mystery game to bots which help in real estate deals and medical diagnosis, chatbots have traversed across domains.
-
-There are many platforms which enable users to create and deploy bots. Recast.AI (now known as SAP Conversational AI after its acquisition by SAP) is a forerunner amongst these.
-
-The cool interface, its collaborative nature and the analytics tools it provides, make it a popular choice.
-As the Recast official site says, “It is an ultimate collaborative platform to build, train, deploy and monitor intelligent bots.”
-
-![Figure 1: Setting the bot properties][3]
-
-![Figure 2: Bot dashboard][4]
-
-![Figure 3: Searching an intent][5]
-
-**Building a basic bot in Recast**
-Let us look at how to build a basic bot in Recast.
-
- 1. Create an account in __. Signing up can be done either with an email ID or with a GitHub account.
- 2. Once you log in, you will land on the dashboard. Click on the + New Bot icon on the top right-hand side to create a new bot.
- 3. On the next screen, you will see that there is a set of predefined skills you can select. Select Greetings for the time being (Figure 1). This bot is already trained to understand basic greetings.
- 4. Provide a name for your bot. For now, since this is a very basic bot, you can have the bot crack some jokes, so let us name it Joke Bot and select the default language as English.
- 5. Select Non-personal data under the data policy since you won’t be dealing with any sensitive information; then select the Public bot option and click on Create a bot.
-
-
-
-So that’s your bot created on the Recast platform.
-
-![Figure 4: @joke intent][6]
-
-![Figure 5: Predefined expressions][7]
-
-**The five stages of developing a bot**
-To use the words from the official Recast blog, there are five stages in a bot’s life.
-
- * Training – Teaching your bot what it needs to understand
- * Building – Creating your conversational flow with the Bot Builder tool
- * Coding – Connecting your bot with external APIs or a database
- * Connecting – Shipping your bot to one or several messaging platforms
- * Monitoring – Training your bot to make it sharper and get insights on its usage
-
-
-
-**Training a bot through intents**
-You will be able to see the options to either search, fork or create an intent in the dashboard.
-“An intent is a box of expressions that mean the same thing but which are constructed in different ways. Intents are the heart of your bot’s understanding. Each one of your intents represents an idea your bot is able to understand.” (from the _Recast.AI_ website)
-As decided earlier, you need the bot to be able to crack jokes. So the base line is that the bot should be able to understand that the user is asking it to tell a joke; it shouldn’t be that even when the user just says, “Hi,” the bot responds with a joke – that would not be good.
-So group the utterances that the user might make, like:
-
-```
-Tell me a joke.
-Tell me a funny fact.
-Can you crack a joke?
-What’s funny today?
-```
-
-…………………
-
-Before going on to create the intent from scratch, let us explore the Search/fork option. Type _Joke_ in the search field (Figure 3). This gives a list of intents created by users of Recast around the globe, which is public, and this is why Recast is said to be collaborative in nature. So there’s no need to create all intents from scratch, one can build upon intents already created. This brings down the effort needed to train the bot with common intents.
-
- * Select the first intent in the list and fork it into the bot.
- * Click on the Fork button. The intent is now added to the bot (Figure 4).
- * Click on the intent @joke, and a list of expressions which already exist in the intent will be displayed (Figure 5).
- * Add a few more expressions to it (Figure 6).
-
-
-
-![Figure 6: Suggested expressions][8]
-
-![Figure 7: Suggested expressions][9]
-
-Once a few expressions are added, the bot gives suggestions like shown in Figure 7. Select a few and add them to the intent (Figure 7).
-You can also tag your own custom entities to detect keywords, depending on your bot’s context.
-
-**Skills**
-A skill is a block of conversation that has a clear purpose and that your bot can execute to achieve a goal. It can be as simple as the ability to greet someone, but it can also be more complex, like giving movie suggestions based on information provided by the user.
-
-It need not be just a one query-answer set, but rather, skills running through multiple exchanges. For example, consider a bot which helps you learn about currency exchange rates. It starts by asking the source currency, then the target currency, before giving the exact response. Skills can be combined to create complex conversational flows.
-Here’s how you create a skill for the joke bot:
-
- * Go to the _Build_ tab. Click on the + icon to create a skill.
- * Name the skill _Joke_ (Figure 8)
- * Once created, click on the skill. You will see four tabs. _Read me, Triggers, Requirements and Actions_.
- * Navigate to the Requirements tab. You should store the information only if the intent joke is present. So, add a requirement as shown in Figure 9.
-
-
-
-![Figure 8: Skills dashboard][10]
-
-![Figure 9: Adding a trigger][11]
-
-Since this is a simple use case, you needn’t consider any specific requirements in the Requirement tab but consider a case for which a response needs to be triggered only if certain keywords or entities are present – in such a case you will need ‘requirements’.
-
-Requirements are either intents or entities that your skill needs to retrieve before executing actions. Requirements are pieces of information that are important in the conversation and that your bot can use; for example, the user’s name or a location. Once a requirement is completed, the associated value is stored in the bot’s memory for the entire conversation.
-
-Now let us move to the Action tab to set the responses (see Figure 10).
-Click on Add _new message group_. Then select _Send message_ and add a text message, which can be any joke in this case. Also, since you don’t want your bot to crack the same joke each time, you can add multiple messages which will be randomly picked each time.
-
-![Figure 10: Adding actions][12]
-
-![Figure 11: Adding text messages][13]
-
-![Figure 12: Setting up webchat][14]
-
-**Channel integrations**
-Well, the success of a bot also depends upon how easily it is accessible. Recast has built-in integrations with many messaging channels such as Skype for Business, Kik Messenger, Telegram, Line, Facebook Messenger, Slack, Alexa, etc. In addition to that, Recast also provides SDKs to develop custom channels.
-
-Also, there is a ready-to-use Web chat provided by Recast (in the Connect tab). You can customise the colour schemes, headers, bot pictures, etc. It provides you with a script tag to be injected into the page. Your interface is now up (Figure 12).
-
-The Web chat code base is open sourced, which makes it easier for developers to play around with the look and feel, the standard response types and much more.
-The dashboard provides step-by-step procedures on how to deploy the bot on various channels. The joke bot was deployed in Telegram and in Web chat, as shown in Figure 13.
-
-![Figure 13: Webchat deployed][15]
-
-![Figure 14: Bot deployed in Telegram][16]
-
-![Figure 15: Multi-language bot][17]
-
-**And there is more**
-Recast supports multiple languages, Select one language as the base while creating the bot, but then you also have the option to add as many languages as you want.
-
-The example considered here is a simple static joke bot, but actual use cases will need interaction with various systems. Recast has a Web hook feature which allows users to connect with various systems to get responses. Also, there is detailed API documentation to help leverage each independent feature of the platform.
-
-As for analytics, Recast has a monitoring dashboard which helps you understand the accuracy of the bot and train it further.
-
-![Avatar][18]
-
-[Athira Lekshmi C.V][19]
-
-The author is an open-source enthusiast.
-
-[![][20]][21]
-
---------------------------------------------------------------------------------
-
-via: https://opensourceforu.com/2019/11/creating-a-chat-bot-with-recast-ai/
-
-作者:[Athira Lekshmi C.V][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensourceforu.com/author/athira-lekshmi/
-[b]: https://github.com/lujun9972
-[1]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/04/Build-ChatBoat.jpg?resize=696%2C442&ssl=1 (Build ChatBoat)
-[2]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/04/Build-ChatBoat.jpg?fit=900%2C572&ssl=1
-[3]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-1-Setting-the-bot-properties.jpg?resize=350%2C201&ssl=1
-[4]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-2-Setting-the-bot-properties.jpg?resize=350%2C217&ssl=1
-[5]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-3-Searching-an-intent.jpg?resize=350%2C271&ssl=1
-[6]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-4-@joke-intent.jpg?resize=350%2C214&ssl=1
-[7]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-5-Predefined-expressions-350x227.jpg?resize=350%2C227&ssl=1
-[8]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-6-Suggested-expressions-350x197.jpg?resize=350%2C197&ssl=1
-[9]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-7-Suggested-expressions-350x248.jpg?resize=350%2C248&ssl=1
-[10]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-8-Skills-dashboard.jpg?resize=350%2C187&ssl=1
-[11]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-9-Adding-a-trigger.jpg?resize=350%2C197&ssl=1
-[12]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-10-Adding-actions.jpg?resize=350%2C175&ssl=1
-[13]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-11-Adding-text-messages.jpg?resize=350%2C255&ssl=1
-[14]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-12-Setting-up-webchat.jpg?resize=350%2C326&ssl=1
-[15]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-13-Webchat-deployed.jpg?resize=350%2C425&ssl=1
-[16]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-14-Bot-deployed-in-Telegram.jpg?resize=350%2C269&ssl=1
-[17]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Figure-15-Multi-language-bot.jpg?resize=350%2C419&ssl=1
-[18]: https://secure.gravatar.com/avatar/d24503a2a0bb8bd9eefe502587d67323?s=100&r=g
-[19]: https://opensourceforu.com/author/athira-lekshmi/
-[20]: https://opensourceforu.com/wp-content/uploads/2019/11/assoc.png
-[21]: https://feedburner.google.com/fb/a/mailverify?uri=LinuxForYou&loc=en_US
diff --git a/sources/tech/20191118 How to use regular expressions in awk.md b/sources/tech/20191118 How to use regular expressions in awk.md
index a0be0df4d7..2cf5881263 100644
--- a/sources/tech/20191118 How to use regular expressions in awk.md
+++ b/sources/tech/20191118 How to use regular expressions in awk.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: (lixin555)
+[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
diff --git a/sources/tech/20191125 My top 5 Ansible modules.md b/sources/tech/20191125 My top 5 Ansible modules.md
deleted file mode 100644
index 9a76342854..0000000000
--- a/sources/tech/20191125 My top 5 Ansible modules.md
+++ /dev/null
@@ -1,74 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (My top 5 Ansible modules)
-[#]: via: (https://opensource.com/article/19/11/ansible-modules)
-[#]: author: (Mark Phillips https://opensource.com/users/markp)
-
-My top 5 Ansible modules
-======
-Learn how to achieve almost anything with these Ansible modules.
-![][1]
-
-When I was growing up, my grandfather had a shed in his garden. He would spend hours in there, making and fixing things. This was way before we had the internet, so I spent a lot of time studying him creating things in that shed. Although the shed was full of many tools, from drills to lathes to electrical gubbins and lots of things I doubt I could identify even today, he made use of only a tiny subset of what he had at hand. Yet there never seemed to be limits to what he could achieve.
-
-I tell you that story because I feel like my career has been spent in a metaphorical shed. Computers are so many tools, all in a small (virtual?) space. And there are tool sheds within tool sheds—my favourite being Ansible. The recent 2.9 release ships with 3,681 modules! **3,681!** When I first started using Ansible in the summer of 2013, version 1.2.1 had just 113 modules, yet, as [I wrote at the time][2], I could still achieve anything I imagined.
-
-Modules are the backbone of Ansible, the gears to make light of heavy lifting. They're designed to do one job well, thus realising [the Unix philosophy][3]. This is how we've come to bundle so many of them; Ansible as the conductor of the orchestra now has a lot of instruments at its command.
-
-Reviewing a Git repository of my Ansible plays and roles over the years reveals that I have used just 35 modules. This small subset was used to build large infrastructures. I wonder what could be achieved with an even smaller subset, though? As I reviewed those 35, I pondered if I could achieve the same results with only five modules at my disposal. So here are my five favourite modules, in a rather tenuous order of precedence.
-
-### 5. [authorized_key][4]
-
-Secure shell (SSH) is at the heart of Ansible, at least for almost everything besides Windows. Key (no pun intended) to using SSH efficiently with Ansible is… [keys][5]! Slight aside—there are a lot of very cool things you can do for security with SSH keys. It's worth perusing the **authorized_keys** section of the [sshd manual page][6]. Managing SSH keys can become laborious if you're getting into the realms of granular user access, and although we could do it with either of my next two favourites, I prefer to use the module because it [enables easy management through variables][7].
-
-### 4. [file][8]
-
-Besides the obvious function of placing a file somewhere, the **file** module also sets ownership and permissions. I'd say that's a lot of _bang for your buck_ with one module. I'd proffer a substantial portion of security relates to setting permissions too, so the **file** module plays nicely with **authorized_keys**.
-
-### 3. [template][9]
-
-There are so many ways to manipulate the contents of files, and I see lots of folk use **[lineinfile][10]**. I've used it myself for small tasks. However, the **template** module is so much clearer because you maintain the entire file for context. My preference is to write Ansible content in such a way that anyone can understand it _easily_—which to me means not making it hard to understand what is happening. Use of **template** means being able to see the entire file you're putting into place, complete with the variables you are using to change pieces.
-
-### 2. [uri][11]
-
-Many modules in the current distribution leverage Ansible as an orchestrator. They talk to another service, rather than doing something specific like putting a file into place. Usually, that talking is over HTTP too. In the days before many of these modules existed, you _could_ program an API directly using the **uri** module. It's a powerful access tool, enabling you to do a lot. I wouldn't be without it in my fictitious Ansible shed.
-
-### 1. [shell][12]
-
-The joker card in our pack. The Swiss Army Knife. If you're absolutely stuck for how to control something else, use **shell**. Some will argue we're now talking about making Ansible a Bash script—but, I would say it's still better because with the use of the **name** parameter in your plays and roles, you document every step. To me, that's as big a bonus as anything. Back in the days when I was still consulting, I once helped a database administrator (DBA) migrate to Ansible. The DBA wasn't one for change and pushed back at changing working methods. So, to ease into the Ansible way, we called some existing DB management scripts from Ansible using the **shell** module. With an informative **name** statement to accompany the task.
-
-You can achieve a lot with these five modules. Yes, modules designed to do a specific task will make your life even easier. But with a smidgen of engineering simplicity, you can achieve a lot with very little. Ansible developer Brian Coca is a master at it, and [his tips and tricks talk][13] is always worth a watch.
-
-* * *
-
-What do you think about my top five? What five modules would you pick and why, if you were so limited? Let me know in the comments below!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/11/ansible-modules
-
-作者:[Mark Phillips][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/markp
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/mandelbrot_set.png?itok=bmPc0np5
-[2]: http://probably.co.uk/post/puppet-vs-chef-vs-ansible/
-[3]: https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well
-[4]: https://docs.ansible.com/ansible/latest/modules/authorized_key_module.html
-[5]: https://linux.die.net/man/1/ssh-keygen
-[6]: https://linux.die.net/man/8/sshd
-[7]: https://github.com/phips/ansible-demos/blob/3bf59df1eb2390b31b5c42333197e2fbb7fec93f/roles/ansible-users/tasks/main.yml#L35
-[8]: https://docs.ansible.com/ansible/latest/modules/file_module.html
-[9]: https://docs.ansible.com/ansible/latest/modules/template_module.html
-[10]: https://docs.ansible.com/ansible/latest/modules/lineinfile_module.html
-[11]: https://docs.ansible.com/ansible/latest/modules/uri_module.html
-[12]: https://docs.ansible.com/ansible/latest/modules/shell_module.html
-[13]: https://www.ansible.com/ansible-tips-and-tricks
diff --git a/sources/tech/20191126 Calculator N- is an open source scientific calculator for your smartphone.md b/sources/tech/20191126 Calculator N- is an open source scientific calculator for your smartphone.md
deleted file mode 100644
index 32d467465a..0000000000
--- a/sources/tech/20191126 Calculator N- is an open source scientific calculator for your smartphone.md
+++ /dev/null
@@ -1,61 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Calculator N+ is an open source scientific calculator for your smartphone)
-[#]: via: (https://opensource.com/article/19/11/calculator-n-mobile)
-[#]: author: (Ricardo Berlasso https://opensource.com/users/rgb-es)
-
-Calculator N+ is an open source scientific calculator for your smartphone
-======
-The Android app does a wide range of advanced mathematical functions in
-the palm of your hand.
-![scientific calculator][1]
-
-Mobile phones are becoming more powerful every day, so it is no surprise that they can beat most computers from the not-so-distant past. This also means the tools available on them are getting more powerful every day.
-
-Previously, I wrote about [scientific calculators for the Linux desktop][2], and I'm following that up here with information about [Calculator N+][3], an awesome GPL v3.0-licensed computer algebra system (CAS) app for Android devices.
-
-Calculator N+ is presented as a "powerful calculator for Android," but that's a humble statement; the app not only works with arbitrary precision, displaying results with roots and fractions in all their glory, it does a _lot_ more.
-
-Finding polynomial roots? Check. Factorization? Check. Symbolic derivatives, integrals, and limits? Check. Number theory (modular arithmetic, combinatorics, prime factorization)? Check.
-
-You can also solve systems of equations, simplify expressions (including trigonometric ones), convert units… you name it!
-
-![Calculator N+ graphical interface][4]
-
-Results are output in LaTeX. The menu in the top-left provides many powerful functions ready to use with a simple touch. Also in that menu, you'll find Help files for all of the app's functions. At the top-right of the screen, you can toggle between exact and decimal representation. Finally, tapping the blue bar at the bottom of the screen gives you access to the whole library of functions available in the app. But be careful! If you are not a mathematician, physicist, or engineer, such a long list may seem overwhelming.
-
-All of this power comes from the [Symja library][5], another great GPL 3 project.
-
-Both projects are under active development, and they are getting better with each version. In particular, version 3.4.6 of Calculator N+ gets a major leap in user interface (UI) quality. And yes, there are still some rough corners here and there, but taming this much power in the tiny UI of a smartphone is a difficult task, and I think the app developers are solving its remaining issues quite well. Kudos to them!
-
-If you are a teacher, a student, or work on a STEM field, check out Calculator N+. It's free, no ads, open source, and covers all your math needs. (Except, of course, during math exams, where smartphones should never be allowed to prevent cheating.)
-
-Calculator N+ is available in the [Google Play Store][6], or you can [build it from source code][7] using the instructions on the GitHub page.
-
-If you know any other useful open source apps for science or engineering, let us know in the comments.
-
-The app makes use of the sensors on your phone and offers a digital science notebook to record your...
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/11/calculator-n-mobile
-
-作者:[Ricardo Berlasso][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/rgb-es
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calculator_money_currency_financial_tool.jpg?itok=2QMa1y8c (scientific calculator)
-[2]: https://opensource.com/article/18/1/scientific-calculators-linux
-[3]: https://github.com/tranleduy2000/ncalc
-[4]: https://opensource.com/sites/default/files/uploads/calculatornplus_sqrt-frac.png (Calculator N+ graphical interface)
-[5]: https://github.com/axkr/symja_android_library
-[6]: https://play.google.com/store/apps/details?id=com.duy.calculator.free
-[7]: https://github.com/tranleduy2000/ncalc/blob/master/README.md
diff --git a/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md b/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md
deleted file mode 100644
index 8c7ddcb1e5..0000000000
--- a/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md
+++ /dev/null
@@ -1,164 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Use the Fluxbox Linux desktop as your window manager)
-[#]: via: (https://opensource.com/article/19/12/fluxbox-linux-desktop)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Use the Fluxbox Linux desktop as your window manager
-======
-This article is part of a special series of 24 days of Linux desktops.
-Fluxbox is very light on system resources, yet it has vital Linux
-desktop features to make your user experience easy, blazingly efficient,
-and unduly fast.
-![Text editor on a browser, in blue][1]
-
-The concept of a desktop may differ from one computer user to another. Many people see the desktop as a home base, or a comfy living room, or even a literal desktop where they place frequently used notepads, their best pens and pencils, and their favorite coffee mug. KDE, GNOME, Pantheon (and so on) provide that kind of comfort on Linux.
-
-But for some users, the desktop is just empty monitor space, a side effect of not yet having any free-floating application windows projected directly onto their retina. For these users, the desktop is a void over which they can run applications—whether big office and graphic suites, or a simple terminal window, or docked applets—to manage services. This model of operating a [POSIX][2] computer has a long history, and one branch of that family tree is the *box window managers: Blackbox, Fluxbox, and Openbox.
-
-[Fluxbox][3] is a window manager for X11 systems that's based on an older project called Blackbox. Blackbox development was waning when I discovered Linux, so I fell into Fluxbox, and I've used it ever since on at least one of my active systems. It is written in C++ and is licensed under the MIT open source license.
-
-### Installing Fluxbox
-
-You are likely to find Fluxbox included in the software repository of your Linux distribution, but you can also find it on [Fluxbox.org][4]. If you're already running a different desktop, it's safe to install Fluxbox on the same system because Fluxbox doesn't predetermine any configuration or accompanying applications.
-
-After installing Fluxbox, log out of your current desktop session so you can log into your new one. By default, your session manager (KDM, GDM, LightDM, or XDM, depending on your setup) will continue to log you into your previous desktop, so you must override that before logging in.
-
-To override the desktop with GDM:
-
-![Select your desktop session in GDM][5]
-
-Or with KDM:
-
-![Select your desktop session with KDM][6]
-
-### Configuring the Fluxbox desktop
-
-When you first log in, the screen is mostly empty because all Fluxbox provides are panels (for a taskbar, system tray, and so on) and window decoration for application windows.
-
-![Default Fluxbox configuration on CentOS 7][7]
-
-If your distribution delivers a plain Fluxbox desktop, you can set a background for your desktop using the **feh** command (you may need to install it from your distribution's repository). This command has a few options for setting the background, including **\--bg-fill** to fill the screen with your wallpaper of choice, **\--bg-scale** to scale it to fit, and so on.
-
-
-```
-`$ feh --bg-fill ~/photo/oamaru/leaf-spiral.jpg`
-```
-
-![Fluxbox with a theme applied][8]
-
-By default, Fluxbox auto-generates a menu, available with a right-click anywhere on the desktop, that gives you access to applications. Depending on your distribution, this menu may be very minimal, or it may list all the launchers in your **/usr/share/applications** directory.
-
-Fluxbox configuration is set in text files, and those text files are contained in the **$HOME/.fluxbox** directory. You can:
-
- * Set keyboard shortcuts in **keys**
- * Set startup services and applications in **startup**
- * Set desktop preferences (such as the number of workspaces, locations of panels, and so on) in **init**
- * Set menu items in **menu**
-
-
-
-The text configuration files are easy to reverse-engineer, but you also can (and should) read the Fluxbox [documentation][9].
-
-For example, this is my typical menu (or at least the basic structure of it):
-
-
-```
-# to use your own menu, copy this to ~/.fluxbox/menu, then edit
-# ~/.fluxbox/init and change the session.menuFile path to ~/.fluxbox/menu
-
-[begin] (fluxkbox)
- [submenu] (apps) {}
- [submenu] (txt) {}
- [exec] (Emacs 23 (text\\)) { x-terminal-emulator -T "Emacs (text)" -e /usr/bin/emacs -nw} <>
- [exec] (Emacs (X11\\)) {/usr/bin/emacs} <>
- [exec] (LibreOffice) {/usr/bin/libreoffice}
- [end]
- [submenu] (code) {}
- [exec] (qtCreator) {/usr/bin/qtcreator}
- [exec] (eclipse) {/usr/bin/eclipse}
- [end]
- [submenu] (graphics) {}
- [exec] (ksnapshot) {/usr/bin/ksnapshot}
- [exec] (gimp) {/usr/bin/gimp}
- [exec] (blender) {/usr/bin/blender}
- [end]
- [submenu] (files) {}
- [exec] (dolphin) {/usr/bin/dolphin}
- [exec] (konqueror) { /usr/bin/kfmclient openURL $HOME }
- [end]
- [submenu] (network) {}
- [exec] (firefox) {/usr/bin/firefox}
- [exec] (konqueror) {/usr/bin/konqueror}
- [end]
- [end]
-## change window manager or work env
-[submenu] (environments) {}
- [restart] (flux) {/usr/bin/startfluxbox}
- [restart] (ratpoison) {/usr/bin/ratpoison}
- [exec] (openIndiana) {/home/kenlon/qemu/startSolaris.sh}
-[end]
-
-[config] (config)
- [submenu] (styles) {}
- [stylesdir] (/usr/share/fluxbox/styles)
- [stylesdir] (~/.fluxbox/styles)
- [end]
-[workspaces] (workspaces)
-[reconfig] (reconfigure)
-[restart] (restart)
-[exit] (exeunt)
-[end]
-```
-
-The menu also provides a few preference settings, such as the ability to pick a theme and restart or log out from your Fluxbox session.
-
-I launch most applications using keyboard shortcuts, which are entered into the **keys** configuration file. Here are some examples (the **Mod4** key is the Super key, which I use to designate global shortcuts):
-
-
-```
-# open apps
-Mod4 t :Exec konsole
-Mod4 k :Exec konqueror
-Mod4 z :Exec fbrun
-Mod4 e :Exec emacs
-Mod4 f :Exec firefox
-Mod4 x :Exec urxvt
-Mod4 d :Exec dolphin
-Mod4 q :Exec xscreensaver-command -activate
-Mod4 3 :Exec ksnapshot
-```
-
-Between these shortcuts and an open terminal, I have little use for a mouse during most of my workday, so there's no wasted time switching from one controller to another. And because Fluxbox stays well out of the way, there's little distraction.
-
-### Why you should use Fluxbox
-
-Fluxbox is very light on system resources, yet it has vital features to make your user experience easy, blazingly efficient, and unduly fast. It's simple to customize, and it allows you to define your own workflow. You don't have to use Fluxbox's panels, because there are other excellent panels out there. You can even middle-click and drag two separate application windows into one another so that they become one window, each in its own tab.
-
-The possibilities are endless, so try the steady simplicity that is Fluxbox on your Linux box today!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/fluxbox-linux-desktop
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
-[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
-[3]: http://fluxbox.org
-[4]: http://fluxbox.org/download/
-[5]: https://opensource.com/sites/default/files/advent-gdm_0.jpg (Select your desktop session in GDM)
-[6]: https://opensource.com/sites/default/files/advent-kdm.jpg (Select your desktop session with KDM)
-[7]: https://opensource.com/sites/default/files/advent-fluxbox-default.jpg (Default Fluxbox configuration on CentOS 7)
-[8]: https://opensource.com/sites/default/files/advent-fluxbox-green.jpg (Fluxbox with a theme applied)
-[9]: http://fluxbox.org/features/
diff --git a/sources/tech/20191216 Relive Linux history with the ROX desktop.md b/sources/tech/20191216 Relive Linux history with the ROX desktop.md
deleted file mode 100644
index 215006514f..0000000000
--- a/sources/tech/20191216 Relive Linux history with the ROX desktop.md
+++ /dev/null
@@ -1,104 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Relive Linux history with the ROX desktop)
-[#]: via: (https://opensource.com/article/19/12/linux-rox-desktop)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Relive Linux history with the ROX desktop
-======
-This article is part of a special series of 24 days of Linux desktops.
-If you're looking for a fun trip back in time, the ROX desktop is well
-worth a go.
-![Person typing on a 1980's computer][1]
-
-The [ROX][2] desktop is no longer being actively developed, but its legacy resounds today, and even when it was active, it was a unique take on what a Linux desktop could be. While other desktops felt roughly similar to old Unix or Windows interfaces, ROX belongs solidly in the BeOS, AmigaOS, and [RISC OS][3] desktop camps.
-
-It focuses on drag-and-drop actions (which makes its accessibility non-optimal for some users), point-and-click actions, pop-up contextual menus, and a unique system of app directories for running local applications with no installation required.
-
-### Installing ROX
-
-Today, ROX is mostly abandoned and left in fragments that the user is left to sort out. Luckily, the puzzle is relatively easy to solve, but don't get confused when you find bits and pieces of the ROX desktop in your distribution's repository—but not _every_ bit of the ROX desktop. The popular parts of ROX—the file manager ([ROX-Filer][4]) and the terminal ([ROXTerm][5])—seem to have endured in most of the popular distribution repositories, and you can install (and use) them as standalone applications. However, to run the ROX desktop, you must also install ROX-Session and the libraries it depends on.
-
-I installed ROX on Slackware 14.2, but it should work on any Linux or BSD system.
-
-First, you must install [ROX-lib2][6] from its repository. True to its philosophy of minimal installs, all you have to do to install ROX-lib2 is download the tarball, [unarchive it][7], and move the **ROX-Lib** directory to **/usr/local/lib**.
-
-Next, you have to install [ROX-Session][8]. This probably needs to be compiled from source code, as it's not likely to be in your software repository. The compile process requires build tools, which ship by default on Slackware but are often omitted in other distributions to save space on the initial download. The names of the packages you must install to build from source code vary depending on your distro, so refer to the documentation for specifics. For example, on Debian-based distributions, you can learn about build requirements in [Debian's wiki][9], and on Fedora-based distributions, refer to [Fedora's docs][10]. Once you have the build tools installed, execute the custom ROX-Session build script:
-
-
-```
-`$ ./AppRun`
-```
-
-This manages its own build and installation and prompts you for root permissions to add itself as an option on your login screen.
-
-If you have not installed ROX-Filer from your software repository, do that before continuing.
-
-Together, these components create a complete ROX desktop. To log into your new desktop, log out of your current desktop session. By default, your session manager (KDM, GDM, LightDM, or XDM, depending on your setup) will continue to log you into your previous desktop, so you must override that before logging in.
-
-With SDDM:
-
-![][11]
-
-With GDM:
-
-![][12]
-
-### ROX desktop features
-
-The ROX desktop is simple by default, with a single panel at the bottom of the screen and a shortcut icon to your home directory on the desktop. The panel contains shortcuts to common locations. That's all there is to the ROX desktop, at least as it's configured out of the box. If you want a clock or a calendar or a system tray, you need to find applications that provide them.
-
-![Default ROX desktop][13]
-
-There is no taskbar, as such, but when you minimize a window, it becomes a temporary icon on your desktop. You can click the icon to bring its window back to its former size and placement.
-
-The panel can be modified some, as well. You can place different shortcuts into it and even create your own applets.
-
-There's no application menu, either, nor are there shortcuts to applications in a contextual menu. Instead, you can navigate manually to **/usr/share/applications**, or you can add your application directory or directories to the ROX panel.
-
-![ROX desktop][14]
-
-The ROX desktop's workflow concentrates on being mouse-driven, reminiscent of Mac OS 7.5 and 8. With ROX-filer, you can manage permissions, file management, introspection, script launching, background setting, and nearly anything else you can think of, provided that you're patient enough for the point-and-click style of interaction. For power users, this seems slow, but ROX manages to make it relatively painless and very intuitive.
-
-### App directories, AppRun, and AppImage
-
-The ROX desktop has an elegant convention by which a directory containing a script named **AppRun** is executed as if it were an application. This means that in order to make a ROX app, all you have to do is compile code into a directory, place a script called **AppRun** at the root of that directory to execute the binary you've compiled, and then mark the directory executable. ROX-Filer displays a directory configured in the manner you set with a special icon and color. When you click on an app directory, ROX-Filer automatically runs the **AppRun** script inside. It looks and behaves exactly like an application that has been installed, but it's local to the user's home directory and requires no special permissions.
-
-This is a convenience feature, but it's one of those small features that feels great when you use it because it's so easy to implement. It's by no means essential, and it's only a few steps ahead of building an application locally, hiding the directory somewhere out of the way, and drumming up a quick **.desktop** file to act as your launcher. However, the concept of an application directory has been [cited][15] as an inspiration for the [AppImage][16] packaging system.
-
-### Why you should try ROX desktop
-
-Getting ROX set up and usable is somewhat difficult, and it appears to truly be abandoned. However, its legacy lives on in many ways today, and it's a fascinating and fun bit of Linux history. It may not become your primary desktop, but if you're looking for a fun trip back in time, then ROX is well worth a go. Explore it, customize it, and see what clever ideas it contains. There may yet be hidden gems that the open source community can benefit from.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/linux-rox-desktop
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
-[2]: http://rox.sourceforge.net/desktop/
-[3]: https://www.riscosopen.org/content/
-[4]: http://rox.sourceforge.net/desktop/ROX-Filer
-[5]: http://roxterm.sourceforge.net/
-[6]: http://rox.sourceforge.net/desktop/ROX-Lib
-[7]: https://opensource.com/article/17/7/how-unzip-targz-file
-[8]: http://rox.sourceforge.net/desktop/ROX-Session.html
-[9]: https://wiki.debian.org/BuildingTutorial
-[10]: https://docs.pagure.org/docs-fedora/installing-software-from-source.html
-[11]: https://opensource.com/sites/default/files/advent-kdm_0.jpg
-[12]: https://opensource.com/sites/default/files/advent-gdm_1.jpg
-[13]: https://opensource.com/sites/default/files/uploads/advent-rox.jpg (Default ROX desktop)
-[14]: https://opensource.com/sites/default/files/uploads/advent-rox-custom.jpg (ROX desktop)
-[15]: https://github.com/AppImage/AppImageKit/wiki/AppDir
-[16]: https://appimage.org/
diff --git a/sources/tech/20191223 10 articles to learn Linux your way.md b/sources/tech/20191223 10 articles to learn Linux your way.md
deleted file mode 100644
index 0ef668ad28..0000000000
--- a/sources/tech/20191223 10 articles to learn Linux your way.md
+++ /dev/null
@@ -1,96 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (10 articles to learn Linux your way)
-[#]: via: (https://opensource.com/article/19/12/learn-linux)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-10 articles to learn Linux your way
-======
-It's been a good year for Linux, so take a look back at the top 10 Linux
-articles on Opensource.com from 2019.
-![Penguins gathered together in the Artic][1]
-
-The year 2019 has been good for Linux with Opensource.com readers. Obviously, the term "Linux" itself is weighted: Does it refer to the kernel or the desktop or the ecosystem? In this look back at the top Linux articles of the year, I've intentionally taken a broad view in defining the top 10 Linux articles (for some definition of "top" and some definition of "Linux"). Here they are, offered in no particular order.
-
-### A beginner's guide to Linux permissions
-
-[_A beginner's guide to Linux permissions_][2] by Bryant Son introduces new users to the concept of file permissions with graphics and charts to illustrate each point. It can be hard to come up with visuals for concepts that are, at their core, purely text-based, and this article is friendly for the visual learners out there. I also like how Bryant stays focused. Any discussion of file permissions can lead to several related topics (like ownership and access control lists and so on), but this article is dedicated to explaining one thing and explaining it well.
-
-### Why I made the switch from Mac to Linux
-
-Matthew Broberg offers an insightful and honest look at his migration to Linux from MacOS in [_Why I made the switch from Mac to Linux_][3]. Changing platforms is always tough, and it's important to record what's behind the decision to switch. Matt's article, I think, serves several purposes, but the two most important for me: it's an invitation for the Linux community to support him by answering questions and offering potential solutions, and it's a good data point for others who are considering Linux adoption.
-
-### Troubleshooting slow WiFi on Linux
-
-In [_Troubleshooting slow WiFi on Linux_][4], David Clinton provides a useful analysis of a problem everyone has on every platform—and has tips on how to solve it. It's a good example of an "incidentally Linux" tip that not only helps everyday people with everyday problems but also shows non-Linux users how approachable troubleshooting (on any platform) is.
-
-### How GNOME uses Git
-
-[_How GNOME uses Git_][5] by Molly de Blanc takes a look behind the scenes, revealing how one of the paragons of open source software (the GNOME desktop) uses one of the other paragons of open source (Git) for development. It's always heartening to me to hear about an open source project that defaults to an open source solution for whatever needs to be done. Believe it or not, this isn't always the case, but for GNOME, it's an important and welcoming part of the project's identity.
-
-### Virtual filesystems in Linux: Why we need them and how they work
-
-Alison Chaiken masterfully explains what is considered incomprehensible to many users in [_Virtual filesystems in Linux: Why we need them and how they work_][6]. Understanding what a filesystem is and what it does is one thing, but _virtual_ ones aren't even, by definition, real. And yet Linux delivers them in a way that even casual users can benefit from, and Alison's article explains it in a way that anyone can understand. As a bonus, Alison goes even deeper in the second half of the article and demonstrates how to use bcc scripts to monitor everything she just taught you.
-
-### Understanding file paths and how to use them
-
-I thought [_Understanding file paths and how to use them_][7] was important to write about because it's a concept most users (on any platform) don't seem to be taught. It's a strange phenomenon, because now, more than ever, the _file path_ is something people see literally on a daily basis: Nearly all internet URLs contain a file path telling you exactly where within the domain you are. I often wonder why computer education doesn't start with the internet, the most familiar app of all and arguably the most heavily used supercomputer in existence, and use it to explain the appliances we interface with each day. (I guess it would help if those appliances were running Linux, but we're working on that.)
-
-### Inter-process communication in Linux
-
-[_Inter-process communication in Linux: Shared storage_][8] by Marty Kalin delves into the developer side of Linux, explaining IPC and how to interact with it in your code. I'm cheating by including this article because it's actually a three-part series, but it's the best explanation of its kind. There is very little documentation that manages to explain how Linux handles IPC, much less what IPC is, why it's important, or how to take advantage of it when programming. It's normally a topic you work your way up to in university. Now you can read all about it here instead.
-
-### Understanding system calls on Linux with strace
-
-[_Understanding system calls on Linux with strace_][9] by Gaurav Kamathe is highly technical in ways I wish that every conference talk I've ever seen about **strace** was. This is a clear and helpful demonstration of a complex but amazingly useful command. To my surprise, the command I've found myself using since this article isn't the titular command, but **ltrace** (to see which functions are called by a command). Obviously, this article's packed with information and is a handy reference for developers and QA testers.
-
-### How the Linux desktop has grown
-
-[_How the Linux desktop has grown_][10] by Jim Hall is a visual journey through the history of the Linux desktop. It starts with [TWM][11] and passes by [FVWM][12], [GNOME][13], [KDE][14], and others. If you're new to Linux, this is a fascinating history lesson from someone who was there (and has the screenshots to prove it). If you've been with Linux for many years, then this will definitely bring back memories. In the end, though, one thing is certain: Anyone who can still locate screenshots from 20 years ago is a superhuman data archivist.
-
-### Create your own video streaming server with Linux
-
-[_Create your own video streaming server with Linux_][15] by Aaron J. Prisk breaks down more than just a few preconceptions most of us have about the services we take for granted. Because services like YouTube and Twitch exist, many people assume that those are the only gateways to broadcasting video to the world. Of course, people used to think that Windows and Mac were the only gateways into computing, and that, thankfully, turned out to be a gross miscalculation. In this article, Aaron sets up a video-streaming server and even manages to find space to talk about [OBS][16] in so you can create videos to stream. Is it a fun weekend project or the start of a new career? You decide.
-
-### 10 moments that shaped Linux history
-
-[_10 moments that shaped Linux history_][17] by Alan Formy-Duval attempts the formidable task of choosing just 10 things to highlight in the history of Linux. It's an exercise in futility, of course, because there have been so many important moments, so I love how Alan filters it through his own experience. For example, when was it obvious that Linux was going to last? When Alan realized that all the systems he maintained at work were running Linux. There's a beauty to interpreting history this way because the moments of importance will differ for each person. There's no definitive list for Linux, or articles about Linux, or for open source. You make your own list, and you make yourself a part of it.
-
-### What do you want to learn?
-
-What else do you want to know about Linux? Please tell us about it in the comments, or [write an article][18] for Opensource.com about your experience with Linux.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/learn-linux
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_Penguin_Image_520x292_12324207_0714_mm_v1a.png?itok=p7cWyQv9 (Penguins gathered together in the Artic)
-[2]: https://opensource.com/article/19/6/understanding-linux-permissions
-[3]: https://opensource.com/article/19/10/why-switch-mac-linux
-[4]: http://opensource.com/article/19/4/troubleshooting-wifi-linux
-[5]: https://opensource.com/article/19/10/how-gnome-uses-git
-[6]: https://opensource.com/article/19/3/virtual-filesystems-linux
-[7]: https://opensource.com/article/19/8/understanding-file-paths-linux
-[8]: https://opensource.com/article/19/4/interprocess-communication-linux-storage
-[9]: https://opensource.com/article/19/2/linux-backup-solutions
-[10]: https://opensource.com/article/19/8/how-linux-desktop-grown
-[11]: https://github.com/freedesktop/twm
-[12]: http://www.fvwm.org/
-[13]: http://gnome.org
-[14]: http://kde.org
-[15]: https://opensource.com/article/19/1/basic-live-video-streaming-server
-[16]: https://opensource.com/life/15/12/real-time-linux-video-editing-with-obs-studio
-[17]: https://opensource.com/article/19/4/top-moments-linux-history
-[18]: https://opensource.com/how-submit-article
diff --git a/sources/tech/20191223 Prioritizing simplicity in your Python code.md b/sources/tech/20191223 Prioritizing simplicity in your Python code.md
deleted file mode 100644
index 53662a8f1c..0000000000
--- a/sources/tech/20191223 Prioritizing simplicity in your Python code.md
+++ /dev/null
@@ -1,59 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Prioritizing simplicity in your Python code)
-[#]: via: (https://opensource.com/article/19/12/zen-python-simplicity-complexity)
-[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
-
-Prioritizing simplicity in your Python code
-======
-This is the second part of a special series about the Zen of Python
-focusing on the third and fourth principles: simplicity and complexity.
-![Person reading a book and digital copy][1]
-
-> "Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y plus rien à retrancher."
->
-> "It seems that perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away."
-> —Antoine de Saint-Exupéry, _[Terre des Hommes][2]_, 1939
-
-A common concern in programming is the struggle with complexity. It is easy for any programmer to make a program so complicated no expert can debug it or modify it. The [Zen of Python][3] would not be complete if it did not touch on this.
-
-### Simple is better than complex.
-
-When it is possible to choose at all, choose the simple solution. Python is rarely in the business of _disallowing_ things. This means it is possible, and even straightforward, to design baroque programs to solve straightforward problems.
-
-It is worthwhile to remember at each point that simplicity is one of the easiest things to lose and the hardest to regain when writing code.
-
-This can mean choosing to write something as a function, rather than introducing an extraneous class. This can mean avoiding a robust third-party library in favor of writing a two-line function that is perfect for the immediate use-case. Most often, it means avoiding predicting the future in favor of solving the problem at hand.
-
-It is much easier to change the program later, especially if simplicity and beauty were among its guiding principles than to load the code down with all possible future variations.
-
-### Complex is better than complicated.
-
-This is possibly the most misunderstood principle because understanding the precise meanings of the words is crucial. Something is _complex_ when it is composed of multiple parts. Something is _complicated_ when it has a lot of different, often hard to predict, behaviors.
-
-When solving a hard problem, it is often the case that no simple solution will do. In that case, the most Pythonic strategy is to go "bottom-up." Build simple tools and combine them to solve the problem.
-
-This is where techniques like _object composition_ shine. Instead of having a complicated inheritance hierarchy, have objects that forward some method calls to a separate object. Each of those can be tested and developed separately and then finally put together.
-
-Another example of "building up" is using [singledispatch][4], so that instead of one complicated object, we have a simple, mostly behavior-less object and separate behaviors.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/zen-python-simplicity-complexity
-
-作者:[Moshe Zadka][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/moshez
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/read_book_guide_tutorial_teacher_student_apaper.png?itok=_GOufk6N (Person reading a book and digital copy)
-[2]: https://en.wikipedia.org/wiki/Wind,_Sand_and_Stars
-[3]: https://www.python.org/dev/peps/pep-0020/
-[4]: https://opensource.com/article/19/5/python-singledispatch
diff --git a/sources/tech/20191224 Why your Python code should be flat and sparse.md b/sources/tech/20191224 Why your Python code should be flat and sparse.md
deleted file mode 100644
index 0e447c5d8e..0000000000
--- a/sources/tech/20191224 Why your Python code should be flat and sparse.md
+++ /dev/null
@@ -1,87 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Why your Python code should be flat and sparse)
-[#]: via: (https://opensource.com/article/19/12/zen-python-flat-sparse)
-[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
-
-Why your Python code should be flat and sparse
-======
-This is part of a special series about the Zen of Python focusing on the
-fifth and sixth principles: flatness and sparseness.
-![Digital creative of a browser on the internet][1]
-
-The [Zen of Python][2] is called that for a reason. It was never supposed to provide easy-to-follow guidelines for programming. The rules are specified tersely and are designed to engage the reader in deep thought.
-
-In order to properly appreciate the Zen of Python, you must read it and then meditate upon the meanings. If the Zen was designed to be a set of clear rules, it would be a fault that it has rules that contradict each other. However, as a tool to help you meditate on the best solution, contradictions are powerful.
-
-### Flat is better than nested.
-
-Nowhere is the pressure to be "flat" more obvious than in Python's strong insistence on indentation. Other languages will often introduce an implementation that "cheats" on the nested structure by reducing indentation requirements. To appreciate this point, let's take a look at JavaScript.
-
-JavaScript is natively async, which means that programmers write code in JavaScript using a lot of callbacks.
-
-
-```
-a(function(resultsFromA) {
- b(resultsFromA, function(resultsfromB) {
- c(resultsFromC, function(resultsFromC) {
- console.log(resultsFromC)
- }
- }
-}
-```
-
-Ignoring the code, observe the pattern and the way indentation leads to a right-most point. This distinctive "arrow" shape is tough on the eye to quickly walk through the code, so it's seen as undesirable and even nicknamed "callback hell." However, in JavaScript, it is possible to "cheat" and not have indentation reflect nesting.
-
-
-```
-a(function(resultsFromA) {
-b(resultsFromA,
- function(resultsfromB) {
-c(resultsFromC,
- function(resultsFromC) {
- console.log(resultsFromC)
-}}}
-```
-
-Python affords no such options to cheat: every nesting level in the program must be reflected in the indentation level. So deep nesting in Python _looks_ deeply nested. That makes "callback hell" was a worse problem in Python than in JavaScript: nesting callbacks mean indenting with no options to "cheat" with braces.
-
-This challenge, in combination with the Zen principle, has led to an elegant solution by a library I worked on. In the [Twisted][3] framework, we came up with the _deferred_ abstraction, which would later inspire the popular JavaScript _promise_ abstraction. In this way, Python's unwavering commitment to clear code forces Python developers to discover new, powerful abstractions.
-
-
-```
-future_value = future_result()
-future_value.addCallback(a)
-future_value.addCallback(b)
-future_value.addCallback(c)
-```
-
-(This might look familiar to modern JavaScript programmers: Promises were heavily influenced by Twisted's deferreds.)
-
-### Sparse is better than dense.
-
-The easiest way to make something less dense is to introduce nesting. This habit is why the principle of sparseness follows the previous one: after we have reduced nesting as much as possible, we are often left with _dense_ code or data structures. Density, in this sense, is jamming too much information into a small amount of code, making it difficult to decipher when something goes wrong.
-
-Reducing that denseness requires creative thinking, and there are no simple solutions. The Zen of Python does not offer simple solutions. All it offers are ways to find what can be improved in the code, without always giving guidance for "how."
-
-Take a walk. Take a shower. Smell the flowers. Sit in a lotus position and think hard, until finally, inspiration strikes. When you are finally enlightened, it is time to write the code.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/zen-python-flat-sparse
-
-作者:[Moshe Zadka][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/moshez
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
-[2]: https://www.python.org/dev/peps/pep-0020/
-[3]: https://twistedmatrix.com/trac/
diff --git a/sources/tech/20191226 10 Linux command tutorials for beginners and experts.md b/sources/tech/20191226 10 Linux command tutorials for beginners and experts.md
deleted file mode 100644
index 03fc77a8e1..0000000000
--- a/sources/tech/20191226 10 Linux command tutorials for beginners and experts.md
+++ /dev/null
@@ -1,86 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (summer2233)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (10 Linux command tutorials for beginners and experts)
-[#]: via: (https://opensource.com/article/19/12/linux-commands)
-[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
-
-10 Linux command tutorials for beginners and experts
-======
-Learn how to make Linux do what you need it to do in Opensource.com's
-top 10 articles about Linux commands from 2019.
-![Penguin driving a car with a yellow background][1]
-
-Using Linux _well_ means understanding what commands are available and what they're capable of doing for you. We have covered a lot of them on Opensource.com during 2019, and here are 10 favorites from the bunch.
-
-### Using the force at the Linux command line
-
-The Force has a light side and a dark side. Properly understanding that is crucial to true mastery. In his article [_Using the force at the Linux command line_][2], Alan Formy-Duval explains the **-f** option (also known as **\--force**) for several popular and sometimes dangerous commands.
-
-### Intro to the Linux useradd command
-
-Sharing accounts is a bad idea. Instead, give separate accounts to different people (and even different roles) with the quintessential **useradd** command. Part of his venerable series on basic Linux administration, Alan Formy-Duval provides an [_Intro to the Linux useradd command_][3], and, as usual, he explains it in _plain English_ so that both new and experienced admins can understand it.
-
-### Linux commands to display your hardware information
-
-What's _inside_ the box? Sometimes it's useful to inspect your hardware without using a screwdriver. In [_Linux commands to display your hardware information_][4], Howard Fosdick provides both popular and obscure commands to help you dig deep into the computer you're using, the computer you're testing at the store before buying, or the computer you're trying to repair.
-
-### How to encrypt files with gocryptfs on Linux
-
-Our files hold lots of private data, from social security numbers to personal letters to loved ones. In [_How to encrypt files with gocryptfs on Linux_][5], Brian "Bex" Exelbierd explains how to keep *private *what's meant to be private. As a bonus, he demonstrates encrypting files in a way that has little to no impact on your existing workflow. This isn't a complex PGP-style puzzle of key management and background key agents; this is quick, seamless, and secure file encryption.
-
-### How to use advanced rsync for large Linux backups
-
-In the New Year, many people will resolve to be more diligent about making backups. Alan Formy-Duval must have made that resolution years ago, because in [_How to use advanced rsync for large Linux backups_][6], he displays remarkable familiarity with the file synchronization command. You might not remember all the syntax right away, but the idea is to read and process the options, construct your backup command, and then automate it. That's the smart way to use **rsync**, and it's the _only_ way to do backups reliably.
-
-### Using more to view text files at the Linux command line
-
-In Scott Nesbitt's article [_Using more to view text files at the Linux command line_][7], the good old default pager **more** finally gets the spotlight. Many people install and use **less**, because it's more flexible than **more**. However, with more and more systems being implemented in the sparsest of containers, the luxury of fancy new tools like **less** or **most** sometimes just doesn't exist. Knowing and using **more** is simple, it's a common default, and it's the production system's debugging tool of last resort.
-
-### What you probably didn't know about sudo
-
-The **sudo** command is famous to a fault. People know the **sudo** term, and most of us believe we know what it does. And we're a little bit correct, but as Peter Czanik reveals in his article [_What you probably didn't know about sudo_][8], there's a lot more to the command than just "Simon says." Like that classic childhood game, the **sudo** command is powerful and also prone to silly mistakes—only with greater potential for horrible consequences. This is one game you do not want to lose!
-
-### How to program with Bash: Syntax and tools
-
-If you're a Linux, BSD, or Mac (and lately, Windows) user, you may have used the Bash shell interactively. It's a great shell for quick, one-off commands, which is why so many Linux users love to use it as their primary user interface. However, Bash is much more than just a command prompt. It's also a programming language, and if you're already using Bash commands, then the path to automation has never been more straightforward. Learn all about it in David Both's excellent [_How to program with Bash: Syntax and tools_][9].
-
-### Master the Linux ls command
-
-The **ls** command is one of those commands that merits a two-letter name; one-letter commands are an optimization for slow terminals where each letter causes a significant delay and also a nice bonus for lazy typists. Seth Kenlon explains how you can [_Master the Linux ls command_][10] and he does so with his usual clarity and pragmatism. Most significantly, in a system where "everything is a file," being able to list the files is crucial.
-
-### Getting started with the Linux cat command
-
-The **cat** command (short for con_cat_enate) is deceptively simple. Whether you use it to quickly see the contents of a file or to pipe the contents to another command, you may not be using **cat** to its full potential. Alan Formy-Duval's elucidating [_Getting started with the Linux cat command_][11] offers new ideas to take advantage of a command that lets you open a file without feeling like you've opened it. As a bonus, learn all about **zcat** so you can decompress files without all the trouble of decompression! It's a small and simple thing, but _this_ is what makes Linux great.
-
-### Continue the journey
-
-Don't let Opensource.com's 10 best articles about Linux commands of 2019 be the end of your journey. There's much more to discover about Linux and its versatile prompt, so stay tuned in 2020 for more insights. And, if there's a Linux command you want us to know about, please tell us about it in the comments, or share your knowledge with Opensource.com readers by [submitting an article][12] about your favorite Linux command.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/linux-commands
-
-作者:[Moshe Zadka][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/moshez
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/car-penguin-drive-linux-yellow.png?itok=twWGlYAc (Penguin driving a car with a yellow background)
-[2]: https://opensource.com/article/19/5/may-the-force-linux
-[3]: https://opensource.com/article/19/10/linux-useradd-command
-[4]: https://opensource.com/article/19/9/linux-commands-hardware-information
-[5]: https://opensource.com/article/19/8/how-encrypt-files-gocryptfs
-[6]: https://opensource.com/article/19/5/advanced-rsync
-[7]: https://opensource.com/article/19/1/more-text-files-linux
-[8]: https://opensource.com/article/19/10/know-about-sudo
-[9]: https://opensource.com/article/19/10/programming-bash-syntax-tools
-[10]: https://opensource.com/article/19/7/master-ls-command
-[11]: https://opensource.com/article/19/2/getting-started-cat-command
-[12]: https://opensource.com/how-submit-article
diff --git a/sources/tech/20200107 Kali Linux Will No Longer Have The Default Root User.md b/sources/tech/20200107 Kali Linux Will No Longer Have The Default Root User.md
deleted file mode 100644
index 0f087529b9..0000000000
--- a/sources/tech/20200107 Kali Linux Will No Longer Have The Default Root User.md
+++ /dev/null
@@ -1,87 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (BrunoJu)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Kali Linux Will No Longer Have The Default Root User)
-[#]: via: (https://itsfoss.com/kali-linux-root-user/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Kali Linux Will No Longer Have The Default Root User
-======
-
-Kali Linux is a specialized Linux distribution for cyber security testing and hacking related tasks.
-
-If you’ve used [Kali Linux][1], you probably know that it followed a default root user policy. In other words, you are always root in Kali Linux. Whatever you do – you will be accessing tools/applications as root by default.
-
-It looks like everything back then was kind of “root for all” for everything. So, the default root user policy existed.
-
-They also explained the history for this in their [announcement post][2]:
-
-> A lot of those tools back then either required root access to run or ran better when ran as root. With this operating system that would be ran from a CD, never be updated, and had a lot of tools that needed root access to run it was a simple decision to have a “everything as root” security model. It made complete sense for the time.
-
-### Kali Linux will now have a default non-root user (like most other distributions)
-
-![][3]
-
-A default non-root model was necessary because a lot of users now use Kali Linux as their daily driver.
-
-Of course, they [do not recommend using Kali Linux][4] as a replacement for stable distributions like Ubuntu/Fedora/Manjaro – however, with its active development, some users do consider using it on a day-to-day basis instead of just using it for its tools.
-
-So, with a wide mainstream usage of the distro, the Kali Linux team thought of switching to a default non-root model because nowadays a lot of applications/tools do not require root access.
-
-> While we don’t encourage people to run Kali as their day to day operating system, over the last few years more and more users have started to do so _(even if they are not using it to do penetration testing full time)_, including some members of the Kali development team. When people do so, they obviously don’t run as default root user. With this usage over time, there is the obvious conclusion that default root user is no longer necessary and Kali will be better off moving to a more traditional security model.
-
-So I am reiterating that you should not consider Kali Linux to be fit for your daily tasks if you do not utilize security-related [Kali Linux tools][5]. Feel free to experiment – but I wouldn’t be so sure to rely on it.
-
-So from the next release, when you install Kali Linux, you’ll be asked to create non-root user that will have admin privileges. Tools and commands that require root access will be run with sudo.
-
-![][6]
-
-#### [Pretend to be Using Windows with Kali Linux Undercover Mode][7]
-
-The new undercover mode in Kali Linux switches the desktop layout to make it look like Windows 10. Find out how to activate the undercover mode.
-
-### New default user and password for Kali Linux live mode
-
-![Kali Linux has new user-password in the live system][8]
-
-Technically, you won’t find a groundbreaking difference. Just note that the default user ID and password in live mode is “**kali**“.
-
-You can find the new non-root model implemented in the new daily/weekly builds if you want to test it early.
-
-In either case, you can wait for the 2020.1 release scheduled for late January to take a look at the new default non-root user model.
-
-### Getting back the old root model in Kali Linux
-
-If you are a long time Kali Linux user, you may not find it convenient to add sudo before commands and then manually enter the password.
-
-The good news here is that you can still get the old password-less root rights with this command:
-
-```
-sudo dpkg-reconfigure kali-grant-root
-```
-
-What do you think about the default non-root user model? Is it a good decision? Let me know your thoughts in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/kali-linux-root-user/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://www.kali.org/
-[2]: https://www.kali.org/news/kali-default-non-root-user/
-[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/01/kali_linux_default_root_user.png?ssl=1
-[4]: https://itsfoss.com/kali-linux-review/
-[5]: https://itsfoss.com/best-kali-linux-tools/
-[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/11/kali_linux_undercover_mode.jpg?fit=800%2C450&ssl=1
-[7]: https://itsfoss.com/kali-linux-undercover-mode/
-[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/01/kali-linux-live-password.png?ssl=1
diff --git a/sources/tech/20200121 Syncthing- Open Source P2P File Syncing Tool.md b/sources/tech/20200121 Syncthing- Open Source P2P File Syncing Tool.md
deleted file mode 100644
index aa87c0f873..0000000000
--- a/sources/tech/20200121 Syncthing- Open Source P2P File Syncing Tool.md
+++ /dev/null
@@ -1,146 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Syncthing: Open Source P2P File Syncing Tool)
-[#]: via: (https://itsfoss.com/syncthing/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Syncthing: Open Source P2P File Syncing Tool
-======
-
-_**Brief: Syncthing is an open-source peer-to-peer file synchronization tool that you can use for syncing files between multiple devices (including an Android phone).**_
-
-Usually, we have a cloud sync solution like [MEGA][1] or Dropbox to have a backup of our files on the cloud while making it easier to share it.
-
-But, what do you do if you want to sync your files across multiple devices without storing them on the cloud?
-
-That is where [Syncthing][2] comes to the rescue.
-
-### Syncthing: An open source tool to synchronize files across devices
-
-![][3]
-
-Syncthing lets you sync your files across multiple devices (including the support for Android smartphones). It primarily works through a web UI on Linux but also offers a GUI (to separately install).
-
-However, Syncthing does not utilize the cloud at all – it is a [peer-to-peer][4] file synchronization tool. Your data doesn’t go to a central server. Instead, the data is synced with all the devices between them. So, it does not really replace the [typical cloud storage services on Linux][5].
-
-To add remote devices, you just need the device ID (or simply scan the QR code), no IP addresses involved.
-
-If you want a remote backup of your files – you should probably rely on the cloud.
-
-![Syncthing GUI][6]
-
-All things considered, Syncthing can come in handy for a lot of things. Technically, you can have your important files accessible on multiple systems securely and privately without worrying about anyone spying on your data.
-
-For instance, you may not want to store some of the sensitive files on the cloud – so you can add other trusted devices to sync and keep a copy of those files.
-
-Even though I described it briefly, there’s more to it and than meets the eye. I’d also recommend reading the [official FAQ][7] to clear some confusion on how it works – if you’re interested.
-
-### Features of Syncthing
-
-You probably do not want a lot of options in a synchronization tool – it should be dead simple to work reliably to sync your files.
-
-Syncthing is indeed quite simple and easy to understand – even though it is recommended that you should go through the [documentation][8] if you want to use every bit of its functionality.
-
-Here, I’ll highlight a few useful features of Syncthing:
-
-#### Cross-Platform Support
-
-![Syncthing on Android][9]
-
-Being an open-source solution, it does support Windows, Linux, and macOS.
-
-In addition to that, it also supports Android smartphones. You’ll be disappointed if you have an iOS device – so far, no plans for iOS support.
-
-#### File Versioning
-
-![Syncthing File Versioning][10]
-
-Syncthing utilizes a variety of [File Versioning methods][11] to archive the old files if they are replaced or deleted.
-
-By default, you won’t find it enabled. But, when you create a folder to sync, that’s when you will find the option to toggle the file versioning to your preferred method.
-
-#### Easy To Use
-
-While being a peer-to-peer file synchronization tool, it just works out of the box with no advanced tweaks.
-
-However, it does let you configure advanced settings when needed.
-
-#### Security & Privacy
-
-Even though you do not share your data with any cloud service providers, there are still some connections made that might gain the attention of an eavesdropper. So, Syncthing makes sure the communication is secured using TLS.
-
-In addition to that, there are solid authentication methods to ensure that only the devices/connections you allow explicitly will be granted access to sync/read data.
-
-For Android smartphones, you can also force the traffic through Tor if you’re using the [Orbot app][12]. You’ll find several other options for Android as well.
-
-#### Other Functionalities
-
-![][13]
-
-When exploring the tool yourself, you will notice that there are no limits to how many folders you can sync and the number of devices that you can sync.
-
-So, being a free and open-source solution with lots of useful features makes it an impressive choice for Linux users looking to have a peer-to-peer sync client.
-
-### Installing Syncthing on Linux
-
-You may not observe a .deb file or an .AppImage file for it on its official download webpage. But, you do get a snap package on the [Snap store][14] – if you’re curious you can read about [using snap apps][15] on Linux to get started.
-
-You may not find it in the software center (if you do – it may not be the latest version).
-
-**Note:** _There’s also a [Syncthing-GTK][16] available if you want a GUI to manage that – instead of a browser._
-
-[Syncthing][2]
-
-You can also utilize the terminal to get it installed if you have a Debian-based distro – the instructions are on the [official download page][17].
-
-### My experience with Syncthing
-
-Personally, I got it installed on Pop!_OS 19.10 and used it for a while before writing this up.
-
-I tried syncing folders, removing them, adding duplicate files to see how the file versioning works, and so on. It worked just fine.
-
-However, when I tried syncing it to a phone (Android) – the sync started a bit late, it wasn’t very quick. So, if we could have an option to explicitly force sync, that could help. Or, did I miss the option? Let me know in the comments if I did.
-
-Technically, it uses the resources of your system to work – so if you have a number of devices connected to sync, it should potentially improve the sync speed (upload/download).
-
-Overall, it works quite well – but I must say that you shouldn’t rely on it as the only backup solution to your data.
-
-**Wrapping Up**
-
-Have you tried Syncthing yet? If yes, how was your experience with it? Feel free to share it in the comments below.
-
-Also, if you know about some awesome alternatives to this – let me know about it as well.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/syncthing/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://itsfoss.com/install-mega-cloud-storage-linux/
-[2]: https://syncthing.net/
-[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/syncthing-screenshot.jpg?ssl=1
-[4]: https://en.wikipedia.org/wiki/Peer-to-peer
-[5]: https://itsfoss.com/cloud-services-linux/
-[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/01/syncthing-gtk.png?ssl=1
-[7]: https://docs.syncthing.net/users/faq.html
-[8]: https://docs.syncthing.net/users/index.html
-[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/syncthing-android.jpg?ssl=1
-[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/01/syncthing-file-versioning.jpg?ssl=1
-[11]: https://docs.syncthing.net/users/versioning.html
-[12]: https://play.google.com/store/apps/details?id=org.torproject.android&hl=en_IN
-[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/01/syncthing-screenshot1.jpg?ssl=1
-[14]: https://snapcraft.io/syncthing
-[15]: https://itsfoss.com/install-snap-linux/
-[16]: https://github.com/syncthing/syncthing-gtk/releases/latest
-[17]: https://syncthing.net/downloads/
diff --git a/sources/tech/20200122 Screenshot your Linux system configuration with Bash tools.md b/sources/tech/20200122 Screenshot your Linux system configuration with Bash tools.md
deleted file mode 100644
index 325b3aa019..0000000000
--- a/sources/tech/20200122 Screenshot your Linux system configuration with Bash tools.md
+++ /dev/null
@@ -1,110 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Screenshot your Linux system configuration with Bash tools)
-[#]: via: (https://opensource.com/article/20/1/screenfetch-neofetch)
-[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
-
-Screenshot your Linux system configuration with Bash tools
-======
-ScreenFetch and Neofetch make it easy to share your Linux environment
-with others.
-![metrics and data shown on a computer screen][1]
-
-There are many reasons you might want to share your Linux configuration with other people. You might be looking for help troubleshooting a problem on your system, or maybe you're so proud of the environment you've created that you want to showcase it to fellow open source enthusiasts.
-
-You could get some of that information with a **cat /proc/cpuinfo** or **lscpu** command at the Bash prompt. But if you want to share more details, such as your operating system, kernel, uptime, shell environment, screen resolution, etc., you have two great tools to choose: screenFetch and Neofetch.
-
-### ScreenFetch
-
-[ScreenFetch][2] is a Bash command-line utility that can produce a very nice screenshot of your system configuration and uptime. It is an easy way to share your system's configuration with others in a colorful way.
-
-It's simple to install screenFetch for many Linux distributions.
-
-On Fedora, enter:
-
-
-```
-`$ sudo dnf install screenfetch`
-```
-
-On Ubuntu, enter:
-
-
-```
-`$ sudo apt install screenfetch`
-```
-
-For other operating systems, including FreeBSD, MacOS, and more, consult the screenFetch wiki's [installation page][3]. Once screenFetch is installed, it can produce a detailed and colorful screenshot like this:
-
-![screenFetch][4]
-
-ScreenFetch also provides various command-line options to fine-tune your results. For example, **screenfetch -v** returns verbose output that presents each option line-by-line along with the display shown above.
-
-And **screenfetch -n** eliminates the operating system icon when it displays your system information.
-
-![screenfetch -n option][5]
-
-Other options include **screenfetch -N**, which strips all color from the output; **screenfetch -t**, which truncates the output depending on the size of the terminal; and **screenFetch -E**, which suppresses errors.
-
-Be sure to check the man page on your system for other options. ScreenFetch is open source under the GPLv3, and you can learn more about the project in its [GitHub repository][6].
-
-### Neofetch
-
-[Neofetch][7] is another tool to create a screenshot with your system information. It is written in Bash 3.2 and is open source under the [MIT License][8].
-
-According to the project's website, "Neofetch supports almost 150 different operating systems. From Linux to Windows, all the way to more obscure operating systems like Minix, AIX, and Haiku."
-
-![Neofetch][9]
-
-The project maintains a wiki with excellent [installation documentation][10] for a variety of distributions and operating systems.
-
-If you are on Fedora, RHEL, or CentOS, you can install Neofetch at the Bash prompt with:
-
-
-```
-`$ sudo dnf install neofetch`
-```
-
-On Ubuntu 17.10 and greater, you can use:
-
-
-```
-`$ sudo apt install neofetch`
-```
-
-On its first run, Neofetch writes a **~/.config/neofetch/config.conf** file to your home directory (**.config/config.conf**), which enables you to [customize and control][11] every aspect of Neofetch's output. For example, you can configure Neofetch to use the image, ASCII file, or wallpaper of your choice—or nothing at all. The config.conf file also makes it easy to share your customization with others.
-
-If Neofetch doesn't support your operating system or provide all the options you are looking for, be sure to open up an issue in the project's [GitHub repo][12].
-
-### Conclusion
-
-No matter why you want to share your system configuration, screenFetch or Neofetch should enable you to do so. Do you know of another open source tool that provides this functionality on Linux? Please share your favorite in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/screenfetch-neofetch
-
-作者:[Don Watkins][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/don-watkins
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
-[2]: https://github.com/KittyKatt/screenFetch
-[3]: https://github.com/KittyKatt/screenFetch/wiki/Installation
-[4]: https://opensource.com/sites/default/files/uploads/screenfetch.png (screenFetch)
-[5]: https://opensource.com/sites/default/files/uploads/screenfetch-n.png (screenfetch -n option)
-[6]: http://github.com/KittyKatt/screenFetch
-[7]: https://github.com/dylanaraps/neofetch
-[8]: https://github.com/dylanaraps/neofetch/blob/master/LICENSE.md
-[9]: https://opensource.com/sites/default/files/uploads/neofetch.png (Neofetch)
-[10]: https://github.com/dylanaraps/neofetch/wiki/Installation
-[11]: https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
-[12]: https://github.com/dylanaraps/neofetch/issues
diff --git a/sources/tech/20200123 6 things you should be doing with Emacs.md b/sources/tech/20200123 6 things you should be doing with Emacs.md
deleted file mode 100644
index b01830cd8e..0000000000
--- a/sources/tech/20200123 6 things you should be doing with Emacs.md
+++ /dev/null
@@ -1,91 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (6 things you should be doing with Emacs)
-[#]: via: (https://opensource.com/article/20/1/emacs-cheat-sheet)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-6 things you should be doing with Emacs
-======
-Here are six things you may not have realized you could do with Emacs.
-Then, get our new cheat sheet to get the most out of Emacs.
-![Text editor on a browser, in blue][1]
-
-Imagine using Python's IDLE interface to edit text. You would be able to load files into memory, edit them, and save changes. But every action you perform would be defined by a Python function. Making a word all capitals, for instance, calls **upper()**, opening a file calls **open**, and so on. Everything in your text document is a Python object and can be manipulated accordingly. From the user's perspective, it's the same experience as any text editor. For a Python developer, it's a rich Python environment that can be changed and developed with just a few custom functions in a config file.
-
-This is what [Emacs][2] does for the 1958 programming language [Lisp][3]. In Emacs, there's no separation between the Lisp engine running the application and the arbitrary text you type into it. To Emacs, everything is Lisp data, so everything can be analyzed and manipulated programmatically.
-
-That makes for a powerful user interface (UI). But if you're a casual Emacs user, you may only be scratching the surface of what it can do for you. Here are six things you may not have realized you could do with Emacs.
-
-## Use Tramp mode for cloud editing
-
-Emacs has been network-transparent for a lot longer than has been trendy, and today it still provides one of the smoothest remote editor experiences available. The [Tramp mode][4] in Emacs (formerly known as RPC mode) stands for "Transparent Remote (file) Access, Multiple Protocol," which spells out exactly what it offers: easy access to remote files you want to edit over most popular network protocols. The most popular and safest protocol for remote editing these days is [OpenSSH][5], so that's the default.
-
-Tramp is already included in Emacs 22.1 or greater, so to use Tramp, you just open a file in the Tramp syntax. In the **File** menu of Emacs, select **Open File**. When prompted in the mini-buffer at the bottom of the Emacs window, enter the file name using this syntax:
-
-
-```
-`/ssh:user@example.com:/path/to/file`
-```
-
-If you are required to log in interactively, Tramp prompts you for your password. However, Tramp uses OpenSSH directly, so to avoid interactive prompts, you can also add your hostname, username, and SSH key path to your **~/.ssh/config** file. Like Git, Emacs uses your SSH config first and only stops to ask for more information in the event of an error.
-
-Tramp is great for editing files that don't exist on your computer, and the user experience is not noticeably any different from editing a local file. The next time you start to SSH into a server just to launch a Vim or Emacs session, try Tramp instead.
-
-## Calendaring
-
-If you parse text better than you parse graphical interfaces, you'll be happy to know that you can schedule your day (or life) in plain text with Emacs but still get fancy notifications on your mobile device with open source [Org mode][6] viewers.
-
-The process takes a little setup to create a convenient way to sync your agenda with your mobile device (I use Git, but you could invoke Bluetooth, KDE Connect, Nextcloud, or your file synchronization tool of choice), and you have to install an Org mode viewer (such as [Orgzly][7]) and a Git client app on your mobile. Once you've got your infrastructure sorted, though, the process is inherently perfectly integrated with your usual (or developing, if you're a new user) Emacs workflow. You can refer to your agenda easily in Emacs, make updates to your schedule, and generally stay on task. Pushing changes to your agenda is reflected on your mobile, so you can stay organized even when Emacs isn't available.
-
-![][8]
-
-Intrigued? Read my step-by-step guide about [calendaring with Org mode and Git][9].
-
-## Access the terminal
-
-There are [lots of terminal emulators][10] available. Although the Elisp terminal emulator in Emacs isn't the greatest general-purpose one, it's got two notable advantages.
-
- 1. **Opens in an Emacs buffer: **I use Emacs' Elisp shell because it's conveniently located in my Emacs window, which I often run in fullscreen. It's a small but significant advantage to have a terminal just a **Ctrl+x+o** (or C-x o in Emacs notation) away, and it's especially nice to be able to glance over at it for status reports when it's running a lengthy job.
- 2. **Easy copying and pasting if no system clipboard is available:** Whether I'm too lazy to move my hand from the keys to the mouse, or I don't have mouse functionality because I'm running Emacs in a remote console, having a terminal in Emacs can sometimes mean a quick transfer of data from my Emacs buffer to Bash.
-
-
-
-To try the Emacs terminal, type **Alt**+**x** (**M-x** in Emacs notation), then type **shell**, and press **Return**.
-
-## Use Racket mode
-
-[Racket][11] is an exciting emerging Lisp dialect with a dynamic programming environment, a GUI toolkit, and a passionate community. The default editor when learning Racket is DrRacket, which has a Definitions panel at the top and an Interactions panel at the bottom. Using this setup, the user writes definitions that affect the Racket runtime. Imagine the old [Logo Turtle][12] program, but with a terminal instead of just a turtle.
-
-![Racket-mode][13]
-
-LGPL sample code by PLT
-
-Emacs, being based on Lisp, makes a great integrated development environment (IDE) for advanced Racket coders. It doesn't ship with [Racket mode][14] (yet), but you can install Racket mode and several other helper extensions using the Emacs package installer. To install it, press **Alt**+**X** (**M-x** in Emacs notation), type **package-install**, and press **Return**. Then enter the package you want to install (**racket-mode**), and press **Return**.
-
-Enter Racket mode with **M-x racket-mode**. If you're new to Racket but not to Lisp or Emacs, start with the excellent [Quick introduction to Racket with pictures][15].
-
-## Scripting
-
-You might know that Bash scripts are popular for automating and enhancing your Linux or Unix experience. You may have heard that Python does a pretty good job of that, too. But did you know that Lisp scripts can be run in much the same way? There's sometimes confusion about just how useful Lisp really is because many people are introduced to Lisp through Emacs, so there's the latent impression that the only way to run Lisp in the 21st century is to open an Emacs window. Luckily, that's not the case at all, and Emacs is a great IDE for the tools that enable you to run Lisp scripts as general system executables.
-
-There are two popular modern Lisps, aside from Elisp, that are easy to run as standalone scripts.
-
- 1. **Racket:** You can run Racket scripts relying on your system's Racket install to provide runtime support, or you can use **raco exe** to produce an executable. The **raco exe** command packages your code together with runtime support files to create an executable. The **raco distribute** command then packages that executable into a distribution that works on other machines. Emacs has many Racket-specific tools, so creating Racket files in Emacs is easy and efficient.
-
- 2. **GNU Guile:** [GNU Guile][16] (short for "GNU Ubiquitous Intelligent Language for Extensions") is an implementation of the [Scheme][17] programming language that's used for creating applications and games for the desktop, internet, terminal, and more. Writing Scheme is easy, using any one of the many Scheme extensions in Emacs. For example, here's a "Hello world" script in Guile: [code] #!/usr/bin/guile -s
-!#
-
-(display "hello world")
- (newline) [/code] Compile and run it with the **guile** command: [code] $ guile ./hello.scheme
-;;; compiling /home/seth/./hello.scheme
-;;; compiled [...]/hello.scheme.go
-hello world
-$ guile ./hello.scheme
-hello world
-```
-## Run Elisp without Emacs
-
-Emacs can serve as an Elisp runtime, but you don't have to "open" Emacs in the traditional sense. The **\--script** option allows you to run Elisp scripts using Emacs as the engine but without launching the Emacs GUI (not even its terminal-based one). In this example, the **-Q** option causes Emacs to ignore your **.emacs** file to avoid any delays in executing the Elisp script (if your script relies upon something
\ No newline at end of file
diff --git a/sources/tech/20200124 Run multiple consoles at once with this open source window environment.md b/sources/tech/20200124 Run multiple consoles at once with this open source window environment.md
deleted file mode 100644
index 97c2849b60..0000000000
--- a/sources/tech/20200124 Run multiple consoles at once with this open source window environment.md
+++ /dev/null
@@ -1,115 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Run multiple consoles at once with this open source window environment)
-[#]: via: (https://opensource.com/article/20/1/multiple-consoles-twin)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-Run multiple consoles at once with this open source window environment
-======
-Simulate the old-school DESQview experience with twin in the fourteenth
-in our series on 20 ways to be more productive with open source in 2020.
-![Digital creative of a browser on the internet][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### Overcome "one screen, one app" limits with twin
-
-Who remembers [DESQview][2]? It allowed for things in DOS we take for granted now in Windows, Linux, and MacOS—namely the ability to run and have multiple programs running onscreen at once. In my early days running a dial-up BBS, DESQview was a necessity—it enabled me to have the BBS running in the background while doing other things in the foreground. For example, I could be working on new features or setting up new external programs while someone was dialed in without impacting their experience. Later, in my early days in support, I could have my work email ([DaVinci email on MHS][3]), the support ticket system, and other DOS programs running all at once. It was amazing!
-
-![twin][4]
-
-Running multiple console applications has come a long way since then. But applications like [tmux][5] and [Screen][6] still follow the "one screen, one app" kind of display. OK, yes, tmux has screen splitting and panes, but not like DESQview, with the ability to "float" windows over others, and I, for one, miss that.
-
-Enter [twin][7], the text-mode window environment. This relatively young project is, in my opinion, a spiritual successor to DESQview. It supports console and graphical environments, as well as the ability to detach from and reattach to sessions. It's not as easy to set up as some things, but it will run on most modern operating systems.
-
-Twin is installed from source (for now). But first, you need to install the required development libraries. The library names will vary by operating system. The following example shows it for my Ubuntu 19.10 installation. Once the libraries are installed, check out the twin source from Git and run **./configure** and **make**, which should auto-detect everything and build twin:
-
-
-```
-sudo apt install libx11-dev libxpm-dev libncurses-dev zlib1g-dev libgpm-dev
-git clone [git@github.com][8]:cosmos72/twin.git
-cd twin
-./configure
-make
-sudo make install
-```
-
-Note: If you are compiling this on MacOS or BSD, you will need to comment out **#define socklen_t int** in the files **include/Tw/autoconf.h** and **include/twautoconf.h** before running **make**. This should be addressed by [twin issue number 57][9].
-
-![twin text mode][10]
-
-Invoking twin for the first time can be a bit of a challenge. You need to tell it what kind of display it is using with the **\--hw** parameter. For example, to launch a text-mode version of twin, you would enter **twin --hw=tty,TERM=linux**. The **TERM** variable specifies an override to the current terminal variable in your shell. To launch a graphical version, run **twin --hw=X@$DISPLAY**. On Linux, twin mostly "just works," and on MacOS, it mostly only works in terminals.
-
-The _real_ fun comes with the ability to attach to running sessions with the **twattach** and **twdisplay** commands. They allow you to attach to a running twin session somewhere else. For example, on my Mac, I can run the following command to connect to the twin session running on my demo box:
-
-
-```
-`twdisplay --twin@20days2020.local:0 --hw=tty,TERM=linux`
-```
-
-![remote twin session][11]
-
-With some extra work, you can also use it as a login shell in place of [getty][12] on consoles. This requires the gdm mouse daemon, the twdm application (included), and a little extra configuration. On systems that use systemd, start by installing and enabling gdm (if it isn't already installed). Then use systemctl to create an override for a console (I used tty6). The commands must be run as the root user; on Ubuntu, they look something like this:
-
-
-```
-apt install gdm
-systemctl enable gdm
-systemctl start gdm
-systemctl edit getty@tty6
-```
-
-The **systemctl edit getty@tty6** command will open an empty file named **override.conf**. This defines systemd service settings to override the default for console 6. Update the contents to:
-
-
-```
-[service]
-ExecStart=
-ExecStart=-/usr/local/sbin/twdm --hw=tty@/dev/tty6,TERM=linux
-StandardInput=tty
-StandardOutput=tty
-```
-
-Now, reload systemd and restart tty6 to get a twin login prompt:
-
-
-```
-systemctl daemon-reload
-systemctl restart getty@tty6
-```
-
-![twin][13]
-
-This will launch a twin session for the user who logs in. I do not recommend this for a multi-user system, but it is pretty cool for a personal desktop. And, by using **twattach** and **twdisplay**, you can access that session from the local GUI or remote desktops.
-
-I think twin is pretty darn cool. It has some rough edges, but the basic functionality is there, and it has some pretty good documentation. Also, it scratches the itch I have for a DESQview-like experience on modern operating systems. I look forward to improvements over time, and I hope you like it as much as I do.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/multiple-consoles-twin
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
-[2]: https://en.wikipedia.org/wiki/DESQview
-[3]: https://en.wikipedia.org/wiki/Message_Handling_System
-[4]: https://opensource.com/sites/default/files/uploads/productivity_14-1.png (twin)
-[5]: https://github.com/tmux/tmux/wiki
-[6]: https://www.gnu.org/software/screen/
-[7]: https://github.com/cosmos72/twin
-[8]: mailto:git@github.com
-[9]: https://github.com/cosmos72/twin/issues/57
-[10]: https://opensource.com/sites/default/files/uploads/productivity_14-2.png (twin text mode)
-[11]: https://opensource.com/sites/default/files/uploads/productivity_14-3.png (remote twin session)
-[12]: https://en.wikipedia.org/wiki/Getty_(Unix)
-[13]: https://opensource.com/sites/default/files/uploads/productivity_14-4.png (twin)
diff --git a/sources/tech/20200125 Use tmux to create the console of your dreams.md b/sources/tech/20200125 Use tmux to create the console of your dreams.md
deleted file mode 100644
index adab130489..0000000000
--- a/sources/tech/20200125 Use tmux to create the console of your dreams.md
+++ /dev/null
@@ -1,120 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Use tmux to create the console of your dreams)
-[#]: via: (https://opensource.com/article/20/1/tmux-console)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-Use tmux to create the console of your dreams
-======
-You can do a lot with tmux, especially when you add tmuxinator to the
-mix. Check them out in the fifteenth in our series on 20 ways to be more
-productive with open source in 2020.
-![Person drinking a hat drink at the computer][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### Do it all on the console with tmux and tmuxinator
-
-In this series so far, I've written about individual apps and tools. Starting today, I'll put them together into comprehensive setups to streamline things. Starting at the command line. Why the command line? Simply put, working at the command line allows me to access a lot of these tools and functions from anywhere I can run SSH. I can SSH into one of my personal machines and run the same setup on my work machine as I use on my personal one. And the primary tool I'm going to use for that is [tmux][2].
-
-Most people use tmux for very basic functions, such as opening it on a remote server then starting a process, maybe opening a second session to watch log files or debug information, then disconnecting and coming back later. But you can do so much work with tmux.
-
-![tmux][3]
-
-First things first—if you have an existing tmux configuration file, back it up. The configuration file for tmux is **~/.tmux.conf**. Move it to another directory, like **~/tmp**. Now, clone the [Oh My Tmux][4] project with Git. Link to **.tmux.conf** from that and copy in the **.tmux.conf.local** file to make adjustments:
-
-
-```
-cd ~
-mkdir ~/tmp
-mv ~/.tmux.conf ~/tmp/
-git clone
-ln -s ~/.tmux/.tmux.conf ./
-cp ~/.tmux.conf.local ./
-```
-
-The **.tmux.conf.local** file contains local settings and overrides. For example, I changed the default colors a bit and turned on the [Powerline][5] dividers. This snippet shows only the things I changed:
-
-
-```
-tmux_conf_theme_24b_colour=true
-tmux_conf_theme_focused_pane_bg='default'
-tmux_conf_theme_pane_border_style=fat
-tmux_conf_theme_left_separator_main='\uE0B0'
-tmux_conf_theme_left_separator_sub='\uE0B1'
-tmux_conf_theme_right_separator_main='\uE0B2'
-tmux_conf_theme_right_separator_sub='\uE0B3'
-#tmux_conf_battery_bar_symbol_full='◼'
-#tmux_conf_battery_bar_symbol_empty='◻'
-tmux_conf_battery_bar_symbol_full='♥'
-tmux_conf_battery_bar_symbol_empty='·'
-tmux_conf_copy_to_os_clipboard=true
-set -g mouse on
-```
-
-Note that you do not need to have Powerline installed—you just need a font that supports the Powerline symbols. I use [Hack Nerd Font][6] for almost everything console-related since it is easy for me to read and has many, many useful extra symbols. You'll also note that I turn on operating system clipboard support and mouse support.
-
-Now, when tmux starts up, the status bar at the bottom provides a bit more information—and in exciting colors. **Ctrl**+**b** is still the "leader" key for entering commands, but some others have changed. Splitting panes horizontally (top/bottom) is now **Ctrl**+**b**+**-** and vertically is now **Ctrl**+**b**+**_**. With mouse mode turned on, you can click to switch between the panes and drag the dividers to resize them. Opening a new window is still **Ctrl**+**b**+**n**, and you can now click on the window name on the bottom bar to switch between them. Also, **Ctrl**+**b**+**e** will open up the **.tmux.conf.local** file for editing. When you exit the editor, tmux will reload the configuration without reloading anything else. Very useful.
-
-So far, I've only made some simple changes to functionality and visual display and added mouse support. Now I'll set it up to launch the apps I want in a way that makes sense and without having to reposition and resize them every time. For that, I'll use [tmuxinator][7]. Tmuxinator is a launcher for tmux that allows you to specify and manage layouts and autostart applications with a YAML file. To use it, start tmux and create panes with the things you want running in them. Then, open a new window with **Ctrl**+**b**+**n**, and execute **tmux list-windows**. You will get detailed information about the layout.
-
-![tmux layout information][8]
-
-Note the first line in the code above where I set up four panes with an application in each one.** **Save the output from when you run it for later. Now, run **tmuxinator new 20days** to create a layout named **20days**. This will bring up a text editor with the default layout file. It has a lot of useful stuff in it, and I encourage you to read up on all the options. Start by putting in the layout information above and what apps you want where:
-
-
-```
-# /Users/ksonney/.config/tmuxinator/20days.yml
-name: 20days
-root: ~/
-windows:
- - mail:
- layout: d9da,208x60,0,0[208x26,0,0{104x26,0,0,0,103x26,105,0,5},208x33,0,27{104x33,0,27,1,103x33,105,27,4}]] @0
- panes:
- - alot
- - abook
- - ikhal
- - todo.sh ls +20days
-```
-
-Be careful with the spaces! Like Python code, the spaces and indentation matter to how the file is interpreted. Save the file and then run **tmuxinator 20days**. You should get four panes with the [alot][9] mail program, [abook][10], ikhal (a shortcut to [khal][11] interactive), and anything in [todo.txt][12] with the tag **+20days**.
-
-![sample layout launched by tmuxinator][13]
-
-You'll also notice that the window on the bottom bar is labeled Mail. You can click on the name (along with other named windows) to jump to that view. Nifty, right? I set up a second window named Social with [Tuir][14], [Newsboat][15], an IRC client connected to [BitlBee][16], and [Rainbow Stream][17] in the same file.
-
-Tmux is my productivity powerhouse for keeping track of all the things, and with tmuxinator, I don't have to worry about constantly resizing, placing, and launching my applications.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/tmux-console
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
-[2]: https://github.com/tmux/tmux
-[3]: https://opensource.com/sites/default/files/uploads/productivity_15-1.png (tumux)
-[4]: https://github.com/gpakosz/.tmux
-[5]: https://github.com/powerline/powerline
-[6]: https://www.nerdfonts.com/
-[7]: https://github.com/tmuxinator/tmuxinator
-[8]: https://opensource.com/sites/default/files/uploads/productivity_15-2.png (tmux layout information)
-[9]: https://opensource.com/article/20/1/organize-email-notmuch
-[10]: https://opensource.com/article/20/1/sync-contacts-locally
-[11]: https://opensource.com/article/20/1/open-source-calendar
-[12]: https://opensource.com/article/20/1/open-source-to-do-list
-[13]: https://opensource.com/sites/default/files/uploads/productivity_15-3.png (sample layout launched by tmuxinator)
-[14]: https://opensource.com/article/20/1/open-source-reddit-client
-[15]: https://opensource.com/article/20/1/open-source-rss-feed-reader
-[16]: https://opensource.com/article/20/1/open-source-chat-tool
-[17]: https://opensource.com/article/20/1/tweet-terminal-rainbow-stream
diff --git a/sources/tech/20200126 Use Vim to send email and check your calendar.md b/sources/tech/20200126 Use Vim to send email and check your calendar.md
deleted file mode 100644
index fdb709aaef..0000000000
--- a/sources/tech/20200126 Use Vim to send email and check your calendar.md
+++ /dev/null
@@ -1,117 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Use Vim to send email and check your calendar)
-[#]: via: (https://opensource.com/article/20/1/vim-email-calendar)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-Use Vim to send email and check your calendar
-======
-Manage your email and calendar right from your text editor in the
-sixteenth in our series on 20 ways to be more productive with open
-source in 2020.
-![Calendar close up snapshot][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### Doing (almost) all the things with Vim, part 1
-
-I use two text editors regularly—[Vim][2] and [Emacs][3]. Why both? They have different use cases, and I'll talk about some of them in the next few articles in this series.
-
-![][4]
-
-OK, so why do everything in Vim? Because if there is one application that is on every machine I have access to, it's Vim. And if you are like me, you probably already spend a lot of time in Vim. So why not use it for _all the things_?
-
-Before that, though, you need to do some things. The first is to make sure you have Ruby support in Vim. You can check that with **vim --version | grep ruby**. If the result is not **+ruby**, that needs to be fixed. This can be tricky, and you should check your distribution's documentation for the right package to install. On MacOS, this is the official MacVim (not from Brew), and on most Linux distributions, this is either vim-nox or vim-gtk—NOT vim-gtk3.
-
-I use [Pathogen][5] to autoload my plugins and bundles. If you use [Vundle][6] or another Vim package manager, you'll need to adjust the commands below to work with it.
-
-#### Do your email in Vim
-
-A good starting place for making Vim a bigger part of your productivity plan is using it to send and receive email with [Notmuch][7] using [abook][8] to access your contact list. You need to install some things for this. All the sample code below is on Ubuntu, so you'll need to adjust for that if you are using a different distribution. Do the setup with:
-
-
-```
-sudo apt install notmuch-vim ruby-mail
-curl -o ~/.vim/plugin/abook --create-dirs
-```
-
-So far, so good. Now start Vim and execute **:NotMuch**. There may be some warnings due to the older version of the mail library **notmuch-vim** was written for, but in general, Vim will now be a full-featured Notmuch mail client.
-
-![Reading Mail in Vim][9]
-
-If you want to perform a search for a specific tag, type **\t**, enter the name of the tag, and press Enter. This will pull up a list of all messages with that tag. The **\s** key combination brings up a **Search:** prompt that will do a full search of the Notmuch database. Navigate the message list with the arrow keys, press Enter to display the selected item, and enter **\q** to exit the current view.
-
-To compose mail, use the **\c** keystroke. You will see a blank message. This is where the **abook.vim** plugin comes in. Hit **Esc** and enter **:AbookQuery <SomeName>**, where <SomeName> is a part of the name or email address you want to look for. You will get a list of entries in the abook database that match your search. Select the address you want by typing its number to add it to the email's address line. Finish typing and editing the email, press **Esc** to exit edit mode, and enter **,s** to send.
-
-If you want to change the default folder view when **:NotMuch** starts up, you can add the variable **g:notmuch_folders** to your **.vimrc** file:
-
-
-```
-let g:notmuch_folders = [
- \ [ 'new', 'tag:inbox and tag:unread' ],
- \ [ 'inbox', 'tag:inbox' ],
- \ [ 'unread', 'tag:unread' ],
- \ [ 'News', 'tag:@sanenews' ],
- \ [ 'Later', 'tag:@sanelater' ],
- \ [ 'Patreon', 'tag:@patreon' ],
- \ [ 'LivestockConservancy', 'tag:livestock-conservancy' ],
- \ ]
-```
-
-There are many more settings covered in the Notmuch plugin's documentation, including setting up keys for tags and using alternate mail programs.
-
-#### Consult your calendar in Vim
-
-![][10]
-
-Sadly, there do not appear to be any calendar programs for Vim that use the vCalendar or iCalendar formats. There is [Calendar.vim][11], which is very well done. Set up Vim to access your calendar with:
-
-
-```
-cd ~/.vim/bundle
-git clone [git@github.com][12]:itchyny/calendar.vim.git
-```
-
-Now, you can see your calendar in Vim by entering **:Calendar**. You can switch between year, month, week, day, and clock views with the **<** and **>** keys. If you want to start with a particular view, use the **-view=** flag to tell it which one you wish to see. You can also add a date to any of the views. For example, if I want to see what is going on the week of July 4, 2020, I would enter **:Calendar -view week 7 4 2020**. The help is pretty good and can be accessed with the **?** key.
-
-![][13]
-
-Calendar.vim also supports Google Calendar (which I need), but in December 2019 Google disabled the access for it. The author has posted a workaround in [the issue on
-GitHub][14].
-
-So there you have it, your mail, addresses, and calendars in Vim. But you aren't done yet; you'll do even more with Vim tomorrow!
-
-Vim offers great benefits to writers, regardless of whether they are technically minded or not.
-
-Need to keep your schedule straight? Learn how to do it using open source with these free...
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/vim-email-calendar
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calendar.jpg?itok=jEKbhvDT (Calendar close up snapshot)
-[2]: https://www.vim.org/
-[3]: https://www.gnu.org/software/emacs/
-[4]: https://opensource.com/sites/default/files/uploads/day16-image1.png
-[5]: https://github.com/tpope/vim-pathogen
-[6]: https://github.com/VundleVim/Vundle.vim
-[7]: https://opensource.com/article/20/1/organize-email-notmuch
-[8]: https://opensource.com/article/20/1/sync-contacts-locally
-[9]: https://opensource.com/sites/default/files/uploads/productivity_16-2.png (Reading Mail in Vim)
-[10]: https://opensource.com/sites/default/files/uploads/day16-image3.png
-[11]: https://github.com/itchyny/calendar.vim
-[12]: mailto:git@github.com
-[13]: https://opensource.com/sites/default/files/uploads/day16-image4.png
-[14]: https://github.com/itchyny/calendar.vim/issues/156
diff --git a/sources/tech/20200128 Send email and check your calendar with Emacs.md b/sources/tech/20200128 Send email and check your calendar with Emacs.md
deleted file mode 100644
index 48be7e8e45..0000000000
--- a/sources/tech/20200128 Send email and check your calendar with Emacs.md
+++ /dev/null
@@ -1,152 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Send email and check your calendar with Emacs)
-[#]: via: (https://opensource.com/article/20/1/emacs-mail-calendar)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-Send email and check your calendar with Emacs
-======
-Manage your email and view your schedule with the Emacs text editor in
-the eighteenth in our series on 20 ways to be more productive with open
-source in 2020.
-![Document sending][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### Doing (almost) all the things with Emacs, part 1
-
-Two days ago, I shared that I use both [Vim][2] and [Emacs][3] regularly, and on days [16][4] and [17][5] of this series, I explained how to do almost everything in Vim. Now, it's time for Emacs!
-
-![Mail and calendar in Emacs][6]
-
-Before I get too far, I should explain two things. First, I'm doing everything here using the default Emacs configuration, not [Spacemacs][7], which I have [written about][8]. Why? Because I will be using the default keyboard mappings so that you can refer back to the documentation and not have to translate things from "native Emacs" to Spacemacs. Second, I'm not setting up Org mode in this series. Org mode almost needs an entire series on its own, and, while it is very powerful, the setup can be quite complex.
-
-#### Configure Emacs
-
-Configuring Emacs is a little bit more complicated than configuring Vim, but in my opinion, it is worth it in the long run. Start by creating a configuration file and opening it in Emacs:
-
-
-```
-mkdir ~/.emacs.d
-emacs ~/.emacs.d/init.el
-```
-
-Next, add some additional package sources to the built-in package manager. Add the following to **init.el**:
-
-
-```
-(package-initialize)
-(add-to-list 'package-archives '("melpa" . ""))
-(add-to-list 'package-archives '("org" . "") t)
-(add-to-list 'package-archives '("gnu" . ""))
-(package-refresh-contents)
-```
-
-Save the file with **Ctrl**+**x** **Ctrl**+**s**, exit with **Ctrl**+**x** **Ctrl**+**c**, and restart Emacs. It will download all the package lists at startup, and then you should be ready to install things with the built-in package manager. Start by typing **Meta**+**x** to bring up a command prompt (the **Meta** key is the **Alt** key on most keyboards or **Option** on MacOS). At the command prompt, type **package-list-packages** to bring up a list of packages you can install. Go through the list and select the following packages with the **i** key:
-
-
-```
-bbdb
-bbdb-vcard
-calfw
-calfw-ical
-notmuch
-```
-
-Once the packages are selected, press **x** to install them. Depending on your internet connection, this could take a while. You may see some compile errors, but it's safe to ignore them. Once it completes, open **~/.emacs.d/init.el** with the key combination **Ctrl**+**x** **Ctrl**+**f**, and add the following lines to the file after **(package-refresh-packages)** and before **(custom-set-variables**. Emacs uses the **(custom-set-variables** line internally, and you should never, ever modify anything below it. Lines beginning with **;;** are comments.
-
-
-```
-;; Set up bbdb
-(require 'bbdb)
-(bbdb-initialize 'message)
-(bbdb-insinuate-message)
-(add-hook 'message-setup-hook 'bbdb-insinuate-mail)
-;; set up calendar
-(require 'calfw)
-(require 'calfw-ical)
-;; Set this to the URL of your calendar. Google users will use
-;; the Secret Address in iCalendar Format from the calendar settings
-(cfw:open-ical-calendar "")
-;; Set up notmuch
-(require 'notmuch)
-;; set up mail sending using sendmail
-(setq send-mail-function (quote sendmail-send-it))
-(setq user-mail-address "[myemail@mydomain.com][9]"
- user-full-name "My Name")
-```
-
-Now you are ready to start Emacs with your setup! Save the **init.el** file (**Ctrl**+**x** **Ctrl**+**s**), exit Emacs (**Ctrl**+**x** **Ctrl**+**c**), and then restart it. It will take a little longer to start this time.
-
-#### Read and write email in Emacs with Notmuch
-
-Once you are at the Emacs splash screen, you can start reading your email with [Notmuch][10]. Type **Meta**+**x notmuch**, and you'll get Notmuch's Emacs interface.
-
-![Reading mail with Notmuch][11]
-
-All the items in bold type are links to email views. You can access them with either a mouse click or by tabbing between them and pressing **Return** or **Enter**. You can use the search bar to
-
-search Notmuch's database using the [same syntax][12] as you use on Notmuch's command line. If you want, you can save any searches for later use with the **[save]** button, and they will be added to the list at the top of the screen. If you follow one of the links, you will get a list of the relevant email messages. You can navigate the list with the **Arrow** keys, and press **Enter** on the message you want to read. Pressing **r** will reply to a message, **f** will forward the message, and **q** will exit the current screen.
-
-You can write a new message by typing **Meta**+**x compose-mail**. Composing, replying, and forwarding all bring up the mail writing interface. When you are done writing your email, press **Ctrl**+**c Ctrl**+**c** to send it. If you decide you don't want to send it, press **Ctrl**+**c Ctrl**+**k** to kill the message compose buffer (window).
-
-#### Autocomplete email addresses in Emacs with BBDB
-
-![Composing a message with BBDB addressing][13]
-
-But what about your address book? That's where [BBDB][14] comes in. But first, import all your addresses from [abook][15] by opening a command line and running the following export command:
-
-
-```
-`abook --convert --outformat vcard --outfile ~/all-my-addresses.vcf --infile ~/.abook/addresses`
-```
-
-Once Emacs starts, run **Meta**+**x bbdb-vcard-import-file**. It will prompt you for the file name you want to import, which is **~/all-my-addresses.vcf**. After the import finishes, when you compose a message, you can start typing a name and use **Tab** to search and autocomplete the "To" field. BBDB will also open a buffer for the contact so you can make sure it's the correct one.
-
-Why do it this way when you already have each address as a **vcf.** file from [vdirsyncer][16]? If you are like me, you have a LOT of addresses, and doing them one at a time is a lot of work. This way, you can take everything you have in abook and make one big file.
-
-#### View your calendar in Emacs with calfw
-
-![calfw calendar][17]
-
-Finally, you can use Emacs to look at your calendar. In the configuration section above, you installed the [calfw][18] package and added lines to tell it where to find the calendars to load. Calfw is short for the Calendar Framework for Emacs, and it supports many calendar formats. Since I use Google calendar, that is the link I put into my config. Your calendar will auto-load at startup, and you can view it by switching the **cfw-calendar** buffer with the **Ctrl**+**x**+**b** command.
-
-Calfw offers views by the day, week, two weeks, and month. You can select the view from the top of the calendar and navigate your calendar with the **Arrow** keys. Unfortunately, calfw can only view calendars, so you'll still need to use something like [khal][19] or a web interface to add, delete, and modify events.
-
-So there you have it: mail, calendars, and addresses in Emacs. Tomorrow I'll do even more.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/emacs-mail-calendar
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_paper_envelope_document.png?itok=uPj_kouJ (Document sending)
-[2]: https://www.vim.org/
-[3]: https://www.gnu.org/software/emacs/
-[4]: https://opensource.com/article/20/1/vim-email-calendar
-[5]: https://opensource.com/article/20/1/vim-task-list-reddit-twitter
-[6]: https://opensource.com/sites/default/files/uploads/productivity_18-1.png (Mail and calendar in Emacs)
-[7]: https://www.spacemacs.org/
-[8]: https://opensource.com/article/19/12/spacemacs
-[9]: mailto:myemail@mydomain.com
-[10]: https://notmuchmail.org/
-[11]: https://opensource.com/sites/default/files/uploads/productivity_18-2.png (Reading mail with Notmuch)
-[12]: https://opensource.com/article/20/1/organize-email-notmuch
-[13]: https://opensource.com/sites/default/files/uploads/productivity_18-3.png (Composing a message with BBDB addressing)
-[14]: https://www.jwz.org/bbdb/
-[15]: https://opensource.com/article/20/1/sync-contacts-locally
-[16]: https://opensource.com/article/20/1/open-source-calendar
-[17]: https://opensource.com/sites/default/files/uploads/productivity_18-4.png (calfw calendar)
-[18]: https://github.com/kiwanami/emacs-calfw
-[19]: https://khal.readthedocs.io/en/v0.9.2/index.html
diff --git a/sources/tech/20200129 Use Emacs to get social and track your todo list.md b/sources/tech/20200129 Use Emacs to get social and track your todo list.md
deleted file mode 100644
index 3893aac377..0000000000
--- a/sources/tech/20200129 Use Emacs to get social and track your todo list.md
+++ /dev/null
@@ -1,162 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Use Emacs to get social and track your todo list)
-[#]: via: (https://opensource.com/article/20/1/emacs-social-track-todo-list)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-Use Emacs to get social and track your todo list
-======
-Access Twitter, Reddit, chat, email, RSS, and your todo list in the
-nineteenth in our series on 20 ways to be more productive with open
-source in 2020.
-![Team communication, chat][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### Doing (almost) all the things with Emacs, part 2
-
-[Yesterday][2], I talked about how to read email, access your addresses, and show calendars in Emacs. Emacs has tons and tons of functionality, and you can also use it for Twitter, chatting, to-do lists, and more!
-
-![All the things with Emacs][3]
-
-To do all of this, you need to install some Emacs packages. As you did yesterday, open the Emacs package manager with **Meta**+**x package-manager** (Meta is **Alt** on most keyboards or **Option** on MacOS). Now select the following packages with **i**, then install them by typing **x**:
-
-
-```
-nnreddit
-todotxt
-twittering-mode
-```
-
-Once they are installed, open **~/.emacs.d/init.el** with **Ctrl**+**x Ctrl**+**x**, and add the following before the **(custom-set-variables** line:
-
-
-```
-;; Todo.txt
-(require 'todotxt)
-(setq todotxt-file (expand-file-name "~/.todo/todo.txt"))
-
-;; Twitter
-(require 'twittering-mode)
-(setq twittering-use-master-password t)
-(setq twittering-icon-mode t)
-
-;; Python3 for nnreddit
-(setq elpy-rpc-python-command "python3")
-```
-
-Save the file with **Ctrl**+**x Ctrl**+**a**, exit Emacs with **Ctrl**+**x Ctrl**+**c**, then restart Emacs.
-
-#### Tweet from Emacs with twittering-mode
-
-![Twitter in Emacs][4]
-
-[Twittering-mode][5] is one of the best Emacs interfaces for Twitter. It supports almost all the features of Twitter and has some easy-to-use keyboard shortcuts.
-
-To get started, type **Meta**+**x twit** to launch twittering-mode. It will give a URL to open—and prompt you to launch a browser with it if you want—so you can log in and get an authorization token. Copy and paste the token into Emacs, and your Twitter timeline should load. You can scroll with the **Arrow** keys, use **Tab** to move from item to item, and press **Enter** to view the URL the cursor is on. If the cursor is on a username, pressing **Enter** will open that timeline in a web browser. If you are on a tweet's text, pressing **Enter** will reply to that tweet. You can create a new tweet with **u**, retweet something with **Ctrl**+**c**+**Enter**, and send a direct message with **d**—the dialog it opens has instructions on how to send, cancel, and shorten URLs.
-
-Pressing **V** will open a prompt to get to other timelines. To open your mentions, type **:mentions**. The home timeline is **:home**, and typing a username will take you to that user's timeline. Finally, pressing **q** will quit twittering-mode and close the window.
-
-There is a lot more functionality available in twittering-mode, and I encourage you to read the [full list][6] on its GitHub page.
-
-#### Track your to-do's in Emacs with Todotxt.el
-
-![todo.txt in emacs][7]
-
-[Todotxt.el][8] is a nice interface for the [todo.txt][9] to-do list manager. It has hotkeys for just about everything.
-
-To start it up, type **Meta**+**x todotxt**, and it will load the todo.txt file you specified in the **todotxt-file** variable (which you set in the first part of this article). Inside the buffer (window) for todo.txt, you can press **a** to add a new task and **c** to mark it complete. You can set priorities with **r**, and add projects and context to an item with **t**. When you are ready to move everything to **done.txt**, just press **A**. And you can filter the list with **/** or refresh back to the full list with **l**. And again, you can press **q** to exit.
-
-#### Chat in Emacs with ERC
-
-![Chatting with erc][10]
-
-One of Vim's shortcomings is that trying to use chat with it is difficult (at best). Emacs, on the other hand, has the [ERC][11] client built into the default distribution. Start ERC with **Meta**+**x erc**, and you will be prompted for a server name, username, and password. You can use the same information you used a few days ago when you set up [BitlBee][12]: server **localhost**, port **6667**, and the same username with no password. It should be the same as using almost any other IRC client. Each channel will be split into a new buffer (window), and you can switch between them with **Ctrl**+**x Ctrl**+**b**, which also switches between other buffers in Emacs. The **/quit** command will exit ERC.
-
-#### Read email, Reddit, and RSS feeds with Gnus
-
-![Mail, Reddit, and RSS feeds with Gnus][13]
-
-I'm sure many long-time Emacs users were asking, "but what about [Gnus][14]?" yesterday when I was talking about reading mail in Emacs. And it's a valid question. Gnus is a mail and newsreader built into Emacs, although it doesn't support [Notmuch][15] as a mail reader, just as a search engine. However, if you are configuring it for Reddit and RSS feeds (as you'll do in a moment), it's smart to add in mail functionality as well.
-
-Gnus was created for reading Usenet News and grew from there. So, a lot of its look and feel (and terminology) seem a lot like a Usenet newsreader.
-
-Gnus has its own configuration file in **~/.gnus** (the configuration can also be included in the main **~/.emacs.d/init.el**). Open **~/.gnus** with **Ctrl**+**x Ctrl**+**f** and add the following:
-
-
-```
-;; Required packages
-(require 'nnir)
-(require 'nnrss)
-
-;; Primary Mailbox
-(setq gnus-select-method
- '(nnmaildir "Local"
- (directory "~/Maildir")
- (nnir-search-engine notmuch)
- ))
-(add-to-list 'gnus-secondary-select-methods
- '(nnreddit ""))
-```
-
-Save the file with **Ctrl**+**x Ctrl**+**s**. This tells Gnus to read mail from the local mailbox in **~/Maildir** as the primary source (**gnus-select-method**) and add a second source (**gnus-secondary-select-methods**) using the [nnreddit][16] plugin. You can also define multiple secondary sources, including Usenet News (nntp), IMAP (nnimap), mbox (nnmbox), and virtual collections (nnvirtual). You can learn more about all the options in the [Gnus manual][17].
-
-Once you save the file, start Gnus with **Meta**+**x gnus**. The first run will install [Reddit Terminal Viewer][18] in a Python virtual environment, which is how it gets Reddit articles. It will then launch your browser to log into Reddit. After that, it will scan and load your subscribed Reddit groups. You will see a list of email folders with new mail and the list of subreddits with new content. Pressing **Enter** on any of them will load the list of messages for the group. You can navigate with the **Arrow** keys and press **Enter** to load and read a message. Pressing **q** will go back to the prior view when viewing message lists, and pressing **q** from the main window will exit Gnus. When reading a Reddit group, **a** creates a new message; in a mail group, **m** creates a new email; and **r** replies to messages in either view.
-
-You can also add RSS feeds to the Gnus interface and read them like mail and newsgroups. To add an RSS feed, type **G**+**R** and fill in the RSS feed's URL. You will be prompted for the title and description of the feed, which should be auto-filled from the feed. Now type **g** to check for new messages (this checks for new messages in all groups). Reading a feed is like reading Reddit groups and mail, so it uses the same keys.
-
-There is a _lot_ of functionality in Gnus, and there are a whole lot more key combinations. The [Gnus Reference Card][19] lists all of them for each view (on five pages in very small type).
-
-#### See your position with nyan-mode
-
-As a final note, you might notice [Nyan cat][20] at the bottom of some of my screenshots. This is [nyan-mode][21], which indicates where you are in a buffer, so it gets longer as you get closer to the bottom of a document or buffer. You can install it with the package manager and set it up with the following code in **~/.emacs.d/init.el**:
-
-
-```
-;; Nyan Cat
-(setq nyan-wavy-trail t)
-(setq nyan-bar-length 20)
-(nyan-mode)
-```
-
-### Scratching Emacs' surface
-
-This is just scratching the surface of all the things you can do with Emacs. It is _very_ powerful, and it is one of my go-to tools for being productive whether I'm tracking to-dos, reading and responding to mail, editing text, or chatting with my friends and co-workers. It takes a bit of getting used to, but once you do, it can become one of the most useful tools on your desktop.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/emacs-social-track-todo-list
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/talk_chat_team_mobile_desktop.png?itok=d7sRtKfQ (Team communication, chat)
-[2]: https://opensource.com/article/20/1/emacs-mail-calendar
-[3]: https://opensource.com/sites/default/files/uploads/productivity_19-1.png (All the things with Emacs)
-[4]: https://opensource.com/sites/default/files/uploads/productivity_19-2.png (Twitter in Emacs)
-[5]: https://github.com/hayamiz/twittering-mode
-[6]: https://github.com/hayamiz/twittering-mode#features
-[7]: https://opensource.com/sites/default/files/uploads/productivity_19-3.png (todo.txt in emacs)
-[8]: https://github.com/rpdillon/todotxt.el
-[9]: http://todotxt.org/
-[10]: https://opensource.com/sites/default/files/uploads/productivity_19-4.png (Chatting with erc)
-[11]: https://www.gnu.org/software/emacs/manual/html_mono/erc.html
-[12]: https://opensource.com/article/20/1/open-source-chat-tool
-[13]: https://opensource.com/sites/default/files/uploads/productivity_19-5.png (Mail, Reddit, and RSS feeds with Gnus)
-[14]: https://www.gnus.org/
-[15]: https://opensource.com/article/20/1/organize-email-notmuch
-[16]: https://github.com/dickmao/nnreddit
-[17]: https://www.gnus.org/manual/gnus.html
-[18]: https://pypi.org/project/rtv/
-[19]: https://www.gnu.org/software/emacs/refcards/pdf/gnus-refcard.pdf
-[20]: http://www.nyan.cat/
-[21]: https://github.com/TeMPOraL/nyan-mode
diff --git a/sources/tech/20200130 4 open source productivity tools on my wishlist.md b/sources/tech/20200130 4 open source productivity tools on my wishlist.md
deleted file mode 100644
index d36f020aa3..0000000000
--- a/sources/tech/20200130 4 open source productivity tools on my wishlist.md
+++ /dev/null
@@ -1,76 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (4 open source productivity tools on my wishlist)
-[#]: via: (https://opensource.com/article/20/1/open-source-productivity-tools)
-[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
-
-4 open source productivity tools on my wishlist
-======
-Find out what the open source world needs to work on in the final
-article in our series on 20 ways to be more productive with open source
-in 2020.
-![Two diverse hands holding a globe][1]
-
-Last year, I brought you 19 days of new (to you) productivity tools for 2019. This year, I'm taking a different approach: building an environment that will allow you to be more productive in the new year, using tools you may or may not already be using.
-
-### But what about…
-
-When searching for productivity apps, I never find everything I want, and I almost always miss something great that my readers share with me. So, as I bring this series to a close, it's time [again][2] to talk about some of the topics I failed to cover in this year's series.
-
-![Desktop with Joplin, Emacs, and Firefox][3]
-
-#### Chatting in Vim
-
-I tried. I really, _really_ tried to get chat to work in Vim, but it was not to be. The one package I was able to find, [VimIRC.vim][4], never did work for me, and I tried for a few days to no avail. The other option I explored was [Irc it][5], which requires a lot more [effort to set up][6] than I could fit into my available space or time. I tried, I really did, and for the Vim users out there, I'm sorry I wasn't able to get something workable for you.
-
-#### Org mode
-
-![Org Mode in Emacs][7]
-
-I love [Org Mode][8], and I use it daily. I could spend several days _just_ talking about Org. It provides basic [task tracking][9]; Google [calendar][10] sync and [CalFW][11] integration; rich text documents, websites, and presentations; linking to all the things; and; and; and…
-
-I expect you will hear more from me about Org in 2020 because it really is pretty cool.
-
-#### GUI programs
-
-In 2019's productivity series, I shared a lot of programs with a graphical user interface (GUI), and this year almost all are command-line applications. There are some great graphical programs to help with some of the things I talked about this year—[mail][12] programs to talk to Maildir mailboxes, calendar programs to read local calendar files, [weather][13] apps, and so on. I even tried several new-to-me things to see if they would fit with the overall theme. With the exception of [twin][14], I didn't feel that there were any GUI programs that were new (to me) or notable (again, to me) to write about this year. And that brings me to…
-
-#### Mobile
-
-More and more people are using tablets (sometimes in conjunction with a laptop) as their primary device. I use my phone for most of my social media and instant messaging, and, more often than not, I use my tablet (OK, let's be honest, _tablets_) to read or browse the web. It isn't that open source mobile apps aren't out there, that's for sure, but they didn't fit with my themes this year. There is a lot going on with open source and mobile apps, and I'm watching carefully for things that can help me be more productive on my phone and tablet.
-
-### Your turn
-
-Thank you very much for reading the series this year. Please comment with what you think I missed or need to look at for 2021. And as I say on the [Productivity Alchemy][15] podcast: "Remember folks: Stay productive!"
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/1/open-source-productivity-tools
-
-作者:[Kevin Sonney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ksonney
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/world_hands_diversity.png?itok=zm4EDxgE (Two diverse hands holding a globe)
-[2]: https://opensource.com/article/19/1/productivity-tool-wish-list
-[3]: https://opensource.com/sites/default/files/uploads/productivity_20-1.png (Desktop with Joplin, Emacs, and Firefox)
-[4]: https://github.com/vim-scripts/VimIRC.vim
-[5]: https://tools.suckless.org/ii/
-[6]: https://www.reddit.com/r/vim/comments/48t7ws/vim_ii_irc_client_xpost_runixporn/d0macnl/
-[7]: https://opensource.com/sites/default/files/uploads/productivity_20-2.png (Org Mode in Emacs)
-[8]: https://orgmode.org/
-[9]: https://opensource.com/article/20/1/open-source-to-do-list
-[10]: https://opensource.com/article/20/1/open-source-calendar
-[11]: https://github.com/kiwanami/emacs-calfw
-[12]: https://opensource.com/article/20/1/organize-email-notmuch
-[13]: https://opensource.com/article/20/1/open-source-weather-forecast
-[14]: https://github.com/cosmos72/twin
-[15]: https://productivityalchemy.com
diff --git a/sources/tech/20200130 Meet FuryBSD- A New Desktop BSD Distribution.md b/sources/tech/20200130 Meet FuryBSD- A New Desktop BSD Distribution.md
deleted file mode 100644
index eee1d27f9c..0000000000
--- a/sources/tech/20200130 Meet FuryBSD- A New Desktop BSD Distribution.md
+++ /dev/null
@@ -1,94 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Meet FuryBSD: A New Desktop BSD Distribution)
-[#]: via: (https://itsfoss.com/furybsd/)
-[#]: author: (John Paul https://itsfoss.com/author/john/)
-
-Meet FuryBSD: A New Desktop BSD Distribution
-======
-
-In the last couple of months, a few new desktop BSD have been announced. There is [HyperbolaBSD which was Hyperbola GNU/Linux][1] previously. Another new entry in the [BSD][2] world is [FuryBSD][3].
-
-### FuryBSD: A new BSD distribution
-
-![][4]
-
-At its heart, FuryBSD is a very simple beast. According to [the site][5], “FuryBSD is a back to basics lightweight desktop distribution based on stock FreeBSD.” It is basically FreeBSD with a desktop environment pre-configured and several apps preinstalled. The goal is to quickly get a FreeBSD-based system running on your computer.
-
-You might be thinking that this sounds a lot like a couple of other BSDs that are available, such as [NomadBSD][6] and [GhostBSD][7]. The major difference between those BSDs and FuryBSD is that FuryBSD is much closer to stock FreeBSD. For example, FuryBSD uses the FreeBSD installer, while others have created their own installers and utilities.
-
-As it states on the [site][8], “Although FuryBSD may resemble past graphical BSD projects like PC-BSD and TrueOS, FuryBSD is created by a different team and takes a different approach focusing on tight integration with FreeBSD. This keeps overhead low and maintains compatibility with upstream.” The lead dev also told me that “One key focus for FuryBSD is for it to be a small live media with a few assistive tools to test drivers for hardware.”
-
-Currently, you can go to the [FuryBSD homepage][3] and download either an XFCE or KDE LiveCD. A GNOME version is in the works.
-
-### Who’s is Behind FuryBSD?
-
-The lead dev behind FuryBSD is [Joe Maloney][9]. Joe has been a FreeBSD user for many years. He contributed to other BSD projects, such as PC-BSD. He also worked with Eric Turgeon, the creator of GhostBSD, to rewrite the GhostBSD LiveCD. Along the way, he picked up a better understanding of BSD and started to form an idea of how he would make a distribution on his own.
-
-Joe is joined by several other devs who have also spent many years in the BSD world, such as Jaron Parsons, Josh Smith, and Damian Szidiropulosz.
-
-### The Future for FuryBSD
-
-At the moment, FuryBSD is nothing more than a pre-configured FreeBSD setup. However, the devs have a [list of improvements][5] that they want to make going forward. These include:
-
- * A sane framework for loading, 3rd party proprietary drivers graphics, wireless
- * Cleanup up the LiveCD experience a bit more to continue to make it more friendly
- * Printing support out of box
- * A few more default applications included to provide a complete desktop experience
- * Integrated [ZFS][10] replication tools for backup and restore
- * Live image persistence options
- * A custom pkg repo with sane defaults
- * Continuous integration for applications updates
- * Quality assurance for FreeBSD on the desktop
- * Tailored artwork, color scheming, and theming
- * Directory services integration
- * Security hardening
-
-
-
-The devs make it quite clear that any changes they make will have a lot of thought and research behind them. They don’t want to compliment a feature, only to have to remove it or change it when it breaks something.
-
-![FuryBSD desktop][11]
-
-### How You Can Help FuryBSD?
-
-At this moment the project is still very young. Since all projects need help to survive, I asked Joe what kind of help they were looking for. He said, “We could use help [answering questions on the forums][12], [GitHub][13] tickets, help with documentation are all needed.” He also said that if people wanted to add support for other desktop environments, pull requests are welcome.
-
-### Final Thoughts
-
-Although I have not tried it yet, I have a good feeling about FuryBSD. It sounds like the project is in capable hands. Joe Maloney has been thinking about how to make the best BSD desktop experience for over a decade. Unlike majority of Linux distros that are basically a rethemed Ubuntu, the devs behind FuryBSD know what they are doing and they are choosing quality over the fancy bells and whistles.
-
-What are your thoughts on this new entry into the every growing desktop BSD market? Have you tried out FuryBSD or will you give it a try? Please let us know in the comments below.
-
-If you found this article interesting, please take a minute to share it on social media, Hacker News or [Reddit][14].
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/furybsd/
-
-作者:[John Paul][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/john/
-[b]: https://github.com/lujun9972
-[1]: https://itsfoss.com/hyperbola-linux-bsd/
-[2]: https://itsfoss.com/bsd/
-[3]: https://www.furybsd.org/
-[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/01/fury-bsd.jpg?ssl=1
-[5]: https://www.furybsd.org/manifesto/
-[6]: https://itsfoss.com/nomadbsd/
-[7]: https://ghostbsd.org/
-[8]: https://www.furybsd.org/furybsd-video-overview-at-knoxbug/
-[9]: https://github.com/pkgdemon
-[10]: https://itsfoss.com/what-is-zfs/
-[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/FuryBSDS-desktop.jpg?resize=800%2C450&ssl=1
-[12]: https://forums.furybsd.org/
-[13]: https://github.com/furybsd
-[14]: https://reddit.com/r/linuxusersgroup
diff --git a/sources/tech/20200203 Give an old MacBook new life with Linux.md b/sources/tech/20200203 Give an old MacBook new life with Linux.md
deleted file mode 100644
index 99bddf8fab..0000000000
--- a/sources/tech/20200203 Give an old MacBook new life with Linux.md
+++ /dev/null
@@ -1,81 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (qianmingtian)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Give an old MacBook new life with Linux)
-[#]: via: (https://opensource.com/article/20/2/macbook-linux-elementary)
-[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
-
-Give an old MacBook new life with Linux
-======
-Elementary OS's latest release, Hera, is an impressive platform for
-resurrecting an outdated MacBook.
-![Coffee and laptop][1]
-
-When I installed Apple's [MacOS Mojave][2], it slowed my formerly reliable MacBook Air to a crawl. My computer, released in 2015, has 4GB RAM, an i5 processor, and a Broadcom 4360 wireless card, but Mojave proved too much for my daily driver—it made working with [GnuCash][3] impossible, and it whetted my appetite to return to Linux. I am glad I did, but I felt bad that I had this perfectly good MacBook lying around unused.
-
-I tried several Linux distributions on my MacBook Air, but there was always a gotcha. Sometimes it was the wireless card; another time, it was a lack of support for the touchpad. After reading some good reviews, I decided to try [Elementary OS][4] 5.0 (Juno). I [made a boot drive][5] with my USB creator and inserted it into the MacBook Air. I got to a live desktop, and the operating system recognized my Broadcom wireless chipset—I thought this just might work!
-
-I liked what I saw in Elementary OS; its [Pantheon][6] desktop is really great, and its look and feel are familiar to Apple users—it has a dock at the bottom of the display and icons that lead to useful applications. I liked the preview of what I could expect, so I decided to install it—and then my wireless disappeared. That was disappointing. I really liked Elementary OS, but no wireless is a non-starter.
-
-Fast-forward to December 2019, when I heard a review on the [Linux4Everyone][7] podcast about Elementary's latest release, v.5.1 (Hera) bringing a MacBook back to life. So, I decided to try again with Hera. I downloaded the ISO, created the bootable drive, plugged it in, and this time the operating system recognized my wireless card. I was in business!
-
-![MacBook Air with Hera][8]
-
-I was overjoyed that my very light, yet powerful MacBook Air was getting a new life with Linux. I have been exploring Elementary OS in greater detail, and I can tell you that I am impressed.
-
-### Elementary OS's features
-
-According to [Elementary's blog][9], "The newly redesigned login and lock screen greeter looks sharper, works better, and fixes many reported issues with the previous greeter including focus issues, HiDPI issues, and better localization. The new design in Hera was in response to user feedback from Juno, and enables some nice new features."
-
-"Nice new features" in an understatement—Elementary OS easily has one of the best-designed Linux user interfaces I have ever seen. A System Settings icon is on the dock by default; it is easy to change the settings, and soon I had the system configured to my liking. I need larger text sizes than the defaults, and the Universal Access controls are easy to use and allow me to set large text and high contrast. I can also adjust the dock with larger icons and other options.
-
-![Elementary OS's Settings screen][10]
-
-Pressing the Mac's Command key brings up a list of keyboard shortcuts, which is very helpful to new users.
-
-![Elementary OS's Keyboard shortcuts][11]
-
-Elementary OS ships with the [Epiphany][12] web browser, which I find quite easy to use. It's a bit different than Chrome, Chromium, or Firefox, but it is more than adequate.
-
-For security-conscious users (as we should all be), Elementary OS's Security and Privacy settings provide multiple options, including a firewall, history, locking, automatic deletion of temporary and trash files, and an on/off switch for location services.
-
-![Elementary OS's Privacy and Security screen][13]
-
-### More on Elementary OS
-
-Elementary OS was originally released in 2011, and its latest version, Hera, was released on December 3, 2019. [Cassidy James Blaede][14], Elementary's co-founder and CXO, is the operating system's UX architect. Cassidy loves to design and build useful, usable, and delightful digital products using open technologies.
-
-Elementary OS has excellent user [documentation][15], and its code (licensed under GPL 3.0) is available on [GitHub][16]. Elementary OS encourages involvement in the project, so be sure to reach out and [join the community][17].
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/macbook-linux-elementary
-
-作者:[Don Watkins][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/don-watkins
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_cafe_brew_laptop_desktop.jpg?itok=G-n1o1-o (Coffee and laptop)
-[2]: https://en.wikipedia.org/wiki/MacOS_Mojave
-[3]: https://www.gnucash.org/
-[4]: https://elementary.io/
-[5]: https://opensource.com/life/14/10/test-drive-linux-nothing-flash-drive
-[6]: https://opensource.com/article/19/12/pantheon-linux-desktop
-[7]: https://www.linux4everyone.com/20-macbook-pro-elementary-os
-[8]: https://opensource.com/sites/default/files/uploads/macbookair_hera.png (MacBook Air with Hera)
-[9]: https://blog.elementary.io/introducing-elementary-os-5-1-hera/
-[10]: https://opensource.com/sites/default/files/uploads/elementaryos_settings.png (Elementary OS's Settings screen)
-[11]: https://opensource.com/sites/default/files/uploads/elementaryos_keyboardshortcuts.png (Elementary OS's Keyboard shortcuts)
-[12]: https://en.wikipedia.org/wiki/GNOME_Web
-[13]: https://opensource.com/sites/default/files/uploads/elementaryos_privacy-security.png (Elementary OS's Privacy and Security screen)
-[14]: https://github.com/cassidyjames
-[15]: https://elementary.io/docs/learning-the-basics#learning-the-basics
-[16]: https://github.com/elementary
-[17]: https://elementary.io/get-involved
diff --git a/sources/tech/20200203 Troubleshoot Kubernetes with the power of tmux and kubectl.md b/sources/tech/20200203 Troubleshoot Kubernetes with the power of tmux and kubectl.md
deleted file mode 100644
index b9480960e6..0000000000
--- a/sources/tech/20200203 Troubleshoot Kubernetes with the power of tmux and kubectl.md
+++ /dev/null
@@ -1,169 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( guevaraya)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Troubleshoot Kubernetes with the power of tmux and kubectl)
-[#]: via: (https://opensource.com/article/20/2/kubernetes-tmux-kubectl)
-[#]: author: (Abhishek Tamrakar https://opensource.com/users/tamrakar)
-
-Troubleshoot Kubernetes with the power of tmux and kubectl
-======
-A kubectl plugin that uses tmux to make troubleshooting Kubernetes much
-simpler.
-![Woman sitting in front of her laptop][1]
-
-[Kubernetes][2] is a thriving open source container orchestration platform that offers scalability, high availability, robustness, and resiliency for applications. One of its many features is support for running custom scripts or binaries through its primary client binary, [kubectl][3]. Kubectl is very powerful and allows users to do anything with it that they could do directly on a Kubernetes cluster.
-
-### Troubleshooting Kubernetes with aliases
-
-Anyone who uses Kubernetes for container orchestration is aware of its features—as well as the complexity it brings because of its design. For example, there is an urgent need to simplify troubleshooting in Kubernetes with something that is quicker and has little need for manual intervention (except in critical situations).
-
-There are many scenarios to consider when it comes to troubleshooting functionality. In one scenario, you know what you need to run, but the command's syntax—even when it can run as a single command—is excessively complex, or it may need one or two inputs to work.
-
-For example, if you frequently need to jump into a running container in the System namespace, you may find yourself repeatedly writing:
-
-
-```
-`kubectl --namespace=kube-system exec -i -t `
-```
-
-To simplify troubleshooting, you could use command-line aliases of these commands. For example, you could add the following to your dotfiles (.bashrc or .zshrc):
-
-
-```
-`alias ksysex='kubectl --namespace=kube-system exec -i -t'`
-```
-
-This is one of many examples from a [repository of common Kubernetes aliases][4] that shows one way to simplify functions in kubectl. For something simple like this scenario, an alias is sufficient.
-
-### Switching to a kubectl plugin
-
-A more complex troubleshooting scenario involves the need to run many commands, one after the other, to investigate an environment and come to a conclusion. Aliases alone are not sufficient for this use
-
-case; you need repeatable logic and correlations between the many parts of your Kubernetes deployment. What you really need is automation to deliver the desired output in less time.
-
-Consider 10 to 20—or even 50 to 100—namespaces holding different microservices on your cluster. What would be helpful for you to start troubleshooting this scenario?
-
- * You would need something that can quickly tell which pod in which namespace is throwing errors.
- * You would need something that can watch logs of all the pods in a namespace.
- * You might also need to watch logs of certain pods in a specific namespace that have shown errors.
-
-
-
-Any solution that covers these points would be very useful in investigating production issues as well as during development and testing cycles.
-
-To create something more powerful than a simple alias, you can use [kubectl plugins][5]. Plugins are like standalone scripts written in any scripting language but are designed to extend the functionality of your main command when serving as a Kubernetes admin.
-
-To create a plugin, you must use the proper syntax of **kubectl-<your-plugin-name>** to copy the script to one of the exported pathways in your **$PATH** and give it executable permissions (**chmod +x**).
-
-After creating a plugin and moving it into your path, you can run it immediately. For example, I have kubectl-krawl and kubectl-kmux in my path:
-
-
-```
-$ kubectl plugin list
-The following compatible plugins are available:
-
-/usr/local/bin/kubectl-krawl
-/usr/local/bin/kubectl-kmux
-
-$ kubectl kmux
-```
-
-Now let's explore what this looks like when you power Kubernetes with tmux.
-
-### Harnessing the power of tmux
-
-[Tmux][6] is a very powerful tool that many sysadmins and ops teams rely on to troubleshoot issues related to ease of operability—from splitting windows into panes for running parallel debugging on multiple machines to monitoring logs. One of its major advantages is that it can be used on the command line or in automation scripts.
-
-I created [a kubectl plugin][7] that uses tmux to make troubleshooting much simpler. I will use annotations to walk through the logic behind the plugin (and leave it for you to go through the plugin's full code):
-
-
-```
-#NAMESPACE is namespace to monitor.
-#POD is pod name
-#Containers is container names
-
-# initialize a counter n to count the number of loop counts, later be used by tmux to split panes.
-n=0;
-
-# start a loop on a list of pod and containers
-while IFS=' ' read -r POD CONTAINERS
-do
-
- # tmux create the new window for each pod
- tmux neww $COMMAND -n $POD 2>/dev/null
-
- # start a loop for all containers inside a running pod
- for CONTAINER in ${CONTAINERS//,/ }
- do
-
- if [ x$POD = x -o x$CONTAINER = x ]; then
- # if any of the values is null, exit.
- warn "Looks like there is a problem getting pods data."
- break
- fi
-
- # set the command to execute
- COMMAND=”kubectl logs -f $POD -c $CONTAINER -n $NAMESPACE”
- # check tmux session
- if tmux has-session -t <session name> 2>/dev/null;
- then
- <set session exists>
- else
- <create session>
- fi
-
- # split planes in the current window for each containers
- tmux selectp -t $n \; \
- splitw $COMMAND \; \
- select-layout tiled \;
-
- # end loop for containers
- done
-
- # rename the window to identify by pod name
- tmux renamew $POD 2>/dev/null
-
- # increment the counter
- ((n+=1))
-
-# end loop for pods
-done< <(<fetch list of pod and containers from kubernetes cluster>)
-
-# finally select the window and attach session
- tmux selectw -t <session name>:1 \; \
- attach-session -t <session name>\;
-```
-
-After the plugin script runs, it will produce output similar to the image below. Each pod has its own window, and each container (if there is more than one) is split by the panes in its pod window, streaming logs as they arrive. The beauty of tmux can be seen below; with the proper configuration, you can even see which window has activity going on (see the white tabs).
-
-![Output of kmux plugin][8]
-
-### Conclusion
-
-Aliases are always helpful for simple troubleshooting in Kubernetes environments. When the environment gets more complex, a kubectl plugin is a powerful option for using more advanced scripting. There are no limits on which programming language you can use to write kubectl plugins. The only requirements are that the naming convention in the path is executable, and it doesn't have the same name as an existing kubectl command.
-
-To read the complete code or try the plugins I created, check my [kube-plugins-github][7] repository. Issues and pull requests are welcome.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/kubernetes-tmux-kubectl
-
-作者:[Abhishek Tamrakar][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/tamrakar
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_women_computing_4.png?itok=VGZO8CxT (Woman sitting in front of her laptop)
-[2]: https://opensource.com/resources/what-is-kubernetes
-[3]: https://kubernetes.io/docs/reference/kubectl/overview/
-[4]: https://github.com/ahmetb/kubectl-aliases/blob/master/.kubectl_aliases
-[5]: https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/
-[6]: https://opensource.com/article/19/6/tmux-terminal-joy
-[7]: https://github.com/abhiTamrakar/kube-plugins
-[8]: https://opensource.com/sites/default/files/uploads/kmux-output.png (Output of kmux plugin)
diff --git a/sources/tech/20200204 DevOps vs Agile- What-s the difference.md b/sources/tech/20200204 DevOps vs Agile- What-s the difference.md
deleted file mode 100644
index ec49c22c92..0000000000
--- a/sources/tech/20200204 DevOps vs Agile- What-s the difference.md
+++ /dev/null
@@ -1,170 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (DevOps vs Agile: What's the difference?)
-[#]: via: (https://opensource.com/article/20/2/devops-vs-agile)
-[#]: author: (Taz Brown https://opensource.com/users/heronthecli)
-
-DevOps vs Agile: What's the difference?
-======
-The difference between the two is what happens after development.
-![Pair programming][1]
-
-Early on, software development didn't really fit under a particular management umbrella. Then along came [waterfall][2], which spoke to the idea that software development could be defined by the length of time an application took to create or build.
-
-Back then, it often took long periods of time to create, test, and deploy software because there were no checks and balances during the development process. The results were poor software quality with defects and bugs and unmet timelines. The focus was on long, drawn-out plans for software projects.
-
-Waterfall projects have been associated with the [triple constraint][3] model, which is also called the project management triangle. Each side of the triangle represents a component of the triple constraints of project management: **scope**, **time**, and **cost**. As [Angelo Baretta writes][4], the triple constraint model "says that cost is a function of time and scope, that these three factors are related in a defined and predictable way… [I]f we want to shorten the schedule (time), we must increase cost. It says that if we want to increase scope, we must increase cost or schedule."
-
-### Transitioning from waterfall to agile
-
-Waterfall came from manufacturing and engineering, where a linear process makes sense; you build the wall before you build the roof. Similarly, software development problems were viewed as something that could be solved with planning. From beginning to end, the development process was clearly defined by a roadmap that would lead to the final delivery of a product.
-
-Eventually, waterfall was recognized as detrimental and counterintuitive to software development because, often, the value could not be determined until the very end of the project cycle, and in many cases, the projects failed. Also, the customer didn't get to see any working software until the end of the project.
-
-Agile takes a different approach that moves away from planning the entire project, committing to estimated dates, and being accountable to a plan. Rather, agile assumes and embraces uncertainty. It is built around the idea of responding to change instead of charging past it or ignoring the need for it. Instead, change is considered as a way to fulfill the needs of the customer.
-
-### Agile values
-
-Agile is governed by the Agile Manifesto, which defines [12 principles][5]:
-
- 1. Satisfying the customer is the top priority
- 2. Welcome changing requirements, even late in development
- 3. Deliver working software frequently
- 4. Development and business must work together
- 5. Build projects around motivated people
- 6. Face-to-face communication is the most efficient and effective method of conveying information
- 7. The primary measure of success is working software
- 8. Agile processes promote sustainable development
- 9. Maintain continuous attention to technical excellence and good design
- 10. Simplicity is essential
- 11. The best architectures, requirements, and designs emerge from self-organizing teams
- 12. Regularly reflect on work, then tune and adjust behavior
-
-
-
-Agile's four [core values][6] are:
-
- * **Individuals and interactions** over processes and tools
- * **Working software** over comprehensive documentation
- * **Customer collaboration** over contract negotiation
- * **Responding to change** over following a plan
-
-
-
-This contrasts with waterfall's rigid planning style. In agile, the customer is a member of the development team rather than engaging only at the beginning, when setting business requirements, and at the end, when reviewing the final product (as in waterfall). The customer helps the team write the [acceptance criteria][7] and remains engaged throughout the process. In addition, agile requires changes and continuous improvement throughout the organization. The development team works with other teams, including the project management office and the testers. What gets done and when are led by a designated role and agreed to by the team as a whole.
-
-### Agile software development
-
-Agile software development requires adaptive planning, evolutionary development, and delivery. Many software development methodologies, frameworks, and practices fall under the umbrella of being agile, including:
-
- * Scrum
- * Kanban (visual workflow)
- * XP (eXtreme Programming)
- * Lean
- * DevOps
- * Feature-driven development (FDD)
- * Test-driven development (TDD)
- * Crystal
- * Dynamic systems development method (DSDM)
- * Adaptive software development (ASD)
-
-
-
-All of these have been used on their own or in combination for developing and deploying software. The most common are [scrum, kanban][8] (or the combination called scrumban), and DevOps.
-
-[Scrum][9] is a framework under which a team, generally consisting of a scrum master, product owner, and developers, operates cross-functionally and in a self-directed manner to increase the speed of software delivery and
-
-to bring greater business value to the customer. The focus is on faster iterations with smaller [increments][10].
-
-[Kanban][11] is an agile framework, sometimes called a workflow management system, that helps teams visualize their work and maximize efficiency (thus being agile). Kanban is usually represented by a digital or physical board. A team's work moves across the board, for example, from not started, to in progress, testing, and finished, as it progresses. Kanban allows each team member to see the state of all work at any time.
-
-### DevOps values
-
-DevOps is a culture, a state of mind, a way that software development or infrastructure is, and a way that software and applications are built and deployed. There is no wall between development and operations; they work simultaneously and without silos.
-
-DevOps is based on two other practice areas: lean and agile. DevOps is not a title or role within a company; it's really a commitment that an organization or team makes to continuous delivery, deployment, and integration. According to [Gene Kim][12], author of _The Phoenix Project_ and _The Unicorn Project_, there are three "ways" that define the principles of DevOps:
-
- * The First Way: Principles of flow
- * The Second Way: Principles of feedback
- * The Third Way: Principles of continuous learning
-
-
-
-### DevOps software development
-
-DevOps does not happen in a vacuum; it is a flexible practice that, in its truest form, is a shared culture and mindset around software development and IT or infrastructure implementation.
-
-When you think of automation, cloud, microservices, you think of DevOps. In an [interview][13], _Accelerate: Building and Scaling High Performing Technology Organizations_ authors Nicole Forsgren, Jez Humble, and Gene Kim explained:
-
-> * Software delivery performance matters, and it has a significant impact on organizational outcomes such as profitability, market share, quality, customer satisfaction, and achieving organizational and mission goals.
-> * High performers achieve levels of throughput, stability, and quality; they're not trading off to achieve these attributes.
-> * You can improve your performance by implementing practices from the lean, agile, and DevOps playbooks.
-> * Implementing these practices and capabilities also has an impact on your organizational culture, which in turn has an impact on both your software delivery performance and organizational performance.
-> * There's still lots of work to do to understand how to improve performance.
->
-
-
-### DevOps vs. agile
-
-Despite their similarities, DevOps and agile are not the same, and some argue that DevOps is better than agile. To eliminate the confusion, it's important to get down to the nuts and bolts.
-
-#### Similarities
-
- * Both are software development methodologies; there is no disputing this.
- * Agile has been around for over 20 years, and DevOps came into the picture fairly recently.
- * Both believe in fast software development, and their principles are based on how fast software can be developed without causing harm to the customer or operations.
-
-
-
-#### Differences
-
- * **The difference between the two** is what happens after development.
- * Software development, testing, and deployment happen in both DevOps and agile. However, pure agile tends to stop after these three stages. In contrast, DevOps includes operations, which happen continually. Therefore, monitoring and software development are also continuous.
- * In agile, separate people are responsible for developing, testing, and deploying the software. In DevOps, the DevOps engineering role is are responsible for everything; development is operations, and operations is development.
- * DevOps is more associated with cost-cutting, and agile is more synonymous with lean and reducing waste, and concepts like agile project accounting and minimum viable product (MVP) are relevant.
- * Agile focuses on and embodies empiricism (**adaptation**, **transparency**, and **inspection**) instead of predictive measures.
-
-Agile | DevOps
----|---
-Feedback from customer | Feedback from self
-Smaller release cycles | Smaller release cycles, immediate feedback
-Focus on speed | Focus on speed and automation
-Not the best for business | Best for business
-
-### Wrapping up
-
-Agile and DevOps are distinct, although their similarities lead people to think they are one and the same. This does both agile and DevOps a disservice.
-
-In my experience as an agilist, I have found it valuable for organizations and teams to understand—from a high level—what agile and DevOps are and how they aid teams in working faster and more efficiently, delivering quality faster, and improving customer satisfaction.
-
-Agile and DevOps are not adversarial in any way (or at least the intent is not there). They are more allies than enemies in the agile revolution. Agile and DevOps can operate exclusively and inclusively, which allows both to exist in the same space.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/devops-vs-agile
-
-作者:[Taz Brown][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/heronthecli
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/collab-team-pair-programming-code-keyboard.png?itok=kBeRTFL1 (Pair programming)
-[2]: http://www.agilenutshell.com/agile_vs_waterfall
-[3]: https://en.wikipedia.org/wiki/Project_management_triangle
-[4]: https://www.pmi.org/learning/library/triple-constraint-erroneous-useless-value-8024
-[5]: https://agilemanifesto.org/principles.html
-[6]: https://agilemanifesto.org/
-[7]: https://www.productplan.com/glossary/acceptance-criteria/
-[8]: https://opensource.com/article/19/8/scrum-vs-kanban
-[9]: https://www.scrum.org/
-[10]: https://www.scrum.org/resources/what-is-an-increment
-[11]: https://www.atlassian.com/agile/kanban
-[12]: https://itrevolution.com/the-unicorn-project/
-[13]: https://www.infoq.com/articles/book-review-accelerate/
diff --git a/sources/tech/20200206 3 ways to use PostgreSQL commands.md b/sources/tech/20200206 3 ways to use PostgreSQL commands.md
deleted file mode 100644
index 645baf65e0..0000000000
--- a/sources/tech/20200206 3 ways to use PostgreSQL commands.md
+++ /dev/null
@@ -1,230 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (Morisun029)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (3 ways to use PostgreSQL commands)
-[#]: via: (https://opensource.com/article/20/2/postgresql-commands)
-[#]: author: (Greg Pittman https://opensource.com/users/greg-p)
-
-3 ways to use PostgreSQL commands
-======
-Whether you need something simple, like a shopping list, or complex,
-like a color swatch generator, PostgreSQL commands make it easy.
-![Team checklist and to dos][1]
-
-In _[Getting started with PostgreSQL][2]_, I explained how to install, set up, and begin using the open source database software. But there's a lot more you can do with commands in [PostgreSQL][3].
-
-For example, I use Postgres to keep track of my grocery shopping list. I do most of the grocery shopping in our home, and the bulk of it happens once a week. I go to several places to buy the things on my list because each store offers a particular selection or quality or maybe a better price. Initially, I made an HTML form page to manage my shopping list, but it couldn't save my entries. So, I had to wait to make my list all at once, and by then I usually forgot some items we need or I want.
-
-Instead, with PostgreSQL, I can enter bits when I think of them as the week goes on and print out the whole thing right before I go shopping. Here's how you can do that, too.
-
-### Create a simple shopping list
-
-First, enter the database with the **psql **command, then create a table for your list with:
-
-
-```
-`Create table groc (item varchar(20), comment varchar(10));`
-```
-
-Type commands like the following to add items to your list:
-
-
-```
-insert into groc values ('milk', 'K');
-insert into groc values ('bananas', 'KW');
-```
-
-There are two pieces of information (separated by a comma) inside the parentheses: the item you want to buy and letters indicating where you want to buy it and whether it's something you usually buy every week (W).
-
-Since **psql** has a history, you can press the Up arrow and edit the data between the parentheses instead of having to type the whole line for each item.
-
-After entering a handful of items, check what you've entered with:
-
-
-```
-Select * from groc order by comment;
-
- item | comment
-\----------------+---------
- ground coffee | H
- butter | K
- chips | K
- steak | K
- milk | K
- bananas | KW
- raisin bran | KW
- raclette | L
- goat cheese | L
- onion | P
- oranges | P
- potatoes | P
- spinach | PW
- broccoli | PW
- asparagus | PW
- cucumber | PW
- sugarsnap peas | PW
- salmon | S
-(18 rows)
-```
-
-This command orders the results by the _comment_ column so that the items are grouped by where you buy them to make it easier to shop.
-
-By using a W to indicate your weekly purchases, you can keep your weekly items on the list when you clear out the table to prepare for the next week's list. To so that, enter:
-
-
-```
-`delete from groc where comment not like '%W';`
-```
-
-Notice that in PostgreSQL, **%** is the wildcard character (instead of an asterisk). So, to save typing, you might type:
-
-
-```
-`delete from groc where item like 'goat%';`
-```
-
-You can't use **item = 'goat%'**; it won't work.
-
-When you're ready to shop, output your list to print it or send it to your phone with:
-
-
-```
-\o groclist.txt
-select * from groc order by comment;
-\o
-```
-
-The last command, **\o**, with nothing afterward, resets the output to the command line. Otherwise, all output will continue to go to the groc file you created.
-
-### Analyze complex tables
-
-This item-by-item entry may be okay for short tables, but what about really big ones? A couple of years ago, I was helping the team at [FreieFarbe.de][4] to create a swatchbook of the free colors (freieFarbe means "free colors" in German) from its HLC color palette, where virtually any imaginable print color can be specified by its hue, luminosity (brightness), and chroma (saturation). The result was the [HLC Color Atlas][5], and here's how we did it.
-
-The team sent me files with color specifications so I could write Python scripts that would work with Scribus to generate the swatchbooks of color patches easily. One example started like:
-
-
-```
-HLC, C, M, Y, K
-H010_L15_C010, 0.5, 49.1, 0.1, 84.5
-H010_L15_C020, 0.0, 79.7, 15.1, 78.9
-H010_L25_C010, 6.1, 38.3, 0.0, 72.5
-H010_L25_C020, 0.0, 61.8, 10.6, 67.9
-H010_L25_C030, 0.0, 79.5, 18.5, 62.7
-H010_L25_C040, 0.4, 94.2, 17.3, 56.5
-H010_L25_C050, 0.0, 100.0, 15.1, 50.6
-H010_L35_C010, 6.1, 32.1, 0.0, 61.8
-H010_L35_C020, 0.0, 51.7, 8.4, 57.5
-H010_L35_C030, 0.0, 68.5, 17.1, 52.5
-H010_L35_C040, 0.0, 81.2, 22.0, 46.2
-H010_L35_C050, 0.0, 91.9, 20.4, 39.3
-H010_L35_C060, 0.1, 100.0, 17.3, 31.5
-H010_L45_C010, 4.3, 27.4, 0.1, 51.3
-```
-
-This is slightly modified from the original, which separated the data with tabs. I transformed it into a CSV (comma-separated value) file, which I prefer to use with Python. (CSV files are also very useful because they can be imported easily into a spreadsheet program.)
-
-In each line, the first item is the color name, and it's followed by its C, M, Y, and K color values. The file consisted of 1,793 colors, and I wanted a way to analyze the information to get a sense of the range of values. This is where PostgreSQL comes into play. I did not want to enter all of this data manually—I don't think I could without errors (and headaches). Fortunately, PostgreSQL has a command for this.
-
-My first step was to create the database with:
-
-
-```
-`Create table hlc_cmyk (color varchar(40), c decimal, m decimal, y decimal, k decimal);`
-```
-
-Then I brought in the data with:
-
-
-```
-`\copy hlc_cmyk from '/home/gregp/HLC_Atlas_CMYK_SampleData.csv' with (header, format CSV);`
-```
-
-The backslash at the beginning is there because using the plain **copy** command is restricted to root and the Postgres superuser. In the parentheses, **header** means the first line contains headings and should be ignored, and **CSV** means the file format is CSV. Note that parentheses are not required around the color name in this method.
-
-If the operation is successful, I see a message that says **COPY NNNN**, where the N's refer to the number of rows inserted into the table.
-
-Finally, I can query the table with:
-
-
-```
-select * from hlc_cmyk;
-
- color | c | m | y | k
-\---------------+-------+-------+-------+------
- H010_L15_C010 | 0.5 | 49.1 | 0.1 | 84.5
- H010_L15_C020 | 0.0 | 79.7 | 15.1 | 78.9
- H010_L25_C010 | 6.1 | 38.3 | 0.0 | 72.5
- H010_L25_C020 | 0.0 | 61.8 | 10.6 | 67.9
- H010_L25_C030 | 0.0 | 79.5 | 18.5 | 62.7
- H010_L25_C040 | 0.4 | 94.2 | 17.3 | 56.5
- H010_L25_C050 | 0.0 | 100.0 | 15.1 | 50.6
- H010_L35_C010 | 6.1 | 32.1 | 0.0 | 61.8
- H010_L35_C020 | 0.0 | 51.7 | 8.4 | 57.5
- H010_L35_C030 | 0.0 | 68.5 | 17.1 | 52.5
-```
-
-It goes on like this for all 1,793 rows of data. In retrospect, I can't say that this query was absolutely necessary for the HLC and Scribus task, but it allayed some of my anxieties about the project.
-
-To generate the HLC Color Atlas, I automated creating the color charts with Scribus for the 13,000+ colors in those pages of color swatches.
-
-I could have used the **copy** command to output my data:
-
-
-```
-`\copy hlc_cmyk to '/home/gregp/hlc_cmyk_backup.csv' with (header, format CSV);`
-```
-
-I also could restrict the output according to certain values with a **where** clause.
-
-For example, the following command will only send the table values for the hues that begin with H10.
-
-
-```
-`\copy hlc_cmyk to '/home/gregp/hlc_cmyk_backup.csv' with (header, format CSV) where color like 'H10%';`
-```
-
-### Back up or transfer a database or table
-
-The final command I will mention here is **pg_dump**, which is used to back up a PostgreSQL database and runs outside of the **psql** console. For example:
-
-
-```
-pg_dump gregp -t hlc_cmyk > hlc.out
-pg_dump gregp > dball.out
-```
-
-The first line exports the **hlc_cmyk** table along with its structure. The second line dumps all the tables inside the **gregp** database. This is very useful for backing up or transferring a database or tables.
-
-To transfer a database or table to another computer, first, create a database on the other computer (see my "[getting started][2]" article for details), then do the reverse process:
-
-
-```
-`psql -d gregp -f dball.out`
-```
-
-This creates all the tables and enters the data in one step.
-
-### Conclusion
-
-In this article, we have seen how to use the **WHERE** parameter to restrict operations, along with the use of the PostgreSQL wildcard character **%**. We've also seen how to load a large amount of data into a table, then output some or all of the table data to a file, or even your entire database with all its individual tables.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/postgresql-commands
-
-作者:[Greg Pittman][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/greg-p
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/todo_checklist_team_metrics_report.png?itok=oB5uQbzf (Team checklist and to dos)
-[2]: https://opensource.com/article/19/11/getting-started-postgresql
-[3]: https://www.postgresql.org/
-[4]: http://freiefarbe.de
-[5]: https://www.freiefarbe.de/en/thema-farbe/hlc-colour-atlas/
diff --git a/sources/tech/20200207 Customize your internet with an open source search engine.md b/sources/tech/20200207 Customize your internet with an open source search engine.md
deleted file mode 100644
index 7974fdbfa8..0000000000
--- a/sources/tech/20200207 Customize your internet with an open source search engine.md
+++ /dev/null
@@ -1,118 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Customize your internet with an open source search engine)
-[#]: via: (https://opensource.com/article/20/2/open-source-search-engine)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Customize your internet with an open source search engine
-======
-Get started with YaCy, an open source, P2P web indexer.
-![Person using a laptop][1]
-
-A long time ago, the internet was small enough to be indexed by a few people who gathered the names and locations of all websites and listed them each by topic on a page or in a printed book. As the World Wide Web network grew, the "web rings" convention developed, in which sites with a similar theme or topic or sensibility banded together to form a circular path to each member. A visitor to any site in the ring could click a button to proceed to the next or previous site in the ring to discover new sites relevant to their interest.
-
-Then for a while, it seemed the internet outgrew itself. Everyone was online, there was a lot of redundancy and spam, and there was no way to find anything. Yahoo and AOL and CompuServe and similar services had unique approaches, but it wasn't until Google came along that the modern model took hold. According to Google, the internet was meant to be indexed, sorted, and ranked through a search engine.
-
-### Why choose an open source alternative?
-
-Search engines like Google and DuckDuckGo are demonstrably effective. You may have reached this site through a search engine. While there's a debate to be had about content falling through the cracks because a host chooses not to follow best practices for search engine optimization, the modern solution for managing the wealth of culture and knowledge and frivolity that is the internet is relentless indexing.
-
-But maybe you prefer not to use Google or DuckDuckGo because of privacy concerns or because you're looking to contribute to an effort to make the internet more independent. If that appeals to you, then consider participating in [YaCy][2], the peer-to-peer internet indexer and search engine.
-
-### Install YaCy
-
-To install and try YaCy, first ensure you have Java installed. If you're on Linux, you can follow the instructions in my [_How to install Java on Linux_][3] article. If you're on Windows or MacOS, obtain an installer from [AdoptOpenJDK.net][4].
-
-Once you have Java installed, [download the installer][5] for your platform.
-
-If you're on Linux, unarchive the tarball and move it to the **/opt** directory:
-
-
-```
-`$ sudo tar --extract --file yacy_*z --directory /opt`
-```
-
-Start YaCy according to instructions for the installer you downloaded.
-
-On Linux, start YaCy running in the background:
-
-
-```
-`$ /opt/startYACY.sh &`
-```
-
-In a web browser, navigate to **localhost:8090** and search.
-
-![YaCy start page][6]
-
-### Add YaCy to your URL bar
-
-If you're using the Firefox web browser, you can make YaCy your default search engine in the Awesome Bar (that's Mozilla's name for the URL field) with just a few clicks.
-
-First, make the dedicated search bar visible in the Firefox toolbar, if it's not already (you don't have to keep the search bar visible; you only need it active long enough to add a custom search engine). The search bar is available in the hamburger menu in the upper-right corner of Firefox in the **Customize** menu. Once the search bar is visible in your Firefox toolbar, navigate to **localhost:8090**, and click the magnifying glass icon in the Firefox search bar you just added. Click the option to add YaCy to your Firefox search engines.
-
-![Adding YaCy to Firefox][7]
-
-Once this is done, you can mark it as your default in Firefox preferences, or just use it selectively in searches performed in the Firefox search bar. If you set it as your default search engine, then you may have no need for the dedicated search bar because the default engine is also used by the Awesome Bar, so you can remove it from your toolbar.
-
-### How to a P2P search engine works
-
-YaCy is an open source and distributed search engine. It's written in [Java][8], so it runs on any platform, and it performs web crawls, indexing, and searching. It's a peer-to-peer (P2P) network, so every user running YaCy joins in the effort to track the internet as it changes from day to day. Of course, no single user possesses a full index of the entire internet because that would take a data center to house, but the index is distributed and redundant across all YaCy users. It's a lot like BitTorrent (as it uses distributed hash tables, or DHT, to reference index entries), except the data you're sharing is a matrix of words and URL associations. By mixing the results returned by the hash tables, no one can tell who has searched for what words, so all searches are functionally anonymous. It's an effective system for unbiased, ad-free, untracked, and anonymous searches, and you can join in just by using it.
-
-### Search engines and algorithms
-
-The act of indexing the internet refers to separating a web page into the singular words on it, then associating the page's URL with each word. Searching for one or more words in a search engine fetches all URLs associated with the query. That's one thing the YaCy client does while running.
-
-The other thing the client does is provide a search interface for your browser. Instead of navigating to Google when you want to search, you can point your web browser to **localhost:8090** to search YaCy. You may even be able to add it to your browser's search bar (depending on your browser's extensibility), so you can search from the URL bar.
-
-### Firewall settings for YaCy
-
-When you first start using YaCy, it's probably running in "junior" mode. This means that the sites your client crawls are available only to you because no other YaCy client can reach your index entries. To join the P2P experience, you must open port 8090 in your router's firewall and possibly your software firewall if you're running one. This is called "senior" mode.
-
-If you're on Linux, you can find out more about your computer's firewall in [_Make Linux stronger with firewalls_][9]. On other platforms, refer to your operating system's documentation.
-
-A firewall is almost always active on the router provided by your internet service provider (ISP), and there are far too many varieties of them to document accurately here. Most routers provide the option to "poke a hole" in your firewall because many popular networked games require two-way traffic.
-
-If you know how to log into your router (it's often either 192.168.0.1 or 10.1.0.1, but can vary depending on the manufacturer's settings), then log in and look for a configuration panel controlling the _firewall_ or _port forwarding_ or _applications_.
-
-Once you find the preferences for your router's firewall, add port 8090 to the whitelist. For example:
-
-![Adding YaCy to an ISP router][10]
-
-If your router is doing port forwarding, then you must forward the incoming traffic to your computer's IP address, using the same port. For example:
-
-![Adding YaCy to an ISP router][11]
-
-If you can't adjust your firewall settings for any reason, that's OK. YaCy will continue to run and operate as a client of the P2P search network in junior mode.
-
-### An internet of your own
-
-There's much more you can do with the YaCy search engine than just search passively. You can force crawls of underrepresented websites, you can request the network crawl a site, you can choose to use YaCy for just on-premises searches, and much more. You have better control over what _your_ internet looks like. The more senior users there are, the more sites indexed. The more sites indexed, the better the experience for all users. Join in!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/open-source-search-engine
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
-[2]: https://yacy.net/
-[3]: https://opensource.com/article/19/11/install-java-linux
-[4]: https://adoptopenjdk.net/releases.html
-[5]: https://yacy.net/download_installation/
-[6]: https://opensource.com/sites/default/files/uploads/yacy-startpage.jpg (YaCy start page)
-[7]: https://opensource.com/sites/default/files/uploads/yacy-add-firefox.jpg (Adding YaCy to Firefox)
-[8]: https://opensource.com/resources/java
-[9]: https://opensource.com/article/19/7/make-linux-stronger-firewalls
-[10]: https://opensource.com/sites/default/files/uploads/router-add-app.jpg (Adding YaCy to an ISP router)
-[11]: https://opensource.com/sites/default/files/uploads/router-add-app1.jpg (Adding YaCy to an ISP router)
diff --git a/sources/tech/20200207 NVIDIA-s Cloud Gaming Service GeForce NOW Shamelessly Ignores Linux.md b/sources/tech/20200207 NVIDIA-s Cloud Gaming Service GeForce NOW Shamelessly Ignores Linux.md
deleted file mode 100644
index c225522379..0000000000
--- a/sources/tech/20200207 NVIDIA-s Cloud Gaming Service GeForce NOW Shamelessly Ignores Linux.md
+++ /dev/null
@@ -1,82 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (geekpi)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (NVIDIA’s Cloud Gaming Service GeForce NOW Shamelessly Ignores Linux)
-[#]: via: (https://itsfoss.com/geforce-now-linux/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-NVIDIA’s Cloud Gaming Service GeForce NOW Shamelessly Ignores Linux
-======
-
-NVIDIA’s [GeForce NOW][1] cloud gaming service is something promising for gamers who probably don’t have the hardware but want to experience the latest and greatest games with the best possible experience using GeForce NOW (stream the game online and play it on any device you want).
-
-The service was limited to a few users (in the form of the waitlist) to access. However, recently, they announced that [GeForce NOW is open to all][2]. But, it really isn’t.
-
-Interestingly, it’s **not available for all the regions** across the globe. And, worse- **GeForce NOW does not support Linux**.
-
-![][3]
-
-### GeForce NOW is Not ‘Open For All’
-
-The whole point of making a subscription-based cloud service to play games is to eliminate platform dependence.
-
-Just like you would normally visit a website using a web browser – you should be able to stream a game on every platform. That’s the concept, right?
-
-![][4]
-
-Well, that’s definitely not rocket science – but NVIDIA still missed supporting Linux (and iOS)?
-
-### Is it because no one uses Linux?
-
-I would strongly disagree with this – even if it’s the reason for some to not support Linux. If that was the case, I wouldn’t be writing for It’s FOSS while using Linux as my primary desktop OS.
-
-Not just that – why do you think a Twitter user mentioned the lack of support for Linux if it wasn’t a thing?
-
-![][5]
-
-Yes, maybe the userbase isn’t large enough but while considering this as a cloud-based service – it doesn’t make sense to **not support Linux**.
-
-Technically, if no one games on Linux, **Valve** wouldn’t have noticed Linux as a platform to improve [Steam Play][6] to help more users play Windows-only games on Linux.
-
-I don’t want to claim anything that’s not true – but the desktop Linux scene is evolving faster than ever for gaming (even if the stats are low when compared to Windows and Mac).
-
-### Cloud gaming isn’t supposed to work like this
-
-![][7]
-
-As I mentioned above, it isn’t tough to find Linux gamers using Steam Play. It’s just that you’ll find the overall “market share” of gamers on Linux to be less than its counterparts.
-
-Even though that’s a fact – cloud gaming isn’t supposed to depend on a specific platform. And, considering that the GeForce NOW is essentially a browser-based streaming service to play games, it shouldn’t be tough for a big shot like NVIDIA to support Linux.
-
-Come on, team green – _you want us to believe that supporting Linux is technically tough_? Or, you just want to say that i_t’s not worth supporting the Linux platform_?
-
-**Wrapping Up**
-
-No matter how excited I was for the GeForce NOW service to launch – it was very disappointing to see that it does not support Linux at all.
-
-If cloud gaming services like GeForce NOW start supporting Linux in the near future – **you probably won’t need a reason to use Windows** (*coughs*).
-
-What do you think about it? Let me know your thoughts in the comments below.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/geforce-now-linux/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://www.nvidia.com/en-us/geforce-now/
-[2]: https://blogs.nvidia.com/blog/2020/02/04/geforce-now-pc-gaming/
-[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/nvidia-geforce-now-linux.jpg?ssl=1
-[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/nvidia-geforce-now.png?ssl=1
-[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/geforce-now-twitter-1.jpg?ssl=1
-[6]: https://itsfoss.com/steam-play/
-[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/ge-force-now.jpg?ssl=1
diff --git a/sources/tech/20200207 What is WireGuard- Why Linux Users Going Crazy Over it.md b/sources/tech/20200207 What is WireGuard- Why Linux Users Going Crazy Over it.md
deleted file mode 100644
index f80298dbb7..0000000000
--- a/sources/tech/20200207 What is WireGuard- Why Linux Users Going Crazy Over it.md
+++ /dev/null
@@ -1,98 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (What is WireGuard? Why Linux Users Going Crazy Over it?)
-[#]: via: (https://itsfoss.com/wireguard/)
-[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
-
-What is WireGuard? Why Linux Users Going Crazy Over it?
-======
-
-From normal Linux users to Linux creator [Linus Torvalds][1], everyone is in awe of WireGuard. What is WireGuard and what makes it so special?
-
-### What is WireGuard?
-
-![][2]
-
-[WireGuard][3] is an easy to configure, fast, and secure open source [VPN][4] that utilizes state-of-the-art cryptography. It’s aim is to provide a faster, simpler and leaner general purpose VPN that can be easily deployed on low-end devices like Raspberry Pi to high-end servers.
-
-Most of the other solutions like [IPsec][5] and OpenVPN were developed decades ago. Security researcher and kernel developer Jason Donenfeld realized that they were slow and difficult to configure and manage properly.
-
-This made him create a new open source VPN protocol and solution which is faster, secure easier to deploy and manage.
-
-WireGuard was originally developed for Linux but it is now available for Windows, macOS, BSD, iOS and Android. It is still under heavy development.
-
-### Why is WireGuard so popular?
-
-![][6]
-
-Apart from being a cross-platform, one of the biggest plus point for WireGuard is the ease of deployment. Configuring and deploying WireGuard is as easy as configuring and using SSH.
-
-Look at [WireGuard set up guide][7]. You install WireGuard, generate public and private keys (like SSH), set up firewall rules and start the service. Now compare it to the [OpenVPN set up guide][8]. There are way too many things to do here.
-
-Another good thing about WireGuard is that it has a lean codebase with just 4000 lines of code. Compare it to 100,000 lines of code of [OpenVPN][9] (another popular open source VPN). It is clearly easier to debug WireGuard.
-
-Don’t go by its simplicity. WireGuard supports all the state-of-the-art cryptography like like the [Noise protocol framework][10], [Curve25519][11], [ChaCha20][12], [Poly1305][13], [BLAKE2][14], [SipHash24][15], [HKDF][16], and secure trusted constructions.
-
-Since WireGuard runs in the [kernel space][17], it provides secure networking at a high speed.
-
-These are some of the reasons why WireGuard has become increasingly popular. Linux creator Linus Torvalds loves WireGuard so much that he is merging it in the [Linux Kernel 5.6][18]:
-
-> Can I just once again state my love for it and hope it gets merged soon? Maybe the code isn’t perfect, but I’ve skimmed it, and compared to the horrors that are OpenVPN and IPSec, it’s a work of art.
->
-> Linus Torvalds
-
-### If WireGuard is already available, then what’s the fuss about including it in Linux kernel?
-
-This could be confusing to new Linux users. You know that you can install and configure a WireGuard VPN server on Linux but then you also read the news that Linux Kernel 5.6 is going to include WireGuard. Let me explain it to you.
-
-At present, you can install WireGuard on Linux as a [kernel module][19]. Regular applications like VLC, GIMP etc are installed on top of the Linux kernel (in [user space][20]), not inside it.
-
-When you install WireGuard as a kernel module, you are basically modifying the Linux kernel on your own and add some code to it. Starting kernel 5.6, you won’t need manually add the kernel module. It will be included in the kernel by default.
-
-The inclusion of WireGuard in Kernel 5.6 will most likely [extend the adoption of WireGuard and thus change the current VPN scene][21].
-
-**Conclusion**
-
-WireGuard is gaining popularity for the good reasons. Some of the popular [privacy focused VPNs][22] like [Mullvad VPN][23] are already using WireGuard and the adoption is likely to grow in the near future.
-
-I hope you have a slightly better understanding of WireGuard. Your feedback is welcome, as always.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/wireguard/
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[b]: https://github.com/lujun9972
-[1]: https://itsfoss.com/linus-torvalds-facts/
-[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/wireguard.png?ssl=1
-[3]: https://www.wireguard.com/
-[4]: https://en.wikipedia.org/wiki/Virtual_private_network
-[5]: https://en.wikipedia.org/wiki/IPsec
-[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/wireguard-logo.png?ssl=1
-[7]: https://www.linode.com/docs/networking/vpn/set-up-wireguard-vpn-on-ubuntu/
-[8]: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04
-[9]: https://openvpn.net/
-[10]: https://noiseprotocol.org/
-[11]: https://cr.yp.to/ecdh.html
-[12]: https://cr.yp.to/chacha.html
-[13]: https://cr.yp.to/mac.html
-[14]: https://blake2.net/
-[15]: https://131002.net/siphash/
-[16]: https://eprint.iacr.org/2010/264
-[17]: http://www.linfo.org/kernel_space.html
-[18]: https://itsfoss.com/linux-kernel-5-6/
-[19]: https://wiki.archlinux.org/index.php/Kernel_module
-[20]: http://www.linfo.org/user_space.html
-[21]: https://www.zdnet.com/article/vpns-will-change-forever-with-the-arrival-of-wireguard-into-linux/
-[22]: https://itsfoss.com/best-vpn-linux/
-[23]: https://mullvad.net/en/
diff --git a/sources/tech/20200210 Install All Essential Media Codecs in Ubuntu With This Single Command -Beginner-s Tip.md b/sources/tech/20200210 Install All Essential Media Codecs in Ubuntu With This Single Command -Beginner-s Tip.md
deleted file mode 100644
index ecbe1dabe3..0000000000
--- a/sources/tech/20200210 Install All Essential Media Codecs in Ubuntu With This Single Command -Beginner-s Tip.md
+++ /dev/null
@@ -1,114 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (geekpi)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Install All Essential Media Codecs in Ubuntu With This Single Command [Beginner’s Tip])
-[#]: via: (https://itsfoss.com/install-media-codecs-ubuntu/)
-[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
-
-Install All Essential Media Codecs in Ubuntu With This Single Command [Beginner’s Tip]
-======
-
-If you have just installed Ubuntu or some other [Ubuntu flavors][1] like Kubuntu, Lubuntu etc, you’ll notice that your system doesn’t play some audio or video file.
-
-For video files, you can [install VLC on Ubuntu][2]. [VLC][3] one of the [best video players for Linux][4] and can play almost any video file format. But you’ll still have troubles with audio media files and flash player.
-
-The good thing is that [Ubuntu][5] provides a single package to install all the essential media codecs: ubuntu-restricted-extras.
-
-![][6]
-
-### What is Ubuntu Restricted Extras?
-
-The ubuntu-restricted-extras is a software package that consists various essential software like flash plugin, [unrar][7], [gstreamer][8], mp4, codecs for [Chromium browser in Ubuntu][9] etc.
-
-Since these software are not open source and some of them involve software patents, Ubuntu doesn’t install them by default. You’ll have to use multiverse repository, the software repository specifically created by Ubuntu to provide non-open source software to its users.
-
-Please read this article to [learn more about various Ubuntu repositories][10].
-
-### How to install Ubuntu Restricted Extras?
-
-I find it surprising that the software center doesn’t list Ubuntu Restricted Extras. In any case, you can install the package using command line and it’s very simple.
-
-Open a terminal by searching for it in the menu or using the [terminal keyboard shortcut Ctrl+Alt+T][11].
-
-Since ubuntu-restrcited-extras package is available in the multiverse repository, you should verify that the multiverse repository is enabled on your system:
-
-```
-sudo add-apt-repository multiverse
-```
-
-And then you can install it in Ubuntu default edition using this command:
-
-```
-sudo apt install ubuntu-restricted-extras
-```
-
-When you enter the command, you’ll be asked to enter your password. When _**you type the password, nothing is displayed on the screen**_. That’s normal. Type your password and press enter.
-
-It will show a huge list of packages to be installed. Press enter to confirm your selection when it asks.
-
-You’ll also encounter an [EULA][12] (End User License Agreement) screen like this:
-
-![Press Tab key to select OK and press Enter key][13]
-
-It could be overwhelming to navigate this screen but don’t worry. Just press tab and it will highlight the options. When the correct options are highlighted, press enter to confirm your selection.
-
-![Press Tab key to highlight Yes and press Enter key][14]
-
-Once the process finishes, you should be able to play MP3 and other media formats thanks to newly installed media codecs.
-
-##### Installing restricted extra package on Kubuntu, Lubuntu, Xubuntu
-
-Do keep in mind that Kubuntu, Lubuntu and Xubuntu has this package available with their own respective names. They should have just used the same name but they don’t unfortunately.
-
-On Kubuntu, use this command:
-
-```
-sudo apt install kubuntu-restricted-extras
-```
-
-On Lubuntu, use:
-
-```
-sudo apt install lubuntu-restricted-extras
-```
-
-On Xubuntu, you should use:
-
-```
-sudo apt install xubuntu-restricted-extras
-```
-
-I always recommend getting ubuntu-restricted-extras as one of the [essential things to do after installing Ubuntu][15]. It’s good to have a single command to install multiple codecs in Ubuntu.
-
-I hope you like this quick tip in the Ubuntu beginner series. I’ll share more such tips in the future.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/install-media-codecs-ubuntu/
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[b]: https://github.com/lujun9972
-[1]: https://itsfoss.com/which-ubuntu-install/
-[2]: https://itsfoss.com/install-latest-vlc/
-[3]: https://www.videolan.org/index.html
-[4]: https://itsfoss.com/video-players-linux/
-[5]: https://ubuntu.com/
-[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/Media_Codecs_in_Ubuntu.png?ssl=1
-[7]: https://itsfoss.com/use-rar-ubuntu-linux/
-[8]: https://gstreamer.freedesktop.org/
-[9]: https://itsfoss.com/install-chromium-ubuntu/
-[10]: https://itsfoss.com/ubuntu-repositories/
-[11]: https://itsfoss.com/ubuntu-shortcuts/
-[12]: https://en.wikipedia.org/wiki/End-user_license_agreement
-[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/installing_ubuntu_restricted_extras.jpg?ssl=1
-[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/installing_ubuntu_restricted_extras_1.jpg?ssl=1
-[15]: https://itsfoss.com/things-to-do-after-installing-ubuntu-18-04/
diff --git a/sources/tech/20200210 Playing Music on your Fedora Terminal with MPD and ncmpcpp.md b/sources/tech/20200210 Playing Music on your Fedora Terminal with MPD and ncmpcpp.md
deleted file mode 100644
index 72344b9f0d..0000000000
--- a/sources/tech/20200210 Playing Music on your Fedora Terminal with MPD and ncmpcpp.md
+++ /dev/null
@@ -1,118 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Playing Music on your Fedora Terminal with MPD and ncmpcpp)
-[#]: via: (https://fedoramagazine.org/playing-music-on-your-fedora-terminal-with-mpd-and-ncmpcpp/)
-[#]: author: (Carmine Zaccagnino https://fedoramagazine.org/author/carzacc/)
-
-Playing Music on your Fedora Terminal with MPD and ncmpcpp
-======
-
-![][1]
-
-MPD, as the name implies, is a Music Playing Daemon. It can play music but, being a daemon, any piece of software can interface with it and play sounds, including some CLI clients.
-
-One of them is called _ncmpcpp_, which is an improvement over the pre-existing _ncmpc_ tool. The name change doesn’t have much to do with the language they’re written in: they’re both C++, but _ncmpcpp_ is called that because it’s the _NCurses Music Playing Client_ _Plus Plus_.
-
-### Installing MPD and ncmpcpp
-
-The _ncmpmpcc_ client can be installed from the official Fedora repositories with DNF directly with
-
-```
-$ sudo dnf install ncmpcpp
-```
-
-On the other hand, MPD has to be installed from the RPMFusion _free_ repositories, which you can enable, [as per the official installation instructions][2], by running
-
-```
-$ sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
-```
-
-and then you can install MPD by running
-
-```
-$ sudo dnf install mpd
-```
-
-### Configuring and Starting MPD
-
-The most painless way to set up MPD is to run it as a regular user. The default is to run it as the dedicated _mpd_ user, but that causes all sorts of issues with permissions.
-
-Before we can run it, we need to create a local config file that will allow it to run as a regular user.
-
-To do that, create a subdirectory called _mpd_ in _~/.config_:
-
-```
-$ mkdir ~/.config/mpd
-```
-
-copy the default config file into this directory:
-
-```
-$ cp /etc/mpd.conf ~/.config/mpd
-```
-
-and then edit it with a text editor like _vim_, _nano_ or _gedit_:
-
-```
-$ nano ~/.config/mpd/mpd.conf
-```
-
-I recommend you read through all of it to check if there’s anything you need to do, but for most setups you can delete everything and just leave the following:
-
-```
-db_file "~/.config/mpd/mpd.db"
-log_file "syslog"
-```
-
-At this point you should be able to just run
-
-```
-$ mpd
-```
-
-with no errors, which will start the MPD daemon in the background.
-
-### Using ncmpcpp
-
-Simply run
-
-```
-$ ncmpcpp
-```
-
-and you’ll see a ncurses-powered graphical user interface in your terminal.
-
-Press _4_ and you should see your local music library, be able to change the selection using the arrow keys and press _Enter_ to play a song.
-
-Doing this multiple times will create a _playlist_, which allows you to move to the next track using the _>_ button (not the right arrow, the _>_ closing angle bracket character) and go back to the previous track with _<_. The + and – buttons increase and decrease volume. The _Q_ button quits ncmpcpp but it doesn’t stop the music. You can play and pause with _P_.
-
-You can see the current playlist by pressing the _1_ button (this is the default view). From this view you can press _i_ to look at the information (tags) about the current song. You can change the tags of the currently playing (or paused) song by pressing _6_.
-
-Pressing the \ button will add (or remove) an informative panel at the top of the view. In the top left, you should see something that looks like this:
-
-```
-[------]
-```
-
-Pressing the _r_, _z_, _y_, _R_, _x_ buttons will respectively toggle the _repeat_, _random_, _single_, _consume_ and _crossfade_ playback modes and will replace one of the _–_ characters in that little indicator to the initial of the selected mode.
-
-Pressing the _F1_ button will display some help text, which contains a list of keybindings, so there’s no need to write a complete list here. So now go on, be geeky, and play all your music from your terminal!
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/playing-music-on-your-fedora-terminal-with-mpd-and-ncmpcpp/
-
-作者:[Carmine Zaccagnino][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/carzacc/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2020/02/play_music_mpd-816x346.png
-[2]: https://rpmfusion.org/Configuration
diff --git a/sources/tech/20200210 Scan Kubernetes for errors with KRAWL.md b/sources/tech/20200210 Scan Kubernetes for errors with KRAWL.md
deleted file mode 100644
index 1c7d36183d..0000000000
--- a/sources/tech/20200210 Scan Kubernetes for errors with KRAWL.md
+++ /dev/null
@@ -1,222 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Scan Kubernetes for errors with KRAWL)
-[#]: via: (https://opensource.com/article/20/2/kubernetes-scanner)
-[#]: author: (Abhishek Tamrakar https://opensource.com/users/tamrakar)
-
-Scan Kubernetes for errors with KRAWL
-======
-The KRAWL script identifies errors in Kubernetes pods and containers.
-![Ship captain sailing the Kubernetes seas][1]
-
-When you're running containers with Kubernetes, you often find that they pile up. This is by design. It's one of the advantages of containers: they're cheap to start whenever a new one is needed. You can use a front-end like OpenShift or OKD to manage pods and containers. Those make it easy to visualize what you have set up, and have a rich set of commands for quick interactions.
-
-If a platform to manage containers doesn't fit your requirements, though, you can also get that information using only a Kubernetes toolchain, but there are a lot of commands you need for a full overview of a complex environment. For that reason, I wrote [KRAWL][2], a simple script that scans pods and containers under the namespaces on Kubernetes clusters and displays the output of events, if any are found. It can also be used as Kubernetes plugin for the same purpose. It's a quick and easy way to get a lot of useful information.
-
-### Prerequisites
-
- * You must have kubectl installed.
- * Your cluster's kubeconfig must be either in its default location ($HOME/.kube/config) or exported (KUBECONFIG=/path/to/kubeconfig).
-
-
-
-### Usage
-
-
-```
-`$ ./krawl`
-```
-
-![KRAWL script][3]
-
-### The script
-
-
-```
-#!/bin/bash
-# AUTHOR: Abhishek Tamrakar
-# EMAIL: [abhishek.tamrakar08@gmail.com][4]
-# LICENSE: Copyright (C) 2018 Abhishek Tamrakar
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-#define the variables
-KUBE_LOC=~/.kube/config
-#define variables
-KUBECTL=$(which kubectl)
-GET=$(which egrep)
-AWK=$(which awk)
-red=$(tput setaf 1)
-normal=$(tput sgr0)
-# define functions
-
-# wrapper for printing info messages
-info()
-{
- printf '\n\e[34m%s\e[m: %s\n' "INFO" "$@"
-}
-
-# cleanup when all done
-cleanup()
-{
- rm -f results.csv
-}
-
-# just check if the command we are about to call is available
-checkcmd()
-{
- #check if command exists
- local cmd=$1
- if [ -z "${!cmd}" ]
- then
- printf '\n\e[31m%s\e[m: %s\n' "ERROR" "check if $1 is installed !!!"
- exit 1
- fi
-}
-
-get_namespaces()
-{
- #get namespaces
- namespaces=( \
- $($KUBECTL get namespaces --ignore-not-found=true | \
- $AWK '/Active/ {print $1}' \
- ORS=" ") \
- )
-#exit if namespaces are not found
-if [ ${#namespaces[@]} -eq 0 ]
-then
- printf '\n\e[31m%s\e[m: %s\n' "ERROR" "No namespaces found!!"
- exit 1
-fi
-}
-
-#get events for pods in errored state
-get_pod_events()
-{
- printf '\n'
- if [ ${#ERRORED[@]} -ne 0 ]
- then
- info "${#ERRORED[@]} errored pods found."
- for CULPRIT in ${ERRORED[@]}
- do
- info "POD: $CULPRIT"
- info
- $KUBECTL get events \
- --field-selector=involvedObject.name=$CULPRIT \
- -ocustom-columns=LASTSEEN:.lastTimestamp,REASON:.reason,MESSAGE:.message \
- --all-namespaces \
- --ignore-not-found=true
- done
- else
- info "0 pods with errored events found."
- fi
-}
-
-#define the logic
-get_pod_errors()
-{
- printf "%s %s %s\n" "NAMESPACE,POD_NAME,CONTAINER_NAME,ERRORS" > results.csv
- printf "%s %s %s\n" "---------,--------,--------------,------" >> results.csv
- for NAMESPACE in ${namespaces[@]}
- do
- while IFS=' ' read -r POD CONTAINERS
- do
- for CONTAINER in ${CONTAINERS//,/ }
- do
- COUNT=$($KUBECTL logs --since=1h --tail=20 $POD -c $CONTAINER -n $NAMESPACE 2>/dev/null| \
- $GET -c '^error|Error|ERROR|Warn|WARN')
- if [ $COUNT -gt 0 ]
- then
- STATE=("${STATE[@]}" "$NAMESPACE,$POD,$CONTAINER,$COUNT")
- else
- #catch pods in errored state
- ERRORED=($($KUBECTL get pods -n $NAMESPACE --no-headers=true | \
- awk '!/Running/ {print $1}' ORS=" ") \
- )
- fi
- done
- done< <($KUBECTL get pods -n $NAMESPACE --ignore-not-found=true -o=custom-columns=NAME:.metadata.name,CONTAINERS:.spec.containers[*].name --no-headers=true)
- done
- printf "%s\n" ${STATE[@]:-None} >> results.csv
- STATE=()
-}
-#define usage for seprate run
-usage()
-{
-cat << EOF
-
- USAGE: "${0##*/} </path/to/kube-config>(optional)"
-
- This program is a free software under the terms of Apache 2.0 License.
- COPYRIGHT (C) 2018 Abhishek Tamrakar
-
-EOF
-exit 0
-}
-
-#check if basic commands are found
-trap cleanup EXIT
-checkcmd KUBECTL
-#
-#set the ground
-if [ $# -lt 1 ]; then
- if [ ! -e ${KUBE_LOC} -a ! -s ${KUBE_LOC} ]
- then
- info "A readable kube config location is required!!"
- usage
- fi
-elif [ $# -eq 1 ]
-then
- export KUBECONFIG=$1
-elif [ $# -gt 1 ]
-then
- usage
-fi
-#play
-get_namespaces
-get_pod_errors
-
-printf '\n%40s\n' 'KRAWL'
-printf '%s\n' '---------------------------------------------------------------------------------'
-printf '%s\n' ' Krawl is a command line utility to scan pods and prints name of errored pods '
-printf '%s\n\n' ' +and containers within. To use it as kubernetes plugin, please check their page '
-printf '%s\n' '================================================================================='
-
-cat results.csv | sed 's/,/,|/g'| column -s ',' -t
-get_pod_events
-```
-
-* * *
-
-_This was originally published as the README in [KRAWL's GitHub repository][2] and is reused with permission._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/kubernetes-scanner
-
-作者:[Abhishek Tamrakar][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/tamrakar
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
-[2]: https://github.com/abhiTamrakar/kube-plugins/tree/master/krawl
-[3]: https://opensource.com/sites/default/files/uploads/krawl_0.png (KRAWL script)
-[4]: mailto:abhishek.tamrakar08@gmail.com
diff --git a/sources/tech/20200210 Top hacks for the YaCy open source search engine.md b/sources/tech/20200210 Top hacks for the YaCy open source search engine.md
deleted file mode 100644
index 7b559e9c5e..0000000000
--- a/sources/tech/20200210 Top hacks for the YaCy open source search engine.md
+++ /dev/null
@@ -1,100 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (HankChow)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Top hacks for the YaCy open source search engine)
-[#]: via: (https://opensource.com/article/20/2/yacy-search-engine-hacks)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Top hacks for the YaCy open source search engine
-======
-Rather than adapting to someone else's vision, customize you search
-engine for the internet you want with YaCY.
-![Browser of things][1]
-
-In my article about [getting started with YaCy][2], I explained how to install and start using the [YaCy][3] peer-to-peer search engine. One of the most exciting things about YaCy, however, is the fact that it's a local client. Each user owns and operates a node in a globally distributed search engine infrastructure, which means each user is in full control of how they navigate and experience the World Wide Web.
-
-For instance, Google used to provide the URL google.com/linux as a shortcut to filter searches for Linux-related topics. It was a small feature that many people found useful, but [topical shortcuts were dropped][4] in 2011.
-
-YaCy makes it possible to customize your search experience.
-
-### Customize YaCy
-
-Once you've installed YaCy, navigate to your search page at **localhost:8090**. To customize your search engine, click the **Administration** button in the top-right corner (it may be concealed in a menu icon on small screens).
-
-The admin panel allows you to configure how YaCy uses your system resources and how it interacts with other YaCy clients.
-
-![YaCy profile selector][5]
-
-For instance, to configure an alternative port and set RAM and disk usage, use the **First steps** menu in the sidebar. To monitor YaCy activity, use the **Monitoring** panel. Most features are discoverable by clicking through the panels, but here are some of my favorites.
-
-### Search appliance
-
-Several companies have offered [intranet search appliances][6], but with YaCy, you can implement it for free. Whether you want to search through your own data or to implement a search system for local file shares at your business, you can choose to run YaCy as an internal indexer for files accessible over HTTP, FTP, and SMB (Samba). People in your local network can use your personalized instance of YaCy to find shared files, and none of the data is shared with users outside your network.
-
-### Network configuration
-
-YaCy favors isolation and privacy by default. You can adjust how you connect to the peer-to-peer network in the **Network Configuration** panel, which is revealed by clicking the link located at the top of the **Use Case & Account** configuration screen.
-
-![YaCy network configuration][7]
-
-### Crawl a site
-
-Peer-to-peer indexing is user-driven. There's no mega-corporation initiating searches on every accessible page on the internet, so a site isn't indexed until someone deliberately crawls it with YaCy.
-
-The YaCy client provides two options to help you help crawl the web: you can perform a manual crawl, and you can make YaCy available for suggested crawls.
-
-![YaCy advanced crawler][8]
-
-#### Start a manual crawling job
-
-A manual crawl is when you enter the URL of a site you want to index and start a YaCy crawl job. To do this, click the **Advanced Crawler** link in the **Production** sidebar. Enter one or more URLs, then scroll to the bottom of the page and enable the **Do remote indexing** option. This enables your client to broadcast the URLs it is indexing, so clients that have opted to accept requests can help you perform the crawl.
-
-To start the crawl, click the **Start New Crawl Job** button at the bottom of the page. I use this method to index sites I use frequently or find useful.
-
-Once the crawl job starts, YaCy indexes the URLs you enter and stores the index on your local machine. As long as you are running in senior mode (meaning your firewall permits incoming and outgoing traffic on port 8090), your index is available to YaCy users all over the globe.
-
-#### Join in on a crawl
-
-While some very dedicated YaCy senior users may crawl the internet compulsively, there are a _lot_ of sites out there in the world. It might seem impossible to match the resources of popular spiders and bots, but because YaCy has so many users, they can band together as a community to index more of the internet than any one user could do alone. If you activate YaCy to broadcast requests for site crawls, participating clients can work together to crawl sites you might not otherwise think to crawl manually.
-
-To configure your client to accept jobs from others, click the **Advanced Crawler** link in the left sidebar menu. In the **Advanced Crawler** panel, click the **Remote Crawling** link under the **Network Harvesting** heading at the top of the page. Enable remote crawls by placing a tick in the checkbox next to the **Load** setting.
-
-![YaCy remote crawling][9]
-
-### YaCy monitoring and more
-
-YaCy is a surprisingly robust search engine, providing you with the opportunity to theme and refine your experience in nearly any way you could want. You can monitor the activity of your YaCy client in the **Monitoring** panel, so you can get an idea of how many people are benefiting from the work of the YaCy community and also see what kind of activity it's generating for your computer and network.
-
-![YaCy monitoring screen][10]
-
-### Search engines make a difference
-
-The more time you spend with the Administration screen, the more fun it becomes to ponder how the search engine you use can change your perspective. Your experience of the internet is shaped by the results you get back for even the simplest of queries. You might notice, in fact, how different one person's "internet" is from another person's when you talk to computer users from a different industry. For some people, the web is littered with ads and promoted searches and suffers from the tunnel vision of learned responses to queries. For instance, if someone consistently searches for answers about X, most commercial search engines will give weight to query responses that concern X. That's a useful feature on the one hand, but it occludes answers that require Y, even though that might be the better solution for a specific task.
-
-As in real life, stepping outside a manufactured view of the world can be healthy and enlightening. Try YaCy, and see what you discover.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/yacy-search-engine-hacks
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_desktop_website_checklist_metrics.png?itok=OKKbl1UR (Browser of things)
-[2]: https://opensource.com/article/20/2/open-source-search-engine
-[3]: https://yacy.net/
-[4]: https://www.linuxquestions.org/questions/linux-news-59/is-there-no-more-linux-google-884306/
-[5]: https://opensource.com/sites/default/files/uploads/yacy-profiles.jpg (YaCy profile selector)
-[6]: https://en.wikipedia.org/wiki/Vivisimo
-[7]: https://opensource.com/sites/default/files/uploads/yacy-network-config.jpg (YaCy network configuration)
-[8]: https://opensource.com/sites/default/files/uploads/yacy-advanced-crawler.jpg (YaCy advanced crawler)
-[9]: https://opensource.com/sites/default/files/uploads/yacy-remote-crawl-accept.jpg (YaCy remote crawling)
-[10]: https://opensource.com/sites/default/files/uploads/yacy-monitor.jpg (YaCy monitoring screen)
diff --git a/sources/tech/20200211 Automate your live demos with this shell script.md b/sources/tech/20200211 Automate your live demos with this shell script.md
new file mode 100644
index 0000000000..56b8626148
--- /dev/null
+++ b/sources/tech/20200211 Automate your live demos with this shell script.md
@@ -0,0 +1,210 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Automate your live demos with this shell script)
+[#]: via: (https://opensource.com/article/20/2/live-demo-script)
+[#]: author: (Lisa Seelye https://opensource.com/users/lisa)
+
+Automate your live demos with this shell script
+======
+Try this script the next time you give a presentation to prevent making
+typos in front of a live audience.
+![Person using a laptop][1]
+
+I gave a talk about [multi-architecture container images][2] at [LISA19][3] in October that included a lengthy live demo. Rather than writing out 30+ commands and risking typos, I decided to automate the demo with a shell script.
+
+The script mimics what appears as input/output and runs the real commands in the background, pausing at various points so I can narrate what is going on. I'm very pleased with how the script turned out and the effect on stage. The script and supporting materials for my presentation are available on [GitHub][4] under an Apache 2.0 license.
+
+### The script
+
+
+```
+#!/bin/bash
+
+set -e
+
+IMG=thedoh/lisa19
+REGISTRY=docker.io
+VERSION=19.10.1
+
+# Plan B with GCR:
+#IMG=dulcet-iterator-213018
+#REGISTRY=us.gcr.io
+#VERSION=19.10.1
+
+pause() {
+ local step="${1}"
+ ps1
+ echo -n "# Next step: ${step}"
+ read
+}
+
+ps1() {
+ echo -ne "\033[01;32m${USER}@$(hostname -s) \033[01;34m$(basename $(pwd)) \$ \033[00m"
+}
+
+echocmd() {
+ echo "$(ps1)$@"
+}
+
+docmd() {
+ echocmd $@
+ $@
+}
+
+step0() {
+ local registry="${1}" img="${2}" version="${3}"
+ # Mindful of tokens in ~/.docker/config.json
+ docmd grep experimental ~/.docker/config.json
+
+ docmd cd ~/go/src/github.com/lisa/lisa19-containers
+
+ pause "This is what we'll be building"
+ docmd export REGISTRY=${registry}
+ docmd export IMG=${img}
+ docmd export VERSION=${version}
+ docmd make REGISTRY=${registry} IMG=${img} VERSION=${version} clean
+}
+
+step1() {
+ local registry="${1}" img="${2}" version="${3}"
+
+ docmd docker build --no-cache --platform=linux/amd64 --build-arg=GOARCH=amd64 -t ${REGISTRY}/${IMG}:amd64-${VERSION} .
+ pause "ARM64 image next"
+ docmd docker build --no-cache --platform=linux/arm64 --build-arg=GOARCH=arm64 -t ${REGISTRY}/${IMG}:arm64-${VERSION} .
+}
+
+step2() {
+ local registry="${1}" img="${2}" version="${3}" origpwd=$(pwd) savedir=$(mktemp -d) jsontemp=$(mktemp -t XXXXX)
+ chmod 700 $jsontemp $savedir
+ # Set our way back home and get ready to fix our arm64 image to amd64.
+ echocmd 'origpwd=$(pwd)'
+ echocmd 'savedir=$(mktemp -d)'
+ echocmd "mkdir -p \$savedir/change"
+ mkdir -p $savedir/change &>/dev/null
+ echocmd "docker save ${REGISTRY}/${IMG}:arm64-${VERSION} 2>/dev/null 1> \$savedir/image.tar"
+ docker save ${REGISTRY}/${IMG}:arm64-${VERSION} 2>/dev/null 1> $savedir/image.tar
+ pause "untar the image to access its metadata"
+
+ echocmd "cd \$savedir/change"
+ cd $savedir/change
+ echocmd tar xf \$savedir/image.tar
+ tar xf $savedir/image.tar
+ docmd ls -l
+
+ pause "find the JSON config file"
+ echocmd 'jsonfile=$(jq -r ".[0].Config" manifest.json)'
+ jsonfile=$(jq -r ".[0].Config" manifest.json)
+
+ pause "notice the original metadata says amd64"
+ echocmd jq '{architecture: .architecture, ID: .config.Image}' \$jsonfile
+ jq '{architecture: .architecture, ID: .config.Image}' $jsonfile
+
+ pause "Change from amd64 to arm64 using a temp file"
+ echocmd "jq '.architecture = \"arm64\"' \$jsonfile > \$jsontemp"
+ jq '.architecture = "arm64"' $jsonfile > $jsontemp
+ echocmd /bin/mv -f -- \$jsontemp \$jsonfile
+ /bin/mv -f -- $jsontemp $jsonfile
+
+ pause "Check to make sure the config JSON file says arm64 now"
+ echocmd jq '{architecture: .architecture, ID: .config.Image}' \$jsonfile
+ jq '{architecture: .architecture, ID: .config.Image}' $jsonfile
+
+ pause "delete the image with the incorrect metadata"
+ docmd docker rmi ${REGISTRY}/${IMG}:arm64-${VERSION}
+
+ pause "Re-compress the ARM64 image and load it back into Docker, then clean up the temp space"
+ echocmd 'tar cf - * | docker load'
+ tar cf - * | docker load
+
+ docmd cd $origpwd
+ echocmd "/bin/rm -rf -- \$savedir"
+ /bin/rm -rf -- $savedir &>/dev/null
+}
+
+step3() {
+ local registry="${1}" img="${2}" version="${3}"
+ docmd docker push ${registry}/${img}:amd64-${version}
+ pause "push ARM64 image to ${registry}"
+ docmd docker push ${registry}/${img}:arm64-${version}
+}
+
+step4() {
+ local registry="${1}" img="${2}" version="${3}"
+ docmd docker manifest create ${registry}/${img}:${version} ${registry}/${img}:arm64-${version} ${registry}/${img}:amd64-${version}
+
+ pause "add a reference to the amd64 image to the manifest list"
+ docmd docker manifest annotate ${registry}/${img}:${version} ${registry}/${img}:amd64-${version} --os linux --arch amd64
+ pause "now add arm64"
+ docmd docker manifest annotate ${registry}/${img}:${version} ${registry}/${img}:arm64-${version} --os linux --arch arm64
+}
+
+step5() {
+ local registry="${1}" img="${2}" version="${3}"
+ docmd docker manifest push ${registry}/${img}:${version}
+}
+
+step6() {
+ local registry="${1}" img="${2}" version="${3}"
+ docmd make REGISTRY=${registry} IMG=${img} VERSION=${version} clean
+
+ pause "ask docker.io if ${img}:${version} has a linux/amd64 manifest, and run it"
+ docmd docker pull --platform linux/amd64 ${registry}/${img}:${version}
+ docmd docker run --rm -i ${registry}/${img}:${version}
+
+ pause "clean slate again"
+ docmd make REGISTRY=${registry} IMG=${img} VERSION=${version} clean
+
+ pause "now repeat for linux/arm64 and see what it gives us"
+ docmd docker pull --platform linux/arm64 ${registry}/${img}:${version}
+ set +e
+ docmd docker run --rm -i ${registry}/${img}:${version}
+ set -e
+ if [[ $(uname -s) == "Darwin" ]]; then
+ pause "note about Docker on Mac and binfmt_misc: binfmt_misc lets a mac run arm64 binaries in the Docker VM"
+ fi
+}
+
+pause "initial setup"
+step0 ${REGISTRY} ${IMG} ${VERSION}
+pause "1 build constituent images"
+step1 ${REGISTRY} ${IMG} ${VERSION}
+
+pause "2 fix ARM64 metadata"
+step2 ${REGISTRY} ${IMG} ${VERSION}
+
+pause "3 push constituent images up to docker.io"
+step3 ${REGISTRY} ${IMG} ${VERSION}
+
+pause "4 build the manifest list for the image"
+step4 ${REGISTRY} ${IMG} ${VERSION}
+
+pause "5 Push the manifest list to docker.io"
+step5 ${REGISTRY} ${IMG} ${VERSION}
+
+pause "6 clean slate, and validate the list-based image"
+step6 ${REGISTRY} ${IMG} ${VERSION}
+
+docmd echo 'Manual steps all done!'
+make REGISTRY=${REGISTRY} IMG=${IMG} VERSION=${VERSION} clean &>/dev/null
+```
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/live-demo-script
+
+作者:[Lisa Seelye][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/lisa
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
+[2]: https://www.usenix.org/conference/lisa19/presentation/seelye
+[3]: https://www.usenix.org/conference/lisa19
+[4]: https://github.com/lisa/lisa19-containers
diff --git a/sources/tech/20200211 Dino is a Modern Looking Open Source XMPP Client.md b/sources/tech/20200211 Dino is a Modern Looking Open Source XMPP Client.md
deleted file mode 100644
index 78135c9f9b..0000000000
--- a/sources/tech/20200211 Dino is a Modern Looking Open Source XMPP Client.md
+++ /dev/null
@@ -1,104 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Dino is a Modern Looking Open Source XMPP Client)
-[#]: via: (https://itsfoss.com/dino-xmpp-client/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Dino is a Modern Looking Open Source XMPP Client
-======
-
-_**Brief: Dino is a relatively new open-source XMPP client that tries to offer a good user experience while encouraging privacy-focused users to utilize XMPP for messaging.**_
-
-### Dino: An Open Source XMPP Client
-
-![][1]
-
-[XMPP][2] (Extensible Messaging Presence Protocol) is a decentralized model of network to facilitate instant messaging and collaboration. Decentralize means there is no central server that has access to your data. The communication is directly between the end-points.
-
-Some of us might call it an “old school” tech probably because the XMPP clients usually have a very bad user experience or simply just because it takes time to get used to (or set it up).
-
-That’s when [Dino][3] comes to the rescue as a modern XMPP client to provide a clean and snappy user experience without compromising your privacy.
-
-### The User Experience
-
-![][4]
-
-Dino does try to improve the user experience as an XMPP client but it is worth noting that the look and feel of it will depend on your Linux distribution to some extent. Your icon theme or the gnome theme might make it look better or worse for your personal experience.
-
-Technically, the user interface is quite simple and easy to use. So, I suggest you take a look at some of the [best icon themes][5] and [GNOME themes][6] for Ubuntu to tweak the look of Dino.
-
-### Features of Dino
-
-![Dino Screenshot][7]
-
-You can expect to use Dino as an alternative to Slack, [Signal][8] or [Wire][9] for your business or personal usage.
-
-It offers all of the essential features you would need in a messaging application, let us take a look at a list of things that you can expect from it:
-
- * Decentralized Communication
- * Public XMPP Servers supported if you cannot setup your own server
- * Similar to UI to other popular messengers – so it’s easy to use
- * Image & File sharing
- * Multiple accounts supported
- * Advanced message search
- * [OpenPGP][10] & [OMEMO][11] encryption supported
- * Lightweight native desktop application
-
-
-
-### Installing Dino on Linux
-
-You may or may not find it listed in your software center. Dino does provide ready to use binaries for Debian (deb) and Fedora (rpm) based distributions.
-
-**For Ubuntu:**
-
-Dino is available in the universe repository on Ubuntu and you can install it using this command:
-
-```
-sudo apt install dino-im
-```
-
-Similarly, you can find packages for other Linux distributions on their [GitHub distribution packages page][12].
-
-If you want the latest and greatest, you can also find both **.deb** and .**rpm** files for Dino to install on your Linux distribution (nightly builds) from [OpenSUSE’s software webpage][13].
-
-In either case, head to their [GitHub page][14] or click on the link below to visit the official site.
-
-[Download Dino][3]
-
-**Wrapping Up**
-
-It works quite well without any issues (at the time of writing this and quick testing it). I’ll try exploring more about it and hopefully cover more XMPP-centric articles to encourage users to use XMPP clients and servers for communication.
-
-What do you think about Dino? Would you recommend another open-source XMPP client that’s potentially better than Dino? Let me know your thoughts in the comments below.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/dino-xmpp-client/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/dino-main.png?ssl=1
-[2]: https://xmpp.org/about/
-[3]: https://dino.im/
-[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/dino-xmpp-client.jpg?ssl=1
-[5]: https://itsfoss.com/best-icon-themes-ubuntu-16-04/
-[6]: https://itsfoss.com/best-gtk-themes/
-[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/dino-screenshot.png?ssl=1
-[8]: https://itsfoss.com/signal-messaging-app/
-[9]: https://itsfoss.com/wire-messaging-linux/
-[10]: https://www.openpgp.org/
-[11]: https://en.wikipedia.org/wiki/OMEMO
-[12]: https://github.com/dino/dino/wiki/Distribution-Packages
-[13]: https://software.opensuse.org/download.html?project=network:messaging:xmpp:dino&package=dino
-[14]: https://github.com/dino/dino
diff --git a/sources/tech/20200211 Using external libraries in Java.md b/sources/tech/20200211 Using external libraries in Java.md
new file mode 100644
index 0000000000..8367b5ca20
--- /dev/null
+++ b/sources/tech/20200211 Using external libraries in Java.md
@@ -0,0 +1,328 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using external libraries in Java)
+[#]: via: (https://opensource.com/article/20/2/external-libraries-java)
+[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
+
+Using external libraries in Java
+======
+External libraries fill gaps in the Java core libraries.
+![books in a library, stacks][1]
+
+Java comes with a core set of libraries, including those that define commonly used data types and related behavior, like **String** or **Date**; utilities to interact with the host operating system, such as **System** or **File**; and useful subsystems to manage security, deal with network communications, and create or parse XML. Given the richness of this core set of libraries, it's often easy to find the necessary bits and pieces to reduce the amount of code a programmer must write to solve a problem.
+
+Even so, there are a lot of interesting Java libraries created by people who find gaps in the core libraries. For example, [Apache Commons][2] "is an Apache project focused on all aspects of reusable Java components" and provides a collection of some 43 open source libraries (as of this writing) covering a range of capabilities either outside the Java core (such as [geometry][3] or [statistics][4]) or that enhance or replace capabilities in the Java core (such as [math][5] or [numbers][6]).
+
+Another common type of Java library is an interface to a system component—for example, to a database system. This article looks at using such an interface to connect to a [PostgreSQL][7] database and get some interesting information. But first, I'll review the important bits and pieces of a library.
+
+### What is a library?
+
+A library, of course, must contain some useful code. But to be useful, that code needs to be organized in such a way that the Java programmer can access the components to solve the problem at hand.
+
+I'll boldly claim that the most important part of a library is its application programming interface (API) documentation. This kind of documentation is familiar to many and is most often produced by [Javadoc][8], which reads structured comments in the code and produces HTML output that displays the API's packages in the panel in the top-left corner of the page; its classes in the bottom-left corner; and the detailed documentation at the library, package, or class level (depending on what is selected in the main panel) on the right. For example, the [top level of API documentation for Apache Commons Math][9] looks like:
+
+![API documentation for Apache Commons Math][10]
+
+Clicking on a package in the main panel shows the Java classes and interfaces defined in that package. For example, **[org.apache.commons.math4.analysis.solvers][11]** shows classes like **BisectionSolver** for finding zeros of univariate real functions using the bisection algorithm. And clicking on the [BisectionSolver][12] link lists all the methods of the class **BisectionSolver**.
+
+This type of documentation is useful as reference information; it's not intended as a tutorial for learning how to use the library. For example, if you know what a univariate real function is and look at the package **org.apache.commons.math4.analysis.function**, you can imagine using that package to compose a function definition and then using the **org.apache.commons.math4.analysis.solvers** package to look for zeros of the just-created function. But really, you probably need more learning-oriented documentation to bridge to the reference documentation. Maybe even an example!
+
+This documentation structure also helps clarify the meaning of _package_—a collection of related Java class and interface definitions—and shows what packages are bundled in a particular library.
+
+The code for such a library is most commonly found in a [**.jar** file][13], which is basically a .zip file created by the Java **jar** command that contains some other useful information. **.jar** files are typically created as the endpoint of a build process that compiles all the **.java** files in the various packages defined.
+
+There are two main steps to accessing the functionality provided by an external library:
+
+ 1. Make sure the library is available to the Java compilation step—[**javac**][14]—and the execution step—**java**—via the classpath (either the **-cp** argument on the command line or the **CLASSPATH** environment variable).
+ 2. Use the appropriate **import** statements to access the package and class in the program source code.
+
+
+
+The rest is just like coding with Java core classes, such as **String**—write the code using the class and interface definitions provided by the library. Easy, eh? Well, maybe not quite that easy; first, you need to understand the intended use pattern for the library components, and then you can write code.
+
+### An example: Connect to a PostgreSQL database
+
+The typical use pattern for accessing data in a database system is:
+
+ 1. Gain access to the code specific to the database software being used.
+ 2. Connect to the database server.
+ 3. Build a query string.
+ 4. Execute the query string.
+ 5. Do something with the results returned.
+ 6. Disconnect from the database server.
+
+
+
+The programmer-facing part of all of this is provided by a database-independent interface package, **[java.sql][15]**, which defines the core client-side Java Database Connectivity (JDBC) API. The **java.sql** package is part of the core Java libraries, so there is no need to supply a **.jar** file to the compile step. However, each database provider creates its own implementation of the **java.sql** interfaces—for example, the **Connection** interface—and those implementations must be provided on the run step.
+
+Let's see how this works, using PostgreSQL.
+
+#### Gain access to the database-specific code
+
+The following code uses the [Java class loader][16] (the **Class.forName()** call) to bring the PostgreSQL driver code into the executing virtual machine:
+
+
+```
+import java.sql.*;
+
+public class Test1 {
+
+ public static void main([String][17] args[]) {
+
+ // Load the driver (jar file must be on class path) [1]
+
+ try {
+ Class.forName("org.postgresql.Driver");
+ [System][18].out.println("driver loaded");
+ } catch ([Exception][19] e1) {
+ [System][18].err.println("couldn't find driver");
+ [System][18].err.println(e1);
+ [System][18].exit(1);
+ }
+
+ // If we get here all is OK
+
+ [System][18].out.println("done.");
+ }
+}
+```
+
+Because the class loader can fail, and therefore can throw an exception when failing, surround the call to **Class.forName()** in a try-catch block.
+
+If you compile the above code with **javac** and run it with Java:
+
+
+```
+me@mymachine:~/Test$ javac Test1.java
+me@mymachine:~/Test$ java Test1
+couldn't find driver
+java.lang.ClassNotFoundException: org.postgresql.Driver
+me@mymachine:~/Test$
+```
+
+The class loader needs the **.jar** file containing the PostgreSQL JDBC driver implementation to be on the classpath:
+
+
+```
+me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test1
+driver loaded
+done.
+me@mymachine:~/Test$
+```
+
+#### Connect to the database server
+
+The following code loads the JDBC driver and creates a connection to the PostgreSQL database:
+
+
+```
+import java.sql.*;
+
+public class Test2 {
+
+ public static void main([String][17] args[]) {
+
+ // Load the driver (jar file must be on class path) [1]
+
+ try {
+ Class.forName("org.postgresql.Driver");
+ [System][18].out.println("driver loaded");
+ } catch ([Exception][19] e1) {
+ [System][18].err.println("couldn't find driver");
+ [System][18].err.println(e1);
+ [System][18].exit(1);
+ }
+
+ // Set up connection properties [2]
+
+ java.util.[Properties][20] props = new java.util.[Properties][20]();
+ props.setProperty("user","me");
+ props.setProperty("password","mypassword");
+ [String][17] database = "jdbc:postgresql://myhost.org:5432/test";
+
+ // Open the connection to the database [3]
+
+ try ([Connection][21] conn = [DriverManager][22].getConnection(database, props)) {
+ [System][18].out.println("connection created");
+ } catch ([Exception][19] e2) {
+ [System][18].err.println("sql operations failed");
+ [System][18].err.println(e2);
+ [System][18].exit(2);
+ }
+ [System][18].out.println("connection closed");
+
+ // If we get here all is OK
+
+ [System][18].out.println("done.");
+ }
+}
+```
+
+Compile and run it:
+
+
+```
+me@mymachine:~/Test$ javac Test2.java
+me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test2
+driver loaded
+connection created
+connection closed
+done.
+me@mymachine:~/Test$
+```
+
+Some notes on the above:
+
+ * The code following comment [2] uses system properties to set up connection parameters—in this case, the PostgreSQL username and password. This allows for grabbing those parameters from the Java command line and passing all the parameters in as an argument bundle. There are other **Driver.getConnection()** options for passing in the parameters individually.
+ * JDBC requires a URL for defining the database, which is declared above as **String database** and passed into the **Driver.getConnection()** method along with the connection parameters.
+ * The code uses try-with-resources, which auto-closes the connection upon completion of the code in the try-catch block. There is a lengthy discussion of this approach on [Stack Overflow][23].
+ * The try-with-resources provides access to the **Connection** instance and can execute SQL statements there; any errors will be caught by the same **catch** statement.
+
+
+
+#### Do something fun with the database connection
+
+In my day job, I often need to know what users have been defined for a given database server instance, and I use this [handy piece of SQL][24] for grabbing a list of all users:
+
+
+```
+import java.sql.*;
+
+public class Test3 {
+
+ public static void main([String][17] args[]) {
+
+ // Load the driver (jar file must be on class path) [1]
+
+ try {
+ Class.forName("org.postgresql.Driver");
+ [System][18].out.println("driver loaded");
+ } catch ([Exception][19] e1) {
+ [System][18].err.println("couldn't find driver");
+ [System][18].err.println(e1);
+ [System][18].exit(1);
+ }
+
+ // Set up connection properties [2]
+
+ java.util.[Properties][20] props = new java.util.[Properties][20]();
+ props.setProperty("user","me");
+ props.setProperty("password","mypassword");
+ [String][17] database = "jdbc:postgresql://myhost.org:5432/test";
+
+ // Open the connection to the database [3]
+
+ try ([Connection][21] conn = [DriverManager][22].getConnection(database, props)) {
+ [System][18].out.println("connection created");
+
+ // Create the SQL command string [4]
+
+ [String][17] qs = "SELECT " +
+ " u.usename AS \"User name\", " +
+ " u.usesysid AS \"User ID\", " +
+ " CASE " +
+ " WHEN u.usesuper AND u.usecreatedb THEN " +
+ " CAST('superuser, create database' AS pg_catalog.text) " +
+ " WHEN u.usesuper THEN " +
+ " CAST('superuser' AS pg_catalog.text) " +
+ " WHEN u.usecreatedb THEN " +
+ " CAST('create database' AS pg_catalog.text) " +
+ " ELSE " +
+ " CAST('' AS pg_catalog.text) " +
+ " END AS \"Attributes\" " +
+ "FROM pg_catalog.pg_user u " +
+ "ORDER BY 1";
+
+ // Use the connection to create a statement, execute it,
+ // analyze the results and close the result set [5]
+
+ [Statement][25] stat = conn.createStatement();
+ [ResultSet][26] rs = stat.executeQuery(qs);
+ [System][18].out.println("User name;User ID;Attributes");
+ while (rs.next()) {
+ [System][18].out.println(rs.getString("User name") + ";" +
+ rs.getLong("User ID") + ";" +
+ rs.getString("Attributes"));
+ }
+ rs.close();
+ stat.close();
+
+ } catch ([Exception][19] e2) {
+ [System][18].err.println("connecting failed");
+ [System][18].err.println(e2);
+ [System][18].exit(1);
+ }
+ [System][18].out.println("connection closed");
+
+ // If we get here all is OK
+
+ [System][18].out.println("done.");
+ }
+}
+```
+
+In the above, once it has the **Connection** instance, it defines a query string (comment [4] above), creates a **Statement** instance and uses it to execute the query string, then puts its results in a **ResultSet** instance, which it can iterate through to analyze the results returned, and ends by closing both the **ResultSet** and **Statement** instances (comment [5] above).
+
+Compiling and executing the program produces the following output:
+
+
+```
+me@mymachine:~/Test$ javac Test3.java
+me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test3
+driver loaded
+connection created
+User name;User ID;[Attributes][27]
+fwa;16395;superuser
+vax;197772;
+mbe;290995;
+aca;169248;
+connection closed
+done.
+me@mymachine:~/Test$
+```
+
+This is a (very simple) example of using the PostgreSQL JDBC library in a simple Java application. It's worth emphasizing that it didn't need to use a Java import statement like **import org.postgresql.jdbc.*;** in the code because of the way the **java.sql** library is designed. Because of that, there's no need to specify the classpath at compile time. Instead, it uses the Java class loader to bring in the PostgreSQL code at run time.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/external-libraries-java
+
+作者:[Chris Hermansen][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/clhermansen
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/books_library_reading_list.jpg?itok=O3GvU1gH (books in a library, stacks)
+[2]: https://commons.apache.org/
+[3]: https://commons.apache.org/proper/commons-geometry/
+[4]: https://commons.apache.org/proper/commons-statistics/
+[5]: https://commons.apache.org/proper/commons-math/
+[6]: https://commons.apache.org/proper/commons-numbers/
+[7]: https://opensource.com/article/19/11/getting-started-postgresql
+[8]: https://en.wikipedia.org/wiki/Javadoc
+[9]: https://commons.apache.org/proper/commons-math/apidocs/index.html
+[10]: https://opensource.com/sites/default/files/uploads/api-documentation_apachecommonsmath.png (API documentation for Apache Commons Math)
+[11]: https://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math4/analysis/solvers/package-summary.html
+[12]: https://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math4/analysis/solvers/BisectionSolver.html
+[13]: https://en.wikipedia.org/wiki/JAR_(file_format)
+[14]: https://en.wikipedia.org/wiki/Javac
+[15]: https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html
+[16]: https://en.wikipedia.org/wiki/Java_Classloader
+[17]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
+[18]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
+[19]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+exception
+[20]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+properties
+[21]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+connection
+[22]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+drivermanager
+[23]: https://stackoverflow.com/questions/8066501/how-should-i-use-try-with-resources-with-jdbc
+[24]: https://www.postgresql.org/message-id/1121195544.8208.242.camel@state.g2switchworks.com
+[25]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+statement
+[26]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+resultset
+[27]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+attributes
diff --git a/sources/tech/20200212 Manage your SSL certificates with the ssl-on-demand script.md b/sources/tech/20200212 Manage your SSL certificates with the ssl-on-demand script.md
new file mode 100644
index 0000000000..e4be89e4f5
--- /dev/null
+++ b/sources/tech/20200212 Manage your SSL certificates with the ssl-on-demand script.md
@@ -0,0 +1,685 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Manage your SSL certificates with the ssl-on-demand script)
+[#]: via: (https://opensource.com/article/20/2/ssl-demand)
+[#]: author: (Abhishek Tamrakar https://opensource.com/users/tamrakar)
+
+Manage your SSL certificates with the ssl-on-demand script
+======
+Keep track of certificate expirations to prevent problems with the
+ssl-on-demand script.
+![Lock][1]
+
+It happens all the time, to the largest of companies. An important certificate doesn't get renewed, and services become inaccessible. It happened to Microsoft Teams in early February 2020, awkwardly timed just after the launch of a major television campaign promoting it as a [Slack competitor][2]. Embarrassing as that may be, it's sure to happen to someone else in the future.
+
+On the modern web, expired [certificates][3] can create major problems for websites, ranging from unhappy users who can't connect to a site to security threats from bad actors who take advantage of the failure to renew a certificate.
+
+[Ssl-on-demand][4] is a set of SSL scripts to help site owners manage certificates. It is used for on-demand certificate generation and validation and it can create certificate signing requests ([CSRs][5]) and predict the expiration of existing certificates.
+
+### Automate SSL expiry checks
+
+
+```
+ USAGE: SSLexpiryPredictions.sh -[cdewh]
+
+ DESCRIPTION: This script predicts the expiring SSL certificates based on the end date.
+
+ OPTIONS:
+
+ -c| sets the value for configuration file which has server:port or host:port details.
+
+ -d| sets the value of directory containing the certificate files in crt or pem format.
+
+ -e| sets the value of certificate extention, e.g crt, pem, cert.
+ crt: default [to be used with -d, if certificate file extention is other than .crt]
+
+ -w| sets the value for writing the script output to a file.
+
+ -h| prints this help and exit.
+```
+
+**Examples:**
+
+To create a file with a list of all servers and their port numbers to make an SSL handshake, use:
+
+
+```
+cat > servers.list
+ server1:port1
+ server2:port2
+ server3:port3
+ (ctrl+d)
+
+$ ./SSLexpiryPredictions.sh -c server.list
+```
+
+Run the script by providing the certificate location and extension (in case it is not .crt):
+
+
+```
+`$ ./SSLexpiryPredictions.sh -d /path/to/certificates/dir -e pem`
+```
+
+### Automate CSR and private key creation
+
+
+```
+Usage: genSSLcsr.sh [options] -[cdmshx]
+ [-c (common name)]
+ [-d (domain name)]
+ [-s (SSL certificate subject)]
+ [-p (password)]
+ [-m (email address)] *(Experimental)
+ [-r (remove pasphrase) default:true]
+ [-h (help)]
+ [-x (optional)]
+
+[OPTIONS]
+ -c| Sets the value for common name.
+ A valid common name is something that ends with 'xyz.com'
+
+ -d| Sets the domain name.
+
+ -s| Sets the subject to be applied to the certificates.
+ '/C=country/ST=state/L=locality/O=organization/OU=organizationalunit/emailAddress=email'
+
+ -p| Sets the password for private key.
+
+ -r| Sets the value of remove passphrase.
+ true:[default] passphrase will be removed from key.
+ false: passphrase will not be removed and key wont get printed.
+
+ -m| Sets the mailing capability to the script.
+ (Experimental at this time and requires a lot of work)
+
+ -x| Creates the certificate request and key but do not print on screen.
+ To be used when script is used just to create the key and CSR with no need
+ + to generate the certficate on the go.
+
+ -h| Displays the usage. No further functions are performed.
+
+ Example: genSSLcsr.sh -c mywebsite.xyz.com -m [myemail@mydomain.com][6]
+```
+
+### The scripts
+
+#### 1. SSLexpiryPredictions.sh
+
+
+```
+#!/bin/bash
+##############################################
+#
+# PURPOSE: The script to predict expiring SSL certificates.
+#
+# AUTHOR: 'Abhishek.Tamrakar'
+#
+# VERSION: 0.0.1
+#
+# COMPANY: Self
+#
+# EMAIL: [abhishek.tamrakar08@gmail.com][7]
+#
+# GENERATED: on 2018-05-20
+#
+# LICENSE: Copyright (C) 2018 Abhishek Tamrakar
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##############################################
+
+#your Variables go here
+script=${0##/}
+exitcode=''
+WRITEFILE=0
+CONFIG=0
+DIR=0
+# functions here
+usage()
+{
+cat <<EOF
+
+ USAGE: $script -[cdewh]"
+
+ DESCRIPTION: This script predicts the expiring SSL certificates based on the end date.
+
+ OPTIONS:
+
+ -c| sets the value for configuration file which has server:port or host:port details.
+
+ -d| sets the value of directory containing the certificate files in crt or pem format.
+
+ -e| sets the value of certificate extention, e.g crt, pem, cert.
+ crt: default
+
+ -w| sets the value for writing the script output to a file.
+
+ -h| prints this help and exit.
+
+EOF
+exit 1
+}
+# print info messages
+info()
+{
+ printf '\n%s: %6s\n' "INFO" "$@"
+}
+# print error messages
+error()
+{
+ printf '\n%s: %6s\n' "ERROR" "$@"
+ exit 1
+}
+# print warning messages
+warn()
+{
+ printf '\n%s: %6s\n' "WARN" "$@"
+}
+# get expiry for the certificates
+getExpiry()
+{
+ local expdate=$1
+ local certname=$2
+ today=$(date +%s)
+ timetoexpire=$(( ($expdate - $today)/(60*60*24) ))
+
+ expcerts=( ${expcerts[@]} "${certname}:$timetoexpire" )
+}
+
+# print all expiry that was found, typically if there is any.
+printExpiry()
+{
+ local args=$#
+ i=0
+ if [[ $args -ne 0 ]]; then
+ #statements
+ printf '%s\n' "---------------------------------------------"
+ printf '%s\n' "List of expiring SSL certificates"
+ printf '%s\n' "---------------------------------------------"
+ printf '%s\n' "$@" | \
+ sort -t':' -g -k2 | \
+ column -s: -t | \
+ awk '{printf "%d.\t%s\n", NR, $0}'
+ printf '%s\n' "---------------------------------------------"
+ fi
+}
+
+# calculate the end date for the certificates first, finally to compare and predict when they are going to expire.
+calcEndDate()
+{
+ sslcmd=$(which openssl)
+ if [[ x$sslcmd = x ]]; then
+ #statements
+ error "$sslcmd command not found!"
+ fi
+ # when cert dir is given
+ if [[ $DIR -eq 1 ]]; then
+ #statements
+ checkcertexists=$(ls -A $TARGETDIR| egrep "*.$EXT$")
+ if [[ -z ${checkcertexists} ]]; then
+ #statements
+ error "no certificate files at $TARGETDIR with extention $EXT"
+ fi
+ for file in $TARGETDIR/*.${EXT:-crt}
+ do
+ expdate=$($sslcmd x509 -in $file -noout -enddate)
+ expepoch=$(date -d "${expdate##*=}" +%s)
+ certificatename=${file##*/}
+ getExpiry $expepoch ${certificatename%.*}
+ done
+ elif [[ $CONFIG -eq 1 ]]; then
+ #statements
+ while read line
+ do
+ if echo "$line" | \
+ egrep -q '^[a-zA-Z0-9.]+:[0-9]+|^[a-zA-Z0-9]+_.*:[0-9]+';
+ then
+ expdate=$(echo | \
+ openssl s_client -connect $line 2>/dev/null | \
+ openssl x509 -noout -enddate 2>/dev/null);
+ if [[ $expdate = '' ]]; then
+ #statements
+ warn "[error:0906D06C] Cannot fetch certificates for $line"
+ else
+ expepoch=$(date -d "${expdate##*=}" +%s);
+ certificatename=${line%:*};
+ getExpiry $expepoch ${certificatename};
+ fi
+ else
+ warn "[format error] $line is not in required format!"
+ fi
+ done < $CONFIGFILE
+ fi
+}
+# your script goes here
+while getopts ":c:d:w:e:h" options
+do
+case $options in
+c )
+ CONFIG=1
+ CONFIGFILE="$OPTARG"
+ if [[ ! -e $CONFIGFILE ]] || [[ ! -s $CONFIGFILE ]]; then
+ #statements
+ error "$CONFIGFILE does not exist or empty!"
+ fi
+ ;;
+e )
+ EXT="$OPTARG"
+ case $EXT in
+ crt|pem|cert )
+ info "Extention check complete."
+ ;;
+ * )
+ error "invalid certificate extention $EXT!"
+ ;;
+ esac
+ ;;
+d )
+ DIR=1
+ TARGETDIR="$OPTARG"
+ [ $TARGETDIR = '' ] && error "$TARGETDIR empty variable!"
+ ;;
+w )
+ WRITEFILE=1
+ OUTFILE="$OPTARG"
+ ;;
+h )
+ usage
+ ;;
+\? )
+ usage
+ ;;
+: )
+ fatal "Argument required !!! see \'-h\' for help"
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+#
+calcEndDate
+#finally print the list
+if [[ $WRITEFILE -eq 0 ]]; then
+ #statements
+ printExpiry ${expcerts[@]}
+else
+ printExpiry ${expcerts[@]} > $OUTFILE
+fi
+```
+
+#### 2. genSSLcsr.sh
+
+
+```
+#!/bin/bash -
+#===============================================================================
+#
+# FILE: genSSLcsr.sh
+#
+# USAGE: ./genSSLcsr.sh [options]
+#
+# DESCRIPTION: ++++version 1.0.2
+# Fixed few bugs from previous script
+# +Removing passphrase after CSR generation
+# Extended use of functions
+# Checks for valid common name
+# ++++1.0.3
+# Fixed line breaks
+# Work directory to be created at the start
+# Used getopts for better code arrangements
+# ++++1.0.4
+# Added mail feature (experimental at this time and needs
+# a mail server running locally.)
+# Added domain input and certificate subject inputs
+#
+# OPTIONS: ---
+# REQUIREMENTS: openssl, mailx
+# BUGS: ---
+# NOTES: ---
+# AUTHOR: Abhishek Tamrakar (), [abhishek.tamrakar08@gmail.com][7]
+# ORGANIZATION: Self
+# CREATED: 6/24/2016
+# REVISION: 4
+# COPYRIGHT AND
+# LICENSE: Copyright (C) 2016 Abhishek Tamrakar
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#===============================================================================
+
+#variables ges here
+#set basename to scriptname
+SCRIPT=${0##*/}
+
+#set flags
+TFOUND=0
+CFOUND=0
+MFOUND=0
+XFOUND=0
+SFOUND=0
+logdir=/var/log
+# edit these below values to replace with yours
+homedir=''
+yourdomain=''
+country=IN
+state=Maharashtra
+locality=Pune
+organization="your_organization"
+organizationalunit="your_organizational_unit"
+email=your_email@your_domain
+password=your_ssl_password
+# OS is declared and will be used in its next version
+OS=$(egrep -io 'Redhat|centos|fedora|ubuntu' /etc/issue)
+
+### function declarations ###
+
+info()
+{
+ printf '\n%s\t%s\t' "INFO" "$@"
+}
+
+#exit on error with a custom error message
+#the extra function was removed and replaced withonly one.
+#using FAILED\n\e<message> is a way but not necessarily required.
+#
+
+fatal()
+{
+ printf '\n%s\t%s\n' "ERROR" "$@"
+ exit 1
+}
+
+checkperms()
+{
+if [[ -z ${homedir} ]]; then
+homedir=$(pwd)
+fi
+if [[ -w ${homedir} ]]; then
+info "Permissions acquired for ${SCRIPT} on ${homedir}."
+else
+fatal "InSufficient permissions to run the ${SCRIPT}."
+fi
+}
+
+checkDomain()
+{
+info "Initializing Domain ${cn} check ? "
+if [[ ! -z ${yourdomain} ]]; then
+workdir=${homedir}/${yourdomain}
+echo -e "${cn}"|grep -E -i -q "${yourdomain}$" && echo -n "[OK]" || fatal "InValid domain in ${cn}"
+else
+workdir=${homedir}/${cn#*.}
+echo -n "[NULL]"
+info "WARNING: No domain declared to check."
+confirmUserAction
+fi
+} # end function checkDomain
+
+usage()
+{
+cat << EOF
+
+Usage: $SCRIPT [options] -[cdmshx]
+ [-c (common name)]
+ [-d (domain name)]
+ [-s (SSL certificate subject)]
+ [-p (password)]
+ [-m (email address)] *(Experimental)
+ [-r (remove pasphrase) default:true]
+ [-h (help)]
+ [-x (optional)]
+
+[OPTIONS]
+ -c| Sets the value for common name.
+ A valid common name is something that ends with 'xyz.com'
+
+ -d| Sets the domain name.
+
+ -s| Sets the subject to be applied to the certificates.
+ '/C=country/ST=state/L=locality/O=organization/OU=organizationalunit/emailAddress=email'
+
+ -p| Sets the password for private key.
+
+ -r| Sets the value of remove passphrase.
+ true:[default] passphrase will be removed from key.
+ false: passphrase will not be removed and key wont get printed.
+
+ -m| Sets the mailing capability to the script.
+ (Experimental at this time and requires a lot of work)
+
+ -x| Creates the certificate request and key but do not print on screen.
+ To be used when script is used just to create the key and CSR with no need
+ + to generate the certficate on the go.
+
+ -h| Displays the usage. No further functions are performed.
+
+ Example: $SCRIPT -c mywebsite.xyz.com -m [myemail@mydomain.com][6]
+
+EOF
+exit 1
+} # end usage
+
+confirmUserAction() {
+while true; do
+read -p "Do you wish to continue? ans: " yn
+case $yn in
+[Yy]* ) info "Initiating the process";
+break;;
+[Nn]* ) exit 1;;
+* ) info "Please answer yes or no.";;
+esac
+done
+} # end function confirmUserAction
+
+parseSubject()
+{
+ local subject="$1"
+ parsedsubject=$(echo $subject|sed 's/\// /g;s/^ //g')
+ for i in ${parsedsubject}; do
+ case ${i%=*} in
+ 'C' )
+ country=${i##*=}
+ ;;
+ 'ST' )
+ state=${i##*=}
+ ;;
+ 'L' )
+ locality=${i##*=}
+ ;;
+ 'O' )
+ organization=${i##*=}
+ ;;
+ 'OU' )
+ organizationalunit=${i##*=}
+ ;;
+ 'emailAddress' )
+ email=${i##*=}
+ ;;
+ esac
+ done
+}
+
+sendMail()
+{
+ mailcmd=$(which mailx)
+ if [[ x"$mailcmd" = "x" ]]; then
+ fatal "Cannot send email! please install mailutils for linux"
+ else
+ echo "SSL CSR attached." | $mailcmd -s "SSL certificate request" \
+ -t $email $ccemail -A ${workdir}/${cn}.csr \
+ && info "mail sent" \
+ || fatal "error in sending mail."
+ fi
+}
+
+genCSRfile()
+{
+info "Creating signed key request for ${cn}"
+#Generate a key
+openssl genrsa -des3 -passout pass:$password -out ${workdir}/${cn}.key 4096 -noout 2>/dev/null && echo -n "[DONE]" || fatal "unable to generate key"
+
+#Create the request
+info "Creating Certificate request for ${cn}"
+openssl req -new -key ${workdir}/${cn}.key -passin pass:$password -sha1 -nodes \
+ -subj "/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalunit/CN=$cn/emailAddress=$email" \
+ -out ${workdir}/${cn}.csr && echo -n "[DONE]" || fatal "unable to create request"
+
+if [[ "${REMOVEPASSPHRASE:-true}" = 'true' ]]; then
+ #statements
+ #Remove passphrase from the key. Comment the line out to keep the passphrase
+ info "Removing passphrase from ${cn}.key"
+ openssl rsa -in ${workdir}/${cn}.key \
+ -passin pass:$password \
+ -out ${workdir}/${cn}.insecure 2>/dev/null \
+ && echo -n "[DONE]" || fatal "unable to remove passphrase"
+ #swap the filenames
+ info "Swapping the ${cn}.key to secure"
+ mv ${workdir}/${cn}.key ${workdir}/${cn}.secure \
+ && echo -n "[DONE]" || fatal "unable to perfom move"
+ info "Swapping insecure key to ${cn}.key"
+ mv ${workdir}/${cn}.insecure ${workdir}/${cn}.key \
+ && echo -n "[DONE]" || fatal "unable to perform move"
+else
+ info "Flag '-r' is set, passphrase will not be removed."
+fi
+}
+
+printCSR()
+{
+if [[ -e ${workdir}/${cn}.csr ]] && [[ -e ${workdir}/${cn}.key ]]
+then
+echo -e "\n\n----------------------------CSR-----------------------------"
+cat ${workdir}/${cn}.csr
+echo -e "\n----------------------------KEY-----------------------------"
+cat ${workdir}/${cn}.key
+echo -e "------------------------------------------------------------\n"
+else
+fatal "CSR or KEY generation failed !!"
+fi
+}
+
+### END Functions ###
+
+#Check the number of arguments. If none are passed, print help and exit.
+NUMARGS=$#
+if [ $NUMARGS -eq 0 ]; then
+fatal "$NUMARGS Arguments provided !!!! See usage with '-h'"
+fi
+
+#Organisational details
+
+while getopts ":c:d:sⓂ️p:rhx" atype
+do
+case $atype in
+c )
+ CFOUND=1
+ cn="$OPTARG"
+ ;;
+d )
+ yourdomain="$OPTARG"
+ ;;
+s )
+ SFOUND=1
+ subj="$OPTARG"
+ ;;
+p )
+ password="$OPTARG"
+ ;;
+r )
+ REMOVEPASSPHRASE='false'
+ ;;
+m )
+ MFOUND=1
+ ccemail="$OPTARG"
+ ;;
+x )
+ XFOUND=1
+ ;;
+h )
+ usage
+ ;;
+\? )
+ usage
+ ;;
+: )
+ fatal "Argument required !!! see \'-h\' for help"
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+#### END CASE #### START MAIN ####
+
+if [ $CFOUND -eq 1 ]
+then
+# take current dir as homedir by default.
+checkperms ${homedir}
+checkDomain
+
+ if [[ ! -d ${workdir} ]]
+ then
+ mkdir ${workdir:-${cn#*.}} 2>/dev/null && info "${workdir} created."
+ else
+ info "${workdir} exists."
+ fi # end workdir check
+ parseSubject "$subj"
+ genCSRfile
+ if [ $XFOUND -eq 0 ]
+ then
+ sleep 2
+ printCSR
+ fi # end x check
+ if [[ $MFOUND -eq 1 ]]; then
+ sendMail
+ fi
+else
+ fatal "Nothing to do!"
+fi # end common name check
+
+##### END MAIN #####
+```
+
+* * *
+
+_This was originally published as the README in [ssl-on-demand's GitHub repository][4] and is reused with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/ssl-demand
+
+作者:[Abhishek Tamrakar][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/tamrakar
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security-lock-password.jpg?itok=KJMdkKum (Lock)
+[2]: https://opensource.com/alternatives/slack
+[3]: https://opensource.com/article/19/1/what-certificate
+[4]: https://github.com/abhiTamrakar/ssl-on-demand
+[5]: https://en.wikipedia.org/wiki/Certificate_signing_request
+[6]: mailto:myemail@mydomain.com
+[7]: mailto:abhishek.tamrakar08@gmail.com
diff --git a/sources/tech/20200214 How to restore a single-core computer with Linux.md b/sources/tech/20200214 How to restore a single-core computer with Linux.md
new file mode 100644
index 0000000000..a88a2c157d
--- /dev/null
+++ b/sources/tech/20200214 How to restore a single-core computer with Linux.md
@@ -0,0 +1,270 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to restore a single-core computer with Linux)
+[#]: via: (https://opensource.com/article/20/2/restore-old-computer-linux)
+[#]: author: (Howard Fosdick https://opensource.com/users/howtech)
+
+How to restore a single-core computer with Linux
+======
+Let's have some geeky fun refurbishing your prehistoric Pentium with
+Linux and open source.
+![Two animated computers waving one missing an arm][1]
+
+In a [previous article][2], I explained how I refurbish old dual-core computers ranging from roughly five to 15 years old. Properly restored, these machines can host a fully capable lightweight Linux distribution like [Mint/Xfce][3], [Xubuntu][4], or [Lubuntu][5] and perform everyday tasks. But what if you have a really old computer gathering dust in your attic or basement? Like a Pentium 4 desktop or Pentium M laptop? Yikes! Can you even do anything with a relic like that?
+
+### Why restore a relic?
+
+For starters, you might learn a bit about hardware and open source software by refurbishing it. And you could have some fun along the way. Whether you can make much use of it depends on your expectations.
+
+A single-core computer can perform well for a specific purpose. For example, my friend created a dandy retro gaming box (like I describe below) that runs hundreds of Linux and old Windows and DOS games. His kids love it!
+
+Another friend uses his Pentium 4 for running design spreadsheets in his workshop. He finds it convenient to have a dedicated machine tucked into a corner of his shop. He likes that he doesn't have to worry about heat or dust ruining an expensive modern computer.
+
+My romance author acquaintance employs her Pentium M as a "novelist's workstation" lodged in her cozy attic hideaway. The laptop functions as her private word processor.
+
+I've used old computers to teach beginners how to build and repair hardware. Old equipment makes the best testbed because it's expendable. If someone makes a mistake and fries a board, it doesn't much matter. (Contrast this to how you would feel if you wrecked your main computer!)
+
+The web suggests many [other potential uses][6] for old Pentiums: security cam monitors, network-attached storage (NAS) servers, [SETI][7] boxes, torrent servers, anonymous [Tails][8] servers, Bitcoin miners, programming workstations, thin clients, terminal emulators, routers, file servers, and more. To me, many of these applications sound more like fun projects than practical uses for single-core computers. That doesn't mean they aren't worth your while; it's just that you want to be clear-eyed about any project you take on.
+
+By current standards, P-4s and Ms are terribly [weak processors][9]. For example, using them for web surfing is problematic because webpage size and programming complexity have [grown exponentially][10]. And the open web is closing—increasingly, sites won't allow you access unless you let them run all those ads that can overwhelm old processors. (I'll discuss web surfing performance tricks later in this article.) Another shortcoming of old computers is their energy consumption. Better electricity-to-performance ratios often make newer computers more sensible. This especially true when a [tablet or smartphone][11] can fulfill your needs.
+
+Nevertheless, you can still have fun and learn a lot by tinkering with an old P-4 or M. They're great educational tools, they're expendable, and they can be useful in dedicated roles. Best of all, you can get them for free. I'll tell you how.
+
+Still reading? Okay, let's have some geeky fun refurbishing your prehistoric Pentium.
+
+### Understand hardware evolution
+
+As a quick level-set, here are the common names for the P-4 and M class processors and their rough dates of manufacture:
+
+**Desktops (2000-2008)**
+
+ * Pentium 4
+ * Pentium 4 HT (Hyper-Threading)
+ * Pentium 4 EE (Extreme Edition)
+
+
+
+**Desktops (2005-2008)**
+
+ * Pentium D (early dual-core)
+
+
+
+**Mobile (2002-2008)**
+
+ * Pentium M
+ * Pentium 4-M
+ * Mobile Pentium 4
+ * Mobile Pentium 4 HT
+
+
+
+Sources: Wikipedia (for the [P-4][12], [P-M][13], and [processor][14] lists), [CPU World,][15] [Revolvy][16].
+
+Machines hosting these processors typically use either DDR2 or DDR memory. Dual-core processors entered the market in 2005 and displaced single-core CPUs within a few years. I'll assume you have some version of what's in the above table. Or you might have an equivalent [AMD][17] or [Celeron][18] processor from the same era.
+
+The big draw of this old hardware is that you can get it for free. People consider it junk. They'll be only too glad to give you their castoffs. If you don't have a machine on hand, just ask your friends or family. Or drop by the local recycling center. Unless they have strict rules, they'll be happy to give you this old equipment. You can even advertise on [Craigslist][19], [Freecycle,][20] or [other reuse websites][21].
+
+**A quick tip:** Grab more than one machine. With old hardware, you often need to cannibalize parts from several computers to build one good working one.
+
+### Prepare the hardware
+
+Before you can use your old computer, you must refurbish it. The steps to fixing it up are:
+
+ 1. Clean it
+ 2. Identify what hardware you have
+ 3. Verify the hardware works
+
+
+
+Start by opening up the box and cleaning out the dirt. Dust causes the heat that kills electronics. A can of compressed air helps.
+
+Always keep yourself grounded when touching things so that you don't harm the electronics. And don't rub anything with a cleaning rag! Even a shock you can't feel can damage computer circuitry.
+
+While you've got the box open, learn everything you can about your hardware. Write it all down, so you remember it later:
+
+ * Count the open memory slots, if any. Is the RAM DDR or DDR2 (or something else)?
+ * Read the hard drive label to learn its capacity and age. (It'll probably be an old IDE drive. You can identify IDE drives by their wide connector ribbons.)
+ * Check the optical drive label to see what kinds of discs it reads and/or writes, at what speed, and to what standard(s).
+ * Note other peripherals, add-in cards, or anything unusual.
+
+
+
+Close and boot the machine into its boot-time [BIOS][22] panels. [This list][23] tells you what program function (PF) key to press to access those startup panels for your specific computer. Now you can complete your hardware identification by rounding out the details on your processor, memory, video memory, and more.
+
+### Verify the hardware
+
+Once you know what you've got, verify that it all works. Test:
+
+ * Memory
+ * Disk
+ * Motherboard
+ * Peripherals (optical drive, USB ports, sound, etc.)
+
+
+
+Run any diagnostic tests in the computer's boot or BIOS panels. Free resource kits like [Hiren's BootCD][24] or the [Ultimate Boot CD][25] can round out your testing with any diagnostics your boot panels lack. These kits offer dozens of testing programs: all are free, but not all are open source. You can boot them off a live USB or DVD so that you don't have to install anything on the computer.
+
+Be sure to run the "extended" or long tests for the memory and disk drive. Run tests overnight if you have to. Do this job right! If you miss a problem now, it could cause you big headaches later.
+
+If you find a problem, refer to my _[Quick guide to fixing hardware][26]_ to solve common issues.
+
+### Essential hardware upgrades
+
+You'll want to make two key hardware upgrades. First, increase memory to the computer's maximum. (You can find the maximum for your computer with a quick web search for its specs.) The practical minimum to run many lightweight Linux distros is 1GB RAM; 2GB or more is ideal. While the maximum allowable memory varies by the machine, the great majority of these computers will upgrade to at least 2GB.
+
+Second—if the desktop doesn't already have one—add a video card. This offloads graphics processing from the motherboard to the video card and increases the computer's video memory. Bumping up the VRAM from 32 or 64MB to 256GB or more greatly increases the range of applications an old computer can run. Especially if you want to run games.
+
+Be sure the video card fits your computer's [video slot][27] (AGP, PCI, or PCI-Express) and has the right [cable connector][28] (VGA or DVI). You can issue a couple of [Linux line commands][29] to see how much VRAM your system has, or look in the BIOS boot panels.
+
+These two simple upgrade hacks—increasing memory and video power—take a marginal machine and make it _way_ more functional. Your goal is to build the most powerful P-4 or M ever. That way, you can squeeze the most performance from this aging design.
+
+The good news is that with the old computers we're talking about, you can get any parts you need for free. Just cannibalize them from other discarded PC's.
+
+### Select the software
+
+Choosing the right software for a P-4 or M is critical. [Don't][30] use an [unsupported][31] Windows version just because it's already on the PC; malware might plague you if you do. A fresh install is mandatory.
+
+Open source software is the way to go. [Many][32] Linux [distributions][33] are specifically designed for older computers. And with Linux, you can install, move, copy, and clone the operating system and its apps at will. This makes your job easier: You won't run into activation or licensing issues, and it's all free.
+
+Which distribution should you pick? Assuming you have at least 2GB of memory, start your search by trying a _lightweight distribution_—these feature resource-stingy [desktop environments][34]. Xfce or LXQt are excellent desktop environment choices. Products that [consume more resources][35] or produce fancier graphics—like Unity, GNOME, KDE, MATE, and Cinnamon—won't perform well.
+
+The lightweight Linux distros I've enjoyed success with are Mint/Xfce, Xubuntu, and Lubuntu. The first two use Xfce while Lubuntu employs LXQt. You can find [many other][36] excellent candidate distros beyond these three choices that I can vouch for.
+
+Be sure to download the 32-bit versions of the operating systems; 64-bit versions don't make much sense unless a computer has at least 4GB of memory.
+
+The lightweight Linux distros I've cited offer friendly menus and feature huge software repositories backed by active forums. They'll enable your old computer to do everything it's capable of. However, they won't run on every computer from the P-4 era. If one of these products runs on your computer and you like it, great! You've found your distro.
+
+If your computer doesn't perform well with these selections, won't boot, or you have less than 2GB of memory, try an _ultralight distribution_. Ultralights reduce resource use by replacing desktop environments with [window managers][37] like Fluxbox, FLWM, IceWM, JWM, or Openbox. Window managers use fewer resources than desktop environments. The trade-off is that they're less flexible. As an example, you may have to dip into code to alter your desktop or taskbar icons.
+
+My go-to ultralight distro is [Puppy Linux][38]. It comes in several variants that run well on Pentium 4's and M's with only 1GB of memory. Puppy's big draw is that it has versions designed specifically for older computers. This means you'll avoid the hassles you might run into with other distros. For example, Puppy versions run on old CPUs that don't support features like PAE or SSE3. They'll even help you run an older kernel or obsolete bootstrap program if your hardware requires it.
+
+And Puppy runs _fast_ on limited-resource computers! It optimizes performance by loading the operating system entirely into memory to avoid slow disk access. It bundles a full range of apps that have been carefully selected to use minimal hardware resources.
+
+Puppy is also user-friendly. Even a naive end user can use its simple menus and attractive desktop. But be advised—it takes expertise to install and configure the product. You might have to spend some time on Puppy's [forum][39] to get oriented. The forum is especially useful because many who post there work with old computers.
+
+A fun alternative to Puppy is [Tiny Core][40] Linux. With Tiny Core, you install only the software components you want. So you build up your environment from the absolute minimum. This takes time but results in a lean, mean system. Tiny Core is perfect for creating a dedicated server. It's a great learning tool, too, so check out its [free eBook][41].
+
+If you want a quick, no-hassles install, you might try [antiX][42]. It's Debian-based, offers a selection of lightweight interfaces, and runs well on machines with only a gigabyte of memory. I've had excellent results installing antiX on a variety of old PCs.
+
+_**Caution:**_ Many distros casually claim that they run on "old computers" when they really mean that they run on _limited-resource computers_. There's a big difference. Old computers sometimes do not support all the CPU features required by newer operating systems. Avoid problems by selecting a Linux proven to run on your hardware.
+
+Don't know if a distro will run on your box? Save yourself some time by posting a message on the distro's forum and asking for responses from folks using hardware like yours. You should receive some success stories. If nobody can say they've done what you're trying to do, I'd avoid that product.
+
+### How to use your refurbished computer
+
+Will you be happy using your restored PC? It depends on what you expect.
+
+People who use aging systems learn to leverage minimal resources. For example, they run resource-stingy programs like GNOME Office in place of LibreOffice. They forgo CPU-intense programs like emulators, graphics-heavy apps, video processing, and virtual machine hosting. They focus on one task at a time and don't expect much concurrency. And they know how to manage machine resources proactively.
+
+Old hardware can perform well in dedicated situations. Earlier, I mentioned my friends who use their old computers for design spreadsheets and as a writer's workbench. And I wrote this article on my personal retro box—a Dell GX280 desktop with a Pentium 4 at 3.2GHz, with 2GB DDR-2 RAM and two 40GB IDE disks, dual-booting Puppy and antiX.
+
+#### Create a retro game box
+
+You can also create a fantastic retro game box. First, install an appropriate distro. Then install [Wine][43], a program designed to run Windows software on Linux. Now you'll be able to run nearly all your old Windows XP, ME/98/95, and 3.1 games. [DOSBox][44] supports tons more [free DOS games][45]. And Linux offers over a thousand more.
+
+I've enjoyed nostalgic fun on a P-4 running antiX and all the old games I remember from years ago. Just be sure you've maxed out system memory and added a good video card for the best results.
+
+#### Access the web
+
+The big challenge with old computers is web surfing. [This study][46] claims that average website size has increased 100% over a three-year period, while [this article][47] tells how bloated news sites have become. Videos, animation, images, trackers, ad requests—they all make websites slower than just a few years ago.
+
+Worse, websites increasingly refuse you access unless you allow them to run their ads. This is a problem because the ads can overwhelm old CPUs. In fact, for most websites, the resources required to run ads and trackers are _way_ greater than that required for the actual website content.
+
+Here are the performance tricks you need to know if you web surf with an older computer:
+
+ * Run the fastest, lightest browser possible. Chrome, Firefox, and Opera are probably the top mainstream offerings.
+ * Try alternative [minimalist browsers][48] to see if they can meet your needs: [Dillo][49], [NetSurf][50], [Dooble][51], [Lynx][52], [Links][53], or others.
+ * Actively manage your browser.
+ * Don't open many browser tabs.
+ * Manually start and stop processing in specific tabs.
+ * Block ads and trackers:
+ * Offload this chore to your virtual private network (VPN) if at all possible.
+ * Otherwise, use a browser extension.
+ * Don't slow down your browser by installing add-ons or extensions beyond the minimum required.
+ * Disable autoplay for videos and Flash.
+ * Toggle JavaScript off and on.
+ * Ensure the browser renders text before graphics.
+ * Don't run background tasks while web surfing.
+ * Manually clear cookies to avoid page-access limits on some websites.
+ * Linux means you don't have to run real-time anti-malware (which consumes a CPU core on many Windows PCs).
+
+
+
+Employing some of these tricks, I happily use refurbished dual-core computers for all my web surfing. But with today's internet, I find single-core processors inadequate for anything beyond the occasional web lookup. In other words, they're acceptable for _web access_ but insufficient for _web surfing_. That's just my opinion. Yours may vary depending on your expectations and the nature of your web activity.
+
+### Enjoy free educational fun
+
+However you use your refurbished P-4 or M, you'll know a lot more about computer hardware and open source software than when you started. It won't cost you a penny, and you'll have some fun along the way!
+
+Please share your own refurbishing experiences in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/restore-old-computer-linux
+
+作者:[Howard Fosdick][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/howtech
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_other11x_cc.png?itok=I_kCDYj0 (Two animated computers waving one missing an arm)
+[2]: http://opensource.com/article/19/7/how-make-old-computer-useful-again
+[3]: http://linuxmint.com/
+[4]: https://xubuntu.org/
+[5]: http://lubuntu.me/
+[6]: http://www.google.com/search?q=uses+for+a+pentium+IV
+[7]: https://en.wikipedia.org/wiki/Search_for_extraterrestrial_intelligence
+[8]: https://en.wikipedia.org/wiki/Tails_(operating_system)
+[9]: http://www.cpubenchmark.net/low_end_cpus.html
+[10]: http://www.digitaltrends.com/web/internet-is-getting-slower/
+[11]: https://www.forbes.com/sites/christopherhelman/2013/09/07/how-much-energy-does-your-iphone-and-other-devices-use-and-what-to-do-about-it/#ba4918e2f702
+[12]: https://en.wikipedia.org/wiki/Pentium_4
+[13]: https://en.wikipedia.org/wiki/Pentium_M
+[14]: https://en.wikipedia.org/wiki/List_of_Intel_Pentium_4_microprocessors
+[15]: http://www.cpu-world.com/CPUs/Pentium_4/index.html
+[16]: https://www.revolvy.com/page/List-of-Intel-Pentium-4-microprocessors?cr=1
+[17]: https://en.wikipedia.org/wiki/List_of_AMD_microprocessors
+[18]: https://en.wikipedia.org/wiki/Celeron
+[19]: https://www.craigslist.org/about/sites
+[20]: https://www.freecycle.org/
+[21]: https://alternativeto.net/software/freecycle/
+[22]: http://en.wikipedia.org/wiki/BIOS
+[23]: http://www.disk-image.com/faq-bootmenu.htm
+[24]: http://www.hirensbootcd.org/download/
+[25]: http://www.ultimatebootcd.com/
+[26]: http://www.rexxinfo.org/Quick_Guide/Quick_Guide_To_Fixing_Computer_Hardware
+[27]: http://www.playtool.com/pages/vidslots/slots.html
+[28]: https://silentpc.com/articles/video-connectors
+[29]: https://www.cyberciti.biz/faq/howto-find-linux-vga-video-card-ram/
+[30]: https://fusetg.com/dangers-running-unsupported-operating-system/
+[31]: http://home.bt.com/tech-gadgets/computing/windows-7/windows-7-support-end-11364081315419
+[32]: https://itsfoss.com/lightweight-linux-beginners/
+[33]: https://fossbytes.com/best-lightweight-linux-distros/
+[34]: https://en.wikipedia.org/wiki/Desktop_environment
+[35]: http://www.phoronix.com/scan.php?page=article&item=ubu-1704-desktops&num=3
+[36]: https://www.google.com/search?ei=TfIoXtG5OYmytAbl04z4Cw&q=best+lightweight+linux+distros+for+old+computers&oq=best+lightweight+linux+distros+for+old&gs_l=psy-ab.1.0.0i22i30l8j0i333.6806.8527..10541...2.2..0.159.1119.2j8......0....1..gws-wiz.......0i71j0.a6LTmaIXan0
+[37]: https://en.wikipedia.org/wiki/X_window_manager
+[38]: http://puppylinux.com/
+[39]: http://murga-linux.com/puppy/
+[40]: http://tinycorelinux.net/
+[41]: http://tinycorelinux.net/book.html
+[42]: http://antixlinux.com/
+[43]: https://www.winehq.org/
+[44]: https://en.wikipedia.org/wiki/DOSBox
+[45]: https://www.dosgamesarchive.com/
+[46]: https://www.digitaltrends.com/web/internet-is-getting-slower/
+[47]: https://www.forbes.com/sites/kalevleetaru/2016/02/06/why-the-web-is-so-slow-and-what-it-tells-us-about-the-future-of-online-journalism/#34475c2072f4
+[48]: http://en.wikipedia.org/wiki/Comparison_of_lightweight_web_browsers
+[49]: http://www.dillo.org/
+[50]: http://www.netsurf-browser.org/
+[51]: http://textbrowser.github.io/dooble/
+[52]: http://lynx.browser.org/
+[53]: http://en.wikipedia.org/wiki/Links_%28web_browser%29
diff --git a/sources/tech/20200217 Automating unit tests in test-driven development.md b/sources/tech/20200217 Automating unit tests in test-driven development.md
new file mode 100644
index 0000000000..fc3971effe
--- /dev/null
+++ b/sources/tech/20200217 Automating unit tests in test-driven development.md
@@ -0,0 +1,69 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Automating unit tests in test-driven development)
+[#]: via: (https://opensource.com/article/20/2/automate-unit-tests)
+[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
+
+Automating unit tests in test-driven development
+======
+What unit tests have in common with carpentry.
+![gears and lightbulb to represent innovation][1]
+
+DevOps is a software engineering discipline focused on minimizing the lead time to achieve a desired business impact. While business stakeholders and sponsors have ideas on how to optimize business operations, those ideas need to be validated in the field. This means business automation (i.e., software products) must be placed in front of end users and paying customers. Only then will the business confirm whether the initial idea for improvement was fruitful or not.
+
+Software engineering is a budding discipline, and it can get difficult to ship products that are defect-free. For that reason, DevOps resorts to maximizing automation. Any repeatable chore, such as testing implemented changes to the source code, should be automated by DevOps engineers.
+
+This article looks at how to automate unit tests. These tests are focused on what I like to call "programming in the small." Much more important test automation (the so-called "programming in the large") must use a different discipline—integration testing. But that's a topic for another article.
+
+### What is a unit?
+
+When I'm teaching approaches to unit testing, often, my students cannot clearly determine what a testable unit is. Which is to say, the granularity of the processing is not always clear.
+
+I like to point out that the easiest way to spot a valid unit is to think of it as a _unit of behavior_. For example (albeit a trivial one), when an authenticated customer begins online shopping, the unit of behavior is a cart that has zero items in it. Once we all agree that an empty shopping cart has zero items in it, we can focus on automating the unit test that will ensure that such a shopping cart always returns zero items.
+
+### What is not a unit?
+
+Any processing that involves more than a single behavior should not be viewed as a unit. For example, if shopping cart processing results in tallying up the number of items in the cart AND calculating the order total AND calculating sales tax AND calculating the suggested shipping method, that behavior is not a good candidate for unit testing. Such behavior is a good candidate for integration testing.
+
+### When to write a unit test
+
+There is a lot of debate about when to write a unit test. Received wisdom states that once the code has been written, it is a good idea to write automated scripts that will assert whether the implemented unit of behavior delivers functionality as expected. Not only does such a unit test (or a few unit tests) document the expected behavior, the collection of all unit tests ensures that future changes will not degrade quality. If a future change adversely affects the already implemented behavior, one or more unit tests will complain, which will alert developers that regression has occurred.
+
+There is another way to look at software engineering. It is based on the traditional adage "measure twice, cut once." In that light, writing code before writing tests would be equivalent to cutting a part of some product (say, a chair leg) and measuring it only after it's cut. If the craftsperson doing the cutting is very skilled, that approach may work (kind of). But more likely than not, the chair legs cut this way would end up with unequal lengths. So, it is advisable to measure before cutting. What that means for the practice of software engineering is that the measurements are expressed in the unit tests. Once we measure the required values, we create a blueprint (a unit test). That blueprint is then used to guide the cutting of the code.
+
+Common sense would suggest that it is more reasonable to measure first and, only then, do the cutting. According to that line of reasoning, writing unit tests before writing code is a recommended way to do proper software engineering. Technically speaking, this "measure twice, cut once" approach is called a "test-first" approach. The opposite approach, where we write the code first, is called "test-later." The test-first approach is the approach advocated by [test-driven development][2] (TDD) methodology. Writing tests later is called test-later development (TLD).
+
+### Why is TLD harmful?
+
+Cutting before measuring is not recommended. Even the most talented craftspeople will eventually make mistakes by cutting without doing so. A lack of measurement will eventually catch up with even the most experienced of us as we continue in our craft. So it's best to produce a blueprint (i.e., measurements) before cutting.
+
+But that's not the only reason why the TLD approach is considered harmful. When we write code, we're simultaneously considering two separate concerns: the expected behavior of the code and the optimal structure of the code. These two concerns are very dissimilar. That fact makes it very challenging to do a proper job satisfying the expectations regarding both the desired behavior and the optimal (or at the very least, decent) code structure.
+
+The TDD approach solves this conundrum by focusing undivided attention first on the expected desired behavior. We start by writing the unit test. In that test, we focus on _what_ we expect to happen. At this point, we don't care, in the least, _how_ the expected behavior is going to materialize.
+
+Once we're done describing the _what_ (i.e., what manifest behavior are we expecting from the unit we are about to build?), we watch that expectation fail. It fails because the code that is concerned with _how_ the expected behavior is going to happen hasn't materialized yet. Now we are compelled to write the code that's going to take care of the _how_.
+
+After we write the code responsible for how, we run the unit test(s) and see if the code we just wrote fulfills the expected behavior. If it does, we're done. Time to move on to fulfilling the next expectation. If it doesn't, we continue transforming the code until it succeeds in passing the test.
+
+If we choose not to do TDD, but write code first and later write the unit test, we miss the opportunity to separate _what_ from _how_. In other words, we write the code while simultaneously taking care of what we expect the code to do _and_ how to structure the code to do it correctly.
+
+As such, writing unit tests after we write code is considered harmful.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/automate-unit-tests
+
+作者:[Alex Bunardzic][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alex-bunardzic
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/innovation_lightbulb_gears_devops_ansible.png?itok=TSbmp3_M (gears and lightbulb to represent innovation)
+[2]: https://opensource.com/article/20/1/test-driven-development
diff --git a/sources/tech/20200217 Create web user interfaces with Qt WebAssembly instead of JavaScript.md b/sources/tech/20200217 Create web user interfaces with Qt WebAssembly instead of JavaScript.md
new file mode 100644
index 0000000000..bc61dab48d
--- /dev/null
+++ b/sources/tech/20200217 Create web user interfaces with Qt WebAssembly instead of JavaScript.md
@@ -0,0 +1,133 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Create web user interfaces with Qt WebAssembly instead of JavaScript)
+[#]: via: (https://opensource.com/article/20/2/wasm-python-webassembly)
+[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
+
+Create web user interfaces with Qt WebAssembly instead of JavaScript
+======
+Get hands-on with Wasm, PyQt, and Qt WebAssembly.
+![Digital creative of a browser on the internet][1]
+
+When I first heard about [WebAssembly][2] and the possibility of creating web user interfaces with Qt, just like I would in ordinary C++, I decided to take a deeper look at the technology.
+
+My open source project [Pythonic][3] is completely Python-based (PyQt), and I use C++ at work; therefore, this minimal, straightforward WebAssembly tutorial uses Python on the backend and C++ Qt WebAssembly for the frontend. It is aimed at programmers who, like me, are not familiar with web development.
+
+![Header Qt C++ frontend][4]
+
+### TL;DR
+
+
+```
+git clone
+
+cd wasm_qt_example
+
+python mysite.py
+```
+
+Then visit with your favorite browser.
+
+### What is WebAssembly?
+
+WebAssembly (often shortened to Wasm) is designed primarily to execute portable binary code in web applications to achieve high-execution performance. It is intended to coexist with JavaScript, and both frameworks are executed in the same sandbox. [Recent performance benchmarks][5] showed that WebAssembly executes roughly 10–40% faster, depending on the browser, and given its novelty, we can still expect improvements. The downside of this great execution performance is its widespread adoption as the preferred malware language. Crypto miners especially benefit from its performance and harder detection of evidence due to its binary format.
+
+### Toolchain
+
+There is a [getting started guide][6] on the Qt wiki. I recommend sticking exactly to the steps and versions mentioned in this guide. You may need to select your Qt version carefully, as different versions have different features (such as multi-threading), with improvements happening with each release.
+
+To get executable WebAssembly code, simply pass your Qt C++ application through [Emscripten][7]. Emscripten provides the complete toolchain, and the build script couldn't be simpler:
+
+
+```
+#!/bin/sh
+source ~/emsdk/emsdk_env.sh
+~/Qt/5.13.1/wasm_32/bin/qmake
+make
+```
+
+Building takes roughly 10 times longer than with a standard C++ compiler like Clang or g++. The build script will output the following files:
+
+ * WASM_Client.js
+ * WASM_Client.wasm
+ * qtlogo.svg
+ * qtloader.js
+ * WASM_Client.html
+ * Makefile (intermediate)
+
+
+
+The versions on my (Fedora 30) build system are:
+
+ * emsdk: 1.38.27
+ * Qt: 5.13.1
+
+
+
+### Frontend
+
+The frontend provides some functionalities based on [WebSocket][8].
+
+![Qt-made frontend in browser][9]
+
+ * **Send message to server:** Send a simple string message to the server with a WebSocket. You could have done this also with a simple HTTP POST request.
+ * **Start/stop timer:** Create a WebSocket and start a timer on the server to send messages to the client at a regular interval.
+ * **Upload file:** Upload a file to the server, where the file is saved to the home directory (**~/**) of the user who runs the server.
+
+
+
+If you adapt the code and face a compiling error like this:
+
+
+```
+error: static_assert failed due to
+ requirement ‘bool(-1 == 1)’ “Required feature http for file
+ ../../Qt/5.13.1/wasm_32/include/QtNetwork/qhttpmultipart.h not available.”
+QT_REQUIRE_CONFIG(http);
+```
+
+it means that the requested feature is not available for Qt Wasm.
+
+### Backend
+
+The server work is done by [Eventlet][10]. I chose Eventlet because it is lightweight and easy to use. Eventlet provides WebSocket functionality and supports threading.
+
+![Decorated functions for WebSocket handling][11]
+
+Inside the repository under **mysite/template**, there is a symbolic link to **WASM_Client.html** in the root path. The static content under **mysite/static** is also linked to the root path of the repository. If you adapt the code and do a recompile, you just have to restart Eventlet to update the content to the client.
+
+Eventlet uses the Web Server Gateway Interface for Python (WSGI). The functions that provide the specific functionality are extended with decorators.
+
+Please note that this is an absolute minimum server implementation. It doesn't implement any multi-user capabilities — every client is able to start/stop the timer, even for other clients.
+
+### Conclusion
+
+Take this example code as a starting point to get familiar with WebAssembly without wasting time on minor issues. I don't make any claims for completeness nor best-practice integration. I walked through a long learning curve until I got it running to my satisfaction, and I hope this gives you a brief look into this promising technology.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/wasm-python-webassembly
+
+作者:[Stephan Avenwedde][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hansic99
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
+[2]: https://webassembly.org/
+[3]: https://github.com/hANSIc99/Pythonic
+[4]: https://opensource.com/sites/default/files/uploads/cpp_qt.png (Header Qt C++ frontend)
+[5]: https://pspdfkit.com/blog/2018/a-real-world-webassembly-benchmark/
+[6]: https://wiki.qt.io/Qt_for_WebAssembly#Getting_Started
+[7]: https://emscripten.org/docs/introducing_emscripten/index.html
+[8]: https://en.wikipedia.org/wiki/WebSocket
+[9]: https://opensource.com/sites/default/files/uploads/wasm_frontend.png (Qt-made frontend in browser)
+[10]: https://eventlet.net/
+[11]: https://opensource.com/sites/default/files/uploads/python_backend.png (Decorated functions for WebSocket handling)
diff --git a/sources/tech/20200218 10 Grafana features you need to know for effective monitoring.md b/sources/tech/20200218 10 Grafana features you need to know for effective monitoring.md
new file mode 100644
index 0000000000..92f1cc3455
--- /dev/null
+++ b/sources/tech/20200218 10 Grafana features you need to know for effective monitoring.md
@@ -0,0 +1,69 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (10 Grafana features you need to know for effective monitoring)
+[#]: via: (https://opensource.com/article/20/2/grafana-features)
+[#]: author: (Daniel Lee https://opensource.com/users/daniellee)
+
+10 Grafana features you need to know for effective monitoring
+======
+Learn how to make the most of this open source dashboard tool.
+![metrics and data shown on a computer screen][1]
+
+The [Grafana][2] project [started in 2013][3] when [Torkel Ödegaard][4] decided to fork Kibana and turn it into a time-series and graph-focused dashboarding tool. His guiding vision: to make everything look more clean and elegant, with fewer things distracting you from the data.
+
+More than 500,000 active installations later, Grafana dashboards are ubiquitous and instantly recognizable. (Even during a [SpaceX launch][5]!)
+
+Whether you're a recent adopter or an experienced power user, you may not be familiar with all of the features that [Grafana Labs][6]—the company formed to accelerate the adoption of the Grafana project and to build a sustainable business around it—and the Grafana community at large have developed over the past 6+ years.
+
+Here's a look at some of the most impactful:
+
+ 1. **Dashboard templating**: One of the key features in Grafana, templating allows you to create dashboards that can be reused for lots of different use cases. Values aren't hard-coded with these templates, so for instance, if you have a production server and a test server, you can use the same dashboard for both. Templating allows you to drill down into your data, say, from all data to North America data, down to Texas data, and beyond. You can also share these dashboards across teams within your organization—or if you create a great dashboard template for a popular data source, you can contribute it to the whole community to customize and use.
+ 2. **Provisioning**: While it's easy to click, drag, and drop to create a single dashboard, power users in need of many dashboards will want to automate the setup with a script. You can script anything in Grafana. For example, if you're spinning up a new Kubernetes cluster, you can also spin up a Grafana automatically with a script that would have the right server, IP address, and data sources preset and locked. It's also a way of getting control over a lot of dashboards.
+ 3. **Annotations:** This feature, which shows up as a graph marker in Grafana, is useful for correlating data in case something goes wrong. You can create the annotations manually—just control-click on a graph and input some text—or you can fetch data from any data source. (Check out how Wikimedia uses annotations on its [public Grafana dashboard][7], and here is [another example][8] from the OpenHAB community.) A good example is if you automatically create annotations around releases, and a few hours after a new release, you start seeing a lot of errors, then you can go back to your annotation and correlate whether the errors started at the same time as the release. This automation can be achieved using the Grafana HTTP API (see examples [here][9] and [here][10]). Many of Grafana's largest customers use the HTTP API for a variety of tasks, particularly setting up databases and adding users. It's an alternative to provisioning for automation, and you can do more with it. For instance, the team at DigitalOcean used the API to integrate a [snapshot feature for reviewing dashboards][11].
+ 4. **Kiosk mode and playlists:** If you want to display your Grafana dashboards on a TV monitor, you can use the playlist feature to pick the dashboards that you or your team need to look at through the course of the day and have them cycle through on the screen. The [kiosk mode][12] hides all the user interface elements that you don't need in view-only mode. Helpful hint: The [Grafana Kiosk][13] utility handles logging in, switching to kiosk mode, and opening a playlist—eliminating the pain of logging in on a TV that has no keyboard.
+ 5. **Custom plugins:** Plugins allow you to extend Grafana with integrations with other tools, different visualizations, and more. Some of the most popular in the community are [Worldmap Panel][14] (for visualizing data on top of a map), [Zabbix][15] (an integration with Zabbix metrics), and [Influx Admin Panel][16] (which offers other functionality like creating databases or adding users). But they're only the tip of the iceberg. Just by writing a bit of code, you can get anything that produces a timestamp and a value visualized in Grafana. Plus, Grafana Enterprise customers have access to more plugins for integrations with Splunk, Datadog, New Relic, and others.
+ 6. **Alerting and alert hooks:** If you're using Grafana alerting, you can have alerts sent through a number of different notifiers, including PagerDuty, SMS, email, or Slack. Alert hooks allow you to create different notifiers with a bit of code if you prefer some other channels of communication.
+ 7. **Permissions and teams**: When organizations have one Grafana and multiple teams, they often want the ability to both keep things separate and share dashboards. Early on, the default in Grafana was that everybody could see everyone else's dashboards, and that was it. Later, Grafana introduced multi-tenant mode, in which you can switch organizations but can't share dashboards. Some people were using huge hacks to enable both, so Grafana decided to officially create an easier way to do this. Now you can create a team of users and then set permissions on folders, dashboards, and down to the data source level if you're using Grafana Enterprise.
+ 8. **SQL data sources:** Grafana's native support for SQL helps you turn anything—not just metrics—in an SQL database into metric data that you can graph. Power users are using SQL data sources to do a whole bunch of interesting things, like creating business dashboards that "make sense for your boss's boss," as the team at Percona put it. Check out their [presentation at GrafanaCon][17].
+ 9. **Monitoring your monitoring**: If you're serious about monitoring and you want to monitor your own monitoring, Grafana has its own Prometheus HTTP endpoint that Prometheus can scrape. It's quite simple to get dashboards and statics. There's also an enterprise version in development that will offer Google Analytics-style easy access to data, such as how much CPU your Grafana is using or how long alerting is taking.
+ 10. **Authentication**: Grafana supports different authentication styles, such as LDAP and OAuth, and allows you to map users to organizations. In Grafana Enterprise, you can also map users to teams: If your company has its own authentication system, Grafana allows you to map the teams in your internal systems to teams in Grafana. That way, you can automatically give people access to the dashboards designated for their teams.
+
+
+
+Want to take a deeper dive? Join the [Grafana community][18], check out the [how-to section][19], and share what you think.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/grafana-features
+
+作者:[Daniel Lee][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/daniellee
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
+[2]: https://github.com/grafana/grafana
+[3]: https://grafana.com/blog/2019/09/03/the-mostly-complete-history-of-grafana-ux/
+[4]: https://grafana.com/author/torkel
+[5]: https://youtu.be/ANv5UfZsvZQ?t=29
+[6]: https://grafana.com/
+[7]: https://grafana.wikimedia.org/d/000000143/navigation-timing?orgId=1&refresh=5m
+[8]: https://community.openhab.org/t/howto-create-annotations-in-grafana-via-rules/48929
+[9]: https://docs.microsoft.com/en-us/azure/devops/service-hooks/services/grafana?view=azure-devops
+[10]: https://medium.com/contentsquare-engineering-blog/from-events-to-grafana-annotation-f35aafe8bd3d
+[11]: https://youtu.be/kV3Ua6guynI
+[12]: https://play.grafana.org/d/vmie2cmWz/bar-gauge?orgId=1&refresh=10s&kiosk
+[13]: https://github.com/grafana/grafana-kiosk
+[14]: https://grafana.com/grafana/plugins/grafana-worldmap-panel
+[15]: https://grafana.com/grafana/plugins/alexanderzobnin-zabbix-app
+[16]: https://grafana.com/grafana/plugins/natel-influx-admin-panel
+[17]: https://www.youtube.com/watch?v=-xlchgoqkqY
+[18]: https://community.grafana.com/
+[19]: https://community.grafana.com/c/howto/6
diff --git a/sources/tech/20200218 Getting started with OpenTaxSolver.md b/sources/tech/20200218 Getting started with OpenTaxSolver.md
new file mode 100644
index 0000000000..b0b1ba1677
--- /dev/null
+++ b/sources/tech/20200218 Getting started with OpenTaxSolver.md
@@ -0,0 +1,124 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting started with OpenTaxSolver)
+[#]: via: (https://opensource.com/article/20/2/do-your-taxes-open-source-way)
+[#]: author: (Jessica Cherry https://opensource.com/users/jrepka)
+
+Getting started with OpenTaxSolver
+======
+If you're a United States citizen, learn how to do your own state tax
+returns with OpenTaxSolver.
+![A document flying away][1]
+
+OpenTaxSolver is an open source application for US taxpayers to calculate their state and federal income tax returns. Before I get into the software, I want to share some of the information I learned when researching this article. I spent about five hours a day for a week looking into open source options for doing your taxes, and I learned about a lot more than just tax software.
+
+The Internal Revenue Service's (IRS's) [Use of federal tax information (FTI) in open source software][2] webpage offers a large amount of information, and it's especially relevant to anyone who may want to start their own open source tax software project. To hit the finer points:
+
+ * Federal tax information (FTI) can be used in any open source software
+ * Software creators mush follow all security laws and compliance requirements
+ * Any such software must be supported either by a vendor or a community
+ * The software must be approved by the federal government
+
+
+
+One other reason researching this topic was rather difficult (but ultimately rewarding) is that, by federal law, the major tax software companies are required to provide their services for free to any person earning under $69,000 per year. About 70% of Americans fit into this category, and if you are one of them, you can check the IRS's [Free File][3] webpage for links to free filing software from well-known companies. (The IRS reminds you that "you are responsible for determining your eligibility for one of the Free File Online offers.")
+
+Please share this information broadly—knowledge is power, and not everyone can (or wants to) use open source software to do their taxes for reasons including:
+
+ * Lack of computer or software access
+ * Low computer competence
+ * Age or disability
+ * Discomfort with doing taxes
+
+
+
+If you don't fall into any of these categories and want to do your taxes the open source way, continue reading to learn about OpenTaxSolver.
+
+### About OpenTaxSolver
+
+[OpenTaxSolver][4] is meant to be used with the IRS's [tax booklet][5], which is published yearly. This booklet provides detailed information for doing your taxes, such as rules around tax credits and write-offs.
+
+OpenTaxSolver cuts down on tax calculations when you fill out your tax forms and simplifies the hardest part of doing your taxes: the math. You still have to fill in your data and turn the paperwork in, but using the software means you can do it in about half of the time. Since OpenTaxSolver is running in beta, you have to double-check all of your number entries and information against the official IRS tax booklet after you use the software.
+
+### Download and install OpenTaxSolver
+
+First, [download the software][6]. There are versions for Linux, Windows, and macOS. If you're using one of the latter two, refer to the download page for installation instructions. I'm using my go-to operating system, Ubuntu Linux, which I installed by:
+
+ 1. Downloading the TGZ file from the website
+ 2. Extracting it to my desktop (but you can choose any location on your computer)
+ 3. Clicking on **Run_taxsolve_GUI**
+
+
+
+![OpenTaxSolver installation][7]
+
+### Enter your tax data
+
+I'll walk through this example using random numbers (for obvious reasons). This walkthrough will explain how do federal taxes with OpenTaxSolver, but if you have to pay state taxes, do that before you begin your federal return.
+
+To do the common Federal 1040 tax return, select **US 1040**, click **Start New Return**, and start answering some basic questions about your tax situation. For this example, I selected the following itemized deductions: mortgage interest, donations, and some random itemizable write-offs. If you don't know what these are or what may apply to you, head over to the IRS website or google "itemizable write-offs."
+
+Next, begin entering the data from your tax documents.
+
+![OpenTaxSolver][8]
+
+![OpenTaxSolver][9]
+
+After you finish entering all your data and filling out the entire form, save it by clicking the **Save** button, and then click **Compute Tax** on the bottom of the screen.
+
+![OpenTaxSolver][10]
+
+### Check your return and file your taxes
+
+If you made any mistakes (such as mistyping something or putting an incorrect value in any field), it will show an error on the bottom of the preview after the computation finishes.
+
+![OpenTaxSolver preview][11]
+
+The preview also reports your marginal tax rate and what percentage of your income you are paying in taxes.
+
+![OpenTaxSolver preview][12]
+
+After you review the information in the preview, make any corrections, and finish your return, click **Fill-out PDF Forms**, and it will provide printable tax forms with all of your information filled in.
+
+![Tax return][13]
+
+If you entered your name, address, and social security number when entering your data, all of that information will also appear in the right places on the form. Double-check everything, print it, and mail your tax return to the IRS.
+
+### Final notes
+
+OpenTaxSolver gives you the opportunity to file your own federal and state taxes. As always, with any federal related tax information (or federal anything, for that matter), always double-check and use due diligence. I found this software very useful for expanding my knowledge about my taxes.
+
+The OpenTaxSolver website includes a request for contributors, so if you want to start contributing to an open source project that helps everyone, this is one I'd definitely suggest.
+
+And if you're someone who likes to wait until the last minute to pay your taxes, this [clock][14] tells you how much time you have until your taxes are due.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/do-your-taxes-open-source-way
+
+作者:[Jessica Cherry][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jrepka
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_odf_1109ay.png?itok=4CqrPAjt (A document flying away)
+[2]: https://www.irs.gov/privacy-disclosure/use-of-federal-tax-information-fti-in-open-source-software
+[3]: https://apps.irs.gov/app/freeFile/
+[4]: http://opentaxsolver.sourceforge.net/index.html
+[5]: https://www.irs.gov/pub/irs-pdf/i1040gi.pdf
+[6]: http://opentaxsolver.sourceforge.net/download2019.html?button=+Download+OTS+
+[7]: https://opensource.com/sites/default/files/uploads/tax2.png (OpenTaxSolver installation)
+[8]: https://opensource.com/sites/default/files/uploads/tax1.png (OpenTaxSolver)
+[9]: https://opensource.com/sites/default/files/uploads/tax7.png (OpenTaxSolver)
+[10]: https://opensource.com/sites/default/files/uploads/tax6.png (OpenTaxSolver)
+[11]: https://opensource.com/sites/default/files/uploads/tax3.png (OpenTaxSolver preview)
+[12]: https://opensource.com/sites/default/files/uploads/tax4.png (OpenTaxSolver preview)
+[13]: https://opensource.com/sites/default/files/uploads/tax5.png (Tax return)
+[14]: https://countdown.onlineclock.net/countdowns/taxes/
diff --git a/sources/tech/20200218 How to embed Twine stories in WordPress.md b/sources/tech/20200218 How to embed Twine stories in WordPress.md
new file mode 100644
index 0000000000..5f2419aa5e
--- /dev/null
+++ b/sources/tech/20200218 How to embed Twine stories in WordPress.md
@@ -0,0 +1,229 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to embed Twine stories in WordPress)
+[#]: via: (https://opensource.com/article/20/2/embed-twine-wordpress)
+[#]: author: (Roman Lukš https://opensource.com/users/romanluks)
+
+How to embed Twine stories in WordPress
+======
+Share your Twine 2 interactive stories on your WordPress site with the
+Embed Twine plugin.
+![Person drinking a hat drink at the computer][1]
+
+From the very beginning, I wanted the "About me" page on my WordPress website [romanluks.eu][2] to be interactive.
+
+At first, I experimented with Dart, a programming language developed by Google that transcompiles into JavaScript. I killed the project when I realized I was making a game instead of an "About me" page.
+
+A bit later, I discovered [Twine][3], an open source tool for creating interactive stories. It reminded me of the gamebooks I loved as a kid. It's so easy to create interconnected pieces of text in Twine, and it's ideal for the interview-like format I was aiming for. Because Twine publishes directly to HTML, you can do a lot of interesting things with it—including creating [interactive fiction][4] and [adventure games][5] or publishing stories on a blog or website.
+
+### Early struggles
+
+I created my "About me" page in Twine and tried to paste it into my WordPress page.
+
+"No, can do," said WordPress and Twine.
+
+You see, a Twine story exported from Twine is just a webpage (i.e., a file in HTML format). However, it not only includes HTML but JavaScript code, as well. And somehow it doesn't work when you simply try to copy-paste the contents. I tried copy-pasting just the body of the Twine story page without success.
+
+I thought, "I guess I need to add that JavaScript code separately," and I tried custom fields.
+
+Nope.
+
+I took a break from my investigation. I just uploaded my "About me" Twine story via FTP and linked to it from my website's menu. People could visit it and interact with the story, however, there was no menu, and it didn't feel like a part of my website. I had made a trap for myself. It made me realize I really _really_ wanted my "About me" included directly on my website.
+
+### DIY embed
+
+I took a stab at the problem and came up with [this solution][6].
+
+It worked. It wasn't perfect, but it worked.
+
+But it wasn't _perfect_. Is there a better way? There is bound to be a better way…
+
+It cost me a couple of pulled hairs, but I managed to get a [responsive iframe and autoscroll][7].
+
+It was way better. I was proud of myself and shared it on [Reddit][8].
+
+### The road to Embed Twine
+
+Suddenly, an idea! What if, instead of following my tutorial, people could use a WordPress plugin?
+
+They would only have to give the plugin a Twine story, and it would take care of the rest. Hassle-free. No need to copy-paste any JavaScript code.
+
+Wouldn't that be glorious?!?
+
+I had no idea how WordPress plugins work. I only knew they are written in PHP. A while back, I had part-time work as a PHP developer, and I remembered the basics.
+
+### Containers and WordPress
+
+I mentioned my idea to a friend, and he suggested I could use containers as my WordPress development environment.
+
+In the past, I'd always used [XAMPP][9], but I wanted to try containers for a while.
+
+No problem, I thought! I'll learn containers while I learn how to make a WordPress plugin and revive my PHP skills. That should be sufficiently stimulating.
+
+And it was.
+
+I can't recall how many times I stopped, removed, and rebuilt my containers. I had to use the command line. And the file permissions are painful.
+
+Oh boy! It was like playing a game that you enjoy playing even though it makes you fairly angry. It was challenging but rewarding.
+
+I found out that it's very easy to create a simple WordPress plugin:
+
+ * Write the source code
+ * Save it in the WP plugin directory
+ * Test it
+ * Repeat
+
+
+
+Containers make it easy to use a specific environment and are easy to clean up when you screw up and need to start over.
+
+Using Git saved me from accidentally wiping out my entire codebase. I used [Sourcetree][10] as my Git user interface. Initially, I wrote my code in [Notepad++][11], but when I divided my code into multiple files, I switched to [Atom][12]. It's such a cool editor for geeks. Using it feels like the code writes itself.
+
+### Intermission
+
+So what do we know so far?
+
+ * I wanted an interactive "About me" page
+ * I created an "About me" story in Twine
+ * Twine exports webpages (as HTML files with JavaScript included)
+ * WP plugins are easy to make
+ * Containers are awesome
+
+
+
+### Embed Twine is born
+
+I wanted an easy way to embed Twine stories into WordPress. So, I used the power of software development, fooled around with containers, wrote a bit of PHP code, and published the result as a WordPress plugin called [Embed Twine][13].
+
+### Install the plugin
+
+ 1. Upload the plugin [files][14] to the **/wp-content/plugins/plugin-name** directory, or install the plugin through the WordPress Plugins screen.
+ 2. Activate the plugin through the Plugins screen in WordPress.
+
+
+
+### Use the plugin
+
+After you've installed the Embed Twine plugin and created a Twine 2 story, embed it in your WordPress site:
+
+ 1. Export your Twine 2 story into an HTML file.
+ 2. Upload it via the plugin's interface.
+ 3. Insert the shortcode into the page or post.
+ 4. Enjoy your embedded story.
+
+
+
+The plugin also provides autoscroll functionality to make it easy for users to navigate through your stories.
+
+### Configure the plugin
+
+The plugin is configurable via shortcode parameters. To use the shortcode, simply put **[embed_twine]** into your post.
+
+You can use additional parameters in the format **[embed_twine story="Story" aheight=112 autoscroll=true ascroll=100]** as follows:
+
+ * **story:** Specify the story name (the filename without an extension).
+ * If the story parameter is omitted, it defaults to "Story." This means there is no need to use this parameter if your Twine filename is Story.html.
+ * If you upload a Twine story called MyFooBar.html, use the shortcode: **[embed_twine story="MyFooBar"]**.
+ * **aheight:** Use this parameter to adjust the iframe's height. You might need to tweak **aheight** to get rid of an iframe scrollbar. The default value is 112; this value is added to the iframe height and used to set the iframe's **style.height**.
+ * **autoscroll:** Autoscroll is enabled by default. You can turn it off with shortcode parameter **[embed_twine autoscroll=false]**.
+ * **ascroll:** Use this to adjust the default position for autoscroll. The default value is 100; this value is subtracted from the iframe's top position and fed into JavaScript method **window.scrollTo()**.
+
+
+
+### Known bugs
+
+Currently, Twine passages that include images might report their height incorrectly, and the scrollbar might show up for these passages. Tweak the shortcode parameter **aheight** to get rid of them.
+
+### The script
+
+
+```
+1 <?php
+2
+3 /**
+4 * Plugin Name: Embed Twine
+5 * Description: Insert Twine stories into WordPress
+6 * Version: 0.0.6
+7 * Author: Roman Luks
+8 * Author URI:
+9 * License: GPLv2 or later
+10 */
+11
+12 require_once('include/embed-twine-load-file.php');
+13 require_once('include/embed-twine-parent-page.php');
+14 require_once('include/embed-twine-process-story.php');
+15
+16 // Add plugin to WP menu
+17 function embed_twine_customplugin_menu() {
+18
+19 add_menu_page("Embed Twine", "Embed Twine","manage_options", __FILE__, "embed_twine_uploadfile");
+20 }
+21
+22 add_action("admin_menu", "embed_twine_customplugin_menu");
+23
+24 function embed_twine_uploadfile(){
+25 include "include/embed-twine-upload-file.php";
+26 }
+27
+28 // Add shortcode
+29 function embed_twine_shortcodes_init()
+30 {
+31 function embed_twine_shortcode($atts = [], $content = null)
+32 {
+33 // Attributes
+34 $atts = shortcode_atts(
+35 [array][15](
+36 'story' => 'Story',
+37 'aheight' => 112, //adjust for style.height (30) and margins of tw-story (2x41)
+38 'autoscroll' => true, //autoscroll enabled by default
+39 'ascroll' => 100, //adjust for autoscroll
+40 ),
+41 $atts,
+42 'embed_twine'
+43 );
+44
+45 $content = embed_twine_buildParentPage($atts['story'], $atts['aheight'], $atts['autoscroll'], $atts['ascroll']);
+46
+47 return $content;
+48 }
+49 add_shortcode('embed_twine', 'embed_twine_shortcode');
+50 }
+51 add_action('init', 'embed_twine_shortcodes_init');
+```
+
+* * *
+
+_This article is adapted from [Roman Luks' blog][16] and [Embed Twine][13] page on WordPress plugins._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/embed-twine-wordpress
+
+作者:[Roman Lukš][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/romanluks
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
+[2]: https://romanluks.eu/
+[3]: https://twinery.org/
+[4]: https://opensource.com/article/18/7/twine-vs-renpy-interactive-fiction
+[5]: https://opensource.com/article/18/2/twine-gaming
+[6]: https://romanluks.eu/blog/how-to-embed-twine-on-your-wordpress-website/
+[7]: https://romanluks.eu/blog/how-to-embed-twine-on-your-wordpress-website-with-responsive-iframe-and-autoscroll/
+[8]: https://www.reddit.com/r/twinegames/comments/dtln4z/how_to_embed_twine_on_your_wordpress_website_with/
+[9]: https://en.wikipedia.org/wiki/XAMPP
+[10]: https://www.sourcetreeapp.com/
+[11]: https://notepad-plus-plus.org/
+[12]: https://atom.io/
+[13]: https://wordpress.org/plugins/embed-twine/
+[14]: https://plugins.trac.wordpress.org/browser/embed-twine/
+[15]: http://www.php.net/array
+[16]: https://romanluks.eu/blog/embed-twine-wordpress-plugin/
diff --git a/sources/tech/20200219 How to conveniently unsubscribe from a mailing list.md b/sources/tech/20200219 How to conveniently unsubscribe from a mailing list.md
new file mode 100644
index 0000000000..ab0a962efa
--- /dev/null
+++ b/sources/tech/20200219 How to conveniently unsubscribe from a mailing list.md
@@ -0,0 +1,93 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to conveniently unsubscribe from a mailing list)
+[#]: via: (https://opensource.com/article/20/2/how-unsubscribe-mailing-list)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+How to conveniently unsubscribe from a mailing list
+======
+Cut down on your email clutter by removing yourself from email lists you
+no longer need.
+![Photo by Anthony Intraversato on Unsplash][1]
+
+If you're on an email discussion group long enough, at some point, you'll see an email from a list member asking to be unsubscribed. Typically, at least 10 other people on the list will respond with instructions on how to unsubscribe, and those 10 responses will be answered by 10 more people confirming or commenting on the instructions. That's a _lot_ of traffic to a mailing list just so one person can unsubscribe.
+
+But unsubscribing from a list can be confusing, especially if you've gotten on the list by accident. It's frustrating to discover that you've been added to a list, and it's annoying that you have to take time out of your day to extricate yourself. This article is here to help make unsubscribing fast, easy, and graceful.
+
+Never send an unsubscribe email to the same email address you use to post messages
+
+### Unsubscribe by email
+
+Mailing lists are controlled by mailing list software (like [GNU Mailman][2]) on a server. You probably aren't aware of the software controlling a mailing list you're on, because they're usually designed to stay out of the way and just deliver mail. But as a member of a mailing list, you actually have some user control over the software.
+
+Some mailing lists allow you to unsubscribe using an automated email address. It can be a little confusing because the email address you use to unsubscribe is NOT the email address you use to send messages to the list. Essentially, you're sending a special command to the email server, telling it to take you off the list. This is a convenient method of unsubscribing because it means you don't have to compose a message or wait for anyone to take action. You speak directly to the computer sending the email, and it does exactly as it's told.
+
+To unsubscribe from a list, take the email address of the list, add **-leave** just before the **@** symbol, and send a message. You can email a blank message; the computer doesn't care. The fact that you're emailing the list with the **-leave** command in front of the **@** symbol is all it needs.
+
+Here's an example.
+
+Say you've joined the mailing list Funny Squirrels. You send a few messages to [funnysquirrels@example.com][3] but soon find that squirrels are not as amusing as you'd hoped. To unsubscribe, you can send an email to:
+
+
+```
+`funnysquirrels-leave@example.com`
+```
+
+You may get a final confirmation email back, and then you'll hear from the mailing list no more.
+
+#### Custom email commands
+
+Sometimes the administrator of a mail server changes the command for unsubscribing. Ideally, they'll include the unsubscribe email address in the footer of emails sent to the mailing list, so check for that before sending your parting email.
+
+The thing to keep in mind is that an unsubscribe email _never_ goes to the actual list, meaning you should never send an unsubscribe email to the same email address you use to post messages. There's a special, separate email address reserved for the unsubscribe command.
+
+### Unsubscribing by webform
+
+Some mailing lists have a webform for unsubscribing, and ideally, it can be found in the footer of each mailing list message. You can navigate to the webform and opt out of your subscription.
+
+This method is common for commercial mailing lists, and it's sometimes a way for them to capture any feedback you have about the list, why you're leaving, and so on. Like the automated email method, the intent is for you to maintain full control of your own subscription. You never have to wait for a human to take you off of a list; instead, you can issue commands directly to a computer.
+
+![Example unsubscribe web form][4]
+
+A webform may send you a final confirmation email, and after that, you should hear nothing from that mailing list ever again.
+
+### Unsubscribing like a pro
+
+Leaving a mailing list is a guilt-free and nonaggressive act. When you want to leave a mailing list, you should be able to find an unsubscribe email address or webform to make it automated and final.
+
+If, in spite of using the methods above, you can't leave a mailing list, don't email the list. Very few people on the mailing list have control over who is subscribed, and sometimes the people who have access to the list of subscribers are not monitoring the list—they're only maintaining the server. Instead, find out what server hosts the mailing list, and contact the hosting provider to alert them of the abuse.
+
+You can find the host of a mailing list by searching for the server name (the part of the email address to the _right_ of the **@** symbol) on a **whois** service. If you're running Linux, you can do this from a terminal:
+
+
+```
+`$ whois `
+```
+
+Otherwise, use the [Whois.net][5] website.
+
+Whois provides the internet hosting provider of any email server plus the abuse and support contact information.
+
+Remember: you are always free to leave a mailing list for any reason, without getting permission from anyone else. And now that you know how, you'll be able to unsubscribe like a pro!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/how-unsubscribe-mailing-list
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/anthony-intraversato-pt_wqgzaiu8-unsplash.jpg?itok=5bbMlgt8 (Photo by Anthony Intraversato on Unsplash)
+[2]: https://www.list.org/
+[3]: mailto:funnysquirrels@example.com
+[4]: https://opensource.com/sites/default/files/uploads/mail-webform.jpg (Example unsubscribe web form)
+[5]: http://whois.net
diff --git a/sources/tech/20200221 Don-t like loops- Try Java Streams.md b/sources/tech/20200221 Don-t like loops- Try Java Streams.md
new file mode 100644
index 0000000000..e327d045a3
--- /dev/null
+++ b/sources/tech/20200221 Don-t like loops- Try Java Streams.md
@@ -0,0 +1,427 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Don't like loops? Try Java Streams)
+[#]: via: (https://opensource.com/article/20/2/java-streams)
+[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
+
+Don't like loops? Try Java Streams
+======
+It's 2020 and time to learn about Java Streams.
+![Person drinking a hat drink at the computer][1]
+
+In this article, I will explain how to not write loops anymore.
+
+What? Whaddaya mean, no more loops?
+
+Yep, that's my 2020 resolution—no more loops in Java. Understand that it's not that loops have failed me, nor have they led me astray (well, at least, I can argue that point). Really, it is that I, a Java programmer of modest abilities since 1997 or so, must finally learn about all this new [Streams][2] stuff, saying "what" I want to do and not "how" I want to do it, maybe being able to parallelize some of my computations, and all that other good stuff.
+
+I'm guessing that there are other Java programmers out there who also have been programming in Java for a decent amount of time and are in the same boat. Therefore, I'm offering my experiences as a guide to "how to not write loops in Java anymore."
+
+### Find a problem worth solving
+
+If you're like me, then the first show-stopper you run into is "right, cool stuff, but what am I solving for, and how do I apply this?" I realized that I can spot the perfect opportunity camouflaged as _Something I've Done Before_.
+
+In my case, it's sampling land cover within a specific area and coming up with an estimate and a confidence interval around that estimate for the land cover across the whole area. The specific problem involves deciding whether an area is "forested" or not, given a specific legal definition: if at least 10% of the soil is covered over by tree crowns, then the area is considered to be forested; otherwise, it's something else.
+
+![Image of land cover in an area][3]
+
+It's a pretty esoteric example of a recurring problem; I'll grant you. But there it is. For the ecologists and foresters out there who are accustomed to cool temperate or tropical forests, 10% might sound kind of low, but in the case of dry areas with low-growing shrubs and trees, that's a reasonable number.
+
+So the basic idea is: use images to stratify the area (i.e., areas completely devoid of trees, areas of predominantly small trees spaced quite far apart, areas of predominantly small trees spaced closer together, areas of somewhat larger trees), locate some samples in those strata, send the crew out to measure the samples, analyze the results, and calculate the proportion of soil covered by tree crowns across the area. Simple, right?
+
+![Survey team assessing land cover][4]
+
+### What the field data looks like
+
+In the current project, the samples are rectangular areas 20 meters wide by 25 meters long, so 500 square meters each. On each patch, the field crew measured each tree: its species, its height, the maximum and minimum width of its crown, and the diameter of its trunk at trunk height (nominally 30cm above the ground). This information was collected, entered into a spreadsheet, and exported to a bar separated value (BSV) file for me to analyze. It looks like this:
+
+Stratum# | Sample# | Tree# | Species | Trunk diameter (cm) | Crown diameter 1 (m) | Crown diameter 2 (m) | Height (m)
+---|---|---|---|---|---|---|---
+1 | 1 | 1 | Ac | 6 | 3.6 | 4.6 | 2.4
+1 | 1 | 2 | Ac | 6 | 2.2 | 2.3 | 2.5
+1 | 1 | 3 | Ac | 16 | 2.5 | 1.7 | 2.4
+1 | 1 | 4 | Ac | 6 | 1.5 | 2.1 | 1.8
+1 | 1 | 5 | Ac | 5 | 0.9 | 1.7 | 1.7
+1 | 1 | 6 | Ac | 6 | 1.7 | 1.3 | 1.6
+1 | 1 | 7 | Ac | 5 | 1.82 | 1.32 | 1.8
+1 | 1 | 1 | Ac | 1 | 0.3 | 0.25 | 0.9
+1 | 1 | 2 | Ac | 2 | 1.2 | 1.2 | 1.7
+
+The first column is the stratum number (where 1 is "predominantly small trees spaced quite far apart," 2 is "predominantly small trees spaced closer together," and 3 is "somewhat larger trees"; we didn't sample the areas "completely devoid of trees"). The second column is the sample number (there are 73 samples altogether, located in the three strata in proportion to the area of each stratum). The third column is the tree number within the sample. The fourth is the two-letter species code, the fifth the trunk diameter (in this case, 10cm above ground or exposed roots), the sixth the smallest distance across the crown, the seventh the largest distance, and the eighth the height of the tree.
+
+For the purposes of this exercise, I'm only concerned with the total amount of ground covered by the tree crowns—not the species, nor the height, nor the diameter of the trunk.
+
+In addition to the measurement information above, I also have the areas of the three strata, also in a BSV:
+
+stratum | hectares
+---|---
+1 | 114.89
+2 | 207.72
+3 | 29.77
+
+### What I want to do (not how I want to do it)
+
+In keeping with one of the main design goals of Java Streams, here is "what" I want to do:
+
+ 1. Read the stratum area BSV and save the data as a lookup table.
+ 2. Read the measurements from the measurement BSV file.
+ 3. Accumulate each measurement (tree) to calculate the total area of the sample covered by tree crowns.
+ 4. Accumulate the sample tree crown area values and count the number of samples to estimate the mean tree crown area coverage and standard error of the mean for each stratum.
+ 5. Summarize the stratum figures.
+ 6. Weigh the stratum means and standard errors by the stratum areas (looked up from the table created in step 1) and accumulate them to estimate the mean tree crown area coverage and standard error of the mean for the total area.
+ 7. Summarize the weighted figures.
+
+
+
+Generally speaking, the way to define "what" with Java Streams is by creating a stream processing pipeline of function calls that pass over the data. So, yes, there is actually a bit of "how" that ends up creeping in… in fact, quite a bit of "how." But, it needs a very different knowledge base than the good, old fashioned loop.
+
+I'll go through each of these steps in detail.
+
+#### Build the stratum area table
+
+The first job is to convert the stratum areas BSV file to a lookup table:
+
+
+```
+[String][5] fileName = "stratum_areas.bsv";
+Stream<String> inputLineStream = Files.lines(Paths.get(fileName)); // (1)
+
+final Map<[Integer][6],Double> stratumAreas = // (2)
+ inputLineStream // (3)
+ .skip(1) // (4)
+ .map(l -> l.split("\\\|")) // (5)
+ .collect( // (6)
+ Collectors.toMap( // (7)
+ a -> [Integer][6].parseInt(a[0]), // (8)
+ a -> [Double][7].parseDouble(a[1]) // (9)
+ )
+ );
+inputLineStream.close(); // (10)
+
+[System][8].out.println("stratumAreas = " + stratumAreas); // (11)
+```
+
+I'll take this a line or two at a time, where the numbers in comments following the lines above—e.g., _// (3)_— correspond to the numbers below:
+
+ 1. java.nio.Files.lines() gives a stream of strings corresponding to lines in the file.
+ 2. The goal is to create the lookup table, **stratumAreas**, which is a **Map<Integer,Double>**. Therefore, I can get the **double** value area for stratum 2 as **stratumAreas.get(2)**.
+ 3. This is the beginning of the stream "pipeline."
+ 4. Skip the first line in the pipeline since it's the header line containing the column names.
+ 5. Use **map()** to split the **String** input line into an array of **String** fields, with the first field being the stratum # and the second being the stratum area.
+ 6. Use **collect()** to [materialize the results][9].
+ 7. The materialized result will be produced as a sequence of **Map** entries.
+ 8. The key of each map entry is the first element of the array in the pipeline—the **int** stratum number. By the way, this is a _Java lambda_ expression—[an anonymous function][10] that takes an argument and returns that argument converted to an **int**.
+ 9. The value of each map entry is the second element of the array in the pipeline—the **double** stratum area.
+ 10. Don't forget to close the stream (file).
+ 11. Print out the result, which looks like: [code]`stratumAreas = {1=114.89, 2=207.72, 3=29.77}`
+```
+### Build the measurements table and accumulate the measurements into the sample totals
+
+Now that I have the stratum areas, I can start processing the main body of data—the measurements. I combine the two tasks of building the measurements table and accumulating the measurements into the sample totals since I don't have any interest in the measurement data per se.
+```
+
+
+fileName = "sample_data_for_testing.bsv";
+inputLineStream = Files.lines(Paths.get(fileName));
+
+ final Map<[Integer][6],Map<[Integer][6],Double>> sampleValues =
+ inputLineStream
+ .skip(1)
+ .map(l -> l.split("\\\|"))
+ .collect( // (1)
+ Collectors.groupingBy(a -> [Integer][6].parseInt(a[0]), // (2)
+ Collectors.groupingBy(b -> [Integer][6].parseInt(b[1]), // (3)
+ Collectors.summingDouble( // (4)
+ c -> { // (5)
+ double rm = ([Double][7].parseDouble(c[5]) +
+ [Double][7].parseDouble(c[6]))/4d; // (6)
+ return rm*rm * [Math][11].PI / 500d; // (7)
+ })
+ )
+ )
+ );
+inputLineStream.close();
+
+[System][8].out.println("sampleValues = " + sampleValues); // (8)
+
+```
+Again, a line or two or so at a time:
+
+ 1. The first seven lines are the same in this task and the previous, except the name of this lookup table is **sampleValues**; and it is a **Map** of **Map**s.
+ 2. The measurement data is grouped into samples (by sample #), which are, in turn, grouped into strata (by stratum #), so I use **Collectors.groupingBy()** at the topmost level [to separate data][12] into strata, with **a[0]** here being the stratum number.
+ 3. I use **Collectors.groupingBy()** once more to separate data into samples, with **b[1]** here being the sample number.
+ 4. I use the handy **Collectors.summingDouble()** [to accumulate the data][13] for each measurement within the sample within the stratum.
+ 5. Again, a Java lambda or anonymous function whose argument **c** is the array of fields, where this lambda has several lines of code that are surrounded by **{** and **}** with a **return** statement just before the **}**.
+ 6. Calculate the mean crown radius of the measurement.
+ 7. Calculate the crown area of the measurement as a proportion of the total sample area and return that value as the result of the lambda.
+ 8. Again, similar to the previous task. The result looks like (with some numbers elided): [code]`sampleValues = {1={1=0.09083231861452731, 66=0.06088002082602869, ... 28=0.0837823490804228}, 2={65=0.14738326403381743, 2=0.16961183847374103, ... 63=0.25083064794883453}, 3={64=0.3306323635177101, 32=0.25911911184680053, ... 30=0.2642668470291564}}`
+```
+
+
+
+This output shows the **Map** of **Map**s structure clearly—there are three entries in the top level corresponding to the strata 1, 2, and 3, and each stratum has subentries corresponding to the proportional area of the sample covered by tree crowns.
+
+#### Accumulate the sample totals into the stratum means and standard errors
+
+At this point, the task becomes more complex; I need to count the number of samples, sum up the sample values in preparation for calculating the sample mean, and sum up the squares of the sample values in preparation for calculating the standard error of the mean. I may as well incorporate the stratum area into this grouping of data as well, as I'll need it shortly to weigh the stratum results together.
+
+So the first thing to do is create a class, **StratumAccumulator**, to handle the accumulation and provide the calculation of the interesting results. This class implements **java.util.function.DoubleConsumer**, which can be passed to **collect()** to handle accumulation:
+
+
+```
+class StratumAccumulator implements DoubleConsumer {
+ private double ha;
+ private int n;
+ private double sum;
+ private double ssq;
+ public StratumAccumulator(double ha) { // (1)
+ this.ha = ha;
+ this.n = 0;
+ this.sum = 0d;
+ this.ssq = 0d;
+ }
+ public void accept(double d) { // (2)
+ this.sum += d;
+ this.ssq += d*d;
+ this.n++;
+ }
+ public void combine(StratumAccumulator other) { // (3)
+ this.sum += other.sum;
+ this.ssq += other.ssq;
+ this.n += other.n;
+ }
+ public double getHa() { // (4)
+ return this.ha;
+ }
+ public int getN() { // (5)
+ return this.n;
+ }
+ public double getMean() { // (6)
+ return this.n > 0 ? this.sum / this.n : 0d;
+ }
+ public double getStandardError() { // (7)
+ double mean = this.getMean();
+ double variance = this.n > 1 ? (this.ssq - mean*mean*n)/(this.n - 1) : 0d;
+ return this.n > 0 ? [Math][11].sqrt(variance/this.n) : 0d;
+ }
+}
+```
+
+Line-by-line:
+
+ 1. The constructor **StratumAccumulator(double ha)** takes an argument, the area of the stratum in hectares, which allows me to merge the stratum area lookup table into instances of this class.
+ 2. The **accept(double d)** method is used to accumulate the stream of double values, and I use it to:
+a. Count the number of values.
+b. Sum the values in preparation for computing the sample mean.
+c. Sum the squares of the values in preparation for computing the standard error of the mean.
+ 3. The **combine()** method is used to merge substreams of **StratumAccumulator**s (in case I want to process in parallel).
+ 4. The getter for the area of the stratum
+ 5. The getter for the number of samples in the stratum
+ 6. The getter for the mean sample value in the stratum
+ 7. The getter for the standard error of the mean in the stratum
+
+
+
+Once I have this accumulator, I can use it to accumulate the sample values pertaining to each stratum:
+
+
+```
+final Map<[Integer][6],StratumAccumulator> stratumValues = // (1)
+ sampleValues.entrySet().stream() // (2)
+ .collect( // (3)
+ Collectors.toMap( // (4)
+ e -> e.getKey(), // (5)
+ e -> e.getValue().entrySet().stream() // (6)
+ .map([Map.Entry][14]::getValue) // (7)
+ .collect( // (8)
+ () -> new StratumAccumulator(stratumAreas.get(e.getKey())), // (9)
+ StratumAccumulator::accept, // (10)
+ StratumAccumulator::combine) // (11)
+ )
+ );
+```
+
+Line-by-line:
+
+ 1. This time, I'm using the pipeline to build **stratumValues**, which is a **Map<Integer,StratumAccumulator>**, so **stratumValues.get(3)** will return the **StratumAccumulator** instance for stratum 3.
+ 2. Here, I'm using the **entrySet().stream()** method provided by **Map** to get a stream of (key, value) pairs; recall these are **Map**s of sample values by stratum.
+ 3. Again, I'm using **collect()** to gather the pipeline results by stratum…
+ 4. using **Collectors.toMap()** to generate a stream of **Map** entries…
+ 5. whose keys are the key of the incoming stream (that is, the stratum #)…
+ 6. and whose values are the Map of sample values, and I again use **entrySet().stream()** to convert to a stream of Map entries, one for each sample.
+ 7. Using **map()** to get the value of the sample **Map** entry; I'm not interested in the key by this point.
+ 8. Yet again, using **collect()** to accumulate the sample results into the **StratumAccumulator** instances.
+ 9. Telling **collect()** how to create a new **StratumAccumulator**—I need to pass the stratum area into the constructor here, so I can't just use **StratumAccumulator::new**.
+ 10. Telling **collect()** to use the **accept()** method of **StratumAccumulator** to accumulate the stream of sample values.
+ 11. Telling **collect()** to use the **combine()** method of **StratumAccumulator** to merge **StratumAccumulator** instances.
+
+
+
+#### Summarize the stratum figures
+
+Whew! After all of that, printing out the stratum figures is pretty straightforward:
+
+
+```
+stratumValues.entrySet().stream()
+ .forEach(e -> {
+ StratumAccumulator sa = e.getValue();
+ int n = sa.getN();
+ double se66 = sa.getStandardError();
+ double t = new TDistribution(n - 1).inverseCumulativeProbability(0.975d);
+ [System][8].out.printf("stratum %d n %d mean %g se66 %g t %g se95 %g ha %g\n",
+ e.getKey(), n, sa.getMean(), se66, t, se66 * t, sa.getHa());
+ });
+```
+
+In the above, once again, I use **entrySet().stream()** to transform the **stratumValues** Map to a stream, and then apply the **forEach()** method to the stream. **ForEach()** is pretty much what it sounds like—a loop! But the business of finding the head of the stream, finding the next element, and checking to see if hits the end is all handled by Java Streams. So, I just get to say what I want to do for each record, which is basically to print it out.
+
+My code looks a bit more complicated because I declare some local variables to hold some intermediate results that I use more than once—**n**, the number of samples, and **se66**, the standard error of the mean. I also calculate the inverse T value to [convert my standard error of the mean to a 95% confidence interval][15].
+
+The result looks like this:
+
+
+```
+stratum 1 n 24 mean 0.0903355 se66 0.0107786 t 2.06866 se95 0.0222973 ha 114.890
+stratum 2 n 38 mean 0.154612 se66 0.00880498 t 2.02619 se95 0.0178406 ha 207.720
+stratum 3 n 11 mean 0.223634 se66 0.0261662 t 2.22814 se95 0.0583020 ha 29.7700
+```
+
+#### Accumulate the stratum means and standard errors into the total
+
+Once again, the task becomes more complex, so I create a class, **TotalAccumulator**, to handle the accumulation and provide the calculation of the interesting results. This class implements **java.util.function.Consumer<T>**, which can be passed to **collect()** to handle accumulation:
+
+
+```
+class TotalAccumulator implements Consumer<StratumAccumulator> {
+ private double ha;
+ private int n;
+ private double sumWtdMeans;
+ private double ssqWtdStandardErrors;
+ public TotalAccumulator() {
+ this.ha = 0d;
+ this.n = 0;
+ this.sumWtdMeans = 0d;
+ this.ssqWtdStandardErrors = 0d;
+ }
+ public void accept(StratumAccumulator sa) {
+ double saha = sa.getHa();
+ double sase = sa.getStandardError();
+ this.ha += saha;
+ this.n += sa.getN();
+ this.sumWtdMeans += saha * sa.getMean();
+ this.ssqWtdStandardErrors += saha * saha * sase * sase;
+ }
+ public void combine(TotalAccumulator other) {
+ this.ha += other.ha;
+ this.n += other.n;
+ this.sumWtdMeans += other.sumWtdMeans;
+ this.ssqWtdStandardErrors += other.ssqWtdStandardErrors;
+ }
+ public double getHa() {
+ return this.ha;
+ }
+ public int getN() {
+ return this.n;
+ }
+ public double getMean() {
+ return this.ha > 0 ? this.sumWtdMeans / this.ha : 0d;
+ }
+ public double getStandardError() {
+ return this.ha > 0 ? [Math][11].sqrt(this.ssqWtdStandardErrors) / this.ha : 0;
+ }
+}
+```
+
+I'm not going to go into much detail on this, since it's structurally pretty similar to **StratumAccumulator**. Of main interest:
+
+ 1. The constructor takes no arguments, which simplifies its use.
+ 2. The **accept()** method accumulates instances of **StratumAccumulator**, not **double** values, hence the use of the **Consumer<T>** interface.
+ 3. As for the calculations, they are assembling a weighted average of the **StratumAccumulator** instances, so they make use of the stratum areas, and the formulas might look a bit strange to anyone who's not used to stratified sampling.
+
+
+
+As for actually carrying out the work, it's easy-peasy:
+
+
+```
+final TotalAccumulator totalValues =
+ stratumValues.entrySet().stream()
+ .map([Map.Entry][14]::getValue)
+ .collect(TotalAccumulator::new, TotalAccumulator::accept, TotalAccumulator::combine);
+```
+
+Same old stuff as before:
+
+ 1. Use **entrySet().stream()** to convert the **stratumValue Map** entries to a stream.
+ 2. Use **map()** to replace the **Map** entries with their values—the instances of **StratumAccumulator**.
+ 3. Use **collect()** to apply the **TotalAccumulator** to the instances of **StratumAccumulator**.
+
+
+
+#### Summarize the total figures
+
+Getting the interesting bits out of the **TotalAccumulator** instance is also pretty straightforward:
+
+
+```
+int nT = totalValues.getN();
+double se66T = totalValues.getStandardError();
+double tT = new TDistribution(nT - stratumValues.size()).inverseCumulativeProbability(0.975d);
+[System][8].out.printf("total n %d mean %g se66 %g t %g se95 %g ha %g\n",
+ nT, totalValues.getMean(), se66T, tT, se66T * tT, totalValues.getHa());
+```
+
+Similar to the **StratumAccumulator**, I just call the relevant getters to pick out the number of samples **nT** and the standard error **se66T**. I calculate the T value **tT** (using "n – 3" here since there are three strata), and then I print the result, which looks like this:
+
+
+```
+`total n 73 mean 0.139487 se66 0.00664653 t 1.99444 se95 0.0132561 ha 352.380`
+```
+
+### In conclusion
+
+Wow, that looks like a bit of a marathon. It feels like it, too. As is often the case, there is a great deal of information about how to use Java Streams, all illustrated with toy examples, which kind of help, but not really. I found that getting this to work with a real-world (albeit very simple) example was difficult.
+
+Because I've been working in [Groovy][16] a lot lately, I kept finding myself wanting to accumulate into "maps of maps of maps" rather than creating accumulator classes, but I was never able to pull that off except in the case of totaling up the measurements in the sample. So, I worked with accumulator classes instead of maps of maps, and maps of accumulator classes instead of maps of maps of maps.
+
+I don't feel like any kind of master of Java Streams at this point, but I do feel I have a pretty solid understanding of **collect()**, which is deeply important, along with various methods to reformat data structures into streams and to reformat stream elements themselves. So yeah, more to learn!
+
+Speaking of collect(), in the examples I presented above, we can see moving from a very simple use of this fundamental method - using the Collectors.summingDouble() accumulation method - through defining an accumulator class that extends one of the pre-defined interfaces - in this case DoubleConsumer - to defining a full-blown accumulator of our own, used to accumulate the intermediate stratum class. I was tempted - sort of - to work backward and implement fully custom accumulators for the stratum and sample accumulators, but the point of this exercise was to learn more about Java Streams, not to become an expert in one single part of it all.
+
+What's your experience with Java Streams? Done anything big and complicated yet? Please share it in the comments.
+
+Optimizing your Java code requires an understanding of how the different elements in Java interact...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/java-streams
+
+作者:[Chris Hermansen][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/clhermansen
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
+[2]: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
+[3]: https://opensource.com/sites/default/files/uploads/landcover.png (Image of land cover in an area)
+[4]: https://opensource.com/sites/default/files/uploads/foresters.jpg (Survey team assessing land cover)
+[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
+[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+integer
+[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+double
+[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
+[9]: https://www.baeldung.com/java-8-collectors
+[10]: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
+[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+math
+[12]: https://www.baeldung.com/java-groupingby-collector
+[13]: http://www.java2s.com/Tutorials/Java/java.util.stream/Collectors/Collectors.summingDouble_ToDoubleFunction_super_T_mapper_.htm
+[14]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+map.entry
+[15]: https://en.wikipedia.org/wiki/Standard_error
+[16]: http://groovy-lang.org/
diff --git a/sources/tech/20200221 Live video streaming with open source Video.js.md b/sources/tech/20200221 Live video streaming with open source Video.js.md
new file mode 100644
index 0000000000..178466a443
--- /dev/null
+++ b/sources/tech/20200221 Live video streaming with open source Video.js.md
@@ -0,0 +1,171 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Live video streaming with open source Video.js)
+[#]: via: (https://opensource.com/article/20/2/video-streaming-tools)
+[#]: author: (Aaron J. Prisk https://opensource.com/users/ricepriskytreat)
+
+Live video streaming with open source Video.js
+======
+Video.js is a widely used protocol that will serve your live video
+stream to a wide range of devices.
+![video editing dashboard][1]
+
+Last year, I wrote about [creating a video streaming server with Linux][2]. That project uses the Real-Time Messaging Protocol (RMTP), Nginx web server, Open Broadcast Studio (OBS), and VLC media player.
+
+I used VLC to play our video stream, which may be fine for a small local deployment but isn't very practical on a large scale. First, your viewers have to use VLC, and RTMP streams can provide inconsistent playback. This is where [Video.js][3] comes into play! Video.js is an open source JavaScript framework for creating custom HTML5 video players. Video.js is incredibly powerful, and it's used by a host of very popular websites—largely due to its open nature and how easy it is to get up and running.
+
+### Get started with Video.js
+
+This project is based off of the video streaming project I wrote about last year. Since that project was set to serve RMTP streams, to use Video.js, you'll need to make some adjustments to that Nginx configuration. HTTP Live Streaming ([HLS][4]) is a widely used protocol developed by Apple that will serve your stream better to a multitude of devices. HLS will take your stream, break it into chunks, and serve it via a specialized playlist. This allows for a more fault-tolerant stream that can play on more devices.
+
+First, create a directory that will house the HLS stream and give Nginx permission to write to it:
+
+
+```
+mkdir /mnt/hls
+chown www:www /mnt/hls
+```
+
+Next, fire up your text editor, open the Nginx.conf file, and add the following under the **application live** section:
+
+
+```
+ application live {
+ live on;
+ # Turn on HLS
+ hls on;
+ hls_path /mnt/hls/;
+ hls_fragment 3;
+ hls_playlist_length 60;
+ # disable consuming the stream from nginx as rtmp
+ deny play all;
+}
+```
+
+Take note of the HLS fragment and playlist length settings. You may want to adjust them later, depending on your streaming needs, but this is a good baseline to start with. Next, we need to ensure that Nginx is able to listen for requests from our player and understand how to present it to the user. So, we'll want to add a new section at the bottom of our nginx.conf file.
+
+
+```
+server {
+ listen 8080;
+
+ location / {
+ # Disable cache
+ add_header 'Cache-Control' 'no-cache';
+
+ # CORS setup
+ add_header 'Access-Control-Allow-Origin' '*' always;
+ add_header 'Access-Control-Expose-Headers' 'Content-Length';
+
+ # allow CORS preflight requests
+ if ($request_method = 'OPTIONS') {
+ add_header 'Access-Control-Allow-Origin' '*';
+ add_header 'Access-Control-Max-Age' 1728000;
+ add_header 'Content-Type' 'text/plain charset=UTF-8';
+ add_header 'Content-Length' 0;
+ return 204;
+ }
+
+ types {
+ application/dash+xml mpd;
+ application/vnd.apple.mpegurl m3u8;
+ video/mp2t ts;
+ }
+
+ root /mnt/;
+ }
+ }
+```
+
+Visit Video.js's [Getting started][5] page to download the latest release and check out the release notes. Also on that page, Video.js has a great introductory template you can use to create a very basic web player. I'll break down the important bits of that template and insert the pieces you need to get your new HTML player to use your stream.
+
+The **head** links in the Video.js library from a content-delivery network (CDN). You can also opt to download and store Video.js locally on your web server if you want.
+
+
+```
+<head>
+ <link href="" rel="stylesheet" />
+
+ <!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
+ <script src="[https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"\>\][6]</script>
+</head>
+```
+
+Now to the real meat of the player. The **body** section sets the parameters of how the video player will be displayed. Within the **video** element, you need to define the properties of your player. How big do you want it to be? Do you want it to have a poster (i.e., a thumbnail)? Does it need any special player controls? This example defines a simple 600x600 pixel player with an appropriate (to me) thumbnail featuring Beastie (the BSD Demon) and Tux (the Linux penguin).
+
+
+```
+<body>
+ <video
+ id="my-video"
+ class="video-js"
+ controls
+ preload="auto"
+ width="600"
+ height="600"
+ poster="BEASTIE-TUX.jpg"
+ data-setup="{}"
+ >
+```
+
+Now that you've set how you want your player to look, you need to tell it what to play. Video.js can handle a large number of different formats, including HLS streams.
+
+
+```
+ <source src="" type="application/x-mpegURL" />
+ <p class="vjs-no-js">
+ To view this video please enable JavaScript, and consider upgrading to a
+ web browser that
+ <a href="" target="_blank"
+ >supports HTML5 video</a
+ >
+ </p>
+ </video>
+```
+
+### Record your streams
+
+Keeping a copy of your streams is super easy. Just add the following at the bottom of your **application live** section in the nginx.conf file:
+
+
+```
+# Enable stream recording
+record all;
+record_path /mnt/recordings/;
+record_unique on;
+```
+
+Make sure that **record_path** exists and that Nginx has permissions to write to it:
+
+
+```
+`chown -R www:www /mnt/recordings`
+```
+
+### Down the stream
+
+That's it! You should now have a spiffy new HTML5-friendly live video player. There are lots of great resources out there on how to expand all your video-making adventures. If you have any questions or suggestions, feel free to reach out to me on [Twitter][7] or leave a comment below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/video-streaming-tools
+
+作者:[Aaron J. Prisk][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/ricepriskytreat
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/video_editing_folder_music_wave_play.png?itok=-J9rs-My (video editing dashboard)
+[2]: https://opensource.com/article/19/1/basic-live-video-streaming-server
+[3]: https://videojs.com/
+[4]: https://en.wikipedia.org/wiki/HTTP_Live_Streaming
+[5]: https://videojs.com/getting-started
+[6]: https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"\>\
+[7]: https://twitter.com/AKernelPanic
diff --git a/sources/tech/20200223 The Zen of Go.md b/sources/tech/20200223 The Zen of Go.md
new file mode 100644
index 0000000000..c4143aed32
--- /dev/null
+++ b/sources/tech/20200223 The Zen of Go.md
@@ -0,0 +1,414 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (The Zen of Go)
+[#]: via: (https://dave.cheney.net/2020/02/23/the-zen-of-go)
+[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
+
+The Zen of Go
+======
+
+_This article was derived from my [GopherCon Israel 2020][1] presentation. It’s also quite long. If you’d prefer a shorter version, head over to [the-zen-of-go.netlify.com][2]_.
+
+_A recording of the presentation is available on [YouTube][3]._
+
+* * *
+
+### How should I write good code?
+
+Something that I’ve been thinking about a lot recently, when reflecting on the body of my own work, is a common subtitle, _how should I write good code?_ Given nobody actively seeks to write _bad_ code, this leads to the question; _how do you know when you’ve written good Go code?_
+
+If there’s a continuum between good and bad, how to do we know what the good parts are? What are its properties, its attributes, its hallmarks, its patterns, and its idioms?
+
+### Idiomatic Go
+
+![][4]
+
+Which brings me to idiomatic Go. To say that something is idiomatic is to say that it follows the style of the time. If something is not idiomatic, it is not following the prevailing style. It is unfashionable.
+
+More importantly, to say to someone that their code is not idiomatic does not explain _why_ it’s not idiomatic. Why is this? Like all truths, the answer is found in the dictionary.
+
+> idiom (noun): a group of words established by usage as having a meaning not deducible from those of the individual words.
+
+Idioms are hallmarks of shared values. Idiomatic Go is not something you learn from a book, it’s something that you acquire by being part of a community.
+
+![][5]
+
+My concern with the mantra of idiomatic Go is, in many ways, it can be exclusionary. It’s saying “you can’t sit with us.” After all, isn’t that what we mean when critique of someone’s work as non-idiomatic? They didn’t do It right. It doesn’t look right. It doesn’t follow the style of time.
+
+I offer that idiomatic Go is not a suitable mechanism for teaching how to write good Go code because it is defined, fundamentally, by telling someone they did it wrong. Wouldn’t it be better if the advice we gave didn’t alienate the author right at the point they were most willing to accept it?
+
+### Proverbs
+
+Stepping away problematic idioms, what other cultural artefacts do Gophers have? Perhaps we can turn to Rob Pike’s wonderful [Go Proverbs][6]. Are these suitable teaching tools? Will these tell newcomers how to write good Go code?
+
+In general, I don’t think so. This is not to dismiss Pike’s work, it is just that the Go Proverbs, like Segoe Kensaku’s original, are observations, not statements of value. Again, the dictionary comes to the rescue:
+
+> proverb (noun): a short, well-known pithy saying, stating a general truth or piece of advice.
+
+The goal of the Go Proverbs are to reveal a deeper truth about the design of the language, but how useful is advice like the _empty interface says nothing_ to a novice from a language that doesn’t have structural typing?
+
+It’s important to recognise that, in a growing community, at any time the people learning Go far outnumber those who claim to have mastered the language. Thus proverbs are perhaps not the best teaching tool in this scenario.
+
+### Engineering Values
+
+Dan Luu found [an old presentation][7] by Mark Lucovsky about the engineering culture of the windows team around the windows NT-windows 2000 timeframe. The reason I mention it is Lukovsky’s description of a culture as a common way of evaluating designs and making tradeoffs.
+
+![][8]
+
+There are many ways of discussing culture, but with respect to an engineering culture Lucovsky’s description is apt. The central idea is _values guide decisions in an unknown design space_. The values of the NT team were; portability, reliability, security, and extensibility. Engineering values are, crudely translated, the way things are done around here.
+
+### Go’s values
+
+What are the explicit values of Go? What are the core beliefs or philosophy that define the way a Go programmer interprets the world? How are they promulgated? How are they taught? How are they enforced? How do they change over time?
+
+How will you, as a newly minted Go programmer, inculcate the engineering values of Go? Or, how will you, a seasoned Go professional promulgate your values to a future generations? And just so we’re clear, this process of knowledge transfer is not optional. Without new blood and new ideas, our community become myopic and wither.
+
+#### The values of other languages
+
+To set the scene for what I’m getting at we can look to other languages we see examples of their engineering values.
+
+For example, C++ (and by extension Rust) believe that a programmer _should not have to pay for a feature they do not use_. If a program does not use some computationally expensive feature of the language, then it shouldn’t be forced to shoulder the cost of that feature. This value extends from the language, to its standard library, and is used as a yardstick for judging the design of all code written in C++.
+
+In Java, and Ruby, and Smalltalk, the core value that _everything is an object_ drives the design of programs around message passing, information hiding, and polymorphism. Designs that shoehorn a procedural style, or even a functional style, into these languages are considered to be wrong–or as Gophers would say, non idiomatic.
+
+Turning to our own community, what are the engineering values that bind Go programmers? Discourse in our community is often fractious, so deriving a set of values from first principles would be a formidable challenge. Consensus is critical, but exponentially more difficult as the number of contributors to the discussion increases. But what if someone had done the hard work for us.
+
+### The Zen of ~~Python~~ Go
+
+Several decades ago Tim Peters sat down and penned _[PEP-20][9]_, the Zen of Python. Peters’ attempted to document the engineering values that he saw Guido van Rossum apply in his role as BDFL for Python.
+
+For the remainder of this article, I’m going to look towards the Zen of Python and ask, is there anything that can inform the engineering values of Go programmers?
+
+### A good package starts with a good name
+
+Let’s start with something spicy,
+
+> “Namespaces are one honking great idea–let’s do more of those!”
+
+The Zen of Python, Item 19
+
+This is pretty unequivocal, Python programmers should use namespaces. Lots of them.
+
+In Go parlance a namespace is a package. I doubt there is any question that grouping things into packages is good for design and potentially reuse. But there might be some confusion, especially if you’re coming with a decade of experience in another language, about the right way to do this.
+
+In Go each package should have a purpose, and the best way to know a package’s purpose is by its name—a noun. A package’s name describes what it provides. So too reinterpret Peters’ words, every Go package should have a single purpose.
+
+This is not a new idea, [I’ve been saying this a while][10], but why should you do this rather than approach where packages are used for fine grained taxonomy? Why, because change.
+
+> “Design is the art of arranging code to work today, and be changeable forever.”
+
+Sandi Metz
+
+Change is the name of the game we’re in. What we do as programmers is manage change. When we do that well we call it design, or architecture. When we do it badly we call it technical debt, or legacy code.
+
+If you are writing a program that works perfectly, one time, for one fixed set of inputs then nobody cares if the code is good or bad because ultimately the output of the program is all the business cares about.
+
+But this is _never_ true. Software has bugs, requirements change, inputs change, and very few programs are written solely to be executed once, thus your program _will_ change over time. Maybe it’s you who’ll be tasked with this, more likely it will be someone else, but someone has to change that code. Someone has to maintain that code.
+
+So, how can we make it easy to for programs to change? Interfaces everywhere? Make everything mockable? Pernicious dependency injection? Well, maybe, for some classes of programs, but not many, those techniques will be useful. However, for the majority of programs, designing something to be flexible up front is over engineering.
+
+What if, instead, we take a position that rather than enhancing components, we replace them. Then the best way to know when something needs to be replaced, is when it doesn’t do what it says on the tin.
+
+A good package starts with choosing a good name. Think of your package’s name as an elevator pitch, using just one word, to describe what it provides. When the name no longer matches the requirement, find a replacement.
+
+### Simplicity matters
+
+> “Simple is better than complex.”
+
+The Zen of Python, Item 3
+
+PEP-20 says simple is better than complex, I couldn’t agree more. A couple of years ago I made this tweet;
+
+> Most programming languages start out aiming to be simple, but end up just settling for being powerful.
+>
+> — Dave Cheney (@davecheney) [December 2, 2014][11]
+
+My observation, at least at the time, was that I couldn’t think of a language introduced in my life time that didn’t purport to be simple. Each new language offered as a justification, and an enticement, their inherent simplicity. But as I researched, I found that simplicity was not a core value of the many of the languages considered Go’s contemporaries. [1][12] Maybe this is just a cheap shot, but could it be that either these languages aren’t simple, or they don’t _think_ of themselves as being simple. They don’t consider simplicity to be a core value.
+
+Call me old fashioned, but when did being simple fall out of style? Why does the commercial software development industry continually, gleefully, forget this fundamental truth?
+
+> “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”
+
+C. A. R. Hoare, The Emperor’s Old Clothes, 1980 Turing Award Lecture
+
+Simple does not mean easy, we know that. Often it is more work to make something simple to use, than easy to build.
+
+> “Simplicity is prerequisite for reliability.”
+
+Edsger W Dijkstra, EWD498, 18 June 1975
+
+Why should we strive for simplicity? Why is important that Go programs be simple? Simple doesn’t mean crude, it means readable and maintainable. Simple doesn’t mean unsophisticated, it means reliable, relatable, and understandable.
+
+> “Controlling complexity is the essence of computer programming.”
+
+Brian W. Kernighan, _Software Tools_ (1976)
+
+Whether Python abides by its mantra of simplicity is a matter for debate, but Go holds simplicity as a core value. I think that we can all agree that when it comes to Go, simple code is preferable to clever code.
+
+### Avoid package level state
+
+> “Explicit is better than implicit.”
+
+_The Zen of Python, Item_ 2
+
+This is a place where I think Peters’ was more aspirational than factual. Many things in Python are not explicit; decorators, dunder methods, and so on. Without doubt they are powerful, there’s a reason those features exists. Each feature is something someone cared enough about to do the work to implement it, especially the complicated ones. But heavy use of those features makes is harder for the reader to predict the cost of an operation.
+
+The good news is we have a choice, as Go programmers, to choose to make our code explicit. Explicit could mean many things, perhaps you may be thinking explicit is just a nice way of saying bureaucratic and long winded, but that’s a superficial interpretation. It’s a misnomer to focus only on the syntax on the page, to fret about line lengths and DRYing up expressions. The more valuable, in my opinon, place to be explicit are to do with coupling and with state.
+
+Coupling is a measure of the amount one thing depends on another. If two things are tightly coupled, they move together. An action that affects one is directly reflected in another. Imagine a train, each carriage joined–ironically the correct word is coupled–together; where the engine goes, the carriages follow.
+
+Another way to describe coupling is the word cohesion. Cohesion measures how well two things naturally belong together. We talk about a cohesive argument, or a cohesive team; all their parts fit together as if they were designed that way.
+
+Why does coupling matter? Because just like trains, when you need to change a piece of code, all the code that is tightly coupled to it must change. A prime example, someone release a new version of their API and now your code doesn’t compile.
+
+APIs are an unavoidable source of coupling but there are more insidious forms of coupling. Clearly everyone knows that if an API’s signature changes the data passing into and out of that call changes. It’s right there in the signature of the function; I take values of these types and return values of other types. But what if the API passed data another way? What if every time you called this API the result was based on the previous time you called that API even though you didn’t change your parameters.
+
+This is state, and management of state is _the_ problem in computer science.
+
+```
+package counter
+
+var count int
+
+func Increment(n int) int {
+ count += n
+ return count
+}
+```
+
+Suppose we have this simple `counter` package. You can call `Increment` to increment the counter, you can even get the value back if you `Increment` with a value of zero.
+
+Suppose you had to test this code, how would you reset the counter after each test? Suppose you wanted to run those tests in parallel, could you do it? Now suppose that you wanted to count more than one thing per program, could you do it?
+
+No, of course not. Clearly the answer is to encapsulate the `count` variable in a type.
+
+```
+package counter
+
+type Counter struct {
+ count int
+}
+
+func (c *Counter) Increment(n int) int {
+ c.count += n
+ return c.count
+}
+```
+
+Now imagine that this problem isn’t restricted to just counters, but your applications main business logic. Can you test it in isolation? Can you test it in parallel? Can you use more than one instance at a time? If the answer those question is _no_, the reason is package level state.
+
+Avoid package level state. Reduce coupling and spooky action at a distance by providing the dependencies a type needs as fields on that type rather than using package variables.
+
+### Plan for failure, not success
+
+> “Errors should never pass silently.”
+
+_The Zen of Python, Item 1_0
+
+It’s been said of languages that favour exception handling follow the Samurai principle; _return victorious or not at all_. In exception based languages functions only return valid results. If they don’t succeed then control flow takes an entirely different path.
+
+Unchecked exceptions are clearly an unsafe model to program in. How can you possibly write code that is robust in the presence of errors when you don’t know which statements could throw an exception? Java tried to make exceptions safer by introducing the notion of a checked exception which, to the best of my knowledge, has not been repeated in another mainstream language. There are plenty of languages which use exceptions but they all, with the singular exception of Java, do so in the unchecked variety.
+
+Obviously Go chose a different path. Go programmers believe that robust programs are composed from pieces that handle the failure cases _before_ they handle the happy path. In the space that Go was designed for; server programs, multi threaded programs, programs that handle input over the network, dealing with unexpected data, timeouts, connection failures and corrupted data must be front and centre of the programmer’s mind if they are to produce robust programs.
+
+> “I think that error handling should be explicit, this should be a core value of the language.”
+
+Peter Bourgon, [GoTime #91][13]
+
+I want to echo Peter’s assertion, as it was the impetus for this article. I think so much of the success of Go is due to the explicit way errors are handled. Go programmers thinks about the failure case first. We solve the “what if…” case first. This leads to programs where failures are handled at the point of writing, rather than the point they occur in production.
+
+The verbosity of
+
+```
+if err != nil {
+ return err
+}
+```
+
+is outweighed by the value of deliberately handling each failure condition at the point at which they occur. Key to this is the cultural value of handling each and every error explicitly.
+
+### Return early rather than nesting deeply
+
+> “Flat is better than nested.”
+
+The Zen of Python, Item 5
+
+This is sage advice coming from a language where indentation is the primary form of control flow. How can we interpret this advice in terms of Go? `gofmt` controls the overall whitespace of a Go program so there’s not thing doing there.
+
+I wrote earlier about package names, and there is probably some advice here about avoiding a complicated package hierarchy. In my experience the more a programmer tries to subdivide and taxonimise their Go codebase the more they risk hitting the dead end that is package import loops.
+
+I think the best application of item 5’s advice is the control flow _within_ a function. Simply put, avoid control flow that requires deep indentation.
+
+> “Line of sight is a straight line along which an observer has unobstructed vision.”
+
+May Ryer, [Code: Align the happy path to the left edge][14]
+
+Mat Ryer describes this idea as line of sight coding. Light of sight coding means things like:
+
+ * Using guard clauses to return early if a precondition is not met.
+ * Placing the successful return statement at the end of the function rather than inside a conditional block.
+ * Reducing the overall indentation level of the function by extracting functions and methods.
+
+
+
+Key to this advice is the thing that you care about, the thing that the function does, is never in danger of sliding out of sight to the right of your screen. This style has a bonus side effect that you’ll avoid pointless arguments about line lengths on your team.
+
+Every time you indent you add another precondition to the programmers stack, consuming one of their 7 ±2 short term memory slots. Rather than nesting deeply, keep the successful path of the function close to the left hand side of your screen.
+
+### If you think it’s slow, prove it with a benchmark
+
+> “In the face of ambiguity, refuse the temptation to guess.”
+
+The Zen of Python, Item 12
+
+Programming is based on mathematics and logic, two concepts which rarely involve the element of chance. But there are many things we, as programmers, guess about every day. What does this variable do? What does this parameter do? What happens if I pass `nil` here? What happens if I call `Register` twice? There’s actually a lot of guesswork in modern programming, especially when it comes to using libraries you didn’t write.
+
+> “APIs should be easy to use and hard to misuse.”
+
+Josh Bloch
+
+One of the best ways I know to help a programmer avoid having to guess is to, when building an API, [focus on the default use case][15]. Make it as easy as you can for the caller to do the most common thing. However, I’ve written and talked a lot about API design in the past, so instead my interpretation of item 12 is; _don’t guess about performance_.
+
+Despite how you may feel about Knuth’s advice, one of the drivers of Go’s success is its efficient execution. You can write efficient programs in Go and thus people _will_ choose Go because of this. There are a lot of misconceptions about performance, so my request is, when you’re looking to performance tune your code or you’re facing some dogmatic advice like defer is slow, CGO is expensive, or always use atomics not mutexes, don’t guess.
+
+Don’t complicate your code because of outdated dogma, and, if you think something is slow, first prove it with a benchmark. Go has excellent benchmarking and profiling tools that come in the distribution for free. Use them to find your bottlenecks.
+
+### Before you launch a goroutine, know when it will stop
+
+At this point I think I think I’ve mined the valuable points from PEP-20 and possibly stretched its reinterpretation beyond the point of good taste. I think that’s fine, because although this was a useful rhetorical device, ultimately we are talking about two different languages.
+
+> “You type g o, a space, and then a function call. Three keystrokes, you can’t make it much shorter than that. Three keystrokes and you’ve just started a sub process.”
+
+Rob Pike, [Simplicity is Complicated][16], dotGo 2015
+
+The next two suggestions I’ll dedicate to goroutines. Goroutines are the signature feature of the language, our answer for first class concurrency. They are so easy to use, just put the word `go` in front of the statement and you’ve launched that function asynchronously. It’s so simple, no threads, no stack sizes, no thread pool executors, no ID’s, no tracking completion status.
+
+Goroutines are cheap. Because of the runtime’s ability to multiplex goroutines onto a small pool of threads (which you don’t have to manage), hundreds of thousands, millions of goroutines are easily accommodated. This opens up designs that would be not be practical under competing concurrency models like threads or evented callbacks.
+
+But as cheap as goroutines are, they’re not free. At a minimum there’s a few kilobytes for their stack, which, when you’re getting up into the 10^6 goroutines, does start to add up. This is not to say you shouldn’t use millions of goroutines if that is what the design calls for, but when you do, it’s critical that you keep track of them because 10^6 of anything can consume a non trivial amount of resources in aggregate.
+
+Goroutines are the key to resource ownership in Go. To be useful a goroutine has to do something, and that means it almost always holds reference to, or ownership of, a resource; a lock, a network connection, a buffer with data, the sending end of a channel. While that goroutine is alive, the lock is held, the network connection remains open, the buffer retained and the receivers of the channel will continue to wait for more data.
+
+The simplest way to free those resources is to tie them to the lifetime of the goroutine–when the goroutine exits, the resource has been freed. So while it’s near trivial to start a goroutine, before you write those three letters, g o and a space, make sure you have an answer to these questions:
+
+ * **Under what condition will a goroutine stop?** Go doesn’t have a way to tell a goroutine to exit. There is no stop or kill function, for good reason. If we cannot command a goroutine to stop, we must instead ask it, politely. Almost always this comes down to a channel operation. Range loops over a channel exit when the channel is closed. A channel will become selectable if it is closed. The signal from one goroutine to another is best expressed as a closed channel.
+ * **What is required for that condition to arise?** If channels are both the vehicle to communicate between goroutines and the mechanism for them to signal completion, the next question to the programmer becomes, who will close the channel, when will that happen?
+ * **What signal will you use to know the goroutine has stopped?** When you signal a goroutine to stop, that stopping will happen at some time in the future relative to the goroutine’s frame of reference. It might happen quickly in terms of human perception, but computers execute billions of instructions every second, and from the point of view of each goroutine, their execution of instructions is unsynchronised. The solution is often to use a channel to signal back or a waitgroup where a fan in approach is needed.
+
+
+
+### Leave concurrency to the caller
+
+It is likely that in any serious Go program you write there will be concurrency involved. This raises the problem, many of the libraries and code that we write fall into this a one goroutine per connection, or worker pattern. How will you manage the lifetime of those goroutines?
+
+`net/http` is a prime example. Shutting down the server owning the listening socket is relatively straight forward, but what about a goroutines spawned from that accepting socket? `net/http` does provide a context object inside the request object which can be used to signal–to code that is listening–that the request should be canceled, thereby terminating the goroutine, however it is less clear how to know when all of these things have been done. It’s one thing to call `context.Cancel`, its another to know that the cancellation has completed.[2][17]
+
+The point I want to make about `net/http` is that its a counter example to good practice. Because each connection is handled by a goroutine spawned inside the `net/http.Server` type, the program, living outside the `net/http` package, does not have an ability to control the goroutines spawned for the accepting socket.
+
+This is an area of design that is still evolving, with efforts like go-kit’s `run.Group` and the Go team’s [`ErrGroup`][18] which provide a framework to execute, cancel and wait on functions run asynchronously.
+
+The bigger design maxim here is for library writers, or anyone writing code that could be run asynchronously, leave the responsibility of starting to goroutine to your caller. Let the caller choose how they want to start, track, and wait on your functions execution.
+
+### Write tests to lock in the behaviour of your package’s API
+
+Perhaps you were hoping to read an article from me where I didn’t rant about testing. Sadly, today is not that day.
+
+Your tests are the contract about what your software does and does not do. Unit tests at the package level should lock in the behaviour of the package’s API. They describe, in code, what the package promises to do. If there is a unit test for each input permutation, you have defined the contract for what the code will do _in code_, not documentation.
+
+This is a contract you can assert as simply as typing `go test`. At any stage, you can _know_ with a high degree of confidence, that the behaviour people relied on before your change continues to function after your change.
+
+Tests lock in api behaviour. Any change that adds, modifies or removes a public api must include changes to its tests.
+
+### Moderation is a virtue
+
+Go is a simple language, only 25 keywords. In some ways this makes the features that are built into the language stand out. Equally these are the features that the language sells itself on, lightweight concurrency, structural typing.
+
+I think all of us have experienced the confusion that comes from trying to use all of Go’s features at once. Who was so excited to use channels that they used them as much as they could, as often as they could? Personally for me I found the result was hard to test, fragile, and ultimately overcomplicated. Am I alone?
+
+I had the same experience with goroutines, attempting to break the work into tiny units I created a hard to manage hurd of Goroutines and ultimately missed the observation that most of my goroutines were always blocked waiting for their predecessor– the code was ultimately sequential and I had added a lot of complexity for little real world benefit. Who has experienced something like this?
+
+I had the same experience with embedding. Initially I mistook it for inheritance. Then later I recreated the fragile base class problem by composing complicated types, which already had several responsibilities, into more complicated mega types.
+
+This is potentially the least actionable piece of advice, but one I think is important enough to mention. The advice is always the same, all things in moderation, and Go’s features are no exception. If you can, don’t reach for a goroutine, or a channel, or embed a struct, anonymous functions, going overboard with packages, interfaces for everything, instead prefer simpler approach rather than the clever approach.
+
+### Maintainability counts
+
+I want to close with one final item from PEP-20,
+
+> “Readability Counts.”
+
+The Zen of Python, Item 7
+
+So much has been said, about the importance of readability, not just in Go, but all programming languages. People like me who stand on stages advocating for Go use words like simplicity, readability, clarity, productivity, but ultimately they are all synonyms for one word–_maintainability_.
+
+The real goal is to write maintainable code. Code that can live on after the original author. Code that can exist not just as a point in time investment, but as a foundation for future value. It’s not that readability doesn’t matter, maintainability matters _more_.
+
+Go is not a language that optimises for clever one liners. Go is not a language which optimises for the least number of lines in a program. We’re not optimising for the size of the source code on disk, nor how long it takes to type the program into an editor. Rather, we want to optimise our code to be clear to the reader. Because its the reader who’s going to have to maintain this code.
+
+If you’re writing a program for yourself, maybe it only has to run once, or you’re the only person who’ll ever see it, then do what ever works for you. But if this is a piece of software that more than one person will contribute to, or that will be used by people over a long enough time that requirements, features, or the environment it runs in may change, then your goal must be for your program to be maintainable. If software cannot be maintained, then it will be rewritten; and that could be the last time your company will invest in Go.
+
+Can the thing you worked hard to build be maintained after you’re gone? What can you do today to make it easier for someone to maintain your code tomorrow?
+
+##### [the-zen-of-go.netlify.com][2]
+
+ 1. This part of the talk had several screenshots of the landing pages for the websites for [Ruby][19], [Swift][20], [Elm][21], [Go][22], [NodeJS][23], [Python][24], [Rust][25], highlighting how the language described itself.[][26]
+ 2. I tend to pick on `net/http` a lot, and this is not because it is bad, in fact it is the opposite, it is the most successful, oldest, most used API in the Go codebase. And because of that its design, evolution, and shortcoming have been thoroughly picked over. Think of this as flattery, not criticism.[][27]
+
+
+
+#### Related posts:
+
+ 1. [Never start a goroutine without knowing how it will stop][28]
+ 2. [Simplicity Debt][29]
+ 3. [Curious Channels][30]
+ 4. [Let’s talk about logging][31]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://dave.cheney.net/2020/02/23/the-zen-of-go
+
+作者:[Dave Cheney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://dave.cheney.net/author/davecheney
+[b]: https://github.com/lujun9972
+[1]: https://www.gophercon.org.il
+[2]: https://the-zen-of-go.netlify.com
+[3]: https://www.youtube.com/watch?v=yd_rtwYaXps
+[4]: https://dave.cheney.net/wp-content/uploads/2020/02/1011226.jpg
+[5]: https://dave.cheney.net/wp-content/uploads/2020/02/mean-girls-you-cant-sit-with-us-main.jpg
+[6]: http://go-proverbs.github.io
+[7]: https://danluu.com/microsoft-culture/
+[8]: https://dave.cheney.net/wp-content/uploads/2020/02/Lucovsky.001.jpeg
+[9]: https://www.python.org/dev/peps/pep-0020/
+[10]: https://dave.cheney.net/2019/01/08/avoid-package-names-like-base-util-or-common
+[11]: https://twitter.com/davecheney/status/539576755254611968?ref_src=twsrc%5Etfw
+[12]: tmp.iUoDiQyXMU#easy-footnote-bottom-1-3936 (This part of the talk had several screenshots of the landing pages for the websites for Ruby, Swift, Elm, Go, NodeJS, Python, Rust, highlighting how the language described itself.)
+[13]: https://changelog.com/gotime/91
+[14]: https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
+[15]: http://sweng.the-davies.net/Home/rustys-api-design-manifesto
+[16]: https://www.youtube.com/watch?v=rFejpH_tAHM
+[17]: tmp.iUoDiQyXMU#easy-footnote-bottom-2-3936 (I tend to pick on net/http a lot, and this is not because it is bad, in fact it is the opposite, it is the most successful, oldest, most used API in the Go codebase. And because of that its design, evolution, and shortcoming have been thoroughly picked over. Think of this as flattery, not criticism.)
+[18]: https://godoc.org/golang.org/x/sync/errgroup
+[19]: https://www.ruby-lang.org/en/
+[20]: https://swift.org
+[21]: https://elm-lang.org
+[22]: https://golang.org
+[23]: https://nodejs.org/en/
+[24]: https://www.python.org
+[25]: https://www.rust-lang.org
+[26]: tmp.iUoDiQyXMU#easy-footnote-1-3936
+[27]: tmp.iUoDiQyXMU#easy-footnote-2-3936
+[28]: https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop (Never start a goroutine without knowing how it will stop)
+[29]: https://dave.cheney.net/2017/06/15/simplicity-debt (Simplicity Debt)
+[30]: https://dave.cheney.net/2013/04/30/curious-channels (Curious Channels)
+[31]: https://dave.cheney.net/2015/11/05/lets-talk-about-logging (Let’s talk about logging)
diff --git a/sources/tech/20200224 17 Cool Arduino Project Ideas for DIY Enthusiasts.md b/sources/tech/20200224 17 Cool Arduino Project Ideas for DIY Enthusiasts.md
new file mode 100644
index 0000000000..2cfe9c1872
--- /dev/null
+++ b/sources/tech/20200224 17 Cool Arduino Project Ideas for DIY Enthusiasts.md
@@ -0,0 +1,272 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (17 Cool Arduino Project Ideas for DIY Enthusiasts)
+[#]: via: (https://itsfoss.com/cool-arduino-projects/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+17 Cool Arduino Project Ideas for DIY Enthusiasts
+======
+
+[Arduino][1] is an open-source electronics platform that combines both open source software and hardware to let people make interactive projects with ease. You can get Arduino-compatible [single board computers][2] and use them to make something useful.
+
+In addition to the hardware, you will also need to know the [Arduino language][3] to use the [Arduino IDE][4] to successfully create something.
+
+You can code using the web editor or use the Arduino IDE offline. Nevertheless, you can always refer to the [official resources][5] available to learn about Arduino.
+
+Considering that you know the essentials, I will be mentioning some of the best (or interesting) Arduino projects. You can try to make them for yourself or modify them to come up with something of your own.
+
+### Interesting Arduino project ideas for beginners, experts, everyone
+
+![][6]
+
+The following projects need a variety of additional hardware – so make sure to check out the official link to the projects (_originally featured on the [official Arduino Project Hub][7]_) to learn more about them.
+
+Also, it is worth noting that they aren’t particularly in any ranking order – so feel free to try what sounds best to you.
+
+#### 1\. LED Controller
+
+Looking for simple Arduino projects? Here’s one for you.
+
+One of the easiest projects that let you control LED lights. Yes, you do not have to opt for expensive LED products just to decorate your room (or for any other use-case), you can simply make an LED controller and customize it to use it however you want.
+
+It requires using the [Arduino UNO board][8] and a couple more things (which also includes an Android phone). You can learn more about it in the link to the project below.
+
+[LED Controller][9]
+
+#### 2\. Hot Glue LED Matrix Lamp
+
+![][10]
+
+Another Arduino LED project for you. Since we are talking about using LEDs to decorate, you can also make an LED lamp that looks beautiful.
+
+For this, you might want to make sure that you have a 3D printer. Next, you need an LED strip and **Arduino Nano R3** as the primary materials.
+
+Once you’ve printed the case and assembled the lamp section, all you need to do is to add the glue sticks and figure out the wiring. It does sound very simple to mention – you can learn more about it on the official Arduino project feature site.
+
+[LED Matrix Lamp][11]
+
+#### 3\. Arduino Mega Chess
+
+![][12]
+
+Want to have a personal digital chessboard? Why not?
+
+You’ll need a TFT LCD touch screen display and an [Arduino Mega 2560][13] board as the primary materials. If you have a 3D printer, you can create a pretty case for it and make changes accordingly.
+
+Take a look at the original project for inspiration.
+
+[Arduino Mega Chess][14]
+
+#### 4\. Enough Already: Mute My TV
+
+A very interesting project. I wouldn’t argue the usefulness of it – but if you’re annoyed by certain celebrities (or personalities) on TV, you can simply mute their voice whenever they’re about to speak something on TV.
+
+Technically, it was tested with the old tech back then (when you didn’t really stream anything). You can watch the video above to get an idea and try to recreate it or simply head to the link to read more about it.
+
+[Mute My TV][15]
+
+#### 5\. Robot Arm with Controller
+
+![][16]
+
+If you want to do something with the help of your robot and still have manual control over it, the robot arm with a controller is one of the most useful Arduino projects. It uses the [Arduino UNO board][8] if you’re wondering.
+
+You will have a robot arm -for which you can make a case using the 3D printer to enhance its usage and you can use it for a variety of use-cases. For instance, to clean the carbage using the robot arm or anything similar where you don’t want to directly intervene.
+
+[Robotic Arm With Controller][17]
+
+#### 6\. Make Musical Instrument Using Arduino
+
+I’ve seen a variety of musical instruments made using Arduino. You can explore the Internet if you want something different than this.
+
+You would need a [Pi supply flick charge][18] and an **Arduino UNO** to make it happen. It is indeed a cool Arduino project where you get to simply tap and your hand waves will be converted to music. Also, it isn’t tough to make this – so you should have a lot of fun making this.
+
+[Musical Instrument using Arduino][19]
+
+#### 7\. Pet Trainer: The MuttMentor
+
+An Arduino-based device that assists you to help train your pet – sounds exciting!
+
+For this, they’re using the [Arduino Nano 33 BLE Sense][20] while utilizing TensorFlow to train a small neural network for all the common actions that your pet does. Accordingly, the buzzer will offer a reinforcing notification when your pet obeys your command.
+
+This can have wide applications when tweaked as per your requirements. Check out the details below.
+
+[The MuttMentor][21]
+
+#### 8\. Basic Earthquake Detector
+
+Normally, you depend on the government officials to announce/inform about the earthquake stats (or the warning for it).
+
+But with Arduino boards, you can simply build a basic earthquake detector and have transparent results for yourself without depending on the authorities. Click on the button below to know about the relevant details to help make it.
+
+[Basic Earthquake Detector][22]
+
+#### 9\. Security Access Using RFID Reader
+
+![][23]
+
+As the project describes – “_RFID tagging is an ID system that uses small radio frequency identification_ “.
+
+So, in this project, you will be making an RFID reader using Arduino while pairing it with an [Adafruit NFC card][24] for security access. Check out the full details using the button below and let me know how it works for you.
+
+[Security Access using RFID reader][25]
+
+#### 10\. Smoke Detection using MQ-2 Gas Sensor
+
+![][26]
+
+This could be potentially one of the best Arduino projects out there. You don’t need to spend a lot of money to equip smoke detectors for your home, you can manage with a DIY solution to some extent.
+
+Of course, unless you want a complex failsafe set up along with your smoke detector, a basic inexpensive solution should do the trick. In either case, you can also find other applications for the smoke detector.
+
+[Smoke Detector][27]
+
+#### 11\. Arduino Based Amazon Echo using 1Sheeld
+
+![][28]
+
+In case you didn’t know [1Sheeld][29] basically replaces the need for an add-on Arduino board. You just need a smartphone and add Arduino shields to it so that you can do a lot of things with it.
+
+Using 5 such shields, the original creator of this project made himself a DIY Amazon Echo. You can find all the relevant details, schematics, and code to make it happen.
+
+[DIY Amazon Echo][30]
+
+#### 12\. Audio Spectrum Visualizer
+
+![][31]
+
+Just want to make something cool? Well, here’s an idea for an audio spectrum visualizer.
+
+For this, you will need an Arduino Nano R3 and an LED display as primary materials to get started with. You can tweak the display as required. You can connect it with your headphone output or simply a line-out amplifier.
+
+Easily one of the cheapest Arduino projects that you can try for fun.
+
+[Audio Spectrum Visualizer][32]
+
+#### 13\. Motion Following Motorized Camera
+
+![][33]
+
+Up for a challenge? If you are – this will be one of the coolest Arduino Projects in our list.
+
+Basically, this is meant to replace your home security camera which is limited to an angle of video recording. You can turn the same camera into a motorized camera that follows the motion.
+
+So, whenever it detects a movement, it will change its angle to try to follow the object. You can read more about it to find out how to make it.
+
+[Motion Following Motorized Camera][34]
+
+#### 14\. Water Quality Monitoring System
+
+![][35]
+
+If you’re concerned about your health in connection to the water you drink, you can try making this.
+
+It requires an Arduino UNO and the water quality sensors as the primary materials. To be honest, a useful Arduino project to go for. You can find everything you need to make this in the link below.
+
+[Water Quality Monitoring System][36]
+
+#### 15\. Punch Activated Arm Flamethrower
+
+I would be very cautious about this – but seriously, one of the best (and coolest) Arduino projects I’ve ever come across.
+
+Of course, this counts as a fun project to try out to see what bigger projects you can pull off using Arduino and here it is. In the project, he originally used the [SparkFun Arduino Pro Mini 328][37] along with an accelerometer as the primary materials.
+
+[Punch Activated Flamethrower][38]
+
+#### 16\. Polar Drawing Machine
+
+![][39]
+
+This isn’t any ordinary plotter machine that you might’ve seen people creating using Arduino boards.
+
+With this, you can draw some cool vector graphics images or bitmap. It might sound like bit of overkill but then it could also be fun to do something like this.
+
+This could be a tricky project, so you can refer to the details on the link to go through it thoroughly.
+
+[Polar Drawing Machine][40]
+
+#### 17\. Home Automation
+
+Technically, this is just a broad project idea because you can utilize the Arduino board to automate almost anything you want at your home.
+
+Just like I mentioned, you can go for a security access device, maybe create something that automatically waters the plants or simply make an alarm system.
+
+Countless possibilities of what you can do to automate things at your home. For reference, I’ve linked to an interesting home automation project below.
+
+[Home Automation][41]
+
+#### Bonus: Robot Cat (OpenCat)
+
+![][42]
+
+A programmable robotic cat for AI-enhanced services and STEM education. In this project, both Arduino and Raspberry Pi boards have been utilized.
+
+You can also look at the [Raspberry Pi alternatives][2] if you want. This project needs a lot of work, so you would want to invest a good amount of time to make it work.
+
+[OpenCat][43]
+
+**Wrapping Up**
+
+With the help of Arduino boards (coupled with other sensors and materials), you can do a lot of projects with ease. Some of the projects that I’ve listed above are suitable for beginners and some are not. Feel free to take your time to analyze what you need and the cost of the project before proceeding.
+
+Did I miss listing an interesting Arduino project that deserves the mention here? Let me know your thoughts in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/cool-arduino-projects/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://www.arduino.cc/
+[2]: https://itsfoss.com/raspberry-pi-alternatives/
+[3]: https://www.arduino.cc/reference/en/
+[4]: https://www.arduino.cc/en/main/software
+[5]: https://www.arduino.cc/en/Guide/HomePage
+[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/arduino-project-ideas.jpg?ssl=1
+[7]: https://create.arduino.cc/projecthub
+[8]: https://store.arduino.cc/usa/arduino-uno-rev3
+[9]: https://create.arduino.cc/projecthub/mayooghgirish/arduino-bluetooth-basic-tutorial-d8b737?ref=platform&ref_id=424_trending___&offset=89
+[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/led-matrix-lamp.jpg?ssl=1
+[11]: https://create.arduino.cc/projecthub/john-bradnam/hot-glue-led-matrix-lamp-42322b?ref=platform&ref_id=424_trending___&offset=42
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/arduino-chess-board.jpg?ssl=1
+[13]: https://store.arduino.cc/usa/mega-2560-r3
+[14]: https://create.arduino.cc/projecthub/Sergey_Urusov/arduino-mega-chess-d54383?ref=platform&ref_id=424_trending___&offset=95
+[15]: https://makezine.com/2011/08/16/enough-already-the-arduino-solution-to-overexposed-celebs/
+[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/02/robotic-arm-controller.jpg?ssl=1
+[17]: https://create.arduino.cc/projecthub/H0meMadeGarbage/robot-arm-with-controller-2038df?ref=platform&ref_id=424_trending___&offset=13
+[18]: https://uk.pi-supply.com/products/flick-hat-3d-tracking-gesture-hat-raspberry-pi
+[19]: https://create.arduino.cc/projecthub/lanmiLab/make-musical-instrument-using-arduino-and-flick-large-e2890b?ref=platform&ref_id=424_trending___&offset=24
+[20]: https://store.arduino.cc/usa/nano-33-ble-sense
+[21]: https://create.arduino.cc/projecthub/whatsupdog/the-muttmentor-9d9753?ref=platform&ref_id=424_trending___&offset=44
+[22]: https://www.instructables.com/id/Basic-Arduino-Earthquake-Detector/
+[23]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/security-access-arduino.jpg?ssl=1
+[24]: https://www.adafruit.com/product/359
+[25]: https://create.arduino.cc/projecthub/Aritro/security-access-using-rfid-reader-f7c746?ref=platform&ref_id=424_trending___&offset=85
+[26]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/smoke-detection-arduino.jpg?ssl=1
+[27]: https://create.arduino.cc/projecthub/Aritro/smoke-detection-using-mq-2-gas-sensor-79c54a?ref=platform&ref_id=424_trending___&offset=89
+[28]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/diy-amazon-echo.jpg?ssl=1
+[29]: https://1sheeld.com/
+[30]: https://create.arduino.cc/projecthub/ahmedismail3115/arduino-based-amazon-echo-using-1sheeld-84fa6f?ref=platform&ref_id=424_trending___&offset=91
+[31]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/audio-spectrum-visualizer.jpg?ssl=1
+[32]: https://create.arduino.cc/projecthub/Shajeeb/32-band-audio-spectrum-visualizer-analyzer-902f51?ref=platform&ref_id=424_trending___&offset=87
+[33]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/motion-following-camera.jpg?ssl=1
+[34]: https://create.arduino.cc/projecthub/lindsi8784/motion-following-motorized-camera-base-61afeb?ref=platform&ref_id=424_trending___&offset=86
+[35]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/02/water-quality-monitoring.jpg?ssl=1
+[36]: https://create.arduino.cc/projecthub/chanhj/water-quality-monitoring-system-ddcb43?ref=platform&ref_id=424_trending___&offset=93
+[37]: https://www.sparkfun.com/products/11113
+[38]: https://create.arduino.cc/projecthub/Advanced/punch-activated-arm-flamethrowers-real-firebending-95bb80
+[39]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/polar-drawing-machine.jpg?ssl=1
+[40]: https://create.arduino.cc/projecthub/ArduinoFT/polar-drawing-machine-f7a05c?ref=search&ref_id=drawing&offset=2
+[41]: https://create.arduino.cc/projecthub/ahmedel-hinidy2014/home-management-system-control-your-home-from-a-website-076846?ref=search&ref_id=home%20automation&offset=4
+[42]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/opencat.jpg?ssl=1
+[43]: https://create.arduino.cc/projecthub/petoi/opencat-845129?ref=platform&ref_id=424_popular___&offset=8
diff --git a/sources/tech/20200224 Make free encrypted backups to the cloud on Fedora.md b/sources/tech/20200224 Make free encrypted backups to the cloud on Fedora.md
new file mode 100644
index 0000000000..6015e6dc92
--- /dev/null
+++ b/sources/tech/20200224 Make free encrypted backups to the cloud on Fedora.md
@@ -0,0 +1,237 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Make free encrypted backups to the cloud on Fedora)
+[#]: via: (https://fedoramagazine.org/make-free-encrypted-backups-to-the-cloud-on-fedora/)
+[#]: author: (Curt Warfield https://fedoramagazine.org/author/rcurtiswarfield/)
+
+Make free encrypted backups to the cloud on Fedora
+======
+
+![][1]
+
+Most free cloud storage is limited to 5GB or less. Even Google Drive is limited to 15GB. While not heavily advertised, IBM offers free accounts with a whopping **25GB** of cloud storage for free. This is not a limited time offer, and you don’t have to provide a credit card. It’s absolutely free! Better yet, since it’s S3 compatible, most of the S3 tools available for backups should work fine.
+
+This article will show you how to use restic for encrypted backups onto this free storage. Please also refer to [this previous Magazine article about installing and configuring restic.][2] Let’s get started!
+
+### Creating your free IBM account and storage
+
+Head over to the IBM cloud services site and follow the steps to sign up for a free account here: . You’ll need to verify your account from the email confirmation that IBM sends to you.
+
+Then log in to your account to bring up your dashboard, at .
+
+Click on the **Create resource** button.
+
+![][3]
+
+Click on **Storage** and then **Object Storage**.
+
+![][4]
+
+Next click on the **Create Bucket** button.
+
+![][5]
+
+This brings up the **Configure your resource** section.
+
+![][6]
+
+Next, click on the ****Create** button to use the default settings.
+
+![][7]
+
+Under **Predefined buckets** click on the **Standard** box:
+
+![][8]
+
+A unique bucket name is automatically created, but it’s suggested that you change this.
+
+![][9]
+
+In this example, the bucket name is changed to __freecloudstorage_._**
+
+Click on the **Next** button after choosing a bucket name:
+
+![][10]
+
+Continue to click on the **Next** button until you get the the **Summary** page:
+
+![][11]
+
+Scroll down to the **Endpoints** section.
+
+![][12]
+
+The information in the **Public** section is the location of your bucket. This is what you need to specify in restic when you create your backups. In this example, the location is **s3.us-south.cloud-object-storage.appdomain.cloud**.
+
+### Making your credentials
+
+The last thing that you need to do is create an access ID and secret key. To start, click on **Service credentials**.
+
+![][13]
+
+Click on the **New credential** button.
+
+![][14]
+
+Choose a name for your credential, make sure you check the **Include HMAC Credential** box and then click on the **Add** button. In this example I’m using the name **resticbackup**.
+
+![][15]
+
+Click on **View credentials**.
+
+![][16]
+
+The _access_key_id_ and _secret_access_key_ is what you are looking for. (For obvious reasons, the author’s details here are obscured.)
+
+You will need to export these by calling them with the _export_ alias in the shell, or putting them into a backup script.
+
+![][17]
+
+### Preparing a new repository
+
+Restic refers to your backup as a _repository_, and can make backups to any bucket on your IBM cloud account. First, setup the following environment variables using your _access_key_id_ and _secret_access_key_ that you retrieved from your IBM cloud bucket. These can also be set in any backup script you may create.
+
+```
+$ export AWS_ACCESS_KEY_ID=
+$ export AWS_SECRET_ACCESS_KEY=
+```
+
+Even though you are using IBM Cloud and not AWS, as previously mentioned, IBM Cloud storage is S3 compatible, and restic uses its interal AWS commands for any S3 compatible storage. So these AWS keys really refer to the keys from your IBM bucket.
+
+Create the repository by initializing it. A prompt appears for you to type a password for the repository. _**Do not lose this password because your data is irrecoverable without it!**_
+
+```
+restic -r s3:http://PUBLIC_ENDPOINT_LOCATION/BUCKET init
+```
+
+The _PUBLIC_ENDPOINT_LOCATION_ was specified in the Endpoint section of your Bucket summary.
+
+![][18]
+
+For example:
+
+```
+$ restic -r s3:http://s3.us-south.cloud-object-storage.appdomain.cloud/freecloudstorage init
+```
+
+### Creating backups
+
+Now it’s time to backup some data. Backups are called _snapshots_. Run the following command and enter the repository password when prompted.
+
+```
+restic -r s3:http://PUBLIC_ENDPOINT_LOCATION/BUCKET backup files_to_backup
+```
+
+For example:
+
+```
+$ restic -r s3:http://s3.us-south.cloud-object-storage.appdomain.cloud/freecloudstorage backup Documents/
+Enter password for repository:
+ repository 106a2eb4 opened successfully, password is correct
+ Files: 51 new, 0 changed, 0 unmodified
+ Dirs: 0 new, 0 changed, 0 unmodified
+ Added to the repo: 11.451 MiB
+ processed 51 files, 11.451 MiB in 0:06
+ snapshot 611e9577 saved
+```
+
+### Restoring from backups
+
+Now that you’ve backed up some files, it’s time to make sure you know how to restore them. To get a list of all of your backup snapshots, use this command:
+
+```
+restic -r s3:http://PUBLIC_ENDPOINT_LOCATION/BUCKET snapshots
+```
+
+For example:
+
+```
+$ restic -r s3:http://s3.us-south.cloud-object-storage.appdomain.cloud/freecloudstorage snapshots
+Enter password for repository:
+ID Date Host Tags Directory
+-------------------------------------------------------------------
+106a2eb4 2020-01-15 15:20:42 client /home/curt/Documents
+```
+
+To restore an entire snapshot, run a command like this:
+
+```
+restic -r s3:http://s3.us-south.cloud-object-storage.appdomain.cloud/freecloudstorage restore snapshotID --target restoreDirectory
+```
+
+For example:
+
+```
+$ restic -r s3:http://s3.us-south.cloud-object-storage.appdomain.cloud/freecloudstorage restore 106a2eb4 --target ~
+Enter password for repository:
+repository 106a2eb4 opened successfully, password is correct
+restoring to /tmp
+```
+
+* * *
+
+_Photo by [Alex Machado][19] on [Unsplash][20]._
+
+[EDITORS NOTE: The Fedora Project is [sponsored][21] by [Red Hat][22], which is owned by [IBM][23].]
+
+[EDITORS NOTE: Updated at 1647 UTC on 24 February 2020 to correct a broken link.]
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/make-free-encrypted-backups-to-the-cloud-on-fedora/
+
+作者:[Curt Warfield][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/rcurtiswarfield/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/01/encrypted-backups-ibm-cloud-816x345.jpg
+[2]: https://fedoramagazine.org/use-restic-encrypted-backups/
+[3]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmclouddash-3-e1579713553261.png
+[4]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmcloudresourcestorage-3.png
+[5]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmcloudbucket-3.png
+[6]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmcloudbucket2.png
+[7]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmcloudbucket3-e1579713758635.png
+[8]: https://fedoramagazine.org/wp-content/uploads/2020/01/ibmcloudbucket4.png
+[9]: https://fedoramagazine.org/wp-content/uploads/2020/01/createbucket1.png
+[10]: https://fedoramagazine.org/wp-content/uploads/2020/01/next.png
+[11]: https://fedoramagazine.org/wp-content/uploads/2020/01/bucketsummary-1024x368.png
+[12]: https://fedoramagazine.org/wp-content/uploads/2020/01/endpoints-1024x272.png
+[13]: https://fedoramagazine.org/wp-content/uploads/2020/01/servicecreds.png
+[14]: https://fedoramagazine.org/wp-content/uploads/2020/01/newcred.png
+[15]: https://fedoramagazine.org/wp-content/uploads/2020/01/addnewcred.png
+[16]: https://fedoramagazine.org/wp-content/uploads/2020/01/keys-1024x298.png
+[17]: https://fedoramagazine.org/wp-content/uploads/2020/01/keys2.png
+[18]: https://fedoramagazine.org/wp-content/uploads/2020/01/publicendpoint.png
+[19]: https://unsplash.com/@alexmachado?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
+[20]: https://unsplash.com/s/photos/backups-to-cloud?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
+[21]: https://getfedora.org/sponsors/
+[22]: https://redhat.com
+[23]: https://www.ibm.com/cloud/redhat
diff --git a/sources/tech/20200228 4 technologists on careers in tech for minorities.md b/sources/tech/20200228 4 technologists on careers in tech for minorities.md
new file mode 100644
index 0000000000..806300d5db
--- /dev/null
+++ b/sources/tech/20200228 4 technologists on careers in tech for minorities.md
@@ -0,0 +1,126 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (4 technologists on careers in tech for minorities)
+[#]: via: (https://opensource.com/article/20/2/careers-tech-minorities)
+[#]: author: (Shilla Saebi https://opensource.com/users/shillasaebi)
+
+4 technologists on careers in tech for minorities
+======
+Learn what Black History Month means to them, what influences their
+career, resources for minorities wanting to break into tech, and more.
+![Team meeting][1]
+
+In honor of Black History Month, I've garnered the opinions of a few of my favorite technology professionals and open source contributors. These four individuals are paving the way for the next generation alongside the work they're doing in the technology industry. Learn what Black History Month means to them, what influences their career, resources for minorities wanting to break into tech, and more.
+
+**[Tameika Reed][2], founder of Women In Linux**
+
+Since its launch, Tameika leads initiatives with a focus on exploring careers in infrastructure, cybersecurity, DevOps and IoT, pivoting into leadership and continuous skill-building. As a self-taught system administrator, Tameika believes the best way to learn tech is by just diving in. In efforts to give women a 360° view of tech, Tameika hosts a weekly virtual meetup to explore outside the norm of just Linux but introducing hyperledger, Kubernetes, microservices, and high-performance computing. Tameika’s career includes different conference talks from OSCon, LISA 2018, Seagl, HashiCorp EU 2019, and various local events.
+
+**[Michael Scott Winslow][3], Director, Core Applications and Platforms, Comcast**
+
+"I'm a father, husband, brother, and son. I come from a small family so I have fun turning friends into an extended family. When I attach my name to something, I obsess over its success, so I am very careful what I agree to be a part of. Oh, so as far as my career I have been involved with software development for decades. I solve problems. I work with others to help solve large problems. I lead, guide and mentor newer software engineers while observing others that I want to learn from."
+
+**[Bryan Liles][4], senior staff engineer, VMware**
+
+"I’m working with our team to rethink how developers interact with Kubernetes. When not working, I’m out in the community trying to inspire the next generation of software engineers and building robots."
+
+**[Mutale Nkonde][5], founding CEO of AI For the People (AFP)**
+
+AFP is a nonprofit creative agency. Prior to starting a nonprofit she worked in AI Governance. During that time she was part of the team that introduced the Algorithmic and Deep Fakes Algorithmic Acts, as well as the No Biometric Barriers to Housing Act to the US House of Representatives. Nkonde started her career as a broadcast journalist and worked at the BBC, CNN & ABC. She also writes widely on race and tech, as well as holding fellowships at Harvard and Stanford.
+
+### What influenced you to pursue a career in technology?
+
+My fear of the computer when I went back to college. I was afraid of the computer because I dropped out of college. After and going back, I made it my mission to learn all I can. This is still my motto to this day, learning never stops. —Tameika Reed
+
+I won’t mince words, I was a child geek! At 10 years old I started writing GW-BASIC from code that I read in printed magazines. Every single day. I gave it a bit of a break to have a life while I went to high school, but when it came time to pick a major for college, it was an easy choice. I stayed in technology thanks to the amazing mentors and colleagues I’ve had along the way. —Michael Scott Winslow
+
+I’ve been writing software since I was in middle school. I like being able to tell computers to do things and seeing the results. As an adult, I quickly realized that having a job that gave me satisfaction and paid well was the way to go. —Bryan Liles
+
+I wanted to explore the questions around why so few black women were being hired by tech companies. —Mutale Nkonde
+
+### Is there a particular person or people in open source and the tech world who have inspired you?
+
+I get inspired by a lot of other people and projects. For example, I love seeing others come to [Women In Linux][6] and are sure where they want to go. I try to give people a 360-view of tech so they can make a decision on what they like. Its easy to say I want to be in tech but it’s hard to get started and stay. You don’t have to be just a coder/programmer but you can be a cloud architect. —Tameika Reed
+
+[Kelsey Hightower][7], [Bryan Liles][4], and Kim Scott inspire me very much. They are so REAL! They say things that I feel and experience every day. Get your job done! Stop complaining! Own your actions and understand how you contribute to your situation! [Gene Kim][8] is a big inspiration as well. As a leader in the DevOps movement, I see myself following and emulating a lot of things he does. —Michael Scott Winslow
+
+No. I didn’t see the inspiration I wanted, so I’ve worked hard to be the inspiration I needed 20 years ago. —Bryan Liles
+
+There are so many! One of my favorites is [Dorothy Vaughan][9]: She was the first person in the US to program an IBM Watson computer. Her story is captured in the movie Hidden Figures. —Mutale Nkonde
+
+### Are there particular resources you would recommend for minorities wanting to break into tech?
+
+Yes, I recommend finding folks on Twitter and just ask questions. Here is a list of people I follow and admire in tech: —Tameika Reed
+
+ * [@techgirl1908][10]
+ * [@bryanl][4]
+ * [@kelseyhightower][7]
+ * [@kstewart][11]
+ * [@tiffani][12]
+ * [@EricaJoy][13]
+ * [@womeninlinux][6]
+ * [@ArlanWasHere][14]
+ * [@blkintechnology][15]
+ * [@digundiv][16]
+
+
+
+Respected bootcamps are really cutting down the time it takes to break into the tech industry. I’ve met several professionals who went through bootcamps who have outshined their 4-year institution counterparts. I think we can really start respecting everything that people bring to the table, rather than technical fluency. —Michael Scott Winslow
+
+I’m not sure I can recommend anything specific. Tech is a big thing and there isn’t an easy answer. My advice is to pick something you think will be interested in and work to become an expert on the topic. Start asking why instead of how, and also start understanding how things work together. — Bryan Liles
+
+It really depends on the type of work they want to do. For people working at the intersection of tech and social justice, I would recommend the book [Algorithms of Oppression][17] by Safiya Noble. —Mutale Nkonde
+
+### What advice would you give to a person of color considering technology as their career?
+
+I suggest you study your craft. You will be a forever learner. There will always be someone or something in your way how you respond and move will be on you. Never take the first offer push back and know your worth. I look at tech like I look at art. It takes time to develop so be patient with yourself. It's okay to unplug and say no. —Tameika Reed
+
+As someone who is a bit of a protector of the industry, I don’t want people who are not suited for technology. So really decide if you have the personality for tech. Are you a problem solver? Are you more logical than emotional? Do you constantly find yourself creating processes? If so, no matter your background, I think you can find a home in tech. —Michael Scott Winslow
+
+It is not going to be simple. Your progress will be slowed because of your race. You will have to work harder. Use this adversity as a strength. You will be better prepared than those around you and when the opportunity arises, you will be able to tackle it. Find a network of those who look like you. Air grievances in private and show strength in public. You belong and you can succeed. —Bryan Liles
+
+To think beyond working for a company, the field of public interest tech is growing, our work centers on how technology impacts real people. Many of the people leading this work are women of color and Black women are making huge strides. Mutale Nkonde
+
+### What does Black History Month mean to you?
+
+It means never stop because you can never forget. —Tameika Reed
+
+Black History Month to me means focusing on the Tuskegee Airmen and not slavery. Highlighting how we contributed to history and not how were victims of it. I want people to understand where our pride comes from and not our anger. There are a lot of really bad things that happened to our people and we are still right here. Strong! —Michael Scott Winslow
+
+Black History Month is a time to reflect on the forgotten history of black people in the United States. I take it as a time to be thankful for the sacrifices my ancestors made. —Bryan Liles
+
+It is a time to center the contributions black people have made across the globe. I love it, it is one of my favorite times of year. —Mutale Nkonde
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/careers-tech-minorities
+
+作者:[Shilla Saebi][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/shillasaebi
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/meeting-team-listen-communicate.png?itok=KEBP6vZ_ (Team meeting)
+[2]: https://www.linkedin.com/in/tameika-reed-1a7290128/
+[3]: https://twitter.com/michaelswinslow
+[4]: https://twitter.com/bryanl
+[5]: https://twitter.com/mutalenkonde
+[6]: https://twitter.com/WomenInLinux
+[7]: https://twitter.com/kelseyhightower
+[8]: https://twitter.com/RealGeneKim
+[9]: https://en.wikipedia.org/wiki/Dorothy_Vaughan
+[10]: https://twitter.com/techgirl1908
+[11]: https://twitter.com/kstewart
+[12]: https://twitter.com/tiffani
+[13]: https://twitter.com/EricaJoy
+[14]: https://twitter.com/ArlanWasHere
+[15]: https://twitter.com/blkintechnology
+[16]: https://twitter.com/digundiv
+[17]: http://algorithmsofoppression.com/
diff --git a/sources/tech/20200228 Fedora-s gaggle of desktops.md b/sources/tech/20200228 Fedora-s gaggle of desktops.md
new file mode 100644
index 0000000000..d92d84344a
--- /dev/null
+++ b/sources/tech/20200228 Fedora-s gaggle of desktops.md
@@ -0,0 +1,411 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Fedora’s gaggle of desktops)
+[#]: via: (https://fedoramagazine.org/fedoras-gaggle-of-desktops/)
+[#]: author: (Troy Dawson https://fedoramagazine.org/author/tdawson/)
+
+Fedora’s gaggle of desktops
+======
+
+![][1]
+
+There are 38 different desktops or window managers in Fedora 31. You could try a different one every day for a month, and still have some left over. Some have very few features. Some have so many features they are called a desktop environment. This article can’t go into detail on each, but it’s interesting to see the whole list in one place.
+
+### Criteria for desktops
+
+To be on this list, the desktop must show up on the desktop manager’s selection list. If the desktop has more than one entry in the desktop manager list, they are counted just as that one desktop. An example is “GNOME”, “GNOME Classic” and “GNOME (Wayland).” These all show up on the desktop manager list, but they are still just GNOME.
+
+### List of desktops
+```
+
+```
+
+#### [**9wm**][2]
+
+```
+Emulation of the Plan 9 window manager 8 1/2
+ dnf install 9wm
+```
+
+#### [**awesome**][3]
+
+```
+Highly configurable, framework window manager for X. Fast, light and extensible
+https://fedoramagazine.org/5-cool-tiling-window-managers/
+ dnf install awesome
+```
+
+#### [**blackbox**][4]
+
+```
+Very small and fast Window Manager
+Fedora uses the maintained fork on github
+ dnf install blackbox
+```
+
+#### [**bspwm**][5]
+
+```
+A tiling window manager based on binary space partitioning
+https://github.com/windelicato/dotfiles/wiki/bspwm-for-dummies
+ dnf install bspwm
+```
+
+#### **[byobu][6]**
+
+```
+Light-weight, configurable window manager built upon GNU screen
+ dnf install byobu
+```
+
+#### **[Cinnamon][7]**
+
+```
+Cinnamon provides a desktop with a traditional layout, advanced features, easy to use, powerful and flexible.
+https://projects.linuxmint.com/cinnamon/
+https://opensource.com/article/19/12/cinnamon-linux-desktop
+ dnf group install "Cinnamon Desktop"
+```
+
+#### **[cwm][8]**
+
+```
+Calm Window Manager by OpenBSD project
+https://steemit.com/technology/@jamesdeagle/the-calm-window-manager-cwm-a-quick-start-guide
+ dnf install cwm
+```
+
+#### **[Deepin][9]**
+
+```
+Deepin desktop is the desktop environment released with deepin (the linux distribution). It aims at being elegant and easy to use.
+ dnf group install "Deepin Desktop"
+ (optional) dnf group install "Deepin Desktop Office" "Media packages for Deepin Desktop"
+```
+
+#### **[dwm][10]**
+
+```
+Dynamic window manager for X
+https://fedoramagazine.org/lets-try-dwm-dynamic-window-manger/
+https://fedoramagazine.org/5-cool-tiling-window-managers/
+ dnf install dwm
+ (optional) dnf install dwm-user
+```
+
+#### **[enlightenment][11]**
+
+```
+Enlightenment window manager
+https://opensource.com/article/19/12/linux-enlightenment-desktop
+ dnf install enlightenment
+```
+
+#### **[e16][11]**
+
+```
+The Enlightenment window manager, DR16
+ dnf install e16
+ (optional) dnf install e16-epplets e16-keyedit e16-themes
+```
+
+#### **[fluxbox][12]**
+
+```
+Window Manager based on Blackbox
+ dnf install fluxbox
+ (optional) dnf install fluxbox-pulseaudio fluxbox-vim-syntax
+```
+
+#### **[fvwm][13]**
+
+```
+Highly configurable multiple virtual desktop window manager
+http://www.fvwm.org/
+https://opensource.com/article/19/12/fvwm-linux-desktop
+ dnf install fvwm
+```
+
+#### **[GNOME][14]**
+
+```
+GNOME is a highly intuitive and user friendly desktop environment.
+* both X11 and wayland
+https://opensource.com/article/19/12/gnome-linux-desktop
+https://fedoramagazine.org/3-simple-and-useful-gnome-shell-extensions/
+ dnf group install "GNOME"
+ (optional but large) dnf group install "Fedora Workstation"
+```
+
+#### **[herbstluftwm][15]**
+
+```
+A manual tiling window manager
+https://opensource.com/article/19/12/herbstluftwm-linux-desktop
+ dnf install herbstluftwm
+ (optional) dnf install herbstluftwm-zsh herbstluftwm-fish
+```
+
+#### **[i3][16]**
+
+```
+Improved tiling window manager
+https://fedoramagazine.org/getting-started-i3-window-manager/
+https://fedoramagazine.org/using-i3-with-multiple-monitors/
+ dnf install i3
+ (optional) dnf install i3-doc i3-ipc
+```
+
+#### **[icewm][17]**
+
+```
+Window manager designed for speed, usability, and consistency
+https://fedoramagazine.org/icewm-a-really-cool-desktop/
+ dnf install icewm
+ (optional) dnf install icewm-minimal-session
+```
+
+#### **[jwm][18]**
+
+```
+Joe's Window Manager
+https://opensource.com/article/19/12/joes-window-manager-linux-desktop
+ dnf install jwm
+```
+
+#### **[KDE Plasma Desktop][19]**
+
+```
+The KDE Plasma Workspaces, a highly-configurable graphical user interface which includes a panel, desktop, system icons and desktop widgets, and many powerful KDE applications.
+* both X11 and wayland
+https://opensource.com/article/19/12/linux-kde-plasma
+https://fedoramagazine.org/installing-kde-plasma-5/
+ dnf group install "KDE Plasma Workspaces"
+ (optional) dnf group install "KDE Applications" "KDE Educational applications" "KDE Multimedia support" "KDE Office" "KDE Telepathy"
+ (optional for wayland) dnf install kwin-wayland plasma-workspace-wayland
+```
+
+#### **[lumina][20]**
+
+```
+A lightweight, portable desktop environment
+https://opensource.com/article/19/12/linux-lumina-desktop
+ dnf install lumina-desktop
+ (optional) dnf install lumina-*
+```
+
+#### **[LXDE][21]**
+
+```
+LXDE is a lightweight X11 desktop environment designed for computers with low hardware specifications like netbooks, mobile devices or older computers.
+https://opensource.com/article/19/12/lxqt-lxde-linux-desktop
+ dnf group install "LXDE Desktop"
+ (optional) dnf group install "LXDE Office" "Multimedia support for LXDE"
+```
+
+#### **[LXQt][22]**
+
+```
+LXQt is a lightweight X11 desktop environment designed for computers with low hardware specifications like netbooks, mobile devices or older computers.
+https://opensource.com/article/19/12/lxqt-lxde-linux-desktop
+ dnf group install "LXQt Desktop"
+ (optional) dnf group install "LXQt Office" "Multimedia support for LXQt"
+```
+
+#### **[MATE][23]**
+
+```
+MATE Desktop is based on GNOME 2 and provides a powerful graphical user interface for users who seek a simple easy to use traditional desktop interface.
+https://opensource.com/article/19/12/mate-linux-desktop
+https://fedoramagazine.org/installing-another-desktop/
+ dnf group install "MATE Desktop"
+ (optional) dnf group install "MATE Applications"
+```
+
+#### **[musca][24]**
+
+```
+A simple dynamic window manager fox X
+ dnf install musca
+```
+
+#### **[openbox][25]**
+
+```
+A highly configurable and standards-compliant X11 window manager
+https://opensource.com/article/19/12/openbox-linux-desktop
+https://fedoramagazine.org/openbox-fedora/
+ dnf install openbox
+ (optional) dnf install openbox-kde openbox-theme-mistral-thin-dark
+```
+
+#### **[Pantheon][26]**
+
+```
+The Pantheon desktop environment is the DE that powers elementaryOS.
+https://github.com/elementary
+https://opensource.com/article/19/12/pantheon-linux-desktop
+ dnf group install "Pantheon Desktop"
+ (optional) dnf install elementary-capnet-assist elementary-greeter elementary-shortcut-overlay
+```
+
+#### **[pekwm][27]**
+
+```
+A small and flexible window manager
+https://opensource.com/article/19/12/pekwm-linux-desktop
+ dnf install pekwm
+```
+
+#### **[qtile][28]**
+
+```
+A pure-Python tiling window manager
+https://fedoramagazine.org/5-cool-tiling-window-managers/
+ dnf install qtile
+```
+
+#### **[ratpoison][29]**
+
+```
+Minimalistic window manager
+https://opensource.com/article/19/12/ratpoison-linux-desktop
+ dnf install ratpoison
+```
+
+#### **[sawfish][30]**
+
+```
+An extensible window manager for the X Window System
+ dnf install sawfish
+ (optional) dnf install sawfish-pager
+```
+
+#### **[spectrwm][31]**
+
+```
+Minimalist tiling window manager written in C
+ dnf install spectrwm
+```
+
+#### **[Sugar][32]**
+
+```
+A software playground for learning about learning.
+* Possibly the most unique desktop of this list.
+ dnf group install "Sugar Desktop Environment"
+ (optional) dnf group install "Additional Sugar Activities"
+```
+
+#### **[sway][33]**
+
+```
+i3-compatible window manager for Wayland
+* Wayland only
+https://fedoramagazine.org/setting-up-the-sway-window-manager-on-fedora/
+https://fedoramagazine.org/5-cool-tiling-window-managers/
+ dnf install sway
+```
+
+#### **[twm][34]**
+
+```
+X.Org X11 twm window manager
+https://en.wikipedia.org/wiki/Twm
+https://opensource.com/article/19/12/twm-linux-desktop
+ dnf install xorg-x11-twm
+```
+
+#### **[WindowMaker][35]**
+
+```
+A fast, feature rich Window Manager
+https://opensource.com/article/19/12/linux-window-maker-desktop
+ dnf install WindowMaker
+ (optional) dnf install WindowMaker-extra
+```
+
+#### **[wmx][36]**
+
+```
+A really simple window manager for X
+ dnf install wmx
+```
+
+#### **[XFCE][37]**
+
+```
+A lightweight desktop environment that works well on low end machines.
+https://opensource.com/article/19/12/xfce-linux-desktop
+ dnf group install "Xfce Desktop"
+ (optional) dnf group install "Applications for the Xfce Desktop" "Extra plugins for the Xfce panel" "Multimedia support for Xfce" "Xfce Office"
+```
+
+#### **[xmonad][38]**
+
+```
+A tiling window manager
+ dnf install xmonad
+ (optional) dnf install xmonad-mate
+```
+
+* * *
+
+_Photo by [Annie Spratt][39] on [Unsplash][40]._
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/fedoras-gaggle-of-desktops/
+
+作者:[Troy Dawson][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/tdawson/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/01/gaggle-desktops-816x345.jpg
+[2]: https://github.com/9wm/9wm
+[3]: https://awesomewm.org/
+[4]: https://github.com/bbidulock/blackboxwm
+[5]: https://github.com/baskerville/bspwm
+[6]: https://byobu.org/
+[7]: https://github.com/linuxmint/cinnamon
+[8]: https://github.com/leahneukirchen/cwm
+[9]: https://www.deepin.org/en/dde/
+[10]: http://dwm.suckless.org/
+[11]: https://www.enlightenment.org/
+[12]: http://fluxbox.org/
+[13]: https://github.com/fvwmorg/fvwm
+[14]: https://www.gnome.org/
+[15]: http://herbstluftwm.org/
+[16]: https://i3wm.org/
+[17]: https://ice-wm.org/
+[18]: http://joewing.net/projects/jwm/
+[19]: https://kde.org/
+[20]: https://lumina-desktop.org/
+[21]: https://lxde.org/
+[22]: https://lxqt.org/
+[23]: https://mate-desktop.org/
+[24]: https://github.com/enticeing/musca
+[25]: http://openbox.org
+[26]: https://elementary.io/
+[27]: http://www.pekwm.org/
+[28]: http://qtile.org
+[29]: http://www.nongnu.org/ratpoison/
+[30]: http://sawfish.wikia.com/
+[31]: https://github.com/conformal/spectrwm
+[32]: https://sugarlabs.org/
+[33]: https://github.com/swaywm/sway
+[34]: https://www.x.org/releases/X11R7.6/doc/man/man1/twm.1.xhtml
+[35]: http://www.windowmaker.org
+[36]: http://www.all-day-breakfast.com/wmx/
+[37]: https://www.xfce.org/
+[38]: https://hackage.haskell.org/package/xmonad
+[39]: https://unsplash.com/@anniespratt?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
+[40]: https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
diff --git a/sources/tech/20200228 How to process real-time data with Apache.md b/sources/tech/20200228 How to process real-time data with Apache.md
new file mode 100644
index 0000000000..7bf16741b4
--- /dev/null
+++ b/sources/tech/20200228 How to process real-time data with Apache.md
@@ -0,0 +1,87 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to process real-time data with Apache)
+[#]: via: (https://opensource.com/article/20/2/real-time-data-processing)
+[#]: author: (Simon Crosby https://opensource.com/users/simon-crosby)
+
+How to process real-time data with Apache
+======
+Open source is leading the way with a rich canvas of projects for
+processing real-time events.
+![Alarm clocks with different time][1]
+
+In the "always-on" future with billions of connected devices, storing raw data for analysis later will not be an option because users want accurate responses in real time. Prediction of failures and other context-sensitive conditions require data to be processed in real time—certainly before it hits a database.
+
+It's tempting to simply say "the cloud will scale" to meet demands to process streaming data in real time, but some simple examples show that it can never meet the need for real-time responsiveness to boundless data streams. In these situations—from mobile devices to IoT—a new paradigm is needed. Whereas cloud computing relies on a "store then analyze" big data approach, there is a critical need for software frameworks that are comfortable instantly processing endless, noisy, and voluminous streams of data as they arrive to permit a real-time response, prediction, or insight.
+
+For example, the city of Palo Alto, Calif. produces more streaming data from its traffic infrastructure per day than the Twitter Firehose. That's a lot of data. Predicting city traffic for consumers like Uber, Lyft, and FedEx requires real-time analysis, learning, and prediction. Event processing in the cloud leads to an inescapable latency of about half a second per event.
+
+We need a simple yet powerful programming paradigm that lets applications process boundless data streams on the fly in these and similar situations:
+
+ * Data volumes are huge, or moving raw data is expensive.
+ * Data is generated by widely distributed assets (such as mobile devices).
+ * Data is of ephemeral value, and analysis can't wait.
+ * It is critical to always have the latest insight, and extrapolation won't do.
+
+
+
+### Publish and subscribe
+
+A key architectural pattern in the domain of event-driven systems is the concept of pub/sub or publish/subscribe messaging. This is an asynchronous communication method in which messages are delivered from _publishers_ (anything producing data) to *subscribers (*applications that process data). Pub/sub decouples arbitrary numbers of senders from an unknown set of consumers.
+
+In pub/sub, sources _publish_ events for a _topic_ to a _broker_ that stores them in the order in which they are received. An application _subscribes_ to one or more _topics_, and the _broker_ forwards matching events. Apache Kafka and Pulsar and CNCF NATS are pub/sub systems. Cloud services for pub/sub include Google Pub/Sub, AWS Kinesis, Azure Service Bus, Confluent Cloud, and others.
+
+Pub/sub systems do not _run_ subscriber applications—they simply _deliver_ data to topic subscribers.
+
+Streaming data often contains events that are updates to the state of applications or infrastructure. When choosing an architecture to process data, the role of a data-distribution system such as a pub/sub framework is limited. The "how" of the consumer application lies beyond the scope of the pub/sub system. This leaves an enormous amount of complexity for the developer to manage. So-called stream processors are a special kind of subscriber that analyzes data on the fly and delivers results back to the same broker.
+
+### Apache Spark
+
+[Apache Spark][2] is a unified analytics engine for large-scale data processing. Often, Apache Spark Streaming is used as a stream processor, for example, to feed machine learning models with new data. Spark Streaming breaks data into mini-batches that are each independently analyzed by a Spark model or some other system. The stream of events is grouped into mini-batches for analysis, but the stream processor itself must be elastic:
+
+ * The stream processor must be capable of scaling with the data rate, even across servers and clouds, and also balance load across instances, ensuring resilience and other application-layer needs.
+ * It must be able to analyze data from sources that report at widely different rates, meaning it must be stateful—or store state in a database. This latter approach is often used when Spark Streaming is used as the stream processor and can cause performance problems when ultra-low latency responses are needed.
+
+
+
+A related project, [Apache Samza][3], offers a way to process real-time event streams, and to scale elastically using [Hadoop Yarn][4] or [Apache Mesos][5] to manage compute resources.
+
+### Solving the problem of scaling data
+
+It's important to note that even Samza cannot entirely alleviate data processing demands for the application developer. Scaling data rates mean that tasks to process events need to be load-balanced across many instances, and the only way to share the resulting application-layer state between instances is to use a database. However, the moment state coordination between tasks of an application devolves to a database, there is an inevitable knock-on effect upon performance. Moreover, the choice of database is crucial. As the system scales, cluster management for the database becomes the next potential bottleneck.
+
+This can be solved with alternative solutions that are stateful, elastic, and can be used in place of a stream processor. At the application level (within each container or instance), these solutions build a stateful model of concurrent, interlinked "web agents" on the fly from streaming updates. Agents are concurrent "nano-services" that consume raw data for a single source and maintain their state. Agents interlink to share state based on real-world relationships between sources found in the data, such as containment and proximity. Agents thus form a graph of concurrent services that can analyze their own state and the states of agents to which they are linked. Each agent provides a nano-service for a single data source that converts from raw data to state and analyzes, learns, and predicts from its own changes and those of its linked subgraph.
+
+These solutions simplify application architecture by allowing agents—digital twins of real-world sources—to be widely distributed, even while maintaining the distributed graph that interlinks them at the application layer. This is because the links are URLs that map to the current runtime execution instance of the solution and the agent itself. In this way, the application seamlessly scales across instances without DevOps concerns. Agents consume data and maintain state. They also compute over their own state and that of other agents. Because agents are stateful, there is no need for a database, and insights are computed at memory speed.
+
+### Reading world data with open source
+
+There is a sea change afoot in the way we view data: Instead of the database being the system of record, the real world is, and digital twins of real-world things can continuously stream their state. Fortunately, the open source community is leading the way with a rich canvas of projects for processing real-time events. From pub/sub, where the most active communities are Apache Kafka, Pulsar, and CNCF NATS, to the analytical frameworks that continually process streamed data, including Apache Spark, [Flink][6], [Beam][7], Samza, and Apache-licensed [SwimOS][8] and [Hazelcast][9], developers have the widest choices of software systems. Specifically, there is no richer set of proprietary software frameworks available. Developers have spoken, and the future of software is open source.
+
+Introduction to Apache Hadoop, an open source software framework for storage and large scale...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/real-time-data-processing
+
+作者:[Simon Crosby][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/simon-crosby
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/clocks_time.png?itok=_ID09GDk (Alarm clocks with different time)
+[2]: https://spark.apache.org/
+[3]: https://samza.apache.org/
+[4]: https://hadoop.apache.org/
+[5]: http://mesos.apache.org/
+[6]: https://flink.apache.org/
+[7]: https://beam.apache.org
+[8]: https://github.com/swimos/swim
+[9]: https://hazelcast.com/
diff --git a/sources/tech/20200228 Revive your RSS feed with Newsboat in the Linux terminal.md b/sources/tech/20200228 Revive your RSS feed with Newsboat in the Linux terminal.md
new file mode 100644
index 0000000000..27a8d6ecbd
--- /dev/null
+++ b/sources/tech/20200228 Revive your RSS feed with Newsboat in the Linux terminal.md
@@ -0,0 +1,152 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Revive your RSS feed with Newsboat in the Linux terminal)
+[#]: via: (https://opensource.com/article/20/2/newsboat)
+[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
+
+Revive your RSS feed with Newsboat in the Linux terminal
+======
+Newsboat is an excellent RSS reader, whether you need a basic set of
+features or want your application to do a whole lot more.
+![Boat on the ocean with Creative Commons sail][1]
+
+Psst. Word on the web is that RSS died in 2013. That's when Google pulled the plug on Google Reader.
+
+Don't believe everything that you hear. RSS is alive. It's well. It's still a great way to choose the information you want to read without algorithms making the decision for you. All you need is the [right feed reader][2].
+
+Back in January, Opensource.com Correspondent [Kevin Sonney][3] introduced a nifty terminal RSS reader [called Newsboat][4]. In his article, Kevin scratched Newsboat's surface. I figured it was time to take a deeper dive into what Newsboat can do.
+
+### Adding RSS feeds to Newsboat
+
+As Kevin writes, "installing Newsboat is pretty easy since it is included with most distributions (and Homebrew on macOS)." You can, as Kevin also notes, import a [file containing RSS feeds][5] from another reader. If this is your first kick at the RSS can or it's been a while since you've used an RSS reader, chances are you don't have one of those files handy.
+
+Not to worry. You just need to do some copying and pasting. Go to the folder **.newsboat** in your **/home** directory. Once you're there, open the file **urls** in a text editor. Then, go to the websites you want to read, find the links to their RSS feeds, and copy and paste them into the **urls** file.
+
+![Newsboat urls file][6]
+
+Start Newsboat, and you're ready to get reading.
+
+### Reading your feeds
+
+As Kevin Sonney points out, you refresh your feeds by pressing the **r** or **R** keys on your keyboard. To read the articles from a feed, press **Enter** to open that feed and scroll down the list. Then, press **Enter** to read an item.
+
+![Newsboat reading][7]
+
+Return to the list of articles by pressing **q**. Press **q** again to return to your list of feeds.
+
+Every so often, you might run into a feed that shows just part of an article. That can be annoying. To get the full article, press **o** to open it in your desktop's default web browser. On my desktop, for example, that's Firefox. You can change the browser Newsboat works with; I'll explain that below.
+
+### Following links
+
+Hyperlinking has been a staple of the web since its beginnings at CERN in the early 1990s. It's hard to find an article published online that doesn't contain at least a couple of links that point elsewhere.
+
+Instead of leaving links embedded in an article or post, Newsboat gathers them into a numbered list at the end of the article or post.
+
+![Hyperlinks in Newsboat][8]
+
+To follow a link, press the number beside it. In the screenshot above, you'd press **4** to open the link to the homepage of one of the contributors to that article. The link, as you've probably guessed, opens in your default browser.
+
+### Using Newsboat as a client for other feed readers
+
+You might use a web-based feed reader, but might also want to read your RSS feeds in something a bit more minimal on your desktop. Newsboat can do that.
+
+It works with several feed readers, including The Old Reader, Inoreader, Newsblur, Tiny Tiny RSS, FeedHQ, and the newsreader apps for [ownCloud][9] and [Nextcloud][10]. Before you can read feeds from any of them, you'll need to do a little work.
+
+Go back to the **.newsboat** folder in your **/home** directory and create a file named **config**. Then add the settings that hook Newsboat into one of the RSS readers it supports. You can find more information about the specific settings for each reader in [Newsboat's documentation][11].
+
+Here's an example of the settings I use to connect Newsboat with the newsreader app in my instance of Nextcloud:
+
+
+```
+urls-source "ocnews"
+ocnews-url ""
+ocnews-login "myUserName"
+ocnews-password "NotTellingYouThat!"
+```
+
+I've tested this with Nextcloud, The Old Reader, Inoreader, and Newsblur. Newsboat worked seamlessly with all of them.
+
+![Newsboat with The Old Reader][12]
+
+### Other useful configuration tricks
+
+You can really unleash Newsboat's power and flexibility by tapping into [its configuration options][13]. That includes changing text colors, the order Newsboat sorts feeds, where it saves articles, the length of time Newsboat keeps articles, and more.
+
+Below are a few of the options I've added to my configuration file.
+
+#### Change Newsboat's default browser
+
+As I mentioned a few paragraphs back, Newsboat opens articles in your default graphical web browser. If you want to read feeds in a [text-only browser][14] like w3m or ELinks, add this to your Newsboat configuration file:
+
+
+```
+`browser "/path/to/browser %u"`
+```
+
+In my configuration file, I've set w3m up as my browser:
+
+
+```
+`browser "/usr/bin/w3m %u"`
+```
+
+![Newsboat with w3m][15]
+
+#### Remove read articles
+
+I like an uncluttered RSS feed. That means getting rid of articles I've already read. Add this setting to the configuration file to have Newsboat do that automatically:
+
+
+```
+`show-read-feeds no`
+```
+
+#### Refresh feeds at launch
+
+Life gets busy. Sometimes, I go a day or two without checking my RSS feeds. That means having to refresh them after I fire Newsboat up. Sure, I can press **r** or **R**, but why not have the application do it for me? I've added this setting to my configuration file to have Newsboat refresh all of my feeds when I launch it:
+
+
+```
+`refresh-on-startup yes`
+```
+
+If you have a lot of feeds, it can take a while to refresh them. I have around 80 feeds, and it takes over a minute to get new content from all of them.
+
+### Is that everything?
+
+Not even close. In addition to all of its configuration options, Newsboat also has a number of command-line switches you can use when you fire it up. Read more about them in the [documentation][16].
+
+On the surface, Newsboat is simple. But a lot of power and flexibility hides under its hood. That makes Newsboat an excellent RSS reader for anyone who needs a basic set of features or for someone who needs their RSS reader to do a whole lot more.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/2/newsboat
+
+作者:[Scott Nesbitt][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/scottnesbitt
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/CreativeCommons_ideas_520x292_1112JS.png?itok=otei0vKb (Boat on the ocean with Creative Commons sail)
+[2]: https://opensource.com/article/17/3/rss-feed-readers
+[3]: https://opensource.com/users/ksonney
+[4]: https://opensource.com/article/20/1/open-source-rss-feed-reader
+[5]: https://en.wikipedia.org/wiki/OPML
+[6]: https://opensource.com/sites/default/files/uploads/newsboat-urls-file.png (Newsboat urls file)
+[7]: https://opensource.com/sites/default/files/uploads/newsboat-reading.png (Newsboat reading)
+[8]: https://opensource.com/sites/default/files/uploads/newsboat-links.png (Hyperlinks in Newsboat)
+[9]: https://github.com/owncloudarchive/news
+[10]: https://github.com/nextcloud/news
+[11]: https://newsboat.org/releases/2.18/docs/newsboat.html#_newsboat_as_a_client_for_newsreading_services
+[12]: https://opensource.com/sites/default/files/uploads/newsboat-oldreader.png (Newsboat with The Old Reader)
+[13]: https://newsboat.org/releases/2.18/docs/newsboat.html#_example_configuration
+[14]: https://opensource.com/article/16/12/web-browsers-linux-command-line
+[15]: https://opensource.com/sites/default/files/uploads/newsboat-read-with-w3m.png (Newsboat with w3m)
+[16]: https://newsboat.org/releases/2.18/docs/newsboat.html
diff --git a/sources/tech/20200302 Using LibreOffice for your open source budgeting tool.md b/sources/tech/20200302 Using LibreOffice for your open source budgeting tool.md
new file mode 100644
index 0000000000..9d26ff39c7
--- /dev/null
+++ b/sources/tech/20200302 Using LibreOffice for your open source budgeting tool.md
@@ -0,0 +1,168 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using LibreOffice for your open source budgeting tool)
+[#]: via: (https://opensource.com/article/20/3/libreoffice-open-source-budget)
+[#]: author: (Jess Weichler https://opensource.com/users/cyanide-cupcake)
+
+Using LibreOffice for your open source budgeting tool
+======
+Figure out where your money is going with this LibreOffice Calc budget
+template.
+![scientific calculator][1]
+
+Budgets can be intimidating for beginners. It can feel overwhelming to think about money, much less about how to keep track of it. But it's important to know where your money is coming and going.
+
+In this article, I'll step through a sample budget by explaining the logic behind important money decisions as well as the formulas you need to automate the process. Fortunately, LibreOffice makes it easy for anyone to keep their yearly budget in check, even the math-averse.
+
+### Getting started
+
+Begin by downloading and installing [LibreOffice][2], if you don't already have it. Next, download my [LibreOffice Calc template][3], which you can use as a starting point to create your own budget to meet your spending and savings goals.
+
+It's important to interact with your spreadsheet frequently. You can input transactions as they happen, daily, or weekly. You even could save up your receipts to calculate all your expenses at the end of the month, but this can be a hard slog. You want budgeting to be as quick and easy as possible.
+
+### Categories
+
+The first step to creating a budget is to decide on the categories you want to track. These categories can be as simple or as complex as you like. Think about what is useful to your personal situation and financial goals. You can easily add or change categories as your needs change.
+
+The template has a number of example categories you can start with. There is no right or wrong way to choose categories; your budget has to work for you. Look through the list in Column A of the **Budget** tab and decide which ones to keep, which to delete, and any others you want to add. Then edit that list to align with your personal income and expense situation.
+
+#### Create category drop-down menus
+
+![Budget categories][4]
+
+The template uses a drop-down menu to make it easy to assign categories to income and expenses. You can view them on the **Monthly** sheets (accessed with the tabs at the bottom of the LibreOffice window). Click on a cell in Column C, and a drop-down arrow will appear on the right. Click the arrow, and you'll see the example categories. You may need to change some of them so that they will match the categories in your budget (Column A of the **Budget** tab).
+
+To add or remove categories from the dropdown menu, click on Column C in a Monthly sheet to select all **Category** cells. Then, in the main menu, select **Data** > **Validity**. This opens up a dialog box.
+
+In **Validity**, select the **Criteria** tab, then click on the arrow to the right of **Allow**, set it to **List**, and type the categories you want to use in the **Entries** box. Type one category per line. Make sure to use the exact same categories you used on the **Budget** sheet in Column A.
+
+### Estimating your budget
+
+Once you have defined your categories, it's time to estimate how much you expect to earn and spend. You can calculate these amounts monthly, yearly, or using a mix of the two.
+
+Your first year of budgeting estimates won't be perfect, and you may be surprised at how much or little you spend on certain categories. But doing this will help you get a realistic idea of where your money is going. You can make adjustments in your second year to create a more accurate budget based upon what you spend in year one.
+
+In Column B (**Monthly Estimate**) of the **Budget** tab, enter your anticipated _monthly_ income and expenses for each category (an exception is the **Charity** row, which is automatically calculated as a percentage of your income). For _annual_ expenses and income (e.g., taxes, insurance, tuition, etc.), enter them in Column P (**Yearly Estimate**).
+
+#### Calculating the annual cost of monthly expenses
+
+Most expenses occur monthly. To find the yearly cost of a monthly expense, multiply your monthly estimate by 12. You could do this manually for each category, but it is much easier to use formulas.
+
+Formulas are automated calculations that determine the value of a cell. Formulas do all the heavy lifting, so you don't have to do a lot of sums in your head.
+
+In the template, you can use the **Yearly Estimate** column to make an equation to annualize a monthly expense or income. In a cell in Column P, type this:
+
+
+```
+`=SUM(x*12)`
+```
+
+but change _x_ to the name of the **Monthly Estimate** cell you want to use. (For example, to calculate the annual cost of your phone service using the template, the formula would read **=SUM(B12*13)**.)
+
+#### Calculating the monthly cost of yearly expenses
+
+You may pay some expenses, such as car insurance, only once a year. You can either ignore these expenses in the monthly estimates or put money aside for them in your budget each month.
+
+If you want to do the latter, you need to divide your **Yearly Estimate** by 12 and put that amount into your monthly budget. To do so, place this equation in the appropriate cell in the **Monthly Estimate** column:
+
+
+```
+`=SUM(x/12)`
+```
+
+where _x_ is the corresponding **Yearly Estimate** cell on your spreadsheet (from Column P).
+
+#### Finding percentages
+
+If you want to donate or save a percentage of your income, there's a function for that, too!
+
+The common recommendation is to put aside 20% of your take-home pay for savings. While I don't focus on this too much, I do find it helpful to see if I'm meeting my savings goals from month to month.
+
+For instance, Row 32 of the **Budget** tab template uses this formula to calculate the 20% of your income that you should allocate to savings:
+
+
+```
+`=SUM(B2*0.2)`
+```
+
+This same method can be used if you give a percentage (e.g., 10%) of your income to charity (Row 21 of the template):
+
+
+```
+`=SUM(B2*-0.1)`
+```
+
+This formula uses a negative percentage because donating to charity is an expense.
+
+### Entering monthly income and expenses
+
+The template pulls data totals from the **Monthly** sheets (the tabs at the bottom of the spreadsheet) to populate Columns C through N on the **Budget** sheet.
+
+It's useful to place each month's transactions on separate sheets of your budget spreadsheet. By keeping your receipts from purchases and entering them into each month's sheet, you create a digital record of your money.
+
+Enter income as positive numbers and expenses as negative numbers. Select the appropriate category using the drop-down in the **Category** column.
+
+In LibreOffice, the **SUMIF** function can look at values in a specific column and extract only the ones that occur next to a specific word. My template uses a **SUMIF** formula to extract values based on the adjacent category in order to enter an amount in the correct cell on the **Budget** tab. For example, to enter January's internet expenses into the **Budget** spreadsheet, enter this formula in cell C12:
+
+
+```
+`=SUMIF(january.$C:$C,A12,january.$D:$D)`
+```
+
+This looks at January's Column C and, if it sees an entry that contains the word in A12 on the **Budget** tab (Internet), then it extracts the number from Column D on the **January** tab and enters that value into the cell that contains the formula on the **Budget** tab (C12).
+
+### Analyzing your budget data
+
+#### Adding a range of numbers to calculate YTD spending
+
+To see how much you have spent overall this year to date (YTD), select the cell where you want to display that data (in the template, it's cell O29, under the **YTD** column), and enter the following formula to total the range of numbers corresponding to your monthly **Total Expense**:
+
+
+```
+`=SUM(x:y)`
+```
+
+Instead of _x_ and _y_, enter the first cell and the last cell in the range. You can type them in manually, but it's easier and less error-prone to just click and drag from the first to last cell. LibreOffice does the calculation and enters the appropriate values.
+
+#### Seeing how you're doing on your budget
+
+A big part of budgeting is comparing your estimates to your actual income and expenses. In the template, this is the **Budget** tab's Column Q. This column subtracts the contents of each cell in Column O (**YTD**) from Column P (**Yearly Estimate**).
+
+
+```
+`=SUM(x-y)`
+```
+
+where _x_ and _y_ equal the corresponding cells from Column P and O. For example, using the template to calculate how much you've spent on Utilities compared to your budget, you would enter **=SUM(P11-O11)**.
+
+![Budget overview][5]
+
+### Tracking expenses
+
+Now that your yearly budget is set up, you are ready to start meeting your financial goals.
+
+It's important to look at your budget often—and it's equally important to do so without guilt. Think of this process as gathering data so that you can adjust your estimates for the next year. The primary goal of budgeting is to understand your own spending habits and refine either your expectations or your behavior so that you can plan better for how your income is used.
+
+Which open source tools and apps do you use to budget? Tell us in the comments!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/libreoffice-open-source-budget
+
+作者:[Jess Weichler][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/cyanide-cupcake
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calculator_money_currency_financial_tool.jpg?itok=2QMa1y8c (scientific calculator)
+[2]: https://www.libreoffice.org/download/download/
+[3]: https://opensource.com/sites/default/files/uploads/budget_template_0.ods
+[4]: https://opensource.com/sites/default/files/uploads/imagebudget_cat.png (Budget categories)
+[5]: https://opensource.com/sites/default/files/uploads/imagebudget_overview.png (Budget overview)
diff --git a/sources/tech/20200303 Getting started with lightweight alternatives to GNU Emacs.md b/sources/tech/20200303 Getting started with lightweight alternatives to GNU Emacs.md
new file mode 100644
index 0000000000..5f86c79b84
--- /dev/null
+++ b/sources/tech/20200303 Getting started with lightweight alternatives to GNU Emacs.md
@@ -0,0 +1,164 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting started with lightweight alternatives to GNU Emacs)
+[#]: via: (https://opensource.com/article/20/3/lightweight-emacs)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Getting started with lightweight alternatives to GNU Emacs
+======
+Slimmed-down (in size and features) alternatives allow you to take your
+text editor anywhere you go.
+![Text editor on a browser, in blue][1]
+
+I work on a lot of servers, and sometimes I find a host that hasn't installed [GNU Emacs][2]. There's usually a [GNU Nano][3] installation to keep me from resorting to [Vi][4], but I'm not used to Nano the way I am Emacs, and I inevitably run into complications when I try to save my document (**C-x** in Nano stands for Exit, and **C-s** locks Konsole).
+
+While it would be nice to have GNU Emacs available everywhere, it's a lot of program for making a simple update to a config file. My need for a small and lightweight emacs is what took me down the path of discovering MicroEmacs, Jove, and Zile—tiny, self-contained [emacsen][5] that you can put on a thumb drive, an SD card, and nearly any server, so you'll never be without an emacs editor.
+
+### Editing macros
+
+The term "emacs" is a somewhat generic term in the way that only open source produces, and a portmanteau. Before there was [GNU Emacs][6], there were collections of batch process scripts (called _macros_) that could perform common tasks for a user. For instance, if you often found yourself typing "teh" instead of "the," you could either go in and correct each one manually (no small feat when your editor can't even load the entire document into memory, as was often the case in the early 1980s), or you could invoke a macro to perform a quick swap of the "e" and "h."
+
+Eventually, these macros were bundled together into a package called editing macros, or EMACS for short. GNU Emacs is the most famous emacsen (yes, the -en suffix is used to describe many emacs, as in the word "oxen"), but it's not the only one. And it's certainly not the smallest. Quite the contrary, GNU Emacs is probably one of the largest.
+
+Fortunately, GNU Emacs is so popular that other emacs implementations tend to mimic most of the GNU version's basic controls. If you're looking for a basic, fast, and efficient editor that isn't Vim, you'll likely be happy with any of these options.
+
+### MicroEmacs
+
+![µemacs][7]
+
+[MicroEmacs][8], also known as uemacs (as in the Greek letter µ, which denotes "micro" in scientific notation), was written by Dave Conroy, but there's a long list of users who have cloned it and modified it. One user who maintains a personal version of µemacs is a programmer named Linus Torvalds, and his copy is available from his website, [kernel.org][9] (which also, incidentally, includes a small side project of his called [Linux][10]).
+
+#### Size
+
+It takes me five seconds to compile µemacs at the slowest setting I can impose on my computer, and the resulting binary is a mere 493KB. Admittedly, that's not literally "micro" compared to the typical size of a GNU Emacs download (1 millionth of 70MB is 70 bytes, by my calculation), but it's respectably small. For instance, it's easy enough to send it to yourself by email or over Signal, and certainly small enough to keep handy on every thumb drive or SD card you own.
+
+By default, Linus's version expects libcurses, but you can override this setting in the Makefile so that it uses libtermcap instead. The resulting binary is independent enough to run on most Linux boxes:
+
+
+```
+$ ldd em
+linux-vdso.so.1
+libtermcap.so.2 => /lib64/libtermcap.so.2
+libc.so.6 => /lib64/libc.so.6
+/lib64/ld-linux-x86-64.so.2
+```
+
+#### Features
+
+The [keyboard shortcuts][11] are just as you'd expect. You can open files and edit them without ever realizing you're not in GNU Emacs.
+
+Some advanced features are missing. For instance, there's no vertical buffer split, although there is a horizontal split. There's no eval command, so you won't use µemacs for Lisp programming.
+
+The search function is also a little different from what you may be used to: instead of **C-s**, it's **M-s**, which could make all the difference if your terminal emulator accepts **Ctrl+S** as a freeze command. The help page for µemacs is very complete, so use **M-x help** to get familiar with what it has available.
+
+#### License
+
+The license for µemacs is custom to the project with a non-commercial condition. You're free to share, use, and modify µemacs, but you can't do anything commercial with it.
+While not as liberal a policy as I typically prefer, it's a good-enough license for personal use; just don't build a business around it.
+
+### GNU Zile
+
+![GNU Zile][12]
+
+[GNU Zile][13] claims to be a development kit for text editors. It's meant as a framework to enable people to quickly develop their own custom text editor without having to reinvent common data structures. It's a great idea and probably very useful, but as I have no interest in making my own editor, I just use the example implementation that ships with its codebase as a pleasant, lightweight emacs.
+
+The build process for the example editor (supposedly called Zemacs, although the binary it renders is named zile) is the standard [Autotools][14] procedure:
+
+
+```
+$ ./configure
+$ make
+```
+
+#### Size
+
+Compiling it from source takes me a minute on one core or about 50 seconds on six cores (the configuration process is the long part). The binary produced in the end is 1.2MB, making this the heaviest of the lightweight emacsen I use, but compared to even GNU Emacs without X (which is 14MB on my system), it's relatively trivial.
+
+Of the lightweight emacsen I use, it's also the most complex. You can exclude some library links by disabling features during configuration, but here are the defaults:
+
+
+```
+$ ldd src/zile
+linux-vdso.so.1
+libacl.so.1 => /lib64/libacl.so.1
+libncurses.so.5 => /lib64/libncurses.so.5
+libgc.so.1 => /usr/lib64/libgc.so.1
+libc.so.6 => /lib64/libc.so.6
+libattr.so.1 => /lib64/libattr.so.1
+libdl.so.2 => /lib64/libdl.so.2
+libpthread.so.0 => /lib64/libpthread.so.0
+/lib64/ld-linux-x86-64.so.2
+```
+
+#### Features
+
+Zile acts a little more like GNU Emacs than µemacs or Jove, but it's still a minimal experience. But some little touches are refreshing: Tab completion happens in a buffer, you can run shell commands from the mini-buffer, and you have a good assortment of functions available. It's by no means a GNU Emacs replacement, though, and if you wander too far in search of advanced features, you'll find out why it's only 1.2MB.
+
+I've been unable to find in-application help files, and the man page bundled with it is minimal. However, if you're comfortable with Emacs, Zile is a good compromise between the full 14MB (or greater, if you're using a GUI) version and the extremely lightweight implementations.
+
+### Jove
+
+![Jove][15]
+
+[Jove][16] was my first tiny emacs and remains the smallest I've found yet. This was an easy discovery for me, as it ships with [Slackware][17] Linux and, with a surreptitious symlink, quickly became my personal replacement for the Vi binary. Jove is based on GNU Emacs, but the man page cautions that feature parity is by no means to be expected. I find Jove surprisingly feature-rich for such a small binary (in fact, this article was written in Jove version 4.17.06-9), but there's no question that renaming .emacs to .joverc does _not_ behave as you might hope.
+
+#### Size
+
+It takes me five seconds to compile Jove at the slowest setting (-j1) and about a second using all cores. The resulting binary, confusingly called jjove by default, is just 293KB.
+
+The Jove binary is independent enough to run on most Linux boxes:
+
+
+```
+$ ldd jjove
+linux-vdso.so.1
+libtermcap.so.2 => /lib64/libtermcap.so.2
+libc.so.6 => /lib64/libc.so.6
+/lib64/ld-linux-x86-64.so.2
+```
+
+#### Features
+
+Jove has good documentation in the form of a man page. You can also get a helpful listing of all available commands by typing **M-x ?** and using the Spacebar to scroll. If you're entirely new to emacs, you can run **teachjove** to learn Jove (and emacs, accordingly).
+
+Most common editing commands and keybindings work as expected. Some oddities exist; for example, there's no vertical split, and Tab completion for paths in the mini-buffer is non-existent. However, it's the smallest emacs I've found and yet has a full GNU Emacs feel to it.
+
+### Try Emacs
+
+If you've only ever tried GNU Emacs, then you might find that the world of emacsen is richer than you may have expected. There's a rich tradition behind emacs, and trying some of its variants, spin-offs, and alternate implementations is part of the joy of being comfortable with how emacsen work. Get to know emacs; carry a few builds around everywhere you go, and you'll never have to use a substandard editor again!
+
+GNU Emacs can be much more than just a text editor. Learn how to get started.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/lightweight-emacs
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
+[2]: https://www.gnu.org/software/emacs/
+[3]: https://www.nano-editor.org/
+[4]: https://opensource.com/article/19/3/getting-started-vim
+[5]: https://www.emacswiki.org/emacs/Emacsen
+[6]: https://opensource.com/article/20/2/who-cares-about-emacs
+[7]: https://opensource.com/sites/default/files/uploads/lightweight-emacs-uemacs.jpg (µemacs)
+[8]: https://en.wikipedia.org/wiki/MicroEMACS
+[9]: https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git
+[10]: https://opensource.com/tags/linux
+[11]: https://opensource.com/downloads/emacs-cheat-sheet
+[12]: https://opensource.com/sites/default/files/uploads/lightweight-emacs-zile.jpg (GNU Zile)
+[13]: https://www.gnu.org/software/zile/
+[14]: https://opensource.com/article/19/7/introduction-gnu-autotools
+[15]: https://opensource.com/sites/default/files/uploads/lightweight-emacs-jove.jpg (Jove)
+[16]: https://opensource.com/article/17/1/jove-lightweight-alternative-vim
+[17]: http://slackware.com
diff --git a/sources/tech/20200303 Watching activity on Linux with watch and tail commands.md b/sources/tech/20200303 Watching activity on Linux with watch and tail commands.md
new file mode 100644
index 0000000000..15780a5b34
--- /dev/null
+++ b/sources/tech/20200303 Watching activity on Linux with watch and tail commands.md
@@ -0,0 +1,148 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Watching activity on Linux with watch and tail commands)
+[#]: via: (https://www.networkworld.com/article/3529891/watching-activity-on-linux-with-watch-and-tail-commands.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+Watching activity on Linux with watch and tail commands
+======
+The watch and tail commands can help monitor activity on Linux systems. This post looks at some helpful ways to use these commands.
+Loops7 / Getty Images
+
+The **watch** and **tail** commands provide some interesting options for examining activity on a Linux system in an ongoing manner.
+
+That is, instead of just asking a question and getting an answer (like asking **who** and getting a list of currently logged in users), you can get **watch** to provide you with a display showing who is logged in along with updates as users come and go.
+
+[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
+
+With **tail**, you can display the bottoms of files and see content as it is added. This kind of monitoring is often very helpful and requires less effort than running commands periodically.
+
+### Using watch
+
+One of the simplest examples of using **watch** is to use the command **watch who**. You should see a list showing who is logged in along with when they logged in and where they logged in from. Notice that the default is to update the display every two seconds (top left) and that the date and time (upper right) updates itself at that interval. The list of users will grow and shrink as users log in and out.
+
+### $ watch who
+
+This command will dissplay a list of logins like this:
+
+```
+Every 2.0s: who dragonfly: Thu Feb 27 10:52:00 2020
+
+nemo pts/0 2020-02-27 08:07 (192.168.0.11)
+shs pts/1 2020-02-27 10:58 (192.168.0.5)
+```
+
+You can change the interval to get less frequent updates by adding a **-n** option (e.g., -n 10) to select a different number of seconds between updates.
+
+### $ watch -n 10 who
+
+The new interval will be displayed and the time shown will change less frequently, aligning itself with the selected interval.
+
+[][2]
+
+```
+Every 10.0s: who dragonfly: Thu Feb 27 11:05:47 2020
+
+nemo pts/0 2020-02-27 08:07 (192.168.0.11)
+shs pts/1 2020-02-27 10:58 (192.168.0.5)
+```
+
+If you prefer to see only the command's output and not the heading (the top 2 lines), you can omit those lines by adding the **-t** (no title) option.
+
+### $ watch -t who
+
+Your display will then look like this:
+
+```
+nemo pts/0 2020-02-27 08:07 (192.168.0.11)
+shs pts/1 2020-02-27 10:58 (192.168.0.5)
+```
+
+If every time the watched command runs, its output is the same, only the title line (if not omitted) will change. The rest of the displayed information will stay the same.
+
+If you want your **watch** command to exit as soon as the output of the command that it is watching changes, you can use a **-g** (think of this as the "go away") option. You might choose to do this if, for example, you are simply waiting for others to start logging into the system.
+
+You can also highlight changes in the displayed output using the **-d** (differences) option. The highlighting will only last for one interval (2 seconds by default), but can help to draw your attention to the changes.
+
+Here's a more complex example of using the **watch** command to display services that are listening for connections and the ports they are using. While the output isn't likely to change, it would alert you to any new service starting up or one going down.
+
+```
+$ watch 'sudo lsof -i -P -n | grep LISTEN'
+```
+
+Notice that the command being run needs to be enclosed in quotes to ensure that the **watch** command doesn't send its output to the grep command.
+
+Using the **watch -h** command will provide you with a list of the command's options.
+
+```
+$ watch -h
+
+Usage:
+ watch [options] command
+
+Options:
+ -b, --beep beep if command has a non-zero exit
+ -c, --color interpret ANSI color and style sequences
+ -d, --differences[=]
+ highlight changes between updates
+ -e, --errexit exit if command has a non-zero exit
+ -g, --chgexit exit when output from command changes
+ -n, --interval seconds to wait between updates
+ -p, --precise attempt run command in precise intervals
+ -t, --no-title turn off header
+ -x, --exec pass command to exec instead of "sh -c"
+
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+```
+
+### Using tail -f
+
+The **tail -f** command has something in common with **watch**. It will both display the bottom of a file and additional content as it is added. Instead of having to run a "tail" command again and again, you run one command and get a repeatedly updated view of its output. For example, you could watch a system log with a command like this:
+
+```
+$ tail -f /var/log/syslog
+```
+
+Some files, like **/var/log/wtmp**, don't lend themselves to this type of handling because they're not formatted as normal text files, but you could get a similar result by combining **watch** and **tail** like this:
+
+```
+watch 'who /var/log/wtmp | tail -20'
+```
+
+This command will display the most recent 5 logins regardless of how many of the users are still logged in. If another login occurs, a line will be added and the top line removed.
+
+```
+Every 60.0s: who /var/log/wtmp | tail -5 dragonfly: Thu Feb 27 12:46:07 2020
+
+shs pts/0 2020-02-27 08:07 (192.168.0.5)
+nemo pts/1 2020-02-27 08:26 (192.168.0.5)
+shs pts/1 2020-02-27 10:58 (192.168.0.5)
+nemo pts/1 2020-02-27 11:34 (192.168.0.5)
+dory pts/1 2020-02-27 12:14 (192.168.0.5)
+```
+
+Both the **watch** and **tail -f** commands can provide auto-updating views of information that you might at times want to monitor, making the task of monitoring quite a bit easier whether you're monitoring processes, logins or system resources.
+
+Join the Network World communities on [Facebook][3] and [LinkedIn][4] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3529891/watching-activity-on-linux-with-watch-and-tail-commands.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.networkworld.com/newsletters/signup.html
+[2]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
+[3]: https://www.facebook.com/NetworkWorld/
+[4]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200304 How service virtualization relates to test-driven development.md b/sources/tech/20200304 How service virtualization relates to test-driven development.md
new file mode 100644
index 0000000000..4ff4243603
--- /dev/null
+++ b/sources/tech/20200304 How service virtualization relates to test-driven development.md
@@ -0,0 +1,428 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How service virtualization relates to test-driven development)
+[#]: via: (https://opensource.com/article/20/3/service-virtualization-test-driven-development)
+[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
+
+How service virtualization relates to test-driven development
+======
+Mountebank simulates services you're dependent on so autonomous teams
+can continue development activities without having to wait on anyone.
+![Person using a laptop][1]
+
+The agile approach to software development relies on service virtualization to give each IT team autonomy. This approach removes blockages and allows autonomous teams to continue development activities without having to wait on anyone. That way, integration testing can commence as soon as teams start iterating/sprinting.
+
+### How automated services work
+
+Any automated service is available to consumers via a published endpoint. This means services can be automated only if they're made available online.
+
+Any consumer wishing to leverage available automated services must be capable of sending requests to that service's endpoint via an HTTP protocol. Some of those services will, upon receiving the request via the HTTP protocol, respond by simply sending back some data. Other services may respond to receiving a request via HTTP protocol by actually performing some work. For example, a service may create a resource (for example, create an order), update a resource (update an order), or delete a resource (cancel an order).
+
+All those activities get triggered via the HTTP protocol. In the simplest of cases, the action instigated by the service consumer is GET (e.g., HTTP GET). That request may arrive with some query values; those values will get used by the service to narrow down the search (such as "search for order number 12345 and return the data").
+
+In more elaborate cases, a request may arrive with the instruction to POST some values; a service will accept that request and expect some values to be associated with it. Those values are usually called the payload. When the service accepts an HTTP POST request containing the payload, it will attempt to process it. It may or may not succeed in processing it, but either way, it will respond to the service consumer with a status code and an optional status message. That way, service consumers will be notified of the success/failure of their request so that they can decide what the next step should be.
+
+### What is service virtualization?
+
+Now that we understand how automated services work, it should be easier to understand how to virtualize them. In a nutshell, it is possible to simulate any service that is published on a hosting site. Instead of sending HTTP requests directly to the service provider's endpoint, you can interject a fake, pretend service that simulates the behavior of the real service.
+
+From the service consumer's standpoint, it makes absolutely no difference whether it is interacting with a real or a fake service. The interaction remains identical.
+
+### Virtualize one service
+
+OK, enough talking, I'll roll up my sleeves and show how to do it in practical terms. Suppose your team is starting a new project and receives requirements in the form of a fully fleshed user story:
+
+#### Authenticate user
+
+_As a new app_
+_I want to authenticate the user_
+_Because we want to ensure proper security for the app_
+
+#### Acceptance criteria
+
+**Scenario #1:** _New app successfully authenticates the user_
+Given that the user has navigated to the login page
+And the user has submitted credentials
+When new app receives login request
+Then new app successfully authenticates the user
+And new app displays response message "User successfully logged in."
+
+**Scenario #2:** _New app cannot authenticate the user on the first attempt_
+Given that the user has navigated to the login page
+And the user has submitted credentials
+When new app receives login request
+Then new app fails to successfully authenticate the user
+And new app displays response message "Incorrect login. You have 2 more attempts left."
+
+**Scenario #3:** _New app cannot authenticate the user on the second attempt_
+Given that the user has navigated to the login page
+And the user has submitted credentials
+When new app receives login request
+Then new app fails to successfully authenticate the user
+And new app displays response message "Incorrect login. You have 1 more attempt left."
+
+**Scenario #4:** _New app cannot authenticate the user on the third attempt_
+Given that the user has navigated to the login page
+And the user has submitted credentials
+When new app receives login request
+Then new app fails to successfully authenticate the user
+And new app displays response message "Incorrect login. You have no more attempts left."
+
+The first thing to do when starting the work on this user story is to create the so-called "walking skeleton" (for this exercise, I will be using the standard **.Net Core** platform plus **xUnit.net** I discussed in my previous articles ([starting with this one][2] with [another example here][3]). Please refer to them for technical details on how to install, configure, and run the required tools.
+
+Create the walking skeleton infrastructure by opening the command line and typing:
+
+
+```
+`mkdir AuthenticateUser`
+```
+
+Then move inside the **AuthenticateUser** folder:
+
+
+```
+`cd AuthenticateUser`
+```
+
+And create a separate folder for tests:
+
+
+```
+`mkdir tests`
+```
+
+Move into the **tests** folder (**cd tests**) and initiate the **xUnit** framework:
+
+
+```
+`dotnet new xunit`
+```
+
+Now move one folder up (back to **AuthenticateUser**) and create the app folder:
+
+
+```
+mkdir app
+cd app
+```
+
+Create the scaffold necessary for C# code:
+
+
+```
+`dotnet new classlib`
+```
+
+The walking skeleton is now ready! Open the editor of your choice and start coding.
+
+### Write a failing test first
+
+In the spirit of TDD, start by writing the failing test (refer to the [previous article][4] to learn why is it important to see your test fail before attempting to make it pass):
+
+
+```
+using System;
+using Xunit;
+using app;
+
+namespace tests {
+ public class UnitTest1 {
+ Authenticate auth = [new][5] Authenticate();
+
+ [Fact]
+ public void SuccessLogin(){
+ var given = "credentials";
+ var expected = "Successful login.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ }
+}
+```
+
+This test states that if someone supplies some credentials (i.e., a secret username and password) to the **Login** method of the **Authenticate** component when it processes the request, it is expected to return the message "Successful login."
+
+Of course, this is functionality that does not exist yet—the instantiated **Authenticate** module in the **SuccessLogin()** module hasn't been written yet. So you might as well go ahead and take the first stab at writing the desired functionality. Create a new file (**Authenticate.cs**) in the **app** folder and add the following code:
+
+
+```
+using System;
+
+namespace app {
+ public class Authenticate {
+ public string Login(string credentials) {
+ return "Not implemented";
+ }
+ }
+}
+```
+
+Now, navigate to the **tests** folder and run:
+
+
+```
+`dotnet test`
+```
+
+![Output of dotnet.test][6]
+
+The test fails because it was expecting a "Successful login" output but instead got the "Not implemented" output.
+
+### Increasing complexity for day two operations
+
+Now that you have created the "happy path" expectation and made it fail, it is time to work on implementing the functionality that will make the failing test pass. The following day, you attend the standup and report that you have started on the "Authenticate user" story. You let the team know that you have created the first failing test for the "happy path," and today, the plan is to implement the code to make the failing test pass.
+
+You explain your intention to first create a **User** table containing the **username**, **password**, and other pertinent attributes. But the scrum master interrupts and explains that the **User** module is being handled by another team. It would be bad practice to duplicate the maintenance of users, as the information will quickly get out of sync. So instead of building the **User** module (which would include the authentication logic), you are to leverage the authentication services that the **User** team is working on.
+
+That's great news because it saves you the trouble of having to write a lot of code to implement the **User** processing. Emboldened, you enthusiastically announce that you will quickly cobble up a function that will take user credentials and send them to the service that the **User** team has built.
+
+Alas, your intentions get squashed again as you learn that the **User** team hasn't started building the **User authentication** service yet. They're still in the process of assigning user stories to the backlog. Disheartened, you resign to the fact that it will be at least a few days (if not weeks?) before you can start working on the **User authentication** story.
+
+The scrum master then says that there is no reason to wait for the **User authentication** service to be built and deployed to testing. You could start developing the authentication functionality right away. But how can you do that?
+
+The scrum master offers a simple suggestion: leverage service virtualization. Since all specifications for the **User** module have been solidified and signed off, you have a solid, non-volatile contract to build your solution against. The contract published by the **User** services team states that in order to authenticate a user, specific expectations must be fulfilled:
+
+ 1. A client wishing to authenticate a user should send an **HTTP POST** request to the endpoint .
+ 2. The **HTTP POST** sent to the above endpoint must have a **JSON** payload that contains the user credentials (i.e., username and password).
+ 3. Upon receiving the request, the service will attempt to log the user in. If the username and password match the information on record, the service will return an **HTTP** response containing status code 200 with the body of the response containing the message "User successfully logged in."
+
+
+
+So, now that you know the contract details, you can start building the solution. Here's the code that connects to the endpoint, sends the **HTTP POST** request, and receives the **HTTP** response:
+
+
+```
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace app {
+ public class Authenticate {
+ HttpClient client = [new][5] HttpClient();
+ string endPoint = "";
+
+ public string Login(string credentials) {
+ Task<string> response = CheckLogin(credentials);
+ return response.Result;
+ }
+
+ private async Task<string> CheckLogin(string credentials) {
+ var values = [new][5] Dictionary<string, string>{{"credentials", credentials}};
+ var content = [new][5] FormUrlEncodedContent(values);
+ var response = await client.PostAsync(endPoint, content);
+ return await response.Content.ReadAsStringAsync();
+ }
+ }
+}
+```
+
+This code won't work because does not exist (yet). Are you stuck now, waiting for the other team to eventually build and deploy that service?
+
+Not really. Service virtualization to rescue! Let's pretend that the service is already there and continue the development.
+
+### How to virtualize a service
+
+One way to virtualize the **User authentication** service would be to write a new app (the new API) and run it locally. This API will mirror the contract specified by the real **User authentication** API and will only return hard-coded stubbed data (it will be a fake service).
+
+Sounds like a good plan. Again, the team pushes back during the standup, questioning the need for writing, building, testing, and deploying a brand new app just to accomplish this fake functionality. It kind of wouldn't be worth the trouble because, by the time you deliver that new fake app, the other team would probably be ready with the real service.
+
+So you've reached an impasse. It looks like you are forced to wait on your dependency to materialize. You've failed to control your dependencies; you now have no recourse but to work in a sequential fashion.
+
+Not so fast! There is a great new tool called [mountebank][7] that is ideal for virtualizing any service. Using this tool, you can quickly stand up a local server that listens on a port you specify and takes orders. To make it simulate a service, you only have to tell it which port to listen to and which protocol to handle. The choice of protocols is:
+
+ * HTTP
+ * HTTPS
+ * SMTP
+ * TCP
+
+
+
+In this case, you need the HTTP protocol. First, install mountebank—if you have **npm** on your computer, you can simply type on the command line:
+
+
+```
+`npm install -g mountebank`
+```
+
+After it's installed, run mountebank by typing:
+
+
+```
+`mb`
+```
+
+At startup, mountebank will show:
+
+![mountebank startup][8]
+
+Now you're ready to virtualize an HTTP service. In this case, the **User authentication** service expects to receive an HTTP POST request; here is how the implemented code sends an HTTP POST request:
+
+
+```
+`var response = await client.PostAsync(endPoint, content);`
+```
+
+You now have to establish that **endPoint**. Ideally, all virtualized services should be propped in the **localhost** server to ensure quick execution of integration tests.
+
+To do that, you need to configure the **imposter**. In its bare-bones form, the **imposter** is a simple JSON collection of key-value pairs containing the definition of a port and a protocol:
+
+
+```
+{
+ "port": 3001,
+ "protocol": "http"
+}
+```
+
+This imposter is configured to handle the HTTP protocol and to listen to incoming requests on port 3001.
+
+Just listening to incoming HTTP requests on port 3001 is not going to do much. Once the request arrives at that port, mountebank needs to be told what to do with that request. In other words, you are virtualizing not only the availability of a service on a specific port but also the way that virtualized service is going to respond to the request.
+
+To accomplish that level of service virtualization, you need to tell mountebank how to configure stubs. Each stub consists of two components:
+
+ 1. A collection of predicates
+ 2. A collection of expected responses
+
+
+
+A predicate (sometimes called a matcher) narrows down the scope of the incoming request. For example, using the HTTP protocol, you can expect more than one type of method (e.g., GET, POST, PUT, DELETE, PATCH, etc.). In most service-virtualization scenarios, we are interested in simulating the behavior that is specific to a particular HTTP method. This scenario is about responding to the HTTP POST request, so you need to configure your stub to match on HTTP POST requests only:
+
+
+```
+{
+ "port": 3001,
+ "protocol": "http",
+ "stubs": [
+ {
+ "predicates": [
+ {
+ "equals": {
+ "method": "post"
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+This imposter defines one predicate that matches (using the keyword **equals**) on the HTTP POST request only.
+
+Now take a closer look at the **endPoint** value, as defined in the implemented code:
+
+
+```
+`string endPoint = "http://localhost:3001/api/v1/users/login";`
+```
+
+In addition to listening to port 3001 (as defined in ), the **endPoint** is more specific, in that it expects the incoming HTTP POST request to go to the /api/v1/users/login path. How do you tell mountebank to only match exactly on the /api/v1/users/login path? By adding the path key-value pair to the stub's predicate:
+
+
+```
+{
+ "port": 3001,
+ "protocol": "http",
+ "stubs": [
+ {
+ "predicates": [
+ {
+ "equals": {
+ "method": "post",
+ "path": "/api/v1/users/login"
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+This imposter now knows that HTTP requests arriving at port 3001 must be a POST method and must point at the /api/v1/users/login path. The only thing left to simulate is the expected HTTP response.
+
+Add the response to the JSON imposter:
+
+
+```
+{
+ "port": 3001,
+ "protocol": "http",
+ "stubs": [
+ {
+ "predicates": [
+ {
+ "equals": {
+ "method": "post",
+ "path": "/api/v1/users/login"
+ }
+ }
+ ],
+ "responses": [
+ {
+ "is": {
+ "statusCode": 200,
+ "body": "Successful login."
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+With mountebank imposters, you define responses as a collection of JSON key-value pairs. In most cases, it is sufficient to simply state that a response is a **statusCode** and a **body**. This case is simulating the "happy path" response that has the status code **OK (200)** and the body containing a simple message **Successful login** (as specified in the acceptance criteria).
+
+### How to run virtualized services?
+
+OK, now that you have virtualized the **User authentication** service (at least its "happy path"), how do you run it?
+
+Remember that you have already started mountebank, and it reported that it is running in memory as the domain. Mountebank is listening on port 2525 and taking orders.
+
+Great, now you have to tell mountebank that you have the imposter ready. How do you do that? Send an HTTP POST request to . The requests body must contain the JSON you created above. There are a few techniques available to send that request. If you're versed in [curl][9], using it to send HTTP POST requests would be the simplest, quickest way to stand up the imposter. But many people prefer a more user-friendly way to send the HTTP POST to mountebank.
+
+The easy way to do that is to use [Postman][10]. If you download and install Postman, you can point it at , select the POST method from the pulldown menu, and copy and paste the imposter JSON into the raw body.
+
+When you click Send, the imposter will be created, and you should get Status 201 (Created).
+
+![Postman output][11]
+
+Your virtualized service is now running! You can verify it by navigating to the **tests** folder and running the **dotnet test** command:
+
+![dotnet test output][12]
+
+### Conclusion
+
+This demo shows how easy it is to remove blockages and control dependencies by simulating services you're dependent on. Mountebank is a fantastic tool that easily and cheaply simulates all kinds of very elaborate, sophisticated services.
+
+In this installment, I just had time to illustrate how to virtualize a simple "happy path" service. If you go back to the actual user story, you will notice that its acceptance criteria contain several "less happy" paths (cases when someone is repeatedly trying to log in using invalid credentials). It's a bit trickier to properly virtualize and test those use cases, so I've left that exercise for the next installment in this series.
+
+How will you use service virtualization to solve your testing needs? I would love to hear about it in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/service-virtualization-test-driven-development
+
+作者:[Alex Bunardzic][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alex-bunardzic
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
+[2]: https://opensource.com/article/19/8/mutation-testing-evolution-tdd
+[3]: https://opensource.com/article/19/9/mutation-testing-example-tdd
+[4]: https://opensource.com/article/20/2/automate-unit-tests
+[5]: http://www.google.com/search?q=new+msdn.microsoft.com
+[6]: https://opensource.com/sites/default/files/uploads/dotnet-test.png (Output of dotnet.test)
+[7]: http://www.mbtest.org/
+[8]: https://opensource.com/sites/default/files/uploads/mountebank-startup.png (mountebank startup)
+[9]: https://curl.haxx.se/
+[10]: https://www.postman.com/
+[11]: https://opensource.com/sites/default/files/uploads/status-201.png (Postman output)
+[12]: https://opensource.com/sites/default/files/uploads/dotnet-test2.png (dotnet test output)
diff --git a/sources/tech/20200305 5 productivity apps for Linux.md b/sources/tech/20200305 5 productivity apps for Linux.md
new file mode 100644
index 0000000000..3e7423dc59
--- /dev/null
+++ b/sources/tech/20200305 5 productivity apps for Linux.md
@@ -0,0 +1,153 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (5 productivity apps for Linux)
+[#]: via: (https://opensource.com/article/20/3/productivity-apps-linux-elementary)
+[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
+
+5 productivity apps for Linux
+======
+Get organized and accomplish more with these five productivity apps for
+the Elementary Linux desktop.
+![Person drinking a hat drink at the computer][1]
+
+I've had a soft spot for [Elementary OS][2] since I first encountered it in 2013. A lot of that has to do with the distribution being very clean and simple.
+
+Since 2013, I've recommended Elementary to people who I've helped [transition to Linux][3] from other operating systems. Some have stuck with it. Some who moved on to other Linux distributions told me that Elementary helped smooth the transition and gave them more confidence using Linux.
+
+Like the distribution itself, many of the applications created specifically for Elementary OS are simple, clean, and useful. They can help boost your day-to-day productivity, too.
+
+### About "pay-what-you-want" apps
+
+Some apps in the Elementary AppCenter ask you to pay what you can. You're not obliged to pay to the full amount a developer asks for (or pay anything, for that matter). However, any money that changes hands goes to support the development of those apps.
+
+Three of the applications in this article—Quilter, Notes-up, and Envelope—are pay-what-you-want. If you find an app useful, I encourage you to send some money the developer's way.
+
+### Envelope
+
+Managing your budget should be simple. More than a few people, though, struggle with the task. That's where [Envelope][4] can help. While Envelope doesn't pack the features of something like [GnuCash][5], it's good enough for most of us.
+
+The app is built around the [envelope system][6] of personal and household budgeting. The first time you launch Envelope, you need to set up an account. You can do that manually, or you can import a [QIF][7] file containing financial information from another program.
+
+![Adding an account in Envelope][8]
+
+Either way, Envelope offers a set of categories (your envelopes). Add or delete categories as you see fit—for example, I don't own a car, so I deleted the Fuel category.
+
+From there, add transactions. Those can be your expenses or your income. Or both.
+
+![Entering a transaction in Envelope][9]
+
+Envelope gives you an overview of your spending and income. To get a more focused view of your budget, you can report on the current or previous month or a specific range of dates.
+
+### Notes-Up
+
+[Notes-Up][10]'s look and feel are reminiscent of note-taking tools like [Standard Notes][11], Simplenote, and the macOS Notes app. If you use any of them, switching to Notes-Up will be smooth and painless. Regardless, Notes-Up is easy to learn and use.
+
+![Notes-Up][12]
+
+Create a note and start typing. Notes-Up supports Markdown, making it easy to add formatting to your notes.
+
+![Taking notes in Notes-Up][13]
+
+If your Markdown is rusty, you can click the buttons on the toolbar to add formatting like lists; bold, italics, and strikethrough; code blocks; images; and more. You can also export your notes as PDF or Markdown files.
+
+Use Notes-Up for a while, and you'll wind up with a long list of notes. Organize them using _notebooks_. You can, for example, create personal, school, and work notebooks. On top of that, Notes-Up enables you to create sub-notebooks. Under my notebook for Opensource.com, for example, I have sub-notebooks for articles and the news roundups I curate.
+
+Notebooks not your thing? Then use tags to add keywords to your notes to make them easier to sort.
+
+### Yishu
+
+I do as much of my work as I can in [plain text][14]. That includes my task list. For that, I turn to a handy command-line application called [Todo.txt][15].
+
+If you aren't comfortable working at the command line, then [Yishu][16] is for you. It has Todo.txt's key features but graphically on the desktop.
+
+![Yishu][17]
+
+When you first fire up Yishu, it asks you to open an existing Todo.txt file. If you have one, open it. Otherwise, create a task. That also creates a new file for your tasks.
+
+![Adding a task in Yishu][18]
+
+Your options are limited: a description of the task and a priority. You can also add a due date in the format _YYYY-MM-DD_—for example, _2020-02-17_.
+
+When you click **OK**, Yishu saves the file Todo.txt to your **/home** folder. That might not be where you want to store your tasks. You can tell Yishu to use another folder in its preferences.
+
+### Reminduck
+
+Chances are, your notifications and reminders are jarring. A piercing buzz, an annoying beep, a text box that appears when you least expect it. Why not add a bit of [calm][19] and a bit of whimsy to your reminders—with a duck?
+
+That's the idea behind [Reminduck][20]. It's a simple and fun way to tell yourself it's time to do, well, anything.
+
+Fire up the app and create a reminder. You can add a description, date, and time for the reminder to appear, and you can set it to repeat. Reminders can repeat after a number of minutes that you set or at specific times every day, week, or month.
+
+![Reminduck][21]
+
+You can set up more than one reminder. Reminduck organizes your reminders, and you can edit or delete them.
+
+![Reminduck reminders][22]
+
+When the reminder is triggered, a little message pops out of the notification area on the desktop along with a soft alert and an icon of a smiling duck.
+
+![Reminduck notification][23]
+
+### Quilter
+
+It's easy enough to write with [Markdown][24] in a plain old text editor. Some folks, though, prefer to work with a dedicated Markdown editor. On the Elementary OS desktop, one option is [Quilter][25].
+
+![Quilter][26]
+
+Quilter is pretty basic. There's no toolbar to insert formatting; you have to add Markdown by hand. On the other hand, Quilter displays a running word count and an estimate of how long it will take to read what you're writing.
+
+![Quilter][27]
+
+The editor's options are few. There's a preview mode, and you can export your documents to PDF or HTML. The result of an export has the same look as a preview. That's not a bad thing.
+
+Quilter's other options include the ability to change the line spacing and margins, set the editor's font, as well as enable syntax highlighting and spell checking. It also has a mode that you can use to focus on a single line or a single paragraph while you're writing.
+
+### Final thoughts
+
+Sometimes, the best tools to boost your productivity are simple ones. Applications like the five above focus on doing one thing and doing it well.
+
+Envelope, Notes-Up, Yishu, Reminduck, and Quilter won't appeal to everyone. But if you use Elementary OS, give them a try. They can help you keep on track and do what you need to do.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/productivity-apps-linux-elementary
+
+作者:[Scott Nesbitt][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/scottnesbitt
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
+[2]: https://elementary.io
+[3]: https://opensource.com/article/18/12/help-non-techies
+[4]: https://nlaplante.github.io/envelope/
+[5]: https://opensource.com/article/20/2/gnucash
+[6]: https://en.wikipedia.org/wiki/Envelope_system
+[7]: https://en.wikipedia.org/wiki/Quicken_Interchange_Format
+[8]: https://opensource.com/sites/default/files/uploads/envelope-add-account.png (Adding an account in Envelope)
+[9]: https://opensource.com/sites/default/files/uploads/envelope-entering-transaction.png (Entering a transaction in Envelope)
+[10]: https://appcenter.elementary.io/com.github.philip-scott.notes-up/
+[11]: https://opensource.com/article/18/12/taking-notes-standard-notes
+[12]: https://opensource.com/sites/default/files/uploads/notes-up-main-window.png (Notes-Up)
+[13]: https://opensource.com/sites/default/files/uploads/notes-up-taking-note.png (Taking notes in Notes-Up)
+[14]: https://plaintextproject.online
+[15]: https://opensource.com/article/20/1/open-source-to-do-list
+[16]: https://appcenter.elementary.io/com.github.lainsce.yishu/
+[17]: https://opensource.com/sites/default/files/uploads/yishu-task-list.png (Yishu)
+[18]: https://opensource.com/sites/default/files/uploads/yishu-add-task.png (Adding a task in Yishu)
+[19]: https://weeklymusings.net/weekly-musings-025
+[20]: https://appcenter.elementary.io/com.github.matfantinel.reminduck/
+[21]: https://opensource.com/sites/default/files/uploads/reminduck.png (Reminduck)
+[22]: https://opensource.com/sites/default/files/uploads/remiunduck-reminders-list.png (Reminduck reminders)
+[23]: https://opensource.com/sites/default/files/uploads/reminduck-notification.png (Reminduck notification)
+[24]: https://opensource.com/article/19/8/markdown-beginners-cheat-sheet
+[25]: https://appcenter.elementary.io/com.github.lainsce.quilter/
+[26]: https://opensource.com/sites/default/files/uploads/quilter.png (Quilter)
+[27]: https://opensource.com/sites/default/files/uploads/quilter-editing.png (Quilter)
diff --git a/sources/tech/20200307 Compose music as code using Sonic Pi.md b/sources/tech/20200307 Compose music as code using Sonic Pi.md
new file mode 100644
index 0000000000..6944a5f6ea
--- /dev/null
+++ b/sources/tech/20200307 Compose music as code using Sonic Pi.md
@@ -0,0 +1,130 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Compose music as code using Sonic Pi)
+[#]: via: (https://opensource.com/article/20/3/sonic-pi)
+[#]: author: (Matt Bargenquast https://opensource.com/users/mbargenquast)
+
+Compose music as code using Sonic Pi
+======
+There's no need for instrumental mastery with this accessible open
+source program that can turn you into a musical virtuoso.
+![Bird singing and music notes][1]
+
+Maybe you're like me, and you learned a musical instrument when you were in school. For me, it was the piano, and later, the viola. However, I've always held that, as my childhood interests shifted towards computers and coding, I subsequently neglected my music practice. I do wonder what I would have done if I'd had something like Sonic Pi when I was younger. Sonic Pi is an open source program that lets you compose and perform music through code itself. It's the perfect marriage of those two worlds.
+
+Opensource.com is no stranger to Sonic Pi—we [featured an interview][2] with the creator, Dr. Sam Aaron, back in 2015. Since that time, a lot has changed, and Sonic Pi has grown substantially in many ways. It's reached a major new version milestone, with the long-awaited v3.2 release made publically available on February 28, 2020. A growing community of developers is actively contributing to its [GitHub project][3], while an equally thriving community of composers shares ideas and support in the [official forums][4]. The project is now also financially assisted through a [Patreon campaign][5], and Sam himself has been spreading the word of Sonic Pi through schools, conferences, and workshops worldwide.
+
+What really shines about Sonic Pi is its approachability. Releases are available for many major flavors of OS, including Windows, macOS, Linux, and of course, the Raspberry Pi itself. In fact, getting started with Sonic Pi on a Raspberry Pi couldn't be simpler; it comes pre-installed with [Raspbian][6], so if you have an existing Raspbian-based setup, you'll find it situated in the programming menu.
+
+Upon loading Sonic Pi for the first time, you'll be greeted with a simple interface with two main areas: an editor in which to write your code, and a section devoted to Sonic Pi's expansive tutorial. For newcomers, the tutorial is an essential resource for learning the basics, featuring accompanying music programs to reinforce each concept being taught.
+
+If you're following along, let's code ourselves a simple bit of music and explore the potential of live-coding music. Type or paste the following code into the Sonic Pi editor:
+
+
+```
+live_loop :beat do
+ sample :drum_heavy_kick
+ sleep 1
+end
+```
+
+Even if you're a Sonic Pi novice, many coders may immediately understand what's going on here. We're playing a drum kick sample, sleeping for a second, and then repeating. Click the Run button or press ALT+R (meta+R on macOS), and you should hear it begin to play.
+
+This isn't a very exciting song yet, so let's liven it up with a snare playing on the off-beat. Replace the existing code with the block below and Run again. You can leave the existing beat playing while you do this; you'll notice that your changes will be applied naturally, in time with the beat:
+
+
+```
+live_loop :beat do
+ sample :drum_heavy_kick
+ sleep 0.5
+ sample :drum_snare_soft
+ sleep 0.5
+end
+```
+
+While we're at it, let's add a hi-hat right before every fourth beat, just to make things a little interesting. Add this new block below our existing one and Run again:
+
+
+```
+live_loop :hihat do
+ sleep 3.9
+ sample :drum_cymbal_closed
+ sleep 0.1
+end
+```
+
+We've got our beat going now, so let's add a bassline! Sonic Pi comes with a variety of synths built-in, along with effects filters such as reverb and distortion. We'll use a combination of the "dsaw" and "tech_saw" synths to give it an electronic retro-synth feel. Add the block below to your existing program, Run, and have a listen:
+
+
+```
+live_loop :bass do
+ use_synth :dsaw
+ play :a2, attack: 1, release: 2, amp: 0.3
+ sleep 2.5
+ use_synth :tech_saws
+ play :a1, attack: 1, release: 1.5, amp: 0.8
+ sleep 1.5
+end
+```
+
+You'll note above that we have full control over the [ADSR][7] envelope when playing notes, so we can decide when each sound should peak and fade.
+
+Lastly, let's add a lead synth and try out one of those effects features known as the "slicer." To spice things up, we'll also introduce an element of pseudo-randomness by letting Sonic Pi pick from a series of potential chords. This is where some of the fun improvisation and "happy accidents" can begin to occur. Add the block below to your existing program and Run:
+
+
+```
+live_loop :lead do
+ with_fx :slicer do
+ chords = [(chord :A4, :minor7), (chord :A4, :minor), (chord :D4, :minor7), (chord :F4, :major7)]
+ use_synth :blade
+ play chords.choose, attack: 1, release: 2, amp: 1
+ sleep 2
+ end
+end
+```
+
+Great! Now, we're certainly not going to be competing with Daft Punk any time soon, but hopefully, through this process, you've seen how we can go from a bare beat to something much bigger, in real-time, by adding some simple morsels of code. It is well worth watching one of Sam Aaron's [live coding performances][8] on YouTube for a demonstration of how creative and adaptive Sonic Pi can let you be.
+
+![Sonic Pi composition example][9]
+
+Our finished piece, in full
+
+If you've ever wanted to learn a musical instrument, but felt held back by thoughts like "I don't have rhythm" or "my hands aren't nimble enough," Sonic Pi is a versatile instrument for which none of those things matter. All you need are the ideas, the inspiration, and an inexpensive computer such as the humble Raspberry Pi. The rest is at your fingertips—literally!
+
+Here are a few handy links to get you started:
+
+ * The Official Sonic Pi [website][10] and [tutorial][11]
+ * [Getting Started with Sonic Pi][12] ([projects.raspberrypi.org][13])
+ * Sonic Pi [Github project][3]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/sonic-pi
+
+作者:[Matt Bargenquast][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mbargenquast
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/music-birds-recording-520.png?itok=UoM7brl0 (Bird singing and music notes)
+[2]: https://opensource.com/life/15/10/interview-sam-aaron-sonic-pi
+[3]: https://github.com/samaaron/sonic-pi/
+[4]: https://in-thread.sonic-pi.net/
+[5]: https://www.patreon.com/samaaron
+[6]: https://www.raspberrypi.org/downloads/raspbian/
+[7]: https://en.wikipedia.org/wiki/Envelope_(music)
+[8]: https://www.youtube.com/watch?v=JEHpS1aTKp0
+[9]: https://opensource.com/sites/default/files/uploads/sonicpi.png (Sonic Pi composition example)
+[10]: https://sonic-pi.net/
+[11]: https://sonic-pi.net/tutorial.html
+[12]: https://projects.raspberrypi.org/en/projects/getting-started-with-sonic-pi
+[13]: http://projects.raspberrypi.org
diff --git a/sources/tech/20200309 Level up your use of Helm on Kubernetes with Charts.md b/sources/tech/20200309 Level up your use of Helm on Kubernetes with Charts.md
new file mode 100644
index 0000000000..9a08bdb973
--- /dev/null
+++ b/sources/tech/20200309 Level up your use of Helm on Kubernetes with Charts.md
@@ -0,0 +1,288 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Level up your use of Helm on Kubernetes with Charts)
+[#]: via: (https://opensource.com/article/20/3/helm-kubernetes-charts)
+[#]: author: (Jessica Cherry https://opensource.com/users/jrepka)
+
+Level up your use of Helm on Kubernetes with Charts
+======
+Configuring known apps using the Helm package manager.
+![Ships at sea on the web][1]
+
+Applications are complex collections of code and configuration that have a lot of nuance to how they are installed. Like all open source software, they can be installed from source code, but most of the time users want to install something simply and consistently. That’s why package managers exist in nearly every operating system, which manages the installation process.
+
+Similarly, Kubernetes depends on package management to simplify the installation process. In this article, we’ll be using the Helm package manager and its concept of stable charts to create a small application.
+
+### What is Helm package manager?
+
+[Helm][2] is a package manager for applications to be deployed to and run on Kubernetes. It is maintained by the [Cloud Native Computing Foundation][3] (CNCF) with collaboration with the largest companies using Kubernetes. Helm can be used as a command-line utility, which [I cover how to use here][4].
+
+#### Installing Helm
+
+Installing Helm is quick and easy for Linux and macOS. There are two ways to do this, you can go to the release [page][5], download your preferred version, untar the file, and move the Helm executable to your** /usr/local/bin** or your **/usr/bin** whichever you are using.
+
+Alternatively, you can use your operating system package manage (**dnf**, **snap**, **brew**, or otherwise) to install it. There are instructions on how to install on each OS on this [GitHub page][6].
+
+### What are Helm Charts?
+
+We want to be able to repeatably install applications, but also to customize them to our environment. That’s where Helm Charts comes into play. Helm coordinates the deployment of applications using standardized templates called Charts. Charts are used to define, install, and upgrade your applications at any level of complexity.
+
+> A _Chart_ is a Helm package. It contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. Think of it like the Kubernetes equivalent of a Homebrew formula, an Apt dpkg, or a Yum RPM file.
+>
+> [Using Helm][7]
+
+Charts are quick to create, and I find them straightforward to maintain. If you have one that is accessible from a public version control site, you can publish it to the [stable repository][8] to give it greater visibility. In order for a Chart to be added to stable, it must meet a number of [technical requirements][9]. In the end, if it is considered properly maintained by the Helm maintain, it can then be published to [Helm Hub][10].
+
+Since we want to use the community-curated stable charts, we will make that easier by adding a shortcut:
+
+
+```
+$ helm repo add stable
+"stable" has been added to your repositories
+```
+
+### Running our first Helm Chart
+
+Since I’ve already covered the basic Helm usage in [this article][11], I’ll focus on how to edit and use charts in this article. To follow along, you’ll need Helm installed and access to some Kubernetes environment, like minikube (which you can walk through [here][12] or [here][13]).
+
+Starting I will be picking one chart. Usually, in my article I use Jenkins as my example, and I would gladly do this if the chart wasn’t really complex. This time I’ll be using a basic chart and will be creating a small wiki, using [mediawiki and its chart][14].
+
+So how do I get this chart? Helm makes that as easy as a pull.
+
+By default, charts are compressed in a .tgz file, but we can unpack that file to customize our wiki by using the **\--untar** flag.
+
+
+```
+$ helm pull stable/mediawiki --untar
+$ ls
+mediawiki/
+$ cd mediawiki/
+$ ls
+Chart.yaml README.md requirements.lock templates/
+OWNERS charts/ requirements.yaml values.yaml
+```
+
+Now that we have this we can begin customizing the chart.
+
+### Editing your Helm Chart
+
+When the file was untared there was a massive amount of files that came out. While it does look frightening, there really is only one file we should be working with and that's the **values.yaml** file.
+
+Everything that was unpacked was a list of template files that has all the information for the basic application configurations. All the template files actually depend on what is configured in the values.yaml file. Most of these templates and chart files actually are for creating service accounts in the cluster and the various sets of required application configurations that would usually be put together if you were to build this application on a regular server.
+
+But on to the values.yaml file and what we should be changing in it. Open it in your favorite text editor or IDE. We see a [YAML][15] file with a ton of configuration. If we zoom in just on the container image file, we see its repository, registry, and tags amongst other details.
+
+
+```
+## Bitnami DokuWiki image version
+## ref:
+##
+image:
+ registry: docker.io
+ repository: bitnami/mediawiki
+ tag: 1.34.0-debian-10-r31
+ ## Specify a imagePullPolicy
+ ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
+ ## ref:
+ ##
+ pullPolicy: IfNotPresent
+ ## Optionally specify an array of imagePullSecrets.
+ ## Secrets must be manually created in the namespace.
+ ## ref:
+ ##
+ # pullSecrets:
+ # - myRegistryKeySecretName
+```
+
+As you can see in the file each configuration for the values is well-defined. Our pull policy is set to **IfNotPresent**. This means if I run a **helm pull** command, it will not overwrite my existing version. If it’s set to always, the image will default to the latest version of the image on every pull. I’ll be using the default in this case, as in the past I have run into images being broken if it goes to the latest version without me expecting it (remember to version control your software, folks).
+
+### Customizing our Helm Chart
+
+So let’s configure this values file with some basic changes and make it our own. I’ll be changing some naming conventions, the wiki username, and the mediawiki site name. _Note: This is another snippet from values.yaml. All of this customization happens in that one file._
+
+
+```
+## User of the application
+## ref:
+##
+mediawikiUser: cherrybomb
+
+## Application password
+## Defaults to a random 10-character alphanumeric string if not set
+## ref:
+##
+# mediawikiPassword:
+
+## Admin email
+## ref:
+##
+mediawikiEmail: [root@example.com][16]
+
+## Name for the wiki
+## ref:
+##
+mediawikiName: Jess's Home of Helm
+```
+
+After this, I’ll make some small modifications to our database name and user account. I changed the defaults to "jess" so you can see where changes were made.
+
+
+```
+externalDatabase:
+ ## Database host
+ host:
+
+ ## Database port
+ port: 3306
+
+ ## Database user
+ user: jess_mediawiki
+
+ ## Database password
+ password:
+
+ ## Database name
+ database: jess_mediawiki
+
+##
+## MariaDB chart configuration
+##
+##
+##
+mariadb:
+ ## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters
+ enabled: true
+ ## Disable MariaDB replication
+ replication:
+ enabled: false
+
+ ## Create a database and a database user
+ ## ref:
+ ##
+ db:
+ name: jess_mediawiki
+ user: jess_mediawiki
+```
+
+And finally, I’ll be adding some ports in our load balancer to allow traffic from the local host. I'm running on minikube and find the **LoadBalancer** option works well.
+
+
+```
+service:
+ ## Kubernetes svc type
+ ## For minikube, set this to NodePort, elsewhere use LoadBalancer
+ ##
+ type: LoadBalancer
+ ## Use serviceLoadBalancerIP to request a specific static IP,
+ ## otherwise leave blank
+ ##
+ # loadBalancerIP:
+ # HTTP Port
+ port: 80
+ # HTTPS Port
+ ## Set this to any value (recommended: 443) to enable the https service port
+ # httpsPort: 443
+ ## Use nodePorts to requets some specific ports when usin NodePort
+ ## nodePorts:
+ ## http: <to set explicitly, choose port between 30000-32767>
+ ## https: <to set explicitly, choose port between 30000-32767>
+ ##
+ # nodePorts:
+ # http: "30000"
+ # https: "30001"
+ ## Enable client source IP preservation
+ ## ref
+ ##
+ externalTrafficPolicy: Cluster
+```
+
+Now that we have made the configurations to allow traffic and create the database, we know that we can go ahead and deploy our chart.
+
+### Deploy and enjoy!
+
+Now that we have our custom version of the wiki, it's time to create a deployment. Before we get into that, let’s first confirm that nothing else is installed with Helm, to make sure my cluster has available resources to run our wiki.
+
+
+```
+$ helm ls
+NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
+```
+
+There are no other deployments through Helm right now, so let's proceed with ours.
+
+
+```
+$ helm install jesswiki -f values.yaml stable/mediawiki
+NAME: jesswiki
+LAST DEPLOYED: Thu Mar 5 12:35:31 2020
+NAMESPACE: default
+STATUS: deployed
+REVISION: 2
+NOTES:
+1\. Get the MediaWiki URL by running:
+
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ Watch the status with: 'kubectl get svc --namespace default -w jesswiki-mediawiki'
+
+ export SERVICE_IP=$(kubectl get svc --namespace default jesswiki-mediawiki --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
+ echo "Mediawiki URL: http://$SERVICE_IP/"
+
+2\. Get your MediaWiki login credentials by running:
+
+ echo Username: user
+ echo Password: $(kubectl get secret --namespace default jesswiki-mediawiki -o jsonpath="{.data.mediawiki-password}" | base64 --decode)
+$
+```
+
+Perfect! Now we will navigate to the wiki, which is accessible at the cluster IP address. To confirm that address:
+
+
+```
+kubectl get svc --namespace default -w jesswiki-mediawiki
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+jesswiki-mediawiki LoadBalancer 10.103.180.70 <pending> 80:30220/TCP 17s
+```
+
+Now that we have the IP, we go ahead and check to see if it’s up:
+
+![A working wiki installed through helm charts][17]
+
+Now we have our new wiki up and running, and we can enjoy our new application with our personal edits. Use the command from the output above to get the password and start to fill in your wiki.
+
+### Conclusion
+
+Helm is a powerful package manager that makes installing and uninstalling applications on top of Kubernetes as simple as a single command. Charts add to the experience by giving us curated and tested templates to install applications with our unique customizations. Keep exploring what Helm and Charts have to offer and let me know what you do with them in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/helm-kubernetes-charts
+
+作者:[Jessica Cherry][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jrepka
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/kubernetes_containers_ship_lead.png?itok=9EUnSwci (Ships at sea on the web)
+[2]: https://www.google.com/url?q=https://helm.sh/&sa=D&ust=1583425787800000
+[3]: https://www.google.com/url?q=https://www.cncf.io/&sa=D&ust=1583425787800000
+[4]: https://www.google.com/url?q=https://opensource.com/article/20/2/kubectl-helm-commands&sa=D&ust=1583425787801000
+[5]: https://www.google.com/url?q=https://github.com/helm/helm/releases/tag/v3.1.1&sa=D&ust=1583425787801000
+[6]: https://www.google.com/url?q=https://github.com/helm/helm&sa=D&ust=1583425787802000
+[7]: https://helm.sh/docs/intro/using_helm/
+[8]: https://www.google.com/url?q=https://github.com/helm/charts&sa=D&ust=1583425787803000
+[9]: https://github.com/helm/charts/blob/master/CONTRIBUTING.md#technical-requirements
+[10]: https://www.google.com/url?q=https://hub.helm.sh/&sa=D&ust=1583425787803000
+[11]: https://www.google.com/url?q=https://opensource.com/article/20/2/kubectl-helm-commands&sa=D&ust=1583425787803000
+[12]: https://www.google.com/url?q=https://opensource.com/article/18/10/getting-started-minikube&sa=D&ust=1583425787804000
+[13]: https://www.google.com/url?q=https://opensource.com/article/19/7/security-scanning-your-devops-pipeline&sa=D&ust=1583425787804000
+[14]: https://www.google.com/url?q=https://github.com/helm/charts/tree/master/stable/mediawiki&sa=D&ust=1583425787805000
+[15]: https://en.wikipedia.org/wiki/YAML
+[16]: mailto:root@example.com
+[17]: https://opensource.com/sites/default/files/uploads/lookitworked.png (A working wiki installed through helm charts)
diff --git a/sources/tech/20200311 Using the Quarkus Framework on Fedora Silverblue - Just a Quick Look.md b/sources/tech/20200311 Using the Quarkus Framework on Fedora Silverblue - Just a Quick Look.md
new file mode 100644
index 0000000000..1d72cd1d03
--- /dev/null
+++ b/sources/tech/20200311 Using the Quarkus Framework on Fedora Silverblue - Just a Quick Look.md
@@ -0,0 +1,209 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using the Quarkus Framework on Fedora Silverblue – Just a Quick Look)
+[#]: via: (https://fedoramagazine.org/using-the-quarkus-framework-on-fedora-silverblue-just-a-quick-look/)
+[#]: author: (Stephen Snow https://fedoramagazine.org/author/jakfrost/)
+
+Using the Quarkus Framework on Fedora Silverblue – Just a Quick Look
+======
+
+![Using the Quarkus Framework on Fedora Silverblue – Just a Quick Look][1]
+
+[Quarkus][2] is a framework for Java development that is described on their web site as:
+
+> A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards
+>
+> – Feb. 5, 2020
+
+Silverblue — a Fedora Workstation variant with a container based workflow central to its functionality — should be an ideal host system for the Quarkus framework.
+
+There are currently two ways to use Quarkus with Silverblue. It can be run in a pet container such as Toolbox/Coretoolbox. Or it can be run directly in a terminal emulator. This article will focus on the latter method.
+
+### Why Quarkus
+
+[According to Quarkus.io][3]: “Quarkus has been designed around a containers first philosophy. What this means in real terms is that Quarkus is optimized for low memory usage and fast startup times.” To achieve this, they employ first class support for Graal/Substrate VM, build time Metadata processing, reduction in reflection usage, and native image preboot. For details about why this matters, read [Container First][3] at Quarkus.
+
+### Prerequisites
+
+A few prerequisites will need to configured before you can start using Quarkus. First, you need an IDE of your choice. Any of the popular ones will do. VIM or Emacs will work as well. The Quarkus site provides full details on how to set up the three major Java IDE’s (Eclipse, Intellij Idea, and Apache Netbeans). You will need a version of JDK installed. JDK 8, JDK 11 or any distribution of OpenJDK is fine. GrallVM 19.2.1 or 19.3.1 is needed for compiling down to native. You will also need Apache Maven 3.53+ or Gradle. This article will use Maven because that is what the author is more familiar with. Use the following command to layer Java 11 OpenJDK and Maven onto Silverblue:
+
+```
+$ rpm-ostree install java-11-openjdk* maven
+```
+
+Alternatively, you can download your favorite version of Java and install it directly in your home directory.
+
+After rebooting, configure your _JAVA_HOME_ and _PATH_ environment variables to reference the new applications. Next, go to the [GraalVM download page][4], and get GraalVM version 19.2.1 or version 19.3.1 for Java 11 OpenJDK. Install Graal as per the instructions provided. Basically, copy and decompress the archive into a directory under your home directory, then modify the _PATH_ environment variable to include Graal. You use it as you would any JDK. So you can set it up as a platform in the IDE of your choice. Now is the time to setup the native image if you are going to use one. For more details on setting up your system to use Quarkus and the Quarkus native image, check out their [Getting Started tutorial][5]. With these parts installed and the environment setup, you can now try out Quarkus.
+
+### Bootstrapping
+
+Quarkus recommends you create a project using the bootstrapping method. Below are some example commands entered into a terminal emulator in the Gnome shell on Silverblue.
+
+```
+$ mvn io.quarkus:quarkus-maven-plugin:1.2.1.Final:create \
+ -DprojectGroupId=org.jakfrost \
+ -DprojectArtifactId=silverblue-logo \
+ -DclassName="org.jakfrost.quickstart.GreetingResource" \
+ -Dpath="/hello"
+$ cd silverblue-logo
+```
+
+The bootstrapping process shown above will create a project under the current directory with the name _silverblue-logo_. After this completes, start the application in development mode:
+
+```
+$ ./mvnw compile quarkus:dev
+```
+
+With the application running, check whether it responds as expected by issuing the following command:
+
+```
+$ curl -w '\n' http://localhost:8080/hello
+```
+
+The above command should print _hello_ on the next line. Alternatively, test the application by browsing to __ with your web browser. You should see the same lonely _hello_ on an otherwise empty page. Leave the application running for the next section.
+
+### Injection
+
+Open the project in your favorite IDE. If you are using Netbeans, simply open the project directory where the _pom.xml_ file resides. Now would be a good time to have a look at the _pom.xml_ file.
+
+Quarkus uses ArC for its dependency injection. ArC is a dependency of quarkus-resteasy, so it is already part of the core Quarkus installation. Add a companion bean to the project by creating a java class in your IDE called _GreetingService.java_. Then put the following code into it:
+
+```
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class GreetingService {
+
+ public String greeting(String name) {
+ return "hello " + name;
+ }
+
+}
+```
+
+The above code is a verbatim copy of what is used in the injection example in the Quarkus Getting Started tutorial. Modify _GreetingResource.java_ by adding the following lines of code:
+
+```
+import javax.inject.Inject;
+import org.jboss.resteasy.annotations.jaxrs.PathParam;
+
+@Inject
+ GreetingService service;//inject the service
+
+ @GET //add a getter to use the injected service
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("/greeting/{name}")
+ public String greeting(@PathParam String name) {
+ return service.greeting(name);
+ }
+```
+
+If you haven’t stopped the application, it will be easy to see the effect of your changes. Just enter the following _curl_ command:
+
+```
+$ curl -w '\n' http://localhost:8080/hello/greeting/Silverblue
+```
+
+The above command should print _hello Silverblue_ on the following line. The URL should work similarly in a web browser. There are two important things to note:
+
+ 1. The application was running and Quarkus detected the file changes on the fly.
+ 2. The injection of code into the app was very easy to perform.
+
+
+
+### The native image
+
+Next, package your application as a native image that will work in a _podman_ container. Exit the application by pressing **CTRL-C**. Then use the following command to package it:
+
+```
+$ ./mvnw package -Pnative -Dquarkus.native.container-runtime=podman
+```
+
+Now, build the container:
+
+```
+$ podman build -f src/main/docker/Dockerfile.native -t silverblue-logo/silverblue-logo
+```
+
+Now run it with the following:
+
+```
+$ podman run -i --rm -p 8080:8080 localhost/silverblue-logo/silverblue-logo
+```
+
+To get the container build to successfully complete, it was necessary to copy the _/target_ directory and contents into the _src/main/docker/_ directory. Investigation as to the reason why is still required, and though the solution used was quick and easy, it is not an acceptable way to solve the problem.
+
+Now that you have the container running with the application inside, you can use the same methods as before to verify that it is working.
+
+Point your browser to the URL and you should get a _index.html_ that is automatically generated by Quarkus every time you create or modify an application. It resides in the _src/main/resources/META-INF/resources/_ directory. Drop other HTML files in this _resources_ directory to have Quarkus serve them on request.
+
+For example, create a file named _logo.html_ in the _resources_ directory containing the below markup:
+
+```
+
+
+
+
+ Silverblue
+
+
+
+
+
+
+
+
+
+```
+
+Next, save the below image alongside the _logo.html_ file with the name _fedora-silverblue-logo.png_:
+
+![][6]
+
+Now view the results at .
+
+#### Testing your application
+
+Quarkus supports junit 5 tests. Look at your project’s _pom.xml_ file. In it you should see two test dependencies. The generated project will contain a simple test, named _GreetingResourceTest.java_. Testing for the native file is only supported in _prod_ mode. However, you can test the _jar_ file in _dev_ mode. These tests are RestAssured, but you can use whatever test library you wish with Quarkus. Use Maven to run the tests:
+
+```
+$ ./mvnw test
+```
+
+More details can be found in the Quarkus [Getting Started][7] tutorial.
+
+#### Further reading and tutorials
+
+Quarkus has an extensive collection of [tutorials and guides][8]. They are well worth the time to delve into the breadth of this microservices framework.
+
+Quarkus also maintains a [publications][9] page that lists some very interesting articles on actual use cases of Quarkus. This article has only just scratched the surface of the topic. If what was presented here has piqued your interest, then follow the above links for more information.
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/using-the-quarkus-framework-on-fedora-silverblue-just-a-quick-look/
+
+作者:[Stephen Snow][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/jakfrost/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/02/quarkus-816x345.jpg
+[2]: https://quarkus.io/
+[3]: https://quarkus.io/vision/container-first
+[4]: https://www.graalvm.org/downloads/
+[5]: https://quarkus.io/get-started/
+[6]: https://fedoramagazine.org/wp-content/uploads/2020/02/fedora-silverblue-logo.png
+[7]: https://quarkus.io/guides/getting-started
+[8]: https://quarkus.io/guides/
+[9]: https://quarkus.io/publications/
diff --git a/sources/tech/20200313 How to set up the Raspberry Pi Zero for travel.md b/sources/tech/20200313 How to set up the Raspberry Pi Zero for travel.md
new file mode 100644
index 0000000000..5b6ca689d7
--- /dev/null
+++ b/sources/tech/20200313 How to set up the Raspberry Pi Zero for travel.md
@@ -0,0 +1,472 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to set up the Raspberry Pi Zero for travel)
+[#]: via: (https://opensource.com/article/20/3/raspberry-pi-zero)
+[#]: author: (Peter Garner https://opensource.com/users/petergarner)
+
+How to set up the Raspberry Pi Zero for travel
+======
+You don't have to invest large amounts of money to build a relatively
+powerful system that can be taken on the road and used productively.
+![Airplane flying with a globe background][1]
+
+For some time now, I've been a huge fan of the [Raspberry Pi][2] computer in all of its various forms. I have a number of them, and each has a server role to play. Most of the time, they work extremely well, and I'm safe in the knowledge that the small amount of power they consume is keeping the bills down.
+
+If you've read my blog before, you may have read my account of how I [migrated my desktop computing][3] to a Pi 3. This worked well for quite a while, but I finally had to accept that editing large graphics and multimedia files was a problem, so I replaced it with an [Intel NUC][4]. My hankering for Pi experimentation was still there, though, and I decided to do a "what-if" exercise and see if it could survive on the road. And that's when I dragged my Pi Zero out of retirement from my spares box.
+
+### Why travel with a Raspberry Pi
+
+_"Why would I want to do this? Surely the trend is to travel with as powerful a device as possible?"_
+
+Well, it's like this. Last year, my employer issued a decree that in order to conform to its security policy, we would no longer be able to check laptops in as luggage, and not long after, the US government decided to summarily ban carrying laptops in hand baggage to and from certain countries, y'know, for security. So how do we get around that one? The sensible option would be to not travel with a laptop and use a hot-desk style spare at the destination. After all, everything is in the cloud now, right? Or, you could carry your important, commercially sensitive data on a CD/DVD or memory stick, but only if it's encrypted to a standard and your employer's data handling policy allows that.
+
+The problem is multi-faceted though: What if your role is such that you need to be able to fix software/systems on-the-go and you don't always have access to a "spare" laptop? On the occasions when I travel (by train), I have to lug my laptop with me, and it's a pain over the course of a day. Then there's the loss/theft/damage problem. Laptops can be easy targets, they can get left on trains, or you could be mugged. Or there's the "[evil maid][5]" scenario, in which someone interferes with your device without your knowledge. The list goes on.
+
+So, here's what you can get with a Pi Zero portable computer:
+
+ * It's small enough to fit in hand baggage or your pocket.
+ * It's cheap enough at $8 to buy another if yours gets lost/stolen/damaged.
+ * The entire OS and data are held on a "disk" that is as small as a fingernail, is cheap, and is easily bought in a wide variety of retail outlets. If need be, you can create a new one from a borrowed card from a phone.
+ * A full development environment with the ability to work offline or online. It can also act as an SSH server so that more than one person can use it at once.
+ * Safe storage: If you are paranoid or traveling on certain airlines, you can remove the "disk" and store it in your wallet or on your person. If your computer is stolen in transit, go and buy another one off the shelf: you're already set up with the OS.
+ * Network-tolerant: Around the world, there are country-specific WiFi frequencies, and a simple text-file change enables you to be compliant within minutes.
+ * Keyboard independent: You can use a compliant Bluetooth keyboard, but when you need to do something more demanding, you can just plug any USB keyboard into the spare USB connector using an On-The-Go cable.
+ * Power supply tolerant: My 3300mAh power bank can run the Pi Zero for about eight hours, but if all else fails, you can use a TV's USB connector to power it. Generally speaking, if a TV has HDMI, it will also have a USB socket, and the Zero only draws about 120mA. Or use someone's phone charger!
+ * Finally, if you're unfortunate enough to lose/damage your "disk," you can easily create another by downloading your 2GB image from a secure location in the cloud and burning it to a new card. Try doing _that_ with a normal laptop.
+
+
+
+That's motivation enough for me!
+
+Here is my finished product, with a beer coaster for scale.
+
+![Pi Zero W setup][6]
+
+### How I set up the Pi Zero for travel
+
+The cheap-as-chips Pi Zero has always been a bit of an odd beast, in my opinion. It features a single-core CPU and has a frugal 512MB of memory, some of which it has to share with the onboard video. The Raspbian OS currently based on Debian Stretch is touted as being suitable for the Zero with the LXDE-based "Pixel" GUI desktop, and indeed it can be loaded and started—but in reality, the poor thing really struggles to manage a GUI _and_ run useful software.
+
+Nevertheless, I was determined to give it a good try and set it up with the apps that have the smallest memory footprint. I'd already been around this loop with the Pi 3, so it was more of the same—only even more so! Bearing in mind this was to be a road warrior's computer, here's what I wanted to have on it:
+
+Web browser | Lightweight but with privacy in mind
+---|---
+Email | IMAP-capable and seamlessly supporting GPG
+XMPP/Jabber client | No-nonsense messaging
+VPN client | I'm on the road, remember
+Tor client | Always useful...
+Music | I carry a few MP3s, but internet radio is cool, too
+Multiple desktops | Useful with a small screen
+Editor/IDE | Hey, it's a working computer!
+FTP/SFTP client | Hey, it's a working computer!
+
+All in all, it's a very useful bundle for my purposes, and if I achieve a balanced environment, it could actually work.
+
+### Hardware
+
+The hardware was a bit of a challenge. The battery was not a problem, as I have a variety of rechargeable power packs with varying capacity, so it is really just a question of picking a suitable one for the day. The only prerequisite was that the battery should be able to take a charge while being used, and all my Jackery brand batteries do this.
+
+For my "disk," I opted for my in-house standard 32GB SanDisk Extreme microSDHC. They're very reliable, and the size is big enough to hold a lot of software and data while still remaining affordable.
+
+The video output would, I anticipated, be HDMI-out using the Zero's mini-HDMI connector. This suited my purposes well, as the majority of hotel TVs use this interface. Audio would also go via HDMI.
+
+That left the human interface devices (HID), and this, predictably, caused the most consternation. I hate Bluetooth with a passion, and with the Zero's limited connectors, I'd have to bite the bullet and use a Bluetooth keyboard and mouse, preferably a combined one—and small. There's no point in having a tiny computer if you have lug a great honking keyboard around as well, so my unhappy quest began.
+
+### Bluetooth woes
+
+The Zero has a limited number of USB connectors on board—just one, if you allow for the power connector, which obviously means you have limited connection options. You could always use a USB extender hub, but then that's more to carry—including another power supply. That basically leaves you trying to connect a keyboard and mouse via Bluetooth. I don't believe the hype about how it can "_easily connect a wide variety of devices together,_" and I wrestle with a variety of allegedly standard devices trying to get the bloody things to play nicely together. Part of the problem with the Pi (I think) is that there's some unintended interaction between WiFi and Bluetooth that causes weird stuff to happen. My problem was that I was able to connect to the Pi using a keyboard _or_ a mouse, but not both reliably at the same time. And yes, I have a variety of allegedly standards-following Bluetooth devices, none of which decided to work together properly.
+
+At this point, I was wondering if there was a Bluetooth Samaritan's Helpline, but there wasn't, so what the heck was I going to do?! Temporarily, I resorted to using an Apple USB keyboard with two USB sockets; this was useful for setup but not for being on the road. In the end, I spent hours browsing eBay and Amazon, and then I found it: a "_3- in-1 Mini Wireless Bluetooth Keyboard Mouse Touchpad For Windows iOS Android UK - Backlit, Ultra-thin, Built-in Rechargeable Battery, QWERTY_." Perfect on paper, but would it work? I sent off the money, and four days later, a slim package arrived from China. And it bloody well worked!! First time, every time, it got on with the Pi like pie and chips. I promptly ordered another one—accidents happen, and I wouldn't want to be left in the lurch.
+
+So, with my hardware lineup complete, I could settle down to setting up the Pi proper.
+
+### The GUI and the Pi
+
+Going back to my software requirements, I thought long and hard about the smallest desktop environment and went with the supplied LXDE desktop, which I'd used several times on other projects. Although the Pi struggled a bit with screen handling, it generally performed well, and I started setting up my software.
+
+Web browser 1
+
+Midori: a good compromise between size and modernity. Supports private browsing and is bundled with the Pi
+
+Web browser 2
+
+Links2 in graphic mode: lightweight, fast, secure, works with proxies
+
+Email
+
+Sylpheed: small, light, and works well with GPG
+
+XMPP/Jabber client
+
+Profanity. It's great!
+
+VPN client
+
+OpenVPN
+
+Tor client
+
+Ha! Links2 again
+
+Music
+
+SMPlayer: the GUI for MPlayer
+
+Editor/IDE
+
+Geany: small and light but powerful
+
+Image viewer/editor
+
+Pinta
+
+FTP/SFTP client
+
+Filezilla
+
+**Other stuff:**
+
+Midnight Commander
+
+Not just a file manager (more later)
+
+Tor proxy server
+
+Always on, so I can use Tor as needed
+
+Nmap
+
+I sometimes need to test stuff
+
+vnStat
+
+Monitor data usage on the wlan0 interface
+
+SSH/SFTP server
+
+Standard issue on this distro
+
+UFW
+
+Firewall; can't be too careful!
+
+Gopher client
+
+Gopherspace! It's still out there, and I use the _original_ Gopher client!
+
+All of the above are tried, tested, and very stable packages. The web browser decision was a calculated one: the Zero doesn't _really_ have what it takes to negotiate a modern ~~bloated, ad-ridden~~ website, and honestly, I have a phone that can handle that sort of thing. Likewise, the decision to run a Tor proxy: it's very handy to be able to access Marianas Web, and using Links2 as a browser means that the risk is minimal.
+
+Sylpheed is a mature package that I believe has largely been replaced by Claws but is actually less demanding of resources. GPG integrated seamlessly with it, and I was able to exchange signed/encrypted messages with ease. It renders both plain-text and HTML messages well, and the interface is uncluttered.
+
+I needed a _simple_ XMPP/Jabber client. The problem I've found with many apps of this type is that they try to incorporate multiple messaging standards when I only really need XMPP. Profanity is ideal as it does one job and does it very well.
+
+### System setup
+
+I spent a considerable amount of time setting up the OS for the best performance; a task made easier because I have set up numerous Raspberry Pis before. In such a small (as in memory) system, the decision to use a swap file was not taken lightly, and unfortunately, using a GUI desktop meant that the swap is in frequent use. The alternative is to not have one and hope that the system doesn't freeze up too much. I went with the suggested default of 100MB.
+
+I then looked at logging. As this was supposed to be a small, portable system, I didn't see much point in having extensive logging, especially as it would have a negative effect on the SDHC card in the long term. One solution was a combination of disabling logging in apps wherever possible and sacrificing a little memory to create a tmpfs in-memory filesystem. This would have the added advantage that it would be recreated on each boot. So, I worked out that 8MB could be used for this and duly updated **/etc/fstab**. This works extremely well.
+
+
+```
+`tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=0755,size=8m 0 0`
+```
+
+I also had to update **/etc/rc.local** to provide some essential directories on startup; this kept the rsyslog and Tor daemons happy.
+
+
+```
+mkdir -p /var/log/rsyslog
+mkdir -p /var/log/tor/
+mkdir -p /var/log/vnstat/
+chown vnstat.root /var/log/vnstat/
+chown debian-tor /var/log/tor/
+```
+
+With all that in place, the little computer was almost ready for Prime Time. But there was a problem. I've already mentioned the frugal amount of memory on the Zero, and even with the GUI and apps pared down to the bone, I was regularly using swap space. To make matters worse, much worse, my carefully set up desktop menus were having problems.
+
+The Pi desktop comes with an _incredible_ amount of software installed, mainly to satisfy its original purpose as an educational machine. I decided early on to edit the menus to remove a lot of the "junk" and replace it with my list of apps, so I fired up the Main Menu Editor app. Normally this is quite responsive, but on the resource-challenged Zero, it had worrying lags and pauses as I made changes. Ultimately, it meant that my ad-hoc menus were corrupted, and worse still, the default Pi menus had been reinstated. Searching for help with this problem revealed that the menu system is convoluted, and if an update is not saved properly, the defaults will be substituted.
+
+I looked at the structure of the menus as best I could and decided that trying to pick the frigging things apart was more trouble than it was worth. So, I ditched LXDE/Pixel and installed XFCE (and its even lighter-weight GUI) in its place. This time, the menu editor seemed more stable, but as I made the changes, I realized that yes, it was happening again. At that point, I had a tantrum and threw my toys out of the pram. I'd reached a crossroads in my road-warrior setup: it worked very well apart from the menus, and I felt I couldn't go back after all that work, so, with a heavy heart, I had a drastic rethink. It was supposed to be a hacker's machine, right? It was Linux and, to many like-minded people, that meant a text-based interface, right?
+
+So I did what I had to do: I ditched the accursed GUI! Yes, go back to the '90s, maybe even earlier, and Run it Like a Boss.™ The main problem I had in my mind was that I'd no longer have nice, safe, icon-driven apps and multiple desktops to work with. My WiFi/network switcher would be no more, and worse still, I'd have to try and manage Bluetooth from the command line. That was going to be a major challenge, but I decided to proceed anyway, and I had a cloned copy of my microSDHC just in case I lost my nerve.
+
+### Set it up again
+
+Incidentally, if I were using a full-spec Raspberry Pi 3, I wouldn't have been in this situation. But it was my choice, so… This exercise started out well. I was already rebooting into the terminal login prompt, and the Bluetooth keyboard was working, so I was able to log in (previously, I'd run **startx** to get to the desktop). Since I no longer had the desktop bloat to worry about, my memory usage was a mere 78MB and no swap usage; I felt better already. But what about the apps that make life easy? I did more hunting around, and here's what I came up with.
+
+Web browser
+
+Links2 _not_ in graphic mode: lightweight, fast, secure, works with proxies
+
+Email
+
+(Neo)Mutt: powerful, extensible and works well with GPG
+
+XMPP/Jabber client
+
+Profanity. It's great!
+
+VPN client
+
+OpenVPN
+
+Tor client
+
+Ha! Links2 again
+
+Music
+
+Midnight Commander + mpg123
+
+Editor/IDE
+
+Nano: I'm using it to write this
+
+FTP/SFTP client
+
+Midnight Commander
+
+File manager
+
+Midnight Commander
+
+**Other stuff**
+
+Tor proxy server
+
+Always on, so I can use Tor as needed
+
+Nmap
+
+I sometimes need to test stuff
+
+vnStat
+
+Monitor data usage on the wlan0 interface
+
+SSH/SFTP server
+
+Standard issue on this distro
+
+Gopher client
+
+Gopherspace! It's still out there, and I use the _original_ Gopher client!
+
+**Graphics workarounds**
+
+fbcat
+
+Takes a screenshot using the framebuffer device
+
+fbi
+
+Linux framebuffer imageviewer: displays images in a terminal
+
+fbgs
+
+Displays PostScript/PDF files using the Linux framebuffer device on a terminal
+
+pnmtopng
+
+Converts a PPM into a PNG file
+
+You'll notice that there's not too much change there, with a few notable exceptions to display graphical content.
+
+### Do it again, and do it properly
+
+Things looked good, but I still had some issues to solve.
+
+#### Desktops
+
+"But what about the multiple desktops?!" I hear you asking, "How will you view images or connect to WiFi networks?" I needed to find a solution, and fast. For the multiple desktop thing, I decided to install tmux, the Linux Terminal Multiplexer. There are so many good reasons to run tmux on a Linux system, but my key reasons are that it makes multi-screen working possible, and it uses very little memory. It also enables me to connect to the Pi via SSH and take over the session, as you can see below.
+
+![tmux running on Raspberry Pi][7]
+
+#### Music
+
+I must say that it's very important to me to be able to listen to music while I'm working or relaxing, so the loss of (S)MPlayer was a major blow. I was able to listen to single MP3s or complete playlists. I was able to stream internet radio. Sigh. Midnight Commander came to the rescue with its ability to handle various file types. The secret is in the Extension File menu, which looks like this for me:
+
+
+```
+shell/i/.mp3
+ Open=/usr/lib/mc/ext.d/sound.sh open mp3
+regex/i/\\.(m3u|pls)$
+ Open=/usr/lib/mc/ext.d/sound.sh open playlist
+```
+
+And my sound.sh looks like this:
+
+
+```
+#!/bin/bash
+do_open_action() {
+ filetype=$1
+ case "${filetype}" in
+ playlist)
+ mpg123 -C -@ "${MC_EXT_FILENAME}"
+ ;;
+ m3u)
+ mpg123 -C -@ "${MC_EXT_FILENAME}"
+ ;;
+ mp3)
+ mpg123 -C "${MC_EXT_FILENAME}"
+ ;;
+ *)
+ ;;
+ esac
+ }
+case "${action}" in
+open)
+ ("${MC_XDG_OPEN}" "${MC_EXT_FILENAME}" >/dev/null 2>&1) || \
+ do_open_action "${filetype}"
+ ;;
+*)
+ ;;
+esac
+```
+
+Tapping Enter on an MP3 will play the file, or tapping on an M3U playlist will play whatever's in the playlist. I used the **-C** option so that I could have access to mpg123's controls. Sorted!
+
+#### SFTP/FTP clients
+
+Midnight Commander again! You can set up a client connection entry with the built-in menu and use **CTL+\** to select it from a drop-down. The FTP site is rendered in one of the panels as a directory structure, and you can just treat it as you would a local filesystem. SFTP is a bit harder, as you have to set it up as an SSH connection and then copy as required; it's OK if you have password authentication, but for public key authentication, I found it less involved to use SFTP from the command line. For reference, this is the syntax:
+
+
+```
+sftp://[user@]machine:[port]/[remote-dir]
+
+The user, port and remote-dir elements are optional.
+```
+
+![MC FTP client example][8]
+
+#### WiFi selector
+
+In the GUI world, I had had a nice, icon-based WiFi network manager app that I could use to switch between networks. The text-mode alternative is the bizarrely named wicd-curses*.* It's an app that communicates with wicd (wireless control daemon) using cursor keys, and it works very well. I had to disable the dhcpcd service using systemctl to get it to work, but at least it lets me select the appropriate network, including my home network or my phone's wireless hotspot when I'm out on the road. Here's [how to do it][9].
+
+![wicd-curses WiFi app][10]
+
+#### Email and web browsing
+
+For email and web browsing, I use Mutt (Neomutt) and Links2, respectively, and they just work.
+
+#### Gopher
+
+Trust me; you're not old enough to remember Gopher, the text mode forerunner of the WWW. Strictly speaking, it was before my time as well, but I run a thriving Gopher server, so I need a client. Here's what a Gopher server looks like running on a Raspberry Pi.
+
+
+```
+ gopher://gopher.petergarner.net:70
+
+__/\\\\\\\\\\\\\\\\\\_______/\\\\\\\\\\\\\\\\\\\\\\\\\\__________________/\\\\\\____
+_/\\\\\///////\\\\\\____\/\\\\\/////////\\\\\\______________/\\\\\\\\\\____
+_\/\\\\\\_____\/\\\\\\___\/\\\\\\_______\/\\\\\\__/\\\\\\_______/\\\\\/\\\\\\____
+_\/\\\\\\\\\\\\\\\\\\\\\/____\/\\\\\\\\\\\\\\\\\\\\\\\\\/___\///______/\\\\\/\/\\\\\\____
+_\/\\\\\//////\\\\\\____\/\\\\\/////////_____/\\\\\\_____/\\\\\/__\/\\\\\\____
+_\/\\\\\\____\//\\\\\\___\/\\\\\\_____________\/\\\\\\____/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\_
+_\/\\\\\\_____\//\\\\\\__\/\\\\\\_____________\/\\\\\\\\__///////////\\\\\//__
+_\/\\\\\\______\//\\\\\\_\/\\\\\\_____________\/\\\\\\_______________\/\\\\\\___
+_\///________\///__\///______________\///_________________\///___
+
+ Welcome to... "The Rpi4 Gopher"
+ ... your source for local information, and beyond!
+
+ --> [14] About this server (and legal)/
+
+ -- Content
+
+ [18] Tech-related/
+ [19] Politics and Propaganda (from all sides)/
+ [20] Cyber and Internet related/
+ [21] Stuff (filed under "miscellany")/
+.....
+```
+
+### Performance
+
+Overall, I'm pleased to say that my switch to text mode has been very beneficial with userland tasks handled responsively. As you can see from a typical **top** display, there's plenty of available and cached memory remaining from the original 512MB. Right now, I'm listening to a playlist, writing this article in an SSH-connected tmux session, running top**,** and Mutt is handling emails.
+
+On a regular basis, that's all I'll probably need to do, but it's great to have the option to develop and test software on the go, if I need to. Here's a simple Python script to get the Pi's CPU serial number (type):
+
+
+```
+>>> #!/usr/bin/env python
+...
+>>> import subprocess
+>>>
+>>> def GetCPUserial():
+... cpuinfo = subprocess.check_output(["/bin/cat", "/proc/cpuinfo"])
+... cpuinfo = cpuinfo.replace("\t","")
+... cpuinfo = cpuinfo.split("\n")
+... [ legend, cpuserial ] = cpuinfo[11].split(' ')
+... return cpuserial
+...
+>>> print GetCPUserial()
+9000c1
+>>>
+
+[/code] [code]
+
+top - 15:55:47 up 5:49, 6 users, load average: 0.21, 0.25, 0.34
+Tasks: 112 total, 1 running, 110 sleeping, 1 stopped, 0 zombie
+%Cpu(s): 3.9 us, 5.8 sy, 0.0 ni, 90.3 id, 0.0 wa, 0.0 hi, 0.0 si,
+
+KiB Mem : 493252 total, 37984 free, 73248 used, 382020 buff/cache
+KiB Swap: 102396 total, 102392 free, 4 used. 367336 avail Mem
+```
+
+I take regular backups, of course, using the indispensable [rpi-clone][11]. The beauty of this app is that I can copy the entire microSDHC card to another while the Pi is running. It also has the advantage that if I use a smaller capacity card, it will automatically and safely take this into account. I use a 32GB card, but I can dump it to an 8GB card because I'm only using about 4GB. The converse is true for a larger destination card. If you add only one utility to your Pi, this should be it—it's saved me more grief than _anything_ I've ever used! You can also use it to create distribution copies of your system.
+
+#### Battery life
+
+I can only describe the battery life as "impressive." Once the Zero is booted up, it takes an average 0.15A / 0.65W with the following running:
+
+ * System
+ * Bluetooth
+ * WiFi
+ * Audio (HDMI) subsystem
+ * Video (HDMI) subsystem
+
+
+
+I've measured 20 hours of mixed usage from my 6000mAh Jackery Jetpack power bank, and if I disable WiFi and just use it in "local" mode, possibly more. It's certainly practical to use it with my smaller, 3300mAh Anker battery, which unfortunately isn't rechargeable while in use. I also have a 20,000mAh battery for long trips: I have yet to try that out.
+
+### Taking it on the road
+
+In terms of computing as a challenge, setting up the Zero has been a really valuable exercise. It's taught me to become acquainted with the operating system and app software at a low level in order to squeeze the maximum amount of memory from the system. It's also taught me that I don't have to invest large amounts of money to build a relatively powerful system that can be taken on the road and used productively.
+
+Now that I've almost finished setting it up, it's time to actually _take_ it on the road and see how it runs in the field. Hey, maybe I'll actually take into a field and see if I can do some work and listen to music.
+
+* * *
+
+_This was originally published on [Peter Garner's blog][12] under a CC BY-NC-ND 4.0 license and is reused here with the author's permission._
+
+Having recently co-authored a book about building things with the Raspberry Pi ( Raspberry Pi Hacks...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/raspberry-pi-zero
+
+作者:[Peter Garner][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petergarner
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/plane_travel_world_international.png?itok=jG3sYPty (Airplane flying with a globe background)
+[2]: https://opensource.com/resources/raspberry-pi
+[3]: https://www.petergarner.net/projects/Mac_Mini_to_rpi-part_1.pdf
+[4]: https://en.wikipedia.org/wiki/Next_Unit_of_Computing
+[5]: http://threatbrief.com/evil-maid-attack/
+[6]: https://opensource.com/sites/default/files/uploads/pi-zero-on-the-road.jpg (Pi Zero W setup)
+[7]: https://opensource.com/sites/default/files/uploads/tmux-on-pi.png (tmux running on Raspberry Pi)
+[8]: https://opensource.com/sites/default/files/uploads/ftp-client-mc.png (MC FTP client example)
+[9]: https://www.raspberrypi.org/forums/viewtopic.php?t=150124#p987430
+[10]: https://opensource.com/sites/default/files/uploads/wifi-selector.png (wicd-curses WiFi app)
+[11]: https://github.com/billw2/rpi-clone
+[12]: https://petergarner.net/notes/index.php?thisnote=20180202-Travels%20with%20a%20Pi
diff --git a/sources/tech/20200313 How to whiteboard collaboratively with Drawpile.md b/sources/tech/20200313 How to whiteboard collaboratively with Drawpile.md
new file mode 100644
index 0000000000..dba4bce1f8
--- /dev/null
+++ b/sources/tech/20200313 How to whiteboard collaboratively with Drawpile.md
@@ -0,0 +1,118 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to whiteboard collaboratively with Drawpile)
+[#]: via: (https://opensource.com/article/20/3/drawpile)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+How to whiteboard collaboratively with Drawpile
+======
+Need to whiteboard or draw something with others? Give Drawpile a try.
+![markers for a whiteboard][1]
+
+Thanks to applications like [Krita][2] and [MyPaint][3], open source software users have all the tools they need to create stunning digital paintings. They are so good that you can see [art created with Krita][4] in some of your [favorite RPG books][5]. And it's getting better all the time; for example, [GIMP][6] 2.10 adopted MyPaint's brush engine, so users can benefit from MyPaint without even installing the whole application.
+
+But what about collaborative illustration? What do two or more artists do when they want to work together on one piece? What does your work team use when you need to whiteboard during a business meeting? Those are the questions, and the answer is [Drawpile][7].
+
+![Drawpile's UI][8]
+
+Nyarlathotep by Sophia Eberhard
+
+Drawpile is a drawing application for Linux, Windows, and macOS. It's got a respectable brush engine and all the basic editorial tools (selection tools, flips and flops, mirror, and so on) to make it a good freehand digital paint application. But its most powerful feature is its easy multi-user mode. If you have Drawpile installed, you can host a drawing session from your computer or on a Drawpile server, allowing other users to join you in your virtual studio. This goes well beyond a screen-share session, which would just allow other users to _view_ your painting, and it's not a remote desktop with just one cursor. Drawpile enables several users, each with their own brush, to work on the same canvas at the same time over a network that can span the globe.
+
+### Installing Drawpile
+
+If you're using Linux, Drawpile is available as a [Flatpak][9] from [Flathub.org][10].
+
+On Windows and macOS, download and install Drawpile from [Drawpile's download page][11]. When you first launch it on macOS, you must right-click on its icon and select **Open** to accept that it hasn't been signed by a registered Apple developer.
+
+### Drawing with Drawpile
+
+The Drawpile interface is simple and minimal. Along the right side of the application window are docked palettes, and along the top is a toolbar. Most of the tools available to you are visible: paint brushes, paint buckets, lines, Bézier curves, and so on.
+
+For quick access to brushes, Drawpile allows you to assign a unique brush, along with all of its settings (including color), to the number keys **1** through **5** on your keyboard. It's an efficient and easy way to quickly move between drawing tools. The **6** key holds an eraser.
+
+Drawpile also has layers, so you can keep different parts of your painting separate until you combine them for your final render. If you're an animator, you can even use Drawpile's onion skin and flipbook features (both available in the **Layer** menu) to do rudimentary frame-by-frame animation. Unlike Krita, Drawpile doesn't feature an [animation timeline][12], but it's enough for quick and fun animations.
+
+### Custom brushes
+
+Drawpile isn't Krita or MyPaint, so its brush engine is simple in comparison. The preset brushes have the usual properties, though, including:
+
+ * **Opacity** adjusts how your strokes blend with existing paint
+ * **Hardness** defines the edges of your stroke
+ * **Smudging** allows existing strokes to be affected by your brush
+ * **Color pickup** allows your paint to pick up color from existing strokes
+ * **Spacing** controls how often the full brush cursor is sampled during a stroke
+
+
+
+Most of these are pressure-sensitive, so if you're using a drawing tablet (Wacom, for instance), then your brush strokes are dynamic depending upon pen pressure. The tablet support is borrowed from Krita, and it makes a big difference (although it's probably overkill for mock-ups or whiteboarding sessions).
+
+When you find a brush setting you like, you can add it to your brush set so you can use it again later. To add a brush, click the **Menu** button in the top-right corner of the docked **Brushes** palette and select **Add brush**.
+
+![Adding a brush in Drawpile][13]
+
+If the **Brushes** palette isn't visible, go to the **View** menu in the top menu bar and select **Brushes** from the **Docks** submenu.
+
+### Collaborative drawing
+
+To participate in a shared drawing session, go to the **Session** menu and click either **Host** to host a session or **Join** to join in on an existing one.
+
+#### Hosting a session
+
+If you're hosting a session, give your session a title and an optional password (or leave it blank to allow anyone in). In the **Server** section, set whether you're hosting the session from your computer or from someone else's server. You can host sessions on **pub.drawpile.net** for free, but all of your data will be sent out to the internet, which could affect performance. If you have a good internet connection, the lag is negligible, but if you're not confident in your internet speed or there's no reason to go out to the internet because your collaborators are in the same building as you, then you can host your session locally.
+
+![Settings for hosting a session][14]
+
+If you host locally, you must provide your IP address or computer name (ending in **.local**) to your collaborators so their Drawpile apps can find your computer. You can find your computer name in the **Sharing** preferences of the GNOME desktop if you're on Linux:
+
+![Sharing Drawpile in GNOME][15]
+
+You must enable Remote Login, and possibly adjust your [firewall settings][16] to allow other users to get through.
+
+On macOS and Windows, you may be running a firewall, and you may need to provide additional sharing permissions in your control panel or system settings.
+
+#### Joining a session
+
+If you're joining a session, you need to know either the URL or the IP address of the session you're trying to join. A URL is like a website address, such as syntheticdreams.net/listing. An IP address is the numerical version of a URL, such as 93.184.216.34. Some IP addresses are internal to your building, while others exist out on the internet. If you haven't been invited to a drawing session, you might be able to find a public group on Drawpile's [Communities][17] page.
+
+### Drawing with friends
+
+Open source has always been about sharing. Drawpile is not only software you can share with your friends and colleagues; it's software that allows you to work with them in a fun and creative way. Try Drawpile for your next project or boardroom meeting!
+
+Nick Hamilton talks about what he loves about the open source digital painting tool, Krita, prior...
+
+Akkana Peck shares three of her favorite GIMP tools.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/drawpile
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/markers_whiteboard_draw.png?itok=hp6v1gHC (markers for a whiteboard)
+[2]: https://krita.org/en/
+[3]: http://mypaint.org
+[4]: https://krita.org/en/item/interview-with-alexandru-sabo/
+[5]: https://paizo.com/products/btpy9g9x?Pathfinder-Roleplaying-Game-Bestiary-5
+[6]: https://www.gimp.org/
+[7]: https://drawpile.net
+[8]: https://opensource.com/sites/default/files/uploads/drawpile-ui.jpg (Drawpile's UI)
+[9]: https://opensource.com/article/19/10/how-build-flatpak-packaging
+[10]: https://flathub.org/apps/details/net.drawpile.drawpile
+[11]: https://drawpile.net/download/
+[12]: https://opensource.com/life/16/10/animation-krita
+[13]: https://opensource.com/sites/default/files/uploads/drawpile-brush-add.jpg (Adding a brush in Drawpile)
+[14]: https://opensource.com/sites/default/files/uploads/drawpile-session-host.png (Settings for hosting a session)
+[15]: https://opensource.com/sites/default/files/uploads/gnome-sharing.png (Sharing Drawpile in GNOME)
+[16]: https://opensource.com/article/19/7/make-linux-stronger-firewalls
+[17]: https://drawpile.net/communities
diff --git a/sources/tech/20200313 Open source alternative for multi-factor authentication- privacyIDEA.md b/sources/tech/20200313 Open source alternative for multi-factor authentication- privacyIDEA.md
new file mode 100644
index 0000000000..382aa368e5
--- /dev/null
+++ b/sources/tech/20200313 Open source alternative for multi-factor authentication- privacyIDEA.md
@@ -0,0 +1,85 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source alternative for multi-factor authentication: privacyIDEA)
+[#]: via: (https://opensource.com/article/20/3/open-source-multi-factor-authentication)
+[#]: author: (Cornelius Kölbel https://opensource.com/users/cornelius-k%C3%B6lbel)
+
+Open source alternative for multi-factor authentication: privacyIDEA
+======
+As technology changes, so too will our need to adapt our authentication
+mechanisms.
+![Three closed doors][1]
+
+Two-factor authentication, or multi-factor authentication, is not a topic only for nerds anymore. Many services on the internet provide it, and many end-users demand it. While the average end-user might only realize that his preferred web site either offers MFA or it does not, there is more to it behind the scene.
+
+The two-factor market is changing, and changing rapidly. New authentication methods arise, classical vendors are merging, and products have disappeared.
+
+The end-user might not be bothered at all, but organizations and companies who want to require multi-factor authentication for their users may wonder where to turn to and which horse to bet on.
+
+Companies like Secure Computing, Aladdin, SafeNet, Cryptocard, Gemalto, and Thales have been providing authentication solutions for organizations for some decades and have been involved in a round dance of [mergers and acquisitions][2] during the last ten years. And the user was the one who suffered. While the IT department thought it was rolling out a reliable software of a successful vendor, a few years later, they were confronted with the product being end-of-life.
+
+### How the cloud changes things
+
+In 1986, RSA released RSA SecurID, a physical hardware token displaying magic numbers based on an unknown, proprietary algorithm. But, almost 20 years later, thanks to the Open Authentication Initiative, HOTP (RFC4226) and TOTP (RFC6238) were specified—originally for OTP hardware tokens.
+
+SMS Passcode, which specialized in authenticating by sending text messages, was founded in 2005; no hardware token required. While other on-premises solutions kept the authentication server and the enrollment in a confined environment, with SMS Passcode, the authentication information (a secret text message) was transported via the mobile network to the user.
+
+The iPhone 1 was released in 2007, and the Android phone quickly followed. DUO Security was founded in 2009 as a specific cloud MFA provider, with the smartphone acting as a second factor. Both vendors concentrated on a new second factor—the phone with a text message or the smartphone with an app—and they offered and used infrastructure that was not part of the company's network anymore.
+
+Classical on-premises vendors started to move to the cloud, either by offering their new services or acquiring smaller vendors with cloud solutions, such as SafeNet's [acquisition of Cryptocard in 2012][3]. It seemed tempting for classical vendors to offer cloud services—no software updates on-premises, no support cases, unlimited scaling, and unlimited revenue.
+
+Even the old top dog, RSA, now offers a "Cloud Authentication Service." And doesn't it make sense to put authentication services in the cloud? The data is hosted at cloud services like Azure, the identities are hosted in the cloud at Azure AD, so why not put authentication there with Azure MFA? This approach might make sense for companies with a complete cloud-centric approach, but it also probably locks you into one specific vendor.
+
+Cloud seems a big topic also for multi-factor authentication. But what if you want to stay on-prem?
+
+### The state of multi-factor authentication technology
+
+Multi-factor authentication has also come a long way since 1986, when RSA introduced its first OTP tokens. A few decades ago, well-paid consultants made a living by rolling PKI concepts, since smartcard authentication needed a working certificate infrastructure.
+
+After having OTP keyfob tokens and smartphones with HOTP and TOTP apps and even push notification, the current state-of-the-art authentication seems to be FIDO2/WebAuthn. While U2F was specified by the FIDO Alliance alone, WebAuthn was specified by no one else than W3C, and the good news is, the base requirements have been integrated into all browsers except Internet Explorer.
+
+However, applications still need to add a lot of code when supporting Webauthn. But WebAuthn allows for new authentication devices like TPM chips in tablets, computers, and smartphones or cheap and small hardware devices. But U2F also looked good back then, and even it did not make the breakthrough. Will WebAuthn do it?
+
+So these are challenging times since currently, you probably cannot use WebAuthn, but in two years, you'll probably want to. Thus, you need a system that allows you to adapt your authentication mechanisms.
+
+### Getting actual requirements
+
+This is one of the first requirements when you are about to choose a flexible multi-factor authentication solution. It will not work out to solely rely on text messages, or on one single smartphone app or only WebAuthn tokens. The smartphone app may vanish; the WebAuthn devices might not be applicable in all situations.
+
+When looking at the mergers and acquisitions, we learned that it did happen and can happen again; that the software goes end-of-life, or the vendors cease their cloud services. And sometimes it is only the last few months that hurt, when the end of sales means that you cannot buy any new user licenses or onboard any new users! To get a lasting solution, you need to be independent on cloud services and vendor decisions. The safest way to do so is to go for an open source solution.
+
+But when going for an open source solution, you want to get a reliable system, reliable meaning that you can be sure to get updates that do not break and that bugs will be fixed, and there are people to be asked.
+
+### An open source alternative: privacyIDEA
+
+Concentrated experiences in the two-factor market since 2004 have been incorporated into the open source software alternative: [privacyIDEA][4].
+
+privacyIDEA is an open source solution providing a wide variety of different authentication technologies. It started with HOTP and TOTP tokens, but it also supports SMS, email, push notifications, SSH keys, X.509 certificates, Yubikeys, Nitrokeys, U2F, and a lot more. Currently, the support for WebAuthn is added.
+
+The modular structure of the token types (being Python classes) allows new types to be added quickly, making it the most flexible in regards to authentication methods. It runs on-premises at a central location in your network. This way, you stay flexible, have control over your network, and keep pace with the latest developments.
+
+privacyIDEA comes with a mighty and flexible policy framework that allows you to adapt privacyIDEA to your needs. The unique event handler modules enable you to fit privacyIDEA into your existing workflows or create new workflows that work the best for your scenario. It is also plays nice with the others and integrates with identity and authentication solutions like FreeRADIUS, simpleSAMLphp, Keycloak, or Shibboleth. This flexibility may be the reason organizations like the World Wide Web Consortium and companies like Axiad are using privacyIDEA.
+
+privacyIDEA is developed [on GitHub][5] and backed by a Germany-based company providing services and support worldwide.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/open-source-multi-factor-authentication
+
+作者:[Cornelius Kölbel][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/cornelius-k%C3%B6lbel
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/EDU_UnspokenBlockers_1110_A.png?itok=x8A9mqVA (Three closed doors)
+[2]: https://netknights.it/en/consolidation-of-the-market-and-migrations/
+[3]: https://www.infosecurity-magazine.com/news/safenet-acquires-cryptocard/
+[4]: https://privacyidea.org
+[5]: https://github.com/privacyidea/privacyidea
diff --git a/sources/tech/20200314 Adding a display to a travel-ready Raspberry Pi Zero.md b/sources/tech/20200314 Adding a display to a travel-ready Raspberry Pi Zero.md
new file mode 100644
index 0000000000..f8dcb26208
--- /dev/null
+++ b/sources/tech/20200314 Adding a display to a travel-ready Raspberry Pi Zero.md
@@ -0,0 +1,281 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Adding a display to a travel-ready Raspberry Pi Zero)
+[#]: via: (https://opensource.com/article/20/3/pi-zero-display)
+[#]: author: (Peter Garner https://opensource.com/users/petergarner)
+
+Adding a display to a travel-ready Raspberry Pi Zero
+======
+A small eInk display turns a Raspberry Pi into a self-contained,
+pocket-sized travel computer.
+![Pi Zero][1]
+
+In my earlier article, I explained how I [transformed a Raspberry Pi Zero][2] into a minimal, portable, go-anywhere computer system that, although small, can actually achieve useful things. I've since made iterations that have proved interesting and made the little Pi even more useful. Read on to learn what I've done.
+
+### After the road trip
+
+My initial Pi Zero setup [proved its worth][3] on a road trip to Whitby, but afterward, it was largely consigned to the "pending" shelf, waiting for another assignment. It was powered up weekly to apply updates, but other than that, it was idle. Then one day, as I was flicking through emails from various Pi suppliers, I came across a (slightly) reduced e-Ink display offer: hmmm… and there was a version for the Pi Zero as well. What could I do with one?
+
+ModMyPi was selling a rather neat [display and driver board combination][4] and a [small case][5] with a transparent window on top. I read the usual reviews, and apart from one comment about the _boards being a very tight fit_, it sounded positive. I ordered it, and it turned up a few days later. I had noted from the product description that the display board didn't have GPIO headers installed, so I ordered a Pi Zero WH (wireless + headers pre-installed) to save me the bother of soldering one on.
+
+### Some assembly required
+
+As with most of these things, some self-assembly was required, so I carefully opened the boxes and laid out the parts on the desk. The case was nicely made apart from ridiculous slots for a watch strap (?!) and some strange holes in the side to allow tiny fingers to press the five I/O buttons on the display. "_Could I get a top without holes?"_ I inquired on the review page. "_No."_ Okay then.
+
+With the case unpacked, it was time to open the display box. A nicely designed board was first out, and there were clear instructions on the Pi-Supply website. The display was so thin (0.95mm) that I nearly threw it out with the bubble wrap.
+
+The first job was to mount the display board on the Pi Zero. I checked to make sure I could attach the display cable to the driver board when it was joined to the Pi and decided that, with my sausage fingers, I'd attach the display first and leave it flapping in the breeze while I attached the driver board to the Pi. I carefully got the boards lined up on the GPIO pins, and, with those in place, I folded over the display "screen" to sit on top of the board. With the piggy-backed boards in place, I then _verrrry_ carefully shoe-horned the assembly into place in the case. Tight fit? Yeah, you're not kidding, but I got it all safely in place and snapped the top on, and nothing appeared to be broken. Phew!
+
+### How to set up your display
+
+I'm going to skip a chunk of messing about here and refer you to the maker's [instructions][6] instead. Suffice to say that after a few installs, reboots, and coffees, I managed to get a working e-Ink display! Now all I had to do was figure out what to do with it.
+
+One of the main challenges of working with a small device like [my "TravelPi"][2] is that you don't have access to as much screen real estate as you would on a larger machine. I like the size and power of the device though, so it's really a compromise as to what you get out of it. For example, there's a single screen accessible via the HDMI port, and I've used tmux to split that into four separate, usable panes. If I really need to view something else urgently, I could always **Ctrl+Z** into another prompt and do the necessary configs, but that's messy.
+
+I wanted to see various settings and maybe look at some system settings, and the e-Ink display enabled me to do all that! As you can see from the image below, I ended up with a very usable info panel that is updated by a simple(-ish) Python script (**qv**) either manually or by a crontab entry every 10 minutes. The manufacturer states that the update frequency should be "no more than 1Hz if you want your display to last for a long time." Ten minutes is fine, thank you.
+
+Here's what I wanted to be able to see at a glance:
+
+Hostname | And device serial number
+---|---
+IP address | Current internal IP address
+VPN status | Inactive/country/IP address
+Tor status | Inactive/IP address
+"Usage" | Percentage disk space and memory used
+Uptime | So satisfying to see those long uptimes
+
+And here it is: a display that's the same size as the Pi Zero and 1" deep.
+
+![PiZero Display][7]
+
+### How to populate the display
+
+Now I needed to populate the display. As seems to be the norm these days, the e-Ink support software is in Python, which, of course, is installed as standard with most Linux distros. _Disclaimer:_ Python is not my first (dev) language, but the code below works for me. It'll probably work for you, too.
+
+
+```
+#!/usr/bin/env python
+
+import os
+import sys
+import time
+import datetime
+import socket
+import netifaces as ni
+import psutil
+import subprocess
+
+from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET
+from papirus import PapirusText, PapirusTextPos, Papirus
+from subprocess import check_output
+from datetime import timedelta
+
+rot = 0
+screen = Papirus(rotation = rot)
+fbold = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf'
+fnorm = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf'
+text = PapirusTextPos(rotation = rot)
+
+def GetBootTime():
+ return datetime.datetime.fromtimestamp(psutil.boot_time())
+
+def GetUptime():
+ with open('/proc/uptime','r') as f:
+ uptime_seconds = float(f.readline().split()[0])
+ u = str(timedelta(seconds = uptime_seconds))
+ duration,junk = u.split(".")
+ hr,mi,sc = duration.split(":")
+ return "%sh %sm %ss" % ( hr,mi,sc )
+
+def getHostname():
+ hostname = socket.gethostname()
+ return hostname
+
+def getWiFiIPaddress():
+ try:
+ ni.interfaces()
+ [ 'wlan0', ]
+ return ni.ifaddresses('wlan0')[AF_INET][0]['addr']
+ except:
+ return 'inactive'
+
+def getVPNIPaddress():
+ try:
+ ni.interfaces()
+ [ 'tun0', ]
+ return ni.ifaddresses('tun0')[AF_INET][0]['addr']
+ except:
+ return 'inactive'
+
+def GetTmuxEnv():
+ if 'TMUX_PANE' in os.environ:
+ return ' (t)'
+ return ' '
+
+def GetCPUserial():
+ cpuinfo = subprocess.check_output(["/bin/cat", "/proc/cpuinfo"])
+ cpuinfo = cpuinfo.replace("\t","")
+ cpuinfo = cpuinfo.split("\n")
+ [ legend, cpuserial ] = cpuinfo[12].split(' ')
+ cpuserial = cpuserial.lstrip("0")
+ return cpuserial
+
+def GetMemUsed():
+ memUsed = psutil.virtual_memory()[2]
+ return memUsed
+
+def GetDiskUsed():
+ diskUsed = psutil.disk_usage('/')[3]
+ return diskUsed
+
+def CheckTor():
+ try:
+ TS = "active: pid %s" %check_output(['pidof','tor'])
+ except:
+ TS = 'inactive'
+ return TS
+
+def CheckVPN():
+ return VPNlo
+# ---------------------------------------------------------------------------
+def main():
+ pass
+
+if __name__ == '__main__':
+ main()
+
+VPNlo = 'inactive'
+
+if (len(sys.argv) == 2):
+ try:
+ VPNlo = sys.argv[1]
+ except:
+ VPNlo = 'inactive'
+
+text = PapirusTextPos(False,rotation=rot)
+text.AddText("%s %s %s"% (getHostname(),GetCPUserial(),GetTmuxEnv()),x=1,y=0,size=12,invert=True,fontPath=fbold)
+text.AddText("IP %s" % getWiFiIPaddress(),x=1,y=16,size=12,fontPath=fnorm)
+if ( getVPNIPaddress() == 'inactive' ):
+ text.AddText("VPN %s" % CheckVPN(),x=1,y=30,size=12,fontPath=fnorm)
+else:
+ text.AddText("VPN %s" % getVPNIPaddress(),x=1,y=30,size=12,fontPath=fnorm)
+text.AddText("TOR %s" % CheckTor(),x=1,y=44,size=12,fontPath=fnorm)
+text.AddText("MEM %s% DISK %s% used" % (GetMemUsed(),GetDiskUsed()),x=1,y=58,size=12,fontPath=fnorm,maxLines=1)
+text.AddText("UPTIME %s" % GetUptime(),x=1,y=72,size=12,fontPath=fnorm)
+text.WriteAll()
+
+sys.exit(0)
+```
+
+Normally, the script runs without any arguments and is called by a series of Bash scripts that I've written to start up various subsystems; these are, in turn, called from a menu system written in Whiptail, which is pretty versatile. In the case of the VPN system, I have a list of access points to choose from and that update the location on the display. Initially, I call the display updater with the location name (e.g., Honolulu), but at that point, I can't display the VPN IP address because I don't know it:
+
+
+```
+ dispupdate.py ${accesspoint}
+ openvpn --config $PATH/Privacy-${accesspoint}.conf --auth-user-pass credfile
+```
+
+When the display updater runs again (outside the VPN startup script), the IP address is readable from the **tun0** interface and the display is updated with the IP address. I may change this later, but it works fine now. I use the **PapirusTextPos** function (rather than **PapirusText**), as this allows multiple lines to be written before the display is updated, leading to a much faster write. The **text.WriteAll()** function does the actual update.
+
+### Adding more software
+
+I was very pleased with my initial choice of applications, but since I'd managed to slim the whole installation down to 1.7GB, I had plenty of available space. So, I decided to see if there was anything else that could be useful. Here's what I added:
+
+Irssi | IRC client
+---|---
+FreeBSD games | There are still many text-mode games to enjoy
+nmon | A _very_ comprehensive top-alike utility for all aspects of the system
+Newsbeuter | Text-mode Atom/RSS feed reader
+
+And I still have about 300MB free space to take me up to 2GB, so I may add more.
+
+### We keed to talk about ~~Kevin~~ Bluetooth
+
+Observant readers will remember my hatred for Bluetooth and trying to pair terminal-based software with a Bluetooth device. When I bought a new Pi, I realized that I had to pair the damn thing up with the keyboards again. Oh, woe is me! But a search-engine session and a calming coffee enabled me to actually do it! It goes something like this:
+
+
+```
+sudo su
+bluetoothctl {enter}
+
+[bluetooth]#
+
+[bluetooth]# scan on
+Discovery started
+[CHG] Controller B8:27:EB:XX:XX:XX Discovering: yes
+
+[bluetooth]# agent on
+Agent registered
+[NEW] Device B2:2B:XX:XX:XX:XX Bluetooth Keyboard
+Attempting to pair with B2:2B:XX:XX:XX:XX
+[CHG] Device B2:2B:XX:XX:XX:XX Connected: yes
+[agent] PIN code: 834652
+[CHG] Device B2:2B:XX:XX:XX:XX Modalias: usb:v05ACp0220d0001
+[CHG] Device B2:2B:XX:XX:XX:XX UUIDs: zzzzz
+[CHG] Device B2:2B:XX:XX:XX:XX UUIDs: yyyyy
+[CHG] Device B2:2B:XX:XX:XX:XX ServicesResolved: yes
+[CHG] Device B2:2B:XX:XX:XX:XX Paired: yes
+Pairing successful
+[CHG] Device B2:2B:XX:XX:XX:XX ServicesResolved: no
+[CHG] Device B2:2B:XX:XX:XX:XX Connected: no
+
+[bluetooth]# trust B2:2B:XX:XX:XX:XX
+[CHG] Device B2:2B:XX:XX:XX:XX Trusted: yes
+Changing B2:2B:XX:XX:XX:XX trust succeeded
+[CHG] Device B2:2B:XX:XX:XX:XX RSSI: -53
+
+[bluetooth]# scan off
+[CHG] Device B2:2B:XX:XX:XX:XX RSSI is nil
+Discovery stopped
+[CHG] Controller B8:27:EB:XX:XX:XX Discovering: no
+
+[bluetooth]# exit
+Agent unregistered
+
+$
+```
+
+I was gobsmacked! No, really. I paired my other keyboard and am now considering pairing a speaker, but we'll see. I had a beer that night to celebrate my new-found "l33t" tech skills! Here is an [excellent guide][8] on how to do it.
+
+### One more hardware mod
+
+Until recently, I've been using as large a good-quality microSDHC card as I could afford, and in case of problems, I created a backup copy using the rsync-based rpi-clone. However, after reading various articles on the 'net where people complain about corrupted cards due to power problems, unclean shutdowns, and other mishaps, I decided to invest in a higher-quality card that hopefully will survive all this and more. This is important if you're traveling long distances and _really_ need your software to work at the destination.
+
+After a long search, I found the [ATP Industrial-Grade MicroSD/MicroSDHC][9] cards, which are rated military-spec for demanding applications. That sounded perfect. However, with quality comes a cost, as well as (in this case) limited capacity. In order to keep my wallet happy, I limited myself to an 8GB card, which may not sound like a lot for a working computer, but bearing in mind I have a genuine 5.3GB of that 8GB free, it works just fine. I also have a level of reassurance that bigger but lower-quality cards can't give me, and I can create an ISO of that card that's small enough to email if need be. Result!
+
+### What's next?
+
+The Zero goes from strength to strength, only needing to go out more. I've gone technically about as far as I can for now, and any other changes will be small and incremental.
+
+* * *
+
+_This was originally published on [Peter Garner's blog][10] under a CC BY-NC-ND 4.0 and is reused here with the author's permission._
+
+The new issue of the official Raspberry Pi magazine, The MagPi, comes with a free computer stuck to...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/pi-zero-display
+
+作者:[Peter Garner][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petergarner
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/zero-osdc-lead.png?itok=bK70ON2W (Pi Zero)
+[2]: https://opensource.com/article/20/3/raspberry-pi-zero-w-road
+[3]: https://petergarner.net/notes/index.php?thisnote=20180511-Travels+with+a+Pi+%282%29
+[4]: https://www.modmypi.com/raspberry-pi/screens-and-displays/epaper/papirus-zero-epaper--eink-screen-phat-for-pi-zero-medium
+[5]: https://www.modmypi.com/raspberry-pi/cases-183/accessories-1125/watch-straps/pi-supply-papirus-zero-case
+[6]: https://github.com/PiSupply/PaPiRus
+[7]: https://opensource.com/sites/default/files/uploads/pizerodisplay.jpg (PiZero Display)
+[8]: https://www.sigmdel.ca/michel/ha/rpi/bluetooth_01_en.html
+[9]: https://www.digikey.com/en/product-highlight/a/atp/industrial-grade-microsd-microsdhc-cards
+[10]: https://petergarner.net/notes/index.php?thisnote=20190205-Travels+with+a+Pi+%283%29
diff --git a/sources/tech/20200315 Getting started with shaders- signed distance functions.md b/sources/tech/20200315 Getting started with shaders- signed distance functions.md
new file mode 100644
index 0000000000..acba8687fd
--- /dev/null
+++ b/sources/tech/20200315 Getting started with shaders- signed distance functions.md
@@ -0,0 +1,243 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting started with shaders: signed distance functions!)
+[#]: via: (https://jvns.ca/blog/2020/03/15/writing-shaders-with-signed-distance-functions/)
+[#]: author: (Julia Evans https://jvns.ca/)
+
+Getting started with shaders: signed distance functions!
+======
+
+Hello! A while back I learned how to make fun shiny spinny things like this using shaders:
+
+![][1]
+
+My shader skills are still extremely basic, but this fun spinning thing turned out to be a lot easier to make than I thought it would be to make (with a lot of copying of code snippets from other people!).
+
+The big idea I learned when doing this was something called “signed distance functions”, which I learned about from a very fun tutorial called [Signed Distance Function tutorial: box & balloon][2].
+
+In this post I’ll go through the steps I used to learn to write a simple shader and try to convince you that shaders are not that hard to get started with!
+
+### examples of more advanced shaders
+
+If you haven’t seen people do really fancy things with shaders, here are a couple:
+
+ 1. this very complicated shader that is like a realistic video of a river:
+ 2. a more abstract (and shorter!) fun shader with a lot of glowing circles:
+
+
+
+### step 1: my first shader
+
+I knew that you could make shaders on shadertoy, and so I went to . They give you a default shader to start with that looks like this:
+
+![][3]
+
+Here’s the code:
+
+```
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+ // Normalized pixel coordinates (from 0 to 1)
+ vec2 uv = fragCoord/iResolution.xy;
+
+ // Time varying pixel color
+ vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
+
+ // Output to screen
+ fragColor = vec4(col,1.0);
+}
+```
+
+This doesn’t do anythign that exciting, but it already taught me the basic structure of a shader program!
+
+### the idea: map a pair of coordinates (and time) to a colour
+
+The idea here is that you get a pair of coordinates as an input (`fragCoord`) and you need to output a RGBA vector with the colour of that. The function can also use the current time (`iTime`), which is how the picture changes over time.
+
+The neat thing about this programming model (where you map a pair of coordinates and the time to) is that it’s extremely trivially parallelizable. I don’t understand a lot about GPUs but my understanding is that this kind of task (where you have 10000 trivially parallelizable calculations to do at once) is exactly the kind of thing GPUs are good at.
+
+### step 2: iterate faster with `shadertoy-render`
+
+After a while of playing with shadertoy, I got tired of having to click “recompile” on the Shadertoy website every time I saved my shader.
+
+I found a command line tool that will watch a file and update the animation in real time every time I save called [shadertoy-render][4]. So now I can just run:
+
+```
+shadertoy-render.py circle.glsl
+```
+
+and iterate way faster!
+
+### step 3: draw a circle
+
+Next I thought – I’m good at math! I can use some basic trigonometry to draw a bouncing rainbow circle!
+
+I know the equation for a circle (`x**2 + y**2 = whatever`!), so I wrote some code to do that:
+
+![][5]
+
+Here’s the code: (which you can also [see on shadertoy][6])
+
+```
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+ // Normalized pixel coordinates (from 0 to 1)
+ vec2 uv = fragCoord/iResolution.xy;
+ // Draw a circle whose center depends on what time it is
+ vec2 shifted = uv - vec2((sin(iGlobalTime) + 1)/2, (1 + cos(iGlobalTime)) / 2);
+ if (dot(shifted, shifted) < 0.03) {
+ // Varying pixel colour
+ vec3 col = 0.5 + 0.5*cos(iGlobalTime+uv.xyx+vec3(0,2,4));
+ fragColor = vec4(col,1.0);
+ } else {
+ // make everything outside the circle black
+ fragColor = vec4(0,0,0,1.0);
+ }
+}
+```
+
+This takes the dot product of the coordinate vector `fragCoord` with itself, which is the same as calculating `x^2 + y^2`. I played with the center of the circle a little bit in this one too – I made the center `vec2((sin(iGlobalTime) + 1)/2, (1 + cos(faster)) / 2)`, which means that the center of the circle also goes in a circle depending on what time it is.
+
+### shaders are a fun way to play with math!
+
+One thing I think is fun about this already (even though we haven’t done anything super advanced!) is that these shaders give us a fun visual way to play with math – I used `sin` and `cos` to make something go in a circle, and if you want to get some better intuition about how trigonometric work, maybe writing shaders would be a fun way to do that!
+
+I love that you get instant visual feedback about your math code – if you multiply something by 2, things get bigger! or smaller! or faster! or slower! or more red!
+
+### but how do we do something really fancy?
+
+This bouncing circle is nice but it’s really far from the super fancy things I’ve seen other people do with shaders. So what’s the next step?
+
+### idea: instead of using if statements, use signed distance functions!
+
+In my circle code above, I basically wrote:
+
+```
+if (dot(uv, uv) < 0.03) {
+ // code for inside the circle
+} else {
+ // code for outside the circle
+}
+```
+
+But the problem with this (and the reason I was feeling stuck) is that it’s not clear how it generalizes to more complicated shapes! Writing a bajillion if statements doesn’t seem like it would work well. And how do people render those 3d shapes anyway?
+
+So! **Signed distance functions** are a different way to define a shape. Instead of using a hardcoded if statement, instead you define a **function** that tells you, for any point in the world, how far away that point is from your shape. For example, here’s a signed distance function for a sphere.
+
+```
+float sdSphere( vec3 p, float center )
+{
+ return length(p)-center;
+}
+```
+
+Signed distance functions are awesome because they’re:
+
+ * simple to define!
+ * easy to compose! You can take a union / intersection / difference with some simple math if you want a sphere with a chunk taken out of it.
+ * easy to rotate / stretch / bend!
+
+
+
+### the steps to making a spinning top
+
+When I started out I didn’t understand what code I needed to write to make a shiny spinning thing. It turns out that these are the basic steps:
+
+ 1. Make a signed distance function for the shape I want (in my case an octahedron)
+ 2. Raytrace the signed distance function so you can display it in a 2D picture (or raymarch? The tutorial I used called it raytracing and I don’t understand the difference between raytracing and raymarching yet)
+ 3. Write some code to texture the surface of your shape and make it shiny
+
+
+
+I’m not going to explain signed distance functions or raytracing in detail in this post because I found this [AMAZING tutorial on signed distance functions][2] that is very friendly and honestly it does a way better job than I could do. It explains how to do the 3 steps above and the code has a ton of comments and it’s great.
+
+ * The tutorial is called “SDF Tutorial: box & balloon” and it’s here:
+ * Here are tons of signed distance functions that you can copy and paste into your code (and ways to compose them to make other shapes)
+
+
+
+### step 4: copy the tutorial code and start changing things
+
+Here I used the time honoured programming practice here of “copy the code and change things in a chaotic way until I get the result I want”.
+
+My final shader of a bunch of shiny spinny things is here:
+
+The animation comes out looking like this:
+
+![][7]
+
+Basically to make this I just copied the tutorial on signed distance functions that renders the shape based on the signed distance function and:
+
+ * changed `sdfBalloon` to `sdfOctahedron` and made the octahedron spin instead of staying still in my signed distance function
+ * changed the `doBalloonColor` colouring function to make it shiny
+ * made there be lots of octahedrons instead of just one
+
+
+
+### making the octahedron spin!
+
+Here’s some the I used to make the octahedron spin! This turned out to be really simple: first copied an octahedron signed distance function from [this page][8] and then added a `rotate` to make it rotate based on time and then suddenly it’s spinning!
+
+```
+vec2 sdfOctahedron( vec3 currentRayPosition, vec3 offset ){
+ vec3 p = rotate((currentRayPosition), offset.xy, iTime * 3.0) - offset;
+ float s = 0.1; // what is s?
+ p = abs(p);
+ float distance = (p.x+p.y+p.z-s)*0.57735027;
+ float id = 1.0;
+ return vec2( distance, id );
+}
+```
+
+### making it shiny with some noise
+
+The other thing I wanted to do was to make my shape look sparkly/shiny. I used a noise funciton that I found in [this github gist][9] to make the surface look textured.
+
+Here’s how I used the noise function. Basically I just changed parameters to the noise function mostly at random (multiply by 2? 3? 1800? who knows!) until I got an effect I liked.
+
+```
+float x = noise(rotate(positionOfHit, vec2(0, 0), iGlobalTime * 3.0).xy * 1800.0);
+float x2 = noise(lightDirection.xy * 400.0);
+float y = min(max(x, 0.0), 1.0);
+float y2 = min(max(x2, 0.0), 1.0) ;
+vec3 balloonColor = vec3(y , y + y2, y + y2);
+```
+
+### writing shaders is fun!
+
+That’s all! I had a lot of fun making this thing spin and be shiny. If you also want to make fun animations with shaders, I hope this helps you make your cool thing!
+
+As usual with subjects I don’t know tha well, I’ve probably said at least one wrong thing about shaders in this post, let me know what it is!
+
+Again, here are the 2 resources I used:
+
+ 1. “SDF Tutorial: box & balloon”: (which is really fun to modify and play around with)
+ 2. Tons of signed distance functions that you can copy and paste into your code
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://jvns.ca/blog/2020/03/15/writing-shaders-with-signed-distance-functions/
+
+作者:[Julia Evans][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://jvns.ca/
+[b]: https://github.com/lujun9972
+[1]: https://jvns.ca/images/spinny.gif
+[2]: https://www.shadertoy.com/view/Xl2XWt
+[3]: https://jvns.ca/images/colour.gif
+[4]: https://github.com/alexjc/shadertoy-render
+[5]: https://jvns.ca/images/circle.gif
+[6]: https://www.shadertoy.com/view/tsscR4
+[7]: https://jvns.ca/images/octahedron2.gif
+[8]: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
+[9]: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
diff --git a/sources/tech/20200315 How I migrated from a Mac Mini to a Raspberry Pi.md b/sources/tech/20200315 How I migrated from a Mac Mini to a Raspberry Pi.md
new file mode 100644
index 0000000000..0e1c7196fa
--- /dev/null
+++ b/sources/tech/20200315 How I migrated from a Mac Mini to a Raspberry Pi.md
@@ -0,0 +1,184 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I migrated from a Mac Mini to a Raspberry Pi)
+[#]: via: (https://opensource.com/article/20/3/mac-raspberry-pi)
+[#]: author: (Peter Garner https://opensource.com/users/petergarner)
+
+How I migrated from a Mac Mini to a Raspberry Pi
+======
+Learn more about Linux by turning a Raspberry Pi Model 2 into a workable
+desktop computer.
+![Vector, generic Raspberry Pi board][1]
+
+Some time ago, I decided to move my computing environment from a Mac Mini PowerPC to a Raspberry Pi Model 2. This article describes my reasons for doing so and how I did it. While it is quite technical in places, if you're considering switching from an existing system to something decidedly lean and mean, there are things that you need to know before making that leap. There are lots of links to click as well, which will lead you to the software and apps that I mention.
+
+Enjoy!
+
+## Saying goodbye to the Mac
+
+I have to admit, I've never really been an Apple fanboi, especially following a short (and ultimately unsatisfactory) fling with a plastic polycarbonate MacBook back in 2006. Although it was beautifully designed, and the software "Just Worked," I was understandably upset when it decided to expire shortly after the warranty period expired (design faults, apparently). Ah well.
+
+I swore never to "invest" in an Apple machine again—until I discovered a used Mac Mini PowerPC on eBay that could be had for around $100 in 2012. It was new back in 2005 but had apparently been refurbished. "What have I got to lose, especially at that price?" I asked myself. Nobody answered, so I placed a last-minute bid, won it, and invested about the same sum of money again in bumping the memory up to 1GB and buying the OS on DVD. The OS X version was 10.4.7 Tiger, and the architecture was Power PC. It was sedate but reliable, and I was happy. It didn't take a lot of power either; some 60 watts at full load, so that was a bonus. I spent many happy hours tinkering with it and trying to find software that was supported on a device that old.
+
+Predictably though, as my computing requirements grew and the Mac got older, it started to get noticeably slower, and I was aware that even simple tasks—such as asking it to run a web browser and display an HTTPS page—were causing it problems. When I finally managed to find antivirus software for it, I became aware of just how noisy the Mini's cooling fan was as the CPU struggled with the extra load.
+
+A quick check of the performance monitors revealed thousands of memory-paging faults, and I realized that my old friend was soon destined for the knackers yard. Of course, that meant searching for a replacement, and that's when the fun started.
+
+## A(nother) small computer
+
+My main problem was that I didn't have a big budget. I looked at eBay again and found a number of Mac Minis for sale, all around the $500 mark, and many of those were early basic-spec Intel units that, like my old Mac, people had simply grown out of. Essentially, I wanted something like the old Mini, ideally with similar power consumption. A new one was out of the question, obviously.
+
+Let me state that my computer requirements are pretty undemanding, and for photo/graphics work, I have another computer that consumes power like there's no tomorrow and gives off enough heat to keep me warm in winter. And then I got to thinking about the [Raspberry Pi Model 2][2]. Now before you laugh, I have around six of the things running various servers, and they do just fine. One runs a small web server, another runs a mail server, and so on. Each one costs around $30, and most use a cheap microSDHC card, so if one fails, I can easily swap it out for another, and I can usually buy a suitable card at a local supermarket—try doing that when your laptop drive fails! I also have a Netgear ReadyNAS 102 with a couple of 2TB hard drives to act as my bulk storage.
+
+Suddenly, my plan looked as though it might be viable after all!
+
+## Spec'ing it out
+
+The specification was a bit of a no-brainer: The Model 2 Pi comes with 1GB of memory standard, the Ethernet runs at 100Mbps maximum, the clock speed is 900MHz, there are four USB ports, and that's yer lot, mate. You can overclock it, but I've never wanted to try this for various reasons.
+
+I had a Pi in my spares drawer, so no problem there. I ordered a posh aluminum case made by [Flirc][3] that was on offer for $20 and duly slotted in the Pi. The power supply unit (PSU) had to be a genuine two-amp device, and again, I had a spare lying around. If you take your Pi ownership seriously, I recommend the [Anker 40W][4] five-port desktop charger: it has intelligent power management, and I'm running five Pis from one unit. Incidentally, if you inadvertently use a PSU that can't deliver the required current, you'll keep seeing a square, multi-colored icon in the top-right corner of your screen, so be warned.
+
+The microSDHC "disk" was more of an issue, though. I always use SanDisk, and this time I wanted something fast, especially as this was to be a "desktop" machine. In the end, I went for a [SanDisk 8GB Extreme Pro UHS-1][5] card that promised up to 90 to 95 Mbps write/read performance. "8GB? That's not a lot of space," I hear you Windows users cry, and because this is Linux, there doesn't need to be.
+
+The way I envisioned it, I'd set up the Pi normally and use it primarily as a boot disk. I'd host all my documents and media files on the network-attached storage (NAS) box, and all would be well. The NAS shares would be accessed via network filesystem (NFS), and I'd just mount them as directories on the Pi.
+
+Quite early on, I elected to move my entire home directory onto the NAS, and this has worked well, with some quirks. The problem I faced was a Pi quirk, and although I was sure there was a fix, I wanted to get it up and running before the Mac finally crapped out. When the Pi boots, it seems to enable the networking part quite late in the sequence, and I found that I couldn't do my NFS mounts because the networking interface hadn't come up yet. Rather than hack around with tricky scripts, I decided to simply mount the NFS shares by hand after I'd logged in after a successful boot. This seemed to work, and it's the solution I'm using now. Now that I had a basic strategy, it was time to implement it on the "live" machine.
+
+That's the beauty of working with the Raspberry Pi—you can quickly hack together a testbed and have a system up and running in under 30 minutes.
+
+Regarding video, I bought an HDMI-to-DVI cable to use with my Dell monitor, and in GUI desktop mode, this comes up as 1280x1024—plenty good enough for my use. If you have a monster flat-screen TV, you can always use that instead.
+
+## My software environment
+
+### Operating system
+
+I ultimately decided on [Arch Linux for ARM][6] 7H as the operating system. I'm a [Raspbian][7] veteran, but I didn't need the educational software that comes with it (I have other Pis for that). Arch provides a minimal environment but is full-featured, well-supported, and powerful; it also has bucket-loads of software available. After its initial installation, I'd used just over 1.2GB of space, and even now, with all my software on the microSDHC, I'm only using 2.8GB of my 8GB card. Please note that the Pi 2 is officially Arch Linux ARM 7, not 6.
+
+### Desktop
+
+I wanted a graphical desktop environment (even though I'm a command-line sorta guy), but it needed to be in keeping with the lean and mean ethos. I'd used [LXDE][8] before and was happy with it, so I installed it; GNOME and KDE were just too big.
+
+### Web browser
+
+The web browser was a bit of a problem, but after trying the default Midori, Epiphany, and a couple of others, I decided on [Firefox][9]. It's a bit flabby, but it follows standards well, and if you're going to digitally sign LibreOffice ODT documents, you'll need it anyway. One problem on a machine of this power is the tremendous toll that web-based ads place on the overall memory usage. In fact, a badly ad'ed page can make the browser stop completely, so I had to make those ads disappear. One way would be to install an ad-blocker plugin, but that's another hit on available memory, so a simpler method was called for.
+
+As this is a Linux box, I simply downloaded an [ad-blocking hosts file][10]. This is an amazing piece of community work that consists of over 15,000 hostnames for basically any server that spits out ads. All the entries point to an IP address of 0.0.0.0, so there's no time wasted and your bandwidth's your own again. It's a free download and can be added to the end of an existing hosts file. Of course, the major value, as far as I'm concerned, is that page load times are much quicker.
+
+The screen capture below shows an ad-free Firefox overlaid with the same page in [ELinks][11].
+
+![Firefox and eLinks browsers on Raspberry Pi][12]
+
+No ads in either, but if you don't need all the eye candy rendered by Firefox, ELinks will provide a super-clean experience. (Normally, all that whitespace in the Firefox image is filled with ads.) The ELinks browser is an interesting hybrid browser that is primarily text-based and is similar to the classic pure-text Lynx browser.
+
+### Messaging
+
+It would be overkill, and undesirable from a security point of view, to have Microsoft Skype on the Pi, so I decided on a Jabber/XMPP client, [Psi][13]. Psi has the advantage of not having a multitude of dependencies, and it also works really well. It's easy to take part in multi-user chats, and I have another Pi hosting a Jabber server to test it on. There's no character-mode version, unfortunately, and most of the text-based clients I tried had problems, so it's a GUI-only situation at the moment. No matter; it works well and doesn't use a lot of resources.
+
+### Email
+
+I also tried a number of email applications: this was easily the most important application. Eventually, I chose [Claws Mail][14]. Sadly, it doesn't do HTML mail, but it's rock-solid reliable. I have to say that I can't get the GNU Privacy Guard (GPG) plugin working properly yet due to some unresolved version issues, but I can always encrypt messages in a terminal, if need be.
+
+### Audio
+
+Music is important to me, and I chose [SMPlayer][15] as my media player. It supports many options, including playlists for local and networked files and internet radio streaming. It does the job well.
+
+### Video
+
+I'll not go into the video player in any great detail. Bearing in mind the hardware specs of the Pi, reliably playing back a video stream, even on the same network, was problematic. I decided that if I wanted to watch videos, I had other devices more suited to it. I did try and experiment with the **gpu_mem** setting in the **[/boot/config.txt][16]**, switching it from the default 64MB to 96MB. I was prepared to borrow a bit of application memory for the video player, but even that didn't seem to make it work well. In the end, I kept that setting so that the desktop environment would run more smoothly, and so far, I haven't had problems. The irony of this is that I have another Pi that has a [DLNA][17] server installed, and this can stream video exceedingly well—not just to one client, but several. In its defense, though, it doesn't have a desktop environment to contend with. So, for now, I don't bother trying to play video.
+
+### Image processing
+
+I need to do simple, lightweight photo and image editing, and I knew from prior experience that GIMP and similar packages would bring the Pi to its knees. I found an app called [Pinta][18], which resembles an enhanced Microsoft Paint, but with more cojones. As someone with a large image collection, I also needed a slideshow application. After much evaluation, I decided on [feh][19]. Normally run from a terminal within the GUI desktop, it has an incredible array of options that can help you produce an image slideshow, and again, it has low memory requirements.
+
+### Office suite
+
+And then there was an office suite. On the old Mac Mini, I was happily (and legally) running a copy of Microsoft Mac Office 2004, and I was truly sorry to lose that. I just needed a Microsoft Word and Excel equivalent, but I had to bear in mind the Pi's limitations. Sure, there are standalone versions of word-processor and spreadsheet applications, but there was nothing that really gave me confidence that I could edit a full-featured document.
+
+I already knew of [LibreOffice][20], but I had my doubts about it because of its Java Runtime Environment (JRE) requirement, or so I thought. Thankfully, JRE was optional, and as long as I didn't want to use (database) connection pooling of macros, there was no need to enable it. I also used as many built-in options as possible, rejecting skins and themes; this brought the overall memory footprint down to a reasonable level, and hey, I'm writing this on LibreOffice Writer now! I adopted the attitude that if it has a built-in theme, use it!
+
+Here's the current [memory overview][21] (in MB) from within the GUI desktop:
+
+![Raspberry Pi GUI memory usage][22]
+
+### Miscellaneous
+
+Other desktop software I've installed (not much as I wanted in order to keep this a minimal installation) is:
+
+ * [FileZilla][23]: SFTP/FTP client
+ * [PuTTY][24]: SSH/telnet terminal frontend
+ * [Mousepad][25]: A versatile plain-text editor, similar to Wordpad or Notepad, but much more powerful **[Note: this link was broken. Is this ok?]**
+
+
+
+Overall, the entire setup works as intended. I've found that it performs well, if a little slow sometimes, but this is to be expected, as it's running on a Raspberry Pi with a 900MHz clock speed and 1GB of memory. As long you're aware of and prepared to accept the limitations, you can have a cheap, very functional system that doesn't take up all your desk space.
+
+## Lacking in characters
+
+Life with a Pi desktop is not all about the GUI; it's a very competent command-line environment too, should you need one. As a Linux developer and geek, I am very comfortable in a character-mode environment, and this is where the Pi really comes into its own. The performance you can expect in the command-line environment, at least in my configuration, is dependent on a number of factors. I'm limited to a certain extent by the Pi's network-interface speed and the overall performance of my Netgear ReadyNAS 102, another slightly underpowered, consumer-grade ARM box. The one thing that did please me, though, was the noticeable increase in speed over the Mac Mini!
+
+Running in a native terminal environment, this is the typical memory usage (in MB) you might expect:
+
+![Raspberry Pi terminal memory usage][26]
+
+One thing to note is the lack of a swap partition. It's generally accepted that any type of swap system on a Raspberry Pi is a Very Bad Thing™ and will wear out your SD card in no time. I considered setting up a swap partition on the NAS box, but I ruled this out early on, as it would very negatively impact the network as a whole, and as with the NFS mount issue, the swap partition would need to be mounted before the network came up. So no go.
+
+Having lived with Raspberry Pis for some time now, let's just say that one has to learn to set things up carefully in the first place to avoid the need, and ultimately, it can teach you to manage computers better.
+
+As part of my efforts to make the Pi as useful as possible, I had to envision a scenario where whatever I was working on was either so resource-hungry that I couldn't run a GUI desktop or the GUI was just not required. That meant reproducing as many of the desktop-only apps in a character-mode environment. In fact, this was easier than finding the equivalent desktop apps.
+
+Here is my current lineup:
+
+ * **File manager:** [Midnight Commander][27]; if you're old enough to remember Norton Commander, you'll know what it looks like.
+ * **File transfer:** SSH/SFTP; normally handled by PuTTY and FileZilla on the desktop, you just use these two commands as provided.
+ * **Web browser:** Lynx or Links are classic character-mode browsers that significantly speed up the internet experience.
+ * **Music player:** Yes, you can play music in a character-mode terminal! [Mpg123][28] is the name of the app, and when it's run as **mpg123 -C**, it allows full keyboard control of all playback functions. If you want to be really cool, you can alter the way Midnight Commander handles MP3 files by editing **/etc/mc/mc.ext** and adding the code snippet below. This allows you to browse and play your music collection with ease. [code] shell/i/.mp3
+ Open=/usr/bin/mpg123 -C %f
+ View=%view{ascii} /usr/lib/mc/ext.d/sound.sh view mp3
+```
+ * **Office:** Don't be silly! Oh wait, though; I installed the character-mode spreadsheet app called **sc** (Supercalc?), and there's always Vi if you want to edit a text document, but don't expect to able to edit any Microsoft files. If your need is truly great, you can install a supplementary application called Antiword, which will let you view a .doc file.
+ * **Email:** A bit of a problem, as the Claws Mail mailbox format is not directly compatible with my character-mode app of choice, Mutt. There's a workaround, but I'm only going to do it if I get some spare time. For sending quick emails, I installed ssmtp, which is described as "a send-only sendmail emulator for machines which normally pick their mail up from a centralized mail hub." The setup is minimal, and overhead is practically nil, as normally it's invoked only when mail is being sent. So, you can do things like typing **echo "The donuts are on my desk" | mail -s"Important News" [everybody@myoffice.com][29]** from the command line without firing up a GUI mail app.
+
+
+
+For everything else, it's just a question of flipping back to the GUI desktop. Speaking of which…
+
+![Raspberry Pi GUI desktop environment][30]
+
+Quite a busy screen, but the Raspberry Pi handles it well. Here, I'm using LibreOffice to write this article, there's a network status box, Firefox is on the mpg123 website, and there's a terminal running top showing how much memory (isn't) being used. The drop-down menu on the left shows the office suite apps.
+
+## Other scenarios and thoughts
+
+### What's where
+
+With any hybrid system like this, it's important to remember what is located where so that, in the event of any problems, recovery will be easier. In my current configuration, the microSDHC card contains only the operating system, and as much as possible, any system-configuration files are also on there. Your own userland data will be on the NAS in your home directory. Ideally, you should be to replace or update the software on the microSDHC without having any adverse effects on your computing environment as a whole, but in IT, it's never that straightforward.
+
+In the X11 GUI desktop system, although there is a default config file in **/etc/X11**, you will invariably have a customized version containing your own preferences. (This is by design.) Your own file on the NAS, however, will reference files on the microSDHC:
+
+![Location of files][31]
+
+The overall effect is that if you change one environment for another, you will invariably experience a change (or loss) in functionality. Hopefully, the changes will be minor, but you do need to be aware of the sometimes ambiguous links.
+
+Please remember that the **root** user will _always_ be on the microSDHC, and if your NAS box fails for any reason, you'll still be able to boot your system and at least do some recovery work.
+
+### NAS alternatives
+
+While I'm in my home office, I have full access to my NAS box, which represents what (in today's terminology) would be a personal cloud. I much prefer this solution to a commercial cloud that is invariably managed by a company of unknown origin, location, security, and motives. For those reasons, I will always host my data where I can see it and physically get to it as required. Having said that, you may not be as paranoid as I am and will want to hook up your Pi desktop to an external cloud share.
+
+In that case, using an NFS mount as a basis for your home directory should mean that it's simply a matter of editing your **/etc/fstab** to point the NFS client at a different location. In my setup, the NAS box is called, er, NASBOX, and the local NFS share mountpoint is called **/NASmount**. When you create your non-root user, you'll simply move their home directory to an existing directory called **/NASmount**:
+```
+
+
+NASBOX:/data/yourshare /NASmount nfs
+nfsvers=3,rsize=8192,wsize=8192,timeo=60,intr,auto 0 0
+
+mount -t nfs -v NASBOX:/data/yourshare /NASmount
+
+```
+and then your directory tree could look like this:
+```
+`/NASmount/home/user`
+```
+So, by simply changing the **/etc/fstab** entry, you could quickly be hooked up to someone else's cloud. This, as they say, is left as an exercise for the re
\ No newline at end of file
diff --git a/sources/tech/20200316 How to test failed authentication attempts with test-driven development.md b/sources/tech/20200316 How to test failed authentication attempts with test-driven development.md
new file mode 100644
index 0000000000..abe34d97e2
--- /dev/null
+++ b/sources/tech/20200316 How to test failed authentication attempts with test-driven development.md
@@ -0,0 +1,288 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to test failed authentication attempts with test-driven development)
+[#]: via: (https://opensource.com/article/20/3/failed-authentication-attempts-tdd)
+[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
+
+How to test failed authentication attempts with test-driven development
+======
+Mountebank makes it easier to test the "less happy path" in your code.
+![Programming keyboard.][1]
+
+Testing often begins with what we hope happens. In my [previous article][2], I demonstrated how to virtualize a service you depend on when processing the "happy path" scenario (that is, testing the outcome of a successful login attempt). But we all know that software fails in spectacular and unexpected ways. Now's the time to take a closer look into how to process the "less happy paths": what happens when someone tries to log in with the wrong credentials?
+
+In the first article linked above, I walked through building a user authentication module. (Now is a good time to review that code and get it up and running.) This module does not do all the heavy lifting; it mostly relies on another service to do those tougher tasks—enable user registration, store the user accounts, and authenticate the users. The module will only be sending HTTP POST requests to this additional service's endpoint; in this case, **/api/v1/users/login**.
+
+What do you do if the service you're dependent on hasn't been built yet? This scenario creates a blockage. In the previous post, I explored how to remove that blockage by using service virtualization enabled by [mountebank][3], a powerful test environment.
+
+This article walks through the steps required to enable the processing of user authentication in cases when a user repeatedly attempts to log in. The third-party authentication service allows only three attempts to log in, after which it ceases to service the HTTP request arriving from the offending domain.
+
+### How to simulate repeat requests
+
+Mountebank makes it very easy to simulate a service that listens on a network port, matches the method and the path defined in the request, then handles it by sending back an HTTP response. To follow along, be sure to get mountebank running as we [did in the previous article][2]. As I explained there, these values are declared as JSONs that are posted to ****, mountebank's endpoint for processing authentication requests.
+
+But the challenge now is how to simulate the scenario when the HTTP request keeps hitting the same endpoint from the same domain. This is necessary to simulate a user who submits invalid credentials (username and password), is informed they are invalid, tries different credentials, and is repeatedly rejected (or foolishly attempts to log in with the same credentials that failed on previous attempts). Eventually (in this case, after a third failed attempt), the user is barred from additional tries.
+
+Writing executable code to simulate such a scenario would have to model very elaborate processing. However, when using mountebank, this type of simulated processing is extremely simple to accomplish. It is done by creating a rolling buffer of responses, and mountebank responds in the order the buffer was created. Here is an example of one way to simulate repeat requests in mountebank:
+
+
+```
+{
+ "port": 3001,
+ "protocol": "http",
+ "name": "authentication imposter",
+ "stubs": [
+ {
+ "predicates": [
+ {
+ "equals": {
+ "method": "post",
+ "path": "/api/v1/users/login"
+ }
+ }
+ ],
+ "responses": [
+ {
+ "is": {
+ "statusCode": 200,
+ "body": "Successfully logged in."
+ }
+ },
+ {
+ "is": {
+ "statusCode": 400,
+ "body": "Incorrect login. You have 2 more attempts left."
+ }
+ },
+ {
+ "is": {
+ "statusCode": 400,
+ "body": "Incorrect login. You have 1 more attempt left."
+ }
+ },
+ {
+ "is": {
+ "statusCode": 400,
+ "body": "Incorrect login. You have no more attempts left."
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+The rolling buffer is simply an unlimited collection of JSON responses where each response is represented with two key-value pairs: **statusCode** and **body**. In this case, four responses are defined. The first response is the happy path (i.e., user successfully logged in), and the remaining three responses represent failed use cases (i.e., wrong credentials result in status code 400 and corresponding error messages).
+
+### How to test repeat requests
+
+Modify the tests as follows:
+
+
+```
+using System;
+using Xunit;
+using app;
+namespace tests
+{
+ public class UnitTest1
+ {
+ Authenticate auth = [new][4] Authenticate();
+ [Fact]
+ public void SuccessfulLogin()
+ {
+ var given = "valid credentials";
+ var expected = " Successfully logged in.";
+ var actual= auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact]
+ public void FirstFailedLogin()
+ {
+ var given = "invalid credentials";
+ var expected = "Incorrect login. You have 2 more attempts left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact]
+ public void SecondFailedLogin()
+ {
+ var given = “invalid credentials";
+ var expected = "Incorrect login. You have 1 more attempt left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact]
+ public void ThirdFailedLogin()
+ {
+ var given = " invalid credentials";
+ var expected = "Incorrect login. You have no more attempts left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ }
+}
+```
+
+Now, run the tests to confirm that your code still works:
+
+![Failed test][5]
+
+Whoa! The tests now all fail. Why?
+
+If you take a closer look, you'll see a revealing pattern:
+
+![Reason for failed test][6]
+
+Notice that ThirdFailedLogin is executed first, followed by the SuccessfulLogin, followed by FirstFailedLogin, followed by SecondFailedLogin. What's going on here? Why is the third test running before the first test?
+
+The testing framework ([xUnit][7]) is executing all tests in parallel, and the sequence of execution is unpredictable. You need tests to run in order, which means you cannot test these scenarios using the vanilla xUnit toolkit.
+
+### How to run tests in the right sequence
+
+To force your tests to run in a certain sequence that you define (instead of running in an unpredictable order), you need to extend the vanilla xUnit toolkit with the NuGet [Xunit.Extensions.Ordering][8] package. Install the package on the command line with:
+
+
+```
+`$ dotnet add package Xunit.Extensions.Ordering --version 1.4.5`
+```
+
+or add it to your **tests.csproj** config file:
+
+
+```
+``
+```
+
+Once that's taken care of, make some modifications to your **./tests/UnitTests1.cs** file. Add these four lines at the beginning of your **UnitTests1.cs **file:
+
+
+```
+using Xunit.Extensions.Ordering;
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
+[assembly: TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")]
+[assembly: TestCollectionOrderer("Xunit.Extensions.Ordering.CollectionOrderer", "Xunit.Extensions.Ordering")]
+```
+
+Now you can specify the order you want your tests to run. Initially, simulate the happy path (i.e., the **SuccessfulLogin()**) by annotating the test with:
+
+
+```
+[Fact, Order(1)]
+public void SuccessfulLogin() {
+```
+
+After you test a successful login, test the first failed login:
+
+
+```
+[Fact, Order(2)]
+public void FirstFailedLogin()
+```
+
+And so on. You can add the order of the test runs by simply adding the **Order(x)** (where **x** denotes the order you want the test to run) annotation to your Fact.
+
+This annotation guarantees that your tests will run in the exact order you want them to run, and now you can (finally!) completely test your integration scenario.
+
+The final version of your test is:
+
+
+```
+using System;
+using Xunit;
+using app;
+using Xunit.Extensions.Ordering;
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
+[assembly: TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")]
+[assembly: TestCollectionOrderer("Xunit.Extensions.Ordering.CollectionOrderer", "Xunit.Extensions.Ordering")]
+namespace tests
+{
+ public class UnitTest1
+ {
+ Authenticate auth = [new][4] Authenticate();
+ [Fact, Order(1)]
+ public void SuccessfulLogin()
+ {
+ var given = "[elon_musk@tesla.com][9]";
+ var expected = "Successfully logged in.";
+ var actual= auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact, Order(2)]
+ public void FirstFailedLogin()
+ {
+ var given = "[mickey@tesla.com][10]";
+ var expected = "Incorrect login. You have 2 more attempts left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact, Order(3)]
+ public void SecondFailedLogin()
+ {
+ var given = "[mickey@tesla.com][10]";
+ var expected = "Incorrect login. You have 1 more attempt left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ [Fact, Order(4)]
+ public void ThirdFailedLogin()
+ {
+ var given = "[mickey@tesla.com][10]";
+ var expected = "Incorrect login. You have no more attempts left.";
+ var actual = auth.Login(given);
+ Assert.Equal(expected, actual);
+ }
+ }
+}
+```
+
+Run the test again—everything passes!
+
+![Passing test][11]
+
+### What are you testing exactly?
+
+This article has focused on test-driven development (TDD), but let's review it from another methodology, Extreme Programming (XP). XP defines two types of tests:
+
+ 1. Programmer tests
+ 2. Customer tests
+
+
+
+So far, in this series of articles on TDD, I have focused on the first type of tests (i.e., programmer tests). In this and the previous article, I switched my lenses to examine the most efficient ways of doing customer tests.
+
+The important point is that programmer (or producer) tests are focused on precision work. We often refer to these precision tests as "micro tests," while others may call them "unit tests." Customer tests, on the other hand, are more focused on a bigger picture; we sometimes refer to them as "approximation tests" or "end-to-end tests."
+
+### Conclusion
+
+This article demonstrated how to write a suite of approximation tests that integrate several discrete steps and ensure that the code can handle all edge cases, including simulating the customer experience when repeatedly attempting to log in and failing to obtain the necessary clearance. This combination of TDD and tools like xUnit and mountebank can lead to well-tested and thus more reliable application development.
+
+In future articles, I'll look into other usages of mountebank for writing customer (or approximation) tests.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/failed-authentication-attempts-tdd
+
+作者:[Alex Bunardzic][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alex-bunardzic
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming_keyboard_coding.png?itok=E0Vvam7A (Programming keyboard.)
+[2]: https://opensource.com/article/20/3/service-virtualization-test-driven-development
+[3]: http://www.mbtest.org/
+[4]: http://www.google.com/search?q=new+msdn.microsoft.com
+[5]: https://opensource.com/sites/default/files/uploads/testfails_0.png (Failed test)
+[6]: https://opensource.com/sites/default/files/uploads/failurepattern.png (Reason for failed test)
+[7]: https://xunit.net/
+[8]: https://www.nuget.org/packages/Xunit.Extensions.Ordering/#
+[9]: mailto:elon_musk@tesla.com
+[10]: mailto:mickey@tesla.com
+[11]: https://opensource.com/sites/default/files/uploads/testpasses.png (Passing test)
diff --git a/sources/tech/20200316 How to upload an OpenStack disk image to Glance.md b/sources/tech/20200316 How to upload an OpenStack disk image to Glance.md
new file mode 100644
index 0000000000..82fb71244b
--- /dev/null
+++ b/sources/tech/20200316 How to upload an OpenStack disk image to Glance.md
@@ -0,0 +1,848 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to upload an OpenStack disk image to Glance)
+[#]: via: (https://opensource.com/article/20/3/glance)
+[#]: author: (Jair Patete https://opensource.com/users/jpatete)
+
+How to upload an OpenStack disk image to Glance
+======
+Make images available to your private cloud, and more.
+![blank background that says your image here][1]
+
+[Glance][2] is an image service that allows you to discover, provide, register, or even delete disk and/or server images. It is a fundamental part of managing images on [OpenStack][3] and [TripleO][4] (which stands for "OpenStack-On-OpenStack").
+
+If you have used a recent version of the OpenStack platform, you may already have launched your first Overcloud using TripleO, as you interact with Glance when uploading the Overcloud disk images inside the Undercloud's OpenStack (i.e., the node inside your cloud that is used to install the Overcloud, add/delete nodes, and do some other handy things).
+
+In this article, I'll explain how to upload an image to Glance. Uploading an image to the service makes it available for the instances in your private cloud. Also, when you're deploying an Overcloud, it makes the image(s) available so the bare-metal nodes can be deployed using them.
+
+In an Undercloud, execute the following command:
+
+
+```
+`$ openstack overcloud image upload --image-path /home/stack/images/`
+```
+
+This uploads the following Overcloud images to Glance:
+
+ 1. overcloud-full
+ 2. overcloud-full-initrd
+ 3. overcloud-full-vmlinuz
+
+
+
+After some seconds, the images will upload successfully. Check the result by running:
+
+
+```
+(undercloud) [stack@undercloud ~]$ openstack image list
++--------------------------------------+------------------------+--------+
+| ID | Name | Status |
++--------------------------------------+------------------------+--------+
+| 09ca88ea-2771-459d-94a2-9f87c9c393f0 | overcloud-full | active |
+| 806b6c35-2dd5-478d-a384-217173a6e032 | overcloud-full-initrd | active |
+| b2c96922-161a-4171-829f-be73482549d5 | overcloud-full-vmlinuz | active |
++--------------------------------------+------------------------+--------+
+```
+
+This is a mandatory and easy step in the process of deploying an Overcloud, and it happens within seconds, which makes it hard to see what's under the hood. But what if you want to know what is going on?
+
+One thing to keep in mind: Glance works using client-server communication carried through REST APIs. Therefore, you can see what is going on by using [tcpdump][5] to take some TCP packets.
+
+Another thing that is important: There is a database (there's always a database, right?) that is shared among all the OpenStack platform components, and it contains all the information that Glance (and other components) needs to operate. (In my case, MariaDB is the backend.) I won't get into how to access the SQL database, as I don't recommend playing around with it, but I will show what the database looks like during the upload process. (This is an entirely-for-test OpenStack installation, so there's no need to play with the database in this example.)
+
+### The database
+
+The basic flow of this example exercise is:
+
+_Image Created -> Image Queued -> Image Saved -> Image Active_
+
+You need permission to go through this flow, so first, you must ask OpenStack's identity service, [Keystone][6], for authorization. My Keystone catalog entry looks like this; as I'm in the Undercloud, I'll hit the public endpoint:
+
+
+```
+| keystone | identity | regionOne |
+| | | public: |
+| | | regionOne |
+| | | internal: |
+| | | regionOne |
+| | | admin: |
+```
+
+And for Glance:
+
+
+```
+| glance | image | regionOne |
+| | | public: |
+| | | regionOne |
+| | | internal: |
+| | | regionOne |
+| | | admin: |
+```
+
+I'll hit those ports and TCP port 3306 in the capture; the latter is so I can capture what's going on with the SQL database. To capture the packets, use the tcpdump command:
+
+
+```
+`$ tcpdump -nvs0 -i ens3 host 172.16.0.20 and port 13000 or port 3306 or port 13292`
+```
+
+Under the hood, this looks like:
+
+Authentication:
+
+**Initial request (discovery of API Version Information):**
+
+
+```
+`https://172.16.0.20:13000 "GET / HTTP/1.1"`
+```
+
+**Response:**
+
+
+```
+Content-Length: 268 Content-Type: application/json Date: Tue, 18 Feb 2020 04:49:55 GMT Location: Server: Apache Vary: X-Auth-Token x-openstack-request-id: req-6edc6642-3945-4fd0-a0f7-125744fb23ec
+
+{
+ "versions":{
+ "values":[
+ {
+ "id":"v3.13",
+ "status":"stable",
+ "updated":"2019-07-19T00:00:00Z",
+ "links":[
+ {
+ "rel":"self",
+ "href":""
+ }
+ ],
+ "media-types":[
+ {
+ "base":"application/json",
+ "type":"application/vnd.openstack.identity-v3+json"
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+**Authentication request**
+
+
+```
+`https://172.16.0.20:13000 "POST /v3/auth/tokens HTTP/1.1"`
+```
+
+After this step, a token is assigned for the admin user to use the services. (The token cannot be displayed for security reasons.) The token tells the other services something like: "I've already logged in with the proper credentials against Keystone; please let me go straight to the service and ask no more questions about who I am."
+
+At this point, the command:
+
+
+```
+`$ openstack overcloud image upload --image-path /home/stack/images/`
+```
+
+executes, and it is authorized to upload the image to the Glance service.
+
+The current status is:
+
+_**Image Created**_ _-> Image Queued -> Image Saved -> Image Active_
+
+The service checks whether this image already exists:
+
+
+```
+`https://172.16.0.20:13292 "GET /v2/images/overcloud-full-vmlinuz HTTP/1.1"`
+```
+
+From the client's point of view, the request looks like:
+
+
+```
+`curl -g -i -X GET -H 'b'Content-Type': b'application/octet-stream'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive' --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem --cert None --key None https://172.16.0.20:13292/v2/images/overcloud-full-vmlinuz`
+```
+
+Here, you can see the fernet token, the user-agent indicating Glance is speaking, and the TLS certificate; this is why you don't see anything in your tcpdump.
+
+Since the image does not exist, it is OK to get a 404 ERROR for this request.
+
+Next, the current images are consulted:
+
+
+```
+`https://172.16.0.20:13292 "GET /v2/images?limit=20 HTTP/1.1" 200 78`
+```
+
+and retrieved from the service:
+
+
+```
+HTTP/1.1 200 OK
+Content-Length: 78
+Content-Type: application/json
+X-Openstack-Request-Id: req-0f117984-f427-4d35-bec3-956432865dd1
+Date: Tue, 18 Feb 2020 04:49:55 GMT
+
+{
+ "images":[
+
+ ],
+ "first":"/v2/images?limit=20",
+ "schema":"/v2/schemas/images"
+}
+```
+
+Yes, it is still empty.
+
+Meanwhile, the same check has been done on the database, where a huge query has been triggered with the same results. (To sync on the timestamp, I checked on the tcpdump after the connection and queries were finished, and then compared them with the API calls' timestamp.)
+
+To identify where the Glance-DB calls started, I did a full-packet search with the word "glance" inside the tcpdump file. This saves a lot of time vs. searching through all the other database calls, so this is my starting point to check each database call.
+
+![Searching "glance" inside tcpdump][7]
+
+The first query returns nothing in the fields, as the image still does not exist:
+
+
+```
+SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status
+FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id
+WHERE images.id = 'overcloud-full-vmlinuz'
+```
+
+Next, the image will start uploading, so an API call and a write to the database are expected.
+
+On the API side, the image scheme is retrieved by consulting the service in:
+
+
+```
+`https://172.16.0.20:13292 "GET /v2/schemas/image HTTP/1.1"`
+```
+
+Then, some of the fields are populated with image information. This is what the scheme looks like:
+
+
+```
+{
+ "name":"image",
+ "properties":{
+ "id":{
+ "type":"string",
+ "description":"An identifier for the image",
+ "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$"
+ },
+ "name":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "description":"Descriptive name for the image",
+ "maxLength":255
+ },
+ "status":{
+ "type":"string",
+ "readOnly":true,
+ "description":"Status of the image",
+ "enum":[
+ "queued",
+ "saving",
+ "active",
+ "killed",
+ "deleted",
+ "uploading",
+ "importing",
+ "pending_delete",
+ "deactivated"
+ ]
+ },
+ "visibility":{
+ "type":"string",
+ "description":"Scope of image accessibility",
+ "enum":[
+ "community",
+ "public",
+ "private",
+ "shared"
+ ]
+ },
+ "protected":{
+ "type":"boolean",
+ "description":"If true, image will not be deletable."
+ },
+ "os_hidden":{
+ "type":"boolean",
+ "description":"If true, image will not appear in default image list response."
+ },
+ "checksum":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "readOnly":true,
+ "description":"md5 hash of image contents.",
+ "maxLength":32
+ },
+ "os_hash_algo":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "readOnly":true,
+ "description":"Algorithm to calculate the os_hash_value",
+ "maxLength":64
+ },
+ "os_hash_value":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "readOnly":true,
+ "description":"Hexdigest of the image contents using the algorithm specified by the os_hash_algo",
+ "maxLength":128
+ },
+ "owner":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "description":"Owner of the image",
+ "maxLength":255
+ },
+ "size":{
+ "type":[
+ "null",
+ "integer"
+ ],
+ "readOnly":true,
+ "description":"Size of image file in bytes"
+ },
+ "virtual_size":{
+ "type":[
+ "null",
+ "integer"
+ ],
+ "readOnly":true,
+ "description":"Virtual size of image in bytes"
+ },
+ "container_format":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "description":"Format of the container",
+ "enum":[
+ null,
+ "ami",
+ "ari",
+ "aki",
+ "bare",
+ "ovf",
+ "ova",
+ "docker",
+ "compressed"
+ ]
+ },
+ "disk_format":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "description":"Format of the disk",
+ "enum":[
+ null,
+ "ami",
+ "ari",
+ "aki",
+ "vhd",
+ "vhdx",
+ "vmdk",
+ "raw",
+ "qcow2",
+ "vdi",
+ "iso",
+ "ploop"
+ ]
+ },
+ "created_at":{
+ "type":"string",
+ "readOnly":true,
+ "description":"Date and time of image registration"
+ },
+ "updated_at":{
+ "type":"string",
+ "readOnly":true,
+ "description":"Date and time of the last image modification"
+ },
+ "tags":{
+ "type":"array",
+ "description":"List of strings related to the image",
+ "items":{
+ "type":"string",
+ "maxLength":255
+ }
+ },
+ "direct_url":{
+ "type":"string",
+ "readOnly":true,
+ "description":"URL to access the image file kept in external store"
+ },
+ "min_ram":{
+ "type":"integer",
+ "description":"Amount of ram (in MB) required to boot image."
+ },
+ "min_disk":{
+ "type":"integer",
+ "description":"Amount of disk space (in GB) required to boot image."
+ },
+ "self":{
+ "type":"string",
+ "readOnly":true,
+ "description":"An image self url"
+ },
+ "file":{
+ "type":"string",
+ "readOnly":true,
+ "description":"An image file url"
+ },
+ "stores":{
+ "type":"string",
+ "readOnly":true,
+ "description":"Store in which image data resides. Only present when the operator has enabled multiple stores. May be a comma-separated list of store identifiers."
+ },
+ "schema":{
+ "type":"string",
+ "readOnly":true,
+ "description":"An image schema url"
+ },
+ "locations":{
+ "type":"array",
+ "items":{
+ "type":"object",
+ "properties":{
+ "url":{
+ "type":"string",
+ "maxLength":255
+ },
+ "metadata":{
+ "type":"object"
+ },
+ "validation_data":{
+ "description":"Values to be used to populate the corresponding image properties. If the image status is not 'queued', values must exactly match those already contained in the image properties.",
+ "type":"object",
+ "writeOnly":true,
+ "additionalProperties":false,
+ "properties":{
+ "checksum":{
+ "type":"string",
+ "minLength":32,
+ "maxLength":32
+ },
+ "os_hash_algo":{
+ "type":"string",
+ "maxLength":64
+ },
+ "os_hash_value":{
+ "type":"string",
+ "maxLength":128
+ }
+ },
+ "required":[
+ "os_hash_algo",
+ "os_hash_value"
+ ]
+ }
+ },
+ "required":[
+ "url",
+ "metadata"
+ ]
+ },
+ "description":"A set of URLs to access the image file kept in external store"
+ },
+ "kernel_id":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$",
+ "description":"ID of image stored in Glance that should be used as the kernel when booting an AMI-style image.",
+ "is_base":false
+ },
+ "ramdisk_id":{
+ "type":[
+ "null",
+ "string"
+ ],
+ "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$",
+ "description":"ID of image stored in Glance that should be used as the ramdisk when booting an AMI-style image.",
+ "is_base":false
+ },
+ "instance_uuid":{
+ "type":"string",
+ "description":"Metadata which can be used to record which instance this image is associated with. (Informational only, does not create an instance snapshot.)",
+ "is_base":false
+ },
+ "architecture":{
+ "description":"Operating system architecture as specified in ",
+ "type":"string",
+ "is_base":false
+ },
+ "os_distro":{
+ "description":"Common name of operating system distribution as specified in ",
+ "type":"string",
+ "is_base":false
+ },
+ "os_version":{
+ "description":"Operating system version as specified by the distributor.",
+ "type":"string",
+ "is_base":false
+ },
+ "description":{
+ "description":"A human-readable string describing this image.",
+ "type":"string",
+ "is_base":false
+ },
+ "cinder_encryption_key_id":{
+ "description":"Identifier in the OpenStack Key Management Service for the encryption key for the Block Storage Service to use when mounting a volume created from this image",
+ "type":"string",
+ "is_base":false
+ },
+ "cinder_encryption_key_deletion_policy":{
+ "description":"States the condition under which the Image Service will delete the object associated with the 'cinder_encryption_key_id' image property. If this property is missing, the Image Service will take no action",
+ "type":"string",
+ "enum":[
+ "on_image_deletion",
+ "do_not_delete"
+ ],
+ "is_base":false
+ }
+ },
+ "additionalProperties":{
+ "type":"string"
+ },
+ "links":[
+ {
+ "rel":"self",
+ "href":"{self}"
+ },
+ {
+ "rel":"enclosure",
+ "href":"{file}"
+ },
+ {
+ "rel":"describedby",
+ "href":"{schema}"
+ }
+ ]
+}
+```
+
+That's a long scheme!
+
+Here is the API call to start uploading the image information, and it will now move to the "queue" state:
+
+
+```
+`curl -g -i -X POST -H 'b'Content-Type': b'application/json'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive' --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem --cert None --key None -d '{"name": "overcloud-full-vmlinuz", "disk_format": "aki", "visibility": "public", "container_format": "bare"}' https://172.16.0.20:13292/v2/images`
+```
+
+Here is the API response:
+
+
+```
+HTTP/1.1 201 Created
+Content-Length: 629
+Content-Type: application/json
+Location:
+Openstack-Image-Import-Methods: web-download
+X-Openstack-Request-Id: req-bd5194f0-b1c2-40d3-a646-8a24ed0a1b1b
+Date: Tue, 18 Feb 2020 04:49:56 GMT
+
+{
+ "name":"overcloud-full-vmlinuz",
+ "disk_format":"aki",
+ "container_format":"bare",
+ "visibility":"public",
+ "size":null,
+ "virtual_size":null,
+ "status":"queued",
+ "checksum":null,
+ "protected":false,
+ "min_ram":0,
+ "min_disk":0,
+ "owner":"c0a46a106d3341649a25b10f2770aff8",
+ "os_hidden":false,
+ "os_hash_algo":null,
+ "os_hash_value":null,
+ "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "created_at":"2020-02-18T04:49:55Z",
+ "updated_at":"2020-02-18T04:49:55Z",
+ "tags":[
+
+ ],
+ "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
+ "schema":"/v2/schemas/image"
+}
+```
+
+and the SQL call to store the information in the Glance-DB:
+
+
+```
+`INSERT INTO images (created_at, updated_at, deleted_at, deleted, id, name, disk_format, container_format, SIZE, virtual_size, STATUS, visibility, checksum, os_hash_algo, os_hash_value, min_disk, min_ram, owner, protected, os_hidden) VALUES ('2020-02-18 04:49:55.993652', '2020-02-18 04:49:55.993652', NULL, 0, '13892850-6add-4c28-87cd-6da62e6f8a3c', 'overcloud-full-vmlinuz', 'aki', 'bare', NULL, NULL, 'queued', 'public', NULL, NULL, NULL, 0, 0, 'c0a46a106d3341649a25b10f2770aff8', 0, 0)`
+```
+
+Current status:
+
+_Image Created ->_ _**Image Queued**_ _-> Image Saved -> Image Active_
+
+In the Glance architecture, the images are "physically" stored in the specified backend (Swift in this case), so traffic will also hit the Swift endpoint at port 8080. Capturing this traffic will make the .pcap file as large as the images being uploaded (2GB in my case).[*][8]
+
+![Glance architecture][9]
+
+
+```
+SELECT image_properties.created_at AS image_properties_created_at, image_properties.updated_at AS image_properties_updated_at, image_properties.deleted_at AS image_properties_deleted_at, image_properties.deleted AS image_properties_deleted, image_properties.id AS image_properties_id, image_properties.image_id AS image_properties_image_id, image_properties.name AS image_properties_name, image_properties.value AS image_properties_value
+FROM image_properties
+WHERE '13892850-6add-4c28-87cd-6da62e6f8a3c' = image_properties.image_id
+```
+
+You can see some validations happening within the database. At this point, the flow status is "queued" (as shown above), and you can check it here:
+
+![Checking the Glance image status][10]
+
+You can also check it with the following queries, where the **updated_at** field and the flow status are modified accordingly (i.e., queued to saving):
+
+Current status:
+
+_Image Created -> Image Queued ->_ _**Image Saved**_ _-> Image Active_
+
+
+```
+SELECT images.id AS images_id
+FROM images
+WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'queued'
+UPDATE images SET updated_at='2020-02-18 04:49:56.046542', id='13892850-6add-4c28-87cd-6da62e6f8a3c', name='overcloud-full-vmlinuz', disk_format='aki', container_format='bare', SIZE=NULL, virtual_size=NULL, STATUS='saving', visibility='public', checksum=NULL, os_hash_algo=NULL, os_hash_value=NULL, min_disk=0, min_ram=0, owner='c0a46a106d3341649a25b10f2770aff8', protected=0, os_hidden=0 WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'queued'
+```
+
+This is validated during the process with the following query:
+
+
+```
+SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status
+FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id
+WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c'
+```
+
+And you can see its response in the Wireshark capture:
+
+![Wireshark capture][11]
+
+After the image is completely uploaded, its status will change to "active," which means the image is available in the service and ready to use.
+
+
+```
+ "GET /v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c HTTP/1.1" 200
+
+{
+ "name":"overcloud-full-vmlinuz",
+ "disk_format":"aki",
+ "container_format":"bare",
+ "visibility":"public",
+ "size":8106848,
+ "virtual_size":null,
+ "status":"active",
+ "checksum":"5d31ee013d06b83d02c106ea07f20265",
+ "protected":false,
+ "min_ram":0,
+ "min_disk":0,
+ "owner":"c0a46a106d3341649a25b10f2770aff8",
+ "os_hidden":false,
+ "os_hash_algo":"sha512",
+ "os_hash_value":"9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499",
+ "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "created_at":"2020-02-18T04:49:55Z",
+ "updated_at":"2020-02-18T04:49:56Z",
+ "direct_url":"swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "tags":[
+
+ ],
+ "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
+ "schema":"/v2/schemas/image"
+}
+```
+
+You can also see the database call that updates the current status:
+
+
+```
+`UPDATE images SET updated_at='2020-02-18 04:49:56.571879', id='13892850-6add-4c28-87cd-6da62e6f8a3c', name='overcloud-full-vmlinuz', disk_format='aki', container_format='bare', SIZE=8106848, virtual_size=NULL, STATUS='active', visibility='public', checksum='5d31ee013d06b83d02c106ea07f20265', os_hash_algo='sha512', os_hash_value='9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499', min_disk=0, min_ram=0, owner='c0a46a106d3341649a25b10f2770aff8', protected=0, os_hidden=0 WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'saving'`
+```
+
+Current status:
+
+_Image Created -> Image Queued -> Image Saved ->_ _**Image Active**_
+
+One interesting thing is that a property in the image is added after the image is uploaded using a PATCH. This property is **hw_architecture** and it is set to **x86_64**:
+
+
+```
+ "PATCH /v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c HTTP/1.1"
+
+curl -g -i -X PATCH -H 'b'Content-Type': b'application/openstack-images-v2.1-json-patch'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive' --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem --cert None --key None -d '[{"op": "add", "path": "/hw_architecture", "value": "x86_64"}]'
+
+Response:
+
+{
+ "hw_architecture":"x86_64",
+ "name":"overcloud-full-vmlinuz",
+ "disk_format":"aki",
+ "container_format":"bare",
+ "visibility":"public",
+ "size":8106848,
+ "virtual_size":null,
+ "status":"active",
+ "checksum":"5d31ee013d06b83d02c106ea07f20265",
+ "protected":false,
+ "min_ram":0,
+ "min_disk":0,
+ "owner":"c0a46a106d3341649a25b10f2770aff8",
+ "os_hidden":false,
+ "os_hash_algo":"sha512",
+ "os_hash_value":"9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499",
+ "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "created_at":"2020-02-18T04:49:55Z",
+ "updated_at":"2020-02-18T04:49:56Z",
+ "direct_url":"swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "tags":[
+
+ ],
+ "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
+ "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
+ "schema":"/v2/schemas/image"
+}
+```
+
+This is also updated in the MySQL database:
+
+
+```
+`INSERT INTO image_properties (created_at, updated_at, deleted_at, deleted, image_id, name, VALUE) VALUES ('2020-02-18 04:49:56.655780', '2020-02-18 04:49:56.655783', NULL, 0, '13892850-6add-4c28-87cd-6da62e6f8a3c', 'hw_architecture', 'x86_64')`
+```
+
+This is pretty much what happens when you upload an image to Glance. Here's what it looks like if you check on the database:
+
+
+```
+MariaDB [glance]> SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c'\G;
+*************************** 1. row ***************************
+ images_created_at: 2020-02-18 04:49:55
+ images_updated_at: 2020-02-18 04:49:56
+ images_deleted_at: NULL
+ images_deleted: 0
+ images_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
+ images_name: overcloud-full-vmlinuz
+ images_disk_format: aki
+ images_container_format: bare
+ images_size: 8106848
+ images_virtual_size: NULL
+ images_status: active
+ images_visibility: public
+ images_checksum: 5d31ee013d06b83d02c106ea07f20265
+ images_os_hash_algo: sha512
+ images_os_hash_value: 9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499
+ images_min_disk: 0
+ images_min_ram: 0
+ images_owner: c0a46a106d3341649a25b10f2770aff8
+ images_protected: 0
+ images_os_hidden: 0
+image_properties_1_created_at: 2020-02-18 04:49:56
+image_properties_1_updated_at: 2020-02-18 04:49:56
+image_properties_1_deleted_at: NULL
+ image_properties_1_deleted: 0
+ image_properties_1_id: 11
+ image_properties_1_image_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
+ image_properties_1_name: hw_architecture
+ image_properties_1_value: x86_64
+ image_locations_1_created_at: 2020-02-18 04:49:56
+ image_locations_1_updated_at: 2020-02-18 04:49:56
+ image_locations_1_deleted_at: NULL
+ image_locations_1_deleted: 0
+ image_locations_1_id: 7
+ image_locations_1_image_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
+ image_locations_1_value: swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c
+ image_locations_1_meta_data: {}
+ image_locations_1_status: active
+1 row in set (0.00 sec)
+```
+
+The final result is:
+
+
+```
+(undercloud) [stack@undercloud ~]$ openstack image list
++--------------------------------------+------------------------+--------+
+| ID | Name | Status |
++--------------------------------------+------------------------+--------+
+| 9a26b9da-3783-4223-bdd7-c553aa194e30 | overcloud-full | active |
+| a2914297-c70f-4021-bc3e-8ec2123f6ea6 | overcloud-full-initrd | active |
+| 13892850-6add-4c28-87cd-6da62e6f8a3c | overcloud-full-vmlinuz | active |
++--------------------------------------+------------------------+--------+
+(undercloud) [stack@undercloud ~]$
+```
+
+Some other minor things are happening during this process, but overall, this is how it looks.
+
+### Conclusion
+
+Understanding the flow of the most common actions in the OpenStack platform will enable you to enhance your troubleshooting skills when facing some issues at work. You can check the status of an image in Glance; know whether an image is in a "queued," "saving," or "active" state; and do some captures in your environment to see what is going on by checking the endpoints you need to check.
+
+I enjoy debugging. I consider this is an important skill for any role—whether you are working in a support, consulting, developer (of course!), or architect role. I hope this article gave you some basic guidelines to start debugging things.
+
+* * *
+
+* In case you're wondering how to open a 2GB .pcap file without problems, here is one way to do it:
+
+
+```
+`$ editcap -c 5000 image-upload.pcap upload-overcloud-image.pcap`
+```
+
+This splits your huge capture in smaller captures of 5,000 packets each.
+
+* * *
+
+_This article was [originally posted][12] on LinkedIn and is reprinted with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/glance
+
+作者:[Jair Patete][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jpatete
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/yourimagehere_520x292.png?itok=V-xhX7KL (blank background that says your image here)
+[2]: https://www.openstack.org/software/releases/ocata/components/glance
+[3]: https://www.openstack.org/
+[4]: https://wiki.openstack.org/wiki/TripleO
+[5]: https://www.tcpdump.org/
+[6]: https://docs.openstack.org/keystone/latest/
+[7]: https://opensource.com/sites/default/files/uploads/glance-db-calls.png (Searching "glance" inside tcpdump)
+[8]: tmp.qBKg0ttLIJ#*
+[9]: https://opensource.com/sites/default/files/uploads/glance-architecture.png (Glance architecture)
+[10]: https://opensource.com/sites/default/files/uploads/check-flow-status.png (Checking the Glance image status)
+[11]: https://opensource.com/sites/default/files/uploads/wireshark-capture.png (Wireshark capture)
+[12]: https://www.linkedin.com/pulse/what-happens-behind-doors-when-we-upload-image-glance-patete-garc%25C3%25ADa/?trackingId=czWiFC4dRfOsSZJ%2BXdzQfg%3D%3D
diff --git a/sources/tech/20200320 Run a command on binary files with this script.md b/sources/tech/20200320 Run a command on binary files with this script.md
new file mode 100644
index 0000000000..2d6f0b6f26
--- /dev/null
+++ b/sources/tech/20200320 Run a command on binary files with this script.md
@@ -0,0 +1,772 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Run a command on binary files with this script)
+[#]: via: (https://opensource.com/article/20/3/run-binaries-script)
+[#]: author: (Nick Clifton https://opensource.com/users/nickclifton)
+
+Run a command on binary files with this script
+======
+Try this simple script to easily run a command on binary files
+regardless of their packaging.
+![Binary code on a computer screen][1]
+
+Examining files from the command-line is generally an easy thing to do. You just run the command you want, followed by a list of files to be examined. Dealing with binary files, however, is more complicated. These files are often packaged up into archives, tarballs, or other packaging formats. The run-on-binaries script provides a convenient way to run a command on a collection of files, regardless of how they are packaged.
+
+The invocation of the script is quite simple:
+
+
+```
+`run-on-binaries `
+```
+
+So, for example:
+
+
+```
+`run-on-binaries /usr/bin/ls foo.rpm`
+```
+
+will list all of the files inside the **foo.rpm** file, while:
+
+
+```
+`run-on-binaries /usr/bin/readelf -a libc.a`
+```
+
+will run the **readelf** program, with the **-a** command-line option, on all of the object files inside the **libc.a library**.
+
+If necessary, the script can be passed a file containing a list of other files to be processed, rather than specifying them on the command line—like this:
+
+
+```
+`run-on-binaries --files-from=foo.lst /usr/bin/ps2ascii`
+```
+
+This will run the **ps2ascii** script on all of the files listed in **foo.lst**. (The files just need to be separated by white space. There can be multiple files on a single line if desired).
+
+Also, a skip list can be provided to stop the script from processing specified files:
+
+
+```
+`run-on-binaries --skip-list=skip.lst /usr/bin/wc *`
+```
+
+This will run the **wc** program on all of the files in the current directory, except for those specified in **skip.lst**.
+
+The script does not recurse into directories, but this can be handled by combining it with the **find** command, like this:
+
+
+```
+`find . -type f -exec run-on-binaries @ ;`
+```
+
+or
+
+
+```
+`find . -type d -exec run-on-binaries @/* ;`
+```
+
+The only difference between these two invocations is that the second one only runs the target program once per directory, but gives it a long command-line of all of the files in the directory.
+
+Though convenient, the script is lacking in several areas. Right now, it does not examine the PATH environment variable to find the command that it is asked to run, so a full path must be provided. Also, the script ought to be able to handle recursion on its own, without needing help from the find command.
+
+The run-on-binaries script is part of the annobin package, which is available on Fedora. The sources for annobin can also be obtained from the git repository at .
+
+### The script
+
+
+```
+#!/bin/bash
+
+# Script to run another script/program on the executables inside a given file.
+#
+# Created by Nick Clifton. <[nickc@redhat.com][2]>
+# Copyright (c) 2018 Red Hat.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+
+# It is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# Usage:
+# run-on-binaries-in [options] program [options-for-the-program] file(s)
+#
+# This script does not handle directories. This is deliberate.
+# It is intended that if recursion is needed then it will be
+# invoked from find, like this:
+#
+# find . -name "*.rpm" -exec run-on-binaries-in <script-to-run> {} \;
+
+version=1.0
+
+help ()
+{
+ # The following exec goop is so that we don't have to manually
+ # redirect every message to stderr in this function.
+ exec 4>&1 # save stdout fd to fd #4
+ exec 1>&2 # redirect stdout to stderr
+
+ cat <<__EOM__
+
+This is a shell script to run another script/program on one or more binary
+files. If the file(s) specified are archives of some kind (including rpms)
+then the script/program is run on the binary executables inside the archive.
+
+Usage: $prog {options} program {options-for-the-program} files(s)
+
+ {options} are:
+ -h --help Display this information and then exit.
+ -v --version Report the version number of this script.
+ -V --verbose Report on progress.
+ -q --quiet Do not include the script name in the output.
+ -i --ignore Silently ignore files that are not executables or archives.
+ -p=<TEXT> --prefix=<TEXT> Prefix normal output with this string.
+ -t=<DIR> --tmpdir=<DIR> Temporary directory to use when opening archives.
+ -f=<FILE> --files-from=<FILE> Process files listed in <FILE>.
+ -s=<FILE> --skip-list=<FILE> Skip any file listed in <FILE>.
+ -- Stop accumulating options.
+
+Examples:
+
+ $prog hardened foo.rpm
+ Runs the hardened script on the executable
+ files inside foo.rpm.
+
+ $prog check-abi -v fred.tar.xz
+ Runs the check-abi script on the decompressed
+ contents of the fred.tar.xz archive, passing the
+ -v option to check-abi as it does so.
+
+ $prog -V -f=list.txt readelf -a
+ Runs the readelf program, with the -a option on
+ every file listed in the list.txt. Describes
+ what is being done as it works.
+
+ $prog -v -- -fred -a jim -b bert -- -c harry
+ Runs the script "-fred" on the files jim, bert,
+ "-c" and harry. Passes the options "-a" and
+ "-b" to the script (even when run on jim).
+ Reports the version of this script as well.
+
+__EOM__
+ exec 1>&4 # Copy stdout fd back from temporary save fd, #4
+}
+
+main ()
+{
+ init
+
+ parse_args ${1+"$@"}
+
+ if [ $failed -eq 0 ];
+ then
+ run_script_on_files
+ fi
+
+ if [ $failed -ne 0 ];
+ then
+ exit 1
+ else
+ exit 0
+ fi
+}
+
+report ()
+{
+ if [ $quiet -eq 0 ];
+ then
+ echo -n $prog": "
+ fi
+
+ echo ${1+"$@"}
+}
+
+ice ()
+{
+ report "Internal error: " ${1+"$@"}
+ exit 1
+}
+
+fail ()
+{
+ report "Failure:" ${1+"$@"}
+ failed=1
+}
+
+verbose ()
+{
+ if [ $verbose -ne 0 ]
+ then
+ report ${1+"$@"}
+ fi
+}
+
+# Initialise global variables.
+init ()
+{
+ files[0]="";
+ # num_files is the number of files to be scanned.
+ # files[0] is the script to run on the files.
+ num_files=0;
+
+ script=""
+ script_opts="";
+
+ prog_opts="-i"
+
+ tmpdir=/dev/shm
+ prefix=""
+ files_from=""
+ skip_list=""
+
+ failed=0
+ verbose=0
+ ignore=0
+ quiet=0
+}
+
+# Parse our command line
+parse_args ()
+{
+ abs_prog=$0;
+ prog=`basename $abs_prog`;
+
+ # Locate any additional command line switches
+ # Likewise accumulate non-switches to the files list.
+ while [ $# -gt 0 ]
+ do
+ optname="`echo $1 | sed 's,=.*,,'`"
+ optarg="`echo $1 | sed 's,^[^=]*=,,'`"
+ case "$optname" in
+ -v | --version)
+ report "version: $version"
+ ;;
+ -h | --help)
+ help
+ exit 0
+ ;;
+ -q | --quiet)
+ quiet=1;
+ prog_opts="$prog_opts -q"
+ ;;
+ -V | --verbose)
+ if [ $verbose -eq 1 ];
+ then
+ # This has the effect of cancelling out the prog_opts="-i"
+ # in the init function, so that recursive invocations of this
+ # script will complain about unrecognised file types.
+ if [ $quiet -eq 0 ];
+ then
+ prog_opts="-V -V"
+ else
+ prog_opts="-V -V -q"
+ fi
+ else
+ verbose=1;
+ prog_opts="$prog_opts -V"
+ fi
+ ;;
+ -i | --ignore)
+ ignore=1
+ ;;
+ -t | --tmpdir)
+ if test "x$optarg" = "x$optname" ;
+ then
+ shift
+ if [ $# -eq 0 ]
+ then
+ fail "$optname needs a directory name"
+ else
+ tmpdir=$1
+ fi
+ else
+ tmpdir="$optarg"
+ fi
+ ;;
+ -p | --prefix)
+ if test "x$optarg" = "x$optname" ;
+ then
+ shift
+ if [ $# -eq 0 ]
+ then
+ fail "$optname needs a string argument"
+ else
+ prefix=$1
+ fi
+ else
+ prefix="$optarg"
+ fi
+ ;;
+ -f | --files_from)
+ if test "x$optarg" = "x$optname" ;
+ then
+ shift
+ if [ $# -eq 0 ]
+ then
+ fail "$optname needs a file name"
+ else
+ files_from=$1
+ fi
+ else
+ files_from="$optarg"
+ fi
+ ;;
+
+ -s | --skip-list)
+ if test "x$optarg" = "x$optname" ;
+ then
+ shift
+ if [ $# -eq 0 ]
+ then
+ fail "$optname needs a file name"
+ else
+ skip_list=$1
+ fi
+ else
+ skip_list="$optarg"
+ fi
+ ;;
+
+ --)
+ shift
+ break;
+ ;;
+ --*)
+ fail "unrecognised option: $1"
+ help
+ ;;
+ *)
+ script="$1";
+ if ! [ -a "$script" ]
+ then
+ fail "$script: program/script not found"
+ elif ! [ -x "$script" ]
+ then
+ fail "$script: program/script not executable"
+ fi
+ # After we have seen the first non-option we stop
+ # accumulating options for this script and instead
+ # start accumulating options for the script to be
+ # run.
+ shift
+ break;
+ ;;
+ esac
+ shift
+ done
+
+ # Read in the contents of the --file-from list, if specified.
+ if test "x$files_from" != "x" ;
+ then
+ if ! [ -a "$files_from" ]
+ then
+ fail "$files_from: file not found"
+ elif ! [ -r "$files_from" ]
+ then
+ fail "$files_from: file not readable"
+ else
+ eval 'files=($(cat $files_from))'
+ num_files=${#files[*]}
+ fi
+ fi
+ skip_files[foo]=bar
+
+ # Check that the skip list exists, if specified.
+ if test "x$skip_list" != "x" ;
+ then
+ if ! [ -a "$skip_list" ]
+ then
+ fail "$skip_list: file not found"
+ elif ! [ -r "$skip_list" ]
+ then
+ fail "$files_from: file not readable"
+ fi
+ fi
+
+ # Accumulate any remaining arguments separating out the arguments
+ # for the script from the names of the files to scan.
+ while [ $# -gt 0 ]
+ do
+ optname="`echo $1 | sed 's,=.*,,'`"
+ optarg="`echo $1 | sed 's,^[^=]*=,,'`"
+ case "$optname" in
+ --)
+ shift
+ break;
+ ;;
+ -*)
+ script_opts="$script_opts $1"
+ ;;
+ *)
+ files[$num_files]="$1";
+ let "num_files++"
+ ;;
+ esac
+ shift
+ done
+
+ # Accumulate any remaining arguments without processing them.
+ while [ $# -gt 0 ]
+ do
+ files[$num_files]="$1";
+ let "num_files++";
+ shift
+ done
+
+ if [ $num_files -gt 0 ];
+ then
+ # Remember that we are counting from zero not one.
+ let "num_files--"
+ else
+ fail "Must specify a program/script and at least one file to scan."
+ fi
+}
+
+run_script_on_files ()
+{
+ local i
+
+ i=0;
+ while [ $i -le $num_files ]
+ do
+ run_on_file i
+ let "i++"
+ done
+}
+
+# syntax: run <command> [<args>]
+# If being verbose report the command being run, and
+# the directory in which it is run.
+run ()
+{
+ local where
+
+ if test "x$1" = "x" ;
+ then
+ fail "run() called without an argument."
+ fi
+
+ verbose " Running: ${1+$@}"
+
+ ${1+$@}
+}
+
+decompress ()
+{
+ local abs_file decompressor decomp_args orig_file base_file
+
+ # Paranoia checks - the user should never encounter these.
+ if test "x$4" = "x" ;
+ then
+ ice "decompress called with too few arguments"
+ fi
+ if test "x$5" != "x" ;
+ then
+ ice "decompress called with too many arguments"
+ fi
+
+ abs_file=$1
+ decompressor=$2
+ decomp_args=$3
+ orig_file=$4
+
+ base_file=`basename $abs_file`
+
+ run cp $abs_file $base_file
+ run $decompressor $decomp_args $base_file
+ if [ $? != 0 ];
+ then
+ fail "$orig_file: Unable to decompress"
+ fi
+
+ rm -f $base_file
+}
+
+run_on_file ()
+{
+ local file
+
+ # Paranoia checks - the user should never encounter these.
+ if test "x$1" = "x" ;
+ then
+ ice "scan_file called without an argument"
+ fi
+ if test "x$2" != "x" ;
+ then
+ ice "scan_file called with too many arguments"
+ fi
+
+ # Use quotes when accessing files in order to preserve
+ # any spaces that might be in the directory name.
+ file="${files[$1]}";
+
+ # Catch names that start with a dash - they might confuse readelf
+ if test "x${file:0:1}" = "x-" ;
+ then
+ file="./$file"
+ fi
+
+ # See if we should skip this file.
+ if test "x$skip_list" != "x" ;
+ then
+ # This regexp looks for $file being the first text on a line, either
+ # on its own, or with additional text separated from it by at least
+ # one space character. So searching for "fred" in the following gives:
+ # fr <\- no match
+ # fred <\- match
+ # fredjim <\- no match
+ # fred bert <\- match
+ regexp="^$file[^[:graph:]]*"
+ grep --silent --regexp="$regexp" $skip_list
+ if [ $? = 0 ];
+ then
+ verbose "$file: skipping"
+ return
+ fi
+ fi
+
+ # Check the file.
+ if ! [ -a "$file" ]
+ then
+ fail "$file: file not found"
+ return
+ elif ! [ -r "$file" ]
+ then
+ if [ $ignore -eq 0 ];
+ then
+ fail "$file: not readable"
+ fi
+ return
+ elif [ -d "$file" ]
+ then
+ if [ $ignore -eq 0 ];
+ then
+ if [ $num_files -gt 1 ];
+ then
+ verbose "$file: skipping - it is a directory"
+ else
+ report "$file: skipping - it is a directory"
+ fi
+ fi
+ return
+ elif ! [ -f "$file" ]
+ then
+ if [ $ignore -eq 0 ];
+ then
+ fail "$file: not an ordinary file"
+ fi
+ return
+ fi
+
+ file_type=`file -b $file`
+ case "$file_type" in
+ *"ELF "*)
+ verbose "$file: ELF format - running script/program"
+ if test "x$prefix" != "x" ;
+ then
+ report "$prefix:"
+ fi
+ run $script $script_opts $file
+ return
+ ;;
+ "RPM "*)
+ verbose "$file: RPM format."
+ ;;
+ *" cpio "*)
+ verbose "$file: CPIO format."
+ ;;
+ *"tar "*)
+ verbose "$file: TAR archive."
+ ;;
+ *"Zip archive"*)
+ verbose "$file: ZIP archive."
+ ;;
+ *"ar archive"*)
+ verbose "$file: AR archive."
+ ;;
+ *"bzip2 compressed data"*)
+ verbose "$file: contains bzip2 compressed data"
+ ;;
+ *"gzip compressed data"*)
+ verbose "$file: contains gzip compressed data"
+ ;;
+ *"lzip compressed data"*)
+ verbose "$file: contains lzip compressed data"
+ ;;
+ *"XZ compressed data"*)
+ verbose "$file: contains xz compressed data"
+ ;;
+ *"shell script"* | *"ASCII text"*)
+ if [ $ignore -eq 0 ];
+ then
+ fail "$file: test/scripts cannot be scanned."
+ fi
+ return
+ ;;
+ *"symbolic link"*)
+ if [ $ignore -eq 0 ];
+ then
+ # FIXME: We ought to be able to follow symbolic links
+ fail "$file: symbolic links are not followed."
+ fi
+ return
+ ;;
+ *)
+ if [ $ignore -eq 0 ];
+ then
+ fail "$file: Unsupported file type: $file_type"
+ fi
+ return
+ ;;
+ esac
+
+ # We now know that we will need a temporary directory
+ # so create one, and create paths to the file and scripts.
+ if test "x${file:0:1}" = "x/" ;
+ then
+ abs_file=$file
+ else
+ abs_file="$PWD/$file"
+ fi
+
+ if test "x${abs_prog:0:1}" != "x/" ;
+ then
+ abs_prog="$PWD/$abs_prog"
+ fi
+
+ if test "x${script:0:1}" = "x/" ;
+ then
+ abs_script=$script
+ else
+ abs_script="$PWD/$script"
+ fi
+
+ tmp_root=$tmpdir/delme.run.on.binary
+ run mkdir -p "$tmp_root/$file"
+
+ verbose " Changing to directory: $tmp_root/$file"
+ pushd "$tmp_root/$file" > /dev/null
+ if [ $? != 0 ];
+ then
+ fail "Unable to change to temporary directory: $tmp_root/$file"
+ return
+ fi
+
+ # Run the file type switch again, although this time we do not need to
+ # check for unrecognised types. (But we do, just in case...)
+ # Note since are transforming the file we re-invoke the run-on-binaries
+ # script on the decoded contents. This allows for archives that contain
+ # other archives, and so on. We normally pass the -i option to the
+ # invoked script so that it will not complain about unrecognised files in
+ # the decoded archive, although we do not do this when running in very
+ # verbose mode. We also pass an extended -t option to ensure that any
+ # sub-archives are extracted into a unique directory tree.
+
+ case "$file_type" in
+ "RPM "*)
+ # The output redirect confuses the run function...
+ verbose " Running: rpm2cpio $abs_file > delme.cpio"
+ rpm2cpio $abs_file > delme.cpio
+ if [ $? != 0 ];
+ then
+ fail "$file: Unable to extract from rpm archive"
+ else
+ # Save time - run cpio now.
+ run cpio --quiet --extract --make-directories --file delme.cpio
+ if [ $? != 0 ];
+ then
+ fail "$file: Unable to extract files from cpio archive"
+ fi
+ run rm -f delme.cpio
+ fi
+ ;;
+
+ *" cpio "*)
+ run cpio --quiet --extract --make-directories --file=$abs_file
+ if [ $? != 0 ];
+ then
+ fail "$file: Unable to extract files from cpio archive"
+ fi
+ ;;
+
+ *"tar "*)
+ run tar --extract --file=$abs_file
+ if [ $? != 0 ];
+ then
+ fail "$file: Unable to extract files from tarball"
+ fi
+ ;;
+
+ *"ar archive"*)
+ run ar x $abs_file
+ if [ $? != 0 ];
+ then
+ fail "$file: Unable to extract files from ar archive"
+ fi
+ ;;
+
+ *"Zip archive"*)
+ decompress $abs_file unzip "-q" $file
+ ;;
+ *"bzip2 compressed data"*)
+ decompress $abs_file bzip2 "--quiet --decompress" $file
+ ;;
+ *"gzip compressed data"*)
+ decompress $abs_file gzip "--quiet --decompress" $file
+ ;;
+ *"lzip compressed data"*)
+ decompress $abs_file lzip "--quiet --decompress" $file
+ ;;
+ *"XZ compressed data"*)
+ decompress $abs_file xz "--quiet --decompress" $file
+ ;;
+ *)
+ ice "unhandled file type: $file_type"
+ ;;
+ esac
+
+ if [ $failed -eq 0 ];
+ then
+ # Now scan the file(s) created in the previous step.
+ run find . -type f -execdir $abs_prog $prog_opts -t=$tmp_root/$file -p=$file $abs_script $script_opts {} +
+ fi
+
+ verbose " Deleting temporary directory: $tmp_root"
+ rm -fr $tmp_root
+
+ verbose " Return to previous directory"
+ popd > /dev/null
+}
+
+# Invoke main
+main ${1+"$@"}
+```
+
+
+
+Git has extensions for handling binary blobs such as multimedia files, so today we will learn how...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/run-binaries-script
+
+作者:[Nick Clifton][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/nickclifton
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/binary_code_computer_screen.png?itok=7IzHK1nn (Binary code on a computer screen)
+[2]: mailto:nickc@redhat.com
diff --git a/sources/tech/20200323 5 Python scripts for automating basic community management tasks.md b/sources/tech/20200323 5 Python scripts for automating basic community management tasks.md
new file mode 100644
index 0000000000..3f8dd00aa1
--- /dev/null
+++ b/sources/tech/20200323 5 Python scripts for automating basic community management tasks.md
@@ -0,0 +1,114 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (5 Python scripts for automating basic community management tasks)
+[#]: via: (https://opensource.com/article/20/3/automating-community-management-python)
+[#]: author: (Rich Bowen https://opensource.com/users/rbowen)
+
+5 Python scripts for automating basic community management tasks
+======
+If you have to do something three times, try to automate it.
+![shapes of people symbols][1]
+
+I've [written before about what a community manager does][2], and if you ask ten community managers, you'll get 12 different answers. Mostly, though, you do what the community needs for you to do at any given moment. And a lot of it can be repetitive.
+
+Back when I was a sysadmin, I had a rule: if I had to do something three times, I'd try to automate it. And, of course, these days, with awesome tools like Ansible, there's a whole science to that.
+
+Some of what I do on a daily or weekly basis involves looking something up in a few places and then generating some digest or report of that information to publish elsewhere. A task like that is a perfect candidate for automation. None of this is [rocket surgery][3], but when I've shared some of these scripts with colleagues, invariably, at least one of them turns out to be useful.
+
+[On GitHub][4], I have several scripts that I use every week. None of them are complicated, but they save me a few minutes every time. Some of them are in Perl because I'm almost 50. Some of them are in Python because a few years ago, I decided I needed to learn Python. Here's an overview:
+
+### **[tshirts.py][5]**
+
+This simple script takes a number of Tshirts that you're going to order for an event and tells you what the size distribution should be. It spreads them on a normal curve (also called a bell curve), and, in my experience, this coincides pretty well with what you'll actually need for a normal conference audience. You might want to adjust the script to slightly larger if you're using it in the USA, slightly smaller if you're using it in Europe. YMMV.
+
+Usage:
+
+
+```
+[rbowen@sasha:community-tools/scripts]$ ./tshirts.py
+How many shirts? 300
+For a total of 300 shirts, order:
+
+30.0 small
+72.0 medium
+96.0 large
+72.0 xl
+30.0 2xl
+```
+
+### **[followers.py][6]**
+
+This script provides me with the follower count for Twitter handles I care about.
+
+This script is only 14 lines long and isn't exciting, but it saves me perhaps ten minutes of loading web pages and looking for a number.
+
+You'll need to edit the feeds array to add the accounts you care about:
+
+
+```
+feeds = [
+ 'centosproject',
+ 'centos'
+ ];
+```
+
+NB: It probably won't work if you're running it outside of English-speaking countries, because it's just a simple screen-scraping script that reads HTML and looks for particular information buried within it. So when the output is in a different language, the regular expressions won't match.
+
+Usage:
+
+
+```
+[rbowen@sasha:community-tools/scripts]$ ./followers.py
+centosproject: 11,479 Followers
+centos: 18,155 Followers
+```
+
+### **[get_meetups][7]**
+
+This script fits into another category—API scripts. This particular script uses the [meetup.com][8] API to look for meetups on a particular topic in a particular area and time range so that I can report them to my community. Many of the services you rely on provide an API so that your scripts can look up information without having to manually look through web pages. Learning how to use those APIs can be frustrating and time-consuming, but you'll end up with skills that will save you a LOT of time.
+
+_Disclaimer: [meetup.com][8] changed their API in August of 2019, and I have not yet updated this script to the new API, so it doesn't actually work right now. Watch this repo for a fixed version in the coming weeks._
+
+### **[centos-announcements.pl][9]**
+
+This script is considerably more complicated and extremely specific to my use case, but you probably have a similar situation. This script looks at a mailing list archive—in this case, the centos-announce mailing list—and finds messages that are in a particular format, then builds a report of those messages. Reports come in a couple of different formats—one for my monthly newsletter and one for scheduling messages (via Hootsuite) for Twitter.
+
+I use Hootsuite to schedule content for Twitter, and they have a convenient CSV (comma-separated value) format that lets you bulk-schedule a whole week of tweets in one go. Auto-generating that CSV from various data sources (i.e., mailing lists, blogs, other web pages) can save you a lot of time. Do note, however, that this should probably only be used for a first draft, which you then examine and edit yourself so that you don't end up auto-tweeting something you didn't intend to.
+
+### **[reporting.pl][10]**
+
+This script is also fairly specific to my particular needs, but the concept itself is universal. I send out a monthly mailing to the [CentOS SIGs][11] (Special Interest Groups), which are scheduled to report in that given month. This script simply tells me which SIGs those are this month, and writes the email that needs to go to them.
+
+It does not actually send that email, however, for a couple of reasons. One, I may wish to edit those messages before they go out. Two, while scripts sending email worked great in the old days, these days, they're likely to result in getting spam-filtered.
+
+### In conclusion
+
+There are some other scripts in that repo that are more or less specific to my particular needs, but I hope at least one of them is useful to you, and that the variety of what's there inspires you to automate something of your own. I'd love to see your handy automation script repos, too; link to them in the comments!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/automating-community-management-python
+
+作者:[Rich Bowen][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/rbowen
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/Open%20Pharma.png?itok=GP7zqNZE (shapes of people symbols)
+[2]: http://drbacchus.com/what-does-a-community-manager-do/
+[3]: https://6dollarshirts.com/rocket-surgery
+[4]: https://github.com/rbowen/centos-community-tools/tree/master/scripts
+[5]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/tshirts.py
+[6]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/followers.py
+[7]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/get_meetups
+[8]: http://meetup.com
+[9]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/centos-announcements.pl
+[10]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/sig_reporting/reporting.pl
+[11]: https://wiki.centos.org/SpecialInterestGroup
diff --git a/sources/tech/20200326 How to detect outdated Kubernetes APIs.md b/sources/tech/20200326 How to detect outdated Kubernetes APIs.md
new file mode 100644
index 0000000000..a45a9b2add
--- /dev/null
+++ b/sources/tech/20200326 How to detect outdated Kubernetes APIs.md
@@ -0,0 +1,234 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to detect outdated Kubernetes APIs)
+[#]: via: (https://opensource.com/article/20/3/deprek8)
+[#]: author: (Tyler Auerbeck https://opensource.com/users/tylerauerbeck)
+
+How to detect outdated Kubernetes APIs
+======
+Deprek8 and Conftest alert you about deprecated APIs that threaten to
+slip into your codebase.
+![Ship captain sailing the Kubernetes seas][1]
+
+Recently, deprecated APIs have been wreaking havoc on everyone's [Kubernetes][2] manifests. Why is this happening?!? It's because the objects that we've come to know and love are moving on to their new homes. And it's not like this happened overnight. Deprecation warnings have been in place for quite a few releases now. We've all just been lazy and thought the day would never come. Well, _it's here_!
+
+So, maybe it caught up to us this time. But we'll be prepared next time, right?!? Yeah, that's what we said last time. But what if we could put something in place that makes sure that this doesn't happen?
+
+### What is Deprek8?
+
+[Deprek8][3] is a set of [Open Policy Agent][4] (OPA) policies that allow you to check your repository for deprecated API versions. These policies offer a way to provide warnings and errors when something is in the process of being or has already been deprecated. But **Deprek8** is just a set of policies that define what to watch for. How do you actually actively use these policies in order to monitor for deprecations?
+
+There are a number of ways and tools that can do this; one way is to use the OPA Deprek8 policy.
+
+### What is the OPA Deprek8 policy?
+
+OPA is "an open source, general-purpose policy engine that enables unified, context-aware policy enforcement." In other words, OPA provides a means of establishing and enforcing a set of policies based upon a policy file. The policies are defined in a file (or set of files) using the [Rego query language][5]. This use case won't necessarily rely on the OPA application, but more specifically, it uses this query language to do the heavy lifting. By using Rego, you can check whether various manifests match certain criteria and then either warn or error them out based on your definition. For example, in Kubernetes 1.16, the Deployment object can no longer be served from the **extensions/v1beta1 apiVersion**. So in your .rego file, you could have something like:
+
+
+```
+_deny = msg {
+ resources := ["Deployment"]
+ input.apiVersion == "extensions/v1beta1"
+ input.kind == resources[_]
+ msg := sprintf("%s/%s: API extensions/v1beta1 for %s is no longer served by default, use apps/v1 instead.", [input.kind, input.metadata.name, input.kind])
+}
+```
+
+This would alert that you have a deprecated manifest and print a message like:
+
+> Deployment/myDeployment: API extensions/v1beta1 for Deployment is no longer served by default, use apps/v1 instead.
+
+That's great! This is exactly what you need in order to avoid having old manifests lying around. But these are just the policies; you need something that will check these policies and put them into action.
+
+### Conftest
+
+This is where [Conftest][6] comes in. Conftest is a utility that allows you to put Rego policies into action against any number of configuration files. According to the repo, Conftest currently supports:
+
+
+```
+ - YAML
+ - JSON
+ - INI
+ - TOML
+ - HOCON
+ - HCL
+ - CUE
+ - Dockerfile
+ - HCL2 (Experimental)
+ - EDN
+ - VCL
+ - XML
+```
+
+It has some fairly strict defaults (i.e., expecting policy files to be in certain locations), but they can be overridden with the appropriate flags if you have a layout that you prefer. If you want to know more about those specifics, please consult the [documentation][7] in the repository.
+
+For example, you can run any policy file on Conftest with a command like:
+
+
+```
+`helm template --set podSecurityPolicy.enabled=true --set server.ingress.enabled=true . | conftest -p mypolicy.rego -`
+```
+
+This would generate the appropriate output from a Helm template and pipe it directly to the Conftest utility. Conftest inspects that output against any policies defined in the **mypolicy.rego** file and then gives any appropriate warnings or errors for objects that match against those policies. You can, of course, swap out any templating tooling of your choice, or you can feed specific files directly to the Conftest tool.
+
+So now you have the tools to set your policies and enforce them against your configuration files. But how do you tie these two things together? Better yet: How do you automate this process to continuously monitor the codebase to make sure you never fall behind the deprecation line again?
+
+### Using Git to run checks
+
+There are many methods and tools to run checks against code. By adding similar steps to your continuous integration (CI) tooling (e.g., Jenkins, Tekton, etc.), you can accomplish the same goal. In this very basic use case, I used [GitHub Actions][8], a new feature of GitHub repositories.
+
+GitHub Actions allows you to automate your entire workflow, so you don't have to sit in front of your keyboard and hack all of this together. With Actions, you can string together any number of steps into a workflow (or multiple workflows) by either rolling your own Actions if you're doing something custom or, in most cases, using something that already exists in the [Marketplace][9]. Luckily, others have provided Actions to do the things you need to do for this example, so you can lean on the community's expertise to pull your workflow together.
+
+As described in the steps above, the workflow looks something like:
+
+ 1. Retrieve the Deprek8 policy you need and store it somewhere for later use.
+ 2. Run Conftest against the appropriate files/charts with the policy file you grabbed in step 1.
+
+
+
+What does this boil down to? Well, all you really need to do is to use curl to pull your policy file and then run it through Conftest after pointing to your code, using the [curl][10] and [Conftest][11] Actions. Since these Actions already exist, you don't need to write any custom code! And as I'm sure you can tell by the names, they allow you to run the associated commands without having to do any custom work to pre-process anything or pull down any binaries.
+
+Now that you have the Actions you need to use, how do you pull them together? This is where your workflow comes into play. While Actions are the pieces of code that get things done, they're useless without a way to string them together so that they can be triggered by some event. A GitHub Action workflow will look something like this:
+
+
+```
+name: Some Awesome Workflow Name
+on: An Event That Triggers Our Workflow
+jobs:
+ awesome-job-name:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: awesome-step-name
+ uses: someorg/someaction@version
+ with:
+ args: some args that I might pass to someaction
+```
+
+Now you have a workflow that has multiple steps, can be triggered by a specific GitHub event, and can be passed a set of parameters (if that is applicable to that specific Action). This example is _extremely basic_. But luckily, the workflow you're trying to put together is equally simple. This shouldn't be taken as a comprehensive example of a GitHub Action, as there are many more complicated (and elegant) things you can do. If you're interested in learning more, take a look at the [GitHub Actions documentation][12].
+
+Now that you have an idea of what a workflow looks like and know what Actions you're interested in using, take a run at plugging the two together. For this example, you want to make sure that whenever your code is updated, it's checked to make sure it's not using any deprecated APIs.
+
+First, rig up your workflow with some names and the events that you want to trigger off of. Give your workflow and job a useful name that will help you identify it (and what it does).
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+```
+
+Next, you need to tell your workflow that you want to trigger these Actions based on any **pull_request** or **push** that happens to this repository because these are the two main events that get new code into a repository. You can do this by utilizing the **on** keyword.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+```
+
+Then, add where you want these Actions to run and how the Action can get the code. You can tell the Action where to run by using the **runs-on** keyword. You have a few options here: Windows, Mac, or Ubuntu. In most cases, using Ubuntu is fine, as you'll frequently rely on Actions that run inside their own container (versus running on the base OS that you define here). It's also very important to understand that an Action does not check out code by default. When you need to do something that interacts with your code, make sure to use the Action **actions/checkout**. When this is included, your code will be available within your Action, and you can pass that through to the next step in your workflow.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+name: API Deprecation Check
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: curl
+ uses: wei/curl@master
+ with:
+ args: > /github/home/deprek8.rego
+```
+
+Now that your code is checked out, you can start preparing to do something with it. As mentioned, before you can check code for deprecations, you first need the file that contains the policies that you want to check for, so just retrieve the file using the **curl** Action. This is a fairly straightforward Action, in that it accepts whatever parameters you would normally pass into the curl command. If you were doing something more complicated, this is where you could pass in things like specific HTTP Actions, headers, etc. However, in this case, you're just trying to retrieve a file, so the only thing you need to pass to your Action is the URL you want to retrieve (in this case, the one that contains your raw policy file) and then tell it where you want to write that file. In this case, you're going to have it write to **/github/home**. Why? It's because this filesystem persists between steps and will allow you to use the policy file within this next step.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: curl
+ uses: wei/curl@master
+ with:
+ args: > /github/home/deprek8.rego
+ - name: Check helm chart for deprecation
+ uses: instrumenta/conftest-action/helm@master
+ with:
+ chart: nginx-test
+ policy: /github/home/deprek8.rego
+```
+
+Now that you have your policy file, it's just a matter of running it against the code via **conftest**. Similar to the **curl** Action, the **conftest** Action just expects a series of parameters to understand how it should run against the code. In the example above, it runs against a Helm chart, but it can run against a specific file (or set of files) by changing the **uses** value to **instrumenta/[conftest-action@master][13]**. Just point to the path where your chart sits in the repository and then provide the path to your policy file (specified in the previous step). Once you have all of this together, you have a complete workflow. But what does this look like (assuming there's some bad code in your Helm chart)? To find out, take a look at the [example repository][14].
+
+In the Nginx Helm chart, you'll notice that one of the templates is a [statefulset][15]. You may also notice that the apiVersion the StatefulSet is using is **apps/v1beta1**. This API was deprecated in Kubernetes 1.16 and is now hosted in **apps/v1**. So when your GitHub Actions workflow runs, it should detect this issue and serve an error like:
+
+
+```
+FAIL - StatefulSetf/web: API apps/v1beta1 is no longer served by default, use apps/v1 instead.
+Error: plugin "conftest" exited with error
+##[error]Docker run failed with exit code 1
+```
+
+The Action indicates there is something wrong and then fails the rest of the Action. You can see the [full workflow][16] if you are interested.
+
+### Wrapping up
+
+This workflow will save some future heartache by alerting you to any deprecated APIs that slip into your codebase. To be clear, this is an _alerting_ mechanism. This won't prevent you from merging bad code into your codebase. But, as long as you pay attention, you should be completely aware prior to (or just after) merging problematic code.
+
+Where do you go from here? Well, there are a few things to keep in mind. Currently, Deprek8 is up to date as of Kubernetes 1.16. If you're interested in more recent versions, I'm sure Deprek8 would be happy to accept your [pull request][3].
+
+The other shortcoming of this method is that the **conftest** and GitHub Actions are a bit limited in that they only allow you to point at specific files or a single chart at a time. What if you want to point at multiple directories of manifests or have multiple charts inside your repository? Currently, the only way to get around that is to either list out every single file you're interested in (in the case of having multiple charts) or have multiple steps inside your workflow. Other scenarios could become problematic, like other templating engines that require some custom logic to pair the parameters and template files together. But a simple workaround for that could be to have a step in your workflow that pulls down Conftest along with a tiny inline script to loop through some of this. I'm sure there are more elegant solutions (and if you come up with one, I'm sure these projects would be more than happy to take a look at your PR).
+
+Regardless, you now have a mechanism that should allow you to sleep a bit easier when checking in your code! And hopefully, this method will help you build even more robust workflows to protect your code.
+
+* * *
+
+_This was originally published in [Tyler Auerbeck's GitHub repository][17] and is reposted, with edits, with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/deprek8
+
+作者:[Tyler Auerbeck][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/tylerauerbeck
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
+[2]: https://opensource.com/resources/what-is-kubernetes
+[3]: https://github.com/naquada/deprek8
+[4]: https://github.com/open-policy-agent/opa
+[5]: https://blog.openpolicyagent.org/opas-full-stack-policy-language-caeaadb1e077
+[6]: https://github.com/instrumenta/conftest
+[7]: https://github.com/instrumenta/conftest/tree/master/docs
+[8]: https://github.com/features/actions
+[9]: https://github.com/marketplace?type=actions
+[10]: https://github.com/marketplace/actions/github-action-for-curl
+[11]: https://github.com/instrumenta/conftest-action
+[12]: https://help.github.com/en/actions
+[13]: mailto:conftest-action@master
+[14]: https://github.com/tylerauerbeck/deprek8-example
+[15]: https://raw.githubusercontent.com/tylerauerbeck/deprek8-example/master/nginx-test/templates/statefulset.yaml
+[16]: https://github.com/tylerauerbeck/deprek8-example/runs/426774566?check_suite_focus=true
+[17]: https://github.com/tylerauerbeck/writing/blob/master/opa/deprek8.md
diff --git a/sources/tech/20200327 KubeCF Is What DevOps Wanted- Marrying Cloud Foundry with Kubernetes.md b/sources/tech/20200327 KubeCF Is What DevOps Wanted- Marrying Cloud Foundry with Kubernetes.md
new file mode 100644
index 0000000000..f306d94bc7
--- /dev/null
+++ b/sources/tech/20200327 KubeCF Is What DevOps Wanted- Marrying Cloud Foundry with Kubernetes.md
@@ -0,0 +1,79 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (KubeCF Is What DevOps Wanted: Marrying Cloud Foundry with Kubernetes )
+[#]: via: (https://www.linux.com/articles/kubecf-is-what-devops-wanted-marrying-cloud-foundry-with-kubernetes/)
+[#]: author: (Swapnil Bhartiya https://www.linux.com/author/swapnil/)
+
+KubeCF Is What DevOps Wanted: Marrying Cloud Foundry with Kubernetes
+======
+
+[![][1]][2]
+
+There are times when solutions that seem to compete against each other turn out to be complementary. [This is exactly what happened with Cloud Foundry and Kubernetes. ][3]
+
+“Enterprises have moved on from the debate around Cloud Foundry Application Runtime or PaaS experience versus Kubernetes-based experience, and have opted to adopt both. The PaaS experience that Cloud Foundry offers is about optimizing developer time by allowing them to focus on business problems. Let them focus on the app they’re trying to build, not on the plumbing underneath it,” says Chip Childers, CTO at Cloud Foundry Foundation.
+
+“There are plenty of use cases that don’t fit into a PaaS-style architecture. If you look at the breadth of architectures that a typical enterprise deals with, there are tons of applications that you need to just wrap the thing in a container and operate it that way,” he says.
+
+**Integrating Cloud Foundry and Kubernetes **
+
+To incorporate Kubernetes into the Cloud Foundry architecture so Cloud Foundry users can use Kubernetes as an alternative to Diego/Garden to orchestrate application container instances, Cloud Foundry Foundation kickstarted an initiative called [Project Eirini][4].
+
+Similarly, [Project Quarks][5] is another incubating effort within the Cloud Foundry Foundation that is focused on packaging the Cloud Foundry Application Runtime as a set of containers instead of virtual machines, enabling easier deployment to Kubernetes.
+
+“Project Quarks took some code from SUSE called Fizzle. It would take the type of release artifact that our project teams were generally releasing for their component of the system, and work it into a usable Docker image. Then they would use Helm and some scripts to deploy that into Kubernetes,” said Childers.
+
+There was, however, one crucial piece of the jigsaw missing.
+
+“There was this code that SUSE had been working on. It was the basis of the SUSE product called SCF (SUSE Cloud Foundry). SCF became [KubeCF][6]. It creates a Kubernetes native distribution of Cloud Foundry,” reveals Childers.
+
+KubeCF recently hit its 1.0 release. So, where does KubeCF go from here?
+
+“Presenty, we can look at it as the easiest path to a Kubernetes-native Cloud Foundry for pure open search users. There are some other efforts that are happening in parallel that are taking a look at each component of the Cloud Foundry architecture. Project architects are working towards allowing people to take KubeCF, deploy the whole system to Kubernetes, and take advantage of the simplicity that gets enabled as code gets modified,” says Childers.
+
+**Developers First: Ensuring Seamless UX**
+
+One of the strengths of the Cloud Foundry community is that it has always offered a distribution. There is still a distribution called CF deployment, which is based on a VM-centric architecture that uses the Cloud Foundry BOSH platform to orchestrate infrastructures and service environments (or virtualized environments like V-sphere) to deploy VMs and then run the system on top of it.
+
+However, distribution also entails members of the ecosystem packaging it or dictating with their own offerings. In such a scenario, how can developers expect consistency across the distros?
+
+“The commonality between both upstream releases — the CF deployment and KubeCF — lies in the components that they sew together to create the Cloud Foundry platform. The Cloud Foundry Platform certification continues to be based on the idea that a certified distribution uses those components in an unmodified way, and integrates them to create that developer experience,” Childers explains.
+
+“So, regardless of whether you’re deploying to Kubernetes or you’re deploying to virtual machines, regardless of the certified vendor that you use, or if you use upstream distributions, you should have that same developer experience. That’s what Platform Certification ensures,” he says.
+
+Operational consistency is less a concern for the ecosystem and the community because many of these providers are offering it as a service. “Those that do it as subscription-based software delivery have a lot of tooling around operations that’s specific to them plus all of the other values that they bring together,” Childers avers.
+
+**Evolution Unabated**
+
+The KubeCF distribution has finally put the debate of ‘Do I use Kubernetes or do I use Cloud Foundry?’ to rest.
+
+“The answer should’ve always been ‘You use both.’ The architecture fits one on top of the other very nicely, and overcomes the concerns of dual stacks,” says Childers.
+
+With the ‘either-or’ debate over, Chip intends to further evolve this architecture, thereby offering an enormous amount of value to enterprises trying to deal with container-centric infrastructure management and developer productivity.
+
+“We’ve completely re-converged as an ecosystem around embracing the Kubernetes-based infrastructure as being the most popular and rising approach. We’ve been evolving this architecture as a community for years now,” he says.
+
+“There are huge engineering and commercial teams supporting Kubernetes. VMware has an enormous investment in Kubernetes, and it continues to increase that investment. With the acquisition of Pivotal, VMware also has a huge amount of investment in Cloud Foundry. It’s working aggressively on the mission of bringing the two together. We see the same traction with SAP, IBM, and SUSE, which presents a lot of opportunities for everybody,” adds Childers.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/articles/kubecf-is-what-devops-wanted-marrying-cloud-foundry-with-kubernetes/
+
+作者:[Swapnil Bhartiya][a]
+选题:[lujun9972][b]
+译者:[译者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/author/swapnil/
+[b]: https://github.com/lujun9972
+[1]: https://www.linux.com/wp-content/uploads/2020/03/color-3580779_1920-1068x667.jpg (color-3580779_1920)
+[2]: https://www.linux.com/wp-content/uploads/2020/03/color-3580779_1920.jpg
+[3]: https://www.tfir.io/kubecf-a-kubernetes-native-distribution-of-cloud-foundry-chip-childers-cto-cloud-foundry-%e2%80%8bfoundation/
+[4]: https://www.cloudfoundry.org/project-eirini/
+[5]: https://www.cloudfoundry.org/project-quarks/
+[6]: https://github.com/cloudfoundry-incubator/kubecf
diff --git a/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md b/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md
new file mode 100644
index 0000000000..dce9c83a0e
--- /dev/null
+++ b/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md
@@ -0,0 +1,82 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source fights against COVID-19, Google's new security tool written in Python, and more open source news)
+[#]: via: (https://opensource.com/article/20/3/news-march-28)
+[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
+
+Open source fights against COVID-19, Google's new security tool written in Python, and more open source news
+======
+Catch up on the biggest open source headlines from the past two weeks.
+![][1]
+
+In this edition of our open source news roundup, we take a look open source solutions for COVID-19, Google's new security tool, code cleanup software from Uber, and more!
+
+### Using open source in the fight against COVID-19
+
+When COVID-19 started its march around the world, open source [stepped up][2] to try to help stop it. That includes using open data to [create tracking dashboards and apps][3], designing ventilators, and developing protective gear.
+
+Scientists at the University of Waterloo in Canada have teamed with artificial intelligence firm DarwinAI to create an open source tool "[to identify signs of Covid-19 in chest x-rays][4]." Called COVID-Net, it's neural network "that is particularly good at recognizing images." The dataset the researchers are using is [available on GitHub][5], which includes a link the software.
+
+Additionally, many [open source hardware projects][6] are underway to expedite the search for a cure.
+
+### Google releases tool to fight USB keystroke injection attacks
+
+One of the sneakiest and potentially most malicious ways to hack a computer is a USB keystroke injection attack. Using a compromised USB device connected to a computer, a hacker can run commands without you even noticing. Google's making it easier for Linux users to fight back against these kinds of attacks by releasing [an open source detection tool][7].
+
+Called USB Keystroke Injection Protection, the tool detects "if the keystrokes have been made without human involvement". It does that by measuring "the timing of keystrokes coming from connected USB devices." Sebastian Neuner of Google's Information Security Engineering Team said that while the USB Keystroke Injection Protection tool isn't the last word in defense against these kinds of attacks, but offers "another layer of protection and to defend a user sitting in front of their unlocked machine by them seeing the attack happening."
+
+You can find the Python source code for the tool [on GitHub][8].
+
+### Uber makes code deletion tool open source
+
+As applications get bigger, they often contain code that's either no longer used or which is obsolete. That added code make software more difficult to maintain. To help solve the problem of quickly finding that redundant code, Uber recently [open sourced a tool called Pirhana][9].
+
+Pirhana scans code for [feature flags][10], looking for ones that are no longer used. The software then deletes the unused flags from the code. At the moment, Pirhana works with software written in the Objective-C, Swift, and Java languages. Uber's developers hope the number of supported languages will increase "now that outside developers have an opportunity to contribute to the project."
+
+You can grab [Pirhana's source code][11] from its repository on GitHub
+
+#### In other news
+
+ * [Singapore government to open source contact-tracing protocol][12]
+ * [European Commission to use open source messaging service Signal][13]
+ * [Spanish software to computerize healthcare in Cameroon and India][14]
+ * [ING Open-Sources Lion, Its White-Label Web Component Library][15]
+ * [Open Source Goes Mainstream – How Sharing Is Shaping The Future Of Music][16]
+
+
+
+Thanks, as always, to Opensource.com staff members and [Correspondents][17] for their help this week.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/news-march-28
+
+作者:[Scott Nesbitt][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/scottnesbitt
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/weekly_news_roundup_tv.png?itok=tibLvjBd
+[2]: https://jaxenter.com/covid-19-open-source-170237.html
+[3]: https://opensource.com/article/20/3/open-source-software-covid19
+[4]: https://www.technologyreview.com/s/615399/coronavirus-neural-network-can-help-spot-covid-19-in-chest-x-ray-pneumonia/
+[5]: https://github.com/lindawangg/COVID-Net
+[6]: https://opensource.com/article/20/3/open-hardware-covid19
+[7]: https://www.zdnet.com/article/google-linux-systems-can-use-this-new-tool-against-usb-keystroke-injection-attacks/
+[8]: https://github.com/google/ukip
+[9]: https://siliconangle.com/2020/03/17/ubers-open-source-piranha-tool-hunts-redundant-application-code/
+[10]: https://en.wikipedia.org/wiki/Feature_toggle
+[11]: https://github.com/uber/piranha
+[12]: https://www.computerweekly.com/news/252480501/Singapore-government-to-open-source-contact-tracing-protocol
+[13]: https://joinup.ec.europa.eu/collection/open-source-observatory-osor/news/signal-messaging-service
+[14]: https://intallaght.ie/spanish-software-to-computerize-healthcare-in-cameroon-and-india/
+[15]: https://www.infoq.com/articles/ing-open-sources-lion-web-component/
+[16]: https://www.forbes.com/sites/andreazarczynski/2020/03/19/open-source-goes-mainstream--how-sharing-is-shaping-the-future-of-music/#9e1ca1290013
+[17]: https://opensource.com/correspondent-program
diff --git a/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md b/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md
new file mode 100644
index 0000000000..82d84f984b
--- /dev/null
+++ b/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md
@@ -0,0 +1,154 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Nextcloud: The Swiss Army Knife of Remote Working Tools)
+[#]: via: (https://itsfoss.com/nextcloud/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+Nextcloud: The Swiss Army Knife of Remote Working Tools
+======
+
+Remote working culture has been booming for past few years in coding, graphics and other IT related fields. But the recent [Coronavirus pandemic][1] has made it mandatory for the companies to work from home if it’s possible for them.
+
+While there are tons of tools to help you and your organization in working from home, let me share one open source software that has the features of several such tools combined into one.
+
+### Nextcloud Hub: A Suite of Essential Tools for Remote Collaboration
+
+[Nextcloud][2] is an open source software that can be used to store files, photos and videos for personal usage like Dropbox. But it’s more than just a private [cloud service][3].
+
+You can add more than one users in Nextcloud and turn it into a collaboration platform for editing files in real time, chat with users, manage calendars, assign and manage tasks and more.
+
+This video gives a good overview of its main features:
+
+[Subscribe to our YouTube channel for more Linux videos][4]
+
+### Main Features of Nextcloud
+
+Let me highlight the main features of Nextcloud:
+
+#### Sync files and share
+
+![Nextcloud Files][5]
+
+You can create workspaces based on user groups and share files in those folders. Users can create private files and folders and share them with selected users internally or externally (if they are allowed to). You can lock files in read only mode as well.
+
+It also has a very powerful search feature that lets you search files from their name or tags. You can comment on files to provide feedback.
+
+Text files can be edited in real time thanks to its builtin markdown editor. You can use OnlyOffice or Collabora to allow editing of docs, spreadsheet and presentations in real time.
+
+It also has version control for the files so that you can revert changes easily.
+
+#### Text Chat, Audio Chat, Video Chat and Web Meetings
+
+![Nextcloud Video Call][6]
+
+With NextCloud Talk, you can interact with other users by text messaging, audio calls, video calls and group calls for web meetings. You can also take meeting minutes during the video calls and share your screen for presentations. There is also a mobile app to stay connected all the time.
+
+You can also create Slack like channels (known as circles) to communicate between members concerned with a specific topic.
+
+#### Calendar, Contacts & Mail
+
+![Calendar Nextcloud][7]
+
+You can manage all of your organization’s contact, divide them into groups based on departments.
+
+With the calendar, you can see when someone is free or what meetings are taking place, like you do on Outlook.
+
+You can also use the Mail feature and import the emails from other providers to use them inside Nextcloud interface.
+
+#### Kanban project management with Deck
+
+![][8]
+
+Like Trello and Jira, you can create boards for various projects. You can create cards for each tasks, assign them to users and they can move it between the list based on the status of the task. It’s really up to you how you create boards to manage your projects in Kanban style.
+
+#### Plenty of add-ons to get more out of Nextcloud
+
+![Password Manager][9]
+
+Nextcloud also has several add-ons (called apps). Some are developed by Nextcloud teams while some are from third-party developers. You may use them to extend the capability of Nextcloud.
+
+For example, you can add a [Feedly style feed reader][10] and read news from various sources. Similarly, the [Paswords addon][11] lets you use Netxcloud as a password manager. You can even share common passwords with other Nextcloud users.
+
+You can explore [all the apps on its website][12]. You’ll also notice the ratings of apps that will help you decide if you should use an app or not.
+
+#### Many more features
+
+Let me summarize all the features here:
+
+ * Open source software that lets you own your data on your own servers
+ * Seamlessly edit office documents together with others
+ * Communicate with other members of your organization and do audio and video calls and held web meetings
+ * Calendar lets you book meetings, brings busy view for meetings and resource booking and more
+ * Manage users locally or authenticate through LDAP / Active Directory, Kerberos and Shibboleth / SAML 2.0 and more
+ * Secure data with powerful file access control, multi-layer encryption, machine-learning based authentication protection and advanced ransomware recovery capabilities
+ * Access existing storage silos like FTP, Windows Network Drives, SharePoint, Object Storage and Samba shares seamlessly through Nextcloud.
+ * Automation: Automatically turn documents in PDFs, send messages to chat rooms and more!
+ * Built in ONLYOFFICE makes collaborative editing of Microsoft Office documents accessible to everyone
+ * Users can install desktop and mobile apps or simply use it in web browser
+
+
+
+### How to get Nextcloud
+
+![][13]
+
+NextCloud is free and open source software. You can download it and install it on your own server.
+
+You can use cloud server providers like [Linode][14] or [DigitalOcean][15] that allow you to deploy a brand new Linux server within minutes. And then you can use Docker to install NextCloud. At It’s FOSS, we use [Linode][14] for our NextCloud instance.
+
+If you don’t want to do that, you can [signup with one of the Nextcloud partners][16] that provide you with configured Nextcloud instance. Some providers also provide a few GB of free data to try it.
+
+Nextcloud also has an [enterprise plan][17] where Nextcloud team itself handles everything for the users and provide premium support. You can check their pricing [here][18].
+
+If you decide to use Nextcloud, you should refer to its documentation or community forum to explore all its features.
+
+### Conclusion
+
+At It’s FOSS, our entire team works remote. We have no centralized office anywhere and all of us work from our home. Initially we relied on non-open source tools like Slack, Google Drive etc but lately we are migrating to their open source alternatives.
+
+Nextcloud is one of the first software we tried internally. It has features of Dropbox, Google Docs, [Slack][19], [Trello][20], Google Hangout all combined in one software.
+
+NextCloud works for most part but we found it struggling with the video calls. I think that has to do with the fact that we have it installed on a server with 1 GB of RAM that also runs some other web services like [Ghost CMS][21]. We plan to move it to a server with better specs. We’ll see if that should address these issues.
+
+Since the entire world is struggling with the Coronavirus pandemic, using a solution like Nextcloud could be helpful for you and your organization in working from home.
+
+How are you coping during the Coronavirus lockdown? Like [Linus Torvalds’ advice on remote working][22], do you also have some suggestion to share with the rest of us? Please feel free to use the comment section.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/nextcloud/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://en.wikipedia.org/wiki/2019%E2%80%9320_coronavirus_pandemic
+[2]: https://nextcloud.com/
+[3]: https://itsfoss.com/cloud-services-linux/
+[4]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
+[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_files.png?ssl=1
+[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_video_call.jpg?ssl=1
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/calendar_nextcloud.jpeg?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_kanban_project_management_app.jpeg?ssl=1
+[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/passman.png?fit=800%2C389&ssl=1
+[10]: https://apps.nextcloud.com/apps/news
+[11]: https://apps.nextcloud.com/apps/passwords
+[12]: https://apps.nextcloud.com/
+[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud-feature.jpg?ssl=1
+[14]: https://www.linode.com/?r=19db9d1ce8c1c91023c7afef87a28ce8c8c067bd
+[15]: https://m.do.co/c/d58840562553
+[16]: https://nextcloud.com/signup/
+[17]: https://nextcloud.com/enterprise/
+[18]: https://nextcloud.com/pricing/
+[19]: https://slack.com/
+[20]: https://trello.com/
+[21]: https://itsfoss.com/ghost-3-release/
+[22]: https://itsfoss.com/torvalds-remote-work-advice/
diff --git a/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md b/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md
new file mode 100644
index 0000000000..079e775ce1
--- /dev/null
+++ b/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md
@@ -0,0 +1,233 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Access control lists and external drives on Linux: What you need to know)
+[#]: via: (https://opensource.com/article/20/3/external-drives-linux)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Access control lists and external drives on Linux: What you need to know
+======
+Learn how to use external drives correctly on Linux.
+![Penguin driving a car with a yellow background][1]
+
+While cloud storage offers many advantages, there's nothing quite like having your data on a physical hard drive. When you save data to a drive, you know exactly where your data is, and it's always available when you need it. When you save data to an external portable drive like a USB thumb drive, it's even better—not only do you know where your data is, but you can take your data with you everywhere you go. If you're new to [Linux][2], or you're trying to use a Linux file system on an external drive, you might find external drives confusing, being prone to permission errors or conflicts, or even losing metadata.
+
+There are two "right" answers to this:
+
+### ExFAT
+
+Formerly, ExFAT was a file system fraught with legal threats from Microsoft because they own the code. They've sued companies and organizations before to defend their ownership of FAT, so it was commonly feared that they could do the same over ExFAT. However, recently. Microsoft made the specifications for ExFAT open source. They didn't provide a driver, unfortunately, but there's an existing drive to make it function on Linux, and, now that developers have access to the full specs, improvements are inevitable.
+
+The advantage of ExFAT is that it's cross-platform (Windows, Mac, and many portable devices use it), and it's designed without the overhead of file permissions. You can attach a drive formatted as ExFAT to any computer, and all files are available to anyone. Whether that's good or bad depends on your use case, but for portable media, that's often exactly the intent.
+
+### Access control lists (ACL)
+
+If you prefer to use a Linux file system on your portable drive, then you can do that, but to make sharing files seamless, you should use access control lists (ACL).
+
+When you create a file or directory on a drive, there are defaults on your system determining what file permissions it gets. For most cases, those defaults make sense—when you create a file in your home directory, you probably don't want other users to have access to that file. However, when you're creating a file on an external drive, there's a high likelihood that it's because you need to share that file with someone else (even if that someone is you on another computer).
+
+You can override default permissions for file viewing with an ACL, and you can control default file creation mode by setting a sticky bit. An ACL is a layer of security policies in the extended attributes of directories and files. It allows you to specify exceptions to what the file system permissions indicate. Most notably, this allows you to transcend the single-owner and single-group model of traditional UNIX permissions.
+
+For instance, while the **seth** (ID 1000) account might own a directory created on my desktop, **seth** (ID 500) on my laptop does not, because the user IDs are different.
+
+The same could be true for a group. If a directory with group ID 1000 is assigned to a directory on one computer, then a group with an ID 500 or 10922 doesn't have access to it on another computer. But an ACL can add secondary owners and groups to directories and files.
+
+#### View the current ACL
+
+Any directory and file on any common Linux filesystem has ACL rules by default. They're stored in extended attributes, a kind of metadata that you don't normally see.
+
+You can view them in the terminal:
+
+
+```
+$ getfacl ./example
+# file: /run/media/drive/example
+# owner: seth
+# group: users
+user::rwx
+group::rwx
+other::r--
+```
+
+The commented lines are just for your reference; they tell you the path, and the owner and group, of the file or directory you're viewing information about. The next lines display the rules applied to the file or directory. In this example, the user permissions are set to **rwx**, the group to **r-x**, and other to **r-x**. These permissions are reflected by a normal filesystem list:
+
+
+```
+$ ls -lA /run/media/drive
+drwxrwxr-- 26 seth users 4096 Jan 16 21:04 example
+$ id
+uid=1000(seth) gid=100(users) groups=100(users)...
+```
+
+As long as user **seth** (UID 1000) or a member of **group** (GID 100) interacts with the **example** directory, full access is granted. Any other account, however, has only read (**r**) permission.
+
+#### Setting an ACL
+
+To modify an ACL, you use the **setfacl** command or use a file manager with ACL support. You can be very specific or very generic when setting your ACL.
+
+To just modify the filesystem permission settings, you can use either **chmod** or **setfacl**. This is a very generic ACL setting because you're not adding anything to the permissions already available to UNIX from the filesystem specification.
+
+
+```
+$ setfacl --modify g::r example
+$ getfacl ./example | grep "group::"
+group::r--
+$ ls -l . | grep example
+drwxr--r-- 26 seth users 4096 Jan 16 21:04 example
+```
+
+The same effect is available through **chmod**:
+
+
+```
+$ chmod g+x example
+$ getfacl ./example | grep "group::"
+group::r-x
+$ ls -l . | grep example
+drwxr-xr-- 26 seth users 4096 Jan 16 21:04 example
+```
+
+#### Adding users and groups
+
+To really benefit from an ACL is to use it for permissions outside the scope of native UNIX permissions. If I'm logged into my desktop as **seth** with user ID 1000, and I know that a directory on my portable drive needs to be usable by **seth** with ID 500 on my laptop, then just declaring **seth** as owner isn't enough because the user IDs aren't the same.
+
+You can add a user or user ID to an access control list:
+
+
+```
+$ setfacl --modify u:500:rwx example
+$ getfacl example
+# file: /run/media/drive/example
+# owner: seth
+# group: users
+user::rwx
+user:500:rwx
+[...]
+```
+
+A new entry, specific to user ID 500, has been added to the list. Attaching the drive to another Linux or UNIX computer now allows the user with ID 500 to access the **example** folder.
+
+You can also add users by account name, or groups by either group name or group ID. The IDs are what really count with permissions, though, so if you're in a mixed environment (RHEL servers and Elementary clients, for example), you should verify the user IDs and group IDs lurking behind accounts that seem, on the surface, identical.
+
+#### Setting default ACL rules
+
+If you treat access control as a one-time setting, you'll quickly run into problems once your different user accounts start creating files and directories. Any new file or directory created by each user inherits the system's default permissions (and ACL). This means that once laptop user **seth** with ID 500 creates a file in a directory, it could be off-limits to desktop user **seth** with ID 1000 because the owner of the file is set to UID 500.
+
+A default ACL can be applied to directories so that files and subdirectories created within them inherit the parent ACL. You can set the default ACL of a directory with the **–default** option:
+
+
+```
+$ setfacl --default --modify u:500:rwx example
+$ setfacl --default --modify u:1000:rwx example
+$ getfacl --omit-header example
+user::rwx
+user:500:rwx
+group::rw-
+mask::rwx
+other::r-x
+default:user::rwx
+default:group::rw-
+default:group:500:rwx
+default:group:1000:rwx
+default😷:rwx
+default:other::r-x
+```
+
+When a user creates a new directory within the **example** directory, the inherited ACL is the same as its parent:
+
+
+```
+$ cd example
+$ mkdir penguins
+$ getfacl --omit-header penguins
+user::rwx
+group::rw-
+group:500:rwx
+group:1000:rwx
+mask::rwx
+other::r-x
+default:user::rwx
+default:group::rw-
+default:group:500:rwx
+default:group:1000:rwx
+default😷:rwx
+default:other::r-x
+```
+
+This means that any directory or file created inherits the same ACL, so neither user 500 or 1000 are ever excluded from access.
+
+#### Pragmatic ACL for external drives
+
+When using a Linux filesystem for external drives, the easy method of ensuring it works with all the users who expect to use the portable drive is to set an ACL on a single top-level directory.
+
+For instance, assume you have formatted a USB drive called **mydrive** as an ext4 filesystem. You want your account on your laptop and your desktop, as well as your colleague Alice, to be able to access the files.
+
+First, create a directory at the top level of the drive:
+
+
+```
+$ mkdir /mnt/mydrive/umbrella
+```
+
+Then apply an ACL to the top-level directory to grant all-important users access:
+
+
+```
+$ setfacl --modify \
+ u:500:rwx,u:1000:rwx,u:alice:rwx \
+ /mnt/mydrive/umbrella
+```
+
+Finally, apply a default ACL so that all directories and files created within the top-level directory **umbrella** inherit the same default ACL (note that this command uses the short version of **–modify**):
+
+
+```
+$ setfacl --default -m u:500:rwx,u:1000:rwx,u:alice:rwx \
+ /mnt/mydrive/umbrella
+```
+
+#### Applying defaults to an existing system
+
+If you need to apply ACL settings to many files that already exist, you can accomplish that with the **find** command.
+
+First, find all directories and apply ACL rules:
+
+
+```
+$ find /mnt/mydrive/umbrella -type d | \
+ parallel --max-args=6 setfacl \
+ --default -m u:500:rwx,u:1000:rwx,u:alice:rwx
+```
+
+It's not wise to indiscriminately set all file permissions to executable, so next, find all files and set permissions to **re**. Files that require an executable bit can be set manually or by file extension:
+
+
+```
+$ find /mnt/mydrive/umbrella -type f | \
+ parallel --max-args=6 setfacl \
+ --default -m u:500:rw,u:1000:rw,u:alice:rw
+```
+
+Adjust the logic of these commands to suit your individual need (don't run a command that removes the executable bit on **/usr**, for instance, or on a directory containing nothing but executable programs).
+
+### External drives
+
+Don't let confusion around external drives on Linux get the best of you, and don't limit yourself to traditional UNIX permissions. Put access control lists to work for you, and feel free to use native journaled Linux filesystems on your portable drives.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/external-drives-linux
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/car-penguin-drive-linux-yellow.png?itok=twWGlYAc (Penguin driving a car with a yellow background)
+[2]: https://opensource.com/resources/linux
diff --git a/sources/tech/20200330 Why I switched from Mac to Linux.md b/sources/tech/20200330 Why I switched from Mac to Linux.md
new file mode 100644
index 0000000000..95561b6b45
--- /dev/null
+++ b/sources/tech/20200330 Why I switched from Mac to Linux.md
@@ -0,0 +1,68 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Why I switched from Mac to Linux)
+[#]: via: (https://opensource.com/article/20/3/mac-linux)
+[#]: author: (Lee Tusman https://opensource.com/users/leeto)
+
+Why I switched from Mac to Linux
+======
+After 25 years, Lee made the switch to Linux and couldn't be happier.
+Here's what he uses.
+![Code going into a computer.][1]
+
+In 1994, my family bought a Macintosh Performa 475 as a home computer. I had used Macintosh SE computers in school and learned to type with [Mavis Beacon Teaches Typing][2], so I've been a Mac user for well over 25 years. Back in the mid-1990s, I was attracted to its ease of use. It didn't start with a DOS command prompt; it opened to a friendly desktop. It was playful. And even though there was a lot less software for Macintosh than PCs, I thought the Mac ecosystem was better, just on the strength of KidPix and Hypercard, which I still think of as the unsurpassed, most intuitive _creative stack_.
+
+Even so, I still had the feeling that Mac was an underdog compared to Windows. I remember thinking the company could disappear one day. Flash-forward decades later, and Apple is a behemoth, a trillion-dollar company. But as it evolved, it changed significantly. Some changes have been for the better, such as better stabilization, simpler hardware choices, increased security, and more accessibility options. Other changes annoyed me—not all at once, but slowly. Most significantly, I am annoyed by Apple's closed ecosystem—the difficulty of accessing photos without iPhoto; the necessity of using iTunes; and the enforced bundling of the Apple store ecosystem even when I don't want to use it.
+
+Over time, I found myself working largely in the terminal. I used iTerm2 and the [Homebrew][3] package manager. I couldn't get all my Linux software to work, but much of it did. I thought I had the best of both worlds: the macOS graphical operating system and user interface alongside the ability to jump into a quick terminal session.
+
+Later, I began using Raspberry Pi computers booting Raspbian. I also collected a number of very old laptops rescued from the trash at universities, so, by necessity, I decided to try out various Linux distros. While none of them became my main machine, I started to really enjoy using Linux. I began to consider what it would be like to try running a Linux distro as my daily driver, but I thought the Macbook's comfort and ease, especially the hardware's size and weight, would be hard to find in a non-Mac laptop.
+
+## Time to make the switch?
+
+About two years ago, I began using a Dell for work. It was a larger laptop with an integrated GPU, and dual-booted Linux and Windows. I used it for game development, 3D modeling, some machine learning, and basic programming in C# and Java. I considered making it my primary machine, but I loved the portability of my Macbook Air, and continued to use that as well.
+
+Last fall, I started to notice my Air was running hot, and the fan was coming on more often. My primary machine was starting to show its age. For years, I used the Mac's terminal to access Darwin's Unix-like operating system, and I was spending more and more time bouncing between the terminal and my web browser. Was it time to make the switch?
+
+I began exploring the possibilities for a Macbook-like Linux laptop. After doing some research, reading reviews and message boards, I went with the long-celebrated Dell XPS 13 Developer Edition 7390, opting for the 10th Generation i7. I chose it because I love the feel of the Macbook (and especially the slim Macbook Air), and reviews of the XPS 13 suggested it seemed it was similar, with really positive reviews of the trackpad and keyboard.
+
+Most importantly, it came loaded with Ubuntu. While it's easy enough to get a PC, wipe it, and install a new Linux distro, I was attracted to the cohesive operating system and hardware, but one that allowed a lot of the customization we know and love in Linux. So when there was a sale, I took the plunge and purchased it.
+
+## What it's like to run Linux daily
+
+I've been using the XPS 13 for three months and my dual-booted Linux work laptop for two years. At first, I thought I'd want to spend more time finding an alternate desktop environment or window manager that was more Mac-like, such as [Enlightenment][4]. I tried several, but I have to say, I like the simplicity of running [GNOME][5] out of the box. For one thing, it's minimal; there's not much GUI to get caught up in. In fact, it's intuitive and the [overview][6] takes only a couple minutes to read.
+
+I can access my applications through the application dash bar or a grid button to get to the application view. To access my file system, I click on the **Files** icon in the dash. To open the GNOME terminal, I type **Ctrl+Alt+T** or just **Alt+Tab** to switch between an open application and an open terminal. It's also easy to define your own [custom hotkey shortcuts][7].
+
+Beyond this, there's not much else to say. Unlike the Mac's desktop, there's not a lot to get lost in, which means there's less to distract me from my work or the applications I want to run. I didn't realize all the options or how much time I spent navigating windows on my Mac. In Linux, there are just files, applications, and the terminal.
+
+I installed the [i3 tiling window manager][8] to do a test run. I had a few issues configuring it because I type in [Dvorak][9], and i3 doesn't adapt to the alternate keyboard configuration. I think with more effort, I could figure out a new keyboard mapping in i3, but the main thing I was looking for was simple tiling.
+
+I looked up GNOME's tiling capabilities and was pleasantly surprised. You press the **Super** key (for me, it's the key with the Windows logo—which I should cover with a sticker!) and then a modifier key. For example, pressing **Super+Left** moves your current window to a tile on the left side of the screen. **Super+Right** moves to the right half. **Super+Up** maximizes the current window. **Super+Down** reverts to the previous size. You can move between app windows with **Alt+Tab**. This is all default behavior and can be customized in the Keyboard settings.
+
+Plugging in headphones or connecting to HDMI works the way you expect. Sometimes, I open the Sound settings to switch between the HDMI sound output or my external audio cable, just as I would on a Mac or PC. The trackpad is responsive, and I haven't noticed any difference from the Macbook's. When I plug in a three-button mouse, it works instantly, even with my Bluetooth mouse and keyboard.
+
+### Software
+
+I installed Atom, VLC, Keybase, Brave Browser, Krita, Blender, and Thunderbird in a matter of minutes. I installed other software with the Apt package manager in the terminal (as normal), which offers many more packages than the Homebrew package manager for macOS.
+
+### Music
+
+I have a variety of options for listening to music. I use Spotify and [PyRadio][10] to stream music. [Rhythmbox][11] is installed by default on Ubuntu; the simple music player launches instantly and without any bloat. Simply click on the menu, choose **Add Music**, and navigate to a directory of audio tracks (it searches recursively). You can also stream podcasts or online radio easily.
+
+### Text and PDFs
+
+I tend to write in Markdown in [Neovim][12] with some plugins, then convert my document using Pandoc to whatever final format is needed. For a nice Markdown editor with preview, I downloaded [Ghostwriter][13], a minimal-focus writing application.
+
+If someone sends me a Microsoft Word document, I can open it using the default LibreOffice Writer application.
+
+Occasionally, I have to sign a document. This is easy with macOS's Preview application and my signature in PNG format, and I needed a Linux equivalent. I found that the default PDF viewer app didn't have the annotation tools I needed. The LibreOffice Draw program was acceptable but not particularly easy to use, and it occasionally crashed. Based on some research, I installed [Xournal][14], which has the simple annotation tools I need to add dates, text, and my signature and is fairly comparable to Mac's Preview app. It works exactly as needed.
+
+### Importing images from my phone
+
+I have an iPhone. To get my images off the phone, there are a number of methods to sync and access your files. If you have a different phone, your process may be different. Here's my method:
+
+ 1. Install gvfs-backends with **sudo apt install gvfs-backends**, which is part of the GNO
\ No newline at end of file
diff --git a/sources/tech/20200401 How does kanban relate-to DevOps.md b/sources/tech/20200401 How does kanban relate-to DevOps.md
new file mode 100644
index 0000000000..3f37c35a4c
--- /dev/null
+++ b/sources/tech/20200401 How does kanban relate-to DevOps.md
@@ -0,0 +1,117 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How does kanban relate to DevOps?)
+[#]: via: (https://opensource.com/article/20/4/kanban-devops)
+[#]: author: (Willy-Peter Schaub https://opensource.com/users/wpschaub)
+
+How does kanban relate to DevOps?
+======
+Reduce waste, optimize the flow of value, and continuously deliver value
+to delighted users.
+![two women kanban brainstorming and brainmapping with post-it notes on a whiteboard ][1]
+
+Kanban is nothing new; in fact, it predates most readers of this article. Its age becomes apparent when we add the year Toyota introduced kanban in its main plant machine shop (1953) to the timeline image from our [analyzing the DNA of DevOps][2] article.
+
+![DevOps timeline][3]
+
+I have intuitively been using kanban, in one form or the other, for more than two decades to track personal plans, engineering projects, and digital transformations. Only in the past few weeks have I pondered the origins, power, and synergy of kanban with other frameworks and systems, while introducing teams to kanban and helping them embrace it as a powerful system in our common engineering system.
+
+### What is kanban?
+
+Kanban means "visual signal" and has its roots in the Toyota manufacturing industry. It was developed by [Taiichi Ohno][4] to improve manufacturing efficiency. When we jump a few decades into the future, kanban complements agile and lean, often used with frameworks such as scrum, Scaled Agile Framework, and Disciplined Agile to visualize and manage work.
+
+![Kanban complements agile and lean][5]
+
+You can explore the many interpretations of kanban on the internet, in books, and in vibrant discussions with other engineers who have embraced the system. In the context of our common collaboration and engineering system, kanban delivers four pivotal practices:
+
+ * **Visualize work:** We visualize all work and look for triggers such as cards turning **red** when the work they represent is blocked or has been dormant for more than two days.
+ * **Limit work in progress:** We agree on and enforce (soft) work-in-progress limits to encourage reduced batch sizes and manage queue lengths.
+ * **Focus on flow:** We _pull_ not push work, which helps us to defer commitment until we meet our definition of done (_DoD_) and we have the capacity to commit to the next _activity_.
+ * **Continuous improvement:** It is important to measure work from when it enters our backlog, how long it takes to get through the process (lead time), and how efficient we are working (cycle/lead time). This enables us to continuously inspect and improve how we work and track progress.
+
+
+
+![Kanban practices and terminology][6]
+
+We use colorful, visual cards to represent activities that flow through one or more _activities_ in one of many _swim lanes_. Each kanban column represents an activity, and each swim lane represents a person, group, or another bucket to segment the cards. There are no rules for the color of the cards, but **red** typically signals a problem. But remember to combine color with a meaningful icon to visualize special states for users who are color-blind.
+
+> "_We should defer commitment until our Definition of Ready (DOR) is met so that we can ensure that our Definition of Done (DOD) is achieved sooner and with high quality. I like the two distinct terms (DOR and DOD) because the [project owner] should be accountable for the DOR while the team can take ownership of the DOD_." —[Mathew Mathai][7]
+
+I often use this analogy to explain the difference between _lead_ and _cycle_ time to new teams: Imagine you walk into a restaurant. You sit down, study the menu, and decide what you would like to drink and eat. When the waiter takes your order, the _lead_ cycle time starts ticking. When the bar starts pouring your favorite potion and the kitchen starts preparing your meal, the _cycle_ time starts ticking. As the order arrives at your table, both the lead and cycle time are stopped if (and only if) you are satisfied.
+
+Therefore, the _lead_ time measures how long you, the customer, had to wait until you received your order. The _cycle_ time measures the process time of an activity to prepare your order. From a customer perspective, the _lead_ time is important.
+
+It is important to _make your policies explicit_, such as when you start measuring lead and cycle times. Some customers start their "impatience" clock when they enter the restaurant, while others start the clock when they place their order. In both cases, they need to understand how you measure your flow to avoid misunderstandings, unfeasible expectations, and disappointment.
+
+This image is extracted from one of our information transfer posters, and it summarizes key learnings when we started adopting the kanban system.
+
+![Key kanban learnings][8]
+
+### What about DevOps?
+
+In _[Using PowerShell to automate Linux, macOS, and Windows processes][9]_, we briefly introduced value-stream mapping. It enables us to measure individual and total lead times, cycle times, efficiency, and quality and unearth different activities, groups, and silos that cancel out each other.
+
+![value-stream mapping][10]
+
+You will notice a similarity between the kanban board and the value-stream mapping images. Both _visualize_ and _focus_ on the flow of activities represented by individual cards pulled across a visual board.
+
+![Continuous delivery pipeline][11]
+
+Continuous flow and efficiency are core to a healthy DevOps mindset. It transforms into a continuous delivery pipeline, as shown above, which unites different teams, such as business, development, security, and quality assurance, to implement ideas from ideation to production. Continuously measuring and streamlining the delivery pipeline not only helps improve the flow of value, but also the quality of value.
+
+It should be evident that (similar to kanban) the focus here is on flow. Flipping back and forth between activities is frowned upon in kanban and impractical with continuous delivery pipelines. It reminds me of a recent whiteboard discussion where we discussed the challenge of visualizing and managing the flow of work that requires two teams.
+
+![Dividing a job between two teams][12]
+
+As shown here, we slice a job that requires team X to perform activities, then team Y, and again team X, into three stories. The three stories are visualized by three cards on two kanban boards, flowing from A to B to C, with clear ownership by team X and Y, which we can measure independently as lead and cycle time.
+
+We are drifting into another exciting topic of flow optimization … let's get back to the original question.
+
+### What is the relationship between kanban and DevOps?
+
+[Donovan Brown][13] defines DevOps as "_the union of people, process, and products to enable continuous delivery of value to our end users._"
+
+When we unpack this definition, we realize that the core of the DevOps [mindset][14] is to continuously deliver value and delight our customers.
+
+ * _"Feedback from stakeholders is essential."_
+ * _"Improve beyond the limits of today's processes."_
+ * _"No new silos to break down silos."_
+ * _"Knowing your customers means cross-organization collaboration."_
+ * _"Inspire adoption through enthusiasm."_
+
+
+
+The kanban system helps us visualize and improve the efficiency of value delivery, resulting in delighted customers. I argue that if you are comfortable with kanban, you will enjoy the full benefits of DevOps through _visualization_, _flow improvement_, _feedback_, and _continuous innovation_.
+
+We have collaboration at its finest—_synergy_**,** or is that _symbiosis_?
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/kanban-devops
+
+作者:[Willy-Peter Schaub][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/wpschaub
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/whiteboard-brainstorming-brainmapping-design-thinking-postits-kanban.png?itok=Is2Tg1Jk (Brainstorming with post-it notes on a whiteboard)
+[2]: https://opensource.com/article/18/11/analyzing-devops
+[3]: https://opensource.com/sites/default/files/uploads/devops-timeline.png (DevOps timeline)
+[4]: https://en.wikipedia.org/wiki/Taiichi_Ohno
+[5]: https://opensource.com/sites/default/files/uploads/kanban-agile-lean-devops.png (Kanban complements agile and lean)
+[6]: https://opensource.com/sites/default/files/uploads/kanban-practices-terms.png (Kanban practices and terminology)
+[7]: https://opensource.com/users/anicheinc
+[8]: https://opensource.com/sites/default/files/uploads/kanban-key-learnings.png (Key kanban learnings)
+[9]: https://opensource.com/article/20/2/devops-automation
+[10]: https://opensource.com/sites/default/files/uploads/value-stream-mapping.png (value-stream mapping)
+[11]: https://opensource.com/sites/default/files/uploads/cd-pipeline.png (Continuous delivery pipeline)
+[12]: https://opensource.com/sites/default/files/uploads/splitting-jobs.png (Dividing a job between two teams)
+[13]: https://www.donovanbrown.com/post/what-is-devops
+[14]: https://opensource.com/article/19/5/values-devops-mindset
diff --git a/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md b/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md
new file mode 100644
index 0000000000..0eef549525
--- /dev/null
+++ b/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md
@@ -0,0 +1,85 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Building a sensing prosthetic with the Raspberry Pi)
+[#]: via: (https://opensource.com/article/20/4/raspberry-pi-sensebreast)
+[#]: author: (Kathy Reid https://opensource.com/users/kathyreid)
+
+Building a sensing prosthetic with the Raspberry Pi
+======
+SenseBreast is an early prototype of a sensing mastectomy prosthetic
+based on open hardware.
+![Open source doctor.][1]
+
+_Content advisory: this article contains frank discussions of breast cancer._
+
+What's the first question you ask your surgeon when you're discussing reconstruction options after breast cancer?
+
+"How many USB ports can you give me?" is probably not the one that comes to mind for many people!
+
+Although the remark was said jokingly, it sparked a thread that would ultimately become [SenseBreast][2]—an early prototype of a sensing mastectomy prosthetic, based on open hardware.
+
+### How did SenseBreast come about?
+
+All technology has a history—an origin story of experimentation, missteps, successes, setbacks, and breakthroughs. SenseBreast is no different. SenseBreast was developed as a term project for the Masters of Applied Cybernetics—a highly selective course at the Australian National University's [3A Institute][3]. The mission of the 3Ai is to bring artificial intelligence and cyber-physical systems safely, responsibly, and sustainably to scale. The purpose of the assignment was to explore the nexus between the electronic, virtual world, and the physical, tactile world.
+
+### What is SenseBreast?
+
+SenseBreast combines two distinct elements: a cyber component—electronics, sensors, and storage for gathering data, and a physical component—a breast form designed to be worn inside a mastectomy bra. SenseBreast is a rudimentary cyber-physical system. In cyber-physical systems, physical and software components are deeply intertwined and interact in different ways depending on context.
+
+The SenseBreast draws on a rich heritage of open source hardware and software. Based on the Raspberry Pi 3B+, it uses the Debian-flavored Raspbian operating system, Python to interact with the onboard sensors, and d3.js to visualize the data that the sensors generate.
+
+Early versions of the SenseBreast used the SenseHAT, but in the true spirit of open source collaboration, I partnered with Australian open source luminary Jon Oxer to develop a custom SenseBreast board. This contains an inertial motion unit (IMU) and temperature, humidity, and pressure sensors, just like the SenseHAT, but in addition, it contains the BME680 volatile gas sensor and a breakout for a heart rate monitor.
+
+![SenseBreast open hardware board developed by Jon Oxer and Kathy Reid][4]
+
+SenseBreast is wearable tech, so the physical form of the cyber-physical system is also important. Factors like comfort, texture, and fit in clothing are important in the design of wearables because technology isn't better unless it's better for people! The early attempts at building a housing for SenseBreast were spectacular failures; in fact, the very first iteration was put together using acrylic render and linen cloth, and held together with paper clips—in true hacker style! It wasn't comfortable to wear at all, but it served as a proof point for further exploration.
+
+![First attempt at creating a breast form using acrylic render covered in linen cloth][5]
+
+Later iterations used a different approach. This involved taking a cast of a breast, using quick-dry silicone supported by a plaster cast. The resulting mold was then used with slow-setting silicone to create a true-to-life shape. A recess was carved into the form to house the electronic components, and an additional silicone layer was added to protect the wearer's skin from contact with electronics.
+
+### What did we learn from SenseBreast?
+
+The key learning from SenseBreast is that data is partial. It only tells part of a story. It can be misleading and untrustworthy, which makes the decisions based on that data unreliable too. For example, the sensor data gathered by SenseBreast was affected by how hard the CPU was working. The graph below plots a sequence of 5 minutes of data from SenseBreast, just after the device has booted. You can see that the temperature decreases over time; this is because the CPU has to work harder as the Raspberry Pi boots, and then cools down after the boot operations are completed.
+
+![Data visualisation of the readings in SenseBreast using the d3.js library][6]
+
+These sorts of learnings have implications on a broader scale.
+
+What if the SenseBreast were not an open source device, but a commercial wearable that stored data about me? What if part of the business model of that company was to sell the data that was harvested? What if my health insurer had access to that data? Or prospective employers? Now, more than ever, it's important that we have private, open solutions for sensing data about ourselves.
+
+### What's next for the SenseBreast project?
+
+The SenseBreast is a very early prototype, but it has the potential to develop through many different arcs. It could be used to assess range of movement post-surgery, to research how different garments and fabrics adjust to temperature and humidity, and to identify correlations between ambient air pressure and conditions such as lymphoedema. The path SenseBreast takes will be dependent on the passion, needs, and dedication of the incredible global open source community.
+
+You can learn more about SenseBreast at [https://sensebreast.org][2] and see my presentation at [linux.conf.au][7] 2020 [here][8].
+
+The code for SenseBreast is available on [GitHub][9].
+
+Health IT has been surprisingly unwilling to deeply support open source software. Despite the huge...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/raspberry-pi-sensebreast
+
+作者:[Kathy Reid][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/kathyreid
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520x292_opensourcedoctor.png?itok=fk79NwpC (Open source doctor.)
+[2]: https://sensebreast.org/
+[3]: https://3ainstitute.cecs.anu.edu.au/
+[4]: https://opensource.com/sites/default/files/uploads/49427571178_bb5df37c3a_c.jpg (SenseBreast open hardware board developed by Jon Oxer and Kathy Reid)
+[5]: https://opensource.com/sites/default/files/uploads/49641040471_6d0cc91619_c.jpg (First attempt at creating a breast form using acrylic render covered in linen cloth)
+[6]: https://opensource.com/sites/default/files/uploads/49640513813_5a7d63803a_c.jpg (Data visualisation of the readings in SenseBreast using the d3.js library)
+[7]: http://linux.conf.au
+[8]: https://www.youtube.com/watch?v=G3QfZ11DCpc.
+[9]: https://github.com/KathyReid/sensebreast
diff --git a/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md b/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md
new file mode 100644
index 0000000000..855c622e49
--- /dev/null
+++ b/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md
@@ -0,0 +1,92 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Love or hate chat? 4 best practices for remote teams)
+[#]: via: (https://opensource.com/article/20/4/chat-tools-best-practices)
+[#]: author: (Jen Wike Huger https://opensource.com/users/jen-wike)
+
+Love or hate chat? 4 best practices for remote teams
+======
+Plus, learn about a few open source alternatives for chat.
+![Chat via email][1]
+
+Chat is a part of most people's daily lives, especially if you work in tech, and especially if you work with teammates located in different parts of the world. It can be a great way to achieve these goals:
+
+ * **to connect**; to share with teammates on a personal level
+ * **to get work done**; to communicate with teammates about work in progress
+ * **to share**; to give notes and feedback from experiences, meetings, and interactions outside of the group that may be relevant to your work or interests
+
+
+
+I encourage you to explore [open source alternatives to chat][2] like [Mattermost][3], [Rocket.Chat][4], and [Riot][5].
+
+### To chat or not to chat, that is the question
+
+First, it's important to make time to have a discussion with each member of your team focused on answering whether they are comfortable with using a chat platform to keep in touch throughout the workday. Some people enjoy chat and see it as a vital part of their workday, getting things done and communicating with teammates who they rely on to get that work done and move forward with projects. Others struggle with chat as a way of getting work done and prefer to use it when they feel like having more casual conversations with teammates on topics less focused on work and more on social interaction and personal sharing. Some people wish chat would burn in a fire.
+
+Gather these opinions and talk through these feelings with each person. You can do this as a group or one-on-one if that feels more appropriate.
+
+Why? Because communication is important and always will be, and your team will find a way to chat no matter what you do. We're human, and need various levels and types of interaction with each other throughout our days and lives. And when it comes to our work colleagues, it's helpful to put some structure in place to guide your team.
+
+### Best practices for team chat
+
+If you have decided to use chat in some form, the next step is to place structure around when and how to use it and **not** use it. These best practices work well for teams who are working remotely and at home, as well as in the office.
+
+**1\. Create rooms and threads to focus your conversations.**
+
+My team has a room for each of our sub-teams who work on a particular project together. We also have an at-large room for all of us to banter and share.
+
+Additionally, we use threads to focus on one topic at a time which is helpful when you have several to dozens of teammates in one room together. It helps conversations to continue and not stop prematurely because they were lost in the mix of other conversations.
+
+**2\. Decide when your team will be signed in and available to talk.**
+
+Is it throughout the workday (whatever hours those are for you), during a set timeframe, or as desired?
+
+My team has set the expectation that they will be signed in and available to chat at some point during the workday **about work-related topics**, and that at that time they will check for and respond to messages that were sent to them while they were away. So, we are using it as an asynchronous way to communicate about work.
+
+For us, asynchronous chat helps us plan and schedule each day how we see fit with the goal of being productive and serving our project in the best we can _that day_.
+
+If a teammate does **not** plan on signing in and responding to messages one day, that is OK, and we set the expectation that they will send a message to let the team know. For my team, almost no communication is wrong (see guideline #4), but it should be communicated. We also review our schedules for the following week in a team meeting the week before so we know when someone will be away from their desk, not working, or blocking out a chunk of time for a project.
+
+**3\. Decide when your teammates are responsible for responding (and when they are not).**
+
+Use @ mentions if you want someone to see and respond to your question or comment in chat. Don't expect them to be watching every thread and conversation.
+
+And I would recommend that you take it a step further and define when teammates should be responsible for responding and when they should not. This type of decision is meant to free you and your teammates, not hold you down. The more you understand the expectations, the freer you are to operate within the same understood universe. When you are unsure of the rules, you may act and make decisions in fear or trepidation instead, like staying signed in to chat all day when you really just need to block it out to get something done.
+
+Our team has decided that it's nice if you can respond in chat when you are mentioned, but if you don't that is OK. Perhaps you were AFK during that time and lost track of the notification. For us, if you definitely want a response to something from someone, send them an email.
+
+**4\. Communicate clearly and with kindness.**
+
+The way we interpret messages when we are chatting via text is different than when we are chatting verbally, in-person or over video.
+
+My team uses a lot of humor, emojis, and clear, concise messages to chat with each other.
+
+We also hold weekly in-person or video conference meetings so that we can get to know each other better. The more you trust someone, the easier it is to give them the benefit of the doubt when you're confused by a message and the better you are at understanding what they are saying and what their intention is behind the text coming through to you.
+
+### Signing off
+
+What best practices does your team use? Do you love or hate chat, and why?
+
+For all kinds of teams today, chat is a special part of how we stay connected, working, and sharing with each other. Finding ways to do that in a healthy and committed way is part of everyone's responsibility.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/chat-tools-best-practices
+
+作者:[Jen Wike Huger][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jen-wike
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
+[2]: https://opensource.com/alternatives/slack
+[3]: https://mattermost.com/
+[4]: https://rocket.chat/
+[5]: https://riot.im/app/
diff --git a/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md b/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md
new file mode 100644
index 0000000000..63de71fec7
--- /dev/null
+++ b/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md
@@ -0,0 +1,84 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (GNOME Announces Community Engagement Challenge Offering up to $65,000 in Rewards)
+[#]: via: (https://itsfoss.com/gnome-community-engagement-challenge/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+GNOME Announces Community Engagement Challenge Offering up to $65,000 in Rewards
+======
+
+It’s always good to see several competitions or challenges trying to promote Free and Open-Source Software (FOSS) more than ever.
+
+In a recent effort by GNOME with the help of [Endless][1], they announced the inaugural GNOME Community Engagement Challenge.
+
+This Community Challenge is a part of their original announcement of [coding education challenge for which GNOME was granted $500,000 funding by Endless][2] last year.
+
+The three-phase challenge aims to attract new developers to engage with FOSS and potentially create new/unique solutions that would gain more traction from the next-gen coders.
+
+The challenge will involve up to $65,000 in cash prizes. Sounds exciting, right? Let’s take a look at some of the details involved in the challenge.
+
+![][3]
+
+### Why The GNOME Community Engagement Challenge?
+
+In their official [press release][4], they mentioned their primary motive for the challenge:
+
+> “Through the Challenge we hope to reach a diverse audience, to encourage beginning coders to get involved with the FOSS community to help ensure that free software is available long into the future,” said Neil McGovern, GNOME Foundation Executive Director. “What better way to do that than to reach out to the community itself to come up with creative ways to inspire the next generation?”
+
+As Neil mentioned above, it’s definitely a good idea to reach out to more people (community) to look for creative ways to promote and work on FOSS projects that will leave a significant impact on the open-source community.
+
+And, rewarding for the ideas in the form of a challenge will easily get the attention needed.
+
+### Here’s How The Community Challenge Works
+
+To quote the official announcement:
+
+> The Challenge will ask entrants to devise creative ways to promote open-source software to coders typically in high school and college. How a submission will achieve this goal has deliberately been left open-ended to encourage unique, novel approaches.
+
+So, there’s no particular constraint for the type of ideas or projects you can propose and submit. But, it would be wise to read the usual [terms and conditions][5] to know about the submission rules, eligibility, requirements, prize details, and more.
+
+Here are the key information about the three phases of the challenge as per the announcement:
+
+ * The **first phase** of the Challenge asks entrants to submit a written proposal for their concept no later than **July 1, 2020**. Twenty entries will be chosen to move to the next round and receive **$1000 each**.
+ * The **second phase** of the Challenge will require proof of concept, with four entries receiving **$5000** and moving onto the final round.
+ * The final round will call for a deliverable end product, with the winner receiving **$15,000** and the second place finisher receiving **$10,000**.
+
+
+
+They plan to announce the winner of the challenge in the spring of 2021.
+
+You can take a look at their [challenge FAQ][6] and the [official webpage][7] for more details before starting to submit your entry on **April 9th**. The last date of submission is **July 1, 2020**.
+
+Head to their website to get started and explore more about the challenge.
+
+[GNOME Community Engagement Challenge][7]
+
+### Wrapping Up
+
+I think this is a perfect opportunity for developers to get started with FOSS projects that will end up rewarding them with a good amount of money and help the community at the same time.
+
+What do you think about the community engagement challenge by GNOME? Feel free to let me know your thoughts in the comments below.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/gnome-community-engagement-challenge/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://www.endlessnetwork.com/
+[2]: https://itsfoss.com/endless-gnome-coding-education-challenge/
+[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/gnome-community-challenge.png?ssl=1
+[4]: https://www.gnome.org/news/2020/04/gnome-foundation-and-endless-launch-inaugural-community-engagement-challenge/
+[5]: https://www.gnome.org/challenge/terms/
+[6]: https://www.gnome.org/challenge/faq/
+[7]: https://www.gnome.org/challenge/
diff --git a/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md b/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md
new file mode 100644
index 0000000000..327af54c79
--- /dev/null
+++ b/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md
@@ -0,0 +1,75 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to set up a remote school environment for kids with Linux)
+[#]: via: (https://opensource.com/article/20/4/school-home-linux)
+[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
+
+How to set up a remote school environment for kids with Linux
+======
+Repurpose an old computer to support the new home-schooler in your life.
+![Image by Alan Formy-Duvall][1]
+
+COVID-19 has suddenly thrown all of us into a new and challenging situation. Many of us are now working full-time from home, and for a lot of us (especially people who aren't used to working remotely), this is taking some getting used to.
+
+Another group that is similarly challenged is our kids. They can't go to school or participate in their regular after-school activities. My daughter's elementary school closed its classrooms and is teaching through an online, web-based learning portal instead. And one of her favorite extracurricular activities—a coding school where she has been learning Scratch and just recently "graduated" to WoofJS–has also gone to an online-only format.
+
+We are fortunate that so many of our children's activities can be done online now, as this is the only way they will be able to learn, share, and socialize for at least the next several months.
+
+### Setting up a temporary homeschool environment
+
+When our daughter's school went to an online-only format, we realized she needed a place and some tools to do her work. So we cleaned off her desk and cleared the toys from the floor around it to make an "office" for her. We also realized she would need a computer. While I could have shopped online and ordered a new computer (and spent at least several hundred dollars—if not more than $1,000—in the process), I chose an alternative and put an old, unused laptop back to work.
+
+If you have an unused computer sitting around and are willing to do a bit of tech work, you, too, can set something up to get your kids online. Here's how I did it.
+
+### The hardware
+
+While my daughter already has her own small IT department (as I like to say), it consists of some gaming systems, a tablet, and a Chromebook. Even her Chromebook has just an 11.6" screen and a small keyboard, so none of her devices are really quite adequate for full-time school duty.
+
+So we found ourselves in a pinch. She really needed a desktop-capable computer system with a decent-sized screen, a full keyboard, a good-quality microphone, a set of speakers, and a headphone jack. And having an external video connector helps if you decide one screen isn't enough.
+
+I didn't have a spare desktop, but I did have a laptop: a Lenovo G550 with a Pentium Dual-Core T4500 2.3GHz processor and 4GB RAM. I replaced its aging 5400RPM spindle hard drive with a 240GB solid-state drive. The laptop has a 15.6" screen, which is much easier to view than the small screens on her other devices, and a comfortable, full-size keyboard. Its CPU scores a bit better in PassMark's benchmarks (913 vs. 674) than the 1.6GHz Intel Celeron N3060 Dual-Core in the Chromebook.
+
+However, it is 10 years old, certainly on the edge of usability by today's standards. But, thanks to the efficiency of the Linux operating system, it gets the job done. I installed the latest version (v31) of [Fedora Workstation][2], but many other distributions will work just fine. If you really want to eke out every drop of performance, you could use one of the [lightweight Linux distributions][3]. The only area that required a little extra effort with Fedora was the wireless; I had to install the driver for the Broadcom WiFi hardware. But really, this was only a few extra steps and a restart, and it was good to go.
+
+Linux supports all of the other hardware in the laptop. My daughter prefers a full-sized mouse over the touchpad, so I attached one. She likes the keyboard on this laptop, but if she wants an external keyboard, there are enough USB ports to hook one up.
+
+It has a traditional 3.5mm audio jack, so she can use headphones. I recommend giving children decibel-limited headphones to protect their hearing.
+
+Even though this laptop has a 15.6" widescreen display, I think having a second monitor gives the best experience. I have a spare that I might hook up to the external VGA connector.
+
+### The software
+
+My daughter's school set up an online learning portal. The benefit is that students just need a supported web browser to log on and get to work, and I thank the school for its efforts and choice of a vendor-agnostic solution. Most Linux distributions include the Mozilla Firefox web browser installed by default, and Linux provides a full operating system, so I can install any applications she might need. Fedora is also updated regularly (unlike the old Windows Vista that came with the laptop and is no longer supported).
+
+![][4]
+
+Scratch running on Fedora
+
+Her extracurricular coding school is using the Zoom client. I'm happy to report that it was an easy [install with RPM][5] and works great on Fedora 31.
+
+### Success!
+
+My daughter has no trouble using her new laptop. She likes the [GNOME desktop][6], particularly the fact that it "Looks like Dad's!" This is turning out to be a great experiment in practical (and under-pressure) use of a Linux desktop.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/school-home-linux
+
+作者:[Alan Formy-Duval][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alanfdoss
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/homeschool.jpg?itok=vYEd9NON (Image by Alan Formy-Duvall)
+[2]: https://getfedora.org/en/workstation/
+[3]: https://opensource.com/article/19/6/linux-distros-to-try
+[4]: https://opensource.com/sites/default/files/scratch.jpg
+[5]: https://zoom.us/download?os=linux
+[6]: https://www.gnome.org/
diff --git a/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md b/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md
new file mode 100644
index 0000000000..daacfa8365
--- /dev/null
+++ b/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md
@@ -0,0 +1,152 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Print double-sided documents at home with this simple Bash script)
+[#]: via: (https://opensource.com/article/20/4/print-duplex-bash-script)
+[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
+
+Print double-sided documents at home with this simple Bash script
+======
+Use this script and save yourself the hassle and wasted paper of trying
+to manually load and print double-sided documents.
+![bash logo on green background][1]
+
+We have a laser printer at home. This Hewlett Packard LaserJet Pro CP1525nw Color Printer is an older model, but it has been a great workhorse that prints reliably and in color. I [put it on our home network][2] a few years ago using our [Raspberry Pi][3] as a print server.
+
+The LaserJet has been a great addition to my home office. Since [I launched my company][4] last year, I have relied on this little laser printer to print handouts and other materials for client meetings, workshops, and training sessions.
+
+My only gripe with this printer is that it prints single-sided only. If you want to print double-sided, you need to set up a custom print job to do it yourself. That's inconvenient and requires manual steps. In LibreOffice, I need to specifically set up the print job to print the odd-numbered pages first, then reload the paper before printing the even-numbered pages on the other side—but in reverse order.
+
+![LibreOffice print dialog][5]
+
+If I need to print a PDF that someone has sent me, the process is the same. For a four-page document, I first need to print pages 1 and 3, then reload the paper and print pages 2 and 4 in reverse order. In the GNOME print dialog, you need to select "Page Setup" to print odd pages or even pages.
+
+![Gnome print dialog][6]
+
+![Gnome page setup][7]
+
+Regardless of how I print, the overall process is to print the odd-numbered pages, reload the stack of printed pages into the paper tray, then print the even-numbered pages in reverse order. If I'm printing a four-page document, printing the even-numbered pages in reverse order means page 4 prints on the back of page 3 and page 2 prints on the back of page 1. Imagine my frustration in those few instances when I forgot to select the option to print in reverse order when printing the even-numbered pages and ruined a long print job.
+
+Similarly, it's easy to forget how to deal with documents that have an odd number of pages. In a five-page document, you first print pages 1, 3, and 5. But when you reload the printed pages into the printer, you don't want page 5. Instead, you only want to load pages 1 and 3. Otherwise, page 4 will print on the back of page 5, page 2 will print on the back of page 3, and nothing gets printed on the back of page 1.
+
+To make things easier and more reliable, I wrote a simple Bash script that automates printing duplex. This is basically a wrapper to print odd-numbered pages, remind me to reload the pages (and remove the last page if needed), then print the even-numbered pages.
+
+Whenever I need to print a document as duplex, I first convert the document to PDF. This is very easy to do. In LibreOffice, there's a toolbar icon to export directly as PDF. You can also navigate under **File— Export As—Export as PDF** to do the same. Or in any other application, there's usually a **Save to PDF** feature. When in doubt, GNOME supports printing to a PDF file instead of a printer.
+
+![Libre Office toolbar][8]
+
+![Export as PDF][9]
+
+### How it works
+
+Once I've saved to PDF, I let my Bash script do the rest. This really just automates the **lpr** commands to make printing easier. It prints odd pages first, prompts me to reload the paper, then prints the even pages. If the document has an odd number of pages, it also reminds me to remove the last page when I reload the printed pages. It's pretty simple.
+
+The only "programming" part of the script is determining the page count, and figuring out if that's an even or odd number. Both of those are easy to do.
+
+To determine the page count, I use the **pdfinfo** command. This generates useful info about a PDF document. Here's some sample output:
+
+
+```
+$ pdfinfo All\ training\ -\ catalog.pdf
+Creator: Writer
+Producer: LibreOffice 6.3
+CreationDate: Fri Oct 18 16:06:07 2019 CDT
+Tagged: no
+UserProperties: no
+Suspects: no
+Form: none
+JavaScript: no
+Pages: 11
+Encrypted: no
+Page size: 612 x 792 pts (letter)
+Page rot: 0
+File size: 65623 bytes
+Optimized: no
+PDF version: 1.5
+```
+
+That output is very easy to parse. To get the page count, I use an AWK one-line script to look for **Pages:** and print the second field.
+
+
+```
+`pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )`
+```
+
+To figure out if this is an odd or even number, I use the modulo (**%**) arithmetic operator to divide by two and tell me the remainder. The modulo of two will always be zero for an even number, and one for an odd number. I use this simple test to determine if the document has an odd number of pages, so I'll need to remove the last page before printing the rest of the document:
+
+
+```
+`if [ $(( $pages % 2 )) -ne 0 ] ; then`
+```
+
+With that, writing the **print-duplex.sh** Bash script is a simple matter of calling **lpr** with the correct options to send output to my printer (**lpr -P "HP_LaserJet_CP1525nw"**), to print odd-numbered pages (**-o page-set=odd**) or even-numbered pages (**-o page-set=even**), and to print in reverse order (**-o outputorder=reverse**).
+
+### Bash script
+
+
+```
+#!/bin/sh
+# print-duplex.sh
+# simple wrapper to print duplex
+
+cat<<EOF
+$1 ($pages pages)
+\-------------------------------------------------------------------------------
+Printing odd pages first
+Please wait for job to finish printing...
+\-------------------------------------------------------------------------------
+EOF
+
+lpr -P "HP_LaserJet_CP1525nw" -o page-set=odd "$1"
+sleep $pages
+
+cat<<EOF
+===============================================================================
+Put paper back into the printer in EXACT OUTPUT ORDER (face down in tray)
+then press ENTER
+===============================================================================
+EOF
+
+pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )
+
+if [ $(( $pages % 2 )) -ne 0 ] ; then
+ echo '!! Remove the last page - this document has an odd number of pages'
+fi
+
+echo -n '>'
+read x
+
+cat<<EOF
+\-------------------------------------------------------------------------------
+Printing even pages
+Please wait for job to finish printing...
+\-------------------------------------------------------------------------------
+EOF
+
+lpr -P "HP_LaserJet_CP1525nw" -o page-set=even -o outputorder=reverse "$1"
+```
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/print-duplex-bash-script
+
+作者:[Jim Hall][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jim-hall
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
+[2]: https://opensource.com/article/18/3/print-server-raspberry-pi
+[3]: https://opensource.com/resources/raspberry-pi
+[4]: https://opensource.com/article/19/9/business-creators-open-source-tools
+[5]: https://opensource.com/sites/default/files/uploads/print_dialog_-_libreoffice_0.png (LibreOffice print dialog)
+[6]: https://opensource.com/sites/default/files/uploads/print_dialog_-_gnome_0.png (Gnome print dialog)
+[7]: https://opensource.com/sites/default/files/uploads/print_dialog_-_gnome_-_page_setup.png (Gnome page setup)
+[8]: https://opensource.com/sites/default/files/uploads/toolbar_-_export_as_pdf_-_libreoffice.png (Libre Office toolbar)
+[9]: https://opensource.com/sites/default/files/uploads/file_-_export_as_pdf_-_libreoffice.png (Export as PDF)
diff --git a/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md b/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md
new file mode 100644
index 0000000000..461c52a8a5
--- /dev/null
+++ b/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md
@@ -0,0 +1,142 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Use Emacs Org mode to easily create LaTeX documents)
+[#]: via: (https://opensource.com/article/20/4/emacs-org-mode)
+[#]: author: (Peter Prevos https://opensource.com/users/danderzei)
+
+Use Emacs Org mode to easily create LaTeX documents
+======
+You can use LaTeX for scientific and technical documents without all of
+the confusing commands and syntax you would normally need.
+![Filing cabinet for organization][1]
+
+LaTeX is a powerful system, especially for writing scientific and technical documents. But writing documents in LaTeX can be confusing because you need to know a lot of commands, and your text is littered with backslashes, curly braces, and other syntax distractions. But being productive as a writer requires that you focus on the text's content instead of how it looks. Fortunately, the [GNU Emacs][2] Org mode extension makes it easy to write plain-text documents and seamlessly export them to LaTeX and PDF.
+
+[Org mode][3] is a built-in Emacs extension that helps you keep notes, maintain to-do lists, manage projects, and author documents with a fast and effective plain-text system. Emacs also comes with [AUCTeX][4], an extensible package for writing TeX files in Emacs. AUCTeX has a preview module that shows the results of what you type, but I find it distracting because it draws my attention away from the document's content to its design. Writing text in Org mode is my preferred option because the source remains a plain-text file with minimal typesetting elements. The text is independent of its result because Org mode can export it to multiple formats, including LaTeX and PDF.
+
+Emacs is known for being difficult to use with a steep learning curve. But Emacs is only difficult when you want to fine-tune the default settings. By following a minimalist approach to using the vanilla GNU Emacs, this article will get you quickly and easily on your way to writing beautiful documents without any complex configuration.
+
+### First steps
+
+Before you begin, [install Emacs][5] and a fully functioning version of [LaTeX][6] on your computer.
+
+Next, you need to learn some conventions. In Emacs lingo, the abbreviation **C-c** means to enter **Ctrl+C** on your keyboard. The abbreviation **M-x** means **Alt+X**. The M stands for the mod key, which no longer exists in modern systems. The **S** prefix indicates the **Shift** key.
+
+The **find-file** function, which you start with the **C-x C-f** keystroke combination, creates a new document or opens an existing document. Entering this function opens a dialog in the mini-buffer at the bottom of the screen, which is where Emacs communicates with the user. Type the name of the file you want to create or open into the mini-buffer. Emacs is sensitive to file extensions, so make sure that the name of your document ends in **.org**.
+
+In Emacs speak, opening or creating a file is called ["visiting" a file][7]. Visiting a file means reading its contents into an Emacs buffer so that it is available for editing. Emacs generates a new buffer for each file you visit.
+
+### Writing prose with Org mode
+
+Once you're visiting a file, you can start typing your text the same way you would in any text editor or word processor. Some conventions: Begin the file with **#+TITLE:** to denote the title of the document and **#+AUTHOR** for your name. These options are used when exporting the file. Org mode recognizes a range of [export settings][8] to configure the output. For example, to suppress the table of contents, enter **#+OPTIONS: toc:nil**.
+
+Org mode has its own Markdown-like conventions to format your document. [Headlines][9] start with one or more asterisks. Org mode can [collapse a headline][10] to render parts of it invisible with the **TAB** or **S-TAB** keys. You can make words ***bold***, **/italic/**, **_underlined_**, or **=verbatim=**. The Org manual describes the many options for [rich text][11].
+
+One minor issue with plain-vanilla Emacs that you will quickly notice is it does not wrap lines at the end of the visible screen. Emacs has several line-wrapping functions, and [Visual Line mode][12] is the most useful for writing long-form text. To activate this mode, use **M-x** and enter **visual-line-mode** in the mini-buffer at the bottom of the screen. The **M-x** keyboard shortcut enables executing functions for which there is no direct keyboard shortcut.
+
+Adding [images][13] is as easy as adding a link to the image file within double square brackets:
+
+
+```
+`[[file:path_to_image.png]]`
+```
+
+Org has a great system for [formatting tables][14] in plain ASCII. Any line with **|** is considered part of a table. The vertical line is also the column separator. A line starting with **|-** is rendered as a horizontal rule, and rows before the first horizontal rule are header lines. A table might look like this in the source file:
+
+
+```
+| Name | id | Age |
+|-------+------+-----|
+| Peter | 1234 | 50 |
+| Sue | 4321 | 54 |
+```
+
+Both images and tables are preceded with **#+CAPTION:** to add a [caption][15]. Advanced options are also available to control float placement and size of figures.
+
+Emacs has extensive [editing functions][16] to make you more efficient when typing text. Spell checking, thesaurus, auto-completion, and an undo tree are just some of the tools that help you write efficiently.
+
+### Adding LaTeX snippets to Org
+
+In addition to the text itself, Org mode-text can include simple LaTeX commands, such as **\newpage**, within the text. Equations in standard LaTeX syntax are placed between dollar signs **$e^{i\pi} + 1 = 0$**. The **org-latex-preview** function (**C-c C-x C-l**) shows a [preview][17] of any LaTeX equations within the text buffer. Last, you can also add complete LaTeX snippets to insert complex content. The code has to be placed in an export block:
+
+
+```
+#+BEGIN_EXPORT latex
+\setlength{\unitlength}{1cm}
+\thicklines
+\begin{picture}(10,6)
+\put(2,2.2){\line(1,0){6}}
+\put(2,2.2){\circle{2}}
+\put(6,2.2){\oval(4,2)[r]}
+\end{picture}
+#+END_EXPORT
+```
+
+### Exporting to LaTeX
+
+Org mode includes a powerful export module to convert your files to many formats using the powerful [Pandoc][18] software. Start the export module with the **org-export-dispatch** function, which you can run with the **C-c C-e** keyboard shortcut. The dispatch will split your screen and provide a range of options.
+
+First, Pandoc converts the Org mode file to a LaTeX file. Then you can choose to open the LaTeX file in a new buffer or save it as a file. Org mode can also directly render a PDF file, which you can view within Emacs or save to disk.
+
+![Emacs with Org mode source and PDF preview][19]
+
+### Advanced use
+
+This article provides a first taste of writing prose in Org mode and LaTeX. Org mode has numerous configuration options to fine-tune your document or to change default settings.
+
+By default, Org mode uses the article style to export documents, but you can change this with export settings. These settings can also be used to add commands to the document header, for example:
+
+
+```
+#+LATEX_CLASS: report
+#+LATEX_CLASS_OPTIONS: [a4paper]
+#+LATEX_HEADER: \usepackage{times}
+```
+
+If you write scientific documents, the [org-ref][20] package by John Kitchin provides Org-mode modules for citations, cross-references, and bibliographies in Org mode and useful BibTeX tools to go with it.
+
+The Org mode manual's [LaTex export][21] section provides a detailed discussion of the functionality available.
+
+### Conclusion
+
+Org mode is a perfect editor for writing LaTeX. The main advantage is that you lose the clutter of LaTeX syntax and can focus on the text. This comes at no cost because you can still add LaTeX code as much as you need, and you get access to the powerful editing functions in Emacs.
+
+Using Org to write books and articles allows you to focus on the text as you combine two of the oldest and most powerful pieces of open source software.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/emacs-org-mode
+
+作者:[Peter Prevos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/danderzei
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/files_documents_organize_letter.png?itok=GTtiiabr (Filing cabinet for organization)
+[2]: https://opensource.com/article/20/3/getting-started-emacs
+[3]: https://orgmode.org
+[4]: https://www.gnu.org/software/auctex/
+[5]: https://www.gnu.org/software/emacs/
+[6]: https://www.latex-project.org/get/
+[7]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Visiting.html
+[8]: https://orgmode.org/manual/Export-Settings.html
+[9]: https://orgmode.org/manual/Headlines.html#Headlines
+[10]: https://orgmode.org/manual/Global-and-local-cycling.html#Global-and-local-cycling
+[11]: https://orgmode.org/manual/Markup-for-Rich-Contents.html#Markup-for-Rich-Contents
+[12]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Visual-Line-Mode.html
+[13]: https://orgmode.org/manual/Images.html
+[14]: https://orgmode.org/manual/Built_002din-Table-Editor.html#Built_002din-Table-Editor
+[15]: https://orgmode.org/manual/Captions.html#Captions
+[16]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Basic.html#Basic
+[17]: https://orgmode.org/manual/Previewing-LaTeX-fragments.html
+[18]: https://pandoc.org/
+[19]: https://opensource.com/sites/default/files/uploads/org-mode-latex-screenshot.png (Emacs with Org mode source and PDF preview.)
+[20]: https://github.com/jkitchin/org-ref
+[21]: https://orgmode.org/manual/LaTeX-Export.html#LaTeX-Export
diff --git a/sources/tech/20200410 Get started with Bash programming.md b/sources/tech/20200410 Get started with Bash programming.md
new file mode 100644
index 0000000000..875adb9876
--- /dev/null
+++ b/sources/tech/20200410 Get started with Bash programming.md
@@ -0,0 +1,157 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Get started with Bash programming)
+[#]: via: (https://opensource.com/article/20/4/bash-programming-guide)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Get started with Bash programming
+======
+Learn how to write custom programs in Bash to automate your repetitive
+tasks. Download our new eBook to get started.
+![Command line prompt][1]
+
+One of the original hopes for Unix was that it would empower everyday computer users to fine-tune their computers to match their unique working style. The expectations around computer customization have diminished over the decades, and many users consider their collection of apps and websites to be their "custom environment." One reason for that is that the components of many operating systems are not open, so their source code isn't available to normal users.
+
+But for Linux users, custom programs are within reach because the entire system is based around commands available through the terminal. The terminal isn't just an interface for quick commands or in-depth troubleshooting; it's a scripting environment that can reduce your workload by taking care of mundane tasks for you.
+
+### How to learn programming
+
+If you've never done any programming before, it might help to think of it in terms of two different challenges: one is to understand how code is written, and the other is to understand what code to write. You can learn _syntax_—but you won't get far without knowing what words are available to you in the _language_. In practice, you start learning both concepts all at once because you can't learn syntax without words to arrange, so initially, you write simple tasks using basic commands and basic programming structures. Once you feel comfortable with the basics, you can explore more of the language so you can make your programs do more and more significant things.
+
+In [Bash][2], most of the _words_ you use are Linux commands. The _syntax_ is Bash. If you already use Bash on a frequent basis, then the transition to Bash programming is relatively easy. But if you don't use Bash, you'll be pleased to learn that it's a simple language built for clarity and simplicity.
+
+### Interactive design
+
+Sometimes, the hardest thing to figure out when learning to program is what a computer can do for you. Obviously, if a computer on its own could do everything you do with it, then you wouldn't have to ever touch a computer again. But the reality is that humans are important. The key to finding something your computer can help you with is to take notice of tasks you repeatedly do throughout the week. Computers handle repetition particularly well.
+
+But for you to be able to tell your computer to do something, you must know how to do it. This is an area Bash excels in: interactive programming. As you perform an action in the terminal, you are also learning how to script it.
+
+For instance, I was once tasked with converting a large number of PDF books to versions that would be low-ink and printer-friendly. One way to do this is to open the PDF in a PDF editor, select each one of the hundreds of images—page backgrounds and textures counted as images—delete them, and then save it to a new PDF. Just one book would take half a day this way.
+
+My first thought was to learn how to script a PDF editor, but after days of research, I could not find a PDF editing application that could be scripted (outside of very ugly mouse-automation hacks). So I turned my attention to finding out to accomplish the task from within a terminal. This resulted in several new discoveries, including GhostScript, the open source version of PostScript (the printer language PDF is based on). By using GhostScript for the task for a few days, I confirmed that it was the solution to my problem.
+
+Formulating a basic script to run the command was merely a matter of copying the command and options I used to remove images from a PDF and pasting them into a text file. Running the file as a script would, presumably, produce the same results.
+
+### Passing arguments to a Bash script
+
+The difference between running a command in a terminal and running a command in a shell script is that the former is interactive. In a terminal, you can adjust things as you go. For instance, if I just processed **example_1.pdf** and am ready to process the next document, to adapt my command, I only need to change the filename.
+
+A shell script isn't interactive, though. In fact, the only reason a shell _script_ exists is so that you don't have to attend to it. This is why commands (and the shell scripts that run them) accept arguments.
+
+In a shell script, there are a few predefined variables that reflect how a script starts. The initial variable is **$0**, and it represents the command issued to start the script. The next variable is **$1**, which represents the first "argument" passed to the shell script. For example, in the command **echo hello**, the command **echo** is **$0,** and the word **hello** is **$1**. In the command **echo hello world**, the command **echo** is **$0**, **hello** is **$1**, and **world** is **$2**.
+
+In an interactive shell:
+
+
+```
+$ echo hello world
+hello world
+```
+
+In a non-interactive shell script, you _could_ do the same thing in a very literal way. Type this text into a text file and save it as **hello.sh**:
+
+
+```
+`echo hello world`
+```
+
+Now run the script:
+
+
+```
+$ bash hello.sh
+hello world
+```
+
+That works, but it doesn't take advantage of the fact that a script can take input. Change **hello.sh** to this:
+
+
+```
+`echo $1`
+```
+
+Run the script with two arguments grouped together as one with quotation marks:
+
+
+```
+$ bash hello.sh "hello bash"
+hello bash
+```
+
+For my PDF reduction project, I had a real need for this kind of non-interactivity, because each PDF took several minutes to condense. But by creating a script that accepted input from me, I could feed the script several PDF files all at once. The script processed each one sequentially, which could take half an hour or more, but it was a half-hour I could use for other tasks.
+
+### Flow control
+
+It's perfectly acceptable to create Bash scripts that are, essentially, transcripts of the exact process you took to achieve the task you need to be repeated. However, scripts can be made more powerful by controlling how information flows through them. Common methods of managing a script's response to data are:
+
+ * if/then
+ * for loops
+ * while loops
+ * case statements
+
+
+
+Computers aren't intelligent, but they are good at comparing and parsing data. Scripts can feel a lot more intelligent if you build some data analysis into them. For example, the basic **hello.sh** script runs whether or not there's anything to echo:
+
+
+```
+$ bash hello.sh foo
+foo
+$ bash hello.sh
+
+$
+```
+
+It would be more user-friendly if it provided a help message when it receives no input. That's an if/then statement, and if you're using Bash in a basic way, you probably wouldn't know that such a statement existed in Bash. But part of programming is learning the language, and with a little research you'd learn about if/then statements:
+
+
+```
+if [ "$1" = "" ]; then
+ echo "syntax: $0 WORD"
+ echo "If you provide more than one word, enclose them in quotes."
+else
+ echo "$1"
+fi
+```
+
+Running this new version of **hello.sh** results in:
+
+
+```
+$ bash hello.sh
+syntax: hello.sh WORD
+If you provide more than one word, enclose them in quotes.
+$ bash hello.sh "hello world"
+hello world
+```
+
+### Working your way through a script
+
+Whether you're looking for something to remove images from PDF files, or something to manage your cluttered Downloads folder, or something to create and provision Kubernetes images, learning to script Bash is a matter of using Bash and then learning ways to take those scripts from just a list of commands to something that responds to input. It's usually a process of discovery: you're bound to find new Linux commands that perform tasks you never imagined could be performed with text commands, and you'll find new functions of Bash to make your scripts adaptable to all the different ways you want them to run.
+
+One way to learn these tricks is to read other people's scripts. Get a feel for how people are automating rote commands on their systems. See what looks familiar to you, and look for more information about the things that are unfamiliar.
+
+Another way is to download our [introduction to programming with Bash][3] eBook. It introduces you to programming concepts specific to Bash, and with the constructs you learn, you can start to build your own commands. And of course, it's free to download and licensed under a [Creative Commons][4] license, so grab your copy today.
+
+### [Download our introduction to programming with Bash eBook!][3]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/bash-programming-guide
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/command_line_prompt.png?itok=wbGiJ_yg (Command line prompt)
+[2]: https://opensource.com/resources/what-bash
+[3]: https://opensource.com/downloads/bash-programming-guide
+[4]: https://opensource.com/article/20/1/what-creative-commons
diff --git a/sources/tech/20200410 How Kubernetes saved my desktop application.md b/sources/tech/20200410 How Kubernetes saved my desktop application.md
new file mode 100644
index 0000000000..ecbd6ee273
--- /dev/null
+++ b/sources/tech/20200410 How Kubernetes saved my desktop application.md
@@ -0,0 +1,55 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How Kubernetes saved my desktop application)
+[#]: via: (https://opensource.com/article/20/4/kubernetes-desktop-application)
+[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
+
+How Kubernetes saved my desktop application
+======
+Keep this fix in mind if you have a broken Java desktop application but
+aren't a crypto expert.
+![Puzzle pieces coming together to form a computer screen][1]
+
+Recently, fellow Opensource.com scribe James Farrell wrote a wonderful article entitled _[How Ansible brought peace to my home][2]_. In addition to the great article, I really liked the title, one of those unexpected phrases that I’m sure brought a smile to many faces.
+
+I recently had a weird but positive experience of my own that begs a similar sort of unexpected label. I’ve been grappling with a difficult problem that arose when upgrading some server and networking infrastructure that broke a Java application I’ve been supporting since the early 2000s. Strangely enough, I found the solution in what appears to be a very informative and excellent article on Kubernetes, of all things.
+
+Without further ado, here is my problem:
+
+![][3]
+
+I’m guessing that most readers will look at that message and think things like, "I hope there’s more info in the log file," or "I’m really glad I’ve never received a message like that."
+
+Unfortunately, there isn’t a lot of info in the log file, just the same message, in fact. In an effort to debug this, I did three things:
+
+ 1. I searched online for the message. Interestingly, or perhaps ominously, there were only 200 or so hits on this string, [one of which suggested][4] [turn][4][ing][4] [on more debugging output][4], which involved adding the setting
+
+
+```
+**-Djavax.net.debug=ssl:handshake:verbose**[/code] to the **java** command running the application.
+
+ 2. I tried that suggestion, which resulted in a lot of output (good), most of which only vaguely made sense to me as I’m no kind of expert in the underlying bits of stuff like SSL. But one thing I did notice is that there was no information regarding a response from the server in the midst of all of that output;
+
+ 3. So I searched some more.
+
+
+
+
+Another interesting part of this problem is that the code ran fine when executed by the Java command bundled in the OpenJDK, but failed with this error when using a customized runtime [created from the same OpenJDK in this way][5]. So the relatively modest number of apparently similar problems turned up from search #1 above were actually not all that relevant since they all seemed to be dealing mostly with bad SSL certificates on the server in conjunction with the PostgreSQL JDBC’s ability to check the server’s credentials.
+
+I should also mention that it took me quite some time to realize that the problem was introduced by using the custom Java runtime, as I managed to check many other possibilities along the way (and indeed, I did fix a few minor bugs while I was at it). My efforts included things like getting the latest OpenJDK, checking and re-checking all the URLs in case one had a typo, and so forth.
+
+As often happens, after putting the problem aside for a few hours, an idea occurred to me—perhaps I was missing some module in the customized Java runtime. While I didn’t receive any errors directly suggesting that problem, the observable fact that the standard OpenJDK environment worked while the custom one failed seemed to hint at that possibility. I took a quick look in the **jmods/** folder in the OpenJDK installation, but there are some 70 modules there and nothing jumped out at me.
+
+But again, what seemed odd was, with debugging turned on (see #1 above), there was no indication of what the server would accept, just what the client mostly couldn’t offer, many lines like this:
+```
+`Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`
+```
+So I was at least thinking by this time that maybe what was missing was the module that offered those kinds of cipher suites. So I started searching with strings like "jdbc crypto," and in the midst of that, the most unlikely article showed up: [Optimizing Kubernetes Services—Part 2: Spring Web][6], written by [Juan Medina][7]. Midway down the article, I spotted the following:
+
+![][8]
+
+Huh! Imagine that, his script is creating a custom Java runtime, just like mine. But he says he needs to add in manually the module **jdk.crypto.ec** in order t
\ No newline at end of file
diff --git a/sources/tech/20200412 Use this helpful Bash script when stargazing.md b/sources/tech/20200412 Use this helpful Bash script when stargazing.md
new file mode 100644
index 0000000000..f9e39e5632
--- /dev/null
+++ b/sources/tech/20200412 Use this helpful Bash script when stargazing.md
@@ -0,0 +1,121 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Use this helpful Bash script when stargazing)
+[#]: via: (https://opensource.com/article/20/4/linux-astronomy)
+[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
+
+Use this helpful Bash script when stargazing
+======
+Keep your eyes on the stars by putting your Linux machine in night
+vision mode with xcalib.
+![Computer laptop in space][1]
+
+We often talk about [Linux][2] being used on servers and by developers, but it is used in many other fields too, including astronomy. There are a lot of astronomy tools available for Linux, such as sky maps, star charts, and interfaces to telescope drive systems for controlling your telescope. But one challenge for astronomers is using a computer while keeping their eyes working in the dark.
+
+When working out in the field at night, astronomers need to preserve their night vision. It can take up to 30 minutes for the human eye to fully dilate and adjust to low light levels, and doing things like checking a phone or laptop at the regular color and brightness levels can cause the eyes to lose their adjustment. This reduces the ability to see in the dark. An example anyone can understand: if you're reading something on your phone in bed at night and get up to go to the bathroom, you know how difficult it can be to see any obstacles that might be in your way.
+
+### A solution
+
+I'd like to present a nifty little script to help the astronomer in your family keep "their eyes" in the dark. It relies on a utility called [xcalib][3], a "tiny monitor calibration loader for X.org." It can be installed easily using your Linux package manager.
+
+On Fedora, for example:
+
+
+```
+$ sudo dnf info xcalib
+$ sudo dnf install xcalib
+```
+
+Or Ubuntu:
+
+
+```
+`$ sudo apt-get install xcalib`
+```
+
+The xcalib application works only with X11, so it is not functional on Wayland systems. But Wayland has this functionality built-in, so you can get the same results through GNOME Settings. If you're using X11, xcalib is an easy way to change the color temperature of your display.
+
+### The script
+
+I discovered [Redscreen][4], a night vision filter script written by Jeff Jahr in 2014. The original script is written for the C shell, but Bash is the common default these days. In fact, the C shell is not installed by default on my current Fedora Linux workstation. So, I decided to write an updated version of the Redscreen script aimed at the newest Bash syntax, but I made one major change: utilizing a case statement.
+
+
+```
+#!/usr/bin/bash
+# redscreen.sh Fri Feb 28 11:36 EST 2020 Alan Formy-Duval
+# Turn screen red - Useful to Astronomers
+# Inspired by redscreen.csh created by Jeff Jahr 2014
+# ()
+
+# This program is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation,
+# either version 3 of the License, or (at your option) any
+# later version.
+
+# This program is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for
+# more details.
+
+# You should have received a copy of the GNU General Public
+# License along with this program.
+# If not, see <[http://www.gnu.org/licenses/\>][5].
+
+case $1 in
+ on)
+ # adjust color, gamma, brightness, contrast
+ xcalib -green .1 0 1 -blue .1 0 1 -red 0.5 1 40 -alter
+ exit 1
+ ;;
+ off)
+ xcalib -clear
+ exit 1
+ ;;
+ inv)
+ # Invert screen
+ xcalib -i -a
+ exit 1
+ ;;
+ dim)
+ # Make the screen darker
+ xcalib -clear
+ xcalib -co 30 -alter
+ exit 1
+ ;;
+ *)
+ echo "$0 [on | dim | inv | off]"
+ exit 1
+ ;;
+esac
+```
+
+![Skychart for Linux Version 4.2.1 on Fedora workstation][6]
+
+A lot of astronomy programs include a "night-mode" function, but not all do. Also, this script provides a way to affect the entire screen, not just a specific application. This allows you to use your Linux system out in the field at night for other things than just stargazing—such as checking email or reading Opensource.com—without ruining your night vision.
+
+Whether you are an astronomer or just an amateur stargazer, you can spend all night admiring the heavens using Linux and open source!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/linux-astronomy
+
+作者:[Alan Formy-Duval][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alanfdoss
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_space_graphic_cosmic.png?itok=wu493YbB (Computer laptop in space)
+[2]: https://opensource.com/resources/linux
+[3]: http://xcalib.sourceforge.net/
+[4]: http://www.jeffrika.com/~malakai/redscreen/index.html
+[5]: http://www.gnu.org/licenses/\>
+[6]: https://opensource.com/sites/default/files/uploads/starchart_in_red.png (A star chart displayed in red screen mode)
diff --git a/sources/tech/20200414 How young people can help fight COVID-19 with code.md b/sources/tech/20200414 How young people can help fight COVID-19 with code.md
new file mode 100644
index 0000000000..73705b5a62
--- /dev/null
+++ b/sources/tech/20200414 How young people can help fight COVID-19 with code.md
@@ -0,0 +1,139 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How young people can help fight COVID-19 with code)
+[#]: via: (https://opensource.com/article/20/4/covid19-hackathon)
+[#]: author: (Melissa Sasi https://opensource.com/users/mesassi)
+
+How young people can help fight COVID-19 with code
+======
+Youth developers are invited to submit ideas by April 15 to counter the
+educational, informational, social, and health challenges uncovered by
+the COVID-19 pandemic.
+![woman on laptop sitting at the window][1]
+
+More than 91% of students around the world are impacted by school closures due to COVID-19, and most governments have temporarily closed academic institutions. That's nearly [1.6 billion young people in 188 countries][2]. Also, most of the learning platforms available online today aren't practical, engaging, or interactive, and lack true virtual collaboration.
+
+This big and wicked challenge got me thinking about how these circumstances are impacting my children, their friends, and my passions of empowering youth, fostering tech entrepreneurship, and inspiring under-represented communities to find their purpose through building digital skills. These all came together in [CodeTheCurve][3], "a global, virtual hackathon for students, educators, teachers, and the research community to build tech skills, entrepreneurial spirit, and professional competencies to build digital creativity and cooperation to mobilize the world."
+
+We hope you'll want to participate, but you need to act fast: the deadline to submit proposals is April 15.
+
+### My story
+
+The passions mentioned above stem from a deeply personal journey: My children and I are victims of parental kidnapping, and access to the internet and digital literacy are my pathways to being a mother from afar. My children, Zahra (age 13), Zahran (15), and Youmna (18), are safe and healthy, and we are frequently connected. They're living the same life youth all over the world are living these days, trying to social distance and remain in good health while figuring out this school thing (or lack thereof)—only one of my children has access to formal virtual learning during to COVID-19 school closures. The other two, without school-driven online learning options, tend to stay up all night playing Fortnight and making TikTok videos.
+
+I have always been passionate about digital inclusion and empowering the world through computer science, and the effects of COVID-19 have increased my desire to make a difference. About four years ago, I created a non-profit organization, [MentorNations][4], to inspire youth and the world via technology. My non-profit has taught tens of thousands of young people in 12 countries to code. In my work at IBM as a developer advocate, I focus on empowering early-stage entrepreneurs, developers, and students with access to tech skills, professional development, and entrepreneurial thinking. My major focus areas include inspiring students to discover their career potential in enterprise computing while recognizing that we are all ANDs and not ORs.
+
+Teaching the next generation about the power of collaboration, teamwork, problem-solving, and critical thinking that happen through open source code and principles empowers them to be creators and innovators who focus on solving relevant and real-world problems.
+
+Looking through the lens of my children, my non-profit work, my roles within a variety of United Nations Task Forces, and my position as IEEE Chair over the Digital Skills Working Group, I wondered, _**what can I do to make a difference with open source technology?**_ So I reached out to my network, and the world responded in a much bigger way than I had ever imagined.
+
+### CodeTheCurve
+
+In response, we launched UNESCO's [CodeTheCurve][3] hackathon in collaboration with 14 partners, including UN EQUALS, SAP, iHackOnline, Angel Hack, Internet Society, and YPO. Participants are invited to bring their open source ideas to combat the current and future environment and challenges relating to COVID-19. This initiative is centered around youth empowerment, gender inclusion, and making the world a better place for our communities, including for people we may not directly encounter daily.
+
+CodeTheCurve is for anyone above the age of 16. To ensure gender, age, and experience diversity, teams must include a developer or data scientist (early-stage chops are fine); at least one person under the age of 25; and at least one male and one female. The 40 teams selected to participate in CodeTheCurve will have access to more than 80 business and technical mentors (experts!) from around the world to help turn their ideas into reality.
+
+My vision for this hackathon is to train young talent; enable them with free, online resources and access to real people with real answers; and encourage the creation of real-world problem solving in real-time. The results of the hackathon, I hope, will be open source utilities and information that can be used, in some way, to combat COVID-19.
+
+#### Week-long learning, bootcamp, and hacking experience
+
+CodeTheCurve is a three-day virtual hackathon experience guided by expert business and technical mentors. Before the hackathon proper, participants begin with two days of self-paced, online learning from content curated by CodeTheCurve collaborators, followed by a two-day, instructor-led learning journey where the 40 selected teams will collaborate in virtual breakout rooms with activity kits, hands-on computing resources in machine learning, and expert-guided plenary sessions.
+
+#### CodeTheCurve hackathon themes
+
+CodeTheCurve includes three themes:
+
+ * Education
+ * Information and data management
+ * Current and post-COVID-19 health and social issues
+
+
+
+#### Professional development, entrepreneurship, and hands-on open source skills
+
+The 40 teams will be empowered with expert-guided, engaging activities, including the following skill-building opportunities:
+
+ * **Hand-on tech skills**
+ * Using Jupyter Notebooks for data science
+ * Data protection, privacy, security, and encryption
+ * Machine learning and artificial intelligence
+ * Architectural diagrams and frameworks
+ * Technical roadmaps
+ * **Professional development**
+ * Design thinking
+ * Personal branding
+ * Communication skills
+ * How not to feel like an imposter
+ * Conflict resolution
+ * Working in global, virtual teams
+ * Media literacy
+ * Ethics in machine learning and artificial intelligence
+ * **Entrepreneurship**
+ * Problem statements
+ * Mission and vision statements
+ * Value propositions
+ * Audience and target markets
+ * Business model canvassing
+ * Pitch decks
+ * Pitch practice
+
+
+
+### April 15: CodeTheCurve deadline
+
+Did I mention that the initial application deadline is April 15? Here's the full timeline:
+
+ * Video submission deadline: **April 15**
+ * 40 selected teams announced: **April 20**
+ * Learning resources for pre-collaboration: **April 20-21**
+ * Instructor-led learning: **April 22-23**
+ * Hacking: **April 24-26**
+ * CodeTheCurve winners announced: **April 30**
+
+
+
+#### Prizes. Prizes. Prizes.
+
+Prizes include free access to [IBM LinuxONE Community Cloud][5] for one year, free training courses from SAP, four pitch opportunities at IBM and SAP events, free access to enterprise-grade IBM Z and its machine learning suite for six months, and one-on-one technical and business mentorship for a full year with industry experts.
+
+### How to apply
+
+Interested in applying? Know someone who should apply? Simply [submit a video][6] of your **amazing** open source idea, the problem you're trying to solve, and who you expect to reach.
+
+If you'd like to learn more, here are some other articles about CodeTheCurve:
+
+ * [UN News CodeTheCurve article][7]
+ * [UNESCO CodeTheCurve blog][8]
+ * [Forbes CodeTheCurve article][9]
+ * [IBM CodeTheCurve blog][10]
+
+
+
+I cannot wait to see all the amazing open source ideas the world brings our way!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/covid19-hackathon
+
+作者:[Melissa Sasi][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mesassi
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
+[2]: https://en.unesco.org/covid19/educationresponse
+[3]: https://www.codethecurve.org/
+[4]: https://mentornations.org/
+[5]: https://developer.ibm.com/linuxone/
+[6]: http://ibm.biz/codethecurve-apply
+[7]: https://news.un.org/en/story/2020/04/1061142
+[8]: http://ibm.biz/unesco-pr
+[9]: https://www.forbes.com/sites/danielnewman/2020/04/10/digital-transformation-for-good-shines-as-we-fight-covid-19/#78d51a4c4946
+[10]: http://ibm.biz/codethecurve
diff --git a/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md b/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md
new file mode 100644
index 0000000000..fc78ee9bce
--- /dev/null
+++ b/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md
@@ -0,0 +1,196 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Try this Kubernetes HTTP router and reverse proxy)
+[#]: via: (https://opensource.com/article/20/4/http-kubernetes-skipper)
+[#]: author: (Sandor Szücs https://opensource.com/users/sszuecs)
+
+Try this Kubernetes HTTP router and reverse proxy
+======
+Skipper is designed to handle large numbers of HTTP route definitions,
+beyond what you would want to manage in Nginx or Apache.
+![Traffic circle with arrows pointing which way to go][1]
+
+Skipper is an open source HTTP router and reverse proxy for service composition. As its [GitHub page][2] states, it's designed to handle large amounts of dynamically configured HTTP route definitions (>600,000 routes) with detailed lookup conditions and flexible augmentation of the request flow with filters. It can be used out of the box or extended with custom lookup, filter logic, and configuration sources.
+
+### Proxies
+
+When some people think of a proxy, they imagine a webpage that serves as a gateway to an intranet or a suspicious-looking webpage designed to unblock social media sites on a school or work network. A forward proxy is one that operators of desktop infrastructure use to save internet bandwidth, enforce parental controls, or limit social media access. Another kind of proxy is one in which an individual user navigates to a page, provides credentials, and is then forwarded to a protected intranet resource. The inverse of that kind of proxy is the reverse proxy, which accepts all traffic and forwards it to a specific resource, like a server or container. That's the kind of work Skipper does for infrastructure.
+
+When I read [Matt Klein's post][3] on modern network load balancing and proxying, I realized that we, as [Skipper][4] maintainers, should explain more features and details about why and how you can leverage HTTP proxies. In this article, I will treat the terminology "HTTP (reverse) proxy" and "HTTP router" as the same.
+
+### HTTP routing
+
+According to [Wikipedia][5]: "Routing is the process of selecting a path for traffic in a network." This definition refers to routing at [OSI layer 3][6], most commonly based on [IP][7] with routing protocols like [BGP][8] or [OSPF][9]. Since this article isn't about one of those, I will try to explain what HTTP routers are about. But first, I want to introduce Skipper, an [OSI layer 7][10] HTTP router library written in [Go][11] and a core component of retailer [Zalando][12]'s e-commerce shop and the [Kubernetes][13] Ingress infrastructure.
+
+At Zalando, we use Skipper as a [Kubernetes Ingress][14] controller to support our users with visibility, reliability, security, and additional features to offload common applications.
+
+Any organization running HTTP services, often in a microservice architecture, needs to route HTTP requests to the right applications. HTTP routers route based on information provided by the HTTP request. For example, the following shows an HTTP/1.1 request.
+
+
+```
+GET /details HTTP/1.1
+Host: [www.zalando.de][15]
+User-Agent: curl/7.49.0
+Accept: */*
+Authorization: Bearer <token>
+...
+```
+
+We can route based on the method **GET**, the path **/details**, the **Host** header [**www.zalando.de**][16], or any arbitrary part of the request.
+
+One common problem an application owner faces is splitting an API into multiple applications, so you need to split the responsibility of a component into subcomponents. Another common task is to support refactoring; maybe you have rewritten one part of your app, and you want to deploy it separately now.
+
+For example, imagine you you have a store that has a list of products and their details, and you need to split it into _shop_ and _product_ backend applications. At **/**, your shop shows the list of products, and at **/details**, it shows product details, such as color, size, sustainability, and price.
+
+![Figure 1: shop][17]
+
+You need to split the responsibility of the product detail into its own application, such that **/** stays in the _shop_ application and **/details** is refactored to the _product_ application.
+
+![Figure 2: product and shop][18]
+
+To make sure an HTTP proxy finds the right backend for an incoming request, it uses a routing table to check the destination to make sure it's correct.
+
+### Routing tables
+
+In Skipper, the routing table is created by pulling information generated by [dataclients][19] from different sources. One source can be a [routes file][20], similar to what you may see in more popular HTTP servers, like Apache or Nginx.
+
+Depending on the size of your organization—or better, the number of backend applications—the routing table can grow quite large. Skipper implements the routing table as a tree that can scale beyond 600,000 routes (far more than you'd want to manage in an Nginx or Apache config).
+
+Following along with the example application above, Table 1 shows the routing table from [Figure 2][21]. The store **/** should be routed to **shop,** and the **/detail** routed to the **product** application.
+
+path | app
+---|---
+/ | shop
+/detail | product
+
+Table 1: Routing table
+
+The available dataclients in Skipper fetch routes from different sources and what a route consists of.
+
+### Dataclient
+
+The routing configuration in Skipper's routes file [dataclient][22] is similar to what you might know from HTTP proxies in Nginx or Apache. In Skipper, a routes file specifies all routes in [eskip][23] syntax, as shown in Figure 3.
+
+
+```
+r1: P1() && P2() && .. && PN()
+ -> f1()
+ -> f2()
+ ...
+ -> fN()
+ -> <backend>;
+r2: ...
+...
+```
+
+Figure 3: Routes file in eskip
+
+In the above:
+
+ * **r1, r2, ...** are unique routeIDs.
+ * **P1, P2,..,PN** are predicates that define the matching.
+ * **f1, f2,..,fN** are filters that are applied after the route was selected. Filters can change the request and response.
+ * Finally, the Skipper backend is defined. This can be a single URL, a list of load-balanced URLs, and others for special cases such as [direct response][24].
+
+
+
+The [routes string][25] is another dataclient that is handy for tests. For example, if you need a pseudo backend for your demo that replies a green background with HTML, you could use:
+
+
+```
+$ skipper -routes-string='*
+-> inlineContent(
+ "<html><body style=\"background-color: green;\"></body></html>"
+ )'
+```
+
+Skipper's most popular dataclient, by far, is the Kubernetes dataclient, which is used to fetch information from a [Kubernetes API server][26] and create a routing table from [Skipper Ingress][27] resources and the [RouteGroup][28] custom resource definition (CRD).
+
+To summarize the above, dataclients fetch information from different providers to build Skipper's routing table. Table 1 shows a routing table for the shop/description example, and Skipper uses predicates to select the route to process the request.
+
+### Predicates
+
+In Skipper, an incoming request is matched to [predicates][29] of all the routes to find the best matching route for an incoming request. Predicates are functions that match based on the incoming request. In the example from Figure 2 and Table 1, Skipper would have a routing table similar to Figure 4:
+
+
+```
+shop: Path("/")
+ -> "";
+product: Path("/detail")
+ -> "";
+```
+
+Figure 4: Skipper routing table
+
+This means HTTP requests with a path **/** would be matched by the **Path("/")** predicate, such that Skipper will execute the shop route. Requests with a path **/detail** would be matched by **Path("/detail")** and routed to the product application.
+
+In general, routing behavior can be changed by predicates. There are a lot of predicates you can choose from. For example, **Method("POST")** will be true only if a POST request would be passed. A route with more predicates is considered more specific. Also, a route with more predicates has more weight in the route selection than one that has less.
+
+Special cases are **Path()** and **PathSubtree()**, which is matched first in a tree and reduces the number of routes, which are scanned as a list. For example, the tree structure shown in Figure 5 helps to scale the number of routes to more than 600,000 in one of Zalando's production setups.
+
+![Skipper tree example][30]
+
+### Filters
+
+After a route is selected, the request [filters][31] are applied. Filters work on request or response; they can change the incoming request to the backend, and they can change the response to the client.
+
+For example, **setRequestHeader("Foo", "bar")** sets the HTTP header **"Foo"** to the value **"bar"**, such that the backend sees this header in the request.
+
+The response filter **responseCookie("keks", "val", 3600)** sets a Cookie named **"keks"** in the response to the caller, which might be a browser in this case. The cookie would have the value **"val"** and is valid for one hour.
+
+One filter that works on request and response is **enableAccessLog(40, 5)**. This would do access logs for all responses from the backend with status codes 40x or 5xx.
+
+As you can see from the examples, filters can change the request or the response or just do some work based on it. Another filter example is **auth filters** or **ratelimits**. These would stop requests from passing to the backend if the request should not be allowed to pass. For example, to serve static content from a directory called **/var/www**, you can use the filter **static("/var/www")**.
+
+### Learn more
+
+This article provided a basic overview of Skipper and its capabilities. For more information, consult [Skipper's documentation][32], and please share your questions or feedback in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/http-kubernetes-skipper
+
+作者:[Sandor Szücs][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sszuecs
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LAW-patent_reform_520x292_10136657_1012_dc.png?itok=Cd2PmDWf (Traffic circle with arrows pointing which way to go)
+[2]: https://github.com/zalando/skipper
+[3]: https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236
+[4]: https://opensource.zalando.com/skipper
+[5]: https://en.wikipedia.org/wiki/Routing
+[6]: https://en.wikipedia.org/wiki/OSI_model#Layer_3:_Network_Layer
+[7]: https://en.wikipedia.org/wiki/Internet_Protocol
+[8]: https://en.wikipedia.org/wiki/Border_Gateway_Protocol
+[9]: https://en.wikipedia.org/wiki/Open_Shortest_Path_First
+[10]: https://en.wikipedia.org/wiki/OSI_model#Layer_7:_Application_Layer
+[11]: https://golang.org/
+[12]: https://en.zalando.de/
+[13]: https://kubernetes.io
+[14]: https://kubernetes.io/docs/concepts/services-networking/ingress/
+[15]: http://www.zalando.de
+[16]: https://en.zalando.de/?_rfl=de
+[17]: https://opensource.com/sites/default/files/uploads/skipper_1_shop.png (Figure 1: shop)
+[18]: https://opensource.com/sites/default/files/uploads/skipper_2_product-shop.png (Figure 2: product and shop)
+[19]: https://opensource.zalando.com/skipper/reference/backends/
+[20]: https://opensource.zalando.com/skipper/data-clients/eskip-file/
+[21]: tmp.ftM58r5YpM#fig2
+[22]: https://opensource.zalando.com/skipper/tutorials/development/#dataclients
+[23]: https://godoc.org/github.com/zalando/skipper/eskip
+[24]: https://opensource.zalando.com/skipper/reference/backends/#shunt-backend
+[25]: https://opensource.zalando.com/skipper/data-clients/route-string/
+[26]: https://kubernetes.io/docs/concepts/overview/components/#kube-apiserver
+[27]: https://opensource.zalando.com/skipper/kubernetes/ingress-usage/
+[28]: https://opensource.zalando.com/skipper/kubernetes/routegroups/
+[29]: https://opensource.zalando.com/skipper/reference/predicates/
+[30]: https://opensource.com/sites/default/files/uploads/skipper_5_tree.png (Skipper tree example)
+[31]: https://opensource.zalando.com/skipper/reference/filters/
+[32]: https://opensource.zalando.com/skipper/
diff --git a/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md b/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md
new file mode 100644
index 0000000000..807ebfae3d
--- /dev/null
+++ b/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md
@@ -0,0 +1,96 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (6 open source teaching tools for virtual classrooms)
+[#]: via: (https://opensource.com/article/20/4/open-source-remote-teaching-tools)
+[#]: author: (Mathias Hoffmann https://opensource.com/users/mhopensource)
+
+6 open source teaching tools for virtual classrooms
+======
+Create podcasts, online lectures, tutorials, and other teaching
+resources for learning at home with open source tools.
+![Person reading a book and digital copy][1]
+
+As schools and universities are shutting down around the globe due to COVID-19, many of us in academia are wondering how we can get up to speed and establish a stable workflow to get our podcasts, online lectures, and tutorials out there for our students.
+
+Open source software (OSS) has a key role to play in this situation for many reasons, including:
+
+ * **Speed:** OSS can roll out quickly and in large numbers (e.g., to an army of teaching assistants for multiple tutorial sessions in big lectures) without licensing issues and in a decentralized manner.
+ * **Cost:** OSS does not cost anything upfront, which is important for financially stretched schools and universities that need solutions to complex challenges on very short notice.
+
+
+
+With everything going online, we need new ways to engage with students. Here is a list of tools that I have found useful to share my own lectures.
+
+### Create podcasts, videos, or live streams with OBS
+
+[Open Broadcast Studio (OBS)][2] is a professional, open source audio and video recording tool that allows you to record, stream instantly, and do much more. OBS is available for all major platforms (Windows, macOS, and Linux), so interoperability with your colleagues and their various devices is ensured.
+
+Even if you're already using online conferencing software as a recording system, OBS can be a great backup solution. Since it records locally, you're protected against any network lags or disconnections. You also have complete control over your data, so many educational institutions may find it to be a more secure solution than some other options.
+
+Compatibility is also an advantage: OBS stores recordings in a standard intermediate format (MKV), which can be transferred to MP4 or other formats. Also, support for Nvidia graphics cards under OBS is great, as the company is one of the main sponsors of the OBS project. This allows you to make full use of your hardware and speed up the recording process.
+
+### Video and sound editing
+
+After you record your podcast or video, you may find that it needs editing. There are many reasons you may need to edit your audio or video. For example, many university online platforms restrict the size of files you can upload, so you may have to cut long videos. Or, the sound may be too quiet, or maybe it was too noisy when you recorded it, so you need to make adjustments to the audio.
+
+Two of the open source apps to explore are [OpenShot][3] and [Shotcut][4]. Of the two, Shotcut is a more advanced program, which implies a slightly steeper learning curve. Both are cross-platform and have full support for hardware encoding with NVidia and other graphics cards, which will substantially lower processing time compared to CPU-only processing.
+
+You can also extract a soundtrack in either program (although I have found it to be much faster with Shotcut) and export it to an audio-editing program. I find [Audacity][5], another open source, cross-platform (Mac, Linux, Windows) tool, to work extremely well.
+
+My typical workflow looks something like this:
+
+ * Import the recording into Shotcut
+ * Extract the audio, save it to an audio file
+ * Import it into Audacity, normalize and amplify the audio, maybe do some noise reduction
+ * Save the audio to a new file
+ * Import the new audio file into Shotcut, align it with the audio-free video, and cut appropriately
+ * Export into an MP4 video (this last step usually takes some time, so have a coffee…)
+
+
+
+### Electronic blackboards
+
+If you want to annotate your slides or develop ideas on an electronic blackboard, you need note-taking software and a device with a touchscreen or a graphics tablet. A great open source tool (developed with Swiss taxpayer funding) for blackboarding is [OpenBoard][6]. It is cross-platform; although it is officially only available for Linux on Ubuntu 16.04, you can install a [Flatpak][7] and it will work on any Linux flavor. It is really a nice tool; its only shortcoming is that annotating slides is not very good.
+
+My main open source annotation and electric blackboard tool is [Xournal++][8], which is available in some Linux distros repos (e.g., Linux Mint) and otherwise via [Flathub][9]. Like all the tools mentioned earlier, it is also available on Mac and Windows. If you know of any open source, cross-platform note-taking tools, please share them in the comments.
+
+### Built-in solutions have their limits
+
+You might wonder why you should bother with alternative recording software in the first place. After all, most modern operating systems have built-in screen recorders that will also capture audio. However, these built-in solutions have their limits. One key limitation is that you cannot usually capture more than one video source at a time (e.g., a webcam with your talking head and a set of slides plus a whiteboard from a graphics tablet).
+
+The ability to use multiple video sources is very useful, though, since it can be dull for students to just listen to your voice and see your slides for extended periods. Face-to-face interactions—even if done virtually—help keep listeners' attention and make it easier for them to cope with imperfect recording quality and background noise. In addition, many of the built-in tools do not allow you to capture selected areas of the screen, and in general, you cannot change the resolution or the number of frames per second, which can be important for keeping your podcast's memory and bandwidth usage in check.
+
+### Conclusion
+
+When planning your online teaching, you will want to use a blend of audio, video, slides, and electronic blackboards to create an immersive experience even while students are learning remotely. Open source software offers advanced, effective tools for creating such online educational experiences.
+
+* * *
+
+_This article is based on "[Open source software for online teaching in the times of corona][10]" on Mathias Hoffman's blog and is reused with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-remote-teaching-tools
+
+作者:[Mathias Hoffmann][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mhopensource
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/read_book_guide_tutorial_teacher_student_apaper.png?itok=_GOufk6N (Person reading a book and digital copy)
+[2]: https://obsproject.com/
+[3]: http://www.openshot.org/
+[4]: http://www.shotcut.org/
+[5]: https://www.audacityteam.org/
+[6]: http://www.openboard.ch/
+[7]: http://www.flathub.org
+[8]: https://github.com/xournalpp/xournalpp
+[9]: https://flathub.org/apps/details/com.github.xournalpp.xournalpp
+[10]: http://mathiashoffmann.net/2020/03/22/open-source-software-for-online-teaching-in-the-times-of-corona
diff --git a/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md b/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md
new file mode 100644
index 0000000000..c216d22663
--- /dev/null
+++ b/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md
@@ -0,0 +1,424 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to automate your cryptocurrency trades with Python)
+[#]: via: (https://opensource.com/article/20/4/python-crypto-trading-bot)
+[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
+
+How to automate your cryptocurrency trades with Python
+======
+In this tutorial, learn how to set up and use Pythonic, a graphical
+programming tool that makes it easy for users to create Python
+applications using ready-made function modules.
+![scientific calculator][1]
+
+Unlike traditional stock exchanges like the New York Stock Exchange that have fixed trading hours, cryptocurrencies are traded 24/7, which makes it impossible for anyone to monitor the market on their own.
+
+Often in the past, I had to deal with the following questions related to my crypto trading:
+
+ * What happened overnight?
+ * Why are there no log entries?
+ * Why was this order placed?
+ * Why was no order placed?
+
+
+
+The usual solution is to use a crypto trading bot that places orders for you when you are doing other things, like sleeping, being with your family, or enjoying your spare time. There are a lot of commercial solutions available, but I wanted an open source option, so I created the crypto-trading bot [Pythonic][2]. As [I wrote][3] in an introductory article last year, "Pythonic is a graphical programming tool that makes it easy for users to create Python applications using ready-made function modules." It originated as a cryptocurrency bot and has an extensive logging engine and well-tested, reusable parts such as schedulers and timers.
+
+### Getting started
+
+This hands-on tutorial teaches you how to get started with Pythonic for automated trading. It uses the example of trading [Tron][4] against [Bitcoin][5] on the [Binance][6] exchange platform. I choose these coins because of their volatility against each other, rather than any personal preference.
+
+The bot will make decisions based on [exponential moving averages][7] (EMAs).
+
+![TRX/BTC 1-hour candle chart][8]
+
+TRX/BTC 1-hour candle chart
+
+The EMA indicator is, in general, a weighted moving average that gives more weight to recent price data. Although a moving average may be a simple indicator, I've had good experiences using it.
+
+The purple line in the chart above shows an EMA-25 indicator (meaning the last 25 values were taken into account).
+
+The bot monitors the pitch between the current EMA-25 value (t0) and the previous EMA-25 value (t-1). If the pitch exceeds a certain value, it signals rising prices, and the bot will place a buy order. If the pitch falls below a certain value, the bot will place a sell order.
+
+The pitch will be the main indicator for making decisions about trading. For this tutorial, it will be called the _trade factor_.
+
+### Toolchain
+
+The following tools are used in this tutorial:
+
+ * Binance expert trading view (visualizing data has been done by many others, so there's no need to reinvent the wheel by doing it yourself)
+ * Jupyter Notebook for data-science tasks
+ * Pythonic, which is the overall framework
+ * PythonicDaemon as the pure runtime (console- and Linux-only)
+
+
+
+### Data mining
+
+For a crypto trading bot to make good decisions, it's essential to get open-high-low-close ([OHLC][9]) data for your asset in a reliable way. You can use Pythonic's built-in elements and extend them with your own logic.
+
+The general workflow is:
+
+ 1. Synchronize with Binance time
+ 2. Download OHLC data
+ 3. Load existing OHLC data from the file into memory
+ 4. Compare both datasets and extend the existing dataset with the newer rows
+
+
+
+This workflow may be a bit overkill, but it makes this solution very robust against downtime and disconnections.
+
+To begin, you need the **Binance OHLC Query** element and a **Basic Operation** element to execute your own code.
+
+![Data-mining workflow][10]
+
+Data-mining workflow
+
+The OHLC query is set up to query the asset pair **TRXBTC** (Tron/Bitcoin) in one-hour intervals.
+
+![Configuration of the OHLC query element][11]
+
+Configuring the OHLC query element
+
+The output of this element is a [Pandas DataFrame][12]. You can access the DataFrame with the **input** variable in the **Basic Operation** element. Here, the **Basic Operation** element is set up to use Vim as the default code editor.
+
+![Basic Operation element set up to use Vim][13]
+
+Basic Operation element set up to use Vim
+
+Here is what the code looks like:
+
+
+```
+import pickle, pathlib, os
+import pandas as pd
+
+outout = None
+
+if isinstance(input, pd.DataFrame):
+ file_name = 'TRXBTC_1h.bin'
+ home_path = str(pathlib.Path.home())
+ data_path = os.path.join(home_path, file_name)
+
+ try:
+ df = pickle.load(open(data_path, 'rb'))
+ n_row_cnt = df.shape[0]
+ df = pd.concat([df,input], ignore_index=True).drop_duplicates(['close_time'])
+ df.reset_index(drop=True, inplace=True)
+ n_new_rows = df.shape[0] - n_row_cnt
+ log_txt = '{}: {} new rows written'.format(file_name, n_new_rows)
+ except:
+ log_txt = 'File error - writing new one: {}'.format(e)
+ df = input
+
+ pickle.dump(df, open(data_path, "wb" ))
+ output = df
+```
+
+First, check whether the input is the DataFrame type. Then look inside the user's home directory (**~/**) for a file named **TRXBTC_1h.bin**. If it is present, then open it, concatenate new rows (the code in the **try** section), and drop overlapping duplicates. If the file doesn't exist, trigger an _exception_ and execute the code in the **except** section, creating a new file.
+
+As long as the checkbox **log output** is enabled, you can follow the logging with the command-line tool **tail**:
+
+
+```
+`$ tail -f ~/Pythonic_2020/Feb/log_2020_02_19.txt`
+```
+
+For development purposes, skip the synchronization with Binance time and regular scheduling for now. This will be implemented below.
+
+### Data preparation
+
+The next step is to handle the evaluation logic in a separate grid; therefore, you have to pass over the DataFrame from Grid 1 to the first element of Grid 2 with the help of the **Return element**.
+
+In Grid 2, extend the DataFrame by a column that contains the EMA values by passing the DataFrame through a **Basic Technical Analysis** element.
+
+![Technical analysis workflow in Grid 2][14]
+
+Technical analysis workflow in Grid 2
+
+Configure the technical analysis element to calculate the EMAs over a period of 25 values.
+
+![Configuration of the technical analysis element][15]
+
+Configuring the technical analysis element
+
+When you run the whole setup and activate the debug output of the **Technical Analysis** element, you will realize that the values of the EMA-25 column all seem to be the same.
+
+![Missing decimal places in output][16]
+
+Decimal places are missing in the output
+
+This is because the EMA-25 values in the debug output include just six decimal places, even though the output retains the full precision of an 8-byte float value.
+
+For further processing, add a **Basic Operation** element:
+
+![Workflow in Grid 2][17]
+
+Workflow in Grid 2
+
+With the **Basic Operation** element, dump the DataFrame with the additional EMA-25 column so that it can be loaded into a Jupyter Notebook;
+
+![Dump extended DataFrame to file][18]
+
+Dump extended DataFrame to file
+
+### Evaluation logic
+
+Developing the evaluation logic inside Juypter Notebook enables you to access the code in a more direct way. To load the DataFrame, you need the following lines:
+
+![Representation with all decimal places][19]
+
+Representation with all decimal places
+
+You can access the latest EMA-25 values by using [**iloc**][20] and the column name. This keeps all of the decimal places.
+
+You already know how to get the latest value. The last line of the example above shows only the value. To copy the value to a separate variable, you have to access it with the **.at** method, as shown below.
+
+You can also directly calculate the trade factor, which you will need in the next step.
+
+![Buy/sell decision][21]
+
+Buy/sell decision
+
+### Determine the trading factor
+
+As you can see in the code above, I chose 0.009 as the trade factor. But how do I know if 0.009 is a good trading factor for decisions? Actually, this factor is really bad, so instead, you can brute-force the best-performing trade factor.
+
+Assume that you will buy or sell based on the closing price.
+
+![Validation function][22]
+
+Validation function
+
+In this example, **buy_factor** and **sell_factor** are predefined. So extend the logic to brute-force the best performing values.
+
+![Nested for loops for determining the buy and sell factor][23]
+
+Nested _for_ loops for determining the buy and sell factor
+
+This has 81 loops to process (9x9), which takes a couple of minutes on my machine (a Core i7 267QM).
+
+![System utilization while brute forcing][24]
+
+System utilization while brute-forcing
+
+After each loop, it appends a tuple of **buy_factor**, **sell_factor**, and the resulting **profit** to the **trading_factors** list. Sort the list by profit in descending order.
+
+![Sort profit with related trading factors in descending order][25]
+
+Sort profit with related trading factors in descending order
+
+When you print the list, you can see that 0.002 is the most promising factor.
+
+![Sorted list of trading factors and profit][26]
+
+Sorted list of trading factors and profit
+
+When I wrote this in March 2020, the prices were not volatile enough to present more promising results. I got much better results in February, but even then, the best-performing trading factors were also around 0.002.
+
+### Split the execution path
+
+Start a new grid now to maintain clarity. Pass the DataFrame with the EMA-25 column from Grid 2 to element 0A of Grid 3 by using a **Return** element.
+
+In Grid 3, add a **Basic Operation** element to execute the evaluation logic. Here is the code of that element:
+
+![Implemented evaluation logic][27]
+
+Implemented evaluation logic
+
+The element outputs a **1** if you should buy or a **-1** if you should sell. An output of **0** means there's nothing to do right now. Use a **Branch** element to control the execution path.
+
+![Branch element: Grid 3 Position 2A][28]
+
+Branch element: Grid 3, Position 2A
+
+Due to the fact that both **0** and **-1** are processed the same way, you need an additional Branch element on the right-most execution path to decide whether or not you should sell.
+
+![Branch element: Grid 3 Position 3B][29]
+
+Branch element: Grid 3, Position 3B
+
+Grid 3 should now look like this:
+
+![Workflow on Grid 3][30]
+
+Workflow on Grid 3
+
+### Execute orders
+
+Since you cannot buy twice, you must keep a persistent variable between the cycles that indicates whether you have already bought.
+
+You can do this with a **Stack element**. The Stack element is, as the name suggests, a representation of a file-based stack that can be filled with any Python data type.
+
+You need to define that the stack contains only one Boolean element, which determines if you bought (**True**) or not (**False**). As a consequence, you have to preset the stack with one **False**. You can set this up, for example, in Grid 4 by simply passing a **False** to the stack.
+
+![Forward a False-variable to the subsequent Stack element][31]
+
+Forward a **False** variable to the subsequent Stack element
+
+The Stack instances after the branch tree can be configured as follows:
+
+![Configuration of the Stack element][32]
+
+Configuring the Stack element
+
+In the Stack element configuration, set **Do this with input** to **Nothing**. Otherwise, the Boolean value will be overwritten by a 1 or 0.
+
+This configuration ensures that only one value is ever saved in the stack (**True** or **False**), and only one value can ever be read (for clarity).
+
+Right after the Stack element, you need an additional **Branch** element to evaluate the stack value before you place the **Binance Order** elements.
+
+![Evaluate the variable from the stack][33]
+
+Evaluating the variable from the stack
+
+Append the Binance Order element to the **True** path of the Branch element. The workflow on Grid 3 should now look like this:
+
+![Workflow on Grid 3][34]
+
+Workflow on Grid 3
+
+The Binance Order element is configured as follows:
+
+![Configuration of the Binance Order element][35]
+
+Configuring the Binance Order element
+
+You can generate the API and Secret keys on the Binance website under your account settings.
+
+![Creating an API key in Binance][36]
+
+Creating an API key in the Binance account settings
+
+In this tutorial, every trade is executed as a market trade and has a volume of 10,000 TRX (~US$ 150 on March 2020). (For the purposes of this tutorial, I am demonstrating the overall process by using a Market Order. Because of that, I recommend using at least a Limit order.)
+
+The subsequent element is not triggered if the order was not executed properly (e.g., a connection issue, insufficient funds, or incorrect currency pair). Therefore, you can assume that if the subsequent element is triggered, the order was placed.
+
+Here is an example of output from a successful sell order for XMRBTC:
+
+![Output of a successfully placed sell order][37]
+
+Successful sell order output
+
+This behavior makes subsequent steps more comfortable: You can always assume that as long the output is proper, the order was placed. Therefore, you can append a **Basic Operation** element that simply writes the output to **True** and writes this value on the stack to indicate whether the order was placed or not.
+
+If something went wrong, you can find the details in the logging message (if logging is enabled).
+
+![Logging output of Binance Order element][38]
+
+Logging output from Binance Order element
+
+### Schedule and sync
+
+For regular scheduling and synchronization, prepend the entire workflow in Grid 1 with the **Binance Scheduler** element.
+
+![Binance Scheduler at Grid 1, Position 1A][39]
+
+Binance Scheduler at Grid 1, Position 1A
+
+The Binance Scheduler element executes only once, so split the execution path on the end of Grid 1 and force it to re-synchronize itself by passing the output back to the Binance Scheduler element.
+
+![Grid 1: Split execution path][40]
+
+Grid 1: Split execution path
+
+Element 5A points to Element 1A of Grid 2, and Element 5B points to Element 1A of Grid 1 (Binance Scheduler).
+
+### Deploy
+
+You can run the whole setup 24/7 on your local machine, or you could host it entirely on an inexpensive cloud system. For example, you can use a Linux/FreeBSD cloud system for about US$5 per month, but they usually don't provide a window system. If you want to take advantage of these low-cost clouds, you can use PythonicDaemon, which runs completely inside the terminal.
+
+![PythonicDaemon console interface][41]
+
+PythonicDaemon console
+
+PythonicDaemon is part of the basic installation. To use it, save your complete workflow, transfer it to the remote running system (e.g., by Secure Copy [SCP]), and start PythonicDaemon with the workflow file as an argument:
+
+
+```
+`$ PythonicDaemon trading_bot_one`
+```
+
+To automatically start PythonicDaemon at system startup, you can add an entry to the crontab:
+
+
+```
+`# crontab -e`
+```
+
+![Crontab on Ubuntu Server][42]
+
+Crontab on Ubuntu Server
+
+### Next steps
+
+As I wrote at the beginning, this tutorial is just a starting point into automated trading. Programming trading bots is approximately 10% programming and 90% testing. When it comes to letting your bot trade with your money, you will definitely think thrice about the code you program. So I advise you to keep your code as simple and easy to understand as you can.
+
+If you want to continue developing your trading bot on your own, the next things to set up are:
+
+ * Automatic profit calculation (hopefully only positive!)
+ * Calculation of the prices you want to buy for
+ * Comparison with your order book (i.e., was the order filled completely?)
+
+
+
+You can download the whole example on [GitHub][2].
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/python-crypto-trading-bot
+
+作者:[Stephan Avenwedde][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hansic99
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calculator_money_currency_financial_tool.jpg?itok=2QMa1y8c (scientific calculator)
+[2]: https://github.com/hANSIc99/Pythonic
+[3]: https://opensource.com/article/19/5/graphically-programming-pythonic
+[4]: https://tron.network/
+[5]: https://bitcoin.org/en/
+[6]: https://www.binance.com/
+[7]: https://www.investopedia.com/terms/e/ema.asp
+[8]: https://opensource.com/sites/default/files/uploads/1_ema-25.png (TRX/BTC 1-hour candle chart)
+[9]: https://en.wikipedia.org/wiki/Open-high-low-close_chart
+[10]: https://opensource.com/sites/default/files/uploads/2_data-mining-workflow.png (Data-mining workflow)
+[11]: https://opensource.com/sites/default/files/uploads/3_ohlc-query.png (Configuration of the OHLC query element)
+[12]: https://pandas.pydata.org/pandas-docs/stable/getting_started/dsintro.html#dataframe
+[13]: https://opensource.com/sites/default/files/uploads/4_edit-basic-operation.png (Basic Operation element set up to use Vim)
+[14]: https://opensource.com/sites/default/files/uploads/6_grid2-workflow.png (Technical analysis workflow in Grid 2)
+[15]: https://opensource.com/sites/default/files/uploads/7_technical-analysis-config.png (Configuration of the technical analysis element)
+[16]: https://opensource.com/sites/default/files/uploads/8_missing-decimals.png (Missing decimal places in output)
+[17]: https://opensource.com/sites/default/files/uploads/9_basic-operation-element.png (Workflow in Grid 2)
+[18]: https://opensource.com/sites/default/files/uploads/10_dump-extended-dataframe.png (Dump extended DataFrame to file)
+[19]: https://opensource.com/sites/default/files/uploads/11_load-dataframe-decimals.png (Representation with all decimal places)
+[20]: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html
+[21]: https://opensource.com/sites/default/files/uploads/12_trade-factor-decision.png (Buy/sell decision)
+[22]: https://opensource.com/sites/default/files/uploads/13_validation-function.png (Validation function)
+[23]: https://opensource.com/sites/default/files/uploads/14_brute-force-tf.png (Nested for loops for determining the buy and sell factor)
+[24]: https://opensource.com/sites/default/files/uploads/15_system-utilization.png (System utilization while brute forcing)
+[25]: https://opensource.com/sites/default/files/uploads/16_sort-profit.png (Sort profit with related trading factors in descending order)
+[26]: https://opensource.com/sites/default/files/uploads/17_sorted-trading-factors.png (Sorted list of trading factors and profit)
+[27]: https://opensource.com/sites/default/files/uploads/18_implemented-evaluation-logic.png (Implemented evaluation logic)
+[28]: https://opensource.com/sites/default/files/uploads/19_output.png (Branch element: Grid 3 Position 2A)
+[29]: https://opensource.com/sites/default/files/uploads/20_editbranch.png (Branch element: Grid 3 Position 3B)
+[30]: https://opensource.com/sites/default/files/uploads/21_grid3-workflow.png (Workflow on Grid 3)
+[31]: https://opensource.com/sites/default/files/uploads/22_pass-false-to-stack.png (Forward a False-variable to the subsequent Stack element)
+[32]: https://opensource.com/sites/default/files/uploads/23_stack-config.png (Configuration of the Stack element)
+[33]: https://opensource.com/sites/default/files/uploads/24_evaluate-stack-value.png (Evaluate the variable from the stack)
+[34]: https://opensource.com/sites/default/files/uploads/25_grid3-workflow.png (Workflow on Grid 3)
+[35]: https://opensource.com/sites/default/files/uploads/26_binance-order.png (Configuration of the Binance Order element)
+[36]: https://opensource.com/sites/default/files/uploads/27_api-key-binance.png (Creating an API key in Binance)
+[37]: https://opensource.com/sites/default/files/uploads/28_sell-order.png (Output of a successfully placed sell order)
+[38]: https://opensource.com/sites/default/files/uploads/29_binance-order-output.png (Logging output of Binance Order element)
+[39]: https://opensource.com/sites/default/files/uploads/30_binance-scheduler.png (Binance Scheduler at Grid 1, Position 1A)
+[40]: https://opensource.com/sites/default/files/uploads/31_split-execution-path.png (Grid 1: Split execution path)
+[41]: https://opensource.com/sites/default/files/uploads/32_pythonic-daemon.png (PythonicDaemon console interface)
+[42]: https://opensource.com/sites/default/files/uploads/33_crontab.png (Crontab on Ubuntu Server)
diff --git a/sources/tech/20200415 Writing Java with Quarkus in VS Code.md b/sources/tech/20200415 Writing Java with Quarkus in VS Code.md
new file mode 100644
index 0000000000..2d61db71de
--- /dev/null
+++ b/sources/tech/20200415 Writing Java with Quarkus in VS Code.md
@@ -0,0 +1,239 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Writing Java with Quarkus in VS Code)
+[#]: via: (https://opensource.com/article/20/4/java-quarkus-vs-code)
+[#]: author: (Daniel Oh https://opensource.com/users/daniel-oh)
+
+Writing Java with Quarkus in VS Code
+======
+In this tutorial, I'll walk you through how to rebuild, package, and
+deploy cloud-native applications automatically with Quarkus.
+![Person drinking a hat drink at the computer][1]
+
+In the previous articles in this series about cloud-native [Java][2] applications, I shared [_6 requirements of cloud-native software_][3] and [_4 things cloud-native Java must provide_][4]. But now you might want to implement these advanced Java applications in your local machine without climbing a steep learning curve. In this article, I will walk through using the open source technologies [Quarkus][5] and [Visual Studio Code][6] (VS Code) to accelerate the development of both traditional cloud-native Java stacks and also serverless, reactive applications with easier and more familiar methods.
+
+Quarkus is a Kubernetes-native Java stack tailored for GraalVM and OpenJDK HotSpot. It's crafted from best-of-breed Java libraries and standards with live coding, unified configuration, superfast startup, small memory footprint, and unified imperative and reactive development. VS Code is an open source integrated development environment (IDE) for editing code.
+
+### Generate a Quarkus project
+
+Begin by navigating to Quarkus' [Start coding][7] page to generate a Quarkus project that includes a RESTful endpoint. Leave all variables (i.e., Group, Artifact, Build Tool, Extensions) on the default settings, then click **Generate your application** at the top-right of the page. Note that the RESTEasy JAX-RS extension is preselected as default.
+
+![Quarkus Generate application button][8]
+
+The ZIP file will automatically download on your local machine. Extract the file with the following command:
+
+
+```
+$ unzip code-with-quarkus.zip
+Archive: code-with-quarkus.zip
+ creating: code-with-quarkus/
+ inflating: code-with-quarkus/pom.xml
+ ...
+```
+
+### Install VS Code
+
+Download and install VS Code in your preferred way, whether that's [from the website][9] or through your package manager (dnf, apt, brew, etc). Once that's done, open the unzipped Quarkus project using VS Code's command-line tool:
+
+
+```
+$ cd code-with-quarkus/
+$ code .
+```
+
+You will see the [Apache Maven][10] project structure with:
+
+ * **ExampleResource** exposed on **/hello**
+ * Associated JUnit test
+ * Accessible landing page via
+ * Dockerfiles for both [native compilation][11] and JVM HotSpot
+ * A unified application configuration file
+
+
+
+Add Quarkus tools to your IDE through the VS Code's extension feature.
+
+![Add Quarkus tools to VS Code IDE][12]
+
+### Start coding
+
+Run the application using Quarkus development mode. To run the application, you need:
+
+ * JDK 1.8+ installed with JAVA_HOME configured appropriately
+ * Apache Maven 3.6.3+
+
+
+
+Move to the **code-with-quarkus** directory then type **mvn compile quarkus:dev** in VS Code's terminal.
+
+![Run application][13]
+
+You will see that the Java application is running well with:
+
+ * About one second to startup
+ * Live coding activated
+ * EnabledCDI and RESTEASY features
+
+
+
+When you access the endpoint via a web browser, you will see the return code, **hello**.
+
+!["Hello" return][14]
+
+Now, you're ready to change the code! Move back to VS Code, then open the **ExampleResource.java** file in **src/main/java/org/acme**. Replace the return code with "**Welcome, Cloud-Native Java with Quarkus!"** Don't forget to **Save** the file.
+
+![Editing the return][15]
+
+Go back to the web browser and reload the page.
+
+![New return][16]
+
+_It's like magic!_ Behind the scenes, Quarkus rebuilt, packaged, and deployed the application for you automatically, and it only took half a second. This is one of the essential cloud-native Java runtime features for increasing development productivity.
+
+![Quarkus output][17]
+
+Continue running your cloud-native Java application in Quarkus.
+
+### Integrate data transactions via Quakrus Tool
+
+To add an in-memory database (H2) transaction capability, press **F1** then click on **Quarkus: Add extensions to the current project**.
+
+![Adding extensions in Quarkus][18]
+
+Enter **h2** in the search bar, then double-click on **JDBC Driver - H2 Data** in the result.
+
+![JDBC Driver - H2 Data extension][19]
+
+Select the following three extensions, which will simplify your persistence code and return JSON format data:
+
+ * Hibernate ORM with Panache Data
+ * JDBC Driver - H2
+ * RESTEasy JSON-B Web
+
+
+
+Press **Enter** to add those dependencies.
+
+![Add Quarkus extensions][20]
+
+You should see the following in a new VS Code terminal:
+
+![VS Code adding extensions][21]
+
+You should also find the following pulled dependencies in **POM.xml**:
+
+![dependencies in POM.xml][22]
+
+### Create an Inventory entity
+
+With your project in place, you can get to work defining the business logic.
+
+The first step is to define the model (entity) of an Inventory object. Since Quarkus uses Hibernate ORM Panache, create an **Inventory.java** file in the **src.main.java.org.acme** directory, and paste the following code into it:
+
+
+```
+package org.acme;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+
+import io.quarkus.hibernate.orm.panache.PanacheEntity;
+
+@[Entity][23]
+@Cacheable
+public class Inventory extends PanacheEntity {
+
+ public [String][24] itemId;
+ public [String][24] location;
+ public int quantity;
+ public [String][24] link
+
+ public Inventory() {
+
+ }
+
+}
+```
+
+#### Define the RESTful endpoint of Inventory
+
+Next, mirror the abstraction of service so that you can inject the Inventory service into various places (like a RESTful resource endpoint) in the future. Create an **InventoryResource.java** file in the **src.main.java.org.acme** directory and add this code to it:
+
+
+```
+package org.acme;
+
+import java.util.List;
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path("/services/inventory")
+@ApplicationScoped
+@Produces("application/json")
+@Consumes("application/json")
+public class InventoryResource {
+
+ @GET
+
+ public List<Inventory> getAll() {
+ return Inventory.listAll();
+ }
+}
+```
+
+Don't forget to save these files. Go back to your web browser and access a new endpoint, . You will see:
+
+![Inventory endpoint][25]
+
+### Wrapping up
+
+If you have an issue or get an error when you implement this, you can find and reuse the [code in my GitHub repository][26].
+
+If you want to learn more, Quarkus has some [practical and useful guides][27] that show how to develop advanced cloud-native Java applications using Quarkus extensions with event-driven programming, serverless development, and Kubernetes deployment.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/java-quarkus-vs-code
+
+作者:[Daniel Oh][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/daniel-oh
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
+[2]: https://opensource.com/resources/java
+[3]: https://opensource.com/article/20/1/cloud-native-software
+[4]: https://opensource.com/article/20/1/cloud-native-java
+[5]: https://quarkus.io/
+[6]: https://code.visualstudio.com/
+[7]: https://code.quarkus.io/
+[8]: https://opensource.com/sites/default/files/uploads/quarkus_generateapplication.png (Quarkus Generate application button)
+[9]: https://code.visualstudio.com/download
+[10]: https://maven.apache.org/
+[11]: https://quarkus.io/guides/building-native-image
+[12]: https://opensource.com/sites/default/files/uploads/add-quarkus-to-ide.png (Add Quarkus tools to VS Code IDE)
+[13]: https://opensource.com/sites/default/files/uploads/run-application.png (Run application)
+[14]: https://opensource.com/sites/default/files/uploads/endpoint-hello.png ("Hello" return)
+[15]: https://opensource.com/sites/default/files/uploads/edit-return-code.png (Editing the return)
+[16]: https://opensource.com/sites/default/files/uploads/new-return-code.png (New return)
+[17]: https://opensource.com/sites/default/files/uploads/quarkus-magic.png (Quarkus output)
+[18]: https://opensource.com/sites/default/files/uploads/quarkus-add-extensions.png (Adding extensions in Quarkus)
+[19]: https://opensource.com/sites/default/files/uploads/jbdc-driver-h2-data.png (JDBC Driver - H2 Data extension)
+[20]: https://opensource.com/sites/default/files/uploads/add-extensions.png (Add Quarkus extensions)
+[21]: https://opensource.com/sites/default/files/uploads/vscode-adding-extensions.png (VS Code adding extensions)
+[22]: https://opensource.com/sites/default/files/uploads/dependencies-pomxml.png (dependencies in POM.xml)
+[23]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+entity
+[24]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
+[25]: https://opensource.com/sites/default/files/uploads/inventory-endpoint.png (Inventory endpoint)
+[26]: https://github.com/danieloh30/code-with-quarkus
+[27]: https://quarkus.io/guides/
diff --git a/sources/tech/20200417 How to set up and run WordPress for your classroom.md b/sources/tech/20200417 How to set up and run WordPress for your classroom.md
new file mode 100644
index 0000000000..bb8b87d560
--- /dev/null
+++ b/sources/tech/20200417 How to set up and run WordPress for your classroom.md
@@ -0,0 +1,164 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to set up and run WordPress for your classroom)
+[#]: via: (https://opensource.com/article/20/4/wordpress-virtual-machine)
+[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
+
+How to set up and run WordPress for your classroom
+======
+Follow these simple steps to customize WordPress for use in the
+classroom using free open source software.
+![Painting art on a computer screen][1]
+
+There are many good reasons to set up WordPress for your classroom. As more schools switch to online classes, WordPress can become the go-to content management system. Teachers using WordPress can provide a number of different educational choices to differentiate instruction for their students. Blogging is an accessible way to create content that energizes student learning. Teachers can write short stories, poems, and provide picture galleries that function as story starters. Students can comment and those comments can be moderated by their teacher.
+
+There are free options like [WordPress.com][2] and [Edublogs][3]. However, these free versions are limited, and you may want to explore all your options. You can install [Virtualbox][4] on any Windows, macOS, or Linux computer. You can use your own computer or an extra you happen to have access to in a virtual environment.
+
+On Linux, you can install Virtualbox from your package manager. For instance, on Debian, Elementary OS, or Ubuntu:
+
+
+```
+`$ sudo apt install virtualbox`
+```
+
+On Fedora:
+
+
+```
+`$ sudo dnf install virtualbox`
+```
+
+### Download a Wordpress image
+
+Wordpress is easy to install, but server configuration and management can be difficult for the uninitiated. That's why there's [Turnkey Linux][5], a project dedicated to creating virtual machine images and containers of popular server software, preconfigured and ready to run. With Turnkey Linux, you just download a disk image containing the operating system and the software you want to run, and then import that image into Virtualbox.
+
+To get started with Wordpress, download the **VM** virtual machine image from [turnkeylinux.org/wordpress][6] (in the **Builds** section). Make sure you download the image labeled **VM**, because that's the only format meant for Virtualbox.
+
+### Import the image into Virtualbox
+
+After installing Virtualbox, launch the application and import the virtual machine image into Virtualbox.
+
+![][7]
+
+Networking on the imported image is set to NAT by default. You will want to change the network settings to "bridged."
+
+![Virtualbox menu][8]
+
+After restarting the virtual machine, you are prompted to add passwords for MySQL, Adminer, and the WordPress **admin** user.
+
+Then you see the network configuration console for the installation. Launch a web browser and navigate to the **web** address provided (in this example, it's 192.168.86.149).
+
+![Console][9]
+
+In a web browser, you see a login screen for your Wordpress installation. Click on the **Login** link.
+
+![Wordpress welcome][10]
+
+Enter **admin** as the username, followed by the password you created earlier. Click the **Login** link. On this first login as **admin**, you can choose a new password. Be sure to remember it!
+
+![Login screen][11]
+
+After logging in, you're presented with the WordPress Dashboard. The software will likely notify you, in the upper left corner of the window, that a new version of Wordpress exists. Update to the latest versions as prompted so your site is secure.
+
+It's important to note that your Wordpress blog isn't visible by anyone on the Internet yet. It only exists in your local network: only people in your building who are connected to the same router or wifi access point as you can see your Wordpress site right now. The worldwide Internet can't get to it because you're behind a firewall (embedded in your router, and possible also in your computer).
+
+![Wordpress dashboard][12]
+
+Following the upgrade, the application restarts, and you're ready to begin configuring WordPress to your liking.
+
+![Wordpress configuration][13]
+
+On the far left, there is a button to **Customize Your Site**.
+
+There, you can choose the name of your site. You can accept the default theme, which is "Twenty Nineteen," or choose another. My favorite is "Twenty Ten," but browse through the themes available to find your personal favorite. WordPress comes with five free themes installed. You can download other free themes from the [WordPress][14][.org][15] site or choose to purchase a premium theme.
+
+When you click the **Customize Your Site** button, you're presented with new menu options. Select **Site Identity** and change the name of your site. You might use the name of your school or classroom. There's also room to choose a byline (the credit given to the author of a blog post). You can choose the colors for your site and where you will place menus and widgets. WordPress widgets and content and features to the sidebars for your site. Homepage settings are important, as they allow you to choose between a static page that might have a description of your school or classroom or having your blog entries displayed prominently. You can add additional CSS.
+
+![Turnkey theme][16]
+
+You can edit your front page, add additional pages like "About," or add a blog post. You can also manage widgets, manage menus, turn comments on or off, or add a link to learn more about WordPress.
+
+Customizing your site allows you to configure a number of options quickly and easily.
+
+WordPress has dozens of widgets that you can place in different areas of your page. Widgets are independent sections of content that can be placed into specific areas provided by your theme. These areas are called sidebars.
+
+### Adding content
+
+After you have WordPress configured to your liking, you probably want to get busy creating content. The best way to do that is to head back to the WordPress Dashboard.
+
+On the left side, near the top of the page, you see **Posts**. Select that link and a dropdown appears. Choose **Add New** to create your very first blog post.
+
+![Add post dropdown][17]
+
+Fill in your title in the top block and then move down to the body. It's like using a word processor. WordPress has all the tools you need to write. You can set the font size from _small_ to _huge_. You can start a paragraph with dropped capitals. The text and background color can be changed. Your posts can include quote blocks and embedded content. A wide variety of embedded content is supported so you can make your posts a dynamic multimedia experience.
+
+![Wordpress classroom blog][18]
+
+### Going online
+
+So far, your Wordpress blog only exists on your local network. Anyone using the same router as you (your housemates or classroom) can see your Wordpress site by navigating to 192.168.86.149, but once you're away from that router, the site becomes inaccessible.
+
+If you want to go online with your custom Wordpress site, you have to allow traffic through your router, and then direct that traffic to the computer running Virtualbox. If you've installed Virtualbox on a laptop, then your website would disappear any time you closed your laptop, which is why servers that never get shutdown exist. But if this is just a fun lesson on how to run a Wordpress site, then having a website that's only available during class hours is fine.
+
+If you have access to your router, then you can log into it and make the adjustments yourself. If you don't own or control your router, then you must talk to your systems administrator for access.
+
+A _router_ is the box you got from your internet service provider. You might also call it your _modem_.
+
+Every device is different, so there's no way for me to definitively tell you what you need to click on to adjust your settings. Generally, you access your home router through a web browser. Your router's address is often printed on the bottom of the router and begins with either 192.168 or 10.
+
+Navigate to the router address and log in with the credentials you were provided when you got your internet service. It's often as simple as `admin` with a numeric password (sometimes this password is printed on the router, too). If you don't know the login, call your internet provider and ask for details.
+
+Different routers use different terms for the same thing; keywords to look for are **Port forwarding**, **Virtual server**, and **Firewall**. Whatever your router calls it, you want to accept traffic coming to port 80 of your router and forward that traffic to the same port of your virtual machines's IP address (in this example, that is 192.168.86.149, but it could be different for you).
+
+![Example router setting screen][19]
+
+Now you're allowing traffic through the web port of your router's firewall. To view your Wordpress site over the Internet, get your worldwide IP address. You can get your global IP by going to the site [icanhazip.com][20]. Then go to a different computer, open a browser, and navigate to that IP address. As long as Virtualbox is running, you'll see your Wordpress site on the Internet. You can do this from anywhere in the world, because your site is on the Internet now.
+
+Most websites use a domain name so you don't have to remember global IP addresses. You can purchase a domain name from services like [webhosting.coop][21] or [gandi.net][22], or a temporary one from [freenom.com][23]. Mapping that to your Wordpress site, however, is out of scope for this article.
+
+### Wordpress for everyone
+
+[WordPress][24] is open source and is licensed under the [GNU Public License][25]. You are welcome to contribute to WordPress as either a [developer][26] or enthusiast. WordPress is committed to being inclusive and accessible as possible.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/wordpress-virtual-machine
+
+作者:[Don Watkins][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/don-watkins
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/painting_computer_screen_art_design_creative.png?itok=LVAeQx3_ (Painting art on a computer screen)
+[2]: https://wordpress.com/
+[3]: https://edublogs.org/
+[4]: https://www.virtualbox.org/
+[5]: https://www.turnkeylinux.org
+[6]: https://www.turnkeylinux.org/wordpress
+[7]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_1.png
+[8]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_2.png (Virtualbox menu)
+[9]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_3.png (Console)
+[10]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_4.png (Wordpress welcome)
+[11]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_5.png (Login screen)
+[12]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_6.png (Wordpress dashboard)
+[13]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_7.png (Wordpress configuration)
+[14]: http://Wordpress.org
+[15]: http://WordPress.org
+[16]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_8.png (Turnkey theme)
+[17]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_12.png (Add post dropdown)
+[18]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_13.png (Wordpress classroom blog)
+[19]: https://opensource.com/sites/default/files/router-web.jpg (Example router setting screen)
+[20]: http://icanhazip.com/
+[21]: https://webhosting.coop/domain-names
+[22]: https://www.gandi.net
+[23]: http://freenom.com/
+[24]: https://wordpress.org/
+[25]: https://github.com/WordPress/WordPress/blob/master/license.txt
+[26]: https://wordpress.org/five-for-the-future/
diff --git a/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md b/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md
new file mode 100644
index 0000000000..6d57fb30f8
--- /dev/null
+++ b/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md
@@ -0,0 +1,174 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Is reporting 100% of code coverage reasonable?)
+[#]: via: (https://opensource.com/article/20/4/testing-code-coverage)
+[#]: author: (Eric Herman https://opensource.com/users/ericherman)
+
+Is reporting 100% of code coverage reasonable?
+======
+The time required to reach reporting 100% of code coverage is
+considerably less than what I would have estimated before this
+exploration.
+![Code going into a computer.][1]
+
+The [Foundation for Public Code][2] works to enable open and collaborative public-purpose software for public organizations (like local governments) internationally. We do this by supporting software at the codebase level through codebase stewardship. We also publish the [Standard for Public Code][3] (draft version 0.1.4 at the time of this writing), which helps open source codebase communities build solutions that can be reused successfully by other organizations. It includes guidance for policymakers, managers, developers, designers, and vendors.
+
+Among other things, the standard addresses [code coverage][4], or how much of the code is executed when an automated test suite runs. It's one way to measure the likelihood that the code contains undetected software bugs. In the standard's ["Use continuous integration" requirements][5], it says, "source code test and documentation coverage **should** be monitored." Additionally, the [guidance to check][6] this requirement states, "code coverage tools check whether coverage is at 100% of the code."
+
+Over my software development career, which spans more than two decades, I have worked on codebases large and small and some with very high percentages of code coverage. Yet none of the non-trivial codebases I have contributed to have reported 100% test coverage. This made me question whether the "_check whether coverage is at 100%_" guidance would be followed.
+
+When I think about the nature of the test coverage gaps in the codebases I have worked on, they typically have been around system states that are very difficult (and in some cases, impossible) to create. For instance, in earlier versions of Java, I recall we were required to write catch blocks for exceptions that could never be thrown.
+
+Previously, I reasoned that 100% test coverage is something to aspire to, but it is probably not worth the cost on most codebases and may not be realistic in a few.
+
+Coverage tools have been getting smarter and more tunable over time. Languages have been getting lighter, and libraries have been getting easier to mock and test. So how unreasonable is 100% coverage of functionality today?
+
+### Resource exhaustion
+
+The high-quality but low test-coverage codebases I contribute to happen to be written in C or C++. A quick glance at these codebases shows that there is a class of common low-coverage situations that I'll lump together under the umbrella of resource exhaustion: out of memory, out of disk space, etc.
+
+Here is a simple example of code that does not check for resource exhaustion; in this case, memory allocation failure:
+
+
+```
+char *buf = malloc(80);
+sprintf(buf, "hello, world");
+```
+
+This example code needs to allocate a small buffer, so it calls **malloc(80)**, and **malloc** usually returns a pointer to 80 bytes of memory … but that can fail. In the (unlikely) case that **malloc** returns **NULL**, the code above will proceed to call **sprintf** with a **NULL** pointer which causes a crash. It is typical in C code to do something more like this:
+
+
+```
+char *buf = malloc(80);
+if (buf == NULL) {
+ fprintf(stderr, "malloc returned NULL for 80 bytes?\n");
+ return NULL;
+}
+sprintf(buf, "hello, world");
+```
+
+This code guards against **malloc** returning **NULL**, which is better. However, creating tests for correct behavior in the face of this kind of resource exhaustion can be really hard. It's not impossible, of course, and there are multiple approaches. Many approaches result in fragile tests, which require a lot of maintenance over time, and these tests can be very time-consuming to build in the first place.
+
+### Exploration
+
+Pondering this, I decided to run a little experiment to see if I could learn something about the costs and consequences of this strict, 100% criterion.
+
+Since I do some embedded-systems development, I have a few C libraries that I've developed and reused over the years in my embedded projects. I decided to look at some of these libraries and see just how hard it would be to bring them up to 100% code coverage. In the process, I paid attention to the impact on code clarity, code structure, and performance.
+
+#### A library with preexisting dependency injection
+
+Step one is measuring by adding code coverage to a codebase. Since this is C, **gcc** provides quite a lot by default with the **\--coverage** option, and **lcov** (with **genhtml**) does a good job of making reports; thus, this step was easy. I expected the starting coverage to be pretty good—it was, but it had a few untested branches, as well as the predicted gaps around error conditions and error reporting.
+
+I made error reporting pluggable, so it was easier to capture and make assertions around error messages in previously untested branches.
+
+Since this code already allowed for pluggable implementations of **malloc** and **free**, it was straightforward to write little malloc and free wrappers that I could inject memory allocation failures into. Within an hour or two, that was covered.
+
+In the process, I realized that there was one condition where, from the perspective of the calling client code, it was impossible to distinguish between the situation where an error occurs and one where **NULL** is a valid return value. For you C programmers, it was essentially similar to the following:
+
+
+```
+/* stashes a copy of the value
+ * returns the previously stashed value */
+char *foo_stash(foo_s *context,
+ char *stash_me,
+ size_t stash_me_len)
+{
+ char *copy = malloc(stash_me_len);
+ if (copy == NULL) {
+ return NULL;
+ }
+ memcpy(copy, stash_me, stash_me_len);
+ char *previous = context->stash;
+ context->stash = copy;
+ /* previous may be NULL */
+ return previous;
+}
+```
+
+I adjusted the API to allow the error information to be explicitly available. If you are a C developer, you know there are various ways this can be accomplished. I chose an approach similar to this:
+
+
+```
+/* stashes a copy of the value
+ * returns the previously stashed value
+ * on error, the 'err' pointer is set to 1 */
+char *foo_stash2(foo_s *context,
+ char *stash_me,
+ size_t stash_me_len,
+ int *err)
+{
+ char *copy = malloc(stash_me_len);
+ if (copy == NULL) {
+ *err = 1;
+ return NULL;
+ }
+ memcpy(copy, stash_me, stash_me_len);
+ char *previous = context->stash;
+ context->stash = copy;
+ /* previous may be NULL */
+ return previous;
+}
+```
+
+Without testing for resource exhaustion, it may have taken a long time for me to notice this (now obvious) shortcoming of the API.
+
+To get **lcov** to report 100% test coverage, I had to tell the compiler to [not inline any code][7], something I learned it does even at optimization level zero.
+
+When embedded in actual firmware, the compiler optimized away the unused indirection; therefore, the added indirection in the source code imposed no real-world performance penalty in the compiled firmware.
+
+Of course, this was the easy library.
+
+#### A more typical library
+
+Once I established a method of injecting memory allocation failures in tests, I decided to move onto another library, but one for which malloc and free were not already pluggable. I had questions. How invasive will this be to the codebase? Will it clutter the code, making it less clear? How time-consuming will it be?
+
+While I don't always record coverage metrics, I am a big believer in testing: more than 20 years ago, I learned that my code improves if I write the tests and client code [before][8] the implementation code, and I have worked that way ever since. (In [_Test-Driven Development: By Example_][9], you can find my name in the acknowledgments.) Yet, when I added code coverage reporting to the second library, I was surprised to see that (at some point in the past) I had added a pair of functions to the library without adding tests for them. The other untested areas were, unsurprisingly, code to handle memory-allocation failure.
+
+Writing tests for the pair of untested functions was, of course, quick and easy. The coverage tools also revealed that I had a function with an untested code branch that, given only a quick glance, contained a bug. The fix was trivial, yet I was surprised to find a bug, given the different projects where I use this library. Nonetheless, there it was, a humbling reminder that, all too often, bugs lurk in untested code.
+
+Next up was the more challenging stuff: testing for resource exhaustion. I started by introducing some global variables for the malloc/free function pointers, as well as a variable to hold a memory-tracking object. Once that was working, I moved those variables from global scope into a context argument that was already present. Refactoring the code to allow for the necessary indirection took only a couple of hours (less time than I expected), and the complexity added was negligible.
+
+### Reflections
+
+My conclusion from the first library was that it was well worth the time. The code is now more flexible, the API is now more complete for the caller, and writing the failure injection harness was pretty easy.
+
+From the second library, I was reminded that even less-pluggable code could be made testable without adding undue levels of complexity. The code improved, I fixed a bug, and I can be more confident in the code. Also, the additional modularity of being able to plug in an alternative memory allocator is a feature that may prove more valuable in the future.
+
+Exclusion comments are a feature of **lcov** to cause coverage reporting to ignore a block of code. Interestingly, I didn't feel the need to use exclusion comments in either library.
+
+I am more certain than ever that even very good code is improved by investing in test coverage.
+
+Both of these codebases are small, had some modularity already, began from a point of good testing, are single-threaded, and contain no graphical UI code. If I were to try to tackle this on one of the larger, more monolithic codebases I contribute to, it would be harder and require a larger time investment. There would likely be some sections of code where I might still conclude that the best thing to do would be to "cheat" by tuning the tooling to not report on some section of code.
+
+That said, I estimate that the time required to reach reporting 100% of code coverage is considerably less than what I would have estimated before this exploration.
+
+If you happen to be a C coder and want to see a running example of this, including **gcov** / **lcov** usage, I extracted the out-of-memory injecting code and put it in an [example repository][10].
+
+Have you pushed a codebase to 100% coverage by tests, or tried to? What was your experience? Please share it in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/testing-code-coverage
+
+作者:[Eric Herman][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/ericherman
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_development_programming.png?itok=4OM29-82 (Code going into a computer.)
+[2]: https://publiccode.net/
+[3]: https://standard.publiccode.net
+[4]: https://en.wikipedia.org/wiki/Code_coverage
+[5]: https://standard.publiccode.net/criteria/continuous-integration.html#requirements
+[6]: https://standard.publiccode.net/criteria/continuous-integration.html#how-to-test
+[7]: https://twitter.com/Eric_Herman/status/1224983465784938496
+[8]: https://opensource.com/article/20/2/automate-unit-tests
+[9]: https://www.oreilly.com/library/view/test-driven-development/0321146530/
+[10]: https://github.com/ericherman/context-alloc
diff --git a/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md b/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md
new file mode 100644
index 0000000000..98ee9b1b1e
--- /dev/null
+++ b/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md
@@ -0,0 +1,116 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (A stress-free guide to keeping WordPress sites updated)
+[#]: via: (https://opensource.com/article/20/4/updating-wordpress)
+[#]: author: (Sara Kelly https://opensource.com/users/sarapk)
+
+A stress-free guide to keeping WordPress sites updated
+======
+This practical guide to a necessary task will show you how to maximize
+site performance and avoid bugs and other issues with regular updates.
+![Working from home at a laptop][1]
+
+We all know how important it is to keep WordPress sites updated. New updates provide the latest bug and security fixes against any nasties lurking on the web. But, more critically, an outdated site can also lead to poor performance, such as slow loading speed or an outdated look and feel.
+
+Unfortunately, keeping your WordPress site up-to-date is not as easy as clicking a button. There are several components to consider, from theme to plugins to PHP. Even worse, updating too quickly can wreak another kind of havoc. Have you ever experienced the dreaded, "There has been a critical error on your website" warning after an innocent little update? I know I have, many times!
+
+Here is a practical guide on what to look out for, as well as when and what to update, to ensure your WordPress site works well.
+
+### Updating WordPress
+
+Let's start with the basics. Check your WordPress version is up-to-date by visiting Dashboard > Updates.
+
+![WordPress update screen][2]
+
+### Choosing a WordPress theme
+
+Before we deep dive into updating themes, I'd like to take a few steps back. Choose an up-to-date theme from the get-go and do your homework before installing it! There is nothing worse than pouring your heart and soul into customizing a new theme, only to discover it is buggy.
+
+Questions to ask when choosing a theme include:
+
+ * When was it first created?
+ * What is the current version available?
+ * Does the theme provider still maintain an active demo site and helpdesk?
+ * What do recent reviews say about the theme?
+
+
+
+If the theme provider is no longer maintaining the theme, save yourself the trouble and move on. Also, don't assume that just because you paid for a theme, that is necessarily maintained. I recently fell into this trap when I purchased [Pinable][3]. I loved the Pinterest look and feel. However, soon after installation, I noticed the lack of customization within the theme settings, major compatibility issues arose with my plugins, and the customer service was nonexistent. I should have known better. The theme was created in 2013 and selling for a bargain.
+
+If you already have a theme, then pay attention to how frequently updates become available. If there are never any updates, the theme provider may have closed up shop. It is only a matter of time before the impact of an outdated theme will cause problems.
+
+A quick aside while we are on the topic—up-to-date themes also give access to the two new alignment options in the WordPress block editor, which enable wide-width and full-width images. These help your blog posts look more professional. While there are a number of [tutorials][4] on the web that show you how to manually update your functions, PHP file, and CSS to enable the new alignment blocks, the code does not always work on older themes (especially masonry themes).
+
+![Wordpress theme][5]
+
+### Updating themes
+
+To check the current version of your theme, go to Appearance > Themes and click on the active theme to see the current version. If an upgrade is available, there will be an alert banner. Click on "update now" to initiate the update. You can also check for updates by going to Dashboard > Updates.
+
+![Themify screenshot][6]
+
+If you purchased a theme from a marketplace such as [Envato][7] or [Themify][8], check the theme documentation to learn what is required to initiate updates, as it will not show up automatically in the dashboard. In most cases, you will be required to download and install a specific plugin or manually upload new versions when they become available. In the latter case, you will need to delete or rename the old theme file via your cPanel before you can install the new one. A guide to installing themes via cPanel is available [here][9].
+
+If you plan to customize your theme extensively and are worried about the impact of this when upgrading, consider creating a child theme first. A child theme lets you make changes without touching the original theme's code. You can then update your site without losing any customizations you've made. Read more about child themes [here][10].
+
+As I said before, the source of most issues tends to be the theme. Learn what is required to keep your theme up to date, and do so regularly. If your theme provider is no longer creating updates, then find a new theme.
+
+### Easy does it for plugins
+
+If you manage multiple plugins, then you will be used to the frequent dashboard reminders to update! Before we get onto that, though, let's touch on some basics.
+
+As a general rule, you don't want to have too many plugins. They slow down the speed of your site by creating more code that the browser has to load. Always delete any inactive plugins. I prefer to manage plugins on the Plugins tab. Here you can see all active and inactive plugins, the current version, and whether an update is available. To update the plugin, simply click "update."
+
+![Plugin update page][11]
+
+Nonetheless, I implore you to wait a week or two before installing new updates. Updating my plugins too quickly has caused me no end of grievances. To begin with, updates are prone to human error. Don't be the guinea pig that tests out the latest version. Sometimes, the newest version of a plugin is not compatible with an older version of WordPress or your theme. Check these are up-to-date first.
+
+### Website down after updating plugins?
+
+If your site has stopped working or performance has dropped noticeably after updating your plugins, then all is not lost. Forget about those newfangled plugins that promise to test speed and identify buggy plugins (the last thing you want is more plugins)! Disable all your plugins, then activate one at a time while you test the speed and performance of your site on a website such as [Pingdom][12]. This is a great exercise to perform periodically, even if your website has not crashed. Once you identify the plugin causing the problem, delete it.
+
+In the event you cannot access WordPress because there is a critical error, then you will need to access your files via cPanel and delete all the plugin folders from there ([full instructions here][13]). Don't worry; doing this will not impact your website's content. You can then proceed to reinstall and activate the plugins one-by-one via WordPress.
+
+Cache plugins tend to be the biggest culprit in my experience. Issues with cache plugins can be minimized by clearing the cache frequently. Do not install multiple cache plugins that perform the same function, as they will only serve to slow down your site. The only way to truly get around cache plugin issues is to either not use them, use a plugin recommended by your hosting provider, or become an expert on cache. [This blog][14] on common cache issues in WordPress is a good place to start.
+
+### Back up before updating PHP
+
+If you are concerned about your website speed and have spent enough time browsing Google for answers, then you likely have seen the advice, "You gotta update your PHP!" Please tread carefully with manual PHP updates, though! If you have a good hosting provider, you should never need to do this. Rather, select the option for automatic PHP version management with your host. Newer versions of PHP may not be stable or compatible with the version of WordPress you are running. Let your hosting provider be the one to determine when updates are ready.
+
+However, if you are adamant that an old version of PHP is causing your website to be slow, take care to follow these steps before initiating an update. First, back up your site. Investing in a premium version of [Jetpack][15] is worth its weight in gold. Jetpack can perform real-time as well as daily backups, depending on your plan. Not to mention, their customer service and troubleshooting support are excellent. Secondly, inform your hosting provider that you plan to update the PHP and seek their advice first. If your host is unable to advise or wants to charge you for the privilege, you should probably think about changing hosts.
+
+You can update PHP either via cPanel or via your hosting platform under Devs > PHP Manager. After that, you are on your own, as that is where my expertise on PHP ends.
+
+If you have any other tips or pitfalls regarding updating WordPress, drop them in the comments box below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/updating-wordpress
+
+作者:[Sara Kelly][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sarapk
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
+[2]: https://opensource.com/sites/default/files/uploads/wp_update_1.png (Wordpress update screen)
+[3]: https://www.theme-junkie.com/themes/pinable/
+[4]: https://www.billerickson.net/full-and-wide-alignment-in-gutenberg/
+[5]: https://opensource.com/sites/default/files/uploads/wp_theme_2.png (Wordpress theme)
+[6]: https://opensource.com/sites/default/files/uploads/themify_3.png (Themify screenshot)
+[7]: https://elements.envato.com/
+[8]: https://themify.me/
+[9]: https://hostadvice.com/how-to/how-to-install-a-wordpress-theme-using-cpanel/
+[10]: https://developer.wordpress.org/themes/advanced-topics/child-themes/
+[11]: https://opensource.com/sites/default/files/uploads/plugins_4.png (Plugin update page)
+[12]: https://tools.pingdom.com/
+[13]: https://www.wpbeginner.com/plugins/how-to-deactivate-all-plugins-when-not-able-to-access-wp-admin/
+[14]: https://mhthemes.com/support/knb/solving-common-cache-issues-on-wordpress-websites/
+[15]: https://jetpack.com/upgrade/backup/?utm_source=google&utm_campaign=google_jetpack_search_brand_desktop_sg_en&utm_medium=paid_search&utm_term=%2Bwordpress%20%2Bjetpack%20%2Bbackup&creative=379260213317&campaignid=2061290863&utm_content=77066462603&matchtype=b&device=c&network=g&gclid=Cj0KCQjwu6fzBRC6ARIsAJUwa2RuPx5Dzr72eBEtZegsf11MmOBgLiwLX2HcEUXVaULIgv1MdZqGmeAaArmFEALw_wcB&gclsrc=aw.ds
diff --git a/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md b/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md
new file mode 100644
index 0000000000..f2fd06793f
--- /dev/null
+++ b/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md
@@ -0,0 +1,250 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting Started With Pacman Commands in Arch-based Linux Distributions)
+[#]: via: (https://itsfoss.com/pacman-command/)
+[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
+
+Getting Started With Pacman Commands in Arch-based Linux Distributions
+======
+
+_**Brief: This beginner’s guide shows you what you can do with pacmancommands in Linux, how to use them to find new packages, install and upgrade new packages, and clean your system.**_
+
+The [pacman][1] package manager is one of the main difference between [Arch Linux][2] and other major distributions like Red Hat and Ubuntu/Debian. It combines a simple binary package format with an easy-to-use [build system][3]. The aim of pacman is to easily manage packages, either from the [official repositories][4] or the user’s own builds.
+
+If you ever used Ubuntu or Debian-based distributions, you might have used the apt-get or apt commands. Pacman is the equivalent in Arch Linux. If you [just installed Arch Linux][5], one of the first few [things to do after installing Arch Linux][6] is to learn to use pacman commands.
+
+In this beginner’s guide, I’ll explain some of the essential usage of the pacmand command that you should know for managing your Arch-based system.
+
+### Essential pacman commands Arch Linux users should know
+
+![][7]
+
+Like other package managers, pacman can synchronize package lists with the software repositories to allow the user to download and install packages with a simple command by solving all required dependencies.
+
+#### Install packages with pacman
+
+You can install a single package or multiple packages using pacman command in this fashion:
+
+```
+pacman -S _package_name1_ _package_name2_ ...
+```
+
+![Installing a package][8]
+
+The -S stands for synchronization. It means that pacman first synchronizes
+
+The pacman database categorises the installed packages in two groups according to the reason why they were installed:
+
+ * **explicitly-installed**: the packages that were installed by a generic pacman -S or -U command
+ * **dependencies**: the packages that were implicitly installed because [required][9] by another package that was explicitly installed.
+
+
+
+#### Remove an installed package
+
+To remove a single package, leaving all of its dependencies installed:
+
+```
+pacman -R package_name_
+```
+
+![Removing a package][10]
+
+To remove a package and its dependencies which are not required by any other installed package:
+
+```
+pacman -Rs _package_name_
+```
+
+To remove dependencies that are no longer needed. For example, the package which needed the dependencies was removed.
+
+```
+pacman -Qdtq | pacman -Rs -
+```
+
+#### Upgrading packages
+
+Pacman provides an easy way to [update Arch Linux][11]. You can update all installed packages with just one command. This could take a while depending on how up-to-date the system is.
+
+The following command synchronizes the repository databases _and_ updates the system’s packages, excluding “local” packages that are not in the configured repositories:
+
+```
+pacman -Syu
+```
+
+ * S stands for sync
+ * y is for refresh (local
+ * u is for system update
+
+
+
+Basically it is saying that sync to central repository (master package database), refresh the local copy of the master package database and then perform the system update (by updating all packages that have a newer version available).
+
+![System update][12]
+
+Attention!
+
+If you are an Arch Linux user before upgrading, it is advised to visit the [Arch Linux home page][2] to check the latest news for out-of-the-ordinary updates. If manual intervention is needed an appropriate news post will be made. Alternatively you can subscribe to the [RSS feed][13] or the [arch-announce mailing list][14].
+
+Be also mindful to look over the appropriate [forum][15] before upgrading fundamental software (such as the kernel, xorg, systemd, or glibc), for any reported problems.
+
+**Partial upgrades are unsupported** at a rolling release distribution such as Arch and Manjaro. That means when new library versions are pushed to the repositories, all the packages in the repositories need to be rebuilt against the libraries. For example, if two packages depend on the same library, upgrading only one package, might break the other package which depends on an older version of the library.
+
+#### Use pacman to search for packages
+
+Pacman queries the local package database with the -Q flag, the sync database with the -S flag and the files database with the -F flag.
+
+Pacman can search for packages in the database, both in packages’ names and descriptions:
+
+```
+pacman -Ss _string1_ _string2_ ...
+```
+
+![Searching for a package][16]
+
+To search for already installed packages:
+
+```
+pacman -Qs _string1_ _string2_ ...
+```
+
+To search for package file names in remote packages:
+
+```
+pacman -F _string1_ _string2_ ...
+```
+
+To view the dependency tree of a package:
+
+```
+pactree _package_naenter code hereme_
+```
+
+#### Cleaning the package cache
+
+Pacman stores its downloaded packages in /var/cache/pacman/pkg/ and does not remove the old or uninstalled versions automatically. This has some advantages:
+
+ 1. It allows to [downgrade][17] a package without the need to retrieve the previous version through other sources.
+ 2. A package that has been uninstalled can easily be reinstalled directly from the cache folder.
+
+
+
+However, it is necessary to clean up the cache periodically to prevent the folder to grow in size.
+
+The [paccache(8)][18] script, provided within the [pacman-contrib][19] package, deletes all cached versions of installed and uninstalled packages, except for the most recent 3, by default:
+
+```
+paccache -r
+```
+
+![Clear cache][20]
+
+To remove all the cached packages that are not currently installed, and the unused sync database, execute:
+
+```
+pacman -Sc
+```
+
+To remove all files from the cache, use the clean switch twice, this is the most aggressive approach and will leave nothing in the cache folder:
+
+```
+pacman -Scc
+```
+
+#### Installing local or third-party packages
+
+Install a ‘local’ package that is not from a remote repository:
+
+```
+pacman -U _/path/to/package/package_name-version.pkg.tar.xz_
+```
+
+Install a ‘remote’ package, not contained in an official repository:
+
+```
+pacman -U http://www.example.com/repo/example.pkg.tar.xz
+```
+
+### Bonus: Troubleshooting common errors with pacman
+
+Here are some common errors you may encounter while managing packages with pacman.
+
+#### Failed to commit transaction (conflicting files)
+
+If you see the following error:
+
+```
+error: could not prepare transaction
+error: failed to commit transaction (conflicting files)
+package: /path/to/file exists in filesystem
+Errors occurred, no packages were upgraded.
+```
+
+This is happening because pacman has detected a file conflict and will not overwrite files for you.
+
+A safe way to solve this is to first check if another package owns the file (pacman -Qo _/path/to/file_). If the file is owned by another package, file a bug report. If the file is not owned by another package, rename the file which ‘exists in filesystem’ and re-issue the update command. If all goes well, the file may then be removed.
+
+Instead of manually renaming and later removing all the files that belong to the package in question, you may explicitly run _**pacman -S –overwrite glob package**_ to force pacman to overwrite files that match _glob_.
+
+#### Failed to commit transaction (invalid or corrupted package)
+
+Look for .part files (partially downloaded packages) in /var/cache/pacman/pkg/ and remove them. It is often caused by usage of a custom XferCommand in pacman.conf.
+
+#### Failed to init transaction (unable to lock database)
+
+When pacman is about to alter the package database, for example installing a package, it creates a lock file at /var/lib/pacman/db.lck. This prevents another instance of pacman from trying to alter the package database at the same time.
+
+If pacman is interrupted while changing the database, this stale lock file can remain. If you are certain that no instances of pacman are running then delete the lock file.
+
+Check if a process is holding the lock file:
+
+```
+lsof /var/lib/pacman/db.lck
+```
+
+If the above command doesn’t return anything, you can remove the lock file:
+
+```
+rm /var/lib/pacman/db.lck
+```
+
+If you find the PID of the process holding the lock file with lsof command output, kill it first and then remove the lock file.
+
+I hope you like my humble effort in explaining the basic pacman commands. Please leave your comments below and don’t forget to subscribe on our social media. Stay safe!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/pacman-command/
+
+作者:[Dimitrios Savvopoulos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/dimitrios/
+[b]: https://github.com/lujun9972
+[1]: https://www.archlinux.org/pacman/
+[2]: https://www.archlinux.org/
+[3]: https://wiki.archlinux.org/index.php/Arch_Build_System
+[4]: https://wiki.archlinux.org/index.php/Official_repositories
+[5]: https://itsfoss.com/install-arch-linux/
+[6]: https://itsfoss.com/things-to-do-after-installing-arch-linux/
+[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/essential-pacman-commands.jpg?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-S.png?ssl=1
+[9]: https://wiki.archlinux.org/index.php/Dependency
+[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-R.png?ssl=1
+[11]: https://itsfoss.com/update-arch-linux/
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Syu.png?ssl=1
+[13]: https://www.archlinux.org/feeds/news/
+[14]: https://mailman.archlinux.org/mailman/listinfo/arch-announce/
+[15]: https://bbs.archlinux.org/
+[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Ss.png?ssl=1
+[17]: https://wiki.archlinux.org/index.php/Downgrade
+[18]: https://jlk.fjfi.cvut.cz/arch/manpages/man/paccache.8
+[19]: https://www.archlinux.org/packages/?name=pacman-contrib
+[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-paccache-r.png?ssl=1
diff --git a/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md b/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md
new file mode 100644
index 0000000000..a8fdec6e71
--- /dev/null
+++ b/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md
@@ -0,0 +1,99 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (New open source GIS projects for Kubernetes applications)
+[#]: via: (https://opensource.com/article/20/4/gis-kubernetes)
+[#]: author: (Adam Timm https://opensource.com/users/timmam)
+
+New open source GIS projects for Kubernetes applications
+======
+pg_tileserv and pg_featureserv make it easier for developers to add
+location services to Kubernetes applications.
+![A map with a route highlighted][1]
+
+Spatial data from geographic information systems (GIS) is all around us. From smartphones that make our lives better and more convenient to precision agriculture that is increasing the amount of food farmers can produce while reducing the cost, whether or not we realize it, almost every part of our lives is touched by spatial data.
+
+This increase of spatial data is simultaneously bringing an increase of open spatial datasets that people can consume and use to build all sorts of new applications. However, these types of datasets have not always been easy to work with. Also, due to the size of some of the geographic data, they can be difficult to bring to modern application deployment frameworks such as Kubernetes.
+
+To help with these issues, [Crunchy Data][2] recently announced two new open source projects, [pg_tileserv][3] and [pg_featureserv][4], to make it easier to develop cloud-native spatial applications. These projects, part of open source [Crunchy Spatial][5], help developers leverage the robust [PostGIS][6] geospatial database extension to [PostgreSQL][7] without having to write complex SQL statements.
+
+So what are pg_tileserv and pg_featuresev, how do they make it easier for developers to add location services to their Kubernetes applications, and what does this mean for the future of spatial applications?
+
+### Traditional GIS vs. modern spatial microservices
+
+Traditionally, when an organization or individual works with spatial data, they start with a product that grew up as a GIS. There are many high-quality open source GIS products ([QGIS][8], [GeoServer][9], [GeoNode][10], etc.), but they may not align with modern, cloud-native approaches to software design.
+
+The popularity of Kubernetes creates challenges for these legacy applications around automation and deployment, as they require a lot of manual configuration, for example, when data sources are added and modified. In many setups, these spatial applications must exist outside Kubernetes and cannot leverage many of the conveniences it provides.
+
+In contrast, modern spatial services should be driven by the spatial data that they are processing and serving out. They should align with modern software development practices and scale efficiently and integrate easily with developer workflows.
+
+Applications that are spatially aware also need to ensure they can handle the unique characteristics of spatial data (e.g., geometries, projections, etc.). To do all of this in independent microservices can be challenging unless you have a highly capable database to do the majority of the work for you. This is where pg_tileserv and pg_featureserv help, as both projects leverage the power of PostGIS, an open source geospatial extension to PostgreSQL, to provide advanced spatial capabilities from a simple REST framework
+
+### Generate map vector tiles with pg_tileserv
+
+![pg_tileserv][11]
+
+pg_tileserv is a lightweight vector tile server written in Go that enables you to generate [vector tiles][12] directly from PostGIS. It does this by implementing the **ST_AsMVT()** function in a best-practice method that translates an HTTP request to the database. It includes common defaults that allow you to pass a database connection URL to the server and be up and running in no time. There's no heavyweight software to install and configure, and it's designed for cloud-native GIS applications.
+
+For specific examples on how to use it, check out our blog posts on [tile serving][13] and [spatial tile serving with PostgreSQL functions][14].
+
+### Annotate your maps with pg_featureserv
+
+![pg_featureserv][15]
+
+pg_featureserv is a lightweight service written in Go that enables you to serve features directly out of PostGIS. It implements the [OGC API][16] for features and provides a standard REST endpoint for your spatial data and functions contained in PostGIS. Just like pg_tileserv, there's no heavyweight software to install; just pass a database connection URL to your PostGIS database, and you're off to the races. For a specific example of how to use it, check out our post on [querying spatial features][17].
+
+### Focus on spatial data, not GIS
+
+With our deep background in developing PostGIS and building PostGIS-backed applications, we wanted to help developers unlock all the value of spatial data in a way that is easy to deploy, scale, and maintain. As the source code of pg_tileserv and pg_featureserv show, we are just leveraging functions already in PostGIS. This allows developers to quickly add spatial data to their applications and data scientists to focus on the data.
+
+![GIS architecture][18]
+
+The benefits of this approach are:
+
+ * Faster performance because PostgreSQL and PostGIS are doing the work for you
+ * Less configuration to maintain because the database structure is the configuration
+ * By design, it runs in the cloud at enterprise scale from the start
+ * Shorter times to update customer-facing applications—when you update your data in the database, your application is updated instantly
+ * Ability to focus more on maintaining your data and delivering value to your users and less on wrangling software
+
+
+
+Also, since these services respond to the configuration of your database, they also expose functions contained in the database. Rather than developing their data functions to incorporate them into software later, data scientists can create functions in the database that are immediately made available via a REST API. The software begins to fade into the background so an organization can focus on the data.
+
+Suffice it to say, we're pretty excited about these new geospatial services, and we definitely want your feedback on them. Feel free to check out [pg_tileserve][3] and [pg_featureserv][4], try deploying them alongside your PostGIS databases with the [PostgreSQL Operator][19], and share your feedback in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/gis-kubernetes
+
+作者:[Adam Timm][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/timmam
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/map_route_location_gps_path.png?itok=RwtS4DsU (A map with a route highlighted)
+[2]: https://www.crunchydata.com/
+[3]: https://github.com/CrunchyData/pg_tileserv
+[4]: https://github.com/CrunchyData/pg_featureserv
+[5]: https://www.crunchydata.com/products/crunchy-spatial/
+[6]: https://postgis.net/
+[7]: https://www.postgresql.org
+[8]: https://www.qgis.org/en/site/
+[9]: http://geoserver.org/
+[10]: http://geonode.org/
+[11]: https://opensource.com/sites/default/files/pg_tileserv.jpg (pg_tileserv)
+[12]: https://info.crunchydata.com/blog/dynamic-vector-tiles-from-postgis
+[13]: https://info.crunchydata.com/blog/crunchy-spatial-tile-serving
+[14]: https://info.crunchydata.com/blog/crunchy-spatial-tile-serving-with-postgresql-functions
+[15]: https://opensource.com/sites/default/files/pg_featureserv.jpg (pg_featureserv)
+[16]: http://www.ogcapi.org/
+[17]: https://info.crunchydata.com/blog/crunchy-spatial-querying-spatial-features-with-pg_featureserv
+[18]: https://opensource.com/sites/default/files/uploads/architecture_0.png (GIS architecture)
+[19]: https://github.com/CrunchyData/postgres-operator
diff --git a/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md b/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md
new file mode 100644
index 0000000000..bef4b09a9a
--- /dev/null
+++ b/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md
@@ -0,0 +1,99 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I use Hugo for my classroom's open source CMS)
+[#]: via: (https://opensource.com/article/20/4/hugo-classroom)
+[#]: author: (Peter Cheer https://opensource.com/users/petercheer)
+
+How I use Hugo for my classroom's open source CMS
+======
+This open source software streamlines text editing while leaving room
+for customization.
+![Digital hand surrounding by objects, bike, light bulb, graphs][1]
+
+People love Markdown text with good reason—it is easy to write, easy to read, easy to edit, and it can be converted to a wide range of other text mark up formats. While Markdown text is very good for content creation and manipulation, it imposes limitations on the options for content display.
+
+If we could combine the virtues of Markdown with the power and flexibility of Cascading Style Sheets, HTML5, and JavaScript, that would be something special. One of the programs trying to do this is [Hugo][2]. Hugo was created in 2013 by Steve Francia; it is cross-platform and open source under an Apache 2.0 license with an active developer community and a growing user base.
+
+The basic concept is that pieces of content, such as web pages or blog posts, written in Markdown and associated with metadata, are converted into HTML and combined with templates and themes to produce a complete web site. The power and flexibility come through these themes and templates or changing the default behaviors of Hugo. This power comes with a degree of unavoidable complexity, but there are lots of [pre-built templates][3] available if you lack the time or inclination to make your own.
+
+Installing Hugo on my Linux machine was quick and easy. Starting a new project is as simple as typing **hugo new site quickstart** at the command line which creates a new project with this folder structure:
+
+ * **archetypes**: Content template files that contain preconfigured front matter metadata (date, title, draft). You can create new archetypes with custom front matter fields.
+ * **assets**: Stores all the files, which are processed by Hugo Pipes (e.g., CSS/Sass files). This directory is not created by default.
+ * **config.toml**: The default site config file.
+ * **content**: Where all the content Markdown files live.
+ * **data**: Used to store configuration files that can be used by Hugo when generating your website.
+ * **layouts**: Stores templates as .html files.
+ * **static**: Stores all the static content—images, CSS, JavaScript, etc.
+ * **themes**: For the Hugo theme of your choice.
+
+
+
+The Markdown files in the content folder can be created manually or by Hugo and edited with any text editor or your Markdown creation tool of choice. If created manually, you will need to add any metadata that is needed. I prefer to use [Ghostwriter][4] for writing Markdown. Images are usually kept in a sub-folder in the static folder. Site development can proceed quickly, as Hugo includes a web server for testing and pre-viewing.
+
+To check your work, type **hugo server** at the command line to start the server. By default, Hugo will not publish:
+
+ * Content with a future **publishdate** value.
+ * Content with **draft: true** status.
+ * Content with a past **expirydate** value.
+
+
+
+Adding **hugo server -D** will include draft articles, and Hugo can be configured to mark all new articles as draft. After starting the web server, you can see your work in a web browser at localhost:1313. Once the server is started by default, it will automatically reload the browser window when it detects a change to one of your files.
+
+There are tasks Markdown cannot do that need some HTML code. Hugo recognizes this but believes in keeping Markdown code as clean, simple, and uncluttered as possible. Hugo does this with shortcodes such as **{{< youtube id= "w7Ft2ymGmfc" autoplay= "true">}}**, which will embed the YouTube video with id. w7Ft2ymGmfc. There are quite a few pre-built shortcodes for common tasks, but it is also possible to create your own for particular jobs.
+
+I work in education quite a lot and wanted to include some interactive puzzles and questions on my Hugo-generated website. To get the output looking like this:
+
+![JClic shortcode][5]
+
+I created the activities with an open source Java program called [JClic][6], exported them as HTML5, put that into static/activities/excel, and displayed it in an iframe.
+
+The HTML code, which would spoil the nice clean Markdown content, looks like this:
+
+
+```
+ <[iframe][7]
+ src="/activity/excel/index.html"
+ title="Activity"
+ height="400"
+ frameborder="0"
+ marginwidth="0"
+ marginheight="0"
+ scrolling="no"
+ style="border: 1px solid #CCC; border-width: 1px; margin-bottom: 20px; width: 100%;"
+ allowfullscreen="true">
+ </[iframe][7]>
+```
+
+The code is saved in layouts/shortcodes as **activity.html**
+
+This makes the shortcode placed inside my Markdown file **{{<activity>}}**, which is much neater.
+
+When your project is ready, you can build it with the **hugo** command; this will create a public folder and generate the website in it. Hugo has a number of built-in deployment options for different hosting providers—basically, you deploy your site by copying the public folder to your production web server. There is a lot more to Hugo that I haven't even gotten to yet, including configuration options, importing content from other static site generators and Wordpress, display data from JSON files, syntax highlighting of source code, and the fact that it is very fast (an advantage when working with large sites).
+
+In many software tools, ease-of-use comes at the expense of flexibility, or vice-versa; Hugo makes a largely successful attempt at including both. For basic use with Markdown content and a pre-built theme, Hugo is easy to use and produces rapid results. Alternatively, if you have the need to alter the configuration settings or dive in and create your own themes, shortcodes, templates, or metadata schemes, that choice is open to you.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/hugo-classroom
+
+作者:[Peter Cheer][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petercheer
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
+[2]: https://gohugo.io/
+[3]: https://themes.gohugo.io/
+[4]: http://github.com/wereturtle/ghostwriter
+[5]: https://opensource.com/sites/default/files/uploads/jclic_shortcode.png (JClic shortcode)
+[6]: https://clic.xtec.cat/legacy/en/index.html
+[7]: http://december.com/html/4/element/iframe.html
diff --git a/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md b/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md
new file mode 100644
index 0000000000..2f5f8dbef0
--- /dev/null
+++ b/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md
@@ -0,0 +1,170 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I use Python to map the global spread of COVID-19)
+[#]: via: (https://opensource.com/article/20/4/python-map-covid-19)
+[#]: author: (AnuragGupta https://opensource.com/users/999anuraggupta)
+
+How I use Python to map the global spread of COVID-19
+======
+Create a color coded geographic map of the potential spread of the virus
+using these open source scripts.
+![Globe up in the clouds][1]
+
+The spread of disease is a real concern for a world in which global travel is commonplace. A few organizations track significant epidemics (and any pandemic), and fortunately, they publish their work as open data. The raw data can be difficult for humans to process, though, and that's why data science is so vital. For instance, it could be useful to visualize the worldwide spread of COVID-19 with Python and Pandas.
+
+It can be hard to know where to start when you're faced with large amounts of raw data. The more you do it, however, the more patterns begin to emerge. Here's a common scenario, applied to COVID-19 data:
+
+ 1. Download COVID-19 country spread daily data into a Pandas DataFrame object from GitHub. For this, you need the Python Pandas library.
+ 2. Process and clean the downloaded data and make it suitable for visualizing. The downloaded data (as you will see for yourself) is in quite good condition. The one problem with this data is that it uses the names of countries, but it's better to use three-digit ISO 3 codes. To generate the three-digit ISO 3 codes, use a small Python library called pycountry. Having generated these codes, you can add an extra column to our DataFrame and populate it with these codes.
+ 3. Finally, for the visualization, use the **express** module of a library called Plotly. This article uses what are called choropleth maps (available in Plotly) to visualize the worldwide spread of the disease.
+
+
+
+### Step 1: Corona data
+
+We will download the latest corona data from:
+
+
+
+We will load the data directly into a Pandas DataFrame. Pandas provides a function, **read_csv()**, which can take a URL and return a DataFrame object as shown below:
+
+
+```
+import pycountry
+import plotly.express as px
+import pandas as pd
+URL_DATASET = r''
+df1 = pd.read_csv(URL_DATASET)
+print(df1.head(3)) # Get first 3 entries in the dataframe
+print(df1.tail(3)) # Get last 3 entries in the dataframe
+```
+
+The screenshot of output (on Jupyter) is:
+
+![Jupyter screenshot][2]
+
+From output, you can see that the DataFrame (df1) has the following columns:
+
+ 1. Date
+ 2. Country
+ 3. Confirmed
+ 4. Recovered
+ 5. Dead
+
+
+
+Further, you can see that the **Date** column has entries starting from January 22 to March 31. This database is updated daily, so you will get the current values.
+
+### Step 2: Cleaning and modifying the data frame
+
+We need to add another column to this DataFrame, which has the three-letter ISO alpha-3 codes. To do this, I followed these steps:
+
+ 1. Create a list of all countries in the database. This was required because in the **df**, in the column **Country**, each country was figuring for each date. So in effect, the **Country** column had multiple entries for each country. To do this, I used the **unique().tolist()** functions.
+ 2. Then I took a dictionary **d_country_code** (initially empty) and populated it with keys consisting of country names and values consisting of their three-letter ISO codes.
+ 3. To generate the three-letter ISO code for a country, I used the function **pycountry.countries.search_fuzzy(country)**. You need to understand that the return value of this function is a "list of **Country** objects." I passed the return value of this function to a name country_data. Further, in this list of objects, the first object i.e., at index 0, is the best fit. Further, this **\** object has an attribute **alpha_3**. So, I can "access" the 3 letter ISO code by using **country_data[0].alpha_3**. However, it is possible that some country names in the DataFrame may not have a corresponding ISO code (For example, disputed territories). So, for such countries, I gave an ISO code of "i.e. a blank string. Further, you need to wrap this code in a try-except block. The statement: **print(_‘could not add ISO 3 code for ->'_, country)** will give a printout of those countries for which the ISO 3 codes could not be found. In fact, you will find such countries as shown with white color in the final output.
+ 4. Having got the three-letter ISO code for each country (or an empty string for some), I added the country name (as key) and its corresponding ISO code (as value) to the dictionary **d_country_code**. For adding these, I used the **update()** method of the Python dictionary object.
+ 5. Having created a dictionary of country names and their codes, I added them to the DataFrame using a simple for loop.
+
+
+
+### Step 3: Visualizing the spread using Plotly
+
+A choropleth map is a map composed of colored polygons. It is used to represent spatial variations of a quantity. We will use the express module of Plotly conventionally called **px**. Here we show you how to create a choropleth map using the function: **px.choropleth**.
+
+The signature of this function is:
+
+
+```
+`plotly.express.choropleth(data_frame=None, lat=None, lon=None, locations=None, locationmode=None, geojson=None, featureidkey=None, color=None, hover_name=None, hover_data=None, custom_data=None, animation_frame=None, animation_group=None, category_orders={}, labels={}, color_discrete_sequence=None, color_discrete_map={}, color_continuous_scale=None, range_color=None, color_continuous_midpoint=None, projection=None, scope=None, center=None, title=None, template=None, width=None, height=None)`
+```
+
+The noteworthy points are that the **choropleth()** function needs the following things:
+
+ 1. A geometry in the form of a **geojson** object. This is where things are a bit confusing and not clearly mentioned in its documentation. You may or may not provide a **geojson** object. If you provide a **geojson** object, then that object will be used to plot the earth features, but if you don't provide a **geojson** object, then the function will, by default, use one of the built-in geometries. (In our example here, we will use a built-in geometry, so we won't provide any value for the **geojson** argument)
+ 2. A pandas DataFrame object for the attribute **data_frame**. Here we provide our DataFrame ie **df1** we created earlier.
+ 3. We will use the data of **Confirmed** column to decide the color of each country polygon.
+ 4. Further, we will use the **Date** column to create the **animation_frame**. Thus as we slide across the dates, the colors of the countries will change as per the values in the **Confirmed** column.
+
+
+
+The complete code is given below:
+
+
+```
+import pycountry
+import plotly.express as px
+import pandas as pd
+# ----------- Step 1 ------------
+URL_DATASET = r''
+df1 = pd.read_csv(URL_DATASET)
+# print(df1.head) # Uncomment to see what the dataframe is like
+# ----------- Step 2 ------------
+list_countries = df1['Country'].unique().tolist()
+# print(list_countries) # Uncomment to see list of countries
+d_country_code = {} # To hold the country names and their ISO
+for country in list_countries:
+ try:
+ country_data = pycountry.countries.search_fuzzy(country)
+ # country_data is a list of objects of class pycountry.db.Country
+ # The first item ie at index 0 of list is best fit
+ # object of class Country have an alpha_3 attribute
+ country_code = country_data[0].alpha_3
+ d_country_code.update({country: country_code})
+ except:
+ print('could not add ISO 3 code for ->', country)
+ # If could not find country, make ISO code ' '
+ d_country_code.update({country: ' '})
+
+# print(d_country_code) # Uncomment to check dictionary
+
+# create a new column iso_alpha in the df
+# and fill it with appropriate iso 3 code
+for k, v in d_country_code.items():
+ df1.loc[(df1.Country == k), 'iso_alpha'] = v
+
+# print(df1.head) # Uncomment to confirm that ISO codes added
+# ----------- Step 3 ------------
+fig = px.choropleth(data_frame = df1,
+ locations= "iso_alpha",
+ color= "Confirmed", # value in column 'Confirmed' determines color
+ hover_name= "Country",
+ color_continuous_scale= 'RdYlGn', # color scale red, yellow green
+ animation_frame= "Date")
+
+fig.show()
+```
+
+The output is something like the following:
+
+![Map][3]
+
+You can download and run the [complete code][4].
+
+To wrap up, here are some excellent resources on choropleth in Plotly:
+
+ *
+ * [https://plotly.com/python/reference/#choropleth][5]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/python-map-covid-19
+
+作者:[AnuragGupta][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/999anuraggupta
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cloud-globe.png?itok=_drXt4Tn (Globe up in the clouds)
+[2]: https://opensource.com/sites/default/files/uploads/jupyter_screenshot.png (Jupyter screenshot)
+[3]: https://opensource.com/sites/default/files/uploads/map_2.png (Map)
+[4]: https://github.com/ag999git/jupyter_notebooks/blob/master/corona_spread_visualization
+[5]: tmp.azs72dmHFd#choropleth
diff --git a/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md b/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md
new file mode 100644
index 0000000000..249d9d84f5
--- /dev/null
+++ b/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md
@@ -0,0 +1,273 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to take advantage of Linux's extensive vocabulary)
+[#]: via: (https://www.networkworld.com/article/3539011/how-to-takke-advantage-of-linuxs-extensive-vocabulary.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+How to take advantage of Linux's extensive vocabulary
+======
+Linux systems don't only know a lot of words, it has commands that can help you use them by finding words that are on the tip of your tongue or fixing your typos.
+Sandra Henry-Stocker
+
+While you might not think of Linux as a writing tutor, it does have some commendable language skills – at least when it comes to English. While the average American probably has a vocabulary between 20,000 and 50,000 words, Linux can claim over 100,000 words (spellings, not definitions). And you can easily put this vocabulary to work for you in a number of ways. Let’s look at how Linux can help with your word challenges.
+
+### Help with finding words
+
+First, let’s focus on finding words.If you use the **wc** command to count the number of words in the **/usr/share/dict/words** file on your system, you should see something like this:
+
+```
+$ wc -l /usr/share/dict/words
+102402 /usr/share/dict/words
+```
+
+As you can see, the **words** file on this system contains 102,402 words. So, when you’re trying to nail down just the right word and are having trouble, you stand a good chance of finding it on your system by remembering (or guessing at) some part of it. But you'll need a little help narrowing down those 102,402 words to a group worth your time to review. In this command, we’re looking for words that start with the letters “revi”.
+
+[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
+
+```
+$ grep ^reviv /usr/share/dict/words
+revival
+revival's
+revivalist
+revivalist's
+revivalists
+revivals
+revive
+revived
+revives
+revivification
+revivification's
+revivified
+revivifies
+revivify
+revivifying
+reviving
+```
+
+That’s sixteen words that start with the string “revi”. The **^** character represents the beginning of the word and, as you might have suspected, each word in the file is on a line by itself.
+
+A good number of the words in the **/usr/share/dict/words** file are names. If you want to find words regardless of whether they're capitalized, add the **-i** (ignore case) option to your **grep** command.
+
+```
+$ grep -i ^wool /usr/share/dict/words
+Woolf
+Woolf's
+Woolite
+Woolite's
+Woolongong
+Woolongong's
+Woolworth
+Woolworth's
+wool
+...
+```
+
+You can also look for words that end in or contain a certain string of letters. In this next command, we look for words that contain the string “nativ” at any location.
+
+```
+$ grep 'nativ' /usr/share/dict/words
+alternative
+alternative's
+alternatively
+alternatives
+imaginative
+imaginatively
+native
+native's
+natives
+nativities
+nativity
+nativity's
+nominative
+nominative's
+nominatives
+unimaginative
+```
+
+In this next command, we look for words that end in “emblance”, the **$** character representing the end of the line. Only two words in the **words** file fit the bill.
+
+[][2]
+
+```
+$ grep 'emblance$' /usr/share/dict/words
+resemblance
+semblance
+```
+
+If we, for some reason, want to find words with exactly 21 letters, we could use this command:
+
+```
+$ grep '^.....................$' /usr/share/dict/words
+counterintelligence's
+electroencephalograms
+electroencephalograph
+```
+
+On the other hand, making sure we've typed the correct number of dots can be tedious. This next command is little easier to manage:
+
+```
+$ grep -E '^[[:alpha:]]{21}$' /usr/share/dict/words
+electroencephalograms
+electroencephalograph
+```
+
+This command does the same thing:
+
+```
+$ grep -E '^\w{21}$' /usr/share/dict/words
+electroencephalograms
+electroencephalograph
+```
+
+The one important difference between these commands is that the one with the dots matches any string of 21 characters. The two specifying "alpha" or "\w" only match letters, so they find only two matching words.
+
+Now let’s look for words that contain 20 letters (or more) in a row.
+
+```
+$ grep -E '(\w{20})' /usr/share/dict/words
+Andrianampoinimerina
+Andrianampoinimerina's
+counterrevolutionaries
+counterrevolutionary
+counterrevolutionary's
+electroencephalogram
+electroencephalogram's
+electroencephalograms
+electroencephalograph
+electroencephalograph's
+electroencephalographs
+uncharacteristically
+```
+
+That command returns words with apostrophes because they contain 20 letters in a row before they get to that point.
+
+Next, we’ll check out words with 21 or more characters. The 1 and 20 in combination with the **v** (invert) option in this command cause **grep** to skip over words with anywhere from 1 to 20 characters.
+
+```
+$ grep -vwE '\w{1,20}' /usr/share/dict/words
+counterrevolutionaries
+electroencephalograms
+electroencephalograph
+electroencephalographs
+```
+
+In this next command, we look for words that start with “ex” and have four additional letters.
+
+```
+$ grep '^ex.\{4\}$' /usr/share/dict/words
+exacts
+exalts
+exam's
+exceed
+excels
+except
+excess
+excise
+excite
+excuse
+…
+```
+
+In case you're curious, the **words** file on this system contains 43 such words:
+
+```
+$ grep '^ex.\{4\}$' /usr/share/dict/words | wc -l
+43
+```
+
+To get help with spelling, you should try **aspell**. It can help you with individual words or run a spell check scan through an entire text file. In this first example, we ask **aspell** to help with a single word. It finds the word we’re after along with a couple other possibilities.
+
+### Checking a word
+
+```
+$ aspell -a
+@(#) International Ispell Version 3.1.20 (but really Aspell 0.60.7)
+prolifferate <== entered word
+& prolifferate 3 0: proliferate, proliferated, proliferates <== replacement options
+```
+
+If **aspell** doesn’t provide a list of words, that means that the spelling you offered was correct. Here's an example:
+
+```
+$ aspell -a
+@(#) International Ispell Version 3.1.20 (but really Aspell 0.60.7)
+proliferate <== entered text
+* <== no suggestions
+```
+
+Typing **^C** (control-c) exits **aspell**.
+
+### Checking a file
+
+When checking a file with **aspell**, you get suggestions for each misspelled word. When **aspell** spots typos, it highlights the misspelled words one at a time and gives you a chance to choose from a list of properly spelled words that are similar enough to the misspelled words to be good candidates for replacing them.
+
+To start checking a file, type **aspell -c** followed by the file name.
+
+```
+$ aspell -c thesis
+```
+
+You'll see something like this:
+
+```
+This thesis focusses on …
+
+1) focuses 6) Fosse's
+2) focused 7) flosses
+3) cusses 8) courses
+4) fusses 9) focus
+5) focus's 0) fuses
+i) Ignore I) Ignore all
+r) Replace R) Replace all
+a) Add l) Add Lower
+b) Abort x) Exit
+```
+
+Make your selection by pressing the key listed next to the word you want (1, 2, etc.) and **aspell** will replace the misspelled word in the file and move on to the next one if there are others. Notice that you also have options to replace the word by typing another one. Press "x" when you're done.
+
+### Help with crossword puzzles
+
+If you’re working on a crossword puzzle and need to find a five-letter word that starts with a “d” and has a “u” as its fourth letter, you can use a command like this:
+
+```
+$ grep -i '^d..u.$' /usr/share/dict/words
+datum
+debug
+debut
+demur
+donut
+```
+
+### Help with word scrambles
+
+If you’re working on a puzzle that requires you to de-scramble the letters in a string until you've found a proper word, you can offer the list of letters to grep like this example in which **grep** turns the letters "yxusonlia" into the word “anxiously”.
+
+```
+$ grep -P '^(?:([yxusonlia])(?!.*?\1)){9}$' /usr/share/dict/words
+anxiously
+```
+
+Linux’s word skills are impressive and sometimes even fun. Whether you're hoping to find words you can't quite call to mind or get a little help cheating on word puzzles, Linux offers some clever options.
+
+Join the Network World communities on [Facebook][3] and [LinkedIn][4] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3539011/how-to-takke-advantage-of-linuxs-extensive-vocabulary.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.networkworld.com/newsletters/signup.html
+[2]: https://www.networkworld.com/blog/itaas-and-the-corporate-storage-technology/?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE22140&utm_content=sidebar (ITAAS and Corporate Storage Strategy)
+[3]: https://www.facebook.com/NetworkWorld/
+[4]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200423 4 open source chat applications you should use right now.md b/sources/tech/20200423 4 open source chat applications you should use right now.md
new file mode 100644
index 0000000000..25aa100c53
--- /dev/null
+++ b/sources/tech/20200423 4 open source chat applications you should use right now.md
@@ -0,0 +1,139 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (4 open source chat applications you should use right now)
+[#]: via: (https://opensource.com/article/20/4/open-source-chat)
+[#]: author: (Sudeshna Sur https://opensource.com/users/sudeshna-sur)
+
+4 open source chat applications you should use right now
+======
+Collaborating remotely is an essential capability now, making open
+source real-time chat an essential piece of your toolbox.
+![Chat bubbles][1]
+
+The first thing we usually do after waking up in the morning is to check our cellphone to see if there are important messages from our colleagues and friends. Whether or not it's a good idea, this behavior has become part of our daily lifestyle.
+
+> _"Man is a rational animal. He can think up a reason for anything he wants to believe."_
+> _– Anatole France_
+
+No matter the soundness of the reason, we all have a suite of communication tools—email, phone calls, web-conferencing tools, or social networking—we use on a daily basis. Even before COVID-19, working from home already made these communication tools an essential part of our world. And as the pandemic has made working from home the new normal, we're facing unprecedented changes to how we communicate, which makes these tools not merely essential but now required.
+
+### Why chat?
+
+When working remotely as a part of a globally distributed team, we must have a collaborative environment. Chat applications play a vital role in helping us stay connected. In contrast to email, chat applications provide fast, real-time communications with colleagues around the globe.
+
+There are a lot of factors involved in choosing a chat application. To help you pick the right one for you, in this article, I'll explore four open source chat applications and one open source video-communication tool (for when you need to be "face-to-face" with your colleagues), then outline some of the features you should look for in an effective communication application.
+
+### 4 open source chat apps
+
+#### Rocket.Chat
+
+![Rocket.Chat][2]
+
+[Rocket.Chat][3] is a comprehensive communication platform that classifies channels as public (open to anyone who joins) or private (invitation-only) rooms. You can also send direct messages to people who are logged in; share documents, links, photos, videos, and GIFs; make video calls; and send audio messages without leaving the platform.
+
+Rocket.Chat is free and open source, but what makes it unique is its self-hosted chat system. You can download it onto your server, whether it's an on-premises server or a virtual private server on a public cloud.
+
+Rocket.Chat is completely free, and its [source code][4] is available on GitHub. Many open source projects use Rocket.Chat as their official communication platform. It is constantly evolving with new features and improvements.
+
+The things I like the most about Rocket.Chat are its ability to be customized according to user requirements and that it uses machine learning to do automatic, real-time message translation between users. You can also download Rocket.Chat for your mobile device and use it on the go.
+
+#### IRC
+
+![IRC on WeeChat 0.3.5][5]
+
+[Internet Relay Chat (IRC)][6] is a real-time, text-based form of communication. Although it's one of the oldest forms of electronic communication, it remains popular among many well-known software projects.
+
+IRC channels are discrete chat rooms. It allows you to have conversations with multiple people in an open channel or chat with someone privately one-on-one. If a channel name starts with a #, you can assume it to be official, whereas chat rooms that begin with ## are unofficial and usually casual.
+
+[Getting started with IRC][7] is easy. Your IRC handle or nickname is what allows people to find you, so it must be unique. But your choice of IRC client is completely your decision. If you want a more feature-rich application than a standard IRC client, you can connect to IRC with [Riot.im][8].
+
+Given its age, why should you still be on IRC? For one reason, it remains the home for many of the free and open source projects we depend on. If you want to participate in open source software and communities, IRC is the option to get started.
+
+#### Zulip
+
+![Zulip][9]
+
+[Zulip][10] is a popular group-chat application that follows the topic-based threading model. In Zulip, you subscribe to streams, just like in IRC channels or Rocket.Chat. But each Zulip stream opens a topic that is unique, which helps you track conversations later, thus making it more organized.
+
+Like other platforms, it supports emojis, inline images, video, and tweet previews. It also supports LaTeX for sharing math formulas or equations and Markdown and syntax highlighting for sharing code.
+
+Zulip is cross-platform and offers APIs for building your own integrations. Something I especially like about Zulip is its integration feature with GitHub: if I'm working on an issue, I can use Zulip's marker to link back to the pull request ID.
+
+Zulip is open source (you can access its [source code][11] on GitHub) and free to use, but it has paid offerings for on-premises support, [LDAP][12] integration, and more storage.
+
+#### Let's Chat
+
+![Let's Chat][13]
+
+[Let's Chat][14] is a self-hosted chat solution for small teams. It runs on Node.js and MongoDB and can be deployed to local servers or hosted services with a few clicks. It's free and open source, with the [source code][15] available on GitHub.
+
+What differentiates Let's Chat from other open source chat tools is its enterprise features: it supports LDAP and [Kerberos][16] authentication. It also has all the features a new user would want: you can search message history in the archives and tag people with mentions like @username.
+
+What I like about Let's Chat is that it has private and password-protected rooms, image embeds, GIPHY support, and code pasting. It is constantly evolving and adding more features to its bucket.
+
+### Bonus: Open source video chat with Jitsi
+
+![Jitsi][17]
+
+Sometimes text chat isn't enough, and you need to talk to someone face-to-face. In times like these, when in-person meetings aren't an option, video chat is the best alternative. [Jitsi][18] is a complete, open source, multi-platform, and WebRTC-compliant videoconferencing tool.
+
+Jitsi began with Jitsi Desktop and has evolved into multiple [projects][19], including Jitsi Meet, Jitsi Videobridge, jibri, and libjitsi, with [source code][20] published for each on GitHub.
+
+Jitsi is secure and scalable and supports advanced video-routing concepts such as simulcast and bandwidth estimation, as well as typical capabilities like audio, recording, screen-sharing, and dial-in features. You can set a password to secure your video-chat room and protect it against intruders, and it also supports live-streaming over YouTube. You can also build your own Jitsi server and host it on-premises or on a virtual private server, such as a Digital Ocean Droplet.
+
+What I like most about Jitsi is that it is free and frictionless; anyone can start a meeting in no time by visiting [meet.jit.si][21], and users are good to go with no need for registration or installation. (However, registration gives you calendar integrations.) This low-barrier-to-entry alternative to popular videoconferencing services is helping Jitsi's popularity spread rapidly.
+
+### Tips for choosing a chat application
+
+The variety of open source chat applications can make it hard to pick one. The following are some general guidelines for choosing a chat app.
+
+ * Tools that have an interactive interface and simple navigation are ideal.
+ * It's better to look for a tool that has great features and allows people to use it in various ways.
+ * Integrations with tools you use can play an important role in your decision. Some tools have great and seamless integrations with GitHub, GitLab, and certain applications, which is a useful feature.
+ * It's convenient to use tools that have a pathway to hosting on cloud-based services.
+ * The security of the chat service should be taken into account. The ability to host services on a private server is necessary for many organizations and individuals.
+ * It's best to select communication tools that have rich privacy settings and allow for both private and public chat rooms.
+
+
+
+Since people are more dependent than ever on online services, it is smart to have a backup communication platform available. For example, if a project is using Rocket.Chat, it should also have the option to hop into IRC, if necessary. Since these services are continuously updating, you may find yourself connected to multiple channels, and this is where integration becomes so valuable.
+
+Of the different open source chat services available, which ones do you like and use? How do these tools help you work remotely? Please share your thoughts in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-chat
+
+作者:[Sudeshna Sur][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sudeshna-sur
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/talk_chat_communication_team.png?itok=CYfZ_gE7 (Chat bubbles)
+[2]: https://opensource.com/sites/default/files/uploads/rocketchat.png (Rocket.Chat)
+[3]: https://rocket.chat/
+[4]: https://github.com/RocketChat/Rocket.Chat
+[5]: https://opensource.com/sites/default/files/uploads/irc.png (IRC on WeeChat 0.3.5)
+[6]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
+[7]: https://opensource.com/article/16/6/getting-started-irc
+[8]: https://opensource.com/article/17/5/introducing-riot-IRC
+[9]: https://opensource.com/sites/default/files/uploads/zulip.png (Zulip)
+[10]: https://zulipchat.com/
+[11]: https://github.com/zulip/zulip
+[12]: https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol
+[13]: https://opensource.com/sites/default/files/uploads/lets-chat.png (Let's Chat)
+[14]: https://sdelements.github.io/lets-chat/
+[15]: https://github.com/sdelements/lets-chat
+[16]: https://en.wikipedia.org/wiki/Kerberos_(protocol)
+[17]: https://opensource.com/sites/default/files/uploads/jitsi_0_0.jpg (Jitsi)
+[18]: https://jitsi.org/
+[19]: https://jitsi.org/projects/
+[20]: https://github.com/jitsi
+[21]: http://meet.jit.si
diff --git a/sources/tech/20200426 6 tips for securing your WordPress website.md b/sources/tech/20200426 6 tips for securing your WordPress website.md
new file mode 100644
index 0000000000..757ff42d30
--- /dev/null
+++ b/sources/tech/20200426 6 tips for securing your WordPress website.md
@@ -0,0 +1,175 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (6 tips for securing your WordPress website)
+[#]: via: (https://opensource.com/article/20/4/wordpress-security)
+[#]: author: (Lucy Carney https://opensource.com/users/lucy-carney)
+
+6 tips for securing your WordPress website
+======
+Even beginners can—and should—take these steps to protect their
+WordPress sites against cyberattacks.
+![A lock on the side of a building][1]
+
+Already powering over 30% of the internet, WordPress is the fastest-growing content management system (CMS) in the world—and it's not hard to see why. With tons of customization available through coding and plugins, top-notch SEO, and a supreme reputation for blogging, WordPress has certainly earned its popularity.
+
+However, with popularity comes other, less appealing attention. WordPress is a common target for intruders, malware, and cyberattacks—in fact, WordPress accounted for around [90% of hacked CMS platforms][2] in 2019.
+
+Whether you're a first-time WordPress user or an experienced developer, there are important steps you can take to protect your WordPress website. The following six key tips will get you started.
+
+### 1\. Choose reliable hosting
+
+Hosting is the unseen foundation of all websites—without it, you can't publish your site online. But hosting does much more than simply host your site. It's also responsible for site speed, performance, and security.
+
+The first thing to do is to check if a host includes SSL security in its plans.
+
+SSL is an essential security feature for all websites, whether you're running a small blog or a large online store. You'll need a more [advanced SSL certificate][3] if you're accepting payments, but for most sites, the basic free SSL should be fine.
+
+Other security features to look out for include:
+
+ * Frequent, automatic offsite backups
+ * Malware and antivirus scanning and removal
+ * Distributed denial of service (DDoS) protection
+ * Real-time network monitoring
+ * Advanced firewall protection
+
+
+
+In addition to these digital security features, it's worth thinking about your hosting provider's _physical_ security measures as well. These include limiting access to data centers with security guards, CCTV, and two-factor or biometric authentication.
+
+### 2\. Use security plugins
+
+One of the best—and easiest—ways of protecting your website's security is to install a security plugin, such as [Sucuri][4], which is an open source, GPLv2 licensed project. Security plugins are vitally important because they automate security, which means you can focus on running your site rather than committing all your time to fighting off online threats.
+
+These plugins detect and block malicious attacks and alert you about any issues that require your attention. In short, they constantly work in the background to protect your site, meaning you don't have to stay awake 24/7 to fight off hackers, bugs, and other digital nasties.
+
+A good security plugin will provide all the essential security features you need for free, but some advanced features require a paid subscription. For example, you'll need to pay if you want to unlock [Sucuri's website firewall][5]. Enabling a web application firewall (WAF) blocks common threats and adds an extra layer of security to your site, so it's a good idea to look for this feature when choosing a security plugin.
+
+### 3\. Choose trustworthy plugins and themes
+
+The joy of WordPress is that it is open source, so anyone and everyone can pitch in with themes and plugins that they've developed. This can also pose problems when it comes to picking a high-quality theme or plugin.
+
+It serves to be cautious when picking a free theme or plugin, as some are poorly designed—or worse, may hide malicious code.
+
+To avoid this, always source free themes and plugins from reputable sources, such as the WordPress library. Always read reviews and research the developer to see if they've built any other programs.
+
+Outdated or poorly designed themes and plugins can leave "backdoors" open for attackers or bugs to get into your site, which is why it pays to be careful in your choices. However, you should also be wary of nulled or cracked themes. These are premium themes that have been compromised by hackers and are for sale illegally. You might buy a nulled theme believing that it's all above-board—only to have your site damaged by hidden malicious code.
+
+To avoid nulled themes, don't get drawn in by discounted prices, and always stick to reputable stores, such as the official [WordPress directory][6]. If you're looking elsewhere, stick to large and trusted stores, such as [Themify][7], a theme and plugin store that has been running since 2010. Themify ensures all its WordPress themes pass the [Google Mobile-Friendly][8] test and are open source under the [GNU General Public License][9].
+
+### 4\. Run regular updates
+
+It's a fundamental WordPress rule: _always keep your site up to date._ However, it's a rule not everyone sticks to—in fact, only [43% of WordPress sites][10] are running the latest version.
+
+The problem is that when your site becomes outdated, it becomes susceptible to glitches, bugs, intrusions, and crashes because it falls behind on security and performance fixes. Outdated sites can't fix bugs the same way as updated sites can, and attackers can tell which sites are outdated. This means they can search for the most vulnerable sites and attack accordingly.
+
+This is why you should always run your site on the latest version of WordPress. And in order to keep your security at its strongest, you must update your plugins and themes as well as your core WordPress software.
+
+If you choose a managed WordPress hosting plan, you might find that your provider will check and run updates for you—be clear whether your host offers software _and_ plugin updates. If not, you can install an open source plugin manager, such as the GPLv2-licensed [Easy Updates Manager plugin][11], as an alternative.
+
+### 5\. Strengthen your logins
+
+Aside from creating a secure WordPress website through carefully choosing your theme and installing security plugins, you also need to safeguard against unauthorized access through logins.
+
+#### Password protection
+
+The first and simplest way to strengthen your login security is to change your password—especially if you're using an [easily guessed phrase][12] such as "123456" or "qwerty."
+
+Instead, try to use a long passphrase rather than a password, as they are harder to crack. The best way is to use a series of unrelated words strung together that you find easy to remember.
+
+Here are some other tips:
+
+ * Never reuse passwords
+ * Don't include obvious words such as family members' names or your favorite football team
+ * Never share your login details with anyone
+ * Include capitals and numbers to add complexity to your passphrase
+ * Don't write down or store your login details anywhere
+ * Use a [password manager][13]
+
+
+
+#### Change your login URL
+
+It's a good idea to change your default login web address from the standard format: yourdomain.com/wp-admin. This is because hackers know this is the default URL, so you risk brute-force attacks by not changing it.
+
+To avoid this, change the URL to something different. Use an open source plugin such as the GPLv2-licensed [WPS Hide Login][14] for safe, quick, and easy customization.
+
+#### Apply two-factor authentication
+
+For extra protection against unauthorized logins and brute-force attacks, you should add two-factor authentication. This means that even if someone _does_ get access to your login details, they'll need a code that's sent directly to your phone to gain access to your WordPress site's admin.
+
+Adding two-factor authentication is pretty easy. Simply install yet another plugin—this time, search the WordPress Plugin Directory for "two-factor authentication," and select the plugin you want. One option is [Two Factor][15], a popular GPLv2 licensed project that has over 10,000 active installations.
+
+#### Limit login attempts
+
+WordPress tries to be helpful by letting you guess your login details as many times as you like. However, this is also helpful to hackers trying to gain unauthorized access to your WordPress site to release malicious code.
+
+To combat brute-force attacks, install a plugin that limits login attempts and set how many guesses you want to allow.
+
+### 6\. Disable file editing
+
+This isn't such a beginner-friendly step, so don't attempt it unless you're a confident coder—and always back up your site first!
+
+That said, disabling file editing _is_ an important measure if you're really serious about protecting your WordPress website. If you don't hide your files, it means anyone can edit your theme and plugin code straight from the admin area—which is dangerous if an intruder gets in.
+
+To deny unauthorized access, go to your **wp-config.php** file and enter:
+
+
+```
+<Files wp-config.php>
+order allow,deny
+deny from all
+</Files>
+```
+
+Or, to remove the theme and plugin editing options from your WordPress admin area completely, edit your **wp-config.php** file by adding:
+
+
+```
+`define( 'DISALLOW_FILE_EDIT', true );`
+```
+
+Once you've saved and reloaded the file, the plugin and theme editors will disappear from your menus within the WordPress admin area, stopping anyone from editing your theme or plugin code—including you**.** Should you need to restore access to your theme and plugin code, just delete the code you added to your **wp-config.php** file when you disabled editing.
+
+Whether you block unauthorized access or totally disable file editing, it's important to take action to protect your site's code. Otherwise, it's easy for unwelcome visitors to edit your files and add new code. This means an attacker could use the editor to gather data from your WordPress site or even use your site to launch attacks on others.
+
+For an easier way of hiding your files, you can use a security plugin that will do it for you, such as Sucuri.
+
+### WordPress security recap
+
+WordPress is an excellent open source platform that should be enjoyed by beginners and developers alike without the fear of becoming a victim of an attack. Sadly, these threats aren't going anywhere anytime soon, so it's vital to stay on top of your site's security.
+
+Using the measures outlined above, you can create a stronger, more secure level of protection for your WordPress site and ensure a much more enjoyable experience for yourself.
+
+Staying secure is an ongoing commitment rather than a one-time checklist, so be sure to revisit these steps regularly and stay alert when building and using your CMS.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/wordpress-security
+
+作者:[Lucy Carney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/lucy-carney
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_3reasons.png?itok=k6F3-BqA (A lock on the side of a building)
+[2]: https://cyberforces.com/en/wordpress-most-hacked-cms
+[3]: https://opensource.com/article/19/11/internet-security-tls-ssl-certificate-authority
+[4]: https://wordpress.org/plugins/sucuri-scanner/
+[5]: https://sucuri.net/website-firewall/
+[6]: https://wordpress.org/themes/
+[7]: https://themify.me/
+[8]: https://developers.google.com/search/mobile-sites/
+[9]: http://www.gnu.org/licenses/gpl.html
+[10]: https://wordpress.org/about/stats/
+[11]: https://wordpress.org/plugins/stops-core-theme-and-plugin-updates/
+[12]: https://www.forbes.com/sites/kateoflahertyuk/2019/04/21/these-are-the-worlds-most-hacked-passwords-is-yours-on-the-list/#4f157c2f289c
+[13]: https://opensource.com/article/16/12/password-managers
+[14]: https://wordpress.org/plugins/wps-hide-login/
+[15]: https://en-gb.wordpress.org/plugins/two-factor/
diff --git a/sources/tech/20200427 New zine- How Containers Work.md b/sources/tech/20200427 New zine- How Containers Work.md
new file mode 100644
index 0000000000..fa2198ebbc
--- /dev/null
+++ b/sources/tech/20200427 New zine- How Containers Work.md
@@ -0,0 +1,121 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (New zine: How Containers Work!)
+[#]: via: (https://jvns.ca/blog/2020/04/27/new-zine-how-containers-work/)
+[#]: author: (Julia Evans https://jvns.ca/)
+
+New zine: How Containers Work!
+======
+
+On Friday I published a new zine: “How Containers Work!”. I also launched a fun redesign of [wizardzines.com][1].
+
+You can get it for $12 at . If you buy it, you’ll get a PDF that you can either print out or read on your computer. Or you can get a pack of [all 8 zines][2] so far.
+
+Here’s the cover and table of contents:
+
+[![][3]][4]
+
+### why containers?
+
+I’ve spent a lot of time [figuring][5] [out][6] [how to][7] [run][8] [things][9] [in][10] [containers][11] over the last 3-4 years. And at the beginning I was really confused! I knew a bunch of things about Linux, and containers didn’t seem to fit in with anything I thought I knew (“is it a process? what’s a network namespace? what’s happening?“). The whole thing seemed really weird.
+
+It turns out that containers ARE actually pretty weird. They’re not just one thing, they’re what you get when you glue together 6 different features that were mostly designed to work together but have a bunch of confusing edge cases.
+
+As usual, the thing that helped me the most in my container adventures is a good understanding of the **fundamentals** – what exactly is actually happening on my server when I run a container?
+
+So that’s what this zine is about – cgroups, namespaces, pivot_root, seccomp-bpf, and all the other Linux kernel features that make containers work.
+
+Once I understood those ideas, it got a **lot** easier to debug when my containers were doing surprising things in production. I learned a couple of interesting and strange things about containers while writing this zine too – I’ll probably write a blog post about one of them later this week.
+
+### containers aren’t magic
+
+This picture (page 6 of the zine) shows you how to run a fish container image with only 15 lines of bash. This is heavily inspired by [bocker][12], which “implements” Docker in about 100 lines of bash.
+
+
+
+The main things I see missing from that script compared to what Docker actually does when running a container (other than using an actual container image and not just a tarball) are:
+
+ * it doesn’t drop any capabilities – the container is still running as root and has full root privileges (just in a different mount + PID namespace)
+ * it doesn’t block any system calls with seccomp-bpf
+
+
+
+### container command line tools
+
+The zine also goes over a bunch of command line tools & files that you can use to inspect running containers or play with Linux container features. Here’s a list:
+
+ * `mount -t overlay` (create and view overlay filesystems)
+ * `unshare` (create namespaces)
+ * `nsenter` (use an existing namespace)
+ * `getpcaps` (get a process’s capabilities)
+ * `capsh` (drop or add capabilities, etc)
+ * `cgcreate` (create a cgroup)
+ * `cgexec` (run a command in an existing cgroup)
+ * `chroot` (change root directory. not actually what containers use but interesting to play with anyway)
+ * `/sys/fs/cgroups` (for information about cgroups, like `memory.usage_in_bytes`)
+ * `/proc/PID/ns` (all a process’s namespaces)
+ * `lsns` (another way to view namespaces)
+
+
+
+I also made a short youtube video a while back called [ways to spy on a Docker container][13] that demos some of these command line tools.
+
+### container runtime agnostic
+
+I tried to keep this zine pretty container-runtime-agnostic – I mention Docker a couple of times because it’s so widely used, but it’s about the Linux kernel features that make containers work in general, not Docker or LXC or systemd-nspawn or Kubernetes or whatever. If you understand the fundamentals you can figure all those things out!
+
+### we redesigned wizardzines.com!
+
+On Friday I also launched a redesign of [wizardzines.com][1]! [Melody Starling][14] (who is amazing) did the design. I think now it’s better organized but the tiny touch that I’m most delighted by is that now the zines jump with joy when you hover over them.
+
+One cool thing about working with a designer is – they don’t just make things _look_ better, they help _organize_ the information better so the website makes more sense and it’s easier to find things! This is probably obvious to anyone who knows anything about design but I haven’t worked with designers very much (or maybe ever?) so it was really cool to see.
+
+One tiny example of this: Melody had the idea of adding a tiny FAQ on the landing page for each zine, where I can put the answers to all the questions people always ask! Here’s what the little FAQ box looks like:
+
+[![][15]][4]
+
+I probably want to edit those questions & answers over time but it’s SO NICE to have somewhere to put them.
+
+### what’s next: maybe debugging! or working more on flashcards!
+
+The two projects I’m thinking about the most right now are
+
+ 1. a zine about debugging, which I started last summer and haven’t gotten around to finishing yet
+ 2. a [flashcards project][16] that I’ve been adding to slowly over the last couple of months. I think could become a nice way to explain basic ideas.
+
+
+
+Here’s a link to where to [get the zine][4] again :)
+
+--------------------------------------------------------------------------------
+
+via: https://jvns.ca/blog/2020/04/27/new-zine-how-containers-work/
+
+作者:[Julia Evans][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://jvns.ca/
+[b]: https://github.com/lujun9972
+[1]: https://wizardzines.com
+[2]: https://wizardzines.com/zines/all-the-zines/
+[3]: https://jvns.ca/images/containers-cover.jpg
+[4]: https://wizardzines.com/zines/containers
+[5]: https://stripe.com/en-ca/blog/operating-kubernetes
+[6]: https://jvns.ca/blog/2016/09/15/whats-up-with-containers-docker-and-rkt/
+[7]: https://jvns.ca/blog/2016/10/10/what-even-is-a-container/
+[8]: https://jvns.ca/blog/2016/12/22/container-networking/
+[9]: https://jvns.ca/blog/2016/10/26/running-container-without-docker/
+[10]: https://jvns.ca/blog/2017/02/17/mystery-swap/
+[11]: https://jvns.ca/blog/2016/10/02/a-list-of-container-software/
+[12]: https://github.com/p8952/bocker
+[13]: https://www.youtube.com/watch?v=YCVSdnYzH34&t=1s
+[14]: https://melody.dev
+[15]: https://jvns.ca/images/wizardzines-faq.png
+[16]: https://flashcards.wizardzines.com
diff --git a/sources/tech/20200428 Learn Bash with this book of puzzles.md b/sources/tech/20200428 Learn Bash with this book of puzzles.md
new file mode 100644
index 0000000000..08a07b93c5
--- /dev/null
+++ b/sources/tech/20200428 Learn Bash with this book of puzzles.md
@@ -0,0 +1,60 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Learn Bash with this book of puzzles)
+[#]: via: (https://opensource.com/article/20/4/bash-it-out-book)
+[#]: author: (Carlos Aguayo https://opensource.com/users/hwmaster1)
+
+Learn Bash with this book of puzzles
+======
+'Bash it out' covers basic, medium, and advanced Bash scripting using 16
+puzzles.
+![Puzzle pieces coming together to form a computer screen][1]
+
+Computers are both my hobby and my profession. I have about 10 of them scattered around my apartment, all running Linux (including my Macs). Since I enjoy upgrading my computers and my computer skills, when I came across [_Bash it out_][2] by Sylvain Leroux, I jumped on the chance to buy it. I use the command line a lot on Debian Linux, and it seemed like a great opportunity to expand my Bash knowledge. I smiled when the author explained in the preface that he uses Debian Linux, which is one of my two favorite distributions.
+
+Bash lets you automate tasks, so it's a labor-saving, interesting, and useful tool. Before reading the book, I already had a fair amount of experience with Bash on Unix and Linux. I'm not an expert, in part because the scripting language is so extensive and powerful. I first became intrigued with Bash when I saw it on the welcome screen of [EndeavourOS][3], an Arch-based Linux distribution.
+
+The following screenshots show some options from EndeavourOS. Beleieve it or not, these panels just point to Bash scripts, each of which accomplish some relatively complex tasks. And because it's all open source, I can modify any of these scripts if I want.
+
+![EndeavourOS after install][4]
+
+![EndeavourOS install apps][5]
+
+### Always something to learn
+
+My impressions of this book are very favorable. It's not long, but it is well-thought-out. The author has very extensive knowledge of Bash and an uncanny ability to explain how to use it. The book covers basic, medium, and advanced Bash scripting using 16 puzzles, which he calls "challenges." This taught me to see Bash scripting as a programming puzzle to solve, which makes it more interesting to play with.
+
+An exciting aspect of Bash is that it's deeply integrated with the Linux system. While part of its power lies in its syntax, it's also powerful because it has access to so much. You can script repetitive tasks, or tasks that are easy but you're just tired of performing manually. Nothing is too great or too small, and _Bash it out_ helps you understand both what you can do, and how to achieve it.
+
+This review would not be complete if I didn't mention David Both's free resource [_A sysadmin's guide to Bash scripting_][6] on Opensource.com. This 17-page PDF guide is different from _Bash it out_, but together they make a winning combination for anyone who wants to learn about it.
+
+I am not a computer programmer, but _Bash it out_ has increased my desire to get into more advanced levels of Bash scripting—I might inadvertently end up as a computer programmer without planning to.
+
+One reason I love Linux is because of how powerful and versatile the operating system is. However much I know about Linux, there is always something new to learn that makes me appreciate Linux even more.
+
+In a competitive and ever-changing job market, it behooves all of us to continuously update our skills. This book helped me learn Bash in a very hands-on way. It almost felt as if the author was in the same room with me, patiently guiding me in my learning.
+
+The author, Leroux, has an uncanny ability to engage readers. This is a rare gift that I think is even more valuable than his technical expertise. In fact, I am writing this book review to thank the author for anticipating my own learning needs; although we have never met, I have benefited in real ways from his gifts.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/bash-it-out-book
+
+作者:[Carlos Aguayo][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hwmaster1
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/puzzle_computer_solve_fix_tool.png?itok=U0pH1uwj (Puzzle pieces coming together to form a computer screen)
+[2]: https://www.amazon.com/Bash-Out-Strengthen-challenges-difficulties/dp/1521773262/
+[3]: https://endeavouros.com/
+[4]: https://opensource.com/sites/default/files/uploads/endeavouros-welcome.png (EndeavourOS after install)
+[5]: https://opensource.com/sites/default/files/uploads/endeavouros-install-apps.png (EndeavourOS install apps)
+[6]: https://opensource.com/downloads/bash-scripting-ebook
diff --git a/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md b/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md
new file mode 100644
index 0000000000..748786de77
--- /dev/null
+++ b/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md
@@ -0,0 +1,137 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source live streaming with Open Broadcaster Software)
+[#]: via: (https://opensource.com/article/20/4/open-source-live-stream)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Open source live streaming with Open Broadcaster Software
+======
+If you have something to say, a skill to teach, or just something fun to
+share, broadcast it to the world with OBS.
+![An old-fashioned video camera][1]
+
+If you have a talent you want to share with the world, whether it's making your favorite sourdough bread or speedrunning through a level of your favorite video game, live streaming is the modern show-and-tell. It's a powerful way to tell the world about your hobby through a medium once reserved for exclusive and expensive TV studios. Not only is the medium available to anyone with a relatively good internet connection, but the most popular software to make it happen is open source.
+
+[OBS][2] (Open Broadcaster Software) is a cross-platform application that serves as a control center for your live stream. A _stream_, strictly speaking, means _progressive and coherent data_. The data in a stream can be audio, video, graphics, text, or anything else you can represent as digital data. OBS is programmed to accept data as input, combine streams together (technically referred to as _mixing_) into one product, and then broadcast it.
+
+![OBS flowchart][3]
+
+A _broadcast_ is data that can be received by some target. If you're live streaming, your primary target is a streaming service that can host your stream, so other people can find it in a web browser or media player. A live stream is a live event, so people have to "tune in" to your stream when it's happening, or else they miss it. However, you can also target your own hard drive so you can record a presentation and then post it on the internet later for people to watch at their leisure.
+
+### Installing OBS
+
+To install OBS on Windows or macOS, download an installer package from [OBS's website][2].
+
+To install OBS on Linux, either install it with your package manager (such as **dnf**, **zypper**, or **apt**) or [install it as a Flatpak][4].
+
+### Join a streaming service
+
+In order to live stream, you must have a stream broker. That is, you need a central location on the internet for your stream to be delivered, so your viewers can get to what you're broadcasting. There are a few popular streaming services online, like YouTube and Twitch. You can also [set up your own video streaming server][5] using open source software.
+
+Regardless of which option you choose, before you begin streaming, you must have a destination for your stream. If you do use a streaming service, you must obtain a _streaming key_. A streaming key is a hash value (it usually looks something like **2ae2fad4e33c3a89c21**) that is private and unique to you. You use this key to authenticate yourself through your streaming software. Without it, the streaming service can't know you are who you say you are and won't let you broadcast over your user account.
+
+* * *
+
+* * *
+
+* * *
+
+**![Streaming key][6]**
+
+ * In Twitch, your **Primary Stream Key** is available in the **Channel** panel of your **Creator Dashboard**.
+ * On YouTube, you must enable live streaming by verifying your account. Once you've done that, your **Stream Key** is in the **Other Features** menu option of your **Channel Dashboard**.
+ * If you're using your own server, there's no maze-like GUI to navigate. You just [create your own streaming key][7].
+
+
+
+### Enter your streaming key
+
+Once you have a streaming key, launch OBS and go to the **File** > **Settings** menu.
+
+In the **Settings** window, click on the **Stream** category in the left column. Set the **Service** to your stream service (Custom, Twitch, YouTube, etc.), and enter your stream key. Click the **OK** button in the bottom right to save your changes.
+
+### Create sources
+
+In OBS, _sources_ represent any input signal you want to stream. By default, sources are listed at the bottom of the OBS window.
+
+![OBS sources][8]
+
+This might be a webcam, a microphone, an audio stream (such as the sound of a video game you're playing), a screen capture of your computer (a "screencast"), a slideshow you want to present, an image, and so on. Before you start streaming, you should define all the sources you plan on using for your stream. This means you have to do a little pre-production and consider what you anticipate for your show. Any camera you have set up must be defined as a source in OBS. Any extra media you plan on cutting to during your show must be defined as a source. Any sound effects or background music must be defined as a source.
+
+Not all sources "happen" at once. By adding media to your **Sources** panel in OBS, you're just assembling the raw components for your stream. Once you make devices and data available to OBS, you can create your **Scenes**.
+
+#### Setting up audio
+
+Computers have seemingly dozens of ways to route audio. Here's the workflow to follow when setting up sound for your stream:
+
+ 1. Check your cables: verify that your microphone is plugged in.
+ 2. Go to your computer's sound control panel and set the input to whatever microphone you want OBS to treat as the main microphone. This might be a gaming headset or a boom mic or a desktop podcasting mic or a Bluetooth device or a fancy audio interface with XLR ports. Whatever it is, make sure your computer "hears" your main sound input.
+ 3. In OBS, create a source for your main microphone and name it something obvious (e.g., boom mic, master sound, or mic).
+ 4. Do a test. Make sure OBS "hears" your microphone by referring to the audio-level monitors at the bottom of the OBS window. If it's not responding to the input you believe you've set as input, check your cables, check your computer sound control panel, and check OBS.
+
+
+
+I've seen more people panic over audio sources than any other issue when streaming, and we've _all_ made the same dumb mistakes (several times each, probably!) when attempting to set a microphone for a live stream or videoconference call. Breathe deep, check your cables, check your inputs and outputs, and [get comfortable with audio][9]. It'll pay off in the end.
+
+### Create scenes
+
+A **Scene** in OBS is a screen layout and consists of one or more sources.
+
+![Scenes in OBS][10]
+
+For instance, you might create a scene called **Master shot** that shows you sitting at your desk in front of your computer or at the kitchen counter ready to mix ingredients together. The source could be a webcam mounted on a tripod a meter or two in front of you. Because you want to cut to a detail shot, you might create a second scene called **Close-up**, which uses the computer screen and audio as one input source and your microphone as another source, so you can narrate as you demonstrate what you're doing. If you're doing a baking show, you might want to mount a second webcam above the counter, so you can cut to an overhead shot of ingredients being mixed. Here, your source is a different webcam but probably the same microphone (to avoid making changes in the audio).
+
+A _scene_, in other words, is a lot like a _shot_ in traditional production vernacular, but it can be the combination of many shots. The fun thing about OBS is that you can mix and match a lot of different sources together, so when you're adding a **Scene**, you can resize and position different sources to achieve picture-in-picture, or split-screen, or any other effect you might want. It's common in video game "let's play" streams to have the video game in full-screen, with the player inset in the lower right or left. Or, if you're recording a panel or a multi-player game like D&D you might have several cameras covering several players in a _Brady Bunch_ grid.
+
+The possibilities are endless. During streaming, you can cut from one scene to another as needed. This is intended to be a dynamic system, so you can change scenes depending on what the viewer needs to see at any given moment.
+
+Generally, you want to have some preset scenes before you start to stream. Even if you have a friend willing to do video mixing as you stream, you always want a safe scene to fall back to, so take time beforehand to set up at least a master shot that shows you doing whatever it is you're doing. If all else fails, at least you'll have your main shot you can safely and reliably cut to.
+
+### Transitions
+
+When switching from one scene to another, OBS uses a transition. Once you have more than one scene, you can configure what kind of transition it uses in the **Transitions** panel. Simple transitions are usually best. By default, OBS uses a subtle crossfade, but you can experiment with others as you see fit.
+
+### Go live
+
+To start streaming, do your vocal exercises, find your motivation, and press the **Start Streaming** button.
+
+![Start streaming in OBS][11]
+
+As long as you've set up your streaming service correctly, you're on the air (or on the wires, anyway).
+
+If you're the talent (the person in front of the camera), it might be easiest to have someone control OBS during streaming. But if that's not possible, you can control it yourself as long as you've practiced a little in advance. If you're screencasting, it helps to have a two-monitor setup so you can control OBS without it being on screen.
+
+### Streaming for success
+
+Many of us take streaming for granted now that the internet exists and can broadcast media created by _anyone_. It's a hugely powerful means of communication, and we're all responsible for making the most of it.
+
+If you have something positive to say, a skill to teach, words of encouragement, or just something fun that you want to share, and you feel like you want to broadcast to the world, then take the time to learn OBS. You might not get a million viewers, but independent media is a vital part of [free culture][12]. The world can always use empowering and positive open source voices, and yours may be one of the most important of all.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-live-stream
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LIFE_film.png?itok=aElrLLrw (An old-fashioned video camera)
+[2]: http://obsproject.com
+[3]: https://opensource.com/sites/default/files/obs-flowchart.jpg (OBS flowchart)
+[4]: https://flatpak.org/setup
+[5]: https://opensource.com/article/19/1/basic-live-video-streaming-server
+[6]: https://opensource.com/sites/default/files/twitch-key.jpg (Streaming key)
+[7]: https://opensource.com/article/19/1/basic-live-video-streaming-server#obs
+[8]: https://opensource.com/sites/default/files/uploads/obs-sources.jpg (OBS sources)
+[9]: https://opensource.com/article/17/1/linux-plays-sound
+[10]: https://opensource.com/sites/default/files/uploads/obs-scenes.jpg (Scenes in OBS)
+[11]: https://opensource.com/sites/default/files/uploads/obs-stream-start.jpg (Start streaming in OBS)
+[12]: https://opensource.com/article/18/1/creative-commons-real-world
diff --git a/sources/tech/20200430 Edit music recordings with Audacity on Linux.md b/sources/tech/20200430 Edit music recordings with Audacity on Linux.md
new file mode 100644
index 0000000000..be6f68f062
--- /dev/null
+++ b/sources/tech/20200430 Edit music recordings with Audacity on Linux.md
@@ -0,0 +1,161 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Edit music recordings with Audacity on Linux)
+[#]: via: (https://opensource.com/article/20/4/audacity)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Edit music recordings with Audacity on Linux
+======
+How COVID-19 caused me to learn Audacity on the fly and learn to love
+it.
+![Bird singing and music notes][1]
+
+In this strange and difficult time of a global pandemic, we are all called upon to do things differently, to change our routines, and to learn new things.
+
+I have worked from home for many years, so that is nothing new to me. Even though I am allegedly retired, I write articles for Opensource.com and [Enable Sysadmin][2] and books. I also manage my own home network, which is larger than you might think, and my church's network and Linux hosts, and I help a few friends with Linux. All of this keeps me busy doing what I like to do, and all of it is usually well within my comfort zone.
+
+But COVID-19 has changed all of that. And, like many other types of organizations, my church had to move quickly to a new service-delivery paradigm. And that is what churches do—deliver a specific kind of service. As the church sysadmin and with some knowledge of audio recording and editing (back in the '70s, I mixed the sound and was the only roadie for a couple of regional folk-rock groups in Toledo, Ohio), I decided to learn the open source audio recording and editing software [Audacity][3] to help meet this challenge.
+
+This is not a comprehensive how-to article about using Audacity. It is about my experiences getting started with this powerful audio-editing tool, but there should be enough information here to help you get started.
+
+I have learned just what I need to know in order to accomplish my task: combining several separate audio clips into a single MP3 audio file. If you already know Audacity and do things differently or know things that I don't, that is expected. And if you have any suggestions to help me accomplish my task more easily, please share them in the comments.
+
+### The old way
+
+I try not to use the term "normal" now because it is hard to know exactly what that is—if such a state even exists. But our old method of producing recordings for our shut-ins, members who are traveling, and anyone else was to record the sermon portion of our regular, in-person church services and post them on our website.
+
+To do this, I installed a TASCAM SS-R100 solid-state recorder that stores the sermons as MP3 files on a thumb drive. We uploaded the recordings to a special directory of our website so people could download them. The recordings are uploaded using a Bash [program][4] I wrote for the task. _Automate everything!_ I trained a couple of others to perform these tasks using sudo in case I was not available.
+
+This all worked very well. Until it didn't.
+
+### The new way
+
+As soon as the first restrictions on large gatherings occurred, we made some changes. We could still have small gatherings, so four of us met Sunday mornings and recorded an abbreviated service using our in-house recorder and doing the upload the usual way. This worked, but as the crisis deepened and it became more of a risk to meet with even a few people, we had to make more changes.
+
+Like a huge number of other organizations, we realized we each needed to perform our parts of creating services in separate locations from our own homes.
+
+Now, depending upon the structure of the service, I receive several recordings that I need to combine to create the full church service. Our music director records each anthem and interlude using her iPhone and sends me the recordings in the M4A (MPEG-4 audio) format. They each range in length from seconds to five minutes and are up to 3MB in size. Likewise, our rector sends me two to six recordings, also in M4A format, that contains his portion of the service. Sometimes, other musicians in our church send solos or duets recorded with their significant others; these can be in MP3 or M4A formats.
+
+Then, I pull all of this together into a single recording that can be uploaded to our server for people to download. I use Audacity for this because it was available in my repo, and it was easy to get started.
+
+### Getting started with Audacity
+
+I had never used [Audacity][5] before this, so, like many others these days, I needed to learn something new just in time to accomplish what I needed to do. I struggled a bit at first, but it turned out to be fun and very enlightening.
+
+Audacity was easy to install on my Fedora 31 workstation because, as in many distros, it is available from the Fedora repository.
+
+The first time I opened Audacity with the program launcher icon, the application's window was empty with no projects nor tracks present. Audacity projects have an AUP extension, so if you have an existing project, you could click on the file in your favorite file manager and launch Audacity that way.
+
+### Convert M4A to MP3
+
+As installed by Fedora, Audacity does not recognize M4A files. Regardless of how you proceed, you need to install the [LAME][6] MP3 encoder and [FFmpeg][7] import/export library, both of which are available from the Fedora repository and, most likely, any other distro's repository.
+
+There are websites that explain how to configure Audacity to use these tools to import and convert audio files from M4A to other types (such as MP3), but I decided to write a script to do it from the command line. For one reason, using a script is faster than doing a lot of extra clicking in a GUI interface, and for another, the file names need some work, so I already needed a script to rename the files. Many people use non-alphanumeric characters to name files, but I don't like dealing with special keyboard characters from the command line. It's easier to manage files with simple alphanumeric names, so my script removes all non-alphanumeric characters from the file names and then converts the files to MP3 format.
+
+You may choose a different approach, but I like the scripted solution. It is fast, and I only need to run the script once, no matter how many files need to be renamed and converted to MP3.
+
+### Create a new project
+
+You can create a new project whether or not any audio tracks are loaded. I recommend creating the project first, before importing any audio files (aka "clips"). From the Menu bar, select **File > Save Project > Save Project As**. This opens a warning dialog window that says, _"'Save project' is for an Audacity project, not an audio file."_ Click the **OK** button to continue to a standard file-save dialog.
+
+I found that I needed to do this twice. The first time, the warning dialog did not display any buttons, so I had to close the dialog using the window menu or the x icon in the Title bar.
+
+Name the project whatever you like, and Audacity automatically adds the AUP extension. You now have an empty project.
+
+### Add audio files to your project
+
+The first step is to add your audio files to the project. Using the Menu bar, open **File > Import > Audio** and then use the file dialog to select one or more files to import. For my first test project, I loaded all the files at once without sorting the tracks nor aligning the clips in the desired sequence along the timeline. This time, I started by loading the audio files one at a time in the sequence I wanted them from top to bottom. As each file is imported, it is placed into a new track below any existing tracks. The following image shows the files loaded all at one time in the sequence they appear in the working directory.
+
+![Tracks loaded in Audacity][8]
+
+There is a timeline across the top of the window's track area. There is also a scroll bar at the bottom of the window, so you can scroll along the timeline when the tracks extend beyond the width of the Audacity window. There is also a vertical scroll bar if there are more tracks than fit into the window.
+
+Notice the names in the upper-left corner of the waveform section of each track—they are the file names of each track without the extension. These are not there by default, but I find them helpful. To display these names, use the Menu bar to select **Edit > Preferences** and place a check in the **Show Audio Track Name As Overlay** box.
+
+### Order your audio clips
+
+Once you have some files loaded into the Audacity workspace, you can start manipulating them. To order your audio clips, select one and use the **Time-Shift** tool (↔︎) to slide them horizontally along the tracks; continue doing this until all the clips line up end to end in the order you want them. Note that the clip you are moving is book-ended by a pair of vertical alignment lines. When they line up perfectly, the end lines of the two aligned tracks change color to alert you.
+
+You can hover the mouse pointer over the tool icons in the Audacity toolbars to see a pop-up that displays the name of that tool. This helps beginners understand what each tool does.
+
+![Audacity toolbox][9]
+
+Here, the **Selection** tool** **is selected in the Audacity toolbar. The **Time-Shift** tool is second from the left on the bottom row.
+
+The following image shows what happens when you slide the audio clips into place on the project timeline without sorting the tracks into a particular sequence. This may not be optimal for how you like to work. It is not for me.
+
+![Audio clips in Audacity][10]
+
+To remove segments of (or complete) audio clips, select them with the **Selection** tool—you can also select multiple adjacent tracks. Then you can press the **Delete** button on your keyboard to delete the selected segment(s).
+
+In the image above, you can see a vertical black line in track 1 and a vertical green line crossing all the tracks. These are the audio cursors that show the playback positions of a track or the entire project. Choose the **Selection** tool and click the desired position within a track, then click the **Play** button on the transport controls (in the upper-left of the Audacity window) to begin playback. Playback will continue past the end of the selected track and all the way to the end of the project. If tracks overlap on the timeline, they will play simultaneously.
+
+To begin playback immediately, click the desired starting point on the timeline. To play part of a track, hold down the Left mouse button to select a short segment of the track, and then click the **Play** button. The other transport buttons—Pause, Stop, and so—on are identified with universal icons and work as you would expect.
+
+You can also click the **Silence Audio Selection** button—the fifth button from the left on the **Edit** toolbar (shown below)—to completely silence a selected segment while leaving it in place for timing purposes. This is how I silenced a number of background clicks and noises.
+
+![Audacity edit tools][11]
+
+It took me a while to figure out how to sort the tracks vertically, and it turns out there are a few different ways to accomplish the task.
+
+You can use the track menu to reorder arrangement. Each track has its own Control Panel on the left side (shown below). The track drop-down Menu bar at the top of the Control Panel opens a menu that provides several track-sequencing options to move a track up, down, to the top, or to the bottom.
+
+![Moving tracks in Audacity][12]
+
+The items to move a track up or down move the track one position at a time, so you have to select it as many times as necessary to get the track in the desired position.
+
+To drag and drop tracks, you must click on the space occupied by the track details. In this screenshot, that's "Mono, 48000Hz 32 bit float". It can be tricky, because if you click too high, you adjust the panning (the left and right stereo position) and if you click too low, you may collapse or select the track. Target the "Mono" or "Stereo" label (whatever your track happens to be) label, and then click and drag the track up or down to reposition it in your workspace.
+
+### Apply amplification and noise reduction effects
+
+Some tracks need the overall volume to be adjusted. I used the **Selection** tool to double-click and select the entire track (but you could also select a portion of a track). On the Menu bar, select **Effect > Amplify** to display a small dialog window. You can use the slider or enter a value to specify the amount of amplification. Negative numbers decrease the volume. If you try to increase the volume, you need to place a check in the **Allow Clipping** box. Then click OK.
+
+I found that amplification is a bit tricky; it is easy to use too much or too little. Start by using small numbers to see the results. You can always use **Ctrl+Z** to undo your changes if you go too far in either direction.
+
+Another effect I find useful is noise reduction. One of the tracks was recorded with a noticeable 60Hz hum, which is usually due to poor grounding of the microphone or recorder. Fortunately, there were only several seconds of hum and no other sound at the beginning of the recording.
+
+Applying the noise reduction effect was a little confusing at first. First, I selected a few samples of the humming sound to tell Audacity what sound needed to be reduced, and then I navigated to **Effect > Noise Reduction**. This opens the **Noise Reduction** dialog. I clicked on the **Get Noise Profile** button in the Step 1 section of the dialog, which uses the selected sample as the basis for a set of filter presets. After it gathers the selected sample, though, the dialog disappeared (this is by design). I re-opened the dialog, used the slider to select the noise reduction level in decibels (I set it to 15dB and left the other sliders alone), and then clicked **OK**.
+
+This worked well—you can hear the residual hum only if you know it is there. I need to experiment with this some more, but since the result was acceptable, so I did not play with the settings any further.
+
+The reason the dialog box closes after getting a noise profile is actually for the sake of expediency. If you're processing many tracks or segments of audio, each with a different noise profile, you can open the **Noise Reduction** effect, get the current noise profile, and then select the audio you want to clean. You can then run the Noise Reduction filter using **Ctrl+R**, the keyboard shortcut for running the most recent filter. Instead of getting a new noise profile, however, Audacity uses the one you've just stored, and performs the filter instead. This way, you can get a sample with a few clicks but clean lots of audio with just one keyboard shortcut.
+
+### And so much more
+
+I have only worked with a few of the basics and have not even begun to scratch the surface of Audacity. I can already see that it has so many more features and tools that will enable me to create even more professional-sounding projects.
+
+For example, in addition to working with existing audio files, Audacity can make recordings from line inputs, the desktop sound stream, and microphone inputs. It can do special effects like fade in and out and cross-fades. And I have not even tried to figure out what many of the other effects and tools are capable of.
+
+I have a feeling I will need to learn more in the near future. Hopefully, this story of my very limited experience with Audacity will prompt you to check it out. For much more information, you can find the [Audacity manual][13] online.
+
+Using Audacity, you can quickly clean up audio file so that any background noise becomes tolerable.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/audacity
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/music-birds-recording-520.png?itok=UoM7brl0 (Bird singing and music notes)
+[2]: https://www.redhat.com/sysadmin/
+[3]: https://www.audacityteam.org/
+[4]: https://opensource.com/article/17/12/using-sudo-delegate
+[5]: https://opensource.com/education/16/9/audacity-classroom
+[6]: https://manual.audacityteam.org/man/installing_and_updating_audacity_on_linux.html#linlame
+[7]: https://manual.audacityteam.org/man/installing_and_updating_audacity_on_linux.html#linff
+[8]: https://opensource.com/sites/default/files/uploads/audacity1_tracksloaded.png (Tracks loaded in Audacity)
+[9]: https://opensource.com/sites/default/files/uploads/audacity2_tools.png (Audacity toolbox)
+[10]: https://opensource.com/sites/default/files/uploads/audacity3_audioclips.png (Audio clips in Audacity)
+[11]: https://opensource.com/sites/default/files/uploads/audacity4_edittoolbar.png (Audacity edit tools)
+[12]: https://opensource.com/sites/default/files/uploads/audacity5_trackmovement.png (Moving tracks in Audacity)
+[13]: https://manual.audacityteam.org/#
diff --git a/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md b/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md
new file mode 100644
index 0000000000..c3c0c36b66
--- /dev/null
+++ b/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md
@@ -0,0 +1,77 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Linux and Kubernetes: Serving The Common Goals of Enterprises)
+[#]: via: (https://www.linux.com/articles/linux-and-kubernetes-serving-the-common-goals-of-enterprises/)
+[#]: author: (Swapnil Bhartiya https://www.linux.com/author/swapnil/)
+
+Linux and Kubernetes: Serving The Common Goals of Enterprises
+======
+
+[![][1]][2]
+
+For [Stefanie Chiras,][3] VP & GM, Red Hat Enterprise Linux (RHEL) Business Unit at [Red Hat][4], aspects such as security and resiliency have always been important for Red Hat. More so, in the current situation when everyone has gone fully remote and it’s much harder to get people in front of the hardware for carrying out updates, patching, etc.
+
+“As we look at our current situation, never has it been more important to have an operating system that is resilient and secure, and we’re focused on that,” she said.
+
+The recently released version of [Red Hat Enterprise Linux (RHEL) 8.2][5] inadvertently address these challenge as it makes it easier for technology leaders to embrace the latest, production-ready innovations swiftly which offering security and resilience that their IT teams need.
+
+RHEL’s embrace of a predictable 6-month minor release cycle also helped customers plan upgrades more efficiently.
+
+“There is value for customers in having predictability of minor releases on a six-month cycle. Without knowing when they were coming was causing disruptions for them. The launch of 8.2 is now the second time we have delivered on our commitment of having minor releases every six months,” said Stefanie Chiras.
+
+In addition to offering security updates, the new version adds insights capabilities and forays into newer areas of innovation.
+
+The upgrade has expanded the earlier capability called ‘Adviser’ dramatically. Additional functionalities such as drift monitoring and CVE coverage allow for a much deeper granularity into how the infrastructure is running.
+
+“It really amplifies the skills that are already present in ops and sysadmin teams, and this provides a Red Hat consultation, if you will, directly into the data center,” claimed Charis.
+
+As containers are increasingly being leveraged for digital transformation, RHEL 8.2 offers an updated application stream of Red Hat’s container tools. It also has new, containerized versions of Buildah and Skopeo.
+
+[Skopeo][6] is an open-source image copying tool, while Buildah is a tool for building Docker- and Kubernetes-compatible images easily and quickly.
+
+RHEL has also ensured in-place upgrades in the new version. Customers can now directly in-place upgrade from version 7 to version 8.2.
+
+Chiras believes Linux has emerged as the go-to-platform for innovations such as Machine Learning, Deep Learning, and Artificial Intelligence.
+
+“Linux has now become the springboard of innovation,” she argued. “AI, machine learning, and deep learning are driving a real change in not just the software but also the hardware. In the context of these emerging technologies, it’s all about making them consumable into an enterprise.”
+
+“We’re very focused on our ecosystem, making sure that we’re working in the right upstream communities with the right ISVs, with the right hardware partners to make all of that magic come together,” Chiras said.
+
+Towards this end, Red Hat has been partnering with multiple architectures for a long time — be it an x86 architecture, ARM, Power, or mainframe with IBM Z. Its partnership with Nvidia pulls in capabilities such as FPGAs, and GPU.
+
+**Synergizing Kubernetes and Linux **
+
+Kubernetes is fast finding favor in enterprises. So how do Linux and Kubernetes serve the common goals of enterprises?
+
+“Kubernetes is a new way to deploy Linux. We’re very focused on providing operational consistency by leveraging our technology in RHEL and then bringing in that incredible capability of Kubernetes within our OpenShift product line,” Chiras said.
+
+The deployment of Linux within a Kubernetes environment is much more complicated than in a traditional deployment. RHEL, therefore, made some key changes. The company created Red Hat Enterprise Linux CoreOS — an optimized version of RHEL for the OpenShift experience.
+
+“It’s deployed as an immutable. It’s tailored, narrow, and gets updated as part of your OpenShift update to provide consistent user experience and comprehensive security.
+
+The launch of the Red Hat Universal Base Image (UBI) offers users greater security, reliability, and performance of official Red Hat container images where OCI-compliant Linux containers run.
+
+“Kubernetes is a new way to deploy Linux. It really is a tight collaboration but what we’re really focused on is the customer experience. We want them to get easy updates with consistency and reliability, resilience and security. We’re pulling all of that together. With such advancements going on, it’s a fascinating space to watch,” added Chiras.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/articles/linux-and-kubernetes-serving-the-common-goals-of-enterprises/
+
+作者:[Swapnil Bhartiya][a]
+选题:[lujun9972][b]
+译者:[译者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/author/swapnil/
+[b]: https://github.com/lujun9972
+[1]: https://www.linux.com/wp-content/uploads/2019/12/computer-2930704_1280-1068x634.jpg (computer-2930704_1280)
+[2]: https://www.linux.com/wp-content/uploads/2019/12/computer-2930704_1280.jpg
+[3]: https://www.linkedin.com/in/stefanie-chiras-9022144/
+[4]: https://www.redhat.com/en
+[5]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/8.2_release_notes/index
+[6]: https://github.com/containers/skopeo
diff --git a/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md b/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md
new file mode 100644
index 0000000000..d4ce222a39
--- /dev/null
+++ b/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md
@@ -0,0 +1,123 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Transparent, open source alternative to Google Analytics)
+[#]: via: (https://opensource.com/article/20/5/plausible-analytics)
+[#]: author: (Marko Saric https://opensource.com/users/markosaric)
+
+Transparent, open source alternative to Google Analytics
+======
+Plausible Analytics is a leaner, more transparent option, with the
+essential data you need but without all the privacy baggage.
+![Digital creative of a browser on the internet][1]
+
+Google Analytics is the most popular website analytics tool. Millions of developers and creators turn to it to collect and analyze their website statistics.
+
+More than 53% of all sites on the web track their visitors using Google Analytics. [84%][2] of sites that do use a known analytics script use Google Analytics.
+
+Google Analytics has, for years, been one of the first tools I installed on a newly launched site. It is a powerful and useful analytics tool. Installing Google Analytics was a habit I didn't think much about until the introduction of the [GDPR][3] (General Data Protection Regulation) and other privacy regulations.
+
+Using Google Analytics these days comes with several pitfalls, including the need for a privacy policy, the need for cookie banners, and the need for a GDPR consent prompt. All these may negatively impact the site loading time and visitor experience.
+
+This has made me try to [de-Google-ify websites][4] that I work on, and it's made me start working on independent solutions that are open source and more privacy-friendly. This is where Plausible Analytics enters the story.
+
+[Plausible Analytics][5] is an open source and lightweight alternative to Google Analytics. It doesn't use cookies and it doesn't collect any personal data, so you don't need to show any cookie banners or get GDPR or CCPA consent. Let's take a closer look.
+
+### Main differences between Google Analytics and Plausible
+
+Plausible Analytics is not designed to be a clone of Google Analytics. It is meant as a simple-to-use replacement and a privacy-friendly alternative. Here are the main differences between the two web analytics tools:
+
+#### Open source vs. closed source
+
+Google Analytics may be powerful and useful, but it is closed source. It is a proprietary tool run by one of the largest companies in the world, a company that is a key player in the ad-tech industry. There's simply no way of knowing what's going on behind the scenes. You have to put your trust in Google.
+
+Plausible is a fully open source tool. You can read our code [on GitHub][6]. We're "open" in other ways, too, such as our [public roadmap][7], which is based around the feedback and features submitted by the members of our community.
+
+#### Privacy of your website visitors
+
+Google Analytics places [several cookies][8] on the devices of your visitors, and it tracks and collects a lot of data. This means that there are several requirements if you want to use Google Analytics and be compliant with the different regulations:
+
+ * You need to have a privacy policy about analytics
+ * You need to show a cookie banner
+ * You need to obtain a GDPR/CCPA consent
+
+
+
+Plausible is made to be fully compliant with the privacy regulations. No cookies are used, and no personal data is collected. This means that you don't need to display the cookie banner, you don't need a privacy policy, and you don't need to ask for the GDPR/CCPA consent when using Plausible.
+
+#### Page weight and loading time
+
+The recommended way of installing Google Analytics is to use the Google Tag Manager. Google Tag Manager script weights 28 KB, and it downloads another JavaScript file called the Google Analytics tag, which adds an additional 17.7 KB to your page size. That's 45.7 KB of page weight combined.
+
+Plausible script weights only 1.4 KB. That's 33 times smaller than the Google Analytics Global Site Tag. Every KB matters when you want to keep your site fast to load.
+
+#### Accuracy of visitor stats
+
+Google Analytics is being blocked by an increasing number of web users. It's blocked by those who use open source browsers such as [Firefox][9] and [Brave][10]. It's also blocked by those who use open source browser add-ons such as the [uBlock Origin][11]. It's not uncommon to see 40% or more of the audience on a tech site blocking Google Analytics.
+
+Plausible is a new player on this market and it's privacy-friendly by default, so it doesn't see the same level of blockage.
+
+#### Simple vs. complex web analytics
+
+[Google Analytics is overkill][12] for many website owners. It's a complex tool that takes time to understand and requires training. Google Analytics presents hundreds of different reports and metrics for you to get insights from. Many users end up creating custom dashboards while ignoring all the rest.
+
+Plausible cuts through all the noise that Google Analytics creates. It presents everything you need to know on one single page—all the most valuable metrics at a glance. You can get an overview of the most actionable insights about your website in one minute.
+
+### A guided tour of Plausible Analytics
+
+Plausible Analytics is not a full-blown replacement and a feature-by-feature reproduction of Google Analytics. It's not designed for all the different use-cases of Google Analytics.
+
+It's built with simplicity and speed in mind. There is no navigational menu. There are no additional sub-menus. There is no need to create custom reports. You get one simple and useful web analytics dashboard out of the box.
+
+Rather than tracking every metric imaginable, many of them that you will never find a use for, Plausible focuses on the essential website stats only. It is easy to use and understand with no training or prior experience:
+
+![Plausible analytics in action][13]
+
+ * Choose the time range that you want to analyze. The visitor numbers are automatically presented on an hourly, daily, or monthly graph. The default time frame is set at the last 30 days.
+ * See the number of unique visitors, total page views, and the bounce rate. These metrics include a percentage comparison to the previous time period, so you understand if the trends are going up or down.
+ * See all the referral sources of traffic and all the most visited pages on your site. Bounce rates of the individual referrals and pages are included too.
+ * See the list of countries your traffic is coming from. You can also see the device, browser, and operating system your visitors are using.
+ * Track events and goals to identify the number of converted visitors, the conversion rate, and the referral sites that send the best quality traffic.
+
+
+
+Take a look at the [live demo][14] where you can follow the traffic to the Plausible website.
+
+### Give Plausible Analytics a chance
+
+With Plausible Analytics, you get all the important web analytics at a glance so you can focus on creating a better site without needing to annoy your visitors with all the different banners and prompts.
+
+You can try Plausible Analytics on your site alongside Google Analytics. [Register today][15] to try it out, and see what you like and what you don't. Share your feedback with the community. This helps us learn and improve. We'd love to hear from you.
+
+Take a look at five great open source alternatives to Google Docs.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/plausible-analytics
+
+作者:[Marko Saric][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/markosaric
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
+[2]: https://w3techs.com/technologies/details/ta-googleanalytics
+[3]: https://gdpr-info.eu/
+[4]: https://markosaric.com/degoogleify/
+[5]: https://plausible.io/
+[6]: https://github.com/plausible-insights/plausible
+[7]: https://feedback.plausible.io/roadmap
+[8]: https://developers.google.com/analytics/devguides/collection/analyticsjs/cookie-usage
+[9]: https://www.mozilla.org/en-US/firefox/new/
+[10]: https://brave.com/
+[11]: https://github.com/gorhill/uBlock
+[12]: https://plausible.io/vs-google-analytics
+[13]: https://opensource.com/sites/default/files/plausible-analytics.png (Plausible analytics in action)
+[14]: https://plausible.io/plausible.io
+[15]: https://plausible.io/register
diff --git a/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md b/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md
new file mode 100644
index 0000000000..b260116fb6
--- /dev/null
+++ b/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md
@@ -0,0 +1,127 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (13 tips for getting your talk accepted at a tech conference)
+[#]: via: (https://opensource.com/article/20/5/tips-conference-proposals)
+[#]: author: (Todd Lewis https://opensource.com/users/toddlewis)
+
+13 tips for getting your talk accepted at a tech conference
+======
+Before you respond to an event's call for papers, make sure your talk's
+proposal aligns with these best practices.
+![All Things Open check-in at registration booth][1]
+
+As tech conference organizers ramp up for the fall season, you may be seeing calls for papers (CFP) landing in your email box or social media feeds. We at [All Things Open][2] (ATO) have seen a lot of presentation proposals over the years, and we've learned a few things about what makes them successful.
+
+As we prepare for the eighth annual ATO in October 2020, we thought we'd offer a few best practices for writing successful CFP responses. If you're considering submitting a talk to ATO or another tech event, we hope these tips will help improve the chances that your proposal will be accepted.
+
+### 1\. Know the event you're submitting a talk to
+
+This seems like the proverbial _no-brainer_, but some people don't take the time to research an event before they submit a talk. Peruse the conference's website and review the talks, speakers, topics, etc. featured in the last couple of years. You can also find a lot of information simply by googling. The time you invest here will help you avoid a submission that is completely out of context for the event.
+
+### 2\. Understand what the event is looking for
+
+Look for information about what the event is looking for and what types of topics or talks it expects will be a good fit. We try to provide as much information as possible about the [ATO conference][3], [why someone would want to speak][4], and [what we're looking for][5] (both general and special interest topics). We also try to make the submission process as easy as possible (no doubt, there is room for improvement), in part because we believe this improves the quality of submissions and makes our review process go more smoothly.
+
+### 3\. Reach out to the organizer and ask questions
+
+If you're considering submitting a talk, don't hesitate to reach out and ask the event organizers any questions you have and for guidance specific to the event. If there is no or little response, that should be a red flag. If you have any questions about All Things Open, please reach out directly at [info@allthingsopen.org][6].
+
+### 4\. Be clear about what attendees will learn from your talk
+
+This is one of the most common mistakes we see. Only about 25% of the proposals we receive clearly explain the proposed talk's takeaways. One reason you should include this is that nearly every event attendee makes their schedule based on what they will learn if they go to a session. But for organizers and proposal reviewers, having this information clearly stated upfront is pure gold. It simplifies and speeds up the assessment process, which gets you one step closer to being accepted as a speaker. A paragraph titled "Attendee Takeaways" with bullet points is the holy grail for everyone involved.
+
+### 5\. Keep recommended word counts in mind
+
+This is another mistake we see a lot. Many talks are submitted with either a single sentence description in the abstract or an extraordinary long volume of text. Neither is a good idea. The only exception we can think of is when a topic is very popular or topical, and that alone is enough to win the day even if the abstract is extremely short (but this is rare). Most abstracts should be between 75 and 250 words, and perhaps more for an extended workshop with prerequisites (e.g., preexisting knowledge or required downloads). Even then, try to keep your proposal as sharp, concise, and on-point as possible.
+
+Disregard this advice at your own risk; otherwise, there's a high likelihood that your proposal will be met with one of these reactions from reviewers: "They didn't take the time to write any more than this?" or "Sheesh, there's no way I have the time to read all that. I'm going to give it the lowest score and move on."
+
+### 6\. Choose a good title
+
+This is a debate we see all the time: Should a talk's title describe what the talk is about, or should it be written to stand out and get attention (e.g., evoking emotion, anchoring to a popular pop culture topic, or asking a compelling question)? There isn't a single correct answer to this question, but we definitely know when a title "works" and when it doesn't. We've seen some very creative titles work well and generate interest, and we've seen very straightforward titles work well, also.
+
+Here is our rule of thumb: If the talk covers a topic that has been around a while and is not particularly _hot_ right now, try getting creative and spicing it up a bit. If the topic is newer, a more straightforward title describing the talk in plain terms should be good.
+
+Titles on an event schedule may be the only thing attendees use to decide what talks to attend. So, run your potential talk titles by colleagues and friends, and seek their opinions. Ask: "If you were attending an event and saw this title on the schedule, would it pique your interest?"
+
+### 7\. Know the basic criteria that reviewers and organizers use to make decisions
+
+While this isn't a comprehensive list of review criteria, most reviewers and organizers consider one or more of the following when evaluating talk proposals. Therefore, at minimum, consider this list when you're creating a talk and the components that go with it.
+
+ 1. **Timeliness of and estimated interest in the topic:** Is the topic applicable to the session's target audience? Will it deliver value? Is it timely?
+ 2. **Educational value:** Based on the abstract and speaker, is it clear that attendees will learn something from the talk? As mentioned in item 4 above, including an "Attendee Takeaways" section is really helpful to establish educational value.
+ 3. **Technical value:** Is the technology you intend to showcase applicable, unique, or being used in a new and creative way? Is there a live demo or a hands-on component? While some topics don't lend themselves to a demo, most people are visual learners and are better off if a presentation includes one (if it's relevant). For this reason, we place a lot of value on demos and hands-on content.
+ 4. **Diversity:** Yes, there are exceptions, but the majority of events, reviewers, and organizers agree that having a diverse speaker lineup is optimal and results in a better overall event in multiple ways. A topic delivered from a different perspective can often lead to creative breakthroughs for attendees, which is a huge value-add. See item 10 below for more on this.
+ 5. **Talk difficulty level:** We identify All Things Open talks as introductory, intermediate, or advanced. Having a good mix of talk levels ensures everyone in attendance can access applicable content. See item 9 below for more on this, but in general, it's smart to indicate your talk's level, whether or not the CFP requests it.
+
+
+
+### 8\. Stay current on the event's industry or sector
+
+Submitting a proposal on a relevant topic increases the probability your talk will be accepted. But how do you know what topics are of interest, especially if the CFP doesn't spell it out in simple terms? The best way to know what's timely and interesting is to deeply understand the sector the event focuses on.
+
+Yes, this requires time and effort, and it implies you enjoy the sector enough to stay current on it, but it will pay off. This knowledge will result in a higher _sector IQ_, which will be reflected in your topic, title, and abstract. It will be recognized by reviewers and immediately set you apart from others. At All Things Open, we spend the majority of our time reading about and staying current on the "open" space so that we can feature relevant, substantive, and informed content. Submitting a talk that is relevant, substantive, and informed greatly enhances the chance it will be accepted.
+
+### 9\. Describe whether the talk is introductory, intermediate, or advanced
+
+Some CFPs don't ask for this information, but you should offer it anyway. It will make the reviewers and organizer very happy for multiple reasons, including these:
+
+ 1. Unless the event targets attendees with a certain skill or experience level (and most do not), organizers must include content that is appealing to a wide audience, including people of all skill, experience, and expertise levels. Even if an event focuses on a specific type of attendee (perhaps people with higher levels of experience or skills), most want to offer something a little different. Listing the talk level makes this much easier for organizers.
+ 2. News flash: Reviewers and organizers don't know everything and are not experts in every possible topic area. As a result, reviewers will sometimes look for a few keywords or other criteria, and adding the talk level can "seal the deal" and get your talk confirmed.
+
+
+
+### 10\. Tell organizers if you're a member of a historically underrepresented group
+
+A growing number of events are getting better at recognizing the value of diversity and ensuring their speaker lineup reflects it. If you're part of a group that hasn't typically been included in tech events and leadership, look to see if there is a place to indicate that on the submission form. If not, mention it in a conspicuous place somewhere in the abstract. This does not guarantee approval in any way—your proposal must still be well-written and relevant—but it does give reviewers and organizers pertinent information they may value and take into consideration.
+
+### 11\. Don't be ashamed of your credentials or speaking experience if it is light
+
+We talk to a lot of people who would like to deliver a presentation and have a lot to offer, but they never submit a talk because they don't feel they're qualified to speak. _Not true._ Some of the best talks we've seen are from first-time speakers or those very early in their speaking careers. Go ahead and submit the talk, and be honest when discussing your background. Most reviewers and organizers will focus on the substance of the submission over your experience and recognize that new ways of approaching and using technology often come from newbies rather than industry veterans.
+
+One caveat here: It still pays to know yourself. By this, we mean if you absolutely hate public speaking, have no desire to do it, and are only considering submitting a talk due to, for example, pressure from an employer, the talk is not likely to go well. It's better, to be honest, on the frontend than force something you have no desire to do.
+
+### 12\. Consider panel sessions carefully
+
+If you've got an idea for a panel session, please consider it carefully. In more than 10 years of hosting events we've seen some really good panel sessions, but we've seen far more that didn't go so well. Perhaps too many people were on the panel and not everyone had a chance to speak, perhaps a single panel member dominated the entire conversation, or perhaps the moderator didn't keep the dialogue and engagement flowing smoothly. Regardless of the issue, panels have the potential to go very wrong.
+
+That said, panels can still work and deliver a lot of value to attendees. If you do submit a panel session be sure to keep in mind the amount of time allotted for the session and confirm the number of panel members accordingly. Remember, less is always more when it comes to the panel format. Also, be sure the moderator understands the subject matter being discussed and doesn't mind enforcing format parameters and speaking time limits. Finally, let organizers know panel members and the moderator will engage in a pre-conference walk-through/preparation call before the event to ensure a smooth process in front of a live audience. Remember, organizers are well aware panels can be terrific but can also go in the opposite direction and very easily lead to a lot of negative feedback.
+
+### 13\. This is not an opportunity to sell
+
+This is a sensitive topic, but one that absolutely must be mentioned. Over the years we've seen literally hundreds of talks "disqualified" by reviewers because they viewed the talk as a sales pitch. Few things evoke such a visceral response. Yes, there are events, tracks, and session slots where a sales pitch is appropriate (and maybe even required by the company paying your costs). However, make it a priority to know when and where this is appropriate and acceptable. And always, and we mean always, err on the side of making substance the focus of the talk rather than a sales angle.
+
+It might sound like a cliche, but when a talk is delivered effectively with a focus on substance, people will **want** to buy what you're selling. And if you're not selling anything, they'll want to follow you on social media and generally engage with you—because you delivered value to them. Meaning: You gave them something they can apply themselves (education) or because your delivery style was entertaining and engaging. With rare exceptions, always focus any abstract on substance, and the rest will take care of itself.
+
+### Go for it!
+
+We greatly admire and respect anyone who submits a talk for consideration—it takes a lot of time, thought, and courage. Therefore, we go to great lengths to thank everyone who goes through the process; we give free event passes to everyone who applies (regardless of approval or rejection), and we make every effort to host Q&A sessions to provide as much guidance as possible on the front end. Again, the more time and consideration speakers put into the submission process, the easier the lives of reviewers and organizers. We need to make all of this as easy as possible.
+
+While this is not a comprehensive list of best practices, it includes some of the things we think people can benefit from knowing before submitting a talk. There are a lot of people out there with more knowledge and experience, so please share your best tips for submitting conference proposals in the comments, so we can all learn from you.
+
+* * *
+
+_[All Things Open][2] is a universe of platforms and events focusing on open source, open tech, and the open web. It hosts the [All Things Open conference][3], the largest open source/tech/web event on the US East Coast. The conference regularly hosts thousands of attendees and many of the world's most influential companies from a wide variety of industries and sectors. In 2019, nearly 5,000 people attended from 41 US states and 24 countries. Please direct inquiries about ATO to the team at [info@allthingsopen.org][6]._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/tips-conference-proposals
+
+作者:[Todd Lewis][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/toddlewis
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ato2016_checkin_conference.jpg?itok=DJtoSS6t (All Things Open check-in at registration booth)
+[2]: https://www.allthingsopen.org/
+[3]: https://2020.allthingsopen.org/
+[4]: https://2020.allthingsopen.org/call-for-speakers
+[5]: https://www.allthingsopen.org/what-were-looking-for/
+[6]: mailto:info@allthingsopen.org
diff --git a/sources/tech/20200504 Create interactive learning games for kids with open source.md b/sources/tech/20200504 Create interactive learning games for kids with open source.md
new file mode 100644
index 0000000000..f6ade34857
--- /dev/null
+++ b/sources/tech/20200504 Create interactive learning games for kids with open source.md
@@ -0,0 +1,123 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Create interactive learning games for kids with open source)
+[#]: via: (https://opensource.com/article/20/5/jclic-games-kids)
+[#]: author: (Peter Cheer https://opensource.com/users/petercheer)
+
+Create interactive learning games for kids with open source
+======
+Help your students learn by creating fun puzzles and games in JClic, an
+easy Java-based app.
+![Family learning and reading together at night in a room][1]
+
+Schools are closed in many countries around the world to slow the spread of COVID-19. This has suddenly thrown many parents and teachers into homeschooling. Fortunately, there are plenty of educational resources on the internet to use or adapt, although their licenses vary. You can try searching for Creative Commons Open Educational Resources, but if you want to create your own materials, there are many options for that to.
+
+If you want to create digital educational activities with puzzles or tests, two easy-to-use, open source, cross-platform applications that fit the bill are eXeLearning and JClic. My earlier article on [eXeLearning][2] is a good introduction to that program, so here I'll look at [JClic][3]. It is an open source software project for creating various types of interactive activities such as associations, text-based activities, crosswords, and other puzzles with text, graphics, and multimedia elements.
+
+Although it's been around since the 1990s, JClic never developed a large user base in the English-speaking world. It was created in Catalonia by the [Catalan Educational Telematic Network][4] (XTEC).
+
+### About JClic
+
+JClic is a Java-based application that's available in many Linux repositories and can be downloaded from [GitHub][5]. It runs on Linux, macOS, and Windows, but because it is a Java program, you must have a Java runtime environment [installed][6].
+
+The program's interface has not really changed much over the years, even while features have been added or dropped, such as introducing HTML5 export functionality to replace Java Applet technology for web-based deployment. It hasn't needed to change much, though, because it's very effective at what it does.
+
+### Creating a JClic project
+
+Many teachers from many countries have used JClic to create interactive materials for a wide variety of ability levels, subjects, languages, and curricula. Some of these materials have been collected in an [downloadable activities library][7]. Although few activities are in English, you can get a sense of the possibilities JClic offers.
+
+As JClic has a visual, point-and-click program interface, it is easy enough to learn that a new user can quickly concentrate on content creation. [Documentation][8] is available on GitHub.
+
+The screenshots below are from one of the JClic projects I created to teach basic Excel skills to learners in Papua New Guinea.
+
+A JClic project is created in its authoring tool and consists of the following four elements:
+
+#### 1\. Metadata about the project
+
+![JClic metadata][9]
+
+#### 2\. A library of the graphical and other resources it uses
+
+![JClic media][10]
+
+#### 3\. A series of one or more activities
+
+![JClic activities][11]
+
+JClic can produce seven different activity types:
+
+ * Associations where the user discovers the relationships between two information sets
+ * Memory games where the user discovers pairs of identical elements or relations (which are hidden) between them
+ * Exploration activities involving the identification and information, based on a single Information set
+ * Puzzles where the user reconstructs information that is initially presented in a disordered form; the activity can include graphics, text, sound, or a combination of them
+ * Written-response activities that are solved by writing text, either a single word or a sentence
+ * Text activities that are based on words, phrases, letters, and paragraphs of text that need to be completed, understood, corrected, or ordered; these activities can contain images and windows with active content
+ * Word searches and crosswords
+
+
+
+Because of variants in the activities, there are 16 possible activity types.
+
+#### 4\. A timeline to sequence the activities
+
+![JClic timeline][12]
+
+### Using JClic content
+
+Projects can run in JClic's player (part of the Java application you used to create the project), or they can be exported to HTML5 so they can run in a web browser.
+
+The one thing I don't like about JClic is that its default HTML5 export function assumes you'll be online when running a project. If you want a project to work offline as needed, you must download a compiled and minified HTML5 player from [Github][13], and place it in the same folder as your JClic project.
+
+Next, open the **index.html** file in a text editor and replace this line:
+
+
+```
+``
+```
+
+With:
+
+
+```
+``
+```
+
+Now the HTML5 version of your project runs in a web browser, whether the user is online or not.
+
+JClic also provides a reports function that can store test scores in an ODBC-compliant database. I have not explored this feature, as my tests and puzzles are mostly used for self-assessment and to prompt reflection by the learner, rather than as part of a formal scheme, so the scores are not very important. If you would like to learn about it, there is [documentation][14] on running JClic Reports Server with Tomcat and MySQL (or [mariaDB][15]).
+
+### Conclusion
+
+JClic offers a wide range of activity types that provide plenty of room to be creative in designing content to fit your subject area and type of learner. JClic is a valuable addition for anyone who needs a quick and easy way to develop educational resources.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/jclic-games-kids
+
+作者:[Peter Cheer][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petercheer
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/family_learning_kids_night_reading.png?itok=6K7sJVb1 (Family learning and reading together at night in a room)
+[2]: https://opensource.com/article/18/5/exelearning
+[3]: https://clic.xtec.cat/legacy/en/jclic/index.html
+[4]: https://clic.xtec.cat/legacy/en/index.html
+[5]: https://github.com/projectestac/jclic
+[6]: https://adoptopenjdk.net/installation.html
+[7]: https://clic.xtec.cat/repo/
+[8]: https://github.com/projectestac/jclic/wiki/JClic_Guide
+[9]: https://opensource.com/sites/default/files/uploads/metadata.png (JClic metadata)
+[10]: https://opensource.com/sites/default/files/uploads/media.png (JClic media)
+[11]: https://opensource.com/sites/default/files/uploads/activities.png (JClic activities)
+[12]: https://opensource.com/sites/default/files/uploads/sequence.png (JClic timeline)
+[13]: http://projectestac.github.io/jclic.js/
+[14]: https://github.com/projectestac/jclic/wiki/Jclic-Reports-Server-with-Tomcat-and-MySQL-on-Ubuntu
+[15]: https://mariadb.org/
diff --git a/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md b/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md
new file mode 100644
index 0000000000..d28f0daee0
--- /dev/null
+++ b/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md
@@ -0,0 +1,150 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Define and optimize data partitions in Apache Cassandra)
+[#]: via: (https://opensource.com/article/20/5/apache-cassandra)
+[#]: author: (Anil Inamdar https://opensource.com/users/anil-inamdar)
+
+Define and optimize data partitions in Apache Cassandra
+======
+Apache Cassandra is built for speed and scalability; here's how to get
+the most out of those benefits.
+![Person standing in front of a giant computer screen with numbers, data][1]
+
+Apache Cassandra is a database. But it's not just any database; it's a replicating database designed and tuned for scalability, high availability, low-latency, and performance. Cassandra can help your data survive regional outages, hardware failure, and what many admins would consider excessive amounts of data.
+
+Having a thorough command of data partitions enables you to achieve superior Cassandra cluster design, performance, and scalability. In this article, I'll examine how to define partitions and how Cassandra uses them, as well as the most critical best practices and known issues you ought to be aware of.
+
+To set the scene: partitions are chunks of data that serve as the atomic unit for key database-related functions like data distribution, replication, and indexing. Distributed data systems commonly distribute incoming data into these partitions, performing the partitioning with simple mathematical functions such as identity or hashing, and using a "partition key" to group data by partition. For example, consider a case where server logs arrive as incoming data. Using the "identity" partitioning function and the timestamps of each log (rounded to the hour value) for the partition key, we can partition this data such that each partition holds one hour of the logs.
+
+### Data partitions in Cassandra
+
+Cassandra operates as a distributed system and adheres to the data partitioning principles described above. With Cassandra, data partitioning relies on an algorithm configured at the cluster level, and a partition key configured at the table level.
+
+![Cassandra data partition][2]
+
+Cassandra Query Language (CQL) uses the familiar SQL table, row, and column terminologies. In the example diagram above, the table configuration includes the partition key within its primary key, with the format: Primary Key = Partition Key + [Clustering Columns].
+
+A primary key in Cassandra represents both a unique data partition and a data arrangement inside a partition. Data arrangement information is provided by optional clustering columns. Each unique partition key represents a set of table rows managed in a server, as well as all servers that manage its replicas.
+
+### Defining primary keys in CQL
+
+The following four examples demonstrate how a primary key can be represented in CQL syntax. The sets of rows produced by these definitions are generally considered a partition.
+
+#### Definition 1 (partition key: log_hour, clustering columns: none)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP PRIMARYKEY,
+ log_level text,
+ message text,
+ server text
+ )
+```
+
+Here, all rows that share a **log_hour** go into the same partition.
+
+#### Definition 2 (partition key: log_hour, clustering columns: log_level)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY (log_hour, log_level)
+ )
+```
+
+This definition uses the same partition key as Definition 1, but here all rows in each partition are arranged in ascending order by **log_level**.
+
+#### Definition 3 (partition key: log_hour, server, clustering columns: none)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY ((log_hour, server))
+ )
+```
+
+In this definition, all rows share a **log_hour** for each distinct **server** as a single partition.
+
+#### Definition 4 (partition key: log_hour, server, clustering columns: log_level)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY ((log_hour, server),log_level)
+ )WITH CLUSTERING ORDER BY (column3 DESC);
+```
+
+This definition uses the same partition as Definition 3 but arranges the rows within a partition in descending order by **log_level**.
+
+### How Cassandra uses the partition key
+
+Cassandra relies on the partition key to determine which node to store data on and where to locate data when it's needed. Cassandra performs these read and write operations by looking at a partition key in a table, and using tokens (a long value out of range -2^63 to +2^63-1) for data distribution and indexing. These tokens are mapped to partition keys by using a partitioner, which applies a partitioning function that converts any partition key to a token. Through this token mechanism, every node of a Cassandra cluster owns a set of data partitions. The partition key then enables data indexing on each node.
+
+![Cassandra cluster with 3 nodes and token-based ownership][3]
+
+A Cassandra cluster with three nodes and token-based ownership. This is a simplistic representation: the actual implementation uses [Vnodes][4].
+
+### Data partition impacts on Cassandra clusters
+
+Careful partition key design is crucial to achieving the ideal partition size for the use case. Getting it right allows for even data distribution and strong I/O performance. Partition size has several impacts on Cassandra clusters you need to be aware of:
+
+ * Read performance—In order to find partitions in SSTables files on disk, Cassandra uses data structures that include caches, indexes, and index summaries. Partitions that are too large reduce the efficiency of maintaining these data structures – and will negatively impact performance as a result. Cassandra releases have made strides in this area: in particular, version 3.6 and above of the Cassandra engine introduce storage improvements that deliver better performance for large partitions and resilience against memory issues and crashes.
+ * Memory usage— Large partitions place greater pressure on the JVM heap, increasing its size while also making the garbage collection mechanism less efficient.
+ * Cassandra repairs—Large partitions make it more difficult for Cassandra to perform its repair maintenance operations, which keep data consistent by comparing data across replicas.
+ * Tombstone eviction—Not as mean as it sounds, Cassandra uses unique markers known as "tombstones" to mark data for deletion. Large partitions can make that deletion process more difficult if there isn't an appropriate data deletion pattern and compaction strategy in place.
+
+
+
+While these impacts may make it tempting to simply design partition keys that yield especially small partitions, the data access pattern is also highly influential on ideal partition size (for more information, read this in-depth guide to [Cassandra data modeling][5]). The data access pattern can be defined as how a table is queried, including all of the table's **select** queries. Ideally, CQL select queries should have just one partition key in the **where** clause—that is to say, Cassandra is most efficient when queries can get needed data from a single partition, instead of many smaller ones.
+
+### Best practices for partition key design
+
+Following best practices for partition key design helps you get to an ideal partition size. As a rule of thumb, the maximum partition size in Cassandra should stay under 100MB. Ideally, it should be under 10MB. While Cassandra versions 3.6 and newer make larger partition sizes more viable, careful testing and benchmarking must be performed for each workload to ensure a partition key design supports desired cluster performance.
+
+Specifically, these best practices should be considered as part of any partition key design:
+
+ * The goal for a partition key must be to fit an ideal amount of data into each partition for supporting the needs of its access pattern.
+ * A partition key should disallow unbounded partitions: those that may grow indefinitely in size over time. For instance, in the **server_logs** examples above, using the server column as a partition key would create unbounded partitions as the number of server logs continues to increase. In contrast, using **log_hour** limits each partition to an hour of data.
+ * A partition key should also avoid creating a partition skew, in which partitions grow unevenly, and some are able to grow without limit over time. In the **server_logs** examples, using the server column in a scenario where one server generates considerably more logs than others would produce a partition skew. To avoid this, a useful technique is to introduce another attribute from the table to force an even distribution, even if it's necessary to create a dummy column to do so.
+ * It's helpful to partition time-series data with a partition key that uses a time element as well as other attributes. This protects against unbounded partitions, enables access patterns to use the time attribute in querying specific data, and allows for time-bound data deletion. The examples above each demonstrate this by using the **log_hour** time attribute.
+
+
+
+Several tools are available to help test, analyze, and monitor Cassandra partitions to check that a chosen schema is efficient and effective. By carefully designing partition keys to align well with the data and needs of the solution at hand, and following best practices to optimize partition size, you can utilize data partitions that more fully deliver on the scalability and performance potential of a Cassandra deployment.
+
+Dani and Jon will give a three hour tutorial at OSCON this year called: Becoming friends with...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/apache-cassandra
+
+作者:[Anil Inamdar][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/anil-inamdar
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data)
+[2]: https://opensource.com/sites/default/files/uploads/apache_cassandra_1_0.png (Cassandra data partition)
+[3]: https://opensource.com/sites/default/files/uploads/apache_cassandra_2_0.png (Cassandra cluster with 3 nodes and token-based ownership)
+[4]: https://www.instaclustr.com/cassandra-vnodes-how-many-should-i-use/
+[5]: https://www.instaclustr.com/resource/6-step-guide-to-apache-cassandra-data-modelling-white-paper/
diff --git a/sources/tech/20200504 Understanding systemd at startup on Linux.md b/sources/tech/20200504 Understanding systemd at startup on Linux.md
new file mode 100644
index 0000000000..2d0a5ef7b6
--- /dev/null
+++ b/sources/tech/20200504 Understanding systemd at startup on Linux.md
@@ -0,0 +1,445 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Understanding systemd at startup on Linux)
+[#]: via: (https://opensource.com/article/20/5/systemd-startup)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Understanding systemd at startup on Linux
+======
+systemd's startup provides important clues to help you solve problems
+when they occur.
+![People at the start line of a race][1]
+
+In [_Learning to love systemd_][2], the first article in this series, I looked at systemd's functions and architecture and the controversy around its role as a replacement for the old SystemV init program and startup scripts. In this second article, I'll start exploring the files and tools that manage the Linux startup sequence. I'll explain the systemd startup sequence, how to change the default startup target (runlevel in SystemV terms), and how to manually switch to a different target without going through a reboot.
+
+I'll also look at two important systemd tools. The first is the **systemctl** command, which is the primary means of interacting with and sending commands to systemd. The second is **journalctl**, which provides access to the systemd journals that contain huge amounts of system history data such as kernel and service messages (both informational and error messages).
+
+Be sure to use a non-production system for testing and experimentation in this and future articles. Your test system needs to have a GUI desktop (such as Xfce, LXDE, Gnome, KDE, or another) installed.
+
+I wrote in my previous article that I planned to look at creating a systemd unit and adding it to the startup sequence in this article. Because this article became longer than I anticipated, I will hold that for the next article in this series.
+
+### Exploring Linux startup with systemd
+
+Before you can observe the startup sequence, you need to do a couple of things to make the boot and startup sequences open and visible. Normally, most distributions use a startup animation or splash screen to hide the detailed messages that would otherwise be displayed during a Linux host's startup and shutdown. This is called the Plymouth boot screen on Red Hat-based distros. Those hidden messages can provide a great deal of information about startup and shutdown to a sysadmin looking for information to troubleshoot a bug or to just learn about the startup sequence. You can change this using the GRUB (Grand Unified Boot Loader) configuration.
+
+The main GRUB configuration file is **/boot/grub2/grub.cfg**, but, because this file can be overwritten when the kernel version is updated, you do not want to change it. Instead, modify the **/etc/default/grub** file, which is used to modify the default settings of **grub.cfg**.
+
+Start by looking at the current, unmodified version of the **/etc/default/grub** file:
+
+
+```
+[root@testvm1 ~]# cd /etc/default ; cat 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="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
+lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
+testvm1/usr rhgb quiet"
+GRUB_DISABLE_RECOVERY="true"
+[root@testvm1 default]#
+```
+
+Chapter 6 of the [GRUB documentation][3] contains a list of all the possible entries in the **/etc/default/grub** file, but I focus on the following:
+
+ * I change **GRUB_TIMEOUT**, the number of seconds for the GRUB menu countdown, from five to 10 to give a bit more time to respond to the GRUB menu before the countdown hits zero.
+ * I delete the last two parameters on **GRUB_CMDLINE_LINUX**, which lists the command-line parameters that are passed to the kernel at boot time. One of these parameters, **rhgb** stands for Red Hat Graphical Boot, and it displays the little Fedora icon animation during the kernel initialization instead of showing boot-time messages. The other, the **quiet** parameter, prevents displaying the startup messages that document the progress of the startup and any errors that occur. I delete both **rhgb** and **quiet** because sysadmins need to see these messages. If something goes wrong during boot, the messages displayed on the screen can point to the cause of the problem.
+
+
+
+After you make these changes, your GRUB file will look like:
+
+
+```
+[root@testvm1 default]# cat grub
+GRUB_TIMEOUT=10
+GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
+GRUB_DEFAULT=saved
+GRUB_DISABLE_SUBMENU=true
+GRUB_TERMINAL_OUTPUT="console"
+GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
+lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
+testvm1/usr"
+GRUB_DISABLE_RECOVERY="false"
+[root@testvm1 default]#
+```
+
+The **grub2-mkconfig** program generates the **grub.cfg** configuration file using the contents of the **/etc/default/grub** file to modify some of the default GRUB settings. The **grub2-mkconfig** program sends its output to **STDOUT**. It has a **-o** option that allows you to specify a file to send the datastream to, but it is just as easy to use redirection. Run the following command to update the **/boot/grub2/grub.cfg** configuration file:
+
+
+```
+[root@testvm1 grub2]# grub2-mkconfig > /boot/grub2/grub.cfg
+Generating grub configuration file ...
+Found linux image: /boot/vmlinuz-4.18.9-200.fc28.x86_64
+Found initrd image: /boot/initramfs-4.18.9-200.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-4.17.14-202.fc28.x86_64
+Found initrd image: /boot/initramfs-4.17.14-202.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-4.16.3-301.fc28.x86_64
+Found initrd image: /boot/initramfs-4.16.3-301.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-0-rescue-7f12524278bd40e9b10a085bc82dc504
+Found initrd image: /boot/initramfs-0-rescue-7f12524278bd40e9b10a085bc82dc504.img
+done
+[root@testvm1 grub2]#
+```
+
+Reboot your test system to view the startup messages that would otherwise be hidden behind the Plymouth boot animation. But what if you need to view the startup messages and have not disabled the Plymouth boot animation? Or you have, but the messages stream by too fast to read? (Which they do.)
+
+There are a couple of options, and both involve log files and systemd journals—which are your friends. You can use the **less** command to view the contents of the **/var/log/messages** file. This file contains boot and startup messages as well as messages generated by the operating system during normal operation. You can also use the **journalctl** command without any options to view the systemd journal, which contains essentially the same information:
+
+
+```
+[root@testvm1 grub2]# journalctl
+\-- Logs begin at Sat 2020-01-11 21:48:08 EST, end at Fri 2020-04-03 08:54:30 EDT. --
+Jan 11 21:48:08 f31vm.both.org kernel: Linux version 5.3.7-301.fc31.x86_64 ([mockbuild@bkernel03.phx2.fedoraproject.org][4]) (gcc version 9.2.1 20190827 (Red Hat 9.2.1-1) (GCC)) #1 SMP Mon Oct >
+Jan 11 21:48:08 f31vm.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.3.7-301.fc31.x86_64 root=/dev/mapper/VG01-root ro resume=/dev/mapper/VG01-swap rd.lvm.lv=VG01/root rd>
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-provided physical RAM map:
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000dffeffff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000dfff0000-0x00000000dfffffff] ACPI data
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000100000000-0x000000041fffffff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: NX (Execute Disable) protection: active
+Jan 11 21:48:08 f31vm.both.org kernel: SMBIOS 2.5 present.
+Jan 11 21:48:08 f31vm.both.org kernel: DMI: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
+Jan 11 21:48:08 f31vm.both.org kernel: Hypervisor detected: KVM
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: Using msrs 4b564d01 and 4b564d00
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: cpu 0, msr 30ae01001, primary cpu clock
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: using sched offset of 8250734066 cycles
+Jan 11 21:48:08 f31vm.both.org kernel: clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
+Jan 11 21:48:08 f31vm.both.org kernel: tsc: Detected 2807.992 MHz processor
+Jan 11 21:48:08 f31vm.both.org kernel: e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
+Jan 11 21:48:08 f31vm.both.org kernel: e820: remove [mem 0x000a0000-0x000fffff] usable
+<snip>
+```
+
+I truncated this datastream because it can be hundreds of thousands or even millions of lines long. (The journal listing on my primary workstation is 1,188,482 lines long.) Be sure to try this on your test system. If it has been running for some time—even if it has been rebooted many times—huge amounts of data will be displayed. Explore this journal data because it contains a lot of information that can be very useful when doing problem determination. Knowing what this data looks like for a normal boot and startup can help you locate problems when they occur.
+
+I will discuss systemd journals, the **journalctl** command, and how to sort through all of that data to find what you want in more detail in a future article in this series.
+
+After GRUB loads the kernel into memory, it must first extract itself from the compressed version of the file before it can perform any useful work. After the kernel has extracted itself and started running, it loads systemd and turns control over to it.
+
+This is the end of the boot process. At this point, the Linux kernel and systemd are running but unable to perform any productive tasks for the end user because nothing else is running, there's no shell to provide a command line, no background processes to manage the network or other communication links, and nothing that enables the computer to perform any productive function.
+
+Systemd can now load the functional units required to bring the system up to a selected target run state.
+
+### Targets
+
+A systemd target represents a Linux system's current or desired run state. Much like SystemV start scripts, targets define the services that must be present for the system to run and be active in that state. Figure 1 shows the possible run-state targets of a Linux system using systemd. As seen in the first article of this series and in the systemd bootup man page (man bootup), there are other intermediate targets that are required to enable various necessary services. These can include **swap.target**, **timers.target**, **local-fs.target**, and more. Some targets (like **basic.target**) are used as checkpoints to ensure that all the required services are up and running before moving on to the next-higher level target.
+
+Unless otherwise changed at boot time in the GRUB menu, systemd always starts the **default.target**. The **default.target** file is a symbolic link to the true target file. For a desktop workstation, this is typically going to be the **graphical.target**, which is equivalent to runlevel 5 in SystemV. For a server, the default is more likely to be the **multi-user.target**, which is like runlevel 3 in SystemV. The **emergency.target** file is similar to single-user mode. Targets and services are systemd units.
+
+The following table, which I included in the previous article in this series, compares the systemd targets with the old SystemV startup runlevels. The systemd target aliases are provided by systemd for backward compatibility. The target aliases allow scripts—and sysadmins—to use SystemV commands like **init 3** to change runlevels. Of course, the SystemV commands are forwarded to systemd for interpretation and execution.
+
+**systemd targets** | **SystemV runlevel** | **target aliases** | **Description**
+---|---|---|---
+default.target | | | This target is always aliased with a symbolic link to either **multi-user.target** or **graphical.target**. systemd always uses the **default.target** to start the system. The **default.target** should never be aliased to **halt.target**, **poweroff.target**, or **reboot.target**.
+graphical.target | 5 | runlevel5.target | **Multi-user.target** with a GUI
+| 4 | runlevel4.target | Unused. Runlevel 4 was identical to runlevel 3 in the SystemV world. This target could be created and customized to start local services without changing the default **multi-user.target**.
+multi-user.target | 3 | runlevel3.target | All services running, but command-line interface (CLI) only
+| 2 | runlevel2.target | Multi-user, without NFS, but all other non-GUI services running
+rescue.target | 1 | runlevel1.target | A basic system, including mounting the filesystems with only the most basic services running and a rescue shell on the main console
+emergency.target | S | | Single-user mode—no services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.
+halt.target | | | Halts the system without powering it down
+reboot.target | 6 | runlevel6.target | Reboot
+poweroff.target | 0 | runlevel0.target | Halts the system and turns the power off
+
+Each target has a set of dependencies described in its configuration file. systemd starts the required dependencies, which are the services required to run the Linux host at a specific level of functionality. When all of the dependencies listed in the target configuration files are loaded and running, the system is running at that target level. If you want, you can review the systemd startup sequence and runtime targets in the first article in this series, [_Learning to love systemd_][2].
+
+### Exploring the current target
+
+Many Linux distributions default to installing a GUI desktop interface so that the installed systems can be used as workstations. I always install from a Fedora Live boot USB drive with an Xfce or LXDE desktop. Even when I'm installing a server or other infrastructure type of host (such as the ones I use for routers and firewalls), I use one of these installations that installs a GUI desktop.
+
+I could install a server without a desktop (and that would be typical for data centers), but that does not meet my needs. It is not that I need the GUI desktop itself, but the LXDE installation includes many of the other tools I use that are not in a default server installation. This means less work for me after the initial installation.
+
+But just because I have a GUI desktop does not mean it makes sense to use it. I have a 16-port KVM that I can use to access the KVM interfaces of most of my Linux systems, but the vast majority of my interaction with them is via a remote SSH connection from my primary workstation. This way is more secure and uses fewer system resources to run **multi-user.target** compared to **graphical.target.**
+
+To begin, check the default target to verify that it is the **graphical.target**:
+
+
+```
+[root@testvm1 ~]# systemctl get-default
+graphical.target
+[root@testvm1 ~]#
+```
+
+Now verify the currently running target. It should be the same as the default target. You can still use the old method, which displays the old SystemV runlevels. Note that the previous runlevel is on the left; it is **N** (which means None), indicating that the runlevel has not changed since the host was booted. The number 5 indicates the current target, as defined in the old SystemV terminology:
+
+
+```
+[root@testvm1 ~]# runlevel
+N 5
+[root@testvm1 ~]#
+```
+
+Note that the runlevel man page indicates that runlevels are obsolete and provides a conversion table.
+
+You can also use the systemd method. There is no one-line answer here, but it does provide the answer in systemd terms:
+
+
+```
+[root@testvm1 ~]# systemctl list-units --type target
+UNIT LOAD ACTIVE SUB DESCRIPTION
+basic.target loaded active active Basic System
+cryptsetup.target loaded active active Local Encrypted Volumes
+getty.target loaded active active Login Prompts
+graphical.target loaded active active Graphical Interface
+local-fs-pre.target loaded active active Local File Systems (Pre)
+local-fs.target loaded active active Local File Systems
+multi-user.target loaded active active Multi-User System
+network-online.target loaded active active Network is Online
+network.target loaded active active Network
+nfs-client.target loaded active active NFS client services
+nss-user-lookup.target loaded active active User and Group Name Lookups
+paths.target loaded active active Paths
+remote-fs-pre.target loaded active active Remote File Systems (Pre)
+remote-fs.target loaded active active Remote File Systems
+rpc_pipefs.target loaded active active rpc_pipefs.target
+slices.target loaded active active Slices
+sockets.target loaded active active Sockets
+sshd-keygen.target loaded active active sshd-keygen.target
+swap.target loaded active active Swap
+sysinit.target loaded active active System Initialization
+timers.target loaded active active Timers
+
+LOAD = Reflects whether the unit definition was properly loaded.
+ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
+SUB = The low-level unit activation state, values depend on unit type.
+
+21 loaded units listed. Pass --all to see loaded but inactive units, too.
+To show all installed unit files use 'systemctl list-unit-files'.
+```
+
+This shows all of the currently loaded and active targets. You can also see the **graphical.target** and the **multi-user.target**. The **multi-user.target** is required before the **graphical.target** can be loaded. In this example, the **graphical.target** is active.
+
+### Switching to a different target
+
+Making the switch to the **multi-user.target** is easy:
+
+
+```
+`[root@testvm1 ~]# systemctl isolate multi-user.target`
+```
+
+The display should now change from the GUI desktop or login screen to a virtual console. Log in and list the currently active systemd units to verify that **graphical.target** is no longer running:
+
+
+```
+`[root@testvm1 ~]# systemctl list-units --type target`
+```
+
+Be sure to use the **runlevel** command to verify that it shows both previous and current "runlevels":
+
+
+```
+[root@testvm1 ~]# runlevel
+5 3
+```
+
+### Changing the default target
+
+Now, change the default target to the **multi-user.target** so that it will always boot into the **multi-user.target** for a console command-line interface rather than a GUI desktop interface. As the root user on your test host, change to the directory where the systemd configuration is maintained and do a quick listing:
+
+
+```
+[root@testvm1 ~]# cd /etc/systemd/system/ ; ll
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 basic.target.wants
+<snip>
+lrwxrwxrwx. 1 root root 36 Aug 13 16:23 default.target -> /lib/systemd/system/graphical.target
+lrwxrwxrwx. 1 root root 39 Apr 25 2018 display-manager.service -> /usr/lib/systemd/system/lightdm.service
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 getty.target.wants
+drwxr-xr-x. 2 root root 4096 Aug 18 10:16 graphical.target.wants
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 local-fs.target.wants
+drwxr-xr-x. 2 root root 4096 Oct 30 16:54 multi-user.target.wants
+<snip>
+[root@testvm1 system]#
+```
+
+I shortened this listing to highlight a few important things that will help explain how systemd manages the boot process. You should be able to see the entire list of directories and links on your virtual machine.
+
+The **default.target** entry is a symbolic link (symlink, soft link) to the directory **/lib/systemd/system/graphical.target**. List that directory to see what else is there:
+
+
+```
+`[root@testvm1 system]# ll /lib/systemd/system/ | less`
+```
+
+You should see files, directories, and more links in this listing, but look specifically for **multi-user.target** and **graphical.target**. Now display the contents of **default.target**, which is a link to **/lib/systemd/system/graphical.target**:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Graphical Interface
+Documentation=man:systemd.special(7)
+Requires=multi-user.target
+Wants=display-manager.service
+Conflicts=rescue.service rescue.target
+After=multi-user.target rescue.service rescue.target display-manager.service
+AllowIsolate=yes
+[root@testvm1 system]#
+```
+
+This link to the **graphical.target** file describes all of the prerequisites and requirements that the graphical user interface requires. I will explore at least some of these options in the next article in this series.
+
+To enable the host to boot to multi-user mode, you need to delete the existing link and create a new one that points to the correct target. Make the [PWD][5] **/etc/systemd/system**, if it is not already:
+
+
+```
+[root@testvm1 system]# rm -f default.target
+[root@testvm1 system]# ln -s /lib/systemd/system/multi-user.target default.target
+```
+
+List the **default.target** link to verify that it links to the correct file:
+
+
+```
+[root@testvm1 system]# ll default.target
+lrwxrwxrwx 1 root root 37 Nov 28 16:08 default.target -> /lib/systemd/system/multi-user.target
+[root@testvm1 system]#
+```
+
+If your link does not look exactly like this, delete it and try again. List the content of the **default.target** link:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Multi-User System
+Documentation=man:systemd.special(7)
+Requires=basic.target
+Conflicts=rescue.service rescue.target
+After=basic.target rescue.service rescue.target
+AllowIsolate=yes
+[root@testvm1 system]#
+```
+
+The **default.target**—which is really a link to the **multi-user.target** at this point—now has different requirements in the **[Unit]** section. It does not require the graphical display manager.
+
+Reboot. Your virtual machine should boot to the console login for virtual console 1, which is identified on the display as tty1. Now that you know how to change the default target, change it back to the **graphical.target** using a command designed for the purpose.
+
+First, check the current default target:
+
+
+```
+[root@testvm1 ~]# systemctl get-default
+multi-user.target
+[root@testvm1 ~]# systemctl set-default graphical.target
+Removed /etc/systemd/system/default.target.
+Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/graphical.target.
+[root@testvm1 ~]#
+```
+
+Enter the following command to go directly to the **graphical.target** and the display manager login page without having to reboot:
+
+
+```
+`[root@testvm1 system]# systemctl isolate default.target`
+```
+
+I do not know why the term "isolate" was chosen for this sub-command by systemd's developers. My research indicates that it may refer to running the specified target but "isolating" and terminating all other targets that are not required to support the target. However, the effect is to switch targets from one run target to another—in this case, from the multi-user target to the graphical target. The command above is equivalent to the old init 5 command in SystemV start scripts and the init program.
+
+Log into the GUI desktop, and verify that it is working as it should.
+
+### Summing up
+
+This article explored the Linux systemd startup sequence and started to explore two important systemd tools, **systemctl** and **journalctl**. It also explained how to switch from one target to another and to change the default target.
+
+The next article in this series will create a new systemd unit and configure it to run during startup. It will also look at some of the configuration options that help determine where in the sequence a particular unit will start, for example, after networking is up and running.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][6] [to systemd][6]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][7] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][8]'s [description of systemd][9].
+ * [Linux.com][10]'s "More systemd fun" offers more advanced systemd [information and tips][11].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][12]
+ * [systemd for Administrators, Part I][13]
+ * [systemd for Administrators, Part II][14]
+ * [systemd for Administrators, Part III][15]
+ * [systemd for Administrators, Part IV][16]
+ * [systemd for Administrators, Part V][17]
+ * [systemd for Administrators, Part VI][18]
+ * [systemd for Administrators, Part VII][19]
+ * [systemd for Administrators, Part VIII][20]
+ * [systemd for Administrators, Part IX][21]
+ * [systemd for Administrators, Part X][22]
+ * [systemd for Administrators, Part XI][23]
+
+
+
+Alison Chiaken, a Linux kernel and systems programmer at Mentor Graphics, offers a preview of her...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-startup
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/start_line.jpg?itok=9reaaW6m (People at the start line of a race)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: http://www.gnu.org/software/grub/manual/grub
+[4]: mailto:mockbuild@bkernel03.phx2.fedoraproject.org
+[5]: https://en.wikipedia.org/wiki/Pwd
+[6]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[7]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[8]: http://Freedesktop.org
+[9]: http://www.freedesktop.org/wiki/Software/systemd
+[10]: http://Linux.com
+[11]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[12]: http://0pointer.de/blog/projects/systemd.html
+[13]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[14]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[15]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[16]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[17]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[18]: http://0pointer.de/blog/projects/changing-roots
+[19]: http://0pointer.de/blog/projects/blame-game.html
+[20]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[21]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[22]: http://0pointer.de/blog/projects/instances.html
+[23]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200505 8 open source video games to play.md b/sources/tech/20200505 8 open source video games to play.md
new file mode 100644
index 0000000000..ac0577d96b
--- /dev/null
+++ b/sources/tech/20200505 8 open source video games to play.md
@@ -0,0 +1,116 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (8 open source video games to play)
+[#]: via: (https://opensource.com/article/20/5/open-source-fps-games)
+[#]: author: (Aman Gaur https://opensource.com/users/amangaur)
+
+8 open source video games to play
+======
+These games are fun and free to play, a way to connect with friends, and
+an opportunity to make an old favorite even better.
+![Gaming on a grid with penguin pawns][1]
+
+Video games are a big business. That's great for the industry's longevity—not to mention for all the people working in programming and graphics. But it can take a lot of work, time, and money to keep up with all the latest gaming crazes. If you feel like playing a few quick rounds of a video game without investing in a new console or game franchise, then you'll be happy to know that there are plenty of open source combat games you can download, play, share, and even modify (if you're inclined to programming) for free.
+
+First-person shooters (FPS) are one of the most popular categories of video games. They are centered around the perspective of the protagonist (the player), and they often offer weapon-based advancement. As you get better at the game, you survive longer, you get better weapons, and you increase your power. FPS games have a distinct look and feel, which is reflected in the category's name: players see everything—their weapons and the game world—in first person, as if they're looking through their player character's eyes.
+
+If you want to give one a try, check out the following eight great open source FPS games.
+
+### Xonotic
+
+![Xonotic][2]
+
+[Xonotic][3] is a fast-paced, arena-based FPS game. It is a popular game in the open source world. One reason could be the fact that it has never been a mainstream game. It offers a variety of weapons and enemies that are thrown right at you mercilessly from the start. Demanding quick action and response, it is an experience that will keep you on the edge of your seats. The game is available under the GPLv3+ license.
+
+### Wolfenstein Enemy Territory
+
+![Wolfenstein Enemy Territory][4]
+
+Wolfenstein has been a major franchise in gaming for many years. If you are a fan of gore and glory, then you've probably already heard of this game (if not, you'll love it once you try it). [Wolfenstein Enemy Territory][5] is an early iteration of the popular World War II game. It became free to play in 2003, and its [source code][6] is provided under the GPLv3. To play, however, you must own the game data (or recreate it yourself) separately (which remains under its original EULA).
+
+### Doom
+
+![Doom][7]
+
+[Doom][8] is a wildly popular game that was also an early example of games on Linux—way back in 2004. There are many iterations of the game, many of which have been released as open source. The game is about acquiring a teleportation device that's been captured by demons, so the violence, while gory, is low on realism. The source code for the game was provided under the GPL, but many versions require that you own the game for the game assets. There are dozens of ports and adaptations, including [Freedoom][9] (with free assets), [Dhewm3][10], [RBDoom-3-BFG][11], and many more. Try a few and pick your favorite!
+
+### Smokin' Guns
+
+![Smokin' Guns][12]
+
+If you're a fan of the Old West and six-shooters, this FPS is for you. From cowboys to gunslingers and with a captivating background score, [Smokin' Guns][13] has it all. It's a semi-realistic simulation of the old spaghetti western. On your way through the game, you face multiple enemies and get multiple weapons, so there's always the promise of excitement and danger around the corner. The game is free and open source under the terms of the GPLv2.
+
+### Nexuiz
+
+![Nexuiz][14]
+
+[Nexuiz][15] (classic) is another great FPS that's free to play on multiple platforms. The game is based on the Quake engine and has been made open source under the GNU GPLv2. The game offers multiple modes, including online, LAN party, and bot training. The game features sophisticated weapons and fast action. It's brutal and exciting, with an objective: kill as many opponents as possible before they get you.
+
+Note that the open source version of Nexuiz is not the same as the version built on CryEngine3 that is sold on Steam.
+
+### .kkrieger
+
+![kkrieger][16]
+
+[.Kkrieger][17] was developed in 2004 by .theprodukkt, a German demogroup. The game was developed using an unreleased (at the time) engine known as Werkkzeug. This game might feel a little slow to many, but it still offers an intense experience. The approaching enemies are slow, but their sheer number makes it confusing to know which one to take down first. It's an onslaught, and you have to shoot through layers of enemies before you reach the final boss. It was released in a rather raw form on [GitHub][18] by its creators under a BSD license with some public domain components.
+
+### Warsow
+
+![Warsow][19]
+
+If you've ever played Borderlands 2, then imagine [Warsow][20] as an arena-style Borderlands. The game is built on a modernized Quake II engine, and its plot takes a simple approach: Kill as many opponents as possible. The team with the most number of kills wins. Despite its simplicity, it features amazing weaponry and lots of great trick moves, like circle jumping, bunny hopping, double jumping, ramp sliding, and so on. It makes for an engaging multiplayer session, and it's been recognized by multiple online leagues as a worthy game for their competitions. Get the source code from [GitHub][21] or install the game from your software repository.
+
+### World of Padman
+
+![World of Padman][22]
+
+[The World of Padman][23] may be the last game on this list, but it's one of the most unique. Designed by PadWorld Entertainment, World of Padman takes a different twist graphically and introduces you to quirky and whimsical characters in a colorful (albeit cartoonishly violent) world. It's based on the ioquake3 engine, and its unique style and uproarious gameplay have earned it a featured place in multiple gaming magazines. You can download the source code from [GitHub][24].
+
+### Give one a shot
+
+A game that becomes open source can act as a template for something great, whether it's a wholly open source version of an old classic, a remix of a beloved game, or an entirely new platform built on an old reliable engine.
+
+Open source gaming is important for many reasons: it provides users with a fun diversion, a way to connect with friends, and an opportunity for programmers and designers to hack within an existing framework. If titles like Doom weren't made open source, a little bit of video game history would be lost. Instead, it endures and has the opportunity to grow even more.
+
+Try an open source game, and watch your six.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/open-source-fps-games
+
+作者:[Aman Gaur][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/amangaur
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/game_pawn_grid_linux.png?itok=4gERzRkg (Gaming on a grid with penguin pawns)
+[2]: https://opensource.com/sites/default/files/uploads/xonotic.jpg (Xonotic)
+[3]: https://www.xonotic.org/download/
+[4]: https://opensource.com/sites/default/files/uploads/wolfensteinenemyterritory.jpg (Wolfenstein Enemy Territory)
+[5]: https://www.splashdamage.com/games/wolfenstein-enemy-territory/
+[6]: https://github.com/id-Software/Enemy-Territory
+[7]: https://opensource.com/sites/default/files/uploads/doom.jpg (Doom)
+[8]: https://github.com/id-Software/DOOM
+[9]: https://freedoom.github.io/
+[10]: https://dhewm3.org/
+[11]: https://github.com/RobertBeckebans/RBDOOM-3-BFG/
+[12]: https://opensource.com/sites/default/files/uploads/smokinguns.jpg (Smokin' Guns)
+[13]: https://www.smokin-guns.org/downloads
+[14]: https://opensource.com/sites/default/files/uploads/nexuiz.jpg (Nexuiz)
+[15]: https://sourceforge.net/projects/nexuiz/
+[16]: https://opensource.com/sites/default/files/uploads/kkrieger.jpg (kkrieger)
+[17]: https://web.archive.org/web/20120204065621/http://www.theprodukkt.com/kkrieger
+[18]: https://github.com/farbrausch/fr_public
+[19]: https://opensource.com/sites/default/files/uploads/warsow.jpg (Warsow)
+[20]: https://www.warsow.net/download
+[21]: https://github.com/Warsow
+[22]: https://opensource.com/sites/default/files/uploads/padman.jpg (World of Padman)
+[23]: https://worldofpadman.net/en/
+[24]: https://github.com/PadWorld-Entertainment
diff --git a/sources/tech/20200505 Analyzing data science code with R and Emacs.md b/sources/tech/20200505 Analyzing data science code with R and Emacs.md
new file mode 100644
index 0000000000..ebcfadbe92
--- /dev/null
+++ b/sources/tech/20200505 Analyzing data science code with R and Emacs.md
@@ -0,0 +1,133 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Analyzing data science code with R and Emacs)
+[#]: via: (https://opensource.com/article/20/5/r-emacs-data-science)
+[#]: author: (Peter Prevos https://opensource.com/users/danderzei)
+
+Analyzing data science code with R and Emacs
+======
+Emacs' versatility and extensibility bring the editor's full power into
+play for writing data science code.
+![metrics and data shown on a computer screen][1]
+
+Way back in 2012, _Harvard Business Review_ published an article that proclaimed "data scientist" to be the [sexiest job][2] of the 21st century. Interest in data science has exploded since then. Many great open source projects, such as [Python][3] and the [R language][4] for statistical computing, have facilitated the rapid developments in how we analyze data.
+
+I started my career using pencil and paper and moved to spreadsheets. Now the R language is my weapon of choice when I need to create value from data. Emacs is another one of my favorite tools. This article briefly explains how to use the [Emacs Speaks Statistics][5] (ESS) package to get started with developing R projects in this venerable editor.
+
+The vast majority of R developers use the [RStudio][6] IDE to manage their projects. RStudio is a powerful open source editor with specialized functionality to develop data science projects. RStudio is a great integrated development environment (IDE), but its editing functions are limited.
+
+Using Emacs to write data science code means that you have access to the full power of this extensible editor. I prefer using Emacs for my data science projects because I can do many other tasks within the same application, leveraging the multifunctionality of this venerable editor. If you are just getting started with Emacs, then please first read Seth Kenlon's [Emacs getting started][7] article.
+
+### Setting up Emacs for R
+
+Emacs is an almost infinitely extensible text editor, which unfortunately means that many things don't work the way you want them to out of the box. Before you can write and execute R scripts, you need to install some packages and configure them. The ESS package provides an interface between Emacs and R. Other packages, such as [Company][8] and [highlight-parentheses][9] help with completion and balancing parentheses.
+
+Emacs uses a version of Lisp for configuration. The lines of [Emacs Lisp][10] code below install the required extensions and define a minimal configuration to get you started. These lines were tested for GNU Emacs version 26.3.
+
+Copy these lines and save them in a file named **init.el** in your **.emacs.d** folder. This is the folder that Emacs uses to store configurations, including the [init file][11]. If you already have an init file, then you can append these lines to your config. This minimal configuration is enough to get you started.
+
+
+```
+;; Elisp file for R coding with Emacs
+
+;; Add MELPA repository and initialise the package manager
+(require 'package)
+(add-to-list 'package-archives
+ '("melpa" . ""))
+(package-initialize)
+
+;; Install use-package,in case it does not exist yet
+;; The use-package software will install all other packages as required
+(unless (package-installed-p 'use-package)
+ (package-refresh-contents)
+ (package-install 'use-package))
+
+;; ESS configurationEmacs Speaks Statistics
+(use-package ess
+ :ensure t
+)
+
+;; Auto completion
+(use-package company
+ :ensure t
+ :config
+ (setq company-idle-delay 0)
+ (setq company-minimum-prefix-length 2)
+ (global-company-mode t)
+)
+
+; Parentheses
+(use-package highlight-parentheses
+ :ensure t
+ :config
+ (progn
+ (highlight-parentheses-mode)
+ (global-highlight-parentheses-mode))
+ )
+```
+
+### Using the R console
+
+To start an R console session, press **M-x R** and hit **Enter** (**M** is the Emacs way to denote the **Alt** or **Command** key). ESS will ask you to nominate a working directory, which defaults to the folder of the current buffer. You can use more than one console in the same Emacs session by repeating the R command.
+
+Emacs opens a new buffer for your new R console. You can also use the **Up** and **Down** arrow keys to go to previous lines and re-run them. Use the **Ctrl** and **Up/Down** arrow keys to recycle old commands.
+
+The Company ("complete anything") package manages autocompletion in both the console and R scripts. When entering a function, the mini-buffer at the bottom of the screen shows the relevant parameters. When the autocompletion dropdown menu appears, you can press **F1** to view the chosen option's Help file before you select it.
+
+The [highlight-parentheses][9] package does what its name suggests. Several other Emacs packages are available to help you balance parentheses and other structural elements in your code.
+
+### Writing R scripts
+
+Emacs recognizes R mode for any buffer with a **.R** extension (the file extension is case-sensitive). Open or create a new file with the **C-x C-f** shortcut and type the path and file name. You can start writing your code and use all of the powerful editing techniques that Emacs provides.
+
+Several functions are available to evaluate the code. You can evaluate each line separately with **C-<return>**, while **C-c C-c** will evaluate a contiguous region. Keying **C-c C-b** will evaluate the whole buffer.
+
+When you evaluate some code, Emacs will use any running console or ask you to open a new console to run the code.
+
+The output of any plotting functions appears in a window outside of Emacs. If you prefer to view the output within Emacs, then you need to save the output to disk and open the resulting file in a separate buffer.
+
+![Literate programming in Org mode, the ESS buffer, and graphics output.][12]
+
+Literate programming in Org mode, the ESS buffer, and graphics output.
+
+### Advanced use
+
+This article provides a brief introduction to using R in Emacs. Many parameters can be fine-tuned to make Emacs behave according to your preferences, but it would take too much space to cover them here. The [ESS manual][13] describes these in detail. You can also extend functionality with additional packages.
+
+Org mode can integrate R code, providing a productive platform for literate programming. If you prefer to use RMarkdown, the [Polymode][14] package has you covered.
+
+Emacs has various packages to make your editing experience more efficient. The best part of using Emacs to write R code is that the program is more than just an IDE; it is a malleable computer system that you can configure to match your favorite workflow.
+
+Learning how to configure Emacs can be daunting. The best way to learn quickly is to copy ideas from people who share their configurations. Miles McBain manages a [list of Emacs configurations][15] that could be useful if you want to explore using the R language in Emacs further.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/r-emacs-data-science
+
+作者:[Peter Prevos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/danderzei
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
+[2]: https://hbr.org/2012/10/data-scientist-the-sexiest-job-of-the-21st-century
+[3]: https://www.python.org/
+[4]: https://www.r-project.org/
+[5]: https://ess.r-project.org/
+[6]: https://opensource.com/article/18/2/getting-started-RStudio-IDE
+[7]: https://opensource.com/article/20/3/getting-started-emacs
+[8]: https://company-mode.github.io/
+[9]: https://github.com/tsdh/highlight-parentheses.el
+[10]: https://en.wikipedia.org/wiki/Emacs_Lisp
+[11]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html
+[12]: https://opensource.com/sites/default/files/uploads/r-ess-screenshot.jpg (Literate programming in Org mode, the ESS buffer, and graphics output.)
+[13]: https://ess.r-project.org/index.php?Section=documentation&subSection=manuals
+[14]: https://github.com/polymode/polymode
+[15]: https://github.com/MilesMcBain/esscss
diff --git a/sources/tech/20200507 Using the systemctl command to manage systemd units.md b/sources/tech/20200507 Using the systemctl command to manage systemd units.md
new file mode 100644
index 0000000000..e305cee36c
--- /dev/null
+++ b/sources/tech/20200507 Using the systemctl command to manage systemd units.md
@@ -0,0 +1,618 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using the systemctl command to manage systemd units)
+[#]: via: (https://opensource.com/article/20/5/systemd-units)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Using the systemctl command to manage systemd units
+======
+Units are the basis of everything in systemd.
+![woman on laptop sitting at the window][1]
+
+In the first two articles in this series, I explored the Linux systemd startup sequence. In the [first article][2], I looked at systemd's functions and architecture and the controversy around its role as a replacement for the old SystemV init program and startup scripts. And in the [second article][3], I examined two important systemd tools, systemctl and journalctl, and explained how to switch from one target to another and to change the default target.
+
+In this third article, I'll look at systemd units in more detail and how to use the systemctl command to explore and manage units. I'll also explain how to stop and disable units and how to create a new systemd mount unit to mount a new filesystem and enable it to initiate during startup.
+
+### Preparation
+
+All of the experiments in this article should be done as the root user (unless otherwise specified). Some of the commands that simply list various systemd units can be performed by non-root users, but the commands that make changes cannot. Make sure to do all of these experiments only on non-production hosts or virtual machines (VMs).
+
+One of these experiments requires the sysstat package, so install it before you move on. For Fedora and other Red Hat-based distributions you can install sysstat with:
+
+
+```
+`dnf -y install sysstat`
+```
+
+The sysstat RPM installs several statistical tools that can be used for problem determination. One is [System Activity Report][4] (SAR), which records many system performance data points at regular intervals (every 10 minutes by default). Rather than run as a daemon in the background, the sysstat package installs two systemd timers. One timer runs every 10 minutes to collect data, and the other runs once a day to aggregate the daily data. In this article, I will look briefly at these timers but wait to explain how to create a timer in a future article.
+
+### systemd suite
+
+The fact is, systemd is more than just one program. It is a large suite of programs all designed to work together to manage nearly every aspect of a running Linux system. A full exposition of systemd would take a book on its own. Most of us do not need to understand all of the details about how all of systemd's components fit together, so I will focus on the programs and components that enable you to manage various Linux services and deal with log files and journals.
+
+### Practical structure
+
+The structure of systemd—outside of its executable files—is contained in its many configuration files. Although these files have different names and identifier extensions, they are all called "unit" files. Units are the basis of everything systemd.
+
+Unit files are ASCII plain-text files that are accessible to and can be created or modified by a sysadmin. There are a number of unit file types, and each has its own man page. Figure 1 lists some of these unit file types by their filename extensions and a short description of each.
+
+systemd unit | Description
+---|---
+.automount | The **.automount** units are used to implement on-demand (i.e., plug and play) and mounting of filesystem units in parallel during startup.
+.device | The **.device** unit files define hardware and virtual devices that are exposed to the sysadmin in the **/dev/directory**. Not all devices have unit files; typically, block devices such as hard drives, network devices, and some others have unit files.
+.mount | The **.mount** unit defines a mount point on the Linux filesystem directory structure.
+.scope | The **.scope** unit defines and manages a set of system processes. This unit is not configured using unit files, rather it is created programmatically. Per the **systemd.scope** man page, “The main purpose of scope units is grouping worker processes of a system service for organization and for managing resources.”
+.service | The **.service** unit files define processes that are managed by systemd. These include services such as crond cups (Common Unix Printing System), iptables, multiple logical volume management (LVM) services, NetworkManager, and more.
+.slice | The **.slice** unit defines a “slice,” which is a conceptual division of system resources that are related to a group of processes. You can think of all system resources as a pie and this subset of resources as a “slice” out of that pie.
+.socket | The **.socket** units define interprocess communication sockets, such as network sockets.
+.swap | The **.swap** units define swap devices or files.
+.target | The **.target** units define groups of unit files that define startup synchronization points, runlevels, and services. Target units define the services and other units that must be active in order to start successfully.
+.timer | The **.timer** unit defines timers that can initiate program execution at specified times.
+
+### systemctl
+
+I looked at systemd's startup functions in the [second article][3], and here I'll explore its service management functions a bit further. systemd provides the **systemctl** command that is used to start and stop services, configure them to launch (or not) at system startup, and monitor the current status of running services.
+
+In a terminal session as the root user, ensure that root's home directory ( **~** ) is the [PWD][5]. To begin looking at units in various ways, list all of the loaded and active systemd units. systemctl automatically pipes its [stdout][6] data stream through the **less** pager, so you don't have to:
+
+
+```
+[root@testvm1 ~]# systemctl
+UNIT LOAD ACTIVE SUB DESCRIPTION
+proc-sys-fs-binfmt_misc.automount loaded active running Arbitrary Executable File>
+sys-devices-pci0000:00-0000:00:01.1-ata7-host6-target6:0:0-6:0:0:0-block-sr0.device loaded a>
+sys-devices-pci0000:00-0000:00:03.0-net-enp0s3.device loaded active plugged 82540EM Gigabi>
+sys-devices-pci0000:00-0000:00:05.0-sound-card0.device loaded active plugged 82801AA AC'97>
+sys-devices-pci0000:00-0000:00:08.0-net-enp0s8.device loaded active plugged 82540EM Gigabi>
+sys-devices-pci0000:00-0000:00:0d.0-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda1.device loa>
+sys-devices-pci0000:00-0000:00:0d.0-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda2.device loa>
+<snip – removed lots of lines of data from here>
+
+LOAD = Reflects whether the unit definition was properly loaded.
+ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
+SUB = The low-level unit activation state, values depend on unit type.
+
+206 loaded units listed. Pass --all to see loaded but inactive units, too.
+To show all installed unit files use 'systemctl list-unit-files'.
+```
+
+As you scroll through the data in your terminal session, look for some specific things. The first section lists devices such as hard drives, sound cards, network interface cards, and TTY devices. Another section shows the filesystem mount points. Other sections include various services and a list of all loaded and active targets.
+
+The sysstat timers at the bottom of the output are used to collect and generate daily system activity summaries for SAR. SAR is a very useful problem-solving tool. (You can learn more about it in Chapter 13 of my book [_Using and Administering Linux: Volume 1, Zero to SysAdmin: Getting Started_][7].)
+
+Near the very bottom, three lines describe the meanings of the statuses (loaded, active, and sub). Press **q** to exit the pager.
+
+Use the following command (as suggested in the last line of the output above) to see all the units that are installed, whether or not they are loaded. I won't reproduce the output here, because you can scroll through it on your own. The systemctl program has an excellent tab-completion facility that makes it easy to enter complex commands without needing to memorize all the options:
+
+
+```
+`[root@testvm1 ~]# systemctl list-unit-files`
+```
+
+You can see that some units are disabled. Table 1 in the man page for systemctl lists and provides short descriptions of the entries you might see in this listing. Use the **-t** (type) option to view just the timer units:
+
+
+```
+[root@testvm1 ~]# systemctl list-unit-files -t timer
+UNIT FILE STATE
+[chrony-dnssrv@.timer][8] disabled
+dnf-makecache.timer enabled
+fstrim.timer disabled
+logrotate.timer disabled
+logwatch.timer disabled
+[mdadm-last-resort@.timer][9] static
+mlocate-updatedb.timer enabled
+sysstat-collect.timer enabled
+sysstat-summary.timer enabled
+systemd-tmpfiles-clean.timer static
+unbound-anchor.timer enabled
+```
+
+You could do the same thing with this alternative, which provides considerably more detail:
+
+
+```
+[root@testvm1 ~]# systemctl list-timers
+Thu 2020-04-16 09:06:20 EDT 3min 59s left n/a n/a systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
+Thu 2020-04-16 10:02:01 EDT 59min left Thu 2020-04-16 09:01:32 EDT 49s ago dnf-makecache.timer dnf-makecache.service
+Thu 2020-04-16 13:00:00 EDT 3h 57min left n/a n/a sysstat-collect.timer sysstat-collect.service
+Fri 2020-04-17 00:00:00 EDT 14h left Thu 2020-04-16 12:51:37 EDT 3h 49min left mlocate-updatedb.timer mlocate-updatedb.service
+Fri 2020-04-17 00:00:00 EDT 14h left Thu 2020-04-16 12:51:37 EDT 3h 49min left unbound-anchor.timer unbound-anchor.service
+Fri 2020-04-17 00:07:00 EDT 15h left n/a n/a sysstat-summary.timer sysstat-summary.service
+
+6 timers listed.
+Pass --all to see loaded but inactive timers, too.
+[root@testvm1 ~]#
+```
+
+Although there is no option to do systemctl list-mounts, you can list the mount point unit files:
+
+
+```
+[root@testvm1 ~]# systemctl list-unit-files -t mount
+UNIT FILE STATE
+-.mount generated
+boot.mount generated
+dev-hugepages.mount static
+dev-mqueue.mount static
+home.mount generated
+proc-fs-nfsd.mount static
+proc-sys-fs-binfmt_misc.mount disabled
+run-vmblock\x2dfuse.mount disabled
+sys-fs-fuse-connections.mount static
+sys-kernel-config.mount static
+sys-kernel-debug.mount static
+tmp.mount generated
+usr.mount generated
+var-lib-nfs-rpc_pipefs.mount static
+var.mount generated
+
+15 unit files listed.
+[root@testvm1 ~]#
+```
+
+The STATE column in this data stream is interesting and requires a bit of explanation. The "generated" states indicate that the mount unit was generated on the fly during startup using the information in **/etc/fstab**. The program that generates these mount units is **/lib/systemd/system-generators/systemd-fstab-generator,** along with other tools that generate a number of other unit types. The "static" mount units are for filesystems like **/proc** and **/sys**, and the files for these are located in the **/usr/lib/systemd/system** directory.
+
+Now, look at the service units. This command will show all services installed on the host, whether or not they are active:
+
+
+```
+`[root@testvm1 ~]# systemctl --all -t service`
+```
+
+The bottom of this listing of service units displays 166 as the total number of loaded units on my host. Your number will probably differ.
+
+Unit files do not have a filename extension (such as **.unit**) to help identify them, so you can generalize that most configuration files that belong to systemd are unit files of one type or another. The few remaining files are mostly **.conf** files located in **/etc/systemd**.
+
+Unit files are stored in the **/usr/lib/systemd** directory and its subdirectories, while the **/etc/systemd/** directory and its subdirectories contain symbolic links to the unit files necessary to the local configuration of this host.
+
+To explore this, make **/etc/systemd** the PWD and list its contents. Then make **/etc/systemd/system** the PWD and list its contents, and list the contents of at least a couple of the current PWD's subdirectories.
+
+Take a look at the **default.target** file, which determines which runlevel target the system will boot to. In the second article in this series, I explained how to change the default target from the GUI (**graphical.target**) to the command-line only (**multi-user.target**) target. The **default.target** file on my test VM is simply a symlink to **/usr/lib/systemd/system/graphical.target**.
+
+Take a few minutes to examine the contents of the **/etc/systemd/system/default.target** file:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Graphical Interface
+Documentation=man:systemd.special(7)
+Requires=multi-user.target
+Wants=display-manager.service
+Conflicts=rescue.service rescue.target
+After=multi-user.target rescue.service rescue.target display-manager.service
+AllowIsolate=yes
+```
+
+Note that this requires the **multi-user.target**; the **graphical.target** cannot start if the **multi-user.target** is not already up and running. It also says it "wants" the **display-manager.service** unit. A "want" does not need to be fulfilled in order for the unit to start successfully. If the "want" cannot be fulfilled, it will be ignored by systemd, and the rest of the target will start regardless.
+
+The subdirectories in **/etc/systemd/system** are lists of wants for various targets. Take a few minutes to explore the files and their contents in the **/etc/systemd/system/graphical.target.wants** directory.
+
+The **systemd.unit** man page contains a lot of good information about unit files, their structure, the sections they can be divided into, and the options that can be used. It also lists many of the unit types, all of which have their own man pages. If you want to interpret a unit file, this would be a good place to start.
+
+### Service units
+
+A Fedora installation usually installs and enables services that particular hosts do not need for normal operation. Conversely, sometimes it doesn't include services that need to be installed, enabled, and started. Services that are not needed for the Linux host to function as desired, but which are installed and possibly running, represent a security risk and should—at minimum—be stopped and disabled and—at best—should be uninstalled.
+
+The systemctl command is used to manage systemd units, including services, targets, mounts, and more. Take a closer look at the list of services to identify services that will never be used:
+
+
+```
+[root@testvm1 ~]# systemctl --all -t service
+UNIT LOAD ACTIVE SUB DESCRIPTION
+<snip>
+chronyd.service loaded active running NTP client/server
+crond.service loaded active running Command Scheduler
+cups.service loaded active running CUPS Scheduler
+dbus-daemon.service loaded active running D-Bus System Message Bus
+<snip>
+● ip6tables.service not-found inactive dead ip6tables.service
+● ipset.service not-found inactive dead ipset.service
+● iptables.service not-found inactive dead iptables.service
+<snip>
+firewalld.service loaded active running firewalld - dynamic firewall daemon
+<snip>
+● ntpd.service not-found inactive dead ntpd.service
+● ntpdate.service not-found inactive dead ntpdate.service
+pcscd.service loaded active running PC/SC Smart Card Daemon
+```
+
+I have pruned out most of the output from the command to save space. The services that show "loaded active running" are obvious. The "not-found" services are ones that systemd is aware of but are not installed on the Linux host. If you want to run those services, you must install the packages that contain them.
+
+Note the **pcscd.service** unit. This is the PC/SC smart-card daemon. Its function is to communicate with smart-card readers. Many Linux hosts—including VMs—have no need for this reader nor the service that is loaded and taking up memory and CPU resources. You can stop this service and disable it, so it will not restart on the next boot. First, check its status:
+
+
+```
+[root@testvm1 ~]# systemctl status pcscd.service
+● pcscd.service - PC/SC Smart Card Daemon
+ Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
+ Active: active (running) since Fri 2019-05-10 11:28:42 EDT; 3 days ago
+ Docs: man:pcscd(8)
+ Main PID: 24706 (pcscd)
+ Tasks: 6 (limit: 4694)
+ Memory: 1.6M
+ CGroup: /system.slice/pcscd.service
+ └─24706 /usr/sbin/pcscd --foreground --auto-exit
+
+May 10 11:28:42 testvm1 systemd[1]: Started PC/SC Smart Card Daemon.
+```
+
+This data illustrates the additional information systemd provides versus SystemV, which only reports whether or not the service is running. Note that specifying the **.service** unit type is optional. Now stop and disable the service, then re-check its status:
+
+
+```
+[root@testvm1 ~]# systemctl stop pcscd ; systemctl disable pcscd
+Warning: Stopping pcscd.service, but it can still be activated by:
+ pcscd.socket
+Removed /etc/systemd/system/sockets.target.wants/pcscd.socket.
+[root@testvm1 ~]# systemctl status pcscd
+● pcscd.service - PC/SC Smart Card Daemon
+ Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
+ Active: failed (Result: exit-code) since Mon 2019-05-13 15:23:15 EDT; 48s ago
+ Docs: man:pcscd(8)
+ Main PID: 24706 (code=exited, status=1/FAILURE)
+
+May 10 11:28:42 testvm1 systemd[1]: Started PC/SC Smart Card Daemon.
+May 13 15:23:15 testvm1 systemd[1]: Stopping PC/SC Smart Card Daemon...
+May 13 15:23:15 testvm1 systemd[1]: pcscd.service: Main process exited, code=exited, status=1/FAIL>
+May 13 15:23:15 testvm1 systemd[1]: pcscd.service: Failed with result 'exit-code'.
+May 13 15:23:15 testvm1 systemd[1]: Stopped PC/SC Smart Card Daemon.
+```
+
+The short log entry display for most services prevents having to search through various log files to locate this type of information. Check the status of the system runlevel targets—specifying the "target" unit type is required:
+
+
+```
+[root@testvm1 ~]# systemctl status multi-user.target
+● multi-user.target - Multi-User System
+ Loaded: loaded (/usr/lib/systemd/system/multi-user.target; static; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Multi-User System.
+[root@testvm1 ~]# systemctl status graphical.target
+● graphical.target - Graphical Interface
+ Loaded: loaded (/usr/lib/systemd/system/graphical.target; indirect; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Graphical Interface.
+[root@testvm1 ~]# systemctl status default.target
+● graphical.target - Graphical Interface
+ Loaded: loaded (/usr/lib/systemd/system/graphical.target; indirect; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Graphical Interface.
+```
+
+The default target is the graphical target. The status of any unit can be checked in this way.
+
+### Mounts the old way
+
+A mount unit defines all of the parameters required to mount a filesystem on a designated mount point. systemd can manage mount units with more flexibility than those using the **/etc/fstab** filesystem configuration file. Despite this, systemd still uses the **/etc/fstab** file for filesystem configuration and mounting purposes. systemd uses the **systemd-fstab-generator** tool to create transient mount units from the data in the **fstab** file.
+
+I will create a new filesystem and a systemd mount unit to mount it. If you have some available disk space on your test system, you can do it along with me.
+
+_Note that the volume group and logical volume names may be different on your test system. Be sure to use the names that are pertinent to your system._
+
+You will need to create a partition or logical volume, then make an EXT4 filesystem on it. Add a label to the filesystem, **TestFS**, and create a directory for a mount point **/TestFS**.
+
+To try this on your own, first, verify that you have free space on the volume group. Here is what that looks like on my VM where I have some space available on the volume group to create a new logical volume:
+
+
+```
+[root@testvm1 ~]# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+sda 8:0 0 120G 0 disk
+├─sda1 8:1 0 4G 0 part /boot
+└─sda2 8:2 0 116G 0 part
+ ├─VG01-root 253:0 0 5G 0 lvm /
+ ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]
+ ├─VG01-usr 253:2 0 30G 0 lvm /usr
+ ├─VG01-home 253:3 0 20G 0 lvm /home
+ ├─VG01-var 253:4 0 20G 0 lvm /var
+ └─VG01-tmp 253:5 0 10G 0 lvm /tmp
+sr0 11:0 1 1024M 0 rom
+[root@testvm1 ~]# vgs
+ VG #PV #LV #SN Attr VSize VFree
+ VG01 1 6 0 wz--n- <116.00g <23.00g
+```
+
+Then create a new volume on **VG01** named **TestFS**. It does not need to be large; 1GB is fine. Then create a filesystem, add the filesystem label, and create the mount point:
+
+
+```
+[root@testvm1 ~]# lvcreate -L 1G -n TestFS VG01
+ Logical volume "TestFS" created.
+[root@testvm1 ~]# mkfs -t ext4 /dev/mapper/VG01-TestFS
+mke2fs 1.45.3 (14-Jul-2019)
+Creating filesystem with 262144 4k blocks and 65536 inodes
+Filesystem UUID: 8718fba9-419f-4915-ab2d-8edf811b5d23
+Superblock backups stored on blocks:
+ 32768, 98304, 163840, 229376
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+[root@testvm1 ~]# e2label /dev/mapper/VG01-TestFS TestFS
+[root@testvm1 ~]# mkdir /TestFS
+```
+
+Now, mount the new filesystem:
+
+
+```
+[root@testvm1 ~]# mount /TestFS/
+mount: /TestFS/: can't find in /etc/fstab.
+```
+
+This will not work because you do not have an entry in **/etc/fstab**. You can mount the new filesystem even without the entry in **/etc/fstab** using both the device name (as it appears in **/dev**) and the mount point. Mounting in this manner is simpler than it used to be—it used to require the filesystem type as an argument. The mount command is now smart enough to detect the filesystem type and mount it accordingly.
+
+Try it again:
+
+
+```
+[root@testvm1 ~]# mount /dev/mapper/VG01-TestFS /TestFS/
+[root@testvm1 ~]# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+sda 8:0 0 120G 0 disk
+├─sda1 8:1 0 4G 0 part /boot
+└─sda2 8:2 0 116G 0 part
+ ├─VG01-root 253:0 0 5G 0 lvm /
+ ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]
+ ├─VG01-usr 253:2 0 30G 0 lvm /usr
+ ├─VG01-home 253:3 0 20G 0 lvm /home
+ ├─VG01-var 253:4 0 20G 0 lvm /var
+ ├─VG01-tmp 253:5 0 10G 0 lvm /tmp
+ └─VG01-TestFS 253:6 0 1G 0 lvm /TestFS
+sr0 11:0 1 1024M 0 rom
+[root@testvm1 ~]#
+```
+
+Now the new filesystem is mounted in the proper location. List the mount unit files:
+
+
+```
+`[root@testvm1 ~]# systemctl list-unit-files -t mount`
+```
+
+This command does not show a file for the **/TestFS** filesystem because no file exists for it. The command **systemctl status TestFS.mount** does not display any information about the new filesystem either. You can try it using wildcards with the **systemctl status** command:
+
+
+```
+[root@testvm1 ~]# systemctl status *mount
+● usr.mount - /usr
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted)
+ Where: /usr
+ What: /dev/mapper/VG01-usr
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+
+<SNIP>
+● TestFS.mount - /TestFS
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Fri 2020-04-17 16:02:26 EDT; 1min 18s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+
+● run-user-0.mount - /run/user/0
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Thu 2020-04-16 08:52:29 EDT; 1 day 5h ago
+ Where: /run/user/0
+ What: tmpfs
+
+● var.mount - /var
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted) since Thu 2020-04-16 12:51:34 EDT; 1 day 1h ago
+ Where: /var
+ What: /dev/mapper/VG01-var
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+ Tasks: 0 (limit: 19166)
+ Memory: 212.0K
+ CPU: 5ms
+ CGroup: /system.slice/var.mount
+```
+
+This command provides some very interesting information about your system's mounts, and your new filesystem shows up. The **/var** and **/usr** filesystems are identified as being generated from **/etc/fstab**, while your new filesystem simply shows that it is loaded and provides the location of the info file in the **/proc/self/mountinfo** file.
+
+Next, automate this mount. First, do it the old-fashioned way by adding an entry in **/etc/fstab**. Later, I'll show you how to do it the new way, which will teach you about creating units and integrating them into the startup sequence.
+
+Unmount **/TestFS** and add the following line to the **/etc/fstab** file:
+
+
+```
+`/dev/mapper/VG01-TestFS /TestFS ext4 defaults 1 2`
+```
+
+Now, mount the filesystem with the simpler **mount** command and list the mount units again:
+
+
+```
+[root@testvm1 ~]# mount /TestFS
+[root@testvm1 ~]# systemctl status *mount
+<SNIP>
+● TestFS.mount - /TestFS
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Fri 2020-04-17 16:26:44 EDT; 1min 14s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+<SNIP>
+```
+
+This did not change the information for this mount because the filesystem was manually mounted. Reboot and run the command again, and this time specify **TestFS.mount** rather than using the wildcard. The results for this mount are now consistent with it being mounted at startup:
+
+
+```
+[root@testvm1 ~]# systemctl status TestFS.mount
+● TestFS.mount - /TestFS
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted) since Fri 2020-04-17 16:30:21 EDT; 1min 38s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+ Tasks: 0 (limit: 19166)
+ Memory: 72.0K
+ CPU: 6ms
+ CGroup: /system.slice/TestFS.mount
+
+Apr 17 16:30:21 testvm1 systemd[1]: Mounting /TestFS...
+Apr 17 16:30:21 testvm1 systemd[1]: Mounted /TestFS.
+```
+
+### Creating a mount unit
+
+Mount units may be configured either with the traditional **/etc/fstab** file or with systemd units. Fedora uses the **fstab** file as it is created during the installation. However, systemd uses the **systemd-fstab-generator** program to translate the **fstab** file into systemd units for each entry in the **fstab** file. Now that you know you can use systemd **.mount** unit files for filesystem mounting, try it out by creating a mount unit for this filesystem.
+
+First, unmount **/TestFS**. Edit the **/etc/fstab** file and delete or comment out the **TestFS** line. Now, create a new file with the name **TestFS.mount** in the **/etc/systemd/system** directory. Edit it to contain the configuration data below. The unit file name and the name of the mount point _must_ be identical, or the mount will fail:
+
+
+```
+# This mount unit is for the TestFS filesystem
+# By David Both
+# Licensed under GPL V2
+# This file should be located in the /etc/systemd/system directory
+
+[Unit]
+Description=TestFS Mount
+
+[Mount]
+What=/dev/mapper/VG01-TestFS
+Where=/TestFS
+Type=ext4
+Options=defaults
+
+[Install]
+WantedBy=multi-user.target
+```
+
+The **Description** line in the **[Unit]** section is for us humans, and it provides the name that's shown when you list mount units with **systemctl -t mount**. The data in the **[Mount]** section of this file contains essentially the same data that would be found in the **fstab** file.
+
+Now enable the mount unit:
+
+
+```
+[root@testvm1 etc]# systemctl enable TestFS.mount
+Created symlink /etc/systemd/system/multi-user.target.wants/TestFS.mount → /etc/systemd/system/TestFS.mount.
+```
+
+This creates the symlink in the **/etc/systemd/system** directory, which will cause this mount unit to be mounted on all subsequent boots. The filesystem has not yet been mounted, so you must "start" it:
+
+
+```
+`[root@testvm1 ~]# systemctl start TestFS.mount`
+```
+
+Verify that the filesystem has been mounted:
+
+
+```
+[root@testvm1 ~]# systemctl status TestFS.mount
+● TestFS.mount - TestFS Mount
+ Loaded: loaded (/etc/systemd/system/TestFS.mount; enabled; vendor preset: disabled)
+ Active: active (mounted) since Sat 2020-04-18 09:59:53 EDT; 14s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+ Tasks: 0 (limit: 19166)
+ Memory: 76.0K
+ CPU: 3ms
+ CGroup: /system.slice/TestFS.mount
+
+Apr 18 09:59:53 testvm1 systemd[1]: Mounting TestFS Mount...
+Apr 18 09:59:53 testvm1 systemd[1]: Mounted TestFS Mount.
+```
+
+This experiment has been specifically about creating a unit file for a mount, but it can be applied to other types of unit files as well. The details will be different, but the concepts are the same. Yes, I know it is still easier to add a line to the **/etc/fstab** file than it is to create a mount unit. But this is a good example of how to create a unit file because systemd does not have generators for every type of unit.
+
+### In summary
+
+This article looked at systemd units in more detail and how to use the systemctl command to explore and manage units. It also showed how to stop and disable units and create a new systemd mount unit to mount a new filesystem and enable it to initiate during startup.
+
+In the next article in this series, I will take you through a recent problem I had during startup and show you how I circumvented it using systemd.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][10] [to systemd][10]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][11] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][12]'s [description of systemd][13].
+ * [Linux.com][14]'s "More systemd fun" offers more advanced systemd [information and tips][15].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][16]
+ * [systemd for Administrators, Part I][17]
+ * [systemd for Administrators, Part II][18]
+ * [systemd for Administrators, Part III][19]
+ * [systemd for Administrators, Part IV][20]
+ * [systemd for Administrators, Part V][21]
+ * [systemd for Administrators, Part VI][22]
+ * [systemd for Administrators, Part VII][23]
+ * [systemd for Administrators, Part VIII][24]
+ * [systemd for Administrators, Part IX][25]
+ * [systemd for Administrators, Part X][26]
+ * [systemd for Administrators, Part XI][27]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-units
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: https://opensource.com/article/20/4/systemd-startup
+[4]: https://en.wikipedia.org/wiki/Sar_%28Unix%29
+[5]: https://en.wikipedia.org/wiki/Pwd
+[6]: https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)
+[7]: http://www.both.org/?page_id=1183
+[8]: mailto:chrony-dnssrv@.timer
+[9]: mailto:mdadm-last-resort@.timer
+[10]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[11]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[12]: http://Freedesktop.org
+[13]: http://www.freedesktop.org/wiki/Software/systemd
+[14]: http://Linux.com
+[15]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[16]: http://0pointer.de/blog/projects/systemd.html
+[17]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[18]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[19]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[20]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[21]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[22]: http://0pointer.de/blog/projects/changing-roots
+[23]: http://0pointer.de/blog/projects/blame-game.html
+[24]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[25]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[26]: http://0pointer.de/blog/projects/instances.html
+[27]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md b/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md
new file mode 100644
index 0000000000..ea3aa01866
--- /dev/null
+++ b/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md
@@ -0,0 +1,193 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (A guide to setting up your Open Source Program Office (OSPO) for success)
+[#]: via: (https://opensource.com/article/20/5/open-source-program-office)
+[#]: author: (J. Manrique Lopez de la Fuente https://opensource.com/users/jsmanrique)
+
+A guide to setting up your Open Source Program Office (OSPO) for success
+======
+Learn how to best grow and maintain your open source communities and
+allies.
+![community team brainstorming ideas][1]
+
+Companies create Open Source Program Offices (OSPO) to manage their relationship with the open source ecosystems they depend on. By understanding the company's open source ecosystem, an OSPO is able to maximize the company's return on investment and reduce the risks of consuming, contributing to, and releasing open source software. Additionally, since the company depends on its open source ecosystem, ensuring its health and sustainability shall ensure the company's health, sustainable growth, and evolution.
+
+### How has OSPO become vital to companies and their open source ecosystem?
+
+Marc Andreessen has said that "software is eating the world," and more recently, it could be said that open source is eating the software world. But how is that process happening?
+
+Companies get involved with open source projects in several ways. These projects comprise the company's open source ecosystem, and their relationships and interactions can be seen through Open Source Software's (OSS) inbound and outbound processes.
+
+From the OSS inbound point of view, companies use it to build their own solutions and their own infrastructure. OSS gets introduced because it's part of the code their technology providers use, or because their own developers add open source components to the company's information technology (IT) infrastructure.
+
+From the OSS outbound point of view, some companies contribute to OSS projects. That contribution could be part of the company's requirements for their solutions that need certain fixes in upstream projects. For example, Samsung contributes to certain graphics-related projects to ensure its hardware has software support once it gets into the market. In some other cases, contributing to OSS is a mechanism to retain talent by allowing the people to contribute to projects different from their daily work.
+
+Some companies release their own open source projects as an outbound OSS process. For companies like Red Hat or GitLab, it would be expected. But, there are increasingly more non-software companies releasing a lot of OSS, like Lyft.
+
+![OSS inbound and outbound processes][2]
+
+OSS inbound and outbound processes
+
+Ultimately, all of these projects involved in the inbound and outbound OSS flow are the company's OSS ecosystem. And like any living being, the company's health and sustainability depend on the ecosystem that surrounds it.
+
+### OSPO responsibilities
+
+Following the species and their ecosystem, people working in the OSPO team could be seen as the rangers in the organization's OSS ecosystem. They take care of the ecosystem and its relationship with the company, to keep everything healthy and sustainable.
+
+When the company consumes open source software projects, they need to be aware of licenses and compliance, to check the project's health, to ensure there are no security flaws, and, in some cases, to identify talented community members for potential hiring processes.
+
+When the company contributes to open source software projects, they need to be sure there are no Intellectual Property (IP) issues, to ensure the company contributions' footprint and its leadership in the projects, and sometimes, also to help talented people stay engaged with the company through their contributions.
+
+And when the company releases and maintains open source projects, they are responsible for ensuring community engagement and growth, for checking there are no IP issues, that the company maintains its footprint and leadership, and perhaps, to attract new talent to the company.
+
+Have you realized the whole set of skills required in an OSPO team? When I've asked people working in OSPO about the size of their teams, the number is around 1 to 5 people per 1,000 developers in the company. That's a small team to monitor a lot of people and their potential OSS related activity.
+
+### How to manage an OSPO
+
+With all these activities in OSPO people's minds and all the resources they need to worry about, how are they able to manage all of this?
+
+There are at least a couple of open source communities with valuable knowledge and resources available for them:
+
+ * The [TODO Group][3] is "an open group of companies who want to collaborate on practices, tools, and other ways to run successful and effective open source projects and programs." For example, they have a complete set of [guides][4] with best practices for and from companies running OSPOS.
+ * The [CHAOSS (Community Health Analytics for Open Source Software)][5] community develops metrics, methodologies, and software for managing open source project health and sustainability. (See more on CHAOSS' active communities and working groups below).
+
+
+
+OSPO managers need to report a lot of information to the rest of the company to answer many questions related to their OSS inbound and outbound processes, i.e., Which projects are we using in our organization? What's the health of those projects? Who are the key people in those projects? Which projects are we contributing to? Which projects are we releasing? How are we dealing with community contributions? Who are the key contributors?
+
+### Data-driven OSPO
+
+As William Edwards Deming said, "Without data, you are just a person with an opinion."
+
+Having opinions is not a bad thing, but having opinions based on data certainly makes it easier to understand, discuss, and determine the processes best suited to your company and its goals. CHAOSS is the recommended community to look to for guidance about metrics strategies and tools.
+
+Recently, the CHAOSS community has released [a new set of metric definitions][6]. These metrics are only subsets of all the ones being discussed in the focus areas of each working group (WG):
+
+ * [Common WG][7]: Defines the metrics that are used by both working groups or are important for community health, but that do not cleanly fit into one of the other existing working groups. Areas of interest include organizational affiliation, responsiveness, and geographic coverage.
+ * [Diversity and Inclusion WG][8]: Gathers experiences regarding diversity and inclusion in open source projects with the goal of understanding, from a qualitative and quantitative point of view, how diversity and inclusion can be measured.
+ * [Evolution WG][9]: Refines the metrics that inform evolution and works with software implementations.
+ * [Risk WG][10]: Refines the metrics that inform risk and works with software implementations.
+ * [Value WG][11]: Focuses on industry-standard metrics for economic value in open source. Their main goal is to publish trusted industry-standard value metrics—a kind of S&P for software development and an authoritative source for metrics significance and industry norms.
+
+
+
+On the tooling side, projects like [Augur][12], [Cregit][13], and [GrimoireLab][14] are the reference tools that report these metrics, but also many others related to OSPO activities. They are also the seed for new tools and solutions provided by the OSS community like [Cauldron.io][15], a SaaS open source solution to ease OSS ecosystem analysis.
+
+![CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io][16]
+
+CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io
+
+All these metrics and data are useless without a metrics strategy. Usually, the first approach is to try to measure as much as possible, producing overwhelming reports and dashboards full of charts and data. What is the value of that?
+
+Experience has shown that a very valid approach is the [Goal, Questions, Metrics (GQM)][17] strategy. But how do we put that in practice in an OSPO?
+
+First of all, we need to understand the company's goals when using, consuming, contributing to, or releasing and maintaining OSS projects. The usual goals are related to market positioning, required upstream features development, and talent attraction or retention. Based on these goals, we should write down related questions that can be answered with numbers, like the following:
+
+#### Who/how many are the core maintainers of my OSS ecosystem projects?
+
+![Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io][18]
+
+Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io
+
+People contribute through different mechanisms or tools (code, issues, comments, tests, etc.). Measuring the core contributors (those that have done 80% of the contributions), the regular ones (those that have done 15% of the contributions), and the casual ones (those have made 5% of the contributions) can answer questions related to participation over time, but also how people move between the different buckets. Adding affiliation information helps to identify external core contributors.
+
+#### Where are the contributions happening?
+
+![Uber OSS activity based on location. Source: uber.biterg.io][19]
+
+Uber OSS activity based on location. Source: uber.biterg.io
+
+The growth of OSS ecosystems is also related to OSS projects spread across the world. Understanding that spread helps OSPO, and the company, to manage actions that improve support for people from different countries and regions.
+
+#### What is the company's OSS network?
+
+![Uber OSS network. Source: uber.biterg.io][20]
+
+Uber OSS network. Source: uber.biterg.io
+
+The company's OSS ecosystem includes those projects that the company's people contribute to. Understanding which projects they contribute to offers insight into which technologies or OSS components are interesting to people, and which companies or organizations the company collaborates with.
+
+#### How is the company dealing with contributions?
+
+![Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io][21]
+
+Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io
+
+One of the goals when releasing OSS projects is to grow the community around them. Measuring how the company handles contributions to its projects from outside its boundaries helps to understand how "welcoming" it is and identifies mentors (or bottlenecks) and opportunities to lower the barrier to contribute.
+
+#### Consumers vs. maintainers
+
+Over the last months, we have been hearing that corporations are taking OSS for free without contributing back. The typical arguments are that these corporations are making millions of dollars thanks to free work, plus the issue of OSS project maintainer burnout due to users' complaints and requests for free support.
+
+The system is unbalanced; usually, the number of users exceeds the number of maintainers. Is that good or bad? Having users for our software is (or should be) good. But we need to manage expectations on both sides.
+
+From the corporation's point of view, consuming OSS without care is very, very risky.
+
+OSPO can play an important role in educating the company about the risks they are facing, and how to reduce them by contributing back to their OSS ecosystem. Remember, a company's overall sustainability could rely heavily on its ecosystem sustainability.
+
+A good strategy is to start shifting your company from being pure OSS consumers to becoming contributors to their OSS inbound projects. From just submitting issues and asking questions to help solve issues, answering questions, and even sending patches, contributing helps grow and maintain the project while giving back to the community. It doesn't happen immediately, but over time, the company will be perceived as an OSS ecosystem citizen. Eventually, some people from the company could end up helping to maintain those projects too.
+
+And what about money? There are plenty of ways to support the OSS ecosystem financially. Some examples:
+
+ * Business initiatives like [Tidelift][22], or [OpenCollective][23]
+ * Foundations and their supporting mechanisms, like [Software Freedom Conservancy][24], or [CommunityBridge][25] from the Linux Foundation
+ * Self-funding programs (like [Indeed][26] and [Salesforce][27] have done)
+ * Emerging gig development approaches like [Github Sponsors][28] or [Patreon][29]
+
+
+
+Last but not least, companies need to avoid the "not invented here" syndrome. For some OSS projects, there might be companies providing consulting, customization, maintenance, and/or support services. Instead of taking OSS and spending time and people to self-host, self-customize, or try to bring those kinds of services in-house, it might be smarter and more efficient to hire some of those companies to do the thought work.
+
+As a final remark, I would like to emphasize the importance of an OSPO for a company to succeed and grow in the current market. As shepherds of the company's OSS ecosystem, they are the best people in the organization to understand how the ecosystem works and flows, and they should be empowered to manage, monitor, and make recommendations and decisions to ensure sustainability and growth.
+
+Does your organization have an OSPO yet?
+
+Six common traits of successful open source programs, and a look back at how the open source...
+
+Why would a company not in the business of software development create an open source program...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/open-source-program-office
+
+作者:[J. Manrique Lopez de la Fuente][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jsmanrique
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/meeting_discussion_brainstorm.png?itok=7_m4CC8S (community team brainstorming ideas)
+[2]: https://opensource.com/sites/default/files/uploads/ospo_1.png (OSS inbound and outbound processes)
+[3]: https://todogroup.org/
+[4]: https://todogroup.org/guides/
+[5]: https://chaoss.community/
+[6]: https://chaoss.community/metrics/
+[7]: https://github.com/chaoss/wg-common
+[8]: https://github.com/chaoss/wg-diversity-inclusion
+[9]: https://github.com/chaoss/wg-evolution
+[10]: https://github.com/chaoss/wg-risk
+[11]: https://github.com/chaoss/wg-value
+[12]: https://github.com/chaoss/augur
+[13]: https://github.com/cregit
+[14]: https://chaoss.github.io/grimoirelab/
+[15]: https://cauldron.io/
+[16]: https://opensource.com/sites/default/files/uploads/ospo_2.png (CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io)
+[17]: https://en.wikipedia.org/wiki/GQM
+[18]: https://opensource.com/sites/default/files/uploads/ospo_3.png (Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io)
+[19]: https://opensource.com/sites/default/files/uploads/ospo_4.png (Uber OSS activity based on location. Source: uber.biterg.io)
+[20]: https://opensource.com/sites/default/files/uploads/ospo_5_0.png (Uber OSS network. Source: uber.biterg.io)
+[21]: https://opensource.com/sites/default/files/uploads/ospo_6.png (Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io)
+[22]: https://tidelift.com/
+[23]: https://opencollective.com/
+[24]: https://sfconservancy.org/
+[25]: https://funding.communitybridge.org/
+[26]: https://engineering.indeedblog.com/blog/2019/02/sponsoring-osi/
+[27]: https://sustain.codefund.fm/23
+[28]: https://help.github.com/en/github/supporting-the-open-source-community-with-github-sponsors
+[29]: https://www.patreon.com/
diff --git a/sources/tech/20200508 Metaphors in man pages.md b/sources/tech/20200508 Metaphors in man pages.md
new file mode 100644
index 0000000000..8a9ea9c3b9
--- /dev/null
+++ b/sources/tech/20200508 Metaphors in man pages.md
@@ -0,0 +1,182 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Metaphors in man pages)
+[#]: via: (https://jvns.ca/blog/2020/05/08/metaphors-in-man-pages/)
+[#]: author: (Julia Evans https://jvns.ca/)
+
+Metaphors in man pages
+======
+
+This morning I was watching a [great talk by Maggie Appleton][1] about metaphors. In the talk, she explains the difference between a “figurative metaphor” and a “cognitive metaphor”, and references this super interesting book called [Metaphors We Live By][2] which I immediately got and started reading.
+
+Here’s an example from “Metaphors We Live By” of a bunch of metaphors we use for ideas:
+
+ * ideas as **food**: “_raw_ facts”, “_half-baked_ ideas”, “_swallow_ that claim”, “_spoon-feed_ our students”, “_meaty_ part of the paper”, “that idea has been _fermenting_ for years”
+ * ideas as **people**: “the theory of relativity _gave birth_ to an enormous number of ideas”, “whose _brainchild_ was that”, “those ideas _died off_ in the middle ages”, “cognitive psychology is in its _infancy_“
+ * ideas as **products**: “we’ve _generated_ a lot of ideas this week”, “it needs to be _refined_”, “his _intellectual productivity_ has decreased in recent years”
+ * ideas as **commodities**: “he won’t _buy_ that”, “that’s a _worthless_ idea”, “she has _valuable_ ideas”
+ * ideas as **resources**: “he _ran out_ of ideas”, “let’s _pool_ our ideas”, “that idea will _go a long way_“
+ * ideas as **cutting instruments**: “that’s an _incisive_ idea”, “that _cuts right to the heart_ of the matter”, “he’s _sharp_“
+ * ideas as **fashions**: “that idea _went out of style_ years ago”, “marxism is _fashionable_ in western europe”, “berkeley is a center of _avant-garde_ thought”, “semiotics has become quite _chic_“
+
+
+
+There’s a [long list of more English metaphors here][3], including many metaphors from the book.
+
+I was surprised that there were so many different metaphors for ideas, and that we’re using metaphors like this all the time in normal language.
+
+### let’s look for metaphors in man pages!
+
+Okay, let’s get to the point of this blog post, which is just a small fun exploration – there aren’t going to be any Deep Programming Insights here.
+
+I went through some of the examples of metaphors in Metaphors To Live By and grepped all the man pages on my computer for them.
+
+### processes as people
+
+This is one of the richer categories – a lot of different man pages seem to agree that processes are people, or at least alive in some way.
+
+ * Hangup detected on controlling terminal or **death** of controlling process (`man 7 signal`)
+ * can access the local **agent** through the forwarded connection (`man ssh_config`)
+ * If the exit of the process causes a process group to become **orphaned** (`man exit`)
+ * If a parent process terminates, then its **“zombie” children** (if any) (`man wait`)
+ * … send SIGHUP to the **parent** process of the client (`man tmux`)
+ * Otherwise, it **“runs” to catch up** or waits (`man mplayer`)
+ * However, Git does not (and it should not) change tags **behind users back** (`man git-tag`)
+ * will **listen** forever for a connection (`man nc_openbsd`)
+ * this monitor scales badly with the number of files being **observed** (`man fswatch`)
+ * If you try to use the **birth** time of a reference file (`man file`)
+ * a program **died** due to a fatal signal (`man xargs`)
+ * protocol version in the TLS **handshake** (`man curl`)
+ * it will **look for** a debug object at… (`man valgrind`)
+
+
+
+### data as food
+
+ * “Apparently some digital cameras get **indigestion** if you feed them a CF card) (`man mkfs`)
+ * “Send packets using **raw** ethernet frames or IP packets” (`man nmap`)
+ * “the above example can be thought of as a maximizing repeat that must **swallow** everything it can” (`man pcrepattern`)
+ * “This will allow you to **feed** newline-delimited name=value pairs to the script on’ (`man CGI`)
+
+
+
+### data as objects
+
+ * Kill the tmux server and clients and **destroy** all sessions (`tmux`)
+ * Each command will produce one **block** of output on standard output. (`man tmux`)
+ * “HTTPS guarantees that the password will not **travel** in the clear” (`man Net::SSLeay`)
+ * “way to **pack** more than one certificate into an ASN.1 structure” (`man gpgsm`)
+
+
+
+### processes as machines/objects
+
+ * “This is **fragile**, subject to change, and thus should not be relied upon” (`man ps`)
+ * “This is useful if you have to use **broken** DNS” (`man aria2c`)
+ * “This provides good safety measures, but **breaks down** when” (`man git-apply`)
+ * “debugfs is a debugging tool. It has **rough edges**!” (`man debugfs`)
+
+
+
+### containers
+
+There are LOTS of containers: directories, files, strings, caches, queues, buffers, etc.
+
+ * can exploit that to **get out** of the chroot directory (`man chroot`)
+ * “The file **containing** the RFC 4648 Section 5 base64url encoded 128-bit secret key”
+ * “Keys must start with a lowercase character and **contain** only hyphens”
+ * “just specify an **empty** string” (`man valgrind`)
+ * “the cache is **full** and a new page that isn’t cached becomes visible” (`man zathurarc`)
+ * “Number of table **overflows**” (`man lnstat`)
+ * “likely **overflow** the buffer” (`man g++`)
+
+
+
+### resources
+
+There are also lots of kinds of resources: bandwidth, TCP sockets, session IDs, stack space, memory, disk space.
+
+ * This is not recommended and **wastes** bitrate (`man bitrate`)
+ * corruption or **lost** data if the system crashes (`man btree`)
+ * you don’t want Wget to **consume** the entire available bandwidth (`man wget`)
+ * Larger values will be slower and cause x264 to **consume** more memory (`man mplayer`)
+ * the resulting file can **consume** some disk space (`man socat`)
+ * attempting to **reuse** SSL session-ID (`man curl`)
+ * This option controls stack space **reuse** (`man gcc`)
+ * Keep the TCP socket open between queries and **reuse** it rather than creating a new TCP socket (`man dig`)
+ * the maximum value will easily **eat up** three extra gigabytes or so of memory (`man valgrind`)
+
+
+
+### orientation (up, down, above, below)
+
+ * Send the escape character to the **frontend** (`man qemu-system`)
+ * Note that TLS 1.3 is only supported by a subset of TLS **backends** (`man curl`)
+ * This option may be useful if you are **behind** a router (`man mplayer`)
+ * When a file that exists on the **lower** layer is renamed (`man rename`)
+ * Several of the socket options should be handled at **lower** levels (`man getsockopt`)
+ * while still performing such **higher** level functionality (`man nmap`)
+ * This is the same string passed **back to** the front end (`man sudo_plugin`)
+ * On Linux, `futimens` is a library function implemented **on top** of the `utimensat` system call (`man futimens`)
+
+
+
+### buildings
+
+Limits as rooms/buildings (which have floors, and ceilings, which you hit) are kind of fun:
+
+ * the kernel places a **floor** of 32 pages on this size limit (`man execve`)
+ * This specifies a **ceiling** to which the process’s nice value can be raised (`man getrlimit`)
+ * If this limit is **hit** the search is aborted (`man gcc`)
+ * these libraries are used as the **foundation** for many of the libraries (`man Glib`)
+
+
+
+### money / wealth
+
+ * This is a very **expensive** operation for large projects, so use it with caution (`man git-log`)
+ * Note that since this operation is very I/O **expensive** (`man git-filter-branch`)
+ * provides a **rich** interface for scripts to print disk layouts (`man fdisk`)
+ * The number of times the softirq handler function terminated per second because its **budget** was consumed (`man sar.sysstat`)
+ * the extra **cost** depends a lot on the application at hand (`man valgrind`)
+
+
+
+### more miscellaneous metaphors
+
+here are some more I found that didn’t fit into any of those categories yet.
+
+ * when a thread is created under glibc, just one **big** lock is used for all thread setup (`man valgrind`)
+ * will likely **drop** the connection (`man x11vnc`)
+ * on all **paths** from the load to the function entry (`man gcc`)
+ * it is a very good idea to **wipe** filesystem signatures, data, etc. before (`man cryptsetup`)
+ * they will be **embedded** into the document
+ * the client should automatically **follow** referrals returned
+ * even if there exist mappings that **cover** the whole address space requested (`man mremap`)
+ * when a network interface **disappears** (`man systemd-resolve`)
+
+
+
+### we’re all using metaphors all the time
+
+I found a lot more metaphors than I expected, and most of them are just part of how I’d normally talk about a program. Interesting!
+
+--------------------------------------------------------------------------------
+
+via: https://jvns.ca/blog/2020/05/08/metaphors-in-man-pages/
+
+作者:[Julia Evans][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://jvns.ca/
+[b]: https://github.com/lujun9972
+[1]: https://www.youtube.com/watch?v=K8MF3aDg-bM&feature=youtu.be&t=14991
+[2]: https://www.goodreads.com/book/show/34459.Metaphors_We_Live_By
+[3]: https://metaphor.icsi.berkeley.edu/pub/en/index.php/Category:Metaphor
diff --git a/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md b/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md
new file mode 100644
index 0000000000..5ce9ce0a1f
--- /dev/null
+++ b/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md
@@ -0,0 +1,86 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source underpins coronavirus IoT and robotics solutions)
+[#]: via: (https://opensource.com/article/20/5/robotics-covid19)
+[#]: author: (Sam Bocetta https://opensource.com/users/sambocetta)
+
+Open source underpins coronavirus IoT and robotics solutions
+======
+From sanitization of equipment and facilities to plotting the spread of
+the virus, robots are playing an active role in combating COVID-19.
+![Three giant robots and a person][1]
+
+The tech sector is quietly having a boom during the COVID-19 pandemic. Open source developers are getting involved with many aspects of the fight against the coronavirus, [using Python to visualize its spread][2] and helping to repurpose data acquisition systems to perform contact tracing.
+
+However, one of the most exciting areas of current research is the use of robotics to contain the spread of the coronavirus. In the last few weeks, robots have been deployed in critical environments—particularly in hospitals and on airplanes—to help staff sterilize surfaces and objects.
+
+Most of these robots are produced by tech startups, who have seen an opportunity to prove the worth of their proprietary systems. Many of them, however, rely on [open source cloud and IoT tools][3] that have been developed by the open source community.
+
+In this article, we'll take a look at how robotics are being used to fight the disease, the IoT infrastructure that underpins these systems, and finally, the security and privacy concerns that their increased use is highlighting.
+
+### Robots and COVID-19
+
+Around the world, robots are being deployed to help the fight against COVID-19. The most direct use of robots has been in healthcare facilities, and China has taken the lead when it comes to deploying robots in hospitals.
+
+For example, a field hospital that recently opened in Wuhan—where the virus originated—is [making extensive use of robots][4] to help healthcare workers care for patients. Some of these robots provide food, drink, and medicine to patients, and others are used to clean parts of the hospital.
+
+Other companies, such as the Texas startup Xenex Disinfection Services, are using robots and UV light to deactivate viruses, bacteria, and spores on surfaces in airports. Still others, like Dimer UVC Innovations, are focusing on making robots that can [improve aircraft hygiene][5].
+
+Not all of the "robots" deployed against the disease are anthropomorphic, though. The same field hospital in Wuhan that is using human-like robots is also making extensive use of less obviously "robotic" IoT devices.
+
+Patients entering the hospital are screened by networked 5G thermometers to alert staff for anyone showing a high fever, and patients wear smart bracelets and rings equipped with sensors. These are synced with CloudMinds' AI platform, and patients' vital signs, including temperature, heart rate, and blood oxygen levels, can be monitored.
+
+### Robots and the IoT
+
+Even when these robots appear to be independent entities, they make [extensive use of the IoT][6]. In other words, although patients may feel that they are being cared for by a robot that can make its own decisions, in reality, these robots are controlled by large, distributed sensing and data processing systems.
+
+Although many of the robots being deployed are the proprietary property of the tech firms who produce their hardware, their functioning is based on an ecosystem of software that is largely open source.
+
+This observation is an important one because it overturns one of the primary misconceptions about the [way that AI is used today][7][,][7] whether in a healthcare setting or elsewhere. Most research into robotics today does not seek to embed fully intelligent AI systems into robots themselves but, instead, uses centralized AI systems to control a wide variety of far less "smart" IoT devices.
+
+This observation, in turn, highlights two key points about the robots currently being developed and used to fight COVID-19. One is that they rely on a software ecosystem—much of it open source—that has been developed in a truly collaborative process involving thousands of engineers. The second is that the networked nature of these robots makes them vulnerable to exploitation.
+
+### Security and privacy
+
+This vulnerability to cybersecurity threats has led some analysts to raise questions about the wisdom of widespread deployment of IoT-driven robotics, whether in the healthcare system or anywhere else. Spyware in the IoT [remains a huge problem][8], and some fear that by integrating IoT systems into healthcare, we may be exposing more data—and more sensitive data—to intruders.
+
+Even where developers are careful to build security into these devices, the sheer number of components they rely on makes DevSecOps processes difficult to implement. Especially in this current time of crisis, many software engineers have been forced to accelerate the release of new components, and this could lead to them being vulnerable. If a company is rushing to bring a healthcare robot onto the market in response to COVID-19, it's unlikely that the open source code that these devices run on will be [properly audited][9].
+
+And even if companies are able to maintain the integrity of their DevSecOps processes while still accelerating development, it's far from certain that patients themselves understand the privacy implications of delegating their care to IoT devices. Many lack the open source privacy tools [necessary to keep their data private][10] when browsing the internet, let alone those that should be deployed to protect sensitive healthcare data.
+
+### The future
+
+In short, the deployment of robots in the fight against COVID-19 is highlighting long-standing concerns about the integrity, security, and privacy of IoT systems more generally. Professionals in this field have long argued that [IoT audits][11] and [embedded Linux systems][12] should be the standard for IoT development, but in the current crisis, their warnings are likely to be ignored.
+
+This is worrying because it's likely that IoT systems will be increasingly used in healthcare in the coming decade. So whilst the COVID-19 pandemic will provide a proof of their utility in this sector, it should also not be used as an excuse to roll out poorly secured, poorly audited IoT software in highly sensitive environments.
+
+Open source isn’t just changing the way we interact with the world, it’s changing the way the world...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/robotics-covid19
+
+作者:[Sam Bocetta][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sambocetta
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_robots.png?itok=TOZgajrd (Three giant robots and a person)
+[2]: https://opensource.com/article/20/4/python-data-covid-19
+[3]: https://opensource.com/article/18/7/digital-transformation-strategy-think-cloud
+[4]: https://www.cnbc.com/2020/03/18/how-china-is-using-robots-and-telemedicine-to-combat-the-coronavirus.html
+[5]: https://www.therobotreport.com/company-offers-germ-killing-robot-to-airports-to-address-coronavirus-outbreak/
+[6]: https://www.cloudwards.net/what-is-the-internet-of-things/
+[7]: https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives
+[8]: https://blog.eccouncil.org/spyware-in-the-iot-what-does-it-mean-for-your-online-privacy/
+[9]: https://opensource.com/article/17/10/doc-audits
+[10]: https://privacyaustralia.net/privacy-tools/
+[11]: https://opensource.com/article/19/11/how-many-iot-devices
+[12]: https://opensource.com/article/17/3/embedded-linux-iot-ecosystem
diff --git a/sources/tech/20200511 How I track my home-s energy consumption with open source.md b/sources/tech/20200511 How I track my home-s energy consumption with open source.md
new file mode 100644
index 0000000000..10dfaa5f8e
--- /dev/null
+++ b/sources/tech/20200511 How I track my home-s energy consumption with open source.md
@@ -0,0 +1,144 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I track my home's energy consumption with open source)
+[#]: via: (https://opensource.com/article/20/5/energy-monitoring)
+[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
+
+How I track my home's energy consumption with open source
+======
+These open source components help you find ways to save money and
+conserve resources.
+![lightbulb drawing outline][1]
+
+An important step towards optimizing energy consumption is knowing your actual consumption. My house was built during the oil crisis in the 1970s, and due to the lack of a natural gas connection, the builders decided to use electricity to do all of the heating (water and home heating). This is not unusual for this area of Germany, and it remains an appropriate solution in countries that depend highly on nuclear power.
+
+Electricity prices here are quite high (around € 0.28/kWh), so I decided to monitor my home's energy consumption to get a feel for areas where I could save some energy.
+
+I used to work for a company that sold energy-monitoring systems for industrial customers. While this company mostly used proprietary software, you can set up a similar smart monitoring and logging solution for your home based on open source components. This article will show you how.
+
+In Germany, the grid operator owns the electricity meter. The grid operator is obliged to provide an interface on its metering device to enable the customer to access the meter reading. Here is the metering device on my home:
+
+![Actaris ACE3000 electricity meter][2]
+
+Actaris ACE3000 Type 110 (dry contact located behind the marked cover)
+
+Generally, almost every metering device has at least a [dry contact][3]—as my electricity meter does—that you can use to log metering. As you can see, my electricity meter has two counters: The upper one is for the day tariff (6am to 10pm), and the lower one is for the night tariff (10pm to 6am). The night tariff is a bit cheaper. Two-tariff meters are usually found only in houses with electric heating.
+
+### Design
+
+A reliable energy-monitoring solution for private use should meet the following requirements:
+
+ * Logging of metering impulses (dry contact)
+ * 24/7 operation
+ * Energy-saving operation
+ * Visualization of consumption data
+ * Long-term recording of consumption data
+ * Connectivity (e.g., Ethernet, USB, WiFi, etc.)
+ * Affordability
+
+
+
+I choose the Siemens SIMATIC IOT2020 as my hardware platform. This industrial-proven device is based on an Intel Quark x86 CPU, has programmable interrupts, and is compatible with many Arduino shields.
+
+![Siemens SIMATIC IOT2020][4]
+
+Siemens SIMATIC IOT2020
+
+The Siemens device comes without an SD card and, therefore, without an operating system. Luckily, you can find a current Yocto-based Linux OS image and instructions on how to flash the SD card in the [Siemens forum][5].
+
+In addition to the hardware platform, you also need some accessories. The following materials list shows the minimum components you need. Each item includes links to the parts I purchased, so you can get a sense of the project's costs.
+
+#### Materials list
+
+ * [Siemens SIMATIC IoT2020 unit][6]
+ * [Siemens I/O Shield for SIMATIC IoT2000 series][7]
+ * [microSD card][8] (2GB or more)
+ * [CSL 300Mbit USB-WLAN adapter][9]
+ * 24V power supply (I used a 2.1A [TDK-Lambda DRB50-24-1][10], which I already owned). You could use a less expensive power supply with less power: the SIMATIC IOT2020 has a maximum current of 1.4A, and the dry contact needs an additional 0.1A (24V / 220Ω).
+ * 5 terminal blocks ([Weidmueller WDU 2.5mm][11])
+ * 2 terminal cross-connecting bridges ([Weidmueller WQV][12])
+ * [DIN rail][13] (~300 mm)
+ * [220Ω / 3W resistor][14]
+ * Wire
+
+
+
+Here is the assembled result:
+
+![Mounted and hooked up energy logger][15]
+
+Energy logger mounted and hooked up
+
+Unfortunately, I didn't have enough space at the rear wall of the cabinet; therefore, the DIN rail with the mounted parts lies on the ground.
+
+The connections between the meter and the Siemens device look like this:
+
+![Wiring between meter and energy logger][16]
+
+### How it works
+
+A dry contact is a current interface. When the electricity meter triggers, a current of 0.1A starts flowing between **s0+** and **s0-**. On **DI0**, the voltage rises to 24V and triggers an interrupt. When the electricity meter disconnects **s0+** and **s0-**, **DI0** is grounded over the resistor.
+
+On my device, the contact closes 1,000 times per kWh (this value varies between metering devices).
+
+To count these peaks reliably, I created [a C program][17] that registers an interrupt service routine on the DI0 input and counts upwards in memory. Once a minute, the values from memory are written to an [SQLite][18] database.
+
+The overall meter reading is also written to a text file and can be preset with a starting value. This acts as a copy of the overall metering value of the meter in the cabinet.
+
+![Energy logger architecture][19]
+
+Energy logger architecture
+
+The data is visualized using [Node-RED][20], and I can access overviews, like the daily consumption dashboard below, over a web-based GUI.
+
+![Node-RED based GUI][21]
+
+Daily overview in the Node-RED GUI
+
+For the daily overview, I calculate the hourly costs based on the consumption data (the large bar chart). On the top-left of the dashboard you can see the actual power; below that is the daily consumption (energy and costs). The water heater for the shower causes the large peak in the bar chart.
+
+### A reliable system
+
+Aside from a lost timestamp during a power failure (the real-time clock in the Siemens device is not backed by a battery by default), everything has been working fine for more than one-and-a-half years.
+
+If you can set up the whole Linux system completely from the command line, you'll get a reliable and flexible system with the ability to link interrupt service routines to the I/O level.
+
+Because the I/O Shield runs on standard control voltage (24V), you can extend its functionality with the whole range of standardized industrial components (e.g., relays, sensors, actors, etc.). And, due to its open architecture, this system can be extended easily and applied to other applications, like for monitoring gas or water consumption or as a weather station, a simple controller for tasks, and more.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/energy-monitoring
+
+作者:[Stephan Avenwedde][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hansic99
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/Collaboration%20for%20health%20innovation.png?itok=s4O5EX2w (lightbulb drawing outline)
+[2]: https://opensource.com/sites/default/files/uploads/openenergylogger_1_electricity_meter.jpg (Actaris ACE3000 electricity meter)
+[3]: https://en.wikipedia.org/wiki/Dry_contact
+[4]: https://opensource.com/sites/default/files/uploads/openenergylogger_2_siemens_device.jpg (Siemens SIMATIC IOT2020)
+[5]: https://support.industry.siemens.com/tf/ww/en/posts/new-example-image-version-online/189090/?page=0&pageSize=10
+[6]: https://de.rs-online.com/web/p/products/1244037
+[7]: https://de.rs-online.com/web/p/products/1354133
+[8]: https://de.rs-online.com/web/p/micro-sd-karten/7582584/
+[9]: https://www.amazon.de/300Mbit-WLAN-Adapter-Hochleistungs-Antennen-Dual-Band/dp/B00LLIOT34
+[10]: https://de.rs-online.com/web/p/products/8153133
+[11]: https://de.rs-online.com/web/p/din-schienenklemmen-ohne-sicherung/0425190/
+[12]: https://de.rs-online.com/web/p/din-schienenklemmen-zubehor/0202574/
+[13]: https://de.rs-online.com/web/p/din-schienen/2835729/
+[14]: https://de.rs-online.com/web/p/widerstande-durchsteckmontage/2142673/
+[15]: https://opensource.com/sites/default/files/uploads/openenergylogger_3_assembled_device.jpg (Mounted and hooked up energy logger)
+[16]: https://opensource.com/sites/default/files/uploads/openenergylogger_4_wiring.png (Wiring between meter and energy logger)
+[17]: https://github.com/hANSIc99/OpenEnergyLogger
+[18]: https://www.sqlite.org/index.html
+[19]: https://opensource.com/sites/default/files/uploads/openenergylogger_5_architecure.png (Energy logger architecture)
+[20]: https://nodered.org/
+[21]: https://opensource.com/sites/default/files/uploads/openenergylogger_6_dashboard.png (Node-RED based GUI)
diff --git a/sources/tech/20200511 Start using systemd as a troubleshooting tool.md b/sources/tech/20200511 Start using systemd as a troubleshooting tool.md
new file mode 100644
index 0000000000..372be7660e
--- /dev/null
+++ b/sources/tech/20200511 Start using systemd as a troubleshooting tool.md
@@ -0,0 +1,269 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Start using systemd as a troubleshooting tool)
+[#]: via: (https://opensource.com/article/20/5/systemd-troubleshooting-tool)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Start using systemd as a troubleshooting tool
+======
+While systemd is not really a troubleshooting tool, the information in
+its output points the way toward solving problems.
+![Magnifying glass on code][1]
+
+No one would really consider systemd to be a troubleshooting tool, but when I encountered a problem on my webserver, my growing knowledge of systemd and some of its features helped me locate and circumvent the problem.
+
+The problem was that my server, yorktown, which provides name services, DHCP, NTP, HTTPD, and SendMail email services for my home office network, failed to start the Apache HTTPD daemon during normal startup. I had to start it manually after I realized that it was not running. The problem had been going on for some time, and I recently got around to trying to fix it.
+
+Some of you will say that systemd itself is the cause of this problem, and, based on what I know now, I agree with you. However, I had similar types of problems with SystemV. (In the [first article][2] in this series, I looked at the controversy around systemd as a replacement for the old SystemV init program and startup scripts. If you're interested in learning more about systemd, read the [second][3] and [third][4] articles, too.) No software is perfect, and neither systemd nor SystemV is an exception, but systemd provides far more information for problem-solving than SystemV ever offered.
+
+### Determining the problem
+
+The first step to finding the source of this problem is to determine the httpd service's status:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Active: failed (Result: exit-code) since Thu 2020-04-16 11:54:37 EDT; 15min ago
+ Docs: man:httpd.service(8)
+ Process: 1101 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
+ Main PID: 1101 (code=exited, status=1/FAILURE)
+ Status: "Reading configuration..."
+ CPU: 60ms
+
+Apr 16 11:54:35 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: (99)Cannot assign requested address: AH00072: make_sock: could not bind to address 192.168.0.52:80
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: no listening sockets available, shutting down
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: AH00015: Unable to open logs
+Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
+Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Failed with result 'exit-code'.
+Apr 16 11:54:37 yorktown.both.org systemd[1]: Failed to start The Apache HTTP Server.
+[root@yorktown ~]#
+```
+
+This status information is one of the systemd features that I find much more useful than anything SystemV offers. The amount of helpful information here leads me easily to a logical conclusion that takes me in the right direction. All I ever got from the old **chkconfig** command is whether or not the service is running and the process ID (PID) if it is. That is not very helpful.
+
+The key entry in this status report shows that HTTPD cannot bind to the IP address, which means it cannot accept incoming requests. This indicates that the network is not starting fast enough to be ready for the HTTPD service to bind to the IP address because the IP address has not yet been set. This is not supposed to happen, so I explored my network service systemd startup configuration files; all appeared to be correct with the right "after" and "requires" statements. Here is the **/lib/systemd/system/httpd.service** file from my server:
+
+
+```
+# Modifying this file in-place is not recommended, because changes
+# will be overwritten during package upgrades. To customize the
+# behaviour, run "systemctl edit httpd" to create an override unit.
+
+# For example, to pass additional options (such as -D definitions) to
+# the httpd binary at startup, create an override unit (as is done by
+# systemctl edit) and enter the following:
+
+# [Service]
+# Environment=OPTIONS=-DMY_DEFINE
+
+[Unit]
+Description=The Apache HTTP Server
+Wants=httpd-init.service
+After=network.target remote-fs.target nss-lookup.target httpd-init.service
+Documentation=man:httpd.service(8)
+
+[Service]
+Type=notify
+Environment=LANG=C
+
+ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
+ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
+# Send SIGWINCH for graceful stop
+KillSignal=SIGWINCH
+KillMode=mixed
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
+```
+
+The **httpd.service** unit file explicitly specifies that it should load after the **network.target** and the **httpd-init.service** (among others). I tried to find all of these services using the **systemctl list-units** command and searching for them in the resulting data stream. All were present and should have ensured that the httpd service did not load before the network IP address was set.
+
+### First solution
+
+A bit of searching on the internet confirmed that others had encountered similar problems with httpd and other services. This appears to happen because one of the required services indicates to systemd that it has finished its startup—but it actually spins off a child process that has not finished. After a bit more searching, I came up with a circumvention.
+
+I could not figure out why the IP address was taking so long to be assigned to the network interface card. So, I thought that if I could delay the start of the HTTPD service by a reasonable amount of time, the IP address would be assigned by that time.
+
+Fortunately, the **/lib/systemd/system/httpd.service** file above provides some direction. Although it says not to alter it, it does indicate how to proceed: Use the command **systemctl edit httpd**, which automatically creates a new file (**/etc/systemd/system/httpd.service.d/override.conf**) and opens the [GNU Nano][5] editor. (If you are not familiar with Nano, be sure to look at the hints at the bottom of the Nano interface.)
+
+Add the following text to the new file and save it:
+
+
+```
+[root@yorktown ~]# cd /etc/systemd/system/httpd.service.d/
+[root@yorktown httpd.service.d]# ll
+total 4
+-rw-r--r-- 1 root root 243 Apr 16 11:43 override.conf
+[root@yorktown httpd.service.d]# cat override.conf
+# Trying to delay the startup of httpd so that the network is
+# fully up and running so that httpd can bind to the correct
+# IP address
+#
+# By David Both, 2020-04-16
+
+[Service]
+ExecStartPre=/bin/sleep 30
+```
+
+The **[Service]** section of this override file contains a single line that delays the start of the HTTPD service by 30 seconds. The following status command shows the service status during the wait time:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Drop-In: /etc/systemd/system/httpd.service.d
+ └─override.conf
+ /usr/lib/systemd/system/httpd.service.d
+ └─php-fpm.conf
+ Active: activating (start-pre) since Thu 2020-04-16 12:14:29 EDT; 28s ago
+ Docs: man:httpd.service(8)
+Cntrl PID: 1102 (sleep)
+ Tasks: 1 (limit: 38363)
+ Memory: 260.0K
+ CPU: 2ms
+ CGroup: /system.slice/httpd.service
+ └─1102 /bin/sleep 30
+
+Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.
+[root@yorktown ~]#
+```
+
+And this command shows the status of the HTTPD service after the 30-second delay expires. The service is up and running correctly:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Drop-In: /etc/systemd/system/httpd.service.d
+ └─override.conf
+ /usr/lib/systemd/system/httpd.service.d
+ └─php-fpm.conf
+ Active: active (running) since Thu 2020-04-16 12:15:01 EDT; 1min 18s ago
+ Docs: man:httpd.service(8)
+ Process: 1102 ExecStartPre=/bin/sleep 30 (code=exited, status=0/SUCCESS)
+ Main PID: 1567 (httpd)
+ Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
+ Tasks: 213 (limit: 38363)
+ Memory: 21.8M
+ CPU: 82ms
+ CGroup: /system.slice/httpd.service
+ ├─1567 /usr/sbin/httpd -DFOREGROUND
+ ├─1569 /usr/sbin/httpd -DFOREGROUND
+ ├─1570 /usr/sbin/httpd -DFOREGROUND
+ ├─1571 /usr/sbin/httpd -DFOREGROUND
+ └─1572 /usr/sbin/httpd -DFOREGROUND
+
+Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.
+```
+
+I could have experimented to see if a shorter delay would work as well, but my system is not that critical, so I decided not to. It works reliably as it is, so I am happy.
+
+Because I gathered all this information, I reported it to Red Hat Bugzilla as Bug [1825554][6]. I believe that it is much more productive to report bugs than it is to complain about them.
+
+### The better solution
+
+A couple of days after reporting this as a bug, I received a response indicating that systemd is just the manager, and if httpd needs to be ordered after some requirements are met, it needs to be expressed in the unit file. The response pointed me to the **httpd.service** man page. I wish I had found this earlier because it is a better solution than the one I came up with. This solution is explicitly targeted to the prerequisite target unit rather than a somewhat random delay.
+
+From the [**httpd.service** man page][7]:
+
+> **Starting the service at boot time**
+>
+> The httpd.service and httpd.socket units are _disabled_ by default. To start the httpd service at boot time, run: **systemctl enable httpd.service**. In the default configuration, the httpd daemon will accept connections on port 80 (and, if mod_ssl is installed, TLS connections on port 443) for any configured IPv4 or IPv6 address.
+>
+> If httpd is configured to depend on any specific IP address (for example, with a "Listen" directive) which may only become available during start-up, or if httpd depends on other services (such as a database daemon), the service _must_ be configured to ensure correct start-up ordering.
+>
+> For example, to ensure httpd is only running after all configured network interfaces are configured, create a drop-in file (as described above) with the following section:
+>
+> [Unit]
+> After=network-online.target
+> Wants=network-online.target
+
+I still think this is a bug because it is quite common—at least in my experience—to use a **Listen** directive in the **httpd.conf** configuration file. I have always used **Listen** directives, even on hosts with only a single IP address, and it is clearly necessary on hosts with multiple network interface cards (NICs) and internet protocol (IP) addresses. Adding the lines above to the **/usr/lib/systemd/system/httpd.service** default file would not cause problems for configurations that do not use a **Listen** directive and would prevent this problem for those that do.
+
+In the meantime, I will use the suggested solution.
+
+### Next steps
+
+This article describes a problem I had with starting the Apache HTTPD service on my server. It leads you through the problem determination steps I took and shows how I used systemd to assist. I also covered the circumvention I implemented using systemd and the better solution that followed from my bug report.
+
+As I mentioned at the start, it is very likely that this is the result of a problem with systemd, specifically the configuration for httpd startup. Nevertheless, systemd provided me with the tools to locate the likely source of the problem and to formulate and implement a circumvention. Neither solution really resolves the problem to my satisfaction. For now, the root cause of the problem still exists and must be fixed. If that is simply adding the recommended lines to the **/usr/lib/systemd/system/httpd.service** file, that would work for me.
+
+One of the things I discovered during this is process is that I need to learn more about defining the sequences in which things start. I will explore that in my next article, the fifth in this series.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][8] [to systemd][8]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][9] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][10]'s [description of systemd][11].
+ * [Linux.com][12]'s "More systemd fun" offers more advanced systemd [information and tips][13].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][14]
+ * [systemd for Administrators, Part I][15]
+ * [systemd for Administrators, Part II][16]
+ * [systemd for Administrators, Part III][17]
+ * [systemd for Administrators, Part IV][18]
+ * [systemd for Administrators, Part V][19]
+ * [systemd for Administrators, Part VI][20]
+ * [systemd for Administrators, Part VII][21]
+ * [systemd for Administrators, Part VIII][22]
+ * [systemd for Administrators, Part IX][23]
+ * [systemd for Administrators, Part X][24]
+ * [systemd for Administrators, Part XI][25]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-troubleshooting-tool
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/find-file-linux-code_magnifying_glass_zero.png?itok=E2HoPDg0 (Magnifying glass on code)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: https://opensource.com/article/20/4/systemd-startup
+[4]: https://opensource.com/article/20/4/understanding-and-using-systemd-units
+[5]: https://www.nano-editor.org/
+[6]: https://bugzilla.redhat.com/show_bug.cgi?id=1825554
+[7]: https://www.mankier.com/8/httpd.service#Description-Starting_the_service_at_boot_time
+[8]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[9]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[10]: http://Freedesktop.org
+[11]: http://www.freedesktop.org/wiki/Software/systemd
+[12]: http://Linux.com
+[13]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[14]: http://0pointer.de/blog/projects/systemd.html
+[15]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[16]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[17]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[18]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[19]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[20]: http://0pointer.de/blog/projects/changing-roots
+[21]: http://0pointer.de/blog/projects/blame-game.html
+[22]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[23]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[24]: http://0pointer.de/blog/projects/instances.html
+[25]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200511 Tips and tricks for optimizing container builds.md b/sources/tech/20200511 Tips and tricks for optimizing container builds.md
new file mode 100644
index 0000000000..0a4fbed8cb
--- /dev/null
+++ b/sources/tech/20200511 Tips and tricks for optimizing container builds.md
@@ -0,0 +1,201 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Tips and tricks for optimizing container builds)
+[#]: via: (https://opensource.com/article/20/5/optimize-container-builds)
+[#]: author: (Ravi Chandran https://opensource.com/users/ravichandran)
+
+Tips and tricks for optimizing container builds
+======
+Try these techniques to minimize the number and length of your container
+build iterations.
+![Toolbox drawing of a container][1]
+
+How many iterations does it take to get a container configuration just right? And how long does each iteration take? Well, if you answered "too many times and too long," then my experiences are similar to yours. On the surface, creating a configuration file seems like a straightforward exercise: implement the same steps in a configuration file that you would perform if you were installing the system by hand. Unfortunately, I've found that it usually doesn't quite work that way, and a few "tricks" are handy for such DevOps exercises.
+
+In this article, I'll share some techniques I've found that help minimize the number and length of iterations. In addition, I'll outline a few good practices beyond the [standard ones][2].
+
+In the [tutorial repository][3] from my previous article about [containerizing build systems][4], I've added a folder called **/tutorial2_docker_tricks** with an example covering some of the tricks that I'll walk through in this post. If you want to follow along and you have Git installed, you can pull it locally with:
+
+
+```
+`$ git clone https://github.com/ravi-chandran/dockerize-tutorial`
+```
+
+The tutorial has been tested with Docker Desktop Edition, although it should work with any compatible Linux container system (like [Podman][5]).
+
+### Save time on container image build iterations
+
+If the Dockerfile involves downloading and installing a 5GB file, each iteration of **docker image build** could take a lot of time even with good network speeds. And forgetting to include one item to be installed can mean rebuilding all the layers after that point.
+
+One way around that challenge is to use a local HTTP server to avoid downloading large files from the internet multiple times during **docker image build** iterations. To illustrate this by example, say you need to create a container image with Anaconda 3 under Ubuntu 18.04. The Anaconda 3 installer is a ~0.5GB file, so this will be the "large" file for this example.
+
+Note that you don't want to use the **COPY** instruction, as it creates a new layer. You should also delete the large installer after using it to minimize the container image size. You could use [multi-stage builds][6], but I've found the following approach sufficient and quite effective.
+
+The basic idea is to use a Python-based HTTP server locally to serve the large file(s) and have the Dockerfile **wget** the large file(s) from this local server. Let's explore the details of how to set this up effectively. As a reminder, you can access the [full example][7].
+
+The necessary contents of the folder **tutorial2_docker_tricks/** in this example repository are:
+
+
+```
+tutorial2_docker_tricks/
+├── build_docker_image.sh # builds the docker image
+├── run_container.sh # instantiates a container from the image
+├── install_anaconda.dockerfile # Dockerfile for creating our target docker image
+├── .dockerignore # used to ignore contents of the installer/ folder from the docker context
+├── installer # folder with all our large files required for creating the docker image
+│ └── Anaconda3-2019.10-Linux-x86_64.sh # from
+└── workdir # example folder used as a volume in the running container
+```
+
+The key steps of the approach are:
+
+ * Place the large file(s) in the **installer/** folder. In this example, I have the large Anaconda installer file **Anaconda3-2019.10-Linux-x86_64.sh**. You won't find this file if you clone my [Git repository][8] because only you, as the container image creator, need this source file. The end users of the image don't. [Download the installer][9] to follow along with the example.
+ * Create the **.dockerignore** file and have it ignore the **installer/** folder to avoid Docker copying all the large files into the build context.
+ * In a terminal, **cd** into the **tutorial2_docker_tricks/** folder and execute the build script as **./build_docker_image.sh**.
+ * In **build_docker_image.sh**, start the Python HTTP server to serve any files from the **installer/** folder: [code] cd installer
+python3 -m http.server --bind 10.0.2.15 8888 &
+cd ..
+```
+* If you're wondering about the strange internet protocol (IP) address, I'm working with a VirtualBox Linux VM, and **10.0.2.15** shows up as the address of the Ethernet adapter when I run **ifconfig**. This IP seems to be the convention used by VirtualBox. If your setup is different, you'll need to update this IP address to match your environment and then update **build_docker_image.sh** and **install_anaconda.dockerfile**. The server's port number is set to **8888** for this example. Note that the IP and port numbers could be passed in as build arguments, but I've hard-coded them for brevity.
+* Since the HTTP server is set to run in the background, stop the server near the end of the script with the **kill -9** command using an [elegant approach][10] I found: [code]`kill -9 `ps -ef | grep http.server | grep 8888 | awk '{print $2}'`
+```
+ * Note that this same **kill -9** is also used earlier in the script (before starting the HTTP server). In general, when I iterate on any build script that I might deliberately interrupt, this ensures a clean start of the HTTP server each time.
+ * In the [Dockerfile][11], there is a **RUN wget** instruction that downloads the Anaconda installer from the local HTTP server. It also deletes the installer file and cleans up after the installation. Most importantly, all these actions are performed within the same layer to keep the image size to a minimum: [code] # install Anaconda by downloading the installer via the local http server
+ARG ANACONDA
+RUN wget --no-proxy -O ~/anaconda.sh \
+ && /bin/bash ~/anaconda.sh -b -p /opt/conda \
+ && rm ~/anaconda.sh \
+ && rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
+```
+ * This file runs the wrapper script, **anaconda.sh**, and cleans up large files by removing them with **rm**.
+ * After the build is complete, you should see an image **anaconda_ubuntu1804:v1**. (You can list the images with **docker image ls**.)
+ * You can instantiate a container from this image using **./run_container.sh** at the terminal while in the folder **tutorial2_docker_tricks/**. You can verify that Anaconda is installed with: [code] $ ./run_container.sh
+$ python --version
+Python 3.7.5
+$ conda --version
+conda 4.8.0
+$ anaconda --version
+anaconda Command line client (version 1.7.2)
+```
+ * You'll note that **run_container.sh** sets up a volume **workdir**. In this example repository, the folder **workdir/** is empty. This is a convention I use to set up a volume where I can have my Python and other scripts that are independent of the container image.
+
+
+
+### Minimize container image size
+
+Each **RUN** command is equivalent to executing a new shell, and each **RUN** command creates a layer. The naive approach of mimicking installation instructions with separate **RUN** commands may eventually break at one or more interdependent steps. If it happens to work, it will typically result in a larger image. Chaining multiple installation steps in one **RUN** command and including the **autoremove**, **autoclean**, and **rm** commands (as in the example below) is useful to minimize the size of each layer. Some of these steps may not be needed, depending on what's being installed. However, since these steps take an insignificant amount of time, I always throw them in for good measure at the end of **RUN** commands invoking **apt-get**:
+
+
+```
+RUN apt-get update \
+ && DEBIAN_FRONTEND=noninteractive \
+ apt-get -y --quiet --no-install-recommends install \
+ # list of packages being installed go here \
+ && apt-get -y autoremove \
+ && apt-get clean autoclean \
+ && rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
+```
+
+Also, ensure that you have a **.dockerignore** file in place to ignore items that don't need to be sent to the Docker build context (such as the Anaconda installer file in the earlier example).
+
+### Organize the build tool I/O
+
+For software build systems, the build inputs and outputs—all the scripts that configure and invoke the tools—should be outside the image and the eventually running container. The container itself should remain stateless so that different users will have identical results with it. I covered this extensively in my [previous article][4] but wanted to emphasize it because it's been a useful convention for my work. These inputs and outputs are best accessed by setting up container volumes.
+
+I've had to use a container image that provides data in the form of source code and large pre-built binaries. As a software developer, I was expected to edit the code in the container. This was problematic, because containers are by default stateless: they don't save data within the container, because they're designed to be disposable. But I worked on it, and at the end of each day, I stopped the container and had to be careful not to remove it, because the state had to be maintained so I could continue work the next day. The disadvantage of this approach was that there would be a divergence of development state had there been more than one person working on the project. The value of having identical build systems across developers is somewhat lost with this approach.
+
+### Generate output as non-root user
+
+An important aspect of I/O concerns the ownership of the output files generated when running the tools in the container. By default, since Docker runs as **root**, the output files would be owned by **root**, which is unpleasant. You typically want to work as a non-root user. Changing the ownership after the build output is generated can be done with scripts, but it is an additional and unnecessary step. It's best to set the [**USER**][12] argument in the Dockerfile at the earliest point possible:
+
+
+```
+ARG USERNAME
+# other commands...
+USER ${USERNAME}
+```
+
+The **USERNAME** can be passed in as a build argument (**\--build-arg**) when executing the **docker image build**. You can see an example of this in the example [Dockerfile][11] and corresponding [build script][13].
+
+Some portions of the tools may also need to be installed as a non-root user. So the sequence of installations in the Dockerfile may need to be different from the way it's done if you are installing manually and directly under Linux.
+
+### Non-interactive installation
+
+Interactivity is the opposite of container automation. I've found the
+
+
+```
+`DEBIAN_FRONTEND=noninteractive apt-get -y --quiet --no-install-recommends`
+```
+
+options for the **apt-get install** instruction (as in the example above) necessary to prevent the installer from opening dialog boxes. Note that these options should be used as part of the **RUN** instruction. The **DEBIAN_FRONTEND=noninteractive** should not be set as an environment variable (**ENV**) in the Dockerfile, as this [FAQ explains][14], as it will be inherited by the containers.
+
+### Log your build and run output
+
+Debugging why a build failed is a common task, and logs are a great way to do this. Save a TypeScript of everything that happened during the container image build or container run session using the **tee** utility in a Bash script. In other words, add **|& tee $BASH_SOURCE.log** to the end of the **docker image build** and the **docker image run** commands in your scripts. See the examples in the [image build][13] and [container run][15] scripts.
+
+What this **tee**-ing technique does is generate a file with the same name as the Bash script but with a **.log** extension appended to it so that you know which script it originated from. Everything you see printed to the terminal when running the script will get logged to this file with a similar name.
+
+This is especially valuable for users of your container images to report issues to you when something doesn't work. You can ask them to send you the log file to help diagnose the issue. Many tools generate so much output that it easily overwhelms the default size of the terminal's buffer. Relying only on the terminal's buffer capacity to copy-paste error messages may not be sufficient for diagnosing issues because earlier errors may have been lost.
+
+I've found this to be useful, even in the container image-building scripts, especially when using the Python-based HTTP server discussed above. The server generates so many lines during a download that it typically overwhelms the terminal's buffer.
+
+### Deal with proxies elegantly
+
+In my work environment, proxies are required to reach the internet for downloading the resources in **RUN apt-get** and **RUN wget** commands. The proxies are typically inferred from the environment variables **http_proxy** or **https_proxy**. While **ENV** commands can be used to hard-code such proxy settings in the Dockerfile, there are multiple issues with using **ENV** for proxies directly.
+
+If you are the only one who will ever build the container, then perhaps this will work. But the Dockerfile couldn't be used by someone else at a different location with a different proxy setting. Another issue is that the IT department could change the proxy at some point, resulting in a Dockerfile that won't work any longer. Furthermore, the Dockerfile is a precise document specifying a configuration-controlled system, and every change will be scrutinized by quality assurance.
+
+One simple approach to avoid hard-coding the proxy is to pass your local proxy setting as a build argument in the **docker image build** command:
+
+
+```
+docker image build \
+ --build-arg MY_PROXY=
+```
+
+And then, in the Dockerfile, set the environment variables based on the build argument. In the example shown here, you can still set a default proxy value that can be overridden by the build argument above:
+
+
+```
+# set a default proxy
+ARG MY_PROXY=MY_PROXY=
+ENV http_proxy=$MY_PROXY
+ENV https_proxy=$MY_PROXY
+```
+
+### Summary
+
+These techniques have helped me significantly reduce the time it takes to create container images and debug them when they go wrong. I continue to be on the lookout for additional best practices to add to my list. I hope you find the above techniques useful.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/optimize-container-builds
+
+作者:[Ravi Chandran][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/ravichandran
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/toolbox-learn-draw-container-yearbook.png?itok=xDbwz1pP (Toolbox drawing of a container)
+[2]: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
+[3]: https://github.com/ravi-chandran/dockerize-tutorial
+[4]: https://opensource.com/article/20/4/how-containerize-build-system
+[5]: https://podman.io/getting-started/installation
+[6]: https://docs.docker.com/develop/develop-images/multistage-build/
+[7]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/
+[8]: https://github.com/ravi-chandran/dockerize-tutorial/
+[9]: https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
+[10]: https://stackoverflow.com/a/37214138
+[11]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/install_anaconda.dockerfile
+[12]: https://docs.docker.com/engine/reference/builder/#user
+[13]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/build_docker_image.sh
+[14]: https://docs.docker.com/engine/faq/
+[15]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/run_container.sh
diff --git a/sources/tech/20200515 How to examine processes running on Linux.md b/sources/tech/20200515 How to examine processes running on Linux.md
new file mode 100644
index 0000000000..0659ab04f9
--- /dev/null
+++ b/sources/tech/20200515 How to examine processes running on Linux.md
@@ -0,0 +1,232 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to examine processes running on Linux)
+[#]: via: (https://www.networkworld.com/article/3543232/how-to-examine-processes-running-on-linux.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+How to examine processes running on Linux
+======
+
+Thinkstock
+
+There are quite a number of ways to look at running processes on Linux systems – to see what’s running, the resources that processes are using, how the system is affected by the load and how memory is being used. Each command gives you a different view, and the range of details is considerable. In this post, we’ll run through a series of commands that can help you view process details in a number of different ways.
+
+### ps
+
+While the **ps** command is the most obvious command for examining processes, the arguments that you use when running **ps** will make a big difference in how much information will be provided. With no arguments, **ps** will only show processes associated with your current login session. Add a **-u** and you'll see extended details.
+
+Here is a comparison:
+
+```
+nemo$ ps
+ PID TTY TIME CMD
+ 45867 pts/1 00:00:00 bash
+ 46140 pts/1 00:00:00 ps
+nemo$ ps -u
+USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+nemo 45867 0.0 0.0 11232 5636 pts/1 Ss 19:04 0:00 -bash
+nemo 46141 0.0 0.0 11700 3648 pts/1 R+ 19:16 0:00 ps -u
+```
+
+Using **ps -ef** will display details on all of the processes running on the system but **ps -eF** will add some additional details.
+
+```
+$ ps -ef | head -2
+UID PID PPID C STIME TTY TIME CMD
+root 1 0 0 May10 ? 00:00:06 /sbin/init splash
+$ ps -eF | head -2
+UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
+root 1 0 0 42108 12524 0 May10 ? 00:00:06 /sbin/init splash
+```
+
+Both commands show who is running the process, the process and parent process IDs, process start time, accumulated run time and the task being run. The additional fields shown when you use **F** instead of **f** include:
+
+ * SZ: the process **size** in physical pages for the core image of the process
+ * RSS: the **resident set size** which shows how much memory is allocated to those parts of the process in RAM. It does not include memory that is swapped out, but does include memory from shared libraries as long as the pages from those libraries are currently in memory. It also includes stack and heap memory.
+ * PSR: the **processor** the process is using
+
+
+
+##### ps -fU
+
+You can list processes for some particular user with a command like "ps -ef | grep USERNAME", but with **ps -fU** command, you’re going to see considerably more data. This is because details of processes that are being run on the user's behalf are also included. In fact, nearly all these processes shown have been kicked off by system simply to support this user’s online session. Nemo has only just logged in and is not yet running any commands or scripts.
+
+```
+$ ps -fU nemo
+UID PID PPID C STIME TTY TIME CMD
+nemo 45726 1 0 19:04 ? 00:00:00 /lib/systemd/systemd --user
+nemo 45732 45726 0 19:04 ? 00:00:00 (sd-pam)
+nemo 45738 45726 0 19:04 ? 00:00:00 /usr/bin/pulseaudio --daemon
+nemo 45740 45726 0 19:04 ? 00:00:00 /usr/libexec/tracker-miner-f
+nemo 45754 45726 0 19:04 ? 00:00:00 /usr/bin/dbus-daemon --sessi
+nemo 45829 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd
+nemo 45856 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd-fuse /run
+nemo 45862 45706 0 19:04 ? 00:00:00 sshd: nemo@pts/1
+nemo 45864 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-udisks2-vo
+nemo 45867 45862 0 19:04 pts/1 00:00:00 -bash
+nemo 45878 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-afc-volume
+nemo 45883 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-goa-volume
+nemo 45887 45726 0 19:04 ? 00:00:00 /usr/libexec/goa-daemon
+nemo 45895 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-mtp-volume
+nemo 45896 45726 0 19:04 ? 00:00:00 /usr/libexec/goa-identity-se
+nemo 45903 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-gphoto2-vo
+nemo 45946 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd-metadata
+```
+
+Note that the only process with an assigned TTY is Nemo's shell and that the parent of all of the other processes is **systemd**.
+
+You can supply a comma-separated list of usernames instead of a single name. Just be prepared to be looking at quite a bit more data.
+
+#### top and ntop
+
+The **top** and **ntop** commands will help when you want to get an idea which processes are using the most resources and allow you to reorder your view depending on what criteria you want to use to rank the processes (e.g., highest CPU or memory use).
+
+```
+top - 11:51:27 up 1 day, 21:40, 1 user, load average: 0.08, 0.02, 0.01
+Tasks: 211 total, 1 running, 210 sleeping, 0 stopped, 0 zombie
+%Cpu(s): 5.0 us, 0.5 sy, 0.0 ni, 94.3 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
+MiB Mem : 5944.4 total, 3527.4 free, 565.1 used, 1851.9 buff/cache
+MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 5084.3 avail Mem
+
+ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
+ 999 root 20 0 394660 14380 10912 S 8.0 0.2 0:46.54 udisksd
+ 65224 shs 20 0 314268 9824 8084 S 1.7 0.2 0:00.34 gvfs-ud+
+ 2034 gdm 20 0 314264 9820 7992 S 1.3 0.2 0:06.25 gvfs-ud+
+ 67909 root 20 0 0 0 0 I 0.3 0.0 0:00.09 kworker+
+ 1 root 20 0 168432 12532 8564 S 0.0 0.2 0:09.93 systemd
+ 2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd
+```
+
+Use **shift+m** to sort by memory use and **shift+p** to go back to sorting by CPU usage (the default).
+
+#### /proc
+
+A tremendous amount of information is available on running processes in the **/proc** directory. In fact, if you haven't visited **/proc** quite a few times, you might be astounded by the amount of details available. Just keep in mind that **/proc** is a very different kind of file system. As an interface to kernel data, it provides a view of process details that are currently being used by the system.
+
+Some of the more useful **/proc** files for viewing include **cmdline**, **environ**, **fd**, **limits** and **status**. The following views provide some samples of what you might see.
+
+The **status** file shows the process that is running (bash), its status, the user and group ID for the person running bash, a full list of the groups the user is a member of and the process ID and parent process ID.
+
+```
+$ head -11 /proc/65333/status
+Name: bash
+Umask: 0002
+State: S (sleeping)
+Tgid: 65333
+Ngid: 0
+Pid: 65333
+PPid: 65320
+TracerPid: 0
+Uid: 1000 1000 1000 1000
+Gid: 1000 1000 1000 1000
+FDSize: 256
+Groups: 4 11 24 27 30 46 118 128 500 1000
+...
+```
+
+The **cmdline** file shows the command line used to start the process.
+
+```
+$ cat /proc/65333/cmdline
+-bash
+```
+
+The **environ** file shows the environment variables that are in effect.
+
+```
+$ cat environ
+USER=shsLOGNAME=shsHOME=/home/shsPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/gamesSHELL=/bin/bashTERM=xtermXDG_SESSION_ID=626XDG_RUNTIME_DIR=/run/user/1000DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busXDG_SESSION_TYPE=ttyXDG_SESSION_CLASS=userMOTD_SHOWN=pamLANG=en_US.UTF-8SSH_CLIENT=192.168.0.19 9385 22SSH_CONNECTION=192.168.0.19 9385 192.168.0.11 22SSH_TTY=/dev/pts/0$
+```
+
+The **fd** file shows the file descriptors. Note how they reflect the pseudo-tty that is being used (pts/0).
+
+```
+$ ls -l /proc/65333/fd
+total 0
+lrwx------ 1 shs shs 64 May 12 09:45 0 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:45 1 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:45 2 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:56 255 -> /dev/pts/0
+$ who
+shs pts/0 2020-05-12 09:45 (192.168.0.19)
+```
+
+The **limits** file contains information about the limits imposed on the process.
+
+```
+$ cat limits
+Limit Soft Limit Hard Limit Units
+Max cpu time unlimited unlimited seconds
+Max file size unlimited unlimited bytes
+Max data size unlimited unlimited bytes
+Max stack size 8388608 unlimited bytes
+Max core file size 0 unlimited bytes
+Max resident set unlimited unlimited bytes
+Max processes 23554 23554 processes
+Max open files 1024 1048576 files
+Max locked memory 67108864 67108864 bytes
+Max address space unlimited unlimited bytes
+Max file locks unlimited unlimited locks
+Max pending signals 23554 23554 signals
+Max msgqueue size 819200 819200 bytes
+Max nice priority 0 0
+Max realtime priority 0 0
+Max realtime timeout unlimited unlimited us
+```
+
+#### pmap
+
+The **pmap** command takes you in an entirely different direction when it comes to memory use. It provides a detailed map of a process’s memory usage. To make sense of this, you need to keep in mind that processes do not run entirely on their own. Instead, they make use of a wide range of system resources. The truncated **pmap** output below shows a portion of the memory map for a single user’s bash login along with some memory usage totals at the bottom.
+
+```
+$ pmap -x 43120
+43120: -bash
+Address Kbytes RSS Dirty Mode Mapping
+000055887655b000 180 180 0 r---- bash
+0000558876588000 708 708 0 r-x-- bash
+0000558876639000 220 148 0 r---- bash
+0000558876670000 16 16 16 r---- bash
+0000558876674000 36 36 36 rw--- bash
+000055887667d000 40 28 28 rw--- [ anon ]
+0000558876b96000 1328 1312 1312 rw--- [ anon ]
+00007f0bd9a7e000 28 28 0 r---- libpthread-2.31.so
+00007f0bd9a85000 68 68 0 r-x-- libpthread-2.31.so
+00007f0bd9a96000 20 0 0 r---- libpthread-2.31.so
+00007f0bd9a9b000 4 4 4 r---- libpthread-2.31.so
+00007f0bd9a9c000 4 4 4 rw--- libpthread-2.31.so
+00007f0bd9a9d000 16 4 4 rw--- [ anon ]
+00007f0bd9aa1000 20 20 0 r---- libnss_systemd.so.2
+00007f0bd9aa6000 148 148 0 r-x-- libnss_systemd.so.2
+...
+ffffffffff600000 4 0 0 --x-- [ anon ]
+---------------- ------- ------- -------
+total kB 11368 5664 1656
+
+Kbytes: size of map in kilobytes
+RSS: resident set size in kilobytes
+Dirty: dirty pages (both shared and private) in kilobytes
+```
+```
+
+```
+
+Join the Network World communities on [Facebook][1] and [LinkedIn][2] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3543232/how-to-examine-processes-running-on-linux.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.facebook.com/NetworkWorld/
+[2]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200515 The pieces of Fedora Silverblue.md b/sources/tech/20200515 The pieces of Fedora Silverblue.md
new file mode 100644
index 0000000000..04bd4e1643
--- /dev/null
+++ b/sources/tech/20200515 The pieces of Fedora Silverblue.md
@@ -0,0 +1,172 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (The pieces of Fedora Silverblue)
+[#]: via: (https://fedoramagazine.org/pieces-of-fedora-silverblue/)
+[#]: author: (Nick Hardiman https://fedoramagazine.org/author/nickhardiman/)
+
+The pieces of Fedora Silverblue
+======
+
+![][1]
+
+Fedora Silverblue provides a useful workstation build on an immutable operating system. In “[What is Silverblue?][2]“, you learned about the benefits that an immutable OS provides. But what pieces go into making it? This article examines some of the technology that powers Silverblue.
+
+### The filesystem
+
+Fedora Workstation users may find the idea of an immutable OS to be the most brain-melting part of Silverblue. What does that mean? Find some answers by taking a look at the filesystem.
+
+At first glance, the layout looks pretty much the same as a regular Fedora file system. It has some differences, like making _/home_ a symbolic link to _/var/home_. And you can get more answers by looking at how libostree works. libostree treats the whole tree like it’s an object, checks it into a code repository, and checks out a copy for your machine to use.
+
+#### libostree
+
+The [libostree project][3] supplies the goods for managing Silverblue’s file system. It is an upgrade system that the user can control using [rpm-ostree commands][4].
+
+libostree knows nothing about packages—an upgrade means replacing one complete file system with another complete file system. libostree treats the file system tree as one atomic object (an unbreakable unit). In fact, the forerunner to Silverblue was named [Project Atomic][5].
+
+The libostree project provides a library and set of tools. It’s an upgrade system that carries out these tasks.
+
+ 1. Pull in a new file system
+ 2. Store the new file system
+ 3. Deploy the new file system
+
+
+
+##### Pull in a new file system
+
+Pulling in a new file system means copying an object (the entire file system) from a remote source to its own store. If you’ve worked with virtual machine image files, you already understand the concept of a file system object that you can copy.
+
+##### Store the new file system
+
+The libostree store has some source code control qualities—it stores many file system objects, and checks one out to be used as the root file system. libostree’s store has two parts:
+
+ * a repository database at _/sysroot/ostree/repo/_
+ * file systems in _/sysroot/ostree/deploy/fedora/deploy/_
+
+
+
+libostree keeps track of what’s been checked in using commit IDs. Each commit ID can be found in a directory name, nested deep inside _/sysroot_ .A libostree commit ID is a long checksum, and looks similar to a git commit ID.
+
+```
+$ ls -d /sysroot/ostree/deploy/fedora/deploy/*/
+/sysroot/ostree/deploy/fedora/deploy/c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4.0/
+```
+
+_rpm-ostree status_ gives a little more information about that commit ID. The output is a little confusing; it can take a while to see this file system is Fedora 31.
+
+```
+$ rpm-ostree status
+State: idle
+AutomaticUpdates: disabled
+Deployments:
+● ostree://fedora:fedora/31/x86_64/silverblue
+ Version: 31.1.9 (2019-10-23T21:44:48Z)
+ Commit: c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4
+ GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4
+```
+
+##### Deploy the new filesystem
+
+libostree deploys a new file system by checking out the new object from its store. libostree doesn’t check out a file system by copying all the files—it uses hard links instead. If you look inside the commit ID directory, you see something that looks suspiciously like the root directory. That’s because it _is_ the root directory. You can see these two directories are pointing to the same place by checking their inodes.
+
+```
+$ ls -di1 / /sysroot/ostree/deploy/fedora/deploy/*/
+260102 /
+260102 /sysroot/ostree/deploy/fedora/deploy/c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4.0/
+```
+
+This is a fresh install, so there’s only one commit ID. After a system update, there will be two. If more copies of the file system are checked into libostree’s repo, more commit IDs appear here.
+
+##### Upgrade process
+
+Putting the pieces together, the update process looks like this:
+
+ 1. libostree checks out a copy of the file system object from the repository
+ 2. DNF installs packages into the copy
+ 3. libostree checks in the copy as a new object
+ 4. libostree checks out the copy to become the new file system
+ 5. You reboot to pick up the new system files
+
+
+
+In addition to more safety, there is more flexibility. You can do new things with libostree’s repo, like store a few different file systems and check out whichever one you feel like using.
+
+#### Silverblue’s root file system
+
+Fedora keeps its system files in all the usual Linux places, such as _/boot_ for boot files, _/etc_ for configuration files, and _/home_ for user home directories. The root directory in Silverblue looks much like the root directory in traditional Fedora, but there are some differences.
+
+ * The filesystem has been checked out by libostree
+ * Some directories are now symbolic links to new locations. For example, _/home_ is a symbolic link to _/var/home_
+ * _/usr_ is a read-only directory
+ * There’s a new directory named _/sysroot_. This is libostree’s new home
+
+
+
+#### Juggling file systems
+
+You can store many file systems and switch between them. This is called _rebasing_, and it’s similar to git rebasing. In fact, upgrading Silverblue to the next Fedora version is not a big package install—it’s a pull from a remote repository and a rebase.
+
+You could store three copies with three different desktops: one KDE, one GNOME, and one XFCE. Or three different OS versions: how about keeping the current version, the nightly build, and an old classic? Switching between them is a matter of rebasing to the appropriate file system object.
+
+Rebasing is also how you upgrade from one Fedora release to the next. See “[How to rebase to Fedora 32 on Silverblue][6]” for more information.
+
+### Flatpak
+
+The [Flatpak project][7] provides a way of installing applications like LibreOffice. Applications are pulled from remote repositories like [Flathub][8]. It’s a kind of package manager, although you won’t find the word _package_ in the [docs][9]. Traditional Fedora variants like Fedora Workstation can also use Flatpak, but the sandboxed nature of flatpaks make it particularly good for Silverblue. This way you do not have to do the entire ostree update process every time you wish to install an application.
+
+Flatpak is well-suited to desktop applications, but also works for command line applications. You can install the [vim][10] editor with the command _flatpak install flathub org.vim.Vim_ and run it with _flatpak run org.vim.Vim_.
+
+### toolbox
+
+The [toolbox project][11] provides a traditional operating system inside a container. The idea is that you can mess with the mutable OS inside your toolbox (the Fedora container) as much as you like, and leave the immutable OS outside your toolbox untouched. You pack as many toolboxes as you want on your system, so you can keep work separated. Behind the scenes, the executable _/usr/bin/toolbox_ is a shell script that uses [podman][12].
+
+A fresh install does not include a default toolbox. The _toolbox create_ command checks the OS version (by reading _/usr/lib/os-release_), looks for a matching version at the Fedora container registry, and downloads the container.
+
+```
+$ toolbox create
+Image required to create toolbox container.
+Download registry.fedoraproject.org/f31/fedora-toolbox:31 (500MB)? [y/N]: y
+Created container: fedora-toolbox-31
+Enter with: toolbox enter
+```
+
+Hundreds of packages are installed inside the toolbox. The _dnf_ command and the usual Fedora repos are set up, ready to install more. The _ostree_ and _rpm-ostree_ commands are not included – no immutable OS here.
+
+Each user’s home directory is mounted on their toolbox, for storing content files outside the container.
+
+### Put the pieces together
+
+Spend some time exploring Fedora Silverblue and it will become clear how these components fit together. Like other Fedora variants, all these of tools come from open source projects. You can get as up close and personal as you want, from reading their docs to contributing code. Or you can [contribute to Silverblue][13] itself.
+
+Join the Fedora Silverblue conversations on [discussion.fedoraproject.org][14] or in [#silverblue on Freenode IRC][15].
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/pieces-of-fedora-silverblue/
+
+作者:[Nick Hardiman][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/nickhardiman/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/04/silverblue-pieces-816x345.png
+[2]: https://fedoramagazine.org/what-is-silverblue/
+[3]: https://ostree.readthedocs.io/en/latest/
+[4]: https://rpm-ostree.readthedocs.io/en/latest/manual/administrator-handbook/#administering-an-rpm-ostree-based-system
+[5]: https://www.projectatomic.io/
+[6]: https://fedoramagazine.org/how-to-rebase-to-fedora-32-on-silverblue/
+[7]: https://github.com/flatpak/flatpak
+[8]: https://flathub.org/
+[9]: http://docs.flatpak.org/en/latest/index.html
+[10]: https://www.vim.org/
+[11]: https://github.com/containers/toolbox
+[12]: https://github.com/containers/libpod
+[13]: https://silverblue.fedoraproject.org/contribute
+[14]: https://discussion.fedoraproject.org/c/desktop/silverblue
+[15]: https://webchat.freenode.net/#silverblue
diff --git a/sources/tech/20200516 Fatih-s question.md b/sources/tech/20200516 Fatih-s question.md
new file mode 100644
index 0000000000..1225c624a8
--- /dev/null
+++ b/sources/tech/20200516 Fatih-s question.md
@@ -0,0 +1,214 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Fatih’s question)
+[#]: via: (https://dave.cheney.net/2020/05/16/fatihs-question)
+[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
+
+Fatih’s question
+======
+
+A few days ago Fatih posted [this question][1] on twitter.
+
+I’m going to attempt to give my answer, however to do that I need to apply some simplifications as my previous attempts to answer it involved a lot of phrases like _a pointer to a pointer_, and other unhelpful waffling. Hopefully my simplified answer can be useful in building a mental framework to answer Fatih’s original question.
+
+### Restating the question
+
+Fatih’s original tweet showed [four different variations][2] of `json.Unmarshal`. I’m going to focus on the last two, which I’ll rewrite a little:
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Result struct {
+ Foo string `json:"foo"`
+}
+
+func main() {
+ content := []byte(`{"foo": "bar"}`)
+ var result1, result2 *Result
+
+ err := json.Unmarshal(content, &result1)
+ fmt.Println(result1, err) // &{bar}
+
+ err = json.Unmarshal(content, result2)
+ fmt.Println(result2, err) // json: Unmarshal(nil *main.Result)
+}
+```
+
+Restated in words, `result1` and `result2` are the same type; `*Result`. Decoding into `result1` works as expected, whereas decoding into `result2` causes the `json` package to complain that the value passed to `Unmarshal` is `nil`. However, both values were declared without an initialiser so both would have taken on the type’s zero value, `nil`.
+
+Eagle eyed readers will have spotted that the reason for the difference is the first` `invocation is passed `&result1`, while the second is passed `result2`, but this explanation is unsatisfactory because the documentation for `json.Unmarshal` states:
+
+> Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. **If v is nil or not a pointer**, Unmarshal returns an InvalidUnmarshalError.
+
+Which is confusing because `result1` and `result2` _are_ pointers. Furthermore, without initialisation, both _are_ `nil`. Now, the documentation is correct (as you’d expect from a package that has been hammered on for a decade), but explaining _why_ takes a little more investigation.
+
+### Functions receive a copy of their arguments
+
+Every assignment in Go is a copy, this includes function arguments and return values.
+
+```
+package main
+
+import (
+ "fmt"
+)
+
+func increment(v int) {
+ v++
+}
+
+func main() {
+ v := 1
+ increment(v)
+ fmt.Println(v) // 1
+}
+```
+
+In this example, `increment` is operating on a _copy_ of `main`‘s `v`. This is because the `v` declared in `main` and `increment`‘s `v` parameter have different addresses in memory. Thus changes to `increment`‘s `v` cannot affect the contents of `main`‘s `v`.
+
+```
+package main
+
+import (
+ "fmt"
+)
+
+func increment(v *int) {
+ *v++
+}
+
+func main() {
+ v := 1
+ increment(&v)
+ fmt.Println(v) // 2
+}
+```
+
+If we wanted to write `increment` in a way that it could affect the contents of its caller we would need to pass a reference, a pointer, to `main.v`.[1][3] This example demonstrates why `json.Unmarshal` needs a pointer to the value to decode JSON into.
+
+### Pointers to pointers
+
+Returning to the original question, both `result1` and `result2` are declared as `*Result`, that is, pointers to a `Result` value. We established that you have to pass the address of caller’s value to `json.Unmarshal` otherwise it won’t be able to alter the contents of the caller’s value. Why then must we pass the address of `result1`, a `**Result`, a pointer to a pointer to a `Result`, for the operation to succeed.
+
+To explain this another detour is required. Consider this code:
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Result struct {
+ Foo *string `json:"foo"`
+}
+
+func main() {
+ content := []byte(`{"foo": "bar"}`)
+ var result1 *Result
+
+ err := json.Unmarshal(content, &result1)
+ fmt.Printf("%#v %v", result1, err) // &main.Result{Foo:(*string)(0xc0000102f0)}
+}
+```
+
+In this example `Result` contains a pointer typed field, `Foo *string`. During JSON decoding `Unmarshal` allocated a new `string` value, stored the value `bar` in it, then placed the address of the string in `Result.Foo`. This behaviour is quite handy as it frees the caller from having to initialise `Result.Foo` and makes it easier to detect when a field was not initialised because the JSON did not contain a value. Beyond the convenience this offers for simple examples it would be prohibitively difficult for the caller to properly initialise all the reference type fields in a structure before decoding unknown JSON without first inspecting the incoming JSON which itself may be problematic if the input is coming from an `io.Reader` without the ability to rewind the input.
+
+> To unmarshal JSON into a pointer, Unmarshal first handles the case of the JSON being the JSON literal null. In that case, Unmarshal sets the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into the value pointed at by the pointer. **If the pointer is nil, Unmarshal allocates a new value for it to point to**.
+
+`json.Unmarshal`‘s handling of pointer fields is clearly documented, and works as you would expect, allocating a new value whenever there is a need to decode into a pointer shaped field. It is this behaviour that gives us a hint to what is happening in the original example.
+
+We’ve seen that when `json.Unmarshal` encounters a field which points to `nil` it will allocate a new value of the correct type and assign its address the field before proceeding. Not only is does behaviour is applied recursively–for example in the case of a complex structure which contains pointers to other structures–but it also applies to the _value passed to `Unmarshal`._
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+func main() {
+ content := []byte(`1`)
+ var result *int
+
+ err := json.Unmarshal(content, &result)
+ fmt.Println(*result, err) // 1